/library/

bmit();'>space:mode:
Diffstat (limited to 'tk8.6')
-rw-r--r--tk8.6/ChangeLog5286
-rw-r--r--tk8.6/ChangeLog.20027877
-rw-r--r--tk8.6/ChangeLog.20043653
-rw-r--r--tk8.6/ChangeLog.20075283
-rw-r--r--tk8.6/README.md37
-rw-r--r--tk8.6/bitmaps/error.xbm8
-rw-r--r--tk8.6/bitmaps/gray12.xbm6
-rw-r--r--tk8.6/bitmaps/gray25.xbm6
-rw-r--r--tk8.6/bitmaps/gray50.xbm6
-rw-r--r--tk8.6/bitmaps/gray75.xbm6
-rw-r--r--tk8.6/bitmaps/hourglass.xbm9
-rw-r--r--tk8.6/bitmaps/info.xbm5
-rw-r--r--tk8.6/bitmaps/questhead.xbm9
-rw-r--r--tk8.6/bitmaps/question.xbm10
-rw-r--r--tk8.6/bitmaps/warning.xbm5
-rw-r--r--tk8.6/changes7571
-rw-r--r--tk8.6/compat/stdlib.h40
-rw-r--r--tk8.6/compat/unistd.h80
-rw-r--r--tk8.6/doc/3DBorder.3294
-rw-r--r--tk8.6/doc/AddOption.350
-rw-r--r--tk8.6/doc/BindTable.3153
-rw-r--r--tk8.6/doc/CanvPsY.3121
-rw-r--r--tk8.6/doc/CanvTkwin.3158
-rw-r--r--tk8.6/doc/CanvTxtInfo.3100
-rw-r--r--tk8.6/doc/Clipboard.377
-rw-r--r--tk8.6/doc/ClrSelect.338
-rw-r--r--tk8.6/doc/ConfigWidg.3631
-rw-r--r--tk8.6/doc/ConfigWind.3147
-rw-r--r--tk8.6/doc/CoordToWin.347
-rw-r--r--tk8.6/doc/CrtCmHdlr.364
-rw-r--r--tk8.6/doc/CrtConsoleChan.344
-rw-r--r--tk8.6/doc/CrtErrHdlr.3140
-rw-r--r--tk8.6/doc/CrtGenHdlr.381
-rw-r--r--tk8.6/doc/CrtImgType.3283
-rw-r--r--tk8.6/doc/CrtItemType.3695
-rw-r--r--tk8.6/doc/CrtPhImgFmt.3270
-rw-r--r--tk8.6/doc/CrtSelHdlr.3116
-rw-r--r--tk8.6/doc/CrtWindow.3146
-rw-r--r--tk8.6/doc/DeleteImg.331
-rw-r--r--tk8.6/doc/DrawFocHlt.336
-rw-r--r--tk8.6/doc/EventHndlr.375
-rw-r--r--tk8.6/doc/FindPhoto.3283
-rw-r--r--tk8.6/doc/FontId.394
-rw-r--r--tk8.6/doc/FreeXId.348
-rw-r--r--tk8.6/doc/GeomReq.392
-rw-r--r--tk8.6/doc/GetAnchor.389
-rw-r--r--tk8.6/doc/GetBitmap.3296
-rw-r--r--tk8.6/doc/GetCapStyl.364
-rw-r--r--tk8.6/doc/GetClrmap.377
-rw-r--r--tk8.6/doc/GetColor.3176
-rw-r--r--tk8.6/doc/GetCursor.3231
-rw-r--r--tk8.6/doc/GetDash.382
-rw-r--r--tk8.6/doc/GetFont.3110
-rw-r--r--tk8.6/doc/GetGC.370
-rw-r--r--tk8.6/doc/GetHINSTANCE.322
-rw-r--r--tk8.6/doc/GetHWND.336
-rw-r--r--tk8.6/doc/GetImage.3130
-rw-r--r--tk8.6/doc/GetJoinStl.363
-rw-r--r--tk8.6/doc/GetJustify.387
-rw-r--r--tk8.6/doc/GetOption.342
-rw-r--r--tk8.6/doc/GetPixels.395
-rw-r--r--tk8.6/doc/GetPixmap.352
-rw-r--r--tk8.6/doc/GetRelief.382
-rw-r--r--tk8.6/doc/GetRootCrd.339
-rw-r--r--tk8.6/doc/GetScroll.375
-rw-r--r--tk8.6/doc/GetSelect.378
-rw-r--r--tk8.6/doc/GetUid.345
-rw-r--r--tk8.6/doc/GetVRoot.346
-rw-r--r--tk8.6/doc/GetVisual.3100
-rw-r--r--tk8.6/doc/Grab.358
-rw-r--r--tk8.6/doc/HWNDToWindow.326
-rw-r--r--tk8.6/doc/HandleEvent.346
-rw-r--r--tk8.6/doc/IdToWindow.332
-rw-r--r--tk8.6/doc/ImgChanged.364
-rw-r--r--tk8.6/doc/Inactive.334
-rw-r--r--tk8.6/doc/InternAtom.355
-rw-r--r--tk8.6/doc/MainLoop.328
-rw-r--r--tk8.6/doc/MainWin.340
-rw-r--r--tk8.6/doc/MaintGeom.399
-rw-r--r--tk8.6/doc/ManageGeom.390
-rw-r--r--tk8.6/doc/MapWindow.349
-rw-r--r--tk8.6/doc/MeasureChar.3127
-rw-r--r--tk8.6/doc/MoveToplev.351
-rw-r--r--tk8.6/doc/Name.386
-rw-r--r--tk8.6/doc/NameOfImg.330
-rw-r--r--tk8.6/doc/OwnSelect.349
-rw-r--r--tk8.6/doc/ParseArgv.3360
-rw-r--r--tk8.6/doc/QWinEvent.350
-rw-r--r--tk8.6/doc/Restack.345
-rw-r--r--tk8.6/doc/RestrictEv.379
-rw-r--r--tk8.6/doc/SetAppName.362
-rw-r--r--tk8.6/doc/SetCaret.336
-rw-r--r--tk8.6/doc/SetClass.357
-rw-r--r--tk8.6/doc/SetClassProcs.387
-rw-r--r--tk8.6/doc/SetGrid.363
-rw-r--r--tk8.6/doc/SetOptions.3656
-rw-r--r--tk8.6/doc/SetVisual.350
-rw-r--r--tk8.6/doc/StrictMotif.338
-rw-r--r--tk8.6/doc/TextLayout.3276
-rw-r--r--tk8.6/doc/TkInitStubs.379
-rw-r--r--tk8.6/doc/Tk_Init.385
-rw-r--r--tk8.6/doc/Tk_Main.370
-rw-r--r--tk8.6/doc/WindowId.3188
-rw-r--r--tk8.6/doc/bell.n34
-rw-r--r--tk8.6/doc/bind.n730
-rw-r--r--tk8.6/doc/bindtags.n102
-rw-r--r--tk8.6/doc/bitmap.n124
-rw-r--r--tk8.6/doc/busy.n275
-rw-r--r--tk8.6/doc/button.n210
-rw-r--r--tk8.6/doc/canvas.n1923
-rw-r--r--tk8.6/doc/checkbutton.n293
-rw-r--r--tk8.6/doc/chooseColor.n48
-rw-r--r--tk8.6/doc/chooseDirectory.n71
-rw-r--r--tk8.6/doc/clipboard.n157
-rw-r--r--tk8.6/doc/colors.n992
-rw-r--r--tk8.6/doc/console.n145
-rw-r--r--tk8.6/doc/cursors.n191
-rw-r--r--tk8.6/doc/destroy.n45
-rw-r--r--tk8.6/doc/dialog.n74
-rw-r--r--tk8.6/doc/entry.n539
-rw-r--r--tk8.6/doc/event.n604
-rw-r--r--tk8.6/doc/focus.n137
-rw-r--r--tk8.6/doc/focusNext.n60
-rw-r--r--tk8.6/doc/font.n409
-rw-r--r--tk8.6/doc/fontchooser.n181
-rw-r--r--tk8.6/doc/frame.n143
-rw-r--r--tk8.6/doc/getOpenFile.n207
-rw-r--r--tk8.6/doc/grab.n150
-rw-r--r--tk8.6/doc/grid.n456
-rw-r--r--tk8.6/doc/image.n102
-rw-r--r--tk8.6/doc/keysyms.n937
-rw-r--r--tk8.6/doc/label.n130
-rw-r--r--tk8.6/doc/labelframe.n175
-rw-r--r--tk8.6/doc/listbox.n582
-rw-r--r--tk8.6/doc/loadTk.n69
-rw-r--r--tk8.6/doc/lower.n40
-rw-r--r--tk8.6/doc/menu.n841
-rw-r--r--tk8.6/doc/menubar.n38
-rw-r--r--tk8.6/doc/menubutton.n202
-rw-r--r--tk8.6/doc/message.n150
-rw-r--r--tk8.6/doc/messageBox.n122
-rw-r--r--tk8.6/doc/option.n140
-rw-r--r--tk8.6/doc/optionMenu.n45
-rw-r--r--tk8.6/doc/options.n358
-rw-r--r--tk8.6/doc/pack-old.n195
-rw-r--r--tk8.6/doc/pack.n283
-rw-r--r--tk8.6/doc/palette.n73
-rw-r--r--tk8.6/doc/panedwindow.n347
-rw-r--r--tk8.6/doc/photo.n543
-rw-r--r--tk8.6/doc/place.n255
-rw-r--r--tk8.6/doc/popup.n49
-rw-r--r--tk8.6/doc/radiobutton.n265
-rw-r--r--tk8.6/doc/raise.n57
-rw-r--r--tk8.6/doc/scale.n253
-rw-r--r--tk8.6/doc/scrollbar.n360
-rw-r--r--tk8.6/doc/selection.n206
-rw-r--r--tk8.6/doc/send.n109
-rw-r--r--tk8.6/doc/spinbox.n602
-rw-r--r--tk8.6/doc/text.n2285
-rw-r--r--tk8.6/doc/tk.n135
-rw-r--r--tk8.6/doc/tk4.0.ps4602
-rw-r--r--tk8.6/doc/tk_mac.n306
-rw-r--r--tk8.6/doc/tkerror.n37
-rw-r--r--tk8.6/doc/tkvars.n110
-rw-r--r--tk8.6/doc/tkwait.n52
-rw-r--r--tk8.6/doc/toplevel.n163
-rw-r--r--tk8.6/doc/ttk_Geometry.3223
-rw-r--r--tk8.6/doc/ttk_Theme.332
-rw-r--r--tk8.6/doc/ttk_button.n109
-rw-r--r--tk8.6/doc/ttk_checkbutton.n105
-rw-r--r--tk8.6/doc/ttk_combobox.n200
-rw-r--r--tk8.6/doc/ttk_entry.n472
-rw-r--r--tk8.6/doc/ttk_frame.n71
-rw-r--r--tk8.6/doc/ttk_image.n98
-rw-r--r--tk8.6/doc/ttk_intro.n177
-rw-r--r--tk8.6/doc/ttk_label.n86
-rw-r--r--tk8.6/doc/ttk_labelframe.n114
-rw-r--r--tk8.6/doc/ttk_menubutton.n81
-rw-r--r--tk8.6/doc/ttk_notebook.n267
-rw-r--r--tk8.6/doc/ttk_panedwindow.n162
-rw-r--r--tk8.6/doc/ttk_progressbar.n122
-rw-r--r--tk8.6/doc/ttk_radiobutton.n102
-rw-r--r--tk8.6/doc/ttk_scale.n130
-rw-r--r--tk8.6/doc/ttk_scrollbar.n196
-rw-r--r--tk8.6/doc/ttk_separator.n52
-rw-r--r--tk8.6/doc/ttk_sizegrip.n82
-rw-r--r--tk8.6/doc/ttk_spinbox.n128
-rw-r--r--tk8.6/doc/ttk_style.n131
-rw-r--r--tk8.6/doc/ttk_treeview.n555
-rw-r--r--tk8.6/doc/ttk_vsapi.n113
-rw-r--r--tk8.6/doc/ttk_widget.n369
-rw-r--r--tk8.6/doc/winfo.n357
-rw-r--r--tk8.6/doc/wish.1218
-rw-r--r--tk8.6/doc/wm.n860
-rw-r--r--tk8.6/generic/README3
-rw-r--r--tk8.6/generic/default.h27
-rw-r--r--tk8.6/generic/ks_names.h939
-rw-r--r--tk8.6/generic/tk.decls1154
-rw-r--r--tk8.6/generic/tk.h1623
-rw-r--r--tk8.6/generic/tk3d.c1398
-rw-r--r--tk8.6/generic/tk3d.h85
-rw-r--r--tk8.6/generic/tkArgv.c417
-rw-r--r--tk8.6/generic/tkAtom.c215
-rw-r--r--tk8.6/generic/tkBind.c4365
-rw-r--r--tk8.6/generic/tkBitmap.c1205
-rw-r--r--tk8.6/generic/tkBusy.c931
-rw-r--r--tk8.6/generic/tkBusy.h41
-rw-r--r--tk8.6/generic/tkButton.c1931
-rw-r--r--tk8.6/generic/tkButton.h322
-rw-r--r--tk8.6/generic/tkCanvArc.c2119
-rw-r--r--tk8.6/generic/tkCanvBmap.c1010
-rw-r--r--tk8.6/generic/tkCanvImg.c883
-rw-r--r--tk8.6/generic/tkCanvLine.c2518
-rw-r--r--tk8.6/generic/tkCanvPoly.c1999
-rw-r--r--tk8.6/generic/tkCanvPs.c1782
-rw-r--r--tk8.6/generic/tkCanvText.c1660
-rw-r--r--tk8.6/generic/tkCanvUtil.c1873
-rw-r--r--tk8.6/generic/tkCanvWind.c1095
-rw-r--r--tk8.6/generic/tkCanvas.c5984
-rw-r--r--tk8.6/generic/tkCanvas.h312
-rw-r--r--tk8.6/generic/tkClipboard.c721
-rw-r--r--tk8.6/generic/tkCmds.c2166
-rw-r--r--tk8.6/generic/tkColor.c947
-rw-r--r--tk8.6/generic/tkColor.h75
-rw-r--r--tk8.6/generic/tkConfig.c2114
-rw-r--r--tk8.6/generic/tkConsole.c968
-rw-r--r--tk8.6/generic/tkCursor.c882
-rw-r--r--tk8.6/generic/tkDecls.h1733
-rw-r--r--tk8.6/generic/tkEntry.c4518
-rw-r--r--tk8.6/generic/tkEntry.h298
-rw-r--r--tk8.6/generic/tkError.c299
-rw-r--r--tk8.6/generic/tkEvent.c2158
-rw-r--r--tk8.6/generic/tkFileFilter.c473
-rw-r--r--tk8.6/generic/tkFileFilter.h78
-rw-r--r--tk8.6/generic/tkFocus.c1215
-rw-r--r--tk8.6/generic/tkFont.c4269
-rw-r--r--tk8.6/generic/tkFont.h224
-rw-r--r--tk8.6/generic/tkFrame.c2038
-rw-r--r--tk8.6/generic/tkGC.c397
-rw-r--r--tk8.6/generic/tkGeometry.c790
-rw-r--r--tk8.6/generic/tkGet.c752
-rw-r--r--tk8.6/generic/tkGrab.c1591
-rw-r--r--tk8.6/generic/tkGrid.c3678
-rw-r--r--tk8.6/generic/tkImage.c1142
-rw-r--r--tk8.6/generic/tkImgBmap.c1323
-rw-r--r--tk8.6/generic/tkImgGIF.c2255
-rw-r--r--tk8.6/generic/tkImgPNG.c3563
-rw-r--r--tk8.6/generic/tkImgPPM.c854
-rw-r--r--tk8.6/generic/tkImgPhInstance.c1997
-rw-r--r--tk8.6/generic/tkImgPhoto.c4174
-rw-r--r--tk8.6/generic/tkImgPhoto.h262
-rw-r--r--tk8.6/generic/tkImgUtil.c83
-rw-r--r--tk8.6/generic/tkInt.decls1822
-rw-r--r--tk8.6/generic/tkInt.h1287
-rw-r--r--tk8.6/generic/tkIntDecls.h1179
-rw-r--r--tk8.6/generic/tkIntPlatDecls.h667
-rw-r--r--tk8.6/generic/tkIntXlibDecls.h1394
-rw-r--r--tk8.6/generic/tkListbox.c3670
-rw-r--r--tk8.6/generic/tkMacWinMenu.c146
-rw-r--r--tk8.6/generic/tkMain.c562
-rw-r--r--tk8.6/generic/tkMenu.c3639
-rw-r--r--tk8.6/generic/tkMenu.h551
-rw-r--r--tk8.6/generic/tkMenuDraw.c977
-rw-r--r--tk8.6/generic/tkMenubutton.c984
-rw-r--r--tk8.6/generic/tkMenubutton.h216
-rw-r--r--tk8.6/generic/tkMessage.c903
-rw-r--r--tk8.6/generic/tkObj.c1153
-rw-r--r--tk8.6/generic/tkOldConfig.c1184
-rw-r--r--tk8.6/generic/tkOldTest.c410
-rw-r--r--tk8.6/generic/tkOption.c1602
-rw-r--r--tk8.6/generic/tkPack.c1878
-rw-r--r--tk8.6/generic/tkPanedWindow.c3157
-rw-r--r--tk8.6/generic/tkPlace.c1271
-rw-r--r--tk8.6/generic/tkPlatDecls.h176
-rw-r--r--tk8.6/generic/tkPointer.c647
-rw-r--r--tk8.6/generic/tkPort.h31
-rw-r--r--tk8.6/generic/tkRectOval.c1527
-rw-r--r--tk8.6/generic/tkScale.c1627
-rw-r--r--tk8.6/generic/tkScale.h243
-rw-r--r--tk8.6/generic/tkScrollbar.c703
-rw-r--r--tk8.6/generic/tkScrollbar.h183
-rw-r--r--tk8.6/generic/tkSelect.c1603
-rw-r--r--tk8.6/generic/tkSelect.h167
-rw-r--r--tk8.6/generic/tkSquare.c623
-rw-r--r--tk8.6/generic/tkStubInit.c1136
-rw-r--r--tk8.6/generic/tkStubLib.c146
-rw-r--r--tk8.6/generic/tkStyle.c1554
-rw-r--r--tk8.6/generic/tkTest.c2086
-rw-r--r--tk8.6/generic/tkText.c6920
-rw-r--r--tk8.6/generic/tkText.h1171
-rw-r--r--tk8.6/generic/tkTextBTree.c4895
-rw-r--r--tk8.6/generic/tkTextDisp.c9106
-rw-r--r--tk8.6/generic/tkTextImage.c855
-rw-r--r--tk8.6/generic/tkTextIndex.c2402
-rw-r--r--tk8.6/generic/tkTextMark.c1027
-rw-r--r--tk8.6/generic/tkTextTag.c1802
-rw-r--r--tk8.6/generic/tkTextWind.c1409
-rw-r--r--tk8.6/generic/tkTrig.c1753
-rw-r--r--tk8.6/generic/tkUndo.c736
-rw-r--r--tk8.6/generic/tkUndo.h115
-rw-r--r--tk8.6/generic/tkUtil.c1281
-rw-r--r--tk8.6/generic/tkVisual.c549
-rw-r--r--tk8.6/generic/tkWindow.c3414
-rw-r--r--tk8.6/generic/ttk/ttk.decls150
-rw-r--r--tk8.6/generic/ttk/ttkBlink.c166
-rw-r--r--tk8.6/generic/ttk/ttkButton.c870
-rw-r--r--tk8.6/generic/ttk/ttkCache.c350
-rw-r--r--tk8.6/generic/ttk/ttkClamTheme.c971
-rw-r--r--tk8.6/generic/ttk/ttkClassicTheme.c511
-rw-r--r--tk8.6/generic/ttk/ttkDecls.h274
-rw-r--r--tk8.6/generic/ttk/ttkDefaultTheme.c1181
-rw-r--r--tk8.6/generic/ttk/ttkElements.c1281
-rw-r--r--tk8.6/generic/ttk/ttkEntry.c2103
-rw-r--r--tk8.6/generic/ttk/ttkFrame.c653
-rw-r--r--tk8.6/generic/ttk/ttkGenStubs.tcl963
-rw-r--r--tk8.6/generic/ttk/ttkImage.c452
-rw-r--r--tk8.6/generic/ttk/ttkInit.c283
-rw-r--r--tk8.6/generic/ttk/ttkLabel.c697
-rw-r--r--tk8.6/generic/ttk/ttkLayout.c1259
-rw-r--r--tk8.6/generic/ttk/ttkManager.c549
-rw-r--r--tk8.6/generic/ttk/ttkManager.h92
-rw-r--r--tk8.6/generic/ttk/ttkNotebook.c1421
-rw-r--r--tk8.6/generic/ttk/ttkPanedwindow.c976
-rw-r--r--tk8.6/generic/ttk/ttkProgress.c547
-rw-r--r--tk8.6/generic/ttk/ttkScale.c532
-rw-r--r--tk8.6/generic/ttk/ttkScroll.c278
-rw-r--r--tk8.6/generic/ttk/ttkScrollbar.c345
-rw-r--r--tk8.6/generic/ttk/ttkSeparator.c136
-rw-r--r--tk8.6/generic/ttk/ttkSquare.c301
-rw-r--r--tk8.6/generic/ttk/ttkState.c276
-rw-r--r--tk8.6/generic/ttk/ttkStubInit.c61
-rw-r--r--tk8.6/generic/ttk/ttkStubLib.c74
-rw-r--r--tk8.6/generic/ttk/ttkTagSet.c306
-rw-r--r--tk8.6/generic/ttk/ttkTheme.c1755
-rw-r--r--tk8.6/generic/ttk/ttkTheme.h450
-rw-r--r--tk8.6/generic/ttk/ttkThemeInt.h42
-rw-r--r--tk8.6/generic/ttk/ttkTrace.c190
-rw-r--r--tk8.6/generic/ttk/ttkTrack.c183
-rw-r--r--tk8.6/generic/ttk/ttkTreeview.c3488
-rw-r--r--tk8.6/generic/ttk/ttkWidget.c791
-rw-r--r--tk8.6/generic/ttk/ttkWidget.h274
-rw-r--r--tk8.6/library/bgerror.tcl270
-rw-r--r--tk8.6/library/button.tcl782
-rw-r--r--tk8.6/library/choosedir.tcl308
-rw-r--r--tk8.6/library/clrpick.tcl695
-rw-r--r--tk8.6/library/comdlg.tcl319
-rw-r--r--tk8.6/library/console.tcl1150
-rw-r--r--tk8.6/library/demos/README44
-rw-r--r--tk8.6/library/demos/anilabel.tcl160
-rw-r--r--tk8.6/library/demos/aniwave.tcl104
-rw-r--r--tk8.6/library/demos/arrow.tcl237
-rw-r--r--tk8.6/library/demos/bind.tcl78
-rw-r--r--tk8.6/library/demos/bitmap.tcl52
-rw-r--r--tk8.6/library/demos/browse66
-rw-r--r--tk8.6/library/demos/button.tcl47
-rw-r--r--tk8.6/library/demos/check.tcl71
-rw-r--r--tk8.6/library/demos/clrpick.tcl54
-rw-r--r--tk8.6/library/demos/colors.tcl99
-rw-r--r--tk8.6/library/demos/combo.tcl61
-rw-r--r--tk8.6/library/demos/cscroll.tcl108
-rw-r--r--tk8.6/library/demos/ctext.tcl172
-rw-r--r--tk8.6/library/demos/dialog1.tcl25
-rw-r--r--tk8.6/library/demos/dialog2.tcl18
-rw-r--r--tk8.6/library/demos/en.msg97
-rw-r--r--tk8.6/library/demos/entry1.tcl34
-rw-r--r--tk8.6/library/demos/entry2.tcl46
-rw-r--r--tk8.6/library/demos/entry3.tcl185
-rw-r--r--tk8.6/library/demos/filebox.tcl81
-rw-r--r--tk8.6/library/demos/floor.tcl1366
-rw-r--r--tk8.6/library/demos/fontchoose.tcl69
-rw-r--r--tk8.6/library/demos/form.tcl38
-rw-r--r--tk8.6/library/demos/goldberg.tcl1833
-rw-r--r--tk8.6/library/demos/hello22
-rw-r--r--tk8.6/library/demos/hscale.tcl45
-rw-r--r--tk8.6/library/demos/icon.tcl51
-rw-r--r--tk8.6/library/demos/image1.tcl35
-rw-r--r--tk8.6/library/demos/image2.tcl108
-rw-r--r--tk8.6/library/demos/images/earth.gifbin0 -> 51712 bytes
-rw-r--r--tk8.6/library/demos/images/earthmenu.pngbin0 -> 8157 bytes
-rw-r--r--tk8.6/library/demos/images/earthris.gifbin0 -> 6343 bytes
-rw-r--r--tk8.6/library/demos/images/flagdown.xbm27
-rw-r--r--tk8.6/library/demos/images/flagup.xbm27
-rw-r--r--tk8.6/library/demos/images/gray25.xbm6
-rw-r--r--tk8.6/library/demos/images/letters.xbm27
-rw-r--r--tk8.6/library/demos/images/noletter.xbm27
-rw-r--r--tk8.6/library/demos/images/ouster.pngbin0 -> 54257 bytes
-rw-r--r--tk8.6/library/demos/images/pattern.xbm6
-rw-r--r--tk8.6/library/demos/images/tcllogo.gifbin0 -> 2341 bytes
-rw-r--r--tk8.6/library/demos/images/teapot.ppm31
-rw-r--r--tk8.6/library/demos/items.tcl291
-rw-r--r--tk8.6/library/demos/ixset328
-rw-r--r--tk8.6/library/demos/knightstour.tcl268
-rw-r--r--tk8.6/library/demos/label.tcl40
-rw-r--r--tk8.6/library/demos/labelframe.tcl76
-rw-r--r--tk8.6/library/demos/mclist.tcl119
-rw-r--r--tk8.6/library/demos/menu.tcl163
-rw-r--r--tk8.6/library/demos/menubu.tcl90
-rw-r--r--tk8.6/library/demos/msgbox.tcl62
-rw-r--r--tk8.6/library/demos/nl.msg125
-rw-r--r--tk8.6/library/demos/paned1.tcl32
-rw-r--r--tk8.6/library/demos/paned2.tcl74
-rw-r--r--tk8.6/library/demos/pendulum.tcl197
-rw-r--r--tk8.6/library/demos/plot.tcl97
-rw-r--r--tk8.6/library/demos/puzzle.tcl82
-rw-r--r--tk8.6/library/demos/radio.tcl66
-rw-r--r--tk8.6/library/demos/rmt210
-rw-r--r--tk8.6/library/demos/rolodex204
-rw-r--r--tk8.6/library/demos/ruler.tcl171
-rw-r--r--tk8.6/library/demos/sayings.tcl44
-rw-r--r--tk8.6/library/demos/search.tcl139
-rw-r--r--tk8.6/library/demos/spin.tcl53
-rw-r--r--tk8.6/library/demos/square60
-rw-r--r--tk8.6/library/demos/states.tcl54
-rw-r--r--tk8.6/library/demos/style.tcl155
-rw-r--r--tk8.6/library/demos/tclIndex67
-rw-r--r--tk8.6/library/demos/tcolor358
-rw-r--r--tk8.6/library/demos/text.tcl111
-rw-r--r--tk8.6/library/demos/textpeer.tcl62
-rw-r--r--tk8.6/library/demos/timer47
-rw-r--r--tk8.6/library/demos/toolbar.tcl92
-rw-r--r--tk8.6/library/demos/tree.tcl88
-rw-r--r--tk8.6/library/demos/ttkbut.tcl84
-rw-r--r--tk8.6/library/demos/ttkmenu.tcl53
-rw-r--r--tk8.6/library/demos/ttknote.tcl57
-rw-r--r--tk8.6/library/demos/ttkpane.tcl112
-rw-r--r--tk8.6/library/demos/ttkprogress.tcl46
-rw-r--r--tk8.6/library/demos/ttkscale.tcl39
-rw-r--r--tk8.6/library/demos/twind.tcl351
-rw-r--r--tk8.6/library/demos/unicodeout.tcl137
-rw-r--r--tk8.6/library/demos/vscale.tcl46
-rw-r--r--tk8.6/library/demos/widget721
-rw-r--r--tk8.6/library/dialog.tcl180
-rw-r--r--tk8.6/library/entry.tcl668
-rw-r--r--tk8.6/library/focus.tcl178
-rw-r--r--tk8.6/library/fontchooser.tcl452
-rw-r--r--tk8.6/library/iconlist.tcl696
-rw-r--r--tk8.6/library/icons.tcl153
-rw-r--r--tk8.6/library/images/README7
-rw-r--r--tk8.6/library/images/logo.eps2091
-rw-r--r--tk8.6/library/images/logo100.gifbin0 -> 2341 bytes
-rw-r--r--tk8.6/library/images/logo64.gifbin0 -> 1670 bytes
-rw-r--r--tk8.6/library/images/logoLarge.gifbin0 -> 11000 bytes
-rw-r--r--tk8.6/library/images/logoMed.gifbin0 -> 3889 bytes
-rw-r--r--tk8.6/library/images/pwrdLogo.eps1897
-rw-r--r--tk8.6/library/images/pwrdLogo100.gifbin0 -> 1615 bytes
-rw-r--r--tk8.6/library/images/pwrdLogo150.gifbin0 -> 2489 bytes
-rw-r--r--tk8.6/library/images/pwrdLogo175.gifbin0 -> 2981 bytes
-rw-r--r--tk8.6/library/images/pwrdLogo200.gifbin0 -> 3491 bytes
-rw-r--r--tk8.6/library/images/pwrdLogo75.gifbin0 -> 1171 bytes
-rw-r--r--tk8.6/library/images/tai-ku.gifbin0 -> 5473 bytes
-rw-r--r--tk8.6/library/listbox.tcl552
-rw-r--r--tk8.6/library/megawidget.tcl297
-rw-r--r--tk8.6/library/menu.tcl1379
-rw-r--r--tk8.6/library/mkpsenc.tcl1488
-rw-r--r--tk8.6/library/msgbox.tcl430
-rw-r--r--tk8.6/library/msgs/cs.msg77
-rw-r--r--tk8.6/library/msgs/da.msg78
-rw-r--r--tk8.6/library/msgs/de.msg91
-rw-r--r--tk8.6/library/msgs/el.msg86
-rw-r--r--tk8.6/library/msgs/en.msg91
-rw-r--r--tk8.6/library/msgs/en_gb.msg3
-rw-r--r--tk8.6/library/msgs/eo.msg75
-rw-r--r--tk8.6/library/msgs/es.msg76
-rw-r--r--tk8.6/library/msgs/fr.msg72
-rw-r--r--tk8.6/library/msgs/hu.msg78
-rw-r--r--tk8.6/library/msgs/it.msg73
-rw-r--r--tk8.6/library/msgs/nl.msg91
-rw-r--r--tk8.6/library/msgs/pl.msg91
-rw-r--r--tk8.6/library/msgs/pt.msg74
-rw-r--r--tk8.6/library/msgs/ru.msg75
-rw-r--r--tk8.6/library/msgs/sv.msg76
-rw-r--r--tk8.6/library/obsolete.tcl178
-rw-r--r--tk8.6/library/optMenu.tcl43
-rw-r--r--tk8.6/library/palette.tcl244
-rw-r--r--tk8.6/library/panedwindow.tcl194
-rw-r--r--tk8.6/library/safetk.tcl262
-rw-r--r--tk8.6/library/scale.tcl290
-rw-r--r--tk8.6/library/scrlbar.tcl454
-rw-r--r--tk8.6/library/spinbox.tcl580
-rw-r--r--tk8.6/library/tclIndex253
-rw-r--r--tk8.6/library/tearoff.tcl180
-rw-r--r--tk8.6/library/text.tcl1217
-rw-r--r--tk8.6/library/tk.tcl702
-rw-r--r--tk8.6/library/tkfbox.tcl1240
-rw-r--r--tk8.6/library/ttk/altTheme.tcl109
-rw-r--r--tk8.6/library/ttk/aquaTheme.tcl119
-rw-r--r--tk8.6/library/ttk/button.tcl83
-rw-r--r--tk8.6/library/ttk/clamTheme.tcl147
-rw-r--r--tk8.6/library/ttk/classicTheme.tcl115
-rw-r--r--tk8.6/library/ttk/combobox.tcl443
-rw-r--r--tk8.6/library/ttk/cursors.tcl186
-rw-r--r--tk8.6/library/ttk/defaults.tcl143
-rw-r--r--tk8.6/library/ttk/entry.tcl613
-rw-r--r--tk8.6/library/ttk/fonts.tcl157
-rw-r--r--tk8.6/library/ttk/menubutton.tcl243
-rw-r--r--tk8.6/library/ttk/notebook.tcl197
-rw-r--r--tk8.6/library/ttk/panedwindow.tcl82
-rw-r--r--tk8.6/library/ttk/progress.tcl49
-rw-r--r--tk8.6/library/ttk/scale.tcl94
-rw-r--r--tk8.6/library/ttk/scrollbar.tcl105
-rw-r--r--tk8.6/library/ttk/sizegrip.tcl102
-rw-r--r--tk8.6/library/ttk/spinbox.tcl173
-rw-r--r--tk8.6/library/ttk/treeview.tcl369
-rw-r--r--tk8.6/library/ttk/ttk.tcl176
-rw-r--r--tk8.6/library/ttk/utils.tcl350
-rw-r--r--tk8.6/library/ttk/vistaTheme.tcl229
-rw-r--r--tk8.6/library/ttk/winTheme.tcl84
-rw-r--r--tk8.6/library/ttk/xpTheme.tcl74
-rw-r--r--tk8.6/library/unsupported.tcl269
-rw-r--r--tk8.6/library/xmfbox.tcl989
-rw-r--r--tk8.6/license.terms40
-rw-r--r--tk8.6/macosx/GNUmakefile315
-rw-r--r--tk8.6/macosx/README725
-rw-r--r--tk8.6/macosx/Tk-Common.xcconfig46
-rw-r--r--tk8.6/macosx/Tk-Debug.xcconfig19
-rw-r--r--tk8.6/macosx/Tk-Info.plist.in41
-rw-r--r--tk8.6/macosx/Tk-Release.xcconfig19
-rw-r--r--tk8.6/macosx/Tk.icnsbin0 -> 154497 bytes
-rw-r--r--tk8.6/macosx/Tk.tiffbin0 -> 53684 bytes
-rw-r--r--tk8.6/macosx/Tk.xcode/default.pbxuser384
-rw-r--r--tk8.6/macosx/Tk.xcode/project.pbxproj5779
-rw-r--r--tk8.6/macosx/Tk.xcodeproj/default.pbxuser399
-rw-r--r--tk8.6/macosx/Tk.xcodeproj/project.pbxproj5923
-rw-r--r--tk8.6/macosx/Wish-Info.plist.in116
-rw-r--r--tk8.6/macosx/Wish.sdef46
-rw-r--r--tk8.6/macosx/configure.ac11
-rw-r--r--tk8.6/macosx/tkMacOSX.h34
-rw-r--r--tk8.6/macosx/tkMacOSXBitmap.c428
-rw-r--r--tk8.6/macosx/tkMacOSXButton.c1185
-rw-r--r--tk8.6/macosx/tkMacOSXClipboard.c301
-rw-r--r--tk8.6/macosx/tkMacOSXColor.c922
-rw-r--r--tk8.6/macosx/tkMacOSXConfig.c52
-rw-r--r--tk8.6/macosx/tkMacOSXConstants.h107
-rw-r--r--tk8.6/macosx/tkMacOSXCursor.c603
-rw-r--r--tk8.6/macosx/tkMacOSXCursors.h89
-rw-r--r--tk8.6/macosx/tkMacOSXDebug.c166
-rw-r--r--tk8.6/macosx/tkMacOSXDebug.h34
-rw-r--r--tk8.6/macosx/tkMacOSXDefault.h570
-rw-r--r--tk8.6/macosx/tkMacOSXDialog.c2165
-rw-r--r--tk8.6/macosx/tkMacOSXDraw.c2078
-rw-r--r--tk8.6/macosx/tkMacOSXEmbed.c1225
-rw-r--r--tk8.6/macosx/tkMacOSXEntry.c282
-rw-r--r--tk8.6/macosx/tkMacOSXEvent.c151
-rw-r--r--tk8.6/macosx/tkMacOSXEvent.h23
-rw-r--r--tk8.6/macosx/tkMacOSXFont.c1335
-rw-r--r--tk8.6/macosx/tkMacOSXFont.h32
-rw-r--r--tk8.6/macosx/tkMacOSXHLEvents.c582
-rw-r--r--tk8.6/macosx/tkMacOSXImage.c602
-rw-r--r--tk8.6/macosx/tkMacOSXInit.c652
-rw-r--r--tk8.6/macosx/tkMacOSXInt.h223
-rw-r--r--tk8.6/macosx/tkMacOSXKeyEvent.c762
-rw-r--r--tk8.6/macosx/tkMacOSXKeyboard.c949
-rw-r--r--tk8.6/macosx/tkMacOSXMenu.c1923
-rw-r--r--tk8.6/macosx/tkMacOSXMenubutton.c824
-rw-r--r--tk8.6/macosx/tkMacOSXMenus.c575
-rw-r--r--tk8.6/macosx/tkMacOSXMouseEvent.c689
-rw-r--r--tk8.6/macosx/tkMacOSXNotify.c416
-rw-r--r--tk8.6/macosx/tkMacOSXPort.h167
-rw-r--r--tk8.6/macosx/tkMacOSXPrivate.h440
-rw-r--r--tk8.6/macosx/tkMacOSXRegion.c559
-rw-r--r--tk8.6/macosx/tkMacOSXScale.c500
-rw-r--r--tk8.6/macosx/tkMacOSXScrlbr.c792
-rw-r--r--tk8.6/macosx/tkMacOSXSend.c515
-rw-r--r--tk8.6/macosx/tkMacOSXServices.c240
-rw-r--r--tk8.6/macosx/tkMacOSXSubwindows.c1481
-rw-r--r--tk8.6/macosx/tkMacOSXTest.c130
-rw-r--r--tk8.6/macosx/tkMacOSXWindowEvent.c1205
-rw-r--r--tk8.6/macosx/tkMacOSXWm.c7279
-rw-r--r--tk8.6/macosx/tkMacOSXWm.h277
-rw-r--r--tk8.6/macosx/tkMacOSXXCursors.h711
-rw-r--r--tk8.6/macosx/tkMacOSXXStubs.c987
-rw-r--r--tk8.6/macosx/ttkMacOSXTheme.c3186
-rw-r--r--tk8.6/tests/README5
-rw-r--r--tk8.6/tests/all.tcl19
-rw-r--r--tk8.6/tests/arc.tcl151
-rw-r--r--tk8.6/tests/bell.test53
-rw-r--r--tk8.6/tests/bevel.tcl158
-rw-r--r--tk8.6/tests/bgerror.test67
-rw-r--r--tk8.6/tests/bind.test6149
-rw-r--r--tk8.6/tests/bitmap.test114
-rw-r--r--tk8.6/tests/border.test201
-rw-r--r--tk8.6/tests/bugs.tcl41
-rw-r--r--tk8.6/tests/busy.test477
-rw-r--r--tk8.6/tests/butGeom.tcl126
-rw-r--r--tk8.6/tests/butGeom2.tcl124
-rw-r--r--tk8.6/tests/button.test4006
-rw-r--r--tk8.6/tests/canvImg.test818
-rw-r--r--tk8.6/tests/canvMoveto.test56
-rw-r--r--tk8.6/tests/canvPs.test196
-rw-r--r--tk8.6/tests/canvPsArc.tcl43
-rw-r--r--tk8.6/tests/canvPsBmap.tcl84
-rw-r--r--tk8.6/tests/canvPsGrph.tcl98
-rw-r--r--tk8.6/tests/canvPsImg.tcl84
-rw-r--r--tk8.6/tests/canvPsText.tcl94
-rw-r--r--tk8.6/tests/canvRect.test475
-rw-r--r--tk8.6/tests/canvText.test950
-rw-r--r--tk8.6/tests/canvWind.test144
-rw-r--r--tk8.6/tests/canvas.test960
-rw-r--r--tk8.6/tests/choosedir.test174
-rw-r--r--tk8.6/tests/clipboard.test364
-rw-r--r--tk8.6/tests/clrpick.test216
-rw-r--r--tk8.6/tests/cmap.tcl72
-rw-r--r--tk8.6/tests/cmds.test60
-rw-r--r--tk8.6/tests/color.test310
-rw-r--r--tk8.6/tests/config.test1929
-rw-r--r--tk8.6/tests/constraints.tcl286
-rw-r--r--tk8.6/tests/corruptMangled.gifbin0 -> 64 bytes
-rw-r--r--tk8.6/tests/corruptMangled4G.gif2
-rw-r--r--tk8.6/tests/corruptTruncated.gifbin0 -> 32 bytes
-rw-r--r--tk8.6/tests/cursor.test846
-rw-r--r--tk8.6/tests/deferredClearCode.gifbin0 -> 23355 bytes
-rw-r--r--tk8.6/tests/dialog.test67
-rw-r--r--tk8.6/tests/earth.gifbin0 -> 51712 bytes
-rw-r--r--tk8.6/tests/embed.test88
-rw-r--r--tk8.6/tests/entry.test3546
-rw-r--r--tk8.6/tests/event.test872
-rw-r--r--tk8.6/tests/face.xbm173
-rw-r--r--tk8.6/tests/filebox.test490
-rw-r--r--tk8.6/tests/flagdown.xbm27
-rw-r--r--tk8.6/tests/flagup.xbm27
-rw-r--r--tk8.6/tests/focus.test739
-rw-r--r--tk8.6/tests/focusTcl.test485
-rw-r--r--tk8.6/tests/font.test2409
-rw-r--r--tk8.6/tests/fontchooser.test201
-rw-r--r--tk8.6/tests/frame.test1537
-rw-r--r--tk8.6/tests/geometry.test291
-rw-r--r--tk8.6/tests/get.test138
-rw-r--r--tk8.6/tests/grab.test188
-rw-r--r--tk8.6/tests/grid.test2052
-rw-r--r--tk8.6/tests/iDOT.pngbin0 -> 6279 bytes
-rw-r--r--tk8.6/tests/image.test655
-rw-r--r--tk8.6/tests/imgBmap.test520
-rw-r--r--tk8.6/tests/imgPNG.test1127
-rw-r--r--tk8.6/tests/imgPPM.test239
-rw-r--r--tk8.6/tests/imgPhoto.test1459
-rw-r--r--tk8.6/tests/listbox.test3218
-rw-r--r--tk8.6/tests/main.test120
-rw-r--r--tk8.6/tests/menu.test3971
-rw-r--r--tk8.6/tests/menuDraw.test717
-rw-r--r--tk8.6/tests/menubut.test795
-rw-r--r--tk8.6/tests/message.test502
-rw-r--r--tk8.6/tests/msgbox.test447
-rw-r--r--tk8.6/tests/obj.test28
-rw-r--r--tk8.6/tests/oldpack.test552
-rw-r--r--tk8.6/tests/option.file118
-rw-r--r--tk8.6/tests/option.file22
-rwxr-xr-xtk8.6/tests/option.file318
-rw-r--r--tk8.6/tests/option.test441
-rw-r--r--tk8.6/tests/pack.test1656
-rw-r--r--tk8.6/tests/packgrid.test280
-rw-r--r--tk8.6/tests/panedwindow.test5551
-rw-r--r--tk8.6/tests/place.test523
-rw-r--r--tk8.6/tests/pwrdLogo150.gifbin0 -> 2489 bytes
-rw-r--r--tk8.6/tests/raise.test320
-rw-r--r--tk8.6/tests/red.gifbin0 -> 92 bytes
-rw-r--r--tk8.6/tests/safe.test248
-rw-r--r--tk8.6/tests/safePrimarySelection.test1220
-rw-r--r--tk8.6/tests/scale.test1592
-rw-r--r--tk8.6/tests/scrollbar.test788
-rw-r--r--tk8.6/tests/select.test1182
-rw-r--r--tk8.6/tests/send.test628
-rw-r--r--tk8.6/tests/spinbox.test3832
-rw-r--r--tk8.6/tests/teapot.ppm31
-rw-r--r--tk8.6/tests/text.test7729
-rw-r--r--tk8.6/tests/textBTree.test1247
-rw-r--r--tk8.6/tests/textDisp.test4283
-rw-r--r--tk8.6/tests/textImage.test473
-rw-r--r--tk8.6/tests/textIndex.test963
-rw-r--r--tk8.6/tests/textMark.test306
-rw-r--r--tk8.6/tests/textTag.test1776
-rw-r--r--tk8.6/tests/textWind.test1582
-rw-r--r--tk8.6/tests/tk.test184
-rw-r--r--tk8.6/tests/ttk/all.tcl20
-rw-r--r--tk8.6/tests/ttk/checkbutton.test73
-rw-r--r--tk8.6/tests/ttk/combobox.test88
-rw-r--r--tk8.6/tests/ttk/entry.test310
-rw-r--r--tk8.6/tests/ttk/image.test50
-rw-r--r--tk8.6/tests/ttk/labelframe.test130
-rw-r--r--tk8.6/tests/ttk/layout.test28
-rw-r--r--tk8.6/tests/ttk/notebook.test514
-rw-r--r--tk8.6/tests/ttk/panedwindow.test291
-rw-r--r--tk8.6/tests/ttk/progressbar.test85
-rw-r--r--tk8.6/tests/ttk/radiobutton.test48
-rw-r--r--tk8.6/tests/ttk/scrollbar.test108
-rw-r--r--tk8.6/tests/ttk/spinbox.test301
-rw-r--r--tk8.6/tests/ttk/treetags.test221
-rw-r--r--tk8.6/tests/ttk/treeview.test783
-rw-r--r--tk8.6/tests/ttk/ttk.test647
-rw-r--r--tk8.6/tests/ttk/validate.test277
-rw-r--r--tk8.6/tests/ttk/vsapi.test47
-rw-r--r--tk8.6/tests/unixButton.test269
-rw-r--r--tk8.6/tests/unixEmbed.test1270
-rw-r--r--tk8.6/tests/unixFont.test318
-rw-r--r--tk8.6/tests/unixMenu.test1275
-rw-r--r--tk8.6/tests/unixSelect.test437
-rw-r--r--tk8.6/tests/unixWm.test2612
-rw-r--r--tk8.6/tests/util.test68
-rw-r--r--tk8.6/tests/visual.test570
-rw-r--r--tk8.6/tests/visual_bb.test116
-rw-r--r--tk8.6/tests/winButton.test203
-rw-r--r--tk8.6/tests/winClipboard.test124
-rwxr-xr-xtk8.6/tests/winDialog.test1057
-rw-r--r--tk8.6/tests/winFont.test392
-rw-r--r--tk8.6/tests/winMenu.test1385
-rw-r--r--tk8.6/tests/winMsgbox.test300
-rw-r--r--tk8.6/tests/winSend.test407
-rw-r--r--tk8.6/tests/winWm.test577
-rw-r--r--tk8.6/tests/window.test351
-rw-r--r--tk8.6/tests/winfo.test492
-rw-r--r--tk8.6/tests/wm.test2356
-rw-r--r--tk8.6/tests/xmfbox.test166
-rw-r--r--tk8.6/unix/Makefile.in1709
-rw-r--r--tk8.6/unix/README173
-rw-r--r--tk8.6/unix/aclocal.m41
-rwxr-xr-xtk8.6/unix/configure12293
-rw-r--r--tk8.6/unix/configure.in848
-rw-r--r--tk8.6/unix/install-sh528
-rwxr-xr-xtk8.6/unix/installManPage117
-rw-r--r--tk8.6/unix/tcl.m43074
-rw-r--r--tk8.6/unix/tk.pc.in15
-rw-r--r--tk8.6/unix/tk.spec54
-rw-r--r--tk8.6/unix/tkAppInit.c156
-rw-r--r--tk8.6/unix/tkConfig.h.in256
-rw-r--r--tk8.6/unix/tkConfig.sh.in97
-rw-r--r--tk8.6/unix/tkUnix.c265
-rw-r--r--tk8.6/unix/tkUnix3d.c500
-rw-r--r--tk8.6/unix/tkUnixButton.c1028
-rw-r--r--tk8.6/unix/tkUnixColor.c450
-rw-r--r--tk8.6/unix/tkUnixConfig.c50
-rw-r--r--tk8.6/unix/tkUnixCursor.c650
-rw-r--r--tk8.6/unix/tkUnixDefault.h532
-rw-r--r--tk8.6/unix/tkUnixDialog.c193
-rw-r--r--tk8.6/unix/tkUnixDraw.c243
-rw-r--r--tk8.6/unix/tkUnixEmbed.c1209
-rw-r--r--tk8.6/unix/tkUnixEvent.c825
-rw-r--r--tk8.6/unix/tkUnixFocus.c149
-rw-r--r--tk8.6/unix/tkUnixFont.c3316
-rw-r--r--tk8.6/unix/tkUnixInit.c162
-rw-r--r--tk8.6/unix/tkUnixInt.h35
-rw-r--r--tk8.6/unix/tkUnixKey.c536
-rw-r--r--tk8.6/unix/tkUnixMenu.c1918
-rw-r--r--tk8.6/unix/tkUnixMenubu.c476
-rw-r--r--tk8.6/unix/tkUnixPort.h192
-rw-r--r--tk8.6/unix/tkUnixRFont.c1259
-rw-r--r--tk8.6/unix/tkUnixScale.c736
-rw-r--r--tk8.6/unix/tkUnixScrlbr.c488
-rw-r--r--tk8.6/unix/tkUnixSelect.c1552
-rw-r--r--tk8.6/unix/tkUnixSend.c2066
-rw-r--r--tk8.6/unix/tkUnixWm.c7464
-rw-r--r--tk8.6/unix/tkUnixXId.c152
-rw-r--r--tk8.6/win/Makefile.in748
-rw-r--r--tk8.6/win/README21
-rw-r--r--tk8.6/win/aclocal.m41
-rwxr-xr-xtk8.6/win/buildall.vc.bat107
-rwxr-xr-xtk8.6/win/configure6176
-rw-r--r--tk8.6/win/configure.in314
-rw-r--r--tk8.6/win/makefile.vc705
-rw-r--r--tk8.6/win/mkd.bat12
-rw-r--r--tk8.6/win/nmakehlp.c814
-rw-r--r--tk8.6/win/rc/buttons.bmpbin0 -> 846 bytes
-rw-r--r--tk8.6/win/rc/cursor00.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor02.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor04.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor06.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor08.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor0a.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor0c.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor0e.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor10.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor12.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor14.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor16.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor18.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor1a.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor1c.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor1e.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor20.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor22.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor24.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor26.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor28.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor2a.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor2c.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor2e.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor30.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor32.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor34.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor36.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor38.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor3a.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor3c.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor3e.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor40.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor42.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor44.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor46.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor48.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor4a.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor4c.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor4e.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor50.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor52.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor54.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor56.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor58.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor5a.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor5c.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor5e.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor60.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor62.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor64.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor66.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor68.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor6a.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor6c.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor6e.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor70.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor72.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor74.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor76.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor78.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor7a.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor7c.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor7e.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor80.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor82.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor84.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor86.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor88.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor8a.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor8c.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor8e.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor90.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor92.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor94.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor96.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor98.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/cursor9a.curbin0 -> 326 bytes
-rw-r--r--tk8.6/win/rc/lamp.bmpbin0 -> 2102 bytes
-rw-r--r--tk8.6/win/rc/tk.icobin0 -> 57022 bytes
-rw-r--r--tk8.6/win/rc/tk.rc74
-rw-r--r--tk8.6/win/rc/tk_base.rc140
-rw-r--r--tk8.6/win/rc/wish.icobin0 -> 43646 bytes
-rw-r--r--tk8.6/win/rc/wish.rc87
-rw-r--r--tk8.6/win/rmd.bat20
-rw-r--r--tk8.6/win/rules-ext.vc118
-rw-r--r--tk8.6/win/rules.vc1752
-rw-r--r--tk8.6/win/stubs.c474
-rw-r--r--tk8.6/win/targets.vc98
-rw-r--r--tk8.6/win/tcl.m41299
-rw-r--r--tk8.6/win/tkConfig.sh.in87
-rw-r--r--tk8.6/win/tkWin.h81
-rw-r--r--tk8.6/win/tkWin32Dll.c296
-rw-r--r--tk8.6/win/tkWin3d.c573
-rw-r--r--tk8.6/win/tkWinButton.c1318
-rw-r--r--tk8.6/win/tkWinClipboard.c481
-rw-r--r--tk8.6/win/tkWinColor.c589
-rw-r--r--tk8.6/win/tkWinConfig.c64
-rw-r--r--tk8.6/win/tkWinCursor.c272
-rw-r--r--tk8.6/win/tkWinDefault.h536
-rw-r--r--tk8.6/win/tkWinDialog.c3620
-rw-r--r--tk8.6/win/tkWinDraw.c1523
-rw-r--r--tk8.6/win/tkWinEmbed.c1127
-rw-r--r--tk8.6/win/tkWinFont.c2908
-rw-r--r--tk8.6/win/tkWinImage.c696
-rw-r--r--tk8.6/win/tkWinInit.c223
-rw-r--r--tk8.6/win/tkWinInt.h256
-rw-r--r--tk8.6/win/tkWinKey.c750
-rw-r--r--tk8.6/win/tkWinMenu.c3512
-rw-r--r--tk8.6/win/tkWinPixmap.c251
-rw-r--r--tk8.6/win/tkWinPointer.c546
-rw-r--r--tk8.6/win/tkWinPort.h127
-rw-r--r--tk8.6/win/tkWinRegion.c288
-rw-r--r--tk8.6/win/tkWinScrlbr.c701
-rw-r--r--tk8.6/win/tkWinSend.c1017
-rw-r--r--tk8.6/win/tkWinSendCom.c479
-rw-r--r--tk8.6/win/tkWinSendCom.h61
-rw-r--r--tk8.6/win/tkWinTest.c580
-rw-r--r--tk8.6/win/tkWinWindow.c1017
-rw-r--r--tk8.6/win/tkWinWm.c8692
-rw-r--r--tk8.6/win/tkWinX.c2035
-rw-r--r--tk8.6/win/ttkWinMonitor.c161
-rw-r--r--tk8.6/win/ttkWinTheme.c733
-rw-r--r--tk8.6/win/ttkWinXPTheme.c1350
-rw-r--r--tk8.6/win/winMain.c436
-rw-r--r--tk8.6/win/wish.exe.manifest.in53
-rw-r--r--tk8.6/xlib/X11/X.h686
-rw-r--r--tk8.6/xlib/X11/Xatom.h79
-rw-r--r--tk8.6/xlib/X11/Xfuncproto.h60
-rw-r--r--tk8.6/xlib/X11/Xlib.h1208
-rw-r--r--tk8.6/xlib/X11/Xutil.h855
-rw-r--r--tk8.6/xlib/X11/cursorfont.h79
-rw-r--r--tk8.6/xlib/X11/keysym.h35
-rw-r--r--tk8.6/xlib/X11/keysymdef.h1181
-rw-r--r--tk8.6/xlib/rgb.txt681
-rw-r--r--tk8.6/xlib/xbytes.h63
-rw-r--r--tk8.6/xlib/xcolors.c448
-rw-r--r--tk8.6/xlib/xdraw.c88
-rw-r--r--tk8.6/xlib/xgc.c670
-rw-r--r--tk8.6/xlib/ximage.c69
-rw-r--r--tk8.6/xlib/xutil.c113
901 files changed, 552498 insertions, 0 deletions
diff --git a/tk8.6/ChangeLog b/tk8.6/ChangeLog
new file mode 100644
index 0000000..2c1ca70
--- /dev/null
+++ b/tk8.6/ChangeLog
@@ -0,0 +1,5286 @@
+A NOTE ON THE CHANGELOG:
+Starting in early 2011, Tk source code has been under the management of
+fossil, hosted at http://core.tcl-lang.org/tk/ . Fossil presents a "Timeline"
+view of changes made that is superior in every way to a hand edited log file.
+Because of this, many Tk developers are now out of the habit of maintaining
+this log file. You may still find useful things in it, but the Timeline is
+a better first place to look now.
+============================================================================
+
+2013-08-30 Don Porter <dgp@users.sourceforge.net>
+
+ *** 8.6.1 TAGGED FOR RELEASE ***
+
+ * README: Bump version number to 8.6.1
+ * generic/tk.h:
+ * library/tk.tcl:
+ * unix/configure.in:
+ * unix/tk.spec:
+ * win/configure.in:
+
+ * unix/configure: autoconf-2.59
+ * win/configure:
+
+2013-08-25 Kevin Walzer <wordtech@users.sourceforge.net>
+
+ * macosx/tkMacOSXButton.c: Bug [3016181]: Crash after scrollbar
+ * macosx/tkMacOSXMenu.c: destroyed, Tk Cocoa.
+ * macosx/tkMacOSXScrlbr.c:
+ * macosx/tkMacOSXWm.c:
+
+2012-08-15 Joe English <jenglish@users.sourceforge.net>
+
+ * library/ttk/progress.tcl: Bug [c597acdab3]: Call [$pb step]
+ in tail position in ttk::progressbar::Autoincrement, so that
+ the widget is in a consistent state when any write traces on
+ the linked -variable are fired.
+
+2013-08-14 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkConfig.c: Bug [069c9e43c4]: FreeOptionInternalRep() breaks
+ * tests/config.test: Tk_CreateOptionTable()
+
+2013-07-02 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * unix/tcl.m4: Bug [32afa6e256]: dirent64 check is incorrect in tcl.m4
+ * unix/configure: (thanks to Brian Griffin)
+
+2012-06-28 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * library/ttk/scale.tcl: [Bug 2501278]: ttk::scale keyboard binding
+ problem.
+
+2013-06-05 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/ttk/ttkScroll.c: [Bug 3613759]: ttk::entry and symbolic
+ index names.
+ * generic/ttk/ttkEntry.c: [Bug 2100430]: ttk::entry widget index
+ must be integer
+ * generic/tkEntry.c: Don't set interp result when it will be
+ overwritten later.
+
+2013-06-04 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * unix/tcl.m4: Eliminate NO_VIZ macro as current
+ zlib uses HAVE_HIDDEN in stead. One more last-moment
+ fix for FreeBSD by Pietro Cerutti
+
+2013-05-23 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * unix/tcl.m4: [Bug 3613668]: XFilterEvent() hangs.
+ * unix/configure:
+ * unix/tkUnixEvent.c:
+
+2013-05-19 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * unix/tcl.m4: Fix for FreeBSD, and remove support for older
+ * unix/configure: FreeBSD versions. Patch by Pietro Cerutti.
+
+2013-04-10 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/makefile.vc: [Bug 3568760]: Tk documentation fails to build
+
+2013-04-01 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/window.test: Bring back test window-2.9. No longer hangs.
+
+ * generic/tkInt.h: [Bug 3607830] Runtime checks that Xkb is
+ * unix/tkUnixEvent.c: available in the X server before trying to
+ * unix/tkUnixKey.c: use. Adapted from patch from Brian Griffin.
+
+2013-03-27 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * library/button.tcl: [Bug 3608074]: Add <<Invoke>> bindings to
+ * library/listbox.tcl: Button's, Listbox and Menu.
+ * library/menu.tcl:
+ * doc/event.n: Document <<Invoke>>, <<ThemeChanged>>,
+ * doc/ttk_panedwindow.n: <<EnteredChild>> (ttk_pandedwindow only) and
+ * doc/ttk_spinbox.n: <<Increment/Decrement>> (ttk_spinbox only)
+
+2013-03-13 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * unix/tcl.m4: Patch by Andrew Shadura, providing better support for
+ three architectures they have in Debian.
+
+2013-03-11 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkListbox.c: [Bug 3607326] Stop segfault from
+ * tests/listbox.test: [listbox .l -listvariable $array].
+
+2013-02-28 Donal K. Fellows <dkf@users.sf.net>
+
+ * unix/tkUnixKey.c (TkpGetKeySym): [Bug 3599312]: Put the
+ initialization of the key mapping before the input method handling so
+ that Alt key handling is correct on non-OSX Unix. Thanks to Colin
+ McDonald for developing the fix.
+
+2013-02-18 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * unix/tkUnixEvent.c: Call XInitThreads once before the first Xlib
+ call. Suggested by Brian Griffin.
+
+2013-01-14 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tcl.m4: More flexible search for win32 tclConfig.sh,
+ * win/configure: backported from TEA.
+
+2013-01-13 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * library/tk.tcl: [Bug 3600390]: tk_strictMotif not tested for. Now
+ * library/ttk/entry.tcl: all key-bindings for Control-a,b,e,f,n,p and
+ their shift variants respect tk_strictMotif.
+
+2013-01-10 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * library/text.tcl: [Bug 3600251]: Inappropriate replacement of Mac
+ binding.
+ * library/tk.tcl: [Bug 3600260]: Errors in new virtual event
+ definitions
+
+2012-12-11 Don Porter <dgp@users.sourceforge.net>
+
+ *** 8.6.0 TAGGED FOR RELEASE ***
+
+ * README: Bump version number to 8.6.0
+ * generic/tk.h:
+ * library/tk.tcl:
+ * unix/configure.in:
+ * unix/tk.spec:
+ * win/configure.in:
+
+ * unix/configure: autoconf-2.59
+ * win/configure:
+
+2012-12-04 François Vogel <fvogelnew1@free.fr>
+
+ * generic/tkTextIndex.c: [Bug 3588824]: bug in image index handling
+ * tests/textIndex.test: for weird image names
+
+2012-11-16 Joe Mistachkin <joe@mistachkin.com>
+
+ * generic/tkBind.c: Add support for an 'M' binding substitution
+ that is replaced with the number of script-based binding patterns
+ matched so far for the event.
+
+2012-11-14 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkWinDialog.c: [Bug 3500545]: tk_getOpenFile -multiple 1 wrong
+ on windows.
+ [Bug 3416492]: Crash in open/save file dialog in Windows 7 libraries.
+ [Bug 3095112]: crash when selecting file from Win7 Library.
+
+2012-11-11 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkWinTest.c: [Bug 3585396]: winDialog.test requires user
+ * tests/winDialog.test: interaction.
+
+2012-11-07 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkFocus.c (TkSetFocusWin): [Bug 3574708]: Move window
+ liveness into this function from caller sites to ensure that there are
+ no paths where things can trip up on setting the focus to a partially
+ dead window.
+
+2012-10-24 Don Porter <dgp@users.sourceforge.net>
+
+ * macosx/tkMacOSXWm.c: [Bug 3574893] Add overlooked toplevel ref
+ count maintenance in the [wm manage|forget] operations that could
+ cause segfaults due to premature free of structs.
+
+2012-09-19 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/Makefile.in: Compile win32 binaries with -DTCL_NO_DEPRECATED
+ * win/tkiWinWm.c: Fix gcc compiler warning.
+
+2012-09-17 Don Porter <dgp@users.sourceforge.net>
+
+ *** 8.6b3 TAGGED FOR RELEASE ***
+
+ * macosx/tkMacOSXWm.c: [Bug 3567786] Stop segfault in [wm forget].
+
+2012-09-15 Don Porter <dgp@users.sourceforge.net>
+
+ * macosx/tkMacOSXFont.c: [Bug 3567778] Make Tk_MeasureChars() honor
+ the TK_AT_LEAST_ONE flag properly.
+
+2012-09-13 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/ttk/ttkEntry.c (EntryDisplay): [Bug 3567453]: Clip regions
+ * generic/ttk/ttkLabel.c (TextDraw): must be cleared with XSetClipMask
+ * xlib/xgc.c (TkSetRegion): and not TkSetRegion, or crashes will ensue
+ on X11-based builds, which can't handle None for a region argument.
+ Added a clean panic to the non-X11 TkSetRegion to catch this case and
+ stop such confusion from happening again.
+
+2012-09-13 Donal K. Fellows <dkf@users.sf.net>
+
+ * win/tkWinWm.c (WmTransientCmd): [Bug 3567283]: Added missing cast.
+
+2012-09-11 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/ttk/ttkEntry.c (EntryDisplay): [Bug 3566594]: Must manually
+ * generic/ttk/ttkLabel.c (TextDraw): reset the clip region of GCs
+ when not using the Xft font renderer (well, especially on classic X11)
+ because the GC sharing code doesn't take into account clip handling.
+ Thanks to Christian Nassau for identifying the problem.
+
+2012-09-07 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkCanvPs.c (TkCanvPostscriptCmd): [Bug 3565533]: Purge use
+ of variable that was only ever checked once immediately afterwards,
+ except for one (buggy) case where it was checked without assignment.
+
+2012-09-07 Don Porter <dgp@users.sourceforge.net>
+
+ * README: Bump version number to 8.6b3
+ * generic/tk.h:
+ * library/tk.tcl:
+ * unix/configure.in:
+ * unix/tk.spec:
+ * win/configure.in:
+
+ * unix/configure: autoconf-2.59
+ * win/configure:
+
+2012-08-30 Andreas Kupries <andreask@activestate.com>
+
+ * generic/tkCanvWind.c (CanvasPsWindow): Unbreak AIX, replaced use
+ of C99 comments in commit [961ae24a3f] (2012-08-27) with C89-style.
+ * win/tkWinDialog.c: Unbreak windows problems with commit [961ae24a3f]
+ * win/tkWinMenu.c: as well.
+ * win/tkWinSend.c:
+
+2012-08-28 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkMenuDraw.c: [Bug 3562426]: Context menu goes out of edge of
+ screen.
+
+2012-08-27 Donal K. Fellows <dkf@users.sf.net>
+
+ * (very many files): Reworked the generation of error messages and
+ postscript so that they no longer made nearly as much use of the Tcl
+ interpreter's string result code, in the process substantially
+ reducing the amount of ad-hoc stack buffers used for message
+ generation. There should be no observable changes from this except
+ that Tk now causes the ::errorCode variable to be set meaningfully in
+ virtually all places where errors are generated.
+
+2012-08-24 Donal K. Fellows <dkf@users.sf.net>
+
+ * library/tkfbox.tcl (GlobFiltered): [Bug 3558535]: Factor out the
+ filtered-sorted globbing code into one procedure that knows how to
+ avoid nasty problems when non-list filters are used. This allows the
+ rest of the [tk_getOpenFile] implementation to be ignorant of the
+ considerable complexities of globbing.
+
+2012-08-23 Don Porter <dgp@users.sourceforge.net>
+
+ * unix/tkUnixWm.c: [Bugs 3554026,3561016]: Stop crash with tearoff
+ menus.
+
+2012-08-23 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * library/tk.tcl: [Bug 3555644]: Better use of virtual events,
+ * library/ttk/entry.tcl Add <<ToggleSelection>> virtual event.
+ * library/ttk/treeview.tcl
+
+2012-08-22 Jan Nijtmans <nijtmans@users.sf.net>
+
+ TIP #403 IMPLEMENTATION
+
+ * xlib/xcolors.c: Web Colors for Tk. New colors aqua, crimson,
+ * xlib/rgb.txt: fuchsia, indigo, lime, olive, silver and teal.
+ * unix/tkUnixColor.c: Modified RGB values for gray/grey, green,
+ * generic/tkInt.h: maroon and purple.
+ * generic/tkColor.c
+
+2012-08-17 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/nmakehlp.c: Add "-V<num>" option, in order to be able to detect
+ partial version numbers.
+
+2012-08-15 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/buildall.vc.bat: Only build the threaded builds by default
+ * win/rules.vc: For msvcrt static builds, allow to link
+ against libraries where the 'x' is missing
+ (generated by Makefile.in).
+ * win/makefile.vc: Always compile Tk with -DUSE_TCL_STUBS,
+ formatting.
+ * library/tk.tcl: [FRQ 3555324]: On Windows, re-define Ctrl-A
+ for Select-All., as most Windows applications
+ do.
+
+2012-08-11 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * library/*.tcl: [Bug 3555644]: Better use of virtual events.
+ Pre-define 10 new Virtual events, and correct various bindings
+ according to the Mac OSX documentation.
+ *** POTENTIAL INCOMPATIBILITY *** for code that assumes that widget
+ classes are bound to literal events or that was using one of the new
+ virtual event names itself for other purposes.
+
+ * win/rules.vc: Sync with tcl version of rules.vc
+
+2012-08-11 François Vogel <fvogelnew1@free.fr>
+
+ * generic/tkTextTag.c: [Bug 3554273]: Test textDisp-32.2 failed
+
+2012-08-09 Stuart Cassoff <stwo@users.sourceforge.net>
+
+ * generic/tkEvent.c: Remove useless (void *) casts introduced in
+ * unix/tkUnixEvent.c: checkin [81e50c85ed]. The warnings were false
+ * unix/tkUnixKey.c: flags from a faulty OpenBSD C compiler.
+ * unix/tkUnixRFont.c:
+
+2012-07-31 Donal K. Fellows <dkf@users.sf.net>
+
+ * unix/tkUnixKey.c (TkpSetKeycodeAndState, TkpInitKeymapInfo)
+ (TkpGetKeySym): [Bug 3551802]: Convert from XKeycodeToKeysym to
+ XkbKeycodeToKeysym to fix deprecation warning.
+
+2012-07-31 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/nmakehlp.c: Backport from Tcl 8.6, but add -Q option from
+ sampleextension.
+
+2012-07-17 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/makefile.vc: [Bug 3544932]: Visual studio compiler check fails
+
+2012-07-05 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkWinDialog.c (GetFileNameW): [Bug 3540127]: Better solution,
+ using Tcl_GetIndexFromObj in stead of Tcl_GetIndexFromObjStruct
+
+2012-07-05 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/wm.n (geometry): [Bug 3538401]: Better description of the key
+ difference between [wm geometry] and [winfo geometry]; the former
+ represents the window manager's understanding, not Tk's.
+
+2012-07-04 Donal K. Fellows <dkf@users.sf.net>
+
+ * win/tkWinDialog.c (GetFileNameW): [Bug 3540127]: Clean up the tables
+ of options for the file dialogs so that options are listed in error
+ messages in alphabetical order.
+
+2012-07-02 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkWinDialog.c: [Bug 3540127]: filebox.test fails on win32
+
+2012-06-26 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * unix/configure.in: Link cygwin wish.exe with win32 tk.dll, only
+ * unix/Makefile.in: in combination with --enable-shared.
+ * unix/tcl.m4:
+ * unix/configure: autoconf-2.59
+
+2012-06-24 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * doc/SetOptions.3: [FRQ-3536507]: clientData field in Tk_OptionSpec
+ * generic/tk.h: should be "const void *"
+ * generic/tk*.c: Eliminate many unnessessary type casts
+
+2012-06-22 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/Makefile.in: [Bug 1844430]: cygwin make fails in 8.4.14-8.5b3
+ * unix/tcl.m4: Sync with Tcl version.
+ * unix/configure: autoconf-2.59
+
+2012-06-20 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tk.decls: [FRQ 2636558] simplification. Restore forwards
+ * generic/tkBitmap.c: compatibility with Tk 8.5.
+ * generic/tkdecls.h:
+ * generic/tkStubInit.c:
+
+2012-06-15 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/ttk/ttkTreeview.c (unshareObj): [Bug 3535362]: Changed name
+ of 'unshare' internal function to avoid clash with some libc versions.
+
+2012-06-12 Donal K. Fellows <dkf@users.sf.net>
+
+ * unix/tkUnixRFont.c (Tk_DrawChars, TkUnixSetXftClipRegion): Add some
+ * generic/ttk/ttkEntry.c (EntryDisplay): special magic to make the
+ * generic/ttk/ttkLabel.c (TextDraw): text clipping work right with the
+ Xft-based renderer (which doesn't use the standard Tk GC except to
+ supply the color).
+
+2012-06-11 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/ttk/ttkLabel.c (TextDraw): [Bug 3294450]: Get the clipping
+ * generic/ttk/ttkEntry.c (EntryDisplay): of text in Ttk various text
+ elements (e.g., buttons, entries, etc.) correct. Stops a whole range
+ of visual problems, including loss of the second and subsequent lines
+ of a label when the first line doesn't entirely fit, and failing to
+ draw the last character of an entry at all if it doesn't all exactly
+ fit in the space available (a problem I've noticed in tkchat, and been
+ very frustrated with).
+
+2012-06-10 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * library/*.tcl: [Bug 3534137]: $tcl_platform(platform) !=
+ [tk windowingsystem]
+
+2012-06-08 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkMain.c: Implement TkCygwinMainEx for loading
+ * generic/tkWindow.c: Cygwin's Tk_MainEx from the Tk dll.
+ * generic/tkInt.decls: Change XChangeWindowAttributes signature and
+ * generic/tkIntXlibDeclsDecls.h: many others to match Xorg, needed for
+ Cygwin.
+
+2012-06-06 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * unix/Makefile.in: [Bug 3532186] pkgIndex.tcl file complexity
+ * win/Makefile.in:
+
+2012-05-31 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkWindow.c: Simplify determination whether we are running
+ * generic/tkStubInit.c: on cygwin. Export Tk_GetHINSTANCE,
+ * generic/tkInt.decls: TkSetPixmapColormap and TkpPrintWindowId from
+ the Cygwin dll, sync stub table with Tk 8.6
+ win32 version.
+ * generic/tk*Decls.h: re-generated
+ * win/Makefile.in: "make genstubs" when cross-compiling on UNIX
+
+ * win/stubs.c: Implement XFlush and various others for win32
+ * win/tkWinPort.h: as stubs, so win32 extensions using those can
+ run under CYGWIN as well.
+ * generic/tkMain.c: Allow tk86.dll to cooperate with the cygwin
+ console.
+
+2012-05-29 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkInt.decls (TkMacOSXDrawable): Added OSX-specific mechanism
+ to allow retrieval of the drawing surface. Allows Canvas3d to be
+ adapted to 8.6.
+
+2012-05-28 François Vogel <fvogelnew1@free.fr>
+
+ * doc/text.n: [Bug 1630251]: Doc for -endline option was wrong
+
+2012-05-28 François Vogel <fvogelnew1@free.fr>
+
+ * generic/tkTextDisp.c: [Bug 1630254]: missing scrolling of text widget
+ when from a -startline == -endline initial state it is configured to
+ display a non-empty part of it
+
+2012-05-24 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/stubs.c: Change XSetCommand signature to match Xorg,
+ * win/tkWinWm.c: needed for Cygwin.
+ * generic/tkInt.decls
+ * generic/tk*Decls.h: re-generated
+
+2012-05-09 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkWinWm.c: Change TkpWmSetState signature to match Xorg,
+ * generic/tkInt.decls: needed for Cygwin. (not needed for Mac)
+ * generic/tkIntPlatDeclsDecls.h:
+ * generic/tkWindow.c: Don't check for cygwin in win32 static build.
+ * unix/tkUnixPort.h: Some more useful #defines for Cygwin
+
+2012-05-05 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * xlib/xcolors.c: Single "const" addition
+ * generic/tkWindow.c: If tk.dll loaded in cygwin, don't use the
+ win32 file dialogs
+
+2012-05-04 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * library/menu.tcl: [Bug 2768586]: Menu posting on dual monitors
+
+2012-04-29 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * library/tk.tcl: [Bug 533519]: Window placement with multiple screens
+ * generic/tkBind.c:
+ * generic/tkFocus.c:
+ * generic/tkMenuDraw.c:
+ * generic/tkWinWm.c:
+
+2012-04-26 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkStubInit.c (Tk_GetHINSTANCE): Ensure that this is defined
+ for OSX.
+
+2012-04-26 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tk.decls: [Bug 3508771]: Implement TkClipBox, Tk*Region
+ * generic/tkInt.decls: and Tk_GetHINSTANCE for Cygwin
+ * generic/tkPlatDecls.h:
+ * generic/tkintDecls.h:
+ * generic/tkStubInit.c:
+
+2012-04-22 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkBind.c (ExpandPercents): [Bug 3520202]: Ensure that the
+ %k, %K and %N substitutions use dummy tokens with <MouseWheel> events
+ and that the %D subsitution is a dummy with <Key>/<KeyRelease>. This
+ was causing significant indigestion (and a read of goodness knows what
+ memory) to Tkinter/Python because of the way they map events between
+ languages.
+
+2012-04-20 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkWindow.c (commands): Ensure that all descriptions of
+ commands created by Tk are correct.
+
+2012-04-20 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tk.tcl: Use vroot size in stead of screen size for clipping
+ window coordinates in ::tk::PlaceWindow.
+ * generic/dialog.tcl: Use ::tk::PlaceWindow in dialog.tcl, instead of
+ dumplicating the code there. (harmless part of [Bug 533519])
+
+2012-04-13 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/rules.vc: [Bug 3517448]: TclKit build fails (unresolved
+ __strtoi64)
+
+2012-04-07 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkBind.c: [Bug 3176239]: control-MouseWheel causes segv
+
+2012-03-30 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * unix/tcl.m4: [Bug 3511806]: Compiler checks too early
+ * unix/configure.in: This change allows to build the cygwin
+ * unix/configure and mingw32 ports of Tcl/Tk to build
+ * win/tcl.m4: out-of-the-box using a native or cross-
+ * win/configure.in: compiler.
+ * win/configure
+
+2012-03-21 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkColor.c: [Bug 2809525]: Abort on overlong color name.
+ * unix/tkUnixColor.c:
+
+2012-03-18 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * xlib/xcolors.c: [FRQ 3503317]: XParseColor speedup
+ * xlib/rgb.txt: List of all colors accepted by Tk in Xorg format
+ * tests/color.test: Added test case for all colors in rgb.txt
+
+2012-03-13 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/*.3, doc/*.n: Minor spelling fixes.
+
+2012-03-07 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkObj.c (GetPixelsFromObjEx): [Bug 3497848]: Better rounding
+ of pixel values to integers.
+
+2012-03-04 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * unix/tcl.m4: Patch from the cygwin folks
+ * unix/configure: (re-generated)
+
+2012-02-28 François Vogel <fvogelnew1@free.fr>
+
+ * generic/tkText.c: [Bug 1630262, Bug 1615425]: segfault
+ * generic/tkTextBTree.c when deleting lines or tagging outside of
+ * generic/tkTextDisp.c the -startline/-endline range with peer
+ * generic/tkTextMark.c text widgets.
+ * tests/text.test [Bug 3487407]: Weird text indices.
+ * tests/textMark.test
+
+2012-02-28 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/canvas.n: [Bug 3495198]: Corrected types of bitmap options.
+
+2012-02-26 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * xlib/xcolors.c: Provide fallback for _strtoi64
+ * win/configure.in: Detect whether _strtoi64 is available
+ * win/configure: (regenerated)
+
+2012-02-25 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkWinDialog.c: [Bug 1913750]: tk_chooseDirectory -initialdir
+ internationalization problem.
+
+2012-02-15 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * xlib/xcolors.c: [Bug 3486474]: Inconsistent color scaling
+ * generic/tkColor.c: new internal function TkParseColor
+ * generic/tkInt.h:
+ * generic/tk*.c: Change XParseColor() to TkParseColor() everywhere.
+
+2012-02-10 Donal K. Fellows <dkf@users.sf.net>
+
+ * win/tkWinDialog.c (GetFileName): Ensure that we do not convert a
+ result list to a string inadvertently, as this causes problems with
+ Tkinter's handling of multiple filename results. Issue was reported
+ via StackOverflow: http://stackoverflow.com/q/9227859/301832
+
+2012-01-30 Joe English <jenglish@users.sourceforge.net>
+
+ * library/ttk/combobox.tcl: [Bug 2925561] Don't take focus in
+ disabled state.
+
+2012-01-29 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkImgPhoto.c: [Bug 3480634]: PNG Images missing in menus on Mac
+
+2012-01-27 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkWinDialog.c: [Bug 3480471]: tk_getOpenFile crashes on Win64
+
+2012-01-26 François Vogel <fvogelnew1@free.fr>
+
+ * generic/tkTextDisp.c: [Bug-1754043] and [Bug-2321450]: When
+ -blockcursor is true, the cursor appears as a blinking bar which
+ expands to the right edge of the widget.
+
+2012-01-25 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkImgPhoto.c: [Bug 2433260]: non-critical error in
+ Tk_PhotoPutBlock
+
+2012-01-25 François Vogel <fvogelnew1@free.fr>
+
+ * generic/tkText.c: Don't increase the epoch twice
+
+2012-01-25 François Vogel <fvogelnew1@free.fr>
+
+ * generic/tkText.c: [Bug-1630271]: segfault/infinite loop
+ * generic/tkTextMark.c: when a mark is before -startline
+ * tests/textMark.test:
+
+2012-01-25 François Vogel <fvogelnew1@free.fr>
+
+ * generic/tkText.c: [Bug-3475627]: Test text-31.11 fails
+
+2012-01-22 François Vogel <fvogelnew1@free.fr>
+
+ * generic/tkTextMark.c: [Bug-3288113,3288121]: Missing marks/endless
+ * tests/textMark.test: loop in text mark prev/next
+
+2012-01-19 François Vogel <fvogelnew1@free.fr>
+
+ * generic/tkText.c: [Bug-3021557]: Moving the cursor in
+ * tests/text.test: elided text freezes Tk
+
+2011-12-22 Don Porter <dgp@users.sourceforge.net>
+
+ * win/tkWinMenu.c: [Bug 3235256] Keep menu entry IDs out of system
+ values. Thanks Colin McDonald.
+
+2011-12-13 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/getOpenFile.n: Make example follow best practices. Issue spotted
+ by Emiliano Gavilán.
+
+2011-11-29 Donal K. Fellows <dkf@users.sf.net>
+
+ * tests/safe.test: [Bug 1847925]: Update list of hidden commands.
+
+2011-11-22 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * unix/Makefile.in: [Bug 1945073]: Demo square.tcl
+ * win/Makefile.in: cannot run; need package tktest
+
+2011-11-17 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * doc/menu.n: Fix the escaping of leading dots in lines that start with
+ a widget name, so that nroff doesn't mistake it as a non-existing macro
+ and skips the entire line.
+
+2011-11-14 Alexandre Ferrieux <ferrieux@users.sourceforge.net>
+
+ * generic/tkCanvas.c: [Bug 3437816]: Missing TCL_ERROR return
+ in [canvas lower].
+
+2011-11-08 Reinhard Max <max@suse.de>
+
+ * unix/Makefile.in: Add square to DEMOPROGS. It contains a shebang
+ and hence should get installed with executable bits.
+
+ * doc/label.n: Fix the escaping of leading dots in lines that
+ * doc/text.n: start with a widget name, so that nroff
+ * doc/ttk_notebook.n: doesn't mistake it as a non-existing macro
+ * doc/pack.n: and skips the entire line.
+
+2011-11-01 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkObj.c (GetPixelsFromObjEx): [Bug 3431491]: Use a bit of
+ type hackery to allow numbers to be interpreted as coordinates (most
+ notably on a canvas) without reinterpreting via a string.
+
+2011-10-27 Kevin B. Kenny <kennykb@acm.org>
+
+ * generic/tkInt.h: [Bug 3410609]: Change the event mechanism
+ * unix/tkUnixEvent.c: for <KeyPress> events to use the keysym
+ * unix/tkUnixKey.c: returned by XLookupString in preference to
+ the one that appears in the raw X event at any level. This change
+ allows binding to ISO_Level3_Shift-ed characters, composed characters,
+ and similar beasts. KeyRelease events still work as they did before,
+ as does Tk with input methods disabled.
+
+2011-10-13 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkWinDialog.c: Internationalization of all Windows font
+ * win/tkWinFont.c: handling.
+
+2011-10-10 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkWinDialog.c: [Bug 3163893]: -initialdir option bug for
+ tk_chooseDirectory under XP
+
+2011-10-05 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkWinInt.h: Remove tkWinProcs, as it is no longer
+ * win/tkWinX.c: being used.
+ * win/tkWinTest.c:
+
+2011-09-27 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkImgPNG.c (WriteExtraChunks): [Bug 3405839]: Write the sDAT
+ chunk with the correct length.
+
+2011-09-08 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkDecls.h: Don't let tkDecls.h depend on <tchar.h> on
+ windows, not even in UNICODE mode.
+
+2011-09-01 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/photo.n: Correctly documented what the [$ph data] command
+ produces without the -format option.
+
+2011-08-16 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkWinDialog.c: [Bug 3388350]: mingw64 compiler warnings
+ * win/tkWinEmbed.c
+ * win/tkWinMenu.c
+ * win/tkWinTest.c
+ * win/tkWinWm.c
+ * win/tkWinX.c
+
+2011-08-13 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkBitmap.c: [Bug 3388350]: mingw64 compiler warnings
+ * generic/tkConsole.c
+ * win/tkWinDialog.c
+ * win/tkWinEmbed.c
+ * win/tkWinSend.c
+ * win/tkWinSendCom.c
+
+2011-08-05 Don Porter <dgp@users.sourceforge.net>
+
+ *** 8.6b2 TAGGED FOR RELEASE ***
+
+ * changes: Updates for 8.6b2 release.
+
+2011-08-03 Don Porter <dgp@users.sourceforge.net>
+
+ * win/tkWinWm.c: [Bug 2891541]: Merge of 8.5.8 fix from Pat Thoyts.
+ Permit normal behaviour on Windows for a grabbed toplevel when it
+ is the main window.
+
+2011-08-03 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkWinDialog.c: [Bug 3314770]: regression - Windows file
+ dialogs not resizable
+
+2011-07-28 Don Porter <dgp@users.sourceforge.net>
+
+ * changes: Updates for 8.6b2 release.
+
+2011-07-28 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * xlib/X11/Xutil.h: [Bug 3380684]: XEmptyRegion prototype doesn't
+ match usage
+
+2011-07-19 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/*.3, doc/*.n: Many small fixes to documentation as part of
+ project to improve quality of generated HTML docs.
+
+2011-07-18 Don Porter <dgp@users.sourceforge.net>
+
+ * README: Bump version number to 8.6b2
+ * generic/tk.h:
+ * library/tk.tcl:
+ * unix/configure.in:
+ * unix/tk.spec:
+ * win/configure.in:
+
+ * unix/configure: autoconf-2.59
+ * win/configure:
+
+2011-06-29 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/ttk/ttkTrace.c: [Bug 3341056]: Correct segfault due to flaw
+ * tests/ttk/ttk.test: in the 2011-06-17 commit.
+
+2011-06-19 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/wm.n: Added documentation of the -type attribute that was
+ introduced in TIP#359, and moved documentation of -alpha to common
+ section as it is supported on all platforms now.
+
+2011-06-17 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/ttk/ttkTrace.c: Workaround Bug 3062331.
+ * tests/ttk/ttk.test:
+ * changes: Updated
+
+2011-06-16 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tcl.m4: Sync with win/tcl.m4 from Tcl
+ * win/configure: (regenerated)
+
+2011-06-10 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkEntry.c: [Bug 3315731]: Fix [$entry -invcmd].
+
+2011-06-10 Don Porter <dgp@users.sourceforge.net>
+
+ * README: Correct some README bitrot.
+ * macosx/README:
+
+2011-06-07 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkEntry.c: [Bug 2358545]: Restore support for values "08"
+ and "09" in a [spinbox] configured to use -from and -to values.
+
+2011-06-06 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkConsole.c: [Bug 2546087]: Restore proper NUL output to
+ * library/console.tcl: the [console].
+
+2011-04-22 Peter Spjuth <peter.spjuth@gmail.com>
+
+ * generic/tkCanvPoly.c: [Bug 3291543]: There was a crash if dchars
+ * tests/canvas.test: removed all coordinates of a polygon.
+
+2011-04-21 Peter Spjuth <peter.spjuth@gmail.com>
+
+ * doc/checkbutton.n: Document all variable options as global.
+ * doc/radiobutton.n:
+ * doc/listbox.n:
+ * doc/menu.n:
+ * doc/options.n:
+ * doc/ttk_combobox.n:
+ * doc/ttk_entry.n:
+ * doc/ttk_progressbar.n:
+ * doc/ttk_widget.n:
+
+2011-04-06 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * unix/tkAppInit.c: Make symbols "main" and "Tcl_AppInit"
+ MODULE_SCOPE: there is absolutely no reason for exporting them.
+ * unix/tcl.m4: Don't use -fvisibility=hidden with static
+ * unix/configure libraries (--disable-shared)
+
+2011-04-04 Peter Spjuth <peter.spjuth@gmail.com>
+
+ * tests/grid.test:
+ * generic/tkGrid.c: [Bug 723765]: When a slave was removed from grid,
+ the -in option was not remembered.
+
+2011-04-04 Joe Mistachkin <joe@mistachkin.com>
+
+ * win/tkWinDialog.c (FontchooserShowCmd): Change the CHOOSEFONT and
+ LOGFONT used with sizeof to CHOOSEFONTA and LOGFONTA to match their
+ local variable declarations (i.e. mismatch with -DUNICODE). This code
+ is not present in 8.4 or 8.5.
+
+2011-04-04 Peter Spjuth <peter.spjuth@gmail.com>
+
+ * doc/labelframe.n:
+ * doc/frame.n:
+ * generic/tkFrame.c: [Bug 2997657]: Removed -container from labelframe
+ documentation since it does not work as expected and does not make
+ sense as a container. Added note to frame about restrictions when used
+ as a container.
+
+2011-03-28 Donal K. Fellows <dkf@users.sf.net>
+
+ * library/tk.tcl (::tk::FindAltKeyTarget): Make this handle the
+ traversal of the logical window manager hierarchy correctly. Based on
+ comments by Emiliano Gavilan.
+
+2011-03-28 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkTextBTree.c: [Bug 3129527]: Fix buffer overflow w/ GCC 4.5
+ and -D_FORTIFY_SOURCE=2. One more place where this problem could
+ appear.
+
+2011-03-24 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkWinMenu.c: [Bug #3239768]: tk8.4.19 (and later) WIN32
+ menu font support.
+
+2011-03-16 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * unix/tcl.m4: Make SHLIB_LD_LIBS='${LIBS}' the default and
+ * unix/configure: set to "" on per-platform necessary basis.
+ Backported from TEA, but kept all original platform code which was
+ removed from TEA.
+
+2011-03-14 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkBind.c: Eliminate some more unneeded write-only
+ * generic/tkCanvUtil.c: variables (discovered by gcc-4.6)
+ * generic/tkFocus.c:
+
+2011-03-12 Donal K. Fellows <dkf@users.sf.net>
+
+ Remove casts from uses of ckalloc/ckfree/... now that Tcl declares
+ them to be using useful casts internally.
+
+2011-03-12 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkWin32Dll.c: Eliminate unneeded _TkFinalize wrapper.
+
+2011-03-11 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/ttk/ttkDefaultTheme.c: Eliminate some unneeded write-only
+ * generic/ttk/ttkManager.c: variables (discovered by gcc-4.6)
+ * generic/ttk/ttkSquare.c:
+
+2011-03-09 Reinhard Max <max@suse.de>
+
+ * unix/configure.in: Use a symbol from libXft itself for the link
+ test rather than one from libfreetype, because the latter doesn't
+ work when the linker is called with --as-needed.
+
+2011-03-03 Alexandre Ferrieux <ferrieux@users.sourceforge.net>
+
+ * generic/tkCanvLine.c: [Bug 3175610]: Incomplete refresh of line items.
+
+2011-03-02 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/tk_mac.n (new file): Description of OSX-specific functionality
+ in Tk, contributed by Kevin Walzer.
+ * doc/button.n, doc/font.n, doc/menu.n: Noted which parts of these
+ commands are intentionally not fully supported on OSX.
+
+2011-01-24 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/tkSelect.c: Fix for [Bug #3164879]: (memory allocation
+ bug introduced by [Patch #3129527])
+
+2011-01-22 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkEntry.c(ttk::combobox): Add missing
+ 'validate' command (reported by schelte).
+
+2011-01-13 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * library/msgbox.tcl: [Patch #3154705]: Close button has no effect
+
+2011-01-12 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tcl.m4: handle --enable-64bit=ia64 for gcc
+ * win/configure.in typo
+ * win/configure: (autoconf-2.59)
+
+2011-01-06 Kevin Walzer <wordtech@users.sourceforge.net>
+
+ * macosx/README: Added info on textured background windows.
+ * macosx/tkMacOSXFont.c: Fix for 2857300, improves rounding up on text
+ width [submitted by treectrl]
+ * macosx/tkMacOSXMenu.c: Fix for radiobuttons and checkbuttons not
+ displaying in popup menus, and disabled menu entries.
+ * macosx/tkMacOSXWindowEvent.c: Fix for 3086887, speeds up scrolling;
+ also textured background windows
+ * macosx/tkMacOSXWm.c: Textured background windows.
+
+2011-01-06 Stuart Cassoff <stwo@users.sourceforge.net>
+
+ * generic/tkEvent.c: Cast some NULLs to (void *) in order to quash
+ * unix/tkUnixEvent.c: "missing sentinel in function call"
+ * unix/tkUnixKey.c: compiler warnings.
+ * unix/tkUnixRFont.c:
+
+2010-12-17 Stuart Cassoff <stwo@users.sourceforge.net>
+
+ * unix/Makefile.in: Clean up '.PHONY:' targets: Arrange those
+ common to Tcl and Tk as in Tcl's Makefile.in,
+ add any missing ones and remove duplicates.
+
+2010-12-17 Stuart Cassoff <stwo@users.sourceforge.net>
+
+ * unix/Makefile.in: [Bug 2446711]: Remove 'allpatch' target.
+
+2010-12-17 Stuart Cassoff <stwo@users.sourceforge.net>
+
+ * unix/Makefile.in: [Bug 2537626]: Use 'rpmbuild', not 'rpm'.
+
+2010-12-17 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkMain.c: refactor isatty() function for Windows.
+ * win/tkWinImage.c: better warning message.
+ * win/tkWinInit.c: Let TkpDisplayWarning() send the message
+ directly to the debugger, if available, otherwise do as before.
+
+2010-12-16 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tk.h: [Patch 3124554]: Move WishPanic from Tk to Tcl
+ * win/winMain.c: Remove special MessageBox'es here, since every
+ panic-related thing is now handled correctly by Tcl.
+
+2010-12-15 Stuart Cassoff <stwo@users.sourceforge.net>
+
+ * unix/Makefile.in: Installer Improvements.
+ * unix/install-sh: Similar to Tcl [Patch 3101127].
+
+2010-12-15 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkMain.c: [Patch #3124683]: platform specific stuff
+ in (tcl|tk)Main.c
+
+2010-12-13 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * unix/tcl.m4: [Bug 3135271]: Link error due to hidden
+ * unix/configure: symbols (CentOS 4.2) (autoconf-2.59)
+ * generic/tkMain.c: Change "Application initialization failed" to
+ * tests/main.test: "application-specific initialization failed",
+ for consistency with Tcl.
+ * win/tkWin32Dll.c: See also: [Patch 1910041] and [Patch 3059922].
+ SEH emulation on Win64 was not correct here: it sometimes results in
+ a crash. Contrary to the other places, the code here is not meant to
+ protect from OS bugs, but to protect Finalizing Tk when the application
+ went in an invalid state.
+
+2010-12-12 Stuart Cassoff <stwo@users.sourceforge.net>
+
+ * unix/tcl.m4: Better building on OpenBSD.
+ * unix/configure: (autoconf-2.59)
+
+2010-12-10 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tcl.m4: Fix manifest-generation for 64-bit gcc (mingw-w64)
+ * win/configure: (autoconf-2.59)
+
+2010-12-06 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkSelect.c: [Bug 3129527]: Fix buffer overflow w/ GCC 4.5
+ * generic/tkTextDisp.c: and -D_FORTIFY_SOURCE=2
+ * unix/tkUnixWm.c:
+ * win/tkWinWm.c:
+
+2010-12-05 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * unix/tcl.m4: [Patch 3116490]: cross-compile support for unix
+ * unix/configure (autoconf-2.59)
+
+2010-12-03 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tcl.m4: [Patch 3116490]: cross-compile Tcl mingw32 on unix
+ * win/configure: This makes it possible to cross-compile Tcl/Tk for
+ Windows (either 32-bit or 64-bit) out-of-the-box on UNIX, using
+ mingw-w64 build tools.
+
+2010-12-02 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkInt.decls (TkDrawAngledTextLayout,TkDrawAngledChars,...):
+ Expose angled text API for Emiliano Gavilán. Still only in internal
+ stub table.
+
+2010-11-29 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkAtom.c: Fix various 64-bit gcc(-4.5.2) warnings: cast
+ * generic/tkSelect.c: from pointer to integer of different size.
+ * win/stubs.c:
+ * win/tkWinButton.c:
+ * win/tkWinColor.c:
+ * win/tkWinPixmap.c:
+ * win/tkWinScrlbr.c:
+ * win/tkWinWindow.c:
+ * win/tkWinWm.c:
+ * win/ttkWinMonitor.c:
+ * win/tkWin32Dll.c: Make assembler code compile in Win64 with gcc.
+
+2010-11-24 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkWinDialog.c: [Bug 3071836]: Crash/Tcl_Panic on WinXP saving
+ * win/tkWinInit.c: file to C:\, and rewrite TkpDisplayWarning not
+ to use any Tcl functions any more. This allows TkpDisplayWarning to be
+ used as panic proc.
+ * win/winMain.c: Use TkpDisplayWarning as panic proc on Windows.
+ * generic/tkMain.c: Remove unused strrchr, combine outChannel and
+ errChannel variables to a single variable.
+
+2010-11-19 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkCanv*.c: Revise Tcl_Panic() calls ending with a
+ * generic/tkGeomerty.c: newline removing the newline, because
+ * generic/tkImgPhInstance.c: Tcl_Panic() outputs a final newline
+ * generic/tkMenu.c: already.
+ * generic/tkRectOval.c:
+ * generic/tkTextBTree.c:
+ * generic/tkWindow.c:
+ * unix/tkUnixRFont.c:
+ * win/tkWinColor.c:
+ * win/tkWinDraw.c:
+ * win/tkWinMenu.c:
+
+2010-11-18 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/winMain.c: [FRQ 491789]: "setargv() doesn't support a unicode
+ cmdline" now implemented for cygwin and mingw32 too.
+ * win/configure.in: Allow cross-compilation by default.
+ * win/configure (regenerated)
+
+2010-11-17 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tcl.m4: [FRQ 491789]: "setargv() doesn't support a unicode
+ cmdline" now implemented for mingw-w64
+ * win/configure (regenerated)
+ * win/winMain.c Workaround for bug in some versions of mingw-w64
+
+2010-11-16 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/winMain.c Bring compilation under mingw-w64 a bit closer
+ * win/tcl.m4 to reality. See for what's missing:
+ https://sourceforge.net/apps/trac/mingw-w64/wiki/Unicode%20apps
+ * win/configure: (re-generated)
+ * win/tkWinPort.h: [Bug 3110161]: Extensions using TCHAR don't compile
+ on VS2005 SP1
+
+2010-11-10 Andreas Kupries <andreask@activestate.com>
+
+ * changes: Updates for 8.6b2 release.
+
+2010-11-06 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * library/msgs/*.msg: Update NL catalog. For other languages,
+ sorting and fix some locations of "&".
+
+2010-11-05 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * library/demos/widget: Use unicode copyright sign, instead of
+ * library/demos/en.msg: depending on translation.
+ * library/demos/nl.msg:
+ * generic/tkMain.c: Sync TK_ASCII_MAIN usage with tclMain.c
+
+2010-11-04 Don Porter <dgp@users.sourceforge.net>
+
+ * changes: Updates for 8.6b2 release.
+
+2010-11-03 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkWinClipboard.c: [FRQ 2965056]: Windows build with
+ * win/tkWinDialog.c: -DUNICODE
+ * win/tkWinMenu.c:
+
+2010-10-11 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkDecls.h: [FRQ 491789]: "setargv() doesn't support a
+ * doc/Tk_Main.3: unicode cmdline" implemented for Tk on MSVC++
+ * win/Makefile.in:
+ * win/makefile.vc:
+ * win/winMain.c:
+ * win/rules.vc: Update for VS10
+
+2010-10-11 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkTreeview.c: [Bug 3085489]: Fix crash in 'tag add' /
+ 'tag remove' commands when no -tags specified.
+
+2010-10-11 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkWinMenu.c: [FRQ 2965056]: Windows build with -DUNICODE
+ * win/tkWinWm.c:
+ * win/tcl.m4: Add netapi32 to the link line, so we no longer
+ * win/makefile.vc: have to use LoadLibrary to access those
+ * win/configure: functions.
+
+2010-10-06 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkWinClipboard.c: [FRQ 2965056]: Windows build with
+ * win/tkWinColor.c: -DUNICODE
+ * win/tkWinCursor.c:
+ * win/tkWinFont.c:
+ * win/tkWinTest.c:
+ * win/tkWinMenu.c:
+ * win/tkWinPixmap.c:
+ * win/tkWinX.c: Eliminate isWinNT variable
+ * win/Makefile.in (genstubs): Generate ttk files as well.
+
+2010-10-06 Donal K. Fellows <dkf@users.sf.net>
+
+ * win/Makefile.in (genstubs): [Tcl Bug 3082049]: Typo.
+
+2010-10-05 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkWinX.c: [Bug 3080953]: Malformed Unicode characters in %A
+ substitution Problem was in the static function GetTranslatedKey().
+
+2010-10-01 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkImgPhoto.c (Tk_PhotoPutBlock, Tk_PhotoPutZoomedBlock):
+ [Bug 3078902]: Ensure that zero-dimensioned data blocks cause no
+ changes at all instead of causing a hang.
+
+2010-09-29 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * unix/tcl.m4: Sync with Tcl version
+ * unix/configure: Re-generate with autoconf-2.59
+ * win/configure:
+ * generic/tkMain.c Make compilable with -DUNICODE as well
+
+2010-09-28 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkWinSend.c: [Bug 3076671]: CVS HEAD Tk build fails on win32
+ with msys/mingw. Make it compile on older mingw as well.
+ * generic/tk.decls: Add explicit scspec "EXTERN", as in Tcl
+ * generic/tkInt.decls:
+ * generic/tkStubInit.c: Don't let Tk_MainEx macro disturb compilation
+
+2010-09-23 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tcl.m4: Add -Wdeclaration-after-statement
+ * win/configure: (regenerated)
+ * win/tkWinX.c: Make compilable with -DUNICODE.
+ * win/winMain.c:
+ * unix/tkAppInit.c: Many clean-ups in comments, so all
+ (tcl|tk)AppInit.c variants use the same style.
+ * generic/ttk/ttkGenStubs.tcl: Dummy genStubs::export (from
+ genStubs.tcl)
+
+2010-09-20 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/ttk/ttkGenStubs.tcl: Clean-up, port all genStubs.tcl changes
+ * generic/ttk/ttk.decls: from Tcl to ttkGenStubs.tcl as well (no
+ * generic/tk.decls: change in any output files). This brings
+ * generic/tkInt.decls: all *.decls in the same form as tcl.decls
+
+2010-09-16 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinX.c (_WIN32_IE): update to IE5.5 base expectation
+
+2010-09-14 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/rules.vc [FRQ 2965056]: Windows build with -DUNICODE
+ * win/Makefile.in
+
+2010-09-13 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkWin.h Move definitions of WINVER/_WIN32_WINNT
+ * win/tkWinDialog.h to one place, now that we only support
+ * win/tkWinMenu.c Win2000+
+ * win/tkWinX.c
+
+2010-09-10 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkWinEmbed.c: Make compilable with -DUNICODE
+ * win/tkWinClipboard.c: Mark those files as not compilable with
+ * win/tkWinColor.c: -DUNICODE, so add a TODO.
+ * win/tkWinCursor.c:
+ * win/tkWinDialog.c:
+ * win/tkWinFont.c:
+ * win/tkWinMenu.c:
+ * win/tkWinPixmap.c:
+ * win/tkWinTest.c:
+ * win/tkWinWm.c:
+ * win/tkWinX.c:
+ * win/winMain.c:
+ * win/tkWinPort.h: mingw/cygwin fixes: <tchar.h> should always
+ be included here.
+
+2010-09-09 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/rules.vc: (sync with tcl version)
+ * win/makefile.vc: mingw should always link with -ladvapi32
+ * win/tcl.m4:
+ * win/configure: (regenerated)
+ * win/tkWinInt.h: Remove ascii variant of tkWinPocs table,
+ * win/tkWinX.c: it is no longer necessary.
+ * win/tkWinTest.c:
+
+2010-09-08 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkTreeview.c (TreeviewSeeCommand): [Bug 2829363]:
+ Schedule redisplay if [$tv see] opens any items.
+
+2010-09-05 Donal K. Fellows <dkf@users.sf.net>
+
+ * library/bgerror.tcl: [Bugs 3046742,3046750]: Improve keybindings for
+ the background error dialog, and allow the use of the window manager
+ controls for closing it (where supported). The Escape key now causes
+ all remaining background error messages in the queue to be dropped.
+
+2010-09-02 Joe English <jenglish@users.sourceforge.net>
+
+ * library/ttk/winTheme.tcl, library/ttk/xpTheme.tcl,
+ * library/ttk/vistaTheme.tcl: [Bug 3057573]: Specify disabled combobox
+ text foreground color.
+
+2010-08-31 Andreas Kupries <andreask@activestate.com>
+
+ * win/tcl.m4: Applied patch by Jeff fixing issues with the manifest
+ handling on Win64.
+ * win/configure: Regenerated.
+
+2010-08-26 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/Makefile.in: Add valgrind target
+ * unix/configure, unix/tcl.m4: [Bug 1230554]: SHLIB_LD_LIBS='${LIBS}'
+ for OSF1-V*. Add /usr/lib64 to set of auto-search dirs.
+ (SC_PATH_X): Correct syntax error when xincludes not found.
+
+ * win/Makefile.in (VC_MANIFEST_EMBED_DLL VC_MANIFEST_EMBED_EXE):
+ * win/configure, win/configure.in, win/tcl.m4: SC_EMBED_MANIFEST macro
+ and --enable-embedded-manifest configure arg added to support manifest
+ embedding where we know the magic. Help prevents DLL hell with MSVC8+.
+
+ * generic/tkText.c (DumpLine): [Bug 3053347]: Replace segPtr->size
+ with currentSize throughout, but particularly in if lineChanged block
+ where segPtr may no longer be valid.
+
+2010-08-21 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tk*Decls.h: (regenerated with modified genStubs.tcl)
+ * generic/tk*StubInit.c
+
+2010-08-18 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/ttk/ttkGenStubs.tcl: [Patch 3034251]: partly: remove some
+ more unneeded ifdeffery, as in tcl/tools/genStubs.tcl.
+ * generic/tk.h: Move USE_OLD_IMAGE support after tkDecls.h
+ * generic/*Decls.h (regenerated)
+ * generic/ttk/ttkDecls.h
+
+2010-08-11 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/Makefile.in (%.${OBJEXT}): Better implicit rules support
+
+ * unix/configure: regen with ac-2.59
+ * unix/configure.in, unix/Makefile.in:
+ * unix/tcl.m4 (AIX): Remove the need for ldAIX, replace with
+ -bexpall/-brtl. Remove TK_EXP_FILE (export file) and other baggage
+ that went with it. Remove pre-4 AIX build support.
+
+2010-08-11 Don Porter <dgp@users.sourceforge.net>
+
+ * changes: Updates for 8.6b2 release.
+
+2010-08-04 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * license.terms: fix DFARs note for number-adjusted rights clause
+
+2010-08-03 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/button.tcl (::tk::CheckEnter): [AS Bug#87409]: Use uplevel
+ set instead of set :: to work with other var resolvers (itcl).
+
+2010-07-19 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkImgGIF.c (StringWriteGIF): Added ability to write a GIF to
+ a string (as a byte array, of course) following comments on c.l.t by
+ Aric Bills. Also improved readability of some of the function and
+ field names in this file.
+
+2010-07-16 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkDecls.h: [Tcl Bug 3029891]: Functions that don't belong in
+ the stub table (Tk part, not really removed from the stub table, just
+ disabled)
+ * generic/tkMain.c: [Bug 3027438]: Tk_Main calls Tcl_CreateInterp
+ * generic/tk.h: before Tcl_FindExecutable
+
+2010-07-06 Andreas Kupries <andreask@activestate.com>
+
+ * doc/text.n: Fixed minor typo in the description of 'text delete', as
+ reported by <eee@users.sf.net> on the chat.
+
+2010-07-01 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/rules.vc: [Bug 3020677]: wish can't link reg1.2
+
+2010-06-22 Anton Kovalenko <a_kovalenko@users.sf.net>
+
+ * generic/tkPlace.c: [Patch 3019624]: modify "place" command, making
+ it get main window through ClientData (like grid or pack do), instead
+ of calling Tk_MainWindow(interp).
+ * generic/tkWindow.c: modify "place" entry in commands[], turn on
+ passMainWindow flag.
+
+2010-06-22 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/ttk/ttkGenStubs.tcl: [Bug 3019363]: "make genstubs" failure
+ * generic/ttk/ttkDecls.h: (regenerated)
+ * generic/ttk/ttkTheme.c: Unnecessary type cast
+
+2010-06-21 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkInt.decls: [Patch 2999889]: TkCopyAndGlobalEval obsolete
+ * generic/tkIntDecls.h
+ * generic/tkBind.c
+ * generic/tkStubInit.c
+
+2010-06-19 Joe English <jenglish@users.sourceforge.net>
+
+ * win/tkWinScrlbr.c, carbon/tkMacOSXScrlbr.c: Replace binding
+ procedures with ordinary event handlers [Patch 3009998].
+ * generic/tkBind.c, generic/tk.h, generic/tkInt.h,
+ * generic/tkInt.decls: Simplifications enabled by previous change:
+ TkCreateBindingProcedure() and associated machinery no longer needed;
+ TkBindDeadWindow() no longer needed; TK_DEFER_MODAL_LOOP and
+ associated machinery no longer needed.
+ * generic/tkTest.c, tests/bind.test: Tests related to C binding
+ procedures no longer needed.
+ * generic/tkWindow.c: TkBindDeadWindow() no longer needed.
+ * generic/tkIntDecls.h, generic/tkStubInit.c: Regenerated.
+
+2010-06-15 Joe English <jenglish@users.sourceforge.net>
+
+ * library/ttk/ttk.tcl: Bump dummy [package ifneeded tile] version to
+ 0.8.6; see [Bug 3016598].
+
+2010-06-15 Donal K. Fellows <dkf@users.sf.net>
+
+ * library/text.tcl (TextCursorInSelection): [Patch 2585265]: Make it
+ so that pressing delete or backspace when the primary selection does
+ not include the insertion cursor does not cause the deletion of the
+ inserted text.
+
+2010-06-15 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkCanvArc.c: Eliminate many unnecessary (ClientData) type
+ * generic/tkCanvas.c: casts.
+ * generic/tkCanvBmap.c:
+ * generic/tkCanvImg.c:
+ * generic/tkCanvLine.c:
+ * generic/tkCanvPoly.c:
+ * generic/tkCanvTest.c:
+ * generic/tkCanvWind.c:
+ * generic/tkRectOval.c:
+ * generic/tkScrollbar.c:
+ * generic/tkStyle.c:
+ * generic/tkTest.c:
+ * unix/tkUnixEmbed.c:
+ * unix/tkUnixEvent.c:
+ * unix/tkUnixScale.c:
+ * unix/tkUnixScrlbr.c:
+ * unix/tkUnixSelect.c:
+ * unix/tkUnixWm.c:
+ * carbon/tkMacOSXDialog.c: Terminate TkEnsemble definition with NULL
+ * macosx/tkMacOSXDialog.c:
+
+2010-05-31 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/tkBind.c (Tk_CreateBinding): [Bug 3006842]: Silently ignore
+ empty scripts.
+
+2010-05-27 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkTreeview.c, tests/ttk/treeview.test:
+ [$tv tag bind $tag <...> {}] now removes binding completely.
+ Fixes [Bug 3006842] (although there's still a problem somewhere
+ in Tk_CreateBinding()).
+
+2010-05-26 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * tests/wm.test: Fix 3 tests on Ubuntu 10.4, two of them timing
+ dependent, one wm-dependent.
+ * generic/tkText.c: Fix some gcc strict-aliasing warnings,
+ * unix/tkUnixFont.c: discovered with "-Wstrict-aliasing=2"
+ * unix/tkUnixSelect.c:
+
+2010-05-20 Donal K. Fellows <dkf@users.sf.net>
+
+ * win/tkWinX.c (HandleIMEComposition): [Bug 2992129]: Ensure that all
+ places that generate key events zero them out first; Tk relies on that
+ being true for the generic parts of the fix for Bug 1924761.
+
+2010-05-17 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkWinDialog.c: Fix [Bug 3002230]: tk_chooseDirectory returns
+ garbage on cancel
+
+2010-05-17 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/tkBind.c: Revert [Patch 2999920], as it entails an
+ incompatible change to the C API is and is the cause of [Bug 3002768].
+
+2010-05-17 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkBind.c: [Patch 2999920]: Optimize Internal Virtual event
+ string operations.
+ * win/tkWinDialog.c: [Bug 2987995]: Tk_getOpenFile returns garbage
+ under described circumstances
+
+2010-05-11 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * doc/RestrictEv.3: Consistent use of variable names in RestrictEvent
+ * generic/tkGrab.c: API documentation and implementation: Use 'prev'
+ * unix/tkUnixDraw.c: instead of 'old', and 'arg' instead of
+ * unix/tkUnixSend.c: 'clientData' everywhere, just as in tkEvent.c.
+ * unix/tkUnixWm.c
+
+2010-05-10 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * doc/BindTable.3: Bring in line with actual implementation.
+ * generic/tk.decls: Change Tk_CreateBinding param name, as in doc
+ * generic/tkInt.decls: CONSTify TkCopyAndGlobalEval,
+ * generic/tkBind.c: TkpSetMainMenubar, TkpMenuNotifyToplevelCreate,
+ * generic/tkMenu.c: and TkSetWindowMenuBar
+ * generic/tkDecls.h: (regenerated)
+ * generic/tkIntDecls.h: (regenerated)
+ * carbon/tkMacOSXMenu.c:
+ * macosx/tkMacOSXMenu.c:
+ * unix/tkUnixMenu.c:
+ * win/tkWinMenu.c:
+
+2010-05-03 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tk.h: Bump patchlevel to 8.6b1.2 to distinguish
+ * library/tk.tcl: CVS snapshots from earlier snapshots as well
+ * unix/configure.in: as the 8.6b1 and 8.6b2 releases.
+ * win/configure.in:
+
+ * unix/configure: autoconf-2.59
+ * win/configure:
+
+2010-05-03 Donal K. Fellows <dkf@users.sf.net>
+
+ * library/button.tcl (CheckInvoke, CheckEnter): [Patch 1530276 redux]:
+ Apply a bit more care to ensure that things continue to work correctly
+ even when there is no -selectcolor defined.
+
+2010-04-29 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkWin.h: Unnecessary TCL_STORAGE_CLASS re-definition
+ * win/tkWinInt.h: Make various functions MODULE_SCOPE
+ * win/tkWinButton.c: TCHAR-related fixes, making al those
+ * win/tkWinFont.c: files compile fine when TCHAR != char.
+ * win/tkWinScrlbr.c:
+ * win/tkWinWindow.c:
+ * win/tkWinWm.c:
+ * win/tkWinX.c:
+ * win/ttkWinMonitor.c:
+ * win/ttkWinXPTheme.c:
+
+2010-04-25 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkImgPNG.c (ReadIDAT, DecodePNG): Move the check for overall
+ termination of the compressed stream until after the final IDAT has
+ been read, so that multi-segment images will work right. Reported by
+ Andy Goth on the Wiki.
+
+2010-04-23 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkImgGIF.c: Formatting
+ * generic/tkListbox.c: fix typo;
+ * generic/tkTrig.c: fix typo;
+ * generic/tkInt.h: fix typo; remove not existing tkDisplayList;
+ * generic/*.h: Useless re-definitions of TCL_STORAGE_CLASS
+
+2010-04-20 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkPort.h: Make sure that tkWinPort.h is always
+ * generic/tkIntXlibDecls.h: included before tcl.h, otherwise the
+ * win/tkWinPort.h: fallback for TCHAR might go off before the
+ inclusion of <tchar.h>
+ * win/tkWinDialog.c: Define OPENFILENAME_SIZE_VERSION_400 if
+ needed.
+ * compat/stdlib.h: Include <tcl.h> only when not already
+ * compat/unistd.h: done.
+ * generic/tkInt.h: tkPort.h already includes tk.h, which
+ includes tcl.h.
+ * generic/tk3d.h: Always use #include "tkInt.h", not
+ * generic/tkColor.h: <tkInt.h>
+ * xlib/xcolors.c:
+ * xlib/xgc.c:
+
+2010-04-19 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkWinDialog.c: Fix [Bug 2987995]: Tk_GetOpenFile returns garbage
+ under described circumstances.
+ * win/tkWinDialog.c: [Patch 2898255]: Filenames limit with
+ Tk_GetFileName().
+ Assure modern style dialogs where available
+
+2010-04-13 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkWinPort.h Fix [Patch 2986105]: conditionally defining
+ strcasecmp/strncasecmp
+
+2010-04-12 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkImgPNG.c (WriteIDAT): [Bug 2984787]: Use the correct
+ flushing semantics when handling the last data from the image. Without
+ this, many PNG readers (notably including Firefox) refuse to show the
+ image and instead complain about errors.
+ (ReadIDAT): Added sanity checks to ensure that when we've got bad data
+ of the sorts of forms we were previously generating, we detect it and
+ error out rather than silently failing.
+ (WriteExtraChunks): New function to write in some basic metadata.
+
+2010-04-09 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * doc/photo.n: Follow-up to [Bug 2983824]: update doc.
+
+2010-04-09 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkImgPhoto.c (ImgPhotoCmd): [Bug 2983824]: Use the file
+ extension to guess the output format to use if one isn't specified.
+
+2010-04-08 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkWinPort.h: Add <wchar.h> to tkWinPort.h, and
+ * win/tkWinSend.c: remove some earlier CYGWIN-related
+ * win/tkWinSendCom.c: hacks which are no longer necessary.
+
+2010-04-06 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tcl.m4: Sync with Tcl version
+ * unix/tcl.m4:
+ * win/configure: (regenerate with autoconf-2.59)
+ * unix/configure: [Bug 2982540]: configure and install* script
+ files should always have LF
+
+2010-03-29 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * unix/tcl.m4: Only test for -visibility=hidden with gcc
+ (Second remark in [Bug 2976508])
+ * unix/configure: regen
+
+2010-03-29 Donal K. Fellows <dkf@users.sf.net>
+
+ * unix/tkUnixRFont.c (GetFont): [Bug 2978410]: Do not use non-constant
+ initializers for structures, since HP-UX cc doesn't like it.
+
+2010-03-28 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkTagSet.c, generic/ttk/ttkTheme.c,
+ * generic/ttk/ttkTheme.h, generic/ttk/ttkTreeview.c,
+ * generic/ttk/ttkWidget.h, doc/ttk_treeview.n,
+ * tests/ttk/treetags.test: ttk::treeview widget: add 'tag names',
+ 'tag add', and 'tag remove' methods.
+
+2010-03-23 Donal K. Fellows <dkf@users.sf.net>
+
+ * unix/configure.in, unix/Makefile.in: [Bug 2965133]: Get rid of the
+ spurious NONE and some pointless quotes that were causing problems
+ with building Tk on OSX. Overall bug might not yet be solved.
+
+2010-03-17 Donal K. Fellows <dkf@users.sf.net>
+
+ * library/entry.tcl: [Bug 2971663]: Make the <Up> and <Down> keys
+ * library/ttk/entry.tcl: explicitly do nothing, since Tk-on-Cocoa will
+ generate (invisible zero-width) characters for them otherwise. The
+ explicitly empty bindings are harmless on other platforms.
+
+2010-03-16 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * unix/.cvsignore: Ignore .a and .so
+
+2010-03-12 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/rules.vc: Fix [Tcl Bug 2967340]: Static build failure
+ * win/makefile.vc:
+ * win/.cvsignore:
+
+2010-03-12 Donal K. Fellows <dkf@users.sf.net>
+
+ * library/iconlist.tcl: Factor out some of the machinery for
+ * library/megawidget.tcl: making a megawidget framework. Not a
+ public API at the moment.
+
+2010-03-11 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkText.c (DumpLine): [Bug 2968379]: When peers are about,
+ there can be unnamed marks present during a dump. Ignore them as they
+ will just be for the peers' insert and current marks, which aren't
+ very important.
+ (DumpLine): Removed lame reliance on the leading letters of the names
+ of segment types. Entailed expanding the scope of the declarations of
+ the types of embedded images and windows.
+
+2010-03-08 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkPlatDecls.h: [Bug 2965600]: Correct broken 2886635 fix.
+
+2010-03-06 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * library/menu.tcl: [Bug 2949774]: When using the non-ClickToFocus
+ menu mode cascade menus should popdown once the pointer moves to
+ another entry to be compatible with current X desktop usage.
+
+2010-03-04 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * unix/configure.in: Don't use -fvisibility=hidden
+ * unix/tcl.m4: for cygwin.
+ * win/tkWinTest.c: Make tkTestWinProcs const
+
+2010-03-04 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/clipboard.n: Added note about STRING vs. UTF8_STRING types.
+
+2010-03-02 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * unix/tcl.m4: [Tcl FRQ 2959069]: Support for -fvisibility=hidden
+ * unix/configure: (regenerated with autoconf-2.59)
+
+2010-02-23 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * unix/configure.in: Use @EXEEXT@ in stead of @EXT_SUFFIX@
+ * unix/tcl.m4:
+ * unix/Makefile.in: Use -DBUILD_tk
+ * unix/configure: (regenerated)
+ * generic/tkConfig.c: Make internal Tk_ObjCustomOption const
+ * generic/tkPanedWindow.c:
+ * generic/tkTest.c:
+ * generic/tkText.c:
+
+2010-02-21 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkText.c (TextEditCmd): [Bug 1799782]: Refix this, so that
+ <<Modified>> events are issued when things change.
+
+2010-02-20 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkTreeview.c: Cache the result of the last call to
+ EndPosition() to avoid quadratic-time behavior in the common cases
+ where the treeview is populated in depth-first or breadth-first
+ order.
+
+2010-02-19 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkWinColor.c: remove unused "dataKey" variable
+
+2010-02-19 Donal K. Fellows <dkf@users.sf.net>
+
+ * unix/configure.in, unix/Makefile.in: [Bug 2415437]: Corrections to
+ allow installation of Tcl and Tk to different directories, especially
+ when neither is a system standard location. Also [Tcl Bug 2307398].
+
+ * unix/installManPage: [Tcl Bug 2954638]: Correct behaviour of manual
+ page installer. Also added armouring to check that assumptions about
+ the initial state are actually valid (e.g., look for existing input
+ file).
+
+2010-02-19 Stuart Cassoff <stwo@users.sourceforge.net>
+
+ * tcl.m4: Correct compiler/linker flags for threaded builds on
+ OpenBSD.
+ * configure: (regenerated).
+
+2010-02-18 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkButton.h: Put all Tk_OptionSpec for buttons and labels
+ * generic/tkButton.c: in const memory. With some changes to win32
+ * win/tkWinButton.c: and macosx, preventing direct writes to
+ * unix/tkUnixPort.h: read-only memory.
+ * carbon/tkMacOSXPort.h:
+ * macosx/tkMacOSXButton.c:
+
+2010-02-17 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/tkMenu.c: [Bug 2952745]: Defer TkMenuOptionTables cleanup to
+ CallWhenDeleted() time, to ensure that the record doesn't get freed
+ until after all widget instance commands have been deleted.
+
+2010-02-17 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tk.decls: CONSTify everything related to Tk_ConfigSpec
+ * generic/tk.h:
+ * generic/tkCanvArc.c: Many tables can now be put in const memory
+ * generic/tkCanvas.c:
+ * generic/tkCanvBmap.c:
+ * generic/tkCanvImg.c:
+ * generic/tkCanvLine.c:
+ * generic/tkCanvPoly.c:
+ * generic/tkCanvPs.c:
+ * generic/tkCanvText.c:
+ * generic/tkCanvWind.c:
+ * generic/tkImgBmap.c:
+ * generic/tkImgPhoto.c:
+ * generic/tkOldConfig.c:
+ * generic/tkRectOval.c:
+ * generic/tkScrollbar.c:
+ * generic/tkScrollbar.h:
+ * generic/tkDecls.h: (regenerated)
+ * doc/CanvTkwin.3:
+ * doc/ConfigWidg.3:
+ * doc/CrtItemType.3:
+ * win/tkWinScrlbr.c:
+ * carbon/tkMacOSXScrlbr.c:
+ * macosx/tkMacOSXScrlbr.c:
+
+2010-02-16 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkWindow.c: Reverted rename from tkStubs to tkConstStubs
+ * generic/tkStubInit.c: (regenerated)
+ * generic/tkArgv.c: make defaultTable const
+ * generic/tkScrollbar.c:Store default for "-with" in static non-const
+ space
+ * win/tkWinInt.h: Make tkWinProcs const, and 5 procs
+ * win/tkWinX.c: MODULE_SCOPE.
+ * win/tkWinColor.c: Make sysColors const.
+ * win/tkWinKey.c: Make keymap const.
+ * win/tkWinScrlbr.c: Simplify copying of "-with" default value.
+ * unix/tkUnixWm.c: Make TkSetTransientFor static.
+ * tests/textImage.test: textImage-1.13 depends on hash-order
+
+2010-02-12 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tcl.m4: Use -pipe for gcc on win32
+ * win/configure: (mingw/cygwin) (regenerated)
+ * unix/tkUnixColor.c: Make sure that TkpCmapStressed is exported
+ * generic/tkImgPhoto.c: Clean up unused Tk_CreatePhotoOption
+ * generic/tkBind.c: Make more internal arrays "const"
+ * generic/tkBusy.c:
+ * generic/tkButton.c:
+ * generic/tkEvent.c:
+ * generic/tkGrab.c:
+ * generic/tkImgBmap.c:
+ * generic/tkObj.c:
+ * generic/tkOption.c:
+ * generic/tkPanedWindow.c:
+ * generic/tkPointer.c:
+ * generic/tkWindow.c:
+ * generic/tkImgPhoto.c: Eliminate never used Tk_CreatePhotoOption()
+
+2010-02-05 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * carbon/tkMacOSXDialog.c: Make more internal tables "const"
+ * macosx/tkMacOSXDialog.c:
+ * unix/tkUnixButton.c:
+ * unix/tkUnixWm.c:
+ * win/tkWinDialog.c:
+ * generic/tkWindow.c:
+ * generic/tk*Decls.h: (regenerated with new
+ * generic/tkStubInit.c: genStubs.tcl from Tcl)
+
+2010-02-05 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/*.[ch]: Revert contravariant const qualifiers added by
+ the previous commit to keep codebase in sync with the Tile extension,
+ which must remain 8.4 compatible.
+
+2010-02-05 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/ttk/ttkGenStubs.tcl: Follow-up to [2010-01-29] commit:
+ prevent space within stub table function parameters if the
+ parameter type is a pointer. Make the various stub tables and
+ hook pointers const, just as Tcl and Tk.
+ * generic/ttk/ttkDecls.h: (regenerated)
+ * generic/ttk/ttkStubInit.c: (regenerated)
+ * generic/ttk/ttk.decls: Minor formatting
+ * generic/ttk/ttkButton.c: Make more internal tables "const"
+ * generic/ttk/ttkDefaultTheme.c:
+ * generic/ttk/ttkEntry.c:
+ * generic/ttk/ttkImage.c:
+ * generic/ttk/ttkInit.c:
+ * generic/ttk/ttkLayout.c:
+ * generic/ttk/ttkNotebook.c:
+ * generic/ttk/ttkPanedWindow.c:
+ * generic/ttk/ttkProgress.c:
+ * generic/ttk/ttkStubLib.c:
+ * generic/ttk/ttkTheme.c:
+ * generic/ttk/ttkTreeview.c:
+ * generic/ttk/ttkWidget.c:
+ * generic/ttk/ttkWidget.h:
+
+2010-01-31 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkTheme.h, generic/ttk/ttkWidget.h, generic/ttk/*.c:
+ Change signature of widget subcommand procedures to match
+ Tcl_ObjCmdProc. Merge now-redundant ensemble dispatch code.
+
+2010-01-29 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/ttk/ttkGenStubs.tcl: No longer generate a space after "*"
+ and immediately after a function name, so the
+ format of function definitions in *Decls.h
+ match all other *.h header files.
+ * generic/ttk/ttkDecls.h: (re-generated)
+ * generic/tk.decls: Formatting
+ * generic/tkDecls.h: (re-generated)
+ * generic/tkIntDecls.h:
+ * generic/tkIntPlatDecls.h:
+ * generic/tkIntXlibDecls.h:
+ * generic/tkPlatDecls.h:
+ * generic/tkBind.c: Little simplification
+
+2010-01-19 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkInt.h: Don't depend on <stdio.h> from tcl.h any
+ * generic/tkOldConfig.c: more.
+ * generic/ttk/ttkClamTheme.c: Fix more gcc warnings: missing
+ * generic/ttk/ttkClassicTheme.c: initializer.
+ * generic/ttk/ttkDefaultTheme.c:
+ * generic/ttk/ttkElements.c:
+ * generic/ttk/ttkEntry.c:
+ * generic/ttk/ttkInit.c:
+ * generic/ttk/ttkLabel.c:
+ * generic/ttk/ttkNotebook.c:
+ * generic/ttk/ttkPanedwindow.c:
+ * generic/ttk/ttkSquare.c:
+ * generic/ttk/ttkTreeview.c:
+ * win/ttkWinTheme.c:
+ * win/tkWinMenu.c: Add missing #include <string.h>
+ * win/tkWinPort.h: Fix include files for CYGWIN
+ * win/tkWinSend.c:
+ * win/tkWinSendCom.c:
+ * win/tkWinTest.c: Fix gcc warning
+ * win/winMain.c: Eliminate use of __argc and __argv for CYGWIN
+ * win/tcl.m4: Make cygwin configuration error into
+ * win/configure.in: a warning: CYGWIN compilation works
+ * win/configure: although there still are test failures.
+
+2010-01-19 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkCanvas.c (TagSearchScanExpr): [Bug 2931374]: Stop overflow
+ of working buffer during construction of long tag expressions.
+
+2010-01-19 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ TIP #359 IMPLEMENTATION
+
+ * library/bgerror.tcl: Extended Window Manager Hints following the
+ * library/clrpick.tcl: freedesktop.org specification are now
+ * library/demos/widget: supported on X11 using a new [wm attribute]
+ * library/dialog.tcl: called '-type'. This feature is now used in
+ * library/msgbox.tcl: the Tk library functions where appropriate.
+ * library/tkfbox.tcl:
+ * library/ttk/combobox.tcl:
+ * tests/unixWm.test:
+ * tests/wm.test:
+ * unix/tkUnixWm.c:
+
+2010-01-18 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkCanvArc.c: Fix more gcc warnings: missing initializer
+ * generic/tkCanvBmap.c:
+ * generic/tkCanvImg.c:
+ * generic/tkCanvLine.c:
+ * generic/tkCanvPoly.c:
+ * generic/tkCanvPs.c:
+ * generic/tkCanvText.c:
+ * generic/tkCanvWind.c:
+ * generic/tkCmds.c:
+ * generic/tkImgBmap.c:
+ * generic/tkImgGIF.c:
+ * generic/tkImgPhoto.c:
+ * generic/tkImgPNG.c:
+ * generic/tkImgPPM.c:
+ * generic/tkMenu.c:
+ * generic/tkMenubutton.c:
+ * generic/tkMessage.c:
+ * generic/tkOldTest.c:
+ * generic/tkPanedWindow.c:
+ * generic/tkRectOval.c:
+ * generic/tkScrollbar.c:
+ * generic/tkSquare.c:
+ * generic/tkTest.c:
+ * generic/tkText.c:
+ * generic/tkTextImage.c:
+ * generic/tkTextTag.c:
+ * generic/tkTextWind.c:
+ * generic/tkTrig.c:
+ * generic/tkCanvas.c: [Patch 2932808]: Canvas items not updating
+ on widget state change.
+
+2010-01-13 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkMenubutton.h: Eliminate tkpMenubuttonClass
+ * generic/tkButton.h make tkpButtonProcs CONST
+ * generic/tkBusy.c: fix gcc warning: missing initializer
+ * generic/tkButton.c
+ * generic/tkCanvas.c
+ * generic/tkConsole.c
+ * generic/tkEntry.c
+ * generic/tkFrame.c
+ * generic/tkListbox.c
+ * generic/tkMenu.c
+ * generic/tkMenubutton.c
+ * generic/tkMessage.c
+ * generic/tkScale.c
+ * generic/tkScrollbar.h
+ * generic/tkText.c
+ * generic/ttk/ttkWidget.c
+ * carbon/tkMacOSXButton.c
+ * carbon/tkMacOSXMenubutton.c
+ * carbon/tkMacOSXScrlbr.c
+ * macosx/tkMacOSXButton.c
+ * macosx/tkMacOSXMenubutton.c
+ * macosx/tkMacOSXScrlbr.c
+ * unix/tkUnixButton.c
+ * unix/tkUnixMenubu.c
+ * unix/tkUnixScrolbr.c
+ * win/tkWinButton.c
+ * win/tkWinDialog.c
+ * win/tkWinEmbed.c
+ * win/tkWinFont.c
+ * win/tkWinInit.c
+ * win/tkWinKey.c
+ * win/tkWinScrlbr.c
+ * win/tkWinInt.h Add SPI_SETKEYBOARDCUES definition, needed for
+ original VC++ 6.0.
+
+2010-01-10 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * doc/SetClassProcs.3: CONSTify Tk_SetClassProcs
+ * generic/tk.decls
+ * generic/tkInt.h
+ * generic/tkWindow.c
+ * generic/tkDecls.h: (regenerated)
+ * unix/tcl.m4 Sync with Tcl version
+ * unix/configure (regenerated)
+
+2010-01-09 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ TIP #360 IMPLEMENTATION
+
+ * doc/menu.n: Remove special handling of the .help menu on
+ * library/obsolete.tcl: X11.
+ * unix/tkUnixMenu.c:
+
+ * library/menu.tcl: Make Tk menu activation follow mouse
+ * library/obsolete.tcl: movements.
+
+2010-01-08 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * doc/photo.n: [Bug 2927569]: Multiple edits have peverted the
+ original meaning of the phrase 'image file data' to reference
+ a filename option that does not exist.
+
+2010-01-07 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkTextDisp.c (AsyncUpdateLineMetrics): [Bug 2677890]: Fix
+ odd text widget update problem that had scrollbars being unable to
+ cover the whole widget. Fix is to reify the range to update sooner.
+
+2010-01-06 Donal K. Fellows <dkf@users.sf.net>
+
+ * library/tk.tcl: Centralize the definition of keys that
+ * library/entry.tcl: do common movement in entry and text
+ * library/spinbox.tcl: widgets. This is because they are
+ * library/text.tcl: subtlely different on the different
+ * library/ttk/entry.tcl: platforms. Lets Tk code work more
+ * doc/event.n (PREDEFINED VIRTUAL EVENTS): correctly with platform
+ conventions "out of the box".
+
+ * generic/tkBind.c (HandleEventGenerate, DoWarp): [Bug 2926819]:
+ * generic/tkInt.h (TkDisplay): Factor out the pointer
+ * generic/tkWindow.c (GetScreen): warping code a bit
+ * carbon/tkMacOSXMouseEvent.c (TkpWarpPointer): better and extend it
+ * macosx/tkMacOSXMouseEvent.c (TkpWarpPointer): to work on OSX too.
+ * unix/tkUnixEvent.c (TkpWarpPointer):
+ * win/tkWinPointer.c (TkpWarpPointer):
+
+ * unix/tkUnixWm.c (TkWmMapWindow): [Bug 1163496]: Allow windows to be
+ * tests/wm.test (wm-transient-8.1): set to be transients for withdrawn
+ masters correctly.
+
+2010-01-05 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tkWinDialog.c: [Patch 2898255]: Enable unlimited multiple file
+ selection from the open files dialog. (pawlak,fellows,thoyts)
+
+2010-01-05 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkMenu.c (MenuWidgetObjCmd): [Bug 220950]: Do not delete
+ menu entries if the first index to delete is explicitly after the last
+ index of existing entries.
+
+ * generic/tkFont.h (ROUND16): [Bug 2824916]: Use a correct rounding
+ * unix/tkUnixFont.c (TkpDrawAngledChars): macro for converting a
+ * unix/tkUnixRFont.c (TkpDrawAngledChars): double to a short. This
+ * win/tkWinFont.c (GetScreenFont): stops a number of small
+ visual artefacts from happening and reduces the effect of others. The
+ ROUND16 macro is now shared across all the font code (though some
+ platforms do not need it specially).
+
+2010-01-04 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * doc/TkInitStubs.3: [Bug 2192104]: Mention USE_TK_STUBS macro.
+ * library/dialog.tcl: [Bug 2811266]: <Return> binding should invoke
+ the button with the focus.
+ * library/fontchooser.tcl: [Bug 2727476]: Fix default size of font
+ chooser dialog and assigned minimum sizes for the lists.
+ * library/console.tcl: [Bug 580361]: Fix console <<Cut>> binding.
+ * library/console.tcl: Fix keyboard access to console menu.
+ * library/demos/filebox.tcl: Make prettier using ttk.
+ * library/demos/fontchoose.tcl: Fix display of demo code.
+ * library/tk.tcl: Correctly handle quoted ampersands in AmpMenuArgs
+
+2010-01-03 Donal K. Fellows <dkf@users.sf.net>
+
+ * unix/tcl.m4 (SC_CONFIG_CFLAGS): [Bug 1636685]: Use the configuration
+ for modern FreeBSD suggested by the FreeBSD porter.
+
+2010-01-03 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * generic/tkMenu.h: [Patch 2848897]: Support the system keyboard
+ * win/tkWinMenu.c: cues option on Windows. This system parameter
+ hides the underlines on menu items unless the keyboard is used to
+ open the menu. (kovalenko, thoyts)
+
+2010-01-03 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkFont.c (Tk_TextLayoutToPostscript): Simplified the code to
+ * generic/tkCanvPs.c (TkCanvPostscriptCmd): generate the preamble
+ * library/mkpsenc.tcl: for PS generation and
+ also simplify the code to output text following the observation that
+ it effectively only produces ASCII anyway, even when it might have the
+ option to do otherwise in theory.
+
+2010-01-03 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * library/tearoff.tcl: Tearoff menus should be transient and use the
+ toolwindow style on Windows.
+ * tests/menu.test: Menu tests using 'tkwait visibility' are unix only.
+
+2010-01-02 Donal K. Fellows <dkf@users.sf.net>
+
+ * unix/tkUnixEvent.c (TransferXEventsToTcl): [Bug 1924761]: Use the
+ new cache mechanism to force the extraction of the string of a key
+ event from XIM at the right time rather than after queueing when it
+ can be quashed by a race condition centered on the limited amount of
+ state in some XIM implementations.
+
+ * unix/tkUnixKey.c (TkpGetString): [Bug 1373712]: Cache the value that
+ * generic/tkInt.h (TkKeyEvent): will be substituted via %A so
+ * generic/tkEvent.c (CleanUpTkEvent): that we do not need to make it
+ * doc/HandleEvent.3 (ARGUMENTS): fresh each time, which causes
+ * doc/QWinEvent.3 (ARGUMENTS): trouble with some input
+ * carbon/tkMacOSXKeyEvent.c (InitKeyEvent): methods. Also includes the
+ * macosx/tkMacOSXKeyEvent.c (tkProcessKeyEvent): factoring out of some
+ * win/tkWinX.c (GenerateXEvent): code and update of
+ documentation to describe the slightly increased constraints on
+ how Tk_HandleEvent can be used.
+
+2010-01-01 Donal K. Fellows <dkf@users.sf.net>
+
+ * unix/tkUnixEvent.c (TransferXEventsToTcl): [Bug 1924761]: Move the
+ * generic/tkEvent.c (Tk_HandleEvent): passing of key events to
+ XFilterEvent to the low level point where all other events are
+ handled, where it should have been all along. This makes more input
+ methods work, stops [event generate] from interfering with input
+ methods, and allows the simplification of tkEvent.c by removing half
+ of InvokeInputMethods and allowing the rest - which was not full input
+ method handling - to be rolled back into Tk_HandleEvent. Introduces a
+ small potential bug when a focus change and input method handling are
+ too close together in the Tk event queue, but that should be less
+ deadly to usability than the previous problems where input methods
+ could fail completely or reorder key presses...
+
+2009-12-30 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * generic/tkMenu.c: [Patch 2879789]: Torn off menu items are only
+ * tests/menu.tcl: activated over a limited region of the window.
+ Fixed to make the whole width of a menu item activate the entry.
+
+2009-12-27 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tkWinMenu.c: [Bug 2879927]: Highlight for cascade items in
+ torn-off menus is incorrect on Windows.
+
+2009-12-25 Joe English <jenglish@users.sourceforge.net>
+
+ * library/ttk/utils.tcl, library/notebook.tcl: [Bugs 2917688,2546779]:
+ Reworked ActivateTab focus selection logic.
+
+2009-12-25 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/option.n: [Bug 2914943]: Correct the first example.
+ Also define what the format of option patterns is; that's a much less
+ commonly known fact than it used to be.
+
+2009-12-22 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * unix/tcl.m4: Sync with current Tcl version.
+ * unix/Makefile.in: Use EXE_SUFFIX for Cygwin, and install
+ libtk8.6.dll in bin directory.
+ * unix/configure: (regenerated)
+
+2009-12-22 Joe English <jenglish@users.sourceforge.net>
+
+ * library/ttk/sizegrip.tcl: [Bug 2912356]: Patch to avoid bizarro
+ behavior under compiz.
+
+2009-12-20 Donal K. Fellows <dkf@users.sf.net>
+
+ * unix/tkUnixSend.c (ServerSecure): [Patch 2917663]: Better support
+ for server-interpreted access control addreses.
+
+2009-12-16 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkListbox.c: Fix gcc warning: ignoring return value of
+ "strtol", declared with attribute
+ warn_unused_result.
+ * unix/tkUnixEvent.c: Fix gcc warning: dereferencing pointer
+ "xgePtr" does break strict-aliasing rules.
+ * generic/tkInt.decls: CONSTify return values of TkKeysymToString,
+ * generic/tkBind.c TkFindStateString, TkpGetString, TkpGetChar,
+ * generic/tkIntDecls.h which are all not supposed to be modified by
+ * generic/tkUtil.c the caller. In tkUtil.c this gets rid of a
+ * carbon/tkMacOSXKeyboard.c dangerous type cast.
+ * macosx/tkMacOSXKeyboard.c
+ * unix/tkUnixKey.c
+ * win/tkWinKey.c
+
+2009-12-15 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkConfig.c: Added another dimension of refCounting to the
+ * generic/tkInt.c: "option" Tcl_ObjType to improve memory troubles
+ * generic/tkObj.c: detailed in [Bug 2492179]. Also removed
+ registration of the "option" Tcl_ObjType.
+ *** POTENTIAL INCOMPATIBILITY *** for callers of
+ Tcl_GetObjType("option") which must now handle a NULL return.
+
+2009-12-15 Donal K. Fellows <dkf@users.sf.net>
+
+ * library/demos/unicodeout.tcl (usePresentationFormsFor): Split out
+ the code to decide whether to use presentation forms for clarity, and
+ add some more languages (though only in natural uncomposed form for
+ Devanagari script).
+
+2009-12-14 Kevin B. Kenny <kennykb@acm.org>
+
+ * library/demos/unicodeout.tcl: Added code to check for right-to-left
+ support on Windows and adjust Hebrew and Arabic character strings
+ accordingly. Changed the Hebrew string to 'ktb ebryt' (ktav Ivrit,
+ "Hebrew writing") to be consistent with at least the Greek and Russian
+ strings. Thanks to Rodrigo Readi for calling the inconsistency to our
+ attention.
+
+2009-12-02 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkInt.decls: [Bugs 220600, 220690]: Comment that TkWinChildProc
+ is exported through the stubs table since 8.5.9
+
+2009-12-11 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/makefile.vc: Fix dependancies on ${TKSTUBLIB} when
+ TCL_USE_STATIC_PACKAGES is defined
+ * generic/tkWindow.c: Fix gcc warning, using gcc-4.3.4 on cygwin
+ warning: array subscript has type 'char'
+
+2009-12-11 Donal K. Fellows <dkf@users.sf.net>
+
+ * library/tk.tcl (::tk::ScreenChanged): [Bug 2912473]: Stop problems
+ caused by display names with a double colon in.
+
+2009-12-10 Donal K. Fellows <dkf@users.sf.net>
+
+ * library/demos/ttkscale.tcl: Added demo of [ttk::scale] widget.
+
+2009-12-09 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkColor.c (Tk_GetColorByValue): [Bug 2911570]: Ensure that
+ hash keys of color values are zeroed first, so that they hash properly
+ on 64-bit systems (where X structures are not tightly packed).
+
+ * unix/tkUnixWm.c (TkpMakeMenuWindow): Improve the determining of what
+ * generic/tkMenu.c (ConfigureMenu): EWMH hint to use so that we
+ distinguish between dropdown menus (children of menubars) and what are
+ presumably popup menus.
+
+2009-12-08 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * unix/tkUnixWm.c: [Bug 2864685]: Apply suitable extended window
+ manager hints to the menus so that modern unix window managers can use
+ the correct animation modes.
+
+2009-12-02 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/configure: (regenerated)
+ * win/Makefile.in: Use tktest86.dll for all tests.
+ * win/tkWinInt.h: Mark various functions MODULE_SCOPE
+ * generic/tkInt.decls: [Bugs 220600, 220690]: Make TkWinChildProc
+ available in private stub table.
+ * generic/tkIntPlatDecls.h: (regenerated)
+ * generic/tkStubInit.c: (regenerated)
+
+2009-11-30 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/Makefile.in: Better dependancies in case of static build.
+ Generate tktest86.dll and tktest86.lib.
+
+2009-11-29 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkInt.h: Make all internal initialization
+ * generic/tkTest.c: routines MODULE_SCOPE
+ * generic/tkOldTest.c:
+ * generic/tkSquare.c:
+ * carbon/tkMaxOSXTest.c:
+ * macosx/tkMaxOSXTest.c:
+ * win/tkWinTest.c:
+ * win/tcl.m4: (copied from Tcl 8.6)
+ * win/configure: (regenerated)
+
+2009-11-25 Stuart Cassoff <stwo@users.sf.net>
+
+ * unix/tcl.m4: [Patch 2892871]: Remove unneeded
+ AC_STRUCT_TIMEZONE.
+ * unix/configure: Regenerated with autoconf-2.59.
+
+2009-11-24 Donal K. Fellows <dkf@users.sf.net>
+
+ * unix/tkUnixWm.c (WmIconphotoCmd): [Bug 2902814]: Use the correct
+ type for the array of data passed into X. It's wrong, but "right"
+ because of a mistake in the X11 specification.
+
+2009-11-23 Andreas Kupries <andreask@activestate.com>
+
+ * library/safetk.tcl (::safe::loadTk): [Bug 2902573]: Fixed access
+ to the cleanupHook of the safe base. The code used the old
+ internal commands which have been removed since 2009-11-05/06. See
+ Tcl's ChangeLog.
+
+2009-11-23 Donal K. Fellows <dkf@users.sf.net>
+
+ * unix/Makefile.in: Added .PHONY lines to stop make from getting
+ confused when someone makes an error in a rule.
+
+2009-11-22 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * tests/winWm.test: [Bug 2899949]: Make sure the window is still
+ * win/tkWinWm.c: present when handling delayed activation.
+
+ * win/Makefile.vc: Include tk stubs in the tktest link
+
+2009-11-21 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkUtil.c: Remove some anachronistic techniques (pointless
+ casts, mixed assignments and tests, etc.)
+
+ * generic/tk3d.c, generic/tkBitmap.c, generic/tkColor.c:
+ * generic/tkCursor.c, generic/tkFont.c, generic/tkTextIndex.c:
+ [Tcl Bug 2857044]: Corrections following audit of Tcl_ObjType freeing
+ practises; the typePtr field is now cleared when an object ceases to
+ be of the type.
+
+2009-11-19 Alexandre Ferrieux <ferrieux@users.sourceforge.net>
+
+ * generic/tkCanvas.c: [Bug 2899685]: Fix the redraw logic of [imove]
+
+2009-11-19 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * doc/GetHINSTANCE.3: Fix mentioned header file
+ * generic/tkTest.c: Compile with Stubs
+ * generic/tkOldTest.c
+ * generic/tkSquare.c
+ * win/tcl.m4: Should have been checked in together with the
+ 2009-08-09 check in of "win/configure"
+ * win/tkWinTest.c: Don't access tkWinProcs from Tk dll any more
+ * unix/tcl.m4: [Patch 2883533]: tcl.m4 support for Haiku OS
+ * unix/configure (regenerated)
+ * unix/Makefile.in: Fix library order in X11_LIB_SWITCHES
+
+2009-11-19 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkCanvLine.c (LineDeleteCoords): [Bug 2900121]: Get sense of
+ test for drawing optimization correct.
+
+2009-11-15 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/ttk_treeview.n (detach): Added note that the 'move' operation
+ restores detached nodes.
+
+2009-11-12 Joe English <jenglish@users.sourceforge.net>
+
+ * library/ttk/button.tcl, library/ttk/combobox.tcl,
+ * library/ttk/notebook.tcl, library/ttk/treeview.tcl:
+ [update] hygiene.
+
+ + Where possible, replace [a; update; b] with [a ; after 0 b].
+ + Where not possible, use [update idletasks] instead of full [update].
+ + Use [after 0] in favor of [after idle] for delayed work, to reduce
+ likelihood of reentrancy issues in [update idletasks].
+
+2009-11-11 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkPlatDecls.h: [Bug 2886635]: Restore C++
+ friendliness to the tkPlatDecls.h header file, which we insist
+ extensions #include to gain access to the Tk_*HWND*() routines.
+
+2009-11-10 Andreas Kupries <andreask@activestate.com>
+
+ * unix/Makefile.in: Partially reverted Don Porter's 2009-10-20 commit.
+ The OSX Cocoa code branch still needs tclInt.h and the internal
+ headers, thus the TCL_PLATFORM directory. See tclMacOSXNotify.c for
+ example.
+
+2009-11-09 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkFileFilter.c (TkFreeFileFilters): Simplify the code in
+ this file by consolidating the deletion code together into a single
+ function rather than scattering it over four.
+
+2009-11-01 Joe Mistachkin <joe@mistachkin.com>
+
+ * win/tkWinButton.c: [Bug 1739613]: The default width being stored
+ in TSD cannot be put into the process-wide options table. This fix
+ allocates storage for the default width from the heap and frees it
+ using an exit handler.
+
+2009-11-01 Joe Mistachkin <joe@mistachkin.com>
+
+ * doc/loadTk.n: Minor fix for htmlhelp target.
+
+2009-11-01 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkWidget.c, doc/ttk_widget.n: Uniform, extensible
+ syntax for [$w identify] methods: [$w identify $component $x $y]. All
+ ttk::* widgets support [$w identify element $x $y]; widgets with other
+ identifiable parts may have additional subcommands.
+ * generic/ttk/ttkNotebook.c, doc/ttk_notebook.n: Notebook widgets
+ support [$nb identify tab].
+ * generic/ttk/ttkPanedwindow.c, doc/ttk_panedwindow.n: Panedwindow
+ widgets support [$w identify sash]. Older 2-argument form [$w
+ identify $x $y] still supported, though it does different things
+ depending on the widget.
+
+2009-10-29 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tkWinFont.c: [Bug 1825353]: This patch reverts a previous
+ attempt to fix tiny fonts on Russian Windows. It fixes the issue by
+ requesting a suitable fixed font instead of decoding the system stock
+ font.
+
+2009-10-26 Don Porter <dgp@users.sourceforge.net>
+
+ * unix/Makefile.in: Remove $(PACKAGE).* and prototype from the
+ `make distclean` target. Completes 2009-10-20 commit.
+
+2009-10-25 Donal K. Fellows <dkf@users.sf.net>
+
+ * unix/tkUnixColor.c (TkpGetColor): [Bug 2809525]: Impose a maximum
+ X11 color name length so that it becomes impossible to blow things up
+ that way.
+
+ * library/text.tcl: [Bug 1854913]: Stop <Delete> actions from ever
+ deleting backwards, even when the insertion cursor is "at the end" of
+ the text widget.
+
+2009-10-24 Donal K. Fellows <dkf@users.sf.net>
+
+ * library/button.tcl, unix/tkUnixButton.c (TkpDisplayButton):
+ [Patch 1530276]: Make -selectcolor handling work better for both
+ checkbuttons and radiobuttons when they don't have indicators.
+
+2009-10-22 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkText.c (CreateWidget, TextEditUndo, TextEditRedo)
+ (TextEditCmd, UpdateDirtyFlag):
+ * generic/tkText.h: [Patch 1469210]: Corrected handling of marking as
+ dirty when inserting after an undo from a non-dirty state.
+
+ * win/tkWinDialog.c (GetFileNameA): Make the handling of the filter
+ index the same as in GetFileNameW.
+
+ * library/tkfbox.tcl (::tk::dialog::file::, Done):
+ * library/xmfbox.tcl (MotifFDialog_FileTypes)
+ (MotifFDialog_ActivateSEnt):
+ * macosx/tkMacOSXDialog.c (Tk_GetOpenFileObjCmd):
+ * win/tkWinDialog.c (GetFileNameW, GetFileNameA):
+ * doc/getOpenFile.n: [Patch 2168768]: Corrected handling of the
+ -typevariable option to be consistently global; it's the only way it
+ can work even close to the same on all platforms.
+
+ * macosx/ttkMacOSXTheme.c (RangeToFactor): [Bug 2883712]: Factor out
+ some common code and make sure that it is 64-bit correct.
+
+2009-10-21 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/Makefile.in: [Bug 2875562]: Make sure that winMain.c and
+ * win/winMain.c: tkAppInit.c are never compiled with stubs.
+ * unix/tkAppInit.c:
+
+2009-10-20 Don Porter <dgp@users.sourceforge.net>
+
+ * unix/Makefile.in: Compiling Tk no longer requires header files
+ * win/Makefile.in: from the TCL_PLATFORM DIR. Baby step in
+ pursuit of [Bug 1712098]. Also removed the long outdated and broken
+ targets package-* that were for building Solaris packages. Appears
+ that the pieces needed for these targets to function have never been
+ present in the current era of Tcl development and belong completely
+ to Tcl pre-history.
+
+2009-10-20 Andreas Kupries <andreask@activestate.com>
+
+ * library/msgs/pl.msg: Applied patch to Polish message catalog created
+ and submitted by Pawel Pawlak <morris@elysium.pl> (via JeffH).
+
+2009-10-18 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/menu.n: Reorganized for readability, and added a note describing
+ some subtleties of the -variable entry configuration option following
+ some discussion with Joe Mistachkin.
+
+2009-10-10 Donal K. Fellows <dkf@users.sf.net>
+
+ * unix/tkUnixRFont.c (InitFont, TkpGetFontFromAttributes)
+ (Tk_DrawChars, TkpDrawAngledChars): [Bug 1961455]: Draw underlines and
+ overstrikes when using Xft for font rendering.
+
+ * generic/tkFont.c (TkDrawAngledTextLayout): Optimize the zero-angle
+ case better.
+
+2009-10-08 Donal K. Fellows <dkf@users.sf.net>
+
+ * library/iconlist.tcl (Create): [Patch 2870648]: Corrected cursor
+ used in file/directory dialogs.
+
+2009-10-07 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * library/ttk/vistaTheme.tcl: [Bug 2787164]: Fix size of dropdown
+ arrow on combobox and menubutton for Windows 7.
+
+2009-10-07 Donal K. Fellows <dkf@users.sf.net>
+
+ * unix/tkUnixScrlbr.c (TkpComputeScrollbarGeometry): [Patch 2088597]:
+ Stop scrollbars from getting too small at the end.
+
+2009-10-05 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tkWinButton.c: [Bug 2860827]: Avoid 3D effects with
+ user-specified backgrounds. The default disabled text is embossed on
+ Windows. But this looks poor when a non-default background color is in
+ use. This patch disables the embossed effect for buttons and labels
+ when the background is non- standard.
+
+2009-09-30 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * tests/winWm.test: [Bug 2799589]: Grab on deleted window.
+
+2009-09-25 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkImgPhoto.c (ImgGetPhoto): Correct generation of grayscale
+ data from an image. Reported by Keith Vetter on comp.lang.tcl.
+
+2009-09-19 Peter Spjuth <peter.spjuth@gmail.com>
+
+ * generic/tkGrid.c: [Bug 2859912]: Bug fix in grid/pack collision
+ * generic/tkPack.c: detect. Faulty slave was not properly blocked
+ * tests/packgrid.test: from slave list.
+
+2009-09-14 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkMenuDraw.c (TkPostSubmenu): [Bug 873613]: Fix reposting of
+ * win/tkWinMenu.c (TkWinHandleMenuEvent): submenu in torn off Windows
+ menu.
+ (DrawMenuEntryArrow): [Bug 873608]: Draw Win menu arrow after being
+ torn off.
+
+2009-09-09 Donal K. Fellows <dkf@users.sf.net>
+
+ * unix/tkUnixRFont.c (InitFont): Move pattern disposal in error case
+ to callers so they have more options when they come to recovering from
+ the failure.
+ (TkpGetFontFromAttributes): If the default attributes don't work, try
+ adding a setting to turn off use of XRender. That seems to work for
+ some people for unexplained reasons (possibly local misconfiguration).
+ * generic/tkFont.c (Tk_AllocFontFromObj): Stop this function from
+ keeling over in a heap when the low-level font allocation fails. An
+ error beats a crash! (Issue reported on comp.lang.tcl by Denis
+ Berezhnoy.)
+
+2009-09-07 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tkFocus.c: Fix potential null dereference flagged by clang
+ * generic/tkMenu.c: static analyzer.
+ * generic/tkTextBTree.c:
+ * generic/tkTextDisp.c:
+ * generic/tkTextIndex.c:
+
+ * generic/tkConsole.c: Silence false positives from clang static
+ * generic/tkTest.c: analyzer about potential null dereference.
+ * generic/tkText.c:
+ * generic/tkTextBTree.c:
+ * generic/tkTextTag.c:
+ * generic/tkVisual.c:
+
+2009-09-04 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkInt.h (TkDisplay): Remove fields that are never read from.
+ * generic/tkWindow.c (Tk_DestroyWindow): Remove code to write to
+ write-only fields of TkDisplay. This follows on from [Bug 2039720].
+
+2009-08-25 Donal K. Fellows <dkf@users.sf.net>
+
+ * unix/tkUnixSend.c (ServerSecure): [Bug 1909931]: Added some support
+ for server-interpreted access control addreses.
+
+2009-08-24 Donal K. Fellows <dkf@users.sf.net>
+
+ * library/msgbox.tcl (::tk::MessageBox): Correct bindings so that they
+ work with ttk::buttons. Reported by Hans-Christoph Steiner.
+
+2009-08-24 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tkInt.h: Annotate Tcl_Panic as noreturn for clang static
+ analyzer in PURIFY builds, replacing preprocessor/assert technique.
+
+ * generic/tkBind.c (HandleEventGenerate): Don't generate events for
+ windows that don't exist yet (fixes TkAqua testsuite crash).
+
+ * macosx/tkMacOSXWindowEvent.c: [Bug 2821084]: Allow WM_DELETE_WINDOW
+ handlers to prevent window closure by generating WM destroy event
+ earlier (from window delegate's -windowShouldClose:).
+
+ * macosx/tkMacOSXDraw.c (TkMacOSX{Setup,Restore}DrawingContext):
+ Disable window flushing during Tk drawing to avoid immediate flush of
+ NSView-based native widgets on draw. (fixes drawing performance issue
+ reported by Youness Alaoui on tcl-mac)
+
+ * macosx/tkMacOSXHLEvents.c (ScriptHandler): Fix "do script" apple
+ * carbon/tkMacOSXHLEvents.c (ScriptHandler): event handler issues
+ on recent OS X releases by using AE coercion to 'utf8' for text data
+ and to 'fsrf' for alias data. (reported by Youness Alaoui on tcl-mac)
+
+ * macosx/Wish.sdef (new file): Install and enable sdef file
+ * macosx/Wish-Info.plist.in: into Wish application bundle,
+ * macosx/Tk.xcode/project.pbxproj: describing TkAqua apple event
+ * macosx/Tk.xcodeproj/project.pbxproj: support for use by AppleScript.
+ * unix/Makefile.in: (replaces functionality of
+ * unix/configure.in: 'aete' resource removed with
+ Cocoa port & fixes AppleScript
+ issues reported on tcl-mac)
+ * unix/configure: autoconf-2.59
+
+ * carbon/Wish.xcode/project.pbxproj: Remove references to obsolete
+ * carbon/Wish.xcodeproj/project.pbxproj: prolog.ps file.
+
+2009-08-19 Peter Spjuth <peter.spjuth@gmail.com>
+
+ * generic/tk.h
+ * generic/tkGeometry.c
+ * generic/tkGrid.c
+ * generic/tkInt.h
+ * generic/tkPack.c
+ * generic/tkWindow.c
+ * tests/grid.test
+ * tests/packgrid.test
+ * tests/textIndex.test: [Patch 2475855]: Give an error if grid and
+ pack are used in the same master.
+
+2009-08-14 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXDraw.c: Avoid exception in XCopyArea() when copying
+ from toplevel that has never been mapped. (Reported by Youness Alaoui
+ on tcl-mac)
+
+ * macosx/tkMacOSXWm.c: Workaround for textured windows being draggable
+ from opaque content areas. [Bug 2824538] (walzer)
+
+2009-08-10 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkWinPixmap.c: Eliminate more gcc warnings
+ * win/tkWinWm.c:
+ * win/tkWinTest.c
+
+2009-08-09 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/ttk/ttkInit.c: Eliminate gcc warning
+ * generic/tkBind.c
+ * generic/tkText.c
+ * generic/tkUtil.c
+ * win/ttkWinXPTheme.c: Include <vssym32.h> only when available
+ * win/configure.in: check for vssym32.h, available in newer SDK's
+ * win/configure: (regenerated)
+
+2009-08-08 Donal K. Fellows <dkf@users.sf.net>
+
+ * library/demos/pendulum.tcl: Make the display handle being resized
+ more gracefully.
+
+2009-08-04 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkTextDisp.c (TkTextCharLayoutProc): Make the line breaking
+ algorithm (in the word-wrap case) do the right thing with non-breaking
+ spaces by restricting what we break on to ASCII spaces, which is good
+ enough for most purposes.
+
+2009-08-02 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkWinClipboard.c Correct check for winNT
+ * win/tkWinDialog.c Eliminate many gcc warnings
+ * win/tkWinImage.c:
+ * win/tkWinMenu.c:
+ * win/tkWinWm.c:
+ * win/tkWinX.c:
+ * win/ttkWinXPTheme.c: Eliminate msvc warnings
+ * win/tcl.m4:
+ * win/configure
+ * win/.cvsignore: Prevent files from being checked in by accident
+
+2009-08-01 Donal K. Fellows <dkf@users.sf.net>
+
+ * unix/tkUnixWm.c (WmIconphotoCmd): [Bug 2830420]: Assemble the image
+ for the window manager in a way that doesn't assume we're on a little-
+ endian system.
+
+2009-07-27 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/GetScroll.3: Reworded and reordered so as to indicate that the
+ Tcl_Obj forms are preferred.
+
+2009-07-26 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/canvas.n: Corrected description of acceptable join styles.
+ Spotted by Emiliano Gavilán.
+
+2009-07-23 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkSelect.c (HandleTclCommand): [Bug 2441988]: Stop losing
+ reports of errors in selection handlers; that's what the background
+ error handling code is for.
+ *** POTENTIAL INCOMPATIBILITY *** if your code was relying on erroring
+ selection scripts being silent.
+ (LostSelection, Tk_SelectionObjCmd): Stop using the vastly inefficient
+ TkCopyAndGlobalEval; better to use Tcl_Obj refcount management.
+
+2009-07-22 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkFocus.c (TkFocusDeadWindow): [Bug 2496114]: Ensure that
+ focus desynchronization doesn't cause a crash.
+
+2009-07-21 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkFont.c (TkUnderlineAngledTextLayout): [Bug 2356057]:
+ Corrected drawing of rotated underlines.
+
+2009-07-21 Alexandre Ferrieux <ferrieux@users.sourceforge.net>
+
+ * generic/tkFont.c: [Bug 2328657]: Explicitly exclude hacky zero-char
+ chunks from intersection computation. Might deserve generalization to
+ other tests.
+
+2009-07-20 Donal K. Fellows <dkf@users.sf.net>
+
+ * tests/clipboard.test (clipboard-6.2): [Bug 2824378]: Corrected
+ result of test in light of changes to binary selection retrieval.
+
+2009-07-18 Donal K. Fellows <dkf@users.sf.net>
+
+ * unix/tkUnixSelect.c (SelCvtFromX32, SelCvtFromX8): Make the
+ incremental transfer of binary selections work get deserialized
+ correctly. Thanks to Emiliano Gavilán for detecting.
+
+2009-07-18 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/Makefile.in: Define NDEBUG in optimized (non-
+ symbols) build to disable assert()s.
+
+ * macosx/tkMacOSXBitmap.c: [Bug 2821318]: Fix tk::mac::iconBitmap
+ crash due to off-by-one ckalloc error.
+
+2009-07-15 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/ttkMacOSXTheme.c: [Patch 2819620]: Update notebook tab
+ * library/ttk/aquaTheme.tcl: appearance to modern L&F; adjust tab &
+ notebook padding and tabmargins;
+ correct appearance of selected tree
+ header; add support for native tree
+ header sort arrows via user1 state.
+
+ * library/demos/mclist.tcl: Use native sort arrows with aqua theme
+
+2009-07-15 Donal K. Fellows <dkf@users.sf.net>
+
+ * unix/tkUnixSelect.c (TkSelEventProc, SelRcvIncrProc, SelCvtFromX8):
+ [Bug 2821962]: Make byte sequence selection transfers possible.
+
+2009-07-14 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/canvas.n (WINDOW ITEMS): [Bug 2326602]: Corrected definition of
+ the -height and -width options for these items.
+
+ * unix/configure.in: [Bug 2496018]: Allow the disabling of the use of
+ XScreenSaver at configuration time, so as to permit better control of
+ dependencies in the embedded case.
+
+2009-07-11 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/grid.n: [Bug 2818455]: Corrected example.
+
+2009-07-02 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * generic/tkInt.h: Avoid using C++ reserved word in header.
+
+2009-06-30 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tkInt.h: Add assert macros for clang static
+ analyzer and redefine Tcl_Panic to
+ assert after panic in clang PURIFY
+ builds.
+
+ * generic/tkImgPhInstance.c: Small fixes to make clang static
+ * generic/tkTextDisp.c: analyzer happier.
+
+ * generic/tkConfig.c: Add clang assert for false positives
+ * generic/tkUndo.c: from static analyzer.
+
+2009-06-29 Daniel Steffen <das@users.sourceforge.net>
+
+ Merge of TkAqua Cocoa port <http://github.com/das/tcltk/tree/de-carbon>
+ *** POTENTIAL INCOMPATIBILITY ***
+
+ * macosx/tkMacOSX.h: Large-scale rewrite of TkAqua migrating
+ * macosx/tkMacOSXBitmap.c: all use of deprecated Carbon API to
+ * macosx/tkMacOSXButton.c: Cocoa API; now supports 64bit
+ * macosx/tkMacOSXClipboard.c: architecture and requires Mac OS X 10.5
+ * macosx/tkMacOSXColor.c: or later; with TkAqua enabled, all Tk
+ * macosx/tkMacOSXConfig.c: sources are now built with the
+ * macosx/tkMacOSXCursor.c: Objective-C compiler and running in
+ * macosx/tkMacOSXDebug.c: Objective-C garbage collection mode as
+ * macosx/tkMacOSXDebug.h: well as in retain-release mode is
+ * macosx/tkMacOSXDefault.h: supported; detailed development history
+ * macosx/tkMacOSXDialog.c: is available in github repository.
+ * macosx/tkMacOSXDraw.c:
+ * macosx/tkMacOSXEmbed.c: There should be no script-visible
+ * macosx/tkMacOSXEntry.c: changes to existing Tk functionality,
+ * macosx/tkMacOSXEvent.c: but there are a few aqua-specific
+ * macosx/tkMacOSXEvent.h: additions, see macosx/README for
+ * macosx/tkMacOSXFont.c: details; extensions using only public
+ * macosx/tkMacOSXFont.h: Tk API should continue to work
+ * macosx/tkMacOSXHLEvents.c: unchanged but extensions that rely on
+ * macosx/tkMacOSXInit.c: platform-specific internal Tk API or
+ * macosx/tkMacOSXInt.h: make assumptions about the inner
+ * macosx/tkMacOSXKeyEvent.c: workings of TkAqua (in particular
+ * macosx/tkMacOSXKeyboard.c: presence of QuickDraw) will require
+ * macosx/tkMacOSXMenu.c: porting.
+ * macosx/tkMacOSXMenubutton.c:
+ * macosx/tkMacOSXMenus.c: Configure Tk with --enable-aqua=carbon
+ * macosx/tkMacOSXMouseEvent.c: to fallback to now-deprecated previous
+ * macosx/tkMacOSXNotify.c: TkAqua implementation in tk/carbon.
+ * macosx/tkMacOSXPort.h:
+ * macosx/tkMacOSXPrivate.h:
+ * macosx/tkMacOSXRegion.c:
+ * macosx/tkMacOSXScale.c:
+ * macosx/tkMacOSXScrlbr.c:
+ * macosx/tkMacOSXSend.c:
+ * macosx/tkMacOSXSubwindows.c:
+ * macosx/tkMacOSXTest.c:
+ * macosx/tkMacOSXWindowEvent.c:
+ * macosx/tkMacOSXWm.c:
+ * macosx/tkMacOSXWm.h:
+ * macosx/tkMacOSXXStubs.c:
+ * macosx/ttkMacOSXTheme.c:
+ * macosx/tkMacOSXCarbonEvents.c (removed):
+
+ * macosx/tkMacOSXCursors.h (new): Move cursor data from resources
+ * macosx/tkMacOSXXCursors.h (new): to compiled-in const array;
+ * macosx/tkMacOSXCursors.r (removed): remove obsolete Rez source
+ * macosx/tkMacOSXXCursors.r (removed): files for resource data.
+ * macosx/tkAboutDlg.r (removed):
+ * macosx/tkMacOSXAETE.r (removed):
+
+ * macosx/Tk.tiff (new): Rename and update icon to blue feather;
+ * macosx/Tk.icns (new): add tiff version for about dialog.
+ * macosx/Wish.icns (removed):
+
+ * macosx/Tk-Info.plist.in: Update copyright; adjust minimum system
+ * macosx/Wish-Info.plist.in: version requirement.
+ * generic/tkEntry.h:
+
+ * license.terms: Sync list of entities with those in the
+ tcl license.terms, add Apple Inc.
+
+ * generic/tk.h: Update comment with list of source
+ files containing tk version numbers.
+
+ * generic/tkButton.c: On aqua, recompute button geometry on
+ secondary image change to enable cache
+ of native img format in geom compute.
+
+ * generic/tkGrab.c: On aqua, make all grabs global, the
+ Mac OS X windowserver forces all grabs
+ to be application-local only anyway.
+
+ * generic/tkSelect.c: Enable utf8 atom on aqua.
+
+ * generic/tk.decls: Replace carbon types in public and
+ * generic/tkInt.decls: internal platform stubs interfaces with
+ void* resp. generic Tk types.
+
+ * xlib/xgc.c: Add support for managing a platform-
+ specific cache appended to a GC.
+
+ * tests/dialog.test: Change name of undefined bit to avoid
+ match with OSType native bitmap name.
+
+ * doc/cursors.n: Update list of cursors mapped to native
+ cursors and add new native cursors.
+
+ * doc/menu.n: Add documentation of new aqua-specific
+ .window menu, document new constraints
+ on .apple menu.
+
+ * library/console.tcl: Add aqua window and help menus.
+
+ * unix/Makefile.in: Add support for TkAqua-implementation-
+ specific sources determined at
+ configure-time. Update dist target for
+ new/removed files.
+
+ * unix/configure.in: Add libraries & compiler flags for
+ Cocoa and Objective-C; update build
+ support for new/removed files; add
+ support for configure-time choice of
+ TkAqua implementation.
+
+ * macosx/Tk-Common.xcconfig (new): Rename Xcode projects and
+ * macosx/Tk-Debug.xcconfig (new): related files; update for Xcode
+ * macosx/Tk-Release.xcconfig (new): 3.1 and 3.2; update for Cocoa,
+ * macosx/Tk.xcode/* (new): Objective-C & GC; update with
+ * macosx/Tk.xcodeproj/* (new): new/removed source files;
+ * macosx/Wish.xcode/* (removed): standardize on gcc 4.2; remove
+ * macosx/Wish.xcodeproj/* (removed): obsolete configurations and
+ * macosx/Wish-Debug.xcconfig (removed): pre-Xcode project.
+ * macosx/Wish-Common.xcconfig (removed):
+ * macosx/Wish-Release.xcconfig (removed):
+ * macosx/Wish.pbproj/* (removed):
+
+ * macosx/README: Document new Cocoa-port features and
+ constraints; update project docs;
+ cleanup.
+
+ * carbon/tkMacOSXInt.h: Add dummy defines for empty GC cache.
+
+ * carbon/tkMacOSXColor.c: Update for type changes in platform
+ * carbon/tkMacOSXDraw.c: stubs interfaces.
+ * carbon/tkMacOSXHLEvents.c:
+ * carbon/tkMacOSXMouseEvent.c:
+ * carbon/tkMacOSXSubwindows.c:
+ * carbon/tkMacOSXWm.c:
+
+ * carbon/tkMacOSXButton.c: Fix warning.
+
+ * generic/tkPlatDecls.h: regen.
+ * generic/tkIntPlatDecls.h:
+ * unix/configure: autoconf-2.59
+
+2009-06-27 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkInt.decls (added TkSmooth(Parse|Print)Proc,
+ removed TkTile(Parse|Print)Proc which don't exist):
+ Follow-up to [Bug 2804935]: Expose these functions through the
+ internal stub table as they are useful to existing third-party code.
+
+2009-06-26 Daniel Steffen <das@users.sourceforge.net>
+
+ * carbon/ (new directory): Copy of current state of 'macosx'
+ source directory, to preserve legacy TkAqua implementation based on
+ Carbon API (with support for Mac OS X releases older than 10.5).
+
+ * unix/Makefile.in: Add support for --enable-aqua=carbon
+ * unix/configure.in: configure option (legacy fallback for
+ pre-Mac OS X 10.5 releases).
+
+ * unix/configure: autoconf-2.59
+
+2009-06-22 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkCanvUtil.c: [Bug 220935]: canvas dash update problem
+
+2009-06-12 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkInt.decls (TkOrientParseProc, TkOrientPrintProc):
+ [Bug 2804935]: Expose these functions through the internal stub table
+ as they are useful to existing third-party code.
+
+2009-06-02 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tkWinWm.c: [Bug 2799589]: Avoid setting the focus on a
+ * tests/winWm.test: deleted window during delayed activation.
+
+2009-05-21 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tkWinMenu.c: [Bug 2794778]: Calls to CallWindowProc can lead to
+ other functions overwriting the event strucure. Therefore preserve a
+ local copy of the XKeyEvent while looping over the key events.
+
+2009-05-17 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttkNotebook.c: [Bug 1470246]: More flexible tab placement.
+
+2009-05-14 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * generic/tkButton.c: [Bug 1923684]: If a checkbutton offvalue is the
+ same as the tristate value we should use the off state in
+ preference. (andrey gusev)
+
+2009-05-13 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tkWinSend.c: FormatMessage should always use the ignore-inserts
+ * win/tkWinTest.c: flag when processing system errors.
+
+ * generic/tkFont.c: [Bug 2791352]: Handle parsing of type 5 font
+ * tests/font.test: descriptions with hyphenated family name.
+
+2009-05-06 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * library/images/lamp.svg: Added an SVG version of the Tk lamp and
+ * library/images/lamp.png: a pre-rendered PNG version.
+ * win/rc/wish.ico: Wish gets a new icon using the SVG lamp and the tk
+ * win/rc/tk.ico: dll gets the tcl rendered feather. This provides
+ improved icons for Vista/Windows 7.
+
+2009-05-05 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/MainWin.3 (Tk_GetNumMainWindows): [Bug 487220]: Clarified that
+ this function works per-thread, not per-process.
+
+ * doc/canvas.n (scale): [Bug 1832015]: Clarified that [$c scale] only
+ affects item coordinates.
+
+2009-05-04 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/3DBorder.3, doc/BindTable.3, doc/CanvPsY.3, doc/Clipboard.3:
+ * doc/ConfigWidg.3, doc/CrtWindow.3, doc/GetBitmap.3:
+ * doc/GetCapStyl.3, doc/GetImage.3, doc/GetJoinStl.3, doc/GetScroll.3:
+ * doc/GetSelect.3, doc/GetVisual.3, doc/MainWin.3, doc/Name.3:
+ * doc/ParseArgv.3, doc/TextLayout.3, doc/Tk_Init.3: [Bug 2431507]:
+ Purge all mention of the now-obsolete 'interp->result'.
+
+2009-05-03 Donal K. Fellows <dkf@users.sf.net>
+
+ * win/tkWinWm.c (UpdateWrapper): [Bug 2785744]: Manipulate flag bit
+ correctly so that menubar updates can't smash other attributes.
+
+2009-05-01 Donal K. Fellows <dkf@users.sf.net>
+
+ * library/mkpsenc.tcl (DrawText): [Bug 2777019]: Corrected point of
+ application of rotation transform so rotation is about the anchor
+ point of the text.
+
+ * generic/tkCanvPs.c (Tk_PostscriptPhoto):
+ * library/mkpsenc.tcl: Factor out the postscript code for converting
+ images into postscript so that the code bits are in the prolog and not
+ emitted at runtime if a non-thread-safe static says to...
+
+2009-04-30 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tkWinWm.c: [Patch 2504402]: Create icon bitmaps as device
+ independent bitmaps. This ensures the icon can be drawn properly on
+ various colour depth surfaces - in particular it fixes a problem with
+ remote desktop and looks better in the vista task switching overlay.
+ (cjmcdonald)
+
+2009-04-30 Donal K. Fellows <dkf@users.sf.net>
+
+ * win/tkWinPixmap.c (Tk_GetPixmap): [Bug 2080533]: Added patch that
+ allows Tk to keep working even when the graphics card is stressed.
+
+2009-04-28 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/tcl.m4, unix/configure (SC_CONFIG_CFLAGS): Harden the check
+ to add _r to CC on AIX with threads.
+
+2009-04-27 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkInt.decls: [Bug 2768945]: Expose (as "private") a set of
+ functions needed for easily building canvas items that work like
+ existing standard ones.
+
+2009-04-24 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinDialog.c (ChooseDirectoryValidateProc): No need to set cwd
+ on selchange. Prevents delete of selected folder in dialog.
+
+2009-04-24 Stuart Cassoff <stwo@users.sf.net>
+
+ * unix/Makefile.in: Assorted issues:
+ [Bug 2764263]: Removed stray @ from Makefile.in test target.
+ [Bug 1945073]: Don't chmod+x square demo.
+ [Patch 2764272]: Adjustable demo install location.
+
+2009-04-24 Stuart Cassoff <stwo@users.sf.net>
+
+ * unix/Makefile.in: [Patch 2769530]: Don't chmod/exec installManPage.
+
+2009-04-23 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinDialog.c (Tk_ChooseDirectoryObjCmd): [Bug 2779910]: Enable
+ the new style choosedir that has a "New Folder" button, with
+ ::tk::winChooseDirFlags override for new behavior.
+
+2009-04-14 Donal K. Fellows <dkf@users.sf.net>
+
+ * library/xmfbox.tcl (MotifFDialog_ActivateSEnt): Ensure that the
+ * library/tkfbox.tcl (Done): dialogs have the
+ correct levels for [upvar] for accessing the -typevariable var.
+
+2009-04-13 Donal K. Fellows <dkf@users.sf.net>
+
+ * library/tk.tcl: Corrected another problem; can't determine the exact
+ type of OS - needed for figuring out how to guess the correct binding
+ in some circumstances - in a safe interpreter.
+
+ * library/tkfbox.tcl: [Bug 2759119]: Corrected level handling for the
+ * library/xmfbox.tcl: -typevariable option following updates to tk.tcl
+ [Patch 2739360]: Use more modern images from Tango set for the non-
+ Motif file dialog. Thanks to Emiliano for bring this to my attention.
+
+2008-04-10 Joe English <jenglish@users.sourceforge.net
+
+ * library/palette.tcl (tk_setPalette): Don't set *selectColor:
+ #b03060; this makes radio- and checkbuttons look wrong post-TIP#109.
+
+2009-04-10 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/configure.in (Darwin): Use Darwin SUSv3 extensions if
+ available.
+ * unix/configure: autoconf-2.59
+ * unix/tkConfig.h.in: autoheader-2.59
+
+ * library/demos/filebox.tcl: Only show "Motif Style Dialog"
+ checkbutton on X11 windowingsystem.
+
+ * library/demos/widget: GOOBE: use ttk::cursor
+
+ * library/demos/knightstour.tcl: Fix knightstour demo not running from
+ interactive wish.
+
+ * library/console.tcl (::tk::ConsoleInit): Remove redundant TkAqua
+ Quit menu item.
+
+ * generic/tkPointer.c (Tk_UpdatePointer): Use all 5 buttons.
+
+ * generic/tkMenu.c (PostProcessEntry): Delay call to
+ TkpConfigureMenuEntry() until all menu entry attributes are setup.
+
+ * library/menu.tcl (::tk::MbPost): Fix error thrown in y position
+ computation with indicatoron.
+
+ * generic/tkMenubutton.c: s/DEF_BUTTON_JUSTIFY/DEF_MENUBUTTON_JUSTIFY/
+
+ * generic/tkUtil.c (TkBackgroundEvalObjv): Use Tcl_BackgroundException
+
+ * generic/tkTextBTree.c (TkBTreeDeleteIndexRange): Add bounds check
+ to startEnd array access (fixes testsuite crash).
+
+ * tests/unixFont.test: Only use xlsfonts with X11 windowingsystem.
+
+2009-04-10 Donal K. Fellows <dkf@users.sf.net>
+
+ * library/tk.tcl: [Bug 2116837]: Add event definitions to handle the
+ standard virtual events when Caps Lock is on.
+
+2009-04-08 Donal K. Fellows <dkf@users.sf.net>
+
+ * library/demos/widget (addFormattedText): Stop marking demonstrations
+ as new for 8.6; that label is for wholly new demos.
+
+2009-04-04 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/messageBox.n: [Bug 1881896]: Reworded to be clearer on what the
+ platform restrictions really are.
+
+2009-04-03 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/tkUnixWm.c: [Bug 1789819]: Don't panic when the window manager
+ does something unexpected with the stacking order.
+
+2009-04-03 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/TextLayout.3: [Bug 974421]: Clarified description of how result
+ of lookup of a point after end of layout relates to the underlying
+ string's length.
+
+2009-04-02 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * tests/textTag.test: Ensure the pointer begins outside the window for
+ all the tests checking Enter/Leave motion events.
+
+ * library/demos/pendulum.tcl: Use unicode labels
+ * library/demos/knightstour.tcl: Use polygon knight on x11.
+
+2009-03-31 Donal K. Fellows <dkf@users.sf.net>
+
+ * library/demos/mclist.tcl: Added support for arrow indicators to show
+ which way a column is being sorted. Corrected determination of which
+ fonts to use for measurements.
+
+2009-03-25 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * doc/wish.1: Bring doc and demos in line with
+ * library/demos/hello: http://wiki.tcl.tk/812
+ * library/demos/rmt
+ * library/demos/square
+ * library/demos/tcolor
+ * library/demos/timer
+ * library/demos/widget
+ * win/tkWinMenu.c: Eliminate a few compiler warnings on mingw
+ * win/ttkWinXPTheme.c: Spacing
+
+2009-03-25 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/ttk/ttkTheme.c (BuildOptionMap, NewElementClass):
+ [Bug 2178820]: Ensure that zero-size allocations don't happen; some
+ malloc implementations don't like it at all.
+
+ * win/wish.exe.manifest.in: [Bug 1871101]: Add magic to make Tk not be
+ blurred on Vista with large fonts.
+
+2009-03-14 Donal K. Fellows <dkf@users.sf.net>
+
+ * unix/tk.pc.in (new file): [Patch 2243962] (hat0)
+ * unix/configure.in, unix/Makefile.in: Added support for reporting
+ Tk's public build configuration via the pkg-config system. TEA is
+ still the official mechanism though, in part because pkg-config is not
+ universally supported across all Tk's supported platforms.
+
+2009-03-10 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/event.n: Tidy up and improve examples.
+
+2009-03-09 Benjamin Riefenstahl <b.riefenstahl@turtle-trading.net>
+
+ * tkMacOSXFont.c (GetFontFamilyName): [Bug 2548661]: Handle NULL
+ return from CFStringCreate.
+
+2009-02-27 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * doc/GetBitmap.3: [FRQ 2636558]: Tk_DefineBitmap and
+ * generic/tk.decls: Tk_GetBitmapFromData signature problem
+ * generic/tkInt.decls:
+ * generic/tkBitmap.c:
+ * generic/tkInt.h:
+ * generic/tkStubInit.c:
+ * generic/tkDecls.h: (regenerated)
+ * generic/tkIntDecls.h: (regenerated)
+ * macosx/tkMacOSXBitmap.c:
+
+2009-02-27 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * generic/tkWindow.c: [Bug 2645457]: Check for dead windows after
+ calling Tk_MakeWindowExist to avoid a crash when mapping dead windows.
+
+2009-02-23 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/rc/*.cur: [Patch 2513104]: Fix cursor hotspots (cjmcdonald)
+
+ * win/tkWinMenu.c: Applied patch for menu image display bug.
+ [Bug 1329198, 456299] [Patch 2507419] (cjmcdonald)
+
+2009-02-22 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tkWinCursor.c: Applied patch to support stock Win32 help arrow
+ cursor when question_arrow requested [Patch 2542828] (danckaert)
+
+2009-02-21 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * library/ttk/vistaTheme.tcl: Correct the ttk::treeview border on
+ * win/ttkWinXpTheme.c: XP and vista.
+
+ * library/console.tcl: [Bug 2546087]: In 2004 a fix to Tcl channels
+ prevented the exposure of the internal UTF-8 representation of the
+ ASCII NUL character (\uc080). Since then strings in the console have
+ been truncated at NUL. This restores the older behaviour.
+
+2009-02-17 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tcl.m4, win/configure: Check if cl groks _WIN64 already to avoid
+ CC manipulation that can screw up later configure checks. Use 'd'ebug
+ runtime in 64-bit builds.
+
+2009-02-16 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/configure.in, win/configure: Align better with tcl version.
+ Ensures finding correct CPP for Win64.
+
+2009-02-16 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/ttk_intro.n: [Bug 2604420]: Improve wording so that this page
+ feels less obviously incomplete.
+
+2009-02-12 Donal K. Fellows <dkf@users.sf.net>
+
+ * library/iconlist.tcl: Split out the IconList megawidget from
+ tkfbox.tcl into its own file so as to make it easier to maintain. Also
+ cleans up the API for the megawidget, making it more like a
+ conventional Tk widget.
+
+2009-02-11 Donal K. Fellows <dkf@users.sf.net>
+
+ * library/demos/items.tcl, .../label.tcl, .../twind.tcl:
+ * library/demos/images/ouster.png: [Bug 2588919]: Demo GOOBE. Added
+ new image of John Ousterhout that does not look quite so massively out
+ of date, and also showed off a bit of how we can adjust PNG images
+ when loading them. Also labeled JO as the creator; it's the TCT who
+ are the proprietors now.
+
+2009-02-10 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * unix/tcl.m4: [Bug 2502365]: Building of head on HPUX was broken when
+ using the native CC.
+ * unix/configure (autoconf-2.59)
+
+2009-02-08 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/*.[ch]: Renamed several internal data structures and
+ functions: ElementImpl -> ElementClass, LayoutNode -> Element. Remove
+ more unnecessary casts. Add function Ttk_ClientRegion, common factor
+ of entry, scale, progress, and treeview widgets.
+ * generic/ttk/ttkTrack.c: Fix [Bug 2431428].
+
+2009-02-06 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tkImgPhInstance.c: Fix numerous leaks discovered with the
+ * generic/tkMenu.c: Mac OS X Instruments.app Leaks tool.
+ * generic/tkText.c:
+ * generic/tkTextImage.c:
+ * generic/tkTextIndex.c:
+ * generic/tkUndo.c:
+ * generic/tkUtil.c:
+ * generic/ttk/ttkFrame.c:
+ * macosx/tkMacOSXWm.c:
+
+2009-01-29 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkCanvArc.c - eliminate some unnessary type casts
+ * generic/tkCanvBmap.c - some internal const decorations
+ * generic/tkCanvImg.c - spacing
+ * generic/tkCanvWind.c
+ * generic/tkCmds.c
+ * generic/tkConfig.c
+ * generic/tkEntry.c
+ * generic/tkFocus.c
+ * generic/tkFont.c
+ * generic/tkFrame.c
+ * generic/tkGrab.c
+ * generic/tkGrid.c
+ * generic/tkImage.c
+ * generic/tkListbox.c
+ * generic/tkObj.c
+ * generic/tkOption.c
+ * generic/tkPack.c
+ * generic/tkPanedWindow.c
+ * generic/tkRectOval.c
+ * generic/tkSelect.c
+ * generic/tkText.c
+ * generic/tkTextMark.c
+ * generic/tkTextTag.c
+
+2009-01-28 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/ttk/ttkCache.c: - eliminate some unnessary type casts
+ * generic/ttk/ttkLayout.c - some internal const decorations
+ * generic/ttk/ttkState.c - spacing
+ * generic/ttk/ttkTheme.c
+ * macosx/tkMacOSXMenu.c
+ * macosx/tkMacOSXPrivate.h
+ * unix/tkUnixFont.c
+ * unix/tkUnixMenu.c
+ * unix/tkUnixWm.c
+ * win/tkWinColor.c
+ * win/tkWinDialog.c
+ * win/tkWinFont.c
+ * win/tkWinMenu.c
+ * win/tkWinSend.c
+ * win/tkWinWindow.c
+ * win/tkWinWM.c
+
+2009-01-22 Kevin B. Kenny <kennykb@acm.org>
+
+ * unix/tcl.m4: Corrected a typo ($(SHLIB_VERSION) should be
+ ${SHLIB_VERSION}).
+ * unix/configure: Autoconf 2.59
+
+2009-01-19 Kevin B. Kenny <kennykb@acm.org>
+
+ * unix/Makefile.in: Added a CONFIG_INSTALL_DIR parameter so that
+ * unix/tcl.m4: distributors can control where tclConfig.sh goes.
+ Made the installation of 'ldAix' conditional upon actually being on an
+ AIX system. Allowed for downstream packagers to customize
+ SHLIB_VERSION on BSD-derived systems.
+ Thanks to Stuart Cassoff for [Patch 907924].
+ * unix/configure: Autoconf 2.59
+
+2009-01-16 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tk.h: Bump patchlevel to 8.6b1.1 to distinguish
+ * library/tk.tcl: CVS snapshots from the 8.6b1 and 8.6b2
+ * unix/configure.in: releases.
+ * win/configure.in:
+
+ * unix/configure: autoconf-2.59
+ * win/configure:
+
+2009-01-14 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkImgPhoto.c: [Bug 2507326]: Fix for aMSN compatibility
+ * generic/tkMenu.h: CONSTify Tk(Create|Find)MenuReferences
+ * generic/tkMenu.c: various internal "const" decorations.
+
+2009-01-13 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * unix/tcl.m4: [Bug 2502365]: Building of head on HPUX was broken when
+ using the native CC
+ * unix/configure (autoconf-2.59)
+
+2009-01-13 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * tests/constraints.tcl: Made the tests more independent of the
+ * tests/*.test: presence of images in the interpreter.
+
+2009-01-11 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * tests/bind.test: Fixed keysym bind tests for unix [Bug 2336454]
+
+2009-01-11 George Peter Staplin <georgeps@users.sourceforge.net>
+
+ * generic/tkEvent.c: Fix a possible segv due to a NULL pointer
+ dereference that occurs when XCreateIC fails.
+
+2009-01-11 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * library/bgerror.tcl: Pretty up the unix tk_messageBox icons with PNG
+ * library/icons.tcl: images and grouped all the stock icons in one
+ * library/msgbox.tcl: file.
+ * library/tk.tcl:
+
+2009-01-11 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkNotebook.c (NotebookCleanup): [Bug 2496162]: Don't
+ call Tk_DeleteOptionTable(), it's unnecessary and quite possibly
+ harmful.
+
+2009-01-08 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tk3d.c: CONSTify TkDebugBorder
+ * generic/tkBind.c: CONSTify TkStringToKeysym
+ * generic/tkBitmap.c: CONSTify TkDebugBitmap
+ * generic/tkColor.c: CONSTify TkDebugColor
+ * generic/tkCursor.c: CONSTify TkDebugCursor
+ * generic/tkFont.c: CONSTify TkDebugFont
+ * generic/tkInt.decls All those mods TIP #27 complient,
+ no incompatibility risks.
+ * generic/tkIntDecls.h (regenerated)
+
+2009-01-08 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * library/bgerror.tcl: Theme the bgerror dialog and make use of our
+ PNG support to improve the icon.
+
+2009-01-07 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * library/tkfbox.tcl: [Bug 2473120]: Mis-ordered messagebox args.
+
+ * win/tkWinWm.c: [Bug 1847002]: Prevent grabs being bypassed on
+ Windows.
+
+2009-01-06 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tk.h: A few const -> CONST86 modifications,
+ * generic/tkCanvas.c: improving backwards compatibility. Change
+ * generic/tkCanvLine.c: Tk_ItemIndexProc and Tk_ItemInsertProc
+ * generic/tkCanvPoly.c: signature to have a Tcl_Obj parameter instead
+ * generic/tkCanvText.c: of a string parameter. This is binary and
+ * doc/CrtItemType.3: source compatible with previous API, it just
+ * doc/Clipboard.3: prevents the need for a type cast in the
+ * doc/ConfigWidg.3: Tk_ItemType table construction. Bring doc in
+ * doc/ParseArgv.3: line with API.
+
+2009-01-06 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkImgPhoto.c (Tk_PhotoPutBlock): Optimize a common case for
+ photo image building. [Patch 1539990] (jepler)
+
+2009-01-06 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tkWinDialog.c: Use task modal for messagebox instead of system
+ modal. [Bug 2484771] (ferrieux,thoyts,mjanssen)
+
+2009-01-03 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/canvas.n: [Bug 1836621]: Improve the documentation of the
+ -offset and -outlineoffset item options.
+
+2009-01-03 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tk.decls: CONSTify Tk_ClipboardAppend
+ * generic/tkClipboard.c:
+ * generic/tkDecls.h: (regenerated)
+
+2008-12-31 David Gravereaux <davygrvy@pobox.com>
+
+ * win/rules.vc: Small bug not setting SYMBOLS macro fixed.
+
+2008-12-31 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkDefaultTheme.c: Fix color palette for radiobutton and
+ checkbutton indicators. Fixes [Bug 2003310]; also makes "alt" theme
+ check/radiobuttons look like Windows 98, as intended.
+ * library/ttk/altTheme.tcl: Specify dark gray -bordercolor to soften
+ edges.
+ * tests/ttk/{checkbutton,radiobutton}.test: Split out of ttk.test.
+
+2008-12-28 Donal K. Fellows <dkf@users.sf.net>
+
+ TIP #171 IMPLEMENTATION
+
+ * library/listbox.tcl, library/scrlbar.tcl, library/text.tcl: Adjust
+ users of the <MouseWheel> event to do the right thing horizontally as
+ well as vertically.
+ * win/tkWinX.c (GenerateXEvent): Redirect <MouseWheel> to the window
+ that contains the mouse.
+ * generic/tkEvent.c (InvokeFocusHandlers): Do not direct <MouseWheel>
+ through the focus mechanism.
+ *** POTENTIAL INCOMPATIBILITY *** for anyone counting on shift-wheel
+ to do something else (or nothing at all) or for the wheel events to be
+ following the keyboard on Win.
+
+ * generic/tkImgPNG.c (ReadIDAT): Corrected code to transfer blocks of
+ compressed data into the Tcl_ZlibStream. Allows the reading of all
+ images from PngSuite set. Thanks to Michael Kirkham for fix/testing.
+
+ TIP #244 IMPLEMENTATION
+
+ * generic/tkImgPNG.c, tests/imgPNG.test, doc/photo.n: Adaptation of
+ tkpng to the Tk core, proving support for PNG image reading and
+ writing, based on Tcl's zlib support.
+
+2008-12-27 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkTreeview.c: [Bug 2381555]: Fix inconsistent use of
+ treeArea / headingArea. ([$tv identify] didn't work when horizontally
+ scrolled).
+
+2008-12-21 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/canvas.n (postscript): Regularized documentation of -channel
+ option.
+
+2008-12-19 Don Porter <dgp@users.sourceforge.net>
+
+ *** 8.6b1 TAGGED FOR RELEASE ***
+
+ * changes: Updates for 8.6b1 release.
+
+ * tests/clrpick.test: Eliminate duplicate test names.
+ * tests/embed.test:
+ * tests/text.test:
+ * tests/textMark.test:
+
+ * README: Bump version number to 8.6b1
+ * generic/tk.h:
+ * library/tk.tcl:
+ * unix/configure.in:
+ * unix/tk.spec:
+ * win/configure.in:
+
+ * unix/configure: autoconf-2.59
+ * win/configure:
+
+2008-12-18 Don Porter <dgp@users.sourceforge.net>
+
+ * library/msgs/de.msg: [Patch 2442309]: Updated German messages.
+ Thanks to Ruediger Haertel.
+
+2008-12-17 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tk.h: VOID --> void
+ * unix/tkUnixPort.h:
+ * macosx/tkMacOSXPort.h:
+
+2008-12-17 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/selection.n: [Bugs 2441817,2441884]: Assorted small fixes.
+
+2008-12-16 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tkWinDialog.c: Remove unused variables
+
+2008-12-15 Don Porter <dgp@users.sourceforge.net>
+
+ TIP #338 IMPLEMENTATION
+
+ * doc/Tk_Main.c: Removed the last two '#include "tclInt.h"'.
+ * generic/tkMain.c: Tk is now limited to Tcl's public interface.
+ * macosx/tkMacOSXInit.c:
+
+2008-12-12 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * library/demos/fontchoose.tcl: Simple fontchooser demo.
+ * library/demos/widget:
+
+2008-12-11 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tk3d.c: Make error message from Tk_GetRelief the same
+ as for Tk_GetReliefFromObj.
+ * tests/canvas.test: Adapt test cases for changed error message.
+ * tests/scrollbar.test
+ * tests/textTag.test
+
+2008-12-11 Joe English <jenglish@users.sourceforge.net>
+
+ * library/demos/*.tcl: Omit contraindicated [package require Ttk].
+ Remove logic that switches [ttk::scrollbar]s to [tk::scrollbar]s
+ based on [tk windowingsystem]; this is already handled in
+ library/ttk/scrollbar.tcl.
+
+2008-12-10 Daniel Steffen <das@users.sourceforge.net>
+
+ TIP #324 IMPLEMENTATION
+
+ * generic/tkCmds.c: Implementation of [tk fontchooser] as
+ * generic/tkInt.h: a Ttk dialog for X11 and as a native
+ * win/tkWinDialog.c: platform dialog on Mac OS X & Windows.
+ * win/tkWinInt.h: (thoyts, vetter, robert, steffen)
+ * win/tkWinTest.c: [Patch 1477426]
+ * win/tkWinX.c:
+ * macosx/tkMacOSXCarbonEvents.c:
+ * macosx/tkMacOSXDialog.c:
+ * macosx/tkMacOSXEvent.c:
+ * macosx/tkMacOSXEvent.h:
+ * macosx/tkMacOSXFont.c:
+ * macosx/tkMacOSXFont.h:
+ * macosx/Wish.xcodeproj/project.pbxproj:
+ * library/fontchooser.tcl (new):
+ * library/tclIndex:
+ * library/msgs/de.msg:
+ * library/msgs/en.msg:
+ * tests/fontchooser.test (new):
+ * tests/winDialog.test:
+ * doc/fontchooser.n (new):
+ * doc/tk.n:
+
+ * library/console.tcl: Let user select console font via
+ [tk fontchooser].
+ * library/demos/text.tcl: Add [tk fontchooser] demo.
+
+ * generic/tkUtil.c: Add TkBackgroundEvalObjv() and
+ TkSendVirtualEvent() utility functions
+ (used by TIP #324 code).
+
+ * generic/tkInt.h: Turn [tk] into an ensemble.
+ * generic/tkBusy.c: (thoyts, steffen)
+ * generic/tkCmds.c:
+ * generic/tkWindow.c:
+
+ * macosx/tkMacOSXInit.c (TkpInit): Unconditionally show Tk console if
+ TK_CONSOLE env var is set.
+
+2008-12-09 Don Porter <dgp@users.sourceforge.net>
+
+ TIP #337 IMPLEMENTATION
+
+ * generic/tkBind.c: Updated callers of Tcl_BackgroundError() to
+ * generic/tkCanvas.c: use the new routine
+ * generic/tkEntry.c: Tcl_BackgroundException() as appropriate.
+ * generic/tkImgBmap.c:
+ * generic/tkListbox.c:
+ * generic/tkSelect.c:
+ * generic/tkTextDisp.c:
+ * generic/tkTextWind.c:
+ * macosx/tkMacOSXHLEvents.c:
+ * macosx/tkMacOSXMenu.c:
+ * macosx/tkMacOSXMenus.c:
+ * macosx/tkMacOSXScale.c:
+ * macosx/tkMacOSXWindowEvent.c:
+ * unix/tkUnixScale.c:
+ * unix/tkUnixWm.c:
+ * win/tkWinButton.c:
+ * win/tkWinMenu.c:
+ * win/tkWinScrlbr.c:
+ * win/tkWinWm.c:
+
+2008-12-07 Joe English <jenglish@users.sourceforge.net>
+
+ * macosx/ttkMacOSXTheme.c: [Bug 2219588]: Add native aqua elements for
+ ttk::spinbox
+ * generic/ttk/ttkEntry.c, library/ttk/spinbox.tcl,
+ * tests/ttk/spinbox.test: Moved most spinbox "business logic" out of
+ ttkEntry.c into Tcl bindings.
+ * library/ttk/clamTheme.tcl: Minor spinbox appearance improvements.
+ * library/ttk/combobox.tcl, library/ttk/utils.tcl:
+ Factor out ttk::bindMouseWheel procedure.
+ * library/ttk/spinbox.tcl: Add cross-platform MouseWheel bindings.
+
+2008-12-06 Donal K. Fellows <dkf@users.sf.net>
+
+ TIP #197 IMPLEMENTATION
+
+ * generic/tkText.c (insertUnfocussedStrings, optionSpecs):
+ * generic/tkText.h (TkText, TkTextInsertUnfocussed):
+ * doc/text.n, tests/text.test:
+ Added definitions/tests/docs for "-insertunfocussed" field.
+ * generic/tkTextMark.c (TkTextInsertDisplayProc):
+ * generic/tkText.c (TextBlinkProc):
+ Added user-controlledrendering of insertion cursor when focus is not
+ in the text widget.
+
+2008-12-05 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * library/ttk/ttk.tcl: Added vista theme to iron out the visual
+ * library/ttk/vistaTheme.tcl: differences between vista and XP.
+ * library/ttk/xpTheme.tcl:
+ * win/ttkWinXPTheme.c:
+
+2008-12-05 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkCanvPs.c (Tk_PostscriptFont): [Bug 2107938]: Ensure that
+ font sizes can ever be negative; it triggers a really strange case
+ that is definitely not what is wanted.
+ * library/mkpsenc.tcl: Corrected and improved generation of postscript
+ * library/prolog.ps: prolog. Removed prolog.ps, which wasn't used and
+ was misleading.
+
+2008-12-04 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkInt.decls: [FRQ 220906]: Move 10 functions from tkText.h
+ * generic/tkText.h: to stub table.
+ * generic/tkStubInit.c (regenerated)
+ * generic/tkIntDecls.h (regenerated)
+
+2008-12-04 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/ttk_button.n, doc/ttk_checkbutton.n, doc/ttk_menubutton.n:
+ * doc/ttk_radiobutton.n: Added mention of the Toolbutton style to all
+ widgets that can sensibly make use of it.
+
+2008-12-03 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkState.c, generic/ttk/ttkTheme.h,
+ * generic/ttk/ttkWidget.c, doc/ttk_widget.n:
+ Add new "hover" state (patch from Pat Thoyts; needed to support proper
+ visual feedback on Vista).
+
+2008-11-29 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * library/ttk/altTheme.tcl: Use a styled frame around the popdown
+ * library/ttk/clamTheme.tcl: listbox so we can adjust the border
+ * library/ttk/classicTheme.tcl: for each theme as needed.
+ * library/ttk/combobox.tcl:
+ * library/ttk/defaults.tcl:
+ * library/ttk/winTheme.tcl:
+ * library/ttk/xpTheme.tcl:
+ * tests/ttk/combobox.test:
+
+2008-11-28 Alexandre Ferrieux <ferrieux@users.sourceforge.net>
+
+ * generic/tkCanvUtil.c: [Bug 1813597,2218964]: Millimeter patch.
+ * generic/tkInt.h: Eliminates the functional redundancy and
+ * generic/tkObj.c: unnecessary loss of precision of the
+ * generic/tkText.c: {pixel,mm}ObjType tandem.
+
+2008-11-27 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkCanvLine.c: Replace Tcl_SetResult(interp, NULL, ....)
+ * generic/tkEntry.c: calls with Tcl_ResetResult(interp)
+ * generic/tkMenu.c
+ * generic/tkOldConfig.c
+ * win/tkWinTest.c: Eliminate warning: unused variable 'tkwin'
+
+2008-11-23 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * generic/tkBind.c: [Bug 1389270]: event generate silently ignored
+ * generic/tkFocus.c: focus events. These can now be generated.
+ * generic/tkGrab.c:
+ * generic/tkInt.h:
+ * tests/bind.test: Fixed some locale dependencies in various
+ tests to reduce the noise on non-English windows systems.
+
+2008-11-22 Donal K. Fellows <dkf@users.sf.net>
+
+ * library/demos/ctext.tcl: Extended to show off what you can do with
+ angled text; there is now a pie selector to change the orientation.
+
+2008-11-22 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * library/ttk/combobox.tcl: [Bug 1939129,1991930]: combobox dropdown
+ was drawn behind topmost toplevels.
+ * generic/tkCanvText.c: Fixed up complaints from MSVC engendered
+ * generic/tkFont.c: by the last commit. In particular replaced
+ * win/tkWinDraw.c: round() which is a C99 function.
+ * win/tkWinFont.c:
+
+2008-11-22 Donal K. Fellows <dkf@users.sf.net>
+
+ TIP #119 IMPLEMENTATION
+
+ * generic/tkCanvText.c: Added -angle configuration option to canvas
+ * generic/tkFont.c: text items. This required reengineering the
+ * library/prolog.ps: whole text rendering engine to be able to
+ * macosx/tkMacOSXFont.c: handle an angle! No change to any external
+ * unix/tkUnixFont.c: API. Note, this feature was originally
+ * unix/tkUnixRFont.c: approved for Tk 8.5, but it has proved much
+ * win/tkWinFont.c: harder to implement than originally
+ * generic/tkInt.h: estimated. [Patch 1611359]
+ * tests/canvText.test:
+
+2008-11-22 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * test/winDialog.test: [Bug 2307837]: Avoid some locale-dependent
+ * win/tkWinTest.c: failures by using id's or an english constraint
+
+2008-11-19 Joe English <jenglish@users.sourceforge.net>
+
+ * doc/ttk_panedwindow.n: [Bug 1824996]: Remove inoperative text
+ stating that slave windows must be direct children of the master.
+
+2008-11-19 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkImgPhoto.c Minor simplification in fix for [Bug 2312027]
+ no need to malloc and copy photo type name
+ because it is a constant to begin with.
+ * generic/tkOldConfig.c Convert Tcl_SetResult(......, TCL_DYNAMIC) to
+ * mac/tkMacOSXWm.c Tcl_SetResult(......, TCL_VOLATILE), in
+ * unix/tkUnixWm.c preparation for TIP #340
+ * unix/tkUnixSend.c
+ * win/tkWinWm.c
+
+2008-11-16 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkWidget.c: [Bug 2298720]: Widget self-destruction is
+ not necessarily an error.
+
+2008-11-16 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/wm.n: Added note about [wm overrideredirect] so that users will
+ avoid making unwarranted assumptions about how magical it is.
+ Triggered by [Bug 2282861] discussion.
+
+2008-11-14 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * generic/tk.h: The TIP 125 implementation permits the
+ * generic/tkFrame.c: [wm manage] command to manage any widget but
+ * macosx/tkMacOSXWm.c: only those with Frame instance data should be
+ * unix/tkUnixWm.c: permitted. We now check for the suitability and
+ * win/tkWinWm.c: raise an error for non-frame widgets. Updated
+ * test/wm.test: the tests and documentation. See also [Bug
+ * doc/wm.n: 2239034]
+
+2008-11-12 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkWidget.c: Reworked widget construction and
+ destruction sequence; fixes [Bug 2207435] and several other problems
+ discovered during investigation of same.
+ * generic/ttk/ttkButton.c (CheckbuttonInitialize): Account for
+ initializeProc being called earlier in the construction sequence now.
+ * tests/ttk/ttk.test: Updated test suite.
+
+2008-11-12 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * library/text.tcl: [Bug 1777362]: Handle windows with funky names by
+ * test/text.test: avoiding use of the window path for anchors.
+
+2008-11-11 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkImgPhoto.c Fix [Bug 2265860] new test failures
+
+2008-11-11 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkWidget.c (BeginDrawing): [Bug 2264732]: Don't crash
+ when application uses nondefault visual.
+
+2008-11-11 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tcl.m4: Reverted change from 2008-11-06 (was under the
+ impression that "-Wno-implicit-int" added an extra
+ warning)
+ * win/configure (regenerated)
+ * unix/tcl.m4: Use -O2 as gcc optimization compiler flag, and get
+ rid of -Wno-implicit-int for UNIX
+ * unix/configure (regenerated)
+
+ * generic/tk.decls Modify Tk_Create(Old)ImageType signature,
+ * generic/tk.h relaxing the constraint that every Tk_ImageType
+ * generic/tkImage.c can only be passed to this function once. This
+ * generic/tkImgBmap.c lets tkImg be loaded in multiple interpreters
+ * generic/tkImgPhoto.c in a thread-enabled build of Tk. [Bug 2312027]
+ * generic/tkTest.c This CONSTification complies with TIP #27. It
+ * doc/CrtImgType.3 is binary compatible with the old interface,
+ but not fully source compatible (although tkImg
+ does not suffer).
+ * generic/tkDecls.h (regenerated)
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2008-11-09 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkWidget.c: Remove unnecessary casts.
+
+ * generic/ttk/ttkWidget.h, generic/ttk/ttkWidget.c: Ttk widget
+ initializeProc()s now return void instead of a status code, and are no
+ longer allowed to fail. (Fix for [Bug 2207435] in progress).
+
+ * generic/ttk/ttkButton.c, generic/ttk/ttkEntry.c,
+ * generic/ttk/ttkFrame.c, generic/ttk/ttkNotebook.c,
+ * generic/ttk/ttkPanedwindow.c, generic/ttk/ttkProgress.c,
+ * generic/ttk/ttkScale.c, generic/ttk/ttkScrollbar.c,
+ * generic/ttk/ttkTreeview.c: Adjustments for the above.
+
+2008-11-09 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkCanvas.c: Make all Tk_CustomOption tables const and
+ * generic/tkCanvBmap.c: remove unnecessary type cast.
+ * generic/tkCanvImg.c:
+ * generic/tkCanvPoly.c:
+ * generic/tkCanvText.c:
+ * generic/tkCanvWind.c:
+ * generic/tkRectOval.c:
+ * generic/tkScrollbar.c:
+ * generic/tk.decls: Two more (hopefully the last) signature
+ * generic/tkInt.h: changes in Tk_CreateSmoothMethod and
+ * generic/tkCanvLine.c: Tk_CreatePhotoImageFormat
+ * generic/tkCanvUtil.c:
+ * generic/tkImgPhoto.c:
+ * generic/tkDecls.h: (regenerated)
+ * doc/CrtImgType.3: doc updates
+ * doc/CrtPhImgFmt.3:
+
+2008-11-06 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tcl.m4: Add "-Wno-implicit-int" flag for gcc, as on UNIX
+ * win/configure: (regenerated)
+ * generic/default.h: Use tkUnixDefault.h under CygWin. With this
+ change, at least the X11 version of Tk can be
+ built with cygwin.
+
+2008-11-06 Donal K. Fellows <dkf@users.sf.net>
+
+ * unix/configure.in: [Bug 2229999]: Work around the fact that the
+ HP-UX system compiler cannot handle 'inline'.
+
+2008-11-05 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * unix/tkUnixFont.c: [Bug 2226093]: Const changes not all correct
+ * unix/tkUnixButton.c: More internal -Wwrite-strings warning fixes
+ * unix/tkUnixCursor.c:
+ * unix/tkUnixSend.c:
+ * unix/tkUnixRFont.c:
+ * generic/tkInt.h: No need to use CONST in internal header files
+ * generic/tkFont.h
+ * generic/tkInt.decls: CONSTify string and fileName parameters of
+ * generic/tkImgBmap.c: TkGetBitmapData
+ * generic/tkBitmap.c: Remove unneccessary type cast
+ * generic/tkIntDecls.h: (regenerated)
+ * doc/GetCursor.3: Fix documentation about obsolete X10 bitmaps
+ * doc/GetBitmap.3: [Bug 1866774]: Remove X10 references from docs
+
+2008-11-03 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/ttk/ttkEntry.c: Fix warning: unused variable `currentValue'
+ * generic/tkOldTest.c: Fix warning: assignment discards qualifiers
+ * win/tkWinTest.c: from pointer target type
+
+2008-11-03 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * tests/winClipboard.test: testclipboard no longer returns strings
+ with embedded \r but now returns Tcl strings
+ * tests/winfo.test: Fixed embedding test broken during upgrade
+ * tests/busy.test: Default wait cursor on windows is 'wait'
+ * win/tkWinFont.c: const fixes for the windows code.
+
+2008-11-02 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkFont.h: More internal -Wwrite-strings warning fixes
+ * generic/tkFont.c
+ * generic/ttk/ttkTheme.h
+ * generic/ttk/ttkDefaultTheme.c
+ * generic/ttk/ttkState.c
+ * macosx/tkMacOSXFont.c
+ * unix/tkUnixFont.c
+ * win/tkWinFont.c
+
+2008-11-01 Donal K. Fellows <dkf@users.sf.net>
+
+ TIP #97 IMPLEMENTATION
+
+ * generic/tkCanvas.c (CanvasWidgetCmd): Implementation of the 'imove'
+ and 'rchars' subcommands.
+ * generic/tk.h (TK_MOVABLE_POINTS): New flag to allow items to state
+ whether they support finding and moving individual coordinates.
+ * doc/canvas.n, tests/canvas.test: Docs 'n' tests.
+
+2008-11-01 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * generic/ttk/ttkEntry.c: Implemented the themed spinbox
+ * library/ttk/altTheme.tcl: widget.
+ * library/ttk/clamTheme.tcl:
+ * library/ttk/classicTheme.tcl:
+ * library/ttk/defaults.tcl:
+ * library/ttk/entry.tcl:
+ * library/ttk/ttk.tcl:
+ * library/ttk/winTheme.tcl:
+ * library/ttk/xpTheme.tcl:
+ * library/ttk/spinbox.tcl:
+ * win/ttkWinTheme.c:
+ * win/ttkWinXPTheme.c:
+ * doc/ttk_spinbox.n:
+ * tests/ttk/spinbox.test:
+
+2008-10-31 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/widget.c: Temporary workaround for [Bug 2207435]
+
+2008-10-30 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkAtom.c: more internal -Wwrite-strings warning fixes
+ * generic/tkBusy.c
+ * generic/tkButton.c
+ * generic/tkCanvPoly.c
+ * generic/tkCanvText.c
+ * generic/tkCmds.c
+ * generic/tkListbox.c
+ * generic/tkMenu.c
+ * generic/tkOldConfig.c
+ * generic/tkOption.c
+ * generic/tkPanedWindow.c
+ * generic/tkPlace.c
+ * generic/tkScale.c
+ * generic/tkTest.c
+ * generic/tkText.c
+ * generic/tkTextImage.c
+
+2008-10-30 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/unixSelect.test: Revise the unixSelect-1.* tests so that
+ they test the ability of Tk's selection mechanism to faithfully pass
+ valid Tcl values without corruption, and stop testing details of
+ Tcl's internal encoding scheme. With this change, the Tk test suite
+ no longer uses the identity encoding or [string bytelength].
+
+2008-10-30 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tk.h: CONSTify return value of
+ * generic/tkInt.h Tk_OptionPrintProc, and customPtr
+ * generic/tk.decls field of Tk_ConfigSpec.
+ * generic/tkCanvArc.c See [Bug 2190619]: Warnings due to
+ * generic/tkCanvLine.c Tk_SmoothMethod name constness change
+ * generic/tkCanvUtil.c
+ * generic/tkUtil.c
+ * generic/tkDecls.h: (regenerated)
+
+2008-10-29 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/tkAtom.c(Tk_GetAtomName): Remove incorrect 'const' qualifier.
+ Remove useless 'register' declarations too, while we're at it.
+
+2008-10-28 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tk.h: Add "const" to a few struct member fields.
+ * generic/tkInt.h: CONSTify TkPrintPadAmount
+ * generic/tkSelect.h: Move TkSelGetSelection to tkInt.decls
+ * generic/tk.decls: CONSTify Tk_ParseArgv
+ * generic/tkInt.decls: CONSTify TkCreateFrame and TkCreateMainWindow
+ * generic/tkDecls.h: (regenerated)
+ * generic/tkIntDecls.h: (regenerated)
+ * generic/tkArgv.c:
+ * generic/tkAtom.c:
+ * generic/tkEntry.c:
+ * generic/tkFrame.c:
+ * generic/tkImgPhoto.c:
+ * generic/tkPack.c:
+ * generic/tkSelect.c:
+ * generic/tkVisual.c:
+ * generic/tkWindow.c:
+ * win/tkWinTest.c: Fix compilation under mingw32
+
+2008-10-28 Joe English <jenglish@users.sourceforge.net>
+
+ * library/ttk/cursors.tcl, library/ttk/combobox.tcl,
+ library/ttk/entry.tcl, library/ttk/paned.tcl, library/ttk/sizegrip.tcl,
+ library/treeview.tcl:
+ [Bug 2054562]: Add correct platform-specific cursors for OSX
+ [Bug 1534835]: Expanded set of symbolic cursors. Use correct cursor
+ for ttk::entry and ttk::combobox widgets
+
+2008-10-28 Don Porter <dgp@users.sourceforge.net>
+
+ * win/tkWinTest.c: [Bug 2191960]: Revise [testclipboard]
+ * tests/winClipboard.test: to form that handles encodings.
+ * tests/constraints.tcl: [tcltest::bytestring] no longer used.
+
+2008-10-24 Joe English <jenglish@users.sourceforge.net>
+
+ * tests/ttk/ttk.test: [Bug 2175411]: Disable test ttk-6.3, it's not
+ applicable.
+
+ * generic/ttk/ttkTheme.c: Use different Tcl_AssocData key so the tile
+ extension can be loaded into an 8.6 interp, in the off-chance that
+ anyone wants to do this.
+
+2008-10-24 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkCanvUtil.c (TkSmoothPrintProc): [Bug 2190619]: Corrected
+ 'const'ness to quell warning.
+
+2008-10-23 Don Porter <dgp@users.sourceforge.net>
+
+ * README: Bump version number to 8.6a4
+ * generic/tk.h:
+ * library/tk.tcl:
+ * unix/configure.in:
+ * unix/tk.spec:
+ * win/configure.in:
+
+ * unix/configure: autoconf-2.59
+ * win/configure:
+
+2008-10-22 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tk.h: CONST -> const and white-spacing
+ * generic/tk.decls
+ * generic/tkInt.decls
+ * generic/tkDecls.h: (regenerated)
+ * generic/tkIntDecls.h: (regenerated)
+ * generic/tkIntPlatDecls.h: (regenerated)
+ * generic/tkIntXlibDecls.h: (regenerated)
+ * generic/tkPlatDecls.h: (regenerated)
+ * generic/ttk/tk.decls
+ * generic/ttk/ttkDecls.h (regenerated)
+ * generic/ttk/ttkGenStubs.tcl
+
+2008-10-20 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkBusy.c, macosx/tkMacOSXEmbed.c, unix/tkUnixEmbed.c:
+ * win/tkWinWindow.c: [Bug 2180919]: Factor out the platform-specific
+ parts into the platform directories.
+
+2008-10-18 Donal K. Fellows <dkf@users.sf.net>
+
+ TIP #321 IMPLEMENTATION
+
+ * generic/tkBusy.c, doc/busy.n, tests/busy.test: [Patch 1997907]:
+ Implementation of the [tk busy] command.
+
+2008-10-18 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tkWinFont.c: [Bug 1825353]: To fix a problem with tiny fonts on
+ Russian versions of Windows we will avoid removing the internal
+ leading for fixed width fonts.
+
+2008-10-15 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tk.h: Add "const" to many internal const tables, so
+ * generic/tkBind.c: those will be put by the C-compiler in the
+ * generic/tkButton.c: TEXT segment instead of the DATA segment.
+ * generic/tkCanvas.c: This makes those tables as being shareable in
+ * generic/tkClipboard.c: shared libraries.
+ * generic/tkCmds.c:
+ * generic/tkConsole.c:
+ * generic/tkEntry.c:
+ * generic/tkFocus.c:
+ * generic/tkFrame.c:
+ * generic/tkGet.c:
+ * generic/tkGrab.c:
+ * generic/tkGrid.c:
+ * generic/tkImage.c:
+ * generic/tkImgBmap.c:
+ * generic/tkImgGIF.c:
+ * generic/tkImgPhoto.c:
+ * generic/tkListbox.c:
+ * generic/tkMenu.c:
+ * generic/tkMenu.h:
+ * generic/tkMenubutton.c:
+ * generic/tkMessage.c:
+ * generic/tkOption.c:
+ * generic/tkPack.c:
+ * generic/tkPanedWindow.c:
+ * generic/tkPlace.c:
+ * generic/tkScale.c:
+ * generic/tkSelect.c:
+ * generic/tkSquare.c:
+ * generic/tkTest.c:
+ * generic/tkText.c:
+ * generic/tkTextDisp.c:
+ * generic/tkTextMark.c:
+ * generic/tkTextTag.c:
+ * generic/tkTextWind.c:
+ * macosx/tkMacOSXDialog.c:
+ * macosx/tkMacOSXSend.c:
+ * macosx/tkMacOSXWin.c:
+ * unix/tkUnixFont.c:
+ * unix/tkUnixWm.c:
+ * win/tkWinButton.c:
+ * win/tkWinColor.c:
+ * win/tkWinDialog.c:
+ * win/tkWinMenu.c:
+ * win/tkWinSend.c:
+ * win/tkWinWm.c:
+ * xlib/xcolors.c:
+
+2008-10-17 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * library/ttk/scale.tcl: Implemented keyboard bindings for ttk::scale
+
+2008-10-15 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tkInt.h: Add "const" to many internal const tables, so
+ * generic/tk3d.c: those will be put by the C-compiler in the
+ * generic/tkBitmap.c: TEXT segment instead of the DATA segment.
+ * generic/tkColor.c: This makes those tables as being shareable in
+ * generic/tkConfig.c: shared libraries.
+ * generic/tkCursor.c:
+ * generic/tkFont.c:
+ * generic/tkObj.c:
+ * generic/tkStyle.c:
+ * generic/tkTextIndex.c:
+ * generic/tkUtil.c:
+
+2008-10-14 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkObj.c (TkNewWindowObj): Added utility function for making
+ a Tcl_Obj from a Tk_Window reference. Candidate for future exposure to
+ third-party code I suppose, but useful internal to Tk for sure.
+
+2008-10-11 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tkCanvas.c (CanvasWidgetCmd): Corrected result generation.
+
+2008-10-10 Don Porter <dgp@users.sourceforge.net>
+
+ *** 8.6a3 TAGGED FOR RELEASE ***
+
+ * changes: Updates for 8.6a3 release.
+
+2008-10-09 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkListbox.c: Make literal return values consistent with
+ those generated by Tcl_PrintDouble().
+
+ * tests/entry.test: Restore test naming consistency with Tk 8.5.
+ * tests/listbox.test: Remove some more dependency on precision in
+ * tests/spinbox.test: test results.
+
+2008-10-08 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * unix/tcl.m4: [Bug 2073255]: fix
+ * unix/configure: regenerated
+
+2008-10-08 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/textDisp.test (textDisp-16.34): Update test that tested string
+ equality of double values based on an assumption of tcl_precision==12.
+ Test now does its own formatting.
+
+ * tests/scrollbar.test: Revised testing of the cget subcommand so that
+ it tests consistency with the configure subcommand and not agreement
+ with a hardcoded value that will change as tastes in GUIs evolve.
+
+ * tests/canvText.test (canvText-17.1): Update expected result to match
+ revised PostScript output due to more predictable formatting of
+ floating point values.
+
+ * unix/tkUnixWm.c: [Bug 2021443]: Restored consistency of error
+ * macosx/tkMacOSXWm.c: messages from [wm iconphoto] with the test
+ * tests/unixWm.test: suite and across all platforms.
+
+2008-10-07 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * tests/canvImg.test: Removed dependency on precision in results
+ * tests/canvRect.test:
+ * tests/canvText.test:
+ * tests/entry.test:
+ * tests/listbox.test:
+ * tests/scrollbar.test:
+ * tests/spinbox.test:
+ * tests/winWm.test: Fixed incorrect error strings
+ * tests/wm.test:
+
+2008-10-06 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * tests/winDialog.test: Fixed tests for Vista+
+ * win/tkWinWm.c: corrected some errors from the previous commit
+
+2008-10-05 Donal K. Fellows <dkf@users.sf.net>
+
+ * win/tkWinWm.c (WmAttributesCmd, WmOverrideredirectCmd)
+ (WmStackorderCmd):
+ * win/tkWinSendCom.c (Async):
+ * win/tkWinSend.c (Tk_SendObjCmd):
+ * win/tkWinFont.c (TkpGetFontFamilies, TkpGetSubFonts):
+ * unix/tkUnixWm.c (WmOverrideredirectCmd, WmStackorderCmd):
+ * unix/tkUnixFont.c (TkpGetFontFamilies, TkpGetSubFonts):
+ * macosx/tkMacOSXWm.c (WmOverrideredirectCmd, WmStackorderCmd):
+ * generic/tkTextIndex.c (SetTextIndexFromAny):
+ * generic/tkTest.c (TrivialConfigObjCmd):
+ * generic/tkSelect.c (HandleTclCommand):
+ * generic/tkPanedWindow.c (Tk_PanedWindowObjCmd)
+ (PanedWindowSashCommand, PanedWindowProxyCommand):
+ * generic/tkMenubutton.c (Tk_MenubuttonObjCmd):
+ * generic/tkMenu.c (MenuWidgetObjCmd):
+ * generic/tkListbox.c (ListboxWidgetObjCmd):
+ * generic/tkImgPhoto.c (ImgPhotoCmd): (mostly)
+ * generic/tkImage.c (Tk_ImageObjCmd):
+ * generic/tkFont.c (Tk_FontObjCmd, GetAttributeInfoObj):
+ * generic/tkEntry.c (EntryWidgetObjCmd, SpinboxWidgetObjCmd):
+ * generic/tkConfig.c (SetOptionFromAny, Tk_SetOptions):
+ * generic/tkCmds.c (Tk_TkObjCmd, Tk_WinfoObjCmd, TkGetDisplayOf):
+ * generic/tkButton.c (ButtonCreate): Get rid of code that insists on
+ non-idiomatically writing to the object in the interpreter result.
+
+2008-10-03 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkArgv.c, generic/tkCanvText.c, generic/tkEntry.c:
+ * generic/tkListbox.c, generic/tkScrollbar.c, macosx/tkMacOSXScrlbr.c:
+ * win/tkWinScrlbr.c: [Bug 2112563]: Convert use of %g to
+ Tcl_PrintDouble to create string versions of floats so as to avoid
+ trouble with some locales.
+
+2008-10-02 Joe Mistachkin <joe@mistachkin.com>
+
+ * doc/canvas.n: Fix unmatched font change.
+ * win/buildall.vc.bat: Prefer the HtmlHelp target over the WinHelp
+ target.
+
+2008-10-01 Donal K. Fellows <dkf@users.sf.net>
+
+ TIP #236 IMPLEMENTATION
+
+ * doc/canvas.n, generic/tkCanvas.c (CanvasWidgetCmd)
+ * tests/canvMoveto.test: Added 'moveto' subcommand to canvases to
+ allow items to be easily moved to a particular place.
+
+2008-09-23 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/listbox.n (SEE ALSO): [Bug 2123813]: Redirected this to
+ ttk::treeview(n) which is far more useful (it does multicolumn listbox
+ duties).
+
+ * doc/*.n: [Bug 2118116]: Make sure that the initial line of the
+ manpage includes nothing that chokes old versions of man.
+
+2008-08-25 Todd M. Helfter <tmh@users.sourceforge.net>
+
+ * library/menu.tcl: [Bug 1023955]: Additional fix.
+
+2008-09-08 Todd M. Helfter <tmh@users.sourceforge.net>
+
+ * doc/menu.n: [Bug 2098425]: Fix typo in docs.
+
+2008-09-03 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tk.h: Dropped use of _ANSI_ARGS_ macro to preserve
+ * generic/tkSelect.h: Tk's TCL_NO_DEPRECATED build.
+
+2008-08-30 Ania Pawelczyk <aniap@users.sourceforge.net>
+
+ * tests/textWind.test: Update to tcltest2
+ * tests/unixSelect.test:
+ * tests/visual_bb.test:
+ * tests/visual.test:
+ * tests/window.test:
+ * tests/winfo.test:
+ * tests/xmfbox.test:
+ * tests/winButton.test:
+ * tests/winDialog.test:
+ * tests/winFont.test:
+ * tests/winMenu.test:
+ * tests/winMsbox.test:
+ * tests/winWm.test:
+
+2008-08-28 Don Porter <dgp@users.sourceforge.net>
+
+ * unix/tkConfig.sh.in: Added @XFT_LIBS@ to the definition of TK_LIBS
+ to avoid link failures when a "big wish" program links against a
+ --disable-shared build of libtk. (Discovered building expectTk.)
+
+ * generic/tkImgPhoto.c: Changed TclStack* calls to ck* calls so that
+ we don't create new dependencies on Tcl internals.
+
+ * unix/tkUnixPort.h: Removed #include of tclInt.h that has been
+ * win/tkWinPort.h: disabled for three years. If we needed this
+ we'd have noticed by now.
+
+ * README: Bump version number to 8.6a3
+ * generic/tk.h:
+ * library/tk.tcl:
+ * unix/configure.in:
+ * unix/tk.spec:
+ * win/configure.in:
+
+ * unix/configure: autoconf-2.59
+ * win/configure:
+
+2008-08-28 Donal K. Fellows <dkf@users.sf.net>
+
+ * tests/imgPhoto.test: [Bug 2080587]: Fix failures.
+
+2008-08-28 Ania Pawelczyk <aniap@users.sourceforge.net>
+
+ * tests/option.test: Update to tcltest2
+ * tests/place.test:
+ * tests/scale.test:
+ * tests/select.test:
+ * tests/textBTree.test:
+ * tests/textImage.test:
+ * tests/textMark.test:
+ * tests/textTag.test:
+ * tests/unixMenu.test:
+
+2008-08-25 Todd M. Helfter <tmh@users.sourceforge.net>
+
+ * library/menu.tcl: [Bug 1023955]: Fix typo.
+
+2008-08-27 Peter Spjuth <peter.spjuth@gmail.com>
+
+ * tests/grid.test: [Bug 2075285]: Added a "knownBug"-marked test to
+ show a problem identified in the grid implementation.
+
+2008-08-26 Donal K. Fellows <dkf@users.sf.net>
+
+ * tests/imgPhoto.test: More style improvements.
+
+2008-08-25 Todd M. Helfter <tmh@users.sourceforge.net>
+
+ * library/menu.tcl: [Bug 1023955]: Do not flip to the arrow cursor on
+ menus. This was a Motif convention. Current behavior is maintained iff
+ tk_strictMotif is enabled.
+
+2008-08-25 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkImgPhoto.c (ImgPhotoConfigureMaster): Ensure that uses of
+ TclStackAlloc and TclStackFree balance.
+
+2008-08-25 Todd M. Helfter <tmh@users.sourceforge.net>
+
+ * library/tkfbox.tcl: [Bug 1936220]: Fix the multiple selection error
+ for tk_getOpenFile -multiple 1 which fails on all unix platforms since
+ the adoption of ttk widgets.
+
+2008-08-25 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkImgPhoto.c: Split the implementation of the core of
+ * generic/tkImgPhoto.h: photo images into two pieces, the photo
+ * generic/tkImgPhInstance.c: master (which manages the data model and
+ the interaction with the script level) and the photo instances (which
+ handle display).
+
+2008-08-22 Don Porter <dgp@users.sourceforge.net>
+
+ *** 8.6a2 TAGGED FOR RELEASE ***
+
+ * changes: Updates for 8.6a2 release.
+
+2008-08-21 Ania Pawelczyk <aniap@users.sourceforge.net>
+
+ * tests/menuDraw.test: Update to tcltest2
+ * tests/msgbox.test:
+ * tests/oldpack.test:
+ * tests/pack.test:
+ * tests/panedwindow.test:
+
+2008-08-21 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkOption.c (ExtendArray): Rework so that the code uses
+ ckrealloc (idiomatically) rather than its home-brewed version.
+
+2008-08-19 George Peter Staplin <georgeps@users.sourceforge.net>
+
+ [Bug 2039720]: After some discussion with Joe English and subsequently
+ the X.org developers (Keith Packard in particular), it was discovered
+ that Tk is doing management of XIDs that it shouldn't need to do. The
+ very common XC-MISC extension which has come with every version of X
+ for the last 15 years is used with Xlib now, to retrieve the
+ information about the used/unused XIDs. The public Tk_FreeXId is now a
+ no-op.
+
+ * generic/tkError.c: Remove the usage of TkpWindowWasRecentlyDeleted.
+ * generic/tkInt.decls: Update the declarations for the now unused
+ internal stubs.
+ * generic/tkIntDecls.h: Regenerated based on tkInt.decls.
+ * generic/tkIntPlatDecls.h: Regenerated based on tkInt.decls.
+ * generic/tkStubInit.c
+ * generic/tkWindow.c: Remove the calls to TkInitXId, and
+ TkFreeWindowId.
+ * macosx/tkMaxOSXPort.h: Remove TkFreeWindowId and TkInitXId macro
+ definitions.
+ * macosx/tkMacOSXXStubs.c: Remove the no-op
+ TkpWindowWasRecentlyDeleted.
+ * unix/tkUnixEvent.c: Remove call to TkFreeXId.
+ * unix/tkUnixXId.c: Remove a lot of unnecessary code (see above).
+ * win/tkWinPort.h: Remove TkFreeWindowId and TkInitXId.
+ * win/tkWinWindow.c: Remove TkpWindowWasRecentlyDeleted.
+ * tests/id.test: Remove this unnecessary test.
+
+2008-08-19 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkScroll.c: Don't use sprintf "%g" to format floating
+ point numbers in -[xy]scrollcommand callbacks or [xy]view methods.
+ Minor incompatibility: 0 and 1 now formatted as "0.0" resp "1.0".
+ * tests/ttk/entry.test, tests/ttk/treeview.test: Updated to account
+ for above change.
+
+2008-08-19 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXFont.c (SetFontFeatures): Disable antialiasing of
+ fixed-width fonts with
+ size <= 10.
+
+2008-08-18 Ania Pawelczyk <aniap@users.sourceforge.net>
+
+ * tests/canvWind.test: Update to tcltest2
+ * tests/menubut.test:
+ * tests/raise.test:
+ * tests/unixButton.test:
+ * tests/unixEmbed.test:
+ * tests/winClipboard.test:
+
+2008-08-17 Ania Pawelczyk <aniap@users.sourceforge.net>
+
+ * tests/focus.test: Update to tcltest2
+ * tests/focusTcl.test:
+ * tests/geometry.test:
+ * tests/grab.test:
+ * tests/grid.test:
+ * tests/imgBmap.test:
+ * tests/imgPhoto.test:
+ * tests/imgPPM.test:
+ * tests/listbox.test:
+ * tests/safe.test:
+ * tests/tk.test:
+ * tests/util.test:
+
+2008-08-15 Ania Pawelczyk <aniap@users.sourceforge.net>
+
+ * tests/clrpick.test: Update to tcltest2
+ * tests/frame.test:
+ * tests/font.test:
+ * tests/image.test:
+
+2008-08-14 Ania Pawelczyk <aniap@users.sourceforge.net>
+
+ * tests/event.test: Update to tcltest2
+ * tests/id.test:
+ * tests/menu.test:
+
+2008-08-14 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/tcl.m4 (SC_PATH_X): Check for libX11.dylib in addition to
+ libX11.so et al.
+
+ * unix/configure: autoconf-2.59
+
+2008-08-12 Ania Pawelczyk <aniap@users.sourceforge.net>
+
+ * tests/choosedir.test: Update to tcltest2
+ * tests/clipboard.test:
+ * tests/embed.test:
+ * tests/main.test:
+
+2008-08-12 Don Porter <dgp@users.sourceforge.net>
+
+ * README: Bump version number to 8.6a2
+ * generic/tk.h:
+ * library/tk.tcl:
+ * unix/configure.in:
+ * unix/tk.spec:
+ * win/configure.in:
+
+ * unix/configure: autoconf-2.59
+ * win/configure:
+
+ * changes: Updates for 8.6a2 release.
+
+2008-08-11 Ania Pawelczyk <aniap@users.sourceforge.net>
+
+ * tests/canvImg.test: Update to tcltest2
+ * tests/canvRect.test:
+ * tests/canvText.test:
+ * tests/obj.test:
+
+2008-08-07 Ania Pawelczyk <aniap@users.sourceforge.net>
+
+ * tests/canvPs.test: Update to tcltest2
+ * tests/config.test:
+ * tests/canvas.test:
+
+2008-08-05 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/tk.h, generic/tkEvent.c: Fix for [Bug 2010422] "no event
+ type or button # or keysym while executing "bind Listbox
+ <MouseWheel> [...]".
+
+2008-08-03 Ania Pawelczyk <aniap@users.sourceforge.net>
+
+ * tests/cmds.test: Update to tcltest2
+ * tests/dialog.test:
+ * tests/get.test:
+ * tests/text.test: Update to tcltest2; report: 33.11 fails
+
+2008-08-01 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tkWinWm.c: [Bug 2028703]: Check wmPtr is valid in
+ * tests/wm.test: TopLevelReqProc.
+
+2008-07-31 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tk.h: Added missing EXTERN for the Tcl_PkgInitStubsCheck
+ declaration to fix inability to embed non-stub-enabled Tk on Windows.
+
+2008-07-29 Ania Pawelczyk <aniap@users.sourceforge.net>
+
+ * tests/constraints.tcl: -highlightthickness entry's option (fonts
+ constraint)
+
+2008-07-28 Ania Pawelczyk <aniap@users.sourceforge.net>
+
+ * tests/cursor.test: Update to tcltest2
+ * tests/message.test:
+
+2008-07-26 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * doc/options.n: [Bug 1686012]: Direct to the font manual for -font.
+
+ * tests/constraints.tcl: Add a nonwin contraint.
+ * tests/listbox.test: [Bug 2024753]: Conform to testing policy.
+
+ * win/tkWinWm.c: [Bug 2009788]: Check that the parent has been mapped
+ * tests/wm.test: before calling RemapWindows.
+
+ * win/tkWinWindow.c: [Bug 2026405]: Check for 0x prefix in sprintf %p.
+
+2008-07-25 Ania Pawelczyk <aniap@users.sourceforge.net>
+
+ * tests/bind.test: Update to tcltest2
+
+2008-07-24 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/*.c: [Bug 2021443]: Fix inconsistant "wrong # args" messages
+ * macosx/tkMacOSXSend.c
+ * macosx/tkMacOSXWm.c
+ * unix/tkUnixSend.c
+ * unix/tkUnixWm.c
+ * tests/*.test
+
+2008-07-22 Ania Pawelczyk <aniap@users.sourceforge.net>
+
+ * tests/bell.test: Update to tcltest2
+ * tests/bgerror.test:
+ * tests/bitmap.test:
+ * tests/border.test:
+ * tests/button.test:
+ * tests/entry.test:
+ * tests/spinbox.test:
+
+2008-07-22 Daniel Steffen <das@users.sourceforge.net>
+
+ * library/ttk/aquaTheme.tcl: Use system color names and TIP145 named
+ font instead of hardcoded color values and deprecated native font name
+
+ * macosx/tkMacOSXHLEvents.c: Factor out common code; formatting.
+
+2008-07-08 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * doc/*.n: Fixed broken line endings from last doc commit.
+
+2008-07-04 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkDefaultTheme.c, generic/ttk/ttkClamTheme.c,
+ * generic/ttk/ttkClassicTheme.c, generic/ttk/ttkElements.c:
+ [Bug 2009213]: Audit: ensure that output arguments to Tk_Get*FromObj()
+ are initialized, in case of erroneous style specifications.
+
+2008-07-02 Donal K. Fellows <dkf@users.sf.net>
+
+ * macosx/tkMacOSXHLEvents.c: Some tidying up of this file. Make sure
+ that failing handling callbacks get reported as background errors.
+
+2008-06-30 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/*.1, doc/*.3, doc/*.n: Remove out of date changebars, make
+ formatting of typedefs consistent, other small changes.
+
+2008-06-25 Don Porter <dgp@users.sourceforge.net>
+
+ *** 8.6a1 TAGGED FOR RELEASE ***
+
+ * changes: Updates for 8.6a1 release.
+
+2008-06-24 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * library/demos/ttkpane.tcl: Work around missing timezones
+ * doc/text.n: [Bug 1997293]: Fix documentation of text tag options.
+
+2008-06-19 Don Porter <dgp@users.sourceforge.net>
+
+ * changes: Updates for 8.6a1 release.
+
+ * generic/tk.h: TIP 285 additions make Tk 8.6 call the new
+ * library/tk.tcl: Tcl_Canceled() routine, available only in Tcl
+ 8.6, so bump our Tcl dependencies to version 8.6. Tk 8.6a1 will no
+ longer [load] into a Tcl 8.5 interp.
+
+ * README: Bump version number to 8.6a1
+ * generic/tk.h:
+ * library/tk.tcl:
+ * unix/configure.in:
+ * unix/tk.spec:
+ * win/configure.in:
+
+ * unix/configure: autoconf-2.59
+ * win/configure:
+
+2008-06-18 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXCarbonEvents.c: Fix debug carbon event tracing.
+ (InstallStandardApplicationEventHandler): Replace needless use of
+ TkMacOSXInitNamedDebugSymbol() by standard TkMacOSXInitNamedSymbol().
+
+ * macosx/tkMacOSXDebug.c: Revert 2007-11-09 commit making
+ * macosx/tkMacOSXDebug.h: TkMacOSXInitNamedDebugSymbol()
+ available outside of debug builds.
+
+ * macosx/tkMacOSXEmbed.c (TkpMakeWindow): Fix bug with missing
+ * macosx/tkMacOSXSubwindows.c (XMapWindow): focus on first map by
+ only sending VisibilityNotify events once windows are mapped (rather
+ than when they are created).
+
+ * macosx/tkMacOSXWindowEvent.c (TkMacOSXProcessWindowEvent): Fix
+ return value.
+
+ * macosx/tkMacOSXInit.c: Add helper to efficiently convert from
+ * macosx/tkMacOSXPrivate.h: CFString to Tcl_Obj.
+
+ * macosx/tkMacOSXFont.c (TkpGetFontFromAttributes, InitFont): Fix
+ incorrect conversion to points of font sizes already in points; factor
+ out retrieval of font family name from font family ID.
+
+2008-06-13 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/configure, win/configure.in (TK_WIN_VERSION): Fix handling of
+ interim a/b versioning for manifest usage.
+
+2008-06-13 Joe Mistachkin <joe@mistachkin.com>
+
+ TIP #285 IMPLEMENTATION
+
+ * generic/tkCmds.c: During [tkwait] and [update], always cooperatively
+ check for script cancellation.
+ * win/makefile.vc: Added 'pdbs' option for Windows build rules to
+ * win/rules.vc: allow for non-debug builds with full symbols.
+
+2008-06-12 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tkPointer.c (Tk_UpdatePointer): [Bug 1991932]: Fix failure
+ to restore a global grab capture and to release the restrict window
+ capture when releasing a button grab. Fixes segfault due to dangling
+ reference to restrict window inside TkpSetCapture() implementation.
+
+ * generic/ttk/ttkTreeview.c: Fix warning.
+
+ * unix/tcl.m4 (SunOS-5.11): Fix 64bit amd64 support with gcc & Sun cc.
+ * unix/configure: autoconf-2.59
+
+ * macosx/tkMacOSXXStubs.c (Tk_ResetUserInactiveTime): Use UsrActivity
+ instead of OverallAct (which may be ignored in some circumstances).
+
+ * macosx/Wish.xcodeproj/project.pbxproj: Add tclIORTrans.c; add tclOO
+ * macosx/Wish.xcodeproj/default.pbxuser: files to tktest-X11 target;
+ add debug configs for 64bit and with corefoundation disabled; updates
+ and cleanup for Xcode 3.1 and for Leopard; sync with Tcl.xcodeproj.
+ * macosx/Wish.xcode/project.pbxproj: Sync Wish.xcodeproj changes.
+ * macosx/Wish.xcode/default.pbxuser:
+ * macosx/README: Document new build configs.
+
+2008-06-10 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/tkUnixKey.c: [Patch 1986818]: Use Xutf8LookupString if
+ available. This should fix problems (like [Bug 1908443]) where Xlib's
+ idea of the system encoding does not match Tcl's.
+
+2008-06-01 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Wish.xcodeproj/project.pbxproj: Add new tclOO files; add
+ * macosx/README: debug configs with gcov;
+ update to Xcode 3.1.
+
+2008-05-27 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * generic/ttk/ttkTheme.c: [ttk::style theme use] without an argument
+ * doc/ttk_style.n: now returns the current theme.
+
+2008-05-23 Joe English <jenglish@users.sourceforge.net>
+
+ * doc/ttk_treeview.n, generic/ttk/ttkTreeview.c,
+ * generic/ttk/ttkTagSet.c, generic/ttk/ttkLayout.c,
+ * generic/ttk/ttkTheme.c, generic/ttk/ttkTheme.h,
+ * generic/ttk/ttkThemeInt.h, generic/ttk/ttkWidget.h:
+ Added [$tv identify region], [$tv identify element], and [$tv identify
+ item] subcommands. Simplified bindings. Added [$tv tag has]
+ subcommand. Tag-related display improvements; setting a tag
+ -background or -foreground no longer overrides selection feedback.
+
+ * library/ttk/altTheme.tcl, library/ttk/aquaTheme.tcl,
+ * library/ttk/clamTheme.tcl, library/ttk/classicTheme.tcl,
+ * library/ttk/defaults.tcl, library/ttk/treeview.tcl,
+ * library/ttk/winTheme.tcl, library/ttk/xpTheme.tcl:
+ Don't need separate 'Item', 'Cell', and 'Row' style settings anymore,
+ only the base "Treeview" style is used.
+
+2008-05-23 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkLabel.c: [Bug 1967576]: Avoid passing width or height
+ <= 0 to Tk_RedrawImage, as this leads to a panic on Windows.
+
+2008-05-16 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * library/ttk/xpTheme.tcl: Add correct border to combobox on Vista
+
+2008-05-15 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/makefile.vc: We should use the thread allocator for threaded
+ * win/rules.vc: builds. Added 'tclalloc' option to disable.
+
+2008-05-14 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkPanedWindow.c (PanedWindowProxyCommand)
+ (DisplayPanedWindow): [Bug 1639824]: Ensure that a zero width never
+ gets fed to the underlying window system.
+
+2008-05-13 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * library/console.tcl: Support pixel sized font in +/- keybinding.
+ * tests/listbox.test: -activestyle default is underline on windows.
+ * tests/winDialog.test: Fixed hanging tk_chooseColor tests.
+
+2008-05-11 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * library/tk.tcl: Support for ttk widgets in AmpWidget
+ * doc/button.n: [Patch 1883418]: Note negative widths for button.
+
+2008-05-09 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * doc/ttk_*: 'identify' widget command is on all ttk widgets.
+
+2008-05-04 Joe English <jenglish@users.sourceforge.net>
+
+ * macosx/ttkMacOSAquaTheme.c: [Bug 1942785]: "default" and "focus"
+ adornments should not be disjoint.
+
+2008-04-27 Donal K. Fellows <dkf@users.sf.net>
+
+ * */*.c: A large tranche of getting rid of pre-C89-isms; if your
+ compiler doesn't support things like proper function declarations,
+ 'void' and 'const', borrow a proper one when building Tcl. (The header
+ files allow building things that link against Tcl with really ancient
+ compilers still; the requirement is just when building Tcl itself.)
+
+2008-04-25 Joe English <jenglish@users.sourceforge.net>
+
+ * library/ttk/treeview.tcl: [Bug 1951733]: [$tv selection] takes a
+ list of items, not a single item.
+
+2008-04-20 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/makefile.vc: [Bug 1900872]: Include ws2_32 in the link list.
+ * doc/menu.n: [Bug 1887169]: Minor change regarding the system menu.
+ * doc/button.n: [Bug 1926223]: Minor clarification of button flash.
+
+2008-04-17 Donal K. Fellows <dkf@cspool38.cs.man.ac.uk>
+
+ * doc/text.n: Correct description of when -relief option is ignored on
+ a tag. Thanks to emiliano for spotting.
+
+2008-04-17 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkCanvas.c: [Bug 1327482]: Fix logic that determines when
+ canvas item <Enter> event should fire. Thanks to Sebastian Wangnick.
+
+2008-04-16 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tkStubInit.c: [Patch 1938497]: Make stubs
+ * generic/tkWindow.c (Initialize): tables static const and export
+ only a module-scope pointer to to the main stubs table (for package
+ init).
+
+2008-04-14 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tkWinDialog.c: [Bug 1941740]: Fix [tk_chooseColor -title].
+ * win/tkWinTest.c: Added parent to testgetwininfo
+ * tests/winDialog.test: Created some tk_chooseColor win tests.
+
+2008-04-09 Jan Nijtmans <nijtmans@users.sourceforge.net>
+
+ * generic/tkImgGIF.c: Let the GIF writer use a real LZW compressor.
+
+2008-04-08 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/ttkWinXpTheme.c: Provide a visual-styles API element engine
+ * tests/ttk/vsapi.test: to permit scripts to create any available
+ * doc/ttk_vsapi.n: windows xp/vista element. Plus basic tests.
+
+2008-04-08 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tkDecls.h: make genstubs (genStubs.tcl changes).
+ * generic/tkIntDecls.h:
+ * generic/tkIntPlatDecls.h:
+ * generic/tkIntXlibDecls.h:
+ * generic/tkPlatDecls.h:
+
+2008-04-08 Kevin Kenny <kennykb@acm.org>
+
+ * tkWinEmbed.c: Removed #if 0 code. Trust the revision control
+ system, if you need it again, you can find it.
+
+ * tkWinSend.c: Added conditional compilation to silence several
+ compiler warnings.
+
+2008-04-07 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkWindow.c (Initialize): [Bug 1937135]: Fix double-free on
+ * tests/main.test (main-3.*): Tk_ParseArgv error.
+
+ * generic/tkArgv.c: Fix -help mem explosion. [Bug 1936238] (kenny)
+
+2008-04-04 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * library/ttk/sizegrip.tcl: Don't resize if the toplevel is not
+ resizable or the sizegrip has been disabled.
+
+2008-04-03 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/makefile.vc: Fixed stubs usage
+ * library/ttk/xpTheme.tcl: fix the colour of labelframe in xp
+
+2008-04-02 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tk.decls: Remove 'export' declarations of symbols now
+ only in libtkstub and no longer in libtk.
+
+ * generic/tkStubLib.c: [Bug 1819422]: Make symbols in libtkstub.a
+ MODULE_SCOPE to avoid exporting them from
+ libraries that link with -ltkstub; constify
+ tk*StubsPtr and stub table hook pointers.
+
+ * generic/tkStubLib.c: Undef USE_TCL_STUBS before defining it
+ * generic/ttk/ttkStubLib.c: unconditionally; remove needless #ifdef
+
+ * generic/tkDecls.h: make genstubs
+ * generic/tkIntDecls.h:
+ * generic/tkIntPlatDecls.h:
+ * generic/tkIntXlibDecls.h:
+ * generic/tkPlatDecls.h:
+ * generic/tkStubInit.c:
+
+ * unix/configure.in (Darwin): Remove now unnecessary unexporting of
+ libtclstub symbols from libtk.
+
+ * unix/configure: autoconf-2.59
+
+2008-04-01 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkStubLib.c (Tk_InitStubs): Added missing error
+ * generic/tkWindow.c (Tk_PkgInitStubsCheck): message and removed
+ needless #ifdef complexity.
+
+ * generic/tkWindow.c: [Tcl Bug 1819422]: Revised package init so
+ * unix/Makefile.in: that "tkStubsPtr" is not present in libtk.so,
+ * win/Makefile.in: but is present only in libtkstub.a. This
+ * win/makefile.bc: tightens up the rules for users of the stubs
+ * win/makefile.vc: interfaces.
+
+ * README: Bump version number to 8.6a0
+ * generic/tk.h:
+ * library/tk.tcl:
+ * macosx/Wish-Common.xcconfig:
+ * unix/configure.in:
+ * unix/tk.spec:
+ * win/README:
+ * win/configure.in:
+ * win/tcl.m4:
+
+ * unix/configure: autoconf-2.59
+ * win/configure:
+
+ * generic/tkConsole.c: Relax Tcl_InitStubs() calls so that a Tk 8.6
+ * generic/tkMain.c: might [load] into a Tcl 8.5 interp.
+ * generic/tkWindow.c:
+
+ * generic/tkDecls.h: make genstubs
+ * generic/tkIntDecls.h:
+ * generic/tkIntPlatDecls.h:
+ * generic/tkIntXlibDecls.h:
+ * generic/tkPlatDecls.h:
+
+2008-03-28 Don Porter <dgp@users.sourceforge.net>
+
+ *** 8.5.2 TAGGED FOR RELEASE ***
+
+ * README: Bump to 8.5.2 for release.
+ * generic/tk.h:
+ * library/tk.tcl:
+ * unix/configure.in:
+ * unix/tk.spec:
+ * win/configure.in:
+
+ * unix/configure: autoconf-2.59
+ * win/configure:
+
+ * changes: Updates for 8.5.2 release.
+
+2008-03-27 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/safetk.tcl (::safe::tkInterpInit): Make sure tk_library and
+ its subdirs (eg, ttk) are on the "safe" access path.
+
+2008-03-27 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/tcl.m4 (SunOS-5.1x): [Bug 1921166]: Fix 64bit support for Sun
+ cc.
+
+ * unix/configure: autoconf-2.59
+
+2008-03-27 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/ttk/ttkStubLib.c: Ensure tcl stubs are used in libtkstub
+ even in a static build of Tk.
+ * generic/ttk/ttkDecls.h: Fix incorrect number of arguments in
+ Ttk_InitStubs macro definition.
+
+2008-03-26 Don Porter <dgp@users.sourceforge.net>
+
+ * changes: Updates for 8.5.2 release.
+
+ * unix/tkUnixCursor.c: [Bug 1922466]: Stop crash in [. configure
+ -cursor] on X11. Thanks to Emiliano Gavilán.
+
+2008-03-26 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/tkInt.h, generic/tkEvent.c, unix/tkUnixEvent.c,
+ * unix/tkUnixKey.c: XIM reorganization and cleanup; see
+ [Patch 1919791] for details.
+
+2008-03-21 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/tk.decls, generic/ttk/ttkStubLib.c, unix/Makefile.in:
+ [Bug 1920030]: Keep ttkStubLib.o in libtkstub instead of libtk.
+
+2008-03-20 Donal K. Fellows <dkf@users.sf.net>
+
+ * tests/wm.test: Rewrote so that tests clean up after themselves
+ rather than leaving that to the following test. Makes it easier to
+ catch problems where they originate. Inspired by [Bug 1852338]
+
+2008-03-19 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/GetClrmap.3: [Bug 220809]: Documented Tk_PreserveColormap.
+
+2008-03-17 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/Makefile.in, win/Makefile.in, win/makefile.vc: [Bug 1863007]:
+ Put ttkStubLib.o in libtkstub instead of libtk.
+
+2008-03-16 Donal K. Fellows <dkf@users.sf.net>
+
+ * library/demos/goldberg.tcl: [Bug 1899664]: Made work when run twice
+ in the same session. Also made the control panel use Ttk widgets.
+
+2008-03-13 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/configure.in: [Bug 1913622]: Use backslash-quoting instead of
+ * unix/tcl.m4: double-quoting for lib paths in tkConfig.sh.
+ * unix/configure: autoconf-2.59
+
+2008-03-13 Don Porter <dgp@users.sourceforge.net>
+
+ * changes: Updates for 8.5.2 release.
+
+2008-03-12 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Wish.xcodeproj/project.pbxproj: Add support for Xcode 3.1
+ * macosx/Wish.xcodeproj/default.pbxuser: CODE_SIGN_IDENTITY and
+ * macosx/Wish-Common.xcconfig: 'xcodebuild install'.
+
+2008-03-12 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/tkUnixRFont.c: Try a fallback font if XftFontOpenPattern()
+ fails in GetFont (workaround for [Bug 1090382]).
+
+2008-03-11 Daniel Steffen <das@users.sourceforge.net>
+
+ * library/demos/knightstour.tcl: Aqua GOOBE.
+ * library/demos/widget:
+
+ * macosx/Wish.xcodeproj/project.pbxproj: Add support for Xcode 3.1 and
+ * macosx/Wish.xcodeproj/default.pbxuser: configs for building with
+ * macosx/Wish-Common.xcconfig: gcc-4.2 and llvm-gcc-4.2.
+
+ * generic/tkCanvUtil.c: Fix gcc-4.2 warnings.
+
+ * macosx/GNUmakefile: Fix quoting to allow paths to
+ * macosx/Wish-Common.xcconfig: ${builddir}, ${INSTALL_ROOT}
+ * unix/Makefile.in: and ${TCL_BIN_DIR} to contain
+ * unix/configure.in: spaces.
+ * unix/install-sh:
+ * unix/tcl.m4:
+
+ * unix/configure: autoconf-2.59
+
+ * unix/Makefile.in (install-strip): Strip non-global symbols from
+ dynamic library.
+
+2008-03-10 Don Porter <dgp@users.sourceforge.net>
+
+ * changes: Updates for 8.5.2 release.
+
+2008-03-07 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/colors.n: Reworked to produce nicer HTML output.
+
+2008-03-06 Joe English <jenglish@users.sourceforge.net>
+
+ * doc/ttk_notebook.n: [Bug 1882011]: Move "TAB IDENTIFIERS" section
+ above "WIDGET COMMAND" section.
+
+2008-02-29 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * library/demos/widget: Added a Knight's tour canvas demo.
+ * library/demos/knightstour.tcl:
+
+2008-02-27 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXDraw.c: Workaround leak in Carbon SetPortPenPixPat()
+ API [Bug 1863346]; avoid repeated PixPat allocation/deallocation.
+
+2008-02-23 Joe English <jenglish@users.sourceforge.net>
+
+ * library/ttk/combobox.tcl, doc/ttk_combobox.n,
+ * tests/ttk/combobox.test: Arrange to deliver <<ComboboxSelected>>
+ event after listbox is unposted, as intended [Bug 1890211]. Clarified
+ documentation.
+
+2008-02-23 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkPanedWindow.c: [FRQ 1898288]: Don't enforce minimum
+ sash thickness of 5 pixels, just use 5 as a default.
+
+2008-02-14 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * unix/README: Documented missing configure flags.
+
+2008-02-06 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/ttk_scale.n (new file): [Bug 1881925]: Added basic documentation
+
+2008-02-04 Don Porter <dgp@users.sourceforge.net>
+
+ *** 8.5.1 TAGGED FOR RELEASE ***
+
+ * generic/tk.h: Bump to 8.5.1 for release.
+ * library/tk.tcl:
+ * unix/configure.in:
+ * unix/tk.spec:
+ * win/configure.in:
+
+ * unix/configure: autoconf-2.59
+ * win/configure:
+
+2008-02-04 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/MeasureChar.3, doc/FontId.3: Minor improvements (formatting,
+ keywords).
+
+2008-02-02 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Wish-Info.plist.in: Add CFBundleLocalizations key, listing
+ * unix/configure.in (Darwin): all library/msgs locales.
+
+ * unix/configure.in (Darwin): Correct Info.plist year substitution
+ in non-framework builds.
+
+ * unix/configure: autoconf-2.59
+
+2008-02-01 Don Porter <dgp@users.sourceforge.net>
+
+ * changes: Updates for 8.5.1 release.
+
+2008-02-01 Reinhard Max <max@suse.de>
+
+ * generic/tkImgGIF.c: Fixed a buffer overflow (CVE-2008-0553).
+ * tests/imgPhoto.test: Added a test for the above.
+
+2008-01-31 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/msgbox.tcl (::tk::MessageBox): Don't use ttk::label in low
+ depth/aqua fallback, as it doesn't support -bitmap.
+
+ * win/tkWinDialog.c (Tk_MessageBoxObjCmd): [Bug 1881892]: Pass ""
+ instead of NULL when -title isn't set.
+
+2008-01-31 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/panedwindow.n: Added proper description of -height and -width
+ options, which aren't "standard". Last of fallout from [Bug 1882495].
+
+2008-01-30 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/canvas.n, doc/listbox.n, doc/message.n: [Bug 1882495]: Fix
+ erroneous listing of "standard" options.
+
+2008-01-29 Joe English <jenglish@users.sourceforge.net>
+
+ * library/treeview.tcl: Fix bug in Shift-ButtonPress-1 binding (error
+ if no current focus item; reported on c.l.t.)
+
+2008-01-29 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/ttk_*.n: [Bug 1876493]: Adjusted handling of the standard
+ options part of the Ttk manual pages so that they are documented in
+ the correct location.
+
+2008-01-28 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/tkUnixRFont.c: Re-fix strict-aliasing warnings reintroduced by
+ last patch.
+
+2008-01-27 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkNotebook.c: [Bug 1878298]: Make sure to schedule a
+ redisplay when adding and/or hiding tabs.
+
+2008-01-27 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/tkUnixRFont.c: Merged common code from InitFont() and
+ TkpGetFontAttrsForChar(), factored into GetTkFontAttributes() and
+ GetTkFontMetrics(). Removed write-only struct UnixFtFont member
+ 'drawable'. Removed unneeded double-pointer indirections. Ensure that
+ TkFontAttributes.family member is a Tk_Uid, as specified. Use
+ FcTypeDouble for XFT_SIZE attribute. Finally: fix [Bug 1835848]
+
+2008-01-25 Don Porter <dgp@users.sourceforge.net>
+
+ * changes: Updates for 8.5.1 release.
+
+2008-01-08 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkFrame.c: [Bug 1867122]: fix crash in
+ [ttk::labelframe] when -style option specified.
+
+2008-01-08 Joe English <jenglish@users.sourceforge.net>
+
+ * win/ttkWinTheme.c: [Bug 1865898]: Add tristate support to
+ checkbuttons and radiobuttons.
+ [Bug 1679067]: Fix check and radio indicator size.
+
+2008-01-06 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkWidget.c, generic/ttk/ttkWidget.h: Call
+ Tk_MakeWindowExist() in widget constructor. Removed now-unnecessary
+ initial ConfigureNotify processing.
+
+2008-01-06 Joe English <jenglish@users.sourceforge.net>
+
+ * library/ttk/treeview.tcl, library/ttk/utils.tcl:
+ [Bugs 1442006, 1821939, 1862692]: Fix MouseWheel bindings for
+ ttk::treeview widget.
+
+2008-01-02 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tk.h: Bump version number to 8.5.1b1 to distinguish
+ * library/tk.tcl: CVS development snapshots from the 8.5.0 and
+ * unix/configure.in: 8.5.1 releases.
+ * unix/tk.spec:
+ * win/configure.in:
+
+ * unix/configure: autoconf (2.59)
+ * win/configure:
+
+ ******************************************************************
+ *** CHANGELOG ENTRIES FOR 2005 TO 2007 IN "ChangeLog.2007" ***
+ *** CHANGELOG ENTRIES FOR 2004 AND 2003 IN "ChangeLog.2004" ***
+ *** CHANGELOG ENTRIES FOR 2002 AND EARLIER IN "ChangeLog.2002" ***
+ ******************************************************************
diff --git a/tk8.6/ChangeLog.2002 b/tk8.6/ChangeLog.2002
new file mode 100644
index 0000000..b523e7d
--- /dev/null
+++ b/tk8.6/ChangeLog.2002
@@ -0,0 +1,7877 @@
+2002-12-27 David Gravereaux <davygrvy@pobox.com>
+
+ * generic/tkText.h: ANSI unfriendly typedef for TkTextBTree
+ repaired for C++ compilers.
+
+2002-12-27 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/tkUnixWm.c (WaitForEvent): process Map and Unmap events
+ as well as Configure events during WaitFor{Configure|Map}Notify.
+ Fixes [Bug 578569] (WaitForMapNotify could process Map and Unmap
+ events out of order, making Tk think a window was unmapped when
+ it really wasn't).
+
+2002-12-18 Todd M. Helfter <tmh@purdue.edu>
+
+ * doc/label.n: Fixed documentation of the -compound option to
+ the label widget. The option was simply missing from the
+ man page [Bug 577540]
+
+2002-12-17 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/photo.n: Fixed documentation of the put subcommand to no
+ longer talk about files and to mention that you can use colour
+ names for working with solid colours. [Bug 640026]
+
+2002-12-13 Don Porter <dgp@users.sf.net>
+
+ * generic/tkMain.c (Tk_Main): Call on Tcl*StartupScript*() routines
+ to store the startup script, if any. [Bug 616245].
+
+2002-12-10 David Gravereaux <davygrvy@pobox.com>
+
+ * win/makefile.vc: tclThreadTest.obj not required to link
+ tktest.exe [Bug 651396]
+
+2002-12-08 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkEntry.c (ConfigureEntry): keep a flag to indicate when
+ a var is traced to prevent double-traces caused by configuring the
+ widget in traces with validation on. (dejong)
+
+2002-12-07 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkInt.decls: add TkWinSetHINSTANCE decl
+ * generic/tkIntPlatDecls.h: regen
+ * generic/tkStubInit.c: regen
+ * win/tkWinInit.c (TkpInit): While init and cleanup aren't correct
+ * win/tkWinX.c (TkWinXInit): in DllMain, we had to specify the
+ * win/tkWin32Dll.c (DllMain): true HINSTANCE or the resources of a
+ dynamic Tk weren't being loaded correctly. Created a new function
+ TkWinSetHINSTANCE for this purpose.
+
+2002-12-06 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinX.c (TkWinXInit): Move cleanup into an exit handler
+ * win/tkWin32Dll.c (DllMain): to ensure that it will be called
+ * win/tkWinWm.c (TkWinWmCleanup): without having to unload the dll.
+ Also reset the static int initialized on cleanup to allow reinit.
+
+2002-12-01 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * tests/event.test (_keypress, _text_ind_to_x_y): Force focus to
+ widget in _keypress method to avoid problems with window managers
+ that use focus follows mouse. [Bug 526209]
+
+2002-12-01 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * tests/wm.test: Add wm-transient-6.3 to check that a transient
+ remains withdrawn when it is first withdrawn and then turned into
+ a transient.
+ * unix/tkUnixWm.c:
+ * win/tkWinWm.c: Replace WM_TRANSIENT_WITHDRAWN with WM_WITHDRAWN
+ and set this flag whenever a window is explicitly withdrawn. This
+ fixes the test case added above. [Bug 644356]
+
+2002-11-22 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * tests/textDisp.test:
+ * generic/tkTextDisp.c (TkTextSeeCmd): handle see for unmapped
+ text displays. [Bug #641778]
+
+2002-11-19 Jim Ingham <jingham@apple.com>
+
+ * macosx/tkMacOSXScrlbr.c (TkpDisplayScrollbar): If the
+ scrollbar width is set to 12 or less (but 12 is what you
+ should use) use the small metric scrollbar.
+
+ (UpdateControlValues): Fix thinko in setting off AUTO_ADJUST for
+ the place geometry manager.
+
+2002-11-19 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/Makefile.in: add macosx/*.tcl (buildTkConfig.tcl in
+ particular) to the dist target.
+
+2002-11-14 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tkWindow.c (Tk_DestroyWindow, DeleteWindowsExitProc):
+ Add TkHalfdeadWindow type and halfdeadWindowList to keep track of
+ windows that were only partially deallocated before a call to
+ exit. Finish cleaning up these windows in DeleteWindowsExitProc.
+ Keep track of cleanup status in Tk_DestroyWindow so that a window
+ with a Destroy binding which calls exit will get fully destroyed.
+ * tests/window.test: Add Tk_DestroyWindow tests for an assortment
+ of half dead window cases. [Bug 630533]
+
+2002-11-10 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Wish.pbproj/project.pbxproj: fixed erroneous
+ removal of libtkstub before Wish was built.
+
+2002-11-07 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * tests/unixWm.test: Add short delay to test unixWm-51.7
+ to account for raise/lower changes in TIP 107. This allows
+ the test case to pass under Window Maker on Linux.
+
+2002-11-07 Peter Spjuth <peter.spjuth@space.se>
+
+ * tests/place.test:
+ * generic/tkPlace.c: place info did not return all settings,
+ and didn't make sure the result was a proper list.
+ Put '-in' first in result to be more consistent with how
+ grid/pack info behaves. [Bug #635025][Bug #532022]
+
+2002-11-07 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/Makefile.in: added macosx/README to dist target.
+ * macosx/Wish.pbproj/project.pbxproj: fix to 'wish' script
+ to allow it to work when not installed into '/'.
+
+2002-11-06 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure: Regen.
+ * unix/tcl.m4: Update from Tcl.
+ * win/configure: Regen.
+ * win/configure.in: Check that AR, RANLIB, and RC
+ are found on the path when building with gcc.
+
+2002-11-04 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Wish.pbproj/project.pbxproj: added Wish linker flag
+ -headerpad_max_install_names to allow use of 'install_name_tool'.
+ fixed tkConfig.sh generation and redo_prebinding in the case where
+ Tk is not installed alongside Tcl.
+
+2002-11-03 David Gravereaux <davygrvy@pobox.com>
+
+ * win/winMain.c (Tcl_AppInit): Calls Registry_Init() and
+ Dde_Init() when STATIC_BUILD and TCL_USE_STATIC_PACKAGES macros
+ are set.
+
+ * win/makefile.vc: linkexten option now sets the
+ TCL_USE_STATIC_PACKAGES macro which also adds the registry and
+ dde static lib files to the link of the shell. [Patch 479697]
+
+ * win/rules.vc: Matches the one from Tcl.
+
+ * win/buildall.vc.bat: More useful commentary.
+
+2002-11-01 Andreas Kupries <andreask@activestate.com>
+
+ * win/makefile.vc (TCLREGLIBNAME): Updated to registry 1.1.
+
+2002-10-29 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/README: added info on new package searching in
+ Frameworks directories.
+
+2002-10-22 Jeff Hobbs <jeffh@ActiveState.com>
+
+ *** 8.4.1 TAGGED FOR RELEASE ***
+
+ * changes: updated for 8.4.1 release
+
+2002-10-21 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/README: revised according to Jim's suggestions
+ * macosx/tkMacOSXAppInit.c: use standard PATH_MAX from <limits.h>
+
+2002-10-18 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/winMain.c (WinMain, main): remove obsolete SetMessageQueue call
+
+ * win/configure: Regen.
+ * win/tcl.m4 (SC_CONFIG_CFLAGS): Check for bug in Cygwin version
+ of windres and work around that case by passing a POSIX path
+ instead of a Windows native path. One can't always pass a POSIX
+ path because the mingw native toolchain accepts only Windows
+ native paths. (dejong)
+
+ * win/tkWinPort.h: define OPEN_MAX only if not defined.
+ [Patch #625472] (howell)
+
+2002-10-18 Daniel Steffen <das@users.sourceforge.net>
+
+ * mac/tkMacAppInit.c: removed tcltest dependency.
+ [Bug #592639] (porter)
+
+2002-10-17 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * tests/imgPhoto.test:
+ * generic/tkImgPhoto.c (ImgPhotoConfigureMaster): fix arg handling
+ for missing -format or -data options. [Bug #624974]
+
+ * tests/text.test: properly return the number of
+ * unix/tkUnixFont.c (ControlUtfProc): bytes consumed. [Bug #624732]
+
+2002-10-17 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/README: info specific to building and running
+ TclTk on Mac OS X, answers to tcl-mac list FAQs.
+ * macosx/Makefile: permission fix after embedded install.
+ * macosx/Wish.pbproj/project.pbxproj: after install, fix
+ permissions of uninstalled products.
+
+2002-10-17 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Wish.pbproj/project.pbxproj: added TEXT document
+ type to plist so that files can be dragged onto Wish Shell.
+
+ * macosx/tkMacOSXInt.h:
+ * macosx/tkMacOSXInit.c:
+ * macosx/tkMacOSXFont.c: added private proc
+ TkMacOSXUseAntialiasedText() to enable/disable quickdraw
+ text antialiasing where available, default is enabled.
+ Added a linked boolean ::tk::mac::antialiasedtext with
+ write trace to allow control of antialiasing from tcl.
+
+2002-10-16 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * macosx/tkMacOSXMenu.c: fix to accelerators shown in menus
+ with non-alphanumeric keys.
+ * macosx/tkMacOSXKeyEvent.c:
+ * macosx/tkMacOSXKeyboard.c: applied first patch from [Patch
+ #622582] to fix some of [Bug #616988]. Further work is needed
+ in this area, but this will let foreign keyboards at least work
+ reasonably with Tk.
+
+2002-10-15 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/configure:
+ * unix/tcl.m4: add AIX-5 ppc build support. Remove unused
+ SC_ENABLE_MEMDEBUG.
+
+ * win/configure:
+ * win/tcl.m4: Add --enable-shared=mem support.
+
+2002-10-10 Peter Spjuth <peter.spjuth@space.se>
+
+ * tests/grid.test:
+ * generic/tkGrid.c: The grid size was not updated properly
+ when removing a widget from a grid. [Bug #621241] (forssen)
+
+2002-10-10 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * tests/canvPs.test: tests for canvas embedded window ps generation
+ * generic/tkCanvWind.c (CanvasPsWindow): removed dead code loop.
+ * generic/tkCanvas.h: moved TkColormapData struct to tkCanvPs.c
+ * generic/tkCanvPs.c (TkImageGetColor): corrected bogus use of
+ TkColormapData on Windows (Windows now requires RGB pixel data
+ from image).
+ * win/tkWinImage.c (XGetImage, XGetImageZPixmap): added support
+ for generating ps for embedded widgets on canvases on Windows,
+ tested for 8, 16, 24 and 32-bit depths (XGetImageZPixmap not used).
+
+ * library/tk.tcl: simplified the adding of extra <ISO_Left_Tab>
+ and <hpBackTab> events to <<PrevWindow>>.
+
+2002-10-09 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/README: doc'ed --enable-symbols options.
+ * unix/Makefile.in: comment docs
+ * unix/configure: regen
+ * unix/tcl.m4: replaced SC_ENABLE_MEMDEBUG with a more intelligent
+ SC_ENABLE_SYMBOLS that takes yes|no|mem|all as options now.
+
+2002-10-09 Don Porter <dgp@users.sf.net>
+
+ * generic/tk.h: Added reminder comment to edit
+ macosx/Wish.pbproj/project.pbxproj when version number changes.
+
+2002-10-09 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Makefile: don't remove tclsh after building embedded.
+
+ * macosx/Wish.pbproj/project.pbxproj: bumped version to 8.4.1;
+ added missing library/mkpsenc.tcl to framework.
+
+2002-10-09 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tkInt.decls(tkIntXlib): added XQueryTree declaration for
+ mac & aqua, since it's now called from ParentXId via Tk_HandleEvent.
+ * generic/tkIntXlibDecls.h:
+ * generic/tkStubInit.c: regen.
+ * mac/tkMacXStubs.c: added XQueryTree stub
+
+ * mac/tkMacEmbed.c (TkpUseWindow): check that container window
+ has -container option set (sync with other platforms).
+
+ * mac/tkMacBitmap.c:
+ * mac/tkMacFont.c:
+ * mac/tkMacSend.c:
+ * mac/tkMacTest.c:
+ * mac/tkMacWm.c: CONSTification.
+
+ * mac/tkMacProjects.sea.hqx: added tkStyle.c and tkUndo.c to
+ tk library projects.
+
+2002-10-09 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tkImgPhoto.c (ImgPhotoSetSize): Only error-out if we
+ fail to allocate a non-empty buffer; getting a NULL when we
+ allocate an empty buffer is no problem since nothing will look at
+ the value anyway. [Bug 619544]
+ Also tidied up file to take into account the fact that we're using
+ 32 bits per pixel in the master to accommodate the alpha channel
+ as well as RGB.
+
+2002-10-08 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * tests/winButton.test: add option clear to top to prevent option
+ leakage from other tests causing problems. [Bug #582382]
+
+ * generic/tkPanedWindow.c (Tk_PanedWindowObjCmd): leave the
+ DestroyPanedWindow proc to free the pwPtr, add a Preserve
+ reference to the pwPtr->tkwin.
+ (DestroyPanedWindow): Release the pwPtr->tkwin.
+
+ * generic/tkFocus.c (TkFocusFilterEvent): Ignore event if we are
+ focusing into a dead window. [Bug #588831] (griffin)
+
+2002-10-02 Jim Ingham <jingham@apple.com>
+
+ * macosx/tkMacOSXScrlbr.c (TkpDisplayScrollbar): Put the Tk scrollbar
+ pointer into the control reference data for the Mac scrollbar, so we
+ can get it out again in the ScrollbarActionProc.
+
+2002-10-02 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkText.c (TextBlinkProc): don't blink the cursor unless
+ it is visible. [Bug #616791] [Patch #614474] (bonfield)
+
+ * tests/entry.test: added entry-20.7
+ * generic/tkEntry.c (EntryTextVarProc): check if the entry is
+ being deleted before handling an associated textvariable.
+ [Bug #607390 #617446]
+
+2002-10-01 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/unixSelect.test (unixSelect-1.1[89]): Altered these tests
+ to work around [Bug #616923]
+ * unix/tkUnixSelect.c (SelRcvIncrProc,TkSelPropProc): It turns out
+ a much simpler and more robust solution is possible if we leverage
+ Tcl's encoding engine by using the same code path as for the
+ normal string selection. It might be a bit slower, but it should
+ be a lot more correct. [Bug #614650]
+
+2002-09-30 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * tests/panedwindow.test: added panedwindow-28.[12]
+ * generic/tkPanedWindow.c (PanedWindowCmdDeletedProc):
+ (Tk_PanedWindowObjCmd): when destroying the panedwindow, destroy
+ the proxy before the parent to avoid dependency conflicts.
+ [Bug #616589]
+
+2002-09-30 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/unixSelect.test: Test for various things that can fail to
+ work in 8.4.0...
+ * unix/tkUnixSelect.c (TkSelPropProc,SelRcvIncrProc): Incremental
+ transfers of UTF8_STRING selections should now work; Tk will now
+ tag them with the right size and only transfer complete UTF8
+ characters. Previously, things only worked when the transfer
+ could only happen in one go, and even then not always. [Bug 614650]
+
+ * doc/bind.n: Doc-fix to mention that %A substitutes UNICODE
+ characters rather than ASCII ones. Tk's done this ever since 8.1
+ in any case; after all, it is the right thing to do.
+
+2002-09-27 Don Porter <dgp@users.sf.net>
+
+ * README: Bumped to version 8.4.1 to avoid confusion
+ * generic/tk.h: of CVS snapshots with release 8.4.0.
+ * unix/README:
+ * unix/configure.in:
+ * unix/tk.spec
+ * win/configure.in:
+
+ * unix/configure: autoconf
+ * win/configure:
+
+2002-09-26 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/configure: regen.
+ * unix/tcl.m4: improve AIX-4/5 64bit compilation support.
+
+ * unix/Makefile.in: add macosx subdir to dist target.
+ Do not generate .Z, only .gz and .zip in alldist target.
+
+2002-09-18 Mumit Khan <khan@nanotech.wisc.edu>
+
+ Added basic Cygwin support.
+
+ * win/tcl.m4 (SC_PATH_TCLCONFIG): Support one-tree build.
+ (SC_PATH_TKCONFIG): Likewise.
+ (SC_PROG_TCLSH): Likewise.
+ (SC_CONFIG_CFLAGS): Assume real Cygwin port and remove -mno-cygwin
+ flags. Add -mwin32 to extra_cflags and extra_ldflags.
+ Remove ``-e _WinMain@16'' from LDFLAGS_WINDOW.
+ * win/configure: Regenerate.
+
+ * win/tkWinPort.h (tchar.h): Do not include on Cygwin.
+ (_T): Define for Cygwin.
+ * win/winMain.c (main): Conditionally define.
+
+2002-09-26 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Makefile: preserve environment value of INSTALL_ROOT.
+ When embedding only use deployment build. Force relink before
+ embedded build to ensure new linker flags are picked up.
+
+ * macosx/buildTkConfig.tcl (new):
+ * macosx/Wish.pbproj/project.pbxproj: synthesize tkConfig.sh
+ based on tclConfig.sh in Tcl.framework and tkConfig.sh.in.
+ Add symbolic links to debug lib, stub libs and tkConfig.sh
+ in framework toplevel. Made tkIntXlibDecls.h a public header
+ since Headers/X11/Xlib.h includes it. Install wish8.4 script
+ that runs "Wish Shell.app" and corresponding wish link.
+ Use tcl headers from built Tcl.framework instead of from tcl
+ source directory.
+
+ * macosx/tkMacOSXPort.h: added missing standard unix includes
+ and defines, similarly to tkUnixPort.h.
+ * macosx/tkMacOSXNotify.c: removed dependency on internal tcl
+ header "tclPort.h"
+
+ * unix/Makefile.in:
+ * unix/install-sh: copied support for 'install-strip' target
+ over from tcl/unix/{Makefile.in,install-sh}
+
+2002-09-22 Jim Ingham <jingham@apple.com>
+
+ * macosx/tkMacOSXScrlbr.c (UpdateControlValue): HiliteControl
+ doesn't give the proper "nothing to scroll" look on Mac OS X.
+ You have to set the min value greater than the max value to
+ get this.
+
+2002-09-15 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure: Regen.
+ * unix/tcl.m4: Update from Tcl.
+ * unix/tkUnixEvent.c (TkpCloseDisplay): Use PEEK_XCLOSEIM
+ to examine the input context queue before invoking
+ XCloseIM. Generate an assert if there is an input
+ context that has not been freed.
+ [Patch 570902]
+
+2002-09-13 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * generic/tk.h: Moved RC_INVOKED down so that tcl.h is still
+ included when running the resource compiler. <tcl.h> excludes the
+ unnecessary parts on its own. This reenables the Windows build. It
+ failed because the non-inclusion of tcl.h caused the resource
+ compiler to miss some vital macro definitions (TCL_FINAL_RELEASE,
+ STRINGIFY, ...).
+
+2002-09-12 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tk.h:
+ * mac/tkMacApplication.r:
+ * mac/tkMacLibrary.r:
+ * mac/tkMacResource.r:
+ * macosx/tkAboutDlg.r:
+ * macosx/tkMacOSXApplication.r:
+ * macosx/tkMacOSXLibrary.r:
+ * macosx/tkMacOSXResource.r: unified use of the two equivalent
+ resource compiler header inclusion defines RC_INVOKED and
+ RESOURCE_INCLUDED, now use RC_INVOKED throughout.
+
+ * macosx/tkMacOSXAppInit.c: improved detection of Wish startup
+ by the finder (by checking if stdin is /dev/null), in which
+ case we want to bring up the Tk console window.
+
+ * macosx/tkMacOSXHLEvents.c: added 'rapp' apple event handler.
+
+2002-09-12 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Wish.pbproj/project.pbxproj: reference & install
+ tk/generic/prolog.ps instead of tk/library/prolog.ps.
+
+2002-09-10 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Wish.pbproj/project.pbxproj: added backwards
+ compatibility for OSX 10.1 ProjectBuilder 2.0.
+
+2002-09-10 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/Makefile.in: added DYLIB_INSTALL_DIR variable for Darwin
+ and set it to default value ${LIB_RUNTIME_DIR}
+ * unix/tcl.m4 (Darwin): use DYLIB_INSTALL_DIR instead of
+ LIB_RUNTIME_DIR in the -install_name argument to ld.
+ * unix/configure: regen.
+
+ * macosx/Wish.pbproj/project.pbxproj:
+ * macosx/Makefile: added support for building Tcl as an embedded
+ framework, i.e. using an dyld install_name containing
+ @executable_path/../Frameworks via the new DYLIB_INSTALL_DIR
+ unix/Makefile variable.
+
+2002-09-10 Jeff Hobbs <jeffh@ActiveState.com>
+
+ *** 8.4.0 TAGGED FOR RELEASE ***
+
+2002-09-09 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * macosx/tkMacOSXNotify.c (Tk_MacOSXSetupTkNotifier): corrected
+ Mac Jaguar event loop issue.
+
+ * library/tk.tcl: use command instead of control on Aqua bindings.
+ Force dialogs to appear below fixed native Mac menubar.
+ * macosx/tkMacOSXKeyEvent.c:
+ * macosx/tkMacOSXKeyboard.c: Keypress/release events for pure
+ modifier keys were not being passed to Tk.
+ Deadkey presses were inserting null characters into text windows.
+ Now they do nothing. (Still not ideal, but better than before!)
+ * macosx/tkMacOSXMenu.c: Allow more than 200 menus to exist -
+ increased to 2000.
+ * macosx/tkMacOSXMouseEvent.c: Bad interactions between floating
+ windows and ordinary ones. Ensure that local<->global coordinate
+ transformations are wrt to the correct window.
+ * macosx/tkMacOSXWm.c: Better error msg for 'wm attributes'.
+ Remove crash in 'wm transient'.
+ Add 'noActivates' and 'noUpdates' flags to unsupported command.
+ [Patch #606658] (darley)
+
+ * library/xmfbox.tcl (::tk::MotifFDialog_ActivateSEnt): corrected
+ msgcat code with XPG specifier. [Patch #606719] (miller)
+
+2002-09-06 Don Porter <dgp@users.sf.net>
+
+ * tests/unixWm.test (unixWm-50.3): Constrained test that hangs
+ on Windows.
+
+2002-09-05 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Wish.pbproj/project.pbxproj: added overlooked missing
+ TK_PATCH_LEVEL version bump to 8.4.0.
+
+2002-09-04 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * win/Makefile.in (install-libraries): Added code section to
+ install the message catalogs. Copied same section from
+ unix/Makefile.in and adapted it to the slightly different
+ environment.
+
+2002-09-03 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/button.tcl: further restrict buttons to not resetting
+ the "original" relief if it has changed in the interim. This
+ prevents code that simulated overrelief buttons from not working
+ in 8.4. [Bug #604270]
+
+2002-09-03 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Wish.pbproj/project.pbxproj: Bumped version number to
+ 8.4.0 and updated copyright info.
+
+2002-09-03 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * macosx/tkMacOSXWm.c: fix to 'wm attributes' error-handling bug.
+
+2002-09-03 Don Porter <dgp@users.sf.net>
+
+ * changes: Updated for 8.4.0 release
+
+2002-09-02 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * tests/cursor.test: reverted 2002-08-31 change for OS X to use
+ 'heart' cursor because 'arrow' on windows has a pre-skewed use
+ count. [Bug #602667]
+
+ * tests/button.test: added button-14.1
+ * win/tkWinButton.c (TkpComputeButtonGeometry): correct Win button
+ sizing to be equal for one-line buttons with -height of 0 or 1, as
+ well as -height 0 buttons with empty text and no image, which
+ should be the same as single-line text buttons. [Bug #565485]
+
+ * library/button.tcl (::tk::ButtonLeave): correctly restore state
+ of button to normal for unix bindings. [Bug #597920]
+
+ * doc/tk.n: added tk windowingsystem docs.
+
+ * tests/wm.test:
+ * unix/tkUnixWm.c: remove possible 2-second delay in 'raise'.
+ [Patch #601518] (english) TIP #107
+
+ * unix/tcl.m4: add support for 64-bit builds on HP-11 with gcc.
+ * unix/configure.in: make sure to substitute LD_LIBRARY_PATH_VAR.
+ * unix/configure: regend
+
+ * README: Bumped version number to 8.4.0
+ * generic/tk.h:
+ * unix/configure:
+ * unix/configure.in:
+ * unix/tk.spec:
+ * win/configure:
+ * win/configure.in:
+
+ * generic/tkCmds.c:
+ * generic/tkWindow.c: made 'tk' available in safe interpreters,
+ but only the caret and windowingsystem subcommands may be called.
+ * tests/safe.test (safe-1.2): noted that tk is now available in
+ safe interps, but not the appname/scaling subcommands.
+
+ * tests/tk.test (tk-1.2): noted new tk windowingsystem subcommand
+
+2002-08-31 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/tcl.m4: update from Tcl
+
+ * unix/Makefile.in: import of TK_SHLIB_LD_EXTRAS for Tk library
+ specific linker settings. Added use of new LD_LIBRARY_PATH_VAR.
+
+ * unix/configure: regen
+
+2002-08-31 Daniel Steffen <das@users.sourceforge.net>
+
+ *** macosx-8-4-branch merged into the mainline [tcl patch #602770] ***
+
+ * generic/tk.decls:
+ * generic/tkInt.decls: added new "aqua" specific entries to the
+ stubs tables. Changed all "unix" entries to "x11" to allow us to
+ distinguish and build both "aqua" on MacOSX and "x11" on MacOSX.
+
+ * generic/tk.h: added a #ifnded RESOURCE_INCLUDED so that tk.h can
+ be passed to the resource compiler.
+
+ * generic/tkCmds.c (Tk_TkObjCmd): added [tk windowingsystem]
+ subcommand: returns "x11" when running on X11, "win32" on Windows,
+ "classic" on MacOS9 and "aqua" on MacOSX Aqua (i.e. Carbon)
+
+ * generic/tkFont.c (TkFontGetFirstTextLayout): new private function
+ returning the first chunk of a Tk_TextLayout, i.e. until the first
+ font change on the first line (or the whole first line if there is
+ no such font change).
+
+ * generic/tkMain.c: made Tcl_ThreadDataKey static
+
+ * library/demos/puzzle.tcl: fixed button metrics for aqua
+
+ * tests/cursor.test: check for presence of arrow cursor instead of
+ heart cursor
+
+ * xlib/xcolors.c: changed xColors static initialization to more
+ standard C
+
+ * macosx/Wish.pbproj/jingham.pbxuser (new):
+ * macosx/Wish.pbproj/project.pbxproj (new): project for Apple's
+ ProjectBuilder IDE.
+
+ * macosx/Makefile (new): simple makefile for building the project
+ from the command line via the ProjectBuilder tool 'pbxbuild'.
+
+ * macosx/tkMacOSXAppInit.c (new): macosx specific AppInit looking
+ for a AppMain.tcl file in its bundled Resources/Scripts folder. If
+ present, argv[1] is set to that file and the Scripts folder is
+ added to the auto_path. This allows tk apps to embed scripts within
+ their bundle directory structure.
+
+ * macosx/tkMacOSXInit.c (new): macosx adapted version of
+ tkUnixInit.c: we initialize & cache the Carbon native encoding
+ (e.g. 'macRoman') and try to find the tk script library files
+ inside Tk packaged as a framework.
+
+ * macosx/tkMacOSXNotify.c (new): new macosx specific merged
+ Carbon/select-based notifier.
+
+ * macosx/tkMacOSXEvent.c (new):
+ * macosx/tkMacOSXEvent.h (new):
+ * macosx/tkMacOSXKeyEvent.c (new):
+ * macosx/tkMacOSXMouseEvent.c (new):
+ * macosx/tkMacOSXWindowEvent.c (new): new macosx specific event
+ handling functionality.
+
+ * macosx/tkMacOSX.h (new):
+ * macosx/tkMacOSXBitmap.c (new):
+ * macosx/tkMacOSXButton.c (new):
+ * macosx/tkMacOSXClipboard.c (new):
+ * macosx/tkMacOSXColor.c (new):
+ * macosx/tkMacOSXConfig.c (new):
+ * macosx/tkMacOSXCursor.c (new):
+ * macosx/tkMacOSXDefault.h (new):
+ * macosx/tkMacOSXDialog.c (new):
+ * macosx/tkMacOSXDraw.c (new):
+ * macosx/tkMacOSXEmbed.c (new):
+ * macosx/tkMacOSXFont.c (new):
+ * macosx/tkMacOSXHLEvents.c (new):
+ * macosx/tkMacOSXInt.h (new):
+ * macosx/tkMacOSXKeyboard.c (new):
+ * macosx/tkMacOSXMenu.c (new):
+ * macosx/tkMacOSXMenubutton.c (new):
+ * macosx/tkMacOSXMenus.c (new):
+ * macosx/tkMacOSXPort.h (new):
+ * macosx/tkMacOSXRegion.c (new):
+ * macosx/tkMacOSXScale.c (new):
+ * macosx/tkMacOSXScrlbr.c (new):
+ * macosx/tkMacOSXSubwindows.c (new):
+ * macosx/tkMacOSXTest.c (new):
+ * macosx/tkMacOSXUtil.c (new):
+ * macosx/tkMacOSXUtil.h (new):
+ * macosx/tkMacOSXWm.c (new):
+ * macosx/tkMacOSXWm.h (new):
+ * macosx/tkMacOSXXStubs.c (new): macosx ports of classic mac Tk
+ implementation in tk/mac.
+
+ * macosx/tkMacOSXSend.c (new): only send to local interp
+ implemented currently.
+
+ * macosx/tkMacOSXDebug.h (new):
+ * macosx/tkMacOSXDebug.c (new): new macosx specific functions for
+ debugging MacOS events, regions, etc.
+
+ * macosx/tkAboutDlg.r (new):
+ * macosx/tkMacOSXApplication.r (new):
+ * macosx/tkMacOSXCursors.r (new):
+ * macosx/tkMacOSXLibrary.r (new):
+ * macosx/tkMacOSXMenu.r (new):
+ * macosx/tkMacOSXResource.r (new):
+ * macosx/tkMacOSXXCursors.r (new):
+ * macosx/tclets.r (new): sources for Rez resource compiler.
+
+ * macosx/Wish.icns (new): Wish application icon.
+
+ * generic/tk.h:
+ * generic/default.h:
+ * generic/tkBind.c:
+ * generic/tkCmds.c:
+ * generic/tkGrab.c:
+ * generic/tkPointer.c:
+ * generic/tkPort.h:
+ * generic/tkSelect.c:
+ * generic/tkStubLib.c:
+ * generic/tkTest.c:
+ * generic/tkText.c:
+ * generic/tkWindow.c:
+ * unix/tkUnix3d.c:
+ * xlib/xgc.c:
+ * xlib/X11/X.h:
+ * xlib/X11/Xlib.h:
+ * xlib/X11/Xutil.h: added #includes and #ifdefs for macosx
+
+ * library/bgerror.tcl:
+ * library/button.tcl:
+ * library/console.tcl:
+ * library/dialog.tcl:
+ * library/entry.tcl:
+ * library/listbox.tcl:
+ * library/menu.tcl:
+ * library/msgbox.tcl:
+ * library/scrlbar.tcl:
+ * library/spinbox.tcl:
+ * library/text.tcl:
+ * library/tk.tcl:
+ * library/demos/menu.tcl:
+ * library/demos/menubu.tcl:
+ * library/demos/widget: check [tk windowingsystem] instead of
+ and/or in addition to $tcl_platform(platform).
+
+ * generic/tkInt.h:
+ * mac/tkMacBitmap.c:
+ * mac/tkMacWm.c: added missing CONSTification
+
+ * generic/tkIntDecls.h:
+ * generic/tkIntPlatDecls.h:
+ * generic/tkIntXlibDecls.h:
+ * generic/tkPlatDecls.h:
+ * generic/tkStubInit.c: regen
+
+2002-08-27 D. Richard Hipp <drh@hwaci.com>
+
+ * doc/checkbutton.n: [Bug 582457] Fix the -offrelief option so
+ * doc/radiobutton.n: that when -offrelief is flat and -relief is
+ * mac/tkMacButton.c: sunken and -overrelief is raised, buttons
+ * unix/tkUnixButton.c: work look toolbar buttons under Windows.
+ * win/tkWinButton.c: See also: TIP #82.
+
+2002-08-26 Don Porter <dgp@users.sf.net>
+
+ * win/Makefile.in: Removed dependence on the (parts of) the
+ * win/winMain.c: tcltest executable on Windows. It was not
+ used, and the dependency complicated the Makefile. [Bug 592638].
+
+2002-08-20 Don Porter <dgp@users.sf.net>
+
+ * README: Bumped version number to 8.4b3 to distinguish
+ * generic/tk.h: HEAD from the 8.4b2 release.
+ * unix/configure.in:
+ * win/configure.in:
+ * unix/tk.spec:
+
+ * unix/configure: autoconf
+ * win/configure:
+
+ * generic/tk.h: Added compile-time check that the tcl.h header file
+ #included by Tk 8.4 is one from Tcl 8.4. This is needed to be sure
+ that new #defines like CONST84 are available. [Bug 597432].
+
+2002-08-16 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/Makefile.in (install-binaries): simplified pkgIndex.tcl
+ file created on installation.
+ * win/Makefile.in (install-binaries): corrected and simplified
+ creation of pkgIndex.tcl file on installation.
+
+2002-08-14 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * win/tkWinDialog.c:
+ * win/makefile.vc: broken compilation and link from changes
+ Hobbs-08-07 fixed.
+ * win/tkWinTest.c: CONST problem resolved.
+
+2002-08-13 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/button.tcl: change the bindings to use Priv($w,relief)
+ instead of just Priv(relief). This ensures that neighboring
+ buttons don't confuse (over)relief settings.
+
+2002-08-13 Reinhard Max <max@suse.de>
+
+ * unix/tkUnixSend.c (Tk_SetAppName): Fixed a compiler warning.
+
+2002-08-12 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * library/demos/image2.tcl: Tweaked the behaviour of the directory
+ box on resize, as resizing of the overall window tends to be
+ common given the sample images.
+
+2002-08-08 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/tkUnixWm.c (WmTransientCmd): Apply fix for
+ wm transient assertion error that was applied
+ to tkWinWm.c for Tk Bug #592201.
+
+2002-08-08 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * tests/wm.test: Add deleteWindows at start of
+ new transient tests so they do not fail if the
+ toplevels already exist.
+ * unix/tkUnixWm.c: Revert patch for Tk Bug #592201
+ which incorrectly removed numTransients member.
+
+2002-08-08 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/tkUnixWm.c:
+ * win/tkWinWm.c:
+ * tests/wm.test: Fix for Tk Bug #592201 "wm transient fails with
+ two masters"; fixes panic after a transient window is reassigned
+ to new master and either master is subsequently destroyed.
+
+2002-08-08 Don Porter <dgp@users.sf.net>
+
+ * tests/unixWm.test: Corrected packaging of unixWm-50.3 so that
+ [setupbg] and [cleanupbg] always balance, no matter what tests
+ are skipped.
+
+2002-08-08 Reinhard Max <max@suse.de>
+
+ * unix/Makefile.in: Fixed typos in DISTNAME, and ZIPNAME.
+
+2002-08-08 Jeff Hobbs <jeffh@ActiveState.com>
+
+ *** 8.4b2 TAGGED FOR RELEASE ***
+
+ * generic/tkButton.c (TkButtonWorldChanged): added GCFont handling
+ to the disabledGc of buttons when compound != none. The drawing
+ appears to be incorrect across platforms still. [Bug #477740]
+
+ * generic/tkImgGIF.c (FileReadGIF): fixed -from handling for gifs
+ [Bug #467524] (obermeier)
+
+2002-08-07 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkCanvUtil.c (TkSmoothParseProc): recognize the built-in
+ bezier method by name. [Bug #578654]
+ * doc/canvas.n: update to note that -smooth really doesn't take
+ or return just booleans.
+
+ * win/tkWinMenu.c (TkpSetWindowMenuBar): fixed logic bug in when
+ to idle call ReconfigureWindowsMenu.
+
+ * doc/GetBitmap.3: removed doc refs to deprecated
+ Tk_GetBitmapFromData. [Bug #590379]
+
+ * generic/tkPanedWindow.c (Tk_PanedWindowObjCmd):
+ * library/panedwindow.tcl: changed class from PanedWindow to
+ Panedwindow to not conflict with existing bwidgets, but also to be
+ more regular with other names used in the core.
+
+ * tests/panedwindow.test: added -text foobar to some test buttons
+ to enable correct testing of panedwindow across platforms.
+ [Bug #582370]
+
+ * win/tkWinDialog.c: enabled use of the updated native Windows
+ directory browser (tk_chooseDirectory). This does require
+ shell32.dll v4.71 or greater. [Patch #468139]
+
+ * win/configure:
+ * win/tcl.m4: added shell32 to libs for updated native Windows
+ tk_chooseDirectory dialog.
+
+2002-08-06 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tkPanedWindow.c (RESIZE_PENDING): Separated out flag for
+ indicating that a resize needs to be issued.
+ (PanedWindowReqProc): Do the old behaviour when the panedwindow is
+ not mapped; easiest way of making the test suite pass while still
+ preserving improved behaviour in the face of children whose size
+ is not known immediately.
+
+2002-08-06 Don Porter <dgp@users.sf.net>
+
+ * tests/defs.tcl: removed file. No longer needed now that Tk is
+ using the tcltest package to do its testing.
+
+2002-08-05 Don Porter <dgp@users.sf.net>
+
+ * win/tkWinFont.c: Additional changes to fix CONST warnings on
+ * win/tkWinWM.c: Windows due to latest patch. Tks Vince Darley.
+
+ * doc/3DBorder.3: Applied companion patch for Tcl Patch 585105,
+ * doc/BindTable.3: updating Tk to use Tcl 8.4's fully CONST-ified
+ * doc/ConfigWidg.3: interface, and fully CONSTifying Tk at the
+ * doc/CrtImgType.3: same time.
+ * doc/CrtWindow.3:
+ * doc/DeleteImg.3: This patch includes purging Tk of its last
+ * doc/FindPhoto.3: direct access to interp->result. [Bug 589853]
+ * doc/GetAnchor.3:
+ * doc/GetBitmap.3: The substantial changes include copying
+ * doc/GetCapStyl.3: event sequence strings into Tcl_DStrings
+ * doc/GetClrmap.3: in tkBind.c, and copying [text] indices into
+ * doc/GetColor.3: Tcl_DStrings because parsing them involved
+ * doc/GetCursor.3: overwriting them. If this causes performance
+ * doc/GetFont.3: trouble, that can be resolved by further
+ * doc/GetImage.3: converting them to Tcl_Obj's.
+ * doc/GetJoinStl.3:
+ * doc/GetJustify.3: The #defines USE_NON_CONST and USE_COMPAT_CONST
+ * doc/GetOption.3: have the same effect for Tk as they do for Tcl.
+ * doc/GetRelief.3: (They actually change tcl.h)
+ * doc/GetScroll.3:
+ * doc/GetVisual.3:
+ * doc/InternAtom.3:
+ * doc/NameOfImg.3:
+ * doc/SetAppName.3:
+ * doc/WindowId.3:
+ * generic/tk.decls:
+ * generic/tk.h:
+ * generic/tk3d.c:
+ * generic/tkAtom.c:
+ * generic/tkBind.c:
+ * generic/tkBitmap.c:
+ * generic/tkButton.c:
+ * generic/tkCanvArc.c:
+ * generic/tkCanvBmap.c:
+ * generic/tkCanvImg.c:
+ * generic/tkCanvLine.c:
+ * generic/tkCanvPoly.c:
+ * generic/tkCanvPs.c:
+ * generic/tkCanvText.c:
+ * generic/tkCanvUtil.c:
+ * generic/tkCanvWind.c:
+ * generic/tkCanvas.c:
+ * generic/tkCanvas.h:
+ * generic/tkClipboard.c:
+ * generic/tkCmds.c:
+ * generic/tkColor.c:
+ * generic/tkConfig.c:
+ * generic/tkConsole.c:
+ * generic/tkCursor.c:
+ * generic/tkDecls.h:
+ * generic/tkEntry.c:
+ * generic/tkFont.c:
+ * generic/tkFrame.c:
+ * generic/tkGet.c:
+ * generic/tkGrid.c:
+ * generic/tkImage.c:
+ * generic/tkImgBmap.c:
+ * generic/tkImgPhoto.c:
+ * generic/tkInt.decls:
+ * generic/tkInt.h:
+ * generic/tkIntDecls.h:
+ * generic/tkIntPlatDecls.h:
+ * generic/tkListbox.c:
+ * generic/tkMenu.c:
+ * generic/tkMenubutton.c:
+ * generic/tkMessage.c:
+ * generic/tkOldConfig.c:
+ * generic/tkOption.c:
+ * generic/tkRectOval.c:
+ * generic/tkScale.c:
+ * generic/tkScrollbar.c:
+ * generic/tkSelect.c:
+ * generic/tkStyle.c:
+ * generic/tkTest.c:
+ * generic/tkText.c:
+ * generic/tkText.h:
+ * generic/tkTextBTree.c:
+ * generic/tkTextDisp.c:
+ * generic/tkTextImage.c:
+ * generic/tkTextIndex.c:
+ * generic/tkTextMark.c:
+ * generic/tkTextTag.c:
+ * generic/tkTextWind.c:
+ * generic/tkUtil.c:
+ * generic/tkVisual.c:
+ * generic/tkWindow.c:
+ * mac/tkMacConfig.c:
+ * mac/tkMacCursor.c:
+ * mac/tkMacEmbed.c:
+ * mac/tkMacSend.c:
+ * unix/tkUnixConfig.c:
+ * unix/tkUnixCursor.c:
+ * unix/tkUnixEmbed.c:
+ * unix/tkUnixFont.c:
+ * unix/tkUnixSelect.c:
+ * unix/tkUnixSend.c:
+ * unix/tkUnixWm.c:
+ * win/tkWinConfig.c:
+ * win/tkWinCursor.c:
+ * win/tkWinEmbed.c:
+ * win/tkWinMenu.c:
+ * win/tkWinSend.c:
+
+2002-08-02 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tkPanedWindow.c (DestroyPanedWindow): Idle calls need to
+ be deleted on destruction of the window, or things can *really* go
+ pear-shaped.
+
+2002-07-31 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tkPanedWindow.c (PanedWindowReqProc): Postpone pane
+ arrangement until idle, as is done in other window managers, to
+ fix problems with size calculations when the children don't
+ already know their sizes anyway.
+
+ * unix/configure: Regen.
+ * unix/tcl.m4: Update from Tcl.
+
+2002-07-29 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure: Regen.
+ * unix/configure.in: Remove code that was setting
+ CC_SEARCH_FLAGS and LD_SEARCH_FLAGS to try to
+ account for cc vs ld linking. Tcl now handles this.
+ * unix/tcl.m4: Update from Tcl.
+
+2002-07-27 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/Makefile.in: Add MAJOR_VERSION, MINOR_VERSION,
+ PATCH_LEVEL, INSTALL_LIBRARY, STUB_LIB_FILE, and LIB_FILE
+ to support changes in tcl.m4 related to library builds.
+ Use MAKE_LIB macro to avoid dealing with RANLIB issues.
+ Rename TK_CC_SEARCH_FLAGS to CC_SEARCH_FLAGS and
+ rename TK_LD_SEARCH_FLAGS to LD_SEARCH_FLAGS.
+ Use new INSTALL_LIB and INSTALL_STUB_LIB substs to
+ deal with ranlib issues when install libraries.
+ * unix/configure: Regen.
+ * unix/configure.in: Remove AC_PROG_RANLIB since
+ this is done by tcl.m4 now. Define CC_SEARCH_FLAGS
+ instead of TK_CC_SEARCH_FLAGS and so on.
+ Use MAKE_LIB and MAKE_STUB_LIB from tcl.m4.
+ Remove AC_SUBST calls that are no done in tcl.m4.
+ * unix/tcl.m4: Update from Tcl.
+ * unix/tkConfig.sh.in: Subst CC_SEARCH_FLAGS and
+ LD_SEARCH_FLAGS.
+
+2002-07-25 Peter Spjuth <peter.spjuth@space.se>
+
+ * generic/tkInt.h:
+ * generic/tkWindow.c:
+ * mac/tkMacWm.c:
+ * unix/tkUnixWm.c:
+ * win/tkWinWm.c:
+ * tests/wm.test:
+ * tests/winWm.test:
+ * tests/unixWm.test: Objectifed wm. [Patch #564521]
+ Note: At this point the Mac file is completely untested
+ and may not even compile.
+
+2002-07-25 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * tests/spinbox.test: added spinbox-22.[1-3]
+ * generic/tkEntry.c (ConfigureEntry): made the textvariable value
+ take precedence over changed -from/-to values, unless it must be
+ constrained. [Bug #559078]
+
+ * library/spinbox.tcl (MouseSelect): when not in the entry, just
+ return instead of invoking - ButtonUp handles invoking already.
+ [Bug #499168]
+
+ * library/tk.tcl (RestoreFocusGrab): handle the case where the
+ FocusGrab info is not set. [Bug #553283]
+
+2002-07-24 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * tests/canvas.test: added canvas-14.[1-6]
+ * generic/tkCanvas.c (CanvasWidgetCmd): corrected handling of
+ 'scan' subcommand args. Also removed early return cases to goto
+ done instead where the canvasPtr would be Tcl_Release'd. This may
+ solve other problems with unreleased canvasPtr's. [Bug #581560]
+
+ * win/tkWinButton.c (TkpDisplayButton): corrected display of focus
+ ring around the actual text when the button is a compound button.
+ [Bug #583691]
+
+ * unix/README: Corrected notes about running user interactive Tk
+ tests. [Bug #462320]
+
+ * generic/tkText.c (TextEditUndo): set isDirtyIncrement to -1 when
+ reverting to note proper "dirtiness". [Bug #580362] (callewaert)
+
+ * generic/tkEntry.c (DisplayEntry): correct cursor position before
+ calling Tk_SetCaretPos. (yamamoto)
+
+2002-07-23 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure: Regen.
+ * unix/tcl.m4: Update from Tcl.
+
+2002-07-22 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * library/choosedir.tcl (tk::dialog::file::chooseDir):
+ * library/clrpick.tcl (tk::dialog::file::chooseDir):
+ * library/msgbox.tcl (tk::MessageBox):
+ * library/tkfbox.tcl (tk::dialog::file):
+ * library/xmfbox.tcl (tk::MotifFDialog):
+ Revert [Tk patch 568278]. The transient window workaround
+ is no longer needed since the fix for [Tk bug 570764]
+ solved the problem for withdrawn transients.
+
+2002-07-19 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure:
+ * unix/configure.in:
+ * win/configure:
+ * win/configure.in: Add AC_PREREQ(2.13) in an attempt
+ to make it more clear that the configure scripts
+ must be generated with autoconf version 2.13.
+ [Tcl Bug 583573]
+
+2002-07-19 D. Richard Hipp <drh@hwaci.com>
+
+ * library/mkpsec.tcl: Fix a bug that was causing postscript generation
+ to fail under Win2K.
+
+2002-07-18 Reinhard Max <max@suse.de>
+
+ * unix/tkUnixSend.c: Using Tcl_GetTime instead of TclpGetTime.
+
+2002-07-17 Reinhard Max <max@suse.de>
+
+ * library/unsupported.tcl: Extended ExposePrivateVariable, and
+ ExposePrivateCommand to accept patterns as well.
+
+2002-07-17 Don Porter <dgp@users.sf.net>
+
+ * generic/tkFont.c: Corrected reversed logic in assert -> panic
+ conversion. [Bug 582799]
+
+2002-07-16 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tkFont.c (TkFontPkgFree): Call panic instead
+ of assert since assert is not used in the rest of Tk.
+ [Tk bug 579651]
+
+2002-07-16 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/Makefile.in:
+ * win/Makefile.in: Add a more descriptive warning
+ in the event `make genstubs` needs to be rerun.
+
+2002-07-16 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * win/tkWinWm.c:
+ * doc/wm.n: fix for part of [Bug 581627], and made iconbitmap
+ code on Windows more flexible about reading in icons [Bug
+ 220800].
+
+2002-07-15 David Gravereaux <davygrvy@pobox.com>
+
+ * win/makefile.bc (new): re-add of the borland makefile. Submitted
+ by Helmut Giese <hgiese@ratiosoft.com>. This needs testing, still.
+
+2002-07-15 Don Porter <dgp@users.sf.net>
+
+ * Fixes for [Bug 581627, 581795].
+ * generic/tkTest.c: Test commands not supported on non-Unix
+ platforms should not be defined there in the first place.
+ * tests/constraints.tcl: Fixed "secureserver" constraint.
+ * tests/unixWm.test: Some tests needed "unix" constraint.
+ * win/tkWinWm.c: Typo in error message.
+
+2002-07-14 Don Porter <dgp@users.sf.net>
+
+ * tests/event.test: Fixes to enable testing of only userInteraction
+ * tests/visual_bb.test: tests.
+
+ * README: Bumped HEAD to version 8.4b2 in order to
+ * generic/tk.h: distinguish it from the 8.4b1 release.
+ * unix/configure*: Also extended LOCALES to cover all message
+ * unix/tk.spec: catalogs.
+ * win/configure*:
+
+ * tests/focustTcl.test: Conversion bug: Corrected backwards logic.
+ * tests/imgPhoto.test: Conversion bug: overwrote unix/README.
+
+ * tests/all.tcl: Completed conversion of Tk test suite
+ * tests/constraints.tcl: to use tcltest.
+ * tests/[b-v]*.test:
+ * unix/Makefile.in:
+
+2002-07-12 Don Porter <dgp@users.sf.net>
+
+ * tests/constraints.tcl: Converted more files to tcltest and
+ * tests/[g-x]*.test: factored out common code.
+
+2002-07-11 Don Porter <dgp@users.sf.net>
+
+ * tests/canvPsImg.tcl: Converted several files in the
+ * tests/constraints.tcl (new file): Tk test suite for testing by
+ * tests/[r-x]*.test: tcltest 2.1.
+ * unix/Makefile.in:
+
+2002-07-11 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinDialog.c (Tk_ChooseDirectoryObjCmd): initialize
+ utfTitle to NULL, add a few more notes about limitations of
+ possible new Tk_ChooseDirectoryObjCmd function.
+
+2002-07-11 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/imgPhoto.test (imgPhoto-15.1): Added test of mem-alloc
+ failure, but this is non-portable.
+ * generic/tkImgPhoto.c (ImgPhotoSetSize): Allowed this function to
+ fail when it can't allocate enough memory. Note that not all the
+ places that call it can fail nicely without API changes; some
+ still panic but at least some of the potential failures are now
+ handled gracefully.
+
+ * tests/visual_bb.test (lpr): Stopped this from relying on
+ external files; direct piping is much more flexible for this
+ application.
+
+2002-07-09 Don Porter <dgp@users.sf.net>
+
+ * generic/tkTest.c: Removed unused dependence on TclThread_Init()
+ * tests/defs.tcl: and [testthread]. [Bug 578165, Tcl Bug 531413]
+
+2002-07-08 David Gravereaux <davygrvy@pobox.com>
+
+ * unix/Makefile.in: Added missing win/lamp.bmp to the dist
+ target.
+
+2002-07-05 Jeff Hobbs <jeffh@ActiveState.com>
+
+ *** 8.4b1 TAGGED FOR RELEASE ***
+
+2002-07-04 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * library/bgerror.tcl (bgerror): Stopped the bgerror dialog from
+ getting wider than the screen; in theory really long messages
+ could make it become taller than the screen now, but that's much
+ less likely to happen. Also trimmed a little bit of internal
+ space so that the icon-message gap is the same as the icon-frame
+ and message-frame gaps.
+
+2002-07-01 Don Porter <dgp@users.sf.net>
+
+ * unix/configure:
+ * unix/tcl.m4: Updated to latest tcl.m4 from Tcl.
+
+2002-06-28 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * library/msgbox.tcl (MessageBox): Force all non-button widgets to
+ have the same background as the containing toplevel. [Bug #552515]
+
+2002-06-27 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * win/Makefile.in (install-binaries): Fix of troubled Makefile
+ quoting introduced by [Patch 521356] causing the installed to
+ fail.
+
+2002-06-25 Don Porter <dgp@users.sf.net>
+
+ * unix/tkUnixFont.c: (Tk_DrawChars) silence compiler warning.
+
+2002-06-26 David Gravereaux <davygrvy@pobox.com>
+
+ * generic/tkStyle.c: <eol> of the committing cvs client didn't
+ match the <eol> of the file itself. Windows users where getting
+ \r\r\n. Problem fixed.
+
+2002-06-26 Anton Kovalenko <a_kovalenko@users.sourceforge.net>
+
+ * generic/tkFont.c (TkTextLayoutToPostscript): fixed potential
+ buffer overflow which could be intentionally triggered from
+ within safe interpreter -- malicious applet could modify
+ tk::psglyphs array.
+
+2002-06-26 Anton Kovalenko <a_kovalenko@users.sourceforge.net>
+
+ * tests/font.test (font-32.1): updated this test
+ to expect the new behavior of canvas postscript.
+
+2002-06-25 Don Porter <dgp@users.sf.net>
+
+ * unix/Makefile.in: Expanded install-binaries target to create
+ * win/Makefile.in: and install a pkgIndex.tcl file to enable
+ Tk as a loadable package [Patch 521356]
+
+2002-06-25 Anton Kovalenko <a_kovalenko@users.sourceforge.net>
+
+ * library/mkpsenc.tcl: (added) utilities to generate
+ Postscript prolog for current system encoding.
+ * generic/tkCanvPs.c (TkCanvPostscriptCmd): now
+ uses mkpsenc.tcl to generate Postscript prolog.
+ * generic/tkFont.c (TkTextLayoutToPostscript): modified
+ according to patch #546910. Now outputs system-encoded
+ characters (for unibyte) or Adobe glyph names (for
+ multibyte or outside-locale).
+ * tests/canvText.test (canvText-17.1): updated this test
+ to expect the new behavior of canvas postscript.
+
+2002-06-25 Reinhard Max <max@suse.de>
+
+ * unix/tcl.m4: New macro SC_CONFIG_MANPAGES.
+ * unix/configure.in: Added support for symlinks and compression
+ * unix/Makefile.in: when installing the manpages. [Patch 518052]
+ Default is still hardlinks and no compression.
+
+ * unix/mkLinks: generated
+ * unix/configure:
+
+ * unix/README: Added documentation for the new features.
+
+ * unix/configure: Replaced ${exec_prefix}/lib
+ * unix/tcl.m4 (SC_PATH_TCLCONFIG): by ${libdir}.
+
+2002-06-24 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * tests/winWm.test: Verify that both an unmapped
+ and already mapped toplevel are raised and receive
+ the focus when deiconified.
+ * tests/wm.test: Add wm deiconify tests. Check that
+ a toplevel that has never been mapped is not mapped
+ by the deiconify command since it should be done
+ at idle by MapFrame.
+ * win/tkWinWm.c (Tk_WmCmd): Check the WM_NEVER_MAPPED
+ flag while processing the wm deiconify command.
+ The WM_UPDATE_PENDING flag should never be set when
+ WM_NEVER_MAPPED is set, but double check so that
+ the implementation is more explicit and matches
+ the comment just above.
+ Return without invoking TkWmRestackToplevel or
+ TkSetFocusWin on a toplevel that has never been
+ mapped. This fixes a bug where a toplevel is mapped
+ with the wrong size and is then resized by the
+ idle call to MapFrame. [Tk bug 233150]
+
+2002-06-23 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinWm.c (UpdateGeometryInfo): remove the check for a null
+ wrapper introduced in r1.41 on 2002-06-15 because it prevented
+ geometry setting from taking effect if the window was not on the
+ screen. Another check may go in it's place as IsIconic and
+ IsZoomed should not be passed NULL.
+
+2002-06-22 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * tests/wm.test: Remove invalid minsize test. Add update
+ calls to wm transient tests so that idle handlers get
+ run. This is needed to get the tests to pass under Win32.
+ * unix/tkUnixWm.c (WmWaitMapProc): Move the special
+ transient withdrawn check into the if body to
+ make it easier to set a breakpoint on this test
+ inside a debugger. No functional changes.
+ * win/tkWinWm.c (WmWaitVisibilityOrMapProc): Ditto.
+
+2002-06-22 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * doc/wm.n: TIP #95 Windows implementation and
+ * mac/tkMacWm.c (Tk_WmCmd): docs with mac and unix stubs.
+ * unix/tkUnixWm.c (Tk_WmCmd):
+ * win/tkWinWm.c (Tk_WmCmd):
+ * tests/unixWm.test:
+ * tests/winWm.test: more wm attr tests will be needed.
+
+ * generic/tkGrid.c (GridReqProc): check that gridPtr is not NULL
+ (may be when embedded). [Bug #548791] (halliday)
+
+ * generic/tkFont.c (TkFontPkgFree): changed panic on freeing fonts
+ to an assert, and wrapped panic in #ifdef PURIFY. [Bug #568701]
+
+ * library/menu.tcl: corrected menus from being posted offscreen
+ on Windows. [Bug #464451] (darley)
+
+ * library/console.tcl: corrected the defaultPrompt substitution
+ [Bug #553207] and made Tab a default expansion key (like Escape).
+
+ * win/tkWinEmbed.c (EmbedWindowDeleted): added a check for a null
+ containerPtr. The core of this bug is likely elsewhere. [Bug #476176]
+
+ * doc/text.n: TIP #93 implementation that
+ * generic/tkText.c (TextWidgetCmd): enhances the text get and
+ * generic/tkTextIndex.c (TkTextGetIndex): delete methods to accept
+ * tests/text.test: multiple range pairs.
+ This handles the delete case in an atomic, fixed-index fashion.
+
+2002-06-21 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * tests/wm.test: Add tests to make sure a withdrawn
+ transient does not get remapped by state changes
+ in the master.
+ * unix/tkUnixWm.c (Tk_WmCmd, WmWaitMapProc):
+ * win/tkWinWm.c (Tk_WmCmd, WmWaitVisibilityOrMapProc):
+ Add a WM_TRANSIENT_WITHDRAWN flag that gets set by the
+ withdraw, deiconify, or state wm subcommands. Check
+ this flag before mapping a transient when processing
+ a MapNotify event. [Tk bug 570764]
+
+2002-06-21 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * unix/tk.spec (version), README, win/configure.in, unix/configure.in:
+ * generic/tk.h (TK_RELEASE_*, TK_PATCH_LEVEL): Bumped to beta1.
+
+2002-06-21 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * doc/text.n: TIP #104 implementation which generalizes the
+ * generic/tkText.c: undo/redo stack to not be tied solely to the
+ * generic/tkText.h: text widget. The APIs are still private.
+ * generic/tkUndo.c: This also adds a stack limiting ability and
+ * generic/tkUndo.h: a -maxundo option to the text widget (in
+ * library/text.tcl: addition to the options from TIP #26) should
+ * mac/tkMacDefault.h: users want to limit the undo/redo stack
+ * tests/text.test: (should not be necessary in most cases).
+ * unix/Makefile.in: [Patch #554763] (callewart)
+ * unix/tkUnixDefault.h:
+ * win/Makefile.in:
+ * win/makefile.vc:
+ * win/tkWinDefault.h:
+
+2002-06-21 Don Porter <dgp@users.sf.net>
+
+ * unix/Makefile.in: Removed unnecessary dependence of tktest
+ * unix/tkAppInit.c: executable on the tcltest executable on
+ Unix. If there are similar dependencies on other platforms, they
+ can probably be removed as well. [Bug 572134].
+
+2002-06-20 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * doc/listbox.n:
+ * generic/tkListbox.c (DisplayListbox):
+ * mac/tkMacDefault.h: TIP #94 implementation adding -activestyle
+ * tests/listbox.test: option to the listbox. This adds the ability
+ * unix/tkUnixDefault.h: to have listboxes look native on Windows, and
+ * win/tkWinDefault.h: "nicer" elsewhere using the 'dotbox' style.
+
+2002-06-20 Peter Spjuth <peter.spjuth@space.se>
+
+ * generic/tkGrid.c: Corrected the test for grid propagate change.
+ [Bug #571433]
+
+2002-06-19 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * tests/panedwindow.test:
+ * generic/tkPanedWindow.c: ensure that sash index is lower bounds
+ checked. [Bug #548727]
+
+2002-06-19 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tkClipboard.c (TkClipCleanup): Add code
+ to set dispPtr->clipWindow to NULL, this was
+ accidently removed by last commit. Fixes
+ a crash while running the tests under win32.
+
+2002-06-19 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tkBind.c (TkBindDeadWindow):
+ Handle case where Tk_DestroyWindow is invoked
+ on clipboard and send windows.
+ * generic/tkClipboard.c (TkClipCleanup):
+ Invoke Tk_DestroyWindow to cleanup the
+ dispPtr->clipWindow. Call Tcl_Preserve
+ and Tcl_Release on the window to avoid an
+ invalid memory ref on shutdown.
+ * generic/tkEvent.c (Tk_HandleEvent):
+ Panic if XCreateIC is invoked twice for
+ the same window. This should never happen,
+ the check were just added to make sure it
+ does not since this could lead to crashes
+ in XCloseIM.
+ * generic/tkFocus.c (TkFocusDeadWindow):
+ Handle case where Tk_DestroyWindow is invoked
+ on clipboard and send windows.
+ * generic/tkOption.c (TkOptionDeadWindow): Ditto.
+ * generic/tkWindow.c (TkCloseDisplay): Move
+ deletion of dispPtr->winTable after TkpCloseDisplay
+ call since Tk_DestroyWindow uses it and could
+ be called by TkpCloseDisplay for clipboard/send windows.
+ Also invoke ckfree for the dispPtr instead of
+ doing it in TkpCloseDisplay.
+ (Tk_DestroyWindow): Check for a null winPtr->mainPtr
+ before doing certain cleanup tasks so the we can
+ invoke Tk_DestroyWindow on clipboard and send windows.
+ We need to do this so that XDestroyIC will get invoked
+ for the input contexts of each window.
+ * mac/tkMacXStubs.c (TkpCloseDisplay): Don't free
+ the displayPtr since this is now done in TkCloseDisplay.
+ * unix/tkUnixEvent.c (TkpCloseDisplay, OpenIM): Remove
+ conditional compilation around calls to XCloseIM
+ since I am confident that the crashes related to
+ input contexts has been fixed. Don't free
+ the displayPtr since this is now done in TkCloseDisplay.
+ * unix/tkUnixSend.c (TkSendCleanup): Invoke the
+ Tk_DestroyWindow method to cleanup the special
+ send window. This will call XDestroyIC and thereby
+ avoid a crash in XCloseIM. The send window needs
+ to be Tcl_Preserve and Tcl_Release to avoid an
+ invalid memory ref on shutdown.
+ * win/tkWinX.c (TkpCloseDisplay): Don't free
+ the displayPtr since this is now done in TkCloseDisplay.
+ [Tk patch 570902]
+
+2002-06-19 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tkStyle.c: TIP#48 style engine.
+ See http://purl.org/tcl/tip/48.html for details.
+
+ * generic/tkConfig.c (GetOptionFromObj): Split to allow for access
+ to option tables via name as well as via object.
+ (TkGetOptionSpec): Semi-public interface to GetOption functionality.
+ (DoObjConfig, Tk_RestoreSavedOptions, FreeResources)
+ (GetObjectForOption): Basic style support for configure.
+
+ * generic/tkWindow.c (TkCreateMainWindow, Tk_DestroyWindow): Added
+ calls to set up and tear down the style subsystem.
+
+ * generic/tk.decls, generic/tk.h: Many declarations forming TIP#48
+ public interface.
+
+ * generic/tkInt.decls (TkStylePkgInit,TkStylePkgFree):
+ * generic/tkInt.h (TkGetOptionSpec): Supporting declarations.
+
+ * unix/Makefile.in, win/Makefile.in, win/makefile.vc: Added
+ tkStyle.c to list of generic source files.
+
+2002-06-18 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/defs.tcl (makeFile): Defined the return value of this
+ procedure to be the filename of the created file, as in the real
+ tcltest package...
+
+2002-06-17 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tkImage.c (Tk_ImageObjCmd, DeleteImage): Call
+ Tcl_Preserve and Tcl_Release for the masterPtr->winPtr
+ window to avoid accessing memory that had already
+ been deallocated in DeleteImage.
+
+2002-06-17 David Gravereaux <davygrvy@pobox.com>
+
+ Trims to support the removal of RESOURCE_INCLUDED from rc
+ scripts from Tcl's accepted FR #565088.
+
+ * generic/tk.h: Changed RESOURCE_INCLUDED to be RC_INVOKED
+ as the RC tool defines this already by default.
+
+ * win/rc/tk.rc:
+ * win/rc/wish.rc: removed the #define RESOURCE_INCLUDED lines.
+
+2002-06-17 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/Makefile.in (dist): correct installation of
+ wish.exe.manifest to DISTDIR target directory.
+
+ * generic/tkCmds.c (Tk_TkObjCmd):
+ * generic/tkInt.h (struct TkCaret):
+ * mac/tkMacXStubs.c (Tk_SetCaretPos):
+ * unix/tkUnixKey.c (TkpGetString, Tk_SetCaretPos):
+ * win/tkWinX.c (Tk_SetCaretPos):
+ * tests/tk.test: Added 'tk caret' implementation of TIP#96
+ * doc/SetCaret.3 (new): which adds a TkCaret structure element to
+ * doc/tk.n: TkDisplay for maintaining state.
+
+ * unix/tkUnixSend.c (TkSendCleanup): special cleanup of
+ inputContext to avoid bug in XCloseIM. (dejong)
+
+2002-06-17 Don Porter <dgp@users.sf.net>
+
+ * library/msgs/en_gb.msg: Added catalog for UK English.
+ Currently includes only Color -> Colour translation.
+
+2002-06-17 D. Richard Hipp <drh@hwaci.com>
+
+ * doc/checkbutton.n:
+ * doc/radiobutton.n:
+ * generic/tkButton.c:
+ * generic/tkButton.h:
+ * mac/tkMacButton.c:
+ * tests/button.test:
+ * unix/tkUnixButton.c:
+ * win/tkWinButton.c: Implementation of TIP#82 - Added the
+ -offrelief option to checkbutton and radiobutton.
+
+2002-06-14 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tkWindow.c (Tk_DestroyWindow): Set the pathName
+ component of a window to NULL after its memory has been
+ deallocated to avoid a possible illegal memory access
+ as a result of a call to Tk_PathName() on a Tk_Window
+ structure of a window that has already been destroyed.
+ [Tk bug 521946]
+
+2002-06-14 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tkOption.c (Tk_GetOption): Allocate
+ memory with ckalloc not malloc. This keeps
+ Tk from erroring out when built with
+ TCL_MEM_DEBUG.
+
+2002-06-14 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkBind.c (HandleEventGenerate):
+ * generic/tkInt.h: changed warpInProgress boolean from int to a
+ bit in the flags variable (TK_DISPLAY_IN_WARP)
+
+ * generic/tkCmds.c (Tk_TkObjCmd):
+ * unix/tkUnixKey.c (TkpGetString):
+ * generic/tkEvent.c (Tk_HandleEvent):
+ * generic/tkInt.h: changed useInputMethods boolean from int to a
+ bit in the flags variable (TK_DISPLAY_USE_IM)
+
+ * generic/tkInt.h:
+ * generic/tkCmds.c (Tk_WmObjCmd):
+ * unix/tkUnixWm.c (Tk_WmCmd):
+ * win/tkWinWm.c (Tk_WmCmd): changed wmTracing from being an int to
+ just a bit in the flags variable (TK_DISPLAY_WM_TRACING)
+
+ * generic/tkEvent.c (Tk_HandleEvent):
+ * unix/tkUnixEvent.c (OpenIM):
+ * unix/tkUnixKey.c (TkpGetString):
+ * generic/tkInt.h: added TK_DISPLAY_XIM_SPOT flag bit for TkDisplay
+ and used this to allow a runtime check to see if over-the-spot XIM
+ is possible. If not it will try and fallback to the old-style
+ input context, which handles things like dead keys input.
+
+ * generic/tk.decls: added TIP #84 implementation that adds a
+ * generic/tkDecls.h: Tk_CollapseMotionEvents API which controls Tk's
+ * generic/tkEvent.c: collapsing of incoming motion events on its
+ * generic/tkInt.h: windows. The default remains to do collapsing.
+ * generic/tkStubInit.c: Added a flags parameter to the internal display
+ * generic/tkWindow.c: structure to support this and be used in the
+ * doc/QWinEvent.3: future for other bits. [Tk patch 564642]
+
+ * unix/mkLinks: updated from current docs
+
+2002-06-14 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tkEvent.c (TkXErrorHandler): Declare static
+ function to avoid compiler error with VC++.
+ * generic/tkBind.c (ExpandPercents): Cast argument to
+ Tk_GetAtomName in order to avoid compiler warning.
+
+2002-06-14 Joe English <jenglish@users.sf.net>
+
+ * doc/bind.n:
+ * generic/tk.h:
+ * generic/tkBind.c:
+ * generic/tkCanvWind.c:
+ * generic/tkCmds.c:
+ * generic/tkEvent.c:
+ * generic/tkFocus.c:
+ * generic/tkGrab.c:
+ * generic/tkGrid.c:
+ * generic/tkImage.c:
+ * generic/tkPack.c:
+ * generic/tkPlace.c:
+ * generic/tkPointer.c:
+ * generic/tkTextWind.c:
+ * generic/tkWindow.c:
+ * mac/tkMacSubwindows.c:
+ * mac/tkMacWindowMgr.c
+ * mac/tkMacWm.c:
+ * unix/Makefile.in:
+ * unix/tkUnixEmbed.c:
+ * unix/tkUnixWm.c:
+ * win/tkWinScrlbr.c:
+ * win/tkWinWindow.c:
+ * win/tkWinWm.c: Implementation of TIP #47 by Neil McKay
+ "Modifying Tk to Allow Writing X Window managers".
+ Add CirculateRequest, Create, MapRequest, ResizeRequest,
+ and ConfigureRequest event types;
+ Split TK_TOPLEVEL flag into TK_TOPLEVEL, TK_HAS_WRAPPER,
+ TK_WIN_MANAGED, and TK_TOP_HIERARCHY. [Tk patch 572978]
+
+2002-06-14 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * unix/tkAppInit.c: Removed now unneeded and erroneous reference
+ to 'matherr'. See Tcl ChangeLog entry 2002-05-31 Don Porter.
+
+2002-06-14 David Gravereaux <davygrvy@pobox.com>
+
+ * win/rules.vc: The test for compiler optimizations was in error.
+ Thanks goes to Roy Terry <royterry@earthlink.net> for his
+ assistance with this.
+
+2002-06-14 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ Implement TIP 98 [Tk patch 566765]
+
+ * doc/FindPhoto.3, generic/tk.h, generic/tk.decls:
+ * generic/tkImgPhoto.c: Changed *_Old to *_NoComposite and
+ USE_OLD_PHOTO_PUT_BLOCK to USE_COMPOSITELESS_PHOTO_PUT_BLOCK
+ following a suggestion from Don Porter.
+
+ * tests/imgPhoto.test: Added tests of -compositingrule
+
+ * doc/photo.n: Added documentation for "-compositingrule".
+ * generic/tkImgPhoto.c (ImgPhotoCmd, ParseSubcommandOptions): New
+ "-compositingrule" option for [$photo copy] subcommand, using
+ OPT_COMPOSITE flag and compositingRule field in SubcommandOptions
+ structure.
+
+ * doc/FindPhoto.3: Documented the extra argument for the
+ compositing rule and the action to take if anyone wants to
+ maintain total backward-compatability.
+
+ * generic/tk.h (TK_PHOTO_COMPOSITE_*): Defined values for use as
+ compositing rules.
+ (USE_OLD_PHOTO_PUT_BLOCK): Added a way for users to select the old
+ interface to Tk_PhotoPutBlock to provide an easier upgrade path.
+
+ * generic/tk.decls: Alter Tk_PhotoPut*Block to Tk_PhotoPut*Block_Old
+ and introduce new slots for the old name of function with an extra
+ argument at the end for the compositing rule.
+
+ * generic/tkImgPhoto.c (ImgPhotoCmd): Updated "transparency set"
+ subcommand to use TkSubtractRegion().
+
+ * win/tkWinRegion.c (TkSubtractRegion):
+ * mac/tkMacRegion.c (TkSubtractRegion):
+ * generic/tkInt.decls (TkSubtractRegion):
+ * unix/tkUnixPort.h (TkSubtractRegion): Added function to perform
+ the set-difference operation on regions; it seems all platforms
+ can support it, and it makes removing rectangular bits from
+ regions much easier.
+
+ * generic/tkImgPPM.c (FileReadPPM): Reading a PPM/PGM always uses
+ the SET compositing rule because it is faster and the format does
+ not have any transparency information.
+
+ * generic/tkImgGIF.c (FileReadGIF): Reading a GIF always uses the
+ SET compositing rule because GIF files model transparency as a
+ single special colour.
+
+ * generic/tkImgPhoto.c (Tk_PhotoPutBlock, Tk_PhotoPutZoomedBlock):
+ Added a compositing rule to allow better control over what happens
+ to transparent pixels when inserting data into a photo image.
+
+2002-06-13 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * tests/winfo.test: Add basic tests for winfo ismapped.
+
+2002-06-13 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * tests/unixWm.test:
+ * tests/wm.test: Move wm minsize and wm maxsize
+ usage tests into the cross platform wm tests.
+
+2002-06-13 Don Porter <dgp@users.sf.net>
+
+ * tests/cursor.test: corrected error after cursor-2.2.
+ * tests/defs.tcl: Added enhancements to Tk's fake version of
+ tcltest required by recent cursor.test changes.
+
+2002-06-13 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/cursor.test (cursor-2.[34]): Tests added to ensure that
+ cursor specs really are well-behaved lists. Also some general
+ clean-up...
+ * win/tkWinCursor.c (TkGetCursorByName): Undone Jeff's back-off
+ and fixed things so that they should work now. Cursor specs are
+ lists first and foremost.
+
+2002-06-12 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * changes: Clearly label wm transient changes as
+ a POTENTIAL INCOMPATIBILITY.
+ * doc/wm.n: Remove "some window managers will" text
+ and explicitly state what behavior a transient
+ window will display. Also mention that it is an
+ error to make a window a transient of itself.
+
+2002-06-12 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * library/choosedir.tcl (tk::dialog::file::chooseDir):
+ * library/clrpick.tcl (tk::dialog::file::chooseDir):
+ * library/msgbox.tcl (tk::MessageBox):
+ * library/tkfbox.tcl (tk::dialog::file):
+ * library/xmfbox.tcl (tk::MotifFDialog): Remove the
+ transient property on dialogs after they have been
+ dismissed to insulate them from further state changes
+ in the master. This keeps a withdrawn dialog from
+ being mapped when the master is deiconified. [Tk patch 568278]
+
+2002-06-12 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinCursor.c (TkGetCursorByName): reverted fix from
+ 2002-06-06 because it broke the ability to use built-in cursors
+ like left_ptr.
+
+2002-06-12 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * library/choosedir.tcl (tk::dialog::file::chooseDir):
+ * library/clrpick.tcl (tk::dialog::color):
+ * library/dialog.tcl (tk_dialog):
+ * library/msgbox.tcl (tk::MessageBox):
+ * library/tkfbox.tcl (tk::dialog::file):
+ * library/xmfbox.tcl (tk::MotifFDialog_Create):
+ Only make the dialog window a transient if
+ the master is visible. This check already
+ appeared in some of the dialogs. This patch
+ just copies the check into those that were
+ lacking. [Tk patch 568253]
+
+2002-06-12 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * changes: Add note about new transient behavior.
+ * tests/unixWm.test: Check that the WM_TRANSIENT_FOR
+ property for a transient window is being cleared
+ when the master is destroyed.
+ * tests/wm.test: Source defs.tcl instead of using
+ tcltest to match the rest of Tk's test files.
+ Add new tests that ensure that a transient's state
+ mirrors the state of the master.
+ * unix/tkUnixWm.c (WmInfo, TkWmNewWindow, TkWmMapWindow)
+ (TkWmDeadWindow, Tk_WmCmd, WmWaitMapProc): Add numTransients
+ member to WmInfo structure. Keep state of master and
+ transient in sync using a callback that tracks MapNotify
+ and UnmapNotify events. When the master is mapped, map
+ the transient. When the master is unmapped or iconified,
+ withdraw the transient.
+ * win/tkWinWm.c (TkWmMapWindow, TkpWmSetState)
+ (TkWmDeadWindow, Tk_WmCmd, WmWaitVisibilityOrMapProc):
+ Keep state of master and transient in sync using a
+ callback that tracks MapNotify and UnmapNotify events.
+ Move masterPtr check from TkpWmSetState into TkWmMapWindow
+ to deal with WM_NEVER_MAPPED transients. Cleanup
+ numTransients and the callback in TkWmDeadWindow.
+ Cleanup numTransients and the callback only after
+ deleting a master in wm transient command to avoid
+ deleting the callback when an error is raised.
+ Add support for MapNotify and UnmapNotify events
+ to the master callback. [Tk patch 561708]
+
+2002-06-11 Joe English <jenglish@users.sf.net>
+
+ * library/menu.tcl: fix for bug report #530212 "Bad Window Path
+ Name in tkMenuFind"
+
+2002-06-10 David Gravereaux <davygrvy@pobox.com>
+
+ * win/makefile.vc: Fixed a win98 issue where the /exclude option
+ for xcopy is unsupported.
+ Reported by Roy Terry <royterry@earthlink.net>.
+
+2002-06-10 Anton Kovalenko <a_kovalenko@users.sourceforge.net>
+
+ * library/tk.tcl: added utility functions to get "-underline" and
+ "-text" for labels and buttons from translatable string containing
+ "magic ampersand" [patch #566605]
+ * library/clrpick.tcl:
+ * library/msgbox.tcl:
+ * library/tkfbox.tcl:
+ * library/xmfbox.tcl: some places where msgcat is used to get
+ translated label are modified to handle labels with magic ampersand.
+ * library/msgs/ru.msg: russian translations added
+ * library/msgs/cs.msg:
+ * library/msgs/de.msg:
+ * library/msgs/el.msg:
+ * library/msgs/es.msg:
+ * library/msgs/fr.msg:
+ * library/msgs/it.msg:
+ * library/msgs/nl.msg: all translation files now have labels with
+ 'magic ampersand' where appropriate. In el.msg some ampersands are
+ missing, as I don't know which underline positions seems natural
+ to "el" users.
+
+2002-06-09 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * library/bgerror.tcl (tk::dialog::error::bgerror):
+ Don't set the bgerror dialog as a transient of
+ itself since this operation is ill defined.
+
+2002-06-06 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * win/tkWinCursor.c (TkGetCursorByName): Fixed so that the reading
+ of cursors from a file with a cursor spec was built using [list]
+ works when the file has a space in instead of requiring fiddling
+ with backslashes.
+
+2002-06-06 Anton Kovalenko <a_kovalenko@users.sourceforge.net>
+
+ * library/msgbox.tcl (MessageBox): Add -default normal
+ when creating non-default buttons for message box.
+ They already get -default normal when they're
+ unfocused, and dialog window size used to change suddenly
+ in such cases.
+
+2002-06-05 Anton Kovalenko <a_kovalenko@users.sourceforge.net>
+
+ * unix/tkUnixFont.c (Tk_DrawChars): Don't assume that
+ one char is always one byte, and that required
+ subfont for the last character in any string is
+ the same as for the previous character
+ [Bug #559435] [Patch #559437]
+
+2002-05-27 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * changes: Document [wm transient .t .t] error.
+ * tests/wm.test: Check that setting a window
+ as a transient of itself raises an error. Check
+ that passing a non-toplevel window to the wm
+ transient command uses the enclosing toplevel.
+ * unix/tkUnixWm.c (Tk_WmCmd): Raise an error
+ if the user tries to make a toplevel a
+ transient of itself.
+ * win/tkWinWm.c (Tk_WmCmd): Raise an error
+ if the user tries to make a toplevel a
+ transient of itself. Test for other error
+ before checking for the transient self error.
+
+2002-05-27 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/tkUnixWm.c (WmInfo, TkWmCleanup, TkWmNewWindow)
+ (TkWmMapWindow, TkWmDeadWindow, Tk_WmCmd): Replace
+ WmInfo's master and masterWindowName members with
+ a masterPtr member. This implementation is much
+ simpler and mirrors the Win32 implementation. This
+ change makes it easy to check the flags of the
+ master window. No user visible changes.
+
+2002-05-27 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tkInt.decls: Add unix decl for TkpWmSetState.
+ * generic/tkIntPlatDecls.h: Regen.
+ * generic/tkStubInit.c: Regen.
+ * tests/wm.test: Test state changes between iconic,
+ normal, and withdrawn both before and after initial
+ mapping.
+ * unix/tkUnixWm.c (Tk_WmCmd, TkpWmSetState): Move
+ state change code into TkpWmSetState to more closely
+ match the Win32 implementation. No user visible changes.
+
+2002-05-27 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * tests/embed.test: Added cross platform embed tests.
+ Check that window passed to -use has the -container
+ option set.
+ * tests/wm.test: Remove useless catch call. Deiconify
+ . just in case, stackorder tests will not pass unless
+ it is in the normal state. Add -container flag to
+ embedded stackorder test.
+ * unix/tkUnixEmbed.c (TkpUseWindow):
+ * win/tkWinEmbed.c (TkpUseWindow): Lookup Tk window
+ based on the id passed in as the value for -use.
+ Generate an error if the Tk window did not have
+ the -container option set.
+
+2002-05-26 Peter Spjuth <peter.spjuth@space.se>
+
+ * generic/tkButton.c (ConfigureButton): When creating
+ a radiobutton with -value "" it was not drawn properly
+ if the -variable was created by the radiobutton.
+ [Bug #548765]
+
+2002-05-26 Peter Spjuth <peter.spjuth@space.se>
+
+ * generic/tkCanvText.c (ComputeTextBbox): Negative
+ coordinates were rounded badly causing a 1 pixel
+ displacement. [Bug #556526]
+
+2002-05-24 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * mac/tkMacWm.c (Tk_WmCmd):
+ * tests/unixWm.test: Move wm transient checks over
+ to wm.test so they will be run on all systems.
+ * tests/wm.test: Add tests to check for error when
+ an iconwindow is passed to the wm transient command.
+ * unix/tkUnixWm.c (Tk_WmCmd):
+ * win/tkWinWm.c (Tk_WmCmd): Raise an error if one
+ of the windows passed to the wm transient command
+ is an iconwindow for another toplevel.
+
+2002-05-23 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * mac/tkMacWm.c (TkWmStackorderToplevelWrapperMap):
+ * tests/wm.test: Add embedded Window test case for
+ the stackorder command.
+ * unix/tkUnixWm.c (TkWmStackorderToplevelWrapperMap):
+ * win/tkWinWm.c (TkWmStackorderToplevelWrapperMap):
+ Ignore embedded windows during wm stackorder command.
+
+2002-05-21 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure: Regen.
+ * unix/configure.in: Invoke SC_ENABLE_SHARED before
+ calling SC_CONFIG_CFLAGS so that the SHARED_BUILD
+ variable can be checked inside SC_CONFIG_CFLAGS.
+ * unix/tcl.m4: Update from Tcl.
+
+2002-05-20 Don Porter <dgp@users.sourceforge.net>
+
+ * library/tk.tcl: A little namespace cleanup on Daniel Steffen's
+ latest revisions to avoid defining new global commands.
+
+2002-05-20 Daniel Steffen <das@users.sourceforge.net>
+
+ * mac/tkMacInit.c:
+ * mac/tkMacTclCode.r: include msgcat package in resources
+ as bgerror depends on it. Restores ability of mac static
+ build to run standalone (except for encoding file issues).
+
+ * mac/tkMacInit.c:
+ * library/console.tcl:
+ * library/tk.tcl: fix tk.tcl not sourcing library files
+ that define bindings at startup on mac. (independent of
+ tk library files being in resources or on auto_path)
+
+2002-05-08 Don Porter <dgp@users.sourceforge.net>
+
+ * library/bgerror.tcl:
+ * library/tclIndex: Cleaned up namespace usage of the bgerror
+ dialog. Completes soft dependence on msgcat. [FR 539309]
+
+2002-05-07 David Gravereaux <davygrvy@pobox.com>
+ * win/makefile.vc: Problem with TCLDIR macro not accepting
+ forward slash path seperators resolved. Added the same logic
+ to INSTALLDIR, too. [Bug #553208]
+
+2002-04-26 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/configure:
+ * unix/tcl.m4: change HP-11 SHLIB_LD_LIBS from "" to ${LIBS} so
+ that the .sl knows its dependent libs.
+
+2002-04-24 Daniel Steffen <das@users.sourceforge.net>
+
+ * mac/tkMacTclCode.r:
+ * mac/tkMacResource.r: added check of
+ TCLTK_NO_LIBRARY_TEXT_RESOURCES #define to allow disabling the
+ inclusion of the tk library code in the resource fork of Tk
+ executables and shared libraries.
+ Moved tk library code inclusion to separate file like in tcl.
+ Added 'panedwindow' resource.
+
+2002-04-22 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/button.tcl (ButtonLeave): corrected the 3
+ implementations of ButtonLeave to check for Priv(relief) existing
+ before trying to use it. [Patch #541849]
+
+ * generic/tkTextDisp.c (DisplayLineBackground):
+ * unix/tkUnix3d.c (Tk_3DHorizontalBevel):
+ * unix/tkUnixFont.c (Tk_DrawChars): applied fixes to not overrun
+ the X window 16-bit size limit. [Patch #541999] (bonfield)
+
+2002-04-22 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tkTextDisp.c (GetXView, GetYView): Comparison with
+ previous values of scrollbar range are now done in a way that is
+ sensitive to the bizarreness of floating-point on architectures
+ where IEEE-FP is not used on the processor. Also increased the
+ size of the temporary buffer to take account of the fact that
+ TCL_DOUBLE_SPACE is meant to only imply enough space to take a
+ printed double and trailing '\0', and no more. [Bug #223739]
+ (FP_EQUAL_SCALE): New macro to help compare floating-point numbers
+ for equality in a sane way, used in GetXView and GetYView.
+
+2002-04-12 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkWindow.c (TkCloseDisplay): Added to centralize where a
+ display was closed. This handles freeing memory associated with a
+ display and closing it.
+ (DeleteWindowsExitProc): actually close displays. This would also
+ ideally be done in Tk_DestroyWindow when the last window on the
+ display has been closed, but that still has unresolved order of
+ cleanup problems.
+ (Tk_DestroyWindow): added TkFocusFree call.
+
+ * generic/tkStubInit.c:
+ * generic/tkIntPlatDecls.h:
+ * generic/tkIntDecls.h:
+ * generic/tkInt.decls: added TkFocusFree, TkClipCleanup and
+ TkGCCleanup generic private procs, and TkWmCleanup, TkSendCleanup
+ and TkFreeXId unix private procs.
+
+ * generic/tkInt.h:
+ * unix/tkUnixXId.c (TkFreeXId): frees XID resources.
+ Made idCleanupScheduled a Tcl_TimerToken (was int) in TkDisplay
+ structure to allow us to delete the timer scheduled for it.
+
+ * unix/tkUnixWm.c (TkWmStackorderToplevel): ensure children
+ structure is freed.
+ (ConfigureEvent, ComputeReparentGeometry): Add extra wm tracing info
+ (TkWmRestackToplevel): initialize changes to 0 to prevent UMR.
+ Use WaitForConfigureNotify on all windows. This part still
+ requires fixing as it is the root of the 2 second raise delay on
+ some window managers (those that use extra wrapper windows of
+ their own).
+
+ * unix/tkUnixSend.c (TkSendCleanup): free send-related resources
+
+ * unix/tkUnixEvent.c (TkpCloseDisplay): call TkSendCleanup and
+ TkWmCleanup.
+
+ * unix/tkUnixSelect.c (SelRcvIncrProc): added missing Tcl_Release
+ of interp
+
+ * generic/tkGet.c (FreeUidThreadExitProc): free thread-specific
+ resources on thread exit
+
+ * generic/tkFocus.c (TkFocusFree): frees TkMainInfo data
+ * generic/tkClipboard.c (TkClipCleanup): frees TkDisplay data
+ * generic/tkGC.c (TkGCCleanup): frees TkDisplay data
+
+ * unix/tkUnixFont.c (FontPkgCleanup): cleanup thread specific font
+ resources on thread exit.
+
+ * mac/tkMacXStubs.c (TkpOpenDisplay): memset the initial display
+ structures to 0.
+
+ * generic/tkOption.c (OptionThreadExitProc): freed tsd option
+ stacks on thread exit.
+ (Tk_GetOption): free mem used to get Tk_Uid
+
+ * generic/tkMenu.c (ConfigureMenu): freed saved options in all
+ error cases.
+
+ * win/tkWinInt.h: declaration for TkWinGetUnicodeEncoding
+ * win/tkWinDialog.c (GetFileNameW): use TkWinGetUnicodeEncoding
+ * win/tkWinInit.c (TkpDisplayWarning): use TkWinGetUnicodeEncoding
+ * win/tkWinFont.c: use TkWinGetUnicodeEncoding instead of static
+ unicodeEncoding.
+
+ * win/tkWinX.c (Tk_SetCaretPos): remove WM_IME_STARTCOMPOSITION
+ and place the IME position within Tk_SetCaretPos. Cache results in
+ Tk_SetCaretPos to reduce unnecessary repositioning. Also call
+ DestroyCaret if we receive WM_KILLFOCUS.
+ (TkpOpenDisplay): ZeroMemory the initial display structures.
+ (TkWinGetUnicodeEncoding): Added so that Windows only needs to
+ cache this value one, and then free it in TkWinXCleanup.
+ (HandleIMEComposition): add support for Win98 and ATOK13
+ IME. (yamamoto)
+
+ * generic/tkConsole.c (ConsoleCmd): correct return that should
+ have just set result code.
+
+ * generic/tkImgPhoto.c: Added PhotoFormatThreadExitProc to clean
+ up on thread exit. (Tk_PhotoPutBlock) slight code updates
+
+ * generic/tkPanedWindow.c (DestroyPanedWindow, ConfigureSlaves):
+ fix mem leaks in not freeing slave info
+
+ * win/configure:
+ * win/tcl.m4: Enabled COFF as well as CV style debug info with
+ --enable-symbols to allow Dr. Watson users to see function info.
+ More info on debugging levels can be obtained at:
+ http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp
+
+2002-04-10 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * doc/wm.n:
+ * mac/tkMacWm.c:
+ * tests/wm.test:
+ * unix/tkUnixWm.c:
+ * win/tkWinWm.c: Update wm stackorder usage message
+ to make it clear that either 1 or 3 arguments are
+ required. [Bug 540013]
+
+2002-04-08 Daniel Steffen <das@users.sourceforge.net>
+
+ * mac/tkMacProjects.sea.hqx: added tkPanedWindow.c to projects
+ * mac/tkMacAppInit.c: fixes to MSL stdin/stdout hookup to the
+ TkConsole when using shared MSL libraries; fix for crashing
+ bug on exit: writing to stdin/sterr when console has already
+ been destroyed. (both fixes need support in MSL, see
+ 'CW Pro6 changes' in tcl/mac/tcltkMacBuildSupport.sea.hqx)
+ * mac/tkMacDialog.c: fixes to Navigation Services Dialog filter.
+ * mac/tkMacDraw.c: add panic for overwide TkImages that would
+ crash Tk on mac otherwise.
+
+2002-04-05 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * mac/tkMacXStubs.c: added Tk_SetCaretPos stub (does nothing).
+ * win/tkWinX.c: added Tk_SetCaretPos code to position IME windows
+ correctly when WM_IME_STARTCOMPOSITION is received.
+ * unix/tkUnixKey.c: added Tk_SetCaretPos and code for setting
+ XIM caret in TkpGetString.
+
+ * generic/tkStubInit.c:
+ * generic/tkDecls.h:
+ * generic/tk.decls: added Tk_SetCaretPos declaration. This command
+ allows users to indicate the cursor position and is used by XIM
+ (Unix) or IME (Windows) to place the caret box correctly. It is
+ also part of correct Accessibility style on Windows to make the
+ magnifier jump to the focus point.
+
+ * win/tkWinButton.c (TkpDisplayButton):
+ * generic/tkTextMark.c (TkTextInsertDisplayProc):
+ * generic/tkCanvText.c (DisplayCanvText):
+ * generic/tkEntry.c (DisplayEntry): added Tk_SetCaretPos calls
+
+ * generic/tkInt.h: added TK_XIM_SPOT #define (default 1).
+ Added XFontSet attribute to TkDisplay when TK_XIM_SPOT is true.
+ * generic/tkEvent.c (Tk_HandleEvent): made sure inputContexts are
+ not getting created on DestroyNotify events (for dead windows).
+ Added over-the-spot support if TK_XIM_SPOT is defined (default).
+ The is the nicer XIM behavior, but uses a bit more memory.
+
+ * unix/tkUnixEvent.c:
+ * generic/tkWindow.c: moved OpenIM over to tkUnixEvent.c.
+ Removed setting inputContext to null in Tk_MakeWindowExist as it
+ was redundant.
+
+ * unix/tkUnixWm.c (CreateWrapper): Removed redundat setting of
+ inputContext to null.
+
+ * win/Makefile.in: changed gdb and shell targets to properly build
+ all binaries before running (otherwise an error often occured).
+
+2002-03-28 David Gravereaux <davygrvy@pobox.com>
+
+ * win/.cvsignore (new):
+ * win/lamp.bmp (new):
+ * win/makefile.vc:
+ * win/nmakehlp.c (new):
+ * win/rules.vc: Brought the makefile up-to-date with Tcl's one.
+ This now has support for Win9x issues and the winhelp target now
+ exists. Color scheme can be changed. I'm just imparting a first
+ suggestion using orange :) I'll have to think about the install
+ portion of the helpfile as I'll need to do some tricks to insert
+ tk's contents file into Tcl's using some special winhlp32.exe
+ switches. [Bug 533862 527941]
+
+ * win/makefile.vc: Tk helpfile is now installing itself into Tcl's
+ contents file as part of the install target and rebuilding the
+ contents table as desired. [Bug 527941]
+
+ * doc/console.n: Changed topic from "Tcl Built-In Commands" to
+ "Tk Built-In Commands"
+
+ * win/buildall.vc.bat: Update to match Tcl.
+
+2002-03-26 Andreas Kupries <andreask_kupries@users.sourceforge.net>
+
+ * unix/tkUnixFont.c: Added inclusion of <arpa/inet.h>. This fixes
+ a GCC/HPUX problem with missing a "htons". See also
+ "tclUnixPort.h" for equivalent code.
+
+2002-03-21 David Gravereaux <davygrvy@pobox.com>
+
+ * win/makefile.vc: Changed optimize flag to -0ti instead of -02.
+ [Bug 528441]
+
+2002-03-20 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkButton.c (ButtonTextVarProc,ButtonVarProc):
+ * generic/tkCmds.c (WaitVariableProc):
+ * generic/tkEntry.c (EntryTextVarProc):
+ * generic/tkListbox.c (ListboxListVarProc):
+ * generic/tkMenu.c (MenuVarProc):
+ * generic/tkMenubutton.c (MenuButtonTextVarProc):
+ * generic/tkMessage.c (MessageTextVarProc):
+ * generic/tkScale.c (ScaleVarProc): Updates to handle change in
+ type of part2 argument of Tcl_VarTraceProc typedef. [TIP 27]
+ [Patch 532644].
+
+2002-03-19 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkOldConfig.c (Tk_ConfigureValue): prevent leaving
+ interp->result as NULL.
+
+2002-03-07 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * library/text.tcl (TextPasteSelection): Renaming of TextPaste to
+ prevent confusion with tk_textPaste. Stopped code from inserting
+ selections twice, which seems to have happened with TIP#26, and
+ reorganized code to reduce amount of stuff protected by catch
+ which is tricky to maintain.
+ (tk_textPaste): Reduce amount of code protected by catch.
+
+2002-03-06 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/tkWinX.c: Define _WIN32_IE as 0x0300
+ before including commctrl.h so that we can
+ access the InitCommonControlsEx API when
+ building Tk with mingw.
+
+2002-03-06 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * README, generic/tk.h, unix/configure.in, unix/tk.spec:
+ * win/configure.in: Bumped patchlevel; this might need to change
+ in the future, but it will help us distinguish between the CVS
+ version and the most recent released version.
+
+2002-03-05 Jeff Hobbs <jeffh@ActiveState.com>
+
+ *** 8.4a4 TAGGED FOR RELEASE ***
+
+ * unix/README: updated --* options docs.
+
+ * unix/tk.spec: fixed URL refs to use www.tcl.tk or SF.
+
+2002-03-04 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * README:
+ * mac/README:
+ * unix/README:
+ * win/README: updated to use www.tcl.tk URL.
+
+2002-03-03 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/entry.tcl: added catch around Triple-1 binding use of
+ sel.last
+
+2002-02-28 Don Porter <dgp@users.sourceforge.net>
+
+ * library/console.tcl (ConsoleBind): Corrected console <<Paste>>
+ binding on Unix platforms.
+
+2002-02-26 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/configure: Regen.
+ * unix/tcl.m4: Update from Tcl.
+
+ * generic/tkWindow.c (Tk_MainWindow, Tk_GetNumMainWindows):
+ protect against being called before Tcl stubs are init'ed.
+ [Bug #220916] (porter)
+
+2002-02-25 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkText.c (ConfigureText): reenable the blinking cursor
+ on state change where necessary. [Bug #503772]
+
+ * tests/listbox.test:
+ * generic/tkListbox.c: corrected error handling when setting to an
+ invalid listvar value. [Bug #503613]
+
+ * library/scale.tcl: mirror B2 bindings to B3 on Windows to better
+ accomodate two button mice. [Patch #493145]
+
+ * library/panedwindow.tcl: improved proxy sash handling. (boudaillier)
+
+2002-02-25 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/filebox.test: Reorganised and fixed so that tests are
+ executed fewer times (!) and the automatic extension adding
+ behaviour of tk_getSaveFile is tested.
+
+2002-02-23 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure: Regen.
+ * unix/tcl.m4: Update from Tcl.
+
+2002-02-22 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkPanedWindow.c (PanedWindowWidgetObjCmd): fixed returns
+ that should have been breaks instead. Corrected .pw configure
+ handling for insufficient args. [Patch #521436] (boudaillier)
+
+ * mac/tkMacDefault.h:
+ * unix/tkUnixDefault.h:
+ * win/tkWinDefault.h: changed panedwindow default relief to flat,
+ a more natural outer relief.
+
+ * library/panedwindow.tcl (ReleaseSash): changed to not pass x and
+ y args at all (they aren't used).
+ Added proc comments. Made configuring sash cursor more efficient.
+ Added Cursor timer that restores the default cursor when pointer
+ is no longer over the sash. This is necessary because Leave
+ events won't be seen when moving into a paned child.
+
+2002-02-22 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * library/demos/widget: New section "Paned Windows"
+ * library/demos/paned2.tcl, library/demos/paned1.tcl: New files.
+
+ * library/panedwindow.tcl (ReleaseSash): Added missing arguments.
+ * library/tk.tcl: Bindings for paned window were not being loaded
+ by default.
+
+ * unix/tkUnixMenu.c (GetMenuLabelGeometry,DrawMenuEntryLabel):
+ Stop meaningless GCC warnings.
+
+2002-02-21 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * doc/panedwindow.n (new):
+ * generic/tkPanedWindow.c (new):
+ * generic/tkInt.h:
+ * generic/tkWindow.c:
+ * library/panedwindow.tcl (new):
+ * mac/tkMacDefault.h:
+ * tests/panedwindow.test (new):
+ * unix/Makefile.in:
+ * unix/tkUnixDefault.h:
+ * win/Makefile.in:
+ * win/makefile.vc:
+ * win/tkWinDefault.h: added implementation of TIP #41, panedwindow
+ widget. [Patch #512503] (melski)
+
+ * generic/tkOption.c (ReadOptionFile): fixed Tcl_Seek casting to
+ remove warnings (we expect no option files with be > 2GB).
+
+ * unix/configure: regenerated
+ * unix/tcl.m4: updated to sync with Tcl's tcl.m4
+ Added --enable-64bit support for AIX-4 using IBM's xlc (-q64 flag).
+
+2002-02-19 Don Porter <dgp@users.sourceforge.net>
+
+ * changes: First draft of updated changes for 8.4a4 release.
+
+2002-02-19 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tkImgPhoto.c (MatchFileFormat): Tcl_Seek takes
+ Tcl_WideInt offset (three places.)
+ * generic/tkImgPPM.c (FileReadPPM): Tcl_Seek takes Tcl_WideInt offset.
+ * generic/tkFrame.c (ConfigureFrame): Stop GCC warning.
+
+ * generic/tkImgGIF.c: Made file meet the formatting rules from the
+ Tcl Engineering Manual better; mostly differences in whitespace.
+
+2002-02-18 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/configure: regen'd
+ * unix/tcl.m4:
+ * unix/configure.in: added macros and calls to SC_TCL_EARLY_FLAGS
+ and SC_TCL_64BIT_FLAGS, part of TIP #72.
+
+2002-02-14 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * library/entry.tcl:
+ * library/text.tcl: Adjust <Double-1> and <Triple-1> bindings
+ so that no anchor point is set and the insertion cursor is
+ set to the last character in the selection. [Bug 220943]
+ * tests/event.test: Add test cases for double click and
+ drag as well as triple click and drag in the text and
+ entry widgets.
+
+2002-02-14 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * tests/event.test (_text_ind_to_x_y, _get_selection): Fix
+ incorrect use of results from bbox invocation so that
+ y center point for a give index is calculated correctly.
+ Add new method to return the selection and use it in
+ test cases. Always lappend to the result list to avoid
+ case where initial result includes a space.
+
+2002-02-07 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkMain.c:
+ * mac/tkMacInit.c:
+ * mac/tkMacKeyboard.c:
+ * win/tkWinDialog.c:
+ * win/tkWinTest.c: modified some callers of Tcl routines that
+ were restored to return (char *) pointing into Tcl_DStrings.
+
+2002-02-03 eric melski <ericm@interwoven.com>
+
+ * generic/tkImage.c (Tk_ImageObjCmd): Clean up bogus for loop in
+ [image inuse] subcommand [Bug #485803].
+
+2002-02-01 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkCmds.c (Tk_TkObjCmd): don't use 'bool' as an arg as it
+ conflicts with the C99 spec. [Bug #511956] (ingham)
+
+2002-02-01 David Gravereaux <davygrvy@pobox.com>
+
+ * win/makefile.vc: unset macro located in the tktest target
+ caused a failure to build. [Bug 511652]
+
+2002-01-30 Don Porter <dgp@users.sourceforge.net>
+
+ * win/stubs.c (XSetCommand): Overlooked CONSTification.
+
+2002-02-01 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/photo.n: Documented transparency subcommand.
+ * tests/imgPhoto.test (imgPhoto-4.40...imgPhoto-4.68): Tests for
+ the transparency subcommand.
+ * generic/tkImgPhoto.c (ImgPhotoCmd): Added transparency
+ subcommand (see TIP #14.)
+
+2002-01-31 Todd Helfter <tmh@users.sourceforge.net>
+ * generic/tkMenu.c (ConfigureMenuCloneEntries)
+ * tests/menu.test (menu3.68)
+ Correct and test for logic error when cloning menus. [Bug #508988]
+
+2002-01-30 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tk.decls: The POTENTIAL INCOMPATIBILITY in the changing
+ interface of Tk_ParseArgv can now be removed by the -DUSE_NON_CONST
+ compiler flag.
+ * generic/tkDecls.h: make genstubs
+
+2002-01-29 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * win/tkWinInit.c (TkpGetAppName): TIP 27 fixup. The code now does
+ not write into the CONST path returned by "argv0" and
+ Tcl_SplitPath anymore.
+
+2002-01-28 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure: Regen.
+ * unix/configure.in: Don't set TCL_LIB_SPEC and
+ TCL_STUB_LIB_SPEC variables since this breaks
+ the AIX build. This was used in the past to
+ support linking with Tcl from the build dir
+ or the install dir, but it is no longer needed.
+
+2002-01-28 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/Makefile.in: Remove commented out vars.
+ * unix/configure: Regen.
+ * unix/configure.in: Don't subst vars that are already
+ taken care of in SC_LOAD_TCLCONFIG.
+ * unix/tcl.m4: Update from Tcl.
+ * win/configure: Regen.
+ * win/tcl.m4: Update from Tcl.
+
+2001-01-27 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tkFileFilter.c:
+ * mac/tkMacInit.c:
+ * mac/tkMacKeyboard.c:
+ * mac/tkMacMenus.c: TIP 27 CONSTification induced changes
+
+2002-01-25 Don Porter <dgp@users.sourceforge.net>
+
+ * All changes below are Patch 505159
+
+ * doc/AddOption.3:
+ * doc/CanvTkWin.3:
+ * doc/GetPixels.3:
+ * doc/Name.3:
+ * doc/ParseArgv.3:
+ * generic/tk.decls (Tk_AddOption,Tk_CanvasGetCoord,Tk_GetPixels)
+ (Tk_GetScreenMM,Tk_NameToWindow,Tk_ParseArgv):
+ * generic/tkArgv.c (Tk_ParseArgv):
+ * generic/tkCanvLine.c (ParseArrowShape):
+ * generic/tkCanvUtil.c (Tk_CanvasGetCoord,Tk_CanvasTagsParseProc)
+ (Tk_CanvasTagsPrintProc,Tk_GetDash):
+ * generic/tkCanvas.c (ConfigureCanvas):
+ * generic/tkGet.c (Tk_GetPixels,Tk_GetScreenMM):
+ * generic/tkImgPhoto.c (ImgPhotoCmd):
+ * generic/tkMain.c (Tk_MainEx):
+ * generic/tkOldConfig.c (FormatConfigInfo):
+ * generic/tkOption.c (Tk_AddOption):
+ * generic/tkText.c (TextWidgetCmd,TkTextGetTabs,DumpSegment):
+ * generic/tkText.h (TkTextCreateTag):
+ * generic/tkTextTag.c (TkTextCreateTag):
+ * generic/tkWindow.c (Tk_NameToWindow,Initialize):
+ * mac/tkMacCursor.c (FindCursorByName,TkGetCursorByName):
+ * mac/tkMacWm.c (Tk_WmCmd):
+ * unix/tkUnixCursor.c (TkGetCursorByName):
+ * unix/tkUnixSend.c (ValidateName):
+ * unix/tkUnixWm.c (Tk_WmCmd):
+ * win/tkWinCursor.c (TkGetCursorByName):
+ * win/tkWinWm.c (Tk_WmCmd): Updated callers of Tcl_SplitList and
+ Tcl_Merge.
+ * generic/tkDecls.h: make genstubs
+ ***POTENTIAL INCOMPATIBILITY***
+ Includes a source incompatibility in the argv argument of Tcl_ParseArgv.
+
+ * generic/tkBind.c (DeleteVirtualEvent):
+ * generic/tkCanvas.c (ScrollFractions, CanvasWidgetCmd)
+ (CanvasUpdateScrollbars):
+ * generic/tkTestTag.c (TkTextTagCmd): Updated callers of
+ Tcl_GetStringResult. Rewrote PrintScrollFractions to
+ ScrollFractions to stop scribbling directly on interp->result.
+
+ * generic/tkInt.decls (TkGetDefaultScreenName, TkpDisplayWarning)
+ (TkpOpenDisplay):
+ * generic/tkCanvPs.c (Tk_PostscriptColor, Tk_PostscriptFont):
+ * generic/tkEntry.c (EntrySetValue, EntryValidateChange)
+ (ExpandPercents, EntryValueChanged, Tk_EntryObjCmd, DestroyEntry)
+ (ConfigureEntry, EntryComputeGeometry, InsertChars, DeleteChars)
+ (EntryFetchSelection, EntryTextVarProc, Tk_SpinBoxObjCmd)
+ (SpinboxWidgetObjCmd):
+ * generic/tkMain.c (Prompt):
+ * generic/tkMenu.c (MenuVarProc):
+ * generic/tkMenubutton.c (ConfigureMenuButton, MenuButtonTextVarProc):
+ * generic/tkMessage.c (ConfigureMessage, MessageTextVarProc):
+ * generic/tkWindow.c (GetScreen, Initialize):
+ * mac/tkMacInit.c (TkpInit, TkpDisplayWarning):
+ * mac/tkMacXStubs.c (TkGetDefaultScreenName, TkpOpenDisplay):
+ * unix/tkUnix.c (TkGetDefaultScreenName):
+ * unix/tkUnixEvent.c (TkpOpenDisplay):
+ * unix/tkUnixInit.c (TkpGetAppName, TkpDisplayWarning):
+ * unix/tkUnixSend.c (SendEventProc):
+ * win/tkWinInit.c (TkpGetAppName, TkpDisplayWarning):
+ * win/tkWinX.c (TkGetDefaultScreenName,TkpOpenDisplay): Updated
+ callers of Tcl_GetVar, Tcl_GetVar2
+ * generic/tkIntDecls.h: make genstubs
+
+ * generic/tkCanvPs.c (TkCanvPostscriptCmd):
+ * generic/tkImgBmap.c (TkGetBitmapData):
+ * generic/tkOption.c (ReadOptionFile):
+ * mac/tkMacInit.c (TkpInit, TkpGetAppName):
+ * win/tkWinInit.c (TkpGetAppName): Updated callers of
+ Tcl_SplitPath, Tcl_JoinPath, and Tcl_TranslateFileName.
+
+2002-01-18 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * tests/wm.test: Rewrite stackorder tests that
+ deal with toplevels that have the overrideredirect
+ flag set. [Tk bug 492259]
+
+2002-01-18 Don Porter <dgp@users.sourceforge.net>
+
+ * win/tkWinDialog.c: Overlooked Tcl_GetIndexFromObj callers.
+
+2001-01-18 Daniel Steffen <das@users.sourceforge.net>
+
+ * mac/tkMacDialog.c:
+ * mac/tkMacSend.c: TIP 27 CONSTification broke the mac
+ build in a few places.
+
+2002-01-16 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkListbox.c (ChangeListboxOffset): improved tracking
+ when scrolling on x axis with entry/text. [Bug #225025] (voskuil)
+
+2002-01-16 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tk3d.c (Tk_GetReliefFromObj):
+ * generic/tkBind.c (Tk_EventObjCmd, HandleEventGenerate):
+ * generic/tkButton.c (ButtonWidgetObjCmd):
+ * generic/tkCanvas.c (CanvasWidgetCmd, FindItems):
+ * generic/tkClipboard.c (Tk_ClipboardObjCmd):
+ * generic/tkCmds.c (Tk_BellObjCmd, Tk_TkObjCmd, Tk_TkwaitObjCmd)
+ (Tk_UpdateObjCmd, Tk_WinfoObjCmd, Tk_WmObjCmd):
+ * generic/tkConfig.c (DoObjConfig):
+ * generic/tkEntry.c (EntryWidgetObjCmd, SpinboxWidgetObjCmd):
+ * generic/tkFocus.c (Tk_FocusObjCmd):
+ * generic/tkFont.c (Tk_FocusObjCmd, ConfigAttributesObj):
+ * generic/tkFrame.c (Tk_FrameObjCmd):
+ * generic/tkGet.c (Tk_GetAnchorFromObj, Tk_GetJustifyFromObj):
+ * generic/tkGrab.c (Tk_GrabObjCmd):
+ * generic/tkGrid.c (Tk_GridObjCmd, GridRowColumnConfigureCommand)
+ (GridSlavesCommand, ConfigureSlaves):
+ * generic/tkImage.c (Tk_ImageObjCmd):
+ * generic/tkImgBmap.c (ImgBmapCmd):
+ * generic/tkImgGIF.c (FileReadGIF):
+ * generic/tkImgPhoto.c (ImgPhotoCmd):
+ * generic/tkListbox.c (ListboxWidgetObjCmd, ListboxSelectionSubCmd)
+ (GetListboxIndex):
+ * generic/tkMenu.c (MenuWidgetObjCmd, MenuAddOrInsert, MenuCmd)
+ (ConfigureMenu, CloneMenu):
+ * generic/tkMenubutton.c (MenuButtonWidgetObjCmd):
+ * generic/tkMessage.c (MessageWidgetObjCmd):
+ * generic/tkOption.c (Tk_OptionObjCmd):
+ * generic/tkPack.c (Tk_PackObjCmd, ConfigureSlaves):
+ * generic/tkPlace.c (Tk_PlaceObjCmd):
+ * generic/tkScale.c (ScaleWidgetObjCmd):
+ * generic/tkSelect.c (Tk_SelectionObjCmd):
+ * generic/tkSquare.c (SquareWidgetObjCmd):
+ * generic/tkTest.c (TestobjconfigObjCmd, TrivialConfigObjCmd)
+ (TestfontObjCmd): Updates to handle change in type of tablePtr
+ argument of Tcl_GetIndexFromObj(Struct) from (char **) to
+ (CONST char **). [TIP 27] [Patch 504705]
+
+ * generic/tkCanvText.c (GetSelText):
+ * generic/tkEntry.c (Entry{FetchSelection,Setvalue},ExpandPercents):
+ * generic/tkSelect.c (HandleTclCommand):
+ * generic/tkText.c (TextSearchCmd):
+ * generic/tkTextIndex.c (TkTextMakeByteIndex, TkTextIndexBackChars):
+ * mac/tkMacFont.c (Tk_MeasureChars, BreakLine):
+ * unix/tkUnixMenu.c (DrawMenuUnderline):
+ * win/tkWinMenu.c (GetEntryText, DrawMenuUnderline): Updated
+ callers of Tcl_Utf* and Tcl_Regexp* APIs to reflect TIP 27 API
+ changes (see Tcl Patch 471509). [Patch 471513]
+
+2002-01-16 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure: Regen.
+ * unix/tcl.m4: Update from Tcl.
+ * win/configure: Regen.
+ * win/tcl.m4: Update from Tcl.
+
+2002-01-04 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkMain.c (Tk_MainEx): Updated callers of CONSTified
+ Tcl interfaces Tcl_EvalFile and TclGetStartupScriptFileName.
+
+ * generic/tkConsole.c (ConsoleOutputProc, TkConsolePrint):
+ * generic/tkInt.h (TkConsolePrint):
+ * mac/tkMacAppInit.c (TkConsolePrint): Updated Tk's console to
+ CONSTified channel driver interface. [Tcl Patch 503565, Tk Patch
+ 503983]
+
+2002-01-11 Mo DeJong <mdejong@users.sourceforge.net>
+
+ Use ${libdir} instead of ${exec_prefix}/lib. [Tcl bug 489370]
+
+ * unix/configure: Regen.
+ * unix/configure.in: Define and use libdir.
+ * win/configure: Regen.
+ * win/configure.in: Define libdir.
+
+2002-01-11 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/Makefile.in: Burn Tcl and Tk build
+ directories into tktest executable to avoid crashes
+ caused by ld loading a previously installed version
+ of the tcl or tk shared libraries. Remove setting
+ of LD_LIBRARY_PATH, LIBPATH, and SHLIB_PATH
+ before running tktest since it should no
+ longer be required.
+
+2002-01-11 Mo DeJong <mdejong@users.sourceforge.net>
+
+ Enable use of Tcl stubs when building Tk as
+ a shared library. This should fix the build
+ under AIX. [Bugs 220858, 220955, 220921]
+
+ * unix/Makefile.in: Add TCL_STUB_LIB_SPEC and
+ TCL_STUB_LIB_FLAG variables.
+ * unix/configure: Regen.
+ * unix/configure.in: Pass TCL_STUB_LIB_SPEC into
+ Makefile and use it when linking the tk shared library.
+ Define USE_TCL_STUBS when building shared. Subst
+ TCL_STUB_LIB_SPEC and TCL_STUB_LIB_FLAG.
+
+2002-01-08 D. Richard Hipp <drh@hwaci.com>
+
+ * win/tkWinMenu.c: Fix the following bug: If you select an entry
+ on a cascade menu then the next time the parent menu is posted, the
+ cascade entry was active. Also, if you traverse to a disabled entry
+ using keystrokes and press ENTER on the disabled entry, then that
+ entry appears active the next time the menu is posted. The same
+ patch fixes both problems.
+
+2002-01-04 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkBind.c (TkBindFree):
+ * generic/tkGrid.c (ResolveConstraints,CheckSlotData,DestroyGrid):
+ * generic/tkSelect.c (Tk_DeleteSelHandler,TkSelDeadWindow): Replaced
+ Tcl_Free calls with ckfree so that memory debugging is fully supported.
+
+2001-12-28 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * test/winButton.test:
+ * win/tkWinButton.c: added updated patch #463234 which returns the
+ default sizing behavior (not so native), but enables native L&F
+ with negative sizing (-11 for example).
+
+ * library/text.tcl (tk::TextButton1): made text receive focus even
+ in disabled state for Windows to show selection and allow
+ mouse-wheel scrolling.
+
+ * win/tkWinInit.c (TkpDisplayWarning): added Tcl_DStringFree's
+
+ * win/tkWinInt.h:
+ * win/tkWinX.c: added TkWinProcs that represent a function table
+ to switch between unicode and ansi procs on Windows. This is
+ analogous to the TclWinProcs. Using Tcl_WinUtfToTChar, we can
+ easily take advantage of using unicode functions where available
+ without having to switch on the platform id each time.
+
+ * win/tkWinWm.c (InitWindowClass): corrected init routines to
+ allow unicode in window titles on Windows (for Win2K/XP).
+ (TkWmStackorderToplevel): Corrected casts to enable debug compile
+
+ * win/configure: regen'ed
+ * win/tcl.m4: added shell32.lib to link libs, as these are
+ necessary for new directory chooser (when enabled).
+
+ * win/tkWinDialog.c (Tk_MessageBoxObjCmd): use MessageBoxW for
+ proper display of unicode errors.
+ Added patch which uses new OLE based directory chooser. This
+ still has some issues, so is disabled by default. [Patch #468139]
+ (ColorDlgHookProc) Corrected ability to use unicode chars in
+ tk_chooseColor -title.
+
+2001-12-27 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinInit.c (TkpDisplayWarning): Use MessageBoxW in case the
+ error displayed has unicode chars. [Bug #485986]
+
+2001-12-27 Daniel Steffen <das@users.sourceforge.net>
+
+ * mac/tkMacInit.c:
+ * mac/tkMacResource.r: synced up tkInit features to unix/win:
+ use existing tkInit proc if defined. Added spinbox.tcl resource.
+ Used TclGetEnv() instead of Tcl_GetVar2(interp, env)
+ * mac/tkMacApplication.r:
+ * mac/tkMacLibrary.r: minor version resources cleanup
+
+2001-12-27 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkButton.c (ButtonTextVarProc): guard against being
+ called while the *button/label is being deleted. [Bug #490051]
+
+ * library/entry.tcl:
+ * library/spinbox.tcl:
+ * library/text.tcl: added extra checks against bug #220269 and
+ made spinbox reuse more of the entry procedure code.
+
+2001-12-20 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure: Regen.
+ * unix/tcl.m4: Update from Tcl.
+
+2001-12-19 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure: Regen.
+ * unix/tcl.m4: Update from Tcl.
+
+2001-12-18 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure: Regen.
+ * unix/configure.in: Move EXP file changes over from
+ Tcl configure script to fix AIX build with gcc. [Bug 220955]
+
+2001-12-18 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/Makefile.in:
+ * win/Makefile.in: Use $(MAKE) instead of make
+ in the tcltest rule.
+
+2001-12-18 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/event.test (event-click-drag-1.2): Corrected test that
+ failed on Solaris/CDE due to text scrolling. [Bug 413735]
+
+2001-12-18 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/spinbox.tcl (ButtonDown): added catch to ignore
+ possible error in after cancel when Priv(afterId) isn't defined.
+
+ * doc/spinbox.n: corrected spin(up|down) -> button(up|down)
+
+2001-12-14 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/getOpenFile.n: Documented change.
+ * library/tkfbox.tcl (SetFilter): Added code to guess the correct
+ default extension from whatever value was selected in the
+ filetypes option menu. Adapted from code by Chris Nelson
+ submitted in Patch #492220.
+
+2001-12-12 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/tkUnixWm.c (TkWmStackorderToplevelWrapperMap): added static
+
+2001-12-05 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkText.c:
+ * generic/tkText.h: changed TkTextEditType enums to be prefaced
+ with TK_EDIT_ to prevent name collision.
+
+2001-12-05 Daniel Steffen <das@users.sourceforge.net>
+
+ * mac/tkMacWm.c: mac implementation of wm stackorder
+ (patch 481148, TIP 74)
+
+2001-12-03 Mo DeJong <mdejong@users.sourceforge.net>
+
+ Add TK patch 481148 to implement TIP 74, the
+ wm stackorder command.
+
+ * doc/winfo.n: Update documentation for the winfo
+ children command to indicate that top-level windows
+ are not returned in stacking order.
+ * doc/wm.n: Add documentation for wm stackorder.
+ * generic/tkInt.decls (TkWmStackorderToplevel):
+ Add decl for new function.
+ * generic/tkIntDecls.h: Regen.
+ * generic/tkStubInit.c: Regen.
+ * tests/unixWm.test: Add stackorder command to test
+ for wm command usage message.
+ * tests/wm.test: Add new set of tests for generic
+ window manager methods.
+ * unix/tkUnixWm.c (Tk_WmCmd, TkWmStackorderToplevelWrapperMap)
+ (TkWmStackorderToplevel): Add unix implementation of
+ new wm stackorder command.
+ * win/tkWinWm.c (Tk_WmCmd, TkWmStackorderToplevelEnumProc)
+ (TkWmStackorderToplevelWrapperMap, TkWmStackorderToplevel): Add
+ windows implementation of new wm stackorder command.
+
+2001-12-03 David Gravereaux <davygrvy@pobox.com>
+
+ * win/makefile.vc: install target changes by request from
+ Ryan Casey <scfiead@hotmail.com>.
+
+2001-11-30 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * library/demos/widget: Further overhauling; shrank fonts, made
+ better use of fonts, added an icon, fixed the About box. Prompted
+ by Bug #487442 from Vincent Wartelle.
+
+2001-11-29 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * library/palette.tcl (tk_setPalette): Added heuristic to guess
+ from the background whether to use black or white for the
+ foreground when not told specifically. Suggested by Chris Nelson,
+ this makes the command fit the documentation better!
+
+2001-11-27 David Gravereaux <davygrvy@pobox.com>
+
+ * win/makefile.vc: Fixed CAT32 target. cat.c is located in the Tcl
+ source, not the Tk source.
+
+2001-11-27 D. Richard Hipp <drh@hwaci.com>
+
+ * library/menu.tcl: Do not allow keyboard traversal of torn-off
+ menus to visit the (invisible) tearoff bar.
+
+2001-11-26 D. Richard Hipp <drh@hwaci.com>
+
+ * win/tkWinMenu.c: disabled menu items show the activebackground
+ color in their background. This change makes menu behavior
+ consistent with what native windows does.
+
+2001-11-24 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/Makefile.in: Add comments to better describe
+ TCL_EXE and when it should be available. Add
+ rule that prints message about running `make genstubs`
+ when tkStubInit.c is out of date.
+ * win/Makefile.in: Add TCL_TOOL_DIR and TCL_EXE
+ variables to better match the Tcl Makefile. Add
+ genstubs rule so tkSTubInit.c can be regenerated.
+
+2001-11-24 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/configure: Regen.
+ * win/configure.in: Don't AC_SUBST CFLAGS_DEBUG, CFLAGS_OPTIMIZE,
+ or CFLAGS_WARNING since it is now done in SC_CONFIG_CFLAGS.
+ * win/tcl.m4 (SC_CONFIG_CFLAGS): AC_SUBST DL_LIBS, CFLAGS_DEBUG,
+ CFLAGS_OPTIMIZE, and CFLAGS_WARNING.
+
+2001-11-23 Daniel Steffen <das@users.sourceforge.net>
+
+ Up-port to 8.4 of mac code changes for 8.3.3 & various new
+ changes for 8.4, some already backported to 8.3.4 (patch #435660)
+
+ * library/tk.tcl: added <Key-F1> binding for <<Undo>> on the mac (TIP26)
+
+ * library/button.tcl: fixed undefined $Priv(repeated) error for button
+ without -repeatdelay support
+
+ * generic/tkConsole.c:
+ * library/console.tcl:
+ * mac/tkMacInit.c:
+ * mac/tkMacResource.r: corrected how mac deals with tcl library
+ files present both in resources and in $tk_library directory.
+
+ * generic/tkConsole.c: crashing bug fix when printing to console
+ at program exit after the console has already been closed.
+ Now setting gStdoutInterp=NULL in ConsoleClose().
+
+ * mac/tkMacInit.c: correct use of Tcl_JoinPath in tk_library
+ initialization
+
+ * mac/tkMacMenu.c: special MDEF_PROC_OFFSET only needed for
+ exactly one specific version of the MWERKS 68k compiler .
+
+ * mac/tkMacShLib.exp: removed file
+
+ * unix/Makefile.in: removed reference to .exp files
+
+ * mac/MWTkBuildLibHeader.h:
+ * mac/MW_TkBuildLibHeader.pch:
+ * mac/MW_TkHeaderCommon.h:
+ * mac/MW_TkOldImgStaticHeader.h:
+ * mac/MW_TkStaticHeader.h:
+ * mac/MW_TkStaticHeader.pch: new precompiled header files
+
+ * mac/MW_TkHeader.pch:
+ * mac/MW_TkOldImgHeader.h:
+ * mac/MW_TkTestHeader.pch: revised precompiled header handling: now
+ include a common header file 'MW_TkHeaderCommon.h' from all .pch files,
+ the .pch files themselves now only setup #defines (e.g. BUILD_tk,
+ STATIC_BUILD, TCL_DEBUG, TCL_THREADS) like in makefiles on other
+ platforms.
+
+ * mac/tkMac.h:
+ * mac/tkMacPort.h:
+ * mac/tkMacInt.h: use of BUILD_tk and TCL_STORAGE_CLASS like on other
+ platforms, standardize #include'd files to what's done on other
+ platforms, removed use of #pragma export, changed extern to EXTERN
+ where appropriate to enable DLL export via the TCL_STORAGE_CLASS
+ mechanism.
+
+ * mac/tkMacAppearanceStubs.c: removed use of #pragma export
+
+ * mac/widget.r: new resource file for 'Widget Demos'
+
+ * mac/tkMacProjects.sea.hqx: updated mac build project files:
+ build support for CodeWarrior Pro6, UnivIntf 3.4 & shared runtime
+ libraries (see Tcl ChangeLog for details).
+ changed weak linking so that CFM68k binaries now work on all OS
+ versions from the free 7.5.5 onwards, with or without AppearanceMgr
+ and/or NavigationMgr installed.
+ added target to automatically build 'Widget Demos'
+ included XML versions of the projects for CW Pro5 or Pro7 users.
+ use compat/strtod.c instead of MSL's strtod()
+
+ * generic/tkInt.decls:
+ * generic/tkIntDecls.h:
+ * generic/tkIntPlatDecls.h:
+ * generic/tkStubInit.c:
+
+ * mac/tkMacInt.h: MAC_TCL tk stub support was badly broken due to
+ multiply defined (mac specific) names in tk.decls and tkInt.decls,
+ removed the duplicates from the internal unsupported interfaces
+ "interface tkInt" and "interface tkIntPlat"; moved declaration of
+ TkpIsWindowFloating from tkMacInt.h to tkInt.decls: interface tkIntPlat.
+ - these changes to the stub tables might require you to recompile your
+ Tk extensions if they turn out to reference one of the removed routines
+ in the wrong table (should be unlikely).
+
+ * generic/tkMain.c: MAC_TCL: workaround for broken/non-standard isatty
+ on MW Pro6, #include <unistd.h> instead of defining isatty
+
+ * generic/tkPointer.c: MAC_TCL: #include tkMacInt.h
+
+ * generic/tkStubLib.c: MAC_TCL: removed obsolete special casing of mac
+ headers, standardize #include'd files to what's done on other platforms
+
+ * mac/tclets.r:
+ * mac/tkMacWindowMgr.c:
+ * mac/tkMacScrlbr.c:
+ * mac/tkMacMenu.c:
+ * mac/tkMacMenus.c:
+ * mac/tkMacFont.c:
+ * mac/tkMacDialog.c:
+ * mac/tkMacButton.c: renamed obsolete apple API names to modern
+ equivalents; UH3.4 support: added #include <ControlDefinitions.h>;
+ fixed munged non-ASCII chars in sources due to bungled latin1<->mac
+ roman encoding in CVS repository.
+
+ * mac/tkMacDialog.c: added support for -filetypes option (fix for bug
+ tcl #221636); added update event handling for background windows while
+ in a NavigationMgr dialog; fixed nasty bug when calling CustomGetFile
+ (missing addr operator) (fix for bug tk #220911 & tcl #219367); renamed
+ routines conflicting with standard MoreFiles headers (see Tcl ChangeLog
+ for details)
+
+ * mac/tkMacApplication.r:
+ * mac/tkMacLibrary.r:
+ * mac/tkMacResource.r: fixed obsolete copyrights/dates in version
+ strings, updated version strings to standard usage, added support for
+ '(Support Libraries)' subfolder for shared runtime libraries in
+ unmerged binaries, commented out demo setting of "Tcl Environment
+ Variables"; reorganized resources among these files to avoid
+ multiple copies in applications and shared libraries, the script
+ libraries/Xcursors etc are now no longer duplicated in Wish but are
+ only included in the resources of Tk.shlb.
+
+ * mac/tkMacMenu.c:
+ * mac/tkMacMDEF.r: changes to support MW Pro 6 68k (vers 0x2400 only)
+ compiler producing different offset to start of MDEF; fix to static 68k
+ presence testing when calling the custom MDEF
+
+ * mac/tkMacWm.c.c:
+ * mac/tkMacWindowMgr.c: added/fixed AppearanceMgr checks; override
+ AppearanceMgr version detection on static 68k to ensure static 68k Wish
+ runs on PPCs with recent AppearanceMgr
+
+ * mac/tkMacButton.c: fixed misplaced/missing variable initialization.
+
+2001-11-20 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkText.c (TextGetText): reworked to use DString for
+ improved speed. (callewaert, darley)
+ (DestroyText): plugged mem leak when not clearing stack (callewaert)
+ (TextGetText): more efficient string size calculation (darley)
+
+2001-11-19 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * library/demos/entry3.tcl: New demo showing off validation and
+ password entry.
+
+ * library/demos/widget: Some reorganization to make the code
+ simpler, plus a new entry demo.
+
+2001-11-17 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinButton.c (TkpComputeButtonGeometry): corrected the
+ default size of Windows buttons to conform to the Windows style.
+ This changes the default size of buttons on Windows.
+ [Patch #463234] (nelson)
+ **** POTENTIAL VISUAL INCOMPATABILITY ****
+
+2001-11-16 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/menu.tcl: corrected menu traversal code on Unix to
+ better handle entering cascades. [Patch #481219] (oleinick)
+
+2001-11-16 David Gravereaux <davygrvy@pobox.com>
+
+ * win/makefile.vc: Install target repaired.
+
+2001-11-15 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * library/demos/image2.tcl: Many improvements to this
+ image-viewing demo; now uses labelframes and tk_chooseDirectory
+
+ * library/palette.tcl (::tk::RecolorTree): Made this work better
+ with CDE, which does some extremely annoying things with the
+ option database that interact badly with Tk's way of handling
+ options.
+
+ * doc/text.n: Overhauled the documentation of undo to make it
+ easier to understand.
+ * library/tk.tcl (::tk::EventMotifBindings): Added Emacs-like undo
+ binding, but not behaviour (we separate undo and redo.)
+ * library/demos/text.tcl: Show off our undo capability!
+
+2001-11-12 David Gravereaux <davygrvy@pobox.com>
+
+ * win/mkd.bat:
+ * win/rmd.bat: Removed -kb CVS attribute and added changes
+ from Llyod Lim for better stability. [Patch #456761]
+
+ * win/rules.vc(new):
+ * win/buildall.vc.bat(new):
+ * win/makefile.vc: large rewrite following Tcl's makefile.vc as
+ a guide and Patch #456761. Appears BugFree(tm).
+
+2001-11-12 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * doc/text.n:
+ * generic/tkText.c:
+ * generic/tkText.h:
+ * generic/tkTextTag.c:
+ * library/text.tcl:
+ * library/tk.tcl:
+ * mac/tkMacDefault.h:
+ * tests/text.test:
+ * unix/tkUnixDefault.h:
+ * win/tkWinDefault.h: added TIP #26 implementation of simple
+ built-in undo/redo of text editing in the text widget.
+ [Patch #458879] (callewaert)
+
+2001-11-12 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * library/demos/menu.tcl: Show off -compound support in menus.
+
+ * library/demos/radio.tcl: Added some code to both show off the
+ extra capabilities of the buttons and also show what can be done
+ with compound images on the sly.
+
+2001-11-10 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/Makefile.in:
+ * win/Makefile.in: Add "make gdb" target. This target
+ can run wish inside either gdb or insight.
+
+2001-11-09 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/clrpick.tcl: changed a few parameters so that the full
+ 0..255 range could be accessed via the mouse. [Bug #478498]
+
+ * unix/configure:
+ * unix/tcl.m4: added -lc to AIX libs, fixed path to ldAix
+
+ * win/configure:
+ * win/tcl.m4:
+ * win/makefile.vc: add comctl32.lib to build libs.
+ * win/tkWinX.c (TkWinXInit): added InitCommonControlsEx call.
+ * win/rc/tk.rc:
+ * win/rc/wish.rc:
+ * win/rc/wish.exe.manifest: added resources that specify using v6
+ of the MS Common Controls library when available (WinXP+). This
+ enables use of the themeable widgets (like scrollbars) to be used
+ in Tk. [Patch #478933]
+
+2001-11-09 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure:
+ * unix/tcl.m4: Update from Tcl.
+
+2001-11-08 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/Makefile.in:
+ Avoid adding libc to the LIBS and WISH_LIBS
+ variables since it is not needed when linking with CC.
+ If required when linking with LD it should be done
+ on a case by case basis in tcl.m4.
+
+2001-11-05 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * library/demos/dialog2.tcl: Typo-fix.
+ * library/demos/browse, library/demos/ixset, library/demos/rolodex:
+ Installation does version number fixup, so we shouldn't. Thanks
+ to wohnivec@iol.cz for pointing these (thankfully minor) problems
+ out.
+
+2001-10-30 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * library/demos/widget: Integrated labelframe item into the labels
+ section and added a spinbox demo to the (retitled) entry section.
+
+ * library/demos/labelframe.tcl: Adjusted so as to show off the
+ labelframe widget to better effect and have a better description.
+
+ * library/demos/spin.tcl: New demo to show off spinbox capabilities.
+
+ * library/demos/rolodex: Changes up-ported from core-8-3-1-branch
+ to make the script use more 8.*-isms, but not menus due to the way
+ the context help system works.
+
+ * library/demos/ixset: Changed to use the labelframe widget and
+ the grid geometry manager.
+
+2001-10-29 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * library/demos/browse: Changes up-ported from core-8-3-1-branch
+ to make the script much more robust, particularly when neither the
+ current version of wish or the script are on the path.
+
+ * library/demos/hello: Added emacs trailing tag-line.
+
+ * library/demos/tcolor: Changes up-ported from core-8-3-1-branch
+ to make the script compliant with current good practise, as well
+ as extensive use of the new labelframe widget.
+
+ * library/demos/timer: Changes up-ported from core-8-3-1-branch to
+ make the script look and work better.
+
+ * library/demos/rmt: Changes up-ported from core-8-3-1-branch to
+ use more 8.* features and make the demo script more generally
+ useful to people.
+
+2001-10-23 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tkCursor.c (Tk_GetCursorFromData): Fixed uninit nextPtr
+ field. [adapted from Patch 473875]
+ (GetCursor): Removed double-assignment to nextPtr field.
+
+2001-10-19 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/console.tcl: removed transpose ability until the console
+ can get a proper rewrite of tag handling.
+
+2001-10-18 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * tests/defs.tcl: removed threaded build warning under X.
+
+ * library/console.tcl (ConsoleOutput): fixed undefined widget
+ argument.
+
+2001-10-16 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/xmfbox.tcl: fixed filtering in motif file dialog.
+ [Patch #469670] (nelson)
+
+ * generic/tkWindow.c (OpenIM): Added simple XIM patch to enable
+ basic XIM input on Unix. [Patch #412727] (fabian)
+
+2001-10-15 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/configure:
+ * unix/configure.in:
+ * win/configure:
+ * win/configure.in:
+ * win/tkConfig.sh.in: reworked to be a little cleaner in
+ comparison to each other, and to AC_SUBST even empty vars for
+ win/tkConfig.sh
+
+2001-10-12 Todd M. Helfter <tmh@purdue.edu>
+
+ * ChangeLog:
+ * doc/menu.n:
+ * generic/tkMenu.c:
+ * generic/tkMenu.h:
+ * generic/tkMenubutton.c:
+ * generic/tkMenubutton.h:
+ * mac/tkMacDefault.h:
+ * mac/tkMacMenu.c:
+ * mac/tkMacMenubutton.c:
+ * tests/menu.test:
+ * unix/tkUnixDefault.h:
+ * unix/tkUnixMenu.c:
+ * win/makefile.vc:
+ * win/tkWinDefault.h:
+ * win/tkWinMenu.c:
+ * win/tkWinWm.c: Implementation of TIP #63, the addition of
+ a -compound option to menu entries allowing text and an image to
+ be displayed at the same time.
+
+2001-10-09 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/console.tcl: added more smarts extracted from tkcon to
+ the default console.
+
+2001-10-01 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinTest.c: better error reporting from testclipboard
+
+ * win/tkWinDialog.c: minor cast changes to support Win64
+
+ * win/tkWinWindow.c: made use of standard Tk_GetHWND instead of
+ older, private TkWinGetHWND.
+
+ * win/configure: regen'ed
+ * win/tcl.m4:
+ * win/makefile.vc: updated for Win64 SDK RC1 compilation support
+
+2001-09-30 Peter Spjuth <peter.spjuth@space.se>
+
+ * doc/grid.n:
+ * generic/tkGrid.c:
+ * tests/grid.test: Added -uniform option to grid's row/column-
+ configure. [TIP 37] [Patch 459343]
+
+2001-09-26 Peter Spjuth <peter.spjuth@space.se>
+
+ * win/tkWinFont.c (Tk_DrawChars): Added support for clipping text.
+
+ * doc/frame.n:
+ * doc/labelframe.n:
+ * doc/toplevel.n:
+ * generic/tkFrame.c:
+ * generic/tkInt.h:
+ * generic/tkWindow.c:
+ * library/demos/radio.tcl:
+ * library/demos/labelframe.tcl:
+ * library/demos/widget:
+ * mac/tkMacDefault.h:
+ * tests/frame.test:
+ * unix/tkUnixDefault.h:
+ * win/tkWinDefault.h: Added labelframe widget. Added -padx/y
+ options to frame and toplevel.
+
+ * tests/grid.test:
+ * tests/pack.test:
+ * tests/place.test: Used labelframe to test geometry manager changes.
+ [TIP 18] [Patch 429164]
+
+2001-09-26 Peter Spjuth <peter.spjuth@space.se>
+
+ * doc/GeomReq.3:
+ * doc/WindowId.3:
+ * generic/tk.decls:
+ * generic/tk.h:
+ * generic/tkDecls.h:
+ * generic/tkGeometry.c:
+ * generic/tkGrid.c (ArrangeGrid):
+ * generic/tkInt.h:
+ * generic/tkPack.c (ArrangePacking):
+ * generic/tkPlace.c (RecomputePlacement):
+ * generic/tkStubInit.c:
+ * generic/tkUtil.c (TkComputeAnchor):
+ * generic/tkWindow.c (TkAllocWindow):
+ * unix/mkLinks: Geometry manager changes to support TIP#18.
+ Allows a widget to set different internal border widths on
+ different sides, and to set a minimum requested size.
+ POTENTIAL INCOMPATIBILITY. [Patch 429164]
+
+2001-09-25 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkBind.c:
+ * generic/tkInt.decls (TkpScanWindowId):
+ * unix/tkUnixPort.h (Tkp{Print,Scan}WindowId):
+ * unix/tkUnixXId.c (TkpScanWindowId):
+ * win/tkWinWindow.c (TkpScanWindowId): Corrected definition of
+ TkpScanWindowId to handle situation where types Window and int
+ do not have the same number of bits. CONST-ified too.
+
+ * generic/tkIntPlatDecls.h:
+ * generic/tkStubInit.c: make genstubs
+
+2001-09-24 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkMain.c (StdinProc): Update to handle change in
+ return type of Tcl_DStringAppend() from (char *) to (CONST char *).
+ [TIP 27]
+
+2001-09-23 Peter Spjuth <peter.spjuth@space.se>
+ * generic/tkPack.c (ConfigureSlaves):
+ * tests/pack.test:
+ * tests/grid.test: Pack accepted asymmetric values for -ipadx/y.
+ Only -padx/y supports asymmetry. [Bug #462348]
+
+2001-09-21 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinWindow.c (TkpPrintWindowId, TkpScanWindowId): fixed to
+ work on Win64 with 64bit XIDs.
+
+ * generic/tkWindow.c (Tk_CreateAnonymousWindow):
+ * generic/tkEntry.c (GetSpinboxElement): fixed unreachable returns.
+
+ * win/tkWinX.c (TkGetServerInfo): added recognition of Win64.
+
+ * xlib/X11/X.h: made XID __int64 type for Win64.
+
+ * unix/tkUnixPort.h:
+ * mac/tkMacPort.h: add (int*) cast to TkpScanWindowId.
+ These may need to be changed to Window* (ulong).
+
+ * generic/tkCmds.c (Tk_WinfoObjCmd):
+ * generic/tkBind.c (NameToWindow):
+ correct Window id's to be of type Window
+
+ * generic/tkIntDecls.h:
+ * generic/tkIntPlatDecls.h:
+ * generic/tkInt.decls (TkpScanWindowId): changed decl to use
+ Window* instead of int*.
+
+ * xlib/xcolors.c:
+ * generic/tkPack.c,tkWindow.c:
+ * win/tkWinFont.c,tkWinMenu.c:
+ * unix/tkUnixScale.c: minor cast fixes to prevent 64bit warnings.
+
+ * tests/scrollbar.test (scrollbar-6.27): marked knownBug because
+ it is skewed by bad dimensions returned by Windows.
+
+ * tests/textDisp.test (textDisp-4.12): corrected test to work
+ properly on Windows.
+
+ * tests/id.test,macFont.test,macMenu.test,macscrollbar.test:
+ * tests/send.test,winClipboard.test,winDialog.test,winFont.test:
+ improved use of test constraints
+
+ * win/tkWinWm.c (WinSetIcon): fixed SetClassLong for 64bit support.
+
+2001-09-20 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/configure: regen'ed
+ * unix/tcl.m4: added --enable-64bit support for HP-11 with the
+ 64-bit kernel.
+
+2001-09-17 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkGrid.c (ConfigureSlaves):
+ * generic/tkPack.c (PackAfter): Corrected type definition of
+ argument passed to Tcl_GetStringFromObj() from size_t to int.
+ Incorrect type broke [pack] and [grid] on systems where
+ sizeof(size_t) != sizeof(int). [Bugs 462375, 462342, 462338]
+
+2001-09-17 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * library/choosedir.tcl (DblClick):
+ * library/tkfbox.tcl (OkCmd, ListInvoke): Rewrote so as to avoid
+ the highly confusing string "text" and to be consistent about what
+ is and what is not a list. [Bug 459895, reported by fandom]
+
+2001-09-14 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * generic/tkImgGIF.c:
+ * generic/tkImgPPM.c:
+ * generic/tkImgPhoto.c:
+ * generic/tkMenu.c: Applied patch [461578], provided by Vincent
+ Darley. This fixes several memory leaks in the image code. They
+ happen if there are errors during the initialization of the
+ channel the image is supposed to be read from.
+
+2001-09-12 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure:
+ * unix/tcl.m4: Update from Tcl.
+
+2001-09-12 D. Richard Hipp <drh@hwaci.com>
+
+ * library/tkfbox.tcl: fixed error that appeared when you would
+ click on the canvas while viewing an empty directory.
+
+2001-09-10 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure:
+ * unix/tcl.m4: Update from Tcl.
+
+2001-09-09 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/Makefile.in: Fix Windows Makefile so that
+ tcltest will automatically be compiled if the
+ user tries to build tktest.
+
+2001-09-09 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/Makefile.in: Use TKTEST variable directly
+ instead of depending on the tktest alias.
+
+2001-09-08 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/mkd.bat:
+ * win/rmd.bat:
+ Apply binary property (cvs admin -kb) to files and convert
+ to CRLF linefeed format to fix the VC++ build. [Tcl Bug #219409]
+
+2001-08-29 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * tests/menu.test:
+ * tests/send.test:
+ * tests/select.test: corrected to use testConfig constraints in
+ the TK_ALT_DISPLAY case
+
+ * tests/unixSend.test: removed test file completely identical to
+ send.test. Removed platform specific named file in case somebody
+ gets send working on Win/Mac in the future.
+
+ * tests/config.test: added config-14.1 to test namespace import
+ evaluation of widgets.
+ * generic/tkButton.c (ButtonCreate):
+ * generic/tkFrame.c (CreateFrame):
+ * generic/tkMenubutton.c (Tk_MenubuttonObjCmd):
+ * generic/tkPlace.c (Tk_PlaceObjCmd):
+ * generic/tkScale.c (Tk_ScaleObjCmd):
+ * generic/tkMessage.c (Tk_MessageObjCmd):
+ * generic/tkEntry.c (Tk_EntryObjCmd, Tk_SpinboxObjCmd):
+ * generic/tkSquare.c (SquareObjCmd): redid the handling of
+ optionTables in widgets to allow them to be imported into other
+ namespaces. [Bug #456632]
+
+2001-08-28 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinDialog.c (ChooseDirectoryHookProc): work-around for MS
+ bug that caused crashing in tk_chooseDirectory on Win95.
+ [Bug #224936] (baker)
+
+ * unix/tkUnixWm.c (TkWmRestackToplevel): reworked how
+ ConfigureNotify requests were handled in relation to the parent to
+ avoid the problem with potential 'raise' delays on some wms.
+ [Bug #220260] (baker) wms that were affected should notice the
+ difference in tests unixWm-51.* not failing that failed before.
+
+2001-08-26 Don Porter <dgp@users.sourceforge.net>
+
+ * library/text.tcl (<Shift-Up> binding): Corrected TIP 44 typo
+ that broke binding. Thanks to "Michal" for the fix.
+ [Bug 455468]
+
+2001-08-23 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/configure:
+ * unix/tcl.m4: added QNX-6 build support. [Bug #219410] (loverso)
+
+ * doc/CrtPhImgFmt.3: removed bogus note about including tkPhoto.h
+
+2001-08-22 Peter Spjuth <peter.spjuth@space.se>
+
+ * generics/tkGrid.c (ConfigureSlaves):
+ * tests/grid.test: Fixed a bug where adjacent 'x' and '^' where
+ not handled properly. [Bug #452040]
+
+2001-08-22 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkPack.c (TkParsePadAmount): added lint init for sepChar.
+
+ * tests/dialog.test (HitReturn): fixed failing dialog-2.1 test
+ because it wasn't always getting focus properly.
+
+2001-08-21 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * tests/unixFont.test (unixFont-2.[234]): fixed to be more
+ sensitive on systems that have more installed fonts.
+
+ * library/dialog.tcl (tk_dialog): changed dialog to show bar on
+ Windows as well and added some y padding between the buttons and
+ the bar. [Patch #442835] (harrismh)
+
+2001-08-20 Peter Spjuth <peter.spjuth@space.se>
+
+ * generic/tkInt.h:
+ * generic/tkWindow.c:
+ * generic/tkGrid.c:
+ * generic/tkPack.c:
+ * tests/grid.test:
+ * tests/oldpack.test:
+ * tests/pack.test: Objectified grid and pack commands.
+
+2001-08-20 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tkObj.c (TkGetWindowFromObj): Rewrote window code to
+ reuse a previously worked-out set of window information exactly
+ when the reference window is the same and no window deletions have
+ occurred since the object was allocated (display has same epoch
+ counter.) Required changing the internal rep of the window quite
+ a bit as now need to save three words-worth of information in the
+ internal rep (this window, reference window, display epoch.)
+ * generic/tkObj.c (SetWindowFromAny, DupWindowInternalRep)
+ (FreeWindowInternalRep): Code to support new internal rep for
+ window objects.
+ * generic/tkInt.h: Added epoch counter to TkDisplay structure
+ * generic/tkWindow.c (GetScreen, Tk_DestroyWindow): Epoch counter
+ is incremented every time a window is deleted.
+
+2001-08-18 Peter Spjuth <peter.spjuth@space.se>
+
+ * doc/grid.n:
+ * tests/grid.test:
+ * generic/tkGrid.c: Grid configure rejected initial "x" and "^".
+ [Bug #418664]
+
+2001-08-17 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tkObj.c (TkGetWindowFromObj): Was failing to reuse
+ cached window objects, forcing a call to Tcl_GetStringFromObj and
+ Tk_NameToWindow every time. This fault has been in there for
+ nearly three years...
+
+2001-08-15 Don Porter <dgp@users.sourceforge.net>
+
+ * changes: Labelled the TIP 44 changes as "POTENTIAL INCOMPATIBILITY".
+ Although technically internal changes are not incompatible, they'll
+ be perceived as such by those who get bitten, and this will help
+ them find the cause of their trouble.
+
+2001-08-14 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tk{Util,Font,Cursor,Color,Bitmap,3d}.c: Modified
+ objtype declarations so that they can be picked up in tkObj.c and
+ the names are now prefixed with "tk" too.
+ * generic/tkObj.c (TkRegisterObjTypes):
+ * generic/tkWindow.c (Initialize):
+ * generic/tkInt.h: Added code to register Tk's object types with
+ the Tcl runtime. [Tcl Bug 450545]
+
+2001-08-12 Mo DeJong <mdejong@redhat.com>
+
+ * unix/configure: Regen.
+ * unix/tcl.m4: Update from Tcl.
+
+2001-08-10 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * library/demos/image2.tcl (loadDir): Converted non-portable
+ [glob [file join $dirName *]] to [glob -directory $dirName *]
+ which is both fully portable and more reliable when directory
+ names contain glob-significant characters. [Bug 223313]
+
+2001-08-08 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/dialog.test: New file testing [tk_dialog].
+
+ * library/dialog.tcl:
+ * library/tkfbox.tcl: Corrections to problems introduced by
+ the TIP 44 changes. [Bug 449261]
+
+ * README:
+ * generic/tk.h:
+ * unix/configure:
+ * unix/configure.in:
+ * unix/tk.spec:
+ * win/configure:
+ * win/configure.in: Bumped up patchlevel to 8.4a4 to distinguish
+ CVS snapshots from the 8.4a3 release. This does not necessarily
+ mean there will be an 8.4a4 release. [Bug 448938].
+
+2001-08-07 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/Makefile.in (dist): added {unix,win}/tcl.m4 and
+ library/msgs/*.msg to dist target. [Bug: #448802]
+
+2001-08-06 Jeff Hobbs <jeffh@ActiveState.com>
+
+ 8.4a3 RELEASE
+
+ * changes:
+ * README: updated for 8.4a3 release
+
+ * unix/configure: regenerated
+ * unix/tcl.m4: added GNU (HURD) configuration target. (brinkmann)
+ [Patch: #442974]
+
+2001-08-06 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkConsole.c:
+ * generic/tkWindow.c:
+ * library/bgerror.tcl:
+ * library/dialog.tcl:
+ * library/msgbox.tcl:
+ * library/unsupported.tcl:
+ * mac/tclets.tcl:
+ * mac/tkMacHLEvents.c:
+ * mac/tkMacWm.c: TIP 44 changes specific to the Mac and
+ Windows platforms that were overlooked before: tkOpenDocument,
+ tkConsoleExit, tkConsoleOutput, unsupported1 out of namespace :: .
+ Thanks to Vince Darley for prompting another look.
+
+2001-08-03 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/winMain.c (WishPanic): fixed CONST changes to go with
+ CONST-ification in Tcl.
+
+ * win/configure: regenerated
+ * win/tcl.m4: fixed DLLSUFFIX definition to always be ${DBGX}.dll.
+ This is necessary for TEA compliant builds that build shared
+ against a static-built Tk.
+ * win/Makefile.in ($(WISH)): added $(TK_STUB_LIB_FILE) to build
+ target, otherwise it wouldn't get generated in a static build.
+
+2001-08-01 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/console.n:
+ * doc/menu.n:
+ * doc/text.n:
+ * doc/tkvars.n:
+ * generic/tkBind.c:
+ * generic/tkMenu.c:
+ * library/bgerror.tcl:
+ * library/button.tcl:
+ * library/choosedir.tcl:
+ * library/clrpick.tcl:
+ * library/comdlg.tcl:
+ * library/console.tcl:
+ * library/dialog.tcl:
+ * library/entry.tcl:
+ * library/focus.tcl:
+ * library/listbox.tcl:
+ * library/menu.tcl:
+ * library/msgbox.tcl:
+ * library/optMenu.tcl:
+ * library/palette.tcl:
+ * library/scale.tcl:
+ * library/scrlbar.tcl:
+ * library/spinbox.tcl:
+ * library/tclIndex:
+ * library/tearoff.tcl:
+ * library/text.tcl:
+ * library/tk.tcl:
+ * library/tkfbox.tcl:
+ * library/unsupported.tcl:
+ * library/xmfbox.tcl:
+ * mac/tkMacMenu.c:
+ * tests/clrpick.test:
+ * tests/filebox.test:
+ * tests/macMenu.test:
+ * tests/menu.test:
+ * tests/menuDraw.test:
+ * tests/msgbox.test:
+ * tests/text.test:
+ * tests/unixMenu.test:
+ * tests/winMenu.test:
+ * tests/xmfbox.test:
+ * unix/mkLinks:
+ * unix/tkUnixDialog.c: Merged changes from feature branch
+ dgp-privates-into-namespace, implementing TIP 44. All
+ Tk commands and variables matching tk[A-Z]* are now in the
+ ::tk namespace. See "BRANCH: dgp-privates-into-namespace"
+ entries below for details. [FR 220936]
+
+2001-07-24 Mo DeJong <mdejong@redhat.com>
+
+ * generic/default.h: Include tkWinDefault.h
+ when built with Cygwin or Mingw.
+
+2001-07-18 Don Porter <dgp@users.sourceforge.net>
+
+ BRANCH dgp-privates-into-namespace:
+ * doc/console.n: Updated names of private console commands.
+
+2001-07-16 Don Porter <dgp@users.sourceforge.net>
+
+ BRANCH dgp-privates-into-namespace:
+ * library/console.tcl:
+ * library/unsupported.tcl: Renamed tk::histNum to tk::HistNum
+ as directed by the Tcl Style Guide.
+
+2001-07-10 Mo DeJong <mdejong@redhat.com>
+
+ * unix/Makefile.in: Add AR and STLIB_LD variables.
+ * unix/configure:
+ * unix/configure.in: Use STLIB_LD when defining MAKE_LIB
+ and MAKE_STUB_LIB. Subst STLIB_LD, RANLIB, and AR.
+ * unix/tcl.m4: Update from Tcl.
+ * win/configure: Regen.
+ * win/tcl.m4: Update from Tcl.
+
+2001-07-06 Mo DeJong <mdejong@redhat.com>
+
+ * win/configure: Regen.
+ * win/tcl.m4: Update from Tcl.
+
+2001-07-05 Mo DeJong <mdejong@redhat.com>
+
+ * win/Makefile.in: Subst DEPARG directly instead
+ of relying on a variable. This will make Cygwin
+ build faster since an extra exec will be avoided.
+ * win/configure: Regen.
+ * win/configure.in: Subst DEPARG.
+ * win/tcl.m4: Update from Tcl.
+
+2001-07-04 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * README:
+ * mac/README:
+ * unix/README:
+ * win/README: updated READMEs with purls
+
+2001-07-03 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * tests/canvas.test:
+ * generic/tkCanvPoly.c (PolygonToArea): Added patch that respects
+ the polygon difference of including points in the polygon even
+ when fill is empty. [Bug #226357]
+
+2001-07-03 Mo DeJong <mdejong@redhat.com>
+
+ * win/Makefile.in: Remove PATHTYPE variable.
+ * win/configure: Regen.
+ * win/configure.in: Don't subst PATHTYPE.
+ * win/tcl.m4: Update from Tcl.
+
+2001-07-03 Mo DeJong <mdejong@redhat.com>
+
+ * win/Makefile.in: Don't use VPSEP, instead just use :
+ in the VPATH.
+ * win/configure: Regen.
+ * win/configure.in: Don't subst VPSEP.
+
+2001-07-03 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * library/xmfbox.tcl (tkMotifFDialog_ActivateSEnt): Added missing
+ backslash [Bug #438247]
+
+2001-07-02 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkWindow.c (Tk_DestroyWindow): changed to use
+ Tcl_EventuallyFree instead of ckfree so that widgets that have
+ references to a tkwin can use them.
+
+ * generic/tkCanvArc.c:
+ * generic/tkCanvBmap.c:
+ * generic/tkCanvLine.c:
+ * generic/tkCanvPoly.c:
+ * generic/tkCanvText.c:
+ * generic/tkCanvWind.c:
+ * generic/tkRectOval.c: corrected argument handling in
+ Create<Item> functions that could lead to ABRs or FMRs and
+ corrected names of argc/argv to objc/objv.
+
+ * generic/tkImgGIF.c (Mgetc): corrected screwy use of ternary
+ operator and possible FMR.
+
+ * generic/tkEntry.c: corrected missing Tcl_Release that caused
+ font not freed complaints when trying valid cleanup calls.
+ * generic/tkListbox.c: made use of Tcl_Preserve/Tcl_Release to
+ prevent FMR errors in Display functions.
+
+ * unix/tkUnixScale.c (TkpDisplayScale): corrected FMR when scale
+ was deleted while calling its command.
+
+ * library/console.tcl:
+ * library/entry.tcl:
+ * library/spinbox.tcl:
+ * library/text.tcl:
+ * library/tk.tcl: added private ::tk::GetSelection command to
+ handle requesting selection. This is to support requesting
+ UTF8_STRING before generic STRING on Unix. Changed Text, Spinbox,
+ Entry and Console to use this command.
+
+ * tests/select.test:
+ * generic/tkSelect.c (Tk_CreateSelHandler, Tk_DeleteSelHandler):
+ on Unix, a UTF8_STRING handler will be created when the user
+ requests a STRING handler (in addition to the STRING handler).
+ This provides implicit support for the new UTF8_STRING selection
+ target.
+ * unix/tkUnixSelect.c (TkSelEventProc, ConvertSelection): Added
+ support for UTF8_STRING target. [RFE #418653, Patch #433283]
+
+ * generic/tkInt.h: added utf8Atom to TkDisplay structure.
+
+ * tests/listbox.test: changed 'darkblue' to 'white' in a test
+ because it isn't a portable color name.
+
+ * generic/tkEntry.c (DestroyEntry): used Tcl_EventuallyFree
+ instead of ckfree for entryPtr to prevent FMRs. [Bug #413904]
+
+2001-06-26 Mo DeJong <mdejong@redhat.com>
+
+ * unix/Makefile.in:
+ * win/Makefile.in: Add `make shell` target. This target
+ will set the proper env vars before invoking wish
+ from the build directory.
+
+2001-06-26 Mo DeJong <mdejong@redhat.com>
+
+ * win/configure:
+ * win/configure.in: Revert cross compiling change
+ accidently added during last checkin.
+
+2001-06-26 Mo DeJong <mdejong@redhat.com>
+
+ * unix/configure: Regen.
+ * unix/configure.in: Fix last checkin by removing
+ export since that only works in bash.
+ * win/configure: Regen.
+ * win/configure.in: Ditto.
+
+2001-06-26 Mo DeJong <mdejong@redhat.com>
+
+ * unix/configure: Regen.
+ * unix/configure.in: Set CFLAGS to "" if the user
+ did not set CFLAGS in the env. This keeps AC_PROG_CC
+ from adding "-g -O2" to the CFLAGS by default.
+ * win/configure: Regen.
+ * win/configure.in: Ditto.
+
+2001-06-22 Mo DeJong <mdejong@redhat.com>
+
+ * win/configure: Regen.
+ * win/configure.in: Use RC_DEFINE flag from tcl.m4.
+ * win/tcl.m4: Update from Tcl.
+
+2001-06-22 Mo DeJong <mdejong@redhat.com>
+
+ * win/configure: Regen.
+ * win/tcl.m4: Update from Tcl.
+
+2001-06-22 Mo DeJong <mdejong@redhat.com>
+
+ * win/configure: Regen.
+ * win/tcl.m4 (SC_CONFIG_CFLAGS): Link to the
+ imm32 library when building with mingw gcc.
+ * win/tkWinX.c: Include the imm.h header
+ to fix compiling with mingw gcc.
+
+2001-06-22 Mo DeJong <mdejong@redhat.com>
+
+ * win/configure: Regen.
+ * win/configure.in: Add resource compiler fix from
+ 8.3.3 to fix compiling with mingw.
+
+2001-06-22 Mo DeJong <mdejong@redhat.com>
+
+ * win/configure: Regen.
+ * win/tcl.m4: Fix silly typo in last checkin.
+
+2001-06-22 Mo DeJong <mdejong@redhat.com>
+
+ * unix/Makefile.in: Set CFLAGS to @CFLAGS@ and @CFLAGS_DEFAULT@.
+ Set LDFLAGS to @LDFLAGS@ and @LDFLAGS_DEFAULT@. Add LDFLAGS_DEBUG
+ and LDFLAGS_OPTIMIZE to match the way CFLAGS_DEFAULT works. Use
+ new LDFLAGS variable in the Makefile instead of @LDFLAGS@.
+ * unix/configure: Regen.
+ * unix/configure.in: Don't set CFLAGS to CFLAGS_DEFAULT, instead
+ subst CFLAGS_DEFAULT into the Makefile. Add AC_SUBST for CFLAGS_DEBUG,
+ CFLAGS_OPTIMIZE, LDFLAGS_DEFAULT, LDFLAGS_DEBUG, and LDFLAGS_OPTIMIZE.
+ Remove unused LD_FLAGS subst.
+ * unix/tcl.m4: Update from Tcl.
+ * win/Makefile.in: Set CFLAGS to @CFLAGS@ and @CFLAGS_DEFAULT@.
+ Set LDFLAGS to @LDFLAGS@ and @LDFLAGS_DEFAULT@.
+ * win/configure: Regen.
+ * win/configure.in: Don't set CFLAGS or LDFLAGS, instead subst
+ CFLAGS_DEFAULT and LDFLAGS_DEFAULT into the Makefile.
+ * win/tcl.m4: Update from Tcl.
+
+2001-06-22 Mo DeJong <mdejong@redhat.com>
+
+ * win/configure:
+ * win/tcl.m4: Update From Tcl.
+
+2001-06-21 eric melski <ericm@interwoven.com>
+
+ * doc/colors.n: Corrected bogus documentation with respect to
+ several shades of blue, all of which were listed as RGB 0 0 0.
+ [Bug #432104].
+
+2001-06-14 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * library/demos/floor.tcl, library/demos/filebox.tcl,
+ * library/demos/clrpick.tcl, library/demos/vscale.tcl,
+ * library/demos/twind.tcl, library/demos/ruler.tcl,
+ * library/demos/plot.tcl, library/demos/items.tcl,
+ * library/demos/hscale.tcl, library/demos/ctext.tcl,
+ * library/demos/cscroll.tcl, library/demos/arrow.tcl,
+ * library/xmfbox.tcl, library/msgbox.tcl,
+ * library/clrpick.tcl, library/bgerror.tcl: Braced expressions.
+
+2001-06-06 Mo DeJong <mdejong@redhat.com>
+
+ * win/configure: Regen.
+ * win/configure.in: Handle the --prefix option correctly
+ it should default to /usr/local like the unix version.
+
+2001-06-03 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * doc/selection.n:
+ * doc/clipboard.n: added SEE ALSOs to cross-reference selection
+ and clipboard, with extra note for clipboard command in selection
+ docs. [Patch #422256]
+
+ * unix/tkUnixFont.c: Corrected support for iso10646 (X11 Unicode)
+ fonts on Unix. This adds a ucs-2be (UCS-2 Big Endian) encoding in
+ Tk on Unix that is used for those fonts (X11 requires
+ big-endianness). (welch) [Patch #406411; Bug #220890 #220899]
+ This differs from the 8.3.3 patch by not adding ucs-2be in the
+ preferred encodingList (seems works fine without).
+ Added alias for jisx0201* fonts to jis0201 encoding. [Bug #414033]
+
+2001-05-30 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinKey.c (TkpSetKeycodeAndState): removed old debug info
+
+2001-05-29 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinX.c: moved the initialization of tkPlatformId from
+ TkWinXInit to TkWinGetPlatformId because static builds could call
+ it before it was initialized. [Bug #427278]
+
+2001-05-28 Peter Spjuth <peter.spjuth@space.se>
+
+ * generic/tkFrame.c:
+ * generic/tkWindow.c:
+ * tests/frame.test: Upgraded frame to use the newer TK_OPTION
+ style when processing configuration options. Some cleanup of
+ bad comments and bad code. [part of patch #420861]
+
+2001-05-23 Mo DeJong <mdejong@redhat.com>
+
+ * unix/configure:
+ * unix/tcl.m4:
+ * win/configure:
+ * win/tcl.m4: Sync from Tcl sources.
+
+2001-05-21 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/tcl.m4: sync'ed up wih Tcl tcl.m4. [Bug #419812]
+
+ * doc/TkInitStubs.3:
+ * generic/tk.h:
+ * generic/tkStubLib.c: CONST'ified Tk_InitStubs to match CONST
+ changes to Tcl_PkgRequireEx.
+
+2001-05-21 Todd M. Helfter <tmh@purdue.edu>
+
+ * doc/menubutton.n:
+ * generic/tkMenubutton.c:
+ * generic/tkMenubutton.h:
+ * mac/tkMacMenubutton.c:
+ * tests/menubut.test:
+ * unix/tkUnixMenubu.c: Implementation of TIP #11, the addition of
+ a -compound option to the menubutton allowing text and an image to
+ be displayed at the same time. This behavior is identical to the
+ behavior of the button widget.
+
+2001-05-16 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/console.n: Added - was erroneously placed in Tcl before...
+
+2001-04-25 Mo DeJong <mdejong@redhat.com>
+
+ * unix/configure: Regen.
+ * unix/tcl.m4: Update from Tcl.
+ * win/configure: Regen.
+ * win/tcl.m4: Update from Tcl.
+
+2001-04-25 Mo DeJong <mdejong@redhat.com>
+
+ * unix/configure: Regen.
+ * unix/configure.in: Use $@ in MAKE_LIB and MAKE_STUB_LIB
+ commands instead of using a delayed subst variable. Replace
+ instances of STUB_LIB_FILE with TK_STUB_LIB_FILE.
+
+2001-04-25 Mo DeJong <mdejong@redhat.com>
+
+ * unix/Makefile.in: Use TCL_STUB_LIB_FILE instead of STUB_LIB_FILE.
+ * unix/configure: Regen.
+ * unix/configure.in: Don't subst STUB_LIB_FILE, use TCL_STUB_LIB_FILE
+ instead.
+
+2001-04-12 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tkImage.c (Tk_ImageObjCmd,DeleteImage): Better detection
+ of deletion when world is falling apart. [Bug #220819]
+
+2001-04-04 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinMenu.c (TkWinHandleMenuEvent): corrected reseting of
+ service mode to only occur when it was set. [Bug #220948]
+
+2001-04-03 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * tests/winClipboard.test: improved results for understanding when
+ tests fail.
+
+ * tests/winDialog.test: string totitle'd some results that
+ expected [pwd] to return a capital drive letter.
+
+ * tests/cursor.test: changed tests to use 'heart' cursor because
+ 'arrow' on windows has a pre-skewed use count.
+
+ * win/tkWinDialog.c (GetFileNameA): initialize multi to 0.
+
+2001-04-02 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/configure:
+ * win/tcl.m4 (SHLIB_LD): added -incremental:no. [Bug #219381]
+
+ * generic/tkMenu.c (TkInvokeMenu): checked for menu deletion
+ before calling associated menu entry command. [Bug #220821]
+
+ * doc/image.n: added warning about names chosen for images.
+
+ * generic/tkImgPhoto.c (ImgPhotoCmd): corrected the src and dest
+ values for $imageName put when -format and -to are used.
+ [Bug #232741]
+
+ * tests/listbox.test: added test listbox-27.1, delete during
+ scrollbar update
+ * generic/tkListbox.c (DestroyListbox, ListboxEventProc):
+ corrected listbox to make proper use of Tcl_EventuallyFree and
+ protect against unusual listbox deletion.
+
+ * tests/entry.test: added tests entry-20.*, delete during widget
+ activity
+ * generic/tkEntry.c (DestroyEntry, EntryEventProc): fixed the
+ entry widget to survive deletion while processing scrollbar
+ updates and validation.
+
+ * tests/canvas.test: test of canvas delete during event
+ * generic/tkCanvas.c (DestroyCanvas, CanvasEventProc): fixed the
+ canvas to survive deletion during event processing. [Bug #228024]
+
+2001-04-01 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * README:
+ * mac/README: updated patchlevel to 8.4a3 and corrected links and
+ notes.
+
+ * generic/tk.h:
+ * unix/configure.in (TK_PATCH_LEVEL):
+ * unix/configure:
+ * unix/tk.spec:
+ * win/configure.in (TK_PATCH_LEVEL):
+ * win/configure: updated patchlevel to 8.4a3
+
+2001-03-30 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * tests/safe.test: added note about correcting failures in
+ safe.test.
+ * library/tk.tcl: moved package require msgcat inside if case to
+ not be used in safe interps.
+
+ * win/makefile.vc:
+ * win/configure:
+ * win/tcl.m4: added imm32.lib to LIBS_GUI for Tk IME support.
+ * win/tkWinInt.h:
+ * win/tkWinKey.c:
+ * win/tkWinX.c: added support for changing IME on the fly in
+ Windows (2000). (lam) [Patch #402993]
+
+ * tests/bind.test (bind-22.18):
+ * generic/tkBind.c (NameToWindow): handled the error case where a
+ valid-looking but invalid identifier could be passed in certain
+ event generate options causing a crash. [Bug #411307]
+
+ * win/tkWinWm.c (UpdateWrapper): ensured that the passed in winPtr
+ had an existent window to operate on. [Bug #409172]
+
+ * win/Makefile.in (install-*): improved install-* targets to use
+ their base build dependency.
+
+ * generic/tkImage.c (Tk_ImageObjCmd, EventuallyDeleteImage):
+ added casts to allow compiling on Windows with debbuging.
+
+2001-03-29 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/msgs/de.msg: fixed translations. [Patch #403525]
+
+ * doc/canvas.n: Noted ability to specify coords as a list in the
+ docs. (techentin) [Patch #403660]
+
+ * tests/canvas.test: added test case to check obj conversion
+ * generic/tkObj.c (UpdateStringOfMM, SetMMFromAny): better
+ obj-aware screen distances. (pgbaum, hobbs) [Patch #403327]
+
+ * library/bgerror.tcl (bgerror): allow focus into details window
+ for Windows C&P to work. [Bug #220929]
+
+ * library/tk.tcl: put a catch around adding <hpBackTab> to the
+ <<PrevWindow>> virtual event as it doesn't seem to work on all HP
+ systems. [Bug #411669]
+
+ * library/tkfbox.tcl: fixed selecting directories and single files
+ with spaces using tk_getOpenFile -multiple 1. [Bug #411640]
+
+ * win/tkWinDialog.c (GetFileNameA): added support for -multiple to
+ ascii-based tk_getOpenFile (Win9*). (haneef) [Patch #403047]
+ (GetFileNameW): increased number of files that could be returned
+ by tk_getOpenFile -multiple. [Patch #412042]
+
+2001-03-29 Mo DeJong <mdejong@redhat.com>
+
+ * library/entry.tcl (tkEntryMouseSelect):
+ * library/text.tcl (tkTextSelectTo): When
+ the mouse is dragged with the button down,
+ move the insertion cursor to the current
+ mouse position.
+ * tests/event.test: Add a series of tests
+ for event generation. Add tests for selection,
+ check the position of the insertion cursor.
+
+2001-03-28 Jeff Hobbs <jeffh@gimlet.activestate.com>
+
+ * unix/configure:
+ * unix/tcl.m4: corrected IRIX-5.x config to not use -n32.
+ (english) [Patch 403626]
+
+2001-03-28 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/focus.test (focus-6.1):
+ * tests/macEmbed.test (unixEmbed-5.1):
+ * tests/macMenu.test (macMenu-21.3):
+ * tests/menu.test (menu-27.1):
+ * tests/unixEmbed.test (unixEmbed-8.2):
+ * tests/unixWm.test (unixWm-50.4): Replaced all [load {} tk]
+ in Tk test suite with [load {} Tk]. [Bug 220940, Patch 411952]
+
+2001-03-12 Don Porter <dgp@users.sourceforge.net>
+
+ BRANCH dgp-privates-into-namespace:
+ * doc/menu.n:
+ * unix/mkLinks: Added documentation for [tk_menuSetFocus].
+
+2001-03-12 Don Porter <dgp@users.sourceforge.net>
+
+ BRANCH dgp-privates-into-namespace:
+ * doc/text.n:
+ * doc/tkvars.n:
+ * unix/mkLinks: Added documentation for commands and variables
+ matching tk_text*.
+
+2001-03-08 Don Porter <dgp@users.sourceforge.net>
+
+ BRANCH dgp-privates-into-namespace:
+ * generic/tkTextDisp.c:
+ * library/unsupported.tcl:
+ * tests/textDisp.test: Restored the global variables tk_textRedraw
+ and tk_textRelayout. Since they match tk_*, they should remain
+ publicly available until at least Tk 9.
+
+2001-03-01 Don Porter <dgp@users.sourceforge.net>
+
+ BRANCH dgp-privates-into-namespace:
+ * library/unsupported.tcl: New file for Tk's unsupported
+ interfaces. Contains [tk::unsupported::ExposePrivateCommand]
+ and [tk::unsupported::ExposePrivateVariable] that restore the
+ availability of an old public name of one of Tk's private
+ commands and variables, respectively, for those applications
+ and extensions that depend on the old names against advice.
+
+2001-02-28 Don Porter <dgp@users.sourceforge.net>
+
+ BRANCH dgp-privates-into-namespace: Feature branch to move all
+ of Tk's private commands and variable into the ::tk namespace
+ and its children.
+
+ * doc/tkvars.n: Documented private variable tkPriv renamed tk::Priv.
+
+ * generic/tkBind.c:
+ * generic/tkMenu.c:
+ * generic/tkTextDisp.c:
+ * library/bgerror.tcl:
+ * library/button.tcl:
+ * library/choosedir.tcl:
+ * library/clrpick.tcl:
+ * library/comdlg.tcl:
+ * library/console.tcl:
+ * library/dialog.tcl:
+ * library/entry.tcl:
+ * library/focus.tcl:
+ * library/listbox.tcl:
+ * library/menu.tcl:
+ * library/msgbox.tcl:
+ * library/optMenu.tcl:
+ * library/palette.tcl:
+ * library/scale.tcl:
+ * library/scrlbar.tcl:
+ * library/spinbox.tcl:
+ * library/tclIndex:
+ * library/tearoff.tcl:
+ * library/text.tcl:
+ * library/tk.tcl:
+ * library/tkfbox.tcl:
+ * library/xmfbox.tcl:
+ * mac/tkMacMenu.c:
+ * tests/clrpick.test:
+ * tests/filebox.test:
+ * tests/macMenu.test:
+ * tests/menu.test:
+ * tests/menuDraw.test:
+ * tests/msgbox.test:
+ * tests/text.test:
+ * tests/textDisp.test:
+ * tests/unixMenu.test:
+ * tests/winMenu.test:
+ * tests/xmfbox.test:
+ * unix/tkUnixDialog.c: All Tk commands matching ::tk[A-Z]* and
+ all Tk private variables in the global namespace were renamed to
+ live in the namespace ::tk or one of its children.
+
+2001-02-13 Eric Melski <ericm@interwoven.com>
+
+ * doc/photo.n: [Bug 132213] Added clarification on interpretation
+ of ranges for "photoName data -from" subcommand.
+
+2001-02-12 D. Richard Hipp <drh@hwaci.com>
+
+ TIP #21: Asymmetric padding in the pack and grid geometry managers.
+ With this changes, you can now say "-padx {10 20}" to put 10 pixels
+ of padding on the left and 20 on the right. Similar rules apply
+ for vertical padding. See the revised documentation for details.
+
+2001-01-02 Andreas Kupries <a.kupries@westend.com>
+
+ Everything below belongs together and implements TIP#8 (SF patch#102833)
+
+ * win/tkWinWm.c (line 56f): Added icon structures.
+ * win/tkWinWm.c (struct WmInfo, line 242): Added reference to
+ optional icon for titlebar.
+ * win/tkWinWm.c (struct ThreadSpecificData, line 335): Added
+ reference to optional default icon for toplevel windows.
+ * win/tkWinWm.c (line 387 ... 1169): All the new functions required
+ to deal with icon specifications, 'InitWm' changed.
+ * win/tkWinWm.c (TkWmNewWindow, UpdateWrapper, TkWmDeadWindow, Tk_WmCmd):
+ Added initialization and handling of the new fields.
+ * doc/wm.n: Documentation updated to explain the newly available
+ functionality.
+
+2000-12-13 jeff hobbs <jhobbs@interwoven.com>
+
+ * generic/tkObj.c (SetMMFromAny): Added ability to recognize
+ double type object to speed up canvas coord calculations.
+ [Patch 403327]
+
+2000-12-12 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/entry.n: Improved documentation of interplay between the
+ -state and -textvariable options.
+
+2000-11-29 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/image.test (image-1.10): Improved this test, which
+ previously only worked if the command failed to delete the root
+ window, and caused *major* trouble otherwise...
+ * generic/tkImage.c (EventuallyDeleteImage): Created this function
+ so that images that get deleted during the creation of an image
+ won't cause a nasty core dump. Properly fixes bug #120819.
+
+2000-11-28 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/image.n:
+ * generic/tkImage.c (Tk_ImageObjCmd): Backed out previous change.
+ Bug #120819 is back again in force. Left the test in there
+ though.
+
+2000-11-23 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/image.n:
+ * tests/image.test (image-1.10):
+ * generic/tkImage.c (Tk_ImageObjCmd): Prohibited image names that
+ start with "." since they can cause some really obscure crashes.
+ Fixes Bug #120819.
+
+2000-11-21 Eric Melski <ericm@ajubasolutions.com>
+
+ Overall change: Implemented TIP 5, which exports
+ TkClassProcs/TkSetClassProcs as Tk_ClassProcs/Tk_SetClassProcs,
+ adding a size field to Tk_ClassProcs to allow for future
+ expansion, and renaming the geometryProc to worldChangedProc,
+ which is more in keeping with the actual use of the callback.
+
+ * unix/mkLinks: Added link for Tk_SetClassProcs.
+
+ * doc/SetClassProcs.3: Documentation for
+ Tk_ClassProcs/Tk_SetClassProcs.
+
+ * generic/tkCanvas.c:
+ * generic/tkEntry.c:
+ * generic/tkFrame.c:
+ * generic/tkListbox.c:
+ * generic/tkMenu.c:
+ * generic/tkMessage.c:
+ * generic/tkScale.c:
+ * generic/tkText.c: Updated to use Tk_ClassProcs/Tk_SetClassProcs
+ instead of TkClassProcs/TkSetClassProcs.
+
+ * generic/tkMenubutton.c:
+ * generic/tkScrollbar.c:
+ * generic/tkButton.c: Updated to use Tk_SetClassProcs instead of
+ TkSetClassProcs.
+
+ * generic/tkMenubutton.h:
+ * generic/tkScrollbar.h:
+ * generic/tkButton.h:
+ * win/tkWinButton.c:
+ * win/tkWinScrlbr.c:
+ * mac/tkMacButton.c:
+ * mac/tkMacMenubutton.c:
+ * mac/tkMacScrlbr.c:
+ * unix/tkUnixButton.c:
+ * unix/tkUnixMenubu.c:
+ * unix/tkUnixScrlbr.c: Updated to use Tk_ClassProcs instead of
+ TkClassProcs.
+
+ * generic/tkDecls.h:
+ * generic/tkStubInit.c:
+ * generic/tkIntDecls.h: Regenned from tk.decls, tkInt.decls.
+
+ * generic/tk.h: Added declaration of Tk_ClassProcs, with size
+ field. Added typedef's for Tk_ClassCreateProc,
+ Tk_ClassWorldChangedProc, Tk_ClassModalProc. Added definition of
+ Tk_GetClassProc macro, shorthand for extracting a member of the
+ Tk_ClassProcs structure.
+
+ * generic/tkInt.h: Removed declaration of TkClassProcs,
+ TkClassGeometryProc, etc.
+
+ * generic/tkBind.c (Tk_BindEvent): Updated to use Tk_GetClassProc
+ macro to extract modalProc; added check that the modalProc is non-NULL.
+
+ * generic/tkFont.c (RecomputeWidgets): Updated to use
+ Tk_GetClassProc macro to extract worldChangedProc; added comment
+ about the choice of a recursive versus iterative algorithm for
+ propagating world changed messages.
+
+ * generic/tkWindow.c (Tk_MakeWindowExist): Updated to use
+ Tk_GetClassProc macro to extract createProc from Tk_ClassProcs.
+
+ * generic/tk.decls: Added declaration for Tk_SetClassProcs.
+
+ * generic/tkInt.decls: Commented out declaration for
+ TkSetClassProcs, which is made public by this change. The entry
+ is left in place, but commented, so that future developers will
+ know not to reuse it's stub number.
+
+2000-11-21 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/ConfigWidg.3: Added deprecation note from Bug #120944 - use
+ Tk_SetOption() instead.
+
+ * generic/tkImgPhoto.c (TkPhotoGetValidRegion): Applied patch to
+ create this function and add it to tkInt stubs. Should now be
+ possible to write an extension that accesses the transparency data
+ in a photo image. Bug #120930
+
+2000-11-03 Jeff Hobbs <hobbs@ajubasolutions.com>
+
+ 8.4a2 RELEASE
+
+ * generic/tkWindow.c (Initialize): added call to Tcl_SetMainLoop.
+ This only has effect when tclsh is run (not wish), and then Tk is
+ loaded in interactively.
+
+2000-11-02 Jeff Hobbs <hobbs@ajubasolutions.com>
+
+ * win/tkWinButton.c:
+ * win/tkWinDialog.c:
+ * win/tkWinScrlbr.c:
+ * win/tkWinWm.c: fixed up code for Win64 support. This mostly
+ remains in _WIN64 #ifdef's, until updated compilers are standard.
+
+ * win/tcl.m4:
+ * win/makefile.vc: updated for Win64 compile support
+
+ * unix/configure:
+ * win/configure: checked in configure scripts so people doing
+ CVS checkouts aren't required to have autoconf. Changes to
+ configure.in in the future will require the corresponding
+ configure script to also be re-autoconf'ed and checked in.
+
+ * doc/event.n: added note that key events require window focus.
+
+2000-11-01 Jeff Hobbs <hobbs@ajubasolutions.com>
+
+ * win/tkWinDialog.c (GetFileNameW, GetFileNameA)
+ (Tk_ChooseDirectoryObjCmd): created
+ work-around for change in NT5.0/98 that caused no initialdir
+ setting to open the browser up in the user's documents dir.
+
+ * tests/color.test: marked color-2.6 nonPortable as we can't
+ reliably assume what 'red' maps to.
+
+2000-11-01 Eric Melski <ericm@ajubasolutions.com>
+
+ * tests/winDialog.test: Corrected expected results for bad option
+ tests (5.2, 5.5) to include -multiple option.
+
+ * win/tkWinDialog.c: Added branch for 0 return from
+ CommDlgExtendedError() switches; this was formerly treated as an
+ error, but it actually is not, since it just means the user hit
+ cancel or closed the dialog. (GetFileNameW): Added better smarts
+ such that -multiple is not considered a valid option for
+ tk_getSaveFile.
+ Removed CommDlgExtendedError() checks for color and choosedir
+ dialogs, and removed all except the explicit invalid filename
+ checks for the file dialogs.
+
+2000-10-30 David Gravereaux <davygrvy@ajubasolutions.com>
+
+ * win/configure.in:
+ * win/Makefile.in:
+ * win/makefile.vc:
+ * win/rc/tk.rc:
+ * win/rc/tk_base.rc (new):
+ * win/rc/wish.rc: Added logic to derive filenames better in the
+ resource scripts based on compile options along with better
+ support for building a static wish shell with cursor resources.
+
+2000-10-27 Jeff Hobbs <hobbs@ajubasolutions.com>
+
+ * unix/tcl.m4: added support for AIX-5.
+
+ * tests/tk.test:
+ * doc/tk.n: updated to reflect default on status of useinputmethods.
+ * library/tk.tcl: tk useinputmethods is set to 1 by default. This
+ enables Kanji and dead-char input by default. Intro'd in
+ 1999-12-16 with default off to avoid some problems with older X
+ servers that would slow down widget creation over time.
+
+ * win/Makefile.in (test, winhelp, tktest): corrected the
+ TCL_LIBRARY path specification.
+
+2000-10-18 Eric Melski <ericm@ajubasolutions.com>
+
+ * win/tkWinDraw.c (RenderObject): Applied patch from [Bug: 6368],
+ which corrects rendering of 1-pixel wide stippled lines on Windows.
+
+ * generic/tkCanvLine.c (DisplayLine): Applied patch from
+ [Bug: 6368], corrects bugs relating to use of active- and
+ disabledwidth values for displaying lines (disabledwidth was never
+ used, and activewidth/disablewidths would only possibly be used
+ when greater than default width, rather than when simply not equal
+ to default width).
+
+ * library/tkfbox.tcl (OkCmd): Applied patch from [Bug: 6365],
+ which adds safety for directory names containing spaces or which
+ are non-lists.
+
+ * win/tkWinDialog.c (GetFileNameW, GetFileNameA)
+ (Tk_ChooseColorObjCmd, Tk_ChooseDirectoryObjCmd): Added error
+ checking for the return value from the common dialog functions, so
+ that the commands will not silently fail if the common dialog
+ returns an error. [Bug: 6369].
+
+2000-10-10 Eric Melski <ericm@ajubasolutions.com>
+
+ * generic/tkConfig.c (Tk_InitOptions): Added
+ Tcl_IncrRefCount/Tcl_DecrRefCount calls on valuePtr, to prevent
+ memory leaks when the value object comes from the option
+ database. [Bug: 6275].
+
+2000-10-06 Jeff Hobbs <hobbs@ajubasolutions.com>
+
+ * win/Makefile.in (cat32.${OBJEXT}): add win/ subdirectory to
+ cat32 target to correctly find the source file.
+
+2000-10-05 Eric Melski <ericm@ajubasolutions.com>
+
+ * generic/tkCmds.c (Tk_WinfoObjCmd): Added check for
+ TK_ANONYMOUS_WINDOW flag in the [winfo children] subcommand; if
+ set, the window will not be printed in the list of children.
+
+ * doc/CrtWindow.3: Added entry for Tk_CreateAnonymousWindow.
+
+ * generic/tkWindow.c
+ (Tk_CreateAnonymousWindow): New API for creating anonymous
+ windows. These windows are manipulable from C, but not from Tcl,
+ because they have no pathname associated with them. They are used
+ initially by widgets that do rubber-band resizing (panedwindow,
+ multi-column listbox, etc.), and may be useful for other widgets
+ as well (dropbox, combobox).
+ (Tk_DestroyWindow): Added check for TK_ANONYMOUS_WINDOW flag when
+ determining whether to generate a DestroyNotify event.
+
+ * generic/tkStubInit.c:
+ * generic/tkDecls.h: Regen'd from tk.decls.
+
+ * generic/tk.decls: Added Tk_CreateAnonymousWindow declaration.
+
+ * generic/tk.h: Added TK_ANONYMOUS_WINDOW flag for Tk_Window's.
+
+2000-10-04 Eric Melski <ericm@ajubasolutions.com>
+
+ * doc/MaintGeom.3: Noted that Tk_MaintainGeometry handles direct
+ descendants properly.
+
+ * generic/tkGeometry.c (Tk_MaintainGeometry): Added a check for
+ the case in which the slave window is a direct descendant of the
+ master window. In this case, we need not set up the additional
+ infrastructure normally provide by Tk_MaintainGeometry, because we
+ can rely on the parent/child relationship to handle it for us
+ implicitly. In this case, Tk_MaintainGeometry just calls directly
+ to Tk_MoveResizeWindow. This allows geometry managers to simply
+ always use Tk_MaintainGeometry to maintain geometry for slaves,
+ and avoid doing the direct descendant check themselves.
+ (Tk_UnmaintainGeometry): Added a matching check for the direct
+ descendant case; in this case, Tk_UnmaintainGeometry simply
+ returns immediately.
+
+2000-10-01 Eric Melski <ericm@ajubasolutions.com>
+
+ * generic/tkButton.c (ConfigureButton): Added tests for -compound
+ option, so that when there is a textvariable and an image, and
+ -compound is not none, the button will display both the
+ textvariable and the image.
+
+ * doc/SetOptions.3: Added note that restoreProc and freeProc may
+ be NULL.
+
+ * generic/tkConfig.c (Tk_RestoreSavedOptions): For custom options,
+ added test that the restoreProc is not NULL, to allow for custom
+ options that don't care about supporting Tk_RestoreSavedOptions.
+
+2000-09-29 D. Richard Hipp <drh@hwaci.com>
+
+ * generic/tkBitmap.c: Changes to prevent a BadMatch error from the
+ Xserver when the same bitmap is used on two or more screens of the
+ same display.
+
+ * tests/menu.test: Print a warning if the TK_ALT_DISPLAY environment
+ variable is not configured so as to test for the bug fix above.
+
+ * library/tk.tcl (::tk::SetGrabFocus): "Catch" the grab in case
+ another application already holds the grab and the "grab" command
+ fails.
+
+2000-09-29 Jeff Hobbs <hobbs@scriptics.com>
+
+ * win/Makefile.in: commented use of TESTFLAGS
+ * unix/Makefile.in: added TESTFLAGS to test and testlang targets to
+ conform with Windows makefile and TEA style.
+
+2000-09-29 Eric Melski <ericm@ajubasolutions.com>
+
+ * generic/tkTest.c: Fixed tests to use updated API.
+
+ * doc/SetOptions.3:
+ * generic/tk.h:
+ * generic/tkConfig.c: Changed interface for Tk_CustomOptionSetProc
+ and Tk_CustomOptionGetProc; these now take a pointer to the start
+ of the widget record, and an integer offset to the slot for the
+ option value, instead of just a pointer to the slot. This allows
+ more sophisticated options to do interesting things based on other
+ data in the widget record.
+
+2000-09-17 Eric Melski <ericm@ajubasolutions.com>
+
+ * generic/tk.h: Added declaration of Tk_ObjCustomOption structure,
+ used for TK_OPTION_CUSTOM, and typedef's of the functions
+ Tk_CustomOptionSetProc, Tk_CustomOptionGetProc,
+ Tk_CustomOptionRestoreProc, and Tk_CustomOptionFreeProc, used for
+ TK_OPTION_CUSTOM.
+
+ * doc/SetOptions.3: Added documentation of TK_OPTION_CUSTOM, and
+ section "CUSTOM OPTION TYPES" explaining how to create and use
+ custom options.
+
+ * tests/config.test: Added tests for custom option type.
+
+ * generic/tkTest.c: Added test support for TK_OPTION_CUSTOM to
+ TestobjconfigObjCmd. Added CustomOption* functions to implement a
+ test custom option.
+
+ * generic/tkConfig.c: Added new option type TK_OPTION_CUSTOM,
+ which allows the definition of custom option types by creating
+ parsing, printing, freeing, and restoring procedures for a custom
+ option. This is needed by the text and canvas widgets if they are
+ to be fully objectified.
+
+2000-09-07 Jeff Hobbs <hobbs@scriptics.com>
+
+ * doc/Tk_Init.3:
+ * doc/bell.n:
+ * doc/loadTk.n: minor doc cleanup
+
+2000-09-06 Eric Melski <ericm@ajubasolutions.com>
+
+ * doc/HWNDToWindow.3:
+ * doc/GetHWND.3: Changed synopsis to indicate the tkPlatDecls.h
+ should be included, not tk.h.
+
+ * generic/tkPlatDecls.h: Removed #include <windows.h> for Windows,
+ a better solution for now is to update the docs and have extension
+ authors #include <tkPlatDecls.h>.
+
+ * generic/tk.h: Removed '#include "tkPlatDecls.h"', as the
+ incorrect inclusion order between windows.h/tkPlatDecls.h causes
+ build conflicts on Windows.
+
+ * generic/tkPlatDecls.h: Added #include <windows.h> for Windows,
+ so that HWND, etc., are defined properly.
+
+2000-09-06 Jeff Hobbs <hobbs@scriptics.com>
+
+ * doc/canvas.n: fixed doc bug (ellson). [Bug: 6218]
+
+ * README:
+ * generic/tk.h:
+ * unix/configure.in:
+ * unix/tk.spec:
+ * win/configure.in: updated to patchlevel 8.4a2
+
+ * generic/tkMessage.c (MessageWidgetObjCmd): initialized result to
+ avoid pedantic warning.
+
+ * generic/tkGrab.c (Tk_GrabObjCmd): changed len arg from size_t to
+ int to fix pedantic warning.
+
+2000-09-01 Eric Melski <ericm@ajubasolutions.com>
+
+ * win/makefile.vc (install-libraries):
+ * win/Makefile.in (install-libraries):
+ * unix/Makefile.in (install-libraries): Added tkPlatDecls.h to
+ list of header files to install.
+
+ * generic/tk.h: Added #include "tkPlatDecls.h", which declares the
+ platform specific component of the public Tk stubs API's.
+
+2000-08-29 Eric Melski <ericm@ajubasolutions.com>
+
+ * win/tkWinMenu.c (DrawWindowsSystemBitmap): Use scratchDC
+ for determining the source's logical coordinates. Patch from
+ [Bug: 6134 (Markus Oberhumer)].
+
+ * win/tkWinMenu.c (SetDefaults): Compute the indicatorDimensions[]
+ under Windows NT/2000 in the same way as under Windows 95/98.
+ Patch from [Bug: 6134 (Markus Oberhumer)].
+
+ * win/tkWinFont.c (GetScreenFont): Added a memset() to
+ pacify memory checkers. Patch from [Bug: 6134 (Markus Oberhumer)].
+
+ * library/tkfbox.tcl (::tk::dialog::file::Update): Corrected
+ handling of multi-pattern filters (eg, "* *.*"), which was broken
+ by the getOpenFile performance patches applied earlier.
+
+2000-08-24 Eric Melski <ericm@ajubasolutions.com>
+
+ * doc/toplevel.n:
+ * doc/spinbox.n:
+ * doc/scrollbar.n:
+ * doc/scale.n:
+ * doc/menubutton.n:
+ * doc/menu.n:
+ * doc/listbox.n:
+ * doc/entry.n:
+ * doc/frame.n:
+ * doc/message.n:
+ * doc/checkbutton.n:
+ * doc/radiobutton.n:
+ * doc/button.n:
+ * doc/label.n:
+ * doc/canvas.n:
+ * doc/text.n: Fixed Standard Options section to make best use of
+ new tab settings in man.macros.
+
+2000-08-24 Mo DeJong <mdejong@redhat.com>
+
+ * unix/README: Update to account for removal of --enable-gcc.
+ * unix/configure.in:
+ * unix/tcl.m4 (SC_ENABLE_GCC): Remove --enable-gcc option.
+ * win/configure.in:
+ * win/tcl.m4 (SC_ENABLE_GCC): Remove --enable-gcc option.
+ Remove quick hack that provided cross compile support for
+ windows builds.
+
+2000-08-23 Jeff Hobbs <hobbs@scriptics.com>
+
+ * generic/tkButton.c (ButtonTextVarProc): reversed change below,
+ it was not correct.
+
+2000-08-22 Jeff Hobbs <hobbs@scriptics.com>
+
+ * generic/tkButton.c (ButtonTextVarProc): changed order of
+ incr/decr of new value object, in case they are equal.
+
+2000-08-18 Eric Melski <ericm@ajubasolutions.com>
+
+ * generic/tkImgPhoto.c (ImgPhotoGet): Removed redundant call to
+ DitherInstance; this call was formerly being made from
+ ImgPhotoGet->ImgPhotoConfigureInstance->DitherInstance, and
+ ImgPhotoGet->DitherInstance. The second call was removed.
+
+2000-08-10 Jeff Hobbs <hobbs@scriptics.com>
+
+ * doc/SetOptions.3: added missing ')'.
+
+2000-08-09 Eric Melski <ericm@ajubasolutions.com>
+
+ * doc/SetOptions.3: Updated documentation to reflect support for
+ TK_OPTION_NULL_OK for TK_OPTION_DOUBLE and TK_OPTION_PIXELS.
+
+ * generic/tkConfig.c: Added for TK_OPTION_NULL_OK support for
+ TK_OPTION_DOUBLE and TK_OPTION_PIXELS.
+
+ * doc/place.n: Updated, reformatted manual entry.
+
+ * tests/place.test: Added many tests.
+
+ * generic/tkPlace.c (Tk_PlaceObjCmd): Updated to use Tk
+ widget-option management facilities to manage place options (-x,
+ -y, etc.), which simplifies the placer code. Added support for
+ [place configure pathName] and [place configure pathName -option],
+ similar to the behavior of the configure subcommand supported by
+ widgets.
+
+2000-08-08 Eric Melski <ericm@ajubasolutions.com>
+
+ * tests/place.test: Extended test suite to test error returns from
+ [place].
+
+ * generic/tkInt.h: Replaced Tk_PlaceCmd prototype with
+ Tk_PlaceObjCmd prototype.
+
+ * generic/tkWindow.c: Updated [place] command entry to use new
+ Tcl_Obj interface.
+
+ * generic/tkPlace.c (Tk_PlaceObjCmd): Tcl_Obj'ified [place] command.
+
+2000-08-07 Eric Melski <ericm@ajubasolutions.com>
+
+ * generic/tkWindow.c: Updated [selection] command entry to use
+ new Tcl_Obj interface.
+
+ * generic/tkInt.h: Replaced Tk_SelectionCmd prototype with
+ Tk_SelectionObjCmd prototype.
+
+ * tests/select.test: Updated test suite to recognize standardized
+ error messages.
+
+ * generic/tkSelect.c (Tk_SelectionObjCmd): Tcl_Obj'ified
+ [selection] command.
+
+2000-08-07 Jeff Hobbs <hobbs@scriptics.com>
+
+ * doc/cursors.n: changed .SS to more compatible macros.
+
+2000-08-05 Jeff Hobbs <hobbs@scriptics.com>
+
+ * library/safetk.tcl: rationalized the setting of tk_library when
+ initialized Tk in a safe interpreter.
+
+2000-08-03 Eric Melski <ericm@ajubasolutions.com>
+
+ * generic/tkWindow.c: Updated "grab" command entry to use
+ Tcl_Obj'ified command.
+
+ * generic/tkInt.h: Replaced Tk_GrabCmd prototype with
+ Tk_GrabObjCmd prototype.
+
+ * tests/grab.test: Initial suite of tests for [grab] command.
+
+ * generic/tkGrab.c (Tk_GrabObjCmd): Tcl_Obj'ified [grab] command.
+
+ * generic/tkInt.h: Removed Tk_AfterCmd function prototype; the
+ function does not exist (since 4.0p3). Cleaned up some line
+ wrapping.
+
+ * generic/tk.h: Removed "#define Tk_AfterCmd Tcl_AfterCmd";
+ nothing in the core uses Tk_AfterCmd, and Tcl_AfterCmd doesn't exist
+ anymore anyway.
+
+ * generic/tkInt.h: Replace Tk_BindCmd prototype with
+ Tk_BindObjCmd prototype.
+
+ * generic/tkWindow.c: Updated "bind" command entry to use
+ Tcl_Obj'ified command.
+
+ * generic/tkCmds.c (Tk_BindObjCmd): Tcl_Obj'ified [bind] command.
+
+ * tests/bind.test: Tweaked expected error messages for [bindtags]
+ to comply with updated error messages.
+
+ * generic/tkMenu.c (CloneMenu): Replaced calls to Tk_BindtagsCmd
+ with equivalent calls to Tk_BindtagsObjCmd.
+
+ * generic/tkInt.h: Replace Tk_BindtagsCmd prototype with
+ Tk_BindtagsObjCmd prototype.
+
+ * generic/tkWindow.c: Updated "bindtags" command entry to use
+ Tcl_Obj'ified command.
+
+ * generic/tkCmds.c (Tk_BindtagsObjCmd): Tcl_Obj'ified [bindtags]
+ command.
+
+2000-08-02 Eric Melski <ericm@ajubasolutions.com>
+
+ * generic/tkCmds.c (Tk_TkwaitObjCmd): Tcl_Obj'ified [tkwait] command.
+
+ * generic/tkWindow.c: Updated "tkwait" command entry to use
+ Tcl_Obj'ified command.
+
+ * generic/tkInt.h: Replace Tk_TkwaitCmd prototype with
+ Tk_TkwaitObjCmd prototype.
+
+ * generic/tkGrid.c (Tk_GridCmd): Split [grid] subcommands into
+ separate functions instead of inlining them all in Tk_GridCmd.
+
+2000-08-01 Eric Melski <ericm@ajubasolutions.com>
+
+ * generic/tkInt.h: Replaced prototype for Tk_MessageCmd with
+ prototype for Tk_MessageObjCmd.
+
+ * generic/tkWindow.c: Marked message command as using the new
+ MessageObjCmd instead of the old MessageCmd.
+
+ * tests/message.test: Added tests for the message widget.
+
+ * generic/tkMessage.c: Obj'ified the message widget.
+
+ * generic/tkInt.h: Removed prototype for Tk_ClipboardCmd, added
+ prototype for Tk_ClipboardObjCmd.
+
+ * generic/tkWindow.c: Updated function pointers for clipboard
+ command to use Tcl_Obj version.
+
+ * tests/clipboard.test: Updated tests to expect standard error
+ messages.
+
+ * generic/tkClipboard.c (Tk_ClipboardObjCmd): Obj'ified
+ Tk_ClipboardCmd -> Tk_ClipboardObjCmd.
+
+2000-07-28 Eric Melski <ericm@ajubasolutions.com>
+
+ * unix/tkUnixButton.c (TkpDisplayButton): Added bits to change
+ the indicator color when radio-/check-buttons are disabled. This
+ reduces the visual incongruity when a group of these controls are
+ disabled together.
+
+ * win/tkWinMenu.c (ReconfigureWindowsMenu): Added MF_GRAYED bit
+ for disabled menu entries, to ensure that those which are drawn by
+ the system are shown grayed (such as entries on menubars) [Bug: 4372].
+
+ * doc/label.n: Added -disabledforeground to list of options [Bug:
+ 6053].
+
+ * mac/tkMacDefault.h:
+ * unix/tkUnixDefault.h: Added default values for listbox
+ disabledforeground and state.
+
+ * win/tkWinDefault.h: Changed default listbox background color to
+ white and listbox selection borderwidth to 0, in keeping with the
+ "Microsoft Windows User Experience"; added default values for
+ listbox disabledforeground and listbox state.
+
+ * doc/listbox.n: Added documentation for -state option.
+
+ * generic/tkListbox.c: Added support for -state to listbox. [RFE:
+ 6052].
+
+ * tests/listbox.test: Tests for listbox disabled state.
+
+2000-07-27 Mo DeJong <mdejong@redhat.com>
+
+ * win/configure.in: TCL_STUB_LIB_FLAG and
+ TK_STUB_LIB_FLAG should not include ${TCL_DBGX}
+ in win/tkConfig.sh, fix that.
+
+2000-07-25 Joe English <jenglish@flightlab.com>
+
+ * doc: CanvPsY.3, ConfigWidg.3, CrtImgType.3, CrtItemType.3,
+ FontId.3, GetFont.3, canvas.n, font.n, options.n, text.n:
+ Documentation fix: Replaced references to XFontStruct *
+ and Tk_FontStruct with Tk_Font.
+
+2000-07-24 Eric Melski <ericm@ajubasolutions.com>
+
+ * tests/text.test: Added tests for -regexp -nocase searches with
+ backslash character classes.
+
+ * generic/tkText.c (TextSearchCmd): Text search did not work
+ properly when -regexp and -nocase were used, in combination with
+ backslash character classes represented by capital letters (ie,
+ \W, \M); altered implementation of -regexp -nocase searches to use
+ new regexp interfaces to fix this problem. [Bug: 5988].
+
+2000-07-21 Eric Melski <ericm@ajubasolutions.com>
+
+ * tests/text.test: Added tests for searching when text is elided.
+
+ * generic/tkText.c (TextSearchCmd): Text search was not returning
+ the correct index when the search covered (but did not search)
+ elided characters; corrected this by adjusting the match index by
+ the number of elided characters preceeding the start of the match,
+ just as is done with embedded windows, etc. [Bug: 5470].
+
+2000-07-21 Mo DeJong <mdejong@redhat.com>
+
+ * win/configure.in: Add TK_STUB_LIB_FLAG and
+ TK_BUILD_STUB_LIB_SPEC. These are needed to build a stub enabled
+ extension.
+
+2000-07-20 Eric Melski <ericm@ajubasolutions.com>
+
+ * unix/tkUnixDraw.c (TkScrollWindow): Replaced a use of a trinary
+ operator with an if/else, to avoid build problems on some
+ platforms [Bug: 5819].
+
+ * win/makefile.vc: Applied patch from Don Porter to enhance nmake
+ support on NT/Alpha [RFE: 5939].
+
+2000-07-19 Eric Melski <ericm@ajubasolutions.com>
+
+ * library/text.tcl: Enhanced <Tab> binding to behave like normal
+ <Tab> bindings when the text widget is disabled (ie, it advances
+ focus to the next widget).
+
+ * generic/tkText.c (TextSearchCmd): Added a test for a NULL
+ segment pointer when doing backwards searches for "" on an empty
+ text widget. [Bug: 6007].
+
+2000-07-18 Mo DeJong <mdejong@redhat.com>
+
+ * unix/aclocal.m4: Use tcl.m4.
+
+ * unix/configure.in: Properly quote LOCALES variable. Properly quote
+ argument to m4 macro.
+
+ * unix/tcl.m4: Add updated file from tcl.
+
+ * win/tcl.m4: Updated file from tcl.
+
+2000-07-18 Eric Melski <ericm@ajubasolutions.com>
+
+ * library/tkfbox.tcl: Fixed keyboard navigation in the iconlist.
+
+ * unix/configure.in (MAKE_LIB): Corrected definition of MAKE_LIB
+ for shared builds, with patch from Mike Hopkirk.
+
+2000-07-18 Mo DeJong <mdejong@redhat.com>
+
+ * win/Makefile.in: Fix TCL_GENERIC_DIR variable
+ so that it uses the TK_SRC_DIR in the same way
+ as the unix version.
+
+2000-07-17 David Gravereaux <davygrvy@ajubasolutions.com>
+
+ * generic/tkConsole.c: Added comments for a Win2K OS bug with
+ GetStdHandle(STD_OUTPUT_HANDLE). No change was done to the code
+ as the resulting behaviour of ShouldUseConsoleChannel() was
+ correct, anyways. [BUG: 5971]
+
+2000-07-17 Eric Melski <ericm@scriptics.com>
+
+ * generic/tkStubImg.c (Tk_InitImageArgs): Applied patch from [Bug:
+ 5990], from Anselm Lingnau, which correctly sets the value of
+ useNewImage to 0 when the new image system is not to be used,
+ instead of leaving it at -1, which causes the check to be
+ performed more times than is really necessary.
+
+ * library/bgerror.tcl: Fixed a typo in one of the bgerror dialog
+ label.
+
+ * library/msgs/it.msg: Italian message catalog, from Paolo
+ Brutti. [RFE: 6012].
+
+2000-07-07 Eric Melski <ericm@ajubasolutions.com>
+
+ * library/msgs/el.msg: Greek message catalog, from George Petasis.
+
+2000-07-07 Mo DeJong <mdejong@redhat.com>
+
+ * win/configure.in: Fix subst of TK_SHARED_BUILD
+ variable in tkConfig.sh.in. Fix definition of
+ TK_SRC_DIR variable so that it matches the
+ unix version.
+
+2000-07-05 Mo DeJong <mdejong@redhat.com>
+
+ * generic/tkFileFilter.c (AddClause): Cast to match function prototype.
+ * win/stubs.c (_XInitImageFuncPtrs): Add return value for function.
+ * win/tkWinButton.c (buttonStyles, ButtonBindProc, ComputeStyle):
+ Remove unused declarations.
+ * win/tkWinColor.c (GetColorByName, GetColorByValue): Remove unused
+ function declarations.
+ * win/tkWinDialog.c (TrySetDirectory): Remove unused function
+ declaration.
+ * win/tkWinEmbed.c (TkWinEmbeddedEventProc): Cast to match function
+ prototype.
+ * win/tkWinMenu.c (winMenuMutex, MenuExitProc): Remove unused
+ declaration.
+ * win/tkWinWindow.c (StackWindow): Remove unused declaration.
+ * win/tkWinWm.c (ConfigureEvent): Remove unused declaration.
+ * win/tkWinX.c (winXMutex): Remove unused declaration.
+ * xlib/ximage.c (XCreateBitmapFromData): Cast to match function
+ prototype.
+
+2000-07-05 Eric Melski <ericm@ajubasolutions.com>
+
+ * tests/imgPhoto.test: Added test for GIF writing code [Bug: 5823].
+
+ * generic/tkImgGIF.c: Applied patch from Jan Nijtmans to fix a
+ problem with the GIF writing code [Bug: 5823].
+
+ * generic/tkCursor.c: Added initialization for nextPtr field of
+ TkCursor, patch from Nijtmans/Howlett.
+
+2000-07-05 Eric Melski <ericm@ajubasolutions.com>
+
+ * library/msgs/nl.msg: Dutch message catalog for dialogs, from Jan
+ Nijtmans.
+
+2000-06-30 Eric Melski <ericm@scriptics.com>
+
+ * doc/keysyms.n:
+ * doc/colors.n: Added extra .CE/.CS pairs to break up the large
+ text block, so that the generated Windows help file could
+ accomodate the manual entry. [Bug: 5862]
+
+ * tests/filebox.test: Adjusted tests to accomodate -multiple.
+
+ * library/xmfbox.tcl: Adjusted arguments list construction such
+ that -multiple is not presented as an option for tk_getSaveFile.
+
+ * library/tk.tcl: Added test for safe interpreter status before
+ attempting to load message catalogs (which is impossible in a
+ standard safe interpreter). This means that SafeTk will not have
+ localized dialogs, unless a means is found for loading the message
+ catalog files.
+
+2000-06-29 Eric Melski <ericm@scriptics.com>
+
+ * library/msgs/de.msg: German message catalog.
+
+ * library/msgs/en.msg: English message catalog.
+
+ * library/msgs/es.msg: Spanish message catalog.
+
+ * library/msgs/fr.msg: French message catalog.
+
+ * unix/Makefile.in:
+ * unix/configure.in:
+ * library/tk.tcl:
+ * library/clrpick.tcl:
+ * library/choosedir.tcl:
+ * library/console.tcl:
+ * library/msgbox.tcl:
+ * library/tkfbox.tcl:
+ * library/xmfbox.tcl:
+ * library/bgerror.tcl: Applied patches from Laurent Duperval to
+ provide localization of Tk dialogs. [RFE: 2671].
+
+2000-06-27 Eric Melski <ericm@scriptics.com>
+
+ * generic/tkMenu.c (DeleteMenuCloneEntries): Applied fix from
+ [Bug: 5275], which corrected a segfault-causing indexing problem
+ when deleting entries from torn-off menus.
+
+2000-06-22 Eric Melski <ericm@ajubasolutions.com>
+
+ * doc/getOpenFile.n: Updated with information about -multiple.
+
+ * library/choosedir.tcl: Tweaked to handle modified tkIconList API's.
+
+ * library/tkfbox.tcl: Preliminary implementation of multiple
+ selection; based on patch from [RFE: 604]. Some of the tkIconList
+ functions changed to support this and to make the dialog faster.
+
+ * library/xmfbox.tcl: Added support for multiple selection, from
+ patch in [RFE: 4999].
+
+2000-06-21 Eric Melski <ericm@scriptics.com>
+
+ * library/text.tcl: Corrected behavior of text widget with respect
+ to this sequence of events: click, shift-click. Previously, the
+ shift-click just moved the cursor and anchor; now, the shift-click
+ will select the text between the click and the shift-click, which
+ is the behavior most users expect. [Bug: 5929].
+
+2000-06-19 Eric Melski <ericm@scriptics.com>
+
+ * library/bgerror.tcl: Added auto-truncation for long error
+ messages (more than 30 characters wide, or more than 4 lines
+ long), so that the dialog remains a manageable size. [RFE: 5782]
+
+2000-06-15 Eric Melski <ericm@scriptics.com>
+
+ * win/tkWinDialog.c: Patched to support tk_getOpenFile
+ -multiple. [RFE: 604].
+
+2000-06-13 Eric Melski <ericm@scriptics.com>
+
+ * win/aclocal.m4:
+ * win/configure.in:
+ * win/Makefile.in: Applied patch from [RFE: 5844], to provide
+ support for the mingw compile environment for Windows.
+
+2000-06-06 Jeff Hobbs <hobbs@scriptics.com>
+
+ 8.4a1 RELEASE
+
+2000-06-03 Jeff Hobbs <hobbs@scriptics.com>
+
+ * doc/CrtCmHdlr.3: new doc for ClientMessage handler procs
+ * generic/tk.h: added typdef for Tk_ClientMessageProc
+ * generic/tkStubInit.c:
+ * generic/tkDecls.h:
+ * generic/tk.decls: Added Tk_CreateClientMessageHandler and
+ Tk_DeleteClientMessageHandler declarations.
+ * generic/tkEvent.c (Tk_HandleEvent): Added
+ Tk_CreateClientMessageHandler and Tk_DeleteClientMessageHandler to
+ allow adding event handlers that invoke for ClientMessage events.
+ This is necessary to support unix dnd protocols.
+
+2000-06-02 Jeff Hobbs <hobbs@scriptics.com>
+
+ * canvas.test: added test for 5783.
+ * generic/tkCanvPoly.c (DisplayPolygon): added checks for the
+ polygon fillGC not being empty to prevent segfault. [Bug: 5783]
+
+2000-05-31 Eric Melski <ericm@scriptics.com>
+
+ * library/bgerror.tcl: Improved bgerror based on work by Donal
+ K. Fellows; no longer dependant on tk_dialog; features a
+ Windows-esque "Details" button, and a customizable extra function
+ button that allows the user to (for example) save the stack trace
+ to a file.
+
+2000-05-30 Eric Melski <ericm@scriptics.com>
+
+ * generic/tkImgGIF.c: Changed defines for GIF87a/GIF89a to be
+ static char arrays with integer initialization, to address EBCIDIC
+ vs. ASCII encoding issues and to handle compilers that don't deal
+ with "\xAB" syntax for specifying hex values in strings.
+
+2000-05-28 Jeff Hobbs <hobbs@scriptics.com>
+
+ * doc/spinbox.n: (new file) docs for spinbox widget
+ * generic/tkInt.h: added Tk_SpinboxObjCmd declaration
+ * generic/tkEntry.c: added 'spinbox' widget - an extension of the
+ entry widget type.
+ * generic/tkWindow.c: added 'spinbox' to core Tk commands
+ * library/spinbox.tcl: (new file) binding and helper procs for spinbox
+ * library/tk.tcl: added spinbox.tcl to list of files to source
+ * tests/entry.test: updated changed error messages
+ * tests/spinbox.test: (new file) test suite for spinbox
+
+ * generic/tkPlace.c (Tk_PlaceCmd): reworked place master/slave
+ table init'n to prevent seg fault when using place on multiple
+ displays.
+
+ * generic/tk.h: added comments ot Tk_FakeWin structure
+
+2000-05-26 Eric Melski <ericm@scriptics.com>
+
+ * generic/tkOption.c (Tk_GetOption): Extended Tk_GetOption to
+ support a new syntax for option names in option tables. If the
+ option name has an embedded ".", it indicates that the name field
+ contains both an option name and an overriding widget class, in
+ the form "class.option". The lookup for the option value will be
+ performed as though the widget class is that specified, rather
+ than the actual widget class.
+ (SetupStacks): Replaced several lines of array element copying
+ with a for loop for conciseness.
+
+2000-05-25 Eric Melski <ericm@scriptics.com>
+
+ * library/button.tcl: Tweaks for -overrelief handling on Windows.
+
+ * doc/radiobutton.n: Added documentation for -overrelief option.
+
+ * doc/checkbutton.n: Added documentation for -overrelief option.
+
+ * doc/label.n: Added documentation for -state option.
+
+ * generic/tkButton.c: Added -overrelief option for checkbuttons,
+ and radiobuttons.
+
+ * library/button.tcl (tkButtonDown, macintosh version): Added
+ protection against querying the -repeatdelay option from a widget
+ that doesn't support it (ie, checkbuttons, radiobuttons, etc).
+ Other platforms use a different binding script for checkbuttons
+ and radiobuttons, so they don't have this issue.
+ (tkCheckRadioEnter, windows version): Added code to handle
+ -overrelief for check/radiobuttons on windows.
+
+2000-05-22 Eric Melski <ericm@scriptics.com>
+
+ * generic/tkButton.c: Added -activeforeground, -activebackground
+ for labels, for the -state option.
+
+ * doc/label.n: Added documentation for -state option,
+ -activeforeground, -activebackground.
+
+2000-05-22 Jeff Hobbs <hobbs@scriptics.com>
+
+ * win/Makefile.in (install-libraries): corrected to install X
+ headers [Bug: 5516]
+
+ * doc/bind.n:
+ * doc/canvas.n:
+ * doc/entry.n:
+ * doc/listbox.n:
+ * doc/photo.n: doc fix-ups [Bug: 5396]
+
+2000-05-17 Jeff Hobbs <hobbs@scriptics.com>
+
+ * doc/bell.n:
+ * tests/bell.test:
+ * generic/tkCmds.c (Tk_BellObjCmd): added -nice option to
+ optionally avoid resetting screen saver [Bug: 4279]
+
+2000-05-15 Jeff Hobbs <hobbs@scriptics.com>
+
+ * win/tkWinWm.c (Tk_WmCmd): changed wm deiconify from using idle
+ callback to calling restack and focus code immediately.
+
+2000-05-17 Eric Melski <ericm@scriptics.com>
+
+ Overall change: Added "-readonlybackground" option for entries,
+ to enable a visual change when state goes to readonly.
+
+ * mac/tkMacDefault.h (DEF_ENTRY_READONLY_BG_COLOR)
+ (DEF_ENTRY_READONLY_BG_COLOR):
+ * win/tkWinDefault.h (DEF_ENTRY_READONLY_BG_COLOR)
+ (DEF_ENTRY_READONLY_BG_COLOR):
+ * unix/tkUnixDefault.h (DEF_ENTRY_READONLY_BG_COLOR)
+ (DEF_ENTRY_READONLY_BG_COLOR): Added default values for entry
+ -readonlybackground option.
+
+ * generic/tkEntry.c: Added -readonlybackground option, cleaned up
+ excessive use of graphics contexts.
+
+ * tests/entry.test: Added configuration test for
+ -readonlybackground option.
+
+ * doc/entry.n: Added documentation for -readonlybackground option.
+
+ Overall change: changed implementation of "link" relief for
+ buttons. Instead of a new relief style (-relief link), there is a
+ new option, -overrelief, which if set is used when the mouse is
+ over the button.
+
+ * doc/SetOptions.3: Added information about TK_OPTION_NULL_OK with
+ TK_OPTION_RELIEF.
+
+ * win/tkWinButton.c: Removed bits about TK_RELIEF_LINK.
+
+ * tests/button.test: Added tests for -overrelief; removed tests
+ for -relief link.
+
+ * mac/tkMacButton.c: Removed bits about TK_RELIEF_LINK.
+
+ * generic/tkOldConfig.c: Removed bits about TK_RELIEF_LINK.
+
+ * generic/tkConfig.c: Removed bits about TK_RELIEF_LINK; added
+ support for TK_OPTION_NULL_OK for TK_OPTION_RELIEF.
+
+ * library/button.tcl: Added binding support for -overrelief.
+
+ * generic/tk3d.c (Tk_GetRelief): Added branch for TK_RELIEF_NULL.
+
+ * generic/tkButton.c: Added -overrelief option; removed
+ Enter/Leave EventProc masks and handlers.
+
+ * generic/tk.h: Added TK_RELIEF_NULL definition, removed
+ TK_RELIEF_LINK.
+
+ * mac/tkMacDefault.h (DEF_BUTTON_OVER_RELIEF):
+ * win/tkWinDefault.h (DEF_BUTTON_OVER_RELIEF):
+ * unix/tkUnixDefault.h (DEF_BUTTON_OVER_RELIEF): Added default
+ value for the -overrelief option.
+
+2000-05-16 Eric Melski <ericm@scriptics.com>
+
+ * win/tkWinMenu.c (ReconfigureWindowsMenu): Added code to add the
+ MF_SEPARATOR bit for SEPARATOR_ENTRY menu items. This causes
+ separator entries on the system menu to be drawn correctly [Bug: 5451].
+
+2000-05-15 Eric Melski <ericm@scriptics.com>
+
+ * doc/image.n: Added documentation for [image inuse] command.
+
+ * tests/image.test: Added tests for [image inuse] command.
+
+ * generic/tkImage.c (Tk_ImageObjCmd): Added [image inuse] command,
+ which provides a means for programmers to determine if a given
+ image is in use by any widgets. [RFE: 3327].
+
+2000-05-14 Eric Melski <ericm@scriptics.com>
+
+ * doc/clipboard.n: Added documentation for "clipboard get".
+
+ * generic/tkClipboard.c (Tk_ClipboardCmd): Added "clipboard get"
+ subcommand [RFE: 4628].
+
+ * tests/clipboard.test: Updated to use "clipboard get" instead of
+ "selection get -s CLIPBOARD".
+
+ * library/entry.tcl: Adjusted Button-1 binding to set focus to the
+ entry when it is readonly or normal.
+
+ * doc/entry.n: Added documentation for readonly state,
+ -disabledforeground, -disabledbackground.
+
+ * tests/entry.test: Added tests for readonly state.
+
+ * generic/tkEntry.c: Added support for "readonly" state, and
+ redefined "disabled" state. A disabled entry will display its
+ text in a dimmed color and possibly with a different background,
+ and will be completely unusable (no selection, no editing). A
+ readonly entry will look like a normal entry, but it will not be
+ editable; selection is still allowed. [RFE: 4239]. To support the
+ new disabled state properly, "-disabledforeground" and
+ "-disabledbackground" options were added.
+ *** THIS IS A BACKWARDS INCOMPATIBLE BEHAVIOR CHANGE ***
+
+ * win/tkWinDefault.h:
+ * mac/tkMacDefault.h:
+ * unix/tkUnixDefault.h: Added DEF_ENTRY_DISABLED_FG,
+ DEF_ENTRY_DISABLED_BG_COLOR, DEF_ENTRY_DISABLED_BG_MONO.
+
+2000-05-12 Eric Melski <ericm@scriptics.com>
+
+ * unix/tkUnixButton.c (TkpDisplayButton, TkpComputeButtonGeometry):
+ * mac/tkMacButton.c (TkpDisplayButton, TkpComputeButtonGeometry):
+ * win/tkWinButton.c (TkpDisplayButton, TkpComputeButtonGeometry):
+ Added code for drawing compound buttons.
+
+ * tests/button.test: Added configuration tests for -repeatdelay,
+ -repeatinterval, -compound.
+
+ * library/button.tcl: Added support for -repeatedelay,
+ -repeatinterval options.
+
+ * generic/tkOldConfig.c: Changed handling of link relief so that
+ proper error messages are used.
+
+ * generic/tkButton.h: Added -compound, -repeatdelay,
+ -repeatinterval options.
+
+ * generic/tkButton.c: Added event watchers for enter/leave events,
+ for link relief support.
+
+ * generic/tk3d.c: Changed handling of link relief so that proper
+ error messages are used.
+
+ * generic/tk.h: Changed values of
+ TK_OPTION_LINK_OK/TK_CONFIG_LINK_OK for link relief support.
+
+2000-05-12 Jeff Hobbs <hobbs@scriptics.com>
+
+ * win/tkWinFont.c (LoadFontRanges): improved support for all chars
+ in 0-255 range for bitmap ANSI fonts. May be improved to handle
+ bitmap non-ANSI fonts in the future. [Bug: 2172]
+
+ * win/tkWinWm.c (RaiseWinWhenIdle): added TK_DONT_DESTROY_WINDOW
+ to flag check to prevent timing related core dump. [Bug: 5438]
+
+2000-05-11 Jeff Hobbs <hobbs@scriptics.com>
+
+ * win/tkWinTest.c (TestclipboardObjCmd): ensured CloseClipboard
+ would always get called for each OpenClipboard.
+
+ * tests/focus.test (focusSetupAlt): removed wm withdraw from proc
+ as it would cause a hang for tkwait visibility
+
+ * tests/menu.test:
+ * generic/tk3d.c:
+ * generic/tkColor.c:
+ * generic/tkCursor.c: corrected handling of 3DBorder, Cursor and
+ Color objects on multiple screens. [Bug: 5454]
+
+2000-05-09 Eric Melski <ericm@scriptics.com>
+
+ * doc/button.n: Added documentation for link relief.
+
+ * tests/button.test: Added tests for link relief for buttons.
+
+ * generic/tk.h (TK_CONFIG_LINK_OK): Added definition of
+ TK_RELIEF_LINK, TK_OPTION_LINK_OK and TK_CONFIG_LINK_OK. [RFE: 4348]
+
+ * generic/tk3d.c: Added support for link relief. [RFE: 4348]
+
+ * mac/tkMacButton.c (TkpDisplayButton):
+ * unix/tkUnixButton.c (TkpDisplayButton): Added support for link
+ relief. [RFE: 4348]
+
+ * generic/tkOldConfig.c (Tk_ConfigureWidget):
+ * generic/tkConfig.c (DoObjConfig): Added understanding of link
+ relief, which is allowed only for widgets that have
+ TK_OPTION_LINK_OK or TK_CONFIG_LINK_OK set for the "-relief"
+ option. [RFE: 4348]
+
+ * generic/tkButton.c: Added TK_OPTION_LINK_OK to "-relief" option
+ for buttons. [RFE: 4348]
+
+ * win/tkWinWm.c (EX_TRANSIENT_STYLE): Removed WS_EX_TOOLWINDOW
+ style bit, so that transient windows have full-size titlebars
+ (like the tk_getOpenFile dialog).
+
+ * win/tkWinMenu.c (GetMenuSeparatorGeometry): Tweaked height
+ requested for separator bars to be (linespace - (2*descent))
+ instead of just (linespace); this makes the separator occupy a
+ more correct amount of vertical space. [Bug: 5303].
+
+2000-05-09 Jeff Hobbs <hobbs@scriptics.com>
+
+ * library/focus.tcl: fixed calling of takeFocus proc [Bug: 5372]
+
+2000-05-02 Jeff Hobbs <hobbs@scriptics.com>
+
+ * README:
+ * generic/tk.h:
+ * library/tk.tcl:
+ * mac/README:
+ * unix/README:
+ * unix/configure.in:
+ * unix/tk.spec:
+ * win/README:
+ * win/aclocal.m4:
+ * win/configure.in:
+ * win/makefile.vc: updated patchlevel to 8.4a1
+
+ * unix/Makefile.in: added tk.spec to dist target
+
+2000-04-27 Eric Melski <ericm@scriptics.com>
+
+ * doc/Tk_Init.3: Added Tk_SafeInit information [Bug: 1884].
+
+ * doc/keysyms.n: Man page enumerating keysyms [RFE: 1645].
+
+ * doc/colors.n: Man page enumerating valid color names [RFE: 1645].
+
+ * doc/cursors.n: Man page enumerating valid cursor values [RFE: 1645].
+
+ * library/msgbox.tcl: Corrected Unix tk_messageBox implementation
+ to make the first button the default when no default is specified
+ [Bug: 2218].
+
+ * doc/messageBox.n: Updated documentation with regards to
+ selection of default button when none is specified (now it will
+ use the first button as the default in that case) [Bug: 2218].
+
+2000-04-26 Jeff Hobbs <hobbs@scriptics.com>
+
+ 8.3.1 RELEASE
+
+ * README:
+ * mac/README:
+ * unix/README:
+ * unix/tk.spec:
+ * win/README: Updating URLs to reference dev.scriptics.com
+
+2000-04-25 Jeff Hobbs <hobbs@scriptics.com>
+
+ * unix/Makefile.in:
+ * win/Makefile.in: makefile cleanup
+
+2000-04-25 Eric Melski <ericm@scriptics.com>
+
+ * generic/tkMain.c: Fixed function header comment for Tk_MainEx.
+
+ * unix/mkLinks:
+ * doc/GetScroll.3: Added information about Tk_GetScrollInfoObj
+ [Bug: 1866].
+
+2000-04-24 Eric Melski <ericm@scriptics.com>
+
+ * unix/mkLinks:
+ * doc/Grab.3: Man page for Tk_Grab and Tk_Ungrab [Bug: 1868, 1889]
+
+ * unix/mkLinks:
+ * doc/MainWin.3: Added entry for Tk_GetNumMainWindows [Bug: 1865].
+
+ * unix/mkLinks:
+ * doc/GetHINSTANCE.3: Man page for Tk_GetHINSTANCE [Bug: 1862].
+
+2000-04-24 Jeff Hobbs <hobbs@scriptics.com>
+
+ * generic/tkImage.c (Tk_PostscriptImage): added check to create
+ necessary prolog for photos
+ * generic/tkCanvPs.c: added Tk_PostscriptPhoto that outputs PS for
+ photo images
+ * generic/tkImgPhoto.c: new func ImgPhotoPostscript and added that
+ in as ps proc in tkPhotoImageType.
+ * generic/tkStubInit.c:
+ * generic/tkDecls.h:
+ * generic/tk.decls: added Tk_PostscriptPhoto
+
+ * generic/tkConfig.c (DoObjConfig): removed direct setting of
+ interp->result.
+
+ * mac/tkMacWm.c (Tk_WmCmd): initialized gotToplevel in
+ colormapwindows case (bug found by Reasoning, Inc's automated code
+ testing).
+
+2000-04-24 Eric Melski <ericm@scriptics.com>
+
+ * unix/mkLinks:
+ * doc/GetHWND.3: Man page for Tk_GetHWND [Bug: 1863].
+
+ * unix/mkLinks:
+ * doc/HWNDToWindow.3: Man page for Tk_HWNDToWindow [Bug: 1869].
+
+ * unix/mkLinks:
+ * doc/AddOption.3: Man page for Tk_AddOption [Bug: 1854]
+
+2000-04-22 Jim Ingham <jingham@cygnus.com>
+
+ * mac/tkMacDialog.c (Tk_MacGetOpenFile): Add empty bodies for the
+ "-initialfile" and "-defaultextension" options.
+
+ * mac/tkMacDialog.c (NavServicesGetFile): Only cons the result up
+ into a list if multiple is true.
+
+ * mac/tkMacMenus.c (SourceDialog): Use the "tk_getOpenFile"
+ instead of hand-coding the dialog with StandardGetFile. This way
+ we get the Navigation dialogs for free.
+
+ * doc/getOpenFile.n: Document the -multiple and -message flags
+ which are only implemented on the Mac. Also note that the -title
+ works on the Mac with Nav Services installed.
+
+2000-04-19 Eric Melski <ericm@scriptics.com>
+
+ * doc/WinViewable.3:
+ * unix/mkLinks: Removed docs for Tk_IsViewable.
+
+ * win/tkWinDialog.c: Removed calls to Tk_IsViewable.
+
+ * generic/tkUtil.c:
+ * generic/tkStubInit.c:
+ * generic/tkDecls.h:
+ * generic/tkCmds.c:
+ * generic/tk.decls: Removed Tk_IsViewable function (it was not
+ actually needed).
+
+2000-04-19 Jeff Hobbs <hobbs@scriptics.com>
+
+ * win/aclocal.m4: made SC_PROG_TCLSH search specifically for
+ tclsh*.exe type files to find an executable.
+
+ * win/Makefile.in: fixed up cleanup, winhelp, cat32 targets
+
+ * library/console.tcl: made console use systemfixed font on Win
+
+ * generic/tkEntry.c: removed unnecessary ENTRY_VALIDATE #define
+
+2000-04-19 Eric Melski <ericm@scriptics.com>
+
+ * generic/tkRectOval.c (ConfigureRectOval): Added checks for valid
+ outline settings before creating of outline GC; this means that it
+ is really possible now to have an oval or rectangle with no
+ outline. [Bug: 5029].
+
+2000-04-19 Jeff Hobbs <hobbs@scriptics.com>
+
+ * library/choosedir.tcl (::tk::dialog::file::chooseDir::Config):
+ * library/tkfbox.tcl (::tk::dialog::file::Config): removed the
+ extraneous glob on -initialdir after file isdir already returned 1
+ and moved cd trick into this case as the else already uses [pwd].
+ [Bug: 5181]
+
+ * win/winMain.c: moved extern call out of WinMain func
+
+ * README:
+ * generic/tk.h:
+ * unix/configure.in:
+ * unix/tk.spec:
+ * win/configure.in: bumped to version 8.3.1
+
+ * library/msgbox.tcl (tkMessageBox): changed to use grid in some
+ places, realign icon to anchor nw.
+
+ * mac/tkMacScale.c: reverted tkMacScale.c to 1.5 equivalent (it
+ was accidentally bumped forward).
+
+2000-04-18 Eric Melski <ericm@scriptics.com>
+
+ * win/tkWinPointer.c: Changed Mod2Mask in TkWinGetModifierState to
+ ALT_MASK, to fix some event problems [Bugs: 1160, 5088].
+
+ * win/tkWinX.c: Changed Mod2Mask in GetState to ALT_MASK, to fix
+ some event problems [Bugs: 1160, 5088].
+
+ * generic/tkInt.h: Moved definition of ALT_MASK and META_MASK here
+ so that it would be accessible from other modules than tkBind.c.
+
+ * generic/tkBind.c: Added code in BindEvent to check for ALT_MASK
+ and META_MASK in the event state field, as this field may not be
+ set up with the correct display modifier mask bits if the XEvent
+ structure was created by [event generate] or by the Windows X
+ emulation. [Bugs: 1160, 5088].
+
+2000-04-18 Scott Redman <redman@HILO>
+
+ * win/tk.rc:
+ * win/wish.rc:
+ * win/wish.ico: Modified copyright dates in Windows resource
+ files. Updated the icon for wish.exe.
+
+2000-04-17 Eric Melski <ericm@scriptics.com>
+
+ * win/tkWinDialog.c: Added checks for visibility of parent window
+ before creating MessageBox and ChooseColor dialogs; this prevents
+ the application from locking when the parent is withdrawn and the
+ message box is created. In these cases, the window will be
+ created without a parent.
+
+ * unix/mkLinks: Added WinViewable.3.
+
+ * tests/msgbox.test: Added tests for patch from [Bug: 4997].
+
+ * library/msgbox.tcl:
+ * library/dialog.tcl: Applied patch from [Bug: 4997]; detaches
+ dialog window from parent if parent is not viewable.
+
+ * library/bgerror.tcl: Removed workaround from [Bug: 4370]; this
+ is superceeded by patches to dialog.tcl.
+
+ * generic/tkCmds.c: Changed WinfoObjCmd to use Tk_IsViewable
+ function to determine visibility of windows instead of inlining
+ the code.
+
+ * generic/tkStubInit.c:
+ * generic/tkDecls.h:
+ * generic/tk.decls: Added Tk_IsViewable declaration.
+
+2000-04-17 Eric Melski <ericm@scriptics.com>
+
+ * library/text.tcl: Tweaked double-/triple-click selection;
+ previously, anchor and insert marks were placed in unexpected
+ locations following a double or triple click. Now they are placed
+ logically. Also tweaked the extension of selection via
+ shift-double-clicks so that it no longer selects the contiguous
+ whitespace on the side of the selection opposite the
+ double-click. [RFE: 4253].
+
+ * doc/menu.n: Added note regarding rendering of
+ checkbuttons/radiobuttons in menubars on different platforms --
+ some systems do not draw indicators for check/radiobuttons in
+ menubars.
+
+ * library/menu.tcl: Corrected behavior of
+ checkbuttons/commands/radiobuttons in menubars [Bug: 630].
+
+ * tests/grid.test: Added test for [grid propagate . 0] to not toggle.
+
+ * generic/tkGrid.c: Fixed bogus logic in [grid propagate] that
+ caused [grid propagate . 0] to act as a toggle instead of an
+ absolute set. [Bug: 2286].
+
+2000-04-16 Jeff Hobbs <hobbs@scriptics.com>
+
+ * win/tkWinColor.c (FindSystemColor): correct calculation of
+ colors when shifting value. [Bug: 4919]
+
+2000-04-16 Jim Ingham <jingham@cygnus.com>
+
+ * mac/tkMacPort.h: protect against strncasecmp already defined -
+ it is in the Pro5 version of MSL.
+
+ * mac/tkMacWindowMgr.c (GenerateKeyEvent): Check for a null tkWin.
+ If the hidden window we use for double-buffering controls manages
+ to percolate to the top (should never happen, but...) this will
+ keep us from crashing.
+
+ * mac/tkMacButton.c (InitSampleControls): Hide the
+ double-buffering window BEHIND the first "." window you can find.
+ This will keep it from ever being the front window, and thus a
+ black hole for events. * mac/tkMacButton.c (ButtonEventProc):
+ Disable the controls when the window is in the background. This
+ is required by the MacOS HIG. This doesn't always get called when
+ it should, it still needs more work.
+
+ * mac/tkMacDialog.c: Pretty substantial rewrite to include
+ Navigation Services support for systems which have it.
+
+2000-04-14 Eric Melski <ericm@scriptics.com>
+
+ * win/tkWinKey.c: Added check for ASCII delete character in
+ KeycodeToKeysym, to fix [Bug: 5090]. See comment in code for more
+ information.
+
+ * generic/ks_names.h: Added Scroll_Lock and Sys_Req definitions.
+
+ * win/tkWinKey.c: Changed implementation of KeycodeToKeysym,
+ et. al., to use a keycode table for lookups; this will result in
+ faster keycode -> keysym translations for non-ASCII keys like
+ Control, Alt, etc.
+
+2000-04-14 Jeff Hobbs <hobbs@scriptics.com>
+
+ * win/tkWinWm.c (WmProc): added check in WM_MOUSEACTIVATE so we
+ correctly activate native menus when clicking in when we didn't
+ have focus [Bug: 2272]
+
+ * generic/tkCanvas.c (CanvasEventProc:2451): corrected cast
+
+ * generic/tkEntry.c (Tk_EntryObjCmd): adjusted finishing error
+ cases and changed TK_CONFIG_NULL_OK to TK_OPTION_NULL_OK
+
+ * tests/scale.test:
+ * generic/tkScale.c:
+ * generic/tkScale.h:
+ * unix/tkUnixScale.c:
+ * mac/tkMacScale.c: moved (PixelToValue|ValueToPixel|SetScaleValue)
+ to tkScale.c. Caused an associated variable to be immediately set
+ [Bug: 4833]
+
+ * library/scale.tcl (tkScaleActivate): reduced number of scale
+ redisplays by checking current value of state before setting it
+ again. [Bug: 4191]
+
+ * tests/winDialog.test: tk_chooseDirectory seems to get a noop
+ from GetOpenFileName in the static build, hanging some tests.
+ The tests were fixed to timeout (noop cause unknown).
+
+ * unix/aclocal.m4 (SC_ENABLE_THREADS): enhanced the detection of
+ pthread_mutex_init [Bug: 4359] and (SC_CONFIG_CFLAGS) added
+ --enable-64bit-vis switch for Sparc VIS compilation [Bug: 4995]
+
+2000-04-13 Eric Melski <ericm@scriptics.com>
+
+ * win/tkWinKey.c: Added smarts to check whether the left or right
+ Control, Shift, or Alt key was pressed. [Bug: 870].
+
+ * win/tkWinMenu.c: Corrected code that created separator items on
+ menus; originally, it requested that the system be responsible for
+ drawing those items, so it would ignore configuration items like
+ the widget background. Now, we draw the separators ourselves (as
+ we do with every other kind of menu item already). [Bug: 1166].
+
+ * win/tkWin3d.c:
+ * unix/tkUnix3d.c: Applied patch from [RFE: 2501]: adds more
+ sophisticated smarts to TkpGetShadows, so that the highlight of a
+ very bright color is actually distinguishable from the color, and
+ the shadow of a very dark color is similarly distinguishable from
+ the color.
+
+ * generic/tkCanvas.c: Applied patch from [Bug: 4202]; adds a check
+ for NULL tkwin in Tk_CanvasEventuallyRedraw.
+
+2000-04-12 Jeff Hobbs <hobbs@scriptics.com>
+
+ * test/winClipboard.test:
+ * win/tkWinInt.h:
+ * win/tkWinClipboard.c (UpdateClipboard):
+ * win/tkWinX.c (GenerateXEvent): added updatingClipboard tsd and
+ TkWinUpdatingClipboard accessor function to allow us to flag
+ ourselves when we are the ones updating the clipboard. This
+ corrected inability to create our own clipboard types within a Tk
+ application. [Bug: 2338 4318]
+ * win/tkWinTest.c (TestclipboardCmd): improved TestclipboardCmd
+ with better error handling and obj'ification
+
+2000-04-11 Eric Melski <ericm@scriptics.com>
+
+ * msgcat.n: Added docs for new behavior from patch in [Bug: 4158].
+
+ * msgcat.test: Added tests for new behavior from patch in [Bug:
+ 4158].
+
+ * msgcat.tcl: Applied patch from [Bug: 4158], which enables
+ msgcat::mc to search the entire namespace ancestry chain for
+ message translations (ie, first it checks the current namespace,
+ then the parent, then the parent's parent, etc). Also allows the
+ specification of additional args for msgcat::mc; if extra args are
+ given, the [format] command is used to substitute the additional
+ args in the translated message.
+
+ * library/bgerror.tcl: Moved check for withdrawn state after check
+ for tkerror; this was causing problems when tkerror was used.
+
+2000-04-10 Eric Melski <ericm@scriptics.com>
+
+ * library/bgerror.tcl: Added check for withdrawn state of . and
+ unsetting of transient bit for .bgerrorDialog if . is not
+ viewable; this protects against the application hanging on systems
+ like Windows, where transient windows are withdrawn with their
+ parents. [Bug: 4370].
+
+ * tests/event.test: Added test for [event generate $widget
+ <Alt-z>] [Bug: 4611].
+
+ * tests/choosedir.test: Changed "namespace import ::tcltest" to
+ "namespace import -force ::tcltest".
+
+ * win/tkWinKey.c:
+ * unix/tkUnixKey.c:
+ * mac/tkMacKeyboard.c: Changed InitKeymapInfo to
+ TkpInitKeymapInfo. [Bug: 4611].
+
+ * generic/tkStubInit.c:
+ * generic/tkIntDecls.h: Re-gen'd from tkInt.decls.
+
+ * generic/tkInt.decls: Added TkpInitKeymapInfo to list of function
+ decls.
+
+ * generic/tkBind.c (HandleEventGenerate): Added code to initialize
+ keymap info if necessary, and to correctly set modifier bits in
+ XEvent structure create to handle [event generate] calls.
+ Previously, the alt/meta bits were not set correctly, so [event
+ generate $widget <Alt-z>] would always fail. [Bug: 4611]
+
+2000-04-07 Jeff Hobbs <hobbs@scriptics.com>
+
+ * generic/tkGrid.c (InitMasterData): fixed uninit'd data in
+ GridMaster struct [Bug: 4387]
+
+ * library/safetk.tcl (disallowTk): made disallowTk work in the
+ simple case.
+
+ * library/comdlg.tcl (tkFocusGroup_In): fixed key navigation
+ problems in dialogs under CDE [Bug: 2960]
+
+ * tests/winDialog.test: removed knownBug constraint from 5.16
+
+ * win/tkWinFont.c (GetScreenFont): corrected adjustment against
+ LC_FACESIZE limitation for NT [Bug: 4931]
+
+ * win/makefile.vc (TKTEST_OBJS):
+ * win/Makefile.in (TKTEST_OBJS): moved tkWinTest.c from normal
+ objs to TKTEST_OBJS where it belonged.
+
+2000-04-03 Jeff Hobbs <hobbs@scriptics.com>
+
+ * generic/tkTest.c: fixed incorrect platform inclusion for
+ TkplatformtestInit (it would never get called).
+
+ * unix/Makefile.in (MAN_INSTALL_DIR): patch to accept --mandir
+ correctly [Bug: 4085]
+
+ * library/clrpick.tcl (tkColorDialog_Config): error now thrown
+ when -initialcolor "" specified. [Bug: 4198]
+
+2000-03-31 Jeff Hobbs <hobbs@scriptics.com>
+
+ * doc/DrawFocHlt.3: doc name correction
+
+ * generic/tkEntry.c: set TK_OPTION_NULL_OK bit on -invcmd option
+ and removed #ifdef ENTRY_VALIDATE expressions
+
+ * library/menu.tcl (tkMenuInvoke): corrected naming of tearoffs
+ [Bug: 4506]
+
+ * library/tkfbox.tcl (tkIconList_Goto): caused browsecmd to be
+ called in tkIconList_Select. This causes the entry to be set
+ properly when using the type-in-name-in-listbox bindings.
+
+ * win/tkWinDialog.c: added unicode-aware open/save file dialogs
+
+ * win/tkWinFont.c (TkpFontPkgInit): move private ref to platformId
+ to TkWinGetPlatformId
+
+ * win/tkWinMenu.c (SetDefaults): moved private use of versionInfo
+ to TkWinGetPlatformId and removed all code for
+ (versionInfo.dwMajorVersion < 4) (== Win32s)
+
+ * win/tkWinX.c:
+ * win/tkWin32Dll.c: moved TkWinGetPlatformId to tkWinX.c
+ * win/tkWinInit.c: added TkWinXInit to TkpInit to ensure that its
+ called for static Windows shells. [Bug: 3647]
+
+ * win/tkWinInt.h:
+ * win/tkWinX.c:
+ * win/tkWinDraw.c (SetUpGraphicsPort):
+ * win/tkWinScrlbr.c (UpdateScrollbar): removed use of tkpIsWin32s
+
+ * win/tkWinInt.h (TkWinDCState struct): added bkmode value
+ * win/tkWinDraw.c (TkWinGetDrawableDC, et al): added support for
+ properly transparent dashed lines on Windows. [Bug: 4617]
+
+2000-03-30 Eric Melski <ericm@scriptics.com>
+
+ * generic/tkImgGIF.c: Fixed some ANSI specific bits to avoid
+ compile problems with non-ANSI compilers (ie, replace const with
+ CONST, etc). [Bug: 4223].
+
+ * unix/configure.in: Applied patch from [Bug: 4237]; ensures that
+ srcdir is fully qualified.
+
+ * unix/Makefile.in: Applied patch from [Bug: 4237]; if tcltest was
+ not compiled, make test/tktest failed. Now it has a rule to build
+ tcltest if it has not been built.
+
+2000-03-28 Eric Melski <ericm@scriptics.com>
+
+ * library/tkfbox.tcl: Moved an overlooked tkFDialog* function in
+ ::tk::dialog::file namespace.
+
+ * tests/unixWm.test: Added tests for memory leak conditions in
+ tkUnixWm.c.
+
+ * tests/canvas.test: Added test for bad configuration options on
+ empty and non-empty canvas.
+
+ * generic/tkCanvas.c: Removed bad code in CANV_CONFIGURE block of
+ CanvasWidgetCmd; this was causing non-empty canvases to improperly
+ handle bad configuration options [Bug: 4456].
+
+2000-03-27 Eric Melski <ericm@scriptics.com>
+
+ * unix/tkUnixWm.c: Applied patch from [Bug: 4405]; fixes memory
+ leak in Unix wm command.
+
+2000-03-24 Eric Melski <ericm@scriptics.com>
+
+ * tests/filebox.test:
+ * tests/choosedir.test: Updated tests.
+
+ * library/xmfbox.tcl: Updated to stash data array in
+ ::tk::dialog::file namespace instead of in global namespace.
+
+ * library/tkfbox.tcl: Extended some functions to support creation
+ of a choosedir dialog, to allow greater code reuse between the two
+ dialogs. Moved tkFDialog* functions into a namespace
+ (::tk::dialog::file). Because these are private Tk functions (and
+ should thus not be used directly by users), this should not impact
+ anybody (the tk_getOpenFile and tk_getSaveFile commands still
+ exist at the global scope).
+
+ * library/tk.tcl:
+ * library/tclIndex: Updated function names for tkFDialog*
+ functions and choosedir functions.
+
+ * library/choosedir.tcl: New and improved implementation of
+ tk_chooseDirectory dialog. Based on tk_getOpenFile dialog.
+
+2000-03-23 Eric Melski <ericm@scriptics.com>
+
+ * generic/tkWindow.c:
+ * generic/tkInt.h: Updated Tcl_OptionCmd -> Tcl_OptionObjCmd
+
+ * generic/tkOption.c: Tcl_Obj'ectified the "option" command.
+
+2000-03-22 Eric Melski <ericm@scriptics.com>
+
+ * library/listbox.tcl (tkListboxCancel): Added a check for empty
+ string value for tkPriv(listboxPrev). Without this check, it's
+ possible to get a stack trace under certain conditions. [Bug: 4373].
+
+2000-03-15 Sven Delmas <sven@scriptics.com>
+
+ * win/tkWinDialog.c: Changed the behavior for the
+ tk_chooseDirectory dialog under Windows. Instead of trying to
+ return the currently selected listbox entry (which didn't work in
+ case the user selected the initial directory anyway), we now
+ return the value shown in the entry. This seems to be in
+ accordance with the expected behavior for this dialog.
+
+2000-03-14 Eric Melski <ericm@scriptics.com>
+
+ * tests/choosedir.test: Marked test 3.1 and 3.2 as bad until the
+ issue with those tests on IRIX can be determined.
+
+2000-03-10 Eric Melski <ericm@scriptics.com>
+
+ * library/menu.tcl: Applied patch from [Bug: 4155]; protects
+ against grabs on non-viewable windows.
+
+2000-03-08 Eric Melski <ericm@scriptics.com>
+
+ * tests/choosedir.test: Modified test 3.1 (-mustexist works) to be
+ more careful about cleaning up its potentially troublesome after
+ events.
+
+2000-03-07 Eric Melski <ericm@scriptics.com>
+
+ * tests/button.test:
+ * generic/tkButton.c: Added -disabledforeground/-state to labels.
+
+2000-03-07 Jeff Hobbs <hobbs@scriptics.com>
+
+ * tests/entry.test:
+ * generic/tkEntry.c (EntrySetValue): malloc the value when
+ validating because validation could cause the pointer to become
+ invalid. Also fixed configure to not trigger focus-based
+ validation. Improved use of Tcl_WrongNumArgs. [Bug: 4320]
+
+2000-03-06 Eric Melski <ericm@scriptics.com>
+
+ * library/menu.tcl: Added a check in tkMenuFirstEntry that changes
+ menu behavior to only auto-post an immediate child cascade if we
+ are currently on a menubar menu. This prevents massive
+ auto-cascading in cases where the first entry of the cascade is
+ itself a cascade, and the first entry of that cascade is a
+ cascade, and the first entry of that cascade is a cascade
+ ... [Bug: 676].
+
+ * generic/tkOldConfig.c: Added check for NULL tkwin value in
+ Tk_ConfigureWidget [Bug: 4079]
+
+ * generic/tkWindow.c: Added check for NULL tkwin value in
+ Tk_NameToWindow [Bug: 4079]
+
+2000-03-02 Jeff Hobbs <hobbs@scriptics.com>
+
+ * tests/color.test:
+ * xlib/xcolors.c (XParseColor FindColor):
+ * win/tkWinColor.c (XAllocColor): Fixed bit fiddling for colors to
+ return "correct" values for color mapping. [Bug: 4282]
+
+ * unix/Makefile.in (SCRIPT_INSTALL_DIR): removed extraneous '/'
+ * unix/aclocal.m4: corrected TCL_NEEDS_EXP_FILE to be 1 for AIX
+
+ * win/tkWinInt.h: change extern to EXTERN for TkWinChildProc
+ declaration with extra #defs. [Bug: 4240]
+
+ * library/focus.tcl: fixed tkFocusOK to protect $w in
+ uplevel with list. [Bug: 4208]
+
+ * doc/CrtItemType.3: fixed docs for Tk_CreateItemType to reflect
+ changes made in 8.3.0 (but old style would still work as well).
+ [Bug: 4252]
+
+ * tests/config.test: extra test to check object cleanup when
+ destroying the widget
+ * generic/tkListbox.c (DestroyListbox): fixed crash in
+ DestroyListbox due to null tkwin. [Bug: 4207]
+
+ * tests/entry.test: added test suite for entry validation
+ * doc/entry.n: improved docs discussing caveats and gotchas when
+ mixing textvar with widget validation
+ * generic/tkEntry.c (EntryValidateChange): improved handling of
+ validation with relation to -textvariable. Previously, it would
+ turn off whenever the textvar was set. Now it will it will turn
+ off only when the textvar is set and validation returns 0. Added
+ %V (type of validation occuring) to %-subs to help work with
+ trickier validation.
+
+2000-03-01 Eric Melski <ericm@scriptics.com>
+
+ * tests/clrpick.test:
+ * library/clrpick.tcl: Added code to make color chooser dialog
+ inherit screen setting from parent (bug #2334)
+
+2000-02-25 Jeff Hobbs <hobbs@scriptics.com>
+
+ * win/tkWinWm.c (RaiseWinWhenIdle): Checked for the possibility
+ that the window could be destroyed (can occur with
+ wm deiconify .toplevel; destroy .toplevel).
+
+2000-02-25 Eric Melski <ericm@scriptics.com>
+
+ * generic/tkImgGIF.c: Applied "spirit of" the patch in 1605 (the
+ submitted patch was more complicated than necessary and did not
+ extend to writing GIF's, only reading), to allow reading/writing
+ of GIF files on EBCDIC and other non-ASCII based systems.
+
+2000-02-14 Eric Melski <ericm@scriptics.com>
+
+ * unix/tk.spec: RPM specification for producing a binary Tk RPM
+ for Linux.
+
+ * unix/Makefile.in: Added rpm target to generate Tk
+ binary RPM.
+
+2000-02-10 Jeff Hobbs <hobbs@scriptics.com>
+
+ 8.3.0 RELEASE
+
+ * changes: updated for 8.3.0 release
+
+ * generic/tkImgGIF.c (FileReadGIF): added cast for trashBuffer
+
+ * generic/tkIntXlibDecls.h:
+ * generic/tkInt.decls: declared some Xlib emulation calls for
+ the Mac
+
+ * generic/tkFrame.c (TkInstallFrameMenu): added extra panic to
+ inform user of bad call when framePtr is NULL [Bug: 2530]
+
+ * generic/tkMenu.c (DestroyMenuInstance): Placed checks around
+ menu name objects before trying to incr the ref. [Bug: 3402]
+
+ * generic/tkTest.c: removed USE_OLD_IMAGE def for Mac
+
+ * library/listbox.tcl:
+ * library/text.tcl: added support for <4> and <5> for mousewheel
+ style scrolling on Unix for mice that map to these buttons.
+
+ * tests/scrollbar.test: fixed check of testmetrics command to
+ allow unix tests to run (testmetrics is mac/pc only)
+
+ * unix/tkUnixWm.c (Tk_CoordsToWindow): qualified delete of error
+ handler as the goto label is reached from above and below.
+
+ * unix/configure.in:
+ * unix/aclocal.m4: cleaned up macros to coincide with tcl.m4,
+ added -export-dynamic to LDFLAGS for FreeBSD-3+ [Bug: 2998]
+
+ * unix/README:
+ * unix/Makefile.in (dist): removed porting.notes and porting.old
+ from distribution and CVS. The information was very outdated. Now
+ refer to http://dev.scriptics.com/services/support/platforms.html
+
+ * xlib/xgc.c: #def'd out XDrawSegments for the Mac, and added
+ some extra include info for the Mac
+
+2000-02-09 Jim Ingham <jingham@cygnus.com>
+
+ * mac/tkMacButton.c: Stop removing the appearance window from the
+ Window List. It is not clear why Ray did this, and it causes the
+ Appearance manager to crash at random times.
+
+ * mac/tkMacWM.c: Add support in unsupported1 style for the Appearance
+ specification of window styles, including floating window support.
+ * mac/tkMacWindowMgr.c: Operate on the front non-floating window,
+ unless the mouse is directly over the floating window. Also,
+ keystrokes go to the front non-floating window.
+ * mac/tkMacAppInit.c: Initialize floating window support.
+ * mac/tkMacScrlbr.c:
+ * mac/tkMacmenu.c: Fixes for floating windows - operate on the
+ FrontNonFloatingWindow.
+ * mac/tkMacLibrary.r: Fix typo in File info string.
+ * mac/tkMacApplication.r: Fix typo in file info string. Add
+ Finder balloon help for no apparent reason.
+
+ * mac/tkMacSubwindows.c: Change panic in tkMacGetDrawablePort to
+ Debugger. This is only a temporary fix. The panic is only
+ triggered when a safeTk interpreter is torn down, and ignoring it
+ does no harm. I haven't figured out how to avoid it yet, however.
+ Also use the Appearance MoveWindowStructure call when available.
+
+ New Files:
+ * MW_TkOldImageHeader.h: Handle #defining USE_OLD_IMAGE for tkImgPPM.c.
+ * MW_TkTestHeader.h:
+ * MW_TkTestHeader.pch:
+ * MW_TkHeader.h: Add separate prefix files for test & release
+ versions of Tk, so we can just have separate targets w/o having to
+ edit files.
+
+ * tclets.r: The D&D Tclets icon in rez form so we can have a
+ target for this.
+
+ The above are curtesy of Daniel Steffen (steffen@math.mq.edu.au)
+
+ * tkMacAppearanceStubs.c: Stubs of the Mac Appearance calls I use
+ so I can link the static 68K Shell without putting ifdef's all
+ over the code.
+
+2000-02-08 Jeff Hobbs <hobbs@scriptics.com>
+
+ * generic/tk.decls:
+ * generic/tkBind.c:
+ * generic/tkInt.decls:
+ * generic/tkIntDecls.h:
+ * generic/tkStubInit.c:
+ * mac/tkMacKeyboard.c:
+ * unix/tkUnixKey.c:
+ * win/tkWinKey.c: Fix for keyboard handling of "dead" keys and
+ caps lock from Peter Spjuth. [Bug: 4105 3359 2493]
+ Split functions into platform specific files:
+ Static functions GetKeySym(), SetKeycodeAndState() and InitKeymapInfo()
+ from tkBind.c moved into platform files tkWinKey.c tkUnixKey.c and
+ tkMacKeyboard.c. GetKeySym() and SetKeycodeAndState() renamed to
+ Tkp* and made public (as private functions) in tkInt.decls.
+
+ Step 2, fixes in tkWinKey.c
+ New static function: KeycodeToKeysym(), based on XKeycodeToKeysym()
+ but with different arguments, and a lot of improvements.
+ TkpGetString() changed to use KeycodeToKeysym() + other fixes.
+ TkpGetKeySym() changed to use KeycodeToKeysym() + other fixes.
+ InitKeymapInfo() changed to use KeycodeToKeysym().
+ TkpSetKeycodeAndState() rewritten, mostly by copying code from
+ XKeysymToKeycode().
+ XKeycodeToKeysym() rewritten. Preferably it should be removed.
+
+ EXPLANATION: The main problem is ToAscii() which has a lot of side
+ effects, and also that XKeycodeToKeysym() is not provided enough
+ input to do a proper job. The changes' main goal is to avoid
+ calling ToAscii() if not necessary, and to provide it with as
+ correct information as possible when called. Also some attempts
+ to clean up what ToAscii() did are done. See the code for details.
+
+ BUGS FIXED: Typing shifted (and AltGr) dead keys did not work.
+ Keyboard lock lamps did not work on Win98.
+ Events regarding AltGr-keys behaved badly.
+ Example: On a Swedish keyboard, $ is typed with AltGr-4.
+ That keyboard event would get the keysym '4' not 'dollar'.
+ Also, doing [event generete . <Key-dollar>] would send keysym '4'.
+ Translation to ascii in TkpGetString did not handle return and
+ tab correctly. I.e. [event generate . <Key-Return>] gave wrong %A
+
+ * generic/tkDecls.h:
+ * generic/tk.decls:
+ * generic/tk.h: moved new public functions created in dash patch
+ to the stubs interface [Bug: 4062]
+
+ * generic/tk.h:
+ * doc/CrtImgType.3:
+ * doc/CrtPhImgFmt.3:
+ * generic/tk.h:
+ * generic/tkImgGIF.c:
+ * generic/tkImgPhoto.c:
+ * generic/tkStubImg.c (new file):
+ * generic/tkTest.c:
+ * unix/Makefile.in:
+ * win/Makefile.in:
+ * win/makefile.vc: improved support for moving from the old style
+ image C API to the new obj'ified one with new Tk_InitImageArgs
+ command and stub'ing of image code. See docs for how to make the
+ transition. [Bug: 4060]
+
+ * library/tk.tcl: wrapped check for tcl_platform(os) around info
+ exists because it won't in safe interpreters
+
+ * win/tkWinFont.c: corrected symbol font use to only work on 8-bit
+ characters [Bug: 2406]
+
+ * unix/aclocal.m4: changed all -fpic to -fPIC
+
+ * README:
+ * unix/configure.in:
+ * win/configure.in:
+ * generic/tk.h (TK_RELEASE_SERIAL): Moved to 8.3.0 patchlevel
+
+2000-02-07 Eric Melski <ericm@scriptics.com>
+
+ * library/tkfbox.tcl: Applied patch from bug #4117,
+ tk_getOpenFile/getSaveFile doesn't do the right thing when user
+ types a directory name in the entry and a default extension is
+ specified.
+
+2000-02-05 Jeff Hobbs <hobbs@scriptics.com>
+
+ * unix/tkUnixScale.c (TkpDestroyScale): changed ckfree to
+ Tcl_EventuallyFree to behave with Tcl_Preserve in TkpDisplayScale
+ (prevents possible segfault).
+
+2000-02-03 Eric Melski <ericm@scriptics.com>
+
+ * tests/canvText.test: test for fix for bug #2525.
+
+ * generic/tkFont.c (Tk_ComputeTextLayout): Was erroneously setting
+ the width of newline-only text display chunks to some arbitrary
+ huge number, instead of 0; this was interfering with things like
+ the canvas find enclosed feature. (bug #2525).
+
+ * tests/text.test:
+ * generic/tkText.c (DumpLine/DumpSegment): Changed DumpSegment to
+ take a TkTextIndex instead of two integer offsets, so that it
+ could use TkTextPrintIndex to format the offsets into an index,
+ which makes it UTF smart (bug #2582).
+
+2000-02-01 Eric Melski <ericm@scriptics.com>
+
+ * library/tk.tcl:
+ * library/tclIndex:
+ * library/choosedir.tcl: Moved choosedir functions into the
+ ::tk::dialog::chooseDir namespace instead of a toplevel
+ ::tkChooseDirectory namespace. Additional cleanup on the
+ chooseDir dialog.
+
+2000-02-01 Jeff Hobbs <hobbs@scriptics.com>
+
+ * doc/text.n: clarified docs on what happens during a search with
+ -count when images/windows are embedded
+
+ * win/Makefile.in (install-*): reduced verbosity of install
+
+ * win/tkWinPixmap.c (XGetGeometry): added support for windows in
+ XGetGeometry [Bug: 4069]
+
+ * win/tkWinFont.c (GetScreenFont): fixed possible mem overrun with
+ long font names [Bug: 4108]
+
+ * win/tkWinDialog.c: added EnableWindow calls to dialogs to
+ correct for possible loss of control in parent Tk toplevel
+ [Bug: 1212 et al]
+
+ * generic/tkRectOval.c (ConfigureRectOval):
+ * generic/tkCanvLine.c (ConfigureLine):
+ * generic/tkCanvPoly.c (ConfigurePoly):
+ * generic/tkCanvArc.c (Configure/DisplayArc): fixed handling for
+ negative dash values [Bug: 4104]
+
+ * generic/tkScale.c (TkRoundToResolution): fixed incorrect
+ assumption that (N+1)*delta = N*delta + delta with floating point
+ math [Bug: 3689, 4099]
+ (DestroyScale) Fixed check for cancelling TkpDisplayScale (was
+ REDRAW_ALL, is now REDRAW_PENDING)
+
+ * tests/listbox.test: corrected test case for listbox itemconfigure
+
+ * unix/aclocal.m4: added *BSD ELF recognition for
+ SHARED_LIB_SUFFIX determination (from Tcl's tcl.m4)
+
+2000-01-27 Eric Melski <ericm@scriptics.com>
+
+ * generic/tkImgPhoto.c: Removed unneccesary object translation in
+ MatchStringFormat (bug #4103).
+
+2000-01-27 Eric Melski <ericm@scriptics.com>
+
+ * generic/tkImgGIF.c: Additional code cleanup (now we only have
+ one decoder! neat!)
+
+2000-01-26 Eric Melski <ericm@scriptics.com>
+
+ * doc/getOpenFile.n:
+ * doc/chooseDirectory.n: Man page/cross links for
+ tk_chooseDirectory (bug #1786).
+
+ * library/tk.tcl:
+ * library/tclIndex: Added hooks for tk_chooseDirectory. (bug #1786)
+
+ * library/choosedir.tcl: tk_chooseDirectory implementation for
+ Unix/Mac (bug #1786).
+
+ * generic/tkImgPhoto.c: Added some comments regarding slow
+ processing of transparent images.
+
+ * generic/tkImgGIF.c: Improved GIF decoder for ~60% speed
+ increase. Added some comments on how to further improve the
+ implementation, time permitting.
+
+ * doc/photo.n: Added a description of what the -data string can
+ contain (base64 or binary data).
+
+ * generic/tkImgPhoto.c: Fixed bug with use of binary data for
+ "-data" option to "image create" command.
+
+2000-01-21 Eric Melski <ericm@scriptics.com>
+
+ * library/tkfbox.tcl: Fixed bug relating to incorrect parent
+ values for error message boxes displayed by the file dialog (bug
+ #3616).
+
+ * tests/text.test:
+ * generic/tkText.c: Fixed bug relating to regexp searching for
+ empty lines; previously, the starting line was ignored. (bug #1643).
+
+2000-01-20 Jeff Hobbs <hobbs@scriptics.com>
+
+ * library/text.tcl: fixed double-click selection behavior where
+ there were embedded windows/widgets in the same line. [Bug: 3989]
+
+ * win/tkWinWm.c (TkWmProtocolEventProc): cached atom name as the
+ window could get destroyed during eval [Bug: 2513]
+
+ * generic/tkCanvLine.c (LineCoords): fixed segfault when too few
+ coords were passed to a line with certain options set (it should
+ always have thrown an error anyway). [Bug: 4042]
+
+ * tests/text.test:
+ * generic/tkText.c: fixed missing " in error case and missing
+ 'dump' in subcommand listing [Bug: 4036]
+
+ * generic/tkListbox.c: adjusted use of basic string concatenation
+ in (non-K&R behavior) [Bug: 4027]
+ Swapped bg/fg class for -select(bg|fg) for listbox and their
+ items [Bug: 4039]
+
+ * unix/mkLinks:
+ * doc/WindowId.3: added docs for Tk_IsContainer and Tk_IsEmbedded
+
+ * doc/text.n: clarified mark gravity definition and usage of
+ ``word'' in binding definitions. [Bug: 2004 2277 1388]
+
+ * generic/tkInt.h: moved new TkDisplay useInputMethods structure
+ element to end to not disturb position of previous elements in
+ the structure (as compared to Tk <=8.2).
+
+2000-01-20 Eric Melski <ericm@scriptics.com>
+
+ * tests/grid.test: Added a test for the consecutive ^ and multiple
+ widget case (bug #1386).
+
+ * generic/tkGrid.c: Fixed interpretation of consecutive ^
+ characters in grid command. Previously, ^ ^ was interpreted as
+ meaning that there must be a 2-column widget above to extend,
+ neglecting the case where there was actually 2 1-column widgets
+ above. Now, ^ ^ is interpreted as a possible width; the gridder
+ will consume as many ^'s as there are columns in the widget, and
+ leave the rest for the extension of other widgets. (bug #1386).
+
+2000-01-19 Eric Melski <ericm@scriptics.com>
+
+ * library/tk.tcl: Created a virtual event <<PrevWindow>> for
+ reverse tab traversals, with one default binding <Shift-Tab>, and
+ OS specific bindings for Linux, HP-UX, and IRIX. (bug #3163)
+
+2000-01-13 Jeff Hobbs <hobbs@scriptics.com>
+
+ * changes: updated changes file to reflect 8.3b2 mods
+ * README:
+ * generic/tk.h:
+ * unix/configure.in:
+ * win/configure.in: updated to patchlevel 8.3b2
+
+ * win/tkWinWm.c: added visibility event handler to make sure
+ that transient window wrappers would be updated when the master
+ was initially mapped.
+
+2000-01-12 Jeff Hobbs <hobbs@scriptics.com>
+
+ * tests/text.test: changed test to reflect change of -hidden
+ to -elide in search options.
+
+ * win/tkWinScrlbr.c: added check for valid hwnd in ModalLoopProc
+ to avoid crash when building statically
+
+ * doc/event.n:
+ * generic/tkBind.c: prevented core with event -warp on Windows
+ when window wasn't mapped [Bug: 4004] and added docs stating
+ the requirement for mapped windows.
+
+ * generic/tkCanvas.c: fixed mem leak with TagSearchExprInit
+ [Bug: 3977]
+
+ * generic/tkStubInit.c:
+ * generic/tkDecls.h: remove non-existent
+ Tk_(Get|Create)CanvasVisitor prototypes
+
+ * generic/tkText.c:
+ * generic/tkEntry.c: fixed cursor to not blink when widget was
+ disabled [Bug: 1807]
+
+ * generic/tkRectOval.c: added note about change to bloat for
+ RectOval bounds calculation for WIN32 only
+
+ * library/dialog.tcl: improved handling of $default arg to allow
+ for name of given button, as well as bounds checking
+
+ * doc/wm.n:
+ * tests/winWm.test:
+ * tests/unixWm.test:
+ * mac/tkMacWm.c:
+ * unix/tkUnixWm.c: fixed possible X error being raised [Bug: 3377]
+ * win/tkWinWm.c: wm deiconify in zoom state [Bug: 2077],
+ fixed possible flashing of unmapped toplevel in deiconify [Bug: 3338]
+ and fixed mapping of transient window [Bug: 572]
+ Also, for all wm's, extended 'wm state' command to allow setting
+ of the state, and added official support of 'zoomed' state on Win.
+
+ * unix/aclocal.m4: strtod bug on Tru64 [Bug: 3378]
+
+ * unix/Makefile.in: added tests to prevent unnecessary chmod +x
+ in source dirs while installing [Bug: 3367]
+
+ * unix/configure.in: properly sub'ed in TK_SHARED_BUILD [Bug: 3385]
+
+2000-01-05 Jeff Hobbs <hobbs@scriptics.com>
+
+ * doc/text.n:
+ * generic/tkText.c:
+ * generic/tkText.h:
+ * generic/tkTextBTree.c:
+ * generic/tkTextDisp.c:
+ * generic/tkTextTag.c: removed the -state option for text tags,
+ and reoriented it around -elide, as -state disabled was never
+ implemented, and -state hidden is better as -elide.
+
+ * mac/tkMacClipboard.c: fixed i18n problems with clipboard [Bug: 3544]
+
+ * library/entry.tcl:
+ * library/focus.tcl:
+ * library/listbox.tcl:
+ * library/scale.tcl:
+ * library/scrlbar.tcl:
+ * library/tearoff.tcl:
+ * library/text.tcl:
+ * library/tkfbox.tcl:
+ * library/xmfbox.tcl: fixed unprotected arg parsing through eval/after
+ [Bug: 3943]
+
+ * unix/Makefile.in: added unix/aclocal.m4 to distribution [Bug: 3938]
+ * unix/aclocal.m4: changed NetBSD SHLIB_CFLAGS from -fpic to -fPIC
+
+ * win/tkWinImage.c: added static declaration to function
+
+1999-12-22 Jeff Hobbs <hobbs@scriptics.com>
+
+ * changes: updated changes file
+
+ * generic/tkScale.c:
+ * generic/tkScale.h:
+ * mac/tkMacScale.c:
+ * unix/tkUnixScale.c: fixed potential segv from patch in 3897
+
+ * tests/unixWm.test: nonPOrtable -> nonPortable
+
+1999-12-21 Jeff Hobbs <hobbs@scriptics.com>
+
+ * generic/tk.h:
+ * unix/configure.in:
+ * win/configure.in:
+ * win/aclocal.m4:
+ * README: updated for patch level 8.3b1
+
+ * unix/tkUnixWm.c: fixed panic in Tk_CoordsToWindow to print error
+ and continue instead (for Tix) [Bug: 716 et al]
+
+ * scale.test:
+ * generic/tkScale.c:
+ * generic/tkScale.h: fixed possible core when freeing options
+ (cursor) associated with scale widget [Bug: 3897]
+
+ * doc/MeasureChar.3: fixed docs for Tk_MeasureChars to reflect code
+ * doc/listbox.n: fixed formatting problem
+
+ * generic/tk3d.c: added extra calculations to ensure that thin
+ frames get refreshed too [Bug: 3596]
+
+ * unix/tkUnixMenu.c:
+ * unix/tkUnixFont.c:
+ * generic/tkCanvText.c:
+ * generic/tkEntry.c:
+ * generic/tkFont.c:
+ * generic/tkImgPPM.c: removed extranneous vars that were set but
+ never used.
+
+ * mac/tclMacHLEvents.c: fixed applescript for I18N [Bug: 3644]
+
+ * unix/aclocal.m4: removed -O flag for AIX when using the IBM
+ compiler (several versions have a bug that crops up in the text
+ widget). [Bug: 2316]
+
+ * unix/Makefile.in: removed extra slash in SCRIPT_INSTALL_DIR
+ [Bug: 3896]
+
+ * library/listbox.tcl: added extra checks for existence of
+ tkPriv(listboxSelection) before it was used. [Bug: 3892]
+
+1999-12-16 Jeff Hobbs <hobbs@scriptics.com>
+
+ * doc/GetCursor.3:
+ * win/tkWinCursor.c: added support for Windows cursors to
+ TkGetCursorByName (.ani, .cur) using -cursor @<filename>
+ (Ascher) [Bug: 1350]
+
+ * win/tkWinWm.c: fixed 'wm deiconify' to update position of the
+ toplevel if event is waiting before mapping. (Mao) [Bug: 3687]
+ This removes the need for 'update idle' before 'wm deiconify' on
+ Windows.
+
+ * doc/listbox.n: added doc for <<ListboxSelect>> [Bug: 3500]
+
+ * doc/getOpenFile.n: removed note that -initialfile didn't work
+ for tk_getOpenFile
+ * library/tkfbox.tcl: updated tk_get*File to better match the
+ Windows file box it emulates, give proper support to -initialfile,
+ and fixes lack of global tkPriv call. [Bug: 3735 3882]
+
+ * doc/tk.n: added doc for 'tk useinputmethods ...'
+ * tests/tk.test:
+ * unix/tkUnixKey.c:
+ * generic/tkCmds.c:
+ * generic/tkEvent.c:
+ * generic/tkWindow.c:
+ * generic/tkInt.h: add 'tk useinputmethods ?-display win? ?bool?'
+ call to provide support for disabling/enabling the use of XIM on
+ X. This was previously all done at compile time, and always on.
+ Now it is turned off by default, even when available, and the user
+ must turn it on to use XIM (per display).
+
+ * generic/tkCanvUtil.c: fixed bug in Tk_CanvasPsOutline that freed
+ mem it shouldn't.
+
+ * generic/tkFont.c: added "bitstream cyberbit" (popular Windows
+ CJK font) to list of font fallbacks. (kenny) [Bug: 2407]
+
+ * mac/tkMacMenu.c: finished bug 3075 by changing the char values of
+ what was checked (verified correctness on Mac).
+
+1999-12-13 Jeff Hobbs <hobbs@scriptics.com>
+
+ * doc/canvas.n: added docs for items added by dash patch (-*dash*,
+ -state, -active*, -disabled*, -offset, essentially rewrote the
+ man patch for completely updated 8.3 canvas widget.
+ * doc/entry.n: added docs for entry widget validation
+ * doc/event.n: added docs for -warp
+ * doc/text.n: doc'ed new -state value 'hidden'
+ * doc/GetDash.3: (new file) man page explaining Tk_GetDash
+ * generic/tkStubInit.c:
+ * generic/tkDecls.h:
+ * generic/tkIntXlibDecls.h:
+ * generic/tkInt.decls: added XSetDashes and XWarpPointer
+ * generic/tk.decls: added Tk_CreateSmoothMethod, and reserved
+ two spots
+ * generic/tk.h: added Tk_SmoothMethod struct,
+ state item to canvas record, #defines for item state,
+ support for using old char*-based canvas item C creation
+ procedures with -DUSE_OLD_CANVAS,
+ Tk_Dash, Tk_TSOffset (-offsets) & Tk_Outline structs and #defs,
+ decls for dash, outline and postscript routines
+ * generic/tkBind.c: added support for Quadruple clicks, and added
+ the -warp option to 'event' with pointer warping routines
+ * xlib/xgc.c:
+ * generic/tkRectOval.c:
+ * generic/tkCanvArc.c:
+ * generic/tkCanvBmap.c:
+ * generic/tkCanvImg.c:
+ * generic/tkCanvLine.c:
+ * generic/tkCanvPoly.c:
+ * generic/tkCanvPs.c:
+ * generic/tkCanvText.c:
+ * generic/tkCanvUtil.c:
+ * generic/tkCanvWind.c:
+ * generic/tkCanvas.c:
+ * generic/tkCanvas.h: Canvas and items received overhaul to with
+ the addition of the dash patch (Nijtmans, et al) This includes
+ objectification of the 'canvas' command, as well as support for
+ (where appropriate) dashes in items, extended stipple support,
+ state for all items, and postscript generation of images and
+ windows. See the new canvas man page for related docs.
+ * generic/tkEntry.c: added entry widget validation, see entry.n
+ * generic/tkEvent.c: on simulated events, ButtonPress should
+ be matched with ButtonRelease to be correct
+ * generic/tkFont.c: corrected possible null reference
+ * generic/tkFrame.c: made frame a Tcl_Obj based command
+ * generic/tkGet.c: added TkGetDoublePixels
+ * generic/tkImage.c: bug fixes from Img patch and new
+ Tk_PostscriptImage and Tk_SetTSOrigin functions
+ * generic/tkImgBmap.c: new ImgBmapPostscript function
+ * generic/tkImgPhoto.c: new Tk_CreatePhotoOption, Tk_DitherPhoto
+ * generic/tkInt.h: declarations for some new functions
+ * generic/tkMessage.c: reworked relief drawing
+ * generic/tkOldConfig.c: added TK_CONFIG_OBJS so old style
+ ConfigureWidget calls can pass in Tcl_Obj arrays
+ * generic/tkScrollbar.c:
+ * generic/tkScrollbar.h: made -orient use an option table
+ * generic/tkText.c:
+ * generic/tkText.h: made -wrap and -state use option tables
+ * generic/tkTextBTree.c:
+ * generic/tkTextDisp.c:
+ * generic/tkTextImage.c:
+ * generic/tkTextMark.c:
+ * generic/tkTextTag.c:
+ * generic/tkTextWind.c: added support for -elide and -state hidden
+ * generic/tkTrig.c: changed TkMakeBezierCurve to support returning
+ the upper limit of points needed for spline
+ * generic/tkUtil.c: new option table parsing routines
+ * generic/tkWindow.c: init'ing of warp stuff, mouseButtonState
+
+ related bug ids for the fixes:
+ [Bug: 648 1541 1540 1779 2168 2311 2297 2340 2348 2578 3386]
+
+ * tests/bind.test:
+ * tests/canvImg.test:
+ * tests/canvPsArc.tcl:
+ * tests/canvPsImg.tcl: (new file)
+ * tests/canvRect.test:
+ * tests/canvText.test:
+ * tests/canvas.test:
+ * tests/defs.tcl:
+ * tests/entry.test:
+ * tests/event.test:
+ * tests/font.test:
+ * tests/frame.test:
+ * tests/imgPhoto.test:
+ * tests/safe.test:
+ * tests/scale.test:
+ * tests/scrollbar.test:
+ * tests/select.test:
+ * tests/text.test:
+ * tests/textDisp.test:
+ * tests/textTag.test:
+ * tests/unixFont.test:
+ * tests/unixWm.test:
+ * tests/visual_bb.test:
+ * tests/winClipboard.test: tests for the dash patch changes
+
+ * unix/mkLinks: added GetDash.3 into the mkLink step
+
+ * mac/tkMacDraw.c: mac still needs pointer warping routine
+ * mac/tkMacXStubs.c:
+ * win/tkWinDraw.c:
+ * win/tkWinPointer.c: added support for pointer warping and
+ platform specific support for dash patch items
+
+1999-12-12 Jeff Hobbs <hobbs@scriptics.com>
+
+ * generic/tkText.c: fixed bug in TextSearchCmd for multibyte chars
+ (Darley) [Bug: 3839]
+
+ * unix/aclocal.m4: added warning when configuring with
+ --enable-threads that Tk may have problems
+
+1999-12-09 Jeff Hobbs <hobbs@scriptics.com>
+
+ * generic/tkImgGIF.c: updated casting
+
+ * win/makefile.vc: removed 16bit stuff, simplified makefile.
+
+1999-12-06 Scott Redman <redman@scriptics.com>
+
+ * generic/tkMain.c: need to include tclInt.h for new hook
+ functions that are internal-use-only.
+
+1999-12-06 Jeff Hobbs <hobbs@scriptics.com>
+
+ * library/comdlg.tcl: removed tclVerifyInteger and tclSortNoCase,
+ they weren't used, and were not actually correct
+
+ * mac/tkMacFont.c:
+ * mac/tkMacMenu.c:
+ * mac/tkMacWindowMgr.c: fixed greyed out menu items, handling of
+ ... elipsis, font mapping problem, and enabled generated menu
+ posting [Bug: 3705]
+
+1999-12-02 Jeff Hobbs <hobbs@scriptics.com>
+
+ * generic/tkInt.h:
+ * generic/tkWindow.c:
+ * generic/tkCmds.c: converted Tk_DestroyCmd, Tk_LowerCmd and
+ Tk_RaiseCmd to their ObjCmd equivalent.
+
+ * library/msgbox.tcl: added color icons for tk_messageBox on Unix
+ and Mac when tk_strictMotif isn't set. (Hipp)
+ * library/tk.tcl: added window bounds checking to ::tk::PlaceWindow
+
+ * tests/imgPPM.test: fixed test 2.2 to use -format ppm (since
+ we know have GIF write capability)
+
+1999-12-01 Scott Redman <redman@scriptics.com>
+
+ * generic/tkMain.c :
+ * unix/tkAppInit.c:
+ * win/winMain.c: Added added hooks into the main() code for
+ supporting TclPro and other "big" shells more easily without
+ requiring a copy of the main() code.
+
+1999-11-29 Jeff Hobbs <hobbs@scriptics.com>
+
+ * generic/tkImgGIF.c: added GIF writing that uses miGIF RLE
+ [Bug: 2039, new patch]
+
+ * library/entry.tcl: fixed up tkEntrySeeInsert (Nemthi)
+
+ * generic/tkListbox.c: fixed 'get' of listbox to return a string
+ when only one item is requested.
+
+ * tests/clrpick.test:
+ * tests/filebox.test: minor whitespace cleanup
+
+ * library/tk.tcl: fixed missing $w in ::tk::PlaceWindow
+
+1999-11-24 Jeff Hobbs <hobbs@scriptics.com>
+
+ * library/clrpick.tcl:
+ * library/msgbox.tcl:
+ * library/tk.tcl:
+ * library/tkfbox.tcl:
+ * library/xmfbox.tcl: fixed dialogs to center over -parent,
+ added utility functions ::tk::PlaceWindow, ::tk::SetFocusGrab,
+ ::tk::RestoreFocusGrab to tk.tcl to help
+
+1999-11-23 Eric Melski <ericm@scriptics.com>
+
+ * tests/listbox.test: Added a test to check that the topIndex is
+ update when items are removed from the listvar variable.
+
+ * generic/tkListbox.c: Added a check the updates the topIndex when
+ items are removed from the listvar variable.
+
+ * tests/listbox.test: Added a test to check that the vertical
+ scrollbar is updated when the listvar changes.
+
+ * generic/tkListbox.c (ListboxListVarProc): added a check that
+ sets the UPDATE_V_SCROLLBAR flag if the length of the listvar has
+ changed.
+
+1999-11-23 Jeff Hobbs <hobbs@scriptics.com>
+
+ * generic/tk.h:
+ * generic/tkConfig.c: added support for TK_OPTION_DONT_SET_DEFAULT
+ as equiv for TK_CONFIG_DONT_SET_DEFAULT
+ * generic/tkListbox.c: added TK_OPTION_DONT_SET_DEFAULT to the
+ item specs
+
+1999-11-19 Jeff Hobbs <hobbs@scriptics.com>
+
+ * generic/tkColor.c:
+ * generic/tkColor.h: fixed Tk_NameOfColor to work correctly,
+ with minor change to TkColor struct.
+
+ * generic/tkConsole.c: added static declaration to
+ ConsoleDeleteProc function (proto already had it)
+
+ * win/tkWinInt.h: removed TkFontAttributes typedef (was
+ redundant with tkFont.h).
+ * win/tkWinPort.h: put #ifndef __GNUC__ around redefinition
+ of str[n]casecmp, as cygwin uses the originals.
+ * win/tkWinX.c: changed GetCurrentTime to GetTickCount (the
+ former is deprecated). [Bug: 2053]
+
+1999-11-19 Eric Melski <ericm@scriptics.com>
+
+ * tests/listbox.test: Added tests for itemcget and itemconfigure.
+
+ * doc/listbox.n: Added documentation for -listvar option and for
+ itemconfigure and itemcget commands.
+
+ * generic/tkListbox.c: Added support for itemconfigure/itemcget
+ listbox subcommands (addresses rfe #936)
+
+1999-11-17 Eric Melski <ericm@scriptics.com>
+
+ * tests/listbox.test: Updated tests for new error messages.
+
+ * generic/tkListbox.c: Improved error messages for bad -listvar's.
+
+ * tests/listbox.test: Added tests for bad -listvar's.
+
+ * generic/tkListbox.c: Added handlers for bad -listvar's (ie, bad
+ lists)
+
+ * tests/listbox.test: Added tests for ListboxUpdateHScrollbar.
+
+ * generic/tkListbox.c: Changed some old static buffers to base
+ size on TCL_DOUBLLE_SPACE instead of (completely) hardcoding the size.
+
+ * tests/listbox.test: New tests for -listvar functionality, and an
+ odd extra case that wasn't covered before.
+
+ * generic/tkListbox.c: Tests exposed some bugs, now fixed.
+
+1999-11-16 Eric Melski <ericm@scriptics.com>
+
+ * tests/listbox.test: Fixed tests to comply with new objectified
+ error messages. No -listvar specific tests yet.
+
+ * win/tkWinDefault.h:
+ * unix/tkUnixDefault.h:
+ * mac/tkMacDefault.h: Added default value for -listvar option.
+
+ * generic/tkWindow.c: Changed "listbox" mapping from old-school to
+ new-school objectified command.
+
+ * generic/tkListbox.c: Objectified listbox; added support for
+ -listvar option. Converted internal structure to use a Tcl list
+ object to store the data.
+
+ * generic/tkInt.h: Changed reference to Tk_ListboxCmd to
+ Tk_ListboxObjCmd.
+
+1999-11-09 Jeff Hobbs <hobbs@scriptics.com>
+
+ * generic/tkGrid.c: changed Tcl_Alloc to ckalloc
+
+ * generic/tkEntry.c: fixed C expr error in destroy of entry
+ that could lead to 'malformed bucket chain' error
+
+ * win/winMain.c: corrected winMain to not do a DebugBreak when
+ returning an error message from the top level
+
+1999-10-30 Jeff Hobbs <hobbs@scriptics.com>
+
+ * win/tkWinKey.c: fixed XKeysymToKeycode to handle mapping of
+ symbolic keysyms (Left, Home, ...) with event generate
+
+ * library/entry.tcl: change tkEntrySeeInsert to avoid the use
+ of a while loop that could eat CPU tremendously. Behavior of
+ moving the cursor at the right edge changes slightly (previously
+ it tried to keep the cursor at the right edge, now it moves the
+ cursor to a "central right" location - better IMHO).
+
+1999-10-28 Jeff Hobbs <hobbs@scriptics.com>
+
+ * doc/CrtImgType.3:
+ * doc/CrtPhImgFmt.3:
+ * doc/FindPhoto.3:
+ * doc/photo.n:
+ * generic/tk.h:
+ * generic/tkCmds.c:
+ * generic/tkImage.c:
+ * generic/tkImgBmap.c:
+ * generic/tkImgGIF.c:
+ * generic/tkImgPPM.c:
+ * generic/tkImgPhoto.c:
+ * generic/tkInt.h:
+ * generic/tkTest.c:
+ * generic/tkWindow.c:
+ * tests/imgPhoto.test: added Img patch (Nijtmans) with docs,
+ headers #def'd with USE_OLD_IMAGE. Upgrades image stuff to
+ Tcl_Obj API, adds alpha channel (images are now 32 bpp)
+
+ * makefile.vc: changed 'c:/program files' to c:/progra~1
+
+1999-10-19 Jeff Hobbs <hobbs@scriptics.com>
+
+ * library/scrlbar.tcl: changed tkScrollButtonUp to check for
+ existence of tkPriv(relief) in order to avoid spurious release
+ events
+
+ * unix/Makefile.in: added ChangeLog to dist archive
+
+1999-09-24 Jeff Hobbs <hobbs@scriptics.com>
+
+ * */README:
+ * win/makefile.vc:
+ * */configure.in:
+ * generic/tk.h:
+ * library/tk.tcl: up'd to 8.3a1
+
+ * unix/Makefile.in: changed 'mkdir' to 'mkdir -p'
+
+ * library/dialog.tcl: changed {Times 18} to {Times 12} for
+ dialog font.
+
+1999-09-16 Jeff Hobbs <hobbs@scriptics.com>
+
+ * generic/tkFont.c: fixed processing of font options and error
+ returned [Bug: 2075]
+
+ * win/tkWinWm.c: fixed bug in 'wm deiconify' that raised the
+ wrong toplevel, and changed it to not set focus on overridden
+ toplevels
+
+1999-09-15 Jeff Hobbs <hobbs@scriptics.com>
+
+ * unix/aclocal.m4: added fix for FreeBSD-[1-2] recognition [Bug: 2070]
+ and fix to AIX-* to get ldAix right [Bug: 2624], fixed AIX
+ version check (readjust from 8-21 fix) and several other config
+ fixes for AIX
+ * mac/tkMacMenubutton.c:
+ * unix/tkUnixMenubu.c: fixed permanently stippled menubutton image
+ * win/tkWinButton.c: fixed possible pointer smash [Bug: 2733]
+
+1999-09-14 Jeff Hobbs <hobbs@scriptics.com>
+
+ * win/tkWinMenu.c: fix for stack overrun in GetTextFace [Bug: 909]
+
+1999-09-01 Jeff Hobbs <hobbs@scriptics.com>
+
+ * win/tkWinDraw.c:
+ * unix/tkUnixDraw.c: fixed header style for TkpDrawHighlightBorder
+ * generic/tkCanvas.c: fixed GC error (bg <> fg) in tkCanvas.c
+ (from code added to support TkpDrawHighlightBorder) [Bug: 2676]
+ * unix/aclocal.m4: added -bnoentry to the AIX-* flags
+ * library/msgbox.tcl: changed the behavior of tk_messageBox on
+ Unix to be more Windows like in handling of <Return> and the
+ default button
+ * library/button.tcl:
+ * library/clrpick.tcl:
+ * library/comdlg.tcl:
+ * library/console.tcl:
+ * library/dialog.tcl:
+ * library/entry.tcl:
+ * library/focus.tcl:
+ * library/listbox.tcl:
+ * library/menu.tcl:
+ * library/msgbox.tcl:
+ * library/palette.tcl:
+ * library/safetk.tcl:
+ * library/scale.tcl:
+ * library/scrlbar.tcl:
+ * library/tearoff.tcl:
+ * library/text.tcl:
+ * library/tk.tcl:
+ * library/tkfbox.tcl:
+ * library/xmfbox.tcl: updated commands to use [string] ops
+ instead of expr equality operators
+
+1999-08-21 Jeff Hobbs <hobbs@scriptics.com>
+
+ * unix/aclocal.m4: Changed AIX-4.[2-9] check to AIX-4.[1-9]
+ [Bug: 1909]
+
+1999-08-20 Jeff Hobbs <hobbs@scriptics.com>
+
+ * generic/tkCursor.c: fixed bug in GetCursorFromObj that caused
+ panic [Bug: 2562]
+
+ * TK 8.2.0 RELEASED
+
+1999-08-13 Jim Ingham <jingham@cygnus.com>
+
+ * mac/tkMacMenu.c: Tk_DrawChars ends up setting the menu background
+ wrong. There is no clean way to stop it, so I use lower level routines
+ here to draw the text.
+ * mac/tkMacProjects.sea.hqx: Rearrange the projects so that the build
+ directory is separate from the sources. Much more convenient!
+
+1999-08-10 Jeff Hobbs <hobbs@scriptics.com>
+
+ * win/tkWinWm.c: changed "wm deiconify" on Windows to raise and
+ force the focus on the deiconified window (behavioral change from
+ 8.1 to comply better with Windows style) [Bug: 1609]
+ * doc/wm.n: clarified behavior of "wm deiconify".
+ * generic/tkInt.decls: added TkSetFocusWin
+ * generic/tkFocus.c: changed static SetFocus to TkSetFocusWin
+
+ * library/clrpick.tcl:
+ * library/console.tcl:
+ * library/tk.tcl: fixed code where abbreviations where used
+ in calling widget methods (confuses iWidgets) [Bug: 2422]
+
+1999-08-09 Jeff Hobbs <hobbs@scriptics.com>
+
+ * library/button.tcl: cleaned up programming (config -> configure)
+ and fixed Windows relief bug [Bug: 664]
+ * library/entry.tcl: changed Entry C/C/P to not use global data
+ (now uses tkPriv(data)) [Bug: 1475]
+ * library/listbox.tcl: fixed extended mode script error [Bug: 866]
+ * doc/options.n: clarified that -troughcolor doesn't work on Windows
+ * doc/wm.n: fixed wm positionfrom docs [Bug: 2284]
+
+1999-08-01 Jeff Hobbs <hobbs@scriptics.com>
+
+ * mac/tkMacPort.h: wrapped panic in #ifndef panic to avoid
+ compiler errors when used with stubs-#defines, from Vince Darley.
+ [Bug: 2389]
+
+1999-07-31 Scott Redman <redman@scriptics.com>
+
+ * xlib/X11/Xlib.h: Remove XFillRectangle since it is now in the
+ stub tables.
+
+1999-07-30 Jeff Hobbs <hobbs@scriptics.com>
+
+ * generic/tkInt.decls: Added stub entry for XFillRectangle [Bug: 2446]
+
+1999-07-30 Scott Redman <redman@scriptics.com>
+
+ * win/makefile.vc: Corrected building threaded tktest.exe on
+ Windows. Needed to link in .obj files from Tcl, needs to change
+ later so that code is in Tk and doesn't require a Tcl build.
+ Also added runtest target.
+
+1999-07-29 Scott Redman <redman@scriptics.com>
+
+ * generic/tkConsole.c: Allow tcl to open CON and NUL, even for std
+ channels. Checking for bad/unusable std channels was moved to Tk
+ since its only purpose was to check whether to use the Tk Console
+ Window for the std channels. [Bug: 2393 2392 2209 2458]
+
+ * win/Makefile.in: Corrected building threaded tktest.exe on
+ Windows. Needed to link in .obj files from Tcl, needs to change
+ later so that code is in Tk and doesn't require a Tcl build.
+
+1999-07-22 Scott Redman <redman@scriptics.com>
+
+ * Changed version to 8.2b2
+
+ * win/tkWinPort.h: Block out include of sys/stat.h in order to
+ build extensions with MetroWerks compiler for Win32. [Bug: 2385]
+
+ * unix/Makefile.in: Need to make install-sh executable before
+ calling (with chmod +x). [Bug: 2413]
+
+ * library/menu.tcl: Applied patch from Jeff Hobbs to fix typo.
+ [Bug: 2425]
+
+1999-07-21 Scott Redman <redman@scriptics.com>
+
+ * unix/Makefile.in: Add Windows configure script to distribution.
+
+1999-07-16 Scott Redman <redman@scriptics.com>
+
+ * unix/Makefile.in:
+ * win/Makefile.in: Copy the prolog.ps from the generic directory
+ for install-libraries.
+
+ * unix/aclocal.m4: Check for Alpha/Linux to set the IEEE flag to
+ the compiler to be -mieee. Patch from Don Porter.
+
+1999-07-08 Scott Stanton <stanton@scriptics.com>
+
+ * tests/unixSelect.test: Fixed broken test.
+
+ * win/makefile.vc: Added special case target to ensure that
+ tkStubLib.obj is built with -DSTATIC_BUILD.
+
+ * win/tkWinX.c (TkWinChildProc): Changed to pass
+ WM_WINDOWPOSCHANGED through to DefWindowProc to make OpenGL
+ sub-windows happy. This allows Windows to generate the WM_SIZE
+ and WM_MOVE messages.
+
+1999-07-08 Scott Redman <redman@scriptics.com>
+
+ * unix/configure.in: Fix Tk stub lib file names and flags.
+
+1999-06-30 Scott Redman <redman@scriptics.com>
+
+ * generic/tkGrid.c: removed deprecated functions (applied patch
+ from Jan Nijtmans). [Bug: 2080]
+
+ * generic/tkImgGIF.c:
+ * generic/tkImgPPM.c:
+ * generic/tkImgPhoto.c: Applied patch to allow Img extension to
+ work with 8.2, from Jan Nijtmans. [Bug: 2068]
+
+ * win/tkWinWm.c: Applied patch from Don Porter to prevent the
+ windows code from calling the Tcl functions when the stub table
+ has not been initialized in TkWinWmCleanup. [Bug: 2269]
+
+1999-06-16 Michael Thomas <wart@scriptics.com>
+
+ * unix/configure.in:
+ * unix/Makefile.in:
+ * unix/aclocal.m4: Numerous build changes to make Tk conform to
+ the proposed TEA spec
+
+ * tkConsole.c: changed some variable types from (int) to (size_t)
+ to prevent compiler warnings. Cast return value from strlen()
+ to (int) in one place for the same reason.
+
+1999-06-03 Scott Stanton <stanton@scriptics.com>
+
+ * unix/tkUnixSelect.c:
+ * tests/unixSelect.test:
+ * generic/tkSelect.c: Fixed selection code to handle Unicode data
+ in COMPOUND_TEXT and STRING selections. [Bug: 1791]
+
+1999-06-02 Scott Stanton <stanton@scriptics.com>
+
+ * generic/tkIntXlibDecls.h:
+ * xlib/X11/Xlib.h: Added Mac specific defines to help with
+ compilation.
+
+ * generic/tkFont.c: lint
+
+1999-06-01 Scott Stanton <stanton@scriptics.com>
+
+ * unix/tkUnixSelect.c: Improved I18N selection support.
+ COMPOUND_TEXT is converted to/from iso2022, and STRING is
+ converted to/from iso8859-1. There are still a few loose ends to
+ tie up before this is completely done.
+
+ * unix/tkUnixFont.c: Eliminated redundant case folding code.
+
+ * generic/tkFont.c: Eliminated use of isupper/tolower in favor of
+ Unicode variants.
+
+1999-05-24 Scott Stanton <stanton@scriptics.com>
+
+ * generic/tkStubLib.c:
+ * generic/tkStubInit.c:
+ * generic/tkIntXlibDecls.h:
+ * generic/tkIntPlatDecls.h:
+ * generic/tkIntDecls.h:
+ * generic/tkInt.decls:
+ * generic/tkConsole.c: Various changes to try to get the Mac
+ builds working.
+
+1999-05-21 Scott Stanton <stanton@scriptics.com>
+
+ * win/tkWinClipboard.c: Fixed clipboard code to handle lack of
+ CF_LOCALE information (e.g. from command.com).
+
+1999-05-20 Scott Redman <redman@scriptics.com>
+
+ * library/console.tcl: Changed copyright string to read 1999
+ Scriptics Corp. in wish console about box.
+
+1999-05-19 Scott Redman <redman@scriptics.com>
+
+ * generic/tk.h: Add extern "C" block around entire header file for
+ C++ compilers to fix linkage issues. Submitted by Don Porter and
+ Paul Duffin.
+
+1999-05-18 Scott Stanton <stanton@scriptics.com>
+
+ * tests/winClipboard.test:
+ * win/tkWinClipboard.c: Fixed clipboard code so it handles Unicode
+ data properly on Windows NT and 95. [Bug: 1791]
+
+1999-05-07 Scott Stanton <stanton@scriptics.com>
+
+ * library/menu.tcl: Fixed bug where tk_popup fails when called too
+ quickly. [Bug: 2009]
+
+1999-04-30 Scott Stanton <stanton@scriptics.com>
+
+ * Changed version number to 8.1.1.
+
+1999-04-30 Scott Stanton <stanton@scriptics.com>
+
+ * Merged changes from 8.1.0 branch:
+
+ * generic/tkDecls.h:
+ * generic/tkIntDecls.h:
+ * generic/tkIntPlatDecls.h:
+ * generic/tkIntXlibDecls.h:
+ * generic/tkPlatDecls.h:
+ * generic/tkStubInit.c: Changed to avoid the need for forward
+ declarations in stub initializers. Added extern "C" blocks around
+ stub table pointer declarations so the stubs can be used from C++
+ code. [Bug: 1934]
+
+ * generic/tkInt.decls: Added TkClipBox, XDrawSegments, and
+ XForceScreenSaver to stubs.
+
+ * generic/tkStubLib.c: Reordered declarations to avoid
+ circularities and forward references.
+
+ * generic/tkStubInit.c: Added includes for Mac.
+
+ * generic/tkMenubutton.c: lint
+
+ * generic/tkEntry.c: Fixed bad option table entry.
+
+ * generic/tkImgBmap.c:
+ * generic/tkImgPPM.c:
+ * generic/tkImgPhoto.c: Set the -translation and -encoding options
+ to binary for image files. (reported by Marco Gazzetta)
+
+1999-04-23 Scott Stanton <stanton@scriptics.com>
+
+ * generic/tkInt.decls: Added TkClipBox, XDrawSegments, and
+ XForceScreenSaver to stubs.
+
+ * generic/tkStubLib.c: Reordered declarations to avoid
+ circularities and forward references.
+
+ * generic/tkStubInit.c: Added includes for Mac.
+
+ * generic/tkMenubutton.c: lint
+
+ * generic/tkEntry.c: Fixed bad option table entry.
+
+1999-04-22 Scott Redman <redman@scriptics.com>
+
+ * generic/tkImgBmap.c:
+ * generic/tkImgPPM.c:
+ * generic/tkImgPhoto.c: Set the -translation and -encoding options
+ to binary for image files. (reported by Marco Gazzetta)
+
+1999-04-20 Scott Redman <redman@scriptics.com>
+
+ * xlib/X11/Xlib.h: changed definition of Status type to use a
+ typedef instead of a #define to avoid conflicting with the cygwin
+ win32 headers [Bug 1804]
+
+1999-04-15 Scott Stanton <stanton@scriptics.com>
+
+ * Merged 8.1 branch into the main trunk
+
+1999-04-09 Scott Redman <redman@scriptics.com>
+
+ * generic/tkWindow.c: Fixed deadlock situation when the Initialize()
+ function returns without releasing the mutex. Found while testing
+ Bug 1700, during safe.test (tk).
+
+1999-04-06 Scott Stanton <stanton@scriptics.com>
+
+ * generic/tkMain.c (Tk_MainEx): Changed to reset result before
+ calling Tcl_EvalFile. The ensures that error messages will be
+ generated cleanly.
+
+ * tests/winfo.test: Enabled tests that previously failed.
+
+1999-04-05 Scott Stanton <stanton@scriptics.com>
+
+ * library/bgerror.tcl:
+ * library/button.tcl:
+ * library/clrpick.tcl:
+ * library/console.tcl:
+ * library/dialog.tcl:
+ * library/entry.tcl:
+ * library/focus.tcl:
+ * library/listbox.tcl:
+ * library/menu.tcl:
+ * library/msgbox.tcl:
+ * library/palette.tcl:
+ * library/scale.tcl:
+ * library/scrlbar.tcl:
+ * library/tearoff.tcl:
+ * library/text.tcl:
+ * library/tk.tcl: Lots of minor performance improvements
+ contributed by Jeffrey Hobbs. [Bug: 1118]
+
+ * win/tkWinWm.c (Tk_WmCmd): Fixed bad code in tracing
+ suboption. [Bug: 1519]
+
+ * library/tkfbox.tcl: Change to restore button text after an
+ action to avoid the sticky "Open" button in a save dialog.
+ [Bug: 1640]
+
+ * library/entry.tcl: Fixed so selection is returned using the
+ -show character during cut and paste operations. [Bug: 1687]
+
+1999-04-5 Scott Redman <redman@scriptics.com>
+
+ * generic/tkInt.decls:
+ * generic/tkIntXlibDecls.h:
+ * generic/tkStubInit.c:
+ * xlib/xgc.c:
+ * xlib/X11/Xlib.h:
+ * xlib/X11/Xutil.h: Added more X functions to the Win & Mac stubs
+ tables.
+
+1999-04-05 Scott Stanton <stanton@scriptics.com>
+
+ * unix/configure.in:
+ * generic/tkCanvPs.c: Added configure test for pw_gecos field in
+ pwd to support OS/390. [Bug: 1724]
+
+1999-04-02 Scott Stanton <stanton@scriptics.com>
+
+ * tests/text.test:
+ * generic/tkText.c: Fixed handling of Unicode in text searches.
+ The -count option was returning byte counts instead of character
+ counts. [Bug: 1056, 1148, 1666]
+
+1999-04-01 Scott Redman <redman@scriptics.com>
+
+ * generic/tk.decls:
+ * generic/tk.h:
+ * generic/tkStubInit.c:
+ * generic/tkWindow.c:
+ * unix/Makefile.in:
+ * win/makefile.vc: Tk now uses its own stub library to store
+ pointers to its own stubs table.
+
+ * doc/dde.n: (removed)
+ * doc/send.n:
+ * generic/tk.decls:
+ * tests/winSend.test:
+ * generic/tkPlatDecls.h:
+ * win/tkWinSend.c: Removed the DDE-based send and dde commands,
+ they were causing Tk to lock up when any window on the system was
+ not processing its message queue (more importantly, windows in Tcl
+ and Tk). The send command needs to be rewritten to prevent the
+ deadlock situation (soon). The dde command is being pushed into
+ its own package and will provide almost all of the capabilities
+ that send did before (using a "dde eval" command), not yet
+ completed.
+
+1999-03-31 Scott Redman <redman@scriptics.com>
+
+ * win/tkWinSend.c: Modified dde/send code to work properly on
+ Win95/Win98. String lengths are not returned properly by DDE, so
+ NULL terminate all strings going in and ignore the string length
+ coming back out. Do not destroy handles until all necessary work
+ on those handles (and child handles) is done.
+
+1999-03-30 Scott Stanton <stanton@scriptics.com>
+
+ * generic/tkWindow.c (Tk_DestroyWindow): Image handlers are now
+ finalized before the font subsystem since complex image handlers
+ may contain references to fonts (e.g. Tix compound images).
+ [Bug: 1603]
+
+1999-03-29 Scott Stanton <stanton@scriptics.com>
+
+ * doc/MeasureChar.3:
+ * doc/TextLayout.3:
+ * generic/tk.decls:
+ * generic/tkCanvText.c:
+ * generic/tkEntry.c:
+ * generic/tkFont.c:
+ * generic/tkListbox.c:
+ * generic/tkMessage.c:
+ * mac/tkMacFont.c:
+ * unix/tkUnixButton.c:
+ * unix/tkUnixFont.c:
+ * unix/tkUnixMenu.c:
+ * win/tkWinFont.c:
+ * win/tkWinMenu.c: Standardized text layout and font interfaces
+ so they are consistent with respect to byte versus character
+ oriented indices. The layout functions all manipulate character
+ oriented values while the lower level measurement functions all
+ operate on byte oriented values. This distinction was not clear
+ and so the functions were being used improperly in a number of
+ places. [Bug: 1053, 747, 749, 1646]
+
+ * generic/tk.decls: Eliminated uses of C++ STL types string and
+ list from declarations.
+
+ * generic/tkFont.c: Changes to named fonts were not being
+ propagated in some cases. [Bug: 1144]
+
+ * xlib/X11/Xlib.h:
+ * generic/tkInt.decls: Added XParseColor to xlib stub
+ tables. [Bug: 1574]
+
+ * doc/GetBitmap.3:
+ * generic/tkBitmap.c (BitmapInit): Eliminated use of Tk_Uid's in
+ bitmaps. Added a few CONST declarations.
+
+1999-03-29 Scott Redman <redman@scriptics.com>
+
+ * unix/configure.in:
+ * unix/Makefile.in:
+ * win/makefile.vc:
+ * generic/tkDecls.h:
+ * generic/tkIntDecls.h:
+ * generic/tkIntPlatDecls.h:
+ * generic/tkPlatDecls.h:
+ * generic/tkIntXlibDecls.h: Removed stub functions. Always use the
+ Tcl stubs when building with --enable-shared.
+
+1999-03-26 Scott Redman <redman@scriptics.com>
+
+ * generic/tkTextIndex.c:
+ * tests/testIndex.test: Avoid looking past the beginning of the
+ array storing data for the text widget (.t index end-2c). Added
+ test case to check for the bug. [Bug 991]
+
+ * generic/tkConsole.c: Copy static strings into a Tcl_DString
+ before passing to Tcl_Eval, in case the compiler puts static
+ strings into read-only memory.
+
+1999-03-26 Suresh Ankolekar <suresh@scriptics.com>
+
+ * unix/configure.in:
+ --nameble-shared is now the default and builds Tk as a shared
+ library; specify --disable-shared to build a static Tk library
+ and shell.
+
+1999-03-26 Bryan Surles <surles@scriptics.com>
+
+ * library/menu.tcl: Fixed bug reported by Bryan Oakley in the
+ menubutton bindings. There was a false assumption that there was
+ always a menu attached to the button. [Bug 1116]
+
+1999-03-26 Scott Redman <redman@scriptics.com>
+
+ * unix/configure.in: Removed --enable-tcl-stub. Linking Tk to Tcl
+ stubs is causing too many problems when linking executables like wish.
+ Until the Tk is a fully loadable extension, linking against the Tcl
+ stubs is not supported in Tk.
+
+1999-03-19 Scott Redman <redman@scriptics.com>
+
+ * generic/tkBitmap.c:
+ * generic/tkCursor.c:
+ * generic/tkGC.c: When creating hash tables that key off of XID
+ handles, make sure to pass TCL_ONE_WORD_KEYS. XIDs are guaranteed
+ to be 32bit numbers, although on some 64bit systems (including 64bit
+ Solaris 7) they are packed into a 64bit value where the upper 32bits
+ are zero. The normal method of sizeof(XID)/sizeof(int) causes the
+ hash table code to assume that the XID is a pointer to an array of
+ two ints, which it is not. Tk now supports 64bit Solaris 7.
+
+1999-03-17 Scott Stanton <stanton@scriptics.com>
+
+ * win/makefile.vc:
+ * generic/tk.h: Changed to use TCL_BETA_RELEASE macro, and fixed
+ so this works in rc files.
+
+ * win/makefile.vc:
+ * win/makefile.bc:
+ * win/README:
+ * unix/configure.in:
+ * generic/tk.h:
+ * README: Updated version to 8.1b3.
+
+1999-03-14 Scott Stanton <stanton@GASPODE>
+
+ * unix/configure.in: Added missing stub related definitions.
+
+ * unix/Makefile.in: Install tkDecls.h in addition to tk.h.
+
+ * generic/tkStubLib.c: Added flags to ensure we are using Tcl
+ stub macros.
+
+1999-03-11 Scott Stanton <stanton@GASPODE>
+
+ * generic/tkInt.decls: Added reserved slot for XSetDashes for use
+ by the dash patch.
+
+1999-03-10 Scott Redman <redman@scriptics.com>
+
+ * xlib/xdraw.c:
+ * xlib/X11/Xlib.h:
+ * mac/tkMac.h:
+ * mac/tkMacInt.h:
+ * mac/tkMacPort.h:
+ * mac/tkMacXStubs.c:
+ * mac/tkMacAppInit.c:
+ * mac/tkMacCursor.c:
+ * win/makefile.vc:
+ * win/tkWin.h:
+ * win/tkWinInt.h:
+ * win/tkWinPort.h:
+ * win/winMain.c:
+ * generic/tk.h:
+ * generic/tkInt.h:
+ * generic/tk.decls:
+ * generic/tkInt.decls:
+ * generic/tkDecls.h:
+ * generic/tkPlatDecls.h:
+ * generic/tkIntDecls.h:
+ * generic/tkIntPlatDecls.h:
+ * generic/tkIntXlibDecls.h:
+ * generic/tkStubs.c:
+ * generic/tkPlatStubs.c:
+ * generic/tkIntStubs.c:
+ * generic/tkIntPlatStubs.c:
+ * generic/tkIntXlibStubs.c:
+ * generic/tkStubInit.c:
+ * generic/tkStubLib.c:
+ * generic/tkBind.c:
+ * generic/tkCmds.c:
+ * generic/tkConfig.c:
+ * generic/tkConsole.c:
+ * generic/tkCursor.c:
+ * generic/tkGrab.c:
+ * generic/tkImgPhoto.c:
+ * generic/tkMain.c:
+ * generic/tkMenu.c:
+ * generic/tkPointer.c:
+ * generic/tkTextDisp.c:
+ * generic/tkWindow.c:
+ * unix/tkUnixInt.h:
+ * unix/tkUnixPort.h:
+ * unix/Makefile.in:
+ * unix/configure.in:
+ * unix/tkConfig.sh.in:
+ * unix/tkUnix.c:
+ * unix/tkUnix3d.c:
+ * unix/tkUnixDraw.c:
+ * unix/tkUnixFont.c:
+ * unix/tkUnixMenubu.c: Stubs implementation for 8.1. Tk_Main() is
+ replaced with a macro which calls Tk_MainEx(). Tk can link to the Tcl
+ stubs library, wish links directly to Tcl and Tk. Use
+ --enable-tcl-stubs to link Tk to the Tcl stubs library (Unix), on
+ by default on Windows. Exported all public functions through the
+ stubs mechanism (see the *.decls files) and many of the internal
+ functions. Most of the changes dealt with shifting around the
+ function declarations in the header files. Mac code may not
+ compile, but it shouldn't take much work to fix this.
+
+ * mac/tkMacMenu.c: Added dummy TkpMenuThreadInit for Mac to be
+ consistent with Unix and Windows versions.
+
+1999-03-08 Lee Bernhard <lfb@scriptics.com>
+
+ * win/tkWinWm.c: Toplevel class no longer shared between
+ threads.
+
+ * win/tkWinX.c: Multiple threads no longer share the same
+ TkDisplay structure. Required because TkDisplay stores much
+ thread-specific data for a given thread.
+
+ * win/tkWinSend.c: Moved application instance handle out
+ out thread-local storage. DDE was failing to initialize
+ when the instance handles were different between threads.
+
+ * win/makefile.vc: Added THREADDEFINES for building with
+ threads enabled.
+
+ * generic/tkMenu.c:
+ * win/tkWinMenu.c:
+ * unix/tkUnixMenu.c: Added TkpMenuThreadInit for initializing
+ thread-specific Menu state.
+
+1999-03-01 Scott Redman <redman@scriptics.com>
+
+ * win/tkWinWm.c:
+ * win/tkWinPointer.c:
+ * win/tkWinInt.h: Fix "focus -force" for Windows. The Win32 API
+ function SetForegroundWindow() does not work unless the window
+ handle is a toplevel window (a Windows toplevel). The handle
+ being passed was a Tk toplevel, which is a child of the Windows
+ toplevel.
+
+1999-02-26 Scott Redman <redman@scriptics.com>
+
+ * win/cat.c: Remove this file, use the one in the Tcl source directory.
+
+ * win/makefile.vc: Remove the wishc.exe from the default targets. Add
+ a separate console-wish target to build it. The need for a
+ console-wish will go away soon, so we don't want to encourage its
+ use.
+
+1999-02-25 Scott Redman <redman@scriptics.com>
+
+ * win/tkWinWm.c: Properly initialize the tsdPtr->firstWindow field.
+
+ * win/cat.c: Code for cat32.exe, copied from the Tcl sources. Required
+ in order to run the test suite from the makefile
+
+ * win/winMain.c: Add main() for a console-based wishc.exe, which meant
+ adding code to disable the call to Tk_ConsoleInit().
+
+ * generic/tkConsole.c: Check the standard handles before creating the
+ new standard channels. This allows a windows app that has stdin,
+ stdout, or stderr to correctly connect to them.
+
+ * generic/tkMain.c: Add a proper check for the interactive mode, since
+ the standard channels may actually be connected in windows mode or
+ even in the console-based wish.
+
+ * win/makefile.vc: Add targets for wishc.exe (console-based wish) and
+ cat32.exe (for testing). Fix the test suite target so it can be run
+ from the makefile (which can happen since the standard handles have
+ been fixed).
+
+1999-02-12 Lee Bernhard <lfb@scriptics.com>
+
+ * generic/tkMenuButton.h:
+ * generic/tkMenuButton.c:
+ * mac/tkMacMenubutton.c:
+ * mac/tkMacDefault.h
+ * unix/tkUnixMenubu.c: Eliminated Tk_Uids used by -state option.
+ * unix/tkUnixDefault.h
+ * win/tkWinDefault.h
+
+ * generic/tk.h:
+ * generic/tkScale.h:
+ * generic/tkScale.c:
+ * generic/tkWindow.c:
+ * unix/tkUnixScale.c:
+ * unix/tkUnixDefault.h:
+ * unix/tkWinDefault.h:
+ * mac/tkMacDefault.h: Objectified scale widget.
+
+ * win/tkWinX.c: Removed Thread-specific data from process
+ initialization code that was stopping the Tk Dll from
+ loading.
+
+1999-02-11 Scott Stanton <stanton@GASPODE>
+
+ * README:
+ * generic/tk.h:
+ * unix/configure.in:
+ * win/README:
+ * win/makefile.bc:
+ * win/makefile.vc: Updated version to 8.1b2.
+
+ * unix/tkUnixSend.c: Fixed one more Tcl_*ObjVar instance.
+
+1999-02-04 Scott Stanton <stanton@GASPODE>
+
+ * Various cleanup related to the Tcl_Eval and Tcl_ObjSetVar
+ changes in Tcl.
+
+ INTEGRATED PATCHES FROM 8.0.5b2:
+
+ * win/tkWinMenu.c (TkpDestroyMenu): Changed so modalMenuPtr is
+ cleared when it is being destroyed.
+
+ * generic/tkImgPhoto.c: Changed so color tables are freed
+ immediately instead of being delayed. This ensures that color
+ tables are properly disposed at process exit.
+
+ * library/prolog.ps: Changed string that determines font height to
+ include European character with an umlaut.
+
+ * generic/tkImgBmap.c (ImgBmapConfigureInstance): If an image
+ mask changed but ended up with the same XID, the GC failed to be
+ updated and so the new mask was not used. [Bug: 970]
+
+ * generic/tkFocus.c (SetFocus): Changed so focus window is always
+ set if -force is specified. This fixes the problem on Windows
+ where Tk does not activate the window if it already has focus.
+
+ * generic/tkConsole.c: Fixed so errors in console eval are
+ reported properly. Eliminated duplicate result messages. [Bug: 973]
+
+ * win/tkWinWm.c: Changed so windows that aren't resizable don't
+ have resize handles and the zoom box is disabled.
+
+ * win/tkWinInt.h:
+ * win/tkWinPointer.c: Changed to cancel the mouse timer when a
+ user initiated move/resize loop begins.
+
+ * unix/configure.in: TK_LD_SEARCH_FLAGS was set incorrectly if
+ SHLIB_LD_LIBS='${LIBS}', and shared linking is performed through
+ the C compiler. Systems affected are Linux, MP-RAS and NEXTSTEP,
+ but also with gcc on many more systems. [Bug: 908]
+
+ * win/makefile.vc: First stab at install target. Fixed quoting so
+ paths with spaces work.
+
+ * tests/main.test:
+ * tests/unixWm.test: Better cleanup of temporary files.
+
+ * mac/tkMacAppInit.c:
+ * generic/tkTest.c:
+ * generic/tkAppInit.c:
+ * win/winMain.c: Changed some EXTERN declarations to extern
+ since they are not defining exported interfaces. This avoids
+ generating useless declspec() attributes and makes the windows
+ makefile simpler.
+
+ * library/menu.tcl (tkMenuFind): Changed so keyboard shortcuts
+ will only be found in the current toplevel. Previously, they
+ might be found in menus attached to other toplevels that might not
+ even be mapped. [Bug: 924]
+
+ * generic/tkCanvLine.c: Changed to treat zero width lines like
+ they have width 1 for purposes of selection. [Bug: 925]
+
+ * win/tkWinFont.c (Tk_MeasureChars): Added a workaround for a bug
+ in GetTextExtentExPoint on Win NT 4.0/Japanese. [Bug: 1006]
+
+ * unix/tkUnixSend.c (Tk_SetAppName): Fixed uninitialized memory
+ access bug. [Bug: 919]
+
+1999-1-28 Scott Stanton <stanton@GASPODE>
+
+ * generic/tkGrid.c: Fixed bug in "grid forget" that failed to cancel
+ pending idle handlers, resulting in a crash in a few odd cases.
+
+1999-01-06 Lee Bernhard <lfb@JUSTICE>
+
+ * generic/tk.h, generic/tkGet.c, generic/tkConfig.c,
+ * generic/tkOldConfig.c, generic/tkEntry.c, generic/tkMenubutton.c,
+ * generic/tkMenubutton.h, generic/tkScale.c, generic/tkScale.h,
+ * generic/tkTextDisplay.c, generic/tkText.c, unix/tkUnixMenubu.c,
+ * unix/tkUnixScale.c, mac/tkMacMenu.c, mac/tkMacMenubutton.c,
+
+ Removed global Tk_Uids dealing with "-state" configuration option
+ and added new TK_CONFIG_STATE configSpec that doesn't use
+ Tk_Uids.
+
+1998-12-11 === Tk 8.1b1 Release ===
+
+1998-12-11 Scott Stanton <stanton@GASPODE>
+
+ * generic/tkMain.c (Tk_Main): Fixed improper command line encoding
+ handling.
+
+1998-12-08 Scott Stanton <stanton@GASPODE>
+
+ * win/tkWinClipboard.c (TkSelGetSelection, TkWinClipboardRender):
+ Changed to handle multibyte characters properly. [Bug: 935]
+
+1998-12-07 Scott Stanton <stanton@GASPODE>
+
+ * library/xmfbox.tcl (tkMotifFDialog_Create): In the cached case,
+ the data array was not being initialized with the correct set of
+ widgets.
+
+1998-12-4 Brent Welch <welch@SAGE>
+
+ * Changed patchLevel to 8.1b1
+
+ * generic/tkMenu.c (ConfigureMenuCloneEntries): The -menu configuration
+ option was being incorrectly specified as just "menu".
+
+1998-11-30 Scott Stanton <stanton@GASPODE>
+
+ * generic/tkButton.c (ConfigureButton): The error result was
+ getting lost when restoring configuration options. [Bug: 619]
+
+1998-11-25 Scott Stanton <stanton@GASPODE>
+
+ * unix/tkUnixFont.c (GetFontAttributes): Initialize an unspecified
+ family to an empty string.
+ (FontMapLoadPage): if the font included characters below 32, the
+ index computation was incorrect because the range was shifted up
+ to 32.
+ (CreateClosestFont): check for empty locale as well as NULL.
+
+ * generic/tkFont.c (TkFontParseXLFD): initialize charset to
+ iso8859-1 if no charset is specified.
+
+ * mac/tkMacHLEvents.c (OdocHandler): added conversion from
+ external string to UTF [Bug: 869]
+
+ * integrated tk8.0.4 changes.
+
+ * generic/tkBind.c: fixed deletion order bug where a crash would
+ result if a binding deleted "."
+
+ * generic/tkMenu.c (MenuWidgetObjCmd): disabled menu entries were
+ getting reenabled whenever the mouse passed over the entry [Bug: 860]
+
+ * unix/tkUnixMenu.c (TkpComputeStandardMenuGeometry): hidemargin
+ option was not honored properly in menus [Bug: 859]
+
+1998-11-24 Scott Stanton <stanton@GASPODE>
+
+ * tkMacMenu.c, tkUnixMenu.c, tkWinMenu.c, tkMenuDraw.c, tkMenu.h,
+ * tkMenu.c: Backed out the previous fix for bug 620 and
+ eliminated a bunch of code that created unnecessary objects.
+ Changed back to using internal types instead of objects for many
+ configuration options. There are many more fixes like this that
+ could be made, but some require a little restructuring of the
+ code. In any case the leaks are fixed and there is a lot less
+ allocation happening. [Bug: 620]
+
+1998-11-19 Scott Stanton <stanton@GASPODE>
+
+ * tkMenu.c (DestroyMenuEntry): fixed memory leaks [Bug: 620]
+
+ * tkWinX.c (GetTranslatedKey): fixed bad code merge
+
+ * tkWinWm.c, tkWinMenu.c: fixed titles and menus so they properly
+ display Unicode [Bug: 819]
diff --git a/tk8.6/ChangeLog.2004 b/tk8.6/ChangeLog.2004
new file mode 100644
index 0000000..bf86629
--- /dev/null
+++ b/tk8.6/ChangeLog.2004
@@ -0,0 +1,3653 @@
+2004-12-29 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tcl.m4, win/configure: update MSVC CFLAGS_OPT to -O2, remove -Gs
+ (included in -O2) and -GD (outdated). Use "link -lib" instead of "lib"
+ binary and remove -YX for MSVC7 portability. Add -fomit-frame-pointer
+ for gcc OPT compiles. [Bug 1092952, 1091967]
+
+2004-12-21 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * library/demos/*.tcl: Add [package require Tk] to all the widget demo
+ scripts so they follow standard practice better. [FRQ 815118]
+
+2004-12-20 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkFileFilter.c:
+ * generic/tkFileFilter.h:
+ * macosx/tkMacOSXDialog.c:
+ * win/tkWinDialog.c:
+ * tests/filebox.test:
+ * tests/winDialog.test: Corrected handling of MacOS file types in
+ tk_*file dialogs [Bug 1083878].
+
+2004-12-20 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/panedwindow.n: Fix silly typo. [Bug 1087842]
+
+2004-12-19 Chengye Mao <chengye.geo@yahoo.com>
+
+ * win/tkWin.h, win/tkWinEmbed.h: Make embedding work better on Windows.
+ * win/tkWinWm.c, win/tkWinX.c: [Bugs 222677, 831627, 842945, 1024364]
+
+2004-12-17 Chengye Mao <chengye.geo@yahoo.com>
+
+ * generic/tkFrame.c: Make container windows display their
+ * generic/tkWindow.c: background when they don't have content.
+
+2004-12-10 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * unix/tk.spec, macosx/Tk-Info.plist, macosx/Wish-Info.plist:
+ * macosx/Wish.pbproj/project.pbxproj, README, win/configure.in:
+ * unix/configure.in, generic/tk.h: Bump version to 8.5a3.
+
+2004-12-09 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/tcl.m4: synced with tcl/unix/tcl.m4
+ * unix/configure: regen
+
+2004-12-09 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tkImgPhoto.c (Tk_PhotoPutBlock, Tk_PhotoPutZoomedBlock):
+ Added guards so that rescanning for the complex-alpha check is not done
+ in the common case of creating a simple image a bit at a time, or any
+ other time where the image was simple before and the input data has no
+ alpha channel. [Bug 1081966]
+
+2004-12-07 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/canvPs.test: Cleaned up the matching of [makeFile] and
+ * tests/choosedir.test: [removeFile] commands as indicated by the
+ * tests/filebox.test: results of a -debug 1 run of the test suite.
+ * tests/imgPPM.test: Tk test suite is now -debug 1 clean. This
+ * tests/imgPhoto.test: completes fixing [1078648].
+ * tests/listbox.test:
+ * tests/main.test:
+
+2004-12-07 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * tests/bind.test, tests/button.test, tests/canvas.test:
+ * tests/cursor.test, tests/scrollbar.test: Eliminate all duplicate test
+ names. [Bug 1078648 again]
+
+2004-12-06 Jeff Hobbs <jeffh@ActiveState.com>
+
+ *** 8.5a2 TAGGED FOR RELEASE ***
+
+2004-12-06 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/safe.test: Trim auto_path to improve performance [1080039]
+
+2004-12-05 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * changes: updated for 8.5a2 release
+
+2004-12-04 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * tests/*.test: Resolve duplicate test names. [Bug 1078648]
+
+2004-12-03 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tkImgPhoto.c (Tk_PhotoPutBlock, Tk_PhotoPutZoomedBlock): Make
+ overlay compositing where the target is empty no longer set the target
+ to magical gray, and also make sure that the complex-alpha flag is
+ toggled when necessary. [Patch 848161]
+
+2004-12-01 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/tkUnixButton.c (TkpDisplayButton): constrain coords to
+ Tk_RedrawImage to display only portion that is valid.
+ * generic/tkImgPhoto.c (ImgPhotoDisplay): add X error suppression
+ around XGetImage to prevent app abort. [Bug 979239]
+
+2004-11-28 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/tkUnixRFont.c(Tk_DrawChars): Check for short integer overflow in
+ x,y coordinates [Fixes: Bug 942320 "Tk, Xft, text and long lines"]
+
+2004-11-26 David Gravereaux <davygrvy@pobox.com>
+
+ * win/makefile.vc: Shell targets needed more stack space. [Bug 1066755]
+
+2004-11-20 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * tests/text.test: fix to test's platform sensitivities [Bug 1025871]
+ * tests/textDisp.test: made test less timing sensitive [Bug 1034171],
+ and fixed a platform-sensitive test [Bug 966845]
+
+2004-11-19 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Wish.pbproj/project.pbxproj: reverted earlier changes for
+ tclConfig.h changes to tcl, since those have been reverted for now.
+
+ Note that newly added macosx/Wish.xcode will not work without
+ tclConfig.h, this project has not been removed again.
+
+2004-11-18 Reinhard Max <max@suse.de>
+
+ * unix/tcl.m4 (SC_CONFIG_MANPAGES): Applied an improved version of
+ * unix/configure.in: [Patch 996085], that introduces
+ * unix/Makefile.in: --enable-man-suffix.
+
+ * unix/installManPage: added
+ * unix/mkLinks.tcl: removed
+ * unix/mkLinks: removed
+ * unix/configure: generated
+
+2004-11-17 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkCanvWind.c (ConfigureWinItem): unmap windows immediately
+ when state hidden is requested. [Bug 982248]
+
+ * generic/tkCanvImg.c (ImageToPostscript): don't try ps generation of
+ canvas image item without image specified. [Bug 1032300]
+
+ * library/console.tcl (::tk::console::ExpandVariable): correct array
+ keyname expansion. [Bug 1004508] (bold)
+
+ * generic/tkPanedWindow.c (Tk_PanedWindowObjCmd): set save_under X attr
+ to prevent expose events when moving sash. [Bug 1036963]
+
+2004-11-16 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * doc/text.n: clarified documentation on use of -tabs option.
+
+2004-11-16 Don Porter <dgp@users.sourceforge.net>
+
+ * library/msgs/it.msg: Updated Italian message catalog. Thanks to
+ Roberto Ugoccioni [Bug 1063675].
+
+2004-11-16 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Wish.pbproj/project.pbxproj:
+ * macosx/buildTkConfig.tcl: fixes for tclConfig.h changes.
+
+ * macosx/Wish.pbproj/project.pbxproj: fixed references to renamed
+ bitmap files.
+
+ * macosx/Wish.xcode/project.pbxproj (new):
+ * macosx/Wish.xcode/default.pbxuser (new):
+ * macosx/Wish-Info.plist (new):
+ * macosx/Tk-Info.plist (new): added new Xcode 1.5 project using native
+ targets, made possible by tclConfig.h changes.
+
+ * generic/tk.h: added version number change comments for new files.
+
+2004-11-15 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkText.c: fix to multi-line search problem and removed
+ * tests/text.test: 'knownBug' from one test.
+
+2004-11-15 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * unix/tcl.m4, unix/configure.in: Expanded all AC_DEFINE calls to the
+ three-argument form and ported recent changes to the tcl.m4 from the
+ Tcl distribution. *No* call to AC_CONFIG_HEADERS has been added; this
+ change should be virtually entirely cosmetic.
+
+2004-11-12 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXXStubs.c: implemented XGetGeometry().
+
+2004-11-12 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkCmds.c (Tk_TkObjCmd): use correct screen data when
+ -displayof arg is passed to [tk scaling]. [Bug 800178]
+
+2004-11-12 Daniel Steffen <das@users.sourceforge.net>
+
+ * doc/SetOptions.3:
+ * doc/text.n: fixed *roff errors uncovered by running 'make html'.
+
+ * macosx/tkMacOSXFont.c (Tk_MeasureChars,Tk_DrawChars,etc): Make sure
+ that the lastSubFontPtr remains valid even when the subfont array is
+ reallocated. [Bug 618872]
+
+2004-11-11 Reinhard Max <max@suse.de>
+
+ * generic/tkEvent.c (InvokeInputMethods): Call XSetICFocus whenever the
+ window receives focus. This fixes [Bug 905830] but avoids [Bug 1000051]
+
+2004-11-11 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tkMain.c:
+ * macosx/tkMacOSXAppInit.c (removed):
+ * macosx/Wish.pbproj/project.pbxproj:
+ * macosx/tkMacOSXInit.c:
+ * macosx/tkMacOSXInt.h: changes to make TkAqua dynamically loadable,
+ enabling [package require Tk] from tclsh. Startup code from
+ tkMacOSXAppInit.c moved into tkMacOSXInit.c, added code that notifies
+ the window server that an unbundled executable is a full GUI
+ application after loading Tk. [Patch 1035348]
+
+ * doc/wm.n: documented [wm attributes] on Mac OS X. [Bug 606665]
+ * macosx/tkMacOSXWm.c: implemented TIP 222 [wm attributes -alpha] on
+ Mac OS X. [Patch 892194]
+ WmIconbitmapCmd: adopted FSRef changes from [wm atttrs -titlepath].
+
+ * macosx/tkMacOSXSubwindows.c: synced spacing/formatting with
+ core-8-4-branch.
+
+ * generic/tkRectOval.c:
+ * macosx/README:
+ * macosx/tkMacOSXDefault.h:
+ * macosx/tkMacOSXDraw.c:
+ * macosx/tkMacOSXInit.c:
+ * macosx/tkMacOSXInt.h:
+ * macosx/tkMacOSXMenu.c:
+ * macosx/tkMacOSXWm.c: forward port from core-8-4-branch of Jim's and
+ my changes for CG drawing and [wm attributes] (corresponds to 8.4
+ changes dating from 09-18, 07-27, 07-24).
+
+ * macosx/tkMacOSXMouseEvent.c: endianness fixes.
+
+ * macosx/Wish.pbproj/project.pbxproj: corrected path to html help
+ inside framework.
+
+ * macosx/Makefile: prevent parallel make from building several targets
+ at the same time.
+
+2004-11-09 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * macosx/tkMacOSXButton.c: fix to dynamic reconfiguration of button
+ '-compound' options (cosmetic problem), [Bug 1055023]
+
+ * tests/text.test: added 'knownBug' 20.172.1 in text widget multiline
+ search routines.
+
+2004-11-08 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * library/demos/goldberg.tcl: Added slightly adapted version of Keith
+ Vetter's tkGoldberg as the final animation demo. Many many thanks to
+ Keith for giving his permission! [FRQ 627466]
+
+2004-11-07 Peter Spjuth <peter.spjuth@space.se>
+
+ * doc/frame.n: Added some info for -width/-height options. [Bug
+ 1055423]
+
+2004-11-07 Peter Spjuth <peter.spjuth@space.se>
+
+ * tests/grid.test:
+ * generic/tkGrid.c: Made handling of ^ a bit more consistent in corner
+ cases. This makes ^ work without any widgets in the same command. [Bug
+ 962589]
+
+2004-11-07 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * library/demos/pendulum.tcl: Added demonstrations of how to do
+ * library/demos/aniwave.tcl: animations using Tcl/Tk to the widget
+ * library/demos/anilabel.tcl: demo.
+
+2004-11-03 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/button.test: Update expected results to account for more
+ verbose errorinfo from errors in variable traces [Tcl Bug 572164]
+
+2004-11-01 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/dialog.test (dialog-1.1): Update expected result to changes in
+ the error messages produced by procs.
+
+2004-10-29 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * tests/wm.test: Add Win32 test cases for attributes subcommand.
+ * win/tkWinWm.c (WmAttributesCmd): Fixup broken option processing logic
+ for attributes subcommand.
+
+2004-10-28 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/tkWin32Dll.c (DllMain, _except_dllmain_detach_handler): Rework
+ pushing of exception handler function pointer so that compiling with
+ gcc -O3 works. Remove empty function call to avoid compiler warning.
+ Mark the DllMain function as noinline to avoid compiler error from
+ duplicated asm labels in generated code.
+
+2004-10-28 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * unix/tkUnixScale.c (DisplayHorizontalValue): Fix for [Bug 220927] by
+ Michael Schlenker to keep the labels within the window.
+
+2004-10-28 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/*.n: Assorted minor documentation fixes.
+
+2004-10-26 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tkWinX.c: Signature for tkWinXCleanup needed to be
+ * generic/tkInt.decls: changed so it matches the Tcl_ExitProc
+ * generic/tkIntPlatDecls.h: typedef to avoid a bad-style cast.
+
+ * win/makefile.vc: Force TCL_LIBRARY envar when calling tclsh
+
+2004-10-26 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tkWinRegion.c (TkpBuildRegionFromAlphaData): Fixed syntax error
+ * generic/tkImgPhoto.c (Tk_PhotoPutBlock): Removed unreferences vars.
+
+2004-10-26 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * macosx/tkMacOSXRegion.c (TkpBuildRegionFromAlphaData):
+ * win/tkWinRegion.c (TkpBuildRegionFromAlphaData): Factor out the
+ * unix/tkUnix.c (TkpBuildRegionFromAlphaData): building of region
+ * generic/tkImgPhoto.c (Tk_PhotoPutBlock): data to permit
+ better implementations on particular platforms. [Bug 919066]
+
+2004-10-24 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ TIP#177 AND TIP#179 IMPLEMENTATIONS
+
+ * doc/panedwindow.n: Docs for -hide and -stretch options.
+ * tests/panedwindow.test: Basic tests of -hide and -stretch options.
+ * generic/tkPanedWindow.c (Slave,slaveOptionSpecs,ComputeGeometry):
+ (DisplayPanedWindow,ArrangePanes,MoveSash,PanedWindowIdentifyCoords):
+ Add hide flag and stretch setting to list of options supported on a
+ panedwindow's slaves. [Patch 983886] Much thanks to Brian Griffin for
+ these options.
+
+2004-10-20 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinWm.c (UpdateWrapper): pass SWP_NOOWNERZORDER to SetWindowPos
+ when maintaining win Z order, to prevent parent from flashing (when
+ adjusting Z order).
+
+2004-10-19 Joe English <jenglish@users.sourceforge.net>
+
+ TIP#204 IMPLEMENTATION
+
+ * library/tk.tcl, library/entry.tcl, library/spinbox.tcl:
+ TIP #204 "Virtual Events for Keyboard Traversal" [Patch 976928]
+
+2004-10-19 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * tests/canvPsImg.tcl, tests/canvPsBmap.tcl:
+ * generic/tkBitmap.c, bitmaps/*.bmp:
+ * library/demos/icon.tcl, library/demos/items.tcl:
+ * library/demos/label.tcl, library/demos/menu.tcl:
+ * library/demos/ruler.tcl, library/demos/twind.tcl:
+ * library/demos/images/*.bmp: Renamed all X bitmap files files to have
+ an .xbm extension so Windows users won't get confused when wandering
+ around the Tcl source tree. [Bug 733835]
+
+2004-10-11 Miguel Bañon <bagnonm@users.sourceforge.net>
+
+ * library/msgs/sv.msg: Swedish message catalog from Mats Bengtsson.
+
+2004-10-09 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/wm.n: Recorded what attribute values are supported on OSX though
+ I don't know what they do.
+
+2004-10-08 Joe English <jenglish@users.sourceforge.net>
+
+ TIP#205 IMPLEMENTATION
+
+ * unix/tkUnixRFont.c: TIP #205 "Use pkgconfig Database to Register Xft
+ Support".
+
+2004-10-05 Jeff Hobbs <jeffh@ActiveState.com>
+
+ TIP#159 IMPLEMENTATION
+
+ * doc/wm.n (iconphoto): Added support for Tk photo images as
+ * generic/tkInt.h (TkDisplay): title-bar icons. TIP #159
+ * win/tkWinWm.c (WmIconphotoCmd): "wm iconphoto ?-default? image1 ..."
+ * macosx/tkMacOSXWm.c (WmIconphotoCmd): Implemented for Win/Unix,
+ * unix/tkUnixWm.c (WmIconphotoCmd): stubbed out for OS X.
+ * tests/wm.test, tests/unixWm.test, tests/winWm.test: [Bug 815751]
+
+2004-10-04 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkTextWind.c (EmbWinDelayedUnmap): Fix init warnings
+ * generic/tkTextTag.c (TkTextCreateTag):
+ * generic/tkTextMark.c (TkTextSetMark):
+ * generic/tkTextIndex.c (GetIndex):
+ * generic/tkUndo.c (EvaluateActionList):
+
+2004-09-24 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkCursor.c: Add missing initialization in debug routine.
+
+2004-09-24 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * library/text.tcl: corrected mousewheel scrolling [Bug 960190]
+
+ * tests/textDisp.test: made some tests more robust to slowness in
+ asynchronous height calculation callbacks [Bug 1025781]
+
+2004-09-24 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tkWinX.c: Added declaration for advapi32 now that this file uses
+ the Reg* functions (req'd for nmake build system).
+
+2004-09-23 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkTest.c
+ * tests/text.test: fix and tests for [Bug 1026485] - negative text
+ search ranges should not lead to any matches.
+
+2004-09-22 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinInt.h (TkWinDisplayChanged): added decl
+ * win/tkWinX.c (TkWinDisplayChanged, TkpOpenDisplay): Correctly handle
+ * win/tkWinWm.c (InvalidateSubTreeDepth, WmProc): color and screen
+ resolution changes. Tested for 16/24/32 bpp changes on XP. May need
+ more fixes for 8bpp switch, use of special colormaps, or other special
+ palette handling cases. [Bug 223689]
+
+2004-09-21 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tkInt.decls: Add decl for TkWinGetPlatformTheme. It is only
+ defined under Win32.
+ * generic/tkIntPlatDecls.h: Regen.
+ * generic/tkStubInit.c: Regen.
+ * win/tkWinInt.h: Define TK_THEME_WIN_CLASSIC and TK_THEME_WIN_XP.
+ * win/tkWinMenu.c (DrawMenuEntryAccelerator, DrawMenuEntryLabel): Draw
+ a disabled 3D text highlight for the accelerator only with the Win95/98
+ look. Same goes for the menu entry text.
+ * win/tkWinX.c (TkWinGetPlatformId, TkWinGetPlatformTheme):
+ Automatically detect the Windows theme in use and return either
+ TK_THEME_WIN_CLASSIC or TK_THEME_WIN_XP when the TkWinGetPlatformTheme
+ function is invoked. [Patch 866194]
+
+2004-09-21 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/tkWinWm.c: Rework WS_EX_LAYERED and LWA_ALPHA defines so that
+ compiling with mingw works again.
+
+2004-09-20 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinWm.c (UpdateWrapper, WmAttributesCmd): handle attribute
+ settings prior to window mapping and resort to more forceful wrapper
+ update again for -toolwindow (to remove it from taskbar).
+
+2004-09-19 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/*: Standardize style of references to manual sections and public
+ Tcl symbols along the lines of what I set out in [Tcl Patch 1022527].
+
+2004-09-18 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinWm.c (WmAttributesCmd): correct -alpha 0.0/1.0 setting and
+ round the value.
+ (UpdateWrapper): don't adjust Z order of TOPMOST window.
+ (WmAttributesCmd): don't call UpdateWrapper for -disabled or
+ -toolwindow attr changes.
+
+2004-09-17 Jeff Hobbs <jeffh@ActiveState.com>
+
+ TIP#222 IMPLEMENTATION
+
+ * doc/wm.n:
+ * tests/winWm.test: Add 'wm attributes -alpha' to control toplevel
+ * win/tkWinInt.h: alpha transparency on Win2K/XP+.
+ * win/tkWinWm.c: TIP #222 [Patch 892194]
+
+ * win/tkWinWm.c (UpdateWrapper): Ensure that we maintain Z order and
+ * tests/winWm.test: focus of preexisting window when
+ replacing the wrapper window.
+
+2004-09-16 David Gravereaux <davygrvy@pobox.com>
+
+ * win/makefile.vc : added VC7-safe environment check as used in the Tcl
+ makefile.vc [Bug 1029349]
+
+2004-09-16 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkMenu.c (MenuWorldChanged): ensure that we recompute the
+ menu geometry on WorldChanged to handle font size changes. [Bug 607649]
+
+2004-09-16 Peter Spjuth <peter.spjuth@space.se>
+
+ * tests/place.test:
+ * generic/tkPlace.c: Fixed a memory leak when a placed widget was
+ forgotten. [Bug 1028888]
+
+2004-09-14 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/tkWinWm.c (WmIconwindowCmd): Replace bogus call to
+ XWithdrawWindow with proper code. This avoids a "couldn't send withdraw
+ message to window manager" error when the iconwindow is already mapped.
+ The wm iconwindow command does not seem to do much under Win32, but at
+ least this avoids an error message.
+
+2004-09-13 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinWm.c (ReadIconFromFile): fix mem alloc to get the right size
+ for both icons ('?:' order of precedence mistake).
+
+2004-09-10 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * library/tkfbox.tcl (::tk::dialog::file::): Make sure that the state
+ is reset properly when starting to run the dialog. [Bug 845189]
+
+ * library/demos/filebox.tcl: Stop the use of tk_strictMotif from
+ poisoning the rest of the widget demo. [Bug 1013942]
+
+2004-09-10 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinWm.c (ActivateWindow): SetFocus to grab window when clicking
+ outside the grab window hierarchy. [Bug 220908]
+ (UpdateWrapper): update to 2004-06-12 Kovalenko to account for whether
+ the override window has a transient parent, and apply WS_POPUP in the
+ correct case. The makes splash screens pop up as well as making
+ dropdowns not grab focus away from the parent.
+
+2004-09-10 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ TIP#169 IMPLEMENTATION
+
+ * doc/text.n, generic/tkTest.c, generic/tkText.c, generic/tkText.h:
+ * generic/tkTextBTree.c, generic/tkTextDisp.c, generic/tkTextImage.c:
+ * generic/tkTextIndex.c, generic/tkTextMark.c, generic/tkTextTag.c:
+ * generic/tkTextWind.c, generic/tkUndo.c, generic/tkUndo.h:
+ * library/text.tcl, library/demos/twind.tcl, library/demos/widget:
+ * tests/text.test, tests/textImage.test, tests/textIndex.test:
+ * tests/textWind.test: implementation of TIP#169, which provides the
+ new '$text peer' widget subcommand. This includes new documentation,
+ tests, and an extension to the text widget demos to illustrate some of
+ the new features. Many thanks also to Brian Griffin for the initial
+ implementation.
+
+2004-09-09 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * tests/panedwindow.test: bulletproof 23.2 result [Bug 1019100]
+
+ * win/tkWinWm.c (ReadIconFromFile): when using SHGetFileInfo to
+ retrieve icon, get regular icon as well for correct Alt-Tab icon.
+
+2004-09-09 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/wish.1: Added note that the -use option is linked to the frame's
+ -container option to help with [Bug 1024364]
+
+2004-09-06 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/tkfbox.tcl (::tk::dialog::file::Create): use label instead of
+ button for "File of type", as it properly handles -state disabled now.
+
+2004-09-06 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/makefile.vc: Set TK_LIBRARY when execing Tk apps (test, runtest,
+ rundemo).
+
+2004-09-03 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * macosx/tkMacOSXMenus.c (GenerateEditEvent):
+ * macosx/tkMacOSXMenu.c (MenuSelectEvent):
+ * win/tkWinMenu.c (MenuSelectEvent): Make sure everywhere that needs to
+ NULL-out the user_data field does actually do so. (Code that uses
+ bzero() or memset() for the task just needs to be rebuilt to work).
+ [Bug 1021812]
+
+2004-09-01 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * tests/bind.test (bind-22.163): Fix inadvertent minor breakage from
+ TIP#165. [Bug 1019085]
+
+ * doc/toplevel.n, doc/loadTk.n: More spelling/abbreviation fixes from
+ Mikhail Kolesnitchenko.
+
+2004-08-29 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ TIP#165 IMPLEMENTATION
+
+ * generic/tk.h (XVirtualEvent): Added user_data field to structure.
+ * generic/tkBind.c (ExpandPercents, HandleEventGenerate):
+ * generic/tkEvent.c (Tk_HandleEvent): Handle putting data into the
+ user_data field, passing it to scripts as %d substitution, and
+ releasing the field's contents once the event has been processed.
+ * doc/bind.n, doc/event.n, tests/bind.test: Docs + tests.
+
+2004-08-26 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/text.tcl (::tk::TextTranspose): Ensure that Transpose is an
+ atomic op to undo.
+
+2004-08-25 Don Porter <dgp@users.sourceforge.net>
+
+ * macosx/tkMacOSXWm.c: Made use of Tcl_WrongNumArgs in a few
+ * win/tkWinMenu.c: appropriate spots.
+
+2004-08-22 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/SetOptions.3, doc/SetClassProcs.3, doc/MeasureChar.3:
+ * doc/GetVRoot.3, doc/GetHWND.3, doc/GetDash.3, doc/GetBitmap.3:
+ * doc/FontId.3, doc/CrtItemType.3, doc/ConfigWidg.3, doc/GetCursor.3:
+ More doc fixes from Mikhail Kolesnitchenko. [Patch 1013520]
+
+2004-08-20 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/TkInitStubs.3, doc/photo.n, doc/ParseArgv.3, doc/options.n:
+ * doc/keysyms.n, doc/font.n: More doc fixes. [Patch 1012837]
+
+ * doc/place.n, doc/pack.n, doc/grid.n, doc/getOpenFile.n:
+ * doc/event.n, doc/chooseDirectory.n, doc/bind.n:
+ Spelling and grammar fixes from Mikhail Kolesnitchenko. [Patch 1012083]
+
+ * tests/canvas.test (canvas-17.1): Report the result of the test so
+ that it can be compared. [Bug 1012331]
+
+2004-08-19 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinDialog.c (Tk_MessageBoxObjCmd): Inherit the icon from the
+ * win/tkWinInt.h: -parent window for the
+ * win/tkWinWm.c (TkWinGetIcon): MessageBox.
+
+2004-08-19 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/tkUnixWm.c: Cast argument 7 of XChangeProperty to 'const
+ unsigned char *' (from 'const char *') to satisfy Solaris 8 Forte C
+ compiler [Bug 1012325]
+
+2004-08-19 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/safe.test (safe-1.3): Made test less sensitve to the full set
+ of existing aliases in an interp, so the it only tests whether the
+ tested ones are present.
+
+ * unix/Makefile.in: Copied LD_LIBRARY_PATH machinery from `make shell`
+ target to other similar targets so that just built libraries are
+ tested, rather than previous installations.
+
+2004-08-19 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ TIP#168 IMPLEMENTATION
+
+ * generic/tkTrig.c (TkMakeRawCurve, TkMakeRawCurvePostscript):
+ * generic/tkInt.decls: New functions to handle the geometry for "raw"
+ bezier curves.
+ * generic/tkCanvUtil.c (tkRawSmoothMethod, InitSmoothMethods)
+ (TkSmoothParseProc): Add new type of smoothing method, simplify the
+ method initialization, and change the old smoothing method to be called
+ "true" and just keep "bezier" as an alias.
+ * tests/canvas.test (canvas-17.1): Basic test of built-in smoothing
+ method support.
+ * doc/canvas.n: Documentation updates.
+
+2004-08-18 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tkPanedWindow.c (optionSpecs): Add missing GEOMETRY flag to
+ -handlepad option. [Bug 1010938]
+
+2004-08-17 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/menu.n, doc/text.n: Assorted fixes, including spelling fixes from
+ Mikhail Kolesnitschenko. [Patch 1010083]
+
+ * doc/spinbox.n, doc/scrollbar.n, doc/scale.n, doc/panedwindow.n:
+ * doc/message.n, doc/listbox.n, doc/entry.n, doc/button.n:
+ More spelling fixes from Mikhail Kolesnitschenko. [Patch 1010607]
+
+2004-08-16 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/button.n, doc/checkbutton.n, doc/label.n, doc/menubutton.n:
+ * doc/radiobutton.n: Added cross-reference to new standard option.
+ * doc/options.n: Added standard documentation for the -compound
+ option. [Bug 712588]
+
+ * doc/canvas.n: Spelling and grammar fixes from Mikhail
+ Kolesnitschenko. [Bug 1009636]
+
+2004-08-11 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * library/tkfbox.tcl (ResolveFile): Added some environment variable
+ handling; this isn't perfect, but should do what most people want most
+ of the time. [FRQ 979101]
+ * library/xmfbox.tcl (MotifFDialog_BuildUI): Fix [Bug 987169] in the
+ Motif file dialogs as well.
+
+2004-08-10 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/tkUnixWm.c: Fix for [Bug 1006686] "wm resizable command not
+ working on Solaris/CDE" (patch from Colin McDonald).
+
+2004-08-09 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * tests/canvText.test:
+ * win/tkWinFont.c (Tk_MeasureChars): Fix for text wrapping problem that
+ appeared using canvas text under Win32. A long wrapping string that had
+ leading spaces was being incorrectly wrapped. This change makes the
+ Win32 implementation behave the same as the Unix implementation. [Patch
+ 1006286]
+
+2004-08-05 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * library/clrpick.tcl (BuildDialog):
+ * library/msgbox.tcl (MessageBox): Add scheme for cancelling dialog
+ boxes with Escape and also handle what happens when the window gets
+ nuked from outside. [Bug 987169]
+
+2004-08-04 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tkImgPhoto.c (ImgPhotoBlendComplexAlpha): Clean the code up a
+ bit and add a few more comments.
+ (Tk_PhotoPutBlock, Tk_PhotoPutZoomedBlock): Clarified the code,
+ corrected the compositing rule now that I have looked up what the right
+ thing to do is, and factorized out the compositing rule code into a few
+ simpler macros.
+
+2004-07-30 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/configure:
+ * unix/tcl.m4 (SC_CONFIG_CFLAGS): Darwin: instead of setting PLAT_OBJS
+ to explict object files in tcl.m4, refer to MAC_OSX_OBJS makefile var.
+
+2004-07-29 George Peter Staplin <georgeps@xmission.com>
+
+ * generic/tkEvent.c (TkQueueEventForAllChildren): Code from the
+ core-8-4-branch to not queue events for unmapped windows was added.
+
+2004-07-27 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tkImgGIF.c (FileReadGIF): fix crash reported by Reinhard
+ Max: in case of premature end of image data, return error instead of
+ passing nil buffer to Tk_PhotoPutBlock().
+
+2004-07-22 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/tkfbox.tcl (::tk::dialog::file::Update): use -directory [pwd]
+ (instead of .) to get around some VFS edge case bugs. Correct args
+ passes to tk_messageBox when failing to cd. Add -force back to
+ namespace import of msgcat.
+
+2004-07-20 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkEvent.c (InvokeInputMethods): ensure IC focus is set after
+ creation. [Bug 905830]
+
+2004-07-20 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Makefile: added support to tk framework build to optionally
+ install tk manpages in addition to html help, similarly to
+ tcl/macosx/Makefile.
+
+ * macosx/Wish.pbproj/project.pbxproj: fixes for building with
+ non-default SYMROOT/OBJROOT/SRCROOT, added support for using a
+ Tcl.framework in DYLIB_INSTALL_PATH != /Library/Frameworks, added
+ optional support for building html help without tcl sources present by
+ giving explicit location of tcltk-man2html script.
+
+ * macosx/tkMacOSXMenu.c: fixed #include case sensitivity bug.
+
+ * unix/Makefile.in:
+ * win/Makefile.in: added 'install-private-headers' makefile target to
+ allow optionally installing private tk headers. [Tcl FR 922727]
+
+2004-07-16 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/Makefile.in, unix/tcl.m4: move (C|LD)FLAGS after their
+ * unix/configure.in, unix/configure: _DEFAULT to allow for env setting
+ to override m4 switches.
+ Consolidate header checks to limit redundancy in configure.
+ (CFLAGS_WARNING): Remove -Wconversion
+ (SC_ENABLE_THREADS): Set m4 to force threaded build when built against
+ a threaded Tcl core.
+ Reorder configure.in for better 64-bit build configuration, replacing
+ EXTRA_CFLAGS with CFLAGS. [Bug 874058]
+
+2004-07-14 Jim Ingham <jingham@apple.com>
+
+ * macosx/tkMacOSXCursor.c (TkpSetCursor): The code to not reset the
+ cursor more often than necessary was getting fooled when the current
+ cursor was nulled out when the current cursor gets freed. So in the
+ case where the input cursor was NULL, we have to just always set it.
+ [Bug 894550]
+
+2004-07-13 Don Porter <dgp@users.sourceforge.net>
+
+ * library/tkfbox.tcl: Corrected coding errors in most recent change.
+ Use [bind $w], not [$w configure] to modify bindings.
+
+2004-07-11 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * library/tkfbox.tcl (::tk::dialog::file::Create): Watch out for users
+ destroying the dialog indirectly. [Bug 987169]
+
+2004-07-07 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/canvas.n: Add paragraph to make clearer what is going on with the
+ default canvas origin. [Bug 956681]
+
+2004-07-05 George Peter Staplin <GeorgePS@XMission.com>
+
+ * generic/tkEvent.c: TK_XIM_SPOT preprocessor usage was modified
+ slightly to fix a bug that occured when TK_XIM_SPOT was defined as 0.
+ Thanks to Joe Mistachkin for reporting this bug.
+
+2004-07-05 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ TIP#158 IMPLEMENTATION
+
+ * tests/bind.test: Allow Win apps to distinguish keys
+ * win/tkWinX.c (GetState): on the keypad using the Extended
+ * generic/tkInt.h (EXTENDED_MASK): modifier. Thanks to Wolfgang
+ * generic/tkBind.c: Grossbauer and Kevin Kenny for
+ * doc/bind.n: developing this patch [Patch 797404]
+
+2004-07-05 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/tkUnixWm.c: Set _NET_WM_NAME and _NET_WM_ICON_NAME
+ (freedesktop.org) in addition to WM_NAME and WM_ICON_NAME (ICCCM). This
+ allows the full Unicode character set to be used in window manager
+ strings (but only for newer WMs that support the EWMH spec). [Bug
+ 959973]
+
+2004-07-02 George Peter Staplin <GeorgePS@XMission.com>
+
+ * generic/tkEvent.c: Tk_HandleEvent was refactored to be more readable,
+ and during this process two bugs were found.
+ 1) Button 4 and 5 masks will now be synchronized with the TkDisplay.
+ 2) ClientMessage handlers will use the proper last pointer rather than
+ writing to the last GenericHandler pointer.
+
+ Thanks to Joe English for his help and encouragement, and DKF for
+ review.
+
+2004-07-01 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/place.n, doc/pack.n: Doc fixes. [Tcl Bug 983146]
+
+2004-06-30 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ TIP#153 IMPLEMENTATION
+
+ * generic/tkCmds.c (GetTopHierarchy): Modified from GetToplevel so
+ * doc/winfo.n: that [winfo toplevel] does not
+ assume that it is really working with toplevels. Occasionally this is
+ important. Thanks to Neil McKay for this patch!
+
+2004-06-29 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkCmds.c (Tk_WinfoObjCmd): refetch interp result obj for
+ 'winfo id' as it can change when making the window exist.
+
+2004-06-26 Joe Mistachkin <joe@mistachkin.com>
+
+ * generic/tkConsole.c (ConsoleDeleteProc): Set tsdPtr->gStdoutInterp to
+ NULL when the console command is deleted [Bug 756840]. Also, added
+ Tcl_Preserve/Tcl_Release for consoleInterp in InterpreterCmd in case it
+ gets deleted during the calls to Tcl_GlobalEval and Tcl_RecordAndEval.
+
+2004-06-24 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * tests/canvPs.test, etc: Use standard tcltest constraint names.
+
+2004-06-19 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/tcl.m4: autoconf 2.5 fixes in Darwin section.
+ * unix/configure: autoconf-2.57
+
+2004-06-17 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * tests/constraints.tcl, tests/*.test: Systematization of test
+ constraints so many common and basic constraints are defined once with
+ a single name.
+
+2004-06-16 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/tkUnixWm.c, win/tkWinWm.c, macosx/tkMacOSXWm.c, tests/wm.test
+ * tests/unixWm.test: Fix for [Bug 742882] "Potential division by zero
+ in gridded wm geometry"
+
+2004-06-15 Anton Kovalenko <a_kovalenko@users.sourceforge.net>
+
+ * win/tkWinButton.c: Add a 3D highlight to disabled *buttons and
+ labels, the same way as it's now done for disabled menu entries.
+
+2004-06-15 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/image.n: Enhanced the documentation to take into account the
+ concerns raised in [RFE 803060]
+
+ * tests/canvas.test: Updated tests affected by the change to
+ ScrollFractions, which is now clean about result generation.
+
+ * generic/tkCanvas.c: Make tag search subsystem use symbolic names for
+ type flags for easier maintenance.
+ (FIRST_CANVAS_ITEM_MATCHING,FOR_EVERY_CANVAS_ITEM_MATCHING): Factorize
+ out searching idioms into macros to reduce the #ifdef count and make
+ braces match.
+ (ScrollFractions): Really create a list Tcl_Obj.
+
+2004-06-12 Anton Kovalenko <a_kovalenko@users.sourceforge.net>
+
+ * win/tkWinWm.c (UpdateWrapper): Let overrideredirect'ed window's
+ wrapper be the child of desktop window, thus making it to behave more
+ similarly to X11 Override Redirect. Esp. useful for combobox-like
+ megawidgets.
+
+2004-06-09 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkText.c:
+ * tests/text.test: fix to multi-line regexp search bugs in text widget
+ (reported against Alphatk editor, not on sf). Addded 3 new tests.
+
+2004-06-09 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tkUndo.c (TkUndoSetDepth): Delete the unlinked element and
+ not the next element. Stops a crash in some situations and a memory
+ leak in others. Thanks to Jiang Wu for spotting this. [Bug 969358]
+
+2004-06-08 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tkCanvText.c (DisplayCanvText): Fix text rendering problem
+ with canvas text items that have a selected region. The previous
+ implementation would render the whole line and then redraw the
+ selected text if it was a different color. This caused problems when
+ the selected text foreground differs from the normal text foreground,
+ the anti-aliasing alpha pixels for the two text strings would blend
+ together resulting in strange looking text. The fix is to draw the
+ normal text and the selected text separately. This problem has only
+ been observed under Windows, with anti-aliased text. [Patch 968725]
+
+2004-06-07 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkTextDisp.c:
+ * generic/tkTextBTree.c: fix to (Bug 965186) in which the text widget's
+ record of partial-line-height calculations (for very long wrapped
+ lines) was being incorrectly reused. This resulted in confusing
+ scrollbar-text interactions.
+
+2004-06-06 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * tests/frame.test: Fix frame-2.8 for ![info exists env(DISPLAY)]
+
+2004-06-04 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/filebox.test: A few typo corrections in dkf's recent style
+ * tests/frame.test: upgrade for the test suite.
+ * tests/select.test:
+ * tests/visual.test:
+
+2004-06-04 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkTextIndex.c:
+ * generic/tkText.c:
+ * generic/tkTextDisp.c:
+ * doc/text.n: fix to shimmering infinite loop scrolling problem in text
+ widget under some rare circumstances (Bug 965398). Improved comments
+ and documentation.
+
+ * tests/textDisp.test: corrected rounding from float to int in test,
+ fixing occasional failures
+
+ * library/text.tcl: corrected mousewheel bindings for TkAqua
+
+2004-05-29 Joe English <jenglish@users.sourceforge.net>
+
+ * doc/messageBox.n: Fix minor markup errors (backslash is \e, not \b).
+
+2004-05-24 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/messageBox.n: Added documentation for the -detail option.
+ * tests/msgbox.test: Updated test suite with correct list of options.
+ * win/tkWinDialog.c (Tk_MessageBoxObjCmd): Added "support" for the
+ -detail option by concatenating it onto the end of the message.
+
+2004-05-24 Jim Ingham <jingham@apple.com>
+
+ * tkMacOSXDialog.c (Tk_MessageBoxObjCmd): Turn on the -detail option
+ for Mac OS X.
+
+2004-05-23 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * ChangeLog.2002: Split older ChangeLog entries off into a separate
+ file.
+ * doc/bindtags.n: Added example.
+
+ * tests/*.test: Many minor fixes aiming towards making the Tk test
+ suite have better style. (A very large fraction of test files were
+ modified.)
+
+ * generic/tkVisual.c (Tk_GetVisual): Minor fix for error message.
+
+2004-05-14 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ TIP#152 IMPLEMENTATION (Unix only)
+
+ * library/msgbox.tcl (MessageBox): Added TIP#152's -detail option for
+ Unix/X11 platforms. Also shrank the size of the main -message text
+ which was grossly large.
+
+2004-05-12 Chengye Mao <chengye.geo@yahoo.com>
+
+ * generic/tkBind.c <HandleEventGenerate>: Modified to fix wish crash
+ due to incorrectly generate <Destroy> event. This bug was reported in
+ comp.lang.tcl but not logged.
+
+2004-05-07 Chengye Mao <chengye.geo@yahoo.com>
+
+ * win/tkWinWm.c <UpdateWrapper>: handle and destroy old wrapper
+ correctly and fix crash problem in wish exiting [Bug 767176].
+
+2004-05-05 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinFont.c (FindSubFontForChar): corrections to dkf patch to
+ handle subFontPtrPtr in EnumFontFamilies callback.
+
+2004-05-05 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * win/tkWinFont.c (Tk_MeasureChars,Tk_DrawChars,etc): Make sure that
+ the lastSubFontPtr remains valid even when the subfont array is
+ reallocated. [Bug 618872]
+
+2004-05-03 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/tkUnixButton.c (TkpDrawCheckIndicator): allow radiobuttons to be
+ drawn when disabledforeground and/or selectcolor are NULL.
+ [Bug 826850] (griffin)
+
+ * win/tkWinMenu.c, unix/tkUnixMenu.c (DrawMenuEntryLabel): place images
+ of compound menu entries in indicator space if not a radio of
+ checkbutton. [Bug 756952] (eserte)
+
+ * win/tkWinX.c: fix drawing of unicode chars in menu
+ * win/tkWinInt.h (TkWinProcs): titles. [Bug 904371] (riefenstahl)
+ * win/tkWinMenu.c (ReconfigureWindowsMenu):
+
+ * generic/tkClipboard.c: Move TkClipCleanup from tkClipboard.c to
+ * macosx/tkMacOSXXStubs.c: being implemented in a platform-specific
+ * unix/tkUnixEvent.c: manner. The cleanup order was bad at least
+ * win/tkWinX.c: on Windows, where we reset/cleared display
+ info that was still needed for the clipboard to render. [Bug 939389,
+ 822002, 732662]
+
+ * library/panedwindow.tcl (MarkSash): call DragSash to stop sash jump
+ when B1 is pressed and released without moving. [Bug 932155]
+
+ * tests/panedwindow.test: panedwindow-25.1
+ * generic/tkPanedWindow.c (Unlink): clean up -before/-after refs to a
+ slave when removing it. [Bug 928413] (griffin)
+
+ * generic/tkImgPhoto.c (ImgPhotoConfigureMaster): force -data into
+ ByteArray and -format into String to correctly handle them if they
+ have been shimmered or created as some other object type.
+
+2004-04-24 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tkPort.h:
+ * unix/Makefile.in:
+ * win/makefile.bc:
+ * win/Makefile.in: followup on tcl header reform [FR 922727]: removed
+ use of relative #include paths in tkPort.h to allow installation of
+ private headers outside of tk source tree; added tcl plaform source dir
+ to compiler header search path.
+
+2004-04-23 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/bind.n: Added examples (in line with the parallel programme for
+ adding examples to Tcl manual pages) and made assorted minor
+ alterations to improve the overall look.
+
+2004-04-21 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * tests/textDisp.test: Get rid of windows that are no longer needed so
+ single-proc tests don't have extra windows hanging around unexpectedly.
+
+2004-04-21 Benjamin Riefenstahl <Benjamin.Riefenstahl@epost.de>
+
+ Mac OS X: Fix several problems with Icelandic (and Faroese) keyboards
+ reported by Jérôme Gagnon-Voyer <gagnonje5000<at>mac<dot>com> on
+ tcl-mac on 2004-03-22.
+
+ * macosx/tkMacOSXKeyEvent.c (KLSInit): Add.
+ (GetKeyboardLayout): Add calls to Keyboard Layout Services, if present.
+ Rework classic handling. Use GetKCHREncoding(). Add parameter
+ encodingPtr.
+ (GetKCHREncoding): Add.
+
+2004-04-16 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/bgerror.tcl (bgerror): rework to only set -topmost bit on
+ Windows if necessary. Also use existing ::tk functions for placing
+ dialog and managing focus/grab.
+
+2004-04-04 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/tkUnixWm.c: Fix for [Bug 915350] "Tk sets min, max size in
+ WM_HINTS when it shouldn't" and [Bug 922336] "Tk apps have no maximize
+ window button under KDE-3.2.1"
+
+2004-03-31 Jim Ingham <jingham@apple.com>
+
+ * tkMacOSXCarbonEvents.c (AppEventHandlerProc): Handle the
+ kEventAppHidden and kEventAppShown events.
+ (TkMacOSXInitCarbonEvents): Register for the above events.
+ * tkMacOSXKeyEvent.c (TkMacOSXProcessKeyboardEvent): Steal the
+ Command-H menu key event and allow the Application handler to have it.
+ This is currently the only way to get the Hide behavior to work. [Bug
+ 917557]
+
+ * tkMacOSMenus.c (TkMacOSXHandleMenuSelect): Remove the Quit menu
+ handler - this was for the Quit item in the File menu, but it doesn't
+ belong there.
+ (TkMacOSXInitMenus): Remove the Quit menu item from the File menu.
+
+ * tkMacOSXMenu.c (EventuallyInvokeMenu): Report errors from invoking
+ menu commands as background errors. [Bug 220871]
+
+2004-03-31 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkImgPhoto.c: Removed outdated #include's of the tclMath.h
+ * generic/tkScale.c: header file. All tk*Port.h files have long had
+ a #include <math.h>, and other parts of Tk routinely make use of
+ libm-supplied math routines.
+
+2004-03-30 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tclets.r (removed): obsolete holdover from mac classic.
+
+2004-03-26 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tkImgPPM.c (ReadPPMStringHeader): Code to read PPM/PGM data
+ (StringReadPPM, StringMatchPPM): from strings/bytearrays. [FRQ 540375]
+
+2004-03-26 Don Porter <dgp@users.sourceforge.net>
+
+ * unix/tcl.m4: Replaced -Wno-strict-alias with more portable
+ -fno-strict-alias alternative.
+
+ * README: Bump version to 8.5a2.
+ * generic/tk.h:
+ * macosx/Wish.pbproj/project.pbxproj:
+ * unix/configure.in:
+ * unix/tk.spec:
+ * win/configure.in:
+
+ * unix/configure: autoconf-2.57
+ * win/configure:
+
+2004-03-26 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tkImgPPM.c (StringWritePPM): New function to support
+ converting of images to PPM strings. Other direction not yet done. Rest
+ of file converted to use new image API.
+ * generic/tkImgPhoto.c (ImgPhotoCmd): Restored support for the
+ stringWriteProc of old photo formats. [Bug 923555]
+
+2004-03-25 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/winfo.n: Clarified the range of colour intensities returned by
+ [winfo rgb]. [Bug 922610]
+
+2004-03-22 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/ConfigWidg.3: Converted malloc/free to Tcl_Alloc/Tcl_Free to help
+ avoid confusion and crashes on Windows. [Bug 920695]
+
+2004-03-20 Jim Ingham <jingham@apple.com>
+
+ * macosx/tkMacOSXSubwindows.c (GenerateConfigureNotify): New function.
+ (XMoveWindow): Generate configure notify events for child widgets on
+ move.
+ (XMoveResizeWindow): Ditto.
+
+2004-03-18 Daniel Steffen <das@users.sourceforge.net>
+
+ Removed support for Mac OS Classic platform [Patch 918139]
+
+ * doc/console.n:
+ * doc/tk.n:
+ * generic/README:
+ * generic/default.h:
+ * generic/tk.decls:
+ * generic/tk.h:
+ * generic/tkBind.c:
+ * generic/tkCmds.c:
+ * generic/tkConsole.c:
+ * generic/tkFileFilter.h:
+ * generic/tkGrab.c:
+ * generic/tkInitScript.h:
+ * generic/tkInt.decls:
+ * generic/tkIntDecls.h:
+ * generic/tkIntPlatDecls.h:
+ * generic/tkIntXlibDecls.h:
+ * generic/tkMain.c:
+ * generic/tkPlatDecls.h:
+ * generic/tkPointer.c:
+ * generic/tkPort.h:
+ * generic/tkSelect.c:
+ * generic/tkStubInit.c:
+ * generic/tkStubLib.c:
+ * generic/tkTest.c:
+ * generic/tkText.c:
+ * generic/tkWindow.c:
+ * library/bgerror.tcl:
+ * library/button.tcl:
+ * library/console.tcl:
+ * library/dialog.tcl:
+ * library/entry.tcl:
+ * library/msgbox.tcl:
+ * library/spinbox.tcl:
+ * library/tearoff.tcl:
+ * library/text.tcl:
+ * library/tk.tcl:
+ * library/demos/text.tcl:
+ * library/demos/widget:
+ * mac/MW_TkBuildLibHeader.h (removed):
+ * mac/MW_TkBuildLibHeader.pch (removed):
+ * mac/MW_TkHeader.h (removed):
+ * mac/MW_TkHeader.pch (removed):
+ * mac/MW_TkHeaderCommon.h (removed):
+ * mac/MW_TkOldImgHeader.h (removed):
+ * mac/MW_TkOldImgStaticHeader.h (removed):
+ * mac/MW_TkStaticHeader.h (removed):
+ * mac/MW_TkStaticHeader.pch (removed):
+ * mac/MW_TkTestHeader.h (removed):
+ * mac/MW_TkTestHeader.pch (removed):
+ * mac/README (removed):
+ * mac/bugs.doc (removed):
+ * mac/tclets.r (removed):
+ * mac/tclets.tcl (removed):
+ * mac/tkMac.h (removed):
+ * mac/tkMacAppInit.c (removed):
+ * mac/tkMacAppearanceStubs.c (removed):
+ * mac/tkMacApplication.r (removed):
+ * mac/tkMacBitmap.c (removed):
+ * mac/tkMacButton.c (removed):
+ * mac/tkMacClipboard.c (removed):
+ * mac/tkMacColor.c (removed):
+ * mac/tkMacConfig.c (removed):
+ * mac/tkMacCursor.c (removed):
+ * mac/tkMacCursors.r (removed):
+ * mac/tkMacDefault.h (removed):
+ * mac/tkMacDialog.c (removed):
+ * mac/tkMacDraw.c (removed):
+ * mac/tkMacEmbed.c (removed):
+ * mac/tkMacFont.c (removed):
+ * mac/tkMacHLEvents.c (removed):
+ * mac/tkMacInit.c (removed):
+ * mac/tkMacInt.h (removed):
+ * mac/tkMacKeyboard.c (removed):
+ * mac/tkMacLibrary.r (removed):
+ * mac/tkMacMDEF.c (removed):
+ * mac/tkMacMDEF.r (removed):
+ * mac/tkMacMenu.c (removed):
+ * mac/tkMacMenu.r (removed):
+ * mac/tkMacMenubutton.c (removed):
+ * mac/tkMacMenus.c (removed):
+ * mac/tkMacPort.h (removed):
+ * mac/tkMacProjects.sea.hqx (removed):
+ * mac/tkMacRegion.c (removed):
+ * mac/tkMacResource.r (removed):
+ * mac/tkMacScale.c (removed):
+ * mac/tkMacScrlbr.c (removed):
+ * mac/tkMacSend.c (removed):
+ * mac/tkMacSubwindows.c (removed):
+ * mac/tkMacTclCode.r (removed):
+ * mac/tkMacTest.c (removed):
+ * mac/tkMacWindowMgr.c (removed):
+ * mac/tkMacWm.c (removed):
+ * mac/tkMacXCursors.r (removed):
+ * mac/tkMacXStubs.c (removed):
+ * mac/widget.r (removed):
+ * tests/clrpick.test:
+ * tests/cursor.test:
+ * tests/entry.test:
+ * tests/font.test:
+ * tests/macEmbed.test (removed):
+ * tests/macFont.test (removed):
+ * tests/macMenu.test (removed):
+ * tests/macWinMenu.test (removed):
+ * tests/macscrollbar.test (removed):
+ * tests/menuDraw.test:
+ * tests/safe.test:
+ * tests/scrollbar.test:
+ * tests/select.test:
+ * tests/spinbox.test:
+ * tests/text.test:
+ * tests/tk.test:
+ * tests/winfo.test:
+ * tests/wm.test:
+ * unix/Makefile.in:
+ * unix/README:
+ * unix/tk.spec:
+ * unix/tkUnix3d.c:
+ * unix/tkUnixDraw.c:
+ * xlib/xgc.c:
+ * xlib/xutil.c:
+ * xlib/X11/X.h:
+ * xlib/X11/Xlib.h:
+ * xlib/X11/Xutil.h:
+ * xlib/X11/keysym.h:
+
+2004-03-16 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/tkUnixButton.c (TkpDrawCheckIndicator): correct crash condition
+ for new radio/checkbuttons when colors are exhausted.
+ [Bug 915330] (griffin)
+
+ * generic/tkGrid.c (GridRowColumnConfigureCommand): fix lint warning
+
+ * generic/tkCanvUtil.c: fix cast warnings
+
+ * generic/tkTextImage.c (EmbImageConfigure): fix casts
+
+ * unix/tkUnixSelect.c (ConvertSelection, TkSelPropProc): fix casts
+
+ * unix/configure, unix/tcl.m4: add -Wno-strict-aliasing for GCC to
+ suppress useless type puning warnings.
+
+2004-03-08 David Gravereaux <davygrvy@pobox.com>
+
+ * win/makefile.vc:
+ * win/buildall.vc.bat: Checks MSDevDir, not MSVCDir envar.
+
+2004-03-04 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/tkWin32Dll.c: Add variables needed when compiling with mem debug
+ under Mingw. This fixes the checking from 2003-12-25.
+
+2004-03-03 Jeff Hobbs <jeffh@ActiveState.com>
+
+ *** 8.5a1 TAGGED FOR RELEASE ***
+
+ * unix/Makefile.in (dist): don't require win/lamp.bmp copy in dist
+ target (it's already handled by win/rc/*.bmp copy)
+
+ * changes: updated for 8.5a1
+
+2004-03-01 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * README: update to patchlevel 8.5a1
+ * generic/tk.h:
+ * macosx/Wish.pbproj/project.pbxproj:
+ * unix/configure, unix/configure.in, unix/tk.spec:
+ * win/configure, win/configure.in:
+
+ * unix/tcl.m4: update HP-11 build libs setup
+
+2004-03-01 Don Porter <dgp@users.sourceforge.net>
+
+ * unix/tcl.m4 (SC_CONFIG_CFLAGS): Allow 64-bit enabling on
+ IRIX64-6.5* systems. [Bug 218561]
+ * unix/configure: autoconf-2.57
+
+2004-02-28 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkTextIndex.c: remove use of internal Tcl interface
+ 'TclUtfToUniChar'
+
+2004-02-25 Benjamin Riefenstahl <Benjamin.Riefenstahl@epost.de>
+
+ * library/demos/widget (addFormattedText): Correct off-by-one error.
+
+2004-02-23 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Makefile: ensure that xcodebuild will use the Wish.pbproj
+ project even if a .xcode project is also present.
+
+ * macosx/tkMacOSXMouseEvent.c: fixed modifiers for MouseWheel events.
+
+ * macosx/Wish.pbproj/project.pbxproj:
+ * macosx/tkAboutDlg.r: changed year in copyright strings to 2004.
+
+2004-02-23 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXDraw.c:
+ * macosx/tkMacOSXXStubs.c:
+ * xlib/ximage.c: fixed MacOSX XGetImage/XPutImage and related functions
+ to deal properly with XImages copied from screen.
+ * generic/tkCanvPs.c (TkImageGetColor): MacOSX fix. [Bug 809157]
+
+2004-02-18 Peter Spjuth <peter.spjuth@space.se>
+
+ * tests/grid.test:
+ * generic/tkGrid.c: Fixed a bug in grid geometry calculations for a
+ shrinking grid. [Bug 899246]
+
+2004-02-17 Benjamin Riefenstahl <Benjamin.Riefenstahl@epost.de>
+
+ * macosx/tkMacOSXKeyboard.c (TkpInitKeymapInfo): Don't make <Alt> and
+ <Meta> synonyms for <Command> and <Option> for now.
+
+2004-02-17 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkBind.c (HandleEventGenerate): only modify root[xy] with
+ [xy] when they haven't been otherwise set.
+
+ TIP#110 IMPLEMENTATION
+
+ * doc/checkbutton.n: Tristate Checkbutton and Radiobuttons
+ * doc/radiobutton.n:
+ * generic/tkButton.c:
+ * generic/tkButton.h:
+ * library/demos/check.tcl:
+ * library/demos/radio.tcl:
+ * macosx/tkMacOSXButton.c:
+ * macosx/tkMacOSXDefault.h:
+ * tests/button.test:
+ * unix/tkUnixButton.c:
+ * unix/tkUnixDefault.h:
+ * win/tkWinButton.c:
+ * win/tkWinDefault.h:
+
+2004-02-17 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/imgPhoto.test (imgPhoto-16.1): Corrected incorrect variable
+ name [Bug 899010].
+
+2004-02-15 Jim Ingham <jingham@apple.com>
+
+ * tkMacOSXDialog.c (MatchOneType): If the Macintosh filetype is 0, then
+ automatically pass the fileType check.
+
+ * tkMacOSXCarbonEvents.c: New file - this doesn't do anything yet -
+ just registers for a couple of App Events.
+
+ * tkMacOSXInit.c (TkpInit.c): Call TkMacOSXInitCarbonEvents.c.
+
+ * tkMacOSXAppInit.c: Formatting cleanups.
+ * tkMacOSXButton.c: Ditto
+ * tkMacOSXClipboard.c: Ditto
+ * tkMacOSXDebug.c: Ditto
+ * tkMacOSXDialog.c: Ditto
+ * tkMacOSXDraw.c: Ditto
+ * tkMacOSXEvent.c: Ditto
+ * tkMacOSXFont.c: Ditto
+ * tkMacOSXHLEvents.c: Ditto
+ * tkMacOSXInit.c: Ditto
+ * tkMacOSXInt.h
+ * tkMacOSXKeyEvent.c: Ditto
+ * tkMacOSXMenu.c: Ditto
+ * tkMacOSXMenubutton.c: Ditto
+ * tkMacOSXMouseEvent.c: Ditto
+ * tkMacOSXNotify.c: Ditto
+ * tkMacOSXScale.c: Ditto
+ * tkMacOSXScrlbr.c: Ditto
+ * tkMacOSXSubwindows.c: Ditto
+ * tkMacOSXWindowEvent.c: Ditto
+ * tkMacOSXWm.c: Ditto
+
+2004-02-13 Jim Ingham <jingham@apple.com>
+
+ * tkMacOSXDialog.c (Tk_GetOpenFileObjCmd): Use CFStringRef for title &
+ message options, not pascal strings.
+ (Tk_GetSaveFileObjCmd): Ditto
+ (Tk_ChooseDirectoryObjCmd): Ditto
+ (NavServicesGetFile): Now that we get CFStrings, we don't need to
+ convert them here.
+
+ * tkMacOSXMenu.c (TkMacOSXDispatchMenuEvent): Cleanup, we don't need to
+ handle the Apple Menu picks any more, but the code didn't reflect that.
+
+ * tkMacOSXWm.c (TkSetWMName): Use CFStrings for the Window Title name,
+ not Pascal strings.
+
+2004-02-12 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinDialog.c (ChooseDirectoryValidateProc): create a pidl for
+ -initialdir if we have a UNC path because BFFM_SETSELECTION doesn't
+ support UNC paths in strings.
+
+2004-02-10 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * library/msgs/eo.msg: Language support for Esperanto and Polish from
+ * library/msgs/pl.msg: Artur Trzewik <mail@xdobry.de> with thanks.
+
+2004-02-09 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tkImgPhoto.c (Tk_PhotoPutBlock, Tk_PhotoPutZoomedBlock):
+ * tests/imgPhoto.test (imgPhoto-16.1): Better handling of the case when
+ copying from one area of a photo to another triggers a resizing of the
+ image. [Bug 877950]
+
+2004-02-07 David Gravereaux <davygrvy@pobox.com>
+
+ * win/makefile.vc:
+ * win/rules.vc:
+ * win/rc/tk.rc:
+ * win/rc/wish.rc: Now supports the 'unchecked' option when building.
+
+2004-02-03 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * doc/menubutton.n:
+ * library/menu.tcl (::tk::MbPost): make menubuttons that post above or
+ below reverse direction when not enough space is available.
+
+2004-02-01 David Gravereaux <davygrvy@pobox.com>
+
+ * win/lamp.bmp (deleted): using win/rc/lamp.bmp instead.
+
+ * win/winMain.c: Removed our custom setargv() in favor of __argc and
+ __argv exported by the C run-time.
+
+ * win/makefile.vc:
+ * win/rc/tk.rc:
+ * win/rc/wish.rc: General clean-up.
+
+ * win/rules.vc:
+ * win/nmakehlp.c: sync'd to Tcl.
+
+2004-01-31 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/tkUnixWm.c, unix/tkUnixEvent.c: Replaced TclpGetTime() with
+ Tcl_GetTime(), to remove dependency on tclInt.h [Bug 874745].
+
+2004-01-27 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tkTextIndex.c: added '#include <tclInt.h>' since the code
+ uses the TclUtfToUniChar macro from that file. [Bug 874745]
+
+ * macosx/Wish.pbproj/project.pbxproj: removed erroneous reference to
+ mkpsenc.tcl in bundle resources phase (mkpsenc.tcl is already part of
+ the copy files phase to Resources/Scripts).
+
+ * macosx/Makefile: added support for 'xcodebuild' on Mac OS X 10.3.
+
+2004-01-25 Benjamin Riefenstahl <Benjamin.Riefenstahl@epost.de>
+
+ * macosx/tkMacOSXKeyboard.c: Fix regressions due to the last patches.
+
+2004-01-25 Peter Spjuth <peter.spjuth@space.se>
+
+ * library/dialog.tcl:
+ * library/msgbox.tcl: The dialogs were affected by the TIP#146
+ implementation. Added grid anchor commands to restore original
+ behaviour.
+
+2004-01-15 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tkWinSendCom.c: Placed the requirement for the special COM
+ libraries into the object file itself with #pragma comment (lib, ...)
+ when built with VC++. This will simplify linking for users of the
+ static library. uuid.lib is required for VC5.2, but is implicit with
+ VC6.
+
+ * win/makefile.vc: Removed 'ole32.lib oleaut32.lib uuid.lib' from
+ $(baselibs).
+
+2004-01-12 David Gravereaux <davygrvy@pobox.com>
+
+ * generic/tk3d.c: All uses of 'panic' (the macro) changed to
+ * generic/tkBind.c: 'Tcl_Panic' (the function). The #define of
+ * generic/tkBitmap.c: panic in tcl.h clearly states it is deprecated
+ * generic/tkCanvArc.c: in the comments. [Tcl Patch 865264]
+ * generic/tkCanvBmap.c:
+ * generic/tkCanvImg.c:
+ * generic/tkCanvLine.c:
+ * generic/tkCanvPoly.c:
+ * generic/tkCanvText.c:
+ * generic/tkCanvWind.c:
+ * generic/tkColor.c:
+ * generic/tkConfig.c:
+ * generic/tkCursor.c:
+ * generic/tkError.c:
+ * generic/tkEvent.c:
+ * generic/tkFocus.c:
+ * generic/tkFont.c:
+ * generic/tkFrame.c:
+ * generic/tkGC.c:
+ * generic/tkGrid.c:
+ * generic/tkImgBmap.c:
+ * generic/tkImgPhoto.c:
+ * generic/tkImgUtil.c:
+ * generic/tkMenu.c:
+ * generic/tkObj.c:
+ * generic/tkPack.c:
+ * generic/tkPlace.c:
+ * generic/tkRectOval.c:
+ * generic/tkSelect.c:
+ * generic/tkText.c:
+ * generic/tkTextBTree.c:
+ * generic/tkTextDisp.c:
+ * generic/tkTextImage.c:
+ * generic/tkTextIndex.c:
+ * generic/tkTextMark.c:
+ * generic/tkTextWind.c:
+ * generic/tkVisual.c:
+ * generic/tkWindow.c:
+ * mac/tkMacAppInit.c:
+ * mac/tkMacAppearanceStubs.c:
+ * mac/tkMacButton.c:
+ * mac/tkMacDraw.c:
+ * mac/tkMacEmbed.c:
+ * mac/tkMacFont.c:
+ * mac/tkMacInit.c:
+ * mac/tkMacMenus.c:
+ * mac/tkMacPort.h:
+ * mac/tkMacSubwindows.c:
+ * mac/tkMacWm.c:
+ * mac/tkMacXStubs.c:
+ * macosx/tkMacOSXEmbed.c:
+ * macosx/tkMacOSXFont.c:
+ * macosx/tkMacOSXMenus.c:
+ * macosx/tkMacOSXNotify.c:
+ * macosx/tkMacOSXPort.h:
+ * macosx/tkMacOSXSubwindows.c:
+ * macosx/tkMacOSXWm.c:
+ * macosx/tkMacOSXXStubs.c:
+ * unix/tkUnix3d.c:
+ * unix/tkUnixColor.c:
+ * unix/tkUnixEmbed.c:
+ * unix/tkUnixEvent.c:
+ * unix/tkUnixFocus.c:
+ * unix/tkUnixFont.c:
+ * unix/tkUnixSelect.c:
+ * unix/tkUnixSend.c:
+ * unix/tkUnixWm.c:
+ * win/tkWin3d.c:
+ * win/tkWinButton.c:
+ * win/tkWinColor.c:
+ * win/tkWinDialog.c:
+ * win/tkWinDraw.c:
+ * win/tkWinEmbed.c:
+ * win/tkWinFont.c:
+ * win/tkWinPixmap.c:
+ * win/tkWinPointer.c:
+ * win/tkWinScrlbr.c:
+ * win/tkWinWm.c:
+ * win/tkWinX.c:
+
+ * win/rc/tk.rc:
+ * win/rc/tk_base.rc:
+ * win/rc/wish.rc:
+ * win/makefile.vc: Refreshed how the resource files are built. Should
+ be a bit easier for people linking with a static Tk library.
+
+ * win/lamp.bmp (deleted):
+ * win/rc/lamp.bmp (new): Moved.
+
+ * win/rules.vc: Sync'd to Tcl, respects the CHECKS=nodep command line
+ macro and was used to verify the Tcl_Panic change above.
+
+2004-01-09 Peter Spjuth <peter.spjuth@space.se>
+
+ TIP#146 IMPLEMENTATION
+
+ * doc/grid.n:
+ * tests/grid.test:
+ * generic/tkGrid.c: Implementation of TIP#146, "Add Overall Anchoring
+ to the Grid Geometry Manager", adding [grid anchor] subcommand.
+ **** POTENTIAL VISUAL INCOMPATABILITY ****
+
+2004-01-07 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkTextDisp.c:
+ * generic/tkTextBTree.c:
+ * tests/text.test: fixed crashing [Bug 872299] in yview code, and added
+ tests and better error checking in the B-tree.
+
+2004-01-07 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkTextIndex.c:
+ * tests/textIndex.test: fixed bug in which 'wordstart' and 'wordend'
+ were not utf-8 aware (they haven't been changed since Tk 8.0), and
+ added tests.
+
+2004-01-07 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * win/tkWinMenu.c: only provide a submenu handle when the MF_POPUP flag
+ is given, fixing a recently-introduced crash when submenus are
+ disabled. Also better error checking for this sort of situation in the
+ future.
+
+2003-12-31 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Wish.pbproj/project.pbxproj: added missing private headers to
+ installed Tk.framework, so that tkInt.h can be included sucessfully
+ from Tk.framework/PrivateHeaders.
+ * generic/tkPort.h: corrected include of tkMacOSXPort.h
+
+2003-12-28 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/tkWinMenu.c (ReconfigureWindowsMenu): Fix drawing of a disabled
+ (TkWinHandleMenuEvent, DrawMenuEntryArrow): cascade menu arrow. Tk was
+ displaying a disabled cascade menu arrow in black instead of gray. This
+ was caused by a bug in the Win32 code for user drawn menu items. The
+ fix is to avoid telling Windows that the menu item is a cascade type
+ and then draw the gray arrow bitmap on our own. [Patch 865842]
+
+2003-12-27 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/tkWinMenu.c (DrawWindowsSystemBitmap): Fix a strange Win32 bug
+ where the logical coordinates returned by a call to DPtoLP are wrong
+ the first time a menu is posted. This bug manifested itself by drawing
+ the bitmap in the wrong place in a menu. The fix was to pass the newly
+ created DC instead of the DC from the window.
+
+2003-12-26 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/tkWinMenu.c (DrawMenuEntryAccelerator):
+ (DrawMenuEntryLabel): When drawing the label text and accelerator text
+ for a disabled menu entry be sure to draw a 3D highlight. The only
+ exception to this is when a disabled menu entry is highlighted, in that
+ case do not draw a 3D hightlight.
+
+2003-12-26 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/tkWinMenu.c (DrawMenuEntryAccelerator, DrawMenuEntryArrow): Move
+ the unused menu arrow drawing code in DrawMenuEntryAccelerator into a
+ new function named DrawMenuEntryArrow. This makes no functional change
+ but it will make it easier to fix things in the future.
+
+2003-12-25 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/tkWin32Dll.c (DllMain): Add HAVE_NO_SEH blocks in place of __try
+ and __except statements to support gcc builds. This is needed after
+ David's changes on 2003-12-21. [Tcl patch 858493]
+
+2003-12-22 David Gravereaux <davygrvy@pobox.com>
+
+ * win/nmakehlp.c:
+ * win/rules.vc: sync'd to Tcl.
+
+ * win/makefile.vc: Uses new features of nmakehlp to get the version
+ strings from header files without the use of hardcoded values.
+
+ * generic/tk.h: removed the note about having to update makefile.vc
+ when the version changes.
+
+2003-12-22 Joe English <jenglish@users.sourceforge.net>
+
+ * doc/text.n: Fix markup errors (".t" at beginning of line).
+
+2003-12-21 David Gravereaux <davygrvy@pobox.com>
+
+ * generic/tkEvent.c: Added three new functions: TkCreateExitHandler,
+ * generic/tkInt.h: TkDeleteExitHandler, and TkFinalize. This adds an
+ * generic/tkMenu.c: insertion point so Tk's exit handlers can be
+ * generic/tkWindow.c: called on their own from tk85.dll's DllMain for
+ * mac/tkMacButton.c: DLL_PROCESS_DETACH. These are private to the
+ * unix/tkUnixEvent.c: binary and not exported. It is possible the
+ * win/tkWin32Dll.c: Windows OS can unload Tk _prior_ to Tcl under
+ * win/tkWinEmbed.c: some conditions such as ExitProcess(). This
+ * win/tkWinMenu.c: avoids a dangling pointer problem when Tcl does
+ * win/tkWinX.c: Tcl_Finalize after Tk has been unloaded.
+ * win/winMain.c: DllMain's DLL_PROCESS_DETACH now protected with
+ SEH as DeleteWindowsExitProc is causing an exception of its own under
+ some teardown conditions. AT&T assembly syntax has not been added for
+ MinGW yet. [Tcl Patch 858493]
+
+2003-12-20 Joe English <jenglish@users.sourceforge.net>
+
+ * library/bgerror.tcl: Truncate displayed error message if it's too
+ long. [Bug 231251]
+
+2003-12-16 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/rc/wish.exe.manifest: It seems that Windows XP insists on a
+ strict format for the version value. 8.5.a0 or 8.5.0 results in an
+ unloadable executable -- must be 4 numbers.
+
+ * win/tkWinSend.c: Removed some misleading comments [Bug 846134] and
+ disabled the send package until [Bug 858822] is resolved.
+
+2003-12-16 Anton Kovalenko <a_kovalenko@users.sourceforge.net>
+
+ * win/tkWinWm.c (InstallColormaps): Check for TK_ALREADY_DEAD to avoid
+ handling of dead windows.
+
+2003-12-15 David Gravereaux <davygrvy@pobox.com>
+
+ Some silent invalid handle issues discovered with NuMega's
+ BoundsChecker [Patch 699022]
+
+ * win/tkWinMenu.c (ReconfigureWindowsMenu): Only redraw the menubar
+ when a menubar exists.
+
+ * win/tkWinWm.c (UpdateGeometryInfo): wmPtr->wrapper might be NULL. No
+ exception is thrown, but it isn't correct to ignore.
+
+2003-12-15 Benjamin Riefenstahl <Benjamin.Riefenstahl@epost.de>
+
+ * macosx/tkMacOSXKeyboard.c: General cleanup. Add support for [event
+ generate]. [Bug 860454]
+
+2003-12-15 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkText.h:
+ * generic/tkTextBTree.c:
+ * generic/tkTextDisp.c:
+ * generic/tkTextIndex.c: improved documentation in comments to explain
+ how pixel heights are kept track of. Also ensured correct clean-up of
+ elide-state calculation, even with very large numbers of tags. Also
+ provided slightly better updating of cache for totally elided display
+ lines.
+
+2003-12-12 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tkWinEmbed.c (TkWinEmbeddedEventProc) : for loop dereferences
+ containerPtr but can't get to the if (containerPtr == NULL) test due to
+ the unhandled read memory exception for when it really is NULL.
+
+ * win/tkWinX.c (TkWinXInit): Don't restrict InitCommonControlsEx. It's
+ valid on all platforms given IE 3.0+ is installed. As tkWinX.c does set
+ #define _WIN32_IE 0x0300, I guess we can accept IE3 as the lowest
+ denominator and use the version 4.71 features of Comctl32.dll
+
+ * win/rc/wish.exe.manifest: updated version string. This file isn't
+ compiled.
+
+2003-12-10 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * tests/textWind.test: fixed 2 tests so they run on Windows as well as
+ unix, and so their results take account of -padx/-pady settings for the
+ text widget.
+
+2003-12-10 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/CrtImgType.3: Fixed line-transposition error found by Eric
+ Raymond. [Bug 857159]
+
+2003-12-09 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/configure:
+ * unix/tcl.m4: updated OpenBSD build configuration based on [Patch
+ 775246] (cassoff)
+
+2003-12-09 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * win/tkWinWm.c: fix to memory leak on certain error cases.
+
+ * generic/tkTextTag.c: fix reading of freed tag memory, by removing all
+ references to freed tags.
+
+2003-12-08 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * doc/entry.n: clean up usage of 'edition' as a verb.
+
+2003-12-05 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * tests/text.test:
+ * generic/tkText.c: after debate on sf, allow decreasing tab-stops,
+ hence removing any potential backwards incompatibility, even for buggy
+ code. Added new test. [Bug 852949]
+
+ * generic/tkText.h:
+ * generic/tkTextDisp.c:
+ * generic/tkTextTag.c: fix to performance problems in the text widget
+ when inserting lines which wrap thousands of times [Bug 853003]. Note
+ that the text widget must now perform additional calculations (pixel
+ heights) compared to Tk <= 8.4, and so some actions will be slower, by
+ necessity.
+
+2003-12-05 Benjamin Riefenstahl <Benjamin.Riefenstahl@epost.de>
+
+ * win/tkWinFont.c (Tk_MeasureChars): Fix indentation. Fix memory leak.
+ Fix handling of TK_WHOLE_WORDS.
+
+2003-12-04 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkText.c: disallow negative or decreasing tab-stops, which
+ fixes [Bug 852949], but is a
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+ with Tk 8.4.5 or earlier, but only for code which assumed (incorrectly)
+ that tab stops are relative to each other instead of relative to the
+ widget's left edge. Such code will now throw an error instead of doing
+ the wrong thing.
+
+ [[MAINTAINER NOTE: SEE TIP#256]]
+
+ * generic/tkTextDisp.c: restore previous meaning of -[xy]scrollcommand
+ [Bug 852954], and remove unused argument to 'MeasureChars'
+
+ * generic/tkTextWind.c:
+ * generic/tkTextImage.c: better border handling and fixed typos in
+ comments.
+
+ * tests/text.test: tests for negative and decreasing tab stops.
+
+ * doc/text.n: documentation of '-tabs', to clarify Tk's longstanding
+ interpretation of all distances as relative to the left edge of the
+ widget.
+
+ * library/demos/twind.tcl:
+ * library/demos/widget: minor enhancements to text widget demo, showing
+ embedded images, for example.
+
+2003-12-04 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * win/tkWinFont.c: applied [Patch 852669] which fixes [Bug 478568] with
+ certain bold or italic fonts on Windows.
+ * tests/textDisp.test: added test for the font measurement problem.
+
+2003-12-02 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkMenu.c (MenuVarProc): prevent this from triggering while
+ interp is being destroyed.
+
+2003-11-25 Anton Kovalenko <a_kovalenko@users.sourceforge.net>
+
+ * generic/tkPointer.c (Tk_UpdatePointer): corrected targetWinPtr check
+ (line 369) so any pointer event with winPtr==0 is really redirected to
+ the grab or restrict window (if any).
+
+2003-11-21 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkTextDisp.c:
+ * generic/tkText.h:
+ * generic/tkText.c:
+ * tests/textDisp.test: ensure interpolated tabs are at the same
+ location as the equivalent real tabs, by making use of fractional
+ rather than integer pixel calculations.
+
+2003-11-21 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkTextDisp.c: prevent wrapped line height calculations until
+ the widget has actually been given a geometry.
+
+ * tests/textWind.test:
+ * tests/textDisp.test: fix to [Bug 843752], allowing tests to complete
+ cross-platform. Thanks to dgp for extensive testing.
+
+2003-11-21 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/FindPhoto.3: Removed reference to long-gone header file.
+
+2003-11-20 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * win/tkWinSend.c:
+ * win/tkWinSendCom.c: ensure object is not shared before lappend (fix
+ for crash in Windows test suite), and clean up of files to bring them
+ closer to Tcl standards.
+
+2003-11-20 Benjamin Riefenstahl <Benjamin.Riefenstahl@epost.de>
+
+ * macosx/tkMacOSXKeyboard.c: Add PowerBook keycode 0x34 as <Return>.
+
+2003-11-18 Jim Ingham <jingham@apple.com>
+
+ * macosx/tkMacOSXScrlbr.c: Reworking Vince's fix to [Bug 842952]. This
+ version is clearer, and works helps keep the mouse better pinned to the
+ scrollbar. I also removed the glitch where the scrollbar would jump get
+ its middle over the mouse when you first moved it.
+
+2003-11-17 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/constraints.tcl:When running the test suite in a process where
+ * tests/image.test: Tk has been [load]ed, there's no guarantee that
+ * tests/select.test: child processes created by [exec [interpreter]]
+ * tests/unixWm.test: will have Tk in them. Made modifications to
+ * tests/window.test: force a [load] of Tk in those situations.
+
+2003-11-17 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkMenubutton.h: fixed compound menubutton handling like
+ * generic/tkMenubutton.c: *button corrections of 2003-04-25.
+ * mac/tkMacMenubutton.c (TkpDisplayMenuButton):
+ * unix/tkUnixMenubu.c (TkpDisplayMenuButton):
+
+2003-11-16 Don Porter <dgp@users.sourceforge.net>
+
+ * win/makefile.vc: Restored consistency of pkgIndex.tcl file with that
+ generated by Makefile.
+
+2003-11-15 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * macosx/tkMacOSXScrlbr.c: [Bug 842952] correct scrollbar tracking with
+ mouse. Also increased scrollbar resolution for better scrolling in very
+ large text widgets.
+
+ * generic/tkTextDisp.c: cleanup and clarify some comments
+ * doc/text.n: cleanup some of the markup.
+
+2003-11-15 David Gravereaux <davygrvy@pobox.com>
+
+ * win/makefile.vc: Fixes pkgIndex.tcl generation so a symbols build is
+ loaded when Tcl is symbols.
+
+2003-11-15 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkTextDisp.c:
+ * tests/textDisp.test: fixes to one more old Tk [Bug 422411] this time
+ concerning inconsistent tab interpretation. Also fixed an unreported
+ new problem if a single logical line wraps to fill more than the
+ entire display.
+
+ * macosx/tkMacOSXScrlbr.c: fix to [Bug 840978] where the size of the
+ proportional scrollbar was calculated wrongly.
+
+2003-11-14 Joe English <jenglish@users.sourceforge.net>
+
+ * doc/text.n: Fix markup errors.
+
+2003-11-15 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkText.h:
+ * generic/tkText.c:
+ * generic/tkTextDisp.c:
+ * generic/tkTextWind.c:
+ * generic/tkTextTag.c:
+ * tests/textDisp.test: fixes to another pair of old Tk bugs [Bug
+ 220816] (can't scroll horizontally to display all of last character),
+ [Bug 842498] (xview confused on window creation), and more efficiency
+ in tag creation. Added new tests.
+
+2003-11-14 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tkTextDisp.c (TkTextRedrawTag): Get the correct number of
+ lines in the region to be updated. This fix due to Vince Darley.
+ (TkTextUpdateLineMetrics): Return the correct marker value when we know
+ the update loop should terminate. [Bug 837300]
+
+2003-11-13 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * tests/event.test:
+ * library/text.tcl: fixed the text widget portion of [Bug 542199]
+
+2003-11-13 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tkMenuDraw.c (TkPostSubmenu,AdjustMenuCoords): Rewrote to use
+ Tcl_EvalObjv instead of Tcl_VarEval for greater robustness. A side
+ benefit is that this should all be faster now too. [Bug 723856]
+
+2003-11-12 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkText.h:
+ * generic/tkText.c:
+ * generic/tkTextDisp.c:
+ * generic/tkTextIndex.c:
+ * generic/tkTextTag.c:
+ * tests/textTag.test: fixes to two very old Tk bugs [Bug 583286]
+ (focus handling with embedded windows), [Bug 220780] (tag bindings
+ trigger on window borders), and made two more functions static in
+ tkTextDisp.c.
+
+ * library/text.tcl: fixed [Tcl Bug 699642] with double/triple-click
+ insert positioning.
+
+2003-11-11 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/configure:
+ * unix/configure.in: use xft-config instead of pkg-config to determine
+ xft info.
+ * unix/tcl.m4: improve AIX --enable-64bit handling remove
+ -D__NO_STRING_INLINES -D__NO_MATH_INLINES from CFLAGS_OPTIMIZE on
+ Linux. Make default opt -O2 (was -O).
+
+ * generic/tkButton.c (ConfigureButton): abort option processing if the
+ button was deleted. [Bug 824479]
+
+ * generic/tkMenuDraw.c (TkPostSubmenu): add {} around menu name in case
+ it has spaces when calling Tcl_VarEval. This is a hack until this is
+ rewritten for proper Tcl_Obj handling. [Bug 723856]
+
+ * library/tkfbox.tcl (::tk::dialog::file::Update): optimize the
+ dir/files list separation by using the -tails, -directory and -type
+ option of 'glob'. Also passes the glob the -filetypes filters instead
+ of calling string match over each file. [Patch 833819]
+ (::tk::dialog::file::ActivateEnt): allow typing filename into entry
+ when tk_getOpenFile -multiple 1 is specified. [Bug 788069]
+
+ * generic/tkListbox.c (ListboxDeleteSubCmd, ListboxListVarProc): free
+ itemconfig data when removing it from table. [Bug 836483]
+
+ * macosx/tkMacOSXClipboard.c (TkSuspendClipboard, TkSelGetSelection):
+ add unicode clipboard support. [Patch 840107] (senn)
+
+2003-11-10 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/configure:
+ * win/tcl.m4: add necessary ole libs to VC LIBS_GUI line.
+
+ * win/tkWinDraw.c (XFillRectangles): correctly handle the
+ XGCValues.function parameter when filling rectangles. [Bug 820278]
+ [Patch 820282]
+
+ * win/configure:
+ * win/configure.in: define TK_LIB_FLAG, TK_LIB_SPEC,
+ TK_BUILD_LIB_SPEC, TK_STUB_LIB_SPEC, TK_STUB_LIB_PATH, and
+ TK_BUILD_STUB_LIB_PATH for tkConfig.sh [Bug 826614]
+
+ * unix/Makefile.in (SHLIB_LD_FLAGS): include in Makefile as it is used
+ in MAKE_LIB sometimes (ie: AIX-64) [Bug 829686] (jimix)
+
+2003-11-10 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkTextDisp.c: correct yview handling of text widgets
+ containing no vertical pixels at all.
+
+2003-11-08 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tclWinSend.c: Fixed an error returning the registered name.
+
+2003-11-08 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * tests/textDisp.test:
+ * tests/text.test:
+ * generic/tkText.h:
+ * generic/tkTextIndex.c:
+ * generic/tkTextBTree.c:
+ * generic/tkTextDisp.c: fix to another version of [Bug 833627] (crash
+ in tkchat), adding more tests. I believe the handling of nested elide
+ tags of all types is now correct!
+
+2003-11-07 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * tests/textDisp.test:
+ * generic/tkTextDisp.c: fix to another version of [Bug 833627] (crash
+ in tkchat), adding two new tests.
+
+ * generic/tkText.c
+ * generic/tkTextIndex.c
+ * generic/tkTextDisp.c
+ * generic/tkTextWind.c
+ * generic/tkTextImage.c
+ * generic/tkTextTag.c
+ * generic/tkTextMark.c
+ * generic/tkTextBTree.c
+ * generic/tkText.h
+ * doc/text.n
+ * tests/text.test
+ * tests/textWind.test: better handling of 'elide' tags, especially
+ during line layout, counting and forward/backward index movement. Added
+ new tests to ensure correct behaviour with multiple tags of multiple
+ priorities.
+
+2003-11-05 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * library/demos/nl.msg: Dutch messages from Arjen Markus [Patch 836368]
+ * library/demos/widget: Added mechanism to support some l10n of the
+ actual hotkeys used.
+
+2003-11-04 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * tests/textDisp.test:
+ * tests/textWind.test: fix to rest of test suite problems reported in
+ [Bug 833761]. This also has the nice effect that many more tests are
+ now run on Windows.
+
+2003-11-04 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * library/demos/widget (showCode,printCode): Added code to print the
+ source code on Unix and Win, courtesy of Arjen Markus and the Wiki.
+ [Patch 835644]
+
+2003-11-03 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkTextDisp.c
+ * tests/textDisp.test: test and fix to a panic reported in [Bug
+ 833627], with tkchat, and an unused variable [Bug 835010]. Also fixes
+ substantial parts of [Bug 833761]
+
+2003-11-03 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * library/demos/widget, etc.: Made widget demos locate themselves
+ independently of the main Tk library using the new global variable
+ tk_demoDirectory. [Patch 832691, adapted]
+
+ * generic/tkTextDisp.c (TextGetScrollInfoObj): Stop complaints about
+ signed vs. unsigned for the length of strings.
+
+2003-11-01 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * library/msgs/nl.msg: Updated messages from Arjen Markus and Pascal
+ Scheffers. Thanks! [Patch 820519]
+
+2003-10-31 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkImgPhoto.c (ImgPhotoBlendComplexAlpha): OS X uses 32bpp
+ images internally always, so make use of the assumption.
+
+2003-10-31 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ TIP#155 IMPLEMENTATION
+
+ * generic/tkText.c, generic/tkTextIndex.c, generic/tkTextDisp.c
+ * generic/tkTextWind.c, generic/tkTextImage.c, generic/tkTextTag.c
+ * generic/tkTextMark.c, generic/tkTextBTree.c, generic/tkText.h
+ * doc/text.n, tests/text.test, tests/textDisp.test
+ * tests/textImage.test, tests/textIndex.test, tests/textWind.test
+ * library/text.tcl, generic/tkCanvas.c, unix/tkUnixDefault.h
+ * win/tkWinDefault.h, mac/tkMacDefault.h, macosx/tkMacOSXDefault.h
+
+ This adds the 'count' and 'replace' subcommands to the text widget, the
+ '-blockcursor' option, and in particular provides correct, smooth
+ pixel-based scrolling of the widget under all circumstances. See the
+ text.n man page for the complete new documentation. This also fixes
+ [Bugs 559450 778511 779174].
+
+ * generic/tkTextDisp.c
+ * tests/textDisp.test: tests and fix to the promptly reported [Bug
+ 833627]
+
+2003-10-31 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * win/tkWinMenu.c: more correct placing of images in compound menu
+ entries.
+
+2003-10-30 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkImgPhoto.c (ImgPhotoBlendComplexAlpha): add alpha blending
+ for images with partial transparency. Only operates for 15bpp+ display.
+ [Bug 809157]
+
+2003-10-29 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * unix/tkUnixRFont.c: Some cleaning up to get the file more in lines
+ with the general style guidelines. [Bug 832091] Still many comments
+ needed (from someone who knows the code!) for the style guide to be
+ satisfied, so bug still open.
+
+ * library/tkfbox.tcl (IconList_Create,IconList_Add): Added option
+ munging to allow some control of foreground colours on Unix in the same
+ way that you can influence the background. [Bug 795717]
+
+2003-10-28 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/tkUnixFont.c (GetFontAttributes): place extra check for NULL
+ family against bad X servers.
+
+ * win/tkWinImage.c (XGetImageZPixmap): add separate 16bpp XGetImage
+ code to correctly handle 16bpp requests. This appears to never have
+ worked correctly.
+
+ * tests/focusTcl.test (setup1): expand frame size to allow for correct
+ visibility of windows that use larger default fonts.
+
+2003-10-28 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * library/tk.tcl (::tk::PlaceWindow): Added check for empty string
+ first when determining placement strategy. [Bug 819284]
+
+2003-10-23 Jim Ingham <jingham@apple.com>
+
+ * macosx/tkMacOSXDialog.c (NavServicesGetFile): Minor cleanups.
+ (OpenFileFilterProc): Handle FSRef's as well as FSSpec's in the input
+ file. Also convert the FSSpec filename to an C-string before passing to
+ MatchOneFile. [Bug 517600]
+ (MatchOneFile): Require the input filename to be a C-string, not a
+ pascal string.
+
+2003-10-22 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * library/dialog.tcl (tk_dialog): Constrain the dialog to be fairly
+ sensibly sized and placed. [Bug 827535]
+
+2003-10-15 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/tkUnixWm.c, tests/unixWm.test: Delete WM_TRANSIENT_FOR property
+ instead of setting it to None when making a window nontransient [Bug
+ 632816 "cannot remove transient"]
+
+2003-10-14 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/tkUnixPort.h(TkPutImage): changed macro argument names to match
+ function argument names ('dest' and 'src' were swapped, which was
+ confusing) [GPS]
+
+2003-10-14 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/makefile.vc: Applied patches from tcl bug 801467 from
+ * win/winMain.c: Joe Mistachkin
+
+2003-10-12 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkInt.h: move TkGetOptionSpec to stubs intDecls
+ * generic/tkIntDecls.h:
+ * generic/tkInt.decls:
+ * generic/tkStubInit.c:
+ * tkDecls.h: updated with latest genstubs
+ * tkIntPlatDecls.h:
+ * tkIntXlibDecls.h:
+ * tkPlatDecls.h:
+
+ * tests/listbox.test (13.3): correct result size
+ (4.7): correct test for possible window drift [Bug 701931] (dgp)
+
+ * unix/mkLinks:
+ * doc/GetHWND.3: add Tk_AttachHWND docs [Bug 220803]
+
+2003-10-10 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * mac/tkMacButton.c (TkpDisplayButton):
+ * macosx/tkMacOSXButton.c (TkpDisplayButton):
+ * unix/tkUnixButton.c (TkpDisplayButton): correct imageYOffset for
+ buttons with just images.
+
+2003-10-10 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tkObj.c (TkRegisterObjTypes): Register the type of text
+ indexes.
+
+2003-10-09 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinButton.c (TkpDisplayButton): correct imageYOffset for
+ buttons with just images.
+
+2003-10-08 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tcl.m4: Add TIP #150 items to the TEA makefiles.
+ * win/configure:
+ * win/Makefile.in:
+
+ * win/tkWinSend.c: Clean up some warnings from gcc -Wall.
+ * win/tkWinSendCom.c:
+
+2003-10-06 Joe English <jenglish@users.sourceforge.net>
+
+ * library/text.tcl, doc/text.n: Text widget binding for Control-v is
+ now Mac-only, since it conflicts with standard <<Paste>> binding on
+ other platforms. [Bug 605277]
+
+2003-10-06 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/tkStyle.c: Fix double-free in style engine [Bug 798211]
+
+2003-10-06 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/configure:
+ * win/tcl.m4: removed incorrect checks for existence of optimization.
+ TCL_CFG_OPTIMIZED is now defined whenever the user does not build with
+ --enable-symbols.
+
+2003-10-06 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/ConfigWidg.3: Removed reference to Tk_Offset from the NAME
+ section to resolve mkLinks conflict with SetOptions.3 [Bug 404197]
+
+ * unix/configure.in: Reconfigured to use $TCL_PREFIX as the default
+ value of --prefix, and also added warning when a TK_PREFIX value
+ different from TCL_PREFIX is selected, since [package require Tk] fails
+ in that configuration. [Bugs 428627,765642]
+
+ * unix/tcl.m4 (SC_PATH_TCLCONFIG): Corrected search path so that
+ alpha and beta releases of Tcl are not favored. [Bug 608698]
+
+ * unix/configure.in: Added check that version of Tcl header found by
+ configure matches that of the Tk we wish to build. As long as the Tk
+ sources insist on lockstep releases, Tk's configuration should verify
+ that's what we have. [Bug 749088]
+
+ * unix/configure: autoconf (2.57)
+ * unix/mkLinks: make mklinks
+
+2003-10-03 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * library/scale.tcl: Clear bug with chording mouse buttons.
+
+ * library/console.tcl: Avoid including the console in the list of
+ interpreters exposed by [winfo interps].
+
+2003-10-01 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Wish.pbproj/project.pbxproj:
+ * macosx/Makefile: fixed redo prebinding bug when DESTDIR="". Added
+ support for all applicable customizable makefile variables from
+ tcl/macosx/Makefile.
+
+ * macosx/README:
+ * macosx/Wish.pbproj/project.pbxproj: ensure that the versioned wishX.X
+ script works correctly when Tk.framework with multiple versions is
+ present by referring to a copy of 'Wish Shell.app' located in
+ Tk.framework/Versions/X.X/Resources.
+
+2003-09-30 Jim Ingham <jingham@apple.com>
+
+ * macosx/tkMacOSXButton.c (TkpDisplayButton): Use the tk text drawing
+ for checkbuttons & radiobuttons as well as for labels.
+ * macosx/tkMacOSXEvent.c (XSync): New function, need to implement this
+ so drawing will get flushed in "update idletasks".
+ * tkMacOSXPort.h: convert #define of XSync to function def'n.
+
+2003-09-30 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * library/demos/browse: Added suitable [package require] lines
+ * library/demos/hello: to all the Tk demo scripts which are
+ * library/demos/ixset: not run as part of something larger.
+ * library/demos/rmt: [FRQ 815118]
+ * library/demos/rolodex:
+ * library/demos/square:
+ * library/demos/tcolor:
+ * library/demos/timer:
+ * library/demos/widget:
+
+2003-09-30 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * tests/safe.test: Accomodate TIP #150 in the results.
+ * tests/textWind.test: Fix a dependancy on font size in 10.1
+
+2003-09-30 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tkCanvas.c (TkGetStringsFromObjs):
+ * generic/tkPanedWindow.c (PanedWindowWorldChanged): Private functions
+ should be either static or prefixed with 'Tk' (thanks to George Staplin
+ for spotting this.)
+
+2003-09-27 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ TIP#150 IMPLEMENTATION
+
+ * win/makefile.vc: Implementation of TIP #150, "Provide 'send'
+ * win/tkWinSend.c: command for Windows"
+ * win/tkWinSendCom.h:
+ * win/tkWinSendCom.c:
+
+2003-09-26 Benjamin Riefenstahl <Benjamin.Riefenstahl@epost.de>
+
+ * macosx/tkMacOSXWm.c (TkWmStackorderToplevelWrapperMap): Add
+ GetWindowFromPort() [Bug 812415]; make function static.
+
+2003-09-25 Daniel Steffen <das@users.sourceforge.net>
+
+ * library/demos/widget: don't create iconwindow on aqua, but add about
+ menu like on classic.
+ * macosx/Makefile: pass MAKEOVERRIDES to pxbuild.
+ * macosx/tkMacOSXButton.c: added -compound support for bevel buttons.
+
+ * unix/configure:
+ * unix/configure.in:
+ * unix/tkConfig.sh.in: added TK_INCLUDE_SPEC to allow extensions to
+ find installed Tk headers, parallel to TCL_INCLUDE_SPEC. [Bug 777203]
+
+2003-09-18 Chengye Mao <chengye.geo@yahoo.com>
+
+ * generic/tkConsole.c: Fixed memory leak [Bug 802435]
+
+2003-09-18 Peter Spjuth <peter.spjuth@space.se>
+
+ TIP#147 IMPLEMENTATION
+
+ * doc/grid.n:
+ * tests/grid.test:
+ * generic/tkGrid.c: Implementation of TIP#147, "Make Grid's Column/Row
+ Configure Easier".
+
+2003-09-17 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkImage.c: Stopped [image create] from generating an image
+ * tests/image.test: command name that would overwrite an existing
+ command name. Thanks to Michael Schlenker. [Bug 808039].
+
+2003-09-16 Peter Spjuth <peter.spjuth@space.se>
+
+ * tests/grid.test:
+ * generic/tkGrid.c: Reworked a part of grid's geometry computations to
+ handle some tricky cases better. [Bug 792387]
+
+2003-09-05 Joe English <jenglish@users.sourceforge.net>
+
+ * doc/bind.n: Describe %P and %s substitution for Property events.
+ [Bug 577906 "%P substitution not documented"]
+
+2003-09-05 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/wish.1: Implementation of TIPs 137/151.
+ * generic/tkMain.c (Tk_MainEx): Added recognition of the -encoding
+ * tests/main.test: command line option by Tk_MainEx() and
+ thus by wish and any other program built on Tk_MainEx(). [Patch 800139]
+ This is a ***POTENTIAL INCOMPATIBILITY*** only for those C programs
+ that embed Tcl and Tk, build on Tk_MainEx(), and make use of
+ Tk_MainEx's former ability to pass a leading "-encoding" option to
+ interactive shell operations.
+
+2003-08-27 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tkListbox.c (ListboxSelect): Remove unused variable
+ 'increment'. [Bug 664783]
+
+2003-08-25 David Gravereaux <davygrvy@pobox.com>
+
+ * win/makefile.vc: Don't do a string compare on the $(DBGX) variable,
+ use the $(DEBUG) boolean directly. Also, don't try to regen the stubs
+ table if $(TCLSH) doesn't exist.
+
+2003-08-22 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * library/demos/msgbox.tcl: Brought into line with the newer
+ look-and-feel for the demos.
+ * library/demos/widget (addSeeDismiss): Added support for an extra
+ button defined by the caller.
+
+2003-08-21 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tkWin3d.c: Applied Tk patch 791273 from Jeremy Collins which
+ improves the 3d lines for sunken widgets under windows.
+
+2003-08-20 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/demos/widget: Redo code view dialog, use named fonts,
+ * library/demos/arrow.tcl: add basic see/dismiss routine with images
+ * library/demos/bind.tcl: for better look & feel
+ * library/demos/bitmap.tcl:
+ * library/demos/button.tcl:
+ * library/demos/check.tcl:
+ * library/demos/clrpick.tcl:
+ * library/demos/colors.tcl:
+ * library/demos/cscroll.tcl:
+ * library/demos/ctext.tcl:
+ * library/demos/entry1.tcl:
+ * library/demos/entry2.tcl:
+ * library/demos/entry3.tcl:
+ * library/demos/filebox.tcl:
+ * library/demos/floor.tcl:
+ * library/demos/form.tcl:
+ * library/demos/hscale.tcl:
+ * library/demos/icon.tcl:
+ * library/demos/image1.tcl:
+ * library/demos/image2.tcl:
+ * library/demos/items.tcl:
+ * library/demos/label.tcl:
+ * library/demos/labelframe.tcl:
+ * library/demos/menu.tcl:
+ * library/demos/menubu.tcl:
+ * library/demos/paned1.tcl:
+ * library/demos/paned2.tcl:
+ * library/demos/plot.tcl:
+ * library/demos/puzzle.tcl:
+ * library/demos/radio.tcl:
+ * library/demos/ruler.tcl:
+ * library/demos/sayings.tcl:
+ * library/demos/search.tcl:
+ * library/demos/spin.tcl:
+ * library/demos/states.tcl:
+ * library/demos/style.tcl:
+ * library/demos/text.tcl:
+ * library/demos/twind.tcl:
+ * library/demos/unicodeout.tcl:
+ * library/demos/vscale.tcl:
+
+2003-08-20 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tkCanvPs.c (Tk_PostscriptFont): Use Tcl_Obj-based interfaces
+ for working with user-supplied font maps.
+
+2003-08-19 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/tkPanedWindow.c (PanedWindowWorldChanged): Set window
+ background from the -background resource. Fixes [Bug 791500
+ "PanedWindow refresh glitches on X"]
+
+2003-08-19 Joe English <jenglish@users.sourceforge.net>
+
+ * doc/bind.n: Added more information on event types and details [FRQ
+ 523593 "bind(n) manpage needs more detail"]
+
+2003-08-18 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/configure: Regen.
+ * win/tcl.m4: Update from Tcl to fix Tcl bug 781109.
+
+2003-08-15 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tkImgPhoto.c (ImgPhotoCmd): Faster color data parsing code
+ for the [$photo put] subcommand. Now doesn't do everything through the
+ pre-8.0 list handling routines!
+
+2003-08-14 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * unix/tkUnixButton.c (TkpDisplayButton): Stopped accesses to NULL
+ * unix/tkUnixMenu.c (TkpDrawMenuEntry): pointers that crashed tests.
+
+ TIP #109 IMPLEMENTATION FROM Brian Griffin <bgriffin@model.com>
+ * unix/tkUnixButton.c (TkpDrawCheckIndicator, TkpDisplayButton):
+ * unix/tkUnixMenu.c (DrawMenuEntryIndicator, TkpDrawMenuEntry):
+ Much improved display of checkbuttons and radiobuttons on UNIX/X.
+
+2003-08-13 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * library/scale.tcl: Fix for [Bug 787065] for Button-2 press.
+ * tests/scale.test: Added test for this bug.
+
+2003-08-12 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXMenu.c: fixed C99'ism that breaks gcc 2.95.
+
+2003-07-28 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tkWinDialog.c: Applied patch from [Bug 611615] which fixes a
+ problem with double clicks in file dialogs falling through to the
+ window underneath in win32.
+
+ * library/panedwindow.tcl: Apply patch from [Bug 778893] to make the
+ panedwindow -opaqueresize option work as per the docs.
+
+ * library/tk.tcl: Apply fix for [Bug 778840] for window placement when
+ using multiple desktops on windows.
+
+2003-07-24 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tkWinCursor.c: Fix for [Bug 776646] for a native hand2 and fleur
+ (move) cursor under win.
+ * tests/cursor.test: Check that documented cursors are available.
+
+2003-07-20 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/buildTkConfig.tcl: fix to TK_BUILD_* ref generation broken by
+ changes to tcl buildsystem.
+
+2003-07-19 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tkWinCursor.c (TkGetCursorByName): Fix bug 420510 to provide
+ consistency between unix and windows -cursor option.
+
+ * library/scale.tcl: Fix for bug 706765 to correctly handle the
+ -sliderrelief option while moving the thumb.
+
+2003-07-18 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/tkUnixFont.c (Tk_DrawChars): do not make XGetGeometry call that
+ prevents overwidth lines as it requires a roundtrip call to the X
+ server for every string drawn. Hard-code max width to 32768 until a
+ better solution to get max width is made.
+
+ * library/panedwindow.tcl: use widget-specific Priv slots for pwAfterId
+ and panecursor items to correctly handle cursor changes with adjacant
+ panedwindows.
+
+ * generic/tkEvent.c (Tk_HandleEvent): correct XCreateIC call for
+ TK_XIM_SPOT usage. [Bug 742660] (takahashi)
+
+ * win/tkWinDialog.c: doubled the TK_MULTI_MAX_PATH value to ~10K. This
+ is a short-term solution until the -multiple option is extended. [Bug
+ 641261]
+
+2003-07-18 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkWindow.c:
+ * macosx/tkMacOSXDialog.c: added native tk_messageBox command,
+ (Tk_MessageBoxObjCmd) for MacOS X platform.
+
+ * macosx/tkMacOSXMenu.c: corrected encoding conversion for torn-off
+ menu entries (but many other display problems still exist with these)
+
+ * macosx/tkMacOSXMouseEvent.c: improved handling of events in the
+ presence of grabs, particularly activation events.
+
+2003-07-18 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/panedwindow.test (panedwindow-30.2):
+ * generic/tkPanedWindow.c (Tk_PanedWindowObjCmd): Ensure that we can
+ share GCs between a panedwindow and its sash proxy, even if the
+ panedwindow is in a toplevel with a different visual. [Bug 702230]
+
+2003-07-17 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Makefile: Changes for new tcl buildsystem.
+
+ * macosx/Wish.pbproj/jingham.pbxuser:
+ * macosx/Wish.pbproj/project.pbxproj:
+ Changes for new tcl buildsystem. Changed build to include tk specific
+ html help in Tk.framework instead of Tcl.framework. Set default SYMROOT
+ in target options to simplify setting up PB (manually setting common
+ build folder for tcl & tk no longer needed).
+
+ * macosx/README: Updated info for changes to buildsystem, html help
+ location and PB setup.
+
+2003-07-17 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/photo.n: [$photo put] has been able to take rectangles of pixel
+ colours, specified as lists of lists, for years. Now this is a
+ documented feature. [Bug 728952]
+
+ * doc/panedwindow.n: Removed warning invalidated by fix from Bug
+ 738143. [Bug 747814]
+
+ * generic/tkImgPhoto.c (ImgPhotoCmd): Rewrote subcommand processing to
+ never jump to the end of the switch. I find that confusing as I can't
+ see whether there's processing still to be done from a quick glance at
+ the code, unlike with a direct return. [Bug 771988]
+ (ImgPhotoCmd, ImgPhotoSetSize, ImgPhotoInstanceSetSize): Try harder to
+ avoid zero-length mallocs()... [Bug 404421]
+
+2003-07-16 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkPack.c (ConfigureSlaves): silence compiler warning
+ [Bug 771982]
+
+2003-07-16 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinImage.c (XGetImage): correct init of biSizeImage in bitmap
+ header. [Bug 703697] (cap)
+
+2003-07-17 Peter Spjuth <peter.spjuth@space.se>
+
+ * tests/frame.test:
+ * generic/tkFrame.c (CreateFrame): Make sure all options can be set to
+ their default value. [Bug 697652]
+
+2003-07-16 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkPanedWindow.c (ArrangePanes): Ensure that the last pane
+ * tests/panedwindow.test: shrinks instead of being clipped when resized
+ below the reqsize. [Bug 748277] (spjuth)
+
+ * generic/tkWindow.c (Initialize): do not free uninit'ed dstring.
+ [Bug 755906] (mistachkin)
+
+2003-07-09 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/send.test: Strengthened constraints to stop accidental smashing
+ of Xserver access; some systems (*ahem* mine *ahem*) require
+ xhost-style security for all use... :^/
+
+2003-07-07 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkTextDisp.c (DisplayText): correct use of textPtr data with
+ respect to Tcl_Release time. [Bug 767009]
+
+2003-07-07 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tkImage.c (TkDeleteAllImages,etc.): Stopped the deleting of
+ hash entries from a table that has just been deleted by this function
+ when some images are Tcl_Preserve()d... [Bug 749353]
+
+2003-07-03 Jim Ingham <jingham@apple.com>
+
+ * macosx/tkMacOSXColor.c (GetControlPartColor): Use the ThemeBrushes to
+ get the control text color for buttons.
+
+2003-07-02 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/tkUnixEvent.c (TkpCloseDisplay): Don't test for XCloseIM bug
+ when the XFree86 version is newer than 4.0 since the layout of the XIM
+ structure has changed. The check is not needed for newer XFree86
+ releases since the bug we are checking for was fixed in the 4.2.99.2
+ release. [Bug 755530]
+
+2003-06-26 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * library/menu.tcl: workaround problem on some Windows systems by
+ trying to avoid posting a menu offscreen.
+
+2003-06-09 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/tkUnixRFont.c: fix for [Bug 751553] "Xft: [font configure] does
+ not update in-use fonts". Fixed TkpGetSubFonts() to return information
+ about all subfonts, not just the first one.
+
+2003-06-01 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/configure.in: BUGFIX, --enable-xft test was broken.
+ * unix/configure: regen
+
+2003-05-31 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/tkUnixRFont.c (InitFont): Fill in TkFontAttributes from pattern
+ returned from GetFont (actual font) instead of the query pattern
+ (requested font).
+
+2003-05-31 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/tkUnixRFont.c: New file
+ * unix/tkUnixDefault.h: Use different default fonts if HAVE_XFT
+ * unix/Makefile.in:
+ * unix/configure.in: Add --enable-xft flag
+ * unix/configure: regen
+ Experimental support for antialiased text under X11 [Patch 535541]
+
+2003-05-30 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkMenu.c
+ * generic/tkMenu.h
+ * generic/tkMenuDraw.c:
+ * tests/menu.test: fixed complex bug in menu clone cleanup [Bug 465324]
+ and removed 'knownBug' from a test.
+
+2003-05-29 Joe English <jenglish@users.sourceforge.net>
+
+ * doc/text.n: Fixed markup errors.
+
+2003-05-28 Miguel Bañón <bagnonm@users.sourceforge.net>
+
+ * library/msgs/cs.msg: Updated messages from wohnivec@iol.cz
+
+2003-05-27 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkText.c
+ * generic/tkTextTag.c
+ * generic/tkTextDisp.c
+ * generic/tkText.h: refactoring of text widget cleanup code to ensure
+ all resources are freed. [Bug 741179]
+
+ * library/tearoff.tcl: ensure torn-off menus do not appear underneath
+ the MacOS/MacOS X main menu bar.
+
+2003-05-23 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/mkLinks: Set the var S to "" at the top of the file to avoid
+ error when user has set S to something. [Bug 739833]
+
+2003-05-21 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tkPanedWindow.c (PanedWindowReqProc): Thanks very much to
+ Eric Boudaillier for making panes resize correctly! [Bug 738143]
+
+ * generic/tkText.c (TextSearchCmd): Forwards and backwards aren't the
+ same. [Bug 740558] Also edited SearchCore to get it closer to the
+ Engineering Manual style guidelines.
+
+2003-05-19 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/textImage.test: Fixed faults in option parsing and made
+ * tests/text.test: tests conformant. [Bug 739965]
+ * generic/tkText.c (TextSearchCmd):
+
+ * library/demos/en.msg: Base catalog for the widget demo.
+ * library/demos/widget: Added message-catalog support.
+ * library/console.tcl: Reworked to use tk::AmpMenuArgs and be more "in
+ style".
+ * library/tk.tcl (tk::AmpMenuArgs): New procedure for doing
+ tk::AmpWidget-like processing for menus.
+
+ * generic/tkTextMark.c: Removed complaints about signed vs.
+ * generic/tkTextImage.c: unsigned in arguments to strncmp() by
+ * generic/tkText.c: using Tcl_GetIndexFromObj() more.
+
+2003-05-19 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ TIP#113 IMPLEMENTATION
+
+ * doc/text.n
+ * generic/tkCanvas.c
+ * generic/tkInt.h
+ * generic/tkTest.c
+ * generic/tkText.c
+ * generic/tkText.h
+ * generic/tkTextBTree.c
+ * generic/tkTextDisp.c
+ * generic/tkTextImage.c
+ * generic/tkTextIndex.c
+ * generic/tkTextMark.c
+ * generic/tkTextTag.c
+ * generic/tkTextWind.c
+ * generic/tkUndo.c
+ * generic/tkUndo.h
+ * generic/tkWindow.c
+ * library/text.tcl
+ * tests/text.test
+ * tests/textIndex.test
+ * tests/textMark.test
+ * tests/textTag.test
+ * tests/textWind.test: This adds multi-line searching and '-all'
+ searching to the text widget. In addition the changes contain a
+ complete 'objectification' of the text widget. Includes documentation
+ and new tests.
+
+2003-05-19 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Wish.pbproj/project.pbxproj: changed tkConfig.sh location in
+ versioned framework subdirectories to be identical to location in
+ framework toplevel; fixed stub library symbolic links to be tk version
+ specific.
+
+2003-05-15 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/tkUnixFont.c: use gb2312-raw as the alias for gb2312* charset
+ fonts. gb2312.enc was made to be euc-cn for Tcl because that is what
+ is most often meant, but X really wants the original (-raw) gb2312
+ encoding. [Bug 557030]
+
+2003-05-14 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/msgs/fr.msg: updated msg catalog. [Bug 737790] (zolli)
+
+2003-05-13 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * win/makefile.vc: fix to installation of winhelp into path containing
+ a space (Bug 693512)
+
+2003-05-13 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXInit.c (TkpInit): use new versioned bundle resource
+ API to get tk runtime library for TK_VERSION. [Bug 736774]
+
+2003-05-10 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkCanvPoly.c (PolygonToPostscript):
+ * tests/canvPs.test: correct crash when generating postscript for a
+ single-line polygon (point) with no color. [Bug 734498] (wilm)
+
+2003-05-10 Jim Ingham <jingham@apple.com>
+
+ * macosx/tkMacOSXClipboard.c (TkSelGetSelection): Convert '\r' to '\n'
+ on the way into Tcl.
+
+2003-05-08 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/image.test (image-15.1): Test to ensure that widgets pick up
+ image information even if the image is deleted and recreated.
+
+ * generic/tkImage.c (Tk_ImageObjCmd): Use the ImageMaster's deleted
+ flag to stop deleted images from showing up in the various [image *]
+ operations. Can't delete directly from the table because that makes us
+ lose the information about what widgets want to use the image. [Bug
+ 634864]
+
+2003-04-30 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * macosx/tkMacOSXButton.c (TkpDisplayButton): correct typo for
+ stippleGC [Bug 730124].
+
+2003-04-25 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkButton.h: Rewrote the handling of
+ * generic/tkButton.c (TkButtonWorldChanged): compound *buttons to
+ * mac/tkMacButton.c (TkpDisplayButton): correctly display mixture
+ * macosx/tkMacOSXButton.c (TkpDisplayButton): of disabledfg,
+ * unix/tkUnixButton.c (TkpDisplayButton): selectcolor, indicator,
+ * win/tkWinButton.c (TkpDisplayButton): etc. *buttons will now
+ only stipple the image, unless no disabledfg is given, in which case it
+ will stipple the whole button.
+
+ * library/bgerror.tcl: make bgerror dialog topmost on Windows to
+ prevent it being covered by other windows.
+
+ * unix/tkUnixButton.c (TkpDisplayButton): Use the normalTextGc when
+ * win/tkWinButton.c (TkpDisplayButton): displaying disabled text that
+ have images, as they get a gray50 stipple as well and the disabledGc is
+ not set up correctly for font drawing. [Bug 477740]
+
+2003-04-18 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/configure: regen
+ * win/configure.in (SHELL): force it to /bin/sh as autoconf 2.5x uses
+ /bin/bash, which can fail to find exes in the path (ie: lib).
+
+ * generic/tkCanvBmap.c: s/CreateBitmap/TkcCreateBitmap as Windows has a
+ CreateBitmap function already.
+
+ * generic/tkCursor.c: s/GetCursor/TkcGetCursor as Windows has a
+ GetCursor func already, which causes compiler warnings.
+
+2003-04-14 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/tkWinMenu.c (TkpInitializeMenuBindings): Rename the private menu
+ helper cmd from tk::tkWinMenuKey to tk::WinMenuKey. [Bug 721514]
+
+2003-04-14 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tkBind.c (TkpGetBindingXEvent): Add helper method that can be
+ used to query the XEvent* for the currently executing binding.
+ * generic/tkInt.h: Declare TkpGetBindingXEvent.
+ * win/tkWinMenu.c (MenuKeyBindProc, TkWinMenuKeyObjCmd)
+ (TkpInitializeMenuBindings): Rename MenuKeyBindProc to
+ TkWinMenuKeyObjCmd and convert it into a Tcl command named
+ tk::tkWinMenuKey. Bind keyboard accelerator actions to this Tcl command
+ instead of using a native C binding. This makes it possible to extend
+ the existing binding with Tcl code and makes the Windows version work
+ just like the unix version.
+
+2003-04-04 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/Makefile.in: Subst TCL_LIBS instead of DL_LIBS and MATH_LIBS.
+ * unix/configure: Regen.
+ * unix/configure.in: Remove SC_ENABLE_THREADS invocation. Thread
+ support in an extension should be automatic when Tcl is compiled with
+ thread support. Add AC_DEFINE calls to set TCL_THREADS, _REENTRANT, and
+ _THREAD_SAFE since this was done in SC_ENABLE_THREADS. Remove socket
+ and math lib checks since these are already done in the Tcl configure
+ script.
+ * unix/tcl.m4: Update from Tcl to get TCL_LIBS fix. This fixes [Bug
+ 597847] which was caused by improper linking.
+ * unix/tkConfig.sh.in: Subst TCL_LIBS instead of MATH_LIBS and DL_LIBS.
+ [Bug 597847]
+
+2003-04-02 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/configure: Regen.
+ * win/configure.in: Set stub lib flag based on new LIBFLAGSUFFIX
+ variable.
+ * win/tcl.m4: Update from Tcl to get new LIBFLAGSUFFIX variable.
+
+2003-04-02 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/configure: Regen.
+ * win/configure.in: Don't set TCL_DLL_FILE, TCL_LIB_FILE,
+ TCL_STUB_LIB_FILE, TCL_STUB_LIB_FLAG, and TCL_BUILD_STUB_LIB_SPEC.
+ These variables are already set in tclConfig.sh. Don't subst vars that
+ are either not used, or already covered by a subst in
+ SC_LOAD_TCLCONFIG. [Bug 691908]
+
+2003-04-01 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure: Regen.
+ * unix/tcl.m4: Update from Tcl.
+
+2003-04-01 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/all.tcl: Made better use of a common -loadfile
+ * tests/constraints.tcl: to hold definitions common to all test
+ * tests/*.test: files.
+
+2003-03-27 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure: Regen.
+ * unix/tcl.m4: Update from Tcl.
+
+2003-03-26 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure: Regen.
+ * unix/tcl.m4: Update from Tcl to get BeOS changes.
+
+2003-03-22 Kevin Kenny <kennykb@acm.org>
+
+ * win/makefile.vc:
+ * win/rules.vc: Corrected several problems that prevented OPTS=symbols
+ from building properly. [Patch 707792] Thanks to Joe Mistachkin for the
+ fixes.
+
+2003-03-20 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXApplication.r (removed):
+ * macosx/tkMacOSXLibrary.r (removed):
+ * macosx/tkMacOSXResource.r (removed):
+ * macosx/Wish.pbproj/project.pbxproj:
+ * macosx/tkAboutDlg.r: updated copyrights, cleaned up about box,
+ removed obsolete unused resource files.
+
+ * macosx/buildTkConfig.tcl: TK_DEFS space fix.
+
+2003-03-18 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/tkConfig.sh.in: Add TK_DLL_FILE entry to mirror the TCL_DLL_FILE
+ entry in tclConfig.sh. [Patch 694271]
+
+2003-03-18 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/configure: Regen.
+ * win/configure.in: Don't run the AC_CYGWIN macro since it uses
+ AC_CANONICAL_HOST under autoconf 2.5X. Just check to see if __CYGWIN__
+ is defined by the compiler and set the ac_cv_cygwin variable based on
+ that. [Tcl Bug 705912]
+
+2003-03-18 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/unixWm.test (unixWm-41.2): Corrected typo in 2003-03-13 commit.
+ Thanks Larry Virden. [Bug 705567]
+
+2003-03-18 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Wish.pbproj/project.pbxproj:
+ * macosx/Makefile:
+ * macosx/README: added support for giving 'make' the location of
+ Tcl.framework and tclsh to build and link against.
+
+ * macosx/tkMacOSXXStubs.c: fixed crash in [winfo server].
+
+2003-03-13 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/unixWm.test: Constrained all tests older than revision 1.21 to
+ run only on Unix. Alternative approach did not match maintainer habits.
+ * tests/spinbox.test (spinbox-17.4): Avoid long failure message.
+
+2003-03-13 Mo DeJong <mdejong@users.sourceforge.net>
+
+ Require autoconf 2.57 or newer, see TIP 34 for a detailed explanation
+ of why this is good. This will no doubt break the build on some
+ platforms, let the flaming begin.
+
+ * unix/configure: Regen with autoconf 2.57.
+ * unix/configure.in: Require autoconf 2.57.
+ * unix/tcl.m4: Update from Tcl.
+ * win/configure: Regen with autoconf 2.57.
+ * win/configure.in: Require autoconf 2.57.
+ * win/tcl.m4: Update from Tcl.
+
+2003-03-12 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * library/msgbox.tcl (tk::MessageBox): Stopped message box buttons from
+ getting very wide, and added some compensatory space so that the
+ smaller buttons still look nice (well, to me). [Bug 701812]
+
+2003-03-11 Jim Ingham <jingham@apple.com>
+
+ * macosx/tkMacOSXMenu.c (EventuallyInvokeMenu): New function, used to
+ invoke menu commands at idle time.
+ (TkMacOSXDispatchMenuEvent): Don't immediately dispatch menu commands,
+ wait till the idle loop to do so. This is more like what is done on
+ Windows, and avoids the crash from destroying a menu in it's command.
+
+ * macosx/tkMacOSXHLEvents.c (ReallyKillMe): Don't force the shell to
+ exit. According to the OS X HI guidelines, it should be possible to
+ cancel an attempt to quit, and if we force the kill, here, it would not
+ be possible to implement this.
+
+2003-03-11 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * tests/unixWm.test: Add the testwrapper constraint to tests that
+ depend on the testwrapper command. These tests should not be run under
+ Windows for example.
+
+2003-03-11 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * doc/wm.n (minimize, maximize): Remove claim that the resizable
+ command keeps scripts from changing the size of windows since it is not
+ true. The resizable command only applies to user sizing via user
+ interaction.
+ * tests/unixWm.test: Replace broken tests with the nonPortable
+ constraint with new tests for maxsize and minsize options. These tests
+ verify that setting the minsize and maxsize will resize the window if
+ needed, and that the wm hints will be updated with the new sizes.
+ * tests/wm.test: Add an exhaustive set of tests for the wm maxsize and
+ wm minsize commands. These tests verify that setting the minsize and
+ maxsize will resize the window if needed. These tests have only been
+ run under Win98 and Window Maker under Linux, so further tweaking may
+ be needed for other systems.
+ * unix/tkUnixWm.c (UpdateGeometryInfo, UpdateSizeHints): Fixup
+ comments and initialization for the minWidth, minHeight, maxWidth,
+ maxHeight, width, and height members of the WmInfo struct. Check to
+ ensure that a new toplevel window size is not larger than the maxsize
+ or smaller than the minsize when updating the geometry at idle time.
+ Pass new width and height values to the UpdateSizeHints method so that
+ it can properly set the window min and max sizes for a window that
+ cannot be resized by the user. This fixes a bug where the window
+ resizes back to the original size when the user clicks on the window
+ border.
+ * win/tkWinWm.c (UpdateGeometryInfo): Fixup comments and
+ initialization for the minWidth, minHeight, maxWidth, maxHeight, width,
+ and height members of the WmInfo struct. Check to ensure that a new
+ toplevel window size is not larger than the maxsize or smaller than the
+ minsize when updating the geometry at idle time. [Patch 568861]
+
+2003-03-11 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tkGrid.c (GridStructureProc, ConfigureSlaves): Check for a
+ NULL masterPtr and slavePtr in the GridStructureProc code to ensure
+ that a Gridder created before some error condition is ignored when it
+ comes to geometry calculations. This approach closely matches the pack
+ implementation. Keep track of a -in argument to a grid command in order
+ to detect the case of an already gridded widget that wants to change
+ some options. The previous implementation could make repeated and
+ unnecessary calls to Tk_ManageGeometry. Replace use of "parent" with
+ "master" in comments throughout the file.
+ * generic/tkPack.c (PackStructureProc): Check for a NULL masterPtr
+ before other checks so that a slave created under certain error
+ conditions is cleaned up properly. Replace use of "parent" with
+ "master" in comments throughout the file.
+ * generic/tkPlace.c (CreateSlave, ConfigureSlave, SlaveStructureProc):
+ Don't call Tk_ManageGeometry in CreateSlave since this was causing
+ incorrect results in some error cases. Rework the ConfigureSlave method
+ so that slave setup is done in one place. The call to Tk_ManageGeometry
+ was added to the one place where a slave is setup. When a slave is
+ configured but the master is not changed, simply goto the
+ scheduleLayout label. Check for a NULL master in SlaveStructureProc for
+ the sake of readability.
+ * tests/grid.test:
+ * tests/pack.test:
+ * tests/place.test: Add test to check that a winfo manager call does
+ not return incorrect results after an error condition is hit. [Patch
+ 693063]
+
+2003-03-11 Kevin Kenny <kennykb@users.sourceforge.net>
+
+ * win/makefile.vc: Backported the code that makes the makefile build
+ pkgIndex.tcl as part of the install step.
+
+2003-03-07 Jim Ingham <jingham@apple.com>
+
+ * macosx/tkMacOSXMenus.c (TkMacOSXInitMenus): No longer need to call
+ TkMacOSXSetHelpMenuItemCount.
+ * macosx/tkMacOSXMenu.c (TkMacOSXHelpMenuItemCount): Stub out since it
+ is no longer need (but is in the stubs table...).
+ (TkMacOSXDispatchMenuEvent): Get the number of system help menu items
+ from HMGetHelpMenu.
+ (ReconfigureMacintoshMenu): Ditto.
+ (TkpDestroyMenu): Ditto.
+
+2003-03-06 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ TIP#116 IMPLEMENTATION
+
+ * doc/FindPhoto.3: Documentation of the photo API changes due to
+ TIP#116
+
+ * generic/tkImgPhoto.c (Tk_PhotoExpand, Tk_PhotoPutBlock)
+ (Tk_PhotoPutZoomedBlock, Tk_PhotoSetSize): Added interp argument to
+ these functions and made them return a standard Tcl result, with error
+ indicating memory allocation failure instead of panic()ing.
+ [See TIP #116 at http://purl.org/tcl/tip/116.html for discussion.]
+ Each of these functions has also acquired a backward-compatability
+ variant as well, named with a _Panic suffix.
+ * generic.tk.decls: New API in new slots, back-compat API in old ones.
+ * generic/tk.h (USE_PANIC_ON_PHOTO_ALLOC_FAILURE): Allow users to
+ define this symbol to get the old 8.4 photo image API, including
+ panic() calls when things go wrong.
+
+ * generic/tkImgPhoto.c (ImgPhotoCmd): Adjusted to use the new API
+ * generic/tkImgGIF.c (FileReadGIF): discussed above.
+ * generic/tkImgPPM.c (FileReadPPM):
+
+2003-03-05 David Gravereaux <davygrvy@pobox.com>
+
+ * win/rules.vc: updated default tcl version to 8.5.
+
+2003-03-04 Don Porter <dgp@users.sf.net>
+
+ * README: Bumped version number of Tk to
+ * generic/tk.h: 8.5a0.
+ * library/tk.tcl:
+ * mac/README:
+ * macosx/Wish.pbproj/project.pbxproj:
+ * unix/README:
+ * unix/configure.in:
+ * unix/tk.spec:
+ * win/README:
+ * win/configure.in:
+ * win/makefile.vc:
+ * win/tcl.m4:
+
+ * unix/configure: autoconf
+ * win/configure:
+
+2003-03-03 Jeff Hobbs <jeffh@ActiveState.com>
+
+ *** 8.4.2 TAGGED FOR RELEASE ***
+
+2003-02-28 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/bind.test (bind-16.44):
+ * generic/tkBind.c (ExpandPercents): Only allow events to see those
+ expansions that are actually valid for them, and force the substitution
+ of the rest as "??". This stops some crashes on Windows and gets rid of
+ bogus values everywhere. [Bug 612110]
+
+2003-02-26 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * macosx/README: correct 8.4.3 refs to 8.4.2.
+
+ * unix/README: replace version refs with version-agnostic wording.
+
+2003-02-25 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinInt.h:
+ * win/tkWinDraw.c:
+ * win/tkWinFont.c (Tk_DrawChars): add support for simple XOR text
+ drawing on Windows. [Patch 685388] (martin)
+
+ * generic/tkMenu.c (TkMenuCleanup): make sure to reset static
+ menusInitialized on finalize. [Bug 548729]
+
+2003-02-25 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXHLEvents.c: fixed conversion of apple event parameters
+ to posix style path names. [Bug 621672] (steffen, Benjamin Riefenstahl)
+
+ * macosx/tkMacOSXDialog.c:
+ * macosx/tkMacOSXWm.c:
+ * macosx/Wish.pbproj/project.pbxproj:
+ * macosx/tkMacOSXUtil.c (removed):
+ * macosx/tkMacOSXUtil.h (removed): removed all references to
+ tkMacOSXUtil.{c,h}, made obsolete by the patch above. [Bug 621672]
+
+2003-02-24 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/tkUnixFont.c (CreateClosestFont, CanUseFallback): use the first
+ best font match in user font path. [Bug 647497] (dal zotto)
+
+ * generic/tkListbox.c (ListboxSelectionSubCmd):
+ * tests/listbox.test: Allow 'selection includes' to respond when
+ disabled (but only 'includes'). [Bug 632514]
+
+ * unix/tkUnixButton.c (TkpDisplayButton): Correct visual display of
+ disabled check/radiobutton to be more distinctive on unix.
+ * tests/unixButton.test: [Bug 669595] (hintermayer)
+
+ * doc/panedwindow.n: clarified the need to use 'update idle' when
+ adding unmapped windows. Needs further examination. [Bug 605105]
+
+ * generic/tkEntry.c (SpinboxWidgetObjCmd, EntryWidgetObjCmd):
+ * tests/entry.test: return 1 if selection is present even if
+ * tests/spinbox.test: entry/spinbox is disabled, as selection get will
+ still return the selection (although selection still ignore modify
+ requests when entry/spinbox is disabled). [Bug 637828]
+
+2003-02-24 Benjamin Riefenstahl <Benjamin.Riefenstahl@epost.de>
+
+ * tkMacOSXDialog.c (NavServicesGetFile): Fix bug with
+ kNavCtlSetSelection - control data should be a pointer not a handle.
+
+2003-02-21 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * library/clrpick.tcl (color::BuildDialog):
+ * library/msgbox.tcl (MessageBox): Yet more places that did complex
+ and fragile width calculations instead of using grid, though with these
+ it is the -uniform option that saves the day.
+
+ * library/tkfbox.tcl (file::Create): This procedure was really very
+ crufty in how it went about creating the GUI. It is far easier and more
+ robust to use the grid geometry manager than it is to tune the results
+ of pack with tweaks to -width. [Bug 673722]
+
+ * library/comdlg.tcl (FDGetFileTypes): Set an upper limit on how long a
+ file type item description string can get due to appending of types.
+ [Bug 617392]
+
+ * tests/panedwindow.test (panedwindow-30.1):
+ * generic/tkPanedWindow.c (DisplayPanedWindow, DisplayProxyWindow):
+ Use the window's depth, not the screen's default depth. [Bug 671122]
+
+2003-02-20 Daniel Steffen <das@users.sourceforge.net>
+
+ * library/console.tcl: (aqua & macintosh) added missing <Cmd-q> binding
+ for corresponding Quit menu item shortcut.
+
+ * macosx/README: updated instructions for embedded build, added various
+ improvements by Russell Owen.
+
+ * unix/tcl.m4: update from Tcl.
+ * unix/configure: regen.
+
+2003-02-20 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinScrlbr.c (UpdateScrollbar): use SIF_DISABLENOSCROLL to
+ "disable" scrollbar when on Windows when there is nothing to scroll.
+ This is Windows style, and fixes [Bug 624116].
+
+ * tests/panedwindow.test:
+ * generic/tkPanedWindow.c (ValidSashIndex): corrected to note that 2
+ panes must exist before any one sash does. [tcllib Bug 689258]
+
+2003-02-20 Peter Spjuth <peter.spjuth@space.se>
+
+ * tests/panedwindow.test:
+ * generic/tkPanedWindow.c: Fixed calculation of the last slave's size
+ when increasing the size of the panedwindow. [Bug 689099]
+
+2003-02-20 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tkImgGIF.c (GetDataBlock): Removed pointless static variable
+ ZeroDataBlock [Bug 664788]
+
+ * unix/tkUnixFont.c (CanUseFallback): Added argument, passed through
+ from callers to FindSubFontForChar(), so that pointers into the old
+ subfont table to be updated when that table is reallocated, avoiding a
+ (sometimes fatal) FMR. [Bugs 618872, 689357]
+
+2003-02-19 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXKeyEvent.c: fix for uninitialized var warning.
+
+2003-02-19 Jim Ingham <jingham@apple.com>
+
+ * macosx/tkMacOSXMouseEvents.c (GeneratePollingEvents): In the case
+ where there was a capture window, we were sending the events to the
+ capture window. But the capture window (return value or
+ TkMacOSXGetCapture) is always a toplevel. So this is wrong in the case
+ that the Event's toplevel IS the capture window - in which case the
+ event should go to the subwindow most closely containing the event.
+
+2003-02-19 Benjamin Riefenstahl <Benjamin.Riefenstahl@epost.de>
+ and Jim Ingham <jingham@apple.com>
+
+ This patch changes the default Tk behavior so that events are by
+ default routed to the standard event handlers after Tk has looked at
+ them.
+
+ * macosx/tkMacOSXEvent.h: Rename "handledByTk" into "stopProcessing".
+
+ * macosx/tkMacOSXEvent.c: Update erroneous comments and remove unused
+ includes.
+ (TkMacOSXProcessAppleEvent): Don't declare events handled that we did
+ not even look at.
+ (TkMacOSXProcessEvent): Add a comment on policy for "stopProcessing".
+ (TkMacOSXProcessEvent): Remove "handling" of events that are not our
+ business.
+ (TkMacOSXProcessEvent): Rename "handledByTk" into "stopProcessing".
+ (ReceiveAndProcessEvent): Ditto.
+ (ReceiveAndProcessEvent): Tune error production of message.
+
+ * macosx/tkMacOSXKeyEvent.c (TkMacOSXProcessKeyboardEvent): Rename
+ "handledByTk" into "stopProcessing".
+
+ * macosx/tkMacOSXWindowEvent.c: Ditto.
+
+ * macosx/tkMacOSXMouseEvent.c: Remove setting of "handledByTk".
+ (TkMacOSXProcessMouseEvent): Handle clicks in the "traffic lights" in
+ the window title when the window (or app) is in the background.
+
+ This patch changes the key event handling to use the MacOS translation
+ mechanisms. It also improves dead key handling.
+
+ * macosx/tkMacOSXKeyEvent.c (InitKeyData): Add.
+ (InitKeyEvent): Add.
+ (DecodeViaUnicodeResource): Rename KeycodeToUnicodeViaUnicodeResource.
+ (DecodeViaKCHRResource): Rename KeycodeToUnicodeViaKCHRResource.
+ (GetKeyboardLayout): Use a boolean flag instead of a special layout id.
+ (KeycodeToUnicodeViaUnicodeResource): Change interface and
+ implementation to return a Unicode string instead of directly filling
+ an XEvent.
+ (KeycodeToUnicodeViaKCHRResource): Ditto.
+ (KeycodeToUnicodeViaUnicodeResource): Add handling for callers that
+ don't want deadkey processing (i.e. XKeycodeToKeysym).
+ (KeycodeToUnicodeViaKCHRResource): Ditto.
+ (KeycodeToUnicodeViaUnicodeResource): Clear deadKeyState if a character
+ was produced.
+ (KeycodeToUnicodeViaKCHRResource): Use CFString and current keyboard
+ encoding instead of Tcl Tcl_ExternalToUtf() and fixed
+ TkMacOSXCarbonEncoding.
+ (TkMacOSXKeycodeToUnicode): Add.
+
+ (TkMacOSXProcessKeyboardEvent): Add some heuristics to improve keyup
+ events.
+ (deadKeyState): Split into deadKeyStateUp and deadKeyStateDown.
+ (GenerateKeyEvent): Change interface and implementation to accept a
+ Unicode string instead of individual characters.
+ (GenerateKeyEvent): Don't generate string representations for special
+ characters.
+
+ * macosx/tkMacOSXEvent.h (TkMacOSXKeycodeToUnicode): Add prototype.
+
+ * macosx/tkMacOSXKeyboard.c (KCHRPtr): Remove.
+ (XKeycodeToKeysym): Use TkMacOSXKeycodeToUnicode instead of
+ KeyTranslate.
+ (XKeycodeToKeysym): Support latin-1 keysyms.
+
+ This patch reverts the hack to put icons in menus that Vince put in
+ yesterday (but preserves the bug fix in that submission.)
+
+ * macosx/tkMacOSXMenu.c (SetMenuTitle): revert treating "<bullet>
+ number" as a request to put icon number <number> in the menu.
+
+2003-02-18 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * doc/entry.n:
+ * doc/text.n: Update double and triple click docs to match
+ implementation changes made on 2002-02-14.
+
+2003-02-19 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Wish.pbproj/project.pbxproj:
+ * macosx/Makefile: reworked embedded build to no longer require
+ relinking but to use install_name_tool instead to change the
+ install_names for embedded frameworks. [Bug 644510]
+
+2003-02-19 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * library/demos/widget: New part for the widget demo showing
+ * library/demos/unicodeout.tcl: Tk's UNICODE output. [Patch 627453]
+
+2003-02-18 Andreas Kupries <andreask@activestate.com>
+
+ * unix/configure: Regen.
+ * unix/tcl.m4: Update from Tcl (HP xnet [Bug 651811]).
+
+2003-02-18 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure: Regen.
+ * unix/tcl.m4: Update from Tcl.
+
+2003-02-18 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkText.c (TextWidgetCmd): remove unused lastEnd var. [Bug
+ 664790]
+
+ * generic/tkCanvPs.c (TkPostscriptImage): remove unused depth var. [Bug
+ 664787]
+
+ * generic/tkEntry.c (EntrySetValue): removed unused code var. [Bug
+ 664781]
+
+ * library/tk.tcl (::tk::TabToWindow): auto-highlight spinboxes as well
+ as entries when tabbing in. [Patch 683813] (bron)
+
+ * library/xmfbox.tcl (::tk::MotifFDialog_ActivateSEnt): correct sub on
+ embedded newlines. [Patch 688572] (bonfield)
+
+ * doc/colors.n: corrected B values [Bug 682714].
+
+ * win/tkWinInit.c (TkpDisplayWarning): truncate MessageBox string to
+ 1024 chars to prevent possible oversized window errors. May be
+ necessary in other MB uses (ie Tcl_AppInit). [Tcl Bug 608559]
+
+2003-02-18 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * macosx/tkMacOSXMenu.c: (SetMenuTitle) fix to utf encoding problem
+ when setting menu titles, and provisional support for icons. [Tcl Bug
+ 625080]
+
+2003-02-18 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tkImgGIF.c (FileReadGIF): Ensure that the trashBuffer is
+ always deallocated on function exit to stop a potential memory leak.
+
+2003-02-17 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tkEvent.c (Tk_HandleEvent): Fixup button press state saving
+ code, it was incorrectly converting normal motion events into button
+ press and motion events in some cases.
+ * generic/tkInt.h: Add mouseButtonWindow member to the TkDisplay
+ structure.
+ * tests/event.test: Add test case for faulty button motion logic.
+
+2003-02-14 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * README: Bumped to 8.4.2.
+ * generic/tk.h:
+ * macosx/Wish.pbproj/project.pbxproj:
+ * unix/configure:
+ * unix/configure.in:
+ * unix/tcl.m4:
+ * unix/tk.spec:
+ * win/configure:
+ * win/configure.in:
+
+ * unix/tcl.m4: correct HP-UX ia64 --enable-64bit build flags
+
+2003-02-13 Kevin Kenny <kennykb@users.sourceforge.net>
+
+ * doc/wish.n: Added language to describe the handling of the
+ end-of-file character \u001a in script files. [Bug 685505]
+
+2003-02-10 Jim Ingham <jingham@apple.com>
+
+ * macosx/tkMacOSXCursor.c (TkMacOSXInstallCursor): Set all theme
+ cursors using SetThemeCursor or SetAnimatedThemeCursors.
+ (TkGetCursorByName): Use the theme cursors for arrow, ibeam, etc. Allow
+ animatedCursor{NUM} form for an animated cursor with count.
+ (TkpSetCursor): Don't reset the cursor if there is no change.
+ * macosx/tkMacOSXMouseEvent.c (GeneratePollingEvents): Don't directly
+ call TkMacOSXInstallCursor, it gets called by the call to
+ Tk_UpdatePointer immediately above.
+
+2003-02-05 Fred Fish <fnf@intrinsity.com>
+
+ * macosx/tkMacOSXWm.c (Tk_SetGrid): Fix precedence problem with
+ * mac/tkMacWm.c (Tk_SetGrid): '==' and '|'.
+
+2003-02-08 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkCanvArc.c (CreateArc): Rework canvas create item type
+ * generic/tkCanvBmap.c (CreateBitmap): coords handling to be
+ * generic/tkCanvImg.c (CreateImage): consistent across types and
+ * generic/tkCanvPoly.c (CreatePolygon): not pass empty coords to item
+ * generic/tkCanvLine.c (CreateLine): creation procs.
+ * generic/tkCanvText.c (CreateText):
+ * generic/tkCanvWind.c (CreateWinItem):
+ * generic/tkCanvas.c (CanvasWidgetCmd CANV_CREATE):
+ * generic/tkRectOval.c (CreateRectOval):
+ * tests/canvRect.test:
+ * tests/canvText.test:
+ * tests/canvas.test:
+
+2003-01-28 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/tkInt.h (TkDisplay,TkMainInfo):
+ * generic/tkObj.c (windowObjType):
+ * generic/tkWindow.c (Tk_DestroyWindow):
+ * tests/wm.test (wm-deletion-epoch-1.1): Moved 'deletionEpoch' field
+ from TkDisplay to TkMainInfo. Reworked windowObj type. Fixes [Bug
+ 671330] "segfault when e.g. deiconifying destroyed window"
+
+2003-01-23 D. Richard Hipp <drh@hwaci.com>
+
+ * library/entry.tcl: Fix the KeyPress binding on the entry widget so
+ that it enters text from left to right (not right to left) even if the
+ mouse button is being held down. [Bug 673687]
+
+2003-01-22 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tkFrame.c (TkToplevelWindowForCommand): Added way of mapping
+ from command names to tkwins-for-toplevels.
+ * generic/tkImage.c (Tk_ImageObjCmd): Added check to make sure that
+ you're not creating an image named the same as .'s command, which
+ refixes 220891, even when the name of the command has been changed with
+ 'rename'. The error message is better too.
+ * tests/image.test (image-1.10,image-1.11): Updated to match new error
+ message and added test for the rename case.
+
+2003-01-19 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkImage.c (DeleteImage): delete the image's entry in the
+ image table correctly when there are no more instances. This reopens
+ bug 220891. [Bug 669759]
+
+2003-01-18 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * doc/loadTk.n: note that ::safe::loadTk has a prereq on
+ ::safe::interpCreate or ::safe::interpInit. [Bug 669159]
+
+ * doc/photo.n: $image put only accepts -format and -to, and note
+ extended use of -to.
+
+2003-01-17 D. Richard Hipp <drh@hwaci.com>
+
+ * generic/tkCanvUtil.c: The clipping algorithm introduced on 2003-01-08
+ was unnecessarily aggressive in reducing the size of the clipping box.
+ This did not cause a problem for normal display, but did create trouble
+ for some extensions that attempt to render a canvas on a GDI printer
+ under Windows. The patch here relaxes the constraints on the clipping
+ box somewhat. [Bug 663981]
+
+2003-01-14 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/tkSelect.c (Tk_CreateSelHandler): Fix for [Bug 666346]
+ "Selection handling crashes under KDE 3.0"
+ * tests/unixSelect.test (unixSelect-1.20): Added test case.
+
+2003-01-13 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/tkWinDialog.c (Tk_ChooseDirectoryObjCmd)
+ (ChooseDirectoryValidateProc, Tk_MessageBoxObjCmd): Remove unused
+ tsdPtr variable. Use TEXT macro instead of _T macro since _T does not
+ work under Cygwin. Declare flags as UINT to avoid compiler warning when
+ compiling with mingw.
+
+2003-01-12 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/Makefile.in: Add TCL_DEFS to AC_FLAGS so that compiler flags
+ defined by Tcl get passed to the compiler. Add empty rule for cat.c so
+ that Tk compiles under msys.
+ * win/configure: Regen.
+ * win/tcl.m4: Update from Tcl, this pulls in a subst of TCL_DEFS, it
+ also defines USE_THREAD_ALLOC when threads are used and it updates the
+ SC_ENABLE_SYMBOLS and SC_PROG_TCLSH macros to match the ones used in
+ Tcl.
+
+2003-01-10 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/tkUnixEvent.c (OpenIM): Remove unused variable (Fixes: [Bug
+ 664780] "SGI warning: OpenIM")
+
+2003-01-08 D. Richard Hipp <drh@hwaci.com>
+
+ * generic/tkCanvLine.c:
+ * generic/tkCanvas.h:
+ * generic/tkCanvUtil.c: Clip long lines so that they will display
+ properly even on windowing systems where coordinates are expressed as
+ 16-bit numbers. [Bug 663981]
+
+2003-01-03 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkFrame.c (CreateFrame): throw a Tcl error instead of a panic
+ when we cannot get a main window and appname is NULL. This can indicate
+ that a user tried to create a frame/toplevel while Tk was dying. [Bug
+ 661792]
+
+ ******************************************************************
+ *** CHANGELOG ENTRIES FOR 2002 AND EARLIER IN "ChangeLog.2002" ***
+ ******************************************************************
diff --git a/tk8.6/ChangeLog.2007 b/tk8.6/ChangeLog.2007
new file mode 100644
index 0000000..8c458be
--- /dev/null
+++ b/tk8.6/ChangeLog.2007
@@ -0,0 +1,5283 @@
+2007-12-30 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/canvas.n: Documented exact behaviour of items with respect to
+ when they are the current item. [Bug 1774593] Also documented the
+ clipping behaviour of window items.
+
+ * library/demos/nl.msg: Corrected following testing "in the field" by
+ Arjen Markus. [Bug 1860802]
+
+2007-12-17 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ *** 8.5.0 TAGGED FOR RELEASE ***
+
+ * doc/canvas.n: Documented -outlineoffset item option. [Bug 1836621]
+
+2007-12-14 Don Porter <dgp@users.sourceforge.net>
+
+ * changes: More updates for 8.5.0 release.
+
+2007-12-14 Joe English <jenglish@users.sourceforge.net>
+
+ * doc/ttk_treeview.n: Fix typo. [Bug 1850713]
+
+2007-12-14 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tkWinInt.h: Add in missing function definitions
+ * win/tkWinButton.c: to support plain MSVC6 and use INT_PTR
+ * win/tkWinScrlBar.c: rather than LONG_PTR which isn'tr defined
+ * win/tkWinWm.c: in the msvc6 headers.
+
+2007-12-14 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/nmakehlp.c: Support compilation with MSVC9 for AMD64.
+ * win/makefile.vc:
+
+2007-12-13 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkMenubutton.c (ConfigureMenuButton): trace the
+ -textvariable even if an image exists as it may use -compound.
+
+2007-12-12 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkText.c (DeleteIndexRange, TextEditCmd, UpdateDirtyFlag):
+ * tests/text.test (text-25.10.1,25.11.[12]):
+ Don't require [update idle] to trigger Modified event [Bug 1809538]
+ Modified virtual event should only fire on state change [Bug 1799782]
+ Make sure we delete chars before triggering <<Modified>> [Bug 1737288]
+
+2007-12-12 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXWm.c (ApplyMasterOverrideChanges): Revert 2007-10-26
+ change to window class of transient toplevels that are not also
+ overrideredirect. [Bug 1845899]
+
+ * macosx/tkMacOSXWm.c (ApplyMasterOverrideChanges): Implement more
+ * macosx/tkMacOSXMouseEvent.c (BringWindowForward): X11-like transient
+ * macosx/tkMacOSXSubwindows.c (XDestroyWindow): behaviour by
+ adding transient windows to a window group owned by the master window,
+ this ensures transients always remain in front of and are collapsed
+ with the master; bring master to front when selecting transient
+ windows; restore default window group of transients if master
+ destroyed. [Bug 1845899]
+
+2007-12-12 Joe English <jenglish@users.sourceforge.net>
+
+ * doc/ttk_intro.n, doc/ttk_style.n, doc/ttk_widget.n:
+ Various minor updates.
+
+2007-12-12 Don Porter <dgp@users.sourceforge.net>
+
+ * changes: Updated for 8.5.0 release.
+
+2007-12-11 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkTheme.c (StyleElementOptionsCmd): Use
+ Ttk_GetElement() to find element instead of direct hash table access.
+
+2007-12-11 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkText.c (TextReplaceCmd): Added code to rebuild the from
+ index after the deletion phase so that the linePtr field is valid for
+ the insertion phase. [Bug 1602537]
+
+2007-12-10 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/event.n: Clarify the fact that [event info] only returns the
+ names of virtual events that are bound to physical event sequences.
+ This follows on from comments on comp.lang.tcl.
+ http://groups.google.com/group/comp.lang.tcl/msg/935d2d226ae8a770
+
+2007-12-10 Joe English <jenglish@users.sourceforge.net>
+
+ * doc/AddOption.3, doc/CrtImgType.3, doc/CrtPhImgFmt.3,
+ * doc/InternAtom.3, doc/TextLayout.3, doc/chooseColor.n,
+ * doc/chooseDirectory.n, doc/loadTk.n, doc/palette.n,
+ * doc/ttk_combobox.n: Various markup fixes (mostly: missing quotes on
+ .SH arguments, extraneous .PPs)
+
+ * doc/ttk_entry.n, doc/ttk_scrollbar.n, doc/ttk_treeview.n: Remove
+ extra .BEs that got added by mistake somewhere.
+
+2007-12-10 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tk.decls: use new genstubs 'export' command to
+ * generic/tkInt.decls: mark exported symbols not in stubs
+ table [FR 1716117]; cleanup formatting
+
+ * generic/tkIntDecls.h: regen with new genStubs.tcl.
+ * generic/tkIntPlatDecls.h: [Tcl Bug 1834288]
+ * generic/tkIntXlibDecls.h:
+ * generic/tkPlatDecls.h:
+ * generic/tkStubInit.c:
+
+2007-12-10 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * tests/safe.test: Ensure list of hidden commands is correct. [Bug
+ 1847925]
+
+2007-12-10 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tkWin.h: We must specify the lowest Windows version we intend to
+ support. In particular the SystemParametersInfo API doesn't like to
+ receive structures that are larger than it expects which affects the
+ font assignements. Set to Win98 support.
+
+ * win/tkWinFont.c: Handle failure to read the system parameters. This
+ causes ttk/fonts.tcl to set any missing named fonts.
+
+ * win/ttkWinMonitor.c: Only tkWin.h should include windows.h unless
+ * win/ttkWinTheme.c: we have an explicit override of the WINVER
+ * tin/ttkWinXPTheme.c: macro.
+
+ * win/rules.vc: Handle MSVC 9 (aka: Visual Studio 2008)
+
+ * tests/safe.test: Update for 'unload' as a safe command (tcl 8.5b3+)
+
+2007-12-09 Donal K. Fellows <dkf@users.sf.net>
+
+ * win/configure.in: Adjusted code so that running configure does not
+ generate an error message when the full current directory name
+ contains a space.
+
+ * win/tkWinWm.c: Added set of #defs to make this file build with my
+ version of the SDK (i.e. with the msys suite we distribute).
+
+2007-12-07 Joe English <jenglish@users.sourceforge.net>
+
+ * library/ttk/altTheme.tcl, library/ttk/classicTheme.tcl:
+ s/style/ttk::style/.
+
+2007-12-07 Don Porter <dgp@users.sourceforge.net>
+
+ * unix/README: Mention the stub library created by `make` and warn
+ about the effect of embedded paths in the installed binaries. Thanks
+ to Larry Virden. [Tcl Bug 1794084]
+
+2007-12-05 Joe English <jenglish@users.sourceforge.net>
+
+ * macosx/ttkMacOSXTheme.c: Fix TCombobox layout so as not to truncate
+ long text when combobox is wider than requested. [Bug 1845164]
+
+2007-12-05 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/demos/widget: reduce start size to 70% of screenheight from
+ sh-200 for a more reasonable size.
+
+ * win/tkWinButton.c, win/tkWinDialog.c: use SetWindowLongPtr and
+ * win/tkWinScrlbr.c, win/tkWinWm.c: GetWindowLongPtr only.
+ * win/ttkWinMonitor.c:
+
+ * win/tkWinInt.h: remove CS_CLASSDC (not recommended for any apps now)
+ * win/tkWinX.c: and simplify WNDCLASS to one style.
+ * win/tkWinWm.c: Reduce wrapper update for exStyle to toolwindow
+ change only and set WS_EX_LAYERED as sticky (once set on a window, do
+ not remove it) to reduce alpha transition flicker.
+
+ * win/configure, win/tcl.m4 (LIBS_GUI): mingw needs -lole32 -loleaut32
+ but not msvc for Tk's [send]. [Bug 1844749]
+
+2007-12-04 Joe English <jenglish@users.sourceforge.net>
+
+ * doc/ttk_style.n: Remove nonsense about "this manpage has not yet
+ been written"; everything supported is documented.
+
+2007-12-04 Donal K. Fellows <dkf@users.sf.net>
+
+ * library/msgs/en.msg: Added missing messages. [Patch 1800744]
+
+ * library/msgs/da.msg: Added Danish messages. [Patch 1844143]. Many
+ thanks to Torsten Berg <treincke@users.sf.net>.
+
+2007-12-03 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/configure, win/tcl.m4 (LIBS_GUI): remove ole32.lib oleaut32.lib
+ (LIBS): add ws2_32.lib for static builds with Tcl.
+
+2007-12-01 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkTheme.h, generic/ttk/ttkThemeInt.h,
+ * generic/ttk/ttkTheme.c, generic/ttk/ttkLayout.c,
+ * generic/ttk/ttkClamTheme.c, generic/ttk/ttkClassicTheme.c,
+ * generic/ttk/ttkTreeview.c, macosx/ttkMacOSXTheme.c,
+ * win/ttkWinTheme.c, win/ttkWinXPTheme.c: Improved macrology for
+ statically-initialized layout template tables.
+
+2007-11-28 Don Porter <dgp@users.sourceforge.net>
+
+ * unix/tkUnixPort.h: When unix/configure determines whether the
+ intptr_t type is available, it has the <inttypes.h> header present.
+ It's only fair that we let Tk have it too.
+
+2007-11-26 Kevin Kenny <kennykb@acm.org>
+
+ * generic/tkImgPPM.c (StringReadPPM): Corrected a comparison whose
+ sense was reversed that resulted in reading beyond the end of the
+ input buffer on malformed PPM data. [Bug 1822391]
+ * library/tkfbox.tcl (VerifyFileName): Corrected a couple of typos in
+ handling of bad file names. [Bug 1822076] Thanks to Christoph Bauer
+ (fridolin@users.sf.net) for the patch.
+ * tests/filebox.test (filebox-7.1, filebox-7.2): Added test cases that
+ exercise. [Bug 1822076]
+ * tests/imgPPM.test (imgPPM-4.1): Added test case that exercises. [Bug
+ 1822391]
+
+2007-11-25 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkManager.h, generic/ttk/ttkManager.c,
+ * generic/ttk/ttkFrame.c, generic/ttk/ttkNotebook.c,
+ * generic/ttk/ttkPanedwindow.c: Internal Ttk_Manager API updates;
+ Fixed [Bug 1343984]; Added [$nb hide] method; [$nb add] on
+ already-managed windows no longer throws an error, can be used to
+ re-add a hidden tab.
+
+ * doc/ttk_notebook.n, tests/ttk/notebook.test,
+ * tests/ttk/panedwindow.test: Updated docs and test suite.
+
+2007-11-23 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * unix/README: General improvements.
+
+2007-11-21 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * library/tkfbox.tcl: Better theming in the file list area.
+
+2007-11-19 Don Porter <dgp@users.sourceforge.net>
+
+ *** 8.5b3 TAGGED FOR RELEASE ***
+
+ * README: Bump version number to 8.5b3.
+ * generic/tk.h:
+ * library/tk.tcl:
+ * unix/configure.in:
+ * unix/tk.spec:
+ * win/configure.in:
+
+ * unix/configure: autoconf-2.59
+ * win/configure:
+
+ * changes: Update changes for 8.5b3 release.
+
+2007-11-19 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * generic/ttk/ttkTheme.c: Fix crash when 'style element create'
+ * tests/ttk/ttk.test: called w/ insufficient args; add tests.
+
+2007-11-18 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkElements.c, macosx/ttkMacOSXTheme.c: Add "fill"
+ element: like "background" but only erases parcel.
+
+ * generic/ttk/ttkFrame.c: Use fill element in Labelframe Label
+ sublayout. Also improved default labelmargins for -labelanchor w*, e*.
+
+ * generic/ttk/ttkLabel.c: no longer need Labelframe hack.
+
+ * library/ttk/aquaTheme.tcl: ImageTextElement no longer needed.
+ TextElement no longer needs '-background' option.
+
+ * generic/ttk/ttkFrame.c: Use sublayout for ttk::labelframe labels
+ instead of single element.
+
+ * generic/ttk/ttkLabel.c: Default -anchor for text and label elements
+ is now "w" instead of "center". [Bug 1614540]
+
+ * library/ttk/defaults.tcl, library/ttk/*Theme.tcl: Button styles now
+ need explicit "-anchor center".
+
+ * generic/ttk/ttkLayout.c (TTKInitPadding): BUGFIX:
+ Ttk_GetPaddingFromObj() and Ttk_GetBorderFromObj() returned garbage
+ when passed an empty list.
+
+ * macosx/ttkMacOSXTheme.c: Resynchronize with Tile codebase so that
+ patches can flow back and forth.
+
+ * library/ttk/aquaTheme.tcl: Extra TButton -padding no longer needed.
+
+2007-11-18 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/ttkWinXPTheme.c: Add support for size information flags for
+ scrollbar and combobox buttons. This handles Tile [Patches 1596647 and
+ 1596657] but a bit more generically.
+
+2007-11-17 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * generic/(tkArgv.c, tkBind.c, tkCipboard.c, tkEntry.c, tkOption.c,
+ tkScale.c, tkScrollbar.c, tkTextImage.c, tkVisual.c, tkWindow.c): Tidy
+ up some variable types.
+
+ * generic/tkFont.c: Only check for -displayof if there are
+ * test/font.test: sufficient arguments. This permits checking
+ strings like -d.
+
+2007-11-17 Joe English <jenglish@users.sourceforge.net>
+
+ * library/ttk/scrollbar.tcl: Swap in core scrollbars for
+ [ttk::scrollbar]s on OSX.
+
+2007-11-16 Benjamin Riefenstahl <b.riefenstahl@turtle-trading.net>
+
+ * macosx/tkMacOSXFont.c (TkpMeasureCharsInContext): Correct an
+ oversight in the bug fix from 2007-11-11. [Bug 1824638]
+
+2007-11-15 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Wish.xcodeproj/project.pbxproj: add new chanio.test.
+ * macosx/Wish.xcode/project.pbxproj:
+
+2007-11-14 Donal K. Fellows <dkf@users.sf.net>
+
+ * library/msgs/sv.msg: Get the locale declared within the message
+ catalog correct! [Bug 1831803]
+
+2007-11-11 Benjamin Riefenstahl <b.riefenstahl@turtle-trading.net>
+
+ * macosx/tkMacOSXFont.c (TkpMeasureCharsInContext): Fix the case when
+ TK_WHOLE_WORDS and TK_AT_LEAST_ONE are both set and maxLength is small.
+ [Bug 1824638]
+
+2007-11-09 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXCarbonEvents.c
+ (InstallStandardApplicationEventHandler): on Mac OS X Leopard, replace
+ the 2005-11-27 approach of installing the standard application handler
+ by calling RAEL and immediately longjmping out of it from an event
+ handler, as that now leads to crashes in -[NSView unlockFocus] whenever
+ HIToolbox uses Cocoa in Leopard (Help menu, Nav Services, Color
+ Picker). Instead call InstallStandardEventHandler() on the application
+ and menubar event targets, as Leopard ISEH finally handles these
+ correctly. Unfortunately need a HIToolbox-internal SPI to retrieve the
+ menubar event target, no public API appears have that functionality.
+
+ * macosx/tkMacOSXDebug.c: make TkMacOSXInitNamedDebugSymbol()
+ * macosx/tkMacOSXDebug.h: available outside of debug builds as
+ the new Leopard ISAEH needs it.
+
+ * macosx/tkMacOSXButton.c: replace HiliteControl() by modern API
+ * macosx/tkMacOSXMenubutton.c: for activation and enabling;
+ distinguish inactive and disabled
+ look&feel; correct activation handling
+ to match that of container toplevel.
+
+ * macosx/tkMacOSXMenubutton.c: correct size computation of bevelbutton
+ variant to match that of buttons;
+ fix crash with bitmap due to NULL GC;
+ delay picParams setup until needed;
+ formatting cleanup. [Bug 1824521]
+
+ * library/menu.tcl: correct handling of menubutton "active"
+ state on Aqua to match that of buttons.
+
+ * macosx/tkMacOSXDefault.h: correct button & menubutton active
+ foreground and background colors and
+ menubutton border width.
+
+ * macosx/tkMacOSXWindowEvent.c: handle kEventWindowExpanding carbon
+ * macosx/tkMacOSXCarbonEvents.c: event instead of kEventWindowExpanded
+ to ensure activate event arrives after
+ window is remapped, also need to
+ process all Tk events generated by
+ remapping in the event handler to
+ ensure children are remapped before
+ activate event is processed.
+
+ * macosx/tkMacOSXSubwindows.c: add pixmap size field to MacDrawable
+ * macosx/tkMacOSXInt.h: struct; add flag for B&W pixmaps.
+ * macosx/tkMacOSXDraw.c:
+ * macosx/tkMacOSXEmbed.c:
+ * macosx/tkMacOSXMenu.c:
+
+ * macosx/tkMacOSXPrivate.h: correct Leopard HIToolboxVersionNumber.
+
+ * macosx/ttkMacOSXTheme.c: add error checking; cleanup formatting.
+
+ * macosx/tkMacOSXFont.c (TkpGetFontAttrsForChar): panic on false return
+ from TkMacOSXSetupDrawingContext().
+
+ * macosx/tkMacOSXButton.c: sync formatting, whitespace, copyright
+ * macosx/tkMacOSXDialog.c: with core-8-4-branch.
+ * macosx/tkMacOSXMenus.c:
+ * macosx/tkMacOSXWm.c:
+ * xlib/xgc.c
+ * library/bgerror.tcl:
+ * library/console.tcl:
+ * library/menu.tcl:
+
+2007-11-07 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkTheme.c (Ttk_ElementSize): Fixed longstanding, subtle
+ bug that caused element padding to sometimes be counted twice in size
+ computations.
+
+ * generic/ttk/ttkElements.c, generic/ttk/ttkClamTheme.c,
+ * generic/ttk/ttkDefaultTheme.c, generic/ttk/ttkTreeview.c,
+ * generic/ttk/ttkImage.c, macosx/ttkMacOSXTheme.c,
+ * win/ttkWinTheme.c, win/ttkWinXPTheme.c:
+ Fix ElementSizeProcs affected by previous change.
+
+2007-11-06 Andreas Kupries <andreask@activestate.com>
+
+ * doc/CrtConsoleChan.3: Fixed markup typo and extended see also
+ section per suggestions by Donal.
+
+2007-11-05 Joe English <jenglish@users.sourceforge.net>
+
+ * library/ttk/combobox.tcl: Set focus to listbox in <Map> binding
+ instead of in Post command (see [Bug 1349811] for info).
+
+2007-11-05 Andreas Kupries <andreask@activestate.com>
+
+ * doc/CrtConsoleChan.3: New file providing minimal documentation of
+ 'Tk_InitConsoleChannels()'. [Bug 432435]
+
+2007-11-05 Joe English <jenglish@users.sourceforge.net>
+
+ * macosx/ttkMacOSXTheme.c (TreeitemLayout): Remove focus ring
+ from treeview items on OSX (problem reported by Kevin Walzer).
+
+2007-11-04 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkTreeview.c: Use null "treearea" element for treeview
+ owner-draw area instead of "client", to avoid nameclash with
+ Notebook.client element (this was causing sizing anomalies in XP
+ theme, and introduced extraneous padding).
+ * generic/ttk/ttkDefaultTheme.c: Treeitem.indicator element needs left
+ margin now.
+
+2007-11-04 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXMenus.c: add "Run Widget Demo" menu item to the
+ default Edit menu along with associated carbon event handler enabling
+ the item only if demo files are installed; cleanup handling of "About"
+ and "Source" menu items.
+
+ * library/bgerror.tcl: fix background of detail text on Aqua.
+
+ * library/console.tcl: add accelerators and fix Aqua bindings
+ of the new font size menu items.
+
+ * library/demos/mclist.tcl: Aqua GOOBE.
+ * library/demos/tree.tcl:
+ * library/demos/ttknote.tcl:
+ * library/demos/widget:
+
+ * doc/chooseDirectory.n: remove/correct obsolete Mac OS 9-era
+ * doc/getOpenFile.n: information.
+ * doc/menu.n:
+
+ * macosx/tkMacOSXEvent.c (TkMacOSXProcessCommandEvent): fix boolean
+ arg
+
+ * macosx/Wish.xcodeproj/project.pbxproj: add new demo file.
+ * macosx/Wish.xcode/project.pbxproj:
+
+2007-11-03 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * library/console.tcl: Add menu item and key binding to adjust font.
+
+2007-11-02 Donal K. Fellows <dkf@users.sf.net>
+
+ * library/demos/mclist.tcl: Added a demo of how to do a multi-column
+ sortable listbox.
+
+ * library/msgbox.tcl: Made message dialog use Ttk widgets for better
+ L&F.
+
+ * library/tkfbox.tcl (::tk::dialog::file::CompleteEnt): Added <Tab>
+ completion. [FR 805091]
+ * library/tkfbox.tcl: Made file dialog use Ttk widgets for better L&F.
+
+ * library/demos/sayings.tcl: Better resizing. [Bug 1822410]
+
+2007-11-01 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * library/demos/textpeer.tcl: Better resizing. [Bug 1822601]
+
+ * doc/colors.n: Added list of Windows system colors. [Bug 945409]
+
+2007-11-01 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXColor.c (GetThemeColor): improve translation of RGB
+ pixel values into RGBColor.
+
+ * library/demos/widget: increase height of main window text widget to
+ use more of the available vertical space.
+
+ * doc/bind.n: document the Option modifier, clarify meaning
+ and availability of Command & Option.
+
+ * doc/console.n: clarify availability of [console] in TkAqua.
+
+2007-11-01 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * unix/installManPage, doc/*.n: Make documentation use the name that
+ scripts use as much as possible. [Bug 1640073]
+
+ * doc/text.n: Fixed mistake in [$t tag remove] docs. [Bug 1792191]
+
+ * doc/bind.n: Documented the Command modifier. [Bug 1232908]
+
+ * doc/console.n, doc/wish.1: Made it clearer when and why the console
+ command is present. [Bug 1386955]
+
+2007-10-31 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * library/demos/entry3.tcl: Improved description/comments so that
+ people better understand what is being validated, following suggestion
+ from Don Porter.
+
+ * library/demos/image2.tcl (loadImage): Mark non-loadable images as
+ such instead of throwing a nasty dialog, following suggestion from Don
+ Porter.
+
+ * generic/tkImgPhoto.c (Tk_PhotoPutBlock): More optimization, derived
+ from [Patch 224066].
+
+2007-10-30 Joe English <jenglish@users.sourceforge.net>
+
+ * library/ttk/combobox.tcl (Unpost): BUGFIX: Unpost can be called with
+ no preceding Post.
+
+2007-10-31 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/rules.vc: Use -fp:strict with msvc8 as -fp:precise fails on
+ * generic/tkObj.c: amd64 builds. Fix the two places in Tk that
+ * generic/tkTrig.c: generate errors with msvc8 when using this flag.
+
+2007-10-30 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/choosedir.tcl: only enable OK button when valid in
+ conjunction with -mustexist. [Bug 1550528]
+
+ * library/listbox.tcl (::tk::ListboxBeginSelect): ignore -takefocus
+ when considering focus on <1>, it is for tab focus.
+
+2007-10-30 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tk.h: Bump version number to 8.5b2.1 to distinguish
+ * library/tk.tcl: CVS development snapshots from the 8.5b2
+ * unix/configure.in: release.
+ * unix/tk.spec:
+ * win/configure.in:
+
+ * unix/configure: autoconf (2.59)
+ * win/configure:
+
+2007-10-30 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * doc/text.n: fix spelling of -inactiveselectbackground [Bug 1626415]
+
+ * library/entry.tcl: don't error with Clear event. [Bug 1509288]
+
+ * library/ttk/fonts.tcl: use size -12 TkFixedFont (was -10) on X11
+
+2007-10-30 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * library/demos/unicodeout.tcl: Fixed Arabic and Hebrew rendering on
+ Windows. [Bug 1803723]
+
+ * generic/tkImgPhoto.c (ImgPhotoCmd): Rename enumeration for somewhat
+ simpler-to-read code. [Bug 1677613]
+
+2007-10-30 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkWidget.c: Split up RedisplayWidget() to factor out
+ double-buffering related code.
+
+ * macosx/ttkMacOSXAquaTheme.c: Use SetThemeBackGround/
+ kThemeBrushModelessDialogBackground{Active|Inactive} instead of
+ ApplyThemeBackground/kThemeBackgroundWindowHeader (advice from DAS).
+
+ * library/ttk/aquaTheme.tcl: Use darker shade for inactive and
+ disabled text, to match typical values of most
+ kThemeXXXTextColorInactive values.
+
+2007-10-30 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/selection.n: Clarify UTF8_STRING handling. [Bug 1778563]
+
+ * doc/text.n: Clarify search subccommand docs. [Bug 1622919]
+
+2007-10-29 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * macosx/tkMacOSXFont.c (InitSystemFonts):
+ * library/ttk/fonts.tcl: use Monaco 11 (was 9) as Aqua TkFixedFont
+
+ * tests/listbox.test, tests/panedwindow.test, tests/scrollbar.test:
+ * library/bgerror.tcl, library/dialog.tcl, library/listbox.tcl:
+ * library/msgbox.tcl, library/optMenu.tcl, library/tclIndex:
+ * library/tkfbox.tcl, library/demos/floor.tcl, library/demos/rmt:
+ * library/demos/tcolor, library/demos/text.tcl:
+ * library/demos/twind.tcl, library/demos/widget: Buh-bye Motif look
+ * library/ttk/fonts.tcl: Update of Tk default look in 8.5
+ * macosx/tkMacOSXDefault.h: Trims border sizes, cleaner X11 look
+ * unix/tkUnixDefault.h: with minor modifications for Win32/Aqua.
+ * win/tkWinDefault.h: Uses Tk*Font definitions throughout for
+ * win/tkWinFont.c: classic widgets. [Bug 1820344]
+ * library/obsolete.tcl (::tk::classic::restore): This restores
+ changes made to defaults in 8.5 using the 'option' command,
+ segmented into logical groups.
+
+ * tests/winfo.test: winfo-4.5 raise .t to above . for Windows
+
+ * tests/unixWm.test: note TIP#142 results and remove unnecessary
+ catches.
+
+2007-10-29 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/*.1, doc/*.n, doc/*.3: Lots more GOOBE work.
+
+2007-10-28 Joe English <jenglish@users.sourceforge.net>
+
+ * library/ttk/combobox.tcl: Make popdown window [wm resizable 0 0] on
+ OSX, to prevent TkAqua from shrinking the scrollbar to make room for a
+ grow box that isn't there.
+ * macosx/ttkMacOSXTheme.c, library/ttk/aquaTheme.tcl: Reworked
+ combobox layout.
+
+2007-10-26 Don Porter <dgp@users.sourceforge.net>
+
+ *** 8.5b2 TAGGED FOR RELEASE ***
+
+ * changes: Update changes for 8.5b2 release.
+
+ * doc/*.1: Revert doc changes that broke
+ * doc/*.3: `make html` so we can get the release
+ * doc/*.n: out the door.
+
+ * README: Bump version number to 8.5b2.
+ * generic/tk.h:
+ * library/tk.tcl:
+ * unix/configure.in:
+ * unix/tk.spec:
+ * win/configure.in:
+
+ * unix/configure: autoconf-2.59
+ * win/configure:
+
+2007-10-26 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXWm.c (ApplyMasterOverrideChanges): fix window class
+ of transient toplevels that are not also overrideredirect. [Bug
+ 1816252]
+
+ * macosx/tkMacOSXDialog.c: TIP#242 cleanup.
+ * library/demos/filebox.tcl: demo TIP#242 -typevariable.
+
+2007-10-25 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkNotebook.c: [Bug 1817596]
+
+2007-10-25 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * doc/getOpenFile.n: TIP#242 implementation of -typevariable to
+ * library/tkfbox.tcl: return type of selected file in file dialogs.
+ * library/xmfbox.tcl: [Bug 1156388]
+ * macosx/tkMacOSXDialog.c:
+ * tests/filebox.test:
+ * tests/winDialog.test:
+ * win/tkWinDialog.c:
+
+2007-10-25 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkPlace.c: Prevent segfault in place geometry manager.
+ Thanks to Colin McDonald. [Bug 1818491]
+
+2007-10-24 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/*.c, win/{ttkWinMonitor,ttkWinTheme,ttkWinXPTheme}.c,
+ * macosx/ttkMacOSXTheme.c: Move widget layout registration from
+ TtkElements_Init() to widget *_Init() routines. Renaming/consistency:
+ s/...ElementGeometry()/...ElementSize()/
+
+2007-10-24 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/*.n, doc/*.3, doc/*.1: Lots of changes to take advantage of the
+ new macros.
+
+2007-10-24 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tkWinDraw.c: Applied [Patch 1723362] for transparent bitmaps.
+
+ * generic/tkWindow.c: permit wm manage of any widget (esp: ttk::frame)
+
+2007-10-23 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/ttk/combobox.tcl (ttk::combobox::PopdownWindow): redo wm
+ transient on each drop to handle reparent-able frames. [Bug 1818441]
+
+2007-10-23 Joe English <jenglish@users.sourceforge.net>
+
+ * library/ttk/combobox.tcl: [namespace import ::ttk::scrollbar]
+ doesn't work, since ttk::scrollbar isn't [namespace export]ed.
+
+2007-10-23 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/cursor.test: Make tests robust against changes in Tcl's
+ rules for accepting integers in octal format.
+
+2007-10-23 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * doc/font.n: Added section on the TIP#145 fonts.
+
+2007-10-23 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tkWinFont.c: Fixed leak in CreateNamedFont spotted by das.
+
+2007-10-23 Daniel Steffen <das@users.sourceforge.net>
+
+ * library/demos/combo.tcl: Aqua GOOBE.
+ * library/demos/toolbar.tcl:
+ * library/demos/tree.tcl:
+ * library/demos/ttknote.tcl:
+ * library/demos/ttkprogress.tcl:
+ * library/demos/widget:
+
+ * macosx/Wish.xcodeproj/project.pbxproj: add new demo files.
+ * macosx/Wish.xcode/project.pbxproj:
+
+2007-10-22 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * library/demos/widget: Added more demos, reorganized to make Tk and
+ Ttk demos seem to be more coherent whole. Made localization a bit
+ easier by reducing the amount of duplication.
+ * library/demos/{combo,toolbar,tree,ttknote,ttkprogress}.tcl: New
+ demos of new (mostly) Ttk widgets.
+ * library/demos/ttkbut.tcl: Improvements.
+
+2007-10-22 Joe English <jenglish@users.sourceforge.net>
+
+ * library/ttk/combobox.tcl: ttk::combobox overhaul; fixes [Bugs
+ 1814778, 1780286, 1609168, 1349586]
+ * library/ttk/aquaTheme.tcl: Factored out aqua-specific combobox
+ -postposition adjustments.
+ * generic/ttk/ttkTrack.c: Detect [grab]s and unpress pressed
+ element; combobox workaround no longer
+ needed.
+
+2007-10-22 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXFont.c: register named fonts for TIP #145 fonts
+ and all theme font IDs.
+
+ * generic/tkFont.c (Tk{Create,Delete}NamedFont): allow NULL interp.
+
+ * library/ttk/fonts.tcl: check for TIP #145 fonts on all
+ platforms; correct aqua font sizes.
+
+ * library/demos/ttkmenu.tcl: Aqua GOOBE.
+ * library/demos/ttkpane.tcl:
+ * library/demos/widget:
+
+ * macosx/Wish.xcodeproj/project.pbxproj: add new demo files.
+ * macosx/Wish.xcode/project.pbxproj:
+
+2007-10-18 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * library/demos/ttkmenu.tcl: Added more demos of Ttk widgets. These
+ * library/demos/ttkpane.tcl: ones are of menubuttons, panedwindows and
+ a progress bar (indirectly).
+
+2007-10-18 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * library/ttk/fonts.tcl: Create all the TIP #145 font names on all
+ platforms (mac and unix get handled in script, windows in C)
+
+2007-10-17 David Gravereaux <davygrvy@pobox.com>
+
+ * bitmaps/*.xbm: Changed CVS storage mode from -kb to -kkv as these
+ are really text files, not binaries.
+ * win/makefile.vc: Added $(BITMAPDIR) to the search path for the
+ depend target.
+
+2007-10-18 Daniel Steffen <das@users.sourceforge.net>
+
+ * library/demos/widget: Aqua GOOBE, cleanup icons.
+ * library/demos/ttkbut.tcl:
+ * library/demos/entry3.tcl:
+ * library/demos/msgbox.tcl:
+
+ * library/demos/button.tcl: restore setting of button
+ highlightbackground on Aqua.
+
+ * macosx/ttkMacOSXTheme.c: adjust button and separator geometry.
+
+ * macosx/tkMacOSXWm.c: fix warnings.
+
+ * macosx/Wish.xcodeproj/project.pbxproj: add new demo files.
+ * macosx/Wish.xcode/project.pbxproj:
+
+2007-10-17 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * library/demos/ttkbut.tcl: Added demo of the basic Ttk widgets.
+
+2007-10-16 David Gravereaux <davygrvy@pobox.com>
+
+ * win/makefile.vc: depend target now works and builds a generated
+ dependency list with $(TCLTOOLSDIR)/mkdepend.tcl
+
+2007-10-16 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * library/demos/widget: Made the code for generating the contents of
+ the main widget more informative. Added 'new' flagging for wholly new
+ demos.
+
+ * doc/text.n: Made it clearer what things are text widget invokations
+ and what are not. Also some other clarity improvements.
+
+2007-10-15 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * library/demos/widget: Use Ttk widgets for the widget demo core, for
+ vastly improved look-and-feel on at least one platform (Windows).
+ * library/demos/{button,check,style,twind}.tcl: Various tweaks for
+ GOOBE...
+ * library/demos/textpeer.tcl: New demo script to show off peering as a
+ specific feature.
+
+2007-10-15 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkFocus.c, generic/tkFrame.c, generic/tkInt.h:
+ * macosx/tkMacOSXButton.c, macosx/tkMacOSXMenubutton.c:
+ * macosx/tkMacOSXWm.c, unix/tkUnixWm.c, win/tkWinWm.c:
+ * doc/wm.n, tests/wm.test: TIP #125 implementation. [Bug 998125]
+ Adds [wm manage|forget] for dockable frames.
+ Finished X11 and Windows code, needs OS X completion.
+
+2007-10-15 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkTreeview.c: Store pointer to column table entry
+ instead of column index in columnNames hash table. This avoids the
+ need for the evil PTR2INT and INT2PTR macros, and simplifies things a
+ bit.
+
+2007-10-15 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tkArgv.c: Fix gcc warnings about 'cast to/from
+ * generic/tkCanvUtil.c: pointer from/to integer of different
+ * generic/tkCanvas.c: size' on 64-bit platforms by casting
+ * generic/tkCursor.c: to intermediate types
+ * generic/tkInt.h: intptr_t/uintptr_t via new PTR2INT(),
+ * generic/tkListbox.c: INT2PTR(), PTR2UINT() and UINT2PTR()
+ * generic/tkObj.c: macros.
+ * generic/tkStyle.c:
+ * generic/tkTextIndex.c:
+ * generic/tkUtil.c:
+ * generic/ttk/ttkTheme.h:
+ * generic/ttk/ttkTreeview.c:
+ * unix/tkUnixMenu.c:
+ * unix/configure.in:
+
+ * unix/configure: autoconf-2.59
+ * unix/tkConfig.h.in: autoheader-2.59
+
+ * macosx/Wish-Common.xcconfig: add 'tktest-X11' target.
+ * macosx/Wish.xcode/project.pbxproj:
+ * macosx/Wish.xcode/default.pbxuser:
+ * macosx/Wish.xcodeproj/default.pbxuser:
+ * macosx/Wish.xcodeproj/project.pbxproj:
+
+ * unix/configure.in (Darwin): add support for 64-bit X11.
+ * unix/configure: autoconf-2.59
+
+2007-10-14 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/configure, win/configure.in (TK_WIN_VERSION): Make sure the
+ patchlevel doesn't contain extra dotted pairs (eg. interim release)
+
+2007-10-12 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/makefile.vc: Mine all version information from headers.
+ * win/rules.vc: Sync tcl and tk and bring extension versions
+ * win/nmakehlp.c: closer together. Try and avoid using tclsh
+ to do substitutions as we may cross compile.
+
+ * library/console.tcl: Use TkFixedFont and ttk widgets
+
+2007-10-12 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXDraw.c: replace all (internal) use of QD region
+ * macosx/tkMacOSXSubwindows.c: API by HIShape API, with conversion to
+ * macosx/tkMacOSXWindowEvent.c: QD regions only when required by legacy
+ * macosx/tkMacOSXPrivate.h: Carbon or Tk API.
+ * macosx/tkMacOSXRegion.c:
+ * macosx/tkMacOSXDebug.c:
+ * macosx/tkMacOSXDebug.h:
+
+ * macosx/tkMacOSXInt.h: replace MacDrawable's QD RgnHandles
+ * macosx/tkMacOSXEmbed.c: clipRgn, aboveClipRgn & drawRgn by
+ * macosx/tkMacOSXMenu.c: HIShapeRefs visRgn & aboveVisRgn and
+ * macosx/tkMacOSXSubwindows.c: CGRect drawRect.
+
+ * macosx/tkMacOSXWindowEvent.c: remove use of QD port vis rgn in
+ * macosx/tkMacOSXSubwindows.c: window update rgn calculation,
+ * macosx/tkMacOSXWm.c: manually excise growbox from toplevel
+ clip rgn instead.
+
+ * macosx/tkMacOSXDraw.c: replace use of QD port clip rgn by new
+ * macosx/tkMacOSXPrivate.h: clipRgn fld in TkMacOSXDrawingContext;
+ handle QD/CG drawing mismatches in
+ XCopyArea, XCopyPlane and TkPutImage;
+ cleanup/speedup CGContext setup in
+ TkMacOSXSetupDrawingContext().
+
+ * macosx/tkMacOSXDraw.c: change TkMacOSXSetupDrawingContext()
+ * macosx/tkMacOSXEntry.c: to return boolean indicating whether
+ * macosx/tkMacOSXFont.c: drawing is allowed (and was setup) or
+ * macosx/tkMacOSXMenu.c: not (e.g. when clipRgn is empty).
+ * macosx/ttkMacOSXTheme.c:
+
+ * macosx/tkMacOSXSubwindows.c: signal that drawable is a pixmap via
+ * macosx/tkMacOSXInt.h: new explicit TK_IS_PIXMAP flag instead
+ of a NULL cligRgn field.
+
+ * macosx/tkMacOSXRegion.c: add wrappers for missing/buggy HIShape
+ * macosx/tkMacOSXPrivate.h: API, and private helpers to operate on
+ HIShapeRefs & convert to/from TkRegion
+
+ * macosx/tkMacOSXRegion.c: add Tkp{Retain,Release}Region() API
+ * macosx/tkMacOSXInt.h: for TkRegion.
+
+ * xlib/xgc.c: factor out alloc/free of GC clip_mask;
+ * macosx/tkMacOSXXStubs.c: manage clip rgn lifetime with new
+ Tkp{Retain,Release}Region().
+
+ * macosx/tkMacOSXButton.c: delay picParams setup until needed.
+
+ * generic/tkTextDisp.c (CharUndisplayProc): fix textDisp.test crash.
+
+2007-10-11 David Gravereaux <davygrvy@pobox.com>
+
+ * win/winMain.c: Replaced incorrect comments in main() to descibe why
+ the console widget does not need to be created for this application
+ entry point (if used). Must have been a bad copy/paste of WinMain()
+ from 10 years back.
+
+2007-10-11 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXWm.c (TkMacOSXGrowToplevel): manually constrain resize
+ limitBounds to maxBounds, works around SectRect() mis-feature (return
+ zero rect if input rect has zero height/width). [Bug 1810818]
+
+2007-10-09 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * generic/tkImage.c: Make Ttk_GetImage safe if called with NULL
+ * tests/ttk/image.test: interp. Added some tests that crash on Windows
+ without this fix.
+
+2007-10-02 Don Porter <dgp@users.sourceforge.net>
+
+ [core-stabilizer-branch]
+
+ * README: Bump version number to 8.5.0
+ * generic/tk.h:
+ * library/tk.tcl:
+ * unix/configure.in: Updated LOCALES.
+ * unix/tk.spec:
+ * win/configure.in:
+
+ * unix/configure: autoconf (2.59)
+ * win/configure:
+
+2007-09-30 Joe English <jenglish@users.sourceforge.net>
+
+ * library/ttk/entry.tcl (WordBack, WordForward):
+ Fix private routines accidentally defined in global namespace
+ [Bug 1803836]
+
+2007-09-26 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * library/msgs/hu.msg: Added Hungarian message set, from Pader Reszo.
+ [Patch 1800742]
+
+2007-09-20 Donal K. Fellows <dkf@users.sf.net>
+
+ *** 8.5b1 TAGGED FOR RELEASE ***
+
+ * generic/tkTextDisp.c (LayoutDLine): Only call callbacks that are
+ * tests/textDisp.test (textDisp-32.3): not NULL. [Bug 1791052]
+
+2007-09-20 Don Porter <dgp@users.sourceforge.net>
+
+ * changes: updates for 8.5b1 release.
+
+2007-09-19 Don Porter <dgp@users.sourceforge.net>
+
+ * README: Bump version number to 8.5b1.
+ * generic/tk.h: Merge from core-stabilizer-branch.
+ * library/tk.tcl: Stabilizing toward 8.5b1 release now done
+ * unix/configure.in: on the HEAD. core-stabilizer-branch is
+ * unix/tk.spec: now suspended.
+ * win/configure.in:
+
+2007-09-19 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * generic/tkStubLib.: Replaced isdigit with internal implementation.
+
+2007-09-18 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkStubLib.c: Remove C library calls from Tk_InitStubs()
+ * win/makefile.vc: so that we don't need the C library linked
+ in to libtkStub.
+
+2007-09-18 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tkImgGIF.c (FileReadGIF, StringReadGIF): Rewrite for greater
+ clarity (more comments, saner code arrangement, etc.)
+
+2007-09-18 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * tests/all.tcl: Made ttk/all.tcl be the same as tk's all.tcl and
+ * tests/ttk/all.tcl: make use of file normalize (bugs noted by
+ mjanssen and GPS with msys)
+
+2007-09-17 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/makefile.vc: Add crt flags for tkStubLib now it uses C-library
+ functions.
+
+2007-09-17 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/tcl.m4: use '${CC} -shared' instead of 'ld -Bshareable' to
+ build shared libraries on current NetBSDs. [Bug 1749251]
+ * unix/configure: regenerated (autoconf-2.59).
+
+2007-09-17 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkConsole.c: Revised callers of Tcl_InitStubs() to account
+ * generic/tkMain.c: for restored compatible support for the call
+ * generic/tkWindow.c: Tcl_InitStubs(interp, TCL_VERSION, 1). Also
+ revised Tcl_PkgRequire() call for Tcl so that, for example, a Tk
+ library built against Tcl 8.5.1 headers will not refuse to [load] into
+ a Tcl 8.5.0 interpreter. [Tcl Bug 1578344]
+
+ * generic/tk.h: Revised Tk_InitStubs() to restore Tk 8.4
+ * generic/tkStubLib.c: source compatibility with callers of
+ * generic/tkWindow.c: Tk_InitStubs(interp, TK_VERSION, 1).
+
+2007-09-17 Joe English <jenglish@users.sourceforge.net>
+
+ * library/ttk/combobox.tcl: Try to improve combobox appearance on
+ OSX + Tk 8.5. [Bug 1780286]
+
+2007-09-15 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/tcl.m4: replace all direct references to compiler by ${CC} to
+ enable CC overriding at configure & make time; run
+ check for visibility "hidden" with all compilers;
+ quoting fixes from TEA tcl.m4.
+ (SunOS-5.1x): replace direct use of '/usr/ccs/bin/ld' in SHLIB_LD by
+ 'cc' compiler driver.
+ * unix/configure: autoconf-2.59
+
+2007-09-14 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Wish-Common.xcconfig: enable Tcl DTrace support.
+ * macosx/Wish.xcodeproj/project.pbxproj:
+
+2007-09-12 Andreas Kupries <andreask@activestate.com>
+
+ * win/Makefile.in (install-binaries): Fixed missing brace in the
+ * win/makefile.vc (install-binaries): generated package index file.
+ Note: unix/Makefile.in is good.
+
+2007-09-11 Reinhard Max <max@suse.de>
+
+ * generic/tkImgGIF.c: Fixed a buffer overrun that got triggered by
+ multi-frame interlaced GIFs that contain subsequent frames that are
+ smaller than the first one.
+
+ * tests/imgPhoto.test: Added a test for the above.
+
+2007-09-11 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkConsole.c: Revised calls to Tcl_InitStubs() and
+ * generic/tkMain.c: [package require Tcl] so that Tk Says What It
+ * generic/tkWindow.c: Means using the new facilties of [package] in
+ * library/tk.tcl: Tcl 8.5 about what version(s) of Tcl it is
+ * unix/Makefile.in: willing to work with. [Bug 1578344]
+ * win/Makefile.in:
+ * win/makefile.vc:
+
+2007-09-10 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/README: typo corrections [Bug 1788682]
+
+2007-09-10 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkConsole.c: Revise all Tcl_InitStubs() calls to restore
+ * generic/tkMain.c: the traditional practice that a Tk shared
+ * generic/tkWindow.c: library may [load] into a Tcl 8.5 interp at
+ any patchlevel. This practice also matches the compile time checks of
+ TCL_MAJOR_VERSION and TCL_MINOR_VERSION in tk.h. [Bug 1723622]
+
+2007-09-06 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkWindow.c (Initialize): Moved common Tk initialization
+ * generic/tkInitScript.h (removed): script out of tkInitScript.h
+ * macosx/tkMacOSXInit.c: and multiple TkpInit() routines and
+ * unix/Makefile.in: into the common Initialize() routine in
+ * unix/tkUnixInit.c: generic code. Also removed constraint on
+ * win/tkWinInit.c: ability to define a custom [tkInit] before
+ calling Tk_Init(). Until now the custom [tkInit] had to be a proc. Now
+ it can be any command. Removal of tkInitScript.h also fixes [Bug
+ 1656283].
+
+2007-09-06 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Wish.xcode/project.pbxproj: discontinue unmaintained support
+ * macosx/Wish.xcode/default.pbxuser: for Xcode 1.5; replace by Xcode2
+ project for use on Tiger (with Wish.xcodeproj to be used on Leopard).
+
+ * macosx/Wish.xcodeproj/project.pbxproj: updates for Xcode 2.5 and 3.0.
+ * macosx/Wish.xcodeproj/default.pbxuser:
+ * macosx/Wish.xcode/project.pbxproj:
+ * macosx/Wish.xcode/default.pbxuser:
+ * macosx/Wish-Common.xcconfig:
+
+ * macosx/README: document project changes.
+
+2007-09-04 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/tkTest.c: Fix for [Bug 1788019] "tkTest.c compiler warning".
+
+2007-09-04 Don Porter <dgp@users.sourceforge.net>
+
+ * unix/Makefile.in: It's unreliable to count on the release
+ manager to remember to `make genstubs` before `make dist`. Let the
+ Makefile remember the dependency for us.
+
+ * unix/Makefile.in: Corrections to `make dist` dependencies to be
+ sure that macosx/configure gets generated whenever it does not exist.
+
+2007-09-03 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/ttk/ttkInit.c (Ttk_Init): register ttk in package database
+ to enable extension access to the ttkStubs table.
+
+ * generic/ttk/ttkDecls.h: correct capitalization of ttk package name.
+
+2007-08-28 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ Assorted documentation improvements.
+ * doc/button.n: Added examples.
+ * doc/checkbutton.n: Added example.
+ * doc/console.n: Standardized section ordering.
+ * doc/tk.n: Added "See also".
+ * doc/ttk_combobox.n: Added keywords.
+
+2007-08-27 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXDialog.c (Tk_ChooseColorObjCmd): correct setting of
+ interp result [Bug 1782105]; fix -initialcolor overwriting last color
+ selection; style cleanup.
+
+2007-08-21 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/rules.vc: Synchronize with tcl rules.vc
+ * tests/all.tcl: Fix the line-endings.
+
+2007-08-07 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/Makefile.in: Add support for compile flags specific to
+ object files linked directly into executables.
+
+ * unix/configure.in (Darwin): Only use -seg1addr flag when prebinding;
+ use -mdynamic-no-pic flag for object files linked directly into exes.
+
+ * unix/configure: autoconf-2.59
+
+2007-08-01 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tkWinDialog.c: Fix [Bug 1692927] (buffer length problems)
+ * win/tkWinTest.c: Added 'testfindwindow' and 'testgetwindowinfo'
+ and extended 'testwinevent' for WM_COMMAND support to enable testing
+ native messagebox dialogs.
+ * tests/winMsgbox.test: New Windows native messagebox tests.
+
+2007-07-25 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXDialog.c (NavServicesGetFile): Reset interp result on
+ nav dialog cancel. [Bug 1743786]
+
+2007-07-09 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/Makefile.in: clarify what the headers installed are, and
+ add ttkTheme.h and ttkDecls.h to private headers (later public).
+
+2007-07-09 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXWindowEvent.c (Tk_MacOSXIsAppInFront): Use process mgr
+ * macosx/tkMacOSXMouseEvent.c: to determine if
+ app is in front instead of relying on activate/deactivate events (which
+ may arrive after this info is needed, e.g. during window drag/click
+ activation); replace other process mgr use to get this info with calls
+ to Tk_MacOSXIsAppInFront().
+
+ * macosx/tkMacOSXMouseEvent.c (TkMacOSXProcessMouseEvent): Correct
+ window click activation, titlebar click handling and background window
+ dragging/growing in the presence of grabs or window-/app-modal windows;
+ fix window click activation bringing all other app windows to front.
+
+ * macosx/tkMacOSXDraw.c (TkPutImage): Handle non-native XImage byte and
+ bit orders; reverse bits via xBitReverseTable instead of InvertByte().
+
+2007-07-06 Joe English <jenglish@users.sourceforge.net>
+
+ * library/ttk/aquaTheme.tcl: Set -anchor w for TMenubuttons.
+ [Bug 1614540]
+
+2007-07-04 Andreas Kupries <andreask@activestate.com>
+
+ * macosx/tkMacOSXXStubs.c (DestroyImage): Fixed seg.fault in release
+ of image data for images coming from XGetImage. Change committed by me
+ for Daniel Steffen. See 2007-06-23 for the change which introduced the
+ problem.
+
+2007-07-02 Daniel Steffen <das@users.sourceforge.net>
+
+ * xlib/xgc.c (XCreateGC): Correct black and white pixel values used to
+ initialize GC foregrund and background fields.
+
+ * macosx/tkMacOSXColor.c: Add debug messages for unknown pixel values.
+
+ * macosx/tkMacOSXDraw.c (TkMacOSXRestoreDrawingContext): Don't restore
+ port state if it wasn't altered by TkMacOSXSetupDrawingContext().
+
+2007-06-29 Daniel Steffen <das@users.sourceforge.net>
+
+ * xlib/ximage.c: Bitmaps created from the static .xbm
+ arrays always have LSBFirst bit order.
+
+ * unix/configure.in: Fix flag used to weak-link libXss.
+ * unix/configure: autoconf-2.59
+
+ * macosx/tkMacOSXScrlbr.c: Correct int <-> dobule conversion issues
+ that could lead to Carbon getting confused about scrollbar thumb size.
+
+ * macosx/tkMacOSXDraw.c (XCopyArea, XCopyPlane, TkPutImage): Use
+ TkMacOSX{Setup,Restore}DrawingContext() to setup/restore clip & colors.
+ (TkMacOSXSetupDrawingContext, TkMacOSXRestoreDrawingContext): Add save
+ and restore of QD port clip region; factor out clip region code common
+ to CG and QD branches; check for port and context validity; handle
+ tkPictureIsOpen flag during QD port setup.
+ (TkScrollWindow): Remove unnecessary scroll region manipulation
+
+ * macosx/tkMacOSXDraw.c: Remove second global QD temp region
+ * macosx/tkMacOSXInt.h: (no longer necessary) and rename
+ * macosx/tkMacOSXRegion.c: remaining global QD temp region.
+ * macosx/tkMacOSXSubwindows.c:
+ * macosx/tkMacOSXWindowEvent.c:
+
+ * macosx/tkMacOSXDraw.c: Make useCGDrawing variable MODULE_SCOPE
+ * macosx/tkMacOSXFont.c: and respect it for ATSUI font drawing.
+
+ * macosx/tkMacOSXButton.c: Reduce reliance on current QD port
+ * macosx/tkMacOSXColor.c: setting and remove unnecessary
+ * macosx/tkMacOSXDebug.c: references to a drawable's QD port,
+ * macosx/tkMacOSXDebug.h: notably replace GetWindowFromPort(
+ * macosx/tkMacOSXDialog.c: TkMacOSXGetDrawablePort()) idiom by new
+ * macosx/tkMacOSXDraw.c: TkMacOSXDrawableWindow() and change
+ * macosx/tkMacOSXKeyEvent.c: TkMacOSXSetColorInPort() to take a port
+ * macosx/tkMacOSXMenu.c: argument.
+ * macosx/tkMacOSXMenubutton.c:
+ * macosx/tkMacOSXMouseEvent.c:
+ * macosx/tkMacOSXScale.c:
+ * macosx/tkMacOSXScrlbr.c:
+ * macosx/tkMacOSXSubwindows.c:
+ * macosx/tkMacOSXWindowEvent.c:
+ * macosx/tkMacOSXWm.c:
+
+ * macosx/tkMacOSXInt.h: Factor out macros, declarations
+ * macosx/tkMacOSXPrivate.h (new): and prototypes that are purely
+ internal and private to the 'macosx' sources into a new internal header
+ file that does _not_ get installed into Tk.framework/PrivateHeaders.
+
+ * macosx/tkMacOSXButton.c: #include new tkMacOSXPrivate.h
+ * macosx/tkMacOSXCarbonEvents.c: instead of tkMacOSXInt.h.
+ * macosx/tkMacOSXClipboard.c:
+ * macosx/tkMacOSXColor.c:
+ * macosx/tkMacOSXCursor.c:
+ * macosx/tkMacOSXDebug.c:
+ * macosx/tkMacOSXDialog.c:
+ * macosx/tkMacOSXDraw.c:
+ * macosx/tkMacOSXEntry.c:
+ * macosx/tkMacOSXEvent.c:
+ * macosx/tkMacOSXFont.c:
+ * macosx/tkMacOSXHLEvents.c:
+ * macosx/tkMacOSXInit.c:
+ * macosx/tkMacOSXKeyEvent.c:
+ * macosx/tkMacOSXMenu.c:
+ * macosx/tkMacOSXMenubutton.c:
+ * macosx/tkMacOSXMenus.c:
+ * macosx/tkMacOSXMouseEvent.c:
+ * macosx/tkMacOSXNotify.c:
+ * macosx/tkMacOSXRegion.c:
+ * macosx/tkMacOSXScale.c:
+ * macosx/tkMacOSXScrlbr.c:
+ * macosx/tkMacOSXSubwindows.c:
+ * macosx/tkMacOSXWindowEvent.c:
+ * macosx/tkMacOSXWm.c:
+ * macosx/tkMacOSXXStubs.c:
+ * macosx/ttkMacOSXTheme.c:
+
+ * macosx/Wish.xcodeproj/project.pbxproj: Improve support for renamed
+ * macosx/Wish.xcodeproj/default.pbxuser: tcl and tk source dirs; add
+ * macosx/Wish-Common.xcconfig: 10.5 SDK build config; remove
+ tclMathOp.c.
+
+ * macosx/README: Document Wish.xcodeproj changes.
+
+2007-06-23 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tkImgPhoto.c (ImgPhotoConfigureInstance, DisposeInstance):
+ Use XDestroyImage instead of XFree to destroy XImage; replace runtime
+ endianness determination by compile-time check for WORDS_BIGENDIAN.
+
+ * xlib/ximage.c (XCreateBitmapFromData): Use XCreateImage and
+ XDestroyImage instead of creating XImage structure manually.
+
+ * macosx/tkMacOSXXStubs.c (XCreateImage, DestroyImage): Correct XImage
+ bytes_per_line/bitmap_pad calculations and endianness setting; free
+ image data and XImage structure at destruction; formatting cleanup.
+
+ * macosx/tkMacOSXDialog.c (NavServicesGetFile): Disable app-modal
+ sheet variant of nav dialog on OS versions where it causes problems.
+
+2007-06-20 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/ttk/ttk.tcl: Should require Tk before pseudo-providing
+ tile 0.8.0.
+
+2007-06-09 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkPanedwindow.c, doc/ttk_panedwindow.n,
+ * tests/ttk/panedwindow.test: Added -width and -height options. Added
+ 'panes' method, return list of managed windows. 'sashpos' method is
+ now documented as part of the public interface, and details clarified.
+ Should be easier to set initial sash positions now. Alleviates [Bug
+ 1659067].
+
+2007-06-09 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinWm.c (WmIconphotoCmd): fix wm iconphoto RGBA issues.
+ [Bug 1467997] (janssen)
+
+ * win/tkWinMenu.c (TkWinHandleMenuEvent): Improve handling to allow
+ for unicode char menu indices and not use CharUpper on Tcl utf
+ strings. [Bug 1734223]
+
+2007-06-09 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkManager.h, generic/ttk/ttkManager.c,
+ * generic/ttk/ttkNotebook.c, generic/ttk/ttkPanedwindow.c,
+ * generic/ttk/ttkFrame.c: Ttk_Manager API overhaul:
+ + Ttk_Manager no longer responsible for managing slave records
+ + Ttk_Manager structure now opaque
+ + Ttk_Slave structure now private
+ + Pass Ttk_Manager* to Tk_GeomMgr hooks instead of Ttk_Slave*
+
+ * generic/ttk/ttkFrame.c: Simplified -labelwidget management.
+
+ * doc/ttk_panedwindow.n, library/ttk/panedwindow.tcl: Changed
+ documentation of ttk::panedwindow 'identify' command to match
+ implementation.
+
+ * generic/ttk/ttkNotebook.c, tests/ttk/notebook.test:
+ BUGFIX: ttk::noteboook 'insert' command didn't correctly maintain
+ current tab.
+
+2007-06-09 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXColor.c: Fix issues with TK_{IF,ELSE,ENDIF} macros;
+ * macosx/tkMacOSXDraw.c: implement Jaguar equivalent of unavailable
+ * macosx/tkMacOSXEntry.c: kHIToolboxVersion global; panic at startup
+ * macosx/tkMacOSXEvent.c: if MAC_OS_X_VERSION_MIN_REQUIRED constraint
+ * macosx/tkMacOSXInit.c: is not satisfied.
+ * macosx/tkMacOSXInt.h:
+ * macosx/tkMacOSXWm.c:
+
+ * macosx/tkMacOSXDraw.c (XCopyArea, XCopyPlane, TkPutImage)
+ (TkMacOSXSetupDrawingContext): Factor out common code and standardize
+ setup/restore of port, context and clipping; formatting cleanup.
+
+ * macosx/tkMacOSXWindowEvent.c: Add error checking.
+ * macosx/tkMacOSXMenu.c: Fix gcc3 warning.
+ * macosx/tkMacOSXScrlbr.c: Fix testsuite crash.
+ * macosx/tkMacOSXSubwindows.c: Formatting cleanup.
+ * macosx/tkMacOSXRegion.c: Fix typos.
+ * macosx/tkMacOSXScale.c:
+
+ * macosx/tkMacOSXXStubs.c (Tk_GetUserInactiveTime): Remove superfluous
+ CFRetain/CFRelease.
+
+ * macosx/Wish-Release.xcconfig: Disable tktest release build stripping.
+
+ * macosx/Wish.xcodeproj/project.pbxproj: Add new Tclsh-Info.plist.in.
+
+2007-06-06 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXInt.h: Use native debug message API when available.
+ * macosx/Wish-Debug.xcconfig:
+
+ * macosx/tkMacOSXMouseEvent.c (GenerateMouseWheelEvent): Enable
+ processing of mousewheel events in background windows.
+
+ * macosx/tkMacOSXScrlbr.c: Modernize checks for active/front window.
+ * macosx/tkMacOSXScale.c:
+ * macosx/tkMacOSXWm.c:
+
+ * macosx/tkMacOSXColor.c: Factor out verbose #ifdef checks of
+ * macosx/tkMacOSXDraw.c: MAC_OS_X_VERSION_{MAX_ALLOWED,MIN_REQUIRED}
+ * macosx/tkMacOSXEntry.c: and runtime checks of kHIToolboxVersion into
+ * macosx/tkMacOSXEvent.c: new TK_{IF,ELSE,ENDIF}_MAC_OS_X macros.
+ * macosx/tkMacOSXInit.c:
+ * macosx/tkMacOSXInt.h:
+ * macosx/tkMacOSXWm.c:
+
+ * macosx/tkMacOSXDraw.c: Factor out clip clearing in QD ports;
+ * macosx/tkMacOSXEntry.c: Formatting cleanup.
+
+ * macosx/Wish.xcodeproj/project.pbxproj: Add settings for Fix&Continue.
+
+ * unix/configure.in (Darwin): Link the Tk and Wish plists into their
+ binaries in all cases; fix 64bit arch removal in fat 32&64bit builds.
+
+ * unix/tcl.m4 (Darwin): Fix CF checks in fat 32&64bit builds.
+ * unix/configure: autoconf-2.59
+
+2007-06-05 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/photo.n: Clarified the fact that base64 support for the -data
+ option is not universal. [Bug 1731348] (matzek)
+
+2007-06-03 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/Makefile.in: Add datarootdir to silence autoconf-2.6x warning.
+
+ * macosx/Wish.xcodeproj/default.pbxuser: Add ttk tests.
+
+ * macosx/tkMacOSXMenu.c: Add error checking; whitespace cleanup.
+
+ * macosx/tkMacOSXDraw.c: Comment formatting fixes for Xcode 3.0
+ * macosx/tkMacOSXEmbed.c:
+ * macosx/tkMacOSXEntry.c:
+ * macosx/tkMacOSXFont.c:
+ * macosx/tkMacOSXInit.c:
+ * macosx/tkMacOSXKeyEvent.c:
+ * macosx/tkMacOSXKeyboard.c:
+ * macosx/tkMacOSXMenus.c:
+ * macosx/tkMacOSXSend.c:
+ * macosx/tkMacOSXSubwindows.c:
+ * macosx/tkMacOSXWindowEvent.c:
+ * macosx/tkMacOSXWm.c:
+ * macosx/tkMacOSXXStubs.c:
+
+2007-06-02 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXMenu.c (TkpPostMenu): Ensure cascade menus display in
+ posted menus that are not part of the menubar or attached to a
+ menubutton (fixes bug reported on tcl-mac by Linus Nyberg).
+
+2007-05-31 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXWindowEvent.c (GenerateUpdateEvent): Complete all
+ pending idle-time redraws before newly posted Expose events are
+ processed; add bounds of redrawn windows to update region to ensure
+ all child windows overdrawn by parents are redrawn.
+
+ * macosx/tkMacOSXWindowEvent.c: Centralize clip and window invalidation
+ * macosx/tkMacOSXSubwindows.c: after location/size changes in the
+ * macosx/tkMacOSXWm.c: BoundsChanged carbon event handler;
+ correct/add window invalidation after window attribute changes.
+
+ * macosx/tkMacOSXSubwindows.c (XResizeWindow, XMoveResizeWindow)
+ (XMoveWindow): Factor out common code dealing with embedded and
+ non-toplevel windows; remove unnecessary clip and window invalidation.
+
+ * macosx/tkMacOSXButton.c (TkpDisplayButton): Move clip setup closer
+ to native button drawing calls.
+
+ * macosx/tkMacOSXWm.c (TkMacOSXIsWindowZoomed, TkMacOSXZoomToplevel):
+ Correct handling of gridded windows in max size calculations.
+
+ * macosx/tkMacOSXEvent.c (TkMacOSXFlushWindows): Use HIWindowFlush API
+ when available.
+
+ * macosx/tkMacOSXColor.c: Cleanup whitespace and formatting.
+ * macosx/tkMacOSXDraw.c:
+ * macosx/tkMacOSXSubwindows.c:
+ * macosx/tkMacOSXWm.c:
+
+ * generic/tkFont.c: #ifdef out debug msg printing to stderr.
+ * generic/tkTextDisp.c:
+
+2007-05-30 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tk.h: Correct placement of #include <tcl.h>. [Bug 1723812]
+
+2007-05-30 Daniel Steffen <das@users.sourceforge.net>
+
+ * library/bgerror.tcl: Standardize dialog option & button size
+ * library/dialog.tcl: modifications done when running on on Aqua.
+ * library/msgbox.tcl:
+
+ * library/demos/button.tcl: Set button highlightbackground on Aqua.
+
+ * macosx/tkMacOSXMenu.c (DrawMenuSeparator): Use DrawingContext API.
+
+ * macosx/tkMacOSXWindowEvent.c (ClearPort): Clip to updateRgn.
+
+ * macosx/tkMacOSXDebug.c: Factor out debug region flashing.
+ * macosx/tkMacOSXDebug.h:
+ * macosx/tkMacOSXDraw.c:
+ * macosx/tkMacOSXSubwindows.c:
+ * macosx/tkMacOSXWindowEvent.c:
+
+ * macosx/tkMacOSXEvent.c: Cleanup whitespace and formatting.
+ * macosx/tkMacOSXFont.c:
+ * macosx/tkMacOSXRegion.c:
+ * macosx/tkMacOSXSubwindows.c:
+ * macosx/tkMacOSXWindowEvent.c:
+ * macosx/tkMacOSXWm.c:
+ * macosx/tkMacOSXXStubs.c:
+ * xlib/xgc.c:
+
+ * macosx/Wish.xcodeproj/project.pbxproj: Delete references to removed
+ * macosx/Wish.xcodeproj/default.pbxuser: ttk files.
+
+2007-05-28 Benjamin Riefenstahl <b.riefenstahl@turtle-trading.net>
+
+ * macosx/tkMacOSXFont.c (TkpMeasureCharsInContext): Fix short measures
+ with flags=TK_WHOLE_WORDS|TK_AT_LEAST_ONE [Bug 1716141]. Make some
+ casts unnecessary by changing variable types.
+
+2007-05-25 Joe English <jenglish@users.sourceforge.net>
+
+ * library/ttk/ttk.tcl: Omit ttk::dialog and dependencies.
+ * library/ttk/dialog.tcl, library/ttk/icons.tcl,
+ * library/ttk/keynav.tcl: Removed.
+ * tests/ttk/misc.test: Removed.
+ * doc/ttk_dialog.tcl: Removed.
+
+2007-05-25 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/canvas.n: Fixed documentation of default -joinstyle option
+ values for line and polygon items. [Bug 1725782]
+
+2007-05-22 Don Porter <dgp@users.sourceforge.net>
+
+ [core-stabilizer-branch]
+
+ * unix/configure: autoconf-2.59 (FC6 fork)
+ * win/configure:
+
+ * README: Bump version number to 8.5b1
+ * generic/tk.h:
+ * library/tk.tcl:
+ * unix/configure.in:
+ * unix/tk.spec:
+ * win/configure.in:
+
+2007-05-18 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkEntry.c(EntrySetValue): Ensure that widget is in a
+ consistent state before setting the linked -textvariable. Previously,
+ it was possible for [$e index insert] to point past the end of the
+ string, leading to heap corruption. [Bug 1721532]
+ * tests/ttk/entry.test(entry-9.1): Add test case for the above.
+
+2007-05-18 Don Porter <dgp@users.sourceforge.net>
+
+ * unix/configure: autoconf-2.59 (FC6 fork)
+ * win/configure:
+
+ * README: Bump version number to 8.5a7
+ * generic/tk.h:
+ * library/tk.tcl:
+ * unix/configure.in:
+ * unix/tk.spec:
+ * win/configure.in:
+
+ * tests/ttk/treetags.test: Another bit of test suite
+ SCIM-tolerance. [Bug 1609316]
+
+2007-05-17 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tk.decls: Workaround 'make checkstubs' failures from
+ tkStubLib.c MODULE_SCOPE revert. [Bug 1716117]
+
+ * macosx/Wish.xcodeproj/project.pbxproj: Add tkOldTest.c and remove
+ tkStubImg.c.
+
+2007-05-16 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/tkStubLib.c: Change Tk_InitStubs(), tkStubsPtr, and the
+ auxilliary stubs table pointers back to public visibility. See [Bug
+ 1716117] for details.
+
+ Removed TCL_STORAGE_CLASS monkey business, as it had no effect.
+
+2007-05-16 Don Porter <dgp@users.sourceforge.net>
+
+ * library/choosedir.tcl: Removed uses of obsolete {expand}
+ * library/comdlg.tcl: syntax; replaced with the now
+ * library/tk.tcl: approved {*}. [Bug 1710633]
+ * tests/canvImg.test:
+ * tests/imgPhoto.test:
+
+ * tests/bind.test: Make test suite more SCIM-tolerant. [Bug 1609316]
+
+2007-05-16 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/makefile.vc: Test ttk widgets.
+
+2007-05-15 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/tkUnixRFont.c: Fix crash introduced by previous fix exposed
+ under newer fontconfig libraries [Bug 1717830] again.
+
+2007-05-15 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkGrid.c: Stop crash due to list intrep shimmer [Bug 1677608]
+
+2007-05-15 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/tkUnixRFont.c: Fix various memory leaks. [Bug 1717830], [Bug
+ 800149]
+
+2007-05-14 Don Porter <dgp@users.sourceforge.net>
+
+ [Tk Bug 1712081]
+
+ * unix/Makefile.in: Updates to account for new and deleted files
+ * win/Makefile.in: tkStubImg.c and tkOldTest.c.
+ * win/makefile.bc:
+ * win/makefile.vc:
+
+ * generic/tkOldTest.c (new): New file used to create testing
+ * generic/tkTest.c: commands for testing various Tk
+ * tests/constraints.tcl: legacy interfaces where a separate
+ * tests/image.test: compilation unit is needed in order to
+ #define suitable macros during compilation. Only the effect of
+ USE_OLD_IMAGE on Tk_CreateImageType() is currently tested, but more
+ similar testing commands can be added to this same file. New
+ constraint defined to detect presence of the image type provided by
+ the new testing code, and a few tests added to exercise it. Having
+ USE_OLD_IMAGE support tested by the default test suite should reduce
+ chance of a recurrence of this bug.
+
+ * doc/CrtImgType.3: Revised docs to better indicate the legacy
+ * doc/CrtPhImgFmt.3: nature of the interfaces supported by
+ USE_OLD_IMAGE.
+
+ * generic/tkDecls.h: make genstubs
+ * generic/tkStubInit.c:
+
+ * generic/tk.decls: Reworked USE_OLD_IMAGE support to use
+ * generic/tk.h: the same support mechanisms both with
+ * generic/tkStubImg.c (deleted):and without a stub-enabled build. In
+ each case, route the legacy calls to Tk_CreateImageType and
+ Tk_CreatePhotoImageFormat through the Tk_CreateOldImageType and
+ Tk_CreateOldPhotoImageFormat routines. Add those routines to the
+ public stub table so they're available to a stub-enabled extension.
+ Remove the definition of Tk_InitImageArgs() and use a macro to convert
+ any calls to it in source code into a comment.
+
+ * generic/tkImage.c: Removed the MODULE_SCOPE declarations that
+ * generic/tkImgPhoto.c: broke USE_OLD_IMAGE support.
+
+2007-05-11 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * tests/winButton.test: Avoid font dependencies in results.
+
+ * generic/tkFont.c: propagate error from TkDeleteNamedFont. [Bug
+ 1716613]
+
+2007-05-09 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tkFileFilter.c (AddClause): OSType endianness fixes.
+
+ * library/palette.tcl (tk::RecolorTree): Handle color options with
+ empty value, fixes error due to emtpy -selectforeground (reported on
+ tcl-mac by Russel E. Owen).
+
+ * macosx/tkMacOSXWindowEvent.c: Ensure window is brought to the front
+ * macosx/tkMacOSXMouseEvent.c: at the start of a window drag (except
+ * macosx/tkMacOSXInt.h: when cmd key is down); formatting and
+ whitespace fixes.
+
+ * macosx/tkMacOSXDialog.c (Tk_GetSaveFileObjCmd): Add -filetypes option
+ processing (fixes fileDialog-0.1, fileDialog-0.2 failures).
+
+ * macosx/tkMacOSXEmbed.c (TkpMakeWindow, TkpUseWindow): Fix sending of
+ Visibility event for embedded windows (fixes frame-3.9 hang).
+
+ * macosx/tkMacOSXScrlbr.c (ScrollbarBindProc): Fix testsuite
+ * macosx/tkMacOSXSubwindows.c (TkMacOSXUpdateClipRgn): crashes by
+ adding sanity checks.
+
+ * macosx/Wish.xcodeproj/project.pbxproj: Add 'DebugUnthreaded' &
+ * macosx/Wish.xcodeproj/default.pbxuser: 'DebugLeaks' targets and env
+ var settings needed to run the 'leaks' tool.
+
+ * macosx/tkMacOSXButton.c: Fix debug msg typo.
+
+ * tests/constraints.tcl: Ensure 'nonUnixUserInteraction' constraint is
+ set for aqua.
+
+ * tests/choosedir.test: Add 'notAqua' constraints to X11-only tests;
+ * tests/clrpick.test: add 'nonUnixUserInteraction' to 'unix' tests
+ * tests/menuDraw.test: requiring interaction on aqua.
+ * tests/unixMenu.test:
+ * tests/unixWm.test:
+ * tests/winMenu.test:
+
+2007-05-07 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/tkUnixRFont.c: Properly cast sentinel arguments to variadic
+ function (fixes "warning: missing sentinel in function call", [Bug
+ 1712001])
+
+2007-05-04 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * generic/tkFont.c: TIP #145 implementation -
+ * generic/tkFont.h: Enhanced font handling.
+ * win/tkWinDefault.h:
+ * win/tkWinFont.c:
+ * win/tkWinInt.h:
+ * win/tkWinWm.c:
+ * library/demos/widget:
+ * library/ttk/fonts.tcl:
+
+2007-05-04 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/ttk_treeview.n, doc/ttk_panedwindow.n, doc/ttk_dialog.n:
+ * doc/ttk_checkbutton.n, doc/tk.n, doc/menu.n, doc/font.n:
+ * doc/canvas.n: Spelling fixes. [Bug 1686210]
+
+2007-05-03 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tkStubLib.c (Tk_InitStubs):
+ * generic/ttk/ttkLabel.c (LabelSetup):
+ * unix/tkUnixSelect.c (ConvertSelection):
+ * unix/tkUnixEvent.c (TkUnixDoOneXEvent):
+ * generic/tkConfig.c (Tk_RestoreSavedOptions):
+ * generic/tkCanvPs.c (TkCanvPostscriptCmd):
+ * generic/tkOption.c (GetDefaultOptions):
+ * unix/tkUnixRFont.c (TkpGetFontAttrsForChar, InitFont)
+ (TkpGetFontFamilies, TkpGetSubFonts):
+ * unix/tkUnixSend.c (TkpTestsendCmd, RegOpen): Squelch warnings from
+ GCC type aliasing. [Bug 1711985 and others]
+
+2007-04-29 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/configure.in: Fix for default case in tk debug build detection.
+ * unix/configure: autoconf-2.59
+
+2007-04-27 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkTreeview.c(TagOptionSpecs): Use TK_OPTION_STRING
+ instead of TK_OPTION_FONT to avoid resource leak in tag management.
+
+2007-04-26 Joe English <jenglish@users.sourceforge.net>
+
+ * macosx/ttkMacOSXTheme.c: Merged OFFSET_RECT processing into
+ BoxToRect(); factored out PatternOrigin; resynchronized with Tile
+ codebase.
+
+2007-04-26 Jeff Hobbs <jeffh@ActiveState.com>
+
+ *** 8.5a6 TAGGED FOR RELEASE ***
+
+ * unix/Makefile.in (dist): Correct tests/ttk glob inclusion
+
+2007-04-25 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/Makefile.in (dist): Add tests/ttk dir to src dist
+
+ * unix/tkUnixMenubu.c (TkpDisplayMenuButton): Init width/height to 0
+
+2007-04-25 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/Makefile.in (dist): Add macosx/*.xcconfig files to src dist;
+ copy license.terms to dist macosx dir; fix autoheader bits.
+
+2007-04-24 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/Makefile.in (dist): Add ttk bits to src dist
+
+ * tests/font.test (font-46.[12]): Correct listification of result
+
+2007-04-23 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tkCanvas.c: Allow -selectforeground option to be None; add
+ * generic/tkCanvText.c: fallback to fgColor when selFgColor is None
+ * generic/tkEntry.c: (new default on aqua to match native L&F).
+ * generic/tkListbox.c:
+ * generic/tkText.c:
+
+ * generic/tkCanvas.c: Add support for bypassing all of Tk's double
+ * generic/tkEntry.c: buffered drawing into intermediate pixmaps
+ * generic/tkFrame.c: (via TK_NO_DOUBLE_BUFFERING #define), it is
+ * generic/tkListbox.c: unnecessary & wasteful on aqua where all
+ * generic/tkPanedWindow.c: drawing is already double-buffered by the
+ * generic/tkTextDisp.c: window server. (Use of this on other
+ * generic/ttk/ttkWidget.c: platforms would only require implementation
+ * unix/tkUnixScale.c: of TkpClipDrawableToRect()).
+ * macosx/tkMacOSXPort.h:
+
+ * library/bgerror.tcl: On aqua, use moveable alert resp. modal dialog
+ * library/dialog.tcl: window class and corresponding system
+ background pattern; fix button padding.
+
+ * library/tearoff.tcl: Correct aqua menu bar height; vertically offset
+ * library/tk.tcl: aqua tearoff floating window to match menu.
+
+ * library/demos/goldberg.tcl: Fix overwriting of widget demo global.
+
+ * library/demos/menu.tcl: On aqua, use custom MDEF and tearoffs;
+ * library/demos/menubu.tcl: correct menubutton toplevel name.
+
+ * library/demos/puzzle.tcl: Fix button size & padding for aqua.
+ * library/demos/radio.tcl:
+
+ * macosx/tkMacOSXCarbonEvents.c: Add window event target carbon event
+ * macosx/tkMacOSXEvent.c: handler for all kEventClassWindow and
+ * macosx/tkMacOSXEvent.h: kEventClassMouse events; move all
+ * macosx/tkMacOSXNotify.c: remaining events except for
+ * macosx/tkMacOSXWindowEvent.c: kEventClassKeyboard from dispatcher to
+ application event handler; pass event handler callRef downstream; fix
+ debug event tracing; process all tcl event types in carbon event timer;
+ delay carbon event timer first fire; add TkMacOSXTrackingLoop() to mark
+ enter/exit of event tracking loop during which all tcl events but only
+ carbon update events should be processed by the timer (replaces various
+ calls to Tcl_SetServiceMode()); rename TkMacOSXReceiveAndProcessEvent()
+ to TkMacOSXReceiveAndDispatchEvent(), move it from tkMacOSXEvent.c to
+ tkMacOSXCarbonEvents.c and modify it to dequeue only update events
+ during a tracking loop; add TkMacOSXRunTclEventLoop() to standardize
+ the various ways in use to run the tcl event loop; add handling of
+ kEventClassAppearance events (for ScrollBarVariantChanged event).
+
+ * macosx/tkMacOSXDialog.c: Use new TkMacOSXTrackingLoop() around
+ * macosx/tkMacOSXEvent.c: blocking API that puts up modal dialogs
+ * macosx/tkMacOSXMenu.c: or when entering/exiting menu/control
+ * macosx/tkMacOSXMouseEvent.c: tracking, window dragging and other
+ * macosx/tkMacOSXScale.c: mouse tracking loops.
+ * macosx/tkMacOSXScrlbr.c:
+ * macosx/tkMacOSXWindowEvent.c:
+ * macosx/tkMacOSXWm.c:
+
+ * macosx/tkMacOSXDialog.c: Use new TkMacOSXRunTclEventLoop()
+ * macosx/tkMacOSXScale.c: instead of Tcl_DoOneEvent(),
+ * macosx/tkMacOSXScrlbr.c: Tcl_ServiceAll(), TclServiceIdle()
+ * macosx/tkMacOSXWindowEvent.c: and Tcl_GlobalEval("update idletasks").
+
+ * macosx/tkMacOSXColor.c: Make available as Tk system colors all
+ * macosx/tkMacOSXPort.h: appearance manager brushes, text colors and
+ backgrounds with new and legacy names, as well as the fully transparent
+ color "systemTransparent"; add TkMacOSXSetColorIn{Port,Context}() to
+ directly set an X pixel color value in the current QD port resp. the
+ given CG context without requiring passage through rgb representation
+ (lossy for most system colors); modernize/remove Classic-era code;
+ replace crufty strcmp() elseifs by Tcl_GetIndexFromObjStruct().
+
+ * macosx/tkMacOSXButton.c: Use new TkMacOSXSetColorInPort()
+ * macosx/tkMacOSXDraw.c: instead of setting rgb color directly
+ * macosx/tkMacOSXMenubutton.c: to allow for non-rgb system colors.
+
+ * macosx/tkMacOSXCursor.c: Implement "none" cursor as on other
+ platforms [Patch 1615427]; add all missing appearance manager cursors.
+
+ * macosx/tkMacOSXDefault.h: Set SELECT_FG_COLORs to None to match aqua
+ L&F; use standard system color names; use new 'menu' system font;
+ correct default scrollbar width.
+
+ * macosx/tkMacOSXDraw.c: Standardize initialization, use and
+ * macosx/tkMacOSXInt.h: emptying of various static temp rgns
+ * macosx/tkMacOSXRegion.c: onto two global RgnHandles; in debug
+ * macosx/tkMacOSXSubwindows.c: builds, verify emptiness of these temp
+ * macosx/tkMacOSXWindowEvent.c: rgns before use.
+
+ * macosx/tkMacOSXDraw.c: Add TkMacOSX{Setup,Restore}DrawingContext() to
+ * macosx/tkMacOSXInt.h: abstract common setup & teardown of drawing
+ environment (for both CG and QD); save/restore QD theme drawing state;
+ handle GC clip region; add TkpClipDrawableToRect() to allow clipped
+ drawing into drawable regardless of GC used; use new system color
+ "systemWindowHeaderBackground" to setup background in themed toplevels;
+ correct implementation of TkMacOSXMakeStippleMap().
+
+ * macosx/tkMacOSXEntry.c: Use new TkMacOSXSetupDrawingContext() and
+ * macosx/tkMacOSXFont.c: TkMacOSXRestoreDrawingContext() instead of
+ * macosx/ttkMacOSXTheme.c: various setup/teardown procs like
+ TkMacOSX{SetUp,Release}CGContext(), TkMacOSXQuarz{Start,End}Draw(),
+ TkMacOSXSetUpGraphicsPort() etc.
+
+ * macosx/tkMacOSXEmbed.c: Add CG context and drawable clip rgn fields
+ * macosx/tkMacOSXInt.h: to MacDrawable struct.
+ * macosx/tkMacOSXSubwindows.c:
+
+ * macosx/tkMacOSXDialog.c: Make -parent option of tk_getOpenFile et al.
+ use the sheet version of NavServices dialogs; ensure native parent win
+ exists before using StandardSheet API for tk_messageBox [Bug 1677611];
+ force sheets to behave like app-modal dialogs via WindowModality() API;
+ use more modern ColorPicker API.
+
+ * macosx/tkAboutDlg.r: Use themed movable modal dialog, fix (c) year.
+
+ * macosx/tkMacOSXEntry.c: Take xOff/yOff of MacDrawable into account
+ * macosx/ttkMacOSXTheme.c: when computing locations/bounds to ensure
+ correct posititioning when not drawing into intermediate pixmap.
+
+ * macosx/tkMacOSXFont.c: Use appearance manager API to map system font
+ * macosx/tkMacOSXFont.h: names to TkFonts; add "menu" system font for
+ menu item text drawing from MDEF; always draw with CG; remove QD
+ dependent stippling algorithm; move most header declarations into the
+ source file (as they were not used anywhere else).
+
+ * macosx/tkMacOSXMenu.c: Large-scale rewrite of custom
+ * macosx/tkMacOSXMenu.r (removed): MDEF and related code that
+ * macosx/Wish.xcode/project.pbxproj: restores many longtime-MIA
+ * macosx/Wish.xcodeproj/project.pbxproj: features to working order
+ * unix/Makefile.in: (e.g. images, custom colors &
+ fonts in menus etc); implement compound menu items; use Appearance Mgr
+ and ThemeText APIs to mimic native MDEF as closely as possible when
+ default "menu" system font is used; remove now obsolete SICN drawing
+ code and resources.
+
+ * macosx/tkMacOSXCarbonEvents.c: Handle additional menu carbon events
+ * macosx/tkMacOSXEvent.c: in order to support <<MenuSelect>> in
+ * macosx/tkMacOSXMenu.c: the menubar and in menus that are not
+ * macosx/tkMacOSXMenus.c: using the custom MDEF [Bug 1620826];
+ fix early and missing clearing of current Tk active menu entry; fix
+ extraneous sending of <<MenuSelect>> during active menu entry clearing.
+
+ * macosx/tkMacOSXMouseEvent.c: Add support for async window dragging by
+ the window server; set the corresponding window attribute by default.
+
+ * macosx/tkMacOSXMouseEvent.c: Rationalized handling order of
+ non-mousedown events; add TkMacOSXModifierState() to retrieve the
+ current key modifiers in carbon format.
+
+ * macosx/tkMacOSXScrlbr.c: Use appearance manager API to retrieve
+ scrollbar component metrics; add awareness of multiple possibilites for
+ scrollbar arrow position in aqua and handle user changes to arrow
+ position pref; handle difference in metrics of small & large scrollbar
+ variants; handle aqua "jump to here" scrollbar behaviour; correct
+ computation of scroll view size and position; enforce min scrollbar
+ height to avoid scrollbar component overlap; erase scrollbar area
+ outside of standard width; remove broken auto-adjust code; account for
+ window class when leaving space for grow box; remove code to manually
+ draw grow box; use modern API for thumb scroll proc; replace
+ HiliteControl() by modern API; replace control mgr constants with
+ appearance mgr equivalents.
+
+ * macosx/tkMacOSXSubwindows.c: Use SetWindowBounds() API instead of
+ SizeWindow(); invalidate clip regions after X{Map,Unmap}Window as fix
+ for [Bug 940117] made them dependent on mapping state; remove unneeded
+ calls to TkMacOSXInvalClipRgns() and unnecessary setting of QD port;
+ use native-endian pixmap on intel; remove obsolete pixmap pix locking.
+
+ * macosx/tkMacOSXWindowEvent.c: Handle only the first of a batch of
+ kEventAppAvailableWindowBoundsChanged events sent per transaction;
+ handle kEventWindowBoundsChanged event to support live window resizing
+ and centralized sending of location/size changed ConfigureNotify
+ events; ensure HIGrowBox is redrawn after bounds change; constrain
+ window after dragging to ensure titlebar is not inacessible
+ offscreen or under dock/menubar; handle kEventWindowGetRegion and
+ kEventWindowDrawContent for transparent windows to mark resp. paint
+ content region as transparent; handle kEventWindowConstrain for
+ fullscreen windows to ensure bounds match new screen size; enter/exit
+ fullscreen UIMode upon activation/deactivation of fullscreen window.
+
+ * macosx/tkMacOSXWm.c: Use live-resize and async-drag carbon window
+ * macosx/tkMacOSXWm.h: attributes for toplevels by default; implement
+ new [wm attributes] -topmost, -transparent and -fullscreen; refactor
+ WmAttributesCmd() parallelling the tkUnixWm.c implementation, use thus
+ factored proc to set proxy icon from [wm iconbitmap]; dynamically
+ determine default values for toplevel min and max sizes (similar to
+ tkWinWm.c impl): min sizes depend on window class & attributes to
+ ensure visibility of all titlebar widgets and grow box, max sizes
+ depend on maximal window bounds for all active displays; factor out
+ code that puts into effect changes to master or override_redirect; use
+ RepositionWindow() API to determine staggered initial window bounds;
+ correct resize limit calculations, handle gridding and use modern
+ resize API in TkMacOSXGrowToplevel(); remove sending of ConfigureNotify
+ after resize or zoom (now handled by BoundsChanged handler); correct
+ composite carbon window attribute handling, remove currently unusable
+ attributes and add new attributes in [tk::unsupported::MacWindowStyle];
+ ensure validity of window class and attributes before use; apply
+ changes to window class when handling carbon window attribute changes
+ (if HIWindowChangeClass() API available); add debug build warning
+ message when deprecated window style is used instead of window class;
+ use transparent HIGrowBox for resizable windows; avoid unnecessary
+ calls to window structure width API; use tcl time API in TkpGetMS();
+ add TkMacOSXEnterExitFullscreen() to enter/exit UIMode with dock and
+ menubar hidden; restrict wmTracing output to debug builds; remove
+ unneeded calls to TkMacOSXInvalClipRgns() and unnecessary setting of QD
+ port; workaround GetWindowStructureWidths() Carbon bug (bogus results
+ for never-mapped floating windows).
+
+ * macosx/tkMacOSXXStubs.c (TkMacOSXDisplayChanged): Add maximal window
+ bounds field to Screen record (in ext_data), computed as the union of
+ available window positioning bounds of all graphics devices (displays).
+
+ * macosx/tkMacOSXBitmap.c: Fix macRoman encoding leak.
+ * macosx/tkMacOSXCursor.c:
+
+ * macosx/tkMacOSXDebug.c (TkMacOSXCarbonEventToAscii): Use static
+ * macosx/tkMacOSXDebug.h: buffer to simplify callers; const fixes.
+
+ * macosx/tkMacOSXBitmap.c: Use more efficient QDSwapPort() instead of
+ * macosx/tkMacOSXButton.c: GetPort()/SetPort()/GetGWorld()/SetGWorld().
+ * macosx/tkMacOSXDraw.c:
+ * macosx/tkMacOSXMenubutton.c:
+ * macosx/tkMacOSXScale.c:
+ * macosx/tkMacOSXScrlbr.c:
+ * macosx/tkMacOSXXStubs.c:
+
+ * macosx/tkMacOSXColor.c: Use kHIToolboxVersionNumber for runtime OS
+ * macosx/tkMacOSXEntry.c: version check rather than Gestalt() etc.
+ * macosx/tkMacOSXInt.h:
+ * macosx/tkMacOSXWm.c:
+
+ * macosx/tkMacOSXDraw.c: Remove obsolete and now incorrect
+ * macosx/tkMacOSXInt.h: tkMenuCascadeRgn clipping code.
+ * macosx/tkMacOSXMenu.c:
+
+ * macosx/tkMacOSXHLEvents.c: Replace Tcl_GlobalEval() resp. Tcl_Eval()
+ * macosx/tkMacOSXScrlbr.c: by Tcl_EvalEx().
+ * macosx/tkMacOSXInit.c:
+
+ * macosx/tkMacOSXInit.c (TkpInit): Reorder initialization steps.
+
+ * macosx/tkMacOSXKeyEvent.c: Remove pre-10.2 support.
+
+ * macosx/tkMacOSXMenus.c: Remove now useless call to
+ TkMacOSXHandleTearoffMenu(); use \x.. quoting for non-latin1 macroman
+ literar chars to allow file to be edited as utf-8.
+
+ * macosx/tkMacOSXScale.c: Replace TrackControl() by modern
+ * macosx/tkMacOSXScrlbr.c: HandleControlClick() API (using new
+ TkMacOSXModifierState()).
+
+ * macosx/tkMacOSXInt.h: Move all constant #defines needed to
+ * macosx/tkMacOSXColor.c: support building on older OS X releases
+ * macosx/tkMacOSXEvent.h: to a central location in tkMacOSXInt.h.
+ * macosx/tkMacOSXFont.c:
+ * macosx/tkMacOSXMenu.c:
+ * macosx/tkMacOSXMenubutton.c:
+ * macosx/tkMacOSXMenus.c:
+ * macosx/tkMacOSXMouseEvent.c:
+ * macosx/tkMacOSXWm.c:
+ * macosx/ttkMacOSXTheme.c:
+
+ * macosx/tkMacOSXInt.h: Add ChkErr() macro to factor out
+ * macosx/tkMacOSXButton.c: Carbon OSStatus return value checking
+ * macosx/tkMacOSXCarbonEvents.c: and TkMacOSXDbgMsg() macro to factour
+ * macosx/tkMacOSXClipboard.c: out debug message output; use these
+ * macosx/tkMacOSXColor.c: macros to replace #ifdef TK_MAC_DEBUG
+ * macosx/tkMacOSXCursor.c: blocks & direct printing to stderr,
+ * macosx/tkMacOSXDebug.c: and to do additional OSStatus return
+ * macosx/tkMacOSXDialog.c: checking, and to standardize OSStatus
+ * macosx/tkMacOSXDraw.c: usage.
+ * macosx/tkMacOSXEntry.c:
+ * macosx/tkMacOSXEvent.c:
+ * macosx/tkMacOSXFont.c:
+ * macosx/tkMacOSXHLEvents.c:
+ * macosx/tkMacOSXInit.c:
+ * macosx/tkMacOSXKeyEvent.c:
+ * macosx/tkMacOSXMenu.c:
+ * macosx/tkMacOSXMenubutton.c:
+ * macosx/tkMacOSXMenus.c:
+ * macosx/tkMacOSXMouseEvent.c:
+ * macosx/tkMacOSXScrlbr.c:
+ * macosx/tkMacOSXSubwindows.c:
+ * macosx/tkMacOSXWindowEvent.c:
+ * macosx/tkMacOSXWm.c:
+ * macosx/tkMacOSXXStubs.c:
+
+ * macosx/tkMacOSXSend.c: Remove duplicate/unused declarations.
+ * macosx/tkMacOSXXStubs.c:
+
+ * macosx/tkMacOSXDebug.c: Const fixes.
+ * macosx/tkMacOSXInit.c:
+ * macosx/tkMacOSXTest.c:
+ * macosx/tkMacOSXWm.c:
+ * macosx/tkMacOSXXStubs.c:
+
+ * macosx/Wish-Info.plist.in: Add tcl document extensions/mime types and
+ LSMinimumSystemVersion, LSRequiresCarbon & NSAppleScriptEnabled keys.
+
+ * macosx/Wish-Common.xcconfig: Add Wish's Info.plist as __info_plist
+ section to tktest; enable more warnings.
+
+ * macosx/Wish.xcodeproj/project.pbxproj: Add 'DebugMemCompile' build
+ configuration that calls configure with --enable-symbols=all; disable
+ configure check for __attribute__((__visibility__("hidden"))) in Debug
+ configuration to restore availability of ZeroLink.
+
+ * macosx/Wish-Common.xcconfig: Fix whitespace.
+ * macosx/Wish-Debug.xcconfig:
+ * macosx/Wish-Release.xcconfig:
+ * macosx/tkMacOSXAETE.r:
+ * macosx/tkMacOSXConfig.c:
+ * macosx/tkMacOSXCursors.r:
+ * macosx/tkMacOSXKeyboard.c:
+ * macosx/tkMacOSXSend.c:
+ * macosx/ttkMacOSXTheme.c:
+ * macosx/tkMacOSXXCursors.r:
+ * macosx/README:
+
+ * macosx/GNUmakefile: Fix/add copyright and license refs.
+ * macosx/Tk-Info.plist.in:
+ * macosx/Wish-Info.plist.in:
+ * macosx/Wish.xcode/project.pbxproj:
+ * macosx/Wish.xcodeproj/project.pbxproj:
+ * macosx/tkMacOSX.h:
+
+ * unix/configure.in: Install license.terms into Tk.framework; fix tk
+ debug build detection.
+ * unix/configure: autoconf-2.59
+
+ * doc/colors.n: Document new Mac OS X system colors.
+ * doc/cursors.n: Document new Mac OS X native cursors.
+ * doc/font.n: Document new Mac OS X 'menu' system font.
+ * doc/wm.n: Document new Mac OS X [wm attributes].
+ * doc/ttk_image.n: Fix 'make html' warning.
+ * doc/canvas.n: Fix nroff typo.
+
+2007-04-21 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * macosx/tkMacOSXBitmap.c, macosx/tkMacOSXButton.c:
+ * macosx/tkMacOSXCarbonEvents.c, macosx/tkMacOSXClipboard.c:
+ * macosx/tkMacOSXCursor.c, macosx/tkMacOSXDialog.c:
+ * macosx/tkMacOSXDraw.c, macosx/tkMacOSXEvent.c:
+ * macosx/tkMacOSXFont.c, macosx/tkMacOSXInit.c, macosx/tkMacOSXInt.h:
+ * macosx/tkMacOSXKeyEvent.c, macosx/tkMacOSXMenu.c:
+ * macosx/tkMacOSXMenubutton.c, macosx/tkMacOSXMouseEvent.c:
+ * macosx/tkMacOSXScale.c, macosx/tkMacOSXWindowEvent.c:
+ * macosx/tkMacOSXWm.c: Revert of commits from 2007-04-13 which broke
+ the OS X build.
+
+2007-04-17 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * generic/tkFont.c, generic/tkListbox.c, unix/tkUnixSelect.c:
+ * win/ttkWinMonitor.c, win/ttkWinTheme.c, win/ttkWinXPTheme.c: Make
+ the format of declarations much more standardized (removing K&R-isms
+ and other things like that).
+
+2007-04-13 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * macosx/tkMacOSXInt.h (LOG_MSG, LOG_ON_ERROR): Added macros to make
+ the OSX code much less #ifdef-full.
+
+2007-04-12 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/ttk/panedwindow.tcl (ttk::panedwindow::Press): handle Press
+ triggering outside sash element boundaries.
+
+2007-04-10 Joe English <jenglish@users.sourceforge.net>
+
+ * win/ttkWinMonitor.c, win/ttkWinXPTheme.c: Re-sync with Tile codebase
+ so patches can flow back and forth.
+
+ * win/ttkWinXPTheme.c: Skip OS version test, should work on Vista/Aero
+ now as well as XP. Fixes [Bug 1687299], thanks to George Petasis for
+ tracking this down.
+
+2007-03-21 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkLayout.c(Ttk_BuildLayoutTemplate): BUGFIX: Nested
+ TTK_GROUP nodes did not work unless they appeared at the end of the
+ layout (and only by accident then).
+
+2007-03-08 Joe English <jenglish@users.sourceforge.net>
+
+ * tests/grid.test(grid-21.7): Reset wm geometry . and pack propagate .
+ at end of test. 'pack propagate . 0' was causing cascading failures in
+ subsequent tests. [Bug 1676770]
+
+2007-03-07 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tkMain.c (Tk_MainEx): Replicate macosx-specific code from
+ TkpInit() that ensures the console window appears when wish is started
+ from the OS X Finder (i.e. with stdin == /dev/null), jeffh's 2006-11-24
+ change rendered the corresponding code in TkpInit() ineffective in wish
+ because Tk_MainEx() sets tcl_interactive before calling TkpInit().
+
+ * generic/ttk/ttkGenStubs.tcl (new): Add ttk-specific genstubs.tcl from
+ * unix/Makefile.in (genstubs): tile and run it from 'genstubs'
+ target, restores ability to generate all of Tk's stub sources.
+
+ * generic/ttk/ttkTreeview.c: #ifdef out unused declaration.
+
+ * macosx/tkMacOSXDebug.c (TkMacOSXGetNamedDebugSymbol): Add fix for
+ libraries loaded with a DYLD_IMAGE_SUFFIX.
+
+ * macosx/Wish.xcodeproj/project.pbxproj: Ensure gcc version used by
+ * macosx/Wish.xcodeproj/default.pbxuser: Xcode and configure/make are
+ * macosx/Wish-Common.xcconfig: consistent and independent of
+ gcc_select default and CC env var; fixes for Xcode 3.0.
+
+ * unix/tcl.m4 (Darwin): s/CFLAGS/CPPFLAGS/ in macosx-version-min check.
+ * unix/configure: autoconf-2.59
+
+2007-02-25 Peter Spjuth <peter.spjuth@space.se>
+
+ * generic/tkUtil.c: Fixed grid anchor center problem in labelframes.
+ * tests/grid.test: [Bug 1545765]
+
+2007-02-23 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/ttk/notebook.tcl (ttk::notebook::enableTraversal): OS X
+ needs Option instead of Alt binding
+
+2007-02-19 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/tcl.m4: use SHLIB_SUFFIX=".so" on HP-UX ia64 arch.
+ * unix/configure: autoconf-2.59
+
+ * library/tkfbox.tcl (::tk::IconList_Goto): avoid goto issues in empty
+ dirs. [Bug 1662959]
+
+2007-02-09 Joe Mistachkin <joe@mistachkin.com>
+
+ * win/nmakehlp.c: Properly cleanup after nmakehlp, including the
+ * win/makefile.vc: vcX0.pch file. Sync up fixed nmakehlp usage from
+ Tcl.
+
+2007-02-06 Joe English <jenglish@users.sourceforge.net>
+
+ * library/ttk/ttk.tcl: Add no-op [package ifneeded] script for tile
+ 0.8.0, so that existing applications that use "package require tile"
+ won't fail when run under Tk 8.5.
+
+2007-02-04 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/tcl.m4: Use gcc4's __attribute__((__visibility__("hidden"))) if
+ available to define MODULE_SCOPE effective on all platforms.
+ * unix/configure.in: add caching to -pipe check.
+ * unix/configure: autoconf-2.59
+ * unix/tkConfig.h.in: autoheader-2.59
+
+2007-02-03 Joe Mistachkin <joe@mistachkin.com>
+
+ * win/rules.vc: Fix platform specific file copy macros for downlevel
+ Windows.
+ * win/ttkWinMonitor.c: Windows portability support. Fix "noxp" build
+ * win/ttkWinXPTheme.c: option handling and use GetWindowLongPtr and
+ SetWindowLongPtr only when needed.
+
+2007-02-02 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/ttkWinXPTheme.c: Support IsAppThemed() call. This is what is
+ used when theming is turned off just for an individual application.
+
+2007-01-28 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Wish.xcodeproj/project.pbxproj: Extract build settings that
+ * macosx/Wish.xcodeproj/default.pbxuser: were common to multiple
+ * macosx/Wish-Common.xcconfig (new file): configurations into external
+ * macosx/Wish-Debug.xcconfig (new file): xcconfig files; add extra
+ * macosx/Wish-Release.xcconfig (new file): configurations for building
+ with SDKs; convert legacy jam-based 'Tk' target to native target with
+ single script phase; correct syntax of build setting references to use
+ $() throughout; remove unused tcltest sources from 'tktest' target.
+
+ * macosx/README: Document new Wish.xcodeproj configurations; other
+ minor updates/corrections.
+
+ * generic/tk.h: Update location of version numbers in macosx files.
+
+ * macosx/Wish.xcode/project.pbxproj: Restore 'tktest' target to working
+ * macosx/Wish.xcode/default.pbxuser: order by replicating applicable
+ changes to Wish.xcodeproj since 2006-07-20.
+
+2007-01-25 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/tcl.m4: Integrate CPPFLAGS into CFLAGS as late as possible and
+ move (rather than duplicate) -isysroot flags from CFLAGS to CPPFLAGS to
+ avoid errors about multiple -isysroot flags from some older gcc builds.
+
+ * unix/configure: autoconf-2.59
+
+2007-01-19 Joe Mistachkin <joe@mistachkin.com>
+
+ * win/makefile.vc: Properly build man2tcl.c for MSVC8.
+
+2007-01-19 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Wish.xcodeproj/project.pbxproj: Remove libtommath defines.
+
+ * unix/tcl.m4: Ensure CPPFLAGS env var is used when set. [Bug 1586861]
+ (Darwin): add -isysroot and -mmacosx-version-min flags to CPPFLAGS when
+ present in CFLAGS to avoid discrepancies between what headers configure
+ sees during preprocessing tests and compiling tests.
+
+ * unix/configure: autoconf-2.59
+
+2007-01-11 Jeff Hobbs <jeffh@activestate.com>
+
+ * unix/tkUnixEvent.c, library/msgs/es.msg: s/CRLF/LF/g
+
+2007-01-11 Joe English <jenglish@users.sourceforge.net>
+
+ * win/tcl.m4 (CFLAGS_WARNING): Remove "-Wconversion". This was removed
+ from unix/tcl.m4 2004-07-16 but not from here.
+ * win/configure: Regenerated.
+
+2007-01-11 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkManager.h, generic/ttk/ttk*.c: Revert addition of
+ contravariant 'const' qualifiers, to keep in sync with Tile codebase
+ (which must remain compatible with Tk 8.4).
+
+2007-01-03 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * doc/ManageGeom.3,
+ * generic/tk.decls,
+ * generic/tk.h: Add const to 2nd parameter of Tk_ManageGeometry
+ * generic/tkDecls.h: regenerated
+ * generic/tkInt.h,
+ * generic/tk*.c,
+ * generic/ttk/ttk*.c: Added many "const" specifiers in implementation.
+
+2007-01-02 Donal K. Fellows <dkf@users.sf.net>
+
+ * xlib/*: Made the generic fake-X11 glue layer abide by the formatting
+ rules of the core.
+
+2006-12-31 Benjamin Riefenstahl <b.riefenstahl@turtle-trading.net>
+
+ * macosx/tkMacOSXFont.c: Fill-in TkpGetFontAttrsForChar (TIP #300).
+ * macosx/ttkMacOSXTheme.c: Define a constant to make it compile on Mac
+ OS X 10.3.
+
+2006-12-28 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * tests/wm.test: Update wm attributes output so that tests pass after
+ addition of -transparentcolor for Win32.
+
+2006-12-26 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkLabel.c: ImageElement clientData no longer needed.
+
+2006-12-22 Donal K. Fellows <dkf@users.sf.net>
+
+ * unix/tkUnixEvent.c (TkUnixDoOneXEvent): Made correct on AMD64 and
+ other similar 64-bit systems where fd_mask is not 'unsigned int' in
+ effect. [Bug 1522467]
+
+ * library/msgs/es_ES.msg (removed):
+ * library/msgs/es.msg: Fixed translation fault that was present in all
+ Spanish-speaking locales. [Bug 1111213]
+
+2006-12-19 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinButton.c (TkpDisplayButton): lint init. [Bug 1618604]
+
+2006-12-19 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/tcl.m4 (Darwin): --enable-64bit: verify linking with 64bit -arch
+ flag succeeds before enabling 64bit build.
+ * unix/configure: autoconf-2.59
+
+2006-12-18 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkTreeview.c, library/ttk/treeview.tcl, doc/treeview.n:
+ Added column '-stretch' and '-minwidth' options. Improved column drag
+ and resize behavior. Added horizontal scrolling [Bug 1518650]. Row
+ height and child indent specifiable on Treeview style. Decreased
+ default row height, no default -padding. Use correct heading height
+ [Bug 1163349]. Apply tag settings to tree item as well as to data
+ columns [NOTE: 'tag configure' still buggy]. Fix off-by-one condition
+ when moving nodes forward [Bug 1618142]
+ * generic/ttk/ttkScroll.c (TtkScrollTo): Prevent overscroll [Bug
+ 1173434]
+ * library/ttk/altTheme.tcl, library/ttk/aquaTheme.tcl,
+ * library/ttk/clamTheme.tcl, library/ttk/classicTheme.tcl,
+ * library/ttk/defaults.tcl, library/ttk/winTheme.tcl,
+ * library/ttk/xpTheme.tcl: Per-theme treeview settings.
+ * macosx/ttkMacOSXTheme.c: Added disclosure triangle element.
+
+2006-12-17 Joe English <jenglish@users.sourceforge.net>
+
+ * library/ttk/combobox.tcl, generic/ttk/ttkEntry.c,
+ * doc/ttk_combobox.n: Add combobox -height option; only show scrollbar
+ if the listbox needs to scroll. [Bug 1032869]
+
+2006-12-16 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * doc/cursors.n: Mention "none" in supported cursor list. Fix comment
+ that incorrectly claims that the Win32 "no" cursor hides the cursor.
+ * tests/cursor.test: Test "none" cursor.
+ * unix/tkUnixCursor.c (CreateCursorFromTableOrFile)
+ (TkGetCursorByName): Define a table of Tk cursors that is searched in
+ addition to the X cursor table. A Tk cursor is loaded from a data
+ string and works with the same options as the built in X cursors. This
+ code makes it possible to use "none" as a cursor name under Unix.
+ * win/rc/cursor9a.cur: Added none Win32 cursor.
+ * win/rc/tk_base.rc: Define a built-in Win32 cursor named "none".
+ [Patch 1615427]
+
+2006-12-14 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkButton.c, generic/ttk/ttkElements.c,
+ * generic/ttk/ttkEntry.c, generic/ttk/ttkFrame.c,
+ * generic/ttk/ttkImage.c, generic/ttk/ttkInit.c,
+ * generic/ttk/ttkLabel.c, generic/ttk/ttkNotebook.c,
+ * generic/ttk/ttkPanedwindow.c, generic/ttk/ttkProgress.c,
+ * generic/ttk/ttkScale.c, generic/ttk/ttkScrollbar.c,
+ * generic/ttk/ttkSeparator.c, generic/ttk/ttkTheme.h,
+ * generic/ttk/ttkTreeview.c, generic/ttk/ttkWidget.h:
+ Global reduction: use per-file *_Init() routines to reduce the number
+ of globally-visible initialization records.
+
+2006-12-13 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/Makefile.in (install-doc): intentionally skip ttk_dialog.n
+ installation (not for public consumption)
+
+ * doc/scrollbar.n, doc/button.n, doc/checkbutton.n:
+ * doc/entry.n, doc/frame.n, doc/label.n, doc/labelframe.n:
+ * doc/menu.n, doc/menubutton.n, doc/panedwindow.n:
+ * doc/radiobutton.n, doc/scrollbar.n, doc/ttk_*: revamp ttk docs to
+ use consist nroff format (not 100% consistent with classic widget
+ docs). Add more man page cross-linking "SEE ALSO".
+
+ * generic/ttk/ttkInit.c:
+ * generic/ttk/ttkTreeview.c: make treeview exist by default
+ * generic/ttk/ttkPanedwindow.c: s/TtkPaned_Init/TtkPanedwindow_Init/
+
+ * win/Makefile.in, unix/Makefile.in (demo): add 'demo' target
+
+2006-12-13 Joe English <jenglish@users.sourceforge.net>
+
+ * library/ttk/ttk.tcl: Try to straighten out theme loading and
+ selection logic.
+ * generic/ttk/ttkElements.c, library/ttk/defaults.tcl,
+ * generic/ttk/ttkClamTheme.c, library/ttk/clamTheme.tcl:
+ Provide package in C part instead of Tcl part.
+
+2006-12-12 Joe English <jenglish@users.sourceforge.net>
+
+ * library/ttk/ttk.tcl, generic/ttkTheme.c: Remove nonfunctional code.
+
+2006-12-12 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/tkWinButton.c (InitBoxes): Call Tcl_Panic() if loading of bitmap
+ resources fails. This change generates an error if Tk is unable to
+ find button widget resources instead of silently failing and then
+ drawing widgets incorrectly.
+ * win/rc/tk_base.rc: If the user defines BASE_NO_TK_ICON then compile
+ the base resources file without a "tk" icon. This change makes it
+ easier to replace the default tk icon with a custom icon. [Patch
+ 1614362]
+
+2006-12-11 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * unix/tkUnixWm.c (TkWmMapWindow, WmClientCmd): Added support for
+ _NET_WM_PID property from the EWMH spec. This is only installed when
+ the client machine is set.
+ (WmProtocolCmd, UpdateWmProtocols, TkWmProtocolEventProc): Added
+ support for the _NET_WM_PING protocol from the EWMH spec. Note that
+ the support for this is not exposed to the script level as that would
+ prevent correct handling.
+
+2006-12-10 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkTheme.h, generic/ttk/ttkThemeInt.h,
+ * generic/ttk/ttk.decls, generic/ttk/ttkTheme.c,
+ * generic/ttk/ttkLayout.c, generic/ttk/ttkDecls.h:
+ Rename typedef Ttk_Element => Ttk_ElementImpl.
+
+2006-12-09 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkButton.c, generic/ttk/ttkImage.c,
+ * generic/ttk/ttkLabel.c, generic/ttk/ttkWidget.h,
+ * generic/ttk/ttkTheme.h, generic/ttk/ttkNotebook.c,
+ * generic/ttk/ttkTreeview.c, doc/ttk_image.n:
+ Merged duplicate functionality between image element factory, image
+ element, and -image option processing. Image element factory now takes
+ an imageSpec argument instead of a separate image name and -map option
+ * tests/ttk/image.test(image-1.1): Can catch this error earlier now.
+
+2006-12-06 Kevin Kenny <kennykb@acm.org>
+
+ * unix/configure.in: Further changes to avoid attempting to link
+ * unix/configure: against Xft libraries in a non-Xft build
+ [Bug 1609616] (dgp)
+
+2006-12-04 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkListbox.c (ConfigureListboxItem): ListboxWorldChanged not
+ needed - just call EventuallyRedrawRange. [Bug 1608046] (rezic)
+
+2006-12-04 Donal K. Fellows <dkf@users.sf.net>
+
+ TIP #286 IMPLEMENTATION
+
+ * generic/tkMenu.c (MenuWidgetObjCmd, MenuDoXPosition):
+ * doc/menu.n, tests/menu.test: Added an [$menu xposition] subcommand
+ which is useful in menubars and when menus use multiple columns. Many
+ thanks to Schelte Bron for the implementation.
+
+2006-12-01 Kevin Kenny <kennykb@acm.org>
+
+ TIP #300 IMPLEMENTATION
+
+ * doc/font.n: Added a [font actual $font $char]
+ * generic/tkFont.c: variant that introspects the font that
+ * generic/tkFont.h: is chosen to render a given character
+ * macosx/tkMacOSXFont.c: in a given nominal font. Added
+ * tests/font.test: documentation and test cases for the
+ * unix/tkUnixFont.c: new command syntax.
+ * unix/tkUnixRFont.c:
+ * win/tkWinFont.c:
+
+2006-12-01 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * doc/wm.n, tests/winWm.test:
+ * win/tkWinWm.c: add -transparentcolor attribute for Windows.
+
+2006-12-01 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkTheme.h, generic/ttk/ttkLayout.c: Dead code removal.
+
+2006-11-30 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXDialog.c (Tk_MessageBoxObjCmd): fix inability to use
+ buttons with standard Escape key binding as -default button (reported
+ on tcl-mac by Hans-Christoph Steiner).
+
+ * macosx/tkMacOSXWm.c (WmAttributesCmd): fix getting [wm attr -alpha].
+ [Bug 1581932]
+
+2006-11-28 Joe English <jenglish@users.sourceforge.net>
+
+ * library/ttk/fonts.tcl: Clean up temporary variables.
+
+2006-11-27 Kevin Kenny <kennykb@acm.org>
+
+ * unix/configure.in: Corrected Xft configuration so that Xft actually
+ does get turned on when available.
+ * unix/configure: autoconf
+
+2006-11-26 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkWidget.c, generic/ttk/ttkPaned.c: Fix [Bug 1603506]
+ * library/ttk/button.tcl, library/ttk/combobox.tcl,
+ * library/ttk/utils.tcl: Rename ttk::CopyBindings to ttk::copyBindings
+ * generic/ttk/ttkTreeview.c, doc/ttk_treeview.n:
+ -displaycolumns {} now means "no columns" instead of "all columns".
+ Use -displaycolumns #all for "all columns". [Bug 1547622]
+
+2006-11-26 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/tcl.m4 (Linux): --enable-64bit support. [Patch 1597389]
+ * unix/configure: autoconf-2.59 [Bug 1230558]
+
+2006-11-24 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * macosx/tkMacOSXInit.c (TkpInit): only set tcl_interactive 1 if it
+ isn't already defined. Allows embedders to set it to 0 to prevent the
+ console appearing on OS X. [Bug 1487701]
+
+ * unix/tkUnixMenu.c (DrawMenuUnderline): bound Tcl_UtfAtIndex usage
+ * tests/menu.test (menu-36.1): [Bug 1599877]
+
+2006-11-24 Joe English <jenglish@users.sourceforge.net>
+
+ * library/ttk/altTheme.tcl, library/ttk/clamTheme.tcl,
+ * library/ttk/defaults.tcl, library/ttk/winTheme.tcl,
+ * library/ttk/xpTheme.tcl: explicitly specify -anchor w on TMenubutton
+ * tests/ttk/entry.test: Fixed font dependency; test entry-3.2 should
+ work on all platforms now.
+ * library/classicTheme.tcl: Don't define or use TkClassicDefaultFont.
+ * generic/ttk/ttkTreeview.c, generic/ttk/ttkPanedwindow.c: Handle
+ missing layouts.
+
+2006-11-23 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinMenu.c (TkWinHandleMenuEvent, DrawMenuUnderline): Handle
+ unichar underlining correctly and safely. [Bug 1599877]
+
+2006-11-20 Joe English <jenglish@users.sourceforge.net>
+
+ * win/ttkWinXPTheme.c: Add support for alternate/indeterminate
+ checkbutton state. Fix various spacing parameters [Bug 1596020, patch
+ from Tim Baker]. Remove unused uxtheme hooks.
+
+2006-11-16 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/colors.n, doc/wm.n: Minor fixes, added See Also.
+
+ * doc/labelframe.n: Added an example.
+
+2006-11-15 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/label.n: Added an example and some See Also refs.
+
+ * doc/ConfigWidg.3, doc/bind.n, doc/grid.n, doc/panedwindow.n:
+ * doc/text.n, doc/ttk_Geometry.3, doc/ttk_button.n:
+ * doc/ttk_checkbutton.n, doc/ttk_combobox.n, doc/ttk_dialog.n:
+ * doc/ttk_entry.n, doc/ttk_frame.n, doc/ttk_image.n, doc/ttk_intro.n:
+ * doc/ttk_label.n, doc/ttk_labelframe.n, doc/ttk_menubutton.n:
+ * doc/ttk_notebook.n, doc/ttk_panedwindow.n, doc/ttk_progressbar.n:
+ * doc/ttk_radiobutton.n, doc/ttk_scrollbar.n, doc/ttk_separator.n:
+ * doc/ttk_sizegrip.n, doc/ttk_style.n, doc/ttk_widget.n, doc/wm.n:
+ Convert \fP to \fR so that man-page scrapers have an easier time.
+
+2006-11-14 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkDefaultTheme.c: Fix off-by-one bug in tree indicator
+ size computation [Bug 1596021, patch from Tim Baker]. Increased
+ default size from 7 to 9 pixels.
+
+2006-11-12 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttkScroll.c: *correct* fix for [Bug 1588251].
+
+2006-11-12 Joe English <jenglish@users.sourceforge.net>
+
+ * tests/ttk/ttk.test(ttk-6.9): Workaround for [Bug 1583038]
+
+2006-11-12 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttkScroll.c: Reworked cleanup procedure; "self-cancelling"
+ idle call is not robust, call Tcl_CancelIdleCall() in
+ TtkFreeScrollHandle instead. Fixes [Bug 1588251]
+
+2006-11-10 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Wish.xcodeproj/project.pbxproj: remove tclParseExpr.c and
+ bwidget.test.
+
+ * unix/tcl.m4 (Darwin): suppress linker arch warnings when building
+ universal for both 32 & 64 bit and no 64bit CoreFoundation is
+ available; sync with tcl tcl.m4 change.
+ * unix/configure: autoconf-2.59
+ * unix/tkConfig.h.in: autoheader-2.59
+
+2006-11-08 Kevin Kenny <kennykb@acm.org>
+
+ * unix/configure.in: Silenced warnings about missing Xft configuration
+ unless --enable-xft is requested explicitly. Also added a few basic
+ checks that we can actually compile and link against Xft headers and
+ libraries. [Bug 1592667]
+ * unix/configure: Regen.
+
+2006-11-07 Kevin Kenny <kennykb@acm.org>
+
+ * unix/configure.in: Made --enable-xft the default.
+ * unix/configure: Regen.
+
+2006-11-06 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkClassicTheme.c, generic/ttk/ttkPanedwindow.c,
+ * generic/ttk/ttkTheme.c, generic/ttk/ttkTreeview.c,
+ * win/ttkWinXPTheme.c, library/ttk/entry.tcl,
+ * library/ttk/notebook.tcl, library/ttk/panedwindow.tcl,
+ * library/ttk/utils.tcl, tests/ttk/entry.test, tests/ttk/bwidget.test:
+ Miscellaneous minor changes to re-sync Ttk codebase with Tile CVS: fix
+ comments damaged by overzealous search-and-destroy; removed obsolete
+ [style default] synonym for [ttk::style configure]; removed other dead
+ code.
+
+2006-11-03 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * library/safetk.tcl (::safe::tkTopLevel): Theme it.
+
+ * generic/ttk/ttkLayout.c: We do not want to require tkInt in all
+ * generic/ttk/ttkMananager.h: the ttk files so added the definition
+ * generic/ttk/ttkTheme.h: of MODULE_SCOPE to ttkTheme.h. Ensures
+ * generic/ttk/ttkWinMonitor.c: everyone gets to see the definition
+ from someplace.
+
+ * library/ttk/fonts.tcl: In a safe interp there is no osVersion field
+ in tcl_platform so work around it.
+
+2006-11-02 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/ttk/ttkBlink.c, generic/ttk/ttkButton.c:
+ * generic/ttk/ttkClamTheme.c, generic/ttk/ttkClassicTheme.c:
+ * generic/ttk/ttkDecls.h, generic/ttk/ttkDefaultTheme.c:
+ * generic/ttk/ttkElements.c, generic/ttk/ttkEntry.c:
+ * generic/ttk/ttkFrame.c, generic/ttk/ttkImage.c:
+ * generic/ttk/ttkInit.c, generic/ttk/ttkLabel.c:
+ * generic/ttk/ttkLayout.c, generic/ttk/ttkManager.h:
+ * generic/ttk/ttkNotebook.c, generic/ttk/ttkPanedwindow.c:
+ * generic/ttk/ttkProgress.c, generic/ttk/ttkScale.c:
+ * generic/ttk/ttkScroll.c, generic/ttk/ttkScrollbar.c:
+ * generic/ttk/ttkSeparator.c, generic/ttk/ttkSquare.c:
+ * generic/ttk/ttkStubInit.c, generic/ttk/ttkStubLib.c:
+ * generic/ttk/ttkTheme.c, generic/ttk/ttkTheme.h:
+ * generic/ttk/ttkThemeInt.h, generic/ttk/ttkTrack.c:
+ * generic/ttk/ttkTreeview.c, generic/ttk/ttkWidget.c:
+ * generic/ttk/ttkWidget.h, macosx/ttkMacOSXTheme.c:
+ * win/ttkWinMonitor.c, win/ttkWinTheme.c, win/ttkWinXPTheme.c: ensure
+ all global Ttk symbols have Ttk or ttk prefix; declare all externally
+ visible Ttk symbols not contained in stubs table as MODULE_SCOPE (or as
+ static when possible); so that 'make check{exports,stubs}' once again
+ complete without errors.
+
+ * macosx/tkMacOSXColor.c (TkMacOSXCompareColors): ifdef out when unused
+
+ * macosx/Wish.xcodeproj/project.pbxproj: check autoconf/autoheader exit
+ status and stop build if they fail.
+
+ * macosx/tkMacOSXWindowEvent.c (GenerateUpdateEvent): fix handling of
+ Carbon Update events: the QuickDraw window update region was being
+ ignored and all child TkWindows were sent an Expose XEvent even when
+ they did not need to be redrawn. [Patch 1589226]
+
+2006-11-01 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXDebug.c: add TkMacOSX prefix to leftover
+ * macosx/tkMacOSXDebug.h: macosx-private global symbols without Tk
+ * macosx/tkMacOSXEmbed.c: prefix; ifdef out currently unused debug
+ * macosx/tkMacOSXEvent.c: procs.
+ * macosx/tkMacOSXInt.h:
+ * macosx/tkMacOSXCarbonEvents.c:
+ * macosx/tkMacOSXSubwindows.c:
+ * macosx/tkMacOSXWm.c:
+
+2006-10-31 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/makefile.vc: Added ttk files to msvc build and add manifest
+ * win/rules.vc: files to binaries with MSVC8.
+
+2006-10-31 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Wish.xcodeproj/project.pbxproj: add new Ttk files.
+
+ * macosx/ttkMacOSXTheme.c: standardize header #includes.
+
+ * unix/Makefile (checkstubs, checkexports): check ttk.decls, allow
+ export of Ttk prefixed symbols.
+
+ * generic/ttk/tkDefaultTheme.c: fix warnings.
+
+2006-10-30 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * doc/ttk_Geometry.3, doc/ttk_Theme.3, doc/ttk_button.n:
+ * doc/ttk_checkbutton.n, doc/ttk_combobox.n, doc/ttk_dialog.n:
+ * doc/ttk_entry.n, doc/ttk_frame.n, doc/ttk_image.n:
+ * doc/ttk_intro.n, doc/ttk_label.n, doc/ttk_labelframe.n:
+ * doc/ttk_menubutton.n, doc/ttk_notebook.n, doc/ttk_panedwindow.n:
+ * doc/ttk_progressbar.n, doc/ttk_radiobutton.n, doc/ttk_scrollbar.n:
+ * doc/ttk_separator.n, doc/ttk_sizegrip.n, doc/ttk_style.n:
+ * doc/ttk_treeview.n, doc/ttk_widget.n,:
+ * generic/ttk/ttk.decls, generic/ttk/ttkBlink.c:
+ * generic/ttk/ttkButton.c, generic/ttk/ttkCache.c:
+ * generic/ttk/ttkClamTheme.c, generic/ttk/ttkClassicTheme.c:
+ * generic/ttk/ttkDecls.h, generic/ttk/ttkDefaultTheme.c:
+ * generic/ttk/ttkElements.c, generic/ttk/ttkEntry.c:
+ * generic/ttk/ttkFrame.c, generic/ttk/ttkImage.c:
+ * generic/ttk/ttkInit.c, generic/ttk/ttkLabel.c:
+ * generic/ttk/ttkLayout.c, generic/ttk/ttkManager.c:
+ * generic/ttk/ttkManager.h, generic/ttk/ttkNotebook.c:
+ * generic/ttk/ttkPanedwindow.c, generic/ttk/ttkProgress.c:
+ * generic/ttk/ttkScale.c, generic/ttk/ttkScroll.c:
+ * generic/ttk/ttkScrollbar.c, generic/ttk/ttkSeparator.c:
+ * generic/ttk/ttkSquare.c, generic/ttk/ttkState.c:
+ * generic/ttk/ttkStubInit.c, generic/ttk/ttkStubLib.c:
+ * generic/ttk/ttkTagSet.c, generic/ttk/ttkTheme.c:
+ * generic/ttk/ttkTheme.h, generic/ttk/ttkThemeInt.h:
+ * generic/ttk/ttkTrace.c, generic/ttk/ttkTrack.c:
+ * generic/ttk/ttkTreeview.c, generic/ttk/ttkWidget.c:
+ * generic/ttk/ttkWidget.h:
+ * library/demos/ttk_demo.tcl, library/demos/ttk_iconlib.tcl:
+ * library/demos/ttk_repeater.tcl:
+ * library/ttk/altTheme.tcl, library/ttk/aquaTheme.tcl:
+ * library/ttk/button.tcl, library/ttk/clamTheme.tcl:
+ * library/ttk/classicTheme.tcl, library/ttk/combobox.tcl:
+ * library/ttk/cursors.tcl, library/ttk/defaults.tcl:
+ * library/ttk/dialog.tcl, library/ttk/entry.tcl:
+ * library/ttk/fonts.tcl, library/ttk/icons.tcl:
+ * library/ttk/keynav.tcl, library/ttk/menubutton.tcl:
+ * library/ttk/notebook.tcl, library/ttk/panedwindow.tcl:
+ * library/ttk/progress.tcl, library/ttk/scale.tcl:
+ * library/ttk/scrollbar.tcl, library/ttk/sizegrip.tcl:
+ * library/ttk/treeview.tcl, library/ttk/ttk.tcl:
+ * library/ttk/utils.tcl, library/ttk/winTheme.tcl:
+ * library/ttk/xpTheme.tcl:
+ * macosx/ttkMacOSXTheme.c:
+ * tests/ttk/all.tcl, tests/ttk/bwidget.test, tests/ttk/combobox.test:
+ * tests/ttk/entry.test, tests/ttk/image.test:
+ * tests/ttk/labelframe.test, tests/ttk/layout.test:
+ * tests/ttk/misc.test, tests/ttk/notebook.test:
+ * tests/ttk/panedwindow.test, tests/ttk/progressbar.test:
+ * tests/ttk/scrollbar.test, tests/ttk/treetags.test:
+ * tests/ttk/treeview.test, tests/ttk/ttk.test, tests/ttk/validate.test:
+ * win/ttkWinMonitor.c, win/ttkWinTheme.c, win/ttkWinXPTheme.c:
+ First import of Ttk themed Tk widgets as branched from tile 0.7.8
+
+ * generic/tkInt.h, generic/tkWindow.c: add Ttk_Init call, copy tk
+ classic widgets to ::tk namespace.
+ * library/tk.tcl: add source of ttk/ttk.tcl, define $::ttk::library.
+ * unix/Makefile.in, win/Makefile.in: add Ttk build bits
+ * win/configure, win/configure.in: check for uxtheme.h (XP theme).
+
+2006-10-23 Don Porter <dgp@users.sourceforge.net>
+
+ * README: Bump version number to 8.5a6
+ * generic/tk.h:
+ * library/tk.tcl:
+ * unix/configure.in:
+ * unix/tk.spec:
+ * win/configure.in:
+
+ * unix/configure: autoconf-2.59
+ * win/configure:
+
+2006-10-19 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ *** 8.5a5 TAGGED FOR RELEASE ***
+
+ * generic/tkImgBmap.c: Fixed line endings.
+ * win/makefile.vc: Patched up build system to manage
+ * win/rules.vc: AMD64 with MSVC8
+ * win/nmakehlp.c: Ensure operation without Platform SDK.
+
+2006-10-18 Don Porter <dgp@users.sourceforge.net>
+
+ * changes: 8.5a5 release date set.
+
+2006-10-17 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * doc/text.n: fix docs to not correct -tabs usage case.
+
+ * generic/tkTextDisp.c (SizeOfTab): fix -tabstyle wordprocessor tab
+ alignment to correct tab edge case. [Bug 1578858]
+
+2006-10-17 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * generic/tkText.c: Applied suggested patch from [Bug 1536735]
+ * tests/text.test: Update test for above patch.
+ * tests/textWind.test: Corrected test to catch all messages
+ * tests/safe.test: Silence spurious win32 failure awaiting TIP150
+ * tests/winDialog.test: Updated test for file name length check.
+ * test/winWm.test: Corrected test expectation for menu wrapping.
+
+2006-10-16 Andreas Kupries <andreask@activestate.com>
+
+ * doc/WindowId.3: Pat's commit on 2006-10-08 broke the .SH NAME
+ information across several lines, breaking the cross-linking of
+ manpages during installation for this one. Put everything back on a
+ single line, unbreaking it.
+
+2006-10-16 Daniel Steffen <das@users.sourceforge.net>
+
+ * changes: updates for 8.5a5 release.
+
+ * macosx/tkMacOSXDraw.c: fix numerous issues in CG and QD drawing
+ procs so that they now match X11 drawing much more closely [Bug
+ 1558051]; use Tiger ellipse drawing API when available; fix comments &
+ whitespace.
+
+ * macosx/tkMacOSXInit.c: set default linewidth limit for CG
+ antialiasing to 0 as thin horizontal/vertical lines look good now.
+ * macosx/README: document CG antialiasing limit changes.
+
+ * generic/tkCanvLine.c (ConfigureLine): on TkAqua, pass outline
+ * generic/tkCanvPoly.c (ConfigurePolygon): linewidth in gc even for
+ * generic/tkRectOval.c (ConfigureRectOval): fills (as it controls AA).
+
+ * macosx/GNUmakefile: don't redo prebinding of non-prebound binaires.
+
+ * library/demos/pendulum.tcl: fix incorrect setting of toplevel title.
+
+2006-10-10 Don Porter <dgp@users.sourceforge.net>
+
+ * changes: Updates for 8.5a5 release
+
+2006-10-08 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * generic/tkWindow.c: Implemented TIP #264 - Tk_Interp function.
+ * doc/WindowId.3: Documented Tk_Interp.
+ * generic/tk.decls: Added to the stubs interface and
+ * generic/tkDecls.h: regenerated.
+ * generic/tkStubsInit.c:
+
+2006-10-05 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/tkUnixFont.c (Ucs2beToUtfProc, UtfToUcs2beProc):
+ (TkpFontPkgInit, encodingAliases): Correct alignment issues in
+ encoding conversion. Call ucs-2be "unicode" on big-endian systems.
+ [Bug 1122671]
+
+2006-09-27 Andreas Kupries <andreask@activestate.com>
+
+ * unix/Makefile.in (install-binaries): Added a second guard to the
+ * win/Makefile.in: package index file to prevent older versions of Tcl
+ * win/makefile.vc: from seeing version numbers which may contain a/b
+ information, and then balking on them. This could otherwise happen
+ when Tcl/Tk 8.4 and 8.5 are installed in the same directory, seeing
+ each other. [Bug 1566418]
+
+2006-09-22 Andreas Kupries <andreask@activestate.com>
+
+ * generic/tkConsole.c: TIP #268 update regarding registered package
+ * generic/tkMain.c: version, now using full patchlevel instead of
+ * generic/tkWindow.c: major.minor
+ * library/tk.tcl:
+ * unix/configure:
+ * unix/Makefile.in:
+ * unix/tcl.m4:
+ * win/configure:
+ * win/Makefile.in:
+ * win/makefile.vc:
+ * win/rules.vc:
+ * win/tcl.m4:
+
+2006-09-20 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinMenu.c (TkpPostMenu): disable menu animation in menus with
+ images to avoid clipping bug. [Bug 1329198]
+
+2006-09-21 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkImgBmap.c (ImgBmapPostscript): Change 0 to NULL, since
+ they are not interchangable on all platforms in all circumstances.
+ [Tcl Bug 1562528]
+
+2006-09-11 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXWm.c (TkMacOSXMakeRealWindowExist): revert part of
+ 2006-05-16 change that had set overrideredirect windows to not become
+ activated by the window manager, as this prevented interaction with
+ native widgets in such windows [Bug 1472624]; apply changes to carbon
+ window attributes even if native window has already been created.
+
+ * macosx/tkMacOSXKeyEvent.c (TkMacOSXProcessKeyboardEvent): fix app
+ * macosx/tkMacOSXMenu.c (DrawMenuBarWhenIdle): menu item key shortcuts
+ * macosx/tkMacOSXInt.h: when custom ".apple" menu is installed.
+
+ * library/demos/widget: on TkAqua, don't install file menu with single
+ quit menu item, as the application menu already has a quit item.
+
+ * macosx/tkMacOSXColor.c: fix building on Mac OS X 10.2.
+
+2006-09-10 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXColor.c (TkSetMacColor,TkpGetColor): use AppearanceMgr
+ * macosx/tkMacOSXDefault.h: to retrieve platform std colors for text
+ * macosx/tkMacOSXPort.h: selections, add "systemHighlightSecondary"
+ color name for standard color of inactive selections, use this color as
+ default for text widget -inactiveselectbackground to implement platform
+ standard look for inactive text selections.
+
+ * library/text.tcl (aqua): remove focus bindings to set selection color
+
+ * generic/tkTextBTree.c (TkTextIsElided): on TkAqua, don't show
+ * generic/tkTextDisp.c (GetStyle): inactive text selection when
+ text widget is disabled.
+
+ * generic/tkEntry.c (DisplayEntry): change default TkAqua selection
+ * macosx/tkMacOSXDefault.h: relief to "flat" (platform std).
+
+ * generic/tkText.c (CreateWidget): fix bug leading to default text
+ selection relief string DEF_TEXT_SELECT_RELIEF being ignored.
+
+ * macosx/tkMacOSXMouseEvent.c (TkMacOSXProcessMouseEvent): allow mouse
+ event delivery to background windows with kWindowNoActivatesAttribute
+ (e.g. overrideredirect windows), as these never come to the foreground
+ they would never receive any mouse events otherwise. [Bug 1472624]
+
+ * macosx/tkMacOSXWindowEvent.c (TkMacOSXGenerateFocusEvent): do not
+ send focus events to any windows with kWindowNoActivatesAttribute.
+
+ * macosx/tkMacOSXXStubs.c (XQueryColor, XQueryColors): implement basic
+ XColor computation from pixel values, enough to make tkImg's window.c
+ happy, fixes img::window failures reported on tcl-mac.
+
+ * macosx/tkMacOSXMenu.c (DrawMenuEntryLabel): fix leak. [Bug 1554672]
+
+ * macosx/GNUmakefile: workaround bug in 'cp -pRH' on Darwin 6 and
+ earlier, fixes 'make embedded' failure reported on tcl-mac; fix error
+ from 'make deploy' with same build tree as previous 'make embedded'.
+
+ * macosx/Wish.xcodeproj/project.pbxproj: add new tclUnixCompat.c file.
+
+ * macosx/tkMacOSXEntry.c (TkpDrawEntryBorderAndFocus): fix typo.
+
+ * unix/tcl.m4: sync with tcl/unix/tcl.m4.
+ * unix/configure: autoconf-2.59
+
+2006-09-06 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkEntry.c: move hard-coded ALWAYS_SHOW_SELECTION control
+ * generic/tkInt.h: of entry/text selection display based on focus
+ * generic/tkText.c: to the Tcl level, controlled by
+ * generic/tkWindow.c: ::tk::AlwaysShowSelection (boolean, private).
+ * library/tk.tcl: [Bug 1553691]
+ * macosx/tkMacOSXDefault.h:
+ * unix/tkUnixDefault.h:
+ * unix/tkUnixPort.h:
+ * win/tkWinDefault.h:
+
+2006-08-30 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinKey.c: Add WM_UNICHAR window message support (used by
+ * win/tkWinX.c: virtual keyboard apps). [Bug 1518677] (petasis)
+
+2006-08-24 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXScrlbr.c (UpdateControlValues): set native scrollbar
+ control bounds only once all size adjustments have been computed.
+ Fixes issue with grow icon obscuring scrollbar reported on tcl-mac.
+
+2006-08-21 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXCarbonEvents.c (CarbonTimerProc): avoid starving main
+ event loop: limit the number of tcl events processed per invocation.
+ Fixes bug reported on tcl-mac by Kevan Hashemi.
+
+2006-08-18 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * tests/text.test (text-25.15): Added test suggested by Sam
+ <baudinm@yahoo.com> on comp.lang.tcl
+
+ * generic/tk.h, generic/tkInt.h: Stylistic improvements. No API change.
+
+2006-08-18 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/tcl.m4 (Darwin): add support for --enable-64bit on x86_64, for
+ universal builds including x86_64, for 64-bit CoreFoundation on Leopard
+ and for use of -mmacosx-version-min instead of MACOSX_DEPLOYMENT_TARGET
+ * unix/configure.in (Darwin): remove 64-bit arch flags from CFLAGS for
+ combined 32-bit and 64-bit universal builds, as neither TkAqua nor
+ TkX11 can be built for 64-bit at present.
+ * unix/configure: autoconf-2.59
+ * unix/tkConfig.h.in: autoheader-2.59
+
+ * macosx/Wish.xcodeproj/project.pbxproj: switch native release targets
+ to use DWARF with dSYM, Xcode 3.0 changes.
+ * macosx/README: updates for x86_64 support in Tcl.
+
+ * macosx/tkMacOSXInit.c (TkpInit): when available, use public
+ TransformProcessType() API instead of CPSEnableForegroundOperation()
+ SPI to notify the window server that we are a GUI application.
+
+ * macosx/tkMacOSXWm.c (WmAttrGetTitlePath): use HIWindow API on >=Tiger
+
+ * macosx/tkMacOSXMouseEvent.c (GenerateToolbarButtonEvent):
+ * macosx/tkMacOSXMenus.c (GenerateEditEvent):
+ * macosx/tkMacOSXMenu.c (MenuSelectEvent): bzero() the XVirtualEvent
+ structure before use to ensure all fields are initialized. [Bug
+ 1542205]
+
+2006-08-16 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * macosx/tkMacOSXWm.c (WmAttributesCmd): correct OS X result for [wm
+ attributes $top].
+
+2006-07-25 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXKeyEvent.c (TkMacOSXProcessKeyboardEvent): handle key
+ shortcut for kHICommandQuit in the same way as other application menu
+ item key shortcuts. [Bug 1516950]
+
+2006-07-24 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXWm.c (TkWmMapWindow): fix incorrect values of wmInfo
+ parentWidth/Height for toplevels by recalculating them once the window
+ is mapped (i.e once the window&structure sizes are known). [Bug
+ 1358663]
+ (ParseGeometry): sync with ParseGeometry in tkUnixWm.c/tkWinWm.c.
+
+2006-07-21 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tkBind.c (TkBindInit): for REDO_KEYSYM_LOOKUP, change
+ keysym-to-string mapping hash to use first name in ks_names.h instead
+ of last (if there are multiple possibilities), e.g. "F11" instead of
+ "L1".
+
+ * macosx/tkMacOSXKeyboard.c (TkpGetKeySym): correct keysyms for pure
+ modifier key presses [Bugs 700311, 1525905]; correct keysym for Enter
+ key; add keysyms for new NumLock and Fn modifiers (added 2005-08-09).
+
+2006-07-20 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXWm.c (WmAttributesCmd, WmIconbitmapCmd): add support
+ * unix/tkUnixSend.c (Tk_GetUserInactiveTime): for weakly
+ importing symbols not available on OSX 10.2 or 10.3, enables binaires
+ built on later OSX versions to run on earlier ones.
+ * macosx/Wish.xcodeproj/project.pbxproj: enable weak-linking; turn on
+ extra warnings.
+ * macosx/README: document how to enable weak-linking; cleanup.
+ * unix/configure.in: add check on Darwin-X11 for ld support of -weak-l
+ * unix/tcl.m4: flag and weak-link libXss if possible as it is not
+ available before OSX 10.4; enforce requirement of OSX 10.2 for TkAqua;
+ move Darwin specific checks & defines that are only relevant to the tcl
+ build out of tcl.m4; restrict framework option to Darwin; clean up
+ quoting and help messages.
+ * unix/configure: autoconf-2.59
+ * unix/tkConfig.h.in: autoheader-2.59
+
+ * macosx/GNUmakefile: enable xft for TkX11 build.
+ * macosx/tkMacOSXFont.c (TkMacOSXQuarzStartDraw, TkMacOSXQuarzEndDraw):
+ verify validity of context returned from QDBeginCGContext() before use.
+ * macosx/tkMacOSXKeyEvent.c: ifdef out diagnostic messages to stderr.
+
+ * macosx/tkMacOSXEvent.h: standardize MAC_OS_X_VERSION_MAX_ALLOWED
+ * macosx/tkMacOSXMenu.c: checks per QA1316, ensure define can be
+ * macosx/tkMacOSXMenubutton.c: overridden on command line (from default
+ * macosx/tkMacOSXMenus.c: of current OS version).
+ * macosx/tkMacOSXMouseEvent.c:
+ * macosx/tkMacOSXWm.c:
+
+ * generic/tkImgGIF.c (ReadImage):
+ * macosx/tkMacOSXCursor.c (TkMacOSXCursor):
+ * macosx/tkMacOSXDebug.c (TkMacOSXGetNamedDebugSymbol):
+ * macosx/tkMacOSXFont.c (TkpMeasureCharsInContext):
+ * macosx/tkMacOSXInit.c (Map):
+ * xlib/xgc.c (XCreateGC): fix signed-with-unsigned comparison and other
+ warnings from gcc4 -Wextra.
+
+2006-07-14 Andreas Kupries <andreask@activestate.com>
+
+ * generic/tkWindow.c (Initialize): Modify change of 2006-05-25 (jeffh).
+ Release mutex a bit earlier, to prevent lock when OS X creates its
+ console windows (recursively enters Tk_Init). Patch by JeffH.
+
+2006-07-06 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/tkfbox.tcl: catch scrollbar use of highlightthickness
+
+2006-06-21 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/bgerror.tcl (::tk::dialog::error::bgerror): remove a couple
+ of unnecessary hardcoded options
+
+2006-06-14 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkScale.c: Revised variable writing logic to account for
+ [scale]'s design that it deals with its value as a formatted string,
+ and not as a double. [Bug 891141]
+
+2006-06-14 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXSubwindows.c (TkMacOSXInvalidateWindow): ensure
+ invalid clip regions are recreated via TkMacOSXUpdateClipRgn() before
+ they are used; correct call order of TkMacOSXInvalidateWindow() and
+ TkMacOSXInvalClipRgns() throughout. [Bug 1501922]
+
+ * macosx/tkMacOSXDraw.c (TkPutImage): implement drawing of very wide
+ images in slices of less than 4096 pixels to workaround CopyBits
+ limitation. [Bug 950121]
+
+2006-06-09 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkMain.c: Added Tcl_Preserve() call on the master interp
+ as crash protection against any Tcl_DeleteInterp() call that might
+ happen.
+
+2006-06-01 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkConsole.c: Added Tcl_RegisterChannel() calls to bump the
+ refcount of channels passed to Tcl_SetStdChannel(). This prevents early
+ free-ing of the channels that leads to crashes. [Bug 912571]
+
+2006-05-29 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinEmbed.c (TkpGetOtherWindow): Do not panic if no window is
+ * unix/tkUnixEmbed.c (TkpGetOtherWindow): found; caller handles. [Bug
+ * unix/tkUnixWm.c (Tk_CoordsToWindow, UpdateGeometryInfo): 1212056]
+
+ * tests/entry.test (entry-22.1):
+ * tests/listbox.test (listbox-6.15):
+ * generic/tkListbox.c (ListboxInsertSubCmd, ListboxDeleteSubCmd):
+ Ignore Tcl_SetVar2Ex failure of listVarName, similar to entry widget
+ handling. [Bug 1424513]
+
+2006-05-26 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * macosx/tkMacOSXButton.c (TkMacOSXDrawControl): correct redraw for
+ direct transition from disabled to active state. [Bug 706446]
+
+2006-05-25 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinMenu.c (TkWinMenuKeyObjCmd): get eventPtr after we know the
+ window is still alive. [AS bug 45987] [Bug 1236306]
+
+ * generic/tkMenu.c (DeleteMenuCloneEntries): Modify entry index
+ changes to work around VC6 optimization bug. [Bug 1224330]
+
+ * generic/tkMessage.c (MessageWidgetObjCmd): Correct msgPtr
+ preserve/release pairing. [Bug 1485750] (afredd)
+
+ * generic/tkWindow.c (Initialize): Correct mutex (un)lock pairing.
+ [Bug 1479587] (loewis)
+
+ * generic/tkBind.c (Tk_BindEvent, TkCopyAndGlobalEval): use Tcl_EvalEx
+ instead of Tcl_GlobalEval.
+
+2006-05-16 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXWindowEvent.c (TkMacOSXGenerateFocusEvent): don't send
+ focus events to windows of class help or to overrideredirect windows.
+ [Bug 1472624]
+
+ * macosx/tkMacOSXWm.c: set overrideredirect windows to not become
+ activated by the window manager and to not receive OS activate events
+ (should make them behave more like on other platforms); use modern
+ window class API for overrideredirect and transient windows; set the
+ default class of overrideredirect windows to 'simple' rather than
+ 'plain' (i.e. no window frame); add missing Panther and Tiger window
+ attributes to [::tk::unsupported::MacWindowStyle].
+
+2006-05-12 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkImgPhoto.c (Tk_PhotoPutBlock, Tk_PhotoPutZoomedBlock): Fix
+ opt added 2006-03 that caused slowdown for some common cases. [Bug
+ 1409140]
+
+2006-05-13 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tkCanvWind.c (DisplayWinItem, WinItemRequestProc): ensure
+ canvas window items are unmapped when canvas is unmapped. [Bug 940117]
+
+ * macosx/tkMacOSXSubwindows.c (TkMacOSXUpdateClipRgn): empty clip
+ region of unmapped windows to prevent any drawing into them or into
+ their children from becoming visible. [Bug 940117]
+
+ * macosx/tkMacOSXInt.h: revert Jim's attempt of 2005-03-14 to
+ * macosx/tkMacOSXSubwindows.c: fix Bug 940117 as it disables Map/Unmap
+ event propagation to children. [Bug 1480105]
+
+ * macosx/tkMacOSXDraw.c (TkPutImage): handle tkPictureIsOpen flag,
+ fixes incorrect positioning of images with complex alpha on native
+ buttons; actual alpha blending is still broken in this situation. [Bug
+ 1155596]
+
+ * macosx/tkMacOSXEvent.c (TkMacOSXProcessCommandEvent):
+ * macosx/tkMacOSXMenus.c (TkMacOSXInitMenus): workaround carbon bug
+ with key shortcut for 'Preferences' app menu item. [Bug 1481503]
+
+ * macosx/tkMacOSXKeyEvent.c (TkMacOSXProcessKeyboardEvent): only check
+ for HICommand menu item shortcuts in the application menu.
+
+ * macosx/tkMacOSXInt.h: initialize keyboard layout setup in
+ * macosx/tkMacOSXInit.c: TkpInit() rather than during handling of
+ * macosx/tkMacOSXKeyEvent.c: first key down event.
+
+ * macosx/tkMacOSXDraw.c: add optional debug code to flash clip
+ * macosx/tkMacOSXSubwindows.c: regions during update or draw.
+
+2006-05-04 Don Porter <dgp@users.sourceforge.net>
+
+ * README: Bump version number to 8.5a5
+ * generic/tk.h:
+ * unix/configure.in:
+ * unix/tk.spec:
+ * win/configure.in:
+
+ * unix/configure: autoconf-2.59
+ * win/configure:
+
+2006-04-28 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXWm.c (TkWmMapWindow, InitialWindowBounds): fix use of
+ potentially stale window position in initial configure event on first
+ map of a window. [Bug 1476443]
+ (TkMacOSXWindowOffset): use modern GetWindowStructureWidths API.
+
+ * macosx/tkMacOSXInt.h:
+ * macosx/tkMacOSXMouseEvent.c (TkGenerateButtonEventForXPointer): new
+ internal function to generate button events for current pointer
+ directly, without requiring prior call to XQueryPointer().
+
+ * macosx/tkMacOSXMouseEvent.c (XQueryPointer): implement return of
+ window-local pointer position.
+
+ * macosx/tkMacOSXInt.h: use improvements above to avoid calls to
+ * macosx/tkMacOSXKeyEvent.c: GlobalToLocal() when the current port
+ * macosx/tkMacOSXMenu.c: might not be set correctly. May fix [Bug
+ * macosx/tkMacOSXMenus.c: 1243318]
+ * macosx/tkMacOSXScale.c:
+ * macosx/tkMacOSXScrlbr.c:
+
+ * tkAboutDlg.r: update copyright.
+
+ * macosx/tkMacOSXDebug.h: sync #includes with core-8-4-branch.
+ * macosx/tkMacOSXEvent.h:
+ * macosx/tkMacOSXFont.h:
+
+2006-04-26 Don Porter <dgp@users.sourceforge.net>
+
+ *** 8.5a4 TAGGED FOR RELEASE ***
+
+ * changes: Updates for next RC
+
+2006-04-25 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * unix/tkUnixFont.c (TkpGetFontFamilies): Fix crash caused when the
+ XServer returns invalid font names. [Bug 1475865]
+
+2006-04-23 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * tests/scrollbar.test: fix to tkAqua test failures
+
+2006-04-18 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * macosx/tkMacOSXEmbed.c: fix to [Bug 1088814] test failures in
+ embed.test
+
+ * macosx/tkMacOSXWm.c:
+ * tests/constraints.tcl:
+ * tests/wm.test: fix to 'wm attributes' test for TkAqua
+
+2006-04-11 Peter Spjuth <peter.spjuth@space.se>
+
+ * generic/tkWindow.c (Tk_NameToWindow): Allow NULL interp to
+ Tk_NameToWindow. This fixes TkGetWindowFromObj which promises to handle
+ NULL but didn't.
+
+ * generic/tkGrid.c: Fixed handling of out of bounds row or column.
+ * tests/grid.test: [Bug 1432666]
+
+2006-04-11 Don Porter <dgp@users.sourceforge.net>
+
+ * unix/Makefile.in: Updated `make dist` target to be sure the
+ message catalogs for the widget demo get packaged into the source code
+ distribution. [Bug 1466509]
+
+2006-04-11 Daniel Steffen <das@users.sourceforge.net>
+
+ * changes: added latest aqua bug fixes.
+
+ * macosx/tkMacOSXDialog.c (Tk_MessageBoxObjCmd): added standard Escape
+ key binding for msgbox cancel buttons [Patch 1193614], whitespace.
+
+ * macosx/tkMacOSXCarbonEvents.c: handle kEventCommandUpdateStatus
+ * macosx/tkMacOSXEvent.c: carbon event to dynamically enable
+ the 'Preferences' app menu item when proc [::tk::mac::ShowPreferences]
+ is defined. [Bug 700316]
+
+ * macosx/tkMacOSXHLEvents.c: call ::tk::mac::* procs for all
+ * macosx/tkMacOSXWindowEvent.c: registered appleevents [FR 1105284],
+ implement print applevent handling, style/whitespace cleanup.
+
+ * macosx/tkMacOSXDraw.c (TkMacOSXInitCGDrawing): prevent multiple init
+
+ * macosx/tkMacOSXFont.c: remove #ifdef'd text measuring codepaths now
+ * macosx/tkMacOSXInit.c: known to be incorrect, cleanup obsolete text
+ * macosx/README: antialiasing control code, document ATSUI
+ text antialiasing changes.
+
+ * macosx/tkMacOSXInt.h: Implemented 'zoomed' window state
+ * macosx/tkMacOSXWindowEvent.c: handling for TkAqua, via titlebar
+ * macosx/tkMacOSXWm.c: widget clicks as well as [wm state].
+ * doc/wm.n: [Bug 1073456]
+
+2006-04-10 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * library/tkfbox.tcl (::tk::IconList_Goto): Fix prefix searching so
+ that the start location is reasonable, and the prefix matching is
+ using the correct Tcl command for this. [Bug 1467938]
+
+2006-04-10 Benjamin Riefenstahl <b.riefenstahl@turtle-trading.net>
+
+ * macosx/tkMacOSXFont.c (MeasureStringWidth): Use implementation based
+ on ATSUGetGlyphBounds (TK_MAC_USE_GETGLYPHBOUNDS), so we can use
+ kATSUseFractionalOrigins. This in turn corrects [Bug 1461650].
+ (InitFont): Use "." and "W" instead of "i" and "w" to determine the
+ "-fixed" attribute. This prevents "Apple Chancery" from being
+ classified as fixed.
+ (InitFontFamilies): Only get the font families once.
+
+2006-04-09 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXWm.c (WmResizableCmd): propagate window attribute
+ changes to Carbon window manager. [FR 1467004]
+ (TkSetWMName, TkMacOSXMakeRealWindowExist): allow empty name for
+ toplevels, remove bogus initial window name. [Bug 1450800]
+
+2006-04-07 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXMouseEvent.c (TkMacOSXProcessMouseEvent): fix return
+ values, implement window dragging & growing in background (with Command
+ key down) and by fronting clicks [Bug 934524], use correct button &
+ modifier state API when application is in background (also in
+ TkMacOSXButtonKeyState).
+
+ * macosx/tkMacOSXWm.c (TkMacOSXGrowToplevel): ensure QD port is set
+ correctly before using API relying on it.
+
+2006-04-06 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * macosx/tkMacOSXMouseEvent.c: Now that [wm attributes -titlepath]
+ works correctly, add OS support for dragging proxy icons and using the
+ titlepath menu.
+
+2006-04-06 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXWm.c (WmAttributesCmd, WmIconbitmapCmd): fix errors in
+ setting/removing window proxy icons via [wm attributes -titlepath] and
+ [wm iconbitmap], use HIWindow API on Tiger or later. [Bug 1455241]
+
+ * unix/tcl.m4: remove TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING
+ define on Darwin. [Tcl Bug 1457515]
+ * unix/configure: autoconf-2.59
+ * unix/tkConfig.h.in: autoheader-2.59
+
+2006-04-05 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkWindow.c (Initialize): remove impotent use of
+ DeleteWindowsExitProc as a global exit handler.
+
+ * generic/tkMenu.c (TkSetWindowMenuBar): remove extra TkMenuInit call
+ that caused finalization panic. [Bug 1456851]
+ * win/tkWinMenu.c (FreeID, TkpNewMenu, MenuExitHandler)
+ (MenuThreadExitHandler, TkpMenuInit, TkpMenuThreadInit): rework Windows
+ menu init/finalization to better respect per-process and per-thread
+ boundaries. [Bug 1456851]
+ (TkWinMenuKeyObjCmd): Do not error when unknown window is passed in.
+ [Bug 1236306]
+
+ * win/tkWinX.c (TkWinXInit): init default keyboard charset correctly.
+ [Bug 1374119] (pajas)
+
+ * win/tkWinWm.c (WmProc): pass WM_QUERYENDSESSION message to Tk as
+ WM_SAVE_YOURSELF wm protocol callback.
+
+ * tests/textWind.test (textWind-10.6.1): prevent infinite update loop
+ in case of test failure.
+
+ * tests/wm.test (wm-attributes-1.2.4): correct expected result.
+
+ * tests/grid.test: fix segfault on empty or "all" index list
+ * generic/tkGrid.c (GridRowColumnConfigureCommand): [Bug 1422430]
+
+2006-04-05 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkText.c: fix to crash caused on some platforms by new tests
+ introduced to check for [Bug 1414171], which destroy the text widget in
+ the dump callback script.
+
+2006-03-29 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkOption.c (TkOptionDeadWindow): handle OptionThreadExitProc
+ being called before DeleteWindowsExitProc.
+
+ * win/Makefile.in: convert _NATIVE paths to use / to avoid ".\"
+ path-as-escape issue.
+
+2006-03-29 Don Porter <dgp@users.sourceforge.net>
+
+ * changes: Updates for next RC
+
+ * unix/tkUnixDefault.h: Changed "Black" to "#000000" and "White" to
+ "#ffffff" to work around the (broken?) X servers that do not accept
+ those color names. [Bug 917433]
+
+2006-03-28 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/tcl.m4, win/tcl.m4: []-quote AC_DEFUN functions.
+
+2006-03-26 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkText.c:
+ * tests/text.test: Fix for elaborations of [Bug 1414171] for '$text
+ dump -command <script>' where script deletes large portions of the
+ text widget, or even destroys the widget.
+
+2006-03-28 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Wish.xcode/default.pbxuser: add '-singleproc 1' cli arg to
+ * macosx/Wish.xcodeproj/default.pbxuser: tktest to ease test debugging.
+
+ * macosx/Wish.xcode/project.pbxproj: removed $prefix/share from
+ * macosx/Wish.xcodeproj/project.pbxproj: TCL_PACKAGE_PATH as per change
+ to tcl/unix/configure.in of 2006-03-13.
+
+ * macosx/tkMacOSXDraw.c: sync whitespace & minor changes with
+ * macosx/tkMacOSXEvent.h: core-8-4-branch.
+ * macosx/tkMacOSXFont.h:
+ * macosx/tkMacOSXMenu.c:
+ * macosx/tkMacOSXNotify.c:
+
+2006-03-27 Don Porter <dgp@users.sourceforge.net>
+
+ * changes: Updates for next RC
+
+2006-03-27 Benjamin Riefenstahl <b.riefenstahl@turtle-trading.net>
+
+ * generic/tkTextDisp.c (MeasureChars): Fix calculations of start and
+ end of string. [Bugs 1325998, 1456157]
+
+2006-03-27 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkImgGIF.c (FileReadGIF): Stop crashes when the first GIF
+ frame does not define the overall size of the image. [Bug 1458234]
+
+2006-03-26 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkText.c:
+ * generic/tkText.h:
+ * generic/tkTextBTree.c:
+ * tests/text.test: Fix for [Bug 1414171] for '$text dump -command
+ <script>' where 'script' actually modifies the widget during the
+ process.
+
+2006-03-25 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXDraw.c (TkMacOSXSetUpCGContext):
+ * macosx/tkMacOSXFont.c (TkMacOSXQuarzStartDraw, TkMacOSXQuarzEndDraw):
+ performance improvements, sync similar code, formatting & whitespace.
+
+2006-03-24 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tkTextDisp.c: Moved #ifdef MAC_OSX_TK code added by
+ * macosx/tkMacOSXColor.c: [Patch 638966] into platform specific files.
+ * macosx/tkMacOSXInt.h:
+
+ * macosx/tkMacOSX.h: Cleaned up & rationalized order of
+ * macosx/tkMacOSXBitmap.c: #includes of tk and carbon headers.
+ * macosx/tkMacOSXButton.c:
+ * macosx/tkMacOSXCarbonEvents.c:
+ * macosx/tkMacOSXClipboard.c:
+ * macosx/tkMacOSXColor.c:
+ * macosx/tkMacOSXConfig.c:
+ * macosx/tkMacOSXCursor.c:
+ * macosx/tkMacOSXDialog.c:
+ * macosx/tkMacOSXDraw.c:
+ * macosx/tkMacOSXEmbed.c:
+ * macosx/tkMacOSXEntry.c:
+ * macosx/tkMacOSXEvent.c:
+ * macosx/tkMacOSXEvent.h:
+ * macosx/tkMacOSXFont.h:
+ * macosx/tkMacOSXHLEvents.c:
+ * macosx/tkMacOSXInit.c:
+ * macosx/tkMacOSXInt.h:
+ * macosx/tkMacOSXKeyEvent.c:
+ * macosx/tkMacOSXKeyboard.c:
+ * macosx/tkMacOSXMenu.c:
+ * macosx/tkMacOSXMenubutton.c:
+ * macosx/tkMacOSXMenus.c:
+ * macosx/tkMacOSXMouseEvent.c:
+ * macosx/tkMacOSXRegion.c:
+ * macosx/tkMacOSXScale.c:
+ * macosx/tkMacOSXScrlbr.c:
+ * macosx/tkMacOSXSend.c:
+ * macosx/tkMacOSXSubwindows.c:
+ * macosx/tkMacOSXWindowEvent.c:
+ * macosx/tkMacOSXWm.c:
+ * macosx/tkMacOSXWm.h:
+ * macosx/tkMacOSXXStubs.c:
+
+2006-03-23 Reinhard Max <max@tclers.tk>
+
+ * unix/tkUnixRFont.c (TkpMeasureCharsInContext): Copied over from
+ tkUnixFont.c to fix compiling with --enable-xft .
+
+ * unix/tk.spec: Cleaned up and completed. An RPM can now be built from
+ the tk source distribution with "rpmbuild -tb <tarball>".
+
+2006-03-23 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/textDisp.test: Updated expected error messages to match the
+ standardized formats established on 2005-11-17. [Bug 1370296]
+
+2006-03-22 Don Porter <dgp@users.sourceforge.net>
+
+ * changes: Updates for next RC
+
+2006-03-21 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tkFont.c: implementation of ATSUI text rendering
+ * generic/tkInt.h: in TkAqua provided by Benjamin
+ * generic/tkTextDisp.c: Riefenstahl. [Patch 638966]
+ * library/demos/unicodeout.tcl:
+ * macosx/tkMacOSXFont.h (new file):
+ * macosx/tkMacOSXFont.c:
+ * tests/font.test:
+ * unix/tkUnixFont.c:
+ * win/tkWinFont.c:
+
+ * generic/tkFont.c: moved MODULE_SCOPE declarations of font
+ * generic/tkFont.h: helper procs into header files.
+ * macosx/tkMacOSXButton.c:
+ * macosx/tkMacOSXFont.h:
+ * macosx/tkMacOSXMenubutton.c:
+
+ * macosx/Wish.xcode/project.pbxproj: add new tkMacOSXFont.h file,
+ * macosx/Wish.xcodeproj/project.pbxproj: turn off dead code stripping
+ as it interferes with -sectcreate (rdar://4486223).
+
+ * macosx/Wish.xcode/default.pbxuser: add TCLLIBPATH=/Library/Tcl
+ * macosx/Wish.xcodeproj/default.pbxuser: env var setting to tktest.
+
+ * unix/configure.in: fix detection of symbols build when enabling
+ TkAqua debug code; filter nm output of libtclstub better to avoid
+ error on intel macs. [Bug 1415789]
+ * unix/configure: autoconf-2.59
+
+2006-03-20 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkConsole.c: Added exit handler to clean up the interp where
+ the console window lives. Also added code to handle multiple calls to
+ Tk_CreateConsoleWindow so that the console channels connect to the last
+ console window opened, in compatibility with the previous
+ implementation.
+
+2006-03-18 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkText.c: Fix for undo/modified status of text widgets when
+ empty strings are inserted and undone.
+
+2006-03-17 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * library/clrpick.tcl: Avoid using abbreviated sub-commands in core
+ * library/palette.tcl: scripts as this can cause problems with
+ * library/scale.tcl: mega-widget libraries like snit.
+ * library/scrlbar.tcl: [Bug 1451587]
+ * library/tkfbox.tcl:
+ * library/xmfbox.tcl:
+
+2006-03-16 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkConsole.c: Substantial rewrite of [console] support.
+ * generic/tkInt.h: Included Obj-ification of the [console] and
+ [consoleinterp] commands, and reworking of all the supporting data
+ structures for cleaner sharing and lifetime management especially in
+ multi-threaded configurations.
+
+2006-03-16 Donal K. Fellows <dkf@users.sf.net>
+
+ * library/msgs/pt.msg: Messages for Portuguese (strictly just for
+ Brazilian Portuguese, but they'll do until we get other Portuguese
+ speakers localize) from Ricardo Jorge <ricardoj@users.sf.net> and Silas
+ Justiano <silasj@users.sf.net>. Many thanks! [Bug 1405069]
+
+ * generic/tkImgPhoto.c (ImgPhotoCmd, Tk_PhotoPutBlock)
+ (Tk_PhotoPutZoomedBlock): Added hack to detect copying of a photo with
+ a simple alpha channel and skip calling ToggleComplexAlphaIfNeeded.
+ This should speed up many photo-to-photo copies, keeping the cost of
+ the alpha channel down.
+
+2006-03-15 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkImgPhoto.c (Tk_PhotoPutBlock, Tk_PhotoPutZoomedBlock): Try
+ to squelch performance issue with code that writes to large images by
+ single pixels. Masses of thanks to George Staplin for helping to trace
+ this down to the COMPLEX_ALPHA flag handling code. [Bug 1409140]
+
+2006-03-13 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/scrollbar.test: Corrected several broken calls to [testmetrics]
+ that were crashing the test suite.
+
+ * tests/constraints.tcl: Added notAqua constraint to canvPs-3.1
+ * tests/canvPs.test: to stop test suite crash on Mac OSX.
+ [Bug 1088807]
+
+ * generic/tkCmds.c: Purged remaining references to errno,
+ * macosx/tkMacOSXPort.h: and errno.h. Standardized the logic
+ * macosx/tkMacOSXWm.c: for using header files from the compat
+ * macosx/tkMacOSXWm.h: directory. Thanks Joe English for the
+ * unix/tkUnixPort.h: patch. [Patch 1445404]
+
+2006-03-08 Don Porter <dgp@users.sourceforge.net>
+
+ * unix/Makefile.in: Update `make dist` to copy the image files needed
+ by the test suite into the source distro. This was overlooked in the
+ 2005-10-12 commit.
+
+ * changes: Update in prep. for 8.5a4 release.
+
+2006-03-07 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/tcl.m4: Set SHLIB_LD_FLAGS='${LIBS}' on NetBSD, as per the other
+ *BSD variants. [Bug 1334613]
+ * unix/configure: Regenerated.
+
+2006-03-07 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/canvas.n: Added note that stipples are not well-supported on
+ non-X11 platforms. [Bug 220787] It's not a great solution, but it does
+ indicate the state of affairs that has existed for years anyway; not
+ much modern software uses stipples anyway.
+
+2006-03-02 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * macosx/tkMacOSXDraw.c (TkPutImage): Fix endian issue on OS X x86
+ displaying images. Bitmap images still have a black/white reversal
+ issue, appears to be a general OS X issue (as seen in frogger demo).
+
+2006-02-27 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * generic/tkBitmap.c (Tk_GetBitmapFromData): Improve thread-safety.
+ [Bug 470322]
+
+ * generic/tkImgBmap.c (ImgBmapConfigureInstance): Force creation of new
+ Pixmaps before deletion of old ones to prevent stupid caching problems.
+ [Bug 480862]
+
+2006-02-09 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tk.decls: fix signature of TkMacOSXInvalClipRgns
+ * generic/tkPlatDecls.h: to use Tk_Window instead of internal
+ * macosx/tkMacOSXSubwindows.c: type TkWindow (which led to any include
+ * macosx/tkMacOSXWindowEvent.c: of public header tkMacOSX.h requiring
+ * macosx/tkMacOSXWm.c: prior include of tkInt.h).
+
+ * generic/tk.h: move TkAqua specific REDO_KEYSYM_LOOKUP define
+ * macosx/tkMacOSXPort.h: out of tk.h into platform header.
+
+2006-01-31 Donal K. Fellows <dkf@users.sf.net>
+
+ * library/bgerror.tcl (::tk::dialog::error::bgerror): Finish the
+ internationalization of the error dialog. [Bug 1409264]
+
+2006-01-25 Don Porter <dgp@users.sourceforge.net>
+
+ * library/bgerror.tcl: Updates to use Tcl 8.4 features. [Patch 1237759]
+ * library/choosedir.tcl:
+ * library/comdlg.tcl:
+ * library/console.tcl:
+ * library/dialog.tcl:
+ * library/focus.tcl:
+ * library/msgbox.tcl:
+ * library/palette.tcl:
+ * library/tk.tcl:
+ * library/tkfbox.tcl:
+ * library/xmfbox.tcl:
+
+2006-01-23 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/configure: minor fix to Darwin specific code removing
+ * unix/configure.in: 64bit flags from CFLAGS for Tk build.
+
+2006-01-20 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/tkEvent.c, unix/tkUnixEvent.c: XIM fixes [See 905830, patch
+ tk84-xim-fixes.patch], and revert 2005-12-05 patch disabling XIM when
+ SCIM in use, and make sure all X events get passed to XFilterEvent,
+ including those without a corresponding Tk window.
+
+2006-01-13 Anton Kovalenko <a_kovalenko@users.sourceforge.net>
+
+ * generic/tkUndo.c (TkUndoSetDepth): Don't free TkUndoSubAtoms for
+ separator entries that are deleted: there is some unpredictable garbage
+ instead of subatoms.
+
+ Free both 'apply' and 'revert' action chains for non-separator entries.
+
+2006-01-12 Donal K. Fellows <dkf@users.sf.net>
+
+ TIP #260 IMPLEMENTATION
+
+ * generic/tkCanvText.c (TextItem, CreateText, DisplayCanvText):
+ * doc/canvas.n: Code, docs and tests to implement an -underline
+ * tests/canvText.test: option for canvases' text items.
+
+2006-01-11 Peter Spjuth <peter.spjuth@space.se>
+
+ * generic/tkGrid.c: Removed a lingering error message from TIP#147
+ implementation.
+
+2006-01-10 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXDebug.c: add TkMacOSXGetNamedDebugSymbol() function
+ * macosx/tkMacOSXDebug.h: that finds unexported symbols in loaded
+ libraries by manually walking their symbol table; only to be used for
+ debugging purposes, may break unexpectedly in the future. Needed to get
+ access to private_extern internal debugging functions in HIToolbox.
+
+ * macosx/tkMacOSXCarbonEvents.c: fix debug event tracing on Tiger.
+ * macosx/tkMacOSXMenu.c: add debug menu printing during reconfigure.
+ * macosx/tkMacOSXInit.c: conditionalize 64bit-unsafe dyld code.
+ * macosx/GNUmakefile: add 'wish8.x' symlink to SYMROOT.
+
+ * macosx/Wish.xcode/project.pbxproj: fix copy to tktest resource
+ * macosx/Wish.xcodeproj/project.pbxproj: fork when zerolinked.
+
+ * macosx/Wish.xcode/default.pbxuser: add widget demo as argument to
+ * macosx/Wish.xcodeproj/default.pbxuser: executables (on by default).
+
+ * unix/configure: add caching, use AC_CACHE_CHECK instead of
+ * unix/configure.in: AC_CACHE_VAL where possible, consistent message
+ * unix/tcl.m4: quoting, sync relevant tclconfig/tcl.m4 changes
+ and gratuitous formatting differences, fix SC_CONFIG_MANPAGES with
+ default argument, Darwin improvements to SC_LOAD_*CONFIG.
+
+2005-12-28 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkUndo.c (TkUndoSetDepth): Apply [Patch 1391939] from Ludwig
+ Callewaert to fix [Bug 1380427].
+
+2005-12-14 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Wish.xcode/project.pbxproj:
+ * macosx/Wish.xcodeproj/project.pbxproj: add new tclTomMath* files.
+
+2005-12-13 Daniel Steffen <das@users.sourceforge.net>
+
+ * library/demos/cscroll.tcl: add MouseWheel bindings for aqua.
+
+ * macosx/tkMacOSXCarbonEvents.c (TkMacOSXInitCarbonEvents):
+ * macosx/tkMacOSXMouseEvent.c (TkMacOSXProcessMouseEvent)
+ (GenerateMouseWheelEvent): add support for kEventMouseScroll events
+ (smooth mouse wheel scrolling from mighty mouse or scrolling trackpad)
+ by handling kEventMouseWheelMoved on application target as well as on
+ dispatcher, in order to pick up synthesized MouseWheel events from
+ HIObject handler (c.f. QA1453); add support for horizontal scrolling
+ events by generating MouseWheel XEvent with Shift modifier.
+
+2005-12-12 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/tcl.m4, unix/configure: Fix sh quoting error reported in
+ bash-3.1+ [Bug 1377619] (schafer)
+
+2005-12-09 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/tkWinWm.c (WinSetIcon): Don't check result of SetClassLong() or
+ SetClassLongPtr() since it was generating an incorrect error and the
+ MSDN docs indicate that the result need not be checked.
+
+2005-12-09 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/configure: Regen.
+ * win/tcl.m4 (SC_CONFIG_CFLAGS): Define MACHINE for gcc builds. The
+ lack of a definition of this variable in the manifest file was causing
+ a runtime error in wish built with gcc.
+
+2005-12-09 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tkInt.decls: Move all platform test sources from tk lib into
+ * generic/tkTest.c: tktest directly, removes requirement to export
+ * macosx/tkMacOSXTest.c:TkplatformtestInit from internal stubs table.
+ * unix/Makefile.in:
+ * win/Makefile.in:
+ * win/makefile.vc:
+ * win/tkWinTest.c:
+
+ * generic/tkIntPlatDecls.h:
+ * generic/tkStubInit.c: regen.
+
+2005-12-08 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tcl.m4: Add build support for Windows-x64 builds.
+ * win/configure: --enable-64bit now accepts =amd64|ia64 for
+ * win/Makefile.in: Windows 64-bit build variants (default: amd64)
+ * win/makefile.vc: [Bug 1369597]
+ (TKOBJS): add tkWinTest.obj to regular Tk obj for TkplatformtestInit
+
+ * win/configure.in: Add CE build support (some C code fixes needed)
+ * win/wish.exe.manifest.in (new): manifest must map in MACHINE and
+ * win/rc/wish.exe.manifest (removed): VERSION to be correct.
+ * unix/Makefile.in: fix dist target for manifest dir change
+
+ * generic/tkTextTag.c (TkTextTagCmd): use correct arraySize for peered
+ text widgets in [$text tag names]. [Bugs 1375069, 1374935]
+
+2005-12-08 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXDraw.c: Remove inclusion of tclInt.h and use of tcl
+ * macosx/tkMacOSXFont.c: internals wherever possible in tk/macosx, the
+ * macosx/tkMacOSXInit.c: only remaining tcl internals in TkAqua are
+ * macosx/tkMacOSXNotify.c:TclServiceIdle() in tkMacOSXScrlbr.c and
+ * macosx/tkMacOSXScrlbr.c:Tcl_Get/SetStartupScript() in tkMacOSXInit.c
+ [RFE 1336531]
+
+ * macosx/tkMacOSXInt.h: sync comments with core-8-4-branch.
+
+2005-12-07 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/tkUnixEvent.c (OpenIM): remove extraneous const
+
+2005-12-06 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * doc/ConfigWidg.3 (TK_CONFIG_OPTION_SPECIFIED): Mentioned that the
+ flag is deprecated because it is not thread-safe.
+
+2005-12-05 Reinhard Max <max@suse.de>
+
+ * unix/tkUnixEvent.c (OpenIM): Added a workaround to allow at least
+ ASCII and the Compose key when typing into text and entry widgets on a
+ system that uses SCIM. This has to be taken out again once the SCIM
+ problems have been fixed.
+
+2005-12-01 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/tcl.m4 (Darwin): fixed error when MACOSX_DEPLOYMENT_TARGET unset
+ * unix/configure: regen.
+
+2005-11-30 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinWm.c (WmAttributesCmd): set (no)topmost window aspect before
+ rewrapping. [Bug 1086049]
+
+ * macosx/tkMacOSXXStubs.c (TkpOpenDisplay, TkMacOSXDisplayChanged):
+ * macosx/tkMacOSXWindowEvent.c (TkMacOSXProcessApplicationEvent):
+ * macosx/tkMacOSXCarbonEvents.c (TkMacOSXInitCarbonEvents):
+ * macosx/tkMacOSXEvent.h: Trap kEventAppAvailableWindowBoundsChanged
+ * macosx/tkMacOSXInt.h: event to watch for change in display size and
+ adjust internal state appropriately.
+
+ * doc/checkbutton.n: fix -selectcolor docs. [Bug 1083838]
+
+ * generic/tkImgGIF.c: cast calls to blockOut
+
+ * win/Makefile.in: place TCL_BIN_DIR first in PATH for targets to get
+ Tcl built dll first.
+ Add tkWinTest.obj to tk84.dll to handle some needed test functions
+ being defined in stubs (TkplatformtestInit).
+
+ * tests/scrollbar.test (6.22): fix rounding-error sensitive test
+
+2005-11-29 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/console.tcl (::tk::ConsoleInit): improve work-around to avoid
+ '% ' from tclMain.c. [Bug 1252259]
+
+2005-11-27 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/tcl.m4 (Darwin): add 64bit support, check for Tiger copyfile(),
+ add CFLAGS to SHLIB_LD to support passing -isysroot in env(CFLAGS) to
+ configure (flag can't be present twice, so can't be in both CFLAGS and
+ LDFLAGS during configure), don't use -prebind when deploying on 10.4,
+ define TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING (rdar://3171542).
+ (SC_ENABLE_LANGINFO, SC_TIME_HANDLER): add/fix caching, fix obsolete
+ autoconf macros. Sync with tcl/unix/tcl.m4.
+
+ * unix/configure.in: fix obsolete autoconf macros, sync gratuitous
+ formatting/ordering differences with tcl/unix/configure.in.
+
+ * unix/Makefile.in: add CFLAGS to wish/tktest link to make executable
+ linking the same as during configure (needed to avoid loosing any
+ linker relevant flags in CFLAGS, in particular flags that can't be in
+ LDFLAGS). Avoid concurrent linking of wish and compiling of
+ tkTestInit.o during parallel make, fix dependencies and flags for
+ building tkMacOSXInit.o
+ (checkstubs, checkexports): dependency and Darwin fixes
+ (dist): add new macosx files.
+
+ * macosx/tkMacOSXEvent.c (TkMacOSXProcessEvent):
+ * macosx/tkMacOSXEvent.h:
+ * macosx/tkMacOSXMouseEvent.c (TkMacOSXProcessMouseEvent):
+ * macosx/tkMacOSXCarbonEvents.c: install standard application event
+ handler, add & call functions to start and stop carbon even timer that
+ runs the tcl event loop periodically during a nested carbon event loop
+ in the toolbox (e.g. during menutracking) to ensure tcl timers etc.
+ continue to fire, register app event handler for menu tracking and HI
+ command carbon events, move menu event handling to new handlers for
+ those carbon events, no longer register for/handle appleevent carbon
+ event (now dealt with by standard application event handler), event
+ debugging code dynamically acquires carbon event debugging functions to
+ allow use on Tiger where they are no longer exported from HIToolbox.
+
+ * macosx/tkMacOSXFont.c (TkMacOSXUseAntialiasedText):
+ * macosx/tkMacOSXKeyEvent.c (GetKeyboardLayout):
+ * macosx/tkMacOSXCarbonEvents.c (TkMacOSXInitCarbonEvents):
+ * macosx/tkMacOSXInit.c:
+ * macosx/tkMacOSXInt.h: abstract common code to dynamically acquire
+ address of a named symbol (from a loaded dynamic library) into new
+ function TkMacOSXGetNamedSymbol() and macro TkMacOSXInitNamedSymbol.
+
+ * macosx/tkMacOSXMenu.c (TkpNewMenu):
+ * macosx/tkMacOSXMenubutton.c (MenuButtonInitControl):
+ * macosx/tkMacOSXMenus.c (TkMacOSXHandleMenuSelect): switch to modern
+ utf-8 aware menu manager API, remove obsolete code, add error handling.
+
+ * macosx/tkMacOSXMenu.c:
+ * macosx/tkMacOSXMenus.c:
+ * macosx/tkMacOSXMenubutton.c:
+ * macosx/tkMacOSXMouseEvent.c: define OSX 10.3 or later only constants
+ if necessary to allow compilation on OSX 10.2
+
+ * macosx/tkMacOSXWm.c (UpdateSizeHints): remove code that is never
+ executed.
+
+ * xlib/xgc.c (XCreateGC): sync with core-8-4-branch change.
+
+ * generic/tk.h: add/correct location of version numbers in macosx files
+
+ * generic/tkInt.h: clarify fat compile comment.
+
+ * macosx/Wish.pbproj/default.pbxuser (new):
+ * macosx/Wish.pbproj/jingham.pbxuser:
+ * macosx/Wish.pbproj/project.pbxproj:
+ * macosx/Wish.xcode/default.pbxuser:
+ * macosx/Wish.xcode/project.pbxproj:
+ * macosx/Wish.xcodeproj/default.pbxuser (new):
+ * macosx/Wish.xcodeproj/project.pbxproj (new): new/updated projects for
+ Xcode 2.2 on 10.4, Xcode 1.5 on 10.3 & ProjectBuilder on 10.2, with
+ native tktest targets and support for universal (fat) compiles.
+
+ * macosx/Tk-Info.plist (removed):
+ * macosx/Wish-Info.plist (removed):
+ * macosx/buildTkConfig.tcl (removed): remove obsolete build files.
+
+ * macosx/README: clarification/cleanup, document new Xcode projects and
+ universal (fat) builds via CFLAGS (i.e. ppc and i386 at the same time).
+
+ * unix/Makefile.in:
+ * unix/aclocal.m4:
+ * unix/configure.in:
+ * macosx/configure.ac (new): add support for inclusion of
+ unix/configure.in by macosx/configure.ac, allows generation of a
+ config headers enabled configure script in macosx (required by Xcode
+ projects).
+
+ * macosx/GNUmakefile: rename from Makefile to avoid overwriting by
+ configure run in tk/macosx, add support for reusing configure cache,
+ build target fixes.
+
+ * generic/tk3d.h:
+ * generic/tkButton.h:
+ * generic/tkCanvas.c:
+ * generic/tkCanvas.h:
+ * generic/tkColor.h:
+ * generic/tkEntry.h:
+ * generic/tkFileFilter.h:
+ * generic/tkFont.c:
+ * generic/tkFont.h:
+ * generic/tkImage.c:
+ * generic/tkImgPhoto.c:
+ * generic/tkInt.h:
+ * generic/tkMenu.c:
+ * generic/tkMenu.h:
+ * generic/tkMenubutton.h:
+ * generic/tkScale.h:
+ * generic/tkScrollbar.h:
+ * generic/tkSelect.h:
+ * generic/tkStubInit.c:
+ * generic/tkStubLib.c:
+ * generic/tkText.h:
+ * generic/tkUndo.h:
+ * macosx/tkMacOSXButton.c:
+ * macosx/tkMacOSXDebug.c:
+ * macosx/tkMacOSXDebug.h:
+ * macosx/tkMacOSXDialog.c:
+ * macosx/tkMacOSXDraw.c:
+ * macosx/tkMacOSXEntry.c:
+ * macosx/tkMacOSXFont.c:
+ * macosx/tkMacOSXInt.h:
+ * macosx/tkMacOSXMenu.c:
+ * macosx/tkMacOSXMenubutton.c:
+ * macosx/tkMacOSXMouseEvent.c:
+ * macosx/tkMacOSXSend.c:
+ * macosx/tkMacOSXSubwindows.c:
+ * macosx/tkMacOSXWindowEvent.c:
+ * macosx/tkMacOSXWm.c:
+ * macosx/tkMacOSXXStubs.c:
+ * unix/tkUnixButton.c:
+ * unix/tkUnixMenu.c:
+ * xlib/xgc.c: ensure externally visible symbols not contained in stubs
+ table are declared as MODULE_SCOPE (or as static if not used outside of
+ own source file), #ifdef out a few Xlib and aqua functions that are
+ never called. These changes allow 'make checkstubs' to complete without
+ error on Darwin with gcc 4.
+
+ * macosx/tkMacOSXTest.c:
+ * macosx/tkMacOSXPort.h:
+ * win/tkWinTest.c:
+ * generic/tkInt.decls: add functions needed by tktest to internal stubs
+ table, correct signature of TkMacOSXHandleMenuSelect, add XSync to aqua
+ Xlib stubs.
+
+ * unix/tkUnixSend.c:
+ * generic/tkText.c:
+ * generic/tkTest.c: #ifdef unix only declarations.
+ (TestmetricsCmd): unify win and mac implementation.
+ (TestsendCmd): move to tkUnixSend.c to avoid access to global var.
+ (TesttextCmd): move to tkText.c to avoid having to put all the internal
+ text functions it uses into the stubs table.
+
+ * generic/tkTextDisp.c:
+ * macosx/tkMacOSXInit.c:
+ * macosx/tkMacOSXKeyEvent.c:
+ * macosx/tkMacOSXWindowEvent.c:
+ * macosx/tkMacOSXXStubs.c: fix gcc 4 warnings.
+
+ * macosx/tkMacOSXNotify.c:
+ * macosx/tkMacOSXScrlbr.c: sync with core-8-4-branch.
+
+ * generic/tkIntDecls.h:
+ * generic/tkIntPlatDecls.h:
+ * generic/tkIntXlibDecls.h:
+ * generic/tkStubInit.c:
+ * unix/configure:
+ * unix/tkConfig.h.in: regen.
+
+2005-11-22 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * library/tkfbox.tcl: Remove all references to data(curItem), as it is
+ no longer used. [Bug 600313]
+ (::tk::IconList_CurSelection): Renamed for clarity.
+
+ * doc/GetFont.3: Revert previous fix; a NULL interp is now legal.
+ * generic/tkFont.c (ParseFontNameObj, GetAttributeInfoObj): Allow these
+ functions to work with a NULL interp by making them check when
+ generating error messages. [Bug 1151523]
+
+ * library/tkfbox.tcl (::tk::dialog::file::): Correct the quoting of the
+ script used in variable traces so that widget names with spaces in will
+ work. [Bug 1335485]
+
+2005-11-16 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * doc/text.n: clarify left to right interpretation of index modifiers,
+ including the fact that validation occurs after each step. [Bug
+ 1357575]
+
+2005-11-15 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/tkUnixWm.c, tests/unixWm.test, doc/wm.n: Support for [wm
+ attributes] on X11. [TIP#231, Patch 1062022]
+
+2005-11-14 Joe English <jenglish@users.sourceforge.net>
+
+ * library/bgerror.tcl: Truncate error messages at 45 characters
+ instead of 30. [Bug 1224235]
+
+2005-11-14 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * generic/tkSelect.c (TkSelDefaultSelection): Test select-9.5
+ highlighted further brokenness in this function.
+
+2005-11-13 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * unix/tkUnixSelect.c (SelCvtToX): Arrange for the parsing code to use
+ Tcl's list parsing code, another simplification that enables testing
+ of the [Bug 1353414] fix.
+
+ * unix/tkUnixSelect.c (SelCvtFromX): Generate string forms of the
+ advanced selection types in a Tcl_DString. This makes fixing [Bug
+ 1353414] trivial, and simplifies the code at the same time.
+ * tests/select.test (select-9.5): Added test for [Bug 1353414]
+
+2005-11-10 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * generic/tkBind.c (ChangeScreen): More DString fixes from
+ * generic/tkTextWind.c (EmbWinLayoutProc): [Bug 1353022]
+ * win/tkWinMenu.c (SetDefaults):
+
+ * win/tkWinDialog.c (ConvertExternalFilename): Factored out the
+ encoding conversion and de-backslash-ing code that is used in many
+ places in this file.
+ (GetFileNameW, GetFileNameA, ChooseDirectoryValidateProc): Make sure
+ that data is freed correctly and that certain (hopefully impossible)
+ failure modes won't cause crashes. [Bug 1353022]
+
+2005-11-06 Pat Thoyts <pat@zsplat.freeserve.co.uk>
+
+ * unix/tcl.m4: Fix SHLIB_LD_LIBS for building tclkit on OpenBSD.
+ * unix/configure: regenerated
+
+2005-10-31 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkText.c
+ * tests/textDisp.test: fix and test for [Bug 1333951] in '.text count
+ -displaylines'.
+
+2005-10-18 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkMain.c: Rewrote code that sets the ::argv value to be sure
+ conversion from the system encoding is complete before any processing
+ sensitive to list-special characters is done. [Bug 1328926]
+
+2005-10-17 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * macosx/tkMacOSXScrlbr.c (UpdateControlValues): check geomMgrPtr is
+ valid before checking type
+
+2005-10-15 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/menu.tcl (::tk::MenuUnpost): remove leftover ] from string
+ equal mods of 2005-07-25. (sowadsky)
+
+2005-10-14 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tkWinSend.c: Avoid using tcl internal headers and fix to
+ * win/tkWinSendCom.h: correctly link on all types of build (was
+ * win/tkWinSendCom.c: broken in static,msvcrt builds).
+
+2005-10-12 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * tests/canvPs.test, tests/canvPsBmap.tcl, tests/canvPsImg.tcl:
+ * tests/imgPhoto.test, tests/menu.test: Arrange for the test suite to
+ only ever refer to images in the same directory as the tests. This
+ makes it possible to package the test suite itself as a starkit. Thanks
+ to David Zolli for suggesting this.
+
+2005-10-10 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkConfig.c (Tk_DeleteOptionTable, Tk_CreateOptionTable):
+ properly alloc/delete one more option. [Bug 1319720] (melbardis)
+
+ * macosx/tkMacOSXInt.h: Move MODULE_SCOPE defn to tkInt.h and add
+ * generic/tkInt.h: WORDS_BIGENDIAN checks that will work with OS X
+ universal binary compiles. (steffen)
+
+ * generic/tkMenu.c (TkSetWindowMenuBar): do not call TkMenuInit if the
+ winPtr indicates TK_ALREADY_DEAD. This prevents reinit that creates a
+ Tk exit handler after all exit handlers should be called. [Bug 749908,
+ 1322294]
+
+2005-10-10 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ TIP #256 IMPLEMENTATION
+
+ * doc/text.n
+ * generic/tkText.c
+ * generic/tkText.h
+ * generic/tkTextBTree.c
+ * generic/tkTextDisp.c
+ * generic/tkTextImage.c
+ * generic/tkTextIndex.c
+ * generic/tkTextMark.c
+ * generic/tkTextTag.c
+ * generic/tkTextWind.c
+ * macosx/tkMacOSXDefault.h
+ * tests/text.test
+ * tests/textDisp.test
+ * unix/tkUnixDefault.h
+ * win/tkWinDefault.h: Implementation of TIP#256, adding a new text
+ widget configuration option '-tabstyle', with new tests and
+ documentation.
+
+ Also a fix for [Bug 1281228] (documentation and full implementation of
+ -strictlimits), and [Bug 1288677] (corrected elide behaviour), again
+ with more tests.
+
+2005-10-04 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/dialog.tcl (::tk_dialog): add tkwait visibility before grab.
+ [Bug 1216775]
+
+ * win/tkWinDialog.c (ChooseDirectoryValidateProc): reset stored path to
+ "" if it doesn't exist and -mustexist is true. [Bug 1309218] Remove
+ old-style dir chooser (no longer used).
+
+ * macosx/tkMacOSXInt.h: add MODULE_SCOPE definition check for extension
+ writers that access private headers on OS X and don't define it in
+ configure.
+
+2005-09-28 Don Porter <dgp@users.sourceforge.net>
+
+ * unix/tkUnixPort.h: Disabled inclusion of the private Tcl header
+ * win/tkWinPort.h: file tclInt.h. Tk ought to have a tiny and
+ shrinking number of calls of private Tcl routines. Each Tk source file
+ doing this should follow the convention in the macosx port and have its
+ own #include "tclInt.h".
+
+ * generic/tkEvent.c: Disabled calls to private Tcl routine
+ TclInExit(). See comment in TkCreateExitHandler() for full rationale.
+
+2005-09-21 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * generic/tkEvent.c (TkCreateThreadExitHandler, TkFinalizeThread)
+ (TkDeleteThreadExitHandler): New internal API (from Joe Mistachkin) to
+ allow Tk to finalize itself correctly in a multi-threaded
+ environment. [Bug 749908]
+
+2005-09-14 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkOldConfig.c (GetCachedSpecs): Split out the code to
+ manipulate the cached writable specs so that it can be reused from all
+ the public Tk_Configure* functions.
+ (Tk_ConfigureInfo, Tk_ConfigureWidget, Tk_ConfigureValue): Use the
+ factored out code everywhere, so we always manipulate the cache
+ correctly. [Bug 1288128]
+
+2005-09-13 Don Porter <dgp@users.sourceforge.net>
+
+ * win/winMain.c (WishPanic): Replaced TCL_VARARGS* macros with direct
+ use of stdarg.h conventions.
+
+2005-09-11 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXMouseEvent.c (TkMacOSXProcessMouseEvent): check if
+ process is in front on MouseDown, otherwise request process activation
+ from BringWindowForward() via new isFrontProcess param.
+
+ * macosx/tkMacOSXCarbonEvents.c (TkMacOSXInitCarbonEvents): register
+ our event handler on the dispatcher target for all carbon events of
+ interest to TkAqua; this replaces event processing directly from the
+ event queue and thus allows to capture events that are syntesized by
+ Carbon and sent directly to the dispatcher and not to the event queue.
+
+ * macosx/tkMacOSXEvent.c: remove TkMacOSXCountAndProcessMacEvents(),
+ rename ReceiveAndProcessEvent() to TkMacOSXReceiveAndProcessEvent().
+ (TkMacOSXReceiveAndProcessEvent): remove tk event processing before
+ sending events to the dispatcher, all events of interest are now
+ processed in our dispatcher target event handler.
+
+ * macosx/tkMacOSXNotify.c (CarbonEventsCheckProc): dispatch events
+ directly via TkMacOSXReceiveAndProcessEvent(), but dispatch no more
+ than four carbon events at one time to avoid starving other event
+ sources.
+
+ * macosx/tkMacOSXEvent.c: formatting cleanup, move XSync() to XStubs,
+ * macosx/tkMacOSXEvent.h: removed obsolete kEventClassWish handling.
+ * macosx/tkMacOSXXStubs.c
+
+ * macosx/tkMacOSXEvent.h: declare macosx internal procs as MODULE_SCOPE
+ * macosx/tkMacOSXEvent.c:
+ * macosx/tkMacOSXKeyEvent.c:
+ * macosx/tkMacOSXMouseEvent.c:
+ * macosx/tkMacOSXWindowEvent.c:
+
+ * macosx/tkMacOSXButton.c: conditionalize all debug message printing to
+ * macosx/tkMacOSXCursor.c: stderr via TK_MAC_DEBUG define.
+ * macosx/tkMacOSXDebug.c:
+ * macosx/tkMacOSXDebug.h:
+ * macosx/tkMacOSXDialog.c:
+ * macosx/tkMacOSXEvent.c:
+ * macosx/tkMacOSXInit.c:
+ * macosx/tkMacOSXKeyEvent.c:
+ * macosx/tkMacOSXMenu.c:
+ * macosx/tkMacOSXMenubutton.c:
+ * macosx/tkMacOSXScale.c:
+ * macosx/tkMacOSXWindowEvent.c:
+ * macosx/tkMacOSXWm.c:
+
+ * unix/configure.in: define TK_MAC_DEBUG on aqua when symbols enabled.
+ * unix/configure: autoconf-2.59
+ * unix/tkConfig.h.in: autoheader-2.59
+
+ * library/listbox.tcl: synced aqua MouseWheel bindings with
+ * library/scrlbar.tcl: core-8-4-branch.
+ * library/text.tcl:
+
+ * xlib/xcolors.c: fixed warning
+
+2005-08-25 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/Makefile.in (html): reverted/amended changes of 2005-08-23 that
+ broke TkAqua 'make install'; added BUILD_HTML_FLAGS optional var like
+ in tcl/unix/Makefile.in.
+
+2005-08-24 Donal K. Fellows <dkf@users.sf.net>
+
+ * tests/text.test (text-8.18): Fix punctuation of error message to
+ match good practice (actual message already fixed). [Bug 1267484]
+
+2005-08-23 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * macosx/tkMacOSXDialog.c: make dialogs ignore -initialfile "" and
+ -initialdir "" instead of error.
+
+2005-08-23 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/tkWin32Dll.c (DllMain): Replace old asm SEH approach with Kenny's
+ new SEH implementation. [Tcl Bug 1235544]
+
+2005-08-23 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/Makefile.in: Subst BUILD_TCLSH and TCL_EXE.
+ * unix/configure: Regen.
+ * unix/configure.in: Update minimum autoconf version to 2.59. Invoke
+ SC_PROG_TCLSH and SC_BUILD_TCLSH.
+ * unix/tcl.m4 (SC_PROG_TCLSH, SC_BUILD_TCLSH):
+ * win/Makefile.in: Subst BUILD_TCLSH and TCL_EXE.
+ * win/configure: Regen.
+ * win/configure.in: Update minimum autoconf version to 2.59. Invoke
+ SC_BUILD_TCLSH.
+ * win/tcl.m4 (SC_PROG_TCLSH, SC_BUILD_TCLSH): Split confused search
+ for tclsh on PATH and build and install locations into two macros.
+ SC_PROG_TCLSH searches just the PATH. SC_BUILD_TCLSH determines the
+ name of the tclsh executable in the Tcl build directory. [Tcl Bug
+ 1160114] [Tcl Patch 1244153]
+
+2005-08-22 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXButton.c:
+ * macosx/tkMacOSXDialog.c: fix warnings.
+
+2005-08-20 Joe Mistachkin <joe@mistachkin.com>
+
+ * win/tkWinX.c: Fixed bad cast. [Bug 1216006]
+
+2005-08-18 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * doc/GetFont.3: Reworded to reflect the truth. [Bug 1151523]
+
+2005-08-16 George Peter Staplin <GeorgePS@XMission.com>
+
+ * doc/CrtItemType.3 prototypes were lacking [] after objv. Thus the man
+ page was wrong about the actual prototypes. This was verified by
+ studying tkCanvBmap.c.
+
+2005-08-13 Chengye Mao <chengye.geo@yahoo.com>
+
+ * generic/tkOldConfig.c: Fixed [Bug 1258604]. This bug was introduced
+ into the modfied Tk_ConfigureWidget. It failed to properly handle the
+ specFlags' bit TK_CONFIG_OPTION_SPECIFIED.
+
+2005-08-12 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * generic/tkOldConfig.c (Tk_ConfigureWidget): Stop storing per-thread
+ data in global data structures. Store it in per-interpreter data (i.e.
+ per-thread data) instead. [Bug 749908]
+
+2005-08-10 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkFrame.c (CreateFrame) and others: Don't use size_t when
+ working with Tcl_GetStringFromObj because it is not 64-bit clean. [Bug
+ 1252702]
+
+2005-08-04 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * doc/text.n: Clarify behaviour of tab stops (as per [Bug 1247835])
+
+2005-08-09 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXCarbonEvents.c (AppEventHandlerProc): handle carbon
+ events sent directly to application event target via the general
+ TkMacOSXProcessEvent() in the same way as events posted to the event
+ loop. Moved existing app event handlers to tkMacOSXWindowEvent.c.
+ (TkMacOSXInitCarbonEvents): register our application event handler for
+ kEventWindowExpanded events to deal with uncollapsing from the dock.
+
+ * macosx/tkMacOSXEvent.h: made TkMacOSXProcessEvent() non-static, added
+ * macosx/tkMacOSXEvent.c: new interp field to TkMacOSXEvent struct for
+ use by app event handler.
+
+ * macosx/tkMacOSXMouseEvent.c (TkMacOSXProcessMouseEvent): retrieve
+ current window, partCode, modifiers and local cursor position from
+ carbon mouse event if possible. Use new static GenerateButtonEvent()
+ taking a MouseEventData struct instead of TkGenerateButtonEvent() to
+ avoid recomputing already known values. Move process activation on
+ MouseDown into BringWindowForward() to allow clicking on window
+ titlebar widgets without activating process. Move code dealing with
+ clicks in window titelbar into separate function
+ HandleWindowTitlebarMouseDown() to avoid code duplication. Avoid
+ repeated calls to TkMacOSXGetXWindow() by storing result in
+ MouseEventData struct.
+ (TkMacOSXButtonKeyState, XQueryPointer): try to get button and modifier
+ state from currently processed carbon event (to avoid unnecessary IPC
+ with the window server), otherwise use modern carbon API to get this
+ info instead of Button() and GetKeys(); only retrieve info caller asks
+ for (via non-NULL ptr passed to XQueryPointer).
+ (ButtonModifiers2State): new static function converting carbon button
+ and modifier state into tk state, allows detection of more than 3 mouse
+ buttons (tk supports up to 5) and of NumLock and Fn modifier keys
+ (NumLock is mapped to Mod3 and Fn to Mod4).
+
+ * macosx/tkMacOSXWindowEvent.c (TkMacOSXProcessApplicationEvent):
+ handle kEventWindowExpanded event to deal with window uncollapsing from
+ the dock by generating tk Map event, handle kEventAppHidden and
+ kEventAppShown events (moved here from tkMacOSXCarbonEvents.c).
+
+ * macosx/tkMacOSXSubwindows.c (XUnmapWindow): only hide window when it
+ is not iconified to avoid window flashing on collapse.
+
+ * macosx/tkMacOSXWm.c: replaced Tk_DoWhenIdle() by Tcl_DoWhenIdle().
+ (TkMacOSXZoomToplevel): remove call to TrackBox(), now done in
+ HandleWindowTitlebarMouseDown() in tkMacOSXMouseEvent.c.
+ (TkpWmSetState): avoid window flashing on collapse by unmapping after
+ calling CollapseWindow(); only uncollapse window if it is collapsed.
+
+ * generic/tkInt.decls: changed TkMacOSXZoomToplevel() signature.
+ * generic/tkIntPlatDecls.h:
+
+ * macosx/tkMacOSXKeyEvent.c (TkMacOSXProcessKeyboardEvent): only call
+ GetMenuItemCommandID() on KeyDown or KeyRepeat events.
+
+ * macosx/tkMacOSXMenu.c (ReconfigureMacintoshMenu): remove call to
+ obsolete AppendResMenu() API.
+
+ * macosx/tkMacOSXKeyEvent.c: replaced all direct uses of expensive
+ * macosx/tkMacOSXMenu.c: GetMouse() and TkMacOSXButtonKeyState()
+ * macosx/tkMacOSXMenus.c: APIs by calls to XQueryPointer()
+ * macosx/tkMacOSXMouseEvent.c:
+ * macosx/tkMacOSXScale.c:
+ * macosx/tkMacOSXScrlbr.c:
+ * macosx/tkMacOSXWm.c:
+
+ * macosx/tkMacOSXDialog.c: replaced use of FrontNonFloatingWindow()
+ * macosx/tkMacOSXKeyEvent.c: by ActiveNonFloatingWindow() as
+ * macosx/tkMacOSXMenu.c: recommended by Carbon docs.
+ * macosx/tkMacOSXMenus.c:
+ * macosx/tkMacOSXSubwindows.c:
+ * macosx/tkMacOSXWm.c:
+
+ * macosx/tkMacOSXDialog.c: fixed warnings
+ * macosx/tkMacOSXTest.c:
+
+ * macosx/tkMacOSXCarbonEvents.c: added CVS Id line to file header.
+ * macosx/tkMacOSXDebug.c:
+ * macosx/tkMacOSXDebug.h:
+ * macosx/tkMacOSXEntry.c:
+ * macosx/tkMacOSXEvent.h:
+ * macosx/tkMacOSXKeyEvent.c:
+ * macosx/tkMacOSXMouseEvent.c:
+ * macosx/tkMacOSXWindowEvent.c:
+ * macosx/tkMacOSXWm.h:
+
+ * macosx/tkMacOSXInt.h: declare macosx internal procs as MODULE_SCOPE.
+ * macosx/tkMacOSXCarbonEvents.c:
+ * macosx/tkMacOSXDraw.c:
+ * macosx/tkMacOSXFont.c:
+ * macosx/tkMacOSXHLEvents.c:
+ * macosx/tkMacOSXInit.c:
+ * macosx/tkMacOSXWindowEvent.c
+
+ * library/bgerror.tcl: sync with core-8-4-branch changes of 2005-07-28.
+ * macosx/tkMacOSXDraw.c:
+ * macosx/tkMacOSXWm.c:
+ * macosx/tkMacOSXMouseEvent.c:
+
+ * generic/tkFrame.c: sync with core-8-4-branch changes of 2005-07-27.
+ * generic/tkIntDecls.h:
+ * generic/tkStubInit.c:
+ * generic/tkFrame.c:
+ * win/tkWinDraw.c:
+ * unix/tkUnixDraw.c:
+ * macosx/tkMacOSXDraw.c:
+ * macosx/tkMacOSXInt.h:
+ * macosx/tkMacOSXWm.c:
+ * macosx/tkMacOSXSubwindows.c:
+
+ * macosx/tkMacOSXButton.c: sync with core-8-4-branch.
+ * macosx/tkMacOSXEntry.c:
+ * macosx/tkMacOSXScale.c:
+
+ * library/demos/menu.tcl: removed errant '}'.
+
+2005-08-04 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * doc/clipboard.n: Add example demonstrating custom types of clipboard
+ data.
+
+2005-07-25 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * library/*.tcl: Updated to use more 8.4 and 8.5 features as part of
+ resolving [Patch 1237759].
+
+2005-07-22 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/tkWinX.c: Define _WIN32_WINNT with NT SP 3 data to fix compiler
+ error because SendInput was not defined. The new msys_mingw7 release is
+ now needed to compile the HEAD with mingw gcc. [Bug 1210712]
+
+2005-07-21 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * macosx/tkMacOSXMouseEvent.c (TkMacOSXProcessMouseEvent): corrected if
+ expression error (use of = instead of ==).
+
+2005-07-18 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkTextMark.c: fix to segfault in "mark prev"
+ * tests/textIndex.test: [Bug 1240221]
+
+ * tests/textWind.test: make test more robust to avoid infinite loop
+
+2005-07-06 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * doc/getOpenFile.n: correct -multiple docs (takes boolean)
+
+2005-07-05 Don Porter <dgp@users.sourceforge.net>
+
+ * unix/Makefile.in: Purged use of TCLTESTARGS. [RFE 1161550]
+
+2005-06-23 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tkConsole.c (TkConsolePrint): prevent potential NULL deref.
+
+ * macosx/tkMacOSXDefault.h: change ENTRY_BORDER defaults to from 5 to 2
+ to make default entry widgets in TkAqua look like in other aqua apps
+ (and have same border dimensions as other platforms). [Bug 1176610]
+
+2005-06-21 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/GetBitmap.3: Fix silly error in SYNOPSIS. [Bug 1224983]
+
+2005-06-19 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkImgGIF.c: Cleanse all static (i.e. non-thread-safe) data
+ at a miniscule performance hit.
+
+2005-06-18 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Makefile: for X11 build, add -X11 suffix to unversioned wish
+ symbolic link.
+
+ * unix/tcl.m4 (Darwin): add -headerpad_max_install_names to LDFLAGS to
+ ensure we can always relocate binaries with install_name_tool.
+
+ * unix/configure: autoconf-2.59
+
+2005-06-07 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ Bump patchlevel to a4 to distinguish from a3 release.
+
+2005-06-04 Jeff Hobbs <jeffh@ActiveState.com>
+
+ *** 8.5a3 TAGGED FOR RELEASE ***
+
+2005-06-02 Jim Ingham <jingham@apple.com>
+
+ * generic/tkEvent.c (InvokeFocusHandlers): On Mac OS X the scrollwheel
+ events are sent to the window under the mouse, not to the focus window
+
+ Another patch from M. Kirkham.
+
+ * macosx/tkMacOSXScrlbr.c (ThumbActionProc, ScrollBarBindProc): Record
+ the first mouse down point, and compute differences from that, rather
+ than getting the mouse down each time through the loop. The old method
+ would get fooled if you moved the mouse less than a text line height in
+ the text widget. [Bug 1083728]
+
+2005-06-03 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Makefile: fixed 'embedded' target.
+
+2005-06-02 Reinhard Max <max@suse.de>
+
+ * unix/tkUnix.c (Tk_GetUserInactiveTime): Improvements to get it
+ working on Solaris, and panic if we run out of memory.
+ * unix/configure.in: Rework the searching for Xss, to make it work on
+ Solaris and provide more useful output. Use AC_HELP_STRING where
+ appropriate.
+ * unix/tcl.m4: synced from Tcl.
+ * unix/configure: regenerated with autoconf 2.59.
+
+2005-06-01 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinInt.h: added private decls of Tk_GetEmbeddedMenuHWND,
+ Tk_GetMenuHWND, TkWinCleanupContainerList, and TkpWmGetState to that
+ are used across source files.
+
+ * win/tkWinX.c (Tk_ResetUserInactiveTime): cast to squelch compiler
+ warning.
+
+2005-05-31 Reinhard Max <max@suse.de>
+
+ * doc/Inactive.3 (new file): C level API documentationn for
+ TIP#245 (Tk_GetUserInactiveTime, Tk_ResetUserInactiveTime).
+ * tests/tk.test: Added tests for the TIP#245 implementation.
+
+2005-05-30 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkPanedWindow.c, tests/panedwindow.test: batch of fixes to
+ panedwindow from Daniel South. Improved auto-size to fit internal
+ windows, fixed sash placement at edge of pane, fixed calculation of
+ stretch amount for internal windows. [Bug 1124198, 1161543, 1054117,
+ 1010941, 795869, 690169, 1192323]
+
+ * generic/tkMenu.c (MenuCmd): create event handler earlier to ensure
+ proper destruction of menu through DestroyNotify. [Bug 1159367]
+
+ * library/console.tcl (::tk::ConsoleInit): print out first prompt and
+ swallow the extra "% " that comes once from Tcl on Windows.
+
+2005-05-29 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXFont.c: use Tcl_Panic instead of panic.
+
+ * unix/configure.in: added description of HAVE_XSS for autoheader.
+ * unix/configure: autoconf-2.59
+ * unix/tkConfig.h.in: autoheader-2.59
+
+ * macosx/Wish.pbproj/project.pbxproj:
+ * macosx/Wish.xcode/project.pbxproj: added missing FRAMEWORK defines
+ introduced with configure/make based build.
+
+ * macosx/tkMacOSXInit.c:
+ * macosx/tkMacOSXNotify.c: fixed warnings.
+
+ * generic/tkDecls.h:
+ * generic/tkIntPlatDecls.h:
+ * generic/tkPlatDecls.h:
+ * generic/tkStubInit.c: ran missing 'make genstubs' for TIP245 changes
+ to tk.decls
+
+ * macosx/tkMacOSXXStubs.c (Tk_ResetUserInactiveTime): use symbolic
+ constant argument in call to UpdateSystemActivity();
+
+ * macosx/Wish.pbproj/project.pbxproj:
+ * macosx/Wish.xcode/project.pbxproj:
+ * unix/configure.in: added/corrected linking to IOKit.framework for
+ TIP245.
+
+ * unix/configure.in: skip X11 configure checks when building tk_aqua.
+ * unix/configure: autoconf-2.59
+
+2005-05-28 Donal K. Fellows <dkf@users.sf.net>
+
+ TIP #245 IMPLEMENTATION from Reinhard Max <max@suse.de>
+
+ * doc/tk.n: Documentation of [tk inactivity].
+ * win/tkWinX.c (Tk_GetUserInactiveTime, Tk_ResetUserInactiveTime):
+ * unix/tkUnix.c (Tk_GetUserInactiveTime, Tk_ResetUserInactiveTime):
+ * macosx/tkMacOSXXStubs.c: Implementations of the core API for
+ (Tk_GetUserInactiveTime): determining how long as user's left
+ (Tk_ResetUserInactiveTime): her machine alone.
+ * unix/configure.in: Test for XScreenSaver support.
+ * generic/tkCmds.c (Tk_TkObjCmd): Implementation of [tk inactivity].
+
+2005-05-27 Todd Helfter <tmh@users.sourceforge.net>
+
+ * library/menu.tcl: correct the sticky behavior of menus posted by
+ tk_popup so that they "stick" after the initial <ButtonRelease>
+ following the post, that is not over an active menu entry.
+
+2005-05-26 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXInit.c (TkpInit): fixed resource file extraction from
+ __tk_rsrc section to work with non-prebound .dylib and .bundle.
+
+ * macosx/Makefile: corrected EMBEDDED_BUILD check, use separate Tcl and
+ Tk version vars to properly support tk/x11 framework version
+ overriding, rewrite tkConfig.sh when overriding tk version, corrected
+ Wish.app symlink in tk build dir.
+
+ * unix/configure.in: corrected framework finalization to softlink stub
+ library to Versions/8.x subdir instead of Versions/Current.
+ * unix/configure: autoconf-2.59
+
+2005-05-25 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/Makefile.in (install-libraries): protect possible empty list in
+ for with list= trick for older shells.
+
+2005-05-23 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkFileFilter.c (FreeGlobPatterns): s/null/NULL/
+
+2005-05-24 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tkTest.c: disable commands not available on TkAqua.
+
+ * macosx/Makefile:
+ * macosx/README:
+ * macosx/Tk-Info.plist.in (new file):
+ * macosx/Wish-Info.plist.in (new file):
+ * unix/Makefile.in:
+ * unix/configure.in:
+ * unix/tcl.m4:
+ * unix/tkUnixInit.c: moved all Darwin framework and TkAqua build
+ support from macosx/Wish.pbproj and macosx/Makefile into the standard
+ unix configure/make buildsystem, the project and macosx/Makefile are no
+ longer required to build Tk.framework and/or TkAqua. TkAqua is now
+ enabled by the --enable-aqua configure option, and static and
+ non-framework builds of TkAqua are now available via the standard
+ configure switches. Tk/X11 can also be built as a framework. The
+ macosx/Makefile now wraps the unix buildsystem and no longer uses the
+ projects, embedded builds are still only available via this Makefile,
+ but for other builds it is not longer required (but its current
+ functionality is still available for backwards compatibility). The
+ projects currently do not call through to the Makefile to build (unlike
+ Tcl.pbproj) so project builds may differ from makefile builds. Due to
+ issues with spaces in pathnames, 'Wish Shell.app' has been renamed to
+ 'Wish.app', the macosx/Makefile installs backwards compatibility
+ symlinks for the old name.
+ * macosx/tkMacOSXInit.c (TkpInit): added support for Tk resource file
+ in non-framework and static builds: the resource file is copied into a
+ __tk_rsrc MachO section of the library or executable at link time and
+ extracted into a temporary location at initialization.
+ * unix/configure: autoconf-2.59
+ * unix/tkConfig.h.in (new file): autoheader-2.59
+
+ * macosx/Wish.pbproj/project.pbxproj:
+ * macosx/Tk-Info.plist:
+ * macosx/Wish-Info.plist:
+ * macosx/tkAboutDlg.r: updated copyright years to 2005.
+
+2005-05-22 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkFileFilter.c (TkGetFileFilters): Add all filters, not just
+ the first one. [Bug 1206133]
+
+2005-05-15 Jim Ingham <jingham@apple.com>
+
+ Fixes from Michael Kirkham:
+
+ * macosx/tkMacOSXMenu.c (TkpConfigureMenuEntry): Thinko in clearing the
+ ENTRY_ACCEL_MASK before re-parsing it. [Bug 1012852]
+
+ * macosx/tkMacOSXScrlbr.c (UpdateControlValues): Don't set the control
+ value BEFORE setting the min and max or the control manager will reset
+ it for you. [Bug 1202181]
+
+ * macosx/tkMacOSXXStubs.c (TkMacOSXXGetPixel, TkMacOSXXPutPixel):
+ Restore the port to what it was before putting we were called. [Bug
+ 1202223]
+
+2005-05-14 Jim Ingham <jingham@apple.com>
+
+ * macosx/tkMacOSXScrlbr.c (ThumbActionProc): Missing Tcl_Release.
+
+2005-05-14 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXInit.c:
+ * macosx/tkMacOSXNotify.c: introduction of new tcl notifier based on
+ CFRunLoop allows replacement of the custom TkAqua notifier by a
+ standard tcl event source. Removes requirement of threaded tcl core
+ for TkAqua, allows to stub-link TkAqua against Tcl by removing use of
+ the unstubbed TclInitNotifier & TclFinalizeNotifier. [Tcl Patch
+ 1202052]
+
+ * macosx/Wish.xcode/project.pbxproj:
+ * macosx/Wish.pbproj/project.pbxproj: stub-link TkAqua: build with
+ USE_TCL_STUBS and link against libtclstub instead of Tcl.framework,
+ unexport libtclstub symbols from Tk to avoid duplicate symbol warnings
+ when linking with both Tcl and Tk, fixes for gcc4.0 warnings.
+
+ * macosx/Wish.xcode/project.pbxproj: sync with Wish.pbproj changes
+ since 2004-11-19.
+ NOTE: to use this project, need to uncomment the tclConfig.h settings
+ at the top of tcl/unix/configure.in, autoconf and rebuild tcl !
+
+ * macosx/tkMacOSXBitmap.c:
+ * macosx/tkMacOSXButton.c:
+ * macosx/tkMacOSXDialog.c:
+ * macosx/tkMacOSXFont.c:
+ * macosx/tkMacOSXHLEvents.c:
+ * macosx/tkMacOSXInit.c:
+ * macosx/tkMacOSXKeyboard.c:
+ * macosx/tkMacOSXMenu.c:
+ * macosx/tkMacOSXMenubutton.c:
+ * macosx/tkMacOSXWm.c:
+ * macosx/tkMacOSXXStubs.c: fixed gcc 4.0 warnings.
+
+ * unix/tcl.m4: sync with tcl
+ * unix/configure: autoconf-2.59
+
+2005-05-10 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * library/text.tcl: test and fix to TextPrevPara to avoid infinite loop
+ * tests/textIndex.test: at start of widget. [Bug 1191895]
+
+ * generic/tkTextDisp.c: better synchronisation between explicit and
+ implicit pixel line-height calculations. [Bug 1186558]
+
+2005-05-10 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkTextDisp.c (GetXView): Improved numerical precision of
+ calculation of [.t xview] return values.
+ * tests/textDisp.test: Match greater precisions of [.t xview] and
+ [.t yview] values in tests.
+
+2005-05-06 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/configure: regen
+ * unix/configure.in: Add AC_C_BIGENDIAN check and pkg-config xft checks
+ to extend xft search.
+ * unix/tcl.m4: Correct Solaris 10 (5.10) check and add support for
+ x86_64 Solaris cc builds.
+
+2005-04-28 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * macosx/tkMacOSXNotify.c (TkMacOSXWaitForEvent): Fix for typo in
+ waitTime computation. [Bug 1191097]
+ (AlertNotifier): Factor out the core of the notifier alerting code.
+
+2005-04-25 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXNotify.c: sync with tclUnixNotfy.c changes since
+ 2004-06-22, added compile time check for threaded tcl core, removed
+ unthreaded code paths as they are never used anyway, fixed
+ TkMacOSXAlertNotifier() implementation.
+
+ * unix/Makefile.in: added TCL_STUB_LIB_FILE, needed for unexporting of
+ symbols from libtclstub to avoid duplicate symbol warnings.
+
+ * unix/tcl.m4 (Darwin): added configure checks for recently added
+ linker flags -single_module and -search_paths_first to allow building
+ with older tools (and on Mac OS X 10.1), use -single_module in SHLIB_LD
+ and not just T{CL,K}_SHLIB_LD_EXTRAS, added unexporting from Tk of
+ symbols from libtclstub to avoid duplicate symbol warnings, added
+ PLAT_SRCS definition for Mac OS X, defined MODULE_SCOPE to
+ __private_extern__.
+ (SC_MISSING_POSIX_HEADERS): added caching of dirent.h check.
+
+ * unix/configure: autoconf-2.59
+
+2005-04-22 George Peter Staplin <GeorgePS@XMission.com>
+
+ * doc/FontId.3: I fixed a typo. "linespace" was used instead of
+ "ascent". I also added a .PP before the paragraph to make the
+ formatting look better for the ascent paragraph.
+
+2003-04-18 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/tkUnixRFont.c(Tk_MeasureChars): Use Tcl_UtfToUnichar() for lax
+ UTF-8 parsing instead of strict parsing with FcUtf8ToUcs4()
+ [fix/workaround for Bug 1185640]
+
+2003-04-18 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * library/text.tcl
+ * doc/text.n: corrected 'Home' and 'End' and Control-a/e handling to
+ work with display lines. This was an ommission of the previous tip155
+ patch. Clarified the documentation on this point.
+
+2005-04-14 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/tkUnixFont.c (FontMapLoadPage): reorder char[] decls to avoid
+ possible segv. Minimal fix for [Bug 1122671]
+
+2005-04-12 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/tkfbox.tcl (::tk::dialog::file::): fix typeMenuLab ref. Add
+ undoc'd ::tk::dialog::file::showHiddenBtn var (default 0) that will add
+ a "Show Hidden" checkbutton to tk_get*File and tk_chooseDirectory if
+ set to true.
+ * library/choosedir.tcl (::tk::dialog::file::chooseDir::): fix
+ cancelBtn ref, add hiddenBtn ref for "Show Hidden" button.
+
+2005-04-09 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/README: updated requirements for OS & developer tool versions
+ + other small fixes/cleanup.
+
+ * macosx/tkMacOSXEntry.c (ComputeIncDecParameters): manually define
+ constants present only in 10.3 headers so that we can build on 10.2.
+
+ * macosx/Wish.pbproj/project.pbxproj: fixed absolute path to tkEntry.h
+ that confused 10.2 PBX.
+
+ * unix/tcl.m4 (Darwin): added -single_module linker flag to
+ TCL_SHLIB_LD_EXTRAS and TK_SHLIB_LD_EXTRAS.
+ * unix/configure: autoconf-2.59
+
+2005-04-07 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * macosx/tkMacOSXWm.c (TkWmStackorderToplevelWrapperMap,
+ (TkWmStackorderToplevel):
+ * unix/tkUnixWm.c (TkWmStackorderToplevelWrapperMap,
+ (TkWmStackorderToplevel):
+ * win/tkWinWm.c (TkWmStackorderToplevelWrapperMap,
+ (TkWmStackorderToplevel):
+ Fix panic in wm stackorder when a toplevel is created on another
+ display. The code now ignores toplevels that have a display that does
+ not match the display of the parent window. [Bug 1152809]
+
+2005-04-06 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/wm.n, doc/winfo.n, doc/tk.n, doc/send.n, doc/selection.n:
+ * doc/radiobutton.n, doc/photo.n, doc/options.n, doc/menu.n:
+ * doc/listbox.n, doc/getOpenFile.n, doc/font.n, doc/event.n:
+ * doc/entry.n, doc/clipboard.n, doc/checkbutton.n, doc/canvas.n:
+ * doc/button.n, doc/bind.n, doc/TextLayout.3, doc/MeasureChar.3:
+ * doc/GetRelief.3, doc/GetPixels.3, doc/GetJustify.3, doc/GetFont.3:
+ * doc/GetCursor.3, doc/GetColor.3, doc/GetBitmap.3, doc/GetAnchor.3:
+ * doc/FontId.3, doc/CrtWindow.3, doc/CrtImgType.3, doc/ConfigWidg.3:
+ * doc/3DBorder.3: Purge old .VS/.VE macro instances.
+
+2005-04-04 Don Porter <dgp@users.sourceforge.net>
+
+ * library/comdlg.tcl: Added Macintosh file type validation to
+ [::tk::FDGetFileTypes]. [Bug 1083878] (Thanks, Vince Darley)
+
+2005-04-04 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkText.c:
+ * tests/text.test: fix to elide searching problems [Bug 1174269] and
+ disappearing cursor with insertofftime 0. [Bug 1169429]
+
+2005-04-03 Peter Spjuth <peter.spjuth@space.se>
+
+ * tests/grid.test:
+ * generic/tkGrid.c: Fixed bug in geometry calculations for widgets that
+ span multiple columns/row. Bug was introduced in 8.5a1 when fixing
+ 792387. [Bug 1175092]
+
+2005-03-29 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tcl.m4, win/configure: do not require cygpath in macros to allow
+ msys alone as an alternative.
+
+2005-03-27 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * tests/textDisp.test: added test for fix of 2005-03-15.
+
+2005-03-24 Jim Ingham <jingham@apple.com>
+
+ * macosx/tkMacOSXEntry.c (TkpDrawEntryBorderAndFocus): Dopey bug - do
+ not reset the width for entry widgets - we didn't change it for them.
+
+2005-03-23 Jim Ingham <jingham@apple.com>
+
+ These changes allow us to draw the Entry and Spinbox widget with a
+ native look and feel on Mac OS X.
+
+ * generic/tkEntry.h: New file, extracting the definitions of Entry and
+ Spinbox.
+ * generic/tkEntry.c (DisplayEntry): Call out to TkpDrawSpinboxButtons
+ and TkpDrawEntryBorderAndFocus. Also provide default implementations
+ for X11 & Win.
+ * macosx/tkMacOSXEntry.c: New file, implements the entry & focus and
+ spinbox button drawing.
+ * tkMacOSXDefaults.h: Change the Mac OS X defaults so they fit the
+ native widget shapes.
+
+ This is cleanup thanks to Neil Madden <nem@cs.nott.ac.uk>.
+
+ * macosx/tkMacOSXWm.c (TkMacOSXWinStyle) New function.
+ (TkUnsupported1ObjCmd): New function, replaces the un-objectified
+ version of the command.
+ * generic/tkInt.h: Swap TkUnsupported1Cmd for TkUnsupported1ObjCmd.
+ * generic/tkWindow.c (): Ditto.
+
+ This adds a "-notify" flag to "wm attributes" that will bounce the
+ dock icon on Mac OS X. This is from Revar Desmera <revarbat@gmail.com>
+
+ * macosx/tkMacOSXWm.c (WmAttrGetNotifyStatus, WmAttrSetNotifyStatus):
+ New functions.
+ (WmAttributesCmd): Add the -notify.
+ * doc/wm.n: Document -notify.
+
+2005-03-19 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkConsole.c (Tk_CreateConsoleWindow,TkConsolePrint): Rewrite
+ so that TkConsolePrint cannot become detached from the console when the
+ [console] command is renamed. [Bug 1016385]
+
+2005-03-15 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkTextDisp.c: fix for [Bug 1143776] in adjusting displayed
+ lines when running into the bottom of the window.
+
+2005-03-14 Jim Ingham <jingham@apple.com>
+
+ * macosx/tkMacOSXScrlbr.c (ThumbActionProc): No need to use "update
+ idletasks" here, TclServiceIdle will do as well and it is simpler.
+
+ These changes implement a change on the Mac OS X side. When we unmap a
+ window we mark all its children as unmapped (not following toplevels.
+ But we preserve whether they had been mapped before, and when the
+ parent is remapped, we remap the children as well. [Bug 940117]
+
+ * macosx/tkMacOSXInt.h: Added TK_MAPPED_IN_PARENT
+ * macosx/tkMacOSXSubwindows.c (FixMappingFlags): New function.
+ (XMapWindow): Call FixMappingFlags.
+ (XUnMapWindow): Ditto.
+
+ * macosx/tkMacOSXSubwindows.c (XMoveResizeWindow): Update the xOff &
+ yOff data in the Macdrawable even if the native window hasn't been
+ created yet. [Bug 700305]
+ (XMoveWindow): Ditto.
+ (XResizeWindow): Ditto.
+
+2005-03-15 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * unix/tcl.m4: Updated the OpenBSD configuration and regenerated the
+ * unix/configure: configure script.
+
+2005-03-14 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * generic/tkEvent.c (InvokeClientMessageHandlers): Ensure that client
+ messages are handled correctly. Thanks to George Petasis for tracking
+ this down. [Bug 1162356]
+
+2005-03-11 Jim Ingham <jingham@apple.com>
+
+ * macosx/tkMacOSXButton.c (TkpDisplayButton): Set the port to the
+ Button window's port BEFORE you set the clip, otherwise you are setting
+ the clip on the wrong window!
+ Also, a little cleanup - move x & y into the branches where they are
+ used, and don't compute the TextAnchor if we are using the native
+ button text, since we aren't going to use it.
+ (TkMacOSXDrawControl): Call ShowControl & SetControlVisibility in a
+ more logical order.
+
+ * tkMacOSXInt.h: Add TkMacOSXGenerateFocusEvent.
+ * tkMacOSXSubwindows.c (XDestroyWindow): We don't get Activate events
+ for the remaining windows when a Floating window is destroyed. This can
+ cause the focus to disappear. So catch this case when the window is
+ being destroyed and move the focus here.
+
+ * tkMacOSXWindowEvent.c (TkMacOSXGenerateFocusEvent): Make this public
+ (used to be GenerateFocusEvent) since we need it here and in
+ tkMacOSXSubwindows.c. Then change the name everywhere it is used. [Bug
+ 1124237]
+
+2005-03-10 Jim Ingham <jingham@apple.com>
+
+ * macosx/tkMacOSXMouseEvent.c (TkMacOSXProcessMouseEvent): In the
+ inDrag section, set the GrafPort to the drag window's GrafPort before
+ doing LocalToGlobal. [Bug 1160025]
+
+2005-03-09 Jim Ingham <jingham@apple.com>
+
+ * macosx/tkMacOSXInit.c (TkpInit): Check to see if the environment
+ variable XCNOSTDIN is set, and if so, close stdin & stdout. This is
+ necessary to make remote debugging under Xcode work properly.
+
+2005-03-08 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinWm.c (WinSetIcon): fix GCLP_ICONSM -> GCLP_HICONSM.
+
+ * win/makefile.vc: clarify necessary defined vars that can come from
+ MSVC or the Platform SDK.
+
+2005-02-28 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinX.c (GenerateXEvent): correct %A translation on MouseWheel.
+ [Bug 1118340]
+
+2005-02-24 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSX.h: fixed incorrect inclusion of internal header.
+ * macosx/tkMacOSXNotify.c: corrected included headers.
+
+2005-02-22 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXDialog.c (Tk_GetSaveFileObjCmd, NavServicesGetFile):
+ fixed encoding problems with -initialfile & -filetypes and corrected
+ potential buffer overrun with -initialdir/-initialfile. [Bug 1146057]
+
+2005-02-16 Mo DeJong <mdejong@users.sourceforge.net>
+
+ TIP#223 IMPLEMENTATION
+
+ * doc/wm.n: Add documentation for -fullscreen attribute.
+ * tests/winWm.test: Add -fullscreen to wm attribute usage message.
+ * tests/wm.test: Add -fullscreen to wm attribute usage message. Add
+ -fullscreen attribute test cases for Windows.
+ * win/tkWinWm.c (WmInfo, UpdateWrapper, TkpWmSetFullScreen)
+ (WmAttributesCmd, UpdateGeometryInfo):
+ Implement TIP 223 [wm attributes -fullscreen].
+
+2005-02-14 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkText.c:
+ * generic/tkText.h:
+ * generic/tkTextDisp.c:
+ * generic/tkTextIndex.c:
+ * generic/tkTextBTree.c:
+ * doc/text.n:
+ * tests/textDisp.test:
+ * tests/textIndex.test: fix of longstanding elide problem when eliding
+ a newline without eliding the entire logical line. [Bug 443848]
+
+2005-02-14 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * doc/options.n: note -cursor {} behavior. [Bug 965618]
+
+2005-02-14 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * tests/all.tcl: Add a [package require Tk] so that a missing display
+ causes an early failure and keeps the error trace short. Issue observed
+ in [FRQ 11122147], even though that's unrelated.
+
+2005-02-11 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/panedwindow.tcl (::tk::panedwindow::Cursor): check window
+ existence on delayed call. [Bug 949792]
+
+ * doc/text.n: note 'image' key in 'dump' command. [Bug 1115907]
+
+ * win/tkWinWm.c (TkWinGetIcon): fix toplevel retrieval for determining
+ icon ref (potential crash). [Bug 1105738]
+
+ * generic/tkCanvBmap.c (ConfigureBitmap, ComputeBitmapBbox): Fixed
+ possible crash with disabled bmap and bbox handling [Bug 1119460]
+ (BitmapToPostscript): made aware of various bitmap types
+
+ * unix/Makefile.in: remove SHLIB_LD_FLAGS (only for AIX, inlined into
+ * unix/tcl.m4: SHLIB_LD). Combine AIX-* and AIX-5 branches in
+ * unix/configure: SC_CONFIG_CFLAGS. Correct gcc builds for AIX-4+ and
+ HP-UX-11. autoconf-2.59 gen'd.
+
+2005-02-09 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * tests/wm.test: Convert to use more tcltest2 features.
+
+2005-02-07 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * generic/tkCanvas.c (CanvasWidgetCmd): Fix stupid mistake in variable
+ names, reported by Andreas Leitgeb.
+
+2005-02-03 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * generic/tkCanvas.c (GetStaticUids): New function to manage the
+ thread-specific data detailing the list of all uids in a thread.
+ (typeList): Protect this (the other piece of global data) with a mutex.
+ [Bug 1114977]
+
+2005-01-31 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/tcl.m4, unix/configure: add solaris-64 gcc build support. [Bug
+ 1021871]
+
+2005-01-31 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * generic/tkImgPhoto.c (PhotoFormatThreadExitProc): Made the comments
+ in the code more relevant to the function they were documenting! [Bug
+ 1110553]
+
+ * library/msgs/es_ES.msg: Added more localization for Spanish Spanish.
+ [Bug 1111213]
+
+2005-01-25 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tkMacOSXInit.c (TkpInit): set tcl_interactive to 1 to show
+ console at startup instead of directly calling [console show].
+
+ * unix/tcl.m4 (Darwin): fixed bug with static build linking to dynamic
+ library in /usr/lib etc instead of linking to static library earlier in
+ search path. [Tcl Bug 956908]
+ Removed obsolete references to Rhapsody.
+ * unix/configure: autoconf-2.57
+
+2005-01-18 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * library/demos/menu.tcl: Reworked to make dialogs children of the
+ demo widget so that they are properly visible. Issue reported by Keith
+ Nash <k.j.nash@usa.net>
+
+2005-01-13 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * library/tkfbox.tcl (IconList_Selection, IconList_Create):
+ (IconList_Arrange): Assorted tk_getOpenFile fixes. [part of Bug 600313]
+ (IconList_ShiftMotion1): Also fix shift-drag.
+
+2005-01-12 Don Porter <dgp@users.sourceforge.net>
+
+ * unix/tcl.m4: Sync'ed to Tcl's copy.
+ * unix/configure: autoconf-2.57
+
+2005-01-12 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/event.n: Added section on predefined virtual events. [Bug 608115]
+
+2005-01-11 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tkTextDisp.c: fix to scrollbar height calculations of text
+ widgets containing a single very long (wrapped) line. This fixes at
+ least part of [Bug 1093631].
+
+2005-01-11 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tkObj.c (TkParsePadAmount):
+ * generic/tkPack.c: Moved function to tkObj.c and rewrote so that it
+ takes advantage of Tcl_Objs properly and cannot leave objects in an
+ inconsistent state. [Bug 1098779]
+
+2005-01-10 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/Makefile.in, unix/configure.in, unix/tkConfig.sh.in:
+ Remove ${DBGX}, ${TK_DBGX} from Tk build system. [Patch 1081595]
+ * unix/tcl.m4: re-synced with tcl/unix/tcl.m4
+ * unix/configure: Regenerated.
+
+2005-01-07 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tkWindow.c (GetScreen): Make sure the result is reset on all
+ error paths to stop strange errors. [Bug 697915]
+
+2005-01-05 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/loadTk.n, doc/toplevel.n: Convert to other form of emacs mode
+ control comment to prevent problems with old versions of man. [Bug
+ 1085127]
+
+2005-01-03 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tkWinWm.c (TkWinWmCleanup): clean up layered window class. This
+ caused crash in reinit of Tk (as seen in plugin).
+
+ ******************************************************************
+ *** CHANGELOG ENTRIES FOR 2004 AND 2003 IN "ChangeLog.2004" ***
+ *** CHANGELOG ENTRIES FOR 2002 AND EARLIER IN "ChangeLog.2002" ***
+ ******************************************************************
diff --git a/tk8.6/README.md b/tk8.6/README.md
new file mode 100644
index 0000000..c989637
--- /dev/null
+++ b/tk8.6/README.md
@@ -0,0 +1,37 @@
+# README: Tk
+
+This is the **Tk 8.6.10** source distribution.
+
+You can get any source release of Tk from [our distribution
+site](https://sourceforge.net/projects/tcl/files/Tcl/).
+
+
+## <a id="intro">1.</a> Introduction
+
+This directory contains the sources and documentation for Tk, a
+cross-platform GUI toolkit implemented with the Tcl scripting language.
+
+For details on features, incompatibilities, and potential problems with
+this release, see [the Tcl/Tk 8.6 Web page](https://www.tcl.tk/software/tcltk/8.6.html)
+or refer to the "changes" file in this directory, which contains a
+historical record of all changes to Tk.
+
+Tk is maintained, enhanced, and distributed freely by the Tcl community.
+Source code development and tracking of bug reports and feature requests
+takes place at [core.tcl-lang.org](https://core.tcl-lang.org/).
+Tcl/Tk release and mailing list services are [hosted by
+SourceForge](https://sourceforge.net/projects/tcl/)
+with the Tcl Developer Xchange hosted at
+[www.tcl-lang.org](https://www.tcl-lang.org).
+
+Tk is a freely available open source package. You can do virtually
+anything you like with it, such as modifying it, redistributing it,
+and selling it either in whole or in part. See the file
+`license.terms` for complete information.
+
+## <a id="tcl">2.</a> See Tcl README.md
+
+Please see the README.md file that comes with the associated Tcl release
+for more information. There are pointers there to extensive
+documentation. In addition, there are additional README files
+in the subdirectories of this distribution.
diff --git a/tk8.6/bitmaps/error.xbm b/tk8.6/bitmaps/error.xbm
new file mode 100644
index 0000000..5a1331f
--- /dev/null
+++ b/tk8.6/bitmaps/error.xbm
@@ -0,0 +1,8 @@
+#define error_width 17
+#define error_height 17
+static unsigned char error_bits[] = {
+ 0xf0, 0x0f, 0x00, 0x58, 0x15, 0x00, 0xac, 0x2a, 0x00, 0x16, 0x50, 0x00,
+ 0x2b, 0xa0, 0x00, 0x55, 0x40, 0x01, 0xa3, 0xc0, 0x00, 0x45, 0x41, 0x01,
+ 0x83, 0xc2, 0x00, 0x05, 0x45, 0x01, 0x03, 0xca, 0x00, 0x05, 0x74, 0x01,
+ 0x0a, 0xa8, 0x00, 0x14, 0x58, 0x00, 0xe8, 0x2f, 0x00, 0x50, 0x15, 0x00,
+ 0xa0, 0x0a, 0x00};
diff --git a/tk8.6/bitmaps/gray12.xbm b/tk8.6/bitmaps/gray12.xbm
new file mode 100644
index 0000000..a0eafa1
--- /dev/null
+++ b/tk8.6/bitmaps/gray12.xbm
@@ -0,0 +1,6 @@
+#define gray12_width 16
+#define gray12_height 16
+static unsigned char gray12_bits[] = {
+ 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x22, 0x22,
+ 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x88, 0x88,
+ 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x88, 0x88};
diff --git a/tk8.6/bitmaps/gray25.xbm b/tk8.6/bitmaps/gray25.xbm
new file mode 100644
index 0000000..fdaef49
--- /dev/null
+++ b/tk8.6/bitmaps/gray25.xbm
@@ -0,0 +1,6 @@
+#define gray25_width 16
+#define gray25_height 16
+static unsigned char gray25_bits[] = {
+ 0x88, 0x88, 0x22, 0x22, 0x88, 0x88, 0x22, 0x22, 0x88, 0x88, 0x22, 0x22,
+ 0x88, 0x88, 0x22, 0x22, 0x88, 0x88, 0x22, 0x22, 0x88, 0x88, 0x22, 0x22,
+ 0x88, 0x88, 0x22, 0x22, 0x88, 0x88, 0x22, 0x22};
diff --git a/tk8.6/bitmaps/gray50.xbm b/tk8.6/bitmaps/gray50.xbm
new file mode 100644
index 0000000..1f9fbc0
--- /dev/null
+++ b/tk8.6/bitmaps/gray50.xbm
@@ -0,0 +1,6 @@
+#define gray50_width 16
+#define gray50_height 16
+static unsigned char gray50_bits[] = {
+ 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa,
+ 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa,
+ 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa};
diff --git a/tk8.6/bitmaps/gray75.xbm b/tk8.6/bitmaps/gray75.xbm
new file mode 100644
index 0000000..f700b2c
--- /dev/null
+++ b/tk8.6/bitmaps/gray75.xbm
@@ -0,0 +1,6 @@
+#define gray75_width 16
+#define gray75_height 16
+static unsigned char gray75_bits[] = {
+ 0x77, 0x77, 0xdd, 0xdd, 0x77, 0x77, 0xdd, 0xdd, 0x77, 0x77, 0xdd, 0xdd,
+ 0x77, 0x77, 0xdd, 0xdd, 0x77, 0x77, 0xdd, 0xdd, 0x77, 0x77, 0xdd, 0xdd,
+ 0x77, 0x77, 0xdd, 0xdd, 0x77, 0x77, 0xdd, 0xdd};
diff --git a/tk8.6/bitmaps/hourglass.xbm b/tk8.6/bitmaps/hourglass.xbm
new file mode 100644
index 0000000..bb1d8ad
--- /dev/null
+++ b/tk8.6/bitmaps/hourglass.xbm
@@ -0,0 +1,9 @@
+#define hourglass_width 19
+#define hourglass_height 21
+static unsigned char hourglass_bits[] = {
+ 0xff, 0xff, 0x07, 0x55, 0x55, 0x05, 0xa2, 0x2a, 0x03, 0x66, 0x15, 0x01,
+ 0xa2, 0x2a, 0x03, 0x66, 0x15, 0x01, 0xc2, 0x0a, 0x03, 0x46, 0x05, 0x01,
+ 0x82, 0x0a, 0x03, 0x06, 0x05, 0x01, 0x02, 0x03, 0x03, 0x86, 0x05, 0x01,
+ 0xc2, 0x0a, 0x03, 0x66, 0x15, 0x01, 0xa2, 0x2a, 0x03, 0x66, 0x15, 0x01,
+ 0xa2, 0x2a, 0x03, 0x66, 0x15, 0x01, 0xa2, 0x2a, 0x03, 0xff, 0xff, 0x07,
+ 0xab, 0xaa, 0x02};
diff --git a/tk8.6/bitmaps/info.xbm b/tk8.6/bitmaps/info.xbm
new file mode 100644
index 0000000..801476e
--- /dev/null
+++ b/tk8.6/bitmaps/info.xbm
@@ -0,0 +1,5 @@
+#define info_width 8
+#define info_height 21
+static unsigned char info_bits[] = {
+ 0x3c, 0x2a, 0x16, 0x2a, 0x14, 0x00, 0x00, 0x3f, 0x15, 0x2e, 0x14, 0x2c,
+ 0x14, 0x2c, 0x14, 0x2c, 0x14, 0x2c, 0xd7, 0xab, 0x55};
diff --git a/tk8.6/bitmaps/questhead.xbm b/tk8.6/bitmaps/questhead.xbm
new file mode 100644
index 0000000..17b2929
--- /dev/null
+++ b/tk8.6/bitmaps/questhead.xbm
@@ -0,0 +1,9 @@
+#define questhead_width 20
+#define questhead_height 22
+static unsigned char questhead_bits[] = {
+ 0xf8, 0x1f, 0x00, 0xac, 0x2a, 0x00, 0x56, 0x55, 0x00, 0xeb, 0xaf, 0x00,
+ 0xf5, 0x5f, 0x01, 0xfb, 0xbf, 0x00, 0x75, 0x5d, 0x01, 0xfb, 0xbe, 0x02,
+ 0x75, 0x5d, 0x05, 0xab, 0xbe, 0x0a, 0x55, 0x5f, 0x07, 0xab, 0xaf, 0x00,
+ 0xd6, 0x57, 0x01, 0xac, 0xab, 0x00, 0xd8, 0x57, 0x00, 0xb0, 0xaa, 0x00,
+ 0x50, 0x55, 0x00, 0xb0, 0x0b, 0x00, 0xd0, 0x17, 0x00, 0xb0, 0x0b, 0x00,
+ 0x58, 0x15, 0x00, 0xa8, 0x2a, 0x00};
diff --git a/tk8.6/bitmaps/question.xbm b/tk8.6/bitmaps/question.xbm
new file mode 100644
index 0000000..ceba2ab
--- /dev/null
+++ b/tk8.6/bitmaps/question.xbm
@@ -0,0 +1,10 @@
+#define question_width 17
+#define question_height 27
+static unsigned char question_bits[] = {
+ 0xf0, 0x0f, 0x00, 0x58, 0x15, 0x00, 0xac, 0x2a, 0x00, 0x56, 0x55, 0x00,
+ 0x2b, 0xa8, 0x00, 0x15, 0x50, 0x01, 0x0b, 0xa0, 0x00, 0x05, 0x60, 0x01,
+ 0x0b, 0xa0, 0x00, 0x05, 0x60, 0x01, 0x0b, 0xb0, 0x00, 0x00, 0x58, 0x01,
+ 0x00, 0xaf, 0x00, 0x80, 0x55, 0x00, 0xc0, 0x2a, 0x00, 0x40, 0x15, 0x00,
+ 0xc0, 0x02, 0x00, 0x40, 0x01, 0x00, 0xc0, 0x02, 0x00, 0x40, 0x01, 0x00,
+ 0xc0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0xc0, 0x02, 0x00,
+ 0x40, 0x01, 0x00, 0xc0, 0x02, 0x00, 0x00, 0x01, 0x00};
diff --git a/tk8.6/bitmaps/warning.xbm b/tk8.6/bitmaps/warning.xbm
new file mode 100644
index 0000000..7925440
--- /dev/null
+++ b/tk8.6/bitmaps/warning.xbm
@@ -0,0 +1,5 @@
+#define warning_width 6
+#define warning_height 19
+static unsigned char warning_bits[] = {
+ 0x0c, 0x16, 0x2b, 0x15, 0x2b, 0x15, 0x2b, 0x16, 0x0a, 0x16, 0x0a, 0x16,
+ 0x0a, 0x00, 0x00, 0x1e, 0x0a, 0x16, 0x0a};
diff --git a/tk8.6/changes b/tk8.6/changes
new file mode 100644
index 0000000..29e992a
--- /dev/null
+++ b/tk8.6/changes
@@ -0,0 +1,7571 @@
+This file summarizes all changes made to Tk since version 1.0 was
+released on March 13, 1991. Changes that aren't backward compatible
+are marked specially.
+
+3/16/91 (bug fix) Modified tkWindow.c to remove Tk's Tcl commands from
+the interpreter when the main window is deleted (otherwise there will
+be dangling pointers to the non-existent window).
+
+3/16/91 (bug fix) Modified tkColor.c not to free black or white colors:
+some X servers get upset at this.
+
+3/18/91 (bug fix) Modified tkShare.c to fix bug causing "DeleteGroup
+couldn't find group on shareList" panic.
+
+3/18/91 (bug fix) Several changes to tkListbox.c and tkScrollbar.c to
+handle listboxes (and scrollbars) with zero total entries in them.
+
+3/22/91 (bug fix) Fixed a few ='s in tkListbox.c that should be ==.
+
+3/22/91 (bug fix) Fixed error in main.c that caused BadWindow errors
+in some cases where wish scripts invoke "destroy .".
+
+3/23/91 (new feature) Added Tk_CancelIdleCall to remove Tk_DoWhenIdle
+handler.
+
+3/23/91 (bug fix and new feature) Added -name option to main.c, made
+it more clever about choosing name (was always using the name "wish"
+on most Unix systems).
+
+3/23/91 (new feature) Added TK_CONFIG_STRING option to Tk_ConfigureWidget,
+used it to malloc strings for various widget options that used to be
+Tk_Uid's (e.g. button text, message strings, etc.). Eliminates core
+leaks when values change in continuous non-repeating fashion.
+
+3/29/91 (new feature) Added Tk_Preserve, Tk_Release, and
+Tk_EventuallyFree procedures to help manage widget records and avoid
+premature memory free-ing.
+
+4/4/91 (bug fix) Fixed problem in tkWm.c where top-level window geometry
+wasn't tracking correctly when wm-induced size change also changed window
+position (e.g. menus wouldn't be displayed at the right places).
+
+4/5/91 (new feature) Added "invoke" option to widget command for buttons,
+check buttons, and radio buttons.
+
+4/5/91 (new feature) Added "unpack" option to "pack" command.
+
+4/5/91 (bug fix) Changed tkPack.c to use new Tk_Preserve code and be
+more careful about window deletions that occur while repacking is in
+progress.
+
+4/6/91 (bug fix) Major overhaul of deletion code in all widgets to use
+Tk_Preserve and Tk_Release. Should fix many problems.
+
+4/6/91 (bug fix) Changed "winfo children" to generate correct lists
+when child names have embedded spaces.
+
+4/6/91 (new feature) Added "screenheight" and "screenwidth" options to
+"winfo".
+
+4/18/91 (bug fix) Binding mechanism didn't correctly handle very long
+%-substitutions in commands (e.g. long path names) and caused memory
+to be overwritten. Modified tkBind.c to fix.
+
+---------------------- Release 1.1, 4/18/91 -------------------------
+
+4/19/91 (bug fix) Inconsistent ICCCM handling of coordinates of reparented
+windows causes windows to gradually walk south when moved or resized.
+Fixed tkWm.c to patch around the problem.
+
+---------------------- Release 1.2, 4/24/91 -------------------------
+
+4/26/91 (new feature) Added -geometry and -display switches to wish.
+Also wrote wish manual entry.
+
+5/3/91 (bug fix) Fixed bug in tkListbox.c that caused garbage to appear
+at right edge of window when strings were to large to fit in window.
+
+5/3/91 (bug fix) Fixed bug in tkListbox.c where topIndex wasn't getting
+updated when elements were deleted: tended to cause errors in
+communication with scrollbars.
+
+5/16/91 (bug fix) Fixed bug in tk3d.c, which caused core dumps when
+consecutive points in a polygon were the same (happened with some
+configurations of radio buttons, for example).
+
+5/16/91 (bug fix) Fixed main.c to allow stdin to be redirected.
+
+6/1/91 (bug fix) Make sure that pointers are never used after being
+freed.
+
+6/15/91 (bug fix) Fixed bug in tkBind.c that caused current binding
+values to not always be printed correctly.
+
+6/15/91 (bug fix) Make sure that interpreters are always unregistered
+when their main windows are deleted, and make wish delete the main
+window before exiting.
+
+8/21/91 (misfeature correction) Automatically set source of window
+position to "user" in "wm geometry" command, unless it has been
+explicitly set to "program".
+
+9/5/91 (bug fix) Modified option code to accept '#' as a comment
+character in .Xdefaults files, in addition to '!'.
+
+9/10/91 (misfeature correction) Changed binding mechanism so that
+numeric %-sequences are output in decimal instead of hex.
+
+9/19/91 (bug fix) Fixed bug in Tk_DoOneEvent(1) where it wasn't
+checking files and X connections properly so it missed events.
+
+10/6/91 (new feature) Reorganized tkBind.c to provide generic "binding
+table" structure, which can be used to create bindings on items in
+canvases as well as windows.
+
+10/6/91 (new feature) Upgraded buttons and menus to use new tracing
+code in Tcl 6.0. Allows radio buttons and check buttons to both set
+and clear themselves when associated variable changes.
+
+10/17/91 (bug fix) Fixed 2 bugs in listboxes: accidentally advanced the
+selection when new entries were inserted in the listbox after the location
+of the selected item(s), and goofed up on redisplay if selected item
+was deleted and then selection was immediately lost.
+
+10/27/91 (bug fix) "pack unpack" wasn't telling Tk that it no longer
+manages window; this led to core dumps in some situations.
+
+10/31/91 (reorganization) Renamed manual entries so that they are no
+more than 14 characters in length.
+
+10/31/91 (reorganization) Changed tk.h and tkInt.h so that tkInt.h
+doesn't needed to be included by tk.h.
+
+11/3/91 (portability improvement) Eliminated use of "class" as a variable
+name, since it's a reserved word in C++.
+
+11/7/91 (reorganization) Many changes to upgrade for Tcl 6.1 including
+use of Tcl hash tables instead of separate "Hash_" module. The "lib"
+subdirectory is no longer needed in Tk.
+
+---------------------- Release 1.3, 11/7/91 -------------------------
+
+11/24/91 (bug fix) Fixed bug causing occasional errors if existing bindings
+are modified (FindSequence in tkBind.c forget to set *maskPtr).
+
+11/24/91 (bug fix) Used wrong hash table in Tk_GetColorByValue. Could
+cause new entries to get created unnecessarily.
+
+12/2/91 (bug fix) Changed "bind" code to put backslashes in front of
+special characters (e.g. [ or \) that appear in %-replacements, so that
+they can be parsed cleanly.
+
+12/10/91 (bug fix) Manual entries had first lines that caused "man" program
+to try weird preprocessor. Added blank comment lines to fix problem.
+
+1/2/92 (documentation cleanup) Changed manual entries for Tk_GetBitmap
+and the like to make it more clear that the argument must be a Tk_Uid
+and not a string.
+
+1/2/92 (bug fix) Fixed problem where scrollbars that were very short or
+very narrow (too small to hold both arrows) could cause negative values
+in calls to XClearArea, which crashed some servers.
+
+1/2/92 (bug fix) Fixed bug in TkMeasureChars occurring when maxChars
+is 0. Occasionally affected things like message window geometry.
+
+1/3/92 (new feature) Added procedures Tk_GetJustify, Tk_GetAnchor,
+Tk_GetCapStyle, and Tk_GetJoinStyle, plus support for these things
+in Tk_ConfigureWidget.
+
+---------------------- Release 1.4, 1/10/92 -------------------------
+
+1/12/92 (bug fix) TkMenubutton.c wasn't cleaning up mbPtr->varName
+properly during menubutton cleanup if an error occurred during
+menubutton creation.
+
+1/19/92 (bug fix) Fixed off-by-one bug in tkListbox.c that caused
+scrollbars to display a slider that was too large.
+
+2/10/92 (bug fix) Tk_CreateFileHandler didn't correctly handle case
+where new mask was specified for existing handler.
+
+2/13/92 (bug fix) Tk_DeleteAllBindings wasn't correctly removing
+bindings from the pattern table: only did the removal for the
+first pattern in a pattern list.
+
+2/15/92 (new feature) Added procedures Tk_DefineBitmap and
+Tk_SizeOfBitmap. Tk_GetBitmapFromData is now considered obsolete
+and probably shouldn't be used anymore. Tk_GetBitmapFromData
+is now implemented by calling Tk_DefineBitmap and Tk_GetBitmap.
+
+2/15/92 (new feature) Added "curselection" and "select clear" options
+to widget command for listboxes.
+
+2/15/92 (new feature) Added Tk_3DBorderColor procedure.
+
+2/17/92 (relaxed limitations) Changed scrollbars so they no longer limit
+the slider position to lie within the object's range: can scroll off the
+end of an object, if the object permits it. Changed listboxes and
+entries to explicitly prevent viewing off the ends. Also relaxed
+listbox index checks so that out-of-range indices are automatically
+adjust to fit within the listbox range.
+
+2/19/92 (bug fix) tkWindow.c tended to leave half-created windows around
+if a new window's name was found to be in use already. Fixed to clean
+them up.
+
+2/22/92 (new feature) Added -anchor, -bitmap, -height, -textvariable,
+-width options to labels, buttons, check buttons, menu buttons, and radio
+buttons. This means that (a) size can be controlled better, (b) bitmaps
+can be displayed in any buttons, (c) the position of the text within the
+button can be controlled, and (d) a button can be made to display the value
+of a variable, continuously updating itself. Also changed -selector option
+so that if it's specified as an empty string then no selector is drawn
+for the button.
+
+2/22/92 (new feature) Changed menus to support bitmaps in menu entries:
+added new -bitmap option for entries.
+
+2/26/92 (bug fix) "after" command, when invoked with just one argument,
+called Tk_Sleep rather than registering a timer handler and looping on
+Tk_DoOneEvent. As a result, it caused the application to become non-
+responsive to X events during the sleep. Changed to use a Tk_DoOneEvent
+loop so that it is responsive.
+
+2/26/92 (bug fix) Tk's main program didn't map the main window until
+after the startup script returned. Changed to map the window as a
+do-when-idle handler, so that scripts can cause the window to be
+mapped immediately with a call to "update" or "after".
+
+2/28/92 (bug fix) "wm withdraw" wasn't working if invoked before window
+was originally mapped: window got mapped anyway. Fixed so that the
+window doesn't get mapped as long as it's withdrawn.
+
+2/29/92 (new feature) Can use "focus none" to clear input focus.
+
+2/29/92 (bug fix) Fixed tkEvent.c to generate SubstructureNotify events
+properly. These weren't being generated previously.
+
+2/29/92 (bug fix) Fixed entries so that newline characters can be properly
+displayed (as `\x0a'). Had to change interface to TkDisplayChars in order
+to do this (added flags argument).
+
+2/29/92 (bug fix) Change Tk not to update size and position of top-level
+windows directly during calls like Tk_ResizeWindow. Instead, wait until
+actual event is received. This makes updates happen at same time as
+callbacks.
+
+3/6/92 (bug fix) TkMenubutton.c was dumping core when a menubutton was
+pressed at a time when there was no associated menu for the button.
+
+3/6/92 (new feature) Added Tk script library directory with official
+Tk initialization file "tk.tcl". Other procedures used by Tk are in
+other files. Tk procedures and variables all have names starting
+with "tk_". Also added Wish startup script "wish.tcl", which sources
+both the Tk and Tcl startup scripts. This means that things like
+auto-loading and abbreviation expansion are now available in wish.
+Added new variables tk_library, tk_priv, and tk_version.
+
+3/6/92 (new feature) It's now possible to set bindings for whole
+classes by using the class name in the bind command. For example,
+"bind Button <Enter> {puts stdout Hi!}" will cause a message to be
+printed whenever any mouse button is entered. Can also use "all"
+to set bindings for all widgets. Widget-specific bindings override
+class bindings which override "all" bindings.
+
+3/6/92 (reorganization) Changed buttons (all flavors) and listboxes to
+eliminate all hard-wired behavior. Instead, default behavior is set
+by class bindings in tk.tcl. Also set up class bindings for menus,
+menubuttons, and entries, which previously had no default behavior at
+all. Scrollbars and scales still have hard-wired behavior that can't
+be overridden.
+
+3/7/92 (look-and-feel change) Changed listboxes and entries and menus
+to use button 2 for scanning instead of button 3. This is more consistent
+with the official Motif use of button 2 for dragging.
+
+3/10/92 (new features) Added more options to "winfo" command: screencells,
+screendepth, screenmmheight, screenmmwidth, and screenvisual.
+
+3/13/92 (bug fix) Event sharing mechanism (tkShare.c) wasn't checking
+to see whether window was mapped before sharing events with it.
+
+3/16/92 (bug fix) Tk_SetInternalBorderWidth was passing wrong window to
+geometry-management procedures, causing core-dumps when menu buttons
+had their border widths changed.
+
+3/16/92 (bug fix) Menus were setting their geometry directory rather
+than using Tk_GeometryRequest mechanism.
+
+3/17/92 (new feature) Added -cursor option to all widgets to set the
+active cursor for the widget. Also added TK_CONFIG_ACTIVE_CURSOR
+configure type.
+
+3/18/92 (new feature) Implemented generalized screen coordinates to
+allow resolution-independent specification in many cases (but pixel-
+based coordinates are still OK). Added Tk_GetScreenMM(),
+Tk_GetPixels(), new configure types TK_CONFIG_SCREEN_MM and
+TK_CONFIG_PIXELS. Changed widgets to use this new configure types
+wherever possible (a few of the more complex cases still haven't
+been taken care of yet). Added "pixels" and "fpixels" options to
+"winfo" command.
+
+3/18/92 (new feature) First cut at canvas widgets is done and part of
+the official Tk now. Canvases display text and structured graphics,
+and allow you to bind commands to events related to the text and
+graphics.
+
+3/21/92 (new feature) Added new "place" command. It implements a
+new geometry manager that provides fixed placement, rubber-sheet
+placement, and combinations of the two. Eliminated the commands
+"move", "resize", and "map" that were provided by main.c but never
+officially supported; the placer provides all of this functionality.
+
+3/23/92 (bug fix) Fixed bug in tkWm.c where top-level windows were
+occasionally not being given the right size. The problem occurred
+when a string of resizes happened all in a row (such as deleting all
+the windows in an application and then recreating them).
+
+3/23/92 (new feature) Added Tk_CoordsToWindow procedure and
+"winfo containing" command. These may be used to locate the window
+containing a given point.
+
+3/28/92 (new feature) Added "-exportselection" option to listboxes,
+so that listbox selection need not necessarily be the X selection.
+
+4/12/92 (bug fix) Changed menu buttons to store name of menubutton
+in the associated variable, rather than the name of the menu. This
+is necessary in order to allow several menu buttons to share the
+same menu.
+*** POTENTIAL INCOMPATIBILITY ***
+
+4/12/92 (bug fix) Fixed core dump that occurred in tkError.c when
+removing the first error record from the error list.
+
+4/15/92 (bug fix) Fixed bug in tkBind.c that prevented <KeyPress-1>
+event specifications from being processed correctly: the "1" was
+treated as a button name rather than a keysym.
+
+4/18/92 (new feature) Added Tk_DefineCursor and Tk_UndefineCursor
+procedures.
+
+4/18/92 (new feature) Major revision to listboxes. Can now scroll and
+scan in both x and y, plus -exportselection option allows selection not
+to be exported. The "view" widget command has been replaced by "xview"
+and "yview", and the "scan" widget command has a new syntax.
+*** POTENTIAL INCOMPATIBILITY ***
+
+4/18/92 (new feature) Added -exportselection option to entries, so you
+can select whether you want the entry selection to be the X selection
+or not.
+
+4/24/92 (new features) Added TK_CONFIG_CUSTOM type to Tk_ConfigureWidget,
+plus added new flags TK_CONFIG_NULL_OK, TK_CONFIG_DONT_SET_DEFAULT,
+and TK_CONFIG_OPTION_SPECIFIED. Several other new types, such as
+TK_CONFIG_CAP_STYLE, were also added as part of implementing canvases.
+
+4/29/92 (bug fix) Changed "-selector" default for menus to have separate
+values for mono and color.
+
+4/30/92 (bug fix) Fixed bug in tkListbox.c where it occasionally generated
+bogus scroll commands (last index less than first).
+
+4/30/92 (reorganization) Moved demos directory to "library/demos".
+
+---------------------- Release 2.0, 5/1/92 -------------------------
+
+5/2/92 (bug fix) Fixed problem in tkListbox.c where it was doing too many
+redisplays after repeated insertions. Also reduced number of invocations
+of scrollbar commands.
+
+5/7/92 (portability improvement) Changed main.c not to use TK_EXCEPTION
+flag; it isn't needed and it causes problems on some systems.
+
+5/9/92 (bug fix) Plugged core leaks in tkListbox.c and tkBind.c
+
+5/9/92 (bug fix) TkBind.c was accidentally deleting bindings during
+attempts to print non-existent bindings.
+
+5/11/92 (bug fix) Maximum name length for applications (name used in
+"send" commands) was too short (only 20); increased to 1000. Also
+fixed bug related to over-long names that caused core dumps.
+
+5/13/92 (bug fix) tkShare.c was using a dangling pointer if a share
+group was deleted as a side-effect of a shared event.
+
+5/13/92 (bug fix) Various initialization and core leak problems in
+tkGC.c, tkSend.c, tkMenu.c, tkEvent.c, tkCanvas.c, tkCanvPoly.c,
+tkCanvLine.c, tkListbox.c, tkEntry.c.
+
+5/13/92 (bug fix) Empty entries could be scanned off the left edge,
+displaying a garbage character.
+
+5/13/92 (bug fix) Fixed a few problems with window manager interactions,
+such as tendency for windows to spontaneously shrink in size. By no
+means are all of the problems fixed, though.
+
+5/13/92 (performance optimization) Changed Tk_GeometryRequest not to
+invoke geometry manager unless requested size has changed.
+
+---------------------- Release 2.1, 5/14/92 -------------------------
+
+5/1/92 (new features) Added flags like TK_IDLE_EVENTS to Tk_DoWhenIdle,
+plus added "idletasks" option to "update" command. Tk_DoWhenIdle arguments
+look different now, but the change should be upward-compatible.
+
+5/17/92 (new feature/bug fix) Added support for VisibilityNotify events
+to the "bind" command. For some reason they weren't supported previously.
+
+5/17/92 (new feature) Added "tkwait" command.
+
+5/17/92 (new feature) Added "grab" command.
+
+5/17/92 (new feature) Added "-width" option to messages. Also changed
+messages to use the computed (i.e. desired) line length when displaying,
+not the actual width of the window.
+
+5/17/92 (bug fixes) Did some more fiddling with tkWm.c in the hopes
+of improving window manager interactions. Now there won't be more than
+one configure request outstanding to the wm at a time.
+
+5/17/92 (bug fix) Arrowheads on canvas lines weren't being translated
+or scaled correctly.
+
+5/20/92 (bug fix) Page-mode scrolling didn't work correctly for canvases
+(wrong windowUnits was passed to scrollbars).
+
+5/20/92 (bug fix) Changed scrollbars not to lose highlight when pointer
+leaves window with button down. Also changed redisplay to double-buffer
+for smoother redraws.
+
+5/21/92 (new feature) Added "gray50" and "gray25" as predefined bitmaps.
+
+5/22/92 (new feature) Buttons can now be disabled using the "-state" and
+"-disabledforeground configuration options. The "activate" and "deactivate"
+widget commands for buttons are now obsolete and will go away soon.
+Please change Tcl scripts not to use them.
+
+5/23/92 (new feature) Entries can now be disabled using the "-state"
+config option. Also improved class bindings for entries to keep the
+cursor visible in the window when operations occur. Also made slight
+improvements in the way redisplay is done.
+
+5/23/92 (new feature) Added "-textvariable" option to entries so that
+the text in an entry can be tied to the value of a global variable in
+a fashion similar to buttons.
+
+5/27/92 (new feature) Added "-textvariable" and "-anchor" options to
+messages.
+
+5/28/92 (new feature) Added "-padx" and "-pady" and "-underline" options
+to menubuttons.
+
+5/28/92 (feature change) Changed "-width" and "-height" options on
+all flavors of buttons and menubuttons so that they are orthogonal
+to "-padx" and "-pady". It used to be that -width overrode -padx
+(no padding). Now they accumulate.
+
+5/29/92 (new feature) Added "-disabledforeground" option to menus and
+all flavors of buttons (can specify color for disabled things rather
+than just using stipple to gray out).
+
+5/29/92 (new features) Added many new options to menu entries:
+-activebackground, -background, -font, -state, -underline. The
+"disable" and "enable" widget commands for menus are now obsolete
+and will go away soon. Please change Tcl scripts not to use them.
+
+5/29/92 (new features) Added "atom" and "atomname" options to "winfo"
+command.
+
+5/29/92 (new feature) Wrote tk_listboxSingleSelect procedure, which
+can be used to change listbox behavior so that only a single item is
+selected at once.
+
+6/1/92 (new feature) Added new modifier names "Meta" and "Alt" for
+"bind" command.
+
+6/3/92 (new feature) Added "winfo toplevel" command.
+
+6/3/92 (new feature) Made several changes for greater Motif compliance,
+including:
+ - menu retention if you click and release in the menu button,
+ - keyboard traversal of menus (see traversal.man)
+ - no widget flashing if you set $tk_strictMotif to 1
+
+6/15/92 (bug fix) Fixed problem in tkBind.c where command string for a
+binding could get reallocated while the command was being executed (e.g.
+bindings that delete or change themselves).
+
+6/15/92 (bug fix) Don't allow "tabWidth" field to become zero in tkFont.c:
+can cause core dumps for fonts that don't enough information to compute
+tab widths.
+
+6/19/92 (bug fix) Fixed bug in binding mechanism that caused structure-
+related events to be reported both to the correct window and its parent.
+
+7/14/92 (bug fix) Changed tkColor.c not to free colors for visual types
+StaticGray or StaticColor.
+
+7/15/92 (new feature) Text widgets now exist. They display any number of
+lines of text with a variety of display formats, and include hypertext
+facilities. See the manual page for details.
+
+7/20/92 (bug fix) If a top-level window was put in the iconic state to
+begin with, it could be deiconified with "wm deiconify .foo" until it had
+first been deiconified by hand from the window manager. Tk was getting
+confused and thought the window was mapped when it wasn't.
+
+7/29/92 (bug fix) Don't permit rectangles or ovals to have zero-sized
+dimensions. Round up to at least one pixel.
+
+7/29/92 (new features) Major upgrade to canvases:
+ - new item types: arc, window, bitmap
+ - added Bezier spline support for lines and polygons
+ - rectangles and ovals now center their outlines on the shape,
+ rather than drawing them entirely inside the shape
+ - new "coords" and "bbox" widget commands
+ - new "-tags" option for all item types.
+ - new "-confine" option to prevent scrolling off edge of canvas.
+
+8/6/92 (new feature) Added "-width" and "-height" options to frames.
+The "-geometry" option is now obsolete and should be removed from Tcl
+scripts: it may go away in the future.
+
+8/7/92 (bug fix) Error messages in Tk_ParseArgv were sometimes including
+the option name where they should have included its value.
+
+---------------------- Release 2.2, 8/7/92 -------------------------
+
+8/7/92 (bug fix) Changed tkCanvas.c to be more conservative in the area
+it passes to XCopyArea.
+
+8/8/92 (bug fix) Fixed bug in tkTextDisp.c that sometimes caused core
+dumps when text views changed (e.g. typing return on last line of screen).
+
+8/8/92 (bug fix) Fixed bug in menu.tcl that caused errors when using
+keyboard to traverse over separator menu entries.
+
+8/10/92 (bug fix) Changed to use OPEN_MAX instead of MAX_FD to compute
+maximum # of open files.
+
+8/10/92 (bug fix) Canvases weren't updating scrollbars on window size
+changes. They also weren't recentering canvases on window size changes.
+
+8/10/92 (bug fix) There were still a few places where commands were being
+invoked at local level instead of global level (e.g. commands associated
+with buttons and menu entries).
+
+8/10/92 (bug fix) TkBind.c used to ignore explicit shift modifiers for
+all keys (i.e. <Shift-Tab> was treated the same as <Tab>). Modified to
+allow explicit request for shift modifier, like <Shift-Tab>.
+
+8/13/92 (feature change) Changed default fonts to request "Adobe" fonts
+explicitly.
+
+8/16/92 (bug fixes) Modified tkCanvArc.c and tkTrig.c to increase slightly
+the bounding boxes for arcs, in order to make sure that proper redisplay
+occurs when arcs are moved (little turds were getting left behind).
+
+8/16/92 (bug fix) Modified tkCanvas.c not to redraw at all if the redisplay
+area is off the screen. Also, only do a background clear for the portion
+of the redraw area that is on-screen. Also, reduced size of off-screen
+pixmaps used for redisplaying, which speeds up redisplay in some cases.
+
+8/19/92 (bug fix) Canvases that were taller than wide were not being
+redisplayed properly.
+
+8/20/92 (new feature) Added Tk_CreateGenericHandler procedure for trapping
+all X events (useful for tracing, watching non-Tk windows, etc.).
+
+8/21/92 (bug fix) Widgets weren't always being notified when they got
+the focus back again (the problem had to do with grabs and menus in
+particular).
+
+8/21/92 (new feature) Added "-state" option to scale widgets.
+
+8/22/92 (new feature) Changed tkBitmap.c to allow tilde-substitution
+to occur in bitmap file names.
+
+---------------------- Release 2.3, 8/24/92 -------------------------
+
+8/27/92 (bug fix) Changes to -activebackground and -activeforeground options
+for menubuttons were being lost.
+
+8/27/92 (bug fix) Entries were selecting last character when a B1-drag
+occurred past the right edge of the text.
+
+8/28/92 (bug fix) Fixed bug in canvases where a grab during a button
+press caused the canvas state to lock up so that it didn't select a
+new current item.
+
+9/7/92 (bug fix) Changed tkMenu.c to accept numerical menu indices that
+are out of range; now it just rounds them off to the nearest existing
+entry.
+
+9/7/92 (bug fix) Fixed bug in tkTextDisp.c that caused core dumps when
+invoking "yview -pickplace" widget command on texts that are too small
+to hold any lines at all.
+
+9/11/92 (bug fix) Fixed bug in tkTextDisp.c that caused core dumps
+when adding tags to non-existent lines.
+
+9/11/92 (bug fix) Line items in canvases didn't permit an empty fill
+color (i.e. couldn't make them transparent).
+
+9/14/92 (reorganization) Changed manual entries to use .1, .3, and .n
+extensions. Added "install" target to Makefile to suggest how Tk should
+be installed.
+
+9/16/92 (bug fix) Changed tkSend.c to always specify the root window of
+screen 0 rather than using DefaultRootWindow. DefaultRootWindow doesn't
+always go to screen 0 on displays with multiple screens, which can result
+in send's not being possible between the screens.
+
+9/18/92 (new feature) Added three new options to "wm" command: "protocol",
+"client", and "command". These provide support for window manager protocols
+such as WM_DELETE_WINDOW and WM_TAKE_FOCUS, plus support for the
+WM_CLIENT_MACHINE and WM_COMMAND properties.
+
+9/30/92 (new feature) Implemented color model support, including
+"tk colormodel" command and Tk_GetColorModel and Tk_SetColorModel
+procedures. These allow you to force mono operation even on a color
+display. Also changed color allocation not to give errors when colors
+run out, but just to switch to a mono color model.
+
+10/1/92 (bug fixes) Fixed two bugs in tkTextBTree.c that caused core dumps
+during text deletion.
+
+10/5/92 (bug work-around) Changed tkColor.c to ignore errors when freeing
+colors. This is needed to work around improper reference count management
+for colormap entries under X11/NeWS.
+
+10/7/92 (new feature) Added support for different visual types, including
+procedures Tk_SetWindowVisual and Tk_SetWindowColormap, plus macros
+Tk_Visual, Tk_Depth, and Tk_Colormap. The code for this was contributed
+by Paul Mackerras.
+
+10/7/92 (new feature) Added Tk_IsTopLevel macro.
+
+10/12/92 (bug fix) Fixed bug in tk.tcl that caused torn-off menus with
+cascaded children not to track mouse motion correctly (the cascade
+switched in response to mouse motions within the cascaded child).
+
+10/12/92 (new feature) Major changes to focus handling:
+(a) Tk watches FocusIn and FocusOut events for focus changes, not Enter
+ and Leave, so it will work better with explicit-focus-model window
+ managers (e.g. mwm in default mode).
+(b) Tk generates FocusIn and FocusOut events for the focus window now.
+ The old procedural interface (via Tk_CreateFocusHandler) is obsolete
+ and is no longer used inside Tk. It is still supported for
+ compatibility, but won't be for long. You should change your code
+ to use FocusIn and FocusOut events instead.
+(c) The model for FocusIn and FocusOut events is different than the
+ one described in Xlib documentation. See the "focus" manual entry
+ for details.
+(d) If there is no input focus then keyboard events are discarded. They
+ used to be directed to the mouse pointer window, although this wasn't
+ documented. The focus now defaults to the root window.
+*** POTENTIAL INCOMPATIBILITY ***
+
+10/15/92 (bug fix) Fixed text items in canvases where they didn't
+display the insertion cursor if the item had no characters in it.
+
+10/26/92 (bug fix) Fixed bug in tkSelect.c that occasionally caused
+BadWindow X protocol errors when retrieving the selection. Tk wasn't
+making sure that a window existed before using it to retrieve the
+selection.
+
+10/30/92 (feature change) Changed canvases so that if the scroll region
+is smaller than the window and -confine is on, the scroll region isn't
+forced to be centered in the window; it can be anywhere that meets the
+confinement restrictions.
+
+11/2/92 (new feature) Added "winfo exists" command.
+
+11/5/92 (new feature) Changed DoWhenIdle handlers so that if a new
+when-idle handler is created as a side-effect of another when-idle
+handler, the new handler isn't invoked until Tk has first checked
+for other events to process.
+
+11/6/92 (bug fixes, new features) Major overhaul of window manager
+interface:
+(a) Tk should now work with virtual-root window managers;
+(b) windows will now place more accurately on the screen and stay where
+ they're supposed to;
+(c) size changes handled more reliably;
+(d) code now works robustly in the face of withdrawals followed
+ immediately by deiconifications.
+(e) Added new procedure Tk_GetVRootInfo and new options to "winfo" command:
+ vrootx, vrooty, vrootwidth, vrootheight.
+(f) Added "overrideredirect" option to "wm".
+(g) Fixed bug where change in width-only via "wm geom" didn't always work
+ (min and max window sizes weren't being set properly for the wm).
+
+11/6/92 (bug fixes) Modified menus so that they work correctly with
+virtual root window managers. Also fixed bug where menus didn't move
+along with their associated windows, so that the menu popped up at
+the old location of the window rather than its new location.
+
+11/9/92 (new constraint) Made it illegal to give windows names that
+start with upper-case letters, since such names will goof up the
+option database by appearing to be classes rather than names.
+*** POTENTIAL INCOMPATIBILITY ***
+
+11/10/92 (new feature) Added Postscript output to canvases.
+
+11/13/92 (bug fix) Changed default for maximum size passed to window
+manager from 1000000 (which causes some wm's to make windows too large
+when "maximized") to the size of the display.
+
+11/14/92 (feature change) Major overhaul of menubuttons and pull-down
+menus. Removed event-sharing code, including Tk_ShareEvents and
+Tk_UnshareEvents. The -variable option for menubuttons has been
+removed,and the "post" and "unpost" widget commands for menubuttons
+no longer exist. The "post" widget command for menus no longer
+allows a group option. The procedure tk_menus has been replaced
+with a new procedure, tk_menuBar, which has a slightly different
+interface.
+*** POTENTIAL INCOMPATIBILITY ***
+
+11/20/92 (new features, feature changes) Major overhaul of grab
+mechanism to produce more correct event streams. Also changed Tcl
+commands to require explicit window for grab releases (makes it
+possible for grabs to work on multiple displays simultaneously).
+The old "grab none" command no longer exists, but new options
+have been added: "current", "release", "set", and "status".
+*** POTENTIAL INCOMPATIBILITY ***
+
+11/20/92 (new feature) Use TK_LIBRARY environment variable to set library
+directory location, if it is defined. Otherwise fall back on usual
+compiled-in value.
+
+11/25/92 (bug fix) "wm grid" command was using wrong window.
+
+11/29/92 (bug fix) Fixed core dump that occurred when trying to use
+placer on top-level windows: return error instead.
+
+11/29/92 (bug fix) Selection retrieval wasn't making sure that the window
+on whose behalf selection is being retrieved actually exists.
+
+12/3/92 (new feature) Added support for Mode_switch key to support the
+full ISO character set. Also added event handlers for MappingNotify
+events so that Tk updates itself in response to keycode and modifier
+changes.
+
+12/6/92 (bug fix) Ignore recursive attempts to destroy window.
+
+12/9/92 (new demos) Added "tcolor" and "rmt" demos.
+
+12/10/92 (new features) Added "yposition" widget command for menus,
+changed "delete" widget command to take an optional second index,
+and changed -command option for cascade entries so that it is
+invoked when the entry is activated rather than when it is invoked.
+*** POTENTIAL INCOMPATIBILITY ***
+
+12/12/92 (implementation change) Changed the procedures Tk_FreeBitmap,
+Tk_NameOfBitmap, Tk_SizeOfBitmap, Tk_FreeCursor, Tk_NameOfCursor, and
+Tk_FreeGC to require an addition Display argument. This is needed for
+Tk to function correctly when an application has windows on multiple
+displays.
+*** POTENTIAL INCOMPATIBILITY ***
+
+12/12/92 (new feature) Started creating a test suite. Right now it
+only has a few tests.
+
+12/12/92 (new feature) Modified the packer so that a window can be
+packed in descendants of its parent (used to be restricted to the
+parent alone). This makes it possible to hide extra windows used
+for geometry management. Also, can use generalized screen distances
+in the "pack" command.
+
+12/16/92 (feature change) Boolean options such as -exportselection now
+print as 0/1 rather than true/false (both the default and current values
+print this way). This makes it easier to use these values in expressions.
+*** POTENTIAL INCOMPATIBILITY ***
+
+12/16/92 (name change) The classes "RadioButton" and "CheckButton" have
+been renamed "Radiobutton" and "Checkbutton" for consistency. From now
+on widget class names will have exactly one capital letter.
+*** POTENTIAL INCOMPATIBILITY ***
+
+12/16/92 (new feature) Added -setgrid option to listboxes.
+
+12/16/92 (new feature) The "destroy" command, and the "delete" widget
+command for canvases, now accept any number of arguments, including
+zero.
+
+12/16/92 (new feature) Changed internal TkBindError procedure to
+Tk_BackgroundError and exported it to Tk clients.
+
+12/16/92 (option name change) Changed the place command's "dependents"
+option to "slaves" for better consistency with documentation.
+*** POTENTIAL INCOMPATIBILITY ***
+
+12/16/92 (name changes) Renamed the "cursor*" options in entries and
+canvases to "insert*". Also renamed the "cursor" index to "insert" and
+the "cursor" widget command to "icursor". This was done to avoid
+confusion between the mouse cursor and the insertion cursor.
+*** POTENTIAL INCOMPATIBILITY ***
+
+---------------------- Release 3.0, 12/17/92 -------------------------
+
+12/17/92 (bug fix) Fixed dangling-pointer bug in canvases that occurred
+if a <LeaveNotify> binding deleted the current item.
+
+12/18/92 (bug fix) Core dump occurred if "wm" invoked with no arguments.
+Also, tkWm.c wasn't properly setting WM_CLASS property on application
+startup.
+
+12/18/92 (incorrect documentation) Updated manual entries for Tk_FreeGC,
+Tk_FreeCursor, and Tk_FreeBitmap to reflect new interface that requires
+"display" argument.
+
+12/18/92 (missing documentation) Added documentation for the canvas
+"postscript" command, which was missing in the 3.0 release.
+
+12/21/92 (bug fixes) There were lots of problems with the new installation
+targets in the Makefiles, such as using "cp -f" and not installing
+prolog.ps. Made several other miscellaneous improvements to Makefile.
+
+12/21/92 (bug fix) Arrowheads on canvas line items weren't moving properly
+after coordinate changes made with the "coords" widget command.
+
+12/21/92 (bug fix) If top-level window was initially withdrawn, couldn't
+ever deiconify it again.
+
+12/21/92 (bug fix) Double-button event sequences didn't always trigger
+properly when grabs were in effect.
+
+12/22/92 (bug fix) The packer didn't display any top or bottom windows
+after a left or right expanded window, and vice versa. Also made the
+distribution of space among expanded windows more even.
+
+12/28/92 (new features) Several improvements to selection:
+(a) Added procedures Tk_ClearSelection and Tk_DeleteSelHandler.
+(b) Added "clear" and "own" options to "selection" command, extended
+ "handle" option to delete handlers.
+(c) Error returns from "selection handle" scripts are now turned into
+ selection retrieval errors ("no such selection") rather than an
+ empty selection.
+(d) Tk responds automatically for targets APPLICATION (name of application,
+ so you can "send" to it) and WINDOW_NAME (name of window within
+ application.
+(e) Added test file "select.test" to test suite.
+
+12/28/92 (bug fix) Fixed problem with flashing menus that occurred
+because menu.tcl was willing to unpost and then immediately repost
+the same menu.
+
+1/6/93 (bug fix) Test for UnmapNotify events in tkPack.c used = instead
+of ==.
+
+1/21/93 (bug fix) Changed many widgets to eliminate use of
+DefaultVisualofScreen, DefaultColormap, etc. and use the visuals
+and colormaps for the actual windows instead. Also changed to
+inherit colormaps and windows from parent by default.
+
+1/21/93 (new features) Added new winfo options "cells", "depth", and
+"visual".
+
+1/23/93 (bug fix) Fixed problem with text display that could result
+in negative XCopyArea heights being sent to X server. This causes some
+servers (e.g. some versions of OpenWindows) to crash.
+
+1/25/93 (new feature) Added -postcommand option to menus, so that menus
+can be reconfigured before each posting.
+
+1/29/93 (feature change) Changed %X and %Y in bindings so that they
+refer to the virtual root rather than the true root. Although
+potentially incompatible, this change should almost always "do the
+right thing".
+*** POTENTIAL INCOMPATIBILITY ***
+
+1/31/93 (bug fix) Changed "send" code to grab server while updating
+the registry property (before this fix, two programs could allocate
+the same interpreter name if they started up simultaneously). In
+order to make this fix I had to change the code for reclaiming
+names of dead interpreters in a way that sometimes allows dead
+interpreters to persist in the registry.
+
+2/1/93 (feature change) Changed entries to allow leftmost "visible"
+character to be the end of the text (i.e. no characters actually visible).
+This is needed so that the cursor can be displayed even if the last
+actual character is too wide to fit in the window.
+
+2/3/93 (bug fix) Fixed two bugs in tkFocus.c: (a) FocusIn events
+were getting lost in some cases because the focus window hadn't been
+created yet (e.g. new top-level window pops up underneath the mouse);
+(b) Tk was accidentally triggering FocusOut events when the mouse
+moved from a top-level window to one of its children.
+
+2/4/93 (new feature) Added "visibility" option to "tkwait" command to make
+it easier to wait for a new window to appear on the screen.
+
+---------------------- Release 3.1, 2/5/93 -------------------------
+
+2/10/93 (installation improvements) Makefile improvements: added RANLIB
+variable for easier Sys-V installation, changed to use INCLUDE_DIR
+properly, and added SHELL variable for SGI systems.
+
+---------------------- Release 3.2, 2/11/93 -------------------------
+
+2/11/93 (new feature) Added "wm state" command, and improved wm so that
+the right thing will happen if you invoke "wm iconify" when a window is
+withdrawn.
+
+2/14/93 (bug fix) When -colormap option was used in generating Postscript
+for canvases, Tk didn't add an extra space after the color command.
+
+2/14/93 (new feature) Changed "extern" declarations in tk.h to "EXTERN",
+which will use the definition of EXTERN from tcl.h and work correctly
+in C++ programs.
+
+2/18/93 (bug fix) Item-specific bindings weren't getting deleted from
+canvas items when the items were deleted. As a result, they could
+suddenly re-appear for new items if the new items were allocated a
+record at the same addresses as the old ones.
+
+2/18/93 (feature reversal) Changed "after" back again, so that it sleeps
+*without* responding to events when it is invoked with just one argument;
+can always use tkwait plus after with additional arguments to achieve
+the effect of responding to events.
+*** POTENTIAL INCOMPATIBILITY ***
+
+2/20/93 (bug fix) Fixed bug in tkWindow.c where colormaps weren't being
+set correctly for new top-level windows on different screens than their
+parents (the bug results in X protocol errors: "invalid Colormap
+parameter").
+
+2/22/93 (bug fix) Changed "#!/usr/local/wish" in demo scripts to
+"#!/usr/local/bin/wish" to reflect new location of binary.
+
+2/22/93 (new feature) Added new reliefs "groove" and "ridge".
+
+2/25/93 (new feature) Added new built-in bitmaps: "error", "hourglass",
+"info", "question", "questhead", and "warning". Also added new demo in
+"widget" to display all of these (under the Miscellaneous menu).
+
+2/25/93 (improved implementation) Changed DrawText procedure in
+prolog for outputting Postscript from canvases to use stringwidth
+instead of charpath+pathbbox: avoids limitcheck problems with long
+strings, and also properly includes space characters in calculation.
+
+2/25/93 (bug fix) Fixed several bugs in library/menu.tcl that caused
+menu traversal to mis-behave when menu had no entries.
+
+2/26/93 (new feature) Added "wm frame" command.
+
+3/6/93 (bug fix) Mwm in click-to-focus mode was goofing up grabs so that
+pull-down menus were sometimes unresponsive. Modified tk.tcl to ignore
+the spurious B1-Enter events generated by mwm, plus modified tkGrab.c to
+release simulated button grabs correctly.
+
+3/8/93 (bug fix) Tk had wrong interpretation of "lbearing" font metric,
+which caused text to be displayed at the wrong horizontal position in
+several places (labels/buttons, listboxes, canvas text, scales). This
+change will cause slight changes in the way certain widgets are
+displayed.
+
+3/12/93 (bug fix) Fixed core dumps that occurred in tkEntry.c because of
+zero values in entryPtr->avgWidth.
+
+3/12/93 (bug fix) Tk_CoordsToWindow was using root coordinates always.
+Changed to use virtual-root coordinates when a virtual-root window
+manager is being used. Before this fix, "winfo containing" didn't
+return the correct window under virtual-root window managers.
+
+3/18/93 (bug fix) Modified tkWm.c so that Tk doesn't fight with window
+manager over position of window; it just takes what the window manager
+gives it.
+
+3/21/93 (new feature) Changed menus to display cascade entries with
+standard Motif arrows at right side.a
+
+3/22/93 (bug fix) Fixed bug in tkPack.c that was causing memory to
+get trashed with the integer value 1.
+
+3/22/93 (bug fix) Canvas text didn't print correctly if it contained
+an open paren (or other special character) immediately followed by
+an octal digit.
+
+3/22/93 (bug fix) Text widgets didn't redisplay properly in cases
+where two or more groups of lines both got taller at the same time
+(e.g. from tag changes), causing two separate bit copies where the
+first bit copy's target area overlapped the source area for
+the second bit copy.
+
+4/1/93 (bug fix) Changed canvases to use ISO Latin-1 font encoding
+if that's supported by the Postscript interpreter. Also added workaround
+for bug in NeWSprint related to stipple fills.
+
+4/1/93 (bug fixes) Made various changes to focusing and grabs to
+eliminate extraneous focus events and generally improve behavior.
+
+4/2/93 (bug fix) Modified tkWm.c not to wait indefinitely for the window
+manager to map or reconfigure a window: this led to deadlock in some
+situations, such as creating a new top-level window with a grab held.
+
+4/19/93 (bug fix) Fixed another bug in tkWm.c that caused windows to walk
+across the screen in some situations. Also fixed problem where rapid
+posting and unposting of cascaded submenus (or menus?) could cause Tk
+to become confused about whether or not a window is mapped (added
+TkWmUnmapWindow procedure to make top-level unmaps synchronous).
+
+4/24/93 (feature change) Changed the "after" command to allow times
+less than or equal to 0, and to use 0 whenever they occur.
+
+4/26/93 (new feature) Implemented security check for "send" as proposed
+by Bennett Todd: incoming sends are now rejected unless (a) xhost-style
+access control is enabled and (b) the list of authorized hosts is
+empty. In other words, you have to use xauth to use send. This feature
+can be disabled by setting the TK_NO_SECURITY flag at compile-time.
+
+5/15/93 (improvement) Switched to use Tcl_PrintDouble whenever returning
+real values as Tcl results. This potentially allows higher precision.
+Switched to use %.15g whenever printing reals in Postscript files.
+However, the change Tcl_PrintDouble causes incompatibilities. For
+now, it's disabled with a macro in tclInt.h that redefines Tcl_PrintDouble.
+Tk 4.0 will delete the macro, and you can also delete it now if you
+want the better (but incompatible) behavior.
+
+5/19/93 (bug fix) Fixed divide-by-zero problem that could occur in
+closeness calculations for canvas oval items.
+
+5/30/93 (bug fix) PROP and CONFIG were accidentally #defined to the same
+value in tkBind.c, which could cause incorrect %-substitutions in event
+bindings in a few exotic cases.
+
+6/4/93 (improvement) Changed to use GNU autoconfig for configuration.
+Makefile format changed, and Tcl is no longer automatically included
+in Tk releases.
+
+6/7/93 (bug fix) Fixed off-by-one error in rounding negative coordinates
+during redisplay of canvases.
+
+6/9/93 (feature improvement) Modified default bindings for entries to
+keep one character visible to the left of the cursor during backspaces.
+
+6/18/93 (feature improvement) Added patchlevel.h, for use in coordinating
+future patch releases, and also added tk_patchLevel variable to make the
+patch level available in scripts.
+
+6/26/93 (bug fix) Fixed numeric problems in scales that occurred with
+very large scale values.
+
+6/26/93 (bug fix) Polygon items in canvases could cause core dumps if
+the "coords" widget command was used to add one new coordinate.
+
+6/26/93 (bug fix) Changed canvases to handle large stipple patterns
+gracefully (stipples used to jump around during redisplay and lose
+coherency).
+
+7/1/93 (syntax change, new feature) Implemented the new packer syntax
+as described in the book. For now the old syntax will continue to be
+supported too. Converting over is straightforward except (a) use
+"-anchor" instead of "frame", and (b) padding is different (separate
+internal and external padding, plus pad amounts are *on each side*
+instead of total). Also added "pack propagate" command for keeping
+the packer from setting the master's requested size.
+
+7/1/93 Changed copyright notices. The effect is the same as with the
+old notices, but the new notices more clearly disclaim liability.
+
+7/7/93 (new feature) Added support for window stacking order. Windows
+will now stack in the order created (most recent on top), plus "raise"
+and "lower" commands may be used to restack (Tk_RestackWindow procedure
+is available from C level).
+
+7/7/93 (reorganization) Moved main.c to tkMain.c, reorganized it to
+call Tcl_AppInit just like tclsh does, and added argv0 variable to contain
+application name, and added default Tcl_AppInit procedure for wish.
+Also added tkTest.c to hold C code for testing.
+
+7/7/93 (new feature) Added new Tk-specific "exit" command, which cleans
+up properly before exiting. It replaces the Tcl "exit" command, and
+can be used in place of "destroy .".
+
+7/9/93 (new features) Added tk_dialog library procedure that creates
+dialogs with a bitmap, message, and any number of buttons. Also changed
+default tkerror procedure to use tk_dialog plus offer the user a chance
+to see a Tcl stack trace.
+
+-------------------- Release 3.3 Beta 1, 7/9/93 -------------------------
+
+7/12/93 (configuration changes) Eliminated leading blank line in
+configure script; provided separate targets in Makefile for installing
+binary and non-binary information; fixed -lnsl and -lsocket handling
+in configure; added autoconf support for fd_set type; check for various
+typedefs like mode_t and size_t, and provide substitutes if they
+don't exist; don't include tkAppInit.o in libtk.a; try to locate the
+X includes and library in all of the standard places for various systems.
+
+7/14/93 (new feature) Modified tkMain.c so that it stores the value
+of the -display command-line option into the DISPLAY environment
+variable, if it is specified.
+
+7/15/93 (feature removal) Removed auto-initialization feature from
+Tk_ConfigureWidget, so that you must once again initialize all fields
+of a widget record before calling Tk_ConfigureWidget. This restores
+the behavior back to what it was in Tk 3.2.
+
+7/16/93 (bug fix) Modified tkBind.c to ignore the Caps Lock modifier
+unless it is explicitly requested in a binding. Without this fix,
+buttons and menus and other things didn't work if the Caps Lock key
+was active.
+
+-------------------- Release 3.3 Beta 2, 7/21/93 -------------------------
+
+7/21/93 (new feature) Change "make install" so that it will modify the
+#! lines on demo scripts to reflect the place where the wish binary
+is installed.
+
+7/23/93 (new feature) Added Tk_MainWindow procedure that returns the
+main window associated with a Tcl interpreter. This is intended for
+use by Tcl_AppInit and other initialization procedures.
+
+7/24/93 (configuration improvements) Changed configure script not to
+omplain about "fd_set" missing if it's defined in <sys/select.h>.
+
+7/28/93 (bug fix) "Bad Match - parameter mismatch" errors were
+sometimes occurring when several top-level windows got created
+at the same time, due to wrong choice of sibling when stacking
+windows.
+
+8/14/93 (new feature) Added support for tcl_prompt1 and tcl_prompt2
+to wish main program: makes prompts user-settable.
+
+8/19/93 (bug fix) Bindings to event sequences like "aD" never matched
+because the Shift key has to be pressed before D. Modified Tk to
+ignore extraneous keypresses if they are for modifier keys.
+
+8/26/93 (configuration changes) Added Tk_Init, modified Tcl_AppInit
+procedures to use it and Tcl_Init. Added support for .wishrc file.
+
+8/28/93 (new feature) The main window is now a legitimate toplevel
+widget.
+
+-------------------- Release 3.3 Beta 3, 8/30/93 -------------------------
+
+9/2/93 (bug fix) The packer wasn't always relaying out a master after
+changes to some of the configuration options of its slaves.
+
+9/2/93 (bug fix) The binding mechanism made it impossible for patterns
+like <Double-ButtonRelease-1> to ever match.
+
+9/2/93 (bug fix) Fixed core dump that occurred for bitmap canvas items
+if Postscript is generated but no -bitmap option has been specified.
+
+9/4/93 (enhancement) Slight improvements to menu traversal: set menu
+traversal bindings for menubar window in tk_menuBar, plus trigger
+traversal on <Any-Alt-Keypress> instead of <Alt-Keypress>.
+
+9/9/93 (bug fix) Changed tkBind.c so that the Num_Lock key doesn't
+prevent events from triggering bindings.
+
+9/9/93 (bug fix) Changed tkOption.c to always fetch RESOURCE_MANAGER
+property from root window of screen 0, rather than using default
+screen.
+
+9/9/93 (bug fix) Entry widgets weren't allocating quite enough width
+for themselves. Fixed this and changed the size computation to match
+what's done for buttons and texts.
+
+9/16/93 (bug fix) Changed tkMain.c not to call exit C procedure directly;
+instead always invoke "exit" Tcl command so that application can redefine
+the command to do additional cleanup.
+
+-------------------- Release 3.3, 9/29/93 -------------------------
+
+9/30/93 (bug fix) Packer wasn't unmapping slaves when master got deleted.
+
+9/30/93 (bug fix) Binding event sequences such as <Right> were being
+misprinted as ASCII characters such as "S".
+
+10/6/93 (bug fix) Canvases weren't unmapping window items when the canvas
+got unmapped, which caused problems for window items whose windows weren't
+descendants of the canvas (they got left on the screen).
+
+10/7/93 (feature change) NULL proc arguments to Tk_CreateFileHandler used
+to have a special undocumented meaning (fd was display); eliminated this
+special interpretation.
+
+10/7/93 (configuration change) Eliminated dependency of tkMain.c on
+tkInt.h and tkConfig.h, so that it's easier for people to copy the file
+out of the source directory to make modified versions.
+
+10/8/93 (bug fix) 3.0 introduced a bug where the class of the application
+wasn't being set properly, so options based on the application class
+weren't triggering. Fixed by adding new argument to Tk_CreateMainWindow.
+
+10/11/93 (bug fix) Fixed bug in tkTextBTree.c where some deletions would
+cause core dumps due to halfwayLinePtr not getting set correctly.
+
+10/18/93 (bug fix) Fixed a couple of bugs that made it hard to actually
+display N characters in an entry with "-width N" (tended to scroll the
+entry so that only N-1 characters were visible at once).
+
+10/22/93 (bug fix) During configuration, XINCLUDE_DIR and XLIBRARY_DIR
+weren't overriding xmkmf like they were supposed to.
+
+10/23/93 (new feature) Allow negative scale factors in canvas "scale"
+widget command.
+
+10/23/93 (bug fix) Grabs weren't being cleaned up right if the grab
+window was deleted, causing core-dumps in some cases.
+
+10/23/93 (bug fix) tk_TextSelectTo wasn't checking to be sure that
+the "anchor" mark exists.
+
+10/27/93 (bug fix) Fixed core dump that could occur in a text widget if
+the scroll command modifies the text.
+
+11/1/93 (bug fix) Change texts so that the -yscrollcommand option is
+invoked at display time, not when the window is re-layed out. This
+eliminated various core dumps that could occur if -yscrollcommand modified
+the text.
+
+-------------------- Release 3.4, 11/04/93 -------------------------
+
+Note: there is no 3.5 release. It was flawed and was thus withdrawn
+shortly after it was released.
+
+11/12/93 (bug fix) TkMain.c didn't compile on some systems because of
+R_OK in call to "access". Changed to eliminate call to "access".
+
+-------------------- Release 3.6, 11/26/93 -------------------------
+
+11/10/93 (bug fix) Packer and placer didn't always reposition a window
+correctly if it was managed inside a neice or lower descendant (using
+"-in" option) and the neice's parent moved.
+
+11/24/93 (bug fix) Fixed time problem in selection (retrievals could
+fail if retriever hasn't received any X events since selection was
+made, so that time of retrieval appears to be older than time of
+selection). Selection code is now much less picky about times, both
+on retrieving and supplying sides.
+
+12/2/93 (new feature) Changed arrow-head drawing code for canvas
+lines to draw a 0-width outline in addition to filling the area:
+this produces much nicer, more symmetrical displays.
+
+12/2/93 (bug fix) When colors ran out, Tk was invoking "tkerror"
+when its state was internally inconsistent, which could cause
+core dumps in some situations (e.g. if tkerror used the same color
+that caused colors to run out). Changed notification to occur
+as a when-idle handler.
+
+12/3/93 (bug fix) During a global grab, Tk wasn't including PointerMotion
+in the list of grabbed events, so pointer motion couldn't be tracked
+outside the grabbing application.
+
+12/3/93 (bug fix) Canvases didn't handle smoothed lines correctly
+when they only contained two points.
+
+12/3/93 (bug fix) Fixed bug in tkWindow.c where certain kinds of
+errors during window creation could cause Destroy events to be generated
+for a window that was never completely initialized.
+
+12/13/93 (bug fix) Fixed bug in tkTextDisp.c that resulted in core
+dumps at line 1467 under exmh. The exact situation is that a text
+widget was being redisplayed at a time when it had a -yscrollcommand
+option but hadn't yet been mapped onto the screen.
+
+12/17/93 (bug fix) Fixed bug in tkWindow.c whereby new top-level windows
+with non-default visuals still inherited border pixmap from parent (root),
+which could cause visual clash and X error.
+
+12/17/93 (bug fix) Fixed bug in tkTextDisp.c that caused round-off
+error in the information passed to scroll commands.
+
+12/18/93 (bug fix) Fixed bug in tkPack.c that caused core dumps in
+some situations if a master with siblings packed "-in" it was deleted.
+
+12/18/93 (bug fix) Added "compat" directory to distribution, since it's
+referenced by tkConfig.h on some systems.
+
+12/18/93 (performance improvement) Improved performance of appending to
+a listbox, so that inserting N items doesn't take N**2 time.
+
+12/20/93 (bug fix) Fixed bug in canvas ovals that caused the fill color
+for the oval to stick out past the outline.
+
+1/2/94 (fixed Xlib bug) Added code to reuse X resource identifiers so
+that they won't run out in long running applications. There are three
+new library procedures: Tk_FreeXId, Tk_GetPixmap, and Tk_FreePixmap.
+Modified all Tk code to use these procedures, so wish applications should
+now be able to run forever without running out of identifiers.
+
+1/10/94 (bug fix) tkCursor wasn't freeing pixmaps used to create
+cursors, which caused memory leaks in programs that changed cursors
+frequently.
+
+1/21/94 (bug fix) Fixed bug in scales that caused them to loop
+infinitely drawing tick-marks when -from and -to were the same.
+
+2/2/94 (bug fix) Fixed problem where messages that contained tabs
+didn't always compute the correct size, so that text spilled off
+the right edge. The fix adds an extra "tabOrigin" parameter to
+the internal procedures TkMeasureChars, TkDisplayChars, and
+TkUnderlineChars.
+
+2/4/94 (bug fix) Fixed off-by-one problem in tkBind.c that caused
+it to read past the initialized part of dispPtr->modKeyCodes.
+
+2/7/94 (bug fix) Text widgets didn't handle grabs correctly, such
+that the "current" character got stuck if a grab occurred while a
+mouse button was down. It would get unstuck until after the
+next button press and release.
+
+2/19/94 (bug fix) Fixed prolog.ps (prolog for Postscript printing from
+canvases) so that it correctly prints all of the characters in the
+ISO Latin-1 character set.
+
+2/19/94 (bug fix) Modified tkBind.c to save and restore the interpreter's
+result across the execution of binding scripts. Otherwise if an event
+triggers in the middle of some other script (e.g. a destroy event during
+window creation, because there was an error in the creation command),
+the interpreter's result gets lost.
+
+2/19/94 (bug fix) Fixed bug in dealing with results of sent command
+that could cause them to get lost in some situations.
+
+2/21/94 (bug fix) Don't let user close a dialog window created by
+tk_dialog, since this would cause tk_dialog to hang: force the user
+to select one of the dialog's buttons.
+
+2/21/94 (bug fix) Fixed bug in canvas polygons whereby they didn't
+correctly handle changes in the number of points (via "coords"
+widget command).
+
+2/23/94 (bug fix) Large bitmaps in canvases didn't print correctly
+because they overflowed the 64-KB limit on strings in Postscript.
+Changed canvas printing to split up large bitmaps into mutliple
+smaller ones for printing.
+
+2/25/94 (bug fix) The "." window was being set up with -width
+and -height options, which interfered with geometry management (any
+configuration change on "." causes the window to change size to
+200x200, then change back again).
+
+2/26/94 (bug fix) Fixed several bugs that occurred when a Destroy
+event handler for a window deleted the window's parent.
+
+3/3/94 (new features) Changes to binding mechanism:
+ - The modifiers for "Alt", "Meta", and "M" are now computed by
+ examining the modifier map, rather than being hardwired to
+ M2, M1, and M1.
+ - When processing events, one script is invoked for each object
+ in the list passed to Tk_BindEvent, rather than stopping as
+ soon as a script is invoked for some object. The "break" and
+ "continue" commands can be used within a script to abort all
+ scripts for the event or the current one.
+ *** POTENTIAL INCOMPATIBILITY ***
+ - Added "bindtags" command so that new binding groups can be
+ defined for widgets and the evaluation order can be changed.
+ - When matching events to bindings, extra modifiers are now ignored,
+ as if "Any" were specified for every event. The "Any" modifier
+ is still recognized, but it is ignored and is deprecated.
+ *** POTENTIAL INCOMPATIBILITY ***
+ - In % sequences that print window identifiers (e.g. %a and %S), print
+ in hexadecimal rather than decimal, for consistence with "winfo id".
+ *** POTENTIAL INCOMPATIBILITY ***
+ - The "bind" command no longer supports the event types CirculateRequest,
+ ConfigureRequest, MapRequest, or ResizeRequest. These event types
+ are somewhat dangerous, and they never worked anyway.
+
+3/13/94 (bug fix) Fixed numerous problems with the "wm iconwindow" command.
+It appears that this command never really worked at all, but it should
+work OK now.
+
+3/14/94 (feature changes) Removed several obsolete features:
+ - Eliminated "enable" and "disable" widget commands for menus.
+ *** POTENTIAL INCOMPATIBILITY ***
+ - Eliminated "activate" and "deactivate" widget commands for buttons,
+ checkbuttons, radiobuttons, and menubuttons.
+ *** POTENTIAL INCOMPATIBILITY ***
+ - Removed -geometry option for frames and toplevels: it causes
+ problems when .Xdefaults files contain entries like
+ "*geometry: +0+0". Must use -width and -height instead.
+ *** POTENTIAL INCOMPATIBILITY ***
+ - Desupported "tkVersion" variable: use "tk_version" instead.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+3/16/94 (feature changes) Changes to listboxes:
+ - Eliminated -geometry option (it causes problems when .Xdefaults
+ files contain entries like "*geometry: +0+0"). Added -width
+ and -height options to use instead.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+3/21/94 (bug fix) Fixed bug in tkOption.c where the option cache wasn't
+properly cleaned up after window deletion; this could cause the wrong
+value from the option database to be used under some conditions.
+
+3/25/94 (new features) Changes to geometry management:
+ - Added Tk_MaintainGeometry and Tk_UnmaintainGeometry procedures
+ to solve problems with -in windows. Modified the packer, the
+ placer, and canvases to use them.
+ - Changed 2nd argument to Tk_ManageGeometry from Tk_GeometryProc *
+ to a pointer to a structure with additional information about
+ the geometry manager, such as name and procedure to call when
+ slaves are stolen.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+3/28/94 (new feature) Overhauled event management:
+ - Added "cancel" option to the "after" command so that you can
+ cancel previously-scheduled commands.
+ - Separated X-specific stuff from generic event management. The
+ file tkEvent.c can now be used stand-alone without the rest of Tk.
+ See the manual entry for Tk_EventInit for information on which
+ procedures are available this way.
+ - Added Tk_CreateFileHandler2 procedure, which provides a lower-level
+ and more powerful form of file event handler.
+ - Fixed bug in Tk_DoOneEvent where an infinite loop could occur if
+ the TK_FILE_EVENT and TK_DONT_WAIT flags were set simultaneously
+ (there were bugs with several other combinations too; all should
+ be fixed now).
+
+3/28/94 (new feature) Added "fileevent" command, which allows event-
+driven I/O in the style of Mark Diekhans' "addinput" command.
+
+4/11/94 (new feature) Better support for colormaps and visuals:
+ - Added new -colormap and -visual options to toplevels and frames.
+ - Added "winfo visualsavailable" command.
+ - Added "wm colormapwindows" command, plus support for WM_COLORMAP_WINDOWS
+ to Tk_SetWindowColormap.
+ - Added new library procedures Tk_GetVisual, Tk_GetColormap,
+ and Tk_FreeColormap.
+
+4/11/94 (bug fix) Fixed core dump that used to occur when specifying
+an iconwindow ("wm iconwindow") for a toplevel on a different screen
+than the main window.
+
+4/23/94 (new feature) Added support for images, including the following:
+ - New "image" command for creating images.
+ - Built-in image type: bitmap.
+ - New "image" item type in canvases.
+ - Labels, buttons, checkbuttons, radiobuttons, menubuttons, and
+ menu entries now support a -image option for displaying images.
+ - Tk_CreateImageType and Tk_ImageChanged procedures, for defining
+ new types of images in C.
+ - Tk_GetImage, Tk_FreeImage, Tk_RedrawImage, and Tk_SizeOfImage
+ procedures, for using images in widgets.
+
+5/1/94 (new features) Added new procedures Tk_3DVerticalBevel and
+Tk_3DHorizontalBevel.
+
+5/11/94 (new features) Major overhaul of text widgets:
+ - Implemented embedded windows and "window" widget command.
+ - Added new configuration options for tags: -justify, -lmargin1,
+ -lmargin2, -rmargin, -offset, -spacing1, -spacing2, and -spacing3.
+ See the "Display styles" widget demo for examples.
+ - Added new configuration options for texts: -spacing1, -spacing2,
+ and -spacing3.
+ - Added "tagList" option to "insert" widget command to control
+ tags on new text. Made tagged regions so they aren't sticky on
+ either side: new characters get a tag only if the old chars. on
+ both sides had it.
+ *** POTENTIAL INCOMPATIBILITY ***
+ - Added gravity for marks, and "mark gravity" widget command.
+ - Added horizontal scrolling, "xview" widget command, -xscrollcommand
+ option. Changed "scan" widget commands to support horizontal
+ scrolling.
+ *** POTENTIAL INCOMPATIBILITY ***
+ - Added "search" widget command for searching (either exact matches
+ or regular expressions).
+ - New widget commands: bbox, dlineinfo, and see.
+ - Changed implementation of bindings so that Enter and Leave
+ events are not generated unless the tag has just become present
+ (or just ceased to be present) on the current character. Also
+ changed bindings to process separately for each tag, rather than
+ having high-priority tags override low-priority ones.
+ - The "end" index now refers to the character after the last newline
+ rather than the newline itself. You can now tag the final newline
+ and set a mark after the final newline.
+ - Deletions of the "sel" tag and the "insert" and "current" marks
+ are now ignored silently, rather than generating errors. This means
+ you can do things like "eval .t tag delete [.t tag names]".
+
+5/19/94 (bug fix) Canvases didn't generate proper Postscript for stippled
+text.
+
+5/20/94 (new feature) Added "bell" command to ring the display's bell.
+
+5/20/94 (new feature) Incorporated "square" demonstration widget into
+tktest application.
+
+5/20/94 (new features) Changed wish application (tkMain.c):
+ - wish no longer processes the -help option.
+ *** POTENTIAL INCOMPATIBILITY ***
+ - The wish main program is now called Tk_Main; tkAppInit.c has a
+ "main" procedure that calls Tk_Main. This makes it easier to use
+ Tk with C++ programs, which need their own main programs, and it
+ also allows an application to prefilter the argument list before
+ calling Tk_Main.
+ *** POTENTIAL INCOMPATIBILITY ***
+ - The application's class is now the same as its name (except the
+ first letter is capitalized), instead of "Tk".
+ *** POTENTIAL INCOMPATIBILITY ***
+ - The -file keyword is no longer required: the script file name can
+ be provided as the first argument without being preceded by "-file",
+ as in tclsh. For backward compatibility the "-file" keyword is
+ ignored if it is the first argument, but it is deprecated.
+
+5/26/94 (feature removed) Removed support for "fill" justify mode from
+Tk_GetJustify and from the TK_CONFIG_JUSTIFY configuration option. None
+of the built-in widgets ever supported this mode anyway.
+*** POTENTIAL INCOMPATIBILITY ***
+
+5/27/94 (feature change) Changed Tk to use Tk_PrintDouble everywhere
+that it converts reals to strings. This means that floating-point
+values will be generated in some cases where integer-like values were
+generated before.
+*** POTENTIAL INCOMPATIBILITY ***
+
+6/1/94 (feature change) Renamed "pack newinfo" command to "pack info".
+The old "pack info" command is no longer available.
+*** POTENTIAL INCOMPATIBILITY ***
+
+6/20/94 (feature changes) Overhaul of entry widgets:
+ - Added "-justify" option.
+ - Added "-show" option to make entries easier to use for passwords.
+ - Added "cget" widget command.
+ - Added "selection range" and "selection present" widget commands.
+ - Added "anchor" symbolic index.
+ - Changed "-scrollcommand" option to "-xscrollcommand", "view"
+ widget command to "xview", for compatibility with other widgets.
+ *** POTENTIAL INCOMPATIBILITY ***
+ - Changed sel.last to refer to character just *after* last one
+ selected, again for compatibility with other widgets.
+ *** POTENTIAL INCOMPATIBILITY ***
+ - For "delete" widget command, second index now refers to character
+ just *after* last one to delete.
+ *** POTENTIAL INCOMPATIBILITY ***
+ - Overhauled bindings to be more Motif-compatible and to include
+ common Emacs bindings for editing.
+ - Changed -width option: if specified as 0, widget sizes to fit
+ its current text.
+
+6/11/94 (new features) Improved Motif compatibility:
+ - Added "-highlightwidth" and "-highlightcolor" options to all widgets.
+
+6/27/94 (bug fix) Postscript generation for text items in canvases was
+not justifying the text properly when a -width was specified that was
+longer than the longest line.
+
+6/27/94 (bug fix) "winfo exists" used to report a window as existing
+if it was in the process of being destroyed (i.e., a destroy handler
+is in the middle of execution). Changed to report it as non-existent
+under these conditions.
+*** POTENTIAL INCOMPATIBILITY ***
+
+7/11/94 (bug fix) Selections claimed via "selection own" weren't always
+being cleared properly when the selection was claimed away. Also fixed
+bug where Tk wasn't properly claiming the selection, if there haven't
+been any recent X events at the time of the claim.
+
+7/13/94 (feature changes) Overhaul of scrollbar widgets:
+ - New widget commands: "activate", "cget", "fraction", and "identify".
+ - New options: -activebackground, -activerelief, -highlightcolor,
+ -jump, -highlightthickness, and -troughcolor. What used to be
+ -background is now -troughcolor, -foreground is now -background,
+ and -activeforeground is now -activebackground.
+ *** POTENTIAL INCOMPATIBILITY ***
+ - Added new syntax for "set" command, "get" result, and generated
+ commands. Changed other widgets to use the new syntax.
+ - Moved the bindings out of C and into Tcl scripts, using the new
+ options and widget commands. Added support for all Motif
+ bindings, plus jump scrolling and cancelling of slider drags.
+
+7/16/94 (bug fix) Canvases assumed that the Leave event for one item
+didn't modify or delete the next current item; this could cause core
+dumps under some conditions.
+
+7/23/94 (feature change) Modified Tk_BackgroundError so that tkerror
+is invoked as an idle handler. If tkerror generates a break exception
+then all other queued reports are aborted.
+
+8/14/94 (bug fix) "cursorOffTime" and "cursorOnTime" were confused in
+canvases, resulting in the same time being used for both.
+
+8/16/94 (bug fix) "tkwait variable" command didn't detect errors in
+variable name, such as trying to wait for an entire array.
+
+9/2/94 (new features) Overhaul of scale widgets:
+ - Floating-point values are supported now, following Paul Mackerras'
+ "fscale" widget. Added "-resolution" and "-digits" options.
+ - Added "-variable" option to link scale to variable, following
+ Henning Schulzrinne's implementation.
+ - Added focus highlight (-highlightthickness and -highlightcolor
+ options).
+ - Added new widget commands "cget", "coords", "identify", plus
+ improved "get"; removed wired-in bindings, added complete set
+ of Motif bindings via Tcl scripts.
+ - Changed -sliderforeground option to -background, -background to
+ -troughColor, -activeforeground to -activebackground.
+ *** POTENTIAL INCOMPATIBILITY ***
+ - Moved value label from below horizontal scales to above the scale,
+ for Motif compliance.
+
+9/9/94 (bug fix) Fixed bug in tkWm.c that caused long delays in "raise"
+command under some conditions (window already at the top of the stack).
+
+9/10/94 (new features) Overhaul of label/button/checkbutton/radiobutton
+widgets:
+ - Added focus highlight (-highlightthickness and -highlightcolor
+ options).
+ - Added new widget command "cget".
+ - Changed -selector option to -selectcolor, and changed its meaning
+ too: empty no longer means don't draw the indicator; it means
+ don't use a special color when selected.
+ *** POTENTIAL INCOMPATIBILITY ***
+ - Added -indicatoron (controls whether indicator is displayed) and
+ -selectimage (gives special image to display when selected) options.
+ - Modified bindings to be more Motif-like, added binding for space
+ key.
+ - Changed padding defaults to give widgets correct Motif appearance
+ by default. Also, changed to ignore padding options when displaying
+ an image or bitmap.
+ *** POTENTIAL INCOMPATIBILITY ***
+ - Can now display text on multiple lines: newlines cause line breaks,
+ and word wrapping can be requested with -wraplength option. Also
+ added -justify and -underline options.
+ - The -value option for radiobuttons can now have an empty string as
+ its value; it no longer defaults to the name of the widget.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+9/13/94 (new features) Modified both canvases and messages to support
+-highlightthickness and -highlightcolor options plus "cget" widget
+command.
+
+9/19/94 (new features) Added Tk_UnsetGrid procedure, modified widgets
+to use it. Also changed Tk_SetGrid so that at most one window per
+toplevel can have gridding enabled.
+
+9/23/94 (new features) Major overhaul of listbox widgets:
+ - Added focus highlight (-highlightthickness and -highlightcolor
+ options).
+ - Added new widget command "cget".
+ - Revised selection commands to support single selections as well
+ as multiple disjoint selections; syntax of "selection" widget
+ command has changed to support this. Added new option -selectmode
+ for specifying which mode to use. Default is single selection;
+ tk_listboxSingleSelect procedure no longer exists. Selections
+ now return as items separated by newlines instead of a list whose
+ elements are the items.
+ *** POTENTIAL INCOMPATIBILITY ***
+ - Extended "get" widget command to allow many items to be retrieved
+ at once.
+ - Added "bbox" widget command for finding position of an element on
+ screen.
+ - Added "activate" command to mark element with traversal focus.
+ - Extended index mechanism to support new types of indices:
+ "active", "anchor", "@x,y".
+ - Added "see" widget command.
+ - Revised bindings to include all Motif features except for AddMode.
+ - If -width or -height option is <= 0, the widget requests a size just
+ large enough to hold all of its text.
+
+10/6/94 (new features) Overhaul of menubuttons:
+ - Added focus highlight (-highlightthickness and -highlightcolor
+ options).
+ - Added new widget command "cget".
+ - Added -indicatoron option to display option menu indicator.
+ - The -menu option must be a child of the menubutton.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+10/6/94 (new features) Overhaul of menu widgets:
+ - Added new widget commands "cget" and "entrycget".
+ - Changed the implementation of tear-off menus to be more
+ Motif-like; added -tearoff option for specifying whether
+ tearoff entry is displayed.
+ - Changed interpretation of "@y" index: it now returns the
+ closest entry, rather than "none" if y is outside the menu's
+ range.
+ *** POTENTIAL INCOMPATIBILITY ***
+ - The -menu option for a cascade entry must now be a child of
+ the menu.
+ *** POTENTIAL INCOMPATIBILITY ***
+ - Added "type" widget command, so that you can query the type of
+ an entry.
+ - Added -foreground, -activeforeground, -selectcolor, -indicatoron,
+ -image, and -selectimage options to menu entries.
+ - Changed "selector" menu option to "selectColor" for Motif compliance.
+ *** POTENTIAL INCOMPATIBILITY ***
+ - Added -relief option for menus, just for consistency with other
+ widgets (it was implicitly "raised" before).
+
+10/6/94 (feature change) Completely overhauled the bindings for menus
+and menubuttons. They now fit better with other Tk 4.0 facilities,
+such as the new binding mechanism, and they provide better Motif
+compliance (e.g. keyboard traversal of submenus). Also, the bindings
+now support option menus, popup menus, and proper Motif tear-off
+menus.
+
+10/6/94 (obsolete features) The procedures tk_menuBar and
+tk_bindForTraversal are no longer needed in Tk 4.0. They still exist
+for compability, but they do nothing.
+
+10/6/94 (new procedures) Added "tk_popup" procedure for posting a
+popup menu, and "tk_optionMenu" for creating an option menubutton
+and its associated menu.
+
+10/6/94 (change in name) The variable "tk_priv" has been renamed
+to "tkPriv" to reflect that fact that it is private to Tk now.
+This shouldn't cause any problems, since no-one except Tk should
+have been using it before anyway (right?).
+
+10/6/94 (bug fix) Fixed bug in texts where sometimes the text would
+stop tracking mouse motion (the "current" item wouldn't get updated)
+because the text widget missed a ButtonRelease event.
+
+10/20/94 (new features) Overhauled selection code to support multiple
+selections (primary, secondary, etc.) and multiple displays:
+ - Changed "selection" command to support new options such as
+ "-displayof" and "-selection". Old command formats are still
+ supported for compatibility, but they are no longer documented
+ and are deprecated.
+ - Changed procedures Tk_GetSelection, Tk_CreateSelHandler, and
+ Tk_ClearSelection to take additional "selection" argument.
+ *** POTENTIAL INCOMPATIBILITY ***
+ - Selection targets APPLICATION and WINDOW_NAME have been replaced
+ by TK_APPLICATION and TK_WINDOW.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+10/20/94 (new features) Added support for clipboard:
+ - New "clipboard" command.
+ - C procedures Tk_ClipboardClear and Tk_ClipboardAppend.
+ - Bindings for "cut", "paste", and "copy" for text and entry widgets,
+ plus "copy" binding for listboxes.
+
+10/24/94 (bug fix) Button widgets weren't checking for errors when
+setting the values of associated variables.
+
+11/3/94 (bug fix) Fixed bug whereby Tk would hang if "exit" was invoked
+from inside a <Destroy> binding.
+
+11/15/94 (new features) Overhaul of focus mechanism:
+ - Added support for multiple displays: separate focus windows are
+ kept for each display.
+ - Added support for keyboard traversal.
+ - Changed focus model so Tk keeps track of a focus window for each
+ top-level window and automatically sets the focus on Enter to the
+ top-level. Tk no longer synthesizes FocusIn and FocusOut events,
+ but just uses the standard X mechanisms. There is no "default"
+ focus window anymore; the focus reverts to top-levels by default.
+ *** POTENTIAL INCOMPATIBILITY ***
+ - Changed focus command: eliminated "focus default" and "focus none",
+ added "-displayof" and "-lastfor" options. An empty string is now
+ used to signify "no focus" instead of "none".
+ *** POTENTIAL INCOMPATIBILITY ***
+ - Added library procedures tk_focusNext, tk_focusPrev, and
+ tk_focusFollowsMouse.
+ - Removed obsolete Tk_CreateFocusHandler: must use FocusIn and
+ FocusOut events now.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+11/23/94 (new features) Overhaul of "send" command:
+ - Added support for multiple displays: -displayof option to "send".
+ - Added asynchronous sends: -async option to "send".
+ - Eliminated fixed timeouts on sends: as long as the target
+ application appears to exist, the send will wait for it.
+ - Stale entries get removed from the application registry now,
+ so "winfo interps" should never return non-existent applications.
+ - Can change the name of an application with "tk appname" command.
+ This is also the preferred way of querying the application name
+ now.
+ - The errorCode and errorInfo variables are now propagated back to
+ the sender now, so a full stack trace is available.
+ - Tk checks display security on each send now, instead of just during
+ initialization, so changes in the security status are seen immediately
+ by all applications.
+ - The above changes required changes to the data formats used for
+ communication between source and target applications, so Tk 4.0
+ applications cannot send to, or be sent from, Tk 3.6 applications.
+ *** POTENTIAL INCOMPATIBILITY ***
+ - The procedure Tk_RegisterInterp has been replaced with Tk_SetAppName.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+12/6/94 (cleanup) Eliminated "interp" argument to Tk_GetColorByValue,
+since it is no longer needed.
+*** POTENTIAL INCOMPATIBILITY ***
+
+12/7/94 (feature change) Changed the "wm" command so that top-level
+windows are now resizable by default. You can no longer specify
+empty arguments to "wm maxsize" and "wm minsize".
+*** POTENTIAL INCOMPATIBILITY ***
+
+12/8/94 (new feature) Added new "photo" image type using code provided
+by Paul Mackerras: currently supports only PPM "P6" format images.
+
+12/14/94 (new features) Canvas modifications:
+ - Modified the interfaces between generic canvas code and the item
+ types so that it's easy for people to write new item types outside
+ of Tk.
+ - Added support for transparent bitmap items: just specify an
+ empty string as the background color.
+ - Changed the "xview" and "yview" commands for canvases to use the
+ new scrolling syntax.
+ - Eliminated -scrollincrement option.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+12/14/94 (bug fix) Fixed bug where the dimensions of canvas arrowheads
+scaled during a "scale" widget command, but the scaling was only
+temporary and got lost on the next re-configure of the item. The
+correct behavior is for the arrowheads not to scale.
+
+-------------------- Release 4.0b1, 12/23/94 -------------------------
+
+12/26/94 (bug fix) Removed obsolete demos from Makefile (color, dialog,
+size), fixed "install" target.
+
+1/3/95 (bug fix) Fixed all procedure calls to explicitly cast arguments:
+implicit conversions from prototypes don't work when compiling under
+non-ANSI compilers. Tk is now clean under gcc -Wconversion.
+
+1/4/95 (bug fix) Used "screenX" without ever setting it in DisplayText
+in tkCanvText.c: caused tabs in canvas text items to get messed up.
+
+1/4/95 (bug fix) Canvases forgot to register the built-in types if
+Tk_CreateItemType was called before a canvas widget was created.
+
+1/4/95 (bug fixes) Fixed glitches in various text bindings:
+ - Up used to do nothing if the cursor was at 2.0.
+ - Right used to make the cursor invisible if it was just before
+ the final newline of the text.
+ - Control-t didn't conform to Emacs; made it conform to GNU Emacs.
+ - Deleted Control-x binding, since it doesn't conform to anything and
+ is confusing for Emacs users.
+
+1/4/95 (bug fixes) Changed Control-t for entries just as for texts (see
+above) an deleted Control-x for entries (see above).
+
+1/4/95 (bug fix) The packer didn't map slaves unless the master was mapped;
+this could cause slaves to get "lost" so that they weren't mapped until the
+master resized.
+
+1/5/95 (bug fix) Scrollbars weren't executing the proper code the first time
+the mouse entered the widget; this caused problems if tk_strictMotif was
+set.
+
+1/6/95 (bug fix) Fixed label/button/checkbutton/radiobutton/menubutton
+widgets to allow arbitrary screen distances when specifying -width and
+-height for an image or bitmap (the manual pages already documented this
+but the code didn't implement it).
+
+1/6/95 (new feature) Added very primitive support for input methods,
+as suggested by Martin Forssen. This should be enough for European
+character sets (Compose key) but it isn't near enough for Asian
+character sets.
+
+1/8/95 (bug fix) Fixed problem in canvas "xview" and "yview" commands
+where divide-by-zero errors could sometimes occur.
+
+1/8/95 (bug fix) New event handler didn't properly handle files for
+which both TK_READABLE and TK_WRITABLE were specified.
+
+1/11/95 (bug fix) Fixed bug with text selections: was returning count
+too high for data, causing bogus garbage to appear when selection was
+copied.
+
+-------------------- Release 4.0b2, 1/12/95 -------------------------
+
+1/27/95 (feature removal) Removed %D substitution from binding scripts:
+wasn't portable, shouldn't be used anyway.
+*** POTENTIAL INCOMPATIBILITY ***
+
+1/27/95 (new features) Added -displayof options to the commands
+"winfo atom", "winfo atomname", "winfo containing", "winfo interps",
+and "winfo pathname".
+
+1/27/95 (new feature) Added "idle" option to "after" command to run
+scripts as idle handlers.
+
+1/28/95 (new feature) Modified placer to make -x and -relx additive
+if you specify both. Same for -y and -rely, -width and -relwidth,
+and -height and -relheight. This makes it easy to make request such
+as "make .a 2 pixels larger than .b".
+*** POTENTIAL INCOMPATIBILITY ***
+
+1/28/95 (new feature) Improved auto-grab mechanism in canvases (which
+prevents current item from changing while a button is down): changed
+to report Enter and Leave events for the current item while a button
+is down. However, as before, no Enter events are reported for other
+items until the button goes up.
+
+1/28/95 (new feature) Bitmap images are now transparent if the -background
+is specified as an empty string (-maskdata and -maskfile are ignored in
+this case). This is also the default.
+
+1/28/95 (bug fix) Tk didn't support manufacturer- or site-specific keysyms
+such as SunAudioMute. Modified tkBind.c so that it uses XStringToKeysym
+in addition to its own hash table, so that all keysyms are now available.
+
+1/30/95 (feature change) Modified "clipboard append" so that it reclaims
+the clipboard selection if it had been previously lost, rather than just
+generating an error. This handles certain race conditions more cleanly,
+and also allows the use of programs like "xclipboard".
+
+1/30/95 (new feature) Added -xscrollincrement and -yscrollincrement
+options to canvases.
+
+1/31/95 (bug fix) Geometry management was broken if a particular geometry
+manager claimed a slave away from itself.
+
+1/31/95 (bug fix) Fixed bug in tkVisual.c where a visual with fewer bits
+than requested was being selected in preference to one with just the right
+number of bits.
+
+1/31/95 (bug fix) Texts weren't redisplaying the padding region properly
+after changes in -padx or -pady.
+
+1/31/95 (new features) More text improvements:
+ - Extended "insert" widget command for texts to allow multiple
+ text-tagList pairs in the same command.
+ - Added -nocase option to "search" widget command.
+ - Added -overstrike option to tags.
+ - Added tab stops, via -tabs option for widget and for tags.
+
+2/10/95 (bug fix) Modified all widgets to allow renaming of widget
+commands. Deleting a widget command will delete the widget.
+
+2/11/95 (new feature) Added -highlightbackground option to all widgets.
+
+2/14/95 (new feature) Added "insert" widget command for menus.
+
+2/15/95 (new feature) Modified text display code (for all widgets) to
+display well-known control characters like newline and backspace as
+\n or \b instead of \xa.
+
+2/15/95 (bug fix) Modified bitmap and photo image managers to delete
+the image command when the image is deleted. Also modified them to
+allow renaming of the image command, and to delete the image if the
+image command is deleted.
+
+2/15/95 (bug fix) Fixed text widgets to allow horizontal scrolling
+even if wrapping was enabled, if a line isn't entirely visible due to
+a large character or embedded window.
+
+2/16/95 (feature change) Added "postcascade" widget command to menus,
+changed "invoke" and "activate" not to post or unpost submenus. Also
+fixed bug in redisplay that tended to leave bits of garbage on menu
+when submenu unposted.
+*** POTENTIAL INCOMPATIBILITY ***
+
+2/16/95 (feature removal) Removed "snap back" behavior (slider
+snaps back to old position if you move the mouse outside the widet
+before releasing the button) from scrollbars and scales.
+
+2/16/95 (bug fix) The last line of a listbox wasn't being displayed if
+it was only partially visible.
+
+2/16/95 (new features) Added support for "-resolution 0" (no rounding
+of values) to scale widgets, plus smarter computation of how many digits
+to display.
+
+2/17/95 (bug fix) Fixed bug in text bindings for things like Shift-Left:
+didn't properly set the anchor position.
+
+2/20/95 (bug fix) Changed management of COLORMAP_WINDOWS property to
+add the toplevel implicitly to the end of the list if it wasn't already
+on the list somewhere. Without this, some window managers implicitly
+put it at the front of the list, so that colormaps in internal windows
+are never used.
+
+2/20/95 (bug fix) Changed to use separate command procedures for
+button, checkbutton, label, and radiobutton commands. This allows the
+class commands to be renamed without breaking their behavior.
+
+2/20/95 (removed feature) The "bind" command no longer supports
+"Keymap" events; they never worked anyway.
+
+2/20/95 (bug fix) The text "search" widget command looped infinitely
+when searching an empty text.
+
+2/20/95 (bug fix) Canvases weren't redrawing their borders after
+configuration changes.
+
+2/20/95 (upgrade) Changed to use autoconf version 2.2.
+
+2/21/95 (bug fix) Fixed several bug fixes in menu bindings that occur
+when menus have no entries.
+
+2/21/95 (bug fix) Fixed bug in geometry management that caused windows
+packed -in siblings to not always be mapped and unmapped properly
+(particularly when the toplevel got unmapped and mapped).
+
+2/22/95 (bug fix) Fixed resource leak problem in tkTextDisp.c that
+caused embedded windows not to be unmapped when off-screen.
+
+2/23/95 (bug fix) "After cancel" dumped core when the script for an
+after event cancelled itself.
+
+2/24/95 (bug fix) Text and entry widgets weren't properly ignoring
+Alt-, Control-, and Meta- keystrokes, so a widget-specific binding
+for one of these resulted in the character also being inserted.
+
+2/24/95 (bug fix) Several widgets accidentally performed unsigned
+division on negative numbers, thereby losing the sign bit. This
+mostly affected the display of images and bitmaps in buttons,
+menubuttons, and messages.
+
+2/24/95 (feature reversal) Restored old behavior of %A so that it
+returns non-printing characters as well as printing ones now.
+*** POTENTIAL INCOMPATIBILITY with Tk 4.0b2, but not with Tk 3.6 ***
+
+2/24/95 (bug fix) Duplicate "leave" events could occur for canvas
+items under some conditions, due to recursive calls to PickCurrentItem.
+Added code to detect and skip the nested calls.
+
+2/24/95 (bug fix) Fixed bug where an error could occur during the first
+keystroke in an application if its binding invoked "break".
+
+2/25/95 (new feature) Modified syntax of "search" widget command for
+texts. The -nowrap switch and the "variable" final argument are no
+longer supported. Instead, there is a -count switch to replace
+the final argument; if the final argument is specified, it is now
+a stopping index for the search. The features of -nowrap can be
+achieved now with the stopping index.
+*** POTENTIAL INCOMPATIBILITY with Tk 4.0b2, but not with Tk 3.6 ***
+
+2/27/95 (bug fix) Fixed problem that appears to prevent keyboard
+input for working under IRIX: tkBind.c was ignoring XmbLookupString
+calls that returned a status of XLookupBoth.
+
+2/27/95 (new feature) Added Tk_GetItemTypes procedure to return
+information about available canvas item types.
+
+2/27/95 (feature change) Changed Makefile to always use install-sh
+for installations: there's just too much variation among "install"
+system programs, which makes installation flakey.
+
+2/27/95 (bug fix) Fixed bug in tkSend.c that caused core dumps if
+the app's main window was destroyed by a destroy handler on a
+child.
+
+3/5/95 (feature change) Change separator character used in "bind +..."
+bindings from semi-colon to newline (permits bindings that are
+comments, for what that's worth).
+
+3/7/95 (bug fix/feature change) Overhauled focus code, both in C
+and in Tcl:
+ - Tk won't move the X focus in response to the "focus" command
+ unless either the application already has the focus or the
+ -force switch is specified.
+ - Tk no longer sets the X focus to anything other than top-levels;
+ it synthesizes events for FocusIn and FocusOut to children.
+ - A window no longer has to be viewable when focussed to; Tk will
+ set the X focus later, when the window becomes viewable.
+ - Added -takefocus option to all widgets.
+ - Rewrote tk_focusPrev and tk_focusNext to use the -takefocus option.
+ These procedures no longer set the focus; they just return the
+ next window in focus order.
+ *** POTENTIAL INCOMPATIBILITY with Tk 4.0b2, but not with Tk 3.6 ***
+ - Eliminated tk_focusContinue.
+ *** POTENTIAL INCOMPATIBILITY with Tk 4.0b2, but not with Tk 3.6 ***
+
+3/8/95 (new feature, bug fix) Added support for tk_strictMotif variable
+in C: Tk_StrictMotif library procedure. Modified buttons, menubuttons,
+menus to use it. This fixes the problem with menus not supporting
+tk_strictMotif properly in Tk4.0b1 and b2.
+
+3/16/95 (feature overhaul) Overhauled color management:
+ - Changed Tk so it never denies a color request because a colormap
+ filled up. Instead, it allocates the closest available color.
+ - Eliminated "color model" mechanism. The "tk colormodel" command
+ is gone, as are the procedures Tk_GetColorModel and Tk_SetColorModel.
+ *** POTENTIAL INCOMPATIBILITY ***
+ - Changed 3D border implementation to allocate colors for shadows
+ lazily, so they're never allocated if they're never used. Also
+ added new feature whereby stippling is used for borders when
+ the colormap has run out of entries. Changed arguments to many
+ of Tk_3D C procedures to take a Tk_Window as argument instead of
+ a (Display *). This is needed to do lazy color allocation.
+ *** POTENTIAL INCOMPATIBILITY ***
+ - Eliminated colormap argument to Tk_GetColor, Tk_GetColorByValue,
+ and Tk_Get3DBorder.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+3/16/95 (feature change) Event bindings created from Tcl will now ignore
+Enter, Leave, FocusIn, and FocusOut events with detail NotifyInferior.
+This is done in anticipation of mega-widgets, so that the user of a
+mega-widget can create Enter/Leave bindings on the mega-widget without
+seeing spurious events as the mouse moves among the windows in the
+mega-widget.
+*** POTENTIAL INCOMPATIBILITY ***
+
+3/17/95 (feature change) Changed C interfaces throughout Tk to use ints
+instead of unsigneds: the unsigneds turn out to cause subtle problems
+with arithmetic in some places, and using ints everywhere is just
+simpler.
+*** POTENTIAL INCOMPATIBILITY ***
+
+3/23/95 (bug fix) Selections longer than 4000 bytes were being
+truncated to 4000 bytes.
+
+-------------------- Release 4.0b3, 3/24/95 -------------------------
+
+3/25/95 (bug fix) Changed "install" to "./install" in Makefile so that
+"make install" will work even when "." isn't in the search path.
+
+3/25/95 (bug fix) Modified Tk's selection mechanism to prevent core
+dumps in other applications during retrievals of large selections
+(this is actually a bug in the other apps, but I've patched Tk to
+keep it from getting triggered).
+
+3/25/95 (bug fix) Fixed bug where X window for "." wasn't being
+deleted.
+
+3/27/95 (bug fix) Fixed many bugs associated with having more than
+one application in a single process.
+
+3/28/95 (bug fix) The "search" widget command for texts didn't
+return the correct index and count if there were embedded widgets
+on the same line as the returned range but before the end of
+the range.
+
+3/28/95 (bug fix) Changed pasting via button 2 in text and entries
+so that it inserts at the pointer location, not the location of
+the insertion cursor.
+
+3/28/95 (bug fix) Fixed several bugs related to <Destroy> bindings
+that delete ancestors in the window hierarchy. Also eliminated
+extraneous calls to XDestroyWindow, which speeds up window deletion
+by about 3x.
+
+3/28/95 (bug fix) Several widgets (buttons, menubuttons, menus) didn't
+properly handle image deletions that occurred while the widget was
+being deleted (caused core dumps).
+
+3/29/95 (bug fix) When retrieving long selections from text widgets,
+parts of lines were getting duplicated in the selection information.
+
+4/1/95 (bug fix) Fixed bug that caused infinite loop in horizontal
+scales with 0 range.
+
+4/1/95 (bug fix) Fixed problem with -command option for scrollbars and
+-takefocus option that caused commands to be evaluated in the wrong
+context.
+
+4/1/95 (bug fix) Fixed problem with option database that caused it to
+sometimes use the wrong option (wasn't flushing the database properly
+after a change in a window's class).
+
+4/1/95 (bug fix) If a line in a text widget just barely fit in the window,
+Tk was allocating a second screen line just for the newline character.
+
+4/1/95 (new feature) When backspacing in an entry widget, when you reach
+the left edge of the widget, the insertion cursor gets recentered.
+
+4/1/95 (new features) Added "winfo pointerx" and "winfo pointery" commands
+to fetch the current pointer position.
+
+4/6/95 (bug fix) If the last line of a text widget was only partially
+visible, it was counted as visible for purposes of the scrollbar. Now
+it is treated as if it were off-screen for scrolling purposes.
+
+4/6/95 (new feature) Modified "bell" command to reset screen saver as well.
+
+4/6/95 (feature change) Modified menu scanning (where menus pull down
+as you drag across their menubuttons) so it only works among menus
+in the same toplevel; it used to work for any menubuttons in the
+application.
+
+4/6/95 (bug fix) Canvas text items weren't allowing real numbers in
+"@x,y" notation for specifying indices.
+
+4/7/95 (bug fix) Menus didn't display correctly when -activeborderwidth
+was large.
+
+4/7/95 (bug fix) Changed "clipboard append" command to support -- option
+and to always treat the last argument as data, even if it starts with
+"-".
+
+4/17/95 (new feature) Added -wrap option to text tags.
+
+4/18/95 (bug fix) Listboxes and texts weren't updating their grid information
+when -width or -height changed.
+
+4/18/95 (bug fix) "Down" didn't work right in text widgets if the last
+line was only partially visible in the window.
+
+4/19/95 (bug fix) Listboxes didn't handle partially visible last lines
+right: couldn't scroll it into full visibility, for example.
+
+4/20/95 (bug fix) If a toplevel was positioned with a command like
+"wm geometry . -0-0", the window didn't reposition itself to maintain
+that geometry after a size change.
+
+4/21/95 (feature change) Changed order of binding tags so widget bindings
+fire before class bindings. New order is: widget, class, toplevel, all.
+*** POTENTIAL INCOMPATIBILITY with Tk 4.0b3, but not with Tk 3.6 ***
+
+4/23/95 (new feature) Added "winfo colormapfull" command.
+
+4/23/95 (new feature) Buttons and radiobuttons and checkbuttons now
+treat Return the same as Space, unless tk_strictMotif is set.
+
+4/23/95 (bug fix) Modified menu tear-off procedure to duplicate the
+binding tags and bindings of the original in the copy.
+
+4/25/95 (bug fix and feature change) Modified mechanism for choosing
+"best" visual to fix a bug where depth wasn't really getting highest
+priority in all situations.
+
+4/28/95 (bug fix) Failed text searches starting at "end" could result
+in an infinite loop in Tk.
+
+4/30/95 (new feature) Added "wm resizable" command to enable and
+disable interactive resizing.
+
+4/30/95 (new feature) Added "window names" widget command to texts:
+returns a list of all embedded windows.
+
+5/2/95 (feature change) Changed text searches so that forward searches
+start at the given index, rather than the character just after the
+given index.
+*** POTENTIAL INCOMPATIBILITY with Tk 4.0b3, but not with Tk 3.6 ***
+
+5/4/95 (bug fix) Default bit gravity for windows was wrong (it was
+ForgetGravity) causing unnecessary flashing when windows were resized.
+
+5/4/95 (feature change) Modified Tk_DoOneEvent so that it doesn't
+sleep if there's nothing that will wake it up again (e.g. no file
+or timer handlers). Returns 0 immediately.
+
+5/5/95 (configuration change) Changed to use BSDgettimeofday instead
+of gettimeofday on systems like IRIX where BSDgettimeofday is
+available. This avoids compilation problems due to the different
+interface to gettimeofday provided by IRIX.
+
+5/5/95 (feature change) Changed binding mechanism so that all bindings
+are created immediately at initialization time, rather than waiting
+until the first FocusIn or Enter event for a class.
+
+5/6/95 (feature change) Changed default text for labels, buttons,
+checkbuttons, radiobuttons, menubuttons, and messages from " " to
+"".
+
+5/6/95 (bug fix) If the application was destroyed in the middle of
+an "update" command, Tk would dump core.
+
+5/6/95 (bug fix) Changed manual entries to use the standard .TH
+macro instead of a custom .HS macro; the .HS macro confuses index
+generators like makewhatis.
+
+5/6/95 (bug fix) Change "wm iconwindow" command to disable button
+presses for the icon window. This is needed so that the window
+manager can get those events (X only allows button presses to go
+to one client for a given window).
+
+5/9/95 (new feature) When specifying visuals, can now use "best"
+with a depth, e.g. "-visual {best 8}" to get the best 8-bit visual.
+
+5/18/95 (bug fix) Fixed bug with -spacing* options for text widget:
+screen distances weren't allowed, only integers.
+
+5/20/95 (bug fix) Eliminated memory leaks in tkTextDisp.c and elsewhere.
+
+5/22/95 (color change) Changed the Tk color palette to a gray scheme.
+Also added a library procedure tk_setPalette that makes it easy to
+change colors on the fly, and a procedure tk_bisque that restores the
+previous light brown scheme.
+
+5/28/95 (bug fix) Modified canvases so that the -width and -height
+options refer to the space inside the borders, not the total widget
+space. Also changed "xview" and "yview" commands and scroll-increment
+rounding to use the pixel just inside the borders, rather than (0,0).
+
+5/28/95 (bug fix) Several widgets (e.g. entries, buttons, and menus)
+didn't properly handle unsets of variables they were tracing, if the
+variables were reference through upvars in procedures.
+
+6/4/95 (bug fix) The placer wasn't rounding window widths right when
+both -relx and -relwidth were specified (or -rely and -relheight) so
+that rounding errors accumulated.
+
+6/4/95 (feature improvement) Change parsing of text indices to handle
+weird mark and tag names better (e.g. any string ending with ".first"
+will now be parsed as a tag name, even if it contains embedded spaces,
+etc.).
+
+6/4/95 (feature change) If a font defines glyphs for control characters,
+they are now displayed, instead of translating the character to a
+backslash sequence (however, tabs and newlines are still treated
+specially; glyphs are not displayed for these characters).
+
+6/4/95 (bug fix) Modify the implementation of "raise" and "lower" for
+toplevels so that it now works under olwm and olvwm. It didn't use to
+work, and the problem is really in the window manager, but Tk now
+patches around it. However, only "total" raises and lowers work:
+raising and lowering relative to a sibling still don't work under
+olvwm and olwm.
+
+6/4/95 (feature change) Modified tab code in texts so that a tab always
+occupies at least as much space as a space character.
+
+6/4/95 (bug fix) The "%t" substitution wasn't being made properly in
+Enter and Leave event bindings.
+
+6/7/95 (new feature) Added support for GIF images. Unfortunately it's
+a bit fragile: certain kinds of badly formed images can cause core
+dumps; I don't know enough about the GIF reader (taken from giftoppm)
+to figure this out.
+
+6/7/95 (bug fix and feature change) Fixed PPM image reader to be more
+flexible about header formats, and added support for PGM images.
+
+6/7/95 (feature change) Added -outlinestipple option to canvas arc
+items, changed "-style arc" to use -outline as the color instead of
+-fill (the old approach was pretty quirky).
+*** POTENTIAL INCOMPATIBILITY ***
+
+6/8/95 (feature change) Modified interface to Tk_Main to pass in the
+address of the application-specific initialization procedure.
+Tcl_AppInit is no longer hardwired into Tk_Main. This is needed
+in order to make Tcl a shared library.
+
+6/8/95 (feature change) Modified Makefile so that the installed versions
+of wish and libtk.a have version number in them (e.g. wish4.0 and
+libtk4.0.a) and the library directory name also has an embedded version
+number (e.g., /usr/local/lib/tk4.0). This should make it easier for
+Tk 4.0 to coexist with earlier versions.
+
+6/9/95 (new feature) Added -outline and -width options to canvas polygon
+items.
+
+6/9/95 (feature changed) Renamed -decimate in photo widget to -subsample
+(decimate wasn't technically correct).
+*** POTENTIAL INCOMPATIBILITY with Tk 4.0b3, but not with Tk 3.6 ***
+
+-------------------- Release 4.0b4, 6/16/95 -------------------------
+
+6/19/95 (bug fix) Colors weren't being rounded correctly in canvas
+Postscript generation: caused "white" to appear slightly gray when
+the display of the canvas used only 8 bits per color.
+
+6/20/95 (bug fix) "bbox" widget command for texts didn't return
+proper width for tabs.
+
+6/20/95 (bug fix) Scrollbars didn't always work right for texts:
+couldn't scroll all the way to the bottom of the text in a single
+drag of the slider.
+
+6/20/95 (new feature) Added "delta" widget command for scrollbars
+(needed for above bug fix).
+
+6/23/95 (bug fix) Listboxes weren't properly redisplaying their
+borders when the were configured to a smaller size.
+
+6/23/95 (new feature) Added "winfo server" command.
+
+6/23/95 (bug fix) If a menu was posted, couldn't switch to another
+menu with an Alt- key.
+
+6/24/95 (new feature) Added "winfo pointerxy" command.
+
+6/25/95 (bug fix) Tk_ParseArgv referenced beyond the end of 0-length
+option names.
+
+6/25/95 (bug fix) Fixed problem in tkOption.c where "cachedWindow"
+could get garbage in it if the main window's class was changed by
+calling Tk_SetClass.
+
+6/25/95 (bug fix) Fixed two bugs in menus, one where errors in
+variable traces weren't propagated correctly and one where "invoke"
+was invoked at the wrong stack level, with the result that variable
+traces didn't have access to the right variables.
+
+6/27/95 (bug fix) tk3d.c wasn't using all the right information
+when deciding whether or not to stipple borders, so it stippled
+borders even on 16-bit true-color displays.
+
+6/28/95 (bug fix) Page up and down operations in texts could cause
+insertion cursor to drift to the right. Changed tkTextScrollPages
+to use upper-left corner of current character, rather than center
+of character.
+
+6/28/95 (bug fix) Changed text widget so that you can't put the
+insertion cursor after the last newline in the text.
+
+6/28/95 (bug fix) Bitmap images didn't allow ~'s in file names.
+
+6/28/95 (bug fix) Fixed problem that could cause core dumps in the
+text widget when dealing with embedded windows (there were problems
+if the act of redisplaying caused the window layout to change, which
+can happen with embedded windows).
+
+6/28/95 (bug fix) Texts didn't handle indices with double negatives,
+such as ".t mark set insert {insert + -20 chars}".
+
+6/28/95 (bug fix) Fixed problem where focus didn't always revert to
+its prior window after a dialog box was dismissed.
+
+6/28/95 (bug fix) Fixed problem with "search" widget command returning
+incorrect length on some backwards regexp searches.
+
+6/28/95 (bug fix) Successive "wm iconbitmap . {}" commands could cause
+a core dump.
+
+6/29/95 (new feature) Added -elementborderwidth option for scrollbars
+so the -borderwidth can be set to 0 without flattening the arrows and
+slider.
+
+-------------------- Release 4.0, 7/1/95 -------------------------
+
+7/18/95 (bug fix) %t in event bindings didn't work properly for some
+events (e.g. PropertyNotify).
+
+7/18/95 (bug fix) Changed "exec wish" lines in demo scripts to
+"exec wish4.0" to avoid version conflicts.
+
+7/18/95 (bug fix) Fixed round-off errors in scrolling for texts,
+canvases, listboxes, and entries. The error could cause the view
+to shift up in a command like "$w yview moveto [lindex [$w yview] 0]".
+
+7/19/95 (bug fix) Canvases weren't always redrawing borders correctly
+when they became unobscured. There were also some problems with
+improper refresh after size changes.
+
+7/19/95 (bug fix) Fixed bug in text index processing that causes
+tests textIndex-11.1 and textIndex12.1 to fail on some platforms.
+
+7/19/95 (bug fix) Fixed bug where 2-second delays were ocurring during
+"raise" and "lower" commands for toplevel windows under some window
+managers (such as fvwm).
+
+7/20/95 (bug fix) Text searches were misbehaving when there were embedded
+windows on the starting line of the search. The most common symptom is
+that Tk would fail to find a match at the starting position for the
+search.
+
+7/22/95 (bug fix) Fixed core dump that could occur in menus if a checkbutton
+entry's -variable option referred to an array (or couldn't be read
+by the menu C code for some other reason).
+
+7/22/95 (bug fix) Text widgets didn't update their scrollbars when
+changes were made to information that was off-screen.
+
+7/25/95 (bug fix) Fixed core-dump in tkListbox.c that used to happen
+in the command ".l bbox end" if the listbox was empty.
+
+7/25/95 (bug fix) Page-up and page-down bindings for listboxes didn't
+move active element to remain on the screen.
+
+7/25/95 (bug fix) Patched around H-P compiler problem that results in
+core-dumps in tkImgPhoto.c during image handling.
+
+7/25/95 (bug fix) Fixed bug in tkImgPhoto.c that caused core dumps
+(during Tk self-tests and other image uses) on AIX and other machines
+where "schar" in tkImgPhoto.c was being defined as "short" instead of
+"char".
+
+7/26/95 (bug fix) The PPM image reader couldn't handle maximum intensity
+values other than 255.
+
+7/26/95 (bug fix) Canvases didn't redraw their borders when the relief
+changed from raised to flat.
+
+7/27/95 (bug fix) Canvases didn't set the scrolling values correctly
+when no scroll region was specified.
+
+7/28/95 (bug fix) Modified menu and tk_dialog scripts to restore any
+old grab that might have been in effect before a menu or dialog was
+posted.
+
+----------------- Released patch 4.0p1, 7/29/95 ----------------------
+
+8/4/95 (bug fix) Calls to toupper and tolower weren't using the UCHAR
+macro, so they didn't always work in non-U.S. locales. (JO)
+
+8/14/95 (new feature) Added -tearoffcommand option for menus.
+
+8/16/95 (bug fix) Canvases didn't generate proper Enter and Leave
+events if the Leave handler for an item reconfigured the canvas in
+a way that made the old current item the new current item again. (JO)
+
+8/21/95 (bug fix/feature change) When -takefocus was a script, Tk
+was allowing window viewability to override it. Changed so that
+viewability is now ignored when -takefocus is a script. (JO)
+
+8/21/95 (bug fixes) Fixed memory leaks in tkSend.c, tkSelect.c, and
+tkUnixWm.c (JO).
+
+8/21/95 (bug fix) Text widgets didn't handle commands like
+".t search -backwards foo end 1.0" properly: never found foo. (JO)
+
+8/23/95 (new feature) Added Makefile and configure.in support for
+dynamic loading. (JO)
+
+8/25/95 (bug fix) The "frame" and "toplevel" commands couldn't safely
+be renamed, due to a kludgy way that they shared a single command
+procedure. Split into separate procedures. (JO)
+
+8/25/95 (bug fix) Fixed bug in libary/menu.tcl that caused "grab
+window not visible" errors for popup menus (and perhaps elsewhere?). (JO)
+
+8/25/95 (bug fix / new feature) The "gray25" bitmap was really only
+12.5% on, not 25%. Added new "gray12" bitmap that is the same as the
+old "gray25". "Gray25" is still supported for compatibility, but its
+use is deprecated. (JO)
+
+8/25/95 (bug fix) Scrollbar bindings didn't properly handle case where
+B2 is clicked while B1 is already down. (JO)
+
+8/26/95 (bug fix) Menus were ignoring -activebackground if tk_strictMotif
+was set, but not -activeforeground. Changed to ignore both. (JO)
+
+8/26/95 (bug fix) Scales and scrollbars didn't properly handle a
+-repeatdelay value of 0 (they shouldn't auto-repeat in this case). (JO)
+
+8/28/95 (bug fix) Tcl errors were occurring for tkPriv(oldGrab) when
+clicking on a disabled option menu. (JO)
+
+8/28/95 (bug fix) Changed event-handling code to use FD_SETSIZE instead
+of OPEN_MAX, since OPEN_MAX is incorrect on some systems (e.g., IRIX). (JO)
+
+8/28/95 (bug fix) Fixed bug in photo images that caused garbling of
+image data in the "put" and "copy" commands if the source data had
+only one scan line but had a width less than the width of the target
+image. (JO)
+
+8/29/95 (bug fix) Tk used to refuse to post menus if they had no
+entries. This made it impossible for a menu to fill itself the first
+time it is posted. Changed to allow menus with no entries to be
+posted. (JO)
+
+8/30/95 (bug fix) If there was extra space at the bottom of a menu,
+it wasn't being redisplayed properly.
+
+8/30/95 (new feature) Added -transient option to menus.
+
+8/30/95 (new features) Added proper button 2 support to both scrollbars
+and scales (it sets the slider position from the mouse position). (JO)
+
+8/30/95 (bug fix) Fixed potential core dump that could occur in
+photo images (ReadPPMFileHeader could overflow buffer under some bad
+inputs, such as certain GIF images). (JO)
+
+8/30/95 (bug fix) Errors of the form `syntax error in expression "!"'
+could occasionally happen in tkScaleDrag. (JO)
+
+8/31/95 (new feature) Changed man page installation (with "mkLinks"
+script) to create additional links for manual pages corresponding to
+each of the procedure and command names described in the pages. (JO)
+
+9/1/95 (new feature) Added "after info" command. Also added checks
+so that one interpreter can't cancel another's "after" events. (JO)
+
+9/8/95 (bug fix) Fixed bug that could cause memory corruption and core
+dumps if a "fileevent" handler was deleted while the handler was
+active. (JO)
+
+9/11/95 Reorganized Tk sources for Windows and Mac ports. All sources
+are now in subdirectories: "generic" contains sources that work on all
+platforms, "windows", "mac", and "unix" directories contain platform-
+specific sources. (SS)
+
+9/11/95 (new feature) Added new "notifier" mechanism to allow multiple
+implementations of the mechanisms for finding out about events. This
+change was necessary to support Mac and PC platforms, but it may also
+allow other goodies such as combining Xt and Tk widgets in a single
+application. See the new manual entry Notifier.3 for details. (SS)
+
+9/11/95 (feature change) Changed interface to Tk_RestrictProc so that
+(a) it takes a clientData argument instead of display and arg, and
+(b) it returns a value that can ask for the event to be discarded as well
+as deferred or processed. (SS)
+*** POTENTIAL INCOMPATIBILITY ***
+
+9/11/95 (new feature) Added TK_WINDOW_EVENTS #define, which is equivalent
+to TK_X_EVENTS but is now preferred, since it applies to all platforms. (SS)
+
+9/11/95 (feature change) Can't export variables anymore because this doesn't
+work under Windows DLLs. Eliminated tk_NumMainWindows variable and replaced
+with procedure Tk_GetNumMainWindows. (SS)
+*** POTENTIAL INCOMPATIBILITY ***
+
+9/11/95 (new feature) Added procedure Tk_PreserveColormap to increment
+the reference count on colormaps. Used in photo widgets. (SS)
+
+----------------- Released patch 4.0p2, 9/15/95 ----------------------
+
+----------------- Released 4.1a1, 9/15/95 ----------------------
+
+9/22/95 (renamed files) Changed the names of the bitmap images in the
+$tk_library/demos/images directory to use the .bmap file extension. (RJ)
+
+9/22/95 (bug fix) Fixed bug where text widgets could occasionally
+display the insertion cursor both at the end of one line and the
+beginning of the next. (JO)
+
+9/25/95 (bug fix) Fixed bug that could cause core dumps when an
+application uses multiple screens and a binding destroys the main
+window (bind code was using MainInfo structure after it had been
+freed). (JO)
+
+9/25/95 (bug fix) Text widgets sometimes scrolled backwards on
+occasion if you dragged down past the bottom of the scrollbar. (JO)
+
+9/25/95 (bug fix) Fixed bug in menus where a cascaded submenu posted
+from a torn-off menu could be left posted if mouse was pulled off the
+end of the cascade and released. (JO)
+
+9/25/95 (new feature) Added "--" switch to wish, so that you can
+pass arguments like -n through to a script without having wish
+interpret them. (JO)
+
+9/25/95 (bug fix) Fixed core dump that could occur for radiobuttons
+and selectbuttons if -selectcolor was an empty string. (JO)
+
+9/26/95 (bug fix) Entries didn't used to notice if a trace procedure
+on the -textvariable overrode a new value set by the entry. This
+could cause the variable to get out of sync with the contents of the
+entry. (JO)
+
+9/26/95 (new feature) Added -sliderrelief option to scales, changed
+default bindings to change the slider's relief to sunken while it's
+being dragged with the mouse. (JO)
+
+9/26/95 (bug fix) TkColor.c wasn't computing colormap size correctly;
+could result in X Protocol error for QueryColors when colormaps run
+out of colors. (JO)
+
+9/26/95 (bug fix) Wish couldn't handle script files with spaces in
+their names. (JO)
+
+9/27/95 (cosmetic clean-up) Removed extraneous spaces to make error
+messages consistent: ": should be" is now ": should be". (JO)
+
+9/27/95 (feature change) Modified tk_dialog so that it uses the
+option database for the -wraplength option on the message. This
+allows the option to be overridden by the caller. (JO)
+
+9/28/95 (bug fix) Wish incorrectly parsed the command line under
+Windows, causing backslashes to be substituted. (SS)
+
+9/28/95 (bug fix) Wish now sources wishrc.tcl instead of .wishrc. (SS)
+
+9/28/95 (bug fix) Tk_DoOneEvent returned 0 under some circumstances
+when it was possible to find more work to do. For example, if a
+signal interrupted select(), but no event handlers were triggered, it
+would return 0 even though it could still detect events by reentering
+select(). (SS)
+
+9/29/95 (bug fix) "winfo interps" caused a crash under Windows. (SS)
+
+10/1/95 (feature change) Eliminated Tk_NotifyIdle interface in favor of
+Tk_IdlePending. (SS)
+
+10/1/95 (bug fix) Turned motion event collapsing into an idle handler
+so it will be easier to move the event loop into Tcl. (SS)
+
+10/1/95 (bug fix) Fixed several problems with negative coordinates
+in canvases. One example: dragging a canvas rectangle with a wide
+border and fractional coordinates could leave junk on the screen
+if the rectangle was in negative coordinate space. (JO)
+
+10/2/95 (bug fix) Tk was improperly handling Enter/Leave events
+during a button grab. (SS)
+
+10/2/95 (new feature) Added support for the Macintosh do script
+('dosc') event. Available only on the Macintosh. (RJ)
+
+10/4/95 (new feature) Added support for compiling with VC++.
+Resulting binaries work under Win32s through NT.
+
+----------------- Released 4.1a2, 10/6/95 ----------------------
+
+10/10/95 (new feature) Macintosh Tk now supports the complete set
+of X cursors that Unix Tk supports. (RJ)
+
+10/11/95 (bug fix) Tk now supports all of the X11 cursors under
+Windows. (SS)
+
+10/11/95 (bug fix) The "wm resizable" command was missing from the
+Windows version of Tk. (SS)
+
+10/12/95 (bug fix) Macintosh Tk had problems with clipping toplevel
+windows that children of any frame other than another toplevel. (RJ)
+
+10/13/95 (bug fix) Eliminated dependency on MKS toolkit for generating
+the tk.def file from Borland object files. (SS)
+
+10/16/95 (bug fix) Fixed clipping and update problems relating to
+the raising and lowering of overlapping windows on Mac. (RJ)
+
+10/30/95 (bug fix) When focus-follows-mode (invoked via tk_focusFollowsMouse),
+was focussing on windows even in situations where keyboard traversal would
+skip the window. Changed to use the tkFocusOK procedure so that the
+criteria for focussing are the same in both modes. (JO)
+
+11/2/95 (bug fix) Changed listbox bindings to ignore double-clicks.
+This avoids errors that used to occur if a user defined a binding
+for double-click that deleted the listbox. (JO)
+
+11/3/95 (feature change) Moved most of the Tk event loop to Tcl. Many
+Tk_ names have become Tcl names now:
+
+TK_READABLE => TCL_READABLE
+TK_WRITABLE => TCL_WRITABLE
+TK_EXCEPTION => TCL_EXCEPTION
+TK_DONT_WAIT => TCL_DONT_WAIT
+TK_WINDOW_EVENTS => TCL_WINDOW_EVENTS
+TK_FILE_EVENTS => TCL_FILE_EVENTS
+TK_TIMER_EVENTS => TCL_TIMER_EVENTS
+TK_IDLE_EVENTS => TCL_IDLE_EVENTS
+TK_ALL_EVENTS => TCL_ALL_EVENTS
+Tk_IdleProc => Tcl_IdleProc
+Tk_FileProc => Tcl_FileProc
+Tk_TimerProc => Tcl_TimerProc
+Tk_TimerToken => Tcl_TimerToken
+Tk_BackgroundError => Tcl_BackgroundError
+Tk_CancelIdleCall => Tcl_CancelIdleCall
+Tk_CreateFileHandler => Tcl_CreateFileHandler
+Tk_CreateTimerHandler =>Tcl_CreateTimerHandler
+Tk_DeleteFileHandler => Tcl_DeleteFileHandler
+Tk_DeleteTimerHandler =>Tk_DeleteTimerHandler
+Tk_DoOneEvent => Tcl_DoOneEvent
+Tk_DoWhenIdle => Tcl_DoWhenIdle
+Tk_Sleep => Tcl_Sleep
+tkerror => bgerror
+
+Other than the name changes, the functions are the same. In addition,
+there are #defines in tk.h so that the old Tk names will still work.
+tkerror and bgerror are specially hacked as synonyms, so it should be
+safe to use either one. You should switch to the new Tcl names ASAP,
+though, since the old Tk names will eventually be desupported. (JO)
+
+11/7/95 (features removed) As part of moving the event loop to Tcl,
+the following procedures were deleted:
+ - Tk_EventInit (the presence of the event loop in Tcl should
+ make this unneccessary).
+ - Tk_CreatFileHandler2 (you can get the same effect by using event
+ sources in Tcl, but you have to modify your code to use the new
+ Tcl APIs).
+ - All of the stuff in the manual entries Notifer.3 and QueueEvent.3;
+ this has changed because the notifier got reworked when it was
+ moved to Tcl.
+*** POTENTIAL INCOMPATIBILITY ***
+
+11/7/95 (feature change) Changed to use exit handler to cleanup windows
+in Tk, so Tk no longer needs to have a private copy of the "exit" command.
+(JO)
+
+11/7/95 (bug fix) If wish was invoked with a command-line geometry and
+a script file (e.g. "wish foo.tcl -geometry 30x20"), and if one of
+the windows created by the script used the -setgrid option, then the
+width and height from the command line were lost. (JO)
+
+11/8/95 (bug fix) The "see" command didn't work quite right for texts:
+if the window was small and you try to "see" a line just offscreen,
+Tk centered the line (actually, mis-centered it) when it should have
+aligned it at the top or bottom. (JO)
+
+11/9/95 (bug fix) The "send" command crashed if you tried to send to
+a different display with "-displayof". (JO)
+
+11/9/95 (bug fix) The Symbol font didn't print right in Postscript
+output, because of changes made to re-encode fonts to get proper
+ISO Latin1 behavior. Changed the code not to re-encode the Symbol
+font. (JO)
+
+11/13/95 (bug fix) Fixed Makefile.in and configure.in for UNIX so that
+configure can be run from a clean directory separate from the Tcl source
+tree, and compilations can be performed there. (JO)
+
+11/17/95 (bug fix) If a window was gridded, Tk still computed the
+default maximum dimensions in pixel units, which resulted in windows
+that could grow much larger than the screen. (JO)
+
+11/17/95 (bug fix) If a menus entries were all disabled, posting
+the menu and typing Up or Down caused an infinite loop, locking
+up the screen (JO).
+
+11/19/95 (bug fix) The focus wasn't being restored properly after a
+menu selection in a cascaded menu. (JO)
+
+11/19/95 (bug fix) Menubutton's didn't stipple display their images
+differently when disabled. Change to have the same behavior as buttons:
+the image is stippled over in the background color when the menubutton
+is disabled. (JO)
+
+11/21/95 (bug fix) Changes in display attributes such as font could
+cause core dumps in the text widget under some circumstances involving
+line wrapping. (JO)
+
+11/22/95 (bug fix/new feature) Changed both the placer and the packer
+to ensure that slaves are unmapped whenever the master is unmapped.
+This saves time that slaves might otherwise spend trying to redisplay
+themselves when they're unmapped. (JO)
+
+11/22/95 (bug fix) Space and return keys didn't work for menus if
+they were posted via Alt-x keystrokes. (JO)
+
+11/24/95 (bug fix) tk_dialog procedure had binding for <Return> that
+always activated default binding, even if input focus was in some
+other binding. Removed this feature, since existing focus support
+will already "do the right thing". (JO)
+
+11/24/95 (bug fix) Both canvases and texts could dump core if a binding
+(such as ButtonRelease on an internal item) deleted the widget. (JO)
+
+11/24/95 (feature change) Replaced "configInfo" file with tkConfig.sh,
+which is more complete and uses slightly different names. Also
+arranged for tkConfig.sh to be installed in the platform-specific
+library directory. (JO)
+
+11/24/95 (bug fix) It was possible for a slave to be placed or packed
+-in itself, with unpleasant consequences. It is now an error for the
+slave to be its own master for geometry management. (JO)
+
+11/25/95 (bug fix) The -command option of scales was sometimes being
+invoked spuriously (e.g. when the mouse moved in the scale without a
+button down). This was because the scale wasn't rounding properly
+when setting the scale value from its associated variable. (JO)
+
+----------------- Released patch 4.0p3, 11/28/95 ----------------------
+
+12/18/95 (feature change) Moved Tk_Preserve, Tk_Release, and
+Tk_EventuallyFree to Tcl, renamed to Tcl_Preserve etc. Added #defines
+to tk.h so that the old names still work. (JO)
+
+12/23/95 (bug fix) If a single process had > 1 Tk application, Tk
+didn't guarantee that the application names were unique, which could
+cause all sorts of confusion with "send". (JO)
+
+12/23/95 (feature change) Eliminated Tk_CreateMainWindow and moved
+all of its functionality to Tk_Init. All that you need to do now
+to get Tk in an application is to call Tk_Init. Improved Tk_Init
+so that -colormap and -visual command-line arguments are now passed
+through to TkCreateFrame. Tk_Main is much simpler now, since a lot
+of its functionality has moved to Tk_Init. (JO)
+*** POTENTIAL INCOMPATIBILITY ***
+
+12/23/95 (new feature) Added support for Tcl_StaticPackage so
+that Tk can now be loaded into slave interpreters with the "load"
+command to create new applications. (JO)
+
+12/23/95 (new features) Added support for -colormap and -visual command-
+line options for wish. (JO)
+
+1/4/95 (bug fix) Fixed keyboard code to properly handle alt-key
+sequences for international keyboards and menu-accelerators. (SS)
+
+1/5/96 (bug fix) Scrollbar code sometimes generated errors on accesses
+to tkPriv(relief) during control-clicks. (JO)
+
+1/9/96 (new feature) added the "grid" command to provide a table based
+geometry manager. (SU)
+
+1/12/96 (performance optimization) Changed the way tag information is kept
+in the text's Btree so the cost of adding and removing tag ranges is no longer
+proportional to the number of unique tags in the text. In the old system
+the cost of adding N unique tags was O(N-squared). The new implementation is
+optimized for tags that only cover a small amount of text, measuring from
+their earliest tag range to the end of their last range. In the best case the
+cost of adding a tag range is unrelated to the number of unique tags, so the
+cost of adding N tags is only O(N). In the worst case, where all tags
+cover all the text, the cost is still O(N-squared) to add N such tags.
+Deleting tags still has an O(N) cost (so deleting N tags is O(N-squared),
+but it is now a factor of 2 faster than the old system. (BW)
+
+1/12/96 (new feature) added the text "dump" operation that returns information
+about all elements in a text widget: text, tags, marks, and windows. (BW)
+
+1/12/96 (new feature) added the text "mark next" and "mark previous" operations
+to search forward and backwards for the next (previous) mark in the text. (BW)
+
+1/12/96 (new feature) added the text "tag prevrange" operation to search
+backwards for the current or previous range of a tag. (BW)
+
+1/16/96 (new feature) Added support for relative widget placement on
+the "grid" command. (SU)
+
+1/17/96 (new feature) Modified the Makefile/configure setup to support
+compiling Tk as a shared library. Use the --enable-shared option to
+the "configure" script. (JO)
+
+----------------- Released 4.1b1, 1/26/96 -----------------------
+
+2/2/96 (bug fix) Frames were getting a default size of 200x200, whereas
+there should be no default. (JO)
+
+2/2/96 (bug fix) Argc wasn't getting reset properly after Tk removed
+the arguments it understood from those on the command line. (JO)
+
+2/6/96 (bug fix) Fixed off by one error in argument parsing code under
+Windows. (SS)
+
+2/6/96 (bug fix) "wm transient" now works under Windows. The resulting
+toplevel is created with a modal dialog box frame and will not appear
+in the taskbar under Windows '95. (SS)
+
+2/9/96 (bug fix) Changed Makefile.in to use -L and -l for Tcl and Tk
+libraries so that shared libraries are more likely to be found correctly
+on more platforms. (JO)
+
+2/14/96 (feature change) Eliminated tk_CanvasTagsOption variable because
+it can't be exported safely across DLL boundaries. Instead, exported
+Tk_CanvasTagsParseProc and Tk_CanvasTagsPrintProc procedures for
+use by canvas type managers in creating their own custom options. (JO)
+*** POTENTIAL INCOMPATIBILITY ***
+
+2/14/96 (bug fix) "winfo pointerxy" when applied to a non-toplevel window
+crashed wish. (SS)
+
+2/14/96 (bug fix) "tkwait visibility" would hang under Windows. (SS)
+
+2/14/96 (bug fix) Cursors were not being updated until an enter event.
+In cases where the cursor left the toplevel and reentered before Tk
+noticed, the cursor would get "stuck" until the next enter event.
+Similarly, if the cursor attribute of a window was updated while the
+mouse was in the window, the cursor would not change until the next
+time the mouse entered the window. (SS)
+
+2/15/96 (bug fix) If a top-level was resizable in one direction
+(e.g. "wm resizable . 0 1"), once the user resized it any changes
+in the internally requested size (by the widgets) were ignored,
+even for the non-resizable dimension. Fixed to handle the two
+dimensions totally independently, so the widget's requests are
+honored as long as that dimension hasn't been set by the user. (JO)
+
+2/17/96 (bug fix) If a text widget had very long lines (e.g. more than
+32K pixels), integer overflow could occur, resulting in parts of the
+line not being visible. (JO)
+
+2/20/96 (feature change) Changed the -minsize option of grid to take
+screen units instead of pixels. (SU)
+
+2/20/96 (bug fix) grid row and column weights are compared against
+MINWEIGHT (0.001) instead of 0.0 to guard against divide by zero errors
+during weight normalization. (SU)
+
+2/20/96 (bug fix) Menu commands were not being invoked sometimes.
+There was a race condition that caused events to be processed while a
+menu was being unposted. (SS)
+
+----------------- Released 4.1b2, 2/23/96 -----------------------
+
+2/23/96 (bug fix) Alt-keys invoked in torn-off and popped up menus
+caused menus to be posted in the parent toplevel. (JO)
+
+2/23/96 (bug fix) Canvases weren't always updating their scrollbars
+when they should. (JO)
+
+2/23/96 (bug fix) Fixed core dump that could occur if a WM_DELETE_PROTOCOL
+handler generated an error. (JO)
+
+2/24/96 (bug fix) Removed dependencies on Makefile in the UNIX Makefile:
+this caused problems on some platforms (like Linux?). (JO)
+
+2/24/96 (feature change) Changed text and entry widgets so that they
+set the insertion cursor before inserting during a button-2 click.
+Also made optional bindings check for tk_strictMotif at the time of
+the event, rather than at the time the bindings are created. (JO)
+
+2/24/96 (bug fix) Tk tended to crash with an X error when unsetting
+an icon window (e.g. "wm iconwindow . {}"). (JO)
+
+2/25/96 (bug fix) Wasn't removing windows from the WM_COLORMAP_WINDOWS
+property when they were deleted. (JO)
+
+3/1/96 (new feature) Added new "bbox" widget command for entries.
+Also modified mouse bindings for entries and texts so that the
+mouse position rounds to the nearest inter-character gap, rather
+than the left edge of the character under the mouse. This provides
+more natural selection behavior. (JO)
+
+3/1/96 (bug fix) Fixed core dump that could occur in image code if an
+image was deleted while in use in a widet, then re-used in another
+widget while "deleted". (JO)
+
+3/1/96 (bug fix) Calling wish with a single argument caused a crash
+under Windows due to an off-by-one error in the argument parsing code. (SS)
+
+3/1/96 (bug fix) Palette management was broken and resulted in
+incorrect palette realization and refresh behavior. Also, images were
+being drawn incorrectly if they were attached to widgets that had a
+private colormap. (SS)
+
+3/2/96 (bug fix) It was possible to press the mouse button over an
+option menu, drag to a pulldown menu, and have the pulldown menu
+popup in place of the option menu. Fixed this so that option menus
+are isolated from each other and from pulldowns. (JO)
+
+3/2/96 (bug fix) Fixed yet another bug that caused long delays when
+raising toplevel windows. (JO)
+
+3/2/96 (bug fix) Fixed bug in canvases where zero-sized rectangles
+and ovals didn't always redisplay right (could leave trailing
+garbage on screen when moved). (JO)
+
+3/2/96 (bug fix) Entry widgets reset their insertion cursor, selection,
+and view whenever the text variable changed, plus whenever a "configure"
+widget command was invoked and there was a text variable for the
+widget. Fixed to preserve this information as much as possible. (JO)
+
+3/5/96 (new feature) Added version suffix to shared library names so that
+Tk will compile under NetBSD and FreeBSD (I hope). (JO)
+
+3/6/96 (bug fix) Changed the way certain configure & motion events are
+reported. This fixes several bugs in menus & "winfo rootx". (RJ)
+
+3/7/96 (bug fix) Fixed tag remove bug that showed up when draging out a
+selection. If you had dragged left, then tried to drag back right, the
+left edge of the selection wasn't being updated because the tag remove
+wasn't doing anything. (BW)
+
+3/7/96 (bug fix) Fixed the boundary conditions of tag prevrange. The second
+index argument wasn't effecting in stopping the search if it fell within
+a range. The second index has to come at or before the start of a range
+for the range to be found by tag prevrange. (BW)
+
+3/7/96 (bug fix) "puts" to stdout or stderr when running from a script
+caused wish41.exe to exit silently. Now the output is silently
+discarded without generating an error. (SS)
+
+3/7/96 (bug fix) Fixed bug where wish was treating empty lines in the input
+as end of input, if the input came from stdin. This would cause it to
+complain about missing closing braces etc. (JL)
+
+----------------- Released 4.1b3, 3/8/96 -----------------------
+
+3/9/96 (bug fix) Fixed bug in text.tcl that could cause errors in text
+widgets of the form 'can't use non-numeric string as operand of "-"'. (JO)
+
+3/12/96 (feature improvement) Modified startup script to look in several
+different places for the Tcl library directory. This should allow tk
+to find the libraries under all but the weirdest conditions, even without
+the TK_LIBRARY environment variable being set. (JO)
+
+3/14/96 (bug fix) "wish bogus_file_name" didn't print an error message. (JO)
+
+3/14/96 (bug fix) Button-2 wasn't claiming the focus during paste
+operations. (JO)
+
+3/14/96 (bug fix) "tkwait visibility" use to hang forever if its window
+was deleted. Now it detects this condition and returns an error. (JO)
+
+3/16/96 (bug fix) Changed configuration stuff to get dynamic loading and
+shared libraries working under AIX. (JO)
+
+3/16/96 (bug fix) Fixed core dumps that could occur when a slave interpreter
+was deleted in the middle of executin bindings. (JO)
+
+3/18/96 (new feature) Added support for Activate/Deactivate events.
+Currently, these new X events will generated only on the Macintosh. (RJ/CS)
+
+3/21/96 (bug fix) The "tag prevrange" command would fail to return the current
+range if it began at 1.0 and the starting point of the search was within
+the range. (BW)
+
+3/21/96 (configuration improvement) Changed configure script so it
+doesn't use version numbers (as in -ltk4.1 and libtk4.1.so) under
+SunOS 4.1, where they don't work anyway. (JO)
+
+3/22/96 (bug fix) Made Tk more robust against interpreter deletion. Now it
+should be safe to delete an interpreter with a Tk application inside it,
+without first deleting the Tk application. (JL)
+
+3/26/96 (bug fix) Tk now returns results from a "send" to an interpreter
+in which the Tk application is destroyed, if the interpreter continues
+computing after the Tk application is destroyed. Previously any results
+computed after '.' was destroyed in the target interpreter were discarded
+by the "send". (JL)
+
+3/26/96 (new feature) Tk now provides a static Tktest package which is
+present only in test versions of Tk; this allows the testing commands to
+be loaded into new interpreters besides the main one. (JL)
+
+3/28/96 (bug fix) Changed the tk_dialog procedure *not* to make the
+dialog a transient for its parent. The old behavior meant that the
+dialog did not get posted if the parent was iconified. (JO)
+
+4/5/96 (bug fix) Tk would occasionally crash when destroying toplevels
+under Windows. (SS)
+
+4/5/96 (bug fix) Fonts were not being properly deallocated, causing
+GDI resources to be consumed and never released under Windows. (SS)
+
+4/11/96 (bug fix) Toplevel windows with no specified geometry were
+always appearing in the upper left corner of the screen under
+Windows. (SS)
+
+4/11/96 (bug fix) "wm minsize" did not properly report the minimum
+size imposed by the Windows window manager. (SS)
+
+4/13/96 (bug fix) Text widgets could dump core in some cases where
+text was inserted on the top visible line. (JO)
+
+4/16/96 (bug fix) Changed menu code to ignore errors that occur when
+restoring a grab: the old grab window might not be visible anymore. (JO)
+
+----------------- Released 4.1, 4/21/96 -----------------------
+
+5/1/96 (bug fix) "option readfile" did not handle files with CRLF
+line termination. (SS)
+
+5/1/96 (bug fix) Changed to install tkConfig.sh under "make install-binaries",
+not "make install-libraries". (JO)
+
+5/7/96 (bug fix) Moved initScript in tkUnixInit.c to writable memory to
+avoid potential core dumps. (JO)
+
+5/7/96 (bug fix) Changed tk_dialog back so that the dialog box is a
+transient window again. This is needed to make sure that the dialog
+box doesn't get obscured. Also changed it to return -1 if the dialog
+window is deleted before the user presses a button. (JO)
+
+5/16/96 (bug fix) Fixed bug that caused core-dumps if a text widget
+with -setgrid 1 was deleted by removing its command. (JO)
+
+5/16/96 (bug fix) Fixed bug that caused Tk initialization to use improperly
+initialized variables left over from previous invocation of Tk_Init on
+another interpreter. (JL)
+
+5/16/96 (new feature) Implemented application embedding on Windows
+platforms (only Tk inside another application, not the other way yet). (JL)
+
+5/16/96 (new feature) Added C API Tk_SafeInit that adds Tk to a safe
+interpreter. (JL)
+
+5/16/96 (bug fix) Fixed bug that caused Tk initialization to use improperly
+initialized variables left over from previous invocation of Tk_Init on
+another interpreter. (JL)
+
+5/16/96 (new feature) Implemented application embedding on Windows
+platforms (only Tk inside another application, not the other way yet). (JL)
+
+5/16/96 (new feature) Added C API Tk_SafeInit that adds Tk to a safe
+interpreter. (JL)
+
+5/22/96 (bug fix) Listboxes weren't properly ignoring double clicks on
+button 1. (JO)
+
+6/12/96 (bug fix) Focus was automatically placed on new toplevels.
+This caused the titlebar to flash during menubar traversal. (SS)
+
+6/12/96 (bug fix) Iconification of a window with a specified geometry
+by using the minimize button would leave the window in an inconsistent
+state. When the window was deiconified using "wm deiconify", the
+window would continue to display as an icon with the deiconified
+geometry. (SS)
+
+6/12/96 (bug fix) Fixed a resource leak where the text widget was not
+freeing all of the TkRegions it created. This fix affects all
+platforms, but is particularly important for Win32s. (SS)
+
+6/21/96 (configuration change) Added --enable-gcc switch to configure
+script to make Tk just like Tcl. Now Tk will not use gcc unless you
+request it explicitly. (JO)
+
+7/18/96 (bug fix) Changed "configure" script to add an extra -R switch
+(or whatever is appropriate to the platform) if the X library is in a
+nonstandard place. This guarantees that the shared library can be
+found at runtime without having to set the LD_LIBRARY_PATH variable. (JO)
+
+7/19/96 (bug fix) Fixed bug in tkImgGIF.c that cause core dumps if a
+GIF file contained multiple images. (JO)
+
+7/20/96 (bug fix) Deadlock could occur if a recursive series of send
+operations involved multiple displays. (JO)
+
+7/23/96 (bug fix) Fixed a resource leak where deallocated XIDs were
+taking up memory on Windows and Macintosh platforms. (SS)
+
+7/30/96 (bug fix) A core dump could occur if a <Destroy> handler for
+a window tried to create a child in the half-dead window. Fixed by
+making the window's name disappear from the name table once it starts
+to be deleted. (JO)
+
+----------------- Released patch 4.1p1, 8/2/96 -----------------------
+
+4/30/96 (new feature) Added support for named virtual events. New "event"
+command to define/destroy named virtual events and to programmatically
+send both real and virtual events to Tk. (CS)
+
+8/6/96 (bug fix) Entry widgets were invoking scrollbar update functions
+too often. (JO)
+
+8/9/96 (bug fix) 7/30 change above for <Destroy> handlers broke many
+things by making window available during Destroy handler. Reworked
+fix for core dump to simply disallow creating children of half-dead
+parents. (JO)
+
+8/12/96 (bug fix) Fixed bug where using the Copy menu item on the
+Macintosh would append a NULL character at the end of the text. (RJ)
+
+8/15/96 (bug fix) Fixed Mac code so garbage wouldn't be printed in
+text and entry widgets when function & other non-printing keys were
+pressed. (RJ)
+
+8/15/96 (configuration improvement) Changed the file patchlevel.h
+to be tkPatch.h. This avoids conflict with the Tcl file and is now
+in 8.3 format on the Windows platform. (RJ)
+
+8/19/96 (bug fix) Fixed a bug under Windows where the initial window
+position for a toplevel window was reported as +0+0, regardless of the
+actual position. (SS)
+
+8/21/96 (bug fix) If the last character on a line in a text widget was
+a space character that didn't completely fit, the text widget would
+sometimes add an extra wrap line. (JO)
+
+8/22/96 (feature change) Complete rewrite of the grid geometry manager.
+There is a new layout algorithm that produces better (but different)
+layouts in many common cases. (SU)
+
+8/22/96 (new feature) There are two new options for the grid geometry
+manager, "grid update" which forces an immediate layout calculation,
+and a "-pad" option to rowconfigure and columnconfigure that allows for
+extra space around widgets. (SU)
+
+8/22/96 (feature change) The order in which the grid geometry manager
+reports slaves is now last-managed first. (SU)
+
+8/22/96 (feature change) The column and row weights in the grid
+geometry manager are kept internally as integers, instead of floating
+point values. Floating point values are still accepted on the command line,
+but are truncated to integers. (SU)
+
+8/22/96 (new feature) There are four new commands for opening common
+dialog boxes: tk_chooseColor, tk_getOpenFile, tk_getSaveFile and
+tk_messageBox. Native dialog boxes are used wherever available. (IL)
+
+8/22/96 (new demos) Added "fsbox", "msgbox" and "clrpick" demos. (IL)
+
+8/23/96 (feature change) Invoking the edit menu on the Macintosh now
+generates the following virtual events <<Cut>>, <<Copy>>, <<Paste>>,
+and <<Clear>> instead of faking key events. (RJ)
+*** POTENTIAL INCOMPATIBILITY ***
+
+8/25/96 (bug fix) Fixed a bug that would cause "grid x" to dump core. (SU)
+
+8/26/96 (new feature) Added the "unsupported1" command to the
+Macintosh version of Tk. This command will allow you to set the style
+of a new toplevel Window (much like overrideredirect). You can use
+this to get access to all of the Native Mac window styles. This is to
+hold you over until we get a more general solution added to the
+toplevel command. (RJ)
+
+8/26/96 (new feature) Added support to handle the zoom box on a
+Macintosh window. (Currently, you can only get a Tk window with a
+zoom box by using the "unsupported1" command. (RJ)
+
+8/27/96 (documentation change) Removed old change bars (for changes in
+Tk 4.1 and earlier releases) from manual entries. (JO)
+
+----------------- Released 4.2b1, 8/30/96 -----------------------
+
+9/5/96 (bug fixes) Fixed several bugs in file dialogs: individual files
+could be listed twice, if a long list of files were shown, and the view
+scrolled to the right, and then a different file file was shown, the
+scrollregion on the canvas wasn't being reset, so the file dialog was
+broken from then on, added an update idletasks so that the watch
+cursor was shown when the dialog was thinking. For the motif file
+dialog, fixed the weights for resizing. On the clrpicker, fixed the
+finalColor variable which caused problems when the OK button was
+"clicked" before the dialog was mapped (in the test suite). Added Ioi's
+last changes from before he left. For message boxes, if a single button
+message box is shown (currently only 'ok'), it is set to be the default
+even if not specified. (KC)
+
+9/5/96 (bug fix) Fixed bug on Macintosh where menus would appear in a
+seemingly random location. (RJ)
+
+9/5/96 (bug fix) Text widgets had rounding problems with the "yview"
+command that caused them sometimes to round to the line before the
+correct one. (JO)
+
+9/5/96 (bug fix) Changed grab code to retry grabs after errors where
+another application already has the grab. This is needed to get
+around race conditions with some window managers and will hopefully
+solve the grab errors that people see occasionally. (JO)
+
+9/6/96 (bug fix) Fixed x-y coordinate confusion problem with scaling
+of window items in canvases. (JO)
+
+9/11/96 (bug fix) The open and save file dialogs would change the
+current working directory under Windows. (SS)
+
+9/12/96 (bug fix) The Tk event system was delivering events to dead
+windows, if the event handler got reentered during a Destroy event
+handler. This could cause core dumps and other problems. (JO)
+
+9/20/96 (bug fix) In XFillRectangles under Windows, a brush was not
+being deallocated. (SS)
+
+9/20/96 (bug fix) The Mac window manager used to generate a mouseUp
+event for a top level that was recently raised to the front/active
+window which often caused a tk(priv) error. The up event is no
+longer generated with solves several problems. (RJ)
+
+9/25/96 (bug fix) The font code under Windows was leaking memory
+whenever a new font was referenced using the three part font names. (SS)
+
+9/26/96 (bug fix) The tests for the common dialogs still used the 'testevent'
+function. I updated these calls in clrpick.test, msgbox.test, filebox.test
+to use the new event gereating mechanism.
+
+9/18/96 (bug fix) Long-standing bug in bind where <Button-1><Button-1> was
+reported as <Double-Button-1>, but <Double-Key-a> was reported as "aa". (CS)
+
+9/27/96 (bug fix) Bindings didn't work on 64-bit machines due to changes
+made for virtual events. (CS)
+
+9/30/96 (feature change) Binding for new virtual events included both
+lower and upper-case, e.g., <<Copy>> was defined as <Control-c> and
+<Control-C>. Previously, widgets were directly bound to only lower-case
+bindings. The upper-case binding caused incompatibility with some existing
+Tcl programs, so the upper case bindings for <<Cut>>, <<Copy>>, and <<Paste>>
+were removed. (CS)
+
+9/30/96 (bug fix) The postscript code in the canvas widget now uses
+channels to get and write .ps files which fixed a bug on the Mac where
+an output file would have mixed EOL characters. In addition, I added
+the ability for the prolog to come from the Tk shared library on the
+Mac which makes it possible to have a standalone application. (RJ)
+
+10/1/96 (feature change) "grid forget" was renamed "grid remove". A new
+command "grid forget" was added whose semantics are the same as "pack forget"
+(SAU)
+*** POTENTIAL INCOMPATIBILITY ***
+
+10/1/96 (feature change) grid no longer accepts floating point values for
+row or column weights, integers must be used. (SAU)
+*** POTENTIAL INCOMPATIBILITY ***
+
+10/1/96 (feature change) "grid {column,row}configure <master> <index>"
+returns a list of option value pairs for all of the row or column
+constraints. It used to return an error. (SAU)
+
+10/1/96 (bug fix) "The way grid handles '^' short-cuts was re-written
+to eliminate core dumps. (SAU)
+
+10/3/96 (feature change) A virtual event binding associated with a
+given physical event is now considered less specific than a binding for
+that same physical event, all other things being equal. (CS).
+
+10/3/96 (bug fix) Under Windows text placed on the clipboard did not
+undergo CRLF translation when delivered to other applications. (SS)
+
+10/3/96 (bug fix) Copying an image onto itself with a zoom factor that
+caused the image to grow was accessing freed memory. (SS)
+
+10/3/96 (bug fix) Under Windows, the image blank subcommand did not
+work. (SS)
+
+10/10/96 (bug fix) Under Windows & Macintosh, XSetFont and XChangeGC
+were not implemented, and XSetLineAttributes did not correctly update
+the GC. (SS)
+
+10/10/96 (bug fix) Under Windows, 8-bit non-palette displays were not
+handled properly. (SS)
+
+10/10/96 (bug fix) Under Windows, images of depth other than 8 or 24
+bits were not being rendered properly. (SS)
+
+10/10/96 (bug fix) Under Windows, bitmap subimages were not correctly
+displayed. (SS)
+
+10/14/96 (bug fix) Under Window, wm resizable would constrain both
+programatic resizes as well as user resizes. (SS)
+
+----------------- Released 4.2, 10/16/96 -----------------------
+
+10/17/96 (bug fix) XCopyPlane was broken under Windows and would cause
+a crash when used with a clipping bitmap. (SS)
+
+10/21/96 (bug fix) Added missing resources needed by tk_getOpenDialog
+on the Macintosh to the shared library for Tk. (RJ)
+
+10/22/96 (bug fix) Invoking a menu with an Alt key sequence caused an
+error due to a misplaced common in library/menu.tcl. (JO)
+
+10/23/96 (bug fix) Errors in files sourced by the Macintosh
+"Source..." menu are now correctly reported via the background
+error mechanism. (RJ)
+
+10/23/96 (bug fix) Fixed a bug in the Mac subwindow implementation
+that caused refreshes to not occur for canvases with embedded
+windows. (RJ)
+
+10/24/96 (bug fix) Provided workaround for Apple bug that doesn't
+handle zooming correctly for floating windows. (RJ)
+
+10/24/96 (bug fix) Macintosh tearoff menus are now correctly
+displayed as Mac floating windows. (RJ)
+
+11/1/96 (bug fix) Restored manual page for procedures like
+Tk_CreateWindowFromPath and Tk_DestroyWindow; was accidentally deleted
+when Tk_CreateMainWindow procedure was decommissioned. (JO)
+
+11/19/96 (bug fix) Fixed bugs in postscript code that would cause the
+prefix to not be included and the output file to have the wrong
+permissions. (RJ)
+
+12/2/96 (bug fix) Fixed problem with canvas lines where it didn't
+compute bounding boxes correctly for zero-width lines: this could
+potentially leave garbage on the screen when items were deleted or
+moved. (JO)
+
+12/5/96 (bug fix) Fixed the Macintosh implementation of pointer x/y
+which was returning garbage. (RJ)
+
+12/6/96 (bug fix) Fixed grid bug where the positioning of slaves was
+incorrect for non-zero values of ipadx and ipady (SU)
+
+12/6/96 (bug fix) Fixed grid bug where slaves got "lost" when an
+already managed slave is re-managed in a different master. (SAU)
+
+----------------- Released 4.2p1, 12/8/96 (Mac only) --------------
+
+1/17/97 (bug fix) Fixed bug where the Tk clipboard was not in sync
+with the Macintosh clipboard on start-up. (RJ)
+
+----------------- Released 4.2p2, 1/31/97 --------------
+
+----------------------------------------------------------
+Changes for Tk 4.2 go above this line.
+Changes for Tk 4.3 go below this line.
+----------------------------------------------------------
+
+9/19/96 (improvement) Implemented table driven mechanism for deciding
+whether a command is safe. If it is added by Tk_Init and it appears in the
+table then it is kept, otherwise it is removed in a safe interpreter. (JL)
+
+10/18/96 (new feature) Added support for application embedding:
+ - Frame and toplevel widgets now have a -container option, which
+ turns the widget into a container.
+ - Toplevel widgets have a -use option for requesting that the
+ widget be embedded in another application.
+ - Wish also supports a -use command-line option.
+Embedding is fully supported under Unix, but the implementation is
+not complete under Windows or the Macintosh (it works just well
+enough to support the Tcl/Tk plugin). (JO)
+
+10/22/96 (bug fix) The commands "winfo rootx" and "winfo rooty" didn't
+work for non-toplevel windows in embedded applications: they returned
+the coordinates of the nearest toplevel. (JO)
+
+12/02/96 (new feature) Implemented Safe Tk. Tk can now be loaded into a
+safe interpreter that has been created with tcl_safeCreateInterp, by
+calling load {} Tk interpname. (JL)
+
+12/02/96 (new feature) A safe Tk interpreter can no longer generate
+postscript output from a canvas. (JL)
+
+12/02/96 (new feature) Added -channel option to photo command to allow
+image data to be read from a channel. This is useful in safe Tk
+interpreters where the data cannot be read directly from a file. (JL)
+
+----------------------------------------------------------
+Changes for Tk 4.3 go above this line.
+Changes for Tk 8.0 go below this line.
+----------------------------------------------------------
+
+9/1/96 (new features) The font mechanism in Tk has been completely
+reworked:
+ - Font names need not be nasty X LFDs: more intuitive names like
+ {Times 12 Bold} can also be used. See the manual entry font.n
+ for details.
+ - Font requests always succeed now. If the requested font is not
+ available, Tk finds the closest available font and uses that one.
+ - Tk now supports named fonts whose precise attributes can be
+ changed dynamically. If a named font is changed, any widget
+ using that font updates itself to reflect the change.
+ - There is a new command "font" for creating named fonts and querying
+ various information about fonts.
+ - There are now officially supported C APIs for measuring and
+ displaying text. If you use these APIs now, your code will
+ automatically handle international text when internationalization
+ is added to Tk in a future release. See the manual entries
+ MeasureChar.3, TextLayout.3, and FontId.3.
+ - The old C procedures Tk_GetFontStruct, Tk_NameOfFontStruct, and
+ Tk_FreeFontStruct have been replaced with more portable procedures
+ Tk_GetFont, Tk_NameOfFont, and Tk_FreeFont.
+ *** POTENTIAL INCOMPATIBILITY ***
+(CS)
+
+9/24/96 (bug fix) Under Windows, transient windows would be destroyed
+if their master was destroyed, even if the transient window was not a
+child of the master. (SS)
+
+10/18/96 (new features) A -menu option has been added to the toplevel
+widget command, which allows a menu to operate as a menubar. On the
+Macintosh, the menubar is displayed accross the top of the main monitor,
+just like with other applications. Under Windows and Unix, the menu is
+attached to the toplevel window. Also, changed some semantics.
+Tearoff menus will now reflect changes to the menu it was
+torn off from, and are deleted when the master menu is
+deleted. Tearoffs also reflect more look-and-feel of the
+platforms they are running on. (SRP)
+
+10/31/96 (bug fix) Under Windows, missing system cursors would
+generate an error instead of falling through to the Tk cursor of the
+same name. (SS)
+
+11/7/96 (feature change) Under Unix, default borderwidth is now 1 to
+more closely approximate CDE. (SS)
+Note: this change was undone on 6/12/97, restoring the default border
+width to 2 again. (JO)
+
+11/7/96 (new feature) The button widget now supports a -default option
+that draws a platform specific default ring around the widget. (SS)
+
+11/7/96 (feature change) Under Windows, buttons and scrollbars now
+have native look and feel. This affects the default class bindings
+and the way the some configuration options are interpreted. Refer to
+the widget manual pages for more details. (SS)
+*** POTENTIAL INCOMPATIBILITY ***
+
+11/19/96 (bug fix) Under Windows, images were incorrectly drawn on
+16-bit displays. (SS)
+
+11/19/96 (bug fix) Under Windows, the class name for the main window
+(.) was not properly generated from argv0. (SS)
+
+11/20/96 (bug fix) Fixed a couple of bugs in the Canvas widget. The
+postscript file is now created with the correct permissions. Also,
+the prolog is now properly included in all cases. (RJ)
+
+11/22/96 (bug fix) Under Windows, the initial directory and file names
+were not properly translated before being passed to the system
+open/save file dialogs. So forward slashes were not converted to
+backslashes, and tilde substitution was not performed. (SS)
+
+11/25/96 (feature change) Under Windows and Macintosh, the selection
+highlight is now hidden whenever an entry or text widget loses focus.
+Also, the previous selection information is not lost when a new
+selection is made in a different widget. (SS)
+
+11/26/96 (new feature) Added support for images as primitive types in
+text widgets. (SU)
+
+11/30/96 (configuration improvement) Modified configure.in to handle the
+case where Tcl and Tk are installed in different places by including both
+their library directories in the library search path for Tk. (JO)
+
+12/3/96 (bug fixes) Fixed two bugs related to canvas lines that caused
+the screen to be incorrectly refreshed, leaving garbage on the screen.
+One bug was related to lines with width zero, and the other was
+related to lines with very long miters. (JO)
+
+12/4/96 (bug fix) The "update" command was only syncing the display
+for its main window. Changed to sync all displays. (JO)
+
+12/5/96 (bug fix) Color deallocation would occasionally cause a panic
+under Windows. (SS)
+
+12/5/96 (bug fix) Errors during startup were silently discarded under
+Windows. (SS)
+
+12/5/96 (bug fix) Errors during startup were silently discarded under
+Windows. (SS)
+
+12/11/96 (bug fix) Text widgets weren't considering the -spacing1
+and -spacing2 options when computing their desired geometry. (JO)
+
+12/12/96 (feature change) Option menus using tk_optionMenu were
+created with command entries that set the option menu's variable in a
+command string. This has been changed so that the option menu's
+entries are now radiobutton entries so that the entries that matches
+the variable is now checked when the menu is posted. (SRP)
+
+12/12/96 (feature change) The destroy command no longer returns an
+error when a window does not exist. (SRP)
+
+12/13/96 (new feature) grid row/column-configure accepts a list of
+indices in addition to a single index. (SU)
+
+12/17/96 (bug fix) Under Windows, command line was not being parsed
+correctly if it contained the literal characters \" (CS)
+
+12/17/96 (feature change) Native Windows labels do not get a focus-ring
+border. (CS)
+
+12/17/96 (bug fix) Under Windows, colors specified as "#XXYYZZ" where XX, YY,
+or ZZ were not valid hex digits were getting a random color value instead of
+being an error. (CS)
+
+----------------- Released 8.0a1, 12/17/96 -----------------------
+
+12/23/96 (bug fix) Fixed two menu bugs:
+ - Menus could get stacked below other windows so that they weren't
+ visible when posted (especially under olvwm and fvwm).
+ - Under olvwm if you pressed button 1 over an entry in a new-style
+ menubar, the menu didn't appear until you moved the mouse slightly.
+(JO)
+
+1/6/97 (bug fix) Focus could accidentally get grabbed by an application
+away from the rightful focus owner if the focus recently changed from one
+application to another. (JO)
+
+1/6/97 (bug fix) Under Windows, the console was appearing even for
+non-interactive applications. This was a side effect of a general
+problem with the wm state of windows that were being mapped for the
+first time. (SS)
+
+1/6/97 (bug fix) Under Windows, the initialization code was not
+looking in the right directory for the Tk libraries when the program
+being run was not in the Tcl installation heirarchy. (SS)
+
+1/8/97 (bug fix) Under Windows, the windows were not being unmapped
+properly, which led to strange packer behavior. (SS)
+
+1/8/97 (bug fix) The "winfo containing" command (and the Tk_CoordsToWindow
+procedure) didn't work properly on Unix in the presence of embedding or
+menubars. (JO)
+
+1/15/97 (bug fix) Invoking "destroy ." as the command from a menu would
+cause Tk to crash because TkMainInfo was freed before menu released its
+resources. This bug had already been fixed for scrollbars and buttons. (CS)
+
+1/15/97 (bug fix) Tk is now working under Win32s again, including Win32
+version 1.25. Fixed separate problems in fonts and dialogs. (CS)
+
+1/15/97 (feature change) Under Windows, font sizes are now specified in
+points, not pixels. The mapping between pointsize and pixels depends on
+Windows having accurate metrics for the monitor (plug&play helps). Font
+metrics are still reported in pixels. (CS)
+
+1/21/97 (bug fix) Grid no longer reports rows or columns "out of range"
+when requesting their constraints. (SAU)
+
+1/21/97 (bug fix) Fixed some window manager related bugs on the
+Macintosh. Now better support global grabs. (RJ)
+
+1/21/97 (bug fix) For Windows: Fixed problems with canvas items that
+used end caps. Fixed arc implementation to more closely approximate
+X. Stippling now works properly on fat lines. (SS)
+
+1/21/97 (bug fix) Small interlaced GIF images were not properly
+decoded. (SS)
+
+1/21/97 (bug fix) More changes to image code to try to handle 16-bit
+displays properly under Windows. (SS)
+
+1/21/97 (bug fix) Numerous display bugs on Unix and Macintosh are now
+fixed. Numerous binding problems for menubars under Unix are now
+fixed. Deletion of menu separators under Windows is now fixed. (SRP)
+
+----------------- Released 8.0a2, 1/24/97 -----------------------
+
+1/29/97 (feature change) The -transient field for menus is no longer
+supported. There is now a -type field which is used to achieve the
+same purpose that the -transient field accomplished. When a menu is
+created, the -type field controls whether the menu is a normal
+pull-down menu, a floating tearoff menu or a menubar. This option is
+normally only used by the library code and internally by the menubar
+code. (SRP)
+*** POTENTIAL INCOMPATIBILITY ***
+
+2/5/97 (feature change) Changed the photo image mechanism to use
+Tcl_Channels instead of FILE * as an argument to image matching
+functions. The change will make it much easier to write cross
+platform image types in Tk. Note: FILE * is no longer used anywhere
+in Tk. (RJ)
+*** POTENTIAL INCOMPATIBILITY ***
+
+2/7/97 (enhancement) Were not allowed to bind to virtual events inside of
+canvas or text widget (e.g., "$canvas bind all <<foo>> {script}" or
+"$text tag bind sel <<foo>> {script}"); it would return an error
+disallowing that binding. Now _can_ bind to a virtual event, but that
+binding inside of the canvas or text widget will only fire if the
+underlying virtual event definition is of type key, button, motion,
+enter, or leave; all other physical event types get filtered out by the
+widget before the virtual event mapping is done. (CS)
+
+2/22/97 (bug fix) Under Unix, "wm geometry +-20+-30" didn't work. (JO)
+
+2/24/97 (bug fix) The photo image didn't always zero out enough of its
+pixel and dither correction arrays. (JO)
+
+2/25/97 (bug fix) Fixed focus problem that could cause "BadMatch (invalid
+parameter attributes)" in X_SetInputFocus requests on Unix. (JO)
+
+2/25/97 (bug fix and new feature) Added new "gray75" bitmap, fixed
+"gray25" bitmap to really be 25% on (due to an ancient mistake, it
+had been only 12% on). (JO)
+
+2/28/97 (bug fix) Windows: made embedding work again on Win32 platform.
+Prevent iconification, deiconinification on embedded windows. (JL)
+
+3/4/97 (new feature) Added the ability to manipulate the Apple and
+Help menus on the Macintosh; the system menu on Windows; and to have a
+right justified Help menu on Unix. See the documentation for menu.n
+for more details. (SRP)
+
+3/4/97 (bug fix) Prevented core dump at exit if a <Destroy> binding on "."
+gets invoked from destroying a nested widget and the binding causes the
+interpreter to be deleted. The core dump was being caused by the
+interpreter not being Tcl_Preserve'd during the destroy of ".". (JL)
+
+3/4/97 (bug fix) Under Unix, when embedded Tk is running in a separate
+process, correctly handle a race condition: ignore cross-over messages from
+the X server for windows that Tk thinks it had already deleted, when the
+containing process deletes its container window. Some other race conditions
+still remain, e.g. with pixmaps, colormaps and images. (JL)
+
+3/10/97 (bug fix) Prevented core dump in generic console code due to
+following a NULL pointer when the console interpreter was already deleted.
+This may happen due to different orders of deletion possible at exit. (JL)
+
+3/10/97 (bug fix) Fixed bug on Mac and Windows that caused time to be
+ignored when considering if a single click was actually a double
+click. (RJ)
+
+3/11/97 (feature change) A major oversight has been that although it was
+documented that the Tk programmer was asking for a font in points (1/72 of an
+inch), under Unix and Mac Tk was actually asking for a font in pixels, while
+only under Windows was it using points. This caused applications to appear
+much larger when run under Windows. Now, on all platforms the (purportedly)
+correct size in points is used when asking for fonts. However, for
+compatibility with existing tk4.2 applications that depend on fonts being of
+specified pixel size, XLFDs retain their incorrect behavior of getting a
+font in pixels. (CCS)
+*** POTENTIAL INCOMPATIBILITY ***
+
+3/13/97 (new feature) "tk scaling" command to setup the mapping between
+pixels and points. This scaling factor is used by all widgets that accept
+ruler distances, not just fonts. (CCS)
+
+3/24/97 (new feature) Added "-columnbreak" option to menu
+entries. When this value is "1", the entry will appear at the top of a
+new column in a non-menubar menu. Also added "-hideMargin". Together
+with "-columnBreak", menus with palettes are now possible. (SRP)
+
+3/26/97 (new features and bug fix) Titles for tearoff menus were
+broken on the Mac and Windows. Added the ability to set the title of a
+menu when it gets torn off and override Tk's automatic generation of
+the title. On the Macintosh, whenever a menu
+label contains three dots in a row "...", the menu will instead
+display the elipses character '…'. (SRP)
+
+3/27/97 (bug fixes) When a menu had an error executing a postcommand,
+the error information was getting lost. On Windows, a set of
+menubuttons was not highligting properly when clicking between
+windows. On Windows, post commands were getting executed twice for
+popup menus. On Macintosh, fixed problem where menubars were not
+always current. (SRP)
+
+4/11/97 (new feature) Menubuttons now have a direction flag which
+controls where the menu popups up relative to the button. (SRP)
+
+4/24/97 (bug fix) Transient windows did not obey the resizable setting
+under Windows. (SS)
+
+4/24/97 (bug fix) wm geometry did not correctly parse negative
+coordinates. (SS)
+
+4/29/97 (bug fix) Changed the canvas polygon implementation to only
+report the coordinates specified by the end user not the automatically
+generated end point of a self closing polygon. (RJ)
+*** POTENTIAL INCOMPATIBILITY ***
+
+4/23/97 (feature change) Loosened the rules on parsing font names so that
+unix-centric fonts in scripts don't break when run on Windows or Mac.
+(1) Previously, an XLFD had to specify font name, weight, slant, and size;
+now, a minimal XLFD (such as "*-times-*") will be accepted, and all
+unspecified attributes will be given default values. (2) Previously, in the
+{name size style ...} format, only the style was optional; now both the size
+and the style are optional; this solves the problem of old scripts that
+contain specifications of the form "-font fixed" or "-font times". (CCS)
+
+5/7/97 (new feature) Menus now send a virtual event <<MenuSelect>>
+when an item is highlighted in a menu. Applications can use this to
+implement context-sensitive help. (SRP)
+
+5/14/97 (bug fix) Fixed a race condition in the focus code where focus
+could be taken away from a window incorrectly. Scenario is that the main
+window creates a toplevel and assigns focus to it. When the user moves the
+mouse from the main window into the toplevel there was a race between
+two different kinds of focus events. (BW)
+
+5/20/97 (bug fix) Fixed bug where the clipboard was not rendered before
+the application exited. (SS)
+
+5/22/97 (feature change) When a Tk8.0 menu is configured, all menus
+derived from it (menubars, tearoff) mirror the changes. This was not
+true for the "-tearoff" flag. In Tk4.6, tearoff menus had the
+"-tearoff" flag turned off. Now, the "-tearoff" flag is tracked just
+as the other options are. Tearoff menus and menubars with the
+"-tearoff" option set will not display the tearoff item. This means
+that a given menu entry for a menu and a tearoff of that menu will
+match now. (SRP)
+*** POTENTIAL INCOMPATIBILITY ***
+
+----------------- Released 8.0b1, 5/27/97 -----------------------
+
+5/30/97 (bug fix) Made the options to the grid command shortcut-able.
+Ie. You can now use -stick, in addition to -sticky. (RJ)
+
+6/2/97 (bug fix) Fixed bug in startup code that caused a problem in
+finding the library files when they are installed in a directory
+containing a space in the name. (SS)
+
+6/2/97 (bug fix) Virtual events associated with <Enter>/<Leave> in text
+widget tag caused panic. (CCS)
+
+6/6/97 (bug fix) On some systems, struct timeval.tv_sec is unsigned. (SS)
+
+6/6/97 (feature change) Changed -default option on buttons to take
+three states: normal, active, disabled. This allows apps to have a
+row of buttons where the default ring moves between buttons without
+changing the geometry of the buttons. See the button.n manual page
+for more details. (SS)
+*** POTENTIAL INCOMPATIBILITY with Tk 8.0b1, but not with Tk 4.2 ***
+
+6/9/97 (bug fix) Canvas postscript printing now works for bitmaps
+under Windows. (SS)
+
+6/10/97 (bug fix) Fixed bug in bindings for listboxes where state wasn't
+being properly initialized on Shift-1 button presses. (JO)
+
+6/11/97 (bug fix) Text widget display code did not include internal
+padding in the damage calculation for borders leading to unrefreshed
+sections on Windows and Mac. (SS)
+
+6/12/97 (feature reversal) Changed default border widths under Unix
+back to 2 again. This reverses the change made on 11/7/96. (JO)
+
+6/13/97 (bug fixes) In canvas text item: the insertion cursor wasn't shown
+if insertion point was at end of text item, it was impossible to click to
+position the insertion point after the last character, and @x,y indices were
+computed incorrectly if -scrollregion had been specified and canvas was
+scrolled. (CCS)
+
+6/13/97 (bug fix) Hitting up/down arrows in a text widget packed in a
+toplevel window created with the "-screen" option would cause an error dialog
+to pop up. (CCS)
+
+6/12/97 (bug fix) Fixed bug in canvas text items where multi-line
+selections were not highlighted properly. This bug existed only in
+earlier releases of Tk 8.0. (JO)
+
+6/16/97 (bug fix) In some obscure cases, canvas window items could
+accidentally specified a 0x0 size for the window, which caused a
+BadValue error under X. (JO)
+
+6/17/97 (bug fix) Tk buttons on the Macintosh will now correctly
+draw under MacOS 8.0. (RJ)
+
+6/18/97 (feature change) Changed the way highlights are drawn in text
+widgets so that the empty space to the left of a line is highlighted
+whenever the leftmost character of the line is highlighted (the empty
+space didn't used to be highlighted). This produces a neater left
+edge when several lines are selected. (JO)
+
+6/18/97 (bug fix) Tk was using the wrong system colors to draw various
+widgets under Windows. (SS)
+
+6/19/97 (bug fix) Under Windows, the "wm transient" and "wm overrideredirect"
+subcommands can now be applied to a toplevel to change its window
+style at any time during the life of the window. (SS)
+
+6/19/97 (feature change) All GIF and XBM images needed for the "TK"
+file dialog box are included in-line in tkfbox.tcl. (IL)
+
+6/27/97 (bug fix) Revamped focus code to eliminate most XSetInputFocus
+calls from the FilterEvent procedure. This moves the implementation back
+towards the Tk 4.2 implementation, but adds embedding support. There is
+still a known bug with twm's NoTitleFocus and embedded windows. However,
+the races in a2 and the funny focus stealing in b1 are gone. (BW)
+
+6/25/97 (bug fix) Error message was not properly reported when using
+button 'toggle'. (DL)
+
+6/25/97 (bug fix) Removed one source of memory corruption in tkGrid.c code
+(fixes what was exercised by "grid col . 0 -w 1; grid col . 0 -w 25") (DL)
+
+----------------- Released 8.0b2, 6/30/97 -----------------------
+
+7/1/97 (bug fix) Menu shortcut and tearoff reported problem fixed. (DL)
+
+7/1/97 (new feature) TK_BUILD_SHARED flag set in tkConfig.sh
+when Tk has been built with --enable-shared. TK_SRC_DIR added.
+A new tkLibObjs make target, echoing the list of the .o's needed
+to build a tk library, is now provided. (DL)
+
+7/9/97 (bug fix) Fixed Tk_CreateFileHandler and Tk_DeleteFileHandler
+macros to directly call the Tcl equivalents. (JL)
+
+7/10/97 (bug fix) On the Mac, if the binding for <<MenuSelect>> was
+drawing, the drawing could bleed over into the menus. This is now
+fixed. (SRP)
+
+7/10/97 (bug fixes) Removed duplicate code related to Tk_SafeInit,
+made a single init script handling both cases. (DL)
+
+7/10/97 (feature change) On Unix, to be able to load Tk into a safe
+interp you need to set the env(DISPLAY) var. Some API should be
+added to allow master crontrol over Tk instantiation. (DL)
+
+7/11/97 (new feature) On the Mac, menus that are too big for the
+screen will now scroll. This is part of the interface on the Mac,
+impossible under Windows, and is not done for Unix. (SRP)
+
+7/21/97 (bug fix) After fixing the bug that in canvas text item the insertion
+cursor wasn't shown if insertion point was at end of text item, introduced a
+different bug in where clicking in entry widget with 0 characters would
+crash or display garbage. (CCS)
+
+7/22/97 (bug fix) If there were a whole bunch of returns or tabs in a row in
+a canvas text item, then the temporary buffer used when outputting
+postscript could overflow and overwrite the stack. (CCS)
+
+7/23/97 (feature change) Reenabled "tkwait" in the Safe Tk base. (JL)
+
+7/24/97 (bug fix) Single init script for both Win and Unix.
+new library/safetk.tcl using features from new tcl safe.tcl (DL)
+
+7/30/97 (feature change) As a result of native menus, you can no
+longer drag through a frame of menubuttons on Macintosh and Windows
+and have the menus pop down. You can still click on individual
+menubuttons and their menus will pop down. Applications needing to
+present a menubar should consider using the new "-menu" configuration
+of the toplevel widget to set up menubar which behaves correctly on
+Macintosh, Windows and X Windows. (SRP)
+
+7/31/97 (bug fix) Tk widget commands can now safely be hidden commands.
+Previously destroying the widget would potentially leave dangling pointers
+and destroy an exposed command instead of a hidden one if an exposed
+command by that name existed. (JL)
+
+7/31/97 (bug fix) On Windows, popup menus were not tracking the right mouse
+button correctly if it was used to invoke the menu. On Unix, tearoff
+menus were stealing focus when the mouse moving over them even when
+focus following was turned off. (SRP)
+
+8/4/97 (bug fix) Fixed problem under USENIX where raising a toplevel
+window could cause an X error if the window had just been withdrawn. (JO)
+
+8/4/97 (feature change) tkerror and bgerror are not anymore hard links
+maintained by the Tcl core. The implementation of bgerror provided by
+Tk tries, for backward compatibility only, to to call "tkerror" and
+if that fails, falls back to the usual dialog and stack trace option
+posting. You can thus still use either "bgerror" or "tkerror" as your
+application error handling proc, but using "bgerror" is strongly
+recommended as support for "tkerror" will eventually vanish in upcoming
+releases. (DL)
+*** POTENTIAL INCOMPATIBILITY with scripts that were using
+ the actual hardlink implementation 'features' and with
+ scripts (if any) that would be calling the default "tkerror" to
+ simulate error messages (use "bgerror" instead) ***
+
+8/7/97 (feature change/addition) Removed the gif files used for the
+Open dialog box on UNIX (they were previously made inline). Added a
+new images directory that includes several images of the Tcl and Tcl
+Powered logos. (RJ)
+
+8/7/97 (bug fix) Fixed focus to deal with embedding when there is
+no window manager. (BW)
+
+8/8/97 (bug fix) Fixed bug in photo image code where photo images from
+different interpreters could get confused if they had the same name. (JO)
+
+8/8/97 (new feature) Added new procedure Tk_GetImageMasterData for
+mapping image names to master data. (JO)
+
+8/8/97 (feature change) Modified Tk_FindPhoto procedure to require
+extra "interp" argument (needed for bug fix above). (JO)
+*** POTENTIAL INCOMPATIBILITY ***
+
+8/8/97 (bug fix) Fixed problems under Windows renaming toplevels with
+menubars. Fixed problems on all platforms renaming menu widgets and
+using new menus of the same name as an old one as cascades. Fixed a
+cosmetic problem with tearoff menus. (SRP)
+
+8/13/97 (bug fixes) Fixed "-from" option for the "image create" and
+"imageName read" commands for GIF images, which didn't used to work
+correctly. Also made transparency work correctly for GIF images
+without the TRANSPARENT_GIF_COLOR hack; TRANSPARENT_GIF_COLOR is
+now ignored. These fixes were provided by Jan Nijtmans. (JO)
+
+8/13/97 (new feature) added safe::loadTk command to load Tk in a
+safe slave interpreter. See the loadTk.n manual page for more
+details. (DL)
+
+----------------- Released 8.0, 8/18/97 -----------------------
+
+8/22/97 - (bug fix) Fixed syntax error in tk_popup; option menus now
+popup over their selected items like they did in tk4.2. Fixed problem
+where cascades sometimes did not work on X. On X, menubars with
+checkbuttons and radiobuttons in them would infinite loop when
+mappped. (SRP)
+
+8/27/97 (new feature) Added support for new X11R6 colors under Windows
+and Mac platforms. (SS)
+
+8/29/97 (bug fix) Wish crashed if stdin was closed. (SS)
+
+9/10/97 (bug fix) "font actual {helvetica 10} -displayof ." wasn't taking
+into account the "-displayof" option. This problem also existed for the
+"font metrics" and "font measure" commands. (CCS)
+
+9/16/97 (new feature) Added "resource delete" and "resource files"
+command to the Mac. Also fixed "resource write" when the resource
+was specified by id and already existed. (JI)
+
+9/16/97 (bug fix) Added null bindings to <Command-KeyPress> for the
+text and entry widget on the Macintosh. This prevents unbound command
+key sequences from having the character echoed to the widget. Also
+fixed Cut & Copy bindings. (JI) (RJ)
+
+9/18/97 (bug fix) Revamped Macintosh focus code. Cut, Copy & Paste
+virtual events now go to the correct (focus) window. (RJ)
+
+9/19/97 (bug fix) Made Macintosh tearoff menus non-resizable. (RJ)
+
+10/9/97 (bug fix) Default font for new canvas text items was hardcoded to
+"Helvetica 12" instead of using DEF_CANVTEXT_FONT defined in
+tk{platform}Default.h like all the other widget settings. (CCS)
+
+10/9/97 (bug fix) Image code could cause crashes during "exit" under
+some conditions (such as an image named "place"). (JO)
+
+10/9/97 (bug fix) Fixed bug that sometimes prevented listboxes from
+scrolling far enough horizontally to see the rightmost character. (JO)
+
+10/10/97 (bug fix) In canvas text items, if the text ended with a \n, it
+was not counted in the bbox height, as it did in tk4.2. This caused
+"hello\n" to be the same height as "hello" and you couldn't see the
+cursor positioned on the next line. (CCS)
+
+10/10/97 (bug fix) The grid geometry manager didn't always properly
+forget about windows after a "grid forget" or "grid remove" command:
+the windows could reappear on the screen later. (JO)
+
+10/13/97 (bug fix) Selection could not be restored to a text widget
+after "selection clear" on Windows. (SS)
+
+10/14/97 (bug fix) If a canvas had contained windows that were off-screen,
+the windows could sometimes reappear (in the wrong place) if the canvas was
+enlarged. (JO)
+
+10/20/97 (bug fix) Omitting the arguments to the text widget "mark
+gravity" option caused a crash. (SS)
+
+10/21/97 (bug fix) Tk did not reset the result after native dialog
+modal loops on Window so background events could perturb the dialog
+result. (SS)
+
+10/23/97 (bug fix) Memory leak in unix's TkpGetFontFamilies. Thanks
+to James Bonfield for the fix. (DL)
+
+10/27/97 (bug fix) Fixed event reporting for the Mac during a grab
+when the pointer was out of the toplevel window. (RJ)
+
+10/28/97 (bug fix) Under Unix, override-redirect was getting set
+incorrectly for menus, so that "wm overrideredirect" returned 0. (JO)
+
+10/28/97 (bug fix) Under Unix, focus code could sometimes cause the
+display to deadlock (it wasn't flushing the output buffer after issuing
+an ungrab command). (JO)
+
+10/28/97 (bug fix) If a PPM image file wasn't complete (e.g. it
+consisted of nothing but space characters) Tk entered an infinite loop
+reading the header. (JO)
+
+10/28/97 (bug fixes) On the Mac, menubars assigned to toplevels would
+disappear after a menu item was invoked from them. On Windows,
+clicking a system menu with added items and then again with a
+different set of added items would crash. On all platforms, a command
+menu entry that caused the entry to be deleted, another one created in
+its place, and the replacement deleted would cause a panic. On Unix,
+<<MenuSelect>> event bindings were firing every time the mouse moved,
+instead of everytime the active menu item changed. (SRP)
+
+10/27/97 (bug fix) If a particular race condition occurred under Windows,
+Tk would crash complaining about trying to free a color that wasn't
+allocated. (SS)
+
+10/28/97 (bug fix) Under Windows, button grabs did not report motion
+events that occurred outside of Tk windows. (SS)
+
+10/28/97 (bug fix) Fixed incorrect display of transparent images on
+the Macintosh. (JI)
+
+10/29/97 (bug fix) Reworked the handling of out-of-range indices in
+the widget command for listboxes: there were all sorts of quirks
+before (e.g., ".l delete -1" actually deleted the first element
+of the listbox). (JO)
+
+10/29/97 (bug fix) Fixed crash on the Macintosh that could occur if a
+window is moved before it is mapped where the X window was created but
+the Macintosh port was not. (RJ)
+
+10/29/97 (bug fix) Fixed several errors in how wm state was maintained
+on the Macintosh. Tk now also will iconify a toplevel window on the
+Mac if the new Appearance Manager is present. (RJ)
+
+10/28/97 (bug fixes) In canvas' postscript command: User name
+information was leaked in safe interpreters on Unix (security fix).
+Errors while reading prolog.ps were not propagated and the error
+message was mixed with partial data. Note: postscript output does
+not work in safe interpreters on unix and windows. (DL)
+
+10/28/97 (bug fix) Safe Tk interps on unix were leaking env(DISPLAY). (DL)
+
+10/31/97 (bug fix) Fixed problems related to the input focus when one
+application had windows open simultaneously on several displays. (JO)
+
+10/31/97 (bug fix) Fixed several problems with traversal of menus via
+the keyboard under Unix. (SRP)
+
+11/4/97 (bug fix) Fixed various word-size related problems for 64-bit
+architectures. (SS)
+
+11/5/97 (bug fix) Embedding on Windows was using freed data (crashing
+in safe.test with TCL_MEM_DEBUG). NB: Embedding is still not fully
+implemented on Windows ! (It works mostly when Tk is embeded into it's
+own Tk frame (safe::loadTk case), but not well with respect to resizing
+with a toplevel container or with an external process). (DL)
+
+----------------- Released 8.0p1, 11/7/97 -----------------------
+
+11/20/97 (bug fix) Fixed bug on the Mac where the "package require"
+command caused menus to stop working. (JI)
+
+11/20/97 (bug fix) Fixed bug in rendering transparent gifs on Text
+widgets. (JI)
+
+11/20/97 (enhancement) Made the changes required to work with the new
+Apple Universal Headers V. 3.0 so we can compile with CW Pro 2.0 (JI)
+
+----------------- Released 8.0p2, 11/25/97 -----------------------
+
+11/25/97 (security bug fix + added feature) Tk Safe Init now asks
+the master's safe::TkInit for the 'argv' to use. This is transparently
+dealt with by the safe::loadTk API. New optional "-display displayName"
+argument to safe::loadTk, and the "-use" argument accepts both window
+Ids and Tk window names: see loadTk(n). Made the ":0.0" default display
+work on the Mac as it works on Windows and Unix. (DL)
+
+12/3/97 (bug fix/optimization) Removed unneeded and potentially dangerous
+instances of double evaluations if "if" and "expr" statements from
+the library files. It is recommended that unless you need a double
+evaluation you always use "expr {...}" instead of "expr ..." and
+"if {...} ..." instead of "if ... ...". It will also be faster
+thanks to the byte compiler. (DL)
+
+12/3/97 (new feature) Added support for browser/plugin style embedding,
+and made various other fixes to get the plugin working on the Mac. (JI)
+
+12/8/97 (bug fix) on Windows, using "winfo pathname" before "." was mapped
+was crashing. (DL)
+
+---- Shipped as part of the plugin2.0b5 as 8.0p2Plugin1, Dec 8th 97 ----
+
+12/97 (bug fix) more Macintosh embeding fixes needed for the plugin. (JI)
+
+Jan/9/98 (improvement) Allow applications to have custom init script
+without having to patch the Tk core: Tk_Init will use an existing
+"tkInit" proc if one exists in the interp where one tries to install Tk
+instead of defining it's own (tkInit is the transient proc defined in
+generic/tkInitScript.h that searches and sources tk.tcl and defines
+the 'correct' tk_library). (DL)
+
+---- Shipped as part of the plugin2.0 as 8.0p2Plugin2, Jan 15th 98 ----
+
+6/3/98 (bug fix) Fixed bugs in the tk_getOpenFile under Unix.
+ 1) If the -initialdir option was "." the result would be "././foo.tcl"
+ instead of an absolute path, like the Windows interface.
+ 2) There is a traceVar on the data(selectPath) where the script was
+ assumes the window exists. (BS)
+
+6/12/98 (feature change) Focus -force now sets the foreground window
+on Windows platforms in addition to moving the focus. (SS)
+
+6/12/98 (bug fix) Fixed bug in Windows font measurement that did not
+take kerning into account. (BS)
+
+6/24/98 (bug fix) On Unix, fixed -initialdir switch to tk_getOpenFile
+and tk_getSaveFile to convert the specified directory to an absolute
+path and to use the current working directory if the specified
+directory does not exist. (SS)
+
+6/25/98 (bug fix) On Unix, both the Tk and the Motif file dialogs
+would fail if the -parent flag changed between two parent windows that
+had been previously used as file dialog parents. (SS)
+
+6/29/98 (compatibility patch) Added reserved fields to several Tk
+structures to match additions made by Jan Nijtmans dash patch. This
+means that extensions can be compiled against the dash patch
+and still work with unpatched Tk, and vice versa.
+
+7/6/98 (bug fix) Added keysym definitions for the new keys on the
+Microsoft keyboards. You can bind to <App>, <Win_L>, and <Win_R>,
+but you cannot use the Win keys as modifiers. (SS, BW)
+
+7/6/98 (new feature) Added support for the Macintosh Appearance Manager. (JI)
+
+7/24/98 (feature change) Eliminated the static variable that sets
+tk_library and simplified search order for tk.tcl. The tk_library
+variable can now be set before calling Tk_Init to avoid doing any
+searches. If it isn't set, then Tk checks env(TK_LIBRARY), relative
+to tcl_library, an install directory relative to the executable, a
+source directory relative to the executable, and a tk directory
+relative to the source heirarchy containing the executable. See the
+comment at the top of generic/tkInitScript.h for more details. (SS)
+
+7/27/98 (bug fix) The bbox for coords in the canvas were incorrectly
+including the center of the coord as part of the bound area. (RJ)
+
+8/4/98 (bug fix) Fixed memory leak in Windows menu code. (SS)
+
+8/4/98 (bug fix) Fixed bug where bgerror's were not being generated
+from menu callbacks on Windows. (SS)
+
+8/4/98 (bug fix) Alt-key bindings were not being handled properly
+under Windows, resulting in annoying beeps. (SS)
+
+8/4/98 (bug fix) Fixed bug in Windows menubar handling that allowed
+a shared menubar to be deleted when any window using it was deleted. (SS)
+
+8/4/98 (feature change) Introduced TkReadBitmapFile to replace
+XReadBitmapFile so that all Tk file opens go through the Tcl channel
+mechanism. This lets us wrap applications that define their own
+bitmaps and cursors. Note that XReadBitmapFile is no longer
+emulated for non-unix platforms platforms (RJ, BW)
+
+8/5/98 (bug fix) <Insert> binding in entries was masking the virtual
+event <<Paste>> binding to Shift-Insert on Windows. (SS)
+
+8/5/98 (bug fix) wm frame would crash if the window had not been
+mapped yet on Windows. (SS)
+
+8/5/98 (bug fix) Local grabs did not exclude menus or the caption bar
+under Windows. (SS)
+
+8/5/98 (bug fix) Reduced message traffic by setting
+WS_EX_NOPARENTNOTIFY on TkChild windows. (SS)
+
+8/6/98 (feature change) Changed tkInitScript.h to use the new
+tcl_findLibrary procedure to locate its script library. (BW)
+
+8/10/98 (bug fix) Added special case to font code to limit the
+length of displayed strings to avoid wrap-around bugs in some
+PC X servers when the pixel length of the string exceeds 0x7fff. (SS)
+
+8/12/98 (bug fix) Macintosh, lock down some of the resources
+associated with menus to try and stabilise the menu system
+on memory limited machines. (JI)
+
+8/12/98 (windows build change) Moved the tkConsole.obj into the tk80.dll
+on windows. If you build your own Tk main program, you no longer
+need to compile and link this yourself. (SKS)
+
+-------- Released 8.0.3 to the Tcl Consortium CD-ROM project, 8/13/98 ------
+
+10/5/98 (new feature) Added the event "MouseWheel" that will fire on
+Windows applications in response to mouse wheel movement. You can
+bind to the MouseWheel event and use the %D substitution to get the
+delta the wheel moved. The "event generate" command has also been
+enhanced with the -delta flag so you can generate these events from
+Tcl. See the bind and event man pages for more details. The listbox
+and text widgets' default bindings have been updated to understand
+MouseWheel events. (RJ)
+
+10/12/98 (performance improvement) Added hash table to canvas widget
+that holds numeric ids for items. The hash table makes item lookup
+almost constant time which improves certain canvas operations
+(exspecially for canvases with large number items). Thanks to Mark
+Weissman <weissman@gte.com> and Jan Nijtmans <Jan.Nijtmans@wxs.nl>
+for submitting this improvement. (RJ)
+
+10/15/98 (bug fix) The -fill option to text items in the canvas did
+not allow the empty string as an argument (meaning transparent) even
+though every other item type did. Thanks to Sebastian Wangnick
+<sebastian.wangnick@eurocontrol.be> for supplying this patch. (RJ)
+
+10/20/98 (feature change) The Makefile and configure scripts have been
+changed for IRIX to build n32 binaries instead of the old 32 abi
+format. If you have extensions built with the o32 abi's you will need
+to update them to n32 for them to work with Tcl. (RJ)
+*** POTENTIAL INCOMPATIBILITY ***
+
+11/10/98 (feature change) The Macintosh menus will use the Appearance
+Theme backgrounds, separators and menu shape, if Appearance version
+1.0.1 or greater is installed. The version of Appearance that shipped
+with MacOS 8.0 so it will not work with a straight 8.0, but it will
+with MacOS 8.1 or later. (JI)
+
+----------------- Released 8.0.4, 11/20/98 -----------------------
+
+11/24/98 (bug fix) On some X servers, XQueryLoadFont will always
+return a font, even if the name is meaningless. This prevents Tk from
+parsing the font name, so now we perform a quick sanity check on the
+name before letting X have it. (stanton)
+
+12/30/98 (bug fix) Fixed bug in "grid forget" that failed to cancel
+pending idle handlers, resulting in a crash in a few odd cases. (stanton)
+
+1/28/99 (configure change) Now support -pipe option on gcc. (RJ)
+
+2/4/99 (bug fix) Changed so color tables in photo images are freed
+immediately instead of being delayed. This ensures that color tables
+are properly disposed at process exit. (stanton)
+
+2/4/99 (bug fix) Changed postscript template to include a European
+character with an umlaut when determining font height. (stanton)
+
+2/4/99 (bug fix) If an image bitmap mask changed but ended up with the
+same XID, the GC failed to be updated and so the new mask was
+not used. (stanton)
+
+2/4/99 (bug fix) Changed so focus window is always set if -force is
+specified. This fixes the problem on Windows where Tk does not
+activate the window if it already has focus. (stanton)
+
+2/4/99 (bug fix) Fixed so errors in console eval are reported
+properly. Eliminated duplicate result messages. (stanton)
+
+2/4/99 (bug fix) Under Windows, changed so toplevels that aren't
+resizable don't have resize handles and the zoom box is disabled. (stanton)
+
+2/4/99 (bug fix) Changed to cancel the mouse timer when a user
+initiated move/resize loop begins on Windows. (stanton)
+
+2/4/99 (configure change) TK_LD_SEARCH_FLAGS was set incorrectly if
+SHLIB_LD_LIBS='${LIBS}', and shared linking is performed through the C
+compiler. Systems affected are Linux, MP-RAS and NEXTSTEP, but also
+with gcc on many more systems.
+
+2/4/99 (bug fix) Changed some EXTERN declarations to extern since they
+are not defining exported interfaces. This avoids generating useless
+declspec() attributes and makes the Windows makefile simpler. (stanton)
+
+2/4/99 (bug fix) Changed so keyboard shortcuts will only be found in
+the current toplevel. Previously, they might be found in menus
+attached to other toplevels that might not even be mapped. (stanton)
+*** POTENTIAL INCOMPATIBILITY ***
+
+2/4/99 (bug fix) Changed to treat zero width lines in the canvas like
+they have width 1 for purposes of selection. (stanton)
+
+2/4/99 (bug fix) Added a workaround for a bug in GetTextExtentExPoint
+on Win NT 4.0/Japanese that cause a crash in some cases. (stanton)
+
+2/4/99 (bug fix) Fixed uninitialized memory access bug in Unix send
+code. (stanton)
+
+----------------------------------------------------------
+Changes for Tk 8.0 go above this line.
+Changes for Tk 8.1 go below this line.
+----------------------------------------------------------
+
+1/16/98 (new feature) Tk now supports international characters sets:
+ - Font display mechanism overhauled to display Unicode strings
+ containing full set of international characters. You do not need
+ Unicode fonts on your system in order to use tk or see international
+ characters. For those familiar with the Japanese or Chinese patches,
+ there is no "-kanjifont" option. Characters from any available fonts
+ will automatically be used if the widget's originally selected font is
+ not capable of displaying a given character.
+ - Textual widgets are international aware. For instance, cursor
+ positioning commands would now move the cursor forwards/back by 1
+ international character, not by 1 byte.
+ - Input Method Editors (IMEs) work on Mac and Windows. Unix is still in
+ progress.
+
+7/7/97 (new feature) The send command now works for Microsoft
+Windows. It is implemented using Dynamic Data Exchange, and a new
+command, dde, allows Tk to send more generic DDE commands to other
+applications. (SRP)
+
+11/3/97 (new feature) Major overhaul of code that manages configuration
+options to use Tcl_Obj structures instead of strings:
+ - There is a new set of procedures including Tk_CreateOptionTable,
+ Tk_InitOptions, and Tk_SetOptions, which replace Tk_ConfigureWidget
+ and related procedures. The old procedures are still available.
+ The new procedures use a new format for configuration tables.
+ See SetOptions.3 for more information.
+ - There are new procedures Tk_AllocColorFromObj, Tk_GetColorFromObj,
+ and Tk_FreeColorFromObj to manage colors using objects to hold the
+ name of the color and cache the corresponding XColor pointer.
+ There are similar procedures Tk_Alloc3DBorderFromObj,
+ Tk_AllocBitmapFromObj, Tk_AllocCursorFromObj, Tk_AllocFontFromObj,
+ and so on to manage borders, bitmaps, cursors, and fonts.
+ - The old-style procedures such as Tk_GetColor and Tk_GetBitmap no
+ longer take Tk_Uids for arguments; they just take strings.
+ - Menus, labels, buttons, checkbuttons, and radiobuttons have been
+ converted to use the new object-based configuration library.
+ (SRP & JO)
+
+11/7/97 (improvement) Changed code referring to "interp->result" to call
+accessor functions like Tcl_SetResult().
+
+12/23/97 (fix) Fixed transparency and web optimized the palette of
+the images/ Tcl powered logos. (DL)
+
+12/16/97 (bug fix) Canvas and text "bind" subcommands generated an
+error with no message if called to fetch a binding that didn't exist.
+They now silently return without an error like the "bind" command. (SS)
+
+1/13/98 (bug fix) Keysyms for international characters were not being
+reported properly under Windows. (SS)
+
+----------------- Released 8.1a1, 1/22/98 -----------------------
+
+2/4/98 (bug fix) Calling XFreeFontNames() twice if couldn't allocate
+font. (CCS)
+
+2/10/98 (bug fix) Inlined prolog.ps in tkCanvPs.c to make it accessible
+from safe interpreters: canvas postscript now works in safe interps
+(like in tk8.0plugin). (DL)
+
+2/11/98 (bug fix) Windows "send" to a remote interp wasn't propagating
+$errorInfo correctly from the remote interp to the local invoking interp.
+(CCS)
+
+2/11/98 (bug fix) Windows "send" should have accepted "--" to mean "no more
+arguments". (CCS)
+
+2/11/98 (bug fix) Windows "send" was concatenating its arguments
+incorrectly (not consistent with "eval", "uplevel", or Unix "send"). (CCS)
+
+2/18/98 (bug fix) Macintosh radiobuttons and checkbuttons now color
+their backgrounds correctly under Appearance. The controls gadgets themselves
+however, remain the Theme colors. (JI)
+
+2/18/98 (improvement) The corner pixels that peek through around the
+rounded corners of the Mac button widget are now controlled by the
+-highlightbackground, rather than the -background option. (JI)
+
+2/18/98 (improvement) Implemented the intra-application Send on the
+Mac (RJ)
+
+2/18/98 (bug fix) Under X, a problem mapping from a fontStructPtr to an
+XLFD (no XA_FONT attribute) would lead to dereferencing NULL. (CCS)
+
+----------------- Released 8.1a2, Feb 20 1998 -----------------------
+
+10/21/98 (bug fix) Tk_UnderlineChars did not handle UTF strings properly
+so underline indices were in bytes instead of characters. (stanton)
+
+11/19/98 (bug fix) Fixed menus and titles so they properly display
+Unicode characters under Windows. [Bug: 819] (stanton)
+
+11/24/98 (bug fix) Fixed a bunch of memory leaks in the Windows menu
+code. [Bug: 620] (stanton)
+
+11/25/98 (bug fix) Various small bug fixes: (stanton)
+ - hidemargin option was not honored properly in menus [Bug: 859]
+ - disabled menu entries were getting reenabled whenever the
+ mouse passed over the entry [Bug: 860]
+ - fixed deletion order bug where a crash would result if a
+ binding deleted "."
+
+11/30/98 (bug fix) The error result was getting lost when restoring
+configuration options in buttons. [Bug: 619] (stanton)
+
+12/8/98 (bug fix) The Windows clipboard was not correctly traslating
+multibyte characters. [Bug: 935] (stanton)
+
+----------------- Released 8.1b1, Dec 11 1998 -----------------------
+
+1/29/99 (bug fix) Fixed bug in "grid forget" that failed to cancel
+pending idle handlers, resulting in a crash in a few odd
+cases. (stanton)
+
+2/4/99 (bug fix): Fixed uninitialized memory access in
+Tk_SetAppName. [Bug: 919] (stanton)
+
+2/4/99 (bug fix): Added a workaround for a bug in GetTextExtentExPoint
+on Win NT 4.0/Japanese. [Bug: 1006] (stanton)
+
+2/4/99 (bug fix): Changed so keyboard shortcuts for menus will only be
+found in the current toplevel. Previously, they might be found in
+menus attached to other toplevels that might not even be mapped.
+[Bug: 924] (stanton)
+
+2/4/99 (bug fix): Changed to treat zero width lines in the canvas like
+they have width 1 for purposes of selection. [Bug: 925] (stanton)
+
+2/4/99 (bug fix): TK_LD_SEARCH_FLAGS was set incorrectly if
+SHLIB_LD_LIBS='${LIBS}', and shared linking is performed through the C
+compiler. Systems affected are Linux, MP-RAS and NEXTSTEP, but also
+with gcc on many more systems. [Bug: 908] (stanton)
+
+2/4/99 (feature enhancement): Changed so windows that aren't resizable
+don't have resize handles and the zoom box is disabled on
+Windows. (stanton)
+
+2/4/99 (bug fix): Fixed so errors in console eval are reported
+properly. Eliminated duplicate result messages. [Bug: 973] (stanton)
+
+2/4/99 (bug fix): Changed so focus window is always set if -force is
+specified. This fixes the problem on Windows where Tk does not
+activate the window if it already has focus. (stanton)
+
+2/4/99 (bug fix): If an image mask changed but ended up with the same
+XID, the GC failed to be updated and so the new mask was not
+used. [Bug: 970] (stanton)
+
+2/12/99 (new feature): Tk is now thread safe. You enable this by
+configuring with --enable-threads. Tcl must also be compiled with
+--enable-threads. See Tcl for more information about the threading
+interfaces. (lfb)
+
+2/25/99 (bug fix) Under Windows, wish can now inherit pipe handles on
+stdio so it is possible to use the wish executable in a command
+pipeline to capture the output of puts or read from the pipe with
+gets. (redman)
+
+3/1/99 (bug fix) Under Windows, Tk was not properly handling focus and
+activation changes in some cases. (redman)
+
+3/10/99 (new feature) Tk now uses the new stub library feature in Tcl.
+The Tk library now contains no direct references to any symbols in
+Tcl. In addition, there is a new Tk_MainEx() function that takes an
+interpreter as an argument. See the Tcl documentation for more
+information about the stubs mechanism. (redman)
+
+3/14/99 (feature change) Test suite now uses "test" namespace to
+define the test procedure and other auxiliary procedures as well as
+global variables.
+ - Global array testConfige is now called ::test::testConfig.
+ - Global variable VERBOSE is now called ::test::verbose, and
+ ::test::verbose no longer works with numerical values. We've
+ switched to a bitwise character string. You can set
+ ::test::verbose by using the -verbose option on the Tk command
+ line.
+ - Global variable TESTS is now called ::test::matchingTests, and
+ can be set on the Tk command line via the -match option.
+ - There is now a ::test::skipTests variable (works similarly to
+ ::test::matchTests) that can be set on the Tk command line via
+ the -match option.
+ - The test suite can now be run in any working directory. When
+ you run "make test", the working directory is nolonger switched
+ to ../tests.
+(hirschl)
+*** POTENTIAL INCOMPATIBILITY ***
+
+----------------- Released 8.1b2, March 16, 1999 ---------------------
+
+3/23/99 (feature change) Test suite now uses "tcltest" namespace to
+define the test procedure and other auxiliary procedures as well as
+global variables. The previously chosen "test" namespace was thought
+to be too generic and likely to create conflits.
+(hirschl)
+*** POTENTIAL INCOMPATIBILITY ***
+
+3/26/99 [bug fix] Fixed bug reported by Bryan Oakley in the
+menubutton bindings. There was a false assumption that there was
+always a menu attached to the button. [Bug 1116] (surles)
+
+3/26/99 (feature change) Removed --enable-tcl-stub from the configure
+script. Linking Tk to Tcl stubs is causing too many problems when
+linking executables like wish. Until the Tk is a fully loadable
+extension, linking against the Tcl stubs is not supported in Tk.
+(redman)
+
+3/26/99 (feature change) --nameble-shared is now the default and builds
+Tk as a shared library; specify --disable-shared to build a static Tk
+library and shell.
+*** POTENTIAL INCOMPATIBILITY ***
+
+3/29/99 (api change) Standardized text layout and font interfaces
+so they are consistent with respect to byte versus character
+oriented indices. The layout functions all manipulate character
+oriented values while the lower level measurement functions all
+operate on byte oriented values. (stanton)
+
+4/1/99 (bug fix) Image handlers are finalized before the font subsystem
+to fix crashes during finalization of complex widgets. (stanton)
+
+4/1/99 (feature change) Removed the send command on Windows. Moved
+the DDE basis of that command out to its own extension. The send
+implementation on top of DDE was causing Tk to lock up in some cases.
+(redman)
+
+4/5/99 (bug fix) Fixed handling of Unicode in text searches. The
+-count option was returning byte counts instead of character counts.
+
+4/5/99 (feature change) Cut and paste to an entry widget returns the
+selection instead of the widget contents, which can be different if the
+-show option is used to hide the display. (stanton)
+
+--------------- Released 8.1b3, April 6, 1999 ----------------------
+
+4/20/99 (compiler fix) changed definition of Status type to use a
+typedef instead of a #define to avoid conflicting with the cygwin win32
+headers. (redman)
+
+4/22/99 (bug fix) Set the -translation and -encoding options to binary
+for image files. (redman)
+
+4/27/99 (bug fix) Changed to avoid the need for forward declarations in
+stub initializers. Added extern "C" blocks around stub table pointer
+declarations so the stubs can be used from C++ code. (stanton)
+
+--------------- Released 8.1 final, April 29, 1999 ----------------------
+
+5/7/99 (bug fix) Fixed bug wheretk_popup fails when called too
+quickly. [Bug: 2009] (stanton)
+
+5/18/99 (bug fix) Fixed clipboard code so it handles Unicode data
+properly on Windows NT and 95. [Bug: 1791] (stanton)
+
+5/19/99 (bug fix) Add extern "C" block around entire header file for
+C++ compilers to fix linkage issues. Submitted by Don Porter and Paul
+Duffin. (redman)
+
+--------------- Released 8.1.1, May 25, 1999 ----------------------
+
+5/21/99 (bug fix) Fixed clipboard code to handle lack of CF_LOCALE
+information (from command.com). (stanton)
+
+6/1/99 (bug fix) Improved I18N selection support. COMPOUND_TEXT
+is converted to/from iso2022, and STRING is converted to/from
+iso8859-1. More work is needed. (stanton)
+
+6/3/99 (bug fix) Fixed selection code to handle Unicode data in
+COMPOUND_TEXT and STRING selections. [Bug: 1791] (stanton)
+
+6/16/99 (new feature) Changes to makefiles and configure scripts to
+support TEA specification. (wart)
+
+6/30/99 (bug fix) Removed deprecated functions, patch from Jan
+Nijtmans. [Bug 2080] (redman)
+
+6/30/99 (bug fix) Applied patch to allow Img extension to work with
+8.2, patch from Jan Nijtmans. [Bug 2068] (redman)
+
+6/30/99 (bug fix) Applied patch from Don Porter to prevent the Windows
+shutdown code from calling Tcl functions when the stub table has not
+been initialized in TkWinWmCleanup. [Bug: 2269] (redman)
+
+7/8/99 (bug fix) Changed TkWinChildProc to pass WM_WINDOWSPOSCHANGED
+through to DefWindowProc to make OpenGL sub-windows happpy. This
+allows Windows to generate the WM_SIZE and WM_MOVE messages. (stanton)
+
+--------------- Released 8.2b1, July 14, 1999 ----------------------
+
+7/16/99 (bug fix) Copy prolog.ps from the generic directory for
+install-libraries make target. (redman)
+
+7/22/99 (bug fix) Applied patch from Jeff Hobbs to fix
+library/menu.tcl. [Bug: 2425] (redman)
+
+7/22/99 (bug fix) Make install-sh have executable permissions before
+calling from the Makefile. [Bug: 2413] (redman)
+
+7/22/99 (bug fix) Block out sys/stat.h include with #if to allow
+extension writers to use the MetroWerks compiler on Windows.
+[Bug: 2385] (redman)
+
+7/29/99 (bug fix) Allow tcl to opn CON and NUL on Windows, moved check
+to Tk Console code instead. [Bug: 2393 2392 2209 2458] (redman)
+
+7/30/99 (bug fix) corrected the Windows build of threaded Tk from both
+sets of makefiles (nmake and gmake). (redman)
+
+7/30/99 (bug fix) Added XFillRectangle to stub table, patch from Jan
+Njitmans. [Bug: 2446] (hobbs)
+
+8/1/99 (bug fix) Wrapped #define of panic() inside #ifndef blocks to
+avoid compiler errors on Macintosh. Patch from Vince Darley.
+[Bug: 2389] (hobbs)
+
+--------------- Released 8.2b2, August 5, 1999 ----------------------
+
+8/13/99 (Mac) Rearranged the projects in the tkMacProjects.sea.hqx so
+that the build directory is separate from the sources. Fixed bug in
+Tk_DrawChars(). (Jim Ingham)
+
+--------------- Released 8.2.0, August 17, 1999 ----------------------
+
+9/21/99 (bug fix) fixed 'wm deiconify' quirks on Windows. (hobbs)
+
+9/21/99 (bug fix) fix fg<>bg GC swap bug for canvas. [Bug: 2676] (hobbs)
+
+9/21/99 (config fix) fixed AIX config issues for Tk. (hobbs)
+
+9/24/99 (feature change) tk_dialog now uses {Times 12} by default. (hobbs)
+
+--- Released 8.2.1, October 04, 1999 --- See ChangeLog for details ---
+
+10/30/99 (bug fix) fixed XKeysymToKeycode to handle mapping of symbolic
+keysyms (Left, Home, ...) with event generate (hobbs)
+
+10/30/99 (bug fix) change tkEntrySeeInsert to avoid the use of a while loop
+that could eat CPU tremendously. Behavior of moving the cursor at the
+right edge changes slightly. [Bug: 3195] (hobbs)
+
+10/30/99 (bug fix) changed tkScrollButtonUp to check for existence of
+tkPriv(relief) in order to avoid spurious release events (hobbs)
+
+--- Released 8.2.2, November 04, 1999 --- See ChangeLog for details ---
+
+11/19/99 (bug fix) fixed expression error that could cause
+'malformed bucket chain' error in tkEntry.c. (hobbs)
+
+11/19/99 (bug fix) fixed Tk_NameOfColor (hobbs)
+
+--- Released 8.2.3, December 16, 1999 --- See ChangeLog for details ---
+
+1999-09-01 (feature enhancement) rewrote runtime libraries to use new
+Tcl functions where appropriate
+
+1999-10-28 (feature enhancement) added Img patch from Jan Nijtmans that
+makes the image command Tcl_Obj-based, adds support for binary -data args,
+adds alpha channel to images, adds GIF write capability (RLE). Binary
+compatability is maintained, and source level compatibility is retained
+with -DUSE_OLD_IMAGE. (nijtmans)
+
+1999-11-16 (feature enhancement) made listbox Tcl_Obj based, added
+-listvariable option and itemconfigure command to allow coloring
+individual items. (melski)
+
+1999-11-23 (feature enhancement) added TK_OPTION_DONT_SET_DEFAULT as an
+equivalent to TK_CONFIG_DONT_SET_DEFAULT (hobbs)
+
+1999-11-24 (feature enhancement) updated dialogs to use color icons on
+Unix, center properly over -parent. (hipp, hobbs)
+
+1999-12-01 (feature enhancement) added hooks into main() code to support
+"big" shells more easily. (redman)
+
+1999-12-02 (feature enhancement) converted Tk_DestroyCmd, Tk_LowerCmd and
+Tk_RaiseCmd to their ObjCmd equivalent.
+
+1999-12-12 (bug fix) fixed bug in TextSearchCmd for multibyte chars
+
+1999-12-13 (feature enhancement) added support for pointer warping via the
+event -warp option, added some items from Dash patch: canvas widget now
+Tcl_Obj-based, added Tk_CreateSmoothMethod, added support for <Quadruple>
+clicks, entry widget validation routines, new -state hidden in text
+widgets, new -state -active* -disabled* -offset options to canvas items
+(see man page for full docs). New features include dashed line support on
+the canvas, -elide support for TkMan, postscript printing of images and
+windows from the canvas. Binary compatibility is maintained with 8.2, and
+source level compatibility is kept by using -DUSE_OLD_CANVAS.
+(hobbs, nijtmans, et al)
+
+1999-12-16 (feature enhancement) added "bitstream cyberbit" to list of
+font fallbacks. (hobbs)
+
+1999-12-16 (feature enhancement) added new 'tk useinputmethods ...' command
+to provide support for disabling/enabling the use of XIM on X. This was
+previously all done at compile time, and always on. Now it is turned off
+by default, even when available, and the user must turn it on to use XIM
+(per display).
+ *** POTENTIAL INCOMPATIBILITY ***
+user must add 'tk useinputmethods 1' to retain old style. (hobbs)
+
+1999-12-16 (feature enhancement) added proper support for -initialfile
+to tk_get*File, and made Unix version better match Windows file box
+that it was emulating. (hobbs)
+
+1999-12-16 (bug fix) removed necessity of 'update idle' before 'wm
+deiconify' on Windows. (mao)
+
+1999-12-16 (feature enhancement) added support for Windows system cursors
+to TkGetCursorByName (use -cursor @filename)
+
+1999-12-21 (bug fix) fixed lack of refresh for thin frames (darley)
+
+1999-12-21 (bug fix) fixed panic in Tk_CoordsToWindow to print error
+to stderr instead (for Tix) (hobbs)
+
+1999-12-21 (bug fix) fixed segv with scale widget when using -cursor (hobbs)
+
+--- Released 8.3b1, December 22, 1999 --- See ChangeLog for details ---
+
+2000-01-05 (bug fix) Applied fixes for unprotected arg passing through eval
+and after in Tk runtime code [Bug: 3943] (hobbs)
+
+2000-01-05 (bug fix) Applied fix for i18n problems with Mac clipboard
+[Bug: 3544] (hobbs)
+
+2000-01-05 (feature change) removed the 8.3b1 introduced -state option
+for text tags, and documented -elide (-state hidden == -elide true) (hobbs)
+
+2000-01-12 (bug fix) fix Windows 'wm deiconify' to zoomed state [Bug: 2077]
+and fixed possible flashing of unmapped toplevel in deiconify [Bug: 3338]
+and fixed unwanted mapping of transient window [Bug: 572] (hobbs)
+
+2000-01-12 (feature enhancement) extended 'wm state' to accept a state
+to set for the toplevel, and added support for zoomed (maximized) state
+on Windows (hobbs)
+
+2000-01-12 (bug fix) Applied fix for cursor to not blink when entry or
+text widget was disabled [Bug: 1807] (hobbs)
+
+--- Released 8.3b2, January 13, 2000 --- See ChangeLog for details ---
+
+2000-01-20 (bug fix) fixed interpretation of consecutive ^ characters in
+grid command (melski)
+
+2000-01-20 (bug fix) fixed -select(bg|fg) class names in listbox (hobbs)
+
+2000-01-20 (bug fix) fixed handling of too few coords for line item type in
+canvas (hobbs)
+
+2000-01-20 (bug fix) fixed dialog's association with parent (melski)
+
+2000-01-26 (bug fix) fixed handling of binary data for -data option to
+image create (melski)
+
+2000-01-26 (feature enhancement) improved GIF decoding speed by ~60%
+(melski)
+
+2000-01-26 (feature enhancement) added tk_chooseDirectory implementation
+for Unix and Mac (nelson, melski)
+
+2000-02-01 (bug fix) fixed resolution rounding problem in scale (porter)
+and fixed potential Unix seg fault due to use of ckfree instead of
+Tcl_EventuallyFree (hobbs)
+
+2000-02-01 (bug fix) fixed handling of negative dash values for canvas
+items (nijtmans)
+
+2000-02-01 (bug fix) fixed dialog lockup on Windows where once the native
+dialog disappeared, the parent window could end up locked up (hobbs)
+
+2000-02-03 (bug fix) fixed text dump to use char indices instead of byte
+indices (melski)
+
+2000-02-07 (bug fix) fixed handling of default extension in unix file
+dialogs (dejong)
+
+2000-02-08 (bug fix) corrected windows symbol font use to restrict itself
+to 8-bit chars (kenny)
+
+2000-02-08 (feature enhancement) improved support for moving from the old
+style image C API to the new obj'ified one with new Tk_InitImageArgs
+command and stub'ing of image code. See docs for how to make the
+transition. (nijtmans)
+
+2000-02-08 (bug fix) fixed incorrect handling of CapsLock on Win9* and the
+use of dead keys on international keyboards (spjuth)
+
+2000-02-10 (bug fix) brought Mac back to building state, added support
+for Appearance Manager (ingham)
+
+2000-02-10 (feature enhancement) added support for buttons 4 && 5 as
+mousewheel style scrolling in listbox and text widget for Unix.
+
+--- Released 8.3.0, February 10, 2000 --- See ChangeLog for details ---
+
+2000-03-02 (bug fix) fixed crash in listbox when cursor was configure and
+then widget was destroyed (hobbs)
+
+2000-03-02 (feature enhancement) added %V substitution to entry widget
+validation to clarify type of validation occuring (hobbs)
+
+2000-03-07 (feature enhancement) added -disabledforeground/-state to labels
+(melski)
+
+2000-03-29 (config enhancement) improved build support for gcc/mingw on
+Windows (nijtmans, hobbs) and added RPM target (melski)
+
+2000-03-24 (bug fixes) numerous corrections for more correct Unix dialog
+behaviors (melski)
+
+2000-03-27 (bug fix) fixed mem leak in wm commands (hu)
+
+2000-03-31 (bug fix) correct initialization of Windows static builds and
+added Unicode aware open/save file dialogs on Windows (hobbs)
+
+2000-03 (bug fix) canvas: corrected support for transparency in dashed
+lines on Windows (nijtmans); added support for postscript generation of
+images on Windows, also fixing transparency printing (biancardi); corrected
+handling of configure options in non-empty canvas (melski)
+
+2000-04-07 (bug fix) correct font name length restriction that prevented
+the use of long named (>16 char) fonts on NT/2000 (hobbs)
+
+2000-04-07 (bug fix) fixed safe Tk to work in base cases (hobbs)
+
+2000-04-10 (bug fix) corrected Alt-Key event generation and handling of
+Alt-sequence Windows special char generation and (Control|Shift|Alt)_L/_R
+determination (melski)
+
+2000-04-10 (bug fix) correctly check state of parent when popping up
+bgerror dialog. (melski)
+
+2000-04-11 (feature enhancement) msgcat now searches up the namespace chain
+for a match instead of just in the local namespace (hershey)
+
+2000-04-12 (bug fix) corrected handling of Windows clipboard to allow for
+use of user-defined types within the Tk app (hobbs)
+
+2000-04-13 (feature enhancement) improved handling of shadow determination
+for 3D borders in very light/dark cases (hipp, melski)
+
+2000-04-13 (bug fix) correctly color separator bg in menus on Windows
+(melski)
+
+2000-04-14 (bug fix) improved handling of scale widget, reduced number of
+redraws (hobbs)
+
+2000-04-17 (feature enhancement) made shift-selection more Windows-like
+(intuitive) in text widget (melski)
+
+2000-04-22 (bug fix) mac bug fixes, nav services handling (ingham)
+
+2000-04 more docs for public APIs (melski)
+
+--- Released 8.3.1, April 26, 2000 --- See ChangeLog for details ---
+2000-04 (doc updates) extended, updated docs (melski)
+
+2000-05-09 (feature change) removed WS_EX_TOOLWINDOW style bit for
+transient windows on Windows platforms, so that transients have
+full-size titlebars (melski)
+
+2000-05-09 (bug fix) fixed calling of takeFocus proc (nemethi)
+
+2000-05-11 (bug fix) corrected handling of 3DBorder, Cursor and Color
+objects on multiple screens (hobbs)
+
+2000-05-12 (feature enhancement) improved support for chars in 0-255
+range for bitmap ANSI fonts (spjuth, hobbs)
+
+2000-05-12 (widget enhancement) added support for -repeatdelay,
+-repeatinterval for command buttons; and -compound (image and text
+simultaneously) for labels, check-, radio-, and command buttons (melski)
+
+2000-05-14 (widget change) added "readonly" state for entries and
+changed behavior of "disabled" entries; added -readonlybackground
+option for entries (melski)
+*** THIS IS A BACKWARDS INCOMPATIBLE BEHAVIOR CHANGE ***
+
+2000-05-15 (feature enhancement) added [image inuse] command (melski)
+
+2000-05-15 (feature enhancement) added -nice option to [bell] command (duncan)
+
+2000-05-17 (widget enhancement) added -overrelief option for
+check/radio/buttons (melski)
+
+2000-05-26 (feature change) added support for new syntax in
+Tk_OptionSpec tables; if the database name for an option contains an
+embedded "." it indicates that the name contains an overriding window
+class specifier in addition to the database name, which allows widgets
+to perform queries for certain options as if they were options for a
+different widget class (melski)
+
+2000-05-28 (new widget) added spinbox widget (hobbs)
+
+2000-05-31 (feature change) replaced bgerror dialog with a new and
+improved one (fellows, melski)
+
+--- Released 8.4a1, June 6, 2000 --- See ChangeLog for details ---
+
+2000-05-15 (bug fix) changed wm deiconify from using idle callback to
+calling restack and focus code immediately. (hobbs)
+
+2000-07 (build cleanup) cleanup of defines in tkConfig.sh, and cleanup
+in make and configure files to better handle .rc files across
+builds. (welch)
+
+2000-07 (build improvements) cleanup of the makefiles and configure scripts
+to correct support for building under gcc for Windows. (dejong)
+
+2000-08 (feature enhancements) for Windows, corrected drawing of separator
+menu entries, disable menu entries and the height for separator
+bars. (melski)
+
+2000-08 (bug fix) fixed calling of takeFocus proc with arg bearing
+functions. (nemethi)
+
+2000-08 (bug fix) For text widgets, added a test for a NULL segment pointer
+when doing backwards searches for "", correct searching over elided chars,
+and corrected search combining -regexp and -nocase. (melski)
+
+2000-08 (bug fix) Corrected code for using 'place', cursors, colors and 3D
+borders on multiple screens simultaneously. (hobbs, hipp)
+
+--- Released 8.3.2, August 9, 2000 --- See ChangeLog for details ---
+
+2000-06-15 (new feature) [tk_getOpenFile ... -multiple] (melski)
+
+2000-06-29 (new feature) localization support in Tk dialogs (duperval,
+melski, et al)
+
+200-07-28 (new feature) -state option for listbox, better native color
+defaults (melski)
+
+2000-08 (feature rewrites) Tcl_Obj'ified clipboard, message, tkwait,
+bindtags, grab. place, selection commands (melski)
+
+2000-08-24 (new feature) More correct GNU configure support (no more
+--enable-gcc) (dejong)
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2000-08-29 (bug fix) Corrected Windows menu indicator drawing (oberhumer)
+
+2000-09-01 (bug fix) Added tkPlatDecls.h to default install (melski)
+
+2000-09-17 (new feature) Added TK_OPTION_CUSTOM type, similar to
+TK_CONFIG_CUSTOM (melski)
+
+2000-09-29 (bug fix) Several fixes for multi-display uses of Tk (hipp, hobbs)
+
+2000-10-05 (new feature) Tk_CreateAnonymousWindow API to create anonymous
+Tk windows controllable from C (melski)
+
+2000-10-27 (new default behavior) [tk useinputmethods 1] is the default
+in tk.tcl, for users of XIM and "dead" keys (hobbs)
+
+2000-10-30 Improved support for static builds on Windows (gravereaux)
+
+ * Added support for mingw (gcc on Windows), AIX-5 and Win64 builds
+ (dejong, hobbs)
+
+ * Improved error checking in Windows native dialogs (melski, hobbs)
+
+--- Released 8.4a2, November 3, 2000 --- See ChangeLog for details ---
+
+2001-04-04 (build improvements) redid Mac build structure (steffen)
+Corrected IRIX-5* configure (english). Added support for AIX-5 (hobbs).
+Added support for Win64 (hobbs).
+
+2001-04-04 (doc fixes) numerous doc corrections and clarifications.
+Update of READMEs.
+
+2001-04-04 (bug fix) corrected reseting of service mode to only occur when
+it was set (hedin, hobbs)
+
+2001-04-02 (bug fix) Improved tests on Windows for correctness.
+Checked for menu deletion before calling associated menu entry command.
+Fixed listbox, canvas and entry destruction to be more aware of current
+widget activity. (hobbs)
+
+2001-03-30 (feature enhancement) added support for changing IME on the fly
+in Windows (2000) (lam)
+(bug fix) handled the error case where a valid-looking but invalid
+identifier could be passed in certain event generate options causing a
+crash (hobbs)
+
+2001-03-29 (bug fix) corrected handling of drag-selection (dejong)
+
+2001-01-02 (feature enhancement) added Windows icon support in wm
+iconbitmap (darley)
+
+2000-10-27 (feature enhancement) made [tk useinputmethods 1] the default
+for Tk (hobbs)
+
+2000-10-18 (bug fix) Corrected rendering of 1-pixel wide stippled lines on
+Windows. Correct use of active- and disabledwidth values for displaying
+lines. Enhanced error handling in Windows native dialogs (melski)
+
+2000-09-29 (bug fix) corrected BadMatch errors when using Tk on multiple
+screens (hipp)
+
+2000-08-18 (feature enhancement) Removed redundant call to DitherInstance
+(melski)
+
+--- Released 8.3.3, April 6, 2001 --- See ChangeLog for details ---
+
+2000-11-21 (new feature)[TIP 5] Tk_ClassProcs, Tk_SetClassProcs API (melski)
+
+2000-12-13 (performance enhancement)[403327] Tcl_Objs of type "double"
+are recognized in SetMMFromAny to speed up canvas coord calculations (hobbs)
+
+2001-01-02 (new feature)[TIP 8] [wn iconbitmap -default] on Windows (darley)
+
+2001-02-12 (new feature)[TIP #21] asymmetric padding in the pack and grid
+geometry managers (hipp)
+
+2001-05-21 (new feature)[TIP #11], -compound for [menubutton] widget (helfter)
+
+2001-06-03 (bug fix) corrected support for is10646 fonts on Unix, added a
+ucs-2be encoding (welch)
+
+2001-07-02 (bug fix) allowed tkwin to be Tcl_EventuallyFree'd in
+Tk_DestroyWindow so other widgets could register their use of it. Updated
+entry and listbox widgets to use this, correcting potential crashes. (hobbs)
+
+2001-08-01 (interface rewrite)[TIP 44] moved all private tk[A-Z]* commands and
+variables into the ::tk:: namespace (porter)
+ *** POTENTIAL INCOMPATIBILITY ***
+
+ * overhaul of configure scripts for cleaner standard support and support
+ of mingw gcc on Windows. (mdejong)
+
+ * improved tests to better handle results on variant systems (hobbs)
+
+ * correct several minor Purify complaints (hobbs)
+
+--- Released 8.4a3, August 6, 2000 --- See ChangeLog for details ---
+
+2001-08-06 (new feature) added GNU (HURD) build support. (brinkman)
+
+2001-08-23 (new feature) added QNX-6 build support. (loverso)
+
+2001-08-24 (bug fix) correct several possible free memory reads and array
+bounds read errors reported by purify. (hobbs)
+
+2001-08-27 (new feature) added call to Tcl_SetMainLoop which enables Tk to
+be loaded interactively into tclsh and have the event loop kick in
+correctly. (hobbs)
+
+2001-08-28 (bug fix) fixed tk_chooseDirectory crash on Win95. (baker)
+
+2001-08-28 (bug fix) removed 2 second 'raise' delay seen by some Unix
+window managers. (hobbs, baker)
+
+2001-09-14 (bug fix) fixed memory leaks that occured if errors were
+thrown while initializing the channel for an image. (darley)
+
+2001-09-20 (new feature) --enable-64bit support was added for HP 11 when
+using the native compiler.
+
+2001-10-03 (new feature) finalized Win64 support with latest RC1 release
+and SDK. (hobbs, stacy)
+
+2001-10-04 (new feature) added enhanced bgerror dialog from Hipp. (hobbs)
+
+2001-10-09 (new feature) added brace/quote matching and file/path/var
+expansion to the Win/Mac console. (hobbs)
+
+2001-10-17 (bug fix) fixed file filtering in the motif file dialog (nelson)
+
+2001-10-17 (bug fix) updated Mac build support. (steffen)
+
+--- Released 8.3.4, October 19, 2001 --- See ChangeLog for details ---
+
+2001-08-14 (bug fix)[450545] Tk's Tcl_ObjTypes now registered (fellows)
+
+2001-08-20 (performance enhancement) internal use of a "window" Tcl_ObjType
+(fellows)
+
+2001-08-20 (performance enhancement) Obj-ified [grid] and [pack] (spjuth)
+
+2001-09-26 (new feature)[TIP 18] add labels to frames, update geometry
+managers (spjuth)
+
+2001-09-30 (new feature)[TIP 37] [grid {row|column}configure -uniform] (spjuth)
+
+2001-10-12 (new feature)[TIP 63] [$menu add ... -compound] (helfter)
+
+2001-10-18 (build improvement) no more warnings about building with
+thread-enabled Tcl (hobbs)
+
+2001-11-10 (build improvement) new make target 'make gdb' (dejong)
+
+2001-11-12 (new feature)[TIP 26] simple undo/redo in text widget (callewaert)
+
+2001-11-12 (build improvement) revitalized makefile.vc (gravereaux)
+
+2001-11-17 (visual change) default button size on Windows changed to
+conform to Windows style (hobbs)
+ **** POTENTIAL VISUAL INCOMPATABILITY ****
+
+2001-12-03 (new feature)[TIP 74] [wm stackorder] (dejong, steffen)
+
+2001-12 (new feature) more use of Unicode in native widgets on Windows (hobbs)
+
+2001-12-18 (bug fix)[413735] event-click-drag-1.2 test failure (porter)
+
+2001-12-28 (new feature) On Windows, buttons accept negative widths, meaning
+minimum size, enabling native L&F (hobbs)
+
+2002-01 (bug fix) updates for CONST-ification in Tcl API, notably
+Tcl_ParseArgv. Use -DUSE_NON_CONST to suppress source incompatibility
+ **** POTENTIAL INCOMPATABILITY ****
+
+2002-01-31 (bug fix)[508988] logic error in menu cloning (helfter)
+
+2002-02-01 (new feature)[TIP 14] [$photo transparency] (fellows)
+
+2002-02-01 (bug fix)[511956] C99 spec: avoid 'bool' as a variable name (hobbs)
+
+2002-02-19 (bug fix) updates to image code calls of Tcl_Seek/Tcl_Tell to
+address TIP 72 changes (64-bit) in Tcl (fellows)
+
+2002-02-21 (new widget)[TIP 41] added [panedwindow] (hobbs)
+
+2002-02-22 (new feature) 64-bit support for xlc compiler on AIX-4 (hobbs)
+
+2002-02-25 (bug fix)[503772] blinking cursor fix in [text] (hobbs)
+
+2002-02-25 (bug fix)[503613] [listbox] handling of invalid listvar (hobbs)
+
+2002-02-25 (feature change)[493145] mirror B2 bindings to B3 on Windows (hobbs)
+
+ * (updated demos) many updates to show new features (fellows)
+
+--- Released 8.4a4, March 5, 2002 --- See ChangeLog for details ---
+
+2002-03-20 (feature change)[TIP 27][532644] Constness changes (porter)
+
+2002-03-21 (bug fix)[528441] Change in optimization flags for windows
+(gravereaux)
+
+2002-04-08 (bug fix) MSL stdin/out fixes prevent crash on exit (steffen)
+
+2002-04-12 (bug fix) Centralized closing of display, mem-leak fixes (hobbs)
+
+2002-04-22 (bug fix)[223739] More robust FP comparisons for odd
+architectures (fellows)
+
+2002-04-22 (bug fix)[541999] Fixed posible overun of 16-bit size limit
+of X windows in drawchars (hobbs,bonfield)
+
+2002-04-22 (bug fix)[541849] ButtonLeave implementation corrected (hobbs)
+
+2002-04-24 (new feature) TCLTK_NO_LIBRARY_TEXT_RESOURCES check added,
+allowing disable of inclusion of tk lib into resources (steffen)
+
+2002-05-07 (bug fix)[553208] Makefile/Win fix (TCLDIR, INSTALLDIR
+forward slash trouble resolved) (gravereaux)
+
+2002-05-20 (bug fix) msgcat added to resources, fixed setup of bindings
+on startup (steffen, porter)
+
+2002-05-21 (bug fix) Build system fix, SC_ENABLE_SHARED before
+SC_CONFIG_CFLAGS for usage for SHARED_BUILD (dejong)
+
+2002-05-26 (bug fix)[548765] Fixed -value "" redraw error for variable
+created by radiobutton (spjuth)
+
+2002-05-27 (feature change) [wm transient .t .t] now raises an error (dejong)
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2002-06-10 (new feature)[566605] Utilities for -underline, ampersand magic
+(kovalenko)
+
+2002-06-12 (feature change) A transient toplevel now mirrors state changes
+in the master. (dejong)
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2002-06-13 (bug fix) Fixed handling of cursor specs across platforms to
+be consistent. (fellows)
+
+2002-06-14 (new feature) [TIP 98] Enhanced photo compositing (fellows)
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2002-06-14 (bug fix) Removed references to matherr (kupries)
+
+2002-06-14 (new feature) [TIP 47] Reorganized Tk to allow usage in writing
+an X wm (english)
+
+2002-06-14 (new feature) [TIP 84] Full motion events upon request (hobbs)
+
+2002-06-17 (new feature) [TIP 82] -offrelief option for check/radiobutton
+(hipp)
+
+2002-06-17 (enhancement) Added msg catalog for UK English. (porter)
+
+2002-06-17 (new feature) [TIP 96] Added caret handling (hobbs)
+
+2002-06-19 (new feature) [TIP 48] Added style engine (bonnet)
+
+2002-06-19 (bug fix)[570902] Reorganized Tk shutdown to work around bugs in
+X (dejong)
+
+2002-06-20 (new feature) [TIP 94] Added -activestyle for [listbox] (hobbs)
+
+2002-06-21 (new feature) [TIP 104] generalized text undo/redo (callewart,
+hobbs)
+
+2002-06-22 (new feature) [TIP 95] Added [wm attributes] command (hobbs)
+
+2002-06-22 (new feature) [TIP 93] enhanced get/delete to accept accept
+multiple range pairs (hobbs)
+
+--- Released 8.4b1, July 5, 2002 --- See ChangeLog for details ---
+
+2002-07-11 (bug fix) some memory allocation failures now result in
+ error messages rather than panic (fellows)
+
+2002-07-15 (platform support) Borland makefile on Windows (gravereaux,giese)
+
+2002-07-16 (bug fix)[220800,581627] icon reading (darley)
+
+2002-07-19 (bug fix) Postscript generation on Win2K (hipp)
+
+2002-07-22 (bug fix)[570764,568278] transient windows (dejong)
+
+2002-07-24 (bug fix)[581560] canvas memory management (hobbs)
+
+2002-07-24 (bug fix)[584691] focus ring on compound button (hobbs)
+
+2002-07-25 (feature enhancement)[564521] Obj-ified [wm] (spjuth)
+
+2002-08-04 (new feature)[589853][TIP 27] Tk interfaces are now fully
+ CONST-ified. Use the symbols USE_NON_CONST or USE_COMPAT_CONST
+ to select interfaces with fewer changes.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2002-08-07 (bug fix)[578654] bezier curves on canvas (hobbs)
+
+2002-08-07 (platform support)[468139] native directory browser on Win (hobbs)
+
+2002-08-07 (bug fix)[467524] fixed -from handling for gifs (obermeier)
+
+2002-08-08 (bug fix)[592201] wm transient panic (english,dejong)
+
+Rewrote Tk test suite to use tcltest package.
+
+--- Released 8.4b2, August 9, 2002 --- See ChangeLog for details ---
+
+2002-08-20 (bug fix) tk.h checks for matching tcl.h version (porter)
+
+2002-08-27 (bug fix)[582457] toolbar button bindings (hipp)
+
+2002-08-31 (platform support)[602770] Mac OS X / Aqua port (steffen)
+
+2002-09-02 (bug fix)[565485] button height on windows (hobbs)
+
+2002-09-02 (new feature)[TIP 108] new comand [tk windowingsystem] (steffen)
+
+2002-09-02 (new feature)[TIP 107][601518] [raise] is non-blocking (english)
+
+2002-09-02 (platfrom support) 64-bit compile on HP-11 (martin)
+
+--- Released 8.4.0, September 10, 2002 --- See ChangeLog for details ---
+
+2002-09-15 (bug fix)[570902] Use PEEK_XCLOSEIM to examine the input context
+queue before invoking XCloseIM. Generate an assert if there is an input
+context that has not been freed. (dejong)
+
+2002-09-18 (platform support) Updated support for compiling with Cygwin and
+either mingw or gcc. (khan, howell, dejong)
+
+2002-09-30 (bug fix)[614650] Correct incremental transfers of UTF8_STRING
+selections (fellows)
+
+2002-10-02 (bug fix)[616791, 614474] don't blink the cursor unless it is
+visible. (bonfield)
+
+2002-10-02 (bug fix)[607390, 617446] check if the entry is being deleted
+before handling an associated textvariable. (hobbs)
+
+2002-10-08 (bug fix)[616589] leave the DestroyPanedWindow proc to free the
+pwPtr. (hobbs)
+
+2002-10-08 (bug fix)[588831] Ignore event if we are focusing into a dead
+window (griffin)
+
+2002-10-09 (bug fix)[619544] Only error-out creating an image if we fail to
+allocate a non-empty buffer (fellows)
+
+2002-10-09 (build support) all --enable-symbols to take the enhanced
+options yes|no|mem|all. (hobbs)
+
+2002-10-10 (feature enhancement) added support for generating ps for
+embedded widgets on canvases on Windows (hobbs)
+
+2002-10-10 (bug fix)[621241] The grid size was not updated properly when
+removing a widget from a grid (forssen)
+
+2002-10-16 (bug fix)[616988] macosx fix to accelerators shown in menus
+with non-alphanumeric keys. (darley)
+
+2002-10-15 (platform support) Correct AIX-5 ppc and 4/5 64-bit build flags.
+Correct HP 11 64-bit gcc building. (martin, hobbs)
+
+2002-10-17 (bug fix)[624974] fix arg handling for missing image create
+photo -format or -data options (hobbs)
+
+2002-10-17 (bug fix)[624732] In ControlUtfProc, properly return the number
+of bytes consumed (hobbs)
+
+2002-10-22 (platform support)[624509] On macosx, add embedded framework
+dirs to tcl_pkgPath: @executable_path/../Frameworks and
+@executable_path/../PrivateFrameworks (if they exist), as well as the dirs
+in DYLD_FRAMEWORK_PATH (if set). Added 'rapp' apple event handler. Added
+TEXT document type to plist so that files can be dragged onto Wish Shell.
+Added private proc TkMacOSXUseAntialiasedText() to enable/disable quickdraw
+text antialiasing where available, default is enabled. Added a linked
+boolean ::tk::mac::antialiasedtext with write trace to allow control of
+antialiasing from tcl. (steffen)
+
+--- Released 8.4.1, October 22, 2002 --- See ChangeLog for details ---
+
+2002-11-07 (bug fix)[635025,532022] Make [place info] complete and bring into
+line with other geometry managers. (spjuth)
+
+2002-11-14 (bug fix)[630533] Handle half-dead windows better. (dejong)
+
+2002-11-19 (bug fix) Better handling of narrow scrollbars on OSX. (ingham)
+
+2002-11-22 (bug fix)[641778] Make the [text see] work when the widget is
+unmapped. (hobbs)
+
+2002-12-01 (bug fix) Stopped [wm withdraw] and [wm transient] from interfering
+with each other. (dejong)
+
+2002-12-06 (bug fix) Improved DLL cleanup on Windows. (hobbs)
+
+2002-12-06 (new feature) New function TkWinSetHINSTANCE() as part of enabling
+dynamic Tk to load resources correctly. (hobbs)
+
+2002-12-13 (bug fix)[616245] Use Tcl*StartupScript*() routines in Tk_Main.
+(porter)
+
+2002-12-27 (bug fix)[578569] Made sure that Tk always knows whether its windows
+are mapped or not. (english)
+
+2003-01-03 (bug fix)[661792] Stopped crash when trying to create a toplevel
+when Tk is dying. (hobbs)
+
+2003-01-08 (bug fix)[663981] Clip long lines so they show correctly even when
+they hit windowing-system limits. (hipp)
+
+2003-01-14 (bug fix)[666346] Stopped selection handling crashes under KDE3.0.
+(english)
+
+2003-01-22 (bug fix)[220891] Image creation cannot trigger Tk's death.
+(fellows)
+
+2003-01-23 (bug fix)[673687] Entry typein works as expected even when the mouse
+button is pressed. (hipp)
+
+2003-01-28 (bug fix)[671330] Stopped segfaults from unsynchonized window
+deletion epochs. (english)
+
+2003-02-08 (bug fix) Make canvas item coordinate list handling consistent to
+stop segfaults. Cannot now create items without coordinates. (hobbs)
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2003-02-10 (bug fix) Better support for themed and animated cursors on OSX.
+(ingham)
+
+2003-02-17 (bug fix) Stopped motion events from morphing into button press
+and motion events. (dejong)
+
+2003-02-18 (bug fix) Removed memory leak in GIF image loader. (fellows)
+
+2003-02-18 (bug fix) Made OSX menus support UTF8 text and icons. (darley)
+
+2003-02-18 (bug fix)[608559] Stop message boxes from getting extremely wide.
+(hobbs)
+
+2003-02-18 (bug fix)[683813] Make focus behaviour of spinboxes more like
+entries. (bron)
+
+2003-02-19 (new demo)[627453] New demo showing off Tk's Unicode font handling.
+(fellows,suchenwirth)
+
+2003-02-19 (bug fix) Bring event handling more into line with the OSX standard.
+Also improves "dead key" handling. (riefenstahl,ingham)
+
+2003-02-20 (bug fix)[618872,689357] Stopped read of freed memory when working
+with large composite fonts. (fellows)
+
+2003-02-20 (bug fix)[689099,tcllib 689258] Improvements to [panedwindow] pane
+size and sash handling. (spjuth,hobbs)
+
+2003-02-20 (bug fix)[624116] Stopped semi-crash in Windows scrollbar handling.
+(hobbs)
+
+2003-02-21 (bug fix)[671122] Stopped panedwindow from crashing when embedded
+in a window with a different visual to the root window. (fellows)
+
+2003-02-21 (bug fix)[617392] Limit the screen-size of [tk_get*File] file type
+selection menu. (fellows)
+
+2003-02-21 (bug fix)[673722] Rework standard dialogs to use [grid]. (fellows)
+
+2003-02-24 (bug fix)[637828] Report that entries can provide the selection,
+even if they're not displaying it. (hobbs)
+
+2003-02-24 (bug fix)[669595] Improved display of indicators in disabled
+checkbuttons and radiobuttons. (hintermayer)
+
+2003-02-24 (bug fix)[632514] Allow listbox 'selection includes' to respond
+positively when disabled.
+
+2003-02-24 (bug fix)[647497] Make Tk pick the first best matching font on
+the font path. (dal zotto)
+ *** POTENTIAL VISUAL INCOMPATIBILITY ***
+
+2003-02-25 (bug fix)[621672] Fixed conversion of apple event parameters
+to posix path names. (steffen,riefenstahl)
+
+2003-02-25 (feature enhancement)[patch 685388] Support simple XOR text drawing
+on Windows. (martin)
+
+2003-02-28 (bug fix)[612110] Make %-substitutions for events only read data out
+of the event structure when that field is valid for that event type. (fellows)
+ *** POTENTIAL INCOMPATIBILITY ***
+
+--- Released 8.4.2, March 3, 2003 --- See ChangeLog for details ---
+
+2003-03-14 (bug fix)[701812] Stop buttons from being very wide when a
+tk_messageBox has a lot of content on Unix
+
+2003-03-18 (bug fix) Fixed crash in [winfo server] on Mac OS X
+
+2003-04-25 (bug fix)[477740] Correct compound button display in the
+disabled state
+
+2003-05-10 (bug fix)[734498] Correct crash when generating postscript for a
+single-line polygon (point) with no color.
+
+2003-05-13 (feature enhancement)[736774] Use new versioned bundle resource
+API to get tk runtime library for TK_VERSION on Mac OS X
+
+2003-05-14 (bug fix)[737790] Updated French message catalog
+
+2003-05-15 (bug fix)[557030] Use gb2312-raw as the alias for gb2312*
+charset fonts. gb2312.enc was made to be euc-cn for Tcl because that is
+what is most often meant, but X really wants the original (-raw) gb2312
+encoding.
+
+--- Released 8.4.3, May 20, 2003 --- See ChangeLog for details ---
+
+2003-07-07 (bug fix)[749353] Improve deletion of images on exit.
+
+2003-07-15 (bug fix)[465324] Fixed complex bug in menu clone cleanup.
+
+2003-07-15 (bug fix)[755530] Don't test for XCloseIM bug when the XFree86
+version is newer than 4.0 since the layout of the XIM structure has
+changed.
+
+2003-07-16 (bug fix)[748277, 702230, 738143] Numerous panedwindow fixes.
+Ensure that the last pane shrinks instead of being clipped when resized
+below the reqsize. Ensure that we can share GCs between a panedwindow and
+its sash proxy, even if the panedwindow is in a toplevel with a different
+visual. Ensure that panedwindows get their geometry right even when their
+children don't know their initial size. Use widget-specific Priv slots for
+pwAfterId and panecursor items to correctly handle cursor changes with
+adjacant panedwindows.
+
+2003-07-17 (bug fix)[697652] Make sure all options of a frame can be set to
+their default value.
+
+2003-07-17 (bug fix)[404421] Try harder to avoid zero-length mallocs() when
+creating images.
+
+2003-07-17 (feature enhancement) MacOSX build system rewrite.
+
+2003-07-18 (bug fix) Do not make XGetGeometry call that prevents overwidth
+lines drawing on unix as it requires a roundtrip call to the X server for
+every string drawn. Hard-code max width to 32768 until a beter solution to
+get max width is made.
+
+2003-07-18 (bug fix)[742660] correct XCreateIC call for TK_XIM_SPOT usage
+on unix.
+
+2003-07-18 (bug fix)[420510] Provide consistency between unix and windows
+-cursor option.
+
+2003-07-19 (bug fix)[706765] Correctly handle the -sliderrelief option
+while moving the thumb.
+
+--- Released 8.4.4, July 22, 2003 --- See ChangeLog for details ---
+
+2003-08-13 (bug fix)[787065] Fix Button-2 binding for scale widget.
+
+2003-08-19 (bug fix)[791500] Fix panedwindow refresh glitches for bg.
+
+2003-09-17 (bug fix)[808039] Prevent [image create] from generating an
+image command name that overwrites an existing command.
+
+2003-09-25 (enhancement) Added -compound support for OS X bevel buttons.
+
+2003-10-10 (bug fix) Fix image offset stippling for disabled buttons.
+
+2003-10-22 (enhancement)[827535] Constrain tk_dialog to be sensibly sized and
+placed
+
+2003-10-28 (bug fix) Add 16bpp XGetImage support on Windows
+
+2003-10-29 (enhancement)[795717] Allow some control of foreground and
+background colors on Tk's tk_getOpenFile/tk_chooseDirectory.
+
+2003-11-01 (enhancement)[820519] Updated Dutch (nl) message catalog.
+
+2003-11-10 (enhancement)[826614] Provide more Tk build info in tkConfig.sh.
+
+2003-11-10 (enhancement)[809157] Add alpha blending for images with partial
+transparency on Windows and Unix on 15bpp+ displays.
+
+2003-11-10 (enhancement)[820282] Use the XGCValues.function parameter when
+filling rectangles with XFillRectangles on Windows.
+
+2003-11-11 (enhancement)[840107] Add OS X unicode clipboard support.
+
+2003-11-11 (enhancement)[833819] Improve Tk's
+tk_getOpenFile/tk_chooseDirectory directory glob'ing speed.
+
+2003-11-11 (bug fix)[836483] Fix mem leak in '$listbox itemconfigure'.
+
+2003-11-11 (bug fix)[723856] Correctly handle menu (un)posting on menus
+with spaces in their names.
+
+2003-11-11 (enhancement) Improve AIX-64 build configuration.
+
+2003-11-17 (bug fix) Fix menubutton -compound state disabled drawing.
+
+--- Released 8.4.5, November 20, 2003 --- See ChangeLog for details ---
+
+2003-12-17 (platform support)[842952] Mac OS X: [scrollbar]
+
+2004-02-13 (platform support)[776646] Win: native hand2/fleur cursors
+
+2004-02-03 (enhancement) post menubuttons so they stay on screen.
+
+2004-02-09 (bug fix)[877950] stop crash during intra-image copy/resize
+
+2004-02-10 (enhancement) New msg catalogs for Esperanto and Polish (trzewik)
+
+2004-02-13 (platform support)[478568] Win: bold/italic font handling
+
+2004-02-15 (platform support)[860454] Mac OS X: [event generate]
+
+2004-02-15 (platform support)[840107] Mac OS X: Unicode clipboard (senn)
+
+2004-02-15 (platform support)[517600] Mac OS X: handle FSRef's
+
+2004-02-15 (platform support) Mac OS X: native [tk_messageBox]
+
+2004-02-15 (platform support) Mac OS X: PowerBook keycode 0x34 -> <Return>
+
+2004-02-18 (platform support) Mac OS MouseWheel event handling
+
+2004-02-18 (bug fix)[899246] fix shrinking grid geometry calculations
+
+2003-02-23 (platform support)[809157] Mac OS X: Add alpha blending for
+images with partial transparency.
+
+2004-03-01 (platform support)[218561] Allow 64-bit configure on IRIX64-6.5*
+
+--- Released 8.4.6, March 1, 2004 --- See ChangeLog for details ---
+
+Changes to 8.5a1 include all changes to the 8.4 line through 8.4.6,
+plus the following, which focuses on the high-level feature changes
+in this changeset (new minor version) rather than bug fixes:
+
+ * Tk is no longer guaranteed to work for Win95 (not tested 8.5+)
+
+ * configure scripts now require autoconf 2.57 for regeneration
+
+ * added support for anti-aliased test under X11 (already existed for
+ Win/Mac) using --enable-xft
+
+ * improved speed of 'photo put' handling
+
+ * updated demos for consistency and improved look & feel
+
+ * improve 3D line drawing for sunken widgets on Windows
+
+ * [792387] reworked 'grid' to handle some tricky geometry computations
+ better
+
+ * [TIP #109] updated look of radiobuttons and checkbuttons on X11
+
+ * [TIP #110] tristate value option for checkbuttons and radiobuttons
+
+ * [TIP #113] add multi-line searching and -all searching to the text widget
+ Full Tcl_Obj-ification of the text widget
+ * [TIP #155] add 'count' and 'replace' subcommands and a '-blockcursor'
+ option to text widgets and support smooth-scrolling of them
+ *** POTENTIAL INCOMPATIBILITY ***
+ Negative or decreasing tab-stops are explicitly disallowed
+
+ * [TIP #116] more safety for large image creation through use of attempted
+ allocation of large memory blocks
+
+ * [TIP #137/151] add -encoding option to 'wish' executable (through
+ Tk_MainEX())
+ *** POTENTIAL INCOMPATIBILITY ***
+ For Tk embedders that build on Tk_MainEx() and make use of Tk_MainEx's
+ former ability to pass a leading "-encoding" option to interactive shell
+ operations, this will now be consumed by Tk.
+
+ * [TIP #146] added 'grid anchor' subcommand for overall grid anchoring
+
+ * [TIP #147] recognize widget names and "all" as keywords in grid's
+ 'columnconfigure' and 'rowconfigure' subcommands
+
+ * [TIP #150] make 'send' available on Windows
+
+--- Released 8.5a1, March 3, 2004 --- See ChangeLog for details ---
+
+2004-03-17 (platform support) Mac OS X: Grab the Command-H &
+Command-Shift-H keys and use them for Hide and Hide Others before passing
+keystrokes on to the generic keyboard event processing.
+Stop putting a Quit menu item in the File menu. (ingham)
+
+2004-03-26 (enhancement)[540375] Add code to read and write PPM/PGM data
+from strings and/or bytearrays. (fellows)
+
+2004-03-26 (bug fix)[923555] Restored support for the stringWriteProc of
+old photo formats/ (fellows)
+
+2004-03-31 (bug fix)[Bug 220871] Report errors from invoking menu commands
+as background errors on OS X. (ingham)
+
+2004-04-20 (bug fix)[915350, 922336] Do not set min, max size in WM_HINTS
+when we shouldn't and correctly display maximize window button under
+KDE-3.2.1. (english)
+
+2004-05-03 (enhancement)[756952] Place images of compound menu entries in
+indicator space if not a radio of checkbutton on Windows. (eserte)
+
+2004-05-03 (bug fix)[904371] Fix drawing of unicode chars in menu titles.
+(riefenstahl)
+
+2004-05-03 (bug fix)[939389, 822002, 732662] Correctly post internal
+clipboard data to the Windows clipboard on exit. (hobbs)
+
+2004-05-03 (bug fix)[778893, 932155] Make the panedwindow -opaqueresize
+option work as per the docs, and call DragSash to stop sash jump when B1 is
+pressed and released without moving. (hobbs)
+
+2004-05-05 (bug fix)[618872] Fix Tk_MeasureChars and Tk_DrawChars to handle
+reallocation of subfonts when unicode chars require extra fonts.
+(dkf, hobbs)
+
+2004-05-14 (enhancement) reduce Tk tk_messageBox default font size to
+14-point (was 18-point). (fellows)
+
+2004-07-11 (enhancement)[987169] Handle users destroying the dialog
+indirectly. (fellows)
+
+2004-07-14 (bug fix)[894550] Correctly set the cursor to the platform
+cursor on OS X when Tk asks for the "NULL" (empty) cursor.
+
+2004-07-14 (bug fix)[969358] Prevent possible segfault in -maxundo. (jiangwu)
+
+2004-07-19 (bug fix)[874058] improved build configuration on 64-bit systems.
+Corrects Tcl_StatBuf definition issues. (hobbs)
+
+2004-07-23 (platform support) Mac OS X: Fix several problems with
+Icelandic (and Faroese) keyboards (riefenstahl)
+
+2004-07-24 (platform support) Mac OS X: Complete the implementation of
+the CG version of the X drawing emulation layer. (tittle, ingham)
+
+--- Released 8.4.7, July 26, 2004 --- See ChangeLog for details ---
+
+2004-08-09 (bug fix)[1006286] test wrapping on canvas; Win (dejong)
+
+2004-08-10 (bug fix)[1006686] [wm resizable] Solaris (mcdonald,english)
+
+2004-08-17 (bug fix)[1010938] panedwindow -handlepad GEOMETRY (fellows)
+
+2004-08-19 (bug fix)[611615] file dialog double clicks fell through (hobbs)
+
+2004-09-10 (bug fix)[845189] file dialog state initialization (fellows)
+
+2004-09-10 (bug fix)[1013942] widget demo robust against strict motif (fellows)
+
+2004-09-16 (bug fix)[1028888] [place forget] memory leak (spjuth)
+
+2004-09-16 (bug fix)[607649] font size change: recompute menu geometry (hobbs)
+
+2004-09-17 (new feature)[TIP 222] [wm attributes -alpha] (hobbs)
+
+2004-09-22 (bug fix)[865842] disabled cascade menu arrow draw (dejong)
+
+2004-09-22 (bug fix)[866194] menu accelerator text highlights (dejong)
+
+2004-09-22 (bug fix)[223689] handle color/screen resolution changes (hobbs)
+
+2004-10-05 (new feature)[TIP 159] [wm iconphoto] (hobbs)
+
+2004-10-26 (bug fix)[905830] set IC focus after creation (max)
+
+2004-10-26 (bug fix) shutdown safety corrections for Win (gravereaux)
+
+2004-10-28 (bug fix) HAVE_NO_SEH handler code, Win (dejong)
+
+2004-10-29 (bug fix)[533519] multi-display window placement (thoyts)
+
+2004-11-10 (bug fix)[1055023] compound buttons, MacOSX (kirkham,ingham)
+
+2004-11-11 (bug fix)[1035348] [load]-able Tk on MacOSX/Aqua (steffen)
+
+2004-11-12 (bug fix)[800178] use correct display for [tk scaling] (hobbs)
+
+2004-11-16 (bug fix)[1063675] Italian msg catalog fixes (ugoccioni,welton)
+
+2004-11-17 (bug fix)[1036963] panedwindow: set save_under X attr (hobbs)
+
+2004-11-17 (bug fix)[1004508] console: array keyname expansion (bold,hobbs)
+
+2004-11-17 (bug fix)[1032300] ps generation of unspecified canvas image (hobbs)
+
+2004-11-17 (bug fix)[982248] immediate unmap of hidden canvas windows (hobbs)
+
+2004-11-18 (new feature) configure options --enable-man-suffix (max)
+
+--- Released 8.4.8, November 18, 2004 --- See ChangeLog for details ---
+
+2004-12-01 (bug fix)[979239] Fix clipping of partially transparent images
+on buttons on unix to avoid X error (hobbs, petasis)
+
+2004-12-03 (bug fix)[848161] Fix Tk_PhotoPut(Zoomed)Block overlay
+compositing of partially transparent areas.
+
+--- Released 8.4.9, December 6, 2004 --- See ChangeLog for details ---
+
+Changes to 8.5a2 include all changes to the 8.4 line through 8.4.9, plus
+the following, which focuses on the 8.5-only changes since 8.5a1:
+
+2004-03-16 (bug fix)[915330] correct crash condition for new
+radio/checkbuttons when colors are exhausted (griffin)
+
+2004-03-18 (platform removal)[918139] Removed support for Mac OS Classic
+platform (steffen)
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2004-03-26 (new feature)[FRQ 540375] support for
+[image create photo -format PPM -data] (fellows)
+
+2004-05-14 (bug fix)[TIP 152] -detail option for tk_messageBox (fellows)
+
+2004-06-04 (bug fix)[965398] Fix to shimmering infinite loop scrolling in
+text widget under rare circumstances (darley)
+
+2004-06-04 (bug fix) Fixed mousewheel bindings for OS X/Aqua (darley)
+
+2004-06-07 (bug fix)[965186] Fix text widget's record of
+partial-line-height calculations for very long wrapped lines, correcting
+scrollbar-text interactions (darley)
+
+2004-06-08 (bug fix)[968725] Fix text rendering problem with canvas text
+items that have a selected region. (dejong)
+
+2004-06-09 (bug fix) Fix multi-line regexp search bugs in text widget
+(darley)
+
+2004-06-15 (feature enhancement) Add 3D highlight to disabled *buttons and
+labels, as is done for disabled menu entries (kovalenko)
+
+2004-06-16 (bug fix)[742882] Fix potential division by zero in gridded wm
+geometry (english)
+
+2004-06-26 (bug fix)[756840] Fix Tk console cleanup on exit/reinit
+(mistachkin)
+
+2004-06-30 (new feature)[TIP 153] enhanced 'winfo toplevel' to recognize
+non-Tk windows (mckay)
+
+2004-07-02 (bug fix) Button 4 and 5 masks synchronized with Tk display
+(staplin)
+
+2004-07-05 (bug fix)[959973] Set _NET_WM_NAME and _NET_WM_ICON_NAME
+(freedesktop.org) in addition to WM_NAME and WM_ICON_NAME (ICCCM). Allows
+Unicode characters in wm titlebar on X11. (english)
+
+2004-07-05 (new feature)[TIP 158][797404] Allow Win apps to distinguish
+keys on the keypad using the Extended modifier (grossbauer, kenny)
+
+2004-07-20 (feature enhancement)[922727] add install-private-headers target
+(steffen)
+
+2004-07-27 (bug fix) Fix segfault in case of premature end of GIF image
+data (steffen)
+
+2004-08-11 (feature)[979101] [tk_getOpenFile] consults env vars (fellows)
+
+2004-08-19 (new feature)[TIP 168] Add -smooth method for alternative bezier
+curve implementations on canvas items (hellstroem, fellows)
+
+2004-08-29 (new feature)[TIP 165] Add %d binding substitution for
+user-controlled data field (fellows)
+
+2004-09-10 (new feature)[TIP 169] Allow for text peering with '$text peer'
+widget subcommand (griffin, darley)
+
+2004-10-08 (new feature)[TIP 205] Use pkgconfig Database to register Xft
+support (english)
+
+2004-10-11 (new language) Swedish message catalog from Mats Bengtsson
+
+2004-10-19 (new feature)[TIP 204][976928] Virtual events for keyboard
+traversal (english)
+
+2004-10-24 (new feature)[TIP 177, 179][983886] Add -hide and -stretch
+options to panedwindow widget (griffin)
+
+2004-10-26 (bug fix)[919066] Improve region handling functions
+
+2004-10-28 (bug fix)[220927] Fix scale labels to stay in window (schlenker,
+thoyts)
+
+2004-11-07 (bug fix)[962589] Made handling of ^ more consistent in grid
+(spjuth)
+
+2004-11-28 (bug fix)[942320] Fix short integer overflow in x,y coordinates
+for long lines using unix AA fonts (english)
+
+Updated test suite, documentation, and demos.
+
+--- Released 8.5a2, December 7, 2004 --- See ChangeLog for details ---
+
+2004-12-09 (performance)[1081966] BMP, JPG image load speed (fellows)
+
+2004-12-17 (feature change) Modified DisplayFrame to draw a container's
+background when the embedded window is NULL (chengyemao)
+
+2004-12-17 (bug fix)[842945][831627] Fixed a bug in ContainerEventProc
+to handle ConfigureNotify event properly; Changed CleanupContainList to
+TkWinCleanupContainerList to be invoked in TkWinXCleanup; Changed Intialize
+and CreateTopLevelWindow to create the DeleteWindowsExitProc after TkpInit
+so that finalization will be done in a proper sequence (to avoid painics
+and potential crashes in exit). (chengyemao)
+
+2004-12-17 (platform support) Added TkWinClenupContainerList into stublib.
+(chengyemao)
+
+2004-12-18 (buf fix)[222677] Close the embedded window (of a different
+process) when its container is destroyed. (chengyemao)
+
+2004-12-19 (Windows feature implementation of embedded/embedding
+Tk and bug fix) Implemented container identification, focus, raise, set
+title of and move window so that an embedded widget is able to identify
+a container, to get focus and to receive key press input. Fixed bugs include
+[1024364][1096047] and an incorrect wm overrideredirect for an embedded
+window. (chengyemao)
+
+2004-12-20 (Windows feature implementation of embedded/embedding Tk)
+Implemented overrideredirect for an embedded toplevel; correctly updated a
+frame's upper left x and y of an embedded toplevel after its container
+(of another process) moved. (chengyemao)
+
+2004-12-28 (feature implementatoin of embedded/embedding Tk of Windows)
+Implemented embedded/embedding toplevel menu. A menu may be embedded in
+a container of either the same process or a different process. Working
+fine with Windows 98. But having a problem when invoked with a mouse click
+(Windows XP): if an embedded menu is in a different process, the menu items
+may show as a blank window at the pull-down time and require the mouse
+moves over the menu items to complete display. (chengyemao)
+
+2004-12-29 (platform support)[1092952,1091967] MSVC7, gcc OPT compiles (hobbs)
+
+2005-01-03 (feature implementation of embedded/embedding Tk of Windows) Added
+a separated window handler for an embedded menu; solved the problem of
+a blank menu display with a mouse click in XP. (chengyemao)
+
+2005-01-07 (feature implementation of embedded/embedding Tk of Window) Added
+TK_STATE message (Windows) to support {wm state} for embedded windows; forced
+redraw of container after the embedded window detached; removed unnecessary
+panic in using embedded window; embeded toplevel menu of an embedded window
+automatically in wrapper updating. Modified and added functions: WmStateCmd,
+UpdateWrapper, TkpWmGetState (added) in tkWinWm.c; TkpUseWindow,
+TkWinEmbeddedEventProc in tkWinEmbed.c; TkWinChildProc in tkWinX.c.
+(chengyemao)
+
+2005-01-08 (bug fix)[1098625] Wrong toplevel geometry when created with a menu;
+[637653] Deleting a popup menu crashes wish (chengyemao)
+
+2005-01-09 (feature implementation of embedded/embedding Tk of Windows)
+Changed FrameWidgetObjCmd (tkFrame.c), TkpUseWindow (tkMacOSXEmbed.c,
+tkUnixEmbed.c, tkWinEmbed.c) to make implementation ready for a
+configurable toplevel -use option and completed the implementation for
+Windows (tkWinWm.c, tkWinEmbed.c, tkWinInt.h). Embedding with a frame
+container needs further debugging (chengyemao).
+
+2005-01-10 (enhancement)[1081595] stopped use of TK_DBGX (english)
+
+2005-01-11 (bug fix)[1098779] -pady accept all lists (fellows,kirkham)
+
+2005-01-11 (bug fix)[1093631] [text] scroll long wrapped line (darley)
+
+2005-01-18 (feature implementation of embedded/embedding Tk of Windows)
+Simplified TkpUseWindow, added Tk_DetachEmbeddedWindow and got rid of code
+for saving an embedded window object which is never used. Fixed a bug in
+TkWinHandleMenuEvent for processing WM_MENUSELECT. Wish crashed due to an
+invalid index in a case of MF_POPUP. The -use option of a toplevel can be
+configured after the toplevel is created.
+
+2005-01-18 (bug fix) dialog visibility in demos (nash,fellows)
+
+2005-01-28 (platform support)[1021871] Solaris gcc 64-bit support (hobbs)
+
+2005-01-31 (enhancement)[1111213] msg catalog for Spain's Spanish. (poser)
+
+2005-02-03 (bug fix)[1114977] UID thread-safety in canvas (fellows)
+
+2005-02-11 (bug fix)[949792] Fix error during panedwindow destroy (hobbs)
+
+2005-02-11 (bug fix)[1105738] Fix [tk_messageBox -parent $nonToplevel]
+segfault (hobbs)
+
+2005-02-11 (bug fix)[1119460] Disabled canvas bmap/bbox segfault (hobbs)
+
+2005-02-11 (platform support) Correct gcc builds for AIX-4+, HP-UX-11 (hobbs)
+
+2005-02-14 (bug fix)[443848] [text] elide newline, but not line (darley)
+
+2005-02-16 (new feature)[TIP 223] Windows: [wm attributes -fullscreen] (dejong)
+
+2005-02-22 (bug fix)[1146057] Aqua: [tk_getOpenFile] encoding (steffen)
+
+2005-02-28 (bug fix)[1118340] Fix Mousewheel %A translation (davis,hobbs)
+
+2005-03-09 (bug fix) Mac OS X: remote debugging under Xcode (ingham)
+
+2005-03-10 (bug fix)[1160025] Aqua: offset in mouse coords (davies,ingham)
+
+2005-03-10 (bug fix)[1124237] Aqua: floating window focus (davies,ingham)
+
+2005-03-14 (bug fix)[1162356] ClientMessageHandlers work now (petasis,fellows)
+
+2005-03-14 (bug fix)[1124237] Aqua: (un)map of subwindows (ingham)
+
+2005-03-14 (bug fix)[700305] Aqua: child window updates before creation
+(ingham)
+
+2005-03-15 (platform support) OpenBSD ports patch (thoyts)
+
+2005-03-15 (bug fix)[1143776] [text] display panic (revar,darley)
+
+2005-03-19 (bug fix)[1016385] allow [rename console] (fellows)
+
+2005-03-23 (enhancment) Aqua: native L&F for entry and spinbox (ingham)
+
+2005-03-23 (new feature) Aqua: [wm attributes -notify] (ingham)
+
+2005-03-29 (platform support) Allow msys builds without cygwin (hobbs)
+
+2005-04-03 (bug fix)[1175092] grid geometry calculations (spjuth)
+
+2005-04-04 (bug fix)[1174269] [text] elide search (darley)
+
+2005-04-04 (bug fix)[1169429] [text] invisible cursor (darley)
+
+2005-04-04 (bug fix)[1083878] \0 char in [tk_getOpenFile -filetypes] (darley)
+
+2005-04-07 (bug fix)[1152809] [wm stackorder] panic; multi-DISPLAY (dejong)
+
+2005-04-14 (bug fix)[1122671] font encoding alignment issue (brubaker,hobbs)
+
+2005-04-18 (bug fix) [text] <Home> and <End> bindings (darley)
+
+2005-04-18 (bug fix)[1185640] [text] passed bogus utf-8 to Tk_MeasureChars
+(petasis,english)
+
+2005-04-25 (platform support) Fix builds on Mac OS X 10.1 (steffen)
+
+2005-05-06 (platform support) Added x86_64 Solaris cc and Solaris 10 build
+support (hobbs)
+
+2005-05-10 (bug fix)[1191895] [text] hang on <Control-Key-Up> (vlasov,darley)
+
+2005-05-14 (enhancement)[1202052] Aqua: CFRunLoop notifier allows
+[load]able Tk (steffen)
+
+2005-05-15 (bug fix)[1012852] Aqua: check/radiobutton accelerator (kirkham)
+
+2005-05-15 (bug fix)[1202181] Aqua: scrollbar thumb position (kirkham)
+
+2005-05-15 (bug fix)[1202223] Aqua: [text] window -> scroll lock (kirkham)
+
+2005-05-22 (bug fix)[1206133] TkGetFileFilters: add all (dionizio,fellows)
+
+2005-05-24 (platform support) Darwin/Aqua builds merged into unix (steffen)
+
+2005-05-27 (behavior change) tk_popup menus now "sticky" (helfter)
+
+2005-05-28 (new feature)[TIP 245] [tk inactive] (max,fellows)
+
+2005-05-30 (bug fix)[1161543,1010941,795869,690169] panedwindow
+display/resizing (south)
+
+2005-05-30 (bug fix)[1159367] [menu] creation segfault (schofield,hobbs)
+
+Documentation improvements [1087842,1081527,1115907,etc.]
+
+--- Released 8.5a3, June 4, 2005 --- See ChangeLog for details ---
+
+2005-06-23 (bug fix)[1176610] Aqua: default [entry] borderwidth (steffen)
+
+2005-07-18 (bug fix)[1240221] [$text mark prev] crash (darley)
+
+2005-07-22 (platform support) msys build now requires msys_mingw7.zip (dejong)
+
+2005-08-09 (Aqua enhancement) Carbon events (steffen)
+
+2005-08-10 (bug fix)[1252702] portable Tcl_GetStringFromObj() calls (fellows)
+
+2005-08-12 (bug fix)[749908] per-thread Tk_ConfigSpec tables (fellows)
+
+2005-08-23 (enhancement)[1244153] use SC_PROG_TCLSH, SC_BUILD_TCLSH (dejong)
+
+2005-08-23 (bug fix)[1235544] adopt Tcl's SEH implementation (kenny,dejong)
+
+2005-08-23 (Aqua bug fix) dialogs ignore -initial* options (hobbs)
+
+2005-10-04 (bug fix)[1216775] [tk_dialog] failing [grab] (fontana,hobbs)
+
+2005-10-04 (bug fix)[1309218] [tk_chooseDirectory -mustexist] (lemburg,hobbs)
+
+2005-10-04 (bug fix)[1311734] Fixed the problems that an embedded windows failed
+to respond to display changes (Windows platform) (chengyemao)
+
+2005-10-10 (new feature)[TIP 256] [$text config -tabstyle] (darley)
+
+2005-10-10 (bug fix)[1319720] Tk_DeleteOptionTable() mem leak (melbardis)
+
+2005-10-12 (new feature) one directory test suite (starpackable) (zolli,fellows)
+
+2005-10-18 (bug fix)[1328926] $argv encoding and list formatting (porter)
+
+2005-11-06 (platform support) OpenBSD missing LIBS (thoyts)
+
+2005-11-10 (bug fix)[1353022] minor potential memleaks (fellows)
+
+2005-11-22 (bug fix)[1353414] [selection get] compat w/OpenOffice.org (fellows)
+
+2005-11-14 (feature change) [bgerror] msg truncation at 45 chars (english)
+
+2005-11-15 (new feature)[TIP 231] [wm attributes] on X11 (english)
+
+2005-11-22 (bug fix)[1335485] dialog and space in widget name (taylor,fellows)
+
+2005-11-27 (platform support) Darwin 64bit, Tiger copyfile(), and
+Max OSX universal binaries support (steffen)
+
+2005-11-29 (bug fix)[1252259] clear initial % from console (lawlor,hobbs)
+
+2005-11-30 (bug fix)[1086049] [wm attributes -topmost] fix (courtney,hobbs)
+
+2005-12-08 (enhancement)[1369597] Win 64: --enable-64bit=amd64|ia64 (hobbs)
+
+2005-12-08 (bug fix)[1374935] [$text tag names] crash with peer (hobbs)
+
+2005-12-12 (bug fix)[1377619] configure syntax error exposed in bash-3.1 (hobbs)
+
+2005-12-13 (Aqua) MouseWheel bindings; kEventMouseScroll events (steffen)
+
+2005-12-28 (bug fix)[1380427] text widget undo/redo crash (callewaert)
+
+2006-01-12 (new feature)[TIP 260] canvas text item -underline option (fellows)
+
+2006-01-20 (bug fix)[905830] all events to XFilterEvent (SCIM compat) (english)
+
+2006-01-25 (feature enhance)[1237759] update script lib to 8.4 (fradin,porter)
+
+2006-01-25 (feature enhance)[1409264] I10N of [bgerror] dialog (fellows)
+
+2006-02-27 (bug fix)[480862] [$img configure -data] no display change (fellows)
+
+2006-02-27 (bug fix)[470322] BitmapInit() thread safety (griffin,fellows)
+
+2006-03-02 (Aqua bug fix) image endian issue on OS X/x86 (hobbs)
+
+2006-03-15 (bug fix)[1409140] speed up photo image updates (fellows)
+
+2006-03-16 (enhancement)[1405069] added Portuguese l10n. (ricardoj,silasj)
+
+2006-03-17 (bug fix)[1451587] no abbreviations in script library (thoyts)
+
+2006-03-21 (enhancement)[638966] Aqua: ATSUI text render (reifenstahl,steffen)
+
+2006-03-23 (platform support) new tk.spec file (max)
+
+2006-03-26 (bug fix)[1414171] crash in [$text dump -command] (macdonald,darley)
+
+2006-03-27 (bug fix)[1458234] crash in animated GIFs (bron,fellows)
+
+2006-03-29 (platform support)[917433] tolerate X servers that do not
+accept the color names "Black" and "White" (porter)
+
+2006-04-06 (bug fix)[1455241] Aqua: [wm attributes -titlepath] fix (steffen)
+
+2006-04-07 (bug fix)[934524] Aqua: background window dragging/growing (steffen)
+
+2006-04-09 (bug fix)[1467004] Aqua: [wm resizable] fix (steffen)
+
+2006-04-09 (bug fix)[1450800] Aqua: allow empty toplevel names (steffen)
+
+2006-04-11 (bug fix)[1073456] Aqua: implement toplevel zoom (steffen)
+
+2006-04-11 (bug fix)[700316] Aqua: enable 'Preferences' app menu item (steffen)
+
+2006-04-11 (bug fix)[1193614] Aqua: tk_messageBox escape key binding (steffen)
+
+2006-04-11 (enhancement)[1105284] Aqua: call ::tk::mac::* procs for all
+registered applevents (steffen)
+
+2006-04-12 (bug fix)[1432666] grid row/col out of bounds crash (spjuth)
+
+2006-04-25 (bug fix)[1475865] crash on invalid font name (fellows)
+
+Documentation improvements [1224983,1247835,1151523,1357575,1083838]
+
+--- Released 8.5a4, April 27, 2006 --- See ChangeLog for details ---
+
+2006-04-28 (bug fix)[1243318] Aqua: incorrect cursor pos in bindings (steffen)
+
+2006-04-28 (bug fix)[1476443] Aqua: incorrect toplevel pos on 1st map (steffen)
+
+2006-05-12 (performance)[1409140] restore perf lost in 2006-03-15 change (hobbs)
+
+2006-05-13 (bug fix)[1481503] Aqua: key shortcut for 'Preferences' (steffen)
+
+2006-05-13 (bug fix)[1155596] Aqua: images with alpha on native btns (steffen)
+
+2006-05-13 (bug fix)[1480105] Aqua: Map/Unmap propagation to children (steffen)
+
+2006-05-13 (bug fix)[940117] Unmap canvas window items on canvas Unmap (steffen)
+
+2006-05-16 (bug fix)[1472624] Aqua: balloon help don't steal focus (steffen)
+
+2006-05-29 (bug fix)[706446] Aqua: active [button] highlight (hobbs)
+
+2006-05-29 (bug fix)[1424513] [listbox] crash with namespace var (hobbs)
+
+2006-06-01 (bug fix)[912571] [console] std chan refcount (mistachkin,hobbs)
+
+2006-06-14 (bug fix)[950121] Aqua: crash in draw of very wide images (steffen)
+
+2006-06-14 (bug fix)[1501922] Aqua: invalid clip regions on redraw (steffen)
+
+2006-06-14 (bug fix)[891141] excess variable writes by [scale] (porter)
+
+2006-07-20 (platform support) Mac OS X weak linking (steffen)
+
+2006-07-21 (bug fix)[700311, 1525905] Aqua: pure modifier keysyms (steffen)
+
+2006-07-24 (bug fix)[1358663] Aqua: [wm geometry -x-y] (steffen)
+
+2006-07-25 (bug fix)[1516950] Aqua: cmd-Q app menu key shortcut (steffen)
+
+2006-08-18 (bug fix)[1542205] Aqua: toplevel toolbar button crash (steffen)
+
+2006-08-21 (bug fix) Aqua: recursively called event loop (steffen)
+
+2006-08-24 (bug fix) Aqua: window grow icon obscuring scrollbar (steffen)
+
+2006-08-30 (new feature)[1518677] WM_UNICHAR window message (hobbs,petasis)
+
+2006-09-10 (bug fix) Aqua: active/inactive text selection color&relief (steffen)
+
+2006-09-10 (bug fix)[1472624] Aqua: mouse events in overrideredir wins (steffen)
+
+2006-09-11 (bug fix) Aqua: app menu shortcuts with custom .apple menu (steffen)
+
+2006-09-22 (bug fix)[1562528] NULL terminates variadic calls (fellows,ryazanov)
+
+2006-09-22 (new feature)[TIP 268] [package provide] full patchlevel (kupries)
+
+2006-10-05 (bug fix)[1122671] alignment fixes in ucs-2be encoding routines
+(hobbs,staplin)
+
+2006-10-08 (new feature)[TIP 264] New public routine Tk_Interp() (thoyts)
+
+2006-10-16 (bug fix)[1558051] Aqua: CG drawing matches X11 (steffen)
+
+--- Released 8.5a5, October 20, 2006 --- See ChangeLog for details ---
+
+2006-10-30 (new feature)[TIP 48] Addition of themed tk widgets to Tk as Ttk
+(themed Tk). Adds ttk::notebook, ttk::sizegrip, ttk::combobox,
+ttk::panedwindow, ttk::progressbar, ttk::menubutton, ttk::button,
+ttk::radiobutton, ttk::checkbutton, ttk::treeview, ttk::separator,
+ttk::scrollbar, ttk::entry, ttk::frame and ttk::labelframe widgets. Adds
+ttk::style command.
+
+2006-11-02 (enhancement) Improve OS X Carbon Update event handling (steffen)
+
+2006-11-07 (configure change) Unix --enable-xft is enabled by default (kenny)
+
+2006-11-23 (bug fix)[1599877] Fix unicode character underline in menus (hobbs)
+
+2006-11-24 (bug fix)[1487701] Better handling of tcl_interactive on OS X to
+control display of console (hobbs, steffen)
+
+2006-11-26 (platform support)[1230558] --enable-64bit on more systems (steffen)
+
+2006-11-30 (bug fix) Fix handling of Escape binding on OS X dialogs (steffen)
+
+2006-12-01 (new feature) Add -transparentcolor wm attribute on Windows (hobbs)
+
+2006-12-01 (new feature)[TIP 300] Added [font actual $font $char] (kenny)
+
+2006-12-04 (new feature)[TIP 286] Added [$menu xposition] subcommand (bron)
+
+2006-12-11 (enhancement) Improved EWMH support for _NET_WM_PID and
+_NET_WM_PING (fellows)
+
+2007-01-25 (configure change) ensure CPPFLAGS env var used when set (steffen)
+
+2007-02-19 (configure change) Use SHLIB_SUFFIX=".so" on HP-UX IA64 (was
+".sl") (hobbs)
+
+2007-04-10 (platform support) Correctly handle theming on Vista/Aero (english)
+
+2007-04-23 (enhancement) Allow empty value for -selectforeground opt (steffen)
+
+2007-04-23 (platform support) Aqua: remove Tk-internal double buffering that is
+wasteful on Aqua; allows direct-to-window CoreGraphics drawing (e.g. adding
+support for colors with alpha) (steffen)
+
+2007-04-23 (platform support) Aqua: add all OS theme colors/brushes (patterns)
+as system colors (steffen)
+
+2007-04-23 (platform support) Aqua: tk_dialog & bgerror use OS theme (steffen)
+
+2007-04-23 (platform support) Aqua: add 'none' & missing theme cursors (steffen)
+
+2007-04-23 (platform support) Aqua: [tk_getOpenFile -parent] et al use sheet
+dialog (steffen)
+
+2007-04-23 (bug fix) Aqua: fix custom MDEF and tearoff menu display (steffen)
+
+2007-04-23 (bug fix)[1620826] Aqua: fix <<MenuSelect>> support (steffen)
+
+2007-04-23 (platform support) Aqua: add support for live window resizing and
+asynchronous window dragging; prevent window from becoming inacessible
+offscreen or under Dock after dragging; use transparent grow box (steffen)
+
+2007-04-23 (platform support) Aqua: improve event processing during nested
+event loops (e.g. modal dialogs, menu tracking, window resizing etc) (steffen)
+
+2007-04-23 (bug fix) Aqua: add support for all possible aqua scrollbar arrow
+positions, scrollbar variants and for "jump to here" scrollbar behaviour;
+correct scroll view size computation; enforce minimal scrollbar height (steffen)
+
+2007-04-23 (platform support) Aqua: add [wm attributes] -topmost, -fullscreen
+and -transparent (fully transparent win via -bg "systemTransparent") (steffen)
+
+2007-04-23 (platform support) Aqua: determine win min/max sizes dynamically;
+correct size handling of gridded windows; improve computation of initial
+window bounds; correct window size handling on multi-headed systems (steffen)
+
+2007-04-23 (platform support) Aqua: correct composite attribute handling in
+[tk::unsupported::MacWindowStyle] and add new attributes; allow changing
+window class of already existing windows (steffen)
+
+2007-04-23 (platform support) Aqua: add tcl document extensions and mime type
+to Wish.app's Info.plist (steffen)
+
+--- Released 8.5a6, April 25, 2007 --- See ChangeLog for details ---
+
+2007-05-04 (new feature)[TIP 145] Enhanced font handling (thoyts)
+
+2007-05-14 (bug fix)[1712081] restored USE_OLD_IMAGE support (porter)
+
+2007-05-15 (bug fix)[1717830,800149] memory leaks (jenglish)
+
+2007-05-15 (bug fix)[1677608] [grid *configure] crash (porter)
+
+2007-05-31 (platform support) Aqua: improve interaction of Expose events and
+idle-time redraws (steffen)
+
+2007-05-31 (bug fix) Aqua: gridded window max-size calculation (steffen)
+
+2007-06-02 (bug fix)[1731734] Aqua: menu cascades outside menubar (steffen)
+
+2007-06-06 (platform support) Aqua: enable MouseWheel events in background
+windows (steffen)
+
+2007-06-09 (bug fix)[1724223] Unicode menu entry crash (hobbs)
+
+2007-06-09 (bug fix)[1467997] Blue/red reversal in icons (hobbs,janssen)
+
+2007-06-23 (bug fix) Aqua: nav dialog sheet crash (steffen)
+
+2007-06-29 (platform support) Aqua: remove private internal declarations from
+installed tkMacOSXInt.h header (steffen)
+
+2007-06-29 (bug fix) Aqua: scrollbar thumb size calculation (steffen)
+
+2007-07-09 (bug fix) Aqua: app-is-frontmost detection (steffen)
+
+2007-07-09 (bug fix) Aqua: window click activation & titlebar click handling
+in presence of grabs or modal windows (steffen)
+
+2007-07-25 (bug fix)[1743786] Aqua: [tk_getOpenFile] result (steffen)
+
+2007-08-01 (bug fix)[1692927] [tk_messageBox -detail] buffer (davies,thoyts)
+
+2007-08-27 (bug fix)[1782105] Aqua: tk_chooseColor result (steffen)
+
+2007-09-06 (platform support) Aqua: drop support for Xcode 1.5 project, add
+project for Xcode 3.0 (steffen)
+
+2007-09-11 (bug fix) Animated GIF buffer overrun (max)
+
+2007-09-15 (platform support) SunOS-5.1x link with cc, not ld (steffen)
+
+2007-09-17 (enhancement)[1780286] Aqua: combobox appearance (english)
+
+2007-09-17 (platform support)[1748251] Fix NetBSD link failures (english)
+
+2007-09-20 (bug fix)[1791052] [text] DLine layout crash (khomoutov,fellows)
+
+--- Released 8.5b1, September 26, 2007 --- See ChangeLog for details ---
+
+2007-09-26 (enhancement)[1800742] msg catalog for Hungarian. (reszo)
+
+2007-10-11 (bug fix)[1810818] Aqua: [wm resizeable] (steffen)
+
+2007-10-12 (platform support) Aqua: replace RgnHandles by HIShapeRefs (steffen)
+ *** POTENTIAL INCOMPATIBILITY for C code acessing MacDrawable Rgns ***
+
+2007-10-15 (platform support) Mac OS X: 64-bit X11 support (steffen)
+
+2007-10-15 (new feature)[TIP 125][998125] dockable frame support (hobbs)
+
+2007-10-22 (bug fix)[1814778,1780286,1609168,1349586] combobox overhaul(english)
+
+2007-10-22 (platform support) Aqua: TIP 145 and Aqua Theme fonts (steffen)
+
+2007-10-23 (bug fix)[1818441] combobox & reparentable frames (hobbs)
+
+2007-10-24 (bug fix)[1723362] Win: transparent bitmaps (mcdonald,thoyts)
+
+2007-10-25 (bug fix)[1818491] crash in [place] manager (mcdonald)
+
+2007-10-25 (new feature)[TIP 242][1156388] file dialog filter (hobbs)
+
+2007-10-25 (bug fix)[1817596] ttk::notebook (english)
+
+2007-10-26 (bug fix)[1816252] Aqua: [wm transient] (steffen)
+
+Improvements to demo suite to make more use of Tk 8.5 features (fellows,steffen)
+
+--- Released 8.5b2, October 26, 2007 --- See ChangeLog for details ---
+
+2007-10-29 (appearance change) Default look and fonts on X11 (hobbs)
+ *** POTENTIAL INCOMPATIBILITY; [::tk::classic::restore] to undo ***
+
+2007-10-30 (bug fix)[1803723] Win: Arabic and Hebrew rendering (fellows)
+
+2007-10-30 (bug fix)[1550528] [tk_chooseDirectory -mustexist true] disables
+the "OK" until valid selection (hobbs)
+
+2007-11-03 (new feature) adjustable [console] fonts (thoyts)
+
+2007-11-04 (enhancement) Aqua: "Run Widget Demo" menu item (steffen)
+
+2007-11-09 (bug fix) Aqua: activate event after window expansion (steffen)
+
+2007-11-09 (bug fix)[1824521] Aqua: menubutton crash with -bitmap (steffen)
+
+2007-11-09 (platform support) Aqua: (menu)button pressed/inactive/disabled
+look&feel; menubutton size with -image/-bitmap (steffen)
+
+2007-11-09 (bug fix) Aqua: [tk_getOpenFile] (et al.) and help menu crashes on
+Mac OS X Leopard (steffen)
+
+2007-11-11 (bug fix)[1824638] Aqua: small max-width text measuring (riefenstahl)
+
+2007-11-14 (bug fix)[1831803] sv.msg catalog for "sv" locale (fellows)
+
+Many significant improvements to the documentation and demos (fellows, hobbs,
+steffen, kupries)
+
+--- Released 8.5b3, Novemeber 19, 2007 --- See ChangeLog for details ---
+
+2007-11-25 (bug fix)[1343984] ttk::notebook bugs (english,boudaillier)
+
+2007-11-26 (bug fix)[1822391] [photo put] segfault w/ PPM data (kenny)
+
+2007-11-26 (bug fix)[1822076] [tk_saveFile] and path w/spaces (bauer,kenny)
+
+2007-12-04 (new feature)[1844143] Danish message catalog (berg)
+
+2007-12-11 (bug fix)[1602537] crash in [$text replace] (goth,porter,fellows)
+
+2007-12-12 (bug fix)[1845899] Aqua: [wm transient] (steffen)
+
+2007-12-12 (bug fix)[1809538,1799782,1737288] fixes for the <<Modified>>
+virtual event on [text] widgets (hobbs)
+
+2007-12-13 (bug fix) correctly trace menubutton -textvariable for -compound
+use (hobbs)
+
+Several documentation and release notes improvements
+
+--- Released 8.5.0, December 18, 2007 --- See ChangeLog for details ---
+
+2007-12-30 (bug fix)[1860802] fixed Dutch message catalog (markus,fellows)
+
+2008-01-06 (bug fix)[1442006,1821939,18862692] MouseWheel for treeview (english)
+
+2008-01-08 (bug fix)[1865898,1679067] button size & state (english)
+
+2008-01-08 (bug fix)[1867122] [labelframe -style] crash (english,rib)
+
+2008-01-27 (bug fix)[1835848] size value returned by [font actual] (english)
+
+2008-01-27 (bug fix)[1878298] [notebook] redraws on tab visibility (english)
+
+2008-01-31 (bug fix)[1881892] messagebox default title (hobbs)
+
+2008-02-01 (bug fix)[CVE-2008-0553] buffer overflow in GIF format (max)
+
+--- Released 8.5.1, February 5, 2008 --- See ChangeLog for details ---
+
+2008-02-27 (bug fix)[1863346] Aqua: memleak in QD drawing (steffen)
+
+2008-02-29 (enhancement) Knight's tour demo (thoyts)
+
+2008-03-12 (bug fix)[1090382] crash when GetFont() fails (jenglish)
+
+2008-03-13 (enhancement) support space in INSTALL_ROOT or $builddir (steffen)
+
+2008-03-21 (bug fix)[1863007,1920030] Export Ttk stubs table (english)
+
+2008-03-26 (bug fix)[1922466] crash in [. configure -cursor] (gavilán)
+
+2008-03-27 (platform support)[1921166] Solaris 64bit build fixes (steffen)
+
+2008-03-27 (bug fix) restored [::safe::loadTk] (hobbs)
+
+--- Released 8.5.2, March 28, 2008 --- See ChangeLog for details ---
+
+2008-04-01 (interface)[1819422] tkStubsPtr no longer in libtk (porter)
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2008-04-02 (interface)[1819422] libtkstub symbols MODULE_SCOPE (steffen)
+
+2008-04-07 (bug fix)[1937135] Tk_ParseArgv() double free crash (hobbs)
+
+2008-04-07 (bug fix)[1936238] wish -h mem explosion (bachmann,kenny)
+
+2008-04-08 (new feature) Win: visual-styles API element engine (thoyts)
+
+2008-04-09 (enhancement) real LZW compression in GIF writer (nijtmans)
+
+2008-04-14 (bug fix)[1941740] [tk_chooseColor -title] (thoyts)
+
+2008-04-16 (interface)[1938497] make stubs tables 'static const' (steffen)
+
+2008-04-17 (bug fix)[1327482] canvas item <Enter> events (wangnick)
+
+2008-05-23 (bug fix)[1967576] ttk::label height or width 0 panic (lawlor)
+
+2008-06-10 (enhancement)[1986818] Use Xutf8LookupString when possible (english)
+
+2008-06-12 (bug fix)[1991932] global grab segfault (steffen)
+
+2008-06-12 (platform support) Solaris/amd64 gcc 64bit support (steffen)
+
+2008-06-13 (new feature)[TIP 285] [tkwait] and [update] are now
+[interp cancel]able (mistachkin)
+
+2008-06-18 (bug fix) Aqua: missing focus on first map (steffen)
+
+--- Released 8.6a1, June 25, 2008 --- See ChangeLog for details ---
+
+2008-07-04 (bug fix)[2009213] crash in [ttk::scale] (polo,english)
+
+2008-07-24 (bug fix)[2021443] consistent "wrong # args" messages (nijtmans)
+
+2008-07-26 (bug fix)[2026405] portability of [winfo id] (uchida,thoyts)
+
+2008-07-31 (bug fix) export Tk_PkgInitStubsCheck; fixes Tk embed on Windows
+
+2008-08-01 (bug fix)[2009788,2028703] unmapped toplevel crashes (thoyts)
+
+2008-08-05 (bug fix)[2010422] Tk header files revised to accommodate
+incompatible changes in recent X.org releases of X11 headers. (jenglish)
+
+2008-08-19 (bug fix) revised number format in -[xy]scrollcommand callbacks
+and [xy]view methods (jenglish)
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2008-08-19 (enhancement) removed obsolete XID management code (staplin)
+
+Test suite modernization by Ania Pawelczyk.
+
+--- Released 8.6a2, August 25, 2008 --- See ChangeLog for details ---
+
+2008-08-25 (bug fix)[1936220] fix [tk_getOpenFile -multiple 1] on unix (helfter)
+
+2008-08-25 (bug fix)[1023955] default menu cursor: no more Motif (helfter)
+
+2008-08-28 (bug fix) correct TK_LIBS value to include Xft (porter)
+
+2008-09-03 (support) Dropped support for pre-ANSI compilers. (porter)
+
+2008-10-01 (new feature)[TIP 236] [$canvas moveto] (mckay,fellows)
+
+2008-10-05 (bug fix)[2112563] format double values explicitly in double
+format, avoiding sensitivity to locale setting. (fellows)
+ *** POTENTIAL INCOMPATIBILITY ***
+
+--- Released 8.6a3, October 10, 2008 --- See ChangeLog for details ---
+
+2008-10-17 (enhancement) keyboard bindings for ttk::scale (thoyts)
+
+2008-10-18 (bug fix)[1825353] Russian Windows tiny fonts problem (thoyts)
+
+2008-10-18 (new feature)[TIP 321] [tk busy] (decoster,fellows)
+
+2008-10-28 (bug fix)[1534835,2054562] use of more correct cursors (english)
+
+2008-11-01 (new feature) New [ttk::spinbox] widget (thoyts)
+
+2008-11-01 (new feature)[TIP 97] [$canvas imove] [$canvas rchars] (fellows)
+
+2008-11-09 (bug fix)[2207435] [ttk::entry .t -textvar ::noexist::x] (english)
+
+2008-11-11 (bug fix)[2312027] Tk_Create*ImageType() thread safety (nijtmans)
+
+2008-11-11 (bug fix)[2264732] crash using nondefault visual (english)
+
+2008-11-12 (bug fix)[1777362] permit [text] names containing "-" (thoyts)
+
+2008-11-14 (bug fix)[2239034] limit [wm manage] to Frames (thoyts)
+
+2008-11-22 (new feature)[TIP 119] -angle option for canvas text items (fellows)
+
+2008-11-22 (bug fix)[1939129,1991930] combobox behind other windows (thoyts)
+
+2008-11-22 (new feature) Demo ctext.tcl now demos angled text (fellows)
+
+2008-11-23 (bug fix)[1389270] made [event generate <Focus*>] work (thoyts)
+
+2008-11-28 (bug fix)[1813597,2218964] eliminate unnecessary units conversion
+in screen distances, reducing precision loss (ferrieux)
+
+2008-12-03 (enhancement) new "hover" state for proper Vista visuals (thoyts)
+
+2008-12-05 (bug fix)[2107938] no negative font size in PS (fellows)
+
+2008-12-05 (enhancement) new "vista" theme (thoyts)
+
+2008-12-06 (new feature)[TIP 197] [$text -insertunfocussed] (edwards,fellows)
+
+2008-12-06 (new feature)[TIP 337] handle non-error bg exceptions (porter)
+
+2008-12-10 (new feature)[TIP 324] [tk fontchooser](thoyts,vetter,robert,steffen)
+
+2008-12-12 (new feature) Demo fontchoose.tcl demos [tk fontchooser] (thoyts)
+
+2008-12-18 (enhancement)[24442309] Updated German messages (haertel)
+
+--- Released 8.6b1, December 19, 2008 --- See ChangeLog for details ---
+
+2008-12-27 (bug fix)[2381555] horiz. scroll [$treeview identify] (english)
+
+2008-12-28 (new feature)[TIP 244] PNG photo format support (fellows)
+
+2008-12-28 (new feature)[TIP 171] <MouseWheel> event handling (fellows)
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2008-12-31 (bug fix)[2003310] radio|check button indicator color (english)
+
+2009-01-06 (bug fix)[2484771] messagebox: system to task modal (ferrieux,thoyts,mjanssen)
+
+2009-01-06 (enhancement)[1539990] optimize photo building (jepler)
+
+2009-01-07 (bug fix)[2473120] chooseDir syntax error (bron)
+
+2009-01-07 (bug fix)[1847002] Win: prevent grab bypass (thoyts)
+
+2009-01-11 (bug fix)[2496162] crash calling Tk_DeleteOptionTable() (english)
+
+2009-01-11 (bug fix) crash on XCreateIC failure (staplin)
+
+2009-01-14 (bug fix)[2507326] Restore aMSN compat (nijtmans)
+
+2009-01-19 (new feature) CONFIG_INSTALL_DIR - where tkConfig.sh goes (cassoff)
+
+2009-01-19 (platform support) better tools for BSD ports (cassoff)
+
+2009-02-08 (bug fix)[2431428] panic computing layout on active widget (english)
+
+2009-02-17 (platform support) MSVC and _WIN64 (hobbs)
+
+2009-02-21 (bug fix)[2546087] [console] display of true UTF-8 \0 (thoyts)
+
+2009-02-23 (bug fix)[1329198,456299,2507419] menu image display (mcdonald)
+
+2009-02-23 (bug fix)[2513104] fix cursor hotspots (mcdonald)
+
+2009-02-23 (bug fix)[2542828] Win: standard question_arrow cursor (danckaert)
+
+2009-02-27 (bug fix)[2645457] crash in Tk_MakeWindowExist() (thoyts)
+
+2009-03-09 (bug fix)[2548661] crash in GetFontFamilyName (riefenstahl)
+
+2009-03-25 (bug fix)[2178820] stop zero-size allocs in ttk (fellows)
+
+2009-03-25 (bug fix)[1871101] blurry large fonts on Vista (garvey,fellows)
+
+2009-04-03 (bug fix)[1789819] stop panic on unexpected wm stack order (english)
+
+2009-04-10 (bug fix)[2116837] std virtual events with Caps Lock (fellows)
+
+2009-04-10 (platform) sse Darwin SUSv3 extensions if available (steffen)
+
+2009-04-10 (bug fix) Motif checkbutton on X11 only (steffen)
+
+2009-04-10 (bug fix) remove TkAqua Quit menu item on [console] (steffen)
+
+2009-04-10 (bug fix) crash deleting char range from [text] (steffen)
+
+2009-04-23 (bug fix)[2779910] updated Win chooseDir (hobbs)
+
+2009-04-24 (bug fix) prevent delete of selected folder in Win dialog (hobbs)
+
+2009-04-30 (bug fix)[2080533] panedwindow sash draw crash (fellows)
+
+2009-04-30 (bug fix)[2504402] iconphoto on non-32-bit displays (mcdonald,thoyts)
+
+2009-05-01 (bug fix)[2777019] anchor for text rotation (gavilán,fellows)
+
+2009-05-03 (bug fix)[2785744] broken flag twiddling (baker,fellows)
+
+2009-05-13 (bug fix)[2791352] XLFD parsing error (thoyts)
+
+2009-05-14 (new feature) Vista theme support (thoyts)
+
+2009-05-14 (bug fix)[1923684] confused checkbutton state (thoyts)
+
+2009-05-17 (new feature)[1470246] notebook tab orientation control (english)
+
+2009-05-21 (bug fix)[2794778] Win menu keyboard traversal (thoyts)
+
+2009-06-02 (bug fix)[2799589] crash on delayed window activation (thoyts)
+
+2009-06-23 (bug fix)[220935] canvas dash update problem (nijtmans)
+
+2009-06-23 (platform) new subdir 'carbon' preserved for OSX 10.4-
+use --enable-aqua=carbon option to unix/configure to enable (steffen)
+
+2009-06-29 (new feature) source in `macosx` now built on Cocoa (steffen)
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2009-06-30 (platform support) clang static analyzer macros (steffen)
+
+2009-07-15 (bug fix)[2821962] photo image copy/paste (rib,fellows)
+
+2009-07-21 (bug fix)[2356057] rotated underlined text (fellows)
+
+2009-07-22 (bug fix)[2496114] focus in dead window crash (griffin,fellows)
+
+2009-07-23 (bug fix)[2441988] report errors in selection handlers (fellows)
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2009-08-01 (bug fix)[2830420] X iconphoto for big endian (misch,fellows)
+
+2009-08-04 (bug fix) [text] word-wrap of non-breaking space (fellows)
+
+2009-08-14 (bug fix) copy from unmapped toplevel crash (alaoui,steffen)
+
+2009-08-19 (bug fix)[2475855] prevent grid & pack on same master (spjuth)
+
+2009-08-24 (bug fix)[2821084] Cocoa: let WM_DELETE_WINDOW handler stop window
+deletion (walzer,steffen)
+
+2009-08-24 (bug fix) tk::MessageBox bindings for ttk::buttons (steiner,fellows)
+
+2009-08-25 (bug fix)[1909931] [send] update for Fedora 8 (fellows)
+
+2009-09-10 (bug fix) font allocation crash (berezhnoy,fellows)
+
+2009-09-14 (bug fix)[873608] win tearoff menu, no submenu arrows (traum,hobbs)
+
+2009-09-14 (bug fix)[873613] win tearoff menu repeat select (traum,hobbs)
+
+2009-09-25 (bug fix) grayscale from images (vetter,fellows)
+
+2009-10-07 (bug fix)[2088597] min scrollbar slider size (danckaert,fellows)
+
+2009-10-07 (bug fix)[2787164] combobox/menubutton arrow size (thoyts)
+
+2009-10-08 (bug fix)[2870648] file dialog cursor (danckaert,fellows)
+
+2009-10-10 (feature)[1961455] underline, overstrike Xft fonts (caffin,fellows)
+
+2009-10-20 (enhancement) Updates to Polish messages (pawlak)
+
+2009-10-22 (bug fix)[2168768] file dialog -typevariable scope (danckaert)
+
+2009-10-22 (bug fix)[1469210] [text] modified error (danckaert)
+
+2009-10-22 (bug fix)[2883712] 64-bit Aqua progress bar (haffner)
+
+2009-10-24 (bug fix)[1530276] X checkbutton -selectcolor (danckaert)
+
+2009-10-25 (bug fix)[1854913] [.t delete] before -startindex (danckaert)
+
+2009-10-25 (bug fix)[2809525] prevent X crash on overlong color name (goth)
+
+2009-10-29 (bug fix)[1825353] Russian Windows tiny fonts problem (thoyts)
+
+2009-11-01 (new feature) Ttk: [$w identify] now an ensemble (jenglish)
+
+2009-11-19 (bug fix)[2899685] fix [imove] redraw logic (schekin,ferrieux)
+
+2009-11-22 (bug fix)[2899949] crash on widget destroy (meier,thoyts)
+
+2009-11-23 (bug fix)[2902573] Update Safe Tk to new Safe Base (kurpies)
+
+2009-11-24 (bug fix)[2902814] fix [wm iconphoto] on LP64 systems (fellows)
+
+2009-12-08 (bug fix)[2864685] Compiz menu item animation (gavilán,thoyts)
+
+2009-12-11 (bug fix)[2912473] accept :: in DISPLAY name (fellows)
+
+2009-12-15 (bug fix)[2492179] Tcl_ObjType "option" no longer registered (porter)
+ *** POTENTIAL INCOMPATIBILITY for Tcl_GetObjType("option") ***
+
+2009-12-20 (bug fix)[2917663] [send] accept SI:* on auth list (fellows)
+
+2009-12-22 (bug fix)[2912356] [ttk::sizegrip] accommodate Compiz (english)
+
+2009-12-25 (bug fix)[2977688,2546779] tab selection focus (english)
+
+2009-12-27 (bug fix)[2879927] Win: cascade menu highlight (pawlak,thoyts)
+
+2010-01-01 (bug fix)[1924761] stop [event generate] / XIM conflict (fellows)
+
+2010-01-03 (bug fix)[2848897] ODS_NOACCEL flag support (kovalenko,thoyts)
+
+2010-01-04 (bug fix)[2811266] <Return> binding in [tk_dialog] (thoyts)
+
+2010-01-04 (bug fix)[2727476] font dialog appearance (thoyts)
+
+2010-01-05 (bug fix)[220950] [$menu delete] bounds check (fellows)
+
+2010-01-05 [2898255] unlimited multi-file select (pawlak,fellows,thoyts)
+
+2010-01-06 (bug fix)[1163496] X: [wm transient] fix (bateman,fellows)
+
+2010-01-09 (new feature)[TIP 360] Modernize X11 Menus (thoyts)
+
+2010-01-18 (bug fix)[2932808] canvas update on state change (mcdonald,nijtmans)
+
+2010-01-19 (new feature)[TIP 359] Extended Window Manager Hint Support (thoyts)
+
+2010-01-19 (bug fix)[2931374] overflow in complex tag search (schmitz)
+
+2010-02-17 (bug fix)[2952745] crash in menu deletion (english)
+
+2010-02-20 (performance) treeview stop quadratic common case (english)
+
+2010-03-02 (enhancement) -fvisibility-hidden build support (nijtmans)
+
+2010-03-06 (bug fix)[2949774] cascade menu unpost (thoyts)
+
+2010-03-11 (bug fix)[2968379] crash in peer text dump (fellows)
+
+2010-03-17 (bug fix)[2971663] Cocoa entry <Up>, <Down> (goddard,fellows)
+
+2010-03-28 (new feature) [$treeview tag names|add|remove] (english)
+
+2010-04-09 (new feature)[2983824] [$image write -file] use extension of file
+name to select image format (fellows)
+
+2010-04-19 [2898255] unlimited multi-file select (pawlak,fellows,thoyts)
+
+2010-05-31 (bug fix)[3006842] crash on empty bind scripts (english)
+
+2010-06-15 (bug fix)[2585265] text <Delete>,<Backspace> note selection (fellows)
+
+2010-06-15 (new package)[3016598] Tk now provides "tile 0.8.6" (english)
+
+2010-07-19 (new feature) [$photo data -format GIF] (fellows)
+
+2010-08-03 (bug fix) entry validation compat with Itcl scope (hobbs)
+
+2010-08-11 (platform) Drop pre-aix 4.2 support, ldAix (hobbs)
+
+2010-08-21 (patch)[3034251] genStubs steal features of ttkGenStubs (nijtmans)
+
+2010-08-26 (bug fix)[1230554] configure, OSF-1 problems, windows manifest issues (hobbs)
+
+2010-08-31 fixed manifest handling on windows (hobbs, kupries)
+
+2010-09-02 (bug fix)[3057573] specify combobox text fg color (english)
+
+2010-09-05 (enhancement)[3046742,3046750] Improved error dialog UI (fellows)
+
+2010-09-08 (bug fix)[2829363] [$tv see] open item -> sched display (english)
+
+2010-09-13 (platform) limit support to Win2000+ (nijtmans)
+
+2010-10-01 (bug fix)[3078902] no hang operating on zero-size subimages (fellows)
+
+2010-10-05 (bug fix)[3080953] corrupt multibyte char in %A subst (nijtmans)
+
+2010-10-11 (bug fix)[3085489] crash in [tag add/remove] (english)
+
+2010-10-11 (enhancement)[491789] Unicode command line support on Win (nijtmans)
+
+2010-11-03 windows build with -UNICODE (nijtmans)
+
+2010-11-05 Message catalogs reworked to use unicode copyright char (nijtmans)
+
+2010-11-06 Message catalogs resorted, updates to NL (nijtmans)
+
+2010-11-16 (platform) VS 2005 SP1 MSVC compiler (nijtmans)
+
+2010-11-24 (bug fix)[3071836] crash in tk_getSaveFile (twylite)
+
+2010-12-03 (enhancement)[3116490] mingw x-compile improvements (nijtmans)
+
+2010-12-12 (platform) OpenBSD build improvements (cassoff)
+
+2010-12-17 (platform) Revisions to support rpm 4.4.2 (cassoff)
+
+2011-01-06 (bug fix)[2857300] Cocoa: correct text width rounding (walzer)
+
+2011-01-06 (bug fix)[3086887] Cocoa: textured bg windows (walzer)
+
+2011-01-13 (bug fix)[3154705] tk_messageBox close button disabled (skylera)
+
+2011-01-22 (enhancement) add [ttk::entry validate] (schelte,english)
+
+2011-01-24 (bug fix)[2907388] OSX: composite character entry crash (berg,walzer)
+
+2011-03-02 (new doc) tk_mac.n: OS X specific functions (walzer)
+
+2011-03-03 (bug fix)[3175610] incomplete line item refresh (ferrieux)
+
+2011-03-10 (bug fix)[3205260] crash in [wm manage] (boudaillier, thoyts)
+
+2011-03-16 (bug fix)[3181181] tearoff submenu fix (menez, thoyts)
+
+2011-03-19 (bug fix)[3205464] [wm forget] loses window (boudaillier,thoyts)
+
+2011-03-19 (bug fix)[3223850] ttk button state disabled during click (thoyts)
+
+2011-03-22 (bug fix)[3000002] ttk scrollbar size Appearance (garvey,thoyts)
+
+2011-03-24 (bug fix)[3239768] Win menu font support (wehle)
+
+2011-03-28 (bug fix)[3129527] stop buffer overflows (dirtyepic,nijtmans)
+
+2011-04-04 (feature change)[2997657] No -container for [labelframe] (spjuth)
+
+2011-04-04 (bug fix)[723765] [grid remove] lost -in value (saye,spjuth)
+
+2011-04-22 (bug fix)[3291543] mem corrupt when [$canvas dchars] removes all
+coords of a polygon (rogers,spjuth)
+
+2011-04-29 (platform support) [wm forget|manage] on OS X (walzer)
+
+2011-06-06 (bug fix)[2546087] [console] treatment of '\0' (porter)
+
+2011-06-07 (bug fix)[2358545] Restore "08" in spinbox configured with -from
+and -to (porter)
+
+2011-06-10 (bug fix)[3315731] fix [$entry -invcmd] (porter)
+
+2011-06-17 (bug fix)[3062331] crash in unset traces (macdonald,porter)
+
+2011-08-03 (bug fix)[2891541] fix grab behaviour for main window (thoyts)
+
+--- Released 8.6b2, August 8, 2011 --- See ChangeLog for details ---
+
+2011-09-22 (bug fix)[3404541] -takefocus option (dzach,english)
+
+2011-10-24 (new feature)[TIP 382] -confirmoverwrite on save dialog (porter)
+
+2011-10-25 (bug fix)[3410609] AltGr keysyms on Swiss keyboard (tasser,kenny)
+
+2011-11-17 (bug fix)[3437816] return code of [canvas lower] (hirner,ferrieux)
+
+2011-12-22 (bug fix)[3235256] correct menu failure on Windows (mcdonald)
+
+2012-01-19 (bug fix)[3021557] cursor freeze in elided text (vogel)
+
+2012-01-22 (bug fix)[3476698] hang in [text mark prev/next] (vogel)
+
+2012-01-25 (bug fix)[3475627] Stop text-31.11 failure (vogel)
+
+2012-01-25 (bug fix)[1630271] hang/crash on mark before -startline (vogel)
+
+2012-01-26 (bug fix)[1754043,2321450] -blockcursor appearance (vogel)
+
+2012-01-27 (bug fix)[3480471] crash in [tk_getOpenFile] (nijtmans)
+
+2012-01-29 (bug fix)[3480634] PNG image in menus (nijtmans)
+
+2012-01-30 (bug fix)[2925561] disabled combobox don't take focus (english)
+
+2012-02-10 (bug fix) win dialog avoid shimmer that confuses Python (fellows)
+
+2012-02-15 (bug fix)[3486474] Correct color scaling (goth,nijtmans)
+
+2012-02-28 (bug fix)[1630262,1615425] [text] crash tags & -*line (vogel)
+
+2012-03-07 (bug fix)[3497848] consistent pixel rounding (fassel,fellows)
+
+2012-03-18 (enhancement)[3503317] XParseColor speedup (nijtmans)
+
+2012-04-07 (bug fix)[3176239] control-Mousewheel crash (couch,nijtmans)
+
+2012-04-22 (bug fix)[3520202] <MouseWheel> %k,%K,%N for Python (deily,fellows)
+
+2012-05-02 (bug fix)[533519] multiscreen window placement (nijtmans)
+
+2012-05-04 (bug fix)[2768586] multiscreen menu posting (nijtmans)
+
+2012-05-28 (bug fix)[1630254] text peer update on -startline reset (baker,vogel)
+
+2012-06-11 (bug fix)[3294450] ttk text element clipping (oehlmann,fellows)
+
+2012-07-02 (bug fix) Make sure all index tables are static (kirkham,english)
+
+2012-07-23 (bug fix)[3546073] DisplayString() -> DefaultDisplay() (english)
+
+2012-08-11 (bug fix)[3554273] text elide and tags (vogel)
+
+2012-08-15 (enhancement)[3555324] Win:Ctrl-A now means Select-All (nijtmans)
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2012-08-22 (new feature)[TIP 403] Use Web color definitions (nijtmans)
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2012-08-23 (enhancement)[3555644] better use of virtual events (nijtmans)
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2012-08-24 (bug fix)[3558535] file dialog filtering (fellows)
+
+2012-08-25 (bug fix)[3554026,3561016] crash with tearoff menus (gavilán)
+
+2012-09-11 (bug fix)[3566594] stop clip region leaks (fellows)
+
+2012-09-15 (bug fix)[3567778] stop hang in wrapped label (porter)
+
+2012-09-17 (bug fix)[3567786] stop segfault in [wm forget] (porter)
+
+Many revisions to better support a Cygwin environment (nijtmans)
+
+--- Released 8.6b3, September 18, 2012 --- See ChangeLog for details ---
+
+2012-10-02 (bug fix)[3572016] menu enable after modal dialog (berg,walzer)
+
+2012-10-08 Remove Carbon support
+
+2012-10-24 (bug fix)[3574893] crash in [wm forget] (porter)
+
+2012-11-07 (bug fix)[3574708] crash in focus handling (fellows)
+
+2012-11-14 (bug fix)[3500545] fix [tk_getOpenFile -multiple] (bruederlin)
+
+2012-12-04 (bug fix)[3588824] Support weird image names in [text] (vogel)
+
+2012-12-06 (bug fix)[3592736] stop pink greys from buggy mingw builds (fellows)
+
+--- Released 8.6.0, December 20, 2012 --- See ChangeLog for details ---
+
+2013-01-04 (bug fix) Tk_InitStubs("8.6") rejected in 8.60 interp (nijtmans)
+
+2013-01-10 (bug fix)[3600251] Mac <Control-v> binding (kjnash,nijtmans)
+
+2013-01-10 (bug fix)[3600260] <<SelectNextPara>> binding (kjnash,nijtmans)
+
+2013-01-13 (bug fix)[3600290] restore $tk_strictMotif respect (kjnash,nijtmans)
+
+2013-01-22 (bug fix)[3601782] Tcl_InitStubs failure message (nijtmans)
+
+2013-01-31 (bug fix)[3599928] use XKeycodeToKeysym on old systems (cassoff)
+
+2013-02-04 (bug fix)[3603077] treeview update on tag add/remove (english)
+
+2013-02-28 (bug fix)[3599312] First Alt key event is lost (mcdonald)
+
+2013-03-11 (bug fix)[3607326] Crash [listbox .l -listvariable $array] (porter)
+
+2013-03-13 (enhancement) better build support for Debian arch (shadura)
+
+2013-03-27 (bug fix)[3608074] button, listbox, menu <<Invoke>> (nijtmans)
+
+2013-04-01 (bug fix)[3607830] Xkb runtime checks (griffin)
+
+2013-05-19 (platform support) FreeBSD updates (cerutti)
+
+2013-06-05 (bug fix)[3613759] [ttk::entry .e; .e xview end] (nijtmans)
+
+2013-06-05 (bug fix)[2100430] [ttk::entry .e; .e xview insert] (nijtmans)
+
+2013-06-28 (bug fix)[2501278] reverse ttk::scale key bindings {mcdonald)
+
+2013-07-02 (bug fix)[32afa6] corrected dirent64 check (griffin)
+
+2013-08-14 (bug fix)[069c9e] "option" value refcount crash (tim,nijtmans)
+
+2013-08-15 (bug fix)[c597acd] [$pb step] work with traces (english)
+
+2013-08-25 (bug fix)[3016181] Cocoa: [destroy $scrollbar] => crash (goddard)
+
+--- Released 8.6.1, September 19, 2013 --- http://core.tcl.tk/tk/ for details
+
+2013-10-27 (bug fix) OSX drawing lags (deily,steffen,walzer)
+
+2013-10-28 (bug fix)[3603436] png wrong component indices (nijtmans)
+
+2013-10-31 (bug fix) C++ friendly stubs struct declarations (nijtmans)
+
+2013-10-31 (bug fix)[c0cc9fd] PNG parser accept uppercase -format (nijtmans)
+
+2013-10-31 (bug fix) double free of a TkFont (nijtmans)
+
+2013-11-03 (bug fix)[1632447] support PPM maxval up to 65535 (fellows)
+
+2013-11-05 (bug fix)[426679e] OpenBSD man page rendering (nijtmans)
+
+2013-11-11 (bug fix)[f214b8a] multi-interp font teardown double free (porter)
+
+2013-11-11 (bug fix)[0aa5e85] option file \n syntax support (nijtmans)
+
+2013-11-20 (platforms) Support for Windows 8.1 (nijtmans)
+
+2014-01-23 (bug fix)[3606644] X: correct fontconfig dependence (venable)
+
+2014-01-23 (bug fix) FreeBSD build fixes (cerutti)
+
+2014-02-06 (bug fix)[3279221] [menu] event race (danckaert,kupries)
+
+2014-02-07 (bug fix)[6867cc1] creative writing in [tk fontchooser] (nijtmans)
+
+2014-02-11 (bug fix)[52ca3e7] XkbOpenDisplay macro correction (nijtmans)
+
+2014-03-16 (bug fix) Xcode 5.1 update; Retina displays (walzer)
+
+2014-03-20 (bug fix)[2f7cbd0] FreeBSD 10.0 build failure (nijtmans)
+
+2014-04-01 (bug fix)[5bcb502] @TK_LIBS@ in pkgconfig (badshah400,nijtmans)
+
+2014-05-27 (bug fix)[a80f5d7] autoscroll initiation (crogers,english)
+
+2014-07-07 (bug fix) OSX alpha channel rendering (culler,walzer)
+
+2014-07-08 (workaround)[4955f5d] Ocaml trouble with tailcall splice (nijtmans)
+
+2014-07-24 (bug fix) OSX [text] image display & scrolling (culler,walzer)
+
+2014-08-01 (bug fix) OSX font config crash (rob@bitkeeper)
+
+--- Released 8.6.2, August 27, 2014 --- http://core.tcl.tk/tk/ for details
+
+2014-08-27 (bug) Cocoa: Crash after [$button destroy] (walzer)
+
+2014-09-23 (bug) Cocoa: button and scroll display fixes (walzer)
+
+2014-09-24 (bug) Cocoa: improved drawing performance (walzer)
+
+2014-10-11 (bug)[9e487e] Phony button clicks from browsers to plugin (nijtmans)
+
+2014-10-11 (bug)[810c43] [text] elide changes advance epoch (vogel)
+
+2014-10-14 (bug)[fb35eb] fix PNG transparency appearance (walton,culler)
+
+2014-10-18 (feature)[TIP 432] Win: updated file dialogs (nadkarni)
+
+2014-10-26 Support for Windows 10 (nijtmans)
+
+2014-10-28 (bug) OSX: Improved ttk notebook tab metrics for Yosemite (walzer)
+
+2014-10-30 (bug)[3417012] [scale -digits $bigValue] segfault (vogel)
+
+2014-11-07 (bug)[3529885] [scale] handling of negative resolution (vogel)
+
+--- Released 8.6.3, November 12, 2014 --- http://core.tcl.tk/tk/ for details
+
+2014-11-14 (bug)[d43a10] shimmer-related crash in [tk_getOpenFile] (nadkarni)
+
+2014-11-23 (bug)[1c0d6e] Win build trouble with SIGDN (keene)
+
+2014-12-03 (bug)[4a0451] [tk_getOpenFile] result (nadkarni)
+
+2014-12-13 fix header files installation on OS X (houben)
+
+2015-01-02 (bug) Stop bit loss in [winfo id] on 64-bit Cocoa (porter)
+
+2015-02-06 (bug) several fixes to elided context in [text] (vogel)
+
+2015-02-06 (new feature)[TIP 433] %M binding substitution (mistachkin)
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2015-02-22 (bug)[ab6dab] corrupt dashed lines in postscript (porter)
+
+Tk Cocoa 2.0: App Store enabled (walzer,culler,desmera,owen,nyberg,reincke)
+ *** POTENTIAL INCOMPATIBILITY ***
+
+--- Released 8.6.4, March 12, 2015 --- http://core.tcl.tk/tk/ for details
+
+2015-03-10 (bug) Cocoa: premature image free crash (walzer)
+
+2015-03-15 (bug) Cocoa: wish launches in front. [focus -force] works (culler)
+
+2015-04-09 (bug)[e4ed00] [$text index "1.0 display wordstart"] crash (vogel)
+
+2015-04-09 (bug)[562118] Unicode support of "wordstart" modifier (vogel)
+
+2015-05-05 (bug)[06c3fc] PNG alpha error corrupted output file (gauthier,porter)
+
+2015-05-20 (bug)[dece63] various mem corruptions in images (mic42,porter)
+
+2015-05-24 (bug)[53f8fc] panedwindow geometry management (vogel)
+
+2015-05-26 (bug)[1641721] tk_getOpenFile symlink display doubled (nijtmans)
+
+2015-06-01 (bug)[d7bad5][2368195][3592454][1714535][1292219][3592454]
+ panedwindow fixes (vogel)
+
+2015-06-25 (bug)[805cff] Tk_ConfigureWidget() segfault (aspect,nijtmans)
+
+2015-07-13 (bug)[3f179a] Text widget crash with elided text (vogel)
+
+2015-07-16 (bug)[2886436] Stop [$text delete] acting before start index (vogel)
+
+2015-07-28 (bug)[1236306] TraverseToMenu error bound to toplevel destroy (vogel)
+
+2015-08-20 (bug)[00189c] MSVC 14: semi-static UCRT support (dower,nijtmans)
+
+2015-09-13 (bug)[cc0ba3] PNG read buffer overflow (maxjarek,porter)
+
+2015-09-29 (bug)[1501749] Crash embedded window delete bound to <Map> (vogel)
+
+2015-10-04 (license) Replace icons that lacked clear free license (cowals)
+
+2015-10-06 (bug)[46c83f] Win: tk_getOpenFile -initialdir (koend,nadkarni)
+
+2015-10-08 (new feature)[TIP 437] New panedwindow options (vogel)
+
+2015-10-09 (bug)[1669632] [text] autoseparator placement (nash,vogel)
+
+2015-10-09 (bug)[2262711] [text] RE search Unicode+elided (kaitzschu,vogel)
+
+2015-10-09 (bug)[1815161] [$text count -ypixels] needs management (vogel)
+
+2015-10-22 (bug)[1520118] Document spinbox validate expectations (vogel)
+
+2015-10-22 (bug)[1414025] $entry insertion cursor visibility (vogel)
+
+2015-10-26 (bug) PNG rendering on El Capitan (meier,walzer)
+
+2015-11-08 (bug)[2160206] menubutton panic (vogel)
+
+2015-11-08 (bug)[220854] Display trailing TAB in entry (vogel)
+
+2015-11-08 (bug)[542199] double click on lone char in entry (vogel)
+
+2015-11-08 (bug)[297442d] strict motif binding on <Control-underscore> (vogel)
+
+2015-11-08 (bug)[3601604] $listbox -takefocus (vogel)
+
+2015-11-09 (bug)[5ee8af] X, Win: 64-bit enable embedded windows (vogel)
+
+2015-11-29 (bug)[1997299] [text] tag borderwidth leak (vogel)
+
+2015-12-12 (bug)[1739605] [text see] misbehavior (danckaert)
+
+2015-12-13 (bug)[ff8a1e] Never-mapped [text] performance (danckaert)
+
+2015-12-19 (bug)[1700065] Report errors from -textvariable write trace (vogel)
+
+2015-12-19 (bug)[793909] -textvariable handle undefined namespace (vogel)
+
+2015-12-26 (bug)[2f78c7] crash with [text] and [tablelist] (vogel)
+
+2016-01-06 (bug)[1288433,3102228] <<ListboxSelect>> misfires (vogel)
+
+2016-01-08 (bug)[1510538] initial scrollbar width (vogel,nijtmans)
+
+2016-01-08 (bug)[1305128] event not received by scrollbar (vogel,nijtmans)
+
+2016-01-09 (bug)[1927212] Mousewheel/scrollbar bindings (vogel)
+
+2016-01-11 (bug)[63c354] Cocoa message boxes (culler)
+
+2016-01-12 (bug)[2049429] get more $text options from database (vogel)
+
+2016-01-22 (TIP 441) New option [listbox ... -justify] (vogel)
+
+2016-01-25 (bug) OBOE in ttk::notebook options parsing (bromley,english)
+
+2016-02-08 (enhance) [option readile] expects utf-8 file (oehlmann,nijtmans)
+
+2016-02-08 (bug) crash in [$text delete] (griffin,vogel)
+
+Tk Cocoa 2.0: More drawing internals refinements (culler,walzer)
+
+--- Released 8.6.5, February 29, 2016 --- http://core.tcl.tk/tk/ for details
+
+2016-03-07 (bug)[3137232] spinbox teardown hygiene (vogel)
+
+2016-03-07 (bug)[2981253] spinbox rapid button action (vogel)
+
+2016-03-07 (bug)[2262543] scale initialization callbacks (vogel)
+
+2016-03-07 (bug)[e9112e] incomplete [wm forget] (vogel)
+
+2016-03-11 (bug)[d95e5d] <Map> from hidden panes (vogel)
+
+2016-03-20 (TIP 443) More configuration options for text tags (vogel)
+
+2016-03-20 (bug)[487861] menu: cascade/accelerator appearance (vogel)
+
+2016-03-27 (bug)[1192095] active index from toplevel menus (vogel)
+
+2016-03-27 (bug)[18c08d] revised final newline behavior in [text] (vogel)
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2016-04-29 (bug)[fd3a4d] <<Modified>> delivery to text peers (vogel)
+
+2016-05-03 (bug)[b36218,011706] event reentrancy / widget destruction (vogel)
+
+2016-05-12 (bug)[64261b] mouse events after double click (nadmarki,nijtmans)
+
+2016-05-18 (bug)[545f10] Xft color font speed (bonfield,davies,girffin,vogel)
+
+2016-05-25 (bug)[109865] event reentrancy / widget destruction (vogel)
+
+2016-05-30 (TIP 446)[1273358] [$text edit (canundo|canredo)] (vogel)
+
+2016-05-30 (bug)[79549a] crash in mouse pointer warping (vogel)
+
+2016-06-22 (bug)[787adc] Modernize Tk_Init() (porter)
+
+2016-07-06 (bug) Aqua: excess lable padding (lanam,walzer)
+
+2016-07-08 (bug) Aqua: bitmap distortion (culler,walzer)
+
+2016-07-15 (bug) Aqua/Retina: fix alpha rendering of images (culler,walzer)
+
+2016-07-17 (bug)[c84f66] Aqua: crash: overflow in geometry calc (culler,walzer)
+
+2016-07-21 (bug)[450bb0] Aqua: memory corruption from [tk busy] (porter)
+
+--- Released 8.6.6, July 27, 2016 --- http://core.tcl.tk/tk/ for details
+
+2016-08-23 (bug)[a2abc4] Wrong warp cursor position on 2nd display (vogel)
+
+2016-08-29 (bug)[fa3229] menu-38.1 (calvo,vogel)
+
+2016-08-29 (bug)[2cf3d6] button-5.24 (vogel)
+
+2016-09-04 (bug)[1534455,2945130] Key release events get _L vs _R right. (vogel)
+
+2016-09-10 (bug)[8c4216] listbox-4.1 (vogel)
+
+2016-09-10 (bug)[eb2681] listbox-13.1 (vogel)
+
+2016-09-21 (bug)[3126428] ttk::button react to image change (thoyts)
+
+2016-10-09 (bug)[1082213] wrapped text don't start lines with whitespace (vogel)
+
+2016-10-12 (bug)[3217462] tri-state button on non-native theme (vogel)
+
+2016-10-30 (bug)[3588460] Fix file dialog -typevariable (vogel)
+
+2016-11-01 (bug)[e36963] event generate .e <diaeresis> (matthias,vogel)
+
+2016-11-05 (bug)[6aea69] grid-23 (danckaert,vogel)
+
+2016-11-18 (bug)[f60c54] combobox-3 (panza,vogel)
+
+2017-01-03 (bug)[f32502] crash drawing many dashed objects (reithofer,werner)
+
+2017-01-05 (bug)[dac92f] text-2.[89] (vogel)
+
+2017-01-07 (bug)[3df559] OSX: Negative bbox width (vogel)
+
+2017-01-07 (bug)[28a453] OSX: text widget index OBOE (vogel)
+
+2017-01-07 (bug)[c12af7] OSX: text-21.1 (vogel)
+
+2017-01-08 (bug)[7a838c] X11 ring buffer overflow (werner)
+
+2017-01-11 (bug)[d4fb4e] imgPhoto-4.75 (nijtmans)
+
+2017-01-18 (bug)[fab5fe] OSX: repair textDisp failures (vogel)
+
+2017-01-23 (bug)[89a638] OSX: textDisp-15.8 (vogel)
+
+2017-01-25 (bug)[1403ea] Limits on text line size on Windows (spjuth)
+
+2017-02-05 (bug)[ae32eb] textDisp fails in text custom config (vogel)
+
+2017-02-05 (bug)[7d967c] crash after IME restart (lanam,nijtmans)
+
+2017-02-22 (bug)[c492c9] disabled combobox arrow appearance (danckaert)
+
+2017-03-06 (bug)[6b3644] Fix -alpha for 16-bit color PNG (LemonMan)
+
+2017-03-11 (bug)[775273] artifacts on Ubuntu 16.10+ (nemethi)
+
+2017-03-26 (TIP 464) Win multimedia keys support (fassel,vogel)
+
+2017-03-29 (bug)[28a3c3] test BTree memleaks plugged (anonymous)
+
+2017-04-06 (bug)[db8c54] Stop freed mem access in warp pointer callback (porter)
+
+2017-04-07 (bugs) Fix calculation of ttk::notebook tab widths (vogel)
+
+2017-04-07 (bug)[291296] notebook tab management (decoster)
+
+2017-04-08 (bug)[f0188a] Win reject invalid hex color codes (bachmann)
+
+2017-04-10 (bug)[3f323b] variable struct size on XCode 8.3.1 (auriocus)
+
+2017-04-20 (bug)[061bf9] OSX scrollbar draw position (reincke,walzer,joye)
+
+2017-05-01 (bug) restore -initialfile for OSX file dialogs (reincke,gollwitzer)
+
+2017-05-06 (bug) OSX file dialog type filters (walzer)
+
+2017-05-10 (bug)[a5ba1c] race condition on Win clipboard cleanup (donchenko)
+
+2017-05-18 (bug)[2433781] center image on button (cramer)
+
+2017-05-19 (bug)[434d29] type mismatch with recent Xft (nijtmans,werner)
+
+2017-06-02 (bug)[bc43fd] paneconfigure get pane heights right (vogel)
+
+2017-06-21 (bug)[adc028] menu avoid unreleasable global grab (nash)
+
+2017-06-30 (bug)[92e028,c5eb90] User switch forced theme reset (lanam)
+
+2017-06-30 (bug)[62c5b7] segfault in [text] replace (werner)
+
+2017-07-03 (bug)[8afc6c] OSX crash in save/open dialogs (simpson,walzer)
+
+2017-08-02 (bug)[b601ce] Resource exhaustion processing corrupt GIF (nash)
+
+2017-08-03 (bug)[9eab54] Fix -initialdir for OSX file dialogs (gollwitzer)
+
+2017-08-08 (bug)[28d0b8] Follow ICCCM advice on X selection protocol (donchenko)
+
+2017-08-08 (bug)[4966ca] Scidb race in notebook tab selection (cramer)
+
+--- Released 8.6.7, August 9, 2017 --- http://core.tcl.tk/tk/ for details
+
+2017-08-24 (bug)[f1a3ca] Memory leak in [text] B-tree (edhume3)
+
+2017-08-24 (bug)[ee40fd] Report [console] init errors (the)
+
+2017-08-24 (bug)[3295446] Improve history visibility in [console] (goth)
+
+2017-08-24 (bug) canvas closed polylines fully honor -joinstyle (vogel)
+
+2017-08-24 (bug)[cc42cc] out of mem crash in tests imgPhoto-18.* (vogel)
+
+2017-09-16 (bug)[3406785] fix coords rounding when drawing canvas items (vogel)
+
+2017-09-24 (bug)[8277e1] linux fontchooser sync with available fonts (vogel)
+
+2017-09-24 (bug)[5239fd] Segfault copying a photo image to itself (bachmann)
+
+2017-09-24 (bug)[514ff6] canvas rotated text overlap detection (vogel)
+
+2017-09-24 (bug)[1e0db2] canvas rchars artifacts (bruchie,vogel)
+
+2017-10-07 (bug)[d9fdfa] display of Long non-wrapped lines in text (cramer)
+
+2017-10-07 (bug)[dd9667] text anchor not set (vogel)
+
+2017-10-11 (bugs) memleaks and other changes for macOS 10.13 support (culler)
+
+2017-10-11 (bug)[111de2] macOS colorspace improvement (walzer,culler)
+
+2017-10-13 (bug) macOS scrolling issues (culler)
+
+2017-10-15 (bug) clipping regions in scrolling and drawing on macOS (culler)
+
+2017-10-15 (bug) macOS redraw artifacts (culler)
+
+2017-10-22 (bug)[bb6b40] ::tk::AmpMenuArgs and 'entryconf' (vogel)
+
+2017-10-22 (bug)[55b95f] Crash [scale] with a bignum value (vogel)
+
+2017-10-28 (bug)[ce62c8] text-37.1 fails (vogel)
+
+2017-11-03 (bug)[0ef1c5] OS X - tests menu-22.[345] hang (vogel)
+
+2017-11-04 (bug)[c8c52b] repair OBOE in menu.test on macOS (vogel)
+
+2017-11-11 (feature) Implement [wm_iconphoto] on macOS (walzer)
+
+2017-11-11 (bug) display of embedded toplevels (culler)
+
+2017-11-19 (bug)[73ba07] Correct property type for MULTIPLE conversion (dpb)
+
+2017-11-20 (bug) Memory leak in tkImgPhoto.c. (werner)
+
+2017-11-21 (bug) Defeat zombie toplevels (culler)
+
+2017-11-25 (bug) macOS resposive menu bar for command line apps (culler)
+
+2017-11-25 (bug)[1c659e] support png from mac screenshots (vogel)
+
+2017-11-25 (bug)[de4af1] macOS file selector "all types" setting (culler)
+
+2017-11-26 (bug) [wm withdraw] on Window and Dock menus (walzer)
+
+2017-11-27 (feature) Drop support for macOS 10.5 (culler)
+
+2017-11-30 (bug)[164c1b] Fixes [raise] on macOS (culler)
+
+2017-11-30 (bug)[13d63d] macOS support of menu -postcommand (culler)
+
+2017-12-05 (bug) enable custom icon display on macOS (walzer)
+
+2017-12-05 (bug)[1088805,0feb63] macOS bind failures (culler)
+
+2017-12-05 (bug)[3382424] Suppress noisy messages on macOS (culler)
+
+2017-12-08 (new)[TIP 477] nmake build system reform (nadkarni)
+
+2017-12-18 (bug)[b77626] Make [tk busy -cursor] silent no-op on macOS (vogel)
+
+--- Released 8.6.8, December 22, 2017 --- http://core.tcl.tk/tk/ for details
+
+2017-12-31 (bug)[aa7679] crash using window after master destroyed (vogel)
+
+2017-12-31 (bug)[6525e1] encoding leak in tkMacOSXProcessFiles (werner)
+
+2018-01-07 (bug)[925262] New option -state for ttk::scale (vogel)
+
+2018-01-07 (bug)[fa8de7] Crash [ttk::checkbutton .x -variable {}] (werner)
+
+2018-01-16 (bug)[382712] Crash in [event generate . <KeyPress>] (werner)
+
+2018-01-19 (bug)[657c38] Crash in menu destroy with checkbutton entry (werner)
+
+2018-01-25 (bug)[de156e] Deny PRIMARY selection access in safe interps (nash)
+
+2018-01-28 (bug)[b68710] Fixes in [text] bindings (nash)
+
+2018-01-28 (bug)[e20d5c] Stop failures of textTag-18.1 (vogel)
+
+2018-02-04 (bug)[5d991b] Fortify var traces against deleted vars (vogel)
+
+2018-02-10 (bug)[1821174] Stop RenderBadPicture X error (werner)
+
+2018-02-11 (bug)[502e74] Stop X errors on untrusted connections (werner)
+
+2018-03-07 (bug)[71b131] Regression in Tk_DrawChars() (werner,cramer)
+
+2018-04-03 (bug)[59fccb] menu flaws when empty menubar clicked (vogel,mcdonald)
+
+2018-04-28 (bug)[7423f9] improved legacy support for [tk_setPalette] (bll)
+
+2018-04-30 (bug)[6d5042] enable [tk inactive] on Mac OSX (culler)
+
+2018-05-03 (bug)[75d38f] fix touchpad scroll of listbox on win notebook (vogel)
+
+2018-06-16 (bug)[de01e2] Crash in [$text replace] (vogel)
+
+2018-07-04 (bug)[6ca257] Fix [wm resizable] on Mac OSX (culler)
+
+2018-07-04 (bug)[135696] Crash in [wm transient] (culler)
+
+2018-07-04 (bug)[309b42] Improve ttk high-contrast-mode support (lemburg,vogel)
+
+2018-07-17 (bug)[1088825] fix frame-2.17,3.9,3.10 on Mac (vogel)
+
+2018-07-27 (bug)[fabed1] GIF photo support for "deferred clear code" (vogel)
+
+2018-08-08 (feature) Modern full-screen support on Mac OSX (walzer)
+
+2018-08-12 (bug)[1875c1] scrollbar on Mac OSX (walzer)
+
+2018-08-14 (bug)[1ba71a] KeyRelease events on Mac OSX(walzer)
+
+2018-09-02 (bug)[3441086] error message in layout-2 (vogel)
+
+2018-09-07 (bug)[05bd7f] vista theme for combobox (vogel)
+
+2018-09-08 (bug)[382712] crash in KeyPress event handling (vogel,werner)
+
+2018-09-08 (bug)[6fcaaa] insertion cursor visibility in ttk::entry (nemethi)
+
+2018-09-30 (bug)[822923] cascade menu indicator color (mcdonald)
+
+2018-10-06 (bug)[9658bc] borderwidth calculations on menu items (vogel)
+
+2018-10-17 (bug)[ca403f] treeview border drawing (vogel)
+
+2018-10-17 (bug)[4b555a] hang in [$text search -all] (vogel,danckaert)
+
+2018-10-30 (new platform) port to system changes in Mac OSX 10.14 (culler)
+
+2018-11-04 (bug)[6b22d4] [treeview] binding fix (ohagan)
+
+- Released 8.6.9, November 16, 2018 - http://core.tcl-lang.org/tk/ for details -
diff --git a/tk8.6/compat/stdlib.h b/tk8.6/compat/stdlib.h
new file mode 100644
index 0000000..2c64890
--- /dev/null
+++ b/tk8.6/compat/stdlib.h
@@ -0,0 +1,40 @@
+/*
+ * stdlib.h --
+ *
+ * Declares facilities exported by the "stdlib" portion of the C library.
+ * This file isn't complete in the ANSI-C sense; it only declares things
+ * that are needed by Tk. This file is needed even on many systems with
+ * their own stdlib.h (e.g. SunOS) because not all stdlib.h files declare
+ * all the procedures needed here (such as strtod).
+ *
+ * Copyright (c) 1991 The Regents of the University of California.
+ * Copyright (c) 1994-1998 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef _STDLIB
+#define _STDLIB
+
+#ifndef _TCL
+# include <tcl.h>
+#endif
+
+extern void abort(void);
+extern double atof(const char *string);
+extern int atoi(const char *string);
+extern long atol(const char *string);
+extern char * calloc(unsigned int numElements, unsigned int size);
+extern void exit(int status);
+extern int free(char *blockPtr);
+extern char * getenv(const char *name);
+extern char * malloc(unsigned int numBytes);
+extern void qsort(void *base, int n, int size, int (*compar)(
+ const void *element1, const void *element2));
+extern char * realloc(char *ptr, unsigned int numBytes);
+extern double strtod(const char *string, char **endPtr);
+extern long strtol(const char *string, char **endPtr, int base);
+extern unsigned long strtoul(const char *string, char **endPtr, int base);
+
+#endif /* _STDLIB */
diff --git a/tk8.6/compat/unistd.h b/tk8.6/compat/unistd.h
new file mode 100644
index 0000000..be966cc
--- /dev/null
+++ b/tk8.6/compat/unistd.h
@@ -0,0 +1,80 @@
+/*
+ * unistd.h --
+ *
+ * Macros, constants and prototypes for Posix conformance.
+ *
+ * Copyright 1989 Regents of the University of California Permission to use,
+ * copy, modify, and distribute this software and its documentation for any
+ * purpose and without fee is hereby granted, provided that the above
+ * copyright notice appear in all copies. The University of California makes
+ * no representations about the suitability of this software for any purpose.
+ * It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef _UNISTD
+#define _UNISTD
+
+#include <sys/types.h>
+#ifndef _TCL
+# include <tcl.h>
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/*
+ * Strict POSIX stuff goes here. Extensions go down below, in the ifndef
+ * _POSIX_SOURCE section.
+ */
+
+extern void _exit(int status);
+extern int access(const char *path, int mode);
+extern int chdir(const char *path);
+extern int chown(const char *path, uid_t owner, gid_t group);
+extern int close(int fd);
+extern int dup(int oldfd);
+extern int dup2(int oldfd, int newfd);
+extern int execl(const char *path, ...);
+extern int execle(const char *path, ...);
+extern int execlp(const char *file, ...);
+extern int execv(const char *path, char **argv);
+extern int execve(const char *path, char **argv, char **envp);
+extern int execvp(const char *file, char **argv);
+extern pid_t fork(void);
+extern char * getcwd(char *buf, size_t size);
+extern gid_t getegid(void);
+extern uid_t geteuid(void);
+extern gid_t getgid(void);
+extern int getgroups(int bufSize, int *buffer);
+extern pid_t getpid(void);
+extern uid_t getuid(void);
+extern int isatty(int fd);
+extern long lseek(int fd, long offset, int whence);
+extern int pipe(int *fildes);
+extern int read(int fd, char *buf, size_t size);
+extern int setgid(gid_t group);
+extern int setuid(uid_t user);
+extern unsigned sleep(unsigned seconds);
+extern char * ttyname(int fd);
+extern int unlink(const char *path);
+extern int write(int fd, const char *buf, size_t size);
+
+#ifndef _POSIX_SOURCE
+extern char * crypt(const char *, const char *);
+extern int fchown(int fd, uid_t owner, gid_t group);
+extern int flock(int fd, int operation);
+extern int ftruncate(int fd, unsigned long length);
+extern int ioctl(int fd, int request, ...);
+extern int readlink(const char *path, char *buf, int bufsize);
+extern int setegid(gid_t group);
+extern int seteuid(uid_t user);
+extern int setreuid(int ruid, int euid);
+extern int symlink(const char *, const char *);
+extern int ttyslot(void);
+extern int truncate(const char *path, unsigned long length);
+extern int vfork(void);
+#endif /* _POSIX_SOURCE */
+
+#endif /* _UNISTD */
+
diff --git a/tk8.6/doc/3DBorder.3 b/tk8.6/doc/3DBorder.3
new file mode 100644
index 0000000..f2f0eb8
--- /dev/null
+++ b/tk8.6/doc/3DBorder.3
@@ -0,0 +1,294 @@
+'\"
+'\" Copyright (c) 1990-1993 The Regents of the University of California.
+'\" Copyright (c) 1994-1998 Sun Microsystems, Inc.
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH Tk_Alloc3DBorderFromObj 3 8.1 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_Alloc3DBorderFromObj, Tk_Get3DBorder, Tk_Get3DBorderFromObj, Tk_Draw3DRectangle, Tk_Fill3DRectangle, Tk_Draw3DPolygon, Tk_Fill3DPolygon, Tk_3DVerticalBevel, Tk_3DHorizontalBevel, Tk_SetBackgroundFromBorder, Tk_NameOf3DBorder, Tk_3DBorderColor, Tk_3DBorderGC, Tk_Free3DBorderFromObj, Tk_Free3DBorder \- draw borders with three-dimensional appearance
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+Tk_3DBorder
+\fBTk_Alloc3DBorderFromObj(\fIinterp, tkwin, objPtr\fB)\fR
+.sp
+Tk_3DBorder
+\fBTk_Get3DBorder(\fIinterp, tkwin, colorName\fB)\fR
+.sp
+Tk_3DBorder
+\fBTk_Get3DBorderFromObj(\fItkwin, objPtr\fB)\fR
+.sp
+void
+\fBTk_Draw3DRectangle(\fItkwin, drawable, border, x, y, width, height, borderWidth, relief\fB)\fR
+.sp
+void
+\fBTk_Fill3DRectangle(\fItkwin, drawable, border, x, y, width, height, borderWidth, relief\fB)\fR
+.sp
+void
+\fBTk_Draw3DPolygon(\fItkwin, drawable, border, pointPtr, numPoints, polyBorderWidth, leftRelief\fB)\fR
+.sp
+void
+\fBTk_Fill3DPolygon(\fItkwin, drawable, border, pointPtr, numPoints, polyBorderWidth, leftRelief\fB)\fR
+.sp
+void
+\fBTk_3DVerticalBevel\fR(\fItkwin, drawable, border, x, y, width, height, leftBevel, relief\fB)\fR
+.sp
+void
+\fBTk_3DHorizontalBevel\fR(\fItkwin, drawable, border, x, y, width, height, leftIn, rightIn, topBevel, relief\fB)\fR
+.sp
+void
+\fBTk_SetBackgroundFromBorder(\fItkwin, border\fB)\fR
+.sp
+const char *
+\fBTk_NameOf3DBorder(\fIborder\fB)\fR
+.sp
+XColor *
+\fBTk_3DBorderColor(\fIborder\fB)\fR
+.sp
+GC *
+\fBTk_3DBorderGC(\fItkwin, border, which\fB)\fR
+.sp
+\fBTk_Free3DBorderFromObj(\fItkwin, objPtr\fB)\fR
+.sp
+\fBTk_Free3DBorder(\fIborder\fB)\fR
+.SH ARGUMENTS
+.AS "Tk_3DBorder" borderWidth
+.AP Tcl_Interp *interp in
+Interpreter to use for error reporting.
+.AP Tk_Window tkwin in
+Token for window (for all procedures except \fBTk_Get3DBorder\fR,
+must be the window for which the border was allocated).
+.AP Tcl_Obj *objPtr in
+Pointer to value whose value describes color corresponding to
+background (flat areas). Illuminated edges will be brighter than
+this and shadowed edges will be darker than this.
+.AP char *colorName in
+Same as \fIobjPtr\fR except value is supplied as a string rather
+than a value.
+.AP Drawable drawable in
+X token for window or pixmap; indicates where graphics are to be drawn.
+Must either be the X window for \fItkwin\fR or a pixmap with the
+same screen and depth as \fItkwin\fR.
+.AP Tk_3DBorder border in
+Token for border previously allocated in call to \fBTk_Get3DBorder\fR.
+.AP int x in
+X-coordinate of upper-left corner of rectangle describing border
+or bevel, in pixels.
+.AP int y in
+Y-coordinate of upper-left corner of rectangle describing border or
+bevel, in pixels.
+.AP int width in
+Width of rectangle describing border or bevel, in pixels.
+.AP int height in
+Height of rectangle describing border or bevel, in pixels.
+.AP int borderWidth in
+Width of border in pixels. Positive means border is inside rectangle
+given by \fIx\fR, \fIy\fR, \fIwidth\fR, \fIheight\fR, negative means
+border is outside rectangle.
+.AP int relief in
+Indicates 3-D position of interior of value relative to exterior;
+should be \fBTK_RELIEF_RAISED\fR, \fBTK_RELIEF_SUNKEN\fR, \fBTK_RELIEF_GROOVE\fR,
+\fBTK_RELIEF_SOLID\fR, or \fBTK_RELIEF_RIDGE\fR (may also be \fBTK_RELIEF_FLAT\fR
+for \fBTk_Fill3DRectangle\fR).
+.AP XPoint *pointPtr in
+Pointer to array of points describing the set of vertices in a polygon.
+The polygon need not be closed (it will be closed automatically if it
+is not).
+.AP int numPoints in
+Number of points at \fI*pointPtr\fR.
+.AP int polyBorderWidth in
+Width of border in pixels. If positive, border is drawn to left of
+trajectory given by \fIpointPtr\fR; if negative, border is drawn to
+right of trajectory. If \fIleftRelief\fR is \fBTK_RELIEF_GROOVE\fR or
+\fBTK_RELIEF_RIDGE\fR then the border is centered on the trajectory.
+.AP int leftRelief in
+Height of left side of polygon's path relative to right. \fBTK_RELIEF_RAISED\fR
+means left side should appear higher and \fBTK_RELIEF_SUNKEN\fR means right side
+should appear higher;
+\fBTK_RELIEF_GROOVE\fR and \fBTK_RELIEF_RIDGE\fR mean the obvious things.
+For \fBTk_Fill3DPolygon\fR, \fBTK_RELIEF_FLAT\fR may also be specified to
+indicate no difference in height.
+.AP int leftBevel in
+Non-zero means this bevel forms the left side of the value; zero means
+it forms the right side.
+.AP int leftIn in
+Non-zero means that the left edge of the horizontal bevel angles in,
+so that the bottom of the edge is farther to the right than
+the top.
+Zero means the edge angles out, so that the bottom is farther to the
+left than the top.
+.AP int rightIn in
+Non-zero means that the right edge of the horizontal bevel angles in,
+so that the bottom of the edge is farther to the left than the top.
+Zero means the edge angles out, so that the bottom is farther to the
+right than the top.
+.AP int topBevel in
+Non-zero means this bevel forms the top side of the value; zero means
+it forms the bottom side.
+.AP int which in
+Specifies which of the border's graphics contexts is desired.
+Must be \fBTK_3D_FLAT_GC\fR, \fBTK_3D_LIGHT_GC\fR, or \fBTK_3D_DARK_GC\fR.
+.BE
+.SH DESCRIPTION
+.PP
+These procedures provide facilities for drawing window borders in a
+way that produces a three-dimensional appearance.
+\fBTk_Alloc3DBorderFromObj\fR
+allocates colors and Pixmaps needed to draw a border in the window
+given by the \fItkwin\fR argument. The value of \fIobjPtr\fR
+is a standard Tk color name that determines the border colors.
+The color indicated by \fIobjPtr\fR will not actually be used in
+the border; it indicates the background color for the window
+(i.e. a color for flat surfaces).
+The illuminated portions of the border will appear brighter than indicated
+by \fIobjPtr\fR, and the shadowed portions of the border will appear
+darker than \fIobjPtr\fR.
+.PP
+\fBTk_Alloc3DBorderFromObj\fR returns a token that may be used in later calls
+to \fBTk_Draw3DRectangle\fR. If an error occurs in allocating information
+for the border (e.g. a bogus color name was given)
+then NULL is returned and an error message is left as the result of
+interpreter \fIinterp\fR.
+If it returns successfully, \fBTk_Alloc3DBorderFromObj\fR caches
+information about the return value in \fIobjPtr\fR, which speeds up
+future calls to \fBTk_Alloc3DBorderFromObj\fR with the same \fIobjPtr\fR
+and \fItkwin\fR.
+.PP
+\fBTk_Get3DBorder\fR is identical to \fBTk_Alloc3DBorderFromObj\fR except
+that the color is specified with a string instead of a value. This
+prevents \fBTk_Get3DBorder\fR from caching the return value, so
+\fBTk_Get3DBorder\fR is less efficient than \fBTk_Alloc3DBorderFromObj\fR.
+.PP
+\fBTk_Get3DBorderFromObj\fR returns the token for an existing border, given
+the window and color name used to create the border.
+\fBTk_Get3DBorderFromObj\fR does not actually create the border; it must
+already have been created with a previous call to
+\fBTk_Alloc3DBorderFromObj\fR or \fBTk_Get3DBorder\fR. The return
+value is cached in \fIobjPtr\fR, which speeds up
+future calls to \fBTk_Get3DBorderFromObj\fR with the same \fIobjPtr\fR
+and \fItkwin\fR.
+.PP
+Once a border structure has been created, \fBTk_Draw3DRectangle\fR may be
+invoked to draw the border.
+The \fItkwin\fR argument specifies the
+window for which the border was allocated, and \fIdrawable\fR
+specifies a window or pixmap in which the border is to be drawn.
+\fIDrawable\fR need not refer to the same window as \fItkwin\fR, but it
+must refer to a compatible
+pixmap or window: one associated with the same screen and with the
+same depth as \fItkwin\fR.
+The \fIx\fR, \fIy\fR, \fIwidth\fR, and
+\fIheight\fR arguments define the bounding box of the border region
+within \fIdrawable\fR (usually \fIx\fR and \fIy\fR are zero and
+\fIwidth\fR and \fIheight\fR are the dimensions of the window), and
+\fIborderWidth\fR specifies the number of pixels actually
+occupied by the border. The \fIrelief\fR argument indicates
+which of several three-dimensional effects is desired:
+\fBTK_RELIEF_RAISED\fR means that the interior of the rectangle should
+appear raised relative to the exterior of the rectangle, and
+\fBTK_RELIEF_SUNKEN\fR means that the interior should appear depressed.
+\fBTK_RELIEF_GROOVE\fR and \fBTK_RELIEF_RIDGE\fR mean that there should appear to be
+a groove or ridge around the exterior of the rectangle.
+.PP
+\fBTk_Fill3DRectangle\fR is somewhat like \fBTk_Draw3DRectangle\fR except
+that it first fills the rectangular area with the background color
+(one corresponding
+to the color used to create \fIborder\fR). Then it calls
+\fBTk_Draw3DRectangle\fR to draw a border just inside the outer edge of
+the rectangular area. The argument \fIrelief\fR indicates the desired
+effect (\fBTK_RELIEF_FLAT\fR means no border should be drawn; all that
+happens is to fill the rectangle with the background color).
+.PP
+The procedure \fBTk_Draw3DPolygon\fR may be used to draw more complex
+shapes with a three-dimensional appearance. The \fIpointPtr\fR and
+\fInumPoints\fR arguments define a trajectory, \fIpolyBorderWidth\fR
+indicates how wide the border should be (and on which side of the
+trajectory to draw it), and \fIleftRelief\fR indicates which side
+of the trajectory should appear raised. \fBTk_Draw3DPolygon\fR
+draws a border around the given trajectory using the colors from
+\fIborder\fR to produce a three-dimensional appearance. If the trajectory is
+non-self-intersecting, the appearance will be a raised or sunken
+polygon shape. The trajectory may be self-intersecting, although
+it's not clear how useful this is.
+.PP
+\fBTk_Fill3DPolygon\fR is to \fBTk_Draw3DPolygon\fR what
+\fBTk_Fill3DRectangle\fR is to \fBTk_Draw3DRectangle\fR: it fills
+the polygonal area with the background color from \fIborder\fR,
+then calls \fBTk_Draw3DPolygon\fR to draw a border around the
+area (unless \fIleftRelief\fR is \fBTK_RELIEF_FLAT\fR; in this case no
+border is drawn).
+.PP
+The procedures \fBTk_3DVerticalBevel\fR and \fBTk_3DHorizontalBevel\fR
+provide lower-level drawing primitives that are used by
+procedures such as \fBTk_Draw3DRectangle\fR.
+These procedures are also useful in their own right for drawing
+rectilinear border shapes.
+\fBTk_3DVerticalBevel\fR draws a vertical beveled edge, such as the
+left or right side of a rectangle, and \fBTk_3DHorizontalBevel\fR
+draws a horizontal beveled edge, such as the top or bottom of a
+rectangle.
+Each procedure takes \fIx\fR, \fIy\fR, \fIwidth\fR, and \fIheight\fR
+arguments that describe the rectangular area of the beveled edge
+(e.g., \fIwidth\fR is the border width for \fBTk_3DVerticalBevel\fR).
+The \fIleftBorder\fR and \fItopBorder\fR arguments indicate the
+position of the border relative to the
+.QW inside
+of the value, and
+\fIrelief\fR indicates the relief of the inside of the value relative
+to the outside.
+\fBTk_3DVerticalBevel\fR just draws a rectangular region.
+\fBTk_3DHorizontalBevel\fR draws a trapezoidal region to generate
+mitered corners; it should be called after \fBTk_3DVerticalBevel\fR
+(otherwise \fBTk_3DVerticalBevel\fR will overwrite the mitering in
+the corner).
+The \fIleftIn\fR and \fIrightIn\fR arguments to \fBTk_3DHorizontalBevel\fR
+describe the mitering at the corners; a value of 1 means that the bottom
+edge of the trapezoid will be shorter than the top, 0 means it will
+be longer.
+For example, to draw a rectangular border the top bevel should be
+drawn with 1 for both \fIleftIn\fR and \fIrightIn\fR, and the
+bottom bevel should be drawn with 0 for both arguments.
+.PP
+The procedure \fBTk_SetBackgroundFromBorder\fR will modify the background
+pixel and/or pixmap of \fItkwin\fR to produce a result compatible
+with \fIborder\fR. For color displays, the resulting background will
+just be the color specified when \fIborder\fR was created; for monochrome
+displays, the resulting background
+will be a light stipple pattern, in order to distinguish the background from
+the illuminated portion of the border.
+.PP
+Given a token for a border, the procedure \fBTk_NameOf3DBorder\fR
+will return the color name that was used to create the border.
+.PP
+The procedure \fBTk_3DBorderColor\fR returns the XColor structure
+that will be used for flat surfaces drawn for its \fIborder\fR
+argument by procedures like \fBTk_Fill3DRectangle\fR.
+The return value corresponds to the color name that was used to
+create the border.
+The XColor, and its associated pixel value, will remain allocated
+as long as \fIborder\fR exists.
+.PP
+The procedure \fBTk_3DBorderGC\fR returns one of the X graphics contexts
+that are used to draw the border.
+The argument \fIwhich\fR selects which one of the three possible GC's:
+\fBTK_3D_FLAT_GC\fR returns the context used for flat surfaces,
+\fBTK_3D_LIGHT_GC\fR returns the context for light shadows,
+and \fBTK_3D_DARK_GC\fR returns the context for dark shadows.
+.PP
+When a border is no longer needed, \fBTk_Free3DBorderFromObj\fR
+or \fBTk_Free3DBorder\fR should
+be called to release the resources associated with it.
+For \fBTk_Free3DBorderFromObj\fR the border to release is specified
+with the window and color name used to create the
+border; for \fBTk_Free3DBorder\fR the border to release is specified
+with the Tk_3DBorder token for the border.
+There should be exactly one call to \fBTk_Free3DBorderFromObj\fR or
+\fBTk_Free3DBorder\fR for each call to \fBTk_Alloc3DBorderFromObj\fR
+or \fBTk_Get3DBorder\fR.
+.SH KEYWORDS
+3D, background, border, color, depressed, illumination, value, polygon, raised, shadow, three-dimensional effect
diff --git a/tk8.6/doc/AddOption.3 b/tk8.6/doc/AddOption.3
new file mode 100644
index 0000000..2368f09
--- /dev/null
+++ b/tk8.6/doc/AddOption.3
@@ -0,0 +1,50 @@
+'\"
+'\" Copyright (c) 1998-2000 by Scriptics Corporation.
+'\" All rights reserved.
+'\"
+.TH Tk_AddOption 3 "" Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_AddOption \- Add an option to the option database
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+void
+\fBTk_AddOption\fR(\fItkwin, name, value, priority\fR)
+.SH ARGUMENTS
+.AP Tk_Window tkwin in
+Token for window.
+.AP "const char" *name in
+Multi-element name of option.
+.AP "const char" *value in
+Value of option.
+.AP int priority in
+Overall priority level to use for option.
+.BE
+.SH DESCRIPTION
+.PP
+This procedure is invoked to add an option to the database
+associated with \fItkwin\fR's main window. \fIName\fR
+contains the option being specified and consists of names and/or
+classes separated by asterisks or dots, in the usual X format.
+\fIValue\fR contains the text string to associate with \fIname\fR;
+this value will be returned in calls to \fBTk_GetOption\fR.
+\fIPriority\fR specifies the priority of the value; when options are
+queried using \fBTk_GetOption\fR, the value with the highest priority
+is returned. \fIPriority\fR must be between 0 and \fBTK_MAX_PRIO\fR. Some
+common priority values are:
+.IP 20
+Used for default values hard-coded into widgets.
+.IP 40
+Used for options specified in application-specific startup files.
+.IP 60
+Used for options specified in user-specific defaults files, such as
+\fB.Xdefaults\fR, resource databases loaded into the X server, or
+user-specific startup files.
+.IP 80
+Used for options specified interactively after the application starts
+running.
+.SH KEYWORDS
+class, name, option, add
diff --git a/tk8.6/doc/BindTable.3 b/tk8.6/doc/BindTable.3
new file mode 100644
index 0000000..5130bfc
--- /dev/null
+++ b/tk8.6/doc/BindTable.3
@@ -0,0 +1,153 @@
+'\"
+'\" Copyright (c) 1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_CreateBindingTable 3 4.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_CreateBindingTable, Tk_DeleteBindingTable, Tk_CreateBinding, Tk_DeleteBinding, Tk_GetBinding, Tk_GetAllBindings, Tk_DeleteAllBindings, Tk_BindEvent \- invoke scripts in response to X events
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+Tk_BindingTable
+\fBTk_CreateBindingTable(\fIinterp\fB)\fR
+.sp
+\fBTk_DeleteBindingTable(\fIbindingTable\fB)\fR
+.sp
+unsigned long
+\fBTk_CreateBinding(\fIinterp, bindingTable, object, eventString, script, append\fB)\fR
+.sp
+int
+\fBTk_DeleteBinding(\fIinterp, bindingTable, object, eventString\fB)\fR
+.sp
+const char *
+\fBTk_GetBinding(\fIinterp, bindingTable, object, eventString\fB)\fR
+.sp
+\fBTk_GetAllBindings(\fIinterp, bindingTable, object\fB)\fR
+.sp
+\fBTk_DeleteAllBindings(\fIbindingTable, object\fB)\fR
+.sp
+\fBTk_BindEvent(\fIbindingTable, eventPtr, tkwin, numObjects, objectPtr\fB)\fR
+.SH ARGUMENTS
+.AS Tk_BindingTable bindingTable
+.AP Tcl_Interp *interp in
+Interpreter to use when invoking bindings in binding table. Also
+used for returning results and errors from binding procedures.
+.AP Tk_BindingTable bindingTable in
+Token for binding table; must have been returned by some previous
+call to \fBTk_CreateBindingTable\fR.
+.AP ClientData object in
+Identifies object with which binding is associated.
+.AP "const char" *eventString in
+String describing event sequence.
+.AP "const char" *script in
+Tcl script to invoke when binding triggers.
+.AP int append in
+Non-zero means append \fIscript\fR to existing script for binding,
+if any; zero means replace existing script with new one.
+.AP XEvent *eventPtr in
+X event to match against bindings in \fIbindingTable\fR.
+.AP Tk_Window tkwin in
+Identifier for any window on the display where the event occurred.
+Used to find display-related information such as key maps.
+.AP int numObjects in
+Number of object identifiers pointed to by \fIobjectPtr\fR.
+.AP ClientData *objectPtr in
+Points to an array of object identifiers: bindings will be considered
+for each of these objects in order from first to last.
+.BE
+.SH DESCRIPTION
+.PP
+These procedures provide a general-purpose mechanism for creating
+and invoking bindings.
+Bindings are organized in terms of \fIbinding tables\fR.
+A binding table consists of a collection of bindings plus a history
+of recent events.
+Within a binding table, bindings are associated with \fIobjects\fR.
+The meaning of an object is defined by clients of the binding package.
+For example, Tk keeps uses one binding table to hold all of the bindings
+created by the \fBbind\fR command.
+For this table, objects are pointers to strings such as window names, class
+names, or other binding tags such as \fBall\fR.
+Tk also keeps a separate binding table for each canvas widget, which manages
+bindings created by the canvas's \fBbind\fR widget command; within
+this table, an object is either a pointer to the internal structure for a
+canvas item or a Tk_Uid identifying a tag.
+.PP
+The procedure \fBTk_CreateBindingTable\fR creates a new binding
+table and associates \fIinterp\fR with it (when bindings in the
+table are invoked, the scripts will be evaluated in \fIinterp\fR).
+\fBTk_CreateBindingTable\fR returns a token for the table, which
+must be used in calls to other procedures such as \fBTk_CreateBinding\fR
+or \fBTk_BindEvent\fR.
+.PP
+\fBTk_DeleteBindingTable\fR frees all of the state associated
+with a binding table.
+Once it returns the caller should not use the \fIbindingTable\fR
+token again.
+.PP
+\fBTk_CreateBinding\fR adds a new binding to an existing table.
+The \fIobject\fR argument identifies the object with which the
+binding is to be associated, and it may be any one-word value.
+Typically it is a pointer to a string or data structure.
+The \fIeventString\fR argument identifies the event or sequence
+of events for the binding; see the documentation for the
+\fBbind\fR command for a description of its format.
+\fIscript\fR is the Tcl script to be evaluated when the binding
+triggers.
+\fIappend\fR indicates what to do if there already
+exists a binding for \fIobject\fR and \fIeventString\fR: if \fIappend\fR
+is zero then \fIscript\fR replaces the old script; if \fIappend\fR
+is non-zero then the new script is appended to the old one.
+\fBTk_CreateBinding\fR returns an X event mask for all the events
+associated with the bindings.
+This information may be useful to invoke \fBXSelectInput\fR to
+select relevant events, or to disallow the use of certain events
+in bindings.
+If an error occurred while creating the binding (e.g., \fIeventString\fR
+refers to a non-existent event), then 0 is returned and an error
+message is left as the result of interpreter \fIinterp\fR.
+.PP
+\fBTk_DeleteBinding\fR removes from \fIbindingTable\fR the
+binding given by \fIobject\fR and \fIeventString\fR, if
+such a binding exists.
+\fBTk_DeleteBinding\fR always returns \fBTCL_OK\fR.
+In some cases it may reset the interpreter result to the default
+empty value.
+.PP
+\fBTk_GetBinding\fR returns a pointer to the script associated
+with \fIeventString\fR and \fIobject\fR in \fIbindingTable\fR.
+If no such binding exists then NULL is returned and an error
+message is left as the result of interpreter \fIinterp\fR.
+.PP
+\fBTk_GetAllBindings\fR returns in \fIinterp\fR's result a list
+of all the event strings for which there are bindings in
+\fIbindingTable\fR associated with \fIobject\fR.
+If there are no bindings for \fIobject\fR, the result will be an empty
+string.
+.PP
+\fBTk_DeleteAllBindings\fR deletes all of the bindings in
+\fIbindingTable\fR that are associated with \fIobject\fR.
+.PP
+\fBTk_BindEvent\fR is called to process an event.
+It makes a copy of the event in an internal history list associated
+with the binding table, then it checks for bindings that match
+the event.
+\fBTk_BindEvent\fR processes each of the objects pointed to
+by \fIobjectPtr\fR in turn.
+For each object, it finds all the bindings that match the current
+event history, selects the most specific binding using the priority
+mechanism described in the documentation for \fBbind\fR,
+and invokes the script for that binding.
+If there are no matching bindings for a particular object, then
+the object is skipped.
+\fBTk_BindEvent\fR continues through all of the objects, handling
+exceptions such as errors, \fBbreak\fR, and \fBcontinue\fR as
+described in the documentation for \fBbind\fR.
+.SH KEYWORDS
+binding, event, object, script
diff --git a/tk8.6/doc/CanvPsY.3 b/tk8.6/doc/CanvPsY.3
new file mode 100644
index 0000000..5e104ce
--- /dev/null
+++ b/tk8.6/doc/CanvPsY.3
@@ -0,0 +1,121 @@
+'\"
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_CanvasPs 3 4.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_CanvasPsY, Tk_CanvasPsBitmap, Tk_CanvasPsColor, Tk_CanvasPsFont, Tk_CanvasPsPath, Tk_CanvasPsStipple \- utility procedures for generating Postscript for canvases
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+double
+\fBTk_CanvasPsY\fR(\fIcanvas, canvasY\fR)
+.sp
+int
+\fBTk_CanvasPsBitmap\fR(\fIinterp, canvas, bitmap, x, y, width, height\fR)
+.sp
+int
+\fBTk_CanvasPsColor\fR(\fIinterp, canvas, colorPtr\fR)
+.sp
+int
+\fBTk_CanvasPsFont\fR(\fIinterp, canvas, tkFont\fR)
+.sp
+\fBTk_CanvasPsPath\fR(\fIinterp, canvas, coordPtr, numPoints\fR)
+.sp
+int
+\fBTk_CanvasPsStipple\fR(\fIinterp, canvas, bitmap\fR)
+.SH ARGUMENTS
+.AS "unsigned int" "numPoints"
+.AP Tk_Canvas canvas in
+A token that identifies a canvas widget for which Postscript is
+being generated.
+.AP double canvasY in
+Y-coordinate in the space of the canvas.
+.AP Tcl_Interp *interp in/out
+A Tcl interpreter; Postscript is appended to its result, or the
+result may be replaced with an error message.
+.AP Pixmap bitmap in
+Bitmap to use for generating Postscript.
+.AP int x in
+X-coordinate within \fIbitmap\fR of left edge of region to output.
+.AP int y in
+Y-coordinate within \fIbitmap\fR of top edge of region to output.
+.AP "int" width in
+Width of region of bitmap to output, in pixels.
+.AP "int" height in
+Height of region of bitmap to output, in pixels.
+.AP XColor *colorPtr in
+Information about color value to set in Postscript.
+.AP Tk_Font tkFont in
+Font for which Postscript is to be generated.
+.AP double *coordPtr in
+Pointer to an array of coordinates for one or more
+points specified in canvas coordinates.
+The order of values in \fIcoordPtr\fR is x1, y1, x2, y2, x3, y3,
+and so on.
+.AP int numPoints in
+Number of points at \fIcoordPtr\fR.
+.BE
+.SH DESCRIPTION
+.PP
+These procedures are called by canvas type managers to carry out
+common functions related to generating Postscript.
+Most of the procedures take a \fIcanvas\fR argument, which
+refers to a canvas widget for which Postscript is being
+generated.
+.PP
+\fBTk_CanvasPsY\fR takes as argument a y-coordinate in the space of
+a canvas and returns the value that should be used for that point
+in the Postscript currently being generated for \fIcanvas\fR.
+Y coordinates require transformation because Postscript uses an
+origin at the lower-left corner whereas X uses an origin at the
+upper-left corner.
+Canvas x coordinates can be used directly in Postscript without
+transformation.
+.PP
+\fBTk_CanvasPsBitmap\fR generates Postscript to describe a region
+of a bitmap.
+The Postscript is generated in proper image data format for Postscript,
+i.e., as data between angle brackets, one bit per pixel.
+The Postscript is appended to the result of interpreter \fIinterp\fR
+and \fBTCL_OK\fR is returned unless an error occurs, in which case
+\fBTCL_ERROR\fR is returned and the interpreter result is overwritten
+with an error message.
+.PP
+\fBTk_CanvasPsColor\fR generates Postscript to set the current color
+to correspond to its \fIcolorPtr\fR argument, taking into account any
+color map specified in the \fBpostscript\fR command.
+It appends the Postscript to the interpreter \fIinterp\fR's result and returns
+\fBTCL_OK\fR unless an error occurs, in which case \fBTCL_ERROR\fR is
+returned and the interpreter's result is overwritten with an error message.
+.PP
+\fBTk_CanvasPsFont\fR generates Postscript that sets the current font
+to match \fItkFont\fR as closely as possible.
+\fBTk_CanvasPsFont\fR takes into account any font map specified
+in the \fBpostscript\fR command, and it does
+the best it can at mapping X fonts to Postscript fonts.
+It appends the Postscript to interpreter \fIinterp\fR's result and
+returns \fBTCL_OK\fR unless an error occurs, in which case
+\fBTCL_ERROR\fR is returned and the interpreter's result is
+overwritten with an error message.
+.PP
+\fBTk_CanvasPsPath\fR generates Postscript to set the current path
+to the set of points given by \fIcoordPtr\fR and \fInumPoints\fR.
+It appends the resulting Postscript to the result of interpreter \fIinterp\fR.
+.PP
+\fBTk_CanvasPsStipple\fR generates Postscript that will fill the
+current path in stippled fashion.
+It uses \fIbitmap\fR as the stipple pattern and the current Postscript
+color; ones in the stipple bitmap are drawn in the current color, and
+zeroes are not drawn at all.
+The Postscript is appended to interpreter \fIinterp\fR's result and
+\fBTCL_OK\fR is returned, unless an error occurs, in which case
+\fBTCL_ERROR\fR is returned and the interpreter's result is
+overwritten with an error message.
+.SH KEYWORDS
+bitmap, canvas, color, font, path, Postscript, stipple
diff --git a/tk8.6/doc/CanvTkwin.3 b/tk8.6/doc/CanvTkwin.3
new file mode 100644
index 0000000..3534989
--- /dev/null
+++ b/tk8.6/doc/CanvTkwin.3
@@ -0,0 +1,158 @@
+'\"
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_CanvasTkwin 3 4.1 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_CanvasTkwin, Tk_CanvasGetCoord, Tk_CanvasDrawableCoords, Tk_CanvasSetStippleOrigin, Tk_CanvasWindowCoords, Tk_CanvasEventuallyRedraw, Tk_CanvasTagsOption \- utility procedures for canvas type managers
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+Tk_Window
+\fBTk_CanvasTkwin\fR(\fIcanvas\fR)
+.sp
+int
+\fBTk_CanvasGetCoord\fR(\fIinterp, canvas, string, doublePtr\fR)
+.sp
+\fBTk_CanvasDrawableCoords\fR(\fIcanvas, x, y, drawableXPtr, drawableYPtr\fR)
+.sp
+\fBTk_CanvasSetStippleOrigin\fR(\fIcanvas, gc\fR)
+.sp
+\fBTk_CanvasWindowCoords\fR(\fIcanvas, x, y, screenXPtr, screenYPtr\fR)
+.sp
+\fBTk_CanvasEventuallyRedraw\fR(\fIcanvas, x1, y1, x2, y2\fR)
+.sp
+Tk_OptionParseProc *\fBTk_CanvasTagsParseProc\fR;
+.sp
+Tk_OptionPrintProc *\fBTk_CanvasTagsPrintProc\fR;
+.SH ARGUMENTS
+.AS Tk_ItemType *drawableXPtr
+.AP Tk_Canvas canvas in
+A token that identifies a canvas widget.
+.AP Tcl_Interp *interp in/out
+Interpreter to use for error reporting.
+.AP "const char" *string in
+Textual description of a canvas coordinate.
+.AP double *doublePtr out
+Points to place to store a converted coordinate.
+.AP double x in
+An x coordinate in the space of the canvas.
+.AP double y in
+A y coordinate in the space of the canvas.
+.AP short *drawableXPtr out
+Pointer to a location in which to store an x coordinate in the space
+of the drawable currently being used to redisplay the canvas.
+.AP short *drawableYPtr out
+Pointer to a location in which to store a y coordinate in the space
+of the drawable currently being used to redisplay the canvas.
+.AP GC gc out
+Graphics context to modify.
+.AP short *screenXPtr out
+Points to a location in which to store the screen coordinate in the
+canvas window that corresponds to \fIx\fR.
+.AP short *screenYPtr out
+Points to a location in which to store the screen coordinate in the
+canvas window that corresponds to \fIy\fR.
+.AP int x1 in
+Left edge of the region that needs redisplay. Only pixels at or to
+the right of this coordinate need to be redisplayed.
+.AP int y1 in
+Top edge of the region that needs redisplay. Only pixels at or below
+this coordinate need to be redisplayed.
+.AP int x2 in
+Right edge of the region that needs redisplay. Only pixels to
+the left of this coordinate need to be redisplayed.
+.AP int y2 in
+Bottom edge of the region that needs redisplay. Only pixels above
+this coordinate need to be redisplayed.
+.BE
+.SH DESCRIPTION
+.PP
+These procedures are called by canvas type managers to perform various
+utility functions.
+.PP
+\fBTk_CanvasTkwin\fR returns the Tk_Window associated with a particular
+canvas.
+.PP
+\fBTk_CanvasGetCoord\fR translates a string specification of a
+coordinate (such as \fB2p\fR or \fB1.6c\fR) into a double-precision
+canvas coordinate.
+If \fIstring\fR is a valid coordinate description then \fBTk_CanvasGetCoord\fR
+stores the corresponding canvas coordinate at *\fIdoublePtr\fR
+and returns \fBTCL_OK\fR.
+Otherwise it stores an error message in the interpreter result and
+returns \fBTCL_ERROR\fR.
+.PP
+\fBTk_CanvasDrawableCoords\fR is called by type managers during
+redisplay to compute where to draw things.
+Given \fIx\fR and \fIy\fR coordinates in the space of the
+canvas, \fBTk_CanvasDrawableCoords\fR computes the corresponding
+pixel in the drawable that is currently being used for redisplay;
+it returns those coordinates in *\fIdrawableXPtr\fR and *\fIdrawableYPtr\fR.
+This procedure should not be invoked except during redisplay.
+.PP
+\fBTk_CanvasSetStippleOrigin\fR is also used during redisplay.
+It sets the stipple origin in \fIgc\fR so that stipples drawn
+with \fIgc\fR in the current offscreen pixmap will line up
+with stipples drawn with origin (0,0) in the canvas's actual
+window.
+\fBTk_CanvasSetStippleOrigin\fR is needed in order to guarantee
+that stipple patterns line up properly when the canvas is
+redisplayed in small pieces.
+Redisplays are carried out in double-buffered fashion where a
+piece of the canvas is redrawn in an offscreen pixmap and then
+copied back onto the screen.
+In this approach the stipple origins in graphics contexts need to
+be adjusted during each redisplay to compensate for the position
+of the off-screen pixmap relative to the window.
+If an item is being drawn with stipples, its type manager typically
+calls \fBTk_CanvasSetStippleOrigin\fR just before using \fIgc\fR
+to draw something; after it is finished drawing, the type manager
+calls \fBXSetTSOrigin\fR to restore the origin in \fIgc\fR back to (0,0)
+(the restore is needed because graphics contexts are shared, so
+they cannot be modified permanently).
+.PP
+\fBTk_CanvasWindowCoords\fR is similar to \fBTk_CanvasDrawableCoords\fR
+except that it returns coordinates in the canvas's window on the
+screen, instead of coordinates in an off-screen pixmap.
+.PP
+\fBTk_CanvasEventuallyRedraw\fR may be invoked by a type manager
+to inform Tk that a portion of a canvas needs to be redrawn.
+The \fIx1\fR, \fIy1\fR, \fIx2\fR, and \fIy2\fR arguments
+specify the region that needs to be redrawn, in canvas coordinates.
+Type managers rarely need to invoke \fBTk_CanvasEventuallyRedraw\fR,
+since Tk can normally figure out when an item has changed and make
+the redisplay request on its behalf (this happens, for example
+whenever Tk calls a \fIconfigureProc\fR or \fIscaleProc\fR).
+The only time that a type manager needs to call
+\fBTk_CanvasEventuallyRedraw\fR is if an item has changed on its own
+without being invoked through one of the procedures in its Tk_ItemType;
+this could happen, for example, in an image item if the image is
+modified using image commands.
+.PP
+\fBTk_CanvasTagsParseProc\fR and \fBTk_CanvasTagsPrintProc\fR are
+procedures that handle the \fB\-tags\fR option for canvas items.
+The code of a canvas type manager will not call these procedures
+directly, but will use their addresses to create a \fBTk_CustomOption\fR
+structure for the \fB\-tags\fR option. The code typically looks
+like this:
+.PP
+.CS
+static const Tk_CustomOption tagsOption = {Tk_CanvasTagsParseProc,
+ Tk_CanvasTagsPrintProc, NULL
+};
+
+static const Tk_ConfigSpec configSpecs[] = {
+ ...
+ {TK_CONFIG_CUSTOM, "\-tags", NULL, NULL,
+ NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
+ ...
+};
+.CE
+.SH KEYWORDS
+canvas, focus, item type, redisplay, selection, type manager
diff --git a/tk8.6/doc/CanvTxtInfo.3 b/tk8.6/doc/CanvTxtInfo.3
new file mode 100644
index 0000000..92a2bc3
--- /dev/null
+++ b/tk8.6/doc/CanvTxtInfo.3
@@ -0,0 +1,100 @@
+'\"
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_CanvasTextInfo 3 4.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_CanvasTextInfo \- additional information for managing text items in canvases
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+Tk_CanvasTextInfo *
+\fBTk_CanvasGetTextInfo\fR(\fIcanvas\fR)
+.SH ARGUMENTS
+.AS Tk_Canvas canvas
+.AP Tk_Canvas canvas in
+A token that identifies a particular canvas widget.
+.BE
+.SH DESCRIPTION
+.PP
+Textual canvas items are somewhat more complicated to manage than
+other items, due to things like the selection and the input focus.
+\fBTk_CanvasGetTextInfo\fR may be invoked by a type manager
+to obtain additional information needed for items that display text.
+The return value from \fBTk_CanvasGetTextInfo\fR is a pointer to
+a structure that is shared between Tk and all the items that display
+text.
+The structure has the following form:
+.CS
+typedef struct Tk_CanvasTextInfo {
+ Tk_3DBorder \fIselBorder\fR;
+ int \fIselBorderWidth\fR;
+ XColor *\fIselFgColorPtr\fR;
+ Tk_Item *\fIselItemPtr\fR;
+ int \fIselectFirst\fR;
+ int \fIselectLast\fR;
+ Tk_Item *\fIanchorItemPtr\fR;
+ int \fIselectAnchor\fR;
+ Tk_3DBorder \fIinsertBorder\fR;
+ int \fIinsertWidth\fR;
+ int \fIinsertBorderWidth\fR;
+ Tk_Item *\fIfocusItemPtr\fR;
+ int \fIgotFocus\fR;
+ int \fIcursorOn\fR;
+} \fBTk_CanvasTextInfo\fR;
+.CE
+The \fBselBorder\fR field identifies a Tk_3DBorder that should be
+used for drawing the background under selected text.
+\fIselBorderWidth\fR gives the width of the raised border around
+selected text, in pixels.
+\fIselFgColorPtr\fR points to an XColor that describes the foreground
+color to be used when drawing selected text.
+\fIselItemPtr\fR points to the item that is currently selected, or
+NULL if there is no item selected or if the canvas does not have the
+selection.
+\fIselectFirst\fR and \fIselectLast\fR give the indices of the first
+and last selected characters in \fIselItemPtr\fR, as returned by the
+\fIindexProc\fR for that item.
+\fIanchorItemPtr\fR points to the item that currently has the selection
+anchor; this is not necessarily the same as \fIselItemPtr\fR.
+\fIselectAnchor\fR is an index that identifies the anchor position
+within \fIanchorItemPtr\fR.
+\fIinsertBorder\fR contains a Tk_3DBorder to use when drawing the
+insertion cursor; \fIinsertWidth\fR gives the total width of the
+insertion cursor in pixels, and \fIinsertBorderWidth\fR gives the
+width of the raised border around the insertion cursor.
+\fIfocusItemPtr\fR identifies the item that currently has the input
+focus, or NULL if there is no such item.
+\fIgotFocus\fR is 1 if the canvas widget has the input focus and
+0 otherwise.
+\fIcursorOn\fR is 1 if the insertion cursor should be drawn in
+\fIfocusItemPtr\fR and 0 if it should not be drawn; this field
+is toggled on and off by Tk to make the cursor blink.
+.PP
+The structure returned by \fBTk_CanvasGetTextInfo\fR
+is shared between Tk and the type managers; typically the type manager
+calls \fBTk_CanvasGetTextInfo\fR once when an item is created and
+then saves the pointer in the item's record.
+Tk will update information in the Tk_CanvasTextInfo; for example,
+a \fBconfigure\fR widget command might change the \fIselBorder\fR
+field, or a \fBselect\fR widget command might change the \fIselectFirst\fR
+field, or Tk might change \fIcursorOn\fR in order to make the insertion
+cursor flash on and off during successive redisplays.
+.PP
+Type managers should treat all of the fields of the Tk_CanvasTextInfo
+structure as read-only, except for \fIselItemPtr\fR, \fIselectFirst\fR,
+\fIselectLast\fR, and \fIselectAnchor\fR.
+Type managers may change \fIselectFirst\fR, \fIselectLast\fR, and
+\fIselectAnchor\fR to adjust for insertions and deletions in the
+item (but only if the item is the current owner of the selection or
+anchor, as determined by \fIselItemPtr\fR or \fIanchorItemPtr\fR).
+If all of the selected text in the item is deleted, the item should
+set \fIselItemPtr\fR to NULL to indicate that there is no longer a
+selection.
+.SH KEYWORDS
+canvas, focus, insertion cursor, selection, selection anchor, text
diff --git a/tk8.6/doc/Clipboard.3 b/tk8.6/doc/Clipboard.3
new file mode 100644
index 0000000..3087777
--- /dev/null
+++ b/tk8.6/doc/Clipboard.3
@@ -0,0 +1,77 @@
+'\"
+'\" Copyright (c) 1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_ClipboardClear 3 4.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_ClipboardClear, Tk_ClipboardAppend \- Manage the clipboard
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+int
+\fBTk_ClipboardClear\fR(\fIinterp, tkwin\fR)
+.sp
+int
+\fBTk_ClipboardAppend\fR(\fIinterp, tkwin, target, format, buffer\fR)
+.SH ARGUMENTS
+.AS Tk_ClipboardClear tkwin
+.AP Tcl_Interp *interp in
+Interpreter to use for reporting errors.
+.AP Tk_Window tkwin in
+Window that determines which display's clipboard to manipulate.
+.AP Atom target in
+Conversion type for this clipboard item; has same meaning as
+\fItarget\fR argument to \fBTk_CreateSelHandler\fR.
+.AP Atom format in
+Representation to use when data is retrieved; has same meaning as
+\fIformat\fR argument to \fBTk_CreateSelHandler\fR.
+.AP "const char" *buffer in
+Null terminated string containing the data to be appended to the clipboard.
+.BE
+.SH DESCRIPTION
+.PP
+These two procedures manage the clipboard for Tk.
+The clipboard is typically managed by calling \fBTk_ClipboardClear\fR
+once, then calling \fBTk_ClipboardAppend\fR to add data for any
+number of targets.
+.PP
+\fBTk_ClipboardClear\fR claims the CLIPBOARD selection and frees any
+data items previously stored on the clipboard in this application.
+It normally returns \fBTCL_OK\fR, but if an error occurs it returns
+\fBTCL_ERROR\fR and leaves an error message in interpreter
+\fIinterp\fR's result.
+\fBTk_ClipboardClear\fR must be called before a sequence of
+\fBTk_ClipboardAppend\fR calls can be issued.
+.PP
+\fBTk_ClipboardAppend\fR appends a buffer of data to the clipboard.
+The first buffer for a given \fItarget\fR determines the \fIformat\fR
+for that \fItarget\fR.
+Any successive appends for that \fItarget\fR must have
+the same format or an error will be returned.
+\fBTk_ClipboardAppend\fR returns \fBTCL_OK\fR if the buffer is
+successfully copied onto the clipboard. If the clipboard is not
+currently owned by the application, either
+because \fBTk_ClipboardClear\fR has not been called or because
+ownership of the clipboard has changed since the last call to
+\fBTk_ClipboardClear\fR,
+\fBTk_ClipboardAppend\fR returns \fBTCL_ERROR\fR and leaves an error
+message in the result of interpreter \fIinterp\fR.
+.PP
+In order to guarantee atomicity, no event handling should occur
+between \fBTk_ClipboardClear\fR and the following
+\fBTk_ClipboardAppend\fR calls (otherwise someone could retrieve
+a partially completed clipboard or claim ownership away from
+this application).
+.PP
+\fBTk_ClipboardClear\fR may invoke callbacks, including arbitrary
+Tcl scripts, as a result of losing the CLIPBOARD selection, so
+any calling function should take care to be re-entrant at the point
+\fBTk_ClipboardClear\fR is invoked.
+.SH KEYWORDS
+append, clipboard, clear, format, type
diff --git a/tk8.6/doc/ClrSelect.3 b/tk8.6/doc/ClrSelect.3
new file mode 100644
index 0000000..c56f63c
--- /dev/null
+++ b/tk8.6/doc/ClrSelect.3
@@ -0,0 +1,38 @@
+'\"
+'\" Copyright (c) 1992-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_ClearSelection 3 4.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_ClearSelection \- Deselect a selection
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+\fBTk_ClearSelection\fR(\fItkwin, selection\fR)
+.SH ARGUMENTS
+.AS Tk_Window tkwin
+.AP Tk_Window tkwin in
+The selection will be cleared from the display containing this
+window.
+.AP Atom selection in
+The name of selection to be cleared.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_ClearSelection\fR cancels the selection specified by the atom
+\fIselection\fR for the display containing \fItkwin\fR.
+The selection need not be in \fItkwin\fR itself or even in
+\fItkwin\fR's application.
+If there is a window anywhere on \fItkwin\fR's display that
+owns \fIselection\fR, the window will be notified and the
+selection will be cleared.
+If there is no owner for \fIselection\fR on the display, then the
+procedure has no effect.
+.SH KEYWORDS
+clear, selection
diff --git a/tk8.6/doc/ConfigWidg.3 b/tk8.6/doc/ConfigWidg.3
new file mode 100644
index 0000000..92be073
--- /dev/null
+++ b/tk8.6/doc/ConfigWidg.3
@@ -0,0 +1,631 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_ConfigureWidget 3 4.1 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_ConfigureWidget, Tk_ConfigureInfo, Tk_ConfigureValue, Tk_FreeOptions \- process configuration options for widgets
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+int
+\fBTk_ConfigureWidget(\fIinterp, tkwin, specs, argc, argv, widgRec, flags\fB)\fR
+.sp
+int
+\fBTk_ConfigureInfo(\fIinterp, tkwin, specs, widgRec, argvName, flags\fB)\fR
+.sp
+int
+\fBTk_ConfigureValue(\fIinterp, tkwin, specs, widgRec, argvName, flags\fB)\fR
+.sp
+\fBTk_FreeOptions(\fIspecs, widgRec, display, flags\fB)\fR
+.SH ARGUMENTS
+.AS char *widgRec in/out
+.AP Tcl_Interp *interp in
+Interpreter to use for returning error messages.
+.AP Tk_Window tkwin in
+Window used to represent widget (needed to set up X resources).
+.AP "const Tk_ConfigSpec" *specs in
+Pointer to table specifying legal configuration options for this
+widget.
+.AP int argc in
+Number of arguments in \fIargv\fR.
+.AP "const char" **argv in
+Command-line options for configuring widget.
+.AP char *widgRec in/out
+Points to widget record structure. Fields in this structure get
+modified by \fBTk_ConfigureWidget\fR to hold configuration information.
+.AP int flags in
+If non-zero, then it specifies an OR-ed combination of flags that
+control the processing of configuration information.
+\fBTK_CONFIG_ARGV_ONLY\fR causes the option database and defaults to be
+ignored, and flag bits \fBTK_CONFIG_USER_BIT\fR and higher are used to
+selectively disable entries in \fIspecs\fR.
+.AP "type name" type in
+The name of the type of a widget record.
+.AP "field name" field in
+The name of a field in records of type \fItype\fR.
+.AP "const char" *argvName in
+The name used on Tcl command lines to refer to a particular option
+(e.g. when creating a widget or invoking the \fBconfigure\fR widget
+command). If non-NULL, then information is returned only for this
+option. If NULL, then information is returned for all available
+options.
+.AP Display *display in
+Display containing widget whose record is being freed; needed in
+order to free up resources.
+.BE
+.SH DESCRIPTION
+.PP
+Note: \fBTk_ConfigureWidget\fR should be replaced with the new
+\fBTcl_Obj\fR based API \fBTk_SetOptions\fR. The old interface is
+retained for backward compatibility.
+.PP
+\fBTk_ConfigureWidget\fR is called to configure various aspects of a
+widget, such as colors, fonts, border width, etc.
+It is intended as a convenience procedure to reduce the amount
+of code that must be written in individual widget managers to
+handle configuration information.
+It is typically
+invoked when widgets are created, and again when the \fBconfigure\fR
+command is invoked for a widget.
+Although intended primarily for widgets, \fBTk_ConfigureWidget\fR
+can be used in other situations where \fIargc-argv\fR information
+is to be used to fill in a record structure, such as configuring
+graphical elements for a canvas widget or entries of a menu.
+.PP
+\fBTk_ConfigureWidget\fR processes
+a table specifying the configuration options that are supported
+(\fIspecs\fR) and a collection of command-line arguments (\fIargc\fR and
+\fIargv\fR) to fill in fields of a record (\fIwidgRec\fR).
+It uses the option database and defaults specified in \fIspecs\fR
+to fill in fields of \fIwidgRec\fR that are not specified in \fIargv\fR.
+\fBTk_ConfigureWidget\fR normally returns the value \fBTCL_OK\fR; in this
+case it does not modify \fIinterp\fR.
+If an error
+occurs then \fBTCL_ERROR\fR is returned and \fBTk_ConfigureWidget\fR will
+leave an error message in interpreter \fIinterp\fR's result in the standard Tcl
+fashion.
+In the event of an error return, some of the fields of \fIwidgRec\fR
+could already have been set, if configuration information for them
+was successfully processed before the error occurred.
+The other fields will be set to reasonable initial values so that
+\fBTk_FreeOptions\fR can be called for cleanup.
+.PP
+The \fIspecs\fR array specifies the kinds of configuration options
+expected by the widget. Each of its entries specifies one configuration
+option and has the following structure:
+.CS
+typedef struct {
+ int \fItype\fR;
+ const char *\fIargvName\fR;
+ const char *\fIdbName\fR;
+ const char *\fIdbClass\fR;
+ const char *\fIdefValue\fR;
+ int \fIoffset\fR;
+ int \fIspecFlags\fR;
+ const Tk_CustomOption *\fIcustomPtr\fR;
+} \fBTk_ConfigSpec\fR;
+.CE
+The \fItype\fR field indicates what type of configuration option this is
+(e.g. \fBTK_CONFIG_COLOR\fR for a color value, or \fBTK_CONFIG_INT\fR for
+an integer value). The \fItype\fR field indicates how to use the
+value of the option (more on this below).
+The \fIargvName\fR field is a string such as
+.QW \-font
+or
+.QW \-bg ,
+which is compared with the values in \fIargv\fR (if \fIargvName\fR is
+NULL it means this is a grouped entry; see \fBGROUPED ENTRIES\fR below). The
+\fIdbName\fR and \fIdbClass\fR fields are used to look up a value
+for this option in the option database. The \fIdefValue\fR field
+specifies a default value for this configuration option if no
+value is specified in either \fIargv\fR or the option database.
+\fIOffset\fR indicates where in \fIwidgRec\fR to store information
+about this option, and \fIspecFlags\fR contains additional information
+to control the processing of this configuration option (see FLAGS
+below).
+The last field, \fIcustomPtr\fR, is only used if \fItype\fR is
+\fBTK_CONFIG_CUSTOM\fR; see CUSTOM OPTION TYPES below.
+.PP
+\fBTk_ConfigureWidget\fR first processes \fIargv\fR to see which
+(if any) configuration options are specified there. \fIArgv\fR
+must contain an even number of fields; the first of each pair
+of fields must match the \fIargvName\fR of some entry in \fIspecs\fR
+(unique abbreviations are acceptable),
+and the second field of the pair contains the value for that
+configuration option. If there are entries in \fIspec\fR for which
+there were no matching entries in \fIargv\fR,
+\fBTk_ConfigureWidget\fR uses the \fIdbName\fR and \fIdbClass\fR
+fields of the \fIspecs\fR entry to probe the option database; if
+a value is found, then it is used as the value for the option.
+Finally, if no entry is found in the option database, the
+\fIdefValue\fR field of the \fIspecs\fR entry is used as the
+value for the configuration option. If the \fIdefValue\fR is
+NULL, or if the \fBTK_CONFIG_DONT_SET_DEFAULT\fR bit is set in
+\fIflags\fR, then there is no default value and this \fIspecs\fR entry
+will be ignored if no value is specified in \fIargv\fR or the
+option database.
+.PP
+Once a string value has been determined for a configuration option,
+\fBTk_ConfigureWidget\fR translates the string value into a more useful
+form, such as a color if \fItype\fR is \fBTK_CONFIG_COLOR\fR or an integer
+if \fItype\fR is \fBTK_CONFIG_INT\fR. This value is then stored in the
+record pointed to by \fIwidgRec\fR. This record is assumed to
+contain information relevant to the manager of the widget; its exact
+type is unknown to \fBTk_ConfigureWidget\fR. The \fIoffset\fR field
+of each \fIspecs\fR entry indicates where in \fIwidgRec\fR to store
+the information about this configuration option. You should use the
+\fBTk_Offset\fR macro to generate \fIoffset\fR values (see below for
+a description of \fBTk_Offset\fR). The location indicated by
+\fIwidgRec\fR and \fIoffset\fR will be referred to as the
+.QW target
+in the descriptions below.
+.PP
+The \fItype\fR field of each entry in \fIspecs\fR determines what
+to do with the string value of that configuration option. The
+legal values for \fItype\fR, and the corresponding actions, are:
+.TP
+\fBTK_CONFIG_ACTIVE_CURSOR\fR
+The value
+must be an ASCII string identifying a cursor in a form
+suitable for passing to \fBTk_GetCursor\fR.
+The value is converted to a \fBTk_Cursor\fR by calling
+\fBTk_GetCursor\fR and the result is stored in the target.
+In addition, the resulting cursor is made the active cursor
+for \fItkwin\fR by calling \fBXDefineCursor\fR.
+If \fBTK_CONFIG_NULL_OK\fR is specified in \fIspecFlags\fR then the value
+may be an empty string, in which case the target and \fItkwin\fR's
+active cursor will be set to \fBNone\fR.
+If the previous value of the target
+was not \fBNone\fR, then it is freed by passing it to \fBTk_FreeCursor\fR.
+.TP
+\fBTK_CONFIG_ANCHOR\fR
+The value must be an ASCII string identifying an anchor point in one of the ways
+accepted by \fBTk_GetAnchor\fR.
+The string is converted to a \fBTk_Anchor\fR by calling
+\fBTk_GetAnchor\fR and the result is stored in the target.
+.TP
+\fBTK_CONFIG_BITMAP\fR
+The value must be an ASCII string identifying a bitmap in a form
+suitable for passing to \fBTk_GetBitmap\fR. The value is converted
+to a \fBPixmap\fR by calling \fBTk_GetBitmap\fR and the result
+is stored in the target.
+If \fBTK_CONFIG_NULL_OK\fR is specified in \fIspecFlags\fR then the value
+may be an empty string, in which case the target is set to \fBNone\fR.
+If the previous value of the target
+was not \fBNone\fR, then it is freed by passing it to \fBTk_FreeBitmap\fR.
+.TP
+\fBTK_CONFIG_BOOLEAN\fR
+The value must be an ASCII string specifying a boolean value. Any
+of the values
+.QW true ,
+.QW yes ,
+.QW on ,
+or
+.QW 1 ,
+or an abbreviation of one of these values, means true;
+any of the values
+.QW false ,
+.QW no ,
+.QW off ,
+or
+.QW 0 ,
+or an abbreviation of one of these values, means false.
+The target is expected to be an integer; for true values it will
+be set to 1 and for false values it will be set to 0.
+.TP
+\fBTK_CONFIG_BORDER\fR
+The value must be an ASCII string identifying a border color in a form
+suitable for passing to \fBTk_Get3DBorder\fR. The value is converted
+to a (\fBTk_3DBorder *\fR) by calling \fBTk_Get3DBorder\fR and the result
+is stored in the target.
+If \fBTK_CONFIG_NULL_OK\fR is specified in \fIspecFlags\fR then the value
+may be an empty string, in which case the target will be set to NULL.
+If the previous value of the target
+was not NULL, then it is freed by passing it to \fBTk_Free3DBorder\fR.
+.TP
+\fBTK_CONFIG_CAP_STYLE\fR
+The value must be
+an ASCII string identifying a cap style in one of the ways
+accepted by \fBTk_GetCapStyle\fR.
+The string is converted to an integer value corresponding
+to the cap style by calling
+\fBTk_GetCapStyle\fR and the result is stored in the target.
+.TP
+\fBTK_CONFIG_COLOR\fR
+The value must be an ASCII string identifying a color in a form
+suitable for passing to \fBTk_GetColor\fR. The value is converted
+to an (\fBXColor *\fR) by calling \fBTk_GetColor\fR and the result
+is stored in the target.
+If \fBTK_CONFIG_NULL_OK\fR is specified in \fIspecFlags\fR then the value
+may be an empty string, in which case the target will be set to \fBNone\fR.
+If the previous value of the target
+was not NULL, then it is freed by passing it to \fBTk_FreeColor\fR.
+.TP
+\fBTK_CONFIG_CURSOR\fR
+This option is identical to \fBTK_CONFIG_ACTIVE_CURSOR\fR except
+that the new cursor is not made the active one for \fItkwin\fR.
+.TP
+\fBTK_CONFIG_CUSTOM\fR
+This option allows applications to define new option types.
+The \fIcustomPtr\fR field of the entry points to a structure
+defining the new option type.
+See the section \fBCUSTOM OPTION TYPES\fR below for details.
+.TP
+\fBTK_CONFIG_DOUBLE\fR
+The value must be an ASCII floating-point number in
+the format accepted by \fBstrtol\fR. The string is converted
+to a \fBdouble\fR value, and the value is stored in the
+target.
+.TP
+\fBTK_CONFIG_END\fR
+Marks the end of the table. The last entry in \fIspecs\fR
+must have this type; all of its other fields are ignored and it
+will never match any arguments.
+.TP
+\fBTK_CONFIG_FONT\fR
+The value must be an ASCII string identifying a font in a form
+suitable for passing to \fBTk_GetFont\fR. The value is converted
+to a \fBTk_Font\fR by calling \fBTk_GetFont\fR and the result
+is stored in the target.
+If \fBTK_CONFIG_NULL_OK\fR is specified in \fIspecFlags\fR then the value
+may be an empty string, in which case the target will be set to NULL.
+If the previous value of the target
+was not NULL, then it is freed by passing it to \fBTk_FreeFont\fR.
+.TP
+\fBTK_CONFIG_INT\fR
+The value must be an ASCII integer string
+in the format accepted by \fBstrtol\fR (e.g.
+.QW 0
+and
+.QW 0x
+prefixes may be used to specify octal or hexadecimal
+numbers, respectively). The string is converted to an integer
+value and the integer is stored in the target.
+.TP
+\fBTK_CONFIG_JOIN_STYLE\fR
+The value must be
+an ASCII string identifying a join style in one of the ways
+accepted by \fBTk_GetJoinStyle\fR.
+The string is converted to an integer value corresponding
+to the join style by calling
+\fBTk_GetJoinStyle\fR and the result is stored in the target.
+.TP
+\fBTK_CONFIG_JUSTIFY\fR
+The value must be
+an ASCII string identifying a justification method in one of the
+ways accepted by \fBTk_GetJustify\fR.
+The string is converted to a \fBTk_Justify\fR by calling
+\fBTk_GetJustify\fR and the result is stored in the target.
+.TP
+\fBTK_CONFIG_MM\fR
+The value must specify a screen distance in one of the forms acceptable
+to \fBTk_GetScreenMM\fR.
+The string is converted to double-precision floating-point distance
+in millimeters and the value is stored in the target.
+.TP
+\fBTK_CONFIG_PIXELS\fR
+The value must specify screen units in one of the forms acceptable
+to \fBTk_GetPixels\fR.
+The string is converted to an integer distance in pixels and the
+value is stored in the target.
+.TP
+\fBTK_CONFIG_RELIEF\fR
+The value must be an ASCII string identifying a relief in a form
+suitable for passing to \fBTk_GetRelief\fR. The value is converted
+to an integer relief value by calling \fBTk_GetRelief\fR and the result
+is stored in the target.
+.TP
+\fBTK_CONFIG_STRING\fR
+A copy
+of the value is made by allocating memory space with
+\fBTcl_Alloc\fR and copying the value into the dynamically-allocated
+space. A pointer to the new string is stored in the target.
+If \fBTK_CONFIG_NULL_OK\fR is specified in \fIspecFlags\fR then the value
+may be an empty string, in which case the target will be set to NULL.
+If the previous value of the target was not NULL, then it is
+freed by passing it to \fBTcl_Free\fR.
+.TP
+\fBTK_CONFIG_SYNONYM\fR
+This \fItype\fR value identifies special entries in \fIspecs\fR that
+are synonyms for other entries. If an \fIargv\fR value matches the
+\fIargvName\fR of a \fBTK_CONFIG_SYNONYM\fR entry, the entry is not used
+directly. Instead, \fBTk_ConfigureWidget\fR searches \fIspecs\fR
+for another entry whose \fIargvName\fR is the same as the \fIdbName\fR
+field in the \fBTK_CONFIG_SYNONYM\fR entry; this new entry is used just
+as if its \fIargvName\fR had matched the \fIargv\fR value. The
+synonym mechanism allows multiple \fIargv\fR values to be used for
+a single configuration option, such as
+.QW \-background
+and
+.QW \-bg .
+.TP
+\fBTK_CONFIG_UID\fR
+The value is translated to a \fBTk_Uid\fR
+(by passing it to \fBTk_GetUid\fR). The resulting value
+is stored in the target.
+If \fBTK_CONFIG_NULL_OK\fR is specified in \fIspecFlags\fR and the value
+is an empty string then the target will be set to NULL.
+.TP
+\fBTK_CONFIG_WINDOW\fR
+The value must be a window path name. It is translated to a
+\fBTk_Window\fR token and the token is stored in the target.
+.SH "GROUPED ENTRIES"
+.PP
+In some cases it is useful to generate multiple resources from
+a single configuration value. For example, a color name might
+be used both to generate the background color for a widget (using
+\fBTK_CONFIG_COLOR\fR) and to generate a 3-D border to draw around the
+widget (using \fBTK_CONFIG_BORDER\fR). In cases like this it is possible
+to specify that several consecutive entries in \fIspecs\fR are to
+be treated as a group. The first entry is used to determine a value
+(using its \fIargvName\fR, \fIdbName\fR,
+\fIdbClass\fR, and \fIdefValue\fR fields). The value will be processed
+several times (one for each entry in the group), generating multiple
+different resources and modifying multiple targets within \fIwidgRec\fR.
+Each of the entries after the first must have a NULL value in its
+\fIargvName\fR field; this indicates that the entry is to be grouped
+with the entry that precedes it. Only the \fItype\fR and \fIoffset\fR
+fields are used from these follow-on entries.
+.SH "FLAGS"
+.PP
+The \fIflags\fR argument passed to \fBTk_ConfigureWidget\fR is used
+in conjunction with the \fIspecFlags\fR fields in the entries of \fIspecs\fR
+to provide additional control over the processing of configuration
+options. These values are used in three different ways as
+described below.
+.PP
+First, if the \fIflags\fR argument to \fBTk_ConfigureWidget\fR has
+the \fBTK_CONFIG_ARGV_ONLY\fR bit set (i.e., \fIflags\fR | \fBTK_CONFIG_ARGV_ONLY\fR != 0),
+then the option database and
+\fIdefValue\fR fields are not used. In this case, if an entry in
+\fIspecs\fR does not match a field in \fIargv\fR then nothing happens:
+the corresponding target is not modified. This feature is useful
+when the goal is to modify certain configuration options while
+leaving others in their current state, such as when a \fBconfigure\fR
+widget command is being processed.
+.PP
+Second, the \fIspecFlags\fR field of an entry in \fIspecs\fR may be used
+to control the processing of that entry. Each \fIspecFlags\fR
+field may consists of an OR-ed combination of the following values:
+.TP
+\fBTK_CONFIG_COLOR_ONLY\fR
+If this bit is set then the entry will only be considered if the
+display for \fItkwin\fR has more than one bit plane. If the display
+is monochromatic then this \fIspecs\fR entry will be ignored.
+.TP
+\fBTK_CONFIG_MONO_ONLY\fR
+If this bit is set then the entry will only be considered if the
+display for \fItkwin\fR has exactly one bit plane. If the display
+is not monochromatic then this \fIspecs\fR entry will be ignored.
+.TP
+\fBTK_CONFIG_NULL_OK\fR
+This bit is only relevant for some types of entries (see the
+descriptions of the various entry types above).
+If this bit is set, it indicates that an empty string value
+for the field is acceptable and if it occurs then the
+target should be set to NULL or \fBNone\fR, depending
+on the type of the target.
+This flag is typically used to allow a
+feature to be turned off entirely, e.g. set a cursor value to
+\fBNone\fR so that a window simply inherits its parent's cursor.
+If this bit is not set then empty strings are processed as strings,
+which generally results in an error.
+.TP
+\fBTK_CONFIG_DONT_SET_DEFAULT\fR
+If this bit is one, it means that the \fIdefValue\fR field of the
+entry should only be used for returning the default value in
+\fBTk_ConfigureInfo\fR.
+In calls to \fBTk_ConfigureWidget\fR no default will be supplied
+for entries with this flag set; it is assumed that the
+caller has already supplied a default value in the target location.
+This flag provides a performance optimization where it is expensive
+to process the default string: the client can compute the default
+once, save the value, and provide it before calling
+\fBTk_ConfigureWidget\fR.
+.TP
+\fBTK_CONFIG_OPTION_SPECIFIED\fR
+This bit is
+deprecated. It used to be set and cleared by \fBTk_ConfigureWidget\fR
+so that callers could detect what entries were specified in
+\fIargv\fR, but it was removed because it was inherently
+thread-unsafe. Code that wishes to detect what options were specified
+should use \fBTk_SetOptions\fR instead.
+.PP
+The \fBTK_CONFIG_MONO_ONLY\fR and \fBTK_CONFIG_COLOR_ONLY\fR flags are typically
+used to specify different default values for
+monochrome and color displays. This is done by creating two
+entries in \fIspecs\fR that are identical except for their
+\fIdefValue\fR and \fIspecFlags\fR fields. One entry should have
+the value \fBTK_CONFIG_MONO_ONLY\fR in its \fIspecFlags\fR and the
+default value for monochrome displays in its \fIdefValue\fR; the
+other entry should have the value \fBTK_CONFIG_COLOR_ONLY\fR in
+its \fIspecFlags\fR and the appropriate \fIdefValue\fR for
+color displays.
+.PP
+Third, it is possible to use \fIflags\fR and \fIspecFlags\fR
+together to selectively disable some entries. This feature is
+not needed very often. It is useful in cases where several
+similar kinds of widgets are implemented in one place. It allows
+a single \fIspecs\fR table to be created with all the configuration
+options for all the widget types. When processing a particular
+widget type, only entries relevant to that type will be used. This
+effect is achieved by setting the high-order bits (those in positions
+equal to or greater than \fBTK_CONFIG_USER_BIT\fR) in \fIspecFlags\fR
+values or in \fIflags\fR. In order for a particular entry in
+\fIspecs\fR to be used, its high-order bits must match exactly
+the high-order bits of the \fIflags\fR value passed to
+\fBTk_ConfigureWidget\fR. If a \fIspecs\fR table is being used
+for N different widget types, then N of the high-order bits will
+be used. Each \fIspecs\fR entry will have one of more of those
+bits set in its \fIspecFlags\fR field to indicate the widget types
+for which this entry is valid. When calling \fBTk_ConfigureWidget\fR,
+\fIflags\fR will have a single one of these bits set to select the
+entries for the desired widget type. For a working example of
+this feature, see the code in tkButton.c.
+.SH TK_OFFSET
+.PP
+The \fBTk_Offset\fR macro is provided as a safe way of generating
+the \fIoffset\fR values for entries in Tk_ConfigSpec structures.
+It takes two arguments: the name of a type of record, and the
+name of a field in that record. It returns the byte offset of
+the named field in records of the given type.
+.SH TK_CONFIGUREINFO
+.PP
+The \fBTk_ConfigureInfo\fR procedure may be used to obtain
+information about one or all of the options for a given widget.
+Given a token for a window (\fItkwin\fR), a table describing the
+configuration options for a class of widgets (\fIspecs\fR), a
+pointer to a widget record containing the current information for
+a widget (\fIwidgRec\fR), and a NULL \fIargvName\fR argument,
+\fBTk_ConfigureInfo\fR generates a string describing all of the
+configuration options for the window. The string is placed
+in interpreter \fIinterp\fR's result. Under normal circumstances
+it returns \fBTCL_OK\fR; if an error occurs then it returns \fBTCL_ERROR\fR
+and the interpreter's result will contain an error message.
+.PP
+If \fIargvName\fR is NULL, then the value left in
+the interpreter's result by \fBTk_ConfigureInfo\fR
+consists of a list of one or more entries, each of which describes
+one configuration option (i.e. one entry in \fIspecs\fR). Each
+entry in the list will contain either two or five values. If the
+corresponding entry in \fIspecs\fR has type \fBTK_CONFIG_SYNONYM\fR, then
+the list will contain two values: the \fIargvName\fR for the entry
+and the \fIdbName\fR (synonym name). Otherwise the list will contain
+five values: \fIargvName\fR, \fIdbName\fR, \fIdbClass\fR, \fIdefValue\fR,
+and current value. The current value is computed from the appropriate
+field of \fIwidgRec\fR by calling procedures like \fBTk_NameOfColor\fR.
+.PP
+If the \fIargvName\fR argument to \fBTk_ConfigureInfo\fR is non-NULL,
+then it indicates a single option, and information is returned only
+for that option. The string placed in the interpreter's result will be
+a list containing two or five values as described above; this will
+be identical to the corresponding sublist that would have been returned
+if \fIargvName\fR had been NULL.
+.PP
+The \fIflags\fR argument to \fBTk_ConfigureInfo\fR is used to restrict
+the \fIspecs\fR entries to consider, just as for \fBTk_ConfigureWidget\fR.
+.SH TK_CONFIGUREVALUE
+.PP
+\fBTk_ConfigureValue\fR takes arguments similar to \fBTk_ConfigureInfo\fR;
+instead of returning a list of values, it just returns the current value
+of the option given by \fIargvName\fR (\fIargvName\fR must not be NULL).
+The value is returned in interpreter \fIinterp\fR's result and \fBTCL_OK\fR is
+normally returned as the procedure's result.
+If an error occurs in \fBTk_ConfigureValue\fR (e.g., \fIargvName\fR is
+not a valid option name), \fBTCL_ERROR\fR is returned and an error message
+is left in the interpreter's result.
+This procedure is typically called to implement \fBcget\fR widget
+commands.
+.SH TK_FREEOPTIONS
+.PP
+The \fBTk_FreeOptions\fR procedure may be invoked during widget cleanup
+to release all of the resources associated with configuration options.
+It scans through \fIspecs\fR and for each entry corresponding to a
+resource that must be explicitly freed (e.g. those with
+type \fBTK_CONFIG_COLOR\fR), it frees the resource in the widget record.
+If the field in the widget record does not refer to a resource (e.g.
+it contains a null pointer) then no resource is freed for that
+entry.
+After freeing a resource, \fBTk_FreeOptions\fR sets the
+corresponding field of the widget record to null.
+.SH "CUSTOM OPTION TYPES"
+.PP
+Applications can extend the built-in configuration types with additional
+configuration types by writing procedures to parse and print options
+of the a type and creating a structure pointing to those procedures:
+.CS
+typedef struct Tk_CustomOption {
+ Tk_OptionParseProc *\fIparseProc\fR;
+ Tk_OptionPrintProc *\fIprintProc\fR;
+ ClientData \fIclientData\fR;
+} \fBTk_CustomOption\fR;
+
+typedef int \fBTk_OptionParseProc\fR(
+ ClientData \fIclientData\fR,
+ Tcl_Interp *\fIinterp\fR,
+ Tk_Window \fItkwin\fR,
+ char *\fIvalue\fR,
+ char *\fIwidgRec\fR,
+ int \fIoffset\fR);
+
+typedef const char *\fBTk_OptionPrintProc\fR(
+ ClientData \fIclientData\fR,
+ Tk_Window \fItkwin\fR,
+ char *\fIwidgRec\fR,
+ int \fIoffset\fR,
+ Tcl_FreeProc **\fIfreeProcPtr\fR);
+.CE
+The Tk_CustomOption structure contains three fields, which are pointers
+to the two procedures and a \fIclientData\fR value to be passed to those
+procedures when they are invoked. The \fIclientData\fR value typically
+points to a structure containing information that is needed by the
+procedures when they are parsing and printing options.
+.PP
+The \fIparseProc\fR procedure is invoked by
+\fBTk_ConfigureWidget\fR to parse a string and store the resulting
+value in the widget record.
+The \fIclientData\fR argument is a copy of the \fIclientData\fR
+field in the Tk_CustomOption structure.
+The \fIinterp\fR argument points to a Tcl interpreter used for
+error reporting. \fITkwin\fR is a copy of the \fItkwin\fR argument
+to \fBTk_ConfigureWidget\fR. The \fIvalue\fR argument is a string
+describing the value for the option; it could have been specified
+explicitly in the call to \fBTk_ConfigureWidget\fR or it could
+come from the option database or a default.
+\fIValue\fR will never be a null pointer but it may point to
+an empty string.
+\fIRecordPtr\fR is the same as the \fIwidgRec\fR argument to
+\fBTk_ConfigureWidget\fR; it points to the start of the widget
+record to modify.
+The last argument, \fIoffset\fR, gives the offset in bytes from the start
+of the widget record to the location where the option value is to
+be placed. The procedure should translate the string to whatever
+form is appropriate for the option and store the value in the widget
+record. It should normally return \fBTCL_OK\fR, but if an error occurs
+in translating the string to a value then it should return \fBTCL_ERROR\fR
+and store an error message in interpreter \fIinterp\fR's result.
+.PP
+The \fIprintProc\fR procedure is called
+by \fBTk_ConfigureInfo\fR to produce a string value describing an
+existing option.
+Its \fIclientData\fR, \fItkwin\fR, \fIwidgRec\fR, and \fIoffset\fR
+arguments all have the same meaning as for Tk_OptionParseProc
+procedures.
+The \fIprintProc\fR procedure should examine the option whose value
+is stored at \fIoffset\fR in \fIwidgRec\fR, produce a string describing
+that option, and return a pointer to the string.
+If the string is stored in dynamically-allocated memory, then
+the procedure must set \fI*freeProcPtr\fR to the address of
+a procedure to call to free the string's memory; \fBTk_ConfigureInfo\fR
+will call this procedure when it is finished with the string.
+If the result string is stored in static memory then \fIprintProc\fR
+need not do anything with the \fIfreeProcPtr\fR argument.
+.PP
+Once \fIparseProc\fR and \fIprintProc\fR have been defined and a
+Tk_CustomOption structure has been created for them, options of this
+new type may be manipulated with Tk_ConfigSpec entries whose \fItype\fR
+fields are \fBTK_CONFIG_CUSTOM\fR and whose \fIcustomPtr\fR fields point
+to the Tk_CustomOption structure.
+.SH EXAMPLES
+.PP
+Although the explanation of \fBTk_ConfigureWidget\fR is fairly
+complicated, its actual use is pretty straightforward.
+The easiest way to get started is to copy the code
+from an existing widget.
+The library implementation of frames
+(tkFrame.c) has a simple configuration table, and the library
+implementation of buttons (tkButton.c) has a much more complex
+table that uses many of the fancy \fIspecFlags\fR mechanisms.
+.SH "SEE ALSO"
+Tk_SetOptions(3)
+.SH KEYWORDS
+anchor, bitmap, boolean, border, cap style, color, configuration options,
+cursor, custom, double, font, integer, join style, justify, millimeters,
+pixels, relief, synonym, uid
diff --git a/tk8.6/doc/ConfigWind.3 b/tk8.6/doc/ConfigWind.3
new file mode 100644
index 0000000..7c7adab
--- /dev/null
+++ b/tk8.6/doc/ConfigWind.3
@@ -0,0 +1,147 @@
+'\"
+'\" Copyright (c) 1990-1993 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_ConfigureWindow 3 4.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_ConfigureWindow, Tk_MoveWindow, Tk_ResizeWindow, Tk_MoveResizeWindow, Tk_SetWindowBorderWidth, Tk_ChangeWindowAttributes, Tk_SetWindowBackground, Tk_SetWindowBackgroundPixmap, Tk_SetWindowBorder, Tk_SetWindowBorderPixmap, Tk_SetWindowColormap, Tk_DefineCursor, Tk_UndefineCursor \- change window configuration or attributes
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+\fBTk_ConfigureWindow\fR(\fItkwin, valueMask, valuePtr\fR)
+.sp
+\fBTk_MoveWindow\fR(\fItkwin, x, y\fR)
+.sp
+\fBTk_ResizeWindow\fR(\fItkwin, width, height\fR)
+.sp
+\fBTk_MoveResizeWindow\fR(\fItkwin, x, y, width, height\fR)
+.sp
+\fBTk_SetWindowBorderWidth\fR(\fItkwin, borderWidth\fR)
+.sp
+\fBTk_ChangeWindowAttributes\fR(\fItkwin, valueMask, attsPtr\fR)
+.sp
+\fBTk_SetWindowBackground\fR(\fItkwin, pixel\fR)
+.sp
+\fBTk_SetWindowBackgroundPixmap\fR(\fItkwin, pixmap\fR)
+.sp
+\fBTk_SetWindowBorder\fR(\fItkwin, pixel\fR)
+.sp
+\fBTk_SetWindowBorderPixmap\fR(\fItkwin, pixmap\fR)
+.sp
+\fBTk_SetWindowColormap\fR(\fItkwin, colormap\fR)
+.sp
+\fBTk_DefineCursor\fR(\fItkwin, cursor\fR)
+.sp
+\fBTk_UndefineCursor\fR(\fItkwin\fR)
+.SH ARGUMENTS
+.AS XSetWindowAttributes borderWidth
+.AP Tk_Window tkwin in
+Token for window.
+.AP "unsigned int" valueMask in
+OR-ed mask of values like \fBCWX\fR or \fBCWBorderPixel\fR,
+indicating which fields of \fI*valuePtr\fR or \fI*attsPtr\fR to use.
+.AP XWindowChanges *valuePtr in
+Points to a structure containing new values for the configuration
+parameters selected by \fIvalueMask\fR. Fields not selected
+by \fIvalueMask\fR are ignored.
+.AP int x in
+New x-coordinate for \fItkwin\fR's top left pixel (including
+border, if any) within tkwin's parent.
+.AP int y in
+New y-coordinate for \fItkwin\fR's top left pixel (including
+border, if any) within tkwin's parent.
+.AP "int" width in
+New width for \fItkwin\fR (interior, not including border).
+.AP "int" height in
+New height for \fItkwin\fR (interior, not including border).
+.AP "int" borderWidth in
+New width for \fItkwin\fR's border.
+.AP XSetWindowAttributes *attsPtr in
+Points to a structure containing new values for the attributes
+given by the \fIvalueMask\fR argument. Attributes not selected
+by \fIvalueMask\fR are ignored.
+.AP "unsigned long" pixel in
+New background or border color for window.
+.AP Pixmap pixmap in
+New pixmap to use for background or border of \fItkwin\fR. WARNING:
+cannot necessarily be deleted immediately, as for Xlib calls. See
+note below.
+.AP Colormap colormap in
+New colormap to use for \fItkwin\fR.
+.AP Tk_Cursor cursor in
+New cursor to use for \fItkwin\fR. If \fBNone\fR is specified, then
+\fItkwin\fR will not have its own cursor; it will use the cursor
+of its parent.
+.BE
+.SH DESCRIPTION
+.PP
+These procedures are analogous to the X library procedures
+with similar names, such as \fBXConfigureWindow\fR. Each
+one of the above procedures calls the corresponding X procedure
+and also saves the configuration information in Tk's local
+structure for the window. This allows the information to
+be retrieved quickly by the application (using macros such
+as \fBTk_X\fR and \fBTk_Height\fR) without having to contact
+the X server. In addition, if no X window has actually been
+created for \fItkwin\fR yet, these procedures do not issue
+X operations or cause event handlers to be invoked; they save
+the information in Tk's local
+structure for the window; when the window is created later,
+the saved information will be used to configure the window.
+.PP
+See the X library documentation for details on what these
+procedures do and how they use their arguments.
+.PP
+In the procedures \fBTk_ConfigureWindow\fR, \fBTk_MoveWindow\fR,
+\fBTk_ResizeWindow\fR, \fBTk_MoveResizeWindow\fR, and
+\fBTk_SetWindowBorderWidth\fR,
+if \fItkwin\fR is an internal window then event handlers interested
+in configure events are invoked immediately, before the procedure
+returns. If \fItkwin\fR is a top-level window
+then the event handlers will be invoked later, after X has seen
+the request and returned an event for it.
+.PP
+Applications using Tk should never call procedures like
+\fBXConfigureWindow\fR directly; they should always use the
+corresponding Tk procedures.
+.PP
+The size and location of a window should only be modified by the
+appropriate geometry manager for that window and never by a window
+itself (but see \fBTk_MoveToplevelWindow\fR for moving a top-level
+window).
+.PP
+You may not use \fBTk_ConfigureWindow\fR to change the
+stacking order of a window (\fIvalueMask\fR may not contain the
+\fBCWSibling\fR or \fBCWStackMode\fR bits).
+To change the stacking order, use the procedure \fBTk_RestackWindow\fR.
+.PP
+The procedure \fBTk_SetWindowColormap\fR will automatically add
+\fItkwin\fR to the \fBTK_COLORMAP_WINDOWS\fR property of its
+nearest top-level ancestor if the new colormap is different from
+that of \fItkwin\fR's parent and \fItkwin\fR is not already in
+the \fBTK_COLORMAP_WINDOWS\fR property.
+.SH BUGS
+.PP
+\fBTk_SetWindowBackgroundPixmap\fR and \fBTk_SetWindowBorderPixmap\fR
+differ slightly from their Xlib counterparts in that the \fIpixmap\fR
+argument may not necessarily be deleted immediately after calling
+one of these procedures. This is because \fItkwin\fR's window
+may not exist yet at the time of the call, in which case \fIpixmap\fR
+is merely saved and used later when \fItkwin\fR's window is actually
+created. If you wish to delete \fIpixmap\fR, then call
+\fBTk_MakeWindowExist\fR first to be sure that \fItkwin\fR's window exists
+and \fIpixmap\fR has been passed to the X server.
+.PP
+A similar problem occurs for the \fIcursor\fR argument passed to
+\fBTk_DefineCursor\fR. The solution is the same as for pixmaps above:
+call \fBTk_MakeWindowExist\fR before freeing the cursor.
+.SH "SEE ALSO"
+Tk_MoveToplevelWindow, Tk_RestackWindow
+.SH KEYWORDS
+attributes, border, color, configure, height, pixel, pixmap, width, window, x, y
diff --git a/tk8.6/doc/CoordToWin.3 b/tk8.6/doc/CoordToWin.3
new file mode 100644
index 0000000..5fe96a6
--- /dev/null
+++ b/tk8.6/doc/CoordToWin.3
@@ -0,0 +1,47 @@
+'\"
+'\" Copyright (c) 1990-1993 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_CoordsToWindow 3 "" Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_CoordsToWindow \- Find window containing a point
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+Tk_Window
+\fBTk_CoordsToWindow\fR(\fIrootX, rootY, tkwin\fR)
+.SH ARGUMENTS
+.AS Tk_Window tkwin
+.AP int rootX in
+X-coordinate (in root window coordinates).
+.AP int rootY in
+Y-coordinate (in root window coordinates).
+.AP Tk_Window tkwin in
+Token for window that identifies application.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_CoordsToWindow\fR locates the window that contains a given point.
+The point is specified in root coordinates with \fIrootX\fR and
+\fIrootY\fR (if a virtual-root window manager is in use then
+\fIrootX\fR and \fIrootY\fR are in the coordinate system of the
+virtual root window).
+The return value from the procedure is a token for the window that
+contains the given point.
+If the point is not in any window, or if the containing window
+is not in the same application as \fItkwin\fR, then NULL is
+returned.
+.PP
+The containing window is decided using the same rules that determine
+which window contains the mouse cursor: if a parent and a child both
+contain the point then the child gets preference, and if two siblings
+both contain the point then the highest one in the stacking order
+(i.e. the one that's visible on the screen) gets preference.
+.SH KEYWORDS
+containing, coordinates, root window
diff --git a/tk8.6/doc/CrtCmHdlr.3 b/tk8.6/doc/CrtCmHdlr.3
new file mode 100644
index 0000000..bcc9493
--- /dev/null
+++ b/tk8.6/doc/CrtCmHdlr.3
@@ -0,0 +1,64 @@
+'\"
+'\" Copyright (c) 2000 Ajuba Solutions.
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH Tk_CreateClientMessageHandler 3 "8.4" Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_CreateClientMessageHandler, Tk_DeleteClientMessageHandler \- associate procedure callback with ClientMessage type X events
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+\fBTk_CreateClientMessageHandler\fR(\fIproc\fR)
+.sp
+\fBTk_DeleteClientMessageHandler\fR(\fIproc\fR)
+.SH ARGUMENTS
+.AP Tk_ClientMessageProc *proc in
+Procedure to invoke whenever a ClientMessage X event occurs on any display.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_CreateClientMessageHandler\fR arranges for \fIproc\fR to be invoked
+in the future whenever a ClientMessage X event occurs that is not handled by
+\fBWM_PROTOCOL\fR. \fBTk_CreateClientMessageHandler\fR is intended for use
+by applications which need to watch X ClientMessage events, such as drag and
+drop applications.
+.PP
+The callback to \fIproc\fR will be made by \fBTk_HandleEvent\fR;
+this mechanism only works in programs that dispatch events
+through \fBTk_HandleEvent\fR (or through other Tk procedures that
+call \fBTk_HandleEvent\fR, such as \fBTcl_DoOneEvent\fR or
+\fBTk_MainLoop\fR).
+.PP
+\fIProc\fR should have arguments and result that match the
+type \fBTk_ClientMessageProc\fR:
+.CS
+typedef int \fBTk_ClientMessageProc\fR(
+ Tk_Window \fItkwin\fR,
+ XEvent *\fIeventPtr\fR);
+.CE
+The \fItkwin\fR parameter to \fIproc\fR is the Tk window which is
+associated with this event. \fIEventPtr\fR is a pointer to the X event.
+.PP
+Whenever an X ClientMessage event is processed by \fBTk_HandleEvent\fR,
+the \fIproc\fR is called if it was not handled as a \fBWM_PROTOCOL\fR.
+The return value from \fIproc\fR is normally 0.
+A non-zero return value indicates that the event is not to be handled
+further; that is, \fIproc\fR has done all processing that is to be
+allowed for the event.
+.PP
+If there are multiple ClientMessage event handlers, each one is called
+for each event, in the order in which they were established.
+.PP
+\fBTk_DeleteClientMessageHandler\fR may be called to delete a
+previously-created ClientMessage event handler: it deletes each handler it
+finds that matches the \fIproc\fR argument. If no such handler exists,
+then \fBTk_DeleteClientMessageHandler\fR returns without doing anything.
+Although Tk supports it, it's probably a bad idea to have more than one
+callback with the same \fIproc\fR argument.
+.SH KEYWORDS
+bind, callback, event, handler
diff --git a/tk8.6/doc/CrtConsoleChan.3 b/tk8.6/doc/CrtConsoleChan.3
new file mode 100644
index 0000000..7fd8a6a
--- /dev/null
+++ b/tk8.6/doc/CrtConsoleChan.3
@@ -0,0 +1,44 @@
+'\"
+'\" Copyright (c) 2007 ActiveState Software Inc.
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH Tk_InitConsoleChannels 3 8.5 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_InitConsoleChannels \- Install the console channels as standard channels
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+\fBTk_InitConsoleChannels\fR(\fIinterp\fR)
+.SH ARGUMENTS
+.AS Tcl_Interp *interp in
+.AP Tcl_Interp *interp in
+Interpreter in which the console channels are created.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_InitConsoleChannels\fR is invoked to create a set of console
+channels and install them as the standard channels. All I/O on these
+channels will be discarded until \fBTk_CreateConsoleWindow\fR is
+called to attach the console to a text widget.
+.PP
+This function is for use by shell applications based on Tk, like
+\fBwish\fR, on platforms which have no standard channels in graphical
+mode, like Win32.
+.PP
+The \fIinterp\fR argument is the interpreter in which to create and
+install the console channels.
+.PP
+\fBNOTE:\fR If this function is used it has to be called before the
+first call to \fBTcl_RegisterChannel\fR, directly, or indirectly
+through other channel functions. Because otherwise the standard
+channels will be already initialized to the system defaults, which will
+be nonsensical for the case \fBTk_InitConsoleChannels\fR is for.
+.SH "SEE ALSO"
+console(n)
+.SH KEYWORDS
+standard channels, console
diff --git a/tk8.6/doc/CrtErrHdlr.3 b/tk8.6/doc/CrtErrHdlr.3
new file mode 100644
index 0000000..e506220
--- /dev/null
+++ b/tk8.6/doc/CrtErrHdlr.3
@@ -0,0 +1,140 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_CreateErrorHandler 3 "" Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_CreateErrorHandler, Tk_DeleteErrorHandler \- handle X protocol errors
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+Tk_ErrorHandler
+\fBTk_CreateErrorHandler\fR(\fIdisplay, error, request, minor, proc, clientData\fR)
+.sp
+\fBTk_DeleteErrorHandler\fR(\fIhandler\fR)
+.SH ARGUMENTS
+.AS "Tk_ErrorHandler" clientData
+.AP Display *display in
+Display whose errors are to be handled.
+.AP int error in
+Match only error events with this value in the \fIerror_code\fR
+field. If \-1, then match any \fIerror_code\fR value.
+.AP int request in
+Match only error events with this value in the \fIrequest_code\fR
+field. If \-1, then match any \fIrequest_code\fR value.
+.AP int minor in
+Match only error events with this value in the \fIminor_code\fR
+field. If \-1, then match any \fIminor_code\fR value.
+.AP Tk_ErrorProc *proc in
+Procedure to invoke whenever an error event is received for
+\fIdisplay\fR and matches \fIerror\fR, \fIrequest\fR, and \fIminor\fR.
+NULL means ignore any matching errors.
+.AP ClientData clientData in
+Arbitrary one-word value to pass to \fIproc\fR.
+.AP Tk_ErrorHandler handler in
+Token for error handler to delete (return value from a previous
+call to \fBTk_CreateErrorHandler\fR).
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_CreateErrorHandler\fR arranges for a particular procedure
+(\fIproc\fR) to be called whenever certain protocol errors occur on a
+particular display (\fIdisplay\fR). Protocol errors occur when
+the X protocol is used incorrectly, such as attempting to map a window
+that does not exist. See the Xlib documentation for \fBXSetErrorHandler\fR
+for more information on the kinds of errors that can occur.
+For \fIproc\fR to be invoked
+to handle a particular error, five things must occur:
+.IP [1]
+The error must pertain to \fIdisplay\fR.
+.IP [2]
+Either the \fIerror\fR argument to \fBTk_CreateErrorHandler\fR
+must have been \-1, or the \fIerror\fR argument must match
+the \fIerror_code\fR field from the error event.
+.IP [3]
+Either the \fIrequest\fR argument to \fBTk_CreateErrorHandler\fR
+must have been \-1, or the \fIrequest\fR argument must match
+the \fIrequest_code\fR field from the error event.
+.IP [4]
+Either the \fIminor\fR argument to \fBTk_CreateErrorHandler\fR
+must have been \-1, or the \fIminor\fR argument must match
+the \fIminor_code\fR field from the error event.
+.IP [5]
+The protocol request to which the error pertains must have been
+made when the handler was active (see below for more information).
+.PP
+\fIProc\fR should have arguments and result that match the
+following type:
+.CS
+typedef int \fBTk_ErrorProc\fR(
+ ClientData \fIclientData\fR,
+ XErrorEvent *\fIerrEventPtr\fR);
+.CE
+The \fIclientData\fR parameter to \fIproc\fR is a copy of the \fIclientData\fR
+argument given to \fBTcl_CreateErrorHandler\fR when the callback
+was created. Typically, \fIclientData\fR points to a data
+structure containing application-specific information that is
+needed to deal with the error. \fIErrEventPtr\fR is
+a pointer to the X error event.
+The procedure \fIproc\fR should return an integer value. If it
+returns 0 it means that \fIproc\fR handled the error completely and there
+is no need to take any other action for the error. If it returns
+non-zero it means \fIproc\fR was unable to handle the error.
+.PP
+If a value of NULL is specified for \fIproc\fR, all matching errors
+will be ignored: this will produce the same result as if a procedure
+had been specified that always returns 0.
+.PP
+If more than more than one handler matches a particular error, then
+they are invoked in turn. The handlers will be invoked in reverse
+order of creation: most recently declared handler first.
+If any handler returns 0, then subsequent (older) handlers will
+not be invoked. If no handler returns 0, then Tk invokes X's
+default error handler, which prints an error message and aborts the
+program. If you wish to have a default handler that deals with errors
+that no other handler can deal with, then declare it first.
+.PP
+The X documentation states that
+.QW "the error handler should not call any functions (directly or indirectly) on the display that will generate protocol requests or that will look for input events."
+This restriction applies to handlers declared by \fBTk_CreateErrorHandler\fR;
+disobey it at your own risk.
+.PP
+\fBTk_DeleteErrorHandler\fR may be called to delete a
+previously-created error handler. The \fIhandler\fR argument
+identifies the error handler, and should be a value returned by
+a previous call to \fBTk_CreateEventHandler\fR.
+.PP
+A particular error handler applies to errors resulting
+from protocol requests generated between
+the call to \fBTk_CreateErrorHandler\fR and the call to
+\fBTk_DeleteErrorHandler\fR. However, the actual callback
+to \fIproc\fR may not occur until after the \fBTk_DeleteErrorHandler\fR
+call, due to buffering in the client and server.
+If an error event pertains to
+a protocol request made just before calling \fBTk_DeleteErrorHandler\fR,
+then the error event may not have been processed
+before the \fBTk_DeleteErrorHandler\fR
+call. When this situation arises, Tk will save information about
+the handler and
+invoke the handler's \fIproc\fR later when the error event
+finally arrives.
+If an application wishes to delete an error handler and know
+for certain that all relevant errors have been processed,
+it should first call \fBTk_DeleteErrorHandler\fR and then
+call \fBXSync\fR; this will flush out any buffered requests and errors,
+but will result in a performance penalty because
+it requires communication to and from the X server. After the
+\fBXSync\fR call Tk is guaranteed not to call any error
+handlers deleted before the \fBXSync\fR call.
+.PP
+For the Tk error handling mechanism to work properly, it is essential
+that application code never calls \fBXSetErrorHandler\fR directly;
+applications should use only \fBTk_CreateErrorHandler\fR.
+.SH KEYWORDS
+callback, error, event, handler
diff --git a/tk8.6/doc/CrtGenHdlr.3 b/tk8.6/doc/CrtGenHdlr.3
new file mode 100644
index 0000000..671d105
--- /dev/null
+++ b/tk8.6/doc/CrtGenHdlr.3
@@ -0,0 +1,81 @@
+'\"
+'\" Copyright (c) 1992-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_CreateGenericHandler 3 "" Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_CreateGenericHandler, Tk_DeleteGenericHandler \- associate procedure callback with all X events
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+\fBTk_CreateGenericHandler\fR(\fIproc, clientData\fR)
+.sp
+\fBTk_DeleteGenericHandler\fR(\fIproc, clientData\fR)
+.SH ARGUMENTS
+.AS "Tk_GenericProc" clientData
+.AP Tk_GenericProc *proc in
+Procedure to invoke whenever any X event occurs on any display.
+.AP ClientData clientData in
+Arbitrary one-word value to pass to \fIproc\fR.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_CreateGenericHandler\fR arranges for \fIproc\fR to be
+invoked in the future whenever any X event occurs. This mechanism is
+\fInot\fR intended for dispatching X events on windows managed by Tk
+(you should use \fBTk_CreateEventHandler\fR for this purpose).
+\fBTk_CreateGenericHandler\fR is intended for other purposes, such
+as tracing X events, monitoring events on windows not owned by Tk,
+accessing X-related libraries that were not originally designed for
+use with Tk, and so on.
+.PP
+The callback to \fIproc\fR will be made by \fBTk_HandleEvent\fR;
+this mechanism only works in programs that dispatch events
+through \fBTk_HandleEvent\fR (or through other Tk procedures that
+call \fBTk_HandleEvent\fR, such as \fBTcl_DoOneEvent\fR or
+\fBTk_MainLoop\fR).
+.PP
+\fIProc\fR should have arguments and result that match the
+type \fBTk_GenericProc\fR:
+.CS
+typedef int \fBTk_GenericProc\fR(
+ ClientData \fIclientData\fR,
+ XEvent *\fIeventPtr\fR);
+.CE
+The \fIclientData\fR parameter to \fIproc\fR is a copy of the \fIclientData\fR
+argument given to \fBTk_CreateGenericHandler\fR when the callback
+was created. Typically, \fIclientData\fR points to a data
+structure containing application-specific information about
+how to handle events.
+\fIEventPtr\fR is a pointer to the X event.
+.PP
+Whenever an X event is processed by \fBTk_HandleEvent\fR, \fIproc\fR
+is called. The return value from \fIproc\fR is normally 0.
+A non-zero return value indicates that the event is not to be handled
+further; that is, \fIproc\fR has done all processing that is to be
+allowed for the event.
+.PP
+If there are multiple generic event handlers, each one is called
+for each event, in the order in which they were established.
+.PP
+\fBTk_DeleteGenericHandler\fR may be called to delete a
+previously-created generic event handler: it deletes each handler
+it finds that matches the \fIproc\fR and \fIclientData\fR arguments. If
+no such handler exists, then \fBTk_DeleteGenericHandler\fR returns
+without doing anything. Although Tk supports it, it's probably
+a bad idea to have more than one callback with the same
+\fIproc\fR and \fIclientData\fR arguments.
+.PP
+Establishing a generic event handler does nothing to ensure that the
+process will actually receive the X events that the handler wants to
+process.
+For example, it is the caller's responsibility to invoke
+\fBXSelectInput\fR to select the desired events, if that is necessary.
+.SH KEYWORDS
+bind, callback, event, handler
diff --git a/tk8.6/doc/CrtImgType.3 b/tk8.6/doc/CrtImgType.3
new file mode 100644
index 0000000..cbbc11e
--- /dev/null
+++ b/tk8.6/doc/CrtImgType.3
@@ -0,0 +1,283 @@
+'\"
+'\" Copyright (c) 1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_CreateImageType 3 8.5 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_CreateImageType, Tk_GetImageMasterData, Tk_InitImageArgs \- define new kind of image
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+\fBTk_CreateImageType\fR(\fItypePtr\fR)
+.sp
+ClientData
+\fBTk_GetImageMasterData\fR(\fIinterp, name, typePtrPtr\fR)
+.sp
+\fBTk_InitImageArgs\fR(\fIinterp, argc, argvPtr\fR)
+.SH ARGUMENTS
+.AS "const Tk_ImageType" *typePtrPtr
+.AP "const Tk_ImageType" *typePtr in
+Structure that defines the new type of image.
+For Tk 8.4 and earlier this must be static: a
+pointer to this structure is retained by the image code.
+In Tk 8.5, this limitation was relaxed.
+.AP Tcl_Interp *interp in
+Interpreter in which image was created.
+.AP "const char" *name in
+Name of existing image.
+.AP Tk_ImageType **typePtrPtr out
+Points to word in which to store a pointer to type information for
+the given image, if it exists.
+.AP int argc in
+Number of arguments
+.AP char ***argvPtr in/out
+Pointer to argument list
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_CreateImageType\fR is invoked to define a new kind of image.
+An image type corresponds to a particular value of the \fItype\fR
+argument for the \fBimage create\fR command. There may exist
+any number of different image types, and new types may be defined
+dynamically by calling \fBTk_CreateImageType\fR.
+For example, there might be one type for 2-color bitmaps,
+another for multi-color images, another for dithered images,
+another for video, and so on.
+.PP
+The code that implements a new image type is called an
+\fIimage manager\fR.
+It consists of a collection of procedures plus three different
+kinds of data structures.
+The first data structure is a Tk_ImageType structure, which contains
+the name of the image type and pointers to five procedures provided
+by the image manager to deal with images of this type:
+.CS
+typedef struct Tk_ImageType {
+ const char *\fIname\fR;
+ Tk_ImageCreateProc *\fIcreateProc\fR;
+ Tk_ImageGetProc *\fIgetProc\fR;
+ Tk_ImageDisplayProc *\fIdisplayProc\fR;
+ Tk_ImageFreeProc *\fIfreeProc\fR;
+ Tk_ImageDeleteProc *\fIdeleteProc\fR;
+} \fBTk_ImageType\fR;
+.CE
+The fields of this structure will be described in later subsections
+of this entry.
+.PP
+The second major data structure manipulated by an image manager
+is called an \fIimage master\fR; it contains overall information
+about a particular image, such as the values of the configuration
+options specified in an \fBimage create\fR command.
+There will usually be one of these structures for each
+invocation of the \fBimage create\fR command.
+.PP
+The third data structure related to images is an \fIimage instance\fR.
+There will usually be one of these structures for each usage of an
+image in a particular widget.
+It is possible for a single image to appear simultaneously
+in multiple widgets, or even multiple times in the same widget.
+Furthermore, different instances may be on different screens
+or displays.
+The image instance data structure describes things that may
+vary from instance to instance, such as colors and graphics
+contexts for redisplay.
+There is usually one instance structure for each \fB\-image\fR
+option specified for a widget or canvas item.
+.PP
+The following subsections describe the fields of a Tk_ImageType
+in more detail.
+.SS NAME
+.PP
+\fItypePtr->name\fR provides a name for the image type.
+Once \fBTk_CreateImageType\fR returns, this name may be used
+in \fBimage create\fR commands to create images of the new
+type.
+If there already existed an image type by this name then
+the new image type replaces the old one.
+.SS CREATEPROC
+.PP
+\fItypePtr->createProc\fR provides the address of a procedure for
+Tk to call whenever \fBimage create\fR is invoked to create
+an image of the new type.
+\fItypePtr->createProc\fR must match the following prototype:
+.CS
+typedef int \fBTk_ImageCreateProc\fR(
+ Tcl_Interp *\fIinterp\fR,
+ const char *\fIname\fR,
+ int \fIobjc\fR,
+ Tcl_Obj *const \fIobjv\fR[],
+ const Tk_ImageType *\fItypePtr\fR,
+ Tk_ImageMaster \fImaster\fR,
+ ClientData *\fImasterDataPtr\fR);
+.CE
+The \fIinterp\fR argument is the interpreter in which the \fBimage\fR
+command was invoked, and \fIname\fR is the name for the new image,
+which was either specified explicitly in the \fBimage\fR command
+or generated automatically by the \fBimage\fR command.
+The \fIobjc\fR and \fIobjv\fR arguments describe all the configuration
+options for the new image (everything after the name argument to
+\fBimage\fR).
+The \fImaster\fR argument is a token that refers to Tk's information
+about this image; the image manager must return this token to
+Tk when invoking the \fBTk_ImageChanged\fR procedure.
+Typically \fIcreateProc\fR will parse \fIobjc\fR and \fIobjv\fR
+and create an image master data structure for the new image.
+\fIcreateProc\fR may store an arbitrary one-word value at
+*\fImasterDataPtr\fR, which will be passed back to the
+image manager when other callbacks are invoked.
+Typically the value is a pointer to the master data
+structure for the image.
+.PP
+If \fIcreateProc\fR encounters an error, it should leave an error
+message in the interpreter result and return \fBTCL_ERROR\fR; otherwise
+it should return \fBTCL_OK\fR.
+.PP
+\fIcreateProc\fR should call \fBTk_ImageChanged\fR in order to set the
+size of the image and request an initial redisplay.
+.SS GETPROC
+.PP
+\fItypePtr->getProc\fR is invoked by Tk whenever a widget
+calls \fBTk_GetImage\fR to use a particular image.
+This procedure must match the following prototype:
+.CS
+typedef ClientData \fBTk_ImageGetProc\fR(
+ Tk_Window \fItkwin\fR,
+ ClientData \fImasterData\fR);
+.CE
+The \fItkwin\fR argument identifies the window in which the
+image will be used and \fImasterData\fR is the value
+returned by \fIcreateProc\fR when the image master was created.
+\fIgetProc\fR will usually create a data structure for the new
+instance, including such things as the resources needed to
+display the image in the given window.
+\fIgetProc\fR returns a one-word token for the instance, which
+is typically the address of the instance data structure.
+Tk will pass this value back to the image manager when invoking
+its \fIdisplayProc\fR and \fIfreeProc\fR procedures.
+.SS DISPLAYPROC
+.PP
+\fItypePtr->displayProc\fR is invoked by Tk whenever an image needs
+to be displayed (i.e., whenever a widget calls \fBTk_RedrawImage\fR).
+\fIdisplayProc\fR must match the following prototype:
+.CS
+typedef void \fBTk_ImageDisplayProc\fR(
+ ClientData \fIinstanceData\fR,
+ Display *\fIdisplay\fR,
+ Drawable \fIdrawable\fR,
+ int \fIimageX\fR,
+ int \fIimageY\fR,
+ int \fIwidth\fR,
+ int \fIheight\fR,
+ int \fIdrawableX\fR,
+ int \fIdrawableY\fR);
+.CE
+The \fIinstanceData\fR will be the same as the value returned by
+\fIgetProc\fR when the instance was created.
+\fIdisplay\fR and \fIdrawable\fR indicate where to display the
+image; \fIdrawable\fR may be a pixmap rather than
+the window specified to \fIgetProc\fR (this is usually the case,
+since most widgets double-buffer their redisplay to get smoother
+visual effects).
+\fIimageX\fR, \fIimageY\fR, \fIwidth\fR, and \fIheight\fR
+identify the region of the image that must be redisplayed.
+This region will always be within the size of the image
+as specified in the most recent call to \fBTk_ImageChanged\fR.
+\fIdrawableX\fR and \fIdrawableY\fR indicate where in \fIdrawable\fR
+the image should be displayed; \fIdisplayProc\fR should display
+the given region of the image so that point (\fIimageX\fR, \fIimageY\fR)
+in the image appears at (\fIdrawableX\fR, \fIdrawableY\fR) in \fIdrawable\fR.
+.SS FREEPROC
+.PP
+\fItypePtr->freeProc\fR contains the address of a procedure that
+Tk will invoke when an image instance is released (i.e., when
+\fBTk_FreeImage\fR is invoked).
+This can happen, for example, when a widget is deleted or a image item
+in a canvas is deleted, or when the image displayed in a widget or
+canvas item is changed.
+\fIfreeProc\fR must match the following prototype:
+.CS
+typedef void \fBTk_ImageFreeProc\fR(
+ ClientData \fIinstanceData\fR,
+ Display *\fIdisplay\fR);
+.CE
+The \fIinstanceData\fR will be the same as the value returned by
+\fIgetProc\fR when the instance was created, and \fIdisplay\fR
+is the display containing the window for the instance.
+\fIfreeProc\fR should release any resources associated with the
+image instance, since the instance will never be used again.
+.SS DELETEPROC
+.PP
+\fItypePtr->deleteProc\fR is a procedure that Tk invokes when an
+image is being deleted (i.e. when the \fBimage delete\fR command
+is invoked).
+Before invoking \fIdeleteProc\fR Tk will invoke \fIfreeProc\fR for
+each of the image's instances.
+\fIdeleteProc\fR must match the following prototype:
+.CS
+typedef void \fBTk_ImageDeleteProc\fR(
+ ClientData \fImasterData\fR);
+.CE
+The \fImasterData\fR argument will be the same as the value
+stored in \fI*masterDataPtr\fR by \fIcreateProc\fR when the
+image was created.
+\fIdeleteProc\fR should release any resources associated with
+the image.
+.SH TK_GETIMAGEMASTERDATA
+.PP
+The procedure \fBTk_GetImageMasterData\fR may be invoked to retrieve
+information about an image. For example, an image manager can use this
+procedure to locate its image master data for an image.
+If there exists an image named \fIname\fR
+in the interpreter given by \fIinterp\fR, then \fI*typePtrPtr\fR is
+filled in with type information for the image (the \fItypePtr\fR value
+passed to \fBTk_CreateImageType\fR when the image type was registered)
+and the return value is the ClientData value returned by the
+\fIcreateProc\fR when the image was created (this is typically a
+pointer to the image master data structure). If no such image exists
+then NULL is returned and NULL is stored at \fI*typePtrPtr\fR.
+.SH "LEGACY INTERFACE SUPPORT"
+.PP
+In Tk 8.2 and earlier, the definition of \fBTk_ImageCreateProc\fR
+was incompatibly different, with the following prototype:
+.CS
+typedef int \fBTk_ImageCreateProc\fR(
+ Tcl_Interp *\fIinterp\fR,
+ char *\fIname\fR,
+ int \fIargc\fR,
+ char **\fIargv\fR,
+ Tk_ImageType *\fItypePtr\fR,
+ Tk_ImageMaster \fImaster\fR,
+ ClientData *\fImasterDataPtr\fR);
+.CE
+Legacy programs and libraries dating from those days may still
+contain code that defines extended Tk image types using the old
+interface. The Tk header file will still support this legacy
+interface if the code is compiled with the macro \fBUSE_OLD_IMAGE\fR
+defined.
+.PP
+When the \fBUSE_OLD_IMAGE\fR legacy support is enabled, you may
+see the routine \fBTk_InitImageArgs\fR in use. This was a migration
+tool used to create stub-enabled extensions that could be loaded
+into interps containing all versions of Tk 8.1 and later. Tk 8.5 no longer
+provides this routine, but uses a macro to convert any attempted
+calls of this routine into an empty comment. Any stub-enabled
+extension providing an extended image type via the legacy interface
+that is compiled against Tk 8.5 headers and linked against the
+Tk 8.5 stub library will produce a file that can be loaded only
+into interps with Tk 8.5 or later; that is, the normal stub-compatibility
+rules. If a developer needs to generate from such code a file
+that is loadable into interps with Tk 8.4 or earlier, they must
+use Tk 8.4 headers and stub libraries to do so.
+.PP
+Any new code written today should not make use of the legacy
+interfaces. Expect their support to go away in Tk 9.
+.SH "SEE ALSO"
+Tk_ImageChanged, Tk_GetImage, Tk_FreeImage, Tk_RedrawImage, Tk_SizeOfImage
+.SH KEYWORDS
+image manager, image type, instance, master
diff --git a/tk8.6/doc/CrtItemType.3 b/tk8.6/doc/CrtItemType.3
new file mode 100644
index 0000000..005d2e2
--- /dev/null
+++ b/tk8.6/doc/CrtItemType.3
@@ -0,0 +1,695 @@
+'\"
+'\" Copyright (c) 1994-1995 Sun Microsystems, Inc.
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH Tk_CreateItemType 3 4.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_CreateItemType, Tk_GetItemTypes \- define new kind of canvas item
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+\fBTk_CreateItemType\fR(\fItypePtr\fR)
+.sp
+Tk_ItemType *
+\fBTk_GetItemTypes\fR()
+.SH ARGUMENTS
+.AS Tk_ItemType *typePtr
+.AP Tk_ItemType *typePtr in
+Structure that defines the new type of canvas item.
+.BE
+.SH INTRODUCTION
+.PP
+\fBTk_CreateItemType\fR is invoked to define a new kind of canvas item
+described by the \fItypePtr\fR argument.
+An item type corresponds to a particular value of the \fItype\fR
+argument to the \fBcreate\fR widget command for canvases, and
+the code that implements a canvas item type is called a \fItype manager\fR.
+Tk defines several built-in item types, such as \fBrectangle\fR
+and \fBtext\fR and \fBimage\fR, but \fBTk_CreateItemType\fR
+allows additional item types to be defined.
+Once \fBTk_CreateItemType\fR returns, the new item type may be used
+in new or existing canvas widgets just like the built-in item
+types.
+.PP
+\fBTk_GetItemTypes\fR returns a pointer to the first in the list
+of all item types currently defined for canvases.
+The entries in the list are linked together through their
+\fInextPtr\fR fields, with the end of the list marked by a
+NULL \fInextPtr\fR.
+.PP
+You may find it easier to understand the rest of this manual entry
+by looking at the code for an existing canvas item type such as
+bitmap (in the file tkCanvBmap.c) or text (tkCanvText.c).
+The easiest way to create a new type manager is to copy the code
+for an existing type and modify it for the new type.
+.PP
+Tk provides a number of utility procedures for the use of canvas
+type managers, such as \fBTk_CanvasCoords\fR and \fBTk_CanvasPsColor\fR;
+these are described in separate manual entries.
+.SH "DATA STRUCTURES"
+.PP
+A type manager consists of a collection of procedures that provide a
+standard set of operations on items of that type.
+The type manager deals with three kinds of data
+structures.
+The first data structure is a Tk_ItemType; it contains
+information such as the name of the type and pointers to
+the standard procedures implemented by the type manager:
+.PP
+.CS
+typedef struct Tk_ItemType {
+ const char *\fIname\fR;
+ int \fIitemSize\fR;
+ Tk_ItemCreateProc *\fIcreateProc\fR;
+ const Tk_ConfigSpec *\fIconfigSpecs\fR;
+ Tk_ItemConfigureProc *\fIconfigProc\fR;
+ Tk_ItemCoordProc *\fIcoordProc\fR;
+ Tk_ItemDeleteProc *\fIdeleteProc\fR;
+ Tk_ItemDisplayProc *\fIdisplayProc\fR;
+ int \fIalwaysRedraw\fR;
+ Tk_ItemPointProc *\fIpointProc\fR;
+ Tk_ItemAreaProc *\fIareaProc\fR;
+ Tk_ItemPostscriptProc *\fIpostscriptProc\fR;
+ Tk_ItemScaleProc *\fIscaleProc\fR;
+ Tk_ItemTranslateProc *\fItranslateProc\fR;
+ Tk_ItemIndexProc *\fIindexProc\fR;
+ Tk_ItemCursorProc *\fIicursorProc\fR;
+ Tk_ItemSelectionProc *\fIselectionProc\fR;
+ Tk_ItemInsertProc *\fIinsertProc\fR;
+ Tk_ItemDCharsProc *\fIdCharsProc\fR;
+ Tk_ItemType *\fInextPtr\fR;
+} \fBTk_ItemType\fR;
+.CE
+.PP
+The fields of a Tk_ItemType structure are described in more detail
+later in this manual entry.
+When \fBTk_CreateItemType\fR is called, its \fItypePtr\fR
+argument must point to a structure with all of the fields initialized
+except \fInextPtr\fR, which Tk sets to link all the types together
+into a list.
+The structure must be in permanent memory (either statically
+allocated or dynamically allocated but never freed); Tk retains
+a pointer to this structure.
+.PP
+The second data structure manipulated by a type manager is an
+\fIitem record\fR.
+For each item in a canvas there exists one item record.
+All of the items of a given type generally have item records with
+the same structure, but different types usually have different
+formats for their item records.
+The first part of each item record is a header with a standard structure
+defined by Tk via the type Tk_Item; the rest of the item
+record is defined by the type manager.
+A type manager must define its item records with a Tk_Item as
+the first field.
+For example, the item record for bitmap items is defined as follows:
+.PP
+.CS
+typedef struct BitmapItem {
+ Tk_Item \fIheader\fR;
+ double \fIx\fR, \fIy\fR;
+ Tk_Anchor \fIanchor\fR;
+ Pixmap \fIbitmap\fR;
+ XColor *\fIfgColor\fR;
+ XColor *\fIbgColor\fR;
+ GC \fIgc\fR;
+} \fBBitmapItem\fR;
+.CE
+.PP
+The \fIheader\fR substructure contains information used by Tk
+to manage the item, such as its identifier, its tags, its type,
+and its bounding box.
+The fields starting with \fIx\fR belong to the type manager:
+Tk will never read or write them.
+The type manager should not need to read or write any of the
+fields in the header except for four fields
+whose names are \fIx1\fR, \fIy1\fR, \fIx2\fR, and \fIy2\fR.
+These fields give a bounding box for the items using integer
+canvas coordinates: the item should not cover any pixels
+with x-coordinate lower than \fIx1\fR or y-coordinate
+lower than \fIy1\fR, nor should it cover any pixels with
+x-coordinate greater than or equal to \fIx2\fR or y-coordinate
+greater than or equal to \fIy2\fR.
+It is up to the type manager to keep the bounding box up to
+date as the item is moved and reconfigured.
+.PP
+Whenever Tk calls a procedure in a type manager it passes in a pointer
+to an item record.
+The argument is always passed as a pointer to a Tk_Item; the type
+manager will typically cast this into a pointer to its own specific
+type, such as BitmapItem.
+.PP
+The third data structure used by type managers has type
+Tk_Canvas; it serves as an opaque handle for the canvas widget
+as a whole.
+Type managers need not know anything about the contents of this
+structure.
+A Tk_Canvas handle is typically passed in to the
+procedures of a type manager, and the type manager can pass the
+handle back to library procedures such as Tk_CanvasTkwin
+to fetch information about the canvas.
+.SH "TK_ITEMTYPE FIELDS"
+.SS NAME
+.PP
+This section and the ones that follow describe each of the fields
+in a Tk_ItemType structure in detail.
+The \fIname\fR field provides a string name for the item type.
+Once \fBTk_CreateImageType\fR returns, this name may be used
+in \fBcreate\fR widget commands to create items of the new
+type.
+If there already existed an item type by this name then
+the new item type replaces the old one.
+.SS "FLAGS (IN ALWAYSREDRAW)"
+.PP
+The \fItypePtr\->alwaysRedraw\fR field (so named for historic reasons)
+contains a collection of flag bits that modify how the canvas core interacts
+with the item. The following bits are defined:
+.TP
+\fB1\fR
+.
+Indicates that the item should always be redrawn when any part of the canvas
+is redrawn, rather than only when the bounding box of the item overlaps the
+area being redrawn. This is used by window items, for example, which need to
+unmap subwindows that are not on the screen.
+.TP
+\fBTK_CONFIG_OBJS\fR
+.
+Indicates that operations which would otherwise take a string (or array of
+strings) actually take a Tcl_Obj reference (or an array of such references).
+The operations to which this applies are the \fIconfigProc\fR, the
+\fIcoordProc\fR, the \fIcreateProc\fR, the \fIindexProc\fR and the
+\fIinsertProc\fR.
+.TP
+\fBTK_MOVABLE_POINTS\fR
+.VS 8.6
+Indicates that the item supports the \fIdCharsProc\fR, \fIindexProc\fR and
+\fIinsertProc\fR with the same semantics as Tk's built-in line and polygon
+types, and that hence individual coordinate points can be moved. Must not be
+set if any of the above methods is NULL.
+.VE 8.6
+.SS ITEMSIZE
+.PP
+\fItypePtr\->itemSize\fR gives the size in bytes of item records
+of this type, including the Tk_Item header.
+Tk uses this size to allocate memory space for items of the type.
+All of the item records for a given type must have the same size.
+If variable length fields are needed for an item (such as a list
+of points for a polygon), the type manager can allocate a separate
+object of variable length and keep a pointer to it in the item record.
+.SS CREATEPROC
+.PP
+\fItypePtr\->createProc\fR points to a procedure for
+Tk to call whenever a new item of this type is created.
+\fItypePtr\->createProc\fR must match the following prototype:
+.PP
+.CS
+typedef int \fBTk_ItemCreateProc\fR(
+ Tcl_Interp *\fIinterp\fR,
+ Tk_Canvas \fIcanvas\fR,
+ Tk_Item *\fIitemPtr\fR,
+ int \fIobjc\fR,
+ Tcl_Obj *const \fIobjv\fR[]);
+.CE
+.PP
+The \fIinterp\fR argument is the interpreter in which the canvas's
+\fBcreate\fR widget command was invoked, and \fIcanvas\fR is a
+handle for the canvas widget.
+\fIitemPtr\fR is a pointer to a newly-allocated item of
+size \fItypePtr\->itemSize\fR.
+Tk has already initialized the item's header (the first
+\fBsizeof(Tk_ItemType)\fR bytes).
+The \fIobjc\fR and \fIobjv\fR arguments describe all of the
+arguments to the \fBcreate\fR command after the \fItype\fR
+argument.
+Note that if \fBTK_CONFIG_OBJS\fR is not set in the
+\fItypePtr\->alwaysRedraw\fR field, the \fIobjv\fR parameter will actually
+contain a pointer to an array of constant strings.
+For example, in the widget command:
+.PP
+.CS
+\fB\&.c create rectangle 10 20 50 50 \-fill black\fR
+.CE
+.PP
+\fIobjc\fR will be \fB6\fR and \fIobjv\fR[0] will contain the
+integer object \fB10\fR.
+.PP
+\fIcreateProc\fR should use \fIobjc\fR and \fIobjv\fR to initialize
+the type-specific parts of the item record and set an initial value
+for the bounding box in the item's header.
+It should return a standard Tcl completion code and leave an
+error message in the interpreter result if an error occurs.
+If an error occurs Tk will free the item record, so \fIcreateProc\fR
+must be sure to leave the item record in a clean state if it returns an error
+(e.g., it must free any additional memory that it allocated for
+the item).
+.SS CONFIGSPECS
+.PP
+Each type manager must provide a standard table describing its
+configuration options, in a form suitable for use with
+\fBTk_ConfigureWidget\fR.
+This table will normally be used by \fItypePtr\->createProc\fR
+and \fItypePtr\->configProc\fR, but Tk also uses it directly
+to retrieve option information in the \fBitemcget\fR and
+\fBitemconfigure\fR widget commands.
+\fItypePtr\->configSpecs\fR must point to the configuration table
+for this type.
+Note: Tk provides a custom option type \fBtk_CanvasTagsOption\fR
+for implementing the \fB\-tags\fR option; see an existing type
+manager for an example of how to use it in \fIconfigSpecs\fR.
+.SS CONFIGPROC
+.PP
+\fItypePtr\->configProc\fR is called by Tk whenever the
+\fBitemconfigure\fR widget command is invoked to change the
+configuration options for a canvas item.
+This procedure must match the following prototype:
+.PP
+.CS
+typedef int \fBTk_ItemConfigureProc\fR(
+ Tcl_Interp *\fIinterp\fR,
+ Tk_Canvas \fIcanvas\fR,
+ Tk_Item *\fIitemPtr\fR,
+ int \fIobjc\fR,
+ Tcl_Obj *const \fIobjv\fR[],
+ int \fIflags\fR);
+.CE
+.PP
+The \fIinterp\fR argument identifies the interpreter in which the
+widget command was invoked, \fIcanvas\fR is a handle for the canvas
+widget, and \fIitemPtr\fR is a pointer to the item being configured.
+\fIobjc\fR and \fIobjv\fR contain the configuration options.
+Note that if \fBTK_CONFIG_OBJS\fR is not set in the
+\fItypePtr\->alwaysRedraw\fR field, the \fIobjv\fR parameter will actually
+contain a pointer to an array of constant strings.
+For example, if the following command is invoked:
+.PP
+.CS
+\fB\&.c itemconfigure 2 \-fill red \-outline black\fR
+.CE
+.PP
+\fIobjc\fR is \fB4\fR and \fIobjv\fR contains the string objects \fB\-fill\fR
+through \fBblack\fR.
+\fIobjc\fR will always be an even value.
+The \fIflags\fR argument contains flags to pass to \fBTk_ConfigureWidget\fR;
+currently this value is always \fBTK_CONFIG_ARGV_ONLY\fR when Tk
+invokes \fItypePtr\->configProc\fR, but the type manager's \fIcreateProc\fR
+procedure will usually invoke \fIconfigProc\fR with different flag values.
+.PP
+\fItypePtr\->configProc\fR returns a standard Tcl completion code and
+leaves an error message in the interpreter result if an error occurs.
+It must update the item's bounding box to reflect the new configuration
+options.
+.SS COORDPROC
+.PP
+\fItypePtr\->coordProc\fR is invoked by Tk to implement the \fBcoords\fR
+widget command for an item.
+It must match the following prototype:
+.PP
+.CS
+typedef int \fBTk_ItemCoordProc\fR(
+ Tcl_Interp *\fIinterp\fR,
+ Tk_Canvas \fIcanvas\fR,
+ Tk_Item *\fIitemPtr\fR,
+ int \fIobjc\fR,
+ Tcl_Obj *const \fIobjv\fR[]);
+.CE
+.PP
+The arguments \fIinterp\fR, \fIcanvas\fR, and \fIitemPtr\fR
+all have the standard meanings, and \fIobjc\fR and \fIobjv\fR
+describe the coordinate arguments.
+Note that if \fBTK_CONFIG_OBJS\fR is not set in the
+\fItypePtr\->alwaysRedraw\fR field, the \fIobjv\fR parameter will actually
+contain a pointer to an array of constant strings.
+For example, if the following widget command is invoked:
+.PP
+.CS
+\fB\&.c coords 2 30 90\fR
+.CE
+.PP
+\fIobjc\fR will be \fB2\fR and \fBobjv\fR will contain the integer objects
+\fB30\fR and \fB90\fR.
+.PP
+The \fIcoordProc\fR procedure should process the new coordinates,
+update the item appropriately (e.g., it must reset the bounding
+box in the item's header), and return a standard Tcl completion
+code.
+If an error occurs, \fIcoordProc\fR must leave an error message in
+the interpreter result.
+.SS DELETEPROC
+.PP
+\fItypePtr\->deleteProc\fR is invoked by Tk to delete an item
+and free any resources allocated to it.
+It must match the following prototype:
+.PP
+.CS
+typedef void \fBTk_ItemDeleteProc\fR(
+ Tk_Canvas \fIcanvas\fR,
+ Tk_Item *\fIitemPtr\fR,
+ Display *\fIdisplay\fR);
+.CE
+.PP
+The \fIcanvas\fR and \fIitemPtr\fR arguments have the usual
+interpretations, and \fIdisplay\fR identifies the X display containing
+the canvas.
+\fIdeleteProc\fR must free up any resources allocated for the item,
+so that Tk can free the item record.
+\fIdeleteProc\fR should not actually free the item record; this will
+be done by Tk when \fIdeleteProc\fR returns.
+.SS "DISPLAYPROC"
+.PP
+\fItypePtr\->displayProc\fR is invoked by Tk to redraw an item
+on the screen.
+It must match the following prototype:
+.PP
+.CS
+typedef void \fBTk_ItemDisplayProc\fR(
+ Tk_Canvas \fIcanvas\fR,
+ Tk_Item *\fIitemPtr\fR,
+ Display *\fIdisplay\fR,
+ Drawable \fIdst\fR,
+ int \fIx\fR,
+ int \fIy\fR,
+ int \fIwidth\fR,
+ int \fIheight\fR);
+.CE
+.PP
+The \fIcanvas\fR and \fIitemPtr\fR arguments have the usual meaning.
+\fIdisplay\fR identifies the display containing the canvas, and
+\fIdst\fR specifies a drawable in which the item should be rendered;
+typically this is an off-screen pixmap, which Tk will copy into
+the canvas's window once all relevant items have been drawn.
+\fIx\fR, \fIy\fR, \fIwidth\fR, and \fIheight\fR specify a rectangular
+region in canvas coordinates, which is the area to be redrawn;
+only information that overlaps this area needs to be redrawn.
+Tk will not call \fIdisplayProc\fR unless the item's bounding box
+overlaps the redraw area, but the type manager may wish to use
+the redraw area to optimize the redisplay of the item.
+.PP
+Because of scrolling and the use of off-screen pixmaps for
+double-buffered redisplay, the item's coordinates in \fIdst\fR
+will not necessarily be the same as those in the canvas.
+\fIdisplayProc\fR should call \fBTk_CanvasDrawableCoords\fR
+to transform coordinates from those of the canvas to those
+of \fIdst\fR.
+.PP
+Normally an item's \fIdisplayProc\fR is only invoked if the item
+overlaps the area being displayed.
+However, if bit zero of \fItypePtr\->alwaysRedraw\fR is 1,
+(i.e.\|
+.QW "\fItypePtr\->alwaysRedraw & 1 == 1\fR" )
+then \fIdisplayProc\fR is invoked during every redisplay operation,
+even if the item does not overlap the area of redisplay; this is useful for
+cases such as window items, where the subwindow needs to be unmapped when it
+is off the screen.
+.SS POINTPROC
+.PP
+\fItypePtr\->pointProc\fR is invoked by Tk to find out how close
+a given point is to a canvas item.
+Tk uses this procedure for purposes such as locating the item
+under the mouse or finding the closest item to a given point.
+The procedure must match the following prototype:
+.PP
+.CS
+typedef double \fBTk_ItemPointProc\fR(
+ Tk_Canvas \fIcanvas\fR,
+ Tk_Item *\fIitemPtr\fR,
+ double *\fIpointPtr\fR);
+.CE
+.PP
+\fIcanvas\fR and \fIitemPtr\fR have the usual meaning.
+\fIpointPtr\fR points to an array of two numbers giving
+the x and y coordinates of a point.
+\fIpointProc\fR must return a real value giving the distance
+from the point to the item, or 0 if the point lies inside
+the item.
+.SS AREAPROC
+.PP
+\fItypePtr\->areaProc\fR is invoked by Tk to find out the relationship
+between an item and a rectangular area.
+It must match the following prototype:
+.PP
+.CS
+typedef int \fBTk_ItemAreaProc\fR(
+ Tk_Canvas \fIcanvas\fR,
+ Tk_Item *\fIitemPtr\fR,
+ double *\fIrectPtr\fR);
+.CE
+.PP
+\fIcanvas\fR and \fIitemPtr\fR have the usual meaning.
+\fIrectPtr\fR points to an array of four real numbers;
+the first two give the x and y coordinates of the upper left
+corner of a rectangle, and the second two give the x and y
+coordinates of the lower right corner.
+\fIareaProc\fR must return \-1 if the item lies entirely outside
+the given area, 0 if it lies partially inside and partially
+outside the area, and 1 if it lies entirely inside the area.
+.SS POSTSCRIPTPROC
+.PP
+\fItypePtr\->postscriptProc\fR is invoked by Tk to generate
+Postscript for an item during the \fBpostscript\fR widget command.
+If the type manager is not capable of generating Postscript then
+\fItypePtr\->postscriptProc\fR should be NULL.
+The procedure must match the following prototype:
+.PP
+.CS
+typedef int \fBTk_ItemPostscriptProc\fR(
+ Tcl_Interp *\fIinterp\fR,
+ Tk_Canvas \fIcanvas\fR,
+ Tk_Item *\fIitemPtr\fR,
+ int \fIprepass\fR);
+.CE
+.PP
+The \fIinterp\fR, \fIcanvas\fR, and \fIitemPtr\fR arguments all have
+standard meanings; \fIprepass\fR will be described below.
+If \fIpostscriptProc\fR completes successfully, it should append
+Postscript for the item to the information in the interpreter result
+(e.g. by calling \fBTcl_AppendResult\fR, not \fBTcl_SetResult\fR)
+and return \fBTCL_OK\fR.
+If an error occurs, \fIpostscriptProc\fR should clear the result
+and replace its contents with an error message; then it should
+return \fBTCL_ERROR\fR.
+.PP
+Tk provides a collection of utility procedures to simplify
+\fIpostscriptProc\fR.
+For example, \fBTk_CanvasPsColor\fR will generate Postscript to set
+the current color to a given Tk color and \fBTk_CanvasPsFont\fR will
+set up font information.
+When generating Postscript, the type manager is free to change the
+graphics state of the Postscript interpreter, since Tk places
+\fBgsave\fR and \fBgrestore\fR commands around the Postscript for
+the item.
+The type manager can use canvas x coordinates directly in its Postscript,
+but it must call \fBTk_CanvasPsY\fR to convert y coordinates from
+the space of the canvas (where the origin is at the
+upper left) to the space of Postscript (where the origin is at the
+lower left).
+.PP
+In order to generate Postscript that complies with the Adobe Document
+Structuring Conventions, Tk actually generates Postscript in two passes.
+It calls each item's \fIpostscriptProc\fR in each pass.
+The only purpose of the first pass is to collect font information
+(which is done by \fBTk_CanvasPsFont\fR); the actual Postscript is
+discarded.
+Tk sets the \fIprepass\fR argument to \fIpostscriptProc\fR to 1
+during the first pass; the type manager can use \fIprepass\fR to skip
+all Postscript generation except for calls to \fBTk_CanvasPsFont\fR.
+During the second pass \fIprepass\fR will be 0, so the type manager
+must generate complete Postscript.
+.SS SCALEPROC
+.PP
+\fItypePtr\->scaleProc\fR is invoked by Tk to rescale a canvas item
+during the \fBscale\fR widget command.
+The procedure must match the following prototype:
+.PP
+.CS
+typedef void \fBTk_ItemScaleProc\fR(
+ Tk_Canvas \fIcanvas\fR,
+ Tk_Item *\fIitemPtr\fR,
+ double \fIoriginX\fR,
+ double \fIoriginY\fR,
+ double \fIscaleX\fR,
+ double \fIscaleY\fR);
+.CE
+.PP
+The \fIcanvas\fR and \fIitemPtr\fR arguments have the usual meaning.
+\fIoriginX\fR and \fIoriginY\fR specify an origin relative to which
+the item is to be scaled, and \fIscaleX\fR and \fIscaleY\fR give the
+x and y scale factors.
+The item should adjust its coordinates so that a point in the item
+that used to have coordinates \fIx\fR and \fIy\fR will have new
+coordinates \fIx\(fm\fR and \fIy\(fm\fR, where
+.PP
+.CS
+\fIx\(fm\fR = \fIoriginX\fR + \fIscaleX\fR \(mu (\fIx\fR \(mi \fIoriginX\fR)
+\fIy\(fm\fR = \fIoriginY\fR + \fIscaleY\fR \(mu (\fIy\fR \(mi \fIoriginY\fR)
+.CE
+.PP
+\fIscaleProc\fR must also update the bounding box in the item's
+header.
+.SS TRANSLATEPROC
+.PP
+\fItypePtr\->translateProc\fR is invoked by Tk to translate a canvas item
+during the \fBmove\fR widget command.
+The procedure must match the following prototype:
+.PP
+.CS
+typedef void \fBTk_ItemTranslateProc\fR(
+ Tk_Canvas \fIcanvas\fR,
+ Tk_Item *\fIitemPtr\fR,
+ double \fIdeltaX\fR,
+ double \fIdeltaY\fR);
+.CE
+.PP
+The \fIcanvas\fR and \fIitemPtr\fR arguments have the usual meaning,
+and \fIdeltaX\fR and \fIdeltaY\fR give the amounts that should be
+added to each x and y coordinate within the item.
+The type manager should adjust the item's coordinates and
+update the bounding box in the item's header.
+.SS INDEXPROC
+.PP
+\fItypePtr\->indexProc\fR is invoked by Tk to translate a string
+index specification into a numerical index, for example during the
+\fBindex\fR widget command.
+It is only relevant for item types that support indexable text or coordinates;
+\fItypePtr\->indexProc\fR may be specified as NULL for non-textual
+item types if they do not support detailed coordinate addressing.
+The procedure must match the following prototype:
+.PP
+.CS
+typedef int \fBTk_ItemIndexProc\fR(
+ Tcl_Interp *\fIinterp\fR,
+ Tk_Canvas \fIcanvas\fR,
+ Tk_Item *\fIitemPtr\fR,
+ Tcl_Obj *\fIindexObj\fR,
+ int *\fIindexPtr\fR);
+.CE
+.PP
+The \fIinterp\fR, \fIcanvas\fR, and \fIitemPtr\fR arguments all
+have the usual meaning.
+\fIindexObj\fR contains a textual description of an index,
+and \fIindexPtr\fR points to an integer value that should be
+filled in with a numerical index.
+Note that if \fBTK_CONFIG_OBJS\fR is not set in the
+\fItypePtr\->alwaysRedraw\fR field, the \fIindexObj\fR parameter will
+actually contain a pointer to a constant string.
+It is up to the type manager to decide what forms of index
+are supported (e.g., numbers, \fBinsert\fR, \fBsel.first\fR,
+\fBend\fR, etc.).
+\fIindexProc\fR should return a Tcl completion code and set
+the interpreter result in the event of an error.
+.SS ICURSORPROC
+.PP
+\fItypePtr\->icursorProc\fR is invoked by Tk during
+the \fBicursor\fR widget command to set the position of the
+insertion cursor in a textual item.
+It is only relevant for item types that support an insertion cursor;
+\fItypePtr\->icursorProc\fR may be specified as NULL for item types
+that do not support an insertion cursor.
+The procedure must match the following prototype:
+.PP
+.CS
+typedef void \fBTk_ItemCursorProc\fR(
+ Tk_Canvas \fIcanvas\fR,
+ Tk_Item *\fIitemPtr\fR,
+ int \fIindex\fR);
+.CE
+.PP
+\fIcanvas\fR and \fIitemPtr\fR have the usual meanings, and
+\fIindex\fR is an index into the item's text, as returned by a
+previous call to \fItypePtr\->insertProc\fR.
+The type manager should position the insertion cursor in the
+item just before the character given by \fIindex\fR.
+Whether or not to actually display the insertion cursor is
+determined by other information provided by \fBTk_CanvasGetTextInfo\fR.
+.SS SELECTIONPROC
+.PP
+\fItypePtr\->selectionProc\fR is invoked by Tk during selection
+retrievals; it must return part or all of the selected text in
+the item (if any).
+It is only relevant for item types that support text;
+\fItypePtr\->selectionProc\fR may be specified as NULL for non-textual
+item types.
+The procedure must match the following prototype:
+.PP
+.CS
+typedef int \fBTk_ItemSelectionProc\fR(
+ Tk_Canvas \fIcanvas\fR,
+ Tk_Item *\fIitemPtr\fR,
+ int \fIoffset\fR,
+ char *\fIbuffer\fR,
+ int \fImaxBytes\fR);
+.CE
+.PP
+\fIcanvas\fR and \fIitemPtr\fR have the usual meanings.
+\fIoffset\fR is an offset in bytes into the selection where 0 refers
+to the first byte of the selection; it identifies
+the first character that is to be returned in this call.
+\fIbuffer\fR points to an area of memory in which to store the
+requested bytes, and \fImaxBytes\fR specifies the maximum number
+of bytes to return.
+\fIselectionProc\fR should extract up to \fImaxBytes\fR characters
+from the selection and copy them to \fImaxBytes\fR; it should
+return a count of the number of bytes actually copied, which may
+be less than \fImaxBytes\fR if there are not \fIoffset+maxBytes\fR bytes
+in the selection.
+.SS INSERTPROC
+.PP
+\fItypePtr\->insertProc\fR is invoked by Tk during
+the \fBinsert\fR widget command to insert new text or coordinates into a
+canvas item.
+It is only relevant for item types that support the \fBinsert\fR method;
+\fItypePtr\->insertProc\fR may be specified as NULL for other
+item types.
+The procedure must match the following prototype:
+.PP
+.CS
+typedef void \fBTk_ItemInsertProc\fR(
+ Tk_Canvas \fIcanvas\fR,
+ Tk_Item *\fIitemPtr\fR,
+ int \fIindex\fR,
+ Tcl_Obj *\fIobj\fR);
+.CE
+.PP
+\fIcanvas\fR and \fIitemPtr\fR have the usual meanings.
+\fIindex\fR is an index into the item's text, as returned by a
+previous call to \fItypePtr\->insertProc\fR, and \fIobj\fR
+contains new text to insert just before the character given
+by \fIindex\fR.
+Note that if \fBTK_CONFIG_OBJS\fR is not set in the
+\fItypePtr\->alwaysRedraw\fR field, the \fIobj\fR parameter will
+actually contain a pointer to a constant string to be inserted.
+If the item supports modification of the coordinates list by this
+.PP
+The type manager should insert the text and recompute the bounding
+box in the item's header.
+.SS DCHARSPROC
+.PP
+\fItypePtr\->dCharsProc\fR is invoked by Tk during the \fBdchars\fR
+widget command to delete a range of text from a canvas item or a range of
+coordinates from a pathed item.
+It is only relevant for item types that support text;
+\fItypePtr\->dCharsProc\fR may be specified as NULL for non-textual
+item types that do not want to support coordinate deletion.
+The procedure must match the following prototype:
+.PP
+.CS
+typedef void \fBTk_ItemDCharsProc\fR(
+ Tk_Canvas \fIcanvas\fR,
+ Tk_Item *\fIitemPtr\fR,
+ int \fIfirst\fR,
+ int \fIlast\fR);
+.CE
+.PP
+\fIcanvas\fR and \fIitemPtr\fR have the usual meanings.
+\fIfirst\fR and \fIlast\fR give the indices of the first and last bytes
+to be deleted, as returned by previous calls to \fItypePtr\->indexProc\fR.
+The type manager should delete the specified characters and update
+the bounding box in the item's header.
+.SH "SEE ALSO"
+Tk_CanvasPsY, Tk_CanvasTextInfo, Tk_CanvasTkwin
+.SH KEYWORDS
+canvas, focus, item type, selection, type manager
diff --git a/tk8.6/doc/CrtPhImgFmt.3 b/tk8.6/doc/CrtPhImgFmt.3
new file mode 100644
index 0000000..c7e792a
--- /dev/null
+++ b/tk8.6/doc/CrtPhImgFmt.3
@@ -0,0 +1,270 @@
+'\"
+'\" Copyright (c) 1994 The Australian National University
+'\" Copyright (c) 1994-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.
+'\"
+'\" Author: Paul Mackerras (paulus@cs.anu.edu.au),
+'\" Department of Computer Science,
+'\" Australian National University.
+'\"
+.TH Tk_CreatePhotoImageFormat 3 8.5 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_CreatePhotoImageFormat \- define new file format for photo images
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+\fBTk_CreatePhotoImageFormat\fR(\fIformatPtr\fR)
+.SH ARGUMENTS
+.AS "const Tk_PhotoImageFormat" *formatPtr
+.AP "const Tk_PhotoImageFormat" *formatPtr in
+Structure that defines the new file format.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_CreatePhotoImageFormat\fR is invoked to define a new file format
+for image data for use with photo images. The code that implements an
+image file format is called an image file format handler, or
+handler for short. The photo image code
+maintains a list of handlers that can be used to read and
+write data to or from a file. Some handlers may also
+support reading image data from a string or converting image data to a
+string format.
+The user can specify which handler to use with the \fB\-format\fR
+image configuration option or the \fB\-format\fR option to the
+\fBread\fR and \fBwrite\fR photo image subcommands.
+.PP
+An image file format handler consists of a collection of procedures
+plus a Tk_PhotoImageFormat structure, which contains the name of the
+image file format and pointers to six procedures provided by the
+handler to deal with files and strings in this format. The
+Tk_PhotoImageFormat structure contains the following fields:
+.CS
+typedef struct Tk_PhotoImageFormat {
+ const char *\fIname\fR;
+ Tk_ImageFileMatchProc *\fIfileMatchProc\fR;
+ Tk_ImageStringMatchProc *\fIstringMatchProc\fR;
+ Tk_ImageFileReadProc *\fIfileReadProc\fR;
+ Tk_ImageStringReadProc *\fIstringReadProc\fR;
+ Tk_ImageFileWriteProc *\fIfileWriteProc\fR;
+ Tk_ImageStringWriteProc *\fIstringWriteProc\fR;
+} \fBTk_PhotoImageFormat\fR;
+.CE
+.PP
+The handler need not provide implementations of all six procedures.
+For example, the procedures that handle string data would not be
+provided for a format in which the image data are stored in binary,
+and could therefore contain null characters. If any procedure is not
+implemented, the corresponding pointer in the Tk_PhotoImageFormat
+structure should be set to NULL. The handler must provide the
+\fIfileMatchProc\fR procedure if it provides the \fIfileReadProc\fR
+procedure, and the \fIstringMatchProc\fR procedure if it provides the
+\fIstringReadProc\fR procedure.
+.SS NAME
+.PP
+\fIformatPtr->name\fR provides a name for the image type.
+Once \fBTk_CreatePhotoImageFormat\fR returns, this name may be used
+in the \fB\-format\fR photo image configuration and subcommand option.
+The manual page for the photo image (photo(n)) describes how image
+file formats are chosen based on their names and the value given to
+the \fB\-format\fR option. The first character of \fIformatPtr->name\fR
+must not be an uppercase character from the ASCII character set
+(that is, one of the characters \fBA\fR-\fBZ\fR). Such names are used
+only for legacy interface support (see below).
+.SS FILEMATCHPROC
+.PP
+\fIformatPtr->fileMatchProc\fR provides the address of a procedure for
+Tk to call when it is searching for an image file format handler
+suitable for reading data in a given file.
+\fIformatPtr->fileMatchProc\fR must match the following prototype:
+.CS
+typedef int \fBTk_ImageFileMatchProc\fR(
+ Tcl_Channel \fIchan\fR,
+ const char *\fIfileName\fR,
+ Tcl_Obj *\fIformat\fR,
+ int *\fIwidthPtr\fR,
+ int *\fIheightPtr\fR,
+ Tcl_Interp *\fIinterp\fR);
+.CE
+The \fIfileName\fR argument is the name of the file containing the
+image data, which is open for reading as \fIchan\fR. The
+\fIformat\fR argument contains the value given for the
+\fB\-format\fR option, or NULL if the option was not specified.
+If the data in the file appears to be in the format supported by this
+handler, the \fIformatPtr->fileMatchProc\fR procedure should store the
+width and height of the image in *\fIwidthPtr\fR and *\fIheightPtr\fR
+respectively, and return 1. Otherwise it should return 0.
+.SS STRINGMATCHPROC
+.PP
+\fIformatPtr->stringMatchProc\fR provides the address of a procedure for
+Tk to call when it is searching for an image file format handler for
+suitable for reading data from a given string.
+\fIformatPtr->stringMatchProc\fR must match the following prototype:
+.CS
+typedef int \fBTk_ImageStringMatchProc\fR(
+ Tcl_Obj *\fIdata\fR,
+ Tcl_Obj *\fIformat\fR,
+ int *\fIwidthPtr\fR,
+ int *\fIheightPtr\fR,
+ Tcl_Interp *\fIinterp\fR);
+.CE
+The \fIdata\fR argument points to the object containing the image
+data. The \fIformat\fR argument contains the value given for
+the \fB\-format\fR option, or NULL if the option was not specified.
+If the data in the string appears to be in the format supported by
+this handler, the \fIformatPtr->stringMatchProc\fR procedure should
+store the width and height of the image in *\fIwidthPtr\fR and
+*\fIheightPtr\fR respectively, and return 1. Otherwise it should
+return 0.
+.SS FILEREADPROC
+.PP
+\fIformatPtr->fileReadProc\fR provides the address of a procedure for
+Tk to call to read data from an image file into a photo image.
+\fIformatPtr->fileReadProc\fR must match the following prototype:
+.CS
+typedef int \fBTk_ImageFileReadProc\fR(
+ Tcl_Interp *\fIinterp\fR,
+ Tcl_Channel \fIchan\fR,
+ const char *\fIfileName\fR,
+ Tcl_Obj *\fIformat\fR,
+ PhotoHandle \fIimageHandle\fR,
+ int \fIdestX\fR, int \fIdestY\fR,
+ int \fIwidth\fR, int \fIheight\fR,
+ int \fIsrcX\fR, int \fIsrcY\fR);
+.CE
+The \fIinterp\fR argument is the interpreter in which the command was
+invoked to read the image; it should be used for reporting errors.
+The image data is in the file named \fIfileName\fR, which is open for
+reading as \fIchan\fR. The \fIformat\fR argument contains the
+value given for the \fB\-format\fR option, or NULL if the option was
+not specified. The image data in the file, or a subimage of it, is to
+be read into the photo image identified by the handle
+\fIimageHandle\fR. The subimage of the data in the file is of
+dimensions \fIwidth\fR x \fIheight\fR and has its top-left corner at
+coordinates (\fIsrcX\fR,\fIsrcY\fR). It is to be stored in the photo
+image with its top-left corner at coordinates
+(\fIdestX\fR,\fIdestY\fR) using the \fBTk_PhotoPutBlock\fR procedure.
+The return value is a standard Tcl return value.
+.SS STRINGREADPROC
+.PP
+\fIformatPtr->stringReadProc\fR provides the address of a procedure for
+Tk to call to read data from a string into a photo image.
+\fIformatPtr->stringReadProc\fR must match the following prototype:
+.CS
+typedef int \fBTk_ImageStringReadProc\fR(
+ Tcl_Interp *\fIinterp\fR,
+ Tcl_Obj *\fIdata\fR,
+ Tcl_Obj *\fIformat\fR,
+ PhotoHandle \fIimageHandle\fR,
+ int \fIdestX\fR, int \fIdestY\fR,
+ int \fIwidth\fR, int \fIheight\fR,
+ int \fIsrcX\fR, int \fIsrcY\fR);
+.CE
+The \fIinterp\fR argument is the interpreter in which the command was
+invoked to read the image; it should be used for reporting errors.
+The \fIdata\fR argument points to the image data in object form.
+The \fIformat\fR argument contains the
+value given for the \fB\-format\fR option, or NULL if the option was
+not specified. The image data in the string, or a subimage of it, is to
+be read into the photo image identified by the handle
+\fIimageHandle\fR. The subimage of the data in the string is of
+dimensions \fIwidth\fR x \fIheight\fR and has its top-left corner at
+coordinates (\fIsrcX\fR,\fIsrcY\fR). It is to be stored in the photo
+image with its top-left corner at coordinates
+(\fIdestX\fR,\fIdestY\fR) using the \fBTk_PhotoPutBlock\fR procedure.
+The return value is a standard Tcl return value.
+.SS FILEWRITEPROC
+.PP
+\fIformatPtr->fileWriteProc\fR provides the address of a procedure for
+Tk to call to write data from a photo image to a file.
+\fIformatPtr->fileWriteProc\fR must match the following prototype:
+.CS
+typedef int \fBTk_ImageFileWriteProc\fR(
+ Tcl_Interp *\fIinterp\fR,
+ const char *\fIfileName\fR,
+ Tcl_Obj *\fIformat\fR,
+ Tk_PhotoImageBlock *\fIblockPtr\fR);
+.CE
+The \fIinterp\fR argument is the interpreter in which the command was
+invoked to write the image; it should be used for reporting errors.
+The image data to be written are in memory and are described by the
+Tk_PhotoImageBlock structure pointed to by \fIblockPtr\fR; see the
+manual page FindPhoto(3) for details. The \fIfileName\fR argument
+points to the string giving the name of the file in which to write the
+image data. The \fIformat\fR argument contains the
+value given for the \fB\-format\fR option, or NULL if the option was
+not specified. The format string can contain extra characters
+after the name of the format. If appropriate, the
+\fIformatPtr->fileWriteProc\fR procedure may interpret these
+characters to specify further details about the image file.
+The return value is a standard Tcl return value.
+.SS STRINGWRITEPROC
+.PP
+\fIformatPtr->stringWriteProc\fR provides the address of a procedure for
+Tk to call to translate image data from a photo image into a string.
+\fIformatPtr->stringWriteProc\fR must match the following prototype:
+.CS
+typedef int \fBTk_ImageStringWriteProc\fR(
+ Tcl_Interp *\fIinterp\fR,
+ Tcl_Obj *\fIformat\fR,
+ Tk_PhotoImageBlock *\fIblockPtr\fR);
+.CE
+The \fIinterp\fR argument is the interpreter in which the command was
+invoked to convert the image; it should be used for reporting errors.
+The image data to be converted are in memory and are described by the
+Tk_PhotoImageBlock structure pointed to by \fIblockPtr\fR; see the
+manual page FindPhoto(3) for details. The data for the string
+should be put in the interpreter \fIinterp\fR result.
+The \fIformat\fR argument contains the
+value given for the \fB\-format\fR option, or NULL if the option was
+not specified. The format string can contain extra characters
+after the name of the format. If appropriate, the
+\fIformatPtr->stringWriteProc\fR procedure may interpret these
+characters to specify further details about the image file.
+The return value is a standard Tcl return value.
+.SH "LEGACY INTERFACE SUPPORT"
+.PP
+In Tk 8.2 and earlier, the definition of all the function pointer
+types stored in fields of a \fBTk_PhotoImageFormat\fR struct were
+incompatibly different. Legacy programs and libraries dating from
+those days may still contain code that defines extended Tk photo image
+formats using the old interface. The Tk header file will still support
+this legacy interface if the code is compiled with the
+macro \fBUSE_OLD_IMAGE\fR defined. Alternatively, the legacy interfaces
+are used if the first character of \fIformatPtr->name\fR is an
+uppercase ASCII character (\fBA\fR-\fBZ\fR), and explicit casts
+are used to forgive the type mismatch. For example,
+.CS
+static Tk_PhotoImageFormat myFormat = {
+ "MyFormat",
+ (Tk_ImageFileMatchProc *) FileMatch,
+ NULL,
+ (Tk_ImageFileReadProc *) FileRead,
+ NULL,
+ NULL,
+ NULL
+};
+.CE
+would define a minimal \fBTk_PhotoImageFormat\fR that operates provide
+only file reading capability, where \fBFileMatch\fR and \fBFileRead\fR
+are written according to the legacy interfaces of Tk 8.2 or earlier.
+.PP
+Any stub-enabled extension providing an extended photo image format
+via the legacy interface enabled by the \fBUSE_OLD_IMAGE\fR macro
+that is compiled against Tk 8.5 headers and linked against the
+Tk 8.5 stub library will produce a file that can be loaded only
+into interps with Tk 8.5 or later; that is, the normal stub-compatibility
+rules. If a developer needs to generate from such code a file
+that is loadable into interps with Tk 8.4 or earlier, they must
+use Tk 8.4 headers and stub libraries to do so.
+.PP
+Any new code written today should not make use of the legacy
+interfaces. Expect their support to go away in Tk 9.
+.SH "SEE ALSO"
+Tk_FindPhoto, Tk_PhotoPutBlock
+.SH KEYWORDS
+photo image, image file
diff --git a/tk8.6/doc/CrtSelHdlr.3 b/tk8.6/doc/CrtSelHdlr.3
new file mode 100644
index 0000000..2292ccc
--- /dev/null
+++ b/tk8.6/doc/CrtSelHdlr.3
@@ -0,0 +1,116 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_CreateSelHandler 3 4.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_CreateSelHandler, Tk_DeleteSelHandler \- arrange to handle requests for a selection
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+\fBTk_CreateSelHandler\fR(\fItkwin, selection, target, proc, clientData, format\fR)
+.sp
+\fBTk_DeleteSelHandler\fR(\fItkwin, selection, target\fR)
+.SH ARGUMENTS
+.AS Tk_SelectionProc clientData
+.AP Tk_Window tkwin in
+Window for which \fIproc\fR will provide selection information.
+.AP Atom selection in
+The name of the selection for which \fIproc\fR will provide
+selection information.
+.AP Atom target in
+Form in which \fIproc\fR can provide the selection (e.g. STRING
+or FILE_NAME). Corresponds to \fItype\fR arguments in \fBselection\fR
+commands.
+.AP Tk_SelectionProc *proc in
+Procedure to invoke whenever the selection is owned by \fItkwin\fR
+and the selection contents are requested in the format given by
+\fItarget\fR.
+.AP ClientData clientData in
+Arbitrary one-word value to pass to \fIproc\fR.
+.AP Atom format in
+If the selection requestor is not in this process, \fIformat\fR determines
+the representation used to transmit the selection to its
+requestor.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_CreateSelHandler\fR arranges for a particular procedure
+(\fIproc\fR) to be called whenever \fIselection\fR is owned by
+\fItkwin\fR and the selection contents are requested in the
+form given by \fItarget\fR.
+\fITarget\fR should be one of
+the entries defined in the left column of Table 2 of the
+X Inter-Client Communication Conventions Manual (ICCCM) or
+any other form in which an application is willing to present
+the selection. The most common form is STRING.
+.PP
+\fIProc\fR should have arguments and result that match the
+type \fBTk_SelectionProc\fR:
+.CS
+typedef int \fBTk_SelectionProc\fR(
+ ClientData \fIclientData\fR,
+ int \fIoffset\fR,
+ char *\fIbuffer\fR,
+ int \fImaxBytes\fR);
+.CE
+The \fIclientData\fR parameter to \fIproc\fR is a copy of the
+\fIclientData\fR argument given to \fBTk_CreateSelHandler\fR.
+Typically, \fIclientData\fR points to a data
+structure containing application-specific information that is
+needed to retrieve the selection. \fIOffset\fR specifies an
+offset position into the selection, \fIbuffer\fR specifies a
+location at which to copy information about the selection, and
+\fImaxBytes\fR specifies the amount of space available at
+\fIbuffer\fR. \fIProc\fR should place a NULL-terminated string
+at \fIbuffer\fR containing \fImaxBytes\fR or fewer characters
+(not including the terminating NULL), and it should return a
+count of the number of non-NULL characters stored at
+\fIbuffer\fR. If the selection no longer exists (e.g. it once
+existed but the user deleted the range of characters containing
+it), then \fIproc\fR should return \-1.
+.PP
+When transferring large selections, Tk will break them up into
+smaller pieces (typically a few thousand bytes each) for more
+efficient transmission. It will do this by calling \fIproc\fR
+one or more times, using successively higher values of \fIoffset\fR
+to retrieve successive portions of the selection. If \fIproc\fR
+returns a count less than \fImaxBytes\fR it means that the entire
+remainder of the selection has been returned. If \fIproc\fR's return
+value is \fImaxBytes\fR it means there may be additional information
+in the selection, so Tk must make another call to \fIproc\fR to
+retrieve the next portion.
+.PP
+\fIProc\fR always returns selection information in the form of a
+character string. However, the ICCCM allows for information to
+be transmitted from the selection owner to the selection requestor
+in any of several formats, such as a string, an array of atoms, an
+array of integers, etc. The \fIformat\fR argument to
+\fBTk_CreateSelHandler\fR indicates what format should be used to
+transmit the selection to its requestor (see the middle column of
+Table 2 of the ICCCM for examples). If \fIformat\fR is not
+STRING, then Tk will take the value returned by \fIproc\fR and divided
+it into fields separated by white space. If \fIformat\fR is ATOM,
+then Tk will return the selection as an array of atoms, with each
+field in \fIproc\fR's result treated as the name of one atom. For
+any other value of \fIformat\fR, Tk will return the selection as an
+array of 32-bit values where each field of \fIproc\fR's result is
+treated as a number and translated to a 32-bit value. In any event,
+the \fIformat\fR atom is returned to the selection requestor along
+with the contents of the selection.
+.PP
+If \fBTk_CreateSelHandler\fR is called when there already exists a
+handler for \fIselection\fR and \fItarget\fR on \fItkwin\fR, then the
+existing handler is replaced with a new one.
+.PP
+\fBTk_DeleteSelHandler\fR removes the handler given by \fItkwin\fR,
+\fIselection\fR, and \fItarget\fR, if such a handler exists.
+If there is no such handler then it has no effect.
+.SH KEYWORDS
+format, handler, selection, target
diff --git a/tk8.6/doc/CrtWindow.3 b/tk8.6/doc/CrtWindow.3
new file mode 100644
index 0000000..b254460
--- /dev/null
+++ b/tk8.6/doc/CrtWindow.3
@@ -0,0 +1,146 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_CreateWindow 3 4.2 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_CreateWindow, Tk_CreateWindowFromPath, Tk_DestroyWindow, Tk_MakeWindowExist \- create or delete window
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+Tk_Window
+\fBTk_CreateWindow\fR(\fIinterp, parent, name, topLevScreen\fR)
+.sp
+Tk_Window
+\fBTk_CreateAnonymousWindow\fR(\fIinterp, parent, topLevScreen\fR)
+.sp
+Tk_Window
+\fBTk_CreateWindowFromPath\fR(\fIinterp, tkwin, pathName, topLevScreen\fR)
+.sp
+\fBTk_DestroyWindow\fR(\fItkwin\fR)
+.sp
+\fBTk_MakeWindowExist\fR(\fItkwin\fR)
+.SH ARGUMENTS
+.AS Tcl_Interp *topLevScreen
+.AP Tcl_Interp *interp out
+Tcl interpreter to use for error reporting. If no error occurs,
+then \fI*interp\fR is not modified.
+.AP Tk_Window parent in
+Token for the window that is to serve as the logical parent of
+the new window.
+.AP "const char" *name in
+Name to use for this window. Must be unique among all children of
+the same \fIparent\fR.
+.AP "const char" *topLevScreen in
+Has same format as \fIscreenName\fR. If NULL, then new window is
+created as an internal window. If non-NULL, new window is created as
+a top-level window on screen \fItopLevScreen\fR. If \fItopLevScreen\fR
+is an empty string
+.PQ ""
+then new window is created as top-level window of \fIparent\fR's screen.
+.AP Tk_Window tkwin in
+Token for window.
+.AP "const char" *pathName in
+Name of new window, specified as path name within application
+(e.g. \fB.a.b.c\fR).
+.BE
+.SH DESCRIPTION
+.PP
+The procedures \fBTk_CreateWindow\fR,
+\fBTk_CreateAnonymousWindow\fR, and \fBTk_CreateWindowFromPath\fR
+are used to create new windows for
+use in Tk-based applications. Each of the procedures returns a token
+that can be used to manipulate the window in other calls to the Tk
+library. If the window could not be created successfully, then NULL
+is returned and the result of interpreter \fIinterp\fR is modified to
+hold an error message.
+.PP
+Tk supports two different kinds of windows: internal
+windows and top-level windows.
+An internal window is an interior window of a Tk application, such as a
+scrollbar or menu bar or button. A top-level window is one that is
+created as a child of a screen's root window, rather than as an
+interior window, but which is logically part of some existing main
+window. Examples of top-level windows are pop-up menus and dialog boxes.
+.PP
+New windows may be created by calling
+\fBTk_CreateWindow\fR. If the \fItopLevScreen\fR argument is
+NULL, then the new window will be an internal window. If
+\fItopLevScreen\fR is non-NULL, then the new window will be a
+top-level window: \fItopLevScreen\fR indicates the name of
+a screen and the new window will be created as a child of the
+root window of \fItopLevScreen\fR. In either case Tk will
+consider the new window to be the logical child of \fIparent\fR:
+the new window's path name will reflect this fact, options may
+be specified for the new window under this assumption, and so on.
+The only difference is that new X window for a top-level window
+will not be a child of \fIparent\fR's X window. For example, a pull-down
+menu's \fIparent\fR would be the button-like window used to invoke it,
+which would in turn be a child of the menu bar window. A dialog box might
+have the application's main window as its parent.
+.PP
+\fBTk_CreateAnonymousWindow\fR differs from \fBTk_CreateWindow\fR in
+that it creates an unnamed window. This window will be manipulatable
+only using C interfaces, and will not be visible to Tcl scripts. Both
+interior windows and top-level windows may be created with
+\fBTk_CreateAnonymousWindow\fR.
+.PP
+\fBTk_CreateWindowFromPath\fR offers an alternate way of specifying
+new windows. In \fBTk_CreateWindowFromPath\fR the new
+window is specified with a token for any window in the target
+application (\fItkwin\fR), plus a path name for the new window.
+It produces the same effect as \fBTk_CreateWindow\fR and allows
+both top-level and internal windows to be created, depending on
+the value of \fItopLevScreen\fR. In calls to \fBTk_CreateWindowFromPath\fR,
+as in calls to \fBTk_CreateWindow\fR, the parent of the new window
+must exist at the time of the call, but the new window must not
+already exist.
+.PP
+The window creation procedures do not
+actually issue the command to X to create a window.
+Instead, they create a local data structure associated with
+the window and defer the creation of the X window.
+The window will actually be created by the first call to
+\fBTk_MapWindow\fR. Deferred window creation allows various
+aspects of the window (such as its size, background color,
+etc.) to be modified after its creation without incurring
+any overhead in the X server. When the window is finally
+mapped all of the window attributes can be set while creating
+the window.
+.PP
+The value returned by a window-creation procedure is not the
+X token for the window (it cannot be, since X has not been
+asked to create the window yet). Instead, it is a token
+for Tk's local data structure for the window. Most
+of the Tk library procedures take Tk_Window tokens, rather
+than X identifiers. The actual
+X window identifier can be retrieved from the local
+data structure using the \fBTk_WindowId\fR macro; see
+the manual entry for \fBTk_WindowId\fR for details.
+.PP
+\fBTk_DestroyWindow\fR deletes a window and all the data
+structures associated with it, including any event handlers
+created with \fBTk_CreateEventHandler\fR. In addition,
+\fBTk_DestroyWindow\fR will delete any children of \fItkwin\fR
+recursively (where children are defined in the Tk sense, consisting
+of all windows that were created with the given window as \fIparent\fR).
+If \fItkwin\fR is an internal window, then event
+handlers interested in destroy events
+are invoked immediately. If \fItkwin\fR is a top-level or main window,
+then the event handlers will be invoked later, after X has seen
+the request and returned an event for it.
+.PP
+If a window has been created
+but has not been mapped, so no X window exists, it is
+possible to force the creation of the X window by
+calling \fBTk_MakeWindowExist\fR. This procedure issues
+the X commands to instantiate the window given by \fItkwin\fR.
+.SH KEYWORDS
+create, deferred creation, destroy, display, internal window,
+screen, top-level window, window
diff --git a/tk8.6/doc/DeleteImg.3 b/tk8.6/doc/DeleteImg.3
new file mode 100644
index 0000000..507be72
--- /dev/null
+++ b/tk8.6/doc/DeleteImg.3
@@ -0,0 +1,31 @@
+'\"
+'\" 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.
+'\"
+.TH Tk_DeleteImage 3 4.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_DeleteImage \- Destroy an image.
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+\fBTk_DeleteImage\fR(\fIinterp, name\fR)
+.SH ARGUMENTS
+.AS Tcl_Interp *interp
+.AP Tcl_Interp *interp in
+Interpreter for which the image was created.
+.AP "const char" *name in
+Name of the image.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_DeleteImage\fR deletes the image given by \fIinterp\fR
+and \fIname\fR, if there is one. All instances of that image
+will redisplay as empty regions. If the given image does not
+exist then the procedure has no effect.
+.SH KEYWORDS
+delete image, image manager
diff --git a/tk8.6/doc/DrawFocHlt.3 b/tk8.6/doc/DrawFocHlt.3
new file mode 100644
index 0000000..e2d1578
--- /dev/null
+++ b/tk8.6/doc/DrawFocHlt.3
@@ -0,0 +1,36 @@
+'\"
+'\" 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.
+'\"
+.TH Tk_DrawFocusHighlight 3 4.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_DrawFocusHighlight \- draw the traversal highlight ring for a widget
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+\fBTk_DrawFocusHighlight(\fItkwin, gc, width, drawable\fB)\fR
+.SH ARGUMENTS
+.AS "Tcl_Interp" *joinPtr
+.AP Tk_Window tkwin in
+Window for which the highlight is being drawn. Used to retrieve
+the window's dimensions, among other things.
+.AP GC gc in
+Graphics context to use for drawing the highlight.
+.AP int width in
+Width of the highlight ring, in pixels.
+.AP Drawable drawable in
+Drawable in which to draw the highlight; usually an offscreen
+pixmap for double buffering.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_DrawFocusHighlight\fR is a utility procedure that draws the
+traversal highlight ring for a widget.
+It is typically invoked by widgets during redisplay.
+.SH KEYWORDS
+focus, traversal highlight
diff --git a/tk8.6/doc/EventHndlr.3 b/tk8.6/doc/EventHndlr.3
new file mode 100644
index 0000000..d06de86
--- /dev/null
+++ b/tk8.6/doc/EventHndlr.3
@@ -0,0 +1,75 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_CreateEventHandler 3 "" Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_CreateEventHandler, Tk_DeleteEventHandler \- associate procedure callback with an X event
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+\fBTk_CreateEventHandler\fR(\fItkwin, mask, proc, clientData\fR)
+.sp
+\fBTk_DeleteEventHandler\fR(\fItkwin, mask, proc, clientData\fR)
+.SH ARGUMENTS
+.AS "unsigned long" clientData
+.AP Tk_Window tkwin in
+Token for window in which events may occur.
+.AP "unsigned long" mask in
+Bit-mask of events (such as \fBButtonPressMask\fR)
+for which \fIproc\fR should be called.
+.AP Tk_EventProc *proc in
+Procedure to invoke whenever an event in \fImask\fR occurs
+in the window given by \fItkwin\fR.
+.AP ClientData clientData in
+Arbitrary one-word value to pass to \fIproc\fR.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_CreateEventHandler\fR arranges for \fIproc\fR to be
+invoked in the future whenever one of the event types specified
+by \fImask\fR occurs in the window specified by \fItkwin\fR.
+The callback to \fIproc\fR will be made by \fBTk_HandleEvent\fR;
+this mechanism only works in programs that dispatch events
+through \fBTk_HandleEvent\fR (or through other Tk procedures that
+call \fBTk_HandleEvent\fR, such as \fBTcl_DoOneEvent\fR or
+\fBTk_MainLoop\fR).
+.PP
+\fIProc\fR should have arguments and result that match the
+type \fBTk_EventProc\fR:
+.CS
+typedef void \fBTk_EventProc\fR(
+ ClientData \fIclientData\fR,
+ XEvent *\fIeventPtr\fR);
+.CE
+The \fIclientData\fR parameter to \fIproc\fR is a copy of the \fIclientData\fR
+argument given to \fBTk_CreateEventHandler\fR when the callback
+was created. Typically, \fIclientData\fR points to a data
+structure containing application-specific information about
+the window in which the event occurred. \fIEventPtr\fR is
+a pointer to the X event, which will be one of the ones
+specified in the \fImask\fR argument to \fBTk_CreateEventHandler\fR.
+.PP
+\fBTk_DeleteEventHandler\fR may be called to delete a
+previously-created event handler: it deletes the first handler
+it finds that is associated with \fItkwin\fR and matches the
+\fImask\fR, \fIproc\fR, and \fIclientData\fR arguments. If
+no such handler exists, then \fBTk_HandleEvent\fR returns
+without doing anything. Although Tk supports it, it's probably
+a bad idea to have more than one callback with the same \fImask\fR,
+\fIproc\fR, and \fIclientData\fR arguments.
+When a window is deleted all of its handlers will be deleted
+automatically; in this case there is no need to call
+\fBTk_DeleteEventHandler\fR.
+.PP
+If multiple handlers are declared for the same type of X event
+on the same window, then the handlers will be invoked in the
+order they were created.
+.SH KEYWORDS
+bind, callback, event, handler
diff --git a/tk8.6/doc/FindPhoto.3 b/tk8.6/doc/FindPhoto.3
new file mode 100644
index 0000000..dc218bf
--- /dev/null
+++ b/tk8.6/doc/FindPhoto.3
@@ -0,0 +1,283 @@
+'\"
+'\" Copyright (c) 1994 The Australian National University
+'\" Copyright (c) 1994-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.
+'\"
+'\" Author: Paul Mackerras (paulus@cs.anu.edu.au),
+'\" Department of Computer Science,
+'\" Australian National University.
+'\"
+.TH Tk_FindPhoto 3 8.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_FindPhoto, Tk_PhotoPutBlock, Tk_PhotoPutZoomedBlock, Tk_PhotoGetImage, Tk_PhotoBlank, Tk_PhotoExpand, Tk_PhotoGetSize, Tk_PhotoSetSize \- manipulate the image data stored in a photo image.
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+Tk_PhotoHandle
+\fBTk_FindPhoto\fR(\fIinterp, imageName\fR)
+.sp
+int
+\fBTk_PhotoPutBlock\fR(\fIinterp, handle, blockPtr, x, y, width, height,\
+compRule\fR)
+.sp
+int
+\fBTk_PhotoPutZoomedBlock\fR(\fIinterp, handle, blockPtr, x, y, width, height,\
+zoomX, zoomY, subsampleX, subsampleY, compRule\fR)
+.sp
+int
+\fBTk_PhotoGetImage\fR(\fIhandle, blockPtr\fR)
+.sp
+void
+\fBTk_PhotoBlank\fR(\fIhandle\fR)
+.sp
+int
+\fBTk_PhotoExpand\fR(\fIinterp, handle, width, height\fR)
+.sp
+void
+\fBTk_PhotoGetSize\fR(\fIhandle, widthPtr, heightPtr\fR)
+.sp
+int
+\fBTk_PhotoSetSize\fR(\fIinterp. handle, width, height\fR)
+.SH ARGUMENTS
+.AS Tk_PhotoImageBlock window_path
+.AP Tcl_Interp *interp in
+Interpreter in which image was created and in which error reporting is
+to be done.
+.AP "const char" *imageName in
+Name of the photo image.
+.AP Tk_PhotoHandle handle in
+Opaque handle identifying the photo image to be affected.
+.AP Tk_PhotoImageBlock *blockPtr in
+Specifies the address and storage layout of image data.
+.AP int x in
+Specifies the X coordinate where the top-left corner of the block is
+to be placed within the image.
+.AP int y in
+Specifies the Y coordinate where the top-left corner of the block is
+to be placed within the image.
+.AP int width in
+Specifies the width of the image area to be affected (for
+\fBTk_PhotoPutBlock\fR) or the desired image width (for
+\fBTk_PhotoExpand\fR and \fBTk_PhotoSetSize\fR).
+.AP int compRule in
+Specifies the compositing rule used when combining transparent pixels
+in a block of data with a photo image. Must be one of
+\fBTK_PHOTO_COMPOSITE_OVERLAY\fR (which puts the block of data over the top
+of the existing photo image, with the previous contents showing
+through in the transparent bits) or \fBTK_PHOTO_COMPOSITE_SET\fR (which
+discards the existing photo image contents in the rectangle covered by
+the data block.)
+.AP int height in
+Specifies the height of the image area to be affected (for
+\fBTk_PhotoPutBlock\fR) or the desired image height (for
+\fBTk_PhotoExpand\fR and \fBTk_PhotoSetSize\fR).
+.AP int *widthPtr out
+Pointer to location in which to store the image width.
+.AP int *heightPtr out
+Pointer to location in which to store the image height.
+.AP int subsampleX in
+Specifies the subsampling factor in the X direction for input
+image data.
+.AP int subsampleY in
+Specifies the subsampling factor in the Y direction for input
+image data.
+.AP int zoomX in
+Specifies the zoom factor to be applied in the X direction to pixels
+being written to the photo image.
+.AP int zoomY in
+Specifies the zoom factor to be applied in the Y direction to pixels
+being written to the photo image.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_FindPhoto\fR returns an opaque handle that is used to identify a
+particular photo image to the other procedures. The parameter is the
+name of the image, that is, the name specified to the \fBimage create
+photo\fR command, or assigned by that command if no name was specified.
+If \fIimageName\fR does not exist or is not a photo image,
+\fBTk_FindPhoto\fR returns NULL.
+.PP
+\fBTk_PhotoPutBlock\fR is used to supply blocks of image data to be
+displayed. The call affects an area of the image of size
+\fIwidth\fR x \fIheight\fR pixels, with its top-left corner at
+coordinates (\fIx\fR,\fIy\fR). All of \fIwidth\fR, \fIheight\fR,
+\fIx\fR, and \fIy\fR must be non-negative.
+If part of this area lies outside the
+current bounds of the image, the image will be expanded to include the
+area, unless the user has specified an explicit image size with the
+\fB\-width\fR and/or \fB\-height\fR widget configuration options
+(see photo(n)); in that
+case the area is silently clipped to the image boundaries.
+.PP
+The \fIblock\fR parameter is a pointer to a
+\fBTk_PhotoImageBlock\fR structure, defined as follows:
+.CS
+typedef struct {
+ unsigned char *\fIpixelPtr\fR;
+ int \fIwidth\fR;
+ int \fIheight\fR;
+ int \fIpitch\fR;
+ int \fIpixelSize\fR;
+ int \fIoffset\fR[4];
+} \fBTk_PhotoImageBlock\fR;
+.CE
+The \fIpixelPtr\fR field points to the first pixel, that is, the
+top-left pixel in the block.
+The \fIwidth\fR and \fIheight\fR fields specify the dimensions of the
+block of pixels. The \fIpixelSize\fR field specifies the address
+difference between two horizontally adjacent pixels. It should be 4 for
+RGB and 2 for grayscale image data. Other values are possible, if the
+offsets in the \fIoffset\fR array are adjusted accordingly (e.g. for
+red, green and blue data stored in different planes). Using such a
+layout is strongly discouraged, though. Due to a bug, it might not work
+correctly if an alpha channel is provided. (see the \fBBUGS\fR section
+below). The \fIpitch\fR field specifies the
+address difference between two vertically adjacent pixels. The
+\fIoffset\fR array contains the offsets from the address of a pixel
+to the addresses of the bytes containing the red, green, blue and alpha
+(transparency) components. If the offsets for red, green and blue are
+equal, the image is interpreted as grayscale. If they differ, RGB data
+is assumed. Normally the offsets will be 0, 1, 2, 3 for RGB data
+and 0, 0, 0, 1 for grayscale. It is possible to provide image data
+without an alpha channel by setting the offset for alpha to a negative
+value and adjusting the \fIpixelSize\fR field accordingly. This use is
+discouraged, though (see the \fBBUGS\fR section below).
+.PP
+The \fIcompRule\fR parameter to \fBTk_PhotoPutBlock\fR specifies a
+compositing rule that says what to do with transparent pixels. The
+value \fBTK_PHOTO_COMPOSITE_OVERLAY\fR says that the previous contents of
+the photo image should show through, and the value
+\fBTK_PHOTO_COMPOSITE_SET\fR says that the previous contents of the photo
+image should be completely ignored, and the values from the block be
+copied directly across. The behavior in Tk8.3 and earlier was
+equivalent to having \fBTK_PHOTO_COMPOSITE_OVERLAY\fR as a compositing rule.
+.PP
+The value given for the \fIwidth\fR and \fIheight\fR parameters to
+\fBTk_PhotoPutBlock\fR do not have to correspond to the values specified
+in \fIblock\fR. If they are smaller, \fBTk_PhotoPutBlock\fR extracts a
+sub-block from the image data supplied. If they are larger, the data
+given are replicated (in a tiled fashion) to fill the specified area.
+These rules operate independently in the horizontal and vertical
+directions.
+.PP
+\fBTk_PhotoPutBlock\fR normally returns \fBTCL_OK\fR, though if it cannot
+allocate sufficient memory to hold the resulting image, \fBTCL_ERROR\fR is
+returned instead and, if the \fIinterp\fR argument is non-NULL, an
+error message is placed in the interpreter's result.
+.PP
+\fBTk_PhotoPutZoomedBlock\fR works like \fBTk_PhotoPutBlock\fR except that
+the image can be reduced or enlarged for display. The
+\fIsubsampleX\fR and \fIsubsampleY\fR parameters allow the size of the
+image to be reduced by subsampling.
+\fBTk_PhotoPutZoomedBlock\fR will use only pixels from the input image
+whose X coordinates are multiples of \fIsubsampleX\fR, and whose Y
+coordinates are multiples of \fIsubsampleY\fR. For example, an image
+of 512x512 pixels can be reduced to 256x256 by setting
+\fIsubsampleX\fR and \fIsubsampleY\fR to 2.
+.PP
+The \fIzoomX\fR and \fIzoomY\fR parameters allow the image to be
+enlarged by pixel replication. Each pixel of the (possibly subsampled)
+input image will be written to a block \fIzoomX\fR pixels wide and
+\fIzoomY\fR pixels high of the displayed image. Subsampling and
+zooming can be used together for special effects.
+.PP
+\fBTk_PhotoGetImage\fR can be used to retrieve image data from a photo
+image. \fBTk_PhotoGetImage\fR fills
+in the structure pointed to by the \fIblockPtr\fR parameter with values
+that describe the address and layout of the image data that the
+photo image has stored internally. The values are valid
+until the image is destroyed or its size is changed.
+.PP
+It is possible to modify an image by writing directly to the data
+the \fIpixelPtr\fR field points to. The size of the image cannot be
+changed this way, though.
+Also, changes made by writing directly to \fIpixelPtr\fR will not be
+immediately visible, but only after a call to
+\fBTk_ImageChanged\fR or after an event that causes the interested
+widgets to redraw themselves.
+For these reasons usually it is preferable to make changes to
+a copy of the image data and write it back with
+\fBTk_PhotoPutBlock\fR or \fBTk_PhotoPutZoomedBlock\fR.
+.PP
+\fBTk_PhotoGetImage\fR returns 1 for compatibility with the
+corresponding procedure in the old photo widget.
+.PP
+\fBTk_PhotoBlank\fR blanks the entire area of the
+photo image. Blank areas of a photo image are transparent.
+.PP
+\fBTk_PhotoExpand\fR requests that the widget's image be expanded to be
+at least \fIwidth\fR x \fIheight\fR pixels in size. The width and/or
+height are unchanged if the user has specified an explicit image width
+or height with the \fB\-width\fR and/or \fB\-height\fR configuration
+options, respectively.
+If the image data
+are being supplied in many small blocks, it is more efficient to use
+\fBTk_PhotoExpand\fR or \fBTk_PhotoSetSize\fR at the beginning rather than
+allowing the image to expand in many small increments as image blocks
+are supplied.
+.PP
+\fBTk_PhotoExpand\fR normally returns \fBTCL_OK\fR, though if it cannot
+allocate sufficient memory to hold the resulting image, \fBTCL_ERROR\fR is
+returned instead and, if the \fIinterp\fR argument is non-NULL, an
+error message is placed in the interpreter's result.
+.PP
+\fBTk_PhotoSetSize\fR specifies the size of the image, as if the user
+had specified the given \fIwidth\fR and \fIheight\fR values to the
+\fB\-width\fR and \fB\-height\fR configuration options. A value of
+zero for \fIwidth\fR or \fIheight\fR does not change the image's width
+or height, but allows the width or height to be changed by subsequent
+calls to \fBTk_PhotoPutBlock\fR, \fBTk_PhotoPutZoomedBlock\fR or
+\fBTk_PhotoExpand\fR.
+.PP
+\fBTk_PhotoSetSize\fR normally returns \fBTCL_OK\fR, though if it cannot
+allocate sufficient memory to hold the resulting image, \fBTCL_ERROR\fR is
+returned instead and, if the \fIinterp\fR argument is non-NULL, an
+error message is placed in the interpreter's result.
+.PP
+\fBTk_PhotoGetSize\fR returns the dimensions of the image in
+*\fIwidthPtr\fR and *\fIheightPtr\fR.
+.SH PORTABILITY
+.PP
+In Tk 8.3 and earlier, \fBTk_PhotoPutBlock\fR and
+\fBTk_PhotoPutZoomedBlock\fR had different signatures. If you want to
+compile code that uses the old interface against 8.4 without updating
+your code, compile it with the flag
+-DUSE_COMPOSITELESS_PHOTO_PUT_BLOCK. Code linked using Stubs against
+older versions of Tk will continue to work.
+.PP
+In Tk 8.4, \fBTk_PhotoPutBlock\fR, \fBTk_PhotoPutZoomedBlock\fR,
+\fBTk_PhotoExpand\fR and \fBTk_PhotoSetSize\fR did not take an
+\fIinterp\fR argument or return any result code. If insufficient
+memory was available for an image, Tk would panic. This behaviour is
+still supported if you compile your extension with the additional flag
+-DUSE_PANIC_ON_PHOTO_ALLOC_FAILURE. Code linked using Stubs against
+older versions of Tk will continue to work.
+.SH BUGS
+The \fBTk_PhotoImageBlock\fR structure used to provide image data to
+\fBTk_PhotoPutBlock\fR promises great flexibility in the layout of the
+data (e.g. separate planes for the red, green, blue and alpha
+channels). Unfortunately, the implementation fails to hold this
+promise. The problem is that the \fIpixelSize\fR field is
+(incorrectly) used to determine whether the image has an alpha channel.
+Currently, if the offset for the alpha channel is greater or equal than
+\fIpixelSize\fR, \fBtk_PhotoPutblock\fR assumes no alpha data is
+present and makes the image fully opaque. This means that for layouts
+where the channels are separate (or any other exotic layout where
+\fIpixelSize\fR has to be smaller than the alpha offset), the alpha
+channel will not be read correctly. In order to be on the safe side
+if this issue will be corrected in a future release, it is strongly
+recommended you always provide alpha data - even if the image has no
+transparency - and only use the "standard" layout with a
+\fIpixelSize\fR of 2 for grayscale and 4 for RGB data with
+\fIoffset\fRs of 0, 0, 0, 1 or 0, 1, 2, 3 respectively.
+.SH CREDITS
+.PP
+The code for the photo image type was developed by Paul Mackerras,
+based on his earlier photo widget code.
+.SH KEYWORDS
+photo, image
diff --git a/tk8.6/doc/FontId.3 b/tk8.6/doc/FontId.3
new file mode 100644
index 0000000..9d35ae6
--- /dev/null
+++ b/tk8.6/doc/FontId.3
@@ -0,0 +1,94 @@
+'\"
+'\" 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.
+'\"
+.TH Tk_FontId 3 8.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_FontId, Tk_GetFontMetrics, Tk_PostscriptFontName \- accessor functions for
+fonts
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+Font
+\fBTk_FontId(\fItkfont\fB)\fR
+.sp
+\fBTk_GetFontMetrics(\fItkfont, fmPtr\fB)\fR
+.sp
+int
+\fBTk_PostscriptFontName(\fItkfont, dsPtr\fB)\fR
+.SH ARGUMENTS
+.AS Tk_FontMetrics *dsPtr
+.AP Tk_Font tkfont in
+Opaque font token being queried. Must have been returned by a previous
+call to \fBTk_GetFont\fR.
+.AP Tk_FontMetrics *fmPtr out
+Pointer to structure in which the font metrics for \fItkfont\fR will
+be stored. See \fBDATA STRUCTURES\fR below for details.
+.AP Tcl_DString *dsPtr out
+Pointer to an initialized \fBTcl_DString\fR to which the name of the
+Postscript font that corresponds to \fItkfont\fR will be appended.
+.BE
+.SH DESCRIPTION
+.PP
+Given a \fItkfont\fR, \fBTk_FontId\fR returns the token that should be
+selected into an XGCValues structure in order to construct a graphics
+context that can be used to draw text in the specified font.
+.PP
+\fBTk_GetFontMetrics\fR computes the ascent, descent, and linespace of the
+\fItkfont\fR in pixels and stores those values in the structure pointer to by
+\fIfmPtr\fR. These values can be used in computations such as to space
+multiple lines of text, to align the baselines of text in different
+fonts, and to vertically align text in a given region. See the
+documentation for the \fBfont\fR command for definitions of the terms
+ascent, descent, and linespace, used in font metrics.
+.PP
+\fBTk_PostscriptFontName\fR maps a \fItkfont\fR to the corresponding
+Postscript font name that should be used when printing. The return value
+is the size in points of the \fItkfont\fR and the Postscript font name is
+appended to \fIdsPtr\fR. \fIDsPtr\fR must refer to an initialized
+\fBTcl_DString\fR. Given a
+.QW reasonable
+Postscript printer, the
+following screen font families should print correctly:
+.IP
+\fBAvant Garde\fR, \fBArial\fR, \fBBookman\fR, \fBCourier\fR,
+\fBCourier New\fR, \fBGeneva\fR, \fBHelvetica\fR, \fBMonaco\fR,
+\fBNew Century Schoolbook\fR, \fBNew York\fR, \fBPalatino\fR, \fBSymbol\fR,
+\fBTimes\fR, \fBTimes New Roman\fR, \fBZapf Chancery\fR, and
+\fBZapf Dingbats\fR.
+.PP
+Any other font families may not print correctly because the computed
+Postscript font name may be incorrect or not exist on the printer.
+.SH "DATA STRUCTURES"
+.PP
+The \fBTk_FontMetrics\fR data structure is used by \fBTk_GetFontMetrics\fR to
+return information about a font and is defined as follows:
+.CS
+typedef struct Tk_FontMetrics {
+ int \fIascent\fR;
+ int \fIdescent\fR;
+ int \fIlinespace\fR;
+} \fBTk_FontMetrics\fR;
+.CE
+.PP
+The \fIascent\fR field is the amount in pixels that the tallest
+letter sticks up above the baseline, plus any extra blank space added
+by the designer of the font.
+.PP
+The \fIdescent\fR is the largest amount in pixels that any letter
+sticks below the baseline, plus any extra blank space added by the
+designer of the font.
+.PP
+The \fIlinespace\fR is the sum of the ascent and descent. How far
+apart two lines of text in the same font should be placed so that none
+of the characters in one line overlap any of the characters in the
+other line.
+.SH "SEE ALSO"
+font(n), MeasureChar(3)
+.SH KEYWORDS
+font, measurement, Postscript
diff --git a/tk8.6/doc/FreeXId.3 b/tk8.6/doc/FreeXId.3
new file mode 100644
index 0000000..dd1d141
--- /dev/null
+++ b/tk8.6/doc/FreeXId.3
@@ -0,0 +1,48 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_FreeXId 3 4.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_FreeXId \- make X resource identifier available for reuse
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+\fBTk_FreeXId(\fIdisplay, id\fB)\fR
+.SH ARGUMENTS
+.AS Display *display out
+.AP Display *display in
+Display for which \fIid\fR was allocated.
+.AP XID id in
+Identifier of X resource (window, font, pixmap, cursor, graphics
+context, or colormap) that is no longer in use.
+.BE
+.SH DESCRIPTION
+.PP
+The default allocator for resource identifiers provided by Xlib is very
+simple-minded and does not allow resource identifiers to be re-used.
+If a long-running application reaches the end of the resource id
+space, it will generate an X protocol error and crash.
+Tk replaces the default id allocator with its own allocator, which
+allows identifiers to be reused.
+In order for this to work, \fBTk_FreeXId\fR must be called to
+tell the allocator about resources that have been freed.
+Tk automatically calls \fBTk_FreeXId\fR whenever it frees a
+resource, so if you use procedures like \fBTk_GetFont\fR,
+\fBTk_GetGC\fR, and \fBTk_GetPixmap\fR then you need not call
+\fBTk_FreeXId\fR.
+However, if you allocate resources directly from Xlib, for example
+by calling \fBXCreatePixmap\fR, then you should call \fBTk_FreeXId\fR
+when you call the corresponding Xlib free procedure, such as
+\fBXFreePixmap\fR.
+If you do not call \fBTk_FreeXId\fR then the resource identifier will
+be lost, which could cause problems if the application runs long enough
+to lose all of the available identifiers.
+.SH KEYWORDS
+resource identifier
diff --git a/tk8.6/doc/GeomReq.3 b/tk8.6/doc/GeomReq.3
new file mode 100644
index 0000000..895f683
--- /dev/null
+++ b/tk8.6/doc/GeomReq.3
@@ -0,0 +1,92 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_GeometryRequest 3 "8.4" Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_GeometryRequest, Tk_SetMinimumRequestSize, Tk_SetInternalBorder, Tk_SetInternalBorderEx \- specify desired geometry or internal border for a window
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+\fBTk_GeometryRequest\fR(\fItkwin, reqWidth, reqHeight\fR)
+.sp
+\fBTk_SetMinimumRequestSize\fR(\fItkwin, minWidth, minHeight\fR)
+.sp
+\fBTk_SetInternalBorder\fR(\fItkwin, width\fR)
+.sp
+\fBTk_SetInternalBorderEx\fR(\fItkwin, left, right, top, bottom\fR)
+.SH ARGUMENTS
+.AS baseHeight clientData
+.AP Tk_Window tkwin in
+Window for which geometry is being requested.
+.AP int reqWidth in
+Desired width for \fItkwin\fR, in pixel units.
+.AP int reqHeight in
+Desired height for \fItkwin\fR, in pixel units.
+.AP int minWidth in
+Desired minimum requested width for \fItkwin\fR, in pixel units.
+.AP int minHeight in
+Desired minimum requested height for \fItkwin\fR, in pixel units.
+.AP int width in
+Space to leave for internal border for \fItkwin\fR, in pixel units.
+.AP int left in
+Space to leave for left side of internal border for \fItkwin\fR, in pixel units.
+.AP int right in
+Space to leave for right side of internal border for \fItkwin\fR, in pixel units.
+.AP int top in
+Space to leave for top side of internal border for \fItkwin\fR, in pixel units.
+.AP int bottom in
+Space to leave for bottom side of internal border for \fItkwin\fR, in pixel units.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_GeometryRequest\fR is called by widget code to indicate its
+preference for the dimensions of a particular window. The arguments
+to \fBTk_GeometryRequest\fR are made available to the geometry
+manager for the window, which then decides on the actual geometry
+for the window. Although geometry managers generally try to satisfy
+requests made to \fBTk_GeometryRequest\fR, there is no guarantee that
+this will always be possible. Widget code should not assume that
+a geometry request will be satisfied until it receives a
+\fBConfigureNotify\fR event indicating that the geometry change has
+occurred. Widget code should never call procedures like
+\fBTk_ResizeWindow\fR directly. Instead, it should invoke
+\fBTk_GeometryRequest\fR and leave the final geometry decisions to
+the geometry manager.
+.PP
+If \fItkwin\fR is a top-level window, then the geometry information
+will be passed to the window manager using the standard ICCCM protocol.
+.PP
+\fBTk_SetInternalBorder\fR is called by widget code to indicate that
+the widget has an internal border. This means that the widget draws
+a decorative border inside the window instead of using the standard
+X borders, which are external to the window's area. For example,
+internal borders are used to draw 3-D effects. \fIWidth\fR
+specifies the width of the border in pixels. Geometry managers will
+use this information to avoid placing any children of \fItkwin\fR
+overlapping the outermost \fIwidth\fR pixels of \fItkwin\fR's area.
+.PP
+\fBTk_SetInternalBorderEx\fR works like \fBTk_SetInternalBorder\fR
+but lets you specify different widths for different sides of the window.
+.PP
+\fBTk_SetMinimumRequestSize\fR is called by widget code to indicate
+that a geometry manager should request at least this size for the
+widget. This allows a widget to have some control over its size when
+a propagating geometry manager is used inside it.
+.PP
+The information specified in calls to \fBTk_GeometryRequest\fR,
+\fBTk_SetMinimumRequestSize\fR, \fBTk_SetInternalBorder\fR and
+\fBTk_SetInternalBorderEx\fR can be retrieved using the macros
+\fBTk_ReqWidth\fR, \fBTk_ReqHeight\fR, \fBTk_MinReqWidth\fR,
+\fBTk_MinReqHeight\fR, \fBTk_MinReqWidth\fR, \fBTk_InternalBorderLeft\fR,
+\fBTk_InternalBorderRight\fR, \fBTk_InternalBorderTop\fR and
+\fBTk_InternalBorderBottom\fR.
+See the \fBTk_WindowId\fR manual entry for details.
+.SH KEYWORDS
+geometry, request
diff --git a/tk8.6/doc/GetAnchor.3 b/tk8.6/doc/GetAnchor.3
new file mode 100644
index 0000000..6526772
--- /dev/null
+++ b/tk8.6/doc/GetAnchor.3
@@ -0,0 +1,89 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-1998 Sun Microsystems, Inc.
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH Tk_GetAnchorFromObj 3 8.1 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_GetAnchorFromObj, Tk_GetAnchor, Tk_NameOfAnchor \- translate between strings and anchor positions
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+int
+\fBTk_GetAnchorFromObj(\fIinterp, objPtr, anchorPtr\fB)\fR
+.sp
+int
+\fBTk_GetAnchor(\fIinterp, string, anchorPtr\fB)\fR
+.sp
+const char *
+\fBTk_NameOfAnchor(\fIanchor\fB)\fR
+.SH ARGUMENTS
+.AS "Tk_Anchor" *anchorPtr
+.AP Tcl_Interp *interp in
+Interpreter to use for error reporting, or NULL.
+.AP Tcl_Obj *objPtr in/out
+String value contains name of anchor point:
+.QW \fBn\fR ,
+.QW \fBne\fR ,
+.QW \fBe\fR ,
+.QW \fBse\fR ,
+.QW \fBs\fR ,
+.QW \fBsw\fR ,
+.QW \fBw\fR ,
+.QW \fBnw\fR ,
+or
+.QW \fBcenter\fR ;
+internal rep will be modified to cache corresponding Tk_Anchor. In the
+case of
+.QW \fBcenter\fR
+on input, a non-empty abbreviation of it may also be used on input.
+.AP "const char" *string in
+Same as \fIobjPtr\fR except description of anchor point is passed as
+a string.
+.AP int *anchorPtr out
+Pointer to location in which to store anchor position corresponding to
+\fIobjPtr\fR or \fIstring\fR.
+.AP Tk_Anchor anchor in
+Anchor position, e.g. \fBTCL_ANCHOR_CENTER\fR.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_GetAnchorFromObj\fR places in \fI*anchorPtr\fR an anchor position
+(enumerated type \fBTk_Anchor\fR)
+corresponding to \fIobjPtr\fR's value. The result will be one of
+\fBTK_ANCHOR_N\fR, \fBTK_ANCHOR_NE\fR, \fBTK_ANCHOR_E\fR, \fBTK_ANCHOR_SE\fR,
+\fBTK_ANCHOR_S\fR, \fBTK_ANCHOR_SW\fR, \fBTK_ANCHOR_W\fR, \fBTK_ANCHOR_NW\fR,
+or \fBTK_ANCHOR_CENTER\fR.
+Anchor positions are typically used for indicating a point on an object
+that will be used to position the object, e.g. \fBTK_ANCHOR_N\fR means
+position the top center point of the object at a particular place.
+.PP
+Under normal circumstances the return value is \fBTCL_OK\fR and
+\fIinterp\fR is unused.
+If \fIstring\fR does not contain a valid anchor position
+or an abbreviation of one of these names, \fBTCL_ERROR\fR is returned,
+\fI*anchorPtr\fR is unmodified, and an error message is
+stored in \fIinterp\fR's result if \fIinterp\fR is not NULL.
+\fBTk_GetAnchorFromObj\fR caches information about the return
+value in \fIobjPtr\fR, which speeds up future calls to
+\fBTk_GetAnchorFromObj\fR with the same \fIobjPtr\fR.
+.PP
+\fBTk_GetAnchor\fR is identical to \fBTk_GetAnchorFromObj\fR except
+that the description of the anchor is specified with a string instead
+of an object. This prevents \fBTk_GetAnchor\fR from caching the
+return value, so \fBTk_GetAnchor\fR is less efficient than
+\fBTk_GetAnchorFromObj\fR.
+.PP
+\fBTk_NameOfAnchor\fR is the logical inverse of \fBTk_GetAnchor\fR.
+Given an anchor position such as \fBTK_ANCHOR_N\fR it returns a
+statically-allocated string corresponding to \fIanchor\fR.
+If \fIanchor\fR is not a legal anchor value, then
+.QW "unknown anchor position"
+is returned.
+.SH KEYWORDS
+anchor position
diff --git a/tk8.6/doc/GetBitmap.3 b/tk8.6/doc/GetBitmap.3
new file mode 100644
index 0000000..c4ac44e
--- /dev/null
+++ b/tk8.6/doc/GetBitmap.3
@@ -0,0 +1,296 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-1998 Sun Microsystems, Inc.
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH Tk_AllocBitmapFromObj 3 8.1 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_AllocBitmapFromObj, Tk_GetBitmap, Tk_GetBitmapFromObj, Tk_DefineBitmap, Tk_NameOfBitmap, Tk_SizeOfBitmap, Tk_FreeBitmapFromObj, Tk_FreeBitmap \- maintain database of single-plane pixmaps
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+Pixmap
+\fBTk_AllocBitmapFromObj(\fIinterp, tkwin, objPtr\fB)\fR
+.sp
+Pixmap
+\fBTk_GetBitmap(\fIinterp, tkwin, info\fB)\fR
+.sp
+Pixmap
+\fBTk_GetBitmapFromObj(\fItkwin, objPtr\fB)\fR
+.sp
+int
+\fBTk_DefineBitmap(\fIinterp, name, source, width, height\fB)\fR
+.sp
+const char *
+\fBTk_NameOfBitmap(\fIdisplay, bitmap\fB)\fR
+.sp
+\fBTk_SizeOfBitmap(\fIdisplay, bitmap, widthPtr, heightPtr\fB)\fR
+.sp
+\fBTk_FreeBitmapFromObj(\fItkwin, objPtr\fB)\fR
+.sp
+\fBTk_FreeBitmap(\fIdisplay, bitmap\fB)\fR
+.SH ARGUMENTS
+.AS "unsigned long" *pixelPtr
+.AP Tcl_Interp *interp in
+Interpreter to use for error reporting; if NULL then no error message
+is left after errors.
+.AP Tk_Window tkwin in
+Token for window in which the bitmap will be used.
+.AP Tcl_Obj *objPtr in/out
+String value describes desired bitmap; internal rep will be
+modified to cache pointer to corresponding Pixmap.
+.AP "const char" *info in
+Same as \fIobjPtr\fR except description of bitmap is passed as a string and
+resulting Pixmap is not cached.
+.AP "const char" *name in
+Name for new bitmap to be defined.
+.AP "const void" *source in
+Data for bitmap, in standard bitmap format.
+Must be stored in static memory whose value will never change.
+.AP "int" width in
+Width of bitmap.
+.AP "int" height in
+Height of bitmap.
+.AP "int" *widthPtr out
+Pointer to word to fill in with \fIbitmap\fR's width.
+.AP "int" *heightPtr out
+Pointer to word to fill in with \fIbitmap\fR's height.
+.AP Display *display in
+Display for which \fIbitmap\fR was allocated.
+.AP Pixmap bitmap in
+Identifier for a bitmap allocated by \fBTk_AllocBitmapFromObj\fR or
+\fBTk_GetBitmap\fR.
+.BE
+.SH DESCRIPTION
+.PP
+These procedures manage a collection of bitmaps (one-plane pixmaps)
+being used by an application. The procedures allow bitmaps to be
+re-used efficiently, thereby avoiding server overhead, and also
+allow bitmaps to be named with character strings.
+.PP
+\fBTk_AllocBitmapFromObj\fR returns a Pixmap identifier for a bitmap
+that matches the description in \fIobjPtr\fR and is suitable for use
+in \fItkwin\fR. It re-uses an existing bitmap, if possible, and
+creates a new one otherwise. \fIObjPtr\fR's value must have one
+of the following forms:
+.TP 20
+\fB@\fIfileName\fR
+\fIFileName\fR must be the name of a file containing a bitmap
+description in the standard X11 format.
+.TP 20
+\fIname\fR
+\fIName\fR must be the name of a bitmap defined previously with
+a call to \fBTk_DefineBitmap\fR. The following names are pre-defined
+by Tk:
+.RS
+.TP 12
+\fBerror\fR
+The international
+.QW don't
+symbol: a circle with a diagonal line across it.
+.TP 12
+\fBgray75\fR
+75% gray: a checkerboard pattern where three out of four bits are on.
+.TP 12
+\fBgray50\fR
+50% gray: a checkerboard pattern where every other bit is on.
+.TP 12
+\fBgray25\fR
+25% gray: a checkerboard pattern where one out of every four bits is on.
+.TP 12
+\fBgray12\fR
+12.5% gray: a pattern where one-eighth of the bits are on, consisting of
+every fourth pixel in every other row.
+.TP 12
+\fBhourglass\fR
+An hourglass symbol.
+.TP 12
+\fBinfo\fR
+A large letter
+.QW i .
+.TP 12
+\fBquesthead\fR
+The silhouette of a human head, with a question mark in it.
+.TP 12
+\fBquestion\fR
+A large question-mark.
+.TP 12
+\fBwarning\fR
+A large exclamation point.
+.PP
+In addition, the following pre-defined names are available only on the
+\fBMacintosh\fR platform:
+.TP 12
+\fBdocument\fR
+A generic document.
+.TP 12
+\fBstationery\fR
+Document stationery.
+.TP 12
+\fBedition\fR
+The \fIedition\fR symbol.
+.TP 12
+\fBapplication\fR
+Generic application icon.
+.TP 12
+\fBaccessory\fR
+A desk accessory.
+.TP 12
+\fBfolder\fR
+Generic folder icon.
+.TP 12
+\fBpfolder\fR
+A locked folder.
+.TP 12
+\fBtrash\fR
+A trash can.
+.TP 12
+\fBfloppy\fR
+A floppy disk.
+.TP 12
+\fBramdisk\fR
+A floppy disk with chip.
+.TP 12
+\fBcdrom\fR
+A cd disk icon.
+.TP 12
+\fBpreferences\fR
+A folder with prefs symbol.
+.TP 12
+\fBquerydoc\fR
+A database document icon.
+.TP 12
+\fBstop\fR
+A stop sign.
+.TP 12
+\fBnote\fR
+A face with balloon words.
+.TP 12
+\fBcaution\fR
+A triangle with an exclamation point.
+.RE
+.LP
+Under normal conditions, \fBTk_AllocBitmapFromObj\fR
+returns an identifier for the requested bitmap. If an error
+occurs in creating the bitmap, such as when \fIobjPtr\fR refers
+to a non-existent file, then \fBNone\fR is returned and an error
+message is left in \fIinterp\fR's result if \fIinterp\fR is not
+NULL. \fBTk_AllocBitmapFromObj\fR caches information about the return
+value in \fIobjPtr\fR, which speeds up future calls to procedures
+such as \fBTk_AllocBitmapFromObj\fR and \fBTk_GetBitmapFromObj\fR.
+.PP
+\fBTk_GetBitmap\fR is identical to \fBTk_AllocBitmapFromObj\fR except
+that the description of the bitmap is specified with a string instead
+of an object. This prevents \fBTk_GetBitmap\fR from caching the
+return value, so \fBTk_GetBitmap\fR is less efficient than
+\fBTk_AllocBitmapFromObj\fR.
+.PP
+\fBTk_GetBitmapFromObj\fR returns the token for an existing bitmap, given
+the window and description used to create the bitmap.
+\fBTk_GetBitmapFromObj\fR does not actually create the bitmap; the bitmap
+must already have been created with a previous call to
+\fBTk_AllocBitmapFromObj\fR or \fBTk_GetBitmap\fR. The return
+value is cached in \fIobjPtr\fR, which speeds up
+future calls to \fBTk_GetBitmapFromObj\fR with the same \fIobjPtr\fR
+and \fItkwin\fR.
+.PP
+\fBTk_DefineBitmap\fR associates a name with
+in-memory bitmap data so that the name can be used in later
+calls to \fBTk_AllocBitmapFromObj\fR or \fBTk_GetBitmap\fR. The \fInameId\fR
+argument gives a name for the bitmap; it must not previously
+have been used in a call to \fBTk_DefineBitmap\fR.
+The arguments \fIsource\fR, \fIwidth\fR, and \fIheight\fR
+describe the bitmap.
+\fBTk_DefineBitmap\fR normally returns \fBTCL_OK\fR; if an error occurs
+(e.g. a bitmap named \fInameId\fR has already been defined) then
+\fBTCL_ERROR\fR is returned and an error message is left in
+interpreter \fIinterp\fR's result.
+Note: \fBTk_DefineBitmap\fR expects the memory pointed to by
+\fIsource\fR to be static: \fBTk_DefineBitmap\fR does not make
+a private copy of this memory, but uses the bytes pointed to
+by \fIsource\fR later in calls to \fBTk_AllocBitmapFromObj\fR or
+\fBTk_GetBitmap\fR.
+.PP
+Typically \fBTk_DefineBitmap\fR is used by \fB#include\fR-ing a
+bitmap file directly into a C program and then referencing
+the variables defined by the file.
+For example, suppose there exists a file \fBstip.bitmap\fR,
+which was created by the \fBbitmap\fR program and contains
+a stipple pattern.
+The following code uses \fBTk_DefineBitmap\fR to define a
+new bitmap named \fBfoo\fR:
+.CS
+Pixmap bitmap;
+#include "stip.bitmap"
+Tk_DefineBitmap(interp, "foo", stip_bits,
+ stip_width, stip_height);
+\&...
+bitmap = Tk_GetBitmap(interp, tkwin, "foo");
+.CE
+This code causes the bitmap file to be read
+at compile-time and incorporates the bitmap information into
+the program's executable image. The same bitmap file could be
+read at run-time using \fBTk_GetBitmap\fR:
+.CS
+Pixmap bitmap;
+bitmap = Tk_GetBitmap(interp, tkwin, "@stip.bitmap");
+.CE
+The second form is a bit more flexible (the file could be modified
+after the program has been compiled, or a different string could be
+provided to read a different file), but it is a little slower and
+requires the bitmap file to exist separately from the program.
+.PP
+Tk maintains a database of all the bitmaps that are currently in use.
+Whenever possible, it will return an existing bitmap rather
+than creating a new one.
+When a bitmap is no longer used, Tk will release it automatically.
+This approach can substantially reduce server overhead, so
+\fBTk_AllocBitmapFromObj\fR and \fBTk_GetBitmap\fR should generally
+be used in preference to Xlib procedures like \fBXReadBitmapFile\fR.
+.PP
+The bitmaps returned by \fBTk_AllocBitmapFromObj\fR and \fBTk_GetBitmap\fR
+are shared, so callers should never modify them.
+If a bitmap must be modified dynamically, then it should be
+created by calling Xlib procedures such as \fBXReadBitmapFile\fR
+or \fBXCreatePixmap\fR directly.
+.PP
+The procedure \fBTk_NameOfBitmap\fR is roughly the inverse of
+\fBTk_GetBitmap\fR.
+Given an X Pixmap argument, it returns the textual description that was
+passed to \fBTk_GetBitmap\fR when the bitmap was created.
+\fIBitmap\fR must have been the return value from a previous
+call to \fBTk_AllocBitmapFromObj\fR or \fBTk_GetBitmap\fR.
+.PP
+\fBTk_SizeOfBitmap\fR returns the dimensions of its \fIbitmap\fR
+argument in the words pointed to by the \fIwidthPtr\fR and
+\fIheightPtr\fR arguments. As with \fBTk_NameOfBitmap\fR,
+\fIbitmap\fR must have been created by \fBTk_AllocBitmapFromObj\fR or
+\fBTk_GetBitmap\fR.
+.PP
+When a bitmap is no longer needed, \fBTk_FreeBitmapFromObj\fR or
+\fBTk_FreeBitmap\fR should be called to release it.
+For \fBTk_FreeBitmapFromObj\fR the bitmap to release is specified
+with the same information used to create it; for
+\fBTk_FreeBitmap\fR the bitmap to release is specified
+with its Pixmap token.
+There should be exactly one call to \fBTk_FreeBitmapFromObj\fR
+or \fBTk_FreeBitmap\fR for each call to \fBTk_AllocBitmapFromObj\fR or
+\fBTk_GetBitmap\fR.
+.SH BUGS
+.PP
+In determining whether an existing bitmap can be used to satisfy
+a new request, \fBTk_AllocBitmapFromObj\fR and \fBTk_GetBitmap\fR
+consider only the immediate value of the string description. For
+example, when a file name is passed to \fBTk_GetBitmap\fR,
+\fBTk_GetBitmap\fR will assume it is safe to re-use an existing
+bitmap created from the same file name: it will not check to
+see whether the file itself has changed, or whether the current
+directory has changed, thereby causing the name to refer to
+a different file.
+.SH KEYWORDS
+bitmap, pixmap
diff --git a/tk8.6/doc/GetCapStyl.3 b/tk8.6/doc/GetCapStyl.3
new file mode 100644
index 0000000..28f1a1c
--- /dev/null
+++ b/tk8.6/doc/GetCapStyl.3
@@ -0,0 +1,64 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_GetCapStyle 3 "" Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_GetCapStyle, Tk_NameOfCapStyle \- translate between strings and cap styles
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+int
+\fBTk_GetCapStyle(\fIinterp, string, capPtr\fB)\fR
+.sp
+const char *
+\fBTk_NameOfCapStyle(\fIcap\fB)\fR
+.SH ARGUMENTS
+.AS "Tcl_Interp" *capPtr
+.AP Tcl_Interp *interp in
+Interpreter to use for error reporting.
+.AP "const char" *string in
+String containing name of cap style \- one of
+.QW \fBbutt\fR ,
+.QW \fBprojecting\fR ,
+or
+.QW \fBround\fR
+\- or a unique abbreviation of one.
+.AP int *capPtr out
+Pointer to location in which to store X cap style corresponding to
+\fIstring\fR.
+.AP int cap in
+Cap style: one of \fBCapButt\fR, \fBCapProjecting\fR, or \fBCapRound\fR.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_GetCapStyle\fR places in \fI*capPtr\fR the X cap style
+corresponding to \fIstring\fR.
+This will be one of the values
+\fBCapButt\fR, \fBCapProjecting\fR, or \fBCapRound\fR.
+Cap styles are typically used in X graphics contexts to indicate
+how the end-points of lines should be capped.
+See the X documentation for information on what each style
+implies.
+.PP
+Under normal circumstances the return value is \fBTCL_OK\fR and
+\fIinterp\fR is unused.
+If \fIstring\fR does not contain a valid cap style
+or an abbreviation of one of these names, then an error message is
+stored in interpreter \fIinterp\fR's result, \fBTCL_ERROR\fR is returned, and
+\fI*capPtr\fR is unmodified.
+.PP
+\fBTk_NameOfCapStyle\fR is the logical inverse of \fBTk_GetCapStyle\fR.
+Given a cap style such as \fBCapButt\fR it returns a
+statically-allocated string corresponding to \fIcap\fR.
+If \fIcap\fR is not a legal cap style, then
+.QW "unknown cap style"
+is returned.
+.SH KEYWORDS
+butt, cap style, projecting, round
diff --git a/tk8.6/doc/GetClrmap.3 b/tk8.6/doc/GetClrmap.3
new file mode 100644
index 0000000..9e6da12
--- /dev/null
+++ b/tk8.6/doc/GetClrmap.3
@@ -0,0 +1,77 @@
+'\"
+'\" Copyright (c) 1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_GetColormap 3 4.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_GetColormap, Tk_PreserveColormap, Tk_FreeColormap \- allocate and free colormaps
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+Colormap
+\fBTk_GetColormap(\fIinterp, tkwin, string\fB)\fR
+.sp
+\fBTk_PreserveColormap(\fIdisplay, colormap\fB)\fR
+.sp
+\fBTk_FreeColormap(\fIdisplay, colormap\fB)\fR
+.SH ARGUMENTS
+.AS "Colormap" colormap
+.AP Tcl_Interp *interp in
+Interpreter to use for error reporting.
+.AP Tk_Window tkwin in
+Token for window in which colormap will be used.
+.AP "const char" *string in
+Selects a colormap: either \fBnew\fR or the name of a window
+with the same screen and visual as \fItkwin\fR.
+.AP Display *display in
+Display for which \fIcolormap\fR was allocated.
+.AP Colormap colormap in
+Colormap to free or preserve; must have been returned by a previous
+call to \fBTk_GetColormap\fR or \fBTk_GetVisual\fR.
+.BE
+.SH DESCRIPTION
+.PP
+These procedures are used to manage colormaps.
+\fBTk_GetColormap\fR returns a colormap suitable for use in \fItkwin\fR.
+If its \fIstring\fR argument is \fBnew\fR then a new colormap is
+created; otherwise \fIstring\fR must be the name of another window
+with the same screen and visual as \fItkwin\fR, and the colormap from that
+window is returned.
+If \fIstring\fR does not make sense, or if it refers to a window on
+a different screen from \fItkwin\fR or with
+a different visual than \fItkwin\fR, then \fBTk_GetColormap\fR returns
+\fBNone\fR and leaves an error message in \fIinterp\fR's result.
+.PP
+\fBTk_PreserveColormap\fR increases the internal reference count for a
+colormap previously returned by \fBTk_GetColormap\fR, which allows the
+colormap to be stored in several locations without knowing which order
+they will be released.
+.PP
+\fBTk_FreeColormap\fR should be called when a colormap returned by
+\fBTk_GetColormap\fR is no longer needed.
+Tk maintains a reference count for each colormap returned by
+\fBTk_GetColormap\fR, so there should eventually be one call to
+\fBTk_FreeColormap\fR for each call to \fBTk_GetColormap\fR and each
+call to \fBTk_PreserveColormap\fR.
+When a colormap's reference count becomes zero, Tk releases the
+X colormap.
+.PP
+\fBTk_GetVisual\fR and \fBTk_GetColormap\fR work together, in that
+a new colormap created by \fBTk_GetVisual\fR may later be returned
+by \fBTk_GetColormap\fR.
+The reference counting mechanism for colormaps includes both procedures,
+so callers of \fBTk_GetVisual\fR must also call \fBTk_FreeColormap\fR
+to release the colormap.
+If \fBTk_GetColormap\fR is called with a \fIstring\fR value of
+\fBnew\fR then the resulting colormap will never
+be returned by \fBTk_GetVisual\fR; however, it can be used in other
+windows by calling \fBTk_GetColormap\fR with the original window's
+name as \fIstring\fR.
+.SH KEYWORDS
+colormap, visual
diff --git a/tk8.6/doc/GetColor.3 b/tk8.6/doc/GetColor.3
new file mode 100644
index 0000000..15254aa
--- /dev/null
+++ b/tk8.6/doc/GetColor.3
@@ -0,0 +1,176 @@
+'\"
+'\" Copyright (c) 1990-1991 The Regents of the University of California.
+'\" Copyright (c) 1994-1998 Sun Microsystems, Inc.
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH Tk_AllocColorFromObj 3 8.1 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_AllocColorFromObj, Tk_GetColor, Tk_GetColorFromObj, Tk_GetColorByValue, Tk_NameOfColor, Tk_FreeColorFromObj, Tk_FreeColor \- maintain database of colors
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+XColor *
+\fBTk_AllocColorFromObj(\fIinterp, tkwin, objPtr\fB)\fR
+.sp
+XColor *
+\fBTk_GetColor(\fIinterp, tkwin, name\fB)\fR
+.sp
+XColor *
+\fBTk_GetColorFromObj(\fItkwin, objPtr\fB)\fR
+.sp
+XColor *
+\fBTk_GetColorByValue(\fItkwin, prefPtr\fB)\fR
+.sp
+const char *
+\fBTk_NameOfColor(\fIcolorPtr\fB)\fR
+.sp
+GC
+\fBTk_GCForColor(\fIcolorPtr, drawable\fB)\fR
+.sp
+\fBTk_FreeColorFromObj(\fItkwin, objPtr\fB)\fR
+.sp
+\fBTk_FreeColor(\fIcolorPtr\fB)\fR
+.SH ARGUMENTS
+.AS "Tcl_Interp" *colorPtr
+.AP Tcl_Interp *interp in
+Interpreter to use for error reporting.
+.AP Tk_Window tkwin in
+Token for window in which color will be used.
+.AP Tcl_Obj *objPtr in/out
+String value describes desired color; internal rep will be
+modified to cache pointer to corresponding (XColor *).
+.AP char *name in
+Same as \fIobjPtr\fR except description of color is passed as a string and
+resulting (XColor *) is not cached.
+.AP XColor *prefPtr in
+Indicates red, green, and blue intensities of desired
+color.
+.AP XColor *colorPtr in
+Pointer to X color information. Must have been allocated by previous
+call to \fBTk_AllocColorFromObj\fR, \fBTk_GetColor\fR or
+\fBTk_GetColorByValue\fR, except when passed to \fBTk_NameOfColor\fR.
+.AP Drawable drawable in
+Drawable in which the result graphics context will be used. Must have
+same screen and depth as the window for which the color was allocated.
+.BE
+.SH DESCRIPTION
+.PP
+These procedures manage the colors being used by a Tk application.
+They allow colors to be shared whenever possible, so that colormap
+space is preserved, and they pick closest available colors when
+colormap space is exhausted.
+.PP
+Given a textual description of a color, \fBTk_AllocColorFromObj\fR
+locates a pixel value that may be used to render the color
+in a particular window. The desired color is specified with a
+value whose string value must have one of the following forms:
+.TP 20
+\fIcolorname\fR
+Any of the valid textual names for a color defined in the
+server's color database file, such as \fBred\fR or \fBPeachPuff\fR.
+.TP 20
+\fB#\fIRGB\fR
+.TP 20
+\fB#\fIRRGGBB\fR
+.TP 20
+\fB#\fIRRRGGGBBB\fR
+.TP 20
+\fB#\fIRRRRGGGGBBBB\fR
+A numeric specification of the red, green, and blue intensities
+to use to display the color. Each \fIR\fR, \fIG\fR, or \fIB\fR
+represents a single hexadecimal digit. The four forms permit
+colors to be specified with 4-bit, 8-bit, 12-bit or 16-bit values.
+When fewer than 16 bits are provided for each color, they represent
+the most significant bits of the color, while the lower unfilled
+bits will be repeatedly replicated from the available higher bits.
+For example, #3a7 is the same as #3333aaaa7777.
+.PP
+\fBTk_AllocColorFromObj\fR returns a pointer to
+an XColor structure; the structure indicates the exact intensities of
+the allocated color (which may differ slightly from those requested,
+depending on the limitations of the screen) and a pixel value
+that may be used to draw with the color in \fItkwin\fR.
+If an error occurs in \fBTk_AllocColorFromObj\fR (such as an unknown
+color name) then NULL is returned and an error message is stored in
+\fIinterp\fR's result if \fIinterp\fR is not NULL.
+If the colormap for \fItkwin\fR is full, \fBTk_AllocColorFromObj\fR
+will use the closest existing color in the colormap.
+\fBTk_AllocColorFromObj\fR caches information about
+the return value in \fIobjPtr\fR, which speeds up future calls to procedures
+such as \fBTk_AllocColorFromObj\fR and \fBTk_GetColorFromObj\fR.
+.PP
+\fBTk_GetColor\fR is identical to \fBTk_AllocColorFromObj\fR except
+that the description of the color is specified with a string instead
+of a value. This prevents \fBTk_GetColor\fR from caching the
+return value, so \fBTk_GetColor\fR is less efficient than
+\fBTk_AllocColorFromObj\fR.
+.PP
+\fBTk_GetColorFromObj\fR returns the token for an existing color, given
+the window and description used to create the color.
+\fBTk_GetColorFromObj\fR does not actually create the color; the color
+must already have been created with a previous call to
+\fBTk_AllocColorFromObj\fR or \fBTk_GetColor\fR. The return
+value is cached in \fIobjPtr\fR, which speeds up
+future calls to \fBTk_GetColorFromObj\fR with the same \fIobjPtr\fR
+and \fItkwin\fR.
+.PP
+\fBTk_GetColorByValue\fR is similar to \fBTk_GetColor\fR except that
+the desired color is indicated with the \fIred\fR, \fIgreen\fR, and
+\fIblue\fR fields of the structure pointed to by \fIcolorPtr\fR.
+.PP
+This package maintains a database
+of all the colors currently in use.
+If the same color is requested multiple times from
+\fBTk_GetColor\fR or \fBTk_AllocColorFromObj\fR (e.g. by different
+windows), or if the
+same intensities are requested multiple times from
+\fBTk_GetColorByValue\fR, then existing pixel values will
+be re-used. Re-using an existing pixel avoids any interaction
+with the window server, which makes the allocation much more
+efficient. These procedures also provide a portable interface that
+works across all platforms. For this reason, you should generally use
+\fBTk_AllocColorFromObj\fR, \fBTk_GetColor\fR, or \fBTk_GetColorByValue\fR
+instead of lower level procedures like \fBXAllocColor\fR.
+.PP
+Since different calls to this package
+may return the same shared
+pixel value, callers should never change the color of a pixel
+returned by the procedures.
+If you need to change a color value dynamically, you should use
+\fBXAllocColorCells\fR to allocate the pixel value for the color.
+.PP
+The procedure \fBTk_NameOfColor\fR is roughly the inverse of
+\fBTk_GetColor\fR. If its \fIcolorPtr\fR argument was created
+by \fBTk_AllocColorFromObj\fR or \fBTk_GetColor\fR then the return value
+is the string that was used to create the
+color. If \fIcolorPtr\fR was created by a call to \fBTk_GetColorByValue\fR,
+or by any other mechanism, then the return value is a string
+that could be passed to \fBTk_GetColor\fR to return the same
+color. Note: the string returned by \fBTk_NameOfColor\fR is
+only guaranteed to persist until the next call to
+\fBTk_NameOfColor\fR.
+.PP
+\fBTk_GCForColor\fR returns a graphics context whose \fBforeground\fR
+field is the pixel allocated for \fIcolorPtr\fR and whose other fields
+all have default values.
+This provides an easy way to do basic drawing with a color.
+The graphics context is cached with the color and will exist only as
+long as \fIcolorPtr\fR exists; it is freed when the last reference
+to \fIcolorPtr\fR is freed by calling \fBTk_FreeColor\fR.
+.PP
+When a color is no longer needed \fBTk_FreeColorFromObj\fR or
+\fBTk_FreeColor\fR should be called to release it.
+For \fBTk_FreeColorFromObj\fR the color to release is specified
+with the same information used to create it; for
+\fBTk_FreeColor\fR the color to release is specified
+with a pointer to its XColor structure.
+There should be exactly one call to \fBTk_FreeColorFromObj\fR
+or \fBTk_FreeColor\fR for each call to \fBTk_AllocColorFromObj\fR,
+\fBTk_GetColor\fR, or \fBTk_GetColorByValue\fR.
+.SH KEYWORDS
+color, intensity, value, pixel value
diff --git a/tk8.6/doc/GetCursor.3 b/tk8.6/doc/GetCursor.3
new file mode 100644
index 0000000..403c05e
--- /dev/null
+++ b/tk8.6/doc/GetCursor.3
@@ -0,0 +1,231 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-1998 Sun Microsystems, Inc.
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH Tk_AllocCursorFromObj 3 8.1 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_AllocCursorFromObj, Tk_GetCursor, Tk_GetCursorFromObj, Tk_GetCursorFromData, Tk_NameOfCursor, Tk_FreeCursorFromObj, Tk_FreeCursor \- maintain database of cursors
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+Tk_Cursor
+\fBTk_AllocCursorFromObj(\fIinterp, tkwin, objPtr\fB)\fR
+.sp
+Tk_Cursor
+\fBTk_GetCursor(\fIinterp, tkwin, name\fB)\fR
+.sp
+Tk_Cursor
+\fBTk_GetCursorFromObj(\fItkwin, objPtr\fB)\fR
+.sp
+Tk_Cursor
+\fBTk_GetCursorFromData(\fIinterp, tkwin, source, mask, width, height, xHot, yHot, fg, bg\fB)\fR
+.sp
+const char *
+\fBTk_NameOfCursor(\fIdisplay, cursor\fB)\fR
+.sp
+\fBTk_FreeCursorFromObj(\fItkwin, objPtr\fB)\fR
+.sp
+\fBTk_FreeCursor(\fIdisplay, cursor\fB)\fR
+.SH ARGUMENTS
+.AS "unsigned long" *pixelPtr
+.AP Tcl_Interp *interp in
+Interpreter to use for error reporting.
+.AP Tk_Window tkwin in
+Token for window in which the cursor will be used.
+.AP Tcl_Obj *objPtr in/out
+Description of cursor; see below for possible values. Internal rep will be
+modified to cache pointer to corresponding Tk_Cursor.
+.AP char *name in
+Same as \fIobjPtr\fR except description of cursor is passed as a string and
+resulting Tk_Cursor is not cached.
+.AP "const char" *source in
+Data for cursor cursor, in standard cursor format.
+.AP "const char" *mask in
+Data for mask cursor, in standard cursor format.
+.AP "int" width in
+Width of \fIsource\fR and \fImask\fR.
+.AP "int" height in
+Height of \fIsource\fR and \fImask\fR.
+.AP "int" xHot in
+X-location of cursor hot-spot.
+.AP "int" yHot in
+Y-location of cursor hot-spot.
+.AP Tk_Uid fg in
+Textual description of foreground color for cursor.
+.AP Tk_Uid bg in
+Textual description of background color for cursor.
+.AP Display *display in
+Display for which \fIcursor\fR was allocated.
+.AP Tk_Cursor cursor in
+Opaque Tk identifier for cursor. If passed to \fBTk_FreeCursor\fR, must
+have been returned by some previous call to \fBTk_GetCursor\fR or
+\fBTk_GetCursorFromData\fR.
+.BE
+.SH DESCRIPTION
+.PP
+These procedures manage a collection of cursors
+being used by an application. The procedures allow cursors to be
+re-used efficiently, thereby avoiding server overhead, and also
+allow cursors to be named with character strings.
+.PP
+\fBTk_AllocCursorFromObj\fR takes as argument an object describing a
+cursor, and returns an opaque Tk identifier for a cursor corresponding
+to the description. It re-uses an existing cursor if possible and
+creates a new one otherwise. \fBTk_AllocCursorFromObj\fR caches
+information about the return value in \fIobjPtr\fR, which speeds up
+future calls to procedures such as \fBTk_AllocCursorFromObj\fR and
+\fBTk_GetCursorFromObj\fR. If an error occurs in creating the cursor,
+such as when \fIobjPtr\fR refers to a non-existent file, then \fBNone\fR
+is returned and an error message will be stored in \fIinterp\fR's result
+if \fIinterp\fR is not NULL. \fIObjPtr\fR must contain a standard Tcl
+list with one of the following forms:
+.TP
+\fIname\fR\0[\fIfgColor\fR\0[\fIbgColor\fR]]
+\fIName\fR is the name of a cursor in the standard X cursor cursor,
+i.e., any of the names defined in \fBcursorcursor.h\fR, without
+the \fBXC_\fR. Some example values are \fBX_cursor\fR, \fBhand2\fR,
+or \fBleft_ptr\fR. Appendix B of
+.QW "The X Window System"
+by Scheifler & Gettys has illustrations showing what each of these
+cursors looks like. If \fIfgColor\fR and \fIbgColor\fR are both
+specified, they give the foreground and background colors to use
+for the cursor (any of the forms acceptable to \fBTk_GetColor\fR
+may be used). If only \fIfgColor\fR is specified, then there
+will be no background color: the background will be transparent.
+If no colors are specified, then the cursor
+will use black for its foreground color and white for its background
+color.
+.RS
+.PP
+The Macintosh version of Tk supports all of the X cursors and
+will also accept any of the standard Mac cursors
+including \fBibeam\fR, \fBcrosshair\fR, \fBwatch\fR, \fBplus\fR, and
+\fBarrow\fR. In addition, Tk will load Macintosh cursor resources of
+the types \fBcrsr\fR (color) and \fBCURS\fR (black and white) by the
+name of the resource. The application and all its open
+dynamic library's resource files will be searched for the named
+cursor. If there are conflicts color cursors will always be loaded
+in preference to black and white cursors.
+.RE
+.TP
+\fB@\fIsourceName\0maskName\0fgColor\0bgColor\fR
+In this form, \fIsourceName\fR and \fImaskName\fR are the names of
+files describing cursors for the cursor's source bits and mask.
+Each file must be in standard X11 cursor format.
+\fIFgColor\fR and \fIbgColor\fR
+indicate the colors to use for the
+cursor, in any of the forms acceptable to \fBTk_GetColor\fR. This
+form of the command will not work on Macintosh or Windows computers.
+.TP
+\fB@\fIsourceName\0fgColor\fR
+This form is similar to the one above, except that the source is
+used as mask also. This means that the cursor's background is
+transparent. This form of the command will not work on Macintosh
+or Windows computers.
+.TP
+\fB@\fIsourceName\fR
+This form only works on Windows, and will load a Windows system
+cursor (\fB.ani\fR or \fB.cur\fR) from the file specified in
+\fIsourceName\fR.
+.PP
+\fBTk_GetCursor\fR is identical to \fBTk_AllocCursorFromObj\fR except
+that the description of the cursor is specified with a string instead
+of an object. This prevents \fBTk_GetCursor\fR from caching the
+return value, so \fBTk_GetCursor\fR is less efficient than
+\fBTk_AllocCursorFromObj\fR.
+.PP
+\fBTk_GetCursorFromObj\fR returns the token for an existing cursor, given
+the window and description used to create the cursor.
+\fBTk_GetCursorFromObj\fR does not actually create the cursor; the cursor
+must already have been created with a previous call to
+\fBTk_AllocCursorFromObj\fR or \fBTk_GetCursor\fR. The return
+value is cached in \fIobjPtr\fR, which speeds up
+future calls to \fBTk_GetCursorFromObj\fR with the same \fIobjPtr\fR
+and \fItkwin\fR.
+.PP
+\fBTk_GetCursorFromData\fR allows cursors to be created from
+in-memory descriptions of their source and mask cursors. \fISource\fR
+points to standard cursor data for the cursor's source bits, and
+\fImask\fR points to standard cursor data describing
+which pixels of \fIsource\fR are to be drawn and which are to be
+considered transparent. \fIWidth\fR and \fIheight\fR give the
+dimensions of the cursor, \fIxHot\fR and \fIyHot\fR indicate the
+location of the cursor's hot-spot (the point that is reported when
+an event occurs), and \fIfg\fR and \fIbg\fR describe the cursor's
+foreground and background colors textually (any of the forms
+suitable for \fBTk_GetColor\fR may be used). Typically, the
+arguments to \fBTk_GetCursorFromData\fR are created by including
+a cursor file directly into the source code for a program, as in
+the following example:
+.CS
+Tk_Cursor cursor;
+#include "source.cursor"
+#include "mask.cursor"
+cursor = Tk_GetCursorFromData(interp, tkwin, source_bits,
+ mask_bits, source_width, source_height, source_x_hot,
+ source_y_hot, Tk_GetUid("red"), Tk_GetUid("blue"));
+.CE
+.PP
+Under normal conditions \fBTk_GetCursorFromData\fR
+will return an identifier for the requested cursor. If an error
+occurs in creating the cursor then \fBNone\fR is returned and an error
+message will be stored in \fIinterp\fR's result.
+.PP
+\fBTk_AllocCursorFromObj\fR, \fBTk_GetCursor\fR, and
+\fBTk_GetCursorFromData\fR maintain a
+database of all the cursors they have created. Whenever possible,
+a call to \fBTk_AllocCursorFromObj\fR, \fBTk_GetCursor\fR, or
+\fBTk_GetCursorFromData\fR will
+return an existing cursor rather than creating a new one. This
+approach can substantially reduce server overhead, so the Tk
+procedures should generally be used in preference to Xlib procedures
+like \fBXCreateFontCursor\fR or \fBXCreatePixmapCursor\fR, which
+create a new cursor on each call. The Tk procedures are also more
+portable than the lower-level X procedures.
+.PP
+The procedure \fBTk_NameOfCursor\fR is roughly the inverse of
+\fBTk_GetCursor\fR. If its \fIcursor\fR argument was created
+by \fBTk_GetCursor\fR, then the return value is the \fIname\fR
+argument that was passed to \fBTk_GetCursor\fR to create the
+cursor. If \fIcursor\fR was created by a call to \fBTk_GetCursorFromData\fR,
+or by any other mechanism, then the return value is a hexadecimal string
+giving the X identifier for the cursor.
+Note: the string returned by \fBTk_NameOfCursor\fR is
+only guaranteed to persist until the next call to
+\fBTk_NameOfCursor\fR. Also, this call is not portable except for
+cursors returned by \fBTk_GetCursor\fR.
+.PP
+When a cursor returned by \fBTk_AllocCursorFromObj\fR, \fBTk_GetCursor\fR,
+or \fBTk_GetCursorFromData\fR
+is no longer needed, \fBTk_FreeCursorFromObj\fR or
+\fBTk_FreeCursor\fR should be called to release it.
+For \fBTk_FreeCursorFromObj\fR the cursor to release is specified
+with the same information used to create it; for
+\fBTk_FreeCursor\fR the cursor to release is specified
+with its Tk_Cursor token.
+There should be exactly one call to \fBTk_FreeCursor\fR for
+each call to \fBTk_AllocCursorFromObj\fR, \fBTk_GetCursor\fR,
+or \fBTk_GetCursorFromData\fR.
+.SH BUGS
+.PP
+In determining whether an existing cursor can be used to satisfy
+a new request, \fBTk_AllocCursorFromObj\fR, \fBTk_GetCursor\fR,
+and \fBTk_GetCursorFromData\fR
+consider only the immediate values of their arguments. For
+example, when a file name is passed to \fBTk_GetCursor\fR,
+\fBTk_GetCursor\fR will assume it is safe to re-use an existing
+cursor created from the same file name: it will not check to
+see whether the file itself has changed, or whether the current
+directory has changed, thereby causing the name to refer to
+a different file. Similarly, \fBTk_GetCursorFromData\fR assumes
+that if the same \fIsource\fR pointer is used in two different calls,
+then the pointers refer to the same data; it does not check to
+see if the actual data values have changed.
+.SH KEYWORDS
+cursor
diff --git a/tk8.6/doc/GetDash.3 b/tk8.6/doc/GetDash.3
new file mode 100644
index 0000000..d1eeb70
--- /dev/null
+++ b/tk8.6/doc/GetDash.3
@@ -0,0 +1,82 @@
+'\"
+'\" Copyright (c) 1989-1993 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_GetDash 3 8.3 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_GetDash \- convert from string to valid dash structure.
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+
+int
+\fBTk_GetDash\fR(\fIinterp, string, dashPtr\fR)
+.fi
+.SH ARGUMENTS
+.AS Tk_Dash *dashPtr
+.AP Tcl_Interp *interp in
+Interpreter to use for error reporting.
+.AP "const char" *string in
+Textual value to be converted.
+.AP Tk_Dash *dashPtr out
+Points to place to store the dash pattern
+value converted from \fIstring\fR. Must not be NULL.
+.BE
+.SH DESCRIPTION
+.PP
+These procedure parses the string and fills in the result in the
+Tk_Dash structure. The string can be a list of integers or a
+character string containing only
+.QW \fB.,-_\fR
+and spaces. If all
+goes well, \fBTCL_OK\fR is returned and a dash descriptor is stored
+in the variable pointed to by \fIdashPtr\fR.
+If \fIstring\fR does not have the
+proper syntax then \fBTCL_ERROR\fR is returned, an error message is left
+in the interpreter's result, and nothing is stored at *\fIdashPtr\fR.
+.PP
+The first possible syntax is a list of integers. Each element
+represents the number of pixels of a line segment. Only the odd
+segments are drawn using the
+.QW outline
+color. The other segments are drawn transparent.
+.PP
+The second possible syntax is a character list containing only
+5 possible characters
+.QW "\fB.,-_ \fR" .
+The space can be used
+to enlarge the space between other line elements, and can not
+occur in the first position of the string. Some examples:
+.PP
+.CS
+ \-dash . = \-dash {2 4}
+ \-dash - = \-dash {6 4}
+ \-dash -. = \-dash {6 4 2 4}
+ \-dash -.. = \-dash {6 4 2 4 2 4}
+ \-dash {. } = \-dash {2 8}
+ \-dash , = \-dash {4 4}
+.CE
+.PP
+The main difference between this syntax and the numeric is that it
+is shape-conserving. This means that all values in the dash
+list will be multiplied by the line width before display. This
+ensures that
+.QW .
+will always be displayed as a dot and
+.QW -
+always as a dash regardless of the line width.
+.PP
+On systems where only a limited set of dash patterns, the dash
+pattern will be displayed as the most close dash pattern that
+is available. For example, on Windows only the first 4 of the
+above examples are available; the last 2 examples will be
+displayed identically to the first one.
+.SH "SEE ALSO"
+canvas(n), Tk_CreateItemType(3)
+.SH KEYWORDS
+dash, conversion
diff --git a/tk8.6/doc/GetFont.3 b/tk8.6/doc/GetFont.3
new file mode 100644
index 0000000..0504916
--- /dev/null
+++ b/tk8.6/doc/GetFont.3
@@ -0,0 +1,110 @@
+'\"
+'\" Copyright (c) 1990-1992 The Regents of the University of California.
+'\" Copyright (c) 1994-1998 Sun Microsystems, Inc.
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH Tk_AllocFontFromObj 3 8.1 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_AllocFontFromObj, Tk_GetFont, Tk_GetFontFromObj, Tk_NameOfFont, Tk_FreeFontFromObj, Tk_FreeFont \- maintain database of fonts
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+Tk_Font
+\fBTk_AllocFontFromObj(\fIinterp, tkwin, objPtr\fB)\fR
+.sp
+Tk_Font
+\fBTk_GetFont(\fIinterp, tkwin, string\fB)\fR
+.sp
+Tk_Font
+\fBTk_GetFontFromObj(\fItkwin, objPtr\fB)\fR
+.sp
+const char *
+\fBTk_NameOfFont(\fItkfont\fB)\fR
+.sp
+Tk_Font
+\fBTk_FreeFontFromObj(\fItkwin, objPtr\fB)\fR
+.sp
+void
+\fBTk_FreeFont(\fItkfont\fB)\fR
+.SH ARGUMENTS
+.AS "const char" *tkfont
+.AP "Tcl_Interp" *interp in
+Interpreter to use for error reporting. If \fBNULL\fR, then no error
+messages are left after errors.
+.AP Tk_Window tkwin in
+Token for window in which font will be used.
+.AP Tcl_Obj *objPtr in/out
+Gives name or description of font. See documentation
+for the \fBfont\fR command for details on acceptable formats.
+Internal rep will be modified to cache corresponding Tk_Font.
+.AP "const char" *string in
+Same as \fIobjPtr\fR except description of font is passed as a string and
+resulting Tk_Font is not cached.
+.AP Tk_Font tkfont in
+Opaque font token.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_AllocFontFromObj\fR finds the font indicated by \fIobjPtr\fR and
+returns a token that represents the font. The return value can be used
+in subsequent calls to procedures such as \fBTk_GetFontMetrics\fR,
+\fBTk_MeasureChars\fR, and \fBTk_FreeFont\fR. The Tk_Font token
+will remain valid until
+\fBTk_FreeFontFromObj\fR or \fBTk_FreeFont\fR is called to release it.
+\fIObjPtr\fR can contain either a symbolic name or a font description; see
+the documentation for the \fBfont\fR command for a description of the
+valid formats. If \fBTk_AllocFontFromObj\fR is unsuccessful (because,
+for example, \fIobjPtr\fR did not contain a valid font specification) then it
+returns \fBNULL\fR and leaves an error message in \fIinterp\fR's result
+if \fIinterp\fR is not \fBNULL\fR. \fBTk_AllocFontFromObj\fR caches
+information about the return
+value in \fIobjPtr\fR, which speeds up future calls to procedures
+such as \fBTk_AllocFontFromObj\fR and \fBTk_GetFontFromObj\fR.
+.PP
+\fBTk_GetFont\fR is identical to \fBTk_AllocFontFromObj\fR except
+that the description of the font is specified with a string instead
+of an object. This prevents \fBTk_GetFont\fR from caching the
+matching Tk_Font, so \fBTk_GetFont\fR is less efficient than
+\fBTk_AllocFontFromObj\fR.
+.PP
+\fBTk_GetFontFromObj\fR returns the token for an existing font, given
+the window and description used to create the font.
+\fBTk_GetFontFromObj\fR does not actually create the font; the font
+must already have been created with a previous call to
+\fBTk_AllocFontFromObj\fR or \fBTk_GetFont\fR. The return
+value is cached in \fIobjPtr\fR, which speeds up
+future calls to \fBTk_GetFontFromObj\fR with the same \fIobjPtr\fR
+and \fItkwin\fR.
+.PP
+\fBTk_AllocFontFromObj\fR and \fBTk_GetFont\fR maintain
+a database of all fonts they have allocated. If
+the same font is requested multiple times (e.g. by different
+windows or for different purposes), then a single Tk_Font will be
+shared for all uses. The underlying resources will be freed automatically
+when no-one is using the font anymore.
+.PP
+The procedure \fBTk_NameOfFont\fR is roughly the inverse of
+\fBTk_GetFont\fR. Given a \fItkfont\fR that was created by
+\fBTk_GetFont\fR (or \fBTk_AllocFontFromObj\fR), the return value is
+the \fIstring\fR argument that was
+passed to \fBTk_GetFont\fR to create the font. The string returned by
+\fBTk_NameOfFont\fR is only guaranteed to persist until the \fItkfont\fR
+is deleted. The caller must not modify this string.
+.PP
+When a font is no longer needed,
+\fBTk_FreeFontFromObj\fR or \fBTk_FreeFont\fR should be called to
+release it. For \fBTk_FreeFontFromObj\fR the font to release is specified
+with the same information used to create it; for
+\fBTk_FreeFont\fR the font to release is specified
+with its Tk_Font token. There should be
+exactly one call to \fBTk_FreeFontFromObj\fR or \fBTk_FreeFont\fR
+for each call to \fBTk_AllocFontFromObj\fR or \fBTk_GetFont\fR.
+.SH "SEE ALSO"
+Tk_FontId(3)
+.SH KEYWORDS
+font
diff --git a/tk8.6/doc/GetGC.3 b/tk8.6/doc/GetGC.3
new file mode 100644
index 0000000..44e06fb
--- /dev/null
+++ b/tk8.6/doc/GetGC.3
@@ -0,0 +1,70 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_GetGC 3 "" Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_GetGC, Tk_FreeGC \- maintain database of read-only graphics contexts
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+GC
+\fBTk_GetGC\fR(\fItkwin, valueMask, valuePtr\fR)
+.sp
+\fBTk_FreeGC(\fIdisplay, gc\fR)
+.SH ARGUMENTS
+.AS "unsigned long" valueMask
+.AP Tk_Window tkwin in
+Token for window in which the graphics context will be used.
+.AP "unsigned long" valueMask in
+Mask of bits (such as \fBGCForeground\fR or \fBGCStipple\fR)
+indicating which fields of \fI*valuePtr\fR are valid.
+.AP XGCValues *valuePtr in
+Pointer to structure describing the desired values for the
+graphics context.
+.AP Display *display in
+Display for which \fIgc\fR was allocated.
+.AP GC gc in
+X identifier for graphics context that is no longer needed.
+Must have been allocated by \fBTk_GetGC\fR.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_GetGC\fR and \fBTk_FreeGC\fR manage a collection of graphics contexts
+being used by an application. The procedures allow graphics contexts to be
+shared, thereby avoiding the server overhead that would be incurred
+if a separate GC were created for each use. \fBTk_GetGC\fR takes arguments
+describing the desired graphics context and returns an X identifier
+for a GC that fits the description. The graphics context that is returned
+will have default values in all of the fields not specified explicitly
+by \fIvalueMask\fR and \fIvaluePtr\fR.
+.PP
+\fBTk_GetGC\fR maintains a
+database of all the graphics contexts it has created. Whenever possible,
+a call to \fBTk_GetGC\fR will
+return an existing graphics context rather than creating a new one. This
+approach can substantially reduce server overhead, so \fBTk_GetGC\fR
+should generally be used in preference to the Xlib procedure
+\fBXCreateGC\fR, which creates a new graphics context on each call.
+.PP
+Since the return values of \fBTk_GetGC\fR
+are shared, callers should never modify the graphics contexts
+returned by \fBTk_GetGC\fR.
+If a graphics context must be modified dynamically, then it should be
+created by calling \fBXCreateGC\fR instead of \fBTk_GetGC\fR.
+.PP
+When a graphics context
+is no longer needed, \fBTk_FreeGC\fR should be called to release it.
+There should be exactly one call to \fBTk_FreeGC\fR for
+each call to \fBTk_GetGC\fR.
+When a graphics context is no longer in use anywhere (i.e. it has
+been freed as many times as it has been gotten) \fBTk_FreeGC\fR
+will release it to the X server and delete it from the database.
+.SH KEYWORDS
+graphics context
diff --git a/tk8.6/doc/GetHINSTANCE.3 b/tk8.6/doc/GetHINSTANCE.3
new file mode 100644
index 0000000..de38051
--- /dev/null
+++ b/tk8.6/doc/GetHINSTANCE.3
@@ -0,0 +1,22 @@
+'\"
+'\" Copyright (c) 1998-2000 by Scriptics Corporation.
+'\" All rights reserved.
+'\"
+.TH Tk_GetHISTANCE 3 "" Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_GetHINSTANCE \- retrieve the global application instance handle
+.SH SYNOPSIS
+.nf
+\fB#include <tkPlatDecls.h>\fR
+.sp
+HINSTANCE
+\fBTk_GetHINSTANCE\fR()
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_GetHINSTANCE\fR returns the Windows application instance handle
+for the Tk application. This function is only available on Windows platforms.
+.SH KEYWORDS
+identifier, instance
diff --git a/tk8.6/doc/GetHWND.3 b/tk8.6/doc/GetHWND.3
new file mode 100644
index 0000000..1a5ec2d
--- /dev/null
+++ b/tk8.6/doc/GetHWND.3
@@ -0,0 +1,36 @@
+'\"
+'\" Copyright (c) 1998-2000 by Scriptics Corporation.
+'\" All rights reserved.
+'\"
+.TH HWND 3 8.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_GetHWND, Tk_AttachHWND \- manage interactions between the Windows handle and an X window
+.SH SYNOPSIS
+.nf
+\fB#include <tkPlatDecls.h>\fR
+.sp
+HWND
+\fBTk_GetHWND\fR(\fIwindow\fR)
+.sp
+Window
+\fBTk_AttachHWND\fR(\fItkwin, hwnd\fR)
+.SH ARGUMENTS
+.AP Window window in
+X token for window.
+.AP Tk_Window tkwin in
+Tk window for window.
+.AP HWND hwnd in
+Windows HWND for window.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_GetHWND\fR returns the Windows HWND identifier for X Windows
+window given by \fIwindow\fR.
+.PP
+\fBTk_AttachHWND\fR binds the Windows HWND identifier to the
+specified Tk_Window given by \fItkwin\fR. It returns an X Windows
+window that encapsulates the HWND.
+.SH KEYWORDS
+identifier, window
diff --git a/tk8.6/doc/GetImage.3 b/tk8.6/doc/GetImage.3
new file mode 100644
index 0000000..f2407bc
--- /dev/null
+++ b/tk8.6/doc/GetImage.3
@@ -0,0 +1,130 @@
+'\"
+'\" Copyright (c) 1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_GetImage 3 4.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_GetImage, Tk_RedrawImage, Tk_SizeOfImage, Tk_FreeImage \- use an image in a widget
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+Tk_Image
+\fBTk_GetImage\fR(\fIinterp, tkwin, name, changeProc, clientData\fR)
+.sp
+\fBTk_RedrawImage\fR(\fIimage, imageX, imageY, width, height, drawable, drawableX, drawableY\fR)
+.sp
+\fBTk_SizeOfImage\fR(\fIimage, widthPtr, heightPtr\fR)
+.sp
+\fBTk_FreeImage\fR(\fIimage\fR)
+.SH ARGUMENTS
+.AS Tk_ImageChangedProc *changeProc
+.AP Tcl_Interp *interp in
+Place to leave error message.
+.AP Tk_Window tkwin in
+Window in which image will be used.
+.AP "const char" *name in
+Name of image.
+.AP Tk_ImageChangedProc *changeProc in
+Procedure for Tk to invoke whenever image content or size changes.
+.AP ClientData clientData in
+One-word value for Tk to pass to \fIchangeProc\fR.
+.AP Tk_Image image in
+Token for image instance; must have been returned by a previous
+call to \fBTk_GetImage\fR.
+.AP int imageX in
+X-coordinate of upper-left corner of region of image to redisplay
+(measured in pixels from the image's upper-left corner).
+.AP int imageY in
+Y-coordinate of upper-left corner of region of image to redisplay
+(measured in pixels from the image's upper-left corner).
+.AP "int" width (in)
+Width of region of image to redisplay.
+.AP "int" height (in)
+Height of region of image to redisplay.
+.AP Drawable drawable in
+Where to display image. Must either be window specified to
+\fBTk_GetImage\fR or a pixmap compatible with that window.
+.AP int drawableX in
+Where to display image in \fIdrawable\fR: this is the x-coordinate
+in \fIdrawable\fR where x-coordinate \fIimageX\fR of the image
+should be displayed.
+.AP int drawableY in
+Where to display image in \fIdrawable\fR: this is the y-coordinate
+in \fIdrawable\fR where y-coordinate \fIimageY\fR of the image
+should be displayed.
+.AP "int" widthPtr out
+Store width of \fIimage\fR (in pixels) here.
+.AP "int" heightPtr out
+Store height of \fIimage\fR (in pixels) here.
+.BE
+.SH DESCRIPTION
+.PP
+These procedures are invoked by widgets that wish to display images.
+\fBTk_GetImage\fR is invoked by a widget when it first decides to
+display an image.
+\fIname\fR gives the name of the desired image and \fItkwin\fR
+identifies the window where the image will be displayed.
+\fBTk_GetImage\fR looks up the image in the table of existing
+images and returns a token for a new instance of the image.
+If the image does not exist then \fBTk_GetImage\fR returns NULL
+and leaves an error message in interpreter \fIinterp\fR's result.
+.PP
+When a widget wishes to actually display an image it must
+call \fBTk_RedrawImage\fR, identifying the image (\fIimage\fR),
+a region within the image to redisplay (\fIimageX\fR, \fIimageY\fR,
+\fIwidth\fR, and \fIheight\fR), and a place to display the
+image (\fIdrawable\fR, \fIdrawableX\fR, and \fIdrawableY\fR).
+Tk will then invoke the appropriate image manager, which will
+display the requested portion of the image before returning.
+.PP
+A widget can find out the dimensions of an image by calling
+\fBTk_SizeOfImage\fR: the width and height will be stored
+in the locations given by \fIwidthPtr\fR and \fIheightPtr\fR,
+respectively.
+.PP
+When a widget is finished with an image (e.g., the widget is
+being deleted or it is going to use a different image instead
+of the current one), it must call \fBTk_FreeImage\fR to
+release the image instance.
+The widget should never again use the image token after passing
+it to \fBTk_FreeImage\fR.
+There must be exactly one call to \fBTk_FreeImage\fR for each
+call to \fBTk_GetImage\fR.
+.PP
+If the contents or size of an image changes, then any widgets
+using the image will need to find out about the changes so that
+they can redisplay themselves.
+The \fIchangeProc\fR and \fIclientData\fR arguments to
+\fBTk_GetImage\fR are used for this purpose.
+\fIchangeProc\fR will be called by Tk whenever a change occurs
+in the image; it must match the following prototype:
+.CS
+typedef void \fBTk_ImageChangedProc\fR(
+ ClientData \fIclientData\fR,
+ int \fIx\fR,
+ int \fIy\fR,
+ int \fIwidth\fR,
+ int \fIheight\fR,
+ int \fIimageWidth\fR,
+ int \fIimageHeight\fR);
+.CE
+The \fIclientData\fR argument to \fIchangeProc\fR is the same as the
+\fIclientData\fR argument to \fBTk_GetImage\fR.
+It is usually a pointer to the widget record for the widget or
+some other data structure managed by the widget.
+The arguments \fIx\fR, \fIy\fR, \fIwidth\fR, and \fIheight\fR
+identify a region within the image that must be redisplayed;
+they are specified in pixels measured from the upper-left
+corner of the image.
+The arguments \fIimageWidth\fR and \fIimageHeight\fR give
+the image's (new) size.
+.SH "SEE ALSO"
+Tk_CreateImageType
+.SH KEYWORDS
+images, redisplay
diff --git a/tk8.6/doc/GetJoinStl.3 b/tk8.6/doc/GetJoinStl.3
new file mode 100644
index 0000000..a717b72
--- /dev/null
+++ b/tk8.6/doc/GetJoinStl.3
@@ -0,0 +1,63 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_GetJoinStyle 3 "" Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_GetJoinStyle, Tk_NameOfJoinStyle \- translate between strings and join styles
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+int
+\fBTk_GetJoinStyle(\fIinterp, string, joinPtr\fB)\fR
+.sp
+const char *
+\fBTk_NameOfJoinStyle(\fIjoin\fB)\fR
+.SH ARGUMENTS
+.AS "Tcl_Interp" *joinPtr
+.AP Tcl_Interp *interp in
+Interpreter to use for error reporting.
+.AP "const char" *string in
+String containing name of join style \- one of
+.QW \fBbevel\fR ,
+.QW \fBmiter\fR ,
+or
+.QW \fBround\fR
+\- or a unique abbreviation of one.
+.AP int *joinPtr out
+Pointer to location in which to store X join style corresponding to
+\fIstring\fR.
+.AP int join in
+Join style: one of \fBJoinBevel\fR, \fBJoinMiter\fR, \fBJoinRound\fR.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_GetJoinStyle\fR places in \fI*joinPtr\fR the X join style
+corresponding to \fIstring\fR, which will be one of
+\fBJoinBevel\fR, \fBJoinMiter\fR, or \fBJoinRound\fR.
+Join styles are typically used in X graphics contexts to indicate
+how adjacent line segments should be joined together.
+See the X documentation for information on what each style
+implies.
+.PP
+Under normal circumstances the return value is \fBTCL_OK\fR and
+\fIinterp\fR is unused.
+If \fIstring\fR does not contain a valid join style
+or an abbreviation of one of these names, then an error message is
+stored in interpreter \fIinterp\fR's result, \fBTCL_ERROR\fR is returned, and
+\fI*joinPtr\fR is unmodified.
+.PP
+\fBTk_NameOfJoinStyle\fR is the logical inverse of \fBTk_GetJoinStyle\fR.
+Given a join style such as \fBJoinBevel\fR it returns a
+statically-allocated string corresponding to \fIjoin\fR.
+If \fIjoin\fR is not a legal join style, then
+.QW "unknown join style"
+is returned.
+.SH KEYWORDS
+bevel, join style, miter, round
diff --git a/tk8.6/doc/GetJustify.3 b/tk8.6/doc/GetJustify.3
new file mode 100644
index 0000000..b51cb8d
--- /dev/null
+++ b/tk8.6/doc/GetJustify.3
@@ -0,0 +1,87 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-1998 Sun Microsystems, Inc.
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH Tk_GetJustifyFromObj 3 8.1 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_GetJustifyFromObj, Tk_GetJustify, Tk_NameOfJustify \- translate between strings and justification styles
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+int
+\fBTk_GetJustifyFromObj(\fIinterp, objPtr, justifyPtr\fB)\fR
+.sp
+int
+\fBTk_GetJustify(\fIinterp, string, justifyPtr\fB)\fR
+.sp
+const char *
+\fBTk_NameOfJustify(\fIjustify\fB)\fR
+.SH ARGUMENTS
+.AS "Tk_Justify" *justifyPtr
+.AP Tcl_Interp *interp in
+Interpreter to use for error reporting, or NULL.
+.AP Tcl_Obj *objPtr in/out
+String value contains name of justification style \- one of
+.QW \fBleft\fR ,
+.QW \fBright\fR ,
+or
+.QW \fBcenter\fR
+\- or a unique abbreviation of one.
+The internal rep will be modified to cache corresponding justify value.
+.AP "const char" *string in
+Same as \fIobjPtr\fR except description of justification style is passed as
+a string.
+.AP int *justifyPtr out
+Pointer to location in which to store justify value corresponding to
+\fIobjPtr\fR or \fIstring\fR.
+.AP Tk_Justify justify in
+Justification style (one of the values listed below).
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_GetJustifyFromObj\fR places in \fI*justifyPtr\fR the justify value
+corresponding to \fIobjPtr\fR's value.
+This value will be one of the following:
+.TP
+\fBTK_JUSTIFY_LEFT\fR
+Means that the text on each line should start at the left edge of
+the line; as a result, the right edges of lines may be ragged.
+.TP
+\fBTK_JUSTIFY_RIGHT\fR
+Means that the text on each line should end at the right edge of
+the line; as a result, the left edges of lines may be ragged.
+.TP
+\fBTK_JUSTIFY_CENTER\fR
+Means that the text on each line should be centered; as a result,
+both the left and right edges of lines may be ragged.
+.PP
+Under normal circumstances the return value is \fBTCL_OK\fR and
+\fIinterp\fR is unused.
+If \fIobjPtr\fR does not contain a valid justification style
+or an abbreviation of one of these names, \fBTCL_ERROR\fR is returned,
+\fI*justifyPtr\fR is unmodified, and an error message is
+stored in \fIinterp\fR's result if \fIinterp\fR is not NULL.
+\fBTk_GetJustifyFromObj\fR caches information about the return
+value in \fIobjPtr\fR, which speeds up future calls to
+\fBTk_GetJustifyFromObj\fR with the same \fIobjPtr\fR.
+.PP
+\fBTk_GetJustify\fR is identical to \fBTk_GetJustifyFromObj\fR except
+that the description of the justification is specified with a string instead
+of an object. This prevents \fBTk_GetJustify\fR from caching the
+return value, so \fBTk_GetJustify\fR is less efficient than
+\fBTk_GetJustifyFromObj\fR.
+.PP
+\fBTk_NameOfJustify\fR is the logical inverse of \fBTk_GetJustify\fR.
+Given a justify value it returns a statically-allocated string
+corresponding to \fIjustify\fR.
+If \fIjustify\fR is not a legal justify value, then
+.QW "unknown justification style"
+is returned.
+.SH KEYWORDS
+center, fill, justification, string
diff --git a/tk8.6/doc/GetOption.3 b/tk8.6/doc/GetOption.3
new file mode 100644
index 0000000..81846ad
--- /dev/null
+++ b/tk8.6/doc/GetOption.3
@@ -0,0 +1,42 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_GetOption 3 "" Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_GetOption \- retrieve an option from the option database
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+Tk_Uid
+\fBTk_GetOption\fR(\fItkwin, name, class\fR)
+.SH ARGUMENTS
+.AS Tk_Window *class
+.AP Tk_Window tkwin in
+Token for window.
+.AP "const char" *name in
+Name of desired option.
+.AP "const char" *class in
+Class of desired option. Null means there is no class for
+this option; do lookup based on name only.
+.BE
+.SH DESCRIPTION
+.PP
+This procedure is invoked to retrieve an option from the database
+associated with \fItkwin\fR's main window. If there is an option
+for \fItkwin\fR that matches the given \fIname\fR or \fIclass\fR,
+then it is returned in the form of a Tk_Uid. If multiple options
+match \fIname\fR and \fIclass\fR, then the highest-priority one
+is returned. If no option matches, then NULL is returned.
+.PP
+\fBTk_GetOption\fR caches options related to \fItkwin\fR so that
+successive calls for the same \fItkwin\fR will execute much more
+quickly than successive calls for different windows.
+.SH KEYWORDS
+class, name, option, retrieve
diff --git a/tk8.6/doc/GetPixels.3 b/tk8.6/doc/GetPixels.3
new file mode 100644
index 0000000..e7a9043
--- /dev/null
+++ b/tk8.6/doc/GetPixels.3
@@ -0,0 +1,95 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-1998 Sun Microsystems, Inc.
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH Tk_GetPixelsFromObj 3 8.1 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_GetPixelsFromObj, Tk_GetPixels, Tk_GetMMFromObj, Tk_GetScreenMM \- translate between strings and screen units
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+int
+\fBTk_GetPixelsFromObj(\fIinterp, tkwin, objPtr, intPtr\fB)\fR
+.sp
+int
+\fBTk_GetPixels(\fIinterp, tkwin, string, intPtr\fB)\fR
+.sp
+int
+\fBTk_GetMMFromObj(\fIinterp, tkwin, objPtr, doublePtr\fB)\fR
+.sp
+int
+\fBTk_GetScreenMM(\fIinterp, tkwin, string, doublePtr\fB)\fR
+.SH ARGUMENTS
+.AS "Tcl_Interp" *joinPtr
+.AP Tcl_Interp *interp in
+Interpreter to use for error reporting.
+.AP Tk_Window tkwin in
+Window whose screen geometry determines the conversion between absolute
+units and pixels.
+.AP Tcl_Obj *objPtr in/out
+String value specifies a distance on the screen;
+internal rep will be modified to cache converted distance.
+.AP "const char" *string in
+Same as \fIobjPtr\fR except specification of distance is passed as
+a string.
+.AP int *intPtr out
+Pointer to location in which to store converted distance in pixels.
+.AP double *doublePtr out
+Pointer to location in which to store converted distance in millimeters.
+.BE
+.SH DESCRIPTION
+.PP
+These procedures take as argument a specification of distance on
+the screen (\fIobjPtr\fR or \fIstring\fR) and compute the
+corresponding distance either in integer pixels or floating-point millimeters.
+In either case,
+\fIobjPtr\fR or \fIstring\fR
+specifies a screen distance as a
+floating-point number followed by one of the following characters
+that indicates units:
+.TP
+<none>
+The number specifies a distance in pixels.
+.TP
+\fBc\fR
+The number specifies a distance in centimeters on the screen.
+.TP
+\fBi\fR
+The number specifies a distance in inches on the screen.
+.TP
+\fBm\fR
+The number specifies a distance in millimeters on the screen.
+.TP
+\fBp\fR
+The number specifies a distance in printer's points (1/72 inch)
+on the screen.
+.PP
+\fBTk_GetPixelsFromObj\fR converts the value of \fIobjPtr\fR to the
+nearest even number of pixels and stores that value at \fI*intPtr\fR.
+It returns \fBTCL_OK\fR under normal circumstances.
+If an error occurs (e.g. \fIobjPtr\fR contains a number followed
+by a character that is not one of the ones above) then
+\fBTCL_ERROR\fR is returned and an error message is left
+in \fIinterp\fR's result if \fIinterp\fR is not NULL.
+\fBTk_GetPixelsFromObj\fR caches information about the return
+value in \fIobjPtr\fR, which speeds up future calls to
+\fBTk_GetPixelsFromObj\fR with the same \fIobjPtr\fR.
+.PP
+\fBTk_GetPixels\fR is identical to \fBTk_GetPixelsFromObj\fR except
+that the screen distance is specified with a string instead
+of an object. This prevents \fBTk_GetPixels\fR from caching the
+return value, so \fBTk_GetPixels\fR is less efficient than
+\fBTk_GetPixelsFromObj\fR.
+.PP
+\fBTk_GetMMFromObj\fR and \fBTk_GetScreenMM\fR are similar to
+\fBTk_GetPixelsFromObj\fR and \fBTk_GetPixels\fR (respectively) except
+that they convert the screen distance to millimeters and
+store a double-precision floating-point result at \fI*doublePtr\fR.
+.SH KEYWORDS
+centimeters, convert, inches, millimeters, pixels, points, screen units
diff --git a/tk8.6/doc/GetPixmap.3 b/tk8.6/doc/GetPixmap.3
new file mode 100644
index 0000000..927c75c
--- /dev/null
+++ b/tk8.6/doc/GetPixmap.3
@@ -0,0 +1,52 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_GetPixmap 3 4.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_GetPixmap, Tk_FreePixmap \- allocate and free pixmaps
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+Pixmap
+\fBTk_GetPixmap(\fIdisplay, d, width, height, depth\fB)\fR
+.sp
+\fBTk_FreePixmap(\fIdisplay, pixmap\fB)\fR
+.SH ARGUMENTS
+.AS "Drawable" *pixelPtr
+.AP Display *display in
+X display for the pixmap.
+.AP Drawable d in
+Pixmap or window where the new pixmap will be used for drawing.
+.AP "int" width in
+Width of pixmap.
+.AP "int" height in
+Height of pixmap.
+.AP "int" depth in
+Number of bits per pixel in pixmap.
+.AP Pixmap pixmap in
+Pixmap to destroy.
+.BE
+.SH DESCRIPTION
+.PP
+These procedures are identical to the Xlib procedures \fBXCreatePixmap\fR
+and \fBXFreePixmap\fR, except that they have extra code to manage X
+resource identifiers so that identifiers for deleted pixmaps can be
+reused in the future.
+It is important for Tk applications to use these procedures rather
+than \fBXCreatePixmap\fR and \fBXFreePixmap\fR; otherwise long-running
+applications may run out of resource identifiers.
+.PP
+\fBTk_GetPixmap\fR creates a pixmap suitable for drawing in \fId\fR,
+with dimensions given by \fIwidth\fR, \fIheight\fR, and \fIdepth\fR,
+and returns its identifier.
+\fBTk_FreePixmap\fR destroys the pixmap given by \fIpixmap\fR and makes
+its resource identifier available for reuse.
+.SH KEYWORDS
+pixmap, resource identifier
diff --git a/tk8.6/doc/GetRelief.3 b/tk8.6/doc/GetRelief.3
new file mode 100644
index 0000000..6e8681a
--- /dev/null
+++ b/tk8.6/doc/GetRelief.3
@@ -0,0 +1,82 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-1998 Sun Microsystems, Inc.
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH Tk_GetReliefFromObj 3 8.1 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_GetReliefFromObj, Tk_GetRelief, Tk_NameOfRelief \- translate between strings and relief values
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+int
+\fBTk_GetReliefFromObj(\fIinterp, objPtr, reliefPtr\fB)\fR
+.sp
+int
+\fBTk_GetRelief(\fIinterp, name, reliefPtr\fB)\fR
+.sp
+const char *
+\fBTk_NameOfRelief(\fIrelief\fB)\fR
+.SH ARGUMENTS
+.AS "Tcl_Interp" *reliefPtr
+.AP Tcl_Interp *interp in
+Interpreter to use for error reporting.
+.AP Tcl_Obj *objPtr in/out
+String value contains name of relief, one of
+.QW \fBflat\fR ,
+.QW \fBgroove\fR ,
+.QW \fBraised\fR ,
+.QW \fBridge\fR ,
+.QW \fBsolid\fR ,
+or
+.QW \fBsunken\fR
+(or any unique abbreviation thereof on input);
+the internal rep will be modified to cache corresponding relief value.
+.AP char *string in
+Same as \fIobjPtr\fR except description of relief is passed as
+a string.
+.AP int *reliefPtr out
+Pointer to location in which to store relief value corresponding to
+\fIobjPtr\fR or \fIname\fR.
+.AP "const char" *name
+Name of the relief.
+.AP int relief in
+Relief value (one of \fBTK_RELIEF_FLAT\fR, \fBTK_RELIEF_RAISED\fR,
+\fBTK_RELIEF_SUNKEN\fR, \fBTK_RELIEF_GROOVE\fR, \fBTK_RELIEF_SOLID\fR,
+or \fBTK_RELIEF_RIDGE\fR).
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_GetReliefFromObj\fR places in \fI*reliefPtr\fR the relief value
+corresponding to the value of \fIobjPtr\fR. This value will be one of
+\fBTK_RELIEF_FLAT\fR, \fBTK_RELIEF_RAISED\fR, \fBTK_RELIEF_SUNKEN\fR,
+\fBTK_RELIEF_GROOVE\fR, \fBTK_RELIEF_SOLID\fR, or \fBTK_RELIEF_RIDGE\fR.
+Under normal circumstances the return value is \fBTCL_OK\fR and
+\fIinterp\fR is unused.
+If \fIobjPtr\fR does not contain one of the valid relief names
+or an abbreviation of one of them, then \fBTCL_ERROR\fR is returned,
+\fI*reliefPtr\fR is unmodified, and an error message
+is stored in \fIinterp\fR's result if \fIinterp\fR is not NULL.
+\fBTk_GetReliefFromObj\fR caches information about the return
+value in \fIobjPtr\fR, which speeds up future calls to
+\fBTk_GetReliefFromObj\fR with the same \fIobjPtr\fR.
+.PP
+\fBTk_GetRelief\fR is identical to \fBTk_GetReliefFromObj\fR except
+that the description of the relief is specified with a string instead
+of an object. This prevents \fBTk_GetRelief\fR from caching the
+return value, so \fBTk_GetRelief\fR is less efficient than
+\fBTk_GetReliefFromObj\fR.
+.PP
+\fBTk_NameOfRelief\fR is the logical inverse of \fBTk_GetRelief\fR.
+Given a relief value it returns the corresponding string (\fBflat\fR,
+\fBraised\fR, \fBsunken\fR, \fBgroove\fR, \fBsolid\fR, or \fBridge\fR).
+If \fIrelief\fR is not a legal relief value, then
+.QW "unknown relief"
+is returned.
+.SH KEYWORDS
+name, relief, string
diff --git a/tk8.6/doc/GetRootCrd.3 b/tk8.6/doc/GetRootCrd.3
new file mode 100644
index 0000000..a9d2cd9
--- /dev/null
+++ b/tk8.6/doc/GetRootCrd.3
@@ -0,0 +1,39 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_GetRootCoords 3 "" Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_GetRootCoords \- Compute root-window coordinates of window
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+\fBTk_GetRootCoords\fR(\fItkwin, xPtr, yPtr\fR)
+.SH ARGUMENTS
+.AS Tk_Window tkwin
+.AP Tk_Window tkwin in
+Token for window.
+.AP int *xPtr out
+Pointer to location in which to store root-window x-coordinate
+corresponding to left edge of \fItkwin\fR's border.
+.AP int *yPtr out
+Pointer to location in which to store root-window y-coordinate
+corresponding to top edge of \fItkwin\fR's border.
+.BE
+.SH DESCRIPTION
+.PP
+This procedure scans through the structural information maintained
+by Tk to compute the root-window coordinates corresponding to
+the upper-left corner of \fItkwin\fR's border. If \fItkwin\fR has
+no border, then \fBTk_GetRootCoords\fR returns the root-window
+coordinates corresponding to location (0,0) in \fItkwin\fR.
+\fBTk_GetRootCoords\fR is relatively efficient, since it does not have to
+communicate with the X server.
+.SH KEYWORDS
+coordinates, root window
diff --git a/tk8.6/doc/GetScroll.3 b/tk8.6/doc/GetScroll.3
new file mode 100644
index 0000000..a71986d
--- /dev/null
+++ b/tk8.6/doc/GetScroll.3
@@ -0,0 +1,75 @@
+'\"
+'\" Copyright (c) 1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_GetScrollInfo 3 8.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_GetScrollInfoObj, Tk_GetScrollInfo \- parse arguments for scrolling commands
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+int
+\fBTk_GetScrollInfoObj(\fIinterp, objc, objv, fractionPtr, stepsPtr\fB)\fR
+.sp
+int
+\fBTk_GetScrollInfo(\fIinterp, argc, argv, fractionPtr, stepsPtr\fB)\fR
+.SH ARGUMENTS
+.AS "Tcl_Interp" *fractionPtr
+.AP Tcl_Interp *interp in
+Interpreter to use for error reporting.
+.AP int objc in
+Number of Tcl_Obj's in \fIobjv\fR array.
+.AP "Tcl_Obj *const" objv[] in
+Argument objects. These represent the entire widget command, of
+which the first word is typically the widget name and the second
+word is typically \fBxview\fR or \fByview\fR.
+.AP int argc in
+Number of strings in \fIargv\fR array.
+.AP "const char" *argv[] in
+Argument strings. These represent the entire widget command, of
+which the first word is typically the widget name and the second
+word is typically \fBxview\fR or \fByview\fR.
+.AP double *fractionPtr out
+Filled in with fraction from \fBmoveto\fR option, if any.
+.AP int *stepsPtr out
+Filled in with line or page count from \fBscroll\fR option, if any.
+The value may be negative.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_GetScrollInfoObj\fR parses the arguments expected by widget
+scrolling commands such as \fBxview\fR and \fByview\fR.
+It receives the entire list of words that make up a widget command
+and parses the words starting with \fIobjv\fR[2].
+The words starting with \fIobjv\fR[2] must have one of the following forms:
+.CS
+\fBmoveto \fIfraction\fR
+\fBscroll \fInumber\fB units\fR
+\fBscroll \fInumber\fB pages\fR
+.CE
+.LP
+Any of the \fBmoveto\fR, \fBscroll\fR, \fBunits\fR, and \fBpages\fR
+keywords may be abbreviated.
+If \fIobjv\fR has the \fBmoveto\fR form, \fBTK_SCROLL_MOVETO\fR
+is returned as result and \fI*fractionPtr\fR is filled in with the
+\fIfraction\fR argument to the command, which must be a proper real
+value.
+If \fIobjv\fR has the \fBscroll\fR form, \fBTK_SCROLL_UNITS\fR
+or \fBTK_SCROLL_PAGES\fR is returned and \fI*stepsPtr\fR is filled
+in with the \fInumber\fR value, which must be a proper integer.
+If an error occurs in parsing the arguments, \fBTK_SCROLL_ERROR\fR
+is returned and an error message is left in interpreter
+\fIinterp\fR's result.
+.PP
+\fBTk_GetScrollInfo\fR is identical in function to
+\fBTk_GetScrollInfoObj\fR. However, \fBTk_GetScrollInfo\fR accepts
+string arguments, making it more appropriate for use with legacy
+widgets.
+.SH KEYWORDS
+parse, scrollbar, scrolling command, xview, yview
diff --git a/tk8.6/doc/GetSelect.3 b/tk8.6/doc/GetSelect.3
new file mode 100644
index 0000000..8c30a2b
--- /dev/null
+++ b/tk8.6/doc/GetSelect.3
@@ -0,0 +1,78 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_GetSelection 3 4.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_GetSelection \- retrieve the contents of a selection
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+int
+\fBTk_GetSelection\fR(\fIinterp, tkwin, selection, target, proc, clientData\fR)
+.SH ARGUMENTS
+.AS Tk_GetSelProc clientData
+.AP Tcl_Interp *interp in
+Interpreter to use for reporting errors.
+.AP Tk_Window tkwin in
+Window on whose behalf to retrieve the selection (determines
+display from which to retrieve).
+.AP Atom selection in
+The name of the selection to be retrieved.
+.AP Atom target in
+Form in which to retrieve selection.
+.AP Tk_GetSelProc *proc in
+Procedure to invoke to process pieces of the selection as they
+are retrieved.
+.AP ClientData clientData in
+Arbitrary one-word value to pass to \fIproc\fR.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_GetSelection\fR retrieves the selection specified by the atom
+\fIselection\fR in the format specified by \fItarget\fR. The
+selection may actually be retrieved in several pieces; as each piece
+is retrieved, \fIproc\fR is called to process the piece. \fIProc\fR
+should have arguments and result that match the type
+\fBTk_GetSelProc\fR:
+.PP
+.CS
+typedef int \fBTk_GetSelProc\fR(
+ ClientData \fIclientData\fR,
+ Tcl_Interp *\fIinterp\fR,
+ char *\fIportion\fR);
+.CE
+.PP
+The \fIclientData\fR and \fIinterp\fR parameters to \fIproc\fR
+will be copies of the corresponding arguments to
+\fBTk_GetSelection\fR. \fIPortion\fR will be a pointer to
+a string containing part or all of the selection. For large
+selections, \fIproc\fR will be called several times with successive
+portions of the selection. The X Inter-Client Communication
+Conventions Manual allows a selection to be returned in formats
+other than strings, e.g. as an array of atoms or integers. If
+this happens, Tk converts the selection back into a string
+before calling \fIproc\fR. If a selection is returned as an
+array of atoms, Tk converts it to a string containing the atom names
+separated by white space. For any other format besides string,
+Tk converts a selection to a string containing hexadecimal
+values separated by white space.
+.PP
+\fBTk_GetSelection\fR returns to its caller when the selection has
+been completely retrieved and processed by \fIproc\fR, or when a
+fatal error has occurred (e.g. the selection owner did not respond
+promptly). \fBTk_GetSelection\fR normally returns \fBTCL_OK\fR; if
+an error occurs, it returns \fBTCL_ERROR\fR and leaves an error message
+in interpreter \fIinterp\fR's result. \fIProc\fR should also return either
+\fBTCL_OK\fR or \fBTCL_ERROR\fR. If \fIproc\fR encounters an error in
+dealing with the selection, it should leave an error message in the
+interpreter result and return \fBTCL_ERROR\fR; this will abort the
+selection retrieval.
+.SH KEYWORDS
+format, get, selection retrieval
diff --git a/tk8.6/doc/GetUid.3 b/tk8.6/doc/GetUid.3
new file mode 100644
index 0000000..06b466a
--- /dev/null
+++ b/tk8.6/doc/GetUid.3
@@ -0,0 +1,45 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_GetUid 3 "" Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_GetUid, Tk_Uid \- convert from string to unique identifier
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+Tk_Uid
+\fBTk_GetUid\fR(\fIstring\fR)
+.SH ARGUMENTS
+.AP char *string in
+String for which the corresponding unique identifier is
+desired.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_GetUid\fR returns the unique identifier corresponding
+to \fIstring\fR.
+Unique identifiers are similar to atoms in Lisp, and are used
+in Tk to speed up comparisons and
+searches. A unique identifier (type Tk_Uid) is a string pointer
+and may be used anywhere that a variable of type
+.QW "char *"
+could be used. However, there is guaranteed to be exactly
+one unique identifier for any given string value. If \fBTk_GetUid\fR
+is called twice, once with string \fIa\fR and once with string
+\fIb\fR, and if \fIa\fR and \fIb\fR have the same string value
+(strcmp(a, b) == 0), then \fBTk_GetUid\fR will return exactly
+the same Tk_Uid value for each call (Tk_GetUid(a) == Tk_GetUid(b)).
+This means that variables of type
+Tk_Uid may be compared directly (x == y) without having to call
+\fBstrcmp\fR.
+In addition, the return value from \fBTk_GetUid\fR will have the
+same string value as its argument (strcmp(Tk_GetUid(a), a) == 0).
+.SH KEYWORDS
+atom, unique identifier
diff --git a/tk8.6/doc/GetVRoot.3 b/tk8.6/doc/GetVRoot.3
new file mode 100644
index 0000000..a65ef78
--- /dev/null
+++ b/tk8.6/doc/GetVRoot.3
@@ -0,0 +1,46 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_GetVRootGeometry 3 4.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_GetVRootGeometry \- Get location and size of virtual root for window
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+\fBTk_GetVRootGeometry(\fItkwin, xPtr, yPtr, widthPtr, heightPtr\fB)\fR
+.SH ARGUMENTS
+.AS Tk_Window heightPtr
+.AP Tk_Window tkwin in
+Token for window whose virtual root is to be queried.
+.AP int xPtr out
+Points to word in which to store x-offset of virtual root.
+.AP int yPtr out
+Points to word in which to store y-offset of virtual root.
+.AP "int" widthPtr out
+Points to word in which to store width of virtual root.
+.AP "int" heightPtr out
+Points to word in which to store height of virtual root.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_GetVRootGeometry\fR returns geometry information about the virtual
+root window associated with \fItkwin\fR. The
+.QW associated
+virtual root is the one in which \fItkwin\fR's nearest top-level ancestor (or
+\fItkwin\fR itself if it is a top-level window) has
+been reparented by the window manager. This window is identified by
+a \fB__SWM_ROOT\fR or \fB__WM_ROOT\fR property placed on the top-level
+window by the window manager.
+If \fItkwin\fR is not associated with a virtual root (e.g.
+because the window manager does not use virtual roots) then *\fIxPtr\fR and
+*\fIyPtr\fR will be set to 0 and *\fIwidthPtr\fR and *\fIheightPtr\fR
+will be set to the dimensions of the screen containing \fItkwin\fR.
+.SH KEYWORDS
+geometry, height, location, virtual root, width, window manager
diff --git a/tk8.6/doc/GetVisual.3 b/tk8.6/doc/GetVisual.3
new file mode 100644
index 0000000..fe3d50c
--- /dev/null
+++ b/tk8.6/doc/GetVisual.3
@@ -0,0 +1,100 @@
+'\"
+'\" Copyright (c) 1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_GetVisual 3 4.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_GetVisual \- translate from string to visual
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+Visual *
+\fBTk_GetVisual(\fIinterp, tkwin, string, depthPtr, colormapPtr\fB)\fR
+.SH ARGUMENTS
+.AS "Tcl_Interp" *colormapPtr
+.AP Tcl_Interp *interp in
+Interpreter to use for error reporting.
+.AP Tk_Window tkwin in
+Token for window in which the visual will be used.
+.AP "const char" *string in
+String that identifies the desired visual. See below for
+valid formats.
+.AP int *depthPtr out
+Depth of returned visual gets stored here.
+.AP Colormap *colormapPtr out
+If non-NULL then a suitable colormap for visual is found and its
+identifier is stored here.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_GetVisual\fR takes a string description of a visual and
+finds a suitable X Visual for use in \fItkwin\fR, if there is one.
+It returns a pointer to the X Visual structure for the visual
+and stores the number of bits per pixel for it at \fI*depthPtr\fR.
+If \fIstring\fR is unrecognizable or if no suitable visual could
+be found, then NULL is returned and \fBTk_GetVisual\fR leaves
+an error message in interpreter \fIinterp\fR's result.
+If \fIcolormap\fR is non-NULL then \fBTk_GetVisual\fR
+also locates an appropriate colormap for use with the result visual
+and stores its X identifier at \fI*colormapPtr\fR.
+.PP
+The \fIstring\fR argument specifies the desired visual in one
+of the following ways:
+.TP 15
+\fIclass depth\fR
+The string consists of a class name followed by an integer depth,
+with any amount of white space (including none) in between.
+\fIclass\fR selects what sort of visual is desired and must be one of
+\fBdirectcolor\fR, \fBgrayscale\fR, \fBgreyscale\fR, \fBpseudocolor\fR,
+\fBstaticcolor\fR, \fBstaticgray\fR, \fBstaticgrey\fR, or
+\fBtruecolor\fR, or a unique abbreviation.
+\fIdepth\fR specifies how many bits per pixel are needed for the
+visual.
+If possible, \fBTk_GetVisual\fR will return a visual with this depth;
+if there is no visual of the desired depth then \fBTk_GetVisual\fR
+looks first for a visual with greater depth, then one with less
+depth.
+.TP 15
+\fBdefault\fR
+Use the default visual for \fItkwin\fR's screen.
+.TP 15
+\fIpathName\fR
+Use the visual for the window given by \fIpathName\fR.
+\fIpathName\fR must be the name of a window on the same screen
+as \fItkwin\fR.
+.TP 15
+\fInumber\fR
+Use the visual whose X identifier is \fInumber\fR.
+.TP 15
+\fBbest\fR ?\fIdepth\fR?
+Choose the
+.QW "best possible"
+visual, using the following rules, in decreasing order of priority:
+.RS
+.IP (a)
+a visual that has exactly the desired depth is best, followed
+by a visual with greater depth than requested (but as little extra
+as possible), followed by a visual with less depth than requested
+(but as great a depth as possible);
+.IP (b)
+if no \fIdepth\fR is specified, then the deepest available visual
+is chosen;
+.IP (c)
+\fBpseudocolor\fR is better than \fBtruecolor\fR or \fBdirectcolor\fR,
+which are better than \fBstaticcolor\fR, which is better than
+\fBstaticgray\fR or \fBgrayscale\fR;
+.IP (d)
+the default visual for the screen is better than any other visual.
+.RE
+.SH CREDITS
+.PP
+The idea for \fBTk_GetVisual\fR, and the first implementation, came
+from Paul Mackerras.
+.SH KEYWORDS
+colormap, screen, visual
diff --git a/tk8.6/doc/Grab.3 b/tk8.6/doc/Grab.3
new file mode 100644
index 0000000..1dba2df
--- /dev/null
+++ b/tk8.6/doc/Grab.3
@@ -0,0 +1,58 @@
+'\"
+'\" Copyright (c) 1998-2000 by Scriptics Corporation.
+'\" All rights reserved.
+'\"
+.TH Tk_Grab 3 "" Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_Grab, Tk_Ungrab \- manipulate grab state in an application
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+int
+\fBTk_Grab\fR(\fIinterp, tkwin, grabGlobal\fR)
+.sp
+void
+\fBTk_Ungrab\fR(\fItkwin\fR)
+.SH ARGUMENTS
+.AP Tcl_Interp *interp in
+Interpreter to use for error reporting
+.AP Tk_Window tkwin in
+Window on whose behalf the pointer is to be grabbed or released
+.AP int grabGlobal in
+Boolean indicating whether the grab is global or application local
+.BE
+.SH DESCRIPTION
+.PP
+These functions are used to set or release a global or
+application local grab. When a grab is set on a particular window
+in a Tk application, mouse and keyboard events can only be received by
+that window and its descendants. Mouse and keyboard events for
+windows outside the tree rooted at \fItkwin\fR will be redirected to
+\fItkwin\fR. If the grab is global, then all mouse and keyboard
+events for windows outside the tree rooted at \fItkwin\fR (even those
+intended for windows in other applications) will be redirected to
+\fItkwin\fR. If the grab is application local, only mouse and
+keyboard events intended for a windows within the same application
+(but outside the tree rooted at \fItkwin\fR) will be redirected.
+.PP
+\fBTk_Grab\fR sets a grab on a particular window. \fITkwin\fR
+specifies the window on whose behalf the pointer is to be grabbed.
+\fIGrabGlobal\fR indicates whether the grab should be global or
+application local; if it is non-zero, it means the grab should be
+global. Normally, \fBTk_Grab\fR returns \fBTCL_OK\fR; if an error occurs
+and the grab cannot be set, \fBTCL_ERROR\fR is returned and an error message
+is left if \fIinterp\fR's result. Once this call completes
+successfully, no window outside the tree rooted at \fItkwin\fR will
+receive pointer- or keyboard-related events until the next call to
+Tk_Ungrab. If a previous grab was in effect within the application,
+then it is replaced with a new one.
+.PP
+\fBTk_Ungrab\fR releases a grab on the mouse pointer and keyboard, if
+there is one set on the window given by \fItkwin\fR. Once a grab is
+released, pointer and keyboard events will start being delivered to
+other windows again.
+.SH KEYWORDS
+grab, window
diff --git a/tk8.6/doc/HWNDToWindow.3 b/tk8.6/doc/HWNDToWindow.3
new file mode 100644
index 0000000..9795099
--- /dev/null
+++ b/tk8.6/doc/HWNDToWindow.3
@@ -0,0 +1,26 @@
+'\"
+'\" Copyright (c) 1998-2000 by Scriptics Corporation.
+'\" All rights reserved.
+'\"
+.TH Tk_HWNDToWindow 3 "" Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_HWNDToWindow \- Find Tk's window information for a Windows window
+.SH SYNOPSIS
+.nf
+\fB#include <tkPlatDecls.h>\fR
+.sp
+Tk_Window
+\fBTk_HWNDToWindow\fR(\fIhwnd\fR)
+.SH ARGUMENTS
+.AP HWND hwnd in
+Windows handle for the window.
+.BE
+.SH DESCRIPTION
+.PP
+Given a Windows HWND window identifier, this procedure returns the
+corresponding Tk_Window handle. If there is no Tk_Window corresponding
+to \fIhwnd\fR then NULL is returned.
+.SH KEYWORDS
+Windows window id
diff --git a/tk8.6/doc/HandleEvent.3 b/tk8.6/doc/HandleEvent.3
new file mode 100644
index 0000000..38b5660
--- /dev/null
+++ b/tk8.6/doc/HandleEvent.3
@@ -0,0 +1,46 @@
+'\"
+'\" Copyright (c) 1990-1992 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_HandleEvent 3 "" Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_HandleEvent \- invoke event handlers for window system events
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+\fBTk_HandleEvent\fR(\fIeventPtr\fR)
+.SH ARGUMENTS
+.AS XEvent *eventPtr
+.AP XEvent *eventPtr in
+Pointer to X event to dispatch to relevant handler(s). It is important
+that all unused fields of the structure be set to zero.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_HandleEvent\fR is a lower-level procedure that deals with window
+events. It is called by \fBTcl_ServiceEvent\fR (and indirectly by
+\fBTcl_DoOneEvent\fR), and in a few other cases within Tk.
+It makes callbacks to any window event
+handlers (created by calls to \fBTk_CreateEventHandler\fR)
+that match \fIeventPtr\fR and then returns. In some cases
+it may be useful for an application to bypass the Tk event
+queue and call \fBTk_HandleEvent\fR directly instead of
+calling \fBTcl_QueueEvent\fR followed by
+\fBTcl_ServiceEvent\fR.
+.PP
+This procedure may be invoked recursively. For example,
+it is possible to invoke \fBTk_HandleEvent\fR recursively
+from a handler called by \fBTk_HandleEvent\fR. This sort
+of operation is useful in some modal situations, such
+as when a
+notifier has been popped up and an application wishes to
+wait for the user to click a button in the notifier before
+doing anything else.
+.SH KEYWORDS
+callback, event, handler, window
diff --git a/tk8.6/doc/IdToWindow.3 b/tk8.6/doc/IdToWindow.3
new file mode 100644
index 0000000..f6e397d
--- /dev/null
+++ b/tk8.6/doc/IdToWindow.3
@@ -0,0 +1,32 @@
+'\"
+'\" 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.
+'\"
+.TH Tk_IdToWindow 3 4.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_IdToWindow \- Find Tk's window information for an X window
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+Tk_Window
+\fBTk_IdToWindow\fR(\fIdisplay, window\fR)
+.SH ARGUMENTS
+.AS Tk_Window display
+.AP Display *display in
+X display containing the window.
+.AP Window window in
+X id for window.
+.BE
+.SH DESCRIPTION
+.PP
+Given an X window identifier and the X display it corresponds to,
+this procedure returns the corresponding Tk_Window handle.
+If there is no Tk_Window corresponding to \fIwindow\fR then
+NULL is returned.
+.SH KEYWORDS
+X window id
diff --git a/tk8.6/doc/ImgChanged.3 b/tk8.6/doc/ImgChanged.3
new file mode 100644
index 0000000..f4d2c04
--- /dev/null
+++ b/tk8.6/doc/ImgChanged.3
@@ -0,0 +1,64 @@
+'\"
+'\" Copyright (c) 1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_ImageChanged 3 4.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_ImageChanged \- notify widgets that image needs to be redrawn
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+\fBTk_ImageChanged\fR(\fIimageMaster, x, y, width, height, imageWidth, imageHeight\fR)
+.SH ARGUMENTS
+.AS Tk_ImageMaster imageHeight
+.AP Tk_ImageMaster imageMaster in
+Token for image, which was passed to image's \fIcreateProc\fR when
+the image was created.
+.AP int x in
+X-coordinate of upper-left corner of region that needs redisplay (measured
+from upper-left corner of image).
+.AP int y in
+Y-coordinate of upper-left corner of region that needs redisplay (measured
+from upper-left corner of image).
+.AP "int" width in
+Width of region that needs to be redrawn, in pixels.
+.AP "int" height in
+Height of region that needs to be redrawn, in pixels.
+.AP "int" imageWidth in
+Current width of image, in pixels.
+.AP "int" imageHeight in
+Current height of image, in pixels.
+.BE
+.SH DESCRIPTION
+.PP
+An image manager calls \fBTk_ImageChanged\fR for an image
+whenever anything happens that requires the image to be redrawn.
+As a result of calling \fBTk_ImageChanged\fR, any widgets using
+the image are notified so that they can redisplay themselves
+appropriately.
+The \fIimageMaster\fR argument identifies the image, and
+\fIx\fR, \fIy\fR, \fIwidth\fR, and \fIheight\fR
+specify a rectangular region within the image that needs to
+be redrawn.
+\fIimageWidth\fR and \fIimageHeight\fR specify the image's (new) size.
+.PP
+An image manager should call \fBTk_ImageChanged\fR during
+its \fIcreateProc\fR to specify the image's initial size and to
+force redisplay if there are existing instances for the image.
+If any of the pixel values in the image should change later on,
+\fBTk_ImageChanged\fR should be called again with \fIx\fR, \fIy\fR,
+\fIwidth\fR, and \fIheight\fR values that cover all the pixels
+that changed.
+If the size of the image should change, then \fBTk_ImageChanged\fR
+must be called to indicate the new size, even if no pixels
+need to be redisplayed.
+.SH "SEE ALSO"
+Tk_CreateImageType
+.SH KEYWORDS
+images, redisplay, image size changes
diff --git a/tk8.6/doc/Inactive.3 b/tk8.6/doc/Inactive.3
new file mode 100644
index 0000000..0d2a1b7
--- /dev/null
+++ b/tk8.6/doc/Inactive.3
@@ -0,0 +1,34 @@
+'\"
+'\" Copyright (c) 1998-2000 by Scriptics Corporation.
+'\" All rights reserved.
+'\"
+.TH Tk_GetUserInactiveTime 3 8.5 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_GetUserInactiveTime, Tk_ResetUserInactiveTime \- discover user inactivity time
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+long
+\fBTk_GetUserInactiveTime(\fIdisplay\fB)\fR
+.sp
+\fBTk_ResetUserInactiveTime(\fIdisplay\fB)\fR
+.SH ARGUMENTS
+.AS Display *display
+.AP Display *display in
+The display on which the user inactivity timer is to be queried or
+reset.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_GetUserInactiveTime\fR returns the number of milliseconds that
+have passed since the last user interaction (usually via keyboard or
+mouse) with the respective display. On systems and displays that do not
+support querying the user inactivity time, \fB\-1\fR is returned.
+\fBTk_ResetUserInactiveTime\fR resets the user inactivity timer of the
+given display to zero. On windowing systems that do not support
+multiple displays \fIdisplay\fR can be passed as \fBNULL\fR.
+.SH KEYWORDS
+idle, inactive
diff --git a/tk8.6/doc/InternAtom.3 b/tk8.6/doc/InternAtom.3
new file mode 100644
index 0000000..a16eee1
--- /dev/null
+++ b/tk8.6/doc/InternAtom.3
@@ -0,0 +1,55 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_InternAtom 3 "" Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_InternAtom, Tk_GetAtomName \- manage cache of X atoms
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+Atom
+\fBTk_InternAtom(\fItkwin, name\fR)
+.sp
+const char *
+\fBTk_GetAtomName(\fItkwin, atom\fR)
+.SH ARGUMENTS
+.AS Tk_Window parent
+.AP Tk_Window tkwin in
+Token for window. Used to map atom or name relative to a particular display.
+.AP "const char" *name in
+String name for which atom is desired.
+.AP Atom atom in
+Atom for which corresponding string name is desired.
+.BE
+.SH DESCRIPTION
+.PP
+These procedures are similar to the Xlib procedures
+\fBXInternAtom\fR and \fBXGetAtomName\fR. \fBTk_InternAtom\fR
+returns the atom identifier associated with string given by
+\fIname\fR; the atom identifier is only valid for the display
+associated with \fItkwin\fR.
+\fBTk_GetAtomName\fR returns the string associated
+with \fIatom\fR on \fItkwin\fR's display. The string returned
+by \fBTk_GetAtomName\fR is in Tk's storage: the caller need
+not free this space when finished with the string, and the caller
+should not modify the contents of the returned string.
+If there is no atom \fIatom\fR on \fItkwin\fR's display,
+then \fBTk_GetAtomName\fR returns the string
+.QW "?bad atom?" .
+.PP
+Tk caches
+the information returned by \fBTk_InternAtom\fR and \fBTk_GetAtomName\fR
+so that future calls
+for the same information can be serviced from the cache without
+contacting the server. Thus \fBTk_InternAtom\fR and \fBTk_GetAtomName\fR
+are generally much faster than their Xlib counterparts, and they
+should be used in place of the Xlib procedures.
+.SH KEYWORDS
+atom, cache, display
diff --git a/tk8.6/doc/MainLoop.3 b/tk8.6/doc/MainLoop.3
new file mode 100644
index 0000000..ed4d0ea
--- /dev/null
+++ b/tk8.6/doc/MainLoop.3
@@ -0,0 +1,28 @@
+'\"
+'\" Copyright (c) 1990-1992 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_MainLoop 3 "" Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_MainLoop \- loop for events until all windows are deleted
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+\fBTk_MainLoop\fR()
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_MainLoop\fR is a procedure that loops repeatedly calling
+\fBTcl_DoOneEvent\fR. It returns only when there are no applications
+left in this process (i.e. no main windows exist anymore). Most
+windowing applications will call \fBTk_MainLoop\fR after
+initialization; the main execution of the application will consist
+entirely of callbacks invoked via \fBTcl_DoOneEvent\fR.
+.SH KEYWORDS
+application, event, main loop
diff --git a/tk8.6/doc/MainWin.3 b/tk8.6/doc/MainWin.3
new file mode 100644
index 0000000..c3af3e7
--- /dev/null
+++ b/tk8.6/doc/MainWin.3
@@ -0,0 +1,40 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_MainWindow 3 7.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_MainWindow, Tk_GetNumMainWindows \- functions for querying main window information
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+Tk_Window
+\fBTk_MainWindow\fR(\fIinterp\fR)
+.sp
+int
+\fBTk_GetNumMainWindows\fR()
+.SH ARGUMENTS
+.AS Tcl_Interp *pathName
+.AP Tcl_Interp *interp in/out
+Interpreter associated with the application.
+.BE
+.SH DESCRIPTION
+.PP
+A main window is a special kind of toplevel window used as the
+outermost window in an application.
+.PP
+If \fIinterp\fR is associated with a Tk application then \fBTk_MainWindow\fR
+returns the application's main window. If there is no Tk application
+associated with \fIinterp\fR then \fBTk_MainWindow\fR returns NULL and
+leaves an error message in interpreter \fIinterp\fR's result.
+.PP
+\fBTk_GetNumMainWindows\fR returns a count of the number of main
+windows currently open in the current thread.
+.SH KEYWORDS
+application, main window
diff --git a/tk8.6/doc/MaintGeom.3 b/tk8.6/doc/MaintGeom.3
new file mode 100644
index 0000000..d1c2d1c
--- /dev/null
+++ b/tk8.6/doc/MaintGeom.3
@@ -0,0 +1,99 @@
+'\"
+'\" Copyright (c) 1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_MaintainGeometry 3 4.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_MaintainGeometry, Tk_UnmaintainGeometry \- maintain geometry of one window relative to another
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+\fBTk_MaintainGeometry\fR(\fIslave, master, x, y, width, height\fR)
+.sp
+\fBTk_UnmaintainGeometry\fR(\fIslave, master\fR)
+.SH ARGUMENTS
+.AS Tk_Window master
+.AP Tk_Window slave in
+Window whose geometry is to be controlled.
+.AP Tk_Window master in
+Window relative to which \fIslave\fR's geometry will be controlled.
+.AP int x in
+Desired x-coordinate of \fIslave\fR in \fImaster\fR, measured in pixels
+from the inside of \fImaster\fR's left border to the outside of
+\fIslave\fR's left border.
+.AP int y in
+Desired y-coordinate of \fIslave\fR in \fImaster\fR, measured in pixels
+from the inside of \fImaster\fR's top border to the outside of
+\fIslave\fR's top border.
+.AP int width in
+Desired width for \fIslave\fR, in pixels.
+.AP int height in
+Desired height for \fIslave\fR, in pixels.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_MaintainGeometry\fR and \fBTk_UnmaintainGeometry\fR make it
+easier for geometry managers to deal with slaves whose masters are not
+their parents.
+Three problems arise if the master for a slave is not its parent:
+.IP [1]
+The x- and y-position of the slave must be translated from the
+coordinate system of the master to that of the parent before
+positioning the slave.
+.IP [2]
+If the master window, or any of its ancestors up to the slave's
+parent, is moved, then the slave must be repositioned within its
+parent in order to maintain the correct position relative to the
+master.
+.IP [3]
+If the master or one of its ancestors is mapped or unmapped, then
+the slave must be mapped or unmapped to correspond.
+.LP
+None of these problems is an issue if the parent and master are
+the same. For example, if the master or one of its ancestors
+is unmapped, the slave is automatically removed by the screen
+by X.
+.PP
+\fBTk_MaintainGeometry\fR deals with these problems for slaves
+whose masters are not their parents, as well as handling the simpler
+case of slaves whose masters are their parents.
+\fBTk_MaintainGeometry\fR is typically called by a window manager
+once it has decided where a slave should be positioned relative
+to its master.
+\fBTk_MaintainGeometry\fR translates the coordinates to the
+coordinate system of \fIslave\fR's parent and then moves and
+resizes the slave appropriately.
+Furthermore, it remembers the desired position and creates event
+handlers to monitor the master and all of its ancestors up
+to (but not including) the slave's parent.
+If any of these windows is moved, mapped, or unmapped,
+the slave will be adjusted so that it is mapped only when the
+master is mapped and its geometry relative to the master
+remains as specified by \fIx\fR, \fIy\fR, \fIwidth\fR, and
+\fIheight\fR.
+.PP
+When a window manager relinquishes control over a window, or
+if it decides that it does not want the window to appear on the
+screen under any conditions, it calls \fBTk_UnmaintainGeometry\fR.
+\fBTk_UnmaintainGeometry\fR unmaps the window and cancels any
+previous calls to \fBTk_MaintainGeometry\fR for the
+\fImaster\fR\-\fIslave\fR pair, so that the slave's
+geometry and mapped state are no longer maintained
+automatically.
+\fBTk_UnmaintainGeometry\fR need not be called by a geometry
+manager if the slave, the master, or any of the master's ancestors
+is destroyed: Tk will call it automatically.
+.PP
+If \fBTk_MaintainGeometry\fR is called repeatedly for the same
+\fImaster\fR\-\fIslave\fR pair, the information from the most
+recent call supersedes any older information.
+If \fBTk_UnmaintainGeometry\fR is called for a \fImaster\fR\-\fIslave\fR
+pair that is is not currently managed, the call has no effect.
+.SH KEYWORDS
+geometry manager, map, master, parent, position, slave, unmap
diff --git a/tk8.6/doc/ManageGeom.3 b/tk8.6/doc/ManageGeom.3
new file mode 100644
index 0000000..520546f
--- /dev/null
+++ b/tk8.6/doc/ManageGeom.3
@@ -0,0 +1,90 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_ManageGeometry 3 4.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_ManageGeometry \- arrange to handle geometry requests for a window
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+\fBTk_ManageGeometry\fR(\fItkwin, mgrPtr, clientData\fR)
+.SH ARGUMENTS
+.AS Tk_GeometryProc clientData
+.AP Tk_Window tkwin in
+Token for window to be managed.
+.AP "const Tk_GeomMgr" *mgrPtr in
+Pointer to data structure containing information about the
+geometry manager, or NULL to indicate that \fItkwin\fR's geometry
+should not be managed anymore.
+The data structure pointed to by \fImgrPtr\fR must be static:
+Tk keeps a reference to it as long as the window is managed.
+.AP ClientData clientData in
+Arbitrary one-word value to pass to geometry manager callbacks.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_ManageGeometry\fR arranges for a particular geometry manager,
+described by the \fImgrPtr\fR argument, to control the geometry
+of a particular slave window, given by \fItkwin\fR.
+If \fItkwin\fR was previously managed by some other geometry manager,
+the previous manager loses control in favor of the new one.
+If \fImgrPtr\fR is NULL, geometry management is cancelled for
+\fItkwin\fR.
+.PP
+The structure pointed to by \fImgrPtr\fR contains information about
+the geometry manager:
+.CS
+typedef struct {
+ const char *\fIname\fR;
+ Tk_GeomRequestProc *\fIrequestProc\fR;
+ Tk_GeomLostSlaveProc *\fIlostSlaveProc\fR;
+} \fBTk_GeomMgr\fR;
+.CE
+The \fIname\fR field is the textual name for the geometry manager,
+such as \fBpack\fR or \fBplace\fR; this value will be returned
+by the command \fBwinfo manager\fR.
+.PP
+\fIrequestProc\fR is a procedure in the geometry manager that
+will be invoked whenever \fBTk_GeometryRequest\fR is called by the
+slave to change its desired geometry.
+\fIrequestProc\fR should have arguments and results that match the
+type \fBTk_GeomRequestProc\fR:
+.CS
+typedef void \fBTk_GeomRequestProc\fR(
+ ClientData \fIclientData\fR,
+ Tk_Window \fItkwin\fR);
+.CE
+The parameters to \fIrequestProc\fR will be identical to the
+corresponding parameters passed to \fBTk_ManageGeometry\fR.
+\fIclientData\fR usually points to a data
+structure containing application-specific information about
+how to manage \fItkwin\fR's geometry.
+.PP
+The \fIlostSlaveProc\fR field of \fImgrPtr\fR points to another
+procedure in the geometry manager.
+Tk will invoke \fIlostSlaveProc\fR if some other manager
+calls \fBTk_ManageGeometry\fR to claim
+\fItkwin\fR away from the current geometry manager.
+\fIlostSlaveProc\fR is not invoked if \fBTk_ManageGeometry\fR is
+called with a NULL value for \fImgrPtr\fR (presumably the current
+geometry manager has made this call, so it already knows that the
+window is no longer managed), nor is it called if \fImgrPtr\fR
+is the same as the window's current geometry manager.
+\fIlostSlaveProc\fR should have
+arguments and results that match the following prototype:
+.CS
+typedef void \fBTk_GeomLostSlaveProc\fR(
+ ClientData \fIclientData\fR,
+ Tk_Window \fItkwin\fR);
+.CE
+The parameters to \fIlostSlaveProc\fR will be identical to the
+corresponding parameters passed to \fBTk_ManageGeometry\fR.
+.SH KEYWORDS
+callback, geometry, managed, request, unmanaged
diff --git a/tk8.6/doc/MapWindow.3 b/tk8.6/doc/MapWindow.3
new file mode 100644
index 0000000..a3c6296
--- /dev/null
+++ b/tk8.6/doc/MapWindow.3
@@ -0,0 +1,49 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_MapWindow 3 "" Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_MapWindow, Tk_UnmapWindow \- map or unmap a window
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+Tk_Window
+\fBTk_MapWindow\fR(\fItkwin\fR)
+.sp
+\fBTk_UnmapWindow\fR(\fItkwin\fR)
+.SH ARGUMENTS
+.AS Tk_Window parent
+.AP Tk_Window tkwin in
+Token for window.
+.BE
+.SH DESCRIPTION
+.PP
+These procedures may be used to map and unmap windows
+managed by Tk. \fBTk_MapWindow\fR maps the window given
+by \fItkwin\fR, and also creates an X window corresponding
+to \fItkwin\fR if it does not already exist. See the
+\fBTk_CreateWindow\fR manual entry for information on
+deferred window creation.
+\fBTk_UnmapWindow\fR unmaps \fItkwin\fR's window
+from the screen.
+.PP
+If \fItkwin\fR is a child window (i.e. \fBTk_CreateWindow\fR was
+used to create a child window), then event handlers interested in map
+and unmap events are invoked immediately. If \fItkwin\fR is not an
+internal window, then the event handlers will be invoked later, after
+X has seen the request and returned an event for it.
+.PP
+These procedures should be used in place of the X procedures
+\fBXMapWindow\fR and \fBXUnmapWindow\fR, since they update
+Tk's local data structure for \fItkwin\fR. Applications
+using Tk should not invoke \fBXMapWindow\fR and \fBXUnmapWindow\fR
+directly.
+.SH KEYWORDS
+map, unmap, window
diff --git a/tk8.6/doc/MeasureChar.3 b/tk8.6/doc/MeasureChar.3
new file mode 100644
index 0000000..3959978
--- /dev/null
+++ b/tk8.6/doc/MeasureChar.3
@@ -0,0 +1,127 @@
+'\"
+'\" 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.
+'\"
+.TH Tk_MeasureChars 3 8.1 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_MeasureChars, Tk_TextWidth, Tk_DrawChars, Tk_UnderlineChars \- routines to measure and display simple single-line strings.
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+int
+\fBTk_MeasureChars(\fItkfont, string, numBytes, maxPixels, flags, lengthPtr\fB)\fR
+.sp
+int
+\fBTk_TextWidth(\fItkfont, string, numBytes\fB)\fR
+.sp
+\fBTk_DrawChars(\fIdisplay, drawable, gc, tkfont, string, numBytes, x, y\fB)\fR
+.sp
+\fBTk_UnderlineChars(\fIdisplay, drawable, gc, tkfont, string, x, y, firstByte, lastByte\fB)\fR
+.sp
+.SH ARGUMENTS
+.AS "const char" firstChar
+.AP Tk_Font tkfont in
+Token for font in which text is to be drawn or measured. Must have been
+returned by a previous call to \fBTk_GetFont\fR.
+.AP "const char" *string in
+Text to be measured or displayed. Need not be null terminated. Any
+non-printing meta-characters in the string (such as tabs, newlines, and
+other control characters) will be measured or displayed in a
+platform-dependent manner.
+.AP int numBytes in
+The maximum number of bytes to consider when measuring or drawing
+\fIstring\fR. Must be greater than or equal to 0.
+.AP int maxPixels in
+If \fImaxPixels\fR is >= 0, it specifies the longest permissible
+line length in pixels. Characters from \fIstring\fR are processed only
+until this many pixels have been covered. If \fImaxPixels\fR is < 0, then
+the line length is unbounded and the \fIflags\fR argument is ignored.
+.AP int flags in
+Various flag bits OR-ed together: \fBTK_PARTIAL_OK\fR means include a character
+as long as any part of it fits in the length given by \fImaxPixels\fR;
+otherwise, a character must fit completely to be considered.
+\fBTK_WHOLE_WORDS\fR means stop on a word boundary, if possible. If
+\fBTK_AT_LEAST_ONE\fR is set, it means return at least one character even if no
+characters could fit in the length given by \fImaxPixels\fR. If
+\fBTK_AT_LEAST_ONE\fR is set and \fBTK_WHOLE_WORDS\fR is also set, it means that if
+not even one word fits on the line, return the first few letters of the
+word that did fit; if not even one letter of the word fit, then the first
+letter will still be returned.
+.AP int *lengthPtr out
+Filled with the number of pixels occupied by the number of characters
+returned as the result of \fBTk_MeasureChars\fR.
+.AP Display *display in
+Display on which to draw.
+.AP Drawable drawable in
+Window or pixmap in which to draw.
+.AP GC gc in
+Graphics context for drawing characters. The font selected into this GC
+must be the same as the \fItkfont\fR.
+.AP int "x, y" in
+Coordinates at which to place the left edge of the baseline when displaying
+\fIstring\fR.
+.AP int firstByte in
+The index of the first byte of the first character to underline in the
+\fIstring\fR. Underlining begins at the left edge of this character.
+.AP int lastByte in
+The index of the first byte of the last character up to which the
+underline will be drawn. The character specified by \fIlastByte\fR
+will not itself be underlined.
+.BE
+.SH DESCRIPTION
+.PP
+These routines are for measuring and displaying simple single-font,
+single-line strings. To measure and display single-font, multi-line,
+justified text, refer to the documentation for \fBTk_ComputeTextLayout\fR.
+There is no programming interface in the core of Tk that supports
+multi-font, multi-line text; support for that behavior must be built on
+top of simpler layers.
+Note that the interfaces described here are
+byte-oriented not character-oriented, so index values coming from Tcl
+scripts need to be converted to byte offsets using the
+\fBTcl_UtfAtIndex\fR and related routines.
+.PP
+A glyph is the displayable picture of a letter, number, or some other
+symbol. Not all character codes in a given font have a glyph.
+Characters such as tabs, newlines/returns, and control characters that
+have no glyph are measured and displayed by these procedures in a
+platform-dependent manner; under X, they are replaced with backslashed
+escape sequences, while under Windows and Macintosh hollow or solid boxes
+may be substituted. Refer to the documentation for
+\fBTk_ComputeTextLayout\fR for a programming interface that supports the
+platform-independent expansion of tab characters into columns and
+newlines/returns into multi-line text.
+.PP
+\fBTk_MeasureChars\fR is used both to compute the length of a given
+string and to compute how many characters from a string fit in a given
+amount of space. The return value is the number of bytes from
+\fIstring\fR that fit in the space specified by \fImaxPixels\fR subject to
+the conditions described by \fIflags\fR. If all characters fit, the return
+value will be \fInumBytes\fR. \fI*lengthPtr\fR is filled with the computed
+width, in pixels, of the portion of the string that was measured. For
+example, if the return value is 5, then \fI*lengthPtr\fR is filled with the
+distance between the left edge of \fIstring\fR[0] and the right edge of
+\fIstring\fR[4].
+.PP
+\fBTk_TextWidth\fR is a wrapper function that provides a simpler interface
+to the \fBTk_MeasureChars\fR function. The return value is how much
+space in pixels the given \fIstring\fR needs.
+.PP
+\fBTk_DrawChars\fR draws the \fIstring\fR at the given location in the
+given \fIdrawable\fR.
+.PP
+\fBTk_UnderlineChars\fR underlines the given range of characters in the
+given \fIstring\fR. It does not draw the characters (which are assumed to
+have been displayed previously by \fBTk_DrawChars\fR); it just draws the
+underline. This procedure is used to underline a few characters without
+having to construct an underlined font. To produce natively underlined
+text, the appropriate underlined font should be constructed and used.
+.SH "SEE ALSO"
+font(n), FontId(3)
+.SH KEYWORDS
+font, measurement
diff --git a/tk8.6/doc/MoveToplev.3 b/tk8.6/doc/MoveToplev.3
new file mode 100644
index 0000000..00bbaa5
--- /dev/null
+++ b/tk8.6/doc/MoveToplev.3
@@ -0,0 +1,51 @@
+'\"
+'\" Copyright (c) 1990-1993 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_MoveToplevelWindow 3 "" Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_MoveToplevelWindow \- Adjust the position of a top-level window
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+\fBTk_MoveToplevelWindow(\fItkwin, x, y\fB)\fR
+.SH ARGUMENTS
+.AS Tk_Window tkwin
+.AP Tk_Window tkwin in
+Token for top-level window to move.
+.AP int x in
+New x-coordinate for the top-left pixel of \fItkwin\fR's border, or the
+top-left pixel of the decorative border supplied for \fItkwin\fR by the
+window manager, if there is one.
+.AP int y in
+New y-coordinate for the top-left pixel of \fItkwin\fR's border, or the
+top-left pixel of the decorative border supplied for \fItkwin\fR by the
+window manager, if there is one.
+.BE
+.SH DESCRIPTION
+.PP
+In general, a window should never set its own position; this should be
+done only by the geometry manger that is responsible for the window.
+For top-level windows the window manager is effectively the geometry
+manager; Tk provides interface code between the application and the
+window manager to convey the application's desires to the geometry
+manager. The desired size for a top-level window is conveyed using
+the usual \fBTk_GeometryRequest\fR mechanism. The procedure
+\fBTk_MoveToplevelWindow\fR may be used by an application to request
+a particular position for a top-level window; this procedure is
+similar in function to the \fBwm geometry\fR Tcl command except that
+negative offsets cannot be specified. It is invoked by widgets such as
+menus that want to appear at a particular place on the screen.
+.PP
+When \fBTk_MoveToplevelWindow\fR is called it does not immediately
+pass on the new desired location to the window manager; it defers
+this action until all other outstanding work has been completed,
+using the \fBTcl_DoWhenIdle\fR mechanism.
+.SH KEYWORDS
+position, top-level window, window manager
diff --git a/tk8.6/doc/Name.3 b/tk8.6/doc/Name.3
new file mode 100644
index 0000000..4b9c5bc
--- /dev/null
+++ b/tk8.6/doc/Name.3
@@ -0,0 +1,86 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_Name 3 "" Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_Name, Tk_PathName, Tk_NameToWindow \- convert between names and window tokens
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+Tk_Uid
+\fBTk_Name\fR(\fItkwin\fR)
+.sp
+char *
+\fBTk_PathName\fR(\fItkwin\fR)
+.sp
+Tk_Window
+\fBTk_NameToWindow\fR(\fIinterp, pathName, tkwin\fR)
+.SH ARGUMENTS
+.AS Tcl_Interp *pathName
+.AP Tk_Window tkwin in
+Token for window.
+.AP Tcl_Interp *interp out
+Interpreter to use for error reporting.
+.AP "const char" *pathName in
+Character string containing path name of window.
+.BE
+.SH DESCRIPTION
+.PP
+Each window managed by Tk has two names, a short name that identifies
+a window among children of the same parent, and a path name that
+identifies the window uniquely among all the windows belonging to the
+same main window. The path name is used more often in Tk than the
+short name; many commands, like \fBbind\fR, expect path names as
+arguments.
+.PP
+The \fBTk_Name\fR macro returns a window's
+short name, which is the same as the \fIname\fR argument
+passed to \fBTk_CreateWindow\fR when
+the window was created. The value is returned
+as a Tk_Uid, which may be used just like a string pointer but also has
+the properties of a unique identifier (see the manual entry for
+\fBTk_GetUid\fR for details).
+.PP
+The \fBTk_PathName\fR macro returns a hierarchical name for \fItkwin\fR.
+Path names have a structure similar to file names in Unix but with
+dots between elements instead of slashes: the main window for
+an application has the path name
+.QW . ;
+its children have names like
+.QW .a
+and
+.QW .b ;
+their children have names like
+.QW .a.aa
+and
+.QW .b.bb ;
+and so on. A window is considered to be a child of
+another window for naming purposes if the second window was named
+as the first window's \fIparent\fR when the first window was created.
+This is not always the same as the X window hierarchy. For
+example, a pop-up
+is created as a child of the root window, but its logical parent will
+usually be a window within the application.
+.PP
+The procedure \fBTk_NameToWindow\fR returns the token for a window
+given its path name (the \fIpathName\fR argument) and another window
+belonging to the same main window (\fItkwin\fR). It normally
+returns a token for the named window, but if no such window exists
+\fBTk_NameToWindow\fR leaves an error message in interpreter
+\fIinterp\fR's result
+and returns NULL. The \fItkwin\fR argument to \fBTk_NameToWindow\fR
+is needed because path names are only unique within a single
+application hierarchy. If, for example, a single process has opened
+two main windows, each will have a separate naming hierarchy and the
+same path name might appear in each of the hierarchies. Normally
+\fItkwin\fR is the main window of the desired hierarchy, but this
+need not be the case: any window in the desired hierarchy may be used.
+.SH KEYWORDS
+name, path name, token, window
diff --git a/tk8.6/doc/NameOfImg.3 b/tk8.6/doc/NameOfImg.3
new file mode 100644
index 0000000..78332db
--- /dev/null
+++ b/tk8.6/doc/NameOfImg.3
@@ -0,0 +1,30 @@
+'\"
+'\" 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.
+'\"
+.TH Tk_NameOfImage 3 4.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_NameOfImage \- Return name of image.
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+const char *
+\fBTk_NameOfImage\fR(\fItypePtr\fR)
+.SH ARGUMENTS
+.AS Tk_ImageMaster *masterPtr
+.AP Tk_ImageMaster *masterPtr in
+Token for image, which was passed to image manager's \fIcreateProc\fR when
+the image was created.
+.BE
+.SH DESCRIPTION
+.PP
+This procedure is invoked by image managers to find out the name
+of an image. Given the token for the image, it returns the
+string name for the image.
+.SH KEYWORDS
+image manager, image name
diff --git a/tk8.6/doc/OwnSelect.3 b/tk8.6/doc/OwnSelect.3
new file mode 100644
index 0000000..ed9bcab
--- /dev/null
+++ b/tk8.6/doc/OwnSelect.3
@@ -0,0 +1,49 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_OwnSelection 3 4.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_OwnSelection \- make a window the owner of the primary selection
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+\fBTk_OwnSelection\fR(\fItkwin, selection, proc, clientData\fR)
+.SH ARGUMENTS
+.AS Tk_LostSelProc clientData
+.AP Tk_Window tkwin in
+Window that is to become new selection owner.
+.AP Atom selection in
+The name of the selection to be owned, such as XA_PRIMARY.
+.AP Tk_LostSelProc *proc in
+Procedure to invoke when \fItkwin\fR loses selection ownership later.
+.AP ClientData clientData in
+Arbitrary one-word value to pass to \fIproc\fR.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_OwnSelection\fR arranges for \fItkwin\fR to become the
+new owner of the selection specified by the atom
+\fIselection\fR. After this call completes, future requests
+for the selection will be directed to handlers created for
+\fItkwin\fR using \fBTk_CreateSelHandler\fR. When \fItkwin\fR
+eventually loses the selection ownership, \fIproc\fR will be
+invoked so that the window can clean itself up (e.g. by
+unhighlighting the selection). \fIProc\fR should have arguments and
+result that match the type \fBTk_LostSelProc\fR:
+.CS
+typedef void \fBTk_LostSelProc\fR(
+ ClientData \fIclientData\fR);
+.CE
+The \fIclientData\fR parameter to \fIproc\fR is a copy of the
+\fIclientData\fR argument given to \fBTk_OwnSelection\fR, and is
+usually a pointer to a data structure containing application-specific
+information about \fItkwin\fR.
+.SH KEYWORDS
+own, selection owner
diff --git a/tk8.6/doc/ParseArgv.3 b/tk8.6/doc/ParseArgv.3
new file mode 100644
index 0000000..7749d92
--- /dev/null
+++ b/tk8.6/doc/ParseArgv.3
@@ -0,0 +1,360 @@
+'\"
+'\" Copyright (c) 1990-1992 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_ParseArgv 3 "" Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_ParseArgv \- process command-line options
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+int
+\fBTk_ParseArgv\fR(\fIinterp, tkwin, argcPtr, argv, argTable, flags\fR)
+.SH ARGUMENTS
+.AS Tk_ArgvInfo *argTable
+.AP Tcl_Interp *interp in
+Interpreter to use for returning error messages.
+.AP Tk_Window tkwin in
+Window to use when arguments specify Tk options. If NULL, then
+no Tk options will be processed.
+.AP int argcPtr in/out
+Pointer to number of arguments in argv; gets modified to hold
+number of unprocessed arguments that remain after the call.
+.AP "const char" **argv in/out
+Command line arguments passed to main program. Modified to
+hold unprocessed arguments that remain after the call.
+.AP Tk_ArgvInfo *argTable in
+Array of argument descriptors, terminated by element with
+type \fBTK_ARGV_END\fR.
+.AP int flags in
+If non-zero, then it specifies one or more flags that control the
+parsing of arguments. Different flags may be OR'ed together.
+The flags currently defined are \fBTK_ARGV_DONT_SKIP_FIRST_ARG\fR,
+\fBTK_ARGV_NO_ABBREV\fR, \fBTK_ARGV_NO_LEFTOVERS\fR, and
+\fBTK_ARGV_NO_DEFAULTS\fR.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_ParseArgv\fR processes an array of command-line arguments according
+to a table describing the kinds of arguments that are expected.
+Each of the arguments in \fIargv\fR is processed in turn: if it matches
+one of the entries in \fIargTable\fR, the argument is processed
+according to that entry and discarded. The arguments that do not
+match anything in \fIargTable\fR are copied down to the beginning
+of \fIargv\fR (retaining their original order) and returned to
+the caller. At the end of the call
+\fBTk_ParseArgv\fR sets \fI*argcPtr\fR to hold the number of
+arguments that are left in \fIargv\fR, and \fIargv[*argcPtr]\fR
+will hold the value NULL. Normally, \fBTk_ParseArgv\fR
+assumes that \fIargv[0]\fR is a command name, so it is treated like
+an argument that does not match \fIargTable\fR and returned to the
+caller; however, if the \fBTK_ARGV_DONT_SKIP_FIRST_ARG\fR bit is set in
+\fIflags\fR then \fIargv[0]\fR will be processed just like the other
+elements of \fIargv\fR.
+.PP
+\fBTk_ParseArgv\fR normally returns the value \fBTCL_OK\fR. If an error
+occurs while parsing the arguments, then \fBTCL_ERROR\fR is returned and
+\fBTk_ParseArgv\fR will leave an error message in the result of
+interpreter \fIinterp\fR in the standard Tcl fashion. In
+the event of an error return, \fI*argvPtr\fR will not have been
+modified, but \fIargv\fR could have been partially modified. The
+possible causes of errors are explained below.
+.PP
+The \fIargTable\fR array specifies the kinds of arguments that are
+expected; each of its entries has the following structure:
+.CS
+typedef struct {
+ const char *\fIkey\fR;
+ int \fItype\fR;
+ char *\fIsrc\fR;
+ char *\fIdst\fR;
+ const char *\fIhelp\fR;
+} \fBTk_ArgvInfo\fR;
+.CE
+The \fIkey\fR field is a string such as
+.QW \-display
+or
+.QW \-bg
+that is compared with the values in \fIargv\fR. \fIType\fR
+indicates how to process an argument that matches \fIkey\fR
+(more on this below). \fISrc\fR and \fIdst\fR are additional
+values used in processing the argument. Their exact usage
+depends on \fItype\fR, but typically \fIsrc\fR indicates
+a value and \fIdst\fR indicates where to store the
+value. The \fBchar *\fR declarations for \fIsrc\fR and \fIdst\fR
+are placeholders: the actual types may be different. Lastly,
+\fIhelp\fR is a string giving a brief description
+of this option; this string is printed when users ask for help
+about command-line options.
+.PP
+When processing an argument in \fIargv\fR, \fBTk_ParseArgv\fR
+compares the argument to each of the \fIkey\fR's in \fIargTable\fR.
+\fBTk_ParseArgv\fR selects the first specifier whose \fIkey\fR matches
+the argument exactly, if such a specifier exists. Otherwise
+\fBTk_ParseArgv\fR selects a specifier for which the argument
+is a unique abbreviation. If the argument is a unique abbreviation
+for more than one specifier, then an error is returned. If there
+is no matching entry in \fIargTable\fR, then the argument is
+skipped and returned to the caller.
+.PP
+Once a matching argument specifier is found, \fBTk_ParseArgv\fR
+processes the argument according to the \fItype\fR field of the
+specifier. The argument that matched \fIkey\fR is called
+.QW "the matching argument"
+in the descriptions below. As part of the processing,
+\fBTk_ParseArgv\fR may also use the next argument in \fIargv\fR
+after the matching argument, which is called
+.QW "the following argument" .
+The legal values for \fItype\fR, and the processing
+that they cause, are as follows:
+.TP
+\fBTK_ARGV_END\fR
+Marks the end of the table. The last entry in \fIargTable\fR
+must have this type; all of its other fields are ignored and it
+will never match any arguments.
+.TP
+\fBTK_ARGV_CONSTANT\fR
+\fISrc\fR is treated as an integer and \fIdst\fR is treated
+as a pointer to an integer. \fISrc\fR is stored at \fI*dst\fR.
+The matching argument is discarded.
+.TP
+\fBTK_ARGV_INT\fR
+The following argument must contain an
+integer string in the format accepted by \fBstrtol\fR (e.g.
+.QW 0
+and
+.QW 0x
+prefixes may be used to specify octal or hexadecimal
+numbers, respectively). \fIDst\fR is treated as a pointer to an
+integer; the following argument is converted to an integer value
+and stored at \fI*dst\fR. \fISrc\fR is ignored. The matching
+and following arguments are discarded from \fIargv\fR.
+.TP
+\fBTK_ARGV_FLOAT\fR
+The following argument must contain a floating-point number in
+the format accepted by \fBstrtol\fR.
+\fIDst\fR is treated as the address of a double-precision
+floating point value; the following argument is converted to a
+double-precision value and stored at \fI*dst\fR. The matching
+and following arguments are discarded from \fIargv\fR.
+.TP
+\fBTK_ARGV_STRING\fR
+In this form, \fIdst\fR is treated as a pointer to a (char *);
+\fBTk_ParseArgv\fR stores at \fI*dst\fR a pointer to the following
+argument, and discards the matching and following arguments from
+\fIargv\fR. \fISrc\fR is ignored.
+.TP
+\fBTK_ARGV_UID\fR
+This form is similar to \fBTK_ARGV_STRING\fR, except that the argument
+is turned into a Tk_Uid by calling \fBTk_GetUid\fR.
+\fIDst\fR is treated as a pointer to a
+Tk_Uid; \fBTk_ParseArgv\fR stores at \fI*dst\fR the Tk_Uid
+corresponding to the following
+argument, and discards the matching and following arguments from
+\fIargv\fR. \fISrc\fR is ignored.
+.TP
+\fBTK_ARGV_CONST_OPTION\fR
+This form causes a Tk option to be set (as if the \fBoption\fR
+command had been invoked). The \fIsrc\fR field is treated as a
+pointer to a string giving the value of an option, and \fIdst\fR
+is treated as a pointer to the name of the option. The matching
+argument is discarded. If \fItkwin\fR is NULL, then argument
+specifiers of this type are ignored (as if they did not exist).
+.TP
+\fBTK_ARGV_OPTION_VALUE\fR
+This form is similar to \fBTK_ARGV_CONST_OPTION\fR, except that the
+value of the option is taken from the following argument instead
+of from \fIsrc\fR. \fIDst\fR is used as the name of the option.
+\fISrc\fR is ignored. The matching and following arguments
+are discarded. If \fItkwin\fR is NULL, then argument
+specifiers of this type are ignored (as if they did not exist).
+.TP
+\fBTK_ARGV_OPTION_NAME_VALUE\fR
+In this case the following argument is taken as the name of a Tk
+option and the argument after that is taken as the value for that
+option. Both \fIsrc\fR and \fIdst\fR are ignored. All three
+arguments are discarded from \fIargv\fR. If \fItkwin\fR is NULL,
+then argument
+specifiers of this type are ignored (as if they did not exist).
+.TP
+\fBTK_ARGV_HELP\fR
+When this kind of option is encountered, \fBTk_ParseArgv\fR uses the
+\fIhelp\fR fields of \fIargTable\fR to format a message describing
+all the valid arguments. The message is placed in interpreter
+\fIinterp\fR's result
+and \fBTk_ParseArgv\fR returns \fBTCL_ERROR\fR. When this happens, the
+caller normally prints the help message and aborts. If the \fIkey\fR
+field of a \fBTK_ARGV_HELP\fR specifier is NULL, then the specifier will
+never match any arguments; in this case the specifier simply provides
+extra documentation, which will be included when some other
+\fBTK_ARGV_HELP\fR entry causes help information to be returned.
+.TP
+\fBTK_ARGV_REST\fR
+This option is used by programs or commands that allow the last
+several of their options to be the name and/or options for some
+other program. If a \fBTK_ARGV_REST\fR argument is found, then
+\fBTk_ParseArgv\fR does not process any
+of the remaining arguments; it returns them all at
+the beginning of \fIargv\fR (along with any other unprocessed arguments).
+In addition, \fBTk_ParseArgv\fR treats \fIdst\fR as the address of an
+integer value, and stores at \fI*dst\fR the index of the first of the
+\fBTK_ARGV_REST\fR options in the returned \fIargv\fR. This allows the
+program to distinguish the \fBTK_ARGV_REST\fR options from other
+unprocessed options that preceded the \fBTK_ARGV_REST\fR.
+.TP
+\fBTK_ARGV_FUNC\fR
+For this kind of argument, \fIsrc\fR is treated as the address of
+a procedure, which is invoked to process the following argument.
+The procedure should have the following structure:
+.RS
+.CS
+int
+\fIfunc\fR(\fIdst\fR, \fIkey\fR, \fInextArg\fR)
+ char *\fIdst\fR;
+ char *\fIkey\fR;
+ char *\fInextArg\fR;
+{
+}
+.CE
+The \fIdst\fR and \fIkey\fR parameters will contain the
+corresponding fields from the \fIargTable\fR entry, and
+\fInextArg\fR will point to the following argument from \fIargv\fR
+(or NULL if there are not any more arguments left in \fIargv\fR).
+If \fIfunc\fR uses \fInextArg\fR (so that
+\fBTk_ParseArgv\fR should discard it), then it should return 1. Otherwise it
+should return 0 and \fBTkParseArgv\fR will process the following
+argument in the normal fashion. In either event the matching argument
+is discarded.
+.RE
+.TP
+\fBTK_ARGV_GENFUNC\fR
+This form provides a more general procedural escape. It treats
+\fIsrc\fR as the address of a procedure, and passes that procedure
+all of the remaining arguments. The procedure should have the following
+form:
+.RS
+.CS
+int
+\fIgenfunc\fR(dst, interp, key, argc, argv)
+ char *\fIdst\fR;
+ Tcl_Interp *\fIinterp\fR;
+ char *\fIkey\fR;
+ int \fIargc\fR;
+ char **\fIargv\fR;
+{
+}
+.CE
+The \fIdst\fR and \fIkey\fR parameters will contain the
+corresponding fields from the \fIargTable\fR entry. \fIInterp\fR
+will be the same as the \fIinterp\fR argument to \fBTcl_ParseArgv\fR.
+\fIArgc\fR and \fIargv\fR refer to all of the options after the
+matching one. \fIGenfunc\fR should behave in a fashion similar
+to \fBTk_ParseArgv\fR: parse as many of the remaining arguments as it can,
+then return any that are left by compacting them to the beginning of
+\fIargv\fR (starting at \fIargv\fR[0]). \fIGenfunc\fR
+should return a count of how many arguments are left in \fIargv\fR;
+\fBTk_ParseArgv\fR will process them. If \fIgenfunc\fR encounters
+an error then it should leave an error message in interpreter
+\fIinterp\fR's result,
+in the usual Tcl fashion, and return \-1; when this happens
+\fBTk_ParseArgv\fR will abort its processing and return \fBTCL_ERROR\fR.
+.RE
+.SS "FLAGS"
+.TP
+\fBTK_ARGV_DONT_SKIP_FIRST_ARG\fR
+\fBTk_ParseArgv\fR normally treats \fIargv[0]\fR as a program
+or command name, and returns it to the caller just as if it
+had not matched \fIargTable\fR. If this flag is given, then
+\fIargv[0]\fR is not given special treatment.
+.TP
+\fBTK_ARGV_NO_ABBREV\fR
+Normally, \fBTk_ParseArgv\fR accepts unique abbreviations for
+\fIkey\fR values in \fIargTable\fR. If this flag is given then
+only exact matches will be acceptable.
+.TP
+\fBTK_ARGV_NO_LEFTOVERS\fR
+Normally, \fBTk_ParseArgv\fR returns unrecognized arguments to the
+caller. If this bit is set in \fIflags\fR then \fBTk_ParseArgv\fR
+will return an error if it encounters any argument that does not
+match \fIargTable\fR. The only exception to this rule is \fIargv[0]\fR,
+which will be returned to the caller with no errors as
+long as \fBTK_ARGV_DONT_SKIP_FIRST_ARG\fR is not specified.
+.TP
+\fBTK_ARGV_NO_DEFAULTS\fR
+Normally, \fBTk_ParseArgv\fR searches an internal table of
+standard argument specifiers in addition to \fIargTable\fR. If
+this bit is set in \fIflags\fR, then \fBTk_ParseArgv\fR will
+use only \fIargTable\fR and not its default table.
+.SH EXAMPLE
+.PP
+Here is an example definition of an \fIargTable\fR and
+some sample command lines that use the options. Note the effect
+on \fIargc\fR and \fIargv\fR; arguments processed by \fBTk_ParseArgv\fR
+are eliminated from \fIargv\fR, and \fIargc\fR
+is updated to reflect reduced number of arguments.
+.CS
+/*
+ * Define and set default values for globals.
+ */
+int debugFlag = 0;
+int numReps = 100;
+char defaultFileName[] = "out";
+char *fileName = defaultFileName;
+Boolean exec = FALSE;
+
+/*
+ * Define option descriptions.
+ */
+Tk_ArgvInfo argTable[] = {
+ {"\-X", TK_ARGV_CONSTANT, (char *) 1, (char *) &debugFlag,
+ "Turn on debugging printfs"},
+ {"\-N", TK_ARGV_INT, NULL, (char *) &numReps,
+ "Number of repetitions"},
+ {"\-of", TK_ARGV_STRING, NULL, (char *) &fileName,
+ "Name of file for output"},
+ {"x", TK_ARGV_REST, NULL, (char *) &exec,
+ "File to exec, followed by any arguments (must be last argument)."},
+ {NULL, TK_ARGV_END, NULL, NULL,
+ NULL}
+};
+
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ \&...
+
+ if (Tk_ParseArgv(interp, tkwin, &argc, argv, argTable, 0) != TCL_OK) {
+ fprintf(stderr, "%s\en", Tcl_GetString(Tcl_GetObjResult(interp)));
+ exit(1);
+ }
+
+ /*
+ * Remainder of the program.
+ */
+}
+.CE
+.PP
+Note that default values can be assigned to variables named in
+\fIargTable\fR: the variables will only be overwritten if the
+particular arguments are present in \fIargv\fR.
+Here are some example command lines and their effects.
+.CS
+prog \-N 200 infile # just sets the numReps variable to 200
+prog \-of out200 infile # sets fileName to reference "out200"
+prog \-XN 10 infile # sets the debug flag, also sets numReps
+.CE
+In all of the above examples, \fIargc\fR will be set by \fBTk_ParseArgv\fR to 2,
+\fIargv\fR[0] will be
+.QW prog ,
+\fIargv\fR[1] will be
+.QW infile ,
+and \fIargv\fR[2] will be NULL.
+.SH KEYWORDS
+arguments, command line, options
diff --git a/tk8.6/doc/QWinEvent.3 b/tk8.6/doc/QWinEvent.3
new file mode 100644
index 0000000..caa5026
--- /dev/null
+++ b/tk8.6/doc/QWinEvent.3
@@ -0,0 +1,50 @@
+'\"
+'\" 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.
+'\"
+.TH Tk_QueueWindowEvent 3 7.5 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_CollapseMotionEvents, Tk_QueueWindowEvent \- Add a window event to the Tcl event queue
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+int
+\fBTk_CollapseMotionEvents\fR(\fIdisplay, collapse\fR)
+.sp
+\fBTk_QueueWindowEvent\fR(\fIeventPtr, position\fR)
+.SH ARGUMENTS
+.AS Tcl_QueuePosition position
+.AP Display *display in
+Display for which to control motion event collapsing.
+.AP int collapse in
+Indicates whether motion events should be collapsed or not.
+.AP XEvent *eventPtr in
+An event to add to the event queue. It is important
+that all unused fields of the structure be set to zero.
+.AP Tcl_QueuePosition position in
+Where to add the new event in the queue: \fBTCL_QUEUE_TAIL\fR,
+\fBTCL_QUEUE_HEAD\fR, or \fBTCL_QUEUE_MARK\fR.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_QueueWindowEvent\fR places a window event on Tcl's internal event
+queue for eventual servicing. It creates a Tcl_Event structure, copies the
+event into that structure, and calls \fBTcl_QueueEvent\fR to add the event
+to the queue. When the event is eventually removed from the queue it is
+processed just like all window events.
+.PP
+When multiple motion events are received for the same window in rapid
+succession, they are collapsed by default. This behavior can be controlled
+with \fBTk_CollapseMotionEvents\fR. \fBTk_CollapseMotionEvents\fR always
+returns the previous value for collapse behavior on the \fIdisplay\fR.
+.PP
+The \fIposition\fR argument to \fBTk_QueueWindowEvent\fR has
+the same significance as for \fBTcl_QueueEvent\fR; see the
+documentation for \fBTcl_QueueEvent\fR for details.
+.SH KEYWORDS
+callback, clock, handler, modal timeout, events
diff --git a/tk8.6/doc/Restack.3 b/tk8.6/doc/Restack.3
new file mode 100644
index 0000000..2b9097f
--- /dev/null
+++ b/tk8.6/doc/Restack.3
@@ -0,0 +1,45 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_RestackWindow 3 "" Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_RestackWindow \- Change a window's position in the stacking order
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+int
+\fBTk_RestackWindow\fR(\fItkwin, aboveBelow, other\fR)
+.SH ARGUMENTS
+.AS Tk_Window aboveBelow
+.AP Tk_Window tkwin in
+Token for window to restack.
+.AP int aboveBelow in
+Indicates new position of \fItkwin\fR relative to \fIother\fR;
+must be \fBAbove\fR or \fBBelow\fR.
+.AP Tk_Window other in
+\fITkwin\fR will be repositioned just above or below this window.
+Must be a sibling of \fItkwin\fR or a descendant of a sibling.
+If NULL then \fItkwin\fR is restacked above or below all siblings.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_RestackWindow\fR changes the stacking order of \fIwindow\fR relative
+to its siblings.
+If \fIother\fR is specified as NULL then \fIwindow\fR is repositioned
+at the top or bottom of its stacking order, depending on whether
+\fIaboveBelow\fR is \fBAbove\fR or \fBBelow\fR.
+If \fIother\fR has a non-NULL value then \fIwindow\fR is repositioned
+just above or below \fIother\fR.
+.PP
+The \fIaboveBelow\fR argument must have one of the symbolic values
+\fBAbove\fR or \fBBelow\fR.
+Both of these values are defined by the include file <X11/Xlib.h>.
+.SH KEYWORDS
+above, below, obscure, stacking order
diff --git a/tk8.6/doc/RestrictEv.3 b/tk8.6/doc/RestrictEv.3
new file mode 100644
index 0000000..22014a7
--- /dev/null
+++ b/tk8.6/doc/RestrictEv.3
@@ -0,0 +1,79 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_RestrictEvents 3 "" Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_RestrictEvents \- filter and selectively delay X events
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+Tk_RestrictProc *
+\fBTk_RestrictEvents\fR(\fIproc, arg, prevArgPtr\fR)
+.SH ARGUMENTS
+.AS Tk_RestrictProc **prevArgPtr
+.AP Tk_RestrictProc *proc in
+Predicate procedure to call to filter incoming X events.
+NULL means do not restrict events at all.
+.AP ClientData arg in
+Arbitrary argument to pass to \fIproc\fR.
+.AP ClientData *prevArgPtr out
+Pointer to place to save argument to previous restrict procedure.
+.BE
+.SH DESCRIPTION
+.PP
+This procedure is useful in certain situations where applications
+are only prepared to receive certain X events. After
+\fBTk_RestrictEvents\fR is called, \fBTcl_DoOneEvent\fR (and
+hence \fBTk_MainLoop\fR) will filter X input events through
+\fIproc\fR. \fIProc\fR indicates whether a
+given event is to be processed immediately, deferred until some
+later time (e.g. when the event restriction is lifted), or discarded.
+\fIProc\fR
+is a procedure with arguments and result that match
+the type \fBTk_RestrictProc\fR:
+.CS
+typedef Tk_RestrictAction \fBTk_RestrictProc\fR(
+ ClientData \fIarg\fR,
+ XEvent *\fIeventPtr\fR);
+.CE
+The \fIarg\fR argument is a copy of the \fIarg\fR passed
+to \fBTk_RestrictEvents\fR; it may be used to provide \fIproc\fR with
+information it needs to filter events. The \fIeventPtr\fR points to
+an event under consideration. \fIProc\fR returns a restrict action
+(enumerated type \fBTk_RestrictAction\fR) that indicates what
+\fBTcl_DoOneEvent\fR should do with the event. If the return value is
+\fBTK_PROCESS_EVENT\fR, then the event will be handled immediately.
+If the return value is \fBTK_DEFER_EVENT\fR, then the event will be
+left on the event queue for later processing. If the return value is
+\fBTK_DISCARD_EVENT\fR, then the event will be removed from the event
+queue and discarded without being processed.
+.PP
+\fBTk_RestrictEvents\fR uses its return value and \fIprevArgPtr\fR
+to return information about the current event restriction procedure
+(a NULL return value means there are currently no restrictions).
+These values may be used to restore the previous restriction state
+when there is no longer any need for the current restriction.
+.PP
+There are very few places where \fBTk_RestrictEvents\fR is needed.
+In most cases, the best way to restrict events is by changing the
+bindings with the \fBbind\fR Tcl command or by calling
+\fBTk_CreateEventHandler\fR and \fBTk_DeleteEventHandler\fR from C.
+The main place where \fBTk_RestrictEvents\fR must be used is when
+performing synchronous actions (for example, if you need to wait
+for a particular event to occur on a particular window but you do not
+want to invoke any handlers for any other events). The
+.QW obvious
+solution in these situations is to call \fBXNextEvent\fR or
+\fBXWindowEvent\fR, but these procedures cannot be used because
+Tk keeps its own event queue that is separate from the X event
+queue. Instead, call \fBTk_RestrictEvents\fR to set up a filter,
+then call \fBTcl_DoOneEvent\fR to retrieve the desired event(s).
+.SH KEYWORDS
+delay, event, filter, restriction
diff --git a/tk8.6/doc/SetAppName.3 b/tk8.6/doc/SetAppName.3
new file mode 100644
index 0000000..3978850
--- /dev/null
+++ b/tk8.6/doc/SetAppName.3
@@ -0,0 +1,62 @@
+'\"
+'\" Copyright (c) 1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_SetAppName 3 4.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_SetAppName \- Set the name of an application for 'send' commands
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+const char *
+\fBTk_SetAppName\fR(\fItkwin, name\fR)
+.SH ARGUMENTS
+.AS Tk_Window parent
+.AP Tk_Window tkwin in
+Token for window in application. Used only to select a particular
+application.
+.AP "const char" *name in
+Name under which to register the application.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_SetAppName\fR associates a name with a given application and
+records that association on the display containing with the application's
+main window.
+After this procedure has been invoked, other applications on the
+display will be able to use the \fBsend\fR command to invoke operations
+in the application.
+If \fIname\fR is already in use by some other application on the
+display, then a new name will be generated by appending
+.QW "\fB #2\fR"
+to \fIname\fR; if this name is also in use,
+the number will be incremented until an unused name is found.
+The return value from the procedure is a pointer to the name actually
+used.
+.PP
+If the application already has a name when \fBTk_SetAppName\fR is
+called, then the new name replaces the old name.
+.PP
+\fBTk_SetAppName\fR also adds a \fBsend\fR command to the application's
+interpreter, which can be used to send commands from this application
+to others on any of the displays where the application has windows.
+.PP
+The application's name registration persists until the interpreter is
+deleted or the \fBsend\fR command is deleted from \fIinterp\fR, at which
+point the name is automatically unregistered and the application
+becomes inaccessible via \fBsend\fR.
+The application can be made accessible again by calling \fBTk_SetAppName\fR.
+.PP
+\fBTk_SetAppName\fR is called automatically by \fBTk_Init\fR,
+so applications do not normally need to call it explicitly.
+.PP
+The command \fBtk appname\fR provides Tcl-level access to the
+functionality of \fBTk_SetAppName\fR.
+.SH KEYWORDS
+application, name, register, send command
diff --git a/tk8.6/doc/SetCaret.3 b/tk8.6/doc/SetCaret.3
new file mode 100644
index 0000000..fd63f18
--- /dev/null
+++ b/tk8.6/doc/SetCaret.3
@@ -0,0 +1,36 @@
+'\"
+'\" Copyright (c) 2002 ActiveState Corporation.
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH Tk_SetCaretPos 3 8.4 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_SetCaretPos \- set the display caret location
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+int
+\fBTk_SetCaretPos\fR(\fItkwin, x, y, height\fR)
+.SH ARGUMENTS
+.AP Tk_Window tkwin in
+Token for window.
+.AP int x in
+Window-relative x coordinate.
+.AP int y in
+Window-relative y coordinate.
+.AP int h in
+Height of the caret in the window.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_SetCaretPos\fR sets the caret location for the display of the
+specified Tk_Window \fItkwin\fR. The caret is the per-display cursor
+location used for indicating global focus (e.g. to comply with Microsoft
+Accessibility guidelines), as well as for location of the over-the-spot XIM
+(X Input Methods) or Windows IME windows.
+.SH KEYWORDS
+caret, cursor
diff --git a/tk8.6/doc/SetClass.3 b/tk8.6/doc/SetClass.3
new file mode 100644
index 0000000..707975d
--- /dev/null
+++ b/tk8.6/doc/SetClass.3
@@ -0,0 +1,57 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_SetClass 3 "" Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_SetClass, Tk_Class \- set or retrieve a window's class
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+\fBTk_SetClass\fR(\fItkwin, class\fR)
+.sp
+Tk_Uid
+\fBTk_Class\fR(\fItkwin\fR)
+.SH ARGUMENTS
+.AS Tk_Window parent
+.AP Tk_Window tkwin in
+Token for window.
+.AP char *class in
+New class name for window.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_SetClass\fR is called to associate a class with a particular
+window. The \fIclass\fR string identifies the type of the
+window; all windows with the same general class of behavior
+(button, menu, etc.) should have the same class. By
+convention all class names start with a capital letter, and
+there exists a Tcl command with the same name as
+each class (except all in lower-case) which can be used to
+create and manipulate windows of that class.
+A window's class string is initialized to NULL
+when the window is created.
+.PP
+For main windows, Tk automatically propagates the name and class
+to the WM_CLASS property used by window managers. This happens
+either when a main window is actually created (e.g. in
+\fBTk_MakeWindowExist\fR), or when \fBTk_SetClass\fR
+is called, whichever occurs later. If a main window has not been
+assigned a class then Tk will not set the WM_CLASS property for
+the window.
+.PP
+\fBTk_Class\fR is a macro that returns the
+current value of \fItkwin\fR's class. The value is returned
+as a Tk_Uid, which may be used just like a string pointer but also has
+the properties of a unique identifier (see the manual entry for
+\fBTk_GetUid\fR for details).
+If \fItkwin\fR has not yet been given a class, then
+\fBTk_Class\fR will return NULL.
+.SH KEYWORDS
+class, unique identifier, window, window manager
diff --git a/tk8.6/doc/SetClassProcs.3 b/tk8.6/doc/SetClassProcs.3
new file mode 100644
index 0000000..58618da
--- /dev/null
+++ b/tk8.6/doc/SetClassProcs.3
@@ -0,0 +1,87 @@
+'\"
+'\" Copyright (c) 2000 Ajuba Solutions.
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH Tk_SetClassProcs 3 8.4 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_SetClassProcs \- register widget specific procedures
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+\fBTk_SetClassProcs\fR(\fItkwin, procs, instanceData\fR)
+.SH ARGUMENTS
+.AS Tk_ClassProc instanceData
+.AP Tk_Window tkwin in
+Token for window to modify.
+.AP "const Tk_ClassProcs" *procs in
+Pointer to data structure containing widget specific procedures.
+The data structure pointed to by \fIprocs\fR must be static:
+Tk keeps a reference to it as long as the window exists.
+.AP ClientData instanceData in
+Arbitrary one-word value to pass to widget callbacks.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_SetClassProcs\fR is called to register a set of procedures that
+are used as callbacks in different places.
+.PP
+The structure pointed to by \fIprocs\fR contains the following:
+.CS
+typedef struct Tk_ClassProcs {
+ unsigned int \fIsize\fR;
+ Tk_ClassWorldChangedProc *\fIworldChangedProc\fR;
+ Tk_ClassCreateProc *\fIcreateProc\fR;
+ Tk_ClassModalProc *\fImodalProc\fR;
+} \fBTk_ClassProcs\fR;
+.CE
+The \fIsize\fR field is used to simplify future expansion of the
+structure. It should always be set to (literally) \fBsizeof(Tk_ClassProcs)\fR.
+.PP
+\fIworldChangedProc\fR is invoked when the system has altered
+in some way that requires some reaction from the widget. For example,
+when a font alias (see the \fBfont\fR manual entry) is reconfigured,
+widgets configured to use that font alias must update their display
+accordingly. \fIworldChangedProc\fR should have arguments and results
+that match the type \fBTk_ClassWorldChangedProc\fR:
+.CS
+typedef void \fBTk_ClassWorldChangedProc\fR(
+ ClientData \fIinstanceData\fR);
+.CE
+The \fIinstanceData\fR parameter passed to the \fIworldChangedProc\fR
+will be identical to the \fIinstanceData\fR parameter passed to
+\fBTk_SetClassProcs\fR.
+.PP
+\fIcreateProc\fR is used to create platform-dependant windows. It is
+invoked by \fBTk_MakeWindowExist\fR. \fIcreateProc\fR should have
+arguments and results that match the type \fBTk_ClassCreateProc\fR:
+.CS
+typedef Window \fBTk_ClassCreateProc\fR(
+ Tk_Window \fItkwin\fR,
+ Window \fIparent\fR,
+ ClientData \fIinstanceData\fR);
+.CE
+The \fItkwin\fR and \fIinstanceData\fR parameters will be identical to
+the \fItkwin\fR and \fIinstanceData\fR parameters passed to
+\fBTk_SetClassProcs\fR. The \fIparent\fR parameter will be the parent
+of the window to be created. The \fIcreateProc\fR should return the
+created window.
+.PP
+\fImodalProc\fR is invoked after all bindings on a widget have been
+triggered in order to handle a modal loop. \fImodalProc\fR should
+have arguments and results that match the type \fBTk_ClassModalProc\fR:
+.CS
+typedef void \fBTk_ClassModalProc\fR(
+ Tk_Window \fItkwin\fR,
+ XEvent *\fIeventPtr\fR);
+.CE
+The \fItkwin\fR parameter to \fImodalProc\fR will be identical to the
+\fItkwin\fR parameter passed to \fBTk_SetClassProcs\fR. The
+\fIeventPtr\fR parameter will be a pointer to an XEvent structure
+describing the event being processed.
+.SH KEYWORDS
+callback, class
diff --git a/tk8.6/doc/SetGrid.3 b/tk8.6/doc/SetGrid.3
new file mode 100644
index 0000000..28e428b
--- /dev/null
+++ b/tk8.6/doc/SetGrid.3
@@ -0,0 +1,63 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_SetGrid 3 4.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_SetGrid, Tk_UnsetGrid \- control the grid for interactive resizing
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+\fBTk_SetGrid\fR(\fItkwin, reqWidth, reqHeight, widthInc, heightInc\fR)
+.sp
+\fBTk_UnsetGrid\fR(\fItkwin\fR)
+.SH ARGUMENTS
+.AS Tk_Window heightInc
+.AP Tk_Window tkwin in
+Token for window.
+.AP int reqWidth in
+Width in grid units that corresponds to the pixel dimension \fItkwin\fR
+has requested via \fBTk_GeometryRequest\fR.
+.AP int reqHeight in
+Height in grid units that corresponds to the pixel dimension \fItkwin\fR
+has requested via \fBTk_GeometryRequest\fR.
+.AP int widthInc in
+Width of one grid unit, in pixels.
+.AP int heightInc in
+Height of one grid unit, in pixels.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_SetGrid\fR turns on gridded geometry management for \fItkwin\fR's
+toplevel window and specifies the geometry of the grid.
+\fBTk_SetGrid\fR is typically invoked by a widget when its \fBsetGrid\fR
+option is true.
+It restricts interactive resizing of \fItkwin\fR's toplevel window so
+that the space allocated to the toplevel is equal to its requested
+size plus or minus even multiples of \fIwidthInc\fR and \fIheightInc\fR.
+Furthermore, the \fIreqWidth\fR and \fIreqHeight\fR values are
+passed to the window manager so that it can report the window's
+size in grid units during interactive resizes.
+If \fItkwin\fR's configuration changes (e.g., the size of a grid unit
+changes) then the widget should invoke \fBTk_SetGrid\fR again with the new
+information.
+.PP
+\fBTk_UnsetGrid\fR cancels gridded geometry management for
+\fItkwin\fR's toplevel window.
+.PP
+For each toplevel window there can be at most one internal window
+with gridding enabled.
+If \fBTk_SetGrid\fR or \fBTk_UnsetGrid\fR is invoked when some
+other window is already controlling gridding for \fItkwin\fR's
+toplevel, the calls for the new window have no effect.
+.PP
+See the \fBwm\fR manual entry for additional information on gridded geometry
+management.
+.SH KEYWORDS
+grid, window, window manager
diff --git a/tk8.6/doc/SetOptions.3 b/tk8.6/doc/SetOptions.3
new file mode 100644
index 0000000..b5f0782
--- /dev/null
+++ b/tk8.6/doc/SetOptions.3
@@ -0,0 +1,656 @@
+'\"
+'\" Copyright (c) 1998 Sun Microsystems, Inc.
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH Tk_SetOptions 3 8.1 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_CreateOptionTable, Tk_DeleteOptionTable, Tk_InitOptions, Tk_SetOptions, Tk_FreeSavedOptions, Tk_RestoreSavedOptions, Tk_GetOptionValue, Tk_GetOptionInfo, Tk_FreeConfigOptions, Tk_Offset \- process configuration options
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+Tk_OptionTable
+\fBTk_CreateOptionTable(\fIinterp, templatePtr\fB)\fR
+.sp
+\fBTk_DeleteOptionTable(\fIoptionTable\fB)\fR
+.sp
+int
+\fBTk_InitOptions(\fIinterp, recordPtr, optionTable, tkwin\fB)\fR
+.sp
+int
+\fBTk_SetOptions(\fIinterp, recordPtr, optionTable, objc, objv, tkwin, savePtr, maskPtr\fB)\fR
+.sp
+\fBTk_FreeSavedOptions(\fIsavedPtr\fB)\fR
+.sp
+\fBTk_RestoreSavedOptions(\fIsavedPtr\fB)\fR
+.sp
+Tcl_Obj *
+\fBTk_GetOptionValue(\fIinterp, recordPtr, optionTable, namePtr, tkwin\fB)\fR
+.sp
+Tcl_Obj *
+\fBTk_GetOptionInfo(\fIinterp, recordPtr, optionTable, namePtr, tkwin\fB)\fR
+.sp
+\fBTk_FreeConfigOptions(\fIrecordPtr, optionTable, tkwin\fB)\fR
+.sp
+int
+\fBTk_Offset(\fItype, field\fB)\fR
+.SH ARGUMENTS
+.AS Tk_SavedOptions "*const objv[]" in/out
+.AP Tcl_Interp *interp in
+A Tcl interpreter. Most procedures use this only for returning error
+messages; if it is NULL then no error messages are returned. For
+\fBTk_CreateOptionTable\fR the value cannot be NULL; it gives the
+interpreter in which the option table will be used.
+.AP "const Tk_OptionSpec" *templatePtr in
+Points to an array of static information that describes the configuration
+options that are supported. Used to build a Tk_OptionTable. The information
+pointed to by this argument must exist for the lifetime of the Tk_OptionTable.
+.AP Tk_OptionTable optionTable in
+Token for an option table. Must have been returned by a previous call
+to \fBTk_CreateOptionTable\fR.
+.AP char *recordPtr in/out
+Points to structure in which values of configuration options are stored;
+fields of this record are modified by procedures such as \fBTk_SetOptions\fR
+and read by procedures such as \fBTk_GetOptionValue\fR.
+.AP Tk_Window tkwin in
+For options such as \fBTK_OPTION_COLOR\fR, this argument indicates
+the window in which the option will be used. If \fIoptionTable\fR uses
+no window-dependent options, then a NULL value may be supplied for
+this argument.
+.AP int objc in
+Number of values in \fIobjv\fR.
+.AP Tcl_Obj "*const objv[]" in
+Command-line arguments for setting configuring options.
+.AP Tk_SavedOptions *savePtr out
+If not NULL, the structure pointed to by this argument is filled
+in with the old values of any options that were modified and old
+values are restored automatically if an error occurs in \fBTk_SetOptions\fR.
+.AP int *maskPtr out
+If not NULL, the word pointed to by \fImaskPtr\fR is filled in with the
+bit-wise OR of the \fItypeMask\fR fields for the options that
+were modified.
+.AP Tk_SavedOptions *savedPtr in/out
+Points to a structure previously filled in by \fBTk_SetOptions\fR with
+old values of modified options.
+.AP Tcl_Obj *namePtr in
+The value of this object is the name of a particular option. If NULL
+is passed to \fBTk_GetOptionInfo\fR then information is returned for
+all options. Must not be NULL when \fBTk_GetOptionValue\fR is called.
+.AP "type name" type in
+The name of the type of a record.
+.AP "field name" field in
+The name of a field in records of type \fItype\fR.
+.BE
+.SH DESCRIPTION
+.PP
+These procedures handle most of the details of parsing configuration
+options such as those for Tk widgets. Given a description of what
+options are supported, these procedures handle all the details of
+parsing options and storing their values into a C structure associated
+with the widget or object. The procedures were designed primarily for
+widgets in Tk, but they can also be used for other kinds of objects that
+have configuration options. In the rest of this manual page
+.QW widget
+will be used to refer to the object whose options are being managed; in
+practice the object may not actually be a widget. The term
+.QW "widget record"
+is used to refer to the C-level structure in
+which information about a particular widget or object is stored.
+.PP
+Note: the easiest way to learn how to use these procedures is to
+look at a working example. In Tk, the simplest example is the code
+that implements the button family of widgets, which is in \fBtkButton.c\fR.
+Other examples are in \fBtkSquare.c\fR and \fBtkMenu.c\fR.
+.PP
+In order to use these procedures, the code that implements the widget
+must contain a static array of Tk_OptionSpec structures. This is a
+template that describes the various options supported by that class of
+widget; there is a separate template for each kind of widget. The
+template contains information such as the name of each option, its type,
+its default value, and where the value of the option is stored in the
+widget record. See TEMPLATES below for more detail.
+.PP
+In order to process configuration options efficiently, the static
+template must be augmented with additional information that is available
+only at runtime. The procedure \fBTk_CreateOptionTable\fR creates this
+dynamic information from the template and returns a Tk_OptionTable token
+that describes both the static and dynamic information. All of the
+other procedures, such as \fBTk_SetOptions\fR, take a Tk_OptionTable
+token as argument. Typically, \fBTk_CreateOptionTable\fR is called the
+first time that a widget of a particular class is created and the
+resulting Tk_OptionTable is used in the future for all widgets of that
+class. A Tk_OptionTable may be used only in a single interpreter, given
+by the \fIinterp\fR argument to \fBTk_CreateOptionTable\fR. When an
+option table is no longer needed \fBTk_DeleteOptionTable\fR should be
+called to free all of its resources. All of the option tables
+for a Tcl interpreter are freed automatically if the interpreter is deleted.
+.PP
+\fBTk_InitOptions\fR is invoked when a new widget is created to set the
+default values for all of the widget's configuration options that do not
+have \fBTK_OPTION_DONT_SET_DEFAULT\fR set in their \fIflags\fR field.
+\fBTk_InitOptions\fR is passed a token for an option table
+(\fIoptionTable\fR) and a pointer to a widget record (\fIrecordPtr\fR),
+which is the C structure that holds information about this widget.
+\fBTk_InitOptions\fR uses the information in the option table to choose an
+appropriate default for each option, except those having
+\fBTK_OPTION_DONT_SET_DEFAULT\fR set, then it stores the default value
+directly into the widget record, overwriting any information that was
+already present in the widget record. \fBTk_InitOptions\fR normally
+returns \fBTCL_OK\fR. If an error occurred while setting the default
+values (e.g., because a default value was erroneous) then \fBTCL_ERROR\fR
+is returned and an error message is left in \fIinterp\fR's result if
+\fIinterp\fR is not NULL.
+.PP
+\fBTk_SetOptions\fR is invoked to modify configuration options based
+on information specified in a Tcl command. The command might be one that
+creates a new widget, or a command that modifies options on an existing
+widget. The \fIobjc\fR and \fIobjv\fR arguments describe the
+values of the arguments from the Tcl command. \fIObjv\fR must contain
+an even number of objects: the first object of each pair gives the name of
+an option and the second object gives the new value for that option.
+\fBTk_SetOptions\fR looks up each name in \fIoptionTable\fR, checks that
+the new value of the option conforms to the type in \fIoptionTable\fR,
+and stores the value of the option into the widget record given by
+\fIrecordPtr\fR. \fBTk_SetOptions\fR normally returns \fBTCL_OK\fR. If
+an error occurred (such as an unknown option name or an illegal option
+value) then \fBTCL_ERROR\fR is returned and an error message is left in
+\fIinterp\fR's result if \fIinterp\fR is not NULL.
+.PP
+\fBTk_SetOptions\fR has two additional features. First, if the
+\fImaskPtr\fR argument is not NULL then it points to an integer
+value that is filled in with information about the options that were
+modified. For each option in the template passed to
+\fBTk_CreateOptionTable\fR there is a \fItypeMask\fR field. The
+bits of this field are defined by the code that implements the widget;
+for example, each bit might correspond to a particular configuration option.
+Alternatively, bits might be used functionally. For example, one bit might
+be used for redisplay: all options that affect the widget's display, such
+that changing the option requires the widget to be redisplayed, might have
+that bit set. Another bit might indicate that the geometry of the widget
+must be recomputed, and so on. \fBTk_SetOptions\fR OR's together the
+\fItypeMask\fR fields from all the options that were modified and returns
+this value at *\fImaskPtr\fR; the caller can then use this information
+to optimize itself so that, for example, it does not redisplay the widget
+if the modified options do not affect the widget's appearance.
+.PP
+The second additional feature of \fBTk_SetOptions\fR has to do with error
+recovery. If an error occurs while processing configuration options, this
+feature makes it possible to restore all the configuration options to their
+previous values. Errors can occur either while processing options in
+\fBTk_SetOptions\fR or later in the caller. In many cases the caller does
+additional processing after \fBTk_SetOptions\fR returns; for example, it
+might use an option value to set a trace on a variable and may detect
+an error if the variable is an array instead of a scalar. Error recovery
+is enabled by passing in a non-NULL value for the \fIsavePtr\fR argument
+to \fBTk_SetOptions\fR; this should be a pointer to an uninitialized
+Tk_SavedOptions structure on the caller's stack. \fBTk_SetOptions\fR
+overwrites the structure pointed to by \fIsavePtr\fR with information
+about the old values of any options modified by the procedure.
+If \fBTk_SetOptions\fR returns successfully, the
+caller uses the structure in one of two ways. If the caller completes
+its processing of the new options without any errors, then it must pass
+the structure to \fBTk_FreeSavedOptions\fR so that the old values can be
+freed. If the caller detects an error in its processing of the new
+options, then it should pass the structure to \fBTk_RestoreSavedOptions\fR,
+which will copy the old values back into the widget record and free
+the new values.
+If \fBTk_SetOptions\fR detects an error then it automatically restores
+any options that had already been modified and leaves *\fIsavePtr\fR in
+an empty state: the caller need not call either \fBTk_FreeSavedOptions\fR or
+\fBTk_RestoreSavedOptions\fR.
+If the \fIsavePtr\fR argument to \fBTk_SetOptions\fR is NULL then
+\fBTk_SetOptions\fR frees each old option value immediately when it sets a new
+value for the option. In this case, if an error occurs in the third
+option, the old values for the first two options cannot be restored.
+.PP
+\fBTk_GetOptionValue\fR returns the current value of a configuration option
+for a particular widget. The \fInamePtr\fR argument contains the name of
+an option; \fBTk_GetOptionValue\fR uses \fIoptionTable\fR
+to lookup the option and extract its value from the widget record
+pointed to by \fIrecordPtr\fR, then it returns an object containing
+that value. If an error occurs (e.g., because \fInamePtr\fR contains an
+unknown option name) then NULL is returned and an error message is left
+in \fIinterp\fR's result unless \fIinterp\fR is NULL.
+.PP
+\fBTk_GetOptionInfo\fR returns information about configuration options in
+a form suitable for \fBconfigure\fR widget commands. If the \fInamePtr\fR
+argument is not NULL, it points to an object that gives the name of a
+configuration option; \fBTk_GetOptionInfo\fR returns an object containing
+a list with five elements, which are the name of the option, the name and
+class used for the option in the option database, the default value for
+the option, and the current value for the option. If the \fInamePtr\fR
+argument is NULL, then \fBTk_GetOptionInfo\fR returns information about
+all options in the form of a list of lists; each sublist describes one
+option. Synonym options are handled differently depending on whether
+\fInamePtr\fR is NULL: if \fInamePtr\fR is NULL then the sublist for
+each synonym option has only two elements, which are the name of the
+option and the name of the other option that it refers to; if \fInamePtr\fR
+is non-NULL and names a synonym option then the object returned
+is the five-element list
+for the other option that the synonym refers to. If an error occurs
+(e.g., because \fInamePtr\fR contains an unknown option name) then NULL
+is returned and an error message is left in \fIinterp\fR's result unless
+\fIinterp\fR is NULL.
+.PP
+\fBTk_FreeConfigOptions\fR must be invoked when a widget is deleted.
+It frees all of the resources associated with any of the configuration
+options defined in \fIrecordPtr\fR by \fIoptionTable\fR.
+.PP
+The \fBTk_Offset\fR macro is provided as a safe way of generating the
+\fIobjOffset\fR and \fIinternalOffset\fR values for entries in
+Tk_OptionSpec structures. It takes two arguments: the name of a type
+of record, and the name of a field in that record. It returns the byte
+offset of the named field in records of the given type.
+.SH "TEMPLATES"
+.PP
+The array of Tk_OptionSpec structures passed to \fBTk_CreateOptionTable\fR
+via its \fItemplatePtr\fR argument describes the configuration options
+supported by a particular class of widgets. Each structure specifies
+one configuration option and has the following fields:
+.CS
+typedef struct {
+ Tk_OptionType \fItype\fR;
+ const char *\fIoptionName\fR;
+ const char *\fIdbName\fR;
+ const char *\fIdbClass\fR;
+ const char *\fIdefValue\fR;
+ int \fIobjOffset\fR;
+ int \fIinternalOffset\fR;
+ int \fIflags\fR;
+ const void *\fIclientData\fR;
+ int \fItypeMask\fR;
+} \fBTk_OptionSpec\fR;
+.CE
+The \fItype\fR field indicates what kind of configuration option this is
+(e.g. \fBTK_OPTION_COLOR\fR for a color value, or \fBTK_OPTION_INT\fR for
+an integer value). \fIType\fR determines how the
+value of the option is parsed (more on this below).
+The \fIoptionName\fR field is a string such as \fB\-font\fR or \fB\-bg\fR;
+it is the name used for the option in Tcl commands and passed to
+procedures via the \fIobjc\fR or \fInamePtr\fR arguments.
+The \fIdbName\fR and \fIdbClass\fR fields are used by \fBTk_InitOptions\fR
+to look up a default value for this option in the option database; if
+\fIdbName\fR is NULL then the option database is not used by
+\fBTk_InitOptions\fR for this option. The \fIdefValue\fR field
+specifies a default value for this configuration option if no
+value is specified in the option database. The \fIobjOffset\fR and
+\fIinternalOffset\fR fields indicate where to store the value of this
+option in widget records (more on this below); values for the \fIobjOffset\fR
+and \fIinternalOffset\fR fields should always be generated with the
+\fBTk_Offset\fR macro.
+The \fIflags\fR field contains additional information
+to control the processing of this configuration option (see below
+for details).
+\fIClientData\fR provides additional type-specific data needed
+by certain types. For instance, for \fBTK_OPTION_COLOR\fR types,
+\fIclientData\fR is a string giving the default value to use on
+monochrome displays. See the descriptions of the different types
+below for details.
+The last field, \fItypeMask\fR, is used by \fBTk_SetOptions\fR to
+return information about which options were modified; see the description
+of \fBTk_SetOptions\fR above for details.
+.PP
+When \fBTk_InitOptions\fR and \fBTk_SetOptions\fR store the value of an
+option into the widget record, they can do it in either of two ways.
+If the \fIobjOffset\fR field of the Tk_OptionSpec is greater than
+or equal to zero, then the value of the option is stored as a
+(Tcl_Obj *) at the location in the widget record given by \fIobjOffset\fR.
+If the \fIinternalOffset\fR field of the Tk_OptionSpec is
+greater than or equal to zero, then the value of the option is stored
+in a type-specific internal form at the location in the widget record
+given by \fIinternalOffset\fR. For example, if the option's type is
+\fBTK_OPTION_INT\fR then the internal form is an integer. If the
+\fIobjOffset\fR or \fIinternalOffset\fR field is negative then the
+value is not stored in that form. At least one of the offsets must be
+greater than or equal to zero.
+.PP
+The \fIflags\fR field consists of one or more bits ORed together. The
+following flags are supported:
+.TP
+\fBTK_OPTION_NULL_OK\fR
+If this bit is set for an option then an empty string will be accepted as
+the value for the option and the resulting internal form will be a NULL
+pointer, a zero value, or \fBNone\fR, depending on the type of the option.
+If the flag is not set then empty strings will result in errors.
+\fBTK_OPTION_NULL_OK\fR is typically used to allow a
+feature to be turned off entirely, e.g. set a cursor value to
+\fBNone\fR so that a window simply inherits its parent's cursor.
+Not all option types support the \fBTK_OPTION_NULL_OK\fR
+flag; for those that do, there is an explicit indication of that fact
+in the descriptions below.
+.TP
+\fBTK_OPTION_DONT_SET_DEFAULT\fR
+If this bit is set for an option then no default value will be set in
+\fBTk_InitOptions\fR for this option. Neither the option database, nor any
+system default value, nor \fIoptionTable\fR are used to give a default
+value to this option. Instead it is assumed that the caller has already
+supplied a default value in the widget code.
+.PP
+The \fItype\fR field of each Tk_OptionSpec structure determines
+how to parse the value of that configuration option. The
+legal value for \fItype\fR, and the corresponding actions, are
+described below. If the type requires a \fItkwin\fR value to be
+passed into procedures like \fBTk_SetOptions\fR, or if it uses
+the \fIclientData\fR field of the Tk_OptionSpec, then it is indicated
+explicitly; if not mentioned, the type requires neither \fItkwin\fR
+nor \fIclientData\fR.
+.TP
+\fBTK_OPTION_ANCHOR\fR
+The value must be a standard anchor position such as \fBne\fR or
+\fBcenter\fR. The internal form is a Tk_Anchor value like the ones
+returned by \fBTk_GetAnchorFromObj\fR.
+.TP
+\fBTK_OPTION_BITMAP\fR
+The value must be a standard Tk bitmap name. The internal form is a
+Pixmap token like the ones returned by \fBTk_AllocBitmapFromObj\fR.
+This option type requires \fItkwin\fR to be supplied to procedures
+such as \fBTk_SetOptions\fR, and it supports the \fBTK_OPTION_NULL_OK\fR flag.
+.TP
+\fBTK_OPTION_BOOLEAN\fR
+The value must be a standard boolean value such as \fBtrue\fR or
+\fBno\fR. The internal form is an integer with value 0 or 1.
+.TP
+\fBTK_OPTION_BORDER\fR
+The value must be a standard color name such as \fBred\fR or \fB#ff8080\fR.
+The internal form is a Tk_3DBorder token like the ones returned
+by \fBTk_Alloc3DBorderFromObj\fR.
+This option type requires \fItkwin\fR to be supplied to procedures
+such as \fBTk_SetOptions\fR, and it supports the \fBTK_OPTION_NULL_OK\fR flag.
+.TP
+\fBTK_OPTION_COLOR\fR
+The value must be a standard color name such as \fBred\fR or \fB#ff8080\fR.
+The internal form is an (XColor *) token like the ones returned by
+\fBTk_AllocColorFromObj\fR.
+This option type requires \fItkwin\fR to be supplied to procedures
+such as \fBTk_SetOptions\fR, and it supports the \fBTK_OPTION_NULL_OK\fR flag.
+.TP
+\fBTK_OPTION_CURSOR\fR
+The value must be a standard cursor name such as \fBcross\fR or \fB@foo\fR.
+The internal form is a Tk_Cursor token like the ones returned by
+\fBTk_AllocCursorFromObj\fR.
+This option type requires \fItkwin\fR to be supplied to procedures
+such as \fBTk_SetOptions\fR, and when the option is set the cursor
+for the window is changed by calling \fBXDefineCursor\fR. This
+option type also supports the \fBTK_OPTION_NULL_OK\fR flag.
+.TP
+\fBTK_OPTION_CUSTOM\fR
+This option allows applications to define new option types. The
+clientData field of the entry points to a structure defining the new
+option type. See the section \fBCUSTOM OPTION TYPES\fR below for details.
+.TP
+\fBTK_OPTION_DOUBLE\fR
+The string value must be a floating-point number in
+the format accepted by \fBstrtol\fR. The internal form is a C
+\fBdouble\fR value. This option type supports the \fBTK_OPTION_NULL_OK\fR
+flag; if a NULL value is set, the internal representation is set to zero.
+.TP
+\fBTK_OPTION_END\fR
+Marks the end of the template. There must be a Tk_OptionSpec structure
+with \fItype\fR \fBTK_OPTION_END\fR at the end of each template. If the
+\fIclientData\fR field of this structure is not NULL, then it points to
+an additional array of Tk_OptionSpec's, which is itself terminated by
+another \fBTK_OPTION_END\fR entry. Templates may be chained arbitrarily
+deeply. This feature allows common options to be shared by several
+widget classes.
+.TP
+\fBTK_OPTION_FONT\fR
+The value must be a standard font name such as \fBTimes 16\fR.
+The internal form is a Tk_Font handle like the ones returned by
+\fBTk_AllocFontFromObj\fR.
+This option type requires \fItkwin\fR to be supplied to procedures
+such as \fBTk_SetOptions\fR, and it supports the \fBTK_OPTION_NULL_OK\fR flag.
+.TP
+\fBTK_OPTION_INT\fR
+The string value must be an integer in the format accepted by
+\fBstrtol\fR (e.g. \fB0\fR and \fB0x\fR prefixes may be used to
+specify octal or hexadecimal numbers, respectively). The internal
+form is a C \fBint\fR value.
+.TP
+\fBTK_OPTION_JUSTIFY\fR
+The value must be a standard justification value such as \fBleft\fR.
+The internal form is a Tk_Justify like the values returned by
+\fBTk_GetJustifyFromObj\fR.
+.TP
+\fBTK_OPTION_PIXELS\fR
+The value must specify a screen distance such as \fB2i\fR or \fB6.4\fR.
+The internal form is an integer value giving a
+distance in pixels, like the values returned by
+\fBTk_GetPixelsFromObj\fR. Note: if the \fIobjOffset\fR field is not
+used then information about the original value of this option will be lost.
+See \fBOBJOFFSET VS. INTERNALOFFSET\fR below for details. This option
+type supports the \fBTK_OPTION_NULL_OK\fR flag; if a NULL value is set, the
+internal representation is set to zero.
+.TP
+\fBTK_OPTION_RELIEF\fR
+The value must be standard relief such as \fBraised\fR.
+The internal form is an integer relief value such as
+\fBTK_RELIEF_RAISED\fR. This option type supports the \fBTK_OPTION_NULL_OK\fR
+flag; if the empty string is specified as the value for the option,
+the integer relief value is set to \fBTK_RELIEF_NULL\fR.
+.TP
+\fBTK_OPTION_STRING\fR
+The value may be any string. The internal form is a (char *) pointer
+that points to a dynamically allocated copy of the value.
+This option type supports the \fBTK_OPTION_NULL_OK\fR flag.
+.TP
+\fBTK_OPTION_STRING_TABLE\fR
+For this type, \fIclientData\fR is a pointer to an array of strings
+suitable for passing to \fBTcl_GetIndexFromObj\fR. The value must
+be one of the strings in the table, or a unique abbreviation of
+one of the strings. The internal form is an integer giving the index
+into the table of the matching string, like the return value
+from \fBTcl_GetStringFromObj\fR.
+.TP
+\fBTK_OPTION_SYNONYM\fR
+This type is used to provide alternative names for an option (for
+example, \fB\-bg\fR is often used as a synonym for \fB\-background\fR).
+The \fBclientData\fR field is a string that gives the name of another
+option in the same table. Whenever the synonym option is used, the
+information from the other option will be used instead.
+.TP
+\fBTK_OPTION_WINDOW\fR
+The value must be a window path name. The internal form is a
+\fBTk_Window\fR token for the window.
+This option type requires \fItkwin\fR to be supplied to procedures
+such as \fBTk_SetOptions\fR (in order to identify the application),
+and it supports the \fBTK_OPTION_NULL_OK\fR flag.
+.SH "STORAGE MANAGEMENT ISSUES"
+.PP
+If a field of a widget record has its offset stored in the \fIobjOffset\fR
+or \fIinternalOffset\fR field of a Tk_OptionSpec structure then the
+procedures described here will handle all of the storage allocation and
+resource management issues associated with the field. When the value
+of an option is changed, \fBTk_SetOptions\fR (or \fBTk_FreeSavedOptions\fR)
+will automatically free any resources associated with the old value, such as
+Tk_Fonts for \fBTK_OPTION_FONT\fR options or dynamically allocated memory for
+\fBTK_OPTION_STRING\fR options. For an option stored as an object using the
+\fIobjOffset\fR field of a Tk_OptionSpec, the widget record shares the
+object pointed to by the \fIobjv\fR value from the call to
+\fBTk_SetOptions\fR. The reference count for this object is incremented
+when a pointer to it is stored in the widget record and decremented when
+the option is modified. When the widget is deleted
+\fBTk_FreeConfigOptions\fR should be invoked; it will free the resources
+associated with all options and decrement reference counts for any
+objects.
+.PP
+However, the widget code is responsible for storing NULL or \fBNone\fR in
+all pointer and token fields before invoking \fBTk_InitOptions\fR.
+This is needed to allow proper cleanup in the rare case where
+an error occurs in \fBTk_InitOptions\fR.
+.SH "OBJOFFSET VS. INTERNALOFFSET"
+.PP
+In most cases it is simplest to use the \fIinternalOffset\fR field of
+a Tk_OptionSpec structure and not the \fIobjOffset\fR field. This
+makes the internal form of the value immediately available to the
+widget code so the value does not have to be extracted from an object
+each time it is used. However, there are two cases where the
+\fIobjOffset\fR field is useful. The first case is for
+\fBTK_OPTION_PIXELS\fR options. In this case, the internal form is
+an integer pixel value that is valid only for a particular screen.
+If the value of the option is retrieved, it will be returned as a simple
+number. For example, after the command \fB.b configure \-borderwidth 2m\fR,
+the command \fB.b configure \-borderwidth\fR might return 7, which is the
+integer pixel value corresponding to \fB2m\fR. Unfortunately, this loses
+the original screen-independent value. Thus for \fBTK_OPTION_PIXELS\fR options
+it is better to use the \fIobjOffset\fR field. In this case the original
+value of the option is retained in the object and can be returned when
+the option is retrieved. In most cases it is convenient to use the
+\fIinternalOffset\fR field as well, so that the integer value is
+immediately available for use in the widget code (alternatively,
+\fBTk_GetPixelsFromObj\fR can be used to extract the integer value from
+the object whenever it is needed). Note: the problem of losing information
+on retrievals exists only for \fBTK_OPTION_PIXELS\fR options.
+.PP
+The second reason to use the \fIobjOffset\fR field is in order to
+implement new types of options not supported by these procedures.
+To implement a new type of option, you can use \fBTK_OPTION_STRING\fR as
+the type in the Tk_OptionSpec structure and set the \fIobjOffset\fR field
+but not the \fIinternalOffset\fR field. Then, after calling
+\fBTk_SetOptions\fR, convert the object to internal form yourself.
+.SH "CUSTOM OPTION TYPES"
+.PP
+Applications can extend the built-in configuration types with
+additional configuration types by writing procedures to parse, print,
+free, and restore saved copies of the type and creating a structure
+pointing to those procedures:
+.CS
+typedef struct Tk_ObjCustomOption {
+ char *name;
+ Tk_CustomOptionSetProc *\fIsetProc\fR;
+ Tk_CustomOptionGetProc *\fIgetProc\fR;
+ Tk_CustomOptionRestoreProc *\fIrestoreProc\fR;
+ Tk_CustomOptionFreeProc *\fIfreeProc\fR;
+ ClientData \fIclientData\fR;
+} \fBTk_ObjCustomOption\fR;
+
+typedef int \fBTk_CustomOptionSetProc\fR(
+ ClientData \fIclientData\fR,
+ Tcl_Interp *\fIinterp\fR,
+ Tk_Window \fItkwin\fR,
+ Tcl_Obj **\fIvaluePtr\fR,
+ char *\fIrecordPtr\fR,
+ int \fIinternalOffset\fR,
+ char *\fIsaveInternalPtr\fR,
+ int \fIflags\fR);
+
+typedef Tcl_Obj *\fBTk_CustomOptionGetProc\fR(
+ ClientData \fIclientData\fR,
+ Tk_Window \fItkwin\fR,
+ char *\fIrecordPtr\fR,
+ int \fIinternalOffset\fR);
+
+typedef void \fBTk_CustomOptionRestoreProc\fR(
+ ClientData \fIclientData\fR,
+ Tk_Window \fItkwin\fR,
+ char *\fIinternalPtr\fR,
+ char *\fIsaveInternalPtr\fR);
+
+typedef void \fBTk_CustomOptionFreeProc\fR(
+ ClientData \fIclientData\fR,
+ Tk_Window \fItkwin\fR,
+ char *\fIinternalPtr\fR);
+.CE
+.PP
+The Tk_ObjCustomOption structure contains six fields: a name
+for the custom option type; pointers to the four procedures; and a
+\fIclientData\fR value to be passed to those procedures when they are
+invoked. The \fIclientData\fR value typically points to a structure
+containing information that is needed by the procedures when they are
+parsing and printing options. \fIRestoreProc\fR and \fIfreeProc\fR
+may be NULL, indicating that no function should be called for those
+operations.
+.PP
+The \fIsetProc\fR procedure is invoked by \fBTk_SetOptions\fR to
+convert a Tcl_Obj into an internal representation and store the
+resulting value in the widget record. The arguments are:
+.RS
+.TP
+\fIclientData\fR
+A copy of the \fIclientData\fR field in the Tk_ObjCustomOption
+structure.
+.TP
+\fIinterp\fR
+A pointer to a Tcl interpreter, used for error reporting.
+.TP
+\fITkwin\fR
+A copy of the \fItkwin\fR argument to \fBTk_SetOptions\fR
+.TP
+\fIvaluePtr\fR
+A pointer to a reference to a Tcl_Obj describing the new value for the
+option; it could have been specified explicitly in the call to
+\fBTk_SetOptions\fR or it could come from the option database or a
+default. If the objOffset for the option is non-negative (the option
+value is stored as a (Tcl_Obj *) in the widget record), the Tcl_Obj
+pointer referenced by \fIvaluePtr\fR is the pointer that will be
+stored at the objOffset for the option. \fISetProc\fR may modify the
+value if necessary; for example, \fIsetProc\fR may change the value to
+NULL to support the \fBTK_OPTION_NULL_OK\fR flag.
+.TP
+\fIrecordPtr\fR
+A pointer to the start of the widget record to modify.
+.TP
+\fIinternalOffset\fR
+Offset in bytes from the start of the widget record to the location
+where the internal representation of the option value is to be placed.
+.TP
+\fIsaveInternalPtr\fR
+A pointer to storage allocated in a Tk_SavedOptions structure for the
+internal representation of the original option value. Before setting
+the option to its new value, \fIsetProc\fR should set the value
+referenced by \fIsaveInternalPtr\fR to the original value of the
+option in order to support \fBTk_RestoreSavedOptions\fR.
+.TP
+\fIflags\fR
+A copy of the \fIflags\fR field in the Tk_OptionSpec structure for the
+option
+.RE
+.PP
+\fISetProc\fR returns a standard Tcl result: \fBTCL_OK\fR to indicate successful
+processing, or \fBTCL_ERROR\fR to indicate a failure of any kind. An error
+message may be left in the Tcl interpreter given by \fIinterp\fR in
+the case of an error.
+.PP
+The \fIgetProc\fR procedure is invoked by \fBTk_GetOptionValue\fR and
+\fBTk_GetOptionInfo\fR to retrieve a Tcl_Obj representation of the
+internal representation of an option. The \fIclientData\fR argument
+is a copy of the \fIclientData\fR field in the Tk_ObjCustomOption
+structure. \fITkwin\fR is a copy of the \fItkwin\fR argument to
+\fBTk_GetOptionValue\fR or \fBTk_GetOptionInfo\fR. \fIRecordPtr\fR
+is a pointer to the beginning of the widget record to query.
+\fIInternalOffset\fR is the offset in bytes from the beginning of the
+widget record to the location where the internal representation of the
+option value is stored. \fIGetProc\fR must return a pointer to a
+Tcl_Obj representing the value of the option.
+.PP
+The \fIrestoreProc\fR procedure is invoked by
+\fBTk_RestoreSavedOptions\fR to restore a previously saved internal
+representation of a custom option value. The \fIclientData\fR argument
+is a copy of the \fIclientData\fR field in the Tk_ObjCustomOption
+structure. \fITkwin\fR is a copy of the \fItkwin\fR argument to
+\fBTk_GetOptionValue\fR or \fBTk_GetOptionInfo\fR. \fIInternalPtr\fR
+is a pointer to the location where internal representation of the
+option value is stored.
+\fISaveInternalPtr\fR is a pointer to the saved value.
+\fIRestoreProc\fR must copy the value from \fIsaveInternalPtr\fR to
+\fIinternalPtr\fR to restore the value. \fIRestoreProc\fR need not
+free any memory associated with either \fIinternalPtr\fR or
+\fIsaveInternalPtr\fR; \fIfreeProc\fR will be invoked to free that
+memory if necessary. \fIRestoreProc\fR has no return value.
+.PP
+The \fIfreeProc\fR procedure is invoked by \fBTk_SetOptions\fR and
+\fBTk_FreeSavedOptions\fR to free any storage allocated for the
+internal representation of a custom option. The \fIclientData\fR argument
+is a copy of the \fIclientData\fR field in the Tk_ObjCustomOption
+structure. \fITkwin\fR is a copy of the \fItkwin\fR argument to
+\fBTk_GetOptionValue\fR or \fBTk_GetOptionInfo\fR. \fIInternalPtr\fR
+is a pointer to the location where the internal representation of the
+option value is stored. The \fIfreeProc\fR must free any storage
+associated with the option. \fIFreeProc\fR has no return value.
+.SH KEYWORDS
+anchor, bitmap, boolean, border, color, configuration option,
+cursor, double, font, integer, justify,
+pixels, relief, screen distance, synonym
diff --git a/tk8.6/doc/SetVisual.3 b/tk8.6/doc/SetVisual.3
new file mode 100644
index 0000000..6d3fd83
--- /dev/null
+++ b/tk8.6/doc/SetVisual.3
@@ -0,0 +1,50 @@
+'\"
+'\" Copyright (c) 1992 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_SetWindowVisual 3 4.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_SetWindowVisual \- change visual characteristics of window
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+int
+\fBTk_SetWindowVisual\fR(\fItkwin, visual, depth, colormap\fR)
+.SH ARGUMENTS
+.AS "Tk_Window int" colormap
+.AP Tk_Window tkwin in
+Token for window.
+.AP Visual *visual in
+New visual type to use for \fItkwin\fR.
+.AP "int" depth in
+Number of bits per pixel desired for \fItkwin\fR.
+.AP Colormap colormap in
+New colormap for \fItkwin\fR, which must be compatible with
+\fIvisual\fR and \fIdepth\fR.
+.BE
+.SH DESCRIPTION
+.PP
+When Tk creates a new window it assigns it the default visual
+characteristics (visual, depth, and colormap) for its screen.
+\fBTk_SetWindowVisual\fR may be called to change them.
+\fBTk_SetWindowVisual\fR must be called before the window has
+actually been created in X (e.g. before \fBTk_MapWindow\fR or
+\fBTk_MakeWindowExist\fR has been invoked for the window).
+The safest thing is to call \fBTk_SetWindowVisual\fR immediately
+after calling \fBTk_CreateWindow\fR.
+If \fItkwin\fR has already been created before \fBTk_SetWindowVisual\fR
+is called then it returns 0 and does not make any changes; otherwise
+it returns 1 to signify that the operation
+completed successfully.
+.PP
+Note: \fBTk_SetWindowVisual\fR should not be called if you just want
+to change a window's colormap without changing its visual or depth;
+call \fBTk_SetWindowColormap\fR instead.
+.SH KEYWORDS
+colormap, depth, visual
diff --git a/tk8.6/doc/StrictMotif.3 b/tk8.6/doc/StrictMotif.3
new file mode 100644
index 0000000..4319d53
--- /dev/null
+++ b/tk8.6/doc/StrictMotif.3
@@ -0,0 +1,38 @@
+'\"
+'\" 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.
+'\"
+.TH Tk_StrictMotif 3 4.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_StrictMotif \- Return value of tk_strictMotif variable
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+int
+\fBTk_StrictMotif\fR(\fItkwin\fR)
+.SH ARGUMENTS
+.AS Tk_Window tkwin
+.AP Tk_Window tkwin in
+Token for window.
+.BE
+.SH DESCRIPTION
+.PP
+This procedure returns the current value of the \fBtk_strictMotif\fR
+variable in the interpreter associated with \fItkwin\fR's application.
+The value is returned as an integer that is either 0 or 1.
+1 means that strict Motif compliance has been requested, so anything
+that is not part of the Motif specification should be avoided.
+0 means that
+.QW Motif-like
+is good enough, and extra features are welcome.
+.PP
+This procedure uses a link to the Tcl variable to provide much
+faster access to the variable's value than could be had by calling
+\fBTcl_GetVar\fR.
+.SH KEYWORDS
+Motif compliance, tk_strictMotif variable
diff --git a/tk8.6/doc/TextLayout.3 b/tk8.6/doc/TextLayout.3
new file mode 100644
index 0000000..5729a44
--- /dev/null
+++ b/tk8.6/doc/TextLayout.3
@@ -0,0 +1,276 @@
+'\"
+'\" 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.
+'\"
+.TH Tk_ComputeTextLayout 3 8.1 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_ComputeTextLayout, Tk_FreeTextLayout, Tk_DrawTextLayout, Tk_UnderlineTextLayout, Tk_PointToChar, Tk_CharBbox, Tk_DistanceToTextLayout, Tk_IntersectTextLayout, Tk_TextLayoutToPostscript \- routines to measure and display single-font, multi-line, justified text.
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+Tk_TextLayout
+\fBTk_ComputeTextLayout(\fItkfont, string, numChars, wrapLength, justify, flags, widthPtr, heightPtr\fB)\fR
+.sp
+void
+\fBTk_FreeTextLayout(\fIlayout\fB)\fR
+.sp
+void
+\fBTk_DrawTextLayout(\fIdisplay, drawable, gc, layout, x, y, firstChar, lastChar\fB)\fR
+.sp
+void
+\fBTk_UnderlineTextLayout(\fIdisplay, drawable, gc, layout, x, y, underline\fB)\fR
+.sp
+int
+\fBTk_PointToChar(\fIlayout, x, y\fB)\fR
+.sp
+int
+\fBTk_CharBbox(\fIlayout, index, xPtr, yPtr, widthPtr, heightPtr\fB)\fR
+.sp
+int
+\fBTk_DistanceToTextLayout(\fIlayout, x, y\fB)\fR
+.sp
+int
+\fBTk_IntersectTextLayout(\fIlayout, x, y, width, height\fB)\fR
+.sp
+void
+\fBTk_TextLayoutToPostscript(\fIinterp, layout\fB)\fR
+.SH ARGUMENTS
+.AS Tk_TextLayout "*xPtr, *yPtr"
+.AP Tk_Font tkfont in
+Font to use when constructing and displaying a text layout. The
+\fItkfont\fR must remain valid for the lifetime of the text layout. Must
+have been returned by a previous call to \fBTk_GetFont\fR.
+.AP "const char" *string in
+Potentially multi-line string whose dimensions are to be computed and
+stored in the text layout. The \fIstring\fR must remain valid for the
+lifetime of the text layout.
+.AP int numChars in
+The number of characters to consider from \fIstring\fR. If
+\fInumChars\fR is less than 0, then assumes \fIstring\fR is null
+terminated and uses \fBTcl_NumUtfChars\fR to determine the length of
+\fIstring\fR.
+.AP int wrapLength in
+Longest permissible line length, in pixels. Lines in \fIstring\fR will
+automatically be broken at word boundaries and wrapped when they reach
+this length. If \fIwrapLength\fR is too small for even a single
+character to fit on a line, it will be expanded to allow one character to
+fit on each line. If \fIwrapLength\fR is <= 0, there is no automatic
+wrapping; lines will get as long as they need to be and only wrap if a
+newline/return character is encountered.
+.AP Tk_Justify justify in
+How to justify the lines in a multi-line text layout. Possible values
+are \fBTK_JUSTIFY_LEFT\fR, \fBTK_JUSTIFY_CENTER\fR, or
+\fBTK_JUSTIFY_RIGHT\fR. If the text layout only occupies a single
+line, then \fIjustify\fR is irrelevant.
+.AP int flags in
+Various flag bits OR-ed together. \fBTK_IGNORE_TABS\fR means that tab
+characters should not be expanded to the next tab stop.
+\fBTK_IGNORE_NEWLINES\fR means that newline/return characters should
+not cause a line break. If either tabs or newlines/returns are
+ignored, then they will be treated as regular characters, being
+measured and displayed in a platform-dependent manner as described in
+\fBTk_MeasureChars\fR, and will not have any special behaviors.
+.AP int *widthPtr out
+If non-NULL, filled with either the width, in pixels, of the widest
+line in the text layout, or the width, in pixels, of the bounding box for the
+character specified by \fIindex\fR.
+.AP int *heightPtr out
+If non-NULL, filled with either the total height, in pixels, of all
+the lines in the text layout, or the height, in pixels, of the bounding
+box for the character specified by \fIindex\fR.
+.AP Tk_TextLayout layout in
+A token that represents the cached layout information about the single-font,
+multi-line, justified piece of text. This token is returned by
+\fBTk_ComputeTextLayout\fR.
+.AP Display *display in
+Display on which to draw.
+.AP Drawable drawable in
+Window or pixmap in which to draw.
+.AP GC gc in
+Graphics context to use for drawing text layout. The font selected in
+this GC must correspond to the \fItkfont\fR used when constructing the
+text layout.
+.AP int "x, y" in
+Point, in pixels, at which to place the upper-left hand corner of the
+text layout when it is being drawn, or the coordinates of a point (with
+respect to the upper-left hand corner of the text layout) to check
+against the text layout.
+.AP int firstChar in
+The index of the first character to draw from the given text layout.
+The number 0 means to draw from the beginning.
+.AP int lastChar in
+The index of the last character up to which to draw. The character
+specified by \fIlastChar\fR itself will not be drawn. A number less
+than 0 means to draw all characters in the text layout.
+.AP int underline in
+Index of the single character to underline in the text layout, or a number
+less than 0 for no underline.
+.AP int index in
+The index of the character whose bounding box is desired. The bounding
+box is computed with respect to the upper-left hand corner of the text layout.
+.AP int "*xPtr, *yPtr" out
+Filled with the upper-left hand corner, in pixels, of the bounding box
+for the character specified by \fIindex\fR. Either or both \fIxPtr\fR
+and \fIyPtr\fR may be NULL, in which case the corresponding value
+is not calculated.
+.AP int "width, height" in
+Specifies the width and height, in pixels, of the rectangular area to
+compare for intersection against the text layout.
+.AP Tcl_Interp *interp out
+Postscript code that will print the text layout is appended to
+the result of interpreter \fIinterp\fR.
+.BE
+.SH DESCRIPTION
+.PP
+These routines are for measuring and displaying single-font, multi-line,
+justified text. To measure and display simple single-font, single-line
+strings, refer to the documentation for \fBTk_MeasureChars\fR. There is
+no programming interface in the core of Tk that supports multi-font,
+multi-line text; support for that behavior must be built on top of
+simpler layers.
+Note that unlike the lower level text display routines, the functions
+described here all operate on character-oriented lengths and indices
+rather than byte-oriented values. See the description of
+\fBTcl_UtfAtIndex\fR for more details on converting between character
+and byte offsets.
+.PP
+The routines described here are built on top of the programming interface
+described in the \fBTk_MeasureChars\fR documentation. Tab characters and
+newline/return characters may be treated specially by these procedures,
+but all other characters are passed through to the lower level.
+.PP
+\fBTk_ComputeTextLayout\fR computes the layout information needed to
+display a single-font, multi-line, justified \fIstring\fR of text and
+returns a Tk_TextLayout token that holds this information. This token is
+used in subsequent calls to procedures such as \fBTk_DrawTextLayout\fR,
+\fBTk_DistanceToTextLayout\fR, and \fBTk_FreeTextLayout\fR. The
+\fIstring\fR and \fItkfont\fR used when computing the layout must remain
+valid for the lifetime of this token.
+.PP
+\fBTk_FreeTextLayout\fR is called to release the storage associated with
+\fIlayout\fR when it is no longer needed. A \fIlayout\fR should not be used
+in any other text layout procedures once it has been released.
+.PP
+\fBTk_DrawTextLayout\fR uses the information in \fIlayout\fR to display a
+single-font, multi-line, justified string of text at the specified location.
+.PP
+\fBTk_UnderlineTextLayout\fR uses the information in \fIlayout\fR to
+display an underline below an individual character. This procedure does
+not draw the text, just the underline. To produce natively underlined
+text, an underlined font should be constructed and used. All characters,
+including tabs, newline/return characters, and spaces at the ends of
+lines, can be underlined using this method. However, the underline will
+never be drawn outside of the computed width of \fIlayout\fR; the
+underline will stop at the edge for any character that would extend
+partially outside of \fIlayout\fR, and the underline will not be visible
+at all for any character that would be located completely outside of the
+layout.
+.PP
+\fBTk_PointToChar\fR uses the information in \fIlayout\fR to determine the
+character closest to the given point. The point is specified with respect
+to the upper-left hand corner of the \fIlayout\fR, which is considered to be
+located at (0, 0). Any point whose \fIy\fR-value is less that 0 will be
+considered closest to the first character in the text layout; any point
+whose \fIy\fR-value is greater than the height of the text layout will be
+considered closest to the last character in the text layout. Any point
+whose \fIx\fR-value is less than 0 will be considered closest to the first
+character on that line; any point whose \fIx\fR-value is greater than the
+width of the text layout will be considered closest to the last character on
+that line. The return value is the index of the character that was closest
+to the point, or one more than the index of any character (to indicate that
+the point was after the end of the string and that the corresponding caret
+would be at the end of the string). Given a \fIlayout\fR with no characters,
+the value 0 will always be returned, referring to a hypothetical zero-width
+placeholder character.
+.PP
+\fBTk_CharBbox\fR uses the information in \fIlayout\fR to return the
+bounding box for the character specified by \fIindex\fR. The width of the
+bounding box is the advance width of the character, and does not include any
+left or right bearing. Any character that extends partially outside of
+\fIlayout\fR is considered to be truncated at the edge. Any character
+that would be located completely outside of \fIlayout\fR is considered to
+be zero-width and pegged against the edge. The height of the bounding
+box is the line height for this font, extending from the top of the
+ascent to the bottom of the descent; information about the actual height
+of individual letters is not available. For measurement purposes, a
+\fIlayout\fR that contains no characters is considered to contain a
+single zero-width placeholder character at index 0. If \fIindex\fR was
+not a valid character index, the return value is 0 and \fI*xPtr\fR,
+\fI*yPtr\fR, \fI*widthPtr\fR, and \fI*heightPtr\fR are unmodified.
+Otherwise, if \fIindex\fR did specify a valid, the return value is
+non-zero, and \fI*xPtr\fR, \fI*yPtr\fR, \fI*widthPtr\fR, and
+\fI*heightPtr\fR are filled with the bounding box information for the
+character. If any of \fIxPtr\fR, \fIyPtr\fR, \fIwidthPtr\fR, or
+\fIheightPtr\fR are NULL, the corresponding value is not calculated or
+stored.
+.PP
+\fBTk_DistanceToTextLayout\fR computes the shortest distance in pixels from
+the given point (\fIx, y\fR) to the characters in \fIlayout\fR.
+Newline/return characters and non-displaying space characters that occur at
+the end of individual lines in the text layout are ignored for hit detection
+purposes, but tab characters are not. The return value is 0 if the point
+actually hits the \fIlayout\fR. If the point did not hit the \fIlayout\fR
+then the return value is the distance in pixels from the point to the
+\fIlayout\fR.
+.PP
+\fBTk_IntersectTextLayout\fR determines whether a \fIlayout\fR lies
+entirely inside, entirely outside, or overlaps a given rectangle.
+Newline/return characters and non-displaying space characters that occur
+at the end of individual lines in the \fIlayout\fR are ignored for
+intersection calculations. The return value is \-1 if the \fIlayout\fR is
+entirely outside of the rectangle, 0 if it overlaps, and 1 if it is
+entirely inside of the rectangle.
+.PP
+\fBTk_TextLayoutToPostscript\fR outputs code consisting of a Postscript
+array of strings that represent the individual lines in \fIlayout\fR. It
+is the responsibility of the caller to take the Postscript array of
+strings and add some Postscript function operate on the array to render
+each of the lines. The code that represents the Postscript array of
+strings is appended to interpreter \fIinterp\fR's result.
+.SH "DISPLAY MODEL"
+.PP
+When measuring a text layout, space characters that occur at the end of a
+line are ignored. The space characters still exist and the insertion point
+can be positioned amongst them, but their additional width is ignored when
+justifying lines or returning the total width of a text layout. All
+end-of-line space characters are considered to be attached to the right edge
+of the line; this behavior is logical for left-justified text and reasonable
+for center-justified text, but not very useful when editing right-justified
+text. Spaces are considered variable width characters; the first space that
+extends past the edge of the text layout is clipped to the edge, and any
+subsequent spaces on the line are considered zero width and pegged against
+the edge. Space characters that occur in the middle of a line of text are
+not suppressed and occupy their normal space width.
+.PP
+Tab characters are not ignored for measurement calculations. If wrapping
+is turned on and there are enough tabs on a line, the next tab will wrap
+to the beginning of the next line. There are some possible strange
+interactions between tabs and justification; tab positions are calculated
+and the line length computed in a left-justified world, and then the
+whole resulting line is shifted so it is centered or right-justified,
+causing the tab columns not to align any more.
+.PP
+When wrapping is turned on, lines may wrap at word breaks (space or tab
+characters) or newline/returns. A dash or hyphen character in the middle
+of a word is not considered a word break. \fBTk_ComputeTextLayout\fR
+always attempts to place at least one word on each line. If it cannot
+because the \fIwrapLength\fR is too small, the word will be broken and as
+much as fits placed on the line and the rest on subsequent line(s). If
+\fIwrapLength\fR is so small that not even one character can fit on a
+given line, the \fIwrapLength\fR is ignored for that line and one
+character will be placed on the line anyhow. When wrapping is turned
+off, only newline/return characters may cause a line break.
+.PP
+When a text layout has been created using an underlined \fItkfont\fR,
+then any space characters that occur at the end of individual lines,
+newlines/returns, and tabs will not be displayed underlined when
+\fBTk_DrawTextLayout\fR is called, because those characters are never
+actually drawn \- they are merely placeholders maintained in the
+\fIlayout\fR.
+.SH KEYWORDS
+font
diff --git a/tk8.6/doc/TkInitStubs.3 b/tk8.6/doc/TkInitStubs.3
new file mode 100644
index 0000000..04f5611
--- /dev/null
+++ b/tk8.6/doc/TkInitStubs.3
@@ -0,0 +1,79 @@
+'\"
+'\" Copyright (c) 1999 Scriptics Corporation
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH Tk_InitStubs 3 8.4 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_InitStubs \- initialize the Tk stubs mechanism
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+const char *
+\fBTk_InitStubs\fR(\fIinterp, version, exact\fR)
+.SH ARGUMENTS
+.AS Tcl_Interp *interp in
+.AP Tcl_Interp *interp in
+Tcl interpreter handle.
+.AP char *version in
+A version string consisting of one or more decimal numbers
+separated by dots.
+.AP int exact in
+Non-zero means that only the particular Tk version specified by
+\fIversion\fR is acceptable.
+Zero means that versions newer than \fIversion\fR are also
+acceptable as long as they have the same major version number
+as \fIversion\fR.
+.BE
+.SH INTRODUCTION
+.PP
+The Tcl stubs mechanism defines a way to dynamically bind
+extensions to a particular Tcl implementation at run time.
+the stubs mechanism requires no changes to applications
+incorporating Tcl/Tk interpreters. Only developers creating
+C-based Tcl/Tk extensions need to take steps to use the
+stubs mechanism with their extensions.
+See the \fBTcl_InitStubs\fR page for more information.
+.PP
+Enabling the stubs mechanism for a Tcl/Tk extension requires the following
+steps:
+.IP 1) 5
+Call \fBTcl_InitStubs\fR in the extension before calling any other
+Tcl functions.
+.IP 2) 5
+Call \fBTk_InitStubs\fR if the extension before calling any other
+Tk functions.
+.IP 2) 5
+Define the \fBUSE_TCL_STUBS\fR and the \fBUSE_TK_STUBS\fR
+symbols. Typically, you would include the \fB\-DUSE_TCL_STUBS\fR and
+the \fB\-DUSE_TK_STUBS\fR flags when compiling the extension.
+.IP 3) 5
+Link the extension with the Tcl and Tk stubs libraries instead of the
+standard Tcl and Tk libraries. On Unix platforms, the library names
+are \fIlibtclstub8.4.a\fR and \fIlibtkstub8.4.a\fR; on Windows
+platforms, the library names are \fItclstub84.lib\fR and
+\fItkstub84.lib\fR. Adjust the library names with appropriate version
+number but note that the extension may only be used with versions of
+Tcl/Tk that have that version number or higher.
+.SH DESCRIPTION
+.PP
+\fBTk_InitStubs\fR attempts to initialize the Tk stub table pointers
+and ensure that the correct version of Tk is loaded. In addition
+to an interpreter handle, it accepts as arguments a version number
+and a Boolean flag indicating whether the extension requires
+an exact version match or not. If \fIexact\fR is 0, then the
+extension is indicating that newer versions of Tk are acceptable
+as long as they have the same major version number as \fIversion\fR;
+non-zero means that only the specified \fIversion\fR is acceptable.
+\fBTcl_InitStubs\fR returns a string containing the actual version
+of Tk satisfying the request, or NULL if the Tk version is not
+acceptable, does not support the stubs mechanism, or any other
+error condition occurred.
+.SH "SEE ALSO"
+\fBTcl_InitStubs\fR
+.SH KEYWORDS
+stubs
diff --git a/tk8.6/doc/Tk_Init.3 b/tk8.6/doc/Tk_Init.3
new file mode 100644
index 0000000..7bc46dd
--- /dev/null
+++ b/tk8.6/doc/Tk_Init.3
@@ -0,0 +1,85 @@
+'\"
+'\" 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.
+'\"
+.TH Tk_Init 3 8.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_Init, Tk_SafeInit \- add Tk to an interpreter and make a new Tk application.
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+int
+\fBTk_Init\fR(\fIinterp\fR)
+.sp
+int
+\fBTk_SafeInit\fR(\fIinterp\fR)
+.SH ARGUMENTS
+.AP Tcl_Interp *interp in
+Interpreter in which to load Tk. Tk should not already be loaded
+in this interpreter.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_Init\fR is the package initialization procedure for Tk.
+It is normally invoked by the \fBTcl_AppInit\fR procedure
+for an application or by the \fBload\fR command.
+\fBTk_Init\fR adds all of Tk's commands to \fIinterp\fR
+and creates a new Tk application, including its main window.
+If the initialization is successful \fBTk_Init\fR returns
+\fBTCL_OK\fR; if there is an error it returns \fBTCL_ERROR\fR.
+\fBTk_Init\fR also leaves a result or error message
+in interpreter \fIinterp\fR's result.
+.PP
+If there is a variable \fBargv\fR in \fIinterp\fR, \fBTk_Init\fR
+treats the contents of this variable as a list of options for the
+new Tk application.
+The options may have any of the forms documented for the
+\fBwish\fR application (in fact, \fBwish\fR uses Tk_Init to process
+its command-line arguments).
+.PP
+\fBTk_SafeInit\fR is identical to \fBTk_Init\fR except that it removes
+all Tk commands that are considered unsafe. Those commands and the
+reasons for their exclusion are:
+.TP
+\fBbell\fR
+Continuous ringing of the bell is a nuisance.
+.TP
+\fBclipboard\fR
+A malicious script could replace the contents of the clipboard with
+the string
+.QW "\fBrm \-r *\fR"
+and lead to surprises when the contents of the clipboard are pasted.
+.TP
+\fBgrab\fR
+Grab can be used to block the user from using any other applications.
+.TP
+\fBmenu\fR
+Menus can be used to cover the entire screen and to steal input from
+the user.
+.TP
+\fBselection\fR
+See clipboard.
+.TP
+\fBsend\fR
+Send can be used to cause unsafe interpreters to execute commands.
+.TP
+\fBtk\fR
+The tk command recreates the send command, which is unsafe.
+.TP
+\fBtkwait\fR
+Tkwait can block the containing process forever
+.TP
+\fBtoplevel\fR
+Toplevels can be used to cover the entire screen and to steal input
+from the user.
+.TP
+\fBwm\fR
+If toplevels are ever allowed, wm can be used to remove decorations,
+move windows around, etc.
+.SH KEYWORDS
+safe, application, initialization, load, main window
diff --git a/tk8.6/doc/Tk_Main.3 b/tk8.6/doc/Tk_Main.3
new file mode 100644
index 0000000..ea5f771
--- /dev/null
+++ b/tk8.6/doc/Tk_Main.3
@@ -0,0 +1,70 @@
+'\"
+'\" Copyright (c) 1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_Main 3 4.0 Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_Main \- main program for Tk-based applications
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+\fBTk_Main\fR(\fIargc, argv, appInitProc\fR)
+.SH ARGUMENTS
+.AS Tcl_AppInitProc *appInitProc
+.AP int argc in
+Number of elements in \fIargv\fR.
+.AP char *argv[] in
+Array of strings containing command-line arguments. On Windows, when
+using -DUNICODE, the parameter type changes to wchar_t *.
+.AP Tcl_AppInitProc *appInitProc in
+Address of an application-specific initialization procedure.
+The value for this argument is usually \fBTcl_AppInit\fR.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_Main\fR acts as the main program for most Tk-based applications.
+Starting with Tk 4.0 it is not called \fBmain\fR anymore because it
+is part of the Tk library and having a function \fBmain\fR
+in a library (particularly a shared library) causes problems on many
+systems.
+Having \fBmain\fR in the Tk library would also make it hard to use
+Tk in C++ programs, since C++ programs must have special C++
+\fBmain\fR functions.
+.PP
+Normally each application contains a small \fBmain\fR function that does
+nothing but invoke \fBTk_Main\fR.
+\fBTk_Main\fR then does all the work of creating and running a
+\fBwish\fR-like application.
+.PP
+When it is has finished its own initialization, but before
+it processes commands, \fBTk_Main\fR calls the procedure given by
+the \fIappInitProc\fR argument. This procedure provides a
+.QW hook
+for the application to perform its own initialization, such as defining
+application-specific commands. The procedure must have an interface
+that matches the type \fBTcl_AppInitProc\fR:
+.CS
+typedef int \fBTcl_AppInitProc\fR(
+ Tcl_Interp *\fIinterp\fR);
+.CE
+\fIAppInitProc\fR is almost always a pointer to \fBTcl_AppInit\fR;
+for more details on this procedure, see the documentation
+for \fBTcl_AppInit\fR.
+.PP
+\fBTk_Main\fR functions much the same as \fBTcl_Main\fR. In particular,
+\fBTk_Main\fR supports both an interactive mode and a startup script
+mode, with the file name and encoding of a startup script under the
+control of the \fBTcl_SetStartupScript\fR and \fBTcl_GetStartupScript\fR
+routines. However it calls \fBTk_MainLoop\fR after processing any
+supplied script, and in interactive uses events registered with
+\fBTcl_CreateFileHandler\fR to process user input.
+.SH "SEE ALSO"
+Tcl_DoOneEvent(3)
+.SH KEYWORDS
+application-specific initialization, command-line arguments, main program
diff --git a/tk8.6/doc/WindowId.3 b/tk8.6/doc/WindowId.3
new file mode 100644
index 0000000..f937963
--- /dev/null
+++ b/tk8.6/doc/WindowId.3
@@ -0,0 +1,188 @@
+'\"
+'\" Copyright (c) 1990-1993 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH Tk_WindowId 3 "8.4" Tk "Tk Library Procedures"
+.so man.macros
+.BS
+.SH NAME
+Tk_WindowId, Tk_Parent, Tk_Display, Tk_DisplayName, Tk_ScreenNumber, Tk_Screen, Tk_X, Tk_Y, Tk_Width, Tk_Height, Tk_Changes, Tk_Attributes, Tk_IsContainer, Tk_IsEmbedded, Tk_IsMapped, Tk_IsTopLevel, Tk_ReqWidth, Tk_ReqHeight, Tk_MinReqWidth, Tk_MinReqHeight, Tk_InternalBorderLeft, Tk_InternalBorderRight, Tk_InternalBorderTop, Tk_InternalBorderBottom, Tk_Visual, Tk_Depth, Tk_Colormap, Tk_Interp \- retrieve information from Tk's local data structure
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+Window
+\fBTk_WindowId\fR(\fItkwin\fR)
+.sp
+Tk_Window
+\fBTk_Parent\fR(\fItkwin\fR)
+.sp
+Display *
+\fBTk_Display\fR(\fItkwin\fR)
+.sp
+const char *
+\fBTk_DisplayName\fR(\fItkwin\fR)
+.sp
+int
+\fBTk_ScreenNumber\fR(\fItkwin\fR)
+.sp
+Screen *
+\fBTk_Screen\fR(\fItkwin\fR)
+.sp
+int
+\fBTk_X\fR(\fItkwin\fR)
+.sp
+int
+\fBTk_Y\fR(\fItkwin\fR)
+.sp
+int
+\fBTk_Width\fR(\fItkwin\fR)
+.sp
+int
+\fBTk_Height\fR(\fItkwin\fR)
+.sp
+XWindowChanges *
+\fBTk_Changes\fR(\fItkwin\fR)
+.sp
+XSetWindowAttributes *
+\fBTk_Attributes\fR(\fItkwin\fR)
+.sp
+int
+\fBTk_IsContainer\fR(\fItkwin\fR)
+.sp
+int
+\fBTk_IsEmbedded\fR(\fItkwin\fR)
+.sp
+int
+\fBTk_IsMapped\fR(\fItkwin\fR)
+.sp
+int
+\fBTk_IsTopLevel\fR(\fItkwin\fR)
+.sp
+int
+\fBTk_ReqWidth\fR(\fItkwin\fR)
+.sp
+int
+\fBTk_ReqHeight\fR(\fItkwin\fR)
+.sp
+int
+\fBTk_MinReqWidth\fR(\fItkwin\fR)
+.sp
+int
+\fBTk_MinReqHeight\fR(\fItkwin\fR)
+.sp
+int
+\fBTk_InternalBorderLeft\fR(\fItkwin\fR)
+.sp
+int
+\fBTk_InternalBorderRight\fR(\fItkwin\fR)
+.sp
+int
+\fBTk_InternalBorderTop\fR(\fItkwin\fR)
+.sp
+int
+\fBTk_InternalBorderBottom\fR(\fItkwin\fR)
+.sp
+Visual *
+\fBTk_Visual\fR(\fItkwin\fR)
+.sp
+int
+\fBTk_Depth\fR(\fItkwin\fR)
+.sp
+Colormap
+\fBTk_Colormap\fR(\fItkwin\fR)
+.sp
+Tcl_Interp *
+\fBTk_Interp\fR(\fItkwin\fR)
+.SH ARGUMENTS
+.AS Tk_Window tkwin
+.AP Tk_Window tkwin in
+Token for window.
+.BE
+.SH DESCRIPTION
+.PP
+\fBTk_WindowId\fR and the other names listed above are
+all macros that return fields from Tk's local data structure
+for \fItkwin\fR. None of these macros requires any
+interaction with the server; it is safe to assume that
+all are fast.
+.PP
+\fBTk_WindowId\fR returns the X identifier for \fItkwin\fR,
+or \fBNULL\fR if no X window has been created for \fItkwin\fR
+yet.
+.PP
+\fBTk_Parent\fR returns Tk's token for the logical parent of
+\fItkwin\fR. The parent is the token that was specified when
+\fItkwin\fR was created, or NULL for main windows.
+.PP
+\fBTk_Interp\fR returns the Tcl interpreter associated with a
+\fItkwin\fR or NULL if there is an error.
+.PP
+\fBTk_Display\fR returns a pointer to the Xlib display structure
+corresponding to \fItkwin\fR. \fBTk_DisplayName\fR returns an
+ASCII string identifying \fItkwin\fR's display. \fBTk_ScreenNumber\fR
+returns the index of \fItkwin\fR's screen among all the screens
+of \fItkwin\fR's display. \fBTk_Screen\fR returns a pointer to
+the Xlib structure corresponding to \fItkwin\fR's screen.
+.PP
+\fBTk_X\fR, \fBTk_Y\fR, \fBTk_Width\fR, and \fBTk_Height\fR
+return information about \fItkwin's\fR location within its
+parent and its size. The location information refers to the
+upper-left pixel in the window, or its border if there is one.
+The width and height information refers to the interior size
+of the window, not including any border. \fBTk_Changes\fR
+returns a pointer to a structure containing all of the above
+information plus a few other fields. \fBTk_Attributes\fR
+returns a pointer to an XSetWindowAttributes structure describing
+all of the attributes of the \fItkwin\fR's window, such as background
+pixmap, event mask, and so on (Tk keeps track of all this information
+as it is changed by the application). Note: it is essential that
+applications use Tk procedures like \fBTk_ResizeWindow\fR instead
+of X procedures like \fBXResizeWindow\fR, so that Tk can keep its
+data structures up-to-date.
+.PP
+\fBTk_IsContainer\fR returns a non-zero value if \fItkwin\fR
+is a container, and that some other application may be embedding
+itself inside \fItkwin\fR.
+.PP
+\fBTk_IsEmbedded\fR returns a non-zero value if \fItkwin\fR
+is not a free-standing window, but rather is embedded in some
+other application.
+.PP
+\fBTk_IsMapped\fR returns a non-zero value if \fItkwin\fR
+is mapped and zero if \fItkwin\fR is not mapped.
+.PP
+\fBTk_IsTopLevel\fR returns a non-zero value if \fItkwin\fR
+is a top-level window (its X parent is the root window of the
+screen) and zero if \fItkwin\fR is not a top-level window.
+.PP
+\fBTk_ReqWidth\fR and \fBTk_ReqHeight\fR return information about
+the window's requested size. These values correspond to the last
+call to \fBTk_GeometryRequest\fR for \fItkwin\fR.
+.PP
+\fBTk_MinReqWidth\fR and \fBTk_MinReqHeight\fR return information about
+the window's minimum requested size. These values correspond to the last
+call to \fBTk_SetMinimumRequestSize\fR for \fItkwin\fR.
+.PP
+\fBTk_InternalBorderLeft\fR, \fBTk_InternalBorderRight\fR,
+\fBTk_InternalBorderTop\fR and \fBTk_InternalBorderBottom\fR
+return the width of one side of the internal border
+that has been requested for \fItkwin\fR, or 0 if no internal border was
+requested. The return value is simply the last value passed to
+\fBTk_SetInternalBorder\fR or \fBTk_SetInternalBorderEx\fR for \fItkwin\fR.
+.PP
+\fBTk_Visual\fR, \fBTk_Depth\fR, and \fBTk_Colormap\fR return
+information about the visual characteristics of a window.
+\fBTk_Visual\fR returns the visual type for
+the window, \fBTk_Depth\fR returns the number of bits per pixel,
+and \fBTk_Colormap\fR returns the current
+colormap for the window. The visual characteristics are
+normally set from the defaults for the window's screen, but
+they may be overridden by calling \fBTk_SetWindowVisual\fR.
+.SH KEYWORDS
+attributes, colormap, depth, display, height, geometry manager,
+identifier, mapped, requested size, screen, top-level,
+visual, width, window, x, y
diff --git a/tk8.6/doc/bell.n b/tk8.6/doc/bell.n
new file mode 100644
index 0000000..21c4f1b
--- /dev/null
+++ b/tk8.6/doc/bell.n
@@ -0,0 +1,34 @@
+'\"
+'\" Copyright (c) 1994 The Regents of the University of California.
+'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
+'\" Copyright (c) 2000 Ajuba Solutions.
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH bell n 8.4 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+bell \- Ring a display's bell
+.SH SYNOPSIS
+\fBbell \fR?\fB\-displayof \fIwindow\fR? ?\fB\-nice\fR?
+.BE
+.SH DESCRIPTION
+.PP
+This command rings the bell on the display for \fIwindow\fR and
+returns an empty string.
+If the \fB\-displayof\fR option is omitted, the display of the
+application's main window is used by default.
+The command uses the current bell-related settings for the display, which
+may be modified with programs such as \fBxset\fR.
+.PP
+If \fB\-nice\fR is not specified, this command also resets the screen saver
+for the screen. Some screen savers will ignore this, but others will reset
+so that the screen becomes visible again.
+.SH KEYWORDS
+beep, bell, ring
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/bind.n b/tk8.6/doc/bind.n
new file mode 100644
index 0000000..0f7e26b
--- /dev/null
+++ b/tk8.6/doc/bind.n
@@ -0,0 +1,730 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
+'\" Copyright (c) 1998 by Scriptics Corporation.
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH bind n 8.0 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+bind \- Arrange for X events to invoke Tcl scripts
+.SH SYNOPSIS
+\fBbind\fI tag\fR ?\fIsequence\fR? ?\fB+\fR??\fIscript\fR?
+.BE
+.SH "INTRODUCTION"
+.PP
+The \fBbind\fR command associates Tcl scripts with X events.
+If all three arguments are specified, \fBbind\fR will
+arrange for \fIscript\fR (a Tcl script called the
+.QW "binding script")
+to be evaluated whenever the event(s) given by \fIsequence\fR
+occur in the window(s) identified by \fItag\fR.
+If \fIscript\fR is prefixed with a
+.QW + ,
+then it is appended to
+any existing binding for \fIsequence\fR; otherwise \fIscript\fR replaces
+any existing binding.
+If \fIscript\fR is an empty string then the current binding for
+\fIsequence\fR is destroyed, leaving \fIsequence\fR unbound.
+In all of the cases where a \fIscript\fR argument is provided,
+\fBbind\fR returns an empty string.
+.PP
+If \fIsequence\fR is specified without a \fIscript\fR, then the
+script currently bound to \fIsequence\fR is returned, or
+an empty string is returned if there is no binding for \fIsequence\fR.
+If neither \fIsequence\fR nor \fIscript\fR is specified, then the
+return value is a list whose elements are all the sequences
+for which there exist bindings for \fItag\fR.
+.PP
+The \fItag\fR argument determines which window(s) the binding applies to.
+If \fItag\fR begins with a dot, as in \fB.a.b.c\fR, then it must
+be the path name for a window; otherwise it may be an arbitrary
+string.
+Each window has an associated list of tags, and a binding applies
+to a particular window if its tag is among those specified for
+the window.
+Although the \fBbindtags\fR command may be used to assign an
+arbitrary set of binding tags to a window, the default binding
+tags provide the following behavior:
+.IP \(bu 3
+If a tag is the name of an internal window the binding applies
+to that window.
+.IP \(bu 3
+If the tag is the name of a toplevel window the binding applies
+to the toplevel window and all its internal windows.
+.IP \(bu 3
+If the tag is the name of a class of widgets, such as \fBButton\fR,
+the binding applies to all widgets in that class;
+.IP \(bu 3
+If \fItag\fR has the value \fBall\fR,
+the binding applies to all windows in the application.
+.SH "EVENT PATTERNS"
+.PP
+The \fIsequence\fR argument specifies a sequence of one or more
+event patterns, with optional white space between the patterns. Each
+event pattern may
+take one of three forms. In the simplest case it is a single
+printing ASCII character, such as \fBa\fR or \fB[\fR. The character
+may not be a space character or the character \fB<\fR. This form of
+pattern matches a \fBKeyPress\fR event for the particular
+character. The second form of pattern is longer but more general.
+It has the following syntax:
+.CS
+\fB<\fImodifier\-modifier\-type\-detail\fB>\fR
+.CE
+The entire event pattern is surrounded by angle brackets.
+Inside the angle brackets are zero or more modifiers, an event
+type, and an extra piece of information (\fIdetail\fR) identifying
+a particular button or keysym. Any of the fields may be omitted,
+as long as at least one of \fItype\fR and \fIdetail\fR is present.
+The fields must be separated by white space or dashes.
+.PP
+The third form of pattern is used to specify a user-defined, named virtual
+event. It has the following syntax:
+.CS
+\fB<<\fIname\fB>>\fR
+.CE
+The entire virtual event pattern is surrounded by double angle brackets.
+Inside the angle brackets is the user-defined name of the virtual event.
+Modifiers, such as \fBShift\fR or \fBControl\fR, may not be combined with a
+virtual event to modify it. Bindings on a virtual event may be created
+before the virtual event is defined, and if the definition of a virtual
+event changes dynamically, all windows bound to that virtual event will
+respond immediately to the new definition.
+.PP
+Some widgets (e.g. \fBmenu\fR and \fBtext\fR) issue virtual events
+when their internal state is updated in some ways. Please see the
+manual page for each widget for details.
+.SS "MODIFIERS"
+.PP
+Modifiers consist of any of the following values:
+.DS
+.ta 6c
+\fBControl\fR \fBMod1\fR, \fBM1\fR, \fBCommand\fR
+\fBAlt\fR \fBMod2\fR, \fBM2\fR, \fBOption\fR
+\fBShift\fR \fBMod3\fR, \fBM3\fR
+\fBLock\fR \fBMod4\fR, \fBM4\fR
+\fBExtended\fR \fBMod5\fR, \fBM5\fR
+\fBButton1\fR, \fBB1\fR \fBMeta\fR, \fBM\fR
+\fBButton2\fR, \fBB2\fR \fBDouble\fR
+\fBButton3\fR, \fBB3\fR \fBTriple\fR
+\fBButton4\fR, \fBB4\fR \fBQuadruple\fR
+\fBButton5\fR, \fBB5\fR
+.DE
+Where more than one value is listed, separated by commas, the values
+are equivalent.
+Most of the modifiers have the obvious X meanings.
+For example, \fBButton1\fR requires that
+button 1 be depressed when the event occurs.
+For a binding to match a given event, the modifiers in the event
+must include all of those specified in the event pattern.
+An event may also contain additional modifiers not specified in
+the binding.
+For example, if button 1 is pressed while the shift and control keys
+are down, the pattern \fB<Control\-Button\-1>\fR will match
+the event, but \fB<Mod1\-Button\-1>\fR will not.
+If no modifiers are specified, then any combination of modifiers may
+be present in the event.
+.PP
+\fBMeta\fR and \fBM\fR refer to whichever of the
+\fBM1\fR through \fBM5\fR modifiers is associated with the Meta
+key(s) on the keyboard (keysyms \fBMeta_R\fR and \fBMeta_L\fR).
+If there are no Meta keys, or if they are not associated with any
+modifiers, then \fBMeta\fR and \fBM\fR will not match any events.
+Similarly, the \fBAlt\fR modifier refers to whichever modifier
+is associated with the alt key(s) on the keyboard (keysyms
+\fBAlt_L\fR and \fBAlt_R\fR).
+.PP
+The \fBDouble\fR, \fBTriple\fR and \fBQuadruple\fR modifiers are a
+convenience for specifying double mouse clicks and other repeated
+events. They cause a particular event pattern to be repeated 2, 3 or 4
+times, and also place a time and space requirement on the sequence: for a
+sequence of events to match a \fBDouble\fR, \fBTriple\fR or \fBQuadruple\fR
+pattern, all of the events must occur close together in time and without
+substantial mouse motion in between. For example, \fB<Double\-Button\-1>\fR
+is equivalent to \fB<Button\-1><Button\-1>\fR with the extra time and space
+requirement.
+.PP
+The \fBCommand\fR and \fBOption\fR modifiers are equivalents of \fBMod1\fR
+resp. \fBMod2\fR, they correspond to Macintosh-specific modifier keys.
+.PP
+The \fBExtended\fR modifier is, at present, specific to Windows. It
+appears on events that are associated with the keys on the
+.QW "extended keyboard" .
+On a US keyboard, the extended keys include the \fBAlt\fR
+and \fBControl\fR keys at the right of the keyboard, the cursor keys
+in the cluster to the left of the numeric pad, the \fBNumLock\fR key,
+the \fBBreak\fR key, the \fBPrintScreen\fR key, and the \fB/\fR and
+\fBEnter\fR keys in the numeric keypad.
+.SS "EVENT TYPES"
+.PP
+The \fItype\fR field may be any of the standard X event types, with a
+few extra abbreviations. The \fItype\fR field will also accept a
+couple non-standard X event types that were added to better support
+the Macintosh and Windows platforms. Below is a list of all the valid
+types; where two names appear together, they are synonyms.
+.DS
+.ta \w'\fBButtonPress, Button\0\0\0\fR'u +\w'\fBKeyPress, Key\0\0\0\fR'u
+\fBActivate\fR \fBDestroy\fR \fBMap\fR
+\fBButtonPress\fR, \fBButton\fR \fBEnter\fR \fBMapRequest\fR
+\fBButtonRelease\fR \fBExpose\fR \fBMotion\fR
+\fBCirculate\fR \fBFocusIn\fR \fBMouseWheel\fR
+\fBCirculateRequest\fR \fBFocusOut\fR \fBProperty\fR
+\fBColormap\fR \fBGravity\fR \fBReparent\fR
+\fBConfigure\fR \fBKeyPress\fR, \fBKey\fR \fBResizeRequest\fR
+\fBConfigureRequest\fR \fBKeyRelease\fR \fBUnmap\fR
+\fBCreate\fR \fBLeave\fR \fBVisibility\fR
+\fBDeactivate\fR
+.DE
+Most of the above events have the same fields and behaviors as events
+in the X Windowing system. You can find more detailed descriptions of
+these events in any X window programming book. A couple of the events
+are extensions to the X event system to support features unique to the
+Macintosh and Windows platforms. We provide a little more detail on
+these events here. These include:
+.IP "\fBActivate\fR, \fBDeactivate\fR" 5
+These two events are sent to every sub-window of a toplevel when they
+change state. In addition to the focus Window, the Macintosh platform
+and Windows platforms have a notion of an active window (which often
+has but is not required to have the focus). On the Macintosh, widgets
+in the active window have a different appearance than widgets in
+deactive windows. The \fBActivate\fR event is sent to all the
+sub-windows in a toplevel when it changes from being deactive to
+active. Likewise, the \fBDeactive\fR event is sent when the window's
+state changes from active to deactive. There are no useful percent
+substitutions you would make when binding to these events.
+.IP \fBMouseWheel\fR 5
+Many contemporary mice support a mouse wheel, which is used
+for scrolling documents without using the scrollbars. By rolling the
+wheel, the system will generate \fBMouseWheel\fR events that the
+application can use to scroll. Like \fBKey\fR events the event is
+always routed to the window that currently has focus. When the event
+is received you can use the \fB%D\fR substitution to get the
+\fIdelta\fR field for the event, which is a integer value describing how
+the mouse wheel has moved. The smallest value for which the
+system will report is defined by the OS. The sign of the
+value determines which direction your widget should scroll. Positive
+values should scroll up and negative values should scroll down.
+.IP "\fBKeyPress\fR, \fBKeyRelease\fR" 5
+The \fBKeyPress\fR and \fBKeyRelease\fR events are generated
+whenever a key is pressed or released. \fBKeyPress\fR and \fBKeyRelease\fR
+events are sent to the window which currently has the keyboard focus.
+.IP "\fBButtonPress\fR, \fBButtonRelease\fR, \fBMotion\fR" 5
+The \fBButtonPress\fR and \fBButtonRelease\fR events
+are generated when the user presses or releases a mouse button.
+\fBMotion\fR events are generated whenever the pointer is moved.
+\fBButtonPress\fR, \fBButtonRelease\fR, and \fBMotion\fR events are
+normally sent to the window containing the pointer.
+.RS
+.PP
+When a mouse button is pressed, the window containing the pointer
+automatically obtains a temporary pointer grab.
+Subsequent \fBButtonPress\fR, \fBButtonRelease\fR, and \fBMotion\fR
+events will be sent to that window,
+regardless of which window contains the pointer,
+until all buttons have been released.
+.RE
+.IP \fBConfigure\fR 5
+A \fBConfigure\fR event is sent to a window whenever its
+size, position, or border width changes, and sometimes
+when it has changed position in the stacking order.
+.IP "\fBMap\fR, \fBUnmap\fR" 5
+The \fBMap\fR and \fBUnmap\fR events are generated whenever the mapping
+state of a window changes.
+.RS
+.PP
+Windows are created in the unmapped state.
+Top-level windows become mapped when they transition to the
+\fBnormal\fR state, and are unmapped in the \fBwithdrawn\fR
+and \fBiconic\fR states.
+Other windows become mapped when they are placed under control
+of a geometry manager (for example \fBpack\fR or \fBgrid\fR).
+.PP
+A window is \fIviewable\fR only if it and all of its ancestors are mapped.
+Note that geometry managers typically do not map their children until
+they have been mapped themselves, and unmap all children
+when they become unmapped; hence in Tk \fBMap\fR and \fBUnmap\fR
+events indicate whether or not a window is viewable.
+.RE
+.IP \fBVisibility\fR 5
+A window is said to be \fIobscured\fR when another window
+above it in the stacking order fully or partially overlaps it.
+\fBVisibility\fR events are generated whenever a window's
+obscurity state changes; the \fIstate\fR field (\fB%s\fR)
+specifies the new state.
+.IP \fBExpose\fR 5
+An \fBExpose\fR event is generated whenever all or part of a
+window should be redrawn (for example, when a window is
+first mapped or if it becomes unobscured).
+It is normally not necessary for client applications to
+handle \fBExpose\fR events, since Tk handles them internally.
+.IP \fBDestroy\fR 5
+A \fBDestroy\fR event is delivered to a window when
+it is destroyed.
+.RS
+.PP
+When the \fBDestroy\fR event is delivered
+to a widget, it is in a
+.QW half-dead
+state: the widget still exists, but most operations on it will fail.
+.RE
+.IP "\fBFocusIn\fR, \fBFocusOut\fR" 5
+The \fBFocusIn\fR and \fBFocusOut\fR events are generated
+whenever the keyboard focus changes.
+A \fBFocusOut\fR event is sent to the old focus window,
+and a \fBFocusIn\fR event is sent to the new one.
+.RS
+.PP
+In addition,
+if the old and new focus windows do not share a common parent,
+.QW "virtual crossing"
+focus events are sent to the intermediate windows in the hierarchy.
+Thus a \fBFocusIn\fR event indicates
+that the target window or one of its descendants has acquired the focus,
+and a \fBFocusOut\fR event indicates that the focus
+has been changed to a window outside the target window's hierarchy.
+.PP
+The keyboard focus may be changed explicitly by a call to \fBfocus\fR,
+or implicitly by the window manager.
+.RE
+.IP "\fBEnter\fR, \fBLeave\fR" 5
+An \fBEnter\fR event is sent to a window when the pointer
+enters that window, and a \fBLeave\fR event is sent when
+the pointer leaves it.
+.RS
+.PP
+If there is a pointer grab in effect, \fBEnter\fR and \fBLeave\fR
+events are only delivered to the window owning the grab.
+.PP
+In addition, when the pointer moves
+between two windows, \fBEnter\fR and \fBLeave\fR
+.QW "virtual crossing"
+events are sent to intermediate windows
+in the hierarchy in the same manner as for \fBFocusIn\fR and
+\fBFocusOut\fR events.
+.RE
+.IP \fBProperty\fR
+A \fBProperty\fR event is sent to a window whenever an X property
+belonging to that window is changed or deleted.
+\fBProperty\fR events are not normally delivered to Tk applications as
+they are handled by the Tk core.
+.IP \fBColormap\fR
+A \fBColormap\fR event is generated whenever the colormap
+associated with a window has been changed, installed, or uninstalled.
+.RS
+.PP
+Widgets may be assigned a private colormap by
+specifying a \fB\-colormap\fR option; the window manager
+is responsible for installing and uninstalling colormaps
+as necessary.
+.PP
+Note that Tk provides no useful details for this event type.
+.RE
+'\" The following events were added in TIP#47
+.IP "\fBMapRequest\fR, \fBCirculateRequest\fR, \fBResizeRequest\fR, \fBConfigureRequest\fR, \fBCreate\fR" 5
+These events are not normally delivered to Tk applications.
+They are included for completeness, to make it possible to
+write X11 window managers in Tk.
+(These events are only delivered when a client has
+selected \fBSubstructureRedirectMask\fR on a window;
+the Tk core does not use this mask.)
+.IP "\fBGravity\fR, \fBReparent\fR, \fBCirculate\fR" 5
+The events \fBGravity\fR and \fBReparent\fR
+are not normally delivered to Tk applications.
+They are included for completeness.
+.RS
+.PP
+A \fBCirculate\fR event indicates that the window has moved
+to the top or to the bottom of the stacking order as
+a result of an \fBXCirculateSubwindows\fR protocol request.
+Note that the stacking order may be changed for other reasons
+which do not generate a \fBCirculate\fR event, and that
+Tk does not use \fBXCirculateSubwindows()\fR internally.
+This event type is included only for completeness;
+there is no reliable way to track changes to a window's
+position in the stacking order.
+.RE
+.SS "EVENT DETAILS"
+.PP
+The last part of a long event specification is \fIdetail\fR. In the
+case of a \fBButtonPress\fR or \fBButtonRelease\fR event, it is the
+number of a button (1\-5). If a button number is given, then only an
+event on that particular button will match; if no button number is
+given, then an event on any button will match. Note: giving a
+specific button number is different than specifying a button modifier;
+in the first case, it refers to a button being pressed or released,
+while in the second it refers to some other button that is already
+depressed when the matching event occurs. If a button
+number is given then \fItype\fR may be omitted: if will default
+to \fBButtonPress\fR. For example, the specifier \fB<1>\fR
+is equivalent to \fB<ButtonPress\-1>\fR.
+.PP
+If the event type is \fBKeyPress\fR or \fBKeyRelease\fR, then
+\fIdetail\fR may be specified in the form of an X keysym. Keysyms
+are textual specifications for particular keys on the keyboard;
+they include all the alphanumeric ASCII characters (e.g.
+.QW a
+is the keysym for the ASCII character
+.QW a ),
+plus descriptions for non-alphanumeric characters
+.PQ comma "is the keysym for the comma character" ,
+plus descriptions for all the non-ASCII keys on the keyboard (e.g.
+.QW Shift_L
+is the keysym for the left shift key, and
+.QW F1
+is the keysym for the F1 function key, if it exists). The
+complete list of keysyms is not presented here; it is
+available in other X documentation and may vary from system to
+system.
+If necessary, you can use the \fB%K\fR notation described below
+to print out the keysym name for a particular key.
+If a keysym \fIdetail\fR is given, then the
+\fItype\fR field may be omitted; it will default to \fBKeyPress\fR.
+For example, \fB<Control\-comma>\fR is equivalent to
+\fB<Control\-KeyPress\-comma>\fR.
+.SH "BINDING SCRIPTS AND SUBSTITUTIONS"
+.PP
+The \fIscript\fR argument to \fBbind\fR is a Tcl script, called the
+.QW "binding script",
+which will be executed whenever the given event sequence occurs.
+\fICommand\fR will be executed in the same interpreter that the
+\fBbind\fR command was executed in, and it will run at global
+level (only global variables will be accessible).
+If \fIscript\fR contains
+any \fB%\fR characters, then the script will not be
+executed directly. Instead, a new script will be
+generated by replacing each \fB%\fR, and the character following
+it, with information from the current event. The replacement
+depends on the character following the \fB%\fR, as defined in the
+list below. Unless otherwise indicated, the
+replacement string is the decimal value of the given field from
+the current event.
+Some of the substitutions are only valid for
+certain types of events; if they are used for other types of events
+the value substituted is undefined.
+.IP \fB%%\fR 5
+Replaced with a single percent.
+.IP \fB%#\fR 5
+The number of the last client request processed by the server
+(the \fIserial\fR field from the event). Valid for all event
+types.
+.IP \fB%a\fR 5
+The \fIabove\fR field from the event,
+formatted as a hexadecimal number.
+Valid only for \fBConfigure\fR events.
+Indicates the sibling window immediately below the receiving window
+in the stacking order, or \fB0\fR if the receiving window is at the
+bottom.
+.IP \fB%b\fR 5
+The number of the button that was pressed or released. Valid only
+for \fBButtonPress\fR and \fBButtonRelease\fR events.
+.IP \fB%c\fR 5
+The \fIcount\fR field from the event. Valid only for \fBExpose\fR events.
+Indicates that there are \fIcount\fR pending \fBExpose\fR events which have not
+yet been delivered to the window.
+.IP \fB%d\fR 5
+The \fIdetail\fR or \fIuser_data\fR
+field from the event. The \fB%d\fR is replaced by
+a string identifying the detail. For \fBEnter\fR,
+\fBLeave\fR, \fBFocusIn\fR, and \fBFocusOut\fR events,
+the string will be one of the following:
+.RS
+.DS
+.ta 6c
+\fBNotifyAncestor\fR \fBNotifyNonlinearVirtual\fR
+\fBNotifyDetailNone\fR \fBNotifyPointer\fR
+\fBNotifyInferior\fR \fBNotifyPointerRoot\fR
+\fBNotifyNonlinear\fR \fBNotifyVirtual\fR
+.DE
+For \fBConfigureRequest\fR events, the string will be one of:
+.DS
+.ta 6c
+\fBAbove\fR \fBOpposite\fR
+\fBBelow\fR \fBNone\fR
+\fBBottomIf\fR \fBTopIf\fR
+.DE
+For virtual events, the string will be whatever value is stored in the
+\fIuser_data\fR field when the event was created (typically with
+\fBevent generate\fR), or the empty string if the field is NULL.
+Virtual events corresponding to key sequence presses (see \fBevent
+add\fR for details) set the \fIuser_data\fR to NULL.
+For events other than these, the substituted string is undefined.
+.RE
+.IP \fB%f\fR 5
+The \fIfocus\fR field from the event (\fB0\fR or \fB1\fR). Valid only
+for \fBEnter\fR and \fBLeave\fR events. \fB1\fR if the receiving
+window is the focus window or a descendant of the focus window,
+\fB0\fR otherwise.
+.IP \fB%h\fR 5
+The \fIheight\fR field from the event. Valid for the \fBConfigure\fR,
+\fBConfigureRequest\fR, \fBCreate\fR, \fBResizeRequest\fR, and
+\fBExpose\fR events.
+Indicates the new or requested height of the window.
+.IP \fB%i\fR 5
+The \fIwindow\fR field from the event, represented as a hexadecimal
+integer. Valid for all event types.
+.IP \fB%k\fR 5
+The \fIkeycode\fR field from the event. Valid only for \fBKeyPress\fR
+and \fBKeyRelease\fR events.
+.IP \fB%m\fR 5
+The \fImode\fR field from the event. The substituted string is one of
+\fBNotifyNormal\fR, \fBNotifyGrab\fR, \fBNotifyUngrab\fR, or
+\fBNotifyWhileGrabbed\fR. Valid only for \fBEnter\fR,
+\fBFocusIn\fR, \fBFocusOut\fR, and \fBLeave\fR events.
+.IP \fB%o\fR 5
+The \fIoverride_redirect\fR field from the event. Valid only for
+\fBMap\fR, \fBReparent\fR, and \fBConfigure\fR events.
+.IP \fB%p\fR 5
+The \fIplace\fR field from the event, substituted as one of the
+strings \fBPlaceOnTop\fR or \fBPlaceOnBottom\fR. Valid only
+for \fBCirculate\fR and \fBCirculateRequest\fR events.
+.IP \fB%s\fR 5
+The \fIstate\fR field from the event. For \fBButtonPress\fR,
+\fBButtonRelease\fR, \fBEnter\fR, \fBKeyPress\fR, \fBKeyRelease\fR,
+\fBLeave\fR, and \fBMotion\fR events, a decimal string
+is substituted. For \fBVisibility\fR, one of the strings
+\fBVisibilityUnobscured\fR, \fBVisibilityPartiallyObscured\fR,
+and \fBVisibilityFullyObscured\fR is substituted.
+For \fBProperty\fR events, substituted with
+either the string \fBNewValue\fR (indicating that the property
+has been created or modified) or \fBDelete\fR (indicating that
+the property has been removed).
+.IP \fB%t\fR 5
+The \fItime\fR field from the event.
+This is the X server timestamp (typically the time since
+the last server reset) in milliseconds, when the event occurred.
+Valid for most events.
+.IP \fB%w\fR 5
+The \fIwidth\fR field from the event.
+Indicates the new or requested width of the window.
+Valid only for
+\fBConfigure\fR, \fBConfigureRequest\fR, \fBCreate\fR,
+\fBResizeRequest\fR, and \fBExpose\fR events.
+.IP "\fB%x\fR, \fB%y\fR" 5
+The \fIx\fR and \fIy\fR fields from the event.
+For \fBButtonPress\fR, \fBButtonRelease\fR, \fBMotion\fR,
+\fBKeyPress\fR, \fBKeyRelease\fR, and \fBMouseWheel\fR events,
+\fB%x\fR and \fB%y\fR indicate the position of the mouse pointer
+relative to the receiving window.
+For \fBEnter\fR and \fBLeave\fR events, the position where the
+mouse pointer crossed the window, relative to the receiving window.
+For \fBConfigure\fR and \fBCreate\fR requests, the \fIx\fR and \fIy\fR
+coordinates of the window relative to its parent window.
+.IP \fB%A\fR 5
+Substitutes the UNICODE character corresponding to the event, or
+the empty string if the event does not correspond to a UNICODE character
+(e.g. the shift key was pressed). \fBXmbLookupString\fR (or
+\fBXLookupString\fR when input method support is turned off) does all
+the work of translating from the event to a UNICODE character.
+Valid only for \fBKeyPress\fR and \fBKeyRelease\fR events.
+.IP \fB%B\fR 5
+The \fIborder_width\fR field from the event. Valid only for
+\fBConfigure\fR, \fBConfigureRequest\fR, and \fBCreate\fR events.
+.IP \fB%D\fR 5
+This reports the \fIdelta\fR value of a \fBMouseWheel\fR event. The
+\fIdelta\fR value represents the rotation units the mouse wheel has
+been moved. The sign of the value represents the direction the mouse
+wheel was scrolled.
+.IP \fB%E\fR 5
+The \fIsend_event\fR field from the event. Valid for all event types.
+\fB0\fR indicates that this is a
+.QW normal
+event, \fB1\fR indicates that it is a
+.QW synthetic
+event generated by \fBSendEvent\fR.
+.IP \fB%K\fR 5
+The keysym corresponding to the event, substituted as a textual
+string. Valid only for \fBKeyPress\fR and \fBKeyRelease\fR events.
+.IP \fB%M\fR 5
+The number of script-based binding patterns matched so far for the
+event. Valid for all event types.
+.IP \fB%N\fR 5
+The keysym corresponding to the event, substituted as a decimal
+number. Valid only for \fBKeyPress\fR and \fBKeyRelease\fR events.
+.IP \fB%P\fR 5
+The name of the property being updated or deleted (which
+may be converted to an XAtom using \fBwinfo atom\fR.) Valid
+only for \fBProperty\fR events.
+.IP \fB%R\fR 5
+The \fIroot\fR window identifier from the event. Valid only for
+events containing a \fIroot\fR field.
+.IP \fB%S\fR 5
+The \fIsubwindow\fR window identifier from the event,
+formatted as a hexadecimal number.
+Valid only for events containing a \fIsubwindow\fR field.
+.IP \fB%T\fR 5
+The \fItype\fR field from the event. Valid for all event types.
+.IP \fB%W\fR 5
+The path name of the window to which the event was reported (the
+\fIwindow\fR field from the event). Valid for all event types.
+.IP "\fB%X\fR, \fB%Y\fR" 5
+The \fIx_root\fR and \fIy_root\fR fields from the event.
+If a virtual-root window manager is being used then the substituted
+values are the corresponding x-coordinate and y-coordinate in the virtual root.
+Valid only for
+\fBButtonPress\fR, \fBButtonRelease\fR, \fBEnter\fR, \fBKeyPress\fR,
+\fBKeyRelease\fR, \fBLeave\fR and \fBMotion\fR events.
+Same meaning as \fB%x\fR and \fB%y\fR, except relative to the (virtual) root
+window.
+.LP
+The replacement string for a %-replacement is formatted as a proper
+Tcl list element.
+This means that spaces or special characters such as \fB$\fR and
+\fB{\fR may be preceded by backslashes.
+This guarantees that the string will be passed through the Tcl
+parser when the binding script is evaluated.
+Most replacements are numbers or well-defined strings such
+as \fBAbove\fR; for these replacements no special formatting
+is ever necessary.
+The most common case where reformatting occurs is for the \fB%A\fR
+substitution. For example, if \fIscript\fR is
+.CS
+\fBinsert\0%A\fR
+.CE
+and the character typed is an open square bracket, then the script
+actually executed will be
+.CS
+\fBinsert\0\e[\fR
+.CE
+This will cause the \fBinsert\fR to receive the original replacement
+string (open square bracket) as its first argument.
+If the extra backslash had not been added, Tcl would not have been
+able to parse the script correctly.
+.SH "MULTIPLE MATCHES"
+.PP
+It is possible for several bindings to match a given X event.
+If the bindings are associated with different \fItag\fR's,
+then each of the bindings will be executed, in order.
+By default, a binding for the widget will be executed first, followed
+by a class binding, a binding for its toplevel, and
+an \fBall\fR binding.
+The \fBbindtags\fR command may be used to change this order for
+a particular window or to associate additional binding tags with
+the window.
+.PP
+The \fBcontinue\fR and \fBbreak\fR commands may be used inside a
+binding script to control the processing of matching scripts.
+If \fBcontinue\fR is invoked within a binding script, then this
+binding script, including all other
+.QW +
+appended scripts, is terminated but Tk will continue processing
+binding scripts associated with other \fItag\fR's.
+If the \fBbreak\fR command is invoked within a binding script,
+then that script terminates and no other scripts will be invoked
+for the event.
+.PP
+Within a script called from the binding script, \fBreturn\fR
+\fB-code ok\fR may be used to continue processing (including
+.QW +
+appended scripts), or \fBreturn\fR \fB-code break\fR may be used to
+stop processing all other binding scripts.
+.PP
+If more than one binding matches a particular event and they
+have the same \fItag\fR, then the most specific binding
+is chosen and its script is evaluated.
+The following tests are applied, in order, to determine which of
+several matching sequences is more specific:
+.RS
+.IP (a)
+an event pattern that specifies a specific button or key is more specific
+than one that does not;
+.IP (b)
+a longer sequence (in terms of number
+of events matched) is more specific than a shorter sequence;
+.IP (c)
+if the modifiers specified in one pattern are a subset of the
+modifiers in another pattern, then the pattern with more modifiers
+is more specific;
+.IP (d)
+a virtual event whose physical pattern matches the sequence is less
+specific than the same physical pattern that is not associated with a
+virtual event;
+.IP (e)
+given a sequence that matches two or more virtual events, one
+of the virtual events will be chosen, but the order is undefined.
+.RE
+.PP
+If the matching sequences contain more than one event, then tests
+(c)\-(e) are applied in order from the most recent event to the least recent
+event in the sequences. If these tests fail to determine a winner, then the
+most recently registered sequence is the winner.
+.PP
+If there are two (or more) virtual events that are both triggered by the
+same sequence, and both of those virtual events are bound to the same window
+tag, then only one of the virtual events will be triggered, and it will
+be picked at random:
+.CS
+event add <<Paste>> <Control\-y>
+event add <<Paste>> <Button\-2>
+event add <<Scroll>> <Button\-2>
+\fBbind\fR Entry <<Paste>> {puts Paste}
+\fBbind\fR Entry <<Scroll>> {puts Scroll}
+.CE
+If the user types Control\-y, the \fB<<Paste>>\fR binding
+will be invoked, but if the user presses button 2 then one of
+either the \fB<<Paste>>\fR or the \fB<<Scroll>>\fR bindings will
+be invoked, but exactly which one gets invoked is undefined.
+.PP
+If an X event does not match any of the existing bindings, then the
+event is ignored.
+An unbound event is not considered to be an error.
+.SH "MULTI-EVENT SEQUENCES AND IGNORED EVENTS"
+.PP
+When a \fIsequence\fR specified in a \fBbind\fR command contains
+more than one event pattern, then its script is executed whenever
+the recent events (leading up to and including the current event)
+match the given sequence. This means, for example, that if button 1 is
+clicked repeatedly the sequence \fB<Double\-ButtonPress\-1>\fR will match
+each button press but the first.
+If extraneous events that would prevent a match occur in the middle
+of an event sequence then the extraneous events are
+ignored unless they are \fBKeyPress\fR or \fBButtonPress\fR events.
+For example, \fB<Double\-ButtonPress\-1>\fR will match a sequence of
+presses of button 1, even though there will be \fBButtonRelease\fR
+events (and possibly \fBMotion\fR events) between the
+\fBButtonPress\fR events.
+Furthermore, a \fBKeyPress\fR event may be preceded by any number
+of other \fBKeyPress\fR events for modifier keys without the
+modifier keys preventing a match.
+For example, the event sequence \fBaB\fR will match a press of the
+\fBa\fR key, a release of the \fBa\fR key, a press of the \fBShift\fR
+key, and a press of the \fBb\fR key: the press of \fBShift\fR is
+ignored because it is a modifier key.
+Finally, if several \fBMotion\fR events occur in a row, only
+the last one is used for purposes of matching binding sequences.
+.SH "ERRORS"
+.PP
+If an error occurs in executing the script for a binding then the
+\fBbgerror\fR mechanism is used to report the error.
+The \fBbgerror\fR command will be executed at global level
+(outside the context of any Tcl procedure).
+.SH "EXAMPLES"
+.PP
+Arrange for a string describing the motion of the mouse to be printed
+out when the mouse is double-clicked:
+.CS
+\fBbind\fR . <Double\-1> {
+ puts "hi from (%x,%y)"
+}
+.CE
+.PP
+A little GUI that displays what the keysym name of the last key
+pressed is:
+.CS
+set keysym "Press any key"
+pack [label .l \-textvariable keysym \-padx 2m \-pady 1m]
+\fBbind\fR . <Key> {
+ set keysym "You pressed %K"
+}
+.CE
+.SH "SEE ALSO"
+bgerror(n), bindtags(n), event(n), focus(n), grab(n), keysyms(n)
+.SH KEYWORDS
+binding, event
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/bindtags.n b/tk8.6/doc/bindtags.n
new file mode 100644
index 0000000..dc3973b
--- /dev/null
+++ b/tk8.6/doc/bindtags.n
@@ -0,0 +1,102 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH bindtags n 4.0 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+bindtags \- Determine which bindings apply to a window, and order of evaluation
+.SH SYNOPSIS
+\fBbindtags \fIwindow \fR?\fItagList\fR?
+.BE
+.SH DESCRIPTION
+.PP
+When a binding is created with the \fBbind\fR command, it is
+associated either with a particular window such as \fB.a.b.c\fR,
+a class name such as \fBButton\fR, the keyword \fBall\fR, or any
+other string.
+All of these forms are called \fIbinding tags\fR.
+Each window contains a list of binding tags that determine how
+events are processed for the window.
+When an event occurs in a window, it is applied to each of the
+window's tags in order: for each tag, the most specific binding
+that matches the given tag and event is executed.
+See the \fBbind\fR command for more information on the matching
+process.
+.PP
+By default, each window has four binding tags consisting of the
+name of the window, the window's class name, the name of the window's
+nearest toplevel ancestor, and \fBall\fR, in that order.
+Toplevel windows have only three tags by default, since the toplevel
+name is the same as that of the window.
+The \fBbindtags\fR command allows the binding tags for a window to be
+read and modified.
+.PP
+If \fBbindtags\fR is invoked with only one argument, then the
+current set of binding tags for \fIwindow\fR is returned as a list.
+If the \fItagList\fR argument is specified to \fBbindtags\fR,
+then it must be a proper list; the tags for \fIwindow\fR are changed
+to the elements of the list.
+The elements of \fItagList\fR may be arbitrary strings; however,
+any tag starting with a dot is treated as the name of a window; if
+no window by that name exists at the time an event is processed,
+then the tag is ignored for that event.
+The order of the elements in \fItagList\fR determines the order in
+which binding scripts are executed in response to events.
+For example, the command
+.CS
+\fBbindtags .b {all . Button .b}\fR
+.CE
+reverses the order in which binding scripts will be evaluated for
+a button named \fB.b\fR so that \fBall\fR bindings are invoked
+first, following by bindings for \fB.b\fR's toplevel
+.PQ . "" ,
+followed by class bindings, followed by bindings for \fB.b\fR.
+If \fItagList\fR is an empty list then the binding tags for \fIwindow\fR
+are returned to the default state described above.
+.PP
+The \fBbindtags\fR command may be used to introduce arbitrary
+additional binding tags for a window, or to remove standard tags.
+For example, the command
+.CS
+\fBbindtags .b {.b TrickyButton . all}\fR
+.CE
+replaces the \fBButton\fR tag for \fB.b\fR with \fBTrickyButton\fR.
+This means that the default widget bindings for buttons, which are
+associated with the \fBButton\fR tag, will no longer apply to \fB.b\fR,
+but any bindings associated with \fBTrickyButton\fR (perhaps some
+new button behavior) will apply.
+.SH EXAMPLE
+.PP
+If you have a set of nested \fBframe\fR widgets and you want events
+sent to a \fBbutton\fR widget to also be delivered to all the widgets
+up to the current \fBtoplevel\fR (in contrast to Tk's default
+behavior, where events are not delivered to those intermediate
+windows) to make it easier to have accelerators that are only active
+for part of a window, you could use a helper procedure like this to
+help set things up:
+.CS
+proc setupBindtagsForTreeDelivery {widget} {
+ set tags [list $widget [winfo class $widget]]
+ set w $widget
+ set t [winfo toplevel $w]
+ while {$w ne $t} {
+ set w [winfo parent $w]
+ lappend tags $w
+ }
+ lappend tags all
+ \fBbindtags\fR $widget $tags
+}
+.CE
+.SH "SEE ALSO"
+bind(n)
+.SH KEYWORDS
+binding, event, tag
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/bitmap.n b/tk8.6/doc/bitmap.n
new file mode 100644
index 0000000..ead3311
--- /dev/null
+++ b/tk8.6/doc/bitmap.n
@@ -0,0 +1,124 @@
+'\"
+'\" Copyright (c) 1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH bitmap n 4.0 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+bitmap \- Images that display two colors
+.SH SYNOPSIS
+.nf
+\fBimage create bitmap \fR?\fIname\fR? ?\fIoptions\fR?
+
+\fIimageName \fBcget\fR \fIoption\fR
+\fIimageName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
+.fi
+.BE
+.SH DESCRIPTION
+.PP
+A bitmap is an image whose pixels can display either of two colors
+or be transparent.
+A bitmap image is defined by four things: a background color,
+a foreground color, and two bitmaps, called the \fIsource\fR
+and the \fImask\fR.
+Each of the bitmaps specifies 0/1 values for a rectangular
+array of pixels, and the two bitmaps must have the same
+dimensions.
+For pixels where the mask is zero, the image displays nothing,
+producing a transparent effect.
+For other pixels, the image displays the foreground color if
+the source data is one and the background color if the source
+data is zero.
+.SH "CREATING BITMAPS"
+.PP
+Like all images, bitmaps are created using the \fBimage create\fR
+command.
+Bitmaps support the following \fIoptions\fR:
+.TP
+\fB\-background \fIcolor\fR
+.
+Specifies a background color for the image in any of the standard
+ways accepted by Tk. If this option is set to an empty string
+then the background pixels will be transparent. This effect
+is achieved by using the source bitmap as the mask bitmap, ignoring
+any \fB\-maskdata\fR or \fB\-maskfile\fR options.
+.TP
+\fB\-data \fIstring\fR
+.
+Specifies the contents of the source bitmap as a string.
+The string must adhere to X11 bitmap format (e.g., as generated
+by the \fBbitmap\fR program).
+If both the \fB\-data\fR and \fB\-file\fR options are specified,
+the \fB\-data\fR option takes precedence.
+.TP
+\fB\-file \fIname\fR
+.
+\fIname\fR gives the name of a file whose contents define the
+source bitmap.
+The file must adhere to X11 bitmap format (e.g., as generated
+by the \fBbitmap\fR program).
+.TP
+\fB\-foreground \fIcolor\fR
+.
+Specifies a foreground color for the image in any of the standard
+ways accepted by Tk.
+.TP
+\fB\-maskdata \fIstring\fR
+.
+Specifies the contents of the mask as a string.
+The string must adhere to X11 bitmap format (e.g., as generated
+by the \fBbitmap\fR program).
+If both the \fB\-maskdata\fR and \fB\-maskfile\fR options are specified,
+the \fB\-maskdata\fR option takes precedence.
+.TP
+\fB\-maskfile \fIname\fR
+.
+\fIname\fR gives the name of a file whose contents define the
+mask.
+The file must adhere to X11 bitmap format (e.g., as generated
+by the \fBbitmap\fR program).
+.SH "IMAGE COMMAND"
+.PP
+When a bitmap image is created, Tk also creates a new command
+whose name is the same as the image.
+This command may be used to invoke various operations
+on the image.
+It has the following general form:
+.CS
+\fIimageName option \fR?\fIarg arg ...\fR?
+.CE
+\fIOption\fR and the \fIarg\fRs
+determine the exact behavior of the command. The following
+commands are possible for bitmap images:
+.TP
+\fIimageName \fBcget\fR \fIoption\fR
+.
+Returns the current value of the configuration option given
+by \fIoption\fR.
+\fIOption\fR may have any of the values accepted by the
+\fBimage create\fR \fBbitmap\fR command.
+.TP
+\fIimageName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
+.
+Query or modify the configuration options for the image.
+If no \fIoption\fR is specified, returns a list describing all of
+the available options for \fIimageName\fR (see \fBTk_ConfigureInfo\fR for
+information on the format of this list). If \fIoption\fR is specified
+with no \fIvalue\fR, then the command returns a list describing the
+one named option (this list will be identical to the corresponding
+sublist of the value returned if no \fIoption\fR is specified). If
+one or more \fIoption\-value\fR pairs are specified, then the command
+modifies the given option(s) to have the given value(s); in
+this case the command returns an empty string.
+\fIOption\fR may have any of the values accepted by the
+\fBimage create\fR \fBbitmap\fR command.
+.SH KEYWORDS
+bitmap, image
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/busy.n b/tk8.6/doc/busy.n
new file mode 100644
index 0000000..ab2fd8a
--- /dev/null
+++ b/tk8.6/doc/busy.n
@@ -0,0 +1,275 @@
+'\"
+'\" Copyright (c) 1993-1998 Lucent Technologies, Inc.
+'\" Copyright (c) 2008 Jos Decoster
+'\"
+'\" Permission to use, copy, modify, and distribute this software and its
+'\" documentation for any purpose and without fee is hereby granted, provided
+'\" that the above copyright notice appear in all copies and that both that
+'\" the copyright notice and warranty disclaimer appear in supporting
+'\" documentation, and that the names of Lucent Technologies any of their
+'\" entities not be used in advertising or publicity pertaining to
+'\" distribution of the software without specific, written prior permission.
+'\"
+'\" Lucent Technologies disclaims all warranties with regard to this software,
+'\" including all implied warranties of merchantability and fitness. In no
+'\" event shall Lucent Technologies be liable for any special, indirect or
+'\" consequential damages or any damages whatsoever resulting from loss of
+'\" use, data or profits, whether in an action of contract, negligence or
+'\" other tortuous action, arising out of or in connection with the use or
+'\" performance of this software.
+'\"
+'\" BLT::busy command created by George Howlett.
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH busy n "" Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+busy \- confine pointer events to a window sub-tree
+.SH SYNOPSIS
+\fBtk busy\fR \fIwindow \fR?\fIoptions\fR?
+.sp
+\fBtk busy hold\fR \fIwindow \fR?\fIoptions\fR?
+.sp
+\fBtk busy configure \fIwindow\fR ?\fIoption value\fR?...
+.sp
+\fBtk busy forget\fR \fIwindow \fR?\fIwindow \fR?...
+.sp
+\fBtk busy current\fR ?\fIpattern\fR?
+.sp
+\fBtk busy status \fIwindow\fR
+.BE
+.SH DESCRIPTION
+.PP
+The \fBtk busy\fR command provides a simple means to block pointer events from
+Tk widgets, while overriding the widget's cursor with a configurable busy
+cursor. Note this command does not prevent keyboard events from being sent to
+the widgets made busy.
+.SH INTRODUCTION
+.PP
+There are many times in applications where you want to temporarily restrict
+what actions the user can take. For example, an application could have a
+.QW Run
+button that when pressed causes some processing to occur. However, while the
+application is busy processing, you probably don't want the user to be
+able to click the
+.QW Run
+button again. You may also want restrict the user from other tasks such as
+clicking a
+.QW Print
+button.
+.PP
+The \fBtk busy\fR command lets you make Tk widgets busy. This means that user
+interactions such as button clicks, moving the mouse, typing at the keyboard,
+etc.\0are ignored by the widget. You can set a special cursor (like a watch)
+that overrides the widget's normal cursor, providing feedback that the
+application (widget) is temporarily busy.
+.PP
+When a widget is made busy, the widget and all of its descendants will ignore
+pointer events. It's easy to make an entire panel of widgets busy. You can
+simply make the toplevel widget (such as
+.QW . )
+busy. This is easier and far much more efficient than recursively traversing
+the widget hierarchy, disabling each widget and re-configuring its cursor.
+.PP
+Often, the \fBtk busy\fR command can be used instead of Tk's \fBgrab\fR
+command. Unlike \fBgrab\fR which restricts all user interactions to one
+widget, with the \fBtk busy\fR command you can have more than one widget
+active (for example, a
+.QW Cancel
+dialog and a
+.QW Help
+button).
+.SS EXAMPLE
+.PP
+You can make several widgets busy by simply making its ancestor widget busy
+using the \fBhold\fR operation.
+.PP
+.CS
+frame .top
+button .top.button; canvas .top.canvas
+pack .top.button .top.canvas
+pack .top
+# . . .
+\fBtk busy\fR hold .top
+update
+.CE
+.PP
+All the widgets within \fB.top\fR (including \fB.top\fR) are now busy. Using
+\fBupdate\fR insures that \fBtk busy\fR command will take effect before any
+other user events can occur.
+.PP
+When the application is no longer busy processing, you can allow user
+interactions again and free any resources it allocated by the \fBforget\fR
+operation.
+.PP
+.CS
+\fBtk busy\fR forget .top
+.CE
+.PP
+The busy window has a configurable cursor. You can change the busy cursor
+using the \fBconfigure\fR operation.
+.PP
+.CS
+\fBtk busy\fR configure .top \-cursor "watch"
+.CE
+.PP
+Destroying the widget will also clean up any resources allocated by the \fBtk
+busy\fR command.
+.PP
+.SH OPERATIONS
+.PP
+The following operations are available for the \fBtk busy\fR command:
+.TP
+\fBtk busy \fIwindow\fR ?\fIoption value\fR?...
+.
+Shortcut for \fBtk busy hold\fR command.
+.TP
+\fBtk busy hold \fIwindow\fR ?\fIoption value\fR?...
+.
+Makes the specified \fIwindow\fR (and its descendants in the Tk window
+hierarchy) appear busy. \fIWindow\fR must be a valid path name of a Tk widget.
+A transparent window is put in front of the specified window. This transparent
+window is mapped the next time idle tasks are processed, and the specified
+window and its descendants will be blocked from user interactions. Normally
+\fBupdate\fR should be called immediately afterward to insure that the hold
+operation is in effect before the application starts its processing. The
+following configuration options are valid:
+.RS
+.TP
+\fB\-cursor \fIcursorName\fR
+.
+Specifies the cursor to be displayed when the widget is made busy.
+\fICursorName\fR can be in any form accepted by \fBTk_GetCursor\fR. The
+default cursor is \fBwait\fR on Windows and \fBwatch\fR on other platforms.
+.RE
+.TP
+\fBtk busy cget \fIwindow\fR \fIoption\fR
+.
+Queries the \fBtk busy\fR command configuration options for \fIwindow\fR.
+\fIWindow\fR must be the path name of a widget previously made busy by the
+\fBhold\fR operation. The command returns the present value of the specified
+\fIoption\fR. \fIOption\fR may have any of the values accepted by the
+\fBhold\fR operation.
+.TP
+\fBtk busy configure \fIwindow\fR ?\fIoption value\fR?...
+.
+Queries or modifies the \fBtk busy\fR command configuration options for
+\fIwindow\fR. \fIWindow\fR must be the path name of a widget previously made
+busy by the \fBhold\fR operation. If no options are specified, a list
+describing all of the available options for \fIwindow\fR (see
+\fBTk_ConfigureInfo\fR for information on the format of this list) is
+returned. If \fIoption\fR is specified with no \fIvalue\fR, then the command
+returns a list describing the one named option (this list will be identical to
+the corresponding sublist of the value returned if no \fIoption\fR is
+specified). If one or more \fIoption\-value\fR pairs are specified, then the
+command modifies the given widget option(s) to have the given value(s); in
+this case the command returns the empty string. \fIOption\fR may have any of
+the values accepted by the \fBhold\fR operation.
+.RS
+.PP
+Please note that the option database is referenced through \fIwindow\fR. For
+example, if the widget \fB.frame\fR is to be made busy, the busy cursor can be
+specified for it by either \fBoption\fR command:
+.PP
+.CS
+option add *frame.busyCursor gumby
+option add *Frame.BusyCursor gumby
+.CE
+.RE
+.TP
+\fBtk busy forget \fIwindow\fR ?\fIwindow\fR?...
+.
+Releases resources allocated by the \fBtk busy\fR command for \fIwindow\fR,
+including the transparent window. User events will again be received by
+\fIwindow\fR. Resources are also released when \fIwindow\fR is destroyed.
+\fIWindow\fR must be the name of a widget specified in the \fBhold\fR
+operation, otherwise an error is reported.
+.TP
+\fBtk busy current \fR?\fIpattern\fR?
+.
+Returns the pathnames of all widgets that are currently busy. If a
+\fIpattern\fR is given, only the path names of busy widgets matching
+\fIpattern\fR are returned.
+.TP
+\fBtk busy status \fIwindow\fR
+.
+Returns the status of a widget \fIwindow\fR. If \fIwindow\fR presently can not
+receive user interactions, \fB1\fR is returned, otherwise \fB0\fR.
+.SH "EVENT HANDLING"
+.SS BINDINGS
+.PP
+The event blocking feature is implemented by creating and mapping a
+transparent window that completely covers the widget. When the busy window is
+mapped, it invisibly shields the widget and its hierarchy from all events that
+may be sent. Like Tk widgets, busy windows have widget names in the Tk window
+hierarchy. This means that you can use the \fBbind\fR command, to handle
+events in the busy window.
+.PP
+.CS
+\fBtk busy\fR hold .frame.canvas
+bind .frame.canvas_Busy <Enter> { ... }
+.CE
+.PP
+Normally the busy window is a sibling of the widget. The name of the busy
+window is
+.QW \fIwidget\fB_Busy\fR
+where \fIwidget\fR is the name of the widget to be made busy. In the previous
+example, the pathname of the busy window is
+.QW \fB.frame.canvas_Busy\fR .
+The exception is when the widget is a toplevel widget (such as
+.QW . )
+where the busy window can't be made a sibling. The busy window is then a child
+of the widget named
+.QW \fIwidget\fB._Busy\fR
+where \fIwidget\fR is the name of the toplevel widget. In the following
+example, the pathname of the busy window is
+.QW \fB._Busy\fR .
+.PP
+.CS
+\fBtk busy\fR hold .
+bind ._Busy <Enter> { ... }
+.CE
+.SS "ENTER/LEAVE EVENTS"
+.PP
+Mapping and unmapping busy windows generates Enter/Leave events for all
+widgets they cover. Please note this if you are tracking Enter/Leave events in
+widgets.
+.SS "KEYBOARD EVENTS"
+.PP
+When a widget is made busy, the widget is prevented from gaining the keyboard
+focus by a user clicking on it by the busy window. But if the widget already had
+focus, it still may receive keyboard events. The widget can also still receive
+focus through keyboard traversal. To prevent this, you must move
+focus to another window and make sure the focus can not go back to the widgets
+made busy (e.g. but restricting focus to a cancel button).
+.PP
+.CS
+pack [frame .frame]
+pack [text .frame.text]
+\fBtk busy\fR hold .frame
+pack [button .cancel -text "Cancel" -command exit]
+focus .cancel
+bind .cancel <Tab> {break}
+bind .cancel <Shift-Tab> {break}
+update
+.CE
+.PP
+The above example moves the focus from .frame immediately after invoking the
+\fBhold\fR so that no keyboard events will be sent to \fB.frame\fR or any of
+its descendants. It also makes sure it's not possible to leave button
+\fB.cancel\fR using the keyboard.
+.SH PORTABILITY
+.PP
+Note that the \fBtk busy\fR command does not currently have any effect on OSX
+when Tk is built using Aqua support.
+.SH "SEE ALSO"
+grab(n)
+.SH KEYWORDS
+busy, keyboard events, pointer events, window
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/button.n b/tk8.6/doc/button.n
new file mode 100644
index 0000000..233feb6
--- /dev/null
+++ b/tk8.6/doc/button.n
@@ -0,0 +1,210 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH button n 4.4 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+button \- Create and manipulate 'button' action widgets
+.SH SYNOPSIS
+\fBbutton\fR \fIpathName \fR?\fIoptions\fR?
+.SO
+\-activebackground \-font \-relief
+\-activeforeground \-foreground \-repeatdelay
+\-anchor \-highlightbackground \-repeatinterval
+\-background \-highlightcolor \-takefocus
+\-bitmap \-highlightthickness \-text
+\-borderwidth \-image \-textvariable
+\-compound \-justify \-underline
+\-cursor \-padx \-wraplength
+\-disabledforeground \-pady
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-command command Command
+Specifies a Tcl command to associate with the button. This command
+is typically invoked when mouse button 1 is released over the button
+window.
+.OP \-default default Default
+Specifies one of three states for the default ring: \fBnormal\fR,
+\fBactive\fR, or \fBdisabled\fR. In active state, the button is drawn
+with the platform specific appearance for a default button. In normal
+state, the button is drawn with the platform specific appearance for a
+non-default button, leaving enough space to draw the default button
+appearance. The normal and active states will result in buttons of
+the same size. In disabled state, the button is drawn with the
+non-default button appearance without leaving space for the default
+appearance. The disabled state may result in a smaller button than
+the active state.
+.OP \-height height Height
+Specifies a desired height for the button.
+If an image or bitmap is being displayed in the button then the value is in
+screen units (i.e. any of the forms acceptable to \fBTk_GetPixels\fR);
+for text it is in lines of text.
+If this option is not specified, the button's desired height is computed
+from the size of the image or bitmap or text being displayed in it.
+.OP \-overrelief overRelief OverRelief
+Specifies an alternative relief for the button, to be used when the
+mouse cursor is over the widget. This option can be used to make
+toolbar buttons, by configuring \fB\-relief flat \-overrelief
+raised\fR. If the value of this option is the empty string, then no
+alternative relief is used when the mouse cursor is over the button.
+The empty string is the default value.
+.OP \-state state State
+Specifies one of three states for the button: \fBnormal\fR, \fBactive\fR,
+or \fBdisabled\fR. In normal state the button is displayed using the
+\fB\-foreground\fR and \fB\-background\fR options. The active state is
+typically used when the pointer is over the button. In active state
+the button is displayed using the \fB\-activeforeground\fR and
+\fB\-activebackground\fR options. Disabled state means that the button
+should be insensitive: the default bindings will refuse to activate
+the widget and will ignore mouse button presses.
+In this state the \fB\-disabledforeground\fR and
+\fB\-background\fR options determine how the button is displayed.
+.OP \-width width Width
+Specifies a desired width for the button.
+If an image or bitmap is being displayed in the button then the value is in
+screen units (i.e. any of the forms acceptable to \fBTk_GetPixels\fR).
+For a text button (no image or with \fB\-compound none\fR) then the width
+specifies how much space in characters to allocate for the text label.
+If the width is negative then this specifies a minimum width.
+If this option is not specified, the button's desired width is computed
+from the size of the image or bitmap or text being displayed in it.
+.BE
+.SH DESCRIPTION
+.PP
+The \fBbutton\fR command creates a new window (given by the
+\fIpathName\fR argument) and makes it into a button widget.
+Additional
+options, described above, may be specified on the command line
+or in the option database
+to configure aspects of the button such as its colors, font,
+text, and initial relief. The \fBbutton\fR command returns its
+\fIpathName\fR argument. At the time this command is invoked,
+there must not exist a window named \fIpathName\fR, but
+\fIpathName\fR's parent must exist.
+.PP
+A button is a widget that displays a textual string, bitmap or image.
+If text is displayed, it must all be in a single font, but it
+can occupy multiple lines on the screen (if it contains newlines
+or if wrapping occurs because of the \fB\-wraplength\fR option) and
+one of the characters may optionally be underlined using the
+\fB\-underline\fR option.
+It can display itself in either of three different ways, according
+to
+the \fB\-state\fR option;
+it can be made to appear raised, sunken, or flat;
+and it can be made to flash. When a user invokes the
+button (by pressing mouse button 1 with the cursor over the
+button), then the Tcl command specified in the \fB\-command\fR
+option is invoked.
+.SH "WIDGET COMMAND"
+.PP
+The \fBbutton\fR command creates a new Tcl command whose
+name is \fIpathName\fR. This
+command may be used to invoke various
+operations on the widget. It has the following general form:
+.CS
+\fIpathName option \fR?\fIarg arg ...\fR?
+.CE
+\fIOption\fR and the \fIarg\fRs
+determine the exact behavior of the command. The following
+commands are possible for button widgets:
+.TP
+\fIpathName \fBcget\fR \fIoption\fR
+Returns the current value of the configuration option given
+by \fIoption\fR.
+\fIOption\fR may have any of the values accepted by the \fBbutton\fR
+command.
+.TP
+\fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
+Query or modify the configuration options of the widget.
+If no \fIoption\fR is specified, returns a list describing all of
+the available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for
+information on the format of this list). If \fIoption\fR is specified
+with no \fIvalue\fR, then the command returns a list describing the
+one named option (this list will be identical to the corresponding
+sublist of the value returned if no \fIoption\fR is specified). If
+one or more \fIoption\-value\fR pairs are specified, then the command
+modifies the given widget option(s) to have the given value(s); in
+this case the command returns an empty string.
+\fIOption\fR may have any of the values accepted by the \fBbutton\fR
+command.
+.TP
+\fIpathName \fBflash\fR
+Flash the button. This is accomplished by redisplaying the button
+several times, alternating between the configured activebackground
+and background colors. At the end of the flash the button is left
+in the same normal/active state as when the command was invoked.
+This command is ignored if the button's state is \fBdisabled\fR.
+.TP
+\fIpathName \fBinvoke\fR
+Invoke the Tcl command associated with the button, if there is one.
+The return value is the return value from the Tcl command, or an
+empty string if there is no command associated with the button.
+This command is ignored if the button's state is \fBdisabled\fR.
+.SH "DEFAULT BINDINGS"
+.PP
+Tk automatically creates class bindings for buttons that give them
+default behavior:
+.IP [1]
+A button activates whenever the mouse passes over it and deactivates
+whenever the mouse leaves the button.
+Under Windows, this binding is only active when mouse button 1 has
+been pressed over the button.
+.IP [2]
+A button's relief is changed to sunken whenever mouse button 1 is
+pressed over the button, and the relief is restored to its original
+value when button 1 is later released.
+.IP [3]
+If mouse button 1 is pressed over a button and later released over
+the button, the button is invoked. However, if the mouse is not
+over the button when button 1 is released, then no invocation occurs.
+.IP [4]
+When a button has the input focus, the space key causes the button
+to be invoked.
+.PP
+If the button's state is \fBdisabled\fR then none of the above
+actions occur: the button is completely non-responsive.
+.PP
+The behavior of buttons can be changed by defining new bindings for
+individual widgets or by redefining the class bindings.
+.SH "PLATFORM NOTES"
+.PP
+On Aqua/Mac OS X, some configuration options are ignored for the purpose of
+drawing of the widget because they would otherwise conflict with platform
+guidelines. The \fBconfigure\fR and \fBcget\fR subcommands can still
+manipulate the values, but do not cause any variation to the look of the
+widget. The options affected notably include \fB\-background\fR and
+\fB\-relief\fR.
+.SH EXAMPLES
+.PP
+This is the classic Tk
+.QW "Hello, World!"
+demonstration:
+.PP
+.CS
+\fBbutton\fR .b \-text "Hello, World!" \-command exit
+pack .b
+.CE
+.PP
+This example demonstrates how to handle button accelerators:
+.PP
+.CS
+\fBbutton\fR .b1 \-text Hello \-underline 0
+\fBbutton\fR .b2 \-text World \-underline 0
+bind . <Key\-h> {.b1 flash; .b1 invoke}
+bind . <Key\-w> {.b2 flash; .b2 invoke}
+pack .b1 .b2
+.CE
+.SH "SEE ALSO"
+ttk::button(n)
+.SH KEYWORDS
+button, widget
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/canvas.n b/tk8.6/doc/canvas.n
new file mode 100644
index 0000000..5b65283
--- /dev/null
+++ b/tk8.6/doc/canvas.n
@@ -0,0 +1,1923 @@
+'\"
+'\" Copyright (c) 1992-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
+'\" Copyright (c) 1997-1999 Scriptics Corporation.
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH canvas n 8.3 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+canvas \- Create and manipulate 'canvas' hypergraphics drawing surface widgets
+.SH SYNOPSIS
+\fBcanvas\fR \fIpathName \fR?\fIoptions\fR?
+.SO
+\-background \-borderwidth \-cursor
+\-highlightbackground \-highlightcolor \-highlightthickness
+\-insertbackground \-insertborderwidth \-insertofftime
+\-insertontime \-insertwidth \-relief
+\-selectbackground \-selectborderwidth \-selectforeground
+\-takefocus \-xscrollcommand \-yscrollcommand
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-closeenough closeEnough CloseEnough
+Specifies a floating-point value indicating how close the mouse cursor
+must be to an item before it is considered to be
+.QW inside
+the item. Defaults to 1.0.
+.OP \-confine confine Confine
+Specifies a boolean value that indicates whether or not it should be
+allowable to set the canvas's view outside the region defined by the
+\fBscrollRegion\fR argument.
+Defaults to true, which means that the view will
+be constrained within the scroll region.
+.OP \-height height Height
+Specifies a desired window height that the canvas widget should request from
+its geometry manager. The value may be specified in any
+of the forms described in the \fBCOORDINATES\fR section below.
+.OP \-scrollregion scrollRegion ScrollRegion
+Specifies a list with four coordinates describing the left, top, right, and
+bottom coordinates of a rectangular region.
+This region is used for scrolling purposes and is considered to be
+the boundary of the information in the canvas.
+Each of the coordinates may be specified
+in any of the forms given in the \fBCOORDINATES\fR section below.
+.OP \-state state State
+Modifies the default state of the canvas where \fIstate\fR may be set to
+one of: \fBnormal\fR, \fBdisabled\fR, or \fBhidden\fR. Individual canvas
+objects all have their own state option which may override the default
+state. Many options can take separate specifications such that the
+appearance of the item can be different in different situations. The
+options that start with \fBactive\fR control the appearance when the mouse
+pointer is over it, while the option starting with \fBdisabled\fR controls
+the appearance when the state is disabled. Canvas items which are
+\fBdisabled\fR will not react to canvas bindings.
+.OP \-width width width
+Specifies a desired window width that the canvas widget should request from
+its geometry manager. The value may be specified in any
+of the forms described in the \fBCOORDINATES\fR section below.
+.OP \-xscrollincrement xScrollIncrement ScrollIncrement
+Specifies an increment for horizontal scrolling, in any of the usual forms
+permitted for screen distances. If the value of this option is greater
+than zero, the horizontal view in the window will be constrained so that
+the canvas x coordinate at the left edge of the window is always an even
+multiple of \fBxScrollIncrement\fR; furthermore, the units for scrolling
+(e.g., the change in view when the left and right arrows of a scrollbar
+are selected) will also be \fBxScrollIncrement\fR. If the value of
+this option is less than or equal to zero, then horizontal scrolling
+is unconstrained.
+.OP \-yscrollincrement yScrollIncrement ScrollIncrement
+Specifies an increment for vertical scrolling, in any of the usual forms
+permitted for screen distances. If the value of this option is greater
+than zero, the vertical view in the window will be constrained so that
+the canvas y coordinate at the top edge of the window is always an even
+multiple of \fByScrollIncrement\fR; furthermore, the units for scrolling
+(e.g., the change in view when the top and bottom arrows of a scrollbar
+are selected) will also be \fByScrollIncrement\fR. If the value of
+this option is less than or equal to zero, then vertical scrolling
+is unconstrained.
+.BE
+.SH INTRODUCTION
+.PP
+The \fBcanvas\fR command creates a new window (given
+by the \fIpathName\fR argument) and makes it into a canvas widget.
+Additional options, described above, may be specified on the
+command line or in the option database
+to configure aspects of the canvas such as its colors and 3-D relief.
+The \fBcanvas\fR command returns its
+\fIpathName\fR argument. At the time this command is invoked,
+there must not exist a window named \fIpathName\fR, but
+\fIpathName\fR's parent must exist.
+.PP
+Canvas widgets implement structured graphics.
+A canvas displays any number of \fIitems\fR, which may be things like
+rectangles, circles, lines, and text.
+Items may be manipulated (e.g. moved or re-colored) and commands may
+be associated with items in much the same way that the \fBbind\fR
+command allows commands to be bound to widgets. For example,
+a particular command may be associated with the <Button-1> event
+so that the command is invoked whenever button 1 is pressed with
+the mouse cursor over an item.
+This means that items in a canvas can have behaviors defined by
+the Tcl scripts bound to them.
+.SH "DISPLAY LIST"
+.PP
+The items in a canvas are ordered for purposes of display,
+with the first item in the display list being displayed
+first, followed by the next item in the list, and so on.
+Items later in the display list obscure those that are
+earlier in the display list and are sometimes referred to as being
+.QW "on top"
+of earlier items.
+When a new item is created it is placed at the end of the
+display list, on top of everything else.
+Widget commands may be used to re-arrange the order of the
+display list.
+.PP
+Window items are an exception to the above rules. The underlying
+window systems require them always to be drawn on top of other items.
+In addition, the stacking order of window items
+is not affected by any of the canvas widget commands; you must use
+the Tk \fBraise\fR command and \fBlower\fR command instead.
+.SH "ITEM IDS AND TAGS"
+.PP
+Items in a canvas widget may be named in either of two ways:
+by id or by tag.
+Each item has a unique identifying number, which is assigned to
+that item when it is created. The id of an item never changes
+and id numbers are never re-used within the lifetime of a
+canvas widget.
+.PP
+Each item may also have any number of \fItags\fR associated
+with it. A tag is just a string of characters, and it may
+take any form except that of an integer.
+For example,
+.QW x123
+is OK but
+.QW 123
+is not.
+The same tag may be associated with many different items.
+This is commonly done to group items in various interesting
+ways; for example, all selected items might be given the tag
+.QW selected .
+.PP
+The tag \fBall\fR is implicitly associated with every item
+in the canvas; it may be used to invoke operations on
+all the items in the canvas.
+.PP
+The tag \fBcurrent\fR is managed automatically by Tk;
+it applies to the \fIcurrent item\fR, which is the
+topmost item whose drawn area covers the position of
+the mouse cursor (different item types interpret this in varying ways; see the
+individual item type documentation for details).
+If the mouse is not in the canvas widget or is not over
+an item, then no item has the \fBcurrent\fR tag.
+.PP
+When specifying items in canvas widget commands, if the
+specifier is an integer then it is assumed to refer to
+the single item with that id.
+If the specifier is not an integer, then it is assumed to
+refer to all of the items in the canvas that have a tag
+matching the specifier.
+The symbol \fItagOrId\fR is used below to indicate that
+an argument specifies either an id that selects a single
+item or a tag that selects zero or more items.
+.PP
+\fItagOrId\fR may contain a logical expressions of
+tags by using operators:
+.QW \fB&&\fR ,
+.QW \fB||\fR ,
+.QW \fB^\fR ,
+.QW \fB!\fR ,
+and parenthesized subexpressions. For example:
+.CS
+ .c find withtag {(a&&!b)||(!a&&b)}
+.CE
+or equivalently:
+.CS
+ .c find withtag {a^b}
+.CE
+will find only those items with either
+.QW a
+or
+.QW b
+tags, but not both.
+.PP
+Some widget commands only operate on a single item at a
+time; if \fItagOrId\fR is specified in a way that
+names multiple items, then the normal behavior is for
+the command to use the first (lowest) of these items in
+the display list that is suitable for the command.
+Exceptions are noted in the widget command descriptions
+below.
+.SH "COORDINATES"
+.PP
+All coordinates related to canvases are stored as floating-point
+numbers.
+Coordinates and distances are specified in screen units,
+which are floating-point numbers optionally followed
+by one of several letters.
+If no letter is supplied then the distance is in pixels.
+If the letter is \fBm\fR then the distance is in millimeters on
+the screen; if it is \fBc\fR then the distance is in centimeters;
+\fBi\fR means inches, and \fBp\fR means printers points (1/72 inch).
+Larger y-coordinates refer to points lower on the screen; larger
+x-coordinates refer to points farther to the right.
+Coordinates can be specified either as an even number of parameters,
+or as a single list parameter containing an even number of x and y
+coordinate values.
+.SS TRANSFORMATIONS
+.PP
+Normally the origin of the canvas coordinate system is at the
+upper-left corner of the window containing the canvas.
+It is possible to adjust the origin of the canvas
+coordinate system relative to the origin of the window using the
+\fBxview\fR and \fByview\fR widget commands; this is typically used
+for scrolling.
+Canvases do not support scaling or rotation of the canvas coordinate
+system relative to the window coordinate system.
+.PP
+Individual items may be moved or scaled using widget commands
+described below, but they may not be rotated.
+.PP
+Note that the default origin of the canvas's visible area is
+coincident with the origin for the whole window as that makes bindings
+using the mouse position easier to work with; you only need to use the
+\fBcanvasx\fR and \fBcanvasy\fR widget commands if you adjust the
+origin of the visible area. However, this also means that any focus
+ring (as controlled by the \fB\-highlightthickness\fR option) and
+window border (as controlled by the \fB\-borderwidth\fR option) must
+be taken into account before you get to the visible area of the
+canvas.
+.SH "INDICES"
+.PP
+Text items support the notion of an \fIindex\fR for identifying
+particular positions within the item.
+In a similar fashion, line and polygon items support \fIindex\fR for
+identifying, inserting and deleting subsets of their coordinates.
+Indices are used for commands such as inserting or deleting
+a range of characters or coordinates, and setting the insertion
+cursor position. An index may be specified in any of a number
+of ways, and different types of items may support different forms
+for specifying indices.
+Text items support the following forms for an index; if you
+define new types of text-like items, it would be advisable to
+support as many of these forms as practical.
+Note that it is possible to refer to the character just after
+the last one in the text item; this is necessary for such
+tasks as inserting new text at the end of the item.
+Lines and Polygons do not support the insertion cursor
+and the selection. Their indices are supposed to be even
+always, because coordinates always appear in pairs.
+.TP 10
+\fInumber\fR
+.
+A decimal number giving the position of the desired character
+within the text item.
+0 refers to the first character, 1 to the next character, and
+so on. If indexes are odd for lines and polygons, they will be
+automatically decremented by one.
+A number less than 0 is treated as if it were zero, and a
+number greater than the length of the text item is treated
+as if it were equal to the length of the text item. For
+polygons, numbers less than 0 or greater than the length
+of the coordinate list will be adjusted by adding or subtracting
+the length until the result is between zero and the length,
+inclusive.
+.TP 10
+\fBend\fR
+.
+Refers to the character or coordinate just after the last one
+in the item (same as the number of characters or coordinates
+in the item).
+.TP 10
+\fBinsert\fR
+.
+Refers to the character just before which the insertion cursor
+is drawn in this item. Not valid for lines and polygons.
+.TP 10
+\fBsel.first\fR
+.
+Refers to the first selected character in the item.
+If the selection is not in this item then this form is illegal.
+.TP 10
+\fBsel.last\fR
+.
+Refers to the last selected character in the item.
+If the selection is not in this item then this form is illegal.
+.TP 10
+\fB@\fIx,y\fR
+.
+Refers to the character or coordinate at the point given by \fIx\fR and
+\fIy\fR, where \fIx\fR and \fIy\fR are specified in the coordinate
+system of the canvas.
+If \fIx\fR and \fIy\fR lie outside the coordinates covered by the
+text item, then they refer to the first or last character in the
+line that is closest to the given point.
+.SH "DASH PATTERNS"
+.PP
+Many items support the notion of a dash pattern for outlines.
+.PP
+The first possible syntax is a list of integers. Each element
+represents the number of pixels of a line segment. Only the odd
+segments are drawn using the
+.QW outline
+color. The other segments are drawn transparent.
+.PP
+The second possible syntax is a character list containing only
+5 possible characters
+.QW "\fB.,-_ \fR" .
+The space can be used
+to enlarge the space between other line elements, and cannot
+occur as the first position in the string. Some examples:
+.CS
+\-dash . \(-> \-dash {2 4}
+\-dash - \(-> \-dash {6 4}
+\-dash -. \(-> \-dash {6 4 2 4}
+\-dash -.. \(-> \-dash {6 4 2 4 2 4}
+\-dash {. } \(-> \-dash {2 8}
+\-dash , \(-> \-dash {4 4}
+.CE
+.PP
+The main difference of this syntax with the previous is that it
+is shape-conserving. This means that all values in the dash
+list will be multiplied by the line width before display. This
+assures that
+.QW .
+will always be displayed as a dot and
+.QW -
+always as a dash regardless of the line width.
+.PP
+On systems which support only a limited set of dash patterns, the dash
+pattern will be displayed as the closest dash pattern that is available.
+For example, on Windows only the first 4 of the above examples are
+available. The last 2 examples will be displayed identically to the first
+one.
+.SH "WIDGET COMMAND"
+.PP
+The \fBcanvas\fR command creates a new Tcl command whose
+name is \fIpathName\fR. This
+command may be used to invoke various
+operations on the widget. It has the following general form:
+.CS
+\fIpathName option \fR?\fIarg arg ...\fR?
+.CE
+\fIOption\fR and the \fIarg\fRs
+determine the exact behavior of the command.
+The following widget commands are possible for canvas widgets:
+.TP
+\fIpathName \fBaddtag \fItag searchSpec \fR?\fIarg arg ...\fR?
+.
+For each item that meets the constraints specified by
+\fIsearchSpec\fR and the \fIarg\fRs, add
+\fItag\fR to the list of tags associated with the item if it
+is not already present on that list.
+It is possible that no items will satisfy the constraints
+given by \fIsearchSpec\fR and \fIarg\fRs, in which case the
+command has no effect.
+This command returns an empty string as result.
+\fISearchSpec\fR and \fIarg\fR's may take any of the following
+forms:
+.RS
+.TP
+\fBabove \fItagOrId\fR
+.
+Selects the item just after (above) the one given by \fItagOrId\fR
+in the display list.
+If \fItagOrId\fR denotes more than one item, then the last (topmost)
+of these items in the display list is used.
+.TP
+\fBall\fR
+.
+Selects all the items in the canvas.
+.TP
+\fBbelow \fItagOrId\fR
+.
+Selects the item just before (below) the one given by \fItagOrId\fR
+in the display list.
+If \fItagOrId\fR denotes more than one item, then the first (lowest)
+of these items in the display list is used.
+.TP
+\fBclosest \fIx y \fR?\fIhalo\fR? ?\fIstart\fR?
+.
+Selects the item closest to the point given by \fIx\fR and \fIy\fR.
+If more than one item is at the same closest distance (e.g. two
+items overlap the point), then the top-most of these items (the
+last one in the display list) is used.
+If \fIhalo\fR is specified, then it must be a non-negative
+value.
+Any item closer than \fIhalo\fR to the point is considered to
+overlap it.
+The \fIstart\fR argument may be used to step circularly through
+all the closest items.
+If \fIstart\fR is specified, it names an item using a tag or id
+(if by tag, it selects the first item in the display list with
+the given tag).
+Instead of selecting the topmost closest item, this form will
+select the topmost closest item that is below \fIstart\fR in
+the display list; if no such item exists, then the selection
+behaves as if the \fIstart\fR argument had not been specified.
+.TP
+\fBenclosed\fR \fIx1\fR \fIy1\fR \fIx2\fR \fIy2\fR
+.
+Selects all the items completely enclosed within the rectangular
+region given by \fIx1\fR, \fIy1\fR, \fIx2\fR, and \fIy2\fR.
+\fIX1\fR must be no greater than \fIx2\fR and \fIy1\fR must be
+no greater than \fIy2\fR.
+.TP
+\fBoverlapping\fR \fIx1\fR \fIy1\fR \fIx2\fR \fIy2\fR
+.
+Selects all the items that overlap or are enclosed within the
+rectangular region given by \fIx1\fR, \fIy1\fR, \fIx2\fR,
+and \fIy2\fR.
+\fIX1\fR must be no greater than \fIx2\fR and \fIy1\fR must be
+no greater than \fIy2\fR.
+.TP
+\fBwithtag \fItagOrId\fR
+.
+Selects all the items given by \fItagOrId\fR.
+.RE
+.TP
+\fIpathName \fBbbox \fItagOrId\fR ?\fItagOrId tagOrId ...\fR?
+.
+Returns a list with four elements giving an approximate bounding box
+for all the items named by the \fItagOrId\fR arguments.
+The list has the form
+.QW "\fIx1 y1 x2 y2\fR"
+such that the drawn
+areas of all the named elements are within the region bounded by
+\fIx1\fR on the left, \fIx2\fR on the right, \fIy1\fR on the top,
+and \fIy2\fR on the bottom.
+The return value may overestimate the actual bounding box by
+a few pixels.
+If no items match any of the \fItagOrId\fR arguments or if the
+matching items have empty bounding boxes (i.e. they have nothing
+to display)
+then an empty string is returned.
+.TP
+\fIpathName \fBbind \fItagOrId\fR ?\fIsequence\fR? ?\fIcommand\fR?
+.
+This command associates \fIcommand\fR with all the items given by
+\fItagOrId\fR such that whenever the event sequence given by
+\fIsequence\fR occurs for one of the items the command will
+be invoked.
+This widget command is similar to the \fBbind\fR command except that
+it operates on items in a canvas rather than entire widgets.
+See the \fBbind\fR manual entry for complete details
+on the syntax of \fIsequence\fR and the substitutions performed
+on \fIcommand\fR before invoking it.
+If all arguments are specified then a new binding is created, replacing
+any existing binding for the same \fIsequence\fR and \fItagOrId\fR
+(if the first character of \fIcommand\fR is
+.QW +
+then \fIcommand\fR augments an existing binding rather than replacing it).
+In this case the return value is an empty string.
+If \fIcommand\fR is omitted then the command returns the \fIcommand\fR
+associated with \fItagOrId\fR and \fIsequence\fR (an error occurs
+if there is no such binding).
+If both \fIcommand\fR and \fIsequence\fR are omitted then the command
+returns a list of all the sequences for which bindings have been
+defined for \fItagOrId\fR.
+.RS
+.PP
+The only events for which bindings may be specified are those related to
+the mouse and keyboard (such as \fBEnter\fR, \fBLeave\fR,
+\fBButtonPress\fR, \fBMotion\fR, and \fBKeyPress\fR) or virtual events.
+The handling of events in canvases uses the current item defined in
+\fBITEM IDS AND TAGS\fR above. \fBEnter\fR and \fBLeave\fR events
+trigger for an
+item when it becomes the current item or ceases to be the current item;
+note that these events are different than \fBEnter\fR and \fBLeave\fR
+events for windows. Mouse-related events are directed to the current
+item, if any. Keyboard-related events are directed to the focus item, if
+any (see the \fBfocus\fR widget command below for more on this). If a
+virtual event is used in a binding, that binding can trigger only if the
+virtual event is defined by an underlying mouse-related or
+keyboard-related event.
+.PP
+It is possible for multiple bindings to match a particular event.
+This could occur, for example, if one binding is associated with the
+item's id and another is associated with one of the item's tags.
+When this occurs, all of the matching bindings are invoked.
+A binding associated with the \fBall\fR tag is invoked first,
+followed by one binding for each of the item's tags (in order),
+followed by a binding associated with the item's id.
+If there are multiple matching bindings for a single tag,
+then only the most specific binding is invoked.
+A \fBcontinue\fR command in a binding script terminates that
+script, and a \fBbreak\fR command terminates that script
+and skips any remaining scripts for the event, just as for the
+\fBbind\fR command.
+.PP
+If bindings have been created for a canvas window using the \fBbind\fR
+command, then they are invoked in addition to bindings created for
+the canvas's items using the \fBbind\fR widget command.
+The bindings for items will be invoked before any of the bindings
+for the window as a whole.
+.RE
+.TP
+\fIpathName \fBcanvasx \fIscreenx\fR ?\fIgridspacing\fR?
+.
+Given a window x-coordinate in the canvas \fIscreenx\fR, this command returns
+the canvas x-coordinate that is displayed at that location.
+If \fIgridspacing\fR is specified, then the canvas coordinate is
+rounded to the nearest multiple of \fIgridspacing\fR units.
+.TP
+\fIpathName \fBcanvasy \fIscreeny\fR ?\fIgridspacing\fR?
+.
+Given a window y-coordinate in the canvas \fIscreeny\fR this command returns
+the canvas y-coordinate that is displayed at that location.
+If \fIgridspacing\fR is specified, then the canvas coordinate is
+rounded to the nearest multiple of \fIgridspacing\fR units.
+.TP
+\fIpathName \fBcget\fR \fIoption\fR
+.
+Returns the current value of the configuration option given
+by \fIoption\fR.
+\fIOption\fR may have any of the values accepted by the \fBcanvas\fR
+command.
+.TP
+\fIpathName \fBconfigure ?\fIoption\fR? ?\fIvalue\fR? ?\fIoption value ...\fR?
+.
+Query or modify the configuration options of the widget.
+If no \fIoption\fR is specified, returns a list describing all of
+the available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for
+information on the format of this list). If \fIoption\fR is specified
+with no \fIvalue\fR, then the command returns a list describing the
+one named option (this list will be identical to the corresponding
+sublist of the value returned if no \fIoption\fR is specified). If
+one or more \fIoption\-value\fR pairs are specified, then the command
+modifies the given widget option(s) to have the given value(s); in
+this case the command returns an empty string.
+\fIOption\fR may have any of the values accepted by the \fBcanvas\fR
+command.
+.TP
+\fIpathName\fR \fBcoords \fItagOrId \fR?\fIx0 y0 ...\fR?
+.TP
+\fIpathName\fR \fBcoords \fItagOrId \fR?\fIcoordList\fR?
+.
+Query or modify the coordinates that define an item.
+If no coordinates are specified, this command returns a list
+whose elements are the coordinates of the item named by
+\fItagOrId\fR.
+If coordinates are specified, then they replace the current
+coordinates for the named item.
+If \fItagOrId\fR refers to multiple items, then
+the first one in the display list is used.
+.RS
+.PP
+Note that for rectangles, ovals and arcs the returned list of coordinates
+has a fixed order, namely the left, top, right and bottom coordinates,
+which may not be the order originally given. Also the coordinates are always
+returned in screen units with no units (that is, in pixels). So if the
+original coordinates were specified for instance in centimeters or inches,
+the returned values will nevertheless be in pixels.
+.RE
+.TP
+\fIpathName \fBcreate \fItype x y \fR?\fIx y ...\fR? ?\fIoption value ...\fR?
+.TP
+\fIpathName \fBcreate \fItype coordList \fR?\fIoption value ...\fR?
+.
+Create a new item in \fIpathName\fR of type \fItype\fR.
+The exact format of the arguments after \fItype\fR depends
+on \fItype\fR, but usually they consist of the coordinates for
+one or more points, followed by specifications for zero or
+more item options.
+See the subsections on individual item types below for more
+on the syntax of this command.
+This command returns the id for the new item.
+.TP
+\fIpathName \fBdchars \fItagOrId first \fR?\fIlast\fR?
+.
+For each item given by \fItagOrId\fR, delete the characters, or coordinates,
+in the range given by \fIfirst\fR and \fIlast\fR, inclusive.
+If some of the items given by \fItagOrId\fR do not support
+indexing operations then they ignore this operation.
+Text items interpret \fIfirst\fR and \fIlast\fR as indices to a character,
+line and polygon items interpret them as indices to a coordinate (an x,y pair).
+Indices are described in \fBINDICES\fR above.
+If \fIlast\fR is omitted, it defaults to \fIfirst\fR.
+This command returns an empty string.
+.TP
+\fIpathName \fBdelete \fR?\fItagOrId tagOrId ...\fR?
+.
+Delete each of the items given by each \fItagOrId\fR, and return
+an empty string.
+.TP
+\fIpathName \fBdtag \fItagOrId \fR?\fItagToDelete\fR?
+.
+For each of the items given by \fItagOrId\fR, delete the
+tag given by \fItagToDelete\fR from the list of those
+associated with the item.
+If an item does not have the tag \fItagToDelete\fR then
+the item is unaffected by the command.
+If \fItagToDelete\fR is omitted then it defaults to \fItagOrId\fR.
+This command returns an empty string.
+.TP
+\fIpathName \fBfind \fIsearchCommand \fR?\fIarg arg ...\fR?
+.
+This command returns a list consisting of all the items that
+meet the constraints specified by \fIsearchCommand\fR and
+\fIarg\fR's.
+\fISearchCommand\fR and \fIargs\fR have any of the forms
+accepted by the \fBaddtag\fR command.
+The items are returned in stacking order, with the lowest item first.
+.TP
+\fIpathName \fBfocus \fR?\fItagOrId\fR?
+.
+Set the keyboard focus for the canvas widget to the item given by
+\fItagOrId\fR.
+If \fItagOrId\fR refers to several items, then the focus is set
+to the first such item in the display list that supports the
+insertion cursor.
+If \fItagOrId\fR does not refer to any items, or if none of them
+support the insertion cursor, then the focus is not changed.
+If \fItagOrId\fR is an empty
+string, then the focus item is reset so that no item has the focus.
+If \fItagOrId\fR is not specified then the command returns the
+id for the item that currently has the focus, or an empty string
+if no item has the focus.
+.RS
+.PP
+Once the focus has been set to an item, the item will display
+the insertion cursor and all keyboard events will be directed
+to that item.
+The focus item within a canvas and the focus window on the
+screen (set with the \fBfocus\fR command) are totally independent:
+a given item does not actually have the input focus unless (a)
+its canvas is the focus window and (b) the item is the focus item
+within the canvas.
+In most cases it is advisable to follow the \fBfocus\fR widget
+command with the \fBfocus\fR command to set the focus window to
+the canvas (if it was not there already).
+.RE
+.TP
+\fIpathName \fBgettags\fR \fItagOrId\fR
+.
+Return a list whose elements are the tags associated with the
+item given by \fItagOrId\fR.
+If \fItagOrId\fR refers to more than one item, then the tags
+are returned from the first such item in the display list.
+If \fItagOrId\fR does not refer to any items, or if the item
+contains no tags, then an empty string is returned.
+.TP
+\fIpathName \fBicursor \fItagOrId index\fR
+.
+Set the position of the insertion cursor for the item(s) given by \fItagOrId\fR
+to just before the character whose position is given by \fIindex\fR.
+If some or all of the items given by \fItagOrId\fR do not support
+an insertion cursor then this command has no effect on them.
+See \fBINDICES\fR above for a description of the
+legal forms for \fIindex\fR.
+Note: the insertion cursor is only displayed in an item if
+that item currently has the keyboard focus (see the \fBfocus\fR widget
+command, above), but the cursor position may
+be set even when the item does not have the focus.
+This command returns an empty string.
+.TP
+\fIpathName \fBimove \fItagOrId index x y\fR
+.VS 8.6
+This command causes the \fIindex\fR'th coordinate of each of the items
+indicated by \fItagOrId\fR to be relocated to the location (\fIx\fR,\fIy\fR).
+Each item interprets \fIindex\fR independently according to the rules
+described in \fBINDICES\fR above. Out of the standard set of items, only line
+and polygon items may have their coordinates relocated this way.
+.VE 8.6
+.TP
+\fIpathName \fBindex \fItagOrId index\fR
+.
+This command returns a decimal string giving the numerical index
+within \fItagOrId\fR corresponding to \fIindex\fR.
+\fIIndex\fR gives a textual description of the desired position
+as described in \fBINDICES\fR above.
+Text items interpret \fIindex\fR as an index to a character,
+line and polygon items interpret it as an index to a coordinate (an x,y pair).
+The return value is guaranteed to lie between 0 and the number
+of characters, or coordinates, within the item, inclusive.
+If \fItagOrId\fR refers to multiple items, then the index
+is processed in the first of these items that supports indexing
+operations (in display list order).
+.TP
+\fIpathName \fBinsert \fItagOrId beforeThis string\fR
+.
+For each of the items given by \fItagOrId\fR, if the item supports
+text or coordinate, insertion then \fIstring\fR is inserted into the item's
+text just before the character, or coordinate, whose index is \fIbeforeThis\fR.
+Text items interpret \fIbeforeThis\fR as an index to a character,
+line and polygon items interpret it as an index to a coordinate (an x,y pair).
+For lines and polygons the \fIstring\fR must be a valid coordinate
+sequence.
+See \fBINDICES\fR above for information about the forms allowed
+for \fIbeforeThis\fR.
+This command returns an empty string.
+.TP
+\fIpathName \fBitemcget\fR \fItagOrId\fR \fIoption\fR
+.
+Returns the current value of the configuration option for the
+item given by \fItagOrId\fR whose name is \fIoption\fR.
+This command is similar to the \fBcget\fR widget command except that
+it applies to a particular item rather than the widget as a whole.
+\fIOption\fR may have any of the values accepted by the \fBcreate\fR
+widget command when the item was created.
+If \fItagOrId\fR is a tag that refers to more than one item,
+the first (lowest) such item is used.
+.TP
+\fIpathName \fBitemconfigure \fItagOrId\fR ?\fIoption\fR? ?\fIvalue\fR? ?\fIoption value ...\fR?
+.
+This command is similar to the \fBconfigure\fR widget command except
+that it modifies item-specific options for the items given by
+\fItagOrId\fR instead of modifying options for the overall
+canvas widget.
+If no \fIoption\fR is specified, returns a list describing all of
+the available options for the first item given by \fItagOrId\fR
+(see \fBTk_ConfigureInfo\fR for
+information on the format of this list). If \fIoption\fR is specified
+with no \fIvalue\fR, then the command returns a list describing the
+one named option (this list will be identical to the corresponding
+sublist of the value returned if no \fIoption\fR is specified). If
+one or more \fIoption\-value\fR pairs are specified, then the command
+modifies the given widget option(s) to have the given value(s) in
+each of the items given by \fItagOrId\fR; in
+this case the command returns an empty string.
+The \fIoption\fRs and \fIvalue\fRs are the same as those permissible
+in the \fBcreate\fR widget command when the item(s) were created;
+see the sections describing individual item types below for details
+on the legal options.
+.TP
+\fIpathName \fBlower \fItagOrId \fR?\fIbelowThis\fR?
+.
+Move all of the items given by \fItagOrId\fR to a new position
+in the display list just before the item given by \fIbelowThis\fR.
+If \fItagOrId\fR refers to more than one item then all are moved
+but the relative order of the moved items will not be changed.
+\fIBelowThis\fR is a tag or id; if it refers to more than one
+item then the first (lowest) of these items in the display list is used
+as the destination location for the moved items.
+Note: this command has no effect on window items. Window items always
+obscure other item types, and the stacking order of window items is
+determined by the \fBraise\fR command and \fBlower\fR command, not the
+\fBraise\fR widget command and \fBlower\fR widget command for canvases.
+This command returns an empty string.
+.TP
+\fIpathName \fBmove \fItagOrId xAmount yAmount\fR
+.
+Move each of the items given by \fItagOrId\fR in the canvas coordinate
+space by adding \fIxAmount\fR to the x-coordinate of each point
+associated with the item and \fIyAmount\fR to the y-coordinate of
+each point associated with the item.
+This command returns an empty string.
+.TP
+\fIpathName \fBmoveto \fItagOrId xPos yPos\fR
+.VS 8.6
+Move the items given by \fItagOrId\fR in the canvas coordinate
+space so that the first coordinate pair of the bottommost item with
+tag \fItagOrId\fR is located at
+position (\fIxPos\fR,\fIyPos\fR). \fIxPos\fR and \fIyPos\fR may be
+the empty string, in which case the corresponding coordinate
+will be unchanged. All items matching
+\fItagOrId\fR remain in the same positions relative to each other.
+This command returns an empty string.
+.VE 8.6
+.TP
+\fIpathName \fBpostscript \fR?\fIoption value option value ...\fR?
+.
+Generate a Postscript representation for part or all of the canvas.
+If the \fB\-file\fR option is specified then the Postscript is written
+to a file and an empty string is returned; otherwise the Postscript
+is returned as the result of the command.
+If the interpreter that owns the canvas is marked as safe, the operation
+will fail because safe interpreters are not allowed to write files.
+If the \fB\-channel\fR option is specified, the argument denotes the name
+of a channel already opened for writing. The Postscript is written to
+that channel, and the channel is left open for further writing at the end
+of the operation.
+The Postscript is created in Encapsulated Postscript form using
+version 3.0 of the Document Structuring Conventions.
+Note: by default Postscript is only generated for information that
+appears in the canvas's window on the screen. If the canvas is
+freshly created it may still have its initial size of 1x1 pixel
+so nothing will appear in the Postscript. To get around this problem
+either invoke the \fBupdate\fR command to wait for the canvas window
+to reach its final size, or else use the \fB\-width\fR and \fB\-height\fR
+options to specify the area of the canvas to print.
+The \fIoption\fR\-\fIvalue\fR argument pairs provide additional
+information to control the generation of Postscript. The following
+options are supported:
+.RS
+.TP
+\fB\-channel \fIchannelName\fR
+.
+Specifies the name of the channel to which to write the Postscript.
+If this option and the \fB\-file\fR option are
+not specified then the Postscript is returned as the
+result of the command.
+.TP
+\fB\-colormap \fIvarName\fR
+.
+\fIVarName\fR must be the name of an array variable
+that specifies a color mapping to use in the Postscript.
+Each element of \fIvarName\fR must consist of Postscript
+code to set a particular color value (e.g.
+.QW "\fB1.0 1.0 0.0 setrgbcolor\fR" ).
+When outputting color information in the Postscript, Tk checks
+to see if there is an element of \fIvarName\fR with the same
+name as the color.
+If so, Tk uses the value of the element as the Postscript command
+to set the color.
+If this option has not been specified, or if there is no entry
+in \fIvarName\fR for a given color, then Tk uses the red, green,
+and blue intensities from the X color.
+.TP
+\fB\-colormode \fImode\fR
+.
+Specifies how to output color information. \fIMode\fR must be either
+\fBcolor\fR (for full color output), \fBgray\fR (convert all colors
+to their gray-scale equivalents) or \fBmono\fR (convert all colors
+to black or white).
+.TP
+\fB\-file \fIfileName\fR
+.
+Specifies the name of the file in which to write the Postscript.
+If this option and the \fB\-channel\fR option are
+not specified then the Postscript is returned as the
+result of the command.
+.TP
+\fB\-fontmap \fIvarName\fR
+.
+\fIVarName\fR must be the name of an array variable
+that specifies a font mapping to use in the Postscript.
+Each element of \fIvarName\fR must consist of a Tcl list with
+two elements, which are the name and point size of a Postscript font.
+When outputting Postscript commands for a particular font, Tk
+checks to see if \fIvarName\fR contains an element with the same
+name as the font.
+If there is such an element, then the font information contained in
+that element is used in the Postscript.
+Otherwise Tk attempts to guess what Postscript font to use.
+Tk's guesses generally only work for well-known fonts such as
+Times and Helvetica and Courier, and only if the X font name does not
+omit any dashes up through the point size.
+For example, \fB\-*\-Courier\-Bold\-R\-Normal\-\-*\-120\-*\fR will work but
+\fB*Courier\-Bold\-R\-Normal*120*\fR will not; Tk needs the dashes to
+parse the font name).
+.TP
+\fB\-height \fIsize\fR
+.
+Specifies the height of the area of the canvas to print.
+Defaults to the height of the canvas window.
+.TP
+\fB\-pageanchor \fIanchor\fR
+.
+Specifies which point of the printed area of the canvas should appear over
+the positioning point on the page (which is given by the \fB\-pagex\fR
+and \fB\-pagey\fR options).
+For example, \fB\-pageanchor n\fR means that the top center of the
+area of the canvas being printed (as it appears in the canvas window)
+should be over the positioning point. Defaults to \fBcenter\fR.
+.TP
+\fB\-pageheight \fIsize\fR
+.
+Specifies that the Postscript should be scaled in both x and y so
+that the printed area is \fIsize\fR high on the Postscript page.
+\fISize\fR consists of a floating-point number followed by
+\fBc\fR for centimeters, \fBi\fR for inches, \fBm\fR for millimeters,
+or \fBp\fR or nothing for printer's points (1/72 inch).
+Defaults to the height of the printed area on the screen.
+If both \fB\-pageheight\fR and \fB\-pagewidth\fR are specified then
+the scale factor from \fB\-pagewidth\fR is used (non-uniform scaling
+is not implemented).
+.TP
+\fB\-pagewidth \fIsize\fR
+.
+Specifies that the Postscript should be scaled in both x and y so
+that the printed area is \fIsize\fR wide on the Postscript page.
+\fISize\fR has the same form as for \fB\-pageheight\fR.
+Defaults to the width of the printed area on the screen.
+If both \fB\-pageheight\fR and \fB\-pagewidth\fR are specified then
+the scale factor from \fB\-pagewidth\fR is used (non-uniform scaling
+is not implemented).
+.TP
+\fB\-pagex \fIposition\fR
+.
+\fIPosition\fR gives the x-coordinate of the positioning point on
+the Postscript page, using any of the forms allowed for \fB\-pageheight\fR.
+Used in conjunction with the \fB\-pagey\fR and \fB\-pageanchor\fR options
+to determine where the printed area appears on the Postscript page.
+Defaults to the center of the page.
+.TP
+\fB\-pagey \fIposition\fR
+.
+\fIPosition\fR gives the y-coordinate of the positioning point on
+the Postscript page, using any of the forms allowed for \fB\-pageheight\fR.
+Used in conjunction with the \fB\-pagex\fR and \fB\-pageanchor\fR options
+to determine where the printed area appears on the Postscript page.
+Defaults to the center of the page.
+.TP
+\fB\-rotate \fIboolean\fR
+.
+\fIBoolean\fR specifies whether the printed area is to be rotated 90
+degrees.
+In non-rotated output the x-axis of the printed area runs along
+the short dimension of the page
+.PQ portrait " orientation" ;
+in rotated output the x-axis runs along the long dimension of the page
+.PQ landscape " orientation" .
+Defaults to non-rotated.
+.TP
+\fB\-width \fIsize\fR
+.
+Specifies the width of the area of the canvas to print.
+Defaults to the width of the canvas window.
+.TP
+\fB\-x \fIposition\fR
+.
+Specifies the x-coordinate of the left edge of the area of the
+canvas that is to be printed, in canvas coordinates, not window
+coordinates.
+Defaults to the coordinate of the left edge of the window.
+.TP
+\fB\-y \fIposition\fR
+.
+Specifies the y-coordinate of the top edge of the area of the
+canvas that is to be printed, in canvas coordinates, not window
+coordinates.
+Defaults to the coordinate of the top edge of the window.
+.RE
+.TP
+\fIpathName \fBraise \fItagOrId \fR?\fIaboveThis\fR?
+.
+Move all of the items given by \fItagOrId\fR to a new position
+in the display list just after the item given by \fIaboveThis\fR.
+If \fItagOrId\fR refers to more than one item then all are moved
+but the relative order of the moved items will not be changed.
+\fIAboveThis\fR is a tag or id; if it refers to more than one
+item then the last (topmost) of these items in the display list is used
+as the destination location for the moved items.
+This command returns an empty string.
+.RS
+.PP
+Note: this command has no effect on window items. Window items always
+obscure other item types, and the stacking order of window items is
+determined by the \fBraise\fR command and \fBlower\fR command, not the
+\fBraise\fR widget command and \fBlower\fR widget command for canvases.
+.RE
+.TP
+\fIpathName \fBrchars \fItagOrId first last string\fR
+.VS 8.6
+This command causes the text or coordinates between \fIfirst\fR and \fIlast\fR
+for each of the items indicated by \fItagOrId\fR to be replaced by
+\fIstring\fR. Each item interprets \fIfirst\fR and \fIlast\fR independently
+according to the rules described in \fBINDICES\fR above. Out of the standard
+set of items, text items support this operation by altering their text as
+directed, and line and polygon items support this operation by altering their
+coordinate list (in which case \fIstring\fR should be a list of coordinates to
+use as a replacement). The other items ignore this operation.
+.VE 8.6
+.TP
+\fIpathName \fBscale \fItagOrId xOrigin yOrigin xScale yScale\fR
+.
+Rescale the coordinates of all of the items given by \fItagOrId\fR in canvas
+coordinate space.
+\fIXOrigin\fR and \fIyOrigin\fR identify the origin for the scaling
+operation and \fIxScale\fR and \fIyScale\fR identify the scale
+factors for x- and y-coordinates, respectively (a scale factor of
+1.0 implies no change to that coordinate).
+For each of the points defining each item, the x-coordinate is
+adjusted to change the distance from \fIxOrigin\fR by a factor
+of \fIxScale\fR.
+Similarly, each y-coordinate is adjusted to change the distance
+from \fIyOrigin\fR by a factor of \fIyScale\fR.
+This command returns an empty string.
+.RS
+.PP
+Note that some items have only a single pair of coordinates (e.g., text,
+images and windows) and so scaling of them by this command can only move them
+around.
+.RE
+.TP
+\fIpathName \fBscan\fR \fIoption args\fR
+.
+This command is used to implement scanning on canvases. It has
+two forms, depending on \fIoption\fR:
+.RS
+.TP
+\fIpathName \fBscan mark \fIx y\fR
+.
+Records \fIx\fR and \fIy\fR and the canvas's current view; used
+in conjunction with later \fBscan dragto\fR commands.
+Typically this command is associated with a mouse button press in
+the widget and \fIx\fR and \fIy\fR are the coordinates of the
+mouse. It returns an empty string.
+.TP
+\fIpathName \fBscan dragto \fIx y ?gain?\fR
+.
+This command computes the difference between its \fIx\fR and \fIy\fR
+arguments (which are typically mouse coordinates) and the \fIx\fR and
+\fIy\fR arguments to the last \fBscan mark\fR command for the widget.
+It then adjusts the view by \fIgain\fR times the
+difference in coordinates, where \fIgain\fR defaults to 10.
+This command is typically associated
+with mouse motion events in the widget, to produce the effect of
+dragging the canvas at high speed through its window. The return
+value is an empty string.
+.RE
+.TP
+\fIpathName \fBselect \fIoption\fR ?\fItagOrId arg\fR?
+.
+Manipulates the selection in one of several ways, depending on
+\fIoption\fR.
+The command may take any of the forms described below.
+In all of the descriptions below, \fItagOrId\fR must refer to
+an item that supports indexing and selection; if it refers to
+multiple items then the first of
+these that supports indexing and the selection is used.
+\fIIndex\fR gives a textual description of a position
+within \fItagOrId\fR, as described in \fBINDICES\fR above.
+.RS
+.TP
+\fIpathName \fBselect adjust \fItagOrId index\fR
+.
+Locate the end of the selection in \fItagOrId\fR nearest
+to the character given by \fIindex\fR, and adjust that
+end of the selection to be at \fIindex\fR (i.e. including
+but not going beyond \fIindex\fR).
+The other end of the selection is made the anchor point
+for future \fBselect to\fR commands.
+If the selection is not currently in \fItagOrId\fR then
+this command behaves the same as the \fBselect to\fR widget
+command.
+Returns an empty string.
+.TP
+\fIpathName \fBselect clear\fR
+.
+Clear the selection if it is in this widget.
+If the selection is not in this widget then the command
+has no effect.
+Returns an empty string.
+.TP
+\fIpathName \fBselect from \fItagOrId index\fR
+.
+Set the selection anchor point for the widget to be just
+before the character
+given by \fIindex\fR in the item given by \fItagOrId\fR.
+This command does not change the selection; it just sets
+the fixed end of the selection for future \fBselect to\fR
+commands.
+Returns an empty string.
+.TP
+\fIpathName \fBselect item\fR
+.
+Returns the id of the selected item, if the selection is in an
+item in this canvas.
+If the selection is not in this canvas then an empty string
+is returned.
+.TP
+\fIpathName \fBselect to \fItagOrId index\fR
+.
+Set the selection to consist of those characters of \fItagOrId\fR
+between the selection anchor point and
+\fIindex\fR.
+The new selection will include the character given by \fIindex\fR;
+it will include the character given by the anchor point only if
+\fIindex\fR is greater than or equal to the anchor point.
+The anchor point is determined by the most recent \fBselect adjust\fR
+or \fBselect from\fR command for this widget.
+If the selection anchor point for the widget is not currently in
+\fItagOrId\fR, then it is set to the same character given
+by \fIindex\fR.
+Returns an empty string.
+.RE
+.TP
+\fIpathName \fBtype\fI tagOrId\fR
+.
+Returns the type of the item given by \fItagOrId\fR, such as
+\fBrectangle\fR or \fBtext\fR.
+If \fItagOrId\fR refers to more than one item, then the type
+of the first item in the display list is returned.
+If \fItagOrId\fR does not refer to any items at all then
+an empty string is returned.
+.TP
+\fIpathName \fBxview \fR?\fIargs\fR?
+.
+This command is used to query and change the horizontal position of the
+information displayed in the canvas's window.
+It can take any of the following forms:
+.RS
+.TP
+\fIpathName \fBxview\fR
+.
+Returns a list containing two elements.
+Each element is a real fraction between 0 and 1; together they describe
+the horizontal span that is visible in the window.
+For example, if the first element is .2 and the second element is .6,
+20% of the canvas's area (as defined by the \fB\-scrollregion\fR option)
+is off-screen to the left, the middle 40% is visible
+in the window, and 40% of the canvas is off-screen to the right.
+These are the same values passed to scrollbars via the \fB\-xscrollcommand\fR
+option.
+.TP
+\fIpathName \fBxview moveto\fI fraction\fR
+.
+Adjusts the view in the window so that \fIfraction\fR of the
+total width of the canvas is off-screen to the left.
+\fIFraction\fR must be a fraction between 0 and 1.
+.TP
+\fIpathName \fBxview scroll \fInumber what\fR
+.
+This command shifts the view in the window left or right according to
+\fInumber\fR and \fIwhat\fR.
+\fINumber\fR must be an integer.
+\fIWhat\fR must be either \fBunits\fR or \fBpages\fR or an abbreviation
+of one of these.
+If \fIwhat\fR is \fBunits\fR, the view adjusts left or right in units
+of the \fBxScrollIncrement\fR option, if it is greater than zero,
+or in units of one-tenth the window's width otherwise.
+If \fIwhat is \fBpages\fR then the view
+adjusts in units of nine-tenths the window's width.
+If \fInumber\fR is negative then information farther to the left
+becomes visible; if it is positive then information farther to the right
+becomes visible.
+.RE
+.TP
+\fIpathName \fByview \fI?args\fR?
+.
+This command is used to query and change the vertical position of the
+information displayed in the canvas's window.
+It can take any of the following forms:
+.RS
+.TP
+\fIpathName \fByview\fR
+.
+Returns a list containing two elements.
+Each element is a real fraction between 0 and 1; together they describe
+the vertical span that is visible in the window.
+For example, if the first element is .6 and the second element is 1.0,
+the lowest 40% of the canvas's area (as defined by the \fB\-scrollregion\fR
+option) is visible in the window.
+These are the same values passed to scrollbars via the \fB\-yscrollcommand\fR
+option.
+.TP
+\fIpathName \fByview moveto\fI fraction\fR
+.
+Adjusts the view in the window so that \fIfraction\fR of the canvas's
+area is off-screen to the top.
+\fIFraction\fR is a fraction between 0 and 1.
+.TP
+\fIpathName \fByview scroll \fInumber what\fR
+.
+This command adjusts the view in the window up or down according to
+\fInumber\fR and \fIwhat\fR.
+\fINumber\fR must be an integer.
+\fIWhat\fR must be either \fBunits\fR or \fBpages\fR.
+If \fIwhat\fR is \fBunits\fR, the view adjusts up or down in units
+of the \fByScrollIncrement\fR option, if it is greater than zero,
+or in units of one-tenth the window's height otherwise.
+If \fIwhat\fR is \fBpages\fR then
+the view adjusts in units of nine-tenths the window's height.
+If \fInumber\fR is negative then higher information becomes
+visible; if it is positive then lower information
+becomes visible.
+.RE
+.SH "OVERVIEW OF ITEM TYPES"
+.PP
+The sections below describe the various types of items supported
+by canvas widgets. Each item type is characterized by two things:
+first, the form of the \fBcreate\fR command used to create
+instances of the type; and second, a set of configuration options
+for items of that type, which may be used in the
+\fBcreate\fR and \fBitemconfigure\fR widget commands.
+Most items do not support indexing or selection or the commands
+related to them, such as \fBindex\fR and \fBinsert\fR.
+Where items do support these facilities, it is noted explicitly
+in the descriptions below.
+At present, text, line and polygon items provide this support.
+For lines and polygons the indexing facility is used to manipulate
+the coordinates of the item.
+.SS "COMMON ITEM OPTIONS"
+.PP
+Many items share a common set of options. These options are
+explained here, and then referred to be each widget type for brevity.
+.TP
+\fB\-anchor \fIanchorPos\fR
+.
+\fIAnchorPos\fR tells how to position the item relative to the
+positioning point for the item; it may have any of the forms
+accepted by \fBTk_GetAnchor\fR. For example, if \fIanchorPos\fR
+is \fBcenter\fR then the item is centered on the point; if
+\fIanchorPos\fR is \fBn\fR then the item will be drawn so that
+its top center point is at the positioning point.
+This option defaults to \fBcenter\fR.
+.TP
+\fB\-dash \fIpattern\fR
+.TP
+\fB\-activedash \fIpattern\fR
+.TP
+\fB\-disableddash \fIpattern\fR
+.
+This option specifies dash patterns for the normal, active
+state, and disabled state of an item.
+\fIpattern\fR may have any of the forms accepted by \fBTk_GetDash\fR.
+If the dash options are omitted then the default is a solid outline.
+See \fBDASH PATTERNS\fR for more information.
+.TP
+\fB\-dashoffset \fIoffset\fR
+.
+The starting \fIoffset\fR in pixels into the pattern provided by the
+\fB\-dash\fR option. \fB\-dashoffset\fR is ignored if there is no
+\fB\-dash\fR pattern. The \fIoffset\fR may have any of the forms described
+in the \fBCOORDINATES\fR section above.
+.TP
+\fB\-fill \fIcolor\fR
+.TP
+\fB\-activefill \fIcolor\fR
+.TP
+\fB\-disabledfill \fIcolor\fR
+.
+Specifies the color to be used to fill item's area.
+in its normal, active, and disabled states,
+\fIColor\fR may have any of the forms accepted by \fBTk_GetColor\fR.
+If \fIcolor\fR is an empty string (the default),
+then the item will not be filled.
+For the line item, it specifies the color of the line drawn.
+For the text item, it specifies the foreground color of the text.
+.TP
+\fB\-outline \fIcolor\fR
+.TP
+\fB\-activeoutline \fIcolor\fR
+.TP
+\fB\-disabledoutline \fIcolor\fR
+.
+This option specifies the color that should be used to draw the
+outline of the item in its normal, active and disabled states.
+\fIColor\fR may have any of the forms accepted by \fBTk_GetColor\fR.
+This option defaults to \fBblack\fR. If \fIcolor\fR is specified
+as an empty string then no outline is drawn for the item.
+.TP
+\fB\-offset \fIoffset\fR
+.
+Specifies the offset of stipples. The offset value can be of the form
+\fBx,y\fR or \fIside\fR, where side can be \fBn\fR, \fBne\fR, \fBe\fR,
+\fBse\fR, \fBs\fR, \fBsw\fR, \fBw\fR, \fBnw\fR, or \fBcenter\fR. In the
+first case the origin is the origin of the toplevel of the current window.
+For the canvas itself and canvas objects the origin is the canvas origin,
+but putting \fB#\fR in front of the coordinate pair indicates using the
+toplevel origin instead. For canvas objects, the \fB\-offset\fR option is
+used for stippling as well. For the line and polygon canvas items you can
+also specify an index as argument, which connects the stipple origin to one
+of the coordinate points of the line/polygon. Note that stipple offsets are
+\fIonly supported on X11\fR; they are silently ignored on other platforms.
+.TP
+\fB\-outlinestipple \fIbitmap\fR
+.TP
+\fB\-activeoutlinestipple \fIbitmap\fR
+.TP
+\fB\-disabledoutlinestipple \fIbitmap\fR
+.
+This option specifies stipple patterns that should be used to draw the
+outline of the item in its normal, active and disabled states.
+Indicates that the outline for the item should be drawn with a stipple pattern;
+\fIbitmap\fR specifies the stipple pattern to use, in any of the
+forms accepted by \fBTk_GetBitmap\fR.
+If the \fB\-outline\fR option has not been specified then this option
+has no effect.
+If \fIbitmap\fR is an empty string (the default), then the outline is drawn
+in a solid fashion.
+\fINote that stipples are not well supported on platforms that do not
+use X11 as their drawing API.\fR
+.TP
+\fB\-outlineoffset \fIoffset\fR
+.
+Specifies the offset of the stipple pattern used for outlines, in the same way
+that the \fB\-outline\fR option controls fill stipples. (See the
+\fB\-outline\fR option for a description of the syntax of \fIoffset\fR.)
+.TP
+\fB\-stipple \fIbitmap\fR
+.TP
+\fB\-activestipple \fIbitmap\fR
+.TP
+\fB\-disabledstipple \fIbitmap\fR
+.
+This option specifies stipple patterns that should be used to fill
+the item in its normal, active and disabled states.
+\fIbitmap\fR specifies the stipple pattern to use, in any of the
+forms accepted by \fBTk_GetBitmap\fR.
+If the \fB\-fill\fR option has not been specified then this option
+has no effect.
+If \fIbitmap\fR is an empty string (the default), then filling is done
+in a solid fashion.
+For the text item, it affects the actual text.
+\fINote that stipples are not well supported on platforms that do not
+use X11 as their drawing API.\fR
+.TP
+\fB\-state \fIstate\fR
+.
+This allows an item to override the canvas widget's global \fIstate\fR
+option. It takes the same values:
+\fInormal\fR, \fIdisabled\fR or \fIhidden\fR.
+.TP
+\fB\-tags \fItagList\fR
+.
+Specifies a set of tags to apply to the item.
+\fITagList\fR consists of a list of tag names, which replace any
+existing tags for the item. \fITagList\fR may be an empty list.
+.TP
+\fB\-width \fIoutlineWidth\fR
+.TP
+\fB\-activewidth \fIoutlineWidth\fR
+.TP
+\fB\-disabledwidth \fIoutlineWidth\fR
+.
+Specifies the width of the outline to be drawn around
+the item's region, in its normal, active and disabled states.
+\fIoutlineWidth\fR may be in any of the forms described in the
+\fBCOORDINATES\fR section above.
+If the \fB\-outline\fR option has been specified as an empty string then
+this option has no effect. This option defaults to 1.0.
+For arcs, wide outlines will be drawn centered on the edges of the
+arc's region.
+.SH "STANDARD ITEM TYPES"
+.SS "ARC ITEMS"
+.PP
+Items of type \fBarc\fR appear on the display as arc-shaped regions.
+An arc is a section of an oval delimited by two angles (specified
+by the \fB\-start\fR and \fB\-extent\fR options) and displayed in
+one of several ways (specified by the \fB\-style\fR option).
+Arcs are created with widget commands of the following form:
+.CS
+\fIpathName \fBcreate arc \fIx1 y1 x2 y2 \fR?\fIoption value ...\fR?
+\fIpathName \fBcreate arc \fIcoordList\fR ?\fIoption value ...\fR?
+.CE
+The arguments \fIx1\fR, \fIy1\fR, \fIx2\fR, and \fIy2\fR or \fIcoordList\fR give
+the coordinates of two diagonally opposite corners of a
+rectangular region enclosing the oval that defines the arc.
+After the coordinates there may be any number of \fIoption\fR\-\fIvalue\fR
+pairs, each of which sets one of the configuration options
+for the item. These same \fIoption\fR\-\fIvalue\fR pairs may be
+used in \fBitemconfigure\fR widget commands to change the item's
+configuration. An arc item becomes the current item when the mouse pointer is
+over any part that is painted or (when fully transparent) that would be
+painted if both the \fB\-fill\fR and \fB\-outline\fR options were non-empty.
+.PP
+The following standard options are supported by arcs:
+.DS
+.ta 3i
+\fB\-dash\fR \fB\-activedash\fR
+\fB\-disableddash\fR \fB\-dashoffset\fR
+\fB\-fill\fR \fB\-activefill\fR
+\fB\-disabledfill\fR \fB\-offset\fR
+\fB\-outline\fR \fB\-activeoutline\fR
+\fB\-disabledoutline\fR \fB\-outlineoffset\fR
+\fB\-outlinestipple\fR \fB\-activeoutlinestipple\fR
+\fB\-disabledoutlinestipple\fR \fB\-stipple\fR
+\fB\-activestipple\fR \fB\-disabledstipple\fR
+\fB\-state\fR \fB\-tags\fR
+\fB\-width\fR \fB\-activewidth\fR
+\fB\-disabledwidth\fR
+.DE
+The following extra options are supported for arcs:
+.TP
+\fB\-extent \fIdegrees\fR
+Specifies the size of the angular range occupied by the arc.
+The arc's range extends for \fIdegrees\fR degrees counter-clockwise
+from the starting angle given by the \fB\-start\fR option.
+\fIDegrees\fR may be negative.
+If it is greater than 360 or less than \-360, then \fIdegrees\fR
+modulo 360 is used as the extent.
+.TP
+\fB\-start \fIdegrees\fR
+Specifies the beginning of the angular range occupied by the
+arc.
+\fIDegrees\fR is given in units of degrees measured counter-clockwise
+from the 3-o'clock position; it may be either positive or negative.
+.TP
+\fB\-style \fItype\fR
+Specifies how to draw the arc. If \fItype\fR is \fBpieslice\fR
+(the default) then the arc's region is defined by a section
+of the oval's perimeter plus two line segments, one between the center
+of the oval and each end of the perimeter section.
+If \fItype\fR is \fBchord\fR then the arc's region is defined
+by a section of the oval's perimeter plus a single line segment
+connecting the two end points of the perimeter section.
+If \fItype\fR is \fBarc\fR then the arc's region consists of
+a section of the perimeter alone.
+In this last case the \fB\-fill\fR option is ignored.
+.SS "BITMAP ITEMS"
+.PP
+Items of type \fBbitmap\fR appear on the display as images with
+two colors, foreground and background.
+Bitmaps are created with widget commands of the following form:
+.CS
+\fIpathName \fBcreate bitmap \fIx y \fR?\fIoption value ...\fR?
+\fIpathName \fBcreate bitmap \fIcoordList\fR ?\fIoption value ...\fR?
+.CE
+The arguments \fIx\fR and \fIy\fR or \fIcoordList\fR (which must have two
+elements) specify the coordinates of a
+point used to position the bitmap on the display, as controlled by the
+\fB\-anchor\fR option.
+After the coordinates there may be any number of \fIoption\fR\-\fIvalue\fR
+pairs, each of which sets one of the configuration options
+for the item. These same \fIoption\fR\-\fIvalue\fR pairs may be
+used in \fBitemconfigure\fR widget commands to change the item's
+configuration. A bitmap item becomes the current item when the mouse pointer
+is over any part of its bounding box.
+.PP
+The following standard options are supported by bitmaps:
+.DS
+.ta 3i
+\fB\-anchor\fR \fB\-state\fR
+\fB\-tags\fR
+.DE
+The following extra options are supported for bitmaps:
+.TP
+\fB\-background \fIcolor\fR
+.TP
+\fB\-activebackground \fIcolor\fR
+.TP
+\fB\-disabledbackground \fIcolor\fR
+Specifies the color to use for each of the bitmap's
+.QW 0
+valued pixels in its normal, active and disabled states.
+\fIColor\fR may have any of the forms accepted by \fBTk_GetColor\fR.
+If this option is not specified, or if it is specified as an empty
+string, then nothing is displayed where the bitmap pixels are 0; this
+produces a transparent effect.
+.TP
+\fB\-bitmap \fIbitmap\fR
+.TP
+\fB\-activebitmap \fIbitmap\fR
+.TP
+\fB\-disabledbitmap \fIbitmap\fR
+Specifies the bitmaps to display in the item in its normal, active and
+disabled states.
+\fIBitmap\fR may have any of the forms accepted by \fBTk_GetBitmap\fR.
+.TP
+\fB\-foreground \fIcolor\fR
+.TP
+\fB\-activeforeground \fIcolor\fR
+.TP
+\fB\-disabledforeground \fIcolor\fR
+Specifies the color to use for each of the bitmap's
+.QW 1
+valued pixels in its normal, active and disabled states.
+\fIColor\fR may have any of the forms accepted by \fBTk_GetColor\fR and
+defaults to \fBblack\fR.
+.SS "IMAGE ITEMS"
+.PP
+Items of type \fBimage\fR are used to display images on a
+canvas.
+Images are created with widget commands of the following form:
+.CS
+\fIpathName \fBcreate image \fIx y \fR?\fIoption value ...\fR?
+\fIpathName \fBcreate image \fIcoordList\fR ?\fIoption value ...\fR?
+.CE
+The arguments \fIx\fR and \fIy\fR or \fIcoordList\fR specify the coordinates of a
+point used to position the image on the display, as controlled by the
+\fB\-anchor\fR option.
+After the coordinates there may be any number of \fIoption\fR\-\fIvalue\fR
+pairs, each of which sets one of the configuration options
+for the item. These same \fIoption\fR\-\fIvalue\fR pairs may be
+used in \fBitemconfigure\fR widget commands to change the item's
+configuration. An image item becomes the current item when the mouse pointer
+is over any part of its bounding box.
+.PP
+The following standard options are supported by images:
+.DS
+.ta 3i
+\fB\-anchor\fR \fB\-state\fR
+\fB\-tags\fR
+.DE
+The following extra options are supported for images:
+.TP
+\fB\-image \fIname\fR
+.TP
+\fB\-activeimage \fIname\fR
+.TP
+\fB\-disabledimage \fIname\fR
+Specifies the name of the images to display in the item in is normal,
+active and disabled states.
+This image must have been created previously with the
+\fBimage create\fR command.
+.SS "LINE ITEMS"
+.PP
+Items of type \fBline\fR appear on the display as one or more connected
+line segments or curves.
+Line items support coordinate indexing operations using the \fBdchars\fR,
+\fBindex\fR and \fBinsert\fR widget commands.
+Lines are created with widget commands of the following form:
+.CS
+\fIpathName \fBcreate line \fIx1 y1... xn yn \fR?\fIoption value ...\fR?
+\fIpathName \fBcreate line \fIcoordList\fR ?\fIoption value ...\fR?
+.CE
+The arguments \fIx1\fR through \fIyn\fR or \fIcoordList\fR give
+the coordinates for a series of two or more points that describe
+a series of connected line segments.
+After the coordinates there may be any number of \fIoption\fR\-\fIvalue\fR
+pairs, each of which sets one of the configuration options
+for the item. These same \fIoption\fR\-\fIvalue\fR pairs may be
+used in \fBitemconfigure\fR widget commands to change the item's
+configuration. A line item is the current item whenever the mouse pointer is
+over any segment of the line, whether drawn or not and whether or not the line
+is smoothed.
+.PP
+The following standard options are supported by lines:
+.DS
+.ta 3i
+\fB\-dash\fR \fB\-activedash\fR
+\fB\-disableddash\fR \fB\-dashoffset\fR
+\fB\-fill\fR \fB\-activefill\fR
+\fB\-disabledfill\fR \fB\-stipple\fR
+\fB\-activestipple\fR \fB\-disabledstipple\fR
+\fB\-state\fR \fB\-tags\fR
+\fB\-width\fR \fB\-activewidth\fR
+\fB\-disabledwidth\fR
+.DE
+The following extra options are supported for lines:
+.TP
+\fB\-arrow \fIwhere\fR
+Indicates whether or not arrowheads are to be drawn at one or both
+ends of the line.
+\fIWhere\fR must have one of the values \fBnone\fR (for no arrowheads),
+\fBfirst\fR (for an arrowhead at the first point of the line),
+\fBlast\fR (for an arrowhead at the last point of the line), or
+\fBboth\fR (for arrowheads at both ends).
+This option defaults to \fBnone\fR.
+.TP
+\fB\-arrowshape \fIshape\fR
+This option indicates how to draw arrowheads.
+The \fIshape\fR argument must be a list with three elements, each
+specifying a distance in any of the forms described in
+the \fBCOORDINATES\fR section above.
+The first element of the list gives the distance along the line
+from the neck of the arrowhead to its tip.
+The second element gives the distance along the line from the
+trailing points of the arrowhead to the tip, and the third
+element gives the distance from the outside edge of the line to the
+trailing points.
+If this option is not specified then Tk picks a
+.QW reasonable
+shape.
+.TP
+\fB\-capstyle \fIstyle\fR
+Specifies the ways in which caps are to be drawn at the endpoints
+of the line.
+\fIStyle\fR may have any of the forms accepted by \fBTk_GetCapStyle\fR
+(\fBbutt\fR, \fBprojecting\fR, or \fBround\fR).
+If this option is not specified then it defaults to \fBbutt\fR.
+Where arrowheads are drawn the cap style is ignored.
+.TP
+\fB\-joinstyle \fIstyle\fR
+Specifies the ways in which joints are to be drawn at the vertices
+of the line.
+\fIStyle\fR may have any of the forms accepted by \fBTk_GetJoinStyle\fR
+(\fBbevel\fR, \fBmiter\fR, or \fBround\fR).
+If this option is not specified then it defaults to \fBround\fR.
+If the line only contains two points then this option is
+irrelevant.
+.TP
+\fB\-smooth \fIsmoothMethod\fR
+\fIsmoothMethod\fR must have one of the forms accepted by
+\fBTcl_GetBoolean\fR or a line smoothing method.
+Only \fBtrue\fR and \fBraw\fR are
+supported in the core (with \fBbezier\fR being an alias for \fBtrue\fR), but more can be added at runtime. If a boolean
+false value or empty string is given, no smoothing is applied. A boolean
+truth value assumes \fBtrue\fR smoothing.
+If the smoothing method is \fBtrue\fR, this indicates that the line
+should be drawn as a curve, rendered as a set of quadratic splines: one spline
+is drawn for the first and second line segments, one for the second
+and third, and so on. Straight-line segments can be generated within
+a curve by duplicating the end-points of the desired line segment.
+If the smoothing method is \fBraw\fR, this indicates that the line
+should also be drawn as a curve but where the list of coordinates is
+such that the first coordinate pair (and every third coordinate pair
+thereafter) is a knot point on a cubic Bezier curve, and the other
+coordinates are control points on the cubic Bezier curve. Straight
+line segments can be generated within a curve by making control points
+equal to their neighbouring knot points. If the last point is a
+control point and not a knot point, the point is repeated (one or two
+times) so that it also becomes a knot point.
+.TP
+\fB\-splinesteps \fInumber\fR
+Specifies the degree of smoothness desired for curves: each spline
+will be approximated with \fInumber\fR line segments. This
+option is ignored unless the \fB\-smooth\fR option is true or \fBraw\fR.
+.SS "OVAL ITEMS"
+.PP
+Items of type \fBoval\fR appear as circular or oval regions on
+the display. Each oval may have an outline, a fill, or
+both. Ovals are created with widget commands of the
+following form:
+.CS
+\fIpathName \fBcreate oval \fIx1 y1 x2 y2 \fR?\fIoption value ...\fR?
+\fIpathName \fBcreate oval \fIcoordList\fR ?\fIoption value ...\fR?
+.CE
+The arguments \fIx1\fR, \fIy1\fR, \fIx2\fR, and \fIy2\fR or \fIcoordList\fR give
+the coordinates of two diagonally opposite corners of a
+rectangular region enclosing the oval.
+The oval will include the top and left edges of the rectangle
+not the lower or right edges.
+If the region is square then the resulting oval is circular;
+otherwise it is elongated in shape.
+After the coordinates there may be any number of \fIoption\fR\-\fIvalue\fR
+pairs, each of which sets one of the configuration options
+for the item. These same \fIoption\fR\-\fIvalue\fR pairs may be
+used in \fBitemconfigure\fR widget commands to change the item's
+configuration. An oval item becomes the current item when the mouse pointer is
+over any part that is painted or (when fully transparent) that would be
+painted if both the \fB\-fill\fR and \fB\-outline\fR options were non-empty.
+.PP
+The following standard options are supported by ovals:
+.DS
+.ta 3i
+\fB\-dash\fR \fB\-activedash\fR
+\fB\-disableddash\fR \fB\-dashoffset\fR
+\fB\-fill\fR \fB\-activefill\fR
+\fB\-disabledfill\fR \fB\-offset\fR
+\fB\-outline\fR \fB\-activeoutline\fR
+\fB\-disabledoutline\fR \fB\-outlineoffset\fR
+\fB\-outlinestipple\fR \fB\-activeoutlinestipple\fR
+\fB\-disabledoutlinestipple\fR \fB\-stipple\fR
+\fB\-activestipple\fR \fB\-disabledstipple\fR
+\fB\-state\fR \fB\-tags\fR
+\fB\-width\fR \fB\-activewidth\fR
+\fB\-disabledwidth\fR
+.DE
+There are no oval-specific options.
+.SS "POLYGON ITEMS"
+.PP
+Items of type \fBpolygon\fR appear as polygonal or curved filled regions
+on the display.
+Polygon items support coordinate indexing operations using the \fBdchars\fR,
+\fBindex\fR and \fBinsert\fR widget commands.
+Polygons are created with widget commands of the following form:
+.CS
+\fIpathName \fBcreate polygon \fIx1 y1 ... xn yn \fR?\fIoption value ...\fR?
+\fIpathName \fBcreate polygon \fIcoordList\fR ?\fIoption value ...\fR?
+.CE
+The arguments \fIx1\fR through \fIyn\fR or \fIcoordList\fR specify the coordinates for
+three or more points that define a polygon.
+The first point should not be repeated as the last to
+close the shape; Tk will automatically close the periphery between
+the first and last points.
+After the coordinates there may be any number of \fIoption\fR\-\fIvalue\fR
+pairs, each of which sets one of the configuration options
+for the item. These same \fIoption\fR\-\fIvalue\fR pairs may be
+used in \fBitemconfigure\fR widget commands to change the item's
+configuration. A polygon item is the current item whenever the mouse pointer
+is over any part of the polygon, whether drawn or not and whether or not the
+outline is smoothed.
+.PP
+The following standard options are supported by polygons:
+.DS
+.ta 3i
+\fB\-dash\fR \fB\-activedash\fR
+\fB\-disableddash\fR \fB\-dashoffset\fR
+\fB\-fill\fR \fB\-activefill\fR
+\fB\-disabledfill\fR \fB\-offset\fR
+\fB\-outline\fR \fB\-activeoutline\fR
+\fB\-disabledoutline\fR \fB\-outlineoffset\fR
+\fB\-outlinestipple\fR \fB\-activeoutlinestipple\fR
+\fB\-disabledoutlinestipple\fR \fB\-stipple\fR
+\fB\-activestipple\fR \fB\-disabledstipple\fR
+\fB\-state\fR \fB\-tags\fR
+\fB\-width\fR \fB\-activewidth\fR
+\fB\-disabledwidth\fR
+.DE
+The following extra options are supported for polygons:
+.TP
+\fB\-joinstyle \fIstyle\fR
+Specifies the ways in which joints are to be drawn at the vertices
+of the outline.
+\fIStyle\fR may have any of the forms accepted by \fBTk_GetJoinStyle\fR
+(\fBbevel\fR, \fBmiter\fR, or \fBround\fR).
+If this option is not specified then it defaults to \fBround\fR.
+.TP
+\fB\-smooth \fIboolean\fR
+\fIBoolean\fR must have one of the forms accepted by \fBTcl_GetBoolean\fR
+or a line smoothing method. Only \fBtrue\fR and \fBraw\fR are
+supported in the core (with \fBbezier\fR being an alias for \fBtrue\fR), but more can be added at runtime. If a boolean
+false value or empty string is given, no smoothing is applied. A boolean
+truth value assumes \fBtrue\fR smoothing.
+If the smoothing method is \fBtrue\fR, this indicates that the polygon
+should be drawn as a curve, rendered as a set of quadratic splines: one spline
+is drawn for the first and second line segments, one for the second
+and third, and so on. Straight-line segments can be generated within
+a curve by duplicating the end-points of the desired line segment.
+If the smoothing method is \fBraw\fR, this indicates that the polygon
+should also be drawn as a curve but where the list of coordinates is
+such that the first coordinate pair (and every third coordinate pair
+thereafter) is a knot point on a cubic Bezier curve, and the other
+coordinates are control points on the cubic Bezier curve. Straight
+line segments can be venerated within a curve by making control points
+equal to their neighbouring knot points. If the last point is not the
+second point of a pair of control points, the point is repeated (one or two
+times) so that it also becomes the second point of a pair of control
+points (the associated knot point will be the first control point).
+.TP
+\fB\-splinesteps \fInumber\fR
+Specifies the degree of smoothness desired for curves: each spline
+will be approximated with \fInumber\fR line segments. This
+option is ignored unless the \fB\-smooth\fR option is true or \fBraw\fR.
+.PP
+Polygon items are different from other items such as rectangles, ovals
+and arcs in that interior points are considered to be
+.QW inside
+a polygon (e.g. for purposes of the \fBfind closest\fR and
+\fBfind overlapping\fR widget commands) even if it is not filled.
+For most other item types, an
+interior point is considered to be inside the item only if the item
+is filled or if it has neither a fill nor an outline. If you would
+like an unfilled polygon whose interior points are not considered
+to be inside the polygon, use a line item instead.
+.SS "RECTANGLE ITEMS"
+.PP
+Items of type \fBrectangle\fR appear as rectangular regions on
+the display. Each rectangle may have an outline, a fill, or
+both. Rectangles are created with widget commands of the
+following form:
+.CS
+\fIpathName \fBcreate rectangle \fIx1 y1 x2 y2 \fR?\fIoption value ...\fR?
+\fIpathName \fBcreate rectangle \fIcoordList\fR ?\fIoption value ...\fR?
+.CE
+The arguments \fIx1\fR, \fIy1\fR, \fIx2\fR, and \fIy2\fR or \fIcoordList\fR
+(which must have four elements) give
+the coordinates of two diagonally opposite corners of the rectangle
+(the rectangle will include its upper and left edges but not
+its lower or right edges).
+After the coordinates there may be any number of \fIoption\fR\-\fIvalue\fR
+pairs, each of which sets one of the configuration options
+for the item. These same \fIoption\fR\-\fIvalue\fR pairs may be
+used in \fBitemconfigure\fR widget commands to change the item's
+configuration. A rectangle item becomes the current item when the mouse
+pointer is over any part that is painted or (when fully transparent) that
+would be painted if both the \fB\-fill\fR and \fB\-outline\fR options were
+non-empty.
+.PP
+The following standard options are supported by rectangles:
+.DS
+.ta 3i
+\fB\-dash\fR \fB\-activedash\fR
+\fB\-disableddash\fR \fB\-dashoffset\fR
+\fB\-fill\fR \fB\-activefill\fR
+\fB\-disabledfill\fR \fB\-offset\fR
+\fB\-outline\fR \fB\-activeoutline\fR
+\fB\-disabledoutline\fR \fB\-outlineoffset\fR
+\fB\-outlinestipple\fR \fB\-activeoutlinestipple\fR
+\fB\-disabledoutlinestipple\fR \fB\-stipple\fR
+\fB\-activestipple\fR \fB\-disabledstipple\fR
+\fB\-state\fR \fB\-tags\fR
+\fB\-width\fR \fB\-activewidth\fR
+\fB\-disabledwidth\fR
+.DE
+There are no rectangle-specific options.
+.SS "TEXT ITEMS"
+.PP
+A text item displays a string of characters on the screen in one
+or more lines.
+Text items support indexing, editing and selection through the \fBdchars\fR
+widget command, the \fBfocus\fR widget command, the \fBicursor\fR widget
+command, the \fBindex\fR widget command, the \fBinsert\fR widget command, and
+the \fBselect\fR widget command.
+Text items are created with widget commands of the following
+form:
+.CS
+\fIpathName \fBcreate text \fIx y \fR?\fIoption value ...\fR?
+\fIpathName \fBcreate text \fIcoordList\fR ?\fIoption value ...\fR?
+.CE
+The arguments \fIx\fR and \fIy\fR or \fIcoordList\fR (which must have two
+elements) specify the coordinates of a
+point used to position the text on the display (see the options
+below for more information on how text is displayed).
+After the coordinates there may be any number of \fIoption\fR\-\fIvalue\fR
+pairs, each of which sets one of the configuration options
+for the item. These same \fIoption\fR\-\fIvalue\fR pairs may be
+used in \fBitemconfigure\fR widget commands to change the item's
+configuration. A text item becomes the current item when the mouse pointer
+is over any part of its bounding box.
+.PP
+The following standard options are supported by text items:
+.DS
+.ta 3i
+\fB\-anchor\fR \fB\-fill\fR
+\fB\-activefill\fR \fB\-disabledfill\fR
+\fB\-stipple\fR \fB\-activestipple\fR
+\fB\-disabledstipple\fR \fB\-state\fR
+\fB\-tags\fR
+.DE
+The following extra options are supported for text items:
+.TP
+\fB\-angle \fIrotationDegrees\fR
+.VS 8.6
+\fIRotationDegrees\fR tells how many degrees to rotate the text anticlockwise
+about the positioning point for the text; it may have any floating-point value
+from 0.0 to 360.0. For example, if \fIrotationDegrees\fR is \fB90\fR, then the
+text will be drawn vertically from bottom to top.
+This option defaults to \fB0.0\fR.
+.VE 8.6
+.TP
+\fB\-font \fIfontName\fR
+Specifies the font to use for the text item.
+\fIFontName\fR may be any string acceptable to \fBTk_GetFont\fR.
+If this option is not specified, it defaults to a system-dependent
+font.
+.TP
+\fB\-justify \fIhow\fR
+Specifies how to justify the text within its bounding region.
+\fIHow\fR must be one of the values \fBleft\fR, \fBright\fR,
+or \fBcenter\fR.
+This option will only matter if the text is displayed as multiple
+lines.
+If the option is omitted, it defaults to \fBleft\fR.
+.TP
+\fB\-text \fIstring\fR
+\fIString\fR specifies the characters to be displayed in the text item.
+Newline characters cause line breaks.
+The characters in the item may also be changed with the
+\fBinsert\fR and \fBdelete\fR widget commands.
+This option defaults to an empty string.
+.TP
+\fB\-underline \fI\fR
+Specifies the integer index of a character within the text to be
+underlined. 0 corresponds to the first character of the text
+displayed, 1 to the next character, and so on. \-1 means that no
+underline should be drawn (if the whole text item is to be underlined,
+the appropriate font should be used instead).
+.TP
+\fB\-width \fIlineLength\fR
+Specifies a maximum line length for the text, in any of the forms
+described in the \fBCOORDINATES\fR section above.
+If this option is zero (the default) the text is broken into
+lines only at newline characters.
+However, if this option is non-zero then any line that would
+be longer than \fIlineLength\fR is broken just before a space
+character to make the line shorter than \fIlineLength\fR; the
+space character is treated as if it were a newline
+character.
+.SS "WINDOW ITEMS"
+.PP
+Items of type \fBwindow\fR cause a particular window to be displayed
+at a given position on the canvas.
+Window items are created with widget commands of the following form:
+.CS
+\fIpathName \fBcreate window \fIx y \fR?\fIoption value ...\fR?
+\fIpathName \fBcreate window \fIcoordList\fR ?\fIoption value ...\fR?
+.CE
+The arguments \fIx\fR and \fIy\fR or \fIcoordList\fR (which must have two
+elements) specify the coordinates of a
+point used to position the window on the display, as controlled by the
+\fB\-anchor\fR option.
+After the coordinates there may be any number of \fIoption\fR\-\fIvalue\fR
+pairs, each of which sets one of the configuration options
+for the item. These same \fIoption\fR\-\fIvalue\fR pairs may be
+used in \fBitemconfigure\fR widget commands to change the item's
+configuration. Theoretically, a window item becomes the current item when the
+mouse pointer is over any part of its bounding box, but in practice this
+typically does not happen because the mouse pointer ceases to be over the
+canvas at that point.
+.PP
+The following standard options are supported by window items:
+.DS
+.ta 3i
+\fB\-anchor\fR \fB\-state\fR
+\fB\-tags\fR
+.DE
+The following extra options are supported for window items:
+.TP
+\fB\-height \fIpixels\fR
+.
+Specifies the height to assign to the item's window.
+\fIPixels\fR may have any of the
+forms described in the \fBCOORDINATES\fR section above.
+If this option is not specified, or if it is specified as zero,
+then the window is given whatever height it requests internally.
+.TP
+\fB\-width \fIpixels\fR
+.
+Specifies the width to assign to the item's window.
+\fIPixels\fR may have any of the
+forms described in the \fBCOORDINATES\fR section above.
+If this option is not specified, or if it is specified as zero,
+then the window is given whatever width it requests internally.
+.TP
+\fB\-window \fIpathName\fR
+.
+Specifies the window to associate with this item.
+The window specified by \fIpathName\fR must either be a child of
+the canvas widget or a child of some ancestor of the canvas widget.
+\fIPathName\fR may not refer to a top-level window.
+.PP
+Note: due to restrictions in the ways that windows are managed, it is not
+possible to draw other graphical items (such as lines and images) on top
+of window items. A window item always obscures any graphics that
+overlap it, regardless of their order in the display list. Also note that
+window items, unlike other canvas items, are not clipped for display by their
+containing canvas's border, and are instead clipped by the parent widget of
+the window specified by the \fB\-window\fR option; when the parent widget is
+the canvas, this means that the window item can overlap the canvas's border.
+.SH "APPLICATION-DEFINED ITEM TYPES"
+.PP
+It is possible for individual applications to define new item
+types for canvas widgets using C code.
+See the documentation for \fBTk_CreateItemType\fR.
+.SH BINDINGS
+.PP
+In the current implementation, new canvases are not given any
+default behavior: you will have to execute explicit Tcl commands
+to give the canvas its behavior.
+.SH CREDITS
+.PP
+Tk's canvas widget is a blatant ripoff of ideas from Joel Bartlett's
+\fIezd\fR program. \fIEzd\fR provides structured graphics in a Scheme
+environment and preceded canvases by a year or two. Its simple
+mechanisms for placing and animating graphical objects inspired the
+functions of canvases.
+.SH "SEE ALSO"
+bind(n), font(n), image(n), scrollbar(n)
+.SH KEYWORDS
+canvas, widget
+'\" Local Variables:
+'\" mode: nroff
+'\" fill-column: 78
+'\" End:
diff --git a/tk8.6/doc/checkbutton.n b/tk8.6/doc/checkbutton.n
new file mode 100644
index 0000000..bfefca4
--- /dev/null
+++ b/tk8.6/doc/checkbutton.n
@@ -0,0 +1,293 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH checkbutton n 4.4 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+checkbutton \- Create and manipulate 'checkbutton' boolean selection widgets
+.SH SYNOPSIS
+\fBcheckbutton\fI pathName \fR?\fIoptions\fR?
+.SO
+\-activebackground \-disabledforeground \-padx
+\-activeforeground \-font \-pady
+\-anchor \-foreground \-relief
+\-background \-highlightbackground \-takefocus
+\-bitmap \-highlightcolor \-text
+\-borderwidth \-highlightthickness \-textvariable
+\-compound \-image \-underline
+\-cursor \-justify \-wraplength
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-command command Command
+Specifies a Tcl command to associate with the button. This command
+is typically invoked when mouse button 1 is released over the button
+window. The button's global variable (\fB\-variable\fR option) will
+be updated before the command is invoked.
+.OP \-height height Height
+Specifies a desired height for the button.
+If an image or bitmap is being displayed in the button then the value is in
+screen units (i.e. any of the forms acceptable to \fBTk_GetPixels\fR);
+for text it is in lines of text.
+If this option is not specified, the button's desired height is computed
+from the size of the image or bitmap or text being displayed in it.
+.OP \-indicatoron indicatorOn IndicatorOn
+Specifies whether or not the indicator should be drawn. Must be a
+proper boolean value. If false, the \fB\-relief\fR option is
+ignored and the widget's relief is always sunken if the widget is
+selected and raised otherwise.
+.OP \-offrelief offRelief OffRelief
+Specifies the relief for the checkbutton when the indicator is not drawn and
+the checkbutton is off. The default value is
+.QW raised .
+By setting this option to
+.QW flat
+and setting \fB\-indicatoron\fR to false and \fB\-overrelief\fR to
+.QW raised ,
+the effect is achieved
+of having a flat button that raises on mouse-over and which is
+depressed when activated. This is the behavior typically exhibited by
+the Bold, Italic, and Underline checkbuttons on the toolbar of a
+word-processor, for example.
+.OP \-offvalue offValue Value
+Specifies value to store in the button's associated variable whenever
+this button is deselected. Defaults to
+.QW 0 .
+.OP \-onvalue onValue Value
+Specifies value to store in the button's associated variable whenever
+this button is selected. Defaults to
+.QW 1 .
+.OP \-overrelief overRelief OverRelief
+Specifies an alternative relief for the checkbutton, to be used when the
+mouse cursor is over the widget. This option can be used to make
+toolbar buttons, by configuring \fB\-relief flat \-overrelief
+raised\fR. If the value of this option is the empty string, then no
+alternative relief is used when the mouse cursor is over the checkbutton.
+The empty string is the default value.
+.OP \-selectcolor selectColor Background
+Specifies a background color to use when the button is selected.
+If \fBindicatorOn\fR is true then the color is used as the background for
+the indicator regardless of the select state.
+If \fBindicatorOn\fR is false, this color is used as the background
+for the entire widget, in place of \fBbackground\fR or \fBactiveBackground\fR,
+whenever the widget is selected.
+If specified as an empty string then no special color is used for
+displaying when the widget is selected.
+.OP \-selectimage selectImage SelectImage
+Specifies an image to display (in place of the \fB\-image\fR option)
+when the checkbutton is selected.
+This option is ignored unless the \fB\-image\fR option has been
+specified.
+.OP \-state state State
+Specifies one of three states for the checkbutton: \fBnormal\fR, \fBactive\fR,
+or \fBdisabled\fR. In normal state the checkbutton is displayed using the
+\fB\-foreground\fR and \fB\-background\fR options. The active state is
+typically used when the pointer is over the checkbutton. In active state
+the checkbutton is displayed using the \fB\-activeforeground\fR and
+\fB\-activebackground\fR options. Disabled state means that the checkbutton
+should be insensitive: the default bindings will refuse to activate
+the widget and will ignore mouse button presses.
+In this state the \fB\-disabledforeground\fR and
+\fB\-background\fR options determine how the checkbutton is displayed.
+.OP \-tristateimage tristateImage TristateImage
+Specifies an image to display (in place of the \fB\-image\fR option)
+when the checkbutton is in tri-state mode.
+This option is ignored unless the \fB\-image\fR option has been
+specified.
+.OP \-tristatevalue tristateValue Value
+Specifies the value that causes the checkbutton to display the multi-value
+selection, also known as the tri-state mode. Defaults to
+.QW "" .
+.OP \-variable variable Variable
+Specifies the name of a global variable to set to indicate whether
+or not this button is selected. Defaults to the name of the
+button within its parent (i.e. the last element of the button
+window's path name).
+.OP \-width width Width
+Specifies a desired width for the button.
+If an image or bitmap is being displayed in the button then the value is in
+screen units (i.e. any of the forms acceptable to \fBTk_GetPixels\fR);
+for text it is in characters.
+If this option is not specified, the button's desired width is computed
+from the size of the image or bitmap or text being displayed in it.
+.BE
+.SH DESCRIPTION
+.PP
+The \fBcheckbutton\fR command creates a new window (given by the
+\fIpathName\fR argument) and makes it into a checkbutton widget.
+Additional
+options, described above, may be specified on the command line
+or in the option database
+to configure aspects of the checkbutton such as its colors, font,
+text, and initial relief. The \fBcheckbutton\fR command returns its
+\fIpathName\fR argument. At the time this command is invoked,
+there must not exist a window named \fIpathName\fR, but
+\fIpathName\fR's parent must exist.
+.PP
+A checkbutton is a widget
+that displays a textual string, bitmap or image
+and a square called an \fIindicator\fR.
+If text is displayed, it must all be in a single font, but it
+can occupy multiple lines on the screen (if it contains newlines
+or if wrapping occurs because of the \fB\-wraplength\fR option) and
+one of the characters may optionally be underlined using the
+\fB\-underline\fR option.
+A checkbutton has
+all of the behavior of a simple button, including the
+following: it can display itself in either of three different
+ways, according to the \fB\-state\fR option;
+it can be made to appear
+raised, sunken, or flat; it can be made to flash; and it invokes
+a Tcl command whenever mouse button 1 is clicked over the
+checkbutton.
+.PP
+In addition, checkbuttons can be \fIselected\fR.
+If a checkbutton is selected then the indicator is normally
+drawn with a selected appearance, and
+a Tcl variable associated with the checkbutton is set to a particular
+value (normally 1).
+The indicator is drawn with a check mark inside.
+If the checkbutton is not selected, then the indicator is drawn with a
+deselected appearance, and the associated variable is
+set to a different value (typically 0).
+The indicator is drawn without a check mark inside. In the special case
+where the variable (if specified) has a value that matches the tristatevalue,
+the indicator is drawn with a tri-state appearance and is in the tri-state
+mode indicating mixed or multiple values. (This is used when the check
+box represents the state of multiple items.)
+The indicator is drawn in a platform dependent manner. Under Unix and
+Windows, the background interior of the box is
+.QW grayed .
+Under Mac, the indicator is drawn with a dash mark inside.
+By default, the name of the variable associated with a checkbutton is the
+same as the \fIname\fR used to create the checkbutton.
+The variable name, and the
+.QW on ,
+.QW off
+and
+.QW tristate
+values stored in it, may be modified with options on the command line
+or in the option database.
+Configuration options may also be used to modify the way the
+indicator is displayed (or whether it is displayed at all).
+By default a checkbutton is configured to select and deselect
+itself on alternate button clicks.
+In addition, each checkbutton monitors its associated variable and
+automatically selects and deselects itself when the variables value
+changes to and from the button's
+.QW on ,
+.QW off
+and
+.QW tristate
+values.
+.SH "WIDGET COMMAND"
+.PP
+The \fBcheckbutton\fR command creates a new Tcl command whose
+name is \fIpathName\fR. This
+command may be used to invoke various
+operations on the widget. It has the following general form:
+.CS
+\fIpathName option \fR?\fIarg arg ...\fR?
+.CE
+\fIOption\fR and the \fIarg\fRs
+determine the exact behavior of the command. The following
+commands are possible for checkbutton widgets:
+.TP
+\fIpathName \fBcget\fR \fIoption\fR
+Returns the current value of the configuration option given
+by \fIoption\fR.
+\fIOption\fR may have any of the values accepted by the \fBcheckbutton\fR
+command.
+.TP
+\fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
+Query or modify the configuration options of the widget.
+If no \fIoption\fR is specified, returns a list describing all of
+the available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for
+information on the format of this list). If \fIoption\fR is specified
+with no \fIvalue\fR, then the command returns a list describing the
+one named option (this list will be identical to the corresponding
+sublist of the value returned if no \fIoption\fR is specified). If
+one or more \fIoption\-value\fR pairs are specified, then the command
+modifies the given widget option(s) to have the given value(s); in
+this case the command returns an empty string.
+\fIOption\fR may have any of the values accepted by the \fBcheckbutton\fR
+command.
+.TP
+\fIpathName \fBdeselect\fR
+Deselects the checkbutton and sets the associated variable to its
+.QW off
+value.
+.TP
+\fIpathName \fBflash\fR
+Flashes the checkbutton. This is accomplished by redisplaying the checkbutton
+several times, alternating between active and normal colors. At
+the end of the flash the checkbutton is left in the same normal/active
+state as when the command was invoked.
+This command is ignored if the checkbutton's state is \fBdisabled\fR.
+.TP
+\fIpathName \fBinvoke\fR
+Does just what would have happened if the user invoked the checkbutton
+with the mouse: toggle the selection state of the button and invoke
+the Tcl command associated with the checkbutton, if there is one.
+The return value is the return value from the Tcl command, or an
+empty string if there is no command associated with the checkbutton.
+This command is ignored if the checkbutton's state is \fBdisabled\fR.
+.TP
+\fIpathName \fBselect\fR
+Selects the checkbutton and sets the associated variable to its
+.QW on
+value.
+.TP
+\fIpathName \fBtoggle\fR
+Toggles the selection state of the button, redisplaying it and
+modifying its associated variable to reflect the new state.
+.SH BINDINGS
+.PP
+Tk automatically creates class bindings for checkbuttons that give them
+the following default behavior:
+.IP [1]
+On Unix systems, a checkbutton activates whenever the mouse passes
+over it and deactivates whenever the mouse leaves the checkbutton. On
+Mac and Windows systems, when mouse button 1 is pressed over a
+checkbutton, the button activates whenever the mouse pointer is inside
+the button, and deactivates whenever the mouse pointer leaves the
+button.
+.IP [2]
+When mouse button 1 is pressed over a checkbutton, it is invoked (its
+selection state toggles and the command associated with the button is
+invoked, if there is one).
+.IP [3]
+When a checkbutton has the input focus, the space key causes the checkbutton
+to be invoked. Under Windows, there are additional key bindings; plus
+(\fB+\fR) and equal (\fB=\fR) select the button, and minus (\fB\-\fR)
+deselects the button.
+.PP
+If the checkbutton's state is \fBdisabled\fR then none of the above
+actions occur: the checkbutton is completely non-responsive.
+.PP
+The behavior of checkbuttons can be changed by defining new bindings for
+individual widgets or by redefining the class bindings.
+.SH EXAMPLE
+.PP
+This example shows a group of uncoupled checkbuttons.
+.PP
+.CS
+labelframe .lbl \-text "Steps:"
+\fBcheckbutton\fR .c1 \-text Lights \-variable lights
+\fBcheckbutton\fR .c2 \-text Cameras \-variable cameras
+\fBcheckbutton\fR .c3 \-text Action! \-variable action
+pack .c1 .c2 .c3 \-in .lbl
+pack .lbl
+.CE
+.SH "SEE ALSO"
+button(n), options(n), radiobutton(n), ttk::checkbutton(n)
+.SH KEYWORDS
+checkbutton, widget
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/chooseColor.n b/tk8.6/doc/chooseColor.n
new file mode 100644
index 0000000..015b17d
--- /dev/null
+++ b/tk8.6/doc/chooseColor.n
@@ -0,0 +1,48 @@
+'\"
+'\" 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.
+'\"
+.TH tk_chooseColor n 4.2 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+tk_chooseColor \- pops up a dialog box for the user to select a color.
+.SH SYNOPSIS
+\fBtk_chooseColor \fR?\fIoption value ...\fR?
+.BE
+.SH DESCRIPTION
+.PP
+The procedure \fBtk_chooseColor\fR pops up a dialog box for the
+user to select a color. The following \fIoption\-value\fR pairs are
+possible as command line arguments:
+.TP
+\fB\-initialcolor\fR \fIcolor\fR
+Specifies the color to display in the color dialog when it pops
+up. \fIcolor\fR must be in a form acceptable to the \fBTk_GetColor\fR
+function.
+.TP
+\fB\-parent\fR \fIwindow\fR
+Makes \fIwindow\fR the logical parent of the color dialog. The color
+dialog is displayed on top of its parent window.
+.TP
+\fB\-title\fR \fItitleString\fR
+Specifies a string to display as the title of the dialog box. If this
+option is not specified, then a default title will be displayed.
+.LP
+If the user selects a color, \fBtk_chooseColor\fR will return the
+name of the color in a form acceptable to \fBTk_GetColor\fR. If the
+user cancels the operation, both commands will return the empty
+string.
+.SH EXAMPLE
+.PP
+.CS
+button .b \-bg [tk_chooseColor \-initialcolor gray \-title "Choose color"]
+.CE
+.SH KEYWORDS
+color, color selection, dialog
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/chooseDirectory.n b/tk8.6/doc/chooseDirectory.n
new file mode 100644
index 0000000..e441d78
--- /dev/null
+++ b/tk8.6/doc/chooseDirectory.n
@@ -0,0 +1,71 @@
+'\"
+'\" Copyright (c) 1998-2000 by Scriptics Corporation.
+'\" All rights reserved.
+'\"
+.TH tk_chooseDirectory n 8.3 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+tk_chooseDirectory \- pops up a dialog box for the user to select a directory.
+.SH SYNOPSIS
+\fBtk_chooseDirectory \fR?\fIoption value ...\fR?
+.BE
+.SH DESCRIPTION
+.PP
+The procedure \fBtk_chooseDirectory\fR pops up a dialog box for the
+user to select a directory. The following \fIoption\-value\fR pairs are
+possible as command line arguments:
+.TP
+\fB\-command\fR \fIstring\fR
+Specifies the prefix of a Tcl command to invoke when the user closes the
+dialog after having selected an item. This callback is not called if the
+user cancelled the dialog. The actual command consists of \fIstring\fR
+followed by a space and the value selected by the user in the dialog. This
+is only available on Mac OS X.
+.TP
+\fB\-initialdir\fR \fIdirname\fR
+Specifies that the directories in \fIdirectory\fR should be displayed
+when the dialog pops up. If this parameter is not specified,
+the initial directory defaults to the current working directory
+on non-Windows systems and on Windows systems prior to Vista.
+On Vista and later systems, the initial directory defaults to the last
+user-selected directory for the application. If the
+parameter specifies a relative path, the return value will convert the
+relative path to an absolute path.
+.TP
+\fB\-message\fR \fIstring\fR
+Specifies a message to include in the client area of the dialog.
+This is only available on Mac OS X.
+.TP
+\fB\-mustexist\fR \fIboolean\fR
+Specifies whether the user may specify non-existent directories. If
+this parameter is true, then the user may only select directories that
+already exist. The default value is \fIfalse\fR.
+.TP
+\fB\-parent\fR \fIwindow\fR
+Makes \fIwindow\fR the logical parent of the dialog. The dialog
+is displayed on top of its parent window. On Mac OS X, this
+turns the file dialog into a sheet attached to the parent window.
+.TP
+\fB\-title\fR \fItitleString\fR
+Specifies a string to display as the title of the dialog box. If this
+option is not specified, then a default title will be displayed.
+.SH EXAMPLE
+.PP
+.CS
+set dir [\fBtk_chooseDirectory\fR \e
+ \-initialdir ~ \-title "Choose a directory"]
+if {$dir eq ""} {
+ label .l \-text "No directory selected"
+} else {
+ label .l \-text "Selected $dir"
+}
+.CE
+.SH "SEE ALSO"
+tk_getOpenFile(n), tk_getSaveFile(n)
+.SH KEYWORDS
+directory, selection, dialog, platform-specific
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/clipboard.n b/tk8.6/doc/clipboard.n
new file mode 100644
index 0000000..6f047dd
--- /dev/null
+++ b/tk8.6/doc/clipboard.n
@@ -0,0 +1,157 @@
+'\"
+'\" Copyright (c) 1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH clipboard n 8.4 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+clipboard \- Manipulate Tk clipboard
+.SH SYNOPSIS
+\fBclipboard \fIoption\fR ?\fIarg arg ...\fR?
+.BE
+.SH DESCRIPTION
+.PP
+This command provides a Tcl interface to the Tk clipboard,
+which stores data for later retrieval using the selection mechanism
+(via the \fB\-selection CLIPBOARD\fR option).
+In order to copy data into the clipboard, \fBclipboard clear\fR must
+be called, followed by a sequence of one or more calls to \fBclipboard
+append\fR. To ensure that the clipboard is updated atomically, all
+appends should be completed before returning to the event loop.
+.PP
+The first argument to \fBclipboard\fR determines the format of the
+rest of the arguments and the behavior of the command. The following
+forms are currently supported:
+.TP
+\fBclipboard append\fR ?\fB\-displayof\fR \fIwindow\fR? ?\fB\-format\fR \fIformat\fR? ?\fB\-type\fR \fItype\fR? ?\fB\-\|\-\fR? \fIdata\fR
+.
+Appends \fIdata\fR to the clipboard on \fIwindow\fR's
+display in the form given by \fItype\fR with the representation given
+by \fIformat\fR and claims ownership of the clipboard on \fIwindow\fR's
+display.
+.RS
+.PP
+\fIType\fR specifies the form in which the selection is to be returned
+(the desired
+.QW target
+for conversion, in ICCCM terminology), and
+should be an atom name such as \fBSTRING\fR or \fBFILE_NAME\fR; see the
+Inter-Client Communication Conventions Manual for complete details.
+\fIType\fR defaults to \fBSTRING\fR.
+.PP
+The \fIformat\fR argument specifies the representation that should be
+used to transmit the selection to the requester (the second column of
+Table 2 of the ICCCM), and defaults to \fBSTRING\fR. If \fIformat\fR is
+\fBSTRING\fR, the selection is transmitted as 8-bit ASCII characters. If
+\fIformat\fR is \fBATOM\fR, then the \fIdata\fR is
+divided into fields separated by white space; each field is converted
+to its atom value, and the 32-bit atom value is transmitted instead of
+the atom name. For any other \fIformat\fR, \fIdata\fR is divided
+into fields separated by white space and each
+field is converted to a 32-bit integer; an array of integers is
+transmitted to the selection requester. Note that strings passed to
+\fBclipboard append\fR are concatenated before conversion, so the
+caller must take care to ensure appropriate spacing across string
+boundaries. All items appended to the clipboard with the same
+\fItype\fR must have the same \fIformat\fR.
+.PP
+The \fIformat\fR argument is needed only for compatibility with
+clipboard requesters that do not use Tk. If the Tk toolkit is being
+used to retrieve the \fBCLIPBOARD\fR selection then the value is
+converted back to a string at the requesting end, so \fIformat\fR is
+irrelevant.
+.PP
+A \fB\-\|\-\fR argument may be specified to mark the end of options: the
+next argument will always be used as \fIdata\fR.
+This feature may be convenient if, for example, \fIdata\fR starts
+with a \fB\-\fR.
+.RE
+.TP
+\fBclipboard clear\fR ?\fB\-displayof\fR \fIwindow\fR?
+.
+Claims ownership of the clipboard on \fIwindow\fR's display and removes
+any previous contents. \fIWindow\fR defaults to
+.QW . .
+Returns an empty string.
+.TP
+\fBclipboard get\fR ?\fB\-displayof\fR \fIwindow\fR? ?\fB\-type\fR \fItype\fR?
+.
+Retrieve data from the clipboard on \fIwindow\fR's display.
+\fIWindow\fR defaults to
+.QW . .
+\fIType\fR specifies the form in which
+the data is to be returned and should be an atom name such as \fBSTRING\fR
+or \fBFILE_NAME\fR. \fIType\fR defaults to \fBSTRING\fR. This command is
+equivalent to
+.QW "\fBselection get\fR \fB\-selection CLIPBOARD\fR" .
+.RS
+.PP
+Note that on modern X11 systems, the most useful type to retrieve for
+transferred strings is not \fBSTRING\fR, but rather \fBUTF8_STRING\fR.
+.RE
+.SH EXAMPLES
+.PP
+Get the current contents of the clipboard.
+.CS
+if {[catch {\fBclipboard get\fR} contents]} {
+ # There were no clipboard contents at all
+}
+.CE
+.PP
+Set the clipboard to contain a fixed string.
+.CS
+\fBclipboard clear\fR
+\fBclipboard append\fR "some fixed string"
+.CE
+.PP
+You can put custom data into the clipboard by using a custom \fB\-type\fR
+option. This is not necessarily portable, but can be very useful. The
+method of passing Tcl scripts this way is effective, but should be mixed
+with safe interpreters in production code.
+.CS
+# This is a very simple canvas serializer;
+# it produces a script that recreates the item(s) when executed
+proc getItemConfig {canvas tag} {
+ set script {}
+ foreach item [$canvas find withtag $tag] {
+ append script {$canvas create } [$canvas type $item]
+ append script { } [$canvas coords $item] { }
+ foreach config [$canvas itemconf $item] {
+ lassign $config name \- \- \- value
+ append script [list $name $value] { }
+ }
+ append script \en
+ }
+ return [string trim $script]
+}
+
+# Set up a binding on a canvas to cut and paste an item
+set c [canvas .c]
+pack $c
+$c create text 150 30 \-text "cut and paste me"
+bind $c <<Cut>> {
+ \fBclipboard clear\fR
+ \fBclipboard append \-type\fR TkCanvasItem \e
+ [getItemConfig %W current]
+ # Delete because this is cut, not copy.
+ %W delete current
+}
+bind $c <<Paste>> {
+ catch {
+ set canvas %W
+ eval [\fBclipboard get \-type\fR TkCanvasItem]
+ }
+}
+.CE
+.SH "SEE ALSO"
+interp(n), selection(n)
+.SH KEYWORDS
+clear, format, clipboard, append, selection, type
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/colors.n b/tk8.6/doc/colors.n
new file mode 100644
index 0000000..7a7b5b3
--- /dev/null
+++ b/tk8.6/doc/colors.n
@@ -0,0 +1,992 @@
+'\"
+'\" Copyright (c) 1998-2000 by Scriptics Corporation.
+'\" Copyright (c) 2003 ActiveState Corporation.
+'\" Copyright (c) 2006-2007 Daniel A. Steffen <das@users.sourceforge.net>
+'\" Copyright (c) 2008 Donal K. Fellows
+'\"
+.TH colors n 8.3 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+.\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+colors \- symbolic color names recognized by Tk
+.BE
+.SH DESCRIPTION
+.PP
+Tk recognizes many symbolic color names (e.g., \fBred\fR) when
+specifying colors. The symbolic names recognized by Tk and their
+8-bit-per-channel RGB values are:
+.DS
+.ta 7.2cR 9.5cR 11cR
+\fBName\fR \fBRed\fR \fBGreen\fR \fBBlue\fR
+alice blue 240 248 255
+AliceBlue 240 248 255
+antique white 250 235 215
+AntiqueWhite 250 235 215
+AntiqueWhite1 255 239 219
+AntiqueWhite2 238 223 204
+AntiqueWhite3 205 192 176
+AntiqueWhite4 139 131 120
+agua 0 255 255
+aquamarine 127 255 212
+aquamarine1 127 255 212
+aquamarine2 118 238 198
+aquamarine3 102 205 170
+aquamarine4 69 139 116
+azure 240 255 255
+azure1 240 255 255
+azure2 224 238 238
+azure3 193 205 205
+azure4 131 139 139
+beige 245 245 220
+bisque 255 228 196
+bisque1 255 228 196
+bisque2 238 213 183
+bisque3 205 183 158
+bisque4 139 125 107
+black 0 0 0
+blanched almond 255 235 205
+BlanchedAlmond 255 235 205
+blue 0 0 255
+blue violet 138 43 226
+blue1 0 0 255
+blue2 0 0 238
+blue3 0 0 205
+blue4 0 0 139
+BlueViolet 138 43 226
+brown 165 42 42
+brown1 255 64 64
+brown2 238 59 59
+brown3 205 51 51
+brown4 139 35 35
+burlywood 222 184 135
+burlywood1 255 211 155
+burlywood2 238 197 145
+burlywood3 205 170 125
+burlywood4 139 115 85
+cadet blue 95 158 160
+CadetBlue 95 158 160
+CadetBlue1 152 245 255
+CadetBlue2 142 229 238
+CadetBlue3 122 197 205
+CadetBlue4 83 134 139
+chartreuse 127 255 0
+chartreuse1 127 255 0
+chartreuse2 118 238 0
+chartreuse3 102 205 0
+chartreuse4 69 139 0
+chocolate 210 105 30
+chocolate1 255 127 36
+chocolate2 238 118 33
+chocolate3 205 102 29
+chocolate4 139 69 19
+coral 255 127 80
+coral1 255 114 86
+coral2 238 106 80
+coral3 205 91 69
+coral4 139 62 47
+cornflower blue 100 149 237
+CornflowerBlue 100 149 237
+cornsilk 255 248 220
+cornsilk1 255 248 220
+cornsilk2 238 232 205
+cornsilk3 205 200 177
+cornsilk4 139 136 120
+crymson 220 20 60
+cyan 0 255 255
+cyan1 0 255 255
+cyan2 0 238 238
+cyan3 0 205 205
+cyan4 0 139 139
+dark blue 0 0 139
+dark cyan 0 139 139
+dark goldenrod 184 134 11
+dark gray 169 169 169
+dark green 0 100 0
+dark grey 169 169 169
+dark khaki 189 183 107
+dark magenta 139 0 139
+dark olive green 85 107 47
+dark orange 255 140 0
+dark orchid 153 50 204
+dark red 139 0 0
+dark salmon 233 150 122
+dark sea green 143 188 143
+dark slate blue 72 61 139
+dark slate gray 47 79 79
+dark slate grey 47 79 79
+dark turquoise 0 206 209
+dark violet 148 0 211
+DarkBlue 0 0 139
+DarkCyan 0 139 139
+DarkGoldenrod 184 134 11
+DarkGoldenrod1 255 185 15
+DarkGoldenrod2 238 173 14
+DarkGoldenrod3 205 149 12
+DarkGoldenrod4 139 101 8
+DarkGray 169 169 169
+DarkGreen 0 100 0
+DarkGrey 169 169 169
+DarkKhaki 189 183 107
+DarkMagenta 139 0 139
+DarkOliveGreen 85 107 47
+DarkOliveGreen1 202 255 112
+DarkOliveGreen2 188 238 104
+DarkOliveGreen3 162 205 90
+DarkOliveGreen4 110 139 61
+DarkOrange 255 140 0
+DarkOrange1 255 127 0
+DarkOrange2 238 118 0
+DarkOrange3 205 102 0
+DarkOrange4 139 69 0
+DarkOrchid 153 50 204
+DarkOrchid1 191 62 255
+DarkOrchid2 178 58 238
+DarkOrchid3 154 50 205
+DarkOrchid4 104 34 139
+DarkRed 139 0 0
+DarkSalmon 233 150 122
+DarkSeaGreen 143 188 143
+DarkSeaGreen1 193 255 193
+DarkSeaGreen2 180 238 180
+DarkSeaGreen3 155 205 155
+DarkSeaGreen4 105 139 105
+DarkSlateBlue 72 61 139
+DarkSlateGray 47 79 79
+DarkSlateGray1 151 255 255
+DarkSlateGray2 141 238 238
+DarkSlateGray3 121 205 205
+DarkSlateGray4 82 139 139
+DarkSlateGrey 47 79 79
+DarkTurquoise 0 206 209
+DarkViolet 148 0 211
+deep pink 255 20 147
+deep sky blue 0 191 255
+DeepPink 255 20 147
+DeepPink1 255 20 147
+DeepPink2 238 18 137
+DeepPink3 205 16 118
+DeepPink4 139 10 80
+DeepSkyBlue 0 191 255
+DeepSkyBlue1 0 191 255
+DeepSkyBlue2 0 178 238
+DeepSkyBlue3 0 154 205
+DeepSkyBlue4 0 104 139
+dim gray 105 105 105
+dim grey 105 105 105
+DimGray 105 105 105
+DimGrey 105 105 105
+dodger blue 30 144 255
+DodgerBlue 30 144 255
+DodgerBlue1 30 144 255
+DodgerBlue2 28 134 238
+DodgerBlue3 24 116 205
+DodgerBlue4 16 78 139
+firebrick 178 34 34
+firebrick1 255 48 48
+firebrick2 238 44 44
+firebrick3 205 38 38
+firebrick4 139 26 26
+floral white 255 250 240
+FloralWhite 255 250 240
+forest green 34 139 34
+ForestGreen 34 139 34
+fuchsia 255 0 255
+gainsboro 220 220 220
+ghost white 248 248 255
+GhostWhite 248 248 255
+gold 255 215 0
+gold1 255 215 0
+gold2 238 201 0
+gold3 205 173 0
+gold4 139 117 0
+goldenrod 218 165 32
+goldenrod1 255 193 37
+goldenrod2 238 180 34
+goldenrod3 205 155 29
+goldenrod4 139 105 20
+gray 128 128 128
+gray0 0 0 0
+gray1 3 3 3
+gray2 5 5 5
+gray3 8 8 8
+gray4 10 10 10
+gray5 13 13 13
+gray6 15 15 15
+gray7 18 18 18
+gray8 20 20 20
+gray9 23 23 23
+gray10 26 26 26
+gray11 28 28 28
+gray12 31 31 31
+gray13 33 33 33
+gray14 36 36 36
+gray15 38 38 38
+gray16 41 41 41
+gray17 43 43 43
+gray18 46 46 46
+gray19 48 48 48
+gray20 51 51 51
+gray21 54 54 54
+gray22 56 56 56
+gray23 59 59 59
+gray24 61 61 61
+gray25 64 64 64
+gray26 66 66 66
+gray27 69 69 69
+gray28 71 71 71
+gray29 74 74 74
+gray30 77 77 77
+gray31 79 79 79
+gray32 82 82 82
+gray33 84 84 84
+gray34 87 87 87
+gray35 89 89 89
+gray36 92 92 92
+gray37 94 94 94
+gray38 97 97 97
+gray39 99 99 99
+gray40 102 102 102
+gray41 105 105 105
+gray42 107 107 107
+gray43 110 110 110
+gray44 112 112 112
+gray45 115 115 115
+gray46 117 117 117
+gray47 120 120 120
+gray48 122 122 122
+gray49 125 125 125
+gray50 127 127 127
+gray51 130 130 130
+gray52 133 133 133
+gray53 135 135 135
+gray54 138 138 138
+gray55 140 140 140
+gray56 143 143 143
+gray57 145 145 145
+gray58 148 148 148
+gray59 150 150 150
+gray60 153 153 153
+gray61 156 156 156
+gray62 158 158 158
+gray63 161 161 161
+gray64 163 163 163
+gray65 166 166 166
+gray66 168 168 168
+gray67 171 171 171
+gray68 173 173 173
+gray69 176 176 176
+gray70 179 179 179
+gray71 181 181 181
+gray72 184 184 184
+gray73 186 186 186
+gray74 189 189 189
+gray75 191 191 191
+gray76 194 194 194
+gray77 196 196 196
+gray78 199 199 199
+gray79 201 201 201
+gray80 204 204 204
+gray81 207 207 207
+gray82 209 209 209
+gray83 212 212 212
+gray84 214 214 214
+gray85 217 217 217
+gray86 219 219 219
+gray87 222 222 222
+gray88 224 224 224
+gray89 227 227 227
+gray90 229 229 229
+gray91 232 232 232
+gray92 235 235 235
+gray93 237 237 237
+gray94 240 240 240
+gray95 242 242 242
+gray96 245 245 245
+gray97 247 247 247
+gray98 250 250 250
+gray99 252 252 252
+gray100 255 255 255
+green 0 128 0
+green yellow 173 255 47
+green1 0 255 0
+green2 0 238 0
+green3 0 205 0
+green4 0 139 0
+GreenYellow 173 255 47
+grey 128 128 128
+grey0 0 0 0
+grey1 3 3 3
+grey2 5 5 5
+grey3 8 8 8
+grey4 10 10 10
+grey5 13 13 13
+grey6 15 15 15
+grey7 18 18 18
+grey8 20 20 20
+grey9 23 23 23
+grey10 26 26 26
+grey11 28 28 28
+grey12 31 31 31
+grey13 33 33 33
+grey14 36 36 36
+grey15 38 38 38
+grey16 41 41 41
+grey17 43 43 43
+grey18 46 46 46
+grey19 48 48 48
+grey20 51 51 51
+grey21 54 54 54
+grey22 56 56 56
+grey23 59 59 59
+grey24 61 61 61
+grey25 64 64 64
+grey26 66 66 66
+grey27 69 69 69
+grey28 71 71 71
+grey29 74 74 74
+grey30 77 77 77
+grey31 79 79 79
+grey32 82 82 82
+grey33 84 84 84
+grey34 87 87 87
+grey35 89 89 89
+grey36 92 92 92
+grey37 94 94 94
+grey38 97 97 97
+grey39 99 99 99
+grey40 102 102 102
+grey41 105 105 105
+grey42 107 107 107
+grey43 110 110 110
+grey44 112 112 112
+grey45 115 115 115
+grey46 117 117 117
+grey47 120 120 120
+grey48 122 122 122
+grey49 125 125 125
+grey50 127 127 127
+grey51 130 130 130
+grey52 133 133 133
+grey53 135 135 135
+grey54 138 138 138
+grey55 140 140 140
+grey56 143 143 143
+grey57 145 145 145
+grey58 148 148 148
+grey59 150 150 150
+grey60 153 153 153
+grey61 156 156 156
+grey62 158 158 158
+grey63 161 161 161
+grey64 163 163 163
+grey65 166 166 166
+grey66 168 168 168
+grey67 171 171 171
+grey68 173 173 173
+grey69 176 176 176
+grey70 179 179 179
+grey71 181 181 181
+grey72 184 184 184
+grey73 186 186 186
+grey74 189 189 189
+grey75 191 191 191
+grey76 194 194 194
+grey77 196 196 196
+grey78 199 199 199
+grey79 201 201 201
+grey80 204 204 204
+grey81 207 207 207
+grey82 209 209 209
+grey83 212 212 212
+grey84 214 214 214
+grey85 217 217 217
+grey86 219 219 219
+grey87 222 222 222
+grey88 224 224 224
+grey89 227 227 227
+grey90 229 229 229
+grey91 232 232 232
+grey92 235 235 235
+grey93 237 237 237
+grey94 240 240 240
+grey95 242 242 242
+grey96 245 245 245
+grey97 247 247 247
+grey98 250 250 250
+grey99 252 252 252
+grey100 255 255 255
+honeydew 240 255 240
+honeydew1 240 255 240
+honeydew2 224 238 224
+honeydew3 193 205 193
+honeydew4 131 139 131
+hot pink 255 105 180
+HotPink 255 105 180
+HotPink1 255 110 180
+HotPink2 238 106 167
+HotPink3 205 96 144
+HotPink4 139 58 98
+indian red 205 92 92
+IndianRed 205 92 92
+IndianRed1 255 106 106
+IndianRed2 238 99 99
+IndianRed3 205 85 85
+IndianRed4 139 58 58
+indigo 75 0 130
+ivory 255 255 240
+ivory1 255 255 240
+ivory2 238 238 224
+ivory3 205 205 193
+ivory4 139 139 131
+khaki 240 230 140
+khaki1 255 246 143
+khaki2 238 230 133
+khaki3 205 198 115
+khaki4 139 134 78
+lavender 230 230 250
+lavender blush 255 240 245
+LavenderBlush 255 240 245
+LavenderBlush1 255 240 245
+LavenderBlush2 238 224 229
+LavenderBlush3 205 193 197
+LavenderBlush4 139 131 134
+lawn green 124 252 0
+LawnGreen 124 252 0
+lemon chiffon 255 250 205
+LemonChiffon 255 250 205
+LemonChiffon1 255 250 205
+LemonChiffon2 238 233 191
+LemonChiffon3 205 201 165
+LemonChiffon4 139 137 112
+light blue 173 216 230
+light coral 240 128 128
+light cyan 224 255 255
+light goldenrod 238 221 130
+light goldenrod yellow 250 250 210
+light gray 211 211 211
+light green 144 238 144
+light grey 211 211 211
+light pink 255 182 193
+light salmon 255 160 122
+light sea green 32 178 170
+light sky blue 135 206 250
+light slate blue 132 112 255
+light slate gray 119 136 153
+light slate grey 119 136 153
+light steel blue 176 196 222
+light yellow 255 255 224
+LightBlue 173 216 230
+LightBlue1 191 239 255
+LightBlue2 178 223 238
+LightBlue3 154 192 205
+LightBlue4 104 131 139
+LightCoral 240 128 128
+LightCyan 224 255 255
+LightCyan1 224 255 255
+LightCyan2 209 238 238
+LightCyan3 180 205 205
+LightCyan4 122 139 139
+LightGoldenrod 238 221 130
+LightGoldenrod1 255 236 139
+LightGoldenrod2 238 220 130
+LightGoldenrod3 205 190 112
+LightGoldenrod4 139 129 76
+LightGoldenrodYellow 250 250 210
+LightGray 211 211 211
+LightGreen 144 238 144
+LightGrey 211 211 211
+LightPink 255 182 193
+LightPink1 255 174 185
+LightPink2 238 162 173
+LightPink3 205 140 149
+LightPink4 139 95 101
+LightSalmon 255 160 122
+LightSalmon1 255 160 122
+LightSalmon2 238 149 114
+LightSalmon3 205 129 98
+LightSalmon4 139 87 66
+LightSeaGreen 32 178 170
+LightSkyBlue 135 206 250
+LightSkyBlue1 176 226 255
+LightSkyBlue2 164 211 238
+LightSkyBlue3 141 182 205
+LightSkyBlue4 96 123 139
+LightSlateBlue 132 112 255
+LightSlateGray 119 136 153
+LightSlateGrey 119 136 153
+LightSteelBlue 176 196 222
+LightSteelBlue1 202 225 255
+LightSteelBlue2 188 210 238
+LightSteelBlue3 162 181 205
+LightSteelBlue4 110 123 139
+LightYellow 255 255 224
+LightYellow1 255 255 224
+LightYellow2 238 238 209
+LightYellow3 205 205 180
+LightYellow4 139 139 122
+lime 0 255 0
+lime green 50 205 50
+LimeGreen 50 205 50
+linen 250 240 230
+magenta 255 0 255
+magenta1 255 0 255
+magenta2 238 0 238
+magenta3 205 0 205
+magenta4 139 0 139
+maroon 128 0 0
+maroon1 255 52 179
+maroon2 238 48 167
+maroon3 205 41 144
+maroon4 139 28 98
+medium aquamarine 102 205 170
+medium blue 0 0 205
+medium orchid 186 85 211
+medium purple 147 112 219
+medium sea green 60 179 113
+medium slate blue 123 104 238
+medium spring green 0 250 154
+medium turquoise 72 209 204
+medium violet red 199 21 133
+MediumAquamarine 102 205 170
+MediumBlue 0 0 205
+MediumOrchid 186 85 211
+MediumOrchid1 224 102 255
+MediumOrchid2 209 95 238
+MediumOrchid3 180 82 205
+MediumOrchid4 122 55 139
+MediumPurple 147 112 219
+MediumPurple1 171 130 255
+MediumPurple2 159 121 238
+MediumPurple3 137 104 205
+MediumPurple4 93 71 139
+MediumSeaGreen 60 179 113
+MediumSlateBlue 123 104 238
+MediumSpringGreen 0 250 154
+MediumTurquoise 72 209 204
+MediumVioletRed 199 21 133
+midnight blue 25 25 112
+MidnightBlue 25 25 112
+mint cream 245 255 250
+MintCream 245 255 250
+misty rose 255 228 225
+MistyRose 255 228 225
+MistyRose1 255 228 225
+MistyRose2 238 213 210
+MistyRose3 205 183 181
+MistyRose4 139 125 123
+moccasin 255 228 181
+navajo white 255 222 173
+NavajoWhite 255 222 173
+NavajoWhite1 255 222 173
+NavajoWhite2 238 207 161
+NavajoWhite3 205 179 139
+NavajoWhite4 139 121 94
+navy 0 0 128
+navy blue 0 0 128
+NavyBlue 0 0 128
+old lace 253 245 230
+OldLace 253 245 230
+olive 128 128 0
+olive drab 107 142 35
+OliveDrab 107 142 35
+OliveDrab1 192 255 62
+OliveDrab2 179 238 58
+OliveDrab3 154 205 50
+OliveDrab4 105 139 34
+orange 255 165 0
+orange red 255 69 0
+orange1 255 165 0
+orange2 238 154 0
+orange3 205 133 0
+orange4 139 90 0
+OrangeRed 255 69 0
+OrangeRed1 255 69 0
+OrangeRed2 238 64 0
+OrangeRed3 205 55 0
+OrangeRed4 139 37 0
+orchid 218 112 214
+orchid1 255 131 250
+orchid2 238 122 233
+orchid3 205 105 201
+orchid4 139 71 137
+pale goldenrod 238 232 170
+pale green 152 251 152
+pale turquoise 175 238 238
+pale violet red 219 112 147
+PaleGoldenrod 238 232 170
+PaleGreen 152 251 152
+PaleGreen1 154 255 154
+PaleGreen2 144 238 144
+PaleGreen3 124 205 124
+PaleGreen4 84 139 84
+PaleTurquoise 175 238 238
+PaleTurquoise1 187 255 255
+PaleTurquoise2 174 238 238
+PaleTurquoise3 150 205 205
+PaleTurquoise4 102 139 139
+PaleVioletRed 219 112 147
+PaleVioletRed1 255 130 171
+PaleVioletRed2 238 121 159
+PaleVioletRed3 205 104 127
+PaleVioletRed4 139 71 93
+papaya whip 255 239 213
+PapayaWhip 255 239 213
+peach puff 255 218 185
+PeachPuff 255 218 185
+PeachPuff1 255 218 185
+PeachPuff2 238 203 173
+PeachPuff3 205 175 149
+PeachPuff4 139 119 101
+peru 205 133 63
+pink 255 192 203
+pink1 255 181 197
+pink2 238 169 184
+pink3 205 145 158
+pink4 139 99 108
+plum 221 160 221
+plum1 255 187 255
+plum2 238 174 238
+plum3 205 150 205
+plum4 139 102 139
+powder blue 176 224 230
+PowderBlue 176 224 230
+purple 128 0 128
+purple1 155 48 255
+purple2 145 44 238
+purple3 125 38 205
+purple4 85 26 139
+red 255 0 0
+red1 255 0 0
+red2 238 0 0
+red3 205 0 0
+red4 139 0 0
+rosy brown 188 143 143
+RosyBrown 188 143 143
+RosyBrown1 255 193 193
+RosyBrown2 238 180 180
+RosyBrown3 205 155 155
+RosyBrown4 139 105 105
+royal blue 65 105 225
+RoyalBlue 65 105 225
+RoyalBlue1 72 118 255
+RoyalBlue2 67 110 238
+RoyalBlue3 58 95 205
+RoyalBlue4 39 64 139
+saddle brown 139 69 19
+SaddleBrown 139 69 19
+salmon 250 128 114
+salmon1 255 140 105
+salmon2 238 130 98
+salmon3 205 112 84
+salmon4 139 76 57
+sandy brown 244 164 96
+SandyBrown 244 164 96
+sea green 46 139 87
+SeaGreen 46 139 87
+SeaGreen1 84 255 159
+SeaGreen2 78 238 148
+SeaGreen3 67 205 128
+SeaGreen4 46 139 87
+seashell 255 245 238
+seashell1 255 245 238
+seashell2 238 229 222
+seashell3 205 197 191
+seashell4 139 134 130
+sienna 160 82 45
+sienna1 255 130 71
+sienna2 238 121 66
+sienna3 205 104 57
+sienna4 139 71 38
+silver 192 192 192
+sky blue 135 206 235
+SkyBlue 135 206 235
+SkyBlue1 135 206 255
+SkyBlue2 126 192 238
+SkyBlue3 108 166 205
+SkyBlue4 74 112 139
+slate blue 106 90 205
+slate gray 112 128 144
+slate grey 112 128 144
+SlateBlue 106 90 205
+SlateBlue1 131 111 255
+SlateBlue2 122 103 238
+SlateBlue3 105 89 205
+SlateBlue4 71 60 139
+SlateGray 112 128 144
+SlateGray1 198 226 255
+SlateGray2 185 211 238
+SlateGray3 159 182 205
+SlateGray4 108 123 139
+SlateGrey 112 128 144
+snow 255 250 250
+snow1 255 250 250
+snow2 238 233 233
+snow3 205 201 201
+snow4 139 137 137
+spring green 0 255 127
+SpringGreen 0 255 127
+SpringGreen1 0 255 127
+SpringGreen2 0 238 118
+SpringGreen3 0 205 102
+SpringGreen4 0 139 69
+steel blue 70 130 180
+SteelBlue 70 130 180
+SteelBlue1 99 184 255
+SteelBlue2 92 172 238
+SteelBlue3 79 148 205
+SteelBlue4 54 100 139
+tan 210 180 140
+tan1 255 165 79
+tan2 238 154 73
+tan3 205 133 63
+tan4 139 90 43
+teal 0 128 128
+thistle 216 191 216
+thistle1 255 225 255
+thistle2 238 210 238
+thistle3 205 181 205
+thistle4 139 123 139
+tomato 255 99 71
+tomato1 255 99 71
+tomato2 238 92 66
+tomato3 205 79 57
+tomato4 139 54 38
+turquoise 64 224 208
+turquoise1 0 245 255
+turquoise2 0 229 238
+turquoise3 0 197 205
+turquoise4 0 134 139
+violet 238 130 238
+violet red 208 32 144
+VioletRed 208 32 144
+VioletRed1 255 62 150
+VioletRed2 238 58 140
+VioletRed3 205 50 120
+VioletRed4 139 34 82
+wheat 245 222 179
+wheat1 255 231 186
+wheat2 238 216 174
+wheat3 205 186 150
+wheat4 139 126 102
+white 255 255 255
+white smoke 245 245 245
+WhiteSmoke 245 245 245
+yellow 255 255 0
+yellow green 154 205 50
+yellow1 255 255 0
+yellow2 238 238 0
+yellow3 205 205 0
+yellow4 139 139 0
+YellowGreen 154 205 50
+.DE
+.SH "PORTABILITY ISSUES"
+.TP
+\fBMac OS X\fR
+.
+On macOS, the following additional system colors are available.
+This first group contains all colors available in the HIToolbox library.
+(Note that in some cases the actual color values may depend on the
+current Appearance.)
+.RS
+.DS
+systemActiveAreaFill
+systemAlertActiveText
+systemAlertBackgroundActive
+systemAlertBackgroundInactive
+systemAlertInactiveText
+systemAlternatePrimaryHighlightColor
+systemAppleGuideCoachmark
+systemBevelActiveDark
+systemBevelActiveLight
+systemBevelButtonActiveText
+systemBevelButtonInactiveText
+systemBevelButtonPressedText
+systemBevelButtonStickyActiveText
+systemBevelButtonStickyInactiveText
+systemBevelInactiveDark
+systemBevelInactiveLight
+systemBlack
+systemBlackText
+systemButtonActiveDarkHighlight
+systemButtonActiveDarkShadow
+systemButtonActiveLightHighlight
+systemButtonActiveLightShadow
+systemButtonFace
+systemButtonFaceActive
+systemButtonFaceInactive
+systemButtonFacePressed
+systemButtonFrame
+systemButtonFrameActive
+systemButtonFrameInactive
+systemButtonInactiveDarkHighlight
+systemButtonInactiveDarkShadow
+systemButtonInactiveLightHighlight
+systemButtonInactiveLightShadow
+systemButtonPressedDarkHighlight
+systemButtonPressedDarkShadow
+systemButtonPressedLightHighlight
+systemButtonPressedLightShadow
+systemButtonText
+systemChasingArrows
+systemDialogActiveText
+systemDialogBackgroundActive
+systemDialogBackgroundInactive
+systemDialogInactiveText
+systemDocumentWindowBackground
+systemDocumentWindowTitleActiveText
+systemDocumentWindowTitleInactiveText
+systemDragHilite
+systemDrawerBackground
+systemFinderWindowBackground
+systemFocusHighlight
+systemHighlight
+systemHighlightAlternate
+systemHighlightSecondary
+systemHighlightText
+systemIconLabelBackground
+systemIconLabelBackgroundSelected
+systemIconLabelSelectedText
+systemIconLabelText
+systemListViewBackground
+systemListViewColumnDivider
+systemListViewEvenRowBackground
+systemListViewOddRowBackground
+systemListViewSeparator
+systemListViewSortColumnBackground
+systemListViewText
+systemListViewWindowHeaderBackground
+systemMenu
+systemMenuActive
+systemMenuActiveText
+systemMenuBackground
+systemMenuBackgroundSelected
+systemMenuDisabled
+systemMenuItemActiveText
+systemMenuItemDisabledText
+systemMenuItemSelectedText
+systemMenuText
+systemMetalBackground
+systemModelessDialogActiveText
+systemModelessDialogBackgroundActive
+systemModelessDialogBackgroundInactive
+systemModelessDialogInactiveText
+systemMovableModalBackground
+systemMovableModalWindowTitleActiveText
+systemMovableModalWindowTitleInactiveText
+systemNotificationText
+systemNotificationWindowBackground
+systemPlacardActiveText
+systemPlacardBackground
+systemPlacardInactiveText
+systemPlacardPressedText
+systemPopupArrowActive
+systemPopupArrowInactive
+systemPopupArrowPressed
+systemPopupButtonActiveText
+systemPopupButtonInactiveText
+systemPopupButtonPressedText
+systemPopupLabelActiveText
+systemPopupLabelInactiveText
+systemPopupWindowTitleActiveText
+systemPopupWindowTitleInactiveText
+systemPrimaryHighlightColor
+systemPushButtonActiveText
+systemPushButtonInactiveText
+systemPushButtonPressedText
+systemRootMenuActiveText
+systemRootMenuDisabledText
+systemRootMenuSelectedText
+systemScrollBarDelimiterActive
+systemScrollBarDelimiterInactive
+systemSecondaryGroupBoxBackground
+systemSecondaryHighlightColor
+systemSelectedTabTextColor
+systemSheetBackground
+systemSheetBackgroundOpaque
+systemSheetBackgroundTransparent
+systemStaticAreaFill
+systemSystemDetailText
+systemTabFrontActiveText
+systemTabFrontInactiveText
+systemTabNonFrontActiveText
+systemTabNonFrontInactiveText
+systemTabNonFrontPressedText
+systemTabPaneBackground
+systemToolbarBackground
+systemTransparent
+systemUtilityWindowBackgroundActive
+systemUtilityWindowBackgroundInactive
+systemUtilityWindowTitleActiveText
+systemUtilityWindowTitleInactiveText
+systemWhite
+systemWhiteText
+systemWindowBody
+systemWindowHeaderActiveText
+systemWindowHeaderBackground
+systemWindowHeaderInactiveText
+.DE
+.RE
+.
+The second group of MacOS colors below are based on Apple's "semantic"
+NScolors. On OSX 10.14 (Mojave) and later these colors change value
+when Dark Mode is enabled. However, the change is only observable
+when the Apple window manager is drawing to the screen. So the
+\fBwinfo rgb\fR command will return the color coordinates used in the
+standard Aqua mode, even if Dark Mode has been selected in the system
+preferences. The numbered systemWindowBackgroundColors are used in
+the \fBttk::notebook\fR and \fBttk::labelframe\fR widgets to provide a
+contrasting background. Each numbered color constrasts with its
+predecessor.
+.RS
+.DS
+systemControlAccentColor
+systemControlTextColor
+systemDisabledControlTextColor
+systemLabelColor
+systemSelectedTextBackgroundColor
+systemSelectedTextColor
+systemTextBackgroundColor
+systemTextColor
+systemWindowBackgroundColor
+systemWindowBackgroundColor1
+systemWindowBackgroundColor2
+systemWindowBackgroundColor3
+systemWindowBackgroundColor4
+systemWindowBackgroundColor5
+systemWindowBackgroundColor6
+systemWindowBackgroundColor7
+.DE
+.RE
+.TP
+
+
+\fBWindows\fR
+.
+On Windows, the following additional system colors are available
+(note that the actual color values depend on the currently active OS theme):
+.RS
+.DS
+.ta 6c
+system3dDarkShadow systemHighlight
+system3dLight systemHighlightText
+systemActiveBorder systemInactiveBorder
+systemActiveCaption systemInactiveCaption
+systemAppWorkspace systemInactiveCaptionText
+systemBackground systemInfoBackground
+systemButtonFace systemInfoText
+systemButtonHighlight systemMenu
+systemButtonShadow systemMenuText
+systemButtonText systemScrollbar
+systemCaptionText systemWindow
+systemDisabledText systemWindowFrame
+systemGrayText systemWindowText
+.DE
+.RE
+.SH "SEE ALSO"
+options(n), Tk_GetColor(3)
+.SH KEYWORDS
+color, option
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/console.n b/tk8.6/doc/console.n
new file mode 100644
index 0000000..1313d3a
--- /dev/null
+++ b/tk8.6/doc/console.n
@@ -0,0 +1,145 @@
+'\"
+'\" Copyright (c) 2001 Donal K. Fellows
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH console n 8.4 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+console \- Control the console on systems without a real console
+.SH SYNOPSIS
+\fBconsole\fR \fIsubcommand\fR ?\fIarg ...\fR?
+.BE
+.SH DESCRIPTION
+.PP
+The console window is a replacement for a real console to allow input
+and output on the standard I/O channels on platforms that do not have
+a real console. It is implemented as a separate interpreter with the
+Tk toolkit loaded, and control over this interpreter is given through
+the \fBconsole\fR command. The behaviour of the console window is
+defined mainly through the contents of the \fIconsole.tcl\fR file in
+the Tk library. Except for TkAqua, this command is not available when
+Tk is loaded into a tclsh interpreter with
+.QW "\fBpackage require Tk\fR" ,
+as a conventional terminal is expected to be present in that case.
+In TkAqua, this command is only available when stdin is \fB/dev/null\fR
+(as is the case e.g. when the application embedding Tk is started
+from the Mac OS X Finder).
+.PP
+.TP
+\fBconsole eval \fIscript\fR
+Evaluate the \fIscript\fR argument as a Tcl script in the console
+interpreter. The normal interpreter is accessed through the
+\fBconsoleinterp\fR command in the console interpreter.
+.TP
+\fBconsole hide\fR
+Hide the console window from view. Precisely equivalent to
+withdrawing the \fB.\fR window in the console interpreter.
+.TP
+\fBconsole show\fR
+Display the console window. Precisely equivalent to deiconifying the
+\fB.\fR window in the console interpreter.
+.TP
+\fBconsole title \fR?\fIstring\fR?
+Query or modify the title of the console window. If \fIstring\fR is
+not specified, queries the title of the console window, and sets the
+title of the console window to \fIstring\fR otherwise. Precisely
+equivalent to using the \fBwm title\fR command in the console
+interpreter.
+.SH "ACCESS TO THE MAIN INTERPRETER"
+.PP
+The \fBconsoleinterp\fR command in the console interpreter allows
+scripts to be evaluated in the main interpreter. It supports two
+subcommands: \fBeval\fR and \fBrecord\fR.
+.PP
+.TP
+\fBconsoleinterp eval \fIscript\fR
+Evaluates \fIscript\fR as a Tcl script at the global level in the main
+interpreter.
+.TP
+\fBconsoleinterp record \fIscript\fR
+Records and evaluates \fIscript\fR as a Tcl script at the global level
+in the main interpreter as if \fIscript\fR had been typed in at the
+console.
+.SH "ADDITIONAL TRAP CALLS"
+.PP
+There are several additional commands in the console interpreter that
+are called in response to activity in the main interpreter.
+\fIThese are documented here for completeness only; they form part of
+the internal implementation of the console and are likely to change or
+be modified without warning.\fR
+.PP
+Output to the console from the main interpreter via the stdout and
+stderr channels is handled by invoking the \fBtk::ConsoleOutput\fR
+command in the console interpreter with two arguments. The first
+argument is the name of the channel being written to, and the second
+argument is the string being written to the channel (after encoding
+and end-of-line translation processing has been performed.)
+.PP
+When the \fB.\fR window of the main interpreter is destroyed, the
+\fBtk::ConsoleExit\fR command in the console interpreter is called
+(assuming the console interpreter has not already been deleted itself,
+that is.)
+.SH "DEFAULT BINDINGS"
+.PP
+The default script creates a console window (implemented using a text
+widget) that has the following behaviour:
+.IP [1]
+Pressing the tab key inserts a TAB character (as defined by the Tcl
+\et escape.)
+.IP [2]
+Pressing the return key causes the current line (if complete by the
+rules of \fBinfo complete\fR) to be passed to the main interpreter for
+evaluation.
+.IP [3]
+Pressing the delete key deletes the selected text (if any text is
+selected) or the character to the right of the cursor (if not at the
+end of the line.)
+.IP [4]
+Pressing the backspace key deletes the selected text (if any text is
+selected) or the character to the left of the cursor (of not at the
+start of the line.)
+.IP [5]
+Pressing either Control+A or the home key causes the cursor to go to
+the start of the line (but after the prompt, if a prompt is present on
+the line.)
+.IP [6]
+Pressing either Control+E or the end key causes the cursor to go to
+the end of the line.
+.IP [7]
+Pressing either Control+P or the up key causes the previous entry in
+the command history to be selected.
+.IP [8]
+Pressing either Control+N or the down key causes the next entry in the
+command history to be selected.
+.IP [9]
+Pressing either Control+B or the left key causes the cursor to move
+one character backward as long as the cursor is not at the prompt.
+.IP [10]
+Pressing either Control+F or the right key causes the cursor to move
+one character forward.
+.IP [11]
+Pressing F9 rebuilds the console window by destroying all its children
+and reloading the Tcl script that defined the console's behaviour.
+.PP
+Most other behaviour is the same as a conventional text widget except
+for the way that the \fI<<Cut>>\fR event is handled identically to the
+\fI<<Copy>>\fR event.
+.SH EXAMPLE
+.PP
+Not all platforms have the \fBconsole\fR command, so debugging code
+often has the following code fragment in it so output produced by
+\fBputs\fR can be seen while during development:
+.CS
+catch {\fBconsole show\fR}
+.CE
+.SH "SEE ALSO"
+destroy(n), fconfigure(n), history(n), interp(n), puts(n), text(n), wm(n)
+.SH KEYWORDS
+console, interpreter, window, interactive, output channels
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/cursors.n b/tk8.6/doc/cursors.n
new file mode 100644
index 0000000..1662de4
--- /dev/null
+++ b/tk8.6/doc/cursors.n
@@ -0,0 +1,191 @@
+'\"
+'\" Copyright (c) 1998-2000 by Scriptics Corporation.
+'\" All rights reserved.
+'\"
+'\" Copyright (c) 2006-2007 Daniel A. Steffen <das@users.sourceforge.net>
+'\"
+.TH cursors n 8.3 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+cursors \- mouse cursors available in Tk
+.BE
+.SH DESCRIPTION
+.PP
+The \fB\-cursor\fR widget option allows a Tk programmer to change the
+mouse cursor for a particular widget. The cursor names recognized by
+Tk on all platforms are:
+.CS
+X_cursor
+arrow
+based_arrow_down
+based_arrow_up
+boat
+bogosity
+bottom_left_corner
+bottom_right_corner
+bottom_side
+bottom_tee
+box_spiral
+center_ptr
+circle
+clock
+coffee_mug
+cross
+cross_reverse
+crosshair
+diamond_cross
+dot
+dotbox
+double_arrow
+draft_large
+draft_small
+draped_box
+exchange
+fleur
+gobbler
+gumby
+hand1
+hand2
+heart
+icon
+iron_cross
+left_ptr
+left_side
+left_tee
+leftbutton
+ll_angle
+lr_angle
+man
+middlebutton
+mouse
+none
+pencil
+pirate
+plus
+question_arrow
+right_ptr
+right_side
+right_tee
+rightbutton
+rtl_logo
+sailboat
+sb_down_arrow
+sb_h_double_arrow
+sb_left_arrow
+sb_right_arrow
+sb_up_arrow
+sb_v_double_arrow
+shuttle
+sizing
+spider
+spraycan
+star
+target
+tcross
+top_left_arrow
+top_left_corner
+top_right_corner
+top_side
+top_tee
+trek
+ul_angle
+umbrella
+ur_angle
+watch
+xterm
+.CE
+.PP
+The \fBnone\fR cursor can be specified to eliminate the cursor.
+.SH "PORTABILITY ISSUES"
+.TP
+\fBWindows\fR
+On Windows systems, the following cursors are mapped to native cursors:
+.RS
+.CS
+arrow
+center_ptr
+crosshair
+fleur
+ibeam
+icon
+none
+sb_h_double_arrow
+sb_v_double_arrow
+watch
+xterm
+.CE
+And the following additional cursors are available:
+.CS
+no
+starting
+size
+size_ne_sw
+size_ns
+size_nw_se
+size_we
+uparrow
+wait
+.CE
+.RE
+.TP
+\fBMac OS X\fR
+On Mac OS X systems, the following cursors are mapped to native cursors:
+.RS
+.CS
+arrow
+top_left_arrow
+left_ptr
+cross
+crosshair
+tcross
+ibeam
+none
+xterm
+.CE
+And the following additional native cursors are available:
+.CS
+copyarrow
+aliasarrow
+contextualmenuarrow
+movearrow
+text
+cross-hair
+hand
+openhand
+closedhand
+fist
+pointinghand
+resize
+resizeleft
+resizeright
+resizeleftright
+resizeup
+resizedown
+resizeupdown
+resizebottomleft
+resizetopleft
+resizebottomright
+resizetopright
+notallowed
+poof
+wait
+countinguphand
+countingdownhand
+countingupanddownhand
+spinning
+help
+bucket
+cancel
+eyedrop
+eyedrop-full
+zoom-in
+zoom-out
+.CE
+.RE
+.SH KEYWORDS
+cursor, option
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/destroy.n b/tk8.6/doc/destroy.n
new file mode 100644
index 0000000..3d4743a
--- /dev/null
+++ b/tk8.6/doc/destroy.n
@@ -0,0 +1,45 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH destroy n "" Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+destroy \- Destroy one or more windows
+.SH SYNOPSIS
+\fBdestroy \fR?\fIwindow window ...\fR?
+.BE
+.SH DESCRIPTION
+.PP
+This command deletes the windows given by the
+\fIwindow\fR arguments, plus all of their descendants.
+If a \fIwindow\fR
+.QW .
+is deleted then all windows will be destroyed and the application will
+(normally) exit.
+The \fIwindow\fRs are destroyed in order, and if an error occurs
+in destroying a window the command aborts without destroying the
+remaining windows.
+No error is returned if \fIwindow\fR does not exist.
+.SH EXAMPLE
+.PP
+Destroy all checkbuttons that are direct children of the given widget:
+.CS
+proc killCheckbuttonChildren {parent} {
+ foreach w [winfo children $parent] {
+ if {[winfo class $w] eq "Checkbutton"} {
+ \fBdestroy\fR $w
+ }
+ }
+}
+.CE
+.SH KEYWORDS
+application, destroy, window
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/dialog.n b/tk8.6/doc/dialog.n
new file mode 100644
index 0000000..d2031d3
--- /dev/null
+++ b/tk8.6/doc/dialog.n
@@ -0,0 +1,74 @@
+'\"
+'\" Copyright (c) 1992 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH tk_dialog n 4.1 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+tk_dialog \- Create modal dialog and wait for response
+.SH SYNOPSIS
+\fBtk_dialog \fIwindow title text bitmap default string string ...\fR
+.BE
+.SH DESCRIPTION
+.PP
+This procedure is part of the Tk script library.
+It is largely \fIdeprecated\fR by the \fBtk_messageBox\fR.
+Its arguments describe a dialog box:
+.TP
+\fIwindow\fR
+Name of top-level window to use for dialog. Any existing window
+by this name is destroyed.
+.TP
+\fItitle\fR
+Text to appear in the window manager's title bar for the dialog.
+.TP
+\fItext\fR
+Message to appear in the top portion of the dialog box.
+.TP
+\fIbitmap\fR
+If non-empty, specifies a bitmap (in a form suitable for Tk_GetBitmap)
+to display in the top portion of
+the dialog, to the left of the text.
+If this is an empty string then no bitmap is displayed in the dialog.
+.TP
+\fIdefault\fR
+If this is an integer greater than or equal to zero, then it gives
+the index of the button that is to be the default button for the dialog
+(0 for the leftmost button, and so on).
+If less than zero or an empty string then there will not be any default
+button.
+.TP
+\fIstring\fR
+There will be one button for each of these arguments.
+Each \fIstring\fR specifies text to display in a button,
+in order from left to right.
+.PP
+After creating a dialog box, \fBtk_dialog\fR waits for the user to
+select one of the buttons either by clicking on the button with the
+mouse or by typing return to invoke the default button (if any).
+Then it returns the index of the selected button: 0 for the leftmost
+button, 1 for the button next to it, and so on.
+If the dialog's window is destroyed before the user selects one
+of the buttons, then \-1 is returned.
+.PP
+While waiting for the user to respond, \fBtk_dialog\fR sets a local
+grab. This prevents the user from interacting with the application
+in any way except to invoke the dialog box.
+.SH EXAMPLE
+.PP
+.CS
+set reply [\fBtk_dialog\fR .foo "The Title" "Do you want to say yes?" \e
+ questhead 0 Yes No "I'm not sure"]
+.CE
+.SH "SEE ALSO"
+tk_messageBox(n)
+.SH KEYWORDS
+bitmap, dialog, modal
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/entry.n b/tk8.6/doc/entry.n
new file mode 100644
index 0000000..ccfcd24
--- /dev/null
+++ b/tk8.6/doc/entry.n
@@ -0,0 +1,539 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
+'\" Copyright (c) 1998-2000 Scriptics Corporation.
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH entry n 8.3 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+entry \- Create and manipulate 'entry' one-line text entry widgets
+.SH SYNOPSIS
+\fBentry\fR \fIpathName \fR?\fIoptions\fR?
+.SO
+\-background \-highlightthickness \-selectbackground
+\-borderwidth \-insertbackground \-selectborderwidth
+\-cursor \-insertborderwidth \-selectforeground
+\-exportselection \-insertofftime \-takefocus
+\-font \-insertontime \-textvariable
+\-foreground \-insertwidth \-xscrollcommand
+\-highlightbackground \-justify
+\-highlightcolor \-relief
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-disabledbackground disabledBackground DisabledBackground
+Specifies the background color to use when the entry is disabled. If
+this option is the empty string, the normal background color is used.
+.OP \-disabledforeground disabledForeground DisabledForeground
+Specifies the foreground color to use when the entry is disabled. If
+this option is the empty string, the normal foreground color is used.
+.OP "\-invalidcommand or \-invcmd" invalidCommand InvalidCommand
+Specifies a script to eval when \fB\-validatecommand\fR returns 0.
+Setting it to {} disables this feature (the default). The best use
+of this option is to set it to \fIbell\fR. See \fBVALIDATION\fR
+below for more information.
+.OP \-readonlybackground readonlyBackground ReadonlyBackground
+Specifies the background color to use when the entry is readonly. If
+this option is the empty string, the normal background color is used.
+.OP \-show show Show
+If this option is specified, then the true contents of the entry
+are not displayed in the window.
+Instead, each character in the entry's value will be displayed as
+the first character in the value of this option, such as
+.QW * .
+This is useful, for example, if the entry is to be used to enter
+a password.
+If characters in the entry are selected and copied elsewhere, the
+information copied will be what is displayed, not the true contents
+of the entry.
+.OP \-state state State
+Specifies one of three states for the entry: \fBnormal\fR,
+\fBdisabled\fR, or \fBreadonly\fR. If the entry is readonly, then the
+value may not be changed using widget commands and no insertion cursor
+will be displayed, even if the input focus is in the widget; the
+contents of the widget may still be selected. If the entry is
+disabled, the value may not be changed, no insertion cursor will be
+displayed, the contents will not be selectable, and the entry may
+be displayed in a different color, depending on the values of the
+\fB\-disabledforeground\fR and \fB\-disabledbackground\fR options.
+.OP \-validate validate Validate
+Specifies the mode in which validation should operate: \fBnone\fR,
+\fBfocus\fR, \fBfocusin\fR, \fBfocusout\fR, \fBkey\fR, or \fBall\fR.
+It defaults to \fBnone\fR. When you want validation, you must explicitly
+state which mode you wish to use. See \fBVALIDATION\fR below for more.
+.OP "\-validatecommand or \-vcmd" validateCommand ValidateCommand
+Specifies a script to eval when you want to validate the input into
+the entry widget. Setting it to {} disables this feature (the default).
+This command must return a valid Tcl boolean value. If it returns 0 (or
+the valid Tcl boolean equivalent) then it means you reject the new edition
+and it will not occur and the \fB\-invalidcommand\fR will be evaluated if it
+is set. If it returns 1, then the new edition occurs.
+See \fBVALIDATION\fR below for more information.
+.OP \-width width Width
+Specifies an integer value indicating the desired width of the entry window,
+in average-size characters of the widget's font.
+If the value is less than or equal to zero, the widget picks a
+size just large enough to hold its current text.
+.BE
+.SH DESCRIPTION
+.PP
+The \fBentry\fR command creates a new window (given by the
+\fIpathName\fR argument) and makes it into an entry widget.
+Additional options, described above, may be specified on the
+command line or in the option database
+to configure aspects of the entry such as its colors, font,
+and relief. The \fBentry\fR command returns its
+\fIpathName\fR argument. At the time this command is invoked,
+there must not exist a window named \fIpathName\fR, but
+\fIpathName\fR's parent must exist.
+.PP
+An entry is a widget that displays a one-line text string and
+allows that string to be edited using widget commands described below, which
+are typically bound to keystrokes and mouse actions.
+When first created, an entry's string is empty.
+A portion of the entry may be selected as described below.
+If an entry is exporting its selection (see the \fB\-exportselection\fR
+option), then it will observe the standard X11 protocols for handling the
+selection; entry selections are available as type \fBSTRING\fR.
+Entries also observe the standard Tk rules for dealing with the
+input focus. When an entry has the input focus it displays an
+\fIinsertion cursor\fR to indicate where new characters will be
+inserted.
+.PP
+Entries are capable of displaying strings that are too long to
+fit entirely within the widget's window. In this case, only a
+portion of the string will be displayed; commands described below
+may be used to change the view in the window. Entries use
+the standard \fB\-xscrollcommand\fR mechanism for interacting with
+scrollbars (see the description of the \fB\-xscrollcommand\fR option
+for details). They also support scanning, as described below.
+.SH VALIDATION
+.PP
+Validation works by setting the \fB\-validatecommand\fR option to a
+script (\fIvalidateCommand\fR) which will be evaluated according to
+the \fB\-validate\fR option as follows:
+.PP
+.IP \fBnone\fR 10
+Default. This means no validation will occur.
+.IP \fBfocus\fR 10
+\fIvalidateCommand\fR will be called when the entry receives or
+loses focus.
+.IP \fBfocusin\fR 10
+\fIvalidateCommand\fR will be called when the entry receives focus.
+.IP \fBfocusout\fR 10
+\fIvalidateCommand\fR will be called when the entry loses focus.
+.IP \fBkey\fR 10
+\fIvalidateCommand\fR will be called when the entry is edited.
+.IP \fBall\fR 10
+\fIvalidateCommand\fR will be called for all above conditions.
+.PP
+It is possible to perform percent substitutions on the value of the
+\fB\-validatecommand\fR and \fB\-invalidcommand\fR options,
+just as you would in a \fBbind\fR script. The following substitutions
+are recognized:
+.PP
+.IP \fB%d\fR 5
+Type of action: 1 for \fBinsert\fR, 0 for \fBdelete\fR,
+or \-1 for focus, forced or textvariable validation.
+.IP \fB%i\fR 5
+Index of char string to be inserted/deleted, if any, otherwise \-1.
+.IP \fB%P\fR 5
+The value of the entry if the edit is allowed. If you are configuring the
+entry widget to have a new textvariable, this will be the value of that
+textvariable.
+.IP \fB%s\fR 5
+The current value of entry prior to editing.
+.IP \fB%S\fR 5
+The text string being inserted/deleted, if any, {} otherwise.
+.IP \fB%v\fR 5
+The type of validation currently set.
+.IP \fB%V\fR 5
+The type of validation that triggered the callback
+(key, focusin, focusout, forced).
+.IP \fB%W\fR 5
+The name of the entry widget.
+.PP
+In general, the \fB\-textvariable\fR and \fB\-validatecommand\fR options can be
+dangerous to mix. Any problems have been overcome so that using the
+\fB\-validatecommand\fR will not interfere with the traditional behavior of
+the entry widget. Using the \fB\-textvariable\fR for read-only purposes will
+never cause problems. The danger comes when you try set the
+\fB\-textvariable\fR to something that the \fB\-validatecommand\fR would not
+accept, which causes \fB\-validate\fR to become \fInone\fR (the
+\fB\-invalidcommand\fR will not be triggered). The same happens
+when an error occurs evaluating the \fB\-validatecommand\fR.
+.PP
+Primarily, an error will occur when the \fB\-validatecommand\fR or
+\fB\-invalidcommand\fR encounters an error in its script while evaluating or
+\fB\-validatecommand\fR does not return a valid Tcl boolean value. The
+\fB\-validate\fR option will also set itself to \fBnone\fR when you edit the
+entry widget from within either the \fB\-validatecommand\fR or the
+\fB\-invalidcommand\fR. Such editions will override the one that was being
+validated. If you wish to edit the entry widget (for example set it to {})
+during validation and still have the \fB\-validate\fR option set, you should
+include the command
+.CS
+after idle {%W config \-validate %v}
+.CE
+in the \fB\-validatecommand\fR or \fB\-invalidcommand\fR (whichever one you
+were editing the entry widget from). It is also recommended to not set an
+associated \fB\-textvariable\fR during validation, as that can cause the
+entry widget to become out of sync with the \fB\-textvariable\fR.
+.SH "WIDGET COMMAND"
+.PP
+The \fBentry\fR command creates a new Tcl command whose
+name is \fIpathName\fR. This command may be used to invoke various
+operations on the widget. It has the following general form:
+.CS
+\fIpathName subcommand \fR?\fIarg arg ...\fR?
+.CE
+\fISubcommand\fR and the \fIarg\fRs
+determine the exact behavior of the command.
+.SS INDICES
+.PP
+Many of the widget commands for entries take one or more indices as
+arguments. An index specifies a particular character in the entry's
+string, in any of the following ways:
+.TP 12
+\fInumber\fR
+Specifies the character as a numerical index, where 0 corresponds
+to the first character in the string.
+.TP 12
+\fBanchor\fR
+Indicates the anchor point for the selection, which is set with the
+\fBselect from\fR and \fBselect adjust\fR widget commands.
+.TP 12
+\fBend\fR
+Indicates the character just after the last one in the entry's string.
+This is equivalent to specifying a numerical index equal to the length
+of the entry's string.
+.TP 12
+\fBinsert\fR
+Indicates the character adjacent to and immediately following the
+insertion cursor.
+.TP 12
+\fBsel.first\fR
+Indicates the first character in the selection. It is an error to
+use this form if the selection is not in the entry window.
+.TP 12
+\fBsel.last\fR
+Indicates the character just after the last one in the selection.
+It is an error to use this form if the selection is not in the
+entry window.
+.TP 12
+\fB@\fInumber\fR
+In this form, \fInumber\fR is treated as an x-coordinate in the
+entry's window; the character spanning that x-coordinate is used.
+For example,
+.QW \fB@0\fR
+indicates the left-most character in the window.
+.LP
+Abbreviations may be used for any of the forms above, e.g.
+.QW \fBe\fR
+or
+.QW \fBsel.f\fR .
+In general, out-of-range indices are automatically rounded to the
+nearest legal value.
+.SS SUBCOMMANDS
+.PP
+The following commands are possible for entry widgets:
+.TP
+\fIpathName \fBbbox \fIindex\fR
+Returns a list of four numbers describing the bounding box of the
+character given by \fIindex\fR.
+The first two elements of the list give the x and y coordinates of
+the upper-left corner of the screen area covered by the character
+(in pixels relative to the widget) and the last two elements give
+the width and height of the character, in pixels.
+The bounding box may refer to a region outside the visible area
+of the window.
+.TP
+\fIpathName \fBcget\fR \fIoption\fR
+Returns the current value of the configuration option given
+by \fIoption\fR.
+\fIOption\fR may have any of the values accepted by the \fBentry\fR
+command.
+.TP
+\fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
+Query or modify the configuration options of the widget.
+If no \fIoption\fR is specified, returns a list describing all of
+the available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for
+information on the format of this list). If \fIoption\fR is specified
+with no \fIvalue\fR, then the command returns a list describing the
+one named option (this list will be identical to the corresponding
+sublist of the value returned if no \fIoption\fR is specified). If
+one or more \fIoption\-value\fR pairs are specified, then the command
+modifies the given widget option(s) to have the given value(s); in
+this case the command returns an empty string.
+\fIOption\fR may have any of the values accepted by the \fBentry\fR
+command.
+.TP
+\fIpathName \fBdelete \fIfirst \fR?\fIlast\fR?
+Delete one or more elements of the entry.
+\fIFirst\fR is the index of the first character to delete, and
+\fIlast\fR is the index of the character just after the last
+one to delete.
+If \fIlast\fR is not specified it defaults to \fIfirst\fR+1,
+i.e. a single character is deleted.
+This command returns an empty string.
+.TP
+\fIpathName \fBget\fR
+Returns the entry's string.
+.TP
+\fIpathName \fBicursor \fIindex\fR
+Arrange for the insertion cursor to be displayed just before the character
+given by \fIindex\fR. Returns an empty string.
+.TP
+\fIpathName \fBindex\fI index\fR
+Returns the numerical index corresponding to \fIindex\fR.
+.TP
+\fIpathName \fBinsert \fIindex string\fR
+Insert the characters of \fIstring\fR just before the character
+indicated by \fIindex\fR. Returns an empty string.
+.TP
+\fIpathName \fBscan\fR \fIoption args\fR
+This command is used to implement scanning on entries. It has
+two forms, depending on \fIoption\fR:
+.RS
+.TP
+\fIpathName \fBscan mark \fIx\fR
+Records \fIx\fR and the current view in the entry window; used in
+conjunction with later \fBscan dragto\fR commands. Typically this
+command is associated with a mouse button press in the widget. It
+returns an empty string.
+.TP
+\fIpathName \fBscan dragto \fIx\fR
+This command computes the difference between its \fIx\fR argument
+and the \fIx\fR argument to the last \fBscan mark\fR command for
+the widget. It then adjusts the view left or right by 10 times the
+difference in x-coordinates. This command is typically associated
+with mouse motion events in the widget, to produce the effect of
+dragging the entry at high speed through the window. The return
+value is an empty string.
+.RE
+.TP
+\fIpathName \fBselection \fIoption arg\fR
+This command is used to adjust the selection within an entry. It
+has several forms, depending on \fIoption\fR:
+.RS
+.TP
+\fIpathName \fBselection adjust \fIindex\fR
+Locate the end of the selection nearest to the character given by
+\fIindex\fR, and adjust that end of the selection to be at \fIindex\fR
+(i.e. including but not going beyond \fIindex\fR). The other
+end of the selection is made the anchor point for future
+\fBselect to\fR commands. If the selection
+is not currently in the entry, then a new selection is created to
+include the characters between \fIindex\fR and the most recent
+selection anchor point, inclusive.
+Returns an empty string.
+.TP
+\fIpathName \fBselection clear\fR
+Clear the selection if it is currently in this widget. If the
+selection is not in this widget then the command has no effect.
+Returns an empty string.
+.TP
+\fIpathName \fBselection from \fIindex\fR
+Set the selection anchor point to just before the character
+given by \fIindex\fR. Does not change the selection.
+Returns an empty string.
+.TP
+\fIpathName \fBselection present\fR
+Returns 1 if there is are characters selected in the entry,
+0 if nothing is selected.
+.TP
+\fIpathName \fBselection range \fIstart\fR \fIend\fR
+Sets the selection to include the characters starting with
+the one indexed by \fIstart\fR and ending with the one just
+before \fIend\fR.
+If \fIend\fR refers to the same character as \fIstart\fR or an
+earlier one, then the entry's selection is cleared.
+.TP
+\fIpathName \fBselection to \fIindex\fR
+If \fIindex\fR is before the anchor point, set the selection
+to the characters from \fIindex\fR up to but not including
+the anchor point.
+If \fIindex\fR is the same as the anchor point, do nothing.
+If \fIindex\fR is after the anchor point, set the selection
+to the characters from the anchor point up to but not including
+\fIindex\fR.
+The anchor point is determined by the most recent \fBselect from\fR
+or \fBselect adjust\fR command in this widget.
+If the selection is not in this widget then a new selection is
+created using the most recent anchor point specified for the widget.
+Returns an empty string.
+.RE
+.TP
+\fIpathName \fBvalidate\fR
+This command is used to force an evaluation of the \fB\-validatecommand\fR
+independent of the conditions specified by the \fB\-validate\fR option.
+This is done by temporarily setting the \fB\-validate\fR option to \fBall\fR.
+It returns 0 or 1.
+.TP
+\fIpathName \fBxview \fIargs\fR
+This command is used to query and change the horizontal position of the
+text in the widget's window. It can take any of the following
+forms:
+.RS
+.TP
+\fIpathName \fBxview\fR
+Returns a list containing two elements.
+Each element is a real fraction between 0 and 1; together they describe
+the horizontal span that is visible in the window.
+For example, if the first element is .2 and the second element is .6,
+20% of the entry's text is off-screen to the left, the middle 40% is visible
+in the window, and 40% of the text is off-screen to the right.
+These are the same values passed to scrollbars via the \fB\-xscrollcommand\fR
+option.
+.TP
+\fIpathName \fBxview\fR \fIindex\fR
+Adjusts the view in the window so that the character given by \fIindex\fR
+is displayed at the left edge of the window.
+.TP
+\fIpathName \fBxview moveto\fI fraction\fR
+Adjusts the view in the window so that the character \fIfraction\fR of the
+way through the text appears at the left edge of the window.
+\fIFraction\fR must be a fraction between 0 and 1.
+.TP
+\fIpathName \fBxview scroll \fInumber what\fR
+This command shifts the view in the window left or right according to
+\fInumber\fR and \fIwhat\fR.
+\fINumber\fR must be an integer.
+\fIWhat\fR must be either \fBunits\fR or \fBpages\fR or an abbreviation
+of one of these.
+If \fIwhat\fR is \fBunits\fR, the view adjusts left or right by
+\fInumber\fR average-width characters on the display; if it is
+\fBpages\fR then the view adjusts by \fInumber\fR screenfuls.
+If \fInumber\fR is negative then characters farther to the left
+become visible; if it is positive then characters farther to the right
+become visible.
+.RE
+.SH "DEFAULT BINDINGS"
+.PP
+Tk automatically creates class bindings for entries that give them
+the following default behavior. In the descriptions below,
+.QW word
+refers to a contiguous group of letters, digits, or
+.QW _
+characters, or any single character other than these.
+.IP [1]
+Clicking mouse button 1 positions the insertion cursor
+just before the character underneath the mouse cursor, sets the
+input focus to this widget, and clears any selection in the widget.
+Dragging with mouse button 1 strokes out a selection between
+the insertion cursor and the character under the mouse.
+.IP [2]
+Double-clicking with mouse button 1 selects the word under the mouse
+and positions the insertion cursor at the end of the word.
+Dragging after a double click will stroke out a selection consisting
+of whole words.
+.IP [3]
+Triple-clicking with mouse button 1 selects all of the text in the
+entry and positions the insertion cursor at the end of the line.
+.IP [4]
+The ends of the selection can be adjusted by dragging with mouse
+button 1 while the Shift key is down; this will adjust the end
+of the selection that was nearest to the mouse cursor when button
+1 was pressed.
+If the button is double-clicked before dragging then the selection
+will be adjusted in units of whole words.
+.IP [5]
+Clicking mouse button 1 with the Control key down will position the
+insertion cursor in the entry without affecting the selection.
+.IP [6]
+If any normal printing characters are typed in an entry, they are
+inserted at the point of the insertion cursor.
+.IP [7]
+The view in the entry can be adjusted by dragging with mouse button 2.
+If mouse button 2 is clicked without moving the mouse, the selection
+is copied into the entry at the position of the mouse cursor.
+.IP [8]
+If the mouse is dragged out of the entry on the left or right sides
+while button 1 is pressed, the entry will automatically scroll to
+make more text visible (if there is more text off-screen on the side
+where the mouse left the window).
+.IP [9]
+The Left and Right keys move the insertion cursor one character to the
+left or right; they also clear any selection in the entry and set
+the selection anchor.
+If Left or Right is typed with the Shift key down, then the insertion
+cursor moves and the selection is extended to include the new character.
+Control-Left and Control-Right move the insertion cursor by words, and
+Control-Shift-Left and Control-Shift-Right move the insertion cursor
+by words and also extend the selection.
+Control-b and Control-f behave the same as Left and Right, respectively.
+Meta-b and Meta-f behave the same as Control-Left and Control-Right,
+respectively.
+.IP [10]
+The Home key, or Control-a, will move the insertion cursor to the
+beginning of the entry and clear any selection in the entry.
+Shift-Home moves the insertion cursor to the beginning of the entry
+and also extends the selection to that point.
+.IP [11]
+The End key, or Control-e, will move the insertion cursor to the
+end of the entry and clear any selection in the entry.
+Shift-End moves the cursor to the end and extends the selection
+to that point.
+.IP [12]
+The Select key and Control-Space set the selection anchor to the position
+of the insertion cursor. They do not affect the current selection.
+Shift-Select and Control-Shift-Space adjust the selection to the
+current position of the insertion cursor, selecting from the anchor
+to the insertion cursor if there was not any selection previously.
+.IP [13]
+Control-/ selects all the text in the entry.
+.IP [14]
+Control-\e clears any selection in the entry.
+.IP [15]
+The F16 key (labelled Copy on many Sun workstations) or Meta-w
+copies the selection in the widget to the clipboard, if there is a selection.
+.IP [16]
+The F20 key (labelled Cut on many Sun workstations) or Control-w
+copies the selection in the widget to the clipboard and deletes
+the selection.
+If there is no selection in the widget then these keys have no effect.
+.IP [17]
+The F18 key (labelled Paste on many Sun workstations) or Control-y
+inserts the contents of the clipboard at the position of the
+insertion cursor.
+.IP [18]
+The Delete key deletes the selection, if there is one in the entry.
+If there is no selection, it deletes the character to the right of
+the insertion cursor.
+.IP [19]
+The BackSpace key and Control-h delete the selection, if there is one
+in the entry.
+If there is no selection, it deletes the character to the left of
+the insertion cursor.
+.IP [20]
+Control-d deletes the character to the right of the insertion cursor.
+.IP [21]
+Meta-d deletes the word to the right of the insertion cursor.
+.IP [22]
+Control-k deletes all the characters to the right of the insertion
+cursor.
+.IP [23]
+Control-t reverses the order of the two characters to the right of
+the insertion cursor.
+.PP
+If the entry is disabled using the \fB\-state\fR option, then the entry's
+view can still be adjusted and text in the entry can still be selected,
+but no insertion cursor will be displayed and no text modifications will
+take place
+except if the entry is linked to a variable using the \fB\-textvariable\fR
+option, in which case any changes to the variable are reflected by the
+entry whatever the value of its \fB\-state\fR option.
+.PP
+The behavior of entries can be changed by defining new bindings for
+individual widgets or by redefining the class bindings.
+.SH "SEE ALSO"
+ttk::entry(n)
+.SH KEYWORDS
+entry, widget
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/event.n b/tk8.6/doc/event.n
new file mode 100644
index 0000000..5109794
--- /dev/null
+++ b/tk8.6/doc/event.n
@@ -0,0 +1,604 @@
+'\"
+'\" Copyright (c) 1996 Sun Microsystems, Inc.
+'\" Copyright (c) 1998-2000 Ajuba Solutions.
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH event n 8.3 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+event \- Miscellaneous event facilities: define virtual events and generate events
+.SH SYNOPSIS
+\fBevent\fI option \fR?\fIarg arg ...\fR?
+.BE
+.SH DESCRIPTION
+.PP
+The \fBevent\fR command provides several facilities for dealing with
+window system events, such as defining virtual events and synthesizing
+events. The command has several different forms, determined by the
+first argument. The following forms are currently supported:
+.TP
+\fBevent add <<\fIvirtual\fB>>\fI sequence \fR?\fIsequence ...\fR?
+Associates the virtual event \fIvirtual\fR with the physical
+event sequence(s) given by the \fIsequence\fR arguments, so that
+the virtual event will trigger whenever any one of the \fIsequence\fRs
+occurs.
+\fIVirtual\fR may be any string value and \fIsequence\fR may have
+any of the values allowed for the \fIsequence\fR argument to the
+\fBbind\fR command.
+If \fIvirtual\fR is already defined, the new physical event sequences
+add to the existing sequences for the event.
+.TP
+\fBevent delete <<\fIvirtual\fB>> \fR?\fIsequence\fR \fIsequence ...\fR?
+Deletes each of the \fIsequence\fRs from those associated with
+the virtual event given by \fIvirtual\fR.
+\fIVirtual\fR may be any string value and \fIsequence\fR may have
+any of the values allowed for the \fIsequence\fR argument to the
+\fBbind\fR command.
+Any \fIsequence\fRs not currently associated with \fIvirtual\fR
+are ignored.
+If no \fIsequence\fR argument is provided, all physical event sequences
+are removed for \fIvirtual\fR, so that the virtual event will not
+trigger anymore.
+.TP
+\fBevent generate \fIwindow event \fR?\fIoption value option value ...\fR?
+Generates a window event and arranges for it to be processed just as if
+it had come from the window system.
+\fIWindow\fR gives the path name of the window for which the event
+will be generated; it may also be an identifier (such as returned by
+\fBwinfo id\fR) as long as it is for a window in the current application.
+\fIEvent\fR provides a basic description of
+the event, such as \fB<Shift-Button-2>\fR or \fB<<Paste>>\fR.
+If \fIWindow\fR is empty the whole screen is meant, and coordinates
+are relative to the screen.
+\fIEvent\fR may have any of the forms allowed for the \fIsequence\fR
+argument of the \fBbind\fR command except that it must consist
+of a single event pattern, not a sequence.
+\fIOption-value\fR pairs may be used to specify additional
+attributes of the event, such as the x and y mouse position; see
+\fBEVENT FIELDS\fR below. If the \fB\-when\fR option is not specified, the
+event is processed immediately: all of the handlers for the event
+will complete before the \fBevent generate\fR command returns.
+If the \fB\-when\fR option is specified then it determines when the
+event is processed. Certain events, such as key events, require
+that the window has focus to receive the event properly.
+.TP
+\fBevent info \fR?\fB<<\fIvirtual\fB>>\fR?
+Returns information about virtual events.
+If the \fB<<\fIvirtual\fB>>\fR argument is omitted, the return value
+is a list of all the virtual events that are currently defined.
+If \fB<<\fIvirtual\fB>>\fR is specified then the return value is
+a list whose elements are the physical event sequences currently
+defined for the given virtual event; if the virtual event is
+not defined then an empty string is returned.
+.RS
+.PP
+Note that virtual events that are not bound to physical event
+sequences are \fInot\fR returned by \fBevent info\fR.
+.RE
+.SH "EVENT FIELDS"
+.PP
+The following options are supported for the \fBevent generate\fR
+command. These correspond to the
+.QW %
+expansions allowed in binding scripts for the \fBbind\fR command.
+.TP
+\fB\-above\fI window\fR
+\fIWindow\fR specifies the \fIabove\fR field for the event,
+either as a window path name or as an integer window id.
+Valid for \fBConfigure\fR events.
+Corresponds to the \fB%a\fR substitution for binding scripts.
+.TP
+\fB\-borderwidth\fI size\fR
+\fISize\fR must be a screen distance; it specifies the
+\fIborder_width\fR field for the event.
+Valid for \fBConfigure\fR events.
+Corresponds to the \fB%B\fR substitution for binding scripts.
+.TP
+\fB\-button\fI number\fR
+\fINumber\fR must be an integer; it specifies the \fIdetail\fR field
+for a \fBButtonPress\fR or \fBButtonRelease\fR event, overriding
+any button number provided in the base \fIevent\fR argument.
+Corresponds to the \fB%b\fR substitution for binding scripts.
+.TP
+\fB\-count\fI number\fR
+\fINumber\fR must be an integer; it specifies the \fIcount\fR field
+for the event. Valid for \fBExpose\fR events.
+Corresponds to the \fB%c\fR substitution for binding scripts.
+.TP
+\fB\-data\fI string\fR
+\fIString\fR may be any value; it specifies the \fIuser_data\fR field
+for the event. Only valid for virtual events. Corresponds to the
+\fB%d\fR substitution for virtual events in binding scripts.
+.TP
+\fB\-delta\fI number\fR
+\fINumber\fR must be an integer; it specifies the \fIdelta\fR field
+for the \fBMouseWheel\fR event. The \fIdelta\fR refers to the
+direction and magnitude the mouse wheel was rotated. Note the value
+is not a screen distance but are units of motion in the mouse wheel.
+Typically these values are multiples of 120. For example, 120 should
+scroll the text widget up 4 lines and \-240 would scroll the text
+widget down 8 lines. Of course, other widgets may define different
+behaviors for mouse wheel motion. This field corresponds to the
+\fB%D\fR substitution for binding scripts.
+.TP
+\fB\-detail\fI detail\fR
+\fIDetail\fR specifies the \fIdetail\fR field for the event
+and must be one of the following:
+.RS
+.DS
+.ta 6c
+\fBNotifyAncestor\fR \fBNotifyNonlinearVirtual\fR
+\fBNotifyDetailNone\fR \fBNotifyPointer\fR
+\fBNotifyInferior\fR \fBNotifyPointerRoot\fR
+\fBNotifyNonlinear\fR \fBNotifyVirtual\fR
+.DE
+Valid for \fBEnter\fR, \fBLeave\fR, \fBFocusIn\fR and
+\fBFocusOut\fR events.
+Corresponds to the \fB%d\fR substitution for binding scripts.
+.RE
+.TP
+\fB\-focus\fI boolean\fR
+\fIBoolean\fR must be a boolean value; it specifies the \fIfocus\fR
+field for the event.
+Valid for \fBEnter\fR and \fBLeave\fR events.
+Corresponds to the \fB%f\fR substitution for binding scripts.
+.TP
+\fB\-height\fI size\fR
+\fISize\fR must be a screen distance; it specifies the \fIheight\fR
+field for the event. Valid for \fBConfigure\fR events.
+Corresponds to the \fB%h\fR substitution for binding scripts.
+.TP
+\fB\-keycode\fI number\fR
+\fINumber\fR must be an integer; it specifies the \fIkeycode\fR
+field for the event.
+Valid for \fBKeyPress\fR and \fBKeyRelease\fR events.
+Corresponds to the \fB%k\fR substitution for binding scripts.
+.TP
+\fB\-keysym\fI name\fR
+\fIName\fR must be the name of a valid keysym, such as \fBg\fR,
+\fBspace\fR, or \fBReturn\fR; its corresponding
+keycode value is used as the \fIkeycode\fR field for event, overriding
+any detail specified in the base \fIevent\fR argument.
+Valid for \fBKeyPress\fR and \fBKeyRelease\fR events.
+Corresponds to the \fB%K\fR substitution for binding scripts.
+.TP
+\fB\-mode\fI notify\fR
+\fINotify\fR specifies the \fImode\fR field for the event and must be
+one of \fBNotifyNormal\fR, \fBNotifyGrab\fR, \fBNotifyUngrab\fR, or
+\fBNotifyWhileGrabbed\fR.
+Valid for \fBEnter\fR, \fBLeave\fR, \fBFocusIn\fR, and
+\fBFocusOut\fR events.
+Corresponds to the \fB%m\fR substitution for binding scripts.
+.TP
+\fB\-override\fI boolean\fR
+\fIBoolean\fR must be a boolean value; it specifies the
+\fIoverride_redirect\fR field for the event.
+Valid for \fBMap\fR, \fBReparent\fR, and \fBConfigure\fR events.
+Corresponds to the \fB%o\fR substitution for binding scripts.
+.TP
+\fB\-place\fI where\fR
+\fIWhere\fR specifies the \fIplace\fR field for the event; it must be
+either \fBPlaceOnTop\fR or \fBPlaceOnBottom\fR.
+Valid for \fBCirculate\fR events.
+Corresponds to the \fB%p\fR substitution for binding scripts.
+.TP
+\fB\-root\fI window\fR
+\fIWindow\fR must be either a window path name or an integer window
+identifier; it specifies the \fIroot\fR field for the event.
+Valid for \fBKeyPress\fR, \fBKeyRelease\fR, \fBButtonPress\fR,
+\fBButtonRelease\fR, \fBEnter\fR, \fBLeave\fR, and \fBMotion\fR
+events.
+Corresponds to the \fB%R\fR substitution for binding scripts.
+.TP
+\fB\-rootx\fI coord\fR
+\fICoord\fR must be a screen distance; it specifies the \fIx_root\fR
+field for the event.
+Valid for \fBKeyPress\fR, \fBKeyRelease\fR, \fBButtonPress\fR,
+\fBButtonRelease\fR, \fBEnter\fR, \fBLeave\fR, and \fBMotion\fR
+events. Corresponds to the \fB%X\fR substitution for binding scripts.
+.TP
+\fB\-rooty\fI coord\fR
+\fICoord\fR must be a screen distance; it specifies the \fIy_root\fR
+field for the event.
+Valid for \fBKeyPress\fR, \fBKeyRelease\fR, \fBButtonPress\fR,
+\fBButtonRelease\fR, \fBEnter\fR, \fBLeave\fR, and \fBMotion\fR
+events.
+Corresponds to the \fB%Y\fR substitution for binding scripts.
+.TP
+\fB\-sendevent\fI boolean\fR
+\fIBoolean\fR must be a boolean value; it specifies the \fIsend_event\fR
+field for the event. Valid for all events. Corresponds to the
+\fB%E\fR substitution for binding scripts.
+.TP
+\fB\-serial\fI number\fR
+\fINumber\fR must be an integer; it specifies the \fIserial\fR field
+for the event. Valid for all events.
+Corresponds to the \fB%#\fR substitution for binding scripts.
+.TP
+\fB\-state\fI state\fR
+\fIState\fR specifies the \fIstate\fR field for the event.
+For \fBKeyPress\fR, \fBKeyRelease\fR, \fBButtonPress\fR,
+\fBButtonRelease\fR, \fBEnter\fR, \fBLeave\fR, and \fBMotion\fR events
+it must be an integer value.
+For \fBVisibility\fR events it must be one of \fBVisibilityUnobscured\fR,
+\fBVisibilityPartiallyObscured\fR, or \fBVisibilityFullyObscured\fR.
+This option overrides any modifiers such as \fBMeta\fR or \fBControl\fR
+specified in the base \fIevent\fR.
+Corresponds to the \fB%s\fR substitution for binding scripts.
+.TP
+\fB\-subwindow\fI window\fR
+\fIWindow\fR specifies the \fIsubwindow\fR field for the event, either
+as a path name for a Tk widget or as an integer window identifier.
+Valid for \fBKeyPress\fR, \fBKeyRelease\fR, \fBButtonPress\fR,
+\fBButtonRelease\fR, \fBEnter\fR, \fBLeave\fR, and \fBMotion\fR events.
+Similar to \fB%S\fR substitution for binding scripts.
+.TP
+\fB\-time\fI integer\fR
+\fIInteger\fR must be an integer value; it specifies the \fItime\fR field
+for the event.
+Valid for \fBKeyPress\fR, \fBKeyRelease\fR, \fBButtonPress\fR,
+\fBButtonRelease\fR, \fBEnter\fR, \fBLeave\fR, \fBMotion\fR,
+and \fBProperty\fR events.
+Corresponds to the \fB%t\fR substitution for binding scripts.
+.TP
+\fB\-warp\fI boolean\fR
+\fIboolean\fR must be a boolean value; it specifies whether
+the screen pointer should be warped as well.
+Valid for \fBKeyPress\fR, \fBKeyRelease\fR, \fBButtonPress\fR,
+\fBButtonRelease\fR, and \fBMotion\fR events. The pointer will
+only warp to a window if it is mapped.
+.TP
+\fB\-width\fI size\fR
+\fISize\fR must be a screen distance; it specifies the \fIwidth\fR field
+for the event.
+Valid for \fBConfigure\fR events.
+Corresponds to the \fB%w\fR substitution for binding scripts.
+.TP
+\fB\-when\fI when\fR
+\fIWhen\fR determines when the event will be processed; it must have one
+of the following values:
+.RS
+.IP \fBnow\fR 10
+Process the event immediately, before the command returns.
+This also happens if the \fB\-when\fR option is omitted.
+.IP \fBtail\fR 10
+Place the event on Tcl's event queue behind any events already
+queued for this application.
+.IP \fBhead\fR 10
+Place the event at the front of Tcl's event queue, so that it
+will be handled before any other events already queued.
+.IP \fBmark\fR 10
+Place the event at the front of Tcl's event queue but behind any
+other events already queued with \fB\-when mark\fR.
+This option is useful when generating a series of events that should
+be processed in order but at the front of the queue.
+.RE
+.TP
+\fB\-x\fI coord\fR
+\fICoord\fR must be a screen distance; it specifies the \fIx\fR field
+for the event.
+Valid for \fBKeyPress\fR, \fBKeyRelease\fR, \fBButtonPress\fR,
+\fBButtonRelease\fR, \fBMotion\fR, \fBEnter\fR, \fBLeave\fR,
+\fBExpose\fR, \fBConfigure\fR, \fBGravity\fR, and \fBReparent\fR
+events.
+Corresponds to the \fB%x\fR substitution for binding scripts.
+If \fIWindow\fR is empty the coordinate is relative to the
+screen, and this option corresponds to the \fB%X\fR substitution
+for binding scripts.
+.TP
+\fB\-y\fI coord\fR
+\fICoord\fR must be a screen distance; it specifies the \fIy\fR
+field for the event.
+Valid for \fBKeyPress\fR, \fBKeyRelease\fR, \fBButtonPress\fR,
+\fBButtonRelease\fR, \fBMotion\fR, \fBEnter\fR, \fBLeave\fR,
+\fBExpose\fR, \fBConfigure\fR, \fBGravity\fR, and \fBReparent\fR
+events.
+Corresponds to the \fB%y\fR substitution for binding scripts.
+If \fIWindow\fR is empty the coordinate is relative to the
+screen, and this option corresponds to the \fB%Y\fR substitution
+for binding scripts.
+.PP
+Any options that are not specified when generating an event are filled
+with the value 0, except for \fIserial\fR, which is filled with the
+next X event serial number.
+.SH "PREDEFINED VIRTUAL EVENTS"
+.PP
+Tk defines the following virtual events for the purposes of
+notification:
+.TP
+\fB<<AltUnderlined>>\fR
+This is sent to widget to notify it that the letter it has underlined
+(as an accelerator indicator) with the \fB\-underline\fR option has
+been pressed in combination with the Alt key. The usual response to
+this is to either focus into the widget (or some related widget) or to
+invoke the widget.
+.TP
+\fB<<Invoke>>\fR
+This can be sent to some widgets (e.g. button, listbox, menu) as an
+alternative to <space>.
+.TP
+\fB<<ListboxSelect>>\fR
+This is sent to a listbox when the set of selected item(s) in the
+listbox is updated.
+.TP
+\fB<<MenuSelect>>\fR
+This is sent to a menu when the currently selected item in the menu
+changes. It is intended for use with context-sensitive help systems.
+.TP
+\fB<<Modified>>\fR
+This is sent to a text widget when the contents of the widget are
+changed.
+.TP
+\fB<<Selection>>\fR
+This is sent to a text widget when the selection in the widget is
+changed.
+.TP
+\fB<<ThemeChanged>>\fR
+This is sent to all widgets when the ttk theme changed. The ttk
+widgets listen to this event and redisplay themselves when it fires.
+The legacy widgets ignore this event.
+.TP
+\fB<<TraverseIn>>\fR
+This is sent to a widget when the focus enters the widget because of a
+user-driven
+.QW "tab to widget"
+action.
+.TP
+\fB<<TraverseOut>>\fR
+This is sent to a widget when the focus leaves the widget because of a
+user-driven
+.QW "tab to widget"
+action.
+.TP
+\fB<<UndoStack>>\fR
+This is sent to a text widget when its undo stack or redo stack becomes
+empty or unempty.
+.TP
+\fB<<WidgetViewSync>>\fR
+This is sent to a text widget when its internal data become obsolete,
+and again when these internal data are back in sync with the widget
+view. The detail field (%d substitution) is either true (when the
+widget is in sync) or false (when it is not).
+.PP
+Tk defines the following virtual events for the purposes of unifying
+bindings across multiple platforms. Users expect them to behave in the
+following way:
+.TP
+\fB<<Clear>>\fR
+Delete the currently selected widget contents.
+.TP
+\fB<<Copy>>\fR
+Copy the currently selected widget contents to the clipboard.
+.TP
+\fB<<Cut>>\fR
+Move the currently selected widget contents to the clipboard.
+.TP
+\fB<<LineEnd>>\fR
+.
+Move to the end of the line in the current widget while deselecting any
+selected contents.
+.TP
+\fB<<LineStart>>\fR
+.
+Move to the start of the line in the current widget while deselecting any
+selected contents.
+.TP
+\fB<<NextChar>>\fR
+.
+Move to the next item (i.e., visible character) in the current widget while
+deselecting any selected contents.
+.TP
+\fB<<NextLine>>\fR
+.
+Move to the next line in the current widget while deselecting any selected
+contents.
+.TP
+\fB<<NextPara>>\fR
+.
+Move to the next paragraph in the current widget while deselecting any
+selected contents.
+.TP
+\fB<<NextWord>>\fR
+.
+Move to the next group of items (i.e., visible word) in the current widget
+while deselecting any selected contents.
+.TP
+\fB<<Paste>>\fR
+Replace the currently selected widget contents with the contents of
+the clipboard.
+.TP
+\fB<<PasteSelection>>\fR
+Insert the contents of the selection at the mouse location. (This
+event has meaningful \fB%x\fR and \fB%y\fR substitutions).
+.TP
+\fB<<PrevChar>>\fR
+.
+Move to the previous item (i.e., visible character) in the current widget
+while deselecting any selected contents.
+.TP
+\fB<<PrevLine>>\fR
+.
+Move to the previous line in the current widget while deselecting any selected
+contents.
+.TP
+\fB<<PrevPara>>\fR
+.
+Move to the previous paragraph in the current widget while deselecting any
+selected contents.
+.TP
+\fB<<PrevWindow>>\fR
+Traverse to the previous window.
+.TP
+\fB<<PrevWord>>\fR
+.
+Move to the previous group of items (i.e., visible word) in the current widget
+while deselecting any selected contents.
+.TP
+\fB<<Redo>>\fR
+Redo one undone action.
+.TP
+\fB<<SelectAll>>\fR
+.
+Set the range of selected contents to the complete widget.
+.TP
+\fB<<SelectLineEnd>>\fR
+.
+Move to the end of the line in the current widget while extending the range
+of selected contents.
+.TP
+\fB<<SelectLineStart>>\fR
+.
+Move to the start of the line in the current widget while extending the range
+of selected contents.
+.TP
+\fB<<SelectNextChar>>\fR
+.
+Move to the next item (i.e., visible character) in the current widget while
+extending the range of selected contents.
+.TP
+\fB<<SelectNextLine>>\fR
+.
+Move to the next line in the current widget while extending the range of
+selected contents.
+.TP
+\fB<<SelectNextPara>>\fR
+.
+Move to the next paragraph in the current widget while extending the range
+of selected contents.
+.TP
+\fB<<SelectNextWord>>\fR
+.
+Move to the next group of items (i.e., visible word) in the current widget
+while extending the range of selected contents.
+.TP
+\fB<<SelectNone>>\fR
+.
+Reset the range of selected contents to be empty.
+.TP
+\fB<<SelectPrevChar>>\fR
+.
+Move to the previous item (i.e., visible character) in the current widget
+while extending the range of selected contents.
+.TP
+\fB<<SelectPrevLine>>\fR
+.
+Move to the previous line in the current widget while extending the range of
+selected contents.
+.TP
+\fB<<SelectPrevPara>>\fR
+.
+Move to the previous paragraph in the current widget while extending the
+range of selected contents.
+.TP
+\fB<<SelectPrevWord>>\fR
+.
+Move to the previous group of items (i.e., visible word) in the current widget
+while extending the range of selected contents.
+.TP
+\fB<<ToggleSelection>>\fR
+.
+Toggle the selection.
+.TP
+\fB<<Undo>>\fR
+.
+Undo the last action.
+.SH EXAMPLES
+.SS "MAPPING KEYS TO VIRTUAL EVENTS"
+.PP
+In order for a virtual event binding to trigger, two things must
+happen. First, the virtual event must be defined with the
+\fBevent add\fR command. Second, a binding must be created for
+the virtual event with the \fBbind\fR command.
+Consider the following virtual event definitions:
+.PP
+.CS
+\fBevent add\fR <<Paste>> <Control-y>
+\fBevent add\fR <<Paste>> <Button-2>
+\fBevent add\fR <<Save>> <Control-X><Control-S>
+\fBevent add\fR <<Save>> <Shift-F12>
+if {[tk windowingsystem] eq "aqua"} {
+ \fBevent add\fR <<Save>> <Command-s>
+}
+.CE
+.PP
+In the \fBbind\fR command, a virtual event can be bound like any other
+builtin event type as follows:
+.PP
+.CS
+bind Entry <<Paste>> {%W insert [selection get]}
+.CE
+.PP
+The double angle brackets are used to specify that a virtual event is being
+bound. If the user types Control-y or presses button 2, or if
+a \fB<<Paste>>\fR virtual event is synthesized with \fBevent generate\fR,
+then the \fB<<Paste>>\fR binding will be invoked.
+.PP
+If a virtual binding has the exact same sequence as a separate
+physical binding, then the physical binding will take precedence.
+Consider the following example:
+.PP
+.CS
+\fBevent add\fR <<Paste>> <Control-y> <Meta-Control-y>
+bind Entry <Control-y> {puts Control-y}
+bind Entry <<Paste>> {puts Paste}
+.CE
+.PP
+When the user types Control-y the \fB<Control-y>\fR binding
+will be invoked, because a physical event is considered
+more specific than a virtual event, all other things being equal.
+However, when the user types Meta-Control-y the
+\fB<<Paste>>\fR binding will be invoked, because the
+\fBMeta\fR modifier in the physical pattern associated with the
+virtual binding is more specific than the \fB<Control-y\fR> sequence for
+the physical event.
+.PP
+Bindings on a virtual event may be created before the virtual event exists.
+Indeed, the virtual event never actually needs to be defined, for instance,
+on platforms where the specific virtual event would be meaningless or
+ungeneratable.
+.PP
+When a definition of a virtual event changes at run time, all windows
+will respond immediately to the new definition.
+Starting from the preceding example, if the following code is executed:
+.PP
+.CS
+bind Entry <Control-y> {}
+\fBevent add\fR <<Paste>> <Key-F6>
+.CE
+.PP
+the behavior will change such in two ways. First, the shadowed
+\fB<<Paste>>\fR binding will emerge.
+Typing Control-y will no longer invoke the \fB<Control-y>\fR binding,
+but instead invoke the virtual event \fB<<Paste>>\fR. Second,
+pressing the F6 key will now also invoke the \fB<<Paste>>\fR binding.
+.SS "MOVING THE MOUSE POINTER"
+.PP
+Sometimes it is useful to be able to really move the mouse pointer. For
+example, if you have some software that is capable of demonstrating directly
+to the user how to use the program. To do this, you need to
+.QW warp
+the mouse around by using \fBevent generate\fR, like this:
+.PP
+.CS
+for {set xy 0} {$xy < 200} {incr xy} {
+ \fBevent generate\fR . <Motion> -x $xy -y $xy -warp 1
+ update
+ after 50
+}
+.CE
+.PP
+Note that it is usually considered bad style to move the mouse pointer for the
+user because it removes control from them. Therefore this technique should be
+used with caution. Also note that it is not guaranteed to function on all
+platforms.
+.SH "SEE ALSO"
+bind(n)
+.SH KEYWORDS
+event, binding, define, handle, virtual event
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/focus.n b/tk8.6/doc/focus.n
new file mode 100644
index 0000000..4b8bb2a
--- /dev/null
+++ b/tk8.6/doc/focus.n
@@ -0,0 +1,137 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH focus n 4.0 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+focus \- Manage the input focus
+.SH SYNOPSIS
+.nf
+\fBfocus\fR
+\fBfocus \fIwindow\fR
+\fBfocus \fIoption\fR ?\fIarg arg ...\fR?
+.fi
+.BE
+.SH DESCRIPTION
+.PP
+The \fBfocus\fR command is used to manage the Tk input focus.
+At any given time, one window on each display is designated as
+the \fIfocus window\fR; any key press or key release events for the
+display are sent to that window.
+It is normally up to the window manager to redirect the focus among the
+top-level windows of a display. For example, some window managers
+automatically set the input focus to a top-level window whenever
+the mouse enters it; others redirect the input focus only when
+the user clicks on a window.
+Usually the window manager will set the focus
+only to top-level windows, leaving it up to the application to
+redirect the focus among the children of the top-level.
+.PP
+Tk remembers one focus window for each top-level (the most recent
+descendant of that top-level to receive the focus); when the window
+manager gives the focus
+to a top-level, Tk automatically redirects it to the remembered
+window. Within a top-level Tk uses an \fIexplicit\fR focus model
+by default. Moving the mouse within a top-level does not normally
+change the focus; the focus changes only when a widget
+decides explicitly to claim the focus (e.g., because of a button
+click), or when the user types a key such as Tab that moves the
+focus.
+.PP
+The Tcl procedure \fBtk_focusFollowsMouse\fR may be invoked to
+create an \fIimplicit\fR focus model: it reconfigures Tk so that
+the focus is set to a window whenever the mouse enters it.
+The Tcl procedures \fBtk_focusNext\fR and \fBtk_focusPrev\fR
+implement a focus order among the windows of a top-level; they
+are used in the default bindings for Tab and Shift-Tab, among other
+things.
+.PP
+The \fBfocus\fR command can take any of the following forms:
+.TP
+\fBfocus\fR
+Returns the path name of the focus window on the display containing
+the application's main window, or an empty string if no window in
+this application has the focus on that display. Note: it is
+better to specify the display explicitly using \fB\-displayof\fR
+(see below) so that the code will work in applications using multiple
+displays.
+.TP
+\fBfocus \fIwindow\fR
+If the application currently has the input focus on \fIwindow\fR's
+display, this command resets the input focus for \fIwindow\fR's display
+to \fIwindow\fR and returns an empty string.
+If the application does not currently have the input focus on
+\fIwindow\fR's display, \fIwindow\fR will be remembered as the focus
+for its top-level; the next time the focus arrives at the top-level,
+Tk will redirect it to \fIwindow\fR.
+If \fIwindow\fR is an empty string then the command does nothing.
+.TP
+\fBfocus \-displayof\fR \fIwindow\fR
+Returns the name of the focus window on the display containing \fIwindow\fR.
+If the focus window for \fIwindow\fR's display is not in this
+application, the return value is an empty string.
+.TP
+\fBfocus \-force \fIwindow\fR
+Sets the focus of \fIwindow\fR's display to \fIwindow\fR, even if
+the application does not currently have the input focus for the display.
+This command should be used sparingly, if at all.
+In normal usage, an application should not claim the focus for
+itself; instead, it should wait for the window manager to give it
+the focus.
+If \fIwindow\fR is an empty string then the command does nothing.
+.TP
+\fBfocus \-lastfor\fR \fIwindow\fR
+Returns the name of the most recent window to have the input focus
+among all the windows in the same top-level as \fIwindow\fR.
+If no window in that top-level has ever had the input focus, or
+if the most recent focus window has been deleted, then the name
+of the top-level is returned. The return value is the window that
+will receive the input focus the next time the window manager gives
+the focus to the top-level.
+.SH "QUIRKS"
+.PP
+When an internal window receives the input focus, Tk does not actually
+set the X focus to that window; as far as X is concerned, the focus
+will stay on the top-level window containing the window with the focus.
+However, Tk generates FocusIn and FocusOut events just as if the X
+focus were on the internal window. This approach gets around a
+number of problems that would occur if the X focus were actually moved;
+the fact that the X focus is on the top-level is invisible unless
+you use C code to query the X server directly.
+.SH "EXAMPLE"
+.PP
+To make a window that only participates in the focus traversal ring
+when a variable is set, add the following bindings to the widgets
+\fIbefore\fR and \fIafter\fR it in that focus ring:
+.CS
+button .before \-text "Before"
+button .middle \-text "Middle"
+button .after \-text "After"
+checkbutton .flag \-variable traverseToMiddle \-takefocus 0
+pack .flag \-side left
+pack .before .middle .after
+bind .before <Tab> {
+ if {!$traverseToMiddle} {
+ \fBfocus\fR .after
+ break
+ }
+}
+bind .after <Shift\-Tab> {
+ if {!$traverseToMiddle} {
+ \fBfocus\fR .before
+ break
+ }
+}
+\fBfocus\fR .before
+.CE
+.SH KEYWORDS
+events, focus, keyboard, top-level, window manager
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/focusNext.n b/tk8.6/doc/focusNext.n
new file mode 100644
index 0000000..ffcf971
--- /dev/null
+++ b/tk8.6/doc/focusNext.n
@@ -0,0 +1,60 @@
+'\"
+'\" Copyright (c) 1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH tk_focusNext n 4.0 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+tk_focusNext, tk_focusPrev, tk_focusFollowsMouse \- Utility procedures for managing the input focus.
+.SH SYNOPSIS
+\fBtk_focusNext \fIwindow\fR
+.sp
+\fBtk_focusPrev \fIwindow\fR
+.sp
+\fBtk_focusFollowsMouse\fR
+.BE
+.SH DESCRIPTION
+.PP
+\fBtk_focusNext\fR is a utility procedure used for keyboard traversal.
+It returns the
+.QW next
+window after \fIwindow\fR in focus order. The focus order is determined by
+the stacking order of windows and the structure of the window hierarchy.
+Among siblings, the focus order is the same as the stacking order, with the
+lowest window being first.
+If a window has children, the window is visited first, followed by
+its children (recursively), followed by its next sibling.
+Top-level windows other than \fIwindow\fR are skipped, so that
+\fBtk_focusNext\fR never returns a window in a different top-level
+from \fIwindow\fR.
+.PP
+After computing the next window, \fBtk_focusNext\fR examines the
+window's \fB\-takefocus\fR option to see whether it should be skipped.
+If so, \fBtk_focusNext\fR continues on to the next window in the focus
+order, until it eventually finds a window that will accept the focus
+or returns back to \fIwindow\fR.
+.PP
+\fBtk_focusPrev\fR is similar to \fBtk_focusNext\fR except that it
+returns the window just before \fIwindow\fR in the focus order.
+.PP
+\fBtk_focusFollowsMouse\fR changes the focus model for the application
+to an implicit one where the window under the mouse gets the focus.
+After this procedure is called, whenever the mouse enters a window
+Tk will automatically give it the input focus.
+The \fBfocus\fR command may be used to move the focus to a window
+other than the one under the mouse, but as soon as the mouse moves
+into a new window the focus will jump to that window.
+Note: at present there is no built-in support for returning the
+application to an explicit focus model; to do this you will have
+to write a script that deletes the bindings created by
+\fBtk_focusFollowsMouse\fR.
+.SH KEYWORDS
+focus, keyboard traversal, top-level
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/font.n b/tk8.6/doc/font.n
new file mode 100644
index 0000000..72f9270
--- /dev/null
+++ b/tk8.6/doc/font.n
@@ -0,0 +1,409 @@
+'\"
+'\" Copyright (c) 1996 Sun Microsystems, Inc.
+'\" Copyright (c) 2006-2007 Daniel A. Steffen <das@users.sourceforge.net>
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH font n 8.0 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+font \- Create and inspect fonts.
+.SH SYNOPSIS
+\fBfont\fI option \fR?\fIarg arg ...\fR?
+.BE
+.SH DESCRIPTION
+.PP
+The \fBfont\fR command provides several facilities for dealing with
+fonts, such as defining named fonts and inspecting the actual attributes of
+a font. The command has several different forms, determined by the
+first argument. The following forms are currently supported:
+.TP
+\fBfont actual \fIfont\fR ?\fB\-displayof \fIwindow\fR? ?\fIoption\fR? ?\fB\-\|\-\fR? ?\fIchar\fR?
+.
+Returns information about the actual attributes that are obtained when
+\fIfont\fR is used on \fIwindow\fR's display; the actual attributes obtained
+may differ from the attributes requested due to platform-dependent
+limitations, such as the availability of font families and point sizes.
+\fIfont\fR is a font description; see \fBFONT DESCRIPTIONS\fR below. If the
+\fIwindow\fR argument is omitted, it defaults to the main window. If
+\fIoption\fR is specified, returns the value of that attribute; if it is
+omitted, the return value is a list of all the attributes and their values.
+See \fBFONT OPTIONS\fR below for a list of the possible attributes. If the
+\fIchar\fR argument is supplied, it must be a single character. The font
+attributes returned will be those of the specific font used to render
+that character, which will be different from the base font if the base
+font does not contain the given character. If \fIchar\fR may be a hyphen, it
+should be preceded by \fB\-\|\-\fR to distinguish it from a misspelled
+\fIoption\fR.
+.TP
+\fBfont configure \fIfontname\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
+.
+Query or modify the desired attributes for the named font called
+\fIfontname\fR. If no \fIoption\fR is specified, returns a list describing
+all the options and their values for \fIfontname\fR. If a single \fIoption\fR
+is specified with no \fIvalue\fR, then returns the current value of that
+attribute. If one or more \fIoption\fR\-\fIvalue\fR pairs are specified,
+then the command modifies the given named font to have the given values; in
+this case, all widgets using that font will redisplay themselves using the
+new attributes for the font. See \fBFONT OPTIONS\fR below for a list of the
+possible attributes.
+.RS
+.PP
+Note that on Aqua/Mac OS X, the system fonts (see
+\fBPLATFORM SPECIFIC FONTS\fR below) may not be actually altered because they
+are implemented by the system theme. To achieve the effect of modification,
+use \fBfont actual\fR to get their configuration and \fBfont create\fR to
+synthesize a copy of the font which can be modified.
+.RE
+.TP
+\fBfont create\fR ?\fIfontname\fR? ?\fIoption value ...\fR?
+.
+Creates a new named font and returns its name. \fIfontname\fR specifies the
+name for the font; if it is omitted, then Tk generates a new name of the
+form \fBfont\fIx\fR, where \fIx\fR is an integer. There may be any number
+of \fIoption\fR\-\fIvalue\fR pairs, which provide the desired attributes for
+the new named font. See \fBFONT OPTIONS\fR below for a list of the possible
+attributes.
+.TP
+\fBfont delete\fR \fIfontname\fR ?\fIfontname ...\fR?
+.
+Delete the specified named fonts. If there are widgets using the named font,
+the named font will not actually be deleted until all the instances are
+released. Those widgets will continue to display using the last known values
+for the named font. If a deleted named font is subsequently recreated with
+another call to \fBfont create\fR, the widgets will use the new named font
+and redisplay themselves using the new attributes of that font.
+.TP
+\fBfont families\fR ?\fB\-displayof \fIwindow\fR?
+.
+The return value is a list of the case-insensitive names of all font families
+that exist on \fIwindow\fR's display. If the \fIwindow\fR argument is
+omitted, it defaults to the main window.
+.TP
+\fBfont measure \fIfont\fR ?\fB\-displayof \fIwindow\fR? \fItext\fR
+.
+Measures the amount of space the string \fItext\fR would use in the given
+\fIfont\fR when displayed in \fIwindow\fR. \fIfont\fR is a font description;
+see \fBFONT DESCRIPTIONS\fR below. If the \fIwindow\fR argument is
+omitted, it
+defaults to the main window. The return value is the total width in pixels
+of \fItext\fR, not including the extra pixels used by highly exaggerated
+characters such as cursive
+.QW f .
+If the string contains newlines or tabs,
+those characters are not expanded or treated specially when measuring the
+string.
+.TP
+\fBfont metrics \fIfont\fR ?\fB\-displayof \fIwindow\fR? ?\fIoption\fR?
+.
+Returns information about the metrics (the font-specific data), for
+\fIfont\fR when it is used on \fIwindow\fR's display. \fIfont\fR is a font
+description; see \fBFONT DESCRIPTIONS\fR below. If the \fIwindow\fR
+argument is
+omitted, it defaults to the main window. If \fIoption\fR is specified,
+returns the value of that metric; if it is omitted, the return value is a
+list of all the metrics and their values. See \fBFONT METRICS\fR
+below for a list of the possible metrics.
+.TP
+\fBfont names\fR
+The return value is a list of all the named fonts that are currently defined.
+.SH "FONT DESCRIPTIONS"
+.PP
+The following formats are accepted as a font description anywhere
+\fIfont\fR is specified as an argument above; these same forms are also
+permitted when specifying the \fB\-font\fR option for widgets.
+.TP
+[1] \fIfontname\fR
+.
+The name of a named font, created using the \fBfont create\fR command. When
+a widget uses a named font, it is guaranteed that this will never cause an
+error, as long as the named font exists, no matter what potentially invalid
+or meaningless set of attributes the named font has. If the named font
+cannot be displayed with exactly the specified attributes, some other close
+font will be substituted automatically.
+.TP
+[2] \fIsystemfont\fR
+.
+The platform-specific name of a font, interpreted by the graphics server.
+This also includes, under X, an XLFD (see [4]) for which a single
+.QW \fB*\fR
+character was used to elide more than one field in the middle of the
+name. See \fBPLATFORM SPECIFIC FONTS\fR for a list of the system fonts.
+.TP
+[3] \fIfamily \fR?\fIsize\fR? ?\fIstyle\fR? ?\fIstyle ...\fR?
+.
+A properly formed list whose first element is the desired font
+\fIfamily\fR and whose optional second element is the desired \fIsize\fR.
+The interpretation of the \fIsize\fR attribute follows the same rules
+described for \fB\-size\fR in \fBFONT OPTIONS\fR below. Any
+additional optional
+arguments following the \fIsize\fR are font \fIstyle\fRs. Possible values
+for the \fIstyle\fR arguments are as follows:
+.RS
+.DS
+.ta 3c 6c 9c
+\fBnormal\fR \fBbold\fR \fBroman\fR \fBitalic\fR
+\fBunderline\fR \fBoverstrike\fR
+.DE
+.RE
+.TP
+[4] X-font names (XLFD)
+.
+A Unix-centric font name of the form
+\fI\-foundry\-family\-weight\-slant\-setwidth\-addstyle\-pixel\-point\-resx\-resy\-spacing\-width\-charset\-encoding\fR.
+The
+.QW \fB*\fR
+character may be used to skip individual fields that the
+user does not care about. There must be exactly one
+.QW \fB*\fR
+for each field skipped, except that a
+.QW \fB*\fR
+at the end of the XLFD skips any
+remaining fields; the shortest valid XLFD is simply
+.QW \fB*\fR ,
+signifying all fields as defaults. Any fields that were skipped are
+given default
+values. For compatibility, an XLFD always chooses a font of the specified
+pixel size (not point size); although this interpretation is not strictly
+correct, all existing applications using XLFDs assumed that one
+.QW point
+was in fact one pixel and would display incorrectly (generally larger) if
+the correct size font were actually used.
+.TP
+[5] \fIoption value \fR?\fIoption value ...\fR?
+.
+A properly formed list of \fIoption\fR\-\fIvalue\fR pairs that specify
+the desired attributes of the font, in the same format used when defining
+a named font; see \fBFONT OPTIONS\fR below.
+.LP
+When font description \fIfont\fR is used, the system attempts to parse the
+description according to each of the above five rules, in the order specified.
+Cases [1] and [2] must match the name of an existing named font or of a
+system font. Cases [3], [4], and [5] are accepted on all
+platforms and the closest available font will be used. In some situations
+it may not be possible to find any close font (e.g., the font family was
+a garbage value); in that case, some system-dependent default font is
+chosen. If the font description does not match any of the above patterns,
+an error is generated.
+.SH "FONT METRICS"
+.PP
+The following options are used by the \fBfont metrics\fR command to query
+font-specific data determined when the font was created. These properties are
+for the whole font itself and not for individual characters drawn in that
+font. In the following definitions, the
+.QW baseline
+of a font is the
+horizontal line where the bottom of most letters line up; certain letters,
+such as lower-case
+.QW g
+stick below the baseline.
+.TP
+\fB\-ascent \0\fR
+.
+The amount in pixels that the tallest letter sticks up above the baseline of
+the font, plus any extra blank space added by the designer of the font.
+.TP
+\fB\-descent \0\fR
+.
+The largest amount in pixels that any letter sticks down below the baseline
+of the font, plus any extra blank space added by the designer of the font.
+.TP
+\fB\-linespace\fR
+.
+Returns how far apart vertically in pixels two lines of text using the same
+font should be placed so that none of the characters in one line overlap any
+of the characters in the other line. This is generally the sum of the ascent
+above the baseline line plus the descent below the baseline.
+.TP
+\fB\-fixed \0\fR
+.
+Returns a boolean flag that is
+.QW \fB1\fR
+if this is a fixed-width font,
+where each normal character is the same width as all the other
+characters, or is
+.QW \fB0\fR
+if this is a proportionally-spaced font, where
+individual characters have different widths. The widths of control
+characters, tab characters, and other non-printing characters are not
+included when calculating this value.
+.SH "FONT OPTIONS"
+.PP
+The following options are supported on all platforms, and are used when
+constructing a named font or when specifying a font using style [5] as
+above:
+.TP
+\fB\-family \fIname\fR
+.
+The case-insensitive font family name. Tk guarantees to support the font
+families named \fBCourier\fR (a monospaced
+.QW typewriter
+font), \fBTimes\fR (a serifed
+.QW newspaper
+font), and \fBHelvetica\fR (a sans-serif
+.QW European
+font). The most closely matching native font family will
+automatically be substituted when one of the above font families is used.
+The \fIname\fR may also be the name of a native, platform-specific font
+family; in that case it will work as desired on one platform but may not
+display correctly on other platforms. If the family is unspecified or
+unrecognized, a platform-specific default font will be chosen.
+.TP
+\fB\-size \fIsize\fR
+.
+The desired size of the font. If the \fIsize\fR argument is a positive
+number, it is interpreted as a size in points. If \fIsize\fR is a negative
+number, its absolute value is interpreted as a size in pixels. If a
+font cannot be displayed at the specified size, a nearby size will be
+chosen. If \fIsize\fR is unspecified or zero, a platform-dependent default
+size will be chosen.
+.RS
+.PP
+Sizes should normally be specified in points so the application will remain
+the same ruler size on the screen, even when changing screen resolutions or
+moving scripts across platforms. However, specifying pixels is useful in
+certain circumstances such as when a piece of text must line up with respect
+to a fixed-size bitmap. The mapping between points and pixels is set when
+the application starts, based on properties of the installed monitor, but it
+can be overridden by calling the \fBtk scaling\fR command.
+.RE
+.TP
+\fB\-weight \fIweight\fR
+.
+The nominal thickness of the characters in the font. The value
+\fBnormal\fR specifies a normal weight font, while \fBbold\fR specifies a
+bold font. The closest available weight to the one specified will
+be chosen. The default weight is \fBnormal\fR.
+.TP
+\fB\-slant \fIslant\fR
+The amount the characters in the font are slanted away from the
+vertical. Valid values for slant are \fBroman\fR and \fBitalic\fR.
+A roman font is the normal, upright appearance of a font, while
+an italic font is one that is tilted some number of degrees from upright.
+The closest available slant to the one specified will be chosen.
+The default slant is \fBroman\fR.
+.TP
+\fB\-underline \fIboolean\fR
+The value is a boolean flag that specifies whether characters in this
+font should be underlined. The default value for underline is \fBfalse\fR.
+.TP
+\fB\-overstrike \fIboolean\fR
+The value is a boolean flag that specifies whether a horizontal line should
+be drawn through the middle of characters in this font. The default value
+for overstrike is \fBfalse\fR.
+.SH "STANDARD FONTS"
+.PP
+The following named fonts are supported on all systems, and default to values
+that match appropriate system defaults.
+.TP
+\fBTkDefaultFont\fR
+.
+This font is the default for all GUI items not otherwise specified.
+.TP
+\fBTkTextFont\fR
+.
+This font should be used for user text in entry widgets, listboxes etc.
+.TP
+\fBTkFixedFont\fR
+.
+This font is the standard fixed-width font.
+.TP
+\fBTkMenuFont\fR
+.
+This font is used for menu items.
+.TP
+\fBTkHeadingFont\fR
+.
+This font should be used for column headings in lists and tables.
+.TP
+\fBTkCaptionFont\fR
+.
+This font should be used for window and dialog caption bars.
+.TP
+\fBTkSmallCaptionFont\fR
+.
+This font should be used for captions on contained windows or tool dialogs.
+.TP
+\fBTkIconFont\fR
+.
+This font should be used for icon captions.
+.TP
+\fBTkTooltipFont\fR
+.
+This font should be used for tooltip windows (transient information windows).
+.LP
+It is \fInot\fR advised to change these fonts, as they may be modified by Tk
+itself in response to system changes. Instead, make a copy of the font and
+modify that.
+.SH "PLATFORM SPECIFIC FONTS"
+.PP
+The following system fonts are supported:
+.TP
+\fBX Windows\fR
+All valid X font names, including those listed by xlsfonts(1), are available.
+.TP
+\fBMS Windows\fR
+The following fonts are supported, and are mapped to the user's
+style defaults.
+.RS
+.DS
+.ta 3c 6c
+\fBsystem\fR \fBansi\fR \fBdevice\fR
+\fBsystemfixed\fR \fBansifixed\fR \fBoemfixed\fR
+.DE
+.RE
+.TP
+\fBMac OS X\fR
+The following fonts are supported, and are mapped to the user's
+style defaults.
+.RS
+.DS
+.ta 3c 6c
+\fBsystem\fR \fBapplication\fR \fBmenu\fR
+.DE
+.PP
+Additionally, the following named fonts provide access to the Aqua
+theme fonts:
+.DS
+.ta 5c
+\fBsystemSystemFont\fR \fBsystemEmphasizedSystemFont\fR
+\fBsystemSmallSystemFont\fR \fBsystemSmallEmphasizedSystemFont\fR
+\fBsystemApplicationFont\fR \fBsystemLabelFont\fR
+\fBsystemViewsFont\fR \fBsystemMenuTitleFont\fR
+\fBsystemMenuItemFont\fR \fBsystemMenuItemMarkFont\fR
+\fBsystemMenuItemCmdKeyFont\fR \fBsystemWindowTitleFont\fR
+\fBsystemPushButtonFont\fR \fBsystemUtilityWindowTitleFont\fR
+\fBsystemAlertHeaderFont\fR \fBsystemToolbarFont\fR
+\fBsystemMiniSystemFont\fR \fBsystemDetailSystemFont\fR
+\fBsystemDetailEmphasizedSystemFont\fR
+.DE
+.RE
+.SH EXAMPLE
+.PP
+Fill a text widget with lots of font demonstrators, one for every font
+family installed on your system:
+.CS
+pack [text .t \-wrap none] \-fill both \-expand 1
+set count 0
+set tabwidth 0
+foreach family [lsort \-dictionary [\fBfont families\fR]] {
+ .t tag configure f[incr count] \-font [list $family 10]
+ .t insert end ${family}:\\t {} \e
+ "This is a simple sampler\en" f$count
+ set w [\fBfont measure\fR [.t cget \-font] ${family}:]
+ if {$w+5 > $tabwidth} {
+ set tabwidth [expr {$w+5}]
+ .t configure \-tabs $tabwidth
+ }
+}
+.CE
+.SH "SEE ALSO"
+options(n)
+.SH KEYWORDS
+font
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/fontchooser.n b/tk8.6/doc/fontchooser.n
new file mode 100644
index 0000000..bdd51c7
--- /dev/null
+++ b/tk8.6/doc/fontchooser.n
@@ -0,0 +1,181 @@
+'\"
+'\" Copyright (c) 2008 Daniel A. Steffen <das@users.sourceforge.net>
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH fontchooser n "" Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+fontchooser \- control font selection dialog
+.SH SYNOPSIS
+\fBtk fontchooser\fR \fBconfigure\fR ?\fI\-option value \-option value ...\fR?
+.sp
+\fBtk fontchooser\fR \fBshow\fR
+.sp
+\fBtk fontchooser\fR \fBhide\fR
+.BE
+.SH DESCRIPTION
+.PP
+The \fBtk fontchooser\fR command controls the Tk font selection dialog. It uses
+the native platform font selection dialog where available, or a dialog
+implemented in Tcl otherwise.
+.PP
+Unlike most of the other Tk dialog commands, \fBtk fontchooser\fR does not
+return an immediate result, as on some platforms (Mac OS X) the standard font
+dialog is modeless while on others (Windows) it is modal. To accommodate this
+difference, all user interaction with the dialog will be communicated to the
+caller via callbacks or virtual events.
+.PP
+The \fBtk fontchooser\fR command can have one of the following forms:
+.TP
+\fBtk fontchooser\fR \fBconfigure \fR?\fI\-option value \-option value ...\fR?
+.
+Set or query one or more of the configurations options below (analogous to Tk
+widget configuration).
+.TP
+\fBtk fontchooser\fR \fBshow\fR
+.
+Show the font selection dialog. Depending on the platform, may return
+immediately or only once the dialog has been withdrawn.
+.TP
+\fBtk fontchooser\fR \fBhide\fR
+.
+Hide the font selection dialog if it is visible and cause any pending
+\fBtk fontchooser\fR \fBshow\fR command to return.
+.PP
+.SH "CONFIGURATION OPTIONS"
+.TP
+\fB\-parent\fR
+Specifies/returns the logical parent window of the font selection dialog
+(similar to the \fB\-parent\fR option to other dialogs). The font selection
+dialog is hidden if it is visible when the parent window is destroyed.
+.TP
+\fB\-title\fR
+Specifies/returns the title of the dialog. Has no effect on platforms where the
+font selection dialog does not support titles.
+.TP
+\fB\-font\fR
+Specifies/returns the font that is currently selected in the dialog if it is
+visible, or that will be initially selected when the dialog is shown (if
+supported by the platform). Can be set to the empty string to indicate that no
+font should be selected. Fonts can be specified in any form given by the "FONT
+DESCRIPTION" section in the \fBfont\fR manual page.
+.TP
+\fB\-command\fR
+Specifies/returns the command prefix to be called when a font selection has
+been made by the user. The command prefix is evaluated at the global level
+after having the specification of the selected font appended. On platforms
+where the font selection dialog offers the user control of further font
+attributes (such as color), additional key/value pairs may be appended before
+evaluation. Can be set to the empty string to indicate that no callback should
+be invoked. Fonts are specified by a list of form [3] of the "FONT DESCRIPTION"
+section in the \fBfont\fR manual page (i.e. a list of the form
+\fI{family size style ?style ...?}\fR).
+.TP
+\fB\-visible\fR
+Read-only option that returns a boolean indicating whether the font selection
+dialog is currently visible. Attempting to set this option results in an error.
+
+.PP
+.SH "VIRTUAL EVENTS"
+.TP
+\fB<<TkFontchooserVisibility>>\fR
+Sent to the dialog parent whenever the visibility of the font selection dialog
+changes, both as a result of user action (e.g. disposing of the dialog via
+OK/Cancel button or close box) and of the \fBtk fontchooser\fR
+\fBshow\fR/\fBhide\fR commands being called. Binding scripts can determine the
+current visibility of the dialog by querying the \fB\-visible\fR configuration
+option.
+.TP
+\fB<<TkFontchooserFontChanged>>\fR
+Sent to the dialog parent whenever the font selection dialog is visible and the
+selected font changes, both as a result of user action and of the \fB\-font\fR
+configuration option being set. Binding scripts can determine the currently
+selected font by querying the \fB\-font\fR configuration option.
+.PP
+.SH NOTES
+.PP
+Callers should not expect a result from \fBtk fontchooser\fR \fBshow\fR and may
+not assume that the dialog has been withdrawn or closed when the command
+returns. All user interaction with the dialog is communicated to the caller via
+the \fB\-command\fR callback and the \fB<<TkFontchooser*>>\fR virtual events.
+It is implementation dependent which exact user actions result in the callback
+being called resp. the virtual events being sent. Where an Apply or OK button
+is present in the dialog, that button will trigger the \fB\-command\fR callback
+and \fB<<TkFontchooserFontChanged>>\fR virtual event. On some implementations
+other user actions may also have that effect; on Mac OS X for instance, the
+standard font selection dialog immediately reflects all user choices to the
+caller.
+.PP
+In the presence of multiple widgets intended to be influenced by the font
+selection dialog, care needs to be taken to correctly handle focus changes: the
+font selected in the dialog should always match the current font of the widget
+with the focus, and the \fB\-command\fR callback should only act on the widget
+with the focus. The recommended practice is to set font dialog \fB\-font\fR and
+\fB\-command\fR configuration options in per\-widget \fB<FocusIn>\fR handlers
+(and if necessary to unset them \- i.e. set to the empty string \- in
+corresponding \fB<FocusOut>\fR handlers). This is particularly important for
+implementers of library code using the font selection dialog, to avoid
+conflicting with application code that may also want to use the dialog.
+.PP
+Because the font selection dialog is application-global, in the presence of
+multiple interpreters calling \fBtk fontchooser\fR, only the \fB\-command\fR
+callback set by the interpreter that most recently called \fBtk fontchooser\fR
+\fBconfigure\fR or \fBtk fontchooser\fR \fBshow\fR will be invoked in response
+to user action and only the \fB\-parent\fR set by that interpreter will receive
+\fB<<TkFontchooser*>>\fR virtual events.
+.PP
+The font dialog implementation may only store (and return) \fBfont\fR
+\fBactual\fR data as the value of the \fB\-font\fR configuration option. This
+can be an issue when \fB\-font\fR is set to a named font, if that font is
+subsequently changed, the font dialog \fB\-font\fR option needs to be set again
+to ensure its selected font matches the new value of the named font.
+.PP
+.SH EXAMPLE
+.PP
+.CS
+proc fontchooserDemo {} {
+ wm title . "Font Chooser Demo"
+ \fBtk fontchooser\fR \fBconfigure\fR \-parent .
+ button .b \-command fontchooserToggle \-takefocus 0
+ fontchooserVisibility .b
+ bind . \fB<<TkFontchooserVisibility>>\fR \\
+ [list fontchooserVisibility .b]
+ foreach w {.t1 .t2} {
+ text $w \-width 20 \-height 4 \-borderwidth 1 \-relief solid
+ bind $w <FocusIn> [list fontchooserFocus $w]
+ $w insert end "Text Widget $w"
+ }
+ .t1 configure \-font {Courier 14}
+ .t2 configure \-font {Times 16}
+ pack .b .t1 .t2; focus .t1
+}
+proc fontchooserToggle {} {
+ \fBtk fontchooser\fR [expr {
+ [\fBtk fontchooser\fR \fBconfigure\fR \-visible] ?
+ "\fBhide\fR" : "\fBshow\fR"}]
+}
+proc fontchooserVisibility {w} {
+ $w configure \-text [expr {
+ [\fBtk fontchooser\fR \fBconfigure\fR \-visible] ?
+ "Hide Font Dialog" : "Show Font Dialog"}]
+}
+proc fontchooserFocus {w} {
+ \fBtk fontchooser\fR \fBconfigure\fR \-font [$w cget \-font] \\
+ \-command [list fontchooserFontSelection $w]
+}
+proc fontchooserFontSelection {w font args} {
+ $w configure \-font [font actual $font]
+}
+fontchooserDemo
+.CE
+.SH "SEE ALSO"
+font(n), tk(n)
+.SH KEYWORDS
+dialog, font, font selection, font chooser, font panel
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/frame.n b/tk8.6/doc/frame.n
new file mode 100644
index 0000000..f2fbd96
--- /dev/null
+++ b/tk8.6/doc/frame.n
@@ -0,0 +1,143 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH frame n 8.4 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+frame \- Create and manipulate 'frame' simple container widgets
+.SH SYNOPSIS
+\fBframe\fR \fIpathName\fR ?\fIoptions\fR?
+.SO
+\-borderwidth \-highlightcolor \-pady
+\-cursor \-highlightthickness \-relief
+\-highlightbackground \-padx \-takefocus
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-background background Background
+This option is the same as the standard \fB\-background\fR option
+except that its value may also be specified as an empty string.
+In this case, the widget will display no background or border, and
+no colors will be consumed from its colormap for its background
+and border.
+.OP \-class class Class
+Specifies a class for the window.
+This class will be used when querying the option database for
+the window's other options, and it will also be used later for
+other purposes such as bindings.
+The \fB\-class\fR option may not be changed with the \fBconfigure\fR
+widget command.
+.OP \-colormap colormap Colormap
+Specifies a colormap to use for the window.
+The value may be either \fBnew\fR, in which case a new colormap is
+created for the window and its children, or the name of another
+window (which must be on the same screen and have the same visual
+as \fIpathName\fR), in which case the new window will use the colormap
+from the specified window.
+If the \fB\-colormap\fR option is not specified, the new window
+uses the same colormap as its parent.
+This option may not be changed with the \fBconfigure\fR
+widget command.
+.OP \-container container Container
+The value must be a boolean. If true, it means that this window will
+be used as a container in which some other application will be embedded
+(for example, a Tk toplevel can be embedded using the \fB\-use\fR option).
+The window will support the appropriate window manager protocols for
+things like geometry requests. The window should not have any
+children of its own in this application.
+This option may not be changed with the \fBconfigure\fR
+widget command.
+Note that \fB\-borderwidth\fR, \fB\-padx\fR and \fB\-pady\fR are ignored when
+configured as a container since a container has no border.
+.OP \-height height Height
+Specifies the desired height for the window in any of the forms
+acceptable to \fBTk_GetPixels\fR. If this option is less than or equal
+to zero then the window will not request any size at all. Note that this
+sets the total height of the frame, any \fB\-borderwidth\fR or similar is
+not added. Normally \fB\-height\fR should not be used if a propagating
+geometry manager, such as \fBgrid\fR or \fBpack\fR, is used within the
+frame since the geometry manager will override the height of the frame.
+.OP \-visual visual Visual
+Specifies visual information for the new window in any of the
+forms accepted by \fBTk_GetVisual\fR.
+If this option is not specified, the new window will use the same
+visual as its parent.
+The \fB\-visual\fR option may not be modified with the \fBconfigure\fR
+widget command.
+.OP \-width width Width
+Specifies the desired width for the window in any of the forms
+acceptable to \fBTk_GetPixels\fR. If this option is less than or equal
+to zero then the window will not request any size at all. Note that this
+sets the total width of the frame, any \fB\-borderwidth\fR or similar is
+not added. Normally \fB\-width\fR should not be used if a propagating
+geometry manager, such as \fBgrid\fR or \fBpack\fR, is used within the
+frame since the geometry manager will override the width of the frame.
+.BE
+.SH DESCRIPTION
+.PP
+The \fBframe\fR command creates a new window (given by the
+\fIpathName\fR argument) and makes it into a frame widget.
+Additional
+options, described above, may be specified on the command line
+or in the option database
+to configure aspects of the frame such as its background color
+and relief. The \fBframe\fR command returns the
+path name of the new window.
+.PP
+A frame is a simple widget. Its primary purpose is to act as a
+spacer or container for complex window layouts. The only features
+of a frame are its background color and an optional 3-D border to make the
+frame appear raised or sunken.
+.SH "WIDGET COMMAND"
+.PP
+The \fBframe\fR command creates a new Tcl command whose
+name is the same as the path name of the frame's window. This
+command may be used to invoke various
+operations on the widget. It has the following general form:
+.PP
+.CS
+\fIpathName option \fR?\fIarg arg ...\fR?
+.CE
+.PP
+\fIPathName\fR is the name of the command, which is the same as
+the frame widget's path name. \fIOption\fR and the \fIarg\fRs
+determine the exact behavior of the command. The following
+commands are possible for frame widgets:
+.TP
+\fIpathName \fBcget\fR \fIoption\fR
+.
+Returns the current value of the configuration option given
+by \fIoption\fR.
+\fIOption\fR may have any of the values accepted by the \fBframe\fR
+command.
+.TP
+\fIpathName \fBconfigure\fR ?\fIoption\fR? \fI?value option value ...\fR?
+.
+Query or modify the configuration options of the widget.
+If no \fIoption\fR is specified, returns a list describing all of
+the available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for
+information on the format of this list). If \fIoption\fR is specified
+with no \fIvalue\fR, then the command returns a list describing the
+one named option (this list will be identical to the corresponding
+sublist of the value returned if no \fIoption\fR is specified). If
+one or more \fIoption\-value\fR pairs are specified, then the command
+modifies the given widget option(s) to have the given value(s); in
+this case the command returns an empty string.
+\fIOption\fR may have any of the values accepted by the \fBframe\fR
+command.
+.SH BINDINGS
+.PP
+When a new frame is created, it has no default event bindings:
+frames are not intended to be interactive.
+.SH "SEE ALSO"
+labelframe(n), toplevel(n), ttk::frame(n)
+.SH KEYWORDS
+frame, widget
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/getOpenFile.n b/tk8.6/doc/getOpenFile.n
new file mode 100644
index 0000000..d2323de
--- /dev/null
+++ b/tk8.6/doc/getOpenFile.n
@@ -0,0 +1,207 @@
+'\"
+'\" 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.
+'\"
+.TH tk_getOpenFile n 4.2 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+tk_getOpenFile, tk_getSaveFile \- pop up a dialog box for the user to select a file to open or save.
+.SH SYNOPSIS
+.nf
+\fBtk_getOpenFile \fR?\fIoption value ...\fR?
+\fBtk_getSaveFile \fR?\fIoption value ...\fR?
+.fi
+.BE
+.SH DESCRIPTION
+.PP
+The procedures \fBtk_getOpenFile\fR and \fBtk_getSaveFile\fR pop up a
+dialog box for the user to select a file to open or save. The
+\fBtk_getOpenFile\fR command is usually associated with the \fBOpen\fR
+command in the \fBFile\fR menu. Its purpose is for the user to select an
+existing file \fIonly\fR. If the user enters a non-existent file, the
+dialog box gives the user an error prompt and requires the user to give
+an alternative selection. If an application allows the user to create
+new files, it should do so by providing a separate \fBNew\fR menu command.
+.PP
+The \fBtk_getSaveFile\fR command is usually associated with the \fBSave
+as\fR command in the \fBFile\fR menu. If the user enters a file that
+already exists, the dialog box prompts the user for confirmation
+whether the existing file should be overwritten or not.
+.PP
+The following \fIoption\-value\fR pairs are possible as command line
+arguments to these two commands:
+.TP
+\fB\-command\fR \fIstring\fR
+Specifies the prefix of a Tcl command to invoke when the user closes the
+dialog after having selected an item. This callback is not called if the
+user cancelled the dialog. The actual command consists of \fIstring\fR
+followed by a space and the value selected by the user in the dialog. This
+is only available on Mac OS X.
+.TP
+\fB\-confirmoverwrite\fR \fIboolean\fR
+Configures how the Save dialog reacts when the selected file already
+exists, and saving would overwrite it. A true value requests a
+confirmation dialog be presented to the user. A false value requests
+that the overwrite take place without confirmation. Default value is true.
+.TP
+\fB\-defaultextension\fR \fIextension\fR
+.
+Specifies a string that will be appended to the filename if the user
+enters a filename without an extension. The default value is the empty
+string, which means no extension will be appended to the filename in
+any case. This option is ignored on Mac OS X, which
+does not require extensions to filenames,
+and the UNIX implementation guesses reasonable values for this from
+the \fB\-filetypes\fR option when this is not supplied.
+.TP
+\fB\-filetypes\fR \fIfilePatternList\fR
+.
+If a \fBFile types\fR listbox exists in the file dialog on the particular
+platform, this option gives the \fIfiletype\fRs in this listbox. When
+the user choose a filetype in the listbox, only the files of that type
+are listed. If this option is unspecified, or if it is set to the
+empty list, or if the \fBFile types\fR listbox is not supported by the
+particular platform then all files are listed regardless of their
+types. See the section \fBSPECIFYING FILE PATTERNS\fR below for a
+discussion on the contents of \fIfilePatternList\fR.
+.TP
+\fB\-initialdir\fR \fIdirectory\fR
+.
+Specifies that the files in \fIdirectory\fR should be displayed
+when the dialog pops up. If this parameter is not specified,
+the initial directory defaults to the current working directory
+on non-Windows systems and on Windows systems prior to Vista.
+On Vista and later systems, the initial directory defaults to the last
+user-selected directory for the application. If the
+parameter specifies a relative path, the return value will convert the
+relative path to an absolute path.
+.TP
+\fB\-initialfile\fR \fIfilename\fR
+.
+Specifies a filename to be displayed in the dialog when it pops up.
+.TP
+\fB\-message\fR \fIstring\fR
+.
+Specifies a message to include in the client area of the dialog.
+This is only available on Mac OS X.
+.TP
+\fB\-multiple\fR \fIboolean\fR
+.
+Allows the user to choose multiple files from the Open dialog.
+.TP
+\fB\-parent\fR \fIwindow\fR
+.
+Makes \fIwindow\fR the logical parent of the file dialog. The file
+dialog is displayed on top of its parent window. On Mac OS X, this
+turns the file dialog into a sheet attached to the parent window.
+.TP
+\fB\-title\fR \fItitleString\fR
+.
+Specifies a string to display as the title of the dialog box. If this
+option is not specified, then a default title is displayed.
+.TP
+\fB\-typevariable\fR \fIvariableName\fR
+.
+The global variable \fIvariableName\fR is used to preselect which filter is
+used from \fIfilterList\fR when the dialog box is opened and is
+updated when the dialog box is closed, to the last selected
+filter. The variable is read once at the beginning to select the
+appropriate filter. If the variable does not exist, or its value does
+not match any filter typename, or is empty (\fB{}\fR), the dialog box
+will revert to the default behavior of selecting the first filter in
+the list. If the dialog is canceled, the variable is not modified.
+.PP
+If the user selects a file, both \fBtk_getOpenFile\fR and
+\fBtk_getSaveFile\fR return the full pathname of this file. If the
+user cancels the operation, both commands return the empty string.
+.SH "SPECIFYING FILE PATTERNS"
+.PP
+The \fIfilePatternList\fR value given by the \fB\-filetypes\fR option
+is a list of file patterns. Each file pattern is a list of the
+form
+.CS
+\fItypeName\fR {\fIextension\fR ?\fIextension ...\fR?} ?{\fImacType\fR ?\fImacType ...\fR?}?
+.CE
+\fItypeName\fR is the name of the file type described by this
+file pattern and is the text string that appears in the \fBFile types\fR
+listbox. \fIextension\fR is a file extension for this file pattern.
+\fImacType\fR is a four-character Macintosh file type. The list of
+\fImacType\fRs is optional and may be omitted for applications that do
+not need to execute on the Macintosh platform.
+.PP
+Several file patterns may have the same \fItypeName,\fR in which case
+they refer to the same file type and share the same entry in the
+listbox. When the user selects an entry in the listbox, all the files
+that match at least one of the file patterns corresponding
+to that entry are listed. Usually, each file pattern corresponds to a
+distinct type of file. The use of more than one file pattern for one
+type of file is only necessary on the Macintosh platform.
+.PP
+On the Macintosh platform, a file matches a file pattern if its
+name matches at least one of the \fIextension\fR(s) AND it
+belongs to at least one of the \fImacType\fR(s) of the
+file pattern. For example, the \fBC Source Files\fR file pattern in the
+sample code matches with files that have a \fB\.c\fR extension AND
+belong to the \fImacType\fR \fBTEXT\fR. To use the OR rule instead,
+you can use two file patterns, one with the \fIextensions\fR only and
+the other with the \fImacType\fR only. The \fBGIF Files\fR file type
+in the sample code matches files that \fIeither\fR have a \fB\.gif\fR
+extension OR belong to the \fImacType\fR \fBGIFF\fR.
+.PP
+On the Unix and Windows platforms, a file matches a file pattern
+if its name matches at least one of the \fIextension\fR(s) of
+the file pattern. The \fImacType\fRs are ignored.
+.SH "SPECIFYING EXTENSIONS"
+.PP
+On the Unix and Macintosh platforms, extensions are matched using
+glob-style pattern matching. On the Windows platform, extensions are
+matched by the underlying operating system. The types of possible
+extensions are:
+.IP (1)
+the special extension
+.QW *
+matches any file;
+.IP (2)
+the special extension
+.MT
+matches any files that do not have an extension (i.e., the filename
+contains no full stop character);
+.IP (3)
+any character string that does not contain any wild card characters (*
+and ?).
+.PP
+Due to the different pattern matching rules on the various platforms,
+to ensure portability, wild card characters are not allowed in the
+extensions, except as in the special extension
+.QW * .
+Extensions without a full stop character (e.g.
+.QW ~ )
+are allowed but may not work on all platforms.
+.SH EXAMPLE
+.PP
+.CS
+set types {
+ {{Text Files} {.txt} }
+ {{TCL Scripts} {.tcl} }
+ {{C Source Files} {.c} TEXT}
+ {{GIF Files} {.gif} }
+ {{GIF Files} {} GIFF}
+ {{All Files} * }
+}
+set filename [\fBtk_getOpenFile\fR \-filetypes $types]
+
+if {$filename ne ""} {
+ # Open the file ...
+}
+.CE
+.SH "SEE ALSO"
+tk_chooseDirectory
+.SH KEYWORDS
+file selection dialog
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/grab.n b/tk8.6/doc/grab.n
new file mode 100644
index 0000000..c45e26a
--- /dev/null
+++ b/tk8.6/doc/grab.n
@@ -0,0 +1,150 @@
+'\"
+'\" Copyright (c) 1992 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH grab n "" Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+grab \- Confine pointer and keyboard events to a window sub-tree
+.SH SYNOPSIS
+\fBgrab \fR?\fB\-global\fR? \fIwindow\fR
+.sp
+\fBgrab \fIoption \fR?\fIarg arg \fR...?
+.BE
+.SH DESCRIPTION
+.PP
+This command implements simple pointer and keyboard grabs for Tk.
+Tk's grabs are different than the grabs
+described in the Xlib documentation.
+When a grab is set for a particular window, Tk restricts all pointer
+events to the grab window and its descendants in Tk's window hierarchy.
+Whenever the pointer is within the grab window's subtree, the pointer
+will behave exactly the same as if there had been no grab at all
+and all events will be reported in the normal fashion.
+When the pointer is outside \fIwindow\fR's tree, button presses and
+releases and
+mouse motion events are reported to \fIwindow\fR, and window entry
+and window exit events are ignored. The grab subtree
+.QW owns
+the pointer:
+windows outside the grab subtree will be visible on the screen
+but they will be insensitive until the grab is released.
+The tree of windows underneath the grab window can include top-level
+windows, in which case all of those top-level windows
+and their descendants will continue to receive mouse events
+during the grab.
+.PP
+Two forms of grabs are possible: local and global.
+A local grab affects only the grabbing application: events will
+be reported to other applications as if the grab had never occurred.
+Grabs are local by default.
+A global grab locks out all applications on the screen,
+so that only the given subtree of the grabbing application will be
+sensitive to pointer events (mouse button presses, mouse button releases,
+pointer motions, window entries, and window exits).
+During global grabs the window manager will not receive pointer
+events either.
+.PP
+During local grabs, keyboard events (key presses and key releases)
+are delivered as usual: the window
+manager controls which application receives keyboard events, and
+if they are sent to any window in the grabbing application then they are
+redirected to the focus window.
+During a global grab Tk grabs the keyboard so that all keyboard events
+are always sent to the grabbing application.
+The \fBfocus\fR command is still used to determine which window in the
+application receives the keyboard events.
+The keyboard grab is released when the grab is released.
+.PP
+On macOS a global grab affects all windows created by one Tk process.
+No window in that process other than the grab window can even be
+focused, hence no other window receives key or mouse events. A local
+grab on macOS affects all windows created by one Tcl interpreter. It
+is possible to focus any window belonging to the Tk process during a
+local grab but the grab window is the only window created by its
+interpreter which receives key or mouse events. Windows belonging to the
+same process but created by different interpreters continue to receive
+key and mouse events normally.
+.PP
+Grabs apply to particular displays. If an application has windows
+on multiple displays then it can establish a separate grab on each
+display.
+The grab on a particular display affects only the windows on
+that display.
+It is possible for different applications on a single display to have
+simultaneous local grabs, but only one application can have a global
+grab on a given display at once.
+.PP
+The \fBgrab\fR command can take any of the following forms:
+.TP
+\fBgrab \fR?\fB\-global\fR? \fIwindow\fR
+Same as \fBgrab set\fR, described below.
+.TP
+\fBgrab current \fR?\fIwindow\fR?
+If \fIwindow\fR is specified, returns the name of the current grab
+window in this application for \fIwindow\fR's display, or an empty
+string if there is no such window.
+If \fIwindow\fR is omitted, the command returns a list whose elements
+are all of the windows grabbed by this application for all displays,
+or an empty string if the application has no grabs.
+.TP
+\fBgrab release \fIwindow\fR
+Releases the grab on \fIwindow\fR if there is one, otherwise does
+nothing. Returns an empty string.
+.TP
+\fBgrab set \fR?\fB\-global\fR? \fIwindow\fR
+Sets a grab on \fIwindow\fR. If \fB\-global\fR is specified then the
+grab is global, otherwise it is local.
+If a grab was already in effect for this application on
+\fIwindow\fR's display then it is automatically released.
+If there is already a grab on \fIwindow\fR and it has the same
+global/local form as the requested grab, then the command
+does nothing. Returns an empty string.
+.TP
+\fBgrab status \fIwindow\fR
+Returns \fBnone\fR if no grab is currently set on \fIwindow\fR,
+\fBlocal\fR if a local grab is set on \fIwindow\fR, and
+\fBglobal\fR if a global grab is set.
+.SH WARNING
+.PP
+It is very easy to use global grabs to render a display completely
+unusable (e.g. by setting a grab on a widget which does not respond to
+events and not providing any mechanism for releasing the grab). Take
+\fIextreme\fR care when using them!
+.SH BUGS
+.PP
+It took an incredibly complex and gross implementation to produce
+the simple grab effect described above.
+Given the current implementation, it is not safe for applications
+to use the Xlib grab facilities at all except through the Tk grab
+procedures.
+If applications try to manipulate X's grab mechanisms directly,
+things will probably break.
+.PP
+If a single process is managing several different Tk applications,
+only one of those applications can have a local grab for a given
+display at any given time. If the applications are in different
+processes, this restriction does not exist.
+.SH EXAMPLE
+.PP
+Set a grab so that only one button may be clicked out of a group. The
+other buttons are unresponsive to the mouse until the middle button is
+clicked.
+.CS
+pack [button .b1 \-text "Click me! #1" \-command {destroy .b1}]
+pack [button .b2 \-text "Click me! #2" \-command {destroy .b2}]
+pack [button .b3 \-text "Click me! #3" \-command {destroy .b3}]
+\fBgrab\fR .b2
+.CE
+.SH "SEE ALSO"
+busy(n)
+.SH KEYWORDS
+grab, keyboard events, pointer events, window
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/grid.n b/tk8.6/doc/grid.n
new file mode 100644
index 0000000..c558071
--- /dev/null
+++ b/tk8.6/doc/grid.n
@@ -0,0 +1,456 @@
+'\"
+'\" 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.
+'\"
+.TH grid n 8.5 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+grid \- Geometry manager that arranges widgets in a grid
+.SH SYNOPSIS
+\fBgrid \fIoption arg \fR?\fIarg ...\fR?
+.BE
+.SH DESCRIPTION
+.PP
+The \fBgrid\fR command is used to communicate with the grid
+geometry manager that arranges widgets in rows and columns inside
+of another window, called the geometry master (or master window).
+The \fBgrid\fR command can have any of several forms, depending
+on the \fIoption\fR argument:
+.TP
+\fBgrid \fIslave \fR?\fIslave ...\fR? ?\fIoptions\fR?
+.
+If the first argument to \fBgrid\fR is suitable as the first slave
+argument to \fBgrid configure\fR, either a window name (any value
+starting with \fB.\fR) or one of the characters \fBx\fR or \fB^\fR
+(see the \fBRELATIVE PLACEMENT\fR section below), then the command is
+processed in the same way as \fBgrid configure\fR.
+.TP
+\fBgrid anchor \fImaster\fR ?\fIanchor\fR?
+.
+The anchor value controls how to place the grid within the master
+when no row/column has any weight. See \fBTHE GRID ALGORITHM\fR below
+for further details. The default \fIanchor\fR is \fInw\fR.
+.TP
+\fBgrid bbox \fImaster\fR ?\fIcolumn row\fR? ?\fIcolumn2 row2\fR?
+.
+With no arguments,
+the bounding box (in pixels) of the grid is returned.
+The return value consists of 4 integers. The first two are the pixel
+offset from the master window (x then y) of the top-left corner of the
+grid, and the second two integers are the width and height of the grid,
+also in pixels. If a single \fIcolumn\fR and \fIrow\fR is specified on
+the command line, then the bounding box for that cell is returned, where the
+top left cell is numbered from zero. If both \fIcolumn\fR and \fIrow\fR
+arguments are specified, then the bounding box spanning the rows and columns
+indicated is returned.
+.TP
+\fBgrid columnconfigure \fImaster index \fR?\fI\-option value...\fR?
+.
+Query or set the column properties of the \fIindex\fR column of the
+geometry master, \fImaster\fR.
+The valid options are \fB\-minsize\fR, \fB\-weight\fR, \fB\-uniform\fR
+and \fB\-pad\fR.
+If one or more options are provided, then \fIindex\fR may be given as
+a list of column indices to which the configuration options will operate on.
+Indices may be integers, window names or the keyword \fIall\fR. For \fIall\fR
+the options apply to all columns currently occupied be slave windows. For
+a window name, that window must be a slave of this master and the options
+apply to all columns currently occupied be the slave.
+The \fB\-minsize\fR option sets the minimum size, in screen units,
+that will be permitted for this column.
+The \fB\-weight\fR option (an integer value)
+sets the relative weight for apportioning
+any extra spaces among
+columns.
+A weight of zero (0) indicates the column will not deviate from its requested
+size. A column whose weight is two will grow at twice the rate as a column
+of weight one when extra space is allocated to the layout.
+The \fB\-uniform\fR option, when a non-empty value is supplied, places
+the column in a \fIuniform group\fR with other columns that have the
+same value for \fB\-uniform\fR. The space for columns belonging to a
+uniform group is allocated so that their sizes are always in strict
+proportion to their \fB\-weight\fR values. See
+\fBTHE GRID ALGORITHM\fR below for further details.
+The \fB\-pad\fR option specifies the number of screen units that will be
+added to the largest window contained completely in that column when the
+grid geometry manager requests a size from the containing window.
+If only an option is specified, with no value,
+the current value of that option is returned.
+If only the master window and index is specified, all the current settings
+are returned in a list of
+.QW "\-option value"
+pairs.
+.TP
+\fBgrid configure \fIslave \fR?\fIslave ...\fR? ?\fIoptions\fR?
+.
+The arguments consist of the names of one or more slave windows
+followed by pairs of arguments that specify how
+to manage the slaves.
+The characters \fB\-\fR, \fBx\fR and \fB^\fR,
+can be specified instead of a window name to alter the default
+location of a \fIslave\fR, as described in the \fBRELATIVE PLACEMENT\fR
+section, below.
+The following options are supported:
+.RS
+.TP
+\fB\-column \fIn\fR
+.
+Insert the slave so that it occupies the \fIn\fRth column in the grid.
+Column numbers start with 0. If this option is not supplied, then the
+slave is arranged just to the right of previous slave specified on this
+call to \fBgrid\fR, or column
+.QW 0
+if it is the first slave. For each
+\fBx\fR that immediately precedes the \fIslave\fR, the column position
+is incremented by one. Thus the \fBx\fR represents a blank column
+for this row in the grid.
+.TP
+\fB\-columnspan \fIn\fR
+.
+Insert the slave so that it occupies \fIn\fR columns in the grid.
+The default is one column, unless the window name is followed by a
+\fB\-\fR, in which case the columnspan is incremented once for each immediately
+following \fB\-\fR.
+.TP
+\fB\-in \fIother\fR
+.
+Insert the slave(s) in the master
+window given by \fIother\fR. The default is the first slave's
+parent window.
+.TP
+\fB\-ipadx \fIamount\fR
+.
+The \fIamount\fR specifies how much horizontal internal padding to
+leave on each side of the slave(s). This is space is added
+inside the slave(s) border.
+The \fIamount\fR must be a valid screen distance, such as \fB2\fR or \fB.5c\fR.
+It defaults to 0.
+.TP
+\fB\-ipady \fIamount\fR
+.
+The \fIamount\fR specifies how much vertical internal padding to
+leave on the top and bottom of the slave(s).
+This space is added inside the slave(s) border.
+The \fIamount\fR defaults to 0.
+.TP
+\fB\-padx \fIamount\fR
+.
+The \fIamount\fR specifies how much horizontal external padding to
+leave on each side of the slave(s), in screen units.
+\fIAmount\fR may be a list
+of two values to specify padding for left and right separately.
+The \fIamount\fR defaults to 0.
+This space is added outside the slave(s) border.
+.TP
+\fB\-pady \fIamount\fR
+.
+The \fIamount\fR specifies how much vertical external padding to
+leave on the top and bottom of the slave(s), in screen units.
+\fIAmount\fR may be a list
+of two values to specify padding for top and bottom separately.
+The \fIamount\fR defaults to 0.
+This space is added outside the slave(s) border.
+.TP
+\fB\-row \fIn\fR
+.
+Insert the slave so that it occupies the \fIn\fRth row in the grid.
+Row numbers start with 0. If this option is not supplied, then the
+slave is arranged on the same row as the previous slave specified on this
+call to \fBgrid\fR, or the next row after the highest occupied row
+if this is the first slave.
+.TP
+\fB\-rowspan \fIn\fR
+.
+Insert the slave so that it occupies \fIn\fR rows in the grid.
+The default is one row. If the next \fBgrid\fR command contains
+\fB^\fR characters instead of \fIslaves\fR that line up with the columns
+of this \fIslave\fR, then the \fBrowspan\fR of this \fIslave\fR is
+extended by one.
+.TP
+\fB\-sticky \fIstyle\fR
+.
+If a slave's cell is larger than its requested dimensions, this
+option may be used to position (or stretch) the slave within its cell.
+\fIStyle\fR is a string that contains zero or more of the characters
+\fBn\fR, \fBs\fR, \fBe\fR or \fBw\fR.
+The string can optionally contains spaces or
+commas, but they are ignored. Each letter refers to a side (north, south,
+east, or west) that the slave will
+.QW stick
+to. If both \fBn\fR and \fBs\fR (or \fBe\fR and \fBw\fR) are
+specified, the slave will be stretched to fill the entire
+height (or width) of its cavity. The \fB\-sticky\fR option subsumes the
+combination of \fB\-anchor\fR and \fB\-fill\fR that is used by \fBpack\fR.
+The default is
+.QW "" ,
+which causes the slave to be centered in its cavity, at its requested size.
+.LP
+If any of the slaves are already managed by the geometry manager
+then any unspecified options for them retain their previous values rather
+than receiving default values.
+.RE
+.TP
+\fBgrid forget \fIslave \fR?\fIslave ...\fR?
+.
+Removes each of the \fIslave\fRs from grid for its
+master and unmaps their windows.
+The slaves will no longer be managed by the grid geometry manager.
+The configuration options for that window are forgotten, so that if the
+slave is managed once more by the grid geometry manager, the initial
+default settings are used.
+.TP
+\fBgrid info \fIslave\fR
+.
+Returns a list whose elements are the current configuration state of
+the slave given by \fIslave\fR in the same option-value form that
+might be specified to \fBgrid configure\fR.
+The first two elements of the list are
+.QW "\fB\-in \fImaster\fR"
+where \fImaster\fR is the slave's master.
+.TP
+\fBgrid location \fImaster x y\fR
+.
+Given \fIx\fR and \fIy\fR values in screen units relative to the master window,
+the column and row number at that \fIx\fR and \fIy\fR location is returned.
+For locations that are above or to the left of the grid, \fB\-1\fR is
+returned.
+.TP
+\fBgrid propagate \fImaster\fR ?\fIboolean\fR?
+.
+If \fIboolean\fR has a true boolean value such as \fB1\fR or \fBon\fR
+then propagation is enabled for \fImaster\fR, which must be a window
+name (see \fBGEOMETRY PROPAGATION\fR below).
+If \fIboolean\fR has a false boolean value then propagation is
+disabled for \fImaster\fR.
+In either of these cases an empty string is returned.
+If \fIboolean\fR is omitted then the command returns \fB0\fR or
+\fB1\fR to indicate whether propagation is currently enabled
+for \fImaster\fR.
+Propagation is enabled by default.
+.TP
+\fBgrid rowconfigure \fImaster index \fR?\fI\-option value...\fR?
+.
+Query or set the row properties of the \fIindex\fR row of the
+geometry master, \fImaster\fR.
+The valid options are \fB\-minsize\fR, \fB\-weight\fR, \fB\-uniform\fR
+and \fB\-pad\fR.
+If one or more options are provided, then \fIindex\fR may be given as
+a list of row indices to which the configuration options will operate on.
+Indices may be integers, window names or the keyword \fIall\fR. For \fIall\fR
+the options apply to all rows currently occupied be slave windows. For
+a window name, that window must be a slave of this master and the options
+apply to all rows currently occupied be the slave.
+The \fB\-minsize\fR option sets the minimum size, in screen units,
+that will be permitted for this row.
+The \fB\-weight\fR option (an integer value)
+sets the relative weight for apportioning
+any extra spaces among
+rows.
+A weight of zero (0) indicates the row will not deviate from its requested
+size. A row whose weight is two will grow at twice the rate as a row
+of weight one when extra space is allocated to the layout.
+The \fB\-uniform\fR option, when a non-empty value is supplied, places
+the row in a \fIuniform group\fR with other rows that have the
+same value for \fB\-uniform\fR. The space for rows belonging to a
+uniform group is allocated so that their sizes are always in strict
+proportion to their \fB\-weight\fR values. See
+\fBTHE GRID ALGORITHM\fR below for further details.
+The \fB\-pad\fR option specifies the number of screen units that will be
+added to the largest window contained completely in that row when the
+grid geometry manager requests a size from the containing window.
+If only an option is specified, with no value,
+the current value of that option is returned.
+If only the master window and index is specified, all the current settings
+are returned in a list of
+.QW "-option value"
+pairs.
+.TP
+\fBgrid remove \fIslave \fR?\fIslave ...\fR?
+.
+Removes each of the \fIslave\fRs from grid for its
+master and unmaps their windows.
+The slaves will no longer be managed by the grid geometry manager.
+However, the configuration options for that window are remembered,
+so that if the
+slave is managed once more by the grid geometry manager, the previous
+values are retained.
+.TP
+\fBgrid size \fImaster\fR
+.
+Returns the size of the grid (in columns then rows) for \fImaster\fR.
+The size is determined either by the \fIslave\fR occupying the largest
+row or column, or the largest column or row with a \fB\-minsize\fR,
+\fB\-weight\fR, or \fB\-pad\fR that is non-zero.
+.TP
+\fBgrid slaves \fImaster\fR ?\fI\-option value\fR?
+.
+If no options are supplied, a list of all of the slaves in \fImaster\fR
+are returned, most recently manages first.
+\fIOption\fR can be either \fB\-row\fR or \fB\-column\fR which
+causes only the slaves in the row (or column) specified by \fIvalue\fR
+to be returned.
+.SH "RELATIVE PLACEMENT"
+.PP
+The \fBgrid\fR command contains a limited set of capabilities that
+permit layouts to be created without specifying the row and column
+information for each slave. This permits slaves to be rearranged,
+added, or removed without the need to explicitly specify row and
+column information.
+When no column or row information is specified for a \fIslave\fR,
+default values are chosen for
+\fB\-column\fR, \fB\-row\fR, \fB\-columnspan\fR and \fB\-rowspan\fR
+at the time the \fIslave\fR is managed. The values are chosen
+based upon the current layout of the grid, the position of the \fIslave\fR
+relative to other \fIslave\fRs in the same grid command, and the presence
+of the characters \fB\-\fR, \fBx\fR, and \fB^\fR in \fBgrid\fR
+command where \fIslave\fR names are normally expected.
+.RS
+.TP
+\fB\-\fR
+.
+This increases the \fB\-columnspan\fR of the \fIslave\fR to the left. Several
+\fB\-\fR's in a row will successively increase the number of columns spanned. A \fB\-\fR
+may not follow a \fB^\fR or a \fBx\fR, nor may it be the first \fIslave\fR
+argument to \fBgrid configure\fR.
+.TP
+\fBx\fR
+.
+This leaves an empty column between the \fIslave\fR on the left and
+the \fIslave\fR on the right.
+.TP
+\fB^\fR
+.
+This extends the \fB\-rowspan\fR of the \fIslave\fR above the \fB^\fR's
+in the grid. The number of \fB^\fR's in a row must match the number of
+columns spanned by the \fIslave\fR above it.
+.RE
+.SH "THE GRID ALGORITHM"
+.PP
+The grid geometry manager lays out its slaves in three steps.
+In the first step, the minimum size needed to fit all of the slaves
+is computed, then (if propagation is turned on), a request is made
+of the master window to become that size.
+In the second step, the requested size is compared against the actual size
+of the master. If the sizes are different, then spaces is added to or taken
+away from the layout as needed.
+For the final step, each slave is positioned in its row(s) and column(s)
+based on the setting of its \fIsticky\fR flag.
+.PP
+To compute the minimum size of a layout, the grid geometry manager
+first looks at all slaves whose \fB\-columnspan\fR and \fB\-rowspan\fR values are one,
+and computes the nominal size of each row or column to be either the
+\fIminsize\fR for that row or column, or the sum of the \fIpad\fRding
+plus the size of the largest slave, whichever is greater. After that
+the rows or columns in each uniform group adapt to each other. Then
+the slaves whose row-spans or column-spans are greater than one are
+examined. If a group of rows or columns need to be increased in size
+in order to accommodate these slaves, then extra space is added to each
+row or column in the group according to its \fIweight\fR. For each
+group whose weights are all zero, the additional space is apportioned
+equally.
+.PP
+When multiple rows or columns belong to a uniform group, the space
+allocated to them is always in proportion to their weights. (A weight
+of zero is considered to be 1.) In other words, a row or column
+configured with \fB\-weight 1 \-uniform a\fR will have exactly the same
+size as any other row or column configured with \fB\-weight 1 \-uniform
+a\fR. A row or column configured with \fB\-weight 2 \-uniform b\fR will
+be exactly twice as large as one that is configured with \fB\-weight 1
+\-uniform b\fR.
+.PP
+More technically, each row or column in the group will have a size
+equal to \fIk*weight\fR for some constant \fIk\fR. The constant
+\fIk\fR is chosen so that no row or column becomes smaller than its
+minimum size. For example, if all rows or columns in a group have the
+same weight, then each row or column will have the same size as the
+largest row or column in the group.
+.PP
+For masters whose size is larger than the requested layout, the additional
+space is apportioned according to the row and column weights. If all of
+the weights are zero, the layout is placed within its master according to
+the \fIanchor\fR value.
+For masters whose size is smaller than the requested layout, space is taken
+away from columns and rows according to their weights. However, once a
+column or row shrinks to its minsize, its weight is taken to be zero.
+If more space needs to be removed from a layout than would be permitted, as
+when all the rows or columns are at their minimum sizes, the layout is
+placed and clipped according to the \fIanchor\fR value.
+.SH "GEOMETRY PROPAGATION"
+.PP
+The grid geometry manager normally computes how large a master must be to
+just exactly meet the needs of its slaves, and it sets the
+requested width and height of the master to these dimensions.
+This causes geometry information to propagate up through a
+window hierarchy to a top-level window so that the entire
+sub-tree sizes itself to fit the needs of the leaf windows.
+However, the \fBgrid propagate\fR command may be used to
+turn off propagation for one or more masters.
+If propagation is disabled then grid will not set
+the requested width and height of the master window.
+This may be useful if, for example, you wish for a master
+window to have a fixed size that you specify.
+.SH "RESTRICTIONS ON MASTER WINDOWS"
+.PP
+The master for each slave must either be the slave's parent
+(the default) or a descendant of the slave's parent.
+This restriction is necessary to guarantee that the
+slave can be placed over any part of its master that is
+visible without danger of the slave being clipped by its parent.
+In addition, all slaves in one call to \fBgrid\fR must have the same master.
+.SH "STACKING ORDER"
+.PP
+If the master for a slave is not its parent then you must make sure
+that the slave is higher in the stacking order than the master.
+Otherwise the master will obscure the slave and it will appear as
+if the slave has not been managed correctly.
+The easiest way to make sure the slave is higher than the master is
+to create the master window first: the most recently created window
+will be highest in the stacking order.
+.SH CREDITS
+.PP
+The \fBgrid\fR command is based on ideas taken from the \fIGridBag\fR
+geometry manager written by Doug. Stein, and the \fBblt_table\fR geometry
+manager, written by George Howlett.
+.SH EXAMPLES
+.PP
+A toplevel window containing a text widget and two scrollbars:
+.PP
+.CS
+# Make the widgets
+toplevel .t
+text .t.txt \-wrap none \-xscroll {.t.h set} \-yscroll {.t.v set}
+scrollbar .t.v \-orient vertical \-command {.t.txt yview}
+scrollbar .t.h \-orient horizontal \-command {.t.txt xview}
+
+# Lay them out
+\fBgrid\fR .t.txt .t.v \-sticky nsew
+\fBgrid\fR .t.h \-sticky nsew
+
+# Tell the text widget to take all the extra room
+\fBgrid rowconfigure\fR .t .t.txt \-weight 1
+\fBgrid columnconfigure\fR .t .t.txt \-weight 1
+.CE
+.PP
+Three widgets of equal width, despite their different
+.QW natural
+widths:
+.PP
+.CS
+button .b \-text "Foo"
+entry .e \-variable foo
+label .l \-text "This is a fairly long piece of text"
+
+\fBgrid\fR .b .e .l \-sticky ew
+\fBgrid columnconfigure\fR . "all" \-uniform allTheSame
+.CE
+.SH "SEE ALSO"
+pack(n), place(n)
+.SH KEYWORDS
+geometry manager, location, grid, cell, propagation, size, pack
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/image.n b/tk8.6/doc/image.n
new file mode 100644
index 0000000..fd51cc0
--- /dev/null
+++ b/tk8.6/doc/image.n
@@ -0,0 +1,102 @@
+'\"
+'\" Copyright (c) 1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH image n 4.0 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+image \- Create and manipulate images
+.SH SYNOPSIS
+\fBimage\fR \fIoption \fR?\fIarg arg ...\fR?
+.BE
+.SH DESCRIPTION
+.PP
+The \fBimage\fR command is used to create, delete, and query images.
+It can take several different forms, depending on the
+\fIoption\fR argument. The legal forms are:
+.TP
+\fBimage create \fItype \fR?\fIname\fR? ?\fIoption value ...\fR?
+Creates a new image and a command with the same name and returns its name.
+\fItype\fR specifies the type of the image, which must be one of
+the types currently defined (e.g., \fBbitmap\fR).
+\fIname\fR specifies the name for the image; if it is omitted then
+Tk picks a name of the form \fBimage\fIx\fR, where \fIx\fR is
+an integer.
+There may be any number of \fIoption\fR\-\fIvalue\fR pairs,
+which provide configuration options for the new image.
+The legal set of options is defined separately for each image
+type; see below for details on the options for built-in image types.
+If an image already exists by the given name then it is replaced
+with the new image and any instances of that image will redisplay
+with the new contents.
+It is important to note that the image command will silently overwrite any
+procedure that may currently be defined by the given name, so choose the
+name wisely. It is recommended to use a separate namespace for image names
+(e.g., \fB::img::logo\fR, \fB::img::large\fR).
+.TP
+\fBimage delete \fR?\fIname name\fR ...?
+Deletes each of the named images and returns an empty string.
+If there are instances of the images displayed in widgets,
+the images will not actually be deleted until all of the instances
+are released.
+However, the association between the instances and the image
+manager will be dropped.
+Existing instances will retain their sizes but redisplay as
+empty areas.
+If a deleted image is recreated with another call to \fBimage create\fR,
+the existing instances will use the new image.
+.TP
+\fBimage height \fIname\fR
+Returns a decimal string giving the height of image \fIname\fR
+in pixels.
+.TP
+\fBimage inuse \fIname\fR
+Returns a boolean value indicating whether or not the image given by
+\fIname\fR is in use by any widgets.
+.TP
+\fBimage names\fR
+Returns a list containing the names of all existing images.
+.TP
+\fBimage type \fIname\fR
+Returns the type of image \fIname\fR (the value of the \fItype\fR
+argument to \fBimage create\fR when the image was created).
+.TP
+\fBimage types\fR
+Returns a list whose elements are all of the valid image types
+(i.e., all of the values that may be supplied for the \fItype\fR
+argument to \fBimage create\fR).
+.TP
+\fBimage width \fIname\fR
+Returns a decimal string giving the width of image \fIname\fR
+in pixels.
+.PP
+Additional operations (e.g. writing the image to a file) may be
+available as subcommands of the image instance command. See the manual
+page for the particular image type for details.
+.SH "BUILT-IN IMAGE TYPES"
+.PP
+The following image types are defined by Tk so they will be available
+in any Tk application.
+Individual applications or extensions may define additional types.
+.TP
+\fBbitmap\fR
+Each pixel in the image displays a foreground color, a background
+color, or nothing.
+See the \fBbitmap\fR manual entry for more information.
+.TP
+\fBphoto\fR
+Displays a variety of full-color images, using dithering to
+approximate colors on displays with limited color capabilities.
+See the \fBphoto\fR manual entry for more information.
+.SH "SEE ALSO"
+bitmap(n), options(n), photo(n)
+.SH KEYWORDS
+height, image, types of images, width
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/keysyms.n b/tk8.6/doc/keysyms.n
new file mode 100644
index 0000000..512c1a6
--- /dev/null
+++ b/tk8.6/doc/keysyms.n
@@ -0,0 +1,937 @@
+'\"
+'\" Copyright (c) 1998-2000 by Scriptics Corporation.
+'\" All rights reserved.
+'\"
+.TH keysyms n 8.3 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+keysyms \- keysyms recognized by Tk
+.BE
+.SH DESCRIPTION
+.PP
+Tk recognizes many keysyms when specifying key bindings (e.g.,
+.QW "\fBbind\fR \fB. <Key-\fR\fIkeysym\fR\fB>\fR" ).
+The following list enumerates the
+keysyms that will be recognized by Tk. Note that not all keysyms will
+be valid on all platforms, and some keysyms are also available on
+platforms that have a different native name for that key.
+For example, on Unix systems, the presence
+of a particular keysym is dependant on the configuration of the
+keyboard modifier map. This list shows keysyms along with their
+decimal and hexadecimal values.
+.PP
+.CS
+space 32 0x0020
+exclam 33 0x0021
+quotedbl 34 0x0022
+numbersign 35 0x0023
+dollar 36 0x0024
+percent 37 0x0025
+ampersand 38 0x0026
+quoteright 39 0x0027
+parenleft 40 0x0028
+parenright 41 0x0029
+asterisk 42 0x002a
+plus 43 0x002b
+comma 44 0x002c
+minus 45 0x002d
+period 46 0x002e
+slash 47 0x002f
+0 48 0x0030
+1 49 0x0031
+2 50 0x0032
+3 51 0x0033
+4 52 0x0034
+5 53 0x0035
+6 54 0x0036
+7 55 0x0037
+8 56 0x0038
+9 57 0x0039
+colon 58 0x003a
+semicolon 59 0x003b
+less 60 0x003c
+equal 61 0x003d
+greater 62 0x003e
+question 63 0x003f
+at 64 0x0040
+A 65 0x0041
+B 66 0x0042
+C 67 0x0043
+D 68 0x0044
+E 69 0x0045
+F 70 0x0046
+G 71 0x0047
+H 72 0x0048
+I 73 0x0049
+J 74 0x004a
+K 75 0x004b
+L 76 0x004c
+M 77 0x004d
+N 78 0x004e
+O 79 0x004f
+P 80 0x0050
+Q 81 0x0051
+R 82 0x0052
+S 83 0x0053
+T 84 0x0054
+U 85 0x0055
+V 86 0x0056
+W 87 0x0057
+X 88 0x0058
+Y 89 0x0059
+Z 90 0x005a
+bracketleft 91 0x005b
+backslash 92 0x005c
+bracketright 93 0x005d
+asciicircum 94 0x005e
+underscore 95 0x005f
+quoteleft 96 0x0060
+a 97 0x0061
+b 98 0x0062
+c 99 0x0063
+d 100 0x0064
+e 101 0x0065
+f 102 0x0066
+g 103 0x0067
+h 104 0x0068
+i 105 0x0069
+j 106 0x006a
+k 107 0x006b
+l 108 0x006c
+m 109 0x006d
+n 110 0x006e
+o 111 0x006f
+p 112 0x0070
+q 113 0x0071
+r 114 0x0072
+s 115 0x0073
+t 116 0x0074
+u 117 0x0075
+v 118 0x0076
+w 119 0x0077
+x 120 0x0078
+y 121 0x0079
+z 122 0x007a
+braceleft 123 0x007b
+bar 124 0x007c
+braceright 125 0x007d
+asciitilde 126 0x007e
+nobreakspace 160 0x00a0
+exclamdown 161 0x00a1
+cent 162 0x00a2
+sterling 163 0x00a3
+currency 164 0x00a4
+yen 165 0x00a5
+brokenbar 166 0x00a6
+section 167 0x00a7
+diaeresis 168 0x00a8
+copyright 169 0x00a9
+ordfeminine 170 0x00aa
+guillemotleft 171 0x00ab
+notsign 172 0x00ac
+hyphen 173 0x00ad
+registered 174 0x00ae
+macron 175 0x00af
+degree 176 0x00b0
+plusminus 177 0x00b1
+twosuperior 178 0x00b2
+threesuperior 179 0x00b3
+acute 180 0x00b4
+mu 181 0x00b5
+paragraph 182 0x00b6
+periodcentered 183 0x00b7
+cedilla 184 0x00b8
+onesuperior 185 0x00b9
+masculine 186 0x00ba
+guillemotright 187 0x00bb
+onequarter 188 0x00bc
+onehalf 189 0x00bd
+threequarters 190 0x00be
+questiondown 191 0x00bf
+Agrave 192 0x00c0
+Aacute 193 0x00c1
+Acircumflex 194 0x00c2
+Atilde 195 0x00c3
+Adiaeresis 196 0x00c4
+Aring 197 0x00c5
+AE 198 0x00c6
+Ccedilla 199 0x00c7
+Egrave 200 0x00c8
+Eacute 201 0x00c9
+Ecircumflex 202 0x00ca
+Ediaeresis 203 0x00cb
+Igrave 204 0x00cc
+Iacute 205 0x00cd
+Icircumflex 206 0x00ce
+Idiaeresis 207 0x00cf
+Eth 208 0x00d0
+Ntilde 209 0x00d1
+Ograve 210 0x00d2
+Oacute 211 0x00d3
+Ocircumflex 212 0x00d4
+Otilde 213 0x00d5
+Odiaeresis 214 0x00d6
+multiply 215 0x00d7
+Ooblique 216 0x00d8
+Ugrave 217 0x00d9
+Uacute 218 0x00da
+Ucircumflex 219 0x00db
+Udiaeresis 220 0x00dc
+Yacute 221 0x00dd
+Thorn 222 0x00de
+ssharp 223 0x00df
+agrave 224 0x00e0
+aacute 225 0x00e1
+acircumflex 226 0x00e2
+atilde 227 0x00e3
+adiaeresis 228 0x00e4
+aring 229 0x00e5
+ae 230 0x00e6
+ccedilla 231 0x00e7
+egrave 232 0x00e8
+eacute 233 0x00e9
+ecircumflex 234 0x00ea
+ediaeresis 235 0x00eb
+igrave 236 0x00ec
+iacute 237 0x00ed
+icircumflex 238 0x00ee
+idiaeresis 239 0x00ef
+eth 240 0x00f0
+ntilde 241 0x00f1
+ograve 242 0x00f2
+oacute 243 0x00f3
+ocircumflex 244 0x00f4
+otilde 245 0x00f5
+odiaeresis 246 0x00f6
+division 247 0x00f7
+oslash 248 0x00f8
+ugrave 249 0x00f9
+uacute 250 0x00fa
+ucircumflex 251 0x00fb
+udiaeresis 252 0x00fc
+yacute 253 0x00fd
+thorn 254 0x00fe
+ydiaeresis 255 0x00ff
+Aogonek 417 0x01a1
+breve 418 0x01a2
+Lstroke 419 0x01a3
+Lcaron 421 0x01a5
+Sacute 422 0x01a6
+Scaron 425 0x01a9
+Scedilla 426 0x01aa
+Tcaron 427 0x01ab
+Zacute 428 0x01ac
+.CE
+.CS
+Zcaron 430 0x01ae
+Zabovedot 431 0x01af
+aogonek 433 0x01b1
+ogonek 434 0x01b2
+lstroke 435 0x01b3
+lcaron 437 0x01b5
+sacute 438 0x01b6
+caron 439 0x01b7
+scaron 441 0x01b9
+scedilla 442 0x01ba
+tcaron 443 0x01bb
+zacute 444 0x01bc
+doubleacute 445 0x01bd
+zcaron 446 0x01be
+zabovedot 447 0x01bf
+Racute 448 0x01c0
+Abreve 451 0x01c3
+Cacute 454 0x01c6
+Ccaron 456 0x01c8
+Eogonek 458 0x01ca
+Ecaron 460 0x01cc
+Dcaron 463 0x01cf
+Nacute 465 0x01d1
+Ncaron 466 0x01d2
+Odoubleacute 469 0x01d5
+Rcaron 472 0x01d8
+Uring 473 0x01d9
+Udoubleacute 475 0x01db
+Tcedilla 478 0x01de
+racute 480 0x01e0
+abreve 483 0x01e3
+cacute 486 0x01e6
+ccaron 488 0x01e8
+eogonek 490 0x01ea
+ecaron 492 0x01ec
+dcaron 495 0x01ef
+nacute 497 0x01f1
+ncaron 498 0x01f2
+odoubleacute 501 0x01f5
+rcaron 504 0x01f8
+uring 505 0x01f9
+udoubleacute 507 0x01fb
+tcedilla 510 0x01fe
+abovedot 511 0x01ff
+Hstroke 673 0x02a1
+Hcircumflex 678 0x02a6
+Iabovedot 681 0x02a9
+Gbreve 683 0x02ab
+Jcircumflex 684 0x02ac
+hstroke 689 0x02b1
+hcircumflex 694 0x02b6
+idotless 697 0x02b9
+gbreve 699 0x02bb
+jcircumflex 700 0x02bc
+Cabovedot 709 0x02c5
+Ccircumflex 710 0x02c6
+Gabovedot 725 0x02d5
+Gcircumflex 728 0x02d8
+Ubreve 733 0x02dd
+Scircumflex 734 0x02de
+cabovedot 741 0x02e5
+ccircumflex 742 0x02e6
+gabovedot 757 0x02f5
+gcircumflex 760 0x02f8
+ubreve 765 0x02fd
+scircumflex 766 0x02fe
+kappa 930 0x03a2
+Rcedilla 931 0x03a3
+Itilde 933 0x03a5
+Lcedilla 934 0x03a6
+Emacron 938 0x03aa
+Gcedilla 939 0x03ab
+Tslash 940 0x03ac
+rcedilla 947 0x03b3
+itilde 949 0x03b5
+lcedilla 950 0x03b6
+emacron 954 0x03ba
+gacute 955 0x03bb
+tslash 956 0x03bc
+ENG 957 0x03bd
+eng 959 0x03bf
+Amacron 960 0x03c0
+Iogonek 967 0x03c7
+Eabovedot 972 0x03cc
+Imacron 975 0x03cf
+Ncedilla 977 0x03d1
+Omacron 978 0x03d2
+Kcedilla 979 0x03d3
+Uogonek 985 0x03d9
+Utilde 989 0x03dd
+Umacron 990 0x03de
+amacron 992 0x03e0
+iogonek 999 0x03e7
+eabovedot 1004 0x03ec
+imacron 1007 0x03ef
+ncedilla 1009 0x03f1
+omacron 1010 0x03f2
+kcedilla 1011 0x03f3
+uogonek 1017 0x03f9
+utilde 1021 0x03fd
+umacron 1022 0x03fe
+overline 1150 0x047e
+kana_fullstop 1185 0x04a1
+kana_openingbracket 1186 0x04a2
+kana_closingbracket 1187 0x04a3
+kana_comma 1188 0x04a4
+kana_middledot 1189 0x04a5
+kana_WO 1190 0x04a6
+kana_a 1191 0x04a7
+kana_i 1192 0x04a8
+kana_u 1193 0x04a9
+kana_e 1194 0x04aa
+kana_o 1195 0x04ab
+kana_ya 1196 0x04ac
+kana_yu 1197 0x04ad
+kana_yo 1198 0x04ae
+kana_tu 1199 0x04af
+prolongedsound 1200 0x04b0
+kana_A 1201 0x04b1
+kana_I 1202 0x04b2
+kana_U 1203 0x04b3
+kana_E 1204 0x04b4
+kana_O 1205 0x04b5
+kana_KA 1206 0x04b6
+kana_KI 1207 0x04b7
+kana_KU 1208 0x04b8
+kana_KE 1209 0x04b9
+kana_KO 1210 0x04ba
+kana_SA 1211 0x04bb
+kana_SHI 1212 0x04bc
+kana_SU 1213 0x04bd
+kana_SE 1214 0x04be
+kana_SO 1215 0x04bf
+kana_TA 1216 0x04c0
+kana_TI 1217 0x04c1
+kana_TU 1218 0x04c2
+kana_TE 1219 0x04c3
+kana_TO 1220 0x04c4
+kana_NA 1221 0x04c5
+kana_NI 1222 0x04c6
+kana_NU 1223 0x04c7
+kana_NE 1224 0x04c8
+kana_NO 1225 0x04c9
+kana_HA 1226 0x04ca
+kana_HI 1227 0x04cb
+kana_HU 1228 0x04cc
+kana_HE 1229 0x04cd
+kana_HO 1230 0x04ce
+kana_MA 1231 0x04cf
+kana_MI 1232 0x04d0
+kana_MU 1233 0x04d1
+kana_ME 1234 0x04d2
+kana_MO 1235 0x04d3
+kana_YA 1236 0x04d4
+kana_YU 1237 0x04d5
+kana_YO 1238 0x04d6
+kana_RA 1239 0x04d7
+kana_RI 1240 0x04d8
+kana_RU 1241 0x04d9
+kana_RE 1242 0x04da
+kana_RO 1243 0x04db
+kana_WA 1244 0x04dc
+kana_N 1245 0x04dd
+voicedsound 1246 0x04de
+semivoicedsound 1247 0x04df
+Arabic_comma 1452 0x05ac
+Arabic_semicolon 1467 0x05bb
+Arabic_question_mark 1471 0x05bf
+Arabic_hamza 1473 0x05c1
+Arabic_maddaonalef 1474 0x05c2
+Arabic_hamzaonalef 1475 0x05c3
+Arabic_hamzaonwaw 1476 0x05c4
+Arabic_hamzaunderalef 1477 0x05c5
+Arabic_hamzaonyeh 1478 0x05c6
+Arabic_alef 1479 0x05c7
+Arabic_beh 1480 0x05c8
+Arabic_tehmarbuta 1481 0x05c9
+Arabic_teh 1482 0x05ca
+Arabic_theh 1483 0x05cb
+Arabic_jeem 1484 0x05cc
+Arabic_hah 1485 0x05cd
+Arabic_khah 1486 0x05ce
+Arabic_dal 1487 0x05cf
+Arabic_thal 1488 0x05d0
+Arabic_ra 1489 0x05d1
+Arabic_zain 1490 0x05d2
+Arabic_seen 1491 0x05d3
+Arabic_sheen 1492 0x05d4
+Arabic_sad 1493 0x05d5
+Arabic_dad 1494 0x05d6
+Arabic_tah 1495 0x05d7
+Arabic_zah 1496 0x05d8
+Arabic_ain 1497 0x05d9
+Arabic_ghain 1498 0x05da
+Arabic_tatweel 1504 0x05e0
+Arabic_feh 1505 0x05e1
+Arabic_qaf 1506 0x05e2
+Arabic_kaf 1507 0x05e3
+Arabic_lam 1508 0x05e4
+Arabic_meem 1509 0x05e5
+.CE
+.CS
+Arabic_noon 1510 0x05e6
+Arabic_heh 1511 0x05e7
+Arabic_waw 1512 0x05e8
+Arabic_alefmaksura 1513 0x05e9
+Arabic_yeh 1514 0x05ea
+Arabic_fathatan 1515 0x05eb
+Arabic_dammatan 1516 0x05ec
+Arabic_kasratan 1517 0x05ed
+Arabic_fatha 1518 0x05ee
+Arabic_damma 1519 0x05ef
+Arabic_kasra 1520 0x05f0
+Arabic_shadda 1521 0x05f1
+Arabic_sukun 1522 0x05f2
+Serbian_dje 1697 0x06a1
+Macedonia_gje 1698 0x06a2
+Cyrillic_io 1699 0x06a3
+Ukranian_je 1700 0x06a4
+Macedonia_dse 1701 0x06a5
+Ukranian_i 1702 0x06a6
+Ukranian_yi 1703 0x06a7
+Serbian_je 1704 0x06a8
+Serbian_lje 1705 0x06a9
+Serbian_nje 1706 0x06aa
+Serbian_tshe 1707 0x06ab
+Macedonia_kje 1708 0x06ac
+Byelorussian_shortu 1710 0x06ae
+Serbian_dze 1711 0x06af
+numerosign 1712 0x06b0
+Serbian_DJE 1713 0x06b1
+Macedonia_GJE 1714 0x06b2
+Cyrillic_IO 1715 0x06b3
+Ukranian_JE 1716 0x06b4
+Macedonia_DSE 1717 0x06b5
+Ukranian_I 1718 0x06b6
+Ukranian_YI 1719 0x06b7
+Serbian_JE 1720 0x06b8
+Serbian_LJE 1721 0x06b9
+Serbian_NJE 1722 0x06ba
+Serbian_TSHE 1723 0x06bb
+Macedonia_KJE 1724 0x06bc
+Byelorussian_SHORTU 1726 0x06be
+Serbian_DZE 1727 0x06bf
+Cyrillic_yu 1728 0x06c0
+Cyrillic_a 1729 0x06c1
+Cyrillic_be 1730 0x06c2
+Cyrillic_tse 1731 0x06c3
+Cyrillic_de 1732 0x06c4
+Cyrillic_ie 1733 0x06c5
+Cyrillic_ef 1734 0x06c6
+Cyrillic_ghe 1735 0x06c7
+Cyrillic_ha 1736 0x06c8
+Cyrillic_i 1737 0x06c9
+Cyrillic_shorti 1738 0x06ca
+Cyrillic_ka 1739 0x06cb
+Cyrillic_el 1740 0x06cc
+Cyrillic_em 1741 0x06cd
+Cyrillic_en 1742 0x06ce
+Cyrillic_o 1743 0x06cf
+Cyrillic_pe 1744 0x06d0
+Cyrillic_ya 1745 0x06d1
+Cyrillic_er 1746 0x06d2
+Cyrillic_es 1747 0x06d3
+Cyrillic_te 1748 0x06d4
+Cyrillic_u 1749 0x06d5
+Cyrillic_zhe 1750 0x06d6
+Cyrillic_ve 1751 0x06d7
+Cyrillic_softsign 1752 0x06d8
+Cyrillic_yeru 1753 0x06d9
+Cyrillic_ze 1754 0x06da
+Cyrillic_sha 1755 0x06db
+Cyrillic_e 1756 0x06dc
+Cyrillic_shcha 1757 0x06dd
+Cyrillic_che 1758 0x06de
+Cyrillic_hardsign 1759 0x06df
+Cyrillic_YU 1760 0x06e0
+Cyrillic_A 1761 0x06e1
+Cyrillic_BE 1762 0x06e2
+Cyrillic_TSE 1763 0x06e3
+Cyrillic_DE 1764 0x06e4
+Cyrillic_IE 1765 0x06e5
+Cyrillic_EF 1766 0x06e6
+Cyrillic_GHE 1767 0x06e7
+Cyrillic_HA 1768 0x06e8
+Cyrillic_I 1769 0x06e9
+Cyrillic_SHORTI 1770 0x06ea
+Cyrillic_KA 1771 0x06eb
+Cyrillic_EL 1772 0x06ec
+Cyrillic_EM 1773 0x06ed
+Cyrillic_EN 1774 0x06ee
+Cyrillic_O 1775 0x06ef
+Cyrillic_PE 1776 0x06f0
+Cyrillic_YA 1777 0x06f1
+Cyrillic_ER 1778 0x06f2
+Cyrillic_ES 1779 0x06f3
+Cyrillic_TE 1780 0x06f4
+Cyrillic_U 1781 0x06f5
+Cyrillic_ZHE 1782 0x06f6
+Cyrillic_VE 1783 0x06f7
+Cyrillic_SOFTSIGN 1784 0x06f8
+Cyrillic_YERU 1785 0x06f9
+Cyrillic_ZE 1786 0x06fa
+Cyrillic_SHA 1787 0x06fb
+Cyrillic_E 1788 0x06fc
+Cyrillic_SHCHA 1789 0x06fd
+Cyrillic_CHE 1790 0x06fe
+Cyrillic_HARDSIGN 1791 0x06ff
+Greek_ALPHAaccent 1953 0x07a1
+Greek_EPSILONaccent 1954 0x07a2
+Greek_ETAaccent 1955 0x07a3
+Greek_IOTAaccent 1956 0x07a4
+Greek_IOTAdiaeresis 1957 0x07a5
+Greek_IOTAaccentdiaeresis 1958 0x07a6
+Greek_OMICRONaccent 1959 0x07a7
+Greek_UPSILONaccent 1960 0x07a8
+Greek_UPSILONdieresis 1961 0x07a9
+Greek_UPSILONaccentdieresis 1962 0x07aa
+Greek_OMEGAaccent 1963 0x07ab
+Greek_alphaaccent 1969 0x07b1
+Greek_epsilonaccent 1970 0x07b2
+Greek_etaaccent 1971 0x07b3
+Greek_iotaaccent 1972 0x07b4
+Greek_iotadieresis 1973 0x07b5
+Greek_iotaaccentdieresis 1974 0x07b6
+Greek_omicronaccent 1975 0x07b7
+Greek_upsilonaccent 1976 0x07b8
+Greek_upsilondieresis 1977 0x07b9
+Greek_upsilonaccentdieresis 1978 0x07ba
+Greek_omegaaccent 1979 0x07bb
+Greek_ALPHA 1985 0x07c1
+Greek_BETA 1986 0x07c2
+Greek_GAMMA 1987 0x07c3
+Greek_DELTA 1988 0x07c4
+Greek_EPSILON 1989 0x07c5
+Greek_ZETA 1990 0x07c6
+Greek_ETA 1991 0x07c7
+Greek_THETA 1992 0x07c8
+Greek_IOTA 1993 0x07c9
+Greek_KAPPA 1994 0x07ca
+Greek_LAMBDA 1995 0x07cb
+Greek_MU 1996 0x07cc
+Greek_NU 1997 0x07cd
+Greek_XI 1998 0x07ce
+Greek_OMICRON 1999 0x07cf
+Greek_PI 2000 0x07d0
+Greek_RHO 2001 0x07d1
+Greek_SIGMA 2002 0x07d2
+Greek_TAU 2004 0x07d4
+Greek_UPSILON 2005 0x07d5
+Greek_PHI 2006 0x07d6
+Greek_CHI 2007 0x07d7
+Greek_PSI 2008 0x07d8
+Greek_OMEGA 2009 0x07d9
+Greek_alpha 2017 0x07e1
+Greek_beta 2018 0x07e2
+Greek_gamma 2019 0x07e3
+Greek_delta 2020 0x07e4
+Greek_epsilon 2021 0x07e5
+Greek_zeta 2022 0x07e6
+Greek_eta 2023 0x07e7
+Greek_theta 2024 0x07e8
+Greek_iota 2025 0x07e9
+Greek_kappa 2026 0x07ea
+Greek_lambda 2027 0x07eb
+Greek_mu 2028 0x07ec
+Greek_nu 2029 0x07ed
+Greek_xi 2030 0x07ee
+Greek_omicron 2031 0x07ef
+Greek_pi 2032 0x07f0
+Greek_rho 2033 0x07f1
+Greek_sigma 2034 0x07f2
+Greek_finalsmallsigma 2035 0x07f3
+Greek_tau 2036 0x07f4
+Greek_upsilon 2037 0x07f5
+Greek_phi 2038 0x07f6
+Greek_chi 2039 0x07f7
+Greek_psi 2040 0x07f8
+Greek_omega 2041 0x07f9
+leftradical 2209 0x08a1
+topleftradical 2210 0x08a2
+horizconnector 2211 0x08a3
+topintegral 2212 0x08a4
+botintegral 2213 0x08a5
+vertconnector 2214 0x08a6
+topleftsqbracket 2215 0x08a7
+botleftsqbracket 2216 0x08a8
+toprightsqbracket 2217 0x08a9
+botrightsqbracket 2218 0x08aa
+topleftparens 2219 0x08ab
+botleftparens 2220 0x08ac
+toprightparens 2221 0x08ad
+botrightparens 2222 0x08ae
+leftmiddlecurlybrace 2223 0x08af
+rightmiddlecurlybrace 2224 0x08b0
+topleftsummation 2225 0x08b1
+botleftsummation 2226 0x08b2
+topvertsummationconnector 2227 0x08b3
+botvertsummationconnector 2228 0x08b4
+toprightsummation 2229 0x08b5
+botrightsummation 2230 0x08b6
+rightmiddlesummation 2231 0x08b7
+.CE
+.CS
+lessthanequal 2236 0x08bc
+notequal 2237 0x08bd
+greaterthanequal 2238 0x08be
+integral 2239 0x08bf
+therefore 2240 0x08c0
+variation 2241 0x08c1
+infinity 2242 0x08c2
+nabla 2245 0x08c5
+approximate 2248 0x08c8
+similarequal 2249 0x08c9
+ifonlyif 2253 0x08cd
+implies 2254 0x08ce
+identical 2255 0x08cf
+radical 2262 0x08d6
+includedin 2266 0x08da
+includes 2267 0x08db
+intersection 2268 0x08dc
+union 2269 0x08dd
+logicaland 2270 0x08de
+logicalor 2271 0x08df
+partialderivative 2287 0x08ef
+function 2294 0x08f6
+leftarrow 2299 0x08fb
+uparrow 2300 0x08fc
+rightarrow 2301 0x08fd
+downarrow 2302 0x08fe
+blank 2527 0x09df
+soliddiamond 2528 0x09e0
+checkerboard 2529 0x09e1
+ht 2530 0x09e2
+ff 2531 0x09e3
+cr 2532 0x09e4
+lf 2533 0x09e5
+nl 2536 0x09e8
+vt 2537 0x09e9
+lowrightcorner 2538 0x09ea
+uprightcorner 2539 0x09eb
+upleftcorner 2540 0x09ec
+lowleftcorner 2541 0x09ed
+crossinglines 2542 0x09ee
+horizlinescan1 2543 0x09ef
+horizlinescan3 2544 0x09f0
+horizlinescan5 2545 0x09f1
+horizlinescan7 2546 0x09f2
+horizlinescan9 2547 0x09f3
+leftt 2548 0x09f4
+rightt 2549 0x09f5
+bott 2550 0x09f6
+topt 2551 0x09f7
+vertbar 2552 0x09f8
+emspace 2721 0x0aa1
+enspace 2722 0x0aa2
+em3space 2723 0x0aa3
+em4space 2724 0x0aa4
+digitspace 2725 0x0aa5
+punctspace 2726 0x0aa6
+thinspace 2727 0x0aa7
+hairspace 2728 0x0aa8
+emdash 2729 0x0aa9
+endash 2730 0x0aaa
+signifblank 2732 0x0aac
+ellipsis 2734 0x0aae
+doubbaselinedot 2735 0x0aaf
+onethird 2736 0x0ab0
+twothirds 2737 0x0ab1
+onefifth 2738 0x0ab2
+twofifths 2739 0x0ab3
+threefifths 2740 0x0ab4
+fourfifths 2741 0x0ab5
+onesixth 2742 0x0ab6
+fivesixths 2743 0x0ab7
+careof 2744 0x0ab8
+figdash 2747 0x0abb
+leftanglebracket 2748 0x0abc
+decimalpoint 2749 0x0abd
+rightanglebracket 2750 0x0abe
+marker 2751 0x0abf
+oneeighth 2755 0x0ac3
+threeeighths 2756 0x0ac4
+fiveeighths 2757 0x0ac5
+seveneighths 2758 0x0ac6
+trademark 2761 0x0ac9
+signaturemark 2762 0x0aca
+trademarkincircle 2763 0x0acb
+leftopentriangle 2764 0x0acc
+rightopentriangle 2765 0x0acd
+emopencircle 2766 0x0ace
+emopenrectangle 2767 0x0acf
+leftsinglequotemark 2768 0x0ad0
+rightsinglequotemark 2769 0x0ad1
+leftdoublequotemark 2770 0x0ad2
+rightdoublequotemark 2771 0x0ad3
+prescription 2772 0x0ad4
+minutes 2774 0x0ad6
+seconds 2775 0x0ad7
+latincross 2777 0x0ad9
+hexagram 2778 0x0ada
+filledrectbullet 2779 0x0adb
+filledlefttribullet 2780 0x0adc
+filledrighttribullet 2781 0x0add
+emfilledcircle 2782 0x0ade
+emfilledrect 2783 0x0adf
+enopencircbullet 2784 0x0ae0
+enopensquarebullet 2785 0x0ae1
+openrectbullet 2786 0x0ae2
+opentribulletup 2787 0x0ae3
+opentribulletdown 2788 0x0ae4
+openstar 2789 0x0ae5
+enfilledcircbullet 2790 0x0ae6
+enfilledsqbullet 2791 0x0ae7
+filledtribulletup 2792 0x0ae8
+filledtribulletdown 2793 0x0ae9
+leftpointer 2794 0x0aea
+rightpointer 2795 0x0aeb
+club 2796 0x0aec
+diamond 2797 0x0aed
+heart 2798 0x0aee
+maltesecross 2800 0x0af0
+dagger 2801 0x0af1
+doubledagger 2802 0x0af2
+checkmark 2803 0x0af3
+ballotcross 2804 0x0af4
+musicalsharp 2805 0x0af5
+musicalflat 2806 0x0af6
+malesymbol 2807 0x0af7
+femalesymbol 2808 0x0af8
+telephone 2809 0x0af9
+telephonerecorder 2810 0x0afa
+phonographcopyright 2811 0x0afb
+caret 2812 0x0afc
+singlelowquotemark 2813 0x0afd
+doublelowquotemark 2814 0x0afe
+cursor 2815 0x0aff
+leftcaret 2979 0x0ba3
+rightcaret 2982 0x0ba6
+downcaret 2984 0x0ba8
+upcaret 2985 0x0ba9
+overbar 3008 0x0bc0
+downtack 3010 0x0bc2
+upshoe 3011 0x0bc3
+downstile 3012 0x0bc4
+underbar 3014 0x0bc6
+jot 3018 0x0bca
+quad 3020 0x0bcc
+uptack 3022 0x0bce
+circle 3023 0x0bcf
+upstile 3027 0x0bd3
+downshoe 3030 0x0bd6
+rightshoe 3032 0x0bd8
+leftshoe 3034 0x0bda
+lefttack 3036 0x0bdc
+righttack 3068 0x0bfc
+hebrew_aleph 3296 0x0ce0
+hebrew_beth 3297 0x0ce1
+hebrew_gimmel 3298 0x0ce2
+hebrew_daleth 3299 0x0ce3
+hebrew_he 3300 0x0ce4
+hebrew_waw 3301 0x0ce5
+hebrew_zayin 3302 0x0ce6
+hebrew_het 3303 0x0ce7
+hebrew_teth 3304 0x0ce8
+hebrew_yod 3305 0x0ce9
+hebrew_finalkaph 3306 0x0cea
+hebrew_kaph 3307 0x0ceb
+hebrew_lamed 3308 0x0cec
+hebrew_finalmem 3309 0x0ced
+hebrew_mem 3310 0x0cee
+hebrew_finalnun 3311 0x0cef
+hebrew_nun 3312 0x0cf0
+hebrew_samekh 3313 0x0cf1
+hebrew_ayin 3314 0x0cf2
+hebrew_finalpe 3315 0x0cf3
+hebrew_pe 3316 0x0cf4
+hebrew_finalzadi 3317 0x0cf5
+hebrew_zadi 3318 0x0cf6
+hebrew_kuf 3319 0x0cf7
+hebrew_resh 3320 0x0cf8
+hebrew_shin 3321 0x0cf9
+hebrew_taf 3322 0x0cfa
+BackSpace 65288 0xff08
+Tab 65289 0xff09
+Linefeed 65290 0xff0a
+Clear 65291 0xff0b
+Return 65293 0xff0d
+Pause 65299 0xff13
+Scroll_Lock 65300 0xff14
+Sys_Req 65301 0xff15
+Escape 65307 0xff1b
+Multi_key 65312 0xff20
+Kanji 65313 0xff21
+Home 65360 0xff50
+Left 65361 0xff51
+Up 65362 0xff52
+Right 65363 0xff53
+Down 65364 0xff54
+Prior 65365 0xff55
+Next 65366 0xff56
+End 65367 0xff57
+Begin 65368 0xff58
+Win_L 65371 0xff5b
+Win_R 65372 0xff5c
+.CE
+.CS
+App 65373 0xff5d
+Select 65376 0xff60
+Print 65377 0xff61
+Execute 65378 0xff62
+Insert 65379 0xff63
+Undo 65381 0xff65
+Redo 65382 0xff66
+Menu 65383 0xff67
+Find 65384 0xff68
+Cancel 65385 0xff69
+Help 65386 0xff6a
+Break 65387 0xff6b
+Hebrew_switch 65406 0xff7e
+Num_Lock 65407 0xff7f
+KP_Space 65408 0xff80
+KP_Tab 65417 0xff89
+KP_Enter 65421 0xff8d
+KP_F1 65425 0xff91
+KP_F2 65426 0xff92
+KP_F3 65427 0xff93
+KP_F4 65428 0xff94
+KP_Multiply 65450 0xffaa
+KP_Add 65451 0xffab
+KP_Separator 65452 0xffac
+KP_Subtract 65453 0xffad
+KP_Decimal 65454 0xffae
+KP_Divide 65455 0xffaf
+KP_0 65456 0xffb0
+KP_1 65457 0xffb1
+KP_2 65458 0xffb2
+KP_3 65459 0xffb3
+KP_4 65460 0xffb4
+KP_5 65461 0xffb5
+KP_6 65462 0xffb6
+KP_7 65463 0xffb7
+KP_8 65464 0xffb8
+KP_9 65465 0xffb9
+KP_Equal 65469 0xffbd
+F1 65470 0xffbe
+F2 65471 0xffbf
+F3 65472 0xffc0
+F4 65473 0xffc1
+F5 65474 0xffc2
+F6 65475 0xffc3
+F7 65476 0xffc4
+F8 65477 0xffc5
+F9 65478 0xffc6
+F10 65479 0xffc7
+L1 65480 0xffc8
+L2 65481 0xffc9
+L3 65482 0xffca
+L4 65483 0xffcb
+L5 65484 0xffcc
+L6 65485 0xffcd
+L7 65486 0xffce
+L8 65487 0xffcf
+L9 65488 0xffd0
+L10 65489 0xffd1
+R1 65490 0xffd2
+R2 65491 0xffd3
+R3 65492 0xffd4
+R4 65493 0xffd5
+R5 65494 0xffd6
+R6 65495 0xffd7
+R7 65496 0xffd8
+R8 65497 0xffd9
+R9 65498 0xffda
+R10 65499 0xffdb
+R11 65500 0xffdc
+R12 65501 0xffdd
+F33 65502 0xffde
+R14 65503 0xffdf
+R15 65504 0xffe0
+Shift_L 65505 0xffe1
+Shift_R 65506 0xffe2
+Control_L 65507 0xffe3
+Control_R 65508 0xffe4
+Caps_Lock 65509 0xffe5
+Shift_Lock 65510 0xffe6
+Meta_L 65511 0xffe7
+Meta_R 65512 0xffe8
+Alt_L 65513 0xffe9
+Alt_R 65514 0xffea
+Super_L 65515 0xffeb
+Super_R 65516 0xffec
+Hyper_L 65517 0xffed
+Hyper_R 65518 0xffee
+Delete 65535 0xffff
+XF86AudioLowerVolume 269025041 0x1008FF11
+XF86AudioMute 269025042 0x1008FF12
+XF86AudioRaiseVolume 269025043 0x1008FF13
+XF86AudioPlay 269025044 0x1008FF14
+XF86AudioStop 269025045 0x1008FF15
+XF86AudioPrev 269025046 0x1008FF16
+XF86AudioNext 269025047 0x1008FF17
+.CE
+.SH "SEE ALSO"
+bind(n), event(n)
+.SH KEYWORDS
+bind, binding, event, keysym
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/label.n b/tk8.6/doc/label.n
new file mode 100644
index 0000000..f2ba88c
--- /dev/null
+++ b/tk8.6/doc/label.n
@@ -0,0 +1,130 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH label n 4.0 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+label \- Create and manipulate 'label' non-interactive text or image widgets
+.SH SYNOPSIS
+\fBlabel\fR \fIpathName \fR?\fIoptions\fR?
+.SO
+\-activebackground \-disabledforeground \-padx
+\-activeforeground \-font \-pady
+\-anchor \-foreground \-relief
+\-background \-highlightbackground \-takefocus
+\-bitmap \-highlightcolor \-text
+\-borderwidth \-highlightthickness \-textvariable
+\-compound \-image \-underline
+\-cursor \-justify \-wraplength
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-height height Height
+Specifies a desired height for the label.
+If an image or bitmap is being displayed in the label then the value is in
+screen units (i.e. any of the forms acceptable to \fBTk_GetPixels\fR);
+for text it is in lines of text.
+If this option is not specified, the label's desired height is computed
+from the size of the image or bitmap or text being displayed in it.
+.OP \-state state State
+Specifies one of three states for the label: \fBnormal\fR, \fBactive\fR,
+or \fBdisabled\fR. In normal state the button is displayed using the
+\fB\-foreground\fR and \fB\-background\fR options. In active state
+the label is displayed using the \fB\-activeforeground\fR and
+\fB\-activebackground\fR options. In the disabled state the
+\fB\-disabledforeground\fR and \fB\-background\fR options determine how
+the button is displayed.
+.OP \-width width Width
+Specifies a desired width for the label.
+If an image or bitmap is being displayed in the label then the value is in
+screen units (i.e. any of the forms acceptable to \fBTk_GetPixels\fR);
+for text it is in characters.
+If this option is not specified, the label's desired width is computed
+from the size of the image or bitmap or text being displayed in it.
+.BE
+.SH DESCRIPTION
+.PP
+The \fBlabel\fR command creates a new window (given by the
+\fIpathName\fR argument) and makes it into a label widget.
+Additional
+options, described above, may be specified on the command line
+or in the option database
+to configure aspects of the label such as its colors, font,
+text, and initial relief. The \fBlabel\fR command returns its
+\fIpathName\fR argument. At the time this command is invoked,
+there must not exist a window named \fIpathName\fR, but
+\fIpathName\fR's parent must exist.
+.PP
+A label is a widget that displays a textual string, bitmap or image.
+If text is displayed, it must all be in a single font, but it
+can occupy multiple lines on the screen (if it contains newlines
+or if wrapping occurs because of the \fB\-wraplength\fR option) and
+one of the characters may optionally be underlined using the
+\fB\-underline\fR option.
+The label can be manipulated in a few simple ways, such as
+changing its relief or text, using the commands described below.
+.SH "WIDGET COMMAND"
+.PP
+The \fBlabel\fR command creates a new Tcl command whose
+name is \fIpathName\fR. This
+command may be used to invoke various
+operations on the widget. It has the following general form:
+.CS
+\fIpathName option \fR?\fIarg arg ...\fR?
+.CE
+\fIOption\fR and the \fIarg\fRs
+determine the exact behavior of the command. The following
+commands are possible for label widgets:
+.TP
+\fIpathName \fBcget\fR \fIoption\fR
+Returns the current value of the configuration option given
+by \fIoption\fR.
+\fIOption\fR may have any of the values accepted by the \fBlabel\fR
+command.
+.TP
+\fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
+Query or modify the configuration options of the widget.
+If no \fIoption\fR is specified, returns a list describing all of
+the available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for
+information on the format of this list). If \fIoption\fR is specified
+with no \fIvalue\fR, then the command returns a list describing the
+one named option (this list will be identical to the corresponding
+sublist of the value returned if no \fIoption\fR is specified). If
+one or more \fIoption\-value\fR pairs are specified, then the command
+modifies the given widget option(s) to have the given value(s); in
+this case the command returns an empty string.
+\fIOption\fR may have any of the values accepted by the \fBlabel\fR
+command.
+.SH BINDINGS
+.PP
+When a new label is created, it has no default event bindings:
+labels are not intended to be interactive.
+.SH EXAMPLE
+.PP
+.CS
+# Make the widgets
+\fBlabel\fR .t \-text "This widget is at the top" \-bg red
+\fBlabel\fR .b \-text "This widget is at the bottom" \-bg green
+\fBlabel\fR .l \-text "Left\enHand\enSide"
+\fBlabel\fR .r \-text "Right\enHand\enSide"
+text .mid
+\&.mid insert end "This layout is like Java's BorderLayout"
+# Lay them out
+pack .t \-side top \-fill x
+pack .b \-side bottom \-fill x
+pack .l \-side left \-fill y
+pack .r \-side right \-fill y
+pack .mid \-expand 1 \-fill both
+.CE
+.SH "SEE ALSO"
+labelframe(n), button(n), ttk::label(n)
+.SH KEYWORDS
+label, widget
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/labelframe.n b/tk8.6/doc/labelframe.n
new file mode 100644
index 0000000..857208e
--- /dev/null
+++ b/tk8.6/doc/labelframe.n
@@ -0,0 +1,175 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH labelframe n 8.4 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+labelframe \- Create and manipulate 'labelframe' labelled container widgets
+.SH SYNOPSIS
+\fBlabelframe\fR \fIpathName\fR ?\fIoptions\fR?
+.SO
+\-borderwidth \-highlightbackground \-pady
+\-cursor \-highlightcolor \-relief
+\-font \-highlightthickness \-takefocus
+\-foreground \-padx \-text
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-background background Background
+This option is the same as the standard \fB\-background\fR option
+except that its value may also be specified as an empty string.
+In this case, the widget will display no background or border, and
+no colors will be consumed from its colormap for its background
+and border.
+.OP \-class class Class
+Specifies a class for the window.
+This class will be used when querying the option database for
+the window's other options, and it will also be used later for
+other purposes such as bindings.
+The \fB\-class\fR option may not be changed with the \fBconfigure\fR
+widget command.
+.OP \-colormap colormap Colormap
+Specifies a colormap to use for the window.
+The value may be either \fBnew\fR, in which case a new colormap is
+created for the window and its children, or the name of another
+window (which must be on the same screen and have the same visual
+as \fIpathName\fR), in which case the new window will use the colormap
+from the specified window.
+If the \fB\-colormap\fR option is not specified, the new window
+uses the same colormap as its parent.
+This option may not be changed with the \fBconfigure\fR
+widget command.
+.OP \-height height Height
+Specifies the desired height for the window in any of the forms
+acceptable to \fBTk_GetPixels\fR.
+If this option is less than or equal to zero then the window will
+not request any size at all.
+.OP \-labelanchor labelAnchor LabelAnchor
+Specifies where to place the label. A label is only displayed if the
+\fB\-text\fR option is not the empty string.
+Valid values for this option are (listing them clockwise)
+\fBnw\fR, \fBn\fR, \fBne\fR, \fBen\fR, \fBe\fR, \fBes\fR,
+\fBse\fR, \fBs\fR,\fBsw\fR, \fBws\fR, \fBw\fR and \fBwn\fR.
+The default value is \fBnw\fR.
+.OP \-labelwidget labelWidget LabelWidget
+Specifies a widget to use as label. This overrides any \fB\-text\fR
+option. The widget must exist before being used as \fB\-labelwidget\fR
+and if it is not a descendant of this window, it will be raised
+above it in the stacking order.
+.OP \-visual visual Visual
+Specifies visual information for the new window in any of the
+forms accepted by \fBTk_GetVisual\fR.
+If this option is not specified, the new window will use the same
+visual as its parent.
+The \fB\-visual\fR option may not be modified with the \fBconfigure\fR
+widget command.
+.OP \-width width Width
+Specifies the desired width for the window in any of the forms
+acceptable to \fBTk_GetPixels\fR.
+If this option is less than or equal to zero then the window will
+not request any size at all.
+.BE
+.SH DESCRIPTION
+.PP
+The \fBlabelframe\fR command creates a new window (given by the
+\fIpathName\fR argument) and makes it into a labelframe widget.
+Additional
+options, described above, may be specified on the command line
+or in the option database
+to configure aspects of the labelframe such as its background color
+and relief. The \fBlabelframe\fR command returns the
+path name of the new window.
+.PP
+A labelframe is a simple widget. Its primary purpose is to act as a
+spacer or container for complex window layouts. It has the features
+of a \fBframe\fR plus the ability to display a label.
+.SH "WIDGET COMMAND"
+.PP
+The \fBlabelframe\fR command creates a new Tcl command whose
+name is the same as the path name of the labelframe's window. This
+command may be used to invoke various
+operations on the widget. It has the following general form:
+.CS
+\fIpathName option \fR?\fIarg arg ...\fR?
+.CE
+\fIPathName\fR is the name of the command, which is the same as
+the labelframe widget's path name. \fIOption\fR and the \fIarg\fRs
+determine the exact behavior of the command. The following
+commands are possible for frame widgets:
+.TP
+\fIpathName \fBcget\fR \fIoption\fR
+Returns the current value of the configuration option given
+by \fIoption\fR.
+\fIOption\fR may have any of the values accepted by the \fBlabelframe\fR
+command.
+.TP
+\fIpathName \fBconfigure\fR ?\fIoption\fR? \fI?value option value ...\fR?
+Query or modify the configuration options of the widget.
+If no \fIoption\fR is specified, returns a list describing all of
+the available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for
+information on the format of this list). If \fIoption\fR is specified
+with no \fIvalue\fR, then the command returns a list describing the
+one named option (this list will be identical to the corresponding
+sublist of the value returned if no \fIoption\fR is specified). If
+one or more \fIoption\-value\fR pairs are specified, then the command
+modifies the given widget option(s) to have the given value(s); in
+this case the command returns an empty string.
+\fIOption\fR may have any of the values accepted by the \fBlabelframe\fR
+command.
+.SH BINDINGS
+.PP
+When a new labelframe is created, it has no default event bindings:
+labelframes are not intended to be interactive.
+.SH EXAMPLE
+.PP
+This shows how to build part of a GUI for a hamburger vendor. The
+\fBlabelframe\fR widgets are used to organize the available choices by
+the kinds of things that the choices are being made over.
+.PP
+.CS
+grid [\fBlabelframe\fR .burger \-text "Burger"] \e
+ [\fBlabelframe\fR .bun \-text "Bun"] \-sticky news
+grid [\fBlabelframe\fR .cheese \-text "Cheese Option"] \e
+ [\fBlabelframe\fR .pickle \-text "Pickle Option"] \-sticky news
+foreach {type name val} {
+ burger Beef beef
+ burger Lamb lamb
+ burger Vegetarian beans
+
+ bun Plain white
+ bun Sesame seeds
+ bun Wholemeal brown
+
+ cheese None none
+ cheese Cheddar cheddar
+ cheese Edam edam
+ cheese Brie brie
+ cheese Gruy\eu00e8re gruyere
+ cheese "Monterey Jack" jack
+
+ pickle None none
+ pickle Gherkins gherkins
+ pickle Onions onion
+ pickle Chili chili
+} {
+ set w [radiobutton .$type.$val \-text $name \-anchor w \e
+ \-variable $type \-value $val]
+ pack $w \-side top \-fill x
+}
+set burger beef
+set bun white
+set cheese none
+set pickle none
+.CE
+.SH "SEE ALSO"
+frame(n), label(n), ttk::labelframe(n)
+.SH KEYWORDS
+labelframe, widget
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/listbox.n b/tk8.6/doc/listbox.n
new file mode 100644
index 0000000..66b75b9
--- /dev/null
+++ b/tk8.6/doc/listbox.n
@@ -0,0 +1,582 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH listbox n 8.4 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+listbox \- Create and manipulate 'listbox' item list widgets
+.SH SYNOPSIS
+\fBlistbox\fR \fIpathName \fR?\fIoptions\fR?
+.SO
+\-background \-borderwidth \-cursor
+\-disabledforeground \-exportselection \-font
+\-foreground \-highlightbackground \-highlightcolor
+\-highlightthickness \-justify \-relief
+\-selectbackground \-selectborderwidth \-selectforeground
+\-setgrid \-takefocus \-xscrollcommand
+\-yscrollcommand
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-activestyle activeStyle ActiveStyle
+Specifies the style in which to draw the active element. This must be
+one of \fBdotbox\fR (show a focus ring around the active element),
+\fBnone\fR (no special indication of active element) or
+\fBunderline\fR (underline the active element).
+The default is \fBunderline\fR on Windows, and \fBdotbox\fR elsewhere.
+.OP \-height height Height
+Specifies the desired height for the window, in lines.
+If zero or less, then the desired height for the window is made just
+large enough to hold all the elements in the listbox.
+.OP \-listvariable listVariable Variable
+Specifies the name of a global variable. The value of the variable is a list to
+be displayed inside the widget; if the variable value changes then the
+widget will automatically update itself to reflect the new value. Attempts
+to assign a variable with an invalid list value to \fB\-listvariable\fR
+will cause an error. Attempts to unset a variable in use as a
+\fB\-listvariable\fR will fail but will not generate an error.
+.OP \-selectmode selectMode SelectMode
+Specifies one of several styles for manipulating the selection.
+The value of the option may be arbitrary, but the default bindings
+expect it to be either \fBsingle\fR, \fBbrowse\fR, \fBmultiple\fR,
+or \fBextended\fR; the default value is \fBbrowse\fR.
+.OP \-state state State
+Specifies one of two states for the listbox: \fBnormal\fR or \fBdisabled\fR.
+If the listbox is disabled then items may not be inserted or deleted,
+items are drawn in the \fB\-disabledforeground\fR color, and selection
+cannot be modified and is not shown (though selection information is retained).
+.OP \-width width Width
+Specifies the desired width for the window in characters.
+If the font does not have a uniform width then the width of the character
+.QW 0
+is used in translating from character units to screen units.
+If zero or less, then the desired width for the window is made just
+large enough to hold all the elements in the listbox.
+.BE
+.SH DESCRIPTION
+.PP
+The \fBlistbox\fR command creates a new window (given by the
+\fIpathName\fR argument) and makes it into a listbox widget.
+Additional
+options, described above, may be specified on the command line
+or in the option database
+to configure aspects of the listbox such as its colors, font,
+text, and relief. The \fBlistbox\fR command returns its
+\fIpathName\fR argument. At the time this command is invoked,
+there must not exist a window named \fIpathName\fR, but
+\fIpathName\fR's parent must exist.
+.PP
+A listbox is a widget that displays a list of strings, one per line.
+When first created, a new listbox has no elements.
+Elements may be added or deleted using widget commands described
+below. In addition, one or more elements may be selected as described
+below.
+If a listbox is exporting its selection (see \fB\-exportselection\fR
+option), then it will observe the standard X11 protocols
+for handling the selection.
+Listbox selections are available as type \fBSTRING\fR;
+the value of the selection will be the text of the selected elements, with
+newlines separating the elements.
+.PP
+It is not necessary for all the elements to be
+displayed in the listbox window at once; commands described below
+may be used to change the view in the window. Listboxes allow
+scrolling in both directions using the standard \fB\-xscrollcommand\fR
+and \fB\-yscrollcommand\fR options.
+They also support scanning, as described below.
+.SH "INDICES"
+.PP
+Many of the widget commands for listboxes take one or more indices
+as arguments.
+An index specifies a particular element of the listbox, in any of
+the following ways:
+.TP 12
+\fInumber\fR
+.
+Specifies the element as a numerical index, where 0 corresponds
+to the first element in the listbox.
+.TP 12
+\fBactive\fR
+.
+Indicates the element that has the location cursor. This element
+will be displayed as specified by \fB\-activestyle\fR when the listbox
+has the keyboard focus, and it is specified with the \fBactivate\fR
+widget command.
+.TP 12
+\fBanchor\fR
+.
+Indicates the anchor point for the selection, which is set with the
+\fBselection anchor\fR widget command.
+.TP 12
+\fBend\fR
+.
+Indicates the end of the listbox.
+For most commands this refers to the last element in the listbox,
+but for a few commands such as \fBindex\fR and \fBinsert\fR
+it refers to the element just after the last one.
+.TP 12
+\fB@\fIx\fB,\fIy\fR
+Indicates the element that covers the point in the listbox window
+specified by \fIx\fR and \fIy\fR (in pixel coordinates). If no
+element covers that point, then the closest element to that
+point is used.
+.LP
+In the widget command descriptions below, arguments named \fIindex\fR,
+\fIfirst\fR, and \fIlast\fR always contain text indices in one of
+the above forms.
+.SH "WIDGET COMMAND"
+.PP
+The \fBlistbox\fR command creates a new Tcl command whose
+name is \fIpathName\fR. This
+command may be used to invoke various
+operations on the widget. It has the following general form:
+.CS
+\fIpathName option \fR?\fIarg arg ...\fR?
+.CE
+\fIOption\fR and the \fIarg\fRs
+determine the exact behavior of the command. The following
+commands are possible for listbox widgets:
+.TP
+\fIpathName \fBactivate\fR \fIindex\fR
+.
+Sets the active element to the one indicated by \fIindex\fR.
+If \fIindex\fR is outside the range of elements in the listbox
+then the closest element is activated.
+The active element is drawn as specified by \fB\-activestyle\fR when the
+widget has the input focus, and its index may be retrieved with the
+index \fBactive\fR.
+.TP
+\fIpathName \fBbbox\fR \fIindex\fR
+.
+Returns a list of four numbers describing the bounding box of
+the text in the element given by \fIindex\fR.
+The first two elements of the list give the x and y coordinates
+of the upper-left corner of the screen area covered by the text
+(specified in pixels relative to the widget) and the last two
+elements give the width and height of the area, in pixels.
+If no part of the element given by \fIindex\fR is visible on the
+screen,
+or if \fIindex\fR refers to a non-existent element,
+then the result is an empty string; if the element is
+partially visible, the result gives the full area of the element,
+including any parts that are not visible.
+.TP
+\fIpathName \fBcget\fR \fIoption\fR
+.
+Returns the current value of the configuration option given
+by \fIoption\fR.
+\fIOption\fR may have any of the values accepted by the \fBlistbox\fR
+command.
+.TP
+\fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
+.
+Query or modify the configuration options of the widget.
+If no \fIoption\fR is specified, returns a list describing all of
+the available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for
+information on the format of this list). If \fIoption\fR is specified
+with no \fIvalue\fR, then the command returns a list describing the
+one named option (this list will be identical to the corresponding
+sublist of the value returned if no \fIoption\fR is specified). If
+one or more \fIoption\-value\fR pairs are specified, then the command
+modifies the given widget option(s) to have the given value(s); in
+this case the command returns an empty string.
+\fIOption\fR may have any of the values accepted by the \fBlistbox\fR
+command.
+.TP
+\fIpathName \fBcurselection\fR
+.
+Returns a list containing the numerical indices of
+all of the elements in the listbox that are currently selected.
+If there are no elements selected in the listbox then an empty
+string is returned.
+.TP
+\fIpathName \fBdelete \fIfirst \fR?\fIlast\fR?
+.
+Deletes one or more elements of the listbox. \fIFirst\fR and \fIlast\fR
+are indices specifying the first and last elements in the range
+to delete. If \fIlast\fR is not specified it defaults to
+\fIfirst\fR, i.e. a single element is deleted.
+.TP
+\fIpathName \fBget \fIfirst\fR ?\fIlast\fR?
+.
+If \fIlast\fR is omitted, returns the contents of the listbox
+element indicated by \fIfirst\fR,
+or an empty string if \fIfirst\fR refers to a non-existent element.
+If \fIlast\fR is specified, the command returns a list whose elements
+are all of the listbox elements between \fIfirst\fR and \fIlast\fR,
+inclusive.
+Both \fIfirst\fR and \fIlast\fR may have any of the standard
+forms for indices.
+.TP
+\fIpathName \fBindex \fIindex\fR
+.
+Returns the integer index value that corresponds to \fIindex\fR.
+If \fIindex\fR is \fBend\fR the return value is a count of the number
+of elements in the listbox (not the index of the last element).
+.TP
+\fIpathName \fBinsert \fIindex \fR?\fIelement element ...\fR?
+.
+Inserts zero or more new elements in the list just before the
+element given by \fIindex\fR. If \fIindex\fR is specified as
+\fBend\fR then the new elements are added to the end of the
+list. Returns an empty string.
+.TP
+\fIpathName \fBitemcget \fIindex option\fR
+.
+Returns the current value of the item configuration option given
+by \fIoption\fR. \fIOption\fR may have any of the values accepted
+by the \fBitemconfigure\fR command.
+.TP
+\fIpathName \fBitemconfigure \fIindex\fR ?\fIoption\fR? ?\fIvalue\fR? ?\fIoption value ...\fR?
+.
+Query or modify the configuration options of an item in the listbox.
+If no \fIoption\fR is specified, returns a list describing all of
+the available options for the item (see \fBTk_ConfigureInfo\fR for
+information on the format of this list). If \fIoption\fR is specified
+with no \fIvalue\fR, then the command returns a list describing the
+one named option (this list will be identical to the corresponding
+sublist of the value returned if no \fIoption\fR is specified). If
+one or more \fIoption\-value\fR pairs are specified, then the command
+modifies the given widget option(s) to have the given value(s); in
+this case the command returns an empty string. The following options
+are currently supported for items:
+.RS
+.TP
+\fB\-background \fIcolor\fR
+.
+\fIColor\fR specifies the background color to use when displaying the
+item. It may have any of the forms accepted by \fBTk_GetColor\fR.
+.TP
+\fB\-foreground \fIcolor\fR
+.
+\fIColor\fR specifies the foreground color to use when displaying the
+item. It may have any of the forms accepted by \fBTk_GetColor\fR.
+.TP
+\fB\-selectbackground \fIcolor\fR
+.
+\fIcolor\fR specifies the background color to use when displaying the
+item while it is selected. It may have any of the forms accepted by
+\fBTk_GetColor\fR.
+.TP
+\fB\-selectforeground \fIcolor\fR
+.
+\fIcolor\fR specifies the foreground color to use when displaying the
+item while it is selected. It may have any of the forms accepted by
+\fBTk_GetColor\fR.
+.RE
+.TP
+\fIpathName \fBnearest \fIy\fR
+.
+Given a y-coordinate within the listbox window, this command returns
+the index of the (visible) listbox element nearest to that y-coordinate.
+.TP
+\fIpathName \fBscan\fR \fIoption args\fR
+.
+This command is used to implement scanning on listboxes. It has
+two forms, depending on \fIoption\fR:
+.RS
+.TP
+\fIpathName \fBscan mark \fIx y\fR
+.
+Records \fIx\fR and \fIy\fR and the current view in the listbox
+window; used in conjunction with later \fBscan dragto\fR commands.
+Typically this command is associated with a mouse button press in
+the widget. It returns an empty string.
+.TP
+\fIpathName \fBscan dragto \fIx y\fR.
+.
+This command computes the difference between its \fIx\fR and \fIy\fR
+arguments and the \fIx\fR and \fIy\fR arguments to the last
+\fBscan mark\fR command for the widget.
+It then adjusts the view by 10 times the
+difference in coordinates. This command is typically associated
+with mouse motion events in the widget, to produce the effect of
+dragging the list at high speed through the window. The return
+value is an empty string.
+.RE
+.TP
+\fIpathName \fBsee \fIindex\fR
+.
+Adjust the view in the listbox so that the element given by \fIindex\fR
+is visible.
+If the element is already visible then the command has no effect;
+if the element is near one edge of the window then the listbox
+scrolls to bring the element into view at the edge; otherwise
+the listbox scrolls to center the element.
+.TP
+\fIpathName \fBselection \fIoption arg\fR
+.
+This command is used to adjust the selection within a listbox. It
+has several forms, depending on \fIoption\fR:
+.RS
+.TP
+\fIpathName \fBselection anchor \fIindex\fR
+.
+Sets the selection anchor to the element given by \fIindex\fR.
+If \fIindex\fR refers to a non-existent element, then the closest
+element is used.
+The selection anchor is the end of the selection that is fixed
+while dragging out a selection with the mouse.
+The index \fBanchor\fR may be used to refer to the anchor
+element.
+.TP
+\fIpathName \fBselection clear \fIfirst \fR?\fIlast\fR?
+.
+If any of the elements between \fIfirst\fR and \fIlast\fR
+(inclusive) are selected, they are deselected.
+The selection state is not changed for elements outside
+this range.
+.TP
+\fIpathName \fBselection includes \fIindex\fR
+.
+Returns 1 if the element indicated by \fIindex\fR is currently
+selected, 0 if it is not.
+.TP
+\fIpathName \fBselection set \fIfirst \fR?\fIlast\fR?
+.
+Selects all of the elements in the range between
+\fIfirst\fR and \fIlast\fR, inclusive, without affecting
+the selection state of elements outside that range.
+.RE
+.TP
+\fIpathName \fBsize\fR
+.
+Returns a decimal string indicating the total number of elements
+in the listbox.
+.TP
+\fIpathName \fBxview \fR?\fIargs\fR
+.
+This command is used to query and change the horizontal position of the
+information in the widget's window. It can take any of the following
+forms:
+.RS
+.TP
+\fIpathName \fBxview\fR
+.
+Returns a list containing two elements.
+Each element is a real fraction between 0 and 1; together they describe
+the horizontal span that is visible in the window.
+For example, if the first element is .2 and the second element is .6,
+20% of the listbox's text is off-screen to the left, the middle 40% is visible
+in the window, and 40% of the text is off-screen to the right.
+These are the same values passed to scrollbars via the \fB\-xscrollcommand\fR
+option.
+.TP
+\fIpathName \fBxview \fIindex\fR
+.
+Adjusts the view in the window so that the character position given by
+\fIindex\fR is displayed at the left edge of the window.
+Character positions are defined by the width of the character \fB0\fR.
+.TP
+\fIpathName \fBxview moveto\fI fraction\fR
+.
+Adjusts the view in the window so that \fIfraction\fR of the
+total width of the listbox text is off-screen to the left.
+\fIfraction\fR must be a fraction between 0 and 1.
+.TP
+\fIpathName \fBxview scroll \fInumber what\fR
+.
+This command shifts the view in the window left or right according to
+\fInumber\fR and \fIwhat\fR.
+\fINumber\fR must be an integer.
+\fIWhat\fR must be either \fBunits\fR or \fBpages\fR or an abbreviation
+of one of these.
+If \fIwhat\fR is \fBunits\fR, the view adjusts left or right by
+\fInumber\fR character units (the width of the \fB0\fR character)
+on the display; if it is \fBpages\fR then the view adjusts by
+\fInumber\fR screenfuls.
+If \fInumber\fR is negative then characters farther to the left
+become visible; if it is positive then characters farther to the right
+become visible.
+.RE
+.TP
+\fIpathName \fByview \fR?\fIargs\fR?
+.
+This command is used to query and change the vertical position of the
+text in the widget's window.
+It can take any of the following forms:
+.RS
+.TP
+\fIpathName \fByview\fR
+Returns a list containing two elements, both of which are real fractions
+between 0 and 1.
+The first element gives the position of the listbox element at the
+top of the window, relative to the listbox as a whole (0.5 means
+it is halfway through the listbox, for example).
+The second element gives the position of the listbox element just after
+the last one in the window, relative to the listbox as a whole.
+These are the same values passed to scrollbars via the \fB\-yscrollcommand\fR
+option.
+.TP
+\fIpathName \fByview \fIindex\fR
+.
+Adjusts the view in the window so that the element given by
+\fIindex\fR is displayed at the top of the window.
+.TP
+\fIpathName \fByview moveto\fI fraction\fR
+.
+Adjusts the view in the window so that the element given by \fIfraction\fR
+appears at the top of the window.
+\fIFraction\fR is a fraction between 0 and 1; 0 indicates the first
+element in the listbox, 0.33 indicates the element one-third the
+way through the listbox, and so on.
+.TP
+\fIpathName \fByview scroll \fInumber what\fR
+.
+This command adjusts the view in the window up or down according to
+\fInumber\fR and \fIwhat\fR.
+\fINumber\fR must be an integer.
+\fIWhat\fR must be either \fBunits\fR or \fBpages\fR.
+If \fIwhat\fR is \fBunits\fR, the view adjusts up or down by
+\fInumber\fR lines; if it is \fBpages\fR then
+the view adjusts by \fInumber\fR screenfuls.
+If \fInumber\fR is negative then earlier elements
+become visible; if it is positive then later elements
+become visible.
+.RE
+.SH "DEFAULT BINDINGS"
+.PP
+Tk automatically creates class bindings for listboxes that give them
+Motif-like behavior. Much of the behavior of a listbox is determined
+by its \fB\-selectmode\fR option, which selects one of four ways
+of dealing with the selection.
+.PP
+If the selection mode is \fBsingle\fR or \fBbrowse\fR, at most one
+element can be selected in the listbox at once.
+In both modes, clicking button 1 on an element selects
+it and deselects any other selected item.
+In \fBbrowse\fR mode it is also possible to drag the selection
+with button 1.
+On button 1, the listbox will also take focus if it has a \fBnormal\fR
+state.
+.PP
+If the selection mode is \fBmultiple\fR or \fBextended\fR,
+any number of elements may be selected at once, including discontiguous
+ranges. In \fBmultiple\fR mode, clicking button 1 on an element
+toggles its selection state without affecting any other elements.
+In \fBextended\fR mode, pressing button 1 on an element selects
+it, deselects everything else, and sets the anchor to the element
+under the mouse; dragging the mouse with button 1
+down extends the selection to include all the elements between
+the anchor and the element under the mouse, inclusive.
+.PP
+Most people will probably want to use \fBbrowse\fR mode for
+single selections and \fBextended\fR mode for multiple selections;
+the other modes appear to be useful only in special situations.
+.PP
+Any time the set of selected item(s) in the listbox is updated by the
+user through the keyboard or mouse, the virtual event
+\fB<<ListboxSelect>>\fR will be generated. This virtual event will not
+be generated when adjusting the selection with the \fIpathName
+\fBselection\fR command. It is easiest to bind to this event to be
+made aware of any user changes to listbox selection.
+.PP
+In addition to the above behavior, the following additional behavior
+is defined by the default bindings:
+.IP [1]
+In \fBextended\fR mode, the selected range can be adjusted by pressing
+button 1 with the Shift key down: this modifies the selection to
+consist of the elements between the anchor and the element under
+the mouse, inclusive.
+The un-anchored end of this new selection can also be dragged with
+the button down.
+.IP [2]
+In \fBextended\fR mode, pressing button 1 with the Control key down
+starts a toggle operation: the anchor is set to the element under
+the mouse, and its selection state is reversed. The selection state
+of other elements is not changed.
+If the mouse is dragged with button 1 down, then the selection state
+of all elements between the anchor and the element under the mouse
+is set to match that of the anchor element; the selection state of
+all other elements remains what it was before the toggle operation
+began.
+.IP [3]
+If the mouse leaves the listbox window with button 1 down, the window
+scrolls away from the mouse, making information visible that used
+to be off-screen on the side of the mouse.
+The scrolling continues until the mouse re-enters the window, the
+button is released, or the end of the listbox is reached.
+.IP [4]
+Mouse button 2 may be used for scanning.
+If it is pressed and dragged over the listbox, the contents of
+the listbox drag at high speed in the direction the mouse moves.
+.IP [5]
+If the Up or Down key is pressed, the location cursor (active
+element) moves up or down one element.
+If the selection mode is \fBbrowse\fR or \fBextended\fR then the
+new active element is also selected and all other elements are
+deselected.
+In \fBextended\fR mode the new active element becomes the
+selection anchor.
+.IP [6]
+In \fBextended\fR mode, Shift-Up and Shift-Down move the location
+cursor (active element) up or down one element and also extend
+the selection to that element in a fashion similar to dragging
+with mouse button 1.
+.IP [7]
+The Left and Right keys scroll the listbox view left and right
+by the width of the character \fB0\fR.
+Control-Left and Control-Right scroll the listbox view left and
+right by the width of the window.
+Control-Prior and Control-Next also scroll left and right by
+the width of the window.
+.IP [8]
+The Prior and Next keys scroll the listbox view up and down
+by one page (the height of the window).
+.IP [9]
+The Home and End keys scroll the listbox horizontally to
+the left and right edges, respectively.
+.IP [10]
+Control-Home sets the location cursor to the first element in
+the listbox, selects that element, and deselects everything else
+in the listbox.
+.IP [11]
+Control-End sets the location cursor to the last element in
+the listbox, selects that element, and deselects everything else
+in the listbox.
+.IP [12]
+In \fBextended\fR mode, Control-Shift-Home extends the selection
+to the first element in the listbox and Control-Shift-End extends
+the selection to the last element.
+.IP [13]
+In \fBmultiple\fR mode, Control-Shift-Home moves the location cursor
+to the first element in the listbox and Control-Shift-End moves
+the location cursor to the last element.
+.IP [14]
+The space and Select keys make a selection at the location cursor
+(active element) just as if mouse button 1 had been pressed over
+this element.
+.IP [15]
+In \fBextended\fR mode, Control-Shift-space and Shift-Select
+extend the selection to the active element just as if button 1
+had been pressed with the Shift key down.
+.IP [16]
+In \fBextended\fR mode, the Escape key cancels the most recent
+selection and restores all the elements in the selected range
+to their previous selection state.
+.IP [17]
+Control-slash selects everything in the widget, except in
+\fBsingle\fR and \fBbrowse\fR modes, in which case it selects
+the active element and deselects everything else.
+.IP [18]
+Control-backslash deselects everything in the widget, except in
+\fBbrowse\fR mode where it has no effect.
+.IP [19]
+The F16 key (labelled Copy on many Sun workstations) or Meta-w
+copies the selection in the widget to the clipboard, if there is
+a selection.
+.PP
+The behavior of listboxes can be changed by defining new bindings for
+individual widgets or by redefining the class bindings.
+.SH "SEE ALSO"
+ttk::treeview(n)
+.SH KEYWORDS
+listbox, widget
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/loadTk.n b/tk8.6/doc/loadTk.n
new file mode 100644
index 0000000..3673e98
--- /dev/null
+++ b/tk8.6/doc/loadTk.n
@@ -0,0 +1,69 @@
+'\"
+'\" 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.
+'\"
+.TH "Safe Tk" n 8.0 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+safe::loadTk \- Load Tk into a safe interpreter.
+.SH SYNOPSIS
+\fBsafe::loadTk \fIslave\fR ?\fB\-use\fR \fIwindowId\fR? ?\fB\-display\fR \fIdisplayName\fR?
+.BE
+.SH DESCRIPTION
+.PP
+Safe Tk is based on Safe Tcl, which provides a mechanism that allows
+restricted and mediated access to auto-loading and packages for safe
+interpreters. Safe Tk adds the ability to configure the interpreter for safe
+Tk operations and load Tk into safe interpreters.
+.PP
+The \fBsafe::loadTk\fR command initializes the required data structures in
+the named safe interpreter and then loads Tk into it. The interpreter must
+have been created with \fBsafe::interpCreate\fR or have been initialized
+with \fBsafe::interpInit\fR. The command returns the name of the safe
+interpreter. If \fB\-use\fR is specified, the window identified by the
+specified system dependent identifier \fIwindowId\fR is used to contain the
+.QW .
+window of the safe interpreter; it can be any valid id, eventually referencing
+a window belonging to another application. As a convenience, if the window you
+plan to use is a Tk Window of the application you can use the window name
+(e.g.,
+.QW \fB.x.y\fR )
+instead of its window Id (e.g., from \fBwinfo id\fR \fB.x.y\fR).
+When \fB\-use\fR is not specified, a new toplevel window is created for the
+.QW .
+window of the safe interpreter. On X11 if you want the embedded window to use
+another display than the default one, specify it with \fB\-display\fR. See
+the \fBSECURITY ISSUES\fR section below for implementation details.
+.SH "SECURITY ISSUES"
+.PP
+Please read the \fBsafe\fR manual page for Tcl to learn about the basic
+security considerations for Safe Tcl.
+.PP
+\fBsafe::loadTk\fR adds the value of \fBtk_library\fR taken from the master
+interpreter to the virtual access path of the safe interpreter so that
+auto-loading will work in the safe interpreter.
+.PP
+Tk initialization is now safe with respect to not trusting the slave's state
+for startup. \fBsafe::loadTk\fR registers the slave's name so when the Tk
+initialization (\fBTk_SafeInit\fR) is called and in turn calls the master's
+\fBsafe::InitTk\fR it will return the desired \fBargv\fR equivalent
+(\fB\-use\fR \fIwindowId\fR, correct \fB\-display\fR, etc.)
+.PP
+When \fB\-use\fR is not used, the new toplevel created is specially decorated
+so the user is always aware that the user interface presented comes from a
+potentially unsafe code and can easily delete the corresponding interpreter.
+.PP
+On X11, conflicting \fB\-use\fR and \fB\-display\fR are likely to generate a
+fatal X error.
+.SH "SEE ALSO"
+safe(n), interp(n), library(n), load(n), package(n), source(n), unknown(n)
+.SH KEYWORDS
+alias, auto-loading, auto_mkindex, load, master interpreter, safe
+interpreter, slave interpreter, source
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/lower.n b/tk8.6/doc/lower.n
new file mode 100644
index 0000000..8159a8b
--- /dev/null
+++ b/tk8.6/doc/lower.n
@@ -0,0 +1,40 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH lower n 3.3 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+lower \- Change a window's position in the stacking order
+.SH SYNOPSIS
+\fBlower \fIwindow \fR?\fIbelowThis\fR?
+.BE
+.SH DESCRIPTION
+.PP
+If the \fIbelowThis\fR argument is omitted then the command lowers
+\fIwindow\fR so that it is below all of its siblings in the stacking
+order (it will be obscured by any siblings that overlap it and
+will not obscure any siblings).
+If \fIbelowThis\fR is specified then it must be the path name of
+a window that is either a sibling of \fIwindow\fR or the descendant
+of a sibling of \fIwindow\fR.
+In this case the \fBlower\fR command will insert
+\fIwindow\fR into the stacking order just below \fIbelowThis\fR
+(or the ancestor of \fIbelowThis\fR that is a sibling of \fIwindow\fR);
+this could end up either raising or lowering \fIwindow\fR.
+.PP
+All \fBtoplevel\fR windows may be restacked with respect to each
+other, whatever their relative path names, but the window manager is
+not obligated to strictly honor requests to restack.
+.SH "SEE ALSO"
+raise
+.SH KEYWORDS
+lower, obscure, stacking order
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/menu.n b/tk8.6/doc/menu.n
new file mode 100644
index 0000000..338ce6a
--- /dev/null
+++ b/tk8.6/doc/menu.n
@@ -0,0 +1,841 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH menu n 4.1 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+menu, tk_menuSetFocus \- Create and manipulate 'menu' widgets and menubars
+.SH SYNOPSIS
+.nf
+\fBmenu\fR \fIpathName \fR?\fIoptions\fR?
+\fBtk_menuSetFocus\fR \fIpathName\fR
+.SO
+\-activebackground \-borderwidth \-foreground
+\-activeborderwidth \-cursor \-relief
+\-activeforeground \-disabledforeground \-takefocus
+\-background \-font
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-postcommand postCommand Command
+If this option is specified then it provides a Tcl command to execute
+each time the menu is posted. The command is invoked by the \fBpost\fR
+widget command before posting the menu. Note that in Tk 8.0 on Macintosh
+and Windows, all post-commands in a system of menus are executed before any
+of those menus are posted.
+This is due to the limitations in the individual platforms' menu managers.
+.OP \-selectcolor selectColor Background
+For menu entries that are check buttons or radio buttons, this option
+specifies the color to display in the indicator when the check button
+or radio button is selected.
+.OP \-tearoff tearOff TearOff
+This option must have a proper boolean value, which specifies
+whether or not the menu should include a tear-off entry at the
+top. If so, it will exist as entry 0 of the menu and the other
+entries will number starting at 1. The default
+menu bindings arrange for the menu to be torn off when the tear-off
+entry is invoked.
+This option is ignored under Aqua/Mac OS X, where menus cannot
+be torn off.
+.OP \-tearoffcommand tearOffCommand TearOffCommand
+If this option has a non-empty value, then it specifies a Tcl command
+to invoke whenever the menu is torn off. The actual command will
+consist of the value of this option, followed by a space, followed
+by the name of the menu window, followed by a space, followed by
+the name of the name of the torn off menu window. For example, if
+the option's value is
+.QW "\fBa b\fR"
+and menu \fB.x.y\fR is torn off to
+create a new menu \fB.x.tearoff1\fR, then the command
+.QW "\fBa b .x.y .x.tearoff1\fR"
+will be invoked.
+This option is ignored under Aqua/Mac OS X, where menus cannot
+be torn off.
+.OP \-title title Title
+The string will be used to title the window created when this menu is
+torn off. If the title is NULL, then the window will have the title
+of the menubutton or the text of the cascade item from which this menu
+was invoked.
+.OP \-type type Type
+This option can be one of \fBmenubar\fR, \fBtearoff\fR, or
+\fBnormal\fR, and is set when the menu is created. While the string
+returned by the configuration database will change if this option is
+changed, this does not affect the menu widget's behavior. This is used
+by the cloning mechanism and is not normally set outside of the Tk
+library.
+.BE
+.SH INTRODUCTION
+.PP
+The \fBmenu\fR command creates a new top-level window (given
+by the \fIpathName\fR argument) and makes it into a menu widget.
+That menu widget can either be used as a pop-up window or applied to a
+\fBtoplevel\fR (with its \fB\-menu\fR option) to make it into the menubar for
+that toplevel.
+Additional
+options, described above, may be specified on the command line
+or in the option database
+to configure aspects of the menu such as its colors and font.
+The \fBmenu\fR command returns its
+\fIpathName\fR argument. At the time this command is invoked,
+there must not exist a window named \fIpathName\fR, but
+\fIpathName\fR's parent must exist.
+.PP
+A menu is a widget that displays a collection of one-line entries arranged
+in one or more columns. There exist several different types of entries,
+each with different properties. Entries of different types may be
+combined in a single menu. Menu entries are not the same as
+entry widgets. In fact, menu entries are not even distinct widgets;
+the entire menu is one widget.
+.PP
+Menu entries are displayed with up to three separate fields.
+The main field is a label in the form of a text string,
+a bitmap, or an image, controlled by the \fB\-label\fR,
+\fB\-bitmap\fR, and \fB\-image\fR options for the entry.
+If the \fB\-accelerator\fR option is specified for an entry then a second
+textual field is displayed to the right of the label. The accelerator
+typically describes a keystroke sequence that may be used in the
+application to cause the same result as invoking the menu entry.
+This is a display option, it does not actually set the corresponding
+binding (which can be achieved using the \fBbind\fR command).
+The third field is an \fIindicator\fR. The indicator is present only for
+checkbutton or radiobutton entries. It indicates whether the entry
+is selected or not, and is displayed to the left of the entry's
+string.
+.PP
+In normal use, an entry becomes active (displays itself differently)
+whenever the mouse pointer is over the entry. If a mouse
+button is released over the entry then the entry is \fIinvoked\fR.
+The effect of invocation is different for each type of entry;
+these effects are described below in the sections on individual
+entries.
+.PP
+Entries may be \fIdisabled\fR, which causes their labels
+and accelerators to be displayed
+with dimmer colors.
+The default menu bindings will not allow
+a disabled entry to be activated or invoked.
+Disabled entries may be re-enabled, at which point it becomes
+possible to activate and invoke them again.
+.PP
+Whenever a menu's active entry is changed, a <<MenuSelect>> virtual
+event is send to the menu. The active item can then be queried from
+the menu, and an action can be taken, such as setting
+context-sensitive help text for the entry.
+.SH "TYPES OF ENTRIES"
+.SS "COMMAND ENTRIES"
+.PP
+The most common kind of menu entry is a command entry, which
+behaves much like a button widget. When a command entry is
+invoked, a Tcl command is executed. The Tcl
+command is specified with the \fB\-command\fR option.
+.SS "SEPARATOR ENTRIES"
+.PP
+A separator is an entry that is displayed as a horizontal dividing
+line. A separator may not be activated or invoked, and it has
+no behavior other than its display appearance.
+.SS "CHECKBUTTON ENTRIES"
+.PP
+A checkbutton menu entry behaves much like a checkbutton widget.
+When it is invoked it toggles back and forth between the selected
+and deselected states. When the entry is selected, a particular
+value is stored in a particular global variable (as determined by
+the \fB\-onvalue\fR and \fB\-variable\fR options for the entry); when
+the entry is deselected another value (determined by the
+\fB\-offvalue\fR option) is stored in the global variable.
+An indicator box is displayed to the left of the label in a checkbutton
+entry. If the entry is selected then the indicator's center is displayed
+in the color given by the \fB\-selectcolor\fR option for the entry;
+otherwise the indicator's center is displayed in the background color for
+the menu. If a \fB\-command\fR option is specified for a checkbutton
+entry, then its value is evaluated as a Tcl command each time the entry
+is invoked; this happens after toggling the entry's
+selected state.
+.SS "RADIOBUTTON ENTRIES"
+.PP
+A radiobutton menu entry behaves much like a radiobutton widget.
+Radiobutton entries are organized in groups of which only one
+entry may be selected at a time. Whenever a particular entry
+becomes selected it stores a particular value into a particular
+global variable (as determined by the \fB\-value\fR and
+\fB\-variable\fR options for the entry). This action
+causes any previously-selected entry in the same group
+to deselect itself.
+Once an entry has become selected, any change to the entry's
+associated variable will cause the entry to deselect itself.
+Grouping of radiobutton entries is determined by their
+associated variables: if two entries have the same associated
+variable then they are in the same group.
+An indicator diamond is displayed to the left of the label in each
+radiobutton entry. If the entry is selected then the indicator's
+center is displayed in the color given by the \fB\-selectcolor\fR option
+for the entry;
+otherwise the indicator's center is displayed in the background color for
+the menu. If a \fB\-command\fR option is specified for a radiobutton
+entry, then its value is evaluated as a Tcl command each time the entry
+is invoked; this happens after selecting the entry.
+.SS "CASCADE ENTRIES"
+.PP
+A cascade entry is one with an associated menu (determined
+by the \fB\-menu\fR option). Cascade entries allow the construction
+of cascading menus.
+The \fBpostcascade\fR widget command can be used to post and unpost
+the associated menu just next to of the cascade entry.
+The associated menu must be a child of the menu containing
+the cascade entry (this is needed in order for menu traversal to
+work correctly).
+.PP
+A cascade entry posts its associated menu by invoking a
+Tcl command of the form
+.CS
+\fImenu\fB post \fIx y\fR
+.CE
+where \fImenu\fR is the path name of the associated menu, and \fIx\fR
+and \fIy\fR are the root-window coordinates of the upper-right
+corner of the cascade entry.
+On Unix, the lower-level menu is unposted by executing a Tcl command with
+the form
+.CS
+\fImenu\fB unpost\fR
+.CE
+where \fImenu\fR is the name of the associated menu.
+On other platforms, the platform's native code takes care of unposting the
+menu.
+.PP
+If a \fB\-command\fR option is specified for a cascade entry then it is
+evaluated as a Tcl command whenever the entry is invoked. This is not
+supported on Windows.
+.SS "TEAR-OFF ENTRIES"
+.PP
+A tear-off entry appears at the top of the menu if enabled with the
+\fB\-tearoff\fR option. It is not like other menu entries in that
+it cannot be created with the \fBadd\fR widget command and
+cannot be deleted with the \fBdelete\fR widget command.
+When a tear-off entry is created it appears as a dashed line at
+the top of the menu. Under the default bindings, invoking the
+tear-off entry causes a torn-off copy to be made of the menu and
+all of its submenus.
+.SH "MENUBARS"
+.PP
+Any menu can be set as a menubar for a toplevel window (see
+\fBtoplevel\fR command for syntax). On the Macintosh, whenever the
+toplevel is in front, this menu's cascade items will appear in the
+menubar across the top of the main monitor. On Windows and Unix, this
+menu's items will be displayed in a menubar across the top of the
+window. These menus will behave according to the interface guidelines
+of their platforms. For every menu set as a menubar, a clone menu is
+made. See the \fBCLONES\fR section for more information.
+.PP
+As noted, menubars may behave differently on different platforms. One
+example of this concerns the handling of checkbuttons and radiobuttons
+within the menu. While it is permitted to put these menu elements on
+menubars, they may not be drawn with indicators on some platforms, due
+to system restrictions.
+.SS "SPECIAL MENUS IN MENUBARS"
+.PP
+Certain menus in a menubar will be treated specially. On the Macintosh,
+access to the special Application, Window and Help menus is provided. On
+Windows, access to the Windows System menu in each window is provided.
+On X Windows, a special right-justified help menu may be provided if
+Motif menu compatibility is enabled. In all cases, these menus must be
+created with the command name of the menubar menu concatenated with the
+special name. So for a menubar named .menubar, on the Macintosh, the
+special menus would be .menubar.apple, .menubar.window and .menubar.help;
+on Windows, the special menu would be .menubar.system; on X Windows,
+the help menu would be .menubar.help.
+.PP
+When Tk sees a .menubar.apple menu as the first menu in a menubar on the
+Macintosh, that menu's contents make up the first items of the
+Application menu whenever the window containing the menubar is in front.
+After all of the Tk-defined items, the menu will have a separator,
+followed by all standard Application menu items.
+Such a .apple menu must be present in a menu when that menu is first
+configured as a toplevel's menubar, otherwise a default application menu
+(hidden from Tk) will be inserted into the menubar at that time and
+subsequent addition of a .apple menu will no longer result in it
+becoming the Application menu.
+.PP
+When Tk sees a .menubar.window menu on the Macintosh, the menu's
+contents are inserted into the standard Window menu of the user's
+menubar whenever the window's menubar is in front. The first items in
+the menu are provided by Mac OS X, and the names of the current
+toplevels are automatically appended after all the Tk-defined items and
+a separator. The Window menu on the Mac also allows toggling the
+window into a fullscreen state, and managing a tabbed window interface
+(multiple windows grouped into a single window) if supported by that
+version of the operating system.
+.PP
+When Tk sees a .menubar.help menu on the Macintosh, the menu's contents
+are appended to the standard Help menu of the user's menubar whenever
+the window's menubar is in front. The first items in the menu
+are provided by Mac OS X.
+.PP
+When Tk sees a System menu on Windows, its items are appended to the
+system menu that the menubar is attached to. This menu is tied to the
+application icon and can be invoked with the mouse or by typing
+Alt+Spacebar. Due to limitations in the Windows API, any font changes,
+colors, images, bitmaps, or tearoff images will not appear in the
+system menu.
+.PP
+When Tk sees a Help menu on X Windows and Motif menu compatibility is
+enabled the menu is moved to be last in the menubar and is right
+justified. Motif menu compatibility is enabled by setting the Tk option
+\fB*Menu.useMotifHelp\fR to true or by calling
+\fBtk::classic::restore menu\fR.
+.SH "CLONES"
+.PP
+When a menu is set as a menubar for a toplevel window, or when a menu
+is torn off, a clone of the menu is made. This clone is a menu widget
+in its own right, but it is a child of the original. Changes in the
+configuration of the original are reflected in the
+clone. Additionally, any cascades that are pointed to are also cloned
+so that menu traversal will work right. Clones are destroyed when
+either the tearoff or menubar goes away, or when the original menu is
+destroyed.
+.SH "WIDGET COMMAND"
+.PP
+The \fBmenu\fR command creates a new Tcl command whose
+name is \fIpathName\fR. This
+command may be used to invoke various
+operations on the widget. It has the following general form:
+.CS
+\fIpathName option \fR?\fIarg arg ...\fR?
+.CE
+\fIOption\fR and the \fIarg\fRs
+determine the exact behavior of the command.
+.PP
+Many of the widget commands for a menu take as one argument an
+indicator of which entry of the menu to operate on. These
+indicators are called \fIindex\fRes and may be specified in
+any of the following forms:
+.TP 12
+\fBactive\fR
+.
+Indicates the entry that is currently active. If no entry is
+active then this form is equivalent to \fBnone\fR. This form may
+not be abbreviated.
+.TP 12
+\fBend\fR
+.
+Indicates the bottommost entry in the menu. If there are no
+entries in the menu then this form is equivalent to \fBnone\fR.
+This form may not be abbreviated.
+.TP 12
+\fBlast\fR
+.
+Same as \fBend\fR.
+.TP 12
+\fBnone\fR
+.
+Indicates
+.QW "no entry at all" ;
+this is used most commonly with
+the \fBactivate\fR option to deactivate all the entries in the
+menu. In most cases the specification of \fBnone\fR causes
+nothing to happen in the widget command.
+This form may not be abbreviated.
+.TP 12
+\fB@\fInumber\fR
+.
+In this form, \fInumber\fR is treated as a y-coordinate in the
+menu's window; the entry closest to that y-coordinate is used.
+For example,
+.QW \fB@0\fR
+indicates the top-most entry in the window.
+.TP 12
+\fInumber\fR
+.
+Specifies the entry numerically, where 0 corresponds
+to the top-most entry of the menu, 1 to the entry below it, and
+so on.
+.TP 12
+\fIpattern\fR
+.
+If the index does not satisfy one of the above forms then this
+form is used. \fIPattern\fR is pattern-matched against the label of
+each entry in the menu, in order from the top down, until a
+matching entry is found. The rules of \fBstring match\fR
+are used.
+.PP
+If the index could match more than one of the above forms, then
+the form earlier in the above list takes precedence.
+.PP
+The following widget commands are possible for menu widgets:
+.TP
+\fIpathName \fBactivate \fIindex\fR
+.
+Change the state of the entry indicated by \fIindex\fR to \fBactive\fR
+and redisplay it using its active colors.
+Any previously-active entry is deactivated. If \fIindex\fR
+is specified as \fBnone\fR, or if the specified entry is
+disabled, then the menu ends up with no active entry.
+Returns an empty string.
+.TP
+\fIpathName \fBadd \fItype \fR?\fIoption value option value ...\fR?
+.
+Add a new entry to the bottom of the menu. The new entry's type
+is given by \fItype\fR and must be one of \fBcascade\fR,
+\fBcheckbutton\fR, \fBcommand\fR, \fBradiobutton\fR, or \fBseparator\fR,
+or a unique abbreviation of one of the above. If additional arguments
+are present, they specify the options listed in the \fBMENU ENTRY OPTIONS\fR
+section below.
+The \fBadd\fR widget command returns an empty string.
+.TP
+\fIpathName \fBcget \fIoption\fR
+.
+Returns the current value of the configuration option given
+by \fIoption\fR.
+\fIOption\fR may have any of the values accepted by the \fBmenu\fR
+command.
+.TP
+\fIpathName \fBclone \fInewPathname\fR ?\fIcloneType\fR?
+.
+Makes a clone of the current menu named \fInewPathName\fR. This clone
+is a menu in its own right, but any changes to the clone are
+propagated to the original menu and vice versa. \fIcloneType\fR can be
+\fBnormal\fR, \fBmenubar\fR, or \fBtearoff\fR. Should not normally be
+called outside of the Tk library. See the \fBCLONES\fR section for
+more information.
+.TP
+\fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
+.
+Query or modify the configuration options of the widget.
+If no \fIoption\fR is specified, returns a list describing all of
+the available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for
+information on the format of this list). If \fIoption\fR is specified
+with no \fIvalue\fR, then the command returns a list describing the
+one named option (this list will be identical to the corresponding
+sublist of the value returned if no \fIoption\fR is specified). If
+one or more \fIoption\-value\fR pairs are specified, then the command
+modifies the given widget option(s) to have the given value(s); in
+this case the command returns an empty string.
+\fIOption\fR may have any of the values accepted by the \fBmenu\fR
+command.
+.TP
+\fIpathName \fBdelete \fIindex1\fR ?\fIindex2\fR?
+.
+Delete all of the menu entries between \fIindex1\fR and
+\fIindex2\fR inclusive.
+If \fIindex2\fR is omitted then it defaults to \fIindex1\fR.
+Attempts to delete a tear-off menu entry are ignored (instead, you
+should change the \fB\-tearoff\fR option to remove the tear-off entry).
+.TP
+\fIpathName \fBentrycget \fIindex option\fR
+.
+Returns the current value of a configuration option for
+the entry given by \fIindex\fR.
+\fIOption\fR may have any of the names described in the
+\fBMENU ENTRY OPTIONS\fR section below.
+.TP
+\fIpathName \fBentryconfigure \fIindex \fR?\fIoptions...\fR?
+.
+This command is similar to the \fBconfigure\fR command, except that
+it applies to the options for an individual entry, whereas \fBconfigure\fR
+applies to the options for the menu as a whole.
+\fIOptions\fR may have any of the values described in the
+\fBMENU ENTRY OPTIONS\fR
+section below. If \fIoptions\fR are specified, options are
+modified as indicated in the command and the command returns an empty string.
+If no \fIoptions\fR are specified, returns a list describing
+the current options for entry \fIindex\fR (see \fBTk_ConfigureInfo\fR for
+information on the format of this list).
+.TP
+\fIpathName \fBindex \fIindex\fR
+.
+Returns the numerical index corresponding to \fIindex\fR, or
+\fBnone\fR if \fIindex\fR was specified as \fBnone\fR.
+.TP
+\fIpathName \fBinsert \fIindex type \fR?\fIoption value option value ...\fR?
+.
+Same as the \fBadd\fR widget command except that it inserts the new
+entry just before the entry given by \fIindex\fR, instead of appending
+to the end of the menu. The \fItype\fR, \fIoption\fR, and \fIvalue\fR
+arguments have the same interpretation as for the \fBadd\fR widget
+command. It is not possible to insert new menu entries before the
+tear-off entry, if the menu has one.
+.TP
+\fIpathName \fBinvoke \fIindex\fR
+.
+Invoke the action of the menu entry. See the sections on the
+individual entries above for details on what happens. If the
+menu entry is disabled then nothing happens. If the
+entry has a command associated with it then the result of that
+command is returned as the result of the \fBinvoke\fR widget
+command. Otherwise the result is an empty string. Note: invoking
+a menu entry does not automatically unpost the menu; the default
+bindings normally take care of this before invoking the \fBinvoke\fR
+widget command.
+.TP
+\fIpathName \fBpost \fIx y\fR ?\fIindex\fR?
+.
+Arrange for the menu to be displayed on the screen at the root-window
+coordinates given by \fIx\fR and \fIy\fR. If an index is specified
+the menu will be located so that the entry with that index is
+displayed at the point. These coordinates are adjusted if necessary to
+guarantee that the entire menu is visible on the screen. This command
+normally returns an empty string. If the \fB\-postcommand\fR option
+has been specified, then its value is executed as a Tcl script before
+posting the menu and the result of that script is returned as the
+result of the \fBpost\fR widget command. If an error returns while
+executing the command, then the error is returned without posting the
+menu.
+.TP
+\fIpathName \fBpostcascade \fIindex\fR
+.
+Posts the submenu associated with the cascade entry given by
+\fIindex\fR, and unposts any previously posted submenu.
+If \fIindex\fR does not correspond to a cascade entry,
+or if \fIpathName\fR is not posted,
+the command has no effect except to unpost any currently posted
+submenu.
+.TP
+\fIpathName \fBtype \fIindex\fR
+.
+Returns the type of the menu entry given by \fIindex\fR.
+This is the \fItype\fR argument passed to the \fBadd\fR or \fBinsert\fR widget
+command when the entry was created, such as \fBcommand\fR
+or \fBseparator\fR, or \fBtearoff\fR for a tear-off entry.
+.TP
+\fIpathName \fBunpost\fR
+.
+Unmap the window so that it is no longer displayed. If a
+lower-level cascaded menu is posted, unpost that menu. Returns an
+empty string. This subcommand does not work on Windows and the
+Macintosh, as those platforms have their own way of unposting menus.
+.TP
+\fIpathName \fBxposition \fIindex\fR
+.
+Returns a decimal string giving the x-coordinate within the menu
+window of the leftmost pixel in the entry specified by \fIindex\fR.
+.TP
+\fIpathName \fByposition \fIindex\fR
+.
+Returns a decimal string giving the y-coordinate within the menu
+window of the topmost pixel in the entry specified by \fIindex\fR.
+.SH "MENU ENTRY OPTIONS"
+The following options are allowed on menu entries. Most options are not
+supported by all entry types.
+.TP
+\fB\-activebackground \fIvalue\fR
+.
+Specifies a background color to use for displaying this entry when it
+is active.
+If this option is specified as an empty string (the default), then the
+\fB\-activebackground\fR option for the overall menu is used.
+If the \fBtk_strictMotif\fR variable has been set to request strict
+Motif compliance, then this option is ignored and the \fB\-background\fR
+option is used in its place.
+This option is not available for separator or tear-off entries.
+.TP
+\fB\-activeforeground \fIvalue\fR
+.
+Specifies a foreground color to use for displaying this entry when it
+is active.
+If this option is specified as an empty string (the default), then the
+\fB\-activeforeground\fR option for the overall menu is used.
+This option is not available for separator or tear-off entries.
+.TP
+\fB\-accelerator \fIvalue\fR
+.
+Specifies a string to display at the right side of the menu entry.
+Normally describes an accelerator keystroke sequence that may be
+used to invoke the same function as the menu entry. This is a display
+option, it does not actually set the corresponding binding (which can
+be achieved using the \fBbind\fR command). This option is not available
+for separator or tear-off entries.
+.TP
+\fB\-background \fIvalue\fR
+.
+Specifies a background color to use for displaying this entry when it
+is in the normal state (neither active nor disabled).
+If this option is specified as an empty string (the default), then the
+\fB\-background\fR option for the overall menu is used.
+This option is not available for separator or tear-off entries.
+.TP
+\fB\-bitmap \fIvalue\fR
+.
+Specifies a bitmap to display in the menu instead of a textual
+label, in any of the forms accepted by \fBTk_GetBitmap\fR.
+This option overrides the \fB\-label\fR option
+(as controlled by the \fB\-compound\fR option)
+but may be reset
+to an empty string to enable a textual label to be displayed.
+If a \fB\-image\fR option has been specified, it overrides
+\fB\-bitmap\fR.
+This option is not available for separator or tear-off entries.
+.TP
+\fB\-columnbreak \fIvalue\fR
+.
+When this option is zero, the entry appears below the previous entry. When
+this option is one, the entry appears at the top of a new column in the
+menu.
+This option is ignored on Aqua/Mac OS X, where menus are always a single
+column.
+.TP
+\fB\-command \fIvalue\fR
+.
+Specifies a Tcl command to execute when the menu entry is invoked.
+Not available for separator or tear-off entries.
+.TP
+\fB\-compound \fIvalue\fR
+.
+Specifies whether the menu entry should display both an image and text,
+and if so, where the image should be placed relative to the text.
+Valid values for this option are \fBbottom\fR, \fBcenter\fR,
+\fBleft\fR, \fBnone\fR, \fBright\fR and \fBtop\fR. The default value
+is \fBnone\fR, meaning that the button will display either an image or
+text, depending on the values of the \fB\-image\fR and \fB\-bitmap\fR
+options.
+.TP
+\fB\-font \fIvalue\fR
+.
+Specifies the font to use when drawing the label or accelerator
+string in this entry.
+If this option is specified as an empty string (the default) then
+the \fB\-font\fR option for the overall menu is used.
+This option is not available for separator or tear-off entries.
+.TP
+\fB\-foreground \fIvalue\fR
+.
+Specifies a foreground color to use for displaying this entry when it
+is in the normal state (neither active nor disabled).
+If this option is specified as an empty string (the default), then the
+\fB\-foreground\fR option for the overall menu is used.
+This option is not available for separator or tear-off entries.
+.TP
+\fB\-hidemargin \fIvalue\fR
+.
+Specifies whether the standard margins should be drawn for this menu
+entry. This is useful when creating palette with images in them, i.e.,
+color palettes, pattern palettes, etc. 1 indicates that the margin for
+the entry is hidden; 0 means that the margin is used.
+.TP
+\fB\-image \fIvalue\fR
+.
+Specifies an image to display in the menu instead of a text string
+or bitmap.
+The image must have been created by some previous invocation of
+\fBimage create\fR.
+This option overrides the \fB\-label\fR and \fB\-bitmap\fR options
+(as controlled by the \fB\-compound\fR option)
+but may be reset to an empty string to enable a textual or
+bitmap label to be displayed.
+This option is not available for separator or tear-off entries.
+.TP
+\fB\-indicatoron \fIvalue\fR
+.
+Available only for checkbutton and radiobutton entries.
+\fIValue\fR is a boolean that determines whether or not the
+indicator should be displayed.
+.TP
+\fB\-label \fIvalue\fR
+.
+Specifies a string to display as an identifying label in the menu
+entry. Not available for separator or tear-off entries.
+.TP
+\fB\-menu \fIvalue\fR
+.
+Available only for cascade entries. Specifies the path name of
+the submenu associated with this entry.
+The submenu must be a child of the menu.
+.TP
+\fB\-offvalue \fIvalue\fR
+.
+Available only for checkbutton entries. Specifies the value to
+store in the entry's associated variable when the entry is
+deselected.
+.TP
+\fB\-onvalue \fIvalue\fR
+.
+Available only for checkbutton entries. Specifies the value to
+store in the entry's associated variable when the entry is selected.
+.TP
+\fB\-selectcolor \fIvalue\fR
+.
+Available only for checkbutton and radiobutton entries.
+Specifies the color to display in the indicator when the entry is
+selected.
+If the value is an empty string (the default) then the \fB\-selectcolor\fR
+option for the menu determines the indicator color.
+.TP
+\fB\-selectimage \fIvalue\fR
+.
+Available only for checkbutton and radiobutton entries.
+Specifies an image to display in the entry (in place of
+the \fB\-image\fR option) when it is selected.
+\fIValue\fR is the name of an image, which must have been created
+by some previous invocation of \fBimage create\fR.
+This option is ignored unless the \fB\-image\fR option has
+been specified.
+.TP
+\fB\-state \fIvalue\fR
+.
+Specifies one of three states for the entry: \fBnormal\fR, \fBactive\fR,
+or \fBdisabled\fR. In normal state the entry is displayed using the
+\fB\-foreground\fR option for the menu and the \fB\-background\fR
+option from the entry or the menu.
+The active state is typically used when the pointer is over the entry.
+In active state the entry is displayed using the \fB\-activeforeground\fR
+option for the menu along with the \fB\-activebackground\fR option from
+the entry. Disabled state means that the entry
+should be insensitive: the default bindings will refuse to activate
+or invoke the entry.
+In this state the entry is displayed according to the
+\fB\-disabledforeground\fR option for the menu and the
+\fB\-background\fR option from the entry.
+This option is not available for separator entries.
+.TP
+\fB\-underline \fIvalue\fR
+.
+Specifies the integer index of a character to underline in the entry.
+This option is also queried by the default bindings and used to
+implement keyboard traversal.
+0 corresponds to the first character of the text displayed in the entry,
+1 to the next character, and so on.
+If a bitmap or image is displayed in the entry then this option is ignored.
+This option is not available for separator or tear-off entries.
+.TP
+\fB\-value \fIvalue\fR
+.
+Available only for radiobutton entries. Specifies the value to
+store in the entry's associated variable when the entry is selected.
+If an empty string is specified, then the \fB\-label\fR option
+for the entry as the value to store in the variable.
+.TP
+\fB\-variable \fIvalue\fR
+.
+Available only for checkbutton and radiobutton entries. Specifies
+the name of a global variable to set when the entry is selected.
+For checkbutton entries the variable is also set when the entry
+is deselected. For radiobutton entries, changing the variable
+causes the currently-selected entry to deselect itself.
+.RS
+.PP
+For checkbutton entries, the default value of this option is taken from the
+\fB\-label\fR option, and for radiobutton entries a single fixed value is
+used. It is recommended that you always set the \fB\-variable\fR option when
+creating either a checkbutton or a radiobutton.
+.RE
+.SH "MENU CONFIGURATIONS"
+.PP
+The default bindings support four different ways of using menus:
+.TP
+\fBPulldown Menus in Menubar\fR
+.
+This is the most common case. You create a menu widget that will become the
+menu bar. You then add cascade entries to this menu, specifying the
+pull down menus you wish to use in your menu bar. You then create all
+of the pulldowns. Once you have done this, specify the menu using the
+\fB\-menu\fR option of the toplevel's widget command. See the
+\fBtoplevel\fR manual entry for details.
+.TP
+\fBPulldown Menus in Menu Buttons\fR
+.
+This is the compatible way to do menu bars. You create one menubutton
+widget for each top-level menu, and typically you arrange a series of
+menubuttons in a row in a menubar window. You also create the top-level menus
+and any cascaded submenus, and tie them together with \fB\-menu\fR
+options in menubuttons and cascade menu entries. The top-level menu must
+be a child of the menubutton, and each submenu must be a child of the
+menu that refers to it. Once you have done this, the default bindings
+will allow users to traverse and invoke the tree of menus via its
+menubutton; see the \fBmenubutton\fR manual entry for details.
+.TP
+\fBPopup Menus\fR
+.
+Popup menus typically post in response to a mouse button press or
+keystroke. You create the popup menus and any cascaded submenus,
+then you call the \fBtk_popup\fR procedure at the appropriate time
+to post the top-level menu.
+.TP
+\fBOption Menus\fR
+.
+An option menu consists of a menubutton with an associated menu
+that allows you to select one of several values. The current value
+is displayed in the menubutton and is also stored in a global
+variable. Use the \fBtk_optionMenu\fR procedure to create option
+menubuttons and their menus.
+.TP
+\fBTorn-off Menus\fR
+.
+You create a torn-off menu by invoking the tear-off entry at
+the top of an existing menu. The default bindings will create a new menu
+that is a copy of the original menu and leave it permanently
+posted as a top-level window. The torn-off menu behaves just
+the same as the original menu.
+.SH "DEFAULT BINDINGS"
+.PP
+Tk automatically creates class bindings for menus that give them
+the following default behavior:
+.IP [1]
+When the mouse enters a menu, the entry underneath the mouse
+cursor activates; as the mouse moves around the menu, the active
+entry changes to track the mouse.
+.IP [2]
+When the mouse leaves a menu all of the entries in the menu
+deactivate, except in the special case where the mouse moves from
+a menu to a cascaded submenu.
+.IP [3]
+When a button is released over a menu, the active entry (if any) is invoked.
+The menu also unposts unless it is a torn-off menu.
+.IP [4]
+The Space and Return keys invoke the active entry and
+unpost the menu.
+.IP [5]
+If any of the entries in a menu have letters underlined with
+the \fB\-underline\fR option, then pressing one of the underlined
+letters (or its upper-case or lower-case equivalent) invokes that
+entry and unposts the menu.
+.IP [6]
+The Escape key aborts a menu selection in progress without invoking any
+entry. It also unposts the menu unless it is a torn-off menu.
+.IP [7]
+The Up and Down keys activate the next higher or lower entry
+in the menu. When one end of the menu is reached, the active
+entry wraps around to the other end.
+.IP [8]
+The Left key moves to the next menu to the left.
+If the current menu is a cascaded submenu, then the submenu is
+unposted and the current menu entry becomes the cascade entry
+in the parent.
+If the current menu is a top-level menu posted from a
+menubutton, then the current menubutton is unposted and the
+next menubutton to the left is posted.
+Otherwise the key has no effect.
+The left-right order of menubuttons is determined by their stacking
+order: Tk assumes that the lowest menubutton (which by default
+is the first one created) is on the left.
+.IP [9]
+The Right key moves to the next menu to the right.
+If the current entry is a cascade entry, then the submenu is
+posted and the current menu entry becomes the first entry
+in the submenu.
+Otherwise, if the current menu was posted from a
+menubutton, then the current menubutton is unposted and the
+next menubutton to the right is posted.
+.PP
+Disabled menu entries are non-responsive: they do not activate and
+they ignore mouse button presses and releases.
+.PP
+Several of the bindings make use of the command \fBtk_menuSetFocus\fR.
+It saves the current focus and sets the focus to its \fIpathName\fR
+argument, which is a menu widget.
+.PP
+The behavior of menus can be changed by defining new bindings for
+individual widgets or by redefining the class bindings.
+.SH BUGS
+.PP
+At present it is not possible to use the
+option database to specify values for the options to individual
+entries.
+.SH "SEE ALSO"
+bind(n), menubutton(n), ttk::menubutton(n), toplevel(n)
+.SH KEYWORDS
+menu, widget
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/menubar.n b/tk8.6/doc/menubar.n
new file mode 100644
index 0000000..023bf37
--- /dev/null
+++ b/tk8.6/doc/menubar.n
@@ -0,0 +1,38 @@
+'\"
+'\" Copyright (c) 1992 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH tk_menuBar n "" Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+tk_menuBar, tk_bindForTraversal \- Obsolete support for menu bars
+.SH SYNOPSIS
+\fBtk_menuBar \fIframe \fR?\fImenu menu ...\fR?
+.sp
+\fBtk_bindForTraversal \fIarg arg ... \fR
+.BE
+.SH DESCRIPTION
+.PP
+These procedures were used in Tk 3.6 and earlier releases to help
+manage pulldown menus and to implement keyboard traversal of menus.
+In Tk 4.0 and later releases they are no
+longer needed. Stubs for these procedures have been retained for
+backward compatibility, but they have no effect. You should remove
+calls to these procedures from your code, since eventually the
+procedures will go away.
+.PP
+From Tk 8.0 onwards, you should instead construct your menubar as a
+normal \fBmenu\fR and then attach it to the \fBtoplevel\fR of your
+choice using the \fB\-menu\fR option of that widget.
+.SH "SEE ALSO"
+menu(n), toplevel(n)
+.SH KEYWORDS
+keyboard traversal, menu, menu bar, post
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/menubutton.n b/tk8.6/doc/menubutton.n
new file mode 100644
index 0000000..08b52a0
--- /dev/null
+++ b/tk8.6/doc/menubutton.n
@@ -0,0 +1,202 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH menubutton n 4.0 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+menubutton \- Create and manipulate 'menubutton' pop-up menu indicator widgets
+.SH SYNOPSIS
+\fBmenubutton\fR \fIpathName \fR?\fIoptions\fR?
+.SO
+\-activebackground \-disabledforeground \-padx
+\-activeforeground \-font \-pady
+\-anchor \-foreground \-relief
+\-background \-highlightbackground \-takefocus
+\-bitmap \-highlightcolor \-text
+\-borderwidth \-highlightthickness \-textvariable
+\-cursor \-image \-underline
+\-compound \-justify \-wraplength
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-direction direction Height
+Specifies where the menu is going to be popup up. \fBabove\fR tries to
+pop the menu above the menubutton. \fBbelow\fR tries to pop the menu
+below the menubutton. \fBleft\fR tries to pop the menu to the left of
+the menubutton. \fBright\fR tries to pop the menu to the right of the
+menu button. \fBflush\fR pops the menu directly over the menubutton.
+In the case of \fBabove\fR or \fBbelow\fR, the direction will be
+reversed if the menu would show offscreen.
+.OP \-height height Height
+Specifies a desired height for the menubutton.
+If an image or bitmap is being displayed in the menubutton then the value is in
+screen units (i.e. any of the forms acceptable to \fBTk_GetPixels\fR);
+for text it is in lines of text.
+If this option is not specified, the menubutton's desired height is computed
+from the size of the image or bitmap or text being displayed in it.
+.OP \-indicatoron indicatorOn IndicatorOn
+The value must be a proper boolean value. If it is true then
+a small indicator rectangle will be displayed on the right side
+of the menubutton and the default menu bindings will treat this
+as an option menubutton. If false then no indicator will be
+displayed.
+.OP \-menu menu MenuName
+Specifies the path name of the menu associated with this menubutton.
+The menu must be a child of the menubutton.
+.OP \-state state State
+Specifies one of three states for the menubutton: \fBnormal\fR, \fBactive\fR,
+or \fBdisabled\fR. In normal state the menubutton is displayed using the
+\fBforeground\fR and \fBbackground\fR options. The active state is
+typically used when the pointer is over the menubutton. In active state
+the menubutton is displayed using the \fB\-activeforeground\fR and
+\fB\-activebackground\fR options. Disabled state means that the menubutton
+should be insensitive: the default bindings will refuse to activate
+the widget and will ignore mouse button presses.
+In this state the \fB\-disabledforeground\fR and
+\fB\-background\fR options determine how the button is displayed.
+.OP \-width width Width
+Specifies a desired width for the menubutton.
+If an image or bitmap is being displayed in the menubutton then the value is in
+screen units (i.e. any of the forms acceptable to \fBTk_GetPixels\fR);
+for text it is in characters.
+If this option is not specified, the menubutton's desired width is computed
+from the size of the image or bitmap or text being displayed in it.
+.BE
+.SH INTRODUCTION
+.PP
+The \fBmenubutton\fR command creates a new window (given by the
+\fIpathName\fR argument) and makes it into a menubutton widget.
+Additional
+options, described above, may be specified on the command line
+or in the option database
+to configure aspects of the menubutton such as its colors, font,
+text, and initial relief. The \fBmenubutton\fR command returns its
+\fIpathName\fR argument. At the time this command is invoked,
+there must not exist a window named \fIpathName\fR, but
+\fIpathName\fR's parent must exist.
+.PP
+A menubutton is a widget that displays a textual string, bitmap, or image
+and is associated with a menu widget.
+If text is displayed, it must all be in a single font, but it
+can occupy multiple lines on the screen (if it contains newlines
+or if wrapping occurs because of the \fB\-wraplength\fR option) and
+one of the characters may optionally be underlined using the
+\fB\-underline\fR option. In normal usage, pressing
+mouse button 1 over the menubutton causes the associated menu to
+be posted just underneath the menubutton. If the mouse is moved over
+the menu before releasing the mouse button, the button release
+causes the underlying menu entry to be invoked. When the button
+is released, the menu is unposted.
+.PP
+Menubuttons are used to construct a \fBtk_optionMenu\fR, which is the
+preferred mechanism for allowing a user to select one item from a list
+on Mac OS X.
+.PP
+Menubuttons were also typically organized into groups called menu bars
+that allow scanning:
+if the mouse button is pressed over one menubutton (causing it
+to post its menu) and the mouse is moved over another menubutton
+in the same menu bar without releasing the mouse button, then the
+menu of the first menubutton is unposted and the menu of the
+new menubutton is posted instead.
+\fIThis use is deprecated\fR in favor of setting a \fBmenu\fR directly as a
+menubar; see the \fBtoplevel\fR's \fB\-menu\fR option for how to do that.
+.PP
+There are several interactions between menubuttons and menus; see
+the \fBmenu\fR manual entry for information on various menu configurations,
+such as pulldown menus and option menus.
+.SH "WIDGET COMMAND"
+.PP
+The \fBmenubutton\fR command creates a new Tcl command whose
+name is \fIpathName\fR. This
+command may be used to invoke various
+operations on the widget. It has the following general form:
+.CS
+\fIpathName option \fR?\fIarg arg ...\fR?
+.CE
+\fIOption\fR and the \fIarg\fRs
+determine the exact behavior of the command. The following
+commands are possible for menubutton widgets:
+.TP
+\fIpathName \fBcget \fIoption\fR
+.
+Returns the current value of the configuration option given
+by \fIoption\fR.
+\fIOption\fR may have any of the values accepted by the \fBmenubutton\fR
+command.
+.TP
+\fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
+.
+Query or modify the configuration options of the widget.
+If no \fIoption\fR is specified, returns a list describing all of
+the available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for
+information on the format of this list). If \fIoption\fR is specified
+with no \fIvalue\fR, then the command returns a list describing the
+one named option (this list will be identical to the corresponding
+sublist of the value returned if no \fIoption\fR is specified). If
+one or more \fIoption\-value\fR pairs are specified, then the command
+modifies the given widget option(s) to have the given value(s); in
+this case the command returns an empty string.
+\fIOption\fR may have any of the values accepted by the \fBmenubutton\fR
+command.
+.SH "DEFAULT BINDINGS"
+.PP
+Tk automatically creates class bindings for menubuttons that give them
+the following default behavior:
+.IP [1]
+A menubutton activates whenever the mouse passes over it and deactivates
+whenever the mouse leaves it.
+.IP [2]
+Pressing mouse button 1 over a menubutton posts the menubutton:
+its relief changes to raised and its associated menu is posted
+under the menubutton. If the mouse is dragged down into the menu
+with the button still down, and if the mouse button is then
+released over an entry in the menu, the menubutton is unposted
+and the menu entry is invoked.
+.IP [3]
+If button 1 is pressed over a menubutton and then released over that
+menubutton, the menubutton stays posted: you can still move the mouse
+over the menu and click button 1 on an entry to invoke it.
+Once a menu entry has been invoked, the menubutton unposts itself.
+.IP [4]
+If button 1 is pressed over a menubutton and then dragged over some
+other menubutton, the original menubutton unposts itself and the
+new menubutton posts.
+.IP [5]
+If button 1 is pressed over a menubutton and released outside
+any menubutton or menu, the menubutton unposts without invoking
+any menu entry.
+.IP [6]
+When a menubutton is posted, its associated menu claims the input
+focus to allow keyboard traversal of the menu and its submenus.
+See the \fBmenu\fR manual entry for details on these bindings.
+.IP [7]
+If the \fB\-underline\fR option has been specified for a menubutton
+then keyboard traversal may be used to post the menubutton:
+Alt+\fIx\fR, where \fIx\fR is the underlined character (or its
+lower-case or upper-case equivalent), may be typed in any window
+under the menubutton's toplevel to post the menubutton.
+.IP [8]
+The F10 key may be typed in any window to post the first menubutton
+under its toplevel window that is not disabled.
+.IP [9]
+If a menubutton has the input focus, the space and return keys
+post the menubutton.
+.PP
+If the menubutton's state is \fBdisabled\fR then none of the above
+actions occur: the menubutton is completely non-responsive.
+.PP
+The behavior of menubuttons can be changed by defining new bindings for
+individual widgets or by redefining the class bindings.
+.SH "SEE ALSO"
+ttk::menubutton(n), menu(n)
+.SH KEYWORDS
+menubutton, widget
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/message.n b/tk8.6/doc/message.n
new file mode 100644
index 0000000..bd635ac
--- /dev/null
+++ b/tk8.6/doc/message.n
@@ -0,0 +1,150 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH message n 4.0 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+message \- Create and manipulate 'message' non-interactive text widgets
+.SH SYNOPSIS
+\fBmessage\fR \fIpathName \fR?\fIoptions\fR?
+.SO
+\-anchor \-background \-borderwidth
+\-cursor \-font \-foreground
+\-highlightbackground \-highlightcolor \-highlightthickness
+\-padx \-pady \-relief
+\-takefocus \-text \-textvariable
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-aspect aspect Aspect
+Specifies a non-negative integer value indicating desired
+aspect ratio for the text. The aspect ratio is specified as
+100*width/height. 100 means the text should
+be as wide as it is tall, 200 means the text should
+be twice as wide as it is tall, 50 means the text should
+be twice as tall as it is wide, and so on.
+Used to choose line length for text if \fB\-width\fR option
+is not specified.
+Defaults to 150.
+.OP \-justify justify Justify
+Specifies how to justify lines of text.
+Must be one of \fBleft\fR, \fBcenter\fR, or \fBright\fR. Defaults
+to \fBleft\fR.
+This option works together with the \fB\-anchor\fR, \fB\-aspect\fR,
+\fB\-padx\fR, \fB\-pady\fR, and \fB\-width\fR options to provide a variety
+of arrangements of the text within the window.
+The \fB\-aspect\fR and \fB\-width\fR options determine the amount of
+screen space needed to display the text.
+The \fB\-anchor\fR, \fB\-padx\fR, and \fB\-pady\fR options determine where this
+rectangular area is displayed within the widget's window, and the
+\fB\-justify\fR option determines how each line is displayed within that
+rectangular region.
+For example, suppose \fB\-anchor\fR is \fBe\fR and \fB\-justify\fR is
+\fBleft\fR, and that the message window is much larger than needed
+for the text.
+The text will be displayed so that the left edges of all the lines
+line up and the right edge of the longest line is \fB\-padx\fR from
+the right side of the window; the entire text block will be centered
+in the vertical span of the window.
+.OP \-width width Width
+Specifies the length of lines in the window.
+The value may have any of the forms acceptable to \fBTk_GetPixels\fR.
+If this option has a value greater than zero then the \fB\-aspect\fR
+option is ignored and the \fB\-width\fR option determines the line
+length.
+If this option has a value less than or equal to zero, then
+the \fB\-aspect\fR option determines the line length.
+.BE
+.SH DESCRIPTION
+.PP
+The \fBmessage\fR command creates a new window (given by the
+\fIpathName\fR argument) and makes it into a message widget.
+Additional
+options, described above, may be specified on the command line
+or in the option database
+to configure aspects of the message such as its colors, font,
+text, and initial relief. The \fBmessage\fR command returns its
+\fIpathName\fR argument. At the time this command is invoked,
+there must not exist a window named \fIpathName\fR, but
+\fIpathName\fR's parent must exist.
+.PP
+A message is a widget that displays a textual string. A message
+widget has three special features that differentiate it from a
+\fBlabel\fR widget. First, it breaks up
+its string into lines in order to produce a given aspect ratio
+for the window. The line breaks are chosen at word boundaries
+wherever possible (if not even a single word would fit on a
+line, then the word will be split across lines). Newline characters
+in the string will force line breaks; they can be used, for example,
+to leave blank lines in the display.
+.PP
+The second feature of a message widget is justification. The text
+may be displayed left-justified (each line starts at the left side of
+the window), centered on a line-by-line basis, or right-justified
+(each line ends at the right side of the window).
+.PP
+The third feature of a message widget is that it handles control
+characters and non-printing characters specially. Tab characters
+are replaced with enough blank space to line up on the next
+8-character boundary. Newlines cause line breaks. Other control
+characters (ASCII code less than 0x20) and characters not defined
+in the font are displayed as a four-character sequence \fB\ex\fIhh\fR where
+\fIhh\fR is the two-digit hexadecimal number corresponding to
+the character. In the unusual case where the font does not contain
+all of the characters in
+.QW 0123456789abcdef\ex
+then control characters and undefined characters are not displayed at all.
+.SH "WIDGET COMMAND"
+.PP
+The \fBmessage\fR command creates a new Tcl command whose
+name is \fIpathName\fR. This
+command may be used to invoke various
+operations on the widget. It has the following general form:
+.CS
+\fIpathName option \fR?\fIarg arg ...\fR?
+.CE
+\fIOption\fR and the \fIarg\fRs
+determine the exact behavior of the command. The following
+commands are possible for message widgets:
+.TP
+\fIpathName \fBcget \fIoption\fR
+.
+Returns the current value of the configuration option given
+by \fIoption\fR.
+\fIOption\fR may have any of the values accepted by the \fBmessage\fR
+command.
+.TP
+\fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
+.
+Query or modify the configuration options of the widget.
+If no \fIoption\fR is specified, returns a list describing all of
+the available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for
+information on the format of this list). If \fIoption\fR is specified
+with no \fIvalue\fR, then the command returns a list describing the
+one named option (this list will be identical to the corresponding
+sublist of the value returned if no \fIoption\fR is specified). If
+one or more \fIoption\-value\fR pairs are specified, then the command
+modifies the given widget option(s) to have the given value(s); in
+this case the command returns an empty string.
+\fIOption\fR may have any of the values accepted by the \fBmessage\fR
+command.
+.SH "DEFAULT BINDINGS"
+.PP
+When a new message is created, it has no default event bindings:
+messages are intended for output purposes only.
+.SH BUGS
+.PP
+Tabs do not work very well with text that is centered or right-justified.
+The most common result is that the line is justified wrong.
+.SH "SEE ALSO"
+label(n)
+.SH KEYWORDS
+message, widget
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/messageBox.n b/tk8.6/doc/messageBox.n
new file mode 100644
index 0000000..6bcbc09
--- /dev/null
+++ b/tk8.6/doc/messageBox.n
@@ -0,0 +1,122 @@
+'\"
+'\" 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.
+'\"
+.TH tk_messageBox n 4.2 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+tk_messageBox \- pops up a message window and waits for user response.
+.SH SYNOPSIS
+\fBtk_messageBox \fR?\fIoption value ...\fR?
+.BE
+.SH DESCRIPTION
+.PP
+This procedure creates and displays a message window with an
+application-specified message, an icon and a set of buttons. Each of
+the buttons in the message window is identified by a unique symbolic
+name (see the \fB\-type\fR options). After the message window is
+popped up, \fBtk_messageBox\fR waits for the user to select one of the
+buttons. Then it returns the symbolic name of the selected button.
+.PP
+The following option-value pairs are supported:
+.TP
+\fB\-command\fR \fIstring\fR
+Specifies the prefix of a Tcl command to invoke when the user closes the
+dialog. The actual command consists of \fIstring\fR followed by a space
+and the name of the button clicked by the user to close the dialog. This
+is only available on Mac OS X.
+.TP
+\fB\-default\fR \fIname\fR
+.
+\fIName\fR gives the symbolic name of the default button for
+this message window (
+.QW ok ,
+.QW cancel ,
+and so on). See \fB\-type\fR
+for a list of the symbolic names. If this option is not specified,
+the first button in the dialog will be made the default.
+.TP
+\fB\-detail\fR \fIstring\fR
+.
+Specifies an auxiliary message to the main message given by the
+\fB\-message\fR option. The message detail will be presented beneath the main
+message and, where supported by the OS, in a less emphasized font than the
+main message.
+.TP
+\fB\-icon\fR \fIiconImage\fR
+.
+Specifies an icon to display. \fIIconImage\fR must be one of the
+following: \fBerror\fR, \fBinfo\fR, \fBquestion\fR or
+\fBwarning\fR. If this option is not specified, then the info icon will be
+displayed.
+.TP
+\fB\-message\fR \fIstring\fR
+.
+Specifies the message to display in this message box. The
+default value is an empty string.
+.TP
+\fB\-parent\fR \fIwindow\fR
+.
+Makes \fIwindow\fR the logical parent of the message box. The message
+box is displayed on top of its parent window.
+.TP
+\fB\-title\fR \fItitleString\fR
+.
+Specifies a string to display as the title of the message box. This option
+is ignored on Mac OS X, where platform guidelines forbid the use of a title
+on this kind of dialog.
+.TP
+\fB\-type\fR \fIpredefinedType\fR
+.
+Arranges for a predefined set of buttons to be displayed. The
+following values are possible for \fIpredefinedType\fR:
+.RS
+.TP 18
+\fBabortretryignore\fR
+.
+Displays three buttons whose symbolic names are \fBabort\fR,
+\fBretry\fR and \fBignore\fR.
+.TP 18
+\fBok\fR
+.
+Displays one button whose symbolic name is \fBok\fR.
+.TP 18
+\fBokcancel\fR
+.
+Displays two buttons whose symbolic names are \fBok\fR and \fBcancel\fR.
+.TP 18
+\fBretrycancel\fR
+.
+Displays two buttons whose symbolic names are \fBretry\fR and \fBcancel\fR.
+.TP 18
+\fByesno\fR
+.
+Displays two buttons whose symbolic names are \fByes\fR and \fBno\fR.
+.TP 18
+\fByesnocancel\fR
+.
+Displays three buttons whose symbolic names are \fByes\fR, \fBno\fR
+and \fBcancel\fR.
+.RE
+.PP
+.SH EXAMPLE
+.PP
+.CS
+set answer [\fBtk_messageBox\fR \-message "Really quit?" \e
+ \-icon question \-type yesno \e
+ \-detail "Select \e"Yes\e" to make the application exit"]
+switch \-\- $answer {
+ yes exit
+ no {\fBtk_messageBox\fR \-message "I know you like this application!" \e
+ \-type ok}
+}
+.CE
+.SH KEYWORDS
+message box
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/option.n b/tk8.6/doc/option.n
new file mode 100644
index 0000000..2763d64
--- /dev/null
+++ b/tk8.6/doc/option.n
@@ -0,0 +1,140 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH option n "" Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+option \- Add/retrieve window options to/from the option database
+.SH SYNOPSIS
+.nf
+\fBoption add \fIpattern value \fR?\fIpriority\fR?
+\fBoption clear\fR
+\fBoption get \fIwindow name class\fR
+\fBoption readfile \fIfileName \fR?\fIpriority\fR?
+.fi
+.BE
+.SH DESCRIPTION
+.PP
+The \fBoption\fR command allows you to add entries to the Tk option
+database or to retrieve options from the database. The \fBadd\fR
+form of the command adds a new option to the database.
+\fIPattern\fR contains
+the option being specified, and consists of names and/or classes
+separated by asterisks or dots, in the usual X format (see
+\fBPATTERN FORMAT\fR). \fIValue\fR
+contains a text string to associate with \fIpattern\fR; this is the
+value that will be returned in calls to \fBTk_GetOption\fR or by
+invocations of the \fBoption get\fR command. If \fIpriority\fR
+is specified, it indicates the priority level for this option (see
+below for legal values); it defaults to \fBinteractive\fR.
+This command always returns an empty string.
+.PP
+The \fBoption clear\fR command clears the option database. Default
+options (from the
+\fBRESOURCE_MANAGER\fR property or the \fB.Xdefaults\fR
+file) will be reloaded automatically the next time an
+option is added to the database or removed from it. This command
+always returns an empty string.
+.PP
+The \fBoption get\fR command returns the value of the option
+specified for \fIwindow\fR
+under \fIname\fR and \fIclass\fR. If several entries in the option
+database match \fIwindow\fR, \fIname\fR, and \fIclass\fR, then
+the command returns whichever was created with highest
+\fIpriority\fR level. If there are several matching
+entries at the same priority level, then it returns whichever entry
+was most recently entered into the option database. If there are
+no matching entries, then the empty string is returned.
+.PP
+The \fBreadfile\fR form of the command reads \fIfileName\fR,
+which should have the standard format for an
+X resource database such as \fB.Xdefaults\fR, and adds all the
+options specified in that file to the option database. If \fIpriority\fR
+is specified, it indicates the priority level at which to enter the
+options; \fIpriority\fR defaults to \fBinteractive\fR.
+.PP
+The file is read through a channel which is in "utf-8" encoding,
+invalid byte sequences are automatically converted to valid ones.
+This means that encodings like ISO 8859-1 or cp1252 with high
+probability will work as well, but this cannot be guaranteed.
+This cannot be changed, setting the [encoding system] has no effect.
+.PP
+The \fIpriority\fR arguments to the \fBoption\fR command are
+normally specified symbolically using one of the following values:
+.TP
+\fBwidgetDefault\fR
+Level 20. Used for default values hard-coded into widgets.
+.TP
+\fBstartupFile\fR
+Level 40. Used for options specified in application-specific
+startup files.
+.TP
+\fBuserDefault\fR
+Level 60. Used for options specified in user-specific defaults
+files, such as \fB.Xdefaults\fR, resource databases loaded into
+the X server, or user-specific startup files.
+.TP
+\fBinteractive\fR
+Level 80. Used for options specified interactively after the application
+starts running. If \fIpriority\fR is not specified, it defaults to
+this level.
+.PP
+Any of the above keywords may be abbreviated. In addition, priorities
+may be specified numerically using integers between 0 and 100,
+inclusive. The numeric form is probably a bad idea except for new priority
+levels other than the ones given above.
+.SH "PATTERN FORMAT"
+.PP
+Patterns consist of a sequence of words separated by either periods,
+.QW . ,
+or asterisks
+.QW * .
+The overall pattern may also be optionally preceded by an asterisk.
+.PP
+Each word in the pattern conventionally starts with either an upper-case
+letter (in which case it denotes the class of either a widget or an option) or
+any other character, when it denotes the name of a widget or option. The last
+word in the pattern always indicates the option; the preceding ones constrain
+which widgets that option will be looked for in.
+.PP
+When two words are separated by a period, the latter widget must be a direct
+child of the former (or the option must apply to only the indicated widgets).
+When two words are separated by an asterisk, any depth of widgets may lie
+between the former and latter widgets (and the option applies to all widgets
+that are children of the former widget).
+.PP
+If the overall pattern is preceded by an asterisk, then the overall pattern
+applies anywhere it can throughout the whole widget hierarchy. Otherwise the
+first word of the pattern is matched against the name and class of the
+.QW \fB.\fR
+\fBtoplevel\fR, which are usually set by options to \fBwish\fR.
+.SH EXAMPLES
+.PP
+Instruct every button in the application to have red text on it unless
+explicitly overridden, by setting the \fBforeground\fR for the \fBButton\fR
+class (note that on some platforms the option is ignored):
+.CS
+\fBoption add\fR *Button.foreground red startupFile
+.CE
+.PP
+Allow users to control what happens in an entry widget when the Return
+key is pressed by specifying a script in the option database and add a
+default option for that which rings the bell:
+.CS
+entry .e
+bind .e <Return> [\fBoption get\fR .e returnCommand Command]
+\fBoption add\fR *.e.returnCommand bell widgetDefault
+.CE
+.SH "SEE ALSO"
+options(n), wish(1)
+.SH KEYWORDS
+database, option, priority, retrieve
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/optionMenu.n b/tk8.6/doc/optionMenu.n
new file mode 100644
index 0000000..42275ce
--- /dev/null
+++ b/tk8.6/doc/optionMenu.n
@@ -0,0 +1,45 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH tk_optionMenu n 4.0 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+tk_optionMenu \- Create an option menubutton and its menu
+.SH SYNOPSIS
+\fBtk_optionMenu \fIpathName varName value \fR?\fIvalue value ...\fR?
+.BE
+.SH DESCRIPTION
+.PP
+This procedure creates an option menubutton whose name is \fIpathName\fR,
+plus an associated menu.
+Together they allow the user to select one of the values
+given by the \fIvalue\fR arguments.
+The current value will be stored in the global variable whose
+name is given by \fIvarName\fR and it will also be displayed as the label
+in the option menubutton.
+The user can click on the menubutton to display a menu containing
+all of the \fIvalue\fRs and thereby select a new value.
+Once a new value is selected, it will be stored in the variable
+and appear in the option menubutton.
+The current value can also be changed by setting the variable.
+.PP
+The return value from \fBtk_optionMenu\fR is the name of the menu
+associated with \fIpathName\fR, so that the caller can change its
+configuration options or manipulate it in other ways.
+.SH EXAMPLE
+.PP
+.CS
+tk_optionMenu .foo myVar Foo Bar Boo Spong Wibble
+pack .foo
+.CE
+.SH KEYWORDS
+option menu
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/options.n b/tk8.6/doc/options.n
new file mode 100644
index 0000000..738a1c6
--- /dev/null
+++ b/tk8.6/doc/options.n
@@ -0,0 +1,358 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH options n 4.4 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+options \- Standard options supported by widgets
+.BE
+.SH DESCRIPTION
+.PP
+This manual entry describes the common configuration options supported
+by widgets in the Tk toolkit. Every widget does not necessarily support
+every option (see the manual entries for individual widgets for a list
+of the standard options supported by that widget), but if a widget does
+support an option with one of the names listed below, then the option
+has exactly the effect described below.
+.PP
+In the descriptions below,
+.QW "Command-Line Name"
+refers to the
+switch used in class commands and \fBconfigure\fR widget commands to
+set this value. For example, if an option's command-line switch is
+\fB\-foreground\fR and there exists a widget \fB.a.b.c\fR, then the
+command
+.CS
+\&\fB.a.b.c\0\0configure\0\0\-foreground black\fR
+.CE
+may be used to specify the value \fBblack\fR for the option in
+the widget \fB.a.b.c\fR. Command-line switches may be abbreviated,
+as long as the abbreviation is unambiguous.
+.QW "Database Name"
+refers to the option's name in the option database (e.g. in .Xdefaults files).
+.QW "Database Class"
+refers to the option's class value in the option database.
+.OP \-activebackground activeBackground Foreground
+Specifies background color to use when drawing active elements.
+An element (a widget or portion of a widget) is active if the
+mouse cursor is positioned over the element and pressing a mouse button
+will cause some action to occur.
+If strict Motif compliance has been requested by setting the
+\fBtk_strictMotif\fR variable, this option will normally be
+ignored; the normal background color will be used instead.
+For some elements on Windows and Macintosh systems, the active color
+will only be used while mouse button 1 is pressed over the element.
+.OP \-activeborderwidth activeBorderWidth BorderWidth
+Specifies a non-negative value indicating
+the width of the 3-D border drawn around active elements. See above for
+definition of active elements.
+The value may have any of the forms acceptable to \fBTk_GetPixels\fR.
+This option is typically only available in widgets displaying more
+than one element at a time (e.g. menus but not buttons).
+.OP \-activeforeground activeForeground Background
+Specifies foreground color to use when drawing active elements.
+See above for definition of active elements.
+.OP \-anchor anchor Anchor
+Specifies how the information in a widget (e.g. text or a bitmap)
+is to be displayed in the widget.
+Must be one of the values \fBn\fR, \fBne\fR, \fBe\fR, \fBse\fR,
+\fBs\fR, \fBsw\fR, \fBw\fR, \fBnw\fR, or \fBcenter\fR.
+For example, \fBnw\fR means display the information such that its
+top-left corner is at the top-left corner of the widget.
+.OP "\-background or \-bg" background Background
+Specifies the normal background color to use when displaying the
+widget.
+.OP \-bitmap bitmap Bitmap
+Specifies a bitmap to display in the widget, in any of the forms
+acceptable to \fBTk_GetBitmap\fR.
+The exact way in which the bitmap is displayed may be affected by
+other options such as \fB\-anchor\fR or \fB\-justify\fR.
+Typically, if this option is specified then it overrides other
+options that specify a textual value to display in the widget
+but this is controlled by the \fB\-compound\fR option;
+the \fB\-bitmap\fR option may be reset to an empty string to re-enable
+a text display.
+In widgets that support both \fB\-bitmap\fR and \fB\-image\fR options,
+\fB\-image\fR will usually override \fB\-bitmap\fR.
+.OP "\-borderwidth or \-bd" borderWidth BorderWidth
+Specifies a non-negative value indicating the width
+of the 3-D border to draw around the outside of the widget (if such a
+border is being drawn; the \fB\-relief\fR option typically determines
+this). The value may also be used when drawing 3-D effects in the
+interior of the widget.
+The value may have any of the forms acceptable to \fBTk_GetPixels\fR.
+.OP \-cursor cursor Cursor
+Specifies the mouse cursor to be used for the widget.
+The value may have any of the forms acceptable to \fBTk_GetCursor\fR.
+In addition, if an empty string is specified, it indicates that the
+widget should defer to its parent for cursor specification.
+.OP \-compound compound Compound
+Specifies if the widget should display text and bitmaps/images at the
+same time, and if so, where the bitmap/image should be placed relative
+to the text. Must be one of the values \fBnone\fR, \fBbottom\fR,
+\fBtop\fR, \fBleft\fR, \fBright\fR, or \fBcenter\fR. For example, the
+(default) value \fBnone\fR specifies that the bitmap or image should
+(if defined) be displayed instead of the text, the value \fBleft\fR
+specifies that the bitmap or image should be displayed to the left of
+the text, and the value \fBcenter\fR specifies that the bitmap or
+image should be displayed on top of the text.
+.OP \-disabledforeground disabledForeground DisabledForeground
+Specifies foreground color to use when drawing a disabled element.
+If the option is specified as an empty string (which is typically the
+case on monochrome displays), disabled elements are drawn with the
+normal foreground color but they are dimmed by drawing them
+with a stippled fill pattern.
+.OP \-exportselection exportSelection ExportSelection
+Specifies whether or not a selection in the widget should also be
+the X selection.
+The value may have any of the forms accepted by \fBTcl_GetBoolean\fR,
+such as \fBtrue\fR, \fBfalse\fR, \fB0\fR, \fB1\fR, \fByes\fR, or \fBno\fR.
+If the selection is exported, then selecting in the widget deselects
+the current X selection, selecting outside the widget deselects any
+widget selection, and the widget will respond to selection retrieval
+requests when it has a selection. The default is usually for widgets
+to export selections.
+.OP \-font font Font
+Specifies the font to use when drawing text inside the widget.
+The value may have any of the forms described in the \fBfont\fR manual
+page under \fBFONT DESCRIPTION\fR.
+.OP "\-foreground or \-fg" foreground Foreground
+Specifies the normal foreground color to use when displaying the widget.
+.OP \-highlightbackground highlightBackground HighlightBackground
+Specifies the color to display in the traversal highlight region when
+the widget does not have the input focus.
+.OP \-highlightcolor highlightColor HighlightColor
+Specifies the color to use for the traversal highlight rectangle that is
+drawn around the widget when it has the input focus.
+.OP \-highlightthickness highlightThickness HighlightThickness
+Specifies a non-negative value indicating the width of the highlight
+rectangle to draw around the outside of the widget when it has the
+input focus.
+The value may have any of the forms acceptable to \fBTk_GetPixels\fR.
+If the value is zero, no focus highlight is drawn around the widget.
+.OP \-image image Image
+Specifies an image to display in the widget, which must have been
+created with the \fBimage create\fR command.
+Typically, if the \fB\-image\fR option is specified then it overrides other
+options that specify a bitmap or textual value to display in the
+widget, though this is controlled by the \fB\-compound\fR option;
+the \fB\-image\fR option may be reset to an empty string to re-enable
+a bitmap or text display.
+.OP \-insertbackground insertBackground Foreground
+Specifies the color to use as background in the area covered by the
+insertion cursor. This color will normally override either the normal
+background for the widget (or the selection background if the insertion
+cursor happens to fall in the selection).
+.OP \-insertborderwidth insertBorderWidth BorderWidth
+Specifies a non-negative value indicating the width
+of the 3-D border to draw around the insertion cursor.
+The value may have any of the forms acceptable to \fBTk_GetPixels\fR.
+.OP \-insertofftime insertOffTime OffTime
+Specifies a non-negative integer value indicating the number of
+milliseconds the insertion cursor should remain
+.QW off
+in each blink cycle.
+If this option is zero then the cursor does not blink: it is on
+all the time.
+.OP \-insertontime insertOnTime OnTime
+Specifies a non-negative integer value indicating the number of
+milliseconds the insertion cursor should remain
+.QW on
+in each blink cycle.
+.OP \-insertwidth insertWidth InsertWidth
+Specifies a value indicating the total width of the insertion cursor.
+The value may have any of the forms acceptable to \fBTk_GetPixels\fR.
+If a border has been specified for the insertion
+cursor (using the \fB\-insertborderwidth\fR option), the border
+will be drawn inside the width specified by the \fB\-insertwidth\fR
+option.
+.OP \-jump jump Jump
+For widgets with a slider that can be dragged to adjust a value,
+such as scrollbars, this option determines when
+notifications are made about changes in the value.
+The option's value must be a boolean of the form accepted by
+\fBTcl_GetBoolean\fR.
+If the value is false, updates are made continuously as the
+slider is dragged.
+If the value is true, updates are delayed until the mouse button
+is released to end the drag; at that point a single notification
+is made (the value
+.QW jumps
+rather than changing smoothly).
+.OP \-justify justify Justify
+When there are multiple lines of text displayed in a widget, this
+option determines how the lines line up with each other.
+Must be one of \fBleft\fR, \fBcenter\fR, or \fBright\fR.
+\fBLeft\fR means that the lines' left edges all line up, \fBcenter\fR
+means that the lines' centers are aligned, and \fBright\fR means
+that the lines' right edges line up.
+.OP \-orient orient Orient
+For widgets that can lay themselves out with either a horizontal
+or vertical orientation, such as scrollbars, this option specifies
+which orientation should be used. Must be either \fBhorizontal\fR
+or \fBvertical\fR or an abbreviation of one of these.
+.OP \-padx padX Pad
+Specifies a non-negative value indicating how much extra space
+to request for the widget in the X-direction.
+The value may have any of the forms acceptable to \fBTk_GetPixels\fR.
+When computing how large a window it needs, the widget will
+add this amount to the width it would normally need (as determined
+by the width of the things displayed in the widget); if the geometry
+manager can satisfy this request, the widget will end up with extra
+internal space to the left and/or right of what it displays inside.
+Most widgets only use this option for padding text: if they are
+displaying a bitmap or image, then they usually ignore padding
+options.
+.OP \-pady padY Pad
+Specifies a non-negative value indicating how much extra space
+to request for the widget in the Y-direction.
+The value may have any of the forms acceptable to \fBTk_GetPixels\fR.
+When computing how large a window it needs, the widget will add
+this amount to the height it would normally need (as determined by
+the height of the things displayed in the widget); if the geometry
+manager can satisfy this request, the widget will end up with extra
+internal space above and/or below what it displays inside.
+Most widgets only use this option for padding text: if they are
+displaying a bitmap or image, then they usually ignore padding
+options.
+.OP \-relief relief Relief
+Specifies the 3-D effect desired for the widget. Acceptable
+values are \fBraised\fR, \fBsunken\fR, \fBflat\fR, \fBridge\fR,
+\fBsolid\fR, and \fBgroove\fR.
+The value
+indicates how the interior of the widget should appear relative
+to its exterior; for example, \fBraised\fR means the interior of
+the widget should appear to protrude from the screen, relative to
+the exterior of the widget.
+.OP \-repeatdelay repeatDelay RepeatDelay
+Specifies the number of milliseconds a button or key must be held
+down before it begins to auto-repeat. Used, for example, on the
+up- and down-arrows in scrollbars.
+.OP \-repeatinterval repeatInterval RepeatInterval
+Used in conjunction with \fB\-repeatdelay\fR: once auto-repeat
+begins, this option determines the number of milliseconds between
+auto-repeats.
+.OP \-selectbackground selectBackground Foreground
+Specifies the background color to use when displaying selected
+items.
+.OP \-selectborderwidth selectBorderWidth BorderWidth
+Specifies a non-negative value indicating the width
+of the 3-D border to draw around selected items.
+The value may have any of the forms acceptable to \fBTk_GetPixels\fR.
+.OP \-selectforeground selectForeground Background
+Specifies the foreground color to use when displaying selected
+items.
+.OP \-setgrid setGrid SetGrid
+Specifies a boolean value that determines whether this widget controls the
+resizing grid for its top-level window.
+This option is typically used in text widgets, where the information
+in the widget has a natural size (the size of a character) and it makes
+sense for the window's dimensions to be integral numbers of these units.
+These natural window sizes form a grid.
+If the \fB\-setgrid\fR option is set to true then the widget will
+communicate with the window manager so that when the user interactively
+resizes the top-level window that contains the widget, the dimensions of
+the window will be displayed to the user in grid units and the window
+size will be constrained to integral numbers of grid units.
+See the section \fBGRIDDED GEOMETRY MANAGEMENT\fR in the \fBwm\fR manual
+entry for more details.
+.OP \-takefocus takeFocus TakeFocus
+Determines whether the window accepts the focus during keyboard
+traversal (e.g., Tab and Shift-Tab).
+Before setting the focus to a window, the traversal scripts
+consult the value of the \fB\-takefocus\fR option.
+A value of \fB0\fR means that the window should be skipped entirely
+during keyboard traversal.
+\fB1\fR means that the window should receive the input
+focus as long as it is viewable (it and all of its ancestors are mapped).
+An empty value for the option means that the traversal scripts make
+the decision about whether or not to focus on the window: the current
+algorithm is to skip the window if it is
+disabled, if it has no key bindings, or if it is not viewable.
+If the value has any other form, then the traversal scripts take
+the value, append the name of the window to it (with a separator space),
+and evaluate the resulting string as a Tcl script.
+The script must return \fB0\fR, \fB1\fR, or an empty string: a
+\fB0\fR or \fB1\fR value specifies whether the window will receive
+the input focus, and an empty string results in the default decision
+described above.
+Note: this interpretation of the option is defined entirely by
+the Tcl scripts that implement traversal: the widget implementations
+ignore the option entirely, so you can change its meaning if you
+redefine the keyboard traversal scripts.
+.OP \-text text Text
+Specifies a string to be displayed inside the widget. The way in which
+the string is displayed depends on the particular widget and may be
+determined by other options, such as \fB\-anchor\fR or \fB\-justify\fR.
+.OP \-textvariable textVariable Variable
+Specifies the name of a global variable. The value of the variable is a text
+string to be displayed inside the widget; if the variable value changes
+then the widget will automatically update itself to reflect the new value.
+The way in which the string is displayed in the widget depends on the
+particular widget and may be determined by other options, such as
+\fB\-anchor\fR or \fB\-justify\fR.
+.OP \-troughcolor troughColor Background
+Specifies the color to use for the rectangular trough areas
+in widgets such as scrollbars and scales. This option is ignored for
+scrollbars on Windows (native widget does not recognize this option).
+.OP \-underline underline Underline
+Specifies the integer index of a character to underline in the widget.
+This option is used by the default bindings to implement keyboard
+traversal for menu buttons and menu entries.
+0 corresponds to the first character of the text displayed in the
+widget, 1 to the next character, and so on.
+.OP \-wraplength wrapLength WrapLength
+For widgets that can perform word-wrapping, this option specifies
+the maximum line length.
+Lines that would exceed this length are wrapped onto the next line,
+so that no line is longer than the specified length.
+The value may be specified in any of the standard forms for
+screen distances.
+If this value is less than or equal to 0 then no wrapping is done: lines
+will break only at newline characters in the text.
+.OP \-xscrollcommand xScrollCommand ScrollCommand
+Specifies the prefix for a command used to communicate with horizontal
+scrollbars.
+When the view in the widget's window changes (or
+whenever anything else occurs that could change the display in a
+scrollbar, such as a change in the total size of the widget's
+contents), the widget will
+generate a Tcl command by concatenating the scroll command and
+two numbers.
+Each of the numbers is a fraction between 0 and 1, which indicates
+a position in the document. 0 indicates the beginning of the document,
+1 indicates the end, .333 indicates a position one third the way through
+the document, and so on.
+The first fraction indicates the first information in the document
+that is visible in the window, and the second fraction indicates
+the information just after the last portion that is visible.
+The command is
+then passed to the Tcl interpreter for execution. Typically the
+\fB\-xscrollcommand\fR option consists of the path name of a scrollbar
+widget followed by
+.QW set ,
+e.g.
+.QW ".x.scrollbar set" :
+this will cause
+the scrollbar to be updated whenever the view in the window changes.
+If this option is not specified, then no command will be executed.
+.OP \-yscrollcommand yScrollCommand ScrollCommand
+Specifies the prefix for a command used to communicate with vertical
+scrollbars. This option is treated in the same way as the
+\fB\-xscrollcommand\fR option, except that it is used for vertical
+scrollbars and is provided by widgets that support vertical scrolling.
+See the description of \fB\-xscrollcommand\fR for details
+on how this option is used.
+.SH "SEE ALSO"
+colors, cursors, font
+.SH KEYWORDS
+class, name, standard option, switch
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/pack-old.n b/tk8.6/doc/pack-old.n
new file mode 100644
index 0000000..217dba9
--- /dev/null
+++ b/tk8.6/doc/pack-old.n
@@ -0,0 +1,195 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH pack-old n 4.0 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+pack-old \- Obsolete syntax for packer geometry manager
+.SH SYNOPSIS
+\fBpack after \fIsibling \fIwindow options\fR ?\fIwindow options \fR...?
+.sp
+\fBpack append \fIparent \fIwindow options\fR ?\fIwindow options \fR...?
+.sp
+\fBpack before \fIsibling \fIwindow options\fR ?\fIwindow options \fR...?
+.sp
+\fBpack unpack \fIwindow\fR
+.BE
+.SH DESCRIPTION
+.PP
+\fINote: this manual entry describes the syntax for the \fBpack\fI
+command as it existed before Tk version 3.3.
+Although this syntax continues to be supported for backward
+compatibility, it is obsolete and should not be used anymore.
+At some point in the future it may cease to be supported.\fR
+.PP
+The packer is a geometry manager that arranges the
+children of a parent by packing them in order around the edges of
+the parent. The first child is placed against one side of
+the window, occupying the entire span of the window along that
+side. This reduces the space remaining for other children as
+if the side had been moved in by the size of the first child.
+Then the next child is placed against one side of the remaining
+cavity, and so on until all children have been placed or there
+is no space left in the cavity.
+.PP
+The \fBbefore\fR, \fBafter\fR, and \fBappend\fR forms of the \fBpack\fR
+command are used to insert one or more children into the packing order
+for their parent. The \fBbefore\fR form inserts the children before
+window \fIsibling\fR in the order; all of the other windows must be
+siblings of \fIsibling\fR. The \fBafter\fR form inserts the windows
+after \fIsibling\fR, and the \fBappend\fR form appends one or more
+windows to the end of the packing order for \fIparent\fR. If a
+\fIwindow\fR named in any of these commands is already packed in
+its parent, it is removed from its current position in the packing
+order and repositioned as indicated by the command. All of these
+commands return an empty string as result.
+.PP
+The \fBunpack\fR form of the \fBpack\fR command removes \fIwindow\fR
+from the packing order of its parent and unmaps it. After the
+execution of this command the packer will no longer manage
+\fIwindow\fR's geometry.
+.PP
+The placement of each child is actually a four-step process;
+the \fIoptions\fR argument following each \fIwindow\fR consists of
+a list of one or more fields that govern the placement of that
+window. In the discussion below, the term \fIcavity\fR refers
+to the space left in a parent when a particular child is placed
+(i.e. all the space that was not claimed by earlier children in
+the packing order). The term \fIparcel\fR refers to the space
+allocated to a particular child; this is not necessarily the
+same as the child window's final geometry.
+.PP
+The first step in placing a child is to determine which side of
+the cavity it will lie against. Any one of the following options
+may be used to specify a side:
+.TP
+\fBtop\fR
+Position the child's parcel against the top of the cavity,
+occupying the full width of the cavity.
+.TP
+\fBbottom\fR
+Position the child's parcel against the bottom of the cavity,
+occupying the full width of the cavity.
+.TP
+\fBleft\fR
+Position the child's parcel against the left side of the cavity,
+occupying the full height of the cavity.
+.TP
+\fBright\fR
+Position the child's parcel against the right side of the cavity,
+occupying the full height of the cavity.
+.LP
+At most one of these options should be specified for any given window.
+If no side is specified, then the default is \fBtop\fR.
+.PP
+The second step is to decide on a parcel for the child. For \fBtop\fR
+and \fBbottom\fR windows, the desired parcel width is normally the cavity
+width and the desired parcel height is the window's requested height,
+as passed to \fBTk_GeometryRequest\fR. For \fBleft\fR and \fBright\fR
+windows, the desired parcel height is normally the cavity height and the
+desired width is the window's requested width. However, extra
+space may be requested for the window using any of the following
+options:
+.TP 12
+\fBpadx \fInum\fR
+Add \fInum\fR pixels to the window's requested width before computing
+the parcel size as described above.
+.TP 12
+\fBpady \fInum\fR
+Add \fInum\fR pixels to the window's requested height before computing
+the parcel size as described above.
+.TP 12
+\fBexpand\fR
+This option requests that the window's parcel absorb any extra space left over
+in the parent's cavity after packing all the children.
+The amount of space left over depends on the sizes requested by the
+other children, and may be zero. If several windows have all specified
+\fBexpand\fR then the extra width will be divided equally among all the
+\fBleft\fR and \fBright\fR windows that specified \fBexpand\fR and
+the extra height will be divided equally among all the \fBtop\fR and
+\fBbottom\fR windows that specified \fBexpand\fR.
+.LP
+If the desired width or height for a parcel is larger than the corresponding
+dimension of the cavity, then the cavity's dimension is used instead.
+.PP
+The third step in placing the window is to decide on the window's
+width and height. The default is for the window to receive either
+its requested width and height or the those of the parcel, whichever
+is smaller. If the parcel is larger than the window's requested
+size, then the following options may be used to expand the
+window to partially or completely fill the parcel:
+.TP
+\fBfill\fR
+Set the window's size to equal the parcel size.
+.TP
+\fBfillx\fR
+Increase the window's width to equal the parcel's width, but retain
+the window's requested height.
+.TP
+\fBfilly\fR
+Increase the window's height to equal the parcel's height, but retain
+the window's requested width.
+.PP
+The last step is to decide the window's location within its parcel.
+If the window's size equals the parcel's size, then the window simply
+fills the entire parcel. If the parcel is larger than the window,
+then one of
+the following options may be used to specify where the window should
+be positioned within its parcel:
+.TP 15
+\fBframe center\fR
+Center the window in its parcel. This is the default if no framing
+option is specified.
+.TP 15
+\fBframe n\fR
+Position the window with its top edge centered on the top edge of
+the parcel.
+.TP 15
+\fBframe ne\fR
+Position the window with its upper-right corner at the upper-right corner
+of the parcel.
+.TP 15
+\fBframe e\fR
+Position the window with its right edge centered on the right edge of
+the parcel.
+.TP 15
+\fBframe se\fR
+Position the window with its lower-right corner at the lower-right corner
+of the parcel.
+.TP 15
+\fBframe s\fR
+Position the window with its bottom edge centered on the bottom edge of
+the parcel.
+.TP 15
+\fBframe sw\fR
+Position the window with its lower-left corner at the lower-left corner
+of the parcel.
+.TP 15
+\fBframe w\fR
+Position the window with its left edge centered on the left edge of
+the parcel.
+.TP 15
+\fBframe nw\fR
+Position the window with its upper-left corner at the upper-left corner
+of the parcel.
+.PP
+The packer manages the mapped/unmapped state of all the packed
+children windows. It automatically maps the windows when it packs
+them, and it unmaps any windows for which there was no space left
+in the cavity.
+.PP
+The packer makes geometry requests on behalf of the parent windows
+it manages. For each parent window it requests a size large enough
+to accommodate all the options specified by all the packed children,
+such that zero space would be leftover for \fBexpand\fR options.
+.SH KEYWORDS
+geometry manager, location, packer, parcel, size
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/pack.n b/tk8.6/doc/pack.n
new file mode 100644
index 0000000..538af62
--- /dev/null
+++ b/tk8.6/doc/pack.n
@@ -0,0 +1,283 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH pack n 4.0 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+pack \- Geometry manager that packs around edges of cavity
+.SH SYNOPSIS
+\fBpack \fIoption arg \fR?\fIarg ...\fR?
+.BE
+.SH DESCRIPTION
+.PP
+The \fBpack\fR command is used to communicate with the packer,
+a geometry manager that arranges the children of a parent by
+packing them in order around the edges of the parent.
+The \fBpack\fR command can have any of several forms, depending
+on the \fIoption\fR argument:
+.TP
+\fBpack \fIslave \fR?\fIslave ...\fR? ?\fIoptions\fR?
+If the first argument to \fBpack\fR is a window name (any value
+starting with
+.QW . ),
+then the command is processed in the same way as \fBpack configure\fR.
+.TP
+\fBpack configure \fIslave \fR?\fIslave ...\fR? ?\fIoptions\fR?
+The arguments consist of the names of one or more slave windows
+followed by pairs of arguments that specify how
+to manage the slaves.
+See \fBTHE PACKER ALGORITHM\fR below for details on how the options
+are used by the packer.
+The following options are supported:
+.RS
+.TP
+\fB\-after \fIother\fR
+\fIOther\fR must the name of another window.
+Use its master as the master for the slaves, and insert
+the slaves just after \fIother\fR in the packing order.
+.TP
+\fB\-anchor \fIanchor\fR
+\fIAnchor\fR must be a valid anchor position such as \fBn\fR
+or \fBsw\fR; it specifies where to position each slave in its
+parcel.
+Defaults to \fBcenter\fR.
+.TP
+\fB\-before \fIother\fR
+\fIOther\fR must the name of another window.
+Use its master as the master for the slaves, and insert
+the slaves just before \fIother\fR in the packing order.
+.TP
+\fB\-expand \fIboolean\fR
+Specifies whether the slaves should be expanded to consume
+extra space in their master.
+\fIBoolean\fR may have any proper boolean value, such as \fB1\fR
+or \fBno\fR.
+Defaults to 0.
+.TP
+\fB\-fill \fIstyle\fR
+If a slave's parcel is larger than its requested dimensions, this
+option may be used to stretch the slave.
+\fIStyle\fR must have one of the following values:
+.RS
+.TP
+\fBnone\fR
+Give the slave its requested dimensions plus any internal padding
+requested with \fB\-ipadx\fR or \fB\-ipady\fR. This is the default.
+.TP
+\fBx\fR
+Stretch the slave horizontally to fill the entire width of its
+parcel (except leave external padding as specified by \fB\-padx\fR).
+.TP
+\fBy\fR
+Stretch the slave vertically to fill the entire height of its
+parcel (except leave external padding as specified by \fB\-pady\fR).
+.TP
+\fBboth\fR
+Stretch the slave both horizontally and vertically.
+.RE
+.TP
+\fB\-in \fIother\fR
+Insert the slave(s) at the end of the packing order for the master
+window given by \fIother\fR.
+.TP
+\fB\-ipadx \fIamount\fR
+\fIAmount\fR specifies how much horizontal internal padding to
+leave on each side of the slave(s).
+\fIAmount\fR must be a valid screen distance, such as \fB2\fR or \fB.5c\fR.
+It defaults to 0.
+.TP
+\fB\-ipady \fIamount\fR
+\fIAmount\fR specifies how much vertical internal padding to
+leave on each side of the slave(s).
+\fIAmount\fR defaults to 0.
+.TP
+\fB\-padx \fIamount\fR
+\fIAmount\fR specifies how much horizontal external padding to
+leave on each side of the slave(s). \fIAmount\fR may be a list
+of two values to specify padding for left and right separately.
+\fIAmount\fR defaults to 0.
+.TP
+\fB\-pady \fIamount\fR
+\fIAmount\fR specifies how much vertical external padding to
+leave on each side of the slave(s). \fIAmount\fR may be a list
+of two values to specify padding for top and bottom separately.
+\fIAmount\fR defaults to 0.
+.TP
+\fB\-side \fIside\fR
+Specifies which side of the master the slave(s) will be packed against.
+Must be \fBleft\fR, \fBright\fR, \fBtop\fR, or \fBbottom\fR.
+Defaults to \fBtop\fR.
+.LP
+If no \fB\-in\fR, \fB\-after\fR or \fB\-before\fR option is specified
+then each of the slaves will be inserted at the end of the packing list
+for its parent unless it is already managed by the packer (in which
+case it will be left where it is).
+If one of these options is specified then all the slaves will be
+inserted at the specified point.
+If any of the slaves are already managed by the geometry manager
+then any unspecified options for them retain their previous values rather
+than receiving default values.
+.RE
+.TP
+\fBpack forget \fIslave \fR?\fIslave ...\fR?
+Removes each of the \fIslave\fRs from the packing order for its
+master and unmaps their windows.
+The slaves will no longer be managed by the packer.
+.TP
+\fBpack info \fIslave\fR
+Returns a list whose elements are the current configuration state of
+the slave given by \fIslave\fR in the same option-value form that
+might be specified to \fBpack configure\fR.
+The first two elements of the list are
+.QW "\fB\-in \fImaster\fR"
+where \fImaster\fR is the slave's master.
+.TP
+\fBpack propagate \fImaster\fR ?\fIboolean\fR?
+If \fIboolean\fR has a true boolean value such as \fB1\fR or \fBon\fR
+then propagation is enabled for \fImaster\fR, which must be a window
+name (see \fBGEOMETRY PROPAGATION\fR below).
+If \fIboolean\fR has a false boolean value then propagation is
+disabled for \fImaster\fR.
+In either of these cases an empty string is returned.
+If \fIboolean\fR is omitted then the command returns \fB0\fR or
+\fB1\fR to indicate whether propagation is currently enabled
+for \fImaster\fR.
+Propagation is enabled by default.
+.TP
+\fBpack slaves \fImaster\fR
+Returns a list of all of the slaves in the packing order for \fImaster\fR.
+The order of the slaves in the list is the same as their order in
+the packing order.
+If \fImaster\fR has no slaves then an empty string is returned.
+.SH "THE PACKER ALGORITHM"
+.PP
+For each master the packer maintains an ordered list of slaves
+called the \fIpacking list\fR.
+The \fB\-in\fR, \fB\-after\fR, and \fB\-before\fR configuration
+options are used to specify the master for each slave and the slave's
+position in the packing list.
+If none of these options is given for a slave then the slave
+is added to the end of the packing list for its parent.
+.PP
+The packer arranges the slaves for a master by scanning the
+packing list in order.
+At the time it processes each slave, a rectangular area within
+the master is still unallocated.
+This area is called the \fIcavity\fR; for the first slave it
+is the entire area of the master.
+.PP
+For each slave the packer carries out the following steps:
+.IP [1]
+The packer allocates a rectangular \fIparcel\fR for the slave
+along the side of the cavity given by the slave's \fB\-side\fR option.
+If the side is top or bottom then the width of the parcel is
+the width of the cavity and its height is the requested height
+of the slave plus the \fB\-ipady\fR and \fB\-pady\fR options.
+For the left or right side the height of the parcel is
+the height of the cavity and the width is the requested width
+of the slave plus the \fB\-ipadx\fR and \fB\-padx\fR options.
+The parcel may be enlarged further because of the \fB\-expand\fR
+option (see \fBEXPANSION\fR below)
+.IP [2]
+The packer chooses the dimensions of the slave.
+The width will normally be the slave's requested width plus
+twice its \fB\-ipadx\fR option and the height will normally be
+the slave's requested height plus twice its \fB\-ipady\fR
+option.
+However, if the \fB\-fill\fR option is \fBx\fR or \fBboth\fR
+then the width of the slave is expanded to fill the width of the parcel,
+minus twice the \fB\-padx\fR option.
+If the \fB\-fill\fR option is \fBy\fR or \fBboth\fR
+then the height of the slave is expanded to fill the width of the parcel,
+minus twice the \fB\-pady\fR option.
+.IP [3]
+The packer positions the slave over its parcel.
+If the slave is smaller than the parcel then the \fB\-anchor\fR
+option determines where in the parcel the slave will be placed.
+If \fB\-padx\fR or \fB\-pady\fR is non-zero, then the given
+amount of external padding will always be left between the
+slave and the edges of the parcel.
+.PP
+Once a given slave has been packed, the area of its parcel
+is subtracted from the cavity, leaving a smaller rectangular
+cavity for the next slave.
+If a slave does not use all of its parcel, the unused space
+in the parcel will not be used by subsequent slaves.
+If the cavity should become too small to meet the needs of
+a slave then the slave will be given whatever space is
+left in the cavity.
+If the cavity shrinks to zero size, then all remaining slaves
+on the packing list will be unmapped from the screen until
+the master window becomes large enough to hold them again.
+.SS "EXPANSION"
+.PP
+If a master window is so large that there will be extra space
+left over after all of its slaves have been packed, then the
+extra space is distributed uniformly among all of the slaves
+for which the \fB\-expand\fR option is set.
+Extra horizontal space is distributed among the expandable
+slaves whose \fB\-side\fR is \fBleft\fR or \fBright\fR,
+and extra vertical space is distributed among the expandable
+slaves whose \fB\-side\fR is \fBtop\fR or \fBbottom\fR.
+.SS "GEOMETRY PROPAGATION"
+.PP
+The packer normally computes how large a master must be to
+just exactly meet the needs of its slaves, and it sets the
+requested width and height of the master to these dimensions.
+This causes geometry information to propagate up through a
+window hierarchy to a top-level window so that the entire
+sub-tree sizes itself to fit the needs of the leaf windows.
+However, the \fBpack propagate\fR command may be used to
+turn off propagation for one or more masters.
+If propagation is disabled then the packer will not set
+the requested width and height of the packer.
+This may be useful if, for example, you wish for a master
+window to have a fixed size that you specify.
+.SH "RESTRICTIONS ON MASTER WINDOWS"
+.PP
+The master for each slave must either be the slave's parent
+(the default) or a descendant of the slave's parent.
+This restriction is necessary to guarantee that the
+slave can be placed over any part of its master that is
+visible without danger of the slave being clipped by its parent.
+.SH "PACKING ORDER"
+.PP
+If the master for a slave is not its parent then you must make sure
+that the slave is higher in the stacking order than the master.
+Otherwise the master will obscure the slave and it will appear as
+if the slave has not been packed correctly.
+The easiest way to make sure the slave is higher than the master is
+to create the master window first: the most recently created window
+will be highest in the stacking order.
+Or, you can use the \fBraise\fR and \fBlower\fR commands to change
+the stacking order of either the master or the slave.
+.SH EXAMPLE
+.PP
+.CS
+# Make the widgets
+label .t \-text "This widget is at the top" \-bg red
+label .b \-text "This widget is at the bottom" \-bg green
+label .l \-text "Left\enHand\enSide"
+label .r \-text "Right\enHand\enSide"
+text .mid
+\&.mid insert end "This layout is like Java's BorderLayout"
+# Lay them out
+\fBpack\fR .t \-side top \-fill x
+\fBpack\fR .b \-side bottom \-fill x
+\fBpack\fR .l \-side left \-fill y
+\fBpack\fR .r \-side right \-fill y
+\fBpack\fR .mid \-expand 1 \-fill both
+.CE
+.SH "SEE ALSO"
+grid(n), place(n)
+.SH KEYWORDS
+geometry manager, location, packer, parcel, propagation, size
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/palette.n b/tk8.6/doc/palette.n
new file mode 100644
index 0000000..085c4c6
--- /dev/null
+++ b/tk8.6/doc/palette.n
@@ -0,0 +1,73 @@
+'\"
+'\" 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.
+'\"
+.TH tk_setPalette n 4.0 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+tk_setPalette, tk_bisque \- Modify the Tk color palette
+.SH SYNOPSIS
+\fBtk_setPalette \fIbackground\fR
+.sp
+\fBtk_setPalette \fIname value \fR?\fIname value ...\fR?
+.sp
+\fBtk_bisque\fR
+.BE
+.SH DESCRIPTION
+.PP
+The \fBtk_setPalette\fR procedure changes the color scheme for Tk.
+It does this by modifying the colors of existing widgets and by changing
+the option database so that future widgets will use the new color scheme.
+If \fBtk_setPalette\fR is invoked with a single argument, the
+argument is the name of a color to use as the normal background
+color; \fBtk_setPalette\fR will compute a complete color palette
+from this background color.
+Alternatively, the arguments to \fBtk_setPalette\fR may consist of any number
+of \fIname\fR\-\fIvalue\fR pairs, where the first argument of the pair
+is the name of an option in the Tk option database and the second
+argument is the new value to use for that option. The following
+database names are currently supported:
+.DS
+.ta 4c 8c
+\fBactiveBackground\fR \fBforeground\fR \fBselectColor\fR
+\fBactiveForeground\fR \fBhighlightBackground\fR \fBselectBackground\fR
+\fBbackground\fR \fBhighlightColor\fR \fBselectForeground\fR
+\fBdisabledForeground\fR \fBinsertBackground\fR \fBtroughColor\fR
+.DE
+\fBtk_setPalette\fR tries to compute reasonable defaults for any
+options that you do not specify. You can specify options other
+than the above ones and Tk will change those options on widgets as
+well. This feature may be useful if you are using custom widgets with
+additional color options.
+.PP
+Once it has computed the new value to use for each of the color options,
+\fBtk_setPalette\fR scans the widget hierarchy to modify the options
+of all existing widgets. For each widget, it checks to see if any
+of the above options is defined for the widget. If so, and if the
+option's current value is the default, then the value is changed; if
+the option has a value other than the default, \fBtk_setPalette\fR
+will not change it. The default for an option is the one provided by
+the widget (\fB[lindex [$w configure $option] 3]\fR) unless
+\fBtk_setPalette\fR has been run previously, in which case it is the
+value specified in the previous invocation of \fBtk_setPalette\fR.
+.PP
+After modifying all the widgets in the application, \fBtk_setPalette\fR
+adds options to the option database to change the defaults for
+widgets created in the future. The new options are added at
+priority \fBwidgetDefault\fR, so they will be overridden by options
+from the .Xdefaults file or options specified on the command-line
+that creates a widget.
+.PP
+The procedure \fBtk_bisque\fR is provided for backward compatibility:
+it restores the application's colors to the light brown
+.PQ bisque
+color scheme used in Tk 3.6 and earlier versions.
+.SH KEYWORDS
+bisque, color, palette
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/panedwindow.n b/tk8.6/doc/panedwindow.n
new file mode 100644
index 0000000..9fc2b72
--- /dev/null
+++ b/tk8.6/doc/panedwindow.n
@@ -0,0 +1,347 @@
+'\"
+'\" Copyright (c) 1992 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH panedwindow n 8.4 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+panedwindow \- Create and manipulate 'panedwindow' split container widgets
+.SH SYNOPSIS
+\fBpanedwindow\fR \fIpathName \fR?\fIoptions\fR?
+.SO
+\-background \-borderwidth \-cursor
+\-orient \-relief
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-handlepad handlePad HandlePad
+When sash handles are drawn, specifies the distance from the top or
+left end of the sash (depending on the orientation of the widget) at
+which to draw the handle. May be any value accepted by \fBTk_GetPixels\fR.
+.OP \-handlesize handleSize HandleSize
+Specifies the side length of a sash handle. Handles are always
+drawn as squares. May be any value accepted by \fBTk_GetPixels\fR.
+.OP \-height height Height
+Specifies a desired height for the overall panedwindow widget. May be any
+value accepted by \fBTk_GetPixels\fR. If an empty string, the widget will be
+made high enough to allow all contained widgets to have their natural height.
+.OP \-opaqueresize opaqueResize OpaqueResize
+Specifies whether panes should be resized as a sash is moved (true),
+or if resizing should be deferred until the sash is placed (false).
+In the latter case, a
+.QW ghost
+version of the sash is displayed during the resizing to show where the
+panes will be resized to when releasing the mouse button. This
+.QW ghost
+version of the sash is the proxy. It's rendering can be configured
+using the \fB-proxybackground\fR, \fB-proxyborderwidth\fR and
+\fB-proxyrelief\fR options.
+.OP \-proxybackground proxyBackground ProxyBackground
+Background color to use when drawing the proxy. If an empty string, the
+value of the \fB-background\fR option will be used.
+.OP \-proxyborderwidth proxyBorderWidth ProxyBorderWidth
+Specifies the borderwidth of the proxy. May be any value accepted by
+\fBTk_GetPixels\fR.
+.OP \-proxyrelief proxyRelief ProxyRelief
+Relief to use when drawing the proxy. May be any of the standard Tk
+relief values. If an empty string, the value of the \fB-sashrelief\fR
+option will be used.
+.OP \-sashcursor sashCursor SashCursor
+Mouse cursor to use when over a sash. If null,
+\fBsb_h_double_arrow\fR will be used for horizontal panedwindows, and
+\fBsb_v_double_arrow\fR will be used for vertical panedwindows.
+.OP \-sashpad sashPad SashPad
+Specifies the amount of padding to leave of each side of a sash. May
+be any value accepted by \fBTk_GetPixels\fR.
+.OP \-sashrelief sashRelief SashRelief
+Relief to use when drawing a sash. May be any of the standard Tk
+relief values.
+.OP \-sashwidth sashWidth SashWidth
+Specifies the width of each sash. May be any value accepted by
+\fBTk_GetPixels\fR.
+.OP \-showhandle showHandle ShowHandle
+Specifies whether sash handles should be shown. May be any valid Tcl
+boolean value.
+.OP \-width width Width
+Specifies a desired width for the overall panedwindow widget. May be any
+value accepted by \fBTk_GetPixels\fR. If an empty string, the widget will be
+made wide enough to allow all contained widgets to have their natural width.
+.BE
+.SH DESCRIPTION
+.PP
+The \fBpanedwindow\fR command creates a new window (given by the
+\fIpathName\fR argument) and makes it into a panedwindow widget.
+Additional options, described above, may be specified on the command
+line or in the option database to configure aspects of the panedwindow
+such as its default background color and relief. The
+\fBpanedwindow\fR command returns the path name of the new window.
+.PP
+A panedwindow widget contains any number of panes, arranged
+horizontally or vertically, according to the value of the
+\fB\-orient\fR option. Each pane contains one widget, and each pair of
+panes is separated by a moveable (via mouse movements) sash. Moving a
+sash causes the widgets on either side of the sash to be resized.
+.SH "WIDGET COMMAND"
+.PP
+The \fBpanedwindow\fR command creates a new Tcl command whose name is
+the same as the path name of the panedwindow's window. This command
+may be used to invoke various operations on the widget. It has the
+following general form:
+.CS
+\fIpathName option \fR?\fIarg arg ...\fR?
+.CE
+\fIPathName\fR is the name of the command, which is the same as
+the panedwindow widget's path name. \fIOption\fR and the \fIarg\fRs
+determine the exact behavior of the command. The following
+commands are possible for panedwindow widgets:
+.TP
+\fIpathName \fBadd \fIwindow \fR?\fIwindow ...\fR? ?\fIoption value ...\fR?
+.
+Add one or more windows to the panedwindow, each in a separate pane.
+The arguments consist of the names of one or more windows
+followed by pairs of arguments that specify how to manage the windows.
+\fIOption\fR may have any of the values accepted by the
+\fBconfigure\fR subcommand.
+.TP
+\fIpathName \fBcget \fIoption\fR
+.
+Returns the current value of the configuration option given by
+\fIoption\fR. \fIOption\fR may have any of the values accepted by the
+\fBpanedwindow\fR command.
+.TP
+\fIpathName \fBconfigure \fR?\fIoption\fR? ?\fIvalue option value ...\fR?
+.
+Query or modify the configuration options of the widget. If no
+\fIoption\fR is specified, returns a list describing all of the
+available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for
+information on the format of this list). If \fIoption\fR is specified
+with no \fIvalue\fR, then the command returns a list describing the
+one named option (this list will be identical to the corresponding
+sublist of the value returned if no \fIoption\fR is specified). If
+one or more \fIoption\-value\fR pairs are specified, then the command
+modifies the given widget option(s) to have the given value(s); in
+this case the command returns an empty string. \fIOption\fR may have
+any of the values accepted by the \fBpanedwindow\fR command.
+.TP
+\fIpathName \fBforget \fIwindow \fR?\fIwindow ...\fR?
+.
+Remove the pane containing \fIwindow\fR from the panedwindow. All
+geometry management options for \fIwindow\fR will be forgotten.
+.TP
+\fIpathName \fBidentify \fIx y\fR
+.
+Identify the panedwindow component underneath the point given by
+\fIx\fR and \fIy\fR, in window coordinates. If the point is over a
+sash or a sash handle, the result is a two element list containing the
+index of the sash or handle, and a word indicating whether it is over
+a sash or a handle, such as {0 sash} or {2 handle}. If the point is
+over any other part of the panedwindow, the result is an empty list.
+.TP
+\fIpathName \fBpanecget \fIwindow option\fR
+.
+Query a management option for \fIwindow\fR. \fIOption\fR may be any
+value allowed by the \fBpaneconfigure\fR subcommand.
+.TP
+\fIpathName \fBpaneconfigure \fIwindow \fR?\fIoption\fR? ?\fIvalue option value ...\fR?
+.
+Query or modify the management options for \fIwindow\fR. If no
+\fIoption\fR is specified, returns a list describing all of the
+available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for
+information on the format of this list). If \fIoption\fR is specified
+with no \fIvalue\fR, then the command returns a list describing the
+one named option (this list will be identical to the corresponding
+sublist of the value returned if no \fIoption\fR is specified). If
+one or more \fIoption\-value\fR pairs are specified, then the command
+modifies the given widget option(s) to have the given value(s); in
+this case the command returns an empty string. The following options
+are supported:
+.RS
+.TP
+\fB\-after \fIwindow\fR
+.
+Insert the window after the window specified. \fIwindow\fR should be the
+name of a window already managed by \fIpathName\fR.
+.TP
+\fB\-before \fIwindow\fR
+.
+Insert the window before the window specified. \fIwindow\fR should be
+the name of a window already managed by \fIpathName\fR.
+.TP
+\fB\-height \fIsize\fR
+.
+Specify a height for the window. The height will be the outer
+dimension of the window including its border, if any. If \fIsize\fR
+is an empty string, or if \fB\-height\fR is not specified, then the
+height requested internally by the window will be used initially; the
+height may later be adjusted by the movement of sashes in the
+panedwindow. \fISize\fR may be any value accepted by \fBTk_GetPixels\fR.
+.TP
+\fB\-hide \fIboolean\fR
+.
+Controls the visibility of a pane. When the \fIboolean\fR is true
+(according to \fBTcl_GetBoolean\fR) the pane will not be visible, but
+it will still be maintained in the list of panes.
+.TP
+\fB\-minsize \fIn\fR
+.
+Specifies that the size of the window cannot be made less than
+\fIn\fR. This constraint only affects the size of the widget in the
+paned dimension \(em the x dimension for horizontal panedwindows, the y
+dimension for vertical panedwindows. May be any value accepted by
+\fBTk_GetPixels\fR.
+.TP
+\fB\-padx \fIn\fR
+.
+Specifies a non-negative value indicating how much extra space to
+leave on each side of the window in the X-direction. The value may
+have any of the forms accepted by \fBTk_GetPixels\fR.
+.TP
+\fB\-pady \fIn\fR
+.
+Specifies a non-negative value indicating how much extra space to
+leave on each side of the window in the Y-direction. The value may
+have any of the forms accepted by \fBTk_GetPixels\fR.
+.TP
+\fB\-sticky \fIstyle\fR
+.
+If a window's pane is larger than the requested dimensions of the
+window, this option may be used to position (or stretch) the window
+within its pane. \fIStyle\fR is a string that contains zero or more
+of the characters \fBn\fR, \fBs\fR, \fBe\fR or \fBw\fR. The string
+can optionally contains spaces or commas, but they are ignored. Each
+letter refers to a side (north, south, east, or west) that the window
+will
+.QW stick
+to. If both \fBn\fR and \fBs\fR (or \fBe\fR and \fBw\fR)
+are specified, the window will be stretched to fill the entire height
+(or width) of its cavity.
+.TP
+\fB\-stretch \fIwhen\fR
+.
+Controls how extra space is allocated to each of the panes.
+\fIWhen\fR is one of \fBalways\fR, \fBfirst\fR, \fBlast\fR,
+\fBmiddle\fR, and \fBnever\fR.
+The panedwindow will calculate the required size of all its panes. Any
+remaining (or deficit) space will be distributed to those panes marked
+for stretching. The space will be distributed based on each panes
+current ratio of the whole. The \fIwhen\fR values have the following
+definition:
+.RS
+.TP
+\fBalways\fR
+.
+This pane will always stretch.
+.TP
+\fBfirst\fR
+.
+Only if this pane is the first pane (left-most or top-most) will it
+stretch.
+.TP
+\fBlast\fR
+.
+Only if this pane is the last pane (right-most or bottom-most) will it
+stretch. This is the default value.
+.TP
+\fBmiddle\fR
+.
+Only if this pane is not the first or last pane will it stretch.
+.TP
+\fBnever\fR
+.
+This pane will never stretch.
+.RE
+.TP
+\fB\-width \fIsize\fR
+.
+Specify a width for the window. The width will be the outer
+dimension of the window including its border, if any. If \fIsize\fR
+is an empty string, or if \fB\-width\fR is not specified, then the
+width requested internally by the window will be used initially; the
+width may later be adjusted by the movement of sashes in the
+panedwindow. \fISize\fR may be any value accepted by \fBTk_GetPixels\fR.
+.RE
+.TP
+\fIpathName \fBpanes\fR
+.
+Returns an ordered list of the widgets managed by \fIpathName\fR.
+.TP
+\fIpathName \fBproxy \fR?\fIargs\fR?
+.
+This command is used to query and change the position of the sash
+proxy, used for rubberband-style pane resizing. It can take any of
+the following forms:
+.RS
+.TP
+\fIpathName \fBproxy coord\fR
+.
+Return a list containing the x and y coordinates of the most recent
+proxy location.
+.TP
+\fIpathName \fBproxy forget\fR
+.
+Remove the proxy from the display.
+.TP
+\fIpathName \fBproxy place \fIx y\fR
+.
+Place the proxy at the given \fIx\fR and \fIy\fR coordinates.
+.RE
+.TP
+\fIpathName \fBsash \fR?\fIargs\fR?
+This command is used to query and change the position of sashes in the
+panedwindow. It can take any of the following forms:
+.RS
+.TP
+\fIpathName \fBsash coord \fIindex\fR
+.
+Return the current x and y coordinate pair for the sash given by
+\fIindex\fR. \fIIndex\fR must be an integer between 0 and 1 less than
+the number of panes in the panedwindow. The coordinates given are
+those of the top left corner of the region containing the sash.
+.TP
+\fIpathName \fBsash dragto \fIindex x y\fR
+.
+This command computes the difference between the given coordinates and the
+coordinates given to the last \fBsash mark\fR command for the given
+sash. It then moves that sash the computed difference. The return
+value is the empty string.
+.TP
+\fIpathName \fBsash mark \fIindex x y\fR
+.
+Records \fIx\fR and \fIy\fR for the sash given by \fIindex\fR; used in
+conjunction with later \fBsash dragto\fR commands to move the sash.
+.TP
+\fIpathName \fBsash place \fIindex x y\fR
+.
+Place the sash given by \fIindex\fR at the given coordinates.
+.RE
+.SH "RESIZING PANES"
+.PP
+A pane is resized by grabbing the sash (or sash handle if present) and
+dragging with the mouse. This is accomplished via mouse motion
+bindings on the widget. When a sash is moved, the sizes of the panes
+on each side of the sash, and thus the widgets in those panes, are
+adjusted.
+.PP
+When a pane is resized from outside (e.g. it is packed to expand and
+fill, and the containing toplevel is resized), space is added to the final
+(rightmost or bottommost) pane in the window.
+.PP
+Unlike slave windows managed by e.g. pack or grid, the panes managed by a
+panedwindow do not change width or height to accommodate changes in the
+requested widths or heights of the panes, once these have become mapped.
+Therefore it may be advisable, particularly when creating layouts
+interactively, to not add a pane to the panedwindow widget until after the
+geometry requests of that pane has been finalized (i.e., all components of
+the pane inserted, all options affecting geometry set to their proper
+values, etc.).
+.SH "SEE ALSO"
+ttk::panedwindow(n)
+.SH KEYWORDS
+panedwindow, widget, geometry management
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/photo.n b/tk8.6/doc/photo.n
new file mode 100644
index 0000000..0fe0c61
--- /dev/null
+++ b/tk8.6/doc/photo.n
@@ -0,0 +1,543 @@
+'\"
+'\" Copyright (c) 1994 The Australian National University
+'\" Copyright (c) 1994-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.
+'\"
+'\" Author: Paul Mackerras (paulus@cs.anu.edu.au),
+'\" Department of Computer Science,
+'\" Australian National University.
+'\"
+.TH photo n 4.0 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+photo \- Full-color images
+.SH SYNOPSIS
+.nf
+\fBimage create photo \fR?\fIname\fR? ?\fIoptions\fR?
+
+\fIimageName \fBblank\fR
+\fIimageName \fBcget \fIoption\fR
+\fIimageName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
+\fIimageName \fBcopy \fIsourceImage\fR ?\fIoption value(s) ...\fR?
+\fIimageName \fBdata\fR ?\fIoption value(s) ...\fR?
+\fIimageName \fBget \fIx y\fR
+\fIimageName \fBput \fIdata\fR ?\fIoption value(s) ...\fR?
+\fIimageName \fBread \fIfilename\fR ?\fIoption value(s) ...\fR?
+\fIimageName \fBredither\fR
+\fIimageName \fBtransparency \fIsubcommand \fR?\fIarg arg ...\fR?
+\fIimageName \fBwrite \fIfilename\fR ?\fIoption value(s) ...\fR?
+.fi
+.BE
+.SH DESCRIPTION
+.PP
+A photo is an image whose pixels can display any color or be
+transparent. A photo image is stored internally in full color (32
+bits per pixel), and is displayed using dithering if necessary. Image
+data for a photo image can be obtained from a file or a string, or it
+can be supplied from
+C code through a procedural interface. At present, only
+.VS 8.6
+PNG,
+.VE 8.6
+GIF and PPM/PGM
+formats are supported, but an interface exists to allow additional
+image file formats to be added easily. A photo image is transparent
+in regions where no image data has been supplied
+or where it has been set transparent by the \fBtransparency set\fR
+subcommand.
+.SH "CREATING PHOTOS"
+.PP
+Like all images, photos are created using the \fBimage create\fR
+command.
+Photos support the following \fIoptions\fR:
+.TP
+\fB\-data \fIstring\fR
+.
+Specifies the contents of the image as a string. The string should
+contain binary data or, for some formats, base64-encoded data (this is
+currently guaranteed to be supported for PNG and GIF images). The
+format of the
+string must be one of those for which there is an image file format
+handler that will accept string data. If both the \fB\-data\fR
+and \fB\-file\fR options are specified, the \fB\-file\fR option takes
+precedence.
+.TP
+\fB\-format \fIformat-name\fR
+.
+Specifies the name of the file format for the data specified with the
+\fB\-data\fR or \fB\-file\fR option.
+.TP
+\fB\-file \fIname\fR
+.
+\fIname\fR gives the name of a file that is to be read to supply data
+for the photo image. The file format must be one of those for which
+there is an image file format handler that can read data.
+.TP
+\fB\-gamma \fIvalue\fR
+.
+Specifies that the colors allocated for displaying this image in a
+window should be corrected for a non-linear display with the specified
+gamma exponent value. (The intensity produced by most
+CRT displays is a power function of the input value, to a good
+approximation; gamma is the exponent and is typically around 2).
+The value specified must be greater than zero. The default
+value is one (no correction). In general, values greater than one
+will make the image lighter, and values less than one will make it
+darker.
+.TP
+\fB\-height \fInumber\fR
+.
+Specifies the height of the image, in pixels. This option is useful
+primarily in situations where the user wishes to build up the contents
+of the image piece by piece. A value of zero (the default) allows the
+image to expand or shrink vertically to fit the data stored in it.
+.TP
+\fB\-palette \fIpalette-spec\fR
+.
+Specifies the resolution of the color cube to be allocated for
+displaying this image, and thus the number of colors used from the
+colormaps of the windows where it is displayed. The
+\fIpalette-spec\fR string may be either a single decimal number,
+specifying the number of shades of gray to use, or three decimal
+numbers separated by slashes (/), specifying the number of shades of
+red, green and blue to use, respectively. If the first form (a single
+number) is used, the image will be displayed in monochrome (i.e.,
+grayscale).
+.TP
+\fB\-width \fInumber\fR
+.
+Specifies the width of the image, in pixels. This option is useful
+primarily in situations where the user wishes to build up the contents
+of the image piece by piece. A value of zero (the default) allows the
+image to expand or shrink horizontally to fit the data stored in it.
+.SH "IMAGE COMMAND"
+.PP
+When a photo image is created, Tk also creates a new command
+whose name is the same as the image.
+This command may be used to invoke various operations
+on the image.
+It has the following general form:
+.CS
+\fIimageName option \fR?\fIarg arg ...\fR?
+.CE
+\fIOption\fR and the \fIarg\fRs
+determine the exact behavior of the command.
+.PP
+Those options that write data to the image generally expand the size
+of the image, if necessary, to accommodate the data written to the
+image, unless the user has specified non-zero values for the
+\fB\-width\fR and/or \fB\-height\fR configuration options, in which
+case the width and/or height, respectively, of the image will not be
+changed.
+.PP
+The following commands are possible for photo images:
+.TP
+\fIimageName \fBblank\fR
+.
+Blank the image; that is, set the entire image to have no data, so it
+will be displayed as transparent, and the background of whatever
+window it is displayed in will show through.
+.TP
+\fIimageName \fBcget\fR \fIoption\fR
+.
+Returns the current value of the configuration option given
+by \fIoption\fR.
+\fIOption\fR may have any of the values accepted by the
+\fBimage create\fR \fBphoto\fR command.
+.TP
+\fIimageName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
+.
+Query or modify the configuration options for the image.
+If no \fIoption\fR is specified, returns a list describing all of
+the available options for \fIimageName\fR (see \fBTk_ConfigureInfo\fR for
+information on the format of this list). If \fIoption\fR is specified
+with no \fIvalue\fR, then the command returns a list describing the
+one named option (this list will be identical to the corresponding
+sublist of the value returned if no \fIoption\fR is specified). If
+one or more \fIoption\-value\fR pairs are specified, then the command
+modifies the given option(s) to have the given value(s); in
+this case the command returns an empty string.
+\fIOption\fR may have any of the values accepted by the
+\fBimage create\fR \fBphoto\fR command.
+.TP
+\fIimageName \fBcopy\fR \fIsourceImage\fR ?\fIoption value(s) ...\fR?
+.
+Copies a region from the image called \fIsourceImage\fR (which must
+be a photo image) to the image called \fIimageName\fR, possibly with
+pixel zooming and/or subsampling. If no options are specified, this
+command copies the whole of \fIsourceImage\fR into \fIimageName\fR,
+starting at coordinates (0,0) in \fIimageName\fR. The following
+options may be specified:
+.RS
+.TP
+\fB\-from \fIx1 y1 x2 y2\fR
+.
+Specifies a rectangular sub-region of the source image to be copied.
+(\fIx1,y1\fR) and (\fIx2,y2\fR) specify diagonally opposite corners of
+the rectangle. If \fIx2\fR and \fIy2\fR are not specified, the
+default value is the bottom-right corner of the source image. The
+pixels copied will include the left and top edges of the specified
+rectangle but not the bottom or right edges. If the \fB\-from\fR
+option is not given, the default is the whole source image.
+.TP
+\fB\-to \fIx1 y1 x2 y2\fR
+.
+Specifies a rectangular sub-region of the destination image to be
+affected. (\fIx1,y1\fR) and (\fIx2,y2\fR) specify diagonally opposite
+corners of the rectangle. If \fIx2\fR and \fIy2\fR are not specified,
+the default value is (\fIx1,y1\fR) plus the size of the source
+region (after subsampling and zooming, if specified). If \fIx2\fR and
+\fIy2\fR are specified, the source region will be replicated if
+necessary to fill the destination region in a tiled fashion.
+.TP
+\fB\-shrink\fR
+.
+Specifies that the size of the destination image should be reduced, if
+necessary, so that the region being copied into is at the bottom-right
+corner of the image. This option will not affect the width or height
+of the image if the user has specified a non-zero value for the
+\fB\-width\fR or \fB\-height\fR configuration option, respectively.
+.TP
+\fB\-zoom \fIx y\fR
+.
+Specifies that the source region should be magnified by a factor of
+\fIx\fR in the X direction and \fIy\fR in the Y direction. If \fIy\fR
+is not given, the default value is the same as \fIx\fR. With this
+option, each pixel in the source image will be expanded into a block
+of \fIx\fR x \fIy\fR pixels in the destination image, all the same
+color. \fIx\fR and \fIy\fR must be greater than 0.
+.TP
+\fB\-subsample \fIx y\fR
+.
+Specifies that the source image should be reduced in size by using
+only every \fIx\fRth pixel in the X direction and \fIy\fRth pixel in
+the Y direction. Negative values will cause the image to be flipped
+about the Y or X axes, respectively. If \fIy\fR is not given, the
+default value is the same as \fIx\fR.
+.TP
+\fB\-compositingrule \fIrule\fR
+.
+Specifies how transparent pixels in the source image are combined with
+the destination image. When a compositing rule of \fIoverlay\fR is
+set, the old contents of the destination image are visible, as if the
+source image were printed on a piece of transparent film and placed
+over the top of the destination. When a compositing rule of \fIset\fR
+is set, the old contents of the destination image are discarded and
+the source image is used as-is. The default compositing rule is
+\fIoverlay\fR.
+.RE
+.TP
+\fIimageName \fBdata\fR ?\fIoption value(s) ...\fR?
+.
+Returns image data in the form of a string. The following options
+may be specified:
+.RS
+.TP
+\fB\-background\fI color\fR
+.
+If the color is specified, the data will not contain any transparency
+information. In all transparent pixels the color will be replaced by
+the specified color.
+.TP
+\fB\-format\fI format-name\fR
+.
+Specifies the name of the image file format handler to be used.
+Specifically, this subcommand searches
+for the first handler whose name matches an initial substring of
+\fIformat-name\fR and which has the capability to write a string
+containing this image data.
+If this option is not given, this subcommand uses a format that
+consists of a list (one element per row) of lists (one element per
+pixel/column) of colors in
+.QW \fB#\fIrrggbb\fR
+format (where \fIrr\fR is a pair of hexadecimal digits for the red
+channel, \fIgg\fR for green, and \fIbb\fR for blue).
+.TP
+\fB\-from \fIx1 y1 x2 y2\fR
+.
+Specifies a rectangular region of \fIimageName\fR to be returned.
+If only \fIx1\fR and \fIy1\fR are specified, the region
+extends from \fI(x1,y1)\fR to the bottom-right corner of
+\fIimageName\fR. If all four coordinates are given, they specify
+diagonally opposite corners of the rectangular region, including x1,y1
+and excluding x2,y2. The default, if this option is not given, is the
+whole image.
+.TP
+\fB\-grayscale\fR
+.
+If this options is specified, the data will not contain color
+information. All pixel data will be transformed into grayscale.
+.RE
+.TP
+\fIimageName \fBget\fR \fIx y\fR
+.
+Returns the color of the pixel at coordinates (\fIx\fR,\fIy\fR) in the
+image as a list of three integers between 0 and 255, representing the
+red, green and blue components respectively.
+.TP
+\fIimageName \fBput\fR \fIdata\fR ?\fIoption value(s) ...\fR?
+.
+Sets pixels in \fI imageName\fR to the data specified in \fIdata\fR.
+This command first searches the list of image file format handlers for
+a handler that can interpret the data in \fIdata\fR, and then reads
+the image encoded within into \fIimageName\fR (the destination image).
+If \fIdata\fR does not match any known format, an attempt to interpret
+it as a (top-to-bottom) list of scan-lines is made, with each
+scan-line being a (left-to-right) list of pixel colors (see
+\fBTk_GetColor\fR for a description of valid colors.) Every scan-line
+must be of the same length. Note that when \fIdata\fR is a single
+color name, you are instructing Tk to fill a rectangular region with
+that color. The following options may be specified:
+.RS
+.TP
+\fB\-format \fIformat-name\fR
+.
+Specifies the format of the image data in \fIdata\fR.
+Specifically, only image file format handlers whose names begin with
+\fIformat-name\fR will be used while searching for an image data
+format handler to read the data.
+.TP
+\fB\-to \fIx1 y1\fR ?\fIx2 y2\fR?
+.
+Specifies the coordinates of the top-left corner (\fIx1\fR,\fIy1\fR)
+of the region of \fIimageName\fR into which the image data will be
+copied. The default position is (0,0). If \fIx2\fR,\fIy2\fR is given
+and \fIdata\fR is not large enough to cover the rectangle specified by
+this option, the image data extracted will be tiled so it covers the
+entire destination rectangle. Note that if \fIdata\fR specifies a
+single color value, then a region extending to the bottom-right corner
+represented by (\fIx2\fR,\fIy2\fR) will be filled with that color.
+.RE
+.TP
+\fIimageName \fBread\fR \fIfilename\fR ?\fIoption value(s) ...\fR?
+.
+Reads image data from the file named \fIfilename\fR into the image.
+This command first searches the list of
+image file format handlers for a handler that can interpret the data
+in \fIfilename\fR, and then reads the image in \fIfilename\fR into
+\fIimageName\fR (the destination image). The following options may be
+specified:
+.RS
+.TP
+\fB\-format \fIformat-name\fR
+.
+Specifies the format of the image data in \fIfilename\fR.
+Specifically, only image file format handlers whose names begin with
+\fIformat-name\fR will be used while searching for an image data
+format handler to read the data.
+.TP
+\fB\-from \fIx1 y1 x2 y2\fR
+.
+Specifies a rectangular sub-region of the image file data to be copied
+to the destination image. If only \fIx1\fR and \fIy1\fR are
+specified, the region extends from (\fIx1,y1\fR) to the bottom-right
+corner of the image in the image file. If all four coordinates are
+specified, they specify diagonally opposite corners or the region.
+The default, if this option is not specified, is the whole of the
+image in the image file.
+.TP
+\fB\-shrink\fR
+.
+If this option, the size of \fIimageName\fR will be reduced, if
+necessary, so that the region into which the image file data are read
+is at the bottom-right corner of the \fIimageName\fR. This option
+will not affect the width or height of the image if the user has
+specified a non-zero value for the \fB\-width\fR or \fB\-height\fR
+configuration option, respectively.
+.TP
+\fB\-to \fIx y\fR
+.
+Specifies the coordinates of the top-left corner of the region of
+\fIimageName\fR into which data from \fIfilename\fR are to be read.
+The default is (0,0).
+.RE
+.TP
+\fIimageName \fBredither\fR
+.
+The dithering algorithm used in displaying photo images propagates
+quantization errors from one pixel to its neighbors.
+If the image data for \fIimageName\fR is supplied in pieces, the
+dithered image may not be exactly correct. Normally the difference is
+not noticeable, but if it is a problem, this command can be used to
+recalculate the dithered image in each window where the image is
+displayed.
+.TP
+\fIimageName \fBtransparency \fIsubcommand \fR?\fIarg arg ...\fR?
+.
+Allows examination and manipulation of the transparency information in
+the photo image. Several subcommands are available:
+.RS
+.TP
+\fIimageName \fBtransparency get \fIx y\fR
+.
+Returns a boolean indicating if the pixel at (\fIx\fR,\fIy\fR) is
+transparent.
+.TP
+\fIimageName \fBtransparency set \fIx y boolean\fR
+.
+Makes the pixel at (\fIx\fR,\fIy\fR) transparent if \fIboolean\fR is
+true, and makes that pixel opaque otherwise.
+.RE
+.TP
+\fIimageName \fBwrite \fIfilename\fR ?\fIoption value(s) ...\fR?
+.
+Writes image data from \fIimageName\fR to a file named \fIfilename\fR.
+The following options may be specified:
+.RS
+.TP
+\fB\-background\fI color\fR
+.
+If the color is specified, the data will not contain any transparency
+information. In all transparent pixels the color will be replaced by
+the specified color.
+.TP
+\fB\-format\fI format-name\fR
+.
+Specifies the name of the image file format handler to be used to
+write the data to the file. Specifically, this subcommand searches
+for the first handler whose name matches an initial substring of
+\fIformat-name\fR and which has the capability to write an image
+file. If this option is not given, the format is guessed from
+the file extension. If that cannot be determined, this subcommand
+uses the first handler that has the capability to write an image file.
+.TP
+\fB\-from \fIx1 y1 x2 y2\fR
+.
+Specifies a rectangular region of \fIimageName\fR to be written to the
+image file. If only \fIx1\fR and \fIy1\fR are specified, the region
+extends from \fI(x1,y1)\fR to the bottom-right corner of
+\fIimageName\fR. If all four coordinates are given, they specify
+diagonally opposite corners of the rectangular region. The default,
+if this option is not given, is the whole image.
+.TP
+\fB\-grayscale\fR
+.
+If this options is specified, the data will not contain color
+information. All pixel data will be transformed into grayscale.
+.RE
+.SH "IMAGE FORMATS"
+.PP
+The photo image code is structured to allow handlers for additional
+image file formats to be added easily. The photo image code maintains
+a list of these handlers. Handlers are added to the list by
+registering them with a call to \fBTk_CreatePhotoImageFormat\fR. The
+standard Tk distribution comes with handlers for PPM/PGM, PNG and GIF
+formats, which are automatically registered on initialization.
+.PP
+When reading an image file or processing
+string data specified with the \fB\-data\fR configuration option, the
+photo image code invokes each handler in turn until one is
+found that claims to be able to read the data in the file or string.
+Usually this will find the correct handler, but if it does not, the
+user may give a format name with the \fB\-format\fR option to specify
+which handler to use. In fact the photo image code will try those
+handlers whose names begin with the string specified for the
+\fB\-format\fR option (the comparison is case-insensitive). For
+example, if the user specifies \fB\-format gif\fR, then a handler
+named GIF87 or GIF89 may be invoked, but a handler
+named JPEG may not (assuming that such handlers had been
+registered).
+.PP
+When writing image data to a file, the processing of the
+\fB\-format\fR option is slightly different: the string value given
+for the \fB\-format\fR option must begin with the complete name of the
+requested handler, and may contain additional information following
+that, which the handler can use, for example, to specify which variant
+to use of the formats supported by the handler.
+Note that not all image handlers may support writing transparency data
+to a file, even where the target image format does.
+.SS "FORMAT SUBOPTIONS"
+.PP
+.VS 8.6
+Some image formats support sub-options, which are specified at the time that
+the image is loaded using additional words in the \fB\-format\fR option. At
+the time of writing, the following are supported:
+.TP
+\fBgif \-index\fI indexValue\fR
+.
+When parsing a multi-part GIF image, Tk normally only accesses the first
+image. By giving the \fB\-index\fR sub-option, the \fIindexValue\fR'th value
+may be used instead. The \fIindexValue\fR must be an integer from 0 up to the
+number of image parts in the GIF data.
+.TP
+\fBpng \-alpha\fI alphaValue\fR
+.
+An additional alpha filtering for the overall image, which allows the
+background on which the image is displayed to show through. This usually also
+has the effect of desaturating the image. The \fIalphaValue\fR must be between
+0.0 and 1.0.
+.VE 8.6
+.SH "COLOR ALLOCATION"
+.PP
+When a photo image is displayed in a window, the photo image code
+allocates colors to use to display the image and dithers the image, if
+necessary, to display a reasonable approximation to the image using
+the colors that are available. The colors are allocated as a color
+cube, that is, the number of colors allocated is the product of the
+number of shades of red, green and blue.
+.PP
+Normally, the number of
+colors allocated is chosen based on the depth of the window. For
+example, in an 8-bit PseudoColor window, the photo image code will
+attempt to allocate seven shades of red, seven shades of green and
+four shades of blue, for a total of 198 colors. In a 1-bit StaticGray
+(monochrome) window, it will allocate two colors, black and white. In
+a 24-bit DirectColor or TrueColor window, it will allocate 256 shades
+each of red, green and blue. Fortunately, because of the way that
+pixel values can be combined in DirectColor and TrueColor windows,
+this only requires 256 colors to be allocated. If not all of the
+colors can be allocated, the photo image code reduces the number of
+shades of each primary color and tries again.
+.PP
+The user can exercise some control over the number of colors that a
+photo image uses with the \fB\-palette\fR configuration option. If
+this option is used, it specifies the maximum number of shades of
+each primary color to try to allocate. It can also be used to force
+the image to be displayed in shades of gray, even on a color display,
+by giving a single number rather than three numbers separated by
+slashes.
+.SH CREDITS
+.PP
+The photo image type was designed and implemented by Paul Mackerras,
+based on his earlier photo widget and some suggestions from
+John Ousterhout.
+.SH EXAMPLE
+.PP
+Load an image from a file and tile it to the size of a window, which
+is useful for producing a tiled background:
+.PP
+.CS
+# These lines should be called once
+\fBimage create photo\fR untiled \-file "theFile.ppm"
+\fBimage create photo\fR tiled
+
+# These lines should be called whenever .someWidget changes
+# size; a <Configure> binding is useful here
+set width [winfo width .someWidget]
+set height [winfo height .someWidget]
+tiled \fBcopy\fR untiled \-to 0 0 $width $height \-shrink
+.CE
+.PP
+.VS 8.6
+The PNG image loader allows the application of an additional alpha factor
+during loading, which is useful for generating images suitable for disabled
+buttons:
+.PP
+.CS
+\fBimage create photo\fR icon \-file "icon.png"
+\fBimage create photo\fR iconDisabled \-file "icon.png" \e
+ \-format "png \-alpha 0.5"
+button .b \-image icon \-disabledimage iconDisabled
+.CE
+.VE 8.6
+.SH "SEE ALSO"
+image(n)
+.SH KEYWORDS
+photo, image, color
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/place.n b/tk8.6/doc/place.n
new file mode 100644
index 0000000..3a092c2
--- /dev/null
+++ b/tk8.6/doc/place.n
@@ -0,0 +1,255 @@
+'\"
+'\" Copyright (c) 1992 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH place n "" Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+place \- Geometry manager for fixed or rubber-sheet placement
+.SH SYNOPSIS
+\fBplace \fIoption arg \fR?\fIarg ...\fR?
+.BE
+.SH DESCRIPTION
+.PP
+The placer is a geometry manager for Tk.
+It provides simple fixed placement of windows, where you specify
+the exact size and location of one window, called the \fIslave\fR,
+within another window, called the \fImaster\fR.
+The placer also provides rubber-sheet placement, where you specify the
+size and location of the slave in terms of the dimensions of
+the master, so that the slave changes size and location
+in response to changes in the size of the master.
+Lastly, the placer allows you to mix these styles of placement so
+that, for example, the slave has a fixed width and height but is
+centered inside the master.
+.PP
+.TP
+\fBplace \fIwindow option value \fR?\fIoption value ...\fR?
+Arrange for the placer to manage the geometry of a slave whose
+pathName is \fIwindow\fR. The remaining arguments consist of one or
+more \fIoption\-value\fR pairs that specify the way in which
+\fIwindow\fR's geometry is managed. \fIOption\fR may have any of the
+values accepted by the \fBplace configure\fR command.
+.TP
+\fBplace configure \fIwindow \fR?\fIoption\fR? ?\fIvalue option value ...\fR?
+Query or modify the geometry options of the slave given by
+\fIwindow\fR. If no \fIoption\fR is specified, this command returns a
+list describing the available options (see \fBTk_ConfigureInfo\fR for
+information on the format of this list). If \fIoption\fR is specified
+with no \fIvalue\fR, then the command returns a list describing the
+one named option (this list will be identical to the corresponding
+sublist of the value returned if no \fIoption\fR is specified). If
+one or more \fIoption\-value\fR pairs are specified, then the command
+modifies the given option(s) to have the given value(s); in this case
+the command returns an empty string.
+.RS
+.PP
+The following \fIoption\-value\fR pairs are supported:
+.TP
+\fB\-anchor \fIwhere\fR
+\fIWhere\fR specifies which point of \fIwindow\fR is to be positioned
+at the (x,y) location selected by the \fB\-x\fR, \fB\-y\fR,
+\fB\-relx\fR, and \fB\-rely\fR options.
+The anchor point is in terms of the outer area of \fIwindow\fR
+including its border, if any.
+Thus if \fIwhere\fR is \fBse\fR then the lower-right corner of
+\fIwindow\fR's border will appear at the given (x,y) location
+in the master.
+The anchor position defaults to \fBnw\fR.
+.TP
+\fB\-bordermode \fImode\fR
+\fIMode\fR determines the degree to which borders within the
+master are used in determining the placement of the slave.
+The default and most common value is \fBinside\fR.
+In this case the placer considers the area of the master to
+be the innermost area of the master, inside any border:
+an option of \fB\-x 0\fR corresponds to an x-coordinate just
+inside the border and an option of \fB\-relwidth 1.0\fR
+means \fIwindow\fR will fill the area inside the master's
+border.
+.RS
+.PP
+If \fImode\fR is \fBoutside\fR then the placer considers
+the area of the master to include its border;
+this mode is typically used when placing \fIwindow\fR
+outside its master, as with the options \fB\-x 0 \-y 0 \-anchor ne\fR.
+Lastly, \fImode\fR may be specified as \fBignore\fR, in which
+case borders are ignored: the area of the master is considered
+to be its official X area, which includes any internal border but
+no external border. A bordermode of \fBignore\fR is probably
+not very useful.
+.RE
+.TP
+\fB\-height \fIsize\fR
+\fISize\fR specifies the height for \fIwindow\fR in screen units
+(i.e. any of the forms accepted by \fBTk_GetPixels\fR).
+The height will be the outer dimension of \fIwindow\fR including its
+border, if any.
+If \fIsize\fR is an empty string, or if no \fB\-height\fR or
+\fB\-relheight\fR option is specified, then the height requested
+internally by the window will be used.
+.TP
+\fB\-in \fImaster\fR
+\fIMaster\fR specifies the path name of the window relative
+to which \fIwindow\fR is to be placed.
+\fIMaster\fR must either be \fIwindow\fR's parent or a descendant
+of \fIwindow\fR's parent.
+In addition, \fImaster\fR and \fIwindow\fR must both be descendants
+of the same top-level window.
+These restrictions are necessary to guarantee
+that \fIwindow\fR is visible whenever \fImaster\fR is visible.
+If this option is not specified then the master defaults to
+\fIwindow\fR's parent.
+.TP
+\fB\-relheight \fIsize\fR
+\fISize\fR specifies the height for \fIwindow\fR.
+In this case the height is specified as a floating-point number
+relative to the height of the master: 0.5 means \fIwindow\fR will
+be half as high as the master, 1.0 means \fIwindow\fR will have
+the same height as the master, and so on.
+If both \fB\-height\fR and \fB\-relheight\fR are specified for a slave,
+their values are summed. For example, \fB\-relheight 1.0 \-height \-2\fR
+makes the slave 2 pixels shorter than the master.
+.TP
+\fB\-relwidth \fIsize\fR
+\fISize\fR specifies the width for \fIwindow\fR.
+In this case the width is specified as a floating-point number
+relative to the width of the master: 0.5 means \fIwindow\fR will
+be half as wide as the master, 1.0 means \fIwindow\fR will have
+the same width as the master, and so on.
+If both \fB\-width\fR and \fB\-relwidth\fR are specified for a slave,
+their values are summed. For example, \fB\-relwidth 1.0 \-width 5\fR
+makes the slave 5 pixels wider than the master.
+.TP
+\fB\-relx \fIlocation\fR
+\fILocation\fR specifies the x-coordinate within the master window
+of the anchor point for \fIwindow\fR.
+In this case the location is specified in a relative fashion
+as a floating-point number: 0.0 corresponds to the left edge
+of the master and 1.0 corresponds to the right edge of the master.
+\fILocation\fR need not be in the range 0.0\-1.0.
+If both \fB\-x\fR and \fB\-relx\fR are specified for a slave
+then their values are summed. For example, \fB\-relx 0.5 \-x \-2\fR
+positions the left edge of the slave 2 pixels to the left of the
+center of its master.
+.TP
+\fB\-rely \fIlocation\fR
+\fILocation\fR specifies the y-coordinate within the master window
+of the anchor point for \fIwindow\fR.
+In this case the value is specified in a relative fashion
+as a floating-point number: 0.0 corresponds to the top edge
+of the master and 1.0 corresponds to the bottom edge of the master.
+\fILocation\fR need not be in the range 0.0\-1.0.
+If both \fB\-y\fR and \fB\-rely\fR are specified for a slave
+then their values are summed. For example, \fB\-rely 0.5 \-x 3\fR
+positions the top edge of the slave 3 pixels below the
+center of its master.
+.TP
+\fB\-width \fIsize\fR
+\fISize\fR specifies the width for \fIwindow\fR in screen units
+(i.e. any of the forms accepted by \fBTk_GetPixels\fR).
+The width will be the outer width of \fIwindow\fR including its
+border, if any.
+If \fIsize\fR is an empty string, or if no \fB\-width\fR
+or \fB\-relwidth\fR option is specified, then the width requested
+internally by the window will be used.
+.TP
+\fB\-x \fIlocation\fR
+\fILocation\fR specifies the x-coordinate within the master window
+of the anchor point for \fIwindow\fR.
+The location is specified in screen units (i.e. any of the forms
+accepted by \fBTk_GetPixels\fR) and need not lie within the bounds
+of the master window.
+.TP
+\fB\-y \fIlocation\fR
+\fILocation\fR specifies the y-coordinate within the master window
+of the anchor point for \fIwindow\fR.
+The location is specified in screen units (i.e. any of the forms
+accepted by \fBTk_GetPixels\fR) and need not lie within the bounds
+of the master window.
+.PP
+If the same value is specified separately with
+two different options, such as \fB\-x\fR and \fB\-relx\fR, then
+the most recent option is used and the older one is ignored.
+.RE
+.TP
+\fBplace forget \fIwindow\fR
+Causes the placer to stop managing the geometry of \fIwindow\fR. As a
+side effect of this command \fIwindow\fR will be unmapped so that it
+does not appear on the screen. If \fIwindow\fR is not currently managed
+by the placer then the command has no effect. This command returns an
+empty string.
+.TP
+\fBplace info \fIwindow\fR
+Returns a list giving the current configuration of \fIwindow\fR.
+The list consists of \fIoption\-value\fR pairs in exactly the
+same form as might be specified to the \fBplace configure\fR
+command.
+.TP
+\fBplace slaves \fIwindow\fR
+Returns a list of all the slave windows for which \fIwindow\fR is the master.
+If there are no slaves for \fIwindow\fR then an empty string is returned.
+.PP
+If the configuration of a window has been retrieved with
+\fBplace info\fR, that configuration can be restored later by
+first using \fBplace forget\fR to erase any existing information
+for the window and then invoking \fBplace configure\fR with
+the saved information.
+.SH "FINE POINTS"
+.PP
+It is not necessary for the master window to be the parent
+of the slave window.
+This feature is useful in at least two situations.
+First, for complex window layouts it means you can create a
+hierarchy of subwindows whose only purpose
+is to assist in the layout of the parent.
+The
+.QW "real children"
+of the parent (i.e. the windows that
+are significant for the application's user interface) can be
+children of the parent yet be placed inside the windows
+of the geometry-management hierarchy.
+This means that the path names of the
+.QW "real children"
+do not reflect the geometry-management hierarchy and users
+can specify options for the real children
+without being aware of the structure of the geometry-management
+hierarchy.
+.PP
+A second reason for having a master different than the slave's
+parent is to tie two siblings together.
+For example, the placer can be used to force a window always to
+be positioned centered just below one of its
+siblings by specifying the configuration
+.CS
+\fB\-in \fIsibling\fB \-relx 0.5 \-rely 1.0 \-anchor n \-bordermode outside\fR
+.CE
+Whenever the sibling is repositioned in the future, the slave
+will be repositioned as well.
+.PP
+Unlike many other geometry managers (such as the packer)
+the placer does not make any attempt to manipulate the geometry of
+the master windows or the parents of slave windows (i.e. it does not
+set their requested sizes).
+To control the sizes of these windows, make them windows like
+frames and canvases that provide configuration options for this purpose.
+.SH EXAMPLE
+.PP
+Make the label occupy the middle bit of the toplevel, no matter how it
+is resized:
+.CS
+label .l \-text "In the\enMiddle!" \-bg black \-fg white
+\fBplace\fR .l \-relwidth .3 \-relx .35 \-relheight .3 \-rely .35
+.CE
+.SH "SEE ALSO"
+grid(n), pack(n)
+.SH KEYWORDS
+geometry manager, height, location, master, place, rubber sheet, slave, width
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/popup.n b/tk8.6/doc/popup.n
new file mode 100644
index 0000000..0d32362
--- /dev/null
+++ b/tk8.6/doc/popup.n
@@ -0,0 +1,49 @@
+'\"
+'\" Copyright (c) 1994-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.
+'\"
+.TH tk_popup n 4.0 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+tk_popup \- Post a popup menu
+.SH SYNOPSIS
+\fBtk_popup \fImenu x y \fR?\fIentry\fR?
+.BE
+.SH DESCRIPTION
+.PP
+This procedure posts a menu at a given position on the screen and
+configures Tk so that the menu and its cascaded children can be
+traversed with the mouse or the keyboard.
+\fIMenu\fR is the name of a menu widget and \fIx\fR and \fIy\fR
+are the root coordinates at which to display the menu.
+If \fIentry\fR is omitted or an empty string, the
+menu's upper left corner is positioned at the given point.
+Otherwise \fIentry\fR gives the index of an entry in \fImenu\fR and
+the menu will be positioned so that the entry is positioned over
+the given point.
+.SH EXAMPLE
+.PP
+How to attach a simple popup menu to a widget.
+.CS
+# Create a menu
+set m [menu .popupMenu]
+$m add command \-label "Example 1" \-command bell
+$m add command \-label "Example 2" \-command bell
+
+# Create something to attach it to
+pack [label .l \-text "Click me!"]
+
+# Arrange for the menu to pop up when the label is clicked
+bind .l <1> {\fBtk_popup\fR .popupMenu %X %Y}
+.CE
+.SH "SEE ALSO"
+bind(n), menu(n), tk_optionMenu(n)
+.SH KEYWORDS
+menu, popup
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/radiobutton.n b/tk8.6/doc/radiobutton.n
new file mode 100644
index 0000000..fceb1ec
--- /dev/null
+++ b/tk8.6/doc/radiobutton.n
@@ -0,0 +1,265 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH radiobutton n 4.4 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+radiobutton \- Create and manipulate 'radiobutton' pick-one widgets
+.SH SYNOPSIS
+\fBradiobutton\fR \fIpathName \fR?\fIoptions\fR?
+.SO
+\-activebackground \-disabledforeground \-padx
+\-activeforeground \-font \-pady
+\-anchor \-foreground \-relief
+\-background \-highlightbackground \-takefocus
+\-bitmap \-highlightcolor \-text
+\-borderwidth \-highlightthickness \-textvariable
+\-compound \-image \-underline
+\-cursor \-justify \-wraplength
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-command command Command
+Specifies a Tcl command to associate with the button. This command
+is typically invoked when mouse button 1 is released over the button
+window. The button's global variable (\fB\-variable\fR option) will
+be updated before the command is invoked.
+.OP \-height height Height
+Specifies a desired height for the button.
+If an image or bitmap is being displayed in the button then the value is in
+screen units (i.e. any of the forms acceptable to \fBTk_GetPixels\fR);
+for text it is in lines of text.
+If this option is not specified, the button's desired height is computed
+from the size of the image or bitmap or text being displayed in it.
+.OP \-indicatoron indicatorOn IndicatorOn
+Specifies whether or not the indicator should be drawn. Must be a
+proper boolean value. If false, the \fB\-relief\fR option is
+ignored and the widget's relief is always sunken if the widget is
+selected and raised otherwise.
+.OP \-offrelief offRelief OffRelief
+Specifies the relief for the checkbutton when the indicator is not drawn and
+the checkbutton is off. The default value is
+.QW raised .
+By setting this option to
+.QW flat
+and setting \fB\-indicatoron\fR to false and \fB\-overrelief\fR to
+.QW raised ,
+the effect is achieved
+of having a flat button that raises on mouse-over and which is
+depressed when activated. This is the behavior typically exhibited by
+the Align-Left, Align-Right, and Center radiobuttons on the toolbar of a
+word-processor, for example.
+.OP \-overrelief overRelief OverRelief
+Specifies an alternative relief for the radiobutton, to be used when the
+mouse cursor is over the widget. This option can be used to make
+toolbar buttons, by configuring \fB\-relief flat \-overrelief
+raised\fR. If the value of this option is the empty string, then no
+alternative relief is used when the mouse cursor is over the radiobutton.
+The empty string is the default value.
+.OP \-selectcolor selectColor Background
+Specifies a background color to use when the button is selected.
+If \fBindicatorOn\fR is true then the color is used as the background for
+the indicator regardless of the select state.
+If \fB\-indicatoron\fR is false, this color is used as the background
+for the entire widget, in place of \fB\-background\fR or \fB\-activeBackground\fR,
+whenever the widget is selected.
+If specified as an empty string then no special color is used for
+displaying when the widget is selected.
+.OP \-selectimage selectImage SelectImage
+Specifies an image to display (in place of the \fB\-image\fR option)
+when the radiobutton is selected.
+This option is ignored unless the \fB\-image\fR option has been
+specified.
+.OP \-state state State
+Specifies one of three states for the radiobutton: \fBnormal\fR, \fBactive\fR,
+or \fBdisabled\fR. In normal state the radiobutton is displayed using the
+\fB\-foreground\fR and \fB\-background\fR options. The active state is
+typically used when the pointer is over the radiobutton. In active state
+the radiobutton is displayed using the \fB\-activeforeground\fR and
+\fB\-activebackground\fR options. Disabled state means that the radiobutton
+should be insensitive: the default bindings will refuse to activate
+the widget and will ignore mouse button presses.
+In this state the \fB\-disabledforeground\fR and
+\fB\-background\fR options determine how the radiobutton is displayed.
+.OP \-tristateimage tristateImage TristateImage
+Specifies an image to display (in place of the \fB\-image\fR option)
+when the radiobutton is selected.
+This option is ignored unless the \fB\-image\fR option has been
+specified.
+.OP \-tristatevalue tristateValue Value
+Specifies the value that causes the radiobutton to display the multi-value
+selection, also known as the tri-state mode. Defaults to
+.QW "" .
+.OP \-value value Value
+Specifies value to store in the button's associated variable whenever
+this button is selected.
+.OP \-variable variable Variable
+Specifies the name of a global variable to set whenever this button is
+selected. Changes in this variable also cause the button to select
+or deselect itself.
+Defaults to the value \fBselectedButton\fR.
+.OP \-width width Width
+Specifies a desired width for the button.
+If an image or bitmap is being displayed in the button, the value is in
+screen units (i.e. any of the forms acceptable to \fBTk_GetPixels\fR);
+for text it is in characters.
+If this option is not specified, the button's desired width is computed
+from the size of the image or bitmap or text being displayed in it.
+.BE
+.SH DESCRIPTION
+.PP
+The \fBradiobutton\fR command creates a new window (given by the
+\fIpathName\fR argument) and makes it into a radiobutton widget.
+Additional
+options, described above, may be specified on the command line
+or in the option database
+to configure aspects of the radiobutton such as its colors, font,
+text, and initial relief. The \fBradiobutton\fR command returns its
+\fIpathName\fR argument. At the time this command is invoked,
+there must not exist a window named \fIpathName\fR, but
+\fIpathName\fR's parent must exist.
+.PP
+A radiobutton is a widget that displays a textual string, bitmap or image
+and a diamond or circle called an \fIindicator\fR.
+If text is displayed, it must all be in a single font, but it
+can occupy multiple lines on the screen (if it contains newlines
+or if wrapping occurs because of the \fB\-wraplength\fR option) and
+one of the characters may optionally be underlined using the
+\fB\-underline\fR option. A radiobutton has
+all of the behavior of a simple button: it can display itself in either
+of three different ways, according to the \fB\-state\fR option;
+it can be made to appear
+raised, sunken, or flat; it can be made to flash; and it invokes
+a Tcl command whenever mouse button 1 is clicked over the
+check button.
+.PP
+In addition, radiobuttons can be \fIselected\fR.
+If a radiobutton is selected, the indicator is normally
+drawn with a selected appearance, and
+a Tcl variable associated with the radiobutton is set to a particular
+value (normally 1).
+Under Unix, the indicator is drawn with a sunken relief and a special
+color. Under Windows, the indicator is drawn with a round mark inside.
+If the radiobutton is not selected, then the indicator is drawn with a
+deselected appearance, and the associated variable is
+set to a different value (typically 0).
+The indicator is drawn without a round mark inside.
+Typically, several radiobuttons share a single variable and the
+value of the variable indicates which radiobutton is to be selected.
+When a radiobutton is selected it sets the value of the variable to
+indicate that fact; each radiobutton also monitors the value of
+the variable and automatically selects and deselects itself when the
+variable's value changes.
+If the variable's value matches the \fB\-tristatevalue\fR, then the radiobutton
+is drawn using the tri-state mode. This mode is used to indicate mixed or
+multiple values. (This is used when the radiobutton represents the state
+of multiple items.)
+By default the variable \fBselectedButton\fR
+is used; its contents give the name of the button that is
+selected, or the empty string if no button associated with that
+variable is selected.
+The name of the variable for a radiobutton,
+plus the variable to be stored into it, may be modified with options
+on the command line or in the option database.
+Configuration options may also be used to modify the way the
+indicator is displayed (or whether it is displayed at all).
+By default a radiobutton is configured to select itself on button clicks.
+.SH "WIDGET COMMAND"
+.PP
+The \fBradiobutton\fR command creates a new Tcl command whose
+name is \fIpathName\fR. This
+command may be used to invoke various
+operations on the widget. It has the following general form:
+.CS
+\fIpathName option \fR?\fIarg arg ...\fR?
+.CE
+\fIOption\fR and the \fIarg\fRs
+determine the exact behavior of the command. The following
+commands are possible for radiobutton widgets:
+.TP
+\fIpathName \fBcget\fR \fIoption\fR
+.
+Returns the current value of the configuration option given
+by \fIoption\fR.
+\fIOption\fR may have any of the values accepted by the \fBradiobutton\fR
+command.
+.TP
+\fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
+.
+Query or modify the configuration options of the widget.
+If no \fIoption\fR is specified, returns a list describing all of
+the available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for
+information on the format of this list). If \fIoption\fR is specified
+with no \fIvalue\fR, the command returns a list describing the
+one named option (this list will be identical to the corresponding
+sublist of the value returned if no \fIoption\fR is specified). If
+one or more \fIoption\-value\fR pairs are specified, the command
+modifies the given widget option(s) to have the given value(s); in
+this case the command returns an empty string.
+\fIOption\fR may have any of the values accepted by the \fBradiobutton\fR
+command.
+.TP
+\fIpathName \fBdeselect\fR
+.
+Deselects the radiobutton and sets the associated variable to an
+empty string.
+If this radiobutton was not currently selected, the command has
+no effect.
+.TP
+\fIpathName \fBflash\fR
+.
+Flashes the radiobutton. This is accomplished by redisplaying the radiobutton
+several times, alternating between active and normal colors. At
+the end of the flash the radiobutton is left in the same normal/active
+state as when the command was invoked.
+This command is ignored if the radiobutton's state is \fBdisabled\fR.
+.TP
+\fIpathName \fBinvoke\fR
+.
+Does just what would have happened if the user invoked the radiobutton
+with the mouse: selects the button and invokes
+its associated Tcl command, if there is one.
+The return value is the return value from the Tcl command, or an
+empty string if there is no command associated with the radiobutton.
+This command is ignored if the radiobutton's state is \fBdisabled\fR.
+.TP
+\fIpathName \fBselect\fR
+.
+Selects the radiobutton and sets the associated variable to the
+value corresponding to this widget.
+.SH BINDINGS
+.PP
+Tk automatically creates class bindings for radiobuttons that give them
+the following default behavior:
+.IP [1]
+On Unix systems, a radiobutton activates whenever the mouse passes
+over it and deactivates whenever the mouse leaves the radiobutton. On
+Mac and Windows systems, when mouse button 1 is pressed over a
+radiobutton, the button activates whenever the mouse pointer is inside
+the button, and deactivates whenever the mouse pointer leaves the
+button.
+.IP [2]
+When mouse button 1 is pressed over a radiobutton it is invoked (it
+becomes selected and the command associated with the button is
+invoked, if there is one).
+.IP [3]
+When a radiobutton has the input focus, the space key causes the radiobutton
+to be invoked.
+.PP
+If the radiobutton's state is \fBdisabled\fR then none of the above
+actions occur: the radiobutton is completely non-responsive.
+.PP
+The behavior of radiobuttons can be changed by defining new bindings for
+individual widgets or by redefining the class bindings.
+.SH "SEE ALSO"
+checkbutton(n), labelframe(n), listbox(n), options(n), scale(n), ttk::radiobutton(n)
+.SH KEYWORDS
+radiobutton, widget
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/raise.n b/tk8.6/doc/raise.n
new file mode 100644
index 0000000..c8feb71
--- /dev/null
+++ b/tk8.6/doc/raise.n
@@ -0,0 +1,57 @@
+'\"
+'\" Copyright (c) 1990 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH raise n 3.3 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+raise \- Change a window's position in the stacking order
+.SH SYNOPSIS
+\fBraise \fIwindow \fR?\fIaboveThis\fR?
+.BE
+.SH DESCRIPTION
+.PP
+If the \fIaboveThis\fR argument is omitted then the command raises
+\fIwindow\fR so that it is above all of its siblings in the stacking
+order (it will not be obscured by any siblings and will obscure
+any siblings that overlap it).
+If \fIaboveThis\fR is specified then it must be the path name of
+a window that is either a sibling of \fIwindow\fR or the descendant
+of a sibling of \fIwindow\fR.
+In this case the \fBraise\fR command will insert
+\fIwindow\fR into the stacking order just above \fIaboveThis\fR
+(or the ancestor of \fIaboveThis\fR that is a sibling of \fIwindow\fR);
+this could end up either raising or lowering \fIwindow\fR.
+.PP
+All \fBtoplevel\fR windows may be restacked with respect to each
+other, whatever their relative path names, but the window manager is
+not obligated to strictly honor requests to restack.
+.PP
+On macOS raising an iconified \fBtoplevel\fR window causes it to be
+deiconified.
+.SH EXAMPLE
+.PP
+Make a button appear to be in a sibling frame that was created after
+it. This is is often necessary when building GUIs in the style where
+you create your activity widgets first before laying them out on the
+display:
+.CS
+button .b \-text "Hi there!"
+pack [frame .f \-background blue]
+pack [label .f.l1 \-text "This is above"]
+pack .b \-in .f
+pack [label .f.l2 \-text "This is below"]
+\fBraise\fR .b
+.CE
+.SH "SEE ALSO"
+lower(n)
+.SH KEYWORDS
+obscure, raise, stacking order
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/scale.n b/tk8.6/doc/scale.n
new file mode 100644
index 0000000..b1f1981
--- /dev/null
+++ b/tk8.6/doc/scale.n
@@ -0,0 +1,253 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH scale n 4.1 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+scale \- Create and manipulate 'scale' value-controlled slider widgets
+.SH SYNOPSIS
+\fBscale\fR \fIpathName \fR?\fIoptions\fR?
+.SO
+\-activebackground \-foreground \-relief
+\-background \-highlightbackground \-repeatdelay
+\-borderwidth \-highlightcolor \-repeatinterval
+\-cursor \-highlightthickness \-takefocus
+\-font \-orient \-troughcolor
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-bigincrement bigIncrement BigIncrement
+Some interactions with the scale cause its value to change by
+.QW large
+increments; this option specifies the size of the
+large increments. If specified as 0, the large increments default
+to 1/10 the range of the scale.
+.OP \-command command Command
+Specifies the prefix of a Tcl command to invoke whenever the scale's
+value is changed via a widget command.
+The actual command consists
+of this option followed by a space and a real number indicating the
+new value of the scale.
+.OP \-digits digits Digits
+An integer specifying how many significant digits should be retained
+when converting the value of the scale to a string.
+If the number is less than or equal to zero, then the scale picks
+the smallest value that guarantees that every possible slider
+position prints as a different string.
+.OP \-from from From
+A real value corresponding to the left or top end of the scale.
+.OP \-label label Label
+A string to display as a label for the scale. For
+vertical scales the label is displayed just to the right of the
+top end of the scale. For horizontal scales the label is displayed
+just above the left end of the scale. If the option is specified
+as an empty string, no label is displayed.
+.OP \-length length Length
+Specifies the desired long dimension of the scale in screen units
+(i.e. any of the forms acceptable to \fBTk_GetPixels\fR).
+For vertical scales this is the scale's height; for horizontal scales
+it is the scale's width.
+.OP \-resolution resolution Resolution
+A real value specifying the resolution for the scale.
+If this value is greater than zero then the scale's value will always be
+rounded to an even multiple of this value, as will
+the endpoints of the scale. If the value is less than zero then no
+rounding occurs. Defaults to 1 (i.e., the value will be integral).
+.OP \-showvalue showValue ShowValue
+Specifies a boolean value indicating whether or not the current
+value of the scale is to be displayed.
+.OP \-sliderlength sliderLength SliderLength
+Specifies the size of the slider, measured in screen units along the slider's
+long dimension. The value may be specified in any of the forms acceptable
+to \fBTk_GetPixels\fR.
+.OP \-sliderrelief sliderRelief SliderRelief
+Specifies the relief to use when drawing the slider, such as \fBraised\fR
+or \fBsunken\fR.
+.OP \-state state State
+Specifies one of three states for the scale: \fBnormal\fR,
+\fBactive\fR, or \fBdisabled\fR.
+If the scale is disabled then the value may not be changed and the scale
+will not activate.
+If the scale is active, the slider is displayed using the color
+specified by the \fB\-activebackground\fR option.
+.OP \-tickinterval tickInterval TickInterval
+Must be a real value.
+Determines the spacing between numerical
+tick marks displayed below or to the left of the slider. The values will all be displayed with the same number of decimal places, which will be enough to ensure they are all accurate to within 20% of a tick interval.
+If 0, no tick marks will be displayed.
+.OP \-to to To
+Specifies a real value corresponding
+to the right or bottom end of the scale.
+This value may be either less than or greater than the \fB\-from\fR option.
+.OP \-variable variable Variable
+Specifies the name of a global variable to link to the scale. Whenever the
+value of the variable changes, the scale will update to reflect this
+value.
+Whenever the scale is manipulated interactively, the variable
+will be modified to reflect the scale's new value.
+.OP \-width width Width
+Specifies the desired narrow dimension of the scale in screen units
+(i.e. any of the forms acceptable to \fBTk_GetPixels\fR).
+For vertical scales this is the scale's width; for horizontal scales
+this is the scale's height.
+.BE
+.SH DESCRIPTION
+.PP
+The \fBscale\fR command creates a new window (given by the
+\fIpathName\fR argument) and makes it into a scale widget.
+Additional
+options, described above, may be specified on the command line
+or in the option database
+to configure aspects of the scale such as its colors, orientation,
+and relief. The \fBscale\fR command returns its
+\fIpathName\fR argument. At the time this command is invoked,
+there must not exist a window named \fIpathName\fR, but
+\fIpathName\fR's parent must exist.
+.PP
+A scale is a widget that displays a rectangular \fItrough\fR and a
+small \fIslider\fR. The trough corresponds to a range
+of real values (determined by the \fB\-from\fR, \fB\-to\fR, and
+\fB\-resolution\fR options),
+and the position of the slider selects a particular real value.
+The slider's position (and hence the scale's value) may be adjusted
+with the mouse or keyboard as described in the \fBBINDINGS\fR
+section below. Whenever the scale's value is changed, a Tcl
+command is invoked (using the \fB\-command\fR option) to notify
+other interested widgets of the change.
+In addition, the value
+of the scale can be linked to a Tcl variable (using the \fB\-variable\fR
+option), so that changes in either are reflected in the other.
+.PP
+Three annotations may be displayed in a scale widget: a label
+appearing at the top right of the widget (top left for horizontal
+scales), a number displayed just to the left of the slider
+(just above the slider for horizontal scales), and a collection
+of numerical tick marks just to the left of the current value
+(just below the trough for horizontal scales). Each of these three
+annotations may be enabled or disabled using the
+configuration options.
+.SH "WIDGET COMMAND"
+.PP
+The \fBscale\fR command creates a new Tcl command whose
+name is \fIpathName\fR. This
+command may be used to invoke various
+operations on the widget. It has the following general form:
+.CS
+\fIpathName option \fR?\fIarg arg ...\fR?
+.CE
+\fIOption\fR and the \fIarg\fRs
+determine the exact behavior of the command. The following
+commands are possible for scale widgets:
+.TP
+\fIpathName \fBcget\fR \fIoption\fR
+.
+Returns the current value of the configuration option given
+by \fIoption\fR.
+\fIOption\fR may have any of the values accepted by the \fBscale\fR
+command.
+.TP
+\fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
+.
+Query or modify the configuration options of the widget.
+If no \fIoption\fR is specified, returns a list describing all of
+the available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for
+information on the format of this list). If \fIoption\fR is specified
+with no \fIvalue\fR, then the command returns a list describing the
+one named option (this list will be identical to the corresponding
+sublist of the value returned if no \fIoption\fR is specified). If
+one or more \fIoption\-value\fR pairs are specified, then the command
+modifies the given widget option(s) to have the given value(s); in
+this case the command returns an empty string.
+\fIOption\fR may have any of the values accepted by the \fBscale\fR
+command.
+.TP
+\fIpathName \fBcoords \fR?\fIvalue\fR?
+.
+Returns a list whose elements are the x and y coordinates of
+the point along the centerline of the trough that corresponds
+to \fIvalue\fR.
+If \fIvalue\fR is omitted then the scale's current value is used.
+.TP
+\fIpathName \fBget\fR ?\fIx y\fR?
+.
+If \fIx\fR and \fIy\fR are omitted, returns the current value
+of the scale. If \fIx\fR and \fIy\fR are specified, they give
+pixel coordinates within the widget; the command returns
+the scale value corresponding to the given pixel.
+Only one of \fIx\fR or \fIy\fR is used: for horizontal scales
+\fIy\fR is ignored, and for vertical scales \fIx\fR is ignored.
+.TP
+\fIpathName \fBidentify \fIx y\fR
+.
+Returns a string indicating what part of the scale lies under
+the coordinates given by \fIx\fR and \fIy\fR.
+A return value of \fBslider\fR means that the point is over
+the slider; \fBtrough1\fR means that the point is over the
+portion of the slider above or to the left of the slider;
+and \fBtrough2\fR means that the point is over the portion
+of the slider below or to the right of the slider.
+If the point is not over one of these elements, an empty string
+is returned.
+.TP
+\fIpathName \fBset \fIvalue\fR
+.
+This command is invoked to change the current value of the scale,
+and hence the position at which the slider is displayed. \fIValue\fR
+gives the new value for the scale.
+The command has no effect if the scale is disabled.
+.SH BINDINGS
+.PP
+Tk automatically creates class bindings for scales that give them
+the following default behavior.
+Where the behavior is different for vertical and horizontal scales,
+the horizontal behavior is described in parentheses.
+.IP [1]
+If button 1 is pressed in the trough, the scale's value will
+be incremented or decremented by the value of the \fB\-resolution\fR
+option so that the slider moves in the direction of the cursor.
+If the button is held down, the action auto-repeats.
+.IP [2]
+If button 1 is pressed over the slider, the slider can be dragged
+with the mouse.
+.IP [3]
+If button 1 is pressed in the trough with the Control key down,
+the slider moves all the way to the end of its range, in the
+direction towards the mouse cursor.
+.IP [4]
+If button 2 is pressed, the scale's value is set to the mouse
+position. If the mouse is dragged with button 2 down, the scale's
+value changes with the drag.
+.IP [5]
+The Up and Left keys move the slider up (left) by the value
+of the \fB\-resolution\fR option.
+.IP [6]
+The Down and Right keys move the slider down (right) by the value
+of the \fB\-resolution\fR option.
+.IP [7]
+Control-Up and Control-Left move the slider up (left) by the
+value of the \fB\-bigincrement\fR option.
+.IP [8]
+Control-Down and Control-Right move the slider down (right) by the
+value of the \fB\-bigincrement\fR option.
+.IP [9]
+Home moves the slider to the top (left) end of its range.
+.IP [10]
+End moves the slider to the bottom (right) end of its range.
+.PP
+If the scale is disabled using the \fB\-state\fR option then
+none of the above bindings have any effect.
+.PP
+The behavior of scales can be changed by defining new bindings for
+individual widgets or by redefining the class bindings.
+.SH "SEE ALSO"
+ttk::scale(n)
+.SH KEYWORDS
+scale, slider, trough, widget
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/scrollbar.n b/tk8.6/doc/scrollbar.n
new file mode 100644
index 0000000..4d148af
--- /dev/null
+++ b/tk8.6/doc/scrollbar.n
@@ -0,0 +1,360 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH scrollbar n 4.1 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+scrollbar \- Create and manipulate 'scrollbar' scrolling control and indicator widgets
+.SH SYNOPSIS
+\fBscrollbar\fR \fIpathName \fR?\fIoptions\fR?
+.SO
+\-activebackground \-highlightcolor \-repeatdelay
+\-background \-highlightthickness \-repeatinterval
+\-borderwidth \-jump \-takefocus
+\-cursor \-orient \-troughcolor
+\-highlightbackground \-relief
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-activerelief activeRelief ActiveRelief
+Specifies the relief to use when displaying the element that is
+active, if any.
+Elements other than the active element are always displayed with
+a raised relief.
+.OP \-command command Command
+Specifies the prefix of a Tcl command to invoke to change the view
+in the widget associated with the scrollbar. When a user requests
+a view change by manipulating the scrollbar, a Tcl command is
+invoked. The actual command consists of this option followed by
+additional information as described later. This option almost always has
+a value such as \fB.t xview\fR or \fB.t yview\fR, consisting of the
+name of a widget and either \fBxview\fR (if the scrollbar is for
+horizontal scrolling) or \fByview\fR (for vertical scrolling).
+All scrollable widgets have \fBxview\fR and \fByview\fR commands
+that take exactly the additional arguments appended by the scrollbar
+as described in \fBSCROLLING COMMANDS\fR below.
+.OP \-elementborderwidth elementBorderWidth BorderWidth
+Specifies the width of borders drawn around the internal elements
+of the scrollbar (the two arrows and the slider). The value may
+have any of the forms acceptable to \fBTk_GetPixels\fR.
+If this value is less than zero, the value of the \fB\-borderwidth\fR
+option is used in its place.
+.OP \-width width Width
+Specifies the desired narrow dimension of the scrollbar window,
+not including 3-D border, if any. For vertical
+scrollbars this will be the width and for horizontal scrollbars
+this will be the height.
+The value may have any of the forms acceptable to \fBTk_GetPixels\fR.
+.BE
+.SH DESCRIPTION
+.PP
+The \fBscrollbar\fR command creates a new window (given by the
+\fIpathName\fR argument) and makes it into a scrollbar widget.
+Additional options, described above, may be specified on the command
+line or in the option database to configure aspects of the scrollbar
+such as its colors, orientation, and relief.
+The \fBscrollbar\fR command returns its \fIpathName\fR argument.
+At the time this command is invoked, there must not exist a window
+named \fIpathName\fR, but \fIpathName\fR's parent must exist.
+.PP
+A scrollbar is a widget that displays two arrows, one at each end of
+the scrollbar, and a \fIslider\fR in the middle portion of the
+scrollbar.
+It provides information about what is visible in an \fIassociated window\fR
+that displays a document of some sort (such as a file being edited or
+a drawing).
+The position and size of the slider indicate which portion of the
+document is visible in the associated window. For example, if the
+slider in a vertical scrollbar covers the top third of the area
+between the two arrows, it means that the associated window displays
+the top third of its document.
+.PP
+Scrollbars can be used to adjust the view in the associated window
+by clicking or dragging with the mouse. See the \fBBINDINGS\fR section
+below for details.
+.SH "ELEMENTS"
+.PP
+A scrollbar displays five elements, which are referred to in the
+widget commands for the scrollbar:
+.TP 10
+\fBarrow1\fR
+The top or left arrow in the scrollbar.
+.TP 10
+\fBtrough1\fR
+The region between the slider and \fBarrow1\fR.
+.TP 10
+\fBslider\fR
+The rectangle that indicates what is visible in the associated widget.
+.TP 10
+\fBtrough2\fR
+The region between the slider and \fBarrow2\fR.
+.TP 10
+\fBarrow2\fR
+The bottom or right arrow in the scrollbar.
+.SH "WIDGET COMMAND"
+.PP
+The \fBscrollbar\fR command creates a new Tcl command whose
+name is \fIpathName\fR. This
+command may be used to invoke various
+operations on the widget. It has the following general form:
+.CS
+\fIpathName option \fR?\fIarg arg ...\fR?
+.CE
+\fIOption\fR and the \fIarg\fRs
+determine the exact behavior of the command. The following
+commands are possible for scrollbar widgets:
+.TP
+\fIpathName \fBactivate \fR?\fIelement\fR?
+.
+Marks the element indicated by \fIelement\fR as active, which
+causes it to be displayed as specified by the \fB\-activebackground\fR
+and \fB\-activerelief\fR options.
+The only element values understood by this command are \fBarrow1\fR,
+\fBslider\fR, or \fBarrow2\fR.
+If any other value is specified then no element of the scrollbar
+will be active.
+If \fIelement\fR is not specified, the command returns
+the name of the element that is currently active, or an empty string
+if no element is active.
+.TP
+\fIpathName \fBcget \fIoption\fR
+.
+Returns the current value of the configuration option given
+by \fIoption\fR.
+\fIOption\fR may have any of the values accepted by the \fBscrollbar\fR
+command.
+.TP
+\fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
+.
+Query or modify the configuration options of the widget.
+If no \fIoption\fR is specified, returns a list describing all of
+the available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for
+information on the format of this list). If \fIoption\fR is specified
+with no \fIvalue\fR, then the command returns a list describing the
+one named option (this list will be identical to the corresponding
+sublist of the value returned if no \fIoption\fR is specified). If
+one or more \fIoption\-value\fR pairs are specified, then the command
+modifies the given widget option(s) to have the given value(s); in
+this case the command returns an empty string.
+\fIOption\fR may have any of the values accepted by the \fBscrollbar\fR
+command.
+.TP
+\fIpathName \fBdelta \fIdeltaX deltaY\fR
+.
+Returns a real number indicating the fractional change in
+the scrollbar setting that corresponds to a given change
+in slider position. For example, if the scrollbar is horizontal,
+the result indicates how much the scrollbar setting must change
+to move the slider \fIdeltaX\fR pixels to the right (\fIdeltaY\fR is
+ignored in this case).
+If the scrollbar is vertical, the result indicates how much the
+scrollbar setting must change to move the slider \fIdeltaY\fR pixels
+down. The arguments and the result may be zero or negative.
+.TP
+\fIpathName \fBfraction \fIx y\fR
+.
+Returns a real number between 0 and 1 indicating where the point
+given by \fIx\fR and \fIy\fR lies in the trough area of the scrollbar.
+The value 0 corresponds to the top or left of the trough, the
+value 1 corresponds to the bottom or right, 0.5 corresponds to
+the middle, and so on.
+\fIX\fR and \fIy\fR must be pixel coordinates relative to the scrollbar
+widget.
+If \fIx\fR and \fIy\fR refer to a point outside the trough, the closest
+point in the trough is used.
+.TP
+\fIpathName \fBget\fR
+.
+Returns the scrollbar settings in the form of a list whose
+elements are the arguments to the most recent \fBset\fR widget command.
+.TP
+\fIpathName \fBidentify \fIx y\fR
+.
+Returns the name of the element under the point given by \fIx\fR and
+\fIy\fR (such as \fBarrow1\fR), or an empty string if the point does
+not lie in any element of the scrollbar.
+\fIX\fR and \fIy\fR must be pixel coordinates relative to the scrollbar
+widget.
+.TP
+\fIpathName \fBset \fIfirst last\fR
+.
+This command is invoked by the scrollbar's associated widget to
+tell the scrollbar about the current view in the widget.
+The command takes two arguments, each of which is a real fraction
+between 0 and 1.
+The fractions describe the range of the document that is visible in
+the associated widget.
+For example, if \fIfirst\fR is 0.2 and \fIlast\fR is 0.4, it means
+that the first part of the document visible in the window is 20%
+of the way through the document, and the last visible part is 40%
+of the way through.
+.SH "SCROLLING COMMANDS"
+.PP
+When the user interacts with the scrollbar, for example by dragging
+the slider, the scrollbar notifies the associated widget that it
+must change its view.
+The scrollbar makes the notification by evaluating a Tcl command
+generated from the scrollbar's \fB\-command\fR option.
+The command may take any of the following forms.
+In each case, \fIprefix\fR is the contents of the
+\fB\-command\fR option, which usually has a form like
+.QW \fB.t yview\fR .
+.TP
+\fIprefix \fBmoveto \fIfraction\fR
+.
+\fIFraction\fR is a real number between 0 and 1.
+The widget should adjust its view so that the point given
+by \fIfraction\fR appears at the beginning of the widget.
+If \fIfraction\fR is 0 it refers to the beginning of the
+document. 1.0 refers to the end of the document, 0.333
+refers to a point one-third of the way through the document,
+and so on.
+.TP
+\fIprefix \fBscroll \fInumber \fBunits\fR
+.
+The widget should adjust its view by \fInumber\fR units.
+The units are defined in whatever way makes sense for the widget,
+such as characters or lines in a text widget.
+\fINumber\fR is either 1, which means one unit should scroll off
+the top or left of the window, or \-1, which means that one unit
+should scroll off the bottom or right of the window.
+.TP
+\fIprefix \fBscroll \fInumber \fBpages\fR
+.
+The widget should adjust its view by \fInumber\fR pages.
+It is up to the widget to define the meaning of a page; typically
+it is slightly less than what fits in the window, so that there
+is a slight overlap between the old and new views.
+\fINumber\fR is either 1, which means the next page should
+become visible, or \-1, which means that the previous page should
+become visible.
+.SH "OLD COMMAND SYNTAX"
+.PP
+In versions of Tk before 4.0, the \fBset\fR and \fBget\fR widget
+commands used a different form.
+This form is still supported for backward compatibility, but it
+is deprecated.
+In the old command syntax, the \fBset\fR widget command has the
+following form:
+.TP
+\fIpathName \fBset \fItotalUnits windowUnits firstUnit lastUnit\fR
+In this form the arguments are all integers.
+\fITotalUnits\fR gives the total size of the object being displayed in the
+associated widget. The meaning of one unit depends on the associated
+widget; for example, in a text editor widget units might
+correspond to lines of
+text. \fIWindowUnits\fR indicates the total number of units that
+can fit in the associated window at one time. \fIFirstUnit\fR
+and \fIlastUnit\fR give the indices of the first and last units
+currently visible in the associated window (zero corresponds to the
+first unit of the object).
+.LP
+Under the old syntax the \fBget\fR widget command returns a list
+of four integers, consisting of the \fItotalUnits\fR, \fIwindowUnits\fR,
+\fIfirstUnit\fR, and \fIlastUnit\fR values from the last \fBset\fR
+widget command.
+.PP
+The commands generated by scrollbars also have a different form
+when the old syntax is being used:
+.TP
+\fIprefix\fR \fIunit\fR
+\fIUnit\fR is an integer that indicates what should appear at
+the top or left of the associated widget's window.
+It has the same meaning as the \fIfirstUnit\fR and \fIlastUnit\fR
+arguments to the \fBset\fR widget command.
+.LP
+The most recent \fBset\fR widget command determines whether or not
+to use the old syntax.
+If it is given two real arguments then the new syntax will be
+used in the future, and if it is given four integer arguments then
+the old syntax will be used.
+.SH BINDINGS
+.PP
+Tk automatically creates class bindings for scrollbars that give them
+the following default behavior.
+If the behavior is different for vertical and horizontal scrollbars,
+the horizontal behavior is described in parentheses.
+.IP [1]
+Pressing button 1 over \fBarrow1\fR causes the view in the
+associated widget to shift up (left) by one unit so that the
+document appears to move down (right) one unit.
+If the button is held down, the action auto-repeats.
+.IP [2]
+Pressing button 1 over \fBtrough1\fR causes the view in the
+associated widget to shift up (left) by one screenful so that the
+document appears to move down (right) one screenful.
+If the button is held down, the action auto-repeats.
+.IP [3]
+Pressing button 1 over the slider and dragging causes the view
+to drag with the slider.
+If the \fBjump\fR option is true, then the view does not drag along
+with the slider; it changes only when the mouse button is released.
+.IP [4]
+Pressing button 1 over \fBtrough2\fR causes the view in the
+associated widget to shift down (right) by one screenful so that the
+document appears to move up (left) one screenful.
+If the button is held down, the action auto-repeats.
+.IP [5]
+Pressing button 1 over \fBarrow2\fR causes the view in the
+associated widget to shift down (right) by one unit so that the
+document appears to move up (left) one unit.
+If the button is held down, the action auto-repeats.
+.IP [6]
+If button 2 is pressed over the trough or the slider, it sets
+the view to correspond to the mouse position; dragging the
+mouse with button 2 down causes the view to drag with the mouse.
+If button 2 is pressed over one of the arrows, it causes the
+same behavior as pressing button 1.
+.IP [7]
+If button 1 is pressed with the Control key down, then if the
+mouse is over \fBarrow1\fR or \fBtrough1\fR the view changes
+to the very top (left) of the document; if the mouse is over
+\fBarrow2\fR or \fBtrough2\fR the view changes
+to the very bottom (right) of the document; if the mouse is
+anywhere else then the button press has no effect.
+.IP [8]
+In vertical scrollbars the Up and Down keys have the same behavior
+as mouse clicks over \fBarrow1\fR and \fBarrow2\fR, respectively.
+In horizontal scrollbars these keys have no effect.
+.IP [9]
+In vertical scrollbars Control-Up and Control-Down have the same
+behavior as mouse clicks over \fBtrough1\fR and \fBtrough2\fR, respectively.
+In horizontal scrollbars these keys have no effect.
+.IP [10]
+In horizontal scrollbars the Up and Down keys have the same behavior
+as mouse clicks over \fBarrow1\fR and \fBarrow2\fR, respectively.
+In vertical scrollbars these keys have no effect.
+.IP [11]
+In horizontal scrollbars Control-Up and Control-Down have the same
+behavior as mouse clicks over \fBtrough1\fR and \fBtrough2\fR, respectively.
+In vertical scrollbars these keys have no effect.
+.IP [12]
+The Prior and Next keys have the same behavior
+as mouse clicks over \fBtrough1\fR and \fBtrough2\fR, respectively.
+.IP [13]
+The Home key adjusts the view to the top (left edge) of the document.
+.IP [14]
+The End key adjusts the view to the bottom (right edge) of the document.
+.SH EXAMPLE
+.PP
+Create a window with a scrollable \fBtext\fR widget:
+.CS
+toplevel .tl
+text .tl.t \-yscrollcommand {.tl.s set}
+\fBscrollbar\fR .tl.s \-command {.tl.t yview}
+grid .tl.t .tl.s \-sticky nsew
+grid columnconfigure .tl 0 \-weight 1
+grid rowconfigure .tl 0 \-weight 1
+.CE
+.SH "SEE ALSO"
+ttk:scrollbar(n)
+.SH KEYWORDS
+scrollbar, widget
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/selection.n b/tk8.6/doc/selection.n
new file mode 100644
index 0000000..ec678fa
--- /dev/null
+++ b/tk8.6/doc/selection.n
@@ -0,0 +1,206 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH selection n 8.1 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+selection \- Manipulate the X selection
+.SH SYNOPSIS
+\fBselection \fIoption\fR ?\fIarg arg ...\fR?
+.BE
+.SH DESCRIPTION
+.PP
+This command provides a Tcl interface to the X selection mechanism and
+implements the full selection functionality described in the
+X Inter-Client Communication Conventions Manual (ICCCM).
+.PP
+Note that for management of the \fBCLIPBOARD\fR selection (see below), the
+\fBclipboard\fR command may also be used.
+.PP
+The first argument to \fBselection\fR determines the format of the
+rest of the arguments and the behavior of the command. The following
+forms are currently supported:
+.TP
+\fBselection clear\fR ?\fB\-displayof\fR \fIwindow\fR? ?\fB\-selection\fR \fIselection\fR?
+.
+If \fIselection\fR exists anywhere on \fIwindow\fR's display, clear it
+so that no window owns the selection anymore. \fISelection\fR
+specifies the X selection that should be cleared, and should be an
+atom name such as \fBPRIMARY\fR or \fBCLIPBOARD\fR; see the Inter-Client
+Communication Conventions Manual for complete details.
+\fISelection\fR defaults to \fBPRIMARY\fR and \fIwindow\fR defaults to
+.QW . .
+Returns an empty string.
+.TP
+\fBselection get\fR ?\fB\-displayof\fR \fIwindow\fR? ?\fB\-selection\fR \fIselection\fR? ?\fB\-type\fR \fItype\fR?
+.
+Retrieves the value of \fIselection\fR from \fIwindow\fR's display and
+returns it as a result. \fISelection\fR defaults to \fBPRIMARY\fR and
+\fIwindow\fR defaults to
+.QW . .
+\fIType\fR specifies the form in which the selection is to be returned
+(the desired
+.QW target
+for conversion, in ICCCM terminology), and
+should be an atom name such as \fBSTRING\fR or \fBFILE_NAME\fR; see the
+Inter-Client Communication Conventions Manual for complete details.
+\fIType\fR defaults to \fBSTRING\fR. The selection owner may choose to
+return the selection in any of several different representation
+formats, such as \fBSTRING\fR, \fBUTF8_STRING\fR, \fBATOM\fR,
+\fBINTEGER\fR, etc. (this format is different
+than the selection type; see the ICCCM for all the confusing details).
+If the selection is returned in a non-string format, such as \fBINTEGER\fR
+or \fBATOM\fR, the \fBselection\fR command converts it to string format as a
+collection of fields separated by spaces: atoms are converted to their
+textual names, and anything else is converted to hexadecimal integers.
+Note that \fBselection get\fR does not retrieve the selection in the
+\fBUTF8_STRING\fR format unless told to.
+.TP
+\fBselection handle\fR ?\fB\-selection\fR \fIs\fR? ?\fB\-type\fR \fIt\fR? ?\fB\-format\fR \fIf\fR? \fIwindow command\fR
+.
+Creates a handler for selection requests, such that \fIcommand\fR will
+be executed whenever selection \fIs\fR is owned by \fIwindow\fR and
+someone attempts to retrieve it in the form given by type \fIt\fR
+(e.g. \fIt\fR is specified in the \fBselection get\fR command).
+\fIS\fR defaults to \fBPRIMARY\fR, \fIt\fR defaults to \fBSTRING\fR, and
+\fIf\fR defaults to \fBSTRING\fR. If \fIcommand\fR is an empty string
+then any existing handler for \fIwindow\fR, \fIt\fR, and
+\fIs\fR is removed.
+Note that when the selection is handled as type \fBSTRING\fR it is also
+automatically handled as type \fBUTF8_STRING\fR as well.
+.RS
+.PP
+When \fIselection\fR is requested, \fIwindow\fR is the selection owner,
+and \fItype\fR is the requested type, \fIcommand\fR will be executed
+as a Tcl command with two additional numbers appended to it
+(with space separators).
+The two additional numbers
+are \fIoffset\fR and \fImaxChars\fR: \fIoffset\fR specifies a starting
+character position in the selection and \fImaxChars\fR gives the maximum
+number of characters to retrieve. The command should return a value consisting
+of at most \fImaxChars\fR of the selection, starting at position
+\fIoffset\fR. For very large selections (larger than \fImaxChars\fR)
+the selection will be retrieved using several invocations of \fIcommand\fR
+with increasing \fIoffset\fR values. If \fIcommand\fR returns a string
+whose length is less than \fImaxChars\fR, the return value is assumed to
+include all of the remainder of the selection; if the length of
+\fIcommand\fR's result is equal to \fImaxChars\fR then
+\fIcommand\fR will be invoked again, until it eventually
+returns a result shorter than \fImaxChars\fR. The value of \fImaxChars\fR
+will always be relatively large (thousands of characters).
+.PP
+If \fIcommand\fR returns an error then the selection retrieval is rejected
+just as if the selection did not exist at all.
+.PP
+The \fIformat\fR argument specifies the representation that should be
+used to transmit the selection to the requester (the second column of
+Table 2 of the ICCCM), and defaults to \fBSTRING\fR. If \fIformat\fR is
+\fBSTRING\fR, the selection is transmitted as 8-bit ASCII characters (i.e.
+just in the form returned by \fIcommand\fR, in the system \fBencoding\fR;
+the \fBUTF8_STRING\fR format always uses UTF-8 as its encoding).
+If \fIformat\fR is
+\fBATOM\fR, then the return value from \fIcommand\fR is divided into fields
+separated by white space; each field is converted to its atom value,
+and the 32-bit atom value is transmitted instead of the atom name.
+For any other \fIformat\fR, the return value from \fIcommand\fR is
+divided into fields separated by white space and each field is
+converted to a 32-bit integer; an array of integers is transmitted
+to the selection requester.
+.PP
+The \fIformat\fR argument is needed only for compatibility with
+selection requesters that do not use Tk. If Tk is being
+used to retrieve the selection then the value is converted back to
+a string at the requesting end, so \fIformat\fR is
+irrelevant.
+.RE
+.TP
+\fBselection own\fR ?\fB\-displayof\fR \fIwindow\fR? ?\fB\-selection\fR \fIselection\fR?
+.TP
+\fBselection own\fR ?\fB\-command\fR \fIcommand\fR? ?\fB\-selection\fR \fIselection\fR? \fIwindow\fR
+.
+The first form of \fBselection own\fR returns the path name of the
+window in this application that owns \fIselection\fR on the display
+containing \fIwindow\fR, or an empty string if no window in this
+application owns the selection. \fISelection\fR defaults to \fBPRIMARY\fR and
+\fIwindow\fR defaults to
+.QW . .
+.RS
+.PP
+The second form of \fBselection own\fR causes \fIwindow\fR to become
+the new owner of \fIselection\fR on \fIwindow\fR's display, returning
+an empty string as result. The existing owner, if any, is notified
+that it has lost the selection.
+If \fIcommand\fR is specified, it is a Tcl script to execute when
+some other window claims ownership of the selection away from
+\fIwindow\fR. \fISelection\fR defaults to PRIMARY.
+.RE
+.SH WIDGET FACILITIES
+.PP
+The \fBtext\fR, \fBentry\fR, \fBttk::entry\fR, \fBlistbox\fR, \fBspinbox\fR and \fBttk::spinbox\fR widgets have the option \fB\-exportselection\fR. If a widget has this option set to boolean \fBtrue\fR, then (in an unsafe interpreter) a selection made in the widget is automatically written to the \fBPRIMARY\fR selection.
+.PP
+A GUI event, for example \fB<<PasteSelection>>\fR, can copy the \fBPRIMARY\fR selection to certain widgets. This copy is implemented by a widget binding to the event. The binding script makes appropriate calls to the \fBselection\fR command.
+.PP
+.SH PORTABILITY ISSUES
+.PP
+On X11, the \fBPRIMARY\fR selection is a system-wide feature of the X server, allowing communication between different processes that are X11 clients.
+.PP
+On Windows, the \fBPRIMARY\fR selection is not provided by the system, but only by Tk, and so it is shared only between windows of a master interpreter and its unsafe slave interpreters. It is not shared between interpreters in different processes or different threads. Each master interpreter has a separate \fBPRIMARY\fR selection that is shared only with its unsafe slaves.
+.PP
+.SH SECURITY
+.PP
+A safe interpreter cannot read from the \fBPRIMARY\fR selection because its \fBselection\fR command is hidden. For this reason the \fBPRIMARY\fR selection cannot be written to the Tk widgets of a safe interpreter.
+.PP
+A Tk widget can have its option \fB\-exportselection\fR set to boolean \fBtrue\fR, but in a safe interpreter this option has no effect: writing from the widget to the \fBPRIMARY\fR selection is disabled.
+.PP
+These are security features. A safe interpreter may run untrusted code, and it is a security risk if this untrusted code can read or write the \fBPRIMARY\fR selection used by other interpreters.
+.PP
+.SH EXAMPLES
+.PP
+On X11 platforms, one of the standard selections available is the
+\fBSECONDARY\fR selection. Hardly anything uses it, but here is how to read
+it using Tk:
+.PP
+.CS
+set selContents [\fBselection get\fR \-selection SECONDARY]
+.CE
+.PP
+Many different types of data may be available for a selection; the
+special type \fBTARGETS\fR allows you to get a list of available types:
+.PP
+.CS
+foreach type [\fBselection get\fR \-type TARGETS] {
+ puts "Selection PRIMARY supports type $type"
+}
+.CE
+.PP
+To claim the selection, you must first set up a handler to supply the
+data for the selection. Then you have to claim the selection...
+.CS
+# Set up the data handler ready for incoming requests
+set foo "This is a string with some data in it... blah blah"
+\fBselection handle\fR \-selection SECONDARY . getData
+proc getData {offset maxChars} {
+ puts "Retrieving selection starting at $offset"
+ return [string range $::foo $offset [expr {$offset+$maxChars-1}]]
+}
+
+# Now we grab the selection itself
+puts "Claiming selection"
+\fBselection own\fR \-command lost \-selection SECONDARY .
+proc lost {} {
+ puts "Lost selection"
+}
+.CE
+.SH "SEE ALSO"
+clipboard(n)
+.SH KEYWORDS
+clear, format, handler, ICCCM, own, selection, target, type
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/send.n b/tk8.6/doc/send.n
new file mode 100644
index 0000000..2a683d5
--- /dev/null
+++ b/tk8.6/doc/send.n
@@ -0,0 +1,109 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH send n 4.0 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+send \- Execute a command in a different application
+.SH SYNOPSIS
+\fBsend ?\fIoptions\fR? \fIapp cmd \fR?\fIarg arg ...\fR?
+.BE
+.SH DESCRIPTION
+.PP
+This command arranges for \fIcmd\fR (and \fIarg\fRs) to be executed in the
+application named by \fIapp\fR. It returns the result or
+error from that command execution.
+\fIApp\fR may be the name of any application whose main window is
+on the display containing the sender's main window; it need not
+be within the same process.
+If no \fIarg\fR arguments are present, then the command to be executed is
+contained entirely within the \fIcmd\fR argument. If one or
+more \fIarg\fRs are present, they are concatenated to form the
+command to be executed, just as for the \fBeval\fR command.
+.PP
+If the initial arguments of the command begin with
+.QW \-
+they are treated as options. The following options are currently defined:
+.TP
+\fB\-async\fR
+Requests asynchronous invocation. In this case the \fBsend\fR
+command will complete immediately without waiting for \fIcmd\fR
+to complete in the target application; no result will be available
+and errors in the sent command will be ignored.
+If the target application is in the same process as the sending
+application then the \fB\-async\fR option is ignored.
+.TP
+\fB\-displayof\fR \fIpathName\fR
+Specifies that the target application's main window is on the display
+of the window given by \fIpathName\fR, instead of the display containing
+the application's main window.
+.TP
+\fB\-\|\-\fR
+Serves no purpose except to terminate the list of options. This
+option is needed only if \fIapp\fR could contain a leading
+.QW \-
+character.
+.SH "APPLICATION NAMES"
+.PP
+The name of an application is set initially from the name of the
+program or script that created the application.
+You can query and change the name of an application with the
+\fBtk appname\fR command.
+.SH "DISABLING SENDS"
+.PP
+If the \fBsend\fR command is removed from an application (e.g.
+with the command \fBrename\fR \fBsend {}\fR) then the application
+will not respond to incoming send requests anymore, nor will it
+be able to issue outgoing requests.
+Communication can be reenabled by invoking the \fBtk appname\fR
+command.
+.SH SECURITY
+.PP
+The \fBsend\fR command is potentially a serious security loophole. On Unix,
+any application that can connect to your X server can send
+scripts to your applications.
+These incoming scripts can use Tcl to read and
+write your files and invoke subprocesses under your name.
+Host-based access control such as that provided by \fBxhost\fR
+is particularly insecure, since it allows anyone with an account
+on particular hosts to connect to your server, and if disabled it
+allows anyone anywhere to connect to your server.
+In order to provide at least a small amount of
+security, Tk checks the access control being used by the server
+and rejects incoming sends unless (a) \fBxhost\fR-style access control
+is enabled (i.e. only certain hosts can establish connections) and (b) the
+list of enabled hosts is empty.
+This means that applications cannot connect to your server unless
+they use some other form of authorization
+such as that provide by \fBxauth\fR.
+Under Windows, \fBsend\fR is currently disabled. Most of the
+functionality is provided by the \fBdde\fR command instead.
+.SH EXAMPLE
+.PP
+This script fragment can be used to make an application that only runs
+once on a particular display.
+.CS
+if {[tk appname FoobarApp] ne "FoobarApp"} {
+ \fBsend\fR \-async FoobarApp RemoteStart $argv
+ exit
+}
+# The command that will be called remotely, which raises
+# the application main window and opens the requested files
+proc RemoteStart args {
+ raise .
+ foreach filename $args {
+ OpenFile $filename
+ }
+}
+.CE
+.SH KEYWORDS
+application, dde, name, remote execution, security, send
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/spinbox.n b/tk8.6/doc/spinbox.n
new file mode 100644
index 0000000..acf06d6
--- /dev/null
+++ b/tk8.6/doc/spinbox.n
@@ -0,0 +1,602 @@
+'\"
+'\" Copyright (c) 2000 Jeffrey Hobbs.
+'\" Copyright (c) 2000 Ajuba Solutions.
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH spinbox n 8.4 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+spinbox \- Create and manipulate 'spinbox' value spinner widgets
+.SH SYNOPSIS
+\fBspinbox\fR \fIpathName \fR?\fIoptions\fR?
+.SO
+\-activebackground \-highlightthickness \-repeatinterval
+\-background \-insertbackground \-selectbackground
+\-borderwidth \-insertborderwidth \-selectborderwidth
+\-cursor \-insertontime \-selectforeground
+\-exportselection \-insertwidth \-takefocus
+\-font \-insertofftime \-textvariable
+\-foreground \-justify \-xscrollcommand
+\-highlightbackground \-relief
+\-highlightcolor \-repeatdelay
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-buttonbackground buttonBackground Background
+The background color to be used for the spin buttons.
+.OP \-buttoncursor buttonCursor Cursor
+The cursor to be used when over the spin buttons. If this is empty
+(the default), a default cursor will be used.
+.OP \-buttondownrelief buttonDownRelief Relief
+The relief to be used for the upper spin button.
+.OP \-buttonuprelief buttonUpRelief Relief
+The relief to be used for the lower spin button.
+.OP \-command command Command
+Specifies a Tcl command to invoke whenever a spinbutton is invoked.
+The command recognizes several percent substitutions: \fB%W\fR for
+the widget path, \fB%s\fR for the current value of the widget, and
+\fB%d\fR for the direction of the button pressed (\fBup\fR or \fBdown\fR).
+.OP \-disabledbackground disabledBackground DisabledBackground
+Specifies the background color to use when the spinbox is disabled. If
+this option is the empty string, the normal background color is used.
+.OP \-disabledforeground disabledForeground DisabledForeground
+Specifies the foreground color to use when the spinbox is disabled. If
+this option is the empty string, the normal foreground color is used.
+.OP \-format format Format
+Specifies an alternate format to use when setting the string value
+when using the \fB\-from\fR and \fB\-to\fR range.
+This must be a format specifier of the form \fB%<pad>.<pad>f\fR,
+as it will format a floating-point number.
+.OP \-from from From
+A floating-point value corresponding to the lowest value for a spinbox, to
+be used in conjunction with \fB\-to\fR and \fB\-increment\fR. When all
+are specified correctly, the spinbox will use these values to control its
+contents. This value must be less than the \fB\-to\fR option.
+If \fB\-values\fR is specified, it supersedes this option.
+.OP "\-invalidcommand or \-invcmd" invalidCommand InvalidCommand
+Specifies a script to eval when \fB\-validatecommand\fR returns 0. Setting
+it to an empty string disables this feature (the default). The best use of
+this option is to set it to \fIbell\fR. See \fBVALIDATION\fR below for
+more information.
+.OP \-increment increment Increment
+A floating-point value specifying the increment. When used with
+\fB\-from\fR and \fB\-to\fR, the value in the widget will be adjusted by
+\fB\-increment\fR when a spin button is pressed (up adds the value,
+down subtracts the value).
+.OP \-readonlybackground readonlyBackground ReadonlyBackground
+Specifies the background color to use when the spinbox is readonly. If
+this option is the empty string, the normal background color is used.
+.OP \-state state State
+Specifies one of three states for the spinbox: \fBnormal\fR,
+\fBdisabled\fR, or \fBreadonly\fR. If the spinbox is readonly, then the
+value may not be changed using widget commands and no insertion cursor
+will be displayed, even if the input focus is in the widget; the
+contents of the widget may still be selected. If the spinbox is
+disabled, the value may not be changed, no insertion cursor will be
+displayed, the contents will not be selectable, and the spinbox may
+be displayed in a different color, depending on the values of the
+\fB\-disabledforeground\fR and \fB\-disabledbackground\fR options.
+.OP \-to to To
+A floating-point value corresponding to the highest value for the spinbox,
+to be used in conjunction with \fB\-from\fR and \fB\-increment\fR. When
+all are specified correctly, the spinbox will use these values to control
+its contents. This value must be greater than the \fB\-from\fR option.
+If \fB\-values\fR is specified, it supersedes this option.
+.OP \-validate validate Validate
+Specifies the mode in which validation should operate: \fBnone\fR,
+\fBfocus\fR, \fBfocusin\fR, \fBfocusout\fR, \fBkey\fR, or \fBall\fR.
+It defaults to \fBnone\fR. When you want validation, you must explicitly
+state which mode you wish to use. See \fBVALIDATION\fR below for more.
+.OP "\-validatecommand or \-vcmd" validateCommand ValidateCommand
+Specifies a script to evaluate when you want to validate the input in the
+widget. Setting it to an empty string disables this feature (the default).
+Validation occurs according to the value of \fB\-validate\fR.
+This command must return a valid Tcl boolean value. If it returns 0 (or
+the valid Tcl boolean equivalent) then the value of the widget will not
+change and the \fB\-invalidcommand\fR will be evaluated if it is set. If it
+returns 1, then value will be changed.
+See \fBVALIDATION\fR below for more information.
+.OP \-values values Values
+Must be a proper list value. If specified, the spinbox will use these
+values as to control its contents, starting with the first value. This
+option has precedence over the \fB\-from\fR and \fB\-to\fR range.
+.OP \-width width Width
+Specifies an integer value indicating the desired width of the spinbox window,
+in average-size characters of the widget's font.
+If the value is less than or equal to zero, the widget picks a
+size just large enough to hold its current text.
+.OP \-wrap wrap wrap
+Must be a proper boolean value. If on, the spinbox will wrap around the
+values of data in the widget.
+.BE
+.SH DESCRIPTION
+.PP
+The \fBspinbox\fR command creates a new window (given by the
+\fIpathName\fR argument) and makes it into a spinbox widget.
+Additional options, described above, may be specified on the
+command line or in the option database
+to configure aspects of the spinbox such as its colors, font,
+and relief. The \fBspinbox\fR command returns its
+\fIpathName\fR argument. At the time this command is invoked,
+there must not exist a window named \fIpathName\fR, but
+\fIpathName\fR's parent must exist.
+.PP
+A \fBspinbox\fR is an extended \fBentry\fR widget that allows he user
+to move, or spin, through a fixed set of ascending or descending values
+such as times or dates in addition to editing the value as in an
+\fBentry\fR. When first created, a spinbox's string is empty.
+A portion of the spinbox may be selected as described below.
+If a spinbox is exporting its selection (see the \fB\-exportselection\fR
+option), then it will observe the standard protocols for handling the
+selection; spinbox selections are available as type \fBSTRING\fR.
+Spinboxes also observe the standard Tk rules for dealing with the
+input focus. When a spinbox has the input focus it displays an
+\fIinsertion cursor\fR to indicate where new characters will be
+inserted.
+.PP
+Spinboxes are capable of displaying strings that are too long to
+fit entirely within the widget's window. In this case, only a
+portion of the string will be displayed; commands described below
+may be used to change the view in the window. Spinboxes use
+the standard \fB\-xscrollcommand\fR mechanism for interacting with
+scrollbars (see the description of the \fB\-xscrollcommand\fR option
+for details). They also support scanning, as described below.
+.SH VALIDATION
+.PP
+Validation works by setting the \fB\-validatecommand\fR
+option to a script which will be evaluated according to the \fB\-validate\fR
+option as follows:
+.PP
+.IP \fBnone\fR 10
+Default. This means no validation will occur.
+.IP \fBfocus\fR 10
+The \fB\-validatecommand\fR will be called when the spinbox receives or
+loses focus.
+.IP \fBfocusin\fR 10
+The \fB\-validatecommand\fR will be called when the spinbox receives focus.
+.IP \fBfocusout\fR 10
+The \fB\-validatecommand\fR will be called when the spinbox loses focus.
+.IP \fBkey\fR 10
+The \fB\-validatecommand\fR will be called when the spinbox is edited.
+.IP \fBall\fR 10
+The \fB\-validatecommand\fR will be called for all above conditions.
+.PP
+It is possible to perform percent substitutions on the \fB\-validatecommand\fR
+and \fB\-invalidcommand\fR scripts, just as you would in a \fBbind\fR script. The
+following substitutions are recognized:
+.PP
+.IP \fB%d\fR 5
+Type of action: 1 for \fBinsert\fR, 0 for \fBdelete\fR,
+or \-1 for focus, forced or textvariable validation.
+.IP \fB%i\fR 5
+Index of char string to be inserted/deleted, if any, otherwise \-1.
+.IP \fB%P\fR 5
+The value of the spinbox should edition occur. If you are configuring the
+spinbox widget to have a new textvariable, this will be the value of that
+textvariable.
+.IP \fB%s\fR 5
+The current value of spinbox before edition.
+.IP \fB%S\fR 5
+The text string being inserted/deleted, if any.
+Otherwise it is an empty string.
+.IP \fB%v\fR 5
+The type of validation currently set.
+.IP \fB%V\fR 5
+The type of validation that triggered the callback
+(key, focusin, focusout, forced).
+.IP \fB%W\fR 5
+The name of the spinbox widget.
+.PP
+In general, the \fB\-textvariable\fR and \fB\-validatecommand\fR can be
+dangerous to mix. Any problems have been overcome so that using the
+\fB\-validatecommand\fR will not interfere with the traditional behavior of
+the spinbox widget. Using the \fB\-textvariable\fR for read-only purposes will
+never cause problems. The danger comes when you try set the
+\fB\-textvariable\fR to something that the \fB\-validatecommand\fR would not
+accept, which causes \fB\-validate\fR to become \fBnone\fR (the
+\fB\-invalidcommand\fR will not be triggered). The same happens
+when an error occurs evaluating the \fB\-validatecommand\fR.
+.PP
+Primarily, an error will occur when the \fB\-validatecommand\fR or
+\fB\-invalidcommand\fR encounters an error in its script while evaluating or
+\fB\-validatecommand\fR does not return a valid Tcl boolean value. The
+\fB\-validate\fR option will also set itself to \fBnone\fR when you edit the
+spinbox widget from within either the \fB\-validatecommand\fR or the
+\fB\-invalidcommand\fR. Such editions will override the one that was being
+validated. If you wish to edit the value of the widget
+during validation and still have the \fB\-validate\fR option set, you should
+include the command
+.CS
+ \fI%W config \-validate %v\fR
+.CE
+in the \fB\-validatecommand\fR or \fB\-invalidcommand\fR (whichever one you
+were editing the spinbox widget from). It is also recommended to not set an
+associated \fB\-textvariable\fR during validation, as that can cause the
+spinbox widget to become out of sync with the \fB\-textvariable\fR.
+.PP
+Also, the \fB-validate\fR option will set itself to \fBnone\fR when the
+spinbox value gets changed because of adjustment of \fB-from\fR or \fB-to\fR
+and the \fB-validatecommand\fR returns false. For instance
+.CS
+ \fIspinbox pathName \-from 1 \-to 10 \-validate all \-vcmd {return 0}\fR
+.CE
+will in fact set the \fB-validate\fR option to \fBnone\fR because the default
+value for the spinbox gets changed (due to the \fB-from\fR and \fB-to\fR
+options) to a value not accepted by the validation script.
+.PP
+Moreover, forced validation is performed when invoking any spinbutton of
+the spinbox. If the validation script returns false in this situation,
+then the \fB-validate\fR option will be automatically set to \fBnone\fR.
+.SH "WIDGET COMMAND"
+.PP
+The \fBspinbox\fR command creates a new Tcl command whose
+name is \fIpathName\fR. This command may be used to invoke various
+operations on the widget. It has the following general form:
+.CS
+\fIpathName option \fR?\fIarg arg ...\fR?
+.CE
+\fIOption\fR and the \fIarg\fRs
+determine the exact behavior of the command.
+.SS INDICES
+.PP
+Many of the widget commands for spinboxes take one or more indices as
+arguments. An index specifies a particular character in the spinbox's
+string, in any of the following ways:
+.TP 12
+\fInumber\fR
+Specifies the character as a numerical index, where 0 corresponds
+to the first character in the string.
+.TP 12
+\fBanchor\fR
+Indicates the anchor point for the selection, which is set with the
+\fBselect from\fR and \fBselect adjust\fR widget commands.
+.TP 12
+\fBend\fR
+Indicates the character just after the last one in the spinbox's string.
+This is equivalent to specifying a numerical index equal to the length
+of the spinbox's string.
+.TP 12
+\fBinsert\fR
+Indicates the character adjacent to and immediately following the
+insertion cursor.
+.TP 12
+\fBsel.first\fR
+Indicates the first character in the selection. It is an error to
+use this form if the selection is not in the spinbox window.
+.TP 12
+\fBsel.last\fR
+Indicates the character just after the last one in the selection.
+It is an error to use this form if the selection is not in the
+spinbox window.
+.TP 12
+\fB@\fInumber\fR
+In this form, \fInumber\fR is treated as an x-coordinate in the
+spinbox's window; the character spanning that x-coordinate is used.
+For example,
+.QW \fB@0\fR
+indicates the left-most character in the window.
+.LP
+Abbreviations may be used for any of the forms above, e.g.
+.QW \fBe\fR
+or
+.QW \fBsel.f\fR .
+In general, out-of-range indices are automatically rounded to the
+nearest legal value.
+.SS SUBCOMMANDS
+.PP
+The following commands are possible for spinbox widgets:
+.TP
+\fIpathName \fBbbox \fIindex\fR
+Returns a list of four numbers describing the bounding box of the
+character given by \fIindex\fR.
+The first two elements of the list give the x and y coordinates of
+the upper-left corner of the screen area covered by the character
+(in pixels relative to the widget) and the last two elements give
+the width and height of the character, in pixels.
+The bounding box may refer to a region outside the visible area
+of the window.
+.TP
+\fIpathName \fBcget\fR \fIoption\fR
+Returns the current value of the configuration option given
+by \fIoption\fR.
+\fIOption\fR may have any of the values accepted by the \fBspinbox\fR
+command.
+.TP
+\fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
+Query or modify the configuration options of the widget.
+If no \fIoption\fR is specified, returns a list describing all of
+the available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for
+information on the format of this list). If \fIoption\fR is specified
+with no \fIvalue\fR, then the command returns a list describing the
+one named option (this list will be identical to the corresponding
+sublist of the value returned if no \fIoption\fR is specified). If
+one or more \fIoption\-value\fR pairs are specified, then the command
+modifies the given widget option(s) to have the given value(s); in
+this case the command returns an empty string.
+\fIOption\fR may have any of the values accepted by the \fBspinbox\fR
+command.
+.TP
+\fIpathName \fBdelete \fIfirst \fR?\fIlast\fR?
+Delete one or more elements of the spinbox.
+\fIFirst\fR is the index of the first character to delete, and
+\fIlast\fR is the index of the character just after the last
+one to delete.
+If \fIlast\fR is not specified it defaults to \fIfirst\fR+1,
+i.e. a single character is deleted.
+This command returns an empty string.
+.TP
+\fIpathName \fBget\fR
+Returns the spinbox's string.
+.TP
+\fIpathName \fBicursor \fIindex\fR
+Arrange for the insertion cursor to be displayed just before the character
+given by \fIindex\fR. Returns an empty string.
+.TP
+\fIpathName \fBidentify\fI x y\fR
+Returns the name of the window element corresponding to coordinates
+\fIx\fR and \fIy\fR in the spinbox. Return value is one of:
+\fBnone\fR, \fBbuttondown\fR, \fBbuttonup\fR, \fBentry\fR.
+.TP
+\fIpathName \fBindex\fI index\fR
+Returns the numerical index corresponding to \fIindex\fR.
+.TP
+\fIpathName \fBinsert \fIindex string\fR
+Insert the characters of \fIstring\fR just before the character
+indicated by \fIindex\fR. Returns an empty string.
+.TP
+\fIpathName \fBinvoke\fI element\fR
+Causes the specified element, either \fBbuttondown\fR or \fBbuttonup\fR,
+to be invoked, triggering the action associated with it.
+.TP
+\fIpathName \fBscan\fR \fIoption args\fR
+This command is used to implement scanning on spinboxes. It has
+two forms, depending on \fIoption\fR:
+.RS
+.TP
+\fIpathName \fBscan mark \fIx\fR
+Records \fIx\fR and the current view in the spinbox window; used in
+conjunction with later \fBscan dragto\fR commands. Typically this
+command is associated with a mouse button press in the widget. It
+returns an empty string.
+.TP
+\fIpathName \fBscan dragto \fIx\fR
+This command computes the difference between its \fIx\fR argument
+and the \fIx\fR argument to the last \fBscan mark\fR command for
+the widget. It then adjusts the view left or right by 10 times the
+difference in x-coordinates. This command is typically associated
+with mouse motion events in the widget, to produce the effect of
+dragging the spinbox at high speed through the window. The return
+value is an empty string.
+.RE
+.TP
+\fIpathName \fBselection \fIoption arg\fR
+This command is used to adjust the selection within a spinbox. It
+has several forms, depending on \fIoption\fR:
+.RS
+.TP
+\fIpathName \fBselection adjust \fIindex\fR
+Locate the end of the selection nearest to the character given by
+\fIindex\fR, and adjust that end of the selection to be at \fIindex\fR
+(i.e. including but not going beyond \fIindex\fR). The other
+end of the selection is made the anchor point for future
+\fBselect to\fR commands. If the selection
+is not currently in the spinbox, then a new selection is created to
+include the characters between \fIindex\fR and the most recent
+selection anchor point, inclusive.
+Returns an empty string.
+.TP
+\fIpathName \fBselection clear\fR
+Clear the selection if it is currently in this widget. If the
+selection is not in this widget then the command has no effect.
+Returns an empty string.
+.TP
+\fIpathName \fBselection element\fR ?\fIelement\fR?
+Sets or gets the currently selected element. If a spinbutton element
+is specified, it will be displayed depressed.
+.TP
+\fIpathName \fBselection from \fIindex\fR
+Set the selection anchor point to just before the character
+given by \fIindex\fR. Does not change the selection.
+Returns an empty string.
+.TP
+\fIpathName \fBselection present\fR
+Returns 1 if there is are characters selected in the spinbox,
+0 if nothing is selected.
+.TP
+\fIpathName \fBselection range \fIstart end\fR
+Sets the selection to include the characters starting with
+the one indexed by \fIstart\fR and ending with the one just
+before \fIend\fR.
+If \fIend\fR refers to the same character as \fIstart\fR or an
+earlier one, then the spinbox's selection is cleared.
+.TP
+\fIpathName \fBselection to \fIindex\fR
+If \fIindex\fR is before the anchor point, set the selection
+to the characters from \fIindex\fR up to but not including
+the anchor point.
+If \fIindex\fR is the same as the anchor point, do nothing.
+If \fIindex\fR is after the anchor point, set the selection
+to the characters from the anchor point up to but not including
+\fIindex\fR.
+The anchor point is determined by the most recent \fBselect from\fR
+or \fBselect adjust\fR command in this widget.
+If the selection is not in this widget then a new selection is
+created using the most recent anchor point specified for the widget.
+Returns an empty string.
+.RE
+.TP
+\fIpathName \fBset\fR ?\fIstring\fR?
+If \fIstring\fR is specified, the spinbox will try and set it to this
+value, otherwise it just returns the spinbox's string.
+If validation is on, it will occur when setting the string.
+.TP
+\fIpathName \fBvalidate\fR
+This command is used to force an evaluation of the \fB\-validatecommand\fR
+independent of the conditions specified by the \fB\-validate\fR option.
+This is done by temporarily setting the \fB\-validate\fR option to \fBall\fR.
+It returns 0 or 1.
+.TP
+\fIpathName \fBxview \fIargs\fR
+This command is used to query and change the horizontal position of the
+text in the widget's window. It can take any of the following
+forms:
+.RS
+.TP
+\fIpathName \fBxview\fR
+Returns a list containing two elements.
+Each element is a real fraction between 0 and 1; together they describe
+the horizontal span that is visible in the window.
+For example, if the first element is .2 and the second element is .6,
+20% of the spinbox's text is off-screen to the left, the middle 40% is visible
+in the window, and 40% of the text is off-screen to the right.
+These are the same values passed to scrollbars via the \fB\-xscrollcommand\fR
+option.
+.TP
+\fIpathName \fBxview \fIindex\fR
+Adjusts the view in the window so that the character given by \fIindex\fR
+is displayed at the left edge of the window.
+.TP
+\fIpathName \fBxview moveto\fI fraction\fR
+Adjusts the view in the window so that the character \fIfraction\fR of the
+way through the text appears at the left edge of the window.
+\fIFraction\fR must be a fraction between 0 and 1.
+.TP
+\fIpathName \fBxview scroll \fInumber what\fR
+This command shifts the view in the window left or right according to
+\fInumber\fR and \fIwhat\fR.
+\fINumber\fR must be an integer.
+\fIWhat\fR must be either \fBunits\fR or \fBpages\fR or an abbreviation
+of one of these.
+If \fIwhat\fR is \fBunits\fR, the view adjusts left or right by
+\fInumber\fR average-width characters on the display; if it is
+\fBpages\fR then the view adjusts by \fInumber\fR screenfuls.
+If \fInumber\fR is negative then characters farther to the left
+become visible; if it is positive then characters farther to the right
+become visible.
+.RE
+.SH "DEFAULT BINDINGS"
+.PP
+Tk automatically creates class bindings for spinboxes that give them
+the following default behavior.
+In the descriptions below,
+.QW word
+refers to a contiguous group of letters, digits, or
+.QW _
+characters, or any single character other than these.
+.IP [1]
+Clicking mouse button 1 positions the insertion cursor
+just before the character underneath the mouse cursor, sets the
+input focus to this widget, and clears any selection in the widget.
+Dragging with mouse button 1 strokes out a selection between
+the insertion cursor and the character under the mouse.
+.IP [2]
+Double-clicking with mouse button 1 selects the word under the mouse
+and positions the insertion cursor at the beginning of the word.
+Dragging after a double click will stroke out a selection consisting
+of whole words.
+.IP [3]
+Triple-clicking with mouse button 1 selects all of the text in the
+spinbox and positions the insertion cursor before the first character.
+.IP [4]
+The ends of the selection can be adjusted by dragging with mouse
+button 1 while the Shift key is down; this will adjust the end
+of the selection that was nearest to the mouse cursor when button
+1 was pressed.
+If the button is double-clicked before dragging then the selection
+will be adjusted in units of whole words.
+.IP [5]
+Clicking mouse button 1 with the Control key down will position the
+insertion cursor in the spinbox without affecting the selection.
+.IP [6]
+If any normal printing characters are typed in a spinbox, they are
+inserted at the point of the insertion cursor.
+.IP [7]
+The view in the spinbox can be adjusted by dragging with mouse button 2.
+If mouse button 2 is clicked without moving the mouse, the selection
+is copied into the spinbox at the position of the mouse cursor.
+.IP [8]
+If the mouse is dragged out of the spinbox on the left or right sides
+while button 1 is pressed, the spinbox will automatically scroll to
+make more text visible (if there is more text off-screen on the side
+where the mouse left the window).
+.IP [9]
+The Left and Right keys move the insertion cursor one character to the
+left or right; they also clear any selection in the spinbox and set
+the selection anchor.
+If Left or Right is typed with the Shift key down, then the insertion
+cursor moves and the selection is extended to include the new character.
+Control-Left and Control-Right move the insertion cursor by words, and
+Control-Shift-Left and Control-Shift-Right move the insertion cursor
+by words and also extend the selection.
+Control-b and Control-f behave the same as Left and Right, respectively.
+Meta-b and Meta-f behave the same as Control-Left and Control-Right,
+respectively.
+.IP [10]
+The Home key, or Control-a, will move the insertion cursor to the
+beginning of the spinbox and clear any selection in the spinbox.
+Shift-Home moves the insertion cursor to the beginning of the spinbox
+and also extends the selection to that point.
+.IP [11]
+The End key, or Control-e, will move the insertion cursor to the
+end of the spinbox and clear any selection in the spinbox.
+Shift-End moves the cursor to the end and extends the selection
+to that point.
+.IP [12]
+The Select key and Control-Space set the selection anchor to the position
+of the insertion cursor. They do not affect the current selection.
+Shift-Select and Control-Shift-Space adjust the selection to the
+current position of the insertion cursor, selecting from the anchor
+to the insertion cursor if there was not any selection previously.
+.IP [13]
+Control-/ selects all the text in the spinbox.
+.IP [14]
+Control-\e clears any selection in the spinbox.
+.IP [15]
+The F16 key (labelled Copy on many Sun workstations) or Meta-w
+copies the selection in the widget to the clipboard, if there is a selection.
+.IP [16]
+The F20 key (labelled Cut on many Sun workstations) or Control-w
+copies the selection in the widget to the clipboard and deletes
+the selection.
+If there is no selection in the widget then these keys have no effect.
+.IP [17]
+The F18 key (labelled Paste on many Sun workstations) or Control-y
+inserts the contents of the clipboard at the position of the
+insertion cursor.
+.IP [18]
+The Delete key deletes the selection, if there is one in the spinbox.
+If there is no selection, it deletes the character to the right of
+the insertion cursor.
+.IP [19]
+The BackSpace key and Control-h delete the selection, if there is one
+in the spinbox.
+If there is no selection, it deletes the character to the left of
+the insertion cursor.
+.IP [20]
+Control-d deletes the character to the right of the insertion cursor.
+.IP [21]
+Meta-d deletes the word to the right of the insertion cursor.
+.IP [22]
+Control-k deletes all the characters to the right of the insertion
+cursor.
+.IP [23]
+Control-t reverses the order of the two characters to the right of
+the insertion cursor.
+.PP
+If the spinbox is disabled using the \fB\-state\fR option, then the spinbox's
+view can still be adjusted and text in the spinbox can still be selected,
+but no insertion cursor will be displayed and no text modifications will
+take place.
+.PP
+The behavior of spinboxes can be changed by defining new bindings for
+individual widgets or by redefining the class bindings.
+.SH "SEE ALSO"
+ttk::spinbox(n)
+.SH KEYWORDS
+spinbox, entry, widget
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/text.n b/tk8.6/doc/text.n
new file mode 100644
index 0000000..2a161e6
--- /dev/null
+++ b/tk8.6/doc/text.n
@@ -0,0 +1,2285 @@
+'\"
+'\" Copyright (c) 1992 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH text n 8.5 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+text, tk_textCopy, tk_textCut, tk_textPaste \- Create and manipulate 'text' hypertext editing widgets
+.SH SYNOPSIS
+.nf
+\fBtext\fR \fIpathName \fR?\fIoptions\fR?
+\fBtk_textCopy\fR \fIpathName\fR
+\fBtk_textCut\fR \fIpathName\fR
+\fBtk_textPaste\fR \fIpathName\fR
+.SO
+\-background \-highlightthickness \-relief
+\-borderwidth \-insertbackground \-selectbackground
+\-cursor \-insertborderwidth \-selectborderwidth
+\-exportselection \-insertofftime \-selectforeground
+\-font \-insertontime \-setgrid
+\-foreground \-insertwidth \-takefocus
+\-highlightbackground \-padx \-xscrollcommand
+\-highlightcolor \-pady \-yscrollcommand
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-autoseparators autoSeparators AutoSeparators
+Specifies a boolean that says whether separators are automatically inserted in
+the undo stack. Only meaningful when the \fB\-undo\fR option is true.
+.OP \-blockcursor blockCursor BlockCursor
+Specifies a boolean that says whether the blinking insertion cursor should be
+drawn as a character-sized rectangular block. If false (the default) a thin
+vertical line is used for the insertion cursor.
+.OP \-endline endLine EndLine
+Specifies an integer line index representing the line of the underlying
+textual data store that should be just after the last line contained in
+the widget. This allows a text widget to reflect only a portion of a
+larger piece of text. Instead of an integer, the empty string can be
+provided to this configuration option, which will configure the widget
+to end at the very last line in the textual data store.
+.OP \-height height Height
+Specifies the desired height for the window, in units of characters in the
+font given by the \fB\-font\fR option. Must be at least one.
+.OP \-inactiveselectbackground inactiveSelectBackground Foreground
+Specifies the colour to use for the selection (the \fBsel\fR tag) when the
+window does not have the input focus. If empty, \fB{}\fR, then no selection is
+shown when the window does not have the focus.
+.OP \-insertunfocussed insertUnfocussed InsertUnfocussed
+.VS 8.6
+Specifies how to display the insertion cursor when the widget does not have
+the focus. Must be \fBnone\fR (the default) which means to not display the
+cursor, \fBhollow\fR which means to display a hollow box, or \fBsolid\fR which
+means to display a solid box. Note that \fBhollow\fR and \fBsolid\fR will
+appear very similar when the \fB\-blockcursor\fR option is false.
+.VE 8.6
+.OP \-maxundo maxUndo MaxUndo
+Specifies the maximum number of compound undo actions on the undo stack. A
+zero or a negative value imply an unlimited undo stack.
+.OP \-spacing1 spacing1 Spacing1
+Requests additional space above each text line in the widget, using any of the
+standard forms for screen distances. If a line wraps, this option only applies
+to the first line on the display. This option may be overridden with
+\fB\-spacing1\fR options in tags.
+.OP \-spacing2 spacing2 Spacing2
+For lines that wrap (so that they cover more than one line on the display)
+this option specifies additional space to provide between the display lines
+that represent a single line of text. The value may have any of the standard
+forms for screen distances. This option may be overridden with
+\fB\-spacing2\fR options in tags.
+.OP \-spacing3 spacing3 Spacing3
+Requests additional space below each text line in the widget, using any of the
+standard forms for screen distances. If a line wraps, this option only applies
+to the last line on the display. This option may be overridden with
+\fB\-spacing3\fR options in tags.
+.OP \-startline startLine StartLine
+Specifies an integer line index representing the first line of the underlying
+textual data store that should be contained in the widget. This allows a text
+widget to reflect only a portion of a larger piece of text. Instead of an
+integer, the empty string can be provided to this configuration option, which
+will configure the widget to start at the very first line in the textual data
+store.
+.OP \-state state State
+Specifies one of two states for the text: \fBnormal\fR or \fBdisabled\fR. If
+the text is disabled then characters may not be inserted or deleted and no
+insertion cursor will be displayed, even if the input focus is in the widget.
+.OP \-tabs tabs Tabs
+Specifies a set of tab stops for the window. The option's value consists of a
+list of screen distances giving the positions of the tab stops, each of which
+is a distance relative to the left edge of the widget (excluding borders,
+padding, etc). Each position may optionally be followed in the next list
+element by one of the keywords \fBleft\fR, \fBright\fR, \fBcenter\fR, or
+\fBnumeric\fR, which specifies how to justify text relative to the tab stop.
+\fBLeft\fR is the default; it causes the text following the tab character to
+be positioned with its left edge at the tab position. \fBRight\fR means that
+the right edge of the text following the tab character is positioned at the
+tab position, and \fBcenter\fR means that the text is centered at the tab
+position. \fBNumeric\fR means that the decimal point in the text is positioned
+at the tab position; if there is no decimal point then the least significant
+digit of the number is positioned just to the left of the tab position; if
+there is no number in the text then the text is right-justified at the tab
+position. For example,
+.QW "\fB\-tabs {2c left 4c 6c center}\fR"
+creates three tab stops at two-centimeter intervals; the first two use left
+justification and the third uses center justification.
+.RS
+.PP
+If the list of tab stops does not have enough elements to cover all of the
+tabs in a text line, then Tk extrapolates new tab stops using the spacing and
+alignment from the last tab stop in the list. Tab distances must be strictly
+positive, and must always increase from one tab stop to the next (if not, an
+error is thrown). The value of the \fB\-tabs\fR option may be overridden by
+\fB\-tabs\fR options in tags.
+.PP
+If no \fB\-tabs\fR option is specified, or if it is specified as an empty
+list, then Tk uses default tabs spaced every eight (average size) characters.
+To achieve a different standard spacing, for example every 4 characters,
+simply configure the widget with
+.QW "\fB\-tabs \N'34'[expr {4 * [font measure $font 0]}] left\N'34' \-tabstyle wordprocessor\fR" .
+.RE
+.OP \-tabstyle tabStyle TabStyle
+Specifies how to interpret the relationship between tab stops on a line and
+tabs in the text of that line. The value must be \fBtabular\fR (the default)
+or \fBwordprocessor\fR. Note that tabs are interpreted as they are encountered
+in the text. If the tab style is \fBtabular\fR then the \fIn\fR'th tab
+character in the line's text will be associated with the \fIn\fR'th tab stop
+defined for that line. If the tab character's x coordinate falls to the right
+of the \fIn\fR'th tab stop, then a gap of a single space will be inserted as a
+fallback. If the tab style is \fBwordprocessor\fR then any tab character being
+laid out will use (and be defined by) the first tab stop to the right of the
+preceding characters already laid out on that line. The value of the
+\fB\-tabstyle\fR option may be overridden by \fB\-tabstyle\fR options in tags.
+.OP \-undo undo Undo
+Specifies a boolean that says whether the undo mechanism is active or not.
+.OP \-width width Width
+Specifies the desired width for the window in units of characters in the font
+given by the \fB\-font\fR option. If the font does not have a uniform width
+then the width of the character
+.QW 0
+is used in translating from character units to screen units.
+.OP \-wrap wrap Wrap
+Specifies how to handle lines in the text that are too long to be displayed in
+a single line of the text's window. The value must be \fBnone\fR or \fBchar\fR
+or \fBword\fR. A wrap mode of \fBnone\fR means that each line of text appears
+as exactly one line on the screen; extra characters that do not fit on the
+screen are not displayed. In the other modes each line of text will be broken
+up into several screen lines if necessary to keep all the characters visible.
+In \fBchar\fR mode a screen line break may occur after any character; in
+\fBword\fR mode a line break will only be made at word boundaries.
+.BE
+.SH DESCRIPTION
+.PP
+The \fBtext\fR command creates a new window (given by the \fIpathName\fR
+argument) and makes it into a text widget. Additional options, described
+above, may be specified on the command line or in the option database to
+configure aspects of the text such as its default background color and relief.
+The \fBtext\fR command returns the path name of the new window.
+.PP
+A text widget displays one or more lines of text and allows that text to be
+edited. Text widgets support four different kinds of annotations on the text,
+called tags, marks, embedded windows or embedded images. Tags allow different
+portions of the text to be displayed with different fonts and colors. In
+addition, Tcl commands can be associated with tags so that scripts are invoked
+when particular actions such as keystrokes and mouse button presses occur in
+particular ranges of the text. See \fBTAGS\fR below for more details.
+.PP
+The second form of annotation consists of floating markers in the text called
+.QW marks .
+Marks are used to keep track of various interesting positions in the text as
+it is edited. See \fBMARKS\fR below for more details.
+.PP
+The third form of annotation allows arbitrary windows to be embedded in a text
+widget. See \fBEMBEDDED WINDOWS\fR below for more details.
+.PP
+The fourth form of annotation allows Tk images to be embedded in a text
+widget. See \fBEMBEDDED IMAGES\fR below for more details.
+.PP
+The text widget also has a built-in undo/redo mechanism. See
+\fBTHE UNDO MECHANISM\fR below for more details.
+.PP
+The text widget allows for the creation of peer widgets. These are other text
+widgets which share the same underlying data (text, marks, tags, images, etc).
+See \fBPEER WIDGETS\fR below for more details.
+.SH INDICES
+.PP
+Many of the widget commands for texts take one or more indices as arguments.
+An index is a string used to indicate a particular place within a text, such
+as a place to insert characters or one endpoint of a range of characters to
+delete. Indices have the syntax
+.CS
+\fIbase modifier modifier modifier ...\fR
+.CE
+Where \fIbase\fR gives a starting point and the \fImodifier\fRs adjust the
+index from the starting point (e.g. move forward or backward one character).
+Every index must contain a \fIbase\fR, but the \fImodifier\fRs are optional.
+Most modifiers (as documented below) allow an optional submodifier. Valid
+submodifiers are \fBany\fR and \fBdisplay\fR. If the submodifier is
+abbreviated, then it must be followed by whitespace, but otherwise there need
+be no space between the submodifier and the following \fImodifier\fR.
+Typically the \fBdisplay\fR submodifier adjusts the meaning of the following
+\fImodifier\fR to make it refer to visual or non-elided units rather than
+logical units, but this is explained for each relevant case below. Lastly,
+where \fIcount\fR is used as part of a modifier, it can be positive or
+negative, so
+.QW "\fIbase\fR \- \-3 lines"
+is perfectly valid (and equivalent to
+.QW "\fIbase\fR +3lines" ).
+.PP
+The \fIbase\fR for an index must have one of the following forms:
+.TP 12
+\fIline\fB.\fIchar\fR
+.
+Indicates \fIchar\fR'th character on line \fIline\fR. Lines are numbered from
+1 for consistency with other UNIX programs that use this numbering scheme.
+Within a line, characters are numbered from 0. If \fIchar\fR is \fBend\fR then
+it refers to the newline character that ends the line.
+.TP 12
+\fB@\fIx\fB,\fIy\fR
+.
+Indicates the character that covers the pixel whose x and y coordinates within
+the text's window are \fIx\fR and \fIy\fR.
+.TP 12
+\fBend\fR
+.
+Indicates the end of the text (the character just after the last newline).
+.TP 12
+\fImark\fR
+.
+Indicates the character just after the mark whose name is \fImark\fR.
+.TP 12
+\fItag\fB.first\fR
+.
+Indicates the first character in the text that has been tagged with \fItag\fR.
+This form generates an error if no characters are currently tagged with
+\fItag\fR.
+.TP 12
+\fItag\fB.last\fR
+.
+Indicates the character just after the last one in the text that has been
+tagged with \fItag\fR. This form generates an error if no characters are
+currently tagged with \fItag\fR.
+.TP 12
+\fIpathName\fR
+.
+Indicates the position of the embedded window whose name is \fIpathName\fR.
+This form generates an error if there is no embedded window by the given name.
+.TP 12
+\fIimageName\fR
+.
+Indicates the position of the embedded image whose name is \fIimageName\fR.
+This form generates an error if there is no embedded image by the given name.
+.PP
+If the \fIbase\fR could match more than one of the above forms, such as a
+\fImark\fR and \fIimageName\fR both having the same value, then the form
+earlier in the above list takes precedence. If modifiers follow the base
+index, each one of them must have one of the forms listed below. Keywords such
+as \fBchars\fR and \fBwordend\fR may be abbreviated as long as the
+abbreviation is unambiguous.
+.TP
+\fB+ \fIcount\fR ?\fIsubmodifier\fR? \fBchars\fR
+.
+Adjust the index forward by \fIcount\fR characters, moving to later lines in
+the text if necessary. If there are fewer than \fIcount\fR characters in the
+text after the current index, then set the index to the last index in the
+text. Spaces on either side of \fIcount\fR are optional. If the \fBdisplay\fR
+submodifier is given, elided characters are skipped over without being
+counted. If \fBany\fR is given, then all characters are counted. For
+historical reasons, if neither modifier is given then the count actually takes
+place in units of index positions (see \fBINDICES\fR for details). This
+behaviour may be changed in a future major release, so if you need an index
+count, you are encouraged to use \fBindices\fR instead wherever possible.
+.TP
+\fB\- \fIcount\fR ?\fIsubmodifier\fR? \fBchars\fR
+.
+Adjust the index backward by \fIcount\fR characters, moving to earlier lines
+in the text if necessary. If there are fewer than \fIcount\fR characters in
+the text before the current index, then set the index to the first index in
+the text (1.0). Spaces on either side of \fIcount\fR are optional. If the
+\fBdisplay\fR submodifier is given, elided characters are skipped over without
+being counted. If \fBany\fR is given, then all characters are counted. For
+historical reasons, if neither modifier is given then the count actually takes
+place in units of index positions (see \fBINDICES\fR for details). This
+behavior may be changed in a future major release, so if you need an index
+count, you are encouraged to use \fBindices\fR instead wherever possible.
+.TP
+\fB+ \fIcount\fR ?\fIsubmodifier\fR? \fBindices\fR
+.
+Adjust the index forward by \fIcount\fR index positions, moving to later lines
+in the text if necessary. If there are fewer than \fIcount\fR index positions
+in the text after the current index, then set the index to the last index
+position in the text. Spaces on either side of \fIcount\fR are optional. Note
+that an index position is either a single character or a single embedded image
+or embedded window. If the \fBdisplay\fR submodifier is given, elided indices
+are skipped over without being counted. If \fBany\fR is given, then all
+indices are counted; this is also the default behaviour if no modifier is
+given.
+.TP
+\fB\- \fIcount\fR ?\fIsubmodifier\fR? \fBindices\fR
+.
+Adjust the index backward by \fIcount\fR index positions, moving to earlier
+lines in the text if necessary. If there are fewer than \fIcount\fR index
+positions in the text before the current index, then set the index to the
+first index position (1.0) in the text. Spaces on either side of \fIcount\fR
+are optional. If the \fBdisplay\fR submodifier is given, elided indices are
+skipped over without being counted. If \fBany\fR is given, then all indices
+are counted; this is also the default behaviour if no modifier is given.
+.TP
+\fB+ \fIcount\fR ?\fIsubmodifier\fR? \fBlines\fR
+.
+Adjust the index forward by \fIcount\fR lines, retaining the same character
+position within the line. If there are fewer than \fIcount\fR lines after the
+line containing the current index, then set the index to refer to the same
+character position on the last line of the text. Then, if the line is not long
+enough to contain a character at the indicated character position, adjust the
+character position to refer to the last character of the line (the newline).
+Spaces on either side of \fIcount\fR are optional. If the \fBdisplay\fR
+submodifier is given, then each visual display line is counted separately.
+Otherwise, if \fBany\fR (or no modifier) is given, then each logical line (no
+matter how many times it is visually wrapped) counts just once. If the
+relevant lines are not wrapped, then these two methods of counting are
+equivalent.
+.TP
+\fB\- \fIcount\fR ?\fIsubmodifier\fR? \fBlines\fR
+.
+Adjust the index backward by \fIcount\fR logical lines, retaining the same
+character position within the line. If there are fewer than \fIcount\fR lines
+before the line containing the current index, then set the index to refer to
+the same character position on the first line of the text. Then, if the line
+is not long enough to contain a character at the indicated character position,
+adjust the character position to refer to the last character of the line (the
+newline). Spaces on either side of \fIcount\fR are optional. If the
+\fBdisplay\fR submodifier is given, then each visual display line is counted
+separately. Otherwise, if \fBany\fR (or no modifier) is given, then each
+logical line (no matter how many times it is visually wrapped) counts just
+once. If the relevant lines are not wrapped, then these two methods of
+counting are equivalent.
+.TP
+?\fIsubmodifier\fR? \fBlinestart\fR
+.
+Adjust the index to refer to the first index on the line. If the \fBdisplay\fR
+submodifier is given, this is the first index on the display line, otherwise
+on the logical line.
+.TP
+?\fIsubmodifier\fR? \fBlineend\fR
+.
+Adjust the index to refer to the last index on the line (the newline). If the
+\fBdisplay\fR submodifier is given, this is the last index on the display
+line, otherwise on the logical line.
+.TP
+?\fIsubmodifier\fR? \fBwordstart\fR
+.
+Adjust the index to refer to the first character of the word containing the
+current index. A word consists of any number of adjacent characters that are
+letters, digits, or underscores, or a single character that is not one of
+these. If the \fBdisplay\fR submodifier is given, this only examines
+non-elided characters, otherwise all characters (elided or not) are examined.
+.TP
+?\fIsubmodifier\fR? \fBwordend\fR
+.
+Adjust the index to refer to the character just after the last one of the word
+containing the current index. If the current index refers to the last
+character of the text then it is not modified. If the \fBdisplay\fR
+submodifier is given, this only examines non-elided characters, otherwise all
+characters (elided or not) are examined.
+.PP
+If more than one modifier is present then they are applied in left-to-right
+order. For example, the index
+.QW "\fBend \- 1 chars\fR"
+refers to the next-to-last character in the text and
+.QW "\fBinsert wordstart \- 1 c\fR"
+refers to the character just before the first one in the word containing the
+insertion cursor. Modifiers are applied one by one in this left to right
+order, and after each step the resulting index is constrained to be a valid
+index in the text widget. So, for example, the index
+.QW "\fB1.0 \-1c +1c\fR"
+refers to the index
+.QW \fB2.0\fR .
+.PP
+Where modifiers result in index changes by display lines, display chars or
+display indices, and the \fIbase\fR refers to an index inside an elided tag,
+that base index is considered to be equivalent to the first following
+non-elided index.
+.SH TAGS
+.PP
+The first form of annotation in text widgets is a tag. A tag is a textual
+string that is associated with some of the characters in a text. Tags may
+contain arbitrary characters, but it is probably best to avoid using the
+characters
+.QW " "
+(space), \fB+\fR, or \fB\-\fR: these characters have special meaning in
+indices, so tags containing them cannot be used as indices. There may be any
+number of tags associated with characters in a text. Each tag may refer to a
+single character, a range of characters, or several ranges of characters. An
+individual character may have any number of tags associated with it.
+.PP
+A priority order is defined among tags, and this order is used in implementing
+some of the tag-related functions described below. When a tag is defined (by
+associating it with characters or setting its display options or binding
+commands to it), it is given a priority higher than any existing tag. The
+priority order of tags may be redefined using the
+.QW "\fIpathName \fBtag raise\fR"
+and
+.QW "\fIpathName \fBtag lower\fR"
+widget commands.
+.PP
+Tags serve three purposes in text widgets. First, they control the way
+information is displayed on the screen. By default, characters are displayed
+as determined by the \fB\-background\fR, \fB\-font\fR, and \fB\-foreground\fR
+options for the text widget. However, display options may be associated with
+individual tags using the
+.QW "\fIpathName \fBtag configure\fR"
+widget command. If a character has been tagged, then the display options
+associated with the tag override the default display style. The following
+options are currently supported for tags:
+.TP
+\fB\-background \fIcolor\fR
+.
+\fIColor\fR specifies the background color to use for characters associated
+with the tag. It may have any of the forms accepted by \fBTk_GetColor\fR.
+.TP
+\fB\-bgstipple \fIbitmap\fR
+.
+\fIBitmap\fR specifies a bitmap that is used as a stipple pattern for the
+background. It may have any of the forms accepted by \fBTk_GetBitmap\fR. If
+\fIbitmap\fR has not been specified, or if it is specified as an empty string,
+then a solid fill will be used for the background.
+.TP
+\fB\-borderwidth \fIpixels\fR
+.
+\fIPixels\fR specifies the width of a border to draw around the tag using any
+of the forms accepted by \fBTk_GetPixels\fR. This option should be used in
+conjunction with the \fB\-relief\fR option to provide the desired border.
+.TP
+\fB\-elide \fIboolean\fR
+.
+\fIElide\fR specifies whether the data should be elided. Elided data
+(characters, images, embedded windows, etc.) is not displayed and takes no
+space on screen, but further on behaves just as normal data.
+.TP
+\fB\-fgstipple \fIbitmap\fR
+.
+\fIBitmap\fR specifies a bitmap that is used as a stipple pattern when drawing
+text and other foreground information such as underlines. It may have any of
+the forms accepted by \fBTk_GetBitmap\fR. If \fIbitmap\fR has not been
+specified, or if it is specified as an empty string, then a solid fill will be
+used.
+.TP
+\fB\-font \fIfontName\fR
+.
+\fIFontName\fR is the name of a font to use for drawing characters. It may
+have any of the forms accepted by \fBTk_GetFont\fR.
+.TP
+\fB\-foreground \fIcolor\fR
+.
+\fIColor\fR specifies the color to use when drawing text and other foreground
+information such as underlines. It may have any of the forms accepted by
+\fBTk_GetColor\fR.
+.TP
+\fB\-justify \fIjustify\fR
+.
+If the first non-elided character of a display line has a tag for which this
+option has been specified, then \fIjustify\fR determines how to justify the
+line. It must be one of \fBleft\fR, \fBright\fR, or \fBcenter\fR. If a line
+wraps, then the justification for each line on the display is determined by
+the first non-elided character of that display line.
+.TP
+\fB\-lmargin1 \fIpixels\fR
+.
+If the first non-elided character of a text line has a tag for which this
+option has been specified, then \fIpixels\fR specifies how much the line
+should be indented from the left edge of the window. \fIPixels\fR may have any
+of the standard forms for screen distances. If a line of text wraps, this
+option only applies to the first line on the display; the \fB\-lmargin2\fR
+option controls the indentation for subsequent lines.
+.TP
+\fB\-lmargin2 \fIpixels\fR
+.
+If the first non-elided character of a display line has a tag for which this
+option has been specified, and if the display line is not the first for its
+text line (i.e., the text line has wrapped), then \fIpixels\fR specifies how
+much the line should be indented from the left edge of the window.
+\fIPixels\fR may have any of the standard forms for screen distances. This
+option is only used when wrapping is enabled, and it only applies to the
+second and later display lines for a text line.
+.TP
+\fB\-lmargincolor \fIcolor\fR
+.
+\fIColor\fR specifies the background color to use in regions that do not
+contain characters because they are indented by \fB\-lmargin1\fR or
+\fB\-lmargin2\fR. It may have any of the forms accepted by
+\fBTk_GetColor\fR. If \fIcolor\fR has not been specified, or if it is
+specified as an empty string, then the color used is specified by the
+\fB-background\fR tag option (or, if this is also unspecified, by the
+\fB-background\fR widget option).
+.TP
+\fB\-offset \fIpixels\fR
+.
+\fIPixels\fR specifies an amount by which the text's baseline should be offset
+vertically from the baseline of the overall line, in pixels. For example, a
+positive offset can be used for superscripts and a negative offset can be used
+for subscripts. \fIPixels\fR may have any of the standard forms for screen
+distances.
+.TP
+\fB\-overstrike \fIboolean\fR
+.
+Specifies whether or not to draw a horizontal rule through the middle of
+characters. \fIBoolean\fR may have any of the forms accepted by
+\fBTcl_GetBoolean\fR.
+.TP
+\fB\-overstrikefg \fIcolor\fR
+.
+\fIColor\fR specifies the color to use when displaying the overstrike. It may
+have any of the forms accepted by \fBTk_GetColor\fR. If \fIcolor\fR has not
+been specified, or if it is specified as an empty string, then the color
+specified by the \fB\-foreground\fR tag option is used.
+.TP
+\fB\-relief \fIrelief\fR
+.
+\fIRelief\fR specifies the relief style to use for drawing the border, in any
+of the forms accepted by \fBTk_GetRelief\fR. This option is used in
+conjunction with the \fB\-borderwidth\fR option to enable to the desired
+border appearance.
+.TP
+\fB\-rmargin \fIpixels\fR
+.
+If the first non-elided character of a display line has a tag for which this
+option has been specified, then \fIpixels\fR specifies how wide a margin to
+leave between the end of the line and the right edge of the window.
+\fIPixels\fR may have any of the standard forms for screen distances. This
+option is only used when wrapping is enabled. If a text line wraps, the right
+margin for each line on the display is determined by the first non-elided
+character of that display line.
+.TP
+\fB\-rmargincolor \fIcolor\fR
+.
+\fIColor\fR specifies the background color to use in regions that do not
+contain characters because they are indented by \fB\-rmargin\fR. It may
+have any of the forms accepted by \fBTk_GetColor\fR. If \fIcolor\fR has not
+been specified, or if it is specified as an empty string, then the color
+used is specified by the \fB-background\fR tag option (or, if this is also
+unspecified, by the \fB-background\fR widget option).
+.TP
+\fB\-selectbackground \fIcolor\fR
+\fIColor\fR specifies the background color to use when displaying selected
+items. It may have any of the forms accepted by \fBTk_GetColor\fR. If
+\fIcolor\fR has not been specified, or if it is specified as an empty
+string, then the color specified by the \fB\-background\fR tag option is
+used.
+.TP
+\fB\-selectforeground \fIcolor\fR
+\fIColor\fR specifies the foreground color to use when displaying selected
+items. It may have any of the forms accepted by \fBTk_GetColor\fR. If
+\fIcolor\fR has not been specified, or if it is specified as an empty
+string, then the color specified by the \fB\-foreground\fR tag option is
+used.
+.TP
+\fB\-spacing1 \fIpixels\fR
+.
+\fIPixels\fR specifies how much additional space should be left above each
+text line, using any of the standard forms for screen distances. If a line
+wraps, this option only applies to the first line on the display.
+.TP
+\fB\-spacing2 \fIpixels\fR
+.
+For lines that wrap, this option specifies how much additional space to leave
+between the display lines for a single text line. \fIPixels\fR may have any of
+the standard forms for screen distances.
+.TP
+\fB\-spacing3 \fIpixels\fR
+.
+\fIPixels\fR specifies how much additional space should be left below each
+text line, using any of the standard forms for screen distances. If a line
+wraps, this option only applies to the last line on the display.
+.TP
+\fB\-tabs \fItabList\fR
+.
+\fITabList\fR specifies a set of tab stops in the same form as for the
+\fB\-tabs\fR option for the text widget. This option only applies to a display
+line if it applies to the first non-elided character on that display line. If
+this option is specified as an empty string, it cancels the option, leaving it
+unspecified for the tag (the default). If the option is specified as a
+non-empty string that is an empty list, such as \fB\-tags\0{\0}\fR, then it
+requests default 8-character tabs as described for the \fB\-tags\fR widget
+option.
+.TP
+\fB\-tabstyle \fIstyle\fR
+.
+\fIStyle\fR specifies either the \fItabular\fR or \fIwordprocessor\fR style of
+tabbing to use for the text widget. This option only applies to a display line
+if it applies to the first non-elided character on that display line. If this
+option is specified as an empty string, it cancels the option, leaving it
+unspecified for the tag (the default).
+.TP
+\fB\-underline \fIboolean\fR
+.
+\fIBoolean\fR specifies whether or not to draw an underline underneath
+characters. It may have any of the forms accepted by \fBTcl_GetBoolean\fR.
+.TP
+\fB\-underlinefg \fIcolor\fR
+.
+\fIColor\fR specifies the color to use when displaying the underline. It may
+have any of the forms accepted by \fBTk_GetColor\fR. If \fIcolor\fR has not
+been specified, or if it is specified as an empty string, then the color
+specified by the \fB\-foreground\fR tag option is used.
+.TP
+\fB\-wrap \fImode\fR
+.
+\fIMode\fR specifies how to handle lines that are wider than the text's
+window. This option only applies to a display line if it applies to the
+first non-elided character on that display line. It has the same legal
+values as the \fB\-wrap\fR option for the text widget: \fBnone\fR,
+\fBchar\fR, or \fBword\fR. If this tag option is specified, it
+overrides the \fB\-wrap\fR option for the text widget.
+.PP
+If a character has several tags associated with it, and if their display
+options conflict, then the options of the highest priority tag are used. If a
+particular display option has not been specified for a particular tag, or if
+it is specified as an empty string, then that option will never be used; the
+next-highest-priority tag's option will used instead. If no tag specifies a
+particular display option, then the default style for the widget will be used.
+.PP
+The second purpose for tags is event bindings. You can associate bindings with
+a tag in much the same way you can associate bindings with a widget class:
+whenever particular X events occur on characters with the given tag, a given
+Tcl command will be executed. Tag bindings can be used to give behaviors to
+ranges of characters; among other things, this allows hypertext-like features
+to be implemented. For details, see the description of the
+.QW "\fIpathName \fBtag bind\fR"
+widget command below. Tag bindings are shared between all peer widgets
+(including any bindings for the special \fBsel\fR tag).
+.PP
+The third use for tags is in managing the selection. See \fBTHE SELECTION\fR
+below. With the exception of the special \fBsel\fR tag, all tags are shared
+between peer text widgets, and may be manipulated on an equal basis from any
+such widget. The \fBsel\fR tag exists separately and independently in each
+peer text widget (but any tag bindings to \fBsel\fR are shared).
+.SH MARKS
+.PP
+The second form of annotation in text widgets is a mark. Marks are used for
+remembering particular places in a text. They are something like tags, in that
+they have names and they refer to places in the file, but a mark is not
+associated with particular characters. Instead, a mark is associated with the
+gap between two characters. Only a single position may be associated with a
+mark at any given time. If the characters around a mark are deleted the mark
+will still remain; it will just have new neighbor characters. In contrast, if
+the characters containing a tag are deleted then the tag will no longer have
+an association with characters in the file. Marks may be manipulated with the
+.QW "\fIpathName \fBmark\fR"
+widget command, and their current locations may be determined by using the
+mark name as an index in widget commands.
+.PP
+Each mark also has a
+.QW gravity ,
+which is either \fBleft\fR or \fBright\fR. The gravity for a mark specifies
+what happens to the mark when text is inserted at the point of the mark. If a
+mark has left gravity, then the mark is treated as if it were attached to the
+character on its left, so the mark will remain to the left of any text
+inserted at the mark position. If the mark has right gravity, new text
+inserted at the mark position will appear to the left of the mark (so that the
+mark remains rightmost). The gravity for a mark defaults to \fBright\fR.
+.PP
+The name space for marks is different from that for tags: the same name may be
+used for both a mark and a tag, but they will refer to different things.
+.PP
+Two marks have special significance. First, the mark \fBinsert\fR is
+associated with the insertion cursor, as described under
+\fBTHE INSERTION CURSOR\fR
+below. Second, the mark \fBcurrent\fR is associated with the
+character closest to the mouse and is adjusted automatically to track the
+mouse position and any changes to the text in the widget (one exception:
+\fBcurrent\fR is not updated in response to mouse motions if a mouse button is
+down; the update will be deferred until all mouse buttons have been released).
+Neither of these special marks may be deleted. With the exception of these two
+special marks, all marks are shared between peer text widgets, and may be
+manipulated on an equal basis from any peer.
+.SH "EMBEDDED WINDOWS"
+.PP
+The third form of annotation in text widgets is an embedded window. Each
+embedded window annotation causes a window to be displayed at a particular
+point in the text. There may be any number of embedded windows in a text
+widget, and any widget may be used as an embedded window (subject to the usual
+rules for geometry management, which require the text window to be the parent
+of the embedded window or a descendant of its parent).
+.PP
+The embedded window's position on the screen will be updated as the text is
+modified or scrolled, and it will be mapped and unmapped as it moves into and
+out of the visible area of the text widget. Each embedded window occupies one
+unit's worth of index space in the text widget, and it may be referred to
+either by the name of its embedded window or by its position in the widget's
+index space. If the range of text containing the embedded window is deleted
+then the window is destroyed. Similarly if the text widget as a whole is
+deleted, then the window is destroyed.
+.PP
+Eliding an embedded window immediately after scheduling it for creation via
+\fIpathName \fBwindow create \fIindex \fB-create\fR will prevent it from being
+effectively created. Uneliding an elided embedded window scheduled for creation
+via \fIpathName \fBwindow create \fIindex \fB-create\fR will automatically
+trigger the associated creation script. After destroying an elided embedded
+window, the latter won't get automatically recreated.
+.PP
+When an embedded window is added to a text widget with the \fIpathName
+\fBwindow create\fR widget command, several configuration options may be
+associated with it. These options may be modified later with the \fIpathName
+\fBwindow configure\fR widget command. The following options are currently
+supported:
+.TP
+\fB\-align \fIwhere\fR
+.
+If the window is not as tall as the line in which it is displayed, this option
+determines where the window is displayed in the line. \fIWhere\fR must have
+one of the values \fBtop\fR (align the top of the window with the top of the
+line), \fBcenter\fR (center the window within the range of the line),
+\fBbottom\fR (align the bottom of the window with the bottom of the line's
+area), or \fBbaseline\fR (align the bottom of the window with the baseline of
+the line).
+.TP
+\fB\-create \fIscript\fR
+.
+Specifies a Tcl script that may be evaluated to create the window for the
+annotation. If no \fB\-window\fR option has been specified for the annotation
+this script will be evaluated when the annotation is about to be displayed on
+the screen. \fIScript\fR must create a window for the annotation and return
+the name of that window as its result. Two substitutions will be performed in
+\fIscript\fR before evaluation. \fI%W\fR will be substituted by the name of
+the parent text widget, and \fI%%\fR will be substituted by a single \fI%\fR.
+If the annotation's window should ever be deleted, \fIscript\fR will be
+evaluated again the next time the annotation is displayed.
+.TP
+\fB\-padx \fIpixels\fR
+.
+\fIPixels\fR specifies the amount of extra space to leave on each side of the
+embedded window. It may have any of the usual forms defined for a screen
+distance.
+.TP
+\fB\-pady \fIpixels\fR
+.
+\fIPixels\fR specifies the amount of extra space to leave on the top and on
+the bottom of the embedded window. It may have any of the usual forms defined
+for a screen distance.
+.TP
+\fB\-stretch \fIboolean\fR
+.
+If the requested height of the embedded window is less than the height of the
+line in which it is displayed, this option can be used to specify whether the
+window should be stretched vertically to fill its line. If the \fB\-pady\fR
+option has been specified as well, then the requested padding will be retained
+even if the window is stretched.
+.TP
+\fB\-window \fIpathName\fR
+.
+Specifies the name of a window to display in the annotation. Note that if a
+\fIpathName\fR has been set, then later configuring a window to the empty
+string will not delete the widget corresponding to the old \fIpathName\fR.
+Rather it will remove the association between the old \fIpathName\fR and the
+text widget. If multiple peer widgets are in use, it is usually simpler to use
+the \fB\-create\fR option if embedded windows are desired in each peer.
+.SH "EMBEDDED IMAGES"
+.PP
+The final form of annotation in text widgets is an embedded image. Each
+embedded image annotation causes an image to be displayed at a particular
+point in the text. There may be any number of embedded images in a text
+widget, and a particular image may be embedded in multiple places in the same
+text widget.
+.PP
+The embedded image's position on the screen will be updated as the text is
+modified or scrolled. Each embedded image occupies one unit's worth of index
+space in the text widget, and it may be referred to either by its position in
+the widget's index space, or the name it is assigned when the image is inserted
+into the text widget with \fIpathName \fBimage create\fR. If the range of text
+containing the embedded image is deleted then that copy of the image is removed
+from the screen.
+.PP
+Eliding an embedded image immediately after scheduling it for creation via
+\fIpathName \fBimage create \fIindex \fB-create\fR will prevent it from being
+effectively created. Uneliding an elided embedded image scheduled for creation
+via \fIpathName \fBimage create \fIindex \fB-create\fR will automatically
+trigger the associated creation script. After destroying an elided embedded
+image, the latter won't get automatically recreated.
+.PP
+When an embedded image is added to a text widget with the \fIpathName \fBimage
+create\fR widget command, a name unique to this instance of the image is
+returned. This name may then be used to refer to this image instance. The name
+is taken to be the value of the \fB\-name\fR option (described below). If the
+\fB\-name\fR option is not provided, the \fB\-image\fR name is used instead.
+If the \fIimageName\fR is already in use in the text widget, then \fB#\fInn\fR
+is added to the end of the \fIimageName\fR, where \fInn\fR is an arbitrary
+integer. This insures the \fIimageName\fR is unique. Once this name is
+assigned to this instance of the image, it does not change, even though the
+\fB\-image\fR or \fB\-name\fR values can be changed with \fIpathName \fBimage
+configure\fR.
+.PP
+When an embedded image is added to a text widget with the \fIpathName \fBimage
+create\fR widget command, several configuration options may be associated with
+it. These options may be modified later with the \fIpathName \fBimage
+configure\fR widget command. The following options are currently supported:
+.TP
+\fB\-align \fIwhere\fR
+.
+If the image is not as tall as the line in which it is displayed, this option
+determines where the image is displayed in the line. \fIWhere\fR must have one
+of the values \fBtop\fR (align the top of the image with the top of the line),
+\fBcenter\fR (center the image within the range of the line), \fBbottom\fR
+(align the bottom of the image with the bottom of the line's area), or
+\fBbaseline\fR (align the bottom of the image with the baseline of the line).
+.TP
+\fB\-image \fIimage\fR
+.
+Specifies the name of the Tk image to display in the annotation. If
+\fIimage\fR is not a valid Tk image, then an error is returned.
+.TP
+\fB\-name \fIImageName\fR
+.
+Specifies the name by which this image instance may be referenced in the text
+widget. If \fIImageName\fR is not supplied, then the name of the Tk image is
+used instead. If the \fIimageName\fR is already in use, \fI#nn\fR is appended
+to the end of the name as described above.
+.TP
+\fB\-padx \fIpixels\fR
+.
+\fIPixels\fR specifies the amount of extra space to leave on each side of the
+embedded image. It may have any of the usual forms defined for a screen
+distance.
+.TP
+\fB\-pady \fIpixels\fR
+.
+\fIPixels\fR specifies the amount of extra space to leave on the top and on
+the bottom of the embedded image. It may have any of the usual forms defined
+for a screen distance.
+.SH "THE SELECTION"
+.PP
+Selection support is implemented via tags. If the \fB\-exportselection\fR option
+for the text widget is true then the \fBsel\fR tag will be associated with the
+selection:
+.IP [1]
+Whenever characters are tagged with \fBsel\fR the text widget will claim
+ownership of the selection.
+.IP [2]
+Attempts to retrieve the selection will be serviced by the text widget,
+returning all the characters with the \fBsel\fR tag.
+.IP [3]
+If the selection is claimed away by another application or by another window
+within this application, then the \fBsel\fR tag will be removed from all
+characters in the text.
+.IP [4]
+Whenever the \fBsel\fR tag range changes a virtual event \fB<<Selection>>\fR
+is generated.
+.PP
+The \fBsel\fR tag is automatically defined when a text widget is created, and
+it may not be deleted with the
+.QW "\fIpathName \fBtag delete\fR"
+widget command. Furthermore, the \fB\-selectbackground\fR,
+\fB\-selectborderwidth\fR, and \fB\-selectforeground\fR options for the text
+widget are tied to the \fB\-background\fR, \fB\-borderwidth\fR, and
+\fB\-foreground\fR options for the \fBsel\fR tag: changes in either will
+automatically be reflected in the other. Also the
+\fB\-inactiveselectbackground\fR option for the text widget is used instead of
+\fB\-selectbackground\fR when the text widget does not have the focus. This
+allows programmatic control over the visualization of the \fBsel\fR tag for
+foreground and background windows, or to have \fBsel\fR not shown at all (when
+\fB\-inactiveselectbackground\fR is empty) for background windows. Each peer
+text widget has its own \fBsel\fR tag which can be separately configured and
+set.
+.SH "THE INSERTION CURSOR"
+.PP
+The mark named \fBinsert\fR has special significance in text widgets. It is
+defined automatically when a text widget is created and it may not be unset
+with the
+.QW "\fIpathName \fBmark unset\fR"
+widget command. The \fBinsert\fR mark represents the position of the insertion
+cursor, and the insertion cursor will automatically be drawn at this point
+whenever the text widget has the input focus.
+.SH "THE MODIFIED FLAG"
+.PP
+The text widget can keep track of changes to the content of the widget by
+means of the modified flag. Inserting or deleting text will set this flag. The
+flag can be queried, set and cleared programmatically as well. Whenever the
+flag changes state a \fB<<Modified>>\fR virtual event is generated. See the
+\fIpathName \fBedit modified\fR widget command for more details.
+.SH "THE UNDO MECHANISM"
+.PP
+The text widget has an unlimited undo and redo mechanism (when the
+\fB\-undo\fR widget option is true) which records every insert and delete
+action on a stack.
+.PP
+Boundaries (called
+.QW separators )
+are inserted between edit actions. The purpose of these separators is to group
+inserts, deletes and replaces into one compound edit action. When undoing a
+change everything between two separators will be undone. The undone changes
+are then moved to the redo stack, so that an undone edit can be redone again.
+The redo stack is cleared whenever new edit actions are recorded on the undo
+stack. The undo and redo stacks can be cleared to keep their depth under
+control.
+.PP
+Separators are inserted automatically when the \fB\-autoseparators\fR widget
+option is true. You can insert separators programmatically as well. If a
+separator is already present at the top of the undo stack no other will be
+inserted. That means that two separators on the undo stack are always
+separated by at least one insert or delete action.
+.PP
+The \fB<<UndoStack>>\fR virtual event is generated every time the undo stack
+or the redo stack becomes empty or unempty.
+.PP
+The undo mechanism is also linked to the modified flag. This means that
+undoing or redoing changes can take a modified text widget back to the
+unmodified state or vice versa. The modified flag will be set automatically to
+the appropriate state. This automatic coupling does not work when the modified
+flag has been set by the user, until the flag has been reset again.
+.PP
+See below for the \fIpathName \fBedit\fR widget command that controls the undo
+mechanism.
+.SH "PEER WIDGETS"
+.PP
+The text widget has a separate store of all its data concerning each line's
+textual contents, marks, tags, images and windows, and the undo stack.
+.PP
+While this data store cannot be accessed directly (i.e. without a text widget
+as an intermediary), multiple text widgets can be created, each of which
+present different views on the same underlying data. Such text widgets are
+known as peer text widgets.
+.PP
+As text is added, deleted, edited and coloured in any one widget, and as
+images, marks, tags are adjusted, all such changes will be reflected in all
+peers.
+.PP
+All data and markup is shared, except for a few small details. First, the
+\fBsel\fR tag may be set and configured (in its display style) differently for
+each peer. Second, each peer has its own \fBinsert\fR and \fBcurrent\fR mark
+positions (but all other marks are shared). Third, embedded windows, which are
+arbitrary other widgets, cannot be shared between peers. This means the
+\fB\-window\fR option of embedded windows is independently set for each peer
+(it is advisable to use the \fB\-create\fR script capabilities to allow each
+peer to create its own embedded windows as needed). Fourth, all of the
+configuration options of each peer (e.g. \fB\-font\fR, etc) can be set
+independently, with the exception of \fB\-undo\fR, \fB\-maxundo\fR,
+\fB\-autoseparators\fR (i.e. all undo, redo and modified state issues are
+shared).
+.PP
+Finally any single peer need not contain all lines from the underlying data
+store. When creating a peer, a contiguous range of lines (e.g. only lines 52
+through 125) may be specified. This allows a peer to contain just a small
+portion of the overall text. The range of lines will expand and contract as
+text is inserted or deleted. The peer will only ever display complete lines of
+text (one cannot share just part of a line). If the peer's contents contracts
+to nothing (i.e. all complete lines in the peer widget have been deleted from
+another widget), then it is impossible for new lines to be inserted. The peer
+will simply become an empty shell on which the background can be configured,
+but which will never show any content (without manual reconfiguration of the
+start and end lines). Note that a peer which does not contain all of the
+underlying data store still has indices numbered from
+.QW 1.0
+to
+.QW end .
+It is simply that those indices reflect a subset of the total data, and data
+outside the contained range is not accessible to the peer. This means that the
+command \fIpeerName \fBindex end\fR may return quite different values in
+different peers. Similarly, commands like \fIpeerName \fBtag ranges\fR will
+not return index ranges outside that which is meaningful to the peer. The
+configuration options \fB\-startline\fR and \fB\-endline\fR may be used to
+control how much of the underlying data is contained in any given text widget.
+.PP
+Note that peers are really peers. Deleting the
+.QW original
+text widget will not cause any other peers to be deleted, or otherwise
+affected.
+.PP
+See below for the \fIpathName \fBpeer\fR widget command that controls the
+creation of peer widgets.
+.SH "ASYNCHRONOUS UPDATE OF LINE HEIGHTS"
+.PP
+In order to maintain a responsive user-experience, the text widget calculates
+lines metrics (line heights in pixels) asynchronously. Because of this, some
+commands of the text widget may return wrong results if the asynchronous
+calculations are not finished at the time of calling. This applies to
+\fIpathName \fBcount -ypixels\fR and \fIpathName \fByview\fR.
+.PP
+Again for performance reasons, it would not be appropriate to let these
+commands always wait for the end of the update calculation each time they are
+called. In most use cases of these commands a more or less inaccurate result
+does not really matter compared to execution speed.
+.PP
+In case accurate result is needed (and if the text widget is managed by a
+geometry manager), one can resort to \fIpathName \fBsync\fR and \fIpathName
+\fBpendingsync\fR to control the synchronization of the view of text widgets.
+.PP
+The \fB<<WidgetViewSync>>\fR virtual event fires when the line heights of the
+text widget become obsolete (due to some editing command or configuration
+change), and again when the internal data of the text widget are back in sync
+with the widget view. The detail field (%d substitution) is either true (when
+the widget is in sync) or false (when it is not).
+.PP
+\fIpathName \fBsync\fR, \fIpathName \fBpendingsync\fR and
+\fB<<WidgetViewSync>>\fR apply to each text widget independently of its peers.
+.PP
+Examples of use:
+.CS
+## Example 1:
+# immediately complete line metrics at any cost (GUI unresponsive)
+$w sync
+$w yview moveto $fraction
+
+## Example 2:
+# synchronously wait for up-to-date line metrics (GUI responsive)
+# before executing the scheduled command, but don't block execution flow
+$w sync -command [list $w yview moveto $fraction]
+
+## Example 3:
+# init
+set yud($w) 0
+proc updateaction w {
+\&set ::yud($w) 1
+\&# any other update action here...
+}
+# runtime, synchronously wait for up-to-date line metrics (GUI responsive)
+$w sync -command [list updateaction $w]
+vwait yud($w)
+$w yview moveto $fraction
+
+## Example 4:
+# init
+set todo($w) {}
+proc updateaction w {
+\&foreach cmd $::todo($w) {uplevel #0 $cmd}
+\&set todo($w) {}
+}
+# runtime
+lappend todo($w) [list $w yview moveto $fraction]
+$w sync -command [list updateaction $w]
+
+## Example 5:
+# init
+set todo($w) {}
+bind $w <<WidgetViewSync>> {
+\&if {%d} {
+\&\&foreach cmd $todo(%W) {eval $cmd}
+\&\&set todo(%W) {}
+\&}
+}
+# runtime
+if {![$w pendingsync]} {
+\&$w yview moveto $fraction
+} else {
+\&lappend todo($w) [list $w yview moveto $fraction]
+}
+.CE
+.SH "WIDGET COMMAND"
+.PP
+The \fBtext\fR command creates a new Tcl command whose name is the same as the
+path name of the text's window. This command may be used to invoke various
+operations on the widget. It has the following general form:
+.CS
+\fIpathName option \fR?\fIarg arg ...\fR?
+.CE
+\fIPathName\fR is the name of the command, which is the same as the text
+widget's path name. \fIOption\fR and the \fIarg\fRs determine the exact
+behavior of the command. The following commands are possible for text widgets:
+.TP
+\fIpathName \fBbbox \fIindex\fR
+.
+Returns a list of four elements describing the screen area of the character
+given by \fIindex\fR. The first two elements of the list give the x and y
+coordinates of the upper-left corner of the area occupied by the character,
+and the last two elements give the width and height of the area. If the
+character is only partially visible on the screen, then the return value
+reflects just the visible part. If the character is not visible on the screen
+then the return value is an empty list.
+.TP
+\fIpathName \fBcget\fR \fIoption\fR
+.
+Returns the current value of the configuration option given by \fIoption\fR.
+\fIOption\fR may have any of the values accepted by the \fBtext\fR command.
+.TP
+\fIpathName \fBcompare\fR \fIindex1 op index2\fR
+.
+Compares the indices given by \fIindex1\fR and \fIindex2\fR according to the
+relational operator given by \fIop\fR, and returns 1 if the relationship is
+satisfied and 0 if it is not. \fIOp\fR must be one of the operators <, <=, ==,
+>=, >, or !=. If \fIop\fR is == then 1 is returned if the two indices refer to
+the same character, if \fIop\fR is < then 1 is returned if \fIindex1\fR refers
+to an earlier character in the text than \fIindex2\fR, and so on.
+.TP
+\fIpathName \fBconfigure\fR ?\fIoption\fR? \fI?value option value ...\fR?
+.
+Query or modify the configuration options of the widget. If no \fIoption\fR is
+specified, returns a list describing all of the available options for
+\fIpathName\fR (see \fBTk_ConfigureInfo\fR for information on the format of
+this list). If \fIoption\fR is specified with no \fIvalue\fR, then the command
+returns a list describing the one named option (this list will be identical to
+the corresponding sublist of the value returned if no \fIoption\fR is
+specified). If one or more \fIoption\-value\fR pairs are specified, then the
+command modifies the given widget option(s) to have the given value(s); in
+this case the command returns an empty string. \fIOption\fR may have any of
+the values accepted by the \fBtext\fR command.
+.TP
+\fIpathName \fBcount\fR \fI?options\fR? \fIindex1 index2\fR
+.
+Counts the number of relevant things between the two indices. If \fIindex1\fR
+is after \fIindex2\fR, the result will be a negative number (and this holds
+for each of the possible options). The actual items which are counted depend
+on the options given. The result is a list of integers, one for the result of
+each counting option given. Valid counting options are \fB\-chars\fR,
+\fB\-displaychars\fR, \fB\-displayindices\fR, \fB\-displaylines\fR,
+\fB\-indices\fR, \fB\-lines\fR, \fB\-xpixels\fR and \fB\-ypixels\fR. The
+default value, if no option is specified, is \fB\-indices\fR. There is an
+additional possible option \fB\-update\fR which is a modifier. If given (and
+if the text widget is managed by a geometry manager), then all subsequent
+options ensure that any possible out of date information is recalculated.
+This currently only has any effect for the \fB\-ypixels\fR count (which, if
+\fB\-update\fR is not given, will use the text widget's current cached value
+for each line). This \fB\-update\fR option is obsoleted by \fIpathName
+\fBsync\fR, \fIpathName \fBpendingsync\fR and \fB<<WidgetViewSync>>\fR. The
+count options are interpreted as follows:
+.RS
+.IP \fB\-chars\fR
+count all characters, whether elided or not. Do not count embedded windows or
+images.
+.IP \fB\-displaychars\fR
+count all non-elided characters.
+.IP \fB\-displayindices\fR
+count all non-elided characters, windows and images.
+.IP \fB\-displaylines\fR
+count all display lines (i.e. counting one for each time a line wraps) from
+the line of the first index up to, but not including the display line of the
+second index. Therefore if they are both on the same display line, zero will
+be returned. By definition displaylines are visible and therefore this only
+counts portions of actual visible lines.
+.IP \fB\-indices\fR
+count all characters and embedded windows or images (i.e. everything which
+counts in text-widget index space), whether they are elided or not.
+.IP \fB\-lines\fR
+count all logical lines (irrespective of wrapping) from the line of the first
+index up to, but not including the line of the second index. Therefore if they
+are both on the same line, zero will be returned. Logical lines are counted
+whether they are currently visible (non-elided) or not.
+.IP \fB\-xpixels\fR
+count the number of horizontal pixels from the first pixel of the first index
+to (but not including) the first pixel of the second index. To count the total
+desired width of the text widget (assuming wrapping is not enabled), first
+find the longest line and then use
+.QW ".text count \-xpixels \N'34'${line}.0\N'34' \N'34'${line}.0 lineend\N'34'" .
+.IP \fB\-ypixels\fR
+count the number of vertical pixels from the first pixel of the first index to
+(but not including) the first pixel of the second index. If both indices are
+on the same display line, zero will be returned. To count the total number of
+vertical pixels in the text widget, use
+.QW ".text count \-ypixels 1.0 end" ,
+and to ensure this is up to date, use
+.QW ".text count \-update \-ypixels 1.0 end" .
+.PP
+The command returns a positive or negative integer corresponding to the number
+of items counted between the two indices. One such integer is returned for
+each counting option given, so a list is returned if more than one option was
+supplied. For example
+.QW ".text count \-xpixels \-ypixels 1.3 4.5"
+is perfectly valid and will return a list of two elements.
+.RE
+.TP
+\fIpathName \fBdebug \fR?\fIboolean\fR?
+.
+If \fIboolean\fR is specified, then it must have one of the true or false
+values accepted by Tcl_GetBoolean. If the value is a true one then internal
+consistency checks will be turned on in the B-tree code associated with text
+widgets. If \fIboolean\fR has a false value then the debugging checks will be
+turned off. In either case the command returns an empty string. If
+\fIboolean\fR is not specified then the command returns \fBon\fR or \fBoff\fR
+to indicate whether or not debugging is turned on. There is a single debugging
+switch shared by all text widgets: turning debugging on or off in any widget
+turns it on or off for all widgets. For widgets with large amounts of text,
+the consistency checks may cause a noticeable slow-down.
+.RS
+.PP
+When debugging is turned on, the drawing routines of the text widget set the
+global variables \fBtk_textRedraw\fR and \fBtk_textRelayout\fR to the lists of
+indices that are redrawn. The values of these variables are tested by Tk's
+test suite.
+.RE
+.TP
+\fIpathName \fBdelete \fIindex1 \fR?\fIindex2 ...\fR?
+.
+Delete a range of characters from the text.
+If both \fIindex1\fR and \fIindex2\fR are specified, then delete
+all the characters starting with the one given by \fIindex1\fR
+and stopping just before \fIindex2\fR (i.e. the character at
+\fIindex2\fR is not deleted).
+If \fIindex2\fR does not specify a position later in the text
+than \fIindex1\fR then no characters are deleted.
+If \fIindex2\fR is not specified then the single character at
+\fIindex1\fR is deleted.
+Attempts to delete characters in a way that would leave
+the text without a newline as the last character will be tweaked by the
+text widget to avoid this. In particular, deletion of complete lines of
+text up to the end of the text will also delete the newline character just
+before the deleted block so that it is replaced by the new final newline
+of the text widget.
+The command returns an empty string.
+If more indices are given, multiple ranges of text will be deleted.
+All indices are first checked for validity before any deletions are made.
+They are sorted and the text is removed from the last range to the
+first range so deleted text does not cause an undesired index shifting
+side-effects. If multiple ranges with the same start index are given,
+then the longest range is used. If overlapping ranges are given, then
+they will be merged into spans that do not cause deletion of text
+outside the given ranges due to text shifted during deletion.
+.TP
+\fIpathName \fBdlineinfo \fIindex\fR
+.
+Returns a list with five elements describing the area occupied by the display
+line containing \fIindex\fR. The first two elements of the list give the x and
+y coordinates of the upper-left corner of the area occupied by the line, the
+third and fourth elements give the width and height of the area, and the fifth
+element gives the position of the baseline for the line, measured down from
+the top of the area. All of this information is measured in pixels. If the
+current wrap mode is \fBnone\fR and the line extends beyond the boundaries of
+the window, the area returned reflects the entire area of the line, including
+the portions that are out of the window. If the line is shorter than the full
+width of the window then the area returned reflects just the portion of the
+line that is occupied by characters and embedded windows. If the display line
+containing \fIindex\fR is not visible on the screen then the return value is
+an empty list.
+.TP
+\fIpathName \fBdump \fR?\fIswitches\fR? \fIindex1 \fR?\fIindex2\fR?
+.
+Return the contents of the text widget from \fIindex1\fR up to, but not
+including \fIindex2\fR, including the text and information about marks, tags,
+and embedded windows. If \fIindex2\fR is not specified, then it defaults to
+one character past \fIindex1\fR. The information is returned in the following
+format:
+.RS
+.LP
+\fIkey1 value1 index1 key2 value2 index2\fR ...
+.LP
+The possible \fIkey\fR values are \fBtext\fR, \fBmark\fR, \fBtagon\fR,
+\fBtagoff\fR, \fBimage\fR, and \fBwindow\fR. The corresponding \fIvalue\fR is
+the text, mark name, tag name, image name, or window name. The \fIindex\fR
+information is the index of the start of the text, mark, tag transition, image
+or window. One or more of the following switches (or abbreviations thereof)
+may be specified to control the dump:
+.TP
+\fB\-all\fR
+.
+Return information about all elements: text, marks, tags, images and windows.
+This is the default.
+.TP
+\fB\-command \fIcommand\fR
+.
+Instead of returning the information as the result of the dump operation,
+invoke the \fIcommand\fR on each element of the text widget within the range.
+The command has three arguments appended to it before it is evaluated: the
+\fIkey\fR, \fIvalue\fR, and \fIindex\fR.
+.TP
+\fB\-image\fR
+.
+Include information about images in the dump results.
+.TP
+\fB\-mark\fR
+.
+Include information about marks in the dump results.
+.TP
+\fB\-tag\fR
+.
+Include information about tag transitions in the dump results. Tag information
+is returned as \fBtagon\fR and \fBtagoff\fR elements that indicate the begin
+and end of each range of each tag, respectively.
+.TP
+\fB\-text\fR
+.
+Include information about text in the dump results. The value is the text up
+to the next element or the end of range indicated by \fIindex2\fR. A text
+element does not span newlines. A multi-line block of text that contains no
+marks or tag transitions will still be dumped as a set of text segments that
+each end with a newline. The newline is part of the value.
+.TP
+\fB\-window\fR
+.
+Include information about embedded windows in the dump results. The value of a
+window is its Tk pathname, unless the window has not been created yet. (It
+must have a create script.) In this case an empty string is returned, and you
+must query the window by its index position to get more information.
+.RE
+.TP
+\fIpathName \fBedit \fIoption \fR?\fIarg arg ...\fR?
+.
+This command controls the undo mechanism and the modified flag. The exact
+behavior of the command depends on the \fIoption\fR argument that follows the
+\fBedit\fR argument. The following forms of the command are currently
+supported:
+.RS
+.TP
+\fIpathName \fBedit canredo\fR
+.
+Returns a boolean true if redo is possible, i.e. when the redo stack is not
+empty. Otherwise returns false.
+.TP
+\fIpathName \fBedit canundo\fR
+.
+Returns a boolean true if undo is possible, i.e. when the undo stack is not
+empty. Otherwise returns false.
+.TP
+\fIpathName \fBedit modified \fR?\fIboolean\fR?
+.
+If \fIboolean\fR is not specified, returns the modified flag of the widget.
+The insert, delete, edit undo and edit redo commands or the user can set or
+clear the modified flag. If \fIboolean\fR is specified, sets the modified flag
+of the widget to \fIboolean\fR.
+.TP
+\fIpathName \fBedit redo\fR
+.
+When the \fB\-undo\fR option is true, reapplies the last undone edits provided
+no other edits were done since then. Generates an error when the redo stack is
+empty. Does nothing when the \fB\-undo\fR option is false.
+.TP
+\fIpathName \fBedit reset\fR
+.
+Clears the undo and redo stacks.
+.TP
+\fIpathName \fBedit separator\fR
+.
+Inserts a separator (boundary) on the undo stack. Does nothing when the
+\fB\-undo\fR option is false.
+.TP
+\fIpathName \fBedit undo\fR
+.
+Undoes the last edit action when the \fB\-undo\fR option is true. An edit
+action is defined as all the insert and delete commands that are recorded on
+the undo stack in between two separators. Generates an error when the undo
+stack is empty. Does nothing when the \fB\-undo\fR option is false.
+.RE
+.TP
+\fIpathName \fBget\fR ?\fB\-displaychars\fR? ?\fB\-\-\fR? \fIindex1\fR ?\fIindex2 ...\fR?
+.
+Return a range of characters from the text. The return value will be all the
+characters in the text starting with the one whose index is \fIindex1\fR and
+ending just before the one whose index is \fIindex2\fR (the character at
+\fIindex2\fR will not be returned). If \fIindex2\fR is omitted then the single
+character at \fIindex1\fR is returned. If there are no characters in the
+specified range (e.g. \fIindex1\fR is past the end of the file or \fIindex2\fR
+is less than or equal to \fIindex1\fR) then an empty string is returned. If
+the specified range contains embedded windows, no information about them is
+included in the returned string. If multiple index pairs are given, multiple
+ranges of text will be returned in a list. Invalid ranges will not be
+represented with empty strings in the list. The ranges are returned in the
+order passed to \fIpathName \fBget\fR. If the \fB\-displaychars\fR option is
+given, then, within each range, only those characters which are not elided
+will be returned. This may have the effect that some of the returned ranges
+are empty strings.
+.TP
+\fIpathName \fBimage \fIoption \fR?\fIarg arg ...\fR?
+.
+This command is used to manipulate embedded images. The behavior of the
+command depends on the \fIoption\fR argument that follows the \fBtag\fR
+argument. The following forms of the command are currently supported:
+.RS
+.TP
+\fIpathName \fBimage cget \fIindex option\fR
+.
+Returns the value of a configuration option for an embedded image. \fIIndex\fR
+identifies the embedded image, and \fIoption\fR specifies a particular
+configuration option, which must be one of the ones listed in the section
+\fBEMBEDDED IMAGES\fR.
+.TP
+\fIpathName \fBimage configure \fIindex\fR ?\fIoption value ...\fR?
+.
+Query or modify the configuration options for an embedded image. If no
+\fIoption\fR is specified, returns a list describing all of the available
+options for the embedded image at \fIindex\fR (see \fBTk_ConfigureInfo\fR for
+information on the format of this list). If \fIoption\fR is specified with no
+\fIvalue\fR, then the command returns a list describing the one named option
+(this list will be identical to the corresponding sublist of the value
+returned if no \fIoption\fR is specified). If one or more \fIoption\-value\fR
+pairs are specified, then the command modifies the given option(s) to have the
+given value(s); in this case the command returns an empty string. See
+\fBEMBEDDED IMAGES\fR for information on the options that are supported.
+.TP
+\fIpathName \fBimage create \fIindex\fR ?\fIoption value ...\fR?
+.
+This command creates a new image annotation, which will appear in the text at
+the position given by \fIindex\fR. Any number of \fIoption\-value\fR pairs may
+be specified to configure the annotation. Returns a unique identifier that may
+be used as an index to refer to this image. See \fBEMBEDDED IMAGES\fR for
+information on the options that are supported, and a description of the
+identifier returned.
+.TP
+\fIpathName \fBimage names\fR
+.
+Returns a list whose elements are the names of all image instances currently
+embedded in \fIwindow\fR.
+.RE
+.TP
+\fIpathName \fBindex \fIindex\fR
+.
+Returns the position corresponding to \fIindex\fR in the form \fIline.char\fR
+where \fIline\fR is the line number and \fIchar\fR is the character number.
+\fIIndex\fR may have any of the forms described under \fBINDICES\fR above.
+.TP
+\fIpathName \fBinsert \fIindex chars \fR?\fItagList chars tagList ...\fR?
+.
+Inserts all of the \fIchars\fR arguments just before the character at
+\fIindex\fR. If \fIindex\fR refers to the end of the text (the character after
+the last newline) then the new text is inserted just before the last newline
+instead. If there is a single \fIchars\fR argument and no \fItagList\fR, then
+the new text will receive any tags that are present on both the character
+before and the character after the insertion point; if a tag is present on
+only one of these characters then it will not be applied to the new text. If
+\fItagList\fR is specified then it consists of a list of tag names; the new
+characters will receive all of the tags in this list and no others, regardless
+of the tags present around the insertion point. If multiple
+\fIchars\fR\-\fItagList\fR argument pairs are present, they produce the same
+effect as if a separate \fIpathName \fBinsert\fR widget command had been
+issued for each pair, in order. The last \fItagList\fR argument may be
+omitted.
+.TP
+\fIpathName \fBmark \fIoption \fR?\fIarg arg ...\fR?
+.
+This command is used to manipulate marks. The exact behavior of the command
+depends on the \fIoption\fR argument that follows the \fBmark\fR argument. The
+following forms of the command are currently supported:
+.RS
+.TP
+\fIpathName \fBmark gravity \fImarkName\fR ?\fIdirection\fR?
+.
+If \fIdirection\fR is not specified, returns \fBleft\fR or \fBright\fR to
+indicate which of its adjacent characters \fImarkName\fR is attached to. If
+\fIdirection\fR is specified, it must be \fBleft\fR or \fBright\fR; the
+gravity of \fImarkName\fR is set to the given value.
+.TP
+\fIpathName \fBmark names\fR
+.
+Returns a list whose elements are the names of all the marks that are
+currently set.
+.TP
+\fIpathName \fBmark next \fIindex\fR
+.
+Returns the name of the next mark at or after \fIindex\fR. If \fIindex\fR is
+specified in numerical form, then the search for the next mark begins at that
+index. If \fIindex\fR is the name of a mark, then the search for the next mark
+begins immediately after that mark. This can still return a mark at the same
+position if there are multiple marks at the same index. These semantics mean
+that the \fBmark next\fR operation can be used to step through all the marks
+in a text widget in the same order as the mark information returned by the
+\fIpathName \fBdump\fR operation. If a mark has been set to the special
+\fBend\fR index, then it appears to be \fIafter\fR \fBend\fR with respect to
+the \fIpathName \fBmark next\fR operation. An empty string is returned if
+there are no marks after \fIindex\fR.
+.TP
+\fIpathName \fBmark previous \fIindex\fR
+.
+Returns the name of the mark at or before \fIindex\fR. If \fIindex\fR is
+specified in numerical form, then the search for the previous mark begins with
+the character just before that index. If \fIindex\fR is the name of a mark,
+then the search for the next mark begins immediately before that mark. This
+can still return a mark at the same position if there are multiple marks at
+the same index. These semantics mean that the \fIpathName \fBmark previous\fR
+operation can be used to step through all the marks in a text widget in the
+reverse order as the mark information returned by the \fIpathName \fBdump\fR
+operation. An empty string is returned if there are no marks before
+\fIindex\fR.
+.TP
+\fIpathName \fBmark set \fImarkName index\fR
+.
+Sets the mark named \fImarkName\fR to a position just before the character at
+\fIindex\fR. If \fImarkName\fR already exists, it is moved from its old
+position; if it does not exist, a new mark is created. This command returns an
+empty string.
+.TP
+\fIpathName \fBmark unset \fImarkName \fR?\fImarkName markName ...\fR?
+.
+Remove the mark corresponding to each of the \fImarkName\fR arguments. The
+removed marks will not be usable in indices and will not be returned by future
+calls to
+.QW "\fIpathName \fBmark names\fR" .
+This command returns an empty string.
+.RE
+.TP
+\fIpathName \fBpeer \fIoption args\fR
+.
+This command is used to create and query widget peers. It has two forms,
+depending on \fIoption\fR:
+.RS
+.TP
+\fIpathName \fBpeer create \fInewPathName\fR ?\fIoptions\fR?
+.
+Creates a peer text widget with the given \fInewPathName\fR, and any optional
+standard configuration options (as for the \fItext\fR command). By default the
+peer will have the same start and end line as the parent widget, but these can
+be overridden with the standard configuration options.
+.TP
+\fIpathName \fBpeer names\fR
+.
+Returns a list of peers of this widget (this does not include the widget
+itself). The order within this list is undefined.
+.RE
+.TP
+\fIpathName \fBpendingsync\fR
+Returns 1 if the line heights calculations are not up-to-date, 0 otherwise.
+.TP
+\fIpathName \fBreplace\fR \fIindex1 index2 chars\fR ?\fItagList chars tagList ...\fR?
+Replaces the range of characters between \fIindex1\fR and \fIindex2\fR
+with the given characters and tags. See the section on \fIpathName
+\fBinsert\fR for an explanation of the handling of the \fItagList...\fR
+arguments, and the section on \fIpathName
+\fBdelete\fR for an explanation of the handling of the indices. If
+\fIindex2\fR corresponds to an index earlier in the text than
+\fIindex1\fR, an error will be generated.
+.RS
+.PP
+The deletion and insertion are arranged so that no unnecessary scrolling of
+the window or movement of insertion cursor occurs. In addition the undo/redo
+stack are correctly modified, if undo operations are active in the text
+widget. The command returns an empty string.
+.RE
+.TP
+\fIpathName \fBscan \fIoption args\fR
+.
+This command is used to implement scanning on texts. It has two forms,
+depending on \fIoption\fR:
+.RS
+.TP
+\fIpathName \fBscan mark \fIx y\fR
+.
+Records \fIx\fR and \fIy\fR and the current view in the text window, for use
+in conjunction with later \fIpathName \fBscan dragto\fR commands. Typically
+this command is associated with a mouse button press in the widget. It returns
+an empty string.
+.TP
+\fIpathName \fBscan dragto \fIx y\fR
+.
+This command computes the difference between its \fIx\fR and \fIy\fR arguments
+and the \fIx\fR and \fIy\fR arguments to the last \fIpathName \fBscan mark\fR
+command for the widget. It then adjusts the view by 10 times the difference in
+coordinates. This command is typically associated with mouse motion events in
+the widget, to produce the effect of dragging the text at high speed through
+the window. The return value is an empty string.
+.RE
+.TP
+\fIpathName \fBsearch \fR?\fIswitches\fR? \fIpattern index \fR?\fIstopIndex\fR?
+.
+Searches the text in \fIpathName\fR starting at \fIindex\fR for a range of
+characters that matches \fIpattern\fR. If a match is found, the index of the
+first character in the match is returned as result; otherwise an empty string
+is returned. One or more of the following switches (or abbreviations thereof)
+may be specified to control the search:
+.RS
+.TP
+\fB\-forwards\fR
+.
+The search will proceed forward through the text, finding the first matching
+range starting at or after the position given by \fIindex\fR. This is the
+default.
+.TP
+\fB\-backwards\fR
+.
+The search will proceed backward through the text, finding the matching range
+closest to \fIindex\fR whose first character is before \fIindex\fR (it is not
+allowed to be at \fIindex\fR). Note that, for a variety of reasons, backwards
+searches can be substantially slower than forwards searches (particularly when
+using \fB\-regexp\fR), so it is recommended that performance-critical code use
+forward searches.
+.TP
+\fB\-exact\fR
+.
+Use exact matching: the characters in the matching range must be identical to
+those in \fIpattern\fR. This is the default.
+.TP
+\fB\-regexp\fR
+.
+Treat \fIpattern\fR as a regular expression and match it against the text
+using the rules for regular expressions (see the \fBregexp\fR command
+and the \fBre_syntax\fR page for
+details). The default matching automatically passes both the
+\fB\-lineanchor\fR and \fB\-linestop\fR options to the regexp engine (unless
+\fB\-nolinestop\fR is used), so that \fI^$\fR match beginning and end of line,
+and \fI.\fR, \fI[^\fR sequences will never match the newline character
+\fI\en\fR.
+.TP
+\fB\-nolinestop\fR
+.
+This allows \fI.\fR and \fI[^\fR sequences to match the newline character
+\fI\en\fR, which they will otherwise not do (see the \fBregexp\fR command for
+details). This option is only meaningful if \fB\-regexp\fR is also given, and
+an error will be thrown otherwise. For example, to match the entire text, use
+.QW "\fIpathName \fBsearch \-nolinestop \-regexp\fR \N'34'.*\N'34' 1.0" .
+.TP
+\fB\-nocase\fR
+.
+Ignore case differences between the pattern and the text.
+.TP
+\fB\-count\fI varName\fR
+.
+The argument following \fB\-count\fR gives the name of a variable; if a match
+is found, the number of index positions between beginning and end of the
+matching range will be stored in the variable. If there are no embedded images
+or windows in the matching range (and there are no elided characters if
+\fB\-elide\fR is not given), this is equivalent to the number of characters
+matched. In either case, the range \fImatchIdx\fR to \fImatchIdx + $count
+chars\fR will return the entire matched text.
+.TP
+\fB\-all\fR
+.
+Find all matches in the given range and return a list of the indices of the
+first character of each match. If a \fB\-count\fI varName\fR switch is given,
+then \fIvarName\fR is also set to a list containing one element for each
+successful match. Note that, even for exact searches, the elements of this
+list may be different, if there are embedded images, windows or hidden text.
+Searches with \fB\-all\fR behave very similarly to the Tcl command \fBregexp
+\-all\fR, in that overlapping matches are not normally returned. For example,
+applying an \fB\-all\fR search of the pattern
+.QW \ew+
+against
+.QW "hello there"
+will just match twice, once for each word, and matching
+.QW "Z[a\-z]+Z"
+against
+.QW ZooZooZoo
+will just match once.
+.TP
+\fB\-overlap\fR
+.
+When performing \fB\-all\fR searches, the normal behaviour is that matches
+which overlap an already-found match will not be returned. This switch changes
+that behaviour so that all matches which are not totally enclosed within
+another match are returned. For example, applying an \fB\-overlap\fR search of
+the pattern
+.QW \ew+
+against
+.QW "hello there"
+will just match twice (i.e. no different to just \fB\-all\fR), but matching
+.QW Z[a\-z]+Z
+against
+.QW ZooZooZoo
+will now match twice. An error will be thrown if this switch is used without
+\fB\-all\fR.
+.TP
+\fB\-strictlimits\fR
+.
+When performing any search, the normal behaviour is that the start and stop
+limits are checked with respect to the start of the matching text. With the
+\fB\-strictlimits\fR flag, the entire matching range must lie inside the start
+and stop limits specified for the match to be valid.
+.TP
+\fB\-elide\fR
+.
+Find elided (hidden) text as well. By default only displayed text is searched.
+.TP
+\fB\-\|\-\fR
+.
+This switch has no effect except to terminate the list of switches: the next
+argument will be treated as \fIpattern\fR even if it starts with \fB\-\fR.
+.PP
+The matching range may be within a single line of text, or run across multiple
+lines (if parts of the pattern can match a new-line). For regular expression
+matching one can use the various newline-matching features such as \fB$\fR to
+match the end of a line, \fB^\fR to match the beginning of a line, and to
+control whether \fB.\fR is allowed to match a new-line. If \fIstopIndex\fR is
+specified, the search stops at that index: for forward searches, no match at
+or after \fIstopIndex\fR will be considered; for backward searches, no match
+earlier in the text than \fIstopIndex\fR will be considered. If
+\fIstopIndex\fR is omitted, the entire text will be searched: when the
+beginning or end of the text is reached, the search continues at the other end
+until the starting location is reached again; if \fIstopIndex\fR is specified,
+no wrap-around will occur. This means that, for example, if the search is
+\fB\-forwards\fR but \fIstopIndex\fR is earlier in the text than
+\fIstartIndex\fR, nothing will ever be found. See \fBKNOWN BUGS\fR below for a
+number of minor limitations of the \fIpathName \fBsearch\fR command.
+.RE
+.TP
+\fIpathName \fBsee \fIindex\fR
+.
+Adjusts the view in the window so that the character given by \fIindex\fR is
+completely visible. If \fIindex\fR is already visible then the command does
+nothing. If \fIindex\fR is a short distance out of view, the command adjusts
+the view just enough to make \fIindex\fR visible at the edge of the window.
+If \fIindex\fR is far out of view, then the command centers \fIindex\fR in the
+window.
+.TP
+\fIpathName \fBsync\fR ?\fB-command \fIcommand\fR?
+Controls the synchronization of the view of the text widget.
+.RS
+.TP
+\fIpathName \fBsync\fR
+Immediately brings the line metrics up-to-date by forcing computation of any
+outdated line heights. The command returns immediately if there is no such
+outdated line heights, otherwise it returns only at the end of the computation.
+The command returns an empty string.
+.TP
+\fIpathName \fBsync -command \fIcommand\fR
+Schedules \fIcommand\fR to be executed (by the event loop) exactly once as soon
+as all line heights are up-to-date. If there are no pending line metrics
+calculations, the scheduling is immediate. The command returns the empty
+string. \fBbgerror\fR is called on \fIcommand\fR failure.
+.RE
+.TP
+\fIpathName \fBtag \fIoption \fR?\fIarg arg ...\fR?
+.
+This command is used to manipulate tags. The exact behavior of the command
+depends on the \fIoption\fR argument that follows the \fBtag\fR argument. The
+following forms of the command are currently supported:
+.RS
+.TP
+\fIpathName \fBtag add \fItagName index1 \fR?\fIindex2 index1 index2 ...\fR?
+.
+Associate the tag \fItagName\fR with all of the characters starting with
+\fIindex1\fR and ending just before \fIindex2\fR (the character at
+\fIindex2\fR is not tagged). A single command may contain any number of
+\fIindex1\fR\-\fIindex2\fR pairs. If the last \fIindex2\fR is omitted then the
+single character at \fIindex1\fR is tagged. If there are no characters in the
+specified range (e.g. \fIindex1\fR is past the end of the file or \fIindex2\fR
+is less than or equal to \fIindex1\fR) then the command has no effect.
+.TP
+\fIpathName \fBtag bind \fItagName\fR ?\fIsequence\fR? ?\fIscript\fR?
+.
+This command associates \fIscript\fR with the tag given by \fItagName\fR.
+Whenever the event sequence given by \fIsequence\fR occurs for a character
+that has been tagged with \fItagName\fR, the script will be invoked. This
+widget command is similar to the \fBbind\fR command except that it operates on
+characters in a text rather than entire widgets. See the \fBbind\fR manual
+entry for complete details on the syntax of \fIsequence\fR and the
+substitutions performed on \fIscript\fR before invoking it. If all arguments
+are specified then a new binding is created, replacing any existing binding
+for the same \fIsequence\fR and \fItagName\fR (if the first character of
+\fIscript\fR is
+.QW +
+then \fIscript\fR augments an existing binding rather than replacing it). In
+this case the return value is an empty string. If \fIscript\fR is omitted then
+the command returns the \fIscript\fR associated with \fItagName\fR and
+\fIsequence\fR (an error occurs if there is no such binding). If both
+\fIscript\fR and \fIsequence\fR are omitted then the command returns a list of
+all the sequences for which bindings have been defined for \fItagName\fR.
+.RS
+.PP
+The only events for which bindings may be specified are those related to the
+mouse and keyboard (such as \fBEnter\fR, \fBLeave\fR, \fBButtonPress\fR,
+\fBMotion\fR, and \fBKeyPress\fR) or virtual events. Event bindings for a text
+widget use the \fBcurrent\fR mark described under \fBMARKS\fR above. An
+\fBEnter\fR event triggers for a tag when the tag first becomes present on the
+current character, and a \fBLeave\fR event triggers for a tag when it ceases
+to be present on the current character. \fBEnter\fR and \fBLeave\fR events can
+happen either because the \fBcurrent\fR mark moved or because the character at
+that position changed. Note that these events are different than \fBEnter\fR
+and \fBLeave\fR events for windows. Mouse and keyboard events are directed to
+the current character. If a virtual event is used in a binding, that binding
+can trigger only if the virtual event is defined by an underlying
+mouse-related or keyboard-related event.
+.PP
+It is possible for the current character to have multiple tags, and for each
+of them to have a binding for a particular event sequence. When this occurs,
+one binding is invoked for each tag, in order from lowest-priority to highest
+priority. If there are multiple matching bindings for a single tag, then the
+most specific binding is chosen (see the manual entry for the \fBbind\fR
+command for details). \fBcontinue\fR and \fBbreak\fR commands within binding
+scripts are processed in the same way as for bindings created with the
+\fBbind\fR command.
+.PP
+If bindings are created for the widget as a whole using the \fBbind\fR
+command, then those bindings will supplement the tag bindings. The tag
+bindings will be invoked first, followed by bindings for the window as a
+whole.
+.RE
+.TP
+\fIpathName \fBtag cget \fItagName option\fR
+.
+This command returns the current value of the option named \fIoption\fR
+associated with the tag given by \fItagName\fR. \fIOption\fR may have any of
+the values accepted by the \fIpathName \fBtag configure\fR widget command.
+.TP
+\fIpathName \fBtag configure \fItagName\fR ?\fIoption\fR? ?\fIvalue\fR? ?\fIoption value ...\fR?
+.
+This command is similar to the \fIpathName \fBconfigure\fR widget command
+except that it modifies options associated with the tag given by \fItagName\fR
+instead of modifying options for the overall text widget. If no \fIoption\fR
+is specified, the command returns a list describing all of the available
+options for \fItagName\fR (see \fBTk_ConfigureInfo\fR for information on the
+format of this list). If \fIoption\fR is specified with no \fIvalue\fR, then
+the command returns a list describing the one named option (this list will be
+identical to the corresponding sublist of the value returned if no
+\fIoption\fR is specified). If one or more \fIoption\-value\fR pairs are
+specified, then the command modifies the given option(s) to have the given
+value(s) in \fItagName\fR; in this case the command returns an empty string.
+See \fBTAGS\fR above for details on the options available for tags.
+.TP
+\fIpathName \fBtag delete \fItagName \fR?\fItagName ...\fR?
+.
+Deletes all tag information for each of the \fItagName\fR arguments. The
+command removes the tags from all characters in the file and also deletes any
+other information associated with the tags, such as bindings and display
+information. The command returns an empty string.
+.TP
+\fIpathName\fB tag lower \fItagName \fR?\fIbelowThis\fR?
+.
+Changes the priority of tag \fItagName\fR so that it is just lower in priority
+than the tag whose name is \fIbelowThis\fR. If \fIbelowThis\fR is omitted,
+then \fItagName\fR's priority is changed to make it lowest priority of all
+tags.
+.TP
+\fIpathName \fBtag names \fR?\fIindex\fR?
+.
+Returns a list whose elements are the names of all the tags that are active at
+the character position given by \fIindex\fR. If \fIindex\fR is omitted, then
+the return value will describe all of the tags that exist for the text (this
+includes all tags that have been named in a
+.QW "\fIpathName \fBtag\fR"
+widget command but have not been deleted by a
+.QW "\fIpathName \fBtag delete\fR"
+widget command, even if no characters are currently marked with the tag). The
+list will be sorted in order from lowest priority to highest priority.
+.TP
+\fIpathName \fBtag nextrange \fItagName index1 \fR?\fIindex2\fR?
+.
+This command searches the text for a range of characters tagged with
+\fItagName\fR where the first character of the range is no earlier than the
+character at \fIindex1\fR and no later than the character just before
+\fIindex2\fR (a range starting at \fIindex2\fR will not be considered). If
+several matching ranges exist, the first one is chosen. The command's return
+value is a list containing two elements, which are the index of the first
+character of the range and the index of the character just after the last one
+in the range. If no matching range is found then the return value is an empty
+string. If \fIindex2\fR is not given then it defaults to the end of the text.
+.TP
+\fIpathName \fBtag prevrange \fItagName index1 \fR?\fIindex2\fR?
+.
+This command searches the text for a range of characters tagged with
+\fItagName\fR where the first character of the range is before the character
+at \fIindex1\fR and no earlier than the character at \fIindex2\fR (a range
+starting at \fIindex2\fR will be considered). If several matching ranges
+exist, the one closest to \fIindex1\fR is chosen. The command's return value
+is a list containing two elements, which are the index of the first character
+of the range and the index of the character just after the last one in the
+range. If no matching range is found then the return value is an empty string.
+If \fIindex2\fR is not given then it defaults to the beginning of the text.
+.TP
+\fIpathName\fB tag raise \fItagName \fR?\fIaboveThis\fR?
+.
+Changes the priority of tag \fItagName\fR so that it is just higher in
+priority than the tag whose name is \fIaboveThis\fR. If \fIaboveThis\fR is
+omitted, then \fItagName\fR's priority is changed to make it highest priority
+of all tags.
+.TP
+\fIpathName \fBtag ranges \fItagName\fR
+.
+Returns a list describing all of the ranges of text that have been tagged with
+\fItagName\fR. The first two elements of the list describe the first tagged
+range in the text, the next two elements describe the second range, and so on.
+The first element of each pair contains the index of the first character of
+the range, and the second element of the pair contains the index of the
+character just after the last one in the range. If there are no characters
+tagged with \fItag\fR then an empty string is returned.
+.TP
+\fIpathName \fBtag remove \fItagName index1 \fR?\fIindex2 index1 index2 ...\fR?
+.
+Remove the tag \fItagName\fR from all of the characters starting at
+\fIindex1\fR and ending just before \fIindex2\fR (the character at
+\fIindex2\fR is not affected). A single command may contain any number of
+\fIindex1\fR\-\fIindex2\fR pairs. If the last \fIindex2\fR is omitted then the
+tag is removed from the single character at \fIindex1\fR. If there are no
+characters in the specified range (e.g. \fIindex1\fR is past the end of the
+file or \fIindex2\fR is less than or equal to \fIindex1\fR) then the command
+has no effect. This command returns an empty string.
+.RE
+.TP
+\fIpathName \fBwindow \fIoption \fR?\fIarg arg ...\fR?
+.
+This command is used to manipulate embedded windows. The behavior of the
+command depends on the \fIoption\fR argument that follows the \fBwindow\fR
+argument. The following forms of the command are currently supported:
+.RS
+.TP
+\fIpathName \fBwindow cget \fIindex option\fR
+.
+Returns the value of a configuration option for an embedded window.
+\fIIndex\fR identifies the embedded window, and \fIoption\fR specifies a
+particular configuration option, which must be one of the ones listed in the
+section \fBEMBEDDED WINDOWS\fR.
+.TP
+\fIpathName \fBwindow configure \fIindex\fR ?\fIoption value ...\fR?
+.
+Query or modify the configuration options for an embedded window. If no
+\fIoption\fR is specified, returns a list describing all of the available
+options for the embedded window at \fIindex\fR (see \fBTk_ConfigureInfo\fR for
+information on the format of this list). If \fIoption\fR is specified with no
+\fIvalue\fR, then the command returns a list describing the one named option
+(this list will be identical to the corresponding sublist of the value
+returned if no \fIoption\fR is specified). If one or more \fIoption\-value\fR
+pairs are specified, then the command modifies the given option(s) to have the
+given value(s); in this case the command returns an empty string. See
+\fBEMBEDDED WINDOWS\fR for information on the options that are supported.
+.TP
+\fIpathName \fBwindow create \fIindex\fR ?\fIoption value ...\fR?
+.
+This command creates a new window annotation, which will appear in the text at
+the position given by \fIindex\fR. Any number of \fIoption\-value\fR pairs may
+be specified to configure the annotation. See \fBEMBEDDED WINDOWS\fR for
+information on the options that are supported. Returns an empty string.
+.TP
+\fIpathName \fBwindow names\fR
+.
+Returns a list whose elements are the names of all windows currently embedded
+in \fIwindow\fR.
+.RE
+.TP
+\fIpathName \fBxview \fIoption args\fR
+.
+This command is used to query and change the horizontal position of the text
+in the widget's window. It can take any of the following forms:
+.RS
+.TP
+\fIpathName \fBxview\fR
+.
+Returns a list containing two elements. Each element is a real fraction
+between 0 and 1; together they describe the portion of the document's
+horizontal span that is visible in the window. For example, if the first
+element is .2 and the second element is .6, 20% of the text is off-screen to
+the left, the middle 40% is visible in the window, and 40% of the text is
+off-screen to the right. The fractions refer only to the lines that are
+actually visible in the window: if the lines in the window are all very short,
+so that they are entirely visible, the returned fractions will be 0 and 1,
+even if there are other lines in the text that are much wider than the window.
+These are the same values passed to scrollbars via the \fB\-xscrollcommand\fR
+option.
+.TP
+\fIpathName \fBxview moveto\fI fraction\fR
+.
+Adjusts the view in the window so that \fIfraction\fR of the horizontal span
+of the text is off-screen to the left. \fIFraction\fR is a fraction between 0
+and 1.
+.TP
+\fIpathName \fBxview scroll \fInumber what\fR
+.
+This command shifts the view in the window left or right according to
+\fInumber\fR and \fIwhat\fR. \fIWhat\fR must be \fBunits\fR, \fBpages\fR or
+\fBpixels\fR. If \fIwhat\fR is \fBunits\fR or \fBpages\fR then \fInumber\fR
+must be an integer, otherwise number may be specified in any of the forms
+acceptable to \fBTk_GetPixels\fR, such as
+.QW 2.0c
+or
+.QW 1i
+(the result is rounded to the nearest integer value. If no units are given,
+pixels are assumed). If \fIwhat\fR is \fBunits\fR, the view adjusts left or
+right by \fInumber\fR average-width characters on the display; if it is
+\fBpages\fR then the view adjusts by \fInumber\fR screenfuls; if it is
+\fBpixels\fR then the view adjusts by \fInumber\fR pixels. If \fInumber\fR is
+negative then characters farther to the left become visible; if it is positive
+then characters farther to the right become visible.
+.RE
+.TP
+\fIpathName \fByview \fR?\fIargs\fR?
+.
+This command is used to query and change the vertical position of the text in
+the widget's window. It can take any of the following forms:
+.RS
+.TP
+\fIpathName \fByview\fR
+.
+Returns a list containing two elements, both of which are real fractions
+between 0 and 1. The first element gives the position of the first visible
+pixel of the first character (or image, etc) in the top line in the window,
+relative to the text as a whole (0.5 means it is halfway through the text, for
+example). The second element gives the position of the first pixel just after
+the last visible one in the bottom line of the window, relative to the text as
+a whole. These are the same values passed to scrollbars via the
+\fB\-yscrollcommand\fR option.
+.TP
+\fIpathName \fByview moveto\fI fraction\fR
+.
+Adjusts the view in the window so that the pixel given by \fIfraction\fR
+appears at the top of the top line of the window. \fIFraction\fR is a fraction
+between 0 and 1; 0 indicates the first pixel of the first character in the
+text, 0.33 indicates the pixel that is one-third the way through the text; and
+so on. Values close to 1 will indicate values close to the last pixel in the
+text (1 actually refers to one pixel beyond the last pixel), but in such cases
+the widget will never scroll beyond the last pixel, and so a value of 1 will
+effectively be rounded back to whatever fraction ensures the last pixel is at
+the bottom of the window, and some other pixel is at the top.
+.TP
+\fIpathName \fByview scroll \fInumber what\fR
+.
+This command adjust the view in the window up or down according to
+\fInumber\fR and \fIwhat\fR. \fIWhat\fR must be \fBunits\fR, \fBpages\fR or
+\fBpixels\fR. If \fIwhat\fR is \fBunits\fR or \fBpages\fR then \fInumber\fR
+must be an integer, otherwise number may be specified in any of the forms
+acceptable to \fBTk_GetPixels\fR, such as
+.QW 2.0c
+or
+.QW 1i
+(the result is rounded to the nearest integer value. If no units are given,
+pixels are assumed). If \fIwhat\fR is \fBunits\fR, the view adjusts up or down
+by \fInumber\fR lines on the display; if it is \fBpages\fR then the view
+adjusts by \fInumber\fR screenfuls; if it is \fBpixels\fR then the view
+adjusts by \fInumber\fR pixels. If \fInumber\fR is negative then earlier
+positions in the text become visible; if it is positive then later positions
+in the text become visible.
+.TP
+\fIpathName \fByview \fR?\fB\-pickplace\fR? \fIindex\fR
+.
+Changes the view in the widget's window to make \fIindex\fR visible. If the
+\fB\-pickplace\fR option is not specified then \fIindex\fR will appear at the
+top of the window. If \fB\-pickplace\fR is specified then the widget chooses
+where \fIindex\fR appears in the window:
+.RS
+.IP [1]
+If \fIindex\fR is already visible somewhere in the window then the command
+does nothing.
+.IP [2]
+If \fIindex\fR is only a few lines off-screen above the window then it will be
+positioned at the top of the window.
+.IP [3]
+If \fIindex\fR is only a few lines off-screen below the window then it will be
+positioned at the bottom of the window.
+.IP [4]
+Otherwise, \fIindex\fR will be centered in the window.
+.PP
+The \fB\-pickplace\fR option has been obsoleted by the \fIpathName \fBsee\fR
+widget command (\fIpathName \fBsee\fR handles both x- and y-motion to make a
+location visible, whereas the \fB\-pickplace\fR mode only handles motion in
+y).
+.RE
+.TP
+\fIpathName \fByview \fInumber\fR
+.
+This command makes the first character on the line after the one given by
+\fInumber\fR visible at the top of the window. \fINumber\fR must be an
+integer. This command used to be used for scrolling, but now it is obsolete.
+.RE
+.SH BINDINGS
+.PP
+Tk automatically creates class bindings for texts that give them the following
+default behavior. In the descriptions below,
+.QW word
+is dependent on the value of the \fBtcl_wordchars\fR variable. See
+\fBtclvars\fR(n).
+.IP [1]
+Clicking mouse button 1 positions the insertion cursor just before the
+character underneath the mouse cursor, sets the input focus to this widget,
+and clears any selection in the widget. Dragging with mouse button 1 strokes
+out a selection between the insertion cursor and the character under the
+mouse.
+.IP [2]
+Double-clicking with mouse button 1 selects the word under the mouse and
+positions the insertion cursor at the start of the word. Dragging after a
+double click will stroke out a selection consisting of whole words.
+.IP [3]
+Triple-clicking with mouse button 1 selects the line under the mouse and
+positions the insertion cursor at the start of the line. Dragging after a
+triple click will stroke out a selection consisting of whole lines.
+.IP [4]
+The ends of the selection can be adjusted by dragging with mouse button 1
+while the Shift key is down; this will adjust the end of the selection that
+was nearest to the mouse cursor when button 1 was pressed. If the button is
+double-clicked before dragging then the selection will be adjusted in units of
+whole words; if it is triple-clicked then the selection will be adjusted in
+units of whole lines.
+.IP [5]
+Clicking mouse button 1 with the Control key down will reposition the
+insertion cursor without affecting the selection.
+.IP [6]
+If any normal printing characters are typed, they are inserted at the point of
+the insertion cursor.
+.IP [7]
+The view in the widget can be adjusted by dragging with mouse button 2. If
+mouse button 2 is clicked without moving the mouse, the selection is copied
+into the text at the position of the mouse cursor. The Insert key also inserts
+the selection, but at the position of the insertion cursor.
+.IP [8]
+If the mouse is dragged out of the widget while button 1 is pressed, the entry
+will automatically scroll to make more text visible (if there is more text
+off-screen on the side where the mouse left the window).
+.IP [9]
+The Left and Right keys move the insertion cursor one character to the left or
+right; they also clear any selection in the text. If Left or Right is typed
+with the Shift key down, then the insertion cursor moves and the selection is
+extended to include the new character. Control-Left and Control-Right move the
+insertion cursor by words, and Control-Shift-Left and Control-Shift-Right move
+the insertion cursor by words and also extend the selection. Control-b and
+Control-f behave the same as Left and Right, respectively. Meta-b and Meta-f
+behave the same as Control-Left and Control-Right, respectively.
+.IP [10]
+The Up and Down keys move the insertion cursor one line up or down and clear
+any selection in the text. If Up or Right is typed with the Shift key down,
+then the insertion cursor moves and the selection is extended to include the
+new character. Control-Up and Control-Down move the insertion cursor by
+paragraphs (groups of lines separated by blank lines), and Control-Shift-Up
+and Control-Shift-Down move the insertion cursor by paragraphs and also extend
+the selection. Control-p and Control-n behave the same as Up and Down,
+respectively.
+.IP [11]
+The Next and Prior keys move the insertion cursor forward or backwards by one
+screenful and clear any selection in the text. If the Shift key is held down
+while Next or Prior is typed, then the selection is extended to include the
+new character.
+.IP [12]
+Control-Next and Control-Prior scroll the view right or left by one page
+without moving the insertion cursor or affecting the selection.
+.IP [13]
+Home and Control-a move the insertion cursor to the beginning of its display
+line and clear any selection in the widget. Shift-Home moves the insertion
+cursor to the beginning of the display line and also extends the selection to
+that point.
+.IP [14]
+End and Control-e move the insertion cursor to the end of the display line and
+clear any selection in the widget. Shift-End moves the cursor to the end of
+the display line and extends the selection to that point.
+.IP [15]
+Control-Home and Meta-< move the insertion cursor to the beginning of the text
+and clear any selection in the widget. Control-Shift-Home moves the insertion
+cursor to the beginning of the text and also extends the selection to that
+point.
+.IP [16]
+Control-End and Meta-> move the insertion cursor to the end of the text and
+clear any selection in the widget. Control-Shift-End moves the cursor to the
+end of the text and extends the selection to that point.
+.IP [17]
+The Select key and Control-Space set the selection anchor to the position of
+the insertion cursor. They do not affect the current selection. Shift-Select
+and Control-Shift-Space adjust the selection to the current position of the
+insertion cursor, selecting from the anchor to the insertion cursor if there
+was not any selection previously.
+.IP [18]
+Control-/ selects the entire contents of the widget.
+.IP [19]
+Control-\e clears any selection in the widget.
+.IP [20]
+The F16 key (labelled Copy on many Sun workstations) or Meta-w copies the
+selection in the widget to the clipboard, if there is a selection. This
+action is carried out by the command \fBtk_textCopy\fR.
+.IP [21]
+The F20 key (labelled Cut on many Sun workstations) or Control-w copies the
+selection in the widget to the clipboard and deletes the selection. This
+action is carried out by the command \fBtk_textCut\fR. If there is no
+selection in the widget then these keys have no effect.
+.IP [22]
+The F18 key (labelled Paste on many Sun workstations) or Control-y inserts the
+contents of the clipboard at the position of the insertion cursor. This action
+is carried out by the command \fBtk_textPaste\fR.
+.IP [23]
+The Delete key deletes the selection, if there is one in the widget. If there
+is no selection, it deletes the character to the right of the insertion
+cursor.
+.IP [24]
+Backspace and Control-h delete the selection, if there is one in the widget.
+If there is no selection, they delete the character to the left of the
+insertion cursor.
+.IP [25]
+Control-d deletes the character to the right of the insertion cursor.
+.IP [26]
+Meta-d deletes the word to the right of the insertion cursor.
+.IP [27]
+Control-k deletes from the insertion cursor to the end of its line; if the
+insertion cursor is already at the end of a line, then Control-k deletes the
+newline character.
+.IP [28]
+Control-o opens a new line by inserting a newline character in front of the
+insertion cursor without moving the insertion cursor.
+.IP [29]
+Meta-backspace and Meta-Delete delete the word to the left of the insertion
+cursor.
+.IP [30]
+Control-x deletes whatever is selected in the text widget after copying it to
+the clipboard.
+.IP [31]
+Control-t reverses the order of the two characters to the right of the
+insertion cursor.
+.IP [32]
+Control-z undoes the last edit action if the \fB\-undo\fR option is true.
+Does nothing otherwise.
+.IP [33]
+Control-Z (or Control-y on Windows) reapplies the last undone edit action if
+the \fB\-undo\fR option is true. Does nothing otherwise.
+.PP
+If the widget is disabled using the \fB\-state\fR option, then its view can
+still be adjusted and text can still be selected, but no insertion cursor will
+be displayed and no text modifications will take place.
+.PP
+The behavior of texts can be changed by defining new bindings for individual
+widgets or by redefining the class bindings.
+.SH "KNOWN ISSUES"
+.SS "ISSUES CONCERNING CHARS AND INDICES"
+.PP
+Before Tk 8.5, the widget used the string
+.QW chars
+to refer to index positions (which included characters, embedded windows and
+embedded images). As of Tk 8.5 the text widget deals separately and correctly
+with
+.QW chars
+and
+.QW indices .
+For backwards compatibility, however, the index modifiers
+.QW "+N chars"
+and
+.QW "\-N chars"
+continue to refer to indices. One must use any of the full forms
+.QW "+N any chars"
+or
+.QW "\-N any chars"
+etc. to refer to actual character indices. This confusion may be fixed in a
+future release by making the widget correctly interpret
+.QW "+N chars"
+as a synonym for
+.QW "+N any chars" .
+.SS "PERFORMANCE ISSUES"
+.PP
+Text widgets should run efficiently under a variety of conditions. The text
+widget uses about 2-3 bytes of main memory for each byte of text, so texts
+containing a megabyte or more should be practical on most workstations. Text
+is represented internally with a modified B-tree structure that makes
+operations relatively efficient even with large texts. Tags are included in
+the B-tree structure in a way that allows tags to span large ranges or have
+many disjoint smaller ranges without loss of efficiency. Marks are also
+implemented in a way that allows large numbers of marks. In most cases it is
+fine to have large numbers of unique tags, or a tag that has many distinct
+ranges.
+.PP
+One performance problem can arise if you have hundreds or thousands of
+different tags that all have the following characteristics: the first and last
+ranges of each tag are near the beginning and end of the text, respectively,
+or a single tag range covers most of the text widget. The cost of adding and
+deleting tags like this is proportional to the number of other tags with the
+same properties. In contrast, there is no problem with having thousands of
+distinct tags if their overall ranges are localized and spread uniformly
+throughout the text.
+.PP
+Very long text lines can be expensive, especially if they have many marks and
+tags within them.
+.PP
+The display line with the insert cursor is redrawn each time the cursor
+blinks, which causes a steady stream of graphics traffic. Set the
+\fB\-insertofftime\fR attribute to 0 avoid this.
+.SS "KNOWN BUGS"
+.PP
+The \fIpathName \fBsearch \-regexp\fR sub-command attempts to perform
+sophisticated regexp matching across multiple lines in an efficient fashion
+(since Tk 8.5), examining each line individually, and then in small groups of
+lines, whether searching forwards or backwards. Under certain conditions the
+search result might differ from that obtained by applying the same regexp to
+the entire text from the widget in one go. For example, when searching with a
+greedy regexp, the widget will continue to attempt to add extra lines to the
+match as long as one of two conditions are true: either Tcl's regexp library
+returns a code to indicate a longer match is possible (but there are known
+bugs in Tcl which mean this code is not always correctly returned); or if each
+extra line added results in at least a partial match with the pattern. This
+means in the case where the first extra line added results in no match and
+Tcl's regexp system returns the incorrect code and adding a second extra line
+would actually match, the text widget will return the wrong result. In
+practice this is a rare problem, but it can occur, for example:
+.CS
+pack [\fBtext\fR .t]
+\&.t insert 1.0 "aaaa\enbbbb\encccc\enbbbb\enaaaa\en"
+\&.t search \-regexp \-\- {(a+|b+\enc+\enb+)+\ena+} 1.0
+.CE
+will not find a match when one exists of 19 characters starting from the first
+.QW b .
+.PP
+Whenever one possible match is fully enclosed in another, the search command
+will attempt to ensure only the larger match is returned. When performing
+backwards regexp searches it is possible that Tcl will not always achieve
+this, in the case where a match is preceded by one or more short,
+non-overlapping matches, all of which are preceded by a large match which
+actually encompasses all of them. The search algorithm used by the widget does
+not look back arbitrarily far for a possible match which might cover large
+portions of the widget. For example:
+.CS
+pack [\fBtext\fR .t]
+\&.t insert 1.0 "aaaa\enbbbb\enbbbb\enbbbb\enbbbb\\n"
+\&.t search \-regexp \-backward \-\- {b+\en|a+\en(b+\en)+} end
+.CE
+matches at
+.QW 5.0
+when a true greedy match would match at
+.QW 1.0 .
+Similarly if we add \fB\-all\fR to this case, it matches at all of
+.QW 5.0 ,
+.QW 4.0 ,
+.QW 3.0
+and
+.QW 1.0 ,
+when really it should only match at
+.QW 1.0
+since that match encloses all the others.
+.SH "SEE ALSO"
+entry(n), scrollbar(n)
+.SH KEYWORDS
+text, widget, tkvars
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/tk.n b/tk8.6/doc/tk.n
new file mode 100644
index 0000000..1165b67
--- /dev/null
+++ b/tk8.6/doc/tk.n
@@ -0,0 +1,135 @@
+'\"
+'\" Copyright (c) 1992 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH tk n 8.4 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+tk \- Manipulate Tk internal state
+.SH SYNOPSIS
+\fBtk\fR \fIoption \fR?\fIarg arg ...\fR?
+.BE
+.SH DESCRIPTION
+.PP
+The \fBtk\fR command provides access to miscellaneous
+elements of Tk's internal state.
+Most of the information manipulated by this command pertains to the
+application as a whole, or to a screen or display, rather than to a
+particular window.
+The command can take any of a number of different forms
+depending on the \fIoption\fR argument. The legal forms are:
+.TP
+\fBtk appname \fR?\fInewName\fR?
+.
+If \fInewName\fR is not specified, this command returns the name
+of the application (the name that may be used in \fBsend\fR
+commands to communicate with the application).
+If \fInewName\fR is specified, then the name of the application
+is changed to \fInewName\fR.
+If the given name is already in use, then a suffix of the form
+.QW "\fB #2\fR"
+or
+.QW "\fB #3\fR"
+is appended in order to make the name unique.
+The command's result is the name actually chosen.
+\fInewName\fR should not start with a capital letter.
+This will interfere with option processing, since names starting with
+capitals are assumed to be classes; as a result, Tk may not
+be able to find some options for the application.
+If sends have been disabled by deleting the \fBsend\fR command,
+this command will reenable them and recreate the \fBsend\fR
+command.
+.TP
+\fBtk busy \fIsubcommand\fR ...
+.
+This command controls the marking of window hierarchies as
+.QW busy ,
+rendering them non-interactive while some other operation is proceeding. For
+more details see the \fBbusy\fR manual page.
+.TP
+\fBtk caret \fIwindow \fR?\fB\-x \fIx\fR? ?\fB\-y \fIy\fR? ?\fB\-height \fIheight\fR?
+.
+Sets and queries the caret location for the display of the specified
+Tk window \fIwindow\fR. The caret is the per-display cursor location
+used for indicating global focus (e.g. to comply with Microsoft
+Accessibility guidelines), as well as for location of the over-the-spot
+XIM (X Input Methods) or Windows IME windows. If no options are specified,
+the last values used for setting the caret are return in option-value pair
+format. \fB\-x\fR and \fB\-y\fR represent window-relative coordinates, and
+\fB\-height\fR is the height of the current cursor location, or the height
+of the specified \fIwindow\fR if none is given.
+.TP
+\fBtk inactive \fR?\fB\-displayof \fIwindow\fR? ?\fBreset\fR?
+.
+Returns a positive integer, the number of milliseconds since the last
+time the user interacted with the system. If the \fB\-displayof\fR
+option is given then the return value refers to the display of
+\fIwindow\fR; otherwise it refers to the display of the application's
+main window.
+.RS
+.PP
+\fBtk inactive\fR will return \-1, if querying the user inactive time
+is not supported by the system, and in safe interpreters.
+.PP
+If the literal string \fBreset\fR is given as an additional argument,
+the timer is reset and an empty string is returned. Resetting the
+inactivity time is forbidden in safe interpreters and will throw an
+error if tried.
+.RE
+.TP
+\fBtk fontchooser \fIsubcommand\fR ...
+Controls the Tk font selection dialog. For more details see the
+\fBfontchooser\fR manual page.
+.TP
+\fBtk scaling \fR?\fB\-displayof \fIwindow\fR? ?\fInumber\fR?
+.
+Sets and queries the current scaling factor used by Tk to convert between
+physical units (for example, points, inches, or millimeters) and pixels. The
+\fInumber\fR argument is a floating point number that specifies the number of
+pixels per point on \fIwindow\fR's display. If the \fIwindow\fR argument is
+omitted, it defaults to the main window. If the \fInumber\fR argument is
+omitted, the current value of the scaling factor is returned.
+.RS
+.PP
+A
+.QW point
+is a unit of measurement equal to 1/72 inch. A scaling factor
+of 1.0 corresponds to 1 pixel per point, which is equivalent to a standard
+72 dpi monitor. A scaling factor of 1.25 would mean 1.25 pixels per point,
+which is the setting for a 90 dpi monitor; setting the scaling factor to
+1.25 on a 72 dpi monitor would cause everything in the application to be
+displayed 1.25 times as large as normal. The initial value for the scaling
+factor is set when the application starts, based on properties of the
+installed monitor, but it can be changed at any time. Measurements made
+after the scaling factor is changed will use the new scaling factor, but it
+is undefined whether existing widgets will resize themselves dynamically to
+accommodate the new scaling factor.
+.RE
+.TP
+\fBtk useinputmethods \fR?\fB\-displayof \fIwindow\fR? ?\fIboolean\fR?
+.
+Sets and queries the state of whether Tk should use XIM (X Input Methods)
+for filtering events. The resulting state is returned. XIM is used in
+some locales (i.e., Japanese, Korean), to handle special input devices. This
+feature is only significant on X. If XIM support is not available, this
+will always return 0. If the \fIwindow\fR argument is omitted, it defaults
+to the main window. If the \fIboolean\fR argument is omitted, the current
+state is returned. This is turned on by default for the main display.
+.TP
+\fBtk windowingsystem\fR
+.
+Returns the current Tk windowing system, one of
+\fBx11\fR (X11-based), \fBwin32\fR (MS Windows),
+or \fBaqua\fR (Mac OS X Aqua).
+.SH "SEE ALSO"
+busy(n), fontchooser(n), send(n), winfo(n)
+.SH KEYWORDS
+application name, send
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/tk4.0.ps b/tk8.6/doc/tk4.0.ps
new file mode 100644
index 0000000..d79642d
--- /dev/null
+++ b/tk8.6/doc/tk4.0.ps
@@ -0,0 +1,4602 @@
+%!
+%%BoundingBox: (atend)
+%%Pages: (atend)
+%%DocumentFonts: (atend)
+%%EndComments
+%%BeginProlog
+%
+% FrameMaker postscript_prolog 3.0, for use with FrameMaker 3.0
+% This postscript_prolog file is Copyright (c) 1986-1991 Frame Technology
+% Corporation. All rights reserved. This postscript_prolog file may be
+% freely copied and distributed in conjunction with documents created using
+% FrameMaker.
+% NOTE
+% This file fixes the problem with NeWS printers dithering color output.
+% Any questions should be sent to mickey@magickingdom.eng.sun.com
+%
+% Known Problems:
+% Due to bugs in Transcript, the 'PS-Adobe-' is omitted from line 1
+/FMversion (3.0) def
+% Set up Color vs. Black-and-White
+
+/FMPrintInColor { % once-thru loop gimmick
+ % See if we're a NeWSprint printer
+ /currentcanvas where {
+ pop systemdict /separationdict known
+ exit
+ } if
+% originally had the following, which should always be false:
+% /currentcanvas where {
+% pop currentcanvas /Color known {
+% currentcanvas /Color get
+% exit
+% } if
+% } if
+ systemdict /colorimage known
+ systemdict /currentcolortransfer known and
+exit } loop def
+
+% Uncomment the following line to force b&w on color printer
+% /FMPrintInColor false def
+/FrameDict 195 dict def
+systemdict /errordict known not {/errordict 10 dict def
+ errordict /rangecheck {stop} put} if
+% The readline in 23.0 doesn't recognize cr's as nl's on AppleTalk
+FrameDict /tmprangecheck errordict /rangecheck get put
+errordict /rangecheck {FrameDict /bug true put} put
+FrameDict /bug false put
+mark
+% Some PS machines read past the CR, so keep the following 3 lines together!
+currentfile 5 string readline
+00
+0000000000
+cleartomark
+errordict /rangecheck FrameDict /tmprangecheck get put
+FrameDict /bug get {
+ /readline {
+ /gstring exch def
+ /gfile exch def
+ /gindex 0 def
+ {
+ gfile read pop
+ dup 10 eq {exit} if
+ dup 13 eq {exit} if
+ gstring exch gindex exch put
+ /gindex gindex 1 add def
+ } loop
+ pop
+ gstring 0 gindex getinterval true
+ } def
+ } if
+/FMVERSION {
+ FMversion ne {
+ /Times-Roman findfont 18 scalefont setfont
+ 100 100 moveto
+ (FrameMaker version does not match postscript_prolog!)
+ dup =
+ show showpage
+ } if
+ } def
+/FMLOCAL {
+ FrameDict begin
+ 0 def
+ end
+ } def
+ /gstring FMLOCAL
+ /gfile FMLOCAL
+ /gindex FMLOCAL
+ /orgxfer FMLOCAL
+ /orgproc FMLOCAL
+ /organgle FMLOCAL
+ /orgfreq FMLOCAL
+ /yscale FMLOCAL
+ /xscale FMLOCAL
+ /manualfeed FMLOCAL
+ /paperheight FMLOCAL
+ /paperwidth FMLOCAL
+/FMDOCUMENT {
+ array /FMfonts exch def
+ /#copies exch def
+ FrameDict begin
+ 0 ne dup {setmanualfeed} if
+ /manualfeed exch def
+ /paperheight exch def
+ /paperwidth exch def
+ /yscale exch def
+ /xscale exch def
+ currenttransfer cvlit /orgxfer exch def
+ currentscreen cvlit /orgproc exch def
+ /organgle exch def /orgfreq exch def
+ setpapername
+ manualfeed {true} {papersize} ifelse
+ {manualpapersize} {false} ifelse
+ {desperatepapersize} if
+ end
+ } def
+ /pagesave FMLOCAL
+ /orgmatrix FMLOCAL
+ /landscape FMLOCAL
+/FMBEGINPAGE {
+ FrameDict begin
+ /pagesave save def
+ 3.86 setmiterlimit
+ /landscape exch 0 ne def
+ landscape {
+ 90 rotate 0 exch neg translate pop
+ }
+ {pop pop}
+ ifelse
+ xscale yscale scale
+ /orgmatrix matrix def
+ gsave
+ } def
+/FMENDPAGE {
+ grestore
+ pagesave restore
+ end
+ showpage
+ } def
+/FMFONTDEFINE {
+ FrameDict begin
+ findfont
+ ReEncode
+ 1 index exch
+ definefont
+ FMfonts 3 1 roll
+ put
+ end
+ } def
+/FMFILLS {
+ FrameDict begin
+ array /fillvals exch def
+ end
+ } def
+/FMFILL {
+ FrameDict begin
+ fillvals 3 1 roll put
+ end
+ } def
+/FMNORMALIZEGRAPHICS {
+ newpath
+ 0.0 0.0 moveto
+ 1 setlinewidth
+ 0 setlinecap
+ 0 0 0 sethsbcolor
+ 0 setgray
+ } bind def
+ /fx FMLOCAL
+ /fy FMLOCAL
+ /fh FMLOCAL
+ /fw FMLOCAL
+ /llx FMLOCAL
+ /lly FMLOCAL
+ /urx FMLOCAL
+ /ury FMLOCAL
+/FMBEGINEPSF {
+ end
+ /FMEPSF save def
+ /showpage {} def
+ FMNORMALIZEGRAPHICS
+ [/fy /fx /fh /fw /ury /urx /lly /llx] {exch def} forall
+ fx fy translate
+ rotate
+ fw urx llx sub div fh ury lly sub div scale
+ llx neg lly neg translate
+ } bind def
+/FMENDEPSF {
+ FMEPSF restore
+ FrameDict begin
+ } bind def
+FrameDict begin
+/setmanualfeed {
+%%BeginFeature *ManualFeed True
+ statusdict /manualfeed true put
+%%EndFeature
+ } def
+/max {2 copy lt {exch} if pop} bind def
+/min {2 copy gt {exch} if pop} bind def
+/inch {72 mul} def
+/pagedimen {
+ paperheight sub abs 16 lt exch
+ paperwidth sub abs 16 lt and
+ {/papername exch def} {pop} ifelse
+ } def
+ /papersizedict FMLOCAL
+/setpapername {
+ /papersizedict 14 dict def
+ papersizedict begin
+ /papername /unknown def
+ /Letter 8.5 inch 11.0 inch pagedimen
+ /LetterSmall 7.68 inch 10.16 inch pagedimen
+ /Tabloid 11.0 inch 17.0 inch pagedimen
+ /Ledger 17.0 inch 11.0 inch pagedimen
+ /Legal 8.5 inch 14.0 inch pagedimen
+ /Statement 5.5 inch 8.5 inch pagedimen
+ /Executive 7.5 inch 10.0 inch pagedimen
+ /A3 11.69 inch 16.5 inch pagedimen
+ /A4 8.26 inch 11.69 inch pagedimen
+ /A4Small 7.47 inch 10.85 inch pagedimen
+ /B4 10.125 inch 14.33 inch pagedimen
+ /B5 7.16 inch 10.125 inch pagedimen
+ end
+ } def
+/papersize {
+ papersizedict begin
+ /Letter {lettertray letter} def
+ /LetterSmall {lettertray lettersmall} def
+ /Tabloid {11x17tray 11x17} def
+ /Ledger {ledgertray ledger} def
+ /Legal {legaltray legal} def
+ /Statement {statementtray statement} def
+ /Executive {executivetray executive} def
+ /A3 {a3tray a3} def
+ /A4 {a4tray a4} def
+ /A4Small {a4tray a4small} def
+ /B4 {b4tray b4} def
+ /B5 {b5tray b5} def
+ /unknown {unknown} def
+ papersizedict dup papername known {papername} {/unknown} ifelse get
+ end
+ /FMdicttop countdictstack 1 add def
+ statusdict begin stopped end
+ countdictstack -1 FMdicttop {pop end} for
+ } def
+/manualpapersize {
+ papersizedict begin
+ /Letter {letter} def
+ /LetterSmall {lettersmall} def
+ /Tabloid {11x17} def
+ /Ledger {ledger} def
+ /Legal {legal} def
+ /Statement {statement} def
+ /Executive {executive} def
+ /A3 {a3} def
+ /A4 {a4} def
+ /A4Small {a4small} def
+ /B4 {b4} def
+ /B5 {b5} def
+ /unknown {unknown} def
+ papersizedict dup papername known {papername} {/unknown} ifelse get
+ end
+ stopped
+ } def
+/desperatepapersize {
+ statusdict /setpageparams known
+ {
+ paperwidth paperheight 0 1
+ statusdict begin
+ {setpageparams} stopped pop
+ end
+ } if
+ } def
+/savematrix {
+ orgmatrix currentmatrix pop
+ } bind def
+/restorematrix {
+ orgmatrix setmatrix
+ } bind def
+/dmatrix matrix def
+/dpi 72 0 dmatrix defaultmatrix dtransform
+ dup mul exch dup mul add sqrt def
+/freq dpi 18.75 div 8 div round dup 0 eq {pop 1} if 8 mul dpi exch div def
+/sangle 1 0 dmatrix defaultmatrix dtransform exch atan def
+/DiacriticEncoding [
+/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef /space /exclam /quotedbl
+/numbersign /dollar /percent /ampersand /quotesingle /parenleft
+/parenright /asterisk /plus /comma /hyphen /period /slash /zero /one
+/two /three /four /five /six /seven /eight /nine /colon /semicolon
+/less /equal /greater /question /at /A /B /C /D /E /F /G /H /I /J /K
+/L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft /backslash
+/bracketright /asciicircum /underscore /grave /a /b /c /d /e /f /g /h
+/i /j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z /braceleft /bar
+/braceright /asciitilde /.notdef /Adieresis /Aring /Ccedilla /Eacute
+/Ntilde /Odieresis /Udieresis /aacute /agrave /acircumflex /adieresis
+/atilde /aring /ccedilla /eacute /egrave /ecircumflex /edieresis
+/iacute /igrave /icircumflex /idieresis /ntilde /oacute /ograve
+/ocircumflex /odieresis /otilde /uacute /ugrave /ucircumflex
+/udieresis /dagger /.notdef /cent /sterling /section /bullet
+/paragraph /germandbls /registered /copyright /trademark /acute
+/dieresis /.notdef /AE /Oslash /.notdef /.notdef /.notdef /.notdef
+/yen /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
+/ordfeminine /ordmasculine /.notdef /ae /oslash /questiondown
+/exclamdown /logicalnot /.notdef /florin /.notdef /.notdef
+/guillemotleft /guillemotright /ellipsis /.notdef /Agrave /Atilde
+/Otilde /OE /oe /endash /emdash /quotedblleft /quotedblright
+/quoteleft /quoteright /.notdef /.notdef /ydieresis /Ydieresis
+/fraction /currency /guilsinglleft /guilsinglright /fi /fl /daggerdbl
+/periodcentered /quotesinglbase /quotedblbase /perthousand
+/Acircumflex /Ecircumflex /Aacute /Edieresis /Egrave /Iacute
+/Icircumflex /Idieresis /Igrave /Oacute /Ocircumflex /.notdef /Ograve
+/Uacute /Ucircumflex /Ugrave /dotlessi /circumflex /tilde /macron
+/breve /dotaccent /ring /cedilla /hungarumlaut /ogonek /caron
+] def
+/ReEncode {
+ dup
+ length
+ dict begin
+ {
+ 1 index /FID ne
+ {def}
+ {pop pop} ifelse
+ } forall
+ 0 eq {/Encoding DiacriticEncoding def} if
+ currentdict
+ end
+ } bind def
+/graymode true def
+ /bwidth FMLOCAL
+ /bpside FMLOCAL
+ /bstring FMLOCAL
+ /onbits FMLOCAL
+ /offbits FMLOCAL
+ /xindex FMLOCAL
+ /yindex FMLOCAL
+ /x FMLOCAL
+ /y FMLOCAL
+/setpattern {
+ /bwidth exch def
+ /bpside exch def
+ /bstring exch def
+ /onbits 0 def /offbits 0 def
+ freq sangle landscape {90 add} if
+ {/y exch def
+ /x exch def
+ /xindex x 1 add 2 div bpside mul cvi def
+ /yindex y 1 add 2 div bpside mul cvi def
+ bstring yindex bwidth mul xindex 8 idiv add get
+ 1 7 xindex 8 mod sub bitshift and 0 ne
+ {/onbits onbits 1 add def 1}
+ {/offbits offbits 1 add def 0}
+ ifelse
+ }
+ setscreen
+ {} settransfer
+ offbits offbits onbits add div FMsetgray
+ /graymode false def
+ } bind def
+/grayness {
+ FMsetgray
+ graymode not {
+ /graymode true def
+ orgxfer cvx settransfer
+ orgfreq organgle orgproc cvx setscreen
+ } if
+ } bind def
+ /HUE FMLOCAL
+ /SAT FMLOCAL
+ /BRIGHT FMLOCAL
+ /Colors FMLOCAL
+FMPrintInColor
+
+ {
+ /HUE 0 def
+ /SAT 0 def
+ /BRIGHT 0 def
+ % array of arrays Hue and Sat values for the separations [HUE BRIGHT]
+ /Colors
+ [[0 0 ] % black
+ [0 0 ] % white
+ [0.00 1.0] % red
+ [0.37 1.0] % green
+ [0.60 1.0] % blue
+ [0.50 1.0] % cyan
+ [0.83 1.0] % magenta
+ [0.16 1.0] % comment / yellow
+ ] def
+
+ /BEGINBITMAPCOLOR {
+ BITMAPCOLOR} def
+ /BEGINBITMAPCOLORc {
+ BITMAPCOLORc} def
+ /BEGINBITMAPTRUECOLOR {
+ BITMAPTRUECOLOR } def
+ /BEGINBITMAPTRUECOLORc {
+ BITMAPTRUECOLORc } def
+ /K {
+ Colors exch get dup
+ 0 get /HUE exch store
+ 1 get /BRIGHT exch store
+ HUE 0 eq BRIGHT 0 eq and
+ {1.0 SAT sub setgray}
+ {HUE SAT BRIGHT sethsbcolor}
+ ifelse
+ } def
+ /FMsetgray {
+ /SAT exch 1.0 exch sub store
+ HUE 0 eq BRIGHT 0 eq and
+ {1.0 SAT sub setgray}
+ {HUE SAT BRIGHT sethsbcolor}
+ ifelse
+ } bind def
+ }
+
+ {
+ /BEGINBITMAPCOLOR {
+ BITMAPGRAY} def
+ /BEGINBITMAPCOLORc {
+ BITMAPGRAYc} def
+ /BEGINBITMAPTRUECOLOR {
+ BITMAPTRUEGRAY } def
+ /BEGINBITMAPTRUECOLORc {
+ BITMAPTRUEGRAYc } def
+ /FMsetgray {setgray} bind def
+ /K {
+ pop
+ } def
+ }
+ifelse
+/normalize {
+ transform round exch round exch itransform
+ } bind def
+/dnormalize {
+ dtransform round exch round exch idtransform
+ } bind def
+/lnormalize {
+ 0 dtransform exch cvi 2 idiv 2 mul 1 add exch idtransform pop
+ } bind def
+/H {
+ lnormalize setlinewidth
+ } bind def
+/Z {
+ setlinecap
+ } bind def
+ /fillvals FMLOCAL
+/X {
+ fillvals exch get
+ dup type /stringtype eq
+ {8 1 setpattern}
+ {grayness}
+ ifelse
+ } bind def
+/V {
+ gsave eofill grestore
+ } bind def
+/N {
+ stroke
+ } bind def
+/M {newpath moveto} bind def
+/E {lineto} bind def
+/D {curveto} bind def
+/O {closepath} bind def
+ /n FMLOCAL
+/L {
+ /n exch def
+ newpath
+ normalize
+ moveto
+ 2 1 n {pop normalize lineto} for
+ } bind def
+/Y {
+ L
+ closepath
+ } bind def
+ /x1 FMLOCAL
+ /x2 FMLOCAL
+ /y1 FMLOCAL
+ /y2 FMLOCAL
+ /rad FMLOCAL
+/R {
+ /y2 exch def
+ /x2 exch def
+ /y1 exch def
+ /x1 exch def
+ x1 y1
+ x2 y1
+ x2 y2
+ x1 y2
+ 4 Y
+ } bind def
+/RR {
+ /rad exch def
+ normalize
+ /y2 exch def
+ /x2 exch def
+ normalize
+ /y1 exch def
+ /x1 exch def
+ newpath
+ x1 y1 rad add moveto
+ x1 y2 x2 y2 rad arcto
+ x2 y2 x2 y1 rad arcto
+ x2 y1 x1 y1 rad arcto
+ x1 y1 x1 y2 rad arcto
+ closepath
+ 16 {pop} repeat
+ } bind def
+/C {
+ grestore
+ gsave
+ R
+ clip
+ } bind def
+ /FMpointsize FMLOCAL
+/F {
+ FMfonts exch get
+ FMpointsize scalefont
+ setfont
+ } bind def
+/Q {
+ /FMpointsize exch def
+ F
+ } bind def
+/T {
+ moveto show
+ } bind def
+/RF {
+ rotate
+ 0 ne {-1 1 scale} if
+ } bind def
+/TF {
+ gsave
+ moveto
+ RF
+ show
+ grestore
+ } bind def
+/P {
+ moveto
+ 0 32 3 2 roll widthshow
+ } bind def
+/PF {
+ gsave
+ moveto
+ RF
+ 0 32 3 2 roll widthshow
+ grestore
+ } bind def
+/S {
+ moveto
+ 0 exch ashow
+ } bind def
+/SF {
+ gsave
+ moveto
+ RF
+ 0 exch ashow
+ grestore
+ } bind def
+/B {
+ moveto
+ 0 32 4 2 roll 0 exch awidthshow
+ } bind def
+/BF {
+ gsave
+ moveto
+ RF
+ 0 32 4 2 roll 0 exch awidthshow
+ grestore
+ } bind def
+/G {
+ gsave
+ newpath
+ normalize translate 0.0 0.0 moveto
+ dnormalize scale
+ 0.0 0.0 1.0 5 3 roll arc
+ closepath fill
+ grestore
+ } bind def
+/A {
+ gsave
+ savematrix
+ newpath
+ 2 index 2 div add exch 3 index 2 div sub exch
+ normalize 2 index 2 div sub exch 3 index 2 div add exch
+ translate
+ scale
+ 0.0 0.0 1.0 5 3 roll arc
+ restorematrix
+ stroke
+ grestore
+ } bind def
+ /x FMLOCAL
+ /y FMLOCAL
+ /w FMLOCAL
+ /h FMLOCAL
+ /xx FMLOCAL
+ /yy FMLOCAL
+ /ww FMLOCAL
+ /hh FMLOCAL
+ /FMsaveobject FMLOCAL
+ /FMoptop FMLOCAL
+ /FMdicttop FMLOCAL
+/BEGINPRINTCODE {
+ /FMdicttop countdictstack 1 add def
+ /FMoptop count 4 sub def
+ /FMsaveobject save def
+ userdict begin
+ /showpage {} def
+ FMNORMALIZEGRAPHICS
+ 3 index neg 3 index neg translate
+ } bind def
+/ENDPRINTCODE {
+ count -1 FMoptop {pop pop} for
+ countdictstack -1 FMdicttop {pop end} for
+ FMsaveobject restore
+ } bind def
+/gn {
+ 0
+ { 46 mul
+ cf read pop
+ 32 sub
+ dup 46 lt {exit} if
+ 46 sub add
+ } loop
+ add
+ } bind def
+ /str FMLOCAL
+/cfs {
+ /str sl string def
+ 0 1 sl 1 sub {str exch val put} for
+ str def
+ } bind def
+/ic [
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223
+ 0
+ {0 hx} {1 hx} {2 hx} {3 hx} {4 hx} {5 hx} {6 hx} {7 hx} {8 hx} {9 hx}
+ {10 hx} {11 hx} {12 hx} {13 hx} {14 hx} {15 hx} {16 hx} {17 hx} {18 hx}
+ {19 hx} {gn hx} {0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11} {12}
+ {13} {14} {15} {16} {17} {18} {19} {gn} {0 wh} {1 wh} {2 wh} {3 wh}
+ {4 wh} {5 wh} {6 wh} {7 wh} {8 wh} {9 wh} {10 wh} {11 wh} {12 wh}
+ {13 wh} {14 wh} {gn wh} {0 bl} {1 bl} {2 bl} {3 bl} {4 bl} {5 bl} {6 bl}
+ {7 bl} {8 bl} {9 bl} {10 bl} {11 bl} {12 bl} {13 bl} {14 bl} {gn bl}
+ {0 fl} {1 fl} {2 fl} {3 fl} {4 fl} {5 fl} {6 fl} {7 fl} {8 fl} {9 fl}
+ {10 fl} {11 fl} {12 fl} {13 fl} {14 fl} {gn fl}
+ ] def
+ /sl FMLOCAL
+ /val FMLOCAL
+ /ws FMLOCAL
+ /im FMLOCAL
+ /bs FMLOCAL
+ /cs FMLOCAL
+ /len FMLOCAL
+ /pos FMLOCAL
+/ms {
+ /sl exch def
+ /val 255 def
+ /ws cfs
+ /im cfs
+ /val 0 def
+ /bs cfs
+ /cs cfs
+ } bind def
+400 ms
+/ip {
+ is
+ 0
+ cf cs readline pop
+ { ic exch get exec
+ add
+ } forall
+ pop
+
+ } bind def
+/wh {
+ /len exch def
+ /pos exch def
+ ws 0 len getinterval im pos len getinterval copy pop
+ pos len
+ } bind def
+/bl {
+ /len exch def
+ /pos exch def
+ bs 0 len getinterval im pos len getinterval copy pop
+ pos len
+ } bind def
+/s1 1 string def
+/fl {
+ /len exch def
+ /pos exch def
+ /val cf s1 readhexstring pop 0 get def
+ pos 1 pos len add 1 sub {im exch val put} for
+ pos len
+ } bind def
+/hx {
+ 3 copy getinterval
+ cf exch readhexstring pop pop
+ } bind def
+ /h FMLOCAL
+ /w FMLOCAL
+ /d FMLOCAL
+ /lb FMLOCAL
+ /bitmapsave FMLOCAL
+ /is FMLOCAL
+ /cf FMLOCAL
+/wbytes {
+ dup
+ 8 eq {pop} {1 eq {7 add 8 idiv} {3 add 4 idiv} ifelse} ifelse
+ } bind def
+/BEGINBITMAPBWc {
+ 1 {} COMMONBITMAPc
+ } bind def
+/BEGINBITMAPGRAYc {
+ 8 {} COMMONBITMAPc
+ } bind def
+/BEGINBITMAP2BITc {
+ 2 {} COMMONBITMAPc
+ } bind def
+/COMMONBITMAPc {
+ /r exch def
+ /d exch def
+ gsave
+ translate rotate scale /h exch def /w exch def
+ /lb w d wbytes def
+ sl lb lt {lb ms} if
+ /bitmapsave save def
+ r
+ /is im 0 lb getinterval def
+ ws 0 lb getinterval is copy pop
+ /cf currentfile def
+ w h d [w 0 0 h neg 0 h]
+ {ip} image
+ bitmapsave restore
+ grestore
+ } bind def
+/BEGINBITMAPBW {
+ 1 {} COMMONBITMAP
+ } bind def
+/BEGINBITMAPGRAY {
+ 8 {} COMMONBITMAP
+ } bind def
+/BEGINBITMAP2BIT {
+ 2 {} COMMONBITMAP
+ } bind def
+/COMMONBITMAP {
+ /r exch def
+ /d exch def
+ gsave
+ translate rotate scale /h exch def /w exch def
+ /bitmapsave save def
+ r
+ /is w d wbytes string def
+ /cf currentfile def
+ w h d [w 0 0 h neg 0 h]
+ {cf is readhexstring pop} image
+ bitmapsave restore
+ grestore
+ } bind def
+ /proc1 FMLOCAL
+ /proc2 FMLOCAL
+ /newproc FMLOCAL
+/Fmcc {
+ /proc2 exch cvlit def
+ /proc1 exch cvlit def
+ /newproc proc1 length proc2 length add array def
+ newproc 0 proc1 putinterval
+ newproc proc1 length proc2 putinterval
+ newproc cvx
+} bind def
+/ngrayt 256 array def
+/nredt 256 array def
+/nbluet 256 array def
+/ngreent 256 array def
+ /gryt FMLOCAL
+ /blut FMLOCAL
+ /grnt FMLOCAL
+ /redt FMLOCAL
+ /indx FMLOCAL
+ /cynu FMLOCAL
+ /magu FMLOCAL
+ /yelu FMLOCAL
+ /k FMLOCAL
+ /u FMLOCAL
+/colorsetup {
+ currentcolortransfer
+ /gryt exch def
+ /blut exch def
+ /grnt exch def
+ /redt exch def
+ 0 1 255 {
+ /indx exch def
+ /cynu 1 red indx get 255 div sub def
+ /magu 1 green indx get 255 div sub def
+ /yelu 1 blue indx get 255 div sub def
+ /k cynu magu min yelu min def
+ /u k currentundercolorremoval exec def
+ nredt indx 1 0 cynu u sub max sub redt exec put
+ ngreent indx 1 0 magu u sub max sub grnt exec put
+ nbluet indx 1 0 yelu u sub max sub blut exec put
+ ngrayt indx 1 k currentblackgeneration exec sub gryt exec put
+ } for
+ {255 mul cvi nredt exch get}
+ {255 mul cvi ngreent exch get}
+ {255 mul cvi nbluet exch get}
+ {255 mul cvi ngrayt exch get}
+ setcolortransfer
+ {pop 0} setundercolorremoval
+ {} setblackgeneration
+ } bind def
+ /tran FMLOCAL
+/fakecolorsetup {
+ /tran 256 string def
+ 0 1 255 {/indx exch def
+ tran indx
+ red indx get 77 mul
+ green indx get 151 mul
+ blue indx get 28 mul
+ add add 256 idiv put} for
+ currenttransfer
+ {255 mul cvi tran exch get 255.0 div}
+ exch Fmcc settransfer
+} bind def
+/BITMAPCOLOR {
+ /d 8 def
+ gsave
+ translate rotate scale /h exch def /w exch def
+ /bitmapsave save def
+ colorsetup
+ /is w d wbytes string def
+ /cf currentfile def
+ w h d [w 0 0 h neg 0 h]
+ {cf is readhexstring pop} {is} {is} true 3 colorimage
+ bitmapsave restore
+ grestore
+ } bind def
+/BITMAPCOLORc {
+ /d 8 def
+ gsave
+ translate rotate scale /h exch def /w exch def
+ /lb w d wbytes def
+ sl lb lt {lb ms} if
+ /bitmapsave save def
+ colorsetup
+ /is im 0 lb getinterval def
+ ws 0 lb getinterval is copy pop
+ /cf currentfile def
+ w h d [w 0 0 h neg 0 h]
+ {ip} {is} {is} true 3 colorimage
+ bitmapsave restore
+ grestore
+ } bind def
+/BITMAPTRUECOLORc {
+ gsave
+ translate rotate scale /h exch def /w exch def
+ /bitmapsave save def
+
+ /is w string def
+
+ ws 0 w getinterval is copy pop
+ /cf currentfile def
+ w h 8 [w 0 0 h neg 0 h]
+ {ip} {gip} {bip} true 3 colorimage
+ bitmapsave restore
+ grestore
+ } bind def
+/BITMAPTRUECOLOR {
+ gsave
+ translate rotate scale /h exch def /w exch def
+ /bitmapsave save def
+ /is w string def
+ /gis w string def
+ /bis w string def
+ /cf currentfile def
+ w h 8 [w 0 0 h neg 0 h]
+ { cf is readhexstring pop }
+ { cf gis readhexstring pop }
+ { cf bis readhexstring pop }
+ true 3 colorimage
+ bitmapsave restore
+ grestore
+ } bind def
+/BITMAPTRUEGRAYc {
+ gsave
+ translate rotate scale /h exch def /w exch def
+ /bitmapsave save def
+
+ /is w string def
+
+ ws 0 w getinterval is copy pop
+ /cf currentfile def
+ w h 8 [w 0 0 h neg 0 h]
+ {ip gip bip w gray} image
+ bitmapsave restore
+ grestore
+ } bind def
+/ww FMLOCAL
+/r FMLOCAL
+/g FMLOCAL
+/b FMLOCAL
+/i FMLOCAL
+/gray {
+ /ww exch def
+ /b exch def
+ /g exch def
+ /r exch def
+ 0 1 ww 1 sub { /i exch def r i get .299 mul g i get .587 mul
+ b i get .114 mul add add r i 3 -1 roll floor cvi put } for
+ r
+ } bind def
+/BITMAPTRUEGRAY {
+ gsave
+ translate rotate scale /h exch def /w exch def
+ /bitmapsave save def
+ /is w string def
+ /gis w string def
+ /bis w string def
+ /cf currentfile def
+ w h 8 [w 0 0 h neg 0 h]
+ { cf is readhexstring pop
+ cf gis readhexstring pop
+ cf bis readhexstring pop w gray} image
+ bitmapsave restore
+ grestore
+ } bind def
+/BITMAPGRAY {
+ 8 {fakecolorsetup} COMMONBITMAP
+ } bind def
+/BITMAPGRAYc {
+ 8 {fakecolorsetup} COMMONBITMAPc
+ } bind def
+/ENDBITMAP {
+ } bind def
+end
+ /ALDsave FMLOCAL
+ /ALDmatrix matrix def ALDmatrix currentmatrix pop
+/StartALD {
+ /ALDsave save def
+ savematrix
+ ALDmatrix setmatrix
+ } bind def
+/InALD {
+ restorematrix
+ } bind def
+/DoneALD {
+ ALDsave restore
+ } bind def
+%%EndProlog
+%%BeginSetup
+(3.0) FMVERSION
+1 1 612 792 0 1 13 FMDOCUMENT
+0 0 /Helvetica-Bold FMFONTDEFINE
+1 0 /Times-Bold FMFONTDEFINE
+2 0 /Times-Italic FMFONTDEFINE
+3 0 /Times-Roman FMFONTDEFINE
+4 0 /Helvetica FMFONTDEFINE
+5 0 /Courier FMFONTDEFINE
+6 0 /Courier-Oblique FMFONTDEFINE
+32 FMFILLS
+0 0 FMFILL
+1 0.1 FMFILL
+2 0.3 FMFILL
+3 0.5 FMFILL
+4 0.7 FMFILL
+5 0.9 FMFILL
+6 0.97 FMFILL
+7 1 FMFILL
+8 <0f1e3c78f0e1c387> FMFILL
+9 <0f87c3e1f0783c1e> FMFILL
+10 <cccccccccccccccc> FMFILL
+11 <ffff0000ffff0000> FMFILL
+12 <8142241818244281> FMFILL
+13 <03060c183060c081> FMFILL
+14 <8040201008040201> FMFILL
+16 1 FMFILL
+17 0.9 FMFILL
+18 0.7 FMFILL
+19 0.5 FMFILL
+20 0.3 FMFILL
+21 0.1 FMFILL
+22 0.03 FMFILL
+23 0 FMFILL
+24 <f0e1c3870f1e3c78> FMFILL
+25 <f0783c1e0f87c3e1> FMFILL
+26 <3333333333333333> FMFILL
+27 <0000ffff0000ffff> FMFILL
+28 <7ebddbe7e7dbbd7e> FMFILL
+29 <fcf9f3e7cf9f3f7e> FMFILL
+30 <7fbfdfeff7fbfdfe> FMFILL
+%%EndSetup
+%%Page: "1" 1
+%%BeginPaperSize: Letter
+%%EndPaperSize
+612 792 0 FMBEGINPAGE
+98.1 675 512.1 675 2 L
+7 X
+0 K
+V
+2 H
+0 Z
+0 X
+N
+98.1 450 512.1 450 2 L
+7 X
+V
+2 Z
+0 X
+N
+98.1 108 512.1 126 R
+7 X
+V
+0 10 Q
+0 X
+(1) 506.54 119.33 T
+1 24 Q
+-0.48 (Tk4.0 Overview and Porting Guide) 152.1 605 S
+2 12 Q
+(John Ouster) 152.1 563 T
+(hout) 210.84 563 T
+98.1 135 512.1 423 R
+7 X
+V
+3 10 Q
+0 X
+(Tk version 4.0 is a major new release with many improvements, new features, and bug) 152.1 416.33 T
+(\336xes. This document provides an introduction to the new features and describes the most) 152.1 404.33 T
+-0.18 (common problems you are likely to encounter when porting scripts from Tk 3.6, the previ-) 152.1 392.33 P
+(ous release. This is) 152.1 380.33 T
+2 F
+(not) 230.66 380.33 T
+3 F
+( an introduction to Tk: I assume that you are already familiar with) 243.43 380.33 T
+(Tk 3.6 as described in the book) 152.1 368.33 T
+2 F
+(T) 279.79 368.33 T
+(cl and the Tk T) 284.43 368.33 T
+(oolkit) 343.48 368.33 T
+3 F
+(.) 366.24 368.33 T
+-0.26 (The good news about Tk 4.0 is that it has many improvements over Tk 3.6. Here are a) 170.1 356.33 P
+(few of the most important new features:) 152.1 344.33 T
+3 12 Q
+(\245) 152.1 329.33 T
+3 10 Q
+(Tk 4.0 includes a general-purpose mechanism for manipulating color images \050Tk 3.6) 162.9 329.33 T
+(supports only monochrome images\051.) 162.9 317.33 T
+3 12 Q
+(\245) 152.1 302.33 T
+3 10 Q
+-0.17 (The text widget in Tk 4.0 includes many new features such as tab stops, embedded win-) 162.9 302.33 P
+(dows, horizontal scrolling, and many new formatting options.) 162.9 290.33 T
+3 12 Q
+(\245) 152.1 275.33 T
+3 10 Q
+(The binding mechanism in Tk 4.0 is much more powerful in Tk 3.6.) 162.9 275.33 T
+3 12 Q
+(\245) 152.1 260.33 T
+3 10 Q
+(Motif compliance is much better) 162.9 260.33 T
+(. For example, there is now support for keyboard tra-) 292.82 260.33 T
+(versal and focus highlights.) 162.9 248.33 T
+3 12 Q
+(\245) 152.1 233.33 T
+3 10 Q
+(Many widgets have been improved. For example, buttons and labels can display multi-) 162.9 233.33 T
+(line justi\336ed text, and scales can handle real values.) 162.9 221.33 T
+(The bad news about Tk 4.0 is that it contains several incompatibilities with Tk 3.6.) 170.1 206.33 T
+(Ever since the \336rst release of Tk I have assumed that there would eventually be a major) 152.1 194.33 T
+(new release of Tk with substantial incompatibilities. I knew that I wouldn\325) 152.1 182.33 T
+(t be able to get) 450.06 182.33 T
+(all of the features of Tk right the \336rst time; rather than live forever with all of my early) 152.1 170.33 T
+(mistakes, I wanted to have a chance to correct them. Tk 4.0 is that correction. I apologize) 152.1 158.33 T
+-0.05 (for the incompatibilities, but I hope they improve Tk enough to justify the dif) 152.1 146.33 P
+-0.05 (\336culties you) 460.55 146.33 P
+44.1 351 98.1 423 C
+35.1 360 197.1 414 R
+7 X
+0 K
+V
+1 9 Q
+0 X
+(FIGURE 1) 35.1 408 T
+(T) 35.1 387 T
+(ABLE 1) 40.43 387 T
+26.1 351 125.1 423 R
+7 X
+V
+40.5 63 571.5 729 C
+FMENDPAGE
+%%EndPage: "1" 2
+%%Page: "2" 2
+612 792 0 FMBEGINPAGE
+0 10 Q
+0 X
+0 K
+(2) 98.1 668.33 T
+4 F
+(Tk4.0 Overview and Porting Guide) 359.34 668.33 T
+98.1 660.6 512.1 660.6 2 L
+0.25 H
+0 Z
+N
+98.1 135 512.1 639 R
+7 X
+V
+3 F
+0 X
+(encounter during porting. Tk 4.0 is a one-time correction: we will try very hard to avoid) 152.1 632.33 T
+(substantial incompatibilities \050especially in Tk\325) 152.1 620.3 T
+(s T) 337 620.3 T
+(cl-level interfaces\051 in future releases.) 348.79 620.3 T
+-0.4 (Sections 1-1) 170.1 608.3 P
+-0.4 (1 cover the major areas of change in Tk 4.0: bindings, focus, text widgets,) 219.02 608.3 P
+-0 (Motif compliance, other widget changes, images, color management, event handling, sup-) 152.1 596.26 P
+(port for multiple displays, the) 152.1 584.23 T
+5 F
+(send) 273.14 584.23 T
+3 F
+( command, and the selection. Section 12 summarizes) 297.13 584.23 T
+(several smaller changes. Section 13 lists all of the incompatibilities that af) 152.1 572.19 T
+(fect T) 448.4 572.19 T
+(cl scripts,) 471.29 572.19 T
+-0.02 (along with suggestions for how to deal with them. The explanations here are not intended) 152.1 560.16 P
+(to be comprehensive, but rather to introduce you to the issues; for complete information) 152.1 548.12 T
+(on new or modi\336ed commands, refer to the reference documentation that comes with the) 152.1 536.09 T
+(distribution.) 152.1 524.05 T
+98.1 480.7 512.1 483.72 C
+152.1 481.92 512.1 481.92 2 L
+0.5 H
+2 Z
+0 X
+0 K
+N
+98.1 482.21 143.1 482.21 2 L
+0 Z
+N
+40.5 63 571.5 729 C
+0 12 Q
+0 X
+0 K
+(1) 134.63 487.72 T
+(Bindings) 152.1 487.72 T
+3 10 Q
+-0.35 (The changes for Tk 4.0 that are most likely to af) 152.1 464.03 P
+-0.35 (fect existing T) 341.31 464.03 P
+-0.35 (cl scripts are those related to) 397.64 464.03 P
+(bindings. The new binding mechanism in Tk 4.0 is much more powerful than that of Tk) 152.1 452 T
+(3.6, particularly in the way it allows behaviors to be combined, but several incompatible) 152.1 439.96 T
+(changes were required to implement the new features. These changes are likely to break) 152.1 427.93 T
+(most Tk 3.6 scripts. Fortunately) 152.1 415.89 T
+(, it is relatively easy to upgrade your bindings to work) 279.16 415.89 T
+(under Tk 4.0.) 152.1 403.86 T
+-0.27 (The basic mechanism for bindings is the same as in Tk 3.6. A binding associates a T) 170.1 391.86 P
+-0.27 (cl) 502.65 391.86 P
+(script with a particular event \050or sequence of events\051 occurring in one or more windows;) 152.1 379.82 T
+-0.11 (the script will be invoked automatically whenever the event sequence occurs in any of the) 152.1 367.79 P
+-0.13 (speci\336ed windows. The Tk 4.0 binding mechanism has three major feature changes. First,) 152.1 355.75 P
+(there is a more general mechanism for specifying the relationship between windows and) 152.1 343.72 T
+(bindings, called) 152.1 331.68 T
+2 F
+(binding tags) 217.89 331.68 T
+3 F
+(. Second, the con\337ict resolution mechanism \050which is) 267.6 331.68 T
+(invoked when more than one binding matches an event\051 has been changed to allow more) 152.1 319.65 T
+(than one binding script to execute for a single event. Third, the) 152.1 307.61 T
+5 F
+(Any) 405.81 307.61 T
+3 F
+( modi\336er is now) 423.8 307.61 T
+(implicit in all binding patterns. These changes are discussed separately in the subsections) 152.1 295.58 T
+(that follow) 152.1 283.54 T
+(.) 195.04 283.54 T
+-0.16 (Overall, the main ef) 170.1 271.54 P
+-0.16 (fect of Tk 4.0\325) 249.37 271.54 P
+-0.16 (s binding changes is that it allows more bindings to) 306.06 271.54 P
+(trigger than Tk 3.6 does. Feedback from the T) 152.1 259.51 T
+(cl/Tk community about the Tk 3.6 binding) 335.71 259.51 T
+(mechanism indicated that it was too conservative about triggering bindings. This caused) 152.1 247.47 T
+(the system to lose behaviors relatively easily and made the binding structure fragile. It) 152.1 235.44 T
+-0.35 (appears to be easier to deal with too many binding invocations than too few) 152.1 223.4 P
+-0.35 (, so Tk 4.0 tries) 449.17 223.4 P
+(to err in this direction.) 152.1 211.37 T
+0 F
+(1.1) 127.41 181.37 T
+(Binding tags) 152.1 181.37 T
+3 F
+(In Tk 3.6 you specify the window\050s\051 for a binding in one of three ways:) 152.1 165.37 T
+3 12 Q
+(\245) 152.1 150.37 T
+3 10 Q
+(Y) 162.9 150.37 T
+(ou give the name of a window) 169.12 150.37 T
+(, such as) 289.49 150.37 T
+5 F
+(.a.b.c) 326.13 150.37 T
+3 F
+(, in which case the binding applies) 362.11 150.37 T
+(only to that window) 162.9 138.33 T
+(.) 242.49 138.33 T
+FMENDPAGE
+%%EndPage: "2" 3
+%%Page: "3" 3
+612 792 0 FMBEGINPAGE
+4 10 Q
+0 X
+0 K
+(1 Bindings) 98.1 668.33 T
+0 F
+(3) 506.54 668.33 T
+98.1 660.6 512.1 660.6 2 L
+0.25 H
+0 Z
+N
+98.1 135 512.1 639 R
+7 X
+V
+3 12 Q
+0 X
+(\245) 152.1 632.33 T
+3 10 Q
+-0.06 (Y) 162.9 632.33 P
+-0.06 (ou give the name of a class, such as) 169.12 632.33 P
+5 F
+-0.15 (Button) 313.45 632.33 P
+3 F
+-0.06 (, in which case the binding applies to all) 349.43 632.33 P
+(the windows of that class.) 162.9 620.33 T
+3 12 Q
+(\245) 152.1 605.33 T
+3 10 Q
+(Y) 162.9 605.33 T
+(ou specify) 169.12 605.33 T
+5 F
+(all) 212.97 605.33 T
+3 F
+(, in which case the binding applies to all windows.) 230.96 605.33 T
+-0.3 (In Tk4.0 you specify the window\050s\051 using a more general mechanism called a) 170.1 590.33 P
+2 F
+-0.3 (binding) 479.35 590.33 P
+(tag) 152.1 578.33 T
+3 F
+(. A binding tag may be an arbitrary string, but if it starts with a \322.\323 then it must be the) 164.87 578.33 T
+(name of a window) 152.1 566.33 T
+(. If you specify a class name or) 225.56 566.33 T
+5 F
+(all) 352.4 566.33 T
+3 F
+( as a binding tag, it will usually) 370.39 566.33 T
+-0.1 (have the same ef) 152.1 554.33 P
+-0.1 (fect as in Tk 3.6, but you may also specify other strings that were not per-) 218.51 554.33 P
+(mitted in Tk 3.6.) 152.1 542.33 T
+-0.07 (Each window in Tk 4.0 has a list of binding tags. When an event occurs in a window) 170.1 530.33 P
+-0.07 (,) 507.17 530.33 P
+-0.19 (Tk fetches the window\325) 152.1 518.33 P
+-0.19 (s binding tags and matches the event against all of the bindings for) 245.62 518.33 P
+-0.09 (any of the tags. By default, the binding tags for a window consist of the window name, its) 152.1 506.33 P
+-0.14 (class name, the name of its nearest toplevel ancestor) 152.1 494.33 P
+-0.14 (, and) 359.61 494.33 P
+5 F
+-0.33 (all) 381.26 494.33 P
+3 F
+-0.14 (. For example, a button win-) 399.25 494.33 P
+(dow named) 152.1 482.33 T
+5 F
+(.b) 200.95 482.33 T
+3 F
+( will have the tags) 212.95 482.33 T
+5 9 Q
+(.b Button . all) 179.1 468 T
+3 10 Q
+(by default and all of the following bindings will apply to the window:) 152.1 454.33 T
+5 9 Q
+(bind .b <Enter> {identify "press here to exit"}) 179.1 440 T
+(bind Button <Button-Release-1> {%W invoke}) 179.1 430 T
+(bind all <Help> {help %W}) 179.1 420 T
+3 10 Q
+(So far) 152.1 406.33 T
+(, this mechanism produces the same behavior as in Tk 3.6 except that bindings cre-) 175.85 406.33 T
+(ated for a toplevel also apply to its descendants \050see Section 1.5 for more on this issue\051.) 152.1 394.33 T
+(Y) 170.1 382.33 T
+(ou can use the) 176.32 382.33 T
+5 F
+(bindtags) 235.71 382.33 T
+3 F
+( command to change the binding tags for a window or) 283.69 382.33 T
+(their order) 152.1 370.33 T
+(. For example, the command) 193.46 370.33 T
+5 9 Q
+(bindtags .b {.b MyButton all}) 179.1 356 T
+3 10 Q
+(will change the binding tags for) 152.1 342.33 T
+5 F
+(.b) 281.46 342.33 T
+3 F
+( to the three values in the list. This provides a simple) 293.45 342.33 T
+(way to make radical changes the behavior of a window) 152.1 330.33 T
+(. After the above command is) 371.55 330.33 T
+(invoked none of the) 152.1 318.33 T
+5 F
+(Button) 234.26 318.33 T
+3 F
+( class bindings will apply to) 270.24 318.33 T
+5 F
+(.b) 384.63 318.33 T
+3 F
+(. Instead, bindings for) 396.63 318.33 T
+5 F
+-0.81 (MyButton) 152.1 306.33 P
+3 F
+-0.34 ( will apply; this might give the button a totally dif) 200.07 306.33 P
+-0.34 (ferent set of behaviors than a) 395.88 306.33 P
+(normal button. In addition, the) 152.1 294.33 T
+5 F
+(bindtags) 276.75 294.33 T
+3 F
+( command removes the \322.\323 tag, so bindings on) 324.72 294.33 T
+(\322.\323 will not apply to) 152.1 282.33 T
+5 F
+(.b) 234.27 282.33 T
+3 F
+(.) 246.27 282.33 T
+(Y) 170.1 270.33 T
+(ou can also place additional tags on a window with the) 176.32 270.33 T
+5 F
+(bindtags) 397.55 270.33 T
+3 F
+( command to) 445.53 270.33 T
+(combine a number of behaviors. For example,) 152.1 258.33 T
+5 9 Q
+(bindtags .b {.b MyButton Button . all}) 179.1 244 T
+3 10 Q
+(gives) 152.1 230.33 T
+5 F
+(.b) 175.7 230.33 T
+3 F
+( the behaviors of) 187.69 230.33 T
+5 F
+(MyButton) 257.08 230.33 T
+3 F
+( bindings as well as those speci\336ed by) 305.06 230.33 T
+5 F
+(Button) 459.96 230.33 T
+3 F
+(bindings.) 152.1 218.33 T
+(Overall, binding tags are similar to the tag mechanisms already used internally by) 170.1 206.33 T
+(canvas and text widgets in Tk 3.6, except that binding tags apply to windows instead of) 152.1 194.33 T
+(graphical objects or textual characters.) 152.1 182.33 T
+FMENDPAGE
+%%EndPage: "3" 4
+%%Page: "4" 4
+612 792 0 FMBEGINPAGE
+0 10 Q
+0 X
+0 K
+(4) 98.1 668.33 T
+4 F
+(Tk4.0 Overview and Porting Guide) 359.34 668.33 T
+98.1 660.6 512.1 660.6 2 L
+0.25 H
+0 Z
+N
+98.1 135 512.1 639 R
+7 X
+V
+0 F
+0 X
+(1.2) 127.41 632.33 T
+(Con\337ict resolution) 152.1 632.33 T
+3 F
+(It is possible for several bindings to match a particular event. In Tk 3.6 at most one event) 152.1 616.33 T
+(is actually allowed to trigger: a set of con\337ict resolution rules determines the winner) 152.1 604.22 T
+(. In) 488.27 604.22 T
+(general, a more speci\336c binding takes precedence over a less speci\336c binding. For exam-) 152.1 592.11 T
+-0.27 (ple, any binding for a speci\336c widget takes precedence over any class or) 152.1 580 P
+5 F
+-0.66 (all) 439.96 580 P
+3 F
+-0.27 ( binding, and) 457.95 580 P
+(a binding on) 152.1 567.89 T
+5 F
+(<Control-a>) 204.57 567.89 T
+3 F
+( takes precedence over a binding on) 270.54 567.89 T
+5 F
+(<KeyPress>.) 416.24 567.89 T
+3 F
+-0.26 (The mechanism for con\337ict resolution is similar in Tk 4.0 except that one binding can) 170.1 555.89 P
+-0.35 (trigger for) 152.1 543.78 P
+2 F
+-0.35 (each) 194.7 543.78 P
+3 F
+-0.35 ( binding tag on the window where the event occurs. The bindings trigger in) 213.57 543.78 P
+(the order of the tags. Thus if button) 152.1 531.67 T
+5 F
+(.b) 296.17 531.67 T
+3 F
+( has the default binding tags, one binding for) 308.16 531.67 T
+5 F
+(.b) 489.71 531.67 T
+3 F
+(can trigger) 152.1 519.56 T
+(, followed by one for) 194.72 519.56 T
+5 F
+(Button) 281.32 519.56 T
+3 F
+(, followed by one for \322) 317.3 519.56 T
+5 F
+(.) 408.34 519.56 T
+3 F
+(\323, followed by one for) 414.34 519.56 T
+5 F
+(all) 152.1 507.44 T
+3 F
+(. If there are no matching bindings for a given tag then none will trigger) 170.09 507.44 T
+(, and if there) 456.98 507.44 T
+(are several matching bindings for a given tag then a single one is chosen using the same) 152.1 495.33 T
+(rules as in Tk 3.6.) 152.1 483.22 T
+(The philosophy behind binding tags in Tk 4.0 is that each binding tag corresponds to) 170.1 471.22 T
+(an independent behavior) 152.1 459.11 T
+(, so bindings with dif) 249.96 459.11 T
+(ferent tags should usually be additive. Sup-) 334.46 459.11 T
+(pose you de\336ned the following binding:) 152.1 447 T
+5 9 Q
+(bind .b <Enter> {puts "press here to exit"}) 179.1 432.67 T
+3 10 Q
+(This binding will add to the behavior de\336ned by the Button class binding for) 152.1 419 T
+5 F
+(<Enter>) 460.81 419 T
+3 F
+(.) 502.79 419 T
+(In Tk 3.6, the widget-speci\336c binding will replace the class binding, which will break the) 152.1 406.89 T
+(behavior of the button so that it no longer has normal button behavior) 152.1 394.78 T
+(.) 429.71 394.78 T
+(Sometimes there need to be interactions between binding tags. For example, you) 170.1 382.78 T
+(might wish to keep most of the default button behavior for) 152.1 370.67 T
+5 F
+(.b) 388.34 370.67 T
+3 F
+( but replace the default) 400.33 370.67 T
+(behavior for) 152.1 358.56 T
+5 F
+(<ButtonRelease>) 203.72 358.56 T
+3 F
+( with some other behavior) 293.67 358.56 T
+(. T) 397.49 358.56 T
+(o allow bindings to be) 407.9 358.56 T
+-0.17 (overridden, Tk 4.0 allows the) 152.1 346.44 P
+5 F
+-0.41 (break) 271.44 346.44 P
+3 F
+-0.17 ( command to be invoked from inside a binding. This) 301.43 346.44 P
+(causes all remaining binding tags for that binding to be skipped. Consider the following) 152.1 334.33 T
+(binding:) 152.1 322.22 T
+5 9 Q
+(bind .b <ButtonRelease-1> {myRelease .b; break}) 179.1 307.89 T
+3 10 Q
+-0.21 (This will cause the) 152.1 294.22 P
+5 F
+-0.5 (myRelease) 228.99 294.22 P
+3 F
+-0.21 ( procedure to be invoked, then the) 282.96 294.22 P
+5 F
+-0.5 (break) 420.28 294.22 P
+3 F
+-0.21 ( command will) 450.26 294.22 P
+-0.37 (cause the class binding for the event to be skipped \050assuming that the widget name appears) 152.1 282.11 P
+(before its class in the binding tags for) 152.1 270 T
+5 F
+(.b) 304.78 270 T
+3 F
+(\051, along with any bindings for other tags.) 316.77 270 T
+2 F
+(Note:) 119.09 254 T
+-0.07 (Y) 152.1 254 P
+-0.07 (ou cannot invoke) 156.74 254 P
+6 F
+-0.17 (break) 227.31 254 P
+2 F
+-0.07 ( fr) 257.29 254 P
+-0.07 (om within the) 266.02 254 P
+6 F
+-0.17 (myRelease) 322.73 254 P
+2 F
+-0.07 ( pr) 376.7 254 P
+-0.07 (ocedur) 387.64 254 P
+-0.07 (e in the above example:) 415.03 254 P
+-0.02 (this will generate a T) 152.1 242.89 P
+-0.02 (cl err) 236.05 242.89 P
+-0.02 (or) 257.59 242.89 P
+-0.02 (. However) 265.37 242.89 P
+-0.02 (, you can invoke the command \322) 305.31 242.89 P
+6 F
+-0.05 (return -code) 434.25 242.89 P
+(break) 152.1 231.78 T
+2 F
+(\323 in the pr) 182.08 231.78 T
+(ocedur) 223.64 231.78 T
+(e to achieve the same effect as the) 251.03 231.78 T
+6 F
+(break) 389.25 231.78 T
+2 F
+( in the binding script.) 419.23 231.78 T
+0 F
+(1.3) 127.41 202.78 T
+(Implicit Any) 152.1 202.78 T
+3 F
+-0.13 (In Tk 3.6 extraneous modi\336ers prevent a binding from matching an event. For example, if) 152.1 186.78 P
+(a binding is de\336ned for) 152.1 174.67 T
+5 F
+(<Button-1>) 247.32 174.67 T
+3 F
+( and the mouse button is pressed with the) 307.29 174.67 T
+5 F
+(Num-) 474.68 174.67 T
+(Lock) 152.1 162.56 T
+3 F
+( key down, then the binding will not match. If you want a binding to trigger even) 176.09 162.56 T
+(when extraneous modi\336ers are present, you must specify the) 152.1 150.45 T
+5 F
+(Any) 396.37 150.45 T
+3 F
+( modi\336er) 414.36 150.45 T
+(, as in) 450.33 150.45 T
+5 F
+(<Any-) 476.42 150.45 T
+(Button-1>) 152.1 138.33 T
+3 F
+(.) 206.07 138.33 T
+FMENDPAGE
+%%EndPage: "4" 5
+%%Page: "5" 5
+612 792 0 FMBEGINPAGE
+4 10 Q
+0 X
+0 K
+(1 Bindings) 98.1 668.33 T
+0 F
+(5) 506.54 668.33 T
+98.1 660.6 512.1 660.6 2 L
+0.25 H
+0 Z
+N
+98.1 135 512.1 639 R
+7 X
+V
+3 F
+0 X
+-0.06 (In Tk 4.0, all bindings have the) 170.1 632.33 P
+5 F
+-0.15 (Any) 297.08 632.33 P
+3 F
+-0.06 ( modi\336er present implicitly) 315.08 632.33 P
+-0.06 (. The) 423.35 632.33 P
+5 F
+-0.15 (Any) 446.26 632.33 P
+3 F
+-0.06 ( modi\336er is) 464.25 632.33 P
+(still allowed for compatibility) 152.1 620.33 T
+(, but it has no meaning. Thus a binding for) 270.55 620.33 T
+5 F
+(<Button-1>) 443.23 620.33 T
+3 F
+(will match a button press event even if) 152.1 608.33 T
+5 F
+(NumLock) 309.21 608.33 T
+3 F
+(,) 351.19 608.33 T
+5 F
+(Shift) 356.19 608.33 T
+3 F
+(,) 386.17 608.33 T
+5 F
+(Control) 391.17 608.33 T
+3 F
+(, or any combina-) 433.15 608.33 T
+(tion of them. If you wish for a binding not to trigger when a modi\336er is present, you can) 152.1 596.33 T
+(just de\336ne an empty binding for that modi\336er combination. For example,) 152.1 584.33 T
+5 9 Q
+(bind .b <Control-ButtonPress-1> {# this script is a no-op}) 179.1 570 T
+3 10 Q
+(creates a binding that will trigger on mouse button presses when the) 152.1 556.33 T
+5 F
+(Control) 426.36 556.33 T
+3 F
+( key is) 468.34 556.33 T
+-0.22 (down. If there is also a) 152.1 544.33 P
+5 F
+-0.52 (<ButtonPress-1>) 244.35 544.33 P
+3 F
+-0.22 ( binding for) 334.3 544.33 P
+5 F
+-0.52 (.b) 383.35 544.33 P
+3 F
+-0.22 (, it will no longer be invoked) 395.34 544.33 P
+-0.02 (if the) 152.1 532.33 P
+5 F
+-0.05 (Control) 175.37 532.33 P
+3 F
+-0.02 ( key is down, due to the con\337ict resolution rules. The script for the above) 217.35 532.33 P
+(binding is just a T) 152.1 520.33 T
+(cl comment, so it has no ef) 223.59 520.33 T
+(fect when it is invoked. Alternatively) 330.84 520.33 T
+(, you) 478.98 520.33 T
+(could use) 152.1 508.33 T
+5 F
+(%s) 192.63 508.33 T
+3 F
+( in the binding script to extract the modi\336er state, then test to see that only) 204.62 508.33 T
+(desired modi\336ers are present.) 152.1 496.33 T
+0 F
+(1.4) 127.41 466.33 T
+(Porting problems: widget bindings vs. class bindings) 152.1 466.33 T
+3 F
+-0.38 (Y) 152.1 450.33 P
+-0.38 (ou are likely to encounter two problems with bindings when you port Tk 3.6 scripts to Tk) 158.32 450.33 P
+-0.18 (4.0: widget bindings vs. class bindings, and events on top-level windows. This section dis-) 152.1 438.33 P
+(cusses the \336rst problem and the following section discusses the second problem.) 152.1 426.33 T
+(In Tk 3.6, if a widget-speci\336c binding matches an event then no class binding will) 170.1 414.33 T
+-0.15 (trigger for the event; in Tk 4.0 both bindings will trigger) 152.1 402.33 P
+-0.15 (. Because of this change, you will) 375.75 402.33 P
+-0.09 (need to modify most of your widget-speci\336c bindings in one of two ways. If a widget-spe-) 152.1 390.33 P
+(ci\336c binding in Tk 3.6 was intended to supplement the class binding, this could only be) 152.1 378.33 T
+(done by duplicating the code of the class binding in the widget binding script. This dupli-) 152.1 366.33 T
+-0.02 (cated code is no longer necessary in Tk 4.0 and will probably interfere with the new class) 152.1 354.33 P
+(bindings in Tk 4.0; you should remove the duplicated class code, leaving only the widget-) 152.1 342.33 T
+(speci\336c code in the binding script. If a widget-speci\336c binding in Tk 3.6 was intended to) 152.1 330.33 T
+-0.17 (override the class binding, this will no longer occur by default in Tk 4.0; you should add a) 152.1 318.33 P
+5 F
+-0.54 (break) 152.1 306.33 P
+3 F
+-0.22 ( command at the end of the binding script to prevent the class binding from trigger-) 182.08 306.33 P
+(ing. If a widget binding in Tk 3.6 didn\325) 152.1 294.33 T
+(t con\337ict with a class binding, then you will not) 308.49 294.33 T
+(need to modify it for Tk 4.0. For example, a widget binding for) 152.1 282.33 T
+5 F
+(<Help>) 407.49 282.33 T
+3 F
+( in a text widget) 443.47 282.33 T
+(would not need to be modi\336ed, since it doesn\325) 152.1 270.33 T
+(t con\337ict with a class binding.) 336.53 270.33 T
+0 F
+(1.5) 127.41 240.33 T
+(Porting problems: events on top-levels) 152.1 240.33 T
+3 F
+-0.26 (The second binding problem you are likely to encounter in porting Tk 3.6 scripts to Tk 4.0) 152.1 224.33 P
+(is that in Tk 4.0 a binding on a toplevel will match events on any of the internal windows) 152.1 212.33 T
+(within that top-level. For example, suppose you have a binding created as follows:) 152.1 200.33 T
+5 9 Q
+(toplevel .t) 179.1 186 T
+(button .t.b1 ...) 179.1 176 T
+(button .t.b2 ...) 179.1 166 T
+(bind .t <Enter> action) 179.1 156 T
+FMENDPAGE
+%%EndPage: "5" 6
+%%Page: "6" 6
+612 792 0 FMBEGINPAGE
+0 10 Q
+0 X
+0 K
+(6) 98.1 668.33 T
+4 F
+(Tk4.0 Overview and Porting Guide) 359.34 668.33 T
+98.1 660.6 512.1 660.6 2 L
+0.25 H
+0 Z
+N
+98.1 135 512.1 639 R
+7 X
+V
+3 F
+0 X
+-0.27 (This binding will trigger not only when the mouse enters) 152.1 632.33 P
+5 F
+-0.64 (.t) 379.29 632.33 P
+3 F
+-0.27 (, but also when it enters either) 391.28 632.33 P
+5 F
+(.t.b1) 152.1 620.33 T
+3 F
+( or) 182.08 620.33 T
+5 F
+(.t.b2) 195.41 620.33 T
+3 F
+(. This is because the binding tags for a window include its nearest) 225.39 620.33 T
+(ancestor toplevel by default. The toplevel is present in the binding tags to make it easy to) 152.1 608.33 T
+(set up accelerator keys that apply in all the windows of a panel. For example,) 152.1 596.33 T
+5 9 Q
+(bind .t <Control-a> {controlAProc %W}) 179.1 582 T
+3 10 Q
+(will cause) 152.1 568.33 T
+5 F
+(controlAProc) 194.85 568.33 T
+3 F
+( to be invoked whenever) 266.81 568.33 T
+5 F
+(Control-a) 367.56 568.33 T
+3 F
+( is typed in any of the) 421.53 568.33 T
+-0.12 (windows in) 152.1 556.33 P
+5 F
+-0.29 (.t) 200.72 556.33 P
+3 F
+-0.12 (. The procedure will receive the name of the focus window as its ar) 212.71 556.33 P
+-0.12 (gument.) 479.62 556.33 P
+(Unfortunately) 170.1 544.33 T
+(, if you have created bindings on toplevel windows in your Tk 3.6) 225.52 544.33 T
+-0.16 (scripts, they probably expect to trigger only for events in the toplevel, so the bindings will) 152.1 532.33 P
+(misbehave under Tk 4.0. Fortunately you can reproduce the behavior of Tk 3.6 by using) 152.1 520.33 T
+(the) 152.1 508.33 T
+5 F
+(%W) 166.81 508.33 T
+3 F
+( substitution in the binding script. For example, to ensure that) 178.8 508.33 T
+5 F
+(action) 427.28 508.33 T
+3 F
+( is invoked) 463.26 508.33 T
+(only for) 152.1 496.33 T
+5 F
+(Enter) 186.52 496.33 T
+3 F
+( events in a toplevel window itself, create the following binding in place) 216.51 496.33 T
+(of the one above:) 152.1 484.33 T
+5 9 Q
+(bind .t <Enter> {) 179.1 470 T
+(if {"%W" == ".t"} {) 200.63 460 T
+(action) 222.23 450 T
+(}) 200.63 440 T
+(}) 179.1 430 T
+3 10 Q
+-0.01 (When an) 152.1 416.33 P
+5 F
+-0.03 (Enter) 190.38 416.33 P
+3 F
+-0.01 ( event occurs in a descendant of) 220.36 416.33 P
+5 F
+-0.03 (.t) 350.45 416.33 P
+3 F
+-0.01 ( such as) 362.45 416.33 P
+5 F
+-0.03 (.t.x) 396.56 416.33 P
+3 F
+-0.01 (, a binding for) 420.54 416.33 P
+5 F
+-0.03 (Enter) 479.63 416.33 P
+3 F
+(in) 152.1 404.33 T
+5 F
+(.t.x) 162.37 404.33 T
+3 F
+( will trigger \336rst, if there is one. Then the above binding will trigger) 186.36 404.33 T
+(. Since) 457.58 404.33 T
+5 F
+(%W) 487.29 404.33 T
+3 F
+(will be substituted with) 152.1 392.33 T
+5 F
+(.t.x) 248.17 392.33 T
+3 F
+(, the) 272.15 392.33 T
+5 F
+(if) 291.86 392.33 T
+3 F
+( condition will not be satis\336ed and the binding will) 303.86 392.33 T
+(not do anything.) 152.1 380.33 T
+-0.14 ( An alternative solution is to remove the toplevel window from the binding tags of all) 170.1 368.33 P
+-0.12 (its internal windows. However) 152.1 356.33 P
+-0.12 (, this means that you won\325) 274.03 356.33 P
+-0.12 (t be able to take advantage of the) 378.73 356.33 P
+(tag to create key bindings that apply everywhere within the toplevel.) 152.1 344.33 T
+0 F
+(1.6) 127.41 314.33 T
+(Internal bindings in canvases and texts) 152.1 314.33 T
+3 F
+(The same changes in con\337ict resolution described in Section 1.2 also apply to bindings) 152.1 298.33 T
+-0.05 (created internally for the items of a canvas or the tags of a text widget. If a canvas item or) 152.1 286.33 P
+-0.29 (character of text has multiple tags, then one binding can trigger for each tag on each event.) 152.1 274.33 P
+-0.32 (The bindings trigger in the priority order of the tags. Similar porting problems are likely to) 152.1 262.33 P
+-0.19 (occur as described in Section 1.4; if a binding for one tag needs to override that of another) 152.1 250.33 P
+(tag, you\325ll need to add a) 152.1 238.33 T
+5 F
+(break) 251.2 238.33 T
+3 F
+( command under Tk 4.0; if a binding for one tag dupli-) 281.18 238.33 T
+-0.28 (cated the code from another tag\325) 152.1 226.33 P
+-0.28 (s binding, so that they will compose in Tk 3.6, you\325ll have) 279.76 226.33 P
+(to remove the duplicated code in Tk 4.0.) 152.1 214.33 T
+FMENDPAGE
+%%EndPage: "6" 7
+%%Page: "7" 7
+612 792 0 FMBEGINPAGE
+4 10 Q
+0 X
+0 K
+(2 Focus management) 98.1 668.33 T
+0 F
+(7) 506.54 668.33 T
+98.1 660.6 512.1 660.6 2 L
+0.25 H
+0 Z
+N
+98.1 135 512.1 639 R
+7 X
+V
+98.1 623.98 512.1 627 C
+152.1 625.2 512.1 625.2 2 L
+0.5 H
+2 Z
+0 X
+0 K
+N
+98.1 625.49 143.1 625.49 2 L
+0 Z
+N
+40.5 63 571.5 729 C
+0 12 Q
+0 X
+0 K
+(2) 134.63 631 T
+(Focus management) 152.1 631 T
+3 10 Q
+(The input focus is another area where Tk 4.0 contains major changes. Fortunately) 152.1 607.31 T
+(, the) 477.87 607.31 T
+-0.09 (focus changes should not require as many modi\336cations to your Tk 3.6 scripts as the bind-) 152.1 595.31 P
+(ing changes.) 152.1 583.31 T
+0 F
+(2.1) 127.41 553.31 T
+(One focus window per toplevel) 152.1 553.31 T
+3 F
+(Tk 3.6 only keeps track of a single focus window for each application, and this results in) 152.1 537.31 T
+(two problems. First, it doesn\325) 152.1 525.31 T
+(t allow an application to use multiple displays since this) 269.64 525.31 T
+-0.16 (could result in multiple simultaneous focus windows, one on each display) 152.1 513.31 P
+-0.16 (. Second, the Tk) 444.99 513.31 P
+(3.6 model doesn\325) 152.1 501.31 T
+(t work very well for applications that have multiple toplevels: when the) 221.04 501.31 T
+(mouse moves from one toplevel to another) 152.1 489.31 T
+(, the focus window should switch to whatever) 322.7 489.31 T
+-0.24 (window had the focus the last time the mouse was in the new toplevel, but Tk 3.6 does not) 152.1 477.31 P
+(remember this information.) 152.1 465.31 T
+(Tk 4.0 corrects both of these problems. It remembers one focus window for each) 170.1 453.31 T
+(toplevel, which can be queried with the) 152.1 441.31 T
+5 F
+(focus -lastfor) 311.98 441.31 T
+3 F
+( command. When the win-) 395.94 441.31 T
+(dow manager gives the focus to a toplevel window \050because the mouse entered the win-) 152.1 429.31 T
+(dow or because you clicked on the window) 152.1 417.31 T
+(, depending on the focus model being used by) 324.38 417.31 T
+(the window manager\051, Tk passes the focus on to the remembered window) 152.1 405.31 T
+(. Several win-) 446.23 405.31 T
+(dows in an application can have the focus at the same time, one on each display the appli-) 152.1 393.31 T
+(cation is using. When asking for the current focus window in the) 152.1 381.31 T
+5 F
+(focus) 413.31 381.31 T
+3 F
+( command, you) 443.29 381.31 T
+(can use the) 152.1 369.31 T
+5 F
+(-displayof) 199 369.31 T
+3 F
+( switch to specify a particular display) 258.97 369.31 T
+(.) 407.66 369.31 T
+(When you set the focus to a window with the) 170.1 357.31 T
+5 F
+(focus) 353.31 357.31 T
+3 F
+( command, Tk remembers that) 383.29 357.31 T
+(window as the most recent focus window for its toplevel. In addition, if the application) 152.1 345.31 T
+(currently has the focus for the window\325) 152.1 333.31 T
+(s display) 309.2 333.31 T
+(, Tk moves the focus to the speci\336ed win-) 343.82 333.31 T
+-0.35 (dow; this can be used, for example to move the focus to a dialog when the dialog is posted,) 152.1 321.31 P
+(or to perform keyboard traversal among the toplevels of an application. If the application) 152.1 309.31 T
+(doesn\325) 152.1 297.31 T
+(t currently have the focus for the display) 178.57 297.31 T
+(, then Tk will not normally take the focus) 339.74 297.31 T
+(from its current owner) 152.1 285.31 T
+(. However) 241.2 285.31 T
+(, you can specify the) 282.43 285.31 T
+5 F
+(-force) 367.36 285.31 T
+3 F
+( ar) 403.34 285.31 T
+(gument to) 413.43 285.31 T
+5 F
+(focus) 456.18 285.31 T
+3 F
+( to) 486.17 285.31 T
+(insist that Tk grab the focus for this application \050in general this is probably not a good) 152.1 273.31 T
+(idea, since it may clash with the window manager) 152.1 261.31 T
+(\325) 352.05 261.31 T
+(s focus policy\051.) 354.83 261.31 T
+0 F
+(2.2) 127.41 231.31 T
+(Keyboard traversal) 152.1 231.31 T
+3 F
+-0.38 (Tk 4.0 has a much more complete implementation of keyboard traversal than Tk 3.6. In Tk) 152.1 215.31 P
+(3.6 there is built-in support only for keyboard traversal of menus. In Tk 4.0 keyboard tra-) 152.1 203.31 T
+(versal is implemented for all widgets. Y) 152.1 191.31 T
+(ou can type) 311.27 191.31 T
+5 F
+(Tab) 359.85 191.31 T
+3 F
+( to move the focus among the) 377.84 191.31 T
+-0.4 (windows within a toplevel and) 152.1 179.31 P
+5 F
+-0.95 (Shift+Tab) 275.31 179.31 P
+3 F
+-0.4 ( to move in the reverse direction. The order of) 329.28 179.31 P
+-0.11 (traversal is de\336ned by the stacking order of widgets, with the lowest widget \336rst in the tra-) 152.1 167.31 P
+(versal order) 152.1 155.31 T
+(. All Tk widgets now provide a) 199 155.31 T
+5 F
+(-takefocus) 326.14 155.31 T
+3 F
+( option, which determines) 386.11 155.31 T
+FMENDPAGE
+%%EndPage: "7" 8
+%%Page: "8" 8
+612 792 0 FMBEGINPAGE
+0 10 Q
+0 X
+0 K
+(8) 98.1 668.33 T
+4 F
+(Tk4.0 Overview and Porting Guide) 359.34 668.33 T
+98.1 660.6 512.1 660.6 2 L
+0.25 H
+0 Z
+N
+98.1 135 512.1 639 R
+7 X
+V
+3 F
+0 X
+(whether the window should accept the focus during traversal or be skipped. This option) 152.1 632.33 T
+(has several features; see the) 152.1 620.33 T
+5 F
+(options.n) 265.61 620.33 T
+3 F
+( manual entry for details.) 319.58 620.33 T
+(All of the Tk widgets provide a traversal highlight ring as required by Motif. The) 170.1 608.33 T
+(highlight ring turns dark when the widget has the input focus. Its size and colors are con-) 152.1 596.33 T
+(trolled by the) 152.1 584.33 T
+5 F
+(-highlightthickness) 207.9 584.33 T
+3 F
+(,) 321.84 584.33 T
+5 F
+(-highlightbackground) 326.83 584.33 T
+3 F
+(, and) 446.77 584.33 T
+5 F
+(-) 152.1 572.33 T
+(highlightcolor) 158.1 572.33 T
+3 F
+( options. Y) 242.05 572.33 T
+(ou may notice that widgets appear to have extra space) 285.2 572.33 T
+(around them in Tk 4.0; this is due to the traversal highlight ring, which is normally the) 152.1 560.33 T
+(same color as the background for widgets.) 152.1 548.33 T
+0 F
+(2.3) 127.41 518.33 T
+(Support for focus-follows-mouse) 152.1 518.33 T
+3 F
+(Both Tk 3.6 and Tk 4.0 use an) 152.1 502.33 T
+2 F
+(explicit focus model) 275.91 502.33 T
+3 F
+( within a toplevel. This means that) 355.86 502.33 T
+(moving the mouse among the windows of a toplevel does not normally move the focus;) 152.1 490.33 T
+-0.06 (you have to click or perform some other action \050such as pressing) 152.1 478.33 P
+5 F
+-0.15 (Tab) 412.26 478.33 P
+3 F
+-0.06 (\051 to move the focus.) 430.25 478.33 P
+(Tk 3.6 has no support for an) 152.1 466.33 T
+2 F
+(implicit focus model) 267.58 466.33 T
+3 F
+( where the window under the mouse) 348.64 466.33 T
+(always has the focus. In Tk 4.0 you can invoke the library procedure) 152.1 454.33 T
+5 F
+(tk_focusFol-) 428.83 454.33 T
+(lowsMouse) 152.1 442.33 T
+3 F
+( to switch to an implicit focus model; in this mode whenever the mouse) 206.07 442.33 T
+(enters a new window the focus will switch to that window) 152.1 430.33 T
+(.) 384.07 430.33 T
+0 F
+(2.4) 127.41 400.33 T
+(No default focus window) 152.1 400.33 T
+(, no \322none\323 focus.) 269.45 400.33 T
+3 F
+-0.16 (Tk 3.6 has the notion of a default focus window) 152.1 384.33 P
+-0.16 (, which receives the focus if the focus win-) 341.56 384.33 P
+(dow is deleted. It is also possible for an application to abandon the input focus by setting) 152.1 372.33 T
+(the focus to) 152.1 360.33 T
+5 F
+(none) 201.23 360.33 T
+3 F
+(. In Tk 4.0 both of these features have been eliminated. There is no) 225.22 360.33 T
+(default focus window) 152.1 348.33 T
+(, and the focus can never be explicitly abandoned. If the focus win-) 238.05 348.33 T
+(dow is destroyed, Tk resets the input focus to the toplevel containing the old focus win-) 152.1 336.33 T
+(dow) 152.1 324.33 T
+(. If the toplevel is destroyed, the window manager will reclaim the focus and move it) 168.66 324.33 T
+(elsewhere.) 152.1 312.33 T
+-0.18 (If you really want to abandon the focus in Tk 4.0 so that keyboard events are ignored,) 170.1 300.33 P
+(you can create a dummy window with no key bindings \050set its binding tags to an empty) 152.1 288.33 T
+(string to be sure\051, make sure that is never mapped, and give it the input focus.) 152.1 276.33 T
+0 F
+(2.5) 127.41 246.33 T
+(Better focus events) 152.1 246.33 T
+3 F
+-0.13 (Tk 3.6 has a quirky event model for) 152.1 230.33 P
+5 F
+-0.32 (FocusIn) 296.77 230.33 P
+3 F
+-0.13 ( and) 338.75 230.33 P
+5 F
+-0.32 (FocusOut) 357.92 230.33 P
+3 F
+-0.13 ( events: when the window) 405.89 230.33 P
+-0.23 (manager gives the focus to a toplevel, Tk generates a) 152.1 218.33 P
+5 F
+-0.55 (FocusIn) 364.36 218.33 P
+3 F
+-0.23 ( event for the toplevel and) 406.33 218.33 P
+(another) 152.1 206.33 T
+5 F
+(FocusIn) 184.57 206.33 T
+3 F
+( event for the focus window) 226.55 206.33 T
+(, but no events for any other windows.) 337.76 206.33 T
+(When the window manager moves the focus somewhere else,) 152.1 194.33 T
+5 F
+(FocusOut) 400.79 194.33 T
+3 F
+( events are gen-) 448.77 194.33 T
+-0 (erated for these same two windows. In Tk 4.0,) 152.1 182.33 P
+5 F
+-0 (FocusIn) 339.73 182.33 P
+3 F
+-0 ( and) 381.71 182.33 P
+5 F
+-0 (FocusOut) 401.13 182.33 P
+3 F
+-0 ( events are gen-) 449.11 182.33 P
+-0.26 (erated in the same way as) 152.1 170.33 P
+5 F
+-0.63 (Enter) 255.43 170.33 P
+3 F
+-0.26 ( and) 285.41 170.33 P
+5 F
+-0.63 (Leave) 304.31 170.33 P
+3 F
+-0.26 ( events: when the focus arrives, a) 334.29 170.33 P
+5 F
+-0.63 (FocusIn) 467.89 170.33 P
+3 F
+-0.05 (event is generated for each window from the toplevel down to the focus window) 152.1 158.33 P
+-0.05 (, with dif-) 472.5 158.33 P
+FMENDPAGE
+%%EndPage: "8" 9
+%%Page: "9" 9
+612 792 0 FMBEGINPAGE
+4 10 Q
+0 X
+0 K
+(3 T) 98.1 668.33 T
+(ext widgets) 111.43 668.33 T
+0 F
+(9) 506.54 668.33 T
+98.1 660.6 512.1 660.6 2 L
+0.25 H
+0 Z
+N
+98.1 135 512.1 639 R
+7 X
+V
+3 F
+0 X
+-0.33 (ferent detail \336elds for dif) 152.1 632.33 P
+-0.33 (ferent windows \050see Xlib documentation for information on these) 250.53 632.33 P
+(values\051. The reverse happens when the focus leaves a window) 152.1 620.33 T
+(.) 399.57 620.33 T
+0 F
+(2.6) 127.41 590.33 T
+(Porting issues) 152.1 590.33 T
+3 F
+(If you didn\325) 152.1 574.33 T
+(t have any special focus-related code in Tk 3.6, then you shouldn\325) 199.66 574.33 T
+(t need to) 462.9 574.33 T
+(make any changes for 4.0; things will just work better) 152.1 562.33 T
+(. If you wrote code in Tk 3.6 to get) 366.96 562.33 T
+(around the weaknesses with its focus mechanism, then you should remove most or all of) 152.1 550.33 T
+(that code. For example, if you implemented keyboard traversal yourself, or if you built) 152.1 538.33 T
+(your own mechanism to remember a separate focus window for each toplevel and give it) 152.1 526.33 T
+(the input focus whenever the toplevel gets the focus, you can simply remove this code,) 152.1 514.33 T
+-0.33 (since Tk 4.0 performs these functions for you. If you wrote code that depends on the weird) 152.1 502.33 P
+-0.03 (event model in Tk 3.6, that code will need to be rewritten for Tk 4.0. The Tk 4.0 model is) 152.1 490.33 P
+(general enough to duplicate any ef) 152.1 478.33 T
+(fects that were possible in Tk 3.6.) 289.86 478.33 T
+98.1 434.98 512.1 438 C
+152.1 436.2 512.1 436.2 2 L
+0.5 H
+2 Z
+0 X
+0 K
+N
+98.1 436.49 143.1 436.49 2 L
+0 Z
+N
+40.5 63 571.5 729 C
+0 12 Q
+0 X
+0 K
+(3) 134.63 442 T
+(T) 152.1 442 T
+(ext widgets) 158.54 442 T
+3 10 Q
+(T) 152.1 418.31 T
+(ext widgets have under) 157.51 418.31 T
+(gone a major overhaul for Tk 4.0 and they have improved in) 249.76 418.31 T
+(many ways. The changes to text widgets are almost entirely upward-compatible from Tk) 152.1 406.31 T
+(3.6.) 152.1 394.31 T
+0 F
+(3.1) 127.41 364.31 T
+(Embedded windows.) 152.1 364.31 T
+3 F
+(Tk 3.6 supported two kinds of annotations in texts: marks and tags. In Tk 4.0 a third kind) 152.1 348.31 T
+-0.04 (of annotation is available: an embedded window) 152.1 336.31 P
+-0.04 (. This allows you to embed other widgets) 344.99 336.31 P
+(inside a text widget, mixed in with the text. The text widget acts as a geometry manager) 152.1 324.31 T
+(for these windows, laying them out and wrapping them just as if each embedded window) 152.1 312.31 T
+(were a single character in the text. Y) 152.1 300.31 T
+(ou can even have texts with nothing in them but) 297.64 300.31 T
+(embedded windows. The) 152.1 288.31 T
+5 F
+(window) 254.8 288.31 T
+3 F
+( widget command for text widgets provides several) 290.78 288.31 T
+(options to manage embedded windows.) 152.1 276.31 T
+0 F
+(3.2) 127.41 246.31 T
+(More options for tags.) 152.1 246.31 T
+3 F
+(In Tk 4.0 tags support many new options providing additional control over how informa-) 152.1 230.31 T
+(tion is displayed. Here is a summary of the new options:) 152.1 218.31 T
+3 12 Q
+(\245) 152.1 203.31 T
+3 10 Q
+(Y) 162.9 203.31 T
+(ou can now specify tab stops with the) 169.12 203.31 T
+5 F
+(-tabs) 321.79 203.31 T
+3 F
+( option. Each tab stop can use left, cen-) 351.78 203.31 T
+(ter) 162.9 191.31 T
+(, right, or numeric justi\336cation. T) 173.04 191.31 T
+(ab stops can also be speci\336ed for the widget as a) 305.6 191.31 T
+(whole.) 162.9 179.31 T
+3 12 Q
+(\245) 152.1 164.31 T
+3 10 Q
+(Y) 162.9 164.31 T
+(ou can specify justi\336cation \050left, center or right\051 with the) 169.12 164.31 T
+5 F
+(-justify) 398.12 164.31 T
+3 F
+( option.) 446.09 164.31 T
+FMENDPAGE
+%%EndPage: "9" 10
+%%Page: "10" 10
+612 792 0 FMBEGINPAGE
+0 10 Q
+0 X
+0 K
+(10) 98.1 668.33 T
+4 F
+(Tk4.0 Overview and Porting Guide) 359.34 668.33 T
+98.1 660.6 512.1 660.6 2 L
+0.25 H
+0 Z
+N
+98.1 135 512.1 639 R
+7 X
+V
+3 12 Q
+0 X
+(\245) 152.1 632.33 T
+3 10 Q
+(Y) 162.9 632.33 T
+(ou can now specify line spacing with three options,) 169.12 632.33 T
+5 F
+(-spacing1) 376.75 632.33 T
+3 F
+(,) 430.72 632.33 T
+5 F
+(-spacing2) 435.72 632.33 T
+3 F
+(, and) 489.69 632.33 T
+5 F
+(-) 162.9 620.2 T
+(spacing3) 168.9 620.2 T
+3 F
+(, which control the spacing above a line, between wrapped lines, and) 216.87 620.2 T
+(below a line.) 162.9 608.06 T
+3 12 Q
+(\245) 152.1 593.06 T
+3 10 Q
+(Y) 162.9 593.06 T
+(ou can now specify mar) 169.12 593.06 T
+(gins with the) 264.41 593.06 T
+5 F
+(-lmargin1) 318.55 593.06 T
+3 F
+(,) 372.52 593.06 T
+5 F
+(-lmargin2) 377.52 593.06 T
+3 F
+(, and) 431.49 593.06 T
+5 F
+(-rmargin) 453.42 593.06 T
+3 F
+(options.) 162.9 580.92 T
+3 12 Q
+(\245) 152.1 565.92 T
+3 10 Q
+-0.25 (Y) 162.9 565.92 P
+-0.25 (ou can now adjust the vertical position of text \050e.g. for superscripts or subscripts\051 with) 169.12 565.92 P
+(the) 162.9 553.79 T
+5 F
+(-offset) 177.61 553.79 T
+3 F
+( option.) 219.59 553.79 T
+3 12 Q
+(\245) 152.1 538.79 T
+3 10 Q
+-0.03 (Y) 162.9 538.79 P
+-0.03 (ou can now specify the wrapping style \050word wrapping, character wrapping, or none\051) 169.12 538.79 P
+(with the) 162.9 526.65 T
+5 F
+(-wrap) 197.88 526.65 T
+3 F
+( option.) 227.86 526.65 T
+3 12 Q
+(\245) 152.1 511.65 T
+3 10 Q
+(Y) 162.9 511.65 T
+(ou can now request overstriking with the) 169.12 511.65 T
+5 F
+(-overstrike) 334.83 511.65 T
+3 F
+( option.) 400.8 511.65 T
+0 F
+(3.3) 127.41 481.65 T
+(Bindings) 152.1 481.65 T
+3 F
+-0.19 (The default bindings for text widgets have been completely rewritten in Tk 4.0. They now) 152.1 465.65 P
+(support almost all of the Motif behavior \050everything except add mode and secondary) 152.1 453.52 T
+-0.36 (selections\051. They also include a substantial subset of the Emacs bindings for cursor motion) 152.1 441.38 P
+(and basic editing. The) 152.1 429.24 T
+5 F
+(tk_strictMotif) 242.87 429.24 T
+3 F
+( variable disables the Emacs bindings.) 326.82 429.24 T
+0 F
+(3.4) 127.41 399.24 T
+(Miscellaneous new features) 152.1 399.24 T
+3 F
+(In addition to the major changes described above, text widgets also include the following) 152.1 383.24 T
+(new features:) 152.1 371.11 T
+1 F
+(Horizontal scr) 162.9 356.11 T
+(olling) 224.07 356.11 T
+3 F
+(. T) 247.95 356.11 T
+(ext widgets can now be scrolled horizontally as well as verti-) 258.36 356.11 T
+(cally) 162.9 343.97 T
+(, using the) 181.68 343.97 T
+5 F
+(-) 225.55 343.97 T
+(xscrollcommand) 231.54 343.97 T
+3 F
+( option and the) 315.5 343.97 T
+5 F
+(xview) 377.68 343.97 T
+3 F
+( widget command.) 407.67 343.97 T
+1 F
+(Sear) 162.9 328.97 T
+(ching) 182.15 328.97 T
+3 F
+(. T) 205.48 328.97 T
+(ext widgets have a new) 215.88 328.97 T
+5 F
+(search) 311.64 328.97 T
+3 F
+( widget command, which provides ef) 347.62 328.97 T
+(\336-) 495.67 328.97 T
+-0.19 (cient searching of text widgets using either exact matching, glob-style matching, or reg-) 162.9 316.83 P
+(ular expressions. Y) 162.9 304.7 T
+(ou can search forwards or backwards.) 238.79 304.7 T
+1 F
+(Mark gravity) 162.9 289.7 T
+3 F
+(. In Tk 3.6 marks always had \322right gravity\323, which means they stick to) 219.71 289.7 T
+(the character on the right side of the mark; if you insert at the position of a mark, the) 162.9 277.56 T
+-0.1 (new character goes before the mark. In Tk 4.0 you can specify whether marks have left) 162.9 265.42 P
+(or right gravity) 162.9 253.29 T
+(.) 222.77 253.29 T
+1 F
+(Scr) 162.9 238.29 T
+(een information) 177.15 238.29 T
+3 F
+(. In Tk 4.0 there are two new widget commands for text widgets) 245.16 238.29 T
+(that return information about the screen layout. The) 162.9 226.15 T
+5 F
+(dlineinfo) 371.92 226.15 T
+3 F
+( widget command) 425.89 226.15 T
+(returns the bounding box of a display line \050all the information displayed on one line of) 162.9 214.02 T
+(the window) 162.9 201.88 T
+(, which may be either a whole line of text or a partial line if wrapping has) 209.16 201.88 T
+(occurred\051. The) 162.9 189.74 T
+5 F
+(bbox) 224.23 189.74 T
+3 F
+( widget command returns the screen area occupied by a single) 248.21 189.74 T
+(character) 162.9 177.61 T
+(.) 198.97 177.61 T
+1 F
+(Extended insert command) 162.9 162.61 T
+3 F
+(. The) 275.06 162.61 T
+5 F
+(insert) 298.1 162.61 T
+3 F
+( widget command now supports an addi-) 334.08 162.61 T
+-0.32 (tional ar) 162.9 150.47 P
+-0.32 (gument giving a list of tags to apply to the new characters. Y) 195.43 150.47 P
+-0.32 (ou can also include) 434 150.47 P
+(several text and tag ar) 162.9 138.33 T
+(guments in a single) 250.42 138.33 T
+5 F
+(insert) 330.38 138.33 T
+3 F
+( command.) 366.36 138.33 T
+FMENDPAGE
+%%EndPage: "10" 11
+%%Page: "11" 11
+612 792 0 FMBEGINPAGE
+4 10 Q
+0 X
+0 K
+(4 Better Motif compliance) 98.1 668.33 T
+0 F
+(1) 501.54 668.33 T
+(1) 506.54 668.33 T
+98.1 660.6 512.1 660.6 2 L
+0.25 H
+0 Z
+N
+98.1 135 512.1 639 R
+7 X
+V
+1 F
+0 X
+(See command) 162.9 632.33 T
+3 F
+(. There is a new) 222.03 632.33 T
+5 F
+(see) 288.08 632.33 T
+3 F
+( widget command, which adjusts the view in the) 306.07 632.33 T
+(widget if needed to ensure that a particular character is visible in the window) 162.9 620.29 T
+(.) 470.07 620.29 T
+0 F
+(3.5) 127.41 590.29 T
+(Porting issues: tag stickiness, change in end) 152.1 590.29 T
+3 F
+(There are two changes in text widgets that may require modi\336cations to Tk 3.6 scripts.) 152.1 574.29 T
+-0.06 (The \336rst change has to do with tag stickiness. In Tk 3.6, tags are sticky to the right: if you) 152.1 562.24 P
+(insert new text just after a tagged range, the new text acquires the tags of the preceding) 152.1 550.19 T
+(character) 152.1 538.14 T
+(. If you insert text before a tagged range in Tk 3.6, the new characters do not) 188.17 538.14 T
+-0.34 (acquire the tags of the range. In Tk 4.0, tags are not sticky on either side: new text acquires) 152.1 526.09 P
+(a tag from surrounding characters only if the tag is present on both sides of the insertion) 152.1 514.05 T
+(position. The sticky behavior in Tk 3.6 was rarely useful and special code was often) 152.1 502 T
+(needed to work around it. Y) 152.1 489.95 T
+(ou should be able to eliminate this code in Tk 4.0.) 263.24 489.95 T
+(The second incompatible change in text widgets is that the index) 170.1 477.95 T
+5 F
+(end) 431.32 477.95 T
+3 F
+( now refers to) 449.31 477.95 T
+-0.14 (the position just after the \336nal newline in the text, whereas in Tk 3.6 it referred to the posi-) 152.1 465.9 P
+-0.1 (tion just before the \336nal newline. This makes it possible to apply tags to the \336nal newline,) 152.1 453.86 P
+(which was not possible in Tk 3.6, but you may need to modify your scripts if you depend) 152.1 441.81 T
+(on the old position of) 152.1 429.76 T
+5 F
+(end) 240.11 429.76 T
+3 F
+(.) 258.1 429.76 T
+98.1 386.4 512.1 389.43 C
+152.1 387.63 512.1 387.63 2 L
+0.5 H
+2 Z
+0 X
+0 K
+N
+98.1 387.92 143.1 387.92 2 L
+0 Z
+N
+40.5 63 571.5 729 C
+0 12 Q
+0 X
+0 K
+(4) 134.63 393.43 T
+(Better Motif compliance) 152.1 393.43 T
+3 10 Q
+(All of the widgets have been modi\336ed in Tk 4.0 to improve their Motif compliance. This) 152.1 369.74 T
+-0.3 (was done by adding features that were missing and reworking the bindings to comply with) 152.1 357.69 P
+(Motif conventions. I believe that the widgets are now completely Motif compliant except) 152.1 345.64 T
+(for the following missing features:) 152.1 333.6 T
+3 12 Q
+(\245) 152.1 318.6 T
+3 10 Q
+(There is no support for secondary selections.) 162.9 318.6 T
+3 12 Q
+(\245) 152.1 303.6 T
+3 10 Q
+(There is no support for \322add mode\323 in widgets such as texts and listboxes.) 162.9 303.6 T
+3 12 Q
+(\245) 152.1 288.6 T
+3 10 Q
+(There is no support for drag and drop.) 162.9 288.6 T
+-0.02 (Please let me know if you \336nd any other discrepancies between the Tk widgets and Motif) 152.1 273.59 P
+(widgets. W) 152.1 261.55 T
+(e plan to eliminate the remaining incompatibilities over the next year or two.) 196.82 261.55 T
+98.1 218.19 512.1 221.21 C
+152.1 219.41 512.1 219.41 2 L
+0.5 H
+2 Z
+0 X
+0 K
+N
+98.1 219.7 143.1 219.7 2 L
+0 Z
+N
+40.5 63 571.5 729 C
+0 12 Q
+0 X
+0 K
+(5) 134.63 225.21 T
+(W) 152.1 225.21 T
+(idget changes) 163.31 225.21 T
+3 10 Q
+-0.07 (All of the Tk 4.0 widgets have been improved over their 3.6 counterparts, mostly in small) 152.1 201.52 P
+-0.23 (and backwards compatible ways. Here is a summary of the widget improvements; see Sec-) 152.1 189.48 P
+(tion 13 for information about incompatible changes.) 152.1 177.43 T
+3 12 Q
+(\245) 152.1 162.43 T
+3 10 Q
+(All widgets now have a) 162.9 162.43 T
+5 F
+(cget) 259.78 162.43 T
+3 F
+( command, which provides an easier way to retrieve the) 283.76 162.43 T
+(value of a con\336guration option. In other situations where con\336guration options are) 162.9 150.38 T
+(used, such as for menu entries or text tags, a) 162.9 138.33 T
+5 F
+(cget) 342.21 138.33 T
+3 F
+( command is also available.) 366.2 138.33 T
+FMENDPAGE
+%%EndPage: "11" 12
+%%Page: "12" 12
+612 792 0 FMBEGINPAGE
+0 10 Q
+0 X
+0 K
+(12) 98.1 668.33 T
+4 F
+(Tk4.0 Overview and Porting Guide) 359.34 668.33 T
+98.1 660.6 512.1 660.6 2 L
+0.25 H
+0 Z
+N
+98.1 135 512.1 639 R
+7 X
+V
+3 12 Q
+0 X
+(\245) 152.1 632.33 T
+3 10 Q
+-0.22 (All widgets now have) 162.9 632.33 P
+5 F
+-0.53 (-highlightthickness) 251.96 632.33 P
+3 F
+-0.22 (,) 365.9 632.33 P
+5 F
+-0.53 (-highlightbackground) 370.68 632.33 P
+3 F
+-0.22 (, and) 490.61 632.33 P
+5 F
+(-) 162.9 620.33 T
+(highlightcolor) 168.9 620.33 T
+3 F
+( options for displaying a highlight ring when the widget \050or one) 252.85 620.33 T
+(of its descendants\051 has the input focus.) 162.9 608.33 T
+3 12 Q
+(\245) 152.1 593.33 T
+3 10 Q
+(Entry widgets now support justi\336cation and provide a) 162.9 593.33 T
+5 F
+(-show) 379.99 593.33 T
+3 F
+( option for \050not\051 display-) 409.97 593.33 T
+(ing passwords. They will autosize to \336t their text if) 162.9 581.33 T
+5 F
+(-width 0) 369.17 581.33 T
+3 F
+( is speci\336ed.) 417.14 581.33 T
+3 12 Q
+(\245) 152.1 566.33 T
+3 10 Q
+-0.16 (The label/button family of widgets now supports multiline text and justi\336cation, includ-) 162.9 566.33 P
+(ing new options) 162.9 554.33 T
+5 F
+(-wraplength) 229.25 554.33 T
+3 F
+( and) 295.22 554.33 T
+5 F
+(-justify) 314.65 554.33 T
+3 F
+(. These features make the message) 361.97 554.33 T
+-0.04 (widget obsolete. There is also a new) 162.9 542.33 P
+5 F
+-0.1 (-underline) 310.27 542.33 P
+3 F
+-0.04 ( option for highlighting a character) 370.23 542.33 P
+(for keyboard traversal.) 162.9 530.33 T
+3 12 Q
+(\245) 152.1 515.33 T
+3 10 Q
+-0.23 (Listboxes now support all of the Motif selection modes, including single selection, mul-) 162.9 515.33 P
+(tiple selection, and multiple disjoint selections, via the) 162.9 503.33 T
+5 F
+(-selectmode) 382.78 503.33 T
+3 F
+( option. They) 448.74 503.33 T
+(will autosize to \336t their contents if) 162.9 491.33 T
+5 F
+(-width 0) 302.54 491.33 T
+3 F
+( or) 350.52 491.33 T
+5 F
+(-height 0) 363.84 491.33 T
+3 F
+( is speci\336ed. There are) 417.81 491.33 T
+(new) 162.9 479.33 T
+5 F
+(see) 182.05 479.33 T
+3 F
+(,) 200.04 479.33 T
+5 F
+(bbox) 205.04 479.33 T
+3 F
+(, and) 229.02 479.33 T
+5 F
+(activate) 250.95 479.33 T
+3 F
+( widget commands.) 298.92 479.33 T
+3 12 Q
+(\245) 152.1 464.33 T
+3 10 Q
+(Canvas polygons now support) 162.9 464.33 T
+5 F
+(-outline) 286.16 464.33 T
+3 F
+( and) 334.14 464.33 T
+5 F
+(-width) 353.57 464.33 T
+3 F
+( options for drawing outlines.) 389.55 464.33 T
+3 12 Q
+(\245) 152.1 449.33 T
+3 10 Q
+-0.03 (Scale widgets now support real values as well as integers \050see the) 162.9 449.33 P
+5 F
+-0.08 (-resolution) 426.77 449.33 P
+3 F
+-0.03 ( and) 492.73 449.33 P
+5 F
+-0.54 (-digits) 162.9 437.33 P
+3 F
+-0.22 ( options\051, and they have a) 204.88 437.33 P
+5 F
+-0.54 (-variable) 308.73 437.33 P
+3 F
+-0.22 ( option to link to a T) 362.7 437.33 P
+-0.22 (cl variable. They) 442.83 437.33 P
+-0.28 (have two new widget commands,) 162.9 425.33 P
+5 F
+-0.67 (coords) 297.52 425.33 P
+3 F
+-0.28 ( and) 333.5 425.33 P
+5 F
+-0.67 (identify) 352.37 425.33 P
+3 F
+-0.28 (, and their bindings are now) 399.69 425.33 P
+(de\336ned in T) 162.9 413.33 T
+(cl rather than being hardwired in C code as in Tk 3.6.) 210.5 413.33 T
+3 12 Q
+(\245) 152.1 398.33 T
+3 10 Q
+(Scrollbar widgets now have a new interface to the controlling widget, which provides) 162.9 398.33 T
+-0.04 (more \337exibility than the old style \050but the old style is still supported for compatibility\051.) 162.9 386.33 P
+(There is a new option) 162.9 374.33 T
+5 F
+(-jump) 252 374.33 T
+3 F
+( to prevent continuous updates while dragging the slider) 281.98 374.33 T
+(,) 505.88 374.33 T
+-0.24 (and a new option) 162.9 362.33 P
+5 F
+-0.59 (-elementborderwidth) 232.98 362.33 P
+3 F
+-0.24 ( to control the border width of the arrows) 346.92 362.33 P
+(and slider separately from the widget\325) 162.9 350.33 T
+(s outer border) 314.18 350.33 T
+(. There are four new widget com-) 369.14 350.33 T
+(mands,) 162.9 338.33 T
+5 F
+(activate) 193.99 338.33 T
+3 F
+(,) 241.97 338.33 T
+5 F
+(delta) 246.96 338.33 T
+3 F
+(,) 276.95 338.33 T
+5 F
+(fraction) 281.95 338.33 T
+3 F
+(, and) 329.92 338.33 T
+5 F
+(identify) 351.85 338.33 T
+3 F
+(, and the default bindings) 399.17 338.33 T
+(are now de\336ned in T) 162.9 326.33 T
+(cl rather than being hardwired in C code as in Tk 3.6.) 244.91 326.33 T
+3 12 Q
+(\245) 152.1 311.33 T
+3 10 Q
+-0.13 (Menu entries now have several new con\336guration options such as) 162.9 311.33 P
+5 F
+-0.31 (-foreground) 426.97 311.33 P
+3 F
+-0.13 ( and) 492.93 311.33 P
+5 F
+-0.41 (-) 162.9 299.33 P
+-0.41 (indicatoron) 168.9 299.33 P
+3 F
+-0.17 (, and tear) 234.86 299.33 P
+-0.17 (-of) 271.23 299.33 P
+-0.17 (f menus have been reimplemented to be more Motif-like.) 282.7 299.33 P
+(New menu entries can be created in the middle of a menu using the) 162.9 287.33 T
+5 F
+(insert) 434.36 287.33 T
+3 F
+( widget) 470.34 287.33 T
+(command, and there is a) 162.9 275.33 T
+5 F
+(type) 262.83 275.33 T
+3 F
+( widget command that returns the type of a menu entry) 286.81 275.33 T
+(.) 505.45 275.33 T
+3 12 Q
+(\245) 152.1 260.33 T
+3 10 Q
+(Menubuttons now have a) 162.9 260.33 T
+5 F
+(-indicatoron) 266.16 260.33 T
+3 F
+( option for displaying an option menu indi-) 338.12 260.33 T
+-0.38 (cator) 162.9 248.33 P
+-0.38 (. There is now support for option menus via the) 182.33 248.33 P
+5 F
+-0.91 (tk_optionMenu) 370.9 248.33 P
+3 F
+-0.38 ( procedure, and) 448.86 248.33 P
+(popups are simpli\336ed with the) 162.9 236.33 T
+5 F
+(tk_popup) 286.44 236.33 T
+3 F
+( procedure.) 334.42 236.33 T
+3 12 Q
+(\245) 152.1 221.33 T
+3 10 Q
+-0.03 (The variable) 162.9 221.33 P
+5 F
+-0.07 (tk_strictMotif) 215.57 221.33 P
+3 F
+-0.03 ( is used in more places to enforce even stricter Motif) 299.53 221.33 P
+(compliance.) 162.9 209.33 T
+FMENDPAGE
+%%EndPage: "12" 13
+%%Page: "13" 13
+612 792 0 FMBEGINPAGE
+4 10 Q
+0 X
+0 K
+(6 Images) 98.1 668.33 T
+0 F
+(13) 500.99 668.33 T
+98.1 660.6 512.1 660.6 2 L
+0.25 H
+0 Z
+N
+98.1 135 512.1 639 R
+7 X
+V
+98.1 623.98 512.1 627 C
+152.1 625.2 512.1 625.2 2 L
+0.5 H
+2 Z
+0 X
+0 K
+N
+98.1 625.49 143.1 625.49 2 L
+0 Z
+N
+40.5 63 571.5 729 C
+0 12 Q
+0 X
+0 K
+(6) 134.63 631 T
+(Images) 152.1 631 T
+3 10 Q
+(Tk 4.0 contains a general-purpose image mechanism for displaying color pictures and) 152.1 607.31 T
+(other complex objects. There is a new command,) 152.1 595.26 T
+5 F
+(image) 350.84 595.26 T
+3 F
+(, which may be used to create) 380.82 595.26 T
+(image objects. For example, the command) 152.1 583.21 T
+5 9 Q
+(image create photo myFace -f) 179.1 568.88 T
+(ile picture.ppm) 330.09 568.88 T
+3 10 Q
+(creates a new image named) 152.1 555.21 T
+5 F
+(myFace) 264.5 555.21 T
+3 F
+(. The image is of type) 300.48 555.21 T
+5 F
+(photo) 390.14 555.21 T
+3 F
+( \050a full-color represen-) 420.12 555.21 T
+(tation that dithers on monochrome or color) 152.1 543.17 T
+(-mapped displays\051 and the source data for the) 323.46 543.17 T
+(image is in the \336le named) 152.1 531.12 T
+5 F
+(picture.ppm) 257.59 531.12 T
+3 F
+(. Once an image has been created, it can be) 323.56 531.12 T
+-0.15 (used in many dif) 152.1 519.07 P
+-0.15 (ferent places by specifying a) 218.37 519.07 P
+5 F
+-0.36 (-image) 334.46 519.07 P
+3 F
+-0.15 ( option. For example, the command) 370.44 519.07 P
+5 9 Q
+(label .l -image myFace) 179.1 504.74 T
+3 10 Q
+(will create a label widget that displays the image, and if) 152.1 491.07 T
+5 F
+(.c) 377.5 491.07 T
+3 F
+( is a canvas widget the com-) 389.49 491.07 T
+(mand) 152.1 479.02 T
+5 9 Q
+(.c create image 400 200 -image myFace) 179.1 464.69 T
+3 10 Q
+(will create an image item in the canvas that displays) 152.1 451.02 T
+5 F
+(myFace) 363.06 451.02 T
+3 F
+(.) 399.04 451.02 T
+(The image mechanism provides a great deal of \337exibility:) 170.1 439.02 T
+3 12 Q
+(\245) 152.1 424.02 T
+3 10 Q
+-0.18 (Once an image has been de\336ned, it can be used in many dif) 162.9 424.02 P
+-0.18 (ferent places, even on dif) 397.84 424.02 P
+-0.18 (fer-) 497.68 424.02 P
+(ent displays.) 162.9 411.98 T
+3 12 Q
+(\245) 152.1 396.98 T
+3 10 Q
+(Images provide image commands, analogous to widget commands, that can be used to) 162.9 396.98 T
+(manipulate the image; any changes in an image are automatically re\337ected in all of its) 162.9 384.93 T
+(instances.) 162.9 372.88 T
+3 12 Q
+(\245) 152.1 357.88 T
+3 10 Q
+-0.21 (There can be many dif) 162.9 357.88 P
+-0.21 (ferent types of images. Tk 4.0 has two built-in types,) 251.78 357.88 P
+5 F
+-0.51 (photo) 463.11 357.88 P
+3 F
+-0.21 ( and) 493.1 357.88 P
+5 F
+(bitmap) 162.9 345.83 T
+3 F
+(. Other image types can be de\336ned in C as extensions \050see the documentation) 198.88 345.83 T
+-0.16 (for the) 162.9 333.79 P
+5 F
+-0.39 (Tk_CreateImageType) 191.44 333.79 P
+3 F
+-0.16 ( library procedure\051. The photo image type was imple-) 299.38 333.79 P
+(mented by Paul Mackerras, based on his earlier photo widget.) 162.9 321.74 T
+3 12 Q
+(\245) 152.1 306.74 T
+3 10 Q
+(W) 162.9 306.74 T
+(ithin the photo image type, there can be many dif) 171.93 306.74 T
+(ferent \336le formats. In Tk 4.0, only) 368.29 306.74 T
+-0.11 (PPM, PGM, and GIF formats are built-in, but other formats can be added as extensions) 162.9 294.69 P
+(\050see the documentation for the) 162.9 282.64 T
+5 F
+(Tk_CreatePhotoImageFormat) 286.97 282.64 T
+3 F
+( library proce-) 436.89 282.64 T
+(dure\051. Readers for XPM, TIFF) 162.9 270.59 T
+(, and others are available from the T) 284.23 270.59 T
+(cl community) 428.41 270.59 T
+(.) 483.01 270.59 T
+98.1 227.24 512.1 230.26 C
+152.1 228.46 512.1 228.46 2 L
+0.5 H
+2 Z
+0 X
+0 K
+N
+98.1 228.75 143.1 228.75 2 L
+0 Z
+N
+40.5 63 571.5 729 C
+0 12 Q
+0 X
+0 K
+(7) 134.63 234.26 T
+(Color management) 152.1 234.26 T
+3 10 Q
+(Tk 3.6 suf) 152.1 210.57 T
+(fers from a relatively weak mechanism for managing colors. It uses only the) 192.73 210.57 T
+(default colormap for a screen, and if all the entries in that colormap \336ll up then Tk) 152.1 198.52 T
+(switches to monochrome mode and \322rounds\323 all future colors to black or white. This) 152.1 186.48 T
+(approach is becoming increasingly unpleasant because of applications such as Frame and) 152.1 174.43 T
+(W) 152.1 162.38 T
+(eb browsers that use up all the entries in the default colormap.) 160.74 162.38 T
+(Tk 4.0 has a much more powerful color management mechanism. If a colormap \336lls) 170.1 150.38 T
+(up, Tk allocates future colors by picking the closest match from the available colors, so) 152.1 138.33 T
+FMENDPAGE
+%%EndPage: "13" 14
+%%Page: "14" 14
+612 792 0 FMBEGINPAGE
+0 10 Q
+0 X
+0 K
+(14) 98.1 668.33 T
+4 F
+(Tk4.0 Overview and Porting Guide) 359.34 668.33 T
+98.1 660.6 512.1 660.6 2 L
+0.25 H
+0 Z
+N
+98.1 135 512.1 639 R
+7 X
+V
+3 F
+0 X
+(that it need not revert to monochrome mode. Tk also manages colors better by delaying) 152.1 632.33 T
+-0.3 (color allocation until colors are actually needed; in many cases, such as 3D borders, colors) 152.1 620.33 P
+(are never needed. When colors are scarce Tk changes the way it displays beveled borders) 152.1 608.33 T
+-0.38 (so that it uses stippling instead of additional colors for the light and dark shadows. Y) 152.1 596.33 P
+-0.38 (ou can) 484.01 596.33 P
+(\336nd out whether a colormap has \336lled up using the new command) 152.1 584.33 T
+5 F
+(winfo colormap-) 418.59 584.33 T
+(full) 152.1 572.33 T
+3 F
+(.) 176.09 572.33 T
+-0.26 (Tk 4.0 also allows you to allocate new colormaps for toplevel and frame widgets with) 170.1 560.33 P
+(the) 152.1 548.33 T
+5 F
+(-colormap) 166.81 548.33 T
+3 F
+( option, and you change the visual type in these widgets \050with the) 220.78 548.33 T
+5 F
+(-) 152.1 536.33 T
+(visual) 158.1 536.33 T
+3 F
+( option\051 to take advantage of visuals other than the default visual for a screen.) 194.08 536.33 T
+(New commands) 152.1 524.33 T
+5 F
+(winfo visualsavailable) 219.27 524.33 T
+3 F
+( and) 351.2 524.33 T
+5 F
+(wm colormapwindows) 370.63 524.33 T
+3 F
+( have) 478.57 524.33 T
+(been added to help manage colormaps and visuals.) 152.1 512.33 T
+(The default color scheme in Tk 4.0 has changed from a tan palette \050\322bisque\323\051 to a) 170.1 500.33 T
+(gray palette, which seems to becoming standard for Motif. There is a new T) 152.1 488.33 T
+(cl procedure) 454.78 488.33 T
+5 F
+-0.36 (tk_setPalette) 152.1 476.33 P
+3 F
+-0.15 ( that changes the palette of an application on the \337y) 230.06 476.33 P
+-0.15 (, and there is also a) 433.89 476.33 P
+(procedure) 152.1 464.33 T
+5 F
+(tk_bisque) 194.56 464.33 T
+3 F
+( to restore the palette to the old bisque colors.) 248.53 464.33 T
+(The Tk 3.6 color model mechanism is no longer necessary so it has been removed in) 170.1 452.33 T
+(Tk 4.0. If you want to \336nd out whether a screen is monochrome or color) 152.1 440.33 T
+(, you cannot use) 440.38 440.33 T
+(the) 152.1 428.33 T
+5 F
+(tk colormodel) 166.81 428.33 T
+3 F
+( command anymore; use) 244.77 428.33 T
+5 F
+(winfo depth) 345.25 428.33 T
+3 F
+( instead.) 411.22 428.33 T
+98.1 384.98 512.1 388 C
+152.1 386.2 512.1 386.2 2 L
+0.5 H
+2 Z
+0 X
+0 K
+N
+98.1 386.49 143.1 386.49 2 L
+0 Z
+N
+40.5 63 571.5 729 C
+0 12 Q
+0 X
+0 K
+(8) 134.63 392 T
+(Event handling: \336leevent and after) 152.1 392 T
+3 10 Q
+(Tk 4.0 contains several improvements in the area of event handling besides those already) 152.1 368.31 T
+(mentioned for bindings:) 152.1 356.31 T
+3 12 Q
+(\245) 152.1 341.31 T
+3 10 Q
+(There is a new command) 162.9 341.31 T
+5 F
+(f) 265.87 341.31 T
+(ileevent) 271.87 341.31 T
+3 F
+( for performing event-driven I/O to and from) 319.84 341.31 T
+-0.12 (\336les. The) 162.9 329.31 P
+5 F
+-0.29 (f) 202.35 329.31 P
+-0.29 (ileevent) 208.35 329.31 P
+3 F
+-0.12 ( command is modelled very closely after Mark Diekhans\325) 256.33 329.31 P
+5 F
+-0.29 (add-) 488.11 329.31 P
+(input) 162.9 317.31 T
+3 F
+( extension, which has been used widely with Tk 3.6.) 192.88 317.31 T
+3 12 Q
+(\245) 152.1 302.31 T
+3 10 Q
+-0.34 (The) 162.9 302.31 P
+5 F
+-0.82 (after) 180.6 302.31 P
+3 F
+-0.34 ( command has two new options,) 210.58 302.31 P
+5 F
+-0.82 (idle) 339.82 302.31 P
+3 F
+-0.34 ( and) 363.81 302.31 P
+5 F
+-0.82 (cancel) 382.55 302.31 P
+3 F
+-0.34 (.) 418.53 302.31 P
+5 F
+-0.82 (After idle) 423.19 302.31 P
+3 F
+-0.34 ( can be) 482.33 302.31 P
+-0.2 (used to schedule a script as an \322idle handler\323, which means it runs the next time that Tk) 162.9 290.31 P
+(enters the event loop and \336nds no work to do.) 162.9 278.31 T
+5 F
+(After cancel) 348.06 278.31 T
+3 F
+( may be used to delete) 420.02 278.31 T
+(a previously-scheduled) 162.9 266.31 T
+5 F
+(after) 257.83 266.31 T
+3 F
+( script, so that it will no longer be invoked.) 287.81 266.31 T
+98.1 222.95 512.1 225.98 C
+152.1 224.18 512.1 224.18 2 L
+0.5 H
+2 Z
+0 X
+0 K
+N
+98.1 224.46 143.1 224.46 2 L
+0 Z
+N
+40.5 63 571.5 729 C
+0 12 Q
+0 X
+0 K
+(9) 134.63 229.98 T
+(Multiple displays) 152.1 229.98 T
+3 10 Q
+(Although Tk has always allowed a single application to open windows on several dis-) 152.1 206.29 T
+(plays, the support for multiple displays is weak in Tk 3.6. For example, many of the bind-) 152.1 194.29 T
+(ings break if users work simultaneously in windows on dif) 152.1 182.29 T
+(ferent displays, and) 385.94 182.29 T
+(mechanisms like the selection and the input focus have insuf) 152.1 170.29 T
+(\336cient support for multiple) 394.26 170.29 T
+(displays.) 152.1 158.29 T
+FMENDPAGE
+%%EndPage: "14" 15
+%%Page: "15" 15
+612 792 0 FMBEGINPAGE
+4 10 Q
+0 X
+0 K
+(10 The send command) 98.1 668.33 T
+0 F
+(15) 500.99 668.33 T
+98.1 660.6 512.1 660.6 2 L
+0.25 H
+0 Z
+N
+98.1 135 512.1 639 R
+7 X
+V
+3 F
+0 X
+-0.33 (Tk 4.0 contains numerous modi\336cations to improve the handling of multiple displays.) 170.1 632.33 P
+-0.18 (Several commands, such as) 152.1 620.24 P
+5 F
+-0.44 (selection) 263.78 620.24 P
+3 F
+-0.18 (,) 317.76 620.24 P
+5 F
+-0.44 (send) 322.57 620.24 P
+3 F
+-0.18 (, and) 346.55 620.24 P
+5 F
+-0.44 (focus) 368.12 620.24 P
+3 F
+-0.18 (, have a new) 398.1 620.24 P
+5 F
+-0.44 (-displayof) 449.82 620.24 P
+3 F
+(ar) 152.1 608.15 T
+(gument so that you can select a particular display) 159.69 608.15 T
+(. In addition, the bindings have been) 356.12 608.15 T
+(reworked to handle interactions occurring simultaneously on dif) 152.1 596.05 T
+(ferent displays. W) 408.13 596.05 T
+(ith Tk) 480.73 596.05 T
+(4.0 it should be possible to create applications that really use multiple displays gracefully) 152.1 583.96 T
+(.) 508.44 583.96 T
+98.1 540.6 512.1 543.63 C
+152.1 541.83 512.1 541.83 2 L
+0.5 H
+2 Z
+0 X
+0 K
+N
+98.1 542.12 143.1 542.12 2 L
+0 Z
+N
+40.5 63 571.5 729 C
+0 12 Q
+0 X
+0 K
+(10) 127.96 547.63 T
+(The send command) 152.1 547.63 T
+3 10 Q
+-0.2 (The) 152.1 523.94 P
+5 F
+-0.48 (send) 169.94 523.94 P
+3 F
+-0.2 ( command has been completely overhauled for Tk 4.0 to eliminate several prob-) 193.93 523.94 P
+(lems in Tk 3.6 and add a number of new features:) 152.1 511.85 T
+3 12 Q
+(\245) 152.1 496.85 T
+3 10 Q
+(Tk 3.6 aborts a) 162.9 496.85 T
+5 F
+(send) 225.36 496.85 T
+3 F
+( command if no response is received within 5 seconds; this made) 249.34 496.85 T
+(it very dif) 162.9 484.75 T
+(\336cult to invoke long-running commands. Tk 4.0 eliminates the timeout and) 202.14 484.75 T
+(uses a dif) 162.9 472.66 T
+(ferent mechanism to tell if the tar) 200.47 472.66 T
+(get application has crashed.) 333.53 472.66 T
+3 12 Q
+(\245) 152.1 457.66 T
+3 10 Q
+-0.36 (The) 162.9 457.66 P
+5 F
+-0.87 (winfo interps) 180.58 457.66 P
+3 F
+-0.36 ( command no longer returns the names of applications that have) 257.66 457.66 P
+(exited or crashed.) 162.9 445.57 T
+3 12 Q
+(\245) 152.1 430.57 T
+3 10 Q
+(Asynchronous sends are possible using the) 162.9 430.57 T
+5 F
+(-async) 336.67 430.57 T
+3 F
+( switch.) 372.65 430.57 T
+3 12 Q
+(\245) 152.1 415.57 T
+3 10 Q
+(Commands can be sent to displays other than that of the root window) 162.9 415.57 T
+(, using the) 439.3 415.57 T
+5 F
+(-) 162.9 403.47 T
+(displayof) 168.9 403.47 T
+3 F
+( switch.) 222.87 403.47 T
+3 12 Q
+(\245) 152.1 388.47 T
+3 10 Q
+(W) 162.9 388.47 T
+(indow server security is now checked on each) 171.93 388.47 T
+5 F
+(send) 357.89 388.47 T
+3 F
+(, so Tk 4.0 deals better with) 381.88 388.47 T
+(changes in the security of the server) 162.9 376.38 T
+(.) 306.12 376.38 T
+3 12 Q
+(\245) 152.1 361.38 T
+3 10 Q
+(More complete error information \050including the) 162.9 361.38 T
+5 F
+(errorCode) 356.09 361.38 T
+3 F
+( and) 410.06 361.38 T
+5 F
+(errorInfo) 429.49 361.38 T
+3 F
+( vari-) 483.46 361.38 T
+(ables\051 is propagated back to the sender after errors.) 162.9 349.29 T
+3 12 Q
+(\245) 152.1 334.29 T
+3 10 Q
+(Y) 162.9 334.29 T
+(ou can query and change the name of an application with the) 169.12 334.29 T
+5 F
+(tk appname) 414.48 334.29 T
+3 F
+( com-) 474.45 334.29 T
+(mand.) 162.9 322.19 T
+(Unfortunately the improvements to the Tk 4.0) 152.1 307.19 T
+5 F
+(send) 338.65 307.19 T
+3 F
+( mechanism required substantial) 362.63 307.19 T
+(changes to the transport protocol for sends; this makes it impossible for Tk 4.0 applica-) 152.1 295.1 T
+(tions to communicate with Tk 3.6 applications via) 152.1 283.01 T
+5 F
+(send) 355.04 283.01 T
+3 F
+(. The new transport protocol is) 379.02 283.01 T
+(more \337exible than the old protocol, so it should be possible to make protocol improve-) 152.1 270.91 T
+(ments in an upward-compatible way) 152.1 258.82 T
+(.) 296.9 258.82 T
+98.1 215.47 512.1 218.49 C
+152.1 216.69 512.1 216.69 2 L
+0.5 H
+2 Z
+0 X
+0 K
+N
+98.1 216.98 143.1 216.98 2 L
+0 Z
+N
+40.5 63 571.5 729 C
+0 12 Q
+0 X
+0 K
+(1) 128.62 222.49 T
+(1) 134.63 222.49 T
+(The selection and clipboard) 152.1 222.49 T
+3 10 Q
+(In Tk 3.6 the selection mechanism can deal only with the display of the root window and) 152.1 198.8 T
+-0.13 (with the primary selection; there is no support for multiple displays, secondary selections,) 152.1 186.71 P
+(or the clipboard. Tk 4.0 eliminates all of these shortcomings. The) 152.1 174.61 T
+5 F
+(-displayof) 415.82 174.61 T
+3 F
+( option) 475.78 174.61 T
+-0.12 (can be used to specify a particular display in the selection command, and there is now full) 152.1 162.52 P
+(access to all of the X selection types. Tk 4.0 also includes a new) 152.1 150.43 T
+5 F
+(clipboard) 411.36 150.43 T
+3 F
+( command) 465.33 150.43 T
+(for manipulating the clipboard.) 152.1 138.33 T
+FMENDPAGE
+%%EndPage: "15" 16
+%%Page: "16" 16
+612 792 0 FMBEGINPAGE
+0 10 Q
+0 X
+0 K
+(16) 98.1 668.33 T
+4 F
+(Tk4.0 Overview and Porting Guide) 359.34 668.33 T
+98.1 660.6 512.1 660.6 2 L
+0.25 H
+0 Z
+N
+98.1 135 512.1 639 R
+7 X
+V
+98.1 623.98 512.1 627 C
+152.1 625.2 512.1 625.2 2 L
+0.5 H
+2 Z
+0 X
+0 K
+N
+98.1 625.49 143.1 625.49 2 L
+0 Z
+N
+40.5 63 571.5 729 C
+0 12 Q
+0 X
+0 K
+(12) 127.96 631 T
+(Miscellaneous changes) 152.1 631 T
+3 10 Q
+(Here is a quick summary of the remaining changes in Tk 4.0:) 152.1 607.31 T
+3 12 Q
+(\245) 152.1 592.31 T
+3 10 Q
+-0.17 (The) 162.9 592.31 P
+5 F
+-0.42 (wish) 180.76 592.31 P
+3 F
+-0.17 ( application has been modi\336ed so that the) 204.75 592.31 P
+5 F
+-0.42 (-f) 371.58 592.31 P
+-0.42 (ile) 383.57 592.31 P
+3 F
+-0.17 ( switch is no longer needed) 401.56 592.31 P
+(or recommended. This makes) 162.9 580.31 T
+5 F
+(wish) 283.64 580.31 T
+3 F
+( just like) 307.63 580.31 T
+5 F
+(tclsh) 344.56 580.31 T
+3 F
+(, where you specify the script \336le) 374.54 580.31 T
+(as the \336rst ar) 162.9 568.31 T
+(gument to the program, e.g.) 214.07 568.31 T
+5 F
+(wish foo.tcl) 327.33 568.31 T
+3 F
+(. The) 399.29 568.31 T
+5 F
+(-f) 422.33 568.31 T
+(ile) 434.32 568.31 T
+3 F
+( switch is still) 452.31 568.31 T
+(permitted for backward compatibility) 162.9 556.31 T
+(, but its use is deprecated.) 311.87 556.31 T
+3 12 Q
+(\245) 152.1 541.31 T
+5 10 Q
+(Wish) 162.9 541.31 T
+3 F
+( now sets the application\325) 186.89 541.31 T
+(s class from the application name \050what appears in the) 288.49 541.31 T
+-0.37 (title bar of the window by default\051, rather than always using) 162.9 529.31 P
+5 F
+-0.88 (Tk) 400.9 529.31 P
+3 F
+-0.37 ( as the class as in Tk 3.6.) 412.89 529.31 P
+(This makes application-speci\336c options easier to use.) 162.9 517.31 T
+3 12 Q
+(\245) 152.1 502.31 T
+3 10 Q
+(T) 162.9 502.31 T
+(oplevel windows are now resizable by default, whereas in Tk 3.6 they were not. Y) 168.31 502.31 T
+(ou) 496.22 502.31 T
+(can use the) 162.9 490.31 T
+5 F
+(wm resizable) 209.8 490.31 T
+3 F
+( command to make windows non-reiszable.) 281.77 490.31 T
+3 12 Q
+(\245) 152.1 475.31 T
+3 10 Q
+(Tk 4.0 patches around an Xlib bug whereby long-running applications tended to reach) 162.9 475.31 T
+(the end of the space of X resource ids, wrap around to 0 again, and then crash. Tk now) 162.9 463.31 T
+(reuses resource identi\336ers so that wrap-around should never occur) 162.9 451.31 T
+(.) 427.14 451.31 T
+3 12 Q
+(\245) 152.1 436.31 T
+3 10 Q
+-0.13 (There is a new) 162.9 436.31 P
+5 F
+-0.31 (winfo manager) 223.43 436.31 P
+3 F
+-0.13 ( command that tells which geometry manager is con-) 301.08 436.31 P
+(trolling a particular widget.) 162.9 424.31 T
+3 12 Q
+(\245) 152.1 409.31 T
+3 10 Q
+(There is a new) 162.9 409.31 T
+5 F
+(bell) 223.96 409.31 T
+3 F
+( command that does what its name suggests.) 247.94 409.31 T
+3 12 Q
+(\245) 152.1 394.31 T
+3 10 Q
+(There are new) 162.9 394.31 T
+5 F
+(winfo pointerx) 222.56 394.31 T
+3 F
+(,) 306.51 394.31 T
+5 F
+(winfo pointery) 311.51 394.31 T
+3 F
+(, and) 394.81 394.31 T
+5 F
+(winfo pointerxy) 416.74 394.31 T
+3 F
+(commands that can be used to query the position of the mouse pointer) 162.9 382.31 T
+(.) 442.17 382.31 T
+98.1 338.95 512.1 341.98 C
+152.1 340.18 512.1 340.18 2 L
+0.5 H
+2 Z
+0 X
+0 K
+N
+98.1 340.46 143.1 340.46 2 L
+0 Z
+N
+40.5 63 571.5 729 C
+0 12 Q
+0 X
+0 K
+(13) 127.96 345.98 T
+(Summary of Incompatibilites) 152.1 345.98 T
+3 10 Q
+-0.24 (This section lists all of the incompatible changes in Tk 4.0 that may require changes in T) 152.1 322.29 P
+-0.24 (cl) 502.62 322.29 P
+-0.22 (scripts written for T) 152.1 310.29 P
+-0.22 (cl 3.6. Each incompatibility is described in terms of the problem it pro-) 230.42 310.29 P
+(duces when you run your Tk 3.6 script under Tk 4.0 and a possible work-around. Only) 152.1 298.29 T
+(T) 152.1 286.29 T
+(cl-level incompatibilities are covered here. For incompatible changes at the C level, see) 157.51 286.29 T
+(the) 152.1 274.29 T
+5 F
+(README) 166.81 274.29 T
+3 F
+( and) 202.79 274.29 T
+5 F
+(changes) 222.22 274.29 T
+3 F
+( \336les in the distribution. The problems and solutions are) 264.2 274.29 T
+(roughly in order of importance, with the most important problems \336rst.) 152.1 262.29 T
+1 F
+(Pr) 152.1 247.29 T
+(oblem #1:) 162.46 247.29 T
+3 F
+(When you change the background color of a widget, a small ring in the) 206.88 247.29 T
+(default background color remains around the edge of the widget.) 152.1 235.29 T
+2 F
+(Solution:) 170.1 223.29 T
+3 F
+(This is the focus traversal highlight, whose color is speci\336ed separately) 209.25 223.29 T
+(from) 170.1 211.29 T
+5 F
+(-background) 192.03 211.29 T
+3 F
+(; use the) 257.99 211.29 T
+5 F
+(-highlightbackground) 293.8 211.29 T
+3 F
+( option to change the) 413.74 211.29 T
+(color of the highlight. Or) 170.1 199.29 T
+(, you can set) 269.92 199.29 T
+5 F
+(-highlightthickness) 322.38 199.29 T
+3 F
+( to 0 to eliminate) 436.31 199.29 T
+(the traversal highlight altogether) 170.1 187.29 T
+(.) 299.74 187.29 T
+1 F
+(Pr) 152.1 172.29 T
+(oblem #2:) 162.46 172.29 T
+3 F
+(Bindings de\336ned for a widget no longer replace the corresponding class) 206.88 172.29 T
+(bindings, so unwanted class bindings get invoked in addition to the widget bindings.) 152.1 160.29 T
+FMENDPAGE
+%%EndPage: "16" 17
+%%Page: "17" 17
+612 792 0 FMBEGINPAGE
+4 10 Q
+0 X
+0 K
+(13 Summary of Incompatibilites) 98.1 668.33 T
+0 F
+(17) 500.99 668.33 T
+98.1 660.6 512.1 660.6 2 L
+0.25 H
+0 Z
+N
+98.1 135 512.1 639 R
+7 X
+V
+2 F
+0 X
+(Solution:) 170.1 632.33 T
+3 F
+(Add a) 209.25 632.33 T
+5 F
+(break) 235.89 632.33 T
+3 F
+( command at the end of the widget binding, or rework the) 265.88 632.33 T
+(widget binding so that it\325) 170.1 620.33 T
+(s OK for the class binding to execute.) 270.05 620.33 T
+1 F
+(Pr) 152.1 605.33 T
+(oblem #3:) 162.46 605.33 T
+3 F
+(Bindings on toplevel windows are invoked when events occur for internal) 206.88 605.33 T
+(windows inside the toplevels.) 152.1 593.33 T
+2 F
+(Solution:) 170.1 581.33 T
+3 F
+(Use the) 209.25 581.33 T
+5 F
+(%W) 242 581.33 T
+3 F
+( substitution to extract the name of the window where the event) 253.99 581.33 T
+(actually occurred, and only execute the rest of the binding script if this matches the) 170.1 569.33 T
+(name of the toplevel.) 170.1 557.33 T
+1 F
+-0.15 (Pr) 152.1 542.33 P
+-0.15 (oblem #4:) 162.46 542.33 P
+3 F
+-0.15 (The) 206.58 542.33 P
+5 F
+-0.37 (-command) 224.46 542.33 P
+3 F
+-0.15 ( option for a cascade menu entry is no longer invoked when) 272.44 542.33 P
+(the submenu is posted.) 152.1 530.33 T
+2 F
+(Solution:) 170.1 518.33 T
+3 F
+(Use the) 209.25 518.33 T
+5 F
+(-postcommand) 242 518.33 T
+3 F
+( option for the submenu instead.) 313.96 518.33 T
+1 F
+(Pr) 152.1 503.33 T
+(oblem #5:) 162.46 503.33 T
+3 F
+(The) 206.88 503.33 T
+5 F
+(-geometry) 224.92 503.33 T
+3 F
+( option is no longer supported by listboxes, frames, and) 278.89 503.33 T
+(toplevels.) 152.1 491.33 T
+2 F
+(Solution:) 170.1 479.33 T
+3 F
+(Use the) 209.25 479.33 T
+5 F
+(-width) 242 479.33 T
+3 F
+( and) 277.98 479.33 T
+5 F
+(-height) 297.41 479.33 T
+3 F
+( options instead.) 339.39 479.33 T
+1 F
+(Pr) 152.1 464.33 T
+(oblem #6:) 162.46 464.33 T
+3 F
+(The procedure) 206.88 464.33 T
+5 F
+(tk_listboxSingleSelect) 267.38 464.33 T
+3 F
+( no longer exists.) 399.3 464.33 T
+2 F
+(Solution:) 170.1 452.33 T
+3 F
+(Use the) 209.25 452.33 T
+5 F
+(-selectmode) 242 452.33 T
+3 F
+( option on the listbox instead.) 307.96 452.33 T
+1 F
+(Pr) 152.1 437.33 T
+(oblem #7:) 162.46 437.33 T
+3 F
+(Canvases no longer have a) 206.88 437.33 T
+5 F
+(-scrollincrement) 315.96 437.33 T
+3 F
+( option.) 411.91 437.33 T
+2 F
+(Solution:) 170.1 425.33 T
+3 F
+(Use the new) 209.25 425.33 T
+5 F
+(-xscrollincrement) 261.15 425.33 T
+3 F
+( and) 363.09 425.33 T
+5 F
+(-yscrollincrement) 382.52 425.33 T
+3 F
+(options instead.) 170.1 413.33 T
+1 F
+(Pr) 152.1 398.33 T
+(oblem #8:) 162.46 398.33 T
+3 F
+(The) 206.88 398.33 T
+5 F
+(tk colormodel) 224.92 398.33 T
+3 F
+( command no longer exists.) 302.88 398.33 T
+2 F
+-0.28 (Solution:) 170.1 386.33 P
+3 F
+-0.28 (T) 208.97 386.33 P
+-0.28 (o \336nd out whether a window is monochrome or color) 214.37 386.33 P
+-0.28 (, use) 424.34 386.33 P
+5 F
+-0.68 (winfo depth) 444.6 386.33 P
+3 F
+(to extract the window\325) 170.1 374.33 T
+(s depth; a depth of 1 means monochrome.) 259.76 374.33 T
+1 F
+-0.08 (Pr) 152.1 359.33 P
+-0.08 (oblem #9:) 162.46 359.33 P
+3 F
+-0.08 (The class of Tk applications is no longer) 206.72 359.33 P
+5 F
+-0.19 (Tk) 370.97 359.33 P
+3 F
+-0.08 (, so options speci\336ed for the) 382.96 359.33 P
+5 F
+-0.19 (Tk) 497.69 359.33 P
+3 F
+(class in your) 152.1 347.33 T
+5 F
+(.Xdefaults) 205.12 347.33 T
+3 F
+( \336le are no longer used.) 265.09 347.33 T
+2 F
+(Solution:) 170.1 335.33 T
+3 F
+(Modify your) 209.25 335.33 T
+5 F
+(.Xdefaults) 262.55 335.33 T
+3 F
+( \336le \050and any T) 322.52 335.33 T
+(cl code that sets options\051 to) 382.88 335.33 T
+(specify the name of the application \050with the \336rst letter capitalized\051 as the class) 170.1 323.33 T
+(instead of) 170.1 311.33 T
+5 F
+(Tk) 211.74 311.33 T
+3 F
+(.) 223.73 311.33 T
+1 F
+-0.15 (Pr) 152.1 296.33 P
+-0.15 (oblem #10:) 162.46 296.33 P
+3 F
+-0.15 (When text is added to a text widget just after a tagged area, the new text no) 211.57 296.33 P
+(longer receives the tag.) 152.1 284.33 T
+2 F
+-0.1 (Solution:) 170.1 272.33 P
+3 F
+-0.1 (Explicitly tag the new text with the desired tags. If you want the tags on the) 209.15 272.33 P
+-0.08 (new text to be the same as those at some other point in the text, you can use the) 170.1 260.33 P
+5 F
+-0.2 (tag) 488.31 260.33 P
+(names) 170.1 248.33 T
+3 F
+( widget command to query existing tags.) 200.08 248.33 T
+1 F
+(Pr) 152.1 233.33 T
+(oblem #1) 162.46 233.33 T
+(1:) 200.5 233.33 T
+3 F
+(W) 211.33 233.33 T
+(idgets appear lar) 220.36 233.33 T
+(ger than they did in Tk 3.6.) 286.24 233.33 T
+2 F
+(Solution:) 170.1 221.33 T
+3 F
+(There are two issues here. The \336rst is that all widgets now have a focus tra-) 209.25 221.33 T
+-0.24 (versal highlight ring that turns dark when the widget has the focus; this is required for) 170.1 209.33 P
+(Motif compliance but you can eliminate it by specifying a 0 value for the) 170.1 197.33 T
+5 F
+( -high-) 462.4 197.33 T
+(lightthickness) 170.1 185.33 T
+3 F
+( option. The second issue is that the default padding for buttons) 254.05 185.33 T
+-0.17 (and menubuttons has been increased to match the sizes of Motif widgets. If you don\325) 170.1 173.33 P
+-0.17 (t) 506.99 173.33 P
+(mind being dif) 170.1 161.33 T
+(ferent from Motif, you can set the) 228.78 161.33 T
+5 F
+(-padx) 366.45 161.33 T
+3 F
+( and) 396.44 161.33 T
+5 F
+(-) 415.86 161.33 T
+(pady) 421.86 161.33 T
+3 F
+( options back to) 445.85 161.33 T
+FMENDPAGE
+%%EndPage: "17" 18
+%%Page: "18" 18
+612 792 0 FMBEGINPAGE
+0 10 Q
+0 X
+0 K
+(18) 98.1 668.33 T
+4 F
+(Tk4.0 Overview and Porting Guide) 359.34 668.33 T
+98.1 660.6 512.1 660.6 2 L
+0.25 H
+0 Z
+N
+98.1 135 512.1 639 R
+7 X
+V
+3 F
+0 X
+(their Tk 3.6 values \050use the) 170.1 632.33 T
+5 F
+(conf) 281.41 632.33 T
+(igure) 305.4 632.33 T
+3 F
+( widget command in Tk 3.6 to see what the) 335.38 632.33 T
+(old values were\051.) 170.1 620.33 T
+1 F
+(Pr) 152.1 605.33 T
+(oblem #12:) 162.46 605.33 T
+3 F
+(Listboxes now return the selection as a string with newlines separating the) 211.88 605.33 T
+(values, rather than a T) 152.1 593.33 T
+(cl, list.) 240.49 593.33 T
+2 F
+(Solution:) 170.1 581.33 T
+3 F
+(Modify your code to handle the new format. Y) 209.25 581.33 T
+(ou can convert the selection) 395.06 581.33 T
+(back into the old list format with a script like the following:) 170.1 569.33 T
+5 9 Q
+(split [selection get] \134n) 179.1 555 T
+1 10 Q
+(Pr) 152.1 541.33 T
+(oblem #13:) 162.46 541.33 T
+3 F
+(Tk 4.0 applications cannot) 211.88 541.33 T
+5 F
+(send) 320.42 541.33 T
+3 F
+( to or be sent from Tk 3.6 applications.) 344.4 541.33 T
+2 F
+(Solution:) 170.1 529.33 T
+3 F
+(The only solution is to upgrade all your applications to Tk 4.0.) 209.25 529.33 T
+1 F
+-0.17 (Pr) 152.1 514.33 P
+-0.17 (oblem #14:) 162.46 514.33 P
+3 F
+-0.17 (In texts,) 211.54 514.33 P
+5 F
+-0.4 (end) 245.91 514.33 P
+3 F
+-0.17 ( now refers to a position just after the \336nal newline, instead of) 263.9 514.33 P
+(the \336nal newline.) 152.1 502.33 T
+2 F
+-0.08 (Solution:) 170.1 490.33 P
+3 F
+-0.08 (If you wish to refer to the \336nal newline, use the index) 209.17 490.33 P
+5 F
+-0.19 (end-1char) 424.98 490.33 P
+3 F
+-0.08 ( instead) 478.95 490.33 P
+(of) 170.1 478.33 T
+5 F
+(end) 180.92 478.33 T
+3 F
+(.) 198.91 478.33 T
+1 F
+(Pr) 152.1 463.33 T
+(oblem #15:) 162.46 463.33 T
+3 F
+(In entry widgets,) 211.88 463.33 T
+5 F
+(sel.last) 281.83 463.33 T
+3 F
+( now refers to the character just after the last) 329.8 463.33 T
+(selected one, rather than the last selected one. The second index for the) 152.1 451.33 T
+5 F
+(delete) 438.81 451.33 T
+3 F
+( widget) 474.79 451.33 T
+(command has changed in the same way) 152.1 439.33 T
+(.) 309.66 439.33 T
+2 F
+(Solution:) 170.1 427.33 T
+3 F
+(Add one to the values used in your scripts.) 209.25 427.33 T
+1 F
+(Pr) 152.1 412.33 T
+(oblem #16:) 162.46 412.33 T
+3 F
+(Because) 211.88 412.33 T
+5 F
+(Any) 247.68 412.33 T
+3 F
+( is implicit in all bindings, bindings trigger when extra modi-) 265.67 412.33 T
+(\336ers are present, whereas they didn\325) 152.1 400.33 T
+(t trigger in Tk 3.6.) 296.24 400.33 T
+2 F
+(Solution:) 170.1 388.33 T
+3 F
+(In most cases it\325) 209.25 388.33 T
+(s probably \336ne to ignore the extra modi\336ers. If you really) 273.93 388.33 T
+-0.12 (don\325) 170.1 376.33 P
+-0.12 (t want any actions to be taken when extra modi\336ers are present, create additional) 188.24 376.33 P
+(bindings for the cases with extra modi\336ers, and specify a single blank character \050or) 170.1 364.33 T
+(any script that does nothing\051 as the script for those bindings. Alternatively) 170.1 352.33 T
+(, you can) 465.93 352.33 T
+(use the) 170.1 340.33 T
+5 F
+(%s) 200.63 340.33 T
+3 F
+( substitution to extract the mouse and modi\336er state in the event binding,) 212.63 340.33 T
+(then you can test this value for modi\336ers you do or don\325) 170.1 328.33 T
+(t want.) 394.5 328.33 T
+1 F
+(Pr) 152.1 313.33 T
+(oblem #17:) 162.46 313.33 T
+3 F
+(In scrollbars there is no longer a) 211.88 313.33 T
+5 F
+(-foreground) 343.17 313.33 T
+3 F
+( or) 409.13 313.33 T
+5 F
+(-activefore-) 422.45 313.33 T
+(ground) 152.1 301.33 T
+3 F
+( option, and) 188.08 301.33 T
+5 F
+(-background) 238.05 301.33 T
+3 F
+( has a dif) 304.02 301.33 T
+(ferent meaning.) 340.2 301.33 T
+2 F
+-0.4 (Solution:) 170.1 289.33 P
+3 F
+-0.4 (Use) 208.85 289.33 P
+5 F
+-0.96 (-troughcolor) 226.49 289.33 P
+3 F
+-0.4 ( everywhere that you used) 298.45 289.33 P
+5 F
+-0.96 (-background) 403.87 289.33 P
+3 F
+-0.4 ( in Tk 3.6,) 469.83 289.33 P
+5 F
+(-background) 170.1 277.33 T
+3 F
+( everywhere you used to use) 236.06 277.33 T
+5 F
+(-foreground) 352.08 277.33 T
+3 F
+(, and) 418.04 277.33 T
+5 F
+(-activeback-) 439.97 277.33 T
+(ground) 170.1 265.33 T
+3 F
+( everywhere you used to use) 206.08 265.33 T
+5 F
+(-activeforeground) 322.1 265.33 T
+3 F
+(.) 424.04 265.33 T
+1 F
+(Pr) 152.1 250.33 T
+(oblem #18:) 162.46 250.33 T
+3 F
+(Options for colors seem to have changed in scale widgets.) 211.88 250.33 T
+2 F
+(Solution:) 170.1 238.33 T
+3 F
+(Use) 209.25 238.33 T
+5 F
+(-background) 227.29 238.33 T
+3 F
+( where you used to use) 293.25 238.33 T
+5 F
+(-sliderforeground) 387.07 238.33 T
+3 F
+(,) 489.02 238.33 T
+5 F
+(-) 170.1 226.33 T
+(troughcolor) 176.1 226.33 T
+3 F
+( where you used to use) 242.06 226.33 T
+5 F
+(-background) 335.88 226.33 T
+3 F
+(, and) 401.84 226.33 T
+5 F
+( -activeback-) 421.27 226.33 T
+(ground) 170.1 214.33 T
+3 F
+( everywhere you used to use) 206.08 214.33 T
+5 F
+(-activeforeground) 322.1 214.33 T
+3 F
+(.) 424.04 214.33 T
+1 F
+(Pr) 152.1 199.33 T
+(oblem #19:) 162.46 199.33 T
+3 F
+(Scale widgets no longer accept hexadecimal or octal numbers in the) 211.88 199.33 T
+5 F
+(set) 485.84 199.33 T
+3 F
+(command or the) 152.1 187.33 T
+5 F
+(-from) 219.55 187.33 T
+3 F
+( and) 249.54 187.33 T
+5 F
+(-to) 268.97 187.33 T
+3 F
+( options.) 286.96 187.33 T
+2 F
+(Solution:) 170.1 175.33 T
+3 F
+(Use) 209.25 175.33 T
+5 F
+(format) 227.29 175.33 T
+3 F
+( or) 263.27 175.33 T
+5 F
+(expr) 276.59 175.33 T
+3 F
+( to convert the values to decimal.) 300.58 175.33 T
+1 F
+(Pr) 152.1 160.33 T
+(oblem #20:) 162.46 160.33 T
+3 F
+(In checkbuttons, radiobuttons, and menu entries, the) 211.88 160.33 T
+5 F
+(-selector) 423.4 160.33 T
+3 F
+( option) 477.37 160.33 T
+(no longer exists.) 152.1 148.33 T
+FMENDPAGE
+%%EndPage: "18" 19
+%%Page: "19" 19
+612 792 0 FMBEGINPAGE
+4 10 Q
+0 X
+0 K
+(13 Summary of Incompatibilites) 98.1 668.33 T
+0 F
+(19) 500.99 668.33 T
+98.1 660.6 512.1 660.6 2 L
+0.25 H
+0 Z
+N
+98.1 135 512.1 639 R
+7 X
+V
+2 F
+0 X
+(Solution:) 170.1 632.33 T
+3 F
+(Use) 209.25 632.33 T
+5 F
+(-selectcolor) 227.29 632.33 T
+3 F
+( instead of) 299.25 632.33 T
+5 F
+(-select) 343.39 632.33 T
+3 F
+(. T) 385.36 632.33 T
+(o specify that no indicator) 395.77 632.33 T
+(should be drawn at all, use the) 170.1 620.33 T
+5 F
+(-indicatoron) 293.9 620.33 T
+3 F
+( option instead of setting) 365.86 620.33 T
+5 F
+(-select) 467.2 620.33 T
+3 F
+(to an empty string.) 170.1 608.33 T
+1 F
+-0.12 (Pr) 152.1 593.33 P
+-0.12 (oblem #21:) 162.46 593.33 P
+3 F
+-0.12 (The indices of menu entries have changed, and operations on menu entry 0) 211.64 593.33 P
+(no longer work.) 152.1 581.33 T
+2 F
+(Solution:) 170.1 569.33 T
+3 F
+(This is because menus now have a tearof) 209.25 569.33 T
+(f entry at the top by default, and) 372.55 569.33 T
+(this occupies entry 0, so your \336rst entry is now entry 1. Y) 170.1 557.33 T
+(ou can either set the) 398.95 557.33 T
+5 F
+(-) 170.1 545.33 T
+(tearoff) 176.1 545.33 T
+3 F
+( option to 0 to eliminate the tearof) 218.07 545.33 T
+(f entry or add 1 to all the indices you) 354.2 545.33 T
+(use in your scripts.) 170.1 533.33 T
+1 F
+-0.22 (Pr) 152.1 518.33 P
+-0.22 (oblem #22:) 162.46 518.33 P
+3 F
+-0.22 (The) 211.44 518.33 P
+5 F
+-0.53 (enable) 229.26 518.33 P
+3 F
+-0.22 ( and) 265.24 518.33 P
+5 F
+-0.53 (disable) 284.23 518.33 P
+3 F
+-0.22 ( widget commands are no longer supported by) 326.21 518.33 P
+(menus.) 152.1 506.33 T
+2 F
+(Solution:) 170.1 494.33 T
+3 F
+(Use the) 209.25 494.33 T
+5 F
+(-state) 242 494.33 T
+3 F
+( con\336guration option instead.) 277.98 494.33 T
+1 F
+(Pr) 152.1 479.33 T
+(oblem #23:) 162.46 479.33 T
+3 F
+(The) 211.88 479.33 T
+5 F
+(activate) 229.92 479.33 T
+3 F
+( and) 277.89 479.33 T
+5 F
+(deactivate) 297.32 479.33 T
+3 F
+( widget commands are no longer sup-) 357.29 479.33 T
+(ported by buttons, checkbuttons, radiobuttons, and menus.) 152.1 467.33 T
+2 F
+(Solution:) 170.1 455.33 T
+3 F
+(Use the) 209.25 455.33 T
+5 F
+(-state) 242 455.33 T
+3 F
+( con\336guration option instead.) 277.98 455.33 T
+1 F
+(Pr) 152.1 440.33 T
+(oblem #24:) 162.46 440.33 T
+3 F
+(Canvas arc items no longer use the) 211.88 440.33 T
+5 F
+(-f) 353.72 440.33 T
+(ill) 365.71 440.33 T
+3 F
+( and) 383.7 440.33 T
+5 F
+(-stipple) 403.13 440.33 T
+3 F
+( options for) 451.11 440.33 T
+(drawing when the) 152.1 428.33 T
+5 F
+(-style) 226.21 428.33 T
+3 F
+( option is) 262.19 428.33 T
+5 F
+(arc) 301.9 428.33 T
+3 F
+(.) 319.89 428.33 T
+2 F
+(Solution:) 170.1 416.33 T
+3 F
+(Use the) 209.25 416.33 T
+5 F
+(-outline) 242 416.33 T
+3 F
+( and) 289.97 416.33 T
+5 F
+(-outlinestipple) 309.4 416.33 T
+3 F
+( options instead.) 399.35 416.33 T
+1 F
+-0.29 (Pr) 152.1 401.33 P
+-0.29 (oblem #25:) 162.46 401.33 P
+3 F
+-0.29 (The variable) 211.29 401.33 P
+5 F
+-0.7 (tkVersion) 263.43 401.33 P
+3 F
+-0.29 ( no longer exists \050it has been obsolete for several) 317.4 401.33 P
+(releases\051.) 152.1 389.33 T
+2 F
+(Solution:) 170.1 377.33 T
+3 F
+(Use) 209.25 377.33 T
+5 F
+(tk_version) 227.29 377.33 T
+3 F
+( instead.) 287.26 377.33 T
+1 F
+(Pr) 152.1 362.33 T
+(oblem #26:) 162.46 362.33 T
+3 F
+(The syntax of the) 211.88 362.33 T
+5 F
+(scan) 284.05 362.33 T
+3 F
+( widget commands for texts has changed.) 308.03 362.33 T
+2 F
+(Solution:) 170.1 350.33 T
+3 F
+(Modify your code to use the new syntax.) 209.25 350.33 T
+1 F
+(Pr) 152.1 335.33 T
+(oblem #27:) 162.46 335.33 T
+5 F
+(wish) 211.88 335.33 T
+3 F
+( no longer recognizes the) 235.86 335.33 T
+5 F
+(-help) 338.84 335.33 T
+3 F
+( option.) 368.82 335.33 T
+2 F
+(Solution:) 170.1 323.33 T
+3 F
+(Implement this option yourself in your) 209.25 323.33 T
+5 F
+(wish) 366.38 323.33 T
+3 F
+( scripts.) 390.37 323.33 T
+1 F
+(Pr) 152.1 308.33 T
+(oblem #28:) 162.46 308.33 T
+3 F
+(Tk 4.0 always prints real numbers such as canvas coordinates with a deci-) 211.88 308.33 T
+(mal point. This can cause syntax errors if you later use them in situations where integers) 152.1 296.33 T
+(are expected.) 152.1 284.33 T
+2 F
+(Solution:) 170.1 272.33 T
+3 F
+(Change your code so that real numbers work OK, or use the) 209.25 272.33 T
+5 F
+(expr) 451.57 272.33 T
+3 F
+( com-) 475.55 272.33 T
+(mand \050with the) 170.1 260.33 T
+5 F
+(round) 233.12 260.33 T
+3 F
+( function\051 to convert the numbers to integers.) 263.1 260.33 T
+1 F
+(Pr) 152.1 245.33 T
+(oblem #29:) 162.46 245.33 T
+3 F
+(The) 211.88 245.33 T
+5 F
+(pack info) 229.92 245.33 T
+3 F
+( command returns dif) 283.89 245.33 T
+(ferent information, and) 369.48 245.33 T
+5 F
+(pack) 464.41 245.33 T
+(newinfo) 152.1 233.33 T
+3 F
+( no longer exists.) 194.08 233.33 T
+2 F
+(Solution:) 170.1 221.33 T
+3 F
+(Use) 209.25 221.33 T
+5 F
+(pack info) 227.29 221.33 T
+3 F
+( where you used to use) 281.26 221.33 T
+5 F
+(pack newinfo) 375.08 221.33 T
+3 F
+(.) 447.04 221.33 T
+5 F
+(Pack info) 452.04 221.33 T
+3 F
+(was obsolete, so it has been eliminated.) 170.1 209.33 T
+1 F
+(Pr) 152.1 194.33 T
+(oblem #30:) 162.46 194.33 T
+3 F
+(The) 211.88 194.33 T
+5 F
+(view) 229.92 194.33 T
+3 F
+( widget command for entries no longer exists, nor does the) 253.9 194.33 T
+5 F
+(-) 152.1 182.33 T
+(scrollcommand) 158.1 182.33 T
+3 F
+( option.) 236.05 182.33 T
+2 F
+-0.29 (Solution:) 170.1 170.33 P
+3 F
+-0.29 (Use) 208.96 170.33 P
+5 F
+-0.69 (xview) 226.71 170.33 P
+3 F
+-0.29 ( where you used to use) 256.7 170.33 P
+5 F
+-0.69 (view) 348.8 170.33 P
+3 F
+-0.29 (; use) 372.78 170.33 P
+5 F
+-0.69 (-xscrollcommand) 393.31 170.33 P
+3 F
+-0.29 ( where) 483.26 170.33 P
+(you used to use) 170.1 158.33 T
+5 F
+(-scrollcommand) 234.51 158.33 T
+3 F
+(.) 318.46 158.33 T
+FMENDPAGE
+%%EndPage: "19" 20
+%%Page: "20" 20
+612 792 0 FMBEGINPAGE
+0 10 Q
+0 X
+0 K
+(20) 98.1 668.33 T
+4 F
+(Tk4.0 Overview and Porting Guide) 359.34 668.33 T
+98.1 660.6 512.1 660.6 2 L
+0.25 H
+0 Z
+N
+98.1 135 512.1 639 R
+7 X
+V
+1 F
+0 X
+(Pr) 152.1 632.33 T
+(oblem #31:) 162.46 632.33 T
+3 F
+(The) 211.88 632.33 T
+5 F
+(-padx) 229.92 632.33 T
+3 F
+( and) 259.9 632.33 T
+5 F
+(-pady) 279.33 632.33 T
+3 F
+( options are ignored for the button family of wid-) 309.31 632.33 T
+(gets if a bitmap or image is being displayed: the padding is always 0.) 152.1 620.02 T
+2 F
+-0.27 (Solution:) 170.1 608.02 P
+3 F
+-0.27 (Pack the button inside a frame, with extra padding in the frame. Or) 208.98 608.02 P
+-0.27 (, redo the) 472.94 608.02 P
+(image or bitmap to incorporate padding into it.) 170.1 595.71 T
+1 F
+(Pr) 152.1 580.71 T
+(oblem #32:) 162.46 580.71 T
+3 F
+(In radiobuttons, the) 211.88 580.71 T
+5 F
+(-value) 292.38 580.71 T
+3 F
+( option no longer defaults to the name of the) 328.36 580.71 T
+(widget; it defaults to an empty string.) 152.1 568.4 T
+2 F
+(Solution:) 170.1 556.4 T
+3 F
+(Specify the widget\325) 209.25 556.4 T
+(s name explicitly as the value of the option.) 286.98 556.4 T
+1 F
+(Pr) 152.1 541.4 T
+(oblem #33:) 162.46 541.4 T
+3 F
+(The) 211.88 541.4 T
+5 F
+(-menu) 229.92 541.4 T
+3 F
+( option for menubuttons and cascade menu entries may refer) 259.9 541.4 T
+(only to a child of the menubutton or menu.) 152.1 529.08 T
+2 F
+(Solution:) 170.1 517.08 T
+3 F
+(Rename menus to meet this requirement.) 209.25 517.08 T
+1 F
+(Pr) 152.1 502.08 T
+(oblem #34:) 162.46 502.08 T
+3 F
+(The interpretation of) 211.88 502.08 T
+5 F
+(@y) 297.09 502.08 T
+3 F
+( in menus has changed: it never returns) 309.08 502.08 T
+5 F
+(none) 467.86 502.08 T
+3 F
+(,) 491.84 502.08 T
+(even if the y-coordinate is outside the menu \050it returns the index of the closest entry\051.) 152.1 489.77 T
+2 F
+(Solution:) 170.1 477.77 T
+3 F
+(If you care about this distinction, check the y-coordinate explicitly to see if) 209.25 477.77 T
+-0.17 (it is less than 0 or greater than or equal to the window\325) 170.1 465.46 P
+-0.17 (s height \050use) 385.7 465.46 P
+5 F
+-0.41 (winfo height) 438.21 465.46 P
+3 F
+(to get the height\051.) 170.1 453.15 T
+1 F
+-0.13 (Pr) 152.1 438.15 P
+-0.13 (oblem #35:) 162.46 438.15 P
+3 F
+-0.13 (The) 211.62 438.15 P
+5 F
+-0.3 (invoke) 229.54 438.15 P
+3 F
+-0.13 ( and) 265.52 438.15 P
+5 F
+-0.3 (activate) 284.7 438.15 P
+3 F
+-0.13 ( widget commands for menus no longer post) 332.67 438.15 P
+(cascaded submenus.) 152.1 425.83 T
+2 F
+(Solution:) 170.1 413.83 T
+3 F
+(Use the) 209.25 413.83 T
+5 F
+(postcascade) 242 413.83 T
+3 F
+( widget command to post submenus.) 307.96 413.83 T
+1 F
+(Pr) 152.1 398.83 T
+(oblem #36:) 162.46 398.83 T
+3 F
+(The selection tar) 211.88 398.83 T
+(gets) 278.31 398.83 T
+5 F
+(APPLICATION) 296.91 398.83 T
+3 F
+( and) 362.87 398.83 T
+5 F
+(WINDOW_NAME) 382.3 398.83 T
+3 F
+( are no longer) 448.27 398.83 T
+(supported.) 152.1 386.52 T
+2 F
+(Solution:) 170.1 374.52 T
+3 F
+(Use tar) 209.25 374.52 T
+(gets) 237.65 374.52 T
+5 F
+(TK_APPLICATION) 256.25 374.52 T
+3 F
+( and) 340.21 374.52 T
+5 F
+(TK_WINDOW) 359.64 374.52 T
+3 F
+( instead.) 413.61 374.52 T
+1 F
+(Pr) 152.1 359.52 T
+(oblem #37:) 162.46 359.52 T
+3 F
+(There is no longer a default focus.) 211.88 359.52 T
+2 F
+(Solution:) 170.1 347.52 T
+3 F
+(None: modify your code not to depend on this feature.) 209.25 347.52 T
+1 F
+(Pr) 152.1 332.52 T
+(oblem #38:) 162.46 332.52 T
+3 F
+(The) 211.88 332.52 T
+5 F
+(focus) 229.92 332.52 T
+3 F
+( command now returns an empty string to indicate that the) 259.9 332.52 T
+(application doesn\325) 152.1 320.21 T
+(t have the input focus, instead of) 225.48 320.21 T
+5 F
+(none) 358.17 320.21 T
+3 F
+(.) 382.15 320.21 T
+2 F
+(Solution:) 170.1 308.21 T
+3 F
+(Modify your code to check for an empty string instead of) 209.25 308.21 T
+5 F
+(none) 440.47 308.21 T
+3 F
+(.) 464.46 308.21 T
+1 F
+(Pr) 152.1 293.21 T
+(oblem #39:) 162.46 293.21 T
+5 F
+(FocusIn) 211.88 293.21 T
+3 F
+( and) 253.85 293.21 T
+5 F
+(FocusOut) 273.28 293.21 T
+3 F
+( events are delivered to more windows than) 321.26 293.21 T
+(they used to be.) 152.1 280.9 T
+2 F
+-0.02 (Solution:) 170.1 268.9 P
+3 F
+-0.02 (Modify your code to use the new set of events. The old event set was some-) 209.23 268.9 P
+(what bizarre, and the new set matches more closely what happens elsewhere, such as) 170.1 256.58 T
+(with) 170.1 244.27 T
+5 F
+(Enter) 190.37 244.27 T
+3 F
+( and) 220.35 244.27 T
+5 F
+(Leave) 239.78 244.27 T
+3 F
+( events.) 269.77 244.27 T
+1 F
+-0.28 (Pr) 152.1 229.27 P
+-0.28 (oblem #40:) 162.46 229.27 P
+5 F
+-0.67 (wm maxsize) 211.32 229.27 P
+3 F
+-0.28 ( and) 270.62 229.27 P
+5 F
+-0.67 (wm minsize) 289.49 229.27 P
+3 F
+-0.28 ( no longer accept empty ar) 348.79 229.27 P
+-0.28 (guments. This) 453.52 229.27 P
+(means that you cannot use these commands to make windows non-resizable.) 152.1 216.96 T
+2 F
+(Solution:) 170.1 204.96 T
+3 F
+(Use the) 209.25 204.96 T
+5 F
+(wm resizable) 242 204.96 T
+3 F
+( command to make windows resizable.) 313.96 204.96 T
+1 F
+(Pr) 152.1 189.96 T
+(oblem #41:) 162.46 189.96 T
+3 F
+(In the placer) 211.88 189.96 T
+(, if you specify both) 261.43 189.96 T
+5 F
+(-x) 344.15 189.96 T
+3 F
+( and) 356.15 189.96 T
+5 F
+(-relx) 375.58 189.96 T
+3 F
+( then they add, instead of) 405.56 189.96 T
+(the most recent speci\336cation replacing the earlier one. Ditto for) 152.1 177.65 T
+5 F
+(-y) 407.74 177.65 T
+3 F
+( and) 419.73 177.65 T
+5 F
+(-rely) 439.16 177.65 T
+3 F
+(,) 468.5 177.65 T
+5 F
+(-width) 473.49 177.65 T
+3 F
+(and) 152.1 165.33 T
+5 F
+(-relwidth) 169.03 165.33 T
+3 F
+(, and) 223 165.33 T
+5 F
+(-height) 244.93 165.33 T
+3 F
+( and) 286.91 165.33 T
+5 F
+(-relheight) 306.33 165.33 T
+3 F
+(.) 366.3 165.33 T
+2 F
+(Solution:) 170.1 153.33 T
+3 F
+(If you no longer want one of these options to be used, set it to 0 explicitly) 209.25 153.33 T
+(.) 503.14 153.33 T
+1 F
+(Pr) 152.1 138.33 T
+(oblem #42:) 162.46 138.33 T
+3 F
+(The command \322) 211.88 138.33 T
+5 F
+(focus none) 276.27 138.33 T
+3 F
+(\323 doesn\325) 336.24 138.33 T
+(t work in Tk 4.0.) 369.64 138.33 T
+FMENDPAGE
+%%EndPage: "20" 21
+%%Page: "21" 21
+612 792 0 FMBEGINPAGE
+4 10 Q
+0 X
+0 K
+(13 Summary of Incompatibilites) 98.1 668.33 T
+0 F
+(21) 500.99 668.33 T
+98.1 660.6 512.1 660.6 2 L
+0.25 H
+0 Z
+N
+98.1 135 512.1 639 R
+7 X
+V
+2 F
+0 X
+(Solution:) 170.1 632.33 T
+3 F
+(Create a dummy widget that is never mapped and set the focus to that wid-) 209.25 632.33 T
+(get.) 170.1 620.33 T
+1 F
+(Pr) 152.1 605.33 T
+(oblem #43:) 162.46 605.33 T
+5 F
+(%D) 211.88 605.33 T
+3 F
+( substitutions are no longer supported in bindings, nor are the event) 223.87 605.33 T
+(types) 152.1 593.33 T
+5 F
+(CirculateRequest) 175.7 593.33 T
+3 F
+(,) 271.64 593.33 T
+5 F
+(Conf) 276.64 593.33 T
+(igureRequest) 300.63 593.33 T
+3 F
+(,) 372.59 593.33 T
+5 F
+(MapRequest) 377.59 593.33 T
+3 F
+(, and) 437.55 593.33 T
+5 F
+(Resiz-) 459.48 593.33 T
+(eRequest) 152.1 581.33 T
+3 F
+(.) 200.07 581.33 T
+2 F
+-0.25 (Solution:) 170.1 569.33 P
+3 F
+-0.25 (Use the name of the display instead of %D to identify a display; you can get) 209 569.33 P
+(the display name with the) 170.1 557.33 T
+5 F
+(winfo screen) 275.31 557.33 T
+3 F
+( command. The desupported event types) 347.27 557.33 T
+(never really worked anyway) 170.1 545.33 T
+(, so there should be no code that depends on them.) 282.96 545.33 T
+1 F
+(Pr) 152.1 530.33 T
+(oblem #44:) 162.46 530.33 T
+5 F
+(%) 211.88 530.33 T
+3 F
+( binding substitutions that return window identi\336ers, such as) 217.87 530.33 T
+5 F
+(%a) 461.63 530.33 T
+3 F
+( and) 473.62 530.33 T
+5 F
+(%S) 493.05 530.33 T
+3 F
+(,) 505.05 530.33 T
+(now produce hexadecimal results instead of decimal.) 152.1 518.33 T
+2 F
+(Solution:) 170.1 506.33 T
+3 F
+(Use the) 209.25 506.33 T
+5 F
+(format) 242 506.33 T
+3 F
+( command to turn them back to decimal.) 277.98 506.33 T
+1 F
+(Pr) 152.1 491.33 T
+(oblem #45:) 162.46 491.33 T
+5 F
+(Enter) 211.88 491.33 T
+3 F
+(,) 241.46 491.33 T
+5 F
+(Leave) 246.46 491.33 T
+3 F
+(,) 276.44 491.33 T
+5 F
+(FocusIn) 281.44 491.33 T
+3 F
+(, and) 323.42 491.33 T
+5 F
+(FocusOut) 345.34 491.33 T
+3 F
+( events with detail) 393.32 491.33 T
+5 F
+(Notify-) 468.83 491.33 T
+(Inferior) 152.1 479.33 T
+3 F
+( are now ignored by the binding mechanism, so they\325re not visible to T) 200.07 479.33 T
+(cl) 483.08 479.33 T
+(scripts.) 152.1 467.33 T
+2 F
+-0.13 (Solution:) 170.1 455.33 P
+3 F
+-0.13 (In most cases, T) 209.12 455.33 P
+-0.13 (cl scripts work better if these bindings are ignored. Y) 273 455.33 P
+-0.13 (ou can) 483.49 455.33 P
+(still use C code to access these events if you really need them. Or) 170.1 443.33 T
+(, create bindings on) 431.18 443.33 T
+-0.33 (the inferior windows and use) 170.1 431.33 P
+5 F
+-0.8 (NotifyAncestor) 286.96 431.33 P
+3 F
+-0.33 ( bindings on the children instead of) 370.91 431.33 P
+5 F
+(NotifyInferior) 170.1 419.33 T
+3 F
+( bindings on the parent.) 254.05 419.33 T
+FMENDPAGE
+%%EndPage: "21" 22
+%%Page: "22" 22
+612 792 0 FMBEGINPAGE
+0 10 Q
+0 X
+0 K
+(22) 98.1 668.33 T
+4 F
+(Tk4.0 Overview and Porting Guide) 359.34 668.33 T
+98.1 660.6 512.1 660.6 2 L
+0.25 H
+0 Z
+N
+98.1 135 512.1 639 R
+7 X
+V
+FMENDPAGE
+%%EndPage: "22" 23
+%%Trailer
+%%BoundingBox: 0 0 612 792
+%%Pages: 22 1
+%%DocumentFonts: Helvetica-Bold
+%%+ Times-Bold
+%%+ Times-Italic
+%%+ Times-Roman
+%%+ Helvetica
+%%+ Courier
+%%+ Courier-Oblique
diff --git a/tk8.6/doc/tk_mac.n b/tk8.6/doc/tk_mac.n
new file mode 100644
index 0000000..bf338b6
--- /dev/null
+++ b/tk8.6/doc/tk_mac.n
@@ -0,0 +1,306 @@
+'\"
+'\" Copyright (c) 2011 Kevin Walzer.
+'\" Copyright (c) 2011 Donal K. Fellows.
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH tk::mac n 8.6 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+tk::mac \- Access Mac-Specific Functionality on OS X from Tk
+.SH SYNOPSIS
+.nf
+\fB::tk::mac::DoScriptFile\fR
+\fB::tk::mac::DoScriptText\fR
+\fB::tk::mac::ShowPreferences\fR
+\fB::tk::mac::OpenApplication\fR
+\fB::tk::mac::ReopenApplication\fR
+\fB::tk::mac::OpenDocument \fIfile...\fR
+\fB::tk::mac::PrintDocument \fIfile...\fR
+\fB::tk::mac::Quit\fR
+\fB::tk::mac::OnHide\fR
+\fB::tk::mac::OnShow\fR
+\fB::tk::mac::ShowHelp\fR
+\fB::tk::mac::PerformService\fR
+\fB::tk::mac::LaunchURL \fIURL...\fR
+\fB::tk::mac::GetAppPath\fR
+
+\fB::tk::mac::standardAboutPanel\fR
+
+\fB::tk::mac::useCompatibilityMetrics \fIboolean\fR
+\fB::tk::mac::CGAntialiasLimit \fIlimit\fR
+\fB::tk::mac::antialiasedtext \fInumber\fR
+\fB::tk::mac::useThemedToplevel \fIboolean\fR
+
+
+\fB::tk::mac::iconBitmap \fIname width height \-kind value\fR
+.fi
+.BE
+.SH "EVENT HANDLER CALLBACKS"
+.PP
+The Aqua/Mac OS X application environment defines a number of additional
+events that applications should respond to. These events are mapped by Tk to
+calls to commands in the \fB::tk::mac\fR namespace; unless otherwise noted, if
+the command is absent, no action will be taken.
+.TP
+\fB::tk::mac::DoScriptFile\fR
+.
+The default Apple Event handler for AEDoScriptHandler. This command,
+if defined, executes a Tcl file when an AppleScript sends a
+.QW "do script"
+command to Wish with a file path as a parameter.
+.TP
+\fB::tk::mac::DoScriptText\fR
+.
+The default Apple Event handler for AEDoScriptHandler. This command,
+if defined, executes Tcl code when an AppleScript sends a
+.QW "do script"
+command to Wish with Tcl code or a Tcl procedure as a parameter.
+.TP
+\fB::tk::mac::ShowPreferences\fR
+.
+The default Apple Event handler for kAEShowPreferences,
+.QW pref .
+The application menu
+.QW "Preferences"
+menu item is only enabled when this proc is defined. Typically this command is
+used to wrap a specific own preferences command, which pops up a preferences
+window. Something like:
+.RS
+.PP
+.CS
+proc ::tk::mac::ShowPreferences {} {
+ setPref
+}
+.CE
+.RE
+.TP
+\fB::tk::mac::OpenApplication\fR
+.
+If a proc of this name is defined, this proc fill fire when your application
+is initially opened. It is the default Apple Event handler for
+kAEOpenApplication,
+.QW oapp .
+.TP
+\fB::tk::mac::ReopenApplication\fR
+.
+If a proc of this name is defined it is the default Apple Event handler for
+kAEReopenApplication,
+.QW rapp ,
+the Apple Event sent when your application is opened when it is already
+running (e.g. by clicking its icon in the Dock). Here is a sample that raises
+a minimized window when the Dock icon is clicked:
+.RS
+.PP
+.CS
+proc ::tk::mac::ReopenApplication {} {
+ if {[wm state .] eq "withdrawn"} {
+ wm state . normal
+ } else {
+ wm deiconify .
+ }
+ raise .
+}
+.CE
+.RE
+.TP
+\fB::tk::mac::OpenDocument \fIfile...\fR
+.
+If a proc of this name is defined it is the default Apple Event handler for
+kAEOpenDocuments,
+.QW odoc ,
+the Apple Event sent when your application is asked to open one or more
+documents (e.g., by drag & drop onto the app or by opening a document of a
+type associated to the app). The proc should take as arguments paths to the
+files to be opened, like so:
+.RS
+.PP
+.CS
+proc ::tk::mac::OpenDocument {args} {
+ foreach f $args {my_open_document $f}
+}
+.CE
+.RE
+.TP
+\fB::tk::mac::PrintDocument \fIfile...\fR
+.
+If a proc of this name is defined it is the default Apple Event handler for
+kAEPrintDocuments,
+.QW pdoc ,
+the Apple Event sent when your application is asked to print a
+document. It takes a single absolute file path as an argument.
+.TP
+\fB::tk::mac::Quit\fR
+.
+If a proc of this name is defined it is the default Apple Event handler for
+kAEQuitApplication,
+.QW quit ,
+the Apple Event sent when your application is asked to be quit, e.g. via the
+quit menu item in the application menu, the quit menu item in the Dock menu,
+or during a logout/restart/shutdown etc. If this is not defined, \fBexit\fR is
+called instead.
+.TP
+\fB::tk::mac::OnHide\fR
+.
+If defined, this is called when your application receives a kEventAppHidden
+event, e.g. via the hide menu item in the application or Dock menus.
+.TP
+\fB::tk::mac::OnShow\fR
+.
+If defined, this is called when your application receives a kEventAppShown
+event, e.g. via the show all menu item in the application menu, or by clicking
+the Dock icon of a hidden application.
+.TP
+\fB::tk::mac::ShowHelp\fR
+.
+Customizes behavior of Apple Help menu; if this procedure is not defined, the
+platform-specific standard Help menu item
+.QW "YourApp Help"
+performs the default Cocoa action of showing the Help Book configured in the
+application's Info.plist (or displaying an alert if no Help Book is
+set).
+.TP
+\fB::tk::mac::PerformService\fR
+.
+Executes a Tcl procedure called from the macOS
+.QW Services
+menu in the Application menu item. The
+.QW Services
+menu item allows for inter-application communication; data from one
+application, such as selected text, can be sent to another application
+for processing, for example to Safari as a search item for Google, or
+to TextEdit to be appended to a file. An example of the proc is below,
+and should be rewritten in an application script for customization:
+.RS
+.PP
+.CS
+proc ::tk::mac::PerformService {} {
+ set data [clipboard get]
+ $w insert end $data
+}
+.CE
+.RE
+Note that the mechanism for retrieving the data is from the clipboard;
+there is no other supported way to obtain the data. If the Services
+process is not desired, the NSServices keys can be deleted from
+the application's Info.plist file. The underlying code supporting this
+command also allows the text, entry and ttk::entry widgets to access
+services from other applications via the Services menu. The NSPortName
+key in Wish's Info.plist file is currently set as
+.QW "Wish"
+; if a developer changes the name of the Wish executable to something
+ else, this key should be modified with the same name.
+.TP
+\fB::tk::mac::LaunchURL \fIURL...\fR
+.
+If defined, launches a URL within Tk. This would be used if a Tk
+application wants to handle a URL itself, such as displaying data from
+an RSS feed, rather than launching a default application to handle the
+URL, although it can defined as such. Wish includes a stub URL scheme
+of
+.QW foo://
+in the CFBundleURLSchemes key of its Info.plist file; this should be customized for the specific URL
+scheme the developer wants to support.
+.TP
+\fB::tk::mac::GetAppPath\fR
+.
+Returns the current applications's file path.
+.TP
+
+
+.SH "ADDITIONAL DIALOGS"
+.PP
+The Aqua/Mac OS X defines additional dialogs that applications should
+support.
+.TP
+\fB::tk::mac::standardAboutPanel\fR
+.
+Brings the standard Cocoa about panel to the front, with all its information
+filled in from your application bundle files (standard about panel with no
+options specified). See Apple Technote TN2179 and the AppKit documentation for
+-[NSApplication orderFrontStandardAboutPanelWithOptions:] for details on the
+Info.plist keys and app bundle files used by the about panel.
+.SH "SYSTEM CONFIGURATION"
+.PP
+There are a number of additional global configuration options that control the
+details of how Tk renders by default.
+.TP
+\fB::tk::mac::useCompatibilityMetrics \fIboolean\fR
+.
+Preserves compatibility with older Tk/Aqua metrics; set to \fBfalse\fR for
+more native spacing.
+.TP
+\fB::tk::mac::CGAntialiasLimit \fIlimit\fR
+.
+Sets the antialiasing limit; lines thinner that \fIlimit\fR pixels will not be
+antialiased. Integer, set to 0 by default, making all lines be antialiased.
+.TP
+\fB::tk::mac::antialiasedtext \fInumber\fR
+.
+Sets anti-aliased text. Controls text antialiasing, possible values for
+\fInumber\fR are -1 (default, use system default for text AA), 0 (no text AA),
+1 (use text AA).
+.TP
+\fB::tk::mac::useThemedToplevel \fIboolean\fR
+.
+Sets toplevel windows to draw with the modern grayish/ pinstripe Mac
+background. Equivalent to configuring the toplevel with
+.QW "\fB\-background systemWindowHeaderBackground\fR" ,
+or to using a \fBttk::frame\fR.
+.SH "SUPPORT COMMANDS"
+.TP
+\fB::tk::mac::iconBitmap \fIname width height \-kind value\fR
+.
+Renders native icons and bitmaps in Tk applications (including any image file
+readable by NSImage). A native bitmap name is interpreted as follows (in
+order):
+.RS
+.IP \(bu 3
+predefined builtin 32x32 icon name (\fBstop\fR, \fBcaution\fR, \fBdocument\fR,
+etc.)
+.IP \(bu 3
+\fIname\fR, as defined by \fBtk::mac::iconBitmap\fR
+.IP \(bu 3
+NSImage named image name
+.IP \(bu 3
+NSImage url string
+.IP \(bu 3
+4-char OSType of IconServices icon
+.PP
+The \fIwidth\fR and \fIheight\fR arguments to \fBtk::mac::iconBitmap\fR define
+the dimensions of the image to create, and \fI\-kind\fR must be one of:
+.TP
+\fB\-file\fR
+.
+icon of file at given path
+.TP
+\fB\-fileType\fR
+.
+icon of given file type
+.TP
+\fB\-osType\fR
+.
+icon of given 4-char OSType file type
+.TP
+\fB\-systemType\fR
+.
+icon for given IconServices 4-char OSType
+.TP
+\fB\-namedImage\fR
+.
+named NSImage for given name
+.TP
+\fB\-imageFile\fR
+.
+image at given path
+.RE
+.SH "SEE ALSO"
+bind(n), wm(n)
+.SH KEYWORDS
+about dialog, antialiasing, Apple event, icon, NSImage
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/tkerror.n b/tk8.6/doc/tkerror.n
new file mode 100644
index 0000000..53cb0d1
--- /dev/null
+++ b/tk8.6/doc/tkerror.n
@@ -0,0 +1,37 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH tkerror n 4.1 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+tkerror \- Command invoked to process background errors
+.SH SYNOPSIS
+\fBtkerror \fImessage\fR
+.BE
+.SH DESCRIPTION
+.PP
+Note: as of Tk 4.1 the \fBtkerror\fR command has been renamed to
+\fBbgerror\fR because the event loop (which is what usually invokes
+it) is now part of Tcl. For backward compatibility
+the \fBbgerror\fR provided by the current Tk version still
+tries to call \fBtkerror\fR if there is one (or an auto loadable one),
+so old script defining that error handler should still work, but you
+should anyhow modify your scripts to use \fBbgerror\fR instead
+of \fBtkerror\fR because that support for the old name might vanish
+in the near future. If that call fails, \fBbgerror\fR
+posts a dialog showing the error and offering to see the stack trace
+to the user. If you want your own error management you should
+directly override \fBbgerror\fR instead of \fBtkerror\fR.
+Documentation for \fBbgerror\fR is available as part of Tcl's
+documentation.
+.SH KEYWORDS
+background error, reporting
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/tkvars.n b/tk8.6/doc/tkvars.n
new file mode 100644
index 0000000..a80fd54
--- /dev/null
+++ b/tk8.6/doc/tkvars.n
@@ -0,0 +1,110 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH tkvars n 4.1 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+geometry, tk_library, tk_patchLevel, tk_strictMotif, tk_version \- Variables used or set by Tk
+.BE
+.SH DESCRIPTION
+.PP
+The following Tcl variables are either set or used by Tk at various times
+in its execution:
+.TP 15
+\fBtk_library\fR
+.
+This variable holds the file name for a directory containing a library
+of Tcl scripts related to Tk. These scripts include an initialization
+file that is normally processed whenever a Tk application starts up,
+plus other files containing procedures that implement default behaviors
+for widgets.
+.RS
+.PP
+The initial value of \fBtcl_library\fR is set when Tk is added to
+an interpreter; this is done by searching several different directories
+until one is found that contains an appropriate Tk startup script.
+If the \fBTK_LIBRARY\fR environment variable exists, then
+the directory it names is checked first.
+If \fBTK_LIBRARY\fR is not set or does not refer to an appropriate
+directory, then Tk checks several other directories based on a
+compiled-in default location, the location of the Tcl library directory,
+the location of the binary containing the application, and the current
+working directory.
+.PP
+The variable can be modified by an application to switch to a different
+library.
+.RE
+.TP
+\fBtk_patchLevel\fR
+.
+Contains a dot-separated sequence of decimal integers giving the
+current patch level for Tk.
+The patch level is incremented for each new release or patch, and
+it uniquely identifies an official version of Tk.
+.RS
+.PP
+This value is normally the same as the result of
+.QW "\fBpackage require\fR \fBTk\fR" .
+.RE
+.TP
+\fBtk_strictMotif\fR
+.
+This variable is set to zero by default.
+If an application sets it to one, then Tk attempts to adhere as
+closely as possible to Motif look-and-feel standards.
+For example, active elements such as buttons and scrollbar
+sliders will not change color when the pointer passes over them.
+Modern applications should not normally set this variable.
+.TP 15
+\fBtk_version\fR
+.
+Tk sets this variable in the interpreter for each application.
+The variable holds the current version number of the Tk
+library in the form \fImajor\fR.\fIminor\fR. \fIMajor\fR and
+\fIminor\fR are integers. The major version number increases in
+any Tk release that includes changes that are not backward compatible
+(i.e. whenever existing Tk applications and scripts may have to change to
+work with the new release). The minor version number increases with
+each new release of Tk, except that it resets to zero whenever the
+major version number changes.
+.SS "INTERNAL AND DEBUGGING VARIABLES"
+.PP
+These variables should not normally be set by user code.
+.TP
+\fBtk::Priv\fR
+.
+This variable is an array containing several pieces of information
+that are private to Tk. The elements of \fBtk::Priv\fR are used by
+Tk library procedures and default bindings.
+They should not be accessed by any code outside Tk.
+.TP
+\fBtk_textRedraw\fR
+.TP
+\fBtk_textRelayout\fR
+.
+These variables are set by text widgets when they have debugging
+turned on. The values written to these variables can be used to
+test or debug text widget operations. These variables are mostly
+used by Tk's test suite.
+.SH "OTHER GLOBAL VARIABLES"
+The following variables are only guaranteed to exist in \fBwish\fR
+executables; the Tk library does not define them itself but many Tk
+environments do.
+.TP 6
+\fBgeometry\fR
+.
+If set, contains the user-supplied geometry specification to use for
+the main Tk window.
+.SH "SEE ALSO"
+package(n), tclvars(n), wish(1)
+.SH KEYWORDS
+environment, text, variables, version
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/tkwait.n b/tk8.6/doc/tkwait.n
new file mode 100644
index 0000000..a31aee7
--- /dev/null
+++ b/tk8.6/doc/tkwait.n
@@ -0,0 +1,52 @@
+'\"
+'\" Copyright (c) 1992 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH tkwait n "" Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+tkwait \- Wait for variable to change or window to be destroyed
+.SH SYNOPSIS
+\fBtkwait variable \fIname\fR
+.sp
+\fBtkwait visibility \fIname\fR
+.sp
+\fBtkwait window \fIname\fR
+.BE
+.SH DESCRIPTION
+.PP
+The \fBtkwait\fR command waits for one of several things to happen,
+then it returns without taking any other actions.
+The return value is always an empty string.
+If the first argument is \fBvariable\fR (or any abbreviation of
+it) then the second argument is the name of a global variable and the
+command waits for that variable to be modified.
+If the first argument is \fBvisibility\fR (or any abbreviation
+of it) then the second argument is the name of a window and the
+\fBtkwait\fR command waits for a change in its
+visibility state (as indicated by the arrival of a VisibilityNotify
+event). This form is typically used to wait for a newly-created
+window to appear on the screen before taking some action.
+If the first argument is \fBwindow\fR (or any abbreviation
+of it) then the second argument is the name of a window and the
+\fBtkwait\fR command waits for that window to be destroyed.
+This form is typically used to wait for a user to finish interacting
+with a dialog box before using the result of that interaction.
+.PP
+While the \fBtkwait\fR command is waiting it processes events in
+the normal fashion, so the application will continue to respond
+to user interactions.
+If an event handler invokes \fBtkwait\fR again, the nested call
+to \fBtkwait\fR must complete before the outer call can complete.
+.SH "SEE ALSO"
+bind(n), vwait(n)
+.SH KEYWORDS
+variable, visibility, wait, window
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/toplevel.n b/tk8.6/doc/toplevel.n
new file mode 100644
index 0000000..84fab14
--- /dev/null
+++ b/tk8.6/doc/toplevel.n
@@ -0,0 +1,163 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH toplevel n 8.4 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+toplevel \- Create and manipulate 'toplevel' main and popup window widgets
+.SH SYNOPSIS
+\fBtoplevel\fR \fIpathName \fR?\fIoptions\fR?
+.SO
+\-borderwidth \-highlightcolor \-pady
+\-cursor \-highlightthickness \-relief
+\-highlightbackground \-padx \-takefocus
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-background background Background
+This option is the same as the standard \fB\-background\fR option
+except that its value may also be specified as an empty string.
+In this case, the widget will display no background or border, and
+no colors will be consumed from its colormap for its background
+and border.
+.OP \-class class Class
+Specifies a class for the window.
+This class will be used when querying the option database for
+the window's other options, and it will also be used later for
+other purposes such as bindings.
+The \fB\-class\fR option may not be changed with the \fBconfigure\fR
+widget command.
+.OP \-colormap colormap Colormap
+Specifies a colormap to use for the window.
+The value may be either \fBnew\fR, in which case a new colormap is
+created for the window and its children, or the name of another
+window (which must be on the same screen and have the same visual
+as \fIpathName\fR), in which case the new window will use the colormap
+from the specified window.
+If the \fB\-colormap\fR option is not specified, the new window
+uses the default colormap of its screen.
+This option may not be changed with the \fBconfigure\fR
+widget command.
+.OP \-container container Container
+The value must be a boolean. If true, it means that this window will
+be used as a container in which some other application will be embedded
+(for example, a Tk toplevel can be embedded using the \fB\-use\fR option).
+The window will support the appropriate window manager protocols for
+things like geometry requests. The window should not have any
+children of its own in this application.
+This option may not be changed with the \fBconfigure\fR
+widget command.
+.OP \-height height Height
+Specifies the desired height for the window in any of the forms
+acceptable to \fBTk_GetPixels\fR.
+If this option is less than or equal to zero then the window will
+not request any size at all.
+.OP \-menu menu Menu
+Specifies a menu widget to be used as a menubar. On the Macintosh, the
+menubar will be displayed across the top of the main monitor. On
+Microsoft Windows and all UNIX platforms, the menu will appear across
+the toplevel window as part of the window dressing maintained by the
+window manager.
+.OP \-screen "" ""
+Specifies the screen on which to place the new window.
+Any valid screen name may be used, even one associated with a
+different display.
+Defaults to the same screen as its parent.
+This option is special in that it may not be specified via the option
+database, and it may not be modified with the \fBconfigure\fR
+widget command.
+.OP \-use use Use
+This option is used for embedding. If the value is not an empty string,
+it must be the window identifier of a container window, specified as
+a hexadecimal string like the ones returned by the \fBwinfo id\fR
+command. The toplevel widget will be created as a child of the given
+container instead of the root window for the screen. If the container
+window is in a Tk application, it must be a frame or toplevel widget for
+which the \fB\-container\fR option was specified.
+This option may not be changed with the \fBconfigure\fR
+widget command.
+.OP \-visual visual Visual
+Specifies visual information for the new window in any of the
+forms accepted by \fBTk_GetVisual\fR.
+If this option is not specified, the new window will use the default
+visual for its screen.
+The \fB\-visual\fR option may not be modified with the \fBconfigure\fR
+widget command.
+.OP \-width width Width
+Specifies the desired width for the window in any of the forms
+acceptable to \fBTk_GetPixels\fR.
+If this option is less than or equal to zero then the window will
+not request any size at all.
+.BE
+.SH DESCRIPTION
+.PP
+The \fBtoplevel\fR command creates a new toplevel widget (given
+by the \fIpathName\fR argument). Additional
+options, described above, may be specified on the command line
+or in the option database
+to configure aspects of the toplevel such as its background color
+and relief. The \fBtoplevel\fR command returns the
+path name of the new window.
+.PP
+A toplevel is similar to a \fBframe\fR except that it is created as a
+top-level window: its X parent is the root window of a screen
+rather than the logical parent from its Tk path name. The primary
+purpose of a toplevel is to serve as a container for dialog boxes
+and other collections of widgets. The only visible features
+of a toplevel are its background color and an optional 3-D border
+to make the toplevel appear raised or sunken.
+.SH "WIDGET COMMAND"
+.PP
+The \fBtoplevel\fR command creates a new Tcl command whose
+name is the same as the path name of the toplevel's window. This
+command may be used to invoke various
+operations on the widget. It has the following general form:
+.PP
+.CS
+\fIpathName option \fR?\fIarg arg ...\fR?
+.CE
+.PP
+\fIPathName\fR is the name of the command, which is the same as
+the toplevel widget's path name. \fIOption\fR and the \fIarg\fRs
+determine the exact behavior of the command. The following
+commands are possible for toplevel widgets:
+.TP
+\fIpathName \fBcget \fIoption\fR
+.
+Returns the current value of the configuration option given
+by \fIoption\fR.
+\fIOption\fR may have any of the values accepted by the \fBtoplevel\fR
+command.
+.TP
+\fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
+.
+Query or modify the configuration options of the widget.
+If no \fIoption\fR is specified, returns a list describing all of
+the available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for
+information on the format of this list). If \fIoption\fR is specified
+with no \fIvalue\fR, then the command returns a list describing the
+one named option (this list will be identical to the corresponding
+sublist of the value returned if no \fIoption\fR is specified). If
+one or more \fIoption\-value\fR pairs are specified, then the command
+modifies the given widget option(s) to have the given value(s); in
+this case the command returns an empty string.
+\fIOption\fR may have any of the values accepted by the \fBtoplevel\fR
+command.
+.SH BINDINGS
+.PP
+When a new toplevel is created, it has no default event bindings:
+toplevels are not intended to be interactive.
+.PP
+Be aware that bindings on toplevels may receive events from subwidgets.
+.SH "SEE ALSO"
+bind(n), bindtags(n), frame(n), wm(n)
+.SH KEYWORDS
+toplevel, widget
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/ttk_Geometry.3 b/tk8.6/doc/ttk_Geometry.3
new file mode 100644
index 0000000..61015c5
--- /dev/null
+++ b/tk8.6/doc/ttk_Geometry.3
@@ -0,0 +1,223 @@
+'\"
+'\" Copyright (c) 2004 Joe English
+'\"
+.TH Geometry 3 8.5 Tk "Tk Themed Widget"
+.so man.macros
+.BS
+.SH NAME
+Ttk_MakeBox, Ttk_PadBox, Ttk_ExpandBox, Ttk_PackBox, Ttk_StickBox, Ttk_PlaceBox, Ttk_BoxContains, Ttk_MakePadding, Ttk_UniformPadding, Ttk_AddPadding, Ttk_RelievePadding, Ttk_GetPaddingFromObj, Ttk_GetBorderFromObj, Ttk_GetStickyFromObj \- Tk themed geometry utilities
+.SH SYNOPSIS
+.nf
+\fB#include <tkTheme.h>\fR
+
+Ttk_Box
+\fBTtk_MakeBox\fR(int \fIx\fR, int \fIy\fR, int \fIwidth\fR, int \fIheight\fR);
+
+Ttk_Box
+\fBTtk_PadBox\fR(Ttk_Box \fIparcel\fR, Ttk_Padding \fIpadding\fR);
+
+Ttk_Box
+\fBTtk_ExpandBox\fR(Ttk_Box \fIparcel\fR, Ttk_Padding \fIpadding\fR);
+
+Ttk_Box
+\fBTtk_PackBox\fR(Ttk_Box *\fIcavity\fR, int \fIwidth\fR, int \fIheight\fR, Ttk_Side \fIside\fR);
+
+Ttk_Box
+\fBTtk_StickBox\fR(Ttk_Box \fIparcel\fR, int \fIwidth\fR, int \fIheight\fR, unsigned \fIsticky\fR);
+
+Ttk_Box
+\fBTtk_PlaceBox\fR(Ttk_Box *\fIcavity\fR, int \fIwidth\fR, int \fIheight\fR, Ttk_Side \fIside\fR, unsigned \fIsticky\fR);
+
+Ttk_Box
+\fBTtk_AnchorBox\fR(Ttk_Box \fIparcel\fR, int \fIwidth\fR, int \fIheight\fR, Tk_Anchor \fIanchor\fR);
+
+Ttk_Padding
+\fBTtk_MakePadding\fR(short \fIleft\fR, short \fItop\fR, short \fIright\fR, short \fIbottom\fR);
+
+Ttk_Padding
+\fBTtk_UniformPadding\fR(short \fIborder\fR);
+
+Ttk_Padding
+\fBTtk_AddPadding\fR(Ttk_Padding \fIpadding1\fR, Ttk_Padding \fIpadding2\fR;
+
+Ttk_Padding
+\fBTtk_RelievePadding\fR(Ttk_Padding \fIpadding\fR, int \fIrelief\fR);
+
+int
+\fBTtk_BoxContains\fR(Ttk_Box \fIbox\fR, int \fIx\fR, int \fIy\fR);
+
+int
+\fBTtk_GetPaddingFromObj\fR(Tcl_Interp *\fIinterp\fR, Tk_Window \fItkwin\fR, Tcl_Obj *\fIobjPtr\fR, Ttk_Padding *\fIpadding_rtn\fR);
+
+int
+\fBTtk_GetBorderFromObj\fR(Tcl_Interp *\fIinterp\fR, Tcl_Obj *\fIobjPtr\fR, Ttk_Padding *\fIpadding_rtn\fR);
+
+int
+\fBTtk_GetStickyFromObj\fR(Tcl_Interp *\fIinterp\fR, Tcl_Obj *\fIobjPtr\fR, int *\fIsticky_rtn\fR);
+.fi
+.SH ARGUMENTS
+.AP Tk_Anchor anchor in
+One of the symbolic constants \fBTK_ANCHOR_N\fR, \fBTK_ANCHOR_NE\fR,
+etc. See \fITk_GetAnchorFromObj(3)\fR.
+.AP "Ttk_Box *" cavity in/out
+A rectangular region from which a parcel is allocated.
+.AP short border in
+Extra padding (in pixels) to add uniformly to each side of a region.
+.AP short bottom in
+Extra padding (in pixels) to add to the bottom of a region.
+.AP Ttk_Box box in
+.AP "Ttk_Box *" box_rtn out
+Specifies a rectangular region.
+.AP int height in
+The height in pixels of a region.
+.AP "Tcl_Interp *" interp in
+Used to store error messages.
+.AP int left in
+Extra padding (in pixels) to add to the left side of a region.
+.AP "Tcl_Obj *" objPtr in
+String value contains a symbolic name
+to be converted to an enumerated value or bitmask.
+Internal rep may be be modified to cache corresponding value.
+.AP Ttk_Padding padding in
+.AP "Ttk_Padding *" padding_rtn out
+Extra padding to add on the inside of a region.
+.AP Ttk_Box parcel in
+A rectangular region, allocated from a cavity.
+.AP int relief in
+One of the standard Tk relief options
+(TK_RELIEF_RAISED, TK_RELIEF_SUNKEN, etc.).
+See \fBTk_GetReliefFromObj\fR.
+.AP short right in
+Extra padding (in pixels) to add to the right side of a region.
+.AP Ttk_Side side in
+One of \fBTTK_SIDE_LEFT\fR, \fBTTK_SIDE_TOP\fR,
+\fBTTK_SIDE_RIGHT\fR, or \fBTTK_SIDE_BOTTOM\fR.
+.AP unsigned sticky in
+A bitmask containing one or more of the bits
+\fBTTK_STICK_W\fR (west, or left),
+\fBTTK_STICK_E\fR (east, or right,
+\fBTTK_STICK_N\fR (north, or top), and
+\fBTTK_STICK_S\fR (south, or bottom).
+\fBTTK_FILL_X\fR is defined as a synonym for (TTK_STICK_W|TTK_STICK_E),
+\fBTTK_FILL_Y\fR is a synonym for (TTK_STICK_N|TTK_STICK_S),
+and \fBTTK_FILL_BOTH\fR and \fBTTK_STICK_ALL\fR
+are synonyms for (TTK_FILL_X|TTK_FILL_Y).
+See also: \fIgrid(n)\fR.
+.AP Tk_Window tkwin in
+Window whose screen geometry determines
+the conversion between absolute units and pixels.
+.AP short top in
+Extra padding at the top of a region.
+.AP int width in
+The width in pixels of a region.
+.AP int x in
+X coordinate of upper-left corner of region.
+.AP int y in
+Y coordinate of upper-left corner of region.
+.BE
+.SH "BOXES"
+.PP
+The \fBTtk_Box\fR structure represents a rectangular region of a window:
+.CS
+typedef struct {
+ int \fIx\fR;
+ int \fIy\fR;
+ int \fIwidth\fR;
+ int \fIheight\fR;
+} \fBTtk_Box\fR;
+.CE
+All coordinates are relative to the window.
+.PP
+\fBTtk_MakeBox\fR is a convenience routine that constructs
+a \fBTtk_Box\fR structure representing a region \fIwidth\fR pixels
+wide, \fIheight\fR pixels tall, at the specified \fIx, y\fR coordinates.
+.PP
+\fBTtk_PadBox\fR returns a new box located inside the specified \fIparcel\fR,
+shrunken according to the left, top, right, and bottom margins
+specified by \fIpadding\fR.
+.PP
+\fBTtk_ExpandBox\fR is the inverse of \fBTtk_PadBox\fR:
+it returns a new box surrounding the specified \fIparcel\fR,
+expanded according to the left, top, right, and bottom margins
+specified by \fIpadding\fR.
+.PP
+\fBTtk_PackBox\fR allocates a parcel \fIwidth\fR by \fIheight\fR
+pixels wide on the specified \fIside\fR of the \fIcavity\fR,
+and shrinks the \fIcavity\fR accordingly.
+.PP
+\fBTtk_StickBox\fR places a box with the requested \fIwidth\fR
+and \fIheight\fR inside the \fIparcel\fR according to the
+\fIsticky\fR bits.
+.PP
+\fBTtk_PlaceBox\fR combines \fBTtk_PackBox\fR and \fBTtk_StickBox\fR:
+it allocates a parcel on the specified \fIside\fR of the \fIcavity\fR,
+places a box of the requested size inside the parcel according to \fIsticky\fR,
+and shrinks the \fIcavity\fR.
+.PP
+\fBTtk_AnchorBox\fR places a box with the requested \fIwidth\fR
+and \fIheight\fR inside the \fIparcel\fR according to the
+specified \fIanchor\fR option.
+.PP
+\fBTtk_BoxContains\fR tests if the specified \fIx, y\fR coordinate
+lies within the rectangular region \fIbox\fR.
+.SH "PADDDING"
+.PP
+The \fBTtk_Padding\fR structure is used to represent
+borders, internal padding, and external margins:
+.CS
+typedef struct {
+ short \fIleft\fR;
+ short \fItop\fR;
+ short \fIright\fR;
+ short \fIbottom\fR;
+} \fBTtk_Padding\fR;
+.CE
+.PP
+\fBTtk_MakePadding\fR is a convenience routine that constructs
+a \fBTtk_Padding\fR structure with the specified left, top, right, and bottom
+components.
+.PP
+\fBTtk_UniformPadding\fR constructs a \fBTtk_Padding\fR structure
+with all components equal to the specified \fIborder\fR.
+.PP
+\fBTtk_AddPadding\fR adds two \fBTtk_Padding\fRs together
+and returns a combined padding containing the sum of the
+individual padding components.
+.PP
+\fBTtk_RelievePadding\fR
+adds an extra 2 pixels of padding to \fIpadding\fR
+according to the specified \fIrelief\fR.
+If \fIrelief\fR is \fBTK_RELIEF_SUNKEN\fR,
+adds two pixels at the top and left
+so the inner region is shifted down and to the left.
+If it is \fBTK_RELIEF_RAISED\fR, adds two pixels
+at the bottom and right so
+the inner region is shifted up and to the right.
+Otherwise, adds 1 pixel on all sides.
+This is typically used in element geometry procedures to simulate a
+.QW pressed-in
+look for pushbuttons.
+.SH "CONVERSION ROUTINES"
+.PP
+\fBTtk_GetPaddingFromObj\fR converts the string in \fIobjPtr\fR
+to a \fBTtk_Padding\fR structure.
+The string representation is a list of
+up to four length specifications
+.QW "\fIleft top right bottom\fR" .
+If fewer than four elements are specified,
+\fIbottom\fR defaults to \fItop\fR,
+\fIright\fR defaults to \fIleft\fR, and
+\fItop\fR defaults to \fIleft\fR.
+See \fBTk_GetPixelsFromObj(3)\fR for the syntax of length specifications.
+.PP
+\fBTtk_GetBorderFromObj\fR is the same as \fBTtk_GetPaddingFromObj\fR
+except that the lengths are specified as integers
+(i.e., resolution-dependant values like \fI3m\fR are not allowed).
+.PP
+\fBTtk_GetStickyFromObj\fR converts the string in \fIobjPtr\fR
+to a \fIsticky\fR bitmask. The string contains zero or more
+of the characters \fBn\fR, \fBs\fR, \fBe\fR, or \fBw\fR.
+.SH "SEE ALSO"
+Tk_GetReliefFromObj(3), Tk_GetPixelsFromObj(3), Tk_GetAnchorFromObj(3)
+.SH "KEYWORDS"
+geometry, padding, margins, box, region, sticky, relief
diff --git a/tk8.6/doc/ttk_Theme.3 b/tk8.6/doc/ttk_Theme.3
new file mode 100644
index 0000000..8031b8a
--- /dev/null
+++ b/tk8.6/doc/ttk_Theme.3
@@ -0,0 +1,32 @@
+'\"
+'\" Copyright (c) 2003 Joe English
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH Ttk_CreateTheme 3 8.5 Tk "Tk Themed Widget"
+.so man.macros
+.BS
+.SH NAME
+Ttk_CreateTheme, Ttk_GetTheme, Ttk_GetDefaultTheme, Ttk_GetCurrentTheme \- create and use Tk themes.
+.SH SYNOPSIS
+.nf
+Ttk_Theme Ttk_CreateTheme(\fIinterp\fR, \fIname\fR, \fIparentTheme\fR);
+Ttk_Theme Ttk_GetTheme(\fIinterp\fR, \fIname\fR);
+Ttk_Theme Ttk_GetDefaultTheme(\fIinterp\fR);
+Ttk_Theme Ttk_GetCurrentTheme(\fIinterp\fR);
+.fi
+.SH ARGUMENTS
+.AP "Tcl_Interp *" interp in
+The Tcl interpreter in which to register/query available themes.
+.AP "Ttk_Theme" parentTheme in
+Fallback or parent theme from which the new theme will
+inherit elements and layouts.
+.AP "const char *" name in
+The name of the theme.
+.BE
+.SH DESCRIPTION
+.\" TODO - Document these functions better!
+.SH "SEE ALSO"
+Ttk_RegisterLayout, Ttk_BuildLayout
+.\" .SH KEYWORDS
diff --git a/tk8.6/doc/ttk_button.n b/tk8.6/doc/ttk_button.n
new file mode 100644
index 0000000..cf47a1a
--- /dev/null
+++ b/tk8.6/doc/ttk_button.n
@@ -0,0 +1,109 @@
+'\"
+'\" Copyright (c) 2004 Joe English
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH ttk::button n 8.5 Tk "Tk Themed Widget"
+.so man.macros
+.BS
+.SH NAME
+ttk::button \- Widget that issues a command when pressed
+.SH SYNOPSIS
+\fBttk::button\fR \fIpathName \fR?\fIoptions\fR?
+.BE
+.SH DESCRIPTION
+A \fBttk::button\fR widget displays a textual label and/or image,
+and evaluates a command when pressed.
+.SO ttk_widget
+\-class \-compound \-cursor
+\-image \-state \-style
+\-takefocus \-text \-textvariable
+\-underline \-width
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-command command Command
+A script to evaluate when the widget is invoked.
+.OP \-default default Default
+May be set to one of \fBnormal\fR, \fBactive\fR, or \fBdisabled\fR.
+In a dialog box, one button may be designated the
+.QW default
+button (meaning, roughly,
+.QW "the one that gets invoked when the user presses <Enter>" ).
+\fBactive\fR indicates that this is currently the default button;
+\fBnormal\fR means that it may become the default button, and
+\fBdisabled\fR means that it is not defaultable.
+The default is \fBnormal\fR.
+.RS
+.PP
+Depending on the theme, the default button may be displayed
+with an extra highlight ring, or with a different border color.
+.RE
+.\" Not documented -- may go away
+.\" .OP \-padding padding Padding
+.\" .OP \-foreground foreground Foreground
+.\" .OP \-font font Font
+.\" .OP \-anchor anchor Anchor
+.\" .OP \-relief relief Relief
+.SH "WIDGET COMMAND"
+.PP
+In addition to the standard
+\fBcget\fR, \fBconfigure\fR, \fBidentify\fR, \fBinstate\fR, and \fBstate\fR
+commands, buttons support the following additional widget commands:
+.TP
+\fIpathName \fBinvoke\fR
+Invokes the command associated with the button.
+.SH "STANDARD STYLES"
+.PP
+\fBTtk::button\fR widgets support the \fBToolbutton\fR style in all standard
+themes, which is useful for creating widgets for toolbars.
+.SH "STYLING OPTIONS"
+.PP
+The class name for a \fBttk::button\fP is \fBTButton\fP.
+.PP
+Dynamic states: \fBactive\fP, \fBdisabled\fP, \fBpressed\fP, \fBreadonly\fP.
+.PP
+\fBTButton\fP styling options configurable with \fBttk::style\fP
+are:
+.PP
+\fB\-anchor\fP \fIanchor\fP
+.br
+\fB\-background\fP \fIcolor\fP
+.br
+\fB\-bordercolor\fP \fIcolor\fP
+.br
+\fB\-darkcolor\fP \fIcolor\fP
+.br
+\fB\-foreground\fP \fIcolor\fP
+.br
+\fB\-font\fP \fIfont\fP
+.br
+\fB\-highlightcolor\fP \fIcolor\fP
+.br
+\fB\-highlightthickness\fP \fIamount\fP
+.br
+\fB\-lightcolor\fP \fIcolor\fP
+.br
+\fB\-padding\fP \fIpadding\fP
+.br
+\fB\-relief\fP \fIrelief\fP
+.br
+\fB\-shiftrelief\fP \fIamount\fP
+.RS
+\fB\-shiftrelief\fP specifies how far the button contents are
+shifted down and right in the \fIpressed\fP state.
+This action provides additional skeumorphic feedback.
+.RE
+\fB\-width\fP \fIamount\fP
+.PP
+Some options are only available for specific themes.
+.PP
+See the \fBttk::style\fP manual page for information on how to configure
+ttk styles.
+.SH "SEE ALSO"
+ttk::widget(n), button(n)
+.SH "KEYWORDS"
+widget, button, default, command
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/ttk_checkbutton.n b/tk8.6/doc/ttk_checkbutton.n
new file mode 100644
index 0000000..a18a886
--- /dev/null
+++ b/tk8.6/doc/ttk_checkbutton.n
@@ -0,0 +1,105 @@
+'\"
+'\" Copyright (c) 2004 Joe English
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH ttk::checkbutton n 8.5 Tk "Tk Themed Widget"
+.so man.macros
+.BS
+.SH NAME
+ttk::checkbutton \- On/off widget
+.SH SYNOPSIS
+\fBttk::checkbutton\fR \fIpathName \fR?\fIoptions\fR?
+.BE
+.SH DESCRIPTION
+A \fBttk::checkbutton\fR widget is used to show or change a setting.
+It has two states, selected and deselected.
+The state of the checkbutton may be linked to a Tcl variable.
+.SO ttk_widget
+\-class \-compound \-cursor
+\-image \-state \-style
+\-takefocus \-text \-textvariable
+\-underline \-width
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-command command Command
+A Tcl script to execute whenever the widget is invoked.
+.OP \-offvalue offValue OffValue
+The value to store in the associated \fB\-variable\fR
+when the widget is deselected. Defaults to \fB0\fR.
+.OP \-onvalue onValue OnValue
+The value to store in the associated \fB\-variable\fR
+when the widget is selected. Defaults to \fB1\fR.
+.OP \-variable variable Variable
+The name of a global variable whose value is linked to the widget.
+Defaults to the widget pathname if not specified.
+.SH "WIDGET COMMAND"
+.PP
+In addition to the standard
+\fBcget\fR, \fBconfigure\fR, \fBidentify\fR, \fBinstate\fR, and \fBstate\fR
+commands, checkbuttons support the following additional
+widget commands:
+.TP
+\fIpathname\fB invoke\fR
+Toggles between the selected and deselected states
+and evaluates the associated \fB\-command\fR.
+If the widget is currently selected, sets the \fB\-variable\fR
+to the \fB\-offvalue\fR and deselects the widget;
+otherwise, sets the \fB\-variable\fR to the \fB\-onvalue\fR
+Returns the result of the \fB\-command\fR.
+.\" Missing: select, deselect, toggle
+.\" Are these useful? They don't invoke the -command
+.\" Missing: flash. This is definitely not useful.
+.SH "WIDGET STATES"
+.PP
+The widget does not respond to user input if the \fBdisabled\fR state is set.
+The widget sets the \fBselected\fR state whenever
+the linked \fB\-variable\fR is set to the widget's \fB\-onvalue\fR,
+and clears it otherwise.
+The widget sets the \fBalternate\fR state whenever the
+linked \fB\-variable\fR is unset.
+(The \fBalternate\fR state may be used to indicate a
+.QW tri-state
+or
+.QW indeterminate
+selection.)
+.SH "STANDARD STYLES"
+.PP
+\fBTtk::checkbutton\fR widgets support the \fBToolbutton\fR style in all
+standard themes, which is useful for creating widgets for toolbars.
+.SH "STYLING OPTIONS"
+.PP
+The class name for a \fBttk::checkbutton\fP is \fBTCheckbutton\fP.
+.PP
+Dynamic states: \fBactive\fP, \fBalternate\fP, \fBdisabled\fP,
+\fBpressed\fP, \fBselected\fP, \fBreadonly\fP.
+.PP
+\fBTCheckbutton\fP styling options configurable with \fBttk::style\fP
+are:
+.PP
+\fB\-background\fP \fIcolor\fP
+.br
+\fB\-foreground\fP \fIcolor\fP
+.br
+\fB\-indicatorbackground\fP \fIcolor\fP
+.br
+\fB\-indicatorcolor\fP \fIcolor\fP
+.br
+\fB\-indicatormargin\fP \fIpadding\fP
+.br
+\fB\-indicatorrelief\fP \fIrelief\fP
+.br
+\fB\-padding\fP \fIpadding\fP
+.PP
+Some options are only available for specific themes.
+.PP
+See the \fBttk::style\fP manual page for information on how to configure
+ttk styles.
+.SH "SEE ALSO"
+ttk::widget(n), ttk::radiobutton(n), checkbutton(n)
+.SH "KEYWORDS"
+widget, button, toggle, check, option
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/ttk_combobox.n b/tk8.6/doc/ttk_combobox.n
new file mode 100644
index 0000000..9d0bcc6
--- /dev/null
+++ b/tk8.6/doc/ttk_combobox.n
@@ -0,0 +1,200 @@
+'\"
+'\" Copyright (c) 2004 Joe English
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH ttk::combobox n 8.5 Tk "Tk Themed Widget"
+.so man.macros
+.BS
+.SH NAME
+ttk::combobox \- text field with popdown selection list
+.SH SYNOPSIS
+\fBttk::combobox\fR \fIpathName \fR?\fIoptions\fR?
+.BE
+.SH DESCRIPTION
+.PP
+A \fBttk::combobox\fR combines a text field with a pop-down list of values;
+the user may select the value of the text field from among the
+values in the list.
+.SO ttk_widget
+\-class \-cursor \-takefocus
+\-style
+.SE
+.\" ALSO: Other entry widget options
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-exportselection exportSelection ExportSelection
+Boolean value.
+If set, the widget selection is linked to the X selection.
+.OP \-justify justify Justify
+Specifies how the text is aligned within the widget.
+Must be one of \fBleft\fR, \fBcenter\fR, or \fBright\fR.
+.OP \-height height Height
+Specifies the height of the pop-down listbox, in rows.
+.OP \-postcommand postCommand PostCommand
+A Tcl script to evaluate immediately before displaying the listbox.
+The \fB\-postcommand\fR script may specify the \fB\-values\fR to display.
+.OP \-state state State
+One of \fBnormal\fR, \fBreadonly\fR, or \fBdisabled\fR.
+In the \fBreadonly\fR state,
+the value may not be edited directly, and
+the user can only select one of the \fB\-values\fR from the
+dropdown list.
+In the \fBnormal\fR state,
+the text field is directly editable.
+In the \fBdisabled\fR state, no interaction is possible.
+.OP \-textvariable textVariable TextVariable
+Specifies the name of a global variable whose value is linked
+to the widget value.
+Whenever the variable changes value the widget value is updated,
+and vice versa.
+.OP \-values values Values
+Specifies the list of values to display in the drop-down listbox.
+.OP \-width width Width
+Specifies an integer value indicating the desired width of the entry window,
+in average-size characters of the widget's font.
+.SH "WIDGET COMMAND"
+.PP
+The following subcommands are possible for combobox widgets:
+'\".TP
+'\"\fIpathName \fBcget\fR \fIoption\fR
+'\"Returns the current value of the specified \fIoption\fR.
+'\"See \fIttk::widget(n)\fR.
+'\".TP
+'\"\fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
+'\"Modify or query widget options.
+'\"See \fIttk::widget(n)\fR.
+.TP
+\fIpathName \fBcurrent\fR ?\fInewIndex\fR?
+If \fInewIndex\fR is supplied, sets the combobox value
+to the element at position \fInewIndex\fR in the list of \fB\-values\fR
+(in addition to integers, the \fBend\fR index is supported and indicates
+the last element of the list).
+Otherwise, returns the index of the current value in the list of
+\fB\-values\fR or \fB\-1\fR if the current value does not appear in the list.
+.TP
+\fIpathName \fBget\fR
+Returns the current value of the combobox.
+'\".TP
+'\"\fIpathName \fBidentify \fIx y\fR
+'\"Returns the name of the element at position \fIx\fR, \fIy\fR.
+'\"See \fIttk::widget(n)\fR.
+'\".TP
+'\"\fIpathName \fBinstate \fIstateSpec\fR ?\fIscript\fR?
+'\"Test the widget state.
+'\"See \fIttk::widget(n)\fR.
+.TP
+\fIpathName \fBset\fR \fIvalue\fR
+Sets the value of the combobox to \fIvalue\fR.
+'\".TP
+'\"\fIpathName \fBstate\fR ?\fIstateSpec\fR?
+'\"Modify or query the widget state.
+'\"See \fIttk::widget(n)\fR.
+.PP
+The combobox widget also supports the following \fBttk::entry\fR
+widget subcommands (see \fIttk::entry(n)\fR for details):
+.DS
+.ta 5.5c 11c
+\fBbbox\fR \fBdelete\fR \fBicursor\fR
+\fBindex\fR \fBinsert\fR \fBselection\fR
+\fBxview\fR
+.DE
+The combobox widget also supports the following generic \fBttk::widget\fR
+widget subcommands (see \fIttk::widget(n)\fR for details):
+.DS
+.ta 5.5c 11c
+\fBcget\fR \fBconfigure\fR \fBidentify\fR
+\fBinstate\fR \fBstate\fR
+.DE
+.SH "VIRTUAL EVENTS"
+.PP
+The combobox widget generates a \fB<<ComboboxSelected>>\fR virtual event
+when the user selects an element from the list of values.
+If the selection action unposts the listbox,
+this event is delivered after the listbox is unposted.
+.SH "STYLING OPTIONS"
+.PP
+The class name for a \fBttk::combobox\fP is \fBTCombobox\fP.
+The \fBttk::combobox\fP uses the \fBentry\fP and
+\fBlistbox\fP widgets internally.
+The listbox frame has a class name of \fBComboboxPopdownFrame\fP.
+.PP
+Dynamic states: \fBdisabled\fP, \fBfocus\fP, \fBpressed\fP, \fBreadonly\fP.
+.PP
+\fBTCombobox\fP styling options configurable with \fBttk::style\fP
+are:
+.PP
+\fB\-arrowcolor\fP \fIcolor\fP
+.br
+\fB\-arrowsize\fP \fIamount\fP
+.br
+\fB\-background\fP \fIcolor\fP
+.br
+\fB\-bordercolor\fP \fIcolor\fP
+.br
+\fB\-darkcolor\fP \fIcolor\fP
+.br
+\fB\-focusfill\fP \fIcolor\fP
+.br
+\fB\-foreground\fP \fIcolor\fP
+.br
+\fB\-fieldbackground\fP \fIcolor\fP
+.RS
+Can only be changed when using non-native and non-graphical themes.
+.RE
+\fB\-insertwidth\fP \fIamount\fP
+.br
+\fB\-lightcolor\fP \fIcolor\fP
+.br
+\fB\-padding\fP \fIpadding\fP
+.br
+\fB\-postoffset\fP \fIpadding\fP
+.br
+\fB\-selectbackground\fP \fIcolor\fP
+.RS
+Text entry select background.
+.RE
+\fB\-selectforeground\fP \fIcolor\fP
+.RS
+Text entry select foreground.
+.RE
+.PP
+The \fBttk::combobox\fP popdown listbox cannot be configured using
+\fBttk::style\fP nor via the widget \fBconfigure\fP command. The listbox
+can be configured using the option database.
+.PP
+option add *TCombobox*Listbox.background \fIcolor\fP
+.br
+option add *TCombobox*Listbox.font \fIfont\fP
+.br
+option add *TCombobox*Listbox.foreground \fIcolor\fP
+.br
+option add *TCombobox*Listbox.selectBackground \fIcolor\fP
+.br
+option add *TCombobox*Listbox.selectForeground \fIcolor\fP
+.PP
+To configure a specific listbox (subject to future change):
+.CS
+set popdown [ttk::combobox::PopdownWindow .mycombobox]
+$popdown.f.l configure \-font \fIfont\fP
+.CE
+.PP
+\fBComboboxPopdownFrame\fP
+styling options configurable with \fBttk::style\fP
+are:
+.PP
+\fB\-borderwidth\fP \fIamount\fP
+.br
+\fB\-relief\fP \fIrelief\fP
+.PP
+Some options are only available for specific themes.
+.PP
+See the \fBttk::style\fP manual page for information on how to configure
+ttk styles.
+.SH "SEE ALSO"
+ttk::widget(n), ttk::entry(n)
+.SH KEYWORDS
+choice, entry, list box, text box, widget
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/ttk_entry.n b/tk8.6/doc/ttk_entry.n
new file mode 100644
index 0000000..adc4f16
--- /dev/null
+++ b/tk8.6/doc/ttk_entry.n
@@ -0,0 +1,472 @@
+'\"
+'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
+'\" Copyright (c) 1998-2000 Scriptics Corporation.
+'\" Copyright (c) 2004 Joe English
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH ttk::entry n 8.5 Tk "Tk Themed Widget"
+.so man.macros
+.BS
+.SH NAME
+ttk::entry \- Editable text field widget
+.SH SYNOPSIS
+\fBttk::entry\fR \fIpathName \fR?\fIoptions\fR?
+.BE
+.SH DESCRIPTION
+.PP
+An \fBttk::entry\fR widget displays a one-line text string and
+allows that string to be edited by the user.
+The value of the string may be linked to a Tcl variable
+with the \fB\-textvariable\fR option.
+Entry widgets support horizontal scrolling with the
+standard \fB\-xscrollcommand\fR option and \fBxview\fR widget command.
+.SO ttk_widget
+\-class \-cursor \-style
+\-takefocus \-xscrollcommand
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-exportselection exportSelection ExportSelection
+A boolean value specifying whether or not
+a selection in the widget should be linked to the X selection.
+If the selection is exported, then selecting in the widget deselects
+the current X selection, selecting outside the widget deselects any
+widget selection, and the widget will respond to selection retrieval
+requests when it has a selection.
+.\" MAYBE: .OP \-font font Font
+.\" MAYBE: .OP \-foreground foreground Foreground
+.\" MAYBE: .OP \-insertbackground insertBackground Foreground
+.\" MAYBE: .OP \-insertwidth insertWidth InsertWidth
+.OP \-invalidcommand invalidCommand InvalidCommand
+A script template to evaluate whenever the \fB\-validatecommand\fR returns 0.
+See \fBVALIDATION\fR below for more information.
+.OP \-justify justify Justify
+Specifies how the text is aligned within the entry widget.
+One of \fBleft\fR, \fBcenter\fR, or \fBright\fR.
+.\" MAYBE: .OP \-selectbackground selectBackground Foreground
+.\" MAYBE: .OP \-selectborderwidth selectBorderWidth BorderWidth
+.\" MAYBE: .OP \-selectforeground selectForeground Background
+.OP \-show show Show
+If this option is specified, then the true contents of the entry
+are not displayed in the window.
+Instead, each character in the entry's value will be displayed as
+the first character in the value of this option, such as
+.QW *
+or a bullet.
+This is useful, for example, if the entry is to be used to enter
+a password.
+If characters in the entry are selected and copied elsewhere, the
+information copied will be what is displayed, not the true contents
+of the entry.
+.OP \-state state State
+Compatibility option; see \fIttk::widget(n)\fR for details.
+Specifies one of three states for the entry,
+\fBnormal\fR, \fBdisabled\fR, or \fBreadonly\fR.
+See \fBWIDGET STATES\fR, below.
+.OP \-textvariable textVariable Variable
+Specifies the name of a global variable whose value is linked
+to the entry widget's contents.
+Whenever the variable changes value, the widget's contents are updated,
+and vice versa.
+.OP \-validate validate Validate
+Specifies the mode in which validation should operate:
+\fBnone\fR, \fBfocus\fR, \fBfocusin\fR, \fBfocusout\fR, \fBkey\fR, or \fBall\fR.
+Default is \fBnone\fR, meaning that validation is disabled.
+See \fBVALIDATION\fR below.
+.OP \-validatecommand validateCommand ValidateCommand
+A script template to evaluate whenever validation is triggered.
+If set to the empty string (the default), validation is disabled.
+The script must return a boolean value.
+See \fBVALIDATION\fR below.
+.OP \-width width Width
+Specifies an integer value indicating the desired width of the entry window,
+in average-size characters of the widget's font.
+.\" Not in ttk: If the value is less than or equal to zero, the widget picks a
+.\" Not in ttk: size just large enough to hold its current text.
+.SH NOTES
+.PP
+A portion of the entry may be selected as described below.
+If an entry is exporting its selection (see the \fB\-exportselection\fR
+option), then it will observe the standard X11 protocols for handling the
+selection; entry selections are available as type \fBSTRING\fR.
+Entries also observe the standard Tk rules for dealing with the
+input focus. When an entry has the input focus it displays an
+\fIinsert cursor\fR to indicate where new characters will be
+inserted.
+.PP
+Entries are capable of displaying strings that are too long to
+fit entirely within the widget's window. In this case, only a
+portion of the string will be displayed; commands described below
+may be used to change the view in the window. Entries use
+the standard \fB\-xscrollcommand\fR mechanism for interacting with
+scrollbars (see the description of the \fB\-xscrollcommand\fR option
+for details).
+.SH "INDICES"
+.PP
+Many of the \fBentry\fR widget commands take one or more indices as
+arguments. An index specifies a particular character in the entry's
+string, in any of the following ways:
+.IP \fInumber\fR
+Specifies the character as a numerical index, where 0 corresponds
+to the first character in the string.
+.IP \fB@\fInumber\fR
+In this form, \fInumber\fR is treated as an x-coordinate in the
+entry's window; the character spanning that x-coordinate is used.
+For example,
+.QW \fB@0\fR
+indicates the left-most character in the window.
+.IP \fBend\fR
+Indicates the character just after the last one in the entry's string.
+This is equivalent to specifying a numerical index equal to the length
+of the entry's string.
+.IP \fBinsert\fR
+Indicates the character adjacent to and immediately following the
+insert cursor.
+.IP \fBsel.first\fR
+Indicates the first character in the selection. It is an error to
+use this form if the selection is not in the entry window.
+.IP \fBsel.last\fR
+Indicates the character just after the last one in the selection.
+It is an error to use this form if the selection is not in the
+entry window.
+.LP
+Abbreviations may be used for any of the forms above, e.g.\|
+.QW \fBe\fR
+or
+.QW \fBsel.l\fR .
+In general, out-of-range indices are automatically rounded to the
+nearest legal value.
+.SH "WIDGET COMMAND"
+.PP
+The following subcommands are possible for entry widgets:
+.TP
+\fIpathName \fBbbox \fIindex\fR
+Returns a list of four numbers describing the bounding box of the
+character given by \fIindex\fR.
+The first two elements of the list give the x and y coordinates of
+the upper-left corner of the screen area covered by the character
+(in pixels relative to the widget) and the last two elements give
+the width and height of the character, in pixels.
+The bounding box may refer to a region outside the visible area
+of the window.
+'\".TP
+'\"\fIpathName \fBcget\fR \fIoption\fR
+'\"Returns the current value of the specified \fIoption\fR.
+'\"See \fIttk::widget(n)\fR.
+'\".TP
+'\"\fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
+'\"Modify or query widget options.
+'\"See \fIttk::widget(n)\fR.
+.TP
+\fIpathName \fBdelete \fIfirst \fR?\fIlast\fR?
+Delete one or more elements of the entry.
+\fIFirst\fR is the index of the first character to delete, and
+\fIlast\fR is the index of the character just after the last
+one to delete.
+If \fIlast\fR is not specified it defaults to \fIfirst\fR+1,
+i.e. a single character is deleted.
+This command returns the empty string.
+.TP
+\fIpathName \fBget\fR
+Returns the entry's string.
+.TP
+\fIpathName \fBicursor \fIindex\fR
+Arrange for the insert cursor to be displayed just before the character
+given by \fIindex\fR. Returns the empty string.
+'\".TP
+'\"\fIpathName \fBidentify \fIx y\fR
+'\"Returns the name of the element at position \fIx\fR, \fIy\fR,
+'\"or the empty string if the coordinates are outside the window.
+.TP
+\fIpathName \fBindex\fI index\fR
+Returns the numerical index corresponding to \fIindex\fR.
+.TP
+\fIpathName \fBinsert \fIindex string\fR
+Insert \fIstring\fR just before the character
+indicated by \fIindex\fR. Returns the empty string.
+'\".TP
+'\"\fIpathName \fBinstate \fIstatespec\fR ?\fIscript\fR?
+'\"Test the widget state.
+'\"See \fIttk::widget(n)\fR.
+.TP
+\fIpathName \fBselection \fIoption arg\fR
+This command is used to adjust the selection within an entry. It
+has several forms, depending on \fIoption\fR:
+.RS
+.TP
+\fIpathName \fBselection clear\fR
+Clear the selection if it is currently in this widget.
+If the selection is not in this widget then the command has no effect.
+Returns the empty string.
+.TP
+\fIpathName \fBselection present\fR
+Returns 1 if there is are characters selected in the entry,
+0 if nothing is selected.
+.TP
+\fIpathName \fBselection range \fIstart\fR \fIend\fR
+Sets the selection to include the characters starting with
+the one indexed by \fIstart\fR and ending with the one just
+before \fIend\fR.
+If \fIend\fR refers to the same character as \fIstart\fR or an
+earlier one, then the entry's selection is cleared.
+.RE
+'\".TP
+'\"\fIpathName \fBstate\fR ?\fIstateSpec\fR?
+'\"Modify or query the widget state.
+'\"See \fIttk::widget(n)\fR.
+.TP
+\fIpathName \fBvalidate\fR
+Force revalidation, independent of the conditions specified
+by the \fB\-validate\fR option.
+Returns 0 if validation fails, 1 if it succeeds.
+Sets or clears the \fBinvalid\fR state accordingly.
+See \fBVALIDATION\fR below for more details.
+.PP
+The entry widget also supports the following generic \fBttk::widget\fR
+widget subcommands (see \fIttk::widget(n)\fR for details):
+.DS
+.ta 5.5c 11c
+\fBcget\fR \fBconfigure\fR \fBidentify\fR
+\fBinstate\fR \fBstate\fR \fBxview\fR
+.DE
+.SH VALIDATION
+.PP
+The \fB\-validate\fR, \fB\-validatecommand\fR, and \fB\-invalidcommand\fR
+options are used to enable entry widget validation.
+.SS "VALIDATION MODES"
+.PP
+There are two main validation modes: \fIprevalidation\fR,
+in which the \fB\-validatecommand\fR is evaluated prior to each edit
+and the return value is used to determine whether to accept
+or reject the change;
+and \fIrevalidation\fR, in which the \fB\-validatecommand\fR is
+evaluated to determine whether the current value is valid.
+.PP
+The \fB\-validate\fR option determines when validation occurs;
+it may be set to any of the following values:
+.RS
+.IP \fBnone\fR
+Default. This means validation will only occur when
+specifically requested by the \fBvalidate\fR widget command.
+.IP \fBkey\fR
+The entry will be prevalidated prior to each edit
+(specifically, whenever the \fBinsert\fR or \fBdelete\fR
+widget commands are called).
+If prevalidation fails, the edit is rejected.
+.IP \fBfocus\fR
+The entry is revalidated when the entry receives or loses focus.
+.IP \fBfocusin\fR
+The entry is revalidated when the entry receives focus.
+.IP \fBfocusout\fR
+The entry is revalidated when the entry loses focus.
+.IP \fBall\fR
+Validation is performed for all above conditions.
+.RE
+.PP
+The \fB\-invalidcommand\fR is evaluated whenever
+the \fB\-validatecommand\fR returns a false value.
+.PP
+The \fB\-validatecommand\fR and \fB\-invalidcommand\fR
+may modify the entry widget's value
+via the widget \fBinsert\fR or \fBdelete\fR commands,
+or by setting the linked \fB\-textvariable\fR.
+If either does so during prevalidation,
+then the edit is rejected
+regardless of the value returned by the \fB\-validatecommand\fR.
+.PP
+If \fB\-validatecommand\fR is empty (the default),
+validation always succeeds.
+.SS "VALIDATION SCRIPT SUBSTITUTIONS"
+.PP
+It is possible to perform percent substitutions on the
+\fB\-validatecommand\fR and \fB\-invalidcommand\fR,
+just as in a \fBbind\fR script.
+The following substitutions are recognized:
+.RS
+.IP \fB%d\fR
+Type of action: 1 for \fBinsert\fR prevalidation,
+0 for \fBdelete\fR prevalidation,
+or \-1 for revalidation.
+.IP \fB%i\fR
+Index of character string to be inserted/deleted, if any, otherwise \-1.
+.IP \fB%P\fR
+In prevalidation, the new value of the entry if the edit is accepted.
+In revalidation, the current value of the entry.
+.IP \fB%s\fR
+The current value of entry prior to editing.
+.IP \fB%S\fR
+The text string being inserted/deleted, if any, {} otherwise.
+.IP \fB%v\fR
+The current value of the \fB\-validate\fR option.
+.IP \fB%V\fR
+The validation condition that triggered the callback
+(\fBkey\fR, \fBfocusin\fR, \fBfocusout\fR, or \fBforced\fR).
+.IP \fB%W\fR
+The name of the entry widget.
+.RE
+.SS "DIFFERENCES FROM TK ENTRY WIDGET VALIDATION"
+.PP
+The standard Tk entry widget automatically disables validation
+(by setting \fB\-validate\fR to \fBnone\fR)
+if the \fB\-validatecommand\fR or \fB\-invalidcommand\fR modifies
+the entry's value.
+The Tk themed entry widget only disables validation if one
+of the validation scripts raises an error, or if \fB\-validatecommand\fR
+does not return a valid boolean value.
+(Thus, it is not necessary to re-enable validation after
+modifying the entry value in a validation script).
+.PP
+In addition, the standard entry widget invokes validation whenever the linked
+\fB\-textvariable\fR is modified; the Tk themed entry widget does not.
+.SH "DEFAULT BINDINGS"
+.PP
+The entry widget's default bindings enable the following behavior.
+In the descriptions below,
+.QW word
+refers to a contiguous group of letters, digits, or
+.QW _
+characters, or any single character other than these.
+.IP \0\(bu 4
+Clicking mouse button 1 positions the insert cursor
+just before the character underneath the mouse cursor, sets the
+input focus to this widget, and clears any selection in the widget.
+Dragging with mouse button 1 down strokes out a selection between
+the insert cursor and the character under the mouse.
+.IP \0\(bu 4
+Double-clicking with mouse button 1 selects the word under the mouse
+and positions the insert cursor at the end of the word.
+Dragging after a double click strokes out a selection consisting
+of whole words.
+.IP \0\(bu 4
+Triple-clicking with mouse button 1 selects all of the text in the
+entry and positions the insert cursor at the end of the line.
+.IP \0\(bu 4
+The ends of the selection can be adjusted by dragging with mouse
+button 1 while the Shift key is down.
+If the button is double-clicked before dragging then the selection
+will be adjusted in units of whole words.
+.IP \0\(bu 4
+Clicking mouse button 1 with the Control key down will position the
+insert cursor in the entry without affecting the selection.
+.IP \0\(bu 4
+If any normal printing characters are typed in an entry, they are
+inserted at the point of the insert cursor.
+.IP \0\(bu 4
+The view in the entry can be adjusted by dragging with mouse button 2.
+If mouse button 2 is clicked without moving the mouse, the selection
+is copied into the entry at the position of the mouse cursor.
+.IP \0\(bu 4
+If the mouse is dragged out of the entry on the left or right sides
+while button 1 is pressed, the entry will automatically scroll to
+make more text visible (if there is more text off-screen on the side
+where the mouse left the window).
+.IP \0\(bu 4
+The Left and Right keys move the insert cursor one character to the
+left or right; they also clear any selection in the entry.
+If Left or Right is typed with the Shift key down, then the insertion
+cursor moves and the selection is extended to include the new character.
+Control-Left and Control-Right move the insert cursor by words, and
+Control-Shift-Left and Control-Shift-Right move the insert cursor
+by words and also extend the selection.
+Control-b and Control-f behave the same as Left and Right, respectively.
+.IP \0\(bu 4
+The Home key and Control-a move the insert cursor to the
+beginning of the entry and clear any selection in the entry.
+Shift-Home moves the insert cursor to the beginning of the entry
+and extends the selection to that point.
+.IP \0\(bu 4
+The End key and Control-e move the insert cursor to the
+end of the entry and clear any selection in the entry.
+Shift-End moves the cursor to the end and extends the selection
+to that point.
+.IP \0\(bu 4
+Control-/ selects all the text in the entry.
+.IP \0\(bu 4
+Control-\e clears any selection in the entry.
+.IP \0\(bu 4
+The standard Tk <<Cut>>, <<Copy>>, <<Paste>>, and <<Clear>>
+virtual events operate on the selection in the expected manner.
+.IP \0\(bu 4
+The Delete key deletes the selection, if there is one in the entry.
+If there is no selection, it deletes the character to the right of
+the insert cursor.
+.IP \0\(bu 4
+The BackSpace key and Control-h delete the selection, if there is one
+in the entry.
+If there is no selection, it deletes the character to the left of
+the insert cursor.
+.IP \0\(bu 4
+Control-d deletes the character to the right of the insert cursor.
+.IP \0\(bu 4
+Control-k deletes all the characters to the right of the insertion
+cursor.
+.SH "WIDGET STATES"
+.PP
+In the \fBdisabled\fR state,
+the entry cannot be edited and the text cannot be selected.
+In the \fBreadonly\fR state,
+no insert cursor is displayed and
+the entry cannot be edited
+(specifically: the \fBinsert\fR and \fBdelete\fR commands have no effect).
+The \fBdisabled\fR state is the same as \fBreadonly\fR,
+and in addition text cannot be selected.
+.PP
+Note that changes to the linked \fB\-textvariable\fR will
+still be reflected in the entry, even if it is disabled or readonly.
+.PP
+Typically, the text is
+.QW grayed-out
+in the \fBdisabled\fR state,
+and a different background is used in the \fBreadonly\fR state.
+.PP
+The entry widget sets the \fBinvalid\fR state if revalidation fails,
+and clears it whenever validation succeeds.
+.SH "STYLING OPTIONS"
+.PP
+The class name for a \fBttk::entry\fP is \fBTEntry\fP.
+.PP
+Dynamic states: \fBdisabled\fP, \fBfocus\fP, \fBreadonly\fP.
+.PP
+\fBTEntry\fP styling options configurable with \fBttk::style\fP
+are:
+.PP
+\fB\-background\fP \fIcolor\fP
+.RS
+For backwards compatibility, when using the aqua theme (for macOS), this
+option behaves as an alias for the \fB\-fieldbackground\fP provided that no
+value is specified for \fB\-fieldbackground\fP. Otherwise it is ignored.
+.RE
+\fB\-bordercolor\fP \fIcolor\fP
+.br
+\fB\-darkcolor\fP \fIcolor\fP
+.br
+\fB\-fieldbackground\fP \fIcolor\fP
+.RS
+Some themes use a graphical background and their field background colors cannot be changed.
+.RE
+\fB\-foreground\fP \fIcolor\fP
+.br
+\fB\-insertwidth\fP \fIamount\fP
+.br
+\fB\-lightcolor\fP \fIcolor\fP
+.br
+\fB\-padding\fP \fIpadding\fP
+.br
+\fB\-relief\fP \fIrelief\fP
+.br
+\fB\-selectbackground\fP \fIcolor\fP
+.br
+\fB\-selectborderwidth\fP \fIamount\fP
+.br
+\fB\-selectforeground\fP \fIcolor\fP
+.PP
+See the \fBttk::style\fP manual page for information on how to configure
+ttk styles.
+.SH "SEE ALSO"
+ttk::widget(n), entry(n)
+.SH KEYWORDS
+entry, widget, text field
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/ttk_frame.n b/tk8.6/doc/ttk_frame.n
new file mode 100644
index 0000000..572f10c
--- /dev/null
+++ b/tk8.6/doc/ttk_frame.n
@@ -0,0 +1,71 @@
+'\"
+'\" Copyright (c) 2005 Joe English
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH ttk::frame n 8.5 Tk "Tk Themed Widget"
+.so man.macros
+.BS
+.SH NAME
+ttk::frame \- Simple container widget
+.SH SYNOPSIS
+\fBttk::frame\fR \fIpathName \fR?\fIoptions\fR?
+.BE
+.SH DESCRIPTION
+.PP
+A \fBttk::frame\fR widget is a container, used to group other widgets
+together.
+.SO ttk_widget
+\-class \-cursor \-padding \-style
+\-takefocus
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-borderwidth borderWidth BorderWidth
+The desired width of the widget border. Defaults to 0.
+.OP \-relief relief Relief
+One of the standard Tk border styles:
+\fBflat\fR, \fBgroove\fR, \fBraised\fR, \fBridge\fR,
+\fBsolid\fR, or \fBsunken\fR.
+Defaults to \fBflat\fR.
+.OP \-width width Width
+If specified, the widget's requested width in pixels.
+.OP \-height height Height
+If specified, the widget's requested height in pixels.
+.SH "WIDGET COMMAND"
+.PP
+Supports the standard widget commands
+\fBconfigure\fR, \fBcget\fR, \fBidentify\fR, \fBinstate\fR, and \fBstate\fR;
+see \fIttk::widget(n)\fR.
+.SH "NOTES"
+.PP
+Note that if the \fBpack\fR, \fBgrid\fR, or other geometry managers
+are used to manage the children of the \fBframe\fR,
+by the GM's requested size will normally take precedence
+over the \fBframe\fR widget's \fB\-width\fR and \fB\-height\fR options.
+\fBpack propagate\fR and \fBgrid propagate\fR can be used
+to change this.
+.SH "STYLING OPTIONS"
+.PP
+The class name for a \fBttk::frame\fP is \fBTFrame\fP.
+.PP
+\fBTFrame\fP styling options configurable with \fBttk::style\fP
+are:
+.PP
+\fB\-background\fP \fIcolor\fP
+.PP
+Some options are only available for specific themes.
+.PP
+See the \fBttk::style\fP manual page for information on how to configure
+ttk styles.
+.SH BINDINGS
+.PP
+When a new \fBttk::frame\fR is created, it has no default event bindings;
+\fBttk::frame\fRs are not intended to be interactive.
+.SH "SEE ALSO"
+ttk::widget(n), ttk::labelframe(n), frame(n)
+.SH "KEYWORDS"
+widget, frame, container
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/ttk_image.n b/tk8.6/doc/ttk_image.n
new file mode 100644
index 0000000..bc1dd3f
--- /dev/null
+++ b/tk8.6/doc/ttk_image.n
@@ -0,0 +1,98 @@
+'\"
+'\" Copyright (c) 2004 Joe English
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH ttk_image n 8.5 Tk "Tk Themed Widget"
+.so man.macros
+.BS
+.SH NAME
+ttk_image \- Define an element based on an image
+.SH SYNOPSIS
+\fBttk::style element create \fIname\fR \fBimage\fR \fIimageSpec\fR ?\fIoptions\fR?
+.BE
+.SH DESCRIPTION
+.PP
+The \fIimage\fR element factory creates a new element
+in the current theme whose visual appearance is determined
+by Tk images.
+\fIimageSpec\fP is a list of one or more elements.
+The first element is the default image name.
+The rest of the list is a sequence of \fIstatespec / value\fR
+pairs specifying other images to use when the element is
+in a particular state or combination of states.
+.SH OPTIONS
+.PP
+Valid \fIoptions\fR are:
+.TP
+\fB\-border\fR \fIpadding\fR
+\fIpadding\fR is a list of up to four integers, specifying
+the left, top, right, and bottom borders, respectively.
+If fewer than four elements are specified,
+\fIbottom\fR defaults to \fItop\fR,
+\fIright\fR defaults to \fIleft\fR, and
+\fItop\fR defaults to \fIleft\fR.
+In other words, a list of three numbers specify the left, vertical, and right border;
+a list of two numbers specify the horizontal and the vertical border;
+a single number specifies the same border all the way around the element.
+See \fBIMAGE STRETCHING\fR, below.
+.TP
+\fB\-height \fIheight\fR
+Specifies a minimum height for the element.
+If less than zero, the base image's height is used as a default.
+.TP
+\fB\-padding\fR \fIpadding\fR
+Specifies the element's interior padding.
+The padding is a list of up to four length specifications
+\fIleft top right bottom\fR.
+If fewer than four elements are specified,
+\fIbottom\fR defaults to \fItop\fR,
+\fIright\fR defaults to \fIleft\fR, and
+\fItop\fR defaults to \fIleft\fR.
+In other words, a list of three numbers specify the left, vertical, and right padding;
+a list of two numbers specify the horizontal and the vertical padding;
+a single number specifies the same padding all the way around the widget.
+Defaults to \fB\-border\fR if not specified.
+.TP
+\fB\-sticky\fR \fIspec\fR
+Specifies how the image is placed within the final parcel.
+\fIspec\fR contains zero or more characters
+.QW n ,
+.QW s ,
+.QW w ,
+or
+.QW e .
+.TP
+\fB\-width \fIwidth\fR
+Specifies a minimum width for the element.
+If less than zero, the base image's width is used as a default.
+.SH "IMAGE STRETCHING"
+.PP
+If the element's allocated parcel is larger than the image,
+the image will be placed in the parcel based on the \fB\-sticky\fR option.
+If the image needs to stretch horizontally (i.e., \fB\-sticky ew\fR)
+or vertically (\fB\-sticky ns\fR),
+subregions of the image are replicated to fill the parcel
+based on the \fB\-border\fR option.
+The \fB\-border\fR divides the image into 9 regions:
+four fixed corners, top and left edges (which may be tiled horizontally),
+left and right edges (which may be tiled vertically),
+and the central area (which may be tiled in both directions).
+.SH "EXAMPLE"
+.PP
+.CS
+set img1 [image create photo \-file button.png]
+set img2 [image create photo \-file button-pressed.png]
+set img3 [image create photo \-file button-active.png]
+style element create Button.button image \e
+ [list $img1 pressed $img2 active $img3] \e
+ \-border {2 4} \-sticky we
+.CE
+.SH "SEE ALSO"
+ttk::intro(n), ttk::style(n), ttk_vsapi(n), image(n), photo(n)
+.SH KEYWORDS
+style, theme, appearance, pixmap theme, image
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/ttk_intro.n b/tk8.6/doc/ttk_intro.n
new file mode 100644
index 0000000..bc3cd69
--- /dev/null
+++ b/tk8.6/doc/ttk_intro.n
@@ -0,0 +1,177 @@
+'\"
+'\" Copyright (c) 2004 Joe English
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH ttk::intro n 8.5 Tk "Tk Themed Widget"
+.so man.macros
+.BS
+.SH NAME
+ttk::intro \- Introduction to the Tk theme engine
+.BE
+.SH "OVERVIEW"
+.PP
+The Tk themed widget set is based on a revised and enhanced version
+of TIP #48 (http://tip.tcl.tk/48) specified style engine.
+The main concepts are described below.
+The basic idea is to separate, to the extent possible,
+the code implementing a widget's behavior from
+the code implementing its appearance.
+Widget class bindings are primarily responsible for
+maintaining the widget state and invoking callbacks;
+all aspects of the widget's appearance are controlled by the style of
+the widget (i.e. the style of the elements of the widget).
+.SH "THEMES"
+.PP
+A \fItheme\fR is a collection of elements and styles
+that determine the look and feel of the widget set.
+Themes can be used to:
+.IP \(bu
+isolate platform differences (X11 vs. classic Windows vs. XP vs. Aqua ...)
+.IP \(bu
+adapt to display limitations (low-color, grayscale, monochrome, tiny screens)
+.IP \(bu
+accessibility (high contrast, large type)
+.IP \(bu
+application suite branding
+.IP \(bu
+blend in with the rest of the desktop (Gnome, KDE, Java)
+.IP \(bu
+and, of course: eye candy.
+.SH "ELEMENTS"
+.PP
+An \fIelement\fR displays an individual part of a widget.
+For example, a vertical scrollbar widget contains \fBuparrow\fR,
+\fBdownarrow\fR, \fBtrough\fR and \fBslider\fR elements.
+.PP
+Element names use a recursive dotted notation.
+For example, \fBuparrow\fR identifies a generic arrow element,
+and \fBScrollbar.uparrow\fR and \fBCombobox.uparrow\fR identify
+widget-specific elements.
+When looking for an element, the style engine looks for
+the specific name first, and if an element of that name is
+not found it looks for generic elements by stripping off
+successive leading components of the element name.
+.PP
+Like widgets, elements have \fIoptions\fR which
+specify what to display and how to display it.
+For example, the \fBtext\fR element
+(which displays a text string) has
+\fB\-text\fR, \fB\-font\fR, \fB\-foreground\fR, \fB\-background\fR,
+\fB\-underline\fR, and \fB\-width\fR options.
+The value of an element option is taken from:
+.IP \(bu
+an option of the same name and type in the widget containing the element;
+.IP \(bu
+a dynamic setting specified by \fBstyle map\fR and the current state;
+.IP \(bu
+the default setting specified by \fBstyle configure\fR; or
+.IP \(bu
+the element's built-in default value for the option.
+.SH "LAYOUTS"
+.PP
+A \fIlayout\fR specifies which elements make up a widget
+and how they are arranged.
+The layout engine uses a simplified version of the \fBpack\fR
+algorithm: starting with an initial cavity equal to the size
+of the widget, elements are allocated a parcel within the cavity along
+the side specified by the \fB\-side\fR option,
+and placed within the parcel according to the \fB\-sticky\fR
+option.
+For example, the layout for a horizontal scrollbar is:
+.PP
+.CS
+ttk::\fBstyle layout\fR Horizontal.TScrollbar {
+ Scrollbar.trough \-children {
+ Scrollbar.leftarrow \-side left \-sticky w
+ Scrollbar.rightarrow \-side right \-sticky e
+ Scrollbar.thumb \-side left \-expand true \-sticky ew
+ }
+}
+.CE
+.PP
+By default, the layout for a widget is the same as its class name.
+Some widgets may override this (for example, the \fBttk::scrollbar\fR
+widget chooses different layouts based on the \fB\-orient\fR option).
+.SH "STATES"
+.PP
+In standard Tk, many widgets have a \fB\-state\fR option
+which (in most cases) is either \fBnormal\fR or \fBdisabled\fR.
+Some widgets support additional states, such
+as the \fBentry\fR widget which has a \fBreadonly\fR state
+and the various flavors of buttons which have \fBactive\fR state.
+.PP
+The themed Tk widgets generalizes this idea:
+every widget has a bitmap of independent state flags.
+Widget state flags include \fBactive\fR, \fBdisabled\fR,
+\fBpressed\fR, \fBfocus\fR, etc.,
+(see \fIttk::widget(n)\fR for the full list of state flags).
+.PP
+Instead of a \fB\-state\fR option, every widget now has
+a \fBstate\fR widget command which is used to set or query
+the state.
+A \fIstate specification\fR is a list of symbolic state names
+indicating which bits are set, each optionally prefixed with an
+exclamation point indicating that the bit is cleared instead.
+.PP
+For example, the class bindings for the \fBttk::button\fR
+widget are:
+.PP
+.CS
+bind TButton <Enter> { %W state active }
+bind TButton <Leave> { %W state !active }
+bind TButton <ButtonPress-1> { %W state pressed }
+bind TButton <Button1-Leave> { %W state !pressed }
+bind TButton <Button1-Enter> { %W state pressed }
+bind TButton <ButtonRelease-1> \e
+ { %W instate {pressed} { %W state !pressed ; %W invoke } }
+.CE
+.PP
+This specifies that the widget becomes \fBactive\fR when
+the pointer enters the widget, and inactive when it leaves.
+Similarly it becomes \fBpressed\fR when the mouse button is pressed,
+and \fB!pressed\fR on the ButtonRelease event.
+In addition, the button unpresses if
+pointer is dragged outside the widget while Button-1 is held down,
+and represses if it's dragged back in.
+Finally, when the mouse button is released, the widget's
+\fB\-command\fR is invoked, but only if the button is currently
+in the \fBpressed\fR state.
+(The actual bindings are a little more complicated than the above,
+but not by much).
+'\" Note to self: rewrite that paragraph. It's horrible.
+.SH "STYLES"
+.PP
+Each widget is associated with a \fIstyle\fR,
+which specifies values for element options.
+Style names use a recursive dotted notation like layouts and elements;
+by default, widgets use the class name to look up a style in the current theme.
+For example:
+.PP
+.CS
+ttk::\fBstyle configure\fR TButton \e
+ \-background #d9d9d9 \e
+ \-foreground black \e
+ \-relief raised \e
+ ;
+.CE
+.PP
+Many elements are displayed differently depending on the widget state.
+For example, buttons have a different background when they are active,
+a different foreground when disabled, and a different relief when pressed.
+The \fBstyle map\fR command specifies dynamic option settings
+for a particular style:
+.PP
+.CS
+ttk::\fBstyle map\fR TButton \e
+ \-background [list disabled #d9d9d9 active #ececec] \e
+ \-foreground [list disabled #a3a3a3] \e
+ \-relief [list {pressed !disabled} sunken] \e
+ ;
+.CE
+.SH "SEE ALSO"
+ttk::widget(n), ttk::style(n)
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/ttk_label.n b/tk8.6/doc/ttk_label.n
new file mode 100644
index 0000000..1e30592
--- /dev/null
+++ b/tk8.6/doc/ttk_label.n
@@ -0,0 +1,86 @@
+'\"
+'\" Copyright (c) 2004 Joe English
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH ttk::label n 8.5 Tk "Tk Themed Widget"
+.so man.macros
+.BS
+.SH NAME
+ttk::label \- Display a text string and/or image
+.SH SYNOPSIS
+\fBttk::label\fR \fIpathName \fR?\fIoptions\fR?
+.BE
+.SH DESCRIPTION
+.PP
+A \fBttk::label\fR widget displays a textual label and/or image.
+The label may be linked to a Tcl variable
+to automatically change the displayed text.
+.SO ttk_widget
+\-class \-compound \-cursor
+\-image \-padding \-state \-style \-takefocus
+\-text \-textvariable \-underline
+\-width
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-anchor anchor Anchor
+Specifies how the information in the widget is positioned
+relative to the inner margins. Legal values are
+\fBn\fR, \fBne\fR, \fBe\fR, \fBse\fR,
+\fBs\fR, \fBsw\fR, \fBw\fR, \fBnw\fR, and \fBcenter\fR.
+See also \fB\-justify\fR.
+.OP \-background frameColor FrameColor
+The widget's background color.
+If unspecified, the theme default is used.
+.OP \-font font Font
+Font to use for label text.
+.OP \-foreground textColor TextColor
+The widget's foreground color.
+If unspecified, the theme default is used.
+.OP \-justify justify Justify
+If there are multiple lines of text, specifies how
+the lines are laid out relative to one another.
+One of \fBleft\fR, \fBcenter\fR, or \fBright\fR.
+See also \fB\-anchor\fR.
+.OP \-relief relief Relief
+.\" Rewrite this:
+Specifies the 3-D effect desired for the widget border.
+Valid values are
+\fBflat\fR, \fBgroove\fR, \fBraised\fR, \fBridge\fR, \fBsolid\fR,
+and \fBsunken\fR.
+.OP \-wraplength wrapLength WrapLength
+Specifies the maximum line length (in pixels).
+If this option is less than or equal to zero,
+then automatic wrapping is not performed; otherwise
+the text is split into lines such that no line is longer
+than the specified value.
+.SH "WIDGET COMMAND"
+.PP
+Supports the standard widget commands
+\fBconfigure\fR, \fBcget\fR, \fBidentify\fR, \fBinstate\fR, and \fBstate\fR;
+see \fIttk::widget(n)\fR.
+.SH "STYLING OPTIONS"
+.PP
+The class name for a \fBttk::label\fP is \fBTLabel\fP.
+.PP
+Dynamic states: \fBdisabled\fP, \fBreadonly\fP.
+.PP
+\fBTLabel\fP styling options configurable with \fBttk::style\fP
+are:
+.PP
+\fB\-background\fP \fIcolor\fP
+.br
+\fB\-foreground\fP \fIcolor\fP
+.br
+\fB\-font\fP \fIfont\fP
+.PP
+Some options are only available for specific themes.
+.PP
+See the \fBttk::style\fP manual page for information on how to configure
+ttk styles.
+.SH "SEE ALSO"
+ttk::widget(n), label(n)
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/ttk_labelframe.n b/tk8.6/doc/ttk_labelframe.n
new file mode 100644
index 0000000..12f0b89
--- /dev/null
+++ b/tk8.6/doc/ttk_labelframe.n
@@ -0,0 +1,114 @@
+'\"
+'\" Copyright (c) 2005 Joe English
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH ttk::labelframe n 8.5 Tk "Tk Themed Widget"
+.so man.macros
+.BS
+.SH NAME
+ttk::labelframe \- Container widget with optional label
+.SH SYNOPSIS
+\fBttk::labelframe\fR \fIpathName \fR?\fIoptions\fR?
+.BE
+.SH DESCRIPTION
+.PP
+A \fBttk::labelframe\fR widget is a container used to group other widgets
+together. It has an optional label, which may be a plain text string or
+another widget.
+.SO ttk_widget
+\-class \-cursor \-padding \-style
+\-takefocus
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.\" XXX: Currently included, but may go away:
+.\" XXX: .OP -borderwidth borderWidth BorderWidth
+.\" XXX: The desired width of the widget border. Default is theme-dependent.
+.\" XXX: .OP -relief relief Relief
+.\" XXX: One of the standard Tk border styles:
+.\" XXX: \fBflat\fR, \fBgroove\fR, \fBraised\fR, \fBridge\fR,
+.\" XXX: \fBsolid\fR, or \fBsunken\fR.
+.\" XXX: Default is theme-dependent.
+.OP \-labelanchor labelAnchor LabelAnchor
+Specifies where to place the label.
+Allowed values are (clockwise from the top upper left corner):
+\fBnw\fR, \fBn\fR, \fBne\fR, \fBen\fR, \fBe\fR, \fBes\fR,
+\fBse\fR, \fBs\fR,\fBsw\fR, \fBws\fR, \fBw\fR and \fBwn\fR.
+The default value is theme-dependent.
+.\" Alternate explanation: The first character must be one of n, s, e, or w
+.\" and specifies which side the label should be placed on;
+.\" the remaining characters specify how the label is aligned on that side.
+.\" NOTE: Now allows other values as well; leave this undocumented for now
+.OP \-text text Text
+Specifies the text of the label.
+.OP \-underline underline Underline
+If set, specifies the integer index (0-based) of a character to
+underline in the text string.
+The underlined character is used for mnemonic activation.
+Mnemonic activation for a \fBttk::labelframe\fR
+sets the keyboard focus to the first child of the \fBttk::labelframe\fR widget.
+.OP \-labelwidget labelWidget LabelWidget
+The name of a widget to use for the label.
+If set, overrides the \fB\-text\fR option.
+The \fB\-labelwidget\fR must be a child of the \fBlabelframe\fR widget
+or one of the \fBlabelframe\fR's ancestors, and must belong to the
+same top-level widget as the \fBlabelframe\fR.
+.OP \-width width Width
+If specified, the widget's requested width in pixels.
+.OP \-height height Height
+If specified, the widget's requested height in pixels.
+(See \fIttk::frame(n)\fR for further notes on \fB\-width\fR and
+\fB\-height\fR).
+.SH "WIDGET COMMAND"
+.PP
+Supports the standard widget commands
+\fBconfigure\fR, \fBcget\fR, \fBidentify\fR, \fBinstate\fR, and \fBstate\fR;
+see \fIttk::widget(n)\fR.
+.SH "STYLING OPTIONS"
+.PP
+The class name for a \fBttk::labelframe\fP is \fBTLabelframe\fP.
+The text label
+has a class of \fBTLabelframe.Label\fP.
+.PP
+Dynamic states: \fBdisabled\fP, \fBreadonly\fP.
+.PP
+\fBTLabelframe\fP styling options configurable with \fBttk::style\fP
+are:
+.PP
+\fB\-background\fP \fIcolor\fP
+.br
+\fB\-bordercolor\fP \fIcolor\fP
+.br
+\fB\-borderwidth\fP \fIamount\fP
+.br
+\fB\-darkcolor\fP \fIcolor\fP
+.br
+\fB\-labelmargins\fP \fIamount\fP
+.br
+\fB\-labeloutside\fP \fIboolean\fP
+.br
+\fB\-lightcolor\fP \fIcolor\fP
+.br
+\fB\-relief\fP \fIrelief\fP
+.PP
+\fBTLabelframe.Label\fP styling options configurable with \fBttk::style\fP
+are:
+.PP
+\fB\-background\fP \fIcolor\fP
+.br
+\fB\-font\fP \fIfont\fP
+.br
+\fB\-foreground\fP \fIcolor\fP
+.PP
+Some options are only available for specific themes.
+.PP
+See the \fBttk::style\fP manual page for information on how to configure
+ttk styles.
+.SH "SEE ALSO"
+ttk::widget(n), ttk::frame(n), labelframe(n)
+.SH "KEYWORDS"
+widget, frame, container, label, groupbox
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/ttk_menubutton.n b/tk8.6/doc/ttk_menubutton.n
new file mode 100644
index 0000000..76d3829
--- /dev/null
+++ b/tk8.6/doc/ttk_menubutton.n
@@ -0,0 +1,81 @@
+'\"
+'\" Copyright (c) 2004 Joe English
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH ttk::menubutton n 8.5 Tk "Tk Themed Widget"
+.so man.macros
+.BS
+.SH NAME
+ttk::menubutton \- Widget that pops down a menu when pressed
+.SH SYNOPSIS
+\fBttk::menubutton\fR \fIpathName \fR?\fIoptions\fR?
+.BE
+.SH DESCRIPTION
+.PP
+A \fBttk::menubutton\fR widget displays a textual label and/or image,
+and displays a menu when pressed.
+.SO ttk_widget
+\-class \-compound \-cursor
+\-image \-state \-style
+\-takefocus \-text \-textvariable
+\-underline \-width
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-direction direction Direction
+Specifies where the menu is to be popped up relative
+to the menubutton.
+One of: \fBabove\fR, \fBbelow\fR, \fBleft\fR, \fBright\fR,
+or \fBflush\fR. The default is \fBbelow\fR.
+\fBflush\fR pops the menu up directly over the menubutton.
+.OP \-menu menu Menu
+Specifies the path name of the menu associated with the menubutton.
+To be on the safe side, the menu ought to be a direct child of the
+menubutton.
+.\" not documented: may go away:
+.\" .OP \-anchor anchor Anchor
+.\" .OP \-padding padding Pad
+.SH "WIDGET COMMAND"
+.PP
+Menubutton widgets support the standard
+\fBcget\fR, \fBconfigure\fR, \fBidentify\fR, \fBinstate\fR, and \fBstate\fR
+methods. No other widget methods are used.
+.SH "STANDARD STYLES"
+.PP
+\fBTtk::menubutton\fR widgets support the \fBToolbutton\fR style in all
+standard themes, which is useful for creating widgets for toolbars.
+.SH "STYLING OPTIONS"
+.PP
+The class name for a \fBttk::menubutton\fP is \fBTMenubutton\fP.
+.PP
+Dynamic states: \fBactive\fP, \fBdisabled\fP, \fBreadonly\fP.
+.PP
+\fBTMenubutton\fP styling options configurable with \fBttk::style\fP
+are:
+.PP
+\fB\-arrowsize\fP \fIamount\fP
+.br
+\fB\-background\fP \fIcolor\fP
+.br
+\fB\-foreground\fP \fIcolor\fP
+.br
+\fB\-font\fP \fIfont\fP
+.br
+\fB\-padding\fP \fIpadding\fP
+.br
+\fB\-relief\fP \fIrelief\fP
+.br
+\fB\-width\fP \fIamount\fP
+.PP
+Some options are only available for specific themes.
+.PP
+See the \fBttk::style\fP manual page for information on how to configure
+ttk styles.
+.SH "SEE ALSO"
+ttk::widget(n), menu(n), menubutton(n)
+.SH "KEYWORDS"
+widget, button, menu
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/ttk_notebook.n b/tk8.6/doc/ttk_notebook.n
new file mode 100644
index 0000000..19416b5
--- /dev/null
+++ b/tk8.6/doc/ttk_notebook.n
@@ -0,0 +1,267 @@
+'\"
+'\" Copyright (c) 2004 Joe English
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH ttk::notebook n 8.5 Tk "Tk Themed Widget"
+.so man.macros
+.BS
+.SH NAME
+ttk::notebook \- Multi-paned container widget
+.SH SYNOPSIS
+.nf
+\fBttk::notebook\fR \fIpathname \fR?\fIoptions...\fR?
+.br
+\fIpathname \fBadd\fR \fIwindow\fR ?\fIoptions...\fR?
+\fIpathname \fBinsert\fR \fIindex\fR \fIwindow\fR ?\fIoptions...\fR?
+.fi
+.BE
+.SH DESCRIPTION
+A \fBttk::notebook\fR widget manages a collection of windows
+and displays a single one at a time.
+Each slave window is associated with a \fItab\fR,
+which the user may select to change the currently-displayed window.
+.SO ttk_widget
+\-class \-cursor \-takefocus
+\-style
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-height height Height
+If present and greater than zero,
+specifies the desired height of the pane area
+(not including internal padding or tabs).
+Otherwise, the maximum height of all panes is used.
+.OP \-padding padding Padding
+Specifies the amount of extra space to add around the outside
+of the notebook.
+The padding is a list of up to four length specifications
+\fIleft top right bottom\fR.
+If fewer than four elements are specified,
+\fIbottom\fR defaults to \fItop\fR,
+\fIright\fR defaults to \fIleft\fR, and
+\fItop\fR defaults to \fIleft\fR.
+In other words, a list of three numbers specify the left, vertical, and right padding;
+a list of two numbers specify the horizontal and the vertical padding;
+a single number specifies the same padding all the way around the widget.
+.OP \-width width Width
+If present and greater than zero,
+specifies the desired width of the pane area
+(not including internal padding).
+Otherwise, the maximum width of all panes is used.
+.SH "TAB OPTIONS"
+The following options may be specified for individual notebook panes:
+.OP \-state state State
+Either \fBnormal\fR, \fBdisabled\fR or \fBhidden\fR.
+If \fBdisabled\fR, then the tab is not selectable.
+If \fBhidden\fR, then the tab is not shown.
+.OP \-sticky sticky Sticky
+Specifies how the slave window is positioned within the pane area.
+Value is a string containing zero or more of the characters
+\fBn, s, e,\fR or \fBw\fR.
+Each letter refers to a side (north, south, east, or west)
+that the slave window will
+.QW stick
+to, as per the \fBgrid\fR geometry manager.
+.OP \-padding padding Padding
+Specifies the amount of extra space to add between the notebook and this pane.
+Syntax is the same as for the widget \fB\-padding\fR option.
+.OP \-text text Text
+Specifies a string to be displayed in the tab.
+.OP \-image image Image
+Specifies an image to display in the tab.
+See \fIttk_widget(n)\fR for details.
+.OP \-compound compound Compound
+Specifies how to display the image relative to the text,
+in the case both \fB\-text\fR and \fB\-image\fR are present.
+See \fIlabel(n)\fR for legal values.
+.OP \-underline underline Underline
+Specifies the integer index (0-based) of a character to underline
+in the text string.
+The underlined character is used for mnemonic activation
+if \fBttk::notebook::enableTraversal\fR is called.
+.SH "TAB IDENTIFIERS"
+The \fItabid\fR argument to the following commands may take
+any of the following forms:
+.IP \(bu
+An integer between zero and the number of tabs;
+.IP \(bu
+The name of a slave window;
+.IP \(bu
+A positional specification of the form
+.QW @\fIx\fR,\fIy\fR ,
+which identifies the tab
+.IP \(bu
+The literal string
+.QW \fBcurrent\fR ,
+which identifies the currently-selected tab; or:
+.IP \(bu
+The literal string
+.QW \fBend\fR ,
+which returns the number of tabs
+(only valid for
+.QW "\fIpathname \fBindex\fR" ).
+.SH "WIDGET COMMAND"
+.TP
+\fIpathname \fBadd \fIwindow\fR ?\fIoptions...\fR?
+Adds a new tab to the notebook.
+See \fBTAB OPTIONS\fR for the list of available \fIoptions\fR.
+If \fIwindow\fR is currently managed by the notebook but hidden,
+it is restored to its previous position.
+.TP
+\fIpathname \fBconfigure\fR ?\fIoptions\fR?
+See \fIttk::widget(n)\fR.
+.TP
+\fIpathname \fBcget \fIoption\fR
+See \fIttk::widget(n)\fR.
+.TP
+\fIpathname \fBforget \fItabid\fR
+Removes the tab specified by \fItabid\fR,
+unmaps and unmanages the associated window.
+.TP
+\fIpathname \fBhide \fItabid\fR
+Hides the tab specified by \fItabid\fR.
+The tab will not be displayed, but the associated window
+remains managed by the notebook and its configuration remembered.
+Hidden tabs may be restored with the \fBadd\fR command.
+.TP
+\fIpathname \fBidentify\fI component x y\fR
+Returns the name of the element under the point given by \fIx\fR and \fIy\fR,
+or the empty string if no component is present at that location.
+The following subcommands are supported:
+.RS
+.TP
+\fIpathname \fBidentify element\fR \fIx y\fR
+Returns the name of the element at the specified location.
+.TP
+\fIpathname \fBidentify tab\fR \fIx y\fR
+Returns the index of the tab at the specified location.
+.RE
+.TP
+\fIpathname \fBindex \fItabid\fR
+Returns the numeric index of the tab specified by \fItabid\fR,
+or the total number of tabs if \fItabid\fR is the string
+.QW \fBend\fR .
+.TP
+\fIpathname \fBinsert \fIpos subwindow options...\fR
+Inserts a pane at the specified position.
+\fIpos\fR is either the string \fBend\fR, an integer index,
+or the name of a managed subwindow.
+If \fIsubwindow\fR is already managed by the notebook,
+moves it to the specified position.
+See \fBTAB OPTIONS\fR for the list of available options.
+.TP
+\fIpathname \fBinstate \fIstatespec \fR?\fIscript...\fR?
+See \fIttk::widget(n)\fR.
+.TP
+\fIpathname \fBselect\fR ?\fItabid\fR?
+Selects the specified tab.
+The associated slave window will be displayed,
+and the previously-selected window (if different) is unmapped.
+If \fItabid\fR is omitted, returns the widget name of the
+currently selected pane.
+.TP
+\fIpathname \fBstate\fR ?\fIstatespec\fR?
+See \fIttk::widget(n)\fR.
+.TP
+\fIpathname \fBtab \fItabid\fR ?\fI\-option \fR?\fIvalue ...\fR
+Query or modify the options of the specific tab.
+If no \fI\-option\fR is specified,
+returns a dictionary of the tab option values.
+If one \fI\-option\fR is specified,
+returns the value of that \fIoption\fR.
+Otherwise, sets the \fI\-option\fRs to the corresponding \fIvalue\fRs.
+See \fBTAB OPTIONS\fR for the available options.
+.TP
+\fIpathname \fBtabs\fR
+Returns the list of windows managed by the notebook, in the index order of
+their associated tabs.
+.SH "KEYBOARD TRAVERSAL"
+To enable keyboard traversal for a toplevel window
+containing a notebook widget \fI$nb\fR, call:
+.CS
+ttk::notebook::enableTraversal $nb
+.CE
+.PP
+This will extend the bindings for the toplevel window
+containing the notebook as follows:
+.IP \(bu
+\fBControl-Tab\fR selects the tab following the currently selected one.
+.IP \(bu
+\fBControl-Shift-Tab\fR selects the tab preceding the currently selected one.
+.IP \(bu
+\fBAlt-\fIK\fR, where \fIK\fR is the mnemonic (underlined) character
+of any tab, will select that tab.
+.PP
+Multiple notebooks in a single toplevel may be enabled for traversal,
+including nested notebooks.
+However, notebook traversal only works properly if all panes
+are direct children of the notebook.
+.SH "VIRTUAL EVENTS"
+The notebook widget generates a \fB<<NotebookTabChanged>>\fR
+virtual event after a new tab is selected.
+.SH "EXAMPLE"
+.CS
+pack [\fBttk::notebook\fR .nb]
+\&.nb add [frame .nb.f1] \-text "First tab"
+\&.nb add [frame .nb.f2] \-text "Second tab"
+\&.nb select .nb.f2
+ttk::notebook::enableTraversal .nb
+.CE
+.SH "STYLING OPTIONS"
+.PP
+The class name for a \fBttk::notebook\fP is \fBTNotebook\fP. The tab has
+a class name of \fBTNotebook.Tab\fP
+.PP
+Dynamic states: \fBactive\fP, \fBdisabled\fP, \fBselected\fP.
+.PP
+\fBTNotebook\fP styling options configurable with \fBttk::style\fP
+are:
+.PP
+\fB\-background\fP \fIcolor\fP
+.br
+\fB\-bordercolor\fP \fIcolor\fP
+.br
+\fB\-darkcolor\fP \fIcolor\fP
+.br
+\fB\-foreground\fP \fIcolor\fP
+.br
+\fB\-lightcolor\fP \fIcolor\fP
+.br
+\fB\-padding\fP \fIpadding\fP
+.br
+\fB\-tabmargins\fP \fIpadding\fP
+.br
+\fB\-tabposition\fP \fIside\fP
+.br
+.PP
+\fBTNotebook.Tab\fP styling options configurable with \fBttk::style\fP
+are:
+.PP
+\fB\-background\fP \fIcolor\fP
+.br
+\fB\-bordercolor\fP \fIcolor\fP
+.br
+\fB\-expand\fP \fIpadding\fP
+.RS
+Defines how much the tab grows in size. Usually used with the
+\fBselected\fP dynamic state. \fB\-tabmargins\fP should be
+set appropriately so that there is room for the tab growth.
+.RE
+\fB\-font\fP \fIfont\fP
+.br
+\fB\-foreground\fP \fIcolor\fP
+.br
+\fB\-padding\fP \fIpadding\fP
+.PP
+Some options are only available for specific themes.
+.PP
+See the \fBttk::style\fP manual page for information on how to configure
+ttk styles.
+.SH "SEE ALSO"
+ttk::widget(n), grid(n)
+.SH "KEYWORDS"
+pane, tab
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/ttk_panedwindow.n b/tk8.6/doc/ttk_panedwindow.n
new file mode 100644
index 0000000..d6b3ea3
--- /dev/null
+++ b/tk8.6/doc/ttk_panedwindow.n
@@ -0,0 +1,162 @@
+'\"
+'\" Copyright (c) 2005 Joe English
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH ttk::panedwindow n 8.5 Tk "Tk Themed Widget"
+.so man.macros
+.BS
+.SH NAME
+ttk::panedwindow \- Multi-pane container window
+.SH SYNOPSIS
+.nf
+\fBttk::panedwindow\fR \fIpathname \fR?\fIoptions\fR?
+.br
+\fIpathname \fBadd\fR \fIwindow\fR ?\fIoptions...\fR?
+\fIpathname \fBinsert\fR \fIindex\fR \fIwindow\fR ?\fIoptions...\fR?
+.fi
+.BE
+.SH DESCRIPTION
+A \fBttk::panedwindow\fR widget displays a number of subwindows,
+stacked either vertically or horizontally.
+The user may adjust the relative sizes of the subwindows
+by dragging the sash between panes.
+.SO ttk_widget
+\-class \-cursor \-takefocus
+\-style
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-orient orient Orient
+Specifies the orientation of the window.
+If \fBvertical\fR, subpanes are stacked top-to-bottom;
+if \fBhorizontal\fR, subpanes are stacked left-to-right.
+.OP \-width width Width
+If present and greater than zero,
+specifies the desired width of the widget in pixels.
+Otherwise, the requested width is determined by the width
+of the managed windows.
+.OP \-height height Height
+If present and greater than zero,
+specifies the desired height of the widget in pixels.
+Otherwise, the requested height is determined by the height
+of the managed windows.
+.SH "PANE OPTIONS"
+The following options may be specified for each pane:
+.OP \-weight weight Weight
+An integer specifying the relative stretchability of the pane.
+When the paned window is resized, the extra space is added
+or subtracted to each pane proportionally to its \fB\-weight\fR.
+.SH "WIDGET COMMAND"
+Supports the standard \fBconfigure\fR, \fBcget\fR, \fBstate\fR,
+and \fBinstate\fR commands; see \fIttk::widget(n)\fR for details.
+Additional commands:
+.TP
+\fIpathname \fBadd \fIsubwindow options...\fR
+Adds a new pane to the window.
+See \fBPANE OPTIONS\fR for the list of available options.
+.TP
+\fIpathname \fBforget \fIpane\fR
+Removes the specified subpane from the widget.
+\fIpane\fR is either an integer index or the name of a managed subwindow.
+.TP
+\fIpathname \fBidentify \fIcomponent x y\fR
+Returns the name of the element under the point given by \fIx\fR and \fIy\fR,
+or the empty string if no component is present at that location.
+If \fIcomponent\fR is omitted, it defaults to \fBsash\fR.
+The following subcommands are supported:
+.RS
+.TP
+\fIpathname \fBidentify element \fIx y\fR
+Returns the name of the element at the specified location.
+.TP
+\fIpathname \fBidentify sash \fIx y\fR
+Returns the index of the sash at the specified location.
+.RE
+.TP
+\fIpathname \fBinsert \fIpos subwindow options...\fR
+Inserts a pane at the specified position.
+\fIpos\fR is either the string \fBend\fR, an integer index,
+or the name of a managed subwindow.
+If \fIsubwindow\fR is already managed by the paned window,
+moves it to the specified position.
+See \fBPANE OPTIONS\fR for the list of available options.
+.TP
+\fIpathname \fBpane \fIpane \-option \fR?\fIvalue \fR?\fI\-option value...\fR
+Query or modify the options of the specified \fIpane\fR,
+where \fIpane\fR is either an integer index or the name of a managed subwindow.
+If no \fI\-option\fR is specified, returns a dictionary of the pane
+option values.
+If one \fI\-option\fR is specified, returns the value of that \fIoption\fR.
+Otherwise, sets the \fI\-option\fRs to the corresponding \fIvalue\fRs.
+.TP
+\fIpathname \fBpanes\fR
+Returns the list of all windows managed by the widget, in the index order of
+their associated panes.
+.TP
+\fIpathname \fBsashpos \fIindex\fR ?\fInewpos\fR?
+If \fInewpos\fR is specified, sets the position
+of sash number \fIindex\fR.
+May adjust the positions of adjacent sashes
+to ensure that positions are monotonically increasing.
+Sash positions are further constrained to be between 0
+and the total size of the widget.
+.\" Full story: "total size" is either the -height (resp -width),
+.\" or the actual window height (resp actual window width),
+.\" depending on which changed most recently.
+Returns the new position of sash number \fIindex\fR.
+.\" Full story: new position may be different than the requested position.
+.PP
+The panedwindow widget also supports the following generic \fBttk::widget\fR
+widget subcommands (see \fIttk::widget(n)\fR for details):
+.DS
+.ta 5.5c 11c
+\fBcget\fR \fBconfigure\fR
+\fBinstate\fR \fBstate\fR
+.DE
+.SH "VIRTUAL EVENTS"
+.PP
+The panedwindow widget generates an \fB<<EnteredChild>>\fR virtual event on
+LeaveNotify/NotifyInferior events, because Tk does not execute binding scripts
+for <Leave> events when the pointer crosses from a parent to a child. The
+panedwindow widget needs to know when that happens.
+.SH "STYLING OPTIONS"
+.PP
+The class name for a \fBttk::panedwindow\fP is \fBTPanedwindow\fP. The
+sash has a class name of \fBSash\fP.
+.PP
+\fBTPanedwindow\fP styling options configurable with \fBttk::style\fP
+are:
+.PP
+\fB\-background\fP \fIcolor\fP
+.PP
+\fBSash\fP styling options configurable with \fBttk::style\fP
+are:
+.PP
+\fB\-background\fP \fIcolor\fP
+.br
+\fB\-bordercolor\fP \fIcolor\fP
+.br
+\fB\-gripcount\fP \fIcount\fP
+.br
+\fB\-handlepad\fP \fIamount\fP
+.br
+\fB\-handlesize\fP \fIamount\fP
+.br
+\fB\-lightcolor\fP \fIcolor\fP
+.br
+\fB\-sashpad\fP \fIamount\fP
+.br
+\fB\-sashrelief\fP \fIrelief\fP
+.br
+\fB\-sashthickness\fP \fIamount\fP
+.PP
+Some options are only available for specific themes.
+.PP
+See the \fBttk::style\fP manual page for information on how to configure
+ttk styles.
+.SH "SEE ALSO"
+ttk::widget(n), ttk::notebook(n), panedwindow(n)
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/ttk_progressbar.n b/tk8.6/doc/ttk_progressbar.n
new file mode 100644
index 0000000..1687123
--- /dev/null
+++ b/tk8.6/doc/ttk_progressbar.n
@@ -0,0 +1,122 @@
+'\"
+'\" Copyright (c) 2005 Joe English
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH ttk::progressbar n 8.5 Tk "Tk Themed Widget"
+.so man.macros
+.BS
+.SH NAME
+ttk::progressbar \- Provide progress feedback
+.SH SYNOPSIS
+\fBttk::progressbar\fR \fIpathName \fR?\fIoptions\fR?
+.BE
+.SH DESCRIPTION
+.PP
+A \fBttk::progressbar\fR widget shows the status of a long-running
+operation. They can operate in two modes: \fIdeterminate\fR mode shows the
+amount completed relative to the total amount of work to be done, and
+\fIindeterminate\fR mode provides an animated display to let the user know
+that something is happening.
+.SO ttk_widget
+\-class \-cursor \-takefocus
+\-style
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-length length Length
+Specifies the length of the long axis of the progress bar
+(width if horizontal, height if vertical).
+.OP \-maximum maximum Maximum
+A floating point number specifying the maximum \fB\-value\fR.
+Defaults to 100.
+.OP \-mode mode Mode
+One of \fBdeterminate\fR or \fBindeterminate\fR.
+.OP \-orient orient Orient
+One of \fBhorizontal\fR or \fBvertical\fR.
+Specifies the orientation of the progress bar.
+.OP \-phase phase Phase
+Read-only option.
+The widget periodically increments the value of this option
+whenever the \fB\-value\fR is greater than 0 and,
+in \fIdeterminate\fR mode, less than \fB\-maximum\fR.
+This option may be used by the current theme
+to provide additional animation effects.
+.OP \-value value Value
+The current value of the progress bar.
+In \fIdeterminate\fR mode, this represents the amount of work completed.
+In \fIindeterminate\fR mode, it is interpreted modulo \fB\-maximum\fR;
+that is, the progress bar completes one
+.QW cycle
+when the \fB\-value\fR increases by \fB\-maximum\fR.
+.OP \-variable variable Variable
+The name of a global Tcl variable which is linked to the \fB\-value\fR.
+If specified, the \fB\-value\fR of the progress bar is
+automatically set to the value of the variable whenever
+the latter is modified.
+.SH "WIDGET COMMAND"
+.PP
+.TP
+\fIpathName \fBcget \fIoption\fR
+Returns the current value of the specified \fIoption\fR; see \fIttk::widget(n)\fR.
+.TP
+\fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
+Modify or query widget options; see \fIttk::widget(n)\fR.
+.TP
+\fIpathName \fBidentify \fIx y\fR
+Returns the name of the element at position \fIx\fR, \fIy\fR.
+See \fIttk::widget(n)\fR.
+.TP
+\fIpathName \fBinstate \fIstatespec\fR ?\fIscript\fR?
+Test the widget state; see \fIttk::widget(n)\fR.
+.TP
+\fIpathName \fBstart\fR ?\fIinterval\fR?
+Begin autoincrement mode:
+schedules a recurring timer event that calls \fBstep\fR
+every \fIinterval\fR milliseconds.
+If omitted, \fIinterval\fR defaults to 50 milliseconds (20 steps/second).
+.TP
+\fIpathName \fBstate\fR ?\fIstateSpec\fR?
+Modify or query the widget state; see \fIttk::widget(n)\fR.
+.TP
+\fIpathName \fBstep\fR ?\fIamount\fR?
+Increments the \fB\-value\fR by \fIamount\fR.
+\fIamount\fR defaults to 1.0 if omitted.
+.TP
+\fIpathName \fBstop\fR
+Stop autoincrement mode:
+cancels any recurring timer event initiated by \fIpathName \fBstart\fR.
+.SH "STYLING OPTIONS"
+.PP
+The class name for a \fBttk::progressbar\fP is \fBTProgressbar\fP.
+.PP
+\fBTProgressbar\fP styling options configurable with \fBttk::style\fP
+are:
+.PP
+\fB\-background\fP \fIcolor\fP
+.br
+\fB\-bordercolor\fP \fIcolor\fP
+.br
+\fB\-darkcolor\fP \fIcolor\fP
+.br
+\fB\-lightcolor\fP \fIcolor\fP
+.br
+\fB\-maxphase\fP
+.RS
+For the aqua theme.
+.RE
+\fB\-period\fP
+.RS
+For the aqua theme.
+.RE
+\fB\-troughcolor\fP \fIcolor\fP
+.PP
+Some options are only available for specific themes.
+.PP
+See the \fBttk::style\fP manual page for information on how to configure
+ttk styles.
+.SH "SEE ALSO"
+ttk::widget(n)
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/ttk_radiobutton.n b/tk8.6/doc/ttk_radiobutton.n
new file mode 100644
index 0000000..1344ae2
--- /dev/null
+++ b/tk8.6/doc/ttk_radiobutton.n
@@ -0,0 +1,102 @@
+'\"
+'\" Copyright (c) 2004 Joe English
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH ttk::radiobutton n 8.5 Tk "Tk Themed Widget"
+.so man.macros
+.BS
+.SH NAME
+ttk::radiobutton \- Mutually exclusive option widget
+.SH SYNOPSIS
+\fBttk::radiobutton\fR \fIpathName \fR?\fIoptions\fR?
+.BE
+.SH DESCRIPTION
+.PP
+\fBttk::radiobutton\fR widgets are used in groups to show or change
+a set of mutually-exclusive options.
+Radiobuttons are linked to a Tcl variable,
+and have an associated value; when a radiobutton is clicked,
+it sets the variable to its associated value.
+.SO ttk_widget
+\-class \-compound \-cursor
+\-image \-state \-style
+\-takefocus \-text \-textvariable
+\-underline \-width
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-command command Command
+A Tcl script to evaluate whenever the widget is invoked.
+.OP \-value Value Value
+The value to store in the associated \fB\-variable\fR
+when the widget is selected.
+.OP \-variable variable Variable
+The name of a global variable whose value is linked to the widget.
+Default value is \fB::selectedButton\fR.
+.SH "WIDGET COMMAND"
+.PP
+In addition to the standard
+\fBcget\fR, \fBconfigure\fR, \fBidentify\fR, \fBinstate\fR, and \fBstate\fR
+commands, radiobuttons support the following additional
+widget commands:
+.TP
+\fIpathname\fB invoke\fR
+Sets the \fB\-variable\fR to the \fB\-value\fR, selects the widget,
+and evaluates the associated \fB\-command\fR.
+Returns the result of the \fB\-command\fR, or the empty
+string if no \fB\-command\fR is specified.
+.\" Missing: select, deselect. Useful?
+.\" Missing: flash. This is definitely not useful.
+.SH "WIDGET STATES"
+.PP
+The widget does not respond to user input if the \fBdisabled\fR state is set.
+The widget sets the \fBselected\fR state whenever
+the linked \fB\-variable\fR is set to the widget's \fB\-value\fR,
+and clears it otherwise.
+The widget sets the \fBalternate\fR state whenever the
+linked \fB\-variable\fR is unset.
+(The \fBalternate\fR state may be used to indicate a
+.QW tri-state
+or
+.QW indeterminate
+selection.)
+.SH "STANDARD STYLES"
+.PP
+\fBTtk::radiobutton\fR widgets support the \fBToolbutton\fR style in all
+standard themes, which is useful for creating widgets for toolbars.
+.SH "STYLING OPTIONS"
+.PP
+The class name for a \fBttk::radiobutton\fP is \fBTRadiobutton\fP.
+.PP
+Dynamic states: \fBactive\fP, \fBalternate\fP, \fBdisabled\fP,
+\fBpressed\fP, \fBreadonly\fP, \fBselected\fP.
+.PP
+\fBTRadiobutton\fP styling options configurable with \fBttk::style\fP
+are:
+.PP
+\fB\-background\fP \fIcolor\fP
+.br
+\fB\-foreground\fP \fIcolor\fP
+.br
+\fB\-indicatorbackground\fP \fIcolor\fP
+.br
+\fB\-indicatorcolor\fP \fIcolor\fP
+.br
+\fB\-indicatormargin\fP \fIpadding\fP
+.br
+\fB\-indicatorrelief\fP \fIrelief\fP
+.br
+\fB\-padding\fP \fIpadding\fP
+.PP
+Some options are only available for specific themes.
+.PP
+See the \fBttk::style\fP manual page for information on how to configure
+ttk styles.
+.SH "SEE ALSO"
+ttk::widget(n), ttk::checkbutton(n), radiobutton(n)
+.SH "KEYWORDS"
+widget, button, option
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/ttk_scale.n b/tk8.6/doc/ttk_scale.n
new file mode 100644
index 0000000..f8f5072
--- /dev/null
+++ b/tk8.6/doc/ttk_scale.n
@@ -0,0 +1,130 @@
+.\"
+.\" Copyright (c) 2008 Donal Fellows
+.\"
+.\" See the file "license.terms" for information on usage and redistribution
+.\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+.\"
+.TH ttk::scale n 8.5 Tk "Tk Themed Widget"
+.so man.macros
+.BS
+.SH NAME
+ttk::scale \- Create and manipulate a scale widget
+.SH SYNOPSIS
+\fBttk::scale \fIpathName \fR?\fIoptions...\fR?
+.BE
+.SH DESCRIPTION
+.PP
+A \fBttk::scale\fR widget is typically used to control the numeric value of a
+linked variable that varies uniformly over some range. A scale displays a
+\fIslider\fR that can be moved along over a \fItrough\fR, with the relative
+position of the slider over the trough indicating the value of the variable.
+.SO ttk_widget
+\-class \-cursor \-style
+\-takefocus
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-command command Command
+Specifies the prefix of a Tcl command to invoke whenever the scale's value is
+changed via a widget command. The actual command consists of this option
+followed by a space and a real number indicating the new value of the scale.
+.OP \-from from From
+A real value corresponding to the left or top end of the scale.
+.OP \-length length Length
+Specifies the desired long dimension of the scale in screen units (i.e. any of
+the forms acceptable to \fBTk_GetPixels\fR). For vertical scales this is the
+scale's height; for horizontal scales it is the scale's width.
+.OP \-orient orient Orient
+Specifies which orientation whether the widget should be laid out horizontally
+or vertically. Must be either \fBhorizontal\fR or \fBvertical\fR or an
+abbreviation of one of these.
+.OP \-to to To
+Specifies a real value corresponding to the right or bottom end of the scale.
+This value may be either less than or greater than the \fB\-from\fR option.
+.OP \-value value Value
+Specifies the current floating-point value of the variable.
+.OP \-variable variable Variable
+Specifies the name of a global variable to link to the scale. Whenever the
+value of the variable changes, the scale will update to reflect this value.
+Whenever the scale is manipulated interactively, the variable will be modified
+to reflect the scale's new value.
+.SH "WIDGET COMMAND"
+.PP
+.TP
+\fIpathName \fBcget \fIoption\fR
+.
+Returns the current value of the specified \fIoption\fR; see
+\fIttk::widget(n)\fR.
+.TP
+\fIpathName \fBconfigure \fR?\fIoption\fR? ?\fIvalue option value ...\fR?
+.
+Modify or query widget options; see \fIttk::widget(n)\fR.
+.TP
+\fIpathName \fBget \fR?\fIx y\fR?
+.
+Get the current value of the \fB\-value\fR option, or the value corresponding
+to the coordinates \fIx,y\fR if they are specified. \fIX\fR and \fIy\fR are
+pixel coordinates relative to the scale widget origin.
+.TP
+\fIpathName \fBidentify \fIx y\fR
+Returns the name of the element at position \fIx\fR, \fIy\fR.
+See \fIttk::widget(n)\fR.
+.TP
+\fIpathName \fBinstate \fIstatespec\fR ?\fIscript\fR?
+.
+Test the widget state; see \fIttk::widget(n)\fR.
+.TP
+\fIpathName \fBset \fIvalue\fR
+.
+Set the value of the widget (i.e. the \fB\-value\fR option) to \fIvalue\fR.
+The value will be clipped to the range given by the \fB\-from\fR and
+\fB\-to\fR options. Note that setting the linked variable (i.e. the variable
+named in the \fB\-variable\fR option) does not cause such clipping.
+.TP
+\fIpathName \fBstate\fR ?\fIstateSpec\fR?
+.
+Modify or query the widget state; see \fIttk::widget(n)\fR.
+.SH "INTERNAL COMMANDS"
+.PP
+.TP
+\fIpathName \fBcoords \fR?\fIvalue\fR?
+.
+Get the coordinates corresponding to \fIvalue\fR, or the coordinates
+corresponding to the current value of the \fB\-value\fR option if \fIvalue\fR
+is omitted.
+.SH "STYLING OPTIONS"
+.PP
+The class name for a \fBttk::scale\fP is \fBTScale\fP.
+.PP
+Dynamic states: \fBactive\fP.
+.PP
+\fBTProgressbar\fP styling options configurable with \fBttk::style\fP
+are:
+.PP
+\fB\-background\fP \fIcolor\fP
+.br
+\fB\-borderwidth\fP \fIamount\fP
+.br
+\fB\-darkcolor\fP \fIcolor\fP
+.br
+\fB\-groovewidth\fP \fIamount\fP
+.br
+\fB\-lightcolor\fP \fIcolor\fP
+.br
+\fB\-sliderwidth\fP \fIamount\fP
+.br
+\fB\-troughcolor\fP \fIcolor\fP
+.br
+\fB\-troughrelief\fP \fIrelief\fP
+.PP
+Some options are only available for specific themes.
+.PP
+See the \fBttk::style\fP manual page for information on how to configure
+ttk styles.
+.SH "SEE ALSO"
+ttk::widget(n), scale(n)
+.SH KEYWORDS
+scale, slider, trough, widget
+.\" Local Variables:
+.\" mode: nroff
+.\" fill-column: 78
+.\" End:
diff --git a/tk8.6/doc/ttk_scrollbar.n b/tk8.6/doc/ttk_scrollbar.n
new file mode 100644
index 0000000..bd80760
--- /dev/null
+++ b/tk8.6/doc/ttk_scrollbar.n
@@ -0,0 +1,196 @@
+'\"
+'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
+'\" Copyright (c) 2004 Joe English
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH ttk::scrollbar n 8.5 Tk "Tk Themed Widget"
+.so man.macros
+.BS
+.SH NAME
+ttk::scrollbar \- Control the viewport of a scrollable widget
+.SH SYNOPSIS
+\fBttk::scrollbar\fR \fIpathName \fR?\fIoptions...\fR?
+.BE
+.SH DESCRIPTION
+.PP
+\fBttk::scrollbar\fR widgets are typically linked to an associated window
+that displays a document of some sort, such as a file being edited or a
+drawing.
+A scrollbar displays a \fIthumb\fR in the middle portion of the scrollbar,
+whose position and size provides information about the portion of the
+document visible in the associated window.
+The thumb may be dragged by the user to control the visible region.
+Depending on the theme, two or more arrow buttons may also be present;
+these are used to scroll the visible region in discrete units.
+.SO ttk_widget
+\-class \-cursor \-style
+\-takefocus
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-command command Command
+A Tcl script prefix to evaluate
+to change the view in the widget associated with the scrollbar.
+Additional arguments are appended to the value of this option,
+as described in \fBSCROLLING COMMANDS\fR below,
+whenever the user requests a view change by manipulating the scrollbar.
+.RS
+.PP
+This option typically consists of a two-element list,
+containing the name of a scrollable widget followed by
+either \fBxview\fR (for horizontal scrollbars)
+or \fByview\fR (for vertical scrollbars).
+.RE
+.OP \-orient orient Orient
+One of \fBhorizontal\fR or \fBvertical\fR.
+Specifies the orientation of the scrollbar.
+.SH "WIDGET COMMAND"
+.PP
+.TP
+\fIpathName \fBcget \fIoption\fR
+Returns the current value of the specified \fIoption\fR; see \fIttk::widget(n)\fR.
+.TP
+\fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
+Modify or query widget options; see \fIttk::widget(n)\fR.
+.TP
+\fIpathName \fBget\fR
+Returns the scrollbar settings in the form of a list whose
+elements are the arguments to the most recent \fBset\fR widget command.
+.TP
+\fIpathName \fBidentify \fIx y\fR
+Returns the name of the element at position \fIx\fR, \fIy\fR.
+See \fIttk::widget(n)\fR.
+.TP
+\fIpathName \fBinstate \fIstatespec\fR ?\fIscript\fR?
+Test the widget state; see \fIttk::widget(n)\fR.
+.TP
+\fIpathName \fBset \fIfirst last\fR
+This command is normally invoked by the scrollbar's associated widget
+from an \fB\-xscrollcommand\fR or \fB\-yscrollcommand\fR callback.
+Specifies the visible range to be displayed.
+\fIfirst\fR and \fIlast\fR are real fractions between 0 and 1.
+.TP
+\fIpathName \fBstate\fR ?\fIstateSpec\fR?
+Modify or query the widget state; see \fIttk::widget(n)\fR.
+.SH "INTERNAL COMMANDS"
+.PP
+The following widget commands are used internally
+by the \fBTScrollbar\fP widget class bindings.
+.TP
+\fIpathName \fBdelta \fIdeltaX deltaY\fR
+Returns a real number indicating the fractional change in
+the scrollbar setting that corresponds to a given change
+in thumb position. For example, if the scrollbar is horizontal,
+the result indicates how much the scrollbar setting must change
+to move the thumb \fIdeltaX\fR pixels to the right (\fIdeltaY\fR is
+ignored in this case).
+If the scrollbar is vertical, the result indicates how much the
+scrollbar setting must change to move the thumb \fIdeltaY\fR pixels
+down. The arguments and the result may be zero or negative.
+.TP
+\fIpathName \fBfraction \fIx y\fR
+Returns a real number between 0 and 1 indicating where the point
+given by \fIx\fR and \fIy\fR lies in the trough area of the scrollbar,
+where 0.0 corresponds to the top or left of the trough
+and 1.0 corresponds to the bottom or right.
+\fIX\fR and \fIy\fR are pixel coordinates relative to the scrollbar
+widget.
+If \fIx\fR and \fIy\fR refer to a point outside the trough, the closest
+point in the trough is used.
+.SH "SCROLLING COMMANDS"
+.PP
+When the user interacts with the scrollbar, for example by dragging
+the thumb, the scrollbar notifies the associated widget that it
+must change its view.
+The scrollbar makes the notification by evaluating a Tcl command
+generated from the scrollbar's \fB\-command\fR option.
+The command may take any of the following forms.
+In each case, \fIprefix\fR is the contents of the
+\fB\-command\fR option, which usually has a form like \fB.t yview\fR
+.TP
+\fIprefix \fBmoveto \fIfraction\fR
+\fIFraction\fR is a real number between 0 and 1.
+The widget should adjust its view so that the point given
+by \fIfraction\fR appears at the beginning of the widget.
+If \fIfraction\fR is 0 it refers to the beginning of the
+document. 1.0 refers to the end of the document, 0.333
+refers to a point one-third of the way through the document,
+and so on.
+.TP
+\fIprefix \fBscroll \fInumber \fBunits\fR
+The widget should adjust its view by \fInumber\fR units.
+The units are defined in whatever way makes sense for the widget,
+such as characters or lines in a text widget.
+\fINumber\fR is either 1, which means one unit should scroll off
+the top or left of the window, or \-1, which means that one unit
+should scroll off the bottom or right of the window.
+.TP
+\fIprefix \fBscroll \fInumber \fBpages\fR
+The widget should adjust its view by \fInumber\fR pages.
+It is up to the widget to define the meaning of a page; typically
+it is slightly less than what fits in the window, so that there
+is a slight overlap between the old and new views.
+\fINumber\fR is either 1, which means the next page should
+become visible, or \-1, which means that the previous page should
+become visible.
+.SH "WIDGET STATES"
+.PP
+The scrollbar automatically sets the \fBdisabled\fR state bit.
+when the entire range is visible (range is 0.0 to 1.0),
+and clears it otherwise.
+It also sets the \fBactive\fR and \fBpressed\fR state flags
+of individual elements, based on the position and state of the mouse pointer.
+.SH EXAMPLE
+.PP
+.CS
+set f [frame .f]
+ttk::scrollbar $f.hsb \-orient horizontal \-command [list $f.t xview]
+ttk::scrollbar $f.vsb \-orient vertical \-command [list $f.t yview]
+text $f.t \-xscrollcommand [list $f.hsb set] \-yscrollcommand [list $f.vsb set]
+grid $f.t \-row 0 \-column 0 \-sticky nsew
+grid $f.vsb \-row 0 \-column 1 \-sticky nsew
+grid $f.hsb \-row 1 \-column 0 \-sticky nsew
+grid columnconfigure $f 0 \-weight 1
+grid rowconfigure $f 0 \-weight 1
+pack $f
+.CE
+.SH "STYLING OPTIONS"
+.PP
+The class name for a \fBttk::scrollbar\fP is \fBTScrollbar\fP.
+.PP
+Dynamic states: \fBactive\fP, \fBdisabled\fP.
+.PP
+\fBTScrollbar\fP (or more specifically \fBVertical.TScrollbar\fP and
+\fBHorizontal.TScrollbar\fP) styling options that are configurable with
+\fBttk::style\fP are:
+.PP
+\fB\-arrowcolor\fP \fIcolor\fP
+.br
+\fB\-arrowsize\fP \fIamount\fP
+.br
+\fB\-background\fP \fIcolor\fP
+.br
+\fB\-bordercolor\fP \fIcolor\fP
+.br
+\fB\-darkcolor\fP \fIcolor\fP (color of the dark part of the 3D relief)
+.br
+\fB\-foreground\fP \fIcolor\fP
+.br
+\fB\-gripcount\fP \fIcount\fP (number of lines on the thumb)
+.br
+\fB\-lightcolor\fP \fIcolor\fP (color of the light part of the 3D relief)
+.br
+\fB\-troughcolor\fP \fIcolor\fP
+.PP
+Some options are only available for specific themes.
+.PP
+See the \fBttk::style\fP manual page for information on how to configure
+ttk styles.
+.SH "SEE ALSO"
+ttk::widget(n), scrollbar(n)
+.SH KEYWORDS
+scrollbar, widget
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/ttk_separator.n b/tk8.6/doc/ttk_separator.n
new file mode 100644
index 0000000..4befb0a
--- /dev/null
+++ b/tk8.6/doc/ttk_separator.n
@@ -0,0 +1,52 @@
+'\"
+'\" Copyright (c) 2004 Joe English
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH ttk::separator n 8.5 Tk "Tk Themed Widget"
+.so man.macros
+.BS
+.SH NAME
+ttk::separator \- Separator bar
+.SH SYNOPSIS
+\fBttk::separator\fR \fIpathName \fR?\fIoptions\fR?
+.BE
+.SH DESCRIPTION
+.PP
+A \fBttk::separator\fR widget displays a horizontal or vertical separator
+bar.
+.SO ttk_widget
+\-class \-cursor
+\-style \-takefocus
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-orient orient Orient
+One of \fBhorizontal\fR or \fBvertical\fR.
+Specifies the orientation of the separator.
+.SH "WIDGET COMMAND"
+.PP
+Separator widgets support the standard
+\fBcget\fR, \fBconfigure\fR, \fBidentify\fR, \fBinstate\fR, and \fBstate\fR
+methods. No other widget methods are used.
+.PP
+.SH "STYLING OPTIONS"
+.PP
+The class name for a \fBttk::separator\fP is \fBTSeparator\fP.
+.PP
+\fBTSeparator\fP styling options configurable with \fBttk::style\fP
+are:
+.PP
+\fB\-background\fP \fIcolor\fP
+.PP
+Some options are only available for specific themes.
+.PP
+See the \fBttk::style\fP manual page for information on how to configure
+ttk styles.
+.SH "SEE ALSO"
+ttk::widget(n)
+.SH "KEYWORDS"
+widget, separator
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/ttk_sizegrip.n b/tk8.6/doc/ttk_sizegrip.n
new file mode 100644
index 0000000..707a17e
--- /dev/null
+++ b/tk8.6/doc/ttk_sizegrip.n
@@ -0,0 +1,82 @@
+'\"
+'\" Copyright (c) 2006 Joe English
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH ttk::sizegrip n 8.5 Tk "Tk Themed Widget"
+.so man.macros
+.BS
+.SH NAME
+ttk::sizegrip \- Bottom-right corner resize widget
+.SH SYNOPSIS
+\fBttk::sizegrip\fR \fIpathName \fR?\fIoptions\fR?
+.BE
+.SH DESCRIPTION
+.PP
+A \fBttk::sizegrip\fR widget (also known as a \fIgrow box\fR)
+allows the user to resize the containing toplevel window
+by pressing and dragging the grip.
+.SO ttk_widget
+\-class \-cursor
+\-style \-takefocus
+.SE
+.SH "WIDGET COMMAND"
+.PP
+Sizegrip widgets support the standard
+\fBcget\fR, \fBconfigure\fR, \fBidentify\fR, \fBinstate\fR, and \fBstate\fR
+methods. No other widget methods are used.
+.SH "PLATFORM-SPECIFIC NOTES"
+.PP
+On Mac OSX, toplevel windows automatically include a built-in
+size grip by default.
+Adding a \fBttk::sizegrip\fR there is harmless, since
+the built-in grip will just mask the widget.
+.SH EXAMPLES
+.PP
+Using pack:
+.CS
+pack [ttk::frame $top.statusbar] \-side bottom \-fill x
+pack [\fBttk::sizegrip\fR $top.statusbar.grip] \-side right \-anchor se
+.CE
+.PP
+Using grid:
+.CS
+grid [\fBttk::sizegrip\fR $top.statusbar.grip] \e
+ \-row $lastRow \-column $lastColumn \-sticky se
+# ... optional: add vertical scrollbar in $lastColumn,
+# ... optional: add horizontal scrollbar in $lastRow
+.CE
+.SH "BUGS"
+.PP
+If the containing toplevel's position was specified
+relative to the right or bottom of the screen
+(e.g.,
+.QW "\fBwm geometry ... \fIw\fBx\fIh\fB\-\fIx\fB\-\fIy\fR"
+instead of
+.QW "\fBwm geometry ... \fIw\fBx\fIh\fB+\fIx\fB+\fIy\fR" ),
+the sizegrip widget will not resize the window.
+.PP
+\fBttk::sizegrip\fR widgets only support
+.QW southeast
+resizing.
+.SH "STYLING OPTIONS"
+.PP
+The class name for a \fBttk::sizegrip\fP is \fBTSizegrip\fP.
+.PP
+\fBTSizegrip\fP styling options configurable with \fBttk::style\fP
+are:
+.PP
+\fB\-background\fP \fIcolor\fP
+.PP
+Some options are only available for specific themes.
+.PP
+See the \fBttk::style\fP manual page for information on how to configure
+ttk styles.
+.SH "SEE ALSO"
+ttk::widget(n)
+.SH "KEYWORDS"
+widget, sizegrip, grow box
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/ttk_spinbox.n b/tk8.6/doc/ttk_spinbox.n
new file mode 100644
index 0000000..9ae9881
--- /dev/null
+++ b/tk8.6/doc/ttk_spinbox.n
@@ -0,0 +1,128 @@
+'\"
+'\" Copyright (c) 2008 Pat Thoyts
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH ttk::spinbox n 8.5 Tk "Tk Themed Widget"
+.so man.macros
+.BS
+.SH NAME
+ttk::spinbox \- Selecting text field widget
+.SH SYNOPSIS
+\fBttk::spinbox\fR \fIpathName \fR?\fIoptions\fR?
+.BE
+.SH DESCRIPTION
+.PP
+A \fBttk::spinbox\fR widget is a \fBttk::entry\fR widget with built-in
+up and down buttons that are used to either modify a numeric value or
+to select among a set of values. The widget implements all the features
+of the \fBttk::entry\fR widget including support of the
+\fB\-textvariable\fR option to link the value displayed by the widget
+to a Tcl variable.
+.SO ttk_widget
+\-class \-cursor \-state \-style
+\-takefocus \-xscrollcommand
+.SE
+.SO ttk_entry
+\-validate \-validatecommand
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-command command Command
+Specifies a Tcl command to be invoked whenever a spinbutton is invoked.
+.OP \-format format Format
+Specifies an alternate format to use when setting the string value
+when using the \fB\-from\fR and \fB\-to\fR range.
+This must be a format specifier of the form \fB%<pad>.<pad>f\fR,
+as it will format a floating-point number.
+.OP \-from from From
+A floating\-point value specifying the lowest value for the spinbox. This is
+used in conjunction with \fB\-to\fR and \fB\-increment\fR to set a numerical
+range.
+.OP \-increment increment Increment
+A floating\-point value specifying the change in value to be applied each
+time one of the widget spin buttons is pressed. The up button applies a
+positive increment, the down button applies a negative increment.
+.OP \-to to To
+A floating\-point value specifying the highest permissible value for the
+widget. See also \fB\-from\fR and \fB\-increment\fR.
+range.
+.OP \-values values Values
+This must be a Tcl list of values. If this option is set then this will
+override any range set using the \fB\-from\fR, \fB\-to\fR and
+\fB\-increment\fR options. The widget will instead use the values
+specified beginning with the first value.
+.OP \-wrap wrap Wrap
+Must be a proper boolean value. If on, the spinbox will wrap around the
+values of data in the widget.
+.SH "INDICES"
+.PP
+See the \fBttk::entry\fR manual for information about indexing characters.
+.SH "VALIDATION"
+.PP
+See the \fBttk::entry\fR manual for information about using the
+\fB\-validate\fR and \fB\-validatecommand\fR options.
+.SH "WIDGET COMMAND"
+.PP
+The following subcommands are possible for spinbox widgets in addition to
+the commands described for the \fBttk::entry\fR widget:
+.TP
+\fIpathName \fBget\fR
+Returns the spinbox's current value.
+.TP
+\fIpathName \fBset \fIvalue\fR
+Set the spinbox string to \fIvalue\fR. If a \fB\-format\fR option has
+been configured then this format will be applied. If formatting fails
+or is not set or the \fB\-values\fR option has been used then the value
+is set directly.
+.SH "VIRTUAL EVENTS"
+.PP
+The spinbox widget generates a \fB<<Increment>>\fR virtual event when
+the user presses <Up>, and a \fB<<Decrement>>\fR virtual event when the
+user presses <Down>.
+.SH "STYLING OPTIONS"
+.PP
+The class name for a \fBttk::spinbox\fP is \fBTSpinbox\fP.
+.PP
+Dynamic states: \fBactive\fP, \fBdisabled\fP, \fBfocus\fP, \fBreadonly\fP.
+.PP
+\fBTSpinbox\fP styling options configurable with \fBttk::style\fP
+are:
+.PP
+\fB\-arrowcolor\fP \fIcolor\fP
+.br
+\fB\-arrowsize\fP \fIamount\fP
+.br
+\fB\-background\fP \fIcolor\fP
+.RS
+For backwards compatibility, when using the aqua theme (for macOS), this
+option behaves as an alias for the \fB\-fieldbackground\fP provided that no
+value is specified for \fB\-fieldbackground\fP. Otherwise it is ignored.
+.RE
+\fB\-bordercolor\fP \fIcolor\fP
+.br
+\fB\-darkcolor\fP \fIcolor\fP
+.br
+\fB\-fieldbackground\fP \fIcolor\fP
+.br
+\fB\-foreground\fP \fIcolor\fP
+.br
+\fB\-lightcolor\fP \fIcolor\fP
+.br
+\fB\-padding\fP \fIpadding\fP
+.br
+\fB\-selectbackground\fP \fIcolor\fP
+.br
+\fB\-selectforeground\fP \fIcolor\fP
+.PP
+Some options are only available for specific themes.
+.PP
+See the \fBttk::style\fP manual page for information on how to configure
+ttk styles.
+.SH "SEE ALSO"
+ttk::widget(n), ttk::entry(n), spinbox(n)
+.SH KEYWORDS
+entry, spinbox, widget, text field
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/ttk_style.n b/tk8.6/doc/ttk_style.n
new file mode 100644
index 0000000..985e3cd
--- /dev/null
+++ b/tk8.6/doc/ttk_style.n
@@ -0,0 +1,131 @@
+'\"
+'\" Copyright (c) 2004 Joe English
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH ttk::style n 8.5 Tk "Tk Themed Widget"
+.so man.macros
+.BS
+.SH NAME
+ttk::style \- Manipulate style database
+.SH SYNOPSIS
+\fBttk::style\fR \fIoption\fR ?\fIargs\fR?
+.BE
+.SH NOTES
+.PP
+See also the Tcl'2004 conference presentation,
+available at http://tktable.sourceforge.net/tile/tile-tcl2004.pdf
+.SH DEFINITIONS
+.PP
+Each widget is assigned a \fIstyle\fR,
+which specifies the set of elements making up the widget
+and how they are arranged, along with dynamic and default
+settings for element options.
+By default, the style name is the same as the widget's class;
+this may be overridden by the \fB\-style\fR option.
+.PP
+A \fItheme\fR is a collection of elements and styles
+which controls the overall look and feel of an application.
+.SH DESCRIPTION
+.PP
+The \fBttk::style\fR command takes the following arguments:
+.TP
+\fBttk::style configure \fIstyle\fR ?\fI\-option\fR ?\fIvalue option value...\fR? ?
+Sets the default value of the specified option(s) in \fIstyle\fR.
+.TP
+\fBttk::style map \fIstyle\fR ?\fI\-option\fB { \fIstatespec value...\fB }\fR?
+Sets dynamic values of the specified option(s) in \fIstyle\fR.
+Each \fIstatespec / value\fR pair is examined in order;
+the value corresponding to the first matching \fIstatespec\fR
+is used.
+.TP
+\fBttk::style lookup \fIstyle\fR \fI\-option \fR?\fIstate \fR?\fIdefault\fR??
+Returns the value specified for \fI\-option\fR in style \fIstyle\fR
+in state \fIstate\fR, using the standard lookup rules for element options.
+\fIstate\fR is a list of state names; if omitted,
+it defaults to all bits off (the
+.QW normal
+state).
+If the \fIdefault\fR argument is present, it is used as a fallback
+value in case no specification for \fI\-option\fR is found.
+.\" Otherwise -- signal error? return empty string? Leave unspecified for now.
+.TP
+\fBttk::style layout \fIstyle\fR ?\fIlayoutSpec\fR?
+Define the widget layout for style \fIstyle\fR.
+See \fBLAYOUTS\fR below for the format of \fIlayoutSpec\fR.
+If \fIlayoutSpec\fR is omitted, return the layout specification
+for style \fIstyle\fR.
+.TP
+\fBttk::style element create\fR \fIelementName\fR \fItype\fR ?\fIargs...\fR?
+Creates a new element in the current theme of type \fItype\fR.
+The only cross-platform built-in element type is \fIimage\fR
+(see \fBttk_image\fR(n)) but themes may define other element types
+(see \fBTtk_RegisterElementFactory\fR). On suitable versions of Windows
+an element factory is registered to create Windows theme elements
+(see \fBttk_vsapi\fR(n)).
+.TP
+\fBttk::style element names\fR
+Returns the list of elements defined in the current theme.
+.TP
+\fBttk::style element options \fIelement\fR
+Returns the list of \fIelement\fR's options.
+.TP
+\fBttk::style theme create\fR \fIthemeName\fR ?\fB\-parent \fIbasedon\fR? ?\fB\-settings \fIscript...\fR ?
+Creates a new theme. It is an error if \fIthemeName\fR already exists.
+If \fB\-parent\fR is specified, the new theme will inherit
+styles, elements, and layouts from the parent theme \fIbasedon\fR.
+If \fB\-settings\fR is present, \fIscript\fR is evaluated in the
+context of the new theme as per \fBttk::style theme settings\fR.
+.TP
+\fBttk::style theme settings \fIthemeName\fR \fIscript\fR
+Temporarily sets the current theme to \fIthemeName\fR,
+evaluate \fIscript\fR, then restore the previous theme.
+Typically \fIscript\fR simply defines styles and elements,
+though arbitrary Tcl code may appear.
+.TP
+\fBttk::style theme names\fR
+Returns a list of all known themes.
+.TP
+\fBttk::style theme use\fR ?\fIthemeName\fR?
+Without an argument the result is the name of the current theme.
+Otherwise this command sets the current theme to \fIthemeName\fR,
+and refreshes all widgets.
+.SH LAYOUTS
+.PP
+A \fIlayout\fR specifies a list of elements, each followed
+by one or more options specifying how to arrange the element.
+The layout mechanism uses a simplified version of the \fBpack\fR
+geometry manager: given an initial cavity,
+each element is allocated a parcel.
+Valid options are:
+.TP
+\fB\-side \fIside\fR
+Specifies which side of the cavity to place the element;
+one of \fBleft\fR, \fBright\fR, \fBtop\fR, or \fBbottom\fR.
+If omitted, the element occupies the entire cavity.
+.TP
+\fB\-sticky\fR \fB[\fInswe\fB]\fR
+Specifies where the element is placed inside its allocated parcel.
+.TP
+\fB\-children { \fIsublayout... \fB}\fR
+Specifies a list of elements to place inside the element.
+.\" Also: -border, -unit, -expand: may go away.
+.PP
+For example:
+.CS
+ttk::style layout Horizontal.TScrollbar {
+ Scrollbar.trough \-children {
+ Scrollbar.leftarrow \-side left
+ Scrollbar.rightarrow \-side right
+ Horizontal.Scrollbar.thumb \-side left \-sticky ew
+ }
+}
+.CE
+.SH "SEE ALSO"
+ttk::intro(n), ttk::widget(n), photo(n), ttk_image(n)
+.SH KEYWORDS
+style, theme, appearance
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/ttk_treeview.n b/tk8.6/doc/ttk_treeview.n
new file mode 100644
index 0000000..125cc78
--- /dev/null
+++ b/tk8.6/doc/ttk_treeview.n
@@ -0,0 +1,555 @@
+'\"
+'\" Copyright (c) 2004 Joe English
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH ttk::treeview n 8.5 Tk "Tk Themed Widget"
+.so man.macros
+.BS
+.SH NAME
+ttk::treeview \- hierarchical multicolumn data display widget
+.SH SYNOPSIS
+\fBttk::treeview \fIpathname \fR?\fIoptions\fR?
+.BE
+.SH DESCRIPTION
+.PP
+The \fBttk::treeview\fR widget displays a hierarchical collection of items.
+Each item has a textual label, an optional image,
+and an optional list of data values.
+The data values are displayed in successive columns after
+the tree label.
+.PP
+The order in which data values are displayed may be controlled
+by setting the \fB\-displaycolumns\fR widget option.
+The tree widget can also display column headings.
+Columns may be accessed by number or by symbolic names
+listed in the \fB\-columns\fR widget option;
+see \fBCOLUMN IDENTIFIERS\fR.
+.PP
+Each item is identified by a unique name.
+The widget will generate item IDs if they are not supplied by the caller.
+There is a distinguished root item, named \fB{}\fR.
+The root item itself is not displayed;
+its children appear at the top level of the hierarchy.
+.PP
+Each item also has a list of \fItags\fR,
+which can be used to associate event bindings with individual items
+and control the appearance of the item.
+.\" .PP
+.\" @@@HERE: describe selection, focus item
+.PP
+Treeview widgets support horizontal and vertical scrolling with the
+standard \fB\-\fR[\fBxy\fR]\fBscrollcommand\fR options
+and [\fBxy\fR]\fBview\fR widget commands.
+.SO ttk_widget
+\-class \-cursor \-takefocus
+\-style \-xscrollcommand \-yscrollcommand
+\-padding
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-columns columns Columns
+A list of column identifiers,
+specifying the number of columns and their names.
+.\"X: This is a read-only option; it may only be set when the widget is created.
+.OP \-displaycolumns displayColumns DisplayColumns
+A list of column identifiers
+(either symbolic names or integer indices)
+specifying which data columns are displayed
+and the order in which they appear,
+or the string \fB#all\fP.
+If set to \fB#all\fP (the default),
+all columns are shown in the order given.
+.OP \-height height Height
+Specifies the number of rows which should be visible.
+Note:
+the requested width is determined from the sum of the column widths.
+.OP \-selectmode selectMode SelectMode
+Controls how the built-in class bindings manage the selection.
+One of \fBextended\fR, \fBbrowse\fR, or \fBnone\fR.
+.RS
+.PP
+If set to \fBextended\fR (the default), multiple items may be selected.
+If \fBbrowse\fR, only a single item will be selected at a time.
+If \fBnone\fR, the selection will not be changed.
+.PP
+Note that application code and tag bindings can set the selection
+however they wish, regardless of the value of \fB\-selectmode\fR.
+.RE
+.OP \-show show Show
+A list containing zero or more of the following values, specifying
+which elements of the tree to display.
+.RS
+.IP \fBtree\fR
+Display tree labels in column #0.
+.IP \fBheadings\fR
+Display the heading row.
+.PP
+The default is \fBtree headings\fR, i.e., show all elements.
+.PP
+\fBNOTE:\fR Column #0 always refers to the tree column,
+even if \fB\-show tree\fR is not specified.
+.RE
+.SH "WIDGET COMMAND"
+.PP
+.TP
+\fIpathname \fBbbox \fIitem\fR ?\fIcolumn\fR?
+Returns the bounding box (relative to the treeview widget's window)
+of the specified \fIitem\fR
+in the form \fIx y width height\fR.
+If \fIcolumn\fR is specified, returns the bounding box of that cell.
+If the \fIitem\fR is not visible
+(i.e., if it is a descendant of a closed item or is scrolled offscreen),
+returns the empty list.
+.TP
+\fIpathname \fBcget \fIoption\fR
+Returns the current value of the specified \fIoption\fR; see \fIttk::widget(n)\fR.
+.TP
+\fIpathname \fBchildren \fIitem\fR ?\fInewchildren\fR?
+If \fInewchildren\fR is not specified,
+returns the list of children belonging to \fIitem\fR.
+.RS
+.PP
+If \fInewchildren\fR is specified, replaces \fIitem\fR's child list
+with \fInewchildren\fR.
+Items in the old child list not present in the new child list
+are detached from the tree.
+None of the items in \fInewchildren\fR may be an ancestor
+of \fIitem\fR.
+.RE
+.TP
+\fIpathname \fBcolumn \fIcolumn\fR ?\fI\-option \fR?\fIvalue \-option value...\fR?
+Query or modify the options for the specified \fIcolumn\fR.
+If no \fI\-option\fR is specified,
+returns a dictionary of option/value pairs.
+If a single \fI\-option\fR is specified,
+returns the value of that option.
+Otherwise, the options are updated with the specified values.
+The following options may be set on each column:
+.RS
+.TP
+\fB\-id \fIname\fR
+The column name. This is a read-only option.
+For example, [\fI$pathname \fBcolumn #\fIn \fB\-id\fR]
+returns the data column associated with display column #\fIn\fR.
+.TP
+\fB\-anchor \fIanchor\fR
+Specifies how the text in this column should be aligned
+with respect to the cell. \fIAnchor\fR is one of
+\fBn\fR, \fBne\fR, \fBe\fR, \fBse\fR,
+\fBs\fR, \fBsw\fR, \fBw\fR, \fBnw\fR, or \fBcenter\fR.
+.TP
+\fB\-minwidth \fIminwidth\fR
+The minimum width of the column in pixels.
+The treeview widget will not make the column any smaller than
+\fB\-minwidth\fR when the widget is resized or the user drags a
+column separator. Default is 20 pixels.
+.TP
+\fB\-stretch \fIboolean\fR
+Specifies whether or not the column width should be adjusted
+when the widget is resized or the user drags a column separator.
+\fIBoolean\fR may have any of the forms accepted by \fBTcl_GetBoolean\fR.
+By default columns are stretchable.
+.TP
+\fB\-width \fIwidth\fR
+The width of the column in pixels. Default is 200 pixels. The specified
+column width may be changed by Tk in order to honor \fB\-stretch\fR
+and/or \fB\-minwidth\fR, or when the widget is resized or the user drags a
+column separator.
+.PP
+Use \fIpathname column #0\fR to configure the tree column.
+.RE
+.TP
+\fIpathname \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
+Modify or query widget options; see \fIttk::widget(n)\fR.
+.TP
+\fIpathname \fBdelete \fIitemList\fR
+Deletes each of the items in \fIitemList\fR and all of their descendants.
+The root item may not be deleted.
+See also: \fBdetach\fR.
+.TP
+\fIpathname \fBdetach \fIitemList\fR
+Unlinks all of the specified items in \fIitemList\fR from the tree.
+The items and all of their descendants are still present
+and may be reinserted at another point in the tree
+with the \fBmove\fR operation,
+but will not be displayed until that is done.
+The root item may not be detached.
+See also: \fBdelete\fR.
+.TP
+\fIpathname \fBexists \fIitem\fR
+Returns 1 if the specified \fIitem\fR is present in the tree,
+0 otherwise.
+.TP
+\fIpathname \fBfocus \fR?\fIitem\fR?
+If \fIitem\fR is specified, sets the focus item to \fIitem\fR.
+Otherwise, returns the current focus item, or \fB{}\fR if there is none.
+.\" Need: way to clear the focus item. {} works for this...
+.TP
+\fIpathname \fBheading \fIcolumn\fR ?\fI\-option \fR?\fIvalue \-option value...\fR?
+Query or modify the heading options for the specified \fIcolumn\fR.
+Valid options are:
+.RS
+.TP
+\fB\-text \fItext\fR
+The text to display in the column heading.
+.TP
+\fB\-image \fIimageName\fR
+Specifies an image to display to the right of the column heading.
+.TP
+\fB\-anchor \fIanchor\fR
+Specifies how the heading text should be aligned.
+One of the standard Tk anchor values.
+.TP
+\fB\-command \fIscript\fR
+A script to evaluate when the heading label is pressed.
+.PP
+Use \fIpathname heading #0\fR to configure the tree column heading.
+.RE
+.TP
+\fIpathname \fBidentify \fIcomponent x y\fR
+Returns a description of the specified \fIcomponent\fR
+under the point given by \fIx\fR and \fIy\fR,
+or the empty string if no such \fIcomponent\fR is present at that position.
+The following subcommands are supported:
+.RS
+.TP
+\fIpathname \fBidentify region \fIx y\fR
+.RS
+Returns one of:
+.IP heading
+Tree heading area;
+use [\fBpathname identify column \fIx y\fR]
+to determine the heading number.
+.IP separator
+Space between two column headings;
+[\fBpathname identify column \fIx y\fR]
+will return the display column identifier
+of the heading to left of the separator.
+.IP tree
+The tree area.
+.IP cell
+A data cell.
+.RE
+\fIpathname \fBidentify item \fIx y\fR
+Returns the item ID of the item at position \fIy\fR.
+.TP
+\fIpathname \fBidentify column \fIx y\fR
+Returns the data column identifier of the cell at position \fIx\fR.
+The tree column has ID \fB#0\fR.
+.TP
+\fIpathname \fBidentify element \fIx y\fR
+The element at position \fIx,y\fR.
+.TP
+\fIpathname \fBidentify row \fIx y\fR
+Obsolescent synonym for \fIpathname \fBidentify item\fR.
+.PP
+See \fBCOLUMN IDENTIFIERS\fR for a discussion of display columns
+and data columns.
+.RE
+.TP
+\fIpathname \fBindex \fIitem\fR
+Returns the integer index of \fIitem\fR within its parent's list of children.
+.TP
+\fIpathname \fBinsert \fIparent index\fR ?\fB\-id \fIid\fR? \fIoptions...\fR
+Creates a new item.
+\fIparent\fR is the item ID of the parent item,
+or the empty string \fB{}\fR
+to create a new top-level item.
+\fIindex\fR is an integer, or the value \fBend\fR, specifying where in the
+list of \fIparent\fR's children to insert the new item.
+If \fIindex\fR is less than or equal to zero,
+the new node is inserted at the beginning;
+if \fIindex\fR is greater than or equal to the current number of children,
+it is inserted at the end.
+If \fB\-id\fR is specified, it is used as the item identifier;
+\fIid\fR must not already exist in the tree.
+Otherwise, a new unique identifier is generated.
+.RS
+.PP
+\fIpathname \fBinsert\fR returns the item identifier of the
+newly created item.
+See \fBITEM OPTIONS\fR for the list of available options.
+.RE
+.TP
+\fIpathname \fBinstate \fIstatespec\fR ?\fIscript\fR?
+Test the widget state; see \fIttk::widget(n)\fR.
+.TP
+\fIpathname \fBitem \fIitem\fR ?\fI\-option \fR?\fIvalue \-option value...\fR?
+Query or modify the options for the specified \fIitem\fR.
+If no \fI\-option\fR is specified,
+returns a dictionary of option/value pairs.
+If a single \fI\-option\fR is specified,
+returns the value of that option.
+Otherwise, the item's options are updated with the specified values.
+See \fBITEM OPTIONS\fR for the list of available options.
+.TP
+\fIpathname \fBmove \fIitem parent index\fR
+Moves \fIitem\fR to position \fIindex\fR in \fIparent\fR's list of children.
+It is illegal to move an item under one of its descendants.
+.RS
+.PP
+If \fIindex\fR is less than or equal to zero, \fIitem\fR is moved
+to the beginning; if greater than or equal to the number of children,
+it is moved to the end.
+.RE
+.TP
+\fIpathname \fBnext \fIitem\fR
+Returns the identifier of \fIitem\fR's next sibling,
+or \fB{}\fR if \fIitem\fR is the last child of its parent.
+.TP
+\fIpathname \fBparent \fIitem\fR
+Returns the ID of the parent of \fIitem\fR,
+or \fB{}\fR if \fIitem\fR is at the top level of the hierarchy.
+.TP
+\fIpathname \fBprev \fIitem\fR
+Returns the identifier of \fIitem\fR's previous sibling,
+or \fB{}\fR if \fIitem\fR is the first child of its parent.
+.TP
+\fIpathname \fBsee \fIitem\fR
+Ensure that \fIitem\fR is visible:
+sets all of \fIitem\fR's ancestors to \fB\-open true\fR,
+and scrolls the widget if necessary so that \fIitem\fR is
+within the visible portion of the tree.
+.TP
+\fIpathname \fBselection\fR ?\fIselop itemList\fR?
+If \fIselop\fR is not specified, returns the list of selected items.
+Otherwise, \fIselop\fR is one of the following:
+.RS
+.TP
+\fIpathname \fBselection set \fIitemList\fR
+\fIitemList\fR becomes the new selection.
+.TP
+\fIpathname \fBselection add \fIitemList\fR
+Add \fIitemList\fR to the selection
+.TP
+\fIpathname \fBselection remove \fIitemList\fR
+Remove \fIitemList\fR from the selection
+.TP
+\fIpathname \fBselection toggle \fIitemList\fR
+Toggle the selection state of each item in \fIitemList\fR.
+.RE
+.TP
+\fIpathname \fBset \fIitem\fR ?\fIcolumn\fR? ?\fIvalue\fR?
+With one argument, returns a dictionary of column/value pairs
+for the specified \fIitem\fR.
+With two arguments, returns the current value of the specified \fIcolumn\fR.
+With three arguments, sets the value of column \fIcolumn\fR
+in item \fIitem\fR to the specified \fIvalue\fR.
+See also \fBCOLUMN IDENTIFIERS\fR.
+.TP
+\fIpathname \fBstate\fR ?\fIstateSpec\fR?
+Modify or query the widget state; see \fIttk::widget(n)\fR.
+.TP
+\fIpathName \fBtag \fIargs...\fR
+.RS
+.TP
+\fIpathName \fBtag bind \fItagName \fR?\fIsequence\fR? ?\fIscript\fR?
+Add a Tk binding script for the event sequence \fIsequence\fR
+to the tag \fItagName\fR. When an X event is delivered to an item,
+binding scripts for each of the item's \fB\-tags\fR are evaluated
+in order as per \fIbindtags(n)\fR.
+.RS
+.PP
+\fB<KeyPress>\fR, \fB<KeyRelease>\fR, and virtual events
+are sent to the focus item.
+\fB<ButtonPress>\fR, \fB<ButtonRelease>\fR, and \fB<Motion>\fR events
+are sent to the item under the mouse pointer.
+No other event types are supported.
+.PP
+The binding \fIscript\fR undergoes \fB%\fR-substitutions before
+evaluation; see \fBbind(n)\fR for details.
+.RE
+.TP
+\fIpathName \fBtag configure \fItagName\fR ?\fIoption\fR? ?\fIvalue option value...\fR?
+Query or modify the options for the specified \fItagName\fR.
+If one or more \fIoption/value\fR pairs are specified,
+sets the value of those options for the specified tag.
+If a single \fIoption\fR is specified,
+returns the value of that option
+(or the empty string if the option has not been specified for \fItagName\fR).
+With no additional arguments,
+returns a dictionary of the option settings for \fItagName\fR.
+See \fBTAG OPTIONS\fR for the list of available options.
+.TP
+\fIpathName \fBtag has \fItagName\fR ?\fIitem\fR?
+If \fIitem\fR is specified, returns 1 or 0
+depending on whether the specified item has the named tag.
+Otherwise, returns a list of all items which have
+the specified tag.
+.TP
+\fIpathName \fBtag names\fR
+Returns a list of all tags used by the widget.
+.TP
+\fIpathName \fBtag add \fItag items\fR
+Adds the specified \fItag\fR to each of the listed \fIitems\fR.
+If \fItag\fR is already present for a particular item,
+then the \fB\-tags\fR for that item are unchanged.
+.TP
+\fIpathName \fBtag remove \fItag\fR ?\fIitems\fR?
+Removes the specified \fItag\fR from each of the listed \fIitems\fR.
+If \fIitems\fR is omitted, removes \fItag\fR from each item in the tree.
+If \fItag\fR is not present for a particular item,
+then the \fB\-tags\fR for that item are unchanged.
+.RE
+.PP
+The treeview widget also supports the following generic \fBttk::widget\fR
+widget subcommands (see \fIttk::widget(n)\fR for details):
+.DS
+.ta 5.5c 11c
+\fBxview\fR \fByview\fR
+.DE
+.SH "ITEM OPTIONS"
+.PP
+The following item options may be specified for items
+in the \fBinsert\fR and \fBitem\fR widget commands.
+.OP \-text text Text
+The textual label to display for the item.
+.OP \-image image Image
+A Tk image, displayed to the left of the label.
+.OP \-values values Values
+The list of values associated with the item.
+.RS
+.PP
+Each item should have the same number of values as
+the \fB\-columns\fR widget option.
+If there are fewer values than columns,
+the remaining values are assumed empty.
+If there are more values than columns,
+the extra values are ignored.
+.RE
+.OP \-open open Open
+A boolean value indicating whether the item's children
+should be displayed (\fB\-open true\fR) or hidden (\fB\-open false\fR).
+.OP \-tags tags Tags
+A list of tags associated with this item.
+.SH "TAG OPTIONS"
+.PP
+The following options may be specified on tags:
+.IP \fB\-foreground\fR
+Specifies the text foreground color.
+.IP \fB\-background\fR
+Specifies the cell or item background color.
+.IP \fB\-font\fR
+Specifies the font to use when drawing text.
+.\" ??? Maybe: .IP \-anchor
+.\" ??? Maybe: .IP \-padding
+.\" ??? Maybe: .IP \-text
+.IP \fB\-image\fR
+Specifies the item image, in case the item's \fB\-image\fR option is empty.
+.\" .PP
+.\" \fI(@@@ TODO: sort out order of precedence for options)\fR
+.PP
+Tag priority is decided by the creation order: tags created first receive
+higher priority.
+.SH "COLUMN IDENTIFIERS"
+.PP
+Column identifiers take any of the following forms:
+.IP \(bu
+A symbolic name from the list of \fB\-columns\fR.
+.IP \(bu
+An integer \fIn\fR, specifying the \fIn\fRth data column.
+.IP \(bu
+A string of the form \fB#\fIn\fR, where \fIn\fR is an integer,
+specifying the \fIn\fRth display column.
+.PP
+\fBNOTE:\fR
+Item \fB\-values\fR may be displayed in a different order than
+the order in which they are stored.
+.PP
+\fBNOTE:\fR Column #0 always refers to the tree column,
+even if \fB\-show tree\fR is not specified.
+.PP
+A \fIdata column number\fR is an index into an item's \fB\-values\fR list;
+a \fIdisplay column number\fR is the column number in the tree
+where the values are displayed.
+Tree labels are displayed in column #0.
+If \fB\-displaycolumns\fR is not set,
+then data column \fIn\fR is displayed in display column \fB#\fIn+1\fR.
+Again, \fBcolumn #0 always refers to the tree column\fR.
+.SH "VIRTUAL EVENTS"
+.PP
+The treeview widget generates the following virtual events.
+.IP <<TreeviewSelect>>
+Generated whenever the selection changes.
+.IP <<TreeviewOpen>>
+Generated just before setting the focus item to \fB\-open true\fR.
+.IP <<TreeviewClose>>
+Generated just after setting the focus item to \fB\-open false\fR.
+.PP
+The \fBfocus\fR and \fBselection\fR widget commands can be used
+to determine the affected item or items.
+'\" Not yet:
+'\" In Tk 8.5, the affected item is also passed as the \fB\-detail\fR field
+'\" of the virtual event.
+.SH "STYLING OPTIONS"
+.PP
+The class name for a \fBttk::treeview\fP is \fBTreeview\fP.
+The treeview header class name is \fBHeading\fP.
+The treeview item class name is \fBItem\fP.
+The treeview cell class name is \fBCell\fP.
+.PP
+Dynamic states: \fBdisabled\fP, \fBselected\fP.
+.PP
+\fBTreeview\fP styling options configurable with \fBttk::style\fP
+are:
+.PP
+\fB\-background\fP \fIcolor\fP
+.br
+\fB\-fieldbackground\fP \fIcolor\fP
+.br
+\fB\-font\fP \fIfont\fP
+.br
+\fB\-foreground\fP \fIcolor\fP
+.br
+\fB\-rowheight\fP \fIamount\fP
+.RS
+The \fB\-rowheight\fP value is not corrected by the \fBtk scaling\fP
+value or by the configured font size and must always be set. Also make
+sure that the \fB\-rowheight\fP is large enough to contain any images.
+.PP
+To adjust the \fB\-rowheight\fP for the Treeview style, use the following code
+after \fBtk scaling\fP has been applied.
+Note that even if you do not support or change \fBtk scaling\fP
+in your program, your users may have it set in their .wishrc.
+.RE
+.PP
+.CS
+ttk::style configure Treeview \\
+ \-rowheight [expr {[font metrics \fIfont\fP \-linespace] + 2}]
+.CE
+.PP
+\fBHeading\fP styling options configurable with \fBttk::style\fP
+are:
+.PP
+\fB\-background\fP \fIcolor\fP
+.br
+\fB\-font\fP \fIfont\fP
+.br
+\fB\-relief\fP \fIrelief\fP
+.PP
+\fBItem\fP styling options configurable with \fBttk::style\fP
+are:
+.PP
+\fB\-foreground\fP \fIcolor\fP
+.br
+\fB\-indicatormargins\fP \fIpadding\fP
+.br
+\fB\-indicatorsize\fP \fIamount\fP
+.br
+\fB\-padding\fP \fIpadding\fP
+.PP
+\fBCell\fP styling options configurable with \fBttk::style\fP
+are:
+.PP
+\fB\-padding\fP \fIpadding\fP
+.PP
+Some options are only available for specific themes.
+.PP
+See the \fBttk::style\fP manual page for information on how to configure
+ttk styles.
+.SH "SEE ALSO"
+ttk::widget(n), listbox(n), image(n), bind(n)
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/ttk_vsapi.n b/tk8.6/doc/ttk_vsapi.n
new file mode 100644
index 0000000..af63c39
--- /dev/null
+++ b/tk8.6/doc/ttk_vsapi.n
@@ -0,0 +1,113 @@
+'\"
+'\" Copyright (c) 2008 Pat Thoyts
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH ttk_vsapi n 8.5 Tk "Tk Themed Widget"
+.so man.macros
+.BS
+.SH NAME
+ttk_vsapi \- Define a Microsoft Visual Styles element
+.SH SYNOPSIS
+\fBttk::style element create \fIname\fR \fBvsapi\fR \fIclassName\fR \fIpartId\fR ?\fIstateMap\fR? ?\fIoptions\fR?
+.BE
+.SH DESCRIPTION
+.PP
+The \fBvsapi\fR element factory creates a new element
+in the current theme whose visual appearance is drawn using the
+Microsoft Visual Styles API which is responsible for the themed styles
+on Windows XP and Vista. This factory permits any of the Visual
+Styles parts to be declared as Ttk elements that can then be
+included in a style layout to modify the appearance of Ttk widgets.
+.PP
+\fIclassName\fR and \fIpartId\fR are required parameters and specify
+the Visual Styles class and part as given in the Microsoft
+documentation. The \fIstateMap\fR may be provided to map Ttk states to
+Visual Styles API states (see \fBSTATE MAP\fR).
+.SH "OPTIONS"
+.PP
+Valid \fIoptions\fR are:
+.TP
+\fB\-padding \fIpadding\fR
+.
+Specify the element's interior padding.
+\fIpadding\fR is a list of up to four integers specifying
+the left, top, right and bottom padding quantities respectively.
+If fewer than four elements are specified,
+\fIbottom\fR defaults to \fItop\fR,
+\fIright\fR defaults to \fIleft\fR, and
+\fItop\fR defaults to \fIleft\fR.
+In other words, a list of three numbers specify the left, vertical, and right padding;
+a list of two numbers specify the horizontal and the vertical padding;
+a single number specifies the same padding all the way around the widget.
+This option may not be mixed with any other options.
+.TP
+\fB\-margins \fIpadding\fR
+.
+Specifies the elements exterior padding.
+\fIpadding\fR is a list of up to four integers specifying
+the left, top, right and bottom padding quantities respectively.
+This option may not be mixed with any other options.
+.TP
+\fB\-width \fIwidth\fR
+.
+Specifies the height for the element. If this option is set then
+the Visual Styles API will not be queried for the recommended
+size or the part. If this option is set then \fB\-height\fR should
+also be set. The \fB\-width\fR and \fB\-height\fR options cannot
+be mixed with the \fB\-padding\fR or \fB\-margins\fR options.
+.TP
+\fB\-height \fIheight\fR
+.
+Specifies the height of the element. See the comments for \fB\-width\fR.
+.SH "STATE MAP"
+.PP
+The \fIstateMap\fR parameter is a list of ttk states and the
+corresponding Visual Styles API state value.
+This permits the element appearance to respond to changes in the
+widget state such as becoming active or being pressed. The list should
+be as described for the \fBttk::style map\fR command but note that the
+last pair in the list should be the default state and is typically an
+empty list and 1. Unfortunately all the Visual Styles parts have
+different state values and these must be looked up either in the
+Microsoft documentation or more likely in the header files. The
+original header to use was \fItmschema.h\fR, but in more recent
+versions of the Windows Development Kit this is \fIvssym32.h\fR.
+.PP
+If no \fIstateMap\fR parameter is given there is an implicit default
+map of {{} 1}
+.SH "EXAMPLE"
+.PP
+Create a correctly themed close button by changing the layout of
+a \fBttk::button\fR(n). This uses the WINDOW part WP_SMALLCLOSEBUTTON
+and as documented the states CBS_DISABLED, CBS_HOT, CBS_NORMAL and
+CBS_PUSHED are mapped from ttk states.
+.CS
+ttk::style element create smallclose \fBvsapi\fR WINDOW 19 \\
+ {disabled 4 pressed 3 active 2 {} 1}
+ttk::style layout CloseButton {CloseButton.smallclose -sticky news}
+pack [ttk::button .close -style CloseButton]
+.CE
+.PP
+Change the appearance of a \fBttk::checkbutton\fR(n) to use the
+Explorer pin part EBP_HEADERPIN.
+.CS
+ttk::style element create pin \fBvsapi\fR EXPLORERBAR 3 {
+ {pressed !selected} 3
+ {active !selected} 2
+ {pressed selected} 6
+ {active selected} 5
+ {selected} 4
+ {} 1
+}
+ttk::style layout Explorer.Pin {Explorer.Pin.pin -sticky news}
+pack [ttk::checkbutton .pin -style Explorer.Pin]
+.CE
+.SH "SEE ALSO"
+ttk::intro(n), ttk::widget(n), ttk::style(n), ttk_image(n)
+.SH "KEYWORDS"
+style, theme, appearance, windows
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/ttk_widget.n b/tk8.6/doc/ttk_widget.n
new file mode 100644
index 0000000..281ce74
--- /dev/null
+++ b/tk8.6/doc/ttk_widget.n
@@ -0,0 +1,369 @@
+'\"
+'\" Copyright (c) 2004 Joe English
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH ttk::widget n 8.5 Tk "Tk Themed Widget"
+.so man.macros
+.BS
+.SH NAME
+ttk::widget \- Standard options and commands supported by Tk themed widgets
+.BE
+.SH DESCRIPTION
+This manual describes common widget options and commands.
+.SH "STANDARD OPTIONS"
+The following options are supported by all Tk themed widgets:
+.OP \-class undefined undefined
+Specifies the window class.
+The class is used when querying the option database
+for the window's other options, to determine the default
+bindtags for the window, and to select the widget's default
+layout and style.
+This is a read-only option:
+it may only be specified when the window is created,
+and may not be changed with the \fBconfigure\fR widget command.
+.OP \-cursor cursor Cursor
+Specifies the mouse cursor to be used for the widget.
+See \fBTk_GetCursor\fR and \fIcursors(n)\fR in the Tk reference manual
+for the legal values.
+If set to the empty string (the default),
+the cursor is inherited from the parent widget.
+.OP \-takefocus takeFocus TakeFocus
+Determines whether the window accepts the focus during keyboard traversal.
+Either \fB0\fR, \fB1\fR, a command prefix (to which the widget path
+is appended, and which should return \fB0\fR or \fB1\fR),
+or the empty string.
+See \fIoptions(n)\fR in the Tk reference manual for the full description.
+.OP \-style style Style
+May be used to specify a custom widget style.
+.SH "SCROLLABLE WIDGET OPTIONS"
+The following options are supported by widgets that
+are controllable by a scrollbar.
+See \fIscrollbar(n)\fR for more information
+.OP \-xscrollcommand xScrollCommand ScrollCommand
+A command prefix, used to communicate with horizontal scrollbars.
+.RS
+When the view in the widget's window changes, the widget will
+generate a Tcl command by concatenating the scroll command and
+two numbers.
+Each of the numbers is a fraction between 0 and 1 indicating
+a position in the document; 0 indicates the beginning,
+and 1 indicates the end.
+The first fraction indicates the first information in the widget
+that is visible in the window, and the second fraction indicates
+the information just after the last portion that is visible.
+.PP
+Typically the \fB\-xscrollcommand\fR option consists of the path name
+of a \fBscrollbar\fR widget followed by
+.QW set ,
+e.g.
+.QW ".x.scrollbar set" .
+This will cause the scrollbar to be updated whenever the view in the
+window changes.
+.PP
+If this option is set to the empty string (the default),
+then no command will be executed.
+.RE
+.OP \-yscrollcommand yScrollCommand ScrollCommand
+A command prefix, used to communicate with vertical scrollbars.
+See the description of \fB\-xscrollcommand\fR above for details.
+.SH "LABEL OPTIONS"
+The following options are supported by labels, buttons,
+and other button-like widgets:
+.OP \-compound compound Compound
+Specifies how to display the image relative to the text,
+in the case both \fB\-text\fR and \fB\-image\fR are present.
+Valid values are:
+.RS
+.IP text
+Display text only.
+.IP image
+Display image only.
+.IP center
+Display text centered on top of image.
+.IP top
+.IP bottom
+.IP left
+.IP right
+Display image above, below, left of, or right of the text, respectively.
+.IP none
+The default; display the image if present, otherwise the text.
+.RE
+.OP \-image image Image
+Specifies an image to display.
+This is a list of 1 or more elements.
+The first element is the default image name.
+The rest of the list is a sequence of \fIstatespec / value\fR pairs
+as per \fBstyle map\fR, specifying different images to use when
+the widget is in a particular state or combination of states.
+All images in the list should have the same size.
+.OP \-padding padding Padding
+Specifies the internal padding for the widget.
+The padding is a list of up to four length specifications
+\fIleft top right bottom\fR.
+If fewer than four elements are specified,
+\fIbottom\fR defaults to \fItop\fR,
+\fIright\fR defaults to \fIleft\fR, and
+\fItop\fR defaults to \fIleft\fR.
+In other words, a list of three numbers specify the left, vertical, and right padding;
+a list of two numbers specify the horizontal and the vertical padding;
+a single number specifies the same padding all the way around the widget.
+.OP \-text text Text
+Specifies a text string to be displayed inside the widget
+(unless overridden by \fB\-textvariable\fR).
+.OP \-textvariable textVariable Variable
+Specifies the name of a global variable whose value will be used
+in place of the \fB\-text\fR resource.
+.OP \-underline underline Underline
+If set, specifies the integer index (0-based) of a character to underline
+in the text string.
+The underlined character is used for mnemonic activation.
+.OP \-width width Width
+If greater than zero, specifies how much space, in character widths,
+to allocate for the text label.
+If less than zero, specifies a minimum width.
+If zero or unspecified, the natural width of the text label is used.
+.SH "COMPATIBILITY OPTIONS"
+This option is only available for themed widgets that have
+.QW corresponding
+traditional Tk widgets.
+.OP \-state state State
+May be set to \fBnormal\fR or \fBdisabled\fR
+to control the \fBdisabled\fR state bit.
+This is a write-only option:
+setting it changes the widget state,
+but the \fBstate\fR widget command
+does not affect the \fB\-state\fR option.
+.SH COMMANDS
+.TP
+\fIpathName \fBcget \fIoption\fR
+.
+Returns the current value of the configuration option given
+by \fIoption\fR.
+.TP
+\fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
+.
+Query or modify the configuration options of the widget.
+If one or more \fIoption\-value\fR pairs are specified,
+then the command modifies the given widget option(s)
+to have the given value(s);
+in this case the command returns an empty string.
+If \fIoption\fR is specified with no \fIvalue\fR,
+then the command returns a list describing the named option:
+the elements of the list are the
+option name, database name, database class, default value,
+and current value.
+.\" Note: Ttk widgets don't use TK_OPTION_SYNONYM.
+If no \fIoption\fR is specified, returns a list describing all of
+the available options for \fIpathName\fR.
+.TP
+\fIpathName \fBidentify element \fIx y\fR
+.
+Returns the name of the element under the point given
+by \fIx\fR and \fIy\fR, or an empty string if the point does
+not lie within any element.
+\fIx\fR and \fIy\fR are pixel coordinates relative to the widget.
+Some widgets accept other \fBidentify\fR subcommands.
+.TP
+\fIpathName \fBinstate \fIstatespec\fR ?\fIscript\fR?
+.
+Test the widget's state.
+If \fIscript\fR is not specified, returns 1 if
+the widget state matches \fIstatespec\fR and 0 otherwise.
+If \fIscript\fR is specified, equivalent to
+.CS
+if {[\fIpathName\fR instate \fIstateSpec\fR]} \fIscript\fR
+.CE
+.TP
+\fIpathName \fBstate\fR ?\fIstateSpec\fR?
+.
+Modify or inquire widget state.
+If \fIstateSpec\fR is present, sets the widget state:
+for each flag in \fIstateSpec\fR, sets the corresponding flag
+or clears it if prefixed by an exclamation point.
+.RS
+Returns a new state spec indicating which flags were changed:
+.CS
+set changes [\fIpathName \fRstate \fIspec\fR]
+\fIpathName \fRstate $changes
+.CE
+will restore \fIpathName\fR to the original state.
+If \fIstateSpec\fR is not specified,
+returns a list of the currently-enabled state flags.
+.RE
+.TP
+\fIpathName \fBxview \fIargs\fR
+This command is used to query and change the horizontal position of the
+content in the widget's window. It can take any of the following
+forms:
+.RS
+.TP
+\fIpathName \fBxview\fR
+Returns a list containing two elements.
+Each element is a real fraction between 0 and 1; together they describe
+the horizontal span that is visible in the window.
+For example, if the first element is .2 and the second element is .6,
+20% of the widget's content is off-screen to the left, the middle 40% is visible
+in the window, and 40% of the content is off-screen to the right.
+These are the same values passed to scrollbars via the \fB\-xscrollcommand\fR
+option.
+.TP
+\fIpathName \fBxview\fR \fIindex\fR
+Adjusts the view in the window so that the content given by \fIindex\fR
+is displayed at the left edge of the window.
+.TP
+\fIpathName \fBxview moveto\fI fraction\fR
+Adjusts the view in the window so that the character \fIfraction\fR of the
+way through the content appears at the left edge of the window.
+\fIFraction\fR must be a fraction between 0 and 1.
+.TP
+\fIpathName \fBxview scroll \fInumber what\fR
+This command shifts the view in the window left or right according to
+\fInumber\fR and \fIwhat\fR.
+\fINumber\fR must be an integer.
+\fIWhat\fR must be either \fBunits\fR or \fBpages\fR.
+'\" or an abbreviation of one of these, but we don't document that.
+If \fIwhat\fR is \fBunits\fR, the view adjusts left or right by
+\fInumber\fR average-width characters on the display; if it is
+\fBpages\fR then the view adjusts by \fInumber\fR screenfuls.
+If \fInumber\fR is negative then characters farther to the left
+become visible; if it is positive then characters farther to the right
+become visible.
+.RE
+.TP
+\fIpathName \fByview \fIargs\fR
+This command is used to query and change the vertical position of the
+content in the widget's window. It can take any of the following
+forms:
+.RS
+.TP
+\fIpathName \fByview\fR
+Returns a list containing two elements.
+Each element is a real fraction between 0 and 1; together they describe
+the vertical span that is visible in the window.
+For example, if the first element is .2 and the second element is .6,
+20% of the widget's content is off-screen to the top, the middle 40% is visible
+in the window, and 40% of the content is off-screen to the bottom.
+These are the same values passed to scrollbars via the \fB\-yscrollcommand\fR
+option.
+.TP
+\fIpathName \fByview\fR \fIindex\fR
+Adjusts the view in the window so that the content given by \fIindex\fR
+is displayed at the top edge of the window.
+.TP
+\fIpathName \fByview moveto\fI fraction\fR
+Adjusts the view in the window so that the item \fIfraction\fR of the
+way through the content appears at the top edge of the window.
+\fIFraction\fR must be a fraction between 0 and 1.
+.TP
+\fIpathName \fByview scroll \fInumber what\fR
+This command shifts the view in the window up or down according to
+\fInumber\fR and \fIwhat\fR.
+\fINumber\fR must be an integer.
+\fIWhat\fR must be either \fBunits\fR or \fBpages\fR.
+'\" or an abbreviation of one of these, but we don't document that.
+If \fIwhat\fR is \fBunits\fR, the view adjusts up or down by
+\fInumber\fR average-width characters on the display; if it is
+\fBpages\fR then the view adjusts by \fInumber\fR screenfuls.
+If \fInumber\fR is negative then items farther to the top
+become visible; if it is positive then items farther to the bottom
+become visible.
+.RE
+.SH "WIDGET STATES"
+The widget state is a bitmap of independent state flags.
+Widget state flags include:
+.TP
+\fBactive\fR
+.
+The mouse cursor is over the widget
+and pressing a mouse button will cause some action to occur. (aka
+.QW prelight
+(Gnome),
+.QW hot
+(Windows),
+.QW hover ).
+.TP
+\fBdisabled\fR
+.
+Widget is disabled under program control (aka
+.QW unavailable ,
+.QW inactive ).
+.TP
+\fBfocus\fR
+.
+Widget has keyboard focus.
+.TP
+\fBpressed\fR
+.
+Widget is being pressed (aka
+.QW armed
+in Motif).
+.TP
+\fBselected\fR
+.
+.QW On ,
+.QW true ,
+or
+.QW current
+for things like checkbuttons and radiobuttons.
+.TP
+\fBbackground\fR
+.
+Windows and the Mac have a notion of an
+.QW active
+or foreground window.
+The \fBbackground\fR state is set for widgets in a background window,
+and cleared for those in the foreground window.
+.TP
+\fBreadonly\fR
+.
+Widget should not allow user modification.
+.TP
+\fBalternate\fR
+.
+A widget-specific alternate display format.
+For example, used for checkbuttons and radiobuttons in the
+.QW tristate
+or
+.QW mixed
+state, and for buttons with \fB\-default active\fR.
+.TP
+\fBinvalid\fR
+.
+The widget's value is invalid.
+(Potential uses: scale widget value out of bounds,
+entry widget value failed validation.)
+.TP
+\fBhover\fR
+.
+The mouse cursor is within the widget.
+This is similar to the \fBactive\fP state;
+it is used in some themes for widgets that
+provide distinct visual feedback for
+the active widget in addition to the active element
+within the widget.
+.PP
+A \fIstate specification\fR or \fIstateSpec\fR is a list
+of state names, optionally prefixed with an exclamation point (!)
+indicating that the bit is off.
+.SH EXAMPLES
+.CS
+set b [ttk::button .b]
+
+# Disable the widget:
+$b \fBstate\fR disabled
+
+# Invoke the widget only if it is currently pressed and enabled:
+$b \fBinstate\fR {pressed !disabled} { .b invoke }
+
+# Reenable widget:
+$b \fBstate\fR !disabled
+.CE
+.SH "SEE ALSO"
+ttk::intro(n), ttk::style(n)
+.SH KEYWORDS
+state, configure, option
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/winfo.n b/tk8.6/doc/winfo.n
new file mode 100644
index 0000000..a833e31
--- /dev/null
+++ b/tk8.6/doc/winfo.n
@@ -0,0 +1,357 @@
+'\"
+'\" Copyright (c) 1990-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH winfo n 4.3 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+winfo \- Return window-related information
+.SH SYNOPSIS
+\fBwinfo\fR \fIoption \fR?\fIarg arg ...\fR?
+.BE
+.SH DESCRIPTION
+.PP
+The \fBwinfo\fR command is used to retrieve information about windows
+managed by Tk. It can take any of a number of different forms,
+depending on the \fIoption\fR argument. The legal forms are:
+.TP
+\fBwinfo atom \fR?\fB\-displayof \fIwindow\fR? \fIname\fR
+Returns a decimal string giving the integer identifier for the
+atom whose name is \fIname\fR. If no atom exists with the name
+\fIname\fR then a new one is created.
+If the \fB\-displayof\fR option is given then the atom is looked
+up on the display of \fIwindow\fR; otherwise it is looked up on
+the display of the application's main window.
+.TP
+\fBwinfo atomname \fR?\fB\-displayof \fIwindow\fR? \fIid\fR
+Returns the textual name for the atom whose integer identifier is
+\fIid\fR.
+If the \fB\-displayof\fR option is given then the identifier is looked
+up on the display of \fIwindow\fR; otherwise it is looked up on
+the display of the application's main window.
+This command is the inverse of the \fBwinfo atom\fR command.
+It generates an error if no such atom exists.
+.TP
+\fBwinfo cells \fIwindow\fR
+Returns a decimal string giving the number of cells in the
+color map for \fIwindow\fR.
+.TP
+\fBwinfo children \fIwindow\fR
+Returns a list containing the path names of all the children
+of \fIwindow\fR. Top-level windows are returned as children
+of their logical parents. The list is in stacking order, with
+the lowest window first, except for Top-level windows which
+are not returned in stacking order. Use the \fBwm stackorder\fR
+command to query the stacking order of Top-level windows.
+.TP
+\fBwinfo class \fIwindow\fR
+Returns the class name for \fIwindow\fR.
+.TP
+\fBwinfo colormapfull \fIwindow\fR
+Returns 1 if the colormap for \fIwindow\fR is known to be full, 0
+otherwise. The colormap for a window is
+.QW known
+to be full if the last
+attempt to allocate a new color on that window failed and this
+application has not freed any colors in the colormap since the
+failed allocation.
+.TP
+\fBwinfo containing \fR?\fB\-displayof \fIwindow\fR? \fIrootX rootY\fR
+Returns the path name for the window containing the point given
+by \fIrootX\fR and \fIrootY\fR.
+\fIRootX\fR and \fIrootY\fR are specified in screen units (i.e.
+any form acceptable to \fBTk_GetPixels\fR) in the coordinate
+system of the root window (if a virtual-root window manager is in
+use then the coordinate system of the virtual root window is used).
+If the \fB\-displayof\fR option is given then the coordinates refer
+to the screen containing \fIwindow\fR; otherwise they refer to the
+screen of the application's main window.
+If no window in this application contains the point then an empty
+string is returned.
+An empty string is also returned if the point lies in the title bar
+or border of its highest containing toplevel in this application.
+(Note that with some window managers the borders may be invisible.)
+In selecting the containing window, children are given higher priority
+than parents and among siblings the highest one in the stacking order is
+chosen.
+.TP
+\fBwinfo depth \fIwindow\fR
+Returns a decimal string giving the depth of \fIwindow\fR (number
+of bits per pixel).
+.TP
+\fBwinfo exists \fIwindow\fR
+Returns 1 if there exists a window named \fIwindow\fR, 0 if no such
+window exists.
+.TP
+\fBwinfo fpixels \fIwindow\fR \fInumber\fR
+Returns a floating-point value giving the number of pixels
+in \fIwindow\fR corresponding to the distance given by \fInumber\fR.
+\fINumber\fR may be specified in any of the forms acceptable
+to \fBTk_GetScreenMM\fR, such as
+.QW 2.0c
+or
+.QW 1i .
+The return value may be fractional; for an integer value, use
+\fBwinfo pixels\fR.
+.TP
+\fBwinfo geometry \fIwindow\fR
+Returns the geometry for \fIwindow\fR, in the form
+\fIwidth\fBx\fIheight\fB+\fIx\fB+\fIy\fR. All dimensions are
+in pixels.
+.TP
+\fBwinfo height \fIwindow\fR
+Returns a decimal string giving \fIwindow\fR's height in pixels.
+When a window is first created its height will be 1 pixel; the
+height will eventually be changed by a geometry manager to fulfil
+the window's needs.
+If you need the true height immediately after creating a widget,
+invoke \fBupdate\fR to force the geometry manager to arrange it,
+or use \fBwinfo reqheight\fR to get the window's requested height
+instead of its actual height.
+.TP
+\fBwinfo id \fIwindow\fR
+Returns a hexadecimal string giving a low-level platform-specific
+identifier for \fIwindow\fR. On Unix platforms, this is the X
+window identifier. Under Windows, this is the Windows
+HWND. On the Macintosh the value has no meaning outside Tk.
+.TP
+\fBwinfo interps \fR?\fB\-displayof \fIwindow\fR?
+Returns a list whose members are the names of all Tcl interpreters
+(e.g. all Tk-based applications) currently registered for a particular display.
+If the \fB\-displayof\fR option is given then the return value refers
+to the display of \fIwindow\fR; otherwise it refers to
+the display of the application's main window.
+.TP
+\fBwinfo ismapped \fIwindow\fR
+Returns \fB1\fR if \fIwindow\fR is currently mapped, \fB0\fR otherwise.
+.TP
+\fBwinfo manager \fIwindow\fR
+Returns the name of the geometry manager currently
+responsible for \fIwindow\fR, or an empty string if \fIwindow\fR
+is not managed by any geometry manager.
+The name is usually the name of the Tcl command for the geometry
+manager, such as \fBpack\fR or \fBplace\fR.
+If the geometry manager is a widget, such as canvases or text, the
+name is the widget's class command, such as \fBcanvas\fR.
+.TP
+\fBwinfo name \fIwindow\fR
+Returns \fIwindow\fR's name (i.e. its name within its parent, as opposed
+to its full path name).
+The command \fBwinfo name .\fR will return the name of the application.
+.TP
+\fBwinfo parent \fIwindow\fR
+Returns the path name of \fIwindow\fR's parent, or an empty string
+if \fIwindow\fR is the main window of the application.
+.TP
+\fBwinfo pathname \fR?\fB\-displayof \fIwindow\fR? \fIid\fR
+Returns the path name of the window whose X identifier is \fIid\fR.
+\fIId\fR must be a decimal, hexadecimal, or octal integer and must
+correspond to a window in the invoking application.
+If the \fB\-displayof\fR option is given then the identifier is looked
+up on the display of \fIwindow\fR; otherwise it is looked up on
+the display of the application's main window.
+.TP
+\fBwinfo pixels \fIwindow\fR \fInumber\fR
+Returns the number of pixels in \fIwindow\fR corresponding
+to the distance given by \fInumber\fR.
+\fINumber\fR may be specified in any of the forms acceptable
+to \fBTk_GetPixels\fR, such as
+.QW 2.0c
+or
+.QW 1i .
+The result is rounded to the nearest integer value; for a
+fractional result, use \fBwinfo fpixels\fR.
+.TP
+\fBwinfo pointerx \fIwindow\fR
+If the mouse pointer is on the same screen as \fIwindow\fR, returns the
+pointer's x coordinate, measured in pixels in the screen's root window.
+If a virtual root window is in use on the screen, the position is
+measured in the virtual root.
+If the mouse pointer is not on the same screen as \fIwindow\fR then
+-1 is returned.
+.TP
+\fBwinfo pointerxy \fIwindow\fR
+If the mouse pointer is on the same screen as \fIwindow\fR, returns a list
+with two elements, which are the pointer's x and y coordinates measured
+in pixels in the screen's root window.
+If a virtual root window is in use on the screen, the position
+is computed in the virtual root.
+If the mouse pointer is not on the same screen as \fIwindow\fR then
+both of the returned coordinates are \-1.
+.TP
+\fBwinfo pointery \fIwindow\fR
+If the mouse pointer is on the same screen as \fIwindow\fR, returns the
+pointer's y coordinate, measured in pixels in the screen's root window.
+If a virtual root window is in use on the screen, the position
+is computed in the virtual root.
+If the mouse pointer is not on the same screen as \fIwindow\fR then
+-1 is returned.
+.TP
+\fBwinfo reqheight \fIwindow\fR
+Returns a decimal string giving \fIwindow\fR's requested height,
+in pixels. This is the value used by \fIwindow\fR's geometry
+manager to compute its geometry.
+.TP
+\fBwinfo reqwidth \fIwindow\fR
+Returns a decimal string giving \fIwindow\fR's requested width,
+in pixels. This is the value used by \fIwindow\fR's geometry
+manager to compute its geometry.
+.TP
+\fBwinfo rgb \fIwindow color\fR
+Returns a list containing three decimal values in the range 0 to
+65535, which are the
+red, green, and blue intensities that correspond to \fIcolor\fR in
+the window given by \fIwindow\fR. \fIColor\fR
+may be specified in any of the forms acceptable for a color
+option.
+.TP
+\fBwinfo rootx \fIwindow\fR
+Returns a decimal string giving the x-coordinate, in the root
+window of the screen, of the
+upper-left corner of \fIwindow\fR's border (or \fIwindow\fR if it
+has no border).
+.TP
+\fBwinfo rooty \fIwindow\fR
+Returns a decimal string giving the y-coordinate, in the root
+window of the screen, of the
+upper-left corner of \fIwindow\fR's border (or \fIwindow\fR if it
+has no border).
+.TP
+\fBwinfo screen \fIwindow\fR
+Returns the name of the screen associated with \fIwindow\fR, in
+the form \fIdisplayName\fR.\fIscreenIndex\fR.
+.TP
+\fBwinfo screencells \fIwindow\fR
+Returns a decimal string giving the number of cells in the default
+color map for \fIwindow\fR's screen.
+.TP
+\fBwinfo screendepth \fIwindow\fR
+Returns a decimal string giving the depth of the root window
+of \fIwindow\fR's screen (number of bits per pixel).
+.TP
+\fBwinfo screenheight \fIwindow\fR
+Returns a decimal string giving the height of \fIwindow\fR's screen,
+in pixels.
+.TP
+\fBwinfo screenmmheight \fIwindow\fR
+Returns a decimal string giving the height of \fIwindow\fR's screen,
+in millimeters.
+.TP
+\fBwinfo screenmmwidth \fIwindow\fR
+Returns a decimal string giving the width of \fIwindow\fR's screen,
+in millimeters.
+.TP
+\fBwinfo screenvisual \fIwindow\fR
+Returns one of the following strings to indicate the default visual
+class for \fIwindow\fR's screen: \fBdirectcolor\fR, \fBgrayscale\fR,
+\fBpseudocolor\fR, \fBstaticcolor\fR, \fBstaticgray\fR, or
+\fBtruecolor\fR.
+.TP
+\fBwinfo screenwidth \fIwindow\fR
+Returns a decimal string giving the width of \fIwindow\fR's screen,
+in pixels.
+.TP
+\fBwinfo server \fIwindow\fR
+Returns a string containing information about the server for
+\fIwindow\fR's display. The exact format of this string may vary
+from platform to platform. For X servers the string
+has the form
+.QW "\fBX\fImajor\fBR\fIminor vendor vendorVersion\fR"
+where \fImajor\fR and \fIminor\fR are the version and revision
+numbers provided by the server (e.g., \fBX11R5\fR), \fIvendor\fR
+is the name of the vendor for the server, and \fIvendorRelease\fR
+is an integer release number provided by the server.
+.TP
+\fBwinfo toplevel \fIwindow\fR
+Returns the path name of the top-of-hierarchy window containing \fIwindow\fR.
+In standard Tk this will always be a \fBtoplevel\fR widget, but extensions may
+create other kinds of top-of-hierarchy widgets.
+.TP
+\fBwinfo viewable \fIwindow\fR
+Returns 1 if \fIwindow\fR and all of its ancestors up through the
+nearest toplevel window are mapped. Returns 0 if any of these
+windows are not mapped.
+.TP
+\fBwinfo visual \fIwindow\fR
+Returns one of the following strings to indicate the visual
+class for \fIwindow\fR: \fBdirectcolor\fR, \fBgrayscale\fR,
+\fBpseudocolor\fR, \fBstaticcolor\fR, \fBstaticgray\fR, or
+\fBtruecolor\fR.
+.TP
+\fBwinfo visualid \fIwindow\fR
+Returns the X identifier for the visual for \fIwindow\fR.
+.TP
+\fBwinfo visualsavailable \fIwindow\fR ?\fBincludeids\fR?
+Returns a list whose elements describe the visuals available for
+\fIwindow\fR's screen.
+Each element consists of a visual class followed by an integer depth.
+The class has the same form as returned by \fBwinfo visual\fR.
+The depth gives the number of bits per pixel in the visual.
+In addition, if the \fBincludeids\fR argument is provided, then the
+depth is followed by the X identifier for the visual.
+.TP
+\fBwinfo vrootheight \fIwindow\fR
+Returns the height of the virtual root window associated with \fIwindow\fR
+if there is one; otherwise returns the height of \fIwindow\fR's screen.
+.TP
+\fBwinfo vrootwidth \fIwindow\fR
+Returns the width of the virtual root window associated with \fIwindow\fR
+if there is one; otherwise returns the width of \fIwindow\fR's screen.
+.TP
+\fBwinfo vrootx \fIwindow\fR
+Returns the x-offset of the virtual root window associated with \fIwindow\fR,
+relative to the root window of its screen.
+This is normally either zero or negative.
+Returns 0 if there is no virtual root window for \fIwindow\fR.
+.TP
+\fBwinfo vrooty \fIwindow\fR
+Returns the y-offset of the virtual root window associated with \fIwindow\fR,
+relative to the root window of its screen.
+This is normally either zero or negative.
+Returns 0 if there is no virtual root window for \fIwindow\fR.
+.TP
+\fBwinfo width \fIwindow\fR
+Returns a decimal string giving \fIwindow\fR's width in pixels.
+When a window is first created its width will be 1 pixel; the
+width will eventually be changed by a geometry manager to fulfil
+the window's needs.
+If you need the true width immediately after creating a widget,
+invoke \fBupdate\fR to force the geometry manager to arrange it,
+or use \fBwinfo reqwidth\fR to get the window's requested width
+instead of its actual width.
+.TP
+\fBwinfo x \fIwindow\fR
+Returns a decimal string giving the x-coordinate, in \fIwindow\fR's
+parent, of the
+upper-left corner of \fIwindow\fR's border (or \fIwindow\fR if it
+has no border).
+.TP
+\fBwinfo y \fIwindow\fR
+Returns a decimal string giving the y-coordinate, in \fIwindow\fR's
+parent, of the
+upper-left corner of \fIwindow\fR's border (or \fIwindow\fR if it
+has no border).
+.SH EXAMPLE
+.PP
+Print where the mouse pointer is and what window it is currently over:
+.CS
+lassign [\fBwinfo pointerxy\fR .] x y
+puts \-nonewline "Mouse pointer at ($x,$y) which is "
+set win [\fBwinfo containing\fR $x $y]
+if {$win eq ""} {
+ puts "over no window"
+} else {
+ puts "over $win"
+}
+.CE
+.SH KEYWORDS
+atom, children, class, geometry, height, identifier, information, interpreters,
+mapped, parent, path name, screen, virtual root, width, window
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/doc/wish.1 b/tk8.6/doc/wish.1
new file mode 100644
index 0000000..93ade0d
--- /dev/null
+++ b/tk8.6/doc/wish.1
@@ -0,0 +1,218 @@
+'\"
+'\" Copyright (c) 1991-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH wish 1 8.0 Tk "Tk Applications"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+wish \- Simple windowing shell
+.SH SYNOPSIS
+\fBwish\fR ?\fB\-encoding \fIname\fR? ?\fIfileName arg arg ...\fR?
+.SH OPTIONS
+.IP "\fB\-encoding \fIname\fR" 20
+Specifies the encoding of the text stored in \fIfileName\fR.
+This option is only recognized prior to the \fIfileName\fR argument.
+.IP "\fB\-colormap \fInew\fR" 20
+Specifies that the window should have a new private colormap instead of
+using the default colormap for the screen.
+.IP "\fB\-display \fIdisplay\fR" 20
+Display (and screen) on which to display window.
+.IP "\fB\-geometry \fIgeometry\fR" 20
+Initial geometry to use for window. If this option is specified, its
+value is stored in the \fBgeometry\fR global variable of the application's
+Tcl interpreter.
+.IP "\fB\-name \fIname\fR" 20
+Use \fIname\fR as the title to be displayed in the window, and
+as the name of the interpreter for \fBsend\fR commands.
+.IP "\fB\-sync\fR" 20
+Execute all X server commands synchronously, so that errors
+are reported immediately. This will result in much slower
+execution, but it is useful for debugging.
+.IP "\fB\-use\fR \fIid\fR" 20
+Specifies that the main window for the application is to be embedded in
+the window whose identifier is \fIid\fR, instead of being created as an
+independent toplevel window. \fIId\fR must be specified in the same
+way as the value for the \fB\-use\fR option for toplevel widgets (i.e.
+it has a form like that returned by the \fBwinfo id\fR command).
+.RS
+Note that on some platforms this will only work correctly if \fIid\fR
+refers to a Tk \fBframe\fR or \fBtoplevel\fR that has its
+\fB\-container\fR option enabled.
+.RE
+.IP "\fB\-visual \fIvisual\fR" 20
+Specifies the visual to use for the window.
+\fIVisual\fR may have any of the forms supported by the \fBTk_GetVisual\fR
+procedure.
+.IP "\fB\-\|\-\fR" 20
+Pass all remaining arguments through to the script's \fBargv\fR
+variable without interpreting them.
+This provides a mechanism for passing arguments such as \fB\-name\fR
+to a script instead of having \fBwish\fR interpret them.
+.BE
+.SH DESCRIPTION
+.PP
+\fBWish\fR is a simple program consisting of the Tcl command
+language, the Tk toolkit, and a main program that reads commands
+from standard input or from a file.
+It creates a main window and then processes Tcl commands.
+If \fBwish\fR is invoked with arguments, then the first few
+arguments, ?\fB\-encoding \fIname\fR? ?\fIfileName\fR?, specify the
+name of a script file, and, optionally, the
+encoding of the text data stored in that script file. A value
+for \fIfileName\fR is recognized if the appropriate argument
+does not start with
+.QW \- .
+.PP
+If there are no arguments, or the arguments do not specify a \fIfileName\fR,
+then wish reads Tcl commands interactively from standard input.
+It will continue processing commands until all windows have been
+deleted or until end-of-file is reached on standard input.
+If there exists a file
+.QW \fB.wishrc\fR
+in the home directory of the user, \fBwish\fR evaluates the file as a
+Tcl script just before reading the first command from standard input.
+.PP
+If arguments to \fBwish\fR do specify a \fIfileName\fR, then
+\fIfileName\fR is treated as the name of a script file.
+\fBWish\fR will evaluate the script in \fIfileName\fR (which
+presumably creates a user interface), then it will respond to events
+until all windows have been deleted.
+Commands will not be read from standard input.
+There is no automatic evaluation of
+.QW \fB.wishrc\fR
+when the name of a script file is presented on the \fBwish\fR command line,
+but the script file can always \fBsource\fR it if desired.
+.PP
+Note that on Windows, the \fBwish\fIversion\fB.exe\fR program varies
+from the \fBtclsh\fIversion\fB.exe\fR program in an additional
+important way: it does not connect to a standard Windows console and
+is instead a windowed program. Because of this, it additionally
+provides access to its own \fBconsole\fR command.
+.SH "OPTION PROCESSING"
+.PP
+\fBWish\fR automatically processes all of the command-line options
+described in the \fBOPTIONS\fR summary above.
+Any other command-line arguments besides these are passed through
+to the application using the \fBargc\fR and \fBargv\fR variables
+described later.
+.SH "APPLICATION NAME AND CLASS"
+.PP
+The name of the application, which is used for purposes such as
+\fBsend\fR commands, is taken from the \fB\-name\fR option,
+if it is specified; otherwise it is taken from \fIfileName\fR,
+if it is specified, or from the command name by which
+\fBwish\fR was invoked. In the last two cases, if the name contains a
+.QW /
+character, then only the characters after the last slash are used
+as the application name.
+.PP
+The class of the application, which is used for purposes such as
+specifying options with a \fBRESOURCE_MANAGER\fR property or .Xdefaults
+file, is the same as its name except that the first letter is
+capitalized.
+.SH "VARIABLES"
+.PP
+\fBWish\fR sets the following Tcl variables:
+.TP 15
+\fBargc\fR
+Contains a count of the number of \fIarg\fR arguments (0 if none),
+not including the options described above.
+.TP 15
+\fBargv\fR
+Contains a Tcl list whose elements are the \fIarg\fR arguments
+that follow a \fB\-\|\-\fR option or do not match any of the
+options described in \fBOPTIONS\fR above, in order, or an empty string
+if there are no such arguments.
+.TP 15
+\fBargv0\fR
+Contains \fIfileName\fR if it was specified.
+Otherwise, contains the name by which \fBwish\fR was invoked.
+.TP 15
+\fBgeometry\fR
+If the \fB\-geometry\fR option is specified, \fBwish\fR copies its
+value into this variable. If the variable still exists after
+\fIfileName\fR has been evaluated, \fBwish\fR uses the value of
+the variable in a \fBwm geometry\fR command to set the main
+window's geometry.
+.TP 15
+\fBtcl_interactive\fR
+Contains 1 if \fBwish\fR is reading commands interactively (\fIfileName\fR
+was not specified and standard input is a terminal-like
+device), 0 otherwise.
+.SH "SCRIPT FILES"
+.PP
+If you create a Tcl script in a file whose first line is
+.CS
+\fB#!/usr/local/bin/wish\fR
+.CE
+then you can invoke the script file directly from your shell if
+you mark it as executable.
+This assumes that \fBwish\fR has been installed in the default
+location in /usr/local/bin; if it is installed somewhere else
+then you will have to modify the above line to match.
+Many UNIX systems do not allow the \fB#!\fR line to exceed about
+30 characters in length, so be sure that the \fBwish\fR executable
+can be accessed with a short file name.
+.PP
+An even better approach is to start your script files with the
+following three lines:
+.CS
+\fB#!/bin/sh
+# the next line restarts using wish \e
+exec wish "$0" ${1+"$@"}\fR
+.CE
+This approach has three advantages over the approach in the previous
+paragraph. First, the location of the \fBwish\fR binary does not have
+to be hard-wired into the script: it can be anywhere in your shell
+search path. Second, it gets around the 30-character file name limit
+in the previous approach.
+Third, this approach will work even if \fBwish\fR is
+itself a shell script (this is done on some systems in order to
+handle multiple architectures or operating systems: the \fBwish\fR
+script selects one of several binaries to run). The three lines
+cause both \fBsh\fR and \fBwish\fR to process the script, but the
+\fBexec\fR is only executed by \fBsh\fR.
+\fBsh\fR processes the script first; it treats the second
+line as a comment and executes the third line.
+The \fBexec\fR statement cause the shell to stop processing and
+instead to start up \fBwish\fR to reprocess the entire script.
+When \fBwish\fR starts up, it treats all three lines as comments,
+since the backslash at the end of the second line causes the third
+line to be treated as part of the comment on the second line.
+.PP
+The end of a script file may be marked either by the physical end of
+the medium, or by the character,
+.QW \e032
+.PQ \eu001a ", control-Z" .
+If this character is present in the file, the \fBwish\fR application
+will read text up to but not including the character. An application
+that requires this character in the file may encode it as
+.QW \e032 ,
+.QW \ex1a ,
+or
+.QW \eu001a ;
+or may generate it by use of commands such as \fBformat\fR or \fBbinary\fR.
+.SH PROMPTS
+.PP
+When \fBwish\fR is invoked interactively it normally prompts for each
+command with
+.QW "\fB% \fR" .
+You can change the prompt by setting the
+variables \fBtcl_prompt1\fR and \fBtcl_prompt2\fR. If variable
+\fBtcl_prompt1\fR exists then it must consist of a Tcl script
+to output a prompt; instead of outputting a prompt \fBwish\fR
+will evaluate the script in \fBtcl_prompt1\fR.
+The variable \fBtcl_prompt2\fR is used in a similar way when
+a newline is typed but the current command is not yet complete;
+if \fBtcl_prompt2\fR is not set then no prompt is output for
+incomplete commands.
+.SH "SEE ALSO"
+tclsh(1), toplevel(n), Tk_Main(3), Tk_MainLoop(3), Tk_MainWindow(3)
+.SH KEYWORDS
+application, argument, interpreter, prompt, script file, shell,
+toolkit, toplevel
diff --git a/tk8.6/doc/wm.n b/tk8.6/doc/wm.n
new file mode 100644
index 0000000..a137d06
--- /dev/null
+++ b/tk8.6/doc/wm.n
@@ -0,0 +1,860 @@
+'\"
+'\" Copyright (c) 1991-1994 The Regents of the University of California.
+'\" Copyright (c) 1994-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.
+'\"
+.TH wm n 8.5 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+wm \- Communicate with window manager
+.SH SYNOPSIS
+\fBwm\fR \fIoption window \fR?\fIargs\fR?
+.BE
+.SH DESCRIPTION
+.PP
+The \fBwm\fR command is used to interact with window managers in
+order to control such things as the title for a window, its geometry,
+or the increments in terms of which it may be resized. The \fBwm\fR
+command can take any of a number of different forms, depending on
+the \fIoption\fR argument. All of the forms expect at least one
+additional argument, \fIwindow\fR, which must be the path name of a
+top-level window.
+.PP
+The legal forms for the \fBwm\fR command are:
+.TP
+\fBwm aspect \fIwindow\fR ?\fIminNumer minDenom maxNumer maxDenom\fR?
+.
+If \fIminNumer\fR, \fIminDenom\fR, \fImaxNumer\fR, and \fImaxDenom\fR
+are all specified, then they will be passed to the window manager
+and the window manager should use them to enforce a range of
+acceptable aspect ratios for \fIwindow\fR. The aspect ratio of
+\fIwindow\fR (width/length) will be constrained to lie
+between \fIminNumer\fR/\fIminDenom\fR and \fImaxNumer\fR/\fImaxDenom\fR.
+If \fIminNumer\fR etc. are all specified as empty strings, then
+any existing aspect ratio restrictions are removed.
+If \fIminNumer\fR etc. are specified, then the command returns an
+empty string. Otherwise, it returns
+a Tcl list containing four elements, which are the current values
+of \fIminNumer\fR, \fIminDenom\fR, \fImaxNumer\fR, and \fImaxDenom\fR
+(if no aspect restrictions are in effect, then an empty string is
+returned).
+.TP
+\fBwm attributes \fIwindow\fR
+.TP
+\fBwm attributes \fIwindow\fR ?\fBoption\fR?
+.TP
+\fBwm attributes \fIwindow\fR ?\fBoption value option value...\fR?
+.
+This subcommand returns or sets platform specific attributes associated
+with a window. The first form returns a list of the platform specific
+flags and their values. The second form returns the value for the
+specific option. The third form sets one or more of the values. The
+values are as follows:
+.RS
+.PP
+All platforms support the following attributes (though X11 users
+should see the notes below):
+.TP
+\fB\-alpha\fR
+.
+Specifies the alpha transparency level of the toplevel. It accepts a value
+from \fB0.0\fR (fully transparent) to \fB1.0\fR (opaque). Values outside that
+range will be constrained. Where not supported, the \fB\-alpha\fR value
+remains at \fB1.0\fR.
+.TP
+\fB\-fullscreen\fR
+.
+Places the window in a mode that takes up the entire screen, has no
+borders, and covers the general use area (i.e. Start menu and taskbar on
+Windows, dock and menubar on OSX, general window decorations on X11).
+.TP
+\fB\-topmost\fR
+.
+Specifies whether this is a topmost window (displays above all other windows).
+.PP
+On Windows, the following attributes may be set.
+.TP
+\fB\-disabled\fR
+.
+Specifies whether the window is in a disabled state.
+.TP
+\fB\-toolwindow\fR
+.
+Specifies a toolwindow style window (as defined in the MSDN).
+.TP
+\fB\-transparentcolor\fR
+.
+Specifies the transparent color index of the toplevel. It takes any color
+value accepted by \fBTk_GetColor\fR. If the empty string is specified
+(default), no transparent color is used. This is supported on Windows
+2000/XP+. Where not supported, the \fB\-transparentcolor\fR value remains
+at \fB{}\fR.
+.PP
+On Mac OS X, the following attributes may be set.
+.TP
+\fB\-modified\fR
+.
+Specifies the modification state of the window (determines whether the
+window close widget contains the modification indicator and whether the
+proxy icon is draggable).
+.TP
+\fB\-notify\fR
+.
+Specifies process notification state (bouncing of the application dock icon).
+.TP
+\fB\-titlepath\fR
+.
+Specifies the path of the file referenced as the window proxy icon (which
+can be dragged and dropped in lieu of the file's finder icon).
+.TP
+\fB\-transparent\fR
+.
+Makes the window content area transparent and turns off the window shadow. For
+the transparency to be effective, the toplevel background needs to be set to a
+color with some alpha, e.g.
+.QW systemTransparent .
+.PP
+On X11, the following attributes may be set. These are not supported by all
+window managers, and will have no effect under older WMs.
+.\" See http://www.freedesktop.org/Standards/wm-spec
+.TP
+\fB\-type\fR
+.VS 8.6
+Requests that the window should be interpreted by the window manager as being
+of the specified type(s). This may cause the window to be decorated in a
+different way or otherwise managed differently, though exactly what happens is
+entirely up to the window manager. A list of types may be used, in order of
+preference. The following values are mapped to constants defined in the EWMH
+specification (using others is possible, but not advised):
+.RS
+.TP
+\fBdesktop\fR
+.
+indicates a desktop feature,
+.TP
+\fBdock\fR
+.
+indicates a dock/panel feature,
+.TP
+\fBtoolbar\fR
+.
+indicates a toolbar window that should be acting on behalf of another window,
+as indicated with \fBwm transient\fR,
+.TP
+\fBmenu\fR
+.
+indicates a torn-off menu that should be acting on behalf of another window,
+as indicated with \fBwm transient\fR,
+.TP
+\fButility\fR
+.
+indicates a utility window (e.g., palette or toolbox) that should be acting on
+behalf of another window, as indicated with \fBwm transient\fR,
+.TP
+\fBsplash\fR
+.
+indicates a splash screen, displayed during application start up,
+.TP
+\fBdialog\fR
+.
+indicates a general dialog window, that should be acting on behalf of another
+window, as indicated with \fBwm transient\fR,
+.TP
+\fBdropdown_menu\fR
+.
+indicates a menu summoned from a menu bar, which should usually also be set to
+be override-redirected (with \fBwm overrideredirect\fR),
+.TP
+\fBpopup_menu\fR
+.
+indicates a popup menu, which should usually also be set to be
+override-redirected (with \fBwm overrideredirect\fR),
+.TP
+\fBtooltip\fR
+.
+indicates a tooltip window, which should usually also be set to be
+override-redirected (with \fBwm overrideredirect\fR),
+.TP
+\fBnotification\fR
+.
+indicates a window that provides a background notification of some event,
+which should usually also be set to be override-redirected (with \fBwm
+overrideredirect\fR),
+.TP
+\fBcombo\fR
+.
+indicates the drop-down list of a combobox widget, which should usually also
+be set to be override-redirected (with \fBwm overrideredirect\fR),
+.TP
+\fBdnd\fR
+.
+indicates a window that represents something being dragged, which should
+usually also be set to be override-redirected (with
+\fBwm overrideredirect\fR),
+.TP
+\fBnormal\fR
+.
+indicates a window that has no special interpretation.
+.RE
+.VE 8.6
+.TP
+\fB\-zoomed\fR
+.
+Requests that the window should be maximized. This is the same as \fBwm state
+zoomed\fR on Windows and Mac OS X.
+.PP
+On X11, changes to window attributes are performed asynchronously. Querying
+the value of an attribute returns the current state, which will not be the
+same as the value most recently set if the window manager has not yet
+processed the request or if it does not support the attribute.
+.RE
+.TP
+\fBwm client \fIwindow\fR ?\fIname\fR?
+.
+If \fIname\fR is specified, this command stores \fIname\fR (which
+should be the name of
+the host on which the application is executing) in \fIwindow\fR's
+\fBWM_CLIENT_MACHINE\fR property for use by the window manager or
+session manager.
+The command returns an empty string in this case.
+If \fIname\fR is not specified, the command returns the last name
+set in a \fBwm client\fR command for \fIwindow\fR.
+If \fIname\fR is specified as an empty string, the command deletes the
+\fBWM_CLIENT_MACHINE\fR property from \fIwindow\fR.
+.TP
+\fBwm colormapwindows \fIwindow\fR ?\fIwindowList\fR?
+.
+This command is used to manipulate the \fBWM_COLORMAP_WINDOWS\fR
+property, which provides information to the window managers about
+windows that have private colormaps.
+.RS
+.PP
+If \fIwindowList\fR is not specified, the command returns a list
+whose elements are the names of the windows in the \fBWM_COLORMAP_WINDOWS\fR
+property.
+If \fIwindowList\fR is specified, it consists of a list of window
+path names; the command overwrites the \fBWM_COLORMAP_WINDOWS\fR
+property with the given windows and returns an empty string.
+The \fBWM_COLORMAP_WINDOWS\fR property should normally contain a
+list of the internal windows within \fIwindow\fR whose colormaps differ
+from their parents.
+.PP
+The order of the windows in the property indicates a priority order:
+the window manager will attempt to install as many colormaps as possible
+from the head of this list when \fIwindow\fR gets the colormap focus.
+If \fIwindow\fR is not included among the windows in \fIwindowList\fR,
+Tk implicitly adds it at the end of the \fBWM_COLORMAP_WINDOWS\fR
+property, so that its colormap is lowest in priority.
+If \fBwm colormapwindows\fR is not invoked, Tk will automatically set
+the property for each top-level window to all the internal windows
+whose colormaps differ from their parents, followed by the top-level
+itself; the order of the internal windows is undefined.
+See the ICCCM documentation for more information on the
+\fBWM_COLORMAP_WINDOWS\fR property.
+.RE
+.TP
+\fBwm command \fIwindow\fR ?\fIvalue\fR?
+.
+If \fIvalue\fR is specified, this command stores \fIvalue\fR in \fIwindow\fR's
+\fBWM_COMMAND\fR property for use by the window manager or
+session manager and returns an empty string.
+\fIValue\fR must have proper list structure; the elements should
+contain the words of the command used to invoke the application.
+If \fIvalue\fR is not specified then the command returns the last value
+set in a \fBwm command\fR command for \fIwindow\fR.
+If \fIvalue\fR is specified as an empty string, the command
+deletes the \fBWM_COMMAND\fR property from \fIwindow\fR.
+.TP
+\fBwm deiconify \fIwindow\fR
+.
+Arrange for \fIwindow\fR to be displayed in normal (non-iconified) form.
+This is done by mapping the window. If the window has never been
+mapped then this command will not map the window, but it will ensure
+that when the window is first mapped it will be displayed
+in de-iconified form. On Windows, a deiconified window will also be
+raised and be given the focus (made the active window).
+Returns an empty string.
+.TP
+\fBwm focusmodel \fIwindow\fR ?\fBactive\fR|\fBpassive\fR?
+.
+If \fBactive\fR or \fBpassive\fR is supplied as an optional argument
+to the command, then it specifies the focus model for \fIwindow\fR.
+In this case the command returns an empty string. If no additional
+argument is supplied, then the command returns the current focus
+model for \fIwindow\fR.
+.RS
+.PP
+An \fBactive\fR focus model means that \fIwindow\fR will claim the
+input focus for itself or its descendants, even at times when
+the focus is currently in some other application. \fBPassive\fR means that
+\fIwindow\fR will never claim the focus for itself: the window manager
+should give the focus to \fIwindow\fR at appropriate times. However,
+once the focus has been given to \fIwindow\fR or one of its descendants,
+the application may re-assign the focus among \fIwindow\fR's descendants.
+The focus model defaults to \fBpassive\fR, and Tk's \fBfocus\fR command
+assumes a passive model of focusing.
+.RE
+.TP
+\fBwm forget \fIwindow\fR
+.
+The \fIwindow\fR will be unmapped from the screen and will no longer
+be managed by \fBwm\fR. Windows created with the \fBtoplevel\fR
+command will be treated like \fBframe\fR windows once they are no
+longer managed by \fBwm\fR, however, the \fB\-menu\fR configuration will be
+remembered and the menus will return once the widget is managed again.
+.TP
+\fBwm frame \fIwindow\fR
+.
+If \fIwindow\fR has been reparented by the window manager into a
+decorative frame, the command returns the platform specific window
+identifier for the outermost frame that contains \fIwindow\fR (the
+window whose parent is the root or virtual root). If \fIwindow\fR
+has not been reparented by the window manager then the command returns
+the platform specific window identifier for \fIwindow\fR.
+.TP
+\fBwm geometry \fIwindow\fR ?\fInewGeometry\fR?
+.
+If \fInewGeometry\fR is specified, then the geometry of \fIwindow\fR
+is changed and an empty string is returned. Otherwise the current
+geometry for \fIwindow\fR is returned (this is the most recent
+geometry specified either by manual resizing or
+in a \fBwm geometry\fR command). \fINewGeometry\fR has
+the form \fB=\fIwidth\fBx\fIheight\fB\(+-\fIx\fB\(+-\fIy\fR, where
+any of \fB=\fR, \fIwidth\fBx\fIheight\fR, or \fB\(+-\fIx\fB\(+-\fIy\fR
+may be omitted. \fIWidth\fR and \fIheight\fR are positive integers
+specifying the desired dimensions of \fIwindow\fR. If \fIwindow\fR
+is gridded (see \fBGRIDDED GEOMETRY MANAGEMENT\fR below) then the dimensions
+are specified in grid units; otherwise they are specified in pixel
+units.
+.RS
+.PP
+\fIX\fR and \fIy\fR specify the desired location of
+\fIwindow\fR on the screen, in pixels.
+If \fIx\fR is preceded by \fB+\fR, it specifies
+the number of pixels between the left edge of the screen and the left
+edge of \fIwindow\fR's border; if preceded by \fB\-\fR then
+\fIx\fR specifies the number of pixels
+between the right edge of the screen and the right edge of \fIwindow\fR's
+border. If \fIy\fR is preceded by \fB+\fR then it specifies the
+number of pixels between the top of the screen and the top
+of \fIwindow\fR's border; if \fIy\fR is preceded by \fB\-\fR then
+it specifies the number of pixels between the bottom of \fIwindow\fR's
+border and the bottom of the screen.
+.PP
+If \fInewGeometry\fR is specified as an empty string then any
+existing user-specified geometry for \fIwindow\fR is cancelled, and
+the window will revert to the size requested internally by its
+widgets.
+.PP
+Note that this is related to \fBwinfo geometry\fR, but not the same. That can
+only query the geometry, and always reflects Tk's current understanding of the
+actual size and location of \fIwindow\fR, whereas \fBwm geometry\fR allows
+both setting and querying of the \fIwindow manager\fR's understanding of the
+size and location of the window. This can vary significantly, for example to
+reflect the addition of decorative elements to \fIwindow\fR such as title
+bars, and window managers are not required to precisely follow the requests
+made through this command.
+.RE
+.TP
+\fBwm grid \fIwindow\fR ?\fIbaseWidth baseHeight widthInc heightInc\fR?
+.
+This command indicates that \fIwindow\fR is to be managed as a
+gridded window.
+It also specifies the relationship between grid units and pixel units.
+\fIBaseWidth\fR and \fIbaseHeight\fR specify the number of grid
+units corresponding to the pixel dimensions requested internally
+by \fIwindow\fR using \fBTk_GeometryRequest\fR. \fIWidthInc\fR
+and \fIheightInc\fR specify the number of pixels in each horizontal
+and vertical grid unit.
+These four values determine a range of acceptable sizes for
+\fIwindow\fR, corresponding to grid-based widths and heights
+that are non-negative integers.
+Tk will pass this information to the window manager; during
+manual resizing, the window manager will restrict the window's size
+to one of these acceptable sizes.
+.RS
+.PP
+Furthermore, during manual resizing the window manager will display
+the window's current size in terms of grid units rather than pixels.
+If \fIbaseWidth\fR etc. are all specified as empty strings, then
+\fIwindow\fR will no longer be managed as a gridded window. If
+\fIbaseWidth\fR etc. are specified then the return value is an
+empty string.
+.PP
+Otherwise the return value is a Tcl list containing
+four elements corresponding to the current \fIbaseWidth\fR,
+\fIbaseHeight\fR, \fIwidthInc\fR, and \fIheightInc\fR; if
+\fIwindow\fR is not currently gridded, then an empty string
+is returned.
+.PP
+Note: this command should not be needed very often, since the
+\fBTk_SetGrid\fR library procedure and the \fBsetGrid\fR option
+provide easier access to the same functionality.
+.RE
+.TP
+\fBwm group \fIwindow\fR ?\fIpathName\fR?
+.
+If \fIpathName\fR is specified, it gives the path name for the leader of
+a group of related windows. The window manager may use this information,
+for example, to unmap all of the windows in a group when the group's
+leader is iconified. \fIPathName\fR may be specified as an empty string to
+remove \fIwindow\fR from any group association. If \fIpathName\fR is
+specified then the command returns an empty string; otherwise it
+returns the path name of \fIwindow\fR's current group leader, or an empty
+string if \fIwindow\fR is not part of any group.
+.TP
+\fBwm iconbitmap \fIwindow\fR ?\fIbitmap\fR?
+.
+If \fIbitmap\fR is specified, then it names a bitmap in the standard
+forms accepted by Tk (see the \fBTk_GetBitmap\fR manual entry for details).
+This bitmap is passed to the window manager to be displayed in
+\fIwindow\fR's icon, and the command returns an empty string. If
+an empty string is specified for \fIbitmap\fR, then any current icon
+bitmap is cancelled for \fIwindow\fR.
+If \fIbitmap\fR is specified then the command returns an empty string.
+Otherwise it returns the name of
+the current icon bitmap associated with \fIwindow\fR, or an empty
+string if \fIwindow\fR has no icon bitmap. On the Windows operating
+system, an additional flag is supported:
+.RS
+.TP
+\fBwm iconbitmap \fIwindow\fR ?\fB\-default\fR? ?\fIimage\fR?
+.
+If the \fB\-default\fR
+flag is given, the icon is applied to all toplevel windows (existing
+and future) to which no other specific icon has yet been applied.
+In addition to bitmap image types, a full path specification to
+any file which contains a valid
+Windows icon is also accepted (usually .ico or .icr files), or any
+file for which the shell has assigned an icon. Tcl will
+first test if the file contains an icon, then if it has an assigned
+icon, and finally, if that fails, test for
+a bitmap.
+.RE
+.TP
+\fBwm iconify \fIwindow\fR
+.
+Arrange for \fIwindow\fR to be iconified. It \fIwindow\fR has not
+yet been mapped for the first time, this command will arrange for
+it to appear in the iconified state when it is eventually mapped.
+.TP
+\fBwm iconmask \fIwindow\fR ?\fIbitmap\fR?
+.
+If \fIbitmap\fR is specified, then it names a bitmap in the standard
+forms accepted by Tk (see the \fBTk_GetBitmap\fR manual entry for details).
+This bitmap is passed to the window manager to be used as a mask
+in conjunction with the \fBiconbitmap\fR option: where the mask
+has zeroes no icon will be displayed; where it has ones, the bits
+from the icon bitmap will be displayed. If
+an empty string is specified for \fIbitmap\fR then any current icon
+mask is cancelled for \fIwindow\fR (this is equivalent to specifying
+a bitmap of all ones). If \fIbitmap\fR is specified
+then the command returns an empty string. Otherwise it
+returns the name of the current icon mask associated with
+\fIwindow\fR, or an empty string if no mask is in effect.
+.TP
+\fBwm iconname \fIwindow\fR ?\fInewName\fR?
+.
+If \fInewName\fR is specified, then it is passed to the window
+manager; the window manager should display \fInewName\fR inside
+the icon associated with \fIwindow\fR. In this case an empty
+string is returned as result. If \fInewName\fR is not specified
+then the command returns the current icon name for \fIwindow\fR,
+or an empty string if no icon name has been specified (in this
+case the window manager will normally display the window's title,
+as specified with the \fBwm title\fR command).
+.TP
+\fBwm iconphoto \fIwindow\fR ?\fB\-default\fR? \fIimage1\fR ?\fIimage2 ...\fR?
+.
+Sets the titlebar icon for \fIwindow\fR based on the named photo images.
+If \fB\-default\fR is specified, this is applied to all future created
+toplevels as well. The data in the images is taken as a snapshot at the
+time of invocation. If the images are later changed, this is not
+reflected to the titlebar icons. Multiple images are accepted to allow
+different images sizes (e.g., 16x16 and 32x32) to be provided. The window
+manager may scale provided icons to an appropriate size.
+.RS
+.PP
+On Windows, the images are packed into a Windows icon structure.
+This will override an ico specified to \fBwm iconbitmap\fR, and
+vice versa.
+.PP
+On X, the images are arranged into the _NET_WM_ICON X property, which
+most modern window managers support. A \fBwm iconbitmap\fR may exist
+simultaneously. It is recommended to use not more than 2 icons, placing
+the larger icon first.
+.PP
+On Macintosh, the first image called is loaded into an OSX-native icon
+format, and becomes the application icon in dialogs, the Dock, and
+other contexts. At the
+script level the command will accept only the first image passed in the
+parameters as support for multiple sizes/resolutions on macOS is outside Tk's
+scope. Developers should use the largest icon they can support
+(preferably 512 pixels) to ensure smooth rendering on the Mac.
+.RE
+.TP
+\fBwm iconposition \fIwindow\fR ?\fIx y\fR?
+.
+If \fIx\fR and \fIy\fR are specified, they are passed to the window
+manager as a hint about where to position the icon for \fIwindow\fR.
+In this case an empty string is returned. If \fIx\fR and \fIy\fR are
+specified as empty strings then any existing icon position hint is cancelled.
+If neither \fIx\fR nor \fIy\fR is specified, then the command returns
+a Tcl list containing two values, which are the current icon position
+hints (if no hints are in effect then an empty string is returned).
+.TP
+\fBwm iconwindow \fIwindow\fR ?\fIpathName\fR?
+.
+If \fIpathName\fR is specified, it is the path name for a window to
+use as icon for \fIwindow\fR: when \fIwindow\fR is iconified then
+\fIpathName\fR will be mapped to serve as icon, and when \fIwindow\fR
+is de-iconified then \fIpathName\fR will be unmapped again. If
+\fIpathName\fR is specified as an empty string then any existing
+icon window association for \fIwindow\fR will be cancelled. If
+the \fIpathName\fR argument is specified then an empty string is
+returned. Otherwise the command returns the path name of the
+current icon window for \fIwindow\fR, or an empty string if there
+is no icon window currently specified for \fIwindow\fR.
+Button press events are disabled for \fIwindow\fR as long as it is
+an icon window; this is needed in order to allow window managers to
+.QW own
+those events.
+Note: not all window managers support the notion of an icon window.
+.TP
+\fBwm manage \fIwidget\fR
+.
+The \fIwidget\fR specified will become a stand alone top-level window. The
+window will be decorated with the window managers title bar, etc. Only
+\fIframe\fR, \fIlabelframe\fR and \fItoplevel\fR widgets can be used
+with this command. Attempting to pass any other widget type will raise
+an error. Attempting to manage a \fItoplevel\fR widget is benign and
+achieves nothing. See also \fBGEOMETRY MANAGEMENT\fR.
+.TP
+\fBwm maxsize \fIwindow\fR ?\fIwidth height\fR?
+.
+If \fIwidth\fR and \fIheight\fR are specified, they give
+the maximum permissible dimensions for \fIwindow\fR.
+For gridded windows the dimensions are specified in
+grid units; otherwise they are specified in pixel units.
+The window manager will restrict the window's dimensions to be
+less than or equal to \fIwidth\fR and \fIheight\fR.
+If \fIwidth\fR and \fIheight\fR are
+specified, then the command returns an empty string. Otherwise
+it returns a Tcl list with two elements, which are the
+maximum width and height currently in effect.
+The maximum size defaults to the size of the screen.
+See the sections on geometry management below for more information.
+.TP
+\fBwm minsize \fIwindow\fR ?\fIwidth height\fR?
+.
+If \fIwidth\fR and \fIheight\fR are specified, they give the
+minimum permissible dimensions for \fIwindow\fR.
+For gridded windows the dimensions are specified in
+grid units; otherwise they are specified in pixel units.
+The window manager will restrict the window's dimensions to be
+greater than or equal to \fIwidth\fR and \fIheight\fR.
+If \fIwidth\fR and \fIheight\fR are
+specified, then the command returns an empty string. Otherwise
+it returns a Tcl list with two elements, which are the
+minimum width and height currently in effect.
+The minimum size defaults to one pixel in each dimension.
+See the sections on geometry management below for more information.
+.TP
+\fBwm overrideredirect \fIwindow\fR ?\fIboolean\fR?
+.
+If \fIboolean\fR is specified, it must have a proper boolean form and
+the override-redirect flag for \fIwindow\fR is set to that value.
+If \fIboolean\fR is not specified then \fB1\fR or \fB0\fR is
+returned to indicate whether or not the override-redirect flag
+is currently set for \fIwindow\fR.
+Setting the override-redirect flag for a window causes
+it to be ignored by the window manager; among other things, this means
+that the window will not be reparented from the root window into a
+decorative frame and the user will not be able to manipulate the
+window using the normal window manager mechanisms.
+.RS
+.PP
+Note that the override-redirect flag is only guaranteed to be taken notice of
+when the window is first mapped or when mapped after the state is changed from
+withdrawn to normal. Some, but not all, platforms will take notice at
+additional times.
+.RE
+.TP
+\fBwm positionfrom \fIwindow\fR ?\fIwho\fR?
+.
+If \fIwho\fR is specified, it must be either \fBprogram\fR or
+\fBuser\fR, or an abbreviation of one of these two. It indicates
+whether \fIwindow\fR's current position was requested by the
+program or by the user. Many window managers ignore program-requested
+initial positions and ask the user to manually position the window; if
+\fBuser\fR is specified then the window manager should position the
+window at the given place without asking the user for assistance.
+If \fIwho\fR is specified as an empty string, then the current position
+source is cancelled.
+If \fIwho\fR is specified, then the command returns an empty string.
+Otherwise it returns \fBuser\fR or \fBprogram\fR to indicate the
+source of the window's current position, or an empty string if
+no source has been specified yet. Most window managers interpret
+.QW "no source"
+as equivalent to \fBprogram\fR.
+Tk will automatically set the position source to \fBuser\fR
+when a \fBwm geometry\fR command is invoked, unless the source has
+been set explicitly to \fBprogram\fR.
+.TP
+\fBwm protocol \fIwindow\fR ?\fIname\fR? ?\fIcommand\fR?
+.
+This command is used to manage window manager protocols such as
+\fBWM_DELETE_WINDOW\fR.
+\fIName\fR is the name of an atom corresponding to a window manager
+protocol, such as \fBWM_DELETE_WINDOW\fR or \fBWM_SAVE_YOURSELF\fR
+or \fBWM_TAKE_FOCUS\fR.
+If both \fIname\fR and \fIcommand\fR are specified, then \fIcommand\fR
+is associated with the protocol specified by \fIname\fR.
+\fIName\fR will be added to \fIwindow\fR's \fBWM_PROTOCOLS\fR
+property to tell the window manager that the application has a
+protocol handler for \fIname\fR, and \fIcommand\fR will
+be invoked in the future whenever the window manager sends a
+message to the client for that protocol.
+In this case the command returns an empty string.
+If \fIname\fR is specified but \fIcommand\fR is not, then the current
+command for \fIname\fR is returned, or an empty string if there
+is no handler defined for \fIname\fR.
+If \fIcommand\fR is specified as an empty string then the current
+handler for \fIname\fR is deleted and it is removed from the
+\fBWM_PROTOCOLS\fR property on \fIwindow\fR; an empty string is
+returned.
+Lastly, if neither \fIname\fR nor \fIcommand\fR is specified, the
+command returns a list of all the protocols for which handlers
+are currently defined for \fIwindow\fR.
+.RS
+.PP
+Tk always defines a protocol handler for \fBWM_DELETE_WINDOW\fR, even if
+you have not asked for one with \fBwm protocol\fR.
+If a \fBWM_DELETE_WINDOW\fR message arrives when you have not defined
+a handler, then Tk handles the message by destroying the window for
+which it was received.
+.RE
+.TP
+\fBwm resizable \fIwindow\fR ?\fIwidth height\fR?
+.
+This command controls whether or not the user may interactively
+resize a top-level window. If \fIwidth\fR and \fIheight\fR are
+specified, they are boolean values that determine whether the
+width and height of \fIwindow\fR may be modified by the user.
+In this case the command returns an empty string.
+If \fIwidth\fR and \fIheight\fR are omitted then the command
+returns a list with two 0/1 elements that indicate whether the
+width and height of \fIwindow\fR are currently resizable.
+By default, windows are resizable in both dimensions.
+If resizing is disabled, then the window's size will be the size
+from the most recent interactive resize or \fBwm geometry\fR
+command. If there has been no such operation then
+the window's natural size will be used.
+.TP
+\fBwm sizefrom \fIwindow\fR ?\fIwho\fR?
+.
+If \fIwho\fR is specified, it must be either \fBprogram\fR or
+\fBuser\fR, or an abbreviation of one of these two. It indicates
+whether \fIwindow\fR's current size was requested by the
+program or by the user. Some window managers ignore program-requested
+sizes and ask the user to manually size the window; if
+\fBuser\fR is specified then the window manager should give the
+window its specified size without asking the user for assistance.
+If \fIwho\fR is specified as an empty string, then the current size
+source is cancelled.
+If \fIwho\fR is specified, then the command returns an empty string.
+Otherwise it returns \fBuser\fR or \fBwindow\fR to indicate the
+source of the window's current size, or an empty string if
+no source has been specified yet. Most window managers interpret
+.QW "no source"
+as equivalent to \fBprogram\fR.
+.TP
+\fBwm stackorder \fIwindow\fR ?\fBisabove\fR|\fBisbelow \fIwindow\fR?
+.
+The \fBstackorder\fR command returns a list of toplevel windows
+in stacking order, from lowest to highest. When a single toplevel
+window is passed, the returned list recursively includes all of the
+window's children that are toplevels. Only those toplevels
+that are currently mapped to the screen are returned.
+The \fBstackorder\fR command can also be used to determine if one
+toplevel is positioned above or below a second toplevel.
+When two window arguments separated by either \fBisabove\fR or
+\fBisbelow\fR are passed, a boolean result indicates whether
+or not the first window is currently above or below the second
+window in the stacking order.
+.TP
+\fBwm state \fIwindow\fR ?newstate?
+.
+If \fInewstate\fR is specified, the window will be set to the new state,
+otherwise it returns the current state of \fIwindow\fR: either
+\fBnormal\fR, \fBiconic\fR, \fBwithdrawn\fR, \fBicon\fR, or (Windows and Mac
+OS X only) \fBzoomed\fR.
+The difference between \fBiconic\fR and \fBicon\fR is that
+\fBiconic\fR refers to a window that has been iconified (e.g., with the
+\fBwm iconify\fR command) while \fBicon\fR refers to a window whose only
+purpose is to serve as the icon for some other window (via the \fBwm
+iconwindow\fR command). The \fBicon\fR state cannot be set.
+.TP
+\fBwm title \fIwindow\fR ?\fIstring\fR?
+.
+If \fIstring\fR is specified, then it will be passed to the window
+manager for use as the title for \fIwindow\fR (the window manager
+should display this string in \fIwindow\fR's title bar). In this
+case the command returns an empty string. If \fIstring\fR is not
+specified then the command returns the current title for the
+\fIwindow\fR. The title for a window defaults to its name.
+.TP
+\fBwm transient \fIwindow\fR ?\fImaster\fR?
+.
+If \fImaster\fR is specified, then the window manager is informed that
+\fIwindow\fR is a transient window (e.g. pull-down menu) working on
+behalf of \fImaster\fR (where \fImaster\fR is the path name for a
+top-level window). If \fImaster\fR is specified as an empty string
+then \fIwindow\fR is marked as not being a transient window any more.
+Otherwise the command returns the path name of \fIwindow\fR's current
+master, or an empty string if \fIwindow\fR is not currently a
+transient window. A transient window will mirror state changes in the
+master and inherit the state of the master when initially mapped. The
+directed graph with an edge from each transient to its master must be
+acyclic. In particular, it is an error to attempt to make a window a
+transient of itself. The window manager may also decorate a transient
+window differently, removing some features normally present (e.g.,
+minimize and maximize buttons) though this is entirely at the
+discretion of the window manager.
+.TP
+\fBwm withdraw \fIwindow\fR
+.
+Arranges for \fIwindow\fR to be withdrawn from the screen. This
+causes the window to be unmapped and forgotten about by the window
+manager. If the window
+has never been mapped, then this command
+causes the window to be mapped in the withdrawn state. Not all
+window managers appear to know how to handle windows that are
+mapped in the withdrawn state.
+Note: it sometimes seems to be necessary to withdraw a
+window and then re-map it (e.g. with \fBwm deiconify\fR) to get some
+window managers to pay attention to changes in window attributes
+such as group.
+.SH "GEOMETRY MANAGEMENT"
+.PP
+By default a top-level window appears on the screen in its
+\fInatural size\fR, which is the one determined internally by its
+widgets and geometry managers.
+If the natural size of a top-level window changes, then the window's size
+changes to match.
+A top-level window can be given a size other than its natural size in two ways.
+First, the user can resize the window manually using the facilities
+of the window manager, such as resize handles.
+Second, the application can request a particular size for a
+top-level window using the \fBwm geometry\fR command.
+These two cases are handled identically by Tk; in either case,
+the requested size overrides the natural size.
+You can return the window to its natural by invoking \fBwm geometry\fR
+with an empty \fIgeometry\fR string.
+.PP
+Normally a top-level window can have any size from one pixel in each
+dimension up to the size of its screen.
+However, you can use the \fBwm minsize\fR and \fBwm maxsize\fR commands
+to limit the range of allowable sizes.
+The range set by \fBwm minsize\fR and \fBwm maxsize\fR applies to
+all forms of resizing, including the window's natural size as
+well as manual resizes and the \fBwm geometry\fR command.
+You can also use the command \fBwm resizable\fR to completely
+disable interactive resizing in one or both dimensions.
+.PP
+The \fBwm manage\fR and \fBwm forget\fR commands may be used to
+perform undocking and docking of windows. After a widget is managed
+by \fBwm manage\fR command, all other \fBwm\fR subcommands may be used
+with the widget. Only widgets created using the toplevel command may
+have an attached menu via the \fB\-menu\fR configure option. A toplevel
+widget may be used as a frame and managed with any of the other
+geometry managers after using the \fBwm forget\fR command. Any menu
+associated with a toplevel widget will be hidden when managed by
+another geometry managers. The menus will reappear once the window is
+managed by \fBwm\fR. All custom bindtags for widgets in a subtree
+that have their top-level widget changed via a \fBwm manage\fR or
+\fBwm forget\fR command, must be redone to adjust any top-level widget
+path in the bindtags. Bindtags that have not been customized do not
+have to be redone.
+.SH "GRIDDED GEOMETRY MANAGEMENT"
+.PP
+Gridded geometry management occurs when one of the widgets of an
+application supports a range of useful sizes.
+This occurs, for example, in a text editor where the scrollbars,
+menus, and other adornments are fixed in size but the edit widget
+can support any number of lines of text or characters per line.
+In this case, it is usually desirable to let the user specify the
+number of lines or characters-per-line, either with the
+\fBwm geometry\fR command or by interactively resizing the window.
+In the case of text, and in other interesting cases also, only
+discrete sizes of the window make sense, such as integral numbers
+of lines and characters-per-line; arbitrary pixel sizes are not useful.
+.PP
+Gridded geometry management provides support for this kind of
+application.
+Tk (and the window manager) assume that there is a grid of some
+sort within the application and that the application should be
+resized in terms of \fIgrid units\fR rather than pixels.
+Gridded geometry management is typically invoked by turning on
+the \fBsetGrid\fR option for a widget; it can also be invoked
+with the \fBwm grid\fR command or by calling \fBTk_SetGrid\fR.
+In each of these approaches the particular widget (or sometimes
+code in the application as a whole) specifies the relationship between
+integral grid sizes for the window and pixel sizes.
+To return to non-gridded geometry management, invoke
+\fBwm grid\fR with empty argument strings.
+.PP
+When gridded geometry management is enabled then all the dimensions specified
+in \fBwm minsize\fR, \fBwm maxsize\fR, and \fBwm geometry\fR commands
+are treated as grid units rather than pixel units.
+Interactive resizing is also carried out in even numbers of grid units
+rather than pixels.
+.SH BUGS
+.PP
+Most existing window managers appear to have bugs that affect the
+operation of the \fBwm\fR command. For example, some changes will not
+take effect if the window is already active: the window will have
+to be withdrawn and de-iconified in order to make the change happen.
+.SH EXAMPLES
+.PP
+A fixed-size window that says that it is fixed-size too:
+.CS
+toplevel .fixed
+\fBwm title\fR .fixed "Fixed-size Window"
+\fBwm resizable\fR .fixed 0 0
+.CE
+.PP
+A simple dialog-like window, centred on the screen:
+.CS
+# Create and arrange the dialog contents.
+toplevel .msg
+label .msg.l \-text "This is a very simple dialog demo."
+button .msg.ok \-text OK \-default active \-command {destroy .msg}
+pack .msg.ok \-side bottom \-fill x
+pack .msg.l \-expand 1 \-fill both
+
+# Now set the widget up as a centred dialog.
+
+# But first, we need the geometry managers to finish setting
+# up the interior of the dialog, for which we need to run the
+# event loop with the widget hidden completely...
+\fBwm withdraw\fR .msg
+update
+set x [expr {([winfo screenwidth .]\-[winfo width .msg])/2}]
+set y [expr {([winfo screenheight .]\-[winfo height .msg])/2}]
+\fBwm geometry\fR .msg +$x+$y
+\fBwm transient\fR .msg .
+\fBwm title\fR .msg "Dialog demo"
+\fBwm deiconify\fR .msg
+.CE
+.SH "SEE ALSO"
+toplevel(n), winfo(n)
+.SH KEYWORDS
+aspect ratio, deiconify, focus model, geometry, grid, group, icon, iconify, increments, position, size, title, top-level window, units, window manager
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/tk8.6/generic/README b/tk8.6/generic/README
new file mode 100644
index 0000000..6ac6bb4
--- /dev/null
+++ b/tk8.6/generic/README
@@ -0,0 +1,3 @@
+This directory contains Tk source files that work on all the platforms
+where Tk runs (e.g. UNIX, PCs, and MacOSX). Platform-specific
+sources are in the directories ../unix, ../win, and ../macosx.
diff --git a/tk8.6/generic/default.h b/tk8.6/generic/default.h
new file mode 100644
index 0000000..e6ef132
--- /dev/null
+++ b/tk8.6/generic/default.h
@@ -0,0 +1,27 @@
+/*
+ * default.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 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef _DEFAULT
+#define _DEFAULT
+
+#ifdef _WIN32
+# include "tkWinDefault.h"
+#else
+# if defined(MAC_OSX_TK)
+# include "tkMacOSXDefault.h"
+# else
+# include "tkUnixDefault.h"
+# endif
+#endif
+
+#endif /* _DEFAULT */
diff --git a/tk8.6/generic/ks_names.h b/tk8.6/generic/ks_names.h
new file mode 100644
index 0000000..9f49130
--- /dev/null
+++ b/tk8.6/generic/ks_names.h
@@ -0,0 +1,939 @@
+/*
+ * This file should be maintained in sync with xlib/X11/keysymdefs.h
+ *
+ * Note that this should be done manually only, because in some cases
+ * keysymdefs.h defines the same integer for multiple keysyms, e.g.:
+ *
+ * #define XK_Greek_LAMDA 0x7cb
+ * #define XK_Greek_LAMBDA 0x7cb
+ *
+ * #define XK_Cyrillic_DZHE 0x6bf
+ * #define XK_Serbian_DZE 0x6bf (deprecated)
+ *
+ */
+{ "BackSpace", 0xFF08 },
+{ "Tab", 0xFF09 },
+{ "Linefeed", 0xFF0A },
+{ "Clear", 0xFF0B },
+{ "Return", 0xFF0D },
+{ "Pause", 0xFF13 },
+{ "Scroll_Lock", 0xFF14 },
+{ "Sys_Req", 0xFF15 },
+{ "Escape", 0xFF1B },
+{ "Delete", 0xFFFF },
+{ "Multi_key", 0xFF20 },
+{ "Kanji", 0xFF21 },
+{ "Home", 0xFF50 },
+{ "Left", 0xFF51 },
+{ "Up", 0xFF52 },
+{ "Right", 0xFF53 },
+{ "Down", 0xFF54 },
+{ "Prior", 0xFF55 },
+{ "Next", 0xFF56 },
+{ "End", 0xFF57 },
+{ "Begin", 0xFF58 },
+{ "Win_L", 0xFF5B },
+{ "Win_R", 0xFF5C },
+{ "App", 0xFF5D },
+{ "Select", 0xFF60 },
+{ "Print", 0xFF61 },
+{ "Execute", 0xFF62 },
+{ "Insert", 0xFF63 },
+{ "Undo", 0xFF65 },
+{ "Redo", 0xFF66 },
+{ "Menu", 0xFF67 },
+{ "Find", 0xFF68 },
+{ "Cancel", 0xFF69 },
+{ "Help", 0xFF6A },
+{ "Break", 0xFF6B },
+{ "Mode_switch", 0xFF7E },
+{ "script_switch", 0xFF7E },
+{ "Num_Lock", 0xFF7F },
+{ "KP_Space", 0xFF80 },
+{ "KP_Tab", 0xFF89 },
+{ "KP_Enter", 0xFF8D },
+{ "KP_F1", 0xFF91 },
+{ "KP_F2", 0xFF92 },
+{ "KP_F3", 0xFF93 },
+{ "KP_F4", 0xFF94 },
+{ "KP_Equal", 0xFFBD },
+{ "KP_Multiply", 0xFFAA },
+{ "KP_Add", 0xFFAB },
+{ "KP_Separator", 0xFFAC },
+{ "KP_Subtract", 0xFFAD },
+{ "KP_Decimal", 0xFFAE },
+{ "KP_Divide", 0xFFAF },
+{ "KP_0", 0xFFB0 },
+{ "KP_1", 0xFFB1 },
+{ "KP_2", 0xFFB2 },
+{ "KP_3", 0xFFB3 },
+{ "KP_4", 0xFFB4 },
+{ "KP_5", 0xFFB5 },
+{ "KP_6", 0xFFB6 },
+{ "KP_7", 0xFFB7 },
+{ "KP_8", 0xFFB8 },
+{ "KP_9", 0xFFB9 },
+{ "F1", 0xFFBE },
+{ "F2", 0xFFBF },
+{ "F3", 0xFFC0 },
+{ "F4", 0xFFC1 },
+{ "F5", 0xFFC2 },
+{ "F6", 0xFFC3 },
+{ "F7", 0xFFC4 },
+{ "F8", 0xFFC5 },
+{ "F9", 0xFFC6 },
+{ "F10", 0xFFC7 },
+{ "F11", 0xFFC8 },
+{ "L1", 0xFFC8 },
+{ "F12", 0xFFC9 },
+{ "L2", 0xFFC9 },
+{ "F13", 0xFFCA },
+{ "L3", 0xFFCA },
+{ "F14", 0xFFCB },
+{ "L4", 0xFFCB },
+{ "F15", 0xFFCC },
+{ "L5", 0xFFCC },
+{ "F16", 0xFFCD },
+{ "L6", 0xFFCD },
+{ "F17", 0xFFCE },
+{ "L7", 0xFFCE },
+{ "F18", 0xFFCF },
+{ "L8", 0xFFCF },
+{ "F19", 0xFFD0 },
+{ "L9", 0xFFD0 },
+{ "F20", 0xFFD1 },
+{ "L10", 0xFFD1 },
+{ "F21", 0xFFD2 },
+{ "R1", 0xFFD2 },
+{ "F22", 0xFFD3 },
+{ "R2", 0xFFD3 },
+{ "F23", 0xFFD4 },
+{ "R3", 0xFFD4 },
+{ "F24", 0xFFD5 },
+{ "R4", 0xFFD5 },
+{ "F25", 0xFFD6 },
+{ "R5", 0xFFD6 },
+{ "F26", 0xFFD7 },
+{ "R6", 0xFFD7 },
+{ "F27", 0xFFD8 },
+{ "R7", 0xFFD8 },
+{ "F28", 0xFFD9 },
+{ "R8", 0xFFD9 },
+{ "F29", 0xFFDA },
+{ "R9", 0xFFDA },
+{ "F30", 0xFFDB },
+{ "R10", 0xFFDB },
+{ "F31", 0xFFDC },
+{ "R11", 0xFFDC },
+{ "F32", 0xFFDD },
+{ "R12", 0xFFDD },
+{ "F33", 0xFFDE },
+{ "R13", 0xFFDE },
+{ "F34", 0xFFDF },
+{ "R14", 0xFFDF },
+{ "F35", 0xFFE0 },
+{ "R15", 0xFFE0 },
+{ "Shift_L", 0xFFE1 },
+{ "Shift_R", 0xFFE2 },
+{ "Control_L", 0xFFE3 },
+{ "Control_R", 0xFFE4 },
+{ "Caps_Lock", 0xFFE5 },
+{ "Shift_Lock", 0xFFE6 },
+{ "Meta_L", 0xFFE7 },
+{ "Meta_R", 0xFFE8 },
+{ "Alt_L", 0xFFE9 },
+{ "Alt_R", 0xFFEA },
+{ "Super_L", 0xFFEB },
+{ "Super_R", 0xFFEC },
+{ "Hyper_L", 0xFFED },
+{ "Hyper_R", 0xFFEE },
+{ "space", 0x020 },
+{ "exclam", 0x021 },
+{ "quotedbl", 0x022 },
+{ "numbersign", 0x023 },
+{ "dollar", 0x024 },
+{ "percent", 0x025 },
+{ "ampersand", 0x026 },
+{ "quoteright", 0x027 },
+{ "parenleft", 0x028 },
+{ "parenright", 0x029 },
+{ "asterisk", 0x02a },
+{ "plus", 0x02b },
+{ "comma", 0x02c },
+{ "minus", 0x02d },
+{ "period", 0x02e },
+{ "slash", 0x02f },
+{ "0", 0x030 },
+{ "1", 0x031 },
+{ "2", 0x032 },
+{ "3", 0x033 },
+{ "4", 0x034 },
+{ "5", 0x035 },
+{ "6", 0x036 },
+{ "7", 0x037 },
+{ "8", 0x038 },
+{ "9", 0x039 },
+{ "colon", 0x03a },
+{ "semicolon", 0x03b },
+{ "less", 0x03c },
+{ "equal", 0x03d },
+{ "greater", 0x03e },
+{ "question", 0x03f },
+{ "at", 0x040 },
+{ "A", 0x041 },
+{ "B", 0x042 },
+{ "C", 0x043 },
+{ "D", 0x044 },
+{ "E", 0x045 },
+{ "F", 0x046 },
+{ "G", 0x047 },
+{ "H", 0x048 },
+{ "I", 0x049 },
+{ "J", 0x04a },
+{ "K", 0x04b },
+{ "L", 0x04c },
+{ "M", 0x04d },
+{ "N", 0x04e },
+{ "O", 0x04f },
+{ "P", 0x050 },
+{ "Q", 0x051 },
+{ "R", 0x052 },
+{ "S", 0x053 },
+{ "T", 0x054 },
+{ "U", 0x055 },
+{ "V", 0x056 },
+{ "W", 0x057 },
+{ "X", 0x058 },
+{ "Y", 0x059 },
+{ "Z", 0x05a },
+{ "bracketleft", 0x05b },
+{ "backslash", 0x05c },
+{ "bracketright", 0x05d },
+{ "asciicircum", 0x05e },
+{ "underscore", 0x05f },
+{ "quoteleft", 0x060 },
+{ "a", 0x061 },
+{ "b", 0x062 },
+{ "c", 0x063 },
+{ "d", 0x064 },
+{ "e", 0x065 },
+{ "f", 0x066 },
+{ "g", 0x067 },
+{ "h", 0x068 },
+{ "i", 0x069 },
+{ "j", 0x06a },
+{ "k", 0x06b },
+{ "l", 0x06c },
+{ "m", 0x06d },
+{ "n", 0x06e },
+{ "o", 0x06f },
+{ "p", 0x070 },
+{ "q", 0x071 },
+{ "r", 0x072 },
+{ "s", 0x073 },
+{ "t", 0x074 },
+{ "u", 0x075 },
+{ "v", 0x076 },
+{ "w", 0x077 },
+{ "x", 0x078 },
+{ "y", 0x079 },
+{ "z", 0x07a },
+{ "braceleft", 0x07b },
+{ "bar", 0x07c },
+{ "braceright", 0x07d },
+{ "asciitilde", 0x07e },
+{ "nobreakspace", 0x0a0 },
+{ "exclamdown", 0x0a1 },
+{ "cent", 0x0a2 },
+{ "sterling", 0x0a3 },
+{ "currency", 0x0a4 },
+{ "yen", 0x0a5 },
+{ "brokenbar", 0x0a6 },
+{ "section", 0x0a7 },
+{ "diaeresis", 0x0a8 },
+{ "copyright", 0x0a9 },
+{ "ordfeminine", 0x0aa },
+{ "guillemotleft", 0x0ab },
+{ "notsign", 0x0ac },
+{ "hyphen", 0x0ad },
+{ "registered", 0x0ae },
+{ "macron", 0x0af },
+{ "degree", 0x0b0 },
+{ "plusminus", 0x0b1 },
+{ "twosuperior", 0x0b2 },
+{ "threesuperior", 0x0b3 },
+{ "acute", 0x0b4 },
+{ "mu", 0x0b5 },
+{ "paragraph", 0x0b6 },
+{ "periodcentered", 0x0b7 },
+{ "cedilla", 0x0b8 },
+{ "onesuperior", 0x0b9 },
+{ "masculine", 0x0ba },
+{ "guillemotright", 0x0bb },
+{ "onequarter", 0x0bc },
+{ "onehalf", 0x0bd },
+{ "threequarters", 0x0be },
+{ "questiondown", 0x0bf },
+{ "Agrave", 0x0c0 },
+{ "Aacute", 0x0c1 },
+{ "Acircumflex", 0x0c2 },
+{ "Atilde", 0x0c3 },
+{ "Adiaeresis", 0x0c4 },
+{ "Aring", 0x0c5 },
+{ "AE", 0x0c6 },
+{ "Ccedilla", 0x0c7 },
+{ "Egrave", 0x0c8 },
+{ "Eacute", 0x0c9 },
+{ "Ecircumflex", 0x0ca },
+{ "Ediaeresis", 0x0cb },
+{ "Igrave", 0x0cc },
+{ "Iacute", 0x0cd },
+{ "Icircumflex", 0x0ce },
+{ "Idiaeresis", 0x0cf },
+{ "Eth", 0x0d0 },
+{ "Ntilde", 0x0d1 },
+{ "Ograve", 0x0d2 },
+{ "Oacute", 0x0d3 },
+{ "Ocircumflex", 0x0d4 },
+{ "Otilde", 0x0d5 },
+{ "Odiaeresis", 0x0d6 },
+{ "multiply", 0x0d7 },
+{ "Ooblique", 0x0d8 },
+{ "Ugrave", 0x0d9 },
+{ "Uacute", 0x0da },
+{ "Ucircumflex", 0x0db },
+{ "Udiaeresis", 0x0dc },
+{ "Yacute", 0x0dd },
+{ "Thorn", 0x0de },
+{ "ssharp", 0x0df },
+{ "agrave", 0x0e0 },
+{ "aacute", 0x0e1 },
+{ "acircumflex", 0x0e2 },
+{ "atilde", 0x0e3 },
+{ "adiaeresis", 0x0e4 },
+{ "aring", 0x0e5 },
+{ "ae", 0x0e6 },
+{ "ccedilla", 0x0e7 },
+{ "egrave", 0x0e8 },
+{ "eacute", 0x0e9 },
+{ "ecircumflex", 0x0ea },
+{ "ediaeresis", 0x0eb },
+{ "igrave", 0x0ec },
+{ "iacute", 0x0ed },
+{ "icircumflex", 0x0ee },
+{ "idiaeresis", 0x0ef },
+{ "eth", 0x0f0 },
+{ "ntilde", 0x0f1 },
+{ "ograve", 0x0f2 },
+{ "oacute", 0x0f3 },
+{ "ocircumflex", 0x0f4 },
+{ "otilde", 0x0f5 },
+{ "odiaeresis", 0x0f6 },
+{ "division", 0x0f7 },
+{ "oslash", 0x0f8 },
+{ "ugrave", 0x0f9 },
+{ "uacute", 0x0fa },
+{ "ucircumflex", 0x0fb },
+{ "udiaeresis", 0x0fc },
+{ "yacute", 0x0fd },
+{ "thorn", 0x0fe },
+{ "ydiaeresis", 0x0ff },
+{ "Aogonek", 0x1a1 },
+{ "breve", 0x1a2 },
+{ "Lstroke", 0x1a3 },
+{ "Lcaron", 0x1a5 },
+{ "Sacute", 0x1a6 },
+{ "Scaron", 0x1a9 },
+{ "Scedilla", 0x1aa },
+{ "Tcaron", 0x1ab },
+{ "Zacute", 0x1ac },
+{ "Zcaron", 0x1ae },
+{ "Zabovedot", 0x1af },
+{ "aogonek", 0x1b1 },
+{ "ogonek", 0x1b2 },
+{ "lstroke", 0x1b3 },
+{ "lcaron", 0x1b5 },
+{ "sacute", 0x1b6 },
+{ "caron", 0x1b7 },
+{ "scaron", 0x1b9 },
+{ "scedilla", 0x1ba },
+{ "tcaron", 0x1bb },
+{ "zacute", 0x1bc },
+{ "doubleacute", 0x1bd },
+{ "zcaron", 0x1be },
+{ "zabovedot", 0x1bf },
+{ "Racute", 0x1c0 },
+{ "Abreve", 0x1c3 },
+{ "Cacute", 0x1c6 },
+{ "Ccaron", 0x1c8 },
+{ "Eogonek", 0x1ca },
+{ "Ecaron", 0x1cc },
+{ "Dcaron", 0x1cf },
+{ "Nacute", 0x1d1 },
+{ "Ncaron", 0x1d2 },
+{ "Odoubleacute", 0x1d5 },
+{ "Rcaron", 0x1d8 },
+{ "Uring", 0x1d9 },
+{ "Udoubleacute", 0x1db },
+{ "Tcedilla", 0x1de },
+{ "racute", 0x1e0 },
+{ "abreve", 0x1e3 },
+{ "cacute", 0x1e6 },
+{ "ccaron", 0x1e8 },
+{ "eogonek", 0x1ea },
+{ "ecaron", 0x1ec },
+{ "dcaron", 0x1ef },
+{ "nacute", 0x1f1 },
+{ "ncaron", 0x1f2 },
+{ "odoubleacute", 0x1f5 },
+{ "udoubleacute", 0x1fb },
+{ "rcaron", 0x1f8 },
+{ "uring", 0x1f9 },
+{ "tcedilla", 0x1fe },
+{ "abovedot", 0x1ff },
+{ "Hstroke", 0x2a1 },
+{ "Hcircumflex", 0x2a6 },
+{ "Iabovedot", 0x2a9 },
+{ "Gbreve", 0x2ab },
+{ "Jcircumflex", 0x2ac },
+{ "hstroke", 0x2b1 },
+{ "hcircumflex", 0x2b6 },
+{ "idotless", 0x2b9 },
+{ "gbreve", 0x2bb },
+{ "jcircumflex", 0x2bc },
+{ "Cabovedot", 0x2c5 },
+{ "Ccircumflex", 0x2c6 },
+{ "Gabovedot", 0x2d5 },
+{ "Gcircumflex", 0x2d8 },
+{ "Ubreve", 0x2dd },
+{ "Scircumflex", 0x2de },
+{ "cabovedot", 0x2e5 },
+{ "ccircumflex", 0x2e6 },
+{ "gabovedot", 0x2f5 },
+{ "gcircumflex", 0x2f8 },
+{ "ubreve", 0x2fd },
+{ "scircumflex", 0x2fe },
+{ "kappa", 0x3a2 },
+{ "Rcedilla", 0x3a3 },
+{ "Itilde", 0x3a5 },
+{ "Lcedilla", 0x3a6 },
+{ "Emacron", 0x3aa },
+{ "Gcedilla", 0x3ab },
+{ "Tslash", 0x3ac },
+{ "rcedilla", 0x3b3 },
+{ "itilde", 0x3b5 },
+{ "lcedilla", 0x3b6 },
+{ "emacron", 0x3ba },
+{ "gacute", 0x3bb },
+{ "tslash", 0x3bc },
+{ "ENG", 0x3bd },
+{ "eng", 0x3bf },
+{ "Amacron", 0x3c0 },
+{ "Iogonek", 0x3c7 },
+{ "Eabovedot", 0x3cc },
+{ "Imacron", 0x3cf },
+{ "Ncedilla", 0x3d1 },
+{ "Omacron", 0x3d2 },
+{ "Kcedilla", 0x3d3 },
+{ "Uogonek", 0x3d9 },
+{ "Utilde", 0x3dd },
+{ "Umacron", 0x3de },
+{ "amacron", 0x3e0 },
+{ "iogonek", 0x3e7 },
+{ "eabovedot", 0x3ec },
+{ "imacron", 0x3ef },
+{ "ncedilla", 0x3f1 },
+{ "omacron", 0x3f2 },
+{ "kcedilla", 0x3f3 },
+{ "uogonek", 0x3f9 },
+{ "utilde", 0x3fd },
+{ "umacron", 0x3fe },
+{ "overline", 0x47e },
+{ "kana_fullstop", 0x4a1 },
+{ "kana_openingbracket", 0x4a2 },
+{ "kana_closingbracket", 0x4a3 },
+{ "kana_comma", 0x4a4 },
+{ "kana_middledot", 0x4a5 },
+{ "kana_WO", 0x4a6 },
+{ "kana_a", 0x4a7 },
+{ "kana_i", 0x4a8 },
+{ "kana_u", 0x4a9 },
+{ "kana_e", 0x4aa },
+{ "kana_o", 0x4ab },
+{ "kana_ya", 0x4ac },
+{ "kana_yu", 0x4ad },
+{ "kana_yo", 0x4ae },
+{ "kana_tu", 0x4af },
+{ "prolongedsound", 0x4b0 },
+{ "kana_A", 0x4b1 },
+{ "kana_I", 0x4b2 },
+{ "kana_U", 0x4b3 },
+{ "kana_E", 0x4b4 },
+{ "kana_O", 0x4b5 },
+{ "kana_KA", 0x4b6 },
+{ "kana_KI", 0x4b7 },
+{ "kana_KU", 0x4b8 },
+{ "kana_KE", 0x4b9 },
+{ "kana_KO", 0x4ba },
+{ "kana_SA", 0x4bb },
+{ "kana_SHI", 0x4bc },
+{ "kana_SU", 0x4bd },
+{ "kana_SE", 0x4be },
+{ "kana_SO", 0x4bf },
+{ "kana_TA", 0x4c0 },
+{ "kana_TI", 0x4c1 },
+{ "kana_TU", 0x4c2 },
+{ "kana_TE", 0x4c3 },
+{ "kana_TO", 0x4c4 },
+{ "kana_NA", 0x4c5 },
+{ "kana_NI", 0x4c6 },
+{ "kana_NU", 0x4c7 },
+{ "kana_NE", 0x4c8 },
+{ "kana_NO", 0x4c9 },
+{ "kana_HA", 0x4ca },
+{ "kana_HI", 0x4cb },
+{ "kana_HU", 0x4cc },
+{ "kana_HE", 0x4cd },
+{ "kana_HO", 0x4ce },
+{ "kana_MA", 0x4cf },
+{ "kana_MI", 0x4d0 },
+{ "kana_MU", 0x4d1 },
+{ "kana_ME", 0x4d2 },
+{ "kana_MO", 0x4d3 },
+{ "kana_YA", 0x4d4 },
+{ "kana_YU", 0x4d5 },
+{ "kana_YO", 0x4d6 },
+{ "kana_RA", 0x4d7 },
+{ "kana_RI", 0x4d8 },
+{ "kana_RU", 0x4d9 },
+{ "kana_RE", 0x4da },
+{ "kana_RO", 0x4db },
+{ "kana_WA", 0x4dc },
+{ "kana_N", 0x4dd },
+{ "voicedsound", 0x4de },
+{ "semivoicedsound", 0x4df },
+{ "kana_switch", 0xFF7E },
+{ "Arabic_comma", 0x5ac },
+{ "Arabic_semicolon", 0x5bb },
+{ "Arabic_question_mark", 0x5bf },
+{ "Arabic_hamza", 0x5c1 },
+{ "Arabic_maddaonalef", 0x5c2 },
+{ "Arabic_hamzaonalef", 0x5c3 },
+{ "Arabic_hamzaonwaw", 0x5c4 },
+{ "Arabic_hamzaunderalef", 0x5c5 },
+{ "Arabic_hamzaonyeh", 0x5c6 },
+{ "Arabic_alef", 0x5c7 },
+{ "Arabic_beh", 0x5c8 },
+{ "Arabic_tehmarbuta", 0x5c9 },
+{ "Arabic_teh", 0x5ca },
+{ "Arabic_theh", 0x5cb },
+{ "Arabic_jeem", 0x5cc },
+{ "Arabic_hah", 0x5cd },
+{ "Arabic_khah", 0x5ce },
+{ "Arabic_dal", 0x5cf },
+{ "Arabic_thal", 0x5d0 },
+{ "Arabic_ra", 0x5d1 },
+{ "Arabic_zain", 0x5d2 },
+{ "Arabic_seen", 0x5d3 },
+{ "Arabic_sheen", 0x5d4 },
+{ "Arabic_sad", 0x5d5 },
+{ "Arabic_dad", 0x5d6 },
+{ "Arabic_tah", 0x5d7 },
+{ "Arabic_zah", 0x5d8 },
+{ "Arabic_ain", 0x5d9 },
+{ "Arabic_ghain", 0x5da },
+{ "Arabic_tatweel", 0x5e0 },
+{ "Arabic_feh", 0x5e1 },
+{ "Arabic_qaf", 0x5e2 },
+{ "Arabic_kaf", 0x5e3 },
+{ "Arabic_lam", 0x5e4 },
+{ "Arabic_meem", 0x5e5 },
+{ "Arabic_noon", 0x5e6 },
+{ "Arabic_heh", 0x5e7 },
+{ "Arabic_waw", 0x5e8 },
+{ "Arabic_alefmaksura", 0x5e9 },
+{ "Arabic_yeh", 0x5ea },
+{ "Arabic_fathatan", 0x5eb },
+{ "Arabic_dammatan", 0x5ec },
+{ "Arabic_kasratan", 0x5ed },
+{ "Arabic_fatha", 0x5ee },
+{ "Arabic_damma", 0x5ef },
+{ "Arabic_kasra", 0x5f0 },
+{ "Arabic_shadda", 0x5f1 },
+{ "Arabic_sukun", 0x5f2 },
+{ "Arabic_switch", 0xFF7E },
+{ "Serbian_dje", 0x6a1 },
+{ "Macedonia_gje", 0x6a2 },
+{ "Cyrillic_io", 0x6a3 },
+{ "Ukranian_je", 0x6a4 },
+{ "Macedonia_dse", 0x6a5 },
+{ "Ukranian_i", 0x6a6 },
+{ "Ukranian_yi", 0x6a7 },
+{ "Serbian_je", 0x6a8 },
+{ "Serbian_lje", 0x6a9 },
+{ "Serbian_nje", 0x6aa },
+{ "Serbian_tshe", 0x6ab },
+{ "Macedonia_kje", 0x6ac },
+{ "Byelorussian_shortu", 0x6ae },
+{ "Serbian_dze", 0x6af },
+{ "numerosign", 0x6b0 },
+{ "Serbian_DJE", 0x6b1 },
+{ "Macedonia_GJE", 0x6b2 },
+{ "Cyrillic_IO", 0x6b3 },
+{ "Ukranian_JE", 0x6b4 },
+{ "Macedonia_DSE", 0x6b5 },
+{ "Ukranian_I", 0x6b6 },
+{ "Ukranian_YI", 0x6b7 },
+{ "Serbian_JE", 0x6b8 },
+{ "Serbian_LJE", 0x6b9 },
+{ "Serbian_NJE", 0x6ba },
+{ "Serbian_TSHE", 0x6bb },
+{ "Macedonia_KJE", 0x6bc },
+{ "Byelorussian_SHORTU", 0x6be },
+{ "Serbian_DZE", 0x6bf },
+{ "Cyrillic_yu", 0x6c0 },
+{ "Cyrillic_a", 0x6c1 },
+{ "Cyrillic_be", 0x6c2 },
+{ "Cyrillic_tse", 0x6c3 },
+{ "Cyrillic_de", 0x6c4 },
+{ "Cyrillic_ie", 0x6c5 },
+{ "Cyrillic_ef", 0x6c6 },
+{ "Cyrillic_ghe", 0x6c7 },
+{ "Cyrillic_ha", 0x6c8 },
+{ "Cyrillic_i", 0x6c9 },
+{ "Cyrillic_shorti", 0x6ca },
+{ "Cyrillic_ka", 0x6cb },
+{ "Cyrillic_el", 0x6cc },
+{ "Cyrillic_em", 0x6cd },
+{ "Cyrillic_en", 0x6ce },
+{ "Cyrillic_o", 0x6cf },
+{ "Cyrillic_pe", 0x6d0 },
+{ "Cyrillic_ya", 0x6d1 },
+{ "Cyrillic_er", 0x6d2 },
+{ "Cyrillic_es", 0x6d3 },
+{ "Cyrillic_te", 0x6d4 },
+{ "Cyrillic_u", 0x6d5 },
+{ "Cyrillic_zhe", 0x6d6 },
+{ "Cyrillic_ve", 0x6d7 },
+{ "Cyrillic_softsign", 0x6d8 },
+{ "Cyrillic_yeru", 0x6d9 },
+{ "Cyrillic_ze", 0x6da },
+{ "Cyrillic_sha", 0x6db },
+{ "Cyrillic_e", 0x6dc },
+{ "Cyrillic_shcha", 0x6dd },
+{ "Cyrillic_che", 0x6de },
+{ "Cyrillic_hardsign", 0x6df },
+{ "Cyrillic_YU", 0x6e0 },
+{ "Cyrillic_A", 0x6e1 },
+{ "Cyrillic_BE", 0x6e2 },
+{ "Cyrillic_TSE", 0x6e3 },
+{ "Cyrillic_DE", 0x6e4 },
+{ "Cyrillic_IE", 0x6e5 },
+{ "Cyrillic_EF", 0x6e6 },
+{ "Cyrillic_GHE", 0x6e7 },
+{ "Cyrillic_HA", 0x6e8 },
+{ "Cyrillic_I", 0x6e9 },
+{ "Cyrillic_SHORTI", 0x6ea },
+{ "Cyrillic_KA", 0x6eb },
+{ "Cyrillic_EL", 0x6ec },
+{ "Cyrillic_EM", 0x6ed },
+{ "Cyrillic_EN", 0x6ee },
+{ "Cyrillic_O", 0x6ef },
+{ "Cyrillic_PE", 0x6f0 },
+{ "Cyrillic_YA", 0x6f1 },
+{ "Cyrillic_ER", 0x6f2 },
+{ "Cyrillic_ES", 0x6f3 },
+{ "Cyrillic_TE", 0x6f4 },
+{ "Cyrillic_U", 0x6f5 },
+{ "Cyrillic_ZHE", 0x6f6 },
+{ "Cyrillic_VE", 0x6f7 },
+{ "Cyrillic_SOFTSIGN", 0x6f8 },
+{ "Cyrillic_YERU", 0x6f9 },
+{ "Cyrillic_ZE", 0x6fa },
+{ "Cyrillic_SHA", 0x6fb },
+{ "Cyrillic_E", 0x6fc },
+{ "Cyrillic_SHCHA", 0x6fd },
+{ "Cyrillic_CHE", 0x6fe },
+{ "Cyrillic_HARDSIGN", 0x6ff },
+{ "Greek_ALPHAaccent", 0x7a1 },
+{ "Greek_EPSILONaccent", 0x7a2 },
+{ "Greek_ETAaccent", 0x7a3 },
+{ "Greek_IOTAaccent", 0x7a4 },
+{ "Greek_IOTAdiaeresis", 0x7a5 },
+{ "Greek_IOTAaccentdiaeresis", 0x7a6 },
+{ "Greek_OMICRONaccent", 0x7a7 },
+{ "Greek_UPSILONaccent", 0x7a8 },
+{ "Greek_UPSILONdieresis", 0x7a9 },
+{ "Greek_UPSILONaccentdieresis", 0x7aa },
+{ "Greek_OMEGAaccent", 0x7ab },
+{ "Greek_alphaaccent", 0x7b1 },
+{ "Greek_epsilonaccent", 0x7b2 },
+{ "Greek_etaaccent", 0x7b3 },
+{ "Greek_iotaaccent", 0x7b4 },
+{ "Greek_iotadieresis", 0x7b5 },
+{ "Greek_iotaaccentdieresis", 0x7b6 },
+{ "Greek_omicronaccent", 0x7b7 },
+{ "Greek_upsilonaccent", 0x7b8 },
+{ "Greek_upsilondieresis", 0x7b9 },
+{ "Greek_upsilonaccentdieresis", 0x7ba },
+{ "Greek_omegaaccent", 0x7bb },
+{ "Greek_ALPHA", 0x7c1 },
+{ "Greek_BETA", 0x7c2 },
+{ "Greek_GAMMA", 0x7c3 },
+{ "Greek_DELTA", 0x7c4 },
+{ "Greek_EPSILON", 0x7c5 },
+{ "Greek_ZETA", 0x7c6 },
+{ "Greek_ETA", 0x7c7 },
+{ "Greek_THETA", 0x7c8 },
+{ "Greek_IOTA", 0x7c9 },
+{ "Greek_KAPPA", 0x7ca },
+{ "Greek_LAMBDA", 0x7cb },
+{ "Greek_MU", 0x7cc },
+{ "Greek_NU", 0x7cd },
+{ "Greek_XI", 0x7ce },
+{ "Greek_OMICRON", 0x7cf },
+{ "Greek_PI", 0x7d0 },
+{ "Greek_RHO", 0x7d1 },
+{ "Greek_SIGMA", 0x7d2 },
+{ "Greek_TAU", 0x7d4 },
+{ "Greek_UPSILON", 0x7d5 },
+{ "Greek_PHI", 0x7d6 },
+{ "Greek_CHI", 0x7d7 },
+{ "Greek_PSI", 0x7d8 },
+{ "Greek_OMEGA", 0x7d9 },
+{ "Greek_alpha", 0x7e1 },
+{ "Greek_beta", 0x7e2 },
+{ "Greek_gamma", 0x7e3 },
+{ "Greek_delta", 0x7e4 },
+{ "Greek_epsilon", 0x7e5 },
+{ "Greek_zeta", 0x7e6 },
+{ "Greek_eta", 0x7e7 },
+{ "Greek_theta", 0x7e8 },
+{ "Greek_iota", 0x7e9 },
+{ "Greek_kappa", 0x7ea },
+{ "Greek_lambda", 0x7eb },
+{ "Greek_mu", 0x7ec },
+{ "Greek_nu", 0x7ed },
+{ "Greek_xi", 0x7ee },
+{ "Greek_omicron", 0x7ef },
+{ "Greek_pi", 0x7f0 },
+{ "Greek_rho", 0x7f1 },
+{ "Greek_sigma", 0x7f2 },
+{ "Greek_finalsmallsigma", 0x7f3 },
+{ "Greek_tau", 0x7f4 },
+{ "Greek_upsilon", 0x7f5 },
+{ "Greek_phi", 0x7f6 },
+{ "Greek_chi", 0x7f7 },
+{ "Greek_psi", 0x7f8 },
+{ "Greek_omega", 0x7f9 },
+{ "Greek_switch", 0xFF7E },
+{ "leftradical", 0x8a1 },
+{ "topleftradical", 0x8a2 },
+{ "horizconnector", 0x8a3 },
+{ "topintegral", 0x8a4 },
+{ "botintegral", 0x8a5 },
+{ "vertconnector", 0x8a6 },
+{ "topleftsqbracket", 0x8a7 },
+{ "botleftsqbracket", 0x8a8 },
+{ "toprightsqbracket", 0x8a9 },
+{ "botrightsqbracket", 0x8aa },
+{ "topleftparens", 0x8ab },
+{ "botleftparens", 0x8ac },
+{ "toprightparens", 0x8ad },
+{ "botrightparens", 0x8ae },
+{ "leftmiddlecurlybrace", 0x8af },
+{ "rightmiddlecurlybrace", 0x8b0 },
+{ "topleftsummation", 0x8b1 },
+{ "botleftsummation", 0x8b2 },
+{ "topvertsummationconnector", 0x8b3 },
+{ "botvertsummationconnector", 0x8b4 },
+{ "toprightsummation", 0x8b5 },
+{ "botrightsummation", 0x8b6 },
+{ "rightmiddlesummation", 0x8b7 },
+{ "lessthanequal", 0x8bc },
+{ "notequal", 0x8bd },
+{ "greaterthanequal", 0x8be },
+{ "integral", 0x8bf },
+{ "therefore", 0x8c0 },
+{ "variation", 0x8c1 },
+{ "infinity", 0x8c2 },
+{ "nabla", 0x8c5 },
+{ "approximate", 0x8c8 },
+{ "similarequal", 0x8c9 },
+{ "ifonlyif", 0x8cd },
+{ "implies", 0x8ce },
+{ "identical", 0x8cf },
+{ "radical", 0x8d6 },
+{ "includedin", 0x8da },
+{ "includes", 0x8db },
+{ "intersection", 0x8dc },
+{ "union", 0x8dd },
+{ "logicaland", 0x8de },
+{ "logicalor", 0x8df },
+{ "partialderivative", 0x8ef },
+{ "function", 0x8f6 },
+{ "leftarrow", 0x8fb },
+{ "uparrow", 0x8fc },
+{ "rightarrow", 0x8fd },
+{ "downarrow", 0x8fe },
+{ "blank", 0x9df },
+{ "soliddiamond", 0x9e0 },
+{ "checkerboard", 0x9e1 },
+{ "ht", 0x9e2 },
+{ "ff", 0x9e3 },
+{ "cr", 0x9e4 },
+{ "lf", 0x9e5 },
+{ "nl", 0x9e8 },
+{ "vt", 0x9e9 },
+{ "lowrightcorner", 0x9ea },
+{ "uprightcorner", 0x9eb },
+{ "upleftcorner", 0x9ec },
+{ "lowleftcorner", 0x9ed },
+{ "crossinglines", 0x9ee },
+{ "horizlinescan1", 0x9ef },
+{ "horizlinescan3", 0x9f0 },
+{ "horizlinescan5", 0x9f1 },
+{ "horizlinescan7", 0x9f2 },
+{ "horizlinescan9", 0x9f3 },
+{ "leftt", 0x9f4 },
+{ "rightt", 0x9f5 },
+{ "bott", 0x9f6 },
+{ "topt", 0x9f7 },
+{ "vertbar", 0x9f8 },
+{ "emspace", 0xaa1 },
+{ "enspace", 0xaa2 },
+{ "em3space", 0xaa3 },
+{ "em4space", 0xaa4 },
+{ "digitspace", 0xaa5 },
+{ "punctspace", 0xaa6 },
+{ "thinspace", 0xaa7 },
+{ "hairspace", 0xaa8 },
+{ "emdash", 0xaa9 },
+{ "endash", 0xaaa },
+{ "signifblank", 0xaac },
+{ "ellipsis", 0xaae },
+{ "doubbaselinedot", 0xaaf },
+{ "onethird", 0xab0 },
+{ "twothirds", 0xab1 },
+{ "onefifth", 0xab2 },
+{ "twofifths", 0xab3 },
+{ "threefifths", 0xab4 },
+{ "fourfifths", 0xab5 },
+{ "onesixth", 0xab6 },
+{ "fivesixths", 0xab7 },
+{ "careof", 0xab8 },
+{ "figdash", 0xabb },
+{ "leftanglebracket", 0xabc },
+{ "decimalpoint", 0xabd },
+{ "rightanglebracket", 0xabe },
+{ "marker", 0xabf },
+{ "oneeighth", 0xac3 },
+{ "threeeighths", 0xac4 },
+{ "fiveeighths", 0xac5 },
+{ "seveneighths", 0xac6 },
+{ "trademark", 0xac9 },
+{ "signaturemark", 0xaca },
+{ "trademarkincircle", 0xacb },
+{ "leftopentriangle", 0xacc },
+{ "rightopentriangle", 0xacd },
+{ "emopencircle", 0xace },
+{ "emopenrectangle", 0xacf },
+{ "leftsinglequotemark", 0xad0 },
+{ "rightsinglequotemark", 0xad1 },
+{ "leftdoublequotemark", 0xad2 },
+{ "rightdoublequotemark", 0xad3 },
+{ "prescription", 0xad4 },
+{ "minutes", 0xad6 },
+{ "seconds", 0xad7 },
+{ "latincross", 0xad9 },
+{ "hexagram", 0xada },
+{ "filledrectbullet", 0xadb },
+{ "filledlefttribullet", 0xadc },
+{ "filledrighttribullet", 0xadd },
+{ "emfilledcircle", 0xade },
+{ "emfilledrect", 0xadf },
+{ "enopencircbullet", 0xae0 },
+{ "enopensquarebullet", 0xae1 },
+{ "openrectbullet", 0xae2 },
+{ "opentribulletup", 0xae3 },
+{ "opentribulletdown", 0xae4 },
+{ "openstar", 0xae5 },
+{ "enfilledcircbullet", 0xae6 },
+{ "enfilledsqbullet", 0xae7 },
+{ "filledtribulletup", 0xae8 },
+{ "filledtribulletdown", 0xae9 },
+{ "leftpointer", 0xaea },
+{ "rightpointer", 0xaeb },
+{ "club", 0xaec },
+{ "diamond", 0xaed },
+{ "heart", 0xaee },
+{ "maltesecross", 0xaf0 },
+{ "dagger", 0xaf1 },
+{ "doubledagger", 0xaf2 },
+{ "checkmark", 0xaf3 },
+{ "ballotcross", 0xaf4 },
+{ "musicalsharp", 0xaf5 },
+{ "musicalflat", 0xaf6 },
+{ "malesymbol", 0xaf7 },
+{ "femalesymbol", 0xaf8 },
+{ "telephone", 0xaf9 },
+{ "telephonerecorder", 0xafa },
+{ "phonographcopyright", 0xafb },
+{ "caret", 0xafc },
+{ "singlelowquotemark", 0xafd },
+{ "doublelowquotemark", 0xafe },
+{ "cursor", 0xaff },
+{ "leftcaret", 0xba3 },
+{ "rightcaret", 0xba6 },
+{ "downcaret", 0xba8 },
+{ "upcaret", 0xba9 },
+{ "overbar", 0xbc0 },
+{ "downtack", 0xbc2 },
+{ "upshoe", 0xbc3 },
+{ "downstile", 0xbc4 },
+{ "underbar", 0xbc6 },
+{ "jot", 0xbca },
+{ "quad", 0xbcc },
+{ "uptack", 0xbce },
+{ "circle", 0xbcf },
+{ "upstile", 0xbd3 },
+{ "downshoe", 0xbd6 },
+{ "rightshoe", 0xbd8 },
+{ "leftshoe", 0xbda },
+{ "lefttack", 0xbdc },
+{ "righttack", 0xbfc },
+{ "hebrew_aleph", 0xce0 },
+{ "hebrew_beth", 0xce1 },
+{ "hebrew_gimmel", 0xce2 },
+{ "hebrew_daleth", 0xce3 },
+{ "hebrew_he", 0xce4 },
+{ "hebrew_waw", 0xce5 },
+{ "hebrew_zayin", 0xce6 },
+{ "hebrew_het", 0xce7 },
+{ "hebrew_teth", 0xce8 },
+{ "hebrew_yod", 0xce9 },
+{ "hebrew_finalkaph", 0xcea },
+{ "hebrew_kaph", 0xceb },
+{ "hebrew_lamed", 0xcec },
+{ "hebrew_finalmem", 0xced },
+{ "hebrew_mem", 0xcee },
+{ "hebrew_finalnun", 0xcef },
+{ "hebrew_nun", 0xcf0 },
+{ "hebrew_samekh", 0xcf1 },
+{ "hebrew_ayin", 0xcf2 },
+{ "hebrew_finalpe", 0xcf3 },
+{ "hebrew_pe", 0xcf4 },
+{ "hebrew_finalzadi", 0xcf5 },
+{ "hebrew_zadi", 0xcf6 },
+{ "hebrew_kuf", 0xcf7 },
+{ "hebrew_resh", 0xcf8 },
+{ "hebrew_shin", 0xcf9 },
+{ "hebrew_taf", 0xcfa },
+{ "Hebrew_switch", 0xFF7E },
+{ "XF86AudioLowerVolume", 0x1008FF11 },
+{ "XF86AudioMute", 0x1008FF12 },
+{ "XF86AudioRaiseVolume", 0x1008FF13 },
+{ "XF86AudioPlay", 0x1008FF14 },
+{ "XF86AudioStop", 0x1008FF15 },
+{ "XF86AudioPrev", 0x1008FF16 },
+{ "XF86AudioNext", 0x1008FF17 },
diff --git a/tk8.6/generic/tk.decls b/tk8.6/generic/tk.decls
new file mode 100644
index 0000000..9ceb3af
--- /dev/null
+++ b/tk8.6/generic/tk.decls
@@ -0,0 +1,1154 @@
+# tk.decls --
+#
+# This file contains the declarations for all supported public
+# functions that are exported by the Tk library via the stubs table.
+# This file is used to generate the tkDecls.h, tkPlatDecls.h,
+# tkStub.c, and tkPlatStub.c files.
+#
+# Copyright (c) 1998-2000 Ajuba Solutions.
+# Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+library tk
+
+# Define the tk interface with 3 sub interfaces:
+# tkPlat - platform specific public
+# tkInt - generic private
+# tkPlatInt - platform specific private
+
+interface tk
+hooks {tkPlat tkInt tkIntPlat tkIntXlib}
+scspec EXTERN
+
+# Declare each of the functions in the public Tk interface. Note that
+# the an index should never be reused for a different function in order
+# to preserve backwards compatibility.
+
+declare 0 {
+ void Tk_MainLoop(void)
+}
+declare 1 {
+ XColor *Tk_3DBorderColor(Tk_3DBorder border)
+}
+declare 2 {
+ GC Tk_3DBorderGC(Tk_Window tkwin, Tk_3DBorder border,
+ int which)
+}
+declare 3 {
+ void Tk_3DHorizontalBevel(Tk_Window tkwin,
+ Drawable drawable, Tk_3DBorder border, int x,
+ int y, int width, int height, int leftIn,
+ int rightIn, int topBevel, int relief)
+}
+declare 4 {
+ void Tk_3DVerticalBevel(Tk_Window tkwin,
+ Drawable drawable, Tk_3DBorder border, int x,
+ int y, int width, int height, int leftBevel,
+ int relief)
+}
+declare 5 {
+ void Tk_AddOption(Tk_Window tkwin, const char *name,
+ const char *value, int priority)
+}
+declare 6 {
+ void Tk_BindEvent(Tk_BindingTable bindingTable,
+ XEvent *eventPtr, Tk_Window tkwin, int numObjects,
+ ClientData *objectPtr)
+}
+declare 7 {
+ void Tk_CanvasDrawableCoords(Tk_Canvas canvas,
+ double x, double y, short *drawableXPtr,
+ short *drawableYPtr)
+}
+declare 8 {
+ void Tk_CanvasEventuallyRedraw(Tk_Canvas canvas, int x1, int y1,
+ int x2, int y2)
+}
+declare 9 {
+ int Tk_CanvasGetCoord(Tcl_Interp *interp,
+ Tk_Canvas canvas, const char *str, double *doublePtr)
+}
+declare 10 {
+ Tk_CanvasTextInfo *Tk_CanvasGetTextInfo(Tk_Canvas canvas)
+}
+declare 11 {
+ int Tk_CanvasPsBitmap(Tcl_Interp *interp,
+ Tk_Canvas canvas, Pixmap bitmap, int x, int y,
+ int width, int height)
+}
+declare 12 {
+ int Tk_CanvasPsColor(Tcl_Interp *interp,
+ Tk_Canvas canvas, XColor *colorPtr)
+}
+declare 13 {
+ int Tk_CanvasPsFont(Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Font font)
+}
+declare 14 {
+ void Tk_CanvasPsPath(Tcl_Interp *interp,
+ Tk_Canvas canvas, double *coordPtr, int numPoints)
+}
+declare 15 {
+ int Tk_CanvasPsStipple(Tcl_Interp *interp,
+ Tk_Canvas canvas, Pixmap bitmap)
+}
+declare 16 {
+ double Tk_CanvasPsY(Tk_Canvas canvas, double y)
+}
+declare 17 {
+ void Tk_CanvasSetStippleOrigin(Tk_Canvas canvas, GC gc)
+}
+declare 18 {
+ int Tk_CanvasTagsParseProc(ClientData clientData, Tcl_Interp *interp,
+ Tk_Window tkwin, const char *value, char *widgRec, int offset)
+}
+declare 19 {
+ CONST86 char *Tk_CanvasTagsPrintProc(ClientData clientData, Tk_Window tkwin,
+ char *widgRec, int offset, Tcl_FreeProc **freeProcPtr)
+}
+declare 20 {
+ Tk_Window Tk_CanvasTkwin(Tk_Canvas canvas)
+}
+declare 21 {
+ void Tk_CanvasWindowCoords(Tk_Canvas canvas, double x, double y,
+ short *screenXPtr, short *screenYPtr)
+}
+declare 22 {
+ void Tk_ChangeWindowAttributes(Tk_Window tkwin, unsigned long valueMask,
+ XSetWindowAttributes *attsPtr)
+}
+declare 23 {
+ int Tk_CharBbox(Tk_TextLayout layout, int index, int *xPtr,
+ int *yPtr, int *widthPtr, int *heightPtr)
+}
+declare 24 {
+ void Tk_ClearSelection(Tk_Window tkwin, Atom selection)
+}
+declare 25 {
+ int Tk_ClipboardAppend(Tcl_Interp *interp, Tk_Window tkwin,
+ Atom target, Atom format, const char *buffer)
+}
+declare 26 {
+ int Tk_ClipboardClear(Tcl_Interp *interp, Tk_Window tkwin)
+}
+declare 27 {
+ int Tk_ConfigureInfo(Tcl_Interp *interp,
+ Tk_Window tkwin, const Tk_ConfigSpec *specs,
+ char *widgRec, const char *argvName, int flags)
+}
+declare 28 {
+ int Tk_ConfigureValue(Tcl_Interp *interp,
+ Tk_Window tkwin, const Tk_ConfigSpec *specs,
+ char *widgRec, const char *argvName, int flags)
+}
+declare 29 {
+ int Tk_ConfigureWidget(Tcl_Interp *interp,
+ Tk_Window tkwin, const Tk_ConfigSpec *specs,
+ int argc, CONST84 char **argv, char *widgRec,
+ int flags)
+}
+declare 30 {
+ void Tk_ConfigureWindow(Tk_Window tkwin,
+ unsigned int valueMask, XWindowChanges *valuePtr)
+}
+declare 31 {
+ Tk_TextLayout Tk_ComputeTextLayout(Tk_Font font,
+ const char *str, int numChars, int wrapLength,
+ Tk_Justify justify, int flags, int *widthPtr,
+ int *heightPtr)
+}
+declare 32 {
+ Tk_Window Tk_CoordsToWindow(int rootX, int rootY, Tk_Window tkwin)
+}
+declare 33 {
+ unsigned long Tk_CreateBinding(Tcl_Interp *interp,
+ Tk_BindingTable bindingTable, ClientData object,
+ const char *eventStr, const char *script, int append)
+}
+declare 34 {
+ Tk_BindingTable Tk_CreateBindingTable(Tcl_Interp *interp)
+}
+declare 35 {
+ Tk_ErrorHandler Tk_CreateErrorHandler(Display *display,
+ int errNum, int request, int minorCode,
+ Tk_ErrorProc *errorProc, ClientData clientData)
+}
+declare 36 {
+ void Tk_CreateEventHandler(Tk_Window token,
+ unsigned long mask, Tk_EventProc *proc,
+ ClientData clientData)
+}
+declare 37 {
+ void Tk_CreateGenericHandler(Tk_GenericProc *proc, ClientData clientData)
+}
+declare 38 {
+ void Tk_CreateImageType(const Tk_ImageType *typePtr)
+}
+declare 39 {
+ void Tk_CreateItemType(Tk_ItemType *typePtr)
+}
+declare 40 {
+ void Tk_CreatePhotoImageFormat(const Tk_PhotoImageFormat *formatPtr)
+}
+declare 41 {
+ void Tk_CreateSelHandler(Tk_Window tkwin,
+ Atom selection, Atom target,
+ Tk_SelectionProc *proc, ClientData clientData,
+ Atom format)
+}
+declare 42 {
+ Tk_Window Tk_CreateWindow(Tcl_Interp *interp,
+ Tk_Window parent, const char *name, const char *screenName)
+}
+declare 43 {
+ Tk_Window Tk_CreateWindowFromPath(Tcl_Interp *interp, Tk_Window tkwin,
+ const char *pathName, const char *screenName)
+}
+declare 44 {
+ int Tk_DefineBitmap(Tcl_Interp *interp, const char *name,
+ const void *source, int width, int height)
+}
+declare 45 {
+ void Tk_DefineCursor(Tk_Window window, Tk_Cursor cursor)
+}
+declare 46 {
+ void Tk_DeleteAllBindings(Tk_BindingTable bindingTable, ClientData object)
+}
+declare 47 {
+ int Tk_DeleteBinding(Tcl_Interp *interp,
+ Tk_BindingTable bindingTable, ClientData object,
+ const char *eventStr)
+}
+declare 48 {
+ void Tk_DeleteBindingTable(Tk_BindingTable bindingTable)
+}
+declare 49 {
+ void Tk_DeleteErrorHandler(Tk_ErrorHandler handler)
+}
+declare 50 {
+ void Tk_DeleteEventHandler(Tk_Window token,
+ unsigned long mask, Tk_EventProc *proc,
+ ClientData clientData)
+}
+declare 51 {
+ void Tk_DeleteGenericHandler(Tk_GenericProc *proc, ClientData clientData)
+}
+declare 52 {
+ void Tk_DeleteImage(Tcl_Interp *interp, const char *name)
+}
+declare 53 {
+ void Tk_DeleteSelHandler(Tk_Window tkwin, Atom selection, Atom target)
+}
+declare 54 {
+ void Tk_DestroyWindow(Tk_Window tkwin)
+}
+declare 55 {
+ CONST84_RETURN char *Tk_DisplayName(Tk_Window tkwin)
+}
+declare 56 {
+ int Tk_DistanceToTextLayout(Tk_TextLayout layout, int x, int y)
+}
+declare 57 {
+ void Tk_Draw3DPolygon(Tk_Window tkwin,
+ Drawable drawable, Tk_3DBorder border,
+ XPoint *pointPtr, int numPoints, int borderWidth,
+ int leftRelief)
+}
+declare 58 {
+ void Tk_Draw3DRectangle(Tk_Window tkwin, Drawable drawable,
+ Tk_3DBorder border, int x, int y, int width, int height,
+ int borderWidth, int relief)
+}
+declare 59 {
+ void Tk_DrawChars(Display *display, Drawable drawable, GC gc,
+ Tk_Font tkfont, const char *source, int numBytes, int x, int y)
+}
+declare 60 {
+ void Tk_DrawFocusHighlight(Tk_Window tkwin, GC gc, int width,
+ Drawable drawable)
+}
+declare 61 {
+ void Tk_DrawTextLayout(Display *display,
+ Drawable drawable, GC gc, Tk_TextLayout layout,
+ int x, int y, int firstChar, int lastChar)
+}
+declare 62 {
+ void Tk_Fill3DPolygon(Tk_Window tkwin,
+ Drawable drawable, Tk_3DBorder border,
+ XPoint *pointPtr, int numPoints, int borderWidth,
+ int leftRelief)
+}
+declare 63 {
+ void Tk_Fill3DRectangle(Tk_Window tkwin,
+ Drawable drawable, Tk_3DBorder border, int x,
+ int y, int width, int height, int borderWidth,
+ int relief)
+}
+declare 64 {
+ Tk_PhotoHandle Tk_FindPhoto(Tcl_Interp *interp, const char *imageName)
+}
+declare 65 {
+ Font Tk_FontId(Tk_Font font)
+}
+declare 66 {
+ void Tk_Free3DBorder(Tk_3DBorder border)
+}
+declare 67 {
+ void Tk_FreeBitmap(Display *display, Pixmap bitmap)
+}
+declare 68 {
+ void Tk_FreeColor(XColor *colorPtr)
+}
+declare 69 {
+ void Tk_FreeColormap(Display *display, Colormap colormap)
+}
+declare 70 {
+ void Tk_FreeCursor(Display *display, Tk_Cursor cursor)
+}
+declare 71 {
+ void Tk_FreeFont(Tk_Font f)
+}
+declare 72 {
+ void Tk_FreeGC(Display *display, GC gc)
+}
+declare 73 {
+ void Tk_FreeImage(Tk_Image image)
+}
+declare 74 {
+ void Tk_FreeOptions(const Tk_ConfigSpec *specs,
+ char *widgRec, Display *display, int needFlags)
+}
+declare 75 {
+ void Tk_FreePixmap(Display *display, Pixmap pixmap)
+}
+declare 76 {
+ void Tk_FreeTextLayout(Tk_TextLayout textLayout)
+}
+declare 77 {
+ void Tk_FreeXId(Display *display, XID xid)
+}
+declare 78 {
+ GC Tk_GCForColor(XColor *colorPtr, Drawable drawable)
+}
+declare 79 {
+ void Tk_GeometryRequest(Tk_Window tkwin, int reqWidth, int reqHeight)
+}
+declare 80 {
+ Tk_3DBorder Tk_Get3DBorder(Tcl_Interp *interp, Tk_Window tkwin,
+ Tk_Uid colorName)
+}
+declare 81 {
+ void Tk_GetAllBindings(Tcl_Interp *interp,
+ Tk_BindingTable bindingTable, ClientData object)
+}
+declare 82 {
+ int Tk_GetAnchor(Tcl_Interp *interp,
+ const char *str, Tk_Anchor *anchorPtr)
+}
+declare 83 {
+ CONST84_RETURN char *Tk_GetAtomName(Tk_Window tkwin, Atom atom)
+}
+declare 84 {
+ CONST84_RETURN char *Tk_GetBinding(Tcl_Interp *interp,
+ Tk_BindingTable bindingTable, ClientData object,
+ const char *eventStr)
+}
+declare 85 {
+ Pixmap Tk_GetBitmap(Tcl_Interp *interp, Tk_Window tkwin, const char *str)
+}
+declare 86 {
+ Pixmap Tk_GetBitmapFromData(Tcl_Interp *interp,
+ Tk_Window tkwin, const void *source, int width, int height)
+}
+declare 87 {
+ int Tk_GetCapStyle(Tcl_Interp *interp, const char *str, int *capPtr)
+}
+declare 88 {
+ XColor *Tk_GetColor(Tcl_Interp *interp, Tk_Window tkwin, Tk_Uid name)
+}
+declare 89 {
+ XColor *Tk_GetColorByValue(Tk_Window tkwin, XColor *colorPtr)
+}
+declare 90 {
+ Colormap Tk_GetColormap(Tcl_Interp *interp, Tk_Window tkwin,
+ const char *str)
+}
+declare 91 {
+ Tk_Cursor Tk_GetCursor(Tcl_Interp *interp, Tk_Window tkwin,
+ Tk_Uid str)
+}
+declare 92 {
+ Tk_Cursor Tk_GetCursorFromData(Tcl_Interp *interp,
+ Tk_Window tkwin, const char *source, const char *mask,
+ int width, int height, int xHot, int yHot,
+ Tk_Uid fg, Tk_Uid bg)
+}
+declare 93 {
+ Tk_Font Tk_GetFont(Tcl_Interp *interp,
+ Tk_Window tkwin, const char *str)
+}
+declare 94 {
+ Tk_Font Tk_GetFontFromObj(Tk_Window tkwin, Tcl_Obj *objPtr)
+}
+declare 95 {
+ void Tk_GetFontMetrics(Tk_Font font, Tk_FontMetrics *fmPtr)
+}
+declare 96 {
+ GC Tk_GetGC(Tk_Window tkwin, unsigned long valueMask, XGCValues *valuePtr)
+}
+declare 97 {
+ Tk_Image Tk_GetImage(Tcl_Interp *interp, Tk_Window tkwin, const char *name,
+ Tk_ImageChangedProc *changeProc, ClientData clientData)
+}
+declare 98 {
+ ClientData Tk_GetImageMasterData(Tcl_Interp *interp,
+ const char *name, CONST86 Tk_ImageType **typePtrPtr)
+}
+declare 99 {
+ Tk_ItemType *Tk_GetItemTypes(void)
+}
+declare 100 {
+ int Tk_GetJoinStyle(Tcl_Interp *interp, const char *str, int *joinPtr)
+}
+declare 101 {
+ int Tk_GetJustify(Tcl_Interp *interp,
+ const char *str, Tk_Justify *justifyPtr)
+}
+declare 102 {
+ int Tk_GetNumMainWindows(void)
+}
+declare 103 {
+ Tk_Uid Tk_GetOption(Tk_Window tkwin, const char *name,
+ const char *className)
+}
+declare 104 {
+ int Tk_GetPixels(Tcl_Interp *interp,
+ Tk_Window tkwin, const char *str, int *intPtr)
+}
+declare 105 {
+ Pixmap Tk_GetPixmap(Display *display, Drawable d,
+ int width, int height, int depth)
+}
+declare 106 {
+ int Tk_GetRelief(Tcl_Interp *interp, const char *name, int *reliefPtr)
+}
+declare 107 {
+ void Tk_GetRootCoords(Tk_Window tkwin, int *xPtr, int *yPtr)
+}
+declare 108 {
+ int Tk_GetScrollInfo(Tcl_Interp *interp,
+ int argc, CONST84 char **argv, double *dblPtr, int *intPtr)
+}
+declare 109 {
+ int Tk_GetScreenMM(Tcl_Interp *interp,
+ Tk_Window tkwin, const char *str, double *doublePtr)
+}
+declare 110 {
+ int Tk_GetSelection(Tcl_Interp *interp,
+ Tk_Window tkwin, Atom selection, Atom target,
+ Tk_GetSelProc *proc, ClientData clientData)
+}
+declare 111 {
+ Tk_Uid Tk_GetUid(const char *str)
+}
+declare 112 {
+ Visual *Tk_GetVisual(Tcl_Interp *interp,
+ Tk_Window tkwin, const char *str, int *depthPtr,
+ Colormap *colormapPtr)
+}
+declare 113 {
+ void Tk_GetVRootGeometry(Tk_Window tkwin,
+ int *xPtr, int *yPtr, int *widthPtr, int *heightPtr)
+}
+declare 114 {
+ int Tk_Grab(Tcl_Interp *interp, Tk_Window tkwin, int grabGlobal)
+}
+declare 115 {
+ void Tk_HandleEvent(XEvent *eventPtr)
+}
+declare 116 {
+ Tk_Window Tk_IdToWindow(Display *display, Window window)
+}
+declare 117 {
+ void Tk_ImageChanged(Tk_ImageMaster master, int x, int y,
+ int width, int height, int imageWidth, int imageHeight)
+}
+declare 118 {
+ int Tk_Init(Tcl_Interp *interp)
+}
+declare 119 {
+ Atom Tk_InternAtom(Tk_Window tkwin, const char *name)
+}
+declare 120 {
+ int Tk_IntersectTextLayout(Tk_TextLayout layout, int x, int y,
+ int width, int height)
+}
+declare 121 {
+ void Tk_MaintainGeometry(Tk_Window slave,
+ Tk_Window master, int x, int y, int width, int height)
+}
+declare 122 {
+ Tk_Window Tk_MainWindow(Tcl_Interp *interp)
+}
+declare 123 {
+ void Tk_MakeWindowExist(Tk_Window tkwin)
+}
+declare 124 {
+ void Tk_ManageGeometry(Tk_Window tkwin,
+ const Tk_GeomMgr *mgrPtr, ClientData clientData)
+}
+declare 125 {
+ void Tk_MapWindow(Tk_Window tkwin)
+}
+declare 126 {
+ int Tk_MeasureChars(Tk_Font tkfont,
+ const char *source, int numBytes, int maxPixels,
+ int flags, int *lengthPtr)
+}
+declare 127 {
+ void Tk_MoveResizeWindow(Tk_Window tkwin,
+ int x, int y, int width, int height)
+}
+declare 128 {
+ void Tk_MoveWindow(Tk_Window tkwin, int x, int y)
+}
+declare 129 {
+ void Tk_MoveToplevelWindow(Tk_Window tkwin, int x, int y)
+}
+declare 130 {
+ CONST84_RETURN char *Tk_NameOf3DBorder(Tk_3DBorder border)
+}
+declare 131 {
+ CONST84_RETURN char *Tk_NameOfAnchor(Tk_Anchor anchor)
+}
+declare 132 {
+ CONST84_RETURN char *Tk_NameOfBitmap(Display *display, Pixmap bitmap)
+}
+declare 133 {
+ CONST84_RETURN char *Tk_NameOfCapStyle(int cap)
+}
+declare 134 {
+ CONST84_RETURN char *Tk_NameOfColor(XColor *colorPtr)
+}
+declare 135 {
+ CONST84_RETURN char *Tk_NameOfCursor(Display *display, Tk_Cursor cursor)
+}
+declare 136 {
+ CONST84_RETURN char *Tk_NameOfFont(Tk_Font font)
+}
+declare 137 {
+ CONST84_RETURN char *Tk_NameOfImage(Tk_ImageMaster imageMaster)
+}
+declare 138 {
+ CONST84_RETURN char *Tk_NameOfJoinStyle(int join)
+}
+declare 139 {
+ CONST84_RETURN char *Tk_NameOfJustify(Tk_Justify justify)
+}
+declare 140 {
+ CONST84_RETURN char *Tk_NameOfRelief(int relief)
+}
+declare 141 {
+ Tk_Window Tk_NameToWindow(Tcl_Interp *interp,
+ const char *pathName, Tk_Window tkwin)
+}
+declare 142 {
+ void Tk_OwnSelection(Tk_Window tkwin,
+ Atom selection, Tk_LostSelProc *proc,
+ ClientData clientData)
+}
+declare 143 {
+ int Tk_ParseArgv(Tcl_Interp *interp,
+ Tk_Window tkwin, int *argcPtr, CONST84 char **argv,
+ const Tk_ArgvInfo *argTable, int flags)
+}
+declare 144 {
+ void Tk_PhotoPutBlock_NoComposite(Tk_PhotoHandle handle,
+ Tk_PhotoImageBlock *blockPtr, int x, int y,
+ int width, int height)
+}
+declare 145 {
+ void Tk_PhotoPutZoomedBlock_NoComposite(Tk_PhotoHandle handle,
+ Tk_PhotoImageBlock *blockPtr, int x, int y,
+ int width, int height, int zoomX, int zoomY,
+ int subsampleX, int subsampleY)
+}
+declare 146 {
+ int Tk_PhotoGetImage(Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr)
+}
+declare 147 {
+ void Tk_PhotoBlank(Tk_PhotoHandle handle)
+}
+declare 148 {
+ void Tk_PhotoExpand_Panic(Tk_PhotoHandle handle, int width, int height )
+}
+declare 149 {
+ void Tk_PhotoGetSize(Tk_PhotoHandle handle, int *widthPtr, int *heightPtr)
+}
+declare 150 {
+ void Tk_PhotoSetSize_Panic(Tk_PhotoHandle handle, int width, int height)
+}
+declare 151 {
+ int Tk_PointToChar(Tk_TextLayout layout, int x, int y)
+}
+declare 152 {
+ int Tk_PostscriptFontName(Tk_Font tkfont, Tcl_DString *dsPtr)
+}
+declare 153 {
+ void Tk_PreserveColormap(Display *display, Colormap colormap)
+}
+declare 154 {
+ void Tk_QueueWindowEvent(XEvent *eventPtr, Tcl_QueuePosition position)
+}
+declare 155 {
+ void Tk_RedrawImage(Tk_Image image, int imageX,
+ int imageY, int width, int height,
+ Drawable drawable, int drawableX, int drawableY)
+}
+declare 156 {
+ void Tk_ResizeWindow(Tk_Window tkwin, int width, int height)
+}
+declare 157 {
+ int Tk_RestackWindow(Tk_Window tkwin, int aboveBelow, Tk_Window other)
+}
+declare 158 {
+ Tk_RestrictProc *Tk_RestrictEvents(Tk_RestrictProc *proc,
+ ClientData arg, ClientData *prevArgPtr)
+}
+declare 159 {
+ int Tk_SafeInit(Tcl_Interp *interp)
+}
+declare 160 {
+ const char *Tk_SetAppName(Tk_Window tkwin, const char *name)
+}
+declare 161 {
+ void Tk_SetBackgroundFromBorder(Tk_Window tkwin, Tk_3DBorder border)
+}
+declare 162 {
+ void Tk_SetClass(Tk_Window tkwin, const char *className)
+}
+declare 163 {
+ void Tk_SetGrid(Tk_Window tkwin, int reqWidth, int reqHeight,
+ int gridWidth, int gridHeight)
+}
+declare 164 {
+ void Tk_SetInternalBorder(Tk_Window tkwin, int width)
+}
+declare 165 {
+ void Tk_SetWindowBackground(Tk_Window tkwin, unsigned long pixel)
+}
+declare 166 {
+ void Tk_SetWindowBackgroundPixmap(Tk_Window tkwin, Pixmap pixmap)
+}
+declare 167 {
+ void Tk_SetWindowBorder(Tk_Window tkwin, unsigned long pixel)
+}
+declare 168 {
+ void Tk_SetWindowBorderWidth(Tk_Window tkwin, int width)
+}
+declare 169 {
+ void Tk_SetWindowBorderPixmap(Tk_Window tkwin, Pixmap pixmap)
+}
+declare 170 {
+ void Tk_SetWindowColormap(Tk_Window tkwin, Colormap colormap)
+}
+declare 171 {
+ int Tk_SetWindowVisual(Tk_Window tkwin, Visual *visual, int depth,
+ Colormap colormap)
+}
+declare 172 {
+ void Tk_SizeOfBitmap(Display *display, Pixmap bitmap, int *widthPtr,
+ int *heightPtr)
+}
+declare 173 {
+ void Tk_SizeOfImage(Tk_Image image, int *widthPtr, int *heightPtr)
+}
+declare 174 {
+ int Tk_StrictMotif(Tk_Window tkwin)
+}
+declare 175 {
+ void Tk_TextLayoutToPostscript(Tcl_Interp *interp, Tk_TextLayout layout)
+}
+declare 176 {
+ int Tk_TextWidth(Tk_Font font, const char *str, int numBytes)
+}
+declare 177 {
+ void Tk_UndefineCursor(Tk_Window window)
+}
+declare 178 {
+ void Tk_UnderlineChars(Display *display,
+ Drawable drawable, GC gc, Tk_Font tkfont,
+ const char *source, int x, int y, int firstByte,
+ int lastByte)
+}
+declare 179 {
+ void Tk_UnderlineTextLayout(Display *display, Drawable drawable, GC gc,
+ Tk_TextLayout layout, int x, int y,
+ int underline)
+}
+declare 180 {
+ void Tk_Ungrab(Tk_Window tkwin)
+}
+declare 181 {
+ void Tk_UnmaintainGeometry(Tk_Window slave, Tk_Window master)
+}
+declare 182 {
+ void Tk_UnmapWindow(Tk_Window tkwin)
+}
+declare 183 {
+ void Tk_UnsetGrid(Tk_Window tkwin)
+}
+declare 184 {
+ void Tk_UpdatePointer(Tk_Window tkwin, int x, int y, int state)
+}
+
+# new functions for 8.1
+
+declare 185 {
+ Pixmap Tk_AllocBitmapFromObj(Tcl_Interp *interp, Tk_Window tkwin,
+ Tcl_Obj *objPtr)
+}
+declare 186 {
+ Tk_3DBorder Tk_Alloc3DBorderFromObj(Tcl_Interp *interp, Tk_Window tkwin,
+ Tcl_Obj *objPtr)
+}
+declare 187 {
+ XColor *Tk_AllocColorFromObj(Tcl_Interp *interp, Tk_Window tkwin,
+ Tcl_Obj *objPtr)
+}
+declare 188 {
+ Tk_Cursor Tk_AllocCursorFromObj(Tcl_Interp *interp, Tk_Window tkwin,
+ Tcl_Obj *objPtr)
+}
+declare 189 {
+ Tk_Font Tk_AllocFontFromObj(Tcl_Interp *interp, Tk_Window tkwin,
+ Tcl_Obj *objPtr)
+
+}
+declare 190 {
+ Tk_OptionTable Tk_CreateOptionTable(Tcl_Interp *interp,
+ const Tk_OptionSpec *templatePtr)
+}
+declare 191 {
+ void Tk_DeleteOptionTable(Tk_OptionTable optionTable)
+}
+declare 192 {
+ void Tk_Free3DBorderFromObj(Tk_Window tkwin, Tcl_Obj *objPtr)
+}
+declare 193 {
+ void Tk_FreeBitmapFromObj(Tk_Window tkwin, Tcl_Obj *objPtr)
+}
+declare 194 {
+ void Tk_FreeColorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr)
+}
+declare 195 {
+ void Tk_FreeConfigOptions(char *recordPtr, Tk_OptionTable optionToken,
+ Tk_Window tkwin)
+}
+declare 196 {
+ void Tk_FreeSavedOptions(Tk_SavedOptions *savePtr)
+}
+declare 197 {
+ void Tk_FreeCursorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr)
+}
+declare 198 {
+ void Tk_FreeFontFromObj(Tk_Window tkwin, Tcl_Obj *objPtr)
+}
+declare 199 {
+ Tk_3DBorder Tk_Get3DBorderFromObj(Tk_Window tkwin, Tcl_Obj *objPtr)
+}
+declare 200 {
+ int Tk_GetAnchorFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
+ Tk_Anchor *anchorPtr)
+}
+declare 201 {
+ Pixmap Tk_GetBitmapFromObj(Tk_Window tkwin, Tcl_Obj *objPtr)
+}
+declare 202 {
+ XColor *Tk_GetColorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr)
+}
+declare 203 {
+ Tk_Cursor Tk_GetCursorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr)
+}
+declare 204 {
+ Tcl_Obj *Tk_GetOptionInfo(Tcl_Interp *interp,
+ char *recordPtr, Tk_OptionTable optionTable,
+ Tcl_Obj *namePtr, Tk_Window tkwin)
+}
+declare 205 {
+ Tcl_Obj *Tk_GetOptionValue(Tcl_Interp *interp, char *recordPtr,
+ Tk_OptionTable optionTable, Tcl_Obj *namePtr, Tk_Window tkwin)
+}
+declare 206 {
+ int Tk_GetJustifyFromObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, Tk_Justify *justifyPtr)
+}
+declare 207 {
+ int Tk_GetMMFromObj(Tcl_Interp *interp,
+ Tk_Window tkwin, Tcl_Obj *objPtr, double *doublePtr)
+}
+declare 208 {
+ int Tk_GetPixelsFromObj(Tcl_Interp *interp,
+ Tk_Window tkwin, Tcl_Obj *objPtr, int *intPtr)
+}
+declare 209 {
+ int Tk_GetReliefFromObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, int *resultPtr)
+}
+declare 210 {
+ int Tk_GetScrollInfoObj(Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[], double *dblPtr, int *intPtr)
+}
+declare 211 {
+ int Tk_InitOptions(Tcl_Interp *interp, char *recordPtr,
+ Tk_OptionTable optionToken, Tk_Window tkwin)
+}
+declare 212 {
+ void Tk_MainEx(int argc, char **argv, Tcl_AppInitProc *appInitProc,
+ Tcl_Interp *interp)
+}
+declare 213 {
+ void Tk_RestoreSavedOptions(Tk_SavedOptions *savePtr)
+}
+declare 214 {
+ int Tk_SetOptions(Tcl_Interp *interp, char *recordPtr,
+ Tk_OptionTable optionTable, int objc,
+ Tcl_Obj *const objv[], Tk_Window tkwin,
+ Tk_SavedOptions *savePtr, int *maskPtr)
+}
+declare 215 {
+ void Tk_InitConsoleChannels(Tcl_Interp *interp)
+}
+declare 216 {
+ int Tk_CreateConsoleWindow(Tcl_Interp *interp)
+}
+declare 217 {
+ void Tk_CreateSmoothMethod(Tcl_Interp *interp, const Tk_SmoothMethod *method)
+}
+#declare 218 {
+# void Tk_CreateCanvasVisitor(Tcl_Interp *interp, void *typePtr)
+#}
+#declare 219 {
+# void *Tk_GetCanvasVisitor(Tcl_Interp *interp, const char *name)
+#}
+declare 220 {
+ int Tk_GetDash(Tcl_Interp *interp, const char *value, Tk_Dash *dash)
+}
+declare 221 {
+ void Tk_CreateOutline(Tk_Outline *outline)
+}
+declare 222 {
+ void Tk_DeleteOutline(Display *display, Tk_Outline *outline)
+}
+declare 223 {
+ int Tk_ConfigOutlineGC(XGCValues *gcValues, Tk_Canvas canvas,
+ Tk_Item *item, Tk_Outline *outline)
+}
+declare 224 {
+ int Tk_ChangeOutlineGC(Tk_Canvas canvas, Tk_Item *item,
+ Tk_Outline *outline)
+}
+declare 225 {
+ int Tk_ResetOutlineGC(Tk_Canvas canvas, Tk_Item *item,
+ Tk_Outline *outline)
+}
+declare 226 {
+ int Tk_CanvasPsOutline(Tk_Canvas canvas, Tk_Item *item,
+ Tk_Outline *outline)
+}
+declare 227 {
+ void Tk_SetTSOrigin(Tk_Window tkwin, GC gc, int x, int y)
+}
+declare 228 {
+ int Tk_CanvasGetCoordFromObj(Tcl_Interp *interp, Tk_Canvas canvas,
+ Tcl_Obj *obj, double *doublePtr)
+}
+declare 229 {
+ void Tk_CanvasSetOffset(Tk_Canvas canvas, GC gc, Tk_TSOffset *offset)
+}
+declare 230 {
+ void Tk_DitherPhoto(Tk_PhotoHandle handle, int x, int y, int width,
+ int height)
+}
+declare 231 {
+ int Tk_PostscriptBitmap(Tcl_Interp *interp, Tk_Window tkwin,
+ Tk_PostscriptInfo psInfo, Pixmap bitmap, int startX,
+ int startY, int width, int height)
+}
+declare 232 {
+ int Tk_PostscriptColor(Tcl_Interp *interp, Tk_PostscriptInfo psInfo,
+ XColor *colorPtr)
+}
+declare 233 {
+ int Tk_PostscriptFont(Tcl_Interp *interp, Tk_PostscriptInfo psInfo,
+ Tk_Font font)
+}
+declare 234 {
+ int Tk_PostscriptImage(Tk_Image image, Tcl_Interp *interp,
+ Tk_Window tkwin, Tk_PostscriptInfo psinfo, int x, int y,
+ int width, int height, int prepass)
+}
+declare 235 {
+ void Tk_PostscriptPath(Tcl_Interp *interp, Tk_PostscriptInfo psInfo,
+ double *coordPtr, int numPoints)
+}
+declare 236 {
+ int Tk_PostscriptStipple(Tcl_Interp *interp, Tk_Window tkwin,
+ Tk_PostscriptInfo psInfo, Pixmap bitmap)
+}
+declare 237 {
+ double Tk_PostscriptY(double y, Tk_PostscriptInfo psInfo)
+}
+declare 238 {
+ int Tk_PostscriptPhoto(Tcl_Interp *interp,
+ Tk_PhotoImageBlock *blockPtr, Tk_PostscriptInfo psInfo,
+ int width, int height)
+}
+
+# New in 8.4a1
+#
+declare 239 {
+ void Tk_CreateClientMessageHandler(Tk_ClientMessageProc *proc)
+}
+declare 240 {
+ void Tk_DeleteClientMessageHandler(Tk_ClientMessageProc *proc)
+}
+
+# New in 8.4a2
+#
+declare 241 {
+ Tk_Window Tk_CreateAnonymousWindow(Tcl_Interp *interp,
+ Tk_Window parent, const char *screenName)
+}
+declare 242 {
+ void Tk_SetClassProcs(Tk_Window tkwin,
+ const Tk_ClassProcs *procs, ClientData instanceData)
+}
+
+# New in 8.4a4
+#
+declare 243 {
+ void Tk_SetInternalBorderEx(Tk_Window tkwin, int left, int right,
+ int top, int bottom)
+}
+declare 244 {
+ void Tk_SetMinimumRequestSize(Tk_Window tkwin,
+ int minWidth, int minHeight)
+}
+
+# New in 8.4a5
+#
+declare 245 {
+ void Tk_SetCaretPos(Tk_Window tkwin, int x, int y, int height)
+}
+declare 246 {
+ void Tk_PhotoPutBlock_Panic(Tk_PhotoHandle handle,
+ Tk_PhotoImageBlock *blockPtr, int x, int y,
+ int width, int height, int compRule)
+}
+declare 247 {
+ void Tk_PhotoPutZoomedBlock_Panic(Tk_PhotoHandle handle,
+ Tk_PhotoImageBlock *blockPtr, int x, int y,
+ int width, int height, int zoomX, int zoomY,
+ int subsampleX, int subsampleY, int compRule)
+}
+declare 248 {
+ int Tk_CollapseMotionEvents(Display *display, int collapse)
+}
+
+# Style engine
+declare 249 {
+ Tk_StyleEngine Tk_RegisterStyleEngine(const char *name,
+ Tk_StyleEngine parent)
+}
+declare 250 {
+ Tk_StyleEngine Tk_GetStyleEngine(const char *name)
+}
+declare 251 {
+ int Tk_RegisterStyledElement(Tk_StyleEngine engine,
+ Tk_ElementSpec *templatePtr)
+}
+declare 252 {
+ int Tk_GetElementId(const char *name)
+}
+declare 253 {
+ Tk_Style Tk_CreateStyle(const char *name, Tk_StyleEngine engine,
+ ClientData clientData)
+}
+declare 254 {
+ Tk_Style Tk_GetStyle(Tcl_Interp *interp, const char *name)
+}
+declare 255 {
+ void Tk_FreeStyle(Tk_Style style)
+}
+declare 256 {
+ const char *Tk_NameOfStyle(Tk_Style style)
+}
+declare 257 {
+ Tk_Style Tk_AllocStyleFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr)
+}
+declare 258 {
+ Tk_Style Tk_GetStyleFromObj(Tcl_Obj *objPtr)
+}
+declare 259 {
+ void Tk_FreeStyleFromObj(Tcl_Obj *objPtr)
+}
+declare 260 {
+ Tk_StyledElement Tk_GetStyledElement(Tk_Style style, int elementId,
+ Tk_OptionTable optionTable)
+}
+declare 261 {
+ void Tk_GetElementSize(Tk_Style style, Tk_StyledElement element,
+ char *recordPtr, Tk_Window tkwin, int width, int height,
+ int inner, int *widthPtr, int *heightPtr)
+}
+declare 262 {
+ void Tk_GetElementBox(Tk_Style style, Tk_StyledElement element,
+ char *recordPtr, Tk_Window tkwin, int x, int y, int width,
+ int height, int inner, int *xPtr, int *yPtr, int *widthPtr,
+ int *heightPtr)
+}
+declare 263 {
+ int Tk_GetElementBorderWidth(Tk_Style style, Tk_StyledElement element,
+ char *recordPtr, Tk_Window tkwin)
+}
+declare 264 {
+ void Tk_DrawElement(Tk_Style style, Tk_StyledElement element,
+ char *recordPtr, Tk_Window tkwin, Drawable d, int x, int y,
+ int width, int height, int state)
+}
+
+# TIP#116
+declare 265 {
+ int Tk_PhotoExpand(Tcl_Interp *interp, Tk_PhotoHandle handle,
+ int width, int height)
+}
+declare 266 {
+ int Tk_PhotoPutBlock(Tcl_Interp *interp, Tk_PhotoHandle handle,
+ Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height,
+ int compRule)
+}
+declare 267 {
+ int Tk_PhotoPutZoomedBlock(Tcl_Interp *interp, Tk_PhotoHandle handle,
+ Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height,
+ int zoomX, int zoomY, int subsampleX, int subsampleY, int compRule)
+}
+declare 268 {
+ int Tk_PhotoSetSize(Tcl_Interp *interp, Tk_PhotoHandle handle,
+ int width, int height)
+}
+# TIP#245
+declare 269 {
+ long Tk_GetUserInactiveTime(Display *dpy)
+}
+declare 270 {
+ void Tk_ResetUserInactiveTime(Display *dpy)
+}
+
+# TIP #264
+declare 271 {
+ Tcl_Interp *Tk_Interp(Tk_Window tkwin)
+}
+
+# Now that the Tk 8.2 -> 8.3 transition is long past, use more conventional
+# means to continue support for extensions using the USE_OLD_IMAGE to
+# continue use of their string-based Tcl_ImageTypes and Tcl_PhotoImageFormats.
+#
+# Note that this restores the usual rules for stub compatibility. Stub-enabled
+# extensions compiled against 8.5 headers and linked to the 8.5 stub library
+# will produce a file [load]able into an interp with Tk 8.X, for X >= 5.
+# It will *not* be [load]able into interps with Tk 8.4 (or Tk 8.2!).
+# Developers who need to produce a file [load]able into legacy interps must
+# build against legacy sources.
+declare 272 {
+ void Tk_CreateOldImageType(const Tk_ImageType *typePtr)
+}
+declare 273 {
+ void Tk_CreateOldPhotoImageFormat(const Tk_PhotoImageFormat *formatPtr)
+}
+
+# Define the platform specific public Tk interface. These functions are
+# only available on the designated platform.
+
+interface tkPlat
+
+################################
+# Windows specific functions
+
+declare 0 win {
+ Window Tk_AttachHWND(Tk_Window tkwin, HWND hwnd)
+}
+declare 1 win {
+ HINSTANCE Tk_GetHINSTANCE(void)
+}
+declare 2 win {
+ HWND Tk_GetHWND(Window window)
+}
+declare 3 win {
+ Tk_Window Tk_HWNDToWindow(HWND hwnd)
+}
+declare 4 win {
+ void Tk_PointerEvent(HWND hwnd, int x, int y)
+}
+declare 5 win {
+ int Tk_TranslateWinEvent(HWND hwnd,
+ UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result)
+}
+
+################################
+# Aqua specific functions
+
+declare 0 aqua {
+ void Tk_MacOSXSetEmbedHandler(
+ Tk_MacOSXEmbedRegisterWinProc *registerWinProcPtr,
+ Tk_MacOSXEmbedGetGrafPortProc *getPortProcPtr,
+ Tk_MacOSXEmbedMakeContainerExistProc *containerExistProcPtr,
+ Tk_MacOSXEmbedGetClipProc *getClipProc,
+ Tk_MacOSXEmbedGetOffsetInParentProc *getOffsetProc)
+}
+declare 1 aqua {
+ void Tk_MacOSXTurnOffMenus(void)
+}
+declare 2 aqua {
+ void Tk_MacOSXTkOwnsCursor(int tkOwnsIt)
+}
+declare 3 aqua {
+ void TkMacOSXInitMenus(Tcl_Interp *interp)
+}
+declare 4 aqua {
+ void TkMacOSXInitAppleEvents(Tcl_Interp *interp)
+}
+declare 5 aqua {
+ void TkGenWMConfigureEvent(Tk_Window tkwin, int x, int y, int width,
+ int height, int flags)
+}
+declare 6 aqua {
+ void TkMacOSXInvalClipRgns(Tk_Window tkwin)
+}
+declare 7 aqua {
+ void *TkMacOSXGetDrawablePort(Drawable drawable)
+}
+declare 8 aqua {
+ void *TkMacOSXGetRootControl(Drawable drawable)
+}
+declare 9 aqua {
+ void Tk_MacOSXSetupTkNotifier(void)
+}
+declare 10 aqua {
+ int Tk_MacOSXIsAppInFront(void)
+}
+
+##############################################################################
+
+# Public functions that are not accessible via the stubs table.
+
+export {
+ const char *Tk_PkgInitStubsCheck(Tcl_Interp *interp, const char *version,
+ int exact)
+}
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tk8.6/generic/tk.h b/tk8.6/generic/tk.h
new file mode 100644
index 0000000..7a10689
--- /dev/null
+++ b/tk8.6/generic/tk.h
@@ -0,0 +1,1623 @@
+/*
+ * tk.h --
+ *
+ * Declarations for Tk-related things that are visible outside of the Tk
+ * module itself.
+ *
+ * Copyright (c) 1989-1994 The Regents of the University of California.
+ * Copyright (c) 1994 The Australian National University.
+ * Copyright (c) 1994-1998 Sun Microsystems, Inc.
+ * Copyright (c) 1998-2000 Ajuba Solutions.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef _TK
+#define _TK
+
+#include <tcl.h>
+#if (TCL_MAJOR_VERSION != 8) || (TCL_MINOR_VERSION < 6)
+# error Tk 8.6 must be compiled with tcl.h from Tcl 8.6 or better
+#endif
+
+#ifndef CONST84
+# define CONST84 const
+# define CONST84_RETURN const
+#endif
+#ifndef CONST86
+# define CONST86 CONST84
+#endif
+#ifndef EXTERN
+# define EXTERN extern TCL_STORAGE_CLASS
+#endif
+
+/*
+ * Utility macros: STRINGIFY takes an argument and wraps it in "" (double
+ * quotation marks), JOIN joins two arguments.
+ */
+
+#ifndef STRINGIFY
+# define STRINGIFY(x) STRINGIFY1(x)
+# define STRINGIFY1(x) #x
+#endif
+#ifndef JOIN
+# define JOIN(a,b) JOIN1(a,b)
+# define JOIN1(a,b) a##b
+#endif
+
+/*
+ * For C++ compilers, use extern "C"
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * When version numbers change here, you must also go into the following files
+ * and update the version numbers:
+ *
+ * library/tk.tcl (1 LOC patch)
+ * unix/configure.in (2 LOC Major, 2 LOC minor, 1 LOC patch)
+ * win/configure.in (as above)
+ * README (sections 0 and 1)
+ * macosx/Tk-Common.xcconfig (not patchlevel) 1 LOC
+ * win/README (not patchlevel)
+ * unix/README (not patchlevel)
+ * unix/tk.spec (1 LOC patch)
+ * win/tcl.m4 (not patchlevel)
+ *
+ * You may also need to update some of these files when the numbers change for
+ * the version of Tcl that this release of Tk is compiled against.
+ */
+
+#define TK_MAJOR_VERSION 8
+#define TK_MINOR_VERSION 6
+#define TK_RELEASE_LEVEL TCL_FINAL_RELEASE
+#define TK_RELEASE_SERIAL 10
+
+#define TK_VERSION "8.6"
+#define TK_PATCH_LEVEL "8.6.10"
+
+/*
+ * A special definition used to allow this header file to be included from
+ * windows or mac resource files so that they can obtain version information.
+ * RC_INVOKED is defined by default by the windows RC tool and manually set
+ * for macintosh.
+ *
+ * Resource compilers don't like all the C stuff, like typedefs and procedure
+ * declarations, that occur below, so block them out.
+ */
+
+#ifndef RC_INVOKED
+
+#ifndef _XLIB_H
+# include <X11/Xlib.h>
+# ifdef MAC_OSX_TK
+# include <X11/X.h>
+# endif
+#endif
+#ifdef __STDC__
+# include <stddef.h>
+#endif
+
+#ifdef BUILD_tk
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLEXPORT
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Decide whether or not to use input methods.
+ */
+
+#ifdef XNQueryInputStyle
+#define TK_USE_INPUT_METHODS
+#endif
+
+/*
+ * Dummy types that are used by clients:
+ */
+
+typedef struct Tk_BindingTable_ *Tk_BindingTable;
+typedef struct Tk_Canvas_ *Tk_Canvas;
+typedef struct Tk_Cursor_ *Tk_Cursor;
+typedef struct Tk_ErrorHandler_ *Tk_ErrorHandler;
+typedef struct Tk_Font_ *Tk_Font;
+typedef struct Tk_Image__ *Tk_Image;
+typedef struct Tk_ImageMaster_ *Tk_ImageMaster;
+typedef struct Tk_OptionTable_ *Tk_OptionTable;
+typedef struct Tk_PostscriptInfo_ *Tk_PostscriptInfo;
+typedef struct Tk_TextLayout_ *Tk_TextLayout;
+typedef struct Tk_Window_ *Tk_Window;
+typedef struct Tk_3DBorder_ *Tk_3DBorder;
+typedef struct Tk_Style_ *Tk_Style;
+typedef struct Tk_StyleEngine_ *Tk_StyleEngine;
+typedef struct Tk_StyledElement_ *Tk_StyledElement;
+
+/*
+ * Additional types exported to clients.
+ */
+
+typedef const char *Tk_Uid;
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * The enum below defines the valid types for Tk configuration options as
+ * implemented by Tk_InitOptions, Tk_SetOptions, etc.
+ */
+
+typedef enum {
+ TK_OPTION_BOOLEAN,
+ TK_OPTION_INT,
+ TK_OPTION_DOUBLE,
+ TK_OPTION_STRING,
+ TK_OPTION_STRING_TABLE,
+ TK_OPTION_COLOR,
+ TK_OPTION_FONT,
+ TK_OPTION_BITMAP,
+ TK_OPTION_BORDER,
+ TK_OPTION_RELIEF,
+ TK_OPTION_CURSOR,
+ TK_OPTION_JUSTIFY,
+ TK_OPTION_ANCHOR,
+ TK_OPTION_SYNONYM,
+ TK_OPTION_PIXELS,
+ TK_OPTION_WINDOW,
+ TK_OPTION_END,
+ TK_OPTION_CUSTOM,
+ TK_OPTION_STYLE
+} Tk_OptionType;
+
+/*
+ * Structures of the following type are used by widgets to specify their
+ * configuration options. Typically each widget has a static array of these
+ * structures, where each element of the array describes a single
+ * configuration option. The array is passed to Tk_CreateOptionTable.
+ */
+
+typedef struct Tk_OptionSpec {
+ Tk_OptionType type; /* Type of option, such as TK_OPTION_COLOR;
+ * see definitions above. Last option in table
+ * must have type TK_OPTION_END. */
+ const char *optionName; /* Name used to specify option in Tcl
+ * commands. */
+ const char *dbName; /* Name for option in option database. */
+ const char *dbClass; /* Class for option in database. */
+ const char *defValue; /* Default value for option if not specified
+ * in command line, the option database, or
+ * the system. */
+ int objOffset; /* Where in record to store a Tcl_Obj * that
+ * holds the value of this option, specified
+ * as an offset in bytes from the start of the
+ * record. Use the Tk_Offset macro to generate
+ * values for this. -1 means don't store the
+ * Tcl_Obj in the record. */
+ int internalOffset; /* Where in record to store the internal
+ * representation of the value of this option,
+ * such as an int or XColor *. This field is
+ * specified as an offset in bytes from the
+ * start of the record. Use the Tk_Offset
+ * macro to generate values for it. -1 means
+ * don't store the internal representation in
+ * the record. */
+ int flags; /* Any combination of the values defined
+ * below. */
+ const void *clientData; /* An alternate place to put option-specific
+ * data. Used for the monochrome default value
+ * for colors, etc. */
+ int typeMask; /* An arbitrary bit mask defined by the class
+ * manager; typically bits correspond to
+ * certain kinds of options such as all those
+ * that require a redisplay when they change.
+ * Tk_SetOptions returns the bit-wise OR of
+ * the typeMasks of all options that were
+ * changed. */
+} Tk_OptionSpec;
+
+/*
+ * Flag values for Tk_OptionSpec structures. These flags are shared by
+ * Tk_ConfigSpec structures, so be sure to coordinate any changes carefully.
+ */
+
+#define TK_OPTION_NULL_OK (1 << 0)
+#define TK_OPTION_DONT_SET_DEFAULT (1 << 3)
+
+/*
+ * The following structure and function types are used by TK_OPTION_CUSTOM
+ * options; the structure holds pointers to the functions needed by the Tk
+ * option config code to handle a custom option.
+ */
+
+typedef int (Tk_CustomOptionSetProc) (ClientData clientData,
+ Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj **value, char *widgRec,
+ int offset, char *saveInternalPtr, int flags);
+typedef Tcl_Obj *(Tk_CustomOptionGetProc) (ClientData clientData,
+ Tk_Window tkwin, char *widgRec, int offset);
+typedef void (Tk_CustomOptionRestoreProc) (ClientData clientData,
+ Tk_Window tkwin, char *internalPtr, char *saveInternalPtr);
+typedef void (Tk_CustomOptionFreeProc) (ClientData clientData, Tk_Window tkwin,
+ char *internalPtr);
+
+typedef struct Tk_ObjCustomOption {
+ const char *name; /* Name of the custom option. */
+ Tk_CustomOptionSetProc *setProc;
+ /* Function to use to set a record's option
+ * value from a Tcl_Obj */
+ Tk_CustomOptionGetProc *getProc;
+ /* Function to use to get a Tcl_Obj
+ * representation from an internal
+ * representation of an option. */
+ Tk_CustomOptionRestoreProc *restoreProc;
+ /* Function to use to restore a saved value
+ * for the internal representation. */
+ Tk_CustomOptionFreeProc *freeProc;
+ /* Function to use to free the internal
+ * representation of an option. */
+ ClientData clientData; /* Arbitrary one-word value passed to the
+ * handling procs. */
+} Tk_ObjCustomOption;
+
+/*
+ * Macro to use to fill in "offset" fields of the Tk_OptionSpec structure.
+ * Computes number of bytes from beginning of structure to a given field.
+ */
+
+#define Tk_Offset(type, field) ((int) offsetof(type, field))
+/* Workaround for platforms missing offsetof(), e.g. VC++ 6.0 */
+#ifndef offsetof
+# define offsetof(type, field) ((size_t) ((char *) &((type *) 0)->field))
+#endif
+
+/*
+ * The following two structures are used for error handling. When config
+ * options are being modified, the old values are saved in a Tk_SavedOptions
+ * structure. If an error occurs, then the contents of the structure can be
+ * used to restore all of the old values. The contents of this structure are
+ * for the private use Tk. No-one outside Tk should ever read or write any of
+ * the fields of these structures.
+ */
+
+typedef struct Tk_SavedOption {
+ struct TkOption *optionPtr; /* Points to information that describes the
+ * option. */
+ Tcl_Obj *valuePtr; /* The old value of the option, in the form of
+ * a Tcl object; may be NULL if the value was
+ * not saved as an object. */
+ double internalForm; /* The old value of the option, in some
+ * internal representation such as an int or
+ * (XColor *). Valid only if the field
+ * optionPtr->specPtr->objOffset is < 0. The
+ * space must be large enough to accommodate a
+ * double, a long, or a pointer; right now it
+ * looks like a double (i.e., 8 bytes) is big
+ * enough. Also, using a double guarantees
+ * that the field is properly aligned for
+ * storing large values. */
+} Tk_SavedOption;
+
+#ifdef TCL_MEM_DEBUG
+# define TK_NUM_SAVED_OPTIONS 2
+#else
+# define TK_NUM_SAVED_OPTIONS 20
+#endif
+
+typedef struct Tk_SavedOptions {
+ char *recordPtr; /* The data structure in which to restore
+ * configuration options. */
+ Tk_Window tkwin; /* Window associated with recordPtr; needed to
+ * restore certain options. */
+ int numItems; /* The number of valid items in items field. */
+ Tk_SavedOption items[TK_NUM_SAVED_OPTIONS];
+ /* Items used to hold old values. */
+ struct Tk_SavedOptions *nextPtr;
+ /* Points to next structure in list; needed if
+ * too many options changed to hold all the
+ * old values in a single structure. NULL
+ * means no more structures. */
+} Tk_SavedOptions;
+
+/*
+ * Structure used to describe application-specific configuration options:
+ * indicates procedures to call to parse an option and to return a text string
+ * describing an option. THESE ARE DEPRECATED; PLEASE USE THE NEW STRUCTURES
+ * LISTED ABOVE.
+ */
+
+/*
+ * This is a temporary flag used while tkObjConfig and new widgets are in
+ * development.
+ */
+
+#ifndef __NO_OLD_CONFIG
+
+typedef int (Tk_OptionParseProc) (ClientData clientData, Tcl_Interp *interp,
+ Tk_Window tkwin, CONST84 char *value, char *widgRec, int offset);
+typedef CONST86 char *(Tk_OptionPrintProc) (ClientData clientData,
+ Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr);
+
+typedef struct Tk_CustomOption {
+ Tk_OptionParseProc *parseProc;
+ /* Procedure to call to parse an option and
+ * store it in converted form. */
+ Tk_OptionPrintProc *printProc;
+ /* Procedure to return a printable string
+ * describing an existing option. */
+ ClientData clientData; /* Arbitrary one-word value used by option
+ * parser: passed to parseProc and
+ * printProc. */
+} Tk_CustomOption;
+
+/*
+ * Structure used to specify information for Tk_ConfigureWidget. Each
+ * structure gives complete information for one option, including how the
+ * option is specified on the command line, where it appears in the option
+ * database, etc.
+ */
+
+typedef struct Tk_ConfigSpec {
+ int type; /* Type of option, such as TK_CONFIG_COLOR;
+ * see definitions below. Last option in table
+ * must have type TK_CONFIG_END. */
+ CONST86 char *argvName; /* Switch used to specify option in argv. NULL
+ * means this spec is part of a group. */
+ Tk_Uid dbName; /* Name for option in option database. */
+ Tk_Uid dbClass; /* Class for option in database. */
+ Tk_Uid defValue; /* Default value for option if not specified
+ * in command line or database. */
+ int offset; /* Where in widget record to store value; use
+ * Tk_Offset macro to generate values for
+ * this. */
+ int specFlags; /* Any combination of the values defined
+ * below; other bits are used internally by
+ * tkConfig.c. */
+ CONST86 Tk_CustomOption *customPtr;
+ /* If type is TK_CONFIG_CUSTOM then this is a
+ * pointer to info about how to parse and
+ * print the option. Otherwise it is
+ * irrelevant. */
+} Tk_ConfigSpec;
+
+/*
+ * Type values for Tk_ConfigSpec structures. See the user documentation for
+ * details.
+ */
+
+typedef enum {
+ TK_CONFIG_BOOLEAN, TK_CONFIG_INT, TK_CONFIG_DOUBLE, TK_CONFIG_STRING,
+ TK_CONFIG_UID, TK_CONFIG_COLOR, TK_CONFIG_FONT, TK_CONFIG_BITMAP,
+ TK_CONFIG_BORDER, TK_CONFIG_RELIEF, TK_CONFIG_CURSOR,
+ TK_CONFIG_ACTIVE_CURSOR, TK_CONFIG_JUSTIFY, TK_CONFIG_ANCHOR,
+ TK_CONFIG_SYNONYM, TK_CONFIG_CAP_STYLE, TK_CONFIG_JOIN_STYLE,
+ TK_CONFIG_PIXELS, TK_CONFIG_MM, TK_CONFIG_WINDOW, TK_CONFIG_CUSTOM,
+ TK_CONFIG_END
+} Tk_ConfigTypes;
+
+/*
+ * Possible values for flags argument to Tk_ConfigureWidget:
+ */
+
+#define TK_CONFIG_ARGV_ONLY 1
+#define TK_CONFIG_OBJS 0x80
+
+/*
+ * Possible flag values for Tk_ConfigSpec structures. Any bits at or above
+ * TK_CONFIG_USER_BIT may be used by clients for selecting certain entries.
+ * Before changing any values here, coordinate with tkOldConfig.c
+ * (internal-use-only flags are defined there).
+ */
+
+#define TK_CONFIG_NULL_OK (1 << 0)
+#define TK_CONFIG_COLOR_ONLY (1 << 1)
+#define TK_CONFIG_MONO_ONLY (1 << 2)
+#define TK_CONFIG_DONT_SET_DEFAULT (1 << 3)
+#define TK_CONFIG_OPTION_SPECIFIED (1 << 4)
+#define TK_CONFIG_USER_BIT 0x100
+#endif /* __NO_OLD_CONFIG */
+
+/*
+ * Structure used to specify how to handle argv options.
+ */
+
+typedef struct {
+ CONST86 char *key; /* The key string that flags the option in the
+ * argv array. */
+ int type; /* Indicates option type; see below. */
+ char *src; /* Value to be used in setting dst; usage
+ * depends on type. */
+ char *dst; /* Address of value to be modified; usage
+ * depends on type. */
+ CONST86 char *help; /* Documentation message describing this
+ * option. */
+} Tk_ArgvInfo;
+
+/*
+ * Legal values for the type field of a Tk_ArgvInfo: see the user
+ * documentation for details.
+ */
+
+#define TK_ARGV_CONSTANT 15
+#define TK_ARGV_INT 16
+#define TK_ARGV_STRING 17
+#define TK_ARGV_UID 18
+#define TK_ARGV_REST 19
+#define TK_ARGV_FLOAT 20
+#define TK_ARGV_FUNC 21
+#define TK_ARGV_GENFUNC 22
+#define TK_ARGV_HELP 23
+#define TK_ARGV_CONST_OPTION 24
+#define TK_ARGV_OPTION_VALUE 25
+#define TK_ARGV_OPTION_NAME_VALUE 26
+#define TK_ARGV_END 27
+
+/*
+ * Flag bits for passing to Tk_ParseArgv:
+ */
+
+#define TK_ARGV_NO_DEFAULTS 0x1
+#define TK_ARGV_NO_LEFTOVERS 0x2
+#define TK_ARGV_NO_ABBREV 0x4
+#define TK_ARGV_DONT_SKIP_FIRST_ARG 0x8
+
+/*
+ * Enumerated type for describing actions to be taken in response to a
+ * restrictProc established by Tk_RestrictEvents.
+ */
+
+typedef enum {
+ TK_DEFER_EVENT, TK_PROCESS_EVENT, TK_DISCARD_EVENT
+} Tk_RestrictAction;
+
+/*
+ * Priority levels to pass to Tk_AddOption:
+ */
+
+#define TK_WIDGET_DEFAULT_PRIO 20
+#define TK_STARTUP_FILE_PRIO 40
+#define TK_USER_DEFAULT_PRIO 60
+#define TK_INTERACTIVE_PRIO 80
+#define TK_MAX_PRIO 100
+
+/*
+ * Relief values returned by Tk_GetRelief:
+ */
+
+#define TK_RELIEF_NULL -1
+#define TK_RELIEF_FLAT 0
+#define TK_RELIEF_GROOVE 1
+#define TK_RELIEF_RAISED 2
+#define TK_RELIEF_RIDGE 3
+#define TK_RELIEF_SOLID 4
+#define TK_RELIEF_SUNKEN 5
+
+/*
+ * "Which" argument values for Tk_3DBorderGC:
+ */
+
+#define TK_3D_FLAT_GC 1
+#define TK_3D_LIGHT_GC 2
+#define TK_3D_DARK_GC 3
+
+/*
+ * Special EnterNotify/LeaveNotify "mode" for use in events generated by
+ * tkShare.c. Pick a high enough value that it's unlikely to conflict with
+ * existing values (like NotifyNormal) or any new values defined in the
+ * future.
+ */
+
+#define TK_NOTIFY_SHARE 20
+
+/*
+ * Enumerated type for describing a point by which to anchor something:
+ */
+
+typedef enum {
+ TK_ANCHOR_N, TK_ANCHOR_NE, TK_ANCHOR_E, TK_ANCHOR_SE,
+ TK_ANCHOR_S, TK_ANCHOR_SW, TK_ANCHOR_W, TK_ANCHOR_NW,
+ TK_ANCHOR_CENTER
+} Tk_Anchor;
+
+/*
+ * Enumerated type for describing a style of justification:
+ */
+
+typedef enum {
+ TK_JUSTIFY_LEFT, TK_JUSTIFY_RIGHT, TK_JUSTIFY_CENTER
+} Tk_Justify;
+
+/*
+ * The following structure is used by Tk_GetFontMetrics() to return
+ * information about the properties of a Tk_Font.
+ */
+
+typedef struct Tk_FontMetrics {
+ int ascent; /* The amount in pixels that the tallest
+ * letter sticks up above the baseline, plus
+ * any extra blank space added by the designer
+ * of the font. */
+ int descent; /* The largest amount in pixels that any
+ * letter sticks below the baseline, plus any
+ * extra blank space added by the designer of
+ * the font. */
+ int linespace; /* The sum of the ascent and descent. How far
+ * apart two lines of text in the same font
+ * should be placed so that none of the
+ * characters in one line overlap any of the
+ * characters in the other line. */
+} Tk_FontMetrics;
+
+/*
+ * Flags passed to Tk_MeasureChars:
+ */
+
+#define TK_WHOLE_WORDS 1
+#define TK_AT_LEAST_ONE 2
+#define TK_PARTIAL_OK 4
+
+/*
+ * Flags passed to Tk_ComputeTextLayout:
+ */
+
+#define TK_IGNORE_TABS 8
+#define TK_IGNORE_NEWLINES 16
+
+/*
+ * Widget class procedures used to implement platform specific widget
+ * behavior.
+ */
+
+typedef Window (Tk_ClassCreateProc) (Tk_Window tkwin, Window parent,
+ ClientData instanceData);
+typedef void (Tk_ClassWorldChangedProc) (ClientData instanceData);
+typedef void (Tk_ClassModalProc) (Tk_Window tkwin, XEvent *eventPtr);
+
+typedef struct Tk_ClassProcs {
+ unsigned int size;
+ Tk_ClassWorldChangedProc *worldChangedProc;
+ /* Procedure to invoke when the widget needs
+ * to respond in some way to a change in the
+ * world (font changes, etc.) */
+ Tk_ClassCreateProc *createProc;
+ /* Procedure to invoke when the platform-
+ * dependent window needs to be created. */
+ Tk_ClassModalProc *modalProc;
+ /* Procedure to invoke after all bindings on a
+ * widget have been triggered in order to
+ * handle a modal loop. */
+} Tk_ClassProcs;
+
+/*
+ * Simple accessor for Tk_ClassProcs structure. Checks that the structure is
+ * not NULL, then checks the size field and returns either the requested
+ * field, if present, or NULL if the structure is too small to have the field
+ * (or NULL if the structure is NULL).
+ *
+ * A more general version of this function may be useful if other
+ * size-versioned structure pop up in the future:
+ *
+ * #define Tk_GetField(name, who, which) \
+ * (((who) == NULL) ? NULL :
+ * (((who)->size <= Tk_Offset(name, which)) ? NULL :(name)->which))
+ */
+
+#define Tk_GetClassProc(procs, which) \
+ (((procs) == NULL) ? NULL : \
+ (((procs)->size <= Tk_Offset(Tk_ClassProcs, which)) ? NULL:(procs)->which))
+
+/*
+ * Each geometry manager (the packer, the placer, etc.) is represented by a
+ * structure of the following form, which indicates procedures to invoke in
+ * the geometry manager to carry out certain functions.
+ */
+
+typedef void (Tk_GeomRequestProc) (ClientData clientData, Tk_Window tkwin);
+typedef void (Tk_GeomLostSlaveProc) (ClientData clientData, Tk_Window tkwin);
+
+typedef struct Tk_GeomMgr {
+ const char *name; /* Name of the geometry manager (command used
+ * to invoke it, or name of widget class that
+ * allows embedded widgets). */
+ Tk_GeomRequestProc *requestProc;
+ /* Procedure to invoke when a slave's
+ * requested geometry changes. */
+ Tk_GeomLostSlaveProc *lostSlaveProc;
+ /* Procedure to invoke when a slave is taken
+ * away from one geometry manager by another.
+ * NULL means geometry manager doesn't care
+ * when slaves are lost. */
+} Tk_GeomMgr;
+
+/*
+ * Result values returned by Tk_GetScrollInfo:
+ */
+
+#define TK_SCROLL_MOVETO 1
+#define TK_SCROLL_PAGES 2
+#define TK_SCROLL_UNITS 3
+#define TK_SCROLL_ERROR 4
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Extensions to the X event set
+ *
+ *----------------------------------------------------------------------
+ */
+
+#define VirtualEvent (MappingNotify + 1)
+#define ActivateNotify (MappingNotify + 2)
+#define DeactivateNotify (MappingNotify + 3)
+#define MouseWheelEvent (MappingNotify + 4)
+#define TK_LASTEVENT (MappingNotify + 5)
+
+#define MouseWheelMask (1L << 28)
+#define ActivateMask (1L << 29)
+#define VirtualEventMask (1L << 30)
+
+/*
+ * A virtual event shares most of its fields with the XKeyEvent and
+ * XButtonEvent structures. 99% of the time a virtual event will be an
+ * abstraction of a key or button event, so this structure provides the most
+ * information to the user. The only difference is the changing of the detail
+ * field for a virtual event so that it holds the name of the virtual event
+ * being triggered.
+ *
+ * When using this structure, you should ensure that you zero out all the
+ * fields first using memset() or bzero().
+ */
+
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server. */
+ Bool send_event; /* True if this came from a SendEvent
+ * request. */
+ Display *display; /* Display the event was read from. */
+ Window event; /* Window on which event was requested. */
+ Window root; /* Root window that the event occurred on. */
+ Window subwindow; /* Child window. */
+ Time time; /* Milliseconds. */
+ int x, y; /* Pointer x, y coordinates in event
+ * window. */
+ int x_root, y_root; /* Coordinates relative to root. */
+ unsigned int state; /* Key or button mask */
+ Tk_Uid name; /* Name of virtual event. */
+ Bool same_screen; /* Same screen flag. */
+ Tcl_Obj *user_data; /* Application-specific data reference; Tk
+ * will decrement the reference count *once*
+ * when it has finished processing the
+ * event. */
+} XVirtualEvent;
+
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server. */
+ Bool send_event; /* True if this came from a SendEvent
+ * request. */
+ Display *display; /* Display the event was read from. */
+ Window window; /* Window in which event occurred. */
+} XActivateDeactivateEvent;
+typedef XActivateDeactivateEvent XActivateEvent;
+typedef XActivateDeactivateEvent XDeactivateEvent;
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Macros for querying Tk_Window structures. See the manual entries for
+ * documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#define Tk_Display(tkwin) (((Tk_FakeWin *) (tkwin))->display)
+#define Tk_ScreenNumber(tkwin) (((Tk_FakeWin *) (tkwin))->screenNum)
+#define Tk_Screen(tkwin) \
+ (ScreenOfDisplay(Tk_Display(tkwin), Tk_ScreenNumber(tkwin)))
+#define Tk_Depth(tkwin) (((Tk_FakeWin *) (tkwin))->depth)
+#define Tk_Visual(tkwin) (((Tk_FakeWin *) (tkwin))->visual)
+#define Tk_WindowId(tkwin) (((Tk_FakeWin *) (tkwin))->window)
+#define Tk_PathName(tkwin) (((Tk_FakeWin *) (tkwin))->pathName)
+#define Tk_Name(tkwin) (((Tk_FakeWin *) (tkwin))->nameUid)
+#define Tk_Class(tkwin) (((Tk_FakeWin *) (tkwin))->classUid)
+#define Tk_X(tkwin) (((Tk_FakeWin *) (tkwin))->changes.x)
+#define Tk_Y(tkwin) (((Tk_FakeWin *) (tkwin))->changes.y)
+#define Tk_Width(tkwin) (((Tk_FakeWin *) (tkwin))->changes.width)
+#define Tk_Height(tkwin) \
+ (((Tk_FakeWin *) (tkwin))->changes.height)
+#define Tk_Changes(tkwin) (&((Tk_FakeWin *) (tkwin))->changes)
+#define Tk_Attributes(tkwin) (&((Tk_FakeWin *) (tkwin))->atts)
+#define Tk_IsEmbedded(tkwin) \
+ (((Tk_FakeWin *) (tkwin))->flags & TK_EMBEDDED)
+#define Tk_IsContainer(tkwin) \
+ (((Tk_FakeWin *) (tkwin))->flags & TK_CONTAINER)
+#define Tk_IsMapped(tkwin) \
+ (((Tk_FakeWin *) (tkwin))->flags & TK_MAPPED)
+#define Tk_IsTopLevel(tkwin) \
+ (((Tk_FakeWin *) (tkwin))->flags & TK_TOP_LEVEL)
+#define Tk_HasWrapper(tkwin) \
+ (((Tk_FakeWin *) (tkwin))->flags & TK_HAS_WRAPPER)
+#define Tk_WinManaged(tkwin) \
+ (((Tk_FakeWin *) (tkwin))->flags & TK_WIN_MANAGED)
+#define Tk_TopWinHierarchy(tkwin) \
+ (((Tk_FakeWin *) (tkwin))->flags & TK_TOP_HIERARCHY)
+#define Tk_IsManageable(tkwin) \
+ (((Tk_FakeWin *) (tkwin))->flags & TK_WM_MANAGEABLE)
+#define Tk_ReqWidth(tkwin) (((Tk_FakeWin *) (tkwin))->reqWidth)
+#define Tk_ReqHeight(tkwin) (((Tk_FakeWin *) (tkwin))->reqHeight)
+/* Tk_InternalBorderWidth is deprecated */
+#define Tk_InternalBorderWidth(tkwin) \
+ (((Tk_FakeWin *) (tkwin))->internalBorderLeft)
+#define Tk_InternalBorderLeft(tkwin) \
+ (((Tk_FakeWin *) (tkwin))->internalBorderLeft)
+#define Tk_InternalBorderRight(tkwin) \
+ (((Tk_FakeWin *) (tkwin))->internalBorderRight)
+#define Tk_InternalBorderTop(tkwin) \
+ (((Tk_FakeWin *) (tkwin))->internalBorderTop)
+#define Tk_InternalBorderBottom(tkwin) \
+ (((Tk_FakeWin *) (tkwin))->internalBorderBottom)
+#define Tk_MinReqWidth(tkwin) (((Tk_FakeWin *) (tkwin))->minReqWidth)
+#define Tk_MinReqHeight(tkwin) (((Tk_FakeWin *) (tkwin))->minReqHeight)
+#define Tk_Parent(tkwin) (((Tk_FakeWin *) (tkwin))->parentPtr)
+#define Tk_Colormap(tkwin) (((Tk_FakeWin *) (tkwin))->atts.colormap)
+
+/*
+ * The structure below is needed by the macros above so that they can access
+ * the fields of a Tk_Window. The fields not needed by the macros are declared
+ * as "dummyX". The structure has its own type in order to prevent apps from
+ * accessing Tk_Window fields except using official macros. WARNING!! The
+ * structure definition must be kept consistent with the TkWindow structure in
+ * tkInt.h. If you change one, then change the other. See the declaration in
+ * tkInt.h for documentation on what the fields are used for internally.
+ */
+
+typedef struct Tk_FakeWin {
+ Display *display;
+ char *dummy1; /* dispPtr */
+ int screenNum;
+ Visual *visual;
+ int depth;
+ Window window;
+ char *dummy2; /* childList */
+ char *dummy3; /* lastChildPtr */
+ Tk_Window parentPtr; /* parentPtr */
+ char *dummy4; /* nextPtr */
+ char *dummy5; /* mainPtr */
+ char *pathName;
+ Tk_Uid nameUid;
+ Tk_Uid classUid;
+ XWindowChanges changes;
+ unsigned int dummy6; /* dirtyChanges */
+ XSetWindowAttributes atts;
+ unsigned long dummy7; /* dirtyAtts */
+ unsigned int flags;
+ char *dummy8; /* handlerList */
+#ifdef TK_USE_INPUT_METHODS
+ XIC dummy9; /* inputContext */
+#endif /* TK_USE_INPUT_METHODS */
+ ClientData *dummy10; /* tagPtr */
+ int dummy11; /* numTags */
+ int dummy12; /* optionLevel */
+ char *dummy13; /* selHandlerList */
+ char *dummy14; /* geomMgrPtr */
+ ClientData dummy15; /* geomData */
+ int reqWidth, reqHeight;
+ int internalBorderLeft;
+ char *dummy16; /* wmInfoPtr */
+ char *dummy17; /* classProcPtr */
+ ClientData dummy18; /* instanceData */
+ char *dummy19; /* privatePtr */
+ int internalBorderRight;
+ int internalBorderTop;
+ int internalBorderBottom;
+ int minReqWidth;
+ int minReqHeight;
+#ifdef TK_USE_INPUT_METHODS
+ int dummy20;
+#endif /* TK_USE_INPUT_METHODS */
+ char *dummy21; /* geomMgrName */
+ Tk_Window dummy22; /* maintainerPtr */
+} Tk_FakeWin;
+
+/*
+ * Flag values for TkWindow (and Tk_FakeWin) structures are:
+ *
+ * TK_MAPPED: 1 means window is currently mapped,
+ * 0 means unmapped.
+ * TK_TOP_LEVEL: 1 means this is a top-level widget.
+ * TK_ALREADY_DEAD: 1 means the window is in the process of
+ * being destroyed already.
+ * TK_NEED_CONFIG_NOTIFY: 1 means that the window has been reconfigured
+ * before it was made to exist. At the time of
+ * making it exist a ConfigureNotify event needs
+ * to be generated.
+ * TK_GRAB_FLAG: Used to manage grabs. See tkGrab.c for details
+ * TK_CHECKED_IC: 1 means we've already tried to get an input
+ * context for this window; if the ic field is
+ * NULL it means that there isn't a context for
+ * the field.
+ * TK_DONT_DESTROY_WINDOW: 1 means that Tk_DestroyWindow should not
+ * invoke XDestroyWindow to destroy this widget's
+ * X window. The flag is set when the window has
+ * already been destroyed elsewhere (e.g. by
+ * another application) or when it will be
+ * destroyed later (e.g. by destroying its parent)
+ * TK_WM_COLORMAP_WINDOW: 1 means that this window has at some time
+ * appeared in the WM_COLORMAP_WINDOWS property
+ * for its toplevel, so we have to remove it from
+ * that property if the window is deleted and the
+ * toplevel isn't.
+ * TK_EMBEDDED: 1 means that this window (which must be a
+ * toplevel) is not a free-standing window but
+ * rather is embedded in some other application.
+ * TK_CONTAINER: 1 means that this window is a container, and
+ * that some other application (either in this
+ * process or elsewhere) may be embedding itself
+ * inside the window.
+ * TK_BOTH_HALVES: 1 means that this window is used for
+ * application embedding (either as container or
+ * embedded application), and both the containing
+ * and embedded halves are associated with
+ * windows in this particular process.
+ * TK_WRAPPER: 1 means that this window is the extra wrapper
+ * window created around a toplevel to hold the
+ * menubar under Unix. See tkUnixWm.c for more
+ * information.
+ * TK_REPARENTED: 1 means that this window has been reparented
+ * so that as far as the window system is
+ * concerned it isn't a child of its Tk parent.
+ * Initially this is used only for special Unix
+ * menubar windows.
+ * TK_ANONYMOUS_WINDOW: 1 means that this window has no name, and is
+ * thus not accessible from Tk.
+ * TK_HAS_WRAPPER 1 means that this window has a wrapper window
+ * TK_WIN_MANAGED 1 means that this window is a child of the root
+ * window, and is managed by the window manager.
+ * TK_TOP_HIERARCHY 1 means this window is at the top of a physical
+ * window hierarchy within this process, i.e. the
+ * window's parent either doesn't exist or is not
+ * owned by this Tk application.
+ * TK_PROP_PROPCHANGE 1 means that PropertyNotify events in the
+ * window's children should propagate up to this
+ * window.
+ * TK_WM_MANAGEABLE 1 marks a window as capable of being converted
+ * into a toplevel using [wm manage].
+ */
+
+#define TK_MAPPED 1
+#define TK_TOP_LEVEL 2
+#define TK_ALREADY_DEAD 4
+#define TK_NEED_CONFIG_NOTIFY 8
+#define TK_GRAB_FLAG 0x10
+#define TK_CHECKED_IC 0x20
+#define TK_DONT_DESTROY_WINDOW 0x40
+#define TK_WM_COLORMAP_WINDOW 0x80
+#define TK_EMBEDDED 0x100
+#define TK_CONTAINER 0x200
+#define TK_BOTH_HALVES 0x400
+#define TK_WRAPPER 0x1000
+#define TK_REPARENTED 0x2000
+#define TK_ANONYMOUS_WINDOW 0x4000
+#define TK_HAS_WRAPPER 0x8000
+#define TK_WIN_MANAGED 0x10000
+#define TK_TOP_HIERARCHY 0x20000
+#define TK_PROP_PROPCHANGE 0x40000
+#define TK_WM_MANAGEABLE 0x80000
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Procedure prototypes and structures used for defining new canvas items:
+ *
+ *----------------------------------------------------------------------
+ */
+
+typedef enum {
+ TK_STATE_NULL = -1, TK_STATE_ACTIVE, TK_STATE_DISABLED,
+ TK_STATE_NORMAL, TK_STATE_HIDDEN
+} Tk_State;
+
+typedef struct Tk_SmoothMethod {
+ CONST86 char *name;
+ int (*coordProc) (Tk_Canvas canvas, double *pointPtr, int numPoints,
+ int numSteps, XPoint xPoints[], double dblPoints[]);
+ void (*postscriptProc) (Tcl_Interp *interp, Tk_Canvas canvas,
+ double *coordPtr, int numPoints, int numSteps);
+} Tk_SmoothMethod;
+
+/*
+ * For each item in a canvas widget there exists one record with the following
+ * structure. Each actual item is represented by a record with the following
+ * stuff at its beginning, plus additional type-specific stuff after that.
+ */
+
+#define TK_TAG_SPACE 3
+
+typedef struct Tk_Item {
+ int id; /* Unique identifier for this item (also
+ * serves as first tag for item). */
+ struct Tk_Item *nextPtr; /* Next in display list of all items in this
+ * canvas. Later items in list are drawn on
+ * top of earlier ones. */
+ Tk_Uid staticTagSpace[TK_TAG_SPACE];
+ /* Built-in space for limited # of tags. */
+ Tk_Uid *tagPtr; /* Pointer to array of tags. Usually points to
+ * staticTagSpace, but may point to malloc-ed
+ * space if there are lots of tags. */
+ int tagSpace; /* Total amount of tag space available at
+ * tagPtr. */
+ int numTags; /* Number of tag slots actually used at
+ * *tagPtr. */
+ struct Tk_ItemType *typePtr;/* Table of procedures that implement this
+ * type of item. */
+ int x1, y1, x2, y2; /* Bounding box for item, in integer canvas
+ * units. Set by item-specific code and
+ * guaranteed to contain every pixel drawn in
+ * item. Item area includes x1 and y1 but not
+ * x2 and y2. */
+ struct Tk_Item *prevPtr; /* Previous in display list of all items in
+ * this canvas. Later items in list are drawn
+ * just below earlier ones. */
+ Tk_State state; /* State of item. */
+ char *reserved1; /* reserved for future use */
+ int redraw_flags; /* Some flags used in the canvas */
+
+ /*
+ *------------------------------------------------------------------
+ * Starting here is additional type-specific stuff; see the declarations
+ * for individual types to see what is part of each type. The actual space
+ * below is determined by the "itemInfoSize" of the type's Tk_ItemType
+ * record.
+ *------------------------------------------------------------------
+ */
+} Tk_Item;
+
+/*
+ * Flag bits for canvases (redraw_flags):
+ *
+ * TK_ITEM_STATE_DEPENDANT - 1 means that object needs to be redrawn if the
+ * canvas state changes.
+ * TK_ITEM_DONT_REDRAW - 1 means that the object redraw is already been
+ * prepared, so the general canvas code doesn't
+ * need to do that any more.
+ */
+
+#define TK_ITEM_STATE_DEPENDANT 1
+#define TK_ITEM_DONT_REDRAW 2
+
+/*
+ * Records of the following type are used to describe a type of item (e.g.
+ * lines, circles, etc.) that can form part of a canvas widget.
+ */
+
+#ifdef USE_OLD_CANVAS
+typedef int (Tk_ItemCreateProc)(Tcl_Interp *interp, Tk_Canvas canvas,
+ Tk_Item *itemPtr, int argc, char **argv);
+typedef int (Tk_ItemConfigureProc)(Tcl_Interp *interp, Tk_Canvas canvas,
+ Tk_Item *itemPtr, int argc, char **argv, int flags);
+typedef int (Tk_ItemCoordProc)(Tcl_Interp *interp, Tk_Canvas canvas,
+ Tk_Item *itemPtr, int argc, char **argv);
+#else
+typedef int (Tk_ItemCreateProc)(Tcl_Interp *interp, Tk_Canvas canvas,
+ Tk_Item *itemPtr, int argc, Tcl_Obj *const objv[]);
+typedef int (Tk_ItemConfigureProc)(Tcl_Interp *interp, Tk_Canvas canvas,
+ Tk_Item *itemPtr, int argc, Tcl_Obj *const objv[],
+ int flags);
+typedef int (Tk_ItemCoordProc)(Tcl_Interp *interp, Tk_Canvas canvas,
+ Tk_Item *itemPtr, int argc, Tcl_Obj *const argv[]);
+#endif /* USE_OLD_CANVAS */
+typedef void (Tk_ItemDeleteProc)(Tk_Canvas canvas, Tk_Item *itemPtr,
+ Display *display);
+typedef void (Tk_ItemDisplayProc)(Tk_Canvas canvas, Tk_Item *itemPtr,
+ Display *display, Drawable dst, int x, int y, int width,
+ int height);
+typedef double (Tk_ItemPointProc)(Tk_Canvas canvas, Tk_Item *itemPtr,
+ double *pointPtr);
+typedef int (Tk_ItemAreaProc)(Tk_Canvas canvas, Tk_Item *itemPtr,
+ double *rectPtr);
+typedef int (Tk_ItemPostscriptProc)(Tcl_Interp *interp, Tk_Canvas canvas,
+ Tk_Item *itemPtr, int prepass);
+typedef void (Tk_ItemScaleProc)(Tk_Canvas canvas, Tk_Item *itemPtr,
+ double originX, double originY, double scaleX,
+ double scaleY);
+typedef void (Tk_ItemTranslateProc)(Tk_Canvas canvas, Tk_Item *itemPtr,
+ double deltaX, double deltaY);
+#ifdef USE_OLD_CANVAS
+typedef int (Tk_ItemIndexProc)(Tcl_Interp *interp, Tk_Canvas canvas,
+ Tk_Item *itemPtr, char *indexString, int *indexPtr);
+#else
+typedef int (Tk_ItemIndexProc)(Tcl_Interp *interp, Tk_Canvas canvas,
+ Tk_Item *itemPtr, Tcl_Obj *indexString, int *indexPtr);
+#endif /* USE_OLD_CANVAS */
+typedef void (Tk_ItemCursorProc)(Tk_Canvas canvas, Tk_Item *itemPtr,
+ int index);
+typedef int (Tk_ItemSelectionProc)(Tk_Canvas canvas, Tk_Item *itemPtr,
+ int offset, char *buffer, int maxBytes);
+#ifdef USE_OLD_CANVAS
+typedef void (Tk_ItemInsertProc)(Tk_Canvas canvas, Tk_Item *itemPtr,
+ int beforeThis, char *string);
+#else
+typedef void (Tk_ItemInsertProc)(Tk_Canvas canvas, Tk_Item *itemPtr,
+ int beforeThis, Tcl_Obj *string);
+#endif /* USE_OLD_CANVAS */
+typedef void (Tk_ItemDCharsProc)(Tk_Canvas canvas, Tk_Item *itemPtr,
+ int first, int last);
+
+#ifndef __NO_OLD_CONFIG
+
+typedef struct Tk_ItemType {
+ CONST86 char *name; /* The name of this type of item, such as
+ * "line". */
+ int itemSize; /* Total amount of space needed for item's
+ * record. */
+ Tk_ItemCreateProc *createProc;
+ /* Procedure to create a new item of this
+ * type. */
+ CONST86 Tk_ConfigSpec *configSpecs; /* Pointer to array of configuration specs for
+ * this type. Used for returning configuration
+ * info. */
+ Tk_ItemConfigureProc *configProc;
+ /* Procedure to call to change configuration
+ * options. */
+ Tk_ItemCoordProc *coordProc;/* Procedure to call to get and set the item's
+ * coordinates. */
+ Tk_ItemDeleteProc *deleteProc;
+ /* Procedure to delete existing item of this
+ * type. */
+ Tk_ItemDisplayProc *displayProc;
+ /* Procedure to display items of this type. */
+ int alwaysRedraw; /* Non-zero means displayProc should be called
+ * even when the item has been moved
+ * off-screen. */
+ Tk_ItemPointProc *pointProc;/* Computes distance from item to a given
+ * point. */
+ Tk_ItemAreaProc *areaProc; /* Computes whether item is inside, outside,
+ * or overlapping an area. */
+ Tk_ItemPostscriptProc *postscriptProc;
+ /* Procedure to write a Postscript description
+ * for items of this type. */
+ Tk_ItemScaleProc *scaleProc;/* Procedure to rescale items of this type. */
+ Tk_ItemTranslateProc *translateProc;
+ /* Procedure to translate items of this
+ * type. */
+ Tk_ItemIndexProc *indexProc;/* Procedure to determine index of indicated
+ * character. NULL if item doesn't support
+ * indexing. */
+ Tk_ItemCursorProc *icursorProc;
+ /* Procedure to set insert cursor posn to just
+ * before a given position. */
+ Tk_ItemSelectionProc *selectionProc;
+ /* Procedure to return selection (in STRING
+ * format) when it is in this item. */
+ Tk_ItemInsertProc *insertProc;
+ /* Procedure to insert something into an
+ * item. */
+ Tk_ItemDCharsProc *dCharsProc;
+ /* Procedure to delete characters from an
+ * item. */
+ struct Tk_ItemType *nextPtr;/* Used to link types together into a list. */
+ char *reserved1; /* Reserved for future extension. */
+ int reserved2; /* Carefully compatible with */
+ char *reserved3; /* Jan Nijtmans dash patch */
+ char *reserved4;
+} Tk_ItemType;
+
+/*
+ * Flag (used in the alwaysRedraw field) to say whether an item supports
+ * point-level manipulation like the line and polygon items.
+ */
+
+#define TK_MOVABLE_POINTS 2
+
+#endif /* __NO_OLD_CONFIG */
+
+/*
+ * The following structure provides information about the selection and the
+ * insertion cursor. It is needed by only a few items, such as those that
+ * display text. It is shared by the generic canvas code and the item-specific
+ * code, but most of the fields should be written only by the canvas generic
+ * code.
+ */
+
+typedef struct Tk_CanvasTextInfo {
+ Tk_3DBorder selBorder; /* Border and background for selected
+ * characters. Read-only to items.*/
+ int selBorderWidth; /* Width of border around selection. Read-only
+ * to items. */
+ XColor *selFgColorPtr; /* Foreground color for selected text.
+ * Read-only to items. */
+ Tk_Item *selItemPtr; /* Pointer to selected item. NULL means
+ * selection isn't in this canvas. Writable by
+ * items. */
+ int selectFirst; /* Character index of first selected
+ * character. Writable by items. */
+ int selectLast; /* Character index of last selected character.
+ * Writable by items. */
+ Tk_Item *anchorItemPtr; /* Item corresponding to "selectAnchor": not
+ * necessarily selItemPtr. Read-only to
+ * items. */
+ int selectAnchor; /* Character index of fixed end of selection
+ * (i.e. "select to" operation will use this
+ * as one end of the selection). Writable by
+ * items. */
+ Tk_3DBorder insertBorder; /* Used to draw vertical bar for insertion
+ * cursor. Read-only to items. */
+ int insertWidth; /* Total width of insertion cursor. Read-only
+ * to items. */
+ int insertBorderWidth; /* Width of 3-D border around insert cursor.
+ * Read-only to items. */
+ Tk_Item *focusItemPtr; /* Item that currently has the input focus, or
+ * NULL if no such item. Read-only to items. */
+ int gotFocus; /* Non-zero means that the canvas widget has
+ * the input focus. Read-only to items.*/
+ int cursorOn; /* Non-zero means that an insertion cursor
+ * should be displayed in focusItemPtr.
+ * Read-only to items.*/
+} Tk_CanvasTextInfo;
+
+/*
+ * Structures used for Dashing and Outline.
+ */
+
+typedef struct Tk_Dash {
+ int number;
+ union {
+ char *pt;
+ char array[sizeof(char *)];
+ } pattern;
+} Tk_Dash;
+
+typedef struct Tk_TSOffset {
+ int flags; /* Flags; see below for possible values */
+ int xoffset; /* x offset */
+ int yoffset; /* y offset */
+} Tk_TSOffset;
+
+/*
+ * Bit fields in Tk_TSOffset->flags:
+ */
+
+#define TK_OFFSET_INDEX 1
+#define TK_OFFSET_RELATIVE 2
+#define TK_OFFSET_LEFT 4
+#define TK_OFFSET_CENTER 8
+#define TK_OFFSET_RIGHT 16
+#define TK_OFFSET_TOP 32
+#define TK_OFFSET_MIDDLE 64
+#define TK_OFFSET_BOTTOM 128
+
+typedef struct Tk_Outline {
+ GC gc; /* Graphics context. */
+ double width; /* Width of outline. */
+ double activeWidth; /* Width of outline. */
+ double disabledWidth; /* Width of outline. */
+ int offset; /* Dash offset. */
+ Tk_Dash dash; /* Dash pattern. */
+ Tk_Dash activeDash; /* Dash pattern if state is active. */
+ Tk_Dash disabledDash; /* Dash pattern if state is disabled. */
+ void *reserved1; /* Reserved for future expansion. */
+ void *reserved2;
+ void *reserved3;
+ Tk_TSOffset tsoffset; /* Stipple offset for outline. */
+ XColor *color; /* Outline color. */
+ XColor *activeColor; /* Outline color if state is active. */
+ XColor *disabledColor; /* Outline color if state is disabled. */
+ Pixmap stipple; /* Outline Stipple pattern. */
+ Pixmap activeStipple; /* Outline Stipple pattern if state is
+ * active. */
+ Pixmap disabledStipple; /* Outline Stipple pattern if state is
+ * disabled. */
+} Tk_Outline;
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Procedure prototypes and structures used for managing images:
+ *
+ *----------------------------------------------------------------------
+ */
+
+typedef struct Tk_ImageType Tk_ImageType;
+#ifdef USE_OLD_IMAGE
+typedef int (Tk_ImageCreateProc) (Tcl_Interp *interp, char *name, int argc,
+ char **argv, Tk_ImageType *typePtr, Tk_ImageMaster master,
+ ClientData *masterDataPtr);
+#else
+typedef int (Tk_ImageCreateProc) (Tcl_Interp *interp, CONST86 char *name, int objc,
+ Tcl_Obj *const objv[], CONST86 Tk_ImageType *typePtr, Tk_ImageMaster master,
+ ClientData *masterDataPtr);
+#endif /* USE_OLD_IMAGE */
+typedef ClientData (Tk_ImageGetProc) (Tk_Window tkwin, ClientData masterData);
+typedef void (Tk_ImageDisplayProc) (ClientData instanceData, Display *display,
+ Drawable drawable, int imageX, int imageY, int width, int height,
+ int drawableX, int drawableY);
+typedef void (Tk_ImageFreeProc) (ClientData instanceData, Display *display);
+typedef void (Tk_ImageDeleteProc) (ClientData masterData);
+typedef void (Tk_ImageChangedProc) (ClientData clientData, int x, int y,
+ int width, int height, int imageWidth, int imageHeight);
+typedef int (Tk_ImagePostscriptProc) (ClientData clientData,
+ Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo psinfo,
+ int x, int y, int width, int height, int prepass);
+
+/*
+ * The following structure represents a particular type of image (bitmap, xpm
+ * image, etc.). It provides information common to all images of that type,
+ * such as the type name and a collection of procedures in the image manager
+ * that respond to various events. Each image manager is represented by one of
+ * these structures.
+ */
+
+struct Tk_ImageType {
+ CONST86 char *name; /* Name of image type. */
+ Tk_ImageCreateProc *createProc;
+ /* Procedure to call to create a new image of
+ * this type. */
+ Tk_ImageGetProc *getProc; /* Procedure to call the first time
+ * Tk_GetImage is called in a new way (new
+ * visual or screen). */
+ Tk_ImageDisplayProc *displayProc;
+ /* Call to draw image, in response to
+ * Tk_RedrawImage calls. */
+ Tk_ImageFreeProc *freeProc; /* Procedure to call whenever Tk_FreeImage is
+ * called to release an instance of an
+ * image. */
+ Tk_ImageDeleteProc *deleteProc;
+ /* Procedure to call to delete image. It will
+ * not be called until after freeProc has been
+ * called for each instance of the image. */
+ Tk_ImagePostscriptProc *postscriptProc;
+ /* Procedure to call to produce postscript
+ * output for the image. */
+ struct Tk_ImageType *nextPtr;
+ /* Next in list of all image types currently
+ * known. Filled in by Tk, not by image
+ * manager. */
+ char *reserved; /* reserved for future expansion */
+};
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Additional definitions used to manage images of type "photo".
+ *
+ *----------------------------------------------------------------------
+ */
+
+/*
+ * The following type is used to identify a particular photo image to be
+ * manipulated:
+ */
+
+typedef void *Tk_PhotoHandle;
+
+/*
+ * The following structure describes a block of pixels in memory:
+ */
+
+typedef struct Tk_PhotoImageBlock {
+ unsigned char *pixelPtr; /* Pointer to the first pixel. */
+ int width; /* Width of block, in pixels. */
+ int height; /* Height of block, in pixels. */
+ int pitch; /* Address difference between corresponding
+ * pixels in successive lines. */
+ int pixelSize; /* Address difference between successive
+ * pixels in the same line. */
+ int offset[4]; /* Address differences between the red, green,
+ * blue and alpha components of the pixel and
+ * the pixel as a whole. */
+} Tk_PhotoImageBlock;
+
+/*
+ * The following values control how blocks are combined into photo images when
+ * the alpha component of a pixel is not 255, a.k.a. the compositing rule.
+ */
+
+#define TK_PHOTO_COMPOSITE_OVERLAY 0
+#define TK_PHOTO_COMPOSITE_SET 1
+
+/*
+ * Procedure prototypes and structures used in reading and writing photo
+ * images:
+ */
+
+typedef struct Tk_PhotoImageFormat Tk_PhotoImageFormat;
+#ifdef USE_OLD_IMAGE
+typedef int (Tk_ImageFileMatchProc) (Tcl_Channel chan, char *fileName,
+ char *formatString, int *widthPtr, int *heightPtr);
+typedef int (Tk_ImageStringMatchProc) (char *string, char *formatString,
+ int *widthPtr, int *heightPtr);
+typedef int (Tk_ImageFileReadProc) (Tcl_Interp *interp, Tcl_Channel chan,
+ char *fileName, char *formatString, Tk_PhotoHandle imageHandle,
+ int destX, int destY, int width, int height, int srcX, int srcY);
+typedef int (Tk_ImageStringReadProc) (Tcl_Interp *interp, char *string,
+ char *formatString, Tk_PhotoHandle imageHandle, int destX, int destY,
+ int width, int height, int srcX, int srcY);
+typedef int (Tk_ImageFileWriteProc) (Tcl_Interp *interp, char *fileName,
+ char *formatString, Tk_PhotoImageBlock *blockPtr);
+typedef int (Tk_ImageStringWriteProc) (Tcl_Interp *interp,
+ Tcl_DString *dataPtr, char *formatString, Tk_PhotoImageBlock *blockPtr);
+#else
+typedef int (Tk_ImageFileMatchProc) (Tcl_Channel chan, const char *fileName,
+ Tcl_Obj *format, int *widthPtr, int *heightPtr, Tcl_Interp *interp);
+typedef int (Tk_ImageStringMatchProc) (Tcl_Obj *dataObj, Tcl_Obj *format,
+ int *widthPtr, int *heightPtr, Tcl_Interp *interp);
+typedef int (Tk_ImageFileReadProc) (Tcl_Interp *interp, Tcl_Channel chan,
+ const char *fileName, Tcl_Obj *format, Tk_PhotoHandle imageHandle,
+ int destX, int destY, int width, int height, int srcX, int srcY);
+typedef int (Tk_ImageStringReadProc) (Tcl_Interp *interp, Tcl_Obj *dataObj,
+ Tcl_Obj *format, Tk_PhotoHandle imageHandle, int destX, int destY,
+ int width, int height, int srcX, int srcY);
+typedef int (Tk_ImageFileWriteProc) (Tcl_Interp *interp, const char *fileName,
+ Tcl_Obj *format, Tk_PhotoImageBlock *blockPtr);
+typedef int (Tk_ImageStringWriteProc) (Tcl_Interp *interp, Tcl_Obj *format,
+ Tk_PhotoImageBlock *blockPtr);
+#endif /* USE_OLD_IMAGE */
+
+/*
+ * The following structure represents a particular file format for storing
+ * images (e.g., PPM, GIF, JPEG, etc.). It provides information to allow image
+ * files of that format to be recognized and read into a photo image.
+ */
+
+struct Tk_PhotoImageFormat {
+ CONST86 char *name; /* Name of image file format */
+ Tk_ImageFileMatchProc *fileMatchProc;
+ /* Procedure to call to determine whether an
+ * image file matches this format. */
+ Tk_ImageStringMatchProc *stringMatchProc;
+ /* Procedure to call to determine whether the
+ * data in a string matches this format. */
+ Tk_ImageFileReadProc *fileReadProc;
+ /* Procedure to call to read data from an
+ * image file into a photo image. */
+ Tk_ImageStringReadProc *stringReadProc;
+ /* Procedure to call to read data from a
+ * string into a photo image. */
+ Tk_ImageFileWriteProc *fileWriteProc;
+ /* Procedure to call to write data from a
+ * photo image to a file. */
+ Tk_ImageStringWriteProc *stringWriteProc;
+ /* Procedure to call to obtain a string
+ * representation of the data in a photo
+ * image.*/
+ struct Tk_PhotoImageFormat *nextPtr;
+ /* Next in list of all photo image formats
+ * currently known. Filled in by Tk, not by
+ * image format handler. */
+};
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Procedure prototypes and structures used for managing styles:
+ *
+ *----------------------------------------------------------------------
+ */
+
+/*
+ * Style support version tag.
+ */
+
+#define TK_STYLE_VERSION_1 0x1
+#define TK_STYLE_VERSION TK_STYLE_VERSION_1
+
+/*
+ * The following structures and prototypes are used as static templates to
+ * declare widget elements.
+ */
+
+typedef void (Tk_GetElementSizeProc) (ClientData clientData, char *recordPtr,
+ const Tk_OptionSpec **optionsPtr, Tk_Window tkwin, int width,
+ int height, int inner, int *widthPtr, int *heightPtr);
+typedef void (Tk_GetElementBoxProc) (ClientData clientData, char *recordPtr,
+ const Tk_OptionSpec **optionsPtr, Tk_Window tkwin, int x, int y,
+ int width, int height, int inner, int *xPtr, int *yPtr, int *widthPtr,
+ int *heightPtr);
+typedef int (Tk_GetElementBorderWidthProc) (ClientData clientData,
+ char *recordPtr, const Tk_OptionSpec **optionsPtr, Tk_Window tkwin);
+typedef void (Tk_DrawElementProc) (ClientData clientData, char *recordPtr,
+ const Tk_OptionSpec **optionsPtr, Tk_Window tkwin, Drawable d, int x,
+ int y, int width, int height, int state);
+
+typedef struct Tk_ElementOptionSpec {
+ char *name; /* Name of the required option. */
+ Tk_OptionType type; /* Accepted option type. TK_OPTION_END means
+ * any. */
+} Tk_ElementOptionSpec;
+
+typedef struct Tk_ElementSpec {
+ int version; /* Version of the style support. */
+ char *name; /* Name of element. */
+ Tk_ElementOptionSpec *options;
+ /* List of required options. Last one's name
+ * must be NULL. */
+ Tk_GetElementSizeProc *getSize;
+ /* Compute the external (resp. internal) size
+ * of the element from its desired internal
+ * (resp. external) size. */
+ Tk_GetElementBoxProc *getBox;
+ /* Compute the inscribed or bounding boxes
+ * within a given area. */
+ Tk_GetElementBorderWidthProc *getBorderWidth;
+ /* Return the element's internal border width.
+ * Mostly useful for widgets. */
+ Tk_DrawElementProc *draw; /* Draw the element in the given bounding
+ * box. */
+} Tk_ElementSpec;
+
+/*
+ * Element state flags. Can be OR'ed.
+ */
+
+#define TK_ELEMENT_STATE_ACTIVE 1<<0
+#define TK_ELEMENT_STATE_DISABLED 1<<1
+#define TK_ELEMENT_STATE_FOCUS 1<<2
+#define TK_ELEMENT_STATE_PRESSED 1<<3
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * The definitions below provide backward compatibility for functions and
+ * types related to event handling that used to be in Tk but have moved to
+ * Tcl.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#define TK_READABLE TCL_READABLE
+#define TK_WRITABLE TCL_WRITABLE
+#define TK_EXCEPTION TCL_EXCEPTION
+
+#define TK_DONT_WAIT TCL_DONT_WAIT
+#define TK_X_EVENTS TCL_WINDOW_EVENTS
+#define TK_WINDOW_EVENTS TCL_WINDOW_EVENTS
+#define TK_FILE_EVENTS TCL_FILE_EVENTS
+#define TK_TIMER_EVENTS TCL_TIMER_EVENTS
+#define TK_IDLE_EVENTS TCL_IDLE_EVENTS
+#define TK_ALL_EVENTS TCL_ALL_EVENTS
+
+#define Tk_IdleProc Tcl_IdleProc
+#define Tk_FileProc Tcl_FileProc
+#define Tk_TimerProc Tcl_TimerProc
+#define Tk_TimerToken Tcl_TimerToken
+
+#define Tk_BackgroundError Tcl_BackgroundError
+#define Tk_CancelIdleCall Tcl_CancelIdleCall
+#define Tk_CreateFileHandler Tcl_CreateFileHandler
+#define Tk_CreateTimerHandler Tcl_CreateTimerHandler
+#define Tk_DeleteFileHandler Tcl_DeleteFileHandler
+#define Tk_DeleteTimerHandler Tcl_DeleteTimerHandler
+#define Tk_DoOneEvent Tcl_DoOneEvent
+#define Tk_DoWhenIdle Tcl_DoWhenIdle
+#define Tk_Sleep Tcl_Sleep
+
+/* Additional stuff that has moved to Tcl: */
+
+#define Tk_EventuallyFree Tcl_EventuallyFree
+#define Tk_FreeProc Tcl_FreeProc
+#define Tk_Preserve Tcl_Preserve
+#define Tk_Release Tcl_Release
+
+/* Removed Tk_Main, use macro instead */
+#if defined(_WIN32) || defined(__CYGWIN__)
+#define Tk_Main(argc, argv, proc) Tk_MainEx(argc, argv, proc, \
+ (Tcl_FindExecutable(0), (Tcl_CreateInterp)()))
+#else
+#define Tk_Main(argc, argv, proc) Tk_MainEx(argc, argv, proc, \
+ (Tcl_FindExecutable(argv[0]), (Tcl_CreateInterp)()))
+#endif
+const char * Tk_InitStubs(Tcl_Interp *interp, const char *version,
+ int exact);
+EXTERN const char * Tk_PkgInitStubsCheck(Tcl_Interp *interp,
+ const char *version, int exact);
+
+#ifndef USE_TK_STUBS
+#define Tk_InitStubs(interp, version, exact) \
+ Tk_PkgInitStubsCheck(interp, version, exact)
+#endif /* USE_TK_STUBS */
+
+#define Tk_InitImageArgs(interp, argc, argv) /**/
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Additional procedure types defined by Tk.
+ *
+ *----------------------------------------------------------------------
+ */
+
+typedef int (Tk_ErrorProc) (ClientData clientData, XErrorEvent *errEventPtr);
+typedef void (Tk_EventProc) (ClientData clientData, XEvent *eventPtr);
+typedef int (Tk_GenericProc) (ClientData clientData, XEvent *eventPtr);
+typedef int (Tk_ClientMessageProc) (Tk_Window tkwin, XEvent *eventPtr);
+typedef int (Tk_GetSelProc) (ClientData clientData, Tcl_Interp *interp,
+ CONST86 char *portion);
+typedef void (Tk_LostSelProc) (ClientData clientData);
+typedef Tk_RestrictAction (Tk_RestrictProc) (ClientData clientData,
+ XEvent *eventPtr);
+typedef int (Tk_SelectionProc) (ClientData clientData, int offset,
+ char *buffer, int maxBytes);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Platform independent exported procedures and variables.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#include "tkDecls.h"
+
+#ifdef USE_OLD_IMAGE
+#undef Tk_CreateImageType
+#define Tk_CreateImageType Tk_CreateOldImageType
+#undef Tk_CreatePhotoImageFormat
+#define Tk_CreatePhotoImageFormat Tk_CreateOldPhotoImageFormat
+#endif /* USE_OLD_IMAGE */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Allow users to say that they don't want to alter their source to add extra
+ * arguments to Tk_PhotoPutBlock() et al; DO NOT DEFINE THIS WHEN BUILDING TK.
+ *
+ * This goes after the inclusion of the stubbed-decls so that the declarations
+ * of what is actually there can be correct.
+ */
+
+#ifdef USE_COMPOSITELESS_PHOTO_PUT_BLOCK
+# ifdef Tk_PhotoPutBlock
+# undef Tk_PhotoPutBlock
+# endif
+# define Tk_PhotoPutBlock Tk_PhotoPutBlock_NoComposite
+# ifdef Tk_PhotoPutZoomedBlock
+# undef Tk_PhotoPutZoomedBlock
+# endif
+# define Tk_PhotoPutZoomedBlock Tk_PhotoPutZoomedBlock_NoComposite
+# define USE_PANIC_ON_PHOTO_ALLOC_FAILURE
+#else /* !USE_COMPOSITELESS_PHOTO_PUT_BLOCK */
+# ifdef USE_PANIC_ON_PHOTO_ALLOC_FAILURE
+# ifdef Tk_PhotoPutBlock
+# undef Tk_PhotoPutBlock
+# endif
+# define Tk_PhotoPutBlock Tk_PhotoPutBlock_Panic
+# ifdef Tk_PhotoPutZoomedBlock
+# undef Tk_PhotoPutZoomedBlock
+# endif
+# define Tk_PhotoPutZoomedBlock Tk_PhotoPutZoomedBlock_Panic
+# endif /* USE_PANIC_ON_PHOTO_ALLOC_FAILURE */
+#endif /* USE_COMPOSITELESS_PHOTO_PUT_BLOCK */
+#ifdef USE_PANIC_ON_PHOTO_ALLOC_FAILURE
+# ifdef Tk_PhotoExpand
+# undef Tk_PhotoExpand
+# endif
+# define Tk_PhotoExpand Tk_PhotoExpand_Panic
+# ifdef Tk_PhotoSetSize
+# undef Tk_PhotoSetSize
+# endif
+# define Tk_PhotoSetSize Tk_PhotoSetSize_Panic
+#endif /* USE_PANIC_ON_PHOTO_ALLOC_FAILURE */
+
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLIMPORT
+
+#endif /* RC_INVOKED */
+
+/*
+ * end block for C++
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _TK */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tk3d.c b/tk8.6/generic/tk3d.c
new file mode 100644
index 0000000..987bace
--- /dev/null
+++ b/tk8.6/generic/tk3d.c
@@ -0,0 +1,1398 @@
+/*
+ * tk3d.c --
+ *
+ * This module provides procedures to draw borders in the
+ * three-dimensional Motif style.
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "tkInt.h"
+#include "tk3d.h"
+
+/*
+ * The following table defines the string values for reliefs, which are used
+ * by Tk_GetReliefFromObj.
+ */
+
+static const char *const reliefStrings[] = {
+ "flat", "groove", "raised", "ridge", "solid", "sunken", NULL
+};
+
+/*
+ * Forward declarations for functions defined in this file:
+ */
+
+static void BorderInit(TkDisplay *dispPtr);
+static void DupBorderObjProc(Tcl_Obj *srcObjPtr,
+ Tcl_Obj *dupObjPtr);
+static void FreeBorderObj(Tcl_Obj *objPtr);
+static void FreeBorderObjProc(Tcl_Obj *objPtr);
+static int Intersect(XPoint *a1Ptr, XPoint *a2Ptr,
+ XPoint *b1Ptr, XPoint *b2Ptr, XPoint *iPtr);
+static void InitBorderObj(Tcl_Obj *objPtr);
+static void ShiftLine(XPoint *p1Ptr, XPoint *p2Ptr,
+ int distance, XPoint *p3Ptr);
+
+/*
+ * The following structure defines the implementation of the "border" Tcl
+ * object, used for drawing. The border object remembers the hash table entry
+ * associated with a border. The actual allocation and deallocation of the
+ * border should be done by the configuration package when the border option
+ * is set.
+ */
+
+const Tcl_ObjType tkBorderObjType = {
+ "border", /* name */
+ FreeBorderObjProc, /* freeIntRepProc */
+ DupBorderObjProc, /* dupIntRepProc */
+ NULL, /* updateStringProc */
+ NULL /* setFromAnyProc */
+};
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_Alloc3DBorderFromObj --
+ *
+ * Given a Tcl_Obj *, map the value to a corresponding Tk_3DBorder
+ * structure based on the tkwin given.
+ *
+ * Results:
+ * The return value is a token for a data structure describing a 3-D
+ * border. This token may be passed to functions such as
+ * Tk_Draw3DRectangle and Tk_Free3DBorder. If an error prevented the
+ * border from being created then NULL is returned and an error message
+ * will be left in the interp's result.
+ *
+ * Side effects:
+ * The border is added to an internal database with a reference count.
+ * For each call to this function, there should eventually be a call to
+ * FreeBorderObj so that the database is cleaned up when borders aren't
+ * in use anymore.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_3DBorder
+Tk_Alloc3DBorderFromObj(
+ Tcl_Interp *interp, /* Interp for error results. */
+ Tk_Window tkwin, /* Need the screen the border is used on.*/
+ Tcl_Obj *objPtr) /* Object giving name of color for window
+ * background. */
+{
+ TkBorder *borderPtr;
+
+ if (objPtr->typePtr != &tkBorderObjType) {
+ InitBorderObj(objPtr);
+ }
+ borderPtr = objPtr->internalRep.twoPtrValue.ptr1;
+
+ /*
+ * If the object currently points to a TkBorder, see if it's the one we
+ * want. If so, increment its reference count and return.
+ */
+
+ if (borderPtr != NULL) {
+ if (borderPtr->resourceRefCount == 0) {
+ /*
+ * This is a stale reference: it refers to a border that's no
+ * longer in use. Clear the reference.
+ */
+
+ FreeBorderObj(objPtr);
+ borderPtr = NULL;
+ } else if ((Tk_Screen(tkwin) == borderPtr->screen)
+ && (Tk_Colormap(tkwin) == borderPtr->colormap)) {
+ borderPtr->resourceRefCount++;
+ return (Tk_3DBorder) borderPtr;
+ }
+ }
+
+ /*
+ * The object didn't point to the border that we wanted. Search the list
+ * of borders with the same name to see if one of the others is the right
+ * one.
+ *
+ * If the cached value is NULL, either the object type was not a color
+ * going in, or the object is a color type but had previously been freed.
+ *
+ * If the value is not NULL, the internal rep is the value of the color
+ * the last time this object was accessed. Check the screen and colormap
+ * of the last access, and if they match, we are done.
+ */
+
+ if (borderPtr != NULL) {
+ TkBorder *firstBorderPtr = Tcl_GetHashValue(borderPtr->hashPtr);
+
+ FreeBorderObj(objPtr);
+ for (borderPtr = firstBorderPtr ; borderPtr != NULL;
+ borderPtr = borderPtr->nextPtr) {
+ if ((Tk_Screen(tkwin) == borderPtr->screen)
+ && (Tk_Colormap(tkwin) == borderPtr->colormap)) {
+ borderPtr->resourceRefCount++;
+ borderPtr->objRefCount++;
+ objPtr->internalRep.twoPtrValue.ptr1 = borderPtr;
+ return (Tk_3DBorder) borderPtr;
+ }
+ }
+ }
+
+ /*
+ * Still no luck. Call Tk_Get3DBorder to allocate a new border.
+ */
+
+ borderPtr = (TkBorder *) Tk_Get3DBorder(interp, tkwin,
+ Tcl_GetString(objPtr));
+ objPtr->internalRep.twoPtrValue.ptr1 = borderPtr;
+ if (borderPtr != NULL) {
+ borderPtr->objRefCount++;
+ }
+ return (Tk_3DBorder) borderPtr;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_Get3DBorder --
+ *
+ * Create a data structure for displaying a 3-D border.
+ *
+ * Results:
+ * The return value is a token for a data structure describing a 3-D
+ * border. This token may be passed to functions such as
+ * Tk_Draw3DRectangle and Tk_Free3DBorder. If an error prevented the
+ * border from being created then NULL is returned and an error message
+ * will be left in the interp's result.
+ *
+ * Side effects:
+ * Data structures, graphics contexts, etc. are allocated. It is the
+ * caller's responsibility to eventually call Tk_Free3DBorder to release
+ * the resources.
+ *
+ *--------------------------------------------------------------
+ */
+
+Tk_3DBorder
+Tk_Get3DBorder(
+ Tcl_Interp *interp, /* Place to store an error message. */
+ Tk_Window tkwin, /* Token for window in which border will be
+ * drawn. */
+ Tk_Uid colorName) /* String giving name of color for window
+ * background. */
+{
+ Tcl_HashEntry *hashPtr;
+ TkBorder *borderPtr, *existingBorderPtr;
+ int isNew;
+ XGCValues gcValues;
+ XColor *bgColorPtr;
+ TkDisplay *dispPtr;
+
+ dispPtr = ((TkWindow *) tkwin)->dispPtr;
+
+ if (!dispPtr->borderInit) {
+ BorderInit(dispPtr);
+ }
+
+ hashPtr = Tcl_CreateHashEntry(&dispPtr->borderTable, colorName, &isNew);
+ if (!isNew) {
+ existingBorderPtr = Tcl_GetHashValue(hashPtr);
+ for (borderPtr = existingBorderPtr; borderPtr != NULL;
+ borderPtr = borderPtr->nextPtr) {
+ if ((Tk_Screen(tkwin) == borderPtr->screen)
+ && (Tk_Colormap(tkwin) == borderPtr->colormap)) {
+ borderPtr->resourceRefCount++;
+ return (Tk_3DBorder) borderPtr;
+ }
+ }
+ } else {
+ existingBorderPtr = NULL;
+ }
+
+ /*
+ * No satisfactory border exists yet. Initialize a new one.
+ */
+
+ bgColorPtr = Tk_GetColor(interp, tkwin, colorName);
+ if (bgColorPtr == NULL) {
+ if (isNew) {
+ Tcl_DeleteHashEntry(hashPtr);
+ }
+ return NULL;
+ }
+
+ borderPtr = TkpGetBorder();
+ borderPtr->screen = Tk_Screen(tkwin);
+ borderPtr->visual = Tk_Visual(tkwin);
+ borderPtr->depth = Tk_Depth(tkwin);
+ borderPtr->colormap = Tk_Colormap(tkwin);
+ borderPtr->resourceRefCount = 1;
+ borderPtr->objRefCount = 0;
+ borderPtr->bgColorPtr = bgColorPtr;
+ borderPtr->darkColorPtr = NULL;
+ borderPtr->lightColorPtr = NULL;
+ borderPtr->shadow = None;
+ borderPtr->bgGC = NULL;
+ borderPtr->darkGC = NULL;
+ borderPtr->lightGC = NULL;
+ borderPtr->hashPtr = hashPtr;
+ borderPtr->nextPtr = existingBorderPtr;
+ Tcl_SetHashValue(hashPtr, borderPtr);
+
+ /*
+ * Create the information for displaying the background color, but delay
+ * the allocation of shadows until they are actually needed for drawing.
+ */
+
+ gcValues.foreground = borderPtr->bgColorPtr->pixel;
+ borderPtr->bgGC = Tk_GetGC(tkwin, GCForeground, &gcValues);
+ return (Tk_3DBorder) borderPtr;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_Draw3DRectangle --
+ *
+ * Draw a 3-D border at a given place in a given window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A 3-D border will be drawn in the indicated drawable. The outside
+ * edges of the border will be determined by x, y, width, and height. The
+ * inside edges of the border will be determined by the borderWidth
+ * argument.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_Draw3DRectangle(
+ Tk_Window tkwin, /* Window for which border was allocated. */
+ Drawable drawable, /* X window or pixmap in which to draw. */
+ Tk_3DBorder border, /* Token for border to draw. */
+ int x, int y, int width, int height,
+ /* Outside area of region in which border will
+ * be drawn. */
+ int borderWidth, /* Desired width for border, in pixels. */
+ int relief) /* Type of relief: TK_RELIEF_RAISED,
+ * TK_RELIEF_SUNKEN, TK_RELIEF_GROOVE, etc. */
+{
+ if (width < 2*borderWidth) {
+ borderWidth = width/2;
+ }
+ if (height < 2*borderWidth) {
+ borderWidth = height/2;
+ }
+ Tk_3DVerticalBevel(tkwin, drawable, border, x, y, borderWidth, height,
+ 1, relief);
+ Tk_3DVerticalBevel(tkwin, drawable, border, x+width-borderWidth, y,
+ borderWidth, height, 0, relief);
+ Tk_3DHorizontalBevel(tkwin, drawable, border, x, y, width, borderWidth,
+ 1, 1, 1, relief);
+ Tk_3DHorizontalBevel(tkwin, drawable, border, x, y+height-borderWidth,
+ width, borderWidth, 0, 0, 0, relief);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_NameOf3DBorder --
+ *
+ * Given a border, return a textual string identifying the border's
+ * color.
+ *
+ * Results:
+ * The return value is the string that was used to create the border.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+const char *
+Tk_NameOf3DBorder(
+ Tk_3DBorder border) /* Token for border. */
+{
+ TkBorder *borderPtr = (TkBorder *) border;
+
+ return borderPtr->hashPtr->key.string;
+}
+
+/*
+ *--------------------------------------------------------------------
+ *
+ * Tk_3DBorderColor --
+ *
+ * Given a 3D border, return the X color used for the "flat" surfaces.
+ *
+ * Results:
+ * Returns the color used drawing flat surfaces with the border.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------
+ */
+XColor *
+Tk_3DBorderColor(
+ Tk_3DBorder border) /* Border whose color is wanted. */
+{
+ return ((TkBorder *) border)->bgColorPtr;
+}
+
+/*
+ *--------------------------------------------------------------------
+ *
+ * Tk_3DBorderGC --
+ *
+ * Given a 3D border, returns one of the graphics contexts used to draw
+ * the border.
+ *
+ * Results:
+ * Returns the graphics context given by the "which" argument.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------
+ */
+GC
+Tk_3DBorderGC(
+ Tk_Window tkwin, /* Window for which border was allocated. */
+ Tk_3DBorder border, /* Border whose GC is wanted. */
+ int which) /* Selects one of the border's 3 GC's:
+ * TK_3D_FLAT_GC, TK_3D_LIGHT_GC, or
+ * TK_3D_DARK_GC. */
+{
+ TkBorder * borderPtr = (TkBorder *) border;
+
+ if ((borderPtr->lightGC == NULL) && (which != TK_3D_FLAT_GC)) {
+ TkpGetShadows(borderPtr, tkwin);
+ }
+ if (which == TK_3D_FLAT_GC) {
+ return borderPtr->bgGC;
+ } else if (which == TK_3D_LIGHT_GC) {
+ return borderPtr->lightGC;
+ } else if (which == TK_3D_DARK_GC){
+ return borderPtr->darkGC;
+ }
+ Tcl_Panic("bogus \"which\" value in Tk_3DBorderGC");
+
+ /*
+ * The code below will never be executed, but it's needed to keep
+ * compilers happy.
+ */
+
+ return NULL;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_Free3DBorder --
+ *
+ * This function is called when a 3D border is no longer needed. It frees
+ * the resources associated with the border. After this call, the caller
+ * should never again use the "border" token.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Resources are freed.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_Free3DBorder(
+ Tk_3DBorder border) /* Token for border to be released. */
+{
+ TkBorder *borderPtr = (TkBorder *) border;
+ Display *display = DisplayOfScreen(borderPtr->screen);
+ TkBorder *prevPtr;
+
+ borderPtr->resourceRefCount--;
+ if (borderPtr->resourceRefCount > 0) {
+ return;
+ }
+
+ prevPtr = Tcl_GetHashValue(borderPtr->hashPtr);
+ TkpFreeBorder(borderPtr);
+ if (borderPtr->bgColorPtr != NULL) {
+ Tk_FreeColor(borderPtr->bgColorPtr);
+ }
+ if (borderPtr->darkColorPtr != NULL) {
+ Tk_FreeColor(borderPtr->darkColorPtr);
+ }
+ if (borderPtr->lightColorPtr != NULL) {
+ Tk_FreeColor(borderPtr->lightColorPtr);
+ }
+ if (borderPtr->shadow != None) {
+ Tk_FreeBitmap(display, borderPtr->shadow);
+ }
+ if (borderPtr->bgGC != NULL) {
+ Tk_FreeGC(display, borderPtr->bgGC);
+ }
+ if (borderPtr->darkGC != NULL) {
+ Tk_FreeGC(display, borderPtr->darkGC);
+ }
+ if (borderPtr->lightGC != NULL) {
+ Tk_FreeGC(display, borderPtr->lightGC);
+ }
+ if (prevPtr == borderPtr) {
+ if (borderPtr->nextPtr == NULL) {
+ Tcl_DeleteHashEntry(borderPtr->hashPtr);
+ } else {
+ Tcl_SetHashValue(borderPtr->hashPtr, borderPtr->nextPtr);
+ }
+ } else {
+ while (prevPtr->nextPtr != borderPtr) {
+ prevPtr = prevPtr->nextPtr;
+ }
+ prevPtr->nextPtr = borderPtr->nextPtr;
+ }
+ if (borderPtr->objRefCount == 0) {
+ ckfree(borderPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_Free3DBorderFromObj --
+ *
+ * This function is called to release a border allocated by
+ * Tk_Alloc3DBorderFromObj. It does not throw away the Tcl_Obj *; it only
+ * gets rid of the hash table entry for this border and clears the cached
+ * value that is normally stored in the object.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The reference count associated with the border represented by objPtr
+ * is decremented, and the border's resources are released to X if there
+ * are no remaining uses for it.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_Free3DBorderFromObj(
+ Tk_Window tkwin, /* The window this border lives in. Needed for
+ * the screen and colormap values. */
+ Tcl_Obj *objPtr) /* The Tcl_Obj * to be freed. */
+{
+ Tk_Free3DBorder(Tk_Get3DBorderFromObj(tkwin, objPtr));
+ FreeBorderObj(objPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FreeBorderObjProc, FreeBorderObj --
+ *
+ * This proc is called to release an object reference to a border. Called
+ * when the object's internal rep is released or when the cached
+ * borderPtr needs to be changed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The object reference count is decremented. When both it and the hash
+ * ref count go to zero, the border's resources are released.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+FreeBorderObjProc(
+ Tcl_Obj *objPtr) /* The object we are releasing. */
+{
+ FreeBorderObj(objPtr);
+ objPtr->typePtr = NULL;
+}
+
+static void
+FreeBorderObj(
+ Tcl_Obj *objPtr) /* The object we are releasing. */
+{
+ TkBorder *borderPtr = objPtr->internalRep.twoPtrValue.ptr1;
+
+ if (borderPtr != NULL) {
+ borderPtr->objRefCount--;
+ if ((borderPtr->objRefCount == 0)
+ && (borderPtr->resourceRefCount == 0)) {
+ ckfree(borderPtr);
+ }
+ objPtr->internalRep.twoPtrValue.ptr1 = NULL;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DupBorderObjProc --
+ *
+ * When a cached border object is duplicated, this is called to update
+ * the internal reps.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The border's objRefCount is incremented and the internal rep of the
+ * copy is set to point to it.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+DupBorderObjProc(
+ Tcl_Obj *srcObjPtr, /* The object we are copying from. */
+ Tcl_Obj *dupObjPtr) /* The object we are copying to. */
+{
+ TkBorder *borderPtr = srcObjPtr->internalRep.twoPtrValue.ptr1;
+
+ dupObjPtr->typePtr = srcObjPtr->typePtr;
+ dupObjPtr->internalRep.twoPtrValue.ptr1 = borderPtr;
+
+ if (borderPtr != NULL) {
+ borderPtr->objRefCount++;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_SetBackgroundFromBorder --
+ *
+ * Change the background of a window to one appropriate for a given 3-D
+ * border.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Tkwin's background gets modified.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_SetBackgroundFromBorder(
+ Tk_Window tkwin, /* Window whose background is to be set. */
+ Tk_3DBorder border) /* Token for border. */
+{
+ register TkBorder *borderPtr = (TkBorder *) border;
+
+ Tk_SetWindowBackground(tkwin, borderPtr->bgColorPtr->pixel);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetReliefFromObj --
+ *
+ * Return an integer value based on the value of the objPtr.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If an error occurs during
+ * conversion, an error message is left in the interpreter's result
+ * unless "interp" is NULL.
+ *
+ * Side effects:
+ * The object gets converted by Tcl_GetIndexFromObj.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_GetReliefFromObj(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Obj *objPtr, /* The object we are trying to get the value
+ * from. */
+ int *resultPtr) /* Where to place the answer. */
+{
+ return Tcl_GetIndexFromObjStruct(interp, objPtr, reliefStrings,
+ sizeof(char *), "relief", 0, resultPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetRelief --
+ *
+ * Parse a relief description and return the corresponding relief value,
+ * or an error.
+ *
+ * Results:
+ * A standard Tcl return value. If all goes well then *reliefPtr is
+ * filled in with one of the values TK_RELIEF_RAISED, TK_RELIEF_FLAT, or
+ * TK_RELIEF_SUNKEN.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_GetRelief(
+ Tcl_Interp *interp, /* For error messages. */
+ const char *name, /* Name of a relief type. */
+ int *reliefPtr) /* Where to store converted relief. */
+{
+ char c;
+ size_t length;
+
+ c = name[0];
+ length = strlen(name);
+ if ((c == 'f') && (strncmp(name, "flat", length) == 0)) {
+ *reliefPtr = TK_RELIEF_FLAT;
+ } else if ((c == 'g') && (strncmp(name, "groove", length) == 0)
+ && (length >= 2)) {
+ *reliefPtr = TK_RELIEF_GROOVE;
+ } else if ((c == 'r') && (strncmp(name, "raised", length) == 0)
+ && (length >= 2)) {
+ *reliefPtr = TK_RELIEF_RAISED;
+ } else if ((c == 'r') && (strncmp(name, "ridge", length) == 0)) {
+ *reliefPtr = TK_RELIEF_RIDGE;
+ } else if ((c == 's') && (strncmp(name, "solid", length) == 0)) {
+ *reliefPtr = TK_RELIEF_SOLID;
+ } else if ((c == 's') && (strncmp(name, "sunken", length) == 0)) {
+ *reliefPtr = TK_RELIEF_SUNKEN;
+ } else {
+ Tcl_SetObjResult(interp,
+ Tcl_ObjPrintf("bad relief \"%.50s\": must be %s",
+ name, "flat, groove, raised, ridge, solid, or sunken"));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "RELIEF", NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_NameOfRelief --
+ *
+ * Given a relief value, produce a string describing that relief value.
+ *
+ * Results:
+ * The return value is a static string that is equivalent to relief.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+const char *
+Tk_NameOfRelief(
+ int relief) /* One of TK_RELIEF_FLAT, TK_RELIEF_RAISED, or
+ * TK_RELIEF_SUNKEN. */
+{
+ if (relief == TK_RELIEF_FLAT) {
+ return "flat";
+ } else if (relief == TK_RELIEF_SUNKEN) {
+ return "sunken";
+ } else if (relief == TK_RELIEF_RAISED) {
+ return "raised";
+ } else if (relief == TK_RELIEF_GROOVE) {
+ return "groove";
+ } else if (relief == TK_RELIEF_RIDGE) {
+ return "ridge";
+ } else if (relief == TK_RELIEF_SOLID) {
+ return "solid";
+ } else if (relief == TK_RELIEF_NULL) {
+ return "";
+ } else {
+ return "unknown relief";
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_Draw3DPolygon --
+ *
+ * Draw a border with 3-D appearance around the edge of a given polygon.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Information is drawn in "drawable" in the form of a 3-D border
+ * borderWidth units width wide on the left of the trajectory given by
+ * pointPtr and numPoints (or -borderWidth units wide on the right side,
+ * if borderWidth is negative).
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_Draw3DPolygon(
+ Tk_Window tkwin, /* Window for which border was allocated. */
+ Drawable drawable, /* X window or pixmap in which to draw. */
+ Tk_3DBorder border, /* Token for border to draw. */
+ XPoint *pointPtr, /* Array of points describing polygon. All
+ * points must be absolute
+ * (CoordModeOrigin). */
+ int numPoints, /* Number of points at *pointPtr. */
+ int borderWidth, /* Width of border, measured in pixels to the
+ * left of the polygon's trajectory. May be
+ * negative. */
+ int leftRelief) /* TK_RELIEF_RAISED or TK_RELIEF_SUNKEN:
+ * indicates how stuff to left of trajectory
+ * looks relative to stuff on right. */
+{
+ XPoint poly[4], b1, b2, newB1, newB2;
+ XPoint perp, c, shift1, shift2; /* Used for handling parallel lines. */
+ register XPoint *p1Ptr, *p2Ptr;
+ TkBorder *borderPtr = (TkBorder *) border;
+ GC gc;
+ int i, lightOnLeft, dx, dy, parallel, pointsSeen;
+ Display *display = Tk_Display(tkwin);
+
+ if (borderPtr->lightGC == NULL) {
+ TkpGetShadows(borderPtr, tkwin);
+ }
+
+ /*
+ * Handle grooves and ridges with recursive calls.
+ */
+
+ if ((leftRelief == TK_RELIEF_GROOVE) || (leftRelief == TK_RELIEF_RIDGE)) {
+ int halfWidth = borderWidth/2;
+
+ Tk_Draw3DPolygon(tkwin, drawable, border, pointPtr, numPoints,
+ halfWidth, (leftRelief == TK_RELIEF_GROOVE) ? TK_RELIEF_RAISED
+ : TK_RELIEF_SUNKEN);
+ Tk_Draw3DPolygon(tkwin, drawable, border, pointPtr, numPoints,
+ -halfWidth, (leftRelief == TK_RELIEF_GROOVE) ? TK_RELIEF_SUNKEN
+ : TK_RELIEF_RAISED);
+ return;
+ }
+
+ /*
+ * If the polygon is already closed, drop the last point from it (we'll
+ * close it automatically).
+ */
+
+ p1Ptr = &pointPtr[numPoints-1];
+ p2Ptr = &pointPtr[0];
+ if ((p1Ptr->x == p2Ptr->x) && (p1Ptr->y == p2Ptr->y)) {
+ numPoints--;
+ }
+
+ /*
+ * The loop below is executed once for each vertex in the polgon. At the
+ * beginning of each iteration things look like this:
+ *
+ * poly[1] /
+ * * /
+ * | /
+ * b1 * poly[0] (pointPtr[i-1])
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | | *p1Ptr *p2Ptr
+ * b2 *--------------------*
+ * |
+ * |
+ * x-------------------------
+ *
+ * The job of this iteration is to do the following:
+ * (a) Compute x (the border corner corresponding to pointPtr[i]) and put
+ * it in poly[2]. As part of this, compute a new b1 and b2 value for
+ * the next side of the polygon.
+ * (b) Put pointPtr[i] into poly[3].
+ * (c) Draw the polygon given by poly[0..3].
+ * (d) Advance poly[0], poly[1], b1, and b2 for the next side of the
+ * polygon.
+ */
+
+ /*
+ * The above situation doesn't first come into existence until two points
+ * have been processed; the first two points are used to "prime the pump",
+ * so some parts of the processing are ommitted for these points. The
+ * variable "pointsSeen" keeps track of the priming process; it has to be
+ * separate from i in order to be able to ignore duplicate points in the
+ * polygon.
+ */
+
+ pointsSeen = 0;
+ for (i = -2, p1Ptr = &pointPtr[numPoints-2], p2Ptr = p1Ptr+1;
+ i < numPoints; i++, p1Ptr = p2Ptr, p2Ptr++) {
+ if ((i == -1) || (i == numPoints-1)) {
+ p2Ptr = pointPtr;
+ }
+ if ((p2Ptr->x == p1Ptr->x) && (p2Ptr->y == p1Ptr->y)) {
+ /*
+ * Ignore duplicate points (they'd cause core dumps in ShiftLine
+ * calls below).
+ */
+
+ continue;
+ }
+ ShiftLine(p1Ptr, p2Ptr, borderWidth, &newB1);
+ newB2.x = newB1.x + (p2Ptr->x - p1Ptr->x);
+ newB2.y = newB1.y + (p2Ptr->y - p1Ptr->y);
+ poly[3] = *p1Ptr;
+ parallel = 0;
+ if (pointsSeen >= 1) {
+ parallel = Intersect(&newB1, &newB2, &b1, &b2, &poly[2]);
+
+ /*
+ * If two consecutive segments of the polygon are parallel, then
+ * things get more complex. Consider the following diagram:
+ *
+ * poly[1]
+ * *----b1-----------b2------a
+ * \
+ * \
+ * *---------*----------* b
+ * poly[0] *p2Ptr *p1Ptr /
+ * /
+ * --*--------*----c
+ * newB1 newB2
+ *
+ * Instead of using x and *p1Ptr for poly[2] and poly[3], as in
+ * the original diagram, use a and b as above. Then instead of
+ * using x and *p1Ptr for the new poly[0] and poly[1], use b and c
+ * as above.
+ *
+ * Do the computation in three stages:
+ * 1. Compute a point "perp" such that the line p1Ptr-perp is
+ * perpendicular to p1Ptr-p2Ptr.
+ * 2. Compute the points a and c by intersecting the lines b1-b2
+ * and newB1-newB2 with p1Ptr-perp.
+ * 3. Compute b by shifting p1Ptr-perp to the right and
+ * intersecting it with p1Ptr-p2Ptr.
+ */
+
+ if (parallel) {
+ perp.x = p1Ptr->x + (p2Ptr->y - p1Ptr->y);
+ perp.y = p1Ptr->y - (p2Ptr->x - p1Ptr->x);
+ (void) Intersect(p1Ptr, &perp, &b1, &b2, &poly[2]);
+ (void) Intersect(p1Ptr, &perp, &newB1, &newB2, &c);
+ ShiftLine(p1Ptr, &perp, borderWidth, &shift1);
+ shift2.x = shift1.x + (perp.x - p1Ptr->x);
+ shift2.y = shift1.y + (perp.y - p1Ptr->y);
+ (void) Intersect(p1Ptr, p2Ptr, &shift1, &shift2, &poly[3]);
+ }
+ }
+ if (pointsSeen >= 2) {
+ dx = poly[3].x - poly[0].x;
+ dy = poly[3].y - poly[0].y;
+ if (dx > 0) {
+ lightOnLeft = (dy <= dx);
+ } else {
+ lightOnLeft = (dy < dx);
+ }
+ if (lightOnLeft ^ (leftRelief == TK_RELIEF_RAISED)) {
+ gc = borderPtr->lightGC;
+ } else {
+ gc = borderPtr->darkGC;
+ }
+ XFillPolygon(display, drawable, gc, poly, 4, Convex,
+ CoordModeOrigin);
+ }
+ b1.x = newB1.x;
+ b1.y = newB1.y;
+ b2.x = newB2.x;
+ b2.y = newB2.y;
+ poly[0].x = poly[3].x;
+ poly[0].y = poly[3].y;
+ if (parallel) {
+ poly[1].x = c.x;
+ poly[1].y = c.y;
+ } else if (pointsSeen >= 1) {
+ poly[1].x = poly[2].x;
+ poly[1].y = poly[2].y;
+ }
+ pointsSeen++;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_Fill3DRectangle --
+ *
+ * Fill a rectangular area, supplying a 3D border if desired.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Information gets drawn on the screen.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_Fill3DRectangle(
+ Tk_Window tkwin, /* Window for which border was allocated. */
+ Drawable drawable, /* X window or pixmap in which to draw. */
+ Tk_3DBorder border, /* Token for border to draw. */
+ int x, int y, int width, int height,
+ /* Outside area of rectangular region. */
+ int borderWidth, /* Desired width for border, in pixels. Border
+ * will be *inside* region. */
+ int relief) /* Indicates 3D effect: TK_RELIEF_FLAT,
+ * TK_RELIEF_RAISED, or TK_RELIEF_SUNKEN. */
+{
+ register TkBorder *borderPtr = (TkBorder *) border;
+ int doubleBorder;
+
+ /*
+ * This code is slightly tricky because it only draws the background in
+ * areas not covered by the 3D border. This avoids flashing effects on the
+ * screen for the border region.
+ */
+
+ if (relief == TK_RELIEF_FLAT) {
+ borderWidth = 0;
+ } else {
+ /*
+ * We need to make this extra check, otherwise we will leave garbage
+ * in thin frames [Bug: 3596]
+ */
+
+ if (width < 2*borderWidth) {
+ borderWidth = width/2;
+ }
+ if (height < 2*borderWidth) {
+ borderWidth = height/2;
+ }
+ }
+ doubleBorder = 2*borderWidth;
+
+ if ((width > doubleBorder) && (height > doubleBorder)) {
+ XFillRectangle(Tk_Display(tkwin), drawable, borderPtr->bgGC,
+ x + borderWidth, y + borderWidth,
+ (unsigned) (width - doubleBorder),
+ (unsigned) (height - doubleBorder));
+ }
+ if (borderWidth) {
+ Tk_Draw3DRectangle(tkwin, drawable, border, x, y, width,
+ height, borderWidth, relief);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_Fill3DPolygon --
+ *
+ * Fill a polygonal area, supplying a 3D border if desired.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Information gets drawn on the screen.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_Fill3DPolygon(
+ Tk_Window tkwin, /* Window for which border was allocated. */
+ Drawable drawable, /* X window or pixmap in which to draw. */
+ Tk_3DBorder border, /* Token for border to draw. */
+ XPoint *pointPtr, /* Array of points describing polygon. All
+ * points must be absolute
+ * (CoordModeOrigin). */
+ int numPoints, /* Number of points at *pointPtr. */
+ int borderWidth, /* Width of border, measured in pixels to the
+ * left of the polygon's trajectory. May be
+ * negative. */
+ int leftRelief) /* Indicates 3D effect of left side of
+ * trajectory relative to right:
+ * TK_RELIEF_FLAT, TK_RELIEF_RAISED, or
+ * TK_RELIEF_SUNKEN. */
+{
+ register TkBorder *borderPtr = (TkBorder *) border;
+
+ XFillPolygon(Tk_Display(tkwin), drawable, borderPtr->bgGC,
+ pointPtr, numPoints, Complex, CoordModeOrigin);
+ if (leftRelief != TK_RELIEF_FLAT) {
+ Tk_Draw3DPolygon(tkwin, drawable, border, pointPtr, numPoints,
+ borderWidth, leftRelief);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * BorderInit --
+ *
+ * Initialize the structures used for border management.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Read the code.
+ *
+ *-------------------------------------------------------------
+ */
+
+static void
+BorderInit(
+ TkDisplay *dispPtr) /* Used to access thread-specific data. */
+{
+ dispPtr->borderInit = 1;
+ Tcl_InitHashTable(&dispPtr->borderTable, TCL_STRING_KEYS);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ShiftLine --
+ *
+ * Given two points on a line, compute a point on a new line that is
+ * parallel to the given line and a given distance away from it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ShiftLine(
+ XPoint *p1Ptr, /* First point on line. */
+ XPoint *p2Ptr, /* Second point on line. */
+ int distance, /* New line is to be this many units to the
+ * left of original line, when looking from p1
+ * to p2. May be negative. */
+ XPoint *p3Ptr) /* Store coords of point on new line here. */
+{
+ int dx, dy, dxNeg, dyNeg;
+ static int shiftTable[129]; /* Used for a quick approximation in computing
+ * the new point. An index into the table is
+ * 128 times the slope of the original line
+ * (the slope must always be between 0 and 1).
+ * The value of the table entry is 128 times
+ * the amount to displace the new line in y
+ * for each unit of perpendicular distance. In
+ * other words, the table maps from the
+ * tangent of an angle to the inverse of its
+ * cosine. If the slope of the original line
+ * is greater than 1, then the displacement is
+ * done in x rather than in y. */
+
+ /*
+ * Initialize the table if this is the first time it is used.
+ */
+
+ if (shiftTable[0] == 0) {
+ int i;
+ double tangent, cosine;
+
+ for (i = 0; i <= 128; i++) {
+ tangent = i/128.0;
+ cosine = 128/cos(atan(tangent)) + .5;
+ shiftTable[i] = (int) cosine;
+ }
+ }
+
+ *p3Ptr = *p1Ptr;
+ dx = p2Ptr->x - p1Ptr->x;
+ dy = p2Ptr->y - p1Ptr->y;
+ if (dy < 0) {
+ dyNeg = 1;
+ dy = -dy;
+ } else {
+ dyNeg = 0;
+ }
+ if (dx < 0) {
+ dxNeg = 1;
+ dx = -dx;
+ } else {
+ dxNeg = 0;
+ }
+ if (dy <= dx) {
+ dy = ((distance * shiftTable[(dy<<7)/dx]) + 64) >> 7;
+ if (!dxNeg) {
+ dy = -dy;
+ }
+ p3Ptr->y += dy;
+ } else {
+ dx = ((distance * shiftTable[(dx<<7)/dy]) + 64) >> 7;
+ if (dyNeg) {
+ dx = -dx;
+ }
+ p3Ptr->x += dx;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Intersect --
+ *
+ * Find the intersection point between two lines.
+ *
+ * Results:
+ * Under normal conditions 0 is returned and the point at *iPtr is filled
+ * in with the intersection between the two lines. If the two lines are
+ * parallel, then -1 is returned and *iPtr isn't modified.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+Intersect(
+ XPoint *a1Ptr, /* First point of first line. */
+ XPoint *a2Ptr, /* Second point of first line. */
+ XPoint *b1Ptr, /* First point of second line. */
+ XPoint *b2Ptr, /* Second point of second line. */
+ XPoint *iPtr) /* Filled in with intersection point. */
+{
+ int dxadyb, dxbdya, dxadxb, dyadyb, p, q;
+
+ /*
+ * The code below is just a straightforward manipulation of two equations
+ * of the form y = (x-x1)*(y2-y1)/(x2-x1) + y1 to solve for the
+ * x-coordinate of intersection, then the y-coordinate.
+ */
+
+ dxadyb = (a2Ptr->x - a1Ptr->x)*(b2Ptr->y - b1Ptr->y);
+ dxbdya = (b2Ptr->x - b1Ptr->x)*(a2Ptr->y - a1Ptr->y);
+ dxadxb = (a2Ptr->x - a1Ptr->x)*(b2Ptr->x - b1Ptr->x);
+ dyadyb = (a2Ptr->y - a1Ptr->y)*(b2Ptr->y - b1Ptr->y);
+
+ if (dxadyb == dxbdya) {
+ return -1;
+ }
+ p = (a1Ptr->x*dxbdya - b1Ptr->x*dxadyb + (b1Ptr->y - a1Ptr->y)*dxadxb);
+ q = dxbdya - dxadyb;
+ if (q < 0) {
+ p = -p;
+ q = -q;
+ }
+ if (p < 0) {
+ iPtr->x = - ((-p + q/2)/q);
+ } else {
+ iPtr->x = (p + q/2)/q;
+ }
+ p = (a1Ptr->y*dxadyb - b1Ptr->y*dxbdya + (b1Ptr->x - a1Ptr->x)*dyadyb);
+ q = dxadyb - dxbdya;
+ if (q < 0) {
+ p = -p;
+ q = -q;
+ }
+ if (p < 0) {
+ iPtr->y = - ((-p + q/2)/q);
+ } else {
+ iPtr->y = (p + q/2)/q;
+ }
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_Get3DBorderFromObj --
+ *
+ * Returns the border referred to by a Tcl object. The border must
+ * already have been allocated via a call to Tk_Alloc3DBorderFromObj or
+ * Tk_Get3DBorder.
+ *
+ * Results:
+ * Returns the Tk_3DBorder that matches the tkwin and the string rep of
+ * the name of the border given in objPtr.
+ *
+ * Side effects:
+ * If the object is not already a border, the conversion will free any
+ * old internal representation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_3DBorder
+Tk_Get3DBorderFromObj(
+ Tk_Window tkwin,
+ Tcl_Obj *objPtr) /* The object whose string value selects a
+ * border. */
+{
+ TkBorder *borderPtr = NULL;
+ Tcl_HashEntry *hashPtr;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+
+ if (objPtr->typePtr != &tkBorderObjType) {
+ InitBorderObj(objPtr);
+ }
+
+ /*
+ * If we are lucky (and the user doesn't use too many different displays,
+ * screens, or colormaps...) then the TkBorder structure we need will be
+ * cached in the internal representation of the Tcl_Obj. Check it out...
+ */
+
+ borderPtr = objPtr->internalRep.twoPtrValue.ptr1;
+ if ((borderPtr != NULL)
+ && (borderPtr->resourceRefCount > 0)
+ && (Tk_Screen(tkwin) == borderPtr->screen)
+ && (Tk_Colormap(tkwin) == borderPtr->colormap)) {
+ /*
+ * The object already points to the right border structure. Just
+ * return it.
+ */
+
+ return (Tk_3DBorder) borderPtr;
+ }
+
+ /*
+ * If we make it here, it means we aren't so lucky. Either there was no
+ * cached TkBorder in the Tcl_Obj, or the TkBorder that was there is for
+ * the wrong screen/colormap. Either way, we have to search for the right
+ * TkBorder. For each color name, there is linked list of TkBorder
+ * structures, one structure for each screen/colormap combination. The
+ * head of the linked list is recorded in a hash table (where the key is
+ * the color name) attached to the TkDisplay structure. Walk this list to
+ * find the right TkBorder structure.
+ */
+
+ hashPtr = Tcl_FindHashEntry(&dispPtr->borderTable, Tcl_GetString(objPtr));
+ if (hashPtr == NULL) {
+ goto error;
+ }
+ for (borderPtr = Tcl_GetHashValue(hashPtr); borderPtr != NULL;
+ borderPtr = borderPtr->nextPtr) {
+ if ((Tk_Screen(tkwin) == borderPtr->screen)
+ && (Tk_Colormap(tkwin) == borderPtr->colormap)) {
+ FreeBorderObj(objPtr);
+ objPtr->internalRep.twoPtrValue.ptr1 = borderPtr;
+ borderPtr->objRefCount++;
+ return (Tk_3DBorder) borderPtr;
+ }
+ }
+
+ error:
+ Tcl_Panic("Tk_Get3DBorderFromObj called with non-existent border!");
+ /*
+ * The following code isn't reached; it's just there to please compilers.
+ */
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InitBorderObj --
+ *
+ * Attempt to generate a border internal form for the Tcl object
+ * "objPtr".
+ *
+ * Results:
+ * The return value is a standard Tcl result. If an error occurs during
+ * conversion, an error message is left in the interpreter's result
+ * unless "interp" is NULL.
+ *
+ * Side effects:
+ * If no error occurs, a blank internal format for a border value is
+ * initialized. The final form cannot be done without a Tk_Window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+InitBorderObj(
+ Tcl_Obj *objPtr) /* The object to convert. */
+{
+ const Tcl_ObjType *typePtr;
+
+ /*
+ * Free the old internalRep before setting the new one.
+ */
+
+ Tcl_GetString(objPtr);
+ typePtr = objPtr->typePtr;
+ if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
+ typePtr->freeIntRepProc(objPtr);
+ }
+ objPtr->typePtr = &tkBorderObjType;
+ objPtr->internalRep.twoPtrValue.ptr1 = NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkDebugBorder --
+ *
+ * This function returns debugging information about a border.
+ *
+ * Results:
+ * The return value is a list with one sublist for each TkBorder
+ * corresponding to "name". Each sublist has two elements that contain
+ * the resourceRefCount and objRefCount fields from the TkBorder
+ * structure.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TkDebugBorder(
+ Tk_Window tkwin, /* The window in which the border will be used
+ * (not currently used). */
+ const char *name) /* Name of the desired color. */
+{
+ Tcl_HashEntry *hashPtr;
+ Tcl_Obj *resultPtr;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+
+ resultPtr = Tcl_NewObj();
+ hashPtr = Tcl_FindHashEntry(&dispPtr->borderTable, name);
+ if (hashPtr != NULL) {
+ TkBorder *borderPtr = Tcl_GetHashValue(hashPtr);
+
+ if (borderPtr == NULL) {
+ Tcl_Panic("TkDebugBorder found empty hash table entry");
+ }
+ for ( ; (borderPtr != NULL); borderPtr = borderPtr->nextPtr) {
+ Tcl_Obj *objPtr = Tcl_NewObj();
+
+ Tcl_ListObjAppendElement(NULL, objPtr,
+ Tcl_NewIntObj(borderPtr->resourceRefCount));
+ Tcl_ListObjAppendElement(NULL, objPtr,
+ Tcl_NewIntObj(borderPtr->objRefCount));
+ Tcl_ListObjAppendElement(NULL, resultPtr, objPtr);
+ }
+ }
+ return resultPtr;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tk3d.h b/tk8.6/generic/tk3d.h
new file mode 100644
index 0000000..ec7f7c7
--- /dev/null
+++ b/tk8.6/generic/tk3d.h
@@ -0,0 +1,85 @@
+/*
+ * tk3d.h --
+ *
+ * Declarations of types and functions shared by the 3d border module.
+ *
+ * Copyright (c) 1996-1997 by Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef _TK3D
+#define _TK3D
+
+#include "tkInt.h"
+
+/*
+ * One of the following data structures is allocated for each 3-D border
+ * currently in use. Structures of this type are indexed by borderTable, so
+ * that a single structure can be shared for several uses.
+ */
+
+typedef struct TkBorder {
+ Screen *screen; /* Screen on which the border will be used. */
+ Visual *visual; /* Visual for all windows and pixmaps using
+ * the border. */
+ int depth; /* Number of bits per pixel of drawables where
+ * the border will be used. */
+ Colormap colormap; /* Colormap out of which pixels are
+ * allocated. */
+ int resourceRefCount; /* Number of active uses of this color (each
+ * active use corresponds to a call to
+ * Tk_Alloc3DBorderFromObj or Tk_Get3DBorder).
+ * If this count is 0, then this structure is
+ * no longer valid and it isn't present in
+ * borderTable: it is being kept around only
+ * because there are objects referring to it.
+ * The structure is freed when objRefCount and
+ * resourceRefCount are both 0. */
+ int objRefCount; /* The number of Tcl objects that reference
+ * this structure. */
+ XColor *bgColorPtr; /* Background color (intensity between
+ * lightColorPtr and darkColorPtr). */
+ XColor *darkColorPtr; /* Color for darker areas (must free when
+ * deleting structure). NULL means shadows
+ * haven't been allocated yet.*/
+ XColor *lightColorPtr; /* Color used for lighter areas of border
+ * (must free this when deleting structure).
+ * NULL means shadows haven't been allocated
+ * yet. */
+ Pixmap shadow; /* Stipple pattern to use for drawing shadows
+ * areas. Used for displays with <= 64 colors
+ * or where colormap has filled up. */
+ GC bgGC; /* Used (if necessary) to draw areas in the
+ * background color. */
+ GC darkGC; /* Used to draw darker parts of the border.
+ * NULL means the shadow colors haven't been
+ * allocated yet.*/
+ GC lightGC; /* Used to draw lighter parts of the border.
+ * NULL means the shadow colors haven't been
+ * allocated yet. */
+ Tcl_HashEntry *hashPtr; /* Entry in borderTable (needed in order to
+ * delete structure). */
+ struct TkBorder *nextPtr; /* Points to the next TkBorder structure with
+ * the same color name. Borders with the same
+ * name but different screens or colormaps are
+ * chained together off a single entry in
+ * borderTable. */
+} TkBorder;
+
+/*
+ * Maximum intensity for a color:
+ */
+
+#define MAX_INTENSITY 65535
+
+/*
+ * Declarations for platform specific interfaces used by this module.
+ */
+
+MODULE_SCOPE TkBorder *TkpGetBorder(void);
+MODULE_SCOPE void TkpGetShadows(TkBorder *borderPtr, Tk_Window tkwin);
+MODULE_SCOPE void TkpFreeBorder(TkBorder *borderPtr);
+
+#endif /* _TK3D */
diff --git a/tk8.6/generic/tkArgv.c b/tk8.6/generic/tkArgv.c
new file mode 100644
index 0000000..6c2c5c5
--- /dev/null
+++ b/tk8.6/generic/tkArgv.c
@@ -0,0 +1,417 @@
+/*
+ * tkArgv.c --
+ *
+ * This file contains a function that handles table-based argv-argc
+ * parsing.
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "tkInt.h"
+
+/*
+ * Default table of argument descriptors. These are normally available in
+ * every application.
+ */
+
+static const Tk_ArgvInfo defaultTable[] = {
+ {"-help", TK_ARGV_HELP, NULL, NULL,
+ "Print summary of command-line options and abort"},
+ {NULL, TK_ARGV_END, NULL, NULL, NULL}
+};
+
+/*
+ * Forward declarations for functions defined in this file:
+ */
+
+static void PrintUsage(Tcl_Interp *interp, const Tk_ArgvInfo *argTable,
+ int flags);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_ParseArgv --
+ *
+ * Process an argv array according to a table of expected command-line
+ * options. See the manual page for more details.
+ *
+ * Results:
+ * The return value is a standard Tcl return value. If an error occurs
+ * then an error message is left in the interp's result. Under normal
+ * conditions, both *argcPtr and *argv are modified to return the
+ * arguments that couldn't be processed here (they didn't match the
+ * option table, or followed an TK_ARGV_REST argument).
+ *
+ * Side effects:
+ * Variables may be modified, resources may be entered for tkwin, or
+ * functions may be called. It all depends on the arguments and their
+ * entries in argTable. See the user documentation for details.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_ParseArgv(
+ Tcl_Interp *interp, /* Place to store error message. */
+ Tk_Window tkwin, /* Window to use for setting Tk options. NULL
+ * means ignore Tk option specs. */
+ int *argcPtr, /* Number of arguments in argv. Modified to
+ * hold # args left in argv at end. */
+ const char **argv, /* Array of arguments. Modified to hold those
+ * that couldn't be processed here. */
+ const Tk_ArgvInfo *argTable, /* Array of option descriptions */
+ int flags) /* Or'ed combination of various flag bits,
+ * such as TK_ARGV_NO_DEFAULTS. */
+{
+ register const Tk_ArgvInfo *infoPtr;
+ /* Pointer to the current entry in the table
+ * of argument descriptions. */
+ const Tk_ArgvInfo *matchPtr;/* Descriptor that matches current argument. */
+ const char *curArg; /* Current argument */
+ register char c; /* Second character of current arg (used for
+ * quick check for matching; use 2nd char.
+ * because first char. will almost always be
+ * '-'). */
+ int srcIndex; /* Location from which to read next argument
+ * from argv. */
+ int dstIndex; /* Index into argv to which next unused
+ * argument should be copied (never greater
+ * than srcIndex). */
+ int argc; /* # arguments in argv still to process. */
+ size_t length; /* Number of characters in current argument. */
+ char *endPtr; /* Used for identifying junk in arguments. */
+ int i;
+
+ if (flags & TK_ARGV_DONT_SKIP_FIRST_ARG) {
+ srcIndex = dstIndex = 0;
+ argc = *argcPtr;
+ } else {
+ srcIndex = dstIndex = 1;
+ argc = *argcPtr-1;
+ }
+
+ while (argc > 0) {
+ curArg = argv[srcIndex];
+ srcIndex++;
+ argc--;
+ length = strlen(curArg);
+ if (length > 0) {
+ c = curArg[1];
+ } else {
+ c = 0;
+ }
+
+ /*
+ * Loop throught the argument descriptors searching for one with the
+ * matching key string. If found, leave a pointer to it in matchPtr.
+ */
+
+ matchPtr = NULL;
+ for (i = 0; i < 2; i++) {
+ if (i == 0) {
+ infoPtr = argTable;
+ } else {
+ infoPtr = defaultTable;
+ }
+ for (; (infoPtr != NULL) && (infoPtr->type != TK_ARGV_END);
+ infoPtr++) {
+ if (infoPtr->key == NULL) {
+ continue;
+ }
+ if ((infoPtr->key[1] != c)
+ || (strncmp(infoPtr->key, curArg, length) != 0)) {
+ continue;
+ }
+ if ((tkwin == NULL)
+ && ((infoPtr->type == TK_ARGV_CONST_OPTION)
+ || (infoPtr->type == TK_ARGV_OPTION_VALUE)
+ || (infoPtr->type == TK_ARGV_OPTION_NAME_VALUE))) {
+ continue;
+ }
+ if (infoPtr->key[length] == 0) {
+ matchPtr = infoPtr;
+ goto gotMatch;
+ }
+ if (flags & TK_ARGV_NO_ABBREV) {
+ continue;
+ }
+ if (matchPtr != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "ambiguous option \"%s\"", curArg));
+ Tcl_SetErrorCode(interp, "TK", "ARG", "AMBIGUOUS", curArg,
+ NULL);
+ return TCL_ERROR;
+ }
+ matchPtr = infoPtr;
+ }
+ }
+ if (matchPtr == NULL) {
+ /*
+ * Unrecognized argument. Just copy it down, unless the caller
+ * prefers an error to be registered.
+ */
+
+ if (flags & TK_ARGV_NO_LEFTOVERS) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "unrecognized argument \"%s\"", curArg));
+ Tcl_SetErrorCode(interp, "TK", "ARG", "UNRECOGNIZED", curArg,
+ NULL);
+ return TCL_ERROR;
+ }
+ argv[dstIndex] = curArg;
+ dstIndex++;
+ continue;
+ }
+
+ /*
+ * Take the appropriate action based on the option type
+ */
+
+ gotMatch:
+ infoPtr = matchPtr;
+ switch (infoPtr->type) {
+ case TK_ARGV_CONSTANT:
+ *((int *) infoPtr->dst) = PTR2INT(infoPtr->src);
+ break;
+ case TK_ARGV_INT:
+ if (argc == 0) {
+ goto missingArg;
+ }
+ *((int *) infoPtr->dst) = strtol(argv[srcIndex], &endPtr, 0);
+ if ((endPtr == argv[srcIndex]) || (*endPtr != 0)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "expected %s argument for \"%s\" but got \"%s\"",
+ "integer", infoPtr->key, argv[srcIndex]));
+ Tcl_SetErrorCode(interp, "TK", "ARG", "INTEGER", curArg,NULL);
+ return TCL_ERROR;
+ }
+ srcIndex++;
+ argc--;
+ break;
+ case TK_ARGV_STRING:
+ if (argc == 0) {
+ goto missingArg;
+ }
+ *((const char **) infoPtr->dst) = argv[srcIndex];
+ srcIndex++;
+ argc--;
+ break;
+ case TK_ARGV_UID:
+ if (argc == 0) {
+ goto missingArg;
+ }
+ *((Tk_Uid *) infoPtr->dst) = Tk_GetUid(argv[srcIndex]);
+ srcIndex++;
+ argc--;
+ break;
+ case TK_ARGV_REST:
+ *((int *) infoPtr->dst) = dstIndex;
+ goto argsDone;
+ case TK_ARGV_FLOAT:
+ if (argc == 0) {
+ goto missingArg;
+ }
+ *((double *) infoPtr->dst) = strtod(argv[srcIndex], &endPtr);
+ if ((endPtr == argv[srcIndex]) || (*endPtr != 0)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "expected %s argument for \"%s\" but got \"%s\"",
+ "floating-point", infoPtr->key, argv[srcIndex]));
+ Tcl_SetErrorCode(interp, "TK", "ARG", "FLOAT", curArg, NULL);
+ return TCL_ERROR;
+ }
+ srcIndex++;
+ argc--;
+ break;
+ case TK_ARGV_FUNC: {
+ typedef int (ArgvFunc)(char *, const char *, const char *);
+ ArgvFunc *handlerProc = (ArgvFunc *) infoPtr->src;
+
+ if (handlerProc(infoPtr->dst, infoPtr->key, argv[srcIndex])) {
+ srcIndex++;
+ argc--;
+ }
+ break;
+ }
+ case TK_ARGV_GENFUNC: {
+ typedef int (ArgvGenFunc)(char *, Tcl_Interp *, const char *, int,
+ const char **);
+ ArgvGenFunc *handlerProc = (ArgvGenFunc *) infoPtr->src;
+
+ argc = handlerProc(infoPtr->dst, interp, infoPtr->key, argc,
+ argv+srcIndex);
+ if (argc < 0) {
+ return TCL_ERROR;
+ }
+ break;
+ }
+ case TK_ARGV_HELP:
+ PrintUsage(interp, argTable, flags);
+ Tcl_SetErrorCode(interp, "TK", "ARG", "HELP", NULL);
+ return TCL_ERROR;
+ case TK_ARGV_CONST_OPTION:
+ Tk_AddOption(tkwin, infoPtr->dst, infoPtr->src,
+ TK_INTERACTIVE_PRIO);
+ break;
+ case TK_ARGV_OPTION_VALUE:
+ if (argc < 1) {
+ goto missingArg;
+ }
+ Tk_AddOption(tkwin, infoPtr->dst, argv[srcIndex],
+ TK_INTERACTIVE_PRIO);
+ srcIndex++;
+ argc--;
+ break;
+ case TK_ARGV_OPTION_NAME_VALUE:
+ if (argc < 2) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "\"%s\" option requires two following arguments",
+ curArg));
+ Tcl_SetErrorCode(interp, "TK", "ARG", "NAME_VALUE", curArg,
+ NULL);
+ return TCL_ERROR;
+ }
+ Tk_AddOption(tkwin, argv[srcIndex], argv[srcIndex+1],
+ TK_INTERACTIVE_PRIO);
+ srcIndex += 2;
+ argc -= 2;
+ break;
+ default:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad argument type %d in Tk_ArgvInfo", infoPtr->type));
+ Tcl_SetErrorCode(interp, "TK", "API_ABUSE", NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * If we broke out of the loop because of an OPT_REST argument, copy the
+ * remaining arguments down.
+ */
+
+ argsDone:
+ while (argc) {
+ argv[dstIndex] = argv[srcIndex];
+ srcIndex++;
+ dstIndex++;
+ argc--;
+ }
+ argv[dstIndex] = NULL;
+ *argcPtr = dstIndex;
+ return TCL_OK;
+
+ missingArg:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "\"%s\" option requires an additional argument", curArg));
+ Tcl_SetErrorCode(interp, "TK", "ARG", "MISSING", curArg, NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PrintUsage --
+ *
+ * Generate a help string describing command-line options.
+ *
+ * Results:
+ * The interp's result will be modified to hold a help string describing
+ * all the options in argTable, plus all those in the default table
+ * unless TK_ARGV_NO_DEFAULTS is specified in flags.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+PrintUsage(
+ Tcl_Interp *interp, /* Place information in this interp's result
+ * area. */
+ const Tk_ArgvInfo *argTable,/* Array of command-specific argument
+ * descriptions. */
+ int flags) /* If the TK_ARGV_NO_DEFAULTS bit is set in
+ * this word, then don't generate information
+ * for default options. */
+{
+ register const Tk_ArgvInfo *infoPtr;
+ size_t width, i, numSpaces;
+ Tcl_Obj *message;
+
+ /*
+ * First, compute the width of the widest option key, so that we can make
+ * everything line up.
+ */
+
+ width = 4;
+ for (i = 0; i < 2; i++) {
+ for (infoPtr = i ? defaultTable : argTable;
+ infoPtr->type != TK_ARGV_END; infoPtr++) {
+ size_t length;
+
+ if (infoPtr->key == NULL) {
+ continue;
+ }
+ length = strlen(infoPtr->key);
+ if (length > width) {
+ width = length;
+ }
+ }
+ }
+
+ message = Tcl_NewStringObj("Command-specific options:", -1);
+ for (i = 0; ; i++) {
+ for (infoPtr = i ? defaultTable : argTable;
+ infoPtr->type != TK_ARGV_END; infoPtr++) {
+ if ((infoPtr->type == TK_ARGV_HELP) && (infoPtr->key == NULL)) {
+ Tcl_AppendPrintfToObj(message, "\n%s", infoPtr->help);
+ continue;
+ }
+ Tcl_AppendPrintfToObj(message, "\n %s:", infoPtr->key);
+ numSpaces = width + 1 - strlen(infoPtr->key);
+ while (numSpaces-- > 0) {
+ Tcl_AppendToObj(message, " ", 1);
+ }
+ Tcl_AppendToObj(message, infoPtr->help, -1);
+ switch (infoPtr->type) {
+ case TK_ARGV_INT:
+ Tcl_AppendPrintfToObj(message, "\n\t\tDefault value: %d",
+ *((int *) infoPtr->dst));
+ break;
+ case TK_ARGV_FLOAT:
+ Tcl_AppendPrintfToObj(message, "\n\t\tDefault value: %f",
+ *((double *) infoPtr->dst));
+ break;
+ case TK_ARGV_STRING: {
+ char *string = *((char **) infoPtr->dst);
+
+ if (string != NULL) {
+ Tcl_AppendPrintfToObj(message,
+ "\n\t\tDefault value: \"%s\"", string);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ if ((flags & TK_ARGV_NO_DEFAULTS) || (i > 0)) {
+ break;
+ }
+ Tcl_AppendToObj(message, "\nGeneric options for all commands:", -1);
+ }
+ Tcl_SetObjResult(interp, message);
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkAtom.c b/tk8.6/generic/tkAtom.c
new file mode 100644
index 0000000..2491fb2
--- /dev/null
+++ b/tk8.6/generic/tkAtom.c
@@ -0,0 +1,215 @@
+/*
+ * tkAtom.c --
+ *
+ * This file manages a cache of X Atoms in order to avoid interactions
+ * with the X server. It's much like the Xmu routines, except it has a
+ * cleaner interface (caller doesn't have to provide permanent storage
+ * for atom names, for example).
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkInt.h"
+
+/*
+ * The following are a list of the predefined atom strings. They should match
+ * those found in xatom.h
+ */
+
+static const char *const atomNameArray[] = {
+ "PRIMARY", "SECONDARY", "ARC",
+ "ATOM", "BITMAP", "CARDINAL",
+ "COLORMAP", "CURSOR", "CUT_BUFFER0",
+ "CUT_BUFFER1", "CUT_BUFFER2", "CUT_BUFFER3",
+ "CUT_BUFFER4", "CUT_BUFFER5", "CUT_BUFFER6",
+ "CUT_BUFFER7", "DRAWABLE", "FONT",
+ "INTEGER", "PIXMAP", "POINT",
+ "RECTANGLE", "RESOURCE_MANAGER", "RGB_COLOR_MAP",
+ "RGB_BEST_MAP", "RGB_BLUE_MAP", "RGB_DEFAULT_MAP",
+ "RGB_GRAY_MAP", "RGB_GREEN_MAP", "RGB_RED_MAP",
+ "STRING", "VISUALID", "WINDOW",
+ "WM_COMMAND", "WM_HINTS", "WM_CLIENT_MACHINE",
+ "WM_ICON_NAME", "WM_ICON_SIZE", "WM_NAME",
+ "WM_NORMAL_HINTS", "WM_SIZE_HINTS", "WM_ZOOM_HINTS",
+ "MIN_SPACE", "NORM_SPACE", "MAX_SPACE",
+ "END_SPACE", "SUPERSCRIPT_X", "SUPERSCRIPT_Y",
+ "SUBSCRIPT_X", "SUBSCRIPT_Y", "UNDERLINE_POSITION",
+ "UNDERLINE_THICKNESS", "STRIKEOUT_ASCENT", "STRIKEOUT_DESCENT",
+ "ITALIC_ANGLE", "X_HEIGHT", "QUAD_WIDTH",
+ "WEIGHT", "POINT_SIZE", "RESOLUTION",
+ "COPYRIGHT", "NOTICE", "FONT_NAME",
+ "FAMILY_NAME", "FULL_NAME", "CAP_HEIGHT",
+ "WM_CLASS", "WM_TRANSIENT_FOR",
+ NULL
+};
+
+/*
+ * Forward references to functions defined in this file:
+ */
+
+static void AtomInit(TkDisplay *dispPtr);
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_InternAtom --
+ *
+ * Given a string, produce the equivalent X atom. This function is
+ * equivalent to XInternAtom, except that it keeps a local cache of
+ * atoms. Once a name is known, the server need not be contacted again
+ * for that name.
+ *
+ * Results:
+ * The return value is the Atom corresponding to name.
+ *
+ * Side effects:
+ * A new entry may be added to the local atom cache.
+ *
+ *--------------------------------------------------------------
+ */
+
+Atom
+Tk_InternAtom(
+ Tk_Window tkwin, /* Window token; map name to atom for this
+ * window's display. */
+ const char *name) /* Name to turn into atom. */
+{
+ TkDisplay *dispPtr;
+ Tcl_HashEntry *hPtr;
+ int isNew;
+
+ dispPtr = ((TkWindow *) tkwin)->dispPtr;
+ if (!dispPtr->atomInit) {
+ AtomInit(dispPtr);
+ }
+
+ hPtr = Tcl_CreateHashEntry(&dispPtr->nameTable, name, &isNew);
+ if (isNew) {
+ Tcl_HashEntry *hPtr2;
+ Atom atom;
+
+ atom = XInternAtom(dispPtr->display, name, False);
+ Tcl_SetHashValue(hPtr, INT2PTR(atom));
+ hPtr2 = Tcl_CreateHashEntry(&dispPtr->atomTable, INT2PTR(atom), &isNew);
+ Tcl_SetHashValue(hPtr2, Tcl_GetHashKey(&dispPtr->nameTable, hPtr));
+ }
+ return (Atom)PTR2INT(Tcl_GetHashValue(hPtr));
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_GetAtomName --
+ *
+ * This function is equivalent to XGetAtomName except that it uses the
+ * local atom cache to avoid contacting the server.
+ *
+ * Results:
+ * The return value is a character string corresponding to the atom given
+ * by "atom". This string's storage space is static: it need not be freed
+ * by the caller, and should not be modified by the caller. If "atom"
+ * doesn't exist on tkwin's display, then the string "?bad atom?" is
+ * returned.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+const char *
+Tk_GetAtomName(
+ Tk_Window tkwin, /* Window token; map atom to name relative to
+ * this window's display. */
+ Atom atom) /* Atom whose name is wanted. */
+{
+ TkDisplay *dispPtr;
+ Tcl_HashEntry *hPtr;
+
+ dispPtr = ((TkWindow *) tkwin)->dispPtr;
+ if (!dispPtr->atomInit) {
+ AtomInit(dispPtr);
+ }
+
+ hPtr = Tcl_FindHashEntry(&dispPtr->atomTable, INT2PTR(atom));
+ if (hPtr == NULL) {
+ const char *name;
+ Tk_ErrorHandler handler;
+ int isNew;
+ char *mustFree = NULL;
+
+ handler = Tk_CreateErrorHandler(dispPtr->display, BadAtom, -1, -1,
+ NULL, NULL);
+ name = mustFree = XGetAtomName(dispPtr->display, atom);
+ if (name == NULL) {
+ name = "?bad atom?";
+ }
+ Tk_DeleteErrorHandler(handler);
+ hPtr = Tcl_CreateHashEntry(&dispPtr->nameTable, name, &isNew);
+ Tcl_SetHashValue(hPtr, INT2PTR(atom));
+ if (mustFree) {
+ XFree(mustFree);
+ }
+ name = Tcl_GetHashKey(&dispPtr->nameTable, hPtr);
+ hPtr = Tcl_CreateHashEntry(&dispPtr->atomTable, INT2PTR(atom), &isNew);
+ Tcl_SetHashValue(hPtr, name);
+ }
+ return Tcl_GetHashValue(hPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * AtomInit --
+ *
+ * Initialize atom-related information for a display.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Tables get initialized, etc. etc..
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+AtomInit(
+ TkDisplay *dispPtr)/* Display to initialize. */
+{
+ Tcl_HashEntry *hPtr;
+ Atom atom;
+
+ dispPtr->atomInit = 1;
+ Tcl_InitHashTable(&dispPtr->nameTable, TCL_STRING_KEYS);
+ Tcl_InitHashTable(&dispPtr->atomTable, TCL_ONE_WORD_KEYS);
+
+ for (atom = 1; atom <= XA_LAST_PREDEFINED; atom++) {
+ const char *name;
+ int isNew;
+
+ hPtr = Tcl_FindHashEntry(&dispPtr->atomTable, INT2PTR(atom));
+ if (hPtr != NULL) {
+ continue;
+ }
+
+ name = atomNameArray[atom - 1];
+ hPtr = Tcl_CreateHashEntry(&dispPtr->nameTable, name, &isNew);
+ Tcl_SetHashValue(hPtr, INT2PTR(atom));
+ name = Tcl_GetHashKey(&dispPtr->nameTable, hPtr);
+ hPtr = Tcl_CreateHashEntry(&dispPtr->atomTable, INT2PTR(atom), &isNew);
+ Tcl_SetHashValue(hPtr, name);
+ }
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkBind.c b/tk8.6/generic/tkBind.c
new file mode 100644
index 0000000..e0971ba
--- /dev/null
+++ b/tk8.6/generic/tkBind.c
@@ -0,0 +1,4365 @@
+/*
+ * tkBind.c --
+ *
+ * This file provides functions that associate Tcl commands with X events
+ * or sequences of X events.
+ *
+ * Copyright (c) 1989-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1998 by Scriptics Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkInt.h"
+
+#ifdef _WIN32
+#include "tkWinInt.h"
+#elif defined(MAC_OSX_TK)
+#include "tkMacOSXInt.h"
+#else
+#include "tkUnixInt.h"
+#endif
+
+/*
+ * File structure:
+ *
+ * Structure definitions and static variables.
+ *
+ * Init/Free this package.
+ *
+ * Tcl "bind" command (actually located in tkCmds.c) core implementation, plus
+ * helpers.
+ *
+ * Tcl "event" command implementation, plus helpers.
+ *
+ * Package-specific common helpers.
+ *
+ * Non-package-specific helpers.
+ */
+
+/*
+ * The following union is used to hold the detail information from an XEvent
+ * (including Tk's XVirtualEvent extension).
+ */
+
+typedef union {
+ KeySym keySym; /* KeySym that corresponds to xkey.keycode. */
+ int button; /* Button that was pressed (xbutton.button). */
+ Tk_Uid name; /* Tk_Uid of virtual event. */
+ ClientData clientData; /* Used when type of Detail is unknown, and to
+ * ensure that all bytes of Detail are
+ * initialized when this structure is used in
+ * a hash key. */
+} Detail;
+
+/*
+ * The structure below represents a binding table. A binding table represents
+ * a domain in which event bindings may occur. It includes a space of objects
+ * relative to which events occur (usually windows, but not always), a history
+ * of recent events in the domain, and a set of mappings that associate
+ * particular Tcl commands with sequences of events in the domain. Multiple
+ * binding tables may exist at once, either because there are multiple
+ * applications open, or because there are multiple domains within an
+ * application with separate event bindings for each (for example, each canvas
+ * widget has a separate binding table for associating events with the items
+ * in the canvas).
+ *
+ * Note: it is probably a bad idea to reduce EVENT_BUFFER_SIZE much below 30.
+ * To see this, consider a triple mouse button click while the Shift key is
+ * down (and auto-repeating). There may be as many as 3 auto-repeat events
+ * after each mouse button press or release (see the first large comment block
+ * within Tk_BindEvent for more on this), for a total of 20 events to cover
+ * the three button presses and two intervening releases. If you reduce
+ * EVENT_BUFFER_SIZE too much, shift multi-clicks will be lost.
+ */
+
+/*
+ * NOTE: The changes which were needed to make Tk work on OSX 10.14 (Mojave)
+ * also demand that the event ring be a bit bigger. It might be wise to
+ * augment the current double-click pattern matching by adding a new
+ * DoubleClick modifier bit which could be set based on the clickCount of the
+ * Apple NSEvent object.
+ */
+
+#ifndef TK_MAC_OSX
+ #define EVENT_BUFFER_SIZE 90
+#else
+ #define EVENT_BUFFER_SIZE 30
+#endif
+
+typedef struct Tk_BindingTable_ {
+ XEvent eventRing[EVENT_BUFFER_SIZE];
+ /* Circular queue of recent events (higher
+ * indices are for more recent events). */
+ Detail detailRing[EVENT_BUFFER_SIZE];
+ /* "Detail" information (keySym, button,
+ * Tk_Uid, or 0) for each entry in
+ * eventRing. */
+ int curEvent; /* Index in eventRing of most recent event.
+ * Newer events have higher indices. */
+ Tcl_HashTable patternTable; /* Used to map from an event to a list of
+ * patterns that may match that event. Keys
+ * are PatternTableKey structs, values are
+ * (PatSeq *). */
+ Tcl_HashTable objectTable; /* Used to map from an object to a list of
+ * patterns associated with that object. Keys
+ * are ClientData, values are (PatSeq *). */
+ Tcl_Interp *interp; /* Interpreter in which commands are
+ * executed. */
+} BindingTable;
+
+/*
+ * The following structure represents virtual event table. A virtual event
+ * table provides a way to map from platform-specific physical events such as
+ * button clicks or key presses to virtual events such as <<Paste>>,
+ * <<Close>>, or <<ScrollWindow>>.
+ *
+ * A virtual event is usually never part of the event stream, but instead is
+ * synthesized inline by matching low-level events. However, a virtual event
+ * may be generated by platform-specific code or by Tcl commands. In that case,
+ * no lookup of the virtual event will need to be done using this table,
+ * because the virtual event is actually in the event stream.
+ */
+
+typedef struct {
+ Tcl_HashTable patternTable; /* Used to map from a physical event to a list
+ * of patterns that may match that event. Keys
+ * are PatternTableKey structs, values are
+ * (PatSeq *). */
+ Tcl_HashTable nameTable; /* Used to map a virtual event name to the
+ * array of physical events that can trigger
+ * it. Keys are the Tk_Uid names of the
+ * virtual events, values are PhysicalsOwned
+ * structs. */
+} VirtualEventTable;
+
+/*
+ * The following structure is used as a key in a patternTable for both binding
+ * tables and a virtual event tables.
+ *
+ * In a binding table, the object field corresponds to the binding tag for the
+ * widget whose bindings are being accessed.
+ *
+ * In a virtual event table, the object field is always NULL. Virtual events
+ * are a global definiton and are not tied to a particular binding tag.
+ *
+ * The same key is used for both types of pattern tables so that the helper
+ * functions that traverse and match patterns will work for both binding
+ * tables and virtual event tables.
+ */
+
+typedef struct {
+ ClientData object; /* For binding table, identifies the binding
+ * tag of the object (or class of objects)
+ * relative to which the event occurred. For
+ * virtual event table, always NULL. */
+ int type; /* Type of event (from X). */
+ Detail detail; /* Additional information, such as keysym,
+ * button, Tk_Uid, or 0 if nothing
+ * additional. */
+} PatternTableKey;
+
+/*
+ * The following structure defines a pattern, which is matched against X
+ * events as part of the process of converting X events into Tcl commands.
+ */
+
+typedef struct {
+ int eventType; /* Type of X event, e.g. ButtonPress. */
+ int needMods; /* Mask of modifiers that must be present (0
+ * means no modifiers are required). */
+ Detail detail; /* Additional information that must match
+ * event. Normally this is 0, meaning no
+ * additional information must match. For
+ * KeyPress and KeyRelease events, a keySym
+ * may be specified to select a particular
+ * keystroke (0 means any keystrokes). For
+ * button events, specifies a particular
+ * button (0 means any buttons are OK). For
+ * virtual events, specifies the Tk_Uid of the
+ * virtual event name (never 0). */
+} TkPattern;
+
+/*
+ * The following structure defines a pattern sequence, which consists of one
+ * or more patterns. In order to trigger, a pattern sequence must match the
+ * most recent X events (first pattern to most recent event, next pattern to
+ * next event, and so on). It is used as the hash value in a patternTable for
+ * both binding tables and virtual event tables.
+ *
+ * In a binding table, it is the sequence of physical events that make up a
+ * binding for an object.
+ *
+ * In a virtual event table, it is the sequence of physical events that define
+ * a virtual event.
+ *
+ * The same structure is used for both types of pattern tables so that the
+ * helper functions that traverse and match patterns will work for both
+ * binding tables and virtual event tables.
+ */
+
+typedef struct PatSeq {
+ int numPats; /* Number of patterns in sequence (usually
+ * 1). */
+ char *script; /* Binding script to evaluate when sequence
+ * matches (ckalloc()ed) */
+ int flags; /* Miscellaneous flag values; see below for
+ * definitions. */
+ struct PatSeq *nextSeqPtr; /* Next in list of all pattern sequences that
+ * have the same initial pattern. NULL means
+ * end of list. */
+ Tcl_HashEntry *hPtr; /* Pointer to hash table entry for the initial
+ * pattern. This is the head of the list of
+ * which nextSeqPtr forms a part. */
+ struct VirtualOwners *voPtr;/* In a binding table, always NULL. In a
+ * virtual event table, identifies the array
+ * of virtual events that can be triggered by
+ * this event. */
+ struct PatSeq *nextObjPtr; /* In a binding table, next in list of all
+ * pattern sequences for the same object (NULL
+ * for end of list). Needed to implement
+ * Tk_DeleteAllBindings. In a virtual event
+ * table, always NULL. */
+ TkPattern pats[1]; /* Array of "numPats" patterns. Only one
+ * element is declared here but in actuality
+ * enough space will be allocated for
+ * "numPats" patterns. To match, pats[0] must
+ * match event n, pats[1] must match event
+ * n-1, etc. */
+} PatSeq;
+
+/*
+ * Flag values for PatSeq structures:
+ *
+ * PAT_NEARBY 1 means that all of the events matching this sequence
+ * must occur with nearby X and Y mouse coordinates and
+ * close in time. This is typically used to restrict
+ * multiple button presses.
+ */
+
+#define PAT_NEARBY 0x1
+
+/*
+ * Constants that define how close together two events must be in milliseconds
+ * or pixels to meet the PAT_NEARBY constraint:
+ */
+
+#define NEARBY_PIXELS 5
+#define NEARBY_MS 500
+
+/*
+ * The following structure keeps track of all the virtual events that are
+ * associated with a particular physical event. It is pointed to by the voPtr
+ * field in a PatSeq in the patternTable of a virtual event table.
+ */
+
+typedef struct VirtualOwners {
+ int numOwners; /* Number of virtual events to trigger. */
+ Tcl_HashEntry *owners[1]; /* Array of pointers to entries in nameTable.
+ * Enough space will actually be allocated for
+ * numOwners hash entries. */
+} VirtualOwners;
+
+/*
+ * The following structure is used in the nameTable of a virtual event table
+ * to associate a virtual event with all the physical events that can trigger
+ * it.
+ */
+typedef struct {
+ int numOwned; /* Number of physical events owned. */
+ PatSeq *patSeqs[1]; /* Array of pointers to physical event
+ * patterns. Enough space will actually be
+ * allocated to hold numOwned. */
+} PhysicalsOwned;
+
+/*
+ * One of the following structures exists for each interpreter. This structure
+ * keeps track of the current display and screen in the interpreter, so that a
+ * command can be invoked whenever the display/screen changes (the command does
+ * things like point tk::Priv at a display-specific structure).
+ */
+
+typedef struct {
+ TkDisplay *curDispPtr; /* Display for last binding command invoked in
+ * this application. */
+ int curScreenIndex; /* Index of screen for last binding command */
+ int bindingDepth; /* Number of active instances of Tk_BindEvent
+ * in this application. */
+} ScreenInfo;
+
+/*
+ * The following structure keeps track of all the information local to the
+ * binding package on a per interpreter basis.
+ */
+
+typedef struct TkBindInfo_ {
+ VirtualEventTable virtualEventTable;
+ /* The virtual events that exist in this
+ * interpreter. */
+ ScreenInfo screenInfo; /* Keeps track of the current display and
+ * screen, so it can be restored after a
+ * binding has executed. */
+ int deleted; /* 1 the application has been deleted but the
+ * structure has been preserved. */
+} BindInfo;
+
+/*
+ * In X11R4 and earlier versions, XStringToKeysym is ridiculously slow. The
+ * data structure and hash table below, along with the code that uses them,
+ * implement a fast mapping from strings to keysyms. In X11R5 and later
+ * releases XStringToKeysym is plenty fast so this stuff isn't needed. The
+ * #define REDO_KEYSYM_LOOKUP is normally undefined, so that XStringToKeysym
+ * gets used. It can be set in the Makefile to enable the use of the hash
+ * table below.
+ */
+
+#ifdef REDO_KEYSYM_LOOKUP
+typedef struct {
+ const char *name; /* Name of keysym. */
+ KeySym value; /* Numeric identifier for keysym. */
+} KeySymInfo;
+static const KeySymInfo keyArray[] = {
+#ifndef lint
+#include "ks_names.h"
+#endif
+ {NULL, 0}
+};
+static Tcl_HashTable keySymTable; /* keyArray hashed by keysym value. */
+static Tcl_HashTable nameTable; /* keyArray hashed by keysym name. */
+#endif /* REDO_KEYSYM_LOOKUP */
+
+/*
+ * Set to non-zero when the package-wide static variables have been
+ * initialized.
+ */
+
+static int initialized = 0;
+TCL_DECLARE_MUTEX(bindMutex)
+
+/*
+ * A hash table is kept to map from the string names of event modifiers to
+ * information about those modifiers. The structure for storing this
+ * information, and the hash table built at initialization time, are defined
+ * below.
+ */
+
+typedef struct {
+ const char *name; /* Name of modifier. */
+ int mask; /* Button/modifier mask value, such as
+ * Button1Mask. */
+ int flags; /* Various flags; see below for
+ * definitions. */
+} ModInfo;
+
+/*
+ * Flags for ModInfo structures:
+ *
+ * DOUBLE - Non-zero means duplicate this event,
+ * e.g. for double-clicks.
+ * TRIPLE - Non-zero means triplicate this event,
+ * e.g. for triple-clicks.
+ * QUADRUPLE - Non-zero means quadruple this event,
+ * e.g. for 4-fold-clicks.
+ * MULT_CLICKS - Combination of all of above.
+ */
+
+#define DOUBLE 1
+#define TRIPLE 2
+#define QUADRUPLE 4
+#define MULT_CLICKS 7
+
+static const ModInfo modArray[] = {
+ {"Control", ControlMask, 0},
+ {"Shift", ShiftMask, 0},
+ {"Lock", LockMask, 0},
+ {"Meta", META_MASK, 0},
+ {"M", META_MASK, 0},
+ {"Alt", ALT_MASK, 0},
+ {"Extended", EXTENDED_MASK, 0},
+ {"B1", Button1Mask, 0},
+ {"Button1", Button1Mask, 0},
+ {"B2", Button2Mask, 0},
+ {"Button2", Button2Mask, 0},
+ {"B3", Button3Mask, 0},
+ {"Button3", Button3Mask, 0},
+ {"B4", Button4Mask, 0},
+ {"Button4", Button4Mask, 0},
+ {"B5", Button5Mask, 0},
+ {"Button5", Button5Mask, 0},
+ {"Mod1", Mod1Mask, 0},
+ {"M1", Mod1Mask, 0},
+ {"Command", Mod1Mask, 0},
+ {"Mod2", Mod2Mask, 0},
+ {"M2", Mod2Mask, 0},
+ {"Option", Mod2Mask, 0},
+ {"Mod3", Mod3Mask, 0},
+ {"M3", Mod3Mask, 0},
+ {"Mod4", Mod4Mask, 0},
+ {"M4", Mod4Mask, 0},
+ {"Mod5", Mod5Mask, 0},
+ {"M5", Mod5Mask, 0},
+ {"Double", 0, DOUBLE},
+ {"Triple", 0, TRIPLE},
+ {"Quadruple", 0, QUADRUPLE},
+ {"Any", 0, 0}, /* Ignored: historical relic */
+ {NULL, 0, 0}
+};
+static Tcl_HashTable modTable;
+
+/*
+ * This module also keeps a hash table mapping from event names to information
+ * about those events. The structure, an array to use to initialize the hash
+ * table, and the hash table are all defined below.
+ */
+
+typedef struct {
+ const char *name; /* Name of event. */
+ int type; /* Event type for X, such as ButtonPress. */
+ int eventMask; /* Mask bits (for XSelectInput) for this event
+ * type. */
+} EventInfo;
+
+/*
+ * Note: some of the masks below are an OR-ed combination of several masks.
+ * This is necessary because X doesn't report up events unless you also ask
+ * for down events. Also, X doesn't report button state in motion events
+ * unless you've asked about button events.
+ */
+
+static const EventInfo eventArray[] = {
+ {"Key", KeyPress, KeyPressMask},
+ {"KeyPress", KeyPress, KeyPressMask},
+ {"KeyRelease", KeyRelease, KeyPressMask|KeyReleaseMask},
+ {"Button", ButtonPress, ButtonPressMask},
+ {"ButtonPress", ButtonPress, ButtonPressMask},
+ {"ButtonRelease", ButtonRelease,
+ ButtonPressMask|ButtonReleaseMask},
+ {"Motion", MotionNotify,
+ ButtonPressMask|PointerMotionMask},
+ {"Enter", EnterNotify, EnterWindowMask},
+ {"Leave", LeaveNotify, LeaveWindowMask},
+ {"FocusIn", FocusIn, FocusChangeMask},
+ {"FocusOut", FocusOut, FocusChangeMask},
+ {"Expose", Expose, ExposureMask},
+ {"Visibility", VisibilityNotify, VisibilityChangeMask},
+ {"Destroy", DestroyNotify, StructureNotifyMask},
+ {"Unmap", UnmapNotify, StructureNotifyMask},
+ {"Map", MapNotify, StructureNotifyMask},
+ {"Reparent", ReparentNotify, StructureNotifyMask},
+ {"Configure", ConfigureNotify, StructureNotifyMask},
+ {"Gravity", GravityNotify, StructureNotifyMask},
+ {"Circulate", CirculateNotify, StructureNotifyMask},
+ {"Property", PropertyNotify, PropertyChangeMask},
+ {"Colormap", ColormapNotify, ColormapChangeMask},
+ {"Activate", ActivateNotify, ActivateMask},
+ {"Deactivate", DeactivateNotify, ActivateMask},
+ {"MouseWheel", MouseWheelEvent, MouseWheelMask},
+ {"CirculateRequest", CirculateRequest, SubstructureRedirectMask},
+ {"ConfigureRequest", ConfigureRequest, SubstructureRedirectMask},
+ {"Create", CreateNotify, SubstructureNotifyMask},
+ {"MapRequest", MapRequest, SubstructureRedirectMask},
+ {"ResizeRequest", ResizeRequest, ResizeRedirectMask},
+ {NULL, 0, 0}
+};
+static Tcl_HashTable eventTable;
+
+/*
+ * The defines and table below are used to classify events into various
+ * groups. The reason for this is that logically identical fields (e.g.
+ * "state") appear at different places in different types of events. The
+ * classification masks can be used to figure out quickly where to extract
+ * information from events.
+ */
+
+#define KEY 0x1
+#define BUTTON 0x2
+#define MOTION 0x4
+#define CROSSING 0x8
+#define FOCUS 0x10
+#define EXPOSE 0x20
+#define VISIBILITY 0x40
+#define CREATE 0x80
+#define DESTROY 0x100
+#define UNMAP 0x200
+#define MAP 0x400
+#define REPARENT 0x800
+#define CONFIG 0x1000
+#define GRAVITY 0x2000
+#define CIRC 0x4000
+#define PROP 0x8000
+#define COLORMAP 0x10000
+#define VIRTUAL 0x20000
+#define ACTIVATE 0x40000
+#define MAPREQ 0x80000
+#define CONFIGREQ 0x100000
+#define RESIZEREQ 0x200000
+#define CIRCREQ 0x400000
+
+#define KEY_BUTTON_MOTION_VIRTUAL (KEY|BUTTON|MOTION|VIRTUAL)
+#define KEY_BUTTON_MOTION_CROSSING (KEY|BUTTON|MOTION|VIRTUAL|CROSSING)
+
+static const int flagArray[TK_LASTEVENT] = {
+ /* Not used */ 0,
+ /* Not used */ 0,
+ /* KeyPress */ KEY,
+ /* KeyRelease */ KEY,
+ /* ButtonPress */ BUTTON,
+ /* ButtonRelease */ BUTTON,
+ /* MotionNotify */ MOTION,
+ /* EnterNotify */ CROSSING,
+ /* LeaveNotify */ CROSSING,
+ /* FocusIn */ FOCUS,
+ /* FocusOut */ FOCUS,
+ /* KeymapNotify */ 0,
+ /* Expose */ EXPOSE,
+ /* GraphicsExpose */ EXPOSE,
+ /* NoExpose */ 0,
+ /* VisibilityNotify */ VISIBILITY,
+ /* CreateNotify */ CREATE,
+ /* DestroyNotify */ DESTROY,
+ /* UnmapNotify */ UNMAP,
+ /* MapNotify */ MAP,
+ /* MapRequest */ MAPREQ,
+ /* ReparentNotify */ REPARENT,
+ /* ConfigureNotify */ CONFIG,
+ /* ConfigureRequest */ CONFIGREQ,
+ /* GravityNotify */ GRAVITY,
+ /* ResizeRequest */ RESIZEREQ,
+ /* CirculateNotify */ CIRC,
+ /* CirculateRequest */ 0,
+ /* PropertyNotify */ PROP,
+ /* SelectionClear */ 0,
+ /* SelectionRequest */ 0,
+ /* SelectionNotify */ 0,
+ /* ColormapNotify */ COLORMAP,
+ /* ClientMessage */ 0,
+ /* MappingNotify */ 0,
+ /* VirtualEvent */ VIRTUAL,
+ /* Activate */ ACTIVATE,
+ /* Deactivate */ ACTIVATE,
+ /* MouseWheel */ KEY
+};
+
+/*
+ * The following table is used to map between the location where an generated
+ * event should be queued and the string used to specify the location.
+ */
+
+static const TkStateMap queuePosition[] = {
+ {-1, "now"},
+ {TCL_QUEUE_HEAD, "head"},
+ {TCL_QUEUE_MARK, "mark"},
+ {TCL_QUEUE_TAIL, "tail"},
+ {-2, NULL}
+};
+
+/*
+ * The following tables are used as a two-way map between X's internal numeric
+ * values for fields in an XEvent and the strings used in Tcl. The tables are
+ * used both when constructing an XEvent from user input and when providing
+ * data from an XEvent to the user.
+ */
+
+static const TkStateMap notifyMode[] = {
+ {NotifyNormal, "NotifyNormal"},
+ {NotifyGrab, "NotifyGrab"},
+ {NotifyUngrab, "NotifyUngrab"},
+ {NotifyWhileGrabbed, "NotifyWhileGrabbed"},
+ {-1, NULL}
+};
+
+static const TkStateMap notifyDetail[] = {
+ {NotifyAncestor, "NotifyAncestor"},
+ {NotifyVirtual, "NotifyVirtual"},
+ {NotifyInferior, "NotifyInferior"},
+ {NotifyNonlinear, "NotifyNonlinear"},
+ {NotifyNonlinearVirtual, "NotifyNonlinearVirtual"},
+ {NotifyPointer, "NotifyPointer"},
+ {NotifyPointerRoot, "NotifyPointerRoot"},
+ {NotifyDetailNone, "NotifyDetailNone"},
+ {-1, NULL}
+};
+
+static const TkStateMap circPlace[] = {
+ {PlaceOnTop, "PlaceOnTop"},
+ {PlaceOnBottom, "PlaceOnBottom"},
+ {-1, NULL}
+};
+
+static const TkStateMap visNotify[] = {
+ {VisibilityUnobscured, "VisibilityUnobscured"},
+ {VisibilityPartiallyObscured, "VisibilityPartiallyObscured"},
+ {VisibilityFullyObscured, "VisibilityFullyObscured"},
+ {-1, NULL}
+};
+
+static const TkStateMap configureRequestDetail[] = {
+ {None, "None"},
+ {Above, "Above"},
+ {Below, "Below"},
+ {BottomIf, "BottomIf"},
+ {TopIf, "TopIf"},
+ {Opposite, "Opposite"},
+ {-1, NULL}
+};
+
+static const TkStateMap propNotify[] = {
+ {PropertyNewValue, "NewValue"},
+ {PropertyDelete, "Delete"},
+ {-1, NULL}
+};
+
+/*
+ * Prototypes for local functions defined in this file:
+ */
+
+static void ChangeScreen(Tcl_Interp *interp, char *dispName,
+ int screenIndex);
+static int CreateVirtualEvent(Tcl_Interp *interp,
+ VirtualEventTable *vetPtr, char *virtString,
+ const char *eventString);
+static int DeleteVirtualEvent(Tcl_Interp *interp,
+ VirtualEventTable *vetPtr, char *virtString,
+ const char *eventString);
+static void DeleteVirtualEventTable(VirtualEventTable *vetPtr);
+static void ExpandPercents(TkWindow *winPtr, const char *before,
+ XEvent *eventPtr,KeySym keySym,
+ unsigned int scriptCount, Tcl_DString *dsPtr);
+static PatSeq * FindSequence(Tcl_Interp *interp,
+ Tcl_HashTable *patternTablePtr, ClientData object,
+ const char *eventString, int create,
+ int allowVirtual, unsigned long *maskPtr);
+static void GetAllVirtualEvents(Tcl_Interp *interp,
+ VirtualEventTable *vetPtr);
+static char * GetField(char *p, char *copy, int size);
+static Tcl_Obj * GetPatternObj(PatSeq *psPtr);
+static int GetVirtualEvent(Tcl_Interp *interp,
+ VirtualEventTable *vetPtr, Tcl_Obj *virtName);
+static Tk_Uid GetVirtualEventUid(Tcl_Interp *interp,
+ char *virtString);
+static int HandleEventGenerate(Tcl_Interp *interp, Tk_Window main,
+ int objc, Tcl_Obj *const objv[]);
+static void InitVirtualEventTable(VirtualEventTable *vetPtr);
+static PatSeq * MatchPatterns(TkDisplay *dispPtr,
+ BindingTable *bindPtr, PatSeq *psPtr,
+ PatSeq *bestPtr, ClientData *objectPtr,
+ PatSeq **sourcePtrPtr);
+static int NameToWindow(Tcl_Interp *interp, Tk_Window main,
+ Tcl_Obj *objPtr, Tk_Window *tkwinPtr);
+static int ParseEventDescription(Tcl_Interp *interp,
+ const char **eventStringPtr, TkPattern *patPtr,
+ unsigned long *eventMaskPtr);
+static void DoWarp(ClientData clientData);
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkBindInit --
+ *
+ * This function is called when an application is created. It initializes
+ * all the structures used by bindings and virtual events. It must be
+ * called before any other functions in this file are called.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory allocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+TkBindInit(
+ TkMainInfo *mainPtr) /* The newly created application. */
+{
+ BindInfo *bindInfoPtr;
+
+ if (sizeof(XEvent) < sizeof(XVirtualEvent)) {
+ Tcl_Panic("TkBindInit: virtual events can't be supported");
+ }
+
+ /*
+ * Initialize the static data structures used by the binding package. They
+ * are only initialized once, no matter how many interps are created.
+ */
+
+ if (!initialized) {
+ Tcl_MutexLock(&bindMutex);
+ if (!initialized) {
+ Tcl_HashEntry *hPtr;
+ const ModInfo *modPtr;
+ const EventInfo *eiPtr;
+ int newEntry;
+#ifdef REDO_KEYSYM_LOOKUP
+ const KeySymInfo *kPtr;
+
+ Tcl_InitHashTable(&keySymTable, TCL_STRING_KEYS);
+ Tcl_InitHashTable(&nameTable, TCL_ONE_WORD_KEYS);
+ for (kPtr = keyArray; kPtr->name != NULL; kPtr++) {
+ hPtr = Tcl_CreateHashEntry(&keySymTable, kPtr->name, &newEntry);
+ Tcl_SetHashValue(hPtr, kPtr->value);
+ hPtr = Tcl_CreateHashEntry(&nameTable, (char *) kPtr->value,
+ &newEntry);
+ if (newEntry) {
+ Tcl_SetHashValue(hPtr, kPtr->name);
+ }
+ }
+#endif /* REDO_KEYSYM_LOOKUP */
+
+ Tcl_InitHashTable(&modTable, TCL_STRING_KEYS);
+ for (modPtr = modArray; modPtr->name != NULL; modPtr++) {
+ hPtr = Tcl_CreateHashEntry(&modTable, modPtr->name, &newEntry);
+ Tcl_SetHashValue(hPtr, modPtr);
+ }
+
+ Tcl_InitHashTable(&eventTable, TCL_STRING_KEYS);
+ for (eiPtr = eventArray; eiPtr->name != NULL; eiPtr++) {
+ hPtr = Tcl_CreateHashEntry(&eventTable, eiPtr->name, &newEntry);
+ Tcl_SetHashValue(hPtr, eiPtr);
+ }
+ initialized = 1;
+ }
+ Tcl_MutexUnlock(&bindMutex);
+ }
+
+ mainPtr->bindingTable = Tk_CreateBindingTable(mainPtr->interp);
+
+ bindInfoPtr = ckalloc(sizeof(BindInfo));
+ InitVirtualEventTable(&bindInfoPtr->virtualEventTable);
+ bindInfoPtr->screenInfo.curDispPtr = NULL;
+ bindInfoPtr->screenInfo.curScreenIndex = -1;
+ bindInfoPtr->screenInfo.bindingDepth = 0;
+ bindInfoPtr->deleted = 0;
+ mainPtr->bindInfo = bindInfoPtr;
+
+ TkpInitializeMenuBindings(mainPtr->interp, mainPtr->bindingTable);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkBindFree --
+ *
+ * This function is called when an application is deleted. It deletes all
+ * the structures used by bindings and virtual events.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory freed.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+TkBindFree(
+ TkMainInfo *mainPtr) /* The newly created application. */
+{
+ BindInfo *bindInfoPtr;
+
+ Tk_DeleteBindingTable(mainPtr->bindingTable);
+ mainPtr->bindingTable = NULL;
+
+ bindInfoPtr = mainPtr->bindInfo;
+ DeleteVirtualEventTable(&bindInfoPtr->virtualEventTable);
+ bindInfoPtr->deleted = 1;
+ Tcl_EventuallyFree(bindInfoPtr, TCL_DYNAMIC);
+ mainPtr->bindInfo = NULL;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CreateBindingTable --
+ *
+ * Set up a new domain in which event bindings may be created.
+ *
+ * Results:
+ * The return value is a token for the new table, which must be passed to
+ * functions like Tk_CreateBinding.
+ *
+ * Side effects:
+ * Memory is allocated for the new table.
+ *
+ *--------------------------------------------------------------
+ */
+
+Tk_BindingTable
+Tk_CreateBindingTable(
+ Tcl_Interp *interp) /* Interpreter to associate with the binding
+ * table: commands are executed in this
+ * interpreter. */
+{
+ BindingTable *bindPtr = ckalloc(sizeof(BindingTable));
+ int i;
+
+ /*
+ * Create and initialize a new binding table.
+ */
+
+ for (i = 0; i < EVENT_BUFFER_SIZE; i++) {
+ bindPtr->eventRing[i].type = -1;
+ }
+ bindPtr->curEvent = 0;
+ Tcl_InitHashTable(&bindPtr->patternTable,
+ sizeof(PatternTableKey)/sizeof(int));
+ Tcl_InitHashTable(&bindPtr->objectTable, TCL_ONE_WORD_KEYS);
+ bindPtr->interp = interp;
+ return bindPtr;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_DeleteBindingTable --
+ *
+ * Destroy a binding table and free up all its memory. The caller should
+ * not use bindingTable again after this function returns.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory is freed.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_DeleteBindingTable(
+ Tk_BindingTable bindPtr) /* Token for the binding table to destroy. */
+{
+ PatSeq *psPtr, *nextPtr;
+ Tcl_HashEntry *hPtr;
+ Tcl_HashSearch search;
+
+ /*
+ * Find and delete all of the patterns associated with the binding table.
+ */
+
+ for (hPtr = Tcl_FirstHashEntry(&bindPtr->patternTable, &search);
+ hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
+ for (psPtr = Tcl_GetHashValue(hPtr); psPtr != NULL; psPtr = nextPtr) {
+ nextPtr = psPtr->nextSeqPtr;
+ ckfree(psPtr->script);
+ ckfree(psPtr);
+ }
+ }
+
+ /*
+ * Clean up the rest of the information associated with the binding table.
+ */
+
+ Tcl_DeleteHashTable(&bindPtr->patternTable);
+ Tcl_DeleteHashTable(&bindPtr->objectTable);
+ ckfree(bindPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CreateBinding --
+ *
+ * Add a binding to a binding table, so that future calls to Tk_BindEvent
+ * may execute the command in the binding.
+ *
+ * Results:
+ * The return value is 0 if an error occurred while setting up the
+ * binding. In this case, an error message will be left in the interp's
+ * result. If all went well then the return value is a mask of the event
+ * types that must be made available to Tk_BindEvent in order to properly
+ * detect when this binding triggers. This value can be used to determine
+ * what events to select for in a window, for example.
+ *
+ * Side effects:
+ * An existing binding on the same event sequence may be replaced. The
+ * new binding may cause future calls to Tk_BindEvent to behave
+ * differently than they did previously.
+ *
+ *--------------------------------------------------------------
+ */
+
+unsigned long
+Tk_CreateBinding(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tk_BindingTable bindPtr, /* Table in which to create binding. */
+ ClientData object, /* Token for object with which binding is
+ * associated. */
+ const char *eventString, /* String describing event sequence that
+ * triggers binding. */
+ const char *script, /* Contains Tcl script to execute when
+ * binding triggers. */
+ int append) /* 0 means replace any existing binding for
+ * eventString; 1 means append to that
+ * binding. If the existing binding is for a
+ * callback function and not a Tcl command
+ * string, the existing binding will always be
+ * replaced. */
+{
+ PatSeq *psPtr;
+ unsigned long eventMask;
+ char *newStr, *oldStr;
+
+ if (!*script) {
+ /* Silently ignore empty scripts -- see SF#3006842 */
+ return 1;
+ }
+ psPtr = FindSequence(interp, &bindPtr->patternTable, object, eventString,
+ 1, 1, &eventMask);
+ if (psPtr == NULL) {
+ return 0;
+ }
+ if (psPtr->script == NULL) {
+ int isNew;
+ Tcl_HashEntry *hPtr;
+
+ /*
+ * This pattern sequence was just created. Link the pattern into the
+ * list associated with the object, so that if the object goes away,
+ * these bindings will all automatically be deleted.
+ */
+
+ hPtr = Tcl_CreateHashEntry(&bindPtr->objectTable, (char *) object,
+ &isNew);
+ if (isNew) {
+ psPtr->nextObjPtr = NULL;
+ } else {
+ psPtr->nextObjPtr = Tcl_GetHashValue(hPtr);
+ }
+ Tcl_SetHashValue(hPtr, psPtr);
+ }
+
+ oldStr = psPtr->script;
+ if ((append != 0) && (oldStr != NULL)) {
+ size_t length1 = strlen(oldStr), length2 = strlen(script);
+
+ newStr = ckalloc(length1 + length2 + 2);
+ memcpy(newStr, oldStr, length1);
+ newStr[length1] = '\n';
+ memcpy(newStr+length1+1, script, length2+1);
+ } else {
+ size_t length = strlen(script);
+
+ newStr = ckalloc(length + 1);
+ memcpy(newStr, script, length+1);
+ }
+ if (oldStr != NULL) {
+ ckfree(oldStr);
+ }
+ psPtr->script = newStr;
+ return eventMask;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_DeleteBinding --
+ *
+ * Remove an event binding from a binding table.
+ *
+ * Results:
+ * The result is a standard Tcl return value. If an error occurs then the
+ * interp's result will contain an error message.
+ *
+ * Side effects:
+ * The binding given by object and eventString is removed from
+ * bindingTable.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_DeleteBinding(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tk_BindingTable bindPtr, /* Table in which to delete binding. */
+ ClientData object, /* Token for object with which binding is
+ * associated. */
+ const char *eventString) /* String describing event sequence that
+ * triggers binding. */
+{
+ PatSeq *psPtr, *prevPtr;
+ unsigned long eventMask;
+ Tcl_HashEntry *hPtr;
+
+ psPtr = FindSequence(interp, &bindPtr->patternTable, object, eventString,
+ 0, 1, &eventMask);
+ if (psPtr == NULL) {
+ Tcl_ResetResult(interp);
+ return TCL_OK;
+ }
+
+ /*
+ * Unlink the binding from the list for its object, then from the list for
+ * its pattern.
+ */
+
+ hPtr = Tcl_FindHashEntry(&bindPtr->objectTable, (char *) object);
+ if (hPtr == NULL) {
+ Tcl_Panic("Tk_DeleteBinding couldn't find object table entry");
+ }
+ prevPtr = Tcl_GetHashValue(hPtr);
+ if (prevPtr == psPtr) {
+ Tcl_SetHashValue(hPtr, psPtr->nextObjPtr);
+ } else {
+ for ( ; ; prevPtr = prevPtr->nextObjPtr) {
+ if (prevPtr == NULL) {
+ Tcl_Panic("Tk_DeleteBinding couldn't find on object list");
+ }
+ if (prevPtr->nextObjPtr == psPtr) {
+ prevPtr->nextObjPtr = psPtr->nextObjPtr;
+ break;
+ }
+ }
+ }
+ prevPtr = Tcl_GetHashValue(psPtr->hPtr);
+ if (prevPtr == psPtr) {
+ if (psPtr->nextSeqPtr == NULL) {
+ Tcl_DeleteHashEntry(psPtr->hPtr);
+ } else {
+ Tcl_SetHashValue(psPtr->hPtr, psPtr->nextSeqPtr);
+ }
+ } else {
+ for ( ; ; prevPtr = prevPtr->nextSeqPtr) {
+ if (prevPtr == NULL) {
+ Tcl_Panic("Tk_DeleteBinding couldn't find on hash chain");
+ }
+ if (prevPtr->nextSeqPtr == psPtr) {
+ prevPtr->nextSeqPtr = psPtr->nextSeqPtr;
+ break;
+ }
+ }
+ }
+
+ ckfree(psPtr->script);
+ ckfree(psPtr);
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_GetBinding --
+ *
+ * Return the script associated with a given event string.
+ *
+ * Results:
+ * The return value is a pointer to the script associated with
+ * eventString for object in the domain given by bindingTable. If there
+ * is no binding for eventString, or if eventString is improperly formed,
+ * then NULL is returned and an error message is left in the interp's
+ * result. The return value is semi-static: it will persist until the
+ * binding is changed or deleted.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+const char *
+Tk_GetBinding(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Tk_BindingTable bindPtr, /* Table in which to look for binding. */
+ ClientData object, /* Token for object with which binding is
+ * associated. */
+ const char *eventString) /* String describing event sequence that
+ * triggers binding. */
+{
+ PatSeq *psPtr;
+ unsigned long eventMask;
+
+ psPtr = FindSequence(interp, &bindPtr->patternTable, object, eventString,
+ 0, 1, &eventMask);
+ if (psPtr == NULL) {
+ return NULL;
+ }
+ return psPtr->script;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_GetAllBindings --
+ *
+ * Return a list of event strings for all the bindings associated with a
+ * given object.
+ *
+ * Results:
+ * There is no return value. The interp's result is modified to hold a
+ * Tcl list with one entry for each binding associated with object in
+ * bindingTable. Each entry in the list contains the event string
+ * associated with one binding.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_GetAllBindings(
+ Tcl_Interp *interp, /* Interpreter returning result or error. */
+ Tk_BindingTable bindPtr, /* Table in which to look for bindings. */
+ ClientData object) /* Token for object. */
+{
+ PatSeq *psPtr;
+ Tcl_HashEntry *hPtr;
+ Tcl_Obj *resultObj;
+
+ hPtr = Tcl_FindHashEntry(&bindPtr->objectTable, (char *) object);
+ if (hPtr == NULL) {
+ return;
+ }
+
+ resultObj = Tcl_NewObj();
+ for (psPtr = Tcl_GetHashValue(hPtr); psPtr != NULL;
+ psPtr = psPtr->nextObjPtr) {
+ /*
+ * For each binding, output information about each of the patterns in
+ * its sequence.
+ */
+
+ Tcl_ListObjAppendElement(NULL, resultObj, GetPatternObj(psPtr));
+ }
+ Tcl_SetObjResult(interp, resultObj);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_DeleteAllBindings --
+ *
+ * Remove all bindings associated with a given object in a given binding
+ * table.
+ *
+ * Results:
+ * All bindings associated with object are removed from bindingTable.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_DeleteAllBindings(
+ Tk_BindingTable bindPtr, /* Table in which to delete bindings. */
+ ClientData object) /* Token for object. */
+{
+ PatSeq *psPtr, *prevPtr;
+ PatSeq *nextPtr;
+ Tcl_HashEntry *hPtr;
+
+ hPtr = Tcl_FindHashEntry(&bindPtr->objectTable, (char *) object);
+ if (hPtr == NULL) {
+ return;
+ }
+ for (psPtr = Tcl_GetHashValue(hPtr); psPtr != NULL;
+ psPtr = nextPtr) {
+ nextPtr = psPtr->nextObjPtr;
+
+ /*
+ * Be sure to remove each binding from its hash chain in the pattern
+ * table. If this is the last pattern in the chain, then delete the
+ * hash entry too.
+ */
+
+ prevPtr = Tcl_GetHashValue(psPtr->hPtr);
+ if (prevPtr == psPtr) {
+ if (psPtr->nextSeqPtr == NULL) {
+ Tcl_DeleteHashEntry(psPtr->hPtr);
+ } else {
+ Tcl_SetHashValue(psPtr->hPtr, psPtr->nextSeqPtr);
+ }
+ } else {
+ for ( ; ; prevPtr = prevPtr->nextSeqPtr) {
+ if (prevPtr == NULL) {
+ Tcl_Panic("Tk_DeleteAllBindings couldn't find on hash chain");
+ }
+ if (prevPtr->nextSeqPtr == psPtr) {
+ prevPtr->nextSeqPtr = psPtr->nextSeqPtr;
+ break;
+ }
+ }
+ }
+ ckfree(psPtr->script);
+ ckfree(psPtr);
+ }
+ Tcl_DeleteHashEntry(hPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_BindEvent --
+ *
+ * This function is invoked to process an X event. The event is added to
+ * those recorded for the binding table. Then each of the objects at
+ * *objectPtr is checked in order to see if it has a binding that matches
+ * the recent events. If so, the most specific binding is invoked for
+ * each object.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Depends on the script associated with the matching binding.
+ *
+ * All Tcl binding scripts for each object are accumulated before the
+ * first binding is evaluated. If the action of a Tcl binding is to
+ * change or delete a binding, or delete the window associated with the
+ * binding, all the original Tcl binding scripts will still fire.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+Tk_BindEvent(
+ Tk_BindingTable bindPtr, /* Table in which to look for bindings. */
+ XEvent *eventPtr, /* What actually happened. */
+ Tk_Window tkwin, /* Window on display where event occurred
+ * (needed in order to locate display
+ * information). */
+ int numObjects, /* Number of objects at *objectPtr. */
+ ClientData *objectPtr) /* Array of one or more objects to check for a
+ * matching binding. */
+{
+ TkDisplay *dispPtr;
+ ScreenInfo *screenPtr;
+ BindInfo *bindInfoPtr;
+ TkDisplay *oldDispPtr;
+ XEvent *ringPtr;
+ PatSeq *vMatchDetailList, *vMatchNoDetailList;
+ int flags, oldScreen;
+ unsigned int scriptCount;
+ Tcl_Interp *interp;
+ Tcl_DString scripts;
+ Tcl_InterpState interpState;
+ Detail detail;
+ char *p, *end;
+ TkWindow *winPtr = (TkWindow *) tkwin;
+ PatternTableKey key;
+
+ /*
+ * Ignore events on windows that don't have names: these are windows like
+ * wrapper windows that shouldn't be visible to the application.
+ */
+
+ if (winPtr->pathName == NULL) {
+ return;
+ }
+
+ /*
+ * Ignore the event completely if it is an Enter, Leave, FocusIn, or
+ * FocusOut event with detail NotifyInferior. The reason for ignoring
+ * these events is that we don't want transitions between a window and its
+ * children to visible to bindings on the parent: this would cause
+ * problems for mega-widgets, since the internal structure of a
+ * mega-widget isn't supposed to be visible to people watching the parent.
+ */
+
+ if ((eventPtr->type == EnterNotify) || (eventPtr->type == LeaveNotify)) {
+ if (eventPtr->xcrossing.detail == NotifyInferior) {
+ return;
+ }
+ }
+ if ((eventPtr->type == FocusIn) || (eventPtr->type == FocusOut)) {
+ if (eventPtr->xfocus.detail == NotifyInferior) {
+ return;
+ }
+ }
+
+ /*
+ * Ignore event types which are not in flagArray and all zeroes there.
+ * Most notably, NoExpose events can fill the ring buffer and disturb
+ * (thus masking out) event sequences of interest.
+ */
+
+ if ((eventPtr->type >= TK_LASTEVENT) || !flagArray[eventPtr->type]) {
+ return;
+ }
+
+ dispPtr = ((TkWindow *) tkwin)->dispPtr;
+ bindInfoPtr = winPtr->mainPtr->bindInfo;
+
+ /*
+ * Add the new event to the ring of saved events for the binding table.
+ * Two tricky points:
+ *
+ * 1. Combine consecutive MotionNotify events. Do this by putting the new
+ * event *on top* of the previous event.
+ * 2. If a modifier key is held down, it auto-repeats to generate
+ * continuous KeyPress and KeyRelease events. These can flush the event
+ * ring so that valuable information is lost (such as repeated button
+ * clicks). To handle this, check for the special case of a modifier
+ * KeyPress arriving when the previous two events are a KeyRelease and
+ * KeyPress of the same key. If this happens, mark the most recent
+ * event (the KeyRelease) invalid and put the new event on top of the
+ * event before that (the KeyPress).
+ */
+
+ if ((eventPtr->type == MotionNotify)
+ && (bindPtr->eventRing[bindPtr->curEvent].type == MotionNotify)) {
+ /*
+ * Don't advance the ring pointer.
+ */
+ } else if (eventPtr->type == KeyPress) {
+ int i;
+
+ for (i = 0; ; i++) {
+ if (i >= dispPtr->numModKeyCodes) {
+ goto advanceRingPointer;
+ }
+ if (dispPtr->modKeyCodes[i] == eventPtr->xkey.keycode) {
+ break;
+ }
+ }
+ ringPtr = &bindPtr->eventRing[bindPtr->curEvent];
+ if ((ringPtr->type != KeyRelease)
+ || (ringPtr->xkey.keycode != eventPtr->xkey.keycode)) {
+ goto advanceRingPointer;
+ }
+ if (bindPtr->curEvent <= 0) {
+ i = EVENT_BUFFER_SIZE - 1;
+ } else {
+ i = bindPtr->curEvent - 1;
+ }
+ ringPtr = &bindPtr->eventRing[i];
+ if ((ringPtr->type != KeyPress)
+ || (ringPtr->xkey.keycode != eventPtr->xkey.keycode)) {
+ goto advanceRingPointer;
+ }
+ bindPtr->eventRing[bindPtr->curEvent].type = -1;
+ bindPtr->curEvent = i;
+ } else {
+
+ advanceRingPointer:
+ bindPtr->curEvent++;
+ if (bindPtr->curEvent >= EVENT_BUFFER_SIZE) {
+ bindPtr->curEvent = 0;
+ }
+ }
+ ringPtr = &bindPtr->eventRing[bindPtr->curEvent];
+ memcpy(ringPtr, eventPtr, sizeof(XEvent));
+ detail.clientData = 0;
+ flags = flagArray[ringPtr->type];
+ if (flags & KEY) {
+ detail.keySym = TkpGetKeySym(dispPtr, ringPtr);
+ if (detail.keySym == NoSymbol) {
+ detail.keySym = 0;
+ }
+ } else if (flags & BUTTON) {
+ detail.button = ringPtr->xbutton.button;
+ } else if (flags & VIRTUAL) {
+ detail.name = ((XVirtualEvent *) ringPtr)->name;
+ }
+ bindPtr->detailRing[bindPtr->curEvent] = detail;
+
+ /*
+ * Find out if there are any virtual events that correspond to this
+ * physical event (or sequence of physical events).
+ */
+
+ vMatchDetailList = NULL;
+ vMatchNoDetailList = NULL;
+ memset(&key, 0, sizeof(key));
+
+ if (ringPtr->type != VirtualEvent) {
+ Tcl_HashTable *veptPtr = &bindInfoPtr->virtualEventTable.patternTable;
+ Tcl_HashEntry *hPtr;
+
+ key.object = NULL;
+ key.type = ringPtr->type;
+ key.detail = detail;
+
+ hPtr = Tcl_FindHashEntry(veptPtr, (char *) &key);
+ if (hPtr != NULL) {
+ vMatchDetailList = Tcl_GetHashValue(hPtr);
+ }
+
+ if (key.detail.clientData != 0) {
+ key.detail.clientData = 0;
+ hPtr = Tcl_FindHashEntry(veptPtr, (char *) &key);
+ if (hPtr != NULL) {
+ vMatchNoDetailList = Tcl_GetHashValue(hPtr);
+ }
+ }
+ }
+
+ /*
+ * Loop over all the binding tags, finding the binding script or callback
+ * for each one. Append all of the binding scripts, with %-sequences
+ * expanded, to "scripts", with null characters separating the scripts for
+ * each object.
+ */
+
+ scriptCount = 0;
+ Tcl_DStringInit(&scripts);
+
+ for ( ; numObjects > 0; numObjects--, objectPtr++) {
+ PatSeq *matchPtr = NULL, *sourcePtr = NULL;
+ Tcl_HashEntry *hPtr;
+
+ /*
+ * Match the new event against those recorded in the pattern table,
+ * saving the longest matching pattern. For events with details
+ * (button and key events), look for a binding for the specific key or
+ * button. First see if the event matches a physical event that the
+ * object is interested in, then look for a virtual event.
+ */
+
+ key.object = *objectPtr;
+ key.type = ringPtr->type;
+ key.detail = detail;
+ hPtr = Tcl_FindHashEntry(&bindPtr->patternTable, (char *) &key);
+ if (hPtr != NULL) {
+ matchPtr = MatchPatterns(dispPtr, bindPtr, Tcl_GetHashValue(hPtr),
+ matchPtr, NULL, &sourcePtr);
+ }
+
+ if (vMatchDetailList != NULL) {
+ matchPtr = MatchPatterns(dispPtr, bindPtr, vMatchDetailList,
+ matchPtr, objectPtr, &sourcePtr);
+ }
+
+ /*
+ * If no match was found, look for a binding for all keys or buttons
+ * (detail of 0). Again, first match on a virtual event.
+ */
+
+ if ((detail.clientData != 0) && (matchPtr == NULL)) {
+ key.detail.clientData = 0;
+ hPtr = Tcl_FindHashEntry(&bindPtr->patternTable, (char *) &key);
+ if (hPtr != NULL) {
+ matchPtr = MatchPatterns(dispPtr, bindPtr,
+ Tcl_GetHashValue(hPtr), matchPtr, NULL, &sourcePtr);
+ }
+
+ if (vMatchNoDetailList != NULL) {
+ matchPtr = MatchPatterns(dispPtr, bindPtr, vMatchNoDetailList,
+ matchPtr, objectPtr, &sourcePtr);
+ }
+ }
+
+ if (matchPtr != NULL) {
+ ExpandPercents(winPtr, sourcePtr->script, eventPtr,
+ detail.keySym, scriptCount++, &scripts);
+
+ /*
+ * A "" is added to the scripts string to separate the various
+ * scripts that should be invoked.
+ */
+
+ Tcl_DStringAppend(&scripts, "", 1);
+ }
+ }
+ if (Tcl_DStringLength(&scripts) == 0) {
+ return;
+ }
+
+ /*
+ * Now go back through and evaluate the binding for each object, in order,
+ * dealing with "break" and "continue" exceptions appropriately.
+ *
+ * There are two tricks here:
+ * 1. Bindings can be invoked from in the middle of Tcl commands, where
+ * the interp's result is significant (for example, a widget might be
+ * deleted because of an error in creating it, so the result contains
+ * an error message that is eventually going to be returned by the
+ * creating command). To preserve the result, we save it in a dynamic
+ * string.
+ * 2. The binding's action can potentially delete the binding, so bindPtr
+ * may not point to anything valid once the action completes. Thus we
+ * have to save bindPtr->interp in a local variable in order to restore
+ * the result.
+ */
+
+ interp = bindPtr->interp;
+
+ /*
+ * Save information about the current screen, then invoke a script if the
+ * screen has changed.
+ */
+
+ interpState = Tcl_SaveInterpState(interp, TCL_OK);
+ screenPtr = &bindInfoPtr->screenInfo;
+ oldDispPtr = screenPtr->curDispPtr;
+ oldScreen = screenPtr->curScreenIndex;
+ if ((dispPtr != screenPtr->curDispPtr)
+ || (Tk_ScreenNumber(tkwin) != screenPtr->curScreenIndex)) {
+ screenPtr->curDispPtr = dispPtr;
+ screenPtr->curScreenIndex = Tk_ScreenNumber(tkwin);
+ ChangeScreen(interp, dispPtr->name, screenPtr->curScreenIndex);
+ }
+
+ p = Tcl_DStringValue(&scripts);
+ end = p + Tcl_DStringLength(&scripts);
+
+ /*
+ * Be careful when dereferencing screenPtr or bindInfoPtr. If we evaluate
+ * something that destroys ".", bindInfoPtr would have been freed, but we
+ * can tell that by first checking to see if winPtr->mainPtr == NULL.
+ */
+
+ Tcl_Preserve(bindInfoPtr);
+ while (p < end) {
+ int len = (int) strlen(p);
+ int code;
+
+ if (!bindInfoPtr->deleted) {
+ screenPtr->bindingDepth++;
+ }
+ Tcl_AllowExceptions(interp);
+
+ code = Tcl_EvalEx(interp, p, len, TCL_EVAL_GLOBAL);
+ p += len + 1;
+
+ if (!bindInfoPtr->deleted) {
+ screenPtr->bindingDepth--;
+ }
+ if (code != TCL_OK) {
+ if (code == TCL_CONTINUE) {
+ /*
+ * Do nothing: just go on to the next command.
+ */
+ } else if (code == TCL_BREAK) {
+ break;
+ } else {
+ Tcl_AddErrorInfo(interp, "\n (command bound to event)");
+ Tcl_BackgroundException(interp, code);
+ break;
+ }
+ }
+ }
+
+ if (!bindInfoPtr->deleted && (screenPtr->bindingDepth != 0)
+ && ((oldDispPtr != screenPtr->curDispPtr)
+ || (oldScreen != screenPtr->curScreenIndex))) {
+ /*
+ * Some other binding script is currently executing, but its screen is
+ * no longer current. Change the current display back again.
+ */
+
+ screenPtr->curDispPtr = oldDispPtr;
+ screenPtr->curScreenIndex = oldScreen;
+ ChangeScreen(interp, oldDispPtr->name, oldScreen);
+ }
+ (void) Tcl_RestoreInterpState(interp, interpState);
+ Tcl_DStringFree(&scripts);
+
+ Tcl_Release(bindInfoPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MatchPatterns --
+ *
+ * Given a list of pattern sequences and a list of recent events, return
+ * the pattern sequence that best matches the event list, if there is
+ * one.
+ *
+ * This function is used in two different ways. In the simplest use,
+ * "object" is NULL and psPtr is a list of pattern sequences, each of
+ * which corresponds to a binding. In this case, the function finds the
+ * pattern sequences that match the event list and returns the most
+ * specific of those, if there is more than one.
+ *
+ * In the second case, psPtr is a list of pattern sequences, each of
+ * which corresponds to a definition for a virtual binding. In order for
+ * one of these sequences to "match", it must match the events (as above)
+ * but in addition there must be a binding for its associated virtual
+ * event on the current object. The "object" argument indicates which
+ * object the binding must be for.
+ *
+ * Results:
+
+ * The return value is NULL if bestPtr is NULL and no pattern matches the
+ * recent events from bindPtr. Otherwise the return value is the most
+ * specific pattern sequence among bestPtr and all those at psPtr that
+ * match the event list and object. If a pattern sequence other than
+ * bestPtr is returned, then *bestCommandPtr is filled in with a pointer
+ * to the command from the best sequence.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static PatSeq *
+MatchPatterns(
+ TkDisplay *dispPtr, /* Display from which the event came. */
+ BindingTable *bindPtr, /* Information about binding table, such as
+ * ring of recent events. */
+ PatSeq *psPtr, /* List of pattern sequences. */
+ PatSeq *bestPtr, /* The best match seen so far, from a previous
+ * call to this function. NULL means no prior
+ * best match. */
+ ClientData *objectPtr, /* If NULL, the sequences at psPtr correspond
+ * to "normal" bindings. If non-NULL, the
+ * sequences at psPtr correspond to virtual
+ * bindings; in order to match each sequence
+ * must correspond to a virtual binding for
+ * which a binding exists for object in
+ * bindPtr. */
+ PatSeq **sourcePtrPtr) /* Filled with the pattern sequence that
+ * contains the eventProc and clientData
+ * associated with the best match. If this
+ * differs from the return value, it is the
+ * virtual event that most closely matched the
+ * return value (a physical event). Not
+ * modified unless a result other than bestPtr
+ * is returned. */
+{
+ PatSeq *matchPtr, *bestSourcePtr, *sourcePtr;
+
+ bestSourcePtr = *sourcePtrPtr;
+
+ /*
+ * Iterate over all the pattern sequences.
+ */
+
+ for ( ; psPtr != NULL; psPtr = psPtr->nextSeqPtr) {
+ XEvent *eventPtr = &bindPtr->eventRing[bindPtr->curEvent];
+ Detail *detailPtr = &bindPtr->detailRing[bindPtr->curEvent];
+ TkPattern *patPtr = psPtr->pats;
+ Window window = eventPtr->xany.window;
+ int patCount, ringCount, flags, state, modMask, i;
+
+ /*
+ * Iterate over all the patterns in a sequence to be sure that they
+ * all match.
+ */
+
+ patCount = psPtr->numPats;
+ ringCount = EVENT_BUFFER_SIZE;
+ while (patCount > 0) {
+ if (ringCount <= 0) {
+ goto nextSequence;
+ }
+ if (eventPtr->xany.type != patPtr->eventType) {
+ /*
+ * Most of the event types are considered superfluous in that
+ * they are ignored if they occur in the middle of a pattern
+ * sequence and have mismatching types. The only ones that
+ * cannot be ignored are ButtonPress and ButtonRelease events
+ * (if the next event in the pattern is a KeyPress or
+ * KeyRelease) and KeyPress and KeyRelease events (if the next
+ * pattern event is a ButtonPress or ButtonRelease). Here are
+ * some tricky cases to consider:
+ * 1. Double-Button or Double-Key events.
+ * 2. Double-ButtonRelease or Double-KeyRelease events.
+ * 3. The arrival of various events like Enter and Leave and
+ * FocusIn and GraphicsExpose between two button presses or
+ * key presses.
+ * 4. Modifier keys like Shift and Control shouldn't generate
+ * conflicts with button events.
+ */
+
+ if ((patPtr->eventType == KeyPress)
+ || (patPtr->eventType == KeyRelease)) {
+ if ((eventPtr->xany.type == ButtonPress)
+ || (eventPtr->xany.type == ButtonRelease)) {
+ goto nextSequence;
+ }
+ } else if ((patPtr->eventType == ButtonPress)
+ || (patPtr->eventType == ButtonRelease)) {
+ if ((eventPtr->xany.type == KeyPress)
+ || (eventPtr->xany.type == KeyRelease)) {
+ /*
+ * Ignore key events if they are modifier keys.
+ */
+
+ for (i = 0; i < dispPtr->numModKeyCodes; i++) {
+ if (dispPtr->modKeyCodes[i]
+ == eventPtr->xkey.keycode) {
+ /*
+ * This key is a modifier key, so ignore it.
+ */
+
+ goto nextEvent;
+ }
+ }
+ goto nextSequence;
+ }
+ }
+ goto nextEvent;
+ }
+ if (eventPtr->xany.type == CreateNotify
+ && eventPtr->xcreatewindow.parent != window) {
+ goto nextSequence;
+ } else if (eventPtr->xany.window != window) {
+ goto nextSequence;
+ }
+
+ /*
+ * Note: it's important for the keysym check to go before the
+ * modifier check, so we can ignore unwanted modifier keys before
+ * choking on the modifier check.
+ */
+
+ if ((patPtr->detail.clientData != 0)
+ && (patPtr->detail.clientData != detailPtr->clientData)) {
+ /*
+ * The detail appears not to match. However, if the event is a
+ * KeyPress for a modifier key then just ignore the event.
+ * Otherwise event sequences like "aD" never match because the
+ * shift key goes down between the "a" and the "D".
+ */
+
+ if (eventPtr->xany.type == KeyPress) {
+ for (i = 0; i < dispPtr->numModKeyCodes; i++) {
+ if (dispPtr->modKeyCodes[i] == eventPtr->xkey.keycode) {
+ goto nextEvent;
+ }
+ }
+ }
+ goto nextSequence;
+ }
+ flags = flagArray[eventPtr->type];
+ if (flags & KEY_BUTTON_MOTION_VIRTUAL) {
+ state = eventPtr->xkey.state;
+ } else if (flags & CROSSING) {
+ state = eventPtr->xcrossing.state;
+ } else {
+ state = 0;
+ }
+ if (patPtr->needMods != 0) {
+ modMask = patPtr->needMods;
+ if ((modMask & META_MASK) && (dispPtr->metaModMask != 0)) {
+ modMask = (modMask & ~META_MASK) | dispPtr->metaModMask;
+ }
+ if ((modMask & ALT_MASK) && (dispPtr->altModMask != 0)) {
+ modMask = (modMask & ~ALT_MASK) | dispPtr->altModMask;
+ }
+
+ if ((state & META_MASK) && (dispPtr->metaModMask != 0)) {
+ state = (state & ~META_MASK) | dispPtr->metaModMask;
+ }
+ if ((state & ALT_MASK) && (dispPtr->altModMask != 0)) {
+ state = (state & ~ALT_MASK) | dispPtr->altModMask;
+ }
+
+ if ((state & modMask) != modMask) {
+ goto nextSequence;
+ }
+ }
+ if (psPtr->flags & PAT_NEARBY) {
+ XEvent *firstPtr = &bindPtr->eventRing[bindPtr->curEvent];
+ long timeDiff;
+
+ timeDiff = ((long)firstPtr->xkey.time -
+ (long)eventPtr->xkey.time);
+ if ((firstPtr->xkey.x_root
+ < (eventPtr->xkey.x_root - NEARBY_PIXELS))
+ || (firstPtr->xkey.x_root
+ > (eventPtr->xkey.x_root + NEARBY_PIXELS))
+ || (firstPtr->xkey.y_root
+ < (eventPtr->xkey.y_root - NEARBY_PIXELS))
+ || (firstPtr->xkey.y_root
+ > (eventPtr->xkey.y_root + NEARBY_PIXELS))
+ || (timeDiff > NEARBY_MS)) {
+ goto nextSequence;
+ }
+ }
+ patPtr++;
+ patCount--;
+ nextEvent:
+ if (eventPtr == bindPtr->eventRing) {
+ eventPtr = &bindPtr->eventRing[EVENT_BUFFER_SIZE-1];
+ detailPtr = &bindPtr->detailRing[EVENT_BUFFER_SIZE-1];
+ } else {
+ eventPtr--;
+ detailPtr--;
+ }
+ ringCount--;
+ }
+
+ matchPtr = psPtr;
+ sourcePtr = psPtr;
+
+ if (objectPtr != NULL) {
+ int iVirt;
+ VirtualOwners *voPtr;
+ PatternTableKey key;
+
+ /*
+ * The sequence matches the physical constraints. Is this object
+ * interested in any of the virtual events that correspond to this
+ * sequence?
+ */
+
+ voPtr = psPtr->voPtr;
+
+ memset(&key, 0, sizeof(key));
+ key.object = *objectPtr;
+ key.type = VirtualEvent;
+ key.detail.clientData = 0;
+
+ for (iVirt = 0; iVirt < voPtr->numOwners; iVirt++) {
+ Tcl_HashEntry *hPtr = voPtr->owners[iVirt];
+
+ key.detail.name = (Tk_Uid) Tcl_GetHashKey(hPtr->tablePtr,
+ hPtr);
+ hPtr = Tcl_FindHashEntry(&bindPtr->patternTable,
+ (char *) &key);
+ if (hPtr != NULL) {
+ /*
+ * This tag is interested in this virtual event and its
+ * corresponding physical event is a good match with the
+ * virtual event's definition.
+ */
+
+ PatSeq *virtMatchPtr = Tcl_GetHashValue(hPtr);
+
+ if ((virtMatchPtr->numPats != 1)
+ || (virtMatchPtr->nextSeqPtr != NULL)) {
+ Tcl_Panic("MatchPattern: badly constructed virtual event");
+ }
+ sourcePtr = virtMatchPtr;
+ goto match;
+ }
+ }
+
+ /*
+ * The physical event matches a virtual event's definition, but
+ * the tag isn't interested in it.
+ */
+
+ goto nextSequence;
+ }
+ match:
+
+ /*
+ * This sequence matches. If we've already got another match, pick
+ * whichever is most specific. Detail is most important, then
+ * needMods.
+ */
+
+ if (bestPtr != NULL) {
+ TkPattern *patPtr2;
+
+ if (matchPtr->numPats != bestPtr->numPats) {
+ if (bestPtr->numPats > matchPtr->numPats) {
+ goto nextSequence;
+ } else {
+ goto newBest;
+ }
+ }
+ for (i = 0, patPtr = matchPtr->pats, patPtr2 = bestPtr->pats;
+ i < matchPtr->numPats; i++, patPtr++, patPtr2++) {
+ if (patPtr->detail.clientData != patPtr2->detail.clientData) {
+ if (patPtr->detail.clientData == 0) {
+ goto nextSequence;
+ } else {
+ goto newBest;
+ }
+ }
+ if (patPtr->needMods != patPtr2->needMods) {
+ if ((patPtr->needMods & patPtr2->needMods)
+ == patPtr->needMods) {
+ goto nextSequence;
+ } else if ((patPtr->needMods & patPtr2->needMods)
+ == patPtr2->needMods) {
+ goto newBest;
+ }
+ }
+ }
+
+ /*
+ * Tie goes to current best pattern.
+ *
+ * (1) For virtual vs. virtual, the least recently defined virtual
+ * wins, because virtuals are examined in order of definition.
+ * This order is _not_ guaranteed in the documentation.
+ *
+ * (2) For virtual vs. physical, the physical wins because all the
+ * physicals are examined before the virtuals. This order is
+ * guaranteed in the documentation.
+ *
+ * (3) For physical vs. physical pattern, the most recently
+ * defined physical wins, because physicals are examined in
+ * reverse order of definition. This order is guaranteed in the
+ * documentation.
+ */
+
+ goto nextSequence;
+ }
+ newBest:
+ bestPtr = matchPtr;
+ bestSourcePtr = sourcePtr;
+
+ nextSequence:
+ continue;
+ }
+
+ *sourcePtrPtr = bestSourcePtr;
+ return bestPtr;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ExpandPercents --
+ *
+ * Given a command and an event, produce a new command by replacing %
+ * constructs in the original command with information from the X event.
+ *
+ * Results:
+ * The new expanded command is appended to the dynamic string given by
+ * dsPtr.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ExpandPercents(
+ TkWindow *winPtr, /* Window where event occurred: needed to get
+ * input context. */
+ const char *before, /* Command containing percent expressions to
+ * be replaced. */
+ XEvent *eventPtr, /* X event containing information to be used
+ * in % replacements. */
+ KeySym keySym, /* KeySym: only relevant for KeyPress and
+ * KeyRelease events). */
+ unsigned int scriptCount, /* The number of script-based binding patterns
+ * matched so far for this event. */
+ Tcl_DString *dsPtr) /* Dynamic string in which to append new
+ * command. */
+{
+ int spaceNeeded, cvtFlags; /* Used to substitute string as proper Tcl
+ * list element. */
+ int number, flags, length;
+#define NUM_SIZE 40
+ const char *string;
+ Tcl_DString buf;
+ char numStorage[NUM_SIZE+1];
+
+ Tcl_DStringInit(&buf);
+
+ if (eventPtr->type < TK_LASTEVENT) {
+ flags = flagArray[eventPtr->type];
+ } else {
+ flags = 0;
+ }
+
+ while (1) {
+ /*
+ * Find everything up to the next % character and append it to the
+ * result string.
+ */
+
+ for (string = before; (*string != 0) && (*string != '%'); string++) {
+ /* Empty loop body. */
+ }
+ if (string != before) {
+ Tcl_DStringAppend(dsPtr, before, (int) (string-before));
+ before = string;
+ }
+ if (*before == 0) {
+ break;
+ }
+
+ /*
+ * There's a percent sequence here. Process it.
+ */
+
+ number = 0;
+ string = "??";
+ switch (before[1]) {
+ case '#':
+ number = eventPtr->xany.serial;
+ goto doNumber;
+ case 'a':
+ if (flags & CONFIG) {
+ TkpPrintWindowId(numStorage, eventPtr->xconfigure.above);
+ string = numStorage;
+ }
+ goto doString;
+ case 'b':
+ if (flags & BUTTON) {
+ number = eventPtr->xbutton.button;
+ goto doNumber;
+ }
+ goto doString;
+ case 'c':
+ if (flags & EXPOSE) {
+ number = eventPtr->xexpose.count;
+ goto doNumber;
+ }
+ goto doString;
+ case 'd':
+ if (flags & (CROSSING|FOCUS)) {
+ if (flags & FOCUS) {
+ number = eventPtr->xfocus.detail;
+ } else {
+ number = eventPtr->xcrossing.detail;
+ }
+ string = TkFindStateString(notifyDetail, number);
+ } else if (flags & CONFIGREQ) {
+ if (eventPtr->xconfigurerequest.value_mask & CWStackMode) {
+ string = TkFindStateString(configureRequestDetail,
+ eventPtr->xconfigurerequest.detail);
+ } else {
+ string = "";
+ }
+ } else if (flags & VIRTUAL) {
+ XVirtualEvent *vePtr = (XVirtualEvent *) eventPtr;
+
+ if (vePtr->user_data != NULL) {
+ string = Tcl_GetString(vePtr->user_data);
+ } else {
+ string = "";
+ }
+ }
+ goto doString;
+ case 'f':
+ if (flags & CROSSING) {
+ number = eventPtr->xcrossing.focus;
+ goto doNumber;
+ }
+ goto doString;
+ case 'h':
+ if (flags & EXPOSE) {
+ number = eventPtr->xexpose.height;
+ } else if (flags & CONFIG) {
+ number = eventPtr->xconfigure.height;
+ } else if (flags & CREATE) {
+ number = eventPtr->xcreatewindow.height;
+ } else if (flags & CONFIGREQ) {
+ number = eventPtr->xconfigurerequest.height;
+ } else if (flags & RESIZEREQ) {
+ number = eventPtr->xresizerequest.height;
+ } else {
+ goto doString;
+ }
+ goto doNumber;
+ case 'i':
+ if (flags & CREATE) {
+ TkpPrintWindowId(numStorage, eventPtr->xcreatewindow.window);
+ } else if (flags & CONFIGREQ) {
+ TkpPrintWindowId(numStorage,
+ eventPtr->xconfigurerequest.window);
+ } else if (flags & MAPREQ) {
+ TkpPrintWindowId(numStorage, eventPtr->xmaprequest.window);
+ } else {
+ TkpPrintWindowId(numStorage, eventPtr->xany.window);
+ }
+ string = numStorage;
+ goto doString;
+ case 'k':
+ if ((flags & KEY) && (eventPtr->type != MouseWheelEvent)) {
+ number = eventPtr->xkey.keycode;
+ goto doNumber;
+ }
+ goto doString;
+ case 'm':
+ if (flags & CROSSING) {
+ number = eventPtr->xcrossing.mode;
+ string = TkFindStateString(notifyMode, number);
+ } else if (flags & FOCUS) {
+ number = eventPtr->xfocus.mode;
+ string = TkFindStateString(notifyMode, number);
+ }
+ goto doString;
+ case 'o':
+ if (flags & CREATE) {
+ number = eventPtr->xcreatewindow.override_redirect;
+ } else if (flags & MAP) {
+ number = eventPtr->xmap.override_redirect;
+ } else if (flags & REPARENT) {
+ number = eventPtr->xreparent.override_redirect;
+ } else if (flags & CONFIG) {
+ number = eventPtr->xconfigure.override_redirect;
+ } else {
+ goto doString;
+ }
+ goto doNumber;
+ case 'p':
+ if (flags & CIRC) {
+ string = TkFindStateString(circPlace,
+ eventPtr->xcirculate.place);
+ } else if (flags & CIRCREQ) {
+ string = TkFindStateString(circPlace,
+ eventPtr->xcirculaterequest.place);
+ }
+ goto doString;
+ case 's':
+ if (flags & KEY_BUTTON_MOTION_VIRTUAL) {
+ number = eventPtr->xkey.state;
+ goto doNumber;
+ } else if (flags & CROSSING) {
+ number = eventPtr->xcrossing.state;
+ goto doNumber;
+ } else if (flags & PROP) {
+ string = TkFindStateString(propNotify,
+ eventPtr->xproperty.state);
+ } else if (flags & VISIBILITY) {
+ string = TkFindStateString(visNotify,
+ eventPtr->xvisibility.state);
+ }
+ goto doString;
+ case 't':
+ if (flags & KEY_BUTTON_MOTION_VIRTUAL) {
+ number = (int) eventPtr->xkey.time;
+ } else if (flags & CROSSING) {
+ number = (int) eventPtr->xcrossing.time;
+ } else if (flags & PROP) {
+ number = (int) eventPtr->xproperty.time;
+ } else {
+ goto doString;
+ }
+ goto doNumber;
+ case 'v':
+ number = eventPtr->xconfigurerequest.value_mask;
+ goto doNumber;
+ case 'w':
+ if (flags & EXPOSE) {
+ number = eventPtr->xexpose.width;
+ } else if (flags & CONFIG) {
+ number = eventPtr->xconfigure.width;
+ } else if (flags & CREATE) {
+ number = eventPtr->xcreatewindow.width;
+ } else if (flags & CONFIGREQ) {
+ number = eventPtr->xconfigurerequest.width;
+ } else if (flags & RESIZEREQ) {
+ number = eventPtr->xresizerequest.width;
+ } else {
+ goto doString;
+ }
+ goto doNumber;
+ case 'x':
+ if (flags & KEY_BUTTON_MOTION_VIRTUAL) {
+ number = eventPtr->xkey.x;
+ } else if (flags & CROSSING) {
+ number = eventPtr->xcrossing.x;
+ } else if (flags & EXPOSE) {
+ number = eventPtr->xexpose.x;
+ } else if (flags & (CREATE|CONFIG|GRAVITY)) {
+ number = eventPtr->xcreatewindow.x;
+ } else if (flags & REPARENT) {
+ number = eventPtr->xreparent.x;
+ } else if (flags & CREATE) {
+ number = eventPtr->xcreatewindow.x;
+ } else if (flags & CONFIGREQ) {
+ number = eventPtr->xconfigurerequest.x;
+ } else {
+ goto doString;
+ }
+ goto doNumber;
+ case 'y':
+ if (flags & KEY_BUTTON_MOTION_VIRTUAL) {
+ number = eventPtr->xkey.y;
+ } else if (flags & EXPOSE) {
+ number = eventPtr->xexpose.y;
+ } else if (flags & (CREATE|CONFIG|GRAVITY)) {
+ number = eventPtr->xcreatewindow.y;
+ } else if (flags & REPARENT) {
+ number = eventPtr->xreparent.y;
+ } else if (flags & CROSSING) {
+ number = eventPtr->xcrossing.y;
+ } else if (flags & CREATE) {
+ number = eventPtr->xcreatewindow.y;
+ } else if (flags & CONFIGREQ) {
+ number = eventPtr->xconfigurerequest.y;
+ } else {
+ goto doString;
+ }
+ goto doNumber;
+ case 'A':
+ if ((flags & KEY) && (eventPtr->type != MouseWheelEvent)) {
+ Tcl_DStringFree(&buf);
+ string = TkpGetString(winPtr, eventPtr, &buf);
+ }
+ goto doString;
+ case 'B':
+ if (flags & CREATE) {
+ number = eventPtr->xcreatewindow.border_width;
+ } else if (flags & CONFIGREQ) {
+ number = eventPtr->xconfigurerequest.border_width;
+ } else if (flags & CONFIG) {
+ number = eventPtr->xconfigure.border_width;
+ } else {
+ goto doString;
+ }
+ goto doNumber;
+ case 'D':
+ /*
+ * This is used only by the MouseWheel event.
+ */
+
+ if ((flags & KEY) && (eventPtr->type == MouseWheelEvent)) {
+ number = eventPtr->xkey.keycode;
+ goto doNumber;
+ }
+ goto doString;
+ case 'E':
+ number = (int) eventPtr->xany.send_event;
+ goto doNumber;
+ case 'K':
+ if ((flags & KEY) && (eventPtr->type != MouseWheelEvent)) {
+ const char *name = TkKeysymToString(keySym);
+
+ if (name != NULL) {
+ string = name;
+ }
+ }
+ goto doString;
+ case 'M':
+ number = scriptCount;
+ goto doNumber;
+ case 'N':
+ if ((flags & KEY) && (eventPtr->type != MouseWheelEvent)) {
+ number = (int) keySym;
+ goto doNumber;
+ }
+ goto doString;
+ case 'P':
+ if (flags & PROP) {
+ string = Tk_GetAtomName((Tk_Window) winPtr,
+ eventPtr->xproperty.atom);
+ }
+ goto doString;
+ case 'R':
+ if (flags & KEY_BUTTON_MOTION_CROSSING) {
+ TkpPrintWindowId(numStorage, eventPtr->xkey.root);
+ string = numStorage;
+ }
+ goto doString;
+ case 'S':
+ if (flags & KEY_BUTTON_MOTION_CROSSING) {
+ TkpPrintWindowId(numStorage, eventPtr->xkey.subwindow);
+ string = numStorage;
+ }
+ goto doString;
+ case 'T':
+ number = eventPtr->type;
+ goto doNumber;
+ case 'W': {
+ Tk_Window tkwin;
+
+ tkwin = Tk_IdToWindow(eventPtr->xany.display,
+ eventPtr->xany.window);
+ if (tkwin != NULL) {
+ string = Tk_PathName(tkwin);
+ } else {
+ string = "??";
+ }
+ goto doString;
+ }
+ case 'X':
+ if (flags & KEY_BUTTON_MOTION_CROSSING) {
+
+ number = eventPtr->xkey.x_root;
+ Tk_IdToWindow(eventPtr->xany.display,
+ eventPtr->xany.window);
+ goto doNumber;
+ }
+ goto doString;
+ case 'Y':
+ if (flags & KEY_BUTTON_MOTION_CROSSING) {
+
+ number = eventPtr->xkey.y_root;
+ Tk_IdToWindow(eventPtr->xany.display,
+ eventPtr->xany.window);
+ goto doNumber;
+ }
+ goto doString;
+ default:
+ numStorage[0] = before[1];
+ numStorage[1] = '\0';
+ string = numStorage;
+ goto doString;
+ }
+
+ doNumber:
+ sprintf(numStorage, "%d", number);
+ string = numStorage;
+
+ doString:
+ spaceNeeded = Tcl_ScanElement(string, &cvtFlags);
+ length = Tcl_DStringLength(dsPtr);
+ Tcl_DStringSetLength(dsPtr, length + spaceNeeded);
+ spaceNeeded = Tcl_ConvertElement(string,
+ Tcl_DStringValue(dsPtr) + length,
+ cvtFlags | TCL_DONT_USE_BRACES);
+ Tcl_DStringSetLength(dsPtr, length + spaceNeeded);
+ before += 2;
+ }
+ Tcl_DStringFree(&buf);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ChangeScreen --
+ *
+ * This function is invoked whenever the current screen changes in an
+ * application. It invokes a Tcl command named "tk::ScreenChanged",
+ * passing it the screen name as argument. tk::ScreenChanged does things
+ * like making the tk::Priv variable point to an array for the current
+ * display.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Depends on what tk::ScreenChanged does. If an error occurs then
+ * bgerror will be invoked.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ChangeScreen(
+ Tcl_Interp *interp, /* Interpreter in which to invoke command. */
+ char *dispName, /* Name of new display. */
+ int screenIndex) /* Index of new screen. */
+{
+ Tcl_Obj *cmdObj = Tcl_ObjPrintf("::tk::ScreenChanged %s.%d",
+ dispName, screenIndex);
+ int code;
+
+ Tcl_IncrRefCount(cmdObj);
+ code = Tcl_EvalObjEx(interp, cmdObj, TCL_EVAL_GLOBAL);
+ if (code != TCL_OK) {
+ Tcl_AddErrorInfo(interp,
+ "\n (changing screen in event binding)");
+ Tcl_BackgroundException(interp, code);
+ }
+ Tcl_DecrRefCount(cmdObj);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_EventCmd --
+ *
+ * This function is invoked to process the "event" Tcl command. It is
+ * used to define and generate events.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_EventObjCmd(
+ ClientData clientData, /* Main window associated with interpreter. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ int index, i;
+ char *name;
+ const char *event;
+ Tk_Window tkwin = clientData;
+ TkBindInfo bindInfo = ((TkWindow *) tkwin)->mainPtr->bindInfo;
+ VirtualEventTable *vetPtr = &bindInfo->virtualEventTable;
+ static const char *const optionStrings[] = {
+ "add", "delete", "generate", "info",
+ NULL
+ };
+ enum options {
+ EVENT_ADD, EVENT_DELETE, EVENT_GENERATE, EVENT_INFO
+ };
+
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings,
+ sizeof(char *), "option", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch ((enum options) index) {
+ case EVENT_ADD:
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "virtual sequence ?sequence ...?");
+ return TCL_ERROR;
+ }
+ name = Tcl_GetString(objv[2]);
+ for (i = 3; i < objc; i++) {
+ event = Tcl_GetString(objv[i]);
+ if (CreateVirtualEvent(interp, vetPtr, name, event) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ break;
+ case EVENT_DELETE:
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "virtual ?sequence ...?");
+ return TCL_ERROR;
+ }
+ name = Tcl_GetString(objv[2]);
+ if (objc == 3) {
+ return DeleteVirtualEvent(interp, vetPtr, name, NULL);
+ }
+ for (i = 3; i < objc; i++) {
+ event = Tcl_GetString(objv[i]);
+ if (DeleteVirtualEvent(interp, vetPtr, name, event) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ break;
+ case EVENT_GENERATE:
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "window event ?-option value ...?");
+ return TCL_ERROR;
+ }
+ return HandleEventGenerate(interp, tkwin, objc - 2, objv + 2);
+ case EVENT_INFO:
+ if (objc == 2) {
+ GetAllVirtualEvents(interp, vetPtr);
+ return TCL_OK;
+ } else if (objc == 3) {
+ return GetVirtualEvent(interp, vetPtr, objv[2]);
+ } else {
+ Tcl_WrongNumArgs(interp, 2, objv, "?virtual?");
+ return TCL_ERROR;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * InitVirtualEventTable --
+ *
+ * Given storage for a virtual event table, set up the fields to prepare
+ * a new domain in which virtual events may be defined.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * *vetPtr is now initialized.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+InitVirtualEventTable(
+ VirtualEventTable *vetPtr) /* Pointer to virtual event table. Memory is
+ * supplied by the caller. */
+{
+ Tcl_InitHashTable(&vetPtr->patternTable,
+ sizeof(PatternTableKey) / sizeof(int));
+ Tcl_InitHashTable(&vetPtr->nameTable, TCL_ONE_WORD_KEYS);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DeleteVirtualEventTable --
+ *
+ * Delete the contents of a virtual event table. The caller is
+ * responsible for freeing any memory used by the table itself.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory is freed.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+DeleteVirtualEventTable(
+ VirtualEventTable *vetPtr) /* The virtual event table to delete. */
+{
+ Tcl_HashEntry *hPtr;
+ Tcl_HashSearch search;
+ PatSeq *psPtr, *nextPtr;
+
+ hPtr = Tcl_FirstHashEntry(&vetPtr->patternTable, &search);
+ for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
+ psPtr = Tcl_GetHashValue(hPtr);
+ for ( ; psPtr != NULL; psPtr = nextPtr) {
+ nextPtr = psPtr->nextSeqPtr;
+ ckfree(psPtr->voPtr);
+ ckfree(psPtr);
+ }
+ }
+ Tcl_DeleteHashTable(&vetPtr->patternTable);
+
+ hPtr = Tcl_FirstHashEntry(&vetPtr->nameTable, &search);
+ for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
+ ckfree(Tcl_GetHashValue(hPtr));
+ }
+ Tcl_DeleteHashTable(&vetPtr->nameTable);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CreateVirtualEvent --
+ *
+ * Add a new definition for a virtual event. If the virtual event is
+ * already defined, the new definition augments those that already exist.
+ *
+ * Results:
+ * The return value is TCL_ERROR if an error occured while creating the
+ * virtual binding. In this case, an error message will be left in the
+ * interp's result. If all went well then the return value is TCL_OK.
+ *
+ * Side effects:
+ * The virtual event may cause future calls to Tk_BindEvent to behave
+ * differently than they did previously.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CreateVirtualEvent(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ VirtualEventTable *vetPtr, /* Table in which to augment virtual event. */
+ char *virtString, /* Name of new virtual event. */
+ const char *eventString) /* String describing physical event that
+ * triggers virtual event. */
+{
+ PatSeq *psPtr;
+ int dummy;
+ Tcl_HashEntry *vhPtr;
+ unsigned long eventMask;
+ PhysicalsOwned *poPtr;
+ VirtualOwners *voPtr;
+ Tk_Uid virtUid;
+
+ virtUid = GetVirtualEventUid(interp, virtString);
+ if (virtUid == NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Find/create physical event
+ */
+
+ psPtr = FindSequence(interp, &vetPtr->patternTable, NULL, eventString,
+ 1, 0, &eventMask);
+ if (psPtr == NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Find/create virtual event.
+ */
+
+ vhPtr = Tcl_CreateHashEntry(&vetPtr->nameTable, virtUid, &dummy);
+
+ /*
+ * Make virtual event own the physical event.
+ */
+
+ poPtr = Tcl_GetHashValue(vhPtr);
+ if (poPtr == NULL) {
+ poPtr = ckalloc(sizeof(PhysicalsOwned));
+ poPtr->numOwned = 0;
+ } else {
+ /*
+ * See if this virtual event is already defined for this physical
+ * event and just return if it is.
+ */
+
+ int i;
+
+ for (i = 0; i < poPtr->numOwned; i++) {
+ if (poPtr->patSeqs[i] == psPtr) {
+ return TCL_OK;
+ }
+ }
+ poPtr = ckrealloc(poPtr, sizeof(PhysicalsOwned)
+ + poPtr->numOwned * sizeof(PatSeq *));
+ }
+ Tcl_SetHashValue(vhPtr, poPtr);
+ poPtr->patSeqs[poPtr->numOwned] = psPtr;
+ poPtr->numOwned++;
+
+ /*
+ * Make physical event so it can trigger the virtual event.
+ */
+
+ voPtr = psPtr->voPtr;
+ if (voPtr == NULL) {
+ voPtr = ckalloc(sizeof(VirtualOwners));
+ voPtr->numOwners = 0;
+ } else {
+ voPtr = ckrealloc(voPtr, sizeof(VirtualOwners)
+ + voPtr->numOwners * sizeof(Tcl_HashEntry *));
+ }
+ psPtr->voPtr = voPtr;
+ voPtr->owners[voPtr->numOwners] = vhPtr;
+ voPtr->numOwners++;
+
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DeleteVirtualEvent --
+ *
+ * Remove the definition of a given virtual event. If the event string is
+ * NULL, all definitions of the virtual event will be removed.
+ * Otherwise, just the specified definition of the virtual event will be
+ * removed.
+ *
+ * Results:
+ * The result is a standard Tcl return value. If an error occurs then the
+ * interp's result will contain an error message. It is not an error to
+ * attempt to delete a virtual event that does not exist or a definition
+ * that does not exist.
+ *
+ * Side effects:
+ * The virtual event given by virtString may be removed from the virtual
+ * event table.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+DeleteVirtualEvent(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ VirtualEventTable *vetPtr, /* Table in which to delete event. */
+ char *virtString, /* String describing event sequence that
+ * triggers binding. */
+ const char *eventString) /* The event sequence that should be deleted,
+ * or NULL to delete all event sequences for
+ * the entire virtual event. */
+{
+ int iPhys;
+ Tk_Uid virtUid;
+ Tcl_HashEntry *vhPtr;
+ PhysicalsOwned *poPtr;
+ PatSeq *eventPSPtr;
+
+ virtUid = GetVirtualEventUid(interp, virtString);
+ if (virtUid == NULL) {
+ return TCL_ERROR;
+ }
+
+ vhPtr = Tcl_FindHashEntry(&vetPtr->nameTable, virtUid);
+ if (vhPtr == NULL) {
+ return TCL_OK;
+ }
+ poPtr = Tcl_GetHashValue(vhPtr);
+
+ eventPSPtr = NULL;
+ if (eventString != NULL) {
+ unsigned long eventMask;
+
+ /*
+ * Delete only the specific physical event associated with the virtual
+ * event. If the physical event doesn't already exist, or the virtual
+ * event doesn't own that physical event, return w/o doing anything.
+ */
+
+ eventPSPtr = FindSequence(interp, &vetPtr->patternTable, NULL,
+ eventString, 0, 0, &eventMask);
+ if (eventPSPtr == NULL) {
+ const char *string = Tcl_GetString(Tcl_GetObjResult(interp));
+
+ return (string[0] != '\0') ? TCL_ERROR : TCL_OK;
+ }
+ }
+
+ for (iPhys = poPtr->numOwned; --iPhys >= 0; ) {
+ PatSeq *psPtr = poPtr->patSeqs[iPhys];
+
+ if ((eventPSPtr == NULL) || (psPtr == eventPSPtr)) {
+ int iVirt;
+ VirtualOwners *voPtr;
+
+ /*
+ * Remove association between this physical event and the given
+ * virtual event that it triggers.
+ */
+
+ voPtr = psPtr->voPtr;
+ for (iVirt = 0; iVirt < voPtr->numOwners; iVirt++) {
+ if (voPtr->owners[iVirt] == vhPtr) {
+ break;
+ }
+ }
+ if (iVirt == voPtr->numOwners) {
+ Tcl_Panic("DeleteVirtualEvent: couldn't find owner");
+ }
+ voPtr->numOwners--;
+ if (voPtr->numOwners == 0) {
+ /*
+ * Removed last reference to this physical event, so remove it
+ * from physical->virtual map.
+ */
+
+ PatSeq *prevPtr = Tcl_GetHashValue(psPtr->hPtr);
+
+ if (prevPtr == psPtr) {
+ if (psPtr->nextSeqPtr == NULL) {
+ Tcl_DeleteHashEntry(psPtr->hPtr);
+ } else {
+ Tcl_SetHashValue(psPtr->hPtr,
+ psPtr->nextSeqPtr);
+ }
+ } else {
+ for ( ; ; prevPtr = prevPtr->nextSeqPtr) {
+ if (prevPtr == NULL) {
+ Tcl_Panic("DeleteVirtualEvent couldn't find on hash chain");
+ }
+ if (prevPtr->nextSeqPtr == psPtr) {
+ prevPtr->nextSeqPtr = psPtr->nextSeqPtr;
+ break;
+ }
+ }
+ }
+ ckfree(psPtr->voPtr);
+ ckfree(psPtr);
+ } else {
+ /*
+ * This physical event still triggers some other virtual
+ * event(s). Consolidate the list of virtual owners for this
+ * physical event so it no longer triggers the given virtual
+ * event.
+ */
+
+ voPtr->owners[iVirt] = voPtr->owners[voPtr->numOwners];
+ }
+
+ /*
+ * Now delete the virtual event's reference to the physical event.
+ */
+
+ poPtr->numOwned--;
+ if (eventPSPtr != NULL && poPtr->numOwned != 0) {
+ /*
+ * Just deleting this one physical event. Consolidate list of
+ * owned physical events and return.
+ */
+
+ poPtr->patSeqs[iPhys] = poPtr->patSeqs[poPtr->numOwned];
+ return TCL_OK;
+ }
+ }
+ }
+
+ if (poPtr->numOwned == 0) {
+ /*
+ * All the physical events for this virtual event were deleted, either
+ * because there was only one associated physical event or because the
+ * caller was deleting the entire virtual event. Now the virtual event
+ * itself should be deleted.
+ */
+
+ ckfree(poPtr);
+ Tcl_DeleteHashEntry(vhPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GetVirtualEvent --
+ *
+ * Return the list of physical events that can invoke the given virtual
+ * event.
+ *
+ * Results:
+ * The return value is TCL_OK and the interp's result is filled with the
+ * string representation of the physical events associated with the
+ * virtual event; if there are no physical events for the given virtual
+ * event, the interp's result is filled with and empty string. If the
+ * virtual event string is improperly formed, then TCL_ERROR is returned
+ * and an error message is left in the interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static int
+GetVirtualEvent(
+ Tcl_Interp *interp, /* Interpreter for reporting. */
+ VirtualEventTable *vetPtr, /* Table in which to look for event. */
+ Tcl_Obj *virtName) /* String describing virtual event. */
+{
+ Tcl_HashEntry *vhPtr;
+ int iPhys;
+ PhysicalsOwned *poPtr;
+ Tk_Uid virtUid;
+ Tcl_Obj *resultObj;
+
+ virtUid = GetVirtualEventUid(interp, Tcl_GetString(virtName));
+ if (virtUid == NULL) {
+ return TCL_ERROR;
+ }
+
+ vhPtr = Tcl_FindHashEntry(&vetPtr->nameTable, virtUid);
+ if (vhPtr == NULL) {
+ return TCL_OK;
+ }
+
+ resultObj = Tcl_NewObj();
+ poPtr = Tcl_GetHashValue(vhPtr);
+ for (iPhys = 0; iPhys < poPtr->numOwned; iPhys++) {
+ Tcl_ListObjAppendElement(NULL, resultObj,
+ GetPatternObj(poPtr->patSeqs[iPhys]));
+ }
+ Tcl_SetObjResult(interp, resultObj);
+
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * GetAllVirtualEvents --
+ *
+ * Return a list that contains the names of all the virtual event
+ * defined.
+ *
+ * Results:
+ * There is no return value. The interp's result is modified to hold a
+ * Tcl list with one entry for each virtual event in nameTable.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+GetAllVirtualEvents(
+ Tcl_Interp *interp, /* Interpreter returning result. */
+ VirtualEventTable *vetPtr) /* Table containing events. */
+{
+ Tcl_HashEntry *hPtr;
+ Tcl_HashSearch search;
+ Tcl_Obj *resultObj;
+
+ resultObj = Tcl_NewObj();
+ hPtr = Tcl_FirstHashEntry(&vetPtr->nameTable, &search);
+ for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
+ Tcl_ListObjAppendElement(NULL, resultObj, Tcl_ObjPrintf(
+ "<<%s>>", (char *) Tcl_GetHashKey(hPtr->tablePtr, hPtr)));
+ }
+ Tcl_SetObjResult(interp, resultObj);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * HandleEventGenerate --
+ *
+ * Helper function for the "event generate" command. Generate and process
+ * an XEvent, constructed from information parsed from the event
+ * description string and its optional arguments.
+ *
+ * argv[0] contains name of the target window.
+ * argv[1] contains pattern string for one event (e.g, <Control-v>).
+ * argv[2..argc-1] contains -field/option pairs for specifying additional
+ * detail in the generated event.
+ *
+ * Either virtual or physical events can be generated this way. The event
+ * description string must contain the specification for only one event.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * When constructing the event,
+ * event.xany.serial is filled with the current X serial number.
+ * event.xany.window is filled with the target window.
+ * event.xany.display is filled with the target window's display.
+ * Any other fields in eventPtr which are not specified by the pattern
+ * string or the optional arguments, are set to 0.
+ *
+ * The event may be handled synchronously or asynchronously, depending on
+ * the value specified by the optional "-when" option. The default
+ * setting is synchronous.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static int
+HandleEventGenerate(
+ Tcl_Interp *interp, /* Interp for errors return and name lookup. */
+ Tk_Window mainWin, /* Main window associated with interp. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ union {XEvent general; XVirtualEvent virtual;} event;
+ const char *p;
+ const char *name, *windowName;
+ int count, flags, synch, i, number, warp;
+ Tcl_QueuePosition pos;
+ TkPattern pat;
+ Tk_Window tkwin, tkwin2;
+ TkWindow *mainPtr;
+ unsigned long eventMask;
+ Tcl_Obj *userDataObj;
+
+ static const char *const fieldStrings[] = {
+ "-when", "-above", "-borderwidth", "-button",
+ "-count", "-data", "-delta", "-detail",
+ "-focus", "-height",
+ "-keycode", "-keysym", "-mode", "-override",
+ "-place", "-root", "-rootx", "-rooty",
+ "-sendevent", "-serial", "-state", "-subwindow",
+ "-time", "-warp", "-width", "-window",
+ "-x", "-y", NULL
+ };
+ enum field {
+ EVENT_WHEN, EVENT_ABOVE, EVENT_BORDER, EVENT_BUTTON,
+ EVENT_COUNT, EVENT_DATA, EVENT_DELTA, EVENT_DETAIL,
+ EVENT_FOCUS, EVENT_HEIGHT,
+ EVENT_KEYCODE, EVENT_KEYSYM, EVENT_MODE, EVENT_OVERRIDE,
+ EVENT_PLACE, EVENT_ROOT, EVENT_ROOTX, EVENT_ROOTY,
+ EVENT_SEND, EVENT_SERIAL, EVENT_STATE, EVENT_SUBWINDOW,
+ EVENT_TIME, EVENT_WARP, EVENT_WIDTH, EVENT_WINDOW,
+ EVENT_X, EVENT_Y
+ };
+
+ windowName = Tcl_GetString(objv[0]);
+ if (!windowName[0]) {
+ tkwin = mainWin;
+ } else if (NameToWindow(interp, mainWin, objv[0], &tkwin) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ mainPtr = (TkWindow *) mainWin;
+ if ((tkwin == NULL)
+ || (mainPtr->mainPtr != ((TkWindow *) tkwin)->mainPtr)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "window id \"%s\" doesn't exist in this application",
+ Tcl_GetString(objv[0])));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "WINDOW",
+ Tcl_GetString(objv[0]), NULL);
+ return TCL_ERROR;
+ }
+
+ name = Tcl_GetString(objv[1]);
+
+ p = name;
+ eventMask = 0;
+ userDataObj = NULL;
+ count = ParseEventDescription(interp, &p, &pat, &eventMask);
+ if (count == 0) {
+ return TCL_ERROR;
+ }
+ if (count != 1) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "Double or Triple modifier not allowed", -1));
+ Tcl_SetErrorCode(interp, "TK", "EVENT", "BAD_MODIFIER", NULL);
+ return TCL_ERROR;
+ }
+ if (*p != '\0') {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "only one event specification allowed", -1));
+ Tcl_SetErrorCode(interp, "TK", "EVENT", "MULTIPLE", NULL);
+ return TCL_ERROR;
+ }
+
+ memset(&event, 0, sizeof(event));
+ event.general.xany.type = pat.eventType;
+ event.general.xany.serial = NextRequest(Tk_Display(tkwin));
+ event.general.xany.send_event = False;
+ if (windowName[0]) {
+ event.general.xany.window = Tk_WindowId(tkwin);
+ } else {
+ event.general.xany.window =
+ RootWindow(Tk_Display(tkwin), Tk_ScreenNumber(tkwin));
+ }
+ event.general.xany.display = Tk_Display(tkwin);
+
+ flags = flagArray[event.general.xany.type];
+ if (flags & DESTROY) {
+ /*
+ * Event DestroyNotify should be generated by destroying the window.
+ */
+
+ Tk_DestroyWindow(tkwin);
+ return TCL_OK;
+ }
+ if (flags & KEY_BUTTON_MOTION_VIRTUAL) {
+ event.general.xkey.state = pat.needMods;
+ if ((flags & KEY) && (event.general.xany.type != MouseWheelEvent)) {
+ TkpSetKeycodeAndState(tkwin, pat.detail.keySym, &event.general);
+ } else if (flags & BUTTON) {
+ event.general.xbutton.button = pat.detail.button;
+ } else if (flags & VIRTUAL) {
+ event.virtual.name = pat.detail.name;
+ }
+ }
+ if (flags & (CREATE|UNMAP|MAP|REPARENT|CONFIG|GRAVITY|CIRC)) {
+ event.general.xcreatewindow.window = event.general.xany.window;
+ }
+
+ if (flags & KEY_BUTTON_MOTION_CROSSING) {
+ event.general.xkey.x_root = -1;
+ event.general.xkey.y_root = -1;
+ }
+
+ if (event.general.xany.type == FocusIn
+ || event.general.xany.type == FocusOut) {
+ event.general.xany.send_event = GENERATED_FOCUS_EVENT_MAGIC;
+ }
+
+ /*
+ * Process the remaining arguments to fill in additional fields of the
+ * event.
+ */
+
+ synch = 1;
+ warp = 0;
+ pos = TCL_QUEUE_TAIL;
+ for (i = 2; i < objc; i += 2) {
+ Tcl_Obj *optionPtr, *valuePtr;
+ int index;
+
+ optionPtr = objv[i];
+ valuePtr = objv[i + 1];
+
+ if (Tcl_GetIndexFromObjStruct(interp, optionPtr, fieldStrings,
+ sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (objc & 1) {
+ /*
+ * This test occurs after Tcl_GetIndexFromObj() so that "event
+ * generate <Button> -xyz" will return the error message that
+ * "-xyz" is a bad option, rather than that the value for "-xyz"
+ * is missing.
+ */
+
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "value for \"%s\" missing", Tcl_GetString(optionPtr)));
+ Tcl_SetErrorCode(interp, "TK", "EVENT", "MISSING_VALUE", NULL);
+ return TCL_ERROR;
+ }
+
+ switch ((enum field) index) {
+ case EVENT_WARP:
+ if (Tcl_GetBooleanFromObj(interp, valuePtr, &warp) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (!(flags & KEY_BUTTON_MOTION_VIRTUAL)) {
+ goto badopt;
+ }
+ break;
+ case EVENT_WHEN:
+ pos = (Tcl_QueuePosition) TkFindStateNumObj(interp, optionPtr,
+ queuePosition, valuePtr);
+ if ((int) pos < -1) {
+ return TCL_ERROR;
+ }
+ synch = 0;
+ if ((int) pos == -1) {
+ synch = 1;
+ }
+ break;
+ case EVENT_ABOVE:
+ if (NameToWindow(interp, tkwin, valuePtr, &tkwin2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (flags & CONFIG) {
+ event.general.xconfigure.above = Tk_WindowId(tkwin2);
+ } else {
+ goto badopt;
+ }
+ break;
+ case EVENT_BORDER:
+ if (Tk_GetPixelsFromObj(interp,tkwin,valuePtr,&number) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (flags & (CREATE|CONFIG)) {
+ event.general.xcreatewindow.border_width = number;
+ } else {
+ goto badopt;
+ }
+ break;
+ case EVENT_BUTTON:
+ if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (flags & BUTTON) {
+ event.general.xbutton.button = number;
+ } else {
+ goto badopt;
+ }
+ break;
+ case EVENT_COUNT:
+ if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (flags & EXPOSE) {
+ event.general.xexpose.count = number;
+ } else {
+ goto badopt;
+ }
+ break;
+ case EVENT_DATA:
+ if (flags & VIRTUAL) {
+ /*
+ * Do not increment reference count until after parsing
+ * completes and we know that the event generation is really
+ * going to happen.
+ */
+
+ userDataObj = valuePtr;
+ } else {
+ goto badopt;
+ }
+ break;
+ case EVENT_DELTA:
+ if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((flags & KEY) && (event.general.xkey.type == MouseWheelEvent)) {
+ event.general.xkey.keycode = number;
+ } else {
+ goto badopt;
+ }
+ break;
+ case EVENT_DETAIL:
+ number = TkFindStateNumObj(interp, optionPtr, notifyDetail,
+ valuePtr);
+ if (number < 0) {
+ return TCL_ERROR;
+ }
+ if (flags & FOCUS) {
+ event.general.xfocus.detail = number;
+ } else if (flags & CROSSING) {
+ event.general.xcrossing.detail = number;
+ } else {
+ goto badopt;
+ }
+ break;
+ case EVENT_FOCUS:
+ if (Tcl_GetBooleanFromObj(interp, valuePtr, &number) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (flags & CROSSING) {
+ event.general.xcrossing.focus = number;
+ } else {
+ goto badopt;
+ }
+ break;
+ case EVENT_HEIGHT:
+ if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr,
+ &number) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (flags & EXPOSE) {
+ event.general.xexpose.height = number;
+ } else if (flags & CONFIG) {
+ event.general.xconfigure.height = number;
+ } else {
+ goto badopt;
+ }
+ break;
+ case EVENT_KEYCODE:
+ if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((flags & KEY) && (event.general.xkey.type != MouseWheelEvent)) {
+ event.general.xkey.keycode = number;
+ } else {
+ goto badopt;
+ }
+ break;
+ case EVENT_KEYSYM: {
+ KeySym keysym;
+ const char *value;
+
+ value = Tcl_GetString(valuePtr);
+ keysym = TkStringToKeysym(value);
+ if (keysym == NoSymbol) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "unknown keysym \"%s\"", value));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "KEYSYM", value,
+ NULL);
+ return TCL_ERROR;
+ }
+
+ TkpSetKeycodeAndState(tkwin, keysym, &event.general);
+ if (event.general.xkey.keycode == 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "no keycode for keysym \"%s\"", value));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "KEYCODE", value,
+ NULL);
+ return TCL_ERROR;
+ }
+ if (!(flags & KEY)
+ || (event.general.xkey.type == MouseWheelEvent)) {
+ goto badopt;
+ }
+ break;
+ }
+ case EVENT_MODE:
+ number = TkFindStateNumObj(interp,optionPtr,notifyMode,valuePtr);
+ if (number < 0) {
+ return TCL_ERROR;
+ }
+ if (flags & CROSSING) {
+ event.general.xcrossing.mode = number;
+ } else if (flags & FOCUS) {
+ event.general.xfocus.mode = number;
+ } else {
+ goto badopt;
+ }
+ break;
+ case EVENT_OVERRIDE:
+ if (Tcl_GetBooleanFromObj(interp, valuePtr, &number) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (flags & CREATE) {
+ event.general.xcreatewindow.override_redirect = number;
+ } else if (flags & MAP) {
+ event.general.xmap.override_redirect = number;
+ } else if (flags & REPARENT) {
+ event.general.xreparent.override_redirect = number;
+ } else if (flags & CONFIG) {
+ event.general.xconfigure.override_redirect = number;
+ } else {
+ goto badopt;
+ }
+ break;
+ case EVENT_PLACE:
+ number = TkFindStateNumObj(interp, optionPtr, circPlace, valuePtr);
+ if (number < 0) {
+ return TCL_ERROR;
+ }
+ if (flags & CIRC) {
+ event.general.xcirculate.place = number;
+ } else {
+ goto badopt;
+ }
+ break;
+ case EVENT_ROOT:
+ if (NameToWindow(interp, tkwin, valuePtr, &tkwin2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (flags & KEY_BUTTON_MOTION_CROSSING) {
+ event.general.xkey.root = Tk_WindowId(tkwin2);
+ } else {
+ goto badopt;
+ }
+ break;
+ case EVENT_ROOTX:
+ if (Tk_GetPixelsFromObj(interp,tkwin,valuePtr,&number) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (flags & KEY_BUTTON_MOTION_CROSSING) {
+ event.general.xkey.x_root = number;
+ } else {
+ goto badopt;
+ }
+ break;
+ case EVENT_ROOTY:
+ if (Tk_GetPixelsFromObj(interp,tkwin,valuePtr,&number) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (flags & KEY_BUTTON_MOTION_CROSSING) {
+ event.general.xkey.y_root = number;
+ } else {
+ goto badopt;
+ }
+ break;
+ case EVENT_SEND: {
+ const char *value;
+
+ value = Tcl_GetString(valuePtr);
+ if (isdigit(UCHAR(value[0]))) {
+ /*
+ * Allow arbitrary integer values for the field; they are
+ * needed by a few of the tests in the Tk test suite.
+ */
+
+ if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ } else {
+ if (Tcl_GetBooleanFromObj(interp,valuePtr,&number) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ event.general.xany.send_event = number;
+ break;
+ }
+ case EVENT_SERIAL:
+ if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ event.general.xany.serial = number;
+ break;
+ case EVENT_STATE:
+ if (flags & KEY_BUTTON_MOTION_CROSSING) {
+ if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (flags & KEY_BUTTON_MOTION_VIRTUAL) {
+ event.general.xkey.state = number;
+ } else {
+ event.general.xcrossing.state = number;
+ }
+ } else if (flags & VISIBILITY) {
+ number = TkFindStateNumObj(interp, optionPtr, visNotify,
+ valuePtr);
+ if (number < 0) {
+ return TCL_ERROR;
+ }
+ event.general.xvisibility.state = number;
+ } else {
+ goto badopt;
+ }
+ break;
+ case EVENT_SUBWINDOW:
+ if (NameToWindow(interp, tkwin, valuePtr, &tkwin2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (flags & KEY_BUTTON_MOTION_CROSSING) {
+ event.general.xkey.subwindow = Tk_WindowId(tkwin2);
+ } else {
+ goto badopt;
+ }
+ break;
+ case EVENT_TIME:
+ if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (flags & KEY_BUTTON_MOTION_CROSSING) {
+ event.general.xkey.time = number;
+ } else if (flags & PROP) {
+ event.general.xproperty.time = number;
+ } else {
+ goto badopt;
+ }
+ break;
+ case EVENT_WIDTH:
+ if (Tk_GetPixelsFromObj(interp,tkwin,valuePtr,&number) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (flags & EXPOSE) {
+ event.general.xexpose.width = number;
+ } else if (flags & (CREATE|CONFIG)) {
+ event.general.xcreatewindow.width = number;
+ } else {
+ goto badopt;
+ }
+ break;
+ case EVENT_WINDOW:
+ if (NameToWindow(interp, tkwin, valuePtr, &tkwin2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (flags & (CREATE|UNMAP|MAP|REPARENT|CONFIG|GRAVITY|CIRC)) {
+ event.general.xcreatewindow.window = Tk_WindowId(tkwin2);
+ } else {
+ goto badopt;
+ }
+ break;
+ case EVENT_X:
+ if (Tk_GetPixelsFromObj(interp,tkwin,valuePtr,&number) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (flags & KEY_BUTTON_MOTION_CROSSING) {
+ event.general.xkey.x = number;
+
+ /*
+ * Only modify rootx as well if it hasn't been changed.
+ */
+
+ if (event.general.xkey.x_root == -1) {
+ int rootX, rootY;
+
+ Tk_GetRootCoords(tkwin, &rootX, &rootY);
+ event.general.xkey.x_root = rootX + number;
+ }
+ } else if (flags & EXPOSE) {
+ event.general.xexpose.x = number;
+ } else if (flags & (CREATE|CONFIG|GRAVITY)) {
+ event.general.xcreatewindow.x = number;
+ } else if (flags & REPARENT) {
+ event.general.xreparent.x = number;
+ } else {
+ goto badopt;
+ }
+ break;
+ case EVENT_Y:
+ if (Tk_GetPixelsFromObj(interp,tkwin,valuePtr,&number) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (flags & KEY_BUTTON_MOTION_CROSSING) {
+ event.general.xkey.y = number;
+
+ /*
+ * Only modify rooty as well if it hasn't been changed.
+ */
+
+ if (event.general.xkey.y_root == -1) {
+ int rootX, rootY;
+
+ Tk_GetRootCoords(tkwin, &rootX, &rootY);
+ event.general.xkey.y_root = rootY + number;
+ }
+ } else if (flags & EXPOSE) {
+ event.general.xexpose.y = number;
+ } else if (flags & (CREATE|CONFIG|GRAVITY)) {
+ event.general.xcreatewindow.y = number;
+ } else if (flags & REPARENT) {
+ event.general.xreparent.y = number;
+ } else {
+ goto badopt;
+ }
+ break;
+ }
+ continue;
+
+ badopt:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "%s event doesn't accept \"%s\" option",
+ name, Tcl_GetString(optionPtr)));
+ Tcl_SetErrorCode(interp, "TK", "EVENT", "BAD_OPTION", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Don't generate events for windows that don't exist yet.
+ */
+
+ if (!event.general.xany.window) {
+ goto done;
+ }
+
+ if (userDataObj != NULL) {
+
+ /*
+ * Must be virtual event to set that variable to non-NULL. Now we want
+ * to install the object into the event. Note that we must incr the
+ * refcount before firing it into the low-level event subsystem; the
+ * refcount will be decremented once the event has been processed.
+ */
+
+ event.virtual.user_data = userDataObj;
+ Tcl_IncrRefCount(userDataObj);
+ }
+
+ /*
+ * Now we have constructed the event, inject it into the event handling
+ * code.
+ */
+
+ if (synch != 0) {
+ Tk_HandleEvent(&event.general);
+ } else {
+ Tk_QueueWindowEvent(&event.general, pos);
+ }
+
+ /*
+ * We only allow warping if the window is mapped.
+ */
+
+ if ((warp != 0) && Tk_IsMapped(tkwin)) {
+ TkDisplay *dispPtr = TkGetDisplay(event.general.xmotion.display);
+
+ Tk_Window warpWindow = Tk_IdToWindow(dispPtr->display,
+ event.general.xmotion.window);
+
+ if (!(dispPtr->flags & TK_DISPLAY_IN_WARP)) {
+ Tcl_DoWhenIdle(DoWarp, dispPtr);
+ dispPtr->flags |= TK_DISPLAY_IN_WARP;
+ }
+
+ if (warpWindow != dispPtr->warpWindow) {
+ if (warpWindow) {
+ Tcl_Preserve(warpWindow);
+ }
+ if (dispPtr->warpWindow) {
+ Tcl_Release(dispPtr->warpWindow);
+ }
+ dispPtr->warpWindow = warpWindow;
+ }
+ dispPtr->warpMainwin = mainWin;
+ dispPtr->warpX = event.general.xmotion.x;
+ dispPtr->warpY = event.general.xmotion.y;
+ }
+
+ done:
+ Tcl_ResetResult(interp);
+ return TCL_OK;
+}
+
+static int
+NameToWindow(
+ Tcl_Interp *interp, /* Interp for error return and name lookup. */
+ Tk_Window mainWin, /* Main window of application. */
+ Tcl_Obj *objPtr, /* Contains name or id string of window. */
+ Tk_Window *tkwinPtr) /* Filled with token for window. */
+{
+ const char *name = Tcl_GetString(objPtr);
+ Tk_Window tkwin;
+
+ if (name[0] == '.') {
+ tkwin = Tk_NameToWindow(interp, name, mainWin);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ } else {
+ Window id;
+
+ /*
+ * Check for the winPtr being valid, even if it looks ok to
+ * TkpScanWindowId. [Bug #411307]
+ */
+
+ if (TkpScanWindowId(NULL, name, &id) != TCL_OK) {
+ goto badWindow;
+ }
+ tkwin = Tk_IdToWindow(Tk_Display(mainWin), id);
+ if (tkwin == NULL) {
+ goto badWindow;
+ }
+ }
+ *tkwinPtr = tkwin;
+ return TCL_OK;
+
+ badWindow:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad window name/identifier \"%s\"", name));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "WINDOW_ID", name, NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * DoWarp --
+ *
+ * Perform Warping of X pointer. Executed as an idle handler only.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * X Pointer will move to a new location.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static void
+DoWarp(
+ ClientData clientData)
+{
+ TkDisplay *dispPtr = clientData;
+
+ /*
+ * DoWarp was scheduled only if the window was mapped. It needs to be
+ * still mapped at the time the present idle callback is executed. Also
+ * one needs to guard against window destruction in the meantime.
+ * Finally, the case warpWindow == NULL is special in that it means
+ * the whole screen.
+ */
+
+ if ((dispPtr->warpWindow == NULL) ||
+ (Tk_IsMapped(dispPtr->warpWindow)
+ && (Tk_WindowId(dispPtr->warpWindow) != None))) {
+ TkpWarpPointer(dispPtr);
+ XForceScreenSaver(dispPtr->display, ScreenSaverReset);
+ }
+
+ if (dispPtr->warpWindow) {
+ Tcl_Release(dispPtr->warpWindow);
+ dispPtr->warpWindow = NULL;
+ }
+ dispPtr->flags &= ~TK_DISPLAY_IN_WARP;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * GetVirtualEventUid --
+ *
+ * Determine if the given string is in the proper format for a virtual
+ * event.
+ *
+ * Results:
+ * The return value is NULL if the virtual event string was not in the
+ * proper format. In this case, an error message will be left in the
+ * interp's result. Otherwise the return value is a Tk_Uid that
+ * represents the virtual event.
+ *
+ * Side effects:
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static Tk_Uid
+GetVirtualEventUid(
+ Tcl_Interp *interp,
+ char *virtString)
+{
+ Tk_Uid uid;
+ size_t length;
+
+ length = strlen(virtString);
+
+ if (length < 5 || virtString[0] != '<' || virtString[1] != '<' ||
+ virtString[length - 2] != '>' || virtString[length - 1] != '>') {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "virtual event \"%s\" is badly formed", virtString));
+ Tcl_SetErrorCode(interp, "TK", "EVENT", "VIRTUAL", "MALFORMED", NULL);
+ return NULL;
+ }
+ virtString[length - 2] = '\0';
+ uid = Tk_GetUid(virtString + 2);
+ virtString[length - 2] = '>';
+
+ return uid;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FindSequence --
+ *
+ * Find the entry in the pattern table that corresponds to a particular
+ * pattern string, and return a pointer to that entry.
+ *
+ * Results:
+ * The return value is normally a pointer to the PatSeq in patternTable
+ * that corresponds to eventString. If an error was found while parsing
+ * eventString, or if "create" is 0 and no pattern sequence previously
+ * existed, then NULL is returned and the interp's result contains a
+ * message describing the problem. If no pattern sequence previously
+ * existed for eventString, then a new one is created with a NULL command
+ * field. In a successful return, *maskPtr is filled in with a mask of
+ * the event types on which the pattern sequence depends.
+ *
+ * Side effects:
+ * A new pattern sequence may be allocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static PatSeq *
+FindSequence(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting. */
+ Tcl_HashTable *patternTablePtr,
+ /* Table to use for lookup. */
+ ClientData object, /* For binding table, token for object with
+ * which binding is associated. For virtual
+ * event table, NULL. */
+ const char *eventString, /* String description of pattern to match on.
+ * See user documentation for details. */
+ int create, /* 0 means don't create the entry if it
+ * doesn't already exist. Non-zero means
+ * create. */
+ int allowVirtual, /* 0 means that virtual events are not allowed
+ * in the sequence. Non-zero otherwise. */
+ unsigned long *maskPtr) /* *maskPtr is filled in with the event types
+ * on which this pattern sequence depends. */
+{
+ TkPattern pats[EVENT_BUFFER_SIZE];
+ int numPats, virtualFound;
+ const char *p;
+ TkPattern *patPtr;
+ PatSeq *psPtr;
+ Tcl_HashEntry *hPtr;
+ int flags, count, isNew;
+ size_t sequenceSize;
+ unsigned long eventMask;
+ PatternTableKey key;
+
+ /*
+ *-------------------------------------------------------------
+ * Step 1: parse the pattern string to produce an array of Patterns. The
+ * array is generated backwards, so that the lowest-indexed pattern
+ * corresponds to the last event that must occur.
+ *-------------------------------------------------------------
+ */
+
+ p = eventString;
+ flags = 0;
+ eventMask = 0;
+ virtualFound = 0;
+
+ patPtr = &pats[EVENT_BUFFER_SIZE-1];
+ for (numPats = 0; numPats < EVENT_BUFFER_SIZE; numPats++, patPtr--) {
+ while (isspace(UCHAR(*p))) {
+ p++;
+ }
+ if (*p == '\0') {
+ break;
+ }
+
+ count = ParseEventDescription(interp, &p, patPtr, &eventMask);
+ if (count == 0) {
+ return NULL;
+ }
+
+ if (eventMask & VirtualEventMask) {
+ if (allowVirtual == 0) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "virtual event not allowed in definition of another virtual event",
+ -1));
+ Tcl_SetErrorCode(interp, "TK", "EVENT", "VIRTUAL", "INNER",
+ NULL);
+ return NULL;
+ }
+ virtualFound = 1;
+ }
+
+ /*
+ * Replicate events for DOUBLE, TRIPLE, QUADRUPLE.
+ */
+
+ while ((count-- > 1) && (numPats < EVENT_BUFFER_SIZE-1)) {
+ flags |= PAT_NEARBY;
+ patPtr[-1] = patPtr[0];
+ patPtr--;
+ numPats++;
+ }
+ }
+
+ /*
+ *-------------------------------------------------------------
+ * Step 2: find the sequence in the binding table if it exists, and add a
+ * new sequence to the table if it doesn't.
+ *-------------------------------------------------------------
+ */
+
+ if (numPats == 0) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "no events specified in binding", -1));
+ Tcl_SetErrorCode(interp, "TK", "EVENT", "NO_EVENTS", NULL);
+ return NULL;
+ }
+ if ((numPats > 1) && (virtualFound != 0)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "virtual events may not be composed", -1));
+ Tcl_SetErrorCode(interp, "TK", "EVENT", "VIRTUAL", "COMPOSITION",
+ NULL);
+ return NULL;
+ }
+
+ patPtr = &pats[EVENT_BUFFER_SIZE-numPats];
+ memset(&key, 0, sizeof(key));
+ key.object = object;
+ key.type = patPtr->eventType;
+ key.detail = patPtr->detail;
+ hPtr = Tcl_CreateHashEntry(patternTablePtr, (char *) &key, &isNew);
+ sequenceSize = numPats*sizeof(TkPattern);
+ if (!isNew) {
+ for (psPtr = Tcl_GetHashValue(hPtr); psPtr != NULL;
+ psPtr = psPtr->nextSeqPtr) {
+ if ((numPats == psPtr->numPats)
+ && ((flags & PAT_NEARBY) == (psPtr->flags & PAT_NEARBY))
+ && (memcmp(patPtr, psPtr->pats, sequenceSize) == 0)) {
+ goto done;
+ }
+ }
+ }
+ if (!create) {
+ if (isNew) {
+ Tcl_DeleteHashEntry(hPtr);
+ }
+
+ /*
+ * No binding exists for the sequence, so return an empty error. This
+ * is a special error that the caller will check for in order to
+ * silently ignore this case. This is a hack that maintains backward
+ * compatibility for Tk_GetBinding but the various "bind" commands
+ * silently ignore missing bindings.
+ */
+
+ return NULL;
+ }
+ psPtr = ckalloc(sizeof(PatSeq) + (numPats-1)*sizeof(TkPattern));
+ psPtr->numPats = numPats;
+ psPtr->script = NULL;
+ psPtr->flags = flags;
+ psPtr->nextSeqPtr = Tcl_GetHashValue(hPtr);
+ psPtr->hPtr = hPtr;
+ psPtr->voPtr = NULL;
+ psPtr->nextObjPtr = NULL;
+ Tcl_SetHashValue(hPtr, psPtr);
+
+ memcpy(psPtr->pats, patPtr, sequenceSize);
+
+ done:
+ *maskPtr = eventMask;
+ return psPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ParseEventDescription --
+ *
+ * Fill Pattern buffer with information about event from event string.
+ *
+ * Results:
+ * Leaves error message in interp and returns 0 if there was an error due
+ * to a badly formed event string. Returns 1 if proper event was
+ * specified, 2 if Double modifier was used in event string, or 3 if
+ * Triple was used.
+ *
+ * Side effects:
+ * On exit, eventStringPtr points to rest of event string (after the
+ * closing '>', so that this function can be called repeatedly to parse
+ * all the events in the entire sequence.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static int
+ParseEventDescription(
+ Tcl_Interp *interp, /* For error messages. */
+ const char **eventStringPtr,/* On input, holds a pointer to start of event
+ * string. On exit, gets pointer to rest of
+ * string after parsed event. */
+ TkPattern *patPtr, /* Filled with the pattern parsed from the
+ * event string. */
+ unsigned long *eventMaskPtr)/* Filled with event mask of matched event. */
+{
+ char *p;
+ unsigned long eventMask;
+ int count, eventFlags;
+#define FIELD_SIZE 48
+ char field[FIELD_SIZE];
+ Tcl_HashEntry *hPtr;
+ Tcl_DString copy;
+
+ Tcl_DStringInit(&copy);
+ p = Tcl_DStringAppend(&copy, *eventStringPtr, -1);
+
+ patPtr->eventType = -1;
+ patPtr->needMods = 0;
+ patPtr->detail.clientData = 0;
+
+ eventMask = 0;
+ count = 1;
+
+ /*
+ * Handle simple ASCII characters.
+ */
+
+ if (*p != '<') {
+ char string[2];
+
+ patPtr->eventType = KeyPress;
+ eventMask = KeyPressMask;
+ string[0] = *p;
+ string[1] = 0;
+ patPtr->detail.keySym = TkStringToKeysym(string);
+ if (patPtr->detail.keySym == NoSymbol) {
+ if (isprint(UCHAR(*p))) {
+ patPtr->detail.keySym = *p;
+ } else {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad ASCII character 0x%x", UCHAR(*p)));
+ Tcl_SetErrorCode(interp, "TK", "EVENT", "BAD_CHAR", NULL);
+ count = 0;
+ goto done;
+ }
+ }
+ p++;
+ goto end;
+ }
+
+ /*
+ * A fancier event description. This can be either a virtual event or a
+ * physical event.
+ *
+ * A virtual event description consists of:
+ *
+ * 1. double open angle brackets.
+ * 2. virtual event name.
+ * 3. double close angle brackets.
+ *
+ * A physical event description consists of:
+ *
+ * 1. open angle bracket.
+ * 2. any number of modifiers, each followed by spaces or dashes.
+ * 3. an optional event name.
+ * 4. an option button or keysym name. Either this or item 3 *must* be
+ * present; if both are present then they are separated by spaces or
+ * dashes.
+ * 5. a close angle bracket.
+ */
+
+ p++;
+ if (*p == '<') {
+ /*
+ * This is a virtual event: soak up all the characters up to the next
+ * '>'.
+ */
+
+ char *field = p + 1;
+
+ p = strchr(field, '>');
+ if (p == field) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "virtual event \"<<>>\" is badly formed", -1));
+ Tcl_SetErrorCode(interp, "TK", "EVENT", "VIRTUAL", "MALFORMED",
+ NULL);
+ count = 0;
+ goto done;
+ }
+ if ((p == NULL) || (p[1] != '>')) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "missing \">\" in virtual binding", -1));
+ Tcl_SetErrorCode(interp, "TK", "EVENT", "VIRTUAL", "MALFORMED",
+ NULL);
+ count = 0;
+ goto done;
+ }
+ *p = '\0';
+ patPtr->eventType = VirtualEvent;
+ eventMask = VirtualEventMask;
+ patPtr->detail.name = Tk_GetUid(field);
+ *p = '>';
+
+ p += 2;
+ goto end;
+ }
+
+ while (1) {
+ ModInfo *modPtr;
+
+ p = GetField(p, field, FIELD_SIZE);
+ if (*p == '>') {
+ /*
+ * This solves the problem of, e.g., <Control-M> being
+ * misinterpreted as Control + Meta + missing keysym instead of
+ * Control + KeyPress + M.
+ */
+
+ break;
+ }
+ hPtr = Tcl_FindHashEntry(&modTable, field);
+ if (hPtr == NULL) {
+ break;
+ }
+ modPtr = Tcl_GetHashValue(hPtr);
+ patPtr->needMods |= modPtr->mask;
+ if (modPtr->flags & MULT_CLICKS) {
+ int i = modPtr->flags & MULT_CLICKS;
+
+ count = 2;
+ while (i >>= 1) {
+ count++;
+ }
+ }
+ while ((*p == '-') || isspace(UCHAR(*p))) {
+ p++;
+ }
+ }
+
+ eventFlags = 0;
+ hPtr = Tcl_FindHashEntry(&eventTable, field);
+ if (hPtr != NULL) {
+ const EventInfo *eiPtr = Tcl_GetHashValue(hPtr);
+
+ patPtr->eventType = eiPtr->type;
+ eventFlags = flagArray[eiPtr->type];
+ eventMask = eiPtr->eventMask;
+ while ((*p == '-') || isspace(UCHAR(*p))) {
+ p++;
+ }
+ p = GetField(p, field, FIELD_SIZE);
+ }
+ if (*field != '\0') {
+ if ((*field >= '1') && (*field <= '5') && (field[1] == '\0')) {
+ if (eventFlags == 0) {
+ patPtr->eventType = ButtonPress;
+ eventMask = ButtonPressMask;
+ } else if (eventFlags & KEY) {
+ goto getKeysym;
+ } else if (!(eventFlags & BUTTON)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "specified button \"%s\" for non-button event",
+ field));
+ Tcl_SetErrorCode(interp, "TK", "EVENT", "NON_BUTTON", NULL);
+ count = 0;
+ goto done;
+ }
+ patPtr->detail.button = (*field - '0');
+ } else {
+
+ getKeysym:
+ patPtr->detail.keySym = TkStringToKeysym(field);
+ if (patPtr->detail.keySym == NoSymbol) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad event type or keysym \"%s\"", field));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "KEYSYM", field,
+ NULL);
+ count = 0;
+ goto done;
+ }
+ if (eventFlags == 0) {
+ patPtr->eventType = KeyPress;
+ eventMask = KeyPressMask;
+ } else if (!(eventFlags & KEY)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "specified keysym \"%s\" for non-key event", field));
+ Tcl_SetErrorCode(interp, "TK", "EVENT", "NON_KEY", NULL);
+ count = 0;
+ goto done;
+ }
+ }
+ } else if (eventFlags == 0) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "no event type or button # or keysym", -1));
+ Tcl_SetErrorCode(interp, "TK", "EVENT", "UNMODIFIABLE", NULL);
+ count = 0;
+ goto done;
+ }
+
+ while ((*p == '-') || isspace(UCHAR(*p))) {
+ p++;
+ }
+ if (*p != '>') {
+ while (*p != '\0') {
+ p++;
+ if (*p == '>') {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "extra characters after detail in binding", -1));
+ Tcl_SetErrorCode(interp, "TK", "EVENT", "PAST_DETAIL", NULL);
+ count = 0;
+ goto done;
+ }
+ }
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "missing \">\" in binding", -1));
+ Tcl_SetErrorCode(interp, "TK", "EVENT", "MALFORMED", NULL);
+ count = 0;
+ goto done;
+ }
+ p++;
+
+ end:
+ *eventStringPtr += (p - Tcl_DStringValue(&copy));
+ *eventMaskPtr |= eventMask;
+ done:
+ Tcl_DStringFree(&copy);
+ return count;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetField --
+ *
+ * Used to parse pattern descriptions. Copies up to size characters from
+ * p to copy, stopping at end of string, space, "-", ">", or whenever
+ * size is exceeded.
+ *
+ * Results:
+ * The return value is a pointer to the character just after the last one
+ * copied (usually "-" or space or ">", but could be anything if size was
+ * exceeded). Also places NULL-terminated string (up to size character,
+ * including NULL), at copy.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static char *
+GetField(
+ char *p, /* Pointer to part of pattern. */
+ char *copy, /* Place to copy field. */
+ int size) /* Maximum number of characters to copy. */
+{
+ while ((*p != '\0') && !isspace(UCHAR(*p)) && (*p != '>')
+ && (*p != '-') && (size > 1)) {
+ *copy = *p;
+ p++;
+ copy++;
+ size--;
+ }
+ *copy = '\0';
+ return p;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GetPatternObj --
+ *
+ * Produce a string version of the given event, for displaying to the
+ * user.
+ *
+ * Results:
+ * The string is returned as a Tcl_Obj.
+ *
+ * Side effects:
+ * It is the caller's responsibility to arrange for the object to be
+ * released; it starts with a refCount of zero.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static Tcl_Obj *
+GetPatternObj(
+ PatSeq *psPtr)
+{
+ TkPattern *patPtr;
+ int patsLeft, needMods;
+ const ModInfo *modPtr;
+ const EventInfo *eiPtr;
+ Tcl_Obj *patternObj = Tcl_NewObj();
+
+ /*
+ * The order of the patterns in the sequence is backwards from the order
+ * in which they must be output.
+ */
+
+ for (patsLeft = psPtr->numPats, patPtr = &psPtr->pats[psPtr->numPats - 1];
+ patsLeft > 0; patsLeft--, patPtr--) {
+ /*
+ * Check for simple case of an ASCII character.
+ */
+
+ if ((patPtr->eventType == KeyPress)
+ && !(psPtr->flags & PAT_NEARBY)
+ && (patPtr->needMods == 0)
+ && (patPtr->detail.keySym < 128)
+ && isprint(UCHAR(patPtr->detail.keySym))
+ && (patPtr->detail.keySym != '<')
+ && (patPtr->detail.keySym != ' ')) {
+ char c = (char) patPtr->detail.keySym;
+
+ Tcl_AppendToObj(patternObj, &c, 1);
+ continue;
+ }
+
+ /*
+ * Check for virtual event.
+ */
+
+ if (patPtr->eventType == VirtualEvent) {
+ Tcl_AppendPrintfToObj(patternObj, "<<%s>>", patPtr->detail.name);
+ continue;
+ }
+
+ /*
+ * It's a more general event specification. First check for "Double",
+ * "Triple", "Quadruple", then modifiers, then event type, then keysym
+ * or button detail.
+ */
+
+ Tcl_AppendToObj(patternObj, "<", 1);
+
+ if ((psPtr->flags & PAT_NEARBY) && (patsLeft > 1)
+ && (memcmp(patPtr, patPtr-1, sizeof(TkPattern)) == 0)) {
+ patsLeft--;
+ patPtr--;
+ if ((patsLeft > 1) &&
+ (memcmp(patPtr, patPtr-1, sizeof(TkPattern)) == 0)) {
+ patsLeft--;
+ patPtr--;
+ if ((patsLeft > 1) &&
+ (memcmp(patPtr, patPtr-1, sizeof(TkPattern)) == 0)) {
+ patsLeft--;
+ patPtr--;
+ Tcl_AppendToObj(patternObj, "Quadruple-", 10);
+ } else {
+ Tcl_AppendToObj(patternObj, "Triple-", 7);
+ }
+ } else {
+ Tcl_AppendToObj(patternObj, "Double-", 7);
+ }
+ }
+
+ for (needMods = patPtr->needMods, modPtr = modArray;
+ needMods != 0; modPtr++) {
+ if (modPtr->mask & needMods) {
+ needMods &= ~modPtr->mask;
+ Tcl_AppendPrintfToObj(patternObj, "%s-", modPtr->name);
+ }
+ }
+
+ for (eiPtr = eventArray; eiPtr->name != NULL; eiPtr++) {
+ if (eiPtr->type == patPtr->eventType) {
+ Tcl_AppendToObj(patternObj, eiPtr->name, -1);
+ if (patPtr->detail.clientData != 0) {
+ Tcl_AppendToObj(patternObj, "-", 1);
+ }
+ break;
+ }
+ }
+
+ if (patPtr->detail.clientData != 0) {
+ if ((patPtr->eventType == KeyPress)
+ || (patPtr->eventType == KeyRelease)) {
+ const char *string = TkKeysymToString(patPtr->detail.keySym);
+
+ if (string != NULL) {
+ Tcl_AppendToObj(patternObj, string, -1);
+ }
+ } else {
+ Tcl_AppendPrintfToObj(patternObj, "%d", patPtr->detail.button);
+ }
+ }
+
+ Tcl_AppendToObj(patternObj, ">", 1);
+ }
+
+ return patternObj;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkStringToKeysym --
+ *
+ * This function finds the keysym associated with a given keysym name.
+ *
+ * Results:
+ * The return value is the keysym that corresponds to name, or NoSymbol
+ * if there is no such keysym.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+KeySym
+TkStringToKeysym(
+ const char *name) /* Name of a keysym. */
+{
+#ifdef REDO_KEYSYM_LOOKUP
+ Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&keySymTable, name);
+
+ if (hPtr != NULL) {
+ return (KeySym) Tcl_GetHashValue(hPtr);
+ }
+ if (strlen(name) == 1) {
+ KeySym keysym = (KeySym) (unsigned char) name[0];
+
+ if (TkKeysymToString(keysym) != NULL) {
+ return keysym;
+ }
+ }
+#endif /* REDO_KEYSYM_LOOKUP */
+ return XStringToKeysym(name);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkKeysymToString --
+ *
+ * This function finds the keysym name associated with a given keysym.
+ *
+ * Results:
+ * The return value is a pointer to a static string containing the name
+ * of the given keysym, or NULL if there is no known name.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+const char *
+TkKeysymToString(
+ KeySym keysym)
+{
+#ifdef REDO_KEYSYM_LOOKUP
+ Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&nameTable, (char *)keysym);
+
+ if (hPtr != NULL) {
+ return Tcl_GetHashValue(hPtr);
+ }
+#endif /* REDO_KEYSYM_LOOKUP */
+
+ return XKeysymToString(keysym);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpGetBindingXEvent --
+ *
+ * This function returns the XEvent associated with the currently
+ * executing binding. This function can only be invoked while a binding
+ * is executing.
+ *
+ * Results:
+ * Returns a pointer to the XEvent that caused the current binding code
+ * to be run.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+XEvent *
+TkpGetBindingXEvent(
+ Tcl_Interp *interp) /* Interpreter. */
+{
+ TkWindow *winPtr = (TkWindow *) Tk_MainWindow(interp);
+ BindingTable *bindPtr = winPtr->mainPtr->bindingTable;
+
+ return &(bindPtr->eventRing[bindPtr->curEvent]);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpCancelWarp --
+ *
+ * This function cancels an outstanding pointer warp and
+ * is called during tear down of the display.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpCancelWarp(
+ TkDisplay *dispPtr)
+{
+ if (dispPtr->flags & TK_DISPLAY_IN_WARP) {
+ Tcl_CancelIdleCall(DoWarp, dispPtr);
+ dispPtr->flags &= ~TK_DISPLAY_IN_WARP;
+ }
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkBitmap.c b/tk8.6/generic/tkBitmap.c
new file mode 100644
index 0000000..54bab69
--- /dev/null
+++ b/tk8.6/generic/tkBitmap.c
@@ -0,0 +1,1205 @@
+/*
+ * tkBitmap.c --
+ *
+ * This file maintains a database of read-only bitmaps for the Tk
+ * toolkit. This allows bitmaps to be shared between widgets and also
+ * avoids interactions with the X server.
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1998 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkInt.h"
+
+/*
+ * The includes below are for pre-defined bitmaps.
+ *
+ * Platform-specific issue: Windows complains when the bitmaps are included,
+ * because an array of characters is being initialized with integers as
+ * elements. For lint purposes, the following pragmas temporarily turn off
+ * that warning message.
+ */
+
+#if defined(_MSC_VER)
+#pragma warning (disable : 4305)
+#endif
+
+#include "error.xbm"
+#include "gray12.xbm"
+#include "gray25.xbm"
+#include "gray50.xbm"
+#include "gray75.xbm"
+#include "hourglass.xbm"
+#include "info.xbm"
+#include "questhead.xbm"
+#include "question.xbm"
+#include "warning.xbm"
+
+#if defined(_MSC_VER)
+#pragma warning (default : 4305)
+#endif
+
+/*
+ * One of the following data structures exists for each bitmap that is
+ * currently in use. Each structure is indexed with both "idTable" and
+ * "nameTable".
+ */
+
+typedef struct TkBitmap {
+ Pixmap bitmap; /* X identifier for bitmap. None means this
+ * bitmap was created by Tk_DefineBitmap and
+ * it isn't currently in use. */
+ int width, height; /* Dimensions of bitmap. */
+ Display *display; /* Display for which bitmap is valid. */
+ int screenNum; /* Screen on which bitmap is valid. */
+ int resourceRefCount; /* Number of active uses of this bitmap (each
+ * active use corresponds to a call to
+ * Tk_AllocBitmapFromObj or Tk_GetBitmap). If
+ * this count is 0, then this TkBitmap
+ * structure is no longer valid and it isn't
+ * present in nameTable: it is being kept
+ * around only because there are objects
+ * referring to it. The structure is freed
+ * when resourceRefCount and objRefCount are
+ * both 0. */
+ int objRefCount; /* Number of Tcl_Obj's that reference this
+ * structure. */
+ Tcl_HashEntry *nameHashPtr; /* Entry in nameTable for this structure
+ * (needed when deleting). */
+ Tcl_HashEntry *idHashPtr; /* Entry in idTable for this structure (needed
+ * when deleting). */
+ struct TkBitmap *nextPtr; /* Points to the next TkBitmap structure with
+ * the same name. All bitmaps with the same
+ * name (but different displays or screens)
+ * are chained together off a single entry in
+ * nameTable. */
+} TkBitmap;
+
+/*
+ * Used in bitmapDataTable, stored in the TkDisplay structure, to map between
+ * in-core data about a bitmap to its TkBitmap structure.
+ */
+
+typedef struct {
+ const char *source; /* Bitmap bits. */
+ int width, height; /* Dimensions of bitmap. */
+} DataKey;
+
+typedef struct {
+ int initialized; /* 0 means table below needs initializing. */
+ Tcl_HashTable predefBitmapTable;
+ /* Hash table created by Tk_DefineBitmap to
+ * map from a name to a collection of in-core
+ * data about a bitmap. The table is indexed
+ * by the address of the data for the bitmap,
+ * and the entries contain pointers to
+ * TkPredefBitmap structures. */
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+
+/*
+ * Forward declarations for functions defined in this file:
+ */
+
+static void BitmapInit(TkDisplay *dispPtr);
+static void DupBitmapObjProc(Tcl_Obj *srcObjPtr,
+ Tcl_Obj *dupObjPtr);
+static void FreeBitmap(TkBitmap *bitmapPtr);
+static void FreeBitmapObj(Tcl_Obj *objPtr);
+static void FreeBitmapObjProc(Tcl_Obj *objPtr);
+static TkBitmap * GetBitmap(Tcl_Interp *interp, Tk_Window tkwin,
+ const char *name);
+static TkBitmap * GetBitmapFromObj(Tk_Window tkwin, Tcl_Obj *objPtr);
+static void InitBitmapObj(Tcl_Obj *objPtr);
+
+/*
+ * The following structure defines the implementation of the "bitmap" Tcl
+ * object, which maps a string bitmap name to a TkBitmap object. The ptr1
+ * field of the Tcl_Obj points to a TkBitmap object.
+ */
+
+const Tcl_ObjType tkBitmapObjType = {
+ "bitmap", /* name */
+ FreeBitmapObjProc, /* freeIntRepProc */
+ DupBitmapObjProc, /* dupIntRepProc */
+ NULL, /* updateStringProc */
+ NULL /* setFromAnyProc */
+};
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_AllocBitmapFromObj --
+ *
+ * Given a Tcl_Obj *, map the value to a corresponding Pixmap structure
+ * based on the tkwin given.
+ *
+ * Results:
+ * The return value is the X identifer for the desired bitmap (i.e. a
+ * Pixmap with a single plane), unless string couldn't be parsed
+ * correctly. In this case, None is returned and an error message is left
+ * in the interp's result. The caller should never modify the bitmap that
+ * is returned, and should eventually call Tk_FreeBitmapFromObj when the
+ * bitmap is no longer needed.
+ *
+ * Side effects:
+ * The bitmap is added to an internal database with a reference count.
+ * For each call to this function, there should eventually be a call to
+ * Tk_FreeBitmapFromObj, so that the database can be cleaned up when
+ * bitmaps aren't needed anymore.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Pixmap
+Tk_AllocBitmapFromObj(
+ Tcl_Interp *interp, /* Interp for error results. This may be
+ * NULL. */
+ Tk_Window tkwin, /* Need the screen the bitmap is used on.*/
+ Tcl_Obj *objPtr) /* Object describing bitmap; see manual entry
+ * for legal syntax of string value. */
+{
+ TkBitmap *bitmapPtr;
+
+ if (objPtr->typePtr != &tkBitmapObjType) {
+ InitBitmapObj(objPtr);
+ }
+ bitmapPtr = objPtr->internalRep.twoPtrValue.ptr1;
+
+ /*
+ * If the object currently points to a TkBitmap, see if it's the one we
+ * want. If so, increment its reference count and return.
+ */
+
+ if (bitmapPtr != NULL) {
+ if (bitmapPtr->resourceRefCount == 0) {
+ /*
+ * This is a stale reference: it refers to a TkBitmap that's no
+ * longer in use. Clear the reference.
+ */
+
+ FreeBitmapObj(objPtr);
+ bitmapPtr = NULL;
+ } else if ((Tk_Display(tkwin) == bitmapPtr->display)
+ && (Tk_ScreenNumber(tkwin) == bitmapPtr->screenNum)) {
+ bitmapPtr->resourceRefCount++;
+ return bitmapPtr->bitmap;
+ }
+ }
+
+ /*
+ * The object didn't point to the TkBitmap that we wanted. Search the list
+ * of TkBitmaps with the same name to see if one of the others is the
+ * right one.
+ */
+
+ if (bitmapPtr != NULL) {
+ TkBitmap *firstBitmapPtr = Tcl_GetHashValue(bitmapPtr->nameHashPtr);
+
+ FreeBitmapObj(objPtr);
+ for (bitmapPtr = firstBitmapPtr; bitmapPtr != NULL;
+ bitmapPtr = bitmapPtr->nextPtr) {
+ if ((Tk_Display(tkwin) == bitmapPtr->display) &&
+ (Tk_ScreenNumber(tkwin) == bitmapPtr->screenNum)) {
+ bitmapPtr->resourceRefCount++;
+ bitmapPtr->objRefCount++;
+ objPtr->internalRep.twoPtrValue.ptr1 = bitmapPtr;
+ return bitmapPtr->bitmap;
+ }
+ }
+ }
+
+ /*
+ * Still no luck. Call GetBitmap to allocate a new TkBitmap object.
+ */
+
+ bitmapPtr = GetBitmap(interp, tkwin, Tcl_GetString(objPtr));
+ objPtr->internalRep.twoPtrValue.ptr1 = bitmapPtr;
+ if (bitmapPtr == NULL) {
+ return None;
+ }
+ bitmapPtr->objRefCount++;
+ return bitmapPtr->bitmap;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetBitmap --
+ *
+ * Given a string describing a bitmap, locate (or create if necessary) a
+ * bitmap that fits the description.
+ *
+ * Results:
+ * The return value is the X identifer for the desired bitmap (i.e. a
+ * Pixmap with a single plane), unless string couldn't be parsed
+ * correctly. In this case, None is returned and an error message is left
+ * in the interp's result. The caller should never modify the bitmap that
+ * is returned, and should eventually call Tk_FreeBitmap when the bitmap
+ * is no longer needed.
+ *
+ * Side effects:
+ * The bitmap is added to an internal database with a reference count.
+ * For each call to this function, there should eventually be a call to
+ * Tk_FreeBitmap, so that the database can be cleaned up when bitmaps
+ * aren't needed anymore.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Pixmap
+Tk_GetBitmap(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting,
+ * this may be NULL. */
+ Tk_Window tkwin, /* Window in which bitmap will be used. */
+ const char *string) /* Description of bitmap. See manual entry for
+ * details on legal syntax. */
+{
+ TkBitmap *bitmapPtr = GetBitmap(interp, tkwin, string);
+
+ if (bitmapPtr == NULL) {
+ return None;
+ }
+ return bitmapPtr->bitmap;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetBitmap --
+ *
+ * Given a string describing a bitmap, locate (or create if necessary) a
+ * bitmap that fits the description. This routine returns the internal
+ * data structure for the bitmap. This avoids extra hash table lookups in
+ * Tk_AllocBitmapFromObj.
+ *
+ * Results:
+ * The return value is the X identifer for the desired bitmap (i.e. a
+ * Pixmap with a single plane), unless string couldn't be parsed
+ * correctly. In this case, None is returned and an error message is left
+ * in the interp's result. The caller should never modify the bitmap that
+ * is returned, and should eventually call Tk_FreeBitmap when the bitmap
+ * is no longer needed.
+ *
+ * Side effects:
+ * The bitmap is added to an internal database with a reference count.
+ * For each call to this function, there should eventually be a call to
+ * Tk_FreeBitmap or Tk_FreeBitmapFromObj, so that the database can be
+ * cleaned up when bitmaps aren't needed anymore.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static TkBitmap *
+GetBitmap(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting,
+ * this may be NULL. */
+ Tk_Window tkwin, /* Window in which bitmap will be used. */
+ const char *string) /* Description of bitmap. See manual entry for
+ * details on legal syntax. */
+{
+ Tcl_HashEntry *nameHashPtr, *predefHashPtr;
+ TkBitmap *bitmapPtr, *existingBitmapPtr;
+ TkPredefBitmap *predefPtr;
+ Pixmap bitmap;
+ int isNew, width = 0, height = 0, dummy2;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (!dispPtr->bitmapInit) {
+ BitmapInit(dispPtr);
+ }
+
+ nameHashPtr = Tcl_CreateHashEntry(&dispPtr->bitmapNameTable, string,
+ &isNew);
+ if (!isNew) {
+ existingBitmapPtr = Tcl_GetHashValue(nameHashPtr);
+ for (bitmapPtr = existingBitmapPtr; bitmapPtr != NULL;
+ bitmapPtr = bitmapPtr->nextPtr) {
+ if ((Tk_Display(tkwin) == bitmapPtr->display) &&
+ (Tk_ScreenNumber(tkwin) == bitmapPtr->screenNum)) {
+ bitmapPtr->resourceRefCount++;
+ return bitmapPtr;
+ }
+ }
+ } else {
+ existingBitmapPtr = NULL;
+ }
+
+ /*
+ * No suitable bitmap exists. Create a new bitmap from the information
+ * contained in the string. If the string starts with "@" then the rest of
+ * the string is a file name containing the bitmap. Otherwise the string
+ * must refer to a bitmap defined by a call to Tk_DefineBitmap.
+ */
+
+ if (*string == '@') { /* INTL: ISO char */
+ Tcl_DString buffer;
+ int result;
+
+ if (Tcl_IsSafe(interp)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "can't specify bitmap with '@' in a safe interpreter",
+ -1));
+ Tcl_SetErrorCode(interp, "TK", "SAFE", "BITMAP_FILE", NULL);
+ goto error;
+ }
+
+ /*
+ * Note that we need to cast away the const from the string because
+ * Tcl_TranslateFileName is non-const, even though it doesn't modify
+ * the string.
+ */
+
+ string = Tcl_TranslateFileName(interp, (char *) string + 1, &buffer);
+ if (string == NULL) {
+ goto error;
+ }
+ result = TkReadBitmapFile(Tk_Display(tkwin),
+ RootWindowOfScreen(Tk_Screen(tkwin)), string,
+ (unsigned int *) &width, (unsigned int *) &height,
+ &bitmap, &dummy2, &dummy2);
+ if (result != BitmapSuccess) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "error reading bitmap file \"%s\"", string));
+ Tcl_SetErrorCode(interp, "TK", "BITMAP", "FILE_ERROR", NULL);
+ }
+ Tcl_DStringFree(&buffer);
+ goto error;
+ }
+ Tcl_DStringFree(&buffer);
+ } else {
+ predefHashPtr = Tcl_FindHashEntry(&tsdPtr->predefBitmapTable, string);
+ if (predefHashPtr == NULL) {
+ /*
+ * The following platform specific call allows the user to define
+ * bitmaps that may only exist during run time. If it returns None
+ * nothing was found and we return the error.
+ */
+
+ bitmap = TkpGetNativeAppBitmap(Tk_Display(tkwin), string,
+ &width, &height);
+
+ if (bitmap == None) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bitmap \"%s\" not defined", string));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "BITMAP", string,
+ NULL);
+ }
+ goto error;
+ }
+ } else {
+ predefPtr = Tcl_GetHashValue(predefHashPtr);
+ width = predefPtr->width;
+ height = predefPtr->height;
+ if (predefPtr->native) {
+ bitmap = TkpCreateNativeBitmap(Tk_Display(tkwin),
+ predefPtr->source);
+ if (bitmap == None) {
+ Tcl_Panic("native bitmap creation failed");
+ }
+ } else {
+ bitmap = XCreateBitmapFromData(Tk_Display(tkwin),
+ RootWindowOfScreen(Tk_Screen(tkwin)),
+ predefPtr->source, (unsigned)width, (unsigned)height);
+ }
+ }
+ }
+
+ /*
+ * Add information about this bitmap to our database.
+ */
+
+ bitmapPtr = ckalloc(sizeof(TkBitmap));
+ bitmapPtr->bitmap = bitmap;
+ bitmapPtr->width = width;
+ bitmapPtr->height = height;
+ bitmapPtr->display = Tk_Display(tkwin);
+ bitmapPtr->screenNum = Tk_ScreenNumber(tkwin);
+ bitmapPtr->resourceRefCount = 1;
+ bitmapPtr->objRefCount = 0;
+ bitmapPtr->nameHashPtr = nameHashPtr;
+ bitmapPtr->idHashPtr = Tcl_CreateHashEntry(&dispPtr->bitmapIdTable,
+ (char *) bitmap, &isNew);
+ if (!isNew) {
+ Tcl_Panic("bitmap already registered in Tk_GetBitmap");
+ }
+ bitmapPtr->nextPtr = existingBitmapPtr;
+ Tcl_SetHashValue(nameHashPtr, bitmapPtr);
+ Tcl_SetHashValue(bitmapPtr->idHashPtr, bitmapPtr);
+ return bitmapPtr;
+
+ error:
+ if (isNew) {
+ Tcl_DeleteHashEntry(nameHashPtr);
+ }
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_DefineBitmap --
+ *
+ * This function associates a textual name with a binary bitmap
+ * description, so that the name may be used to refer to the bitmap in
+ * future calls to Tk_GetBitmap.
+ *
+ * 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_DefineBitmap(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting. */
+ const char *name, /* Name to use for bitmap. Must not already be
+ * defined as a bitmap. */
+ const void *source, /* Address of bits for bitmap. */
+ int width, /* Width of bitmap. */
+ int height) /* Height of bitmap. */
+{
+ int isNew;
+ Tcl_HashEntry *predefHashPtr;
+ TkPredefBitmap *predefPtr;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ /*
+ * Initialize the Bitmap module if not initialized already for this
+ * thread. Since the current TkDisplay structure cannot be introspected
+ * from here, pass a NULL pointer to BitmapInit, which will know to
+ * initialize only the data in the ThreadSpecificData structure for the
+ * current thread.
+ */
+
+ if (!tsdPtr->initialized) {
+ BitmapInit(NULL);
+ }
+
+ predefHashPtr = Tcl_CreateHashEntry(&tsdPtr->predefBitmapTable,
+ name, &isNew);
+ if (!isNew) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bitmap \"%s\" is already defined", name));
+ Tcl_SetErrorCode(interp, "TK", "BITMAP", "EXISTS", NULL);
+ return TCL_ERROR;
+ }
+ predefPtr = ckalloc(sizeof(TkPredefBitmap));
+ predefPtr->source = source;
+ predefPtr->width = width;
+ predefPtr->height = height;
+ predefPtr->native = 0;
+ Tcl_SetHashValue(predefHashPtr, predefPtr);
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_NameOfBitmap --
+ *
+ * Given a bitmap, return a textual string identifying the bitmap.
+ *
+ * Results:
+ * The return value is the string name associated with bitmap.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+const char *
+Tk_NameOfBitmap(
+ Display *display, /* Display for which bitmap was allocated. */
+ Pixmap bitmap) /* Bitmap whose name is wanted. */
+{
+ Tcl_HashEntry *idHashPtr;
+ TkBitmap *bitmapPtr;
+ TkDisplay *dispPtr = TkGetDisplay(display);
+
+ if (dispPtr == NULL || !dispPtr->bitmapInit) {
+ unknown:
+ Tcl_Panic("Tk_NameOfBitmap received unknown bitmap argument");
+ }
+
+ idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, (char *) bitmap);
+ if (idHashPtr == NULL) {
+ goto unknown;
+ }
+ bitmapPtr = Tcl_GetHashValue(idHashPtr);
+ return bitmapPtr->nameHashPtr->key.string;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_SizeOfBitmap --
+ *
+ * Given a bitmap managed by this module, returns the width and height of
+ * the bitmap.
+ *
+ * Results:
+ * The words at *widthPtr and *heightPtr are filled in with the
+ * dimenstions of bitmap.
+ *
+ * Side effects:
+ * If bitmap isn't managed by this module then the function panics..
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_SizeOfBitmap(
+ Display *display, /* Display for which bitmap was allocated. */
+ Pixmap bitmap, /* Bitmap whose size is wanted. */
+ int *widthPtr, /* Store bitmap width here. */
+ int *heightPtr) /* Store bitmap height here. */
+{
+ Tcl_HashEntry *idHashPtr;
+ TkBitmap *bitmapPtr;
+ TkDisplay *dispPtr = TkGetDisplay(display);
+
+ if (!dispPtr->bitmapInit) {
+ unknownBitmap:
+ Tcl_Panic("Tk_SizeOfBitmap received unknown bitmap argument");
+ }
+
+ idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, (char *) bitmap);
+ if (idHashPtr == NULL) {
+ goto unknownBitmap;
+ }
+ bitmapPtr = Tcl_GetHashValue(idHashPtr);
+ *widthPtr = bitmapPtr->width;
+ *heightPtr = bitmapPtr->height;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeBitmap --
+ *
+ * This function does all the work of releasing a bitmap allocated by
+ * Tk_GetBitmap or TkGetBitmapFromData. It is invoked by both
+ * Tk_FreeBitmap and Tk_FreeBitmapFromObj
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The reference count associated with bitmap is decremented, and it is
+ * officially deallocated if no-one is using it anymore.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FreeBitmap(
+ TkBitmap *bitmapPtr) /* Bitmap to be released. */
+{
+ TkBitmap *prevPtr;
+
+ bitmapPtr->resourceRefCount--;
+ if (bitmapPtr->resourceRefCount > 0) {
+ return;
+ }
+
+ Tk_FreePixmap(bitmapPtr->display, bitmapPtr->bitmap);
+ Tcl_DeleteHashEntry(bitmapPtr->idHashPtr);
+ prevPtr = Tcl_GetHashValue(bitmapPtr->nameHashPtr);
+ if (prevPtr == bitmapPtr) {
+ if (bitmapPtr->nextPtr == NULL) {
+ Tcl_DeleteHashEntry(bitmapPtr->nameHashPtr);
+ } else {
+ Tcl_SetHashValue(bitmapPtr->nameHashPtr, bitmapPtr->nextPtr);
+ }
+ } else {
+ while (prevPtr->nextPtr != bitmapPtr) {
+ prevPtr = prevPtr->nextPtr;
+ }
+ prevPtr->nextPtr = bitmapPtr->nextPtr;
+ }
+ if (bitmapPtr->objRefCount == 0) {
+ ckfree(bitmapPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_FreeBitmap --
+ *
+ * This function is called to release a bitmap allocated by Tk_GetBitmap
+ * or TkGetBitmapFromData.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The reference count associated with bitmap is decremented, and it is
+ * officially deallocated if no-one is using it anymore.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_FreeBitmap(
+ Display *display, /* Display for which bitmap was allocated. */
+ Pixmap bitmap) /* Bitmap to be released. */
+{
+ Tcl_HashEntry *idHashPtr;
+ TkDisplay *dispPtr = TkGetDisplay(display);
+
+ if (!dispPtr->bitmapInit) {
+ Tcl_Panic("Tk_FreeBitmap called before Tk_GetBitmap");
+ }
+
+ idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, (char *) bitmap);
+ if (idHashPtr == NULL) {
+ Tcl_Panic("Tk_FreeBitmap received unknown bitmap argument");
+ }
+ FreeBitmap(Tcl_GetHashValue(idHashPtr));
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_FreeBitmapFromObj --
+ *
+ * This function is called to release a bitmap allocated by
+ * Tk_AllocBitmapFromObj. It does not throw away the Tcl_Obj *; it only
+ * gets rid of the hash table entry for this bitmap and clears the cached
+ * value that is normally stored in the object.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The reference count associated with the bitmap represented by objPtr
+ * is decremented, and the bitmap is released to X if there are no
+ * remaining uses for it.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_FreeBitmapFromObj(
+ Tk_Window tkwin, /* The window this bitmap lives in. Needed for
+ * the display value. */
+ Tcl_Obj *objPtr) /* The Tcl_Obj * to be freed. */
+{
+ FreeBitmap(GetBitmapFromObj(tkwin, objPtr));
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FreeBitmapObjProc, FreeBitmapObj --
+ *
+ * This proc is called to release an object reference to a bitmap.
+ * Called when the object's internal rep is released or when the cached
+ * bitmapPtr needs to be changed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The object reference count is decremented. When both it and the hash
+ * ref count go to zero, the color's resources are released.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+FreeBitmapObjProc(
+ Tcl_Obj *objPtr) /* The object we are releasing. */
+{
+ FreeBitmapObj(objPtr);
+ objPtr->typePtr = NULL;
+}
+
+static void
+FreeBitmapObj(
+ Tcl_Obj *objPtr) /* The object we are releasing. */
+{
+ TkBitmap *bitmapPtr = objPtr->internalRep.twoPtrValue.ptr1;
+
+ if (bitmapPtr != NULL) {
+ bitmapPtr->objRefCount--;
+ if ((bitmapPtr->objRefCount == 0)
+ && (bitmapPtr->resourceRefCount == 0)) {
+ ckfree(bitmapPtr);
+ }
+ objPtr->internalRep.twoPtrValue.ptr1 = NULL;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DupBitmapObjProc --
+ *
+ * When a cached bitmap object is duplicated, this is called to update
+ * the internal reps.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The color's objRefCount is incremented and the internal rep of the
+ * copy is set to point to it.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+DupBitmapObjProc(
+ Tcl_Obj *srcObjPtr, /* The object we are copying from. */
+ Tcl_Obj *dupObjPtr) /* The object we are copying to. */
+{
+ TkBitmap *bitmapPtr = srcObjPtr->internalRep.twoPtrValue.ptr1;
+
+ dupObjPtr->typePtr = srcObjPtr->typePtr;
+ dupObjPtr->internalRep.twoPtrValue.ptr1 = bitmapPtr;
+
+ if (bitmapPtr != NULL) {
+ bitmapPtr->objRefCount++;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetBitmapFromData --
+ *
+ * Given a description of the bits for a bitmap, make a bitmap that has
+ * the given properties. *** NOTE: this function is obsolete and really
+ * shouldn't be used anymore. ***
+ *
+ * Results:
+ * The return value is the X identifer for the desired bitmap (a
+ * one-plane Pixmap), unless it couldn't be created properly. In this
+ * case, None is returned and an error message is left in the interp's
+ * result. The caller should never modify the bitmap that is returned,
+ * and should eventually call Tk_FreeBitmap when the bitmap is no longer
+ * needed.
+ *
+ * Side effects:
+ * The bitmap is added to an internal database with a reference count.
+ * For each call to this function, there should eventually be a call to
+ * Tk_FreeBitmap, so that the database can be cleaned up when bitmaps
+ * aren't needed anymore.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+Pixmap
+Tk_GetBitmapFromData(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting. */
+ Tk_Window tkwin, /* Window in which bitmap will be used. */
+ const void *source, /* Bitmap data for bitmap shape. */
+ int width, int height) /* Dimensions of bitmap. */
+{
+ DataKey nameKey;
+ Tcl_HashEntry *dataHashPtr;
+ int isNew;
+ char string[16 + TCL_INTEGER_SPACE];
+ char *name;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (!tsdPtr->initialized) {
+ BitmapInit(dispPtr);
+ }
+
+ nameKey.source = source;
+ nameKey.width = width;
+ nameKey.height = height;
+ dataHashPtr = Tcl_CreateHashEntry(&dispPtr->bitmapDataTable,
+ (char *) &nameKey, &isNew);
+ if (!isNew) {
+ name = Tcl_GetHashValue(dataHashPtr);
+ } else {
+ dispPtr->bitmapAutoNumber++;
+ sprintf(string, "_tk%d", dispPtr->bitmapAutoNumber);
+ name = string;
+ Tcl_SetHashValue(dataHashPtr, name);
+ if (Tk_DefineBitmap(interp, name, source, width, height) != TCL_OK) {
+ Tcl_DeleteHashEntry(dataHashPtr);
+ return TCL_ERROR;
+ }
+ }
+ return Tk_GetBitmap(interp, tkwin, name);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetBitmapFromObj --
+ *
+ * Returns the bitmap referred to by a Tcl object. The bitmap must
+ * already have been allocated via a call to Tk_AllocBitmapFromObj or
+ * Tk_GetBitmap.
+ *
+ * Results:
+ * Returns the Pixmap that matches the tkwin and the string rep of
+ * objPtr.
+ *
+ * Side effects:
+ * If the object is not already a bitmap, the conversion will free any
+ * old internal representation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Pixmap
+Tk_GetBitmapFromObj(
+ Tk_Window tkwin,
+ Tcl_Obj *objPtr) /* The object from which to get pixels. */
+{
+ TkBitmap *bitmapPtr = GetBitmapFromObj(tkwin, objPtr);
+
+ return bitmapPtr->bitmap;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetBitmapFromObj --
+ *
+ * Returns the bitmap referred to by a Tcl object. The bitmap must
+ * already have been allocated via a call to Tk_AllocBitmapFromObj or
+ * Tk_GetBitmap.
+ *
+ * Results:
+ * Returns the TkBitmap * that matches the tkwin and the string rep of
+ * objPtr.
+ *
+ * Side effects:
+ * If the object is not already a bitmap, the conversion will free any
+ * old internal representation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static TkBitmap *
+GetBitmapFromObj(
+ Tk_Window tkwin, /* Window in which the bitmap will be used. */
+ Tcl_Obj *objPtr) /* The object that describes the desired
+ * bitmap. */
+{
+ TkBitmap *bitmapPtr;
+ Tcl_HashEntry *hashPtr;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+
+ if (objPtr->typePtr != &tkBitmapObjType) {
+ InitBitmapObj(objPtr);
+ }
+
+ bitmapPtr = objPtr->internalRep.twoPtrValue.ptr1;
+ if (bitmapPtr != NULL) {
+ if ((bitmapPtr->resourceRefCount > 0)
+ && (Tk_Display(tkwin) == bitmapPtr->display)) {
+ return bitmapPtr;
+ }
+ hashPtr = bitmapPtr->nameHashPtr;
+ FreeBitmapObj(objPtr);
+ } else {
+ hashPtr = Tcl_FindHashEntry(&dispPtr->bitmapNameTable,
+ Tcl_GetString(objPtr));
+ if (hashPtr == NULL) {
+ goto error;
+ }
+ }
+
+ /*
+ * At this point we've got a hash table entry, off of which hang one or
+ * more TkBitmap structures. See if any of them will work.
+ */
+
+ for (bitmapPtr = Tcl_GetHashValue(hashPtr); bitmapPtr != NULL;
+ bitmapPtr = bitmapPtr->nextPtr) {
+ if (Tk_Display(tkwin) == bitmapPtr->display) {
+ objPtr->internalRep.twoPtrValue.ptr1 = bitmapPtr;
+ bitmapPtr->objRefCount++;
+ return bitmapPtr;
+ }
+ }
+
+ error:
+ Tcl_Panic("GetBitmapFromObj called with non-existent bitmap!");
+ /*
+ * The following code isn't reached; it's just there to please compilers.
+ */
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InitBitmapObj --
+ *
+ * Bookeeping function to change an objPtr to a bitmap type.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The old internal rep of the object is freed. The internal rep is
+ * cleared. The final form of the object is set by either
+ * Tk_AllocBitmapFromObj or GetBitmapFromObj.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+InitBitmapObj(
+ Tcl_Obj *objPtr) /* The object to convert. */
+{
+ const Tcl_ObjType *typePtr;
+
+ /*
+ * Free the old internalRep before setting the new one.
+ */
+
+ Tcl_GetString(objPtr);
+ typePtr = objPtr->typePtr;
+ if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
+ typePtr->freeIntRepProc(objPtr);
+ }
+ objPtr->typePtr = &tkBitmapObjType;
+ objPtr->internalRep.twoPtrValue.ptr1 = NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * BitmapInit --
+ *
+ * Initializes hash tables used by this module. Initializes tables stored
+ * in TkDisplay structure if a TkDisplay pointer is passed in. Also
+ * initializes the thread-local data in the current thread's
+ * ThreadSpecificData structure.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Read the code.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+BitmapInit(
+ TkDisplay *dispPtr) /* TkDisplay structure encapsulating
+ * thread-specific data used by this module,
+ * or NULL if unavailable. */
+{
+ Tcl_Interp *dummy;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ /*
+ * First initialize the data in the ThreadSpecificData strucuture, if
+ * needed.
+ */
+
+ if (!tsdPtr->initialized) {
+ tsdPtr->initialized = 1;
+ dummy = Tcl_CreateInterp();
+ Tcl_InitHashTable(&tsdPtr->predefBitmapTable, TCL_STRING_KEYS);
+
+ Tk_DefineBitmap(dummy, "error", error_bits,
+ error_width, error_height);
+ Tk_DefineBitmap(dummy, "gray75", gray75_bits,
+ gray75_width, gray75_height);
+ Tk_DefineBitmap(dummy, "gray50", gray50_bits,
+ gray50_width, gray50_height);
+ Tk_DefineBitmap(dummy, "gray25", gray25_bits,
+ gray25_width, gray25_height);
+ Tk_DefineBitmap(dummy, "gray12", gray12_bits,
+ gray12_width, gray12_height);
+ Tk_DefineBitmap(dummy, "hourglass", hourglass_bits,
+ hourglass_width, hourglass_height);
+ Tk_DefineBitmap(dummy, "info", info_bits,
+ info_width, info_height);
+ Tk_DefineBitmap(dummy, "questhead", questhead_bits,
+ questhead_width, questhead_height);
+ Tk_DefineBitmap(dummy, "question", question_bits,
+ question_width, question_height);
+ Tk_DefineBitmap(dummy, "warning", warning_bits,
+ warning_width, warning_height);
+
+ TkpDefineNativeBitmaps();
+ Tcl_DeleteInterp(dummy);
+ }
+
+ /*
+ * Was a valid TkDisplay pointer passed? If so, initialize the Bitmap
+ * module tables in that structure.
+ */
+
+ if (dispPtr != NULL) {
+ dispPtr->bitmapInit = 1;
+ Tcl_InitHashTable(&dispPtr->bitmapNameTable, TCL_STRING_KEYS);
+ Tcl_InitHashTable(&dispPtr->bitmapDataTable,
+ sizeof(DataKey) / sizeof(int));
+
+ /*
+ * The call below is tricky: can't use sizeof(IdKey) because it gets
+ * padded with extra unpredictable bytes on some 64-bit machines.
+ */
+
+ /*
+ * The comment above doesn't make sense...
+ */
+
+ Tcl_InitHashTable(&dispPtr->bitmapIdTable, TCL_ONE_WORD_KEYS);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkReadBitmapFile --
+ *
+ * Loads a bitmap image in X bitmap format into the specified drawable.
+ * This is equivelent to the XReadBitmapFile in X.
+ *
+ * Results:
+ * Sets the size, hotspot, and bitmap on success.
+ *
+ * Side effects:
+ * Creates a new bitmap from the file data.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkReadBitmapFile(
+ Display *display,
+ Drawable d,
+ const char *filename,
+ unsigned int *width_return,
+ unsigned int *height_return,
+ Pixmap *bitmap_return,
+ int *x_hot_return,
+ int *y_hot_return)
+{
+ char *data;
+
+ data = TkGetBitmapData(NULL, NULL, filename,
+ (int *) width_return, (int *) height_return, x_hot_return,
+ y_hot_return);
+ if (data == NULL) {
+ return BitmapFileInvalid;
+ }
+
+ *bitmap_return = XCreateBitmapFromData(display, d, data, *width_return,
+ *height_return);
+ ckfree(data);
+ return BitmapSuccess;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkDebugBitmap --
+ *
+ * This function returns debugging information about a bitmap.
+ *
+ * Results:
+ * The return value is a list with one sublist for each TkBitmap
+ * corresponding to "name". Each sublist has two elements that contain
+ * the resourceRefCount and objRefCount fields from the TkBitmap
+ * structure.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TkDebugBitmap(
+ Tk_Window tkwin, /* The window in which the bitmap will be used
+ * (not currently used). */
+ const char *name) /* Name of the desired color. */
+{
+ TkBitmap *bitmapPtr;
+ Tcl_HashEntry *hashPtr;
+ Tcl_Obj *resultPtr, *objPtr;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+
+ resultPtr = Tcl_NewObj();
+ hashPtr = Tcl_FindHashEntry(&dispPtr->bitmapNameTable, name);
+ if (hashPtr != NULL) {
+ bitmapPtr = Tcl_GetHashValue(hashPtr);
+ if (bitmapPtr == NULL) {
+ Tcl_Panic("TkDebugBitmap found empty hash table entry");
+ }
+ for ( ; (bitmapPtr != NULL); bitmapPtr = bitmapPtr->nextPtr) {
+ objPtr = Tcl_NewObj();
+ Tcl_ListObjAppendElement(NULL, objPtr,
+ Tcl_NewIntObj(bitmapPtr->resourceRefCount));
+ Tcl_ListObjAppendElement(NULL, objPtr,
+ Tcl_NewIntObj(bitmapPtr->objRefCount));
+ Tcl_ListObjAppendElement(NULL, resultPtr, objPtr);
+ }
+ }
+ return resultPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkGetBitmapPredefTable --
+ *
+ * This function is used by tkMacBitmap.c to access the thread-specific
+ * predefBitmap table that maps from the names of the predefined bitmaps
+ * to data associated with those bitmaps. It is required because the
+ * table is allocated in thread-local storage and is not visible outside
+ * this file.
+
+ * Results:
+ * Returns a pointer to the predefined bitmap hash table for the current
+ * thread.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_HashTable *
+TkGetBitmapPredefTable(void)
+{
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ return &tsdPtr->predefBitmapTable;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkBusy.c b/tk8.6/generic/tkBusy.c
new file mode 100644
index 0000000..7bd6262
--- /dev/null
+++ b/tk8.6/generic/tkBusy.c
@@ -0,0 +1,931 @@
+/*
+ * tkBusy.c --
+ *
+ * This file provides functions that implement busy for Tk.
+ *
+ * Copyright 1993-1998 Lucent Technologies, Inc.
+ *
+ * The "busy" command was created by George Howlett. Adapted for
+ * integration into Tk by Jos Decoster and Donal K. Fellows.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkInt.h"
+#include "tkBusy.h"
+#include "default.h"
+
+/*
+ * Things about the busy system that may be configured. Note that on some
+ * platforms this may or may not have an effect.
+ */
+
+static const Tk_OptionSpec busyOptionSpecs[] = {
+ {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
+ DEF_BUSY_CURSOR, -1, Tk_Offset(Busy, cursor),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}
+};
+
+/*
+ * Forward declarations of functions defined in this file.
+ */
+
+static void BusyEventProc(ClientData clientData,
+ XEvent *eventPtr);
+static void BusyGeometryProc(ClientData clientData,
+ Tk_Window tkwin);
+static void BusyCustodyProc(ClientData clientData,
+ Tk_Window tkwin);
+static int ConfigureBusy(Tcl_Interp *interp, Busy *busyPtr,
+ int objc, Tcl_Obj *const objv[]);
+static Busy * CreateBusy(Tcl_Interp *interp, Tk_Window tkRef);
+static void DestroyBusy(void *dataPtr);
+static void DoConfigureNotify(Tk_FakeWin *winPtr);
+static inline Tk_Window FirstChild(Tk_Window parent);
+static Busy * GetBusy(Tcl_Interp *interp,
+ Tcl_HashTable *busyTablePtr,
+ Tcl_Obj *const windowObj);
+static int HoldBusy(Tcl_HashTable *busyTablePtr,
+ Tcl_Interp *interp, Tcl_Obj *const windowObj,
+ int configObjc, Tcl_Obj *const configObjv[]);
+static void MakeTransparentWindowExist(Tk_Window tkwin,
+ Window parent);
+static inline Tk_Window NextChild(Tk_Window tkwin);
+static void RefWinEventProc(ClientData clientData,
+ register XEvent *eventPtr);
+static inline void SetWindowInstanceData(Tk_Window tkwin,
+ ClientData instanceData);
+
+/*
+ * The "busy" geometry manager definition.
+ */
+
+static Tk_GeomMgr busyMgrInfo = {
+ "busy", /* Name of geometry manager used by winfo */
+ BusyGeometryProc, /* Procedure to for new geometry requests */
+ BusyCustodyProc, /* Procedure when window is taken away */
+};
+
+/*
+ * Helper functions, need to check if a Tcl/Tk alternative already exists.
+ */
+
+static inline Tk_Window
+FirstChild(
+ Tk_Window parent)
+{
+ struct TkWindow *parentPtr = (struct TkWindow *) parent;
+
+ return (Tk_Window) parentPtr->childList;
+}
+
+static inline Tk_Window
+NextChild(
+ Tk_Window tkwin)
+{
+ struct TkWindow *winPtr = (struct TkWindow *) tkwin;
+
+ if (winPtr == NULL) {
+ return NULL;
+ }
+ return (Tk_Window) winPtr->nextPtr;
+}
+
+static inline void
+SetWindowInstanceData(
+ Tk_Window tkwin,
+ ClientData instanceData)
+{
+ struct TkWindow *winPtr = (struct TkWindow *) tkwin;
+
+ winPtr->instanceData = instanceData;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * BusyCustodyProc --
+ *
+ * This procedure is invoked when the busy window has been stolen by
+ * another geometry manager. The information and memory associated with
+ * the busy window is released. I don't know why anyone would try to pack
+ * a busy window, but this should keep everything sane, if it is.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The Busy structure is freed at the next idle point.
+ *
+ *----------------------------------------------------------------------
+ */
+
+/* ARGSUSED */
+static void
+BusyCustodyProc(
+ ClientData clientData, /* Information about the busy window. */
+ Tk_Window tkwin) /* Not used. */
+{
+ Busy *busyPtr = clientData;
+
+ Tk_DeleteEventHandler(busyPtr->tkBusy, StructureNotifyMask, BusyEventProc,
+ busyPtr);
+ TkpHideBusyWindow(busyPtr);
+ busyPtr->tkBusy = NULL;
+ Tcl_EventuallyFree(busyPtr, (Tcl_FreeProc *)DestroyBusy);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * BusyGeometryProc --
+ *
+ * This procedure is invoked by Tk_GeometryRequest for busy windows.
+ * Busy windows never request geometry, so it's unlikely that this
+ * function will ever be called;it exists simply as a place holder for
+ * the GeomProc in the Geometry Manager structure.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+/* ARGSUSED */
+static void
+BusyGeometryProc(
+ ClientData clientData, /* Information about window that got new
+ * preferred geometry. */
+ Tk_Window tkwin) /* Other Tk-related information about the
+ * window. */
+{
+ /* Should never get here */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DoConfigureNotify --
+ *
+ * Generate a ConfigureNotify event describing the current configuration
+ * of a window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * An event is generated and processed by Tk_HandleEvent.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DoConfigureNotify(
+ Tk_FakeWin *winPtr) /* Window whose configuration was just
+ * changed. */
+{
+ XEvent event;
+
+ event.type = ConfigureNotify;
+ event.xconfigure.serial = LastKnownRequestProcessed(winPtr->display);
+ event.xconfigure.send_event = False;
+ event.xconfigure.display = winPtr->display;
+ event.xconfigure.event = winPtr->window;
+ event.xconfigure.window = winPtr->window;
+ event.xconfigure.x = winPtr->changes.x;
+ event.xconfigure.y = winPtr->changes.y;
+ event.xconfigure.width = winPtr->changes.width;
+ event.xconfigure.height = winPtr->changes.height;
+ event.xconfigure.border_width = winPtr->changes.border_width;
+ if (winPtr->changes.stack_mode == Above) {
+ event.xconfigure.above = winPtr->changes.sibling;
+ } else {
+ event.xconfigure.above = None;
+ }
+ event.xconfigure.override_redirect = winPtr->atts.override_redirect;
+ Tk_HandleEvent(&event);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * RefWinEventProc --
+ *
+ * This procedure is invoked by the Tk dispatcher for the following
+ * events on the reference window. If the reference and parent windows
+ * are the same, only the first event is important.
+ *
+ * 1) ConfigureNotify The reference window has been resized or
+ * moved. Move and resize the busy window to be
+ * the same size and position of the reference
+ * window.
+ *
+ * 2) DestroyNotify The reference window was destroyed. Destroy
+ * the busy window and the free resources used.
+ *
+ * 3) MapNotify The reference window was (re)shown. Map the
+ * busy window again.
+ *
+ * 4) UnmapNotify The reference window was hidden. Unmap the
+ * busy window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * When the reference window gets deleted, internal structures get
+ * cleaned up. When it gets resized, the busy window is resized
+ * accordingly. If it's displayed, the busy window is displayed. And when
+ * it's hidden, the busy window is unmapped.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+RefWinEventProc(
+ ClientData clientData, /* Busy window record */
+ register XEvent *eventPtr) /* Event which triggered call to routine */
+{
+ register Busy *busyPtr = clientData;
+
+ switch (eventPtr->type) {
+ case ReparentNotify:
+ case DestroyNotify:
+ /*
+ * Arrange for the busy structure to be removed at a proper time.
+ */
+
+ Tcl_EventuallyFree(busyPtr, (Tcl_FreeProc *)DestroyBusy);
+ break;
+
+ case ConfigureNotify:
+ if ((busyPtr->width != Tk_Width(busyPtr->tkRef)) ||
+ (busyPtr->height != Tk_Height(busyPtr->tkRef)) ||
+ (busyPtr->x != Tk_X(busyPtr->tkRef)) ||
+ (busyPtr->y != Tk_Y(busyPtr->tkRef))) {
+ int x, y;
+
+ busyPtr->width = Tk_Width(busyPtr->tkRef);
+ busyPtr->height = Tk_Height(busyPtr->tkRef);
+ busyPtr->x = Tk_X(busyPtr->tkRef);
+ busyPtr->y = Tk_Y(busyPtr->tkRef);
+
+ x = y = 0;
+
+ if (busyPtr->tkParent != busyPtr->tkRef) {
+ Tk_Window tkwin;
+
+ for (tkwin = busyPtr->tkRef; (tkwin != NULL) &&
+ (!Tk_IsTopLevel(tkwin)); tkwin = Tk_Parent(tkwin)) {
+ if (tkwin == busyPtr->tkParent) {
+ break;
+ }
+ x += Tk_X(tkwin) + Tk_Changes(tkwin)->border_width;
+ y += Tk_Y(tkwin) + Tk_Changes(tkwin)->border_width;
+ }
+ }
+ if (busyPtr->tkBusy != NULL) {
+ Tk_MoveResizeWindow(busyPtr->tkBusy, x, y, busyPtr->width,
+ busyPtr->height);
+ TkpShowBusyWindow(busyPtr);
+ }
+ }
+ break;
+
+ case MapNotify:
+ if (busyPtr->tkParent != busyPtr->tkRef) {
+ TkpShowBusyWindow(busyPtr);
+ }
+ break;
+
+ case UnmapNotify:
+ if (busyPtr->tkParent != busyPtr->tkRef) {
+ TkpHideBusyWindow(busyPtr);
+ }
+ break;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyBusy --
+ *
+ * This procedure is called from the Tk event dispatcher. It releases X
+ * resources and memory used by the busy window and updates the internal
+ * hash table.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory and resources are released and the Tk event handler is removed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DestroyBusy(
+ void *data) /* Busy window structure record */
+{
+ register Busy *busyPtr = data;
+
+ if (busyPtr->hashPtr != NULL) {
+ Tcl_DeleteHashEntry(busyPtr->hashPtr);
+ }
+ Tk_DeleteEventHandler(busyPtr->tkRef, StructureNotifyMask,
+ RefWinEventProc, busyPtr);
+
+ if (busyPtr->tkBusy != NULL) {
+ Tk_FreeConfigOptions(data, busyPtr->optionTable, busyPtr->tkBusy);
+ Tk_DeleteEventHandler(busyPtr->tkBusy, StructureNotifyMask,
+ BusyEventProc, busyPtr);
+ Tk_ManageGeometry(busyPtr->tkBusy, NULL, busyPtr);
+ Tk_DestroyWindow(busyPtr->tkBusy);
+ }
+ ckfree(data);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * BusyEventProc --
+ *
+ * This procedure is invoked by the Tk dispatcher for events on the busy
+ * window itself. We're only concerned with destroy events.
+ *
+ * It might be necessary (someday) to watch resize events. Right now, I
+ * don't think there's any point in it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * When a busy window is destroyed, all internal structures associated
+ * with it released at the next idle point.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+BusyEventProc(
+ ClientData clientData, /* Busy window record */
+ XEvent *eventPtr) /* Event which triggered call to routine */
+{
+ Busy *busyPtr = clientData;
+
+ if (eventPtr->type == DestroyNotify) {
+ busyPtr->tkBusy = NULL;
+ Tcl_EventuallyFree(busyPtr, (Tcl_FreeProc *)DestroyBusy);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MakeTransparentWindowExist --
+ *
+ * Similar to Tk_MakeWindowExist but instead creates a transparent window
+ * to block for user events from sibling windows.
+ *
+ * Differences from Tk_MakeWindowExist.
+ *
+ * 1. This is always a "busy" window. There's never a platform-specific
+ * class procedure to execute instead.
+ * 2. The window is transparent and never will contain children, so
+ * colormap information is irrelevant.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * When the procedure returns, the internal window associated with tkwin
+ * is guaranteed to exist. This may require the window's ancestors to be
+ * created too.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+MakeTransparentWindowExist(
+ Tk_Window tkwin, /* Token for window. */
+ Window parent) /* Parent window. */
+{
+ TkWindow *winPtr = (TkWindow *) tkwin;
+ Tcl_HashEntry *hPtr;
+ int notUsed;
+ TkDisplay *dispPtr;
+
+ if (winPtr->window != None) {
+ return; /* Window already exists. */
+ }
+
+ /*
+ * Create a transparent window and put it on top.
+ */
+
+ TkpMakeTransparentWindowExist(tkwin, parent);
+
+ if (winPtr->window == None) {
+ return; /* Platform didn't make Window. */
+ }
+
+ dispPtr = winPtr->dispPtr;
+ hPtr = Tcl_CreateHashEntry(&dispPtr->winTable, (char *) winPtr->window,
+ &notUsed);
+ Tcl_SetHashValue(hPtr, winPtr);
+ winPtr->dirtyAtts = 0;
+ winPtr->dirtyChanges = 0;
+
+ if (!(winPtr->flags & TK_TOP_HIERARCHY)) {
+ TkWindow *winPtr2;
+
+ /*
+ * If any siblings higher up in the stacking order have already been
+ * created then move this window to its rightful position in the
+ * stacking order.
+ *
+ * NOTE: this code ignores any changes anyone might have made to the
+ * sibling and stack_mode field of the window's attributes, so it
+ * really isn't safe for these to be manipulated except by calling
+ * Tk_RestackWindow.
+ */
+
+ for (winPtr2 = winPtr->nextPtr; winPtr2 != NULL;
+ winPtr2 = winPtr2->nextPtr) {
+ if ((winPtr2->window != None) &&
+ !(winPtr2->flags & (TK_TOP_HIERARCHY|TK_REPARENTED))) {
+ XWindowChanges changes;
+
+ changes.sibling = winPtr2->window;
+ changes.stack_mode = Below;
+ XConfigureWindow(winPtr->display, winPtr->window,
+ CWSibling | CWStackMode, &changes);
+ break;
+ }
+ }
+ }
+
+ /*
+ * Issue a ConfigureNotify event if there were deferred configuration
+ * changes (but skip it if the window is being deleted; the
+ * ConfigureNotify event could cause problems if we're being called from
+ * Tk_DestroyWindow under some conditions).
+ */
+
+ if ((winPtr->flags & TK_NEED_CONFIG_NOTIFY)
+ && !(winPtr->flags & TK_ALREADY_DEAD)) {
+ winPtr->flags &= ~TK_NEED_CONFIG_NOTIFY;
+ DoConfigureNotify((Tk_FakeWin *) tkwin);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CreateBusy --
+ *
+ * Creates a child transparent window that obscures its parent window
+ * thereby effectively blocking device events. The size and position of
+ * the busy window is exactly that of the reference window.
+ *
+ * We want to create sibling to the window to be blocked. If the busy
+ * window is a child of the window to be blocked, Enter/Leave events can
+ * sneak through. Futhermore under WIN32, messages of transparent windows
+ * are sent directly to the parent. The only exception to this are
+ * toplevels, since we can't make a sibling. Fortunately, toplevel
+ * windows rarely receive events that need blocking.
+ *
+ * Results:
+ * Returns a pointer to the new busy window structure.
+ *
+ * Side effects:
+ * When the busy window is eventually displayed, it will screen device
+ * events (in the area of the reference window) from reaching its parent
+ * window and its children. User feed back can be achieved by changing
+ * the cursor.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Busy *
+CreateBusy(
+ Tcl_Interp *interp, /* Interpreter to report error to */
+ Tk_Window tkRef) /* Window hosting the busy window */
+{
+ Busy *busyPtr;
+ size_t length;
+ int x, y;
+ const char *fmt;
+ char *name;
+ Tk_Window tkBusy, tkChild, tkParent;
+ Window parent;
+ Tk_FakeWin *winPtr;
+
+ busyPtr = ckalloc(sizeof(Busy));
+ x = y = 0;
+ length = strlen(Tk_Name(tkRef));
+ name = ckalloc(length + 6);
+ if (Tk_IsTopLevel(tkRef)) {
+ fmt = "_Busy"; /* Child */
+ tkParent = tkRef;
+ } else {
+ Tk_Window tkwin;
+
+ fmt = "%s_Busy"; /* Sibling */
+ tkParent = Tk_Parent(tkRef);
+ for (tkwin = tkRef; (tkwin != NULL) && !Tk_IsTopLevel(tkwin);
+ tkwin = Tk_Parent(tkwin)) {
+ if (tkwin == tkParent) {
+ break;
+ }
+ x += Tk_X(tkwin) + Tk_Changes(tkwin)->border_width;
+ y += Tk_Y(tkwin) + Tk_Changes(tkwin)->border_width;
+ }
+ }
+ for (tkChild = FirstChild(tkParent); tkChild != NULL;
+ tkChild = NextChild(tkChild)) {
+ Tk_MakeWindowExist(tkChild);
+ }
+ sprintf(name, fmt, Tk_Name(tkRef));
+ tkBusy = Tk_CreateWindow(interp, tkParent, name, NULL);
+ ckfree(name);
+
+ if (tkBusy == NULL) {
+ return NULL;
+ }
+ Tk_MakeWindowExist(tkRef);
+ busyPtr->display = Tk_Display(tkRef);
+ busyPtr->interp = interp;
+ busyPtr->tkRef = tkRef;
+ busyPtr->tkParent = tkParent;
+ busyPtr->tkBusy = tkBusy;
+ busyPtr->width = Tk_Width(tkRef);
+ busyPtr->height = Tk_Height(tkRef);
+ busyPtr->x = Tk_X(tkRef);
+ busyPtr->y = Tk_Y(tkRef);
+ busyPtr->cursor = NULL;
+ Tk_SetClass(tkBusy, "Busy");
+ busyPtr->optionTable = Tk_CreateOptionTable(interp, busyOptionSpecs);
+ if (Tk_InitOptions(interp, (char *) busyPtr, busyPtr->optionTable,
+ tkBusy) != TCL_OK) {
+ Tk_DestroyWindow(tkBusy);
+ return NULL;
+ }
+ SetWindowInstanceData(tkBusy, busyPtr);
+ winPtr = (Tk_FakeWin *) tkRef;
+
+ TkpCreateBusy(winPtr, tkRef, &parent, tkParent, busyPtr);
+
+ MakeTransparentWindowExist(tkBusy, parent);
+
+ Tk_MoveResizeWindow(tkBusy, x, y, busyPtr->width, busyPtr->height);
+
+ /*
+ * Only worry if the busy window is destroyed.
+ */
+
+ Tk_CreateEventHandler(tkBusy, StructureNotifyMask, BusyEventProc,
+ busyPtr);
+
+ /*
+ * Indicate that the busy window's geometry is being managed. This will
+ * also notify us if the busy window is ever packed.
+ */
+
+ Tk_ManageGeometry(tkBusy, &busyMgrInfo, busyPtr);
+ if (busyPtr->cursor != NULL) {
+ Tk_DefineCursor(tkBusy, busyPtr->cursor);
+ }
+
+ /*
+ * Track the reference window to see if it is resized or destroyed.
+ */
+
+ Tk_CreateEventHandler(tkRef, StructureNotifyMask, RefWinEventProc,
+ busyPtr);
+ return busyPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConfigureBusy --
+ *
+ * This procedure is called from the Tk event dispatcher. It releases X
+ * resources and memory used by the busy window and updates the internal
+ * hash table.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory and resources are released and the Tk event handler is removed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ConfigureBusy(
+ Tcl_Interp *interp,
+ Busy *busyPtr,
+ int objc,
+ Tcl_Obj *const objv[])
+{
+ Tk_Cursor oldCursor = busyPtr->cursor;
+
+ if (Tk_SetOptions(interp, (char *) busyPtr, busyPtr->optionTable, objc,
+ objv, busyPtr->tkBusy, NULL, NULL) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (busyPtr->cursor != oldCursor) {
+ if (busyPtr->cursor == NULL) {
+ Tk_UndefineCursor(busyPtr->tkBusy);
+ } else {
+ Tk_DefineCursor(busyPtr->tkBusy, busyPtr->cursor);
+ }
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetBusy --
+ *
+ * Returns the busy window structure associated with the reference
+ * window, keyed by its path name. The clientData argument is the main
+ * window of the interpreter, used to search for the reference window in
+ * its own window hierarchy.
+ *
+ * Results:
+ * If path name represents a reference window with a busy window, a
+ * pointer to the busy window structure is returned. Otherwise, NULL is
+ * returned and an error message is left in interp->result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Busy *
+GetBusy(
+ Tcl_Interp *interp, /* Interpreter to look up main window of. */
+ Tcl_HashTable *busyTablePtr,/* Busy hash table */
+ Tcl_Obj *const windowObj) /* Path name of parent window */
+{
+ Tcl_HashEntry *hPtr;
+ Tk_Window tkwin;
+
+ if (TkGetWindowFromObj(interp, Tk_MainWindow(interp), windowObj,
+ &tkwin) != TCL_OK) {
+ return NULL;
+ }
+ hPtr = Tcl_FindHashEntry(busyTablePtr, (char *) tkwin);
+ if (hPtr == NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't find busy window \"%s\"", Tcl_GetString(windowObj)));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "BUSY",
+ Tcl_GetString(windowObj), NULL);
+ return NULL;
+ }
+ return Tcl_GetHashValue(hPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HoldBusy --
+ *
+ * Creates (if necessary) and maps a busy window, thereby preventing
+ * device events from being be received by the parent window and its
+ * children.
+ *
+ * Results:
+ * Returns a standard TCL result. If path name represents a busy window,
+ * it is unmapped and TCL_OK is returned. Otherwise, TCL_ERROR is
+ * returned and an error message is left in interp->result.
+ *
+ * Side effects:
+ * The busy window is created and displayed, blocking events from the
+ * parent window and its children.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+HoldBusy(
+ Tcl_HashTable *busyTablePtr,/* Busy hash table. */
+ Tcl_Interp *interp, /* Interpreter to report errors to. */
+ Tcl_Obj *const windowObj, /* Window name. */
+ int configObjc, /* Option pairs. */
+ Tcl_Obj *const configObjv[])
+{
+ Tk_Window tkwin;
+ Tcl_HashEntry *hPtr;
+ Busy *busyPtr;
+ int isNew, result;
+
+ if (TkGetWindowFromObj(interp, Tk_MainWindow(interp), windowObj,
+ &tkwin) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ hPtr = Tcl_CreateHashEntry(busyTablePtr, (char *) tkwin, &isNew);
+ if (isNew) {
+ busyPtr = CreateBusy(interp, tkwin);
+ if (busyPtr == NULL) {
+ return TCL_ERROR;
+ }
+ Tcl_SetHashValue(hPtr, busyPtr);
+ busyPtr->hashPtr = hPtr;
+ } else {
+ busyPtr = Tcl_GetHashValue(hPtr);
+ }
+
+ busyPtr->tablePtr = busyTablePtr;
+ result = ConfigureBusy(interp, busyPtr, configObjc, configObjv);
+
+ /*
+ * Don't map the busy window unless the reference window is also currently
+ * displayed.
+ */
+
+ if (Tk_IsMapped(busyPtr->tkRef)) {
+ TkpShowBusyWindow(busyPtr);
+ } else {
+ TkpHideBusyWindow(busyPtr);
+ }
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_BusyObjCmd --
+ *
+ * This function is invoked to process the "tk busy" 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_BusyObjCmd(
+ 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 = clientData;
+ Tcl_HashTable *busyTablePtr = &((TkWindow *) tkwin)->mainPtr->busyTable;
+ Busy *busyPtr;
+ Tcl_Obj *objPtr;
+ int index, result = TCL_OK;
+ static const char *const optionStrings[] = {
+ "cget", "configure", "current", "forget", "hold", "status", NULL
+ };
+ enum options {
+ BUSY_CGET, BUSY_CONFIGURE, BUSY_CURRENT, BUSY_FORGET, BUSY_HOLD,
+ BUSY_STATUS
+ };
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "options ?arg arg ...?");
+ return TCL_ERROR;
+ }
+
+ /*
+ * [tk busy <window>] command shortcut.
+ */
+
+ if (Tcl_GetString(objv[1])[0] == '.') {
+ if (objc%2 == 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, "window ?option value ...?");
+ return TCL_ERROR;
+ }
+ return HoldBusy(busyTablePtr, interp, objv[1], objc-2, objv+2);
+ }
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings,
+ sizeof(char *), "option", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch ((enum options) index) {
+ case BUSY_CGET:
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window option");
+ return TCL_ERROR;
+ }
+ busyPtr = GetBusy(interp, busyTablePtr, objv[2]);
+ if (busyPtr == NULL) {
+ return TCL_ERROR;
+ }
+ Tcl_Preserve(busyPtr);
+ objPtr = Tk_GetOptionValue(interp, (char *) busyPtr,
+ busyPtr->optionTable, objv[3], busyPtr->tkBusy);
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ } else {
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ Tcl_Release(busyPtr);
+ return result;
+
+ case BUSY_CONFIGURE:
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?option? ?value ...?");
+ return TCL_ERROR;
+ }
+ busyPtr = GetBusy(interp, busyTablePtr, objv[2]);
+ if (busyPtr == NULL) {
+ return TCL_ERROR;
+ }
+ Tcl_Preserve(busyPtr);
+ if (objc <= 4) {
+ objPtr = Tk_GetOptionInfo(interp, (char *) busyPtr,
+ busyPtr->optionTable, (objc == 4) ? objv[3] : NULL,
+ busyPtr->tkBusy);
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ } else {
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ } else {
+ result = ConfigureBusy(interp, busyPtr, objc-3, objv+3);
+ }
+ Tcl_Release(busyPtr);
+ return result;
+
+ case BUSY_CURRENT: {
+ Tcl_HashEntry *hPtr;
+ Tcl_HashSearch cursor;
+ const char *pattern = (objc == 3 ? Tcl_GetString(objv[2]) : NULL);
+
+ objPtr = Tcl_NewObj();
+ for (hPtr = Tcl_FirstHashEntry(busyTablePtr, &cursor); hPtr != NULL;
+ hPtr = Tcl_NextHashEntry(&cursor)) {
+ busyPtr = Tcl_GetHashValue(hPtr);
+ if (pattern == NULL ||
+ Tcl_StringMatch(Tk_PathName(busyPtr->tkRef), pattern)) {
+ Tcl_ListObjAppendElement(interp, objPtr,
+ TkNewWindowObj(busyPtr->tkRef));
+ }
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ return TCL_OK;
+ }
+
+ case BUSY_FORGET:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window");
+ return TCL_ERROR;
+ }
+ busyPtr = GetBusy(interp, busyTablePtr, objv[2]);
+ if (busyPtr == NULL) {
+ return TCL_ERROR;
+ }
+ TkpHideBusyWindow(busyPtr);
+ Tcl_EventuallyFree(busyPtr, (Tcl_FreeProc *)DestroyBusy);
+ return TCL_OK;
+
+ case BUSY_HOLD:
+ if (objc < 3 || objc%2 != 1) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?option value ...?");
+ return TCL_ERROR;
+ }
+ return HoldBusy(busyTablePtr, interp, objv[2], objc-3, objv+3);
+
+ case BUSY_STATUS:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window");
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
+ GetBusy(interp, busyTablePtr, objv[2]) != NULL));
+ return TCL_OK;
+ }
+
+ Tcl_Panic("unhandled option: %d", index);
+ return TCL_ERROR; /* Unreachable */
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkBusy.h b/tk8.6/generic/tkBusy.h
new file mode 100644
index 0000000..9e6b69b
--- /dev/null
+++ b/tk8.6/generic/tkBusy.h
@@ -0,0 +1,41 @@
+/*
+ * tkBusy.h --
+ *
+ * This file defines the type of the structure describing a busy window.
+ *
+ * Copyright 1993-1998 Lucent Technologies, Inc.
+ *
+ * The "busy" command was created by George Howlett. Adapted for
+ * integration into Tk by Jos Decoster and Donal K. Fellows.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+typedef struct Busy {
+ Display *display; /* Display of busy window */
+ Tcl_Interp *interp; /* Interpreter where "busy" command was
+ * created. It's used to key the searches in
+ * the window hierarchy. See the "windows"
+ * command. */
+ Tk_Window tkBusy; /* Busy window: Transparent window used to
+ * block delivery of events to windows
+ * underneath it. */
+ Tk_Window tkParent; /* Parent window of the busy window. It may be
+ * the reference window (if the reference is a
+ * toplevel) or a mutual ancestor of the
+ * reference window */
+ Tk_Window tkRef; /* Reference window of the busy window. It is
+ * used to manage the size and position of the
+ * busy window. */
+ int x, y; /* Position of the reference window */
+ int width, height; /* Size of the reference window. Retained to
+ * know if the reference window has been
+ * reconfigured to a new size. */
+ int menuBar; /* Menu bar flag. */
+ Tk_Cursor cursor; /* Cursor for the busy window. */
+ Tcl_HashEntry *hashPtr; /* Used the delete the busy window entry out
+ * of the global hash table. */
+ Tcl_HashTable *tablePtr;
+ Tk_OptionTable optionTable;
+} Busy;
diff --git a/tk8.6/generic/tkButton.c b/tk8.6/generic/tkButton.c
new file mode 100644
index 0000000..37cfcd2
--- /dev/null
+++ b/tk8.6/generic/tkButton.c
@@ -0,0 +1,1931 @@
+/*
+ * tkButton.c --
+ *
+ * This module implements a collection of button-like widgets for the Tk
+ * toolkit. The widgets implemented include buttons, checkbuttons,
+ * radiobuttons, and labels.
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1998 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkInt.h"
+#include "tkButton.h"
+#include "default.h"
+
+typedef struct {
+ int defaultsInitialized;
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+
+/*
+ * Class names for buttons, indexed by one of the type values defined in
+ * tkButton.h.
+ */
+
+static const char *const classNames[] = {"Label", "Button", "Checkbutton", "Radiobutton"};
+
+/*
+ * The following table defines the legal values for the -default option. It is
+ * used together with the "enum defaultValue" declaration in tkButton.h.
+ */
+
+static const char *const defaultStrings[] = {
+ "active", "disabled", "normal", NULL
+};
+
+/*
+ * The following table defines the legal values for the -state option.
+ * It is used together with the "enum state" declaration in tkButton.h.
+ */
+
+static const char *const stateStrings[] = {
+ "active", "disabled", "normal", NULL
+};
+
+/*
+ * The following table defines the legal values for the -compound option.
+ * It is used with the "enum compound" declaration in tkButton.h
+ */
+
+static const char *const compoundStrings[] = {
+ "bottom", "center", "left", "none", "right", "top", NULL
+};
+
+char tkDefButtonHighlightWidth[TCL_INTEGER_SPACE] = DEF_BUTTON_HIGHLIGHT_WIDTH;
+char tkDefButtonPadx[TCL_INTEGER_SPACE] = DEF_BUTTON_PADX;
+char tkDefButtonPady[TCL_INTEGER_SPACE] = DEF_BUTTON_PADY;
+char tkDefButtonBorderWidth[TCL_INTEGER_SPACE] = DEF_BUTTON_BORDER_WIDTH;
+char tkDefLabelHighlightWidth[TCL_INTEGER_SPACE] = DEF_LABEL_HIGHLIGHT_WIDTH;
+char tkDefLabelPadx[TCL_INTEGER_SPACE] = DEF_LABCHKRAD_PADX;
+char tkDefLabelPady[TCL_INTEGER_SPACE] = DEF_LABCHKRAD_PADY;
+
+/*
+ * Information used for parsing configuration options. There is a
+ * separate table for each of the four widget classes.
+ */
+
+static const Tk_OptionSpec labelOptionSpecs[] = {
+ {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",
+ DEF_BUTTON_ACTIVE_BG_COLOR, -1, Tk_Offset(TkButton, activeBorder),
+ 0, DEF_BUTTON_ACTIVE_BG_MONO, 0},
+ {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background",
+ DEF_BUTTON_ACTIVE_FG_COLOR, -1, Tk_Offset(TkButton, activeFg),
+ TK_OPTION_NULL_OK, DEF_BUTTON_ACTIVE_FG_MONO, 0},
+ {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
+ DEF_BUTTON_ANCHOR, -1, Tk_Offset(TkButton, anchor), 0, 0, 0},
+ {TK_OPTION_BORDER, "-background", "background", "Background",
+ DEF_BUTTON_BG_COLOR, -1, Tk_Offset(TkButton, normalBorder),
+ 0, DEF_BUTTON_BG_MONO, 0},
+ {TK_OPTION_SYNONYM, "-bd", NULL, NULL,
+ NULL, 0, -1, 0, "-borderwidth", 0},
+ {TK_OPTION_SYNONYM, "-bg", NULL, NULL,
+ NULL, 0, -1, 0, "-background", 0},
+ {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap",
+ DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ tkDefButtonBorderWidth, Tk_Offset(TkButton, borderWidthPtr),
+ Tk_Offset(TkButton, borderWidth), 0, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound",
+ DEF_BUTTON_COMPOUND, -1, Tk_Offset(TkButton, compound), 0,
+ compoundStrings, 0},
+ {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
+ DEF_BUTTON_CURSOR, -1, Tk_Offset(TkButton, cursor),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
+ "DisabledForeground", DEF_BUTTON_DISABLED_FG_COLOR,
+ -1, Tk_Offset(TkButton, disabledFg), TK_OPTION_NULL_OK,
+ (ClientData) DEF_BUTTON_DISABLED_FG_MONO, 0},
+ {TK_OPTION_SYNONYM, "-fg", "foreground", NULL,
+ NULL, 0, -1, 0, "-foreground", 0},
+ {TK_OPTION_FONT, "-font", "font", "Font",
+ DEF_BUTTON_FONT, -1, Tk_Offset(TkButton, tkfont), 0, 0, 0},
+ {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
+ DEF_BUTTON_FG, -1, Tk_Offset(TkButton, normalFg), 0, 0, 0},
+ {TK_OPTION_STRING, "-height", "height", "Height",
+ DEF_BUTTON_HEIGHT, Tk_Offset(TkButton, heightPtr), -1, 0, 0, 0},
+ {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground",
+ "HighlightBackground", DEF_BUTTON_HIGHLIGHT_BG_COLOR,
+ -1, Tk_Offset(TkButton, highlightBorder), 0,
+ (ClientData) DEF_BUTTON_HIGHLIGHT_BG_MONO, 0},
+ {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
+ DEF_BUTTON_HIGHLIGHT, -1, Tk_Offset(TkButton, highlightColorPtr),
+ 0, 0, 0},
+ {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
+ "HighlightThickness", tkDefLabelHighlightWidth,
+ Tk_Offset(TkButton, highlightWidthPtr),
+ Tk_Offset(TkButton, highlightWidth), 0, 0, 0},
+ {TK_OPTION_STRING, "-image", "image", "Image",
+ DEF_BUTTON_IMAGE, Tk_Offset(TkButton, imagePtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
+ DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkButton, justify), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
+ tkDefLabelPadx, Tk_Offset(TkButton, padXPtr),
+ Tk_Offset(TkButton, padX), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
+ tkDefLabelPady, Tk_Offset(TkButton, padYPtr),
+ Tk_Offset(TkButton, padY), 0, 0, 0},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ DEF_LABCHKRAD_RELIEF, -1, Tk_Offset(TkButton, relief), 0, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-state", "state", "State",
+ DEF_BUTTON_STATE, -1, Tk_Offset(TkButton, state),
+ 0, stateStrings, 0},
+ {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
+ DEF_LABEL_TAKE_FOCUS, Tk_Offset(TkButton, takeFocusPtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-text", "text", "Text",
+ DEF_BUTTON_TEXT, Tk_Offset(TkButton, textPtr), -1, 0, 0, 0},
+ {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
+ DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarNamePtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_INT, "-underline", "underline", "Underline",
+ DEF_BUTTON_UNDERLINE, -1, Tk_Offset(TkButton, underline), 0, 0, 0},
+ {TK_OPTION_STRING, "-width", "width", "Width",
+ DEF_BUTTON_WIDTH, Tk_Offset(TkButton, widthPtr), -1, 0, 0, 0},
+ {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",
+ DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr),
+ Tk_Offset(TkButton, wrapLength), 0, 0, 0},
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}
+};
+
+static const Tk_OptionSpec buttonOptionSpecs[] = {
+ {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",
+ DEF_BUTTON_ACTIVE_BG_COLOR, -1, Tk_Offset(TkButton, activeBorder),
+ 0, DEF_BUTTON_ACTIVE_BG_MONO, 0},
+ {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background",
+ DEF_BUTTON_ACTIVE_FG_COLOR, -1, Tk_Offset(TkButton, activeFg),
+ TK_OPTION_NULL_OK, DEF_BUTTON_ACTIVE_FG_MONO, 0},
+ {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
+ DEF_BUTTON_ANCHOR, -1, Tk_Offset(TkButton, anchor), 0, 0, 0},
+ {TK_OPTION_BORDER, "-background", "background", "Background",
+ DEF_BUTTON_BG_COLOR, -1, Tk_Offset(TkButton, normalBorder),
+ 0, DEF_BUTTON_BG_MONO, 0},
+ {TK_OPTION_SYNONYM, "-bd", NULL, NULL,
+ NULL, 0, -1, 0, "-borderwidth", 0},
+ {TK_OPTION_SYNONYM, "-bg", NULL, NULL,
+ NULL, 0, -1, 0, "-background", 0},
+ {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap",
+ DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ tkDefButtonBorderWidth, Tk_Offset(TkButton, borderWidthPtr),
+ Tk_Offset(TkButton, borderWidth), 0, 0, 0},
+ {TK_OPTION_STRING, "-command", "command", "Command",
+ DEF_BUTTON_COMMAND, Tk_Offset(TkButton, commandPtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound",
+ DEF_BUTTON_COMPOUND, -1, Tk_Offset(TkButton, compound), 0,
+ compoundStrings, 0},
+ {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
+ DEF_BUTTON_CURSOR, -1, Tk_Offset(TkButton, cursor),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-default", "default", "Default",
+ DEF_BUTTON_DEFAULT, -1, Tk_Offset(TkButton, defaultState),
+ 0, defaultStrings, 0},
+ {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
+ "DisabledForeground", DEF_BUTTON_DISABLED_FG_COLOR,
+ -1, Tk_Offset(TkButton, disabledFg), TK_OPTION_NULL_OK,
+ (ClientData) DEF_BUTTON_DISABLED_FG_MONO, 0},
+ {TK_OPTION_SYNONYM, "-fg", "foreground", NULL,
+ NULL, 0, -1, 0, "-foreground", 0},
+ {TK_OPTION_FONT, "-font", "font", "Font",
+ DEF_BUTTON_FONT, -1, Tk_Offset(TkButton, tkfont), 0, 0, 0},
+ {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
+ DEF_BUTTON_FG, -1, Tk_Offset(TkButton, normalFg), 0, 0, 0},
+ {TK_OPTION_STRING, "-height", "height", "Height",
+ DEF_BUTTON_HEIGHT, Tk_Offset(TkButton, heightPtr), -1, 0, 0, 0},
+ {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground",
+ "HighlightBackground", DEF_BUTTON_HIGHLIGHT_BG_COLOR,
+ -1, Tk_Offset(TkButton, highlightBorder), 0,
+ (ClientData) DEF_BUTTON_HIGHLIGHT_BG_MONO, 0},
+ {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
+ DEF_BUTTON_HIGHLIGHT, -1, Tk_Offset(TkButton, highlightColorPtr),
+ 0, 0, 0},
+ {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
+ "HighlightThickness", tkDefButtonHighlightWidth,
+ Tk_Offset(TkButton, highlightWidthPtr),
+ Tk_Offset(TkButton, highlightWidth), 0, 0, 0},
+ {TK_OPTION_STRING, "-image", "image", "Image",
+ DEF_BUTTON_IMAGE, Tk_Offset(TkButton, imagePtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
+ DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkButton, justify), 0, 0, 0},
+ {TK_OPTION_RELIEF, "-overrelief", "overRelief", "OverRelief",
+ DEF_BUTTON_OVER_RELIEF, -1, Tk_Offset(TkButton, overRelief),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
+ tkDefButtonPadx, Tk_Offset(TkButton, padXPtr),
+ Tk_Offset(TkButton, padX), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
+ tkDefButtonPady, Tk_Offset(TkButton, padYPtr),
+ Tk_Offset(TkButton, padY), 0, 0, 0},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ DEF_BUTTON_RELIEF, -1, Tk_Offset(TkButton, relief),
+ 0, 0, 0},
+ {TK_OPTION_INT, "-repeatdelay", "repeatDelay", "RepeatDelay",
+ DEF_BUTTON_REPEAT_DELAY, -1, Tk_Offset(TkButton, repeatDelay),
+ 0, 0, 0},
+ {TK_OPTION_INT, "-repeatinterval", "repeatInterval", "RepeatInterval",
+ DEF_BUTTON_REPEAT_INTERVAL, -1, Tk_Offset(TkButton, repeatInterval),
+ 0, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-state", "state", "State",
+ DEF_BUTTON_STATE, -1, Tk_Offset(TkButton, state),
+ 0, stateStrings, 0},
+ {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
+ DEF_BUTTON_TAKE_FOCUS, Tk_Offset(TkButton, takeFocusPtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-text", "text", "Text",
+ DEF_BUTTON_TEXT, Tk_Offset(TkButton, textPtr), -1, 0, 0, 0},
+ {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
+ DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarNamePtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_INT, "-underline", "underline", "Underline",
+ DEF_BUTTON_UNDERLINE, -1, Tk_Offset(TkButton, underline), 0, 0, 0},
+ {TK_OPTION_STRING, "-width", "width", "Width",
+ DEF_BUTTON_WIDTH, Tk_Offset(TkButton, widthPtr), -1, 0, 0, 0},
+ {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",
+ DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr),
+ Tk_Offset(TkButton, wrapLength), 0, 0, 0},
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0}
+};
+
+static const Tk_OptionSpec checkbuttonOptionSpecs[] = {
+ {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",
+ DEF_BUTTON_ACTIVE_BG_COLOR, -1, Tk_Offset(TkButton, activeBorder),
+ 0, DEF_BUTTON_ACTIVE_BG_MONO, 0},
+ {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background",
+ DEF_CHKRAD_ACTIVE_FG_COLOR, -1, Tk_Offset(TkButton, activeFg),
+ TK_OPTION_NULL_OK, DEF_BUTTON_ACTIVE_FG_MONO, 0},
+ {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
+ DEF_BUTTON_ANCHOR, -1, Tk_Offset(TkButton, anchor), 0, 0, 0},
+ {TK_OPTION_BORDER, "-background", "background", "Background",
+ DEF_BUTTON_BG_COLOR, -1, Tk_Offset(TkButton, normalBorder),
+ 0, DEF_BUTTON_BG_MONO, 0},
+ {TK_OPTION_SYNONYM, "-bd", NULL, NULL,
+ NULL, 0, -1, 0, "-borderwidth", 0},
+ {TK_OPTION_SYNONYM, "-bg", NULL, NULL,
+ NULL, 0, -1, 0, "-background", 0},
+ {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap",
+ DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ tkDefButtonBorderWidth, Tk_Offset(TkButton, borderWidthPtr),
+ Tk_Offset(TkButton, borderWidth), 0, 0, 0},
+ {TK_OPTION_STRING, "-command", "command", "Command",
+ DEF_BUTTON_COMMAND, Tk_Offset(TkButton, commandPtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound",
+ DEF_BUTTON_COMPOUND, -1, Tk_Offset(TkButton, compound), 0,
+ compoundStrings, 0},
+ {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
+ DEF_BUTTON_CURSOR, -1, Tk_Offset(TkButton, cursor),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
+ "DisabledForeground", DEF_BUTTON_DISABLED_FG_COLOR,
+ -1, Tk_Offset(TkButton, disabledFg), TK_OPTION_NULL_OK,
+ (ClientData) DEF_BUTTON_DISABLED_FG_MONO, 0},
+ {TK_OPTION_SYNONYM, "-fg", "foreground", NULL,
+ NULL, 0, -1, 0, "-foreground", 0},
+ {TK_OPTION_FONT, "-font", "font", "Font",
+ DEF_BUTTON_FONT, -1, Tk_Offset(TkButton, tkfont), 0, 0, 0},
+ {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
+ DEF_CHKRAD_FG, -1, Tk_Offset(TkButton, normalFg), 0, 0, 0},
+ {TK_OPTION_STRING, "-height", "height", "Height",
+ DEF_BUTTON_HEIGHT, Tk_Offset(TkButton, heightPtr), -1, 0, 0, 0},
+ {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground",
+ "HighlightBackground", DEF_BUTTON_HIGHLIGHT_BG_COLOR,
+ -1, Tk_Offset(TkButton, highlightBorder), 0,
+ (ClientData) DEF_BUTTON_HIGHLIGHT_BG_MONO, 0},
+ {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
+ DEF_BUTTON_HIGHLIGHT, -1, Tk_Offset(TkButton, highlightColorPtr),
+ 0, 0, 0},
+ {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
+ "HighlightThickness", tkDefButtonHighlightWidth,
+ Tk_Offset(TkButton, highlightWidthPtr),
+ Tk_Offset(TkButton, highlightWidth), 0, 0, 0},
+ {TK_OPTION_STRING, "-image", "image", "Image",
+ DEF_BUTTON_IMAGE, Tk_Offset(TkButton, imagePtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_BOOLEAN, "-indicatoron", "indicatorOn", "IndicatorOn",
+ DEF_BUTTON_INDICATOR, -1, Tk_Offset(TkButton, indicatorOn), 0, 0, 0},
+ {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
+ DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkButton, justify), 0, 0, 0},
+ {TK_OPTION_RELIEF, "-offrelief", "offRelief", "OffRelief",
+ DEF_BUTTON_RELIEF, -1, Tk_Offset(TkButton, offRelief), 0, 0, 0},
+ {TK_OPTION_STRING, "-offvalue", "offValue", "Value",
+ DEF_BUTTON_OFF_VALUE, Tk_Offset(TkButton, offValuePtr), -1, 0, 0, 0},
+ {TK_OPTION_STRING, "-onvalue", "onValue", "Value",
+ DEF_BUTTON_ON_VALUE, Tk_Offset(TkButton, onValuePtr), -1, 0, 0, 0},
+ {TK_OPTION_RELIEF, "-overrelief", "overRelief", "OverRelief",
+ DEF_BUTTON_OVER_RELIEF, -1, Tk_Offset(TkButton, overRelief),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
+ tkDefLabelPadx, Tk_Offset(TkButton, padXPtr),
+ Tk_Offset(TkButton, padX), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
+ tkDefLabelPady, Tk_Offset(TkButton, padYPtr),
+ Tk_Offset(TkButton, padY), 0, 0, 0},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ DEF_LABCHKRAD_RELIEF, -1, Tk_Offset(TkButton, relief), 0, 0, 0},
+ {TK_OPTION_BORDER, "-selectcolor", "selectColor", "Background",
+ DEF_BUTTON_SELECT_COLOR, -1, Tk_Offset(TkButton, selectBorder),
+ TK_OPTION_NULL_OK, DEF_BUTTON_SELECT_MONO, 0},
+ {TK_OPTION_STRING, "-selectimage", "selectImage", "SelectImage",
+ DEF_BUTTON_SELECT_IMAGE, Tk_Offset(TkButton, selectImagePtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-state", "state", "State",
+ DEF_BUTTON_STATE, -1, Tk_Offset(TkButton, state),
+ 0, stateStrings, 0},
+ {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
+ DEF_BUTTON_TAKE_FOCUS, Tk_Offset(TkButton, takeFocusPtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-text", "text", "Text",
+ DEF_BUTTON_TEXT, Tk_Offset(TkButton, textPtr), -1, 0, 0, 0},
+ {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
+ DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarNamePtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-tristateimage", "tristateImage", "TristateImage",
+ DEF_BUTTON_IMAGE, Tk_Offset(TkButton, tristateImagePtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-tristatevalue", "tristateValue", "TristateValue",
+ DEF_BUTTON_TRISTATE_VALUE, Tk_Offset(TkButton, tristateValuePtr), -1, 0, 0, 0},
+ {TK_OPTION_INT, "-underline", "underline", "Underline",
+ DEF_BUTTON_UNDERLINE, -1, Tk_Offset(TkButton, underline), 0, 0, 0},
+ {TK_OPTION_STRING, "-variable", "variable", "Variable",
+ DEF_CHECKBUTTON_VARIABLE, Tk_Offset(TkButton, selVarNamePtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-width", "width", "Width",
+ DEF_BUTTON_WIDTH, Tk_Offset(TkButton, widthPtr), -1, 0, 0, 0},
+ {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",
+ DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr),
+ Tk_Offset(TkButton, wrapLength), 0, 0, 0},
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0}
+};
+
+static const Tk_OptionSpec radiobuttonOptionSpecs[] = {
+ {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",
+ DEF_BUTTON_ACTIVE_BG_COLOR, -1, Tk_Offset(TkButton, activeBorder),
+ 0, DEF_BUTTON_ACTIVE_BG_MONO, 0},
+ {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background",
+ DEF_CHKRAD_ACTIVE_FG_COLOR, -1, Tk_Offset(TkButton, activeFg),
+ TK_OPTION_NULL_OK, DEF_BUTTON_ACTIVE_FG_MONO, 0},
+ {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
+ DEF_BUTTON_ANCHOR, -1, Tk_Offset(TkButton, anchor), 0, 0, 0},
+ {TK_OPTION_BORDER, "-background", "background", "Background",
+ DEF_BUTTON_BG_COLOR, -1, Tk_Offset(TkButton, normalBorder),
+ 0, DEF_BUTTON_BG_MONO, 0},
+ {TK_OPTION_SYNONYM, "-bd", NULL, NULL,
+ NULL, 0, -1, 0, "-borderwidth", 0},
+ {TK_OPTION_SYNONYM, "-bg", NULL, NULL,
+ NULL, 0, -1, 0, "-background", 0},
+ {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap",
+ DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ tkDefButtonBorderWidth, Tk_Offset(TkButton, borderWidthPtr),
+ Tk_Offset(TkButton, borderWidth), 0, 0, 0},
+ {TK_OPTION_STRING, "-command", "command", "Command",
+ DEF_BUTTON_COMMAND, Tk_Offset(TkButton, commandPtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound",
+ DEF_BUTTON_COMPOUND, -1, Tk_Offset(TkButton, compound), 0,
+ compoundStrings, 0},
+ {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
+ DEF_BUTTON_CURSOR, -1, Tk_Offset(TkButton, cursor),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
+ "DisabledForeground", DEF_BUTTON_DISABLED_FG_COLOR,
+ -1, Tk_Offset(TkButton, disabledFg), TK_OPTION_NULL_OK,
+ (ClientData) DEF_BUTTON_DISABLED_FG_MONO, 0},
+ {TK_OPTION_SYNONYM, "-fg", "foreground", NULL,
+ NULL, 0, -1, 0, "-foreground", 0},
+ {TK_OPTION_FONT, "-font", "font", "Font",
+ DEF_BUTTON_FONT, -1, Tk_Offset(TkButton, tkfont), 0, 0, 0},
+ {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
+ DEF_CHKRAD_FG, -1, Tk_Offset(TkButton, normalFg), 0, 0, 0},
+ {TK_OPTION_STRING, "-height", "height", "Height",
+ DEF_BUTTON_HEIGHT, Tk_Offset(TkButton, heightPtr), -1, 0, 0, 0},
+ {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground",
+ "HighlightBackground", DEF_BUTTON_HIGHLIGHT_BG_COLOR,
+ -1, Tk_Offset(TkButton, highlightBorder), 0,
+ (ClientData) DEF_BUTTON_HIGHLIGHT_BG_MONO, 0},
+ {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
+ DEF_BUTTON_HIGHLIGHT, -1, Tk_Offset(TkButton, highlightColorPtr),
+ 0, 0, 0},
+ {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
+ "HighlightThickness", tkDefButtonHighlightWidth,
+ Tk_Offset(TkButton, highlightWidthPtr),
+ Tk_Offset(TkButton, highlightWidth), 0, 0, 0},
+ {TK_OPTION_STRING, "-image", "image", "Image",
+ DEF_BUTTON_IMAGE, Tk_Offset(TkButton, imagePtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_BOOLEAN, "-indicatoron", "indicatorOn", "IndicatorOn",
+ DEF_BUTTON_INDICATOR, -1, Tk_Offset(TkButton, indicatorOn),
+ 0, 0, 0},
+ {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
+ DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkButton, justify), 0, 0, 0},
+ {TK_OPTION_RELIEF, "-offrelief", "offRelief", "OffRelief",
+ DEF_BUTTON_RELIEF, -1, Tk_Offset(TkButton, offRelief), 0, 0, 0},
+ {TK_OPTION_RELIEF, "-overrelief", "overRelief", "OverRelief",
+ DEF_BUTTON_OVER_RELIEF, -1, Tk_Offset(TkButton, overRelief),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
+ tkDefLabelPadx, Tk_Offset(TkButton, padXPtr),
+ Tk_Offset(TkButton, padX), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
+ tkDefLabelPady, Tk_Offset(TkButton, padYPtr),
+ Tk_Offset(TkButton, padY), 0, 0, 0},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ DEF_LABCHKRAD_RELIEF, -1, Tk_Offset(TkButton, relief), 0, 0, 0},
+ {TK_OPTION_BORDER, "-selectcolor", "selectColor", "Background",
+ DEF_BUTTON_SELECT_COLOR, -1, Tk_Offset(TkButton, selectBorder),
+ TK_OPTION_NULL_OK, DEF_BUTTON_SELECT_MONO, 0},
+ {TK_OPTION_STRING, "-selectimage", "selectImage", "SelectImage",
+ DEF_BUTTON_SELECT_IMAGE, Tk_Offset(TkButton, selectImagePtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-state", "state", "State",
+ DEF_BUTTON_STATE, -1, Tk_Offset(TkButton, state),
+ 0, stateStrings, 0},
+ {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
+ DEF_BUTTON_TAKE_FOCUS, Tk_Offset(TkButton, takeFocusPtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-text", "text", "Text",
+ DEF_BUTTON_TEXT, Tk_Offset(TkButton, textPtr), -1, 0, 0, 0},
+ {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
+ DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarNamePtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-tristateimage", "tristateImage", "TristateImage",
+ DEF_BUTTON_IMAGE, Tk_Offset(TkButton, tristateImagePtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-tristatevalue", "tristateValue", "TristateValue",
+ DEF_BUTTON_TRISTATE_VALUE, Tk_Offset(TkButton, tristateValuePtr), -1, 0, 0, 0},
+ {TK_OPTION_INT, "-underline", "underline", "Underline",
+ DEF_BUTTON_UNDERLINE, -1, Tk_Offset(TkButton, underline), 0, 0, 0},
+ {TK_OPTION_STRING, "-value", "value", "Value",
+ DEF_BUTTON_VALUE, Tk_Offset(TkButton, onValuePtr), -1, 0, 0, 0},
+ {TK_OPTION_STRING, "-variable", "variable", "Variable",
+ DEF_RADIOBUTTON_VARIABLE, Tk_Offset(TkButton, selVarNamePtr), -1,
+ 0, 0, 0},
+ {TK_OPTION_STRING, "-width", "width", "Width",
+ DEF_BUTTON_WIDTH, Tk_Offset(TkButton, widthPtr), -1, 0, 0, 0},
+ {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",
+ DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr),
+ Tk_Offset(TkButton, wrapLength), 0, 0, 0},
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0}
+};
+
+/*
+ * The following table maps from one of the type values defined in tkButton.h,
+ * such as TYPE_LABEL, to the option template for that class of widgets.
+ */
+
+static const Tk_OptionSpec *const optionSpecs[] = {
+ labelOptionSpecs,
+ buttonOptionSpecs,
+ checkbuttonOptionSpecs,
+ radiobuttonOptionSpecs
+};
+
+/*
+ * The following tables define the widget commands supported by each of the
+ * classes, and map the indexes into the string tables into a single
+ * enumerated type used to dispatch the widget command.
+ */
+
+static const char *const commandNames[][8] = {
+ {"cget", "configure", NULL},
+ {"cget", "configure", "flash", "invoke", NULL},
+ {"cget", "configure", "deselect", "flash", "invoke", "select",
+ "toggle", NULL},
+ {"cget", "configure", "deselect", "flash", "invoke", "select", NULL}
+};
+enum command {
+ COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DESELECT, COMMAND_FLASH,
+ COMMAND_INVOKE, COMMAND_SELECT, COMMAND_TOGGLE
+};
+static const enum command map[][8] = {
+ {COMMAND_CGET, COMMAND_CONFIGURE},
+ {COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_FLASH, COMMAND_INVOKE},
+ {COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DESELECT, COMMAND_FLASH,
+ COMMAND_INVOKE, COMMAND_SELECT, COMMAND_TOGGLE},
+ {COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DESELECT, COMMAND_FLASH,
+ COMMAND_INVOKE, COMMAND_SELECT}
+};
+
+/*
+ * Forward declarations for functions defined later in this file:
+ */
+
+static void ButtonCmdDeletedProc(ClientData clientData);
+static int ButtonCreate(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[], int type);
+static void ButtonEventProc(ClientData clientData,
+ XEvent *eventPtr);
+static void ButtonImageProc(ClientData clientData,
+ int x, int y, int width, int height,
+ int imgWidth, int imgHeight);
+static void ButtonSelectImageProc(ClientData clientData,
+ int x, int y, int width, int height,
+ int imgWidth, int imgHeight);
+static void ButtonTristateImageProc(ClientData clientData,
+ int x, int y, int width, int height,
+ int imgWidth, int imgHeight);
+static char * ButtonTextVarProc(ClientData clientData,
+ Tcl_Interp *interp, const char *name1,
+ const char *name2, int flags);
+static char * ButtonVarProc(ClientData clientData,
+ Tcl_Interp *interp, const char *name1,
+ const char *name2, int flags);
+static int ButtonWidgetObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int ConfigureButton(Tcl_Interp *interp, TkButton *butPtr,
+ int objc, Tcl_Obj *const objv[]);
+static void DestroyButton(TkButton *butPtr);
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_ButtonCmd, Tk_CheckbuttonCmd, Tk_LabelCmd, Tk_RadiobuttonCmd --
+ *
+ * These functions are invoked to process the "button", "label",
+ * "radiobutton", and "checkbutton" Tcl commands. See the user
+ * documentation for details on what they do.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation. These functions are just wrappers; they
+ * call ButtonCreate to do all of the real work.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_ButtonObjCmd(
+ ClientData clientData, /* Either NULL or pointer to option table. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument values. */
+{
+ return ButtonCreate(clientData, interp, objc, objv, TYPE_BUTTON);
+}
+
+int
+Tk_CheckbuttonObjCmd(
+ ClientData clientData, /* Either NULL or pointer to option table. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument values. */
+{
+ return ButtonCreate(clientData, interp, objc, objv, TYPE_CHECK_BUTTON);
+}
+
+int
+Tk_LabelObjCmd(
+ ClientData clientData, /* Either NULL or pointer to option table. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument values. */
+{
+ return ButtonCreate(clientData, interp, objc, objv, TYPE_LABEL);
+}
+
+int
+Tk_RadiobuttonObjCmd(
+ ClientData clientData, /* Either NULL or pointer to option table. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument values. */
+{
+ return ButtonCreate(clientData, interp, objc, objv, TYPE_RADIO_BUTTON);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ButtonCreate --
+ *
+ * This function does all the real work of implementing the "button",
+ * "label", "radiobutton", and "checkbutton" Tcl commands. See the user
+ * documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+ButtonCreate(
+ ClientData clientData, /* NULL. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[], /* Argument values. */
+ int type) /* Type of button to create: TYPE_LABEL,
+ * TYPE_BUTTON, TYPE_CHECK_BUTTON, or
+ * TYPE_RADIO_BUTTON. */
+{
+ TkButton *butPtr;
+ Tk_OptionTable optionTable;
+ Tk_Window tkwin;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (!tsdPtr->defaultsInitialized) {
+ TkpButtonSetDefaults();
+ tsdPtr->defaultsInitialized = 1;
+ }
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Create the new window.
+ */
+
+ tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),
+ Tcl_GetString(objv[1]), NULL);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Create the option table for this widget class. If it has already been
+ * created, the cached pointer will be returned.
+ */
+
+ optionTable = Tk_CreateOptionTable(interp, optionSpecs[type]);
+
+ Tk_SetClass(tkwin, classNames[type]);
+ butPtr = TkpCreateButton(tkwin);
+
+ Tk_SetClassProcs(tkwin, &tkpButtonProcs, butPtr);
+
+ /*
+ * Initialize the data structure for the button.
+ */
+
+ butPtr->tkwin = tkwin;
+ butPtr->display = Tk_Display(tkwin);
+ butPtr->interp = interp;
+ butPtr->widgetCmd = Tcl_CreateObjCommand(interp, Tk_PathName(tkwin),
+ ButtonWidgetObjCmd, butPtr, ButtonCmdDeletedProc);
+ butPtr->type = type;
+ butPtr->optionTable = optionTable;
+ butPtr->textPtr = NULL;
+ butPtr->underline = -1;
+ butPtr->textVarNamePtr = NULL;
+ butPtr->bitmap = None;
+ butPtr->imagePtr = NULL;
+ butPtr->image = NULL;
+ butPtr->selectImagePtr = NULL;
+ butPtr->selectImage = NULL;
+ butPtr->tristateImagePtr = NULL;
+ butPtr->tristateImage = NULL;
+ butPtr->state = STATE_NORMAL;
+ butPtr->normalBorder = NULL;
+ butPtr->activeBorder = NULL;
+ butPtr->borderWidthPtr = NULL;
+ butPtr->borderWidth = 0;
+ butPtr->relief = TK_RELIEF_FLAT;
+ butPtr->highlightWidthPtr = NULL;
+ butPtr->highlightWidth = 0;
+ butPtr->highlightBorder = NULL;
+ butPtr->highlightColorPtr = NULL;
+ butPtr->inset = 0;
+ butPtr->tkfont = NULL;
+ butPtr->normalFg = NULL;
+ butPtr->activeFg = NULL;
+ butPtr->disabledFg = NULL;
+ butPtr->normalTextGC = NULL;
+ butPtr->activeTextGC = NULL;
+ butPtr->disabledGC = NULL;
+ butPtr->stippleGC = NULL;
+ butPtr->gray = None;
+ butPtr->copyGC = NULL;
+ butPtr->widthPtr = NULL;
+ butPtr->width = 0;
+ butPtr->heightPtr = NULL;
+ butPtr->height = 0;
+ butPtr->wrapLengthPtr = NULL;
+ butPtr->wrapLength = 0;
+ butPtr->padXPtr = NULL;
+ butPtr->padX = 0;
+ butPtr->padYPtr = NULL;
+ butPtr->padY = 0;
+ butPtr->anchor = TK_ANCHOR_CENTER;
+ butPtr->justify = TK_JUSTIFY_CENTER;
+ butPtr->indicatorOn = 0;
+ butPtr->selectBorder = NULL;
+ butPtr->textWidth = 0;
+ butPtr->textHeight = 0;
+ butPtr->textLayout = NULL;
+ butPtr->indicatorSpace = 0;
+ butPtr->indicatorDiameter = 0;
+ butPtr->defaultState = DEFAULT_DISABLED;
+ butPtr->selVarNamePtr = NULL;
+ butPtr->onValuePtr = NULL;
+ butPtr->offValuePtr = NULL;
+ butPtr->tristateValuePtr = NULL;
+ butPtr->cursor = NULL;
+ butPtr->takeFocusPtr = NULL;
+ butPtr->commandPtr = NULL;
+ butPtr->flags = 0;
+
+ Tk_CreateEventHandler(butPtr->tkwin,
+ ExposureMask|StructureNotifyMask|FocusChangeMask,
+ ButtonEventProc, butPtr);
+
+ if (Tk_InitOptions(interp, (char *) butPtr, optionTable, tkwin)
+ != TCL_OK) {
+ Tk_DestroyWindow(butPtr->tkwin);
+ return TCL_ERROR;
+ }
+ if (ConfigureButton(interp, butPtr, objc - 2, objv + 2) != TCL_OK) {
+ Tk_DestroyWindow(butPtr->tkwin);
+ return TCL_ERROR;
+ }
+
+ Tcl_SetObjResult(interp, TkNewWindowObj(butPtr->tkwin));
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ButtonWidgetCmd --
+ *
+ * This function is invoked to process the Tcl command that corresponds
+ * to a widget managed by this module. See the user documentation for
+ * details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+ButtonWidgetObjCmd(
+ ClientData clientData, /* Information about button widget. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument values. */
+{
+ TkButton *butPtr = clientData;
+ int index;
+ int result;
+ Tcl_Obj *objPtr;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ result = Tcl_GetIndexFromObjStruct(interp, objv[1], commandNames[butPtr->type],
+ sizeof(char *), "option", 0, &index);
+ if (result != TCL_OK) {
+ return result;
+ }
+ Tcl_Preserve(butPtr);
+
+ switch (map[butPtr->type][index]) {
+ case COMMAND_CGET:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "cget option");
+ goto error;
+ }
+ objPtr = Tk_GetOptionValue(interp, (char *) butPtr,
+ butPtr->optionTable, objv[2], butPtr->tkwin);
+ if (objPtr == NULL) {
+ goto error;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ break;
+
+ case COMMAND_CONFIGURE:
+ if (objc <= 3) {
+ objPtr = Tk_GetOptionInfo(interp, (char *) butPtr,
+ butPtr->optionTable, (objc == 3) ? objv[2] : NULL,
+ butPtr->tkwin);
+ if (objPtr == NULL) {
+ goto error;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ } else {
+ result = ConfigureButton(interp, butPtr, objc-2, objv+2);
+ }
+ break;
+
+ case COMMAND_DESELECT:
+ if (objc > 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "deselect");
+ goto error;
+ }
+ if (butPtr->type == TYPE_CHECK_BUTTON) {
+ if (Tcl_ObjSetVar2(interp, butPtr->selVarNamePtr, NULL,
+ butPtr->offValuePtr, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
+ == NULL) {
+ goto error;
+ }
+ } else if (butPtr->flags & SELECTED) {
+ if (Tcl_ObjSetVar2(interp, butPtr->selVarNamePtr, NULL,
+ Tcl_NewObj(), TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL){
+ goto error;
+ }
+ }
+ break;
+
+ case COMMAND_FLASH:
+ if (objc > 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "flash");
+ goto error;
+ }
+ if (butPtr->state != STATE_DISABLED) {
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (butPtr->state == STATE_NORMAL) {
+ butPtr->state = STATE_ACTIVE;
+ Tk_SetBackgroundFromBorder(butPtr->tkwin,
+ butPtr->activeBorder);
+ } else {
+ butPtr->state = STATE_NORMAL;
+ Tk_SetBackgroundFromBorder(butPtr->tkwin,
+ butPtr->normalBorder);
+ }
+ TkpDisplayButton(butPtr);
+
+ /*
+ * Special note: must cancel any existing idle handler for
+ * TkpDisplayButton; it's no longer needed, and
+ * TkpDisplayButton cleared the REDRAW_PENDING flag.
+ */
+
+ Tcl_CancelIdleCall(TkpDisplayButton, butPtr);
+ XFlush(butPtr->display);
+ #ifndef MAC_OSX_TK
+ /*
+ * On the mac you can not sleep in a display proc, and the
+ * flash command doesn't do anything anyway.
+ */
+ Tcl_Sleep(50);
+ #endif
+ }
+ }
+ break;
+
+ case COMMAND_INVOKE:
+ if (objc > 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "invoke");
+ goto error;
+ }
+ if (butPtr->state != STATE_DISABLED) {
+ result = TkInvokeButton(butPtr);
+ }
+ break;
+
+ case COMMAND_SELECT:
+ if (objc > 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "select");
+ goto error;
+ }
+ if (Tcl_ObjSetVar2(interp, butPtr->selVarNamePtr, NULL,
+ butPtr->onValuePtr, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
+ == NULL) {
+ goto error;
+ }
+ break;
+
+ case COMMAND_TOGGLE:
+ if (objc > 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "toggle");
+ goto error;
+ }
+ if (Tcl_ObjSetVar2(interp, butPtr->selVarNamePtr, NULL,
+ (butPtr->flags & SELECTED) ? butPtr->offValuePtr
+ : butPtr->onValuePtr, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
+ == NULL) {
+ goto error;
+ }
+ break;
+ }
+ Tcl_Release(butPtr);
+ return result;
+
+ error:
+ Tcl_Release(butPtr);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyButton --
+ *
+ * This function is invoked by ButtonEventProc to free all the resources
+ * of a button and clean up its state.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Everything associated with the widget is freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DestroyButton(
+ TkButton *butPtr) /* Info about button widget. */
+{
+ butPtr->flags |= BUTTON_DELETED;
+ TkpDestroyButton(butPtr);
+
+ if (butPtr->flags & REDRAW_PENDING) {
+ Tcl_CancelIdleCall(TkpDisplayButton, butPtr);
+ }
+
+ /*
+ * Free up all the stuff that requires special handling, then let
+ * Tk_FreeOptions handle all the standard option-related stuff.
+ */
+
+ Tcl_DeleteCommandFromToken(butPtr->interp, butPtr->widgetCmd);
+ if (butPtr->textVarNamePtr != NULL) {
+ Tcl_UntraceVar2(butPtr->interp, Tcl_GetString(butPtr->textVarNamePtr),
+ NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ ButtonTextVarProc, butPtr);
+ }
+ if (butPtr->image != NULL) {
+ Tk_FreeImage(butPtr->image);
+ }
+ if (butPtr->selectImage != NULL) {
+ Tk_FreeImage(butPtr->selectImage);
+ }
+ if (butPtr->tristateImage != NULL) {
+ Tk_FreeImage(butPtr->tristateImage);
+ }
+ if (butPtr->normalTextGC != NULL) {
+ Tk_FreeGC(butPtr->display, butPtr->normalTextGC);
+ }
+ if (butPtr->activeTextGC != NULL) {
+ Tk_FreeGC(butPtr->display, butPtr->activeTextGC);
+ }
+ if (butPtr->disabledGC != NULL) {
+ Tk_FreeGC(butPtr->display, butPtr->disabledGC);
+ }
+ if (butPtr->stippleGC != NULL) {
+ Tk_FreeGC(butPtr->display, butPtr->stippleGC);
+ }
+ if (butPtr->gray != None) {
+ Tk_FreeBitmap(butPtr->display, butPtr->gray);
+ }
+ if (butPtr->copyGC != NULL) {
+ Tk_FreeGC(butPtr->display, butPtr->copyGC);
+ }
+ if (butPtr->textLayout != NULL) {
+ Tk_FreeTextLayout(butPtr->textLayout);
+ }
+ if (butPtr->selVarNamePtr != NULL) {
+ Tcl_UntraceVar2(butPtr->interp, Tcl_GetString(butPtr->selVarNamePtr),
+ NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ ButtonVarProc, butPtr);
+ }
+ Tk_FreeConfigOptions((char *) butPtr, butPtr->optionTable,
+ butPtr->tkwin);
+ butPtr->tkwin = NULL;
+ Tcl_EventuallyFree(butPtr, TCL_DYNAMIC);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConfigureButton --
+ *
+ * This function is called to process an objc/objv list to set
+ * configuration options for a button widget.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If TCL_ERROR is returned,
+ * then an error message is left in interp's result.
+ *
+ * Side effects:
+ * Configuration information, such as text string, colors, font, etc. get
+ * set for butPtr; old resources get freed, if there were any. The button
+ * is redisplayed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ConfigureButton(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ register TkButton *butPtr, /* Information about widget; may or may
+ * not already have values for some fields. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument values. */
+{
+ Tk_SavedOptions savedOptions;
+ Tcl_Obj *errorResult = NULL;
+ int error, haveImage;
+ Tk_Image image;
+
+ /*
+ * Eliminate any existing trace on variables monitored by the button.
+ */
+
+ if (butPtr->textVarNamePtr != NULL) {
+ Tcl_UntraceVar2(interp, Tcl_GetString(butPtr->textVarNamePtr),
+ NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ ButtonTextVarProc, butPtr);
+ }
+ if (butPtr->selVarNamePtr != NULL) {
+ Tcl_UntraceVar2(interp, Tcl_GetString(butPtr->selVarNamePtr),
+ NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ ButtonVarProc, butPtr);
+ }
+
+ /*
+ * The following loop is potentially executed twice. During the first pass
+ * configuration options get set to their new values. If there is an error
+ * in this pass, we execute a second pass to restore all the options to
+ * their previous values.
+ */
+
+ for (error = 0; error <= 1; error++) {
+ if (!error) {
+ /*
+ * First pass: set options to new values.
+ */
+
+ if (Tk_SetOptions(interp, (char *) butPtr,
+ butPtr->optionTable, objc, objv,
+ butPtr->tkwin, &savedOptions, NULL) != TCL_OK) {
+ continue;
+ }
+ } else {
+ /*
+ * Second pass: restore options to old values.
+ */
+
+ errorResult = Tcl_GetObjResult(interp);
+ Tcl_IncrRefCount(errorResult);
+ Tk_RestoreSavedOptions(&savedOptions);
+ }
+
+ if ((butPtr->flags & BUTTON_DELETED)) {
+ /*
+ * Somehow button was deleted - just abort now. [Bug #824479]
+ */
+ return TCL_ERROR;
+ }
+
+ /*
+ * A few options need special processing, such as setting the
+ * background from a 3-D border, or filling in complicated defaults
+ * that couldn't be specified to Tk_SetOptions.
+ */
+
+ if ((butPtr->state == STATE_ACTIVE)
+ && !Tk_StrictMotif(butPtr->tkwin)) {
+ Tk_SetBackgroundFromBorder(butPtr->tkwin, butPtr->activeBorder);
+ } else {
+ Tk_SetBackgroundFromBorder(butPtr->tkwin, butPtr->normalBorder);
+ }
+ if (butPtr->borderWidth < 0) {
+ butPtr->borderWidth = 0;
+ }
+ if (butPtr->highlightWidth < 0) {
+ butPtr->highlightWidth = 0;
+ }
+ if (butPtr->padX < 0) {
+ butPtr->padX = 0;
+ }
+ if (butPtr->padY < 0) {
+ butPtr->padY = 0;
+ }
+
+ if (butPtr->type >= TYPE_CHECK_BUTTON) {
+ Tcl_Obj *valuePtr, *namePtr;
+
+ if (butPtr->selVarNamePtr == NULL) {
+ butPtr->selVarNamePtr = Tcl_NewStringObj(
+ Tk_Name(butPtr->tkwin), -1);
+ Tcl_IncrRefCount(butPtr->selVarNamePtr);
+ }
+ namePtr = butPtr->selVarNamePtr;
+
+ /*
+ * Select the button if the associated variable has the
+ * appropriate value, initialize the variable if it doesn't exist,
+ * then set a trace on the variable to monitor future changes to
+ * its value.
+ */
+
+ valuePtr = Tcl_ObjGetVar2(interp, namePtr, NULL, TCL_GLOBAL_ONLY);
+ butPtr->flags &= ~SELECTED;
+ butPtr->flags &= ~TRISTATED;
+ if (valuePtr != NULL) {
+ const char *value = Tcl_GetString(valuePtr);
+ if (strcmp(value, Tcl_GetString(butPtr->onValuePtr)) == 0) {
+ butPtr->flags |= SELECTED;
+ } else if (strcmp(value,
+ Tcl_GetString(butPtr->tristateValuePtr)) == 0) {
+ butPtr->flags |= TRISTATED;
+
+ /*
+ * For checkbuttons if the tristate value is the
+ * same as the offvalue then prefer off to tristate
+ */
+
+ if (butPtr->offValuePtr
+ && strcmp(value,
+ Tcl_GetString(butPtr->offValuePtr)) == 0) {
+ butPtr->flags &= ~TRISTATED;
+ }
+ }
+ } else {
+ if (Tcl_ObjSetVar2(interp, namePtr, NULL,
+ (butPtr->type == TYPE_CHECK_BUTTON)
+ ? butPtr->offValuePtr : Tcl_NewObj(),
+ TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
+ == NULL) {
+ continue;
+ }
+
+ /*
+ * If a radiobutton has the empty string as value it should be
+ * selected.
+ */
+
+ if ((butPtr->type == TYPE_RADIO_BUTTON) &&
+ (*Tcl_GetString(butPtr->onValuePtr) == '\0')) {
+ butPtr->flags |= SELECTED;
+ }
+ }
+ }
+
+ /*
+ * Get the images for the widget, if there are any. Allocate the new
+ * images before freeing the old ones, so that the reference counts
+ * don't go to zero and cause image data to be discarded.
+ */
+
+ if (butPtr->imagePtr != NULL) {
+ image = Tk_GetImage(butPtr->interp, butPtr->tkwin,
+ Tcl_GetString(butPtr->imagePtr), ButtonImageProc,
+ butPtr);
+ if (image == NULL) {
+ continue;
+ }
+ } else {
+ image = NULL;
+ }
+ if (butPtr->image != NULL) {
+ Tk_FreeImage(butPtr->image);
+ }
+ butPtr->image = image;
+ if (butPtr->selectImagePtr != NULL) {
+ image = Tk_GetImage(butPtr->interp, butPtr->tkwin,
+ Tcl_GetString(butPtr->selectImagePtr),
+ ButtonSelectImageProc, butPtr);
+ if (image == NULL) {
+ continue;
+ }
+ } else {
+ image = NULL;
+ }
+ if (butPtr->selectImage != NULL) {
+ Tk_FreeImage(butPtr->selectImage);
+ }
+ butPtr->selectImage = image;
+ if (butPtr->tristateImagePtr != NULL) {
+ image = Tk_GetImage(butPtr->interp, butPtr->tkwin,
+ Tcl_GetString(butPtr->tristateImagePtr),
+ ButtonTristateImageProc, butPtr);
+ if (image == NULL) {
+ continue;
+ }
+ } else {
+ image = NULL;
+ }
+ if (butPtr->tristateImage != NULL) {
+ Tk_FreeImage(butPtr->tristateImage);
+ }
+ butPtr->tristateImage = image;
+
+ haveImage = 0;
+ if (butPtr->imagePtr != NULL || butPtr->bitmap != None) {
+ haveImage = 1;
+ }
+ if ((!haveImage || butPtr->compound != COMPOUND_NONE)
+ && (butPtr->textVarNamePtr != NULL)) {
+ /*
+ * The button must display the value of a variable: set up a trace
+ * on the variable's value, create the variable if it doesn't
+ * exist, and fetch its current value.
+ */
+
+ Tcl_Obj *valuePtr, *namePtr;
+
+ namePtr = butPtr->textVarNamePtr;
+ valuePtr = Tcl_ObjGetVar2(interp, namePtr, NULL, TCL_GLOBAL_ONLY);
+ if (valuePtr == NULL) {
+ if (Tcl_ObjSetVar2(interp, namePtr, NULL, butPtr->textPtr,
+ TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
+ == NULL) {
+ continue;
+ }
+ } else {
+ if (butPtr->textPtr != NULL) {
+ Tcl_DecrRefCount(butPtr->textPtr);
+ }
+ butPtr->textPtr = valuePtr;
+ Tcl_IncrRefCount(butPtr->textPtr);
+ }
+ }
+
+ if ((butPtr->bitmap != None) || (butPtr->imagePtr != NULL)) {
+ /*
+ * The button must display the contents of an image or bitmap.
+ */
+
+ if (Tk_GetPixelsFromObj(interp, butPtr->tkwin, butPtr->widthPtr,
+ &butPtr->width) != TCL_OK) {
+ widthError:
+ Tcl_AddErrorInfo(interp, "\n (processing -width option)");
+ continue;
+ }
+ if (Tk_GetPixelsFromObj(interp, butPtr->tkwin, butPtr->heightPtr,
+ &butPtr->height) != TCL_OK) {
+ heightError:
+ Tcl_AddErrorInfo(interp, "\n (processing -height option)");
+ continue;
+ }
+ } else {
+ /*
+ * The button displays an ordinary text string.
+ */
+
+ if (Tcl_GetIntFromObj(interp, butPtr->widthPtr, &butPtr->width)
+ != TCL_OK) {
+ goto widthError;
+ }
+ if (Tcl_GetIntFromObj(interp, butPtr->heightPtr, &butPtr->height)
+ != TCL_OK) {
+ goto heightError;
+ }
+ }
+ break;
+ }
+ if (!error) {
+ Tk_FreeSavedOptions(&savedOptions);
+ }
+
+ /*
+ * Reestablish the variable traces, if they're needed.
+ */
+
+ if (butPtr->textVarNamePtr != NULL) {
+ Tcl_TraceVar2(interp, Tcl_GetString(butPtr->textVarNamePtr),
+ NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ ButtonTextVarProc, butPtr);
+ }
+ if (butPtr->selVarNamePtr != NULL) {
+ Tcl_TraceVar2(interp, Tcl_GetString(butPtr->selVarNamePtr),
+ NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ ButtonVarProc, butPtr);
+ }
+
+ TkButtonWorldChanged(butPtr);
+ if (error) {
+ Tcl_SetObjResult(interp, errorResult);
+ Tcl_DecrRefCount(errorResult);
+ return TCL_ERROR;
+ } else {
+ return TCL_OK;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkButtonWorldChanged --
+ *
+ * This function is called when the world has changed in some way and the
+ * widget needs to recompute all its graphics contexts and determine its
+ * new geometry.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Button will be relayed out and redisplayed.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+TkButtonWorldChanged(
+ ClientData instanceData) /* Information about widget. */
+{
+ XGCValues gcValues;
+ GC newGC;
+ unsigned long mask;
+ TkButton *butPtr = instanceData;
+
+ /*
+ * Recompute GCs.
+ */
+
+ gcValues.font = Tk_FontId(butPtr->tkfont);
+ gcValues.foreground = butPtr->normalFg->pixel;
+ gcValues.background = Tk_3DBorderColor(butPtr->normalBorder)->pixel;
+
+ /*
+ * Note: GraphicsExpose events are disabled in normalTextGC because it's
+ * used to copy stuff from an off-screen pixmap onto the screen (we know
+ * that there's no problem with obscured areas).
+ */
+
+ gcValues.graphics_exposures = False;
+ mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
+ newGC = Tk_GetGC(butPtr->tkwin, mask, &gcValues);
+ if (butPtr->normalTextGC != NULL) {
+ Tk_FreeGC(butPtr->display, butPtr->normalTextGC);
+ }
+ butPtr->normalTextGC = newGC;
+
+ if (butPtr->activeFg != NULL) {
+ gcValues.foreground = butPtr->activeFg->pixel;
+ gcValues.background = Tk_3DBorderColor(butPtr->activeBorder)->pixel;
+ mask = GCForeground | GCBackground | GCFont;
+ newGC = Tk_GetGC(butPtr->tkwin, mask, &gcValues);
+ if (butPtr->activeTextGC != NULL) {
+ Tk_FreeGC(butPtr->display, butPtr->activeTextGC);
+ }
+ butPtr->activeTextGC = newGC;
+ }
+
+ gcValues.background = Tk_3DBorderColor(butPtr->normalBorder)->pixel;
+
+ /*
+ * Create the GC that can be used for stippling
+ */
+
+ if (butPtr->stippleGC == NULL) {
+ gcValues.foreground = gcValues.background;
+ mask = GCForeground;
+ if (butPtr->gray == None) {
+ butPtr->gray = Tk_GetBitmap(NULL, butPtr->tkwin, "gray50");
+ }
+ if (butPtr->gray != None) {
+ gcValues.fill_style = FillStippled;
+ gcValues.stipple = butPtr->gray;
+ mask |= GCFillStyle | GCStipple;
+ }
+ butPtr->stippleGC = Tk_GetGC(butPtr->tkwin, mask, &gcValues);
+ }
+
+ /*
+ * Allocate the disabled graphics context, for drawing text in its
+ * disabled state.
+ */
+
+ mask = GCForeground | GCBackground | GCFont;
+ if (butPtr->disabledFg != NULL) {
+ gcValues.foreground = butPtr->disabledFg->pixel;
+ } else {
+ gcValues.foreground = gcValues.background;
+ }
+ newGC = Tk_GetGC(butPtr->tkwin, mask, &gcValues);
+ if (butPtr->disabledGC != NULL) {
+ Tk_FreeGC(butPtr->display, butPtr->disabledGC);
+ }
+ butPtr->disabledGC = newGC;
+
+ if (butPtr->copyGC == NULL) {
+ butPtr->copyGC = Tk_GetGC(butPtr->tkwin, 0, &gcValues);
+ }
+
+ TkpComputeButtonGeometry(butPtr);
+
+ /*
+ * Lastly, arrange for the button to be redisplayed.
+ */
+
+ if (Tk_IsMapped(butPtr->tkwin) && !(butPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(TkpDisplayButton, butPtr);
+ butPtr->flags |= REDRAW_PENDING;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ButtonEventProc --
+ *
+ * This function is invoked by the Tk dispatcher for various events on
+ * buttons.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * When the window gets deleted, internal structures get cleaned up. When
+ * it gets exposed, it is redisplayed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ButtonEventProc(
+ ClientData clientData, /* Information about window. */
+ XEvent *eventPtr) /* Information about event. */
+{
+ TkButton *butPtr = clientData;
+ if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {
+ goto redraw;
+ } else if (eventPtr->type == ConfigureNotify) {
+ /*
+ * Must redraw after size changes, since layout could have changed and
+ * borders will need to be redrawn.
+ */
+
+ goto redraw;
+ } else if (eventPtr->type == DestroyNotify) {
+ DestroyButton(butPtr);
+ } else if (eventPtr->type == FocusIn) {
+ if (eventPtr->xfocus.detail != NotifyInferior) {
+ butPtr->flags |= GOT_FOCUS;
+ if (butPtr->highlightWidth > 0) {
+ goto redraw;
+ }
+ }
+ } else if (eventPtr->type == FocusOut) {
+ if (eventPtr->xfocus.detail != NotifyInferior) {
+ butPtr->flags &= ~GOT_FOCUS;
+ if (butPtr->highlightWidth > 0) {
+ goto redraw;
+ }
+ }
+ }
+ return;
+
+ redraw:
+ if ((butPtr->tkwin != NULL) && !(butPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(TkpDisplayButton, butPtr);
+ butPtr->flags |= REDRAW_PENDING;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ButtonCmdDeletedProc --
+ *
+ * This function is invoked when a widget command is deleted. If the
+ * widget isn't already in the process of being destroyed, this command
+ * destroys it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The widget is destroyed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ButtonCmdDeletedProc(
+ ClientData clientData) /* Pointer to widget record for widget. */
+{
+ TkButton *butPtr = clientData;
+
+ /*
+ * This function could be invoked either because the window was destroyed
+ * and the command was then deleted or because the command was deleted,
+ * and then this function destroys the widget. The BUTTON_DELETED flag
+ * distinguishes these cases.
+ */
+
+ if (!(butPtr->flags & BUTTON_DELETED)) {
+ Tk_DestroyWindow(butPtr->tkwin);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkInvokeButton --
+ *
+ * This function is called to carry out the actions associated with a
+ * button, such as invoking a Tcl command or setting a variable. This
+ * function is invoked, for example, when the button is invoked via the
+ * mouse.
+ *
+ * Results:
+ * A standard Tcl return value. Information is also left in the interp's
+ * result.
+ *
+ * Side effects:
+ * Depends on the button and its associated command.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkInvokeButton(
+ TkButton *butPtr) /* Information about button. */
+{
+ Tcl_Obj *namePtr = butPtr->selVarNamePtr;
+
+ if (butPtr->type == TYPE_CHECK_BUTTON) {
+ if (butPtr->flags & SELECTED) {
+ if (Tcl_ObjSetVar2(butPtr->interp, namePtr, NULL,
+ butPtr->offValuePtr, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
+ == NULL) {
+ return TCL_ERROR;
+ }
+ } else {
+ if (Tcl_ObjSetVar2(butPtr->interp, namePtr, NULL,
+ butPtr->onValuePtr, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
+ == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ } else if (butPtr->type == TYPE_RADIO_BUTTON) {
+ if (Tcl_ObjSetVar2(butPtr->interp, namePtr, NULL, butPtr->onValuePtr,
+ TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
+ == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ if ((butPtr->type != TYPE_LABEL) && (butPtr->commandPtr != NULL)) {
+ return Tcl_EvalObjEx(butPtr->interp, butPtr->commandPtr,
+ TCL_EVAL_GLOBAL);
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ButtonVarProc --
+ *
+ * This function is invoked when someone changes the state variable
+ * associated with a radio button. Depending on the new value of the
+ * button's variable, the button may be selected or deselected.
+ *
+ * Results:
+ * NULL is always returned.
+ *
+ * Side effects:
+ * The button may become selected or deselected.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static char *
+ButtonVarProc(
+ ClientData clientData, /* Information about button. */
+ Tcl_Interp *interp, /* Interpreter containing variable. */
+ const char *name1, /* Name of variable. */
+ const char *name2, /* Second part of variable name. */
+ int flags) /* Information about what happened. */
+{
+ register TkButton *butPtr = clientData;
+ const char *value;
+ Tcl_Obj *valuePtr;
+
+ /*
+ * If the variable is being unset, then just re-establish the trace unless
+ * the whole interpreter is going away.
+ */
+
+ if (flags & TCL_TRACE_UNSETS) {
+ butPtr->flags &= ~(SELECTED | TRISTATED);
+ if (!Tcl_InterpDeleted(interp)) {
+ ClientData probe = NULL;
+
+ do {
+ probe = Tcl_VarTraceInfo(interp,
+ Tcl_GetString(butPtr->selVarNamePtr),
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ ButtonVarProc, probe);
+ if (probe == (ClientData)butPtr) {
+ break;
+ }
+ } while (probe);
+ if (probe) {
+ /*
+ * We were able to fetch the unset trace for our
+ * selVarNamePtr, which means it is not unset and not
+ * the cause of this unset trace. Instead some outdated
+ * former variable must be, and we should ignore it.
+ */
+ goto redisplay;
+ }
+ Tcl_TraceVar2(interp, Tcl_GetString(butPtr->selVarNamePtr),
+ NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ ButtonVarProc, clientData);
+ }
+ goto redisplay;
+ }
+
+ /*
+ * Use the value of the variable to update the selected status of the
+ * button.
+ */
+
+ valuePtr = Tcl_ObjGetVar2(interp, butPtr->selVarNamePtr, NULL,
+ TCL_GLOBAL_ONLY);
+ if (valuePtr == NULL) {
+ value = Tcl_GetString(butPtr->tristateValuePtr);
+ } else {
+ value = Tcl_GetString(valuePtr);
+ }
+ if (strcmp(value, Tcl_GetString(butPtr->onValuePtr)) == 0) {
+ if (butPtr->flags & SELECTED) {
+ return NULL;
+ }
+ butPtr->flags |= SELECTED;
+ butPtr->flags &= ~TRISTATED;
+ } else if (butPtr->offValuePtr
+ && strcmp(value, Tcl_GetString(butPtr->offValuePtr)) == 0) {
+ if (!(butPtr->flags & (SELECTED | TRISTATED))) {
+ return NULL;
+ }
+ butPtr->flags &= ~(SELECTED | TRISTATED);
+ } else if (strcmp(value, Tcl_GetString(butPtr->tristateValuePtr)) == 0) {
+ if (butPtr->flags & TRISTATED) {
+ return NULL;
+ }
+ butPtr->flags |= TRISTATED;
+ butPtr->flags &= ~SELECTED;
+ } else if (butPtr->flags & (SELECTED | TRISTATED)) {
+ butPtr->flags &= ~(SELECTED | TRISTATED);
+ } else {
+ return NULL;
+ }
+
+ redisplay:
+ if ((butPtr->tkwin != NULL) && Tk_IsMapped(butPtr->tkwin)
+ && !(butPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(TkpDisplayButton, butPtr);
+ butPtr->flags |= REDRAW_PENDING;
+ }
+ return NULL;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ButtonTextVarProc --
+ *
+ * This function is invoked when someone changes the variable whose
+ * contents are to be displayed in a button.
+ *
+ * Results:
+ * NULL is always returned.
+ *
+ * Side effects:
+ * The text displayed in the button will change to match the variable.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static char *
+ButtonTextVarProc(
+ ClientData clientData, /* Information about button. */
+ Tcl_Interp *interp, /* Interpreter containing variable. */
+ const char *name1, /* Not used. */
+ const char *name2, /* Not used. */
+ int flags) /* Information about what happened. */
+{
+ TkButton *butPtr = clientData;
+ Tcl_Obj *valuePtr;
+
+ if (butPtr->flags & BUTTON_DELETED) {
+ return NULL;
+ }
+
+ /*
+ * If the variable is unset, then immediately recreate it unless the whole
+ * interpreter is going away.
+ */
+
+ if (flags & TCL_TRACE_UNSETS) {
+ if (!Tcl_InterpDeleted(interp) && butPtr->textVarNamePtr != NULL) {
+
+ /*
+ * An unset trace on some variable brought us here, but is it
+ * the variable we have stored in butPtr->textVarNamePtr ?
+ */
+
+ ClientData probe = NULL;
+
+ do {
+ probe = Tcl_VarTraceInfo(interp,
+ Tcl_GetString(butPtr->textVarNamePtr),
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ ButtonTextVarProc, probe);
+ if (probe == (ClientData)butPtr) {
+ break;
+ }
+ } while (probe);
+ if (probe) {
+ /*
+ * We were able to fetch the unset trace for our
+ * textVarNamePtr, which means it is not unset and not
+ * the cause of this unset trace. Instead some outdated
+ * former textvariable must be, and we should ignore it.
+ */
+ return NULL;
+ }
+
+ Tcl_ObjSetVar2(interp, butPtr->textVarNamePtr, NULL,
+ butPtr->textPtr, TCL_GLOBAL_ONLY);
+ Tcl_TraceVar2(interp, Tcl_GetString(butPtr->textVarNamePtr),
+ NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ ButtonTextVarProc, clientData);
+ }
+ return NULL;
+ }
+
+ valuePtr = Tcl_ObjGetVar2(interp, butPtr->textVarNamePtr, NULL,
+ TCL_GLOBAL_ONLY);
+ if (valuePtr == NULL) {
+ valuePtr = Tcl_NewObj();
+ }
+ Tcl_DecrRefCount(butPtr->textPtr);
+ butPtr->textPtr = valuePtr;
+ Tcl_IncrRefCount(butPtr->textPtr);
+ TkpComputeButtonGeometry(butPtr);
+
+ if ((butPtr->tkwin != NULL) && Tk_IsMapped(butPtr->tkwin)
+ && !(butPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(TkpDisplayButton, butPtr);
+ butPtr->flags |= REDRAW_PENDING;
+ }
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ButtonImageProc --
+ *
+ * This function is invoked by the image code whenever the manager for an
+ * image does something that affects the size or contents of an image
+ * displayed in a button.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Arranges for the button to get redisplayed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ButtonImageProc(
+ ClientData clientData, /* Pointer to widget record. */
+ int x, int y, /* Upper left pixel (within image) that must
+ * be redisplayed. */
+ int width, int height, /* Dimensions of area to redisplay (might be
+ * <= 0). */
+ int imgWidth, int imgHeight)/* New dimensions of image. */
+{
+ register TkButton *butPtr = clientData;
+
+ if (butPtr->tkwin != NULL) {
+ TkpComputeButtonGeometry(butPtr);
+ if (Tk_IsMapped(butPtr->tkwin) && !(butPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(TkpDisplayButton, butPtr);
+ butPtr->flags |= REDRAW_PENDING;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ButtonSelectImageProc --
+ *
+ * This function is invoked by the image code whenever the manager for an
+ * image does something that affects the size or contents of the image
+ * displayed in a button when it is selected.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * May arrange for the button to get redisplayed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ButtonSelectImageProc(
+ ClientData clientData, /* Pointer to widget record. */
+ int x, int y, /* Upper left pixel (within image) that must
+ * be redisplayed. */
+ int width, int height, /* Dimensions of area to redisplay (might be
+ * <= 0). */
+ int imgWidth, int imgHeight)/* New dimensions of image. */
+{
+ register TkButton *butPtr = clientData;
+
+#ifdef MAC_OSX_TK
+ if (butPtr->tkwin != NULL) {
+ TkpComputeButtonGeometry(butPtr);
+ }
+#else
+ /*
+ * Don't recompute geometry: it's controlled by the primary image.
+ */
+#endif
+
+ if ((butPtr->flags & SELECTED) && (butPtr->tkwin != NULL)
+ && Tk_IsMapped(butPtr->tkwin)
+ && !(butPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(TkpDisplayButton, butPtr);
+ butPtr->flags |= REDRAW_PENDING;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ButtonTristateImageProc --
+ *
+ * This function is invoked by the image code whenever the manager for an
+ * image does something that affects the size or contents of the image
+ * displayed in a button when it is selected.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * May arrange for the button to get redisplayed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ButtonTristateImageProc(
+ ClientData clientData, /* Pointer to widget record. */
+ int x, int y, /* Upper left pixel (within image) that must
+ * be redisplayed. */
+ int width, int height, /* Dimensions of area to redisplay (might be
+ * <= 0). */
+ int imgWidth, int imgHeight)/* New dimensions of image. */
+{
+ register TkButton *butPtr = clientData;
+
+#ifdef MAC_OSX_TK
+ if (butPtr->tkwin != NULL) {
+ TkpComputeButtonGeometry(butPtr);
+ }
+#else
+ /*
+ * Don't recompute geometry: it's controlled by the primary image.
+ */
+#endif
+
+ if ((butPtr->flags & TRISTATED) && (butPtr->tkwin != NULL)
+ && Tk_IsMapped(butPtr->tkwin)
+ && !(butPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(TkpDisplayButton, butPtr);
+ butPtr->flags |= REDRAW_PENDING;
+ }
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkButton.h b/tk8.6/generic/tkButton.h
new file mode 100644
index 0000000..7e04fb9
--- /dev/null
+++ b/tk8.6/generic/tkButton.h
@@ -0,0 +1,322 @@
+/*
+ * tkButton.h --
+ *
+ * Declarations of types and functions used to implement button-like
+ * widgets.
+ *
+ * Copyright (c) 1996-1998 by Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef _TKBUTTON
+#define _TKBUTTON
+
+#ifndef _TKINT
+#include "tkInt.h"
+#endif
+
+/*
+ * Legal values for the "compound" field of TkButton records.
+ */
+
+enum compound {
+ COMPOUND_BOTTOM, COMPOUND_CENTER, COMPOUND_LEFT, COMPOUND_NONE,
+ COMPOUND_RIGHT, COMPOUND_TOP
+};
+
+/*
+ * Legal values for the "state" field of TkButton records.
+ */
+
+enum state {
+ STATE_ACTIVE, STATE_DISABLED, STATE_NORMAL
+};
+
+/*
+ * Legal values for the "defaultState" field of TkButton records.
+ */
+
+enum defaultState {
+ DEFAULT_ACTIVE, DEFAULT_DISABLED, DEFAULT_NORMAL
+};
+
+/*
+ * A data structure of the following type is kept for each widget managed by
+ * this file:
+ */
+
+typedef struct {
+ Tk_Window tkwin; /* Window that embodies the button. NULL means
+ * that the window has been destroyed. */
+ Display *display; /* Display containing widget. Needed to free
+ * up resources after tkwin is gone. */
+ Tcl_Interp *interp; /* Interpreter associated with button. */
+ Tcl_Command widgetCmd; /* Token for button's widget command. */
+ int type; /* Type of widget, such as TYPE_LABEL:
+ * restricts operations that may be performed
+ * on widget. See below for legal values. */
+ Tk_OptionTable optionTable; /* Table that defines configuration options
+ * available for this widget. */
+
+ /*
+ * Information about what's in the button.
+ */
+
+ Tcl_Obj *textPtr; /* Value of -text option: specifies text to
+ * display in button. */
+ int underline; /* Value of -underline option: specifies index
+ * of character to underline. < 0 means don't
+ * underline anything. */
+ Tcl_Obj *textVarNamePtr; /* Value of -textvariable option: specifies
+ * name of variable or NULL. If non-NULL,
+ * button displays the contents of this
+ * variable. */
+ Pixmap bitmap; /* Value of -bitmap option. If not None,
+ * specifies bitmap to display and text and
+ * textVar are ignored. */
+ Tcl_Obj *imagePtr; /* Value of -image option: specifies image to
+ * display in window, or NULL if none. If
+ * non-NULL, bitmap, text, and textVarName are
+ * ignored.*/
+ Tk_Image image; /* Derived from imagePtr by calling
+ * Tk_GetImage, or NULL if imagePtr is
+ * NULL. */
+ Tcl_Obj *selectImagePtr; /* Value of -selectimage option: specifies
+ * image to display in window when selected,
+ * or NULL if none. Ignored if imagePtr is
+ * NULL. */
+ Tk_Image selectImage; /* Derived from selectImagePtr by calling
+ * Tk_GetImage, or NULL if selectImagePtr is
+ * NULL. */
+ Tcl_Obj *tristateImagePtr; /* Value of -tristateimage option: specifies
+ * image to display in window when selected,
+ * or NULL if none. Ignored if imagePtr is
+ * NULL. */
+ Tk_Image tristateImage; /* Derived from tristateImagePtr by calling
+ * Tk_GetImage, or NULL if tristateImagePtr is
+ * NULL. */
+
+ /*
+ * Information used when displaying widget:
+ */
+
+ enum state state; /* Value of -state option: specifies state of
+ * button for display purposes.*/
+ Tk_3DBorder normalBorder; /* Value of -background option: specifies
+ * color for background (and border) when
+ * window isn't active. */
+ Tk_3DBorder activeBorder; /* Value of -activebackground option: this is
+ * the color used to draw 3-D border and
+ * background when widget is active. */
+ Tcl_Obj *borderWidthPtr; /* Value of -borderWidth option: specifies
+ * width of border in pixels. */
+ int borderWidth; /* Integer value corresponding to
+ * borderWidthPtr. Always >= 0. */
+ int relief; /* Value of -relief option: specifies 3-d
+ * effect for border, such as
+ * TK_RELIEF_RAISED. */
+ int overRelief; /* Value of -overrelief option: specifies a
+ * 3-d effect for the border, such as
+ * TK_RELIEF_RAISED, to be used when the mouse
+ * is over the button. */
+ int offRelief; /* Value of -offrelief option: specifies a 3-d
+ * effect for the border, such as
+ * TK_RELIEF_RAISED, to be used when a
+ * checkbutton or radiobutton without
+ * indicator is off. */
+ Tcl_Obj *highlightWidthPtr; /* Value of -highlightthickness option:
+ * specifies width in pixels of highlight to
+ * draw around widget when it has the focus.
+ * <= 0 means don't draw a highlight. */
+ int highlightWidth; /* Integer value corresponding to
+ * highlightWidthPtr. Always >= 0. */
+ Tk_3DBorder highlightBorder;/* Value of -highlightbackground option:
+ * specifies background with which to draw 3-D
+ * default ring and focus highlight area when
+ * highlight is off. */
+ XColor *highlightColorPtr; /* Value of -highlightcolor option: specifies
+ * color for drawing traversal highlight. */
+ int inset; /* Total width of all borders, including
+ * traversal highlight and 3-D border.
+ * Indicates how much interior stuff must be
+ * offset from outside edges to leave room for
+ * borders. */
+ Tk_Font tkfont; /* Value of -font option: specifies font to
+ * use for display text. */
+ XColor *normalFg; /* Value of -font option: specifies foreground
+ * color in normal mode. */
+ XColor *activeFg; /* Value of -activeforeground option:
+ * foreground color in active mode. NULL means
+ * use -foreground instead. */
+ XColor *disabledFg; /* Value of -disabledforeground option:
+ * foreground color when disabled. NULL means
+ * use normalFg with a 50% stipple instead. */
+ GC normalTextGC; /* GC for drawing text in normal mode. Also
+ * used to copy from off-screen pixmap onto
+ * screen. */
+ GC activeTextGC; /* GC for drawing text in active mode (NULL
+ * means use normalTextGC). */
+ GC disabledGC; /* Used to produce disabled effect for text
+ * and check/radio marks. */
+ GC stippleGC; /* Used to produce disabled stipple effect for
+ * images when disabled. */
+ Pixmap gray; /* Pixmap for displaying disabled text if
+ * disabledFg is NULL. */
+ GC copyGC; /* Used for copying information from an
+ * off-screen pixmap to the screen. */
+ Tcl_Obj *widthPtr; /* Value of -width option. */
+ int width; /* Integer value corresponding to widthPtr. */
+ Tcl_Obj *heightPtr; /* Value of -height option. */
+ int height; /* Integer value corresponding to heightPtr. */
+ Tcl_Obj *wrapLengthPtr; /* Value of -wraplength option: specifies line
+ * length (in pixels) at which to wrap onto
+ * next line. <= 0 means don't wrap except at
+ * newlines. */
+ int wrapLength; /* Integer value corresponding to
+ * wrapLengthPtr. */
+ Tcl_Obj *padXPtr; /* Value of -padx option: specifies how many
+ * pixels of extra space to leave on left and
+ * right of text. Ignored for bitmaps and
+ * images. */
+ int padX; /* Integer value corresponding to padXPtr. */
+ Tcl_Obj *padYPtr; /* Value of -padx option: specifies how many
+ * pixels of extra space to leave above and
+ * below text. Ignored for bitmaps and
+ * images. */
+ int padY; /* Integer value corresponding to padYPtr. */
+ Tk_Anchor anchor; /* Value of -anchor option: specifies where
+ * text/bitmap should be displayed inside
+ * button region. */
+ Tk_Justify justify; /* Value of -justify option: specifies how to
+ * align lines of multi-line text. */
+ int indicatorOn; /* Value of -indicatoron option: 1 means draw
+ * indicator in checkbuttons and radiobuttons,
+ * 0 means don't draw it. */
+ Tk_3DBorder selectBorder; /* Value of -selectcolor option: specifies
+ * color for drawing indicator background, or
+ * perhaps widget background, when
+ * selected. */
+ int textWidth; /* Width needed to display text as requested,
+ * in pixels. */
+ int textHeight; /* Height needed to display text as requested,
+ * in pixels. */
+ Tk_TextLayout textLayout; /* Saved text layout information. */
+ int indicatorSpace; /* Horizontal space (in pixels) allocated for
+ * display of indicator. */
+ int indicatorDiameter; /* Diameter of indicator, in pixels. */
+ enum defaultState defaultState;
+ /* Value of -default option, such as
+ * DEFAULT_NORMAL: specifies state of default
+ * ring for buttons (normal, active, or
+ * disabled). NULL for other classes. */
+
+ /*
+ * For check and radio buttons, the fields below are used to manage the
+ * variable indicating the button's state.
+ */
+
+ Tcl_Obj *selVarNamePtr; /* Value of -variable option: specifies name
+ * of variable used to control selected state
+ * of button. */
+ Tcl_Obj *onValuePtr; /* Value of -offvalue option: specifies value
+ * to store in variable when this button is
+ * selected. */
+ Tcl_Obj *offValuePtr; /* Value of -offvalue option: specifies value
+ * to store in variable when this button isn't
+ * selected. Used only by checkbuttons. */
+ Tcl_Obj *tristateValuePtr; /* Value of -tristatevalue option: specifies
+ * value to display Tristate or Multivalue
+ * mode when variable matches this value.
+ * Used by check- buttons. */
+
+ /*
+ * Miscellaneous information:
+ */
+
+ Tk_Cursor cursor; /* Value of -cursor option: if not NULL,
+ * specifies current cursor for window. */
+ Tcl_Obj *takeFocusPtr; /* Value of -takefocus option; not used in the
+ * C code, but used by keyboard traversal
+ * scripts. */
+ Tcl_Obj *commandPtr; /* Value of -command option: specifies script
+ * to execute when button is invoked. If
+ * widget is label or has no command, this is
+ * NULL. */
+ int compound; /* Value of -compound option; specifies
+ * whether the button should show both an
+ * image and text, and, if so, how. */
+ int repeatDelay; /* Value of -repeatdelay option; specifies the
+ * number of ms after which the button will
+ * start to auto-repeat its command. */
+ int repeatInterval; /* Value of -repeatinterval option; specifies
+ * the number of ms between auto-repeat
+ * invocataions of the button command. */
+ int flags; /* Various flags; see below for
+ * definitions. */
+} TkButton;
+
+/*
+ * Possible "type" values for buttons. These are the kinds of widgets
+ * supported by this file. The ordering of the type numbers is significant:
+ * greater means more features and is used in the code.
+ */
+
+#define TYPE_LABEL 0
+#define TYPE_BUTTON 1
+#define TYPE_CHECK_BUTTON 2
+#define TYPE_RADIO_BUTTON 3
+
+/*
+ * Flag bits for buttons:
+ *
+ * REDRAW_PENDING: Non-zero means a DoWhenIdle handler has
+ * already been queued to redraw this window.
+ * SELECTED: Non-zero means this button is selected, so
+ * special highlight should be drawn.
+ * GOT_FOCUS: Non-zero means this button currently has the
+ * input focus.
+ * BUTTON_DELETED: Non-zero needs that this button has been
+ * deleted, or is in the process of being deleted
+ */
+
+#define REDRAW_PENDING (1 << 0)
+#define SELECTED (1 << 1)
+#define GOT_FOCUS (1 << 2)
+#define BUTTON_DELETED (1 << 3)
+#define TRISTATED (1 << 4)
+
+/*
+ * Declaration of button class functions structure
+ * and button/label defaults, for use in optionSpecs.
+ */
+
+MODULE_SCOPE const Tk_ClassProcs tkpButtonProcs;
+MODULE_SCOPE char tkDefButtonHighlightWidth[TCL_INTEGER_SPACE];
+MODULE_SCOPE char tkDefButtonPadx[TCL_INTEGER_SPACE];
+MODULE_SCOPE char tkDefButtonPady[TCL_INTEGER_SPACE];
+MODULE_SCOPE char tkDefButtonBorderWidth[TCL_INTEGER_SPACE];
+MODULE_SCOPE char tkDefLabelHighlightWidth[TCL_INTEGER_SPACE];
+MODULE_SCOPE char tkDefLabelPadx[TCL_INTEGER_SPACE];
+MODULE_SCOPE char tkDefLabelPady[TCL_INTEGER_SPACE];
+
+/*
+ * Declaration of functions used in the implementation of the button widget.
+ */
+
+#ifndef TkpButtonSetDefaults
+MODULE_SCOPE void TkpButtonSetDefaults();
+#endif
+MODULE_SCOPE void TkButtonWorldChanged(ClientData instanceData);
+MODULE_SCOPE void TkpComputeButtonGeometry(TkButton *butPtr);
+MODULE_SCOPE TkButton *TkpCreateButton(Tk_Window tkwin);
+#ifndef TkpDestroyButton
+MODULE_SCOPE void TkpDestroyButton(TkButton *butPtr);
+#endif
+#ifndef TkpDisplayButton
+MODULE_SCOPE void TkpDisplayButton(ClientData clientData);
+#endif
+MODULE_SCOPE int TkInvokeButton(TkButton *butPtr);
+
+#endif /* _TKBUTTON */
diff --git a/tk8.6/generic/tkCanvArc.c b/tk8.6/generic/tkCanvArc.c
new file mode 100644
index 0000000..d9f0461
--- /dev/null
+++ b/tk8.6/generic/tkCanvArc.c
@@ -0,0 +1,2119 @@
+/*
+ * tkCanvArc.c --
+ *
+ * This file implements arc items for canvas widgets.
+ *
+ * Copyright (c) 1992-1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "tkInt.h"
+#include "tkCanvas.h"
+
+/*
+ * The structure below defines the record for each arc item.
+ */
+
+typedef enum {
+ PIESLICE_STYLE, CHORD_STYLE, ARC_STYLE
+} Style;
+
+typedef struct ArcItem {
+ Tk_Item header; /* Generic stuff that's the same for all
+ * types. MUST BE FIRST IN STRUCTURE. */
+ Tk_Outline outline; /* Outline structure */
+ double bbox[4]; /* Coordinates (x1, y1, x2, y2) of bounding
+ * box for oval of which arc is a piece. */
+ double start; /* Angle at which arc begins, in degrees
+ * between 0 and 360. */
+ double extent; /* Extent of arc (angular distance from start
+ * to end of arc) in degrees between -360 and
+ * 360. */
+ double *outlinePtr; /* Points to (x,y) coordinates for points that
+ * define one or two closed polygons
+ * representing the portion of the outline
+ * that isn't part of the arc (the V-shape for
+ * a pie slice or a line-like segment for a
+ * chord). Malloc'ed. */
+ int numOutlinePoints; /* Number of points at outlinePtr. Zero means
+ * no space allocated. */
+ Tk_TSOffset tsoffset;
+ XColor *fillColor; /* Color for filling arc (used for drawing
+ * outline too when style is "arc"). NULL
+ * means don't fill arc. */
+ XColor *activeFillColor; /* Color for filling arc (used for drawing
+ * outline too when style is "arc" and state
+ * is "active"). NULL means use fillColor. */
+ XColor *disabledFillColor; /* Color for filling arc (used for drawing
+ * outline too when style is "arc" and state
+ * is "disabled". NULL means use fillColor */
+ Pixmap fillStipple; /* Stipple bitmap for filling item. */
+ Pixmap activeFillStipple; /* Stipple bitmap for filling item if state is
+ * active. */
+ Pixmap disabledFillStipple; /* Stipple bitmap for filling item if state is
+ * disabled. */
+ Style style; /* How to draw arc: arc, chord, or
+ * pieslice. */
+ GC fillGC; /* Graphics context for filling item. */
+ double center1[2]; /* Coordinates of center of arc outline at
+ * start (see ComputeArcOutline). */
+ double center2[2]; /* Coordinates of center of arc outline at
+ * start+extent (see ComputeArcOutline). */
+} ArcItem;
+
+/*
+ * The definitions below define the sizes of the polygons used to display
+ * outline information for various styles of arcs:
+ */
+
+#define CHORD_OUTLINE_PTS 7
+#define PIE_OUTLINE1_PTS 6
+#define PIE_OUTLINE2_PTS 7
+
+/*
+ * Information used for parsing configuration specs:
+ */
+
+static int StyleParseProc(ClientData clientData, Tcl_Interp *interp,
+ Tk_Window tkwin, const char *value,
+ char *widgRec, int offset);
+static const char * StylePrintProc(ClientData clientData, Tk_Window tkwin,
+ char *widgRec, int offset, Tcl_FreeProc **freeProcPtr);
+
+static const Tk_CustomOption stateOption = {
+ TkStateParseProc, TkStatePrintProc, INT2PTR(2)
+};
+static const Tk_CustomOption styleOption = {
+ StyleParseProc, StylePrintProc, NULL
+};
+static const Tk_CustomOption tagsOption = {
+ Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL
+};
+static const Tk_CustomOption dashOption = {
+ TkCanvasDashParseProc, TkCanvasDashPrintProc, NULL
+};
+static const Tk_CustomOption offsetOption = {
+ TkOffsetParseProc, TkOffsetPrintProc, INT2PTR(TK_OFFSET_RELATIVE)
+};
+static const Tk_CustomOption pixelOption = {
+ TkPixelParseProc, TkPixelPrintProc, NULL
+};
+
+static const Tk_ConfigSpec configSpecs[] = {
+ {TK_CONFIG_CUSTOM, "-activedash", NULL, NULL,
+ NULL, Tk_Offset(ArcItem, outline.activeDash),
+ TK_CONFIG_NULL_OK, &dashOption},
+ {TK_CONFIG_COLOR, "-activefill", NULL, NULL,
+ NULL, Tk_Offset(ArcItem, activeFillColor), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_COLOR, "-activeoutline", NULL, NULL,
+ NULL, Tk_Offset(ArcItem, outline.activeColor), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_BITMAP, "-activeoutlinestipple", NULL, NULL,
+ NULL, Tk_Offset(ArcItem, outline.activeStipple), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_BITMAP, "-activestipple", NULL, NULL,
+ NULL, Tk_Offset(ArcItem, activeFillStipple), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_CUSTOM, "-activewidth", NULL, NULL,
+ "0.0", Tk_Offset(ArcItem, outline.activeWidth),
+ TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
+ {TK_CONFIG_CUSTOM, "-dash", NULL, NULL,
+ NULL, Tk_Offset(ArcItem, outline.dash),
+ TK_CONFIG_NULL_OK, &dashOption},
+ {TK_CONFIG_PIXELS, "-dashoffset", NULL, NULL,
+ "0", Tk_Offset(ArcItem, outline.offset), TK_CONFIG_DONT_SET_DEFAULT, NULL},
+ {TK_CONFIG_CUSTOM, "-disableddash", NULL, NULL,
+ NULL, Tk_Offset(ArcItem, outline.disabledDash),
+ TK_CONFIG_NULL_OK, &dashOption},
+ {TK_CONFIG_COLOR, "-disabledfill", NULL, NULL,
+ NULL, Tk_Offset(ArcItem, disabledFillColor), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_COLOR, "-disabledoutline", NULL, NULL,
+ NULL, Tk_Offset(ArcItem, outline.disabledColor), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_BITMAP, "-disabledoutlinestipple", NULL, NULL,
+ NULL, Tk_Offset(ArcItem, outline.disabledStipple), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_BITMAP, "-disabledstipple", NULL, NULL,
+ NULL, Tk_Offset(ArcItem, disabledFillStipple), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_CUSTOM, "-disabledwidth", NULL, NULL,
+ "0.0", Tk_Offset(ArcItem, outline.disabledWidth),
+ TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
+ {TK_CONFIG_DOUBLE, "-extent", NULL, NULL,
+ "90", Tk_Offset(ArcItem, extent), TK_CONFIG_DONT_SET_DEFAULT, NULL},
+ {TK_CONFIG_COLOR, "-fill", NULL, NULL,
+ NULL, Tk_Offset(ArcItem, fillColor), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_CUSTOM, "-offset", NULL, NULL,
+ "0,0", Tk_Offset(ArcItem, tsoffset),
+ TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},
+ {TK_CONFIG_COLOR, "-outline", NULL, NULL,
+ "black", Tk_Offset(ArcItem, outline.color), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_CUSTOM, "-outlineoffset", NULL, NULL,
+ "0,0", Tk_Offset(ArcItem, outline.tsoffset),
+ TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},
+ {TK_CONFIG_BITMAP, "-outlinestipple", NULL, NULL,
+ NULL, Tk_Offset(ArcItem, outline.stipple), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_DOUBLE, "-start", NULL, NULL,
+ "0", Tk_Offset(ArcItem, start), TK_CONFIG_DONT_SET_DEFAULT, NULL},
+ {TK_CONFIG_CUSTOM, "-state", NULL, NULL,
+ NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption},
+ {TK_CONFIG_BITMAP, "-stipple", NULL, NULL,
+ NULL, Tk_Offset(ArcItem, fillStipple), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_CUSTOM, "-style", NULL, NULL,
+ NULL, Tk_Offset(ArcItem, style), TK_CONFIG_DONT_SET_DEFAULT,
+ &styleOption},
+ {TK_CONFIG_CUSTOM, "-tags", NULL, NULL,
+ NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
+ {TK_CONFIG_CUSTOM, "-width", NULL, NULL,
+ "1.0", Tk_Offset(ArcItem, outline.width), TK_CONFIG_DONT_SET_DEFAULT,
+ &pixelOption},
+ {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}
+};
+
+/*
+ * Prototypes for functions defined in this file:
+ */
+
+static void ComputeArcBbox(Tk_Canvas canvas, ArcItem *arcPtr);
+static int ConfigureArc(Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr, int objc,
+ Tcl_Obj *const objv[], int flags);
+static int CreateArc(Tcl_Interp *interp,
+ Tk_Canvas canvas, struct Tk_Item *itemPtr,
+ int objc, Tcl_Obj *const objv[]);
+static void DeleteArc(Tk_Canvas canvas,
+ Tk_Item *itemPtr, Display *display);
+static void DisplayArc(Tk_Canvas canvas,
+ Tk_Item *itemPtr, Display *display, Drawable dst,
+ int x, int y, int width, int height);
+static int ArcCoords(Tcl_Interp *interp, Tk_Canvas canvas,
+ Tk_Item *itemPtr, int objc, Tcl_Obj *const objv[]);
+static int ArcToArea(Tk_Canvas canvas,
+ Tk_Item *itemPtr, double *rectPtr);
+static double ArcToPoint(Tk_Canvas canvas,
+ Tk_Item *itemPtr, double *coordPtr);
+static int ArcToPostscript(Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr, int prepass);
+static void ScaleArc(Tk_Canvas canvas,
+ Tk_Item *itemPtr, double originX, double originY,
+ double scaleX, double scaleY);
+static void TranslateArc(Tk_Canvas canvas,
+ Tk_Item *itemPtr, double deltaX, double deltaY);
+static int AngleInRange(double x, double y,
+ double start, double extent);
+static void ComputeArcOutline(Tk_Canvas canvas, ArcItem *arcPtr);
+static int HorizLineToArc(double x1, double x2,
+ double y, double rx, double ry,
+ double start, double extent);
+static int VertLineToArc(double x, double y1,
+ double y2, double rx, double ry,
+ double start, double extent);
+
+/*
+ * The structures below defines the arc item types by means of functions that
+ * can be invoked by generic item code.
+ */
+
+Tk_ItemType tkArcType = {
+ "arc", /* name */
+ sizeof(ArcItem), /* itemSize */
+ CreateArc, /* createProc */
+ configSpecs, /* configSpecs */
+ ConfigureArc, /* configureProc */
+ ArcCoords, /* coordProc */
+ DeleteArc, /* deleteProc */
+ DisplayArc, /* displayProc */
+ TK_CONFIG_OBJS, /* flags */
+ ArcToPoint, /* pointProc */
+ ArcToArea, /* areaProc */
+ ArcToPostscript, /* postscriptProc */
+ ScaleArc, /* scaleProc */
+ TranslateArc, /* translateProc */
+ NULL, /* indexProc */
+ NULL, /* icursorProc */
+ NULL, /* selectionProc */
+ NULL, /* insertProc */
+ NULL, /* dTextProc */
+ NULL, /* nextPtr */
+ NULL, 0, NULL, NULL
+};
+
+/*
+ *--------------------------------------------------------------
+ *
+ * CreateArc --
+ *
+ * This function is invoked to create a new arc item in a canvas.
+ *
+ * Results:
+ * A standard Tcl return value. If an error occurred in creating the
+ * item, then an error message is left in the interp's result; in this
+ * case itemPtr is left uninitialized, so it can be safely freed by the
+ * caller.
+ *
+ * Side effects:
+ * A new arc item is created.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+CreateArc(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Tk_Canvas canvas, /* Canvas to hold new item. */
+ Tk_Item *itemPtr, /* Record to hold new item; header has been
+ * initialized by caller. */
+ int objc, /* Number of arguments in objv. */
+ Tcl_Obj *const objv[]) /* Arguments describing arc. */
+{
+ ArcItem *arcPtr = (ArcItem *) itemPtr;
+ int i;
+
+ if (objc == 0) {
+ Tcl_Panic("canvas did not pass any coords");
+ }
+
+ /*
+ * Carry out initialization that is needed in order to clean up after
+ * errors during the the remainder of this function.
+ */
+
+ Tk_CreateOutline(&(arcPtr->outline));
+ arcPtr->start = 0;
+ arcPtr->extent = 90;
+ arcPtr->outlinePtr = NULL;
+ arcPtr->numOutlinePoints = 0;
+ arcPtr->tsoffset.flags = 0;
+ arcPtr->tsoffset.xoffset = 0;
+ arcPtr->tsoffset.yoffset = 0;
+ arcPtr->fillColor = NULL;
+ arcPtr->activeFillColor = NULL;
+ arcPtr->disabledFillColor = NULL;
+ arcPtr->fillStipple = None;
+ arcPtr->activeFillStipple = None;
+ arcPtr->disabledFillStipple = None;
+ arcPtr->style = PIESLICE_STYLE;
+ arcPtr->fillGC = NULL;
+
+ /*
+ * Process the arguments to fill in the item record.
+ */
+
+ for (i = 1; i < objc; i++) {
+ const char *arg = Tcl_GetString(objv[i]);
+
+ if ((arg[0] == '-') && (arg[1] >= 'a') && (arg[1] <= 'z')) {
+ break;
+ }
+ }
+ if (ArcCoords(interp, canvas, itemPtr, i, objv) != TCL_OK) {
+ goto error;
+ }
+ if (ConfigureArc(interp, canvas, itemPtr, objc-i, objv+i, 0) == TCL_OK) {
+ return TCL_OK;
+ }
+
+ error:
+ DeleteArc(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ArcCoords --
+ *
+ * This function is invoked to process the "coords" widget command on
+ * arcs. See the user documentation for details on what it does.
+ *
+ * Results:
+ * Returns TCL_OK or TCL_ERROR, and sets the interp's result.
+ *
+ * Side effects:
+ * The coordinates for the given item may be changed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+ArcCoords(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item whose coordinates are to be read or
+ * modified. */
+ int objc, /* Number of coordinates supplied in objv. */
+ Tcl_Obj *const objv[]) /* Array of coordinates: x1, y1, x2, y2, ... */
+{
+ ArcItem *arcPtr = (ArcItem *) itemPtr;
+
+ if (objc == 0) {
+ Tcl_Obj *objs[4];
+
+ objs[0] = Tcl_NewDoubleObj(arcPtr->bbox[0]);
+ objs[1] = Tcl_NewDoubleObj(arcPtr->bbox[1]);
+ objs[2] = Tcl_NewDoubleObj(arcPtr->bbox[2]);
+ objs[3] = Tcl_NewDoubleObj(arcPtr->bbox[3]);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(4, objs));
+ } else if ((objc == 1)||(objc == 4)) {
+ if (objc==1) {
+ if (Tcl_ListObjGetElements(interp, objv[0], &objc,
+ (Tcl_Obj ***) &objv) != TCL_OK) {
+ return TCL_ERROR;
+ } else if (objc != 4) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "wrong # coordinates: expected 4, got %d", objc));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "COORDS", "ARC",
+ NULL);
+ return TCL_ERROR;
+ }
+ }
+ if ((Tk_CanvasGetCoordFromObj(interp, canvas, objv[0],
+ &arcPtr->bbox[0]) != TCL_OK)
+ || (Tk_CanvasGetCoordFromObj(interp, canvas, objv[1],
+ &arcPtr->bbox[1]) != TCL_OK)
+ || (Tk_CanvasGetCoordFromObj(interp, canvas, objv[2],
+ &arcPtr->bbox[2]) != TCL_OK)
+ || (Tk_CanvasGetCoordFromObj(interp, canvas, objv[3],
+ &arcPtr->bbox[3]) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ ComputeArcBbox(canvas, arcPtr);
+ } else {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "wrong # coordinates: expected 0 or 4, got %d", objc));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "COORDS", "ARC", NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ConfigureArc --
+ *
+ * This function is invoked to configure various aspects of a arc item,
+ * such as its outline and fill colors.
+ *
+ * Results:
+ * A standard Tcl result code. If an error occurs, then an error message
+ * is left in the interp's result.
+ *
+ * Side effects:
+ * Configuration information, such as colors and stipple patterns, may be
+ * set for itemPtr.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+ConfigureArc(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tk_Canvas canvas, /* Canvas containing itemPtr. */
+ Tk_Item *itemPtr, /* Arc item to reconfigure. */
+ int objc, /* Number of elements in objv. */
+ Tcl_Obj *const objv[], /* Arguments describing things to configure. */
+ int flags) /* Flags to pass to Tk_ConfigureWidget. */
+{
+ ArcItem *arcPtr = (ArcItem *) itemPtr;
+ XGCValues gcValues;
+ GC newGC;
+ unsigned long mask;
+ int i;
+ Tk_Window tkwin;
+ Tk_TSOffset *tsoffset;
+ XColor *color;
+ Pixmap stipple;
+ Tk_State state;
+
+ tkwin = Tk_CanvasTkwin(canvas);
+ if (TCL_OK != Tk_ConfigureWidget(interp, tkwin, configSpecs, objc,
+ (const char **) objv, (char *) arcPtr, flags|TK_CONFIG_OBJS)) {
+ return TCL_ERROR;
+ }
+
+ state = itemPtr->state;
+
+ /*
+ * A few of the options require additional processing, such as style and
+ * graphics contexts.
+ */
+
+ if (arcPtr->outline.activeWidth > arcPtr->outline.width ||
+ arcPtr->outline.activeDash.number != 0 ||
+ arcPtr->outline.activeColor != NULL ||
+ arcPtr->outline.activeStipple != None ||
+ arcPtr->activeFillColor != NULL ||
+ arcPtr->activeFillStipple != None) {
+ itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;
+ } else {
+ itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;
+ }
+
+ tsoffset = &arcPtr->outline.tsoffset;
+ flags = tsoffset->flags;
+ if (flags & TK_OFFSET_LEFT) {
+ tsoffset->xoffset = (int) (arcPtr->bbox[0] + 0.5);
+ } else if (flags & TK_OFFSET_CENTER) {
+ tsoffset->xoffset = (int) ((arcPtr->bbox[0]+arcPtr->bbox[2]+1)/2);
+ } else if (flags & TK_OFFSET_RIGHT) {
+ tsoffset->xoffset = (int) (arcPtr->bbox[2] + 0.5);
+ }
+ if (flags & TK_OFFSET_TOP) {
+ tsoffset->yoffset = (int) (arcPtr->bbox[1] + 0.5);
+ } else if (flags & TK_OFFSET_MIDDLE) {
+ tsoffset->yoffset = (int) ((arcPtr->bbox[1]+arcPtr->bbox[3]+1)/2);
+ } else if (flags & TK_OFFSET_BOTTOM) {
+ tsoffset->yoffset = (int) (arcPtr->bbox[2] + 0.5);
+ }
+
+ i = (int) (arcPtr->start/360.0);
+ arcPtr->start -= i*360.0;
+ if (arcPtr->start < 0) {
+ arcPtr->start += 360.0;
+ }
+ i = (int) (arcPtr->extent/360.0);
+ arcPtr->extent -= i*360.0;
+
+ mask = Tk_ConfigOutlineGC(&gcValues, canvas, itemPtr, &(arcPtr->outline));
+ if (mask) {
+ gcValues.cap_style = CapButt;
+ mask |= GCCapStyle;
+ newGC = Tk_GetGC(tkwin, mask, &gcValues);
+ } else {
+ newGC = NULL;
+ }
+ if (arcPtr->outline.gc != NULL) {
+ Tk_FreeGC(Tk_Display(tkwin), arcPtr->outline.gc);
+ }
+ arcPtr->outline.gc = newGC;
+
+ if(state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+ if (state==TK_STATE_HIDDEN) {
+ ComputeArcBbox(canvas, arcPtr);
+ return TCL_OK;
+ }
+
+ color = arcPtr->fillColor;
+ stipple = arcPtr->fillStipple;
+ if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (arcPtr->activeFillColor!=NULL) {
+ color = arcPtr->activeFillColor;
+ }
+ if (arcPtr->activeFillStipple!=None) {
+ stipple = arcPtr->activeFillStipple;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (arcPtr->disabledFillColor!=NULL) {
+ color = arcPtr->disabledFillColor;
+ }
+ if (arcPtr->disabledFillStipple!=None) {
+ stipple = arcPtr->disabledFillStipple;
+ }
+ }
+
+ if (arcPtr->style == ARC_STYLE) {
+ newGC = NULL;
+ } else if (color == NULL) {
+ newGC = NULL;
+ } else {
+ gcValues.foreground = color->pixel;
+ if (arcPtr->style == CHORD_STYLE) {
+ gcValues.arc_mode = ArcChord;
+ } else {
+ gcValues.arc_mode = ArcPieSlice;
+ }
+ mask = GCForeground|GCArcMode;
+ if (stipple != None) {
+ gcValues.stipple = stipple;
+ gcValues.fill_style = FillStippled;
+ mask |= GCStipple|GCFillStyle;
+ }
+ newGC = Tk_GetGC(tkwin, mask, &gcValues);
+ }
+ if (arcPtr->fillGC != NULL) {
+ Tk_FreeGC(Tk_Display(tkwin), arcPtr->fillGC);
+ }
+ arcPtr->fillGC = newGC;
+
+ tsoffset = &arcPtr->tsoffset;
+ flags = tsoffset->flags;
+ if (flags & TK_OFFSET_LEFT) {
+ tsoffset->xoffset = (int) (arcPtr->bbox[0] + 0.5);
+ } else if (flags & TK_OFFSET_CENTER) {
+ tsoffset->xoffset = (int) ((arcPtr->bbox[0]+arcPtr->bbox[2]+1)/2);
+ } else if (flags & TK_OFFSET_RIGHT) {
+ tsoffset->xoffset = (int) (arcPtr->bbox[2] + 0.5);
+ }
+ if (flags & TK_OFFSET_TOP) {
+ tsoffset->yoffset = (int) (arcPtr->bbox[1] + 0.5);
+ } else if (flags & TK_OFFSET_MIDDLE) {
+ tsoffset->yoffset = (int) ((arcPtr->bbox[1]+arcPtr->bbox[3]+1)/2);
+ } else if (flags & TK_OFFSET_BOTTOM) {
+ tsoffset->yoffset = (int) (arcPtr->bbox[3] + 0.5);
+ }
+
+ ComputeArcBbox(canvas, arcPtr);
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DeleteArc --
+ *
+ * This function is called to clean up the data structure associated with
+ * an arc item.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Resources associated with itemPtr are released.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+DeleteArc(
+ Tk_Canvas canvas, /* Info about overall canvas. */
+ Tk_Item *itemPtr, /* Item that is being deleted. */
+ Display *display) /* Display containing window for canvas. */
+{
+ ArcItem *arcPtr = (ArcItem *) itemPtr;
+
+ Tk_DeleteOutline(display, &(arcPtr->outline));
+ if (arcPtr->numOutlinePoints != 0) {
+ ckfree(arcPtr->outlinePtr);
+ }
+ if (arcPtr->fillColor != NULL) {
+ Tk_FreeColor(arcPtr->fillColor);
+ }
+ if (arcPtr->activeFillColor != NULL) {
+ Tk_FreeColor(arcPtr->activeFillColor);
+ }
+ if (arcPtr->disabledFillColor != NULL) {
+ Tk_FreeColor(arcPtr->disabledFillColor);
+ }
+ if (arcPtr->fillStipple != None) {
+ Tk_FreeBitmap(display, arcPtr->fillStipple);
+ }
+ if (arcPtr->activeFillStipple != None) {
+ Tk_FreeBitmap(display, arcPtr->activeFillStipple);
+ }
+ if (arcPtr->disabledFillStipple != None) {
+ Tk_FreeBitmap(display, arcPtr->disabledFillStipple);
+ }
+ if (arcPtr->fillGC != NULL) {
+ Tk_FreeGC(display, arcPtr->fillGC);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ComputeArcBbox --
+ *
+ * This function is invoked to compute the bounding box of all the pixels
+ * that may be drawn as part of an arc.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The fields x1, y1, x2, and y2 are updated in the header for itemPtr.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static void
+ComputeArcBbox(
+ Tk_Canvas canvas, /* Canvas that contains item. */
+ ArcItem *arcPtr) /* Item whose bbox is to be recomputed. */
+{
+ double tmp, center[2], point[2];
+ double width;
+ Tk_State state = arcPtr->header.state;
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+
+ width = arcPtr->outline.width;
+ if (width < 1.0) {
+ width = 1.0;
+ }
+ if (state==TK_STATE_HIDDEN) {
+ arcPtr->header.x1 = arcPtr->header.x2 =
+ arcPtr->header.y1 = arcPtr->header.y2 = -1;
+ return;
+ } else if (Canvas(canvas)->currentItemPtr == (Tk_Item *) arcPtr) {
+ if (arcPtr->outline.activeWidth>width) {
+ width = arcPtr->outline.activeWidth;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (arcPtr->outline.disabledWidth>0) {
+ width = arcPtr->outline.disabledWidth;
+ }
+ }
+
+ /*
+ * Make sure that the first coordinates are the lowest ones.
+ */
+
+ if (arcPtr->bbox[1] > arcPtr->bbox[3]) {
+ double tmp = arcPtr->bbox[3];
+
+ arcPtr->bbox[3] = arcPtr->bbox[1];
+ arcPtr->bbox[1] = tmp;
+ }
+ if (arcPtr->bbox[0] > arcPtr->bbox[2]) {
+ double tmp = arcPtr->bbox[2];
+
+ arcPtr->bbox[2] = arcPtr->bbox[0];
+ arcPtr->bbox[0] = tmp;
+ }
+
+ ComputeArcOutline(canvas,arcPtr);
+
+ /*
+ * To compute the bounding box, start with the the bbox formed by the two
+ * endpoints of the arc. Then add in the center of the arc's oval (if
+ * relevant) and the 3-o'clock, 6-o'clock, 9-o'clock, and 12-o'clock
+ * positions, if they are relevant.
+ */
+
+ arcPtr->header.x1 = arcPtr->header.x2 = (int) arcPtr->center1[0];
+ arcPtr->header.y1 = arcPtr->header.y2 = (int) arcPtr->center1[1];
+ TkIncludePoint((Tk_Item *) arcPtr, arcPtr->center2);
+ center[0] = (arcPtr->bbox[0] + arcPtr->bbox[2])/2;
+ center[1] = (arcPtr->bbox[1] + arcPtr->bbox[3])/2;
+ if (arcPtr->style == PIESLICE_STYLE) {
+ TkIncludePoint((Tk_Item *) arcPtr, center);
+ }
+
+ tmp = -arcPtr->start;
+ if (tmp < 0) {
+ tmp += 360.0;
+ }
+ if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {
+ point[0] = arcPtr->bbox[2];
+ point[1] = center[1];
+ TkIncludePoint((Tk_Item *) arcPtr, point);
+ }
+ tmp = 90.0 - arcPtr->start;
+ if (tmp < 0) {
+ tmp += 360.0;
+ }
+ if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {
+ point[0] = center[0];
+ point[1] = arcPtr->bbox[1];
+ TkIncludePoint((Tk_Item *) arcPtr, point);
+ }
+ tmp = 180.0 - arcPtr->start;
+ if (tmp < 0) {
+ tmp += 360.0;
+ }
+ if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {
+ point[0] = arcPtr->bbox[0];
+ point[1] = center[1];
+ TkIncludePoint((Tk_Item *) arcPtr, point);
+ }
+ tmp = 270.0 - arcPtr->start;
+ if (tmp < 0) {
+ tmp += 360.0;
+ }
+ if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {
+ point[0] = center[0];
+ point[1] = arcPtr->bbox[3];
+ TkIncludePoint((Tk_Item *) arcPtr, point);
+ }
+
+ /*
+ * Lastly, expand by the width of the arc (if the arc's outline is being
+ * drawn) and add one extra pixel just for safety.
+ */
+
+ if (arcPtr->outline.gc == NULL) {
+ tmp = 1;
+ } else {
+ tmp = (int) ((width + 1.0)/2.0 + 1);
+ }
+ arcPtr->header.x1 -= (int) tmp;
+ arcPtr->header.y1 -= (int) tmp;
+ arcPtr->header.x2 += (int) tmp;
+ arcPtr->header.y2 += (int) tmp;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DisplayArc --
+ *
+ * This function is invoked to draw an arc item in a given drawable.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * ItemPtr is drawn in drawable using the transformation information in
+ * canvas.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+DisplayArc(
+ Tk_Canvas canvas, /* Canvas that contains item. */
+ Tk_Item *itemPtr, /* Item to be displayed. */
+ Display *display, /* Display on which to draw item. */
+ Drawable drawable, /* Pixmap or window in which to draw item. */
+ int x, int y, /* Describes region of canvas that must be */
+ int width, int height) /* redisplayed (not used). */
+{
+ ArcItem *arcPtr = (ArcItem *) itemPtr;
+ short x1, y1, x2, y2;
+ int start, extent, dashnumber;
+ double lineWidth;
+ Tk_State state = itemPtr->state;
+ Pixmap stipple;
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+ lineWidth = arcPtr->outline.width;
+ if (lineWidth < 1.0) {
+ lineWidth = 1.0;
+ }
+ dashnumber = arcPtr->outline.dash.number;
+ stipple = arcPtr->fillStipple;
+ if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (arcPtr->outline.activeWidth>lineWidth) {
+ lineWidth = arcPtr->outline.activeWidth;
+ }
+ if (arcPtr->outline.activeDash.number != 0) {
+ dashnumber = arcPtr->outline.activeDash.number;
+ }
+ if (arcPtr->activeFillStipple != None) {
+ stipple = arcPtr->activeFillStipple;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (arcPtr->outline.disabledWidth > 0) {
+ lineWidth = arcPtr->outline.disabledWidth;
+ }
+ if (arcPtr->outline.disabledDash.number != 0) {
+ dashnumber = arcPtr->outline.disabledDash.number;
+ }
+ if (arcPtr->disabledFillStipple != None) {
+ stipple = arcPtr->disabledFillStipple;
+ }
+ }
+
+ /*
+ * Compute the screen coordinates of the bounding box for the item, plus
+ * integer values for the angles.
+ */
+
+ Tk_CanvasDrawableCoords(canvas, arcPtr->bbox[0], arcPtr->bbox[1],
+ &x1, &y1);
+ Tk_CanvasDrawableCoords(canvas, arcPtr->bbox[2], arcPtr->bbox[3],
+ &x2, &y2);
+ if (x2 <= x1) {
+ x2 = x1+1;
+ }
+ if (y2 <= y1) {
+ y2 = y1+1;
+ }
+ start = (int) ((64*arcPtr->start) + 0.5);
+ extent = (int) ((64*arcPtr->extent) + 0.5);
+
+ /*
+ * Display filled arc first (if wanted), then outline. If the extent is
+ * zero then don't invoke XFillArc or XDrawArc, since this causes some
+ * window servers to crash and should be a no-op anyway.
+ */
+
+ if ((arcPtr->fillGC != NULL) && (extent != 0)) {
+ if (stipple != None) {
+ int w = 0;
+ int h = 0;
+ Tk_TSOffset *tsoffset = &arcPtr->tsoffset;
+ int flags = tsoffset->flags;
+
+ if (flags & (TK_OFFSET_CENTER|TK_OFFSET_MIDDLE)) {
+ Tk_SizeOfBitmap(display, stipple, &w, &h);
+ if (flags & TK_OFFSET_CENTER) {
+ w /= 2;
+ } else {
+ w = 0;
+ }
+ if (flags & TK_OFFSET_MIDDLE) {
+ h /= 2;
+ } else {
+ h = 0;
+ }
+ }
+ tsoffset->xoffset -= w;
+ tsoffset->yoffset -= h;
+ Tk_CanvasSetOffset(canvas, arcPtr->fillGC, tsoffset);
+ if (tsoffset) {
+ tsoffset->xoffset += w;
+ tsoffset->yoffset += h;
+ }
+ }
+ XFillArc(display, drawable, arcPtr->fillGC, x1, y1, (unsigned) (x2-x1),
+ (unsigned) (y2-y1), start, extent);
+ if (stipple != None) {
+ XSetTSOrigin(display, arcPtr->fillGC, 0, 0);
+ }
+ }
+ if (arcPtr->outline.gc != NULL) {
+ Tk_ChangeOutlineGC(canvas, itemPtr, &(arcPtr->outline));
+
+ if (extent != 0) {
+ XDrawArc(display, drawable, arcPtr->outline.gc, x1, y1,
+ (unsigned) (x2-x1), (unsigned) (y2-y1), start, extent);
+ }
+
+ /*
+ * If the outline width is very thin, don't use polygons to draw the
+ * linear parts of the outline (this often results in nothing being
+ * displayed); just draw lines instead. The same is done if the
+ * outline is dashed, because then polygons don't work.
+ */
+
+ if (lineWidth < 1.5 || dashnumber != 0) {
+ Tk_CanvasDrawableCoords(canvas, arcPtr->center1[0],
+ arcPtr->center1[1], &x1, &y1);
+ Tk_CanvasDrawableCoords(canvas, arcPtr->center2[0],
+ arcPtr->center2[1], &x2, &y2);
+
+ if (arcPtr->style == CHORD_STYLE) {
+ XDrawLine(display, drawable, arcPtr->outline.gc,
+ x1, y1, x2, y2);
+ } else if (arcPtr->style == PIESLICE_STYLE) {
+ short cx, cy;
+
+ Tk_CanvasDrawableCoords(canvas,
+ (arcPtr->bbox[0] + arcPtr->bbox[2])/2.0,
+ (arcPtr->bbox[1] + arcPtr->bbox[3])/2.0, &cx, &cy);
+ XDrawLine(display, drawable, arcPtr->outline.gc,
+ cx, cy, x1, y1);
+ XDrawLine(display, drawable, arcPtr->outline.gc,
+ cx, cy, x2, y2);
+ }
+ } else {
+ if (arcPtr->style == CHORD_STYLE) {
+ TkFillPolygon(canvas, arcPtr->outlinePtr, CHORD_OUTLINE_PTS,
+ display, drawable, arcPtr->outline.gc, NULL);
+ } else if (arcPtr->style == PIESLICE_STYLE) {
+ TkFillPolygon(canvas, arcPtr->outlinePtr, PIE_OUTLINE1_PTS,
+ display, drawable, arcPtr->outline.gc, NULL);
+ TkFillPolygon(canvas, arcPtr->outlinePtr + 2*PIE_OUTLINE1_PTS,
+ PIE_OUTLINE2_PTS, display, drawable,
+ arcPtr->outline.gc, NULL);
+ }
+ }
+
+ Tk_ResetOutlineGC(canvas, itemPtr, &(arcPtr->outline));
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ArcToPoint --
+ *
+ * Computes the distance from a given point to a given arc, in canvas
+ * units.
+ *
+ * Results:
+ * The return value is 0 if the point whose x and y coordinates are
+ * coordPtr[0] and coordPtr[1] is inside the arc. If the point isn't
+ * inside the arc then the return value is the distance from the point to
+ * the arc. If itemPtr is filled, then anywhere in the interior is
+ * considered "inside"; if itemPtr isn't filled, then "inside" means only
+ * the area occupied by the outline.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static double
+ArcToPoint(
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item to check against point. */
+ double *pointPtr) /* Pointer to x and y coordinates. */
+{
+ ArcItem *arcPtr = (ArcItem *) itemPtr;
+ double vertex[2], pointAngle, diff, dist, newDist;
+ double poly[8], polyDist, width, t1, t2;
+ int filled, angleInRange;
+ Tk_State state = itemPtr->state;
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+
+ width = (double) arcPtr->outline.width;
+ if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (arcPtr->outline.activeWidth>width) {
+ width = (double) arcPtr->outline.activeWidth;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (arcPtr->outline.disabledWidth>0) {
+ width = (double) arcPtr->outline.disabledWidth;
+ }
+ }
+
+ /*
+ * See if the point is within the angular range of the arc. Remember, X
+ * angles are backwards from the way we'd normally think of them. Also,
+ * compensate for any eccentricity of the oval.
+ */
+
+ vertex[0] = (arcPtr->bbox[0] + arcPtr->bbox[2])/2.0;
+ vertex[1] = (arcPtr->bbox[1] + arcPtr->bbox[3])/2.0;
+ t1 = arcPtr->bbox[3] - arcPtr->bbox[1];
+ if (t1 != 0.0) {
+ t1 = (pointPtr[1] - vertex[1]) / t1;
+ }
+ t2 = arcPtr->bbox[2] - arcPtr->bbox[0];
+ if (t2 != 0.0) {
+ t2 = (pointPtr[0] - vertex[0]) / t2;
+ }
+ if ((t1 == 0.0) && (t2 == 0.0)) {
+ pointAngle = 0;
+ } else {
+ pointAngle = -atan2(t1, t2)*180/PI;
+ }
+ diff = pointAngle - arcPtr->start;
+ diff -= ((int) (diff/360.0) * 360.0);
+ if (diff < 0) {
+ diff += 360.0;
+ }
+ angleInRange = (diff <= arcPtr->extent) ||
+ ((arcPtr->extent < 0) && ((diff - 360.0) >= arcPtr->extent));
+
+ /*
+ * Now perform different tests depending on what kind of arc we're dealing
+ * with.
+ */
+
+ if (arcPtr->style == ARC_STYLE) {
+ if (angleInRange) {
+ return TkOvalToPoint(arcPtr->bbox, width, 0, pointPtr);
+ }
+ dist = hypot(pointPtr[0] - arcPtr->center1[0],
+ pointPtr[1] - arcPtr->center1[1]);
+ newDist = hypot(pointPtr[0] - arcPtr->center2[0],
+ pointPtr[1] - arcPtr->center2[1]);
+ if (newDist < dist) {
+ return newDist;
+ }
+ return dist;
+ }
+
+ if ((arcPtr->fillGC != NULL) || (arcPtr->outline.gc == NULL)) {
+ filled = 1;
+ } else {
+ filled = 0;
+ }
+ if (arcPtr->outline.gc == NULL) {
+ width = 0.0;
+ }
+
+ if (arcPtr->style == PIESLICE_STYLE) {
+ if (width > 1.0) {
+ dist = TkPolygonToPoint(arcPtr->outlinePtr, PIE_OUTLINE1_PTS,
+ pointPtr);
+ newDist = TkPolygonToPoint(arcPtr->outlinePtr + 2*PIE_OUTLINE1_PTS,
+ PIE_OUTLINE2_PTS, pointPtr);
+ } else {
+ dist = TkLineToPoint(vertex, arcPtr->center1, pointPtr);
+ newDist = TkLineToPoint(vertex, arcPtr->center2, pointPtr);
+ }
+ if (newDist < dist) {
+ dist = newDist;
+ }
+ if (angleInRange) {
+ newDist = TkOvalToPoint(arcPtr->bbox, width, filled, pointPtr);
+ if (newDist < dist) {
+ dist = newDist;
+ }
+ }
+ return dist;
+ }
+
+ /*
+ * This is a chord-style arc. We have to deal specially with the
+ * triangular piece that represents the difference between a chord-style
+ * arc and a pie-slice arc (for small angles this piece is excluded here
+ * where it would be included for pie slices; for large angles the piece
+ * is included here but would be excluded for pie slices).
+ */
+
+ if (width > 1.0) {
+ dist = TkPolygonToPoint(arcPtr->outlinePtr, CHORD_OUTLINE_PTS,
+ pointPtr);
+ } else {
+ dist = TkLineToPoint(arcPtr->center1, arcPtr->center2, pointPtr);
+ }
+ poly[0] = poly[6] = vertex[0];
+ poly[1] = poly[7] = vertex[1];
+ poly[2] = arcPtr->center1[0];
+ poly[3] = arcPtr->center1[1];
+ poly[4] = arcPtr->center2[0];
+ poly[5] = arcPtr->center2[1];
+ polyDist = TkPolygonToPoint(poly, 4, pointPtr);
+ if (angleInRange) {
+ if ((arcPtr->extent < -180.0) || (arcPtr->extent > 180.0)
+ || (polyDist > 0.0)) {
+ newDist = TkOvalToPoint(arcPtr->bbox, width, filled, pointPtr);
+ if (newDist < dist) {
+ dist = newDist;
+ }
+ }
+ } else {
+ if ((arcPtr->extent < -180.0) || (arcPtr->extent > 180.0)) {
+ if (filled && (polyDist < dist)) {
+ dist = polyDist;
+ }
+ }
+ }
+ return dist;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ArcToArea --
+ *
+ * This function is called to determine whether an item lies entirely
+ * inside, entirely outside, or overlapping a given area.
+ *
+ * Results:
+ * -1 is returned if the item is entirely outside the area given by
+ * rectPtr, 0 if it overlaps, and 1 if it is entirely inside the given
+ * area.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+ArcToArea(
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item to check against arc. */
+ double *rectPtr) /* Pointer to array of four coordinates (x1,
+ * y1, x2, y2) describing rectangular area. */
+{
+ ArcItem *arcPtr = (ArcItem *) itemPtr;
+ double rx, ry; /* Radii for transformed oval: these define an
+ * oval centered at the origin. */
+ double tRect[4]; /* Transformed version of x1, y1, x2, y2, for
+ * coord. system where arc is centered on the
+ * origin. */
+ double center[2], width, angle, tmp;
+ double points[20], *pointPtr;
+ int numPoints, filled;
+ int inside; /* Non-zero means every test so far suggests
+ * that arc is inside rectangle. 0 means every
+ * test so far shows arc to be outside of
+ * rectangle. */
+ int newInside;
+ Tk_State state = itemPtr->state;
+
+ if(state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+ width = (double) arcPtr->outline.width;
+ if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (arcPtr->outline.activeWidth>width) {
+ width = (double) arcPtr->outline.activeWidth;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (arcPtr->outline.disabledWidth>0) {
+ width = (double) arcPtr->outline.disabledWidth;
+ }
+ }
+
+ if ((arcPtr->fillGC != NULL) || (arcPtr->outline.gc == NULL)) {
+ filled = 1;
+ } else {
+ filled = 0;
+ }
+ if (arcPtr->outline.gc == NULL) {
+ width = 0.0;
+ }
+
+ /*
+ * Transform both the arc and the rectangle so that the arc's oval is
+ * centered on the origin.
+ */
+
+ center[0] = (arcPtr->bbox[0] + arcPtr->bbox[2])/2.0;
+ center[1] = (arcPtr->bbox[1] + arcPtr->bbox[3])/2.0;
+ tRect[0] = rectPtr[0] - center[0];
+ tRect[1] = rectPtr[1] - center[1];
+ tRect[2] = rectPtr[2] - center[0];
+ tRect[3] = rectPtr[3] - center[1];
+ rx = arcPtr->bbox[2] - center[0] + width/2.0;
+ ry = arcPtr->bbox[3] - center[1] + width/2.0;
+
+ /*
+ * Find the extreme points of the arc and see whether these are all inside
+ * the rectangle (in which case we're done), partly in and partly out (in
+ * which case we're done), or all outside (in which case we have more work
+ * to do). The extreme points include the following, which are checked in
+ * order:
+ *
+ * 1. The outside points of the arc, corresponding to start and extent.
+ * 2. The center of the arc (but only in pie-slice mode).
+ * 3. The 12, 3, 6, and 9-o'clock positions (but only if the arc includes
+ * those angles).
+ */
+
+ pointPtr = points;
+ angle = -arcPtr->start*(PI/180.0);
+ pointPtr[0] = rx*cos(angle);
+ pointPtr[1] = ry*sin(angle);
+ angle += -arcPtr->extent*(PI/180.0);
+ pointPtr[2] = rx*cos(angle);
+ pointPtr[3] = ry*sin(angle);
+ numPoints = 2;
+ pointPtr += 4;
+
+ if ((arcPtr->style == PIESLICE_STYLE) && (arcPtr->extent < 180.0)) {
+ pointPtr[0] = 0.0;
+ pointPtr[1] = 0.0;
+ numPoints++;
+ pointPtr += 2;
+ }
+
+ tmp = -arcPtr->start;
+ if (tmp < 0) {
+ tmp += 360.0;
+ }
+ if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {
+ pointPtr[0] = rx;
+ pointPtr[1] = 0.0;
+ numPoints++;
+ pointPtr += 2;
+ }
+ tmp = 90.0 - arcPtr->start;
+ if (tmp < 0) {
+ tmp += 360.0;
+ }
+ if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {
+ pointPtr[0] = 0.0;
+ pointPtr[1] = -ry;
+ numPoints++;
+ pointPtr += 2;
+ }
+ tmp = 180.0 - arcPtr->start;
+ if (tmp < 0) {
+ tmp += 360.0;
+ }
+ if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {
+ pointPtr[0] = -rx;
+ pointPtr[1] = 0.0;
+ numPoints++;
+ pointPtr += 2;
+ }
+ tmp = 270.0 - arcPtr->start;
+ if (tmp < 0) {
+ tmp += 360.0;
+ }
+ if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {
+ pointPtr[0] = 0.0;
+ pointPtr[1] = ry;
+ numPoints++;
+ }
+
+ /*
+ * Now that we've located the extreme points, loop through them all to see
+ * which are inside the rectangle.
+ */
+
+ inside = (points[0] > tRect[0]) && (points[0] < tRect[2])
+ && (points[1] > tRect[1]) && (points[1] < tRect[3]);
+ for (pointPtr = points+2; numPoints > 1; pointPtr += 2, numPoints--) {
+ newInside = (pointPtr[0] > tRect[0]) && (pointPtr[0] < tRect[2])
+ && (pointPtr[1] > tRect[1]) && (pointPtr[1] < tRect[3]);
+ if (newInside != inside) {
+ return 0;
+ }
+ }
+
+ if (inside) {
+ return 1;
+ }
+
+ /*
+ * So far, oval appears to be outside rectangle, but can't yet tell for
+ * sure. Next, test each of the four sides of the rectangle against the
+ * bounding region for the arc. If any intersections are found, then
+ * return "overlapping". First, test against the polygon(s) forming the
+ * sides of a chord or pie-slice.
+ */
+
+ if (arcPtr->style == PIESLICE_STYLE) {
+ if (width >= 1.0) {
+ if (TkPolygonToArea(arcPtr->outlinePtr, PIE_OUTLINE1_PTS,
+ rectPtr) != -1) {
+ return 0;
+ }
+ if (TkPolygonToArea(arcPtr->outlinePtr + 2*PIE_OUTLINE1_PTS,
+ PIE_OUTLINE2_PTS, rectPtr) != -1) {
+ return 0;
+ }
+ } else {
+ if ((TkLineToArea(center, arcPtr->center1, rectPtr) != -1) ||
+ (TkLineToArea(center, arcPtr->center2, rectPtr) != -1)) {
+ return 0;
+ }
+ }
+ } else if (arcPtr->style == CHORD_STYLE) {
+ if (width >= 1.0) {
+ if (TkPolygonToArea(arcPtr->outlinePtr, CHORD_OUTLINE_PTS,
+ rectPtr) != -1) {
+ return 0;
+ }
+ } else {
+ if (TkLineToArea(arcPtr->center1, arcPtr->center2,
+ rectPtr) != -1) {
+ return 0;
+ }
+ }
+ }
+
+ /*
+ * Next check for overlap between each of the four sides and the outer
+ * perimiter of the arc. If the arc isn't filled, then also check the
+ * inner perimeter of the arc.
+ */
+
+ if (HorizLineToArc(tRect[0], tRect[2], tRect[1], rx, ry, arcPtr->start,
+ arcPtr->extent)
+ || HorizLineToArc(tRect[0], tRect[2], tRect[3], rx, ry,
+ arcPtr->start, arcPtr->extent)
+ || VertLineToArc(tRect[0], tRect[1], tRect[3], rx, ry,
+ arcPtr->start, arcPtr->extent)
+ || VertLineToArc(tRect[2], tRect[1], tRect[3], rx, ry,
+ arcPtr->start, arcPtr->extent)) {
+ return 0;
+ }
+ if ((width > 1.0) && !filled) {
+ rx -= width;
+ ry -= width;
+ if (HorizLineToArc(tRect[0], tRect[2], tRect[1], rx, ry, arcPtr->start,
+ arcPtr->extent)
+ || HorizLineToArc(tRect[0], tRect[2], tRect[3], rx, ry,
+ arcPtr->start, arcPtr->extent)
+ || VertLineToArc(tRect[0], tRect[1], tRect[3], rx, ry,
+ arcPtr->start, arcPtr->extent)
+ || VertLineToArc(tRect[2], tRect[1], tRect[3], rx, ry,
+ arcPtr->start, arcPtr->extent)) {
+ return 0;
+ }
+ }
+
+ /*
+ * The arc still appears to be totally disjoint from the rectangle, but
+ * it's also possible that the rectangle is totally inside the arc. Do one
+ * last check, which is to check one point of the rectangle to see if it's
+ * inside the arc. If it is, we've got overlap. If it isn't, the arc's
+ * really outside the rectangle.
+ */
+
+ if (ArcToPoint(canvas, itemPtr, rectPtr) == 0.0) {
+ return 0;
+ }
+ return -1;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ScaleArc --
+ *
+ * This function is invoked to rescale an arc item.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The arc referred to by itemPtr is rescaled so that the following
+ * transformation is applied to all point coordinates:
+ * x' = originX + scaleX*(x-originX)
+ * y' = originY + scaleY*(y-originY)
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ScaleArc(
+ Tk_Canvas canvas, /* Canvas containing arc. */
+ Tk_Item *itemPtr, /* Arc to be scaled. */
+ double originX, /* Origin about which to scale rect. */
+ double originY,
+ double scaleX, /* Amount to scale in X direction. */
+ double scaleY) /* Amount to scale in Y direction. */
+{
+ ArcItem *arcPtr = (ArcItem *) itemPtr;
+
+ arcPtr->bbox[0] = originX + scaleX*(arcPtr->bbox[0] - originX);
+ arcPtr->bbox[1] = originY + scaleY*(arcPtr->bbox[1] - originY);
+ arcPtr->bbox[2] = originX + scaleX*(arcPtr->bbox[2] - originX);
+ arcPtr->bbox[3] = originY + scaleY*(arcPtr->bbox[3] - originY);
+ ComputeArcBbox(canvas, arcPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TranslateArc --
+ *
+ * This function is called to move an arc by a given amount.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The position of the arc is offset by (xDelta, yDelta), and the
+ * bounding box is updated in the generic part of the item structure.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+TranslateArc(
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item that is being moved. */
+ double deltaX, /* Amount by which item is to be moved. */
+ double deltaY)
+{
+ ArcItem *arcPtr = (ArcItem *) itemPtr;
+
+ arcPtr->bbox[0] += deltaX;
+ arcPtr->bbox[1] += deltaY;
+ arcPtr->bbox[2] += deltaX;
+ arcPtr->bbox[3] += deltaY;
+ ComputeArcBbox(canvas, arcPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ComputeArcOutline --
+ *
+ * This function creates a polygon describing everything in the outline
+ * for an arc except what's in the curved part. For a "pie slice" arc
+ * this is a V-shaped chunk, and for a "chord" arc this is a linear chunk
+ * (with cutaway corners). For "arc" arcs, this stuff isn't relevant.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The information at arcPtr->outlinePtr gets modified, and storage for
+ * arcPtr->outlinePtr may be allocated or freed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ComputeArcOutline(
+ Tk_Canvas canvas, /* Information about overall canvas. */
+ ArcItem *arcPtr) /* Information about arc. */
+{
+ double sin1, cos1, sin2, cos2, angle, width, halfWidth;
+ double boxWidth, boxHeight;
+ double vertex[2], corner1[2], corner2[2];
+ double *outlinePtr;
+ Tk_State state = arcPtr->header.state;
+
+ /*
+ * Make sure that the outlinePtr array is large enough to hold either a
+ * chord or pie-slice outline.
+ */
+
+ if (arcPtr->numOutlinePoints == 0) {
+ arcPtr->outlinePtr = ckalloc(26 * sizeof(double));
+ arcPtr->numOutlinePoints = 22;
+ }
+ outlinePtr = arcPtr->outlinePtr;
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+
+ /*
+ * First compute the two points that lie at the centers of the ends of the
+ * curved arc segment, which are marked with X's in the figure below:
+ *
+ *
+ * * * *
+ * * *
+ * * * * *
+ * * * * *
+ * * * * *
+ * X * * X
+ *
+ * The code is tricky because the arc can be ovular in shape. It computes
+ * the position for a unit circle, and then scales to fit the shape of the
+ * arc's bounding box.
+ *
+ * Also, watch out because angles go counter-clockwise like you might
+ * expect, but the y-coordinate system is inverted. To handle this, just
+ * negate the angles in all the computations.
+ */
+
+ boxWidth = arcPtr->bbox[2] - arcPtr->bbox[0];
+ boxHeight = arcPtr->bbox[3] - arcPtr->bbox[1];
+ angle = -arcPtr->start*PI/180.0;
+ sin1 = sin(angle);
+ cos1 = cos(angle);
+ angle -= arcPtr->extent*PI/180.0;
+ sin2 = sin(angle);
+ cos2 = cos(angle);
+ vertex[0] = (arcPtr->bbox[0] + arcPtr->bbox[2])/2.0;
+ vertex[1] = (arcPtr->bbox[1] + arcPtr->bbox[3])/2.0;
+ arcPtr->center1[0] = vertex[0] + cos1*boxWidth/2.0;
+ arcPtr->center1[1] = vertex[1] + sin1*boxHeight/2.0;
+ arcPtr->center2[0] = vertex[0] + cos2*boxWidth/2.0;
+ arcPtr->center2[1] = vertex[1] + sin2*boxHeight/2.0;
+
+ /*
+ * Next compute the "outermost corners" of the arc, which are marked with
+ * X's in the figure below:
+ *
+ * * * *
+ * * *
+ * * * * *
+ * * * * *
+ * X * * X
+ * * *
+ *
+ * The code below is tricky because it has to handle eccentricity in the
+ * shape of the oval. The key in the code below is to realize that the
+ * slope of the line from arcPtr->center1 to corner1 is (boxWidth*sin1)
+ * divided by (boxHeight*cos1), and similarly for arcPtr->center2 and
+ * corner2. These formulas can be computed from the formula for the oval.
+ */
+
+ width = arcPtr->outline.width;
+ if (Canvas(canvas)->currentItemPtr == (Tk_Item *) arcPtr) {
+ if (arcPtr->outline.activeWidth>arcPtr->outline.width) {
+ width = arcPtr->outline.activeWidth;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (arcPtr->outline.disabledWidth>arcPtr->outline.width) {
+ width = arcPtr->outline.disabledWidth;
+ }
+ }
+ halfWidth = width/2.0;
+
+ if (((boxWidth*sin1) == 0.0) && ((boxHeight*cos1) == 0.0)) {
+ angle = 0.0;
+ } else {
+ angle = atan2(boxWidth*sin1, boxHeight*cos1);
+ }
+ corner1[0] = arcPtr->center1[0] + cos(angle)*halfWidth;
+ corner1[1] = arcPtr->center1[1] + sin(angle)*halfWidth;
+ if (((boxWidth*sin2) == 0.0) && ((boxHeight*cos2) == 0.0)) {
+ angle = 0.0;
+ } else {
+ angle = atan2(boxWidth*sin2, boxHeight*cos2);
+ }
+ corner2[0] = arcPtr->center2[0] + cos(angle)*halfWidth;
+ corner2[1] = arcPtr->center2[1] + sin(angle)*halfWidth;
+
+ /*
+ * For a chord outline, generate a six-sided polygon with three points for
+ * each end of the chord. The first and third points for each end are butt
+ * points generated on either side of the center point. The second point
+ * is the corner point.
+ */
+
+ if (arcPtr->style == CHORD_STYLE) {
+ outlinePtr[0] = outlinePtr[12] = corner1[0];
+ outlinePtr[1] = outlinePtr[13] = corner1[1];
+ TkGetButtPoints(arcPtr->center2, arcPtr->center1,
+ width, 0, outlinePtr+10, outlinePtr+2);
+ outlinePtr[4] = arcPtr->center2[0] + outlinePtr[2]
+ - arcPtr->center1[0];
+ outlinePtr[5] = arcPtr->center2[1] + outlinePtr[3]
+ - arcPtr->center1[1];
+ outlinePtr[6] = corner2[0];
+ outlinePtr[7] = corner2[1];
+ outlinePtr[8] = arcPtr->center2[0] + outlinePtr[10]
+ - arcPtr->center1[0];
+ outlinePtr[9] = arcPtr->center2[1] + outlinePtr[11]
+ - arcPtr->center1[1];
+ } else if (arcPtr->style == PIESLICE_STYLE) {
+ /*
+ * For pie slices, generate two polygons, one for each side of the pie
+ * slice. The first arm has a shape like this, where the center of the
+ * oval is X, arcPtr->center1 is at Y, and corner1 is at Z:
+ *
+ * _____________________
+ * | \
+ * | \
+ * X Y Z
+ * | /
+ * |_____________________/
+ */
+
+ TkGetButtPoints(arcPtr->center1, vertex, width, 0,
+ outlinePtr, outlinePtr+2);
+ outlinePtr[4] = arcPtr->center1[0] + outlinePtr[2] - vertex[0];
+ outlinePtr[5] = arcPtr->center1[1] + outlinePtr[3] - vertex[1];
+ outlinePtr[6] = corner1[0];
+ outlinePtr[7] = corner1[1];
+ outlinePtr[8] = arcPtr->center1[0] + outlinePtr[0] - vertex[0];
+ outlinePtr[9] = arcPtr->center1[1] + outlinePtr[1] - vertex[1];
+ outlinePtr[10] = outlinePtr[0];
+ outlinePtr[11] = outlinePtr[1];
+
+ /*
+ * The second arm has a shape like this:
+ *
+ * ______________________
+ * / \
+ * / \
+ * Z Y X /
+ * \ /
+ * \______________________/
+ *
+ * Similar to above X is the center of the oval/circle, Y is
+ * arcPtr->center2, and Z is corner2. The extra jog out to the left of
+ * X is needed in or to produce a butted joint with the first arm; the
+ * corner to the right of X is one of the first two points of the
+ * first arm, depending on extent.
+ */
+
+ TkGetButtPoints(arcPtr->center2, vertex, width, 0,
+ outlinePtr+12, outlinePtr+16);
+ if ((arcPtr->extent > 180) ||
+ ((arcPtr->extent < 0) && (arcPtr->extent > -180))) {
+ outlinePtr[14] = outlinePtr[0];
+ outlinePtr[15] = outlinePtr[1];
+ } else {
+ outlinePtr[14] = outlinePtr[2];
+ outlinePtr[15] = outlinePtr[3];
+ }
+ outlinePtr[18] = arcPtr->center2[0] + outlinePtr[16] - vertex[0];
+ outlinePtr[19] = arcPtr->center2[1] + outlinePtr[17] - vertex[1];
+ outlinePtr[20] = corner2[0];
+ outlinePtr[21] = corner2[1];
+ outlinePtr[22] = arcPtr->center2[0] + outlinePtr[12] - vertex[0];
+ outlinePtr[23] = arcPtr->center2[1] + outlinePtr[13] - vertex[1];
+ outlinePtr[24] = outlinePtr[12];
+ outlinePtr[25] = outlinePtr[13];
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * HorizLineToArc --
+ *
+ * Determines whether a horizontal line segment intersects a given arc.
+ *
+ * Results:
+ * The return value is 1 if the given line intersects the infinitely-thin
+ * arc section defined by rx, ry, start, and extent, and 0 otherwise.
+ * Only the perimeter of the arc is checked: interior areas (e.g. chord
+ * or pie-slice) are not checked.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+HorizLineToArc(
+ double x1, double x2, /* X-coords of endpoints of line segment. X1
+ * must be <= x2. */
+ double y, /* Y-coordinate of line segment. */
+ double rx, double ry, /* These x- and y-radii define an oval
+ * centered at the origin. */
+ double start, double extent)/* Angles that define extent of arc, in the
+ * standard fashion for this module. */
+{
+ double tmp, x;
+ double tx, ty; /* Coordinates of intersection point in
+ * transformed coordinate system. */
+
+ /*
+ * Compute the x-coordinate of one possible intersection point between the
+ * arc and the line. Use a transformed coordinate system where the oval is
+ * a unit circle centered at the origin. Then scale back to get actual
+ * x-coordinate.
+ */
+
+ ty = y/ry;
+ tmp = 1 - ty*ty;
+ if (tmp < 0) {
+ return 0;
+ }
+ tx = sqrt(tmp);
+ x = tx*rx;
+
+ /*
+ * Test both intersection points.
+ */
+
+ if ((x >= x1) && (x <= x2) && AngleInRange(tx, ty, start, extent)) {
+ return 1;
+ }
+ if ((-x >= x1) && (-x <= x2) && AngleInRange(-tx, ty, start, extent)) {
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * VertLineToArc --
+ *
+ * Determines whether a vertical line segment intersects a given arc.
+ *
+ * Results:
+ * The return value is 1 if the given line intersects the infinitely-thin
+ * arc section defined by rx, ry, start, and extent, and 0 otherwise.
+ * Only the perimeter of the arc is checked: interior areas (e.g. chord
+ * or pie-slice) are not checked.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+VertLineToArc(
+ double x, /* X-coordinate of line segment. */
+ double y1, double y2, /* Y-coords of endpoints of line segment. Y1
+ * must be <= y2. */
+ double rx, double ry, /* These x- and y-radii define an oval
+ * centered at the origin. */
+ double start, double extent)/* Angles that define extent of arc, in the
+ * standard fashion for this module. */
+{
+ double tmp, y;
+ double tx, ty; /* Coordinates of intersection point in
+ * transformed coordinate system. */
+
+ /*
+ * Compute the y-coordinate of one possible intersection point between the
+ * arc and the line. Use a transformed coordinate system where the oval is
+ * a unit circle centered at the origin. Then scale back to get actual
+ * y-coordinate.
+ */
+
+ tx = x/rx;
+ tmp = 1 - tx*tx;
+ if (tmp < 0) {
+ return 0;
+ }
+ ty = sqrt(tmp);
+ y = ty*ry;
+
+ /*
+ * Test both intersection points.
+ */
+
+ if ((y > y1) && (y < y2) && AngleInRange(tx, ty, start, extent)) {
+ return 1;
+ }
+ if ((-y > y1) && (-y < y2) && AngleInRange(tx, -ty, start, extent)) {
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * AngleInRange --
+ *
+ * Determine whether the angle from the origin to a given point is within
+ * a given range.
+ *
+ * Results:
+ * The return value is 1 if the angle from (0,0) to (x,y) is in the range
+ * given by start and extent, where angles are interpreted in the
+ * standard way for ovals (meaning backwards from normal interpretation).
+ * Otherwise the return value is 0.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+AngleInRange(
+ double x, double y, /* Coordinate of point; angle measured from
+ * origin to here, relative to x-axis. */
+ double start, /* First angle, degrees, >=0, <=360. */
+ double extent) /* Size of arc in degrees >=-360, <=360. */
+{
+ double diff;
+
+ if ((x == 0.0) && (y == 0.0)) {
+ return 1;
+ }
+ diff = -atan2(y, x);
+ diff = diff*(180.0/PI) - start;
+ while (diff > 360.0) {
+ diff -= 360.0;
+ }
+ while (diff < 0.0) {
+ diff += 360.0;
+ }
+ if (extent >= 0) {
+ return diff <= extent;
+ }
+ return (diff-360.0) >= extent;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ArcToPostscript --
+ *
+ * This function is called to generate Postscript for arc items.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If an error occurs in
+ * generating Postscript then an error message is left in the interp's
+ * result, replacing whatever used to be there. If no error occurs, then
+ * Postscript for the item is appended to the result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+ArcToPostscript(
+ Tcl_Interp *interp, /* Leave Postscript or error message here. */
+ Tk_Canvas canvas, /* Information about overall canvas. */
+ Tk_Item *itemPtr, /* Item for which Postscript is wanted. */
+ int prepass) /* 1 means this is a prepass to collect font
+ * information; 0 means final Postscript is
+ * being created. */
+{
+ ArcItem *arcPtr = (ArcItem *) itemPtr;
+ double y1, y2, ang1, ang2;
+ XColor *color;
+ Pixmap stipple;
+ XColor *fillColor;
+ Pixmap fillStipple;
+ Tk_State state = itemPtr->state;
+ Tcl_Obj *psObj;
+ Tcl_InterpState interpState;
+
+ y1 = Tk_CanvasPsY(canvas, arcPtr->bbox[1]);
+ y2 = Tk_CanvasPsY(canvas, arcPtr->bbox[3]);
+ ang1 = arcPtr->start;
+ ang2 = ang1 + arcPtr->extent;
+ if (ang2 < ang1) {
+ ang1 = ang2;
+ ang2 = arcPtr->start;
+ }
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+ color = arcPtr->outline.color;
+ stipple = arcPtr->outline.stipple;
+ fillColor = arcPtr->fillColor;
+ fillStipple = arcPtr->fillStipple;
+ if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (arcPtr->outline.activeColor!=NULL) {
+ color = arcPtr->outline.activeColor;
+ }
+ if (arcPtr->outline.activeStipple!=None) {
+ stipple = arcPtr->outline.activeStipple;
+ }
+ if (arcPtr->activeFillColor!=NULL) {
+ fillColor = arcPtr->activeFillColor;
+ }
+ if (arcPtr->activeFillStipple!=None) {
+ fillStipple = arcPtr->activeFillStipple;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (arcPtr->outline.disabledColor!=NULL) {
+ color = arcPtr->outline.disabledColor;
+ }
+ if (arcPtr->outline.disabledStipple!=None) {
+ stipple = arcPtr->outline.disabledStipple;
+ }
+ if (arcPtr->disabledFillColor!=NULL) {
+ fillColor = arcPtr->disabledFillColor;
+ }
+ if (arcPtr->disabledFillStipple!=None) {
+ fillStipple = arcPtr->disabledFillStipple;
+ }
+ }
+
+ /*
+ * Make our working space.
+ */
+
+ psObj = Tcl_NewObj();
+ interpState = Tcl_SaveInterpState(interp, TCL_OK);
+
+ /*
+ * If the arc is filled, output Postscript for the interior region of the
+ * arc.
+ */
+
+ if (arcPtr->fillGC != NULL) {
+ Tcl_AppendPrintfToObj(psObj,
+ "matrix currentmatrix\n"
+ "%.15g %.15g translate %.15g %.15g scale\n",
+ (arcPtr->bbox[0] + arcPtr->bbox[2])/2, (y1 + y2)/2,
+ (arcPtr->bbox[2] - arcPtr->bbox[0])/2, (y1 - y2)/2);
+
+ if (arcPtr->style != CHORD_STYLE) {
+ Tcl_AppendToObj(psObj, "0 0 moveto ", -1);
+ }
+ Tcl_AppendPrintfToObj(psObj,
+ "0 0 1 %.15g %.15g arc closepath\nsetmatrix\n",
+ ang1, ang2);
+
+ Tcl_ResetResult(interp);
+ if (Tk_CanvasPsColor(interp, canvas, fillColor) != TCL_OK) {
+ goto error;
+ }
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+
+ if (fillStipple != None) {
+ Tcl_AppendToObj(psObj, "clip ", -1);
+
+ Tcl_ResetResult(interp);
+ if (Tk_CanvasPsStipple(interp, canvas, fillStipple) != TCL_OK) {
+ goto error;
+ }
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+
+ if (arcPtr->outline.gc != NULL) {
+ Tcl_AppendToObj(psObj, "grestore gsave\n", -1);
+ }
+ } else {
+ Tcl_AppendToObj(psObj, "fill\n", -1);
+ }
+ }
+
+ /*
+ * If there's an outline for the arc, draw it.
+ */
+
+ if (arcPtr->outline.gc != NULL) {
+ Tcl_AppendPrintfToObj(psObj,
+ "matrix currentmatrix\n"
+ "%.15g %.15g translate %.15g %.15g scale\n",
+ (arcPtr->bbox[0] + arcPtr->bbox[2])/2, (y1 + y2)/2,
+ (arcPtr->bbox[2] - arcPtr->bbox[0])/2, (y1 - y2)/2);
+ Tcl_AppendPrintfToObj(psObj,
+ "0 0 1 %.15g %.15g arc\nsetmatrix\n0 setlinecap\n",
+ ang1, ang2);
+
+ Tcl_ResetResult(interp);
+ if (Tk_CanvasPsOutline(canvas, itemPtr, &arcPtr->outline) != TCL_OK) {
+ goto error;
+ }
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+
+ if (arcPtr->style != ARC_STYLE) {
+ Tcl_AppendToObj(psObj, "grestore gsave\n", -1);
+
+ Tcl_ResetResult(interp);
+ if (arcPtr->style == CHORD_STYLE) {
+ Tk_CanvasPsPath(interp, canvas, arcPtr->outlinePtr,
+ CHORD_OUTLINE_PTS);
+ } else {
+ Tk_CanvasPsPath(interp, canvas, arcPtr->outlinePtr,
+ PIE_OUTLINE1_PTS);
+ if (Tk_CanvasPsColor(interp, canvas, color) != TCL_OK) {
+ goto error;
+ }
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+
+ if (stipple != None) {
+ Tcl_AppendToObj(psObj, "clip ", -1);
+
+ Tcl_ResetResult(interp);
+ if (Tk_CanvasPsStipple(interp, canvas, stipple) !=TCL_OK){
+ goto error;
+ }
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+ } else {
+ Tcl_AppendToObj(psObj, "fill\n", -1);
+ }
+ Tcl_AppendToObj(psObj, "grestore gsave\n", -1);
+
+ Tcl_ResetResult(interp);
+ Tk_CanvasPsPath(interp, canvas,
+ arcPtr->outlinePtr + 2*PIE_OUTLINE1_PTS,
+ PIE_OUTLINE2_PTS);
+ }
+ if (Tk_CanvasPsColor(interp, canvas, color) != TCL_OK) {
+ goto error;
+ }
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+
+ if (stipple != None) {
+ Tcl_AppendToObj(psObj, "clip ", -1);
+
+ Tcl_ResetResult(interp);
+ if (Tk_CanvasPsStipple(interp, canvas, stipple) != TCL_OK) {
+ goto error;
+ }
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+ } else {
+ Tcl_AppendToObj(psObj, "fill\n", -1);
+ }
+ }
+ }
+
+ /*
+ * Plug the accumulated postscript back into the result.
+ */
+
+ (void) Tcl_RestoreInterpState(interp, interpState);
+ Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj);
+ Tcl_DecrRefCount(psObj);
+ return TCL_OK;
+
+ error:
+ Tcl_DiscardInterpState(interpState);
+ Tcl_DecrRefCount(psObj);
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * StyleParseProc --
+ *
+ * This function is invoked during option processing to handle the
+ * "-style" option.
+ *
+ * Results:
+ * A standard Tcl return value.
+ *
+ * Side effects:
+ * The state for a given item gets replaced by the state indicated in the
+ * value argument.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+StyleParseProc(
+ ClientData clientData, /* some flags.*/
+ Tcl_Interp *interp, /* Used for reporting errors. */
+ Tk_Window tkwin, /* Window containing canvas widget. */
+ const char *value, /* Value of option. */
+ char *widgRec, /* Pointer to record for item. */
+ int offset) /* Offset into item. */
+{
+ int c;
+ size_t length;
+
+ register Style *stylePtr = (Style *) (widgRec + offset);
+
+ if (value == NULL || *value == 0) {
+ *stylePtr = PIESLICE_STYLE;
+ return TCL_OK;
+ }
+
+ c = value[0];
+ length = strlen(value);
+
+ if ((c == 'a') && (strncmp(value, "arc", length) == 0)) {
+ *stylePtr = ARC_STYLE;
+ return TCL_OK;
+ }
+ if ((c == 'c') && (strncmp(value, "chord", length) == 0)) {
+ *stylePtr = CHORD_STYLE;
+ return TCL_OK;
+ }
+ if ((c == 'p') && (strncmp(value, "pieslice", length) == 0)) {
+ *stylePtr = PIESLICE_STYLE;
+ return TCL_OK;
+ }
+
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad -style option \"%s\": must be arc, chord, or pieslice",
+ value));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "ARC_STYLE", NULL);
+ *stylePtr = PIESLICE_STYLE;
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * StylePrintProc --
+ *
+ * This function is invoked by the Tk configuration code to produce a
+ * printable string for the "-style" configuration option.
+ *
+ * Results:
+ * The return value is a string describing the state for the item
+ * referred to by "widgRec". In addition, *freeProcPtr is filled in with
+ * the address of a function to call to free the result string when it's
+ * no longer needed (or NULL to indicate that the string doesn't need to
+ * be freed).
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static const char *
+StylePrintProc(
+ ClientData clientData, /* Ignored. */
+ Tk_Window tkwin, /* Ignored. */
+ char *widgRec, /* Pointer to record for item. */
+ int offset, /* Offset into item. */
+ Tcl_FreeProc **freeProcPtr) /* Pointer to variable to fill in with
+ * information about how to reclaim storage
+ * for return string. */
+{
+ register Style *stylePtr = (Style *) (widgRec + offset);
+
+ if (*stylePtr == ARC_STYLE) {
+ return "arc";
+ } else if (*stylePtr == CHORD_STYLE) {
+ return "chord";
+ } else {
+ return "pieslice";
+ }
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkCanvBmap.c b/tk8.6/generic/tkCanvBmap.c
new file mode 100644
index 0000000..b9de07b
--- /dev/null
+++ b/tk8.6/generic/tkCanvBmap.c
@@ -0,0 +1,1010 @@
+/*
+ * tkCanvBmap.c --
+ *
+ * This file implements bitmap items for canvas widgets.
+ *
+ * Copyright (c) 1992-1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "tkInt.h"
+#include "tkCanvas.h"
+
+/*
+ * The structure below defines the record for each bitmap item.
+ */
+
+typedef struct BitmapItem {
+ Tk_Item header; /* Generic stuff that's the same for all
+ * types. MUST BE FIRST IN STRUCTURE. */
+ double x, y; /* Coordinates of positioning point for
+ * bitmap. */
+ Tk_Anchor anchor; /* Where to anchor bitmap relative to (x,y) */
+ Pixmap bitmap; /* Bitmap to display in window. */
+ Pixmap activeBitmap; /* Bitmap to display in window. */
+ Pixmap disabledBitmap; /* Bitmap to display in window. */
+ XColor *fgColor; /* Foreground color to use for bitmap. */
+ XColor *activeFgColor; /* Foreground color to use for bitmap. */
+ XColor *disabledFgColor; /* Foreground color to use for bitmap. */
+ XColor *bgColor; /* Background color to use for bitmap. */
+ XColor *activeBgColor; /* Background color to use for bitmap. */
+ XColor *disabledBgColor; /* Background color to use for bitmap. */
+ GC gc; /* Graphics context to use for drawing bitmap
+ * on screen. */
+} BitmapItem;
+
+/*
+ * Information used for parsing configuration specs:
+ */
+
+static const Tk_CustomOption stateOption = {
+ TkStateParseProc, TkStatePrintProc, INT2PTR(2)
+};
+static const Tk_CustomOption tagsOption = {
+ Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL
+};
+
+static const Tk_ConfigSpec configSpecs[] = {
+ {TK_CONFIG_COLOR, "-activebackground", NULL, NULL,
+ NULL, Tk_Offset(BitmapItem, activeBgColor), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_BITMAP, "-activebitmap", NULL, NULL,
+ NULL, Tk_Offset(BitmapItem, activeBitmap), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_COLOR, "-activeforeground", NULL, NULL,
+ NULL, Tk_Offset(BitmapItem, activeFgColor), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_ANCHOR, "-anchor", NULL, NULL,
+ "center", Tk_Offset(BitmapItem, anchor), TK_CONFIG_DONT_SET_DEFAULT, NULL},
+ {TK_CONFIG_COLOR, "-background", NULL, NULL,
+ NULL, Tk_Offset(BitmapItem, bgColor), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_BITMAP, "-bitmap", NULL, NULL,
+ NULL, Tk_Offset(BitmapItem, bitmap), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_COLOR, "-disabledbackground", NULL, NULL,
+ NULL, Tk_Offset(BitmapItem, disabledBgColor),
+ TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_BITMAP, "-disabledbitmap", NULL, NULL,
+ NULL, Tk_Offset(BitmapItem, disabledBitmap),
+ TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_COLOR, "-disabledforeground", NULL, NULL,
+ NULL, Tk_Offset(BitmapItem, disabledFgColor),
+ TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_COLOR, "-foreground", NULL, NULL,
+ "black", Tk_Offset(BitmapItem, fgColor), 0, NULL},
+ {TK_CONFIG_CUSTOM, "-state", NULL, NULL,
+ NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK,
+ &stateOption},
+ {TK_CONFIG_CUSTOM, "-tags", NULL, NULL,
+ NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
+ {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}
+};
+
+/*
+ * Prototypes for functions defined in this file:
+ */
+
+static int BitmapCoords(Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr, int objc,
+ Tcl_Obj *const objv[]);
+static int BitmapToArea(Tk_Canvas canvas,
+ Tk_Item *itemPtr, double *rectPtr);
+static double BitmapToPoint(Tk_Canvas canvas,
+ Tk_Item *itemPtr, double *coordPtr);
+static int BitmapToPostscript(Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr, int prepass);
+static void ComputeBitmapBbox(Tk_Canvas canvas,
+ BitmapItem *bmapPtr);
+static int ConfigureBitmap(Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr, int objc,
+ Tcl_Obj *const objv[], int flags);
+static int TkcCreateBitmap(Tcl_Interp *interp,
+ Tk_Canvas canvas, struct Tk_Item *itemPtr,
+ int objc, Tcl_Obj *const objv[]);
+static void DeleteBitmap(Tk_Canvas canvas,
+ Tk_Item *itemPtr, Display *display);
+static void DisplayBitmap(Tk_Canvas canvas,
+ Tk_Item *itemPtr, Display *display, Drawable dst,
+ int x, int y, int width, int height);
+static void ScaleBitmap(Tk_Canvas canvas,
+ Tk_Item *itemPtr, double originX, double originY,
+ double scaleX, double scaleY);
+static void TranslateBitmap(Tk_Canvas canvas, Tk_Item *itemPtr,
+ double deltaX, double deltaY);
+
+/*
+ * The structures below defines the bitmap item type in terms of functions
+ * that can be invoked by generic item code.
+ */
+
+Tk_ItemType tkBitmapType = {
+ "bitmap", /* name */
+ sizeof(BitmapItem), /* itemSize */
+ TkcCreateBitmap, /* createProc */
+ configSpecs, /* configSpecs */
+ ConfigureBitmap, /* configureProc */
+ BitmapCoords, /* coordProc */
+ DeleteBitmap, /* deleteProc */
+ DisplayBitmap, /* displayProc */
+ TK_CONFIG_OBJS, /* flags */
+ BitmapToPoint, /* pointProc */
+ BitmapToArea, /* areaProc */
+ BitmapToPostscript, /* postscriptProc */
+ ScaleBitmap, /* scaleProc */
+ TranslateBitmap, /* translateProc */
+ NULL, /* indexProc */
+ NULL, /* icursorProc */
+ NULL, /* selectionProc */
+ NULL, /* insertProc */
+ NULL, /* dTextProc */
+ NULL, /* nextPtr */
+ NULL, 0, NULL, NULL
+};
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkcCreateBitmap --
+ *
+ * This function is invoked to create a new bitmap item in a canvas.
+ *
+ * Results:
+ * A standard Tcl return value. If an error occurred in creating the
+ * item, then an error message is left in the interp's result; in this
+ * case itemPtr is left uninitialized, so it can be safely freed by the
+ * caller.
+ *
+ * Side effects:
+ * A new bitmap item is created.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+TkcCreateBitmap(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Tk_Canvas canvas, /* Canvas to hold new item. */
+ Tk_Item *itemPtr, /* Record to hold new item; header has been
+ * initialized by caller. */
+ int objc, /* Number of arguments in objv. */
+ Tcl_Obj *const objv[]) /* Arguments describing rectangle. */
+{
+ BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
+ int i;
+
+ if (objc == 0) {
+ Tcl_Panic("canvas did not pass any coords");
+ }
+
+ /*
+ * Initialize item's record.
+ */
+
+ bmapPtr->anchor = TK_ANCHOR_CENTER;
+ bmapPtr->bitmap = None;
+ bmapPtr->activeBitmap = None;
+ bmapPtr->disabledBitmap = None;
+ bmapPtr->fgColor = NULL;
+ bmapPtr->activeFgColor = NULL;
+ bmapPtr->disabledFgColor = NULL;
+ bmapPtr->bgColor = NULL;
+ bmapPtr->activeBgColor = NULL;
+ bmapPtr->disabledBgColor = NULL;
+ bmapPtr->gc = NULL;
+
+ /*
+ * Process the arguments to fill in the item record. Only 1 (list) or 2 (x
+ * y) coords are allowed.
+ */
+
+ if (objc == 1) {
+ i = 1;
+ } else {
+ const char *arg = Tcl_GetString(objv[1]);
+ i = 2;
+ if ((arg[0] == '-') && (arg[1] >= 'a') && (arg[1] <= 'z')) {
+ i = 1;
+ }
+ }
+ if (BitmapCoords(interp, canvas, itemPtr, i, objv) != TCL_OK) {
+ goto error;
+ }
+ if (ConfigureBitmap(interp, canvas, itemPtr, objc-i, objv+i, 0)
+ == TCL_OK) {
+ return TCL_OK;
+ }
+
+ error:
+ DeleteBitmap(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * BitmapCoords --
+ *
+ * This function is invoked to process the "coords" widget command on
+ * bitmap items. See the user documentation for details on what it does.
+ *
+ * Results:
+ * Returns TCL_OK or TCL_ERROR, and sets the interp's result.
+ *
+ * Side effects:
+ * The coordinates for the given item may be changed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+BitmapCoords(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item whose coordinates are to be read or
+ * modified. */
+ int objc, /* Number of coordinates supplied in objv. */
+ Tcl_Obj *const objv[]) /* Array of coordinates: x1, y1, x2, y2, ... */
+{
+ BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
+
+ if (objc == 0) {
+ Tcl_Obj *obj = Tcl_NewObj();
+
+ Tcl_ListObjAppendElement(NULL, obj, Tcl_NewDoubleObj(bmapPtr->x));
+ Tcl_ListObjAppendElement(NULL, obj, Tcl_NewDoubleObj(bmapPtr->y));
+ Tcl_SetObjResult(interp, obj);
+ } else if (objc < 3) {
+ if (objc == 1) {
+ if (Tcl_ListObjGetElements(interp, objv[0], &objc,
+ (Tcl_Obj ***) &objv) != TCL_OK) {
+ return TCL_ERROR;
+ } else if (objc != 2) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "wrong # coordinates: expected 2, got %d", objc));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "COORDS", "BITMAP",
+ NULL);
+ return TCL_ERROR;
+ }
+ }
+ if ((Tk_CanvasGetCoordFromObj(interp, canvas, objv[0],
+ &bmapPtr->x) != TCL_OK)
+ || (Tk_CanvasGetCoordFromObj(interp, canvas, objv[1],
+ &bmapPtr->y) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ ComputeBitmapBbox(canvas, bmapPtr);
+ } else {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "wrong # coordinates: expected 0 or 2, got %d", objc));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "COORDS", "BITMAP", NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ConfigureBitmap --
+ *
+ * This function is invoked to configure various aspects of a bitmap
+ * item, such as its anchor position.
+ *
+ * Results:
+ * A standard Tcl result code. If an error occurs, then an error message
+ * is left in the interp's result.
+ *
+ * Side effects:
+ * Configuration information may be set for itemPtr.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+ConfigureBitmap(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tk_Canvas canvas, /* Canvas containing itemPtr. */
+ Tk_Item *itemPtr, /* Bitmap item to reconfigure. */
+ int objc, /* Number of elements in objv. */
+ Tcl_Obj *const objv[], /* Arguments describing things to configure. */
+ int flags) /* Flags to pass to Tk_ConfigureWidget. */
+{
+ BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
+ XGCValues gcValues;
+ GC newGC;
+ Tk_Window tkwin;
+ unsigned long mask;
+ XColor *fgColor;
+ XColor *bgColor;
+ Pixmap bitmap;
+ Tk_State state;
+
+ tkwin = Tk_CanvasTkwin(canvas);
+ if (TCL_OK != Tk_ConfigureWidget(interp, tkwin, configSpecs, objc,
+ (const char **) objv, (char *) bmapPtr, flags|TK_CONFIG_OBJS)) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * A few of the options require additional processing, such as those that
+ * determine the graphics context.
+ */
+
+ state = itemPtr->state;
+
+ if (bmapPtr->activeFgColor!=NULL ||
+ bmapPtr->activeBgColor!=NULL ||
+ bmapPtr->activeBitmap!=None) {
+ itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;
+ } else {
+ itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;
+ }
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+ if (state == TK_STATE_HIDDEN) {
+ ComputeBitmapBbox(canvas, bmapPtr);
+ return TCL_OK;
+ }
+ fgColor = bmapPtr->fgColor;
+ bgColor = bmapPtr->bgColor;
+ bitmap = bmapPtr->bitmap;
+ if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (bmapPtr->activeFgColor!=NULL) {
+ fgColor = bmapPtr->activeFgColor;
+ }
+ if (bmapPtr->activeBgColor!=NULL) {
+ bgColor = bmapPtr->activeBgColor;
+ }
+ if (bmapPtr->activeBitmap!=None) {
+ bitmap = bmapPtr->activeBitmap;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (bmapPtr->disabledFgColor!=NULL) {
+ fgColor = bmapPtr->disabledFgColor;
+ }
+ if (bmapPtr->disabledBgColor!=NULL) {
+ bgColor = bmapPtr->disabledBgColor;
+ }
+ if (bmapPtr->disabledBitmap!=None) {
+ bitmap = bmapPtr->disabledBitmap;
+ }
+ }
+
+ if (bitmap == None) {
+ newGC = NULL;
+ } else {
+ gcValues.foreground = fgColor->pixel;
+ mask = GCForeground;
+ if (bgColor != NULL) {
+ gcValues.background = bgColor->pixel;
+ mask |= GCBackground;
+ } else {
+ gcValues.clip_mask = bitmap;
+ mask |= GCClipMask;
+ }
+ newGC = Tk_GetGC(tkwin, mask, &gcValues);
+ }
+ if (bmapPtr->gc != NULL) {
+ Tk_FreeGC(Tk_Display(tkwin), bmapPtr->gc);
+ }
+ bmapPtr->gc = newGC;
+
+ ComputeBitmapBbox(canvas, bmapPtr);
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DeleteBitmap --
+ *
+ * This function is called to clean up the data structure associated with
+ * a bitmap item.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Resources associated with itemPtr are released.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+DeleteBitmap(
+ Tk_Canvas canvas, /* Info about overall canvas widget. */
+ Tk_Item *itemPtr, /* Item that is being deleted. */
+ Display *display) /* Display containing window for canvas. */
+{
+ BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
+
+ if (bmapPtr->bitmap != None) {
+ Tk_FreeBitmap(display, bmapPtr->bitmap);
+ }
+ if (bmapPtr->activeBitmap != None) {
+ Tk_FreeBitmap(display, bmapPtr->activeBitmap);
+ }
+ if (bmapPtr->disabledBitmap != None) {
+ Tk_FreeBitmap(display, bmapPtr->disabledBitmap);
+ }
+ if (bmapPtr->fgColor != NULL) {
+ Tk_FreeColor(bmapPtr->fgColor);
+ }
+ if (bmapPtr->activeFgColor != NULL) {
+ Tk_FreeColor(bmapPtr->activeFgColor);
+ }
+ if (bmapPtr->disabledFgColor != NULL) {
+ Tk_FreeColor(bmapPtr->disabledFgColor);
+ }
+ if (bmapPtr->bgColor != NULL) {
+ Tk_FreeColor(bmapPtr->bgColor);
+ }
+ if (bmapPtr->activeBgColor != NULL) {
+ Tk_FreeColor(bmapPtr->activeBgColor);
+ }
+ if (bmapPtr->disabledBgColor != NULL) {
+ Tk_FreeColor(bmapPtr->disabledBgColor);
+ }
+ if (bmapPtr->gc != NULL) {
+ Tk_FreeGC(display, bmapPtr->gc);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ComputeBitmapBbox --
+ *
+ * This function is invoked to compute the bounding box of all the pixels
+ * that may be drawn as part of a bitmap item. This function is where the
+ * child bitmap's placement is computed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The fields x1, y1, x2, and y2 are updated in the header for itemPtr.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static void
+ComputeBitmapBbox(
+ Tk_Canvas canvas, /* Canvas that contains item. */
+ BitmapItem *bmapPtr) /* Item whose bbox is to be recomputed. */
+{
+ int width, height;
+ int x, y;
+ Pixmap bitmap;
+ Tk_State state = bmapPtr->header.state;
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+ bitmap = bmapPtr->bitmap;
+ if (Canvas(canvas)->currentItemPtr == (Tk_Item *)bmapPtr) {
+ if (bmapPtr->activeBitmap!=None) {
+ bitmap = bmapPtr->activeBitmap;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (bmapPtr->disabledBitmap!=None) {
+ bitmap = bmapPtr->disabledBitmap;
+ }
+ }
+
+ x = (int) (bmapPtr->x + ((bmapPtr->x >= 0) ? 0.5 : - 0.5));
+ y = (int) (bmapPtr->y + ((bmapPtr->y >= 0) ? 0.5 : - 0.5));
+
+ if (state==TK_STATE_HIDDEN || bitmap == None) {
+ bmapPtr->header.x1 = bmapPtr->header.x2 = x;
+ bmapPtr->header.y1 = bmapPtr->header.y2 = y;
+ return;
+ }
+
+ /*
+ * Compute location and size of bitmap, using anchor information.
+ */
+
+ Tk_SizeOfBitmap(Tk_Display(Tk_CanvasTkwin(canvas)), bitmap,
+ &width, &height);
+ switch (bmapPtr->anchor) {
+ case TK_ANCHOR_N:
+ x -= width/2;
+ break;
+ case TK_ANCHOR_NE:
+ x -= width;
+ break;
+ case TK_ANCHOR_E:
+ x -= width;
+ y -= height/2;
+ break;
+ case TK_ANCHOR_SE:
+ x -= width;
+ y -= height;
+ break;
+ case TK_ANCHOR_S:
+ x -= width/2;
+ y -= height;
+ break;
+ case TK_ANCHOR_SW:
+ y -= height;
+ break;
+ case TK_ANCHOR_W:
+ y -= height/2;
+ break;
+ case TK_ANCHOR_NW:
+ break;
+ case TK_ANCHOR_CENTER:
+ x -= width/2;
+ y -= height/2;
+ break;
+ }
+
+ /*
+ * Store the information in the item header.
+ */
+
+ bmapPtr->header.x1 = x;
+ bmapPtr->header.y1 = y;
+ bmapPtr->header.x2 = x + width;
+ bmapPtr->header.y2 = y + height;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DisplayBitmap --
+ *
+ * This function is invoked to draw a bitmap item in a given drawable.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * ItemPtr is drawn in drawable using the transformation information in
+ * canvas.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+DisplayBitmap(
+ Tk_Canvas canvas, /* Canvas that contains item. */
+ Tk_Item *itemPtr, /* Item to be displayed. */
+ Display *display, /* Display on which to draw item. */
+ Drawable drawable, /* Pixmap or window in which to draw item. */
+ int x, int y, int width, int height)
+ /* Describes region of canvas that must be
+ * redisplayed (not used). */
+{
+ BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
+ int bmapX, bmapY, bmapWidth, bmapHeight;
+ short drawableX, drawableY;
+ Pixmap bitmap;
+ Tk_State state = itemPtr->state;
+
+ /*
+ * If the area being displayed doesn't cover the whole bitmap, then only
+ * redisplay the part of the bitmap that needs redisplay.
+ */
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+ bitmap = bmapPtr->bitmap;
+ if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (bmapPtr->activeBitmap!=None) {
+ bitmap = bmapPtr->activeBitmap;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (bmapPtr->disabledBitmap!=None) {
+ bitmap = bmapPtr->disabledBitmap;
+ }
+ }
+
+ if (bitmap != None) {
+ if (x > bmapPtr->header.x1) {
+ bmapX = x - bmapPtr->header.x1;
+ bmapWidth = bmapPtr->header.x2 - x;
+ } else {
+ bmapX = 0;
+ if ((x+width) < bmapPtr->header.x2) {
+ bmapWidth = x + width - bmapPtr->header.x1;
+ } else {
+ bmapWidth = bmapPtr->header.x2 - bmapPtr->header.x1;
+ }
+ }
+ if (y > bmapPtr->header.y1) {
+ bmapY = y - bmapPtr->header.y1;
+ bmapHeight = bmapPtr->header.y2 - y;
+ } else {
+ bmapY = 0;
+ if ((y+height) < bmapPtr->header.y2) {
+ bmapHeight = y + height - bmapPtr->header.y1;
+ } else {
+ bmapHeight = bmapPtr->header.y2 - bmapPtr->header.y1;
+ }
+ }
+ Tk_CanvasDrawableCoords(canvas,
+ (double) (bmapPtr->header.x1 + bmapX),
+ (double) (bmapPtr->header.y1 + bmapY),
+ &drawableX, &drawableY);
+
+ /*
+ * Must modify the mask origin within the graphics context to line up
+ * with the bitmap's origin (in order to make bitmaps with
+ * "-background {}" work right).
+ */
+
+ XSetClipOrigin(display, bmapPtr->gc, drawableX - bmapX,
+ drawableY - bmapY);
+ XCopyPlane(display, bitmap, drawable,
+ bmapPtr->gc, bmapX, bmapY, (unsigned int) bmapWidth,
+ (unsigned int) bmapHeight, drawableX, drawableY, 1);
+ XSetClipOrigin(display, bmapPtr->gc, 0, 0);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * BitmapToPoint --
+ *
+ * Computes the distance from a given point to a given rectangle, in
+ * canvas units.
+ *
+ * Results:
+ * The return value is 0 if the point whose x and y coordinates are
+ * coordPtr[0] and coordPtr[1] is inside the bitmap. If the point isn't
+ * inside the bitmap then the return value is the distance from the point
+ * to the bitmap.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static double
+BitmapToPoint(
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item to check against point. */
+ double *coordPtr) /* Pointer to x and y coordinates. */
+{
+ BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
+ double x1, x2, y1, y2, xDiff, yDiff;
+
+ x1 = bmapPtr->header.x1;
+ y1 = bmapPtr->header.y1;
+ x2 = bmapPtr->header.x2;
+ y2 = bmapPtr->header.y2;
+
+ /*
+ * Point is outside rectangle.
+ */
+
+ if (coordPtr[0] < x1) {
+ xDiff = x1 - coordPtr[0];
+ } else if (coordPtr[0] > x2) {
+ xDiff = coordPtr[0] - x2;
+ } else {
+ xDiff = 0;
+ }
+
+ if (coordPtr[1] < y1) {
+ yDiff = y1 - coordPtr[1];
+ } else if (coordPtr[1] > y2) {
+ yDiff = coordPtr[1] - y2;
+ } else {
+ yDiff = 0;
+ }
+
+ return hypot(xDiff, yDiff);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * BitmapToArea --
+ *
+ * This function is called to determine whether an item lies entirely
+ * inside, entirely outside, or overlapping a given rectangle.
+ *
+ * Results:
+ * -1 is returned if the item is entirely outside the area given by
+ * rectPtr, 0 if it overlaps, and 1 if it is entirely inside the given
+ * area.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+BitmapToArea(
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item to check against rectangle. */
+ double *rectPtr) /* Pointer to array of four coordinates
+ * (x1,y1,x2,y2) describing rectangular
+ * area. */
+{
+ BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
+
+ if ((rectPtr[2] <= bmapPtr->header.x1)
+ || (rectPtr[0] >= bmapPtr->header.x2)
+ || (rectPtr[3] <= bmapPtr->header.y1)
+ || (rectPtr[1] >= bmapPtr->header.y2)) {
+ return -1;
+ }
+ if ((rectPtr[0] <= bmapPtr->header.x1)
+ && (rectPtr[1] <= bmapPtr->header.y1)
+ && (rectPtr[2] >= bmapPtr->header.x2)
+ && (rectPtr[3] >= bmapPtr->header.y2)) {
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ScaleBitmap --
+ *
+ * This function is invoked to rescale a bitmap item in a canvas. It is
+ * one of the standard item functions for bitmap items, and is invoked by
+ * the generic canvas code.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The item referred to by itemPtr is rescaled so that the following
+ * transformation is applied to all point coordinates:
+ * x' = originX + scaleX*(x-originX)
+ * y' = originY + scaleY*(y-originY)
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ScaleBitmap(
+ Tk_Canvas canvas, /* Canvas containing rectangle. */
+ Tk_Item *itemPtr, /* Rectangle to be scaled. */
+ double originX, double originY,
+ /* Origin about which to scale item. */
+ double scaleX, /* Amount to scale in X direction. */
+ double scaleY) /* Amount to scale in Y direction. */
+{
+ BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
+
+ bmapPtr->x = originX + scaleX*(bmapPtr->x - originX);
+ bmapPtr->y = originY + scaleY*(bmapPtr->y - originY);
+ ComputeBitmapBbox(canvas, bmapPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TranslateBitmap --
+ *
+ * This function is called to move an item by a given amount.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The position of the item is offset by (xDelta, yDelta), and the
+ * bounding box is updated in the generic part of the item structure.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+TranslateBitmap(
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item that is being moved. */
+ double deltaX, double deltaY)
+ /* Amount by which item is to be moved. */
+{
+ BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
+
+ bmapPtr->x += deltaX;
+ bmapPtr->y += deltaY;
+ ComputeBitmapBbox(canvas, bmapPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * BitmapToPostscript --
+ *
+ * This function is called to generate Postscript for bitmap items.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If an error occurs in
+ * generating Postscript then an error message is left in the interp's
+ * result, replacing whatever used to be there. If no error occurs, then
+ * Postscript for the item is appended to the result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+BitmapToPostscript(
+ Tcl_Interp *interp, /* Leave Postscript or error message here. */
+ Tk_Canvas canvas, /* Information about overall canvas. */
+ Tk_Item *itemPtr, /* Item for which Postscript is wanted. */
+ int prepass) /* 1 means this is a prepass to collect font
+ * information; 0 means final Postscript is
+ * being created. */
+{
+ BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
+ double x, y;
+ int width, height, rowsAtOnce, rowsThisTime;
+ int curRow;
+ XColor *fgColor;
+ XColor *bgColor;
+ Pixmap bitmap;
+ Tk_State state = itemPtr->state;
+ Tcl_Obj *psObj;
+ Tcl_InterpState interpState;
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+ fgColor = bmapPtr->fgColor;
+ bgColor = bmapPtr->bgColor;
+ bitmap = bmapPtr->bitmap;
+ if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (bmapPtr->activeFgColor!=NULL) {
+ fgColor = bmapPtr->activeFgColor;
+ }
+ if (bmapPtr->activeBgColor!=NULL) {
+ bgColor = bmapPtr->activeBgColor;
+ }
+ if (bmapPtr->activeBitmap!=None) {
+ bitmap = bmapPtr->activeBitmap;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (bmapPtr->disabledFgColor!=NULL) {
+ fgColor = bmapPtr->disabledFgColor;
+ }
+ if (bmapPtr->disabledBgColor!=NULL) {
+ bgColor = bmapPtr->disabledBgColor;
+ }
+ if (bmapPtr->disabledBitmap!=None) {
+ bitmap = bmapPtr->disabledBitmap;
+ }
+ }
+
+ if (bitmap == None) {
+ return TCL_OK;
+ }
+
+ /*
+ * Compute the coordinates of the lower-left corner of the bitmap, taking
+ * into account the anchor position for the bitmp.
+ */
+
+ x = bmapPtr->x;
+ y = Tk_CanvasPsY(canvas, bmapPtr->y);
+ Tk_SizeOfBitmap(Tk_Display(Tk_CanvasTkwin(canvas)), bitmap,
+ &width, &height);
+ switch (bmapPtr->anchor) {
+ case TK_ANCHOR_NW: y -= height; break;
+ case TK_ANCHOR_N: x -= width/2.0; y -= height; break;
+ case TK_ANCHOR_NE: x -= width; y -= height; break;
+ case TK_ANCHOR_E: x -= width; y -= height/2.0; break;
+ case TK_ANCHOR_SE: x -= width; break;
+ case TK_ANCHOR_S: x -= width/2.0; break;
+ case TK_ANCHOR_SW: break;
+ case TK_ANCHOR_W: y -= height/2.0; break;
+ case TK_ANCHOR_CENTER: x -= width/2.0; y -= height/2.0; break;
+ }
+
+ /*
+ * Make our working space.
+ */
+
+ psObj = Tcl_NewObj();
+ interpState = Tcl_SaveInterpState(interp, TCL_OK);
+
+ /*
+ * Color the background, if there is one.
+ */
+
+ if (bgColor != NULL) {
+ Tcl_AppendPrintfToObj(psObj,
+ "%.15g %.15g moveto %d 0 rlineto 0 %d rlineto "
+ "%d 0 rlineto closepath\n",
+ x, y, width, height, -width);
+
+ Tcl_ResetResult(interp);
+ if (Tk_CanvasPsColor(interp, canvas, bgColor) != TCL_OK) {
+ goto error;
+ }
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+
+ Tcl_AppendToObj(psObj, "fill\n", -1);
+ }
+
+ /*
+ * Draw the bitmap, if there is a foreground color. If the bitmap is very
+ * large, then chop it up into multiple bitmaps, each consisting of one or
+ * more rows. This is needed because Postscript can't handle single
+ * strings longer than 64 KBytes long.
+ */
+
+ if (fgColor != NULL) {
+ Tcl_ResetResult(interp);
+ if (Tk_CanvasPsColor(interp, canvas, fgColor) != TCL_OK) {
+ goto error;
+ }
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+
+ if (width > 60000) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "can't generate Postscript for bitmaps more than 60000"
+ " pixels wide", -1));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "PS", "MEMLIMIT", NULL);
+ goto error;
+ }
+
+ rowsAtOnce = 60000/width;
+ if (rowsAtOnce < 1) {
+ rowsAtOnce = 1;
+ }
+
+ Tcl_AppendPrintfToObj(psObj, "%.15g %.15g translate\n", x, y+height);
+
+ for (curRow = 0; curRow < height; curRow += rowsAtOnce) {
+ rowsThisTime = rowsAtOnce;
+ if (rowsThisTime > (height - curRow)) {
+ rowsThisTime = height - curRow;
+ }
+
+ Tcl_AppendPrintfToObj(psObj,
+ "0 -%.15g translate\n%d %d true matrix {\n",
+ (double) rowsThisTime, width, rowsThisTime);
+
+ Tcl_ResetResult(interp);
+ if (Tk_CanvasPsBitmap(interp, canvas, bitmap,
+ 0, curRow, width, rowsThisTime) != TCL_OK) {
+ goto error;
+ }
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+
+ Tcl_AppendToObj(psObj, "\n} imagemask\n", -1);
+ }
+ }
+
+ /*
+ * Plug the accumulated postscript back into the result.
+ */
+
+ (void) Tcl_RestoreInterpState(interp, interpState);
+ Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj);
+ Tcl_DecrRefCount(psObj);
+ return TCL_OK;
+
+ error:
+ Tcl_DiscardInterpState(interpState);
+ Tcl_DecrRefCount(psObj);
+ return TCL_ERROR;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkCanvImg.c b/tk8.6/generic/tkCanvImg.c
new file mode 100644
index 0000000..70b9c79
--- /dev/null
+++ b/tk8.6/generic/tkCanvImg.c
@@ -0,0 +1,883 @@
+/*
+ * tkCanvImg.c --
+ *
+ * This file implements image items for canvas widgets.
+ *
+ * Copyright (c) 1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "tkInt.h"
+#include "tkCanvas.h"
+
+/*
+ * The structure below defines the record for each image item.
+ */
+
+typedef struct ImageItem {
+ Tk_Item header; /* Generic stuff that's the same for all
+ * types. MUST BE FIRST IN STRUCTURE. */
+ Tk_Canvas canvas; /* Canvas containing the image. */
+ double x, y; /* Coordinates of positioning point for
+ * image. */
+ Tk_Anchor anchor; /* Where to anchor image relative to (x,y). */
+ char *imageString; /* String describing -image option
+ * (malloc-ed). NULL means no image right
+ * now. */
+ char *activeImageString; /* String describing -activeimage option.
+ * NULL means no image right now. */
+ char *disabledImageString; /* String describing -disabledimage option.
+ * NULL means no image right now. */
+ Tk_Image image; /* Image to display in window, or NULL if no
+ * image at present. */
+ Tk_Image activeImage; /* Image to display in window, or NULL if no
+ * image at present. */
+ Tk_Image disabledImage; /* Image to display in window, or NULL if no
+ * image at present. */
+} ImageItem;
+
+/*
+ * Information used for parsing configuration specs:
+ */
+
+static const Tk_CustomOption stateOption = {
+ TkStateParseProc, TkStatePrintProc, INT2PTR(2)
+};
+static const Tk_CustomOption tagsOption = {
+ Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL
+};
+
+static const Tk_ConfigSpec configSpecs[] = {
+ {TK_CONFIG_STRING, "-activeimage", NULL, NULL,
+ NULL, Tk_Offset(ImageItem, activeImageString), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_ANCHOR, "-anchor", NULL, NULL,
+ "center", Tk_Offset(ImageItem, anchor), TK_CONFIG_DONT_SET_DEFAULT, NULL},
+ {TK_CONFIG_STRING, "-disabledimage", NULL, NULL,
+ NULL, Tk_Offset(ImageItem, disabledImageString), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_STRING, "-image", NULL, NULL,
+ NULL, Tk_Offset(ImageItem, imageString), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_CUSTOM, "-state", NULL, NULL,
+ NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption},
+ {TK_CONFIG_CUSTOM, "-tags", NULL, NULL,
+ NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
+ {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}
+};
+
+/*
+ * Prototypes for functions defined in this file:
+ */
+
+static void ImageChangedProc(ClientData clientData,
+ int x, int y, int width, int height, int imgWidth,
+ int imgHeight);
+static int ImageCoords(Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
+ Tcl_Obj *const argv[]);
+static int ImageToArea(Tk_Canvas canvas,
+ Tk_Item *itemPtr, double *rectPtr);
+static double ImageToPoint(Tk_Canvas canvas,
+ Tk_Item *itemPtr, double *coordPtr);
+static int ImageToPostscript(Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr, int prepass);
+static void ComputeImageBbox(Tk_Canvas canvas, ImageItem *imgPtr);
+static int ConfigureImage(Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
+ Tcl_Obj *const argv[], int flags);
+static int CreateImage(Tcl_Interp *interp,
+ Tk_Canvas canvas, struct Tk_Item *itemPtr,
+ int argc, Tcl_Obj *const argv[]);
+static void DeleteImage(Tk_Canvas canvas,
+ Tk_Item *itemPtr, Display *display);
+static void DisplayImage(Tk_Canvas canvas,
+ Tk_Item *itemPtr, Display *display, Drawable dst,
+ int x, int y, int width, int height);
+static void ScaleImage(Tk_Canvas canvas,
+ Tk_Item *itemPtr, double originX, double originY,
+ double scaleX, double scaleY);
+static void TranslateImage(Tk_Canvas canvas,
+ Tk_Item *itemPtr, double deltaX, double deltaY);
+
+/*
+ * The structures below defines the image item type in terms of functions that
+ * can be invoked by generic item code.
+ */
+
+Tk_ItemType tkImageType = {
+ "image", /* name */
+ sizeof(ImageItem), /* itemSize */
+ CreateImage, /* createProc */
+ configSpecs, /* configSpecs */
+ ConfigureImage, /* configureProc */
+ ImageCoords, /* coordProc */
+ DeleteImage, /* deleteProc */
+ DisplayImage, /* displayProc */
+ TK_CONFIG_OBJS, /* flags */
+ ImageToPoint, /* pointProc */
+ ImageToArea, /* areaProc */
+ ImageToPostscript, /* postscriptProc */
+ ScaleImage, /* scaleProc */
+ TranslateImage, /* translateProc */
+ NULL, /* indexProc */
+ NULL, /* icursorProc */
+ NULL, /* selectionProc */
+ NULL, /* insertProc */
+ NULL, /* dTextProc */
+ NULL, /* nextPtr */
+ NULL, 0, NULL, NULL
+};
+
+/*
+ *--------------------------------------------------------------
+ *
+ * CreateImage --
+ *
+ * This function is invoked to create a new image item in a canvas.
+ *
+ * Results:
+ * A standard Tcl return value. If an error occurred in creating the
+ * item, then an error message is left in the interp's result; in this
+ * case itemPtr is left uninitialized, so it can be safely freed by the
+ * caller.
+ *
+ * Side effects:
+ * A new image item is created.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+CreateImage(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Tk_Canvas canvas, /* Canvas to hold new item. */
+ Tk_Item *itemPtr, /* Record to hold new item; header has been
+ * initialized by caller. */
+ int objc, /* Number of arguments in objv. */
+ Tcl_Obj *const objv[]) /* Arguments describing rectangle. */
+{
+ ImageItem *imgPtr = (ImageItem *) itemPtr;
+ int i;
+
+ if (objc == 0) {
+ Tcl_Panic("canvas did not pass any coords");
+ }
+
+ /*
+ * Initialize item's record.
+ */
+
+ imgPtr->canvas = canvas;
+ imgPtr->anchor = TK_ANCHOR_CENTER;
+ imgPtr->imageString = NULL;
+ imgPtr->activeImageString = NULL;
+ imgPtr->disabledImageString = NULL;
+ imgPtr->image = NULL;
+ imgPtr->activeImage = NULL;
+ imgPtr->disabledImage = NULL;
+
+ /*
+ * Process the arguments to fill in the item record. Only 1 (list) or 2 (x
+ * y) coords are allowed.
+ */
+
+ if (objc == 1) {
+ i = 1;
+ } else {
+ const char *arg = Tcl_GetString(objv[1]);
+ i = 2;
+ if ((arg[0] == '-') && (arg[1] >= 'a') && (arg[1] <= 'z')) {
+ i = 1;
+ }
+ }
+ if ((ImageCoords(interp, canvas, itemPtr, i, objv) != TCL_OK)) {
+ goto error;
+ }
+ if (ConfigureImage(interp, canvas, itemPtr, objc-i, objv+i, 0) == TCL_OK) {
+ return TCL_OK;
+ }
+
+ error:
+ DeleteImage(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ImageCoords --
+ *
+ * This function is invoked to process the "coords" widget command on
+ * image items. See the user documentation for details on what it does.
+ *
+ * Results:
+ * Returns TCL_OK or TCL_ERROR, and sets the interp's result.
+ *
+ * Side effects:
+ * The coordinates for the given item may be changed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+ImageCoords(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item whose coordinates are to be read or
+ * modified. */
+ int objc, /* Number of coordinates supplied in objv. */
+ Tcl_Obj *const objv[]) /* Array of coordinates: x1, y1, x2, y2, ... */
+{
+ ImageItem *imgPtr = (ImageItem *) itemPtr;
+
+ if (objc == 0) {
+ Tcl_Obj *objs[2];
+
+ objs[0] = Tcl_NewDoubleObj(imgPtr->x);
+ objs[1] = Tcl_NewDoubleObj(imgPtr->y);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(2, objs));
+ } else if (objc < 3) {
+ if (objc==1) {
+ if (Tcl_ListObjGetElements(interp, objv[0], &objc,
+ (Tcl_Obj ***) &objv) != TCL_OK) {
+ return TCL_ERROR;
+ } else if (objc != 2) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "wrong # coordinates: expected 2, got %d", objc));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "COORDS", "IMAGE",
+ NULL);
+ return TCL_ERROR;
+ }
+ }
+ if ((Tk_CanvasGetCoordFromObj(interp, canvas, objv[0],
+ &imgPtr->x) != TCL_OK)
+ || (Tk_CanvasGetCoordFromObj(interp, canvas, objv[1],
+ &imgPtr->y) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ ComputeImageBbox(canvas, imgPtr);
+ } else {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "wrong # coordinates: expected 0 or 2, got %d", objc));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "COORDS", "IMAGE", NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ConfigureImage --
+ *
+ * This function is invoked to configure various aspects of an image
+ * item, such as its anchor position.
+ *
+ * Results:
+ * A standard Tcl result code. If an error occurs, then an error message
+ * is left in the interp's result.
+ *
+ * Side effects:
+ * Configuration information may be set for itemPtr.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+ConfigureImage(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tk_Canvas canvas, /* Canvas containing itemPtr. */
+ Tk_Item *itemPtr, /* Image item to reconfigure. */
+ int objc, /* Number of elements in objv. */
+ Tcl_Obj *const objv[], /* Arguments describing things to configure. */
+ int flags) /* Flags to pass to Tk_ConfigureWidget. */
+{
+ ImageItem *imgPtr = (ImageItem *) itemPtr;
+ Tk_Window tkwin;
+ Tk_Image image;
+
+ tkwin = Tk_CanvasTkwin(canvas);
+ if (TCL_OK != Tk_ConfigureWidget(interp, tkwin, configSpecs, objc,
+ (const char **) objv, (char *) imgPtr, flags|TK_CONFIG_OBJS)) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Create the image. Save the old image around and don't free it until
+ * after the new one is allocated. This keeps the reference count from
+ * going to zero so the image doesn't have to be recreated if it hasn't
+ * changed.
+ */
+
+ if (imgPtr->activeImageString != NULL) {
+ itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;
+ } else {
+ itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;
+ }
+ if (imgPtr->imageString != NULL) {
+ image = Tk_GetImage(interp, tkwin, imgPtr->imageString,
+ ImageChangedProc, imgPtr);
+ if (image == NULL) {
+ return TCL_ERROR;
+ }
+ } else {
+ image = NULL;
+ }
+ if (imgPtr->image != NULL) {
+ Tk_FreeImage(imgPtr->image);
+ }
+ imgPtr->image = image;
+ if (imgPtr->activeImageString != NULL) {
+ image = Tk_GetImage(interp, tkwin, imgPtr->activeImageString,
+ ImageChangedProc, imgPtr);
+ if (image == NULL) {
+ return TCL_ERROR;
+ }
+ } else {
+ image = NULL;
+ }
+ if (imgPtr->activeImage != NULL) {
+ Tk_FreeImage(imgPtr->activeImage);
+ }
+ imgPtr->activeImage = image;
+ if (imgPtr->disabledImageString != NULL) {
+ image = Tk_GetImage(interp, tkwin, imgPtr->disabledImageString,
+ ImageChangedProc, imgPtr);
+ if (image == NULL) {
+ return TCL_ERROR;
+ }
+ } else {
+ image = NULL;
+ }
+ if (imgPtr->disabledImage != NULL) {
+ Tk_FreeImage(imgPtr->disabledImage);
+ }
+ imgPtr->disabledImage = image;
+ ComputeImageBbox(canvas, imgPtr);
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DeleteImage --
+ *
+ * This function is called to clean up the data structure associated with
+ * a image item.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Resources associated with itemPtr are released.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+DeleteImage(
+ Tk_Canvas canvas, /* Info about overall canvas widget. */
+ Tk_Item *itemPtr, /* Item that is being deleted. */
+ Display *display) /* Display containing window for canvas. */
+{
+ ImageItem *imgPtr = (ImageItem *) itemPtr;
+
+ if (imgPtr->imageString != NULL) {
+ ckfree(imgPtr->imageString);
+ }
+ if (imgPtr->activeImageString != NULL) {
+ ckfree(imgPtr->activeImageString);
+ }
+ if (imgPtr->disabledImageString != NULL) {
+ ckfree(imgPtr->disabledImageString);
+ }
+ if (imgPtr->image != NULL) {
+ Tk_FreeImage(imgPtr->image);
+ }
+ if (imgPtr->activeImage != NULL) {
+ Tk_FreeImage(imgPtr->activeImage);
+ }
+ if (imgPtr->disabledImage != NULL) {
+ Tk_FreeImage(imgPtr->disabledImage);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ComputeImageBbox --
+ *
+ * This function is invoked to compute the bounding box of all the pixels
+ * that may be drawn as part of a image item. This function is where the
+ * child image's placement is computed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The fields x1, y1, x2, and y2 are updated in the header for itemPtr.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static void
+ComputeImageBbox(
+ Tk_Canvas canvas, /* Canvas that contains item. */
+ ImageItem *imgPtr) /* Item whose bbox is to be recomputed. */
+{
+ int width, height;
+ int x, y;
+ Tk_Image image;
+ Tk_State state = imgPtr->header.state;
+
+ if(state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+ image = imgPtr->image;
+ if (Canvas(canvas)->currentItemPtr == (Tk_Item *)imgPtr) {
+ if (imgPtr->activeImage != NULL) {
+ image = imgPtr->activeImage;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (imgPtr->disabledImage != NULL) {
+ image = imgPtr->disabledImage;
+ }
+ }
+
+ x = (int) (imgPtr->x + ((imgPtr->x >= 0) ? 0.5 : - 0.5));
+ y = (int) (imgPtr->y + ((imgPtr->y >= 0) ? 0.5 : - 0.5));
+
+ if ((state == TK_STATE_HIDDEN) || (image == NULL)) {
+ imgPtr->header.x1 = imgPtr->header.x2 = x;
+ imgPtr->header.y1 = imgPtr->header.y2 = y;
+ return;
+ }
+
+ /*
+ * Compute location and size of image, using anchor information.
+ */
+
+ Tk_SizeOfImage(image, &width, &height);
+ switch (imgPtr->anchor) {
+ case TK_ANCHOR_N:
+ x -= width/2;
+ break;
+ case TK_ANCHOR_NE:
+ x -= width;
+ break;
+ case TK_ANCHOR_E:
+ x -= width;
+ y -= height/2;
+ break;
+ case TK_ANCHOR_SE:
+ x -= width;
+ y -= height;
+ break;
+ case TK_ANCHOR_S:
+ x -= width/2;
+ y -= height;
+ break;
+ case TK_ANCHOR_SW:
+ y -= height;
+ break;
+ case TK_ANCHOR_W:
+ y -= height/2;
+ break;
+ case TK_ANCHOR_NW:
+ break;
+ case TK_ANCHOR_CENTER:
+ x -= width/2;
+ y -= height/2;
+ break;
+ }
+
+ /*
+ * Store the information in the item header.
+ */
+
+ imgPtr->header.x1 = x;
+ imgPtr->header.y1 = y;
+ imgPtr->header.x2 = x + width;
+ imgPtr->header.y2 = y + height;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DisplayImage --
+ *
+ * This function is invoked to draw a image item in a given drawable.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * ItemPtr is drawn in drawable using the transformation information in
+ * canvas.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+DisplayImage(
+ Tk_Canvas canvas, /* Canvas that contains item. */
+ Tk_Item *itemPtr, /* Item to be displayed. */
+ Display *display, /* Display on which to draw item. */
+ Drawable drawable, /* Pixmap or window in which to draw item. */
+ int x, int y, int width, int height)
+ /* Describes region of canvas that must be
+ * redisplayed (not used). */
+{
+ ImageItem *imgPtr = (ImageItem *) itemPtr;
+ short drawableX, drawableY;
+ Tk_Image image;
+ Tk_State state = itemPtr->state;
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+
+ image = imgPtr->image;
+ if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (imgPtr->activeImage != NULL) {
+ image = imgPtr->activeImage;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (imgPtr->disabledImage != NULL) {
+ image = imgPtr->disabledImage;
+ }
+ }
+
+ if (image == NULL) {
+ return;
+ }
+
+ /*
+ * Translate the coordinates to those of the image, then redisplay it.
+ */
+
+ Tk_CanvasDrawableCoords(canvas, (double) x, (double) y,
+ &drawableX, &drawableY);
+ Tk_RedrawImage(image, x - imgPtr->header.x1, y - imgPtr->header.y1,
+ width, height, drawable, drawableX, drawableY);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ImageToPoint --
+ *
+ * Computes the distance from a given point to a given rectangle, in
+ * canvas units.
+ *
+ * Results:
+ * The return value is 0 if the point whose x and y coordinates are
+ * coordPtr[0] and coordPtr[1] is inside the image. If the point isn't
+ * inside the image then the return value is the distance from the point
+ * to the image.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static double
+ImageToPoint(
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item to check against point. */
+ double *coordPtr) /* Pointer to x and y coordinates. */
+{
+ ImageItem *imgPtr = (ImageItem *) itemPtr;
+ double x1, x2, y1, y2, xDiff, yDiff;
+
+ x1 = imgPtr->header.x1;
+ y1 = imgPtr->header.y1;
+ x2 = imgPtr->header.x2;
+ y2 = imgPtr->header.y2;
+
+ /*
+ * Point is outside rectangle.
+ */
+
+ if (coordPtr[0] < x1) {
+ xDiff = x1 - coordPtr[0];
+ } else if (coordPtr[0] > x2) {
+ xDiff = coordPtr[0] - x2;
+ } else {
+ xDiff = 0;
+ }
+
+ if (coordPtr[1] < y1) {
+ yDiff = y1 - coordPtr[1];
+ } else if (coordPtr[1] > y2) {
+ yDiff = coordPtr[1] - y2;
+ } else {
+ yDiff = 0;
+ }
+
+ return hypot(xDiff, yDiff);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ImageToArea --
+ *
+ * This function is called to determine whether an item lies entirely
+ * inside, entirely outside, or overlapping a given rectangle.
+ *
+ * Results:
+ * -1 is returned if the item is entirely outside the area given by
+ * rectPtr, 0 if it overlaps, and 1 if it is entirely inside the given
+ * area.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+ImageToArea(
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item to check against rectangle. */
+ double *rectPtr) /* Pointer to array of four coordinates
+ * (x1,y1,x2,y2) describing rectangular
+ * area. */
+{
+ ImageItem *imgPtr = (ImageItem *) itemPtr;
+
+ if ((rectPtr[2] <= imgPtr->header.x1)
+ || (rectPtr[0] >= imgPtr->header.x2)
+ || (rectPtr[3] <= imgPtr->header.y1)
+ || (rectPtr[1] >= imgPtr->header.y2)) {
+ return -1;
+ }
+ if ((rectPtr[0] <= imgPtr->header.x1)
+ && (rectPtr[1] <= imgPtr->header.y1)
+ && (rectPtr[2] >= imgPtr->header.x2)
+ && (rectPtr[3] >= imgPtr->header.y2)) {
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ImageToPostscript --
+ *
+ * This function is called to generate Postscript for image items.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If an error occurs in
+ * generating Postscript then an error message is left in interp->result,
+ * replacing whatever used to be there. If no error occurs, then
+ * Postscript for the item is appended to the result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+ImageToPostscript(
+ Tcl_Interp *interp, /* Leave Postscript or error message here. */
+ Tk_Canvas canvas, /* Information about overall canvas. */
+ Tk_Item *itemPtr, /* Item for which Postscript is wanted. */
+ int prepass) /* 1 means this is a prepass to collect font
+ * information; 0 means final Postscript is
+ * being created.*/
+{
+ ImageItem *imgPtr = (ImageItem *) itemPtr;
+ Tk_Window canvasWin = Tk_CanvasTkwin(canvas);
+ double x, y;
+ int width, height;
+ Tk_Image image;
+ Tk_State state = itemPtr->state;
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+
+ image = imgPtr->image;
+ if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (imgPtr->activeImage != NULL) {
+ image = imgPtr->activeImage;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (imgPtr->disabledImage != NULL) {
+ image = imgPtr->disabledImage;
+ }
+ }
+ if (image == NULL) {
+ /*
+ * Image item without actual image specified.
+ */
+
+ return TCL_OK;
+ }
+ Tk_SizeOfImage(image, &width, &height);
+
+ /*
+ * Compute the coordinates of the lower-left corner of the image, taking
+ * into account the anchor position for the image.
+ */
+
+ x = imgPtr->x;
+ y = Tk_CanvasPsY(canvas, imgPtr->y);
+
+ switch (imgPtr->anchor) {
+ case TK_ANCHOR_NW: y -= height; break;
+ case TK_ANCHOR_N: x -= width/2.0; y -= height; break;
+ case TK_ANCHOR_NE: x -= width; y -= height; break;
+ case TK_ANCHOR_E: x -= width; y -= height/2.0; break;
+ case TK_ANCHOR_SE: x -= width; break;
+ case TK_ANCHOR_S: x -= width/2.0; break;
+ case TK_ANCHOR_SW: break;
+ case TK_ANCHOR_W: y -= height/2.0; break;
+ case TK_ANCHOR_CENTER: x -= width/2.0; y -= height/2.0; break;
+ }
+
+ if (!prepass) {
+ Tcl_Obj *psObj = Tcl_GetObjResult(interp);
+
+ if (Tcl_IsShared(psObj)) {
+ psObj = Tcl_DuplicateObj(psObj);
+ Tcl_SetObjResult(interp, psObj);
+ }
+
+ Tcl_AppendPrintfToObj(psObj, "%.15g %.15g translate\n", x, y);
+ }
+
+ return Tk_PostscriptImage(image, interp, canvasWin,
+ ((TkCanvas *) canvas)->psInfo, 0, 0, width, height, prepass);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ScaleImage --
+ *
+ * This function is invoked to rescale an item.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The item referred to by itemPtr is rescaled so that the following
+ * transformation is applied to all point coordinates:
+ * x' = originX + scaleX*(x-originX)
+ * y' = originY + scaleY*(y-originY)
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ScaleImage(
+ Tk_Canvas canvas, /* Canvas containing rectangle. */
+ Tk_Item *itemPtr, /* Rectangle to be scaled. */
+ double originX, double originY,
+ /* Origin about which to scale rect. */
+ double scaleX, /* Amount to scale in X direction. */
+ double scaleY) /* Amount to scale in Y direction. */
+{
+ ImageItem *imgPtr = (ImageItem *) itemPtr;
+
+ imgPtr->x = originX + scaleX*(imgPtr->x - originX);
+ imgPtr->y = originY + scaleY*(imgPtr->y - originY);
+ ComputeImageBbox(canvas, imgPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TranslateImage --
+ *
+ * This function is called to move an item by a given amount.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The position of the item is offset by (xDelta, yDelta), and the
+ * bounding box is updated in the generic part of the item structure.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+TranslateImage(
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item that is being moved. */
+ double deltaX, double deltaY)
+ /* Amount by which item is to be moved. */
+{
+ ImageItem *imgPtr = (ImageItem *) itemPtr;
+
+ imgPtr->x += deltaX;
+ imgPtr->y += deltaY;
+ ComputeImageBbox(canvas, imgPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImageChangedProc --
+ *
+ * This function is invoked by the image code whenever the manager for an
+ * image does something that affects the image's size or how it is
+ * displayed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Arranges for the canvas to get redisplayed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ImageChangedProc(
+ ClientData clientData, /* Pointer to canvas item for image. */
+ int x, int y, /* Upper left pixel (within image) that must
+ * be redisplayed. */
+ int width, int height, /* Dimensions of area to redisplay (may be <=
+ * 0). */
+ int imgWidth, int imgHeight)/* New dimensions of image. */
+{
+ ImageItem *imgPtr = clientData;
+
+ /*
+ * If the image's size changed and it's not anchored at its northwest
+ * corner then just redisplay the entire area of the image. This is a bit
+ * over-conservative, but we need to do something because a size change
+ * also means a position change.
+ */
+
+ if (((imgPtr->header.x2 - imgPtr->header.x1) != imgWidth)
+ || ((imgPtr->header.y2 - imgPtr->header.y1) != imgHeight)) {
+ x = y = 0;
+ width = imgWidth;
+ height = imgHeight;
+ Tk_CanvasEventuallyRedraw(imgPtr->canvas, imgPtr->header.x1,
+ imgPtr->header.y1, imgPtr->header.x2, imgPtr->header.y2);
+ }
+ ComputeImageBbox(imgPtr->canvas, imgPtr);
+ Tk_CanvasEventuallyRedraw(imgPtr->canvas, imgPtr->header.x1 + x,
+ imgPtr->header.y1 + y, (int) (imgPtr->header.x1 + x + width),
+ (int) (imgPtr->header.y1 + y + height));
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkCanvLine.c b/tk8.6/generic/tkCanvLine.c
new file mode 100644
index 0000000..b6c845d
--- /dev/null
+++ b/tk8.6/generic/tkCanvLine.c
@@ -0,0 +1,2518 @@
+/*
+ * tkCanvLine.c --
+ *
+ * This file implements line items for canvas widgets.
+ *
+ * Copyright (c) 1991-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkInt.h"
+#include "tkCanvas.h"
+
+/*
+ * The structure below defines the record for each line item.
+ */
+
+typedef enum {
+ ARROWS_NONE, ARROWS_FIRST, ARROWS_LAST, ARROWS_BOTH
+} Arrows;
+
+typedef struct LineItem {
+ Tk_Item header; /* Generic stuff that's the same for all
+ * types. MUST BE FIRST IN STRUCTURE. */
+ Tk_Outline outline; /* Outline structure */
+ Tk_Canvas canvas; /* Canvas containing item. Needed for parsing
+ * arrow shapes. */
+ int numPoints; /* Number of points in line (always >= 0). */
+ double *coordPtr; /* Pointer to malloc-ed array containing x-
+ * and y-coords of all points in line.
+ * X-coords are even-valued indices, y-coords
+ * are corresponding odd-valued indices. If
+ * the line has arrowheads then the first and
+ * last points have been adjusted to refer to
+ * the necks of the arrowheads rather than
+ * their tips. The actual endpoints are stored
+ * in the *firstArrowPtr and *lastArrowPtr, if
+ * they exist. */
+ int capStyle; /* Cap style for line. */
+ int joinStyle; /* Join style for line. */
+ GC arrowGC; /* Graphics context for drawing arrowheads. */
+ Arrows arrow; /* Indicates whether or not to draw arrowheads:
+ * "none", "first", "last", or "both". */
+ float arrowShapeA; /* Distance from tip of arrowhead to center. */
+ float arrowShapeB; /* Distance from tip of arrowhead to trailing
+ * point, measured along shaft. */
+ float arrowShapeC; /* Distance of trailing points from outside
+ * edge of shaft. */
+ double *firstArrowPtr; /* Points to array of PTS_IN_ARROW points
+ * describing polygon for arrowhead at first
+ * point in line. First point of arrowhead is
+ * tip. Malloc'ed. NULL means no arrowhead at
+ * first point. */
+ double *lastArrowPtr; /* Points to polygon for arrowhead at last
+ * point in line (PTS_IN_ARROW points, first
+ * of which is tip). Malloc'ed. NULL means no
+ * arrowhead at last point. */
+ const Tk_SmoothMethod *smooth; /* Non-zero means draw line smoothed (i.e.
+ * with Bezier splines). */
+ int splineSteps; /* Number of steps in each spline segment. */
+} LineItem;
+
+/*
+ * Number of points in an arrowHead:
+ */
+
+#define PTS_IN_ARROW 6
+
+/*
+ * Prototypes for functions defined in this file:
+ */
+
+static int ArrowheadPostscript(Tcl_Interp *interp,
+ Tk_Canvas canvas, LineItem *linePtr,
+ double *arrowPtr, Tcl_Obj *psObj);
+static void ComputeLineBbox(Tk_Canvas canvas, LineItem *linePtr);
+static int ConfigureLine(Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr, int objc,
+ Tcl_Obj *const objv[], int flags);
+static int ConfigureArrows(Tk_Canvas canvas, LineItem *linePtr);
+static int CreateLine(Tcl_Interp *interp,
+ Tk_Canvas canvas, struct Tk_Item *itemPtr,
+ int objc, Tcl_Obj *const objv[]);
+static void DeleteLine(Tk_Canvas canvas,
+ Tk_Item *itemPtr, Display *display);
+static void DisplayLine(Tk_Canvas canvas,
+ Tk_Item *itemPtr, Display *display, Drawable dst,
+ int x, int y, int width, int height);
+static int GetLineIndex(Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr,
+ Tcl_Obj *obj, int *indexPtr);
+static int LineCoords(Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr,
+ int objc, Tcl_Obj *const objv[]);
+static void LineDeleteCoords(Tk_Canvas canvas,
+ Tk_Item *itemPtr, int first, int last);
+static void LineInsert(Tk_Canvas canvas,
+ Tk_Item *itemPtr, int beforeThis, Tcl_Obj *obj);
+static int LineToArea(Tk_Canvas canvas,
+ Tk_Item *itemPtr, double *rectPtr);
+static double LineToPoint(Tk_Canvas canvas,
+ Tk_Item *itemPtr, double *coordPtr);
+static int LineToPostscript(Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr, int prepass);
+static int ArrowParseProc(ClientData clientData,
+ Tcl_Interp *interp, Tk_Window tkwin,
+ const char *value, char *recordPtr, int offset);
+static const char * ArrowPrintProc(ClientData clientData,
+ Tk_Window tkwin, char *recordPtr, int offset,
+ Tcl_FreeProc **freeProcPtr);
+static int ParseArrowShape(ClientData clientData,
+ Tcl_Interp *interp, Tk_Window tkwin,
+ const char *value, char *recordPtr, int offset);
+static const char * PrintArrowShape(ClientData clientData,
+ Tk_Window tkwin, char *recordPtr, int offset,
+ Tcl_FreeProc **freeProcPtr);
+static void ScaleLine(Tk_Canvas canvas,
+ Tk_Item *itemPtr, double originX, double originY,
+ double scaleX, double scaleY);
+static void TranslateLine(Tk_Canvas canvas,
+ Tk_Item *itemPtr, double deltaX, double deltaY);
+
+/*
+ * Information used for parsing configuration specs. If you change any of the
+ * default strings, be sure to change the corresponding default values in
+ * CreateLine.
+ */
+
+static const Tk_CustomOption arrowShapeOption = {
+ ParseArrowShape, PrintArrowShape, NULL
+};
+static const Tk_CustomOption arrowOption = {
+ ArrowParseProc, ArrowPrintProc, NULL
+};
+static const Tk_CustomOption smoothOption = {
+ TkSmoothParseProc, TkSmoothPrintProc, NULL
+};
+static const Tk_CustomOption stateOption = {
+ TkStateParseProc, TkStatePrintProc, INT2PTR(2)
+};
+static const Tk_CustomOption tagsOption = {
+ Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL
+};
+static const Tk_CustomOption dashOption = {
+ TkCanvasDashParseProc, TkCanvasDashPrintProc, NULL
+};
+static const Tk_CustomOption offsetOption = {
+ TkOffsetParseProc, TkOffsetPrintProc,
+ INT2PTR(TK_OFFSET_RELATIVE|TK_OFFSET_INDEX)
+};
+static const Tk_CustomOption pixelOption = {
+ TkPixelParseProc, TkPixelPrintProc, NULL
+};
+
+static const Tk_ConfigSpec configSpecs[] = {
+ {TK_CONFIG_CUSTOM, "-activedash", NULL, NULL,
+ NULL, Tk_Offset(LineItem, outline.activeDash),
+ TK_CONFIG_NULL_OK, &dashOption},
+ {TK_CONFIG_COLOR, "-activefill", NULL, NULL,
+ NULL, Tk_Offset(LineItem, outline.activeColor), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_BITMAP, "-activestipple", NULL, NULL,
+ NULL, Tk_Offset(LineItem, outline.activeStipple), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_CUSTOM, "-activewidth", NULL, NULL,
+ "0.0", Tk_Offset(LineItem, outline.activeWidth),
+ TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
+ {TK_CONFIG_CUSTOM, "-arrow", NULL, NULL,
+ "none", Tk_Offset(LineItem, arrow),
+ TK_CONFIG_DONT_SET_DEFAULT, &arrowOption},
+ {TK_CONFIG_CUSTOM, "-arrowshape", NULL, NULL,
+ "8 10 3", Tk_Offset(LineItem, arrowShapeA),
+ TK_CONFIG_DONT_SET_DEFAULT, &arrowShapeOption},
+ {TK_CONFIG_CAP_STYLE, "-capstyle", NULL, NULL,
+ "butt", Tk_Offset(LineItem, capStyle), TK_CONFIG_DONT_SET_DEFAULT, NULL},
+ {TK_CONFIG_COLOR, "-fill", NULL, NULL,
+ "black", Tk_Offset(LineItem, outline.color), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_CUSTOM, "-dash", NULL, NULL,
+ NULL, Tk_Offset(LineItem, outline.dash),
+ TK_CONFIG_NULL_OK, &dashOption},
+ {TK_CONFIG_PIXELS, "-dashoffset", NULL, NULL,
+ "0", Tk_Offset(LineItem, outline.offset), TK_CONFIG_DONT_SET_DEFAULT, NULL},
+ {TK_CONFIG_CUSTOM, "-disableddash", NULL, NULL,
+ NULL, Tk_Offset(LineItem, outline.disabledDash),
+ TK_CONFIG_NULL_OK, &dashOption},
+ {TK_CONFIG_COLOR, "-disabledfill", NULL, NULL,
+ NULL, Tk_Offset(LineItem, outline.disabledColor), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_BITMAP, "-disabledstipple", NULL, NULL,
+ NULL, Tk_Offset(LineItem, outline.disabledStipple), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_CUSTOM, "-disabledwidth", NULL, NULL,
+ "0.0", Tk_Offset(LineItem, outline.disabledWidth),
+ TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
+ {TK_CONFIG_JOIN_STYLE, "-joinstyle", NULL, NULL,
+ "round", Tk_Offset(LineItem, joinStyle), TK_CONFIG_DONT_SET_DEFAULT, NULL},
+ {TK_CONFIG_CUSTOM, "-offset", NULL, NULL,
+ "0,0", Tk_Offset(LineItem, outline.tsoffset),
+ TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},
+ {TK_CONFIG_CUSTOM, "-smooth", NULL, NULL,
+ "0", Tk_Offset(LineItem, smooth),
+ TK_CONFIG_DONT_SET_DEFAULT, &smoothOption},
+ {TK_CONFIG_INT, "-splinesteps", NULL, NULL,
+ "12", Tk_Offset(LineItem, splineSteps), TK_CONFIG_DONT_SET_DEFAULT, NULL},
+ {TK_CONFIG_CUSTOM, "-state", NULL, NULL,
+ NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption},
+ {TK_CONFIG_BITMAP, "-stipple", NULL, NULL,
+ NULL, Tk_Offset(LineItem, outline.stipple), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_CUSTOM, "-tags", NULL, NULL,
+ NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
+ {TK_CONFIG_CUSTOM, "-width", NULL, NULL,
+ "1.0", Tk_Offset(LineItem, outline.width),
+ TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
+ {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}
+};
+
+/*
+ * The structures below defines the line item type by means of functions that
+ * can be invoked by generic item code.
+ */
+
+Tk_ItemType tkLineType = {
+ "line", /* name */
+ sizeof(LineItem), /* itemSize */
+ CreateLine, /* createProc */
+ configSpecs, /* configSpecs */
+ ConfigureLine, /* configureProc */
+ LineCoords, /* coordProc */
+ DeleteLine, /* deleteProc */
+ DisplayLine, /* displayProc */
+ TK_CONFIG_OBJS | TK_MOVABLE_POINTS, /* flags */
+ LineToPoint, /* pointProc */
+ LineToArea, /* areaProc */
+ LineToPostscript, /* postscriptProc */
+ ScaleLine, /* scaleProc */
+ TranslateLine, /* translateProc */
+ GetLineIndex, /* indexProc */
+ NULL, /* icursorProc */
+ NULL, /* selectionProc */
+ LineInsert, /* insertProc */
+ LineDeleteCoords, /* dTextProc */
+ NULL, /* nextPtr */
+ NULL, 0, NULL, NULL
+};
+
+/*
+ * The definition below determines how large are static arrays used to hold
+ * spline points (splines larger than this have to have their arrays
+ * malloc-ed).
+ */
+
+#define MAX_STATIC_POINTS 200
+
+/*
+ *--------------------------------------------------------------
+ *
+ * CreateLine --
+ *
+ * This function is invoked to create a new line item in a canvas.
+ *
+ * Results:
+ * A standard Tcl return value. If an error occurred in creating the
+ * item, then an error message is left in the interp's result; in this
+ * case itemPtr is left uninitialized, so it can be safely freed by the
+ * caller.
+ *
+ * Side effects:
+ * A new line item is created.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+CreateLine(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Tk_Canvas canvas, /* Canvas to hold new item. */
+ Tk_Item *itemPtr, /* Record to hold new item; header has been
+ * initialized by caller. */
+ int objc, /* Number of arguments in objv. */
+ Tcl_Obj *const objv[]) /* Arguments describing line. */
+{
+ LineItem *linePtr = (LineItem *) itemPtr;
+ int i;
+
+ if (objc == 0) {
+ Tcl_Panic("canvas did not pass any coords");
+ }
+
+ /*
+ * Carry out initialization that is needed to set defaults and to allow
+ * proper cleanup after errors during the the remainder of this function.
+ */
+
+ Tk_CreateOutline(&linePtr->outline);
+ linePtr->canvas = canvas;
+ linePtr->numPoints = 0;
+ linePtr->coordPtr = NULL;
+ linePtr->capStyle = CapButt;
+ linePtr->joinStyle = JoinRound;
+ linePtr->arrowGC = NULL;
+ linePtr->arrow = ARROWS_NONE;
+ linePtr->arrowShapeA = (float)8.0;
+ linePtr->arrowShapeB = (float)10.0;
+ linePtr->arrowShapeC = (float)3.0;
+ linePtr->firstArrowPtr = NULL;
+ linePtr->lastArrowPtr = NULL;
+ linePtr->smooth = NULL;
+ linePtr->splineSteps = 12;
+
+ /*
+ * Count the number of points and then parse them into a point array.
+ * Leading arguments are assumed to be points if they start with a digit
+ * or a minus sign followed by a digit.
+ */
+
+ for (i = 1; i < objc; i++) {
+ const char *arg = Tcl_GetString(objv[i]);
+
+ if ((arg[0] == '-') && (arg[1] >= 'a') && (arg[1] <= 'z')) {
+ break;
+ }
+ }
+ if (LineCoords(interp, canvas, itemPtr, i, objv) != TCL_OK) {
+ goto error;
+ }
+ if (ConfigureLine(interp, canvas, itemPtr, objc-i, objv+i, 0) == TCL_OK) {
+ return TCL_OK;
+ }
+
+ error:
+ DeleteLine(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * LineCoords --
+ *
+ * This function is invoked to process the "coords" widget command on
+ * lines. See the user documentation for details on what it does.
+ *
+ * Results:
+ * Returns TCL_OK or TCL_ERROR, and sets the interp's result.
+ *
+ * Side effects:
+ * The coordinates for the given item may be changed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+LineCoords(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item whose coordinates are to be read or
+ * modified. */
+ int objc, /* Number of coordinates supplied in objv. */
+ Tcl_Obj *const objv[]) /* Array of coordinates: x1, y1, x2, y2, ... */
+{
+ LineItem *linePtr = (LineItem *) itemPtr;
+ int i, numPoints;
+ double *coordPtr;
+
+ if (objc == 0) {
+ int numCoords;
+ Tcl_Obj *subobj, *obj = Tcl_NewObj();
+
+ numCoords = 2*linePtr->numPoints;
+ if (linePtr->firstArrowPtr != NULL) {
+ coordPtr = linePtr->firstArrowPtr;
+ } else {
+ coordPtr = linePtr->coordPtr;
+ }
+ for (i = 0; i < numCoords; i++, coordPtr++) {
+ if (i == 2) {
+ coordPtr = linePtr->coordPtr+2;
+ }
+ if ((linePtr->lastArrowPtr != NULL) && (i == (numCoords-2))) {
+ coordPtr = linePtr->lastArrowPtr;
+ }
+ subobj = Tcl_NewDoubleObj(*coordPtr);
+ Tcl_ListObjAppendElement(interp, obj, subobj);
+ }
+ Tcl_SetObjResult(interp, obj);
+ return TCL_OK;
+ }
+ if (objc == 1) {
+ if (Tcl_ListObjGetElements(interp, objv[0], &objc,
+ (Tcl_Obj ***) &objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (objc & 1) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "wrong # coordinates: expected an even number, got %d",
+ objc));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "COORDS", "LINE", NULL);
+ return TCL_ERROR;
+ } else if (objc < 4) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "wrong # coordinates: expected at least 4, got %d", objc));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "COORDS", "LINE", NULL);
+ return TCL_ERROR;
+ }
+
+ numPoints = objc/2;
+ if (linePtr->numPoints != numPoints) {
+ coordPtr = ckalloc(sizeof(double) * objc);
+ if (linePtr->coordPtr != NULL) {
+ ckfree(linePtr->coordPtr);
+ }
+ linePtr->coordPtr = coordPtr;
+ linePtr->numPoints = numPoints;
+ }
+ coordPtr = linePtr->coordPtr;
+ for (i = 0; i < objc ; i++) {
+ if (Tk_CanvasGetCoordFromObj(interp, canvas, objv[i],
+ coordPtr++) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * Update arrowheads by throwing away any existing arrow-head information
+ * and calling ConfigureArrows to recompute it.
+ */
+
+ if (linePtr->firstArrowPtr != NULL) {
+ ckfree(linePtr->firstArrowPtr);
+ linePtr->firstArrowPtr = NULL;
+ }
+ if (linePtr->lastArrowPtr != NULL) {
+ ckfree(linePtr->lastArrowPtr);
+ linePtr->lastArrowPtr = NULL;
+ }
+ if (linePtr->arrow != ARROWS_NONE) {
+ ConfigureArrows(canvas, linePtr);
+ }
+ ComputeLineBbox(canvas, linePtr);
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ConfigureLine --
+ *
+ * This function is invoked to configure various aspects of a line item
+ * such as its background color.
+ *
+ * Results:
+ * A standard Tcl result code. If an error occurs, then an error message
+ * is left in the interp's result.
+ *
+ * Side effects:
+ * Configuration information, such as colors and stipple patterns, may be
+ * set for itemPtr.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+ConfigureLine(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tk_Canvas canvas, /* Canvas containing itemPtr. */
+ Tk_Item *itemPtr, /* Line item to reconfigure. */
+ int objc, /* Number of elements in objv. */
+ Tcl_Obj *const objv[], /* Arguments describing things to configure. */
+ int flags) /* Flags to pass to Tk_ConfigureWidget. */
+{
+ LineItem *linePtr = (LineItem *) itemPtr;
+ XGCValues gcValues;
+ GC newGC, arrowGC;
+ unsigned long mask;
+ Tk_Window tkwin;
+ Tk_State state;
+
+ tkwin = Tk_CanvasTkwin(canvas);
+ if (TCL_OK != Tk_ConfigureWidget(interp, tkwin, configSpecs, objc,
+ (const char **) objv, (char *) linePtr, flags|TK_CONFIG_OBJS)) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * A few of the options require additional processing, such as graphics
+ * contexts.
+ */
+
+ state = itemPtr->state;
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+
+ if (linePtr->outline.activeWidth > linePtr->outline.width ||
+ linePtr->outline.activeDash.number != 0 ||
+ linePtr->outline.activeColor != NULL ||
+ linePtr->outline.activeStipple != None) {
+ itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;
+ } else {
+ itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;
+ }
+ mask = Tk_ConfigOutlineGC(&gcValues, canvas, itemPtr, &linePtr->outline);
+ if (mask) {
+ if (linePtr->arrow == ARROWS_NONE) {
+ gcValues.cap_style = linePtr->capStyle;
+ mask |= GCCapStyle;
+ }
+ gcValues.join_style = linePtr->joinStyle;
+ mask |= GCJoinStyle;
+ newGC = Tk_GetGC(tkwin, mask, &gcValues);
+#ifdef MAC_OSX_TK
+ /*
+ * Mac OS X CG drawing needs access to linewidth even for arrow fills
+ * (as linewidth controls antialiasing).
+ */
+
+ mask |= GCLineWidth;
+#else
+ gcValues.line_width = 0;
+#endif
+ arrowGC = Tk_GetGC(tkwin, mask, &gcValues);
+ } else {
+ newGC = arrowGC = NULL;
+ }
+ if (linePtr->outline.gc != NULL) {
+ Tk_FreeGC(Tk_Display(tkwin), linePtr->outline.gc);
+ }
+ if (linePtr->arrowGC != NULL) {
+ Tk_FreeGC(Tk_Display(tkwin), linePtr->arrowGC);
+ }
+ linePtr->outline.gc = newGC;
+ linePtr->arrowGC = arrowGC;
+
+ /*
+ * Keep spline parameters within reasonable limits.
+ */
+
+ if (linePtr->splineSteps < 1) {
+ linePtr->splineSteps = 1;
+ } else if (linePtr->splineSteps > 100) {
+ linePtr->splineSteps = 100;
+ }
+
+ if ((!linePtr->numPoints) || (state == TK_STATE_HIDDEN)) {
+ ComputeLineBbox(canvas, linePtr);
+ return TCL_OK;
+ }
+
+ /*
+ * Setup arrowheads, if needed. If arrowheads are turned off, restore the
+ * line's endpoints (they were shortened when the arrowheads were added).
+ */
+
+ if ((linePtr->firstArrowPtr != NULL) && (linePtr->arrow != ARROWS_FIRST)
+ && (linePtr->arrow != ARROWS_BOTH)) {
+ linePtr->coordPtr[0] = linePtr->firstArrowPtr[0];
+ linePtr->coordPtr[1] = linePtr->firstArrowPtr[1];
+ ckfree(linePtr->firstArrowPtr);
+ linePtr->firstArrowPtr = NULL;
+ }
+ if ((linePtr->lastArrowPtr != NULL) && (linePtr->arrow != ARROWS_LAST)
+ && (linePtr->arrow != ARROWS_BOTH)) {
+ int i;
+
+ i = 2*(linePtr->numPoints-1);
+ linePtr->coordPtr[i] = linePtr->lastArrowPtr[0];
+ linePtr->coordPtr[i+1] = linePtr->lastArrowPtr[1];
+ ckfree(linePtr->lastArrowPtr);
+ linePtr->lastArrowPtr = NULL;
+ }
+ if (linePtr->arrow != ARROWS_NONE) {
+ ConfigureArrows(canvas, linePtr);
+ }
+
+ /*
+ * Recompute bounding box for line.
+ */
+
+ ComputeLineBbox(canvas, linePtr);
+
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DeleteLine --
+ *
+ * This function is called to clean up the data structure associated with
+ * a line item.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Resources associated with itemPtr are released.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+DeleteLine(
+ Tk_Canvas canvas, /* Info about overall canvas widget. */
+ Tk_Item *itemPtr, /* Item that is being deleted. */
+ Display *display) /* Display containing window for canvas. */
+{
+ LineItem *linePtr = (LineItem *) itemPtr;
+
+ Tk_DeleteOutline(display, &linePtr->outline);
+ if (linePtr->coordPtr != NULL) {
+ ckfree(linePtr->coordPtr);
+ }
+ if (linePtr->arrowGC != NULL) {
+ Tk_FreeGC(display, linePtr->arrowGC);
+ }
+ if (linePtr->firstArrowPtr != NULL) {
+ ckfree(linePtr->firstArrowPtr);
+ }
+ if (linePtr->lastArrowPtr != NULL) {
+ ckfree(linePtr->lastArrowPtr);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ComputeLineBbox --
+ *
+ * This function is invoked to compute the bounding box of all the pixels
+ * that may be drawn as part of a line.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The fields x1, y1, x2, and y2 are updated in the header for itemPtr.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ComputeLineBbox(
+ Tk_Canvas canvas, /* Canvas that contains item. */
+ LineItem *linePtr) /* Item whose bbos is to be recomputed. */
+{
+ double *coordPtr;
+ int i, intWidth;
+ double width;
+ Tk_State state = linePtr->header.state;
+ Tk_TSOffset *tsoffset;
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+
+ if (!(linePtr->numPoints) || (state == TK_STATE_HIDDEN)) {
+ linePtr->header.x1 = -1;
+ linePtr->header.x2 = -1;
+ linePtr->header.y1 = -1;
+ linePtr->header.y2 = -1;
+ return;
+ }
+
+ width = linePtr->outline.width;
+ if (Canvas(canvas)->currentItemPtr == (Tk_Item *)linePtr) {
+ if (linePtr->outline.activeWidth > width) {
+ width = linePtr->outline.activeWidth;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (linePtr->outline.disabledWidth > 0) {
+ width = linePtr->outline.disabledWidth;
+ }
+ }
+
+ coordPtr = linePtr->coordPtr;
+ linePtr->header.x1 = linePtr->header.x2 = (int) coordPtr[0];
+ linePtr->header.y1 = linePtr->header.y2 = (int) coordPtr[1];
+
+ /*
+ * Compute the bounding box of all the points in the line, then expand in
+ * all directions by the line's width to take care of butting or rounded
+ * corners and projecting or rounded caps. This expansion is an
+ * overestimate (worst-case is square root of two over two) but it's
+ * simple. Don't do anything special for curves. This causes an additional
+ * overestimate in the bounding box, but is faster.
+ */
+
+ for (i = 1, coordPtr = linePtr->coordPtr+2; i < linePtr->numPoints;
+ i++, coordPtr += 2) {
+ TkIncludePoint((Tk_Item *) linePtr, coordPtr);
+ }
+ width = linePtr->outline.width;
+ if (width < 1.0) {
+ width = 1.0;
+ }
+ if (linePtr->arrow != ARROWS_NONE) {
+ if (linePtr->arrow != ARROWS_LAST) {
+ TkIncludePoint((Tk_Item *) linePtr, linePtr->firstArrowPtr);
+ }
+ if (linePtr->arrow != ARROWS_FIRST) {
+ TkIncludePoint((Tk_Item *) linePtr, linePtr->lastArrowPtr);
+ }
+ }
+
+ tsoffset = &linePtr->outline.tsoffset;
+ if (tsoffset->flags & TK_OFFSET_INDEX) {
+ double *coordPtr = linePtr->coordPtr
+ + (tsoffset->flags & ~TK_OFFSET_INDEX);
+
+ if (tsoffset->flags <= 0) {
+ coordPtr = linePtr->coordPtr;
+ if ((linePtr->arrow == ARROWS_FIRST)
+ || (linePtr->arrow == ARROWS_BOTH)) {
+ coordPtr = linePtr->firstArrowPtr;
+ }
+ }
+ if (tsoffset->flags > (linePtr->numPoints * 2)) {
+ coordPtr = linePtr->coordPtr + (linePtr->numPoints * 2);
+ if ((linePtr->arrow == ARROWS_LAST)
+ || (linePtr->arrow == ARROWS_BOTH)) {
+ coordPtr = linePtr->lastArrowPtr;
+ }
+ }
+ tsoffset->xoffset = (int) (coordPtr[0] + 0.5);
+ tsoffset->yoffset = (int) (coordPtr[1] + 0.5);
+ } else {
+ if (tsoffset->flags & TK_OFFSET_LEFT) {
+ tsoffset->xoffset = linePtr->header.x1;
+ } else if (tsoffset->flags & TK_OFFSET_CENTER) {
+ tsoffset->xoffset = (linePtr->header.x1 + linePtr->header.x2)/2;
+ } else if (tsoffset->flags & TK_OFFSET_RIGHT) {
+ tsoffset->xoffset = linePtr->header.x2;
+ }
+ if (tsoffset->flags & TK_OFFSET_TOP) {
+ tsoffset->yoffset = linePtr->header.y1;
+ } else if (tsoffset->flags & TK_OFFSET_MIDDLE) {
+ tsoffset->yoffset = (linePtr->header.y1 + linePtr->header.y2)/2;
+ } else if (tsoffset->flags & TK_OFFSET_BOTTOM) {
+ tsoffset->yoffset = linePtr->header.y2;
+ }
+ }
+
+ intWidth = (int) (width + 0.5);
+ linePtr->header.x1 -= intWidth;
+ linePtr->header.x2 += intWidth;
+ linePtr->header.y1 -= intWidth;
+ linePtr->header.y2 += intWidth;
+
+ if (linePtr->numPoints == 1) {
+ linePtr->header.x1 -= 1;
+ linePtr->header.x2 += 1;
+ linePtr->header.y1 -= 1;
+ linePtr->header.y2 += 1;
+ return;
+ }
+
+ /*
+ * For mitered lines, make a second pass through all the points. Compute
+ * the locations of the two miter vertex points and add those into the
+ * bounding box.
+ */
+
+ if (linePtr->joinStyle == JoinMiter) {
+ for (i = linePtr->numPoints, coordPtr = linePtr->coordPtr; i >= 3;
+ i--, coordPtr += 2) {
+ double miter[4];
+ int j;
+
+ if (TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4,
+ width, miter, miter+2)) {
+ for (j = 0; j < 4; j += 2) {
+ TkIncludePoint((Tk_Item *) linePtr, miter+j);
+ }
+ }
+ }
+ }
+
+ /*
+ * Add in the sizes of arrowheads, if any.
+ */
+
+ if (linePtr->arrow != ARROWS_NONE) {
+ if (linePtr->arrow != ARROWS_LAST) {
+ for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;
+ i++, coordPtr += 2) {
+ TkIncludePoint((Tk_Item *) linePtr, coordPtr);
+ }
+ }
+ if (linePtr->arrow != ARROWS_FIRST) {
+ for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;
+ i++, coordPtr += 2) {
+ TkIncludePoint((Tk_Item *) linePtr, coordPtr);
+ }
+ }
+ }
+
+ /*
+ * Add one more pixel of fudge factor just to be safe (e.g. X may round
+ * differently than we do).
+ */
+
+ linePtr->header.x1 -= 1;
+ linePtr->header.x2 += 1;
+ linePtr->header.y1 -= 1;
+ linePtr->header.y2 += 1;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DisplayLine --
+ *
+ * This function is invoked to draw a line item in a given drawable.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * ItemPtr is drawn in drawable using the transformation information in
+ * canvas.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+DisplayLine(
+ Tk_Canvas canvas, /* Canvas that contains item. */
+ Tk_Item *itemPtr, /* Item to be displayed. */
+ Display *display, /* Display on which to draw item. */
+ Drawable drawable, /* Pixmap or window in which to draw item. */
+ int x, int y, int width, int height)
+ /* Describes region of canvas that must be
+ * redisplayed (not used). */
+{
+ LineItem *linePtr = (LineItem *) itemPtr;
+ XPoint staticPoints[MAX_STATIC_POINTS*3];
+ XPoint *pointPtr;
+ double linewidth;
+ int numPoints;
+ Tk_State state = itemPtr->state;
+
+ if (!linePtr->numPoints || (linePtr->outline.gc == NULL)) {
+ return;
+ }
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+ linewidth = linePtr->outline.width;
+ if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (linePtr->outline.activeWidth != linewidth) {
+ linewidth = linePtr->outline.activeWidth;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (linePtr->outline.disabledWidth != linewidth) {
+ linewidth = linePtr->outline.disabledWidth;
+ }
+ }
+ /*
+ * Build up an array of points in screen coordinates. Use a static array
+ * unless the line has an enormous number of points; in this case,
+ * dynamically allocate an array. For smoothed lines, generate the curve
+ * points on each redisplay.
+ */
+
+ if ((linePtr->smooth) && (linePtr->numPoints > 2)) {
+ numPoints = linePtr->smooth->coordProc(canvas, NULL,
+ linePtr->numPoints, linePtr->splineSteps, NULL, NULL);
+ } else {
+ numPoints = linePtr->numPoints;
+ }
+
+ if (numPoints <= MAX_STATIC_POINTS) {
+ pointPtr = staticPoints;
+ } else {
+ pointPtr = ckalloc(numPoints * 3 * sizeof(XPoint));
+ }
+
+ if ((linePtr->smooth) && (linePtr->numPoints > 2)) {
+ numPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr,
+ linePtr->numPoints, linePtr->splineSteps, pointPtr, NULL);
+ } else {
+ numPoints = TkCanvTranslatePath((TkCanvas *) canvas, numPoints,
+ linePtr->coordPtr, 0, pointPtr);
+ }
+
+ /*
+ * Display line, the free up line storage if it was dynamically allocated.
+ * If we're stippling, then modify the stipple offset in the GC. Be sure
+ * to reset the offset when done, since the GC is supposed to be
+ * read-only.
+ */
+
+ if (Tk_ChangeOutlineGC(canvas, itemPtr, &linePtr->outline)) {
+ Tk_CanvasSetOffset(canvas, linePtr->arrowGC,
+ &linePtr->outline.tsoffset);
+ }
+ if (numPoints > 1) {
+ XDrawLines(display, drawable, linePtr->outline.gc, pointPtr, numPoints,
+ CoordModeOrigin);
+ } else {
+ int intwidth = (int) (linewidth + 0.5);
+
+ if (intwidth < 1) {
+ intwidth = 1;
+ }
+ XFillArc(display, drawable, linePtr->outline.gc,
+ pointPtr->x - intwidth/2, pointPtr->y - intwidth/2,
+ (unsigned) intwidth+1, (unsigned) intwidth+1, 0, 64*360);
+ }
+ if (pointPtr != staticPoints) {
+ ckfree(pointPtr);
+ }
+
+ /*
+ * Display arrowheads, if they are wanted.
+ */
+
+ if (linePtr->firstArrowPtr != NULL) {
+ TkFillPolygon(canvas, linePtr->firstArrowPtr, PTS_IN_ARROW,
+ display, drawable, linePtr->arrowGC, NULL);
+ }
+ if (linePtr->lastArrowPtr != NULL) {
+ TkFillPolygon(canvas, linePtr->lastArrowPtr, PTS_IN_ARROW,
+ display, drawable, linePtr->arrowGC, NULL);
+ }
+ if (Tk_ResetOutlineGC(canvas, itemPtr, &linePtr->outline)) {
+ XSetTSOrigin(display, linePtr->arrowGC, 0, 0);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * LineInsert --
+ *
+ * Insert coords into a line item at a given index.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The coords in the given item is modified.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+LineInsert(
+ Tk_Canvas canvas, /* Canvas containing text item. */
+ Tk_Item *itemPtr, /* Line item to be modified. */
+ int beforeThis, /* Index before which new coordinates are to
+ * be inserted. */
+ Tcl_Obj *obj) /* New coordinates to be inserted. */
+{
+ LineItem *linePtr = (LineItem *) itemPtr;
+ int length, objc, i;
+ double *newCoordPtr, *coordPtr;
+ Tk_State state = itemPtr->state;
+ Tcl_Obj **objv;
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+
+ if (!obj || (Tcl_ListObjGetElements(NULL, obj, &objc, &objv) != TCL_OK)
+ || !objc || objc&1) {
+ return;
+ }
+ length = 2*linePtr->numPoints;
+ if (beforeThis < 0) {
+ beforeThis = 0;
+ }
+ if (beforeThis > length) {
+ beforeThis = length;
+ }
+ if (linePtr->firstArrowPtr != NULL) {
+ linePtr->coordPtr[0] = linePtr->firstArrowPtr[0];
+ linePtr->coordPtr[1] = linePtr->firstArrowPtr[1];
+ }
+ if (linePtr->lastArrowPtr != NULL) {
+ linePtr->coordPtr[length-2] = linePtr->lastArrowPtr[0];
+ linePtr->coordPtr[length-1] = linePtr->lastArrowPtr[1];
+ }
+ newCoordPtr = ckalloc(sizeof(double) * (length + objc));
+ for (i=0; i<beforeThis; i++) {
+ newCoordPtr[i] = linePtr->coordPtr[i];
+ }
+ for (i=0; i<objc; i++) {
+ if (Tcl_GetDoubleFromObj(NULL, objv[i],
+ &newCoordPtr[i + beforeThis]) != TCL_OK) {
+ Tcl_ResetResult(Canvas(canvas)->interp);
+ ckfree(newCoordPtr);
+ return;
+ }
+ }
+
+ for (i=beforeThis; i<length; i++) {
+ newCoordPtr[i+objc] = linePtr->coordPtr[i];
+ }
+ if (linePtr->coordPtr) {
+ ckfree(linePtr->coordPtr);
+ }
+ linePtr->coordPtr = newCoordPtr;
+ length += objc ;
+ linePtr->numPoints = length / 2;
+
+ if ((length > 3) && (state != TK_STATE_HIDDEN)) {
+ /*
+ * This is some optimizing code that will result that only the part of
+ * the polygon that changed (and the objects that are overlapping with
+ * that part) need to be redrawn. A special flag is set that instructs
+ * the general canvas code not to redraw the whole object. If this
+ * flag is not set, the canvas will do the redrawing, otherwise I have
+ * to do it here.
+ */
+
+ itemPtr->redraw_flags |= TK_ITEM_DONT_REDRAW;
+
+ if (beforeThis > 0) {
+ beforeThis -= 2;
+ objc += 2;
+ }
+ if (beforeThis+objc < length) {
+ objc += 2;
+ }
+ if (linePtr->smooth) {
+ if (beforeThis > 0) {
+ beforeThis -= 2;
+ objc += 2;
+ }
+ if (beforeThis+objc+2 < length) {
+ objc += 2;
+ }
+ }
+ itemPtr->x1 = itemPtr->x2 = (int) linePtr->coordPtr[beforeThis];
+ itemPtr->y1 = itemPtr->y2 = (int) linePtr->coordPtr[beforeThis+1];
+ if ((linePtr->firstArrowPtr != NULL) && (beforeThis < 1)) {
+ /*
+ * Include old first arrow.
+ */
+
+ for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;
+ i++, coordPtr += 2) {
+ TkIncludePoint(itemPtr, coordPtr);
+ }
+ }
+ if ((linePtr->lastArrowPtr != NULL) && (beforeThis+objc >= length)) {
+ /*
+ * Include old last arrow.
+ */
+
+ for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;
+ i++, coordPtr += 2) {
+ TkIncludePoint(itemPtr, coordPtr);
+ }
+ }
+ coordPtr = linePtr->coordPtr + beforeThis + 2;
+ for (i=2; i<objc; i+=2) {
+ TkIncludePoint(itemPtr, coordPtr);
+ coordPtr += 2;
+ }
+ }
+ if (linePtr->firstArrowPtr != NULL) {
+ ckfree(linePtr->firstArrowPtr);
+ linePtr->firstArrowPtr = NULL;
+ }
+ if (linePtr->lastArrowPtr != NULL) {
+ ckfree(linePtr->lastArrowPtr);
+ linePtr->lastArrowPtr = NULL;
+ }
+ if (linePtr->arrow != ARROWS_NONE) {
+ ConfigureArrows(canvas, linePtr);
+ }
+
+ if (itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW) {
+ double width;
+ int intWidth;
+
+ if ((linePtr->firstArrowPtr != NULL) && (beforeThis > 2)) {
+ /*
+ * Include new first arrow.
+ */
+
+ for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;
+ i++, coordPtr += 2) {
+ TkIncludePoint(itemPtr, coordPtr);
+ }
+ }
+ if ((linePtr->lastArrowPtr != NULL) && (beforeThis+objc < length-2)) {
+ /*
+ * Include new right arrow.
+ */
+
+ for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;
+ i++, coordPtr += 2) {
+ TkIncludePoint(itemPtr, coordPtr);
+ }
+ }
+ width = linePtr->outline.width;
+ if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (linePtr->outline.activeWidth > width) {
+ width = linePtr->outline.activeWidth;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (linePtr->outline.disabledWidth > 0) {
+ width = linePtr->outline.disabledWidth;
+ }
+ }
+ intWidth = (int) (width + 0.5);
+ if (intWidth < 1) {
+ intWidth = 1;
+ }
+ itemPtr->x1 -= intWidth;
+ itemPtr->y1 -= intWidth;
+ itemPtr->x2 += intWidth;
+ itemPtr->y2 += intWidth;
+ Tk_CanvasEventuallyRedraw(canvas, itemPtr->x1, itemPtr->y1,
+ itemPtr->x2, itemPtr->y2);
+ }
+
+ ComputeLineBbox(canvas, linePtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * LineDeleteCoords --
+ *
+ * Delete one or more coordinates from a line item.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Characters between "first" and "last", inclusive, get deleted from
+ * itemPtr.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+LineDeleteCoords(
+ Tk_Canvas canvas, /* Canvas containing itemPtr. */
+ Tk_Item *itemPtr, /* Item in which to delete characters. */
+ int first, /* Index of first character to delete. */
+ int last) /* Index of last character to delete. */
+{
+ LineItem *linePtr = (LineItem *) itemPtr;
+ int count, i, first1, last1;
+ int length = 2*linePtr->numPoints;
+ double *coordPtr;
+ Tk_State state = itemPtr->state;
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+
+ first &= -2;
+ last &= -2;
+
+ if (first < 0) {
+ first = 0;
+ }
+ if (last >= length) {
+ last = length-2;
+ }
+ if (first > last) {
+ return;
+ }
+ if (linePtr->firstArrowPtr != NULL) {
+ linePtr->coordPtr[0] = linePtr->firstArrowPtr[0];
+ linePtr->coordPtr[1] = linePtr->firstArrowPtr[1];
+ }
+ if (linePtr->lastArrowPtr != NULL) {
+ linePtr->coordPtr[length-2] = linePtr->lastArrowPtr[0];
+ linePtr->coordPtr[length-1] = linePtr->lastArrowPtr[1];
+ }
+ first1 = first;
+ last1 = last;
+ if (first1 > 0) {
+ first1 -= 2;
+ }
+ if (last1 < length-2) {
+ last1 += 2;
+ }
+ if (linePtr->smooth) {
+ if (first1 > 0) {
+ first1 -= 2;
+ }
+ if (last1 < length-2) {
+ last1 += 2;
+ }
+ }
+
+ if ((first1 >= 2) || (last1 < length-2)) {
+ /*
+ * This is some optimizing code that will result that only the part of
+ * the line that changed (and the objects that are overlapping with
+ * that part) need to be redrawn. A special flag is set that instructs
+ * the general canvas code not to redraw the whole object. If this
+ * flag is set, the redrawing has to be done here, otherwise the
+ * general Canvas code will take care of it.
+ */
+
+ itemPtr->redraw_flags |= TK_ITEM_DONT_REDRAW;
+ itemPtr->x1 = itemPtr->x2 = (int) linePtr->coordPtr[first1];
+ itemPtr->y1 = itemPtr->y2 = (int) linePtr->coordPtr[first1+1];
+ if ((linePtr->firstArrowPtr != NULL) && (first1 < 2)) {
+ /*
+ * Include old first arrow.
+ */
+
+ for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;
+ i++, coordPtr += 2) {
+ TkIncludePoint(itemPtr, coordPtr);
+ }
+ }
+ if ((linePtr->lastArrowPtr != NULL) && (last1 >= length-2)) {
+ /*
+ * Include old last arrow.
+ */
+
+ for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;
+ i++, coordPtr += 2) {
+ TkIncludePoint(itemPtr, coordPtr);
+ }
+ }
+ coordPtr = linePtr->coordPtr+first1+2;
+ for (i=first1+2; i<=last1; i+=2) {
+ TkIncludePoint(itemPtr, coordPtr);
+ coordPtr += 2;
+ }
+ }
+
+ count = last + 2 - first;
+ for (i=last+2; i<length; i++) {
+ linePtr->coordPtr[i-count] = linePtr->coordPtr[i];
+ }
+ linePtr->numPoints -= count/2;
+ if (linePtr->firstArrowPtr != NULL) {
+ ckfree(linePtr->firstArrowPtr);
+ linePtr->firstArrowPtr = NULL;
+ }
+ if (linePtr->lastArrowPtr != NULL) {
+ ckfree(linePtr->lastArrowPtr);
+ linePtr->lastArrowPtr = NULL;
+ }
+ if (linePtr->arrow != ARROWS_NONE) {
+ ConfigureArrows(canvas, linePtr);
+ }
+ if (itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW) {
+ double width;
+ int intWidth;
+
+ if ((linePtr->firstArrowPtr != NULL) && (first1 < 4)) {
+ /*
+ * Include new first arrow.
+ */
+
+ for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;
+ i++, coordPtr += 2) {
+ TkIncludePoint(itemPtr, coordPtr);
+ }
+ }
+ if ((linePtr->lastArrowPtr != NULL) && (last1 > length-4)) {
+ /*
+ * Include new right arrow.
+ */
+
+ for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;
+ i++, coordPtr += 2) {
+ TkIncludePoint(itemPtr, coordPtr);
+ }
+ }
+ width = linePtr->outline.width;
+ if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (linePtr->outline.activeWidth > width) {
+ width = linePtr->outline.activeWidth;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (linePtr->outline.disabledWidth > 0) {
+ width = linePtr->outline.disabledWidth;
+ }
+ }
+ intWidth = (int) (width + 0.5);
+ if (intWidth < 1) {
+ intWidth = 1;
+ }
+ itemPtr->x1 -= intWidth;
+ itemPtr->y1 -= intWidth;
+ itemPtr->x2 += intWidth;
+ itemPtr->y2 += intWidth;
+ Tk_CanvasEventuallyRedraw(canvas, itemPtr->x1, itemPtr->y1,
+ itemPtr->x2, itemPtr->y2);
+ }
+ ComputeLineBbox(canvas, linePtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * LineToPoint --
+ *
+ * Computes the distance from a given point to a given line, in canvas
+ * units.
+ *
+ * Results:
+ * The return value is 0 if the point whose x and y coordinates are
+ * pointPtr[0] and pointPtr[1] is inside the line. If the point isn't
+ * inside the line then the return value is the distance from the point
+ * to the line.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static double
+LineToPoint(
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item to check against point. */
+ double *pointPtr) /* Pointer to x and y coordinates. */
+{
+ Tk_State state = itemPtr->state;
+ LineItem *linePtr = (LineItem *) itemPtr;
+ double *coordPtr, *linePoints;
+ double staticSpace[2*MAX_STATIC_POINTS];
+ double poly[10];
+ double bestDist, dist, width;
+ int numPoints, count;
+ int changedMiterToBevel; /* Non-zero means that a mitered corner had to
+ * be treated as beveled after all because the
+ * angle was < 11 degrees. */
+
+ bestDist = 1.0e36;
+
+ /*
+ * Handle smoothed lines by generating an expanded set of points against
+ * which to do the check.
+ */
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+
+ width = linePtr->outline.width;
+ if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (linePtr->outline.activeWidth > width) {
+ width = linePtr->outline.activeWidth;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (linePtr->outline.disabledWidth > 0) {
+ width = linePtr->outline.disabledWidth;
+ }
+ }
+
+ if ((linePtr->smooth) && (linePtr->numPoints > 2)) {
+ numPoints = linePtr->smooth->coordProc(canvas, NULL,
+ linePtr->numPoints, linePtr->splineSteps, NULL, NULL);
+ if (numPoints <= MAX_STATIC_POINTS) {
+ linePoints = staticSpace;
+ } else {
+ linePoints = ckalloc(2 * numPoints * sizeof(double));
+ }
+ numPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr,
+ linePtr->numPoints, linePtr->splineSteps, NULL, linePoints);
+ } else {
+ numPoints = linePtr->numPoints;
+ linePoints = linePtr->coordPtr;
+ }
+
+ if (width < 1.0) {
+ width = 1.0;
+ }
+
+ if (!numPoints || itemPtr->state == TK_STATE_HIDDEN) {
+ return bestDist;
+ } else if (numPoints == 1) {
+ bestDist = hypot(linePoints[0]-pointPtr[0], linePoints[1]-pointPtr[1])
+ - width/2.0;
+ if (bestDist < 0) {
+ bestDist = 0;
+ }
+ return bestDist;
+ }
+
+ /*
+ * The overall idea is to iterate through all of the edges of the line,
+ * computing a polygon for each edge and testing the point against that
+ * polygon. In addition, there are additional tests to deal with rounded
+ * joints and caps.
+ */
+
+ changedMiterToBevel = 0;
+ for (count = numPoints, coordPtr = linePoints; count >= 2;
+ count--, coordPtr += 2) {
+ /*
+ * If rounding is done around the first point then compute the
+ * distance between the point and the point.
+ */
+
+ if (((linePtr->capStyle == CapRound) && (count == numPoints))
+ || ((linePtr->joinStyle == JoinRound)
+ && (count != numPoints))) {
+ dist = hypot(coordPtr[0] - pointPtr[0], coordPtr[1] - pointPtr[1])
+ - width/2.0;
+ if (dist <= 0.0) {
+ bestDist = 0.0;
+ goto done;
+ } else if (dist < bestDist) {
+ bestDist = dist;
+ }
+ }
+
+ /*
+ * Compute the polygonal shape corresponding to this edge, consisting
+ * of two points for the first point of the edge and two points for
+ * the last point of the edge.
+ */
+
+ if (count == numPoints) {
+ TkGetButtPoints(coordPtr+2, coordPtr, width,
+ linePtr->capStyle == CapProjecting, poly, poly+2);
+ } else if ((linePtr->joinStyle == JoinMiter) && !changedMiterToBevel) {
+ poly[0] = poly[6];
+ poly[1] = poly[7];
+ poly[2] = poly[4];
+ poly[3] = poly[5];
+ } else {
+ TkGetButtPoints(coordPtr+2, coordPtr, width, 0, poly, poly+2);
+
+ /*
+ * If this line uses beveled joints, then check the distance to a
+ * polygon comprising the last two points of the previous polygon
+ * and the first two from this polygon; this checks the wedges
+ * that fill the mitered joint.
+ */
+
+ if ((linePtr->joinStyle == JoinBevel) || changedMiterToBevel) {
+ poly[8] = poly[0];
+ poly[9] = poly[1];
+ dist = TkPolygonToPoint(poly, 5, pointPtr);
+ if (dist <= 0.0) {
+ bestDist = 0.0;
+ goto done;
+ } else if (dist < bestDist) {
+ bestDist = dist;
+ }
+ changedMiterToBevel = 0;
+ }
+ }
+ if (count == 2) {
+ TkGetButtPoints(coordPtr, coordPtr+2, width,
+ linePtr->capStyle == CapProjecting, poly+4, poly+6);
+ } else if (linePtr->joinStyle == JoinMiter) {
+ if (TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4,
+ width, poly+4, poly+6) == 0) {
+ changedMiterToBevel = 1;
+ TkGetButtPoints(coordPtr, coordPtr+2, width, 0,
+ poly+4, poly+6);
+ }
+ } else {
+ TkGetButtPoints(coordPtr, coordPtr+2, width, 0,
+ poly+4, poly+6);
+ }
+ poly[8] = poly[0];
+ poly[9] = poly[1];
+ dist = TkPolygonToPoint(poly, 5, pointPtr);
+ if (dist <= 0.0) {
+ bestDist = 0.0;
+ goto done;
+ } else if (dist < bestDist) {
+ bestDist = dist;
+ }
+ }
+
+ /*
+ * If caps are rounded, check the distance to the cap around the final end
+ * point of the line.
+ */
+
+ if (linePtr->capStyle == CapRound) {
+ dist = hypot(coordPtr[0] - pointPtr[0], coordPtr[1] - pointPtr[1])
+ - width/2.0;
+ if (dist <= 0.0) {
+ bestDist = 0.0;
+ goto done;
+ } else if (dist < bestDist) {
+ bestDist = dist;
+ }
+ }
+
+ /*
+ * If there are arrowheads, check the distance to the arrowheads.
+ */
+
+ if (linePtr->arrow != ARROWS_NONE) {
+ if (linePtr->arrow != ARROWS_LAST) {
+ dist = TkPolygonToPoint(linePtr->firstArrowPtr, PTS_IN_ARROW,
+ pointPtr);
+ if (dist <= 0.0) {
+ bestDist = 0.0;
+ goto done;
+ } else if (dist < bestDist) {
+ bestDist = dist;
+ }
+ }
+ if (linePtr->arrow != ARROWS_FIRST) {
+ dist = TkPolygonToPoint(linePtr->lastArrowPtr, PTS_IN_ARROW,
+ pointPtr);
+ if (dist <= 0.0) {
+ bestDist = 0.0;
+ goto done;
+ } else if (dist < bestDist) {
+ bestDist = dist;
+ }
+ }
+ }
+
+ done:
+ if ((linePoints != staticSpace) && (linePoints != linePtr->coordPtr)) {
+ ckfree(linePoints);
+ }
+ return bestDist;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * LineToArea --
+ *
+ * This function is called to determine whether an item lies entirely
+ * inside, entirely outside, or overlapping a given rectangular area.
+ *
+ * Results:
+ * -1 is returned if the item is entirely outside the area, 0 if it
+ * overlaps, and 1 if it is entirely inside the given area.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+LineToArea(
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item to check against line. */
+ double *rectPtr)
+{
+ LineItem *linePtr = (LineItem *) itemPtr;
+ double staticSpace[2*MAX_STATIC_POINTS];
+ double *linePoints;
+ int numPoints, result;
+ double radius, width;
+ Tk_State state = itemPtr->state;
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+ width = linePtr->outline.width;
+ if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (linePtr->outline.activeWidth > width) {
+ width = linePtr->outline.activeWidth;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (linePtr->outline.disabledWidth > 0) {
+ width = linePtr->outline.disabledWidth;
+ }
+ }
+
+ radius = (width+1.0)/2.0;
+
+ if ((state == TK_STATE_HIDDEN) || !linePtr->numPoints) {
+ return -1;
+ } else if (linePtr->numPoints == 1) {
+ double oval[4];
+
+ oval[0] = linePtr->coordPtr[0]-radius;
+ oval[1] = linePtr->coordPtr[1]-radius;
+ oval[2] = linePtr->coordPtr[0]+radius;
+ oval[3] = linePtr->coordPtr[1]+radius;
+ return TkOvalToArea(oval, rectPtr);
+ }
+
+ /*
+ * Handle smoothed lines by generating an expanded set of points against
+ * which to do the check.
+ */
+
+ if ((linePtr->smooth) && (linePtr->numPoints > 2)) {
+ numPoints = linePtr->smooth->coordProc(canvas, NULL,
+ linePtr->numPoints, linePtr->splineSteps, NULL, NULL);
+ if (numPoints <= MAX_STATIC_POINTS) {
+ linePoints = staticSpace;
+ } else {
+ linePoints = ckalloc(2 * numPoints * sizeof(double));
+ }
+ numPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr,
+ linePtr->numPoints, linePtr->splineSteps, NULL, linePoints);
+ } else {
+ numPoints = linePtr->numPoints;
+ linePoints = linePtr->coordPtr;
+ }
+
+ /*
+ * Check the segments of the line.
+ */
+
+ if (width < 1.0) {
+ width = 1.0;
+ }
+
+ result = TkThickPolyLineToArea(linePoints, numPoints, width,
+ linePtr->capStyle, linePtr->joinStyle, rectPtr);
+ if (result == 0) {
+ goto done;
+ }
+
+ /*
+ * Check arrowheads, if any.
+ */
+
+ if (linePtr->arrow != ARROWS_NONE) {
+ if (linePtr->arrow != ARROWS_LAST) {
+ if (TkPolygonToArea(linePtr->firstArrowPtr, PTS_IN_ARROW,
+ rectPtr) != result) {
+ result = 0;
+ goto done;
+ }
+ }
+ if (linePtr->arrow != ARROWS_FIRST) {
+ if (TkPolygonToArea(linePtr->lastArrowPtr, PTS_IN_ARROW,
+ rectPtr) != result) {
+ result = 0;
+ goto done;
+ }
+ }
+ }
+
+ done:
+ if ((linePoints != staticSpace) && (linePoints != linePtr->coordPtr)) {
+ ckfree(linePoints);
+ }
+ return result;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ScaleLine --
+ *
+ * This function is invoked to rescale a line item.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The line referred to by itemPtr is rescaled so that the following
+ * transformation is applied to all point coordinates:
+ * x' = originX + scaleX*(x-originX)
+ * y' = originY + scaleY*(y-originY)
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ScaleLine(
+ Tk_Canvas canvas, /* Canvas containing line. */
+ Tk_Item *itemPtr, /* Line to be scaled. */
+ double originX, double originY,
+ /* Origin about which to scale rect. */
+ double scaleX, /* Amount to scale in X direction. */
+ double scaleY) /* Amount to scale in Y direction. */
+{
+ LineItem *linePtr = (LineItem *) itemPtr;
+ double *coordPtr;
+ int i;
+
+ /*
+ * Delete any arrowheads before scaling all the points (so that the
+ * end-points of the line get restored).
+ */
+
+ if (linePtr->firstArrowPtr != NULL) {
+ linePtr->coordPtr[0] = linePtr->firstArrowPtr[0];
+ linePtr->coordPtr[1] = linePtr->firstArrowPtr[1];
+ ckfree(linePtr->firstArrowPtr);
+ linePtr->firstArrowPtr = NULL;
+ }
+ if (linePtr->lastArrowPtr != NULL) {
+ int i;
+
+ i = 2*(linePtr->numPoints-1);
+ linePtr->coordPtr[i] = linePtr->lastArrowPtr[0];
+ linePtr->coordPtr[i+1] = linePtr->lastArrowPtr[1];
+ ckfree(linePtr->lastArrowPtr);
+ linePtr->lastArrowPtr = NULL;
+ }
+ for (i = 0, coordPtr = linePtr->coordPtr; i < linePtr->numPoints;
+ i++, coordPtr += 2) {
+ coordPtr[0] = originX + scaleX*(*coordPtr - originX);
+ coordPtr[1] = originY + scaleY*(coordPtr[1] - originY);
+ }
+ if (linePtr->arrow != ARROWS_NONE) {
+ ConfigureArrows(canvas, linePtr);
+ }
+ ComputeLineBbox(canvas, linePtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * GetLineIndex --
+ *
+ * Parse an index into a line item and return either its value or an
+ * error.
+ *
+ * Results:
+ * A standard Tcl result. If all went well, then *indexPtr is filled in
+ * with the index (into itemPtr) corresponding to string. Otherwise an
+ * error message is left in interp->result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+GetLineIndex(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item for which the index is being
+ * specified. */
+ Tcl_Obj *obj, /* Specification of a particular coord in
+ * itemPtr's line. */
+ int *indexPtr) /* Where to store converted index. */
+{
+ LineItem *linePtr = (LineItem *) itemPtr;
+ const char *string = Tcl_GetString(obj);
+
+ if (string[0] == 'e') {
+ if (strncmp(string, "end", obj->length) == 0) {
+ *indexPtr = 2*linePtr->numPoints;
+ } else {
+ goto badIndex;
+ }
+ } else if (string[0] == '@') {
+ int i;
+ double x, y, bestDist, dist, *coordPtr;
+ char *end;
+ const char *p;
+
+ p = string+1;
+ x = strtod(p, &end);
+ if ((end == p) || (*end != ',')) {
+ goto badIndex;
+ }
+ p = end+1;
+ y = strtod(p, &end);
+ if ((end == p) || (*end != 0)) {
+ goto badIndex;
+ }
+ bestDist = 1.0e36;
+ coordPtr = linePtr->coordPtr;
+ *indexPtr = 0;
+ for (i=0; i<linePtr->numPoints; i++) {
+ dist = hypot(coordPtr[0] - x, coordPtr[1] - y);
+ if (dist < bestDist) {
+ bestDist = dist;
+ *indexPtr = 2*i;
+ }
+ coordPtr += 2;
+ }
+ } else {
+ if (Tcl_GetIntFromObj(interp, obj, indexPtr) != TCL_OK) {
+ goto badIndex;
+ }
+ *indexPtr &= -2; /* If index is odd, make it even. */
+ if (*indexPtr < 0){
+ *indexPtr = 0;
+ } else if (*indexPtr > (2*linePtr->numPoints)) {
+ *indexPtr = (2*linePtr->numPoints);
+ }
+ }
+ return TCL_OK;
+
+ /*
+ * Some of the paths here leave messages in interp->result, so we have to
+ * clear it out before storing our own message.
+ */
+
+ badIndex:
+ Tcl_ResetResult(interp);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad index \"%s\"", string));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "ITEM_INDEX", "LINE", NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TranslateLine --
+ *
+ * This function is called to move a line by a given amount.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The position of the line is offset by (xDelta, yDelta), and the
+ * bounding box is updated in the generic part of the item structure.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+TranslateLine(
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item that is being moved. */
+ double deltaX, double deltaY)
+ /* Amount by which item is to be moved. */
+{
+ LineItem *linePtr = (LineItem *) itemPtr;
+ double *coordPtr;
+ int i;
+
+ for (i = 0, coordPtr = linePtr->coordPtr; i < linePtr->numPoints;
+ i++, coordPtr += 2) {
+ coordPtr[0] += deltaX;
+ coordPtr[1] += deltaY;
+ }
+ if (linePtr->firstArrowPtr != NULL) {
+ for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;
+ i++, coordPtr += 2) {
+ coordPtr[0] += deltaX;
+ coordPtr[1] += deltaY;
+ }
+ }
+ if (linePtr->lastArrowPtr != NULL) {
+ for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;
+ i++, coordPtr += 2) {
+ coordPtr[0] += deltaX;
+ coordPtr[1] += deltaY;
+ }
+ }
+ ComputeLineBbox(canvas, linePtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ParseArrowShape --
+ *
+ * This function is called back during option parsing to parse arrow
+ * shape information.
+ *
+ * Results:
+ * The return value is a standard Tcl result: TCL_OK means that the arrow
+ * shape information was parsed ok, and TCL_ERROR means it couldn't be
+ * parsed.
+ *
+ * Side effects:
+ * Arrow information in recordPtr is updated.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+ParseArrowShape(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tk_Window tkwin, /* Not used. */
+ const char *value, /* Textual specification of arrow shape. */
+ char *recordPtr, /* Pointer to item record in which to store
+ * arrow information. */
+ int offset) /* Offset of shape information in widget
+ * record. */
+{
+ LineItem *linePtr = (LineItem *) recordPtr;
+ double a, b, c;
+ int argc;
+ const char **argv = NULL;
+
+ if (offset != Tk_Offset(LineItem, arrowShapeA)) {
+ Tcl_Panic("ParseArrowShape received bogus offset");
+ }
+
+ if (Tcl_SplitList(interp, (char *) value, &argc, &argv) != TCL_OK) {
+ goto syntaxError;
+ } else if (argc != 3) {
+ goto syntaxError;
+ }
+ if ((Tk_CanvasGetCoord(interp, linePtr->canvas, argv[0], &a) != TCL_OK)
+ || (Tk_CanvasGetCoord(interp, linePtr->canvas, argv[1], &b)
+ != TCL_OK)
+ || (Tk_CanvasGetCoord(interp, linePtr->canvas, argv[2], &c)
+ != TCL_OK)) {
+ goto syntaxError;
+ }
+
+ linePtr->arrowShapeA = (float) a;
+ linePtr->arrowShapeB = (float) b;
+ linePtr->arrowShapeC = (float) c;
+ ckfree(argv);
+ return TCL_OK;
+
+ syntaxError:
+ Tcl_ResetResult(interp);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad arrow shape \"%s\": must be list with three numbers",
+ value));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "ARROW_SHAPE", NULL);
+ if (argv != NULL) {
+ ckfree(argv);
+ }
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * PrintArrowShape --
+ *
+ * This function is a callback invoked by the configuration code to
+ * return a printable value describing an arrow shape.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static const char *
+PrintArrowShape(
+ ClientData clientData, /* Not used. */
+ Tk_Window tkwin, /* Window associated with linePtr's widget. */
+ char *recordPtr, /* Pointer to item record containing current
+ * shape information. */
+ int offset, /* Offset of arrow information in record. */
+ Tcl_FreeProc **freeProcPtr) /* Store address of function to call to free
+ * string here. */
+{
+ LineItem *linePtr = (LineItem *) recordPtr;
+ char *buffer = ckalloc(120);
+
+ sprintf(buffer, "%.5g %.5g %.5g", linePtr->arrowShapeA,
+ linePtr->arrowShapeB, linePtr->arrowShapeC);
+ *freeProcPtr = TCL_DYNAMIC;
+ return buffer;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ArrowParseProc --
+ *
+ * This function is invoked during option processing to handle the
+ * "-arrow" option.
+ *
+ * Results:
+ * A standard Tcl return value.
+ *
+ * Side effects:
+ * The arrow for a given item gets replaced by the arrow indicated in the
+ * value argument.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+ArrowParseProc(
+ ClientData clientData, /* some flags.*/
+ Tcl_Interp *interp, /* Used for reporting errors. */
+ Tk_Window tkwin, /* Window containing canvas widget. */
+ const char *value, /* Value of option. */
+ char *widgRec, /* Pointer to record for item. */
+ int offset) /* Offset into item. */
+{
+ int c;
+ size_t length;
+
+ register Arrows *arrowPtr = (Arrows *) (widgRec + offset);
+
+ if (value == NULL || *value == 0) {
+ *arrowPtr = ARROWS_NONE;
+ return TCL_OK;
+ }
+
+ c = value[0];
+ length = strlen(value);
+
+ if ((c == 'n') && (strncmp(value, "none", length) == 0)) {
+ *arrowPtr = ARROWS_NONE;
+ return TCL_OK;
+ }
+ if ((c == 'f') && (strncmp(value, "first", length) == 0)) {
+ *arrowPtr = ARROWS_FIRST;
+ return TCL_OK;
+ }
+ if ((c == 'l') && (strncmp(value, "last", length) == 0)) {
+ *arrowPtr = ARROWS_LAST;
+ return TCL_OK;
+ }
+ if ((c == 'b') && (strncmp(value, "both", length) == 0)) {
+ *arrowPtr = ARROWS_BOTH;
+ return TCL_OK;
+ }
+
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad arrow spec \"%s\": must be none, first, last, or both",
+ value));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "ARROW", NULL);
+ *arrowPtr = ARROWS_NONE;
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ArrowPrintProc --
+ *
+ * This function is invoked by the Tk configuration code to produce a
+ * printable string for the "-arrow" configuration option.
+ *
+ * Results:
+ * The return value is a string describing the arrows for the item
+ * referred to by "widgRec". In addition, *freeProcPtr is filled in with
+ * the address of a function to call to free the result string when it's
+ * no longer needed (or NULL to indicate that the string doesn't need to
+ * be freed).
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static const char *
+ArrowPrintProc(
+ ClientData clientData, /* Ignored. */
+ Tk_Window tkwin, /* Window containing canvas widget. */
+ char *widgRec, /* Pointer to record for item. */
+ int offset, /* Offset into item. */
+ Tcl_FreeProc **freeProcPtr) /* Pointer to variable to fill in with
+ * information about how to reclaim storage
+ * for return string. */
+{
+ register Arrows *arrowPtr = (Arrows *) (widgRec + offset);
+
+ switch (*arrowPtr) {
+ case ARROWS_FIRST:
+ return "first";
+ case ARROWS_LAST:
+ return "last";
+ case ARROWS_BOTH:
+ return "both";
+ default:
+ return "none";
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ConfigureArrows --
+ *
+ * If arrowheads have been requested for a line, this function makes
+ * arrangements for the arrowheads.
+ *
+ * Results:
+ * Always returns TCL_OK.
+ *
+ * Side effects:
+ * Information in linePtr is set up for one or two arrowheads. The
+ * firstArrowPtr and lastArrowPtr polygons are allocated and initialized,
+ * if need be, and the end points of the line are adjusted so that a
+ * thick line doesn't stick out past the arrowheads.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+ConfigureArrows(
+ Tk_Canvas canvas, /* Canvas in which arrows will be displayed
+ * (interp and tkwin fields are needed). */
+ LineItem *linePtr) /* Item to configure for arrows. */
+{
+ double *poly, *coordPtr;
+ double dx, dy, length, sinTheta, cosTheta, temp;
+ double fracHeight; /* Line width as fraction of arrowhead
+ * width. */
+ double backup; /* Distance to backup end points so the line
+ * ends in the middle of the arrowhead. */
+ double vertX, vertY; /* Position of arrowhead vertex. */
+ double shapeA, shapeB, shapeC;
+ /* Adjusted coordinates (see explanation
+ * below). */
+ double width;
+ Tk_State state = linePtr->header.state;
+
+ if (linePtr->numPoints < 2) {
+ return TCL_OK;
+ }
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+
+ width = linePtr->outline.width;
+ if (Canvas(canvas)->currentItemPtr == (Tk_Item *)linePtr) {
+ if (linePtr->outline.activeWidth > width) {
+ width = linePtr->outline.activeWidth;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (linePtr->outline.disabledWidth > 0) {
+ width = linePtr->outline.disabledWidth;
+ }
+ }
+
+ /*
+ * The code below makes a tiny increase in the shape parameters for the
+ * line. This is a bit of a hack, but it seems to result in displays that
+ * more closely approximate the specified parameters. Without the
+ * adjustment, the arrows come out smaller than expected.
+ */
+
+ shapeA = linePtr->arrowShapeA + 0.001;
+ shapeB = linePtr->arrowShapeB + 0.001;
+ shapeC = linePtr->arrowShapeC + width/2.0 + 0.001;
+
+ /*
+ * If there's an arrowhead on the first point of the line, compute its
+ * polygon and adjust the first point of the line so that the line doesn't
+ * stick out past the leading edge of the arrowhead.
+ */
+
+ fracHeight = (width/2.0)/shapeC;
+ backup = fracHeight*shapeB + shapeA*(1.0 - fracHeight)/2.0;
+ if (linePtr->arrow != ARROWS_LAST) {
+ poly = linePtr->firstArrowPtr;
+ if (poly == NULL) {
+ poly = ckalloc(2 * PTS_IN_ARROW * sizeof(double));
+ poly[0] = poly[10] = linePtr->coordPtr[0];
+ poly[1] = poly[11] = linePtr->coordPtr[1];
+ linePtr->firstArrowPtr = poly;
+ }
+ dx = poly[0] - linePtr->coordPtr[2];
+ dy = poly[1] - linePtr->coordPtr[3];
+ length = hypot(dx, dy);
+ if (length == 0) {
+ sinTheta = cosTheta = 0.0;
+ } else {
+ sinTheta = dy/length;
+ cosTheta = dx/length;
+ }
+ vertX = poly[0] - shapeA*cosTheta;
+ vertY = poly[1] - shapeA*sinTheta;
+ temp = shapeC*sinTheta;
+ poly[2] = poly[0] - shapeB*cosTheta + temp;
+ poly[8] = poly[2] - 2*temp;
+ temp = shapeC*cosTheta;
+ poly[3] = poly[1] - shapeB*sinTheta - temp;
+ poly[9] = poly[3] + 2*temp;
+ poly[4] = poly[2]*fracHeight + vertX*(1.0-fracHeight);
+ poly[5] = poly[3]*fracHeight + vertY*(1.0-fracHeight);
+ poly[6] = poly[8]*fracHeight + vertX*(1.0-fracHeight);
+ poly[7] = poly[9]*fracHeight + vertY*(1.0-fracHeight);
+
+ /*
+ * Polygon done. Now move the first point towards the second so that
+ * the corners at the end of the line are inside the arrowhead.
+ */
+
+ linePtr->coordPtr[0] = poly[0] - backup*cosTheta;
+ linePtr->coordPtr[1] = poly[1] - backup*sinTheta;
+ }
+
+ /*
+ * Similar arrowhead calculation for the last point of the line.
+ */
+
+ if (linePtr->arrow != ARROWS_FIRST) {
+ coordPtr = linePtr->coordPtr + 2*(linePtr->numPoints-2);
+ poly = linePtr->lastArrowPtr;
+ if (poly == NULL) {
+ poly = ckalloc(2 * PTS_IN_ARROW * sizeof(double));
+ poly[0] = poly[10] = coordPtr[2];
+ poly[1] = poly[11] = coordPtr[3];
+ linePtr->lastArrowPtr = poly;
+ }
+ dx = poly[0] - coordPtr[0];
+ dy = poly[1] - coordPtr[1];
+ length = hypot(dx, dy);
+ if (length == 0) {
+ sinTheta = cosTheta = 0.0;
+ } else {
+ sinTheta = dy/length;
+ cosTheta = dx/length;
+ }
+ vertX = poly[0] - shapeA*cosTheta;
+ vertY = poly[1] - shapeA*sinTheta;
+ temp = shapeC * sinTheta;
+ poly[2] = poly[0] - shapeB*cosTheta + temp;
+ poly[8] = poly[2] - 2*temp;
+ temp = shapeC * cosTheta;
+ poly[3] = poly[1] - shapeB*sinTheta - temp;
+ poly[9] = poly[3] + 2*temp;
+ poly[4] = poly[2]*fracHeight + vertX*(1.0-fracHeight);
+ poly[5] = poly[3]*fracHeight + vertY*(1.0-fracHeight);
+ poly[6] = poly[8]*fracHeight + vertX*(1.0-fracHeight);
+ poly[7] = poly[9]*fracHeight + vertY*(1.0-fracHeight);
+ coordPtr[2] = poly[0] - backup*cosTheta;
+ coordPtr[3] = poly[1] - backup*sinTheta;
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * LineToPostscript --
+ *
+ * This function is called to generate Postscript for line items.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If an error occurs in
+ * generating Postscript then an error message is left in the interp's
+ * result, replacing whatever used to be there. If no error occurs, then
+ * Postscript for the item is appended to the result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+LineToPostscript(
+ Tcl_Interp *interp, /* Leave Postscript or error message here. */
+ Tk_Canvas canvas, /* Information about overall canvas. */
+ Tk_Item *itemPtr, /* Item for which Postscript is wanted. */
+ int prepass) /* 1 means this is a prepass to collect font
+ * information; 0 means final Postscript is
+ * being created. */
+{
+ LineItem *linePtr = (LineItem *) itemPtr;
+ int style;
+ double width;
+ XColor *color;
+ Pixmap stipple;
+ Tk_State state = itemPtr->state;
+ Tcl_Obj *psObj;
+ Tcl_InterpState interpState;
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+
+ width = linePtr->outline.width;
+ color = linePtr->outline.color;
+ stipple = linePtr->outline.stipple;
+ if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (linePtr->outline.activeWidth > width) {
+ width = linePtr->outline.activeWidth;
+ }
+ if (linePtr->outline.activeColor != NULL) {
+ color = linePtr->outline.activeColor;
+ }
+ if (linePtr->outline.activeStipple != None) {
+ stipple = linePtr->outline.activeStipple;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (linePtr->outline.disabledWidth > 0) {
+ width = linePtr->outline.disabledWidth;
+ }
+ if (linePtr->outline.disabledColor != NULL) {
+ color = linePtr->outline.disabledColor;
+ }
+ if (linePtr->outline.disabledStipple != None) {
+ stipple = linePtr->outline.disabledStipple;
+ }
+ }
+
+ if (color == NULL || linePtr->numPoints < 1 || linePtr->coordPtr == NULL){
+ return TCL_OK;
+ }
+
+ /*
+ * Make our working space.
+ */
+
+ psObj = Tcl_NewObj();
+ interpState = Tcl_SaveInterpState(interp, TCL_OK);
+
+ /*
+ * Check if we're just doing a "pixel".
+ */
+
+ if (linePtr->numPoints == 1) {
+ Tcl_AppendToObj(psObj, "matrix currentmatrix\n", -1);
+ Tcl_AppendPrintfToObj(psObj, "%.15g %.15g translate %.15g %.15g",
+ linePtr->coordPtr[0], Tk_CanvasPsY(canvas, linePtr->coordPtr[1]),
+ width/2.0, width/2.0);
+ Tcl_AppendToObj(psObj,
+ " scale 1 0 moveto 0 0 1 0 360 arc\nsetmatrix\n", -1);
+
+ Tcl_ResetResult(interp);
+ if (Tk_CanvasPsColor(interp, canvas, color) != TCL_OK) {
+ goto error;
+ }
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+
+ if (stipple != None) {
+ Tcl_AppendToObj(psObj, "clip ", -1);
+ Tcl_ResetResult(interp);
+ if (Tk_CanvasPsStipple(interp, canvas, stipple) != TCL_OK) {
+ goto error;
+ }
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+ } else {
+ Tcl_AppendToObj(psObj, "fill\n", -1);
+ }
+ goto done;
+ }
+
+ /*
+ * Generate a path for the line's center-line (do this differently for
+ * straight lines and smoothed lines).
+ */
+
+ Tcl_ResetResult(interp);
+ if ((!linePtr->smooth) || (linePtr->numPoints < 3)) {
+ Tk_CanvasPsPath(interp, canvas, linePtr->coordPtr, linePtr->numPoints);
+ } else if ((stipple == None) && linePtr->smooth->postscriptProc) {
+ linePtr->smooth->postscriptProc(interp, canvas, linePtr->coordPtr,
+ linePtr->numPoints, linePtr->splineSteps);
+ } else {
+ /*
+ * Special hack: Postscript printers don't appear to be able to turn a
+ * path drawn with "curveto"s into a clipping path without exceeding
+ * resource limits, so TkMakeBezierPostscript won't work for stippled
+ * curves. Instead, generate all of the intermediate points here and
+ * output them into the Postscript file with "lineto"s instead.
+ */
+
+ double staticPoints[2*MAX_STATIC_POINTS];
+ double *pointPtr;
+ int numPoints;
+
+ numPoints = linePtr->smooth->coordProc(canvas, NULL,
+ linePtr->numPoints, linePtr->splineSteps, NULL, NULL);
+ pointPtr = staticPoints;
+ if (numPoints > MAX_STATIC_POINTS) {
+ pointPtr = ckalloc(numPoints * 2 * sizeof(double));
+ }
+ numPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr,
+ linePtr->numPoints, linePtr->splineSteps, NULL, pointPtr);
+ Tk_CanvasPsPath(interp, canvas, pointPtr, numPoints);
+ if (pointPtr != staticPoints) {
+ ckfree(pointPtr);
+ }
+ }
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+
+ /*
+ * Set other line-drawing parameters and stroke out the line.
+ */
+
+ if (linePtr->capStyle == CapRound) {
+ style = 1;
+ } else if (linePtr->capStyle == CapProjecting) {
+ style = 2;
+ } else {
+ style = 0;
+ }
+ Tcl_AppendPrintfToObj(psObj, "%d setlinecap\n", style);
+ if (linePtr->joinStyle == JoinRound) {
+ style = 1;
+ } else if (linePtr->joinStyle == JoinBevel) {
+ style = 2;
+ } else {
+ style = 0;
+ }
+ Tcl_AppendPrintfToObj(psObj, "%d setlinejoin\n", style);
+
+ Tcl_ResetResult(interp);
+ if (Tk_CanvasPsOutline(canvas, itemPtr, &linePtr->outline) != TCL_OK) {
+ goto error;
+ }
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+
+ /*
+ * Output polygons for the arrowheads, if there are any.
+ */
+
+ if (linePtr->firstArrowPtr != NULL) {
+ if (stipple != None) {
+ Tcl_AppendToObj(psObj, "grestore gsave\n", -1);
+ }
+ if (ArrowheadPostscript(interp, canvas, linePtr,
+ linePtr->firstArrowPtr, psObj) != TCL_OK) {
+ goto error;
+ }
+ }
+ if (linePtr->lastArrowPtr != NULL) {
+ if (stipple != None) {
+ Tcl_AppendToObj(psObj, "grestore gsave\n", -1);
+ }
+ if (ArrowheadPostscript(interp, canvas, linePtr,
+ linePtr->lastArrowPtr, psObj) != TCL_OK) {
+ goto error;
+ }
+ }
+
+ /*
+ * Plug the accumulated postscript back into the result.
+ */
+
+ done:
+ (void) Tcl_RestoreInterpState(interp, interpState);
+ Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj);
+ Tcl_DecrRefCount(psObj);
+ return TCL_OK;
+
+ error:
+ Tcl_DiscardInterpState(interpState);
+ Tcl_DecrRefCount(psObj);
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ArrowheadPostscript --
+ *
+ * This function is called to generate Postscript for an arrowhead for a
+ * line item.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If an error occurs in
+ * generating Postscript then an error message is left in the interp's
+ * result, replacing whatever used to be there. If no error occurs, then
+ * Postscript for the arrowhead is appended to the given object.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+ArrowheadPostscript(
+ Tcl_Interp *interp, /* Leave error message here; non-error results
+ * will be discarded by caller. */
+ Tk_Canvas canvas, /* Information about overall canvas. */
+ LineItem *linePtr, /* Line item for which Postscript is being
+ * generated. */
+ double *arrowPtr, /* Pointer to first of five points describing
+ * arrowhead polygon. */
+ Tcl_Obj *psObj) /* Append postscript to this object. */
+{
+ Pixmap stipple;
+ Tk_State state = linePtr->header.state;
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+
+ stipple = linePtr->outline.stipple;
+ if (Canvas(canvas)->currentItemPtr == (Tk_Item *) linePtr) {
+ if (linePtr->outline.activeStipple!=None) {
+ stipple = linePtr->outline.activeStipple;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (linePtr->outline.activeStipple!=None) {
+ stipple = linePtr->outline.disabledStipple;
+ }
+ }
+
+ Tcl_ResetResult(interp);
+ Tk_CanvasPsPath(interp, canvas, arrowPtr, PTS_IN_ARROW);
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+
+ if (stipple != None) {
+ Tcl_AppendToObj(psObj, "clip ", -1);
+
+ Tcl_ResetResult(interp);
+ if (Tk_CanvasPsStipple(interp, canvas, stipple) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+ } else {
+ Tcl_AppendToObj(psObj, "fill\n", -1);
+ }
+ return TCL_OK;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkCanvPoly.c b/tk8.6/generic/tkCanvPoly.c
new file mode 100644
index 0000000..6a8f865
--- /dev/null
+++ b/tk8.6/generic/tkCanvPoly.c
@@ -0,0 +1,1999 @@
+/*
+ * tkCanvPoly.c --
+ *
+ * This file implements polygon items for canvas widgets.
+ *
+ * Copyright (c) 1991-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1998-2000 Ajuba Solutions.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkInt.h"
+#include "tkCanvas.h"
+
+/*
+ * The structure below defines the record for each polygon item.
+ */
+
+typedef struct PolygonItem {
+ Tk_Item header; /* Generic stuff that's the same for all
+ * types. MUST BE FIRST IN STRUCTURE. */
+ Tk_Outline outline; /* Outline structure */
+ int numPoints; /* Number of points in polygon. Polygon is
+ * always closed. */
+ int pointsAllocated; /* Number of points for which space is
+ * allocated at *coordPtr. */
+ double *coordPtr; /* Pointer to malloc-ed array containing x-
+ * and y-coords of all points in polygon.
+ * X-coords are even-valued indices, y-coords
+ * are corresponding odd-valued indices. */
+ int joinStyle; /* Join style for outline */
+ Tk_TSOffset tsoffset;
+ XColor *fillColor; /* Foreground color for polygon. */
+ XColor *activeFillColor; /* Foreground color for polygon if state is
+ * active. */
+ XColor *disabledFillColor; /* Foreground color for polygon if state is
+ * disabled. */
+ Pixmap fillStipple; /* Stipple bitmap for filling polygon. */
+ Pixmap activeFillStipple; /* Stipple bitmap for filling polygon if state
+ * is active. */
+ Pixmap disabledFillStipple; /* Stipple bitmap for filling polygon if state
+ * is disabled. */
+ GC fillGC; /* Graphics context for filling polygon. */
+ const Tk_SmoothMethod *smooth; /* Non-zero means draw shape smoothed (i.e.
+ * with Bezier splines). */
+ int splineSteps; /* Number of steps in each spline segment. */
+ int autoClosed; /* Zero means the given polygon was closed,
+ one means that we auto closed it. */
+} PolygonItem;
+
+/*
+ * Information used for parsing configuration specs:
+ */
+
+static const Tk_CustomOption smoothOption = {
+ TkSmoothParseProc, TkSmoothPrintProc, NULL
+};
+static const Tk_CustomOption stateOption = {
+ TkStateParseProc, TkStatePrintProc, INT2PTR(2)
+};
+static const Tk_CustomOption tagsOption = {
+ Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL
+};
+static const Tk_CustomOption dashOption = {
+ TkCanvasDashParseProc, TkCanvasDashPrintProc, NULL
+};
+static const Tk_CustomOption offsetOption = {
+ TkOffsetParseProc, TkOffsetPrintProc,
+ INT2PTR(TK_OFFSET_RELATIVE|TK_OFFSET_INDEX)
+};
+static const Tk_CustomOption pixelOption = {
+ TkPixelParseProc, TkPixelPrintProc, NULL
+};
+
+static const Tk_ConfigSpec configSpecs[] = {
+ {TK_CONFIG_CUSTOM, "-activedash", NULL, NULL,
+ NULL, Tk_Offset(PolygonItem, outline.activeDash),
+ TK_CONFIG_NULL_OK, &dashOption},
+ {TK_CONFIG_COLOR, "-activefill", NULL, NULL,
+ NULL, Tk_Offset(PolygonItem, activeFillColor), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_COLOR, "-activeoutline", NULL, NULL,
+ NULL, Tk_Offset(PolygonItem, outline.activeColor), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_BITMAP, "-activeoutlinestipple", NULL, NULL,
+ NULL, Tk_Offset(PolygonItem, outline.activeStipple),
+ TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_BITMAP, "-activestipple", NULL, NULL,
+ NULL, Tk_Offset(PolygonItem, activeFillStipple), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_CUSTOM, "-activewidth", NULL, NULL,
+ "0.0", Tk_Offset(PolygonItem, outline.activeWidth),
+ TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
+ {TK_CONFIG_CUSTOM, "-dash", NULL, NULL,
+ NULL, Tk_Offset(PolygonItem, outline.dash),
+ TK_CONFIG_NULL_OK, &dashOption},
+ {TK_CONFIG_PIXELS, "-dashoffset", NULL, NULL,
+ "0", Tk_Offset(PolygonItem, outline.offset),
+ TK_CONFIG_DONT_SET_DEFAULT, NULL},
+ {TK_CONFIG_CUSTOM, "-disableddash", NULL, NULL,
+ NULL, Tk_Offset(PolygonItem, outline.disabledDash),
+ TK_CONFIG_NULL_OK, &dashOption},
+ {TK_CONFIG_COLOR, "-disabledfill", NULL, NULL,
+ NULL, Tk_Offset(PolygonItem, disabledFillColor), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_COLOR, "-disabledoutline", NULL, NULL,
+ NULL, Tk_Offset(PolygonItem, outline.disabledColor),
+ TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_BITMAP, "-disabledoutlinestipple", NULL, NULL,
+ NULL, Tk_Offset(PolygonItem, outline.disabledStipple),
+ TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_BITMAP, "-disabledstipple", NULL, NULL,
+ NULL, Tk_Offset(PolygonItem, disabledFillStipple), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_CUSTOM, "-disabledwidth", NULL, NULL,
+ "0.0", Tk_Offset(PolygonItem, outline.disabledWidth),
+ TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
+ {TK_CONFIG_COLOR, "-fill", NULL, NULL,
+ "black", Tk_Offset(PolygonItem, fillColor), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_JOIN_STYLE, "-joinstyle", NULL, NULL,
+ "round", Tk_Offset(PolygonItem, joinStyle), TK_CONFIG_DONT_SET_DEFAULT, NULL},
+ {TK_CONFIG_CUSTOM, "-offset", NULL, NULL,
+ "0,0", Tk_Offset(PolygonItem, tsoffset),
+ TK_CONFIG_NULL_OK, &offsetOption},
+ {TK_CONFIG_COLOR, "-outline", NULL, NULL,
+ NULL, Tk_Offset(PolygonItem, outline.color), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_CUSTOM, "-outlineoffset", NULL, NULL,
+ "0,0", Tk_Offset(PolygonItem, outline.tsoffset),
+ TK_CONFIG_NULL_OK, &offsetOption},
+ {TK_CONFIG_BITMAP, "-outlinestipple", NULL, NULL,
+ NULL, Tk_Offset(PolygonItem, outline.stipple), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_CUSTOM, "-smooth", NULL, NULL,
+ "0", Tk_Offset(PolygonItem, smooth),
+ TK_CONFIG_DONT_SET_DEFAULT, &smoothOption},
+ {TK_CONFIG_INT, "-splinesteps", NULL, NULL,
+ "12", Tk_Offset(PolygonItem, splineSteps), TK_CONFIG_DONT_SET_DEFAULT, NULL},
+ {TK_CONFIG_CUSTOM, "-state", NULL, NULL,
+ NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption},
+ {TK_CONFIG_BITMAP, "-stipple", NULL, NULL,
+ NULL, Tk_Offset(PolygonItem, fillStipple), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_CUSTOM, "-tags", NULL, NULL,
+ NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
+ {TK_CONFIG_CUSTOM, "-width", NULL, NULL,
+ "1.0", Tk_Offset(PolygonItem, outline.width),
+ TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
+ {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}
+};
+
+/*
+ * Prototypes for functions defined in this file:
+ */
+
+static void ComputePolygonBbox(Tk_Canvas canvas,
+ PolygonItem *polyPtr);
+static int ConfigurePolygon(Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr, int objc,
+ Tcl_Obj *const objv[], int flags);
+static int CreatePolygon(Tcl_Interp *interp,
+ Tk_Canvas canvas, struct Tk_Item *itemPtr,
+ int objc, Tcl_Obj *const objv[]);
+static void DeletePolygon(Tk_Canvas canvas,
+ Tk_Item *itemPtr, Display *display);
+static void DisplayPolygon(Tk_Canvas canvas,
+ Tk_Item *itemPtr, Display *display, Drawable dst,
+ int x, int y, int width, int height);
+static int GetPolygonIndex(Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr,
+ Tcl_Obj *obj, int *indexPtr);
+static int PolygonCoords(Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr,
+ int objc, Tcl_Obj *const objv[]);
+static void PolygonDeleteCoords(Tk_Canvas canvas,
+ Tk_Item *itemPtr, int first, int last);
+static void PolygonInsert(Tk_Canvas canvas,
+ Tk_Item *itemPtr, int beforeThis, Tcl_Obj *obj);
+static int PolygonToArea(Tk_Canvas canvas,
+ Tk_Item *itemPtr, double *rectPtr);
+static double PolygonToPoint(Tk_Canvas canvas,
+ Tk_Item *itemPtr, double *pointPtr);
+static int PolygonToPostscript(Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr, int prepass);
+static void ScalePolygon(Tk_Canvas canvas,
+ Tk_Item *itemPtr, double originX, double originY,
+ double scaleX, double scaleY);
+static void TranslatePolygon(Tk_Canvas canvas,
+ Tk_Item *itemPtr, double deltaX, double deltaY);
+
+/*
+ * The structures below defines the polygon item type by means of functions
+ * that can be invoked by generic item code.
+ */
+
+Tk_ItemType tkPolygonType = {
+ "polygon", /* name */
+ sizeof(PolygonItem), /* itemSize */
+ CreatePolygon, /* createProc */
+ configSpecs, /* configSpecs */
+ ConfigurePolygon, /* configureProc */
+ PolygonCoords, /* coordProc */
+ DeletePolygon, /* deleteProc */
+ DisplayPolygon, /* displayProc */
+ TK_CONFIG_OBJS | TK_MOVABLE_POINTS, /* flags */
+ PolygonToPoint, /* pointProc */
+ PolygonToArea, /* areaProc */
+ PolygonToPostscript, /* postscriptProc */
+ ScalePolygon, /* scaleProc */
+ TranslatePolygon, /* translateProc */
+ GetPolygonIndex, /* indexProc */
+ NULL, /* icursorProc */
+ NULL, /* selectionProc */
+ PolygonInsert, /* insertProc */
+ PolygonDeleteCoords, /* dTextProc */
+ NULL, /* nextPtr */
+ NULL, 0, NULL, NULL
+};
+
+/*
+ * The definition below determines how large are static arrays used to hold
+ * spline points (splines larger than this have to have their arrays
+ * malloc-ed).
+ */
+
+#define MAX_STATIC_POINTS 200
+
+/*
+ *--------------------------------------------------------------
+ *
+ * CreatePolygon --
+ *
+ * This function is invoked to create a new polygon item in a canvas.
+ *
+ * Results:
+ * A standard Tcl return value. If an error occurred in creating the
+ * item, then an error message is left in the interp's result; in this
+ * case itemPtr is left uninitialized, so it can be safely freed by the
+ * caller.
+ *
+ * Side effects:
+ * A new polygon item is created.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+CreatePolygon(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Tk_Canvas canvas, /* Canvas to hold new item. */
+ Tk_Item *itemPtr, /* Record to hold new item; header has been
+ * initialized by caller. */
+ int objc, /* Number of arguments in objv. */
+ Tcl_Obj *const objv[]) /* Arguments describing polygon. */
+{
+ PolygonItem *polyPtr = (PolygonItem *) itemPtr;
+ int i;
+
+ if (objc == 0) {
+ Tcl_Panic("canvas did not pass any coords");
+ }
+
+ /*
+ * Carry out initialization that is needed in order to clean up after
+ * errors during the the remainder of this function.
+ */
+
+ Tk_CreateOutline(&polyPtr->outline);
+ polyPtr->numPoints = 0;
+ polyPtr->pointsAllocated = 0;
+ polyPtr->coordPtr = NULL;
+ polyPtr->joinStyle = JoinRound;
+ polyPtr->tsoffset.flags = 0;
+ polyPtr->tsoffset.xoffset = 0;
+ polyPtr->tsoffset.yoffset = 0;
+ polyPtr->fillColor = NULL;
+ polyPtr->activeFillColor = NULL;
+ polyPtr->disabledFillColor = NULL;
+ polyPtr->fillStipple = None;
+ polyPtr->activeFillStipple = None;
+ polyPtr->disabledFillStipple = None;
+ polyPtr->fillGC = NULL;
+ polyPtr->smooth = NULL;
+ polyPtr->splineSteps = 12;
+ polyPtr->autoClosed = 0;
+
+ /*
+ * Count the number of points and then parse them into a point array.
+ * Leading arguments are assumed to be points if they start with a digit
+ * or a minus sign followed by a digit.
+ */
+
+ for (i = 0; i < objc; i++) {
+ const char *arg = Tcl_GetString(objv[i]);
+
+ if ((arg[0] == '-') && (arg[1] >= 'a') && (arg[1] <= 'z')) {
+ break;
+ }
+ }
+ if (i && PolygonCoords(interp, canvas, itemPtr, i, objv) != TCL_OK) {
+ goto error;
+ }
+
+ if (ConfigurePolygon(interp, canvas, itemPtr, objc-i, objv+i, 0)
+ == TCL_OK) {
+ return TCL_OK;
+ }
+
+ error:
+ DeletePolygon(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * PolygonCoords --
+ *
+ * This function is invoked to process the "coords" widget command on
+ * polygons. See the user documentation for details on what it does.
+ *
+ * Results:
+ * Returns TCL_OK or TCL_ERROR, and sets the interp's result.
+ *
+ * Side effects:
+ * The coordinates for the given item may be changed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+PolygonCoords(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item whose coordinates are to be read or
+ * modified. */
+ int objc, /* Number of coordinates supplied in objv. */
+ Tcl_Obj *const objv[]) /* Array of coordinates: x1, y1, x2, y2, ... */
+{
+ PolygonItem *polyPtr = (PolygonItem *) itemPtr;
+ int i, numPoints;
+
+ if (objc == 0) {
+ /*
+ * Print the coords used to create the polygon. If we auto closed the
+ * polygon then we don't report the last point.
+ */
+
+ Tcl_Obj *subobj, *obj = Tcl_NewObj();
+
+ for (i = 0; i < 2*(polyPtr->numPoints - polyPtr->autoClosed); i++) {
+ subobj = Tcl_NewDoubleObj(polyPtr->coordPtr[i]);
+ Tcl_ListObjAppendElement(interp, obj, subobj);
+ }
+ Tcl_SetObjResult(interp, obj);
+ return TCL_OK;
+ }
+ if (objc == 1) {
+ if (Tcl_ListObjGetElements(interp, objv[0], &objc,
+ (Tcl_Obj ***) &objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (objc & 1) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "wrong # coordinates: expected an even number, got %d",
+ objc));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "COORDS", "POLYGON", NULL);
+ return TCL_ERROR;
+ }
+
+ numPoints = objc/2;
+ if (polyPtr->pointsAllocated <= numPoints) {
+ if (polyPtr->coordPtr != NULL) {
+ ckfree(polyPtr->coordPtr);
+ }
+
+ /*
+ * One extra point gets allocated here, because we always add
+ * another point to close the polygon.
+ */
+
+ polyPtr->coordPtr = ckalloc(sizeof(double) * (objc+2));
+ polyPtr->pointsAllocated = numPoints+1;
+ }
+ for (i = objc-1; i >= 0; i--) {
+ if (Tk_CanvasGetCoordFromObj(interp, canvas, objv[i],
+ &polyPtr->coordPtr[i]) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ polyPtr->numPoints = numPoints;
+ polyPtr->autoClosed = 0;
+
+ /*
+ * Close the polygon if it isn't already closed.
+ */
+
+ if (objc>2 && ((polyPtr->coordPtr[objc-2] != polyPtr->coordPtr[0])
+ || (polyPtr->coordPtr[objc-1] != polyPtr->coordPtr[1]))) {
+ polyPtr->autoClosed = 1;
+ polyPtr->numPoints++;
+ polyPtr->coordPtr[objc] = polyPtr->coordPtr[0];
+ polyPtr->coordPtr[objc+1] = polyPtr->coordPtr[1];
+ }
+
+ ComputePolygonBbox(canvas, polyPtr);
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ConfigurePolygon --
+ *
+ * This function is invoked to configure various aspects of a polygon
+ * item such as its background color.
+ *
+ * Results:
+ * A standard Tcl result code. If an error occurs, then an error message
+ * is left in the interp's result.
+ *
+ * Side effects:
+ * Configuration information, such as colors and stipple patterns, may be
+ * set for itemPtr.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+ConfigurePolygon(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Tk_Canvas canvas, /* Canvas containing itemPtr. */
+ Tk_Item *itemPtr, /* Polygon item to reconfigure. */
+ int objc, /* Number of elements in objv. */
+ Tcl_Obj *const objv[], /* Arguments describing things to configure. */
+ int flags) /* Flags to pass to Tk_ConfigureWidget. */
+{
+ PolygonItem *polyPtr = (PolygonItem *) itemPtr;
+ XGCValues gcValues;
+ GC newGC;
+ unsigned long mask;
+ Tk_Window tkwin;
+ XColor *color;
+ Pixmap stipple;
+ Tk_State state;
+
+ tkwin = Tk_CanvasTkwin(canvas);
+ if (TCL_OK != Tk_ConfigureWidget(interp, tkwin, configSpecs, objc,
+ (const char **) objv, (char *) polyPtr, flags|TK_CONFIG_OBJS)) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * A few of the options require additional processing, such as graphics
+ * contexts.
+ */
+
+ state = itemPtr->state;
+
+ if (polyPtr->outline.activeWidth > polyPtr->outline.width ||
+ polyPtr->outline.activeDash.number != 0 ||
+ polyPtr->outline.activeColor != NULL ||
+ polyPtr->outline.activeStipple != None ||
+ polyPtr->activeFillColor != NULL ||
+ polyPtr->activeFillStipple != None) {
+ itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;
+ } else {
+ itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;
+ }
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+ if (state == TK_STATE_HIDDEN) {
+ ComputePolygonBbox(canvas, polyPtr);
+ return TCL_OK;
+ }
+
+ mask = Tk_ConfigOutlineGC(&gcValues, canvas, itemPtr, &polyPtr->outline);
+ if (mask) {
+ gcValues.cap_style = CapRound;
+ gcValues.join_style = polyPtr->joinStyle;
+ mask |= GCCapStyle|GCJoinStyle;
+ newGC = Tk_GetGC(tkwin, mask, &gcValues);
+ } else {
+ newGC = NULL;
+ }
+ if (polyPtr->outline.gc != NULL) {
+ Tk_FreeGC(Tk_Display(tkwin), polyPtr->outline.gc);
+ }
+ polyPtr->outline.gc = newGC;
+
+ color = polyPtr->fillColor;
+ stipple = polyPtr->fillStipple;
+ if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (polyPtr->activeFillColor != NULL) {
+ color = polyPtr->activeFillColor;
+ }
+ if (polyPtr->activeFillStipple != None) {
+ stipple = polyPtr->activeFillStipple;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (polyPtr->disabledFillColor != NULL) {
+ color = polyPtr->disabledFillColor;
+ }
+ if (polyPtr->disabledFillStipple != None) {
+ stipple = polyPtr->disabledFillStipple;
+ }
+ }
+
+ if (color == NULL) {
+ newGC = NULL;
+ } else {
+ gcValues.foreground = color->pixel;
+ mask = GCForeground;
+ if (stipple != None) {
+ gcValues.stipple = stipple;
+ gcValues.fill_style = FillStippled;
+ mask |= GCStipple|GCFillStyle;
+ }
+#ifdef MAC_OSX_TK
+ /*
+ * Mac OS X CG drawing needs access to the outline linewidth
+ * even for fills (as linewidth controls antialiasing).
+ */
+ gcValues.line_width = polyPtr->outline.gc != NULL ?
+ polyPtr->outline.gc->line_width : 0;
+ mask |= GCLineWidth;
+#endif
+ newGC = Tk_GetGC(tkwin, mask, &gcValues);
+ }
+ if (polyPtr->fillGC != NULL) {
+ Tk_FreeGC(Tk_Display(tkwin), polyPtr->fillGC);
+ }
+ polyPtr->fillGC = newGC;
+
+ /*
+ * Keep spline parameters within reasonable limits.
+ */
+
+ if (polyPtr->splineSteps < 1) {
+ polyPtr->splineSteps = 1;
+ } else if (polyPtr->splineSteps > 100) {
+ polyPtr->splineSteps = 100;
+ }
+
+ ComputePolygonBbox(canvas, polyPtr);
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DeletePolygon --
+ *
+ * This function is called to clean up the data structure associated with
+ * a polygon item.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Resources associated with itemPtr are released.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+DeletePolygon(
+ Tk_Canvas canvas, /* Info about overall canvas widget. */
+ Tk_Item *itemPtr, /* Item that is being deleted. */
+ Display *display) /* Display containing window for canvas. */
+{
+ PolygonItem *polyPtr = (PolygonItem *) itemPtr;
+
+ Tk_DeleteOutline(display, &polyPtr->outline);
+ if (polyPtr->coordPtr != NULL) {
+ ckfree(polyPtr->coordPtr);
+ }
+ if (polyPtr->fillColor != NULL) {
+ Tk_FreeColor(polyPtr->fillColor);
+ }
+ if (polyPtr->activeFillColor != NULL) {
+ Tk_FreeColor(polyPtr->activeFillColor);
+ }
+ if (polyPtr->disabledFillColor != NULL) {
+ Tk_FreeColor(polyPtr->disabledFillColor);
+ }
+ if (polyPtr->fillStipple != None) {
+ Tk_FreeBitmap(display, polyPtr->fillStipple);
+ }
+ if (polyPtr->activeFillStipple != None) {
+ Tk_FreeBitmap(display, polyPtr->activeFillStipple);
+ }
+ if (polyPtr->disabledFillStipple != None) {
+ Tk_FreeBitmap(display, polyPtr->disabledFillStipple);
+ }
+ if (polyPtr->fillGC != NULL) {
+ Tk_FreeGC(display, polyPtr->fillGC);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ComputePolygonBbox --
+ *
+ * This function is invoked to compute the bounding box of all the pixels
+ * that may be drawn as part of a polygon.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The fields x1, y1, x2, and y2 are updated in the header for itemPtr.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ComputePolygonBbox(
+ Tk_Canvas canvas, /* Canvas that contains item. */
+ PolygonItem *polyPtr) /* Item whose bbox is to be recomputed. */
+{
+ double *coordPtr;
+ int i;
+ double width;
+ Tk_State state = polyPtr->header.state;
+ Tk_TSOffset *tsoffset;
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+ width = polyPtr->outline.width;
+ if (polyPtr->coordPtr == NULL || (polyPtr->numPoints < 1)
+ || (state == TK_STATE_HIDDEN)) {
+ polyPtr->header.x1 = polyPtr->header.x2 =
+ polyPtr->header.y1 = polyPtr->header.y2 = -1;
+ return;
+ }
+ if (Canvas(canvas)->currentItemPtr == (Tk_Item *) polyPtr) {
+ if (polyPtr->outline.activeWidth > width) {
+ width = polyPtr->outline.activeWidth;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (polyPtr->outline.disabledWidth > 0.0) {
+ width = polyPtr->outline.disabledWidth;
+ }
+ }
+
+ coordPtr = polyPtr->coordPtr;
+ polyPtr->header.x1 = polyPtr->header.x2 = (int) *coordPtr;
+ polyPtr->header.y1 = polyPtr->header.y2 = (int) coordPtr[1];
+
+ /*
+ * Compute the bounding box of all the points in the polygon, then expand
+ * in all directions by the outline's width to take care of butting or
+ * rounded corners and projecting or rounded caps. This expansion is an
+ * overestimate (worst-case is square root of two over two) but it's
+ * simple. Don't do anything special for curves. This causes an additional
+ * overestimate in the bounding box, but is faster.
+ */
+
+ for (i = 1, coordPtr = polyPtr->coordPtr+2; i < polyPtr->numPoints-1;
+ i++, coordPtr += 2) {
+ TkIncludePoint((Tk_Item *) polyPtr, coordPtr);
+ }
+
+ tsoffset = &polyPtr->tsoffset;
+ if (tsoffset->flags & TK_OFFSET_INDEX) {
+ int index = tsoffset->flags & ~TK_OFFSET_INDEX;
+
+ if (tsoffset->flags == INT_MAX) {
+ index = (polyPtr->numPoints - polyPtr->autoClosed) * 2;
+ if (index < 0) {
+ index = 0;
+ }
+ }
+ index %= (polyPtr->numPoints - polyPtr->autoClosed) * 2;
+ if (index < 0) {
+ index += (polyPtr->numPoints - polyPtr->autoClosed) * 2;
+ }
+ tsoffset->xoffset = (int) (polyPtr->coordPtr[index] + 0.5);
+ tsoffset->yoffset = (int) (polyPtr->coordPtr[index+1] + 0.5);
+ } else {
+ if (tsoffset->flags & TK_OFFSET_LEFT) {
+ tsoffset->xoffset = polyPtr->header.x1;
+ } else if (tsoffset->flags & TK_OFFSET_CENTER) {
+ tsoffset->xoffset = (polyPtr->header.x1 + polyPtr->header.x2)/2;
+ } else if (tsoffset->flags & TK_OFFSET_RIGHT) {
+ tsoffset->xoffset = polyPtr->header.x2;
+ }
+ if (tsoffset->flags & TK_OFFSET_TOP) {
+ tsoffset->yoffset = polyPtr->header.y1;
+ } else if (tsoffset->flags & TK_OFFSET_MIDDLE) {
+ tsoffset->yoffset = (polyPtr->header.y1 + polyPtr->header.y2)/2;
+ } else if (tsoffset->flags & TK_OFFSET_BOTTOM) {
+ tsoffset->yoffset = polyPtr->header.y2;
+ }
+ }
+
+ if (polyPtr->outline.gc != NULL) {
+ tsoffset = &polyPtr->outline.tsoffset;
+ if (tsoffset) {
+ if (tsoffset->flags & TK_OFFSET_INDEX) {
+ int index = tsoffset->flags & ~TK_OFFSET_INDEX;
+
+ if (tsoffset->flags == INT_MAX) {
+ index = (polyPtr->numPoints - 1) * 2;
+ }
+ index %= (polyPtr->numPoints - 1) * 2;
+ if (index < 0) {
+ index += (polyPtr->numPoints - 1) * 2;
+ }
+ tsoffset->xoffset = (int) (polyPtr->coordPtr[index] + 0.5);
+ tsoffset->yoffset = (int) (polyPtr->coordPtr[index+1] + 0.5);
+ } else {
+ if (tsoffset->flags & TK_OFFSET_LEFT) {
+ tsoffset->xoffset = polyPtr->header.x1;
+ } else if (tsoffset->flags & TK_OFFSET_CENTER) {
+ tsoffset->xoffset =
+ (polyPtr->header.x1 + polyPtr->header.x2) / 2;
+ } else if (tsoffset->flags & TK_OFFSET_RIGHT) {
+ tsoffset->xoffset = polyPtr->header.x2;
+ }
+ if (tsoffset->flags & TK_OFFSET_TOP) {
+ tsoffset->yoffset = polyPtr->header.y1;
+ } else if (tsoffset->flags & TK_OFFSET_MIDDLE) {
+ tsoffset->yoffset =
+ (polyPtr->header.y1 + polyPtr->header.y2) / 2;
+ } else if (tsoffset->flags & TK_OFFSET_BOTTOM) {
+ tsoffset->yoffset = polyPtr->header.y2;
+ }
+ }
+ }
+
+ i = (int) ((width+1.5) / 2.0);
+ polyPtr->header.x1 -= i;
+ polyPtr->header.x2 += i;
+ polyPtr->header.y1 -= i;
+ polyPtr->header.y2 += i;
+
+ /*
+ * For mitered lines, make a second pass through all the points.
+ * Compute the locations of the two miter vertex points and add those
+ * into the bounding box.
+ */
+
+ if (polyPtr->joinStyle == JoinMiter) {
+ double miter[4];
+ int j;
+
+ coordPtr = polyPtr->coordPtr;
+ if (polyPtr->numPoints > 3) {
+ if (TkGetMiterPoints(coordPtr+2*(polyPtr->numPoints-2),
+ coordPtr, coordPtr+2, width, miter, miter+2)) {
+ for (j = 0; j < 4; j += 2) {
+ TkIncludePoint((Tk_Item *) polyPtr, miter+j);
+ }
+ }
+ }
+ for (i = polyPtr->numPoints ; i >= 3; i--, coordPtr += 2) {
+ if (TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4, width,
+ miter, miter+2)) {
+ for (j = 0; j < 4; j += 2) {
+ TkIncludePoint((Tk_Item *) polyPtr, miter+j);
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * Add one more pixel of fudge factor just to be safe (e.g. X may round
+ * differently than we do).
+ */
+
+ polyPtr->header.x1 -= 1;
+ polyPtr->header.x2 += 1;
+ polyPtr->header.y1 -= 1;
+ polyPtr->header.y2 += 1;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkFillPolygon --
+ *
+ * This function is invoked to convert a polygon to screen coordinates
+ * and display it using a particular GC.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * ItemPtr is drawn in drawable using the transformation information in
+ * canvas.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkFillPolygon(
+ Tk_Canvas canvas, /* Canvas whose coordinate system is to be
+ * used for drawing. */
+ double *coordPtr, /* Array of coordinates for polygon: x1, y1,
+ * x2, y2, .... */
+ int numPoints, /* Twice this many coordinates are present at
+ * *coordPtr. */
+ Display *display, /* Display on which to draw polygon. */
+ Drawable drawable, /* Pixmap or window in which to draw
+ * polygon. */
+ GC gc, /* Graphics context for drawing. */
+ GC outlineGC) /* If not None, use this to draw an outline
+ * around the polygon after filling it. */
+{
+ XPoint staticPoints[MAX_STATIC_POINTS];
+ XPoint *pointPtr;
+ XPoint *pPtr;
+ int i;
+
+ /*
+ * Build up an array of points in screen coordinates. Use a static array
+ * unless the polygon has an enormous number of points; in this case,
+ * dynamically allocate an array.
+ */
+
+ if (numPoints <= MAX_STATIC_POINTS) {
+ pointPtr = staticPoints;
+ } else {
+ pointPtr = ckalloc(numPoints * sizeof(XPoint));
+ }
+
+ for (i=0, pPtr=pointPtr ; i<numPoints; i+=1, coordPtr+=2, pPtr++) {
+ Tk_CanvasDrawableCoords(canvas, coordPtr[0], coordPtr[1], &pPtr->x,
+ &pPtr->y);
+ }
+
+ /*
+ * Display polygon, then free up polygon storage if it was dynamically
+ * allocated.
+ */
+
+ if (gc != NULL && numPoints > 3) {
+ XFillPolygon(display, drawable, gc, pointPtr, numPoints, Complex,
+ CoordModeOrigin);
+ }
+ if (outlineGC != NULL) {
+ XDrawLines(display, drawable, outlineGC, pointPtr, numPoints,
+ CoordModeOrigin);
+ }
+ if (pointPtr != staticPoints) {
+ ckfree(pointPtr);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DisplayPolygon --
+ *
+ * This function is invoked to draw a polygon item in a given drawable.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * ItemPtr is drawn in drawable using the transformation information in
+ * canvas.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+DisplayPolygon(
+ Tk_Canvas canvas, /* Canvas that contains item. */
+ Tk_Item *itemPtr, /* Item to be displayed. */
+ Display *display, /* Display on which to draw item. */
+ Drawable drawable, /* Pixmap or window in which to draw item. */
+ int x, int y, int width, int height)
+ /* Describes region of canvas that must be
+ * redisplayed (not used). */
+{
+ PolygonItem *polyPtr = (PolygonItem *) itemPtr;
+ Tk_State state = itemPtr->state;
+ Pixmap stipple = polyPtr->fillStipple;
+ double linewidth = polyPtr->outline.width;
+
+ if (((polyPtr->fillGC == NULL) && (polyPtr->outline.gc == NULL)) ||
+ (polyPtr->numPoints < 1) ||
+ (polyPtr->numPoints < 3 && polyPtr->outline.gc == NULL)) {
+ return;
+ }
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+ if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (polyPtr->outline.activeWidth > linewidth) {
+ linewidth = polyPtr->outline.activeWidth;
+ }
+ if (polyPtr->activeFillStipple != None) {
+ stipple = polyPtr->activeFillStipple;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (polyPtr->outline.disabledWidth > 0.0) {
+ linewidth = polyPtr->outline.disabledWidth;
+ }
+ if (polyPtr->disabledFillStipple != None) {
+ stipple = polyPtr->disabledFillStipple;
+ }
+ }
+
+ /*
+ * If we're stippling then modify the stipple offset in the GC. Be sure to
+ * reset the offset when done, since the GC is supposed to be read-only.
+ */
+
+ if ((stipple != None) && (polyPtr->fillGC != NULL)) {
+ Tk_TSOffset *tsoffset = &polyPtr->tsoffset;
+ int w = 0, h = 0;
+ int flags = tsoffset->flags;
+
+ if (!(flags & TK_OFFSET_INDEX)
+ && (flags & (TK_OFFSET_CENTER|TK_OFFSET_MIDDLE))) {
+ Tk_SizeOfBitmap(display, stipple, &w, &h);
+ if (flags & TK_OFFSET_CENTER) {
+ w /= 2;
+ } else {
+ w = 0;
+ }
+ if (flags & TK_OFFSET_MIDDLE) {
+ h /= 2;
+ } else {
+ h = 0;
+ }
+ }
+ tsoffset->xoffset -= w;
+ tsoffset->yoffset -= h;
+ Tk_CanvasSetOffset(canvas, polyPtr->fillGC, tsoffset);
+ tsoffset->xoffset += w;
+ tsoffset->yoffset += h;
+ }
+ Tk_ChangeOutlineGC(canvas, itemPtr, &polyPtr->outline);
+
+ if (polyPtr->numPoints < 3) {
+ short x, y;
+ int intLineWidth = (int) (linewidth + 0.5);
+
+ if (intLineWidth < 1) {
+ intLineWidth = 1;
+ }
+ Tk_CanvasDrawableCoords(canvas, polyPtr->coordPtr[0],
+ polyPtr->coordPtr[1], &x, &y);
+ XFillArc(display, drawable, polyPtr->outline.gc,
+ x - intLineWidth/2, y - intLineWidth/2,
+ (unsigned) intLineWidth+1, (unsigned) intLineWidth+1,
+ 0, 64*360);
+ } else if (!polyPtr->smooth || polyPtr->numPoints < 4) {
+ TkFillPolygon(canvas, polyPtr->coordPtr, polyPtr->numPoints,
+ display, drawable, polyPtr->fillGC, polyPtr->outline.gc);
+ } else {
+ int numPoints;
+ XPoint staticPoints[MAX_STATIC_POINTS];
+ XPoint *pointPtr;
+
+ /*
+ * This is a smoothed polygon. Display using a set of generated spline
+ * points rather than the original points.
+ */
+
+ numPoints = polyPtr->smooth->coordProc(canvas, NULL,
+ polyPtr->numPoints, polyPtr->splineSteps, NULL, NULL);
+ if (numPoints <= MAX_STATIC_POINTS) {
+ pointPtr = staticPoints;
+ } else {
+ pointPtr = ckalloc(numPoints * sizeof(XPoint));
+ }
+ numPoints = polyPtr->smooth->coordProc(canvas, polyPtr->coordPtr,
+ polyPtr->numPoints, polyPtr->splineSteps, pointPtr, NULL);
+ if (polyPtr->fillGC != NULL) {
+ XFillPolygon(display, drawable, polyPtr->fillGC, pointPtr,
+ numPoints, Complex, CoordModeOrigin);
+ }
+ if (polyPtr->outline.gc != NULL) {
+ XDrawLines(display, drawable, polyPtr->outline.gc, pointPtr,
+ numPoints, CoordModeOrigin);
+ }
+ if (pointPtr != staticPoints) {
+ ckfree(pointPtr);
+ }
+ }
+ Tk_ResetOutlineGC(canvas, itemPtr, &polyPtr->outline);
+ if ((stipple != None) && (polyPtr->fillGC != NULL)) {
+ XSetTSOrigin(display, polyPtr->fillGC, 0, 0);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * PolygonInsert --
+ *
+ * Insert coords into a polugon item at a given index.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The coords in the given item is modified.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+PolygonInsert(
+ Tk_Canvas canvas, /* Canvas containing text item. */
+ Tk_Item *itemPtr, /* Line item to be modified. */
+ int beforeThis, /* Index before which new coordinates are to
+ * be inserted. */
+ Tcl_Obj *obj) /* New coordinates to be inserted. */
+{
+ PolygonItem *polyPtr = (PolygonItem *) itemPtr;
+ int length, objc, i;
+ Tcl_Obj **objv;
+ double *newCoordPtr;
+ Tk_State state = itemPtr->state;
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+
+ if (!obj || (Tcl_ListObjGetElements(NULL, obj, &objc, &objv) != TCL_OK)
+ || !objc || objc&1) {
+ return;
+ }
+ length = 2*(polyPtr->numPoints - polyPtr->autoClosed);
+ while (beforeThis > length) {
+ beforeThis -= length;
+ }
+ while (beforeThis < 0) {
+ beforeThis += length;
+ }
+ newCoordPtr = ckalloc(sizeof(double) * (length + 2 + objc));
+ for (i=0; i<beforeThis; i++) {
+ newCoordPtr[i] = polyPtr->coordPtr[i];
+ }
+ for (i=0; i<objc; i++) {
+ if (Tcl_GetDoubleFromObj(NULL, objv[i],
+ &newCoordPtr[i+beforeThis]) != TCL_OK){
+ ckfree(newCoordPtr);
+ return;
+ }
+ }
+
+ for (i=beforeThis; i<length; i++) {
+ newCoordPtr[i+objc] = polyPtr->coordPtr[i];
+ }
+ if (polyPtr->coordPtr) {
+ ckfree(polyPtr->coordPtr);
+ }
+ length += objc;
+ polyPtr->coordPtr = newCoordPtr;
+ polyPtr->numPoints = (length/2) + polyPtr->autoClosed;
+
+ /*
+ * Close the polygon if it isn't already closed, or remove autoclosing if
+ * the user's coordinates are now closed.
+ */
+
+ if (polyPtr->autoClosed) {
+ if ((newCoordPtr[length-2] == newCoordPtr[0])
+ && (newCoordPtr[length-1] == newCoordPtr[1])) {
+ polyPtr->autoClosed = 0;
+ polyPtr->numPoints--;
+ }
+ } else {
+ if ((newCoordPtr[length-2] != newCoordPtr[0])
+ || (newCoordPtr[length-1] != newCoordPtr[1])) {
+ polyPtr->autoClosed = 1;
+ polyPtr->numPoints++;
+ }
+ }
+
+ newCoordPtr[length] = newCoordPtr[0];
+ newCoordPtr[length+1] = newCoordPtr[1];
+ if ((length-objc > 3) && (state != TK_STATE_HIDDEN)) {
+ /*
+ * This is some optimizing code that will result that only the part of
+ * the polygon that changed (and the objects that are overlapping with
+ * that part) need to be redrawn. A special flag is set that instructs
+ * the general canvas code not to redraw the whole object. If this
+ * flag is not set, the canvas will do the redrawing, otherwise I have
+ * to do it here.
+ */
+
+ double width;
+ int j;
+
+ itemPtr->redraw_flags |= TK_ITEM_DONT_REDRAW;
+
+ /*
+ * The header elements that normally are used for the bounding box,
+ * are now used to calculate the bounding box for only the part that
+ * has to be redrawn. That doesn't matter, because afterwards the
+ * bounding box has to be re-calculated anyway.
+ */
+
+ itemPtr->x1 = itemPtr->x2 = (int) polyPtr->coordPtr[beforeThis];
+ itemPtr->y1 = itemPtr->y2 = (int) polyPtr->coordPtr[beforeThis+1];
+ beforeThis -= 2;
+ objc += 4;
+ if (polyPtr->smooth) {
+ beforeThis -= 2;
+ objc += 4;
+ }
+
+ /*
+ * Be careful; beforeThis could now be negative
+ */
+
+ for (i=beforeThis; i<beforeThis+objc; i+=2) {
+ j = i;
+ if (j < 0) {
+ j += length;
+ } else if (j >= length) {
+ j -= length;
+ }
+ TkIncludePoint(itemPtr, polyPtr->coordPtr+j);
+ }
+ width = polyPtr->outline.width;
+ if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (polyPtr->outline.activeWidth > width) {
+ width = polyPtr->outline.activeWidth;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (polyPtr->outline.disabledWidth > 0.0) {
+ width = polyPtr->outline.disabledWidth;
+ }
+ }
+ itemPtr->x1 -= (int) width;
+ itemPtr->y1 -= (int) width;
+ itemPtr->x2 += (int) width;
+ itemPtr->y2 += (int) width;
+ Tk_CanvasEventuallyRedraw(canvas,
+ itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);
+ }
+
+ ComputePolygonBbox(canvas, polyPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * PolygonDeleteCoords --
+ *
+ * Delete one or more coordinates from a polygon item.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Characters between "first" and "last", inclusive, get deleted from
+ * itemPtr.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+PolygonDeleteCoords(
+ Tk_Canvas canvas, /* Canvas containing itemPtr. */
+ Tk_Item *itemPtr, /* Item in which to delete characters. */
+ int first, /* Index of first character to delete. */
+ int last) /* Index of last character to delete. */
+{
+ PolygonItem *polyPtr = (PolygonItem *) itemPtr;
+ int count, i;
+ int length = 2*(polyPtr->numPoints - polyPtr->autoClosed);
+
+ while (first >= length) {
+ first -= length;
+ }
+ while (first < 0) {
+ first += length;
+ }
+ while (last >= length) {
+ last -= length;
+ }
+ while (last < 0) {
+ last += length;
+ }
+
+ first &= -2;
+ last &= -2;
+
+ count = last + 2 - first;
+ if (count <= 0) {
+ count += length;
+ }
+
+ if (count >= length) {
+ polyPtr->numPoints = 0;
+ if (polyPtr->coordPtr != NULL) {
+ ckfree(polyPtr->coordPtr);
+ polyPtr->coordPtr = NULL;
+ }
+ ComputePolygonBbox(canvas, polyPtr);
+ return;
+ }
+
+ if (last >= first) {
+ for (i=last+2; i<length; i++) {
+ polyPtr->coordPtr[i-count] = polyPtr->coordPtr[i];
+ }
+ } else {
+ for (i=last; i<=first; i++) {
+ polyPtr->coordPtr[i-last] = polyPtr->coordPtr[i];
+ }
+ }
+ polyPtr->coordPtr[length-count] = polyPtr->coordPtr[0];
+ polyPtr->coordPtr[length-count+1] = polyPtr->coordPtr[1];
+ polyPtr->numPoints -= count/2;
+ ComputePolygonBbox(canvas, polyPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * PolygonToPoint --
+ *
+ * Computes the distance from a given point to a given polygon, in canvas
+ * units.
+ *
+ * Results:
+ * The return value is 0 if the point whose x and y coordinates are
+ * pointPtr[0] and pointPtr[1] is inside the polygon. If the point isn't
+ * inside the polygon then the return value is the distance from the
+ * point to the polygon.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static double
+PolygonToPoint(
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item to check against point. */
+ double *pointPtr) /* Pointer to x and y coordinates. */
+{
+ PolygonItem *polyPtr = (PolygonItem *) itemPtr;
+ double *coordPtr, *polyPoints;
+ double staticSpace[2*MAX_STATIC_POINTS];
+ double poly[10];
+ double radius;
+ double bestDist, dist;
+ int numPoints, count;
+ int changedMiterToBevel; /* Non-zero means that a mitered corner had to
+ * be treated as beveled after all because the
+ * angle was < 11 degrees. */
+ double width;
+ Tk_State state = itemPtr->state;
+
+ bestDist = 1.0e36;
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+ width = polyPtr->outline.width;
+ if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (polyPtr->outline.activeWidth > width) {
+ width = polyPtr->outline.activeWidth;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (polyPtr->outline.disabledWidth > 0.0) {
+ width = polyPtr->outline.disabledWidth;
+ }
+ }
+ radius = width/2.0;
+
+ /*
+ * Handle smoothed polygons by generating an expanded set of points
+ * against which to do the check.
+ */
+
+ if ((polyPtr->smooth) && (polyPtr->numPoints > 2)) {
+ numPoints = polyPtr->smooth->coordProc(canvas, NULL,
+ polyPtr->numPoints, polyPtr->splineSteps, NULL, NULL);
+ if (numPoints <= MAX_STATIC_POINTS) {
+ polyPoints = staticSpace;
+ } else {
+ polyPoints = ckalloc(2 * numPoints * sizeof(double));
+ }
+ numPoints = polyPtr->smooth->coordProc(canvas, polyPtr->coordPtr,
+ polyPtr->numPoints, polyPtr->splineSteps, NULL, polyPoints);
+ } else {
+ numPoints = polyPtr->numPoints;
+ polyPoints = polyPtr->coordPtr;
+ }
+
+ bestDist = TkPolygonToPoint(polyPoints, numPoints, pointPtr);
+ if (bestDist <= 0.0) {
+ goto donepoint;
+ }
+ if ((polyPtr->outline.gc != NULL) && (polyPtr->joinStyle == JoinRound)) {
+ dist = bestDist - radius;
+ if (dist <= 0.0) {
+ bestDist = 0.0;
+ goto donepoint;
+ } else {
+ bestDist = dist;
+ }
+ }
+
+ if ((polyPtr->outline.gc == NULL) || (width <= 1)) {
+ goto donepoint;
+ }
+
+ /*
+ * The overall idea is to iterate through all of the edges of the line,
+ * computing a polygon for each edge and testing the point against that
+ * polygon. In addition, there are additional tests to deal with rounded
+ * joints and caps.
+ */
+
+ changedMiterToBevel = 0;
+ for (count = numPoints, coordPtr = polyPoints; count >= 2;
+ count--, coordPtr += 2) {
+ /*
+ * If rounding is done around the first point then compute the
+ * distance between the point and the point.
+ */
+
+ if (polyPtr->joinStyle == JoinRound) {
+ dist = hypot(coordPtr[0] - pointPtr[0], coordPtr[1] - pointPtr[1])
+ - radius;
+ if (dist <= 0.0) {
+ bestDist = 0.0;
+ goto donepoint;
+ } else if (dist < bestDist) {
+ bestDist = dist;
+ }
+ }
+
+ /*
+ * Compute the polygonal shape corresponding to this edge, consisting
+ * of two points for the first point of the edge and two points for
+ * the last point of the edge.
+ */
+
+ if (count == numPoints) {
+ TkGetButtPoints(coordPtr+2, coordPtr, (double) width, 0, poly,
+ poly+2);
+ } else if ((polyPtr->joinStyle == JoinMiter) && !changedMiterToBevel) {
+ poly[0] = poly[6];
+ poly[1] = poly[7];
+ poly[2] = poly[4];
+ poly[3] = poly[5];
+ } else {
+ TkGetButtPoints(coordPtr+2, coordPtr, (double) width, 0, poly,
+ poly+2);
+
+ /*
+ * If this line uses beveled joints, then check the distance to a
+ * polygon comprising the last two points of the previous polygon
+ * and the first two from this polygon; this checks the wedges
+ * that fill the mitered joint.
+ */
+
+ if ((polyPtr->joinStyle == JoinBevel) || changedMiterToBevel) {
+ poly[8] = poly[0];
+ poly[9] = poly[1];
+ dist = TkPolygonToPoint(poly, 5, pointPtr);
+ if (dist <= 0.0) {
+ bestDist = 0.0;
+ goto donepoint;
+ } else if (dist < bestDist) {
+ bestDist = dist;
+ }
+ changedMiterToBevel = 0;
+ }
+ }
+ if (count == 2) {
+ TkGetButtPoints(coordPtr, coordPtr+2, (double) width, 0, poly+4,
+ poly+6);
+ } else if (polyPtr->joinStyle == JoinMiter) {
+ if (TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4,
+ (double) width, poly+4, poly+6) == 0) {
+ changedMiterToBevel = 1;
+ TkGetButtPoints(coordPtr, coordPtr+2, (double) width, 0,
+ poly+4, poly+6);
+ }
+ } else {
+ TkGetButtPoints(coordPtr, coordPtr+2, (double) width, 0, poly+4,
+ poly+6);
+ }
+ poly[8] = poly[0];
+ poly[9] = poly[1];
+ dist = TkPolygonToPoint(poly, 5, pointPtr);
+ if (dist <= 0.0) {
+ bestDist = 0.0;
+ goto donepoint;
+ } else if (dist < bestDist) {
+ bestDist = dist;
+ }
+ }
+
+ donepoint:
+ if (polyPoints != staticSpace && polyPoints != polyPtr->coordPtr) {
+ ckfree(polyPoints);
+ }
+ return bestDist;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * PolygonToArea --
+ *
+ * This function is called to determine whether an item lies entirely
+ * inside, entirely outside, or overlapping a given rectangular area.
+ *
+ * Results:
+ * -1 is returned if the item is entirely outside the area given by
+ * rectPtr, 0 if it overlaps, and 1 if it is entirely inside the given
+ * area.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+PolygonToArea(
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item to check against polygon. */
+ double *rectPtr) /* Pointer to array of four coordinates
+ * (x1,y1,x2,y2) describing rectangular
+ * area. */
+{
+ PolygonItem *polyPtr = (PolygonItem *) itemPtr;
+ double *coordPtr;
+ double staticSpace[2*MAX_STATIC_POINTS];
+ double *polyPoints, poly[10];
+ double radius;
+ int numPoints, count;
+ int changedMiterToBevel; /* Non-zero means that a mitered corner had to
+ * be treated as beveled after all because the
+ * angle was < 11 degrees. */
+ int inside; /* Tentative guess about what to return, based
+ * on all points seen so far: one means
+ * everything seen so far was inside the area;
+ * -1 means everything was outside the area. 0
+ * means overlap has been found. */
+ double width;
+ Tk_State state = itemPtr->state;
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+
+ width = polyPtr->outline.width;
+ if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (polyPtr->outline.activeWidth > width) {
+ width = polyPtr->outline.activeWidth;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (polyPtr->outline.disabledWidth > 0.0) {
+ width = polyPtr->outline.disabledWidth;
+ }
+ }
+
+ radius = width/2.0;
+ inside = -1;
+
+ if ((state == TK_STATE_HIDDEN) || polyPtr->numPoints < 2) {
+ return -1;
+ } else if (polyPtr->numPoints < 3) {
+ double oval[4];
+
+ oval[0] = polyPtr->coordPtr[0]-radius;
+ oval[1] = polyPtr->coordPtr[1]-radius;
+ oval[2] = polyPtr->coordPtr[0]+radius;
+ oval[3] = polyPtr->coordPtr[1]+radius;
+ return TkOvalToArea(oval, rectPtr);
+ }
+
+ /*
+ * Handle smoothed polygons by generating an expanded set of points
+ * against which to do the check.
+ */
+
+ if (polyPtr->smooth) {
+ numPoints = polyPtr->smooth->coordProc(canvas, NULL,
+ polyPtr->numPoints, polyPtr->splineSteps, NULL, NULL);
+ if (numPoints <= MAX_STATIC_POINTS) {
+ polyPoints = staticSpace;
+ } else {
+ polyPoints = ckalloc(2 * numPoints * sizeof(double));
+ }
+ numPoints = polyPtr->smooth->coordProc(canvas, polyPtr->coordPtr,
+ polyPtr->numPoints, polyPtr->splineSteps, NULL, polyPoints);
+ } else {
+ numPoints = polyPtr->numPoints;
+ polyPoints = polyPtr->coordPtr;
+ }
+
+ /*
+ * Simple test to see if we are in the polygon. Polygons are different
+ * from othe canvas items in that they register points being inside even
+ * if it isn't filled.
+ */
+
+ inside = TkPolygonToArea(polyPoints, numPoints, rectPtr);
+ if (inside == 0) {
+ goto donearea;
+ }
+
+ if (polyPtr->outline.gc == NULL) {
+ goto donearea;
+ }
+
+ /*
+ * Iterate through all of the edges of the line, computing a polygon for
+ * each edge and testing the area against that polygon. In addition, there
+ * are additional tests to deal with rounded joints and caps.
+ */
+
+ changedMiterToBevel = 0;
+ for (count = numPoints, coordPtr = polyPoints; count >= 2;
+ count--, coordPtr += 2) {
+ /*
+ * If rounding is done around the first point of the edge then test a
+ * circular region around the point with the area.
+ */
+
+ if (polyPtr->joinStyle == JoinRound) {
+ poly[0] = coordPtr[0] - radius;
+ poly[1] = coordPtr[1] - radius;
+ poly[2] = coordPtr[0] + radius;
+ poly[3] = coordPtr[1] + radius;
+ if (TkOvalToArea(poly, rectPtr) != inside) {
+ inside = 0;
+ goto donearea;
+ }
+ }
+
+ /*
+ * Compute the polygonal shape corresponding to this edge, consisting
+ * of two points for the first point of the edge and two points for
+ * the last point of the edge.
+ */
+
+ if (count == numPoints) {
+ TkGetButtPoints(coordPtr+2, coordPtr, width, 0, poly, poly+2);
+ } else if ((polyPtr->joinStyle == JoinMiter) && !changedMiterToBevel) {
+ poly[0] = poly[6];
+ poly[1] = poly[7];
+ poly[2] = poly[4];
+ poly[3] = poly[5];
+ } else {
+ TkGetButtPoints(coordPtr+2, coordPtr, width, 0, poly, poly+2);
+
+ /*
+ * If the last joint was beveled, then also check a polygon
+ * comprising the last two points of the previous polygon and the
+ * first two from this polygon; this checks the wedges that fill
+ * the beveled joint.
+ */
+
+ if ((polyPtr->joinStyle == JoinBevel) || changedMiterToBevel) {
+ poly[8] = poly[0];
+ poly[9] = poly[1];
+ if (TkPolygonToArea(poly, 5, rectPtr) != inside) {
+ inside = 0;
+ goto donearea;
+ }
+ changedMiterToBevel = 0;
+ }
+ }
+ if (count == 2) {
+ TkGetButtPoints(coordPtr, coordPtr+2, width, 0, poly+4, poly+6);
+ } else if (polyPtr->joinStyle == JoinMiter) {
+ if (TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4, width,
+ poly+4, poly+6) == 0) {
+ changedMiterToBevel = 1;
+ TkGetButtPoints(coordPtr, coordPtr+2, width,0, poly+4, poly+6);
+ }
+ } else {
+ TkGetButtPoints(coordPtr, coordPtr+2, width, 0, poly+4, poly+6);
+ }
+ poly[8] = poly[0];
+ poly[9] = poly[1];
+ if (TkPolygonToArea(poly, 5, rectPtr) != inside) {
+ inside = 0;
+ goto donearea;
+ }
+ }
+
+ donearea:
+ if ((polyPoints != staticSpace) && (polyPoints != polyPtr->coordPtr)) {
+ ckfree(polyPoints);
+ }
+ return inside;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ScalePolygon --
+ *
+ * This function is invoked to rescale a polygon item.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The polygon referred to by itemPtr is rescaled so that the following
+ * transformation is applied to all point coordinates:
+ * x' = originX + scaleX*(x-originX)
+ * y' = originY + scaleY*(y-originY)
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ScalePolygon(
+ Tk_Canvas canvas, /* Canvas containing polygon. */
+ Tk_Item *itemPtr, /* Polygon to be scaled. */
+ double originX, double originY,
+ /* Origin about which to scale rect. */
+ double scaleX, /* Amount to scale in X direction. */
+ double scaleY) /* Amount to scale in Y direction. */
+{
+ PolygonItem *polyPtr = (PolygonItem *) itemPtr;
+ double *coordPtr;
+ int i;
+
+ for (i = 0, coordPtr = polyPtr->coordPtr; i < polyPtr->numPoints;
+ i++, coordPtr += 2) {
+ *coordPtr = originX + scaleX*(*coordPtr - originX);
+ coordPtr[1] = originY + scaleY*(coordPtr[1] - originY);
+ }
+ ComputePolygonBbox(canvas, polyPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * GetPolygonIndex --
+ *
+ * Parse an index into a polygon item and return either its value or an
+ * error.
+ *
+ * Results:
+ * A standard Tcl result. If all went well, then *indexPtr is filled in
+ * with the index (into itemPtr) corresponding to string. Otherwise an
+ * error message is left in interp->result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+GetPolygonIndex(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item for which the index is being
+ * specified. */
+ Tcl_Obj *obj, /* Specification of a particular coord in
+ * itemPtr's line. */
+ int *indexPtr) /* Where to store converted index. */
+{
+ PolygonItem *polyPtr = (PolygonItem *) itemPtr;
+ const char *string = Tcl_GetString(obj);
+
+ if (string[0] == 'e') {
+ if (strncmp(string, "end", obj->length) != 0) {
+ goto badIndex;
+ }
+ *indexPtr = 2*(polyPtr->numPoints - polyPtr->autoClosed);
+ } else if (string[0] == '@') {
+ int i;
+ double x, y, bestDist, dist, *coordPtr;
+ char *end;
+ const char *p;
+
+ p = string+1;
+ x = strtod(p, &end);
+ if ((end == p) || (*end != ',')) {
+ goto badIndex;
+ }
+ p = end+1;
+ y = strtod(p, &end);
+ if ((end == p) || (*end != 0)) {
+ goto badIndex;
+ }
+ bestDist = 1.0e36;
+ coordPtr = polyPtr->coordPtr;
+ *indexPtr = 0;
+ for (i=0; i<polyPtr->numPoints-1; i++) {
+ dist = hypot(coordPtr[0] - x, coordPtr[1] - y);
+ if (dist < bestDist) {
+ bestDist = dist;
+ *indexPtr = 2*i;
+ }
+ coordPtr += 2;
+ }
+ } else {
+ int count = 2*(polyPtr->numPoints - polyPtr->autoClosed);
+
+ if (Tcl_GetIntFromObj(interp, obj, indexPtr) != TCL_OK) {
+ goto badIndex;
+ }
+ *indexPtr &= -2; /* if odd, make it even */
+ if (!count) {
+ *indexPtr = 0;
+ } else if (*indexPtr > 0) {
+ *indexPtr = ((*indexPtr - 2) % count) + 2;
+ } else {
+ *indexPtr = -((-(*indexPtr)) % count);
+ }
+ }
+ return TCL_OK;
+
+ /*
+ * Some of the paths here leave messages in interp->result, so we have to
+ * clear it out before storing our own message.
+ */
+
+ badIndex:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad index \"%s\"", string));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "ITEM_INDEX", "POLY", NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TranslatePolygon --
+ *
+ * This function is called to move a polygon by a given amount.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The position of the polygon is offset by (xDelta, yDelta), and the
+ * bounding box is updated in the generic part of the item structure.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+TranslatePolygon(
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item that is being moved. */
+ double deltaX, double deltaY)
+ /* Amount by which item is to be moved. */
+{
+ PolygonItem *polyPtr = (PolygonItem *) itemPtr;
+ double *coordPtr;
+ int i;
+
+ for (i = 0, coordPtr = polyPtr->coordPtr; i < polyPtr->numPoints;
+ i++, coordPtr += 2) {
+ *coordPtr += deltaX;
+ coordPtr[1] += deltaY;
+ }
+ ComputePolygonBbox(canvas, polyPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * PolygonToPostscript --
+ *
+ * This function is called to generate Postscript for polygon items.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If an error occurs in
+ * generating Postscript then an error message is left in the interp's
+ * result, replacing whatever used to be there. If no error occurs, then
+ * Postscript for the item is appended to the result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+PolygonToPostscript(
+ Tcl_Interp *interp, /* Leave Postscript or error message here. */
+ Tk_Canvas canvas, /* Information about overall canvas. */
+ Tk_Item *itemPtr, /* Item for which Postscript is wanted. */
+ int prepass) /* 1 means this is a prepass to collect font
+ * information; 0 means final Postscript is
+ * being created. */
+{
+ PolygonItem *polyPtr = (PolygonItem *) itemPtr;
+ int style;
+ XColor *color;
+ XColor *fillColor;
+ Pixmap stipple;
+ Pixmap fillStipple;
+ Tk_State state = itemPtr->state;
+ double width;
+ Tcl_Obj *psObj;
+ Tcl_InterpState interpState;
+
+ if (polyPtr->numPoints < 2 || polyPtr->coordPtr == NULL) {
+ return TCL_OK;
+ }
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+ width = polyPtr->outline.width;
+ color = polyPtr->outline.color;
+ stipple = polyPtr->fillStipple;
+ fillColor = polyPtr->fillColor;
+ fillStipple = polyPtr->fillStipple;
+ if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (polyPtr->outline.activeWidth > width) {
+ width = polyPtr->outline.activeWidth;
+ }
+ if (polyPtr->outline.activeColor != NULL) {
+ color = polyPtr->outline.activeColor;
+ }
+ if (polyPtr->outline.activeStipple != None) {
+ stipple = polyPtr->outline.activeStipple;
+ }
+ if (polyPtr->activeFillColor != NULL) {
+ fillColor = polyPtr->activeFillColor;
+ }
+ if (polyPtr->activeFillStipple != None) {
+ fillStipple = polyPtr->activeFillStipple;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (polyPtr->outline.disabledWidth > 0.0) {
+ width = polyPtr->outline.disabledWidth;
+ }
+ if (polyPtr->outline.disabledColor != NULL) {
+ color = polyPtr->outline.disabledColor;
+ }
+ if (polyPtr->outline.disabledStipple != None) {
+ stipple = polyPtr->outline.disabledStipple;
+ }
+ if (polyPtr->disabledFillColor != NULL) {
+ fillColor = polyPtr->disabledFillColor;
+ }
+ if (polyPtr->disabledFillStipple != None) {
+ fillStipple = polyPtr->disabledFillStipple;
+ }
+ }
+
+ /*
+ * Make our working space.
+ */
+
+ psObj = Tcl_NewObj();
+ interpState = Tcl_SaveInterpState(interp, TCL_OK);
+
+ if (polyPtr->numPoints == 2) {
+ if (color == NULL) {
+ goto done;
+ }
+
+ /*
+ * Create a point by using a small circle. (Printer pixels are too
+ * tiny to be used directly...)
+ */
+
+ Tcl_AppendPrintfToObj(psObj,
+ "matrix currentmatrix\n" /* save state */
+ "%.15g %.15g translate " /* go to drawing location */
+ "%.15g %.15g scale " /* scale the drawing */
+ "1 0 moveto " /* correct for origin */
+ "0 0 1 0 360 arc\n" /* make the circle */
+ "setmatrix\n", /* restore state */
+ polyPtr->coordPtr[0],
+ Tk_CanvasPsY(canvas, polyPtr->coordPtr[1]),
+ width/2.0, width/2.0);
+
+ /*
+ * Color it in.
+ */
+
+ Tcl_ResetResult(interp);
+ if (Tk_CanvasPsColor(interp, canvas, color) != TCL_OK) {
+ goto error;
+ }
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+
+ if (stipple != None) {
+ Tcl_AppendToObj(psObj, "clip ", -1);
+
+ Tcl_ResetResult(interp);
+ if (Tk_CanvasPsStipple(interp, canvas, stipple) != TCL_OK) {
+ goto error;
+ }
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+ } else {
+ Tcl_AppendToObj(psObj, "fill\n", -1);
+ }
+ goto done;
+ }
+
+ /*
+ * Fill the area of the polygon.
+ */
+
+ if (fillColor != NULL && polyPtr->numPoints > 3) {
+ Tcl_ResetResult(interp);
+ if (!polyPtr->smooth || !polyPtr->smooth->postscriptProc) {
+ Tk_CanvasPsPath(interp, canvas, polyPtr->coordPtr,
+ polyPtr->numPoints);
+ } else {
+ polyPtr->smooth->postscriptProc(interp, canvas, polyPtr->coordPtr,
+ polyPtr->numPoints, polyPtr->splineSteps);
+ }
+ if (Tk_CanvasPsColor(interp, canvas, fillColor) != TCL_OK) {
+ goto error;
+ }
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+
+ if (fillStipple != None) {
+ Tcl_AppendToObj(psObj, "eoclip ", -1);
+
+ Tcl_ResetResult(interp);
+ if (Tk_CanvasPsStipple(interp, canvas, fillStipple) != TCL_OK) {
+ goto error;
+ }
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+
+ if (color != NULL) {
+ Tcl_AppendToObj(psObj, "grestore gsave\n", -1);
+ }
+ } else {
+ Tcl_AppendToObj(psObj, "eofill\n", -1);
+ }
+ }
+
+ /*
+ * Now draw the outline, if there is one.
+ */
+
+ if (color != NULL) {
+ Tcl_ResetResult(interp);
+ if (!polyPtr->smooth || !polyPtr->smooth->postscriptProc) {
+ Tk_CanvasPsPath(interp, canvas, polyPtr->coordPtr,
+ polyPtr->numPoints);
+ } else {
+ polyPtr->smooth->postscriptProc(interp, canvas, polyPtr->coordPtr,
+ polyPtr->numPoints, polyPtr->splineSteps);
+ }
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+
+ if (polyPtr->joinStyle == JoinRound) {
+ style = 1;
+ } else if (polyPtr->joinStyle == JoinBevel) {
+ style = 2;
+ } else {
+ style = 0;
+ }
+ Tcl_AppendPrintfToObj(psObj, "%d setlinejoin 1 setlinecap\n", style);
+
+ Tcl_ResetResult(interp);
+ if (Tk_CanvasPsOutline(canvas, itemPtr, &polyPtr->outline) != TCL_OK){
+ goto error;
+ }
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+ }
+
+ /*
+ * Plug the accumulated postscript back into the result.
+ */
+
+ done:
+ (void) Tcl_RestoreInterpState(interp, interpState);
+ Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj);
+ Tcl_DecrRefCount(psObj);
+ return TCL_OK;
+
+ error:
+ Tcl_DiscardInterpState(interpState);
+ Tcl_DecrRefCount(psObj);
+ return TCL_ERROR;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkCanvPs.c b/tk8.6/generic/tkCanvPs.c
new file mode 100644
index 0000000..4e41a2a
--- /dev/null
+++ b/tk8.6/generic/tkCanvPs.c
@@ -0,0 +1,1782 @@
+/*
+ * tkCanvPs.c --
+ *
+ * This module provides Postscript output support for canvases, including
+ * the "postscript" widget command plus a few utility functions used for
+ * generating Postscript.
+ *
+ * Copyright (c) 1991-1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "tkInt.h"
+#include "tkCanvas.h"
+#include "tkFont.h"
+
+/*
+ * See tkCanvas.h for key data structures used to implement canvases.
+ */
+
+/*
+ * The following definition is used in generating postscript for images and
+ * windows.
+ */
+
+typedef struct TkColormapData { /* Hold color information for a window */
+ int separated; /* Whether to use separate color bands */
+ int color; /* Whether window is color or black/white */
+ int ncolors; /* Number of color values stored */
+ XColor *colors; /* Pixel value -> RGB mappings */
+ int red_mask, green_mask, blue_mask; /* Masks and shifts for each */
+ int red_shift, green_shift, blue_shift; /* color band */
+} TkColormapData;
+
+/*
+ * One of the following structures is created to keep track of Postscript
+ * output being generated. It consists mostly of information provided on the
+ * widget command line.
+ */
+
+typedef struct TkPostscriptInfo {
+ int x, y, width, height; /* Area to print, in canvas pixel
+ * coordinates. */
+ int x2, y2; /* x+width and y+height. */
+ char *pageXString; /* String value of "-pagex" option or NULL. */
+ char *pageYString; /* String value of "-pagey" option or NULL. */
+ double pageX, pageY; /* Postscript coordinates (in points)
+ * corresponding to pageXString and
+ * pageYString. Don't forget that y-values
+ * grow upwards for Postscript! */
+ char *pageWidthString; /* Printed width of output. */
+ char *pageHeightString; /* Printed height of output. */
+ double scale; /* Scale factor for conversion: each pixel
+ * maps into this many points. */
+ Tk_Anchor pageAnchor; /* How to anchor bbox on Postscript page. */
+ int rotate; /* Non-zero means output should be rotated on
+ * page (landscape mode). */
+ char *fontVar; /* If non-NULL, gives name of global variable
+ * containing font mapping information.
+ * Malloc'ed. */
+ char *colorVar; /* If non-NULL, give name of global variable
+ * containing color mapping information.
+ * Malloc'ed. */
+ char *colorMode; /* Mode for handling colors: "monochrome",
+ * "gray", or "color". Malloc'ed. */
+ int colorLevel; /* Numeric value corresponding to colorMode: 0
+ * for mono, 1 for gray, 2 for color. */
+ char *fileName; /* Name of file in which to write Postscript;
+ * NULL means return Postscript info as
+ * result. Malloc'ed. */
+ char *channelName; /* If -channel is specified, the name of the
+ * channel to use. */
+ Tcl_Channel chan; /* Open channel corresponding to fileName. */
+ Tcl_HashTable fontTable; /* Hash table containing names of all font
+ * families used in output. The hash table
+ * values are not used. */
+ int prepass; /* Non-zero means that we're currently in the
+ * pre-pass that collects font information, so
+ * the Postscript generated isn't relevant. */
+ int prolog; /* Non-zero means output should contain the
+ * standard prolog in the header. Generated in
+ * library/mkpsenc.tcl, stored in the variable
+ * ::tk::ps_preamable [sic]. */
+ Tk_Window tkwin; /* Window to get font pixel/point transform
+ * from. */
+} TkPostscriptInfo;
+
+/*
+ * The table below provides a template that's used to process arguments to the
+ * canvas "postscript" command and fill in TkPostscriptInfo structures.
+ */
+
+static const Tk_ConfigSpec configSpecs[] = {
+ {TK_CONFIG_STRING, "-colormap", NULL, NULL,
+ "", Tk_Offset(TkPostscriptInfo, colorVar), 0, NULL},
+ {TK_CONFIG_STRING, "-colormode", NULL, NULL,
+ "", Tk_Offset(TkPostscriptInfo, colorMode), 0, NULL},
+ {TK_CONFIG_STRING, "-file", NULL, NULL,
+ "", Tk_Offset(TkPostscriptInfo, fileName), 0, NULL},
+ {TK_CONFIG_STRING, "-channel", NULL, NULL,
+ "", Tk_Offset(TkPostscriptInfo, channelName), 0, NULL},
+ {TK_CONFIG_STRING, "-fontmap", NULL, NULL,
+ "", Tk_Offset(TkPostscriptInfo, fontVar), 0, NULL},
+ {TK_CONFIG_PIXELS, "-height", NULL, NULL,
+ "", Tk_Offset(TkPostscriptInfo, height), 0, NULL},
+ {TK_CONFIG_ANCHOR, "-pageanchor", NULL, NULL,
+ "", Tk_Offset(TkPostscriptInfo, pageAnchor), 0, NULL},
+ {TK_CONFIG_STRING, "-pageheight", NULL, NULL,
+ "", Tk_Offset(TkPostscriptInfo, pageHeightString), 0, NULL},
+ {TK_CONFIG_STRING, "-pagewidth", NULL, NULL,
+ "", Tk_Offset(TkPostscriptInfo, pageWidthString), 0, NULL},
+ {TK_CONFIG_STRING, "-pagex", NULL, NULL,
+ "", Tk_Offset(TkPostscriptInfo, pageXString), 0, NULL},
+ {TK_CONFIG_STRING, "-pagey", NULL, NULL,
+ "", Tk_Offset(TkPostscriptInfo, pageYString), 0, NULL},
+ {TK_CONFIG_BOOLEAN, "-prolog", NULL, NULL,
+ "", Tk_Offset(TkPostscriptInfo, prolog), 0, NULL},
+ {TK_CONFIG_BOOLEAN, "-rotate", NULL, NULL,
+ "", Tk_Offset(TkPostscriptInfo, rotate), 0, NULL},
+ {TK_CONFIG_PIXELS, "-width", NULL, NULL,
+ "", Tk_Offset(TkPostscriptInfo, width), 0, NULL},
+ {TK_CONFIG_PIXELS, "-x", NULL, NULL,
+ "", Tk_Offset(TkPostscriptInfo, x), 0, NULL},
+ {TK_CONFIG_PIXELS, "-y", NULL, NULL,
+ "", Tk_Offset(TkPostscriptInfo, y), 0, NULL},
+ {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}
+};
+
+/*
+ * Forward declarations for functions defined later in this file:
+ */
+
+static int GetPostscriptPoints(Tcl_Interp *interp,
+ char *string, double *doublePtr);
+static void PostscriptBitmap(Tk_Window tkwin, Pixmap bitmap,
+ int startX, int startY, int width, int height,
+ Tcl_Obj *psObj);
+static inline Tcl_Obj * GetPostscriptBuffer(Tcl_Interp *interp);
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkCanvPostscriptCmd --
+ *
+ * This function is invoked to process the "postscript" options of the
+ * widget command for canvas widgets. See the user documentation for
+ * details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+int
+TkCanvPostscriptCmd(
+ TkCanvas *canvasPtr, /* Information about canvas widget. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. Caller has already parsed
+ * this command enough to know that argv[1] is
+ * "postscript". */
+{
+ TkPostscriptInfo psInfo, *psInfoPtr = &psInfo;
+ Tk_PostscriptInfo oldInfoPtr;
+ int result;
+ Tk_Item *itemPtr;
+#define STRING_LENGTH 400
+ const char *p;
+ time_t now;
+ size_t length;
+ Tk_Window tkwin = canvasPtr->tkwin;
+ Tcl_HashSearch search;
+ Tcl_HashEntry *hPtr;
+ Tcl_DString buffer;
+ Tcl_Obj *preambleObj;
+ Tcl_Obj *psObj;
+ int deltaX = 0, deltaY = 0; /* Offset of lower-left corner of area to be
+ * marked up, measured in canvas units from
+ * the positioning point on the page (reflects
+ * anchor position). Initial values needed
+ * only to stop compiler warnings. */
+
+ /*
+ * Get the generic preamble. We only ever bother with the ASCII encoding;
+ * the others just make life too complicated and never actually worked as
+ * such.
+ */
+
+ result = Tcl_EvalEx(interp, "::tk::ensure_psenc_is_loaded", -1, 0);
+ if (result != TCL_OK) {
+ return result;
+ }
+ preambleObj = Tcl_GetVar2Ex(interp, "::tk::ps_preamble", NULL,
+ TCL_LEAVE_ERR_MSG);
+ if (preambleObj == NULL) {
+ return TCL_ERROR;
+ }
+ Tcl_IncrRefCount(preambleObj);
+ Tcl_ResetResult(interp);
+ psObj = Tcl_NewObj();
+
+ /*
+ * Initialize the data structure describing Postscript generation, then
+ * process all the arguments to fill the data structure in.
+ */
+
+ oldInfoPtr = canvasPtr->psInfo;
+ canvasPtr->psInfo = (Tk_PostscriptInfo) psInfoPtr;
+ psInfo.x = canvasPtr->xOrigin;
+ psInfo.y = canvasPtr->yOrigin;
+ psInfo.width = -1;
+ psInfo.height = -1;
+ psInfo.pageXString = NULL;
+ psInfo.pageYString = NULL;
+ psInfo.pageX = 72*4.25;
+ psInfo.pageY = 72*5.5;
+ psInfo.pageWidthString = NULL;
+ psInfo.pageHeightString = NULL;
+ psInfo.scale = 1.0;
+ psInfo.pageAnchor = TK_ANCHOR_CENTER;
+ psInfo.rotate = 0;
+ psInfo.fontVar = NULL;
+ psInfo.colorVar = NULL;
+ psInfo.colorMode = NULL;
+ psInfo.colorLevel = 0;
+ psInfo.fileName = NULL;
+ psInfo.channelName = NULL;
+ psInfo.chan = NULL;
+ psInfo.prepass = 0;
+ psInfo.prolog = 1;
+ psInfo.tkwin = tkwin;
+ Tcl_InitHashTable(&psInfo.fontTable, TCL_STRING_KEYS);
+ result = Tk_ConfigureWidget(interp, tkwin, configSpecs, argc-2, argv+2,
+ (char *) &psInfo, TK_CONFIG_ARGV_ONLY);
+ if (result != TCL_OK) {
+ goto cleanup;
+ }
+
+ if (psInfo.width == -1) {
+ psInfo.width = Tk_Width(tkwin);
+ }
+ if (psInfo.height == -1) {
+ psInfo.height = Tk_Height(tkwin);
+ }
+ psInfo.x2 = psInfo.x + psInfo.width;
+ psInfo.y2 = psInfo.y + psInfo.height;
+
+ if (psInfo.pageXString != NULL) {
+ if (GetPostscriptPoints(interp, psInfo.pageXString,
+ &psInfo.pageX) != TCL_OK) {
+ goto cleanup;
+ }
+ }
+ if (psInfo.pageYString != NULL) {
+ if (GetPostscriptPoints(interp, psInfo.pageYString,
+ &psInfo.pageY) != TCL_OK) {
+ goto cleanup;
+ }
+ }
+ if (psInfo.pageWidthString != NULL) {
+ if (GetPostscriptPoints(interp, psInfo.pageWidthString,
+ &psInfo.scale) != TCL_OK) {
+ goto cleanup;
+ }
+ psInfo.scale /= psInfo.width;
+ } else if (psInfo.pageHeightString != NULL) {
+ if (GetPostscriptPoints(interp, psInfo.pageHeightString,
+ &psInfo.scale) != TCL_OK) {
+ goto cleanup;
+ }
+ psInfo.scale /= psInfo.height;
+ } else {
+ psInfo.scale = (72.0/25.4)*WidthMMOfScreen(Tk_Screen(tkwin));
+ psInfo.scale /= WidthOfScreen(Tk_Screen(tkwin));
+ }
+ switch (psInfo.pageAnchor) {
+ case TK_ANCHOR_NW:
+ case TK_ANCHOR_W:
+ case TK_ANCHOR_SW:
+ deltaX = 0;
+ break;
+ case TK_ANCHOR_N:
+ case TK_ANCHOR_CENTER:
+ case TK_ANCHOR_S:
+ deltaX = -psInfo.width/2;
+ break;
+ case TK_ANCHOR_NE:
+ case TK_ANCHOR_E:
+ case TK_ANCHOR_SE:
+ deltaX = -psInfo.width;
+ break;
+ }
+ switch (psInfo.pageAnchor) {
+ case TK_ANCHOR_NW:
+ case TK_ANCHOR_N:
+ case TK_ANCHOR_NE:
+ deltaY = - psInfo.height;
+ break;
+ case TK_ANCHOR_W:
+ case TK_ANCHOR_CENTER:
+ case TK_ANCHOR_E:
+ deltaY = -psInfo.height/2;
+ break;
+ case TK_ANCHOR_SW:
+ case TK_ANCHOR_S:
+ case TK_ANCHOR_SE:
+ deltaY = 0;
+ break;
+ }
+
+ if (psInfo.colorMode == NULL) {
+ psInfo.colorLevel = 2;
+ } else {
+ length = strlen(psInfo.colorMode);
+ if (strncmp(psInfo.colorMode, "monochrome", length) == 0) {
+ psInfo.colorLevel = 0;
+ } else if (strncmp(psInfo.colorMode, "gray", length) == 0) {
+ psInfo.colorLevel = 1;
+ } else if (strncmp(psInfo.colorMode, "color", length) == 0) {
+ psInfo.colorLevel = 2;
+ } else {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad color mode \"%s\": must be monochrome, gray, or color",
+ psInfo.colorMode));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "PS", "COLORMODE", NULL);
+ result = TCL_ERROR;
+ goto cleanup;
+ }
+ }
+
+ if (psInfo.fileName != NULL) {
+ /*
+ * Check that -file and -channel are not both specified.
+ */
+
+ if (psInfo.channelName != NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "can't specify both -file and -channel", -1));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "PS", "USAGE", NULL);
+ result = TCL_ERROR;
+ goto cleanup;
+ }
+
+ /*
+ * Check that we are not in a safe interpreter. If we are, disallow
+ * the -file specification.
+ */
+
+ if (Tcl_IsSafe(interp)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "can't specify -file in a safe interpreter", -1));
+ Tcl_SetErrorCode(interp, "TK", "SAFE", "PS_FILE", NULL);
+ result = TCL_ERROR;
+ goto cleanup;
+ }
+
+ p = Tcl_TranslateFileName(interp, psInfo.fileName, &buffer);
+ if (p == NULL) {
+ goto cleanup;
+ }
+ psInfo.chan = Tcl_OpenFileChannel(interp, p, "w", 0666);
+ Tcl_DStringFree(&buffer);
+ if (psInfo.chan == NULL) {
+ goto cleanup;
+ }
+ }
+
+ if (psInfo.channelName != NULL) {
+ int mode;
+
+ /*
+ * Check that the channel is found in this interpreter and that it is
+ * open for writing.
+ */
+
+ psInfo.chan = Tcl_GetChannel(interp, psInfo.channelName, &mode);
+ if (psInfo.chan == NULL) {
+ result = TCL_ERROR;
+ goto cleanup;
+ }
+ if (!(mode & TCL_WRITABLE)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "channel \"%s\" wasn't opened for writing",
+ psInfo.channelName));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "PS", "UNWRITABLE",NULL);
+ result = TCL_ERROR;
+ goto cleanup;
+ }
+ }
+
+ /*
+ * Make a pre-pass over all of the items, generating Postscript and then
+ * throwing it away. The purpose of this pass is just to collect
+ * information about all the fonts in use, so that we can output font
+ * information in the proper form required by the Document Structuring
+ * Conventions.
+ */
+
+ psInfo.prepass = 1;
+ for (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;
+ itemPtr = itemPtr->nextPtr) {
+ if ((itemPtr->x1 >= psInfo.x2) || (itemPtr->x2 < psInfo.x)
+ || (itemPtr->y1 >= psInfo.y2) || (itemPtr->y2 < psInfo.y)) {
+ continue;
+ }
+ if (itemPtr->typePtr->postscriptProc == NULL) {
+ continue;
+ }
+ result = itemPtr->typePtr->postscriptProc(interp,
+ (Tk_Canvas) canvasPtr, itemPtr, 1);
+ Tcl_ResetResult(interp);
+ if (result != TCL_OK) {
+ /*
+ * An error just occurred. Just skip out of this loop. There's no
+ * need to report the error now; it can be reported later (errors
+ * can happen later that don't happen now, so we still have to
+ * check for errors later anyway).
+ */
+
+ break;
+ }
+ }
+ psInfo.prepass = 0;
+
+ /*
+ * Generate the header and prolog for the Postscript.
+ */
+
+ if (psInfo.prolog) {
+ Tcl_AppendToObj(psObj,
+ "%!PS-Adobe-3.0 EPSF-3.0\n"
+ "%%Creator: Tk Canvas Widget\n", -1);
+
+#ifdef HAVE_PW_GECOS
+ if (!Tcl_IsSafe(interp)) {
+ struct passwd *pwPtr = getpwuid(getuid()); /* INTL: Native. */
+
+ Tcl_AppendPrintfToObj(psObj,
+ "%%%%For: %s\n", (pwPtr ? pwPtr->pw_gecos : "Unknown"));
+ endpwent();
+ }
+#endif /* HAVE_PW_GECOS */
+ Tcl_AppendPrintfToObj(psObj,
+ "%%%%Title: Window %s\n", Tk_PathName(tkwin));
+ time(&now);
+ Tcl_AppendPrintfToObj(psObj,
+ "%%%%CreationDate: %s", ctime(&now)); /* INTL: Native. */
+ if (!psInfo.rotate) {
+ Tcl_AppendPrintfToObj(psObj,
+ "%%%%BoundingBox: %d %d %d %d\n",
+ (int) (psInfo.pageX + psInfo.scale*deltaX),
+ (int) (psInfo.pageY + psInfo.scale*deltaY),
+ (int) (psInfo.pageX + psInfo.scale*(deltaX + psInfo.width)
+ + 1.0),
+ (int) (psInfo.pageY + psInfo.scale*(deltaY + psInfo.height)
+ + 1.0));
+ } else {
+ Tcl_AppendPrintfToObj(psObj,
+ "%%%%BoundingBox: %d %d %d %d\n",
+ (int) (psInfo.pageX - psInfo.scale*(deltaY+psInfo.height)),
+ (int) (psInfo.pageY + psInfo.scale*deltaX),
+ (int) (psInfo.pageX - psInfo.scale*deltaY + 1.0),
+ (int) (psInfo.pageY + psInfo.scale*(deltaX + psInfo.width)
+ + 1.0));
+ }
+ Tcl_AppendPrintfToObj(psObj,
+ "%%%%Pages: 1\n"
+ "%%%%DocumentData: Clean7Bit\n"
+ "%%%%Orientation: %s\n",
+ psInfo.rotate ? "Landscape" : "Portrait");
+ p = "%%%%DocumentNeededResources: font %s\n";
+ for (hPtr = Tcl_FirstHashEntry(&psInfo.fontTable, &search);
+ hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
+ Tcl_AppendPrintfToObj(psObj, p,
+ Tcl_GetHashKey(&psInfo.fontTable, hPtr));
+ p = "%%%%+ font %s\n";
+ }
+ Tcl_AppendToObj(psObj, "%%EndComments\n\n", -1);
+
+ /*
+ * Insert the prolog
+ */
+
+ Tcl_AppendObjToObj(psObj, preambleObj);
+
+ if (psInfo.chan != NULL) {
+ if (Tcl_WriteObj(psInfo.chan, psObj) == -1) {
+ channelWriteFailed:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "problem writing postscript data to channel: %s",
+ Tcl_PosixError(interp)));
+ result = TCL_ERROR;
+ goto cleanup;
+ }
+ Tcl_DecrRefCount(psObj);
+ psObj = Tcl_NewObj();
+ }
+
+ /*
+ * Document setup: set the color level and include fonts.
+ */
+
+ Tcl_AppendPrintfToObj(psObj,
+ "%%%%BeginSetup\n/CL %d def\n", psInfo.colorLevel);
+ for (hPtr = Tcl_FirstHashEntry(&psInfo.fontTable, &search);
+ hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
+ Tcl_AppendPrintfToObj(psObj,
+ "%%%%IncludeResource: font %s\n",
+ (char *) Tcl_GetHashKey(&psInfo.fontTable, hPtr));
+ }
+ Tcl_AppendToObj(psObj, "%%EndSetup\n\n", -1);
+
+ /*
+ * Page setup: move to page positioning point, rotate if needed, set
+ * scale factor, offset for proper anchor position, and set clip
+ * region.
+ */
+
+ Tcl_AppendToObj(psObj, "%%Page: 1 1\nsave\n", -1);
+ Tcl_AppendPrintfToObj(psObj,
+ "%.1f %.1f translate\n", psInfo.pageX, psInfo.pageY);
+ if (psInfo.rotate) {
+ Tcl_AppendToObj(psObj, "90 rotate\n", -1);
+ }
+ Tcl_AppendPrintfToObj(psObj,
+ "%.4g %.4g scale\n", psInfo.scale, psInfo.scale);
+ Tcl_AppendPrintfToObj(psObj,
+ "%d %d translate\n", deltaX - psInfo.x, deltaY);
+ Tcl_AppendPrintfToObj(psObj,
+ "%d %.15g moveto %d %.15g lineto %d %.15g lineto %d %.15g "
+ "lineto closepath clip newpath\n",
+ psInfo.x, Tk_PostscriptY((double)psInfo.y,
+ (Tk_PostscriptInfo)psInfoPtr),
+ psInfo.x2, Tk_PostscriptY((double)psInfo.y,
+ (Tk_PostscriptInfo)psInfoPtr),
+ psInfo.x2, Tk_PostscriptY((double)psInfo.y2,
+ (Tk_PostscriptInfo)psInfoPtr),
+ psInfo.x, Tk_PostscriptY((double)psInfo.y2,
+ (Tk_PostscriptInfo)psInfoPtr));
+ if (psInfo.chan != NULL) {
+ if (Tcl_WriteObj(psInfo.chan, psObj) == -1) {
+ goto channelWriteFailed;
+ }
+ Tcl_DecrRefCount(psObj);
+ psObj = Tcl_NewObj();
+ }
+ }
+
+ /*
+ * Iterate through all the items, having each relevant one draw itself.
+ * Quit if any of the items returns an error.
+ */
+
+ result = TCL_OK;
+ for (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;
+ itemPtr = itemPtr->nextPtr) {
+ if ((itemPtr->x1 >= psInfo.x2) || (itemPtr->x2 < psInfo.x)
+ || (itemPtr->y1 >= psInfo.y2) || (itemPtr->y2 < psInfo.y)) {
+ continue;
+ }
+ if (itemPtr->typePtr->postscriptProc == NULL) {
+ continue;
+ }
+ if (itemPtr->state == TK_STATE_HIDDEN) {
+ continue;
+ }
+
+ Tcl_ResetResult(interp);
+ result = itemPtr->typePtr->postscriptProc(interp,
+ (Tk_Canvas) canvasPtr, itemPtr, 0);
+ if (result != TCL_OK) {
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (generating Postscript for item %d)",
+ itemPtr->id));
+ goto cleanup;
+ }
+
+ Tcl_AppendToObj(psObj, "gsave\n", -1);
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+ Tcl_AppendToObj(psObj, "grestore\n", -1);
+
+ if (psInfo.chan != NULL) {
+ if (Tcl_WriteObj(psInfo.chan, psObj) == -1) {
+ goto channelWriteFailed;
+ }
+ Tcl_DecrRefCount(psObj);
+ psObj = Tcl_NewObj();
+ }
+ }
+
+ /*
+ * Output page-end information, such as commands to print the page and
+ * document trailer stuff.
+ */
+
+ if (psInfo.prolog) {
+ Tcl_AppendToObj(psObj,
+ "restore showpage\n\n"
+ "%%Trailer\n"
+ "end\n"
+ "%%EOF\n", -1);
+
+ if (psInfo.chan != NULL) {
+ if (Tcl_WriteObj(psInfo.chan, psObj) == -1) {
+ goto channelWriteFailed;
+ }
+ }
+ }
+
+ if (psInfo.chan == NULL) {
+ Tcl_SetObjResult(interp, psObj);
+ psObj = Tcl_NewObj();
+ }
+
+ /*
+ * Clean up psInfo to release malloc'ed stuff.
+ */
+
+ cleanup:
+ if (psInfo.pageXString != NULL) {
+ ckfree(psInfo.pageXString);
+ }
+ if (psInfo.pageYString != NULL) {
+ ckfree(psInfo.pageYString);
+ }
+ if (psInfo.pageWidthString != NULL) {
+ ckfree(psInfo.pageWidthString);
+ }
+ if (psInfo.pageHeightString != NULL) {
+ ckfree(psInfo.pageHeightString);
+ }
+ if (psInfo.fontVar != NULL) {
+ ckfree(psInfo.fontVar);
+ }
+ if (psInfo.colorVar != NULL) {
+ ckfree(psInfo.colorVar);
+ }
+ if (psInfo.colorMode != NULL) {
+ ckfree(psInfo.colorMode);
+ }
+ if (psInfo.fileName != NULL) {
+ ckfree(psInfo.fileName);
+ }
+ if ((psInfo.chan != NULL) && (psInfo.channelName == NULL)) {
+ Tcl_Close(interp, psInfo.chan);
+ }
+ if (psInfo.channelName != NULL) {
+ ckfree(psInfo.channelName);
+ }
+ Tcl_DeleteHashTable(&psInfo.fontTable);
+ canvasPtr->psInfo = (Tk_PostscriptInfo) oldInfoPtr;
+ Tcl_DecrRefCount(preambleObj);
+ Tcl_DecrRefCount(psObj);
+ return result;
+}
+
+static inline Tcl_Obj *
+GetPostscriptBuffer(
+ Tcl_Interp *interp)
+{
+ Tcl_Obj *psObj = Tcl_GetObjResult(interp);
+
+ if (Tcl_IsShared(psObj)) {
+ psObj = Tcl_DuplicateObj(psObj);
+ Tcl_SetObjResult(interp, psObj);
+ }
+ return psObj;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_PostscriptColor --
+ *
+ * This function is called by individual canvas items when they want to
+ * set a color value for output. Given information about an X color, this
+ * function will generate Postscript commands to set up an appropriate
+ * color in Postscript.
+ *
+ * Results:
+ * Returns a standard Tcl return value. If an error occurs then an error
+ * message will be left in the interp's result. If no error occurs, then
+ * additional Postscript will be appended to the interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_PostscriptColor(
+ Tcl_Interp *interp,
+ Tk_PostscriptInfo psInfo, /* Postscript info. */
+ XColor *colorPtr) /* Information about color. */
+{
+ TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo;
+ double red, green, blue;
+
+ if (psInfoPtr->prepass) {
+ return TCL_OK;
+ }
+
+ /*
+ * If there is a color map defined, then look up the color's name in the
+ * map and use the Postscript commands found there, if there are any.
+ */
+
+ if (psInfoPtr->colorVar != NULL) {
+ const char *cmdString = Tcl_GetVar2(interp, psInfoPtr->colorVar,
+ Tk_NameOfColor(colorPtr), 0);
+
+ if (cmdString != NULL) {
+ Tcl_AppendPrintfToObj(GetPostscriptBuffer(interp),
+ "%s\n", cmdString);
+ return TCL_OK;
+ }
+ }
+
+ /*
+ * No color map entry for this color. Grab the color's intensities and
+ * output Postscript commands for them. Special note: X uses a range of
+ * 0-65535 for intensities, but most displays only use a range of 0-255,
+ * which maps to (0, 256, 512, ... 65280) in the X scale. This means that
+ * there's no way to get perfect white, since the highest intensity is
+ * only 65280 out of 65535. To work around this problem, rescale the X
+ * intensity to a 0-255 scale and use that as the basis for the Postscript
+ * colors. This scheme still won't work if the display only uses 4 bits
+ * per color, but most diplays use at least 8 bits.
+ */
+
+ red = ((double) (((int) colorPtr->red) >> 8))/255.0;
+ green = ((double) (((int) colorPtr->green) >> 8))/255.0;
+ blue = ((double) (((int) colorPtr->blue) >> 8))/255.0;
+ Tcl_AppendPrintfToObj(GetPostscriptBuffer(interp),
+ "%.3f %.3f %.3f setrgbcolor AdjustColor\n",
+ red, green, blue);
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_PostscriptFont --
+ *
+ * This function is called by individual canvas items when they want to
+ * output text. Given information about an X font, this function will
+ * generate Postscript commands to set up an appropriate font in
+ * Postscript.
+ *
+ * Results:
+ * Returns a standard Tcl return value. If an error occurs then an error
+ * message will be left in the interp's result. If no error occurs, then
+ * additional Postscript will be appended to the interp's result.
+ *
+ * Side effects:
+ * The Postscript font name is entered into psInfoPtr->fontTable if it
+ * wasn't already there.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_PostscriptFont(
+ Tcl_Interp *interp,
+ Tk_PostscriptInfo psInfo, /* Postscript Info. */
+ Tk_Font tkfont) /* Information about font in which text is to
+ * be printed. */
+{
+ TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo;
+ Tcl_DString ds;
+ int i, points;
+ const char *fontname;
+
+ /*
+ * First, look up the font's name in the font map, if there is one. If
+ * there is an entry for this font, it consists of a list containing font
+ * name and size. Use this information.
+ */
+
+ if (psInfoPtr->fontVar != NULL) {
+ const char *name = Tk_NameOfFont(tkfont);
+ Tcl_Obj **objv;
+ int objc;
+ double size;
+ Tcl_Obj *list = Tcl_GetVar2Ex(interp, psInfoPtr->fontVar, name, 0);
+
+ if (list != NULL) {
+ if (Tcl_ListObjGetElements(interp, list, &objc, &objv) != TCL_OK
+ || objc != 2
+ || (fontname = Tcl_GetString(objv[0]))[0] == '\0'
+ || strchr(fontname, ' ') != NULL
+ || Tcl_GetDoubleFromObj(interp, objv[1], &size) != TCL_OK
+ || size <= 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad font map entry for \"%s\": \"%s\"",
+ name, Tcl_GetString(list)));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "PS", "FONTMAP",
+ NULL);
+ return TCL_ERROR;
+ }
+
+ Tcl_AppendPrintfToObj(GetPostscriptBuffer(interp),
+ "/%s findfont %d scalefont%s setfont\n",
+ fontname, (int) size,
+ strncasecmp(fontname, "Symbol", 7) ? " ISOEncode" : "");
+ Tcl_CreateHashEntry(&psInfoPtr->fontTable, fontname, &i);
+ return TCL_OK;
+ }
+ }
+
+ /*
+ * Nothing in the font map, so fall back to the old guessing technique.
+ */
+
+ Tcl_DStringInit(&ds);
+ points = Tk_PostscriptFontName(tkfont, &ds);
+ fontname = Tcl_DStringValue(&ds);
+ Tcl_AppendPrintfToObj(GetPostscriptBuffer(interp),
+ "/%s findfont %d scalefont%s setfont\n",
+ fontname, (int)(TkFontGetPoints(psInfoPtr->tkwin, points) + 0.5),
+ strncasecmp(fontname, "Symbol", 7) ? " ISOEncode" : "");
+ Tcl_CreateHashEntry(&psInfoPtr->fontTable, Tcl_DStringValue(&ds), &i);
+ Tcl_DStringFree(&ds);
+
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_PostscriptBitmap --
+ *
+ * This function is called to output the contents of a sub-region of a
+ * bitmap in proper image data format for Postscript (i.e. data between
+ * angle brackets, one bit per pixel).
+ *
+ * Results:
+ * Returns a standard Tcl return value. If an error occurs then an error
+ * message will be left in the interp's result. If no error occurs, then
+ * additional Postscript will be appended to the interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_PostscriptBitmap(
+ Tcl_Interp *interp,
+ Tk_Window tkwin,
+ Tk_PostscriptInfo psInfo, /* Postscript info. */
+ Pixmap bitmap, /* Bitmap for which to generate Postscript. */
+ int startX, int startY, /* Coordinates of upper-left corner of
+ * rectangular region to output. */
+ int width, int height) /* Height of rectangular region. */
+{
+ TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo;
+
+ if (psInfoPtr->prepass) {
+ return TCL_OK;
+ }
+
+ PostscriptBitmap(tkwin, bitmap, startX, startY, width, height,
+ GetPostscriptBuffer(interp));
+ return TCL_OK;
+}
+
+static void
+PostscriptBitmap(
+ Tk_Window tkwin,
+ Pixmap bitmap, /* Bitmap for which to generate Postscript. */
+ int startX, int startY, /* Coordinates of upper-left corner of
+ * rectangular region to output. */
+ int width, int height, /* Height of rectangular region. */
+ Tcl_Obj *psObj) /* Where to append the postscript. */
+{
+ XImage *imagePtr;
+ int charsInLine, x, y, lastX, lastY, value, mask;
+ unsigned int totalWidth, totalHeight;
+ Window dummyRoot;
+ int dummyX, dummyY;
+ unsigned dummyBorderwidth, dummyDepth;
+
+ /*
+ * The following call should probably be a call to Tk_SizeOfBitmap
+ * instead, but it seems that we are occasionally invoked by custom item
+ * types that create their own bitmaps without registering them with Tk.
+ * XGetGeometry is a bit slower than Tk_SizeOfBitmap, but it shouldn't
+ * matter here.
+ */
+
+ XGetGeometry(Tk_Display(tkwin), bitmap, &dummyRoot,
+ (int *) &dummyX, (int *) &dummyY, (unsigned int *) &totalWidth,
+ (unsigned int *) &totalHeight, &dummyBorderwidth, &dummyDepth);
+ imagePtr = XGetImage(Tk_Display(tkwin), bitmap, 0, 0,
+ totalWidth, totalHeight, 1, XYPixmap);
+
+ Tcl_AppendToObj(psObj, "<", -1);
+ mask = 0x80;
+ value = 0;
+ charsInLine = 0;
+ lastX = startX + width - 1;
+ lastY = startY + height - 1;
+ for (y = lastY; y >= startY; y--) {
+ for (x = startX; x <= lastX; x++) {
+ if (XGetPixel(imagePtr, x, y)) {
+ value |= mask;
+ }
+ mask >>= 1;
+ if (mask == 0) {
+ Tcl_AppendPrintfToObj(psObj, "%02x", value);
+ mask = 0x80;
+ value = 0;
+ charsInLine += 2;
+ if (charsInLine >= 60) {
+ Tcl_AppendToObj(psObj, "\n", -1);
+ charsInLine = 0;
+ }
+ }
+ }
+ if (mask != 0x80) {
+ Tcl_AppendPrintfToObj(psObj, "%02x", value);
+ mask = 0x80;
+ value = 0;
+ charsInLine += 2;
+ }
+ }
+ Tcl_AppendToObj(psObj, ">", -1);
+
+ XDestroyImage(imagePtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_PostscriptStipple --
+ *
+ * This function is called by individual canvas items when they have
+ * created a path that they'd like to be filled with a stipple pattern.
+ * Given information about an X bitmap, this function will generate
+ * Postscript commands to fill the current clip region using a stipple
+ * pattern defined by the bitmap.
+ *
+ * Results:
+ * Returns a standard Tcl return value. If an error occurs then an error
+ * message will be left in the interp's result. If no error occurs, then
+ * additional Postscript will be appended to the interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_PostscriptStipple(
+ Tcl_Interp *interp,
+ Tk_Window tkwin,
+ Tk_PostscriptInfo psInfo, /* Interpreter for returning Postscript or
+ * error message. */
+ Pixmap bitmap) /* Bitmap to use for stippling. */
+{
+ TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo;
+ int width, height;
+ Window dummyRoot;
+ int dummyX, dummyY;
+ unsigned dummyBorderwidth, dummyDepth;
+ Tcl_Obj *psObj;
+
+ if (psInfoPtr->prepass) {
+ return TCL_OK;
+ }
+
+ /*
+ * The following call should probably be a call to Tk_SizeOfBitmap
+ * instead, but it seems that we are occasionally invoked by custom item
+ * types that create their own bitmaps without registering them with Tk.
+ * XGetGeometry is a bit slower than Tk_SizeOfBitmap, but it shouldn't
+ * matter here.
+ */
+
+ XGetGeometry(Tk_Display(tkwin), bitmap, &dummyRoot,
+ (int *) &dummyX, (int *) &dummyY, (unsigned *) &width,
+ (unsigned *) &height, &dummyBorderwidth, &dummyDepth);
+
+ psObj = GetPostscriptBuffer(interp);
+ Tcl_AppendPrintfToObj(psObj, "%d %d ", width, height);
+ PostscriptBitmap(tkwin, bitmap, 0, 0, width, height, psObj);
+ Tcl_AppendToObj(psObj, " StippleFill\n", -1);
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_PostscriptY --
+ *
+ * Given a y-coordinate in local coordinates, this function returns a
+ * y-coordinate to use for Postscript output. Required because canvases
+ * have their origin in the top-left, but postscript pages have their
+ * origin in the bottom left.
+ *
+ * Results:
+ * Returns the Postscript coordinate that corresponds to "y".
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+double
+Tk_PostscriptY(
+ double y, /* Y-coordinate in canvas coords. */
+ Tk_PostscriptInfo psInfo) /* Postscript info */
+{
+ TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo;
+
+ return psInfoPtr->y2 - y;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_PostscriptPath --
+ *
+ * Given an array of points for a path, generate Postscript commands to
+ * create the path.
+ *
+ * Results:
+ * Postscript commands get appended to what's in the interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_PostscriptPath(
+ Tcl_Interp *interp,
+ Tk_PostscriptInfo psInfo, /* Canvas on whose behalf Postscript is being
+ * generated. */
+ double *coordPtr, /* Pointer to first in array of 2*numPoints
+ * coordinates giving points for path. */
+ int numPoints) /* Number of points at *coordPtr. */
+{
+ TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo;
+ Tcl_Obj *psObj;
+
+ if (psInfoPtr->prepass) {
+ return;
+ }
+
+ psObj = GetPostscriptBuffer(interp);
+ Tcl_AppendPrintfToObj(psObj, "%.15g %.15g moveto\n",
+ coordPtr[0], Tk_PostscriptY(coordPtr[1], psInfo));
+ for (numPoints--, coordPtr += 2; numPoints > 0;
+ numPoints--, coordPtr += 2) {
+ Tcl_AppendPrintfToObj(psObj, "%.15g %.15g lineto\n",
+ coordPtr[0], Tk_PostscriptY(coordPtr[1], psInfo));
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * GetPostscriptPoints --
+ *
+ * Given a string, returns the number of Postscript points corresponding
+ * to that string.
+ *
+ * Results:
+ * The return value is a standard Tcl return result. If TCL_OK is
+ * returned, then everything went well and the screen distance is stored
+ * at *doublePtr; otherwise TCL_ERROR is returned and an error message is
+ * left in the interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+GetPostscriptPoints(
+ Tcl_Interp *interp, /* Use this for error reporting. */
+ char *string, /* String describing a screen distance. */
+ double *doublePtr) /* Place to store converted result. */
+{
+ char *end;
+ double d;
+
+ d = strtod(string, &end);
+ if (end == string) {
+ goto error;
+ }
+ while ((*end != '\0') && isspace(UCHAR(*end))) {
+ end++;
+ }
+ switch (*end) {
+ case 'c':
+ d *= 72.0/2.54;
+ end++;
+ break;
+ case 'i':
+ d *= 72.0;
+ end++;
+ break;
+ case 'm':
+ d *= 72.0/25.4;
+ end++;
+ break;
+ case 0:
+ break;
+ case 'p':
+ end++;
+ break;
+ default:
+ goto error;
+ }
+ while ((*end != '\0') && isspace(UCHAR(*end))) {
+ end++;
+ }
+ if (*end != 0) {
+ goto error;
+ }
+ *doublePtr = d;
+ return TCL_OK;
+
+ error:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad distance \"%s\"", string));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "PS", "POINTS", NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkImageGetColor --
+ *
+ * This function converts a pixel value to three floating point numbers,
+ * representing the amount of red, green, and blue in that pixel on the
+ * screen. It makes use of colormap data passed as an argument, and
+ * should work for all Visual types.
+ *
+ * This implementation is bogus on Windows because the colormap data is
+ * never filled in. Instead all postscript generated data coming through
+ * here is expected to be RGB color data. To handle lower bit-depth
+ * images properly, XQueryColors must be implemented for Windows.
+ *
+ * Results:
+ * Returns red, green, and blue color values in the range 0 to 1. There
+ * are no error returns.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+#ifdef _WIN32
+#include <windows.h>
+
+/*
+ * We could just define these instead of pulling in windows.h.
+ #define GetRValue(rgb) ((BYTE)(rgb))
+ #define GetGValue(rgb) ((BYTE)(((WORD)(rgb)) >> 8))
+ #define GetBValue(rgb) ((BYTE)((rgb)>>16))
+ */
+
+#else /* !_WIN32 */
+
+#define GetRValue(rgb) ((rgb & cdata->red_mask) >> cdata->red_shift)
+#define GetGValue(rgb) ((rgb & cdata->green_mask) >> cdata->green_shift)
+#define GetBValue(rgb) ((rgb & cdata->blue_mask) >> cdata->blue_shift)
+
+#endif /* _WIN32 */
+
+#if defined(_WIN32) || defined(MAC_OSX_TK)
+static void
+TkImageGetColor(
+ TkColormapData *cdata, /* Colormap data */
+ unsigned long pixel, /* Pixel value to look up */
+ double *red, double *green, double *blue)
+ /* Color data to return */
+{
+ *red = (double) GetRValue(pixel) / 255.0;
+ *green = (double) GetGValue(pixel) / 255.0;
+ *blue = (double) GetBValue(pixel) / 255.0;
+}
+#else /* ! (_WIN32 || MAC_OSX_TK) */
+static void
+TkImageGetColor(
+ TkColormapData *cdata, /* Colormap data */
+ unsigned long pixel, /* Pixel value to look up */
+ double *red, double *green, double *blue)
+ /* Color data to return */
+{
+ if (cdata->separated) {
+ int r = GetRValue(pixel);
+ int g = GetGValue(pixel);
+ int b = GetBValue(pixel);
+
+ *red = cdata->colors[r].red / 65535.0;
+ *green = cdata->colors[g].green / 65535.0;
+ *blue = cdata->colors[b].blue / 65535.0;
+ } else {
+ *red = cdata->colors[pixel].red / 65535.0;
+ *green = cdata->colors[pixel].green / 65535.0;
+ *blue = cdata->colors[pixel].blue / 65535.0;
+ }
+}
+#endif /* _WIN32 || MAC_OSX_TK */
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkPostscriptImage --
+ *
+ * This function is called to output the contents of an image in
+ * Postscript, using a format appropriate for the current color mode
+ * (i.e. one bit per pixel in monochrome, one byte per pixel in gray, and
+ * three bytes per pixel in color).
+ *
+ * Results:
+ * Returns a standard Tcl return value. If an error occurs then an error
+ * message will be left in interp->result. If no error occurs, then
+ * additional Postscript will be appended to interp->result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkPostscriptImage(
+ Tcl_Interp *interp,
+ Tk_Window tkwin,
+ Tk_PostscriptInfo psInfo, /* postscript info */
+ XImage *ximage, /* Image to draw */
+ int x, int y, /* First pixel to output */
+ int width, int height) /* Width and height of area */
+{
+ TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo;
+ int xx, yy, band, maxRows;
+ double red, green, blue;
+ int bytesPerLine = 0, maxWidth = 0;
+ int level = psInfoPtr->colorLevel;
+ Colormap cmap;
+ int i, ncolors;
+ Visual *visual;
+ TkColormapData cdata;
+ Tcl_Obj *psObj;
+
+ if (psInfoPtr->prepass) {
+ return TCL_OK;
+ }
+
+ cmap = Tk_Colormap(tkwin);
+ visual = Tk_Visual(tkwin);
+
+ /*
+ * Obtain information about the colormap, ie the mapping between pixel
+ * values and RGB values. The code below should work for all Visual types.
+ */
+
+ ncolors = visual->map_entries;
+ cdata.colors = ckalloc(sizeof(XColor) * ncolors);
+ cdata.ncolors = ncolors;
+
+ if (visual->class == DirectColor || visual->class == TrueColor) {
+ cdata.separated = 1;
+ cdata.red_mask = visual->red_mask;
+ cdata.green_mask = visual->green_mask;
+ cdata.blue_mask = visual->blue_mask;
+ cdata.red_shift = 0;
+ cdata.green_shift = 0;
+ cdata.blue_shift = 0;
+
+ while ((0x0001 & (cdata.red_mask >> cdata.red_shift)) == 0) {
+ cdata.red_shift ++;
+ }
+ while ((0x0001 & (cdata.green_mask >> cdata.green_shift)) == 0) {
+ cdata.green_shift ++;
+ }
+ while ((0x0001 & (cdata.blue_mask >> cdata.blue_shift)) == 0) {
+ cdata.blue_shift ++;
+ }
+
+ for (i = 0; i < ncolors; i ++) {
+ cdata.colors[i].pixel =
+ ((i << cdata.red_shift) & cdata.red_mask) |
+ ((i << cdata.green_shift) & cdata.green_mask) |
+ ((i << cdata.blue_shift) & cdata.blue_mask);
+ }
+ } else {
+ cdata.separated=0;
+ for (i = 0; i < ncolors; i ++) {
+ cdata.colors[i].pixel = i;
+ }
+ }
+
+ if (visual->class == StaticGray || visual->class == GrayScale) {
+ cdata.color = 0;
+ } else {
+ cdata.color = 1;
+ }
+
+ XQueryColors(Tk_Display(tkwin), cmap, cdata.colors, ncolors);
+
+ /*
+ * Figure out which color level to use (possibly lower than the one
+ * specified by the user). For example, if the user specifies color with
+ * monochrome screen, use gray or monochrome mode instead.
+ */
+
+ if (!cdata.color && level >= 2) {
+ level = 1;
+ }
+
+ if (!cdata.color && cdata.ncolors == 2) {
+ level = 0;
+ }
+
+ /*
+ * Check that at least one row of the image can be represented with a
+ * string less than 64 KB long (this is a limit in the Postscript
+ * interpreter).
+ */
+
+ switch (level) {
+ case 0: bytesPerLine = (width + 7) / 8; maxWidth = 240000; break;
+ case 1: bytesPerLine = width; maxWidth = 60000; break;
+ default: bytesPerLine = 3 * width; maxWidth = 20000; break;
+ }
+
+ if (bytesPerLine > 60000) {
+ Tcl_ResetResult(interp);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't generate Postscript for images more than %d pixels wide",
+ maxWidth));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "PS", "MEMLIMIT", NULL);
+ ckfree(cdata.colors);
+ return TCL_ERROR;
+ }
+
+ maxRows = 60000 / bytesPerLine;
+ psObj = GetPostscriptBuffer(interp);
+
+ for (band = height-1; band >= 0; band -= maxRows) {
+ int rows = (band >= maxRows) ? maxRows : band + 1;
+ int lineLen = 0;
+
+ switch (level) {
+ case 0:
+ Tcl_AppendPrintfToObj(psObj, "%d %d 1 matrix {\n<", width, rows);
+ break;
+ case 1:
+ Tcl_AppendPrintfToObj(psObj, "%d %d 8 matrix {\n<", width, rows);
+ break;
+ default:
+ Tcl_AppendPrintfToObj(psObj, "%d %d 8 matrix {\n<", width, rows);
+ break;
+ }
+ for (yy = band; yy > band - rows; yy--) {
+ switch (level) {
+ case 0: {
+ /*
+ * Generate data for image in monochrome mode. No attempt at
+ * dithering is made--instead, just set a threshold.
+ */
+
+ unsigned char mask = 0x80;
+ unsigned char data = 0x00;
+
+ for (xx = x; xx< x+width; xx++) {
+ TkImageGetColor(&cdata, XGetPixel(ximage, xx, yy),
+ &red, &green, &blue);
+ if (0.30 * red + 0.59 * green + 0.11 * blue > 0.5) {
+ data |= mask;
+ }
+ mask >>= 1;
+ if (mask == 0) {
+ Tcl_AppendPrintfToObj(psObj, "%02X", data);
+ lineLen += 2;
+ if (lineLen > 60) {
+ lineLen = 0;
+ Tcl_AppendToObj(psObj, "\n", -1);
+ }
+ mask = 0x80;
+ data = 0x00;
+ }
+ }
+ if ((width % 8) != 0) {
+ Tcl_AppendPrintfToObj(psObj, "%02X", data);
+ mask = 0x80;
+ data = 0x00;
+ }
+ break;
+ }
+ case 1:
+ /*
+ * Generate data in gray mode; in this case, take a weighted
+ * sum of the red, green, and blue values.
+ */
+
+ for (xx = x; xx < x+width; xx ++) {
+ TkImageGetColor(&cdata, XGetPixel(ximage, xx, yy),
+ &red, &green, &blue);
+ Tcl_AppendPrintfToObj(psObj, "%02X",
+ (int) floor(0.5 + 255.0 *
+ (0.30 * red + 0.59 * green + 0.11 * blue)));
+ lineLen += 2;
+ if (lineLen > 60) {
+ lineLen = 0;
+ Tcl_AppendToObj(psObj, "\n", -1);
+ }
+ }
+ break;
+ default:
+ /*
+ * Finally, color mode. Here, just output the red, green, and
+ * blue values directly.
+ */
+
+ for (xx = x; xx < x+width; xx++) {
+ TkImageGetColor(&cdata, XGetPixel(ximage, xx, yy),
+ &red, &green, &blue);
+ Tcl_AppendPrintfToObj(psObj, "%02X%02X%02X",
+ (int) floor(0.5 + 255.0 * red),
+ (int) floor(0.5 + 255.0 * green),
+ (int) floor(0.5 + 255.0 * blue));
+ lineLen += 6;
+ if (lineLen > 60) {
+ lineLen = 0;
+ Tcl_AppendToObj(psObj, "\n", -1);
+ }
+ }
+ break;
+ }
+ }
+ switch (level) {
+ case 0: case 1:
+ Tcl_AppendToObj(psObj, ">\n} image\n", -1); break;
+ default:
+ Tcl_AppendToObj(psObj, ">\n} false 3 colorimage\n", -1); break;
+ }
+ Tcl_AppendPrintfToObj(psObj, "0 %d translate\n", rows);
+ }
+ ckfree(cdata.colors);
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_PostscriptPhoto --
+ *
+ * This function is called to output the contents of a photo image in
+ * Postscript, using a format appropriate for the requested postscript
+ * color mode (i.e. one byte per pixel in gray, and three bytes per pixel
+ * in color).
+ *
+ * Results:
+ * Returns a standard Tcl return value. If an error occurs then an error
+ * message will be left in interp->result. If no error occurs, then
+ * additional Postscript will be appended to the interpreter's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_PostscriptPhoto(
+ Tcl_Interp *interp,
+ Tk_PhotoImageBlock *blockPtr,
+ Tk_PostscriptInfo psInfo,
+ int width, int height)
+{
+ TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo;
+ int colorLevel = psInfoPtr->colorLevel;
+ const char *displayOperation, *decode;
+ unsigned char *pixelPtr;
+ int bpc, xx, yy, lineLen, alpha;
+ float red, green, blue;
+ int bytesPerLine = 0, maxWidth = 0;
+ unsigned char opaque = 255;
+ unsigned char *alphaPtr;
+ int alphaOffset, alphaPitch, alphaIncr;
+ Tcl_Obj *psObj;
+
+ if (psInfoPtr->prepass) {
+ return TCL_OK;
+ }
+
+ if (colorLevel != 0) {
+ /*
+ * Color and gray-scale code.
+ */
+
+ displayOperation = "TkPhotoColor";
+ } else {
+ /*
+ * Monochrome-only code
+ */
+
+ displayOperation = "TkPhotoMono";
+ }
+
+ /*
+ * Check that at least one row of the image can be represented with a
+ * string less than 64 KB long (this is a limit in the Postscript
+ * interpreter).
+ */
+
+ switch (colorLevel) {
+ case 0: bytesPerLine = (width + 7) / 8; maxWidth = 240000; break;
+ case 1: bytesPerLine = width; maxWidth = 60000; break;
+ default: bytesPerLine = 3 * width; maxWidth = 20000; break;
+ }
+ if (bytesPerLine > 60000) {
+ Tcl_ResetResult(interp);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't generate Postscript for images more than %d pixels wide",
+ maxWidth));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "PS", "MEMLIMIT", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Set up the postscript code except for the image-data stream.
+ */
+
+ psObj = GetPostscriptBuffer(interp);
+ switch (colorLevel) {
+ case 0:
+ Tcl_AppendToObj(psObj, "/DeviceGray setcolorspace\n\n", -1);
+ decode = "1 0";
+ bpc = 1;
+ break;
+ case 1:
+ Tcl_AppendToObj(psObj, "/DeviceGray setcolorspace\n\n", -1);
+ decode = "0 1";
+ bpc = 8;
+ break;
+ default:
+ Tcl_AppendToObj(psObj, "/DeviceRGB setcolorspace\n\n", -1);
+ decode = "0 1 0 1 0 1";
+ bpc = 8;
+ break;
+ }
+
+ Tcl_AppendPrintfToObj(psObj,
+ "<<\n /ImageType 1\n"
+ " /Width %d\n /Height %d\n /BitsPerComponent %d\n"
+ " /DataSource currentfile\n /ASCIIHexDecode filter\n"
+ " /ImageMatrix [1 0 0 -1 0 %d]\n /Decode [%s]\n>>\n"
+ "1 %s\n",
+ width, height, bpc, height, decode, displayOperation);
+
+ /*
+ * Check the PhotoImageBlock information. We assume that:
+ * if pixelSize is 1,2 or 4, the image is R,G,B,A;
+ * if pixelSize is 3, the image is R,G,B and offset[3] is bogus.
+ */
+
+ if (blockPtr->pixelSize == 3) {
+ /*
+ * No alpha information: the whole image is opaque.
+ */
+
+ alphaPtr = &opaque;
+ alphaPitch = alphaIncr = alphaOffset = 0;
+ } else {
+ /*
+ * Set up alpha handling.
+ */
+
+ alphaPtr = blockPtr->pixelPtr;
+ alphaPitch = blockPtr->pitch;
+ alphaIncr = blockPtr->pixelSize;
+ alphaOffset = blockPtr->offset[3];
+ }
+
+ for (yy = 0, lineLen=0; yy < height; yy++) {
+ switch (colorLevel) {
+ case 0: {
+ /*
+ * Generate data for image in monochrome mode. No attempt at
+ * dithering is made--instead, just set a threshold. To handle
+ * transparecies we need to output two lines: one for the black
+ * pixels, one for the white ones.
+ */
+
+ unsigned char mask = 0x80;
+ unsigned char data = 0x00;
+
+ for (xx = 0; xx< width; xx ++) {
+ pixelPtr = blockPtr->pixelPtr + (yy * blockPtr->pitch)
+ + (xx *blockPtr->pixelSize);
+
+ red = pixelPtr[blockPtr->offset[0]];
+ green = pixelPtr[blockPtr->offset[1]];
+ blue = pixelPtr[blockPtr->offset[2]];
+
+ alpha = *(alphaPtr + (yy * alphaPitch)
+ + (xx * alphaIncr) + alphaOffset);
+
+ /*
+ * If pixel is less than threshold, then it is black.
+ */
+
+ if ((alpha != 0) &&
+ (0.3086*red + 0.6094*green + 0.082*blue < 128)) {
+ data |= mask;
+ }
+ mask >>= 1;
+ if (mask == 0) {
+ Tcl_AppendPrintfToObj(psObj, "%02X", data);
+ lineLen += 2;
+ if (lineLen >= 60) {
+ lineLen = 0;
+ Tcl_AppendToObj(psObj, "\n", -1);
+ }
+ mask = 0x80;
+ data = 0x00;
+ }
+ }
+ if ((width % 8) != 0) {
+ Tcl_AppendPrintfToObj(psObj, "%02X", data);
+ mask = 0x80;
+ data = 0x00;
+ }
+
+ mask = 0x80;
+ data = 0x00;
+ for (xx=0 ; xx<width ; xx++) {
+ pixelPtr = blockPtr->pixelPtr + (yy * blockPtr->pitch)
+ + (xx *blockPtr->pixelSize);
+
+ red = pixelPtr[blockPtr->offset[0]];
+ green = pixelPtr[blockPtr->offset[1]];
+ blue = pixelPtr[blockPtr->offset[2]];
+
+ alpha = *(alphaPtr + (yy * alphaPitch)
+ + (xx * alphaIncr) + alphaOffset);
+
+ /*
+ * If pixel is greater than threshold, then it is white.
+ */
+
+ if ((alpha != 0) &&
+ (0.3086*red + 0.6094*green + 0.082*blue >= 128)) {
+ data |= mask;
+ }
+ mask >>= 1;
+ if (mask == 0) {
+ Tcl_AppendPrintfToObj(psObj, "%02X", data);
+ lineLen += 2;
+ if (lineLen >= 60) {
+ lineLen = 0;
+ Tcl_AppendToObj(psObj, "\n", -1);
+ }
+ mask = 0x80;
+ data = 0x00;
+ }
+ }
+ if ((width % 8) != 0) {
+ Tcl_AppendPrintfToObj(psObj, "%02X", data);
+ mask = 0x80;
+ data = 0x00;
+ }
+ break;
+ }
+ case 1: {
+ /*
+ * Generate transparency data. We must prevent a transparent value
+ * of 0 because of a bug in some HP printers.
+ */
+
+ for (xx = 0; xx < width; xx ++) {
+ alpha = *(alphaPtr + (yy * alphaPitch)
+ + (xx * alphaIncr) + alphaOffset);
+ Tcl_AppendPrintfToObj(psObj, "%02X", alpha | 0x01);
+ lineLen += 2;
+ if (lineLen >= 60) {
+ lineLen = 0;
+ Tcl_AppendToObj(psObj, "\n", -1);
+ }
+ }
+
+ /*
+ * Generate data in gray mode; in this case, take a weighted sum
+ * of the red, green, and blue values.
+ */
+
+ for (xx = 0; xx < width; xx ++) {
+ pixelPtr = blockPtr->pixelPtr + (yy * blockPtr->pitch)
+ + (xx *blockPtr->pixelSize);
+
+ red = pixelPtr[blockPtr->offset[0]];
+ green = pixelPtr[blockPtr->offset[1]];
+ blue = pixelPtr[blockPtr->offset[2]];
+
+ Tcl_AppendPrintfToObj(psObj, "%02X", (int) floor(0.5 +
+ ( 0.3086 * red + 0.6094 * green + 0.0820 * blue)));
+ lineLen += 2;
+ if (lineLen >= 60) {
+ lineLen = 0;
+ Tcl_AppendToObj(psObj, "\n", -1);
+ }
+ }
+ break;
+ }
+ default:
+ /*
+ * Generate transparency data. We must prevent a transparent value
+ * of 0 because of a bug in some HP printers.
+ */
+
+ for (xx = 0; xx < width; xx ++) {
+ alpha = *(alphaPtr + (yy * alphaPitch)
+ + (xx * alphaIncr) + alphaOffset);
+ Tcl_AppendPrintfToObj(psObj, "%02X", alpha | 0x01);
+ lineLen += 2;
+ if (lineLen >= 60) {
+ lineLen = 0;
+ Tcl_AppendToObj(psObj, "\n", -1);
+ }
+ }
+
+ /*
+ * Finally, color mode. Here, just output the red, green, and blue
+ * values directly.
+ */
+
+ for (xx = 0; xx < width; xx ++) {
+ pixelPtr = blockPtr->pixelPtr + (yy * blockPtr->pitch)
+ + (xx * blockPtr->pixelSize);
+
+ Tcl_AppendPrintfToObj(psObj, "%02X%02X%02X",
+ pixelPtr[blockPtr->offset[0]],
+ pixelPtr[blockPtr->offset[1]],
+ pixelPtr[blockPtr->offset[2]]);
+ lineLen += 6;
+ if (lineLen >= 60) {
+ lineLen = 0;
+ Tcl_AppendToObj(psObj, "\n", -1);
+ }
+ }
+ break;
+ }
+ }
+
+ /*
+ * The end-of-data marker.
+ */
+
+ Tcl_AppendToObj(psObj, ">\n", -1);
+ return TCL_OK;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkCanvText.c b/tk8.6/generic/tkCanvText.c
new file mode 100644
index 0000000..279e548
--- /dev/null
+++ b/tk8.6/generic/tkCanvText.c
@@ -0,0 +1,1660 @@
+/*
+ * tkCanvText.c --
+ *
+ * This file implements text items for canvas widgets.
+ *
+ * Copyright (c) 1991-1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "tkInt.h"
+#include "tkCanvas.h"
+#include "default.h"
+
+/*
+ * The structure below defines the record for each text item.
+ */
+
+typedef struct TextItem {
+ Tk_Item header; /* Generic stuff that's the same for all
+ * types. MUST BE FIRST IN STRUCTURE. */
+ Tk_CanvasTextInfo *textInfoPtr;
+ /* Pointer to a structure containing
+ * information about the selection and
+ * insertion cursor. The structure is owned by
+ * (and shared with) the generic canvas
+ * code. */
+ /*
+ * Fields that are set by widget commands other than "configure".
+ */
+
+ double x, y; /* Positioning point for text. */
+ int insertPos; /* Character index of character just before
+ * which the insertion cursor is displayed. */
+
+ /*
+ * Configuration settings that are updated by Tk_ConfigureWidget.
+ */
+
+ Tk_Anchor anchor; /* Where to anchor text relative to (x,y). */
+ Tk_TSOffset tsoffset;
+ XColor *color; /* Color for text. */
+ XColor *activeColor; /* Color for text. */
+ XColor *disabledColor; /* Color for text. */
+ Tk_Font tkfont; /* Font for drawing text. */
+ Tk_Justify justify; /* Justification mode for text. */
+ Pixmap stipple; /* Stipple bitmap for text, or None. */
+ Pixmap activeStipple; /* Stipple bitmap for text, or None. */
+ Pixmap disabledStipple; /* Stipple bitmap for text, or None. */
+ char *text; /* Text for item (malloc-ed). */
+ int width; /* Width of lines for word-wrap, pixels. Zero
+ * means no word-wrap. */
+ int underline; /* Index of character to put underline beneath
+ * or -1 for no underlining. */
+ double angle; /* What angle, in degrees, to draw the text
+ * at. */
+
+ /*
+ * Fields whose values are derived from the current values of the
+ * configuration settings above.
+ */
+
+ int numChars; /* Length of text in characters. */
+ int numBytes; /* Length of text in bytes. */
+ Tk_TextLayout textLayout; /* Cached text layout information. */
+ int actualWidth; /* Width of text as computed. Used to make
+ * selections of wrapped text display
+ * right. */
+ double drawOrigin[2]; /* Where we start drawing from. */
+ GC gc; /* Graphics context for drawing text. */
+ GC selTextGC; /* Graphics context for selected text. */
+ GC cursorOffGC; /* If not None, this gives a graphics context
+ * to use to draw the insertion cursor when
+ * it's off. Used if the selection and
+ * insertion cursor colors are the same. */
+ double sine; /* Sine of angle field. */
+ double cosine; /* Cosine of angle field. */
+} TextItem;
+
+/*
+ * Information used for parsing configuration specs:
+ */
+
+static const Tk_CustomOption stateOption = {
+ TkStateParseProc, TkStatePrintProc, INT2PTR(2)
+};
+static const Tk_CustomOption tagsOption = {
+ Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL
+};
+static const Tk_CustomOption offsetOption = {
+ TkOffsetParseProc, TkOffsetPrintProc, INT2PTR(TK_OFFSET_RELATIVE)
+};
+
+static const Tk_ConfigSpec configSpecs[] = {
+ {TK_CONFIG_COLOR, "-activefill", NULL, NULL,
+ NULL, Tk_Offset(TextItem, activeColor), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_BITMAP, "-activestipple", NULL, NULL,
+ NULL, Tk_Offset(TextItem, activeStipple), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_ANCHOR, "-anchor", NULL, NULL,
+ "center", Tk_Offset(TextItem, anchor), TK_CONFIG_DONT_SET_DEFAULT, NULL},
+ {TK_CONFIG_DOUBLE, "-angle", NULL, NULL,
+ "0.0", Tk_Offset(TextItem, angle), TK_CONFIG_DONT_SET_DEFAULT, NULL},
+ {TK_CONFIG_COLOR, "-disabledfill", NULL, NULL,
+ NULL, Tk_Offset(TextItem, disabledColor), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_BITMAP, "-disabledstipple", NULL, NULL,
+ NULL, Tk_Offset(TextItem, disabledStipple), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_COLOR, "-fill", NULL, NULL,
+ "black", Tk_Offset(TextItem, color), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_FONT, "-font", NULL, NULL,
+ DEF_CANVTEXT_FONT, Tk_Offset(TextItem, tkfont), 0, NULL},
+ {TK_CONFIG_JUSTIFY, "-justify", NULL, NULL,
+ "left", Tk_Offset(TextItem, justify), TK_CONFIG_DONT_SET_DEFAULT, NULL},
+ {TK_CONFIG_CUSTOM, "-offset", NULL, NULL,
+ "0,0", Tk_Offset(TextItem, tsoffset),
+ TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},
+ {TK_CONFIG_CUSTOM, "-state", NULL, NULL,
+ NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption},
+ {TK_CONFIG_BITMAP, "-stipple", NULL, NULL,
+ NULL, Tk_Offset(TextItem, stipple), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_CUSTOM, "-tags", NULL, NULL,
+ NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
+ {TK_CONFIG_STRING, "-text", NULL, NULL,
+ "", Tk_Offset(TextItem, text), 0, NULL},
+ {TK_CONFIG_INT, "-underline", NULL, NULL,
+ "-1", Tk_Offset(TextItem, underline), 0, NULL},
+ {TK_CONFIG_PIXELS, "-width", NULL, NULL,
+ "0", Tk_Offset(TextItem, width), TK_CONFIG_DONT_SET_DEFAULT, NULL},
+ {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}
+};
+
+/*
+ * Prototypes for functions defined in this file:
+ */
+
+static void ComputeTextBbox(Tk_Canvas canvas, TextItem *textPtr);
+static int ConfigureText(Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
+ Tcl_Obj *const objv[], int flags);
+static int CreateText(Tcl_Interp *interp,
+ Tk_Canvas canvas, struct Tk_Item *itemPtr,
+ int argc, Tcl_Obj *const objv[]);
+static void DeleteText(Tk_Canvas canvas,
+ Tk_Item *itemPtr, Display *display);
+static void DisplayCanvText(Tk_Canvas canvas,
+ Tk_Item *itemPtr, Display *display, Drawable dst,
+ int x, int y, int width, int height);
+static int GetSelText(Tk_Canvas canvas,
+ Tk_Item *itemPtr, int offset, char *buffer,
+ int maxBytes);
+static int GetTextIndex(Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr,
+ Tcl_Obj *obj, int *indexPtr);
+static void ScaleText(Tk_Canvas canvas,
+ Tk_Item *itemPtr, double originX, double originY,
+ double scaleX, double scaleY);
+static void SetTextCursor(Tk_Canvas canvas,
+ Tk_Item *itemPtr, int index);
+static int TextCoords(Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr,
+ int argc, Tcl_Obj *const objv[]);
+static void TextDeleteChars(Tk_Canvas canvas,
+ Tk_Item *itemPtr, int first, int last);
+static void TextInsert(Tk_Canvas canvas,
+ Tk_Item *itemPtr, int beforeThis, Tcl_Obj *obj);
+static int TextToArea(Tk_Canvas canvas,
+ Tk_Item *itemPtr, double *rectPtr);
+static double TextToPoint(Tk_Canvas canvas,
+ Tk_Item *itemPtr, double *pointPtr);
+static int TextToPostscript(Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr, int prepass);
+static void TranslateText(Tk_Canvas canvas,
+ Tk_Item *itemPtr, double deltaX, double deltaY);
+
+/*
+ * The structures below defines the rectangle and oval item types by means of
+ * functions that can be invoked by generic item code.
+ */
+
+Tk_ItemType tkTextType = {
+ "text", /* name */
+ sizeof(TextItem), /* itemSize */
+ CreateText, /* createProc */
+ configSpecs, /* configSpecs */
+ ConfigureText, /* configureProc */
+ TextCoords, /* coordProc */
+ DeleteText, /* deleteProc */
+ DisplayCanvText, /* displayProc */
+ TK_CONFIG_OBJS, /* flags */
+ TextToPoint, /* pointProc */
+ TextToArea, /* areaProc */
+ TextToPostscript, /* postscriptProc */
+ ScaleText, /* scaleProc */
+ TranslateText, /* translateProc */
+ GetTextIndex, /* indexProc */
+ SetTextCursor, /* icursorProc */
+ GetSelText, /* selectionProc */
+ TextInsert, /* insertProc */
+ TextDeleteChars, /* dTextProc */
+ NULL, /* nextPtr */
+ NULL, 0, NULL, NULL
+};
+
+#define ROUND(d) ((int) floor((d) + 0.5))
+
+/*
+ *--------------------------------------------------------------
+ *
+ * CreateText --
+ *
+ * This function is invoked to create a new text item in a canvas.
+ *
+ * Results:
+ * A standard Tcl return value. If an error occurred in creating the item
+ * then an error message is left in the interp's result; in this case
+ * itemPtr is left uninitialized so it can be safely freed by the caller.
+ *
+ * Side effects:
+ * A new text item is created.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+CreateText(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Tk_Canvas canvas, /* Canvas to hold new item. */
+ Tk_Item *itemPtr, /* Record to hold new item; header has been
+ * initialized by caller. */
+ int objc, /* Number of arguments in objv. */
+ Tcl_Obj *const objv[]) /* Arguments describing rectangle. */
+{
+ TextItem *textPtr = (TextItem *) itemPtr;
+ int i;
+
+ if (objc == 0) {
+ Tcl_Panic("canvas did not pass any coords");
+ }
+
+ /*
+ * Carry out initialization that is needed in order to clean up after
+ * errors during the the remainder of this function.
+ */
+
+ textPtr->textInfoPtr = Tk_CanvasGetTextInfo(canvas);
+
+ textPtr->insertPos = 0;
+
+ textPtr->anchor = TK_ANCHOR_CENTER;
+ textPtr->tsoffset.flags = 0;
+ textPtr->tsoffset.xoffset = 0;
+ textPtr->tsoffset.yoffset = 0;
+ textPtr->color = NULL;
+ textPtr->activeColor = NULL;
+ textPtr->disabledColor = NULL;
+ textPtr->tkfont = NULL;
+ textPtr->justify = TK_JUSTIFY_LEFT;
+ textPtr->stipple = None;
+ textPtr->activeStipple = None;
+ textPtr->disabledStipple = None;
+ textPtr->text = NULL;
+ textPtr->width = 0;
+ textPtr->underline = -1;
+ textPtr->angle = 0.0;
+
+ textPtr->numChars = 0;
+ textPtr->numBytes = 0;
+ textPtr->textLayout = NULL;
+ textPtr->actualWidth = 0;
+ textPtr->drawOrigin[0] = textPtr->drawOrigin[1] = 0.0;
+ textPtr->gc = NULL;
+ textPtr->selTextGC = NULL;
+ textPtr->cursorOffGC = NULL;
+ textPtr->sine = 0.0;
+ textPtr->cosine = 1.0;
+
+ /*
+ * Process the arguments to fill in the item record. Only 1 (list) or 2 (x
+ * y) coords are allowed.
+ */
+
+ if (objc == 1) {
+ i = 1;
+ } else {
+ const char *arg = Tcl_GetString(objv[1]);
+
+ i = 2;
+ if ((arg[0] == '-') && (arg[1] >= 'a') && (arg[1] <= 'z')) {
+ i = 1;
+ }
+ }
+ if ((TextCoords(interp, canvas, itemPtr, i, objv) != TCL_OK)) {
+ goto error;
+ }
+ if (ConfigureText(interp, canvas, itemPtr, objc-i, objv+i, 0) == TCL_OK) {
+ return TCL_OK;
+ }
+
+ error:
+ DeleteText(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TextCoords --
+ *
+ * This function is invoked to process the "coords" widget command on
+ * text items. See the user documentation for details on what it does.
+ *
+ * Results:
+ * Returns TCL_OK or TCL_ERROR, and sets the interp's result.
+ *
+ * Side effects:
+ * The coordinates for the given item may be changed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+TextCoords(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item whose coordinates are to be read or
+ * modified. */
+ int objc, /* Number of coordinates supplied in objv. */
+ Tcl_Obj *const objv[]) /* Array of coordinates: x1, y1, x2, y2, ... */
+{
+ TextItem *textPtr = (TextItem *) itemPtr;
+
+ if (objc == 0) {
+ Tcl_Obj *obj = Tcl_NewObj();
+ Tcl_Obj *subobj = Tcl_NewDoubleObj(textPtr->x);
+
+ Tcl_ListObjAppendElement(interp, obj, subobj);
+ subobj = Tcl_NewDoubleObj(textPtr->y);
+ Tcl_ListObjAppendElement(interp, obj, subobj);
+ Tcl_SetObjResult(interp, obj);
+ return TCL_OK;
+ } else if (objc > 2) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "wrong # coordinates: expected 0 or 2, got %d", objc));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "COORDS", "TEXT", NULL);
+ return TCL_ERROR;
+ }
+
+ if (objc == 1) {
+ if (Tcl_ListObjGetElements(interp, objv[0], &objc,
+ (Tcl_Obj ***) &objv) != TCL_OK) {
+ return TCL_ERROR;
+ } else if (objc != 2) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "wrong # coordinates: expected 2, got %d", objc));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "COORDS", "TEXT", NULL);
+ return TCL_ERROR;
+ }
+ }
+ if ((Tk_CanvasGetCoordFromObj(interp, canvas, objv[0],
+ &textPtr->x) != TCL_OK)
+ || (Tk_CanvasGetCoordFromObj(interp, canvas, objv[1],
+ &textPtr->y) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ ComputeTextBbox(canvas, textPtr);
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ConfigureText --
+ *
+ * This function is invoked to configure various aspects of a text item,
+ * such as its border and background colors.
+ *
+ * Results:
+ * A standard Tcl result code. If an error occurs, then an error message
+ * is left in the interp's result.
+ *
+ * Side effects:
+ * Configuration information, such as colors and stipple patterns, may be
+ * set for itemPtr.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+ConfigureText(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Tk_Canvas canvas, /* Canvas containing itemPtr. */
+ Tk_Item *itemPtr, /* Rectangle item to reconfigure. */
+ int objc, /* Number of elements in objv. */
+ Tcl_Obj *const objv[], /* Arguments describing things to configure. */
+ int flags) /* Flags to pass to Tk_ConfigureWidget. */
+{
+ TextItem *textPtr = (TextItem *) itemPtr;
+ XGCValues gcValues;
+ GC newGC, newSelGC;
+ unsigned long mask;
+ Tk_Window tkwin;
+ Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;
+ XColor *selBgColorPtr;
+ XColor *color;
+ Pixmap stipple;
+ Tk_State state;
+
+ tkwin = Tk_CanvasTkwin(canvas);
+ if (TCL_OK != Tk_ConfigureWidget(interp, tkwin, configSpecs, objc,
+ (const char **) objv, (char *) textPtr, flags|TK_CONFIG_OBJS)) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * A few of the options require additional processing, such as graphics
+ * contexts.
+ */
+
+ state = itemPtr->state;
+
+ if (textPtr->activeColor != NULL || textPtr->activeStipple != None) {
+ itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;
+ } else {
+ itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;
+ }
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+
+ color = textPtr->color;
+ stipple = textPtr->stipple;
+ if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (textPtr->activeColor != NULL) {
+ color = textPtr->activeColor;
+ }
+ if (textPtr->activeStipple != None) {
+ stipple = textPtr->activeStipple;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (textPtr->disabledColor != NULL) {
+ color = textPtr->disabledColor;
+ }
+ if (textPtr->disabledStipple != None) {
+ stipple = textPtr->disabledStipple;
+ }
+ }
+
+ newGC = newSelGC = NULL;
+ if (textPtr->tkfont != NULL) {
+ gcValues.font = Tk_FontId(textPtr->tkfont);
+ mask = GCFont;
+ if (color != NULL) {
+ gcValues.foreground = color->pixel;
+ mask |= GCForeground;
+ if (stipple != None) {
+ gcValues.stipple = stipple;
+ gcValues.fill_style = FillStippled;
+ mask |= GCStipple|GCFillStyle;
+ }
+ newGC = Tk_GetGC(tkwin, mask, &gcValues);
+ }
+ mask &= ~(GCTile|GCFillStyle|GCStipple);
+ if (stipple != None) {
+ gcValues.stipple = stipple;
+ gcValues.fill_style = FillStippled;
+ mask |= GCStipple|GCFillStyle;
+ }
+ if (textInfoPtr->selFgColorPtr != NULL) {
+ gcValues.foreground = textInfoPtr->selFgColorPtr->pixel;
+ }
+ newSelGC = Tk_GetGC(tkwin, mask|GCForeground, &gcValues);
+ }
+ if (textPtr->gc != NULL) {
+ Tk_FreeGC(Tk_Display(tkwin), textPtr->gc);
+ }
+ textPtr->gc = newGC;
+ if (textPtr->selTextGC != NULL) {
+ Tk_FreeGC(Tk_Display(tkwin), textPtr->selTextGC);
+ }
+ textPtr->selTextGC = newSelGC;
+
+ selBgColorPtr = Tk_3DBorderColor(textInfoPtr->selBorder);
+ if (Tk_3DBorderColor(textInfoPtr->insertBorder)->pixel
+ == selBgColorPtr->pixel) {
+ if (selBgColorPtr->pixel == BlackPixelOfScreen(Tk_Screen(tkwin))) {
+ gcValues.foreground = WhitePixelOfScreen(Tk_Screen(tkwin));
+ } else {
+ gcValues.foreground = BlackPixelOfScreen(Tk_Screen(tkwin));
+ }
+ newGC = Tk_GetGC(tkwin, GCForeground, &gcValues);
+ } else {
+ newGC = NULL;
+ }
+ if (textPtr->cursorOffGC != NULL) {
+ Tk_FreeGC(Tk_Display(tkwin), textPtr->cursorOffGC);
+ }
+ textPtr->cursorOffGC = newGC;
+
+ /*
+ * If the text was changed, move the selection and insertion indices to
+ * keep them inside the item.
+ */
+
+ textPtr->numBytes = strlen(textPtr->text);
+ textPtr->numChars = Tcl_NumUtfChars(textPtr->text, textPtr->numBytes);
+ if (textInfoPtr->selItemPtr == itemPtr) {
+
+ if (textInfoPtr->selectFirst >= textPtr->numChars) {
+ textInfoPtr->selItemPtr = NULL;
+ } else {
+ if (textInfoPtr->selectLast >= textPtr->numChars) {
+ textInfoPtr->selectLast = textPtr->numChars - 1;
+ }
+ if ((textInfoPtr->anchorItemPtr == itemPtr)
+ && (textInfoPtr->selectAnchor >= textPtr->numChars)) {
+ textInfoPtr->selectAnchor = textPtr->numChars - 1;
+ }
+ }
+ }
+ if (textPtr->insertPos >= textPtr->numChars) {
+ textPtr->insertPos = textPtr->numChars;
+ }
+
+ /*
+ * Restrict so that 0.0 <= angle < 360.0, and then recompute the cached
+ * sine and cosine of the angle. Note that fmod() can produce negative
+ * results, and we try to avoid negative zero as well.
+ */
+
+ textPtr->angle = fmod(textPtr->angle, 360.0);
+ if (textPtr->angle < 0.0) {
+ textPtr->angle += 360.0;
+ }
+ if (textPtr->angle == 0.0) {
+ textPtr->angle = 0.0;
+ }
+ textPtr->sine = sin(textPtr->angle * PI/180.0);
+ textPtr->cosine = cos(textPtr->angle * PI/180.0);
+
+ ComputeTextBbox(canvas, textPtr);
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DeleteText --
+ *
+ * This function is called to clean up the data structure associated with
+ * a text item.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Resources associated with itemPtr are released.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+DeleteText(
+ Tk_Canvas canvas, /* Info about overall canvas widget. */
+ Tk_Item *itemPtr, /* Item that is being deleted. */
+ Display *display) /* Display containing window for canvas. */
+{
+ TextItem *textPtr = (TextItem *) itemPtr;
+
+ if (textPtr->color != NULL) {
+ Tk_FreeColor(textPtr->color);
+ }
+ if (textPtr->activeColor != NULL) {
+ Tk_FreeColor(textPtr->activeColor);
+ }
+ if (textPtr->disabledColor != NULL) {
+ Tk_FreeColor(textPtr->disabledColor);
+ }
+ Tk_FreeFont(textPtr->tkfont);
+ if (textPtr->stipple != None) {
+ Tk_FreeBitmap(display, textPtr->stipple);
+ }
+ if (textPtr->activeStipple != None) {
+ Tk_FreeBitmap(display, textPtr->activeStipple);
+ }
+ if (textPtr->disabledStipple != None) {
+ Tk_FreeBitmap(display, textPtr->disabledStipple);
+ }
+ if (textPtr->text != NULL) {
+ ckfree(textPtr->text);
+ }
+
+ Tk_FreeTextLayout(textPtr->textLayout);
+ if (textPtr->gc != NULL) {
+ Tk_FreeGC(display, textPtr->gc);
+ }
+ if (textPtr->selTextGC != NULL) {
+ Tk_FreeGC(display, textPtr->selTextGC);
+ }
+ if (textPtr->cursorOffGC != NULL) {
+ Tk_FreeGC(display, textPtr->cursorOffGC);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ComputeTextBbox --
+ *
+ * This function is invoked to compute the bounding box of all the pixels
+ * that may be drawn as part of a text item. In addition, it recomputes
+ * all of the geometry information used to display a text item or check
+ * for mouse hits.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The fields x1, y1, x2, and y2 are updated in the header for itemPtr,
+ * and the linePtr structure is regenerated for itemPtr.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ComputeTextBbox(
+ Tk_Canvas canvas, /* Canvas that contains item. */
+ TextItem *textPtr) /* Item whose bbox is to be recomputed. */
+{
+ Tk_CanvasTextInfo *textInfoPtr;
+ int leftX, topY, width, height, fudge, i;
+ Tk_State state = textPtr->header.state;
+ double x[4], y[4], dx[4], dy[4], sinA, cosA, tmp;
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+
+ Tk_FreeTextLayout(textPtr->textLayout);
+ textPtr->textLayout = Tk_ComputeTextLayout(textPtr->tkfont,
+ textPtr->text, textPtr->numChars, textPtr->width,
+ textPtr->justify, 0, &width, &height);
+
+ if (state == TK_STATE_HIDDEN || textPtr->color == NULL) {
+ width = height = 0;
+ }
+
+ /*
+ * Use overall geometry information to compute the top-left corner of the
+ * bounding box for the text item.
+ */
+
+ leftX = ROUND(textPtr->x);
+ topY = ROUND(textPtr->y);
+ for (i=0 ; i<4 ; i++) {
+ dx[i] = dy[i] = 0.0;
+ }
+ switch (textPtr->anchor) {
+ case TK_ANCHOR_NW:
+ case TK_ANCHOR_N:
+ case TK_ANCHOR_NE:
+ break;
+
+ case TK_ANCHOR_W:
+ case TK_ANCHOR_CENTER:
+ case TK_ANCHOR_E:
+ topY -= height / 2;
+ for (i=0 ; i<4 ; i++) {
+ dy[i] = -height / 2;
+ }
+ break;
+
+ case TK_ANCHOR_SW:
+ case TK_ANCHOR_S:
+ case TK_ANCHOR_SE:
+ topY -= height;
+ for (i=0 ; i<4 ; i++) {
+ dy[i] = -height;
+ }
+ break;
+ }
+ switch (textPtr->anchor) {
+ case TK_ANCHOR_NW:
+ case TK_ANCHOR_W:
+ case TK_ANCHOR_SW:
+ break;
+
+ case TK_ANCHOR_N:
+ case TK_ANCHOR_CENTER:
+ case TK_ANCHOR_S:
+ leftX -= width / 2;
+ for (i=0 ; i<4 ; i++) {
+ dx[i] = -width / 2;
+ }
+ break;
+
+ case TK_ANCHOR_NE:
+ case TK_ANCHOR_E:
+ case TK_ANCHOR_SE:
+ leftX -= width;
+ for (i=0 ; i<4 ; i++) {
+ dx[i] = -width;
+ }
+ break;
+ }
+
+ textPtr->actualWidth = width;
+
+ sinA = textPtr->sine;
+ cosA = textPtr->cosine;
+ textPtr->drawOrigin[0] = textPtr->x + dx[0]*cosA + dy[0]*sinA;
+ textPtr->drawOrigin[1] = textPtr->y + dy[0]*cosA - dx[0]*sinA;
+
+ /*
+ * Last of all, update the bounding box for the item. The item's bounding
+ * box includes the bounding box of all its lines, plus an extra fudge
+ * factor for the cursor border (which could potentially be quite large).
+ */
+
+ textInfoPtr = textPtr->textInfoPtr;
+ fudge = (textInfoPtr->insertWidth + 1) / 2;
+ if (textInfoPtr->selBorderWidth > fudge) {
+ fudge = textInfoPtr->selBorderWidth;
+ }
+
+ /*
+ * Apply the rotation before computing the bounding box.
+ */
+
+ dx[0] -= fudge;
+ dx[1] += width + fudge;
+ dx[2] += width + fudge;
+ dy[2] += height;
+ dx[3] -= fudge;
+ dy[3] += height;
+ for (i=0 ; i<4 ; i++) {
+ x[i] = textPtr->x + dx[i] * cosA + dy[i] * sinA;
+ y[i] = textPtr->y + dy[i] * cosA - dx[i] * sinA;
+ }
+
+ /*
+ * Convert to a rectilinear bounding box.
+ */
+
+ for (i=1,tmp=x[0] ; i<4 ; i++) {
+ if (x[i] < tmp) {
+ tmp = x[i];
+ }
+ }
+ textPtr->header.x1 = ROUND(tmp);
+ for (i=1,tmp=y[0] ; i<4 ; i++) {
+ if (y[i] < tmp) {
+ tmp = y[i];
+ }
+ }
+ textPtr->header.y1 = ROUND(tmp);
+ for (i=1,tmp=x[0] ; i<4 ; i++) {
+ if (x[i] > tmp) {
+ tmp = x[i];
+ }
+ }
+ textPtr->header.x2 = ROUND(tmp);
+ for (i=1,tmp=y[0] ; i<4 ; i++) {
+ if (y[i] > tmp) {
+ tmp = y[i];
+ }
+ }
+ textPtr->header.y2 = ROUND(tmp);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DisplayCanvText --
+ *
+ * This function is invoked to draw a text item in a given drawable.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * ItemPtr is drawn in drawable using the transformation information in
+ * canvas.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+DisplayCanvText(
+ Tk_Canvas canvas, /* Canvas that contains item. */
+ Tk_Item *itemPtr, /* Item to be displayed. */
+ Display *display, /* Display on which to draw item. */
+ Drawable drawable, /* Pixmap or window in which to draw item. */
+ int x, int y, int width, int height)
+ /* Describes region of canvas that must be
+ * redisplayed (not used). */
+{
+ TextItem *textPtr;
+ Tk_CanvasTextInfo *textInfoPtr;
+ int selFirstChar, selLastChar;
+ short drawableX, drawableY;
+ Pixmap stipple;
+ Tk_State state = itemPtr->state;
+
+ textPtr = (TextItem *) itemPtr;
+ textInfoPtr = textPtr->textInfoPtr;
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+ stipple = textPtr->stipple;
+ if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (textPtr->activeStipple != None) {
+ stipple = textPtr->activeStipple;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (textPtr->disabledStipple != None) {
+ stipple = textPtr->disabledStipple;
+ }
+ }
+
+ if (textPtr->gc == NULL) {
+ return;
+ }
+
+ /*
+ * If we're stippling, then modify the stipple offset in the GC. Be sure
+ * to reset the offset when done, since the GC is supposed to be
+ * read-only.
+ */
+
+ if (stipple != None) {
+ Tk_CanvasSetOffset(canvas, textPtr->gc, &textPtr->tsoffset);
+ }
+
+ selFirstChar = -1;
+ selLastChar = 0; /* lint. */
+ Tk_CanvasDrawableCoords(canvas, textPtr->drawOrigin[0],
+ textPtr->drawOrigin[1], &drawableX, &drawableY);
+
+ if (textInfoPtr->selItemPtr == itemPtr) {
+ selFirstChar = textInfoPtr->selectFirst;
+ selLastChar = textInfoPtr->selectLast;
+ if (selLastChar > textPtr->numChars) {
+ selLastChar = textPtr->numChars - 1;
+ }
+ if ((selFirstChar >= 0) && (selFirstChar <= selLastChar)) {
+ int xFirst, yFirst, hFirst;
+ int xLast, yLast, wLast;
+
+ /*
+ * Draw a special background under the selection.
+ */
+
+ Tk_CharBbox(textPtr->textLayout, selFirstChar, &xFirst, &yFirst,
+ NULL, &hFirst);
+ Tk_CharBbox(textPtr->textLayout, selLastChar, &xLast, &yLast,
+ &wLast, NULL);
+
+ /*
+ * If the selection spans the end of this line, then display
+ * selection background all the way to the end of the line.
+ * However, for the last line we only want to display up to the
+ * last character, not the end of the line.
+ */
+
+ x = xFirst;
+ height = hFirst;
+ for (y = yFirst ; y <= yLast; y += height) {
+ int dx1, dy1, dx2, dy2;
+ double s = textPtr->sine, c = textPtr->cosine;
+ XPoint points[4];
+
+ if (y == yLast) {
+ width = xLast + wLast - x;
+ } else {
+ width = textPtr->actualWidth - x;
+ }
+ dx1 = x - textInfoPtr->selBorderWidth;
+ dy1 = y;
+ dx2 = width + 2 * textInfoPtr->selBorderWidth;
+ dy2 = height;
+ points[0].x = (short)(drawableX + dx1*c + dy1*s);
+ points[0].y = (short)(drawableY + dy1*c - dx1*s);
+ points[1].x = (short)(drawableX + (dx1+dx2)*c + dy1*s);
+ points[1].y = (short)(drawableY + dy1*c - (dx1+dx2)*s);
+ points[2].x = (short)(drawableX + (dx1+dx2)*c + (dy1+dy2)*s);
+ points[2].y = (short)(drawableY + (dy1+dy2)*c - (dx1+dx2)*s);
+ points[3].x = (short)(drawableX + dx1*c + (dy1+dy2)*s);
+ points[3].y = (short)(drawableY + (dy1+dy2)*c - dx1*s);
+ Tk_Fill3DPolygon(Tk_CanvasTkwin(canvas), drawable,
+ textInfoPtr->selBorder, points, 4,
+ textInfoPtr->selBorderWidth, TK_RELIEF_RAISED);
+ x = 0;
+ }
+ }
+ }
+
+ /*
+ * If the insertion point should be displayed, then draw a special
+ * background for the cursor before drawing the text. Note: if we're the
+ * cursor item but the cursor is turned off, then redraw background over
+ * the area of the cursor. This guarantees that the selection won't make
+ * the cursor invisible on mono displays, where both are drawn in the same
+ * color.
+ */
+
+ if ((textInfoPtr->focusItemPtr == itemPtr) && (textInfoPtr->gotFocus)) {
+ if (Tk_CharBbox(textPtr->textLayout, textPtr->insertPos,
+ &x, &y, NULL, &height)) {
+ int dx1, dy1, dx2, dy2;
+ double s = textPtr->sine, c = textPtr->cosine;
+ XPoint points[4];
+
+ dx1 = x - (textInfoPtr->insertWidth / 2);
+ dy1 = y;
+ dx2 = textInfoPtr->insertWidth;
+ dy2 = height;
+ points[0].x = (short)(drawableX + dx1*c + dy1*s);
+ points[0].y = (short)(drawableY + dy1*c - dx1*s);
+ points[1].x = (short)(drawableX + (dx1+dx2)*c + dy1*s);
+ points[1].y = (short)(drawableY + dy1*c - (dx1+dx2)*s);
+ points[2].x = (short)(drawableX + (dx1+dx2)*c + (dy1+dy2)*s);
+ points[2].y = (short)(drawableY + (dy1+dy2)*c - (dx1+dx2)*s);
+ points[3].x = (short)(drawableX + dx1*c + (dy1+dy2)*s);
+ points[3].y = (short)(drawableY + (dy1+dy2)*c - dx1*s);
+
+ Tk_SetCaretPos(Tk_CanvasTkwin(canvas), points[0].x, points[0].y,
+ height);
+ if (textInfoPtr->cursorOn) {
+ Tk_Fill3DPolygon(Tk_CanvasTkwin(canvas), drawable,
+ textInfoPtr->insertBorder, points, 4,
+ textInfoPtr->insertBorderWidth, TK_RELIEF_RAISED);
+ } else if (textPtr->cursorOffGC != NULL) {
+ /*
+ * Redraw the background over the area of the cursor, even
+ * though the cursor is turned off. This guarantees that the
+ * selection won't make the cursor invisible on mono displays,
+ * where both may be drawn in the same color.
+ */
+
+ XFillPolygon(display, drawable, textPtr->cursorOffGC,
+ points, 4, Convex, CoordModeOrigin);
+ }
+ }
+ }
+
+ /*
+ * If there is no selected text or the selected text foreground is the
+ * same as the regular text foreground, then draw one text string. If
+ * there is selected text and the foregrounds differ, draw the regular
+ * text up to the selection, draw the selection, then draw the rest of the
+ * regular text. Drawing the regular text and then the selected text over
+ * it would causes problems with anti-aliased text because the two
+ * anti-aliasing colors would blend together.
+ */
+
+ if ((selFirstChar >= 0) && (textPtr->selTextGC != textPtr->gc)) {
+ TkDrawAngledTextLayout(display, drawable, textPtr->gc,
+ textPtr->textLayout, drawableX, drawableY, textPtr->angle,
+ 0, selFirstChar);
+ TkDrawAngledTextLayout(display, drawable, textPtr->selTextGC,
+ textPtr->textLayout, drawableX, drawableY, textPtr->angle,
+ selFirstChar, selLastChar + 1);
+ TkDrawAngledTextLayout(display, drawable, textPtr->gc,
+ textPtr->textLayout, drawableX, drawableY, textPtr->angle,
+ selLastChar + 1, -1);
+ } else {
+ TkDrawAngledTextLayout(display, drawable, textPtr->gc,
+ textPtr->textLayout, drawableX, drawableY, textPtr->angle,
+ 0, -1);
+ }
+ TkUnderlineAngledTextLayout(display, drawable, textPtr->gc,
+ textPtr->textLayout, drawableX, drawableY, textPtr->angle,
+ textPtr->underline);
+
+ if (stipple != None) {
+ XSetTSOrigin(display, textPtr->gc, 0, 0);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TextInsert --
+ *
+ * Insert characters into a text item at a given position.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The text in the given item is modified. The cursor and selection
+ * positions are also modified to reflect the insertion.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+TextInsert(
+ Tk_Canvas canvas, /* Canvas containing text item. */
+ Tk_Item *itemPtr, /* Text item to be modified. */
+ int index, /* Character index before which string is to
+ * be inserted. */
+ Tcl_Obj *obj) /* New characters to be inserted. */
+{
+ TextItem *textPtr = (TextItem *) itemPtr;
+ int byteIndex, byteCount, charsAdded;
+ char *newStr, *text;
+ const char *string;
+ Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;
+
+ string = Tcl_GetStringFromObj(obj, &byteCount);
+
+ text = textPtr->text;
+
+ if (index < 0) {
+ index = 0;
+ }
+ if (index > textPtr->numChars) {
+ index = textPtr->numChars;
+ }
+ byteIndex = Tcl_UtfAtIndex(text, index) - text;
+ byteCount = strlen(string);
+ if (byteCount == 0) {
+ return;
+ }
+
+ newStr = ckalloc(textPtr->numBytes + byteCount + 1);
+ memcpy(newStr, text, (size_t) byteIndex);
+ strcpy(newStr + byteIndex, string);
+ strcpy(newStr + byteIndex + byteCount, text + byteIndex);
+
+ ckfree(text);
+ textPtr->text = newStr;
+ charsAdded = Tcl_NumUtfChars(string, byteCount);
+ textPtr->numChars += charsAdded;
+ textPtr->numBytes += byteCount;
+
+ /*
+ * Inserting characters invalidates indices such as those for the
+ * selection and cursor. Update the indices appropriately.
+ */
+
+ if (textInfoPtr->selItemPtr == itemPtr) {
+ if (textInfoPtr->selectFirst >= index) {
+ textInfoPtr->selectFirst += charsAdded;
+ }
+ if (textInfoPtr->selectLast >= index) {
+ textInfoPtr->selectLast += charsAdded;
+ }
+ if ((textInfoPtr->anchorItemPtr == itemPtr)
+ && (textInfoPtr->selectAnchor >= index)) {
+ textInfoPtr->selectAnchor += charsAdded;
+ }
+ }
+ if (textPtr->insertPos >= index) {
+ textPtr->insertPos += charsAdded;
+ }
+ ComputeTextBbox(canvas, textPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TextDeleteChars --
+ *
+ * Delete one or more characters from a text item.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Characters between "first" and "last", inclusive, get deleted from
+ * itemPtr, and things like the selection position get updated.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+TextDeleteChars(
+ Tk_Canvas canvas, /* Canvas containing itemPtr. */
+ Tk_Item *itemPtr, /* Item in which to delete characters. */
+ int first, /* Character index of first character to
+ * delete. */
+ int last) /* Character index of last character to delete
+ * (inclusive). */
+{
+ TextItem *textPtr = (TextItem *) itemPtr;
+ int byteIndex, byteCount, charsRemoved;
+ char *newStr, *text;
+ Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;
+
+ text = textPtr->text;
+ if (first < 0) {
+ first = 0;
+ }
+ if (last >= textPtr->numChars) {
+ last = textPtr->numChars - 1;
+ }
+ if (first > last) {
+ return;
+ }
+ charsRemoved = last + 1 - first;
+
+ byteIndex = Tcl_UtfAtIndex(text, first) - text;
+ byteCount = Tcl_UtfAtIndex(text + byteIndex, charsRemoved)
+ - (text + byteIndex);
+
+ newStr = ckalloc(textPtr->numBytes + 1 - byteCount);
+ memcpy(newStr, text, (size_t) byteIndex);
+ strcpy(newStr + byteIndex, text + byteIndex + byteCount);
+
+ ckfree(text);
+ textPtr->text = newStr;
+ textPtr->numChars -= charsRemoved;
+ textPtr->numBytes -= byteCount;
+
+ /*
+ * Update indexes for the selection and cursor to reflect the renumbering
+ * of the remaining characters.
+ */
+
+ if (textInfoPtr->selItemPtr == itemPtr) {
+ if (textInfoPtr->selectFirst > first) {
+ textInfoPtr->selectFirst -= charsRemoved;
+ if (textInfoPtr->selectFirst < first) {
+ textInfoPtr->selectFirst = first;
+ }
+ }
+ if (textInfoPtr->selectLast >= first) {
+ textInfoPtr->selectLast -= charsRemoved;
+ if (textInfoPtr->selectLast < first - 1) {
+ textInfoPtr->selectLast = first - 1;
+ }
+ }
+ if (textInfoPtr->selectFirst > textInfoPtr->selectLast) {
+ textInfoPtr->selItemPtr = NULL;
+ }
+ if ((textInfoPtr->anchorItemPtr == itemPtr)
+ && (textInfoPtr->selectAnchor > first)) {
+ textInfoPtr->selectAnchor -= charsRemoved;
+ if (textInfoPtr->selectAnchor < first) {
+ textInfoPtr->selectAnchor = first;
+ }
+ }
+ }
+ if (textPtr->insertPos > first) {
+ textPtr->insertPos -= charsRemoved;
+ if (textPtr->insertPos < first) {
+ textPtr->insertPos = first;
+ }
+ }
+ ComputeTextBbox(canvas, textPtr);
+ return;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TextToPoint --
+ *
+ * Computes the distance from a given point to a given text item, in
+ * canvas units.
+ *
+ * Results:
+ * The return value is 0 if the point whose x and y coordinates are
+ * pointPtr[0] and pointPtr[1] is inside the text item. If the point
+ * isn't inside the text item then the return value is the distance from
+ * the point to the text item.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static double
+TextToPoint(
+ Tk_Canvas canvas, /* Canvas containing itemPtr. */
+ Tk_Item *itemPtr, /* Item to check against point. */
+ double *pointPtr) /* Pointer to x and y coordinates. */
+{
+ TextItem *textPtr;
+ Tk_State state = itemPtr->state;
+ double value, px, py;
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+ textPtr = (TextItem *) itemPtr;
+ px = pointPtr[0] - textPtr->drawOrigin[0];
+ py = pointPtr[1] - textPtr->drawOrigin[1];
+ value = (double) Tk_DistanceToTextLayout(textPtr->textLayout,
+ (int) (px*textPtr->cosine - py*textPtr->sine),
+ (int) (py*textPtr->cosine + px*textPtr->sine));
+
+ if ((state == TK_STATE_HIDDEN) || (textPtr->color == NULL) ||
+ (textPtr->text == NULL) || (*textPtr->text == 0)) {
+ value = 1.0e36;
+ }
+ return value;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TextToArea --
+ *
+ * This function is called to determine whether an item lies entirely
+ * inside, entirely outside, or overlapping a given rectangle.
+ *
+ * Results:
+ * -1 is returned if the item is entirely outside the area given by
+ * rectPtr, 0 if it overlaps, and 1 if it is entirely inside the given
+ * area.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+TextToArea(
+ Tk_Canvas canvas, /* Canvas containing itemPtr. */
+ Tk_Item *itemPtr, /* Item to check against rectangle. */
+ double *rectPtr) /* Pointer to array of four coordinates
+ * (x1,y1,x2,y2) describing rectangular
+ * area. */
+{
+ TextItem *textPtr;
+ Tk_State state = itemPtr->state;
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+
+ textPtr = (TextItem *) itemPtr;
+ return TkIntersectAngledTextLayout(textPtr->textLayout,
+ (int) ((rectPtr[0] + 0.5) - textPtr->drawOrigin[0]),
+ (int) ((rectPtr[1] + 0.5) - textPtr->drawOrigin[1]),
+ (int) (rectPtr[2] - rectPtr[0] + 0.5),
+ (int) (rectPtr[3] - rectPtr[1] + 0.5),
+ textPtr->angle);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ScaleText --
+ *
+ * This function is invoked to rescale a text item.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Scales the position of the text, but not the size of the font for the
+ * text.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static void
+ScaleText(
+ Tk_Canvas canvas, /* Canvas containing rectangle. */
+ Tk_Item *itemPtr, /* Rectangle to be scaled. */
+ double originX, double originY,
+ /* Origin about which to scale rect. */
+ double scaleX, /* Amount to scale in X direction. */
+ double scaleY) /* Amount to scale in Y direction. */
+{
+ TextItem *textPtr = (TextItem *) itemPtr;
+
+ textPtr->x = originX + scaleX*(textPtr->x - originX);
+ textPtr->y = originY + scaleY*(textPtr->y - originY);
+ ComputeTextBbox(canvas, textPtr);
+ return;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TranslateText --
+ *
+ * This function is called to move a text item by a given amount.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The position of the text item is offset by (xDelta, yDelta), and the
+ * bounding box is updated in the generic part of the item structure.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+TranslateText(
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item that is being moved. */
+ double deltaX, double deltaY)
+ /* Amount by which item is to be moved. */
+{
+ TextItem *textPtr = (TextItem *) itemPtr;
+
+ textPtr->x += deltaX;
+ textPtr->y += deltaY;
+ ComputeTextBbox(canvas, textPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * GetTextIndex --
+ *
+ * Parse an index into a text item and return either its value or an
+ * error.
+ *
+ * Results:
+ * A standard Tcl result. If all went well, then *indexPtr is filled in
+ * with the index (into itemPtr) corresponding to string. Otherwise an
+ * error message is left in the interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+GetTextIndex(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item for which the index is being
+ * specified. */
+ Tcl_Obj *obj, /* Specification of a particular character in
+ * itemPtr's text. */
+ int *indexPtr) /* Where to store converted character
+ * index. */
+{
+ TextItem *textPtr = (TextItem *) itemPtr;
+ int length;
+ int c;
+ TkCanvas *canvasPtr = (TkCanvas *) canvas;
+ Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;
+ const char *string = Tcl_GetStringFromObj(obj, &length);
+
+ c = string[0];
+
+ if ((c == 'e') && (strncmp(string, "end", (unsigned) length) == 0)) {
+ *indexPtr = textPtr->numChars;
+ } else if ((c == 'i')
+ && (strncmp(string, "insert", (unsigned) length) == 0)) {
+ *indexPtr = textPtr->insertPos;
+ } else if ((c == 's') && (length >= 5)
+ && (strncmp(string, "sel.first", (unsigned) length) == 0)) {
+ if (textInfoPtr->selItemPtr != itemPtr) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "selection isn't in item", -1));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "UNSELECTED", NULL);
+ return TCL_ERROR;
+ }
+ *indexPtr = textInfoPtr->selectFirst;
+ } else if ((c == 's') && (length >= 5)
+ && (strncmp(string, "sel.last", (unsigned) length) == 0)) {
+ if (textInfoPtr->selItemPtr != itemPtr) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "selection isn't in item", -1));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "UNSELECTED", NULL);
+ return TCL_ERROR;
+ }
+ *indexPtr = textInfoPtr->selectLast;
+ } else if (c == '@') {
+ int x, y;
+ double tmp, c = textPtr->cosine, s = textPtr->sine;
+ char *end;
+ const char *p;
+
+ p = string+1;
+ tmp = strtod(p, &end);
+ if ((end == p) || (*end != ',')) {
+ goto badIndex;
+ }
+ x = (int) ((tmp < 0) ? tmp - 0.5 : tmp + 0.5);
+ p = end+1;
+ tmp = strtod(p, &end);
+ if ((end == p) || (*end != 0)) {
+ goto badIndex;
+ }
+ y = (int) ((tmp < 0) ? tmp - 0.5 : tmp + 0.5);
+ x += canvasPtr->scrollX1 - (int) textPtr->drawOrigin[0];
+ y += canvasPtr->scrollY1 - (int) textPtr->drawOrigin[1];
+ *indexPtr = Tk_PointToChar(textPtr->textLayout,
+ (int) (x*c - y*s), (int) (y*c + x*s));
+ } else if (Tcl_GetIntFromObj(NULL, obj, indexPtr) == TCL_OK) {
+ if (*indexPtr < 0) {
+ *indexPtr = 0;
+ } else if (*indexPtr > textPtr->numChars) {
+ *indexPtr = textPtr->numChars;
+ }
+ } else {
+ /*
+ * Some of the paths here leave messages in the interp's result, so we
+ * have to clear it out before storing our own message.
+ */
+
+ badIndex:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad index \"%s\"", string));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "ITEM_INDEX", "TEXT", NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * SetTextCursor --
+ *
+ * Set the position of the insertion cursor in this item.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The cursor position will change.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static void
+SetTextCursor(
+ Tk_Canvas canvas, /* Record describing canvas widget. */
+ Tk_Item *itemPtr, /* Text item in which cursor position is to be
+ * set. */
+ int index) /* Character index of character just before
+ * which cursor is to be positioned. */
+{
+ TextItem *textPtr = (TextItem *) itemPtr;
+
+ if (index < 0) {
+ textPtr->insertPos = 0;
+ } else if (index > textPtr->numChars) {
+ textPtr->insertPos = textPtr->numChars;
+ } else {
+ textPtr->insertPos = index;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * GetSelText --
+ *
+ * This function is invoked to return the selected portion of a text
+ * item. It is only called when this item has the selection.
+ *
+ * Results:
+ * The return value is the number of non-NULL bytes stored at buffer.
+ * Buffer is filled (or partially filled) with a NULL-terminated string
+ * containing part or all of the selection, as given by offset and
+ * maxBytes.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+GetSelText(
+ Tk_Canvas canvas, /* Canvas containing selection. */
+ Tk_Item *itemPtr, /* Text item containing selection. */
+ int offset, /* Byte offset within selection of first
+ * character to be returned. */
+ char *buffer, /* Location in which to place selection. */
+ int maxBytes) /* Maximum number of bytes to place at buffer,
+ * not including terminating NULL
+ * character. */
+{
+ TextItem *textPtr = (TextItem *) itemPtr;
+ int byteCount;
+ char *text;
+ const char *selStart, *selEnd;
+ Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;
+
+ if ((textInfoPtr->selectFirst < 0) ||
+ (textInfoPtr->selectFirst > textInfoPtr->selectLast)) {
+ return 0;
+ }
+ text = textPtr->text;
+ selStart = Tcl_UtfAtIndex(text, textInfoPtr->selectFirst);
+ selEnd = Tcl_UtfAtIndex(selStart,
+ textInfoPtr->selectLast + 1 - textInfoPtr->selectFirst);
+ byteCount = selEnd - selStart - offset;
+ if (byteCount > maxBytes) {
+ byteCount = maxBytes;
+ }
+ if (byteCount <= 0) {
+ return 0;
+ }
+ memcpy(buffer, selStart + offset, (size_t) byteCount);
+ buffer[byteCount] = '\0';
+ return byteCount;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TextToPostscript --
+ *
+ * This function is called to generate Postscript for text items.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If an error occurs in
+ * generating Postscript then an error message is left in the interp's
+ * result, replacing whatever used to be there. If no error occurs, then
+ * Postscript for the item is appended to the result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+TextToPostscript(
+ Tcl_Interp *interp, /* Leave Postscript or error message here. */
+ Tk_Canvas canvas, /* Information about overall canvas. */
+ Tk_Item *itemPtr, /* Item for which Postscript is wanted. */
+ int prepass) /* 1 means this is a prepass to collect font
+ * information; 0 means final Postscript is
+ * being created. */
+{
+ TextItem *textPtr = (TextItem *) itemPtr;
+ double x, y;
+ Tk_FontMetrics fm;
+ const char *justify;
+ XColor *color;
+ Pixmap stipple;
+ Tk_State state = itemPtr->state;
+ Tcl_Obj *psObj;
+ Tcl_InterpState interpState;
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+ color = textPtr->color;
+ stipple = textPtr->stipple;
+ if (state == TK_STATE_HIDDEN || textPtr->color == NULL ||
+ textPtr->text == NULL || *textPtr->text == 0) {
+ return TCL_OK;
+ } else if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (textPtr->activeColor != NULL) {
+ color = textPtr->activeColor;
+ }
+ if (textPtr->activeStipple != None) {
+ stipple = textPtr->activeStipple;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (textPtr->disabledColor != NULL) {
+ color = textPtr->disabledColor;
+ }
+ if (textPtr->disabledStipple != None) {
+ stipple = textPtr->disabledStipple;
+ }
+ }
+
+ /*
+ * Make our working space.
+ */
+
+ psObj = Tcl_NewObj();
+ interpState = Tcl_SaveInterpState(interp, TCL_OK);
+
+ /*
+ * Generate postscript.
+ */
+
+ Tcl_ResetResult(interp);
+ if (Tk_CanvasPsFont(interp, canvas, textPtr->tkfont) != TCL_OK) {
+ goto error;
+ }
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+
+ if (prepass != 0) {
+ goto done;
+ }
+
+ Tcl_ResetResult(interp);
+ if (Tk_CanvasPsColor(interp, canvas, color) != TCL_OK) {
+ goto error;
+ }
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+
+ if (stipple != None) {
+ Tcl_ResetResult(interp);
+ Tk_CanvasPsStipple(interp, canvas, stipple);
+ Tcl_AppendPrintfToObj(psObj, "/StippleText {\n %s} bind def\n",
+ Tcl_GetString(Tcl_GetObjResult(interp)));
+ }
+
+ x = 0; y = 0; justify = NULL; /* lint. */
+ switch (textPtr->anchor) {
+ case TK_ANCHOR_NW: x = 0; y = 0; break;
+ case TK_ANCHOR_N: x = 1; y = 0; break;
+ case TK_ANCHOR_NE: x = 2; y = 0; break;
+ case TK_ANCHOR_E: x = 2; y = 1; break;
+ case TK_ANCHOR_SE: x = 2; y = 2; break;
+ case TK_ANCHOR_S: x = 1; y = 2; break;
+ case TK_ANCHOR_SW: x = 0; y = 2; break;
+ case TK_ANCHOR_W: x = 0; y = 1; break;
+ case TK_ANCHOR_CENTER: x = 1; y = 1; break;
+ }
+ switch (textPtr->justify) {
+ case TK_JUSTIFY_LEFT: justify = "0"; break;
+ case TK_JUSTIFY_CENTER: justify = "0.5"; break;
+ case TK_JUSTIFY_RIGHT: justify = "1"; break;
+ }
+
+ Tk_GetFontMetrics(textPtr->tkfont, &fm);
+
+ Tcl_AppendPrintfToObj(psObj, "%.15g %.15g %.15g [\n",
+ textPtr->angle, textPtr->x, Tk_CanvasPsY(canvas, textPtr->y));
+ Tcl_ResetResult(interp);
+ Tk_TextLayoutToPostscript(interp, textPtr->textLayout);
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+ Tcl_AppendPrintfToObj(psObj,
+ "] %d %g %g %s %s DrawText\n",
+ fm.linespace, x / -2.0, y / 2.0, justify,
+ ((stipple == None) ? "false" : "true"));
+
+ /*
+ * Plug the accumulated postscript back into the result.
+ */
+
+ done:
+ (void) Tcl_RestoreInterpState(interp, interpState);
+ Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj);
+ Tcl_DecrRefCount(psObj);
+ return TCL_OK;
+
+ error:
+ Tcl_DiscardInterpState(interpState);
+ Tcl_DecrRefCount(psObj);
+ return TCL_ERROR;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkCanvUtil.c b/tk8.6/generic/tkCanvUtil.c
new file mode 100644
index 0000000..6ce671d
--- /dev/null
+++ b/tk8.6/generic/tkCanvUtil.c
@@ -0,0 +1,1873 @@
+/*
+ * tkCanvUtil.c --
+ *
+ * This file contains a collection of utility functions used by the
+ * implementations of various canvas item types.
+ *
+ * Copyright (c) 1994 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkInt.h"
+#include "tkCanvas.h"
+#include <assert.h>
+
+/*
+ * Structures defined only in this file.
+ */
+
+typedef struct SmoothAssocData {
+ struct SmoothAssocData *nextPtr;
+ /* Pointer to next SmoothAssocData. */
+ Tk_SmoothMethod smooth; /* Name and functions associated with this
+ * option. */
+} SmoothAssocData;
+
+const Tk_SmoothMethod tkBezierSmoothMethod = {
+ "true",
+ TkMakeBezierCurve,
+ (void (*) (Tcl_Interp *interp, Tk_Canvas canvas, double *coordPtr,
+ int numPoints, int numSteps)) TkMakeBezierPostscript,
+};
+static const Tk_SmoothMethod tkRawSmoothMethod = {
+ "raw",
+ TkMakeRawCurve,
+ (void (*) (Tcl_Interp *interp, Tk_Canvas canvas, double *coordPtr,
+ int numPoints, int numSteps)) TkMakeRawCurvePostscript,
+};
+
+/*
+ * Function forward-declarations.
+ */
+
+static void SmoothMethodCleanupProc(ClientData clientData,
+ Tcl_Interp *interp);
+static SmoothAssocData *InitSmoothMethods(Tcl_Interp *interp);
+static int DashConvert(char *l, const char *p, int n,
+ double width);
+static void TranslateAndAppendCoords(TkCanvas *canvPtr,
+ double x, double y, XPoint *outArr, int numOut);
+static inline Tcl_Obj * GetPostscriptBuffer(Tcl_Interp *interp);
+
+#define ABS(a) ((a>=0)?(a):(-(a)))
+
+static inline Tcl_Obj *
+GetPostscriptBuffer(
+ Tcl_Interp *interp)
+{
+ Tcl_Obj *psObj = Tcl_GetObjResult(interp);
+
+ if (Tcl_IsShared(psObj)) {
+ psObj = Tcl_DuplicateObj(psObj);
+ Tcl_SetObjResult(interp, psObj);
+ }
+ return psObj;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_CanvasTkwin --
+ *
+ * Given a token for a canvas, this function returns the widget that
+ * represents the canvas.
+ *
+ * Results:
+ * The return value is a handle for the widget.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_Window
+Tk_CanvasTkwin(
+ Tk_Canvas canvas) /* Token for the canvas. */
+{
+ return Canvas(canvas)->tkwin;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_CanvasDrawableCoords --
+ *
+ * Given an (x,y) coordinate pair within a canvas, this function
+ * returns the corresponding coordinates at which the point should
+ * be drawn in the drawable used for display.
+ *
+ * Results:
+ * There is no return value. The values at *drawableXPtr and
+ * *drawableYPtr are filled in with the coordinates at which x and y
+ * should be drawn. These coordinates are clipped to fit within a
+ * "short", since this is what X uses in most cases for drawing.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_CanvasDrawableCoords(
+ Tk_Canvas canvas, /* Token for the canvas. */
+ double x, /* Coordinates in canvas space. */
+ double y,
+ short *drawableXPtr, /* Screen coordinates are stored here. */
+ short *drawableYPtr)
+{
+ double tmp;
+
+ tmp = x - Canvas(canvas)->drawableXOrigin;
+ if (tmp > 0) {
+ tmp += 0.5;
+ } else {
+ tmp -= 0.5;
+ }
+ if (tmp > 32767) {
+ *drawableXPtr = 32767;
+ } else if (tmp < -32768) {
+ *drawableXPtr = -32768;
+ } else {
+ *drawableXPtr = (short) tmp;
+ }
+
+ tmp = y - Canvas(canvas)->drawableYOrigin;
+ if (tmp > 0) {
+ tmp += 0.5;
+ } else {
+ tmp -= 0.5;
+ }
+ if (tmp > 32767) {
+ *drawableYPtr = 32767;
+ } else if (tmp < -32768) {
+ *drawableYPtr = -32768;
+ } else {
+ *drawableYPtr = (short) tmp;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_CanvasWindowCoords --
+ *
+ * Given an (x,y) coordinate pair within a canvas, this function returns
+ * the corresponding coordinates in the canvas's window.
+ *
+ * Results:
+ * There is no return value. The values at *screenXPtr and *screenYPtr
+ * are filled in with the coordinates at which (x,y) appears in the
+ * canvas's window. These coordinates are clipped to fit within a
+ * "short", since this is what X uses in most cases for drawing.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_CanvasWindowCoords(
+ Tk_Canvas canvas, /* Token for the canvas. */
+ double x, /* Coordinates in canvas space. */
+ double y,
+ short *screenXPtr, /* Screen coordinates are stored here. */
+ short *screenYPtr)
+{
+ double tmp;
+
+ tmp = x - Canvas(canvas)->xOrigin;
+ if (tmp > 0) {
+ tmp += 0.5;
+ } else {
+ tmp -= 0.5;
+ }
+ if (tmp > 32767) {
+ *screenXPtr = 32767;
+ } else if (tmp < -32768) {
+ *screenXPtr = -32768;
+ } else {
+ *screenXPtr = (short) tmp;
+ }
+
+ tmp = y - Canvas(canvas)->yOrigin;
+ if (tmp > 0) {
+ tmp += 0.5;
+ } else {
+ tmp -= 0.5;
+ }
+ if (tmp > 32767) {
+ *screenYPtr = 32767;
+ } else if (tmp < -32768) {
+ *screenYPtr = -32768;
+ } else {
+ *screenYPtr = (short) tmp;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CanvasGetCoord --
+ *
+ * Given a string, returns a floating-point canvas coordinate
+ * corresponding to that string.
+ *
+ * Results:
+ * The return value is a standard Tcl return result. If TCL_OK is
+ * returned, then everything went well and the canvas coordinate is
+ * stored at *doublePtr; otherwise TCL_ERROR is returned and an error
+ * message is left in the interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_CanvasGetCoord(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Tk_Canvas canvas, /* Canvas to which coordinate applies. */
+ const char *string, /* Describes coordinate (any screen coordinate
+ * form may be used here). */
+ double *doublePtr) /* Place to store converted coordinate. */
+{
+ if (Tk_GetScreenMM(Canvas(canvas)->interp, Canvas(canvas)->tkwin, string,
+ doublePtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *doublePtr *= Canvas(canvas)->pixelsPerMM;
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CanvasGetCoordFromObj --
+ *
+ * Given a string, returns a floating-point canvas coordinate
+ * corresponding to that string.
+ *
+ * Results:
+ * The return value is a standard Tcl return result. If TCL_OK is
+ * returned, then everything went well and the canvas coordinate is
+ * stored at *doublePtr; otherwise TCL_ERROR is returned and an error
+ * message is left in interp->result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_CanvasGetCoordFromObj(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Tk_Canvas canvas, /* Canvas to which coordinate applies. */
+ Tcl_Obj *obj, /* Describes coordinate (any screen coordinate
+ * form may be used here). */
+ double *doublePtr) /* Place to store converted coordinate. */
+{
+ return Tk_GetDoublePixelsFromObj(Canvas(canvas)->interp, Canvas(canvas)->tkwin, obj, doublePtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_CanvasSetStippleOrigin --
+ *
+ * This function sets the stipple origin in a graphics context so that
+ * stipples drawn with the GC will line up with other stipples previously
+ * drawn in the canvas.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The graphics context is modified.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_CanvasSetStippleOrigin(
+ Tk_Canvas canvas, /* Token for a canvas. */
+ GC gc) /* Graphics context that is about to be used
+ * to draw a stippled pattern as part of
+ * redisplaying the canvas. */
+{
+ XSetTSOrigin(Canvas(canvas)->display, gc,
+ -Canvas(canvas)->drawableXOrigin,
+ -Canvas(canvas)->drawableYOrigin);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_CanvasSetOffset--
+ *
+ * This function sets the stipple offset in a graphics context so that
+ * stipples drawn with the GC will line up with other stipples with the
+ * same offset.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The graphics context is modified.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_CanvasSetOffset(
+ Tk_Canvas canvas, /* Token for a canvas. */
+ GC gc, /* Graphics context that is about to be used
+ * to draw a stippled pattern as part of
+ * redisplaying the canvas. */
+ Tk_TSOffset *offset) /* Offset (may be NULL pointer)*/
+{
+ register TkCanvas *canvasPtr = Canvas(canvas);
+ int flags = 0;
+ int x = - canvasPtr->drawableXOrigin;
+ int y = - canvasPtr->drawableYOrigin;
+
+ if (offset != NULL) {
+ flags = offset->flags;
+ x += offset->xoffset;
+ y += offset->yoffset;
+ }
+ if ((flags & TK_OFFSET_RELATIVE) && !(flags & TK_OFFSET_INDEX)) {
+ Tk_SetTSOrigin(canvasPtr->tkwin, gc, x - canvasPtr->xOrigin,
+ y - canvasPtr->yOrigin);
+ } else {
+ XSetTSOrigin(canvasPtr->display, gc, x, y);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_CanvasGetTextInfo --
+ *
+ * This function returns a pointer to a structure containing information
+ * about the selection and insertion cursor for a canvas widget. Items
+ * such as text items save the pointer and use it to share access to the
+ * information with the generic canvas code.
+ *
+ * Results:
+ * The return value is a pointer to the structure holding text
+ * information for the canvas. Most of the fields should not be modified
+ * outside the generic canvas code; see the user documentation for
+ * details.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_CanvasTextInfo *
+Tk_CanvasGetTextInfo(
+ Tk_Canvas canvas) /* Token for the canvas widget. */
+{
+ return &Canvas(canvas)->textInfo;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CanvasTagsParseProc --
+ *
+ * This function is invoked during option processing to handle "-tags"
+ * options for canvas items.
+ *
+ * Results:
+ * A standard Tcl return value.
+ *
+ * Side effects:
+ * The tags for a given item get replaced by those indicated in the value
+ * argument.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_CanvasTagsParseProc(
+ ClientData clientData, /* Not used.*/
+ Tcl_Interp *interp, /* Used for reporting errors. */
+ Tk_Window tkwin, /* Window containing canvas widget. */
+ const char *value, /* Value of option (list of tag names). */
+ char *widgRec, /* Pointer to record for item. */
+ int offset) /* Offset into item (ignored). */
+{
+ register Tk_Item *itemPtr = (Tk_Item *) widgRec;
+ int argc, i;
+ const char **argv;
+ Tk_Uid *newPtr;
+
+ /*
+ * Break the value up into the individual tag names.
+ */
+
+ if (Tcl_SplitList(interp, value, &argc, &argv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Make sure that there's enough space in the item to hold the tag names.
+ */
+
+ if (itemPtr->tagSpace < argc) {
+ newPtr = ckalloc(argc * sizeof(Tk_Uid));
+ for (i = itemPtr->numTags-1; i >= 0; i--) {
+ newPtr[i] = itemPtr->tagPtr[i];
+ }
+ if (itemPtr->tagPtr != itemPtr->staticTagSpace) {
+ ckfree(itemPtr->tagPtr);
+ }
+ itemPtr->tagPtr = newPtr;
+ itemPtr->tagSpace = argc;
+ }
+ itemPtr->numTags = argc;
+ for (i = 0; i < argc; i++) {
+ itemPtr->tagPtr[i] = Tk_GetUid(argv[i]);
+ }
+ ckfree(argv);
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CanvasTagsPrintProc --
+ *
+ * This function is invoked by the Tk configuration code to produce a
+ * printable string for the "-tags" configuration option for canvas
+ * items.
+ *
+ * Results:
+ * The return value is a string describing all the tags for the item
+ * referred to by "widgRec". In addition, *freeProcPtr is filled in with
+ * the address of a function to call to free the result string when it's
+ * no longer needed (or NULL to indicate that the string doesn't need to
+ * be freed).
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+const char *
+Tk_CanvasTagsPrintProc(
+ ClientData clientData, /* Ignored. */
+ Tk_Window tkwin, /* Window containing canvas widget. */
+ char *widgRec, /* Pointer to record for item. */
+ int offset, /* Ignored. */
+ Tcl_FreeProc **freeProcPtr) /* Pointer to variable to fill in with
+ * information about how to reclaim storage
+ * for return string. */
+{
+ register Tk_Item *itemPtr = (Tk_Item *) widgRec;
+
+ if (itemPtr->numTags == 0) {
+ *freeProcPtr = NULL;
+ return "";
+ }
+ if (itemPtr->numTags == 1) {
+ *freeProcPtr = NULL;
+ return (const char *) itemPtr->tagPtr[0];
+ }
+ *freeProcPtr = TCL_DYNAMIC;
+ return Tcl_Merge(itemPtr->numTags, (const char **) itemPtr->tagPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkCanvasDashParseProc --
+ *
+ * This function is invoked during option processing to handle "-dash",
+ * "-activedash" and "-disableddash" options for canvas objects.
+ *
+ * Results:
+ * A standard Tcl return value.
+ *
+ * Side effects:
+ * The dash list for a given canvas object gets replaced by those
+ * indicated in the value argument.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkCanvasDashParseProc(
+ ClientData clientData, /* Not used.*/
+ Tcl_Interp *interp, /* Used for reporting errors. */
+ Tk_Window tkwin, /* Window containing canvas widget. */
+ const char *value, /* Value of option. */
+ char *widgRec, /* Pointer to record for item. */
+ int offset) /* Offset into item. */
+{
+ return Tk_GetDash(interp, value, (Tk_Dash *) (widgRec+offset));
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkCanvasDashPrintProc --
+ *
+ * This function is invoked by the Tk configuration code to produce a
+ * printable string for the "-dash", "-activedash" and "-disableddash"
+ * configuration options for canvas items.
+ *
+ * Results:
+ * The return value is a string describing all the dash list for the item
+ * referred to by "widgRec"and "offset". In addition, *freeProcPtr is
+ * filled in with the address of a function to call to free the result
+ * string when it's no longer needed (or NULL to indicate that the string
+ * doesn't need to be freed).
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+const char *
+TkCanvasDashPrintProc(
+ ClientData clientData, /* Ignored. */
+ Tk_Window tkwin, /* Window containing canvas widget. */
+ char *widgRec, /* Pointer to record for item. */
+ int offset, /* Offset in record for item. */
+ Tcl_FreeProc **freeProcPtr) /* Pointer to variable to fill in with
+ * information about how to reclaim storage
+ * for return string. */
+{
+ Tk_Dash *dash = (Tk_Dash *) (widgRec+offset);
+ char *buffer, *p;
+ int i = dash->number;
+
+ if (i < 0) {
+ i = -i;
+ *freeProcPtr = TCL_DYNAMIC;
+ buffer = ckalloc(i + 1);
+ p = (i > (int)sizeof(char *)) ? dash->pattern.pt : dash->pattern.array;
+ memcpy(buffer, p, (unsigned int) i);
+ buffer[i] = 0;
+ return buffer;
+ } else if (!i) {
+ *freeProcPtr = NULL;
+ return "";
+ }
+ buffer = ckalloc(4 * i);
+ *freeProcPtr = TCL_DYNAMIC;
+
+ p = (i > (int)sizeof(char *)) ? dash->pattern.pt : dash->pattern.array;
+ sprintf(buffer, "%d", *p++ & 0xff);
+ while (--i) {
+ sprintf(buffer+strlen(buffer), " %d", *p++ & 0xff);
+ }
+ return buffer;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * InitSmoothMethods --
+ *
+ * This function is invoked to set up the initial state of the list of
+ * "-smooth" methods. It should only be called when the list installed
+ * in the interpreter is NULL.
+ *
+ * Results:
+ * Pointer to the start of the list of default smooth methods.
+ *
+ * Side effects:
+ * A linked list of smooth methods is created and attached to the
+ * interpreter's association key "smoothMethod"
+ *
+ *--------------------------------------------------------------
+ */
+
+static SmoothAssocData *
+InitSmoothMethods(
+ Tcl_Interp *interp)
+{
+ SmoothAssocData *methods, *ptr;
+
+ methods = ckalloc(sizeof(SmoothAssocData));
+ methods->smooth.name = tkRawSmoothMethod.name;
+ methods->smooth.coordProc = tkRawSmoothMethod.coordProc;
+ methods->smooth.postscriptProc = tkRawSmoothMethod.postscriptProc;
+
+ ptr = methods->nextPtr = ckalloc(sizeof(SmoothAssocData));
+ ptr->smooth.name = tkBezierSmoothMethod.name;
+ ptr->smooth.coordProc = tkBezierSmoothMethod.coordProc;
+ ptr->smooth.postscriptProc = tkBezierSmoothMethod.postscriptProc;
+ ptr->nextPtr = NULL;
+
+ Tcl_SetAssocData(interp, "smoothMethod", SmoothMethodCleanupProc,methods);
+ return methods;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CreateSmoothMethod --
+ *
+ * This function is invoked to add additional values for the "-smooth"
+ * option to the list.
+ *
+ * Results:
+ * A standard Tcl return value.
+ *
+ * Side effects:
+ * In the future "-smooth <name>" will be accepted as smooth method for
+ * the line and polygon.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_CreateSmoothMethod(
+ Tcl_Interp *interp,
+ const Tk_SmoothMethod *smooth)
+{
+ SmoothAssocData *methods, *typePtr2, *prevPtr, *ptr;
+ methods = Tcl_GetAssocData(interp, "smoothMethod", NULL);
+
+ /*
+ * Initialize if we were not previously initialized.
+ */
+
+ if (methods == NULL) {
+ methods = InitSmoothMethods(interp);
+ }
+
+ /*
+ * If there's already a smooth method with the given name, remove it.
+ */
+
+ for (typePtr2 = methods, prevPtr = NULL; typePtr2 != NULL;
+ prevPtr = typePtr2, typePtr2 = typePtr2->nextPtr) {
+ if (!strcmp(typePtr2->smooth.name, smooth->name)) {
+ if (prevPtr == NULL) {
+ methods = typePtr2->nextPtr;
+ } else {
+ prevPtr->nextPtr = typePtr2->nextPtr;
+ }
+ ckfree(typePtr2);
+ break;
+ }
+ }
+ ptr = ckalloc(sizeof(SmoothAssocData));
+ ptr->smooth.name = smooth->name;
+ ptr->smooth.coordProc = smooth->coordProc;
+ ptr->smooth.postscriptProc = smooth->postscriptProc;
+ ptr->nextPtr = methods;
+ Tcl_SetAssocData(interp, "smoothMethod", SmoothMethodCleanupProc, ptr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SmoothMethodCleanupProc --
+ *
+ * This function is invoked whenever an interpreter is deleted to
+ * cleanup the smooth methods.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Smooth methods are removed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+SmoothMethodCleanupProc(
+ ClientData clientData, /* Points to "smoothMethod" AssocData for the
+ * interpreter. */
+ Tcl_Interp *interp) /* Interpreter that is being deleted. */
+{
+ SmoothAssocData *ptr, *methods = clientData;
+
+ while (methods != NULL) {
+ ptr = methods;
+ methods = methods->nextPtr;
+ ckfree(ptr);
+ }
+}
+/*
+ *--------------------------------------------------------------
+ *
+ * TkSmoothParseProc --
+ *
+ * This function is invoked during option processing to handle the
+ * "-smooth" option.
+ *
+ * Results:
+ * A standard Tcl return value.
+ *
+ * Side effects:
+ * The smooth option for a given item gets replaced by the value
+ * indicated in the value argument.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkSmoothParseProc(
+ ClientData clientData, /* Ignored. */
+ Tcl_Interp *interp, /* Used for reporting errors. */
+ Tk_Window tkwin, /* Window containing canvas widget. */
+ const char *value, /* Value of option. */
+ char *widgRec, /* Pointer to record for item. */
+ int offset) /* Offset into item. */
+{
+ register const Tk_SmoothMethod **smoothPtr =
+ (const Tk_SmoothMethod **) (widgRec + offset);
+ const Tk_SmoothMethod *smooth = NULL;
+ int b;
+ size_t length;
+ SmoothAssocData *methods;
+
+ if (value == NULL || *value == 0) {
+ *smoothPtr = NULL;
+ return TCL_OK;
+ }
+ length = strlen(value);
+ methods = Tcl_GetAssocData(interp, "smoothMethod", NULL);
+
+ /*
+ * Not initialized yet; fix that now.
+ */
+
+ if (methods == NULL) {
+ methods = InitSmoothMethods(interp);
+ }
+
+ /*
+ * Backward compatability hack.
+ */
+
+ if (strncmp(value, "bezier", length) == 0) {
+ smooth = &tkBezierSmoothMethod;
+ }
+
+ /*
+ * Search the list of installed smooth methods.
+ */
+
+ while (methods != NULL) {
+ if (strncmp(value, methods->smooth.name, length) == 0) {
+ if (smooth != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "ambiguous smooth method \"%s\"", value));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "SMOOTH", value,
+ NULL);
+ return TCL_ERROR;
+ }
+ smooth = &methods->smooth;
+ }
+ methods = methods->nextPtr;
+ }
+ if (smooth) {
+ *smoothPtr = smooth;
+ return TCL_OK;
+ }
+
+ /*
+ * Did not find it. Try parsing as a boolean instead.
+ */
+
+ if (Tcl_GetBoolean(interp, (char *) value, &b) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *smoothPtr = b ? &tkBezierSmoothMethod : NULL;
+ return TCL_OK;
+}
+/*
+ *--------------------------------------------------------------
+ *
+ * TkSmoothPrintProc --
+ *
+ * This function is invoked by the Tk configuration code to produce a
+ * printable string for the "-smooth" configuration option.
+ *
+ * Results:
+ * The return value is a string describing the smooth option for the item
+ * referred to by "widgRec". In addition, *freeProcPtr is filled in with
+ * the address of a function to call to free the result string when it's
+ * no longer needed (or NULL to indicate that the string doesn't need to
+ * be freed).
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+const char *
+TkSmoothPrintProc(
+ ClientData clientData, /* Ignored. */
+ Tk_Window tkwin, /* Window containing canvas widget. */
+ char *widgRec, /* Pointer to record for item. */
+ int offset, /* Offset into item. */
+ Tcl_FreeProc **freeProcPtr) /* Pointer to variable to fill in with
+ * information about how to reclaim storage
+ * for return string. */
+{
+ register const Tk_SmoothMethod *smoothPtr =
+ * (Tk_SmoothMethod **) (widgRec + offset);
+
+ return smoothPtr ? smoothPtr->name : "0";
+}
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_GetDash
+ *
+ * This function is used to parse a string, assuming it is dash
+ * information.
+ *
+ * Results:
+ * The return value is a standard Tcl result: TCL_OK means that the dash
+ * information was parsed ok, and TCL_ERROR means it couldn't be parsed.
+ *
+ * Side effects:
+ * Dash information in the dash structure is updated.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_GetDash(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ const char *value, /* Textual specification of dash list. */
+ Tk_Dash *dash) /* Pointer to record in which to store dash
+ * information. */
+{
+ int argc, i;
+ const char **largv, **argv = NULL;
+ char *pt;
+
+ if ((value == NULL) || (*value == '\0')) {
+ dash->number = 0;
+ return TCL_OK;
+ }
+
+ /*
+ * switch is usually compiled more efficiently than a chain of conditions.
+ */
+
+ switch (*value) {
+ case '.': case ',': case '-': case '_':
+ i = DashConvert(NULL, value, -1, 0.0);
+ if (i <= 0) {
+ goto badDashList;
+ }
+ i = strlen(value);
+ if (i > (int) sizeof(char *)) {
+ dash->pattern.pt = pt = ckalloc(strlen(value));
+ } else {
+ pt = dash->pattern.array;
+ }
+ memcpy(pt, value, (unsigned) i);
+ dash->number = -i;
+ return TCL_OK;
+ }
+
+ if (Tcl_SplitList(interp, (char *) value, &argc, &argv) != TCL_OK) {
+ Tcl_ResetResult(interp);
+ goto badDashList;
+ }
+
+ if ((unsigned) ABS(dash->number) > sizeof(char *)) {
+ ckfree(dash->pattern.pt);
+ }
+ if (argc > (int) sizeof(char *)) {
+ dash->pattern.pt = pt = ckalloc(argc);
+ } else {
+ pt = dash->pattern.array;
+ }
+ dash->number = argc;
+
+ largv = argv;
+ while (argc > 0) {
+ if (Tcl_GetInt(interp, *largv, &i) != TCL_OK || i < 1 || i>255) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "expected integer in the range 1..255 but got \"%s\"",
+ *largv));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "DASH", NULL);
+ goto syntaxError;
+ }
+ *pt++ = i;
+ argc--;
+ largv++;
+ }
+
+ if (argv != NULL) {
+ ckfree(argv);
+ }
+ return TCL_OK;
+
+ /*
+ * Something went wrong. Generate error message, clean up and return.
+ */
+
+ badDashList:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad dash list \"%s\": must be a list of integers or a format like \"-..\"",
+ value));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "DASH", NULL);
+ syntaxError:
+ if (argv != NULL) {
+ ckfree(argv);
+ }
+ if ((unsigned) ABS(dash->number) > sizeof(char *)) {
+ ckfree(dash->pattern.pt);
+ }
+ dash->number = 0;
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CreateOutline
+ *
+ * This function initializes the Tk_Outline structure with default
+ * values.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_CreateOutline(
+ Tk_Outline *outline) /* Outline structure to be filled in. */
+{
+ outline->gc = NULL;
+ outline->width = 1.0;
+ outline->activeWidth = 0.0;
+ outline->disabledWidth = 0.0;
+ outline->offset = 0;
+ outline->dash.number = 0;
+ outline->activeDash.number = 0;
+ outline->disabledDash.number = 0;
+ outline->tsoffset.flags = 0;
+ outline->tsoffset.xoffset = 0;
+ outline->tsoffset.yoffset = 0;
+ outline->color = NULL;
+ outline->activeColor = NULL;
+ outline->disabledColor = NULL;
+ outline->stipple = None;
+ outline->activeStipple = None;
+ outline->disabledStipple = None;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_DeleteOutline
+ *
+ * This function frees all memory that might be allocated and referenced
+ * in the Tk_Outline structure.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_DeleteOutline(
+ Display *display, /* Display containing window. */
+ Tk_Outline *outline)
+{
+ if (outline->gc != NULL) {
+ Tk_FreeGC(display, outline->gc);
+ }
+ if ((unsigned) ABS(outline->dash.number) > sizeof(char *)) {
+ ckfree(outline->dash.pattern.pt);
+ }
+ if ((unsigned) ABS(outline->activeDash.number) > sizeof(char *)) {
+ ckfree(outline->activeDash.pattern.pt);
+ }
+ if ((unsigned) ABS(outline->disabledDash.number) > sizeof(char *)) {
+ ckfree(outline->disabledDash.pattern.pt);
+ }
+ if (outline->color != NULL) {
+ Tk_FreeColor(outline->color);
+ }
+ if (outline->activeColor != NULL) {
+ Tk_FreeColor(outline->activeColor);
+ }
+ if (outline->disabledColor != NULL) {
+ Tk_FreeColor(outline->disabledColor);
+ }
+ if (outline->stipple != None) {
+ Tk_FreeBitmap(display, outline->stipple);
+ }
+ if (outline->activeStipple != None) {
+ Tk_FreeBitmap(display, outline->activeStipple);
+ }
+ if (outline->disabledStipple != None) {
+ Tk_FreeBitmap(display, outline->disabledStipple);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_ConfigOutlineGC
+ *
+ * This function should be called in the canvas object during the
+ * configure command. The graphics context description in gcValues is
+ * updated according to the information in the dash structure, as far as
+ * possible.
+ *
+ * Results:
+ * The return-value is a mask, indicating which elements of gcValues have
+ * been updated. 0 means there is no outline.
+ *
+ * Side effects:
+ * GC information in gcValues is updated.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_ConfigOutlineGC(
+ XGCValues *gcValues,
+ Tk_Canvas canvas,
+ Tk_Item *item,
+ Tk_Outline *outline)
+{
+ int mask = 0;
+ double width;
+ Tk_Dash *dash;
+ XColor *color;
+ Pixmap stipple;
+ Tk_State state = item->state;
+
+ if (outline->width < 0.0) {
+ outline->width = 0.0;
+ }
+ if (outline->activeWidth < 0.0) {
+ outline->activeWidth = 0.0;
+ }
+ if (outline->disabledWidth < 0) {
+ outline->disabledWidth = 0.0;
+ }
+ if (state==TK_STATE_HIDDEN) {
+ return 0;
+ }
+
+ width = outline->width;
+ if (width < 1.0) {
+ width = 1.0;
+ }
+ dash = &(outline->dash);
+ color = outline->color;
+ stipple = outline->stipple;
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+ if (Canvas(canvas)->currentItemPtr == item) {
+ if (outline->activeWidth>width) {
+ width = outline->activeWidth;
+ }
+ if (outline->activeDash.number != 0) {
+ dash = &(outline->activeDash);
+ }
+ if (outline->activeColor!=NULL) {
+ color = outline->activeColor;
+ }
+ if (outline->activeStipple!=None) {
+ stipple = outline->activeStipple;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (outline->disabledWidth>0) {
+ width = outline->disabledWidth;
+ }
+ if (outline->disabledDash.number != 0) {
+ dash = &(outline->disabledDash);
+ }
+ if (outline->disabledColor!=NULL) {
+ color = outline->disabledColor;
+ }
+ if (outline->disabledStipple!=None) {
+ stipple = outline->disabledStipple;
+ }
+ }
+
+ if (color==NULL) {
+ return 0;
+ }
+
+ gcValues->line_width = (int) (width + 0.5);
+ if (color != NULL) {
+ gcValues->foreground = color->pixel;
+ mask = GCForeground|GCLineWidth;
+ if (stipple != None) {
+ gcValues->stipple = stipple;
+ gcValues->fill_style = FillStippled;
+ mask |= GCStipple|GCFillStyle;
+ }
+ }
+ if (mask && (dash->number != 0)) {
+ gcValues->line_style = LineOnOffDash;
+ gcValues->dash_offset = outline->offset;
+ if ((unsigned int)ABS(dash->number) > sizeof(char *)) {
+ gcValues->dashes = dash->pattern.pt[0];
+ } else if (dash->number != 0) {
+ gcValues->dashes = dash->pattern.array[0];
+ } else {
+ gcValues->dashes = (char) (4 * width + 0.5);
+ }
+ mask |= GCLineStyle|GCDashList|GCDashOffset;
+ }
+ return mask;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_ChangeOutlineGC
+ *
+ * Updates the GC to represent the full information of the dash
+ * structure. Partly this is already done in Tk_ConfigOutlineGC(). This
+ * function should be called just before drawing the dashed item.
+ *
+ * Results:
+ * 1 if there is a stipple pattern, and 0 otherwise.
+ *
+ * Side effects:
+ * GC is updated.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_ChangeOutlineGC(
+ Tk_Canvas canvas,
+ Tk_Item *item,
+ Tk_Outline *outline)
+{
+ const char *p;
+ double width;
+ Tk_Dash *dash;
+ XColor *color;
+ Pixmap stipple;
+ Tk_State state = item->state;
+
+ width = outline->width;
+ if (width < 1.0) {
+ width = 1.0;
+ }
+ dash = &(outline->dash);
+ color = outline->color;
+ stipple = outline->stipple;
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+ if (Canvas(canvas)->currentItemPtr == item) {
+ if (outline->activeWidth > width) {
+ width = outline->activeWidth;
+ }
+ if (outline->activeDash.number != 0) {
+ dash = &(outline->activeDash);
+ }
+ if (outline->activeColor != NULL) {
+ color = outline->activeColor;
+ }
+ if (outline->activeStipple != None) {
+ stipple = outline->activeStipple;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (outline->disabledWidth > width) {
+ width = outline->disabledWidth;
+ }
+ if (outline->disabledDash.number != 0) {
+ dash = &(outline->disabledDash);
+ }
+ if (outline->disabledColor != NULL) {
+ color = outline->disabledColor;
+ }
+ if (outline->disabledStipple != None) {
+ stipple = outline->disabledStipple;
+ }
+ }
+ if (color==NULL) {
+ return 0;
+ }
+
+ if ((dash->number<-1) ||
+ ((dash->number == -1) && (dash->pattern.array[0] != ','))) {
+ char *q;
+ int i = -dash->number;
+
+ p = (i > (int)sizeof(char *)) ? dash->pattern.pt : dash->pattern.array;
+ q = ckalloc(2 * i);
+ i = DashConvert(q, p, i, width);
+ XSetDashes(Canvas(canvas)->display, outline->gc, outline->offset, q,i);
+ ckfree(q);
+ } else if (dash->number>2 || (dash->number==2 &&
+ (dash->pattern.array[0]!=dash->pattern.array[1]))) {
+ p = (dash->number > (int) sizeof(char *))
+ ? dash->pattern.pt : dash->pattern.array;
+ XSetDashes(Canvas(canvas)->display, outline->gc, outline->offset, p,
+ dash->number);
+ }
+ if (stipple!=None) {
+ int w = 0; int h = 0;
+ Tk_TSOffset *tsoffset = &outline->tsoffset;
+ int flags = tsoffset->flags;
+
+ if (!(flags & TK_OFFSET_INDEX) &&
+ (flags & (TK_OFFSET_CENTER|TK_OFFSET_MIDDLE))) {
+ Tk_SizeOfBitmap(Canvas(canvas)->display, stipple, &w, &h);
+ if (flags & TK_OFFSET_CENTER) {
+ w /= 2;
+ } else {
+ w = 0;
+ }
+ if (flags & TK_OFFSET_MIDDLE) {
+ h /= 2;
+ } else {
+ h = 0;
+ }
+ }
+ tsoffset->xoffset -= w;
+ tsoffset->yoffset -= h;
+ Tk_CanvasSetOffset(canvas, outline->gc, tsoffset);
+ tsoffset->xoffset += w;
+ tsoffset->yoffset += h;
+ return 1;
+ }
+ return 0;
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_ResetOutlineGC
+ *
+ * Restores the GC to the situation before Tk_ChangeOutlineGC() was
+ * called. This function should be called just after the dashed item is
+ * drawn, because the GC is supposed to be read-only.
+ *
+ * Results:
+ * 1 if there is a stipple pattern, and 0 otherwise.
+ *
+ * Side effects:
+ * GC is updated.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_ResetOutlineGC(
+ Tk_Canvas canvas,
+ Tk_Item *item,
+ Tk_Outline *outline)
+{
+ char dashList;
+ double width;
+ Tk_Dash *dash;
+ XColor *color;
+ Pixmap stipple;
+ Tk_State state = item->state;
+
+ width = outline->width;
+ if (width < 1.0) {
+ width = 1.0;
+ }
+ dash = &(outline->dash);
+ color = outline->color;
+ stipple = outline->stipple;
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+ if (Canvas(canvas)->currentItemPtr == item) {
+ if (outline->activeWidth>width) {
+ width = outline->activeWidth;
+ }
+ if (outline->activeDash.number != 0) {
+ dash = &(outline->activeDash);
+ }
+ if (outline->activeColor!=NULL) {
+ color = outline->activeColor;
+ }
+ if (outline->activeStipple!=None) {
+ stipple = outline->activeStipple;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (outline->disabledWidth>width) {
+ width = outline->disabledWidth;
+ }
+ if (outline->disabledDash.number != 0) {
+ dash = &(outline->disabledDash);
+ }
+ if (outline->disabledColor!=NULL) {
+ color = outline->disabledColor;
+ }
+ if (outline->disabledStipple!=None) {
+ stipple = outline->disabledStipple;
+ }
+ }
+ if (color==NULL) {
+ return 0;
+ }
+
+ if ((dash->number > 2) || (dash->number < -1) || (dash->number==2 &&
+ (dash->pattern.array[0] != dash->pattern.array[1])) ||
+ ((dash->number == -1) && (dash->pattern.array[0] != ','))) {
+ if ((unsigned int)ABS(dash->number) > sizeof(char *)) {
+ dashList = dash->pattern.pt[0];
+ } else if (dash->number != 0) {
+ dashList = dash->pattern.array[0];
+ } else {
+ dashList = (char) (4 * width + 0.5);
+ }
+ XSetDashes(Canvas(canvas)->display, outline->gc, outline->offset,
+ &dashList , 1);
+ }
+ if (stipple != None) {
+ XSetTSOrigin(Canvas(canvas)->display, outline->gc, 0, 0);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CanvasPsOutline
+ *
+ * Creates the postscript command for the correct Outline-information
+ * (width, dash, color and stipple).
+ *
+ * Results:
+ * TCL_OK if succeeded, otherwise TCL_ERROR.
+ *
+ * Side effects:
+ * canvas->interp->result contains the postscript string, or an error
+ * message if the result was TCL_ERROR.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_CanvasPsOutline(
+ Tk_Canvas canvas,
+ Tk_Item *item,
+ Tk_Outline *outline)
+{
+ char pattern[11];
+ int i;
+ char *ptr, *lptr = pattern;
+ Tcl_Interp *interp = Canvas(canvas)->interp;
+ double width = outline->width;
+ Tk_Dash *dash = &outline->dash;
+ XColor *color = outline->color;
+ Pixmap stipple = outline->stipple;
+ Tk_State state = item->state;
+ Tcl_Obj *psObj = GetPostscriptBuffer(interp);
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+
+ if (Canvas(canvas)->currentItemPtr == item) {
+ if (outline->activeWidth > width) {
+ width = outline->activeWidth;
+ }
+ if (outline->activeDash.number > 0) {
+ dash = &outline->activeDash;
+ }
+ if (outline->activeColor != NULL) {
+ color = outline->activeColor;
+ }
+ if (outline->activeStipple != None) {
+ stipple = outline->activeStipple;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (outline->disabledWidth > 0) {
+ width = outline->disabledWidth;
+ }
+ if (outline->disabledDash.number > 0) {
+ dash = &outline->disabledDash;
+ }
+ if (outline->disabledColor != NULL) {
+ color = outline->disabledColor;
+ }
+ if (outline->disabledStipple != None) {
+ stipple = outline->disabledStipple;
+ }
+ }
+
+ Tcl_AppendPrintfToObj(psObj, "%.15g setlinewidth\n", width);
+
+ ptr = ((unsigned) ABS(dash->number) > sizeof(char *)) ?
+ dash->pattern.pt : dash->pattern.array;
+ Tcl_AppendToObj(psObj, "[", -1);
+ if (dash->number > 0) {
+ Tcl_Obj *converted;
+ char *p = ptr;
+
+ converted = Tcl_ObjPrintf("%d", *p++ & 0xff);
+ for (i = dash->number-1 ; i>0 ; i--) {
+ Tcl_AppendPrintfToObj(converted, " %d", *p++ & 0xff);
+ }
+ Tcl_AppendObjToObj(psObj, converted);
+ if (dash->number & 1) {
+ Tcl_AppendToObj(psObj, " ", -1);
+ Tcl_AppendObjToObj(psObj, converted);
+ }
+ Tcl_DecrRefCount(converted);
+ Tcl_AppendPrintfToObj(psObj, "] %d setdash\n", outline->offset);
+ } else if (dash->number < 0) {
+ if (dash->number < -5) {
+ lptr = ckalloc(1 - 2*dash->number);
+ }
+ i = DashConvert(lptr, ptr, -dash->number, width);
+ if (i > 0) {
+ char *p = lptr;
+
+ Tcl_AppendPrintfToObj(psObj, "%d", *p++ & 0xff);
+ for (; --i>0 ;) {
+ Tcl_AppendPrintfToObj(psObj, " %d", *p++ & 0xff);
+ }
+ Tcl_AppendPrintfToObj(psObj, "] %d setdash\n", outline->offset);
+ } else {
+ Tcl_AppendToObj(psObj, "] 0 setdash\n", -1);
+ }
+ if (lptr != pattern) {
+ ckfree(lptr);
+ }
+ } else {
+ Tcl_AppendToObj(psObj, "] 0 setdash\n", -1);
+ }
+
+ if (Tk_CanvasPsColor(interp, canvas, color) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Note that psObj might hold an invalid reference now.
+ */
+
+ if (stipple != None) {
+ Tcl_AppendToObj(GetPostscriptBuffer(interp), "StrokeClip ", -1);
+ if (Tk_CanvasPsStipple(interp, canvas, stipple) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ } else {
+ Tcl_AppendToObj(GetPostscriptBuffer(interp), "stroke\n", -1);
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DashConvert
+ *
+ * Converts a character-like dash-list (e.g. "-..") into an X11-style. l
+ * must point to a string that holds room to at least 2*n characters. If
+ * l == NULL, this function can be used for syntax checking only.
+ *
+ * Results:
+ * The length of the resulting X11 compatible dash-list. -1 if failed.
+ *
+ * Side effects:
+ * None
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+DashConvert(
+ char *l, /* Must be at least 2*n chars long, or NULL to
+ * indicate "just check syntax". */
+ const char *p, /* String to parse. */
+ int n, /* Length of string to parse, or -1 to
+ * indicate that strlen() should be used. */
+ double width) /* Width of line. */
+{
+ int result = 0;
+ int size, intWidth;
+
+ if (n < 0) {
+ n = strlen(p);
+ }
+ intWidth = (int) (width + 0.5);
+ if (intWidth < 1) {
+ intWidth = 1;
+ }
+ while (n-- && *p) {
+ switch (*p++) {
+ case ' ':
+ if (result) {
+ if (l) {
+ l[-1] += intWidth + 1;
+ }
+ continue;
+ }
+ return 0;
+ case '_':
+ size = 8;
+ break;
+ case '-':
+ size = 6;
+ break;
+ case ',':
+ size = 4;
+ break;
+ case '.':
+ size = 2;
+ break;
+ default:
+ return -1;
+ }
+ if (l) {
+ *l++ = size * intWidth;
+ *l++ = 4 * intWidth;
+ }
+ result += 2;
+ }
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TranslateAndAppendCoords --
+ *
+ * This is a helper routine for TkCanvTranslatePath() below.
+ *
+ * Given an (x,y) coordinate pair within a canvas, this function computes
+ * the corresponding coordinates at which the point should be drawn in
+ * the drawable used for display. Those coordinates are then written into
+ * outArr[numOut*2] and outArr[numOut*2+1].
+ *
+ * Results:
+ * There is no return value.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+TranslateAndAppendCoords(
+ TkCanvas *canvPtr, /* The canvas. */
+ double x, /* Coordinates in canvas space. */
+ double y,
+ XPoint *outArr, /* Write results into this array */
+ int numOut) /* Num of prior entries in outArr[] */
+{
+ double tmp;
+
+ tmp = x - canvPtr->drawableXOrigin;
+ if (tmp > 0) {
+ tmp += 0.5;
+ } else {
+ tmp -= 0.5;
+ }
+ outArr[numOut].x = (short) tmp;
+
+ tmp = y - canvPtr->drawableYOrigin;
+ if (tmp > 0) {
+ tmp += 0.5;
+ } else {
+ tmp -= 0.5;
+ }
+ outArr[numOut].y = (short) tmp;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkCanvTranslatePath
+ *
+ * Translate a line or polygon path so that all vertices are within a
+ * rectangle that is 1000 pixels larger than the total size of the canvas
+ * window. This will prevent pixel coordinates from overflowing the
+ * 16-bit integer size limitation imposed by most windowing systems.
+ *
+ * coordPtr must point to an array of doubles, two doubles per vertex.
+ * There are a total of numVertex vertices, or 2*numVertex entries in
+ * coordPtr. The result vertices written into outArr have their
+ * coordinate origin shifted to canvPtr->drawableXOrigin by
+ * canvPtr->drawableYOrigin. There might be as many as 3 times more
+ * output vertices than there are input vertices. The calling function
+ * should allocate space accordingly.
+ *
+ * This routine limits the width and height of a canvas window to 31767
+ * pixels. At the highest resolution display devices available today (210
+ * ppi in Jan 2003) that's a window that is over 13 feet wide and tall.
+ * Should be enough for the near future.
+ *
+ * Results:
+ * Clipped and translated path vertices are written into outArr[]. There
+ * might be as many as twice the vertices in outArr[] as there are in
+ * coordPtr[]. The return value is the number of vertices actually
+ * written into outArr[].
+ *
+ * Side effects:
+ * None
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkCanvTranslatePath(
+ TkCanvas *canvPtr, /* The canvas */
+ int numVertex, /* Number of vertices specified by
+ * coordArr[] */
+ double *coordArr, /* X and Y coordinates for each vertex */
+ int closedPath, /* True if this is a closed polygon */
+ XPoint *outArr) /* Write results here, if not NULL */
+{
+ int numOutput = 0; /* Number of output coordinates */
+ double lft, rgh; /* Left and right sides of the bounding box */
+ double top, btm; /* Top and bottom sizes of the bounding box */
+ double *tempArr; /* Temporary storage used by the clipper */
+ double *a, *b, *t; /* Pointers to parts of the temporary
+ * storage */
+ int i, j; /* Loop counters */
+ double limit[4]; /* Boundries at which clipping occurs */
+ double staticSpace[480]; /* Temp space from the stack */
+
+ /*
+ * Constrain all vertices of the path to be within a box that is no larger
+ * than 32000 pixels wide or height. The top-left corner of this clipping
+ * box is 1000 pixels above and to the left of the top left corner of the
+ * window on which the canvas is displayed.
+ *
+ * This means that a canvas will not display properly on a canvas window
+ * that is larger than 31000 pixels wide or high. That is not a problem
+ * today, but might someday become a factor for ultra-high resolutions
+ * displays.
+ *
+ * The X11 protocol allows us (in theory) to expand the size of the
+ * clipping box to 32767 pixels. But we have found experimentally that
+ * XFree86 sometimes fails to draw lines correctly if they are longer than
+ * about 32500 pixels. So we have left a little margin in the size to mask
+ * that bug.
+ */
+
+ lft = canvPtr->xOrigin - 1000.0;
+ top = canvPtr->yOrigin - 1000.0;
+ rgh = lft + 32000.0;
+ btm = top + 32000.0;
+
+ /*
+ * Try the common case first - no clipping. Loop over the input
+ * coordinates and translate them into appropriate output coordinates.
+ * But if a vertex outside of the bounding box is seen, break out of the
+ * loop.
+ *
+ * Most of the time, no clipping is needed, so this one loop is sufficient
+ * to do the translation.
+ */
+
+ for (i=0; i<numVertex; i++){
+ double x, y;
+
+ x = coordArr[i*2];
+ y = coordArr[i*2 + 1];
+ if (x<lft || x>rgh || y<top || y>btm) {
+ break;
+ }
+ TranslateAndAppendCoords(canvPtr, x, y, outArr, numOutput++);
+ }
+ if (i == numVertex){
+ assert(numOutput == numVertex);
+ return numOutput;
+ }
+
+ /*
+ * If we reach this point, it means that some clipping is required. Begin
+ * by allocating some working storage - at least 6 times as much space as
+ * coordArr[] requires. Divide this space into two separate arrays a[] and
+ * b[]. Initialize a[] to be equal to coordArr[].
+ */
+
+ if (numVertex*12 <= (int) (sizeof(staticSpace) / sizeof(double))) {
+ tempArr = staticSpace;
+ } else {
+ tempArr = ckalloc(numVertex * 12 * sizeof(double));
+ }
+ for (i=0; i<numVertex*2; i++){
+ tempArr[i] = coordArr[i];
+ }
+ a = tempArr;
+ b = &tempArr[numVertex*6];
+
+ /*
+ * We will make four passes through the input data. On each pass, we copy
+ * the contents of a[] over into b[]. As we copy, we clip any line
+ * segments that extend to the right past xClip then we rotate the
+ * coordinate system 90 degrees clockwise. After each pass is complete, we
+ * interchange a[] and b[] in preparation for the next pass.
+ *
+ * Each pass clips line segments that extend beyond a single side of the
+ * bounding box, and four passes rotate the coordinate system back to its
+ * original value. I'm not an expert on graphics algorithms, but I think
+ * this is called Cohen-Sutherland polygon clipping.
+ *
+ * The limit[] array contains the xClip value used for each of the four
+ * passes.
+ */
+
+ limit[0] = rgh;
+ limit[1] = -top;
+ limit[2] = -lft;
+ limit[3] = btm;
+
+ /*
+ * This is the loop that makes the four passes through the data.
+ */
+
+ for (j=0; j<4; j++) {
+ double xClip = limit[j];
+ int inside = a[0] < xClip;
+ double priorY = a[1];
+ numOutput = 0;
+
+ /*
+ * Clip everything to the right of xClip. Store the results in b[]
+ * rotated by 90 degrees clockwise.
+ */
+
+ for (i=0; i<numVertex; i++) {
+ double x = a[i*2];
+ double y = a[i*2 + 1];
+
+ if (x >= xClip) {
+ /*
+ * The current vertex is to the right of xClip.
+ */
+
+ if (inside) {
+ /*
+ * If the current vertex is to the right of xClip but the
+ * previous vertex was left of xClip, then draw a line
+ * segment from the previous vertex to until it intersects
+ * the vertical at xClip.
+ */
+
+ double x0, y0, yN;
+
+ assert(i > 0);
+ x0 = a[i*2 - 2];
+ y0 = a[i*2 - 1];
+ yN = y0 + (y - y0)*(xClip-x0)/(x-x0);
+ b[numOutput*2] = -yN;
+ b[numOutput*2 + 1] = xClip;
+ numOutput++;
+ assert(numOutput <= numVertex*3);
+ priorY = yN;
+ inside = 0;
+ } else if (i == 0) {
+ /*
+ * If the first vertex is to the right of xClip, add a
+ * vertex that is the projection of the first vertex onto
+ * the vertical xClip line.
+ */
+
+ b[0] = -y;
+ b[1] = xClip;
+ numOutput = 1;
+ priorY = y;
+ }
+ } else {
+ /*
+ * The current vertex is to the left of xClip
+ */
+
+ if (!inside) {
+ /*
+ * If the current vertex is on the left of xClip and one
+ * or more prior vertices where to the right, then we have
+ * to draw a line segment along xClip that extends from
+ * the spot where we first crossed from left to right to
+ * the spot where we cross back from right to left.
+ */
+
+ double x0, y0, yN;
+
+ assert(i > 0);
+ x0 = a[i*2 - 2];
+ y0 = a[i*2 - 1];
+ yN = y0 + (y - y0)*(xClip-x0)/(x-x0);
+ if (yN != priorY) {
+ b[numOutput*2] = -yN;
+ b[numOutput*2 + 1] = xClip;
+ numOutput++;
+ assert(numOutput <= numVertex*3);
+ }
+ inside = 1;
+ }
+ b[numOutput*2] = -y;
+ b[numOutput*2 + 1] = x;
+ numOutput++;
+ assert(numOutput <= numVertex*3);
+ }
+ }
+
+ /*
+ * Interchange a[] and b[] in preparation for the next pass.
+ */
+
+ t = a;
+ a = b;
+ b = t;
+ numVertex = numOutput;
+ }
+
+ /*
+ * All clipping is now finished. Convert the coordinates from doubles into
+ * XPoints and translate the origin for the drawable.
+ */
+
+ for (i=0; i<numVertex; i++) {
+ TranslateAndAppendCoords(canvPtr, a[i*2], a[i*2+1], outArr, i);
+ }
+ if (tempArr != staticSpace) {
+ ckfree(tempArr);
+ }
+ return numOutput;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkCanvWind.c b/tk8.6/generic/tkCanvWind.c
new file mode 100644
index 0000000..f73546f
--- /dev/null
+++ b/tk8.6/generic/tkCanvWind.c
@@ -0,0 +1,1095 @@
+/*
+ * tkCanvWind.c --
+ *
+ * This file implements window items for canvas widgets.
+ *
+ * Copyright (c) 1992-1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "tkInt.h"
+#include "tkCanvas.h"
+
+/*
+ * The structure below defines the record for each window item.
+ */
+
+typedef struct WindowItem {
+ Tk_Item header; /* Generic stuff that's the same for all
+ * types. MUST BE FIRST IN STRUCTURE. */
+ double x, y; /* Coordinates of positioning point for
+ * window. */
+ Tk_Window tkwin; /* Window associated with item. NULL means
+ * window has been destroyed. */
+ int width; /* Width to use for window (<= 0 means use
+ * window's requested width). */
+ int height; /* Width to use for window (<= 0 means use
+ * window's requested width). */
+ Tk_Anchor anchor; /* Where to anchor window relative to
+ * (x,y). */
+ Tk_Canvas canvas; /* Canvas containing this item. */
+} WindowItem;
+
+/*
+ * Information used for parsing configuration specs:
+ */
+
+static const Tk_CustomOption stateOption = {
+ TkStateParseProc, TkStatePrintProc, INT2PTR(2)
+};
+static const Tk_CustomOption tagsOption = {
+ Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL
+};
+
+static const Tk_ConfigSpec configSpecs[] = {
+ {TK_CONFIG_ANCHOR, "-anchor", NULL, NULL,
+ "center", Tk_Offset(WindowItem, anchor), TK_CONFIG_DONT_SET_DEFAULT, NULL},
+ {TK_CONFIG_PIXELS, "-height", NULL, NULL,
+ "0", Tk_Offset(WindowItem, height), TK_CONFIG_DONT_SET_DEFAULT, NULL},
+ {TK_CONFIG_CUSTOM, "-state", NULL, NULL,
+ NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption},
+ {TK_CONFIG_CUSTOM, "-tags", NULL, NULL,
+ NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
+ {TK_CONFIG_PIXELS, "-width", NULL, NULL,
+ "0", Tk_Offset(WindowItem, width), TK_CONFIG_DONT_SET_DEFAULT, NULL},
+ {TK_CONFIG_WINDOW, "-window", NULL, NULL,
+ NULL, Tk_Offset(WindowItem, tkwin), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}
+};
+
+/*
+ * Prototypes for functions defined in this file:
+ */
+
+static void ComputeWindowBbox(Tk_Canvas canvas,
+ WindowItem *winItemPtr);
+static int ConfigureWinItem(Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr, int objc,
+ Tcl_Obj *const objv[], int flags);
+static int CreateWinItem(Tcl_Interp *interp,
+ Tk_Canvas canvas, struct Tk_Item *itemPtr,
+ int objc, Tcl_Obj *const objv[]);
+static void DeleteWinItem(Tk_Canvas canvas,
+ Tk_Item *itemPtr, Display *display);
+static void DisplayWinItem(Tk_Canvas canvas,
+ Tk_Item *itemPtr, Display *display, Drawable dst,
+ int x, int y, int width, int height);
+static void ScaleWinItem(Tk_Canvas canvas,
+ Tk_Item *itemPtr, double originX, double originY,
+ double scaleX, double scaleY);
+static void TranslateWinItem(Tk_Canvas canvas,
+ Tk_Item *itemPtr, double deltaX, double deltaY);
+static int WinItemCoords(Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr, int objc,
+ Tcl_Obj *const objv[]);
+static void WinItemLostSlaveProc(ClientData clientData,
+ Tk_Window tkwin);
+static void WinItemRequestProc(ClientData clientData,
+ Tk_Window tkwin);
+static void WinItemStructureProc(ClientData clientData,
+ XEvent *eventPtr);
+static int WinItemToArea(Tk_Canvas canvas,
+ Tk_Item *itemPtr, double *rectPtr);
+static int WinItemToPostscript(Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr, int prepass);
+static double WinItemToPoint(Tk_Canvas canvas,
+ Tk_Item *itemPtr, double *pointPtr);
+#ifdef X_GetImage
+static int xerrorhandler(ClientData clientData, XErrorEvent *e);
+#endif
+static int CanvasPsWindow(Tcl_Interp *interp,
+ Tk_Window tkwin, Tk_Canvas canvas, double x,
+ double y, int width, int height);
+
+/*
+ * The structure below defines the window item type by means of functions
+ * that can be invoked by generic item code.
+ */
+
+Tk_ItemType tkWindowType = {
+ "window", /* name */
+ sizeof(WindowItem), /* itemSize */
+ CreateWinItem, /* createProc */
+ configSpecs, /* configSpecs */
+ ConfigureWinItem, /* configureProc */
+ WinItemCoords, /* coordProc */
+ DeleteWinItem, /* deleteProc */
+ DisplayWinItem, /* displayProc */
+ 1|TK_CONFIG_OBJS, /* flags */
+ WinItemToPoint, /* pointProc */
+ WinItemToArea, /* areaProc */
+ WinItemToPostscript, /* postscriptProc */
+ ScaleWinItem, /* scaleProc */
+ TranslateWinItem, /* translateProc */
+ NULL, /* indexProc */
+ NULL, /* cursorProc */
+ NULL, /* selectionProc */
+ NULL, /* insertProc */
+ NULL, /* dTextProc */
+ NULL, /* nextPtr */
+ NULL, 0, NULL, NULL
+};
+
+/*
+ * The structure below defines the official type record for the canvas (as
+ * geometry manager):
+ */
+
+static const Tk_GeomMgr canvasGeomType = {
+ "canvas", /* name */
+ WinItemRequestProc, /* requestProc */
+ WinItemLostSlaveProc, /* lostSlaveProc */
+};
+
+/*
+ *--------------------------------------------------------------
+ *
+ * CreateWinItem --
+ *
+ * This function is invoked to create a new window item in a canvas.
+ *
+ * Results:
+ * A standard Tcl return value. If an error occurred in creating the
+ * item, then an error message is left in the interp's result; in this
+ * case itemPtr is left uninitialized, so it can be safely freed by the
+ * caller.
+ *
+ * Side effects:
+ * A new window item is created.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+CreateWinItem(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Tk_Canvas canvas, /* Canvas to hold new item. */
+ Tk_Item *itemPtr, /* Record to hold new item; header has been
+ * initialized by caller. */
+ int objc, /* Number of arguments in objv. */
+ Tcl_Obj *const objv[]) /* Arguments describing window. */
+{
+ WindowItem *winItemPtr = (WindowItem *) itemPtr;
+ int i;
+
+ if (objc == 0) {
+ Tcl_Panic("canvas did not pass any coords");
+ }
+
+ /*
+ * Initialize item's record.
+ */
+
+ winItemPtr->tkwin = NULL;
+ winItemPtr->width = 0;
+ winItemPtr->height = 0;
+ winItemPtr->anchor = TK_ANCHOR_CENTER;
+ winItemPtr->canvas = canvas;
+
+ /*
+ * Process the arguments to fill in the item record. Only 1 (list) or 2 (x
+ * y) coords are allowed.
+ */
+
+ if (objc == 1) {
+ i = 1;
+ } else {
+ const char *arg = Tcl_GetString(objv[1]);
+
+ i = 2;
+ if ((arg[0] == '-') && (arg[1] >= 'a') && (arg[1] <= 'z')) {
+ i = 1;
+ }
+ }
+ if (WinItemCoords(interp, canvas, itemPtr, i, objv) != TCL_OK) {
+ goto error;
+ }
+ if (ConfigureWinItem(interp, canvas, itemPtr, objc-i, objv+i, 0)
+ == TCL_OK) {
+ return TCL_OK;
+ }
+
+ error:
+ DeleteWinItem(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * WinItemCoords --
+ *
+ * This function is invoked to process the "coords" widget command on
+ * window items. See the user documentation for details on what it does.
+ *
+ * Results:
+ * Returns TCL_OK or TCL_ERROR, and sets the interp's result.
+ *
+ * Side effects:
+ * The coordinates for the given item may be changed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+WinItemCoords(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item whose coordinates are to be read or
+ * modified. */
+ int objc, /* Number of coordinates supplied in objv. */
+ Tcl_Obj *const objv[]) /* Array of coordinates: x1, y1, x2, y2, ... */
+{
+ WindowItem *winItemPtr = (WindowItem *) itemPtr;
+
+ if (objc == 0) {
+ Tcl_Obj *objs[2];
+
+ objs[0] = Tcl_NewDoubleObj(winItemPtr->x);
+ objs[1] = Tcl_NewDoubleObj(winItemPtr->y);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(2, objs));
+ } else if (objc < 3) {
+ if (objc==1) {
+ if (Tcl_ListObjGetElements(interp, objv[0], &objc,
+ (Tcl_Obj ***) &objv) != TCL_OK) {
+ return TCL_ERROR;
+ } else if (objc != 2) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "wrong # coordinates: expected 2, got %d", objc));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "COORDS", "WINDOW",
+ NULL);
+ return TCL_ERROR;
+ }
+ }
+ if ((Tk_CanvasGetCoordFromObj(interp, canvas, objv[0], &winItemPtr->x)
+ != TCL_OK) || (Tk_CanvasGetCoordFromObj(interp, canvas, objv[1],
+ &winItemPtr->y) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ ComputeWindowBbox(canvas, winItemPtr);
+ } else {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "wrong # coordinates: expected 0 or 2, got %d", objc));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "COORDS", "WINDOW", NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ConfigureWinItem --
+ *
+ * This function is invoked to configure various aspects of a window
+ * item, such as its anchor position.
+ *
+ * Results:
+ * A standard Tcl result code. If an error occurs, then an error message
+ * is left in the interp's result.
+ *
+ * Side effects:
+ * Configuration information may be set for itemPtr.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+ConfigureWinItem(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tk_Canvas canvas, /* Canvas containing itemPtr. */
+ Tk_Item *itemPtr, /* Window item to reconfigure. */
+ int objc, /* Number of elements in objv. */
+ Tcl_Obj *const objv[], /* Arguments describing things to configure. */
+ int flags) /* Flags to pass to Tk_ConfigureWidget. */
+{
+ WindowItem *winItemPtr = (WindowItem *) itemPtr;
+ Tk_Window oldWindow;
+ Tk_Window canvasTkwin;
+
+ oldWindow = winItemPtr->tkwin;
+ canvasTkwin = Tk_CanvasTkwin(canvas);
+ if (TCL_OK != Tk_ConfigureWidget(interp, canvasTkwin, configSpecs, objc,
+ (const char **) objv, (char *) winItemPtr, flags|TK_CONFIG_OBJS)) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * A few of the options require additional processing.
+ */
+
+ if (oldWindow != winItemPtr->tkwin) {
+ if (oldWindow != NULL) {
+ Tk_DeleteEventHandler(oldWindow, StructureNotifyMask,
+ WinItemStructureProc, winItemPtr);
+ Tk_ManageGeometry(oldWindow, NULL, NULL);
+ Tk_UnmaintainGeometry(oldWindow, canvasTkwin);
+ Tk_UnmapWindow(oldWindow);
+ }
+ if (winItemPtr->tkwin != NULL) {
+ Tk_Window ancestor, parent;
+
+ /*
+ * Make sure that the canvas is either the parent of the window
+ * associated with the item or a descendant of that parent. Also,
+ * don't allow a top-of-hierarchy window to be managed inside a
+ * canvas.
+ */
+
+ parent = Tk_Parent(winItemPtr->tkwin);
+ for (ancestor = canvasTkwin ;; ancestor = Tk_Parent(ancestor)) {
+ if (ancestor == parent) {
+ break;
+ }
+ if (((Tk_FakeWin *) ancestor)->flags & TK_TOP_HIERARCHY) {
+ goto badWindow;
+ }
+ }
+ if (((Tk_FakeWin *) winItemPtr->tkwin)->flags & TK_TOP_HIERARCHY){
+ goto badWindow;
+ }
+ if (winItemPtr->tkwin == canvasTkwin) {
+ goto badWindow;
+ }
+ Tk_CreateEventHandler(winItemPtr->tkwin, StructureNotifyMask,
+ WinItemStructureProc, winItemPtr);
+ Tk_ManageGeometry(winItemPtr->tkwin, &canvasGeomType, winItemPtr);
+ }
+ }
+ if ((winItemPtr->tkwin != NULL)
+ && (itemPtr->state == TK_STATE_HIDDEN)) {
+ if (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) {
+ Tk_UnmapWindow(winItemPtr->tkwin);
+ } else {
+ Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);
+ }
+ }
+
+ ComputeWindowBbox(canvas, winItemPtr);
+ return TCL_OK;
+
+ badWindow:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't use %s in a window item of this canvas",
+ Tk_PathName(winItemPtr->tkwin)));
+ Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "HIERARCHY", NULL);
+ winItemPtr->tkwin = NULL;
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DeleteWinItem --
+ *
+ * This function is called to clean up the data structure associated with
+ * a window item.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Resources associated with itemPtr are released.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+DeleteWinItem(
+ Tk_Canvas canvas, /* Overall info about widget. */
+ Tk_Item *itemPtr, /* Item that is being deleted. */
+ Display *display) /* Display containing window for canvas. */
+{
+ WindowItem *winItemPtr = (WindowItem *) itemPtr;
+ Tk_Window canvasTkwin = Tk_CanvasTkwin(canvas);
+
+ if (winItemPtr->tkwin != NULL) {
+ Tk_DeleteEventHandler(winItemPtr->tkwin, StructureNotifyMask,
+ WinItemStructureProc, winItemPtr);
+ Tk_ManageGeometry(winItemPtr->tkwin, NULL, NULL);
+ if (canvasTkwin != Tk_Parent(winItemPtr->tkwin)) {
+ Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);
+ }
+ Tk_UnmapWindow(winItemPtr->tkwin);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ComputeWindowBbox --
+ *
+ * This function is invoked to compute the bounding box of all the pixels
+ * that may be drawn as part of a window item. This function is where the
+ * child window's placement is computed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The fields x1, y1, x2, and y2 are updated in the header for itemPtr.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ComputeWindowBbox(
+ Tk_Canvas canvas, /* Canvas that contains item. */
+ WindowItem *winItemPtr) /* Item whose bbox is to be recomputed. */
+{
+ int width, height, x, y;
+ Tk_State state = winItemPtr->header.state;
+
+ x = (int) (winItemPtr->x + ((winItemPtr->x >= 0) ? 0.5 : - 0.5));
+ y = (int) (winItemPtr->y + ((winItemPtr->y >= 0) ? 0.5 : - 0.5));
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+ if ((winItemPtr->tkwin == NULL) || (state == TK_STATE_HIDDEN)) {
+ /*
+ * There is no window for this item yet. Just give it a 1x1 bounding
+ * box. Don't give it a 0x0 bounding box; there are strange cases
+ * where this bounding box might be used as the dimensions of the
+ * window, and 0x0 causes problems under X.
+ */
+
+ winItemPtr->header.x1 = x;
+ winItemPtr->header.x2 = winItemPtr->header.x1 + 1;
+ winItemPtr->header.y1 = y;
+ winItemPtr->header.y2 = winItemPtr->header.y1 + 1;
+ return;
+ }
+
+ /*
+ * Compute dimensions of window.
+ */
+
+ width = winItemPtr->width;
+ if (width <= 0) {
+ width = Tk_ReqWidth(winItemPtr->tkwin);
+ if (width <= 0) {
+ width = 1;
+ }
+ }
+ height = winItemPtr->height;
+ if (height <= 0) {
+ height = Tk_ReqHeight(winItemPtr->tkwin);
+ if (height <= 0) {
+ height = 1;
+ }
+ }
+
+ /*
+ * Compute location of window, using anchor information.
+ */
+
+ switch (winItemPtr->anchor) {
+ case TK_ANCHOR_N:
+ x -= width/2;
+ break;
+ case TK_ANCHOR_NE:
+ x -= width;
+ break;
+ case TK_ANCHOR_E:
+ x -= width;
+ y -= height/2;
+ break;
+ case TK_ANCHOR_SE:
+ x -= width;
+ y -= height;
+ break;
+ case TK_ANCHOR_S:
+ x -= width/2;
+ y -= height;
+ break;
+ case TK_ANCHOR_SW:
+ y -= height;
+ break;
+ case TK_ANCHOR_W:
+ y -= height/2;
+ break;
+ case TK_ANCHOR_NW:
+ break;
+ case TK_ANCHOR_CENTER:
+ x -= width/2;
+ y -= height/2;
+ break;
+ }
+
+ /*
+ * Store the information in the item header.
+ */
+
+ winItemPtr->header.x1 = x;
+ winItemPtr->header.y1 = y;
+ winItemPtr->header.x2 = x + width;
+ winItemPtr->header.y2 = y + height;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DisplayWinItem --
+ *
+ * This function is invoked to "draw" a window item in a given drawable.
+ * Since the window draws itself, we needn't do any actual redisplay
+ * here. However, this function takes care of actually repositioning the
+ * child window so that it occupies the correct screen position.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The child window's position may get changed. Note: this function gets
+ * called both when a window needs to be displayed and when it ceases to
+ * be visible on the screen (e.g. it was scrolled or moved off-screen or
+ * the enclosing canvas is unmapped).
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+DisplayWinItem(
+ Tk_Canvas canvas, /* Canvas that contains item. */
+ Tk_Item *itemPtr, /* Item to be displayed. */
+ Display *display, /* Display on which to draw item. */
+ Drawable drawable, /* Pixmap or window in which to draw item. */
+ int regionX, int regionY, int regionWidth, int regionHeight)
+ /* Describes region of canvas that must be
+ * redisplayed (not used). */
+{
+ WindowItem *winItemPtr = (WindowItem *) itemPtr;
+ int width, height;
+ short x, y;
+ Tk_Window canvasTkwin = Tk_CanvasTkwin(canvas);
+ Tk_State state = itemPtr->state;
+
+ if (winItemPtr->tkwin == NULL) {
+ return;
+ }
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+
+ /*
+ * A drawable of None is used by the canvas UnmapNotify handler
+ * to indicate that we should no longer display ourselves.
+ */
+ if (state == TK_STATE_HIDDEN || drawable == None) {
+ if (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) {
+ Tk_UnmapWindow(winItemPtr->tkwin);
+ } else {
+ Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);
+ }
+ return;
+ }
+ Tk_CanvasWindowCoords(canvas, (double) winItemPtr->header.x1,
+ (double) winItemPtr->header.y1, &x, &y);
+ width = winItemPtr->header.x2 - winItemPtr->header.x1;
+ height = winItemPtr->header.y2 - winItemPtr->header.y1;
+
+ /*
+ * If the window is completely out of the visible area of the canvas then
+ * unmap it. This code used not to be present (why unmap the window if it
+ * isn't visible anyway?) but this could cause the window to suddenly
+ * reappear if the canvas window got resized.
+ */
+
+ if (((x + width) <= 0) || ((y + height) <= 0)
+ || (x >= Tk_Width(canvasTkwin)) || (y >= Tk_Height(canvasTkwin))) {
+ if (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) {
+ Tk_UnmapWindow(winItemPtr->tkwin);
+ } else {
+ Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);
+ }
+ return;
+ }
+
+ /*
+ * Reposition and map the window (but in different ways depending on
+ * whether the canvas is the window's parent).
+ */
+
+ if (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) {
+ if ((x != Tk_X(winItemPtr->tkwin)) || (y != Tk_Y(winItemPtr->tkwin))
+ || (width != Tk_Width(winItemPtr->tkwin))
+ || (height != Tk_Height(winItemPtr->tkwin))) {
+ Tk_MoveResizeWindow(winItemPtr->tkwin, x, y, width, height);
+ }
+ Tk_MapWindow(winItemPtr->tkwin);
+ } else {
+ Tk_MaintainGeometry(winItemPtr->tkwin, canvasTkwin, x, y,
+ width, height);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * WinItemToPoint --
+ *
+ * Computes the distance from a given point to a given window, in canvas
+ * units.
+ *
+ * Results:
+ * The return value is 0 if the point whose x and y coordinates are
+ * coordPtr[0] and coordPtr[1] is inside the window. If the point isn't
+ * inside the window then the return value is the distance from the point
+ * to the window.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static double
+WinItemToPoint(
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item to check against point. */
+ double *pointPtr) /* Pointer to x and y coordinates. */
+{
+ WindowItem *winItemPtr = (WindowItem *) itemPtr;
+ double x1, x2, y1, y2, xDiff, yDiff;
+
+ x1 = winItemPtr->header.x1;
+ y1 = winItemPtr->header.y1;
+ x2 = winItemPtr->header.x2;
+ y2 = winItemPtr->header.y2;
+
+ /*
+ * Point is outside window.
+ */
+
+ if (pointPtr[0] < x1) {
+ xDiff = x1 - pointPtr[0];
+ } else if (pointPtr[0] >= x2) {
+ xDiff = pointPtr[0] + 1 - x2;
+ } else {
+ xDiff = 0;
+ }
+
+ if (pointPtr[1] < y1) {
+ yDiff = y1 - pointPtr[1];
+ } else if (pointPtr[1] >= y2) {
+ yDiff = pointPtr[1] + 1 - y2;
+ } else {
+ yDiff = 0;
+ }
+
+ return hypot(xDiff, yDiff);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * WinItemToArea --
+ *
+ * This function is called to determine whether an item lies entirely
+ * inside, entirely outside, or overlapping a given rectangle.
+ *
+ * Results:
+ * -1 is returned if the item is entirely outside the area given by
+ * rectPtr, 0 if it overlaps, and 1 if it is entirely inside the given
+ * area.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+WinItemToArea(
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item to check against rectangle. */
+ double *rectPtr) /* Pointer to array of four coordinates
+ * (x1,y1,x2,y2) describing rectangular
+ * area. */
+{
+ WindowItem *winItemPtr = (WindowItem *) itemPtr;
+
+ if ((rectPtr[2] <= winItemPtr->header.x1)
+ || (rectPtr[0] >= winItemPtr->header.x2)
+ || (rectPtr[3] <= winItemPtr->header.y1)
+ || (rectPtr[1] >= winItemPtr->header.y2)) {
+ return -1;
+ }
+ if ((rectPtr[0] <= winItemPtr->header.x1)
+ && (rectPtr[1] <= winItemPtr->header.y1)
+ && (rectPtr[2] >= winItemPtr->header.x2)
+ && (rectPtr[3] >= winItemPtr->header.y2)) {
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * xerrorhandler --
+ *
+ * This is a dummy function to catch X11 errors during an attempt to
+ * print a canvas window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+#ifdef X_GetImage
+static int
+xerrorhandler(
+ ClientData clientData,
+ XErrorEvent *e)
+{
+ return 0;
+}
+#endif /* X_GetImage */
+
+/*
+ *--------------------------------------------------------------
+ *
+ * WinItemToPostscript --
+ *
+ * This function is called to generate Postscript for window items.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If an error occurs in
+ * generating Postscript then an error message is left in interp->result,
+ * replacing whatever used to be there. If no error occurs, then
+ * Postscript for the item is appended to the result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+WinItemToPostscript(
+ Tcl_Interp *interp, /* Leave Postscript or error message here. */
+ Tk_Canvas canvas, /* Information about overall canvas. */
+ Tk_Item *itemPtr, /* Item for which Postscript is wanted. */
+ int prepass) /* 1 means this is a prepass to collect font
+ * information; 0 means final Postscript is
+ * being created. */
+{
+ WindowItem *winItemPtr = (WindowItem *) itemPtr;
+ double x, y;
+ int width, height;
+ Tk_Window tkwin = winItemPtr->tkwin;
+
+ if (prepass || winItemPtr->tkwin == NULL) {
+ return TCL_OK;
+ }
+
+ width = Tk_Width(tkwin);
+ height = Tk_Height(tkwin);
+
+ /*
+ * Compute the coordinates of the lower-left corner of the window, taking
+ * into account the anchor position for the window.
+ */
+
+ x = winItemPtr->x;
+ y = Tk_CanvasPsY(canvas, winItemPtr->y);
+
+ switch (winItemPtr->anchor) {
+ case TK_ANCHOR_NW: y -= height; break;
+ case TK_ANCHOR_N: x -= width/2.0; y -= height; break;
+ case TK_ANCHOR_NE: x -= width; y -= height; break;
+ case TK_ANCHOR_E: x -= width; y -= height/2.0; break;
+ case TK_ANCHOR_SE: x -= width; break;
+ case TK_ANCHOR_S: x -= width/2.0; break;
+ case TK_ANCHOR_SW: break;
+ case TK_ANCHOR_W: y -= height/2.0; break;
+ case TK_ANCHOR_CENTER: x -= width/2.0; y -= height/2.0; break;
+ }
+
+ return CanvasPsWindow(interp, tkwin, canvas, x, y, width, height);
+}
+
+static int
+CanvasPsWindow(
+ Tcl_Interp *interp, /* Leave Postscript or error message here. */
+ Tk_Window tkwin, /* window to be printed */
+ Tk_Canvas canvas, /* Information about overall canvas. */
+ double x, double y, /* origin of window. */
+ int width, int height) /* width/height of window. */
+{
+ XImage *ximage;
+ int result;
+#ifdef X_GetImage
+ Tk_ErrorHandler handle;
+#endif
+ Tcl_Obj *cmdObj, *psObj;
+ Tcl_InterpState interpState = Tcl_SaveInterpState(interp, TCL_OK);
+
+ /*
+ * Locate the subwindow within the wider window.
+ */
+
+ psObj = Tcl_ObjPrintf(
+ "\n%%%% %s item (%s, %d x %d)\n" /* Comment */
+ "%.15g %.15g translate\n", /* Position */
+ Tk_Class(tkwin), Tk_PathName(tkwin), width, height, x, y);
+
+ /*
+ * First try if the widget has its own "postscript" command. If it exists,
+ * this will produce much better postscript than when a pixmap is used.
+ */
+
+ Tcl_ResetResult(interp);
+ cmdObj = Tcl_ObjPrintf("%s postscript -prolog 0", Tk_PathName(tkwin));
+ Tcl_IncrRefCount(cmdObj);
+ result = Tcl_EvalObjEx(interp, cmdObj, 0);
+ Tcl_DecrRefCount(cmdObj);
+
+ if (result == TCL_OK) {
+ Tcl_AppendPrintfToObj(psObj,
+ "50 dict begin\nsave\ngsave\n"
+ "0 %d moveto %d 0 rlineto 0 -%d rlineto -%d 0 rlineto closepath\n"
+ "1.000 1.000 1.000 setrgbcolor AdjustColor\nfill\ngrestore\n",
+ height, width, height, width);
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+ Tcl_AppendToObj(psObj, "\nrestore\nend\n\n\n", -1);
+ goto done;
+ }
+
+ /*
+ * If the window is off the screen it will generate a BadMatch/XError. We
+ * catch any BadMatch errors here
+ */
+
+#ifdef X_GetImage
+ handle = Tk_CreateErrorHandler(Tk_Display(tkwin), BadMatch,
+ X_GetImage, -1, xerrorhandler, tkwin);
+#endif
+
+ /*
+ * Generate an XImage from the window. We can then read pixel values out
+ * of the XImage.
+ */
+
+ ximage = XGetImage(Tk_Display(tkwin), Tk_WindowId(tkwin), 0, 0,
+ (unsigned) width, (unsigned) height, AllPlanes, ZPixmap);
+
+#ifdef X_GetImage
+ Tk_DeleteErrorHandler(handle);
+#endif
+
+ if (ximage == NULL) {
+ result = TCL_OK;
+ } else {
+ Tcl_ResetResult(interp);
+ result = TkPostscriptImage(interp, tkwin, Canvas(canvas)->psInfo,
+ ximage, 0, 0, width, height);
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+ XDestroyImage(ximage);
+ }
+
+ /*
+ * Plug the accumulated postscript back into the result.
+ */
+
+ done:
+ if (result == TCL_OK) {
+ (void) Tcl_RestoreInterpState(interp, interpState);
+ Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj);
+ } else {
+ Tcl_DiscardInterpState(interpState);
+ }
+ Tcl_DecrRefCount(psObj);
+ return result;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ScaleWinItem --
+ *
+ * This function is invoked to rescale a window item.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The window referred to by itemPtr is rescaled so that the following
+ * transformation is applied to all point coordinates:
+ * x' = originX + scaleX*(x-originX)
+ * y' = originY + scaleY*(y-originY)
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ScaleWinItem(
+ Tk_Canvas canvas, /* Canvas containing window. */
+ Tk_Item *itemPtr, /* Window to be scaled. */
+ double originX, double originY,
+ /* Origin about which to scale window. */
+ double scaleX, /* Amount to scale in X direction. */
+ double scaleY) /* Amount to scale in Y direction. */
+{
+ WindowItem *winItemPtr = (WindowItem *) itemPtr;
+
+ winItemPtr->x = originX + scaleX*(winItemPtr->x - originX);
+ winItemPtr->y = originY + scaleY*(winItemPtr->y - originY);
+ if (winItemPtr->width > 0) {
+ winItemPtr->width = (int) (scaleX*winItemPtr->width);
+ }
+ if (winItemPtr->height > 0) {
+ winItemPtr->height = (int) (scaleY*winItemPtr->height);
+ }
+ ComputeWindowBbox(canvas, winItemPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TranslateWinItem --
+ *
+ * This function is called to move a window by a given amount.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The position of the window is offset by (xDelta, yDelta), and the
+ * bounding box is updated in the generic part of the item structure.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+TranslateWinItem(
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item that is being moved. */
+ double deltaX, double deltaY)
+ /* Amount by which item is to be moved. */
+{
+ WindowItem *winItemPtr = (WindowItem *) itemPtr;
+
+ winItemPtr->x += deltaX;
+ winItemPtr->y += deltaY;
+ ComputeWindowBbox(canvas, winItemPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * WinItemStructureProc --
+ *
+ * This function is invoked whenever StructureNotify events occur for a
+ * window that's managed as part of a canvas window item. This function's
+ * only purpose is to clean up when windows are deleted.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The window is disassociated from the window item when it is deleted.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+WinItemStructureProc(
+ ClientData clientData, /* Pointer to record describing window item. */
+ XEvent *eventPtr) /* Describes what just happened. */
+{
+ WindowItem *winItemPtr = clientData;
+
+ if (eventPtr->type == DestroyNotify) {
+ winItemPtr->tkwin = NULL;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * WinItemRequestProc --
+ *
+ * This function is invoked whenever a window that's associated with a
+ * window canvas item changes its requested dimensions.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The size and location on the screen of the window may change,
+ * depending on the options specified for the window item.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+WinItemRequestProc(
+ ClientData clientData, /* Pointer to record for window item. */
+ Tk_Window tkwin) /* Window that changed its desired size. */
+{
+ WindowItem *winItemPtr = clientData;
+
+ ComputeWindowBbox(winItemPtr->canvas, winItemPtr);
+
+ /*
+ * A drawable argument of None to DisplayWinItem is used by the canvas
+ * UnmapNotify handler to indicate that we should no longer display
+ * ourselves, so need to pass a (bogus) non-zero drawable value here.
+ */
+ DisplayWinItem(winItemPtr->canvas, (Tk_Item *) winItemPtr, NULL,
+ (Drawable) -1, 0, 0, 0, 0);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * WinItemLostSlaveProc --
+ *
+ * This function is invoked by Tk whenever some other geometry claims
+ * control over a slave that used to be managed by us.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Forgets all canvas-related information about the slave.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static void
+WinItemLostSlaveProc(
+ ClientData clientData, /* WindowItem structure for slave window that
+ * was stolen away. */
+ Tk_Window tkwin) /* Tk's handle for the slave window. */
+{
+ WindowItem *winItemPtr = clientData;
+ Tk_Window canvasTkwin = Tk_CanvasTkwin(winItemPtr->canvas);
+
+ Tk_DeleteEventHandler(winItemPtr->tkwin, StructureNotifyMask,
+ WinItemStructureProc, winItemPtr);
+ if (canvasTkwin != Tk_Parent(winItemPtr->tkwin)) {
+ Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);
+ }
+ Tk_UnmapWindow(winItemPtr->tkwin);
+ winItemPtr->tkwin = NULL;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkCanvas.c b/tk8.6/generic/tkCanvas.c
new file mode 100644
index 0000000..4d260dc
--- /dev/null
+++ b/tk8.6/generic/tkCanvas.c
@@ -0,0 +1,5984 @@
+/*
+ * tkCanvas.c --
+ *
+ * This module implements canvas widgets for the Tk toolkit. A canvas
+ * displays a background and a collection of graphical objects such as
+ * rectangles, lines, and texts.
+ *
+ * Copyright (c) 1991-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+/* #define USE_OLD_TAG_SEARCH 1 */
+
+#include "default.h"
+#include "tkInt.h"
+#include "tkCanvas.h"
+#ifdef TK_NO_DOUBLE_BUFFERING
+#ifdef MAC_OSX_TK
+#include "tkMacOSXInt.h"
+#endif
+#endif /* TK_NO_DOUBLE_BUFFERING */
+
+/*
+ * See tkCanvas.h for key data structures used to implement canvases.
+ */
+
+#ifdef USE_OLD_TAG_SEARCH
+/*
+ * The structure defined below is used to keep track of a tag search in
+ * progress. No field should be accessed by anyone other than StartTagSearch
+ * and NextItem.
+ */
+
+typedef struct TagSearch {
+ TkCanvas *canvasPtr; /* Canvas widget being searched. */
+ Tk_Uid tag; /* Tag to search for. 0 means return all
+ * items. */
+ Tk_Item *currentPtr; /* Pointer to last item returned. */
+ Tk_Item *lastPtr; /* The item right before the currentPtr is
+ * tracked so if the currentPtr is deleted we
+ * don't have to start from the beginning. */
+ int searchOver; /* Non-zero means NextItem should always
+ * return NULL. */
+} TagSearch;
+
+#else /* USE_OLD_TAG_SEARCH */
+/*
+ * The structure defined below is used to keep track of a tag search in
+ * progress. No field should be accessed by anyone other than TagSearchScan,
+ * TagSearchFirst, TagSearchNext, TagSearchScanExpr, TagSearchEvalExpr,
+ * TagSearchExprInit, TagSearchExprDestroy, TagSearchDestroy.
+ * (
+ * Not quite accurate: the TagSearch structure is also accessed from:
+ * CanvasWidgetCmd, FindItems, RelinkItems
+ * The only instances of the structure are owned by:
+ * CanvasWidgetCmd
+ * CanvasWidgetCmd is the only function that calls:
+ * FindItems, RelinkItems
+ * CanvasWidgetCmd, FindItems, RelinkItems, are the only functions that call
+ * TagSearch*
+ * )
+ */
+
+typedef struct TagSearch {
+ TkCanvas *canvasPtr; /* Canvas widget being searched. */
+ Tk_Item *currentPtr; /* Pointer to last item returned. */
+ Tk_Item *lastPtr; /* The item right before the currentPtr is
+ * tracked so if the currentPtr is deleted we
+ * don't have to start from the beginning. */
+ int searchOver; /* Non-zero means NextItem should always
+ * return NULL. */
+ int type; /* Search type (see #defs below) */
+ int id; /* Item id for searches by id */
+ const char *string; /* Tag expression string */
+ int stringIndex; /* Current position in string scan */
+ int stringLength; /* Length of tag expression string */
+ char *rewritebuffer; /* Tag string (after removing escapes) */
+ unsigned int rewritebufferAllocated;
+ /* Available space for rewrites. */
+ TagSearchExpr *expr; /* Compiled tag expression. */
+} TagSearch;
+
+/*
+ * Values for the TagSearch type field.
+ */
+
+#define SEARCH_TYPE_EMPTY 0 /* Looking for empty tag */
+#define SEARCH_TYPE_ID 1 /* Looking for an item by id */
+#define SEARCH_TYPE_ALL 2 /* Looking for all items */
+#define SEARCH_TYPE_TAG 3 /* Looking for an item by simple tag */
+#define SEARCH_TYPE_EXPR 4 /* Compound search */
+
+#endif /* USE_OLD_TAG_SEARCH */
+
+/*
+ * Custom option for handling "-state" and "-offset"
+ */
+
+static const Tk_CustomOption stateOption = {
+ TkStateParseProc, TkStatePrintProc,
+ NULL /* Only "normal" and "disabled". */
+};
+
+static const Tk_CustomOption offsetOption = {
+ TkOffsetParseProc, TkOffsetPrintProc, INT2PTR(TK_OFFSET_RELATIVE)
+};
+
+/*
+ * Information used for argv parsing.
+ */
+
+static const Tk_ConfigSpec configSpecs[] = {
+ {TK_CONFIG_BORDER, "-background", "background", "Background",
+ DEF_CANVAS_BG_COLOR, Tk_Offset(TkCanvas, bgBorder),
+ TK_CONFIG_COLOR_ONLY, NULL},
+ {TK_CONFIG_BORDER, "-background", "background", "Background",
+ DEF_CANVAS_BG_MONO, Tk_Offset(TkCanvas, bgBorder),
+ TK_CONFIG_MONO_ONLY, NULL},
+ {TK_CONFIG_SYNONYM, "-bd", "borderWidth", NULL, NULL, 0, 0, NULL},
+ {TK_CONFIG_SYNONYM, "-bg", "background", NULL, NULL, 0, 0, NULL},
+ {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ DEF_CANVAS_BORDER_WIDTH, Tk_Offset(TkCanvas, borderWidth), 0, NULL},
+ {TK_CONFIG_DOUBLE, "-closeenough", "closeEnough", "CloseEnough",
+ DEF_CANVAS_CLOSE_ENOUGH, Tk_Offset(TkCanvas, closeEnough), 0, NULL},
+ {TK_CONFIG_BOOLEAN, "-confine", "confine", "Confine",
+ DEF_CANVAS_CONFINE, Tk_Offset(TkCanvas, confine), 0, NULL},
+ {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor",
+ DEF_CANVAS_CURSOR, Tk_Offset(TkCanvas, cursor), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_PIXELS, "-height", "height", "Height",
+ DEF_CANVAS_HEIGHT, Tk_Offset(TkCanvas, height), 0, NULL},
+ {TK_CONFIG_COLOR, "-highlightbackground", "highlightBackground",
+ "HighlightBackground", DEF_CANVAS_HIGHLIGHT_BG,
+ Tk_Offset(TkCanvas, highlightBgColorPtr), 0, NULL},
+ {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
+ DEF_CANVAS_HIGHLIGHT, Tk_Offset(TkCanvas, highlightColorPtr), 0, NULL},
+ {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness",
+ "HighlightThickness",
+ DEF_CANVAS_HIGHLIGHT_WIDTH, Tk_Offset(TkCanvas, highlightWidth), 0, NULL},
+ {TK_CONFIG_BORDER, "-insertbackground", "insertBackground", "Foreground",
+ DEF_CANVAS_INSERT_BG, Tk_Offset(TkCanvas, textInfo.insertBorder), 0, NULL},
+ {TK_CONFIG_PIXELS, "-insertborderwidth", "insertBorderWidth", "BorderWidth",
+ DEF_CANVAS_INSERT_BD_COLOR,
+ Tk_Offset(TkCanvas, textInfo.insertBorderWidth), TK_CONFIG_COLOR_ONLY, NULL},
+ {TK_CONFIG_PIXELS, "-insertborderwidth", "insertBorderWidth", "BorderWidth",
+ DEF_CANVAS_INSERT_BD_MONO,
+ Tk_Offset(TkCanvas, textInfo.insertBorderWidth), TK_CONFIG_MONO_ONLY, NULL},
+ {TK_CONFIG_INT, "-insertofftime", "insertOffTime", "OffTime",
+ DEF_CANVAS_INSERT_OFF_TIME, Tk_Offset(TkCanvas, insertOffTime), 0, NULL},
+ {TK_CONFIG_INT, "-insertontime", "insertOnTime", "OnTime",
+ DEF_CANVAS_INSERT_ON_TIME, Tk_Offset(TkCanvas, insertOnTime), 0, NULL},
+ {TK_CONFIG_PIXELS, "-insertwidth", "insertWidth", "InsertWidth",
+ DEF_CANVAS_INSERT_WIDTH, Tk_Offset(TkCanvas, textInfo.insertWidth), 0, NULL},
+ {TK_CONFIG_CUSTOM, "-offset", "offset", "Offset", "0,0",
+ Tk_Offset(TkCanvas, tsoffset),TK_CONFIG_DONT_SET_DEFAULT,
+ &offsetOption},
+ {TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
+ DEF_CANVAS_RELIEF, Tk_Offset(TkCanvas, relief), 0, NULL},
+ {TK_CONFIG_STRING, "-scrollregion", "scrollRegion", "ScrollRegion",
+ DEF_CANVAS_SCROLL_REGION, Tk_Offset(TkCanvas, regionString),
+ TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_BORDER, "-selectbackground", "selectBackground", "Foreground",
+ DEF_CANVAS_SELECT_COLOR, Tk_Offset(TkCanvas, textInfo.selBorder),
+ TK_CONFIG_COLOR_ONLY, NULL},
+ {TK_CONFIG_BORDER, "-selectbackground", "selectBackground", "Foreground",
+ DEF_CANVAS_SELECT_MONO, Tk_Offset(TkCanvas, textInfo.selBorder),
+ TK_CONFIG_MONO_ONLY, NULL},
+ {TK_CONFIG_PIXELS, "-selectborderwidth", "selectBorderWidth", "BorderWidth",
+ DEF_CANVAS_SELECT_BD_COLOR,
+ Tk_Offset(TkCanvas, textInfo.selBorderWidth), TK_CONFIG_COLOR_ONLY, NULL},
+ {TK_CONFIG_PIXELS, "-selectborderwidth", "selectBorderWidth", "BorderWidth",
+ DEF_CANVAS_SELECT_BD_MONO, Tk_Offset(TkCanvas, textInfo.selBorderWidth),
+ TK_CONFIG_MONO_ONLY, NULL},
+ {TK_CONFIG_COLOR, "-selectforeground", "selectForeground", "Background",
+ DEF_CANVAS_SELECT_FG_COLOR, Tk_Offset(TkCanvas, textInfo.selFgColorPtr),
+ TK_CONFIG_COLOR_ONLY|TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_COLOR, "-selectforeground", "selectForeground", "Background",
+ DEF_CANVAS_SELECT_FG_MONO, Tk_Offset(TkCanvas, textInfo.selFgColorPtr),
+ TK_CONFIG_MONO_ONLY|TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_CUSTOM, "-state", "state", "State",
+ "normal", Tk_Offset(TkCanvas, canvas_state), TK_CONFIG_DONT_SET_DEFAULT,
+ &stateOption},
+ {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus",
+ DEF_CANVAS_TAKE_FOCUS, Tk_Offset(TkCanvas, takeFocus),
+ TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_PIXELS, "-width", "width", "Width",
+ DEF_CANVAS_WIDTH, Tk_Offset(TkCanvas, width), 0, NULL},
+ {TK_CONFIG_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
+ DEF_CANVAS_X_SCROLL_CMD, Tk_Offset(TkCanvas, xScrollCmd),
+ TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_PIXELS, "-xscrollincrement", "xScrollIncrement",
+ "ScrollIncrement",
+ DEF_CANVAS_X_SCROLL_INCREMENT, Tk_Offset(TkCanvas, xScrollIncrement),
+ 0, NULL},
+ {TK_CONFIG_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand",
+ DEF_CANVAS_Y_SCROLL_CMD, Tk_Offset(TkCanvas, yScrollCmd),
+ TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_PIXELS, "-yscrollincrement", "yScrollIncrement",
+ "ScrollIncrement",
+ DEF_CANVAS_Y_SCROLL_INCREMENT, Tk_Offset(TkCanvas, yScrollIncrement),
+ 0, NULL},
+ {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}
+};
+
+/*
+ * List of all the item types known at present. This is *global* and is
+ * protected by typeListMutex.
+ */
+
+static Tk_ItemType *typeList = NULL;
+ /* NULL means initialization hasn't been done
+ * yet. */
+TCL_DECLARE_MUTEX(typeListMutex)
+
+#ifndef USE_OLD_TAG_SEARCH
+/*
+ * Uids for operands in compiled advanced tag search expressions.
+ * Initialization is done by GetStaticUids()
+ */
+
+typedef struct {
+ Tk_Uid allUid;
+ Tk_Uid currentUid;
+ Tk_Uid andUid;
+ Tk_Uid orUid;
+ Tk_Uid xorUid;
+ Tk_Uid parenUid;
+ Tk_Uid negparenUid;
+ Tk_Uid endparenUid;
+ Tk_Uid tagvalUid;
+ Tk_Uid negtagvalUid;
+} SearchUids;
+
+static Tcl_ThreadDataKey dataKey;
+static SearchUids * GetStaticUids(void);
+#endif /* USE_OLD_TAG_SEARCH */
+
+/*
+ * Prototypes for functions defined later in this file:
+ */
+
+static void CanvasBindProc(ClientData clientData,
+ XEvent *eventPtr);
+static void CanvasBlinkProc(ClientData clientData);
+static void CanvasCmdDeletedProc(ClientData clientData);
+static void CanvasDoEvent(TkCanvas *canvasPtr, XEvent *eventPtr);
+static void CanvasEventProc(ClientData clientData,
+ XEvent *eventPtr);
+static int CanvasFetchSelection(ClientData clientData, int offset,
+ char *buffer, int maxBytes);
+static Tk_Item * CanvasFindClosest(TkCanvas *canvasPtr,
+ double coords[2]);
+static void CanvasFocusProc(TkCanvas *canvasPtr, int gotFocus);
+static void CanvasLostSelection(ClientData clientData);
+static void CanvasSelectTo(TkCanvas *canvasPtr,
+ Tk_Item *itemPtr, int index);
+static void CanvasSetOrigin(TkCanvas *canvasPtr,
+ int xOrigin, int yOrigin);
+static void CanvasUpdateScrollbars(TkCanvas *canvasPtr);
+static int CanvasWidgetCmd(ClientData clientData,
+ Tcl_Interp *interp, int argc,
+ Tcl_Obj *const *argv);
+static void CanvasWorldChanged(ClientData instanceData);
+static int ConfigureCanvas(Tcl_Interp *interp,
+ TkCanvas *canvasPtr, int argc,
+ Tcl_Obj *const *argv, int flags);
+static void DestroyCanvas(char *memPtr);
+static void DisplayCanvas(ClientData clientData);
+static void DoItem(Tcl_Obj *accumObj,
+ Tk_Item *itemPtr, Tk_Uid tag);
+static void EventuallyRedrawItem(TkCanvas *canvasPtr,
+ Tk_Item *itemPtr);
+#ifdef USE_OLD_TAG_SEARCH
+static int FindItems(Tcl_Interp *interp, TkCanvas *canvasPtr,
+ int argc, Tcl_Obj *const *argv,
+ Tcl_Obj *newTagObj, int first);
+#else /* USE_OLD_TAG_SEARCH */
+static int FindItems(Tcl_Interp *interp, TkCanvas *canvasPtr,
+ int argc, Tcl_Obj *const *argv,
+ Tcl_Obj *newTagObj, int first,
+ TagSearch **searchPtrPtr);
+#endif /* USE_OLD_TAG_SEARCH */
+static int FindArea(Tcl_Interp *interp, TkCanvas *canvasPtr,
+ Tcl_Obj *const *argv, Tk_Uid uid, int enclosed);
+static double GridAlign(double coord, double spacing);
+static const char** TkGetStringsFromObjs(int argc, Tcl_Obj *const *objv);
+static void InitCanvas(void);
+#ifdef USE_OLD_TAG_SEARCH
+static Tk_Item * NextItem(TagSearch *searchPtr);
+#endif /* USE_OLD_TAG_SEARCH */
+static void PickCurrentItem(TkCanvas *canvasPtr, XEvent *eventPtr);
+static Tcl_Obj * ScrollFractions(int screen1,
+ int screen2, int object1, int object2);
+#ifdef USE_OLD_TAG_SEARCH
+static void RelinkItems(TkCanvas *canvasPtr,
+ Tcl_Obj *tag, Tk_Item *prevPtr);
+static Tk_Item * StartTagSearch(TkCanvas *canvasPtr,
+ Tcl_Obj *tag, TagSearch *searchPtr);
+#else /* USE_OLD_TAG_SEARCH */
+static int RelinkItems(TkCanvas *canvasPtr, Tcl_Obj *tag,
+ Tk_Item *prevPtr, TagSearch **searchPtrPtr);
+static void TagSearchExprInit(TagSearchExpr **exprPtrPtr);
+static void TagSearchExprDestroy(TagSearchExpr *expr);
+static void TagSearchDestroy(TagSearch *searchPtr);
+static int TagSearchScan(TkCanvas *canvasPtr,
+ Tcl_Obj *tag, TagSearch **searchPtrPtr);
+static int TagSearchScanExpr(Tcl_Interp *interp,
+ TagSearch *searchPtr, TagSearchExpr *expr);
+static int TagSearchEvalExpr(TagSearchExpr *expr,
+ Tk_Item *itemPtr);
+static Tk_Item * TagSearchFirst(TagSearch *searchPtr);
+static Tk_Item * TagSearchNext(TagSearch *searchPtr);
+#endif /* USE_OLD_TAG_SEARCH */
+
+/*
+ * The structure below defines canvas class behavior by means of functions
+ * that can be invoked from generic window code.
+ */
+
+static const Tk_ClassProcs canvasClass = {
+ sizeof(Tk_ClassProcs), /* size */
+ CanvasWorldChanged, /* worldChangedProc */
+ NULL, /* createProc */
+ NULL /* modalProc */
+};
+
+/*
+ * Macros that significantly simplify all code that finds items.
+ */
+
+#ifdef USE_OLD_TAG_SEARCH
+#define FIRST_CANVAS_ITEM_MATCHING(objPtr,searchPtrPtr,errorExitClause) \
+ itemPtr = StartTagSearch(canvasPtr,(objPtr),&search)
+#define FOR_EVERY_CANVAS_ITEM_MATCHING(objPtr,searchPtrPtr,errorExitClause) \
+ for (itemPtr = StartTagSearch(canvasPtr, (objPtr), &search); \
+ itemPtr != NULL; itemPtr = NextItem(&search))
+#define FIND_ITEMS(objPtr, n) \
+ FindItems(interp, canvasPtr, objc, objv, (objPtr), (n))
+#define RELINK_ITEMS(objPtr, itemPtr) \
+ RelinkItems(canvasPtr, (objPtr), (itemPtr))
+#else /* USE_OLD_TAG_SEARCH */
+#define FIRST_CANVAS_ITEM_MATCHING(objPtr,searchPtrPtr,errorExitClause) \
+ if ((result=TagSearchScan(canvasPtr,(objPtr),(searchPtrPtr))) != TCL_OK){ \
+ errorExitClause; \
+ } \
+ itemPtr = TagSearchFirst(*(searchPtrPtr));
+#define FOR_EVERY_CANVAS_ITEM_MATCHING(objPtr,searchPtrPtr,errorExitClause) \
+ if ((result=TagSearchScan(canvasPtr,(objPtr),(searchPtrPtr))) != TCL_OK){ \
+ errorExitClause; \
+ } \
+ for (itemPtr = TagSearchFirst(*(searchPtrPtr)); \
+ itemPtr != NULL; itemPtr = TagSearchNext(*(searchPtrPtr)))
+#define FIND_ITEMS(objPtr, n) \
+ FindItems(interp, canvasPtr, objc, objv, (objPtr), (n), &searchPtr)
+#define RELINK_ITEMS(objPtr, itemPtr) \
+ result = RelinkItems(canvasPtr, (objPtr), (itemPtr), &searchPtr)
+#endif /* USE_OLD_TAG_SEARCH */
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * AlwaysRedraw, ItemConfigure, ItemCoords, etc. --
+ *
+ * Helper functions that make access to canvas item functions simpler.
+ * Note that these are all inline functions.
+ *
+ * ----------------------------------------------------------------------
+ */
+
+static inline int
+AlwaysRedraw(
+ Tk_Item *itemPtr)
+{
+ return itemPtr->typePtr->alwaysRedraw & 1;
+}
+
+static inline int
+ItemConfigure(
+ TkCanvas *canvasPtr,
+ Tk_Item *itemPtr,
+ int objc,
+ Tcl_Obj *const objv[])
+{
+ Tcl_Interp *interp = canvasPtr->interp;
+ int result;
+
+ if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) {
+ result = itemPtr->typePtr->configProc(interp, (Tk_Canvas) canvasPtr,
+ itemPtr, objc, objv, TK_CONFIG_ARGV_ONLY);
+ } else {
+ const char **args = TkGetStringsFromObjs(objc, objv);
+
+ result = itemPtr->typePtr->configProc(interp, (Tk_Canvas) canvasPtr,
+ itemPtr, objc, (Tcl_Obj **) args, TK_CONFIG_ARGV_ONLY);
+ if (args != NULL) {
+ ckfree(args);
+ }
+ }
+ return result;
+}
+
+static inline int
+ItemConfigInfo(
+ TkCanvas *canvasPtr,
+ Tk_Item *itemPtr,
+ Tcl_Obj *fieldName)
+{
+ return Tk_ConfigureInfo(canvasPtr->interp, canvasPtr->tkwin,
+ itemPtr->typePtr->configSpecs, (char *) itemPtr,
+ (fieldName ? Tcl_GetString(fieldName) : NULL), 0);
+}
+
+static inline int
+ItemConfigValue(
+ TkCanvas *canvasPtr,
+ Tk_Item *itemPtr,
+ Tcl_Obj *fieldName)
+{
+ return Tk_ConfigureValue(canvasPtr->interp, canvasPtr->tkwin,
+ itemPtr->typePtr->configSpecs, (char *) itemPtr,
+ Tcl_GetString(fieldName), 0);
+}
+
+static inline int
+ItemCoords(
+ TkCanvas *canvasPtr,
+ Tk_Item *itemPtr,
+ int objc,
+ Tcl_Obj *const objv[])
+{
+ Tcl_Interp *interp = canvasPtr->interp;
+ int result;
+
+ if (itemPtr->typePtr->coordProc == NULL) {
+ result = TCL_OK;
+ } else if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) {
+ result = itemPtr->typePtr->coordProc(interp, (Tk_Canvas) canvasPtr,
+ itemPtr, objc, objv);
+ } else {
+ const char **args = TkGetStringsFromObjs(objc, objv);
+
+ result = itemPtr->typePtr->coordProc(interp, (Tk_Canvas) canvasPtr,
+ itemPtr, objc, (Tcl_Obj **) args);
+ if (args != NULL) {
+ ckfree(args);
+ }
+ }
+ return result;
+}
+
+static inline int
+ItemCreate(
+ TkCanvas *canvasPtr,
+ Tk_Item *itemPtr, /* Warning: incomplete! typePtr field must be
+ * set by this point. */
+ int objc,
+ Tcl_Obj *const objv[])
+{
+ Tcl_Interp *interp = canvasPtr->interp;
+ int result;
+
+ if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) {
+ result = itemPtr->typePtr->createProc(interp, (Tk_Canvas) canvasPtr,
+ itemPtr, objc-3, objv+3);
+ } else {
+ const char **args = TkGetStringsFromObjs(objc-3, objv+3);
+
+ result = itemPtr->typePtr->createProc(interp, (Tk_Canvas) canvasPtr,
+ itemPtr, objc-3, (Tcl_Obj **) args);
+ if (args != NULL) {
+ ckfree(args);
+ }
+ }
+ return result;
+}
+
+static inline void
+ItemCursor(
+ TkCanvas *canvasPtr,
+ Tk_Item *itemPtr,
+ int index)
+{
+ itemPtr->typePtr->icursorProc((Tk_Canvas) canvasPtr, itemPtr, index);
+}
+
+static inline void
+ItemDelChars(
+ TkCanvas *canvasPtr,
+ Tk_Item *itemPtr,
+ int first,
+ int last)
+{
+ itemPtr->typePtr->dCharsProc((Tk_Canvas) canvasPtr, itemPtr, first, last);
+}
+
+static inline void
+ItemDelete(
+ TkCanvas *canvasPtr,
+ Tk_Item *itemPtr)
+{
+ itemPtr->typePtr->deleteProc((Tk_Canvas) canvasPtr, itemPtr,
+ canvasPtr->display);
+}
+
+static inline void
+ItemDisplay(
+ TkCanvas *canvasPtr,
+ Tk_Item *itemPtr,
+ Pixmap pixmap,
+ int screenX1, int screenY1,
+ int width, int height)
+{
+ itemPtr->typePtr->displayProc((Tk_Canvas) canvasPtr, itemPtr,
+ canvasPtr->display, pixmap, screenX1, screenY1, width, height);
+}
+
+static inline int
+ItemIndex(
+ TkCanvas *canvasPtr,
+ Tk_Item *itemPtr,
+ Tcl_Obj *objPtr,
+ int *indexPtr)
+{
+ Tcl_Interp *interp = canvasPtr->interp;
+
+ if (itemPtr->typePtr->indexProc == NULL) {
+ return TCL_OK;
+ } else if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) {
+ return itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr,
+ itemPtr, objPtr, indexPtr);
+ } else {
+ return itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr,
+ itemPtr, (Tcl_Obj *) Tcl_GetString(objPtr), indexPtr);
+ }
+}
+
+static inline void
+ItemInsert(
+ TkCanvas *canvasPtr,
+ Tk_Item *itemPtr,
+ int beforeThis,
+ Tcl_Obj *toInsert)
+{
+ if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) {
+ itemPtr->typePtr->insertProc((Tk_Canvas) canvasPtr, itemPtr,
+ beforeThis, toInsert);
+ } else {
+ itemPtr->typePtr->insertProc((Tk_Canvas) canvasPtr, itemPtr,
+ beforeThis, (Tcl_Obj *) Tcl_GetString(toInsert));
+ }
+}
+
+static inline int
+ItemOverlap(
+ TkCanvas *canvasPtr,
+ Tk_Item *itemPtr,
+ double rect[])
+{
+ return itemPtr->typePtr->areaProc((Tk_Canvas) canvasPtr, itemPtr, rect);
+}
+
+static inline double
+ItemPoint(
+ TkCanvas *canvasPtr,
+ Tk_Item *itemPtr,
+ double coords[],
+ double halo)
+{
+ double dist;
+
+ dist = itemPtr->typePtr->pointProc((Tk_Canvas) canvasPtr, itemPtr,
+ coords) - halo;
+ return (dist < 0.0) ? 0.0 : dist;
+}
+
+static inline void
+ItemScale(
+ TkCanvas *canvasPtr,
+ Tk_Item *itemPtr,
+ double xOrigin, double yOrigin,
+ double xScale, double yScale)
+{
+ itemPtr->typePtr->scaleProc((Tk_Canvas) canvasPtr, itemPtr,
+ xOrigin, yOrigin, xScale, yScale);
+}
+
+static inline int
+ItemSelection(
+ TkCanvas *canvasPtr,
+ Tk_Item *itemPtr,
+ int offset,
+ char *buffer,
+ int maxBytes)
+{
+ if (itemPtr == NULL || itemPtr->typePtr->selectionProc == NULL) {
+ return -1;
+ }
+
+ return itemPtr->typePtr->selectionProc((Tk_Canvas) canvasPtr, itemPtr,
+ offset, buffer, maxBytes);
+}
+
+static inline void
+ItemTranslate(
+ TkCanvas *canvasPtr,
+ Tk_Item *itemPtr,
+ double xDelta,
+ double yDelta)
+{
+ itemPtr->typePtr->translateProc((Tk_Canvas) canvasPtr, itemPtr,
+ xDelta, yDelta);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CanvasObjCmd --
+ *
+ * This function is invoked to process the "canvas" 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_CanvasObjCmd(
+ ClientData clientData, /* Main window associated with interpreter. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ Tcl_Obj *const argv[]) /* Argument objects. */
+{
+ Tk_Window tkwin = clientData;
+ TkCanvas *canvasPtr;
+ Tk_Window newWin;
+
+ if (typeList == NULL) {
+ InitCanvas();
+ }
+
+ if (argc < 2) {
+ Tcl_WrongNumArgs(interp, 1, argv, "pathName ?-option value ...?");
+ return TCL_ERROR;
+ }
+
+ newWin = Tk_CreateWindowFromPath(interp,tkwin,Tcl_GetString(argv[1]),NULL);
+ if (newWin == NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Initialize fields that won't be initialized by ConfigureCanvas, or
+ * which ConfigureCanvas expects to have reasonable values (e.g. resource
+ * pointers).
+ */
+
+ canvasPtr = ckalloc(sizeof(TkCanvas));
+ canvasPtr->tkwin = newWin;
+ canvasPtr->display = Tk_Display(newWin);
+ canvasPtr->interp = interp;
+ canvasPtr->widgetCmd = Tcl_CreateObjCommand(interp,
+ Tk_PathName(canvasPtr->tkwin), CanvasWidgetCmd, canvasPtr,
+ CanvasCmdDeletedProc);
+ canvasPtr->firstItemPtr = NULL;
+ canvasPtr->lastItemPtr = NULL;
+ canvasPtr->borderWidth = 0;
+ canvasPtr->bgBorder = NULL;
+ canvasPtr->relief = TK_RELIEF_FLAT;
+ canvasPtr->highlightWidth = 0;
+ canvasPtr->highlightBgColorPtr = NULL;
+ canvasPtr->highlightColorPtr = NULL;
+ canvasPtr->inset = 0;
+ canvasPtr->pixmapGC = NULL;
+ canvasPtr->width = None;
+ canvasPtr->height = None;
+ canvasPtr->confine = 0;
+ canvasPtr->textInfo.selBorder = NULL;
+ canvasPtr->textInfo.selBorderWidth = 0;
+ canvasPtr->textInfo.selFgColorPtr = NULL;
+ canvasPtr->textInfo.selItemPtr = NULL;
+ canvasPtr->textInfo.selectFirst = -1;
+ canvasPtr->textInfo.selectLast = -1;
+ canvasPtr->textInfo.anchorItemPtr = NULL;
+ canvasPtr->textInfo.selectAnchor = 0;
+ canvasPtr->textInfo.insertBorder = NULL;
+ canvasPtr->textInfo.insertWidth = 0;
+ canvasPtr->textInfo.insertBorderWidth = 0;
+ canvasPtr->textInfo.focusItemPtr = NULL;
+ canvasPtr->textInfo.gotFocus = 0;
+ canvasPtr->textInfo.cursorOn = 0;
+ canvasPtr->insertOnTime = 0;
+ canvasPtr->insertOffTime = 0;
+ canvasPtr->insertBlinkHandler = NULL;
+ canvasPtr->xOrigin = canvasPtr->yOrigin = 0;
+ canvasPtr->drawableXOrigin = canvasPtr->drawableYOrigin = 0;
+ canvasPtr->bindingTable = NULL;
+ canvasPtr->currentItemPtr = NULL;
+ canvasPtr->newCurrentPtr = NULL;
+ canvasPtr->closeEnough = 0.0;
+ canvasPtr->pickEvent.type = LeaveNotify;
+ canvasPtr->pickEvent.xcrossing.x = 0;
+ canvasPtr->pickEvent.xcrossing.y = 0;
+ canvasPtr->state = 0;
+ canvasPtr->xScrollCmd = NULL;
+ canvasPtr->yScrollCmd = NULL;
+ canvasPtr->scrollX1 = 0;
+ canvasPtr->scrollY1 = 0;
+ canvasPtr->scrollX2 = 0;
+ canvasPtr->scrollY2 = 0;
+ canvasPtr->regionString = NULL;
+ canvasPtr->xScrollIncrement = 0;
+ canvasPtr->yScrollIncrement = 0;
+ canvasPtr->scanX = 0;
+ canvasPtr->scanXOrigin = 0;
+ canvasPtr->scanY = 0;
+ canvasPtr->scanYOrigin = 0;
+ canvasPtr->hotPtr = NULL;
+ canvasPtr->hotPrevPtr = NULL;
+ canvasPtr->cursor = NULL;
+ canvasPtr->takeFocus = NULL;
+ canvasPtr->pixelsPerMM = WidthOfScreen(Tk_Screen(newWin));
+ canvasPtr->pixelsPerMM /= WidthMMOfScreen(Tk_Screen(newWin));
+ canvasPtr->flags = 0;
+ canvasPtr->nextId = 1;
+ canvasPtr->psInfo = NULL;
+ canvasPtr->canvas_state = TK_STATE_NORMAL;
+ canvasPtr->tsoffset.flags = 0;
+ canvasPtr->tsoffset.xoffset = 0;
+ canvasPtr->tsoffset.yoffset = 0;
+#ifndef USE_OLD_TAG_SEARCH
+ canvasPtr->bindTagExprs = NULL;
+#endif
+ Tcl_InitHashTable(&canvasPtr->idTable, TCL_ONE_WORD_KEYS);
+
+ Tk_SetClass(canvasPtr->tkwin, "Canvas");
+ Tk_SetClassProcs(canvasPtr->tkwin, &canvasClass, canvasPtr);
+ Tk_CreateEventHandler(canvasPtr->tkwin,
+ ExposureMask|StructureNotifyMask|FocusChangeMask,
+ CanvasEventProc, canvasPtr);
+ Tk_CreateEventHandler(canvasPtr->tkwin, KeyPressMask|KeyReleaseMask
+ |ButtonPressMask|ButtonReleaseMask|EnterWindowMask
+ |LeaveWindowMask|PointerMotionMask|VirtualEventMask,
+ CanvasBindProc, canvasPtr);
+ Tk_CreateSelHandler(canvasPtr->tkwin, XA_PRIMARY, XA_STRING,
+ CanvasFetchSelection, canvasPtr, XA_STRING);
+ if (ConfigureCanvas(interp, canvasPtr, argc-2, argv+2, 0) != TCL_OK) {
+ goto error;
+ }
+
+ Tcl_SetObjResult(interp, TkNewWindowObj(canvasPtr->tkwin));
+ return TCL_OK;
+
+ error:
+ Tk_DestroyWindow(canvasPtr->tkwin);
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * CanvasWidgetCmd --
+ *
+ * This function is invoked to process the Tcl command that corresponds
+ * to a widget managed by this module. See the user documentation for
+ * details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+CanvasWidgetCmd(
+ ClientData clientData, /* Information about canvas widget. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ TkCanvas *canvasPtr = clientData;
+ int c, result;
+ Tk_Item *itemPtr = NULL; /* Initialization needed only to prevent
+ * compiler warning. */
+#ifdef USE_OLD_TAG_SEARCH
+ TagSearch search;
+#else /* USE_OLD_TAG_SEARCH */
+ TagSearch *searchPtr = NULL;/* Allocated by first TagSearchScan, freed by
+ * TagSearchDestroy */
+#endif /* USE_OLD_TAG_SEARCH */
+
+ int index;
+ static const char *const optionStrings[] = {
+ "addtag", "bbox", "bind", "canvasx",
+ "canvasy", "cget", "configure", "coords",
+ "create", "dchars", "delete", "dtag",
+ "find", "focus", "gettags", "icursor",
+ "imove", "index", "insert", "itemcget",
+ "itemconfigure",
+ "lower", "move", "moveto", "postscript",
+ "raise", "rchars", "scale", "scan",
+ "select", "type", "xview", "yview",
+ NULL
+ };
+ enum options {
+ CANV_ADDTAG, CANV_BBOX, CANV_BIND, CANV_CANVASX,
+ CANV_CANVASY, CANV_CGET, CANV_CONFIGURE, CANV_COORDS,
+ CANV_CREATE, CANV_DCHARS, CANV_DELETE, CANV_DTAG,
+ CANV_FIND, CANV_FOCUS, CANV_GETTAGS, CANV_ICURSOR,
+ CANV_IMOVE, CANV_INDEX, CANV_INSERT, CANV_ITEMCGET,
+ CANV_ITEMCONFIGURE,
+ CANV_LOWER, CANV_MOVE, CANV_MOVETO, CANV_POSTSCRIPT,
+ CANV_RAISE, CANV_RCHARS, CANV_SCALE, CANV_SCAN,
+ CANV_SELECT, CANV_TYPE, CANV_XVIEW, CANV_YVIEW
+ };
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_Preserve(canvasPtr);
+
+ result = TCL_OK;
+ switch ((enum options) index) {
+ case CANV_ADDTAG:
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "tag searchCommand ?arg ...?");
+ result = TCL_ERROR;
+ goto done;
+ }
+ result = FIND_ITEMS(objv[2], 3);
+ break;
+
+ case CANV_BBOX: {
+ int i, gotAny;
+ int x1 = 0, y1 = 0, x2 = 0, y2 = 0; /* Initializations needed only
+ * to prevent overcautious
+ * compiler warnings. */
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "tagOrId ?tagOrId ...?");
+ result = TCL_ERROR;
+ goto done;
+ }
+ gotAny = 0;
+ for (i = 2; i < objc; i++) {
+ FOR_EVERY_CANVAS_ITEM_MATCHING(objv[i], &searchPtr, goto done) {
+ if ((itemPtr->x1 >= itemPtr->x2)
+ || (itemPtr->y1 >= itemPtr->y2)) {
+ continue;
+ }
+ if (!gotAny) {
+ x1 = itemPtr->x1;
+ y1 = itemPtr->y1;
+ x2 = itemPtr->x2;
+ y2 = itemPtr->y2;
+ gotAny = 1;
+ } else {
+ if (itemPtr->x1 < x1) {
+ x1 = itemPtr->x1;
+ }
+ if (itemPtr->y1 < y1) {
+ y1 = itemPtr->y1;
+ }
+ if (itemPtr->x2 > x2) {
+ x2 = itemPtr->x2;
+ }
+ if (itemPtr->y2 > y2) {
+ y2 = itemPtr->y2;
+ }
+ }
+ }
+ }
+ if (gotAny) {
+ Tcl_Obj *resultObjs[4];
+
+ resultObjs[0] = Tcl_NewIntObj(x1);
+ resultObjs[1] = Tcl_NewIntObj(y1);
+ resultObjs[2] = Tcl_NewIntObj(x2);
+ resultObjs[3] = Tcl_NewIntObj(y2);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(4, resultObjs));
+ }
+ break;
+ }
+ case CANV_BIND: {
+ ClientData object;
+
+ if ((objc < 3) || (objc > 5)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "tagOrId ?sequence? ?command?");
+ result = TCL_ERROR;
+ goto done;
+ }
+
+ /*
+ * Figure out what object to use for the binding (individual item vs.
+ * tag).
+ */
+
+ object = NULL;
+#ifdef USE_OLD_TAG_SEARCH
+ if (isdigit(UCHAR(Tcl_GetString(objv[2])[0]))) {
+ int id;
+ char *end;
+ Tcl_HashEntry *entryPtr;
+
+ id = strtoul(Tcl_GetString(objv[2]), &end, 0);
+ if (*end != 0) {
+ goto bindByTag;
+ }
+ entryPtr = Tcl_FindHashEntry(&canvasPtr->idTable, (char *) id);
+ if (entryPtr != NULL) {
+ itemPtr = Tcl_GetHashValue(entryPtr);
+ object = itemPtr;
+ }
+
+ if (object == NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "item \"%s\" doesn't exist", Tcl_GetString(objv[2])));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "CANVAS_ITEM",
+ Tcl_GetString(objv[2]), NULL);
+ result = TCL_ERROR;
+ goto done;
+ }
+ } else {
+ bindByTag:
+ object = Tk_GetUid(Tcl_GetString(objv[2]));
+ }
+#else /* USE_OLD_TAG_SEARCH */
+ result = TagSearchScan(canvasPtr, objv[2], &searchPtr);
+ if (result != TCL_OK) {
+ goto done;
+ }
+ if (searchPtr->type == SEARCH_TYPE_ID) {
+ Tcl_HashEntry *entryPtr;
+
+ entryPtr = Tcl_FindHashEntry(&canvasPtr->idTable,
+ (char *) INT2PTR(searchPtr->id));
+ if (entryPtr != NULL) {
+ itemPtr = Tcl_GetHashValue(entryPtr);
+ object = itemPtr;
+ }
+
+ if (object == 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "item \"%s\" doesn't exist", Tcl_GetString(objv[2])));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "CANVAS_ITEM",
+ Tcl_GetString(objv[2]), NULL);
+ result = TCL_ERROR;
+ goto done;
+ }
+ } else {
+ object = (ClientData) searchPtr->expr->uid;
+ }
+#endif /* USE_OLD_TAG_SEARCH */
+
+ /*
+ * Make a binding table if the canvas doesn't already have one.
+ */
+
+ if (canvasPtr->bindingTable == NULL) {
+ canvasPtr->bindingTable = Tk_CreateBindingTable(interp);
+ }
+
+ if (objc == 5) {
+ int append = 0;
+ unsigned long mask;
+ const char *argv4 = Tcl_GetString(objv[4]);
+
+ if (argv4[0] == 0) {
+ result = Tk_DeleteBinding(interp, canvasPtr->bindingTable,
+ object, Tcl_GetString(objv[3]));
+ goto done;
+ }
+#ifndef USE_OLD_TAG_SEARCH
+ if (searchPtr->type == SEARCH_TYPE_EXPR) {
+ /*
+ * If new tag expression, then insert in linked list.
+ */
+
+ TagSearchExpr *expr, **lastPtr;
+
+ lastPtr = &(canvasPtr->bindTagExprs);
+ while ((expr = *lastPtr) != NULL) {
+ if (expr->uid == searchPtr->expr->uid) {
+ break;
+ }
+ lastPtr = &(expr->next);
+ }
+ if (!expr) {
+ /*
+ * Transfer ownership of expr to bindTagExprs list.
+ */
+
+ *lastPtr = searchPtr->expr;
+ searchPtr->expr->next = NULL;
+
+ /*
+ * Flag in TagSearch that expr has changed ownership so
+ * that TagSearchDestroy doesn't try to free it.
+ */
+
+ searchPtr->expr = NULL;
+ }
+ }
+#endif /* not USE_OLD_TAG_SEARCH */
+ if (argv4[0] == '+') {
+ argv4++;
+ append = 1;
+ }
+ mask = Tk_CreateBinding(interp, canvasPtr->bindingTable,
+ object, Tcl_GetString(objv[3]), argv4, append);
+ if (mask == 0) {
+ result = TCL_ERROR;
+ goto done;
+ }
+ if (mask & (unsigned) ~(ButtonMotionMask|Button1MotionMask
+ |Button2MotionMask|Button3MotionMask|Button4MotionMask
+ |Button5MotionMask|ButtonPressMask|ButtonReleaseMask
+ |EnterWindowMask|LeaveWindowMask|KeyPressMask
+ |KeyReleaseMask|PointerMotionMask|VirtualEventMask)) {
+ Tk_DeleteBinding(interp, canvasPtr->bindingTable,
+ object, Tcl_GetString(objv[3]));
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "requested illegal events; only key, button, motion,"
+ " enter, leave, and virtual events may be used", -1));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "BAD_EVENTS", NULL);
+ result = TCL_ERROR;
+ goto done;
+ }
+ } else if (objc == 4) {
+ const char *command;
+
+ command = Tk_GetBinding(interp, canvasPtr->bindingTable,
+ object, Tcl_GetString(objv[3]));
+ if (command == NULL) {
+ const char *string = Tcl_GetString(Tcl_GetObjResult(interp));
+
+ /*
+ * Ignore missing binding errors. This is a special hack that
+ * relies on the error message returned by FindSequence in
+ * tkBind.c.
+ */
+
+ if (string[0] != '\0') {
+ result = TCL_ERROR;
+ goto done;
+ }
+ Tcl_ResetResult(interp);
+ } else {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(command, -1));
+ }
+ } else {
+ Tk_GetAllBindings(interp, canvasPtr->bindingTable, object);
+ }
+ break;
+ }
+ case CANV_CANVASX: {
+ int x;
+ double grid;
+
+ if ((objc < 3) || (objc > 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "screenx ?gridspacing?");
+ result = TCL_ERROR;
+ goto done;
+ }
+ if (Tk_GetPixelsFromObj(interp, canvasPtr->tkwin, objv[2],
+ &x) != TCL_OK) {
+ result = TCL_ERROR;
+ goto done;
+ }
+ if (objc == 4) {
+ if (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr,
+ objv[3], &grid) != TCL_OK) {
+ result = TCL_ERROR;
+ goto done;
+ }
+ } else {
+ grid = 0.0;
+ }
+ x += canvasPtr->xOrigin;
+ Tcl_SetObjResult(interp, Tcl_NewDoubleObj(GridAlign((double)x,grid)));
+ break;
+ }
+ case CANV_CANVASY: {
+ int y;
+ double grid;
+
+ if ((objc < 3) || (objc > 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "screeny ?gridspacing?");
+ result = TCL_ERROR;
+ goto done;
+ }
+ if (Tk_GetPixelsFromObj(interp, canvasPtr->tkwin, objv[2],
+ &y) != TCL_OK) {
+ result = TCL_ERROR;
+ goto done;
+ }
+ if (objc == 4) {
+ if (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr,
+ objv[3], &grid) != TCL_OK) {
+ result = TCL_ERROR;
+ goto done;
+ }
+ } else {
+ grid = 0.0;
+ }
+ y += canvasPtr->yOrigin;
+ Tcl_SetObjResult(interp, Tcl_NewDoubleObj(GridAlign((double)y,grid)));
+ break;
+ }
+ case CANV_CGET:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option");
+ result = TCL_ERROR;
+ goto done;
+ }
+ result = Tk_ConfigureValue(interp, canvasPtr->tkwin, configSpecs,
+ (char *) canvasPtr, Tcl_GetString(objv[2]), 0);
+ break;
+ case CANV_CONFIGURE:
+ if (objc == 2) {
+ result = Tk_ConfigureInfo(interp, canvasPtr->tkwin, configSpecs,
+ (char *) canvasPtr, NULL, 0);
+ } else if (objc == 3) {
+ result = Tk_ConfigureInfo(interp, canvasPtr->tkwin, configSpecs,
+ (char *) canvasPtr, Tcl_GetString(objv[2]), 0);
+ } else {
+ result = ConfigureCanvas(interp, canvasPtr, objc-2, objv+2,
+ TK_CONFIG_ARGV_ONLY);
+ }
+ break;
+ case CANV_COORDS:
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "tagOrId ?x y x y ...?");
+ result = TCL_ERROR;
+ goto done;
+ }
+ FIRST_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done);
+ if (itemPtr != NULL) {
+ if (objc != 3) {
+ EventuallyRedrawItem(canvasPtr, itemPtr);
+ }
+ result = ItemCoords(canvasPtr, itemPtr, objc-3, objv+3);
+ if (objc != 3) {
+ EventuallyRedrawItem(canvasPtr, itemPtr);
+ }
+ }
+ break;
+ case CANV_IMOVE: {
+ double ignored;
+ Tcl_Obj *tmpObj;
+
+ if (objc != 6) {
+ Tcl_WrongNumArgs(interp, 2, objv, "tagOrId index x y");
+ result = TCL_ERROR;
+ goto done;
+ }
+ if (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr,
+ objv[4], &ignored) != TCL_OK
+ || Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr,
+ objv[5], &ignored) != TCL_OK) {
+ result = TCL_ERROR;
+ goto done;
+ }
+
+ /*
+ * Make a temporary object here that we can reuse for all the
+ * modifications in the loop.
+ */
+
+ tmpObj = Tcl_NewListObj(2, objv+4);
+
+ FOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto doneImove) {
+ int index;
+ int x1, x2, y1, y2;
+ int dontRedraw1, dontRedraw2;
+
+ /*
+ * The TK_MOVABLE_POINTS flag should only be set for types that
+ * support the same semantics of index, dChars and insert methods
+ * as lines and canvases.
+ */
+
+ if (itemPtr == NULL ||
+ !(itemPtr->typePtr->alwaysRedraw & TK_MOVABLE_POINTS)) {
+ continue;
+ }
+
+ result = ItemIndex(canvasPtr, itemPtr, objv[3], &index);
+ if (result != TCL_OK) {
+ break;
+ }
+
+ /*
+ * Redraw both item's old and new areas: it's possible that a
+ * replace could result in a new area larger than the old area.
+ * Except if the dCharsProc or insertProc sets the
+ * TK_ITEM_DONT_REDRAW flag, nothing more needs to be done.
+ */
+
+ x1 = itemPtr->x1; y1 = itemPtr->y1;
+ x2 = itemPtr->x2; y2 = itemPtr->y2;
+
+ itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW;
+ ItemDelChars(canvasPtr, itemPtr, index, index);
+ dontRedraw1 = itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW;
+
+ itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW;
+ ItemInsert(canvasPtr, itemPtr, index, tmpObj);
+ dontRedraw2 = itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW;
+
+ if (!(dontRedraw1 && dontRedraw2)) {
+ Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
+ x1, y1, x2, y2);
+ EventuallyRedrawItem(canvasPtr, itemPtr);
+ }
+ itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW;
+ }
+
+ doneImove:
+ Tcl_DecrRefCount(tmpObj);
+ break;
+ }
+ case CANV_CREATE: {
+ Tk_ItemType *typePtr;
+ Tk_ItemType *matchPtr = NULL;
+ Tk_Item *itemPtr;
+ int isNew = 0;
+ Tcl_HashEntry *entryPtr;
+ const char *arg;
+ size_t length;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "type coords ?arg ...?");
+ result = TCL_ERROR;
+ goto done;
+ }
+ arg = Tcl_GetString(objv[2]);
+ length = objv[2]->length;
+ c = arg[0];
+
+ /*
+ * Lock because the list of types is a global resource that could be
+ * updated by another thread. That's fairly unlikely, but not
+ * impossible.
+ */
+
+ Tcl_MutexLock(&typeListMutex);
+ for (typePtr = typeList; typePtr != NULL; typePtr = typePtr->nextPtr){
+ if ((c == typePtr->name[0])
+ && (!strncmp(arg, typePtr->name, length))) {
+ if (matchPtr != NULL) {
+ Tcl_MutexUnlock(&typeListMutex);
+ goto badType;
+ }
+ matchPtr = typePtr;
+ }
+ }
+
+ /*
+ * Can unlock now because we no longer look at the fields of the
+ * matched item type that are potentially modified by other threads.
+ */
+
+ Tcl_MutexUnlock(&typeListMutex);
+ if (matchPtr == NULL) {
+ badType:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "unknown or ambiguous item type \"%s\"", arg));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "CANVAS_ITEM_TYPE", arg,
+ NULL);
+ result = TCL_ERROR;
+ goto done;
+ }
+ if (objc < 4) {
+ /*
+ * Allow more specific error return.
+ */
+
+ Tcl_WrongNumArgs(interp, 3, objv, "coords ?arg ...?");
+ result = TCL_ERROR;
+ goto done;
+ }
+
+ typePtr = matchPtr;
+ itemPtr = ckalloc(typePtr->itemSize);
+ itemPtr->id = canvasPtr->nextId;
+ canvasPtr->nextId++;
+ itemPtr->tagPtr = itemPtr->staticTagSpace;
+ itemPtr->tagSpace = TK_TAG_SPACE;
+ itemPtr->numTags = 0;
+ itemPtr->typePtr = typePtr;
+ itemPtr->state = TK_STATE_NULL;
+ itemPtr->redraw_flags = 0;
+
+ if (ItemCreate(canvasPtr, itemPtr, objc, objv) != TCL_OK) {
+ ckfree(itemPtr);
+ result = TCL_ERROR;
+ goto done;
+ }
+
+ itemPtr->nextPtr = NULL;
+ entryPtr = Tcl_CreateHashEntry(&canvasPtr->idTable,
+ (char *) INT2PTR(itemPtr->id), &isNew);
+ Tcl_SetHashValue(entryPtr, itemPtr);
+ itemPtr->prevPtr = canvasPtr->lastItemPtr;
+ canvasPtr->hotPtr = itemPtr;
+ canvasPtr->hotPrevPtr = canvasPtr->lastItemPtr;
+ if (canvasPtr->lastItemPtr == NULL) {
+ canvasPtr->firstItemPtr = itemPtr;
+ } else {
+ canvasPtr->lastItemPtr->nextPtr = itemPtr;
+ }
+ canvasPtr->lastItemPtr = itemPtr;
+ itemPtr->redraw_flags |= FORCE_REDRAW;
+ EventuallyRedrawItem(canvasPtr, itemPtr);
+ canvasPtr->flags |= REPICK_NEEDED;
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(itemPtr->id));
+ break;
+ }
+ case CANV_DCHARS: {
+ int first, last;
+ int x1, x2, y1, y2;
+
+ if ((objc != 4) && (objc != 5)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "tagOrId first ?last?");
+ result = TCL_ERROR;
+ goto done;
+ }
+ FOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) {
+ if ((itemPtr->typePtr->indexProc == NULL)
+ || (itemPtr->typePtr->dCharsProc == NULL)) {
+ continue;
+ }
+ result = ItemIndex(canvasPtr, itemPtr, objv[3], &first);
+ if (result != TCL_OK) {
+ goto done;
+ }
+ if (objc == 5) {
+ result = ItemIndex(canvasPtr, itemPtr, objv[4], &last);
+ if (result != TCL_OK) {
+ goto done;
+ }
+ } else {
+ last = first;
+ }
+
+ /*
+ * Redraw both item's old and new areas: it's possible that a
+ * delete could result in a new area larger than the old area.
+ * Except if the dCharsProc sets the TK_ITEM_DONT_REDRAW flag,
+ * nothing more needs to be done.
+ */
+
+ x1 = itemPtr->x1; y1 = itemPtr->y1;
+ x2 = itemPtr->x2; y2 = itemPtr->y2;
+ itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW;
+ ItemDelChars(canvasPtr, itemPtr, first, last);
+ if (!(itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW)) {
+ Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
+ x1, y1, x2, y2);
+ EventuallyRedrawItem(canvasPtr, itemPtr);
+ }
+ itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW;
+ }
+ break;
+ }
+ case CANV_DELETE: {
+ int i;
+ Tcl_HashEntry *entryPtr;
+
+ for (i = 2; i < objc; i++) {
+ FOR_EVERY_CANVAS_ITEM_MATCHING(objv[i], &searchPtr, goto done) {
+ EventuallyRedrawItem(canvasPtr, itemPtr);
+ if (canvasPtr->bindingTable != NULL) {
+ Tk_DeleteAllBindings(canvasPtr->bindingTable, itemPtr);
+ }
+ ItemDelete(canvasPtr, itemPtr);
+ if (itemPtr->tagPtr != itemPtr->staticTagSpace) {
+ ckfree(itemPtr->tagPtr);
+ }
+ entryPtr = Tcl_FindHashEntry(&canvasPtr->idTable,
+ (char *) INT2PTR(itemPtr->id));
+ Tcl_DeleteHashEntry(entryPtr);
+ if (itemPtr->nextPtr != NULL) {
+ itemPtr->nextPtr->prevPtr = itemPtr->prevPtr;
+ }
+ if (itemPtr->prevPtr != NULL) {
+ itemPtr->prevPtr->nextPtr = itemPtr->nextPtr;
+ }
+ if (canvasPtr->firstItemPtr == itemPtr) {
+ canvasPtr->firstItemPtr = itemPtr->nextPtr;
+ if (canvasPtr->firstItemPtr == NULL) {
+ canvasPtr->lastItemPtr = NULL;
+ }
+ }
+ if (canvasPtr->lastItemPtr == itemPtr) {
+ canvasPtr->lastItemPtr = itemPtr->prevPtr;
+ }
+ ckfree(itemPtr);
+ if (itemPtr == canvasPtr->currentItemPtr) {
+ canvasPtr->currentItemPtr = NULL;
+ canvasPtr->flags |= REPICK_NEEDED;
+ }
+ if (itemPtr == canvasPtr->newCurrentPtr) {
+ canvasPtr->newCurrentPtr = NULL;
+ canvasPtr->flags |= REPICK_NEEDED;
+ }
+ if (itemPtr == canvasPtr->textInfo.focusItemPtr) {
+ canvasPtr->textInfo.focusItemPtr = NULL;
+ }
+ if (itemPtr == canvasPtr->textInfo.selItemPtr) {
+ canvasPtr->textInfo.selItemPtr = NULL;
+ }
+ if ((itemPtr == canvasPtr->hotPtr)
+ || (itemPtr == canvasPtr->hotPrevPtr)) {
+ canvasPtr->hotPtr = NULL;
+ }
+ }
+ }
+ break;
+ }
+ case CANV_DTAG: {
+ Tk_Uid tag;
+ int i;
+
+ if ((objc != 3) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "tagOrId ?tagToDelete?");
+ result = TCL_ERROR;
+ goto done;
+ }
+ if (objc == 4) {
+ tag = Tk_GetUid(Tcl_GetString(objv[3]));
+ } else {
+ tag = Tk_GetUid(Tcl_GetString(objv[2]));
+ }
+ FOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) {
+ for (i = itemPtr->numTags-1; i >= 0; i--) {
+ if (itemPtr->tagPtr[i] == tag) {
+ itemPtr->tagPtr[i] = itemPtr->tagPtr[itemPtr->numTags-1];
+ itemPtr->numTags--;
+ }
+ }
+ }
+ break;
+ }
+ case CANV_FIND:
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "searchCommand ?arg ...?");
+ result = TCL_ERROR;
+ goto done;
+ }
+ result = FIND_ITEMS(NULL, 2);
+ break;
+ case CANV_FOCUS:
+ if (objc > 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?tagOrId?");
+ result = TCL_ERROR;
+ goto done;
+ }
+ itemPtr = canvasPtr->textInfo.focusItemPtr;
+ if (objc == 2) {
+ if (itemPtr != NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(itemPtr->id));
+ }
+ goto done;
+ }
+ if (canvasPtr->textInfo.gotFocus) {
+ EventuallyRedrawItem(canvasPtr, itemPtr);
+ }
+ if (Tcl_GetString(objv[2])[0] == 0) {
+ canvasPtr->textInfo.focusItemPtr = NULL;
+ goto done;
+ }
+ FOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) {
+ if (itemPtr->typePtr->icursorProc != NULL) {
+ break;
+ }
+ }
+ if (itemPtr == NULL) {
+ goto done;
+ }
+ canvasPtr->textInfo.focusItemPtr = itemPtr;
+ if (canvasPtr->textInfo.gotFocus) {
+ EventuallyRedrawItem(canvasPtr, itemPtr);
+ }
+ break;
+ case CANV_GETTAGS:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "tagOrId");
+ result = TCL_ERROR;
+ goto done;
+ }
+ FIRST_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done);
+ if (itemPtr != NULL) {
+ int i;
+ Tcl_Obj *resultObj = Tcl_NewObj();
+
+ for (i = 0; i < itemPtr->numTags; i++) {
+ Tcl_ListObjAppendElement(NULL, resultObj,
+ Tcl_NewStringObj(itemPtr->tagPtr[i], -1));
+ }
+ Tcl_SetObjResult(interp, resultObj);
+ }
+ break;
+ case CANV_ICURSOR: {
+ int index;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "tagOrId index");
+ result = TCL_ERROR;
+ goto done;
+ }
+ FOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) {
+ if ((itemPtr->typePtr->indexProc == NULL)
+ || (itemPtr->typePtr->icursorProc == NULL)) {
+ goto done;
+ }
+ result = ItemIndex(canvasPtr, itemPtr, objv[3], &index);
+ if (result != TCL_OK) {
+ goto done;
+ }
+ ItemCursor(canvasPtr, itemPtr, index);
+ if ((itemPtr == canvasPtr->textInfo.focusItemPtr)
+ && (canvasPtr->textInfo.cursorOn)) {
+ EventuallyRedrawItem(canvasPtr, itemPtr);
+ }
+ }
+ break;
+ }
+ case CANV_INDEX: {
+ int index;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "tagOrId string");
+ result = TCL_ERROR;
+ goto done;
+ }
+ FOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) {
+ if (itemPtr->typePtr->indexProc != NULL) {
+ break;
+ }
+ }
+ if (itemPtr == NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't find an indexable item \"%s\"",
+ Tcl_GetString(objv[2])));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "INDEXABLE_ITEM", NULL);
+ result = TCL_ERROR;
+ goto done;
+ }
+ result = ItemIndex(canvasPtr, itemPtr, objv[3], &index);
+ if (result != TCL_OK) {
+ goto done;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(index));
+ break;
+ }
+ case CANV_INSERT: {
+ int beforeThis;
+ int x1, x2, y1, y2;
+
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 2, objv, "tagOrId beforeThis string");
+ result = TCL_ERROR;
+ goto done;
+ }
+ FOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) {
+ if ((itemPtr->typePtr->indexProc == NULL)
+ || (itemPtr->typePtr->insertProc == NULL)) {
+ continue;
+ }
+ result = ItemIndex(canvasPtr, itemPtr, objv[3], &beforeThis);
+ if (result != TCL_OK) {
+ goto done;
+ }
+
+ /*
+ * Redraw both item's old and new areas: it's possible that an
+ * insertion could result in a new area either larger or smaller
+ * than the old area. Except if the insertProc sets the
+ * TK_ITEM_DONT_REDRAW flag, nothing more needs to be done.
+ */
+
+ x1 = itemPtr->x1; y1 = itemPtr->y1;
+ x2 = itemPtr->x2; y2 = itemPtr->y2;
+ itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW;
+ ItemInsert(canvasPtr, itemPtr, beforeThis, objv[4]);
+ if (!(itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW)) {
+ Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
+ x1, y1, x2, y2);
+ EventuallyRedrawItem(canvasPtr, itemPtr);
+ }
+ itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW;
+ }
+ break;
+ }
+ case CANV_ITEMCGET:
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "tagOrId option");
+ result = TCL_ERROR;
+ goto done;
+ }
+ FIRST_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done);
+ if (itemPtr != NULL) {
+ result = ItemConfigValue(canvasPtr, itemPtr, objv[3]);
+ }
+ break;
+ case CANV_ITEMCONFIGURE:
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "tagOrId ?-option value ...?");
+ result = TCL_ERROR;
+ goto done;
+ }
+ FOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) {
+ if (objc == 3) {
+ result = ItemConfigInfo(canvasPtr, itemPtr, NULL);
+ } else if (objc == 4) {
+ result = ItemConfigInfo(canvasPtr, itemPtr, objv[3]);
+ } else {
+ EventuallyRedrawItem(canvasPtr, itemPtr);
+ result = ItemConfigure(canvasPtr, itemPtr, objc-3, objv+3);
+ EventuallyRedrawItem(canvasPtr, itemPtr);
+ canvasPtr->flags |= REPICK_NEEDED;
+ }
+ if ((result != TCL_OK) || (objc < 5)) {
+ break;
+ }
+ }
+ break;
+ case CANV_LOWER: {
+ Tk_Item *itemPtr;
+
+ if ((objc != 3) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "tagOrId ?belowThis?");
+ result = TCL_ERROR;
+ goto done;
+ }
+
+ /*
+ * First find the item just after which we'll insert the named items.
+ */
+
+ if (objc == 3) {
+ itemPtr = NULL;
+ } else {
+ FIRST_CANVAS_ITEM_MATCHING(objv[3], &searchPtr, goto done);
+ if (itemPtr == NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "tagOrId \"%s\" doesn't match any items",
+ Tcl_GetString(objv[3])));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "ITEM", NULL);
+ result = TCL_ERROR;
+ goto done;
+ }
+ itemPtr = itemPtr->prevPtr;
+ }
+ RELINK_ITEMS(objv[2], itemPtr);
+ break;
+ }
+ case CANV_MOVE: {
+ double xAmount, yAmount;
+
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 2, objv, "tagOrId xAmount yAmount");
+ result = TCL_ERROR;
+ goto done;
+ }
+ if ((Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr, objv[3],
+ &xAmount) != TCL_OK) || (Tk_CanvasGetCoordFromObj(interp,
+ (Tk_Canvas) canvasPtr, objv[4], &yAmount) != TCL_OK)) {
+ result = TCL_ERROR;
+ goto done;
+ }
+ FOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) {
+ EventuallyRedrawItem(canvasPtr, itemPtr);
+ ItemTranslate(canvasPtr, itemPtr, xAmount, yAmount);
+ EventuallyRedrawItem(canvasPtr, itemPtr);
+ canvasPtr->flags |= REPICK_NEEDED;
+ }
+ break;
+ }
+ case CANV_MOVETO: {
+ int xBlank, yBlank;
+ double xAmount, yAmount;
+ double oldX = 0, oldY = 0, newX, newY;
+
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 2, objv, "tagOrId x y");
+ result = TCL_ERROR;
+ goto done;
+ }
+
+ xBlank = 0;
+ if (Tcl_GetString(objv[3])[0] == '\0') {
+ xBlank = 1;
+ } else if (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr,
+ objv[3], &newX) != TCL_OK) {
+ result = TCL_ERROR;
+ goto done;
+ }
+
+ yBlank = 0;
+ if (Tcl_GetString(objv[4])[0] == '\0') {
+ yBlank = 1;
+ } else if (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr,
+ objv[4], &newY) != TCL_OK) {
+ result = TCL_ERROR;
+ goto done;
+ }
+
+ FIRST_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done);
+ if (itemPtr != NULL) {
+ oldX = itemPtr->x1;
+ oldY = itemPtr->y1;
+
+ /*
+ * Calculate the displacement.
+ */
+
+ if (xBlank) {
+ xAmount = 0;
+ } else {
+ xAmount = newX - oldX;
+ }
+
+ if (yBlank) {
+ yAmount = 0;
+ } else {
+ yAmount = newY - oldY;
+ }
+
+ /*
+ * Move the object(s).
+ */
+
+ FOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) {
+ EventuallyRedrawItem(canvasPtr, itemPtr);
+ ItemTranslate(canvasPtr, itemPtr, xAmount, yAmount);
+ EventuallyRedrawItem(canvasPtr, itemPtr);
+ canvasPtr->flags |= REPICK_NEEDED;
+ }
+ }
+ break;
+ }
+ case CANV_POSTSCRIPT: {
+ const char **args = TkGetStringsFromObjs(objc, objv);
+
+ result = TkCanvPostscriptCmd(canvasPtr, interp, objc, args);
+ if (args != NULL) {
+ ckfree(args);
+ }
+ break;
+ }
+ case CANV_RAISE: {
+ Tk_Item *prevPtr;
+
+ if ((objc != 3) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "tagOrId ?aboveThis?");
+ result = TCL_ERROR;
+ goto done;
+ }
+
+ /*
+ * First find the item just after which we'll insert the named items.
+ */
+
+ if (objc == 3) {
+ prevPtr = canvasPtr->lastItemPtr;
+ } else {
+ prevPtr = NULL;
+ FOR_EVERY_CANVAS_ITEM_MATCHING(objv[3], &searchPtr, goto done) {
+ prevPtr = itemPtr;
+ }
+ if (prevPtr == NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "tagOrId \"%s\" doesn't match any items",
+ Tcl_GetString(objv[3])));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "ITEM", NULL);
+ result = TCL_ERROR;
+ goto done;
+ }
+ }
+ RELINK_ITEMS(objv[2], prevPtr);
+ break;
+ }
+ case CANV_RCHARS: {
+ int first, last;
+ int x1, x2, y1, y2;
+ int dontRedraw1, dontRedraw2;
+
+ if (objc != 6) {
+ Tcl_WrongNumArgs(interp, 2, objv, "tagOrId first last string");
+ result = TCL_ERROR;
+ goto done;
+ }
+ FOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) {
+ if ((itemPtr->typePtr->indexProc == NULL)
+ || (itemPtr->typePtr->dCharsProc == NULL)
+ || (itemPtr->typePtr->insertProc == NULL)) {
+ continue;
+ }
+ result = ItemIndex(canvasPtr, itemPtr, objv[3], &first);
+ if (result != TCL_OK) {
+ goto done;
+ }
+ result = ItemIndex(canvasPtr, itemPtr, objv[4], &last);
+ if (result != TCL_OK) {
+ goto done;
+ }
+
+ /*
+ * Redraw both item's old and new areas: it's possible that a
+ * replace could result in a new area larger than the old area.
+ * Except if the dCharsProc or insertProc sets the
+ * TK_ITEM_DONT_REDRAW flag, nothing more needs to be done.
+ */
+
+ x1 = itemPtr->x1; y1 = itemPtr->y1;
+ x2 = itemPtr->x2; y2 = itemPtr->y2;
+
+ itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW;
+ ItemDelChars(canvasPtr, itemPtr, first, last);
+ dontRedraw1 = itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW;
+
+ itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW;
+ ItemInsert(canvasPtr, itemPtr, first, objv[5]);
+ dontRedraw2 = itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW;
+
+ if (!(dontRedraw1 && dontRedraw2)) {
+ Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
+ x1, y1, x2, y2);
+ EventuallyRedrawItem(canvasPtr, itemPtr);
+ }
+ itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW;
+ }
+ break;
+ }
+ case CANV_SCALE: {
+ double xOrigin, yOrigin, xScale, yScale;
+
+ if (objc != 7) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "tagOrId xOrigin yOrigin xScale yScale");
+ result = TCL_ERROR;
+ goto done;
+ }
+ if ((Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr,
+ objv[3], &xOrigin) != TCL_OK)
+ || (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr,
+ objv[4], &yOrigin) != TCL_OK)
+ || (Tcl_GetDoubleFromObj(interp, objv[5], &xScale)!=TCL_OK)
+ || (Tcl_GetDoubleFromObj(interp, objv[6], &yScale)!=TCL_OK)) {
+ result = TCL_ERROR;
+ goto done;
+ }
+ if ((xScale == 0.0) || (yScale == 0.0)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "scale factor cannot be zero", -1));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "BAD_SCALE", NULL);
+ result = TCL_ERROR;
+ goto done;
+ }
+ FOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) {
+ EventuallyRedrawItem(canvasPtr, itemPtr);
+ ItemScale(canvasPtr, itemPtr, xOrigin, yOrigin, xScale, yScale);
+ EventuallyRedrawItem(canvasPtr, itemPtr);
+ canvasPtr->flags |= REPICK_NEEDED;
+ }
+ break;
+ }
+ case CANV_SCAN: {
+ int x, y, gain = 10;
+ static const char *const optionStrings[] = {
+ "mark", "dragto", NULL
+ };
+
+ if (objc < 5) {
+ Tcl_WrongNumArgs(interp, 2, objv, "mark|dragto x y ?dragGain?");
+ result = TCL_ERROR;
+ } else if (Tcl_GetIndexFromObj(interp, objv[2], optionStrings,
+ "scan option", 0, &index) != TCL_OK) {
+ result = TCL_ERROR;
+ } else if ((objc != 5) && (objc != 5+index)) {
+ Tcl_WrongNumArgs(interp, 3, objv, index?"x y ?gain?":"x y");
+ result = TCL_ERROR;
+ } else if ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)){
+ result = TCL_ERROR;
+ } else if ((objc == 6) &&
+ (Tcl_GetIntFromObj(interp, objv[5], &gain) != TCL_OK)) {
+ result = TCL_ERROR;
+ } else if (!index) {
+ canvasPtr->scanX = x;
+ canvasPtr->scanXOrigin = canvasPtr->xOrigin;
+ canvasPtr->scanY = y;
+ canvasPtr->scanYOrigin = canvasPtr->yOrigin;
+ } else {
+ int newXOrigin, newYOrigin, tmp;
+
+ /*
+ * Compute a new view origin for the canvas, amplifying the
+ * mouse motion.
+ */
+
+ tmp = canvasPtr->scanXOrigin - gain*(x - canvasPtr->scanX)
+ - canvasPtr->scrollX1;
+ newXOrigin = canvasPtr->scrollX1 + tmp;
+ tmp = canvasPtr->scanYOrigin - gain*(y - canvasPtr->scanY)
+ - canvasPtr->scrollY1;
+ newYOrigin = canvasPtr->scrollY1 + tmp;
+ CanvasSetOrigin(canvasPtr, newXOrigin, newYOrigin);
+ }
+ break;
+ }
+ case CANV_SELECT: {
+ int index, optionindex;
+ static const char *const optionStrings[] = {
+ "adjust", "clear", "from", "item", "to", NULL
+ };
+ enum options {
+ CANV_ADJUST, CANV_CLEAR, CANV_FROM, CANV_ITEM, CANV_TO
+ };
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option ?tagOrId? ?arg?");
+ result = TCL_ERROR;
+ goto done;
+ }
+ if (objc >= 4) {
+ FOR_EVERY_CANVAS_ITEM_MATCHING(objv[3], &searchPtr, goto done) {
+ if ((itemPtr->typePtr->indexProc != NULL)
+ && (itemPtr->typePtr->selectionProc != NULL)){
+ break;
+ }
+ }
+ if (itemPtr == NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't find an indexable and selectable item \"%s\"",
+ Tcl_GetString(objv[3])));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "SELECTABLE_ITEM",
+ NULL);
+ result = TCL_ERROR;
+ goto done;
+ }
+ }
+ if (objc == 5) {
+ result = ItemIndex(canvasPtr, itemPtr, objv[4], &index);
+ if (result != TCL_OK) {
+ goto done;
+ }
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[2], optionStrings,
+ "select option", 0, &optionindex) != TCL_OK) {
+ result = TCL_ERROR;
+ goto done;
+ }
+ switch ((enum options) optionindex) {
+ case CANV_ADJUST:
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 3, objv, "tagOrId index");
+ result = TCL_ERROR;
+ goto done;
+ }
+ if (canvasPtr->textInfo.selItemPtr == itemPtr) {
+ if (index < (canvasPtr->textInfo.selectFirst
+ + canvasPtr->textInfo.selectLast)/2) {
+ canvasPtr->textInfo.selectAnchor =
+ canvasPtr->textInfo.selectLast + 1;
+ } else {
+ canvasPtr->textInfo.selectAnchor =
+ canvasPtr->textInfo.selectFirst;
+ }
+ }
+ CanvasSelectTo(canvasPtr, itemPtr, index);
+ break;
+ case CANV_CLEAR:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ result = TCL_ERROR;
+ goto done;
+ }
+ EventuallyRedrawItem(canvasPtr, canvasPtr->textInfo.selItemPtr);
+ canvasPtr->textInfo.selItemPtr = NULL;
+ break;
+ case CANV_FROM:
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 3, objv, "tagOrId index");
+ result = TCL_ERROR;
+ goto done;
+ }
+ canvasPtr->textInfo.anchorItemPtr = itemPtr;
+ canvasPtr->textInfo.selectAnchor = index;
+ break;
+ case CANV_ITEM:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ result = TCL_ERROR;
+ goto done;
+ }
+ if (canvasPtr->textInfo.selItemPtr != NULL) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewIntObj(canvasPtr->textInfo.selItemPtr->id));
+ }
+ break;
+ case CANV_TO:
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 2, objv, "tagOrId index");
+ result = TCL_ERROR;
+ goto done;
+ }
+ CanvasSelectTo(canvasPtr, itemPtr, index);
+ break;
+ }
+ break;
+ }
+ case CANV_TYPE:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "tag");
+ result = TCL_ERROR;
+ goto done;
+ }
+ FIRST_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done);
+ if (itemPtr != NULL) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj(itemPtr->typePtr->name, -1));
+ }
+ break;
+ case CANV_XVIEW: {
+ int count, type;
+ int newX = 0; /* Initialization needed only to prevent gcc
+ * warnings. */
+ double fraction;
+ const char **args;
+
+ if (objc == 2) {
+ Tcl_SetObjResult(interp, ScrollFractions(
+ canvasPtr->xOrigin + canvasPtr->inset,
+ canvasPtr->xOrigin + Tk_Width(canvasPtr->tkwin)
+ - canvasPtr->inset, canvasPtr->scrollX1,
+ canvasPtr->scrollX2));
+ break;
+ }
+
+ args = TkGetStringsFromObjs(objc, objv);
+ type = Tk_GetScrollInfo(interp, objc, args, &fraction, &count);
+ if (args != NULL) {
+ ckfree(args);
+ }
+ switch (type) {
+ case TK_SCROLL_ERROR:
+ result = TCL_ERROR;
+ goto done;
+ case TK_SCROLL_MOVETO:
+ newX = canvasPtr->scrollX1 - canvasPtr->inset
+ + (int) (fraction * (canvasPtr->scrollX2
+ - canvasPtr->scrollX1) + 0.5);
+ break;
+ case TK_SCROLL_PAGES:
+ newX = (int) (canvasPtr->xOrigin + count * .9
+ * (Tk_Width(canvasPtr->tkwin) - 2*canvasPtr->inset));
+ break;
+ case TK_SCROLL_UNITS:
+ if (canvasPtr->xScrollIncrement > 0) {
+ newX = canvasPtr->xOrigin + count*canvasPtr->xScrollIncrement;
+ } else {
+ newX = (int) (canvasPtr->xOrigin + count * .1
+ * (Tk_Width(canvasPtr->tkwin) - 2*canvasPtr->inset));
+ }
+ break;
+ }
+ CanvasSetOrigin(canvasPtr, newX, canvasPtr->yOrigin);
+ break;
+ }
+ case CANV_YVIEW: {
+ int count, type;
+ int newY = 0; /* Initialization needed only to prevent gcc
+ * warnings. */
+ double fraction;
+ const char **args;
+
+ if (objc == 2) {
+ Tcl_SetObjResult(interp, ScrollFractions(
+ canvasPtr->yOrigin + canvasPtr->inset,
+ canvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin)
+ - canvasPtr->inset,
+ canvasPtr->scrollY1, canvasPtr->scrollY2));
+ break;
+ }
+
+ args = TkGetStringsFromObjs(objc, objv);
+ type = Tk_GetScrollInfo(interp, objc, args, &fraction, &count);
+ if (args != NULL) {
+ ckfree(args);
+ }
+ switch (type) {
+ case TK_SCROLL_ERROR:
+ result = TCL_ERROR;
+ goto done;
+ case TK_SCROLL_MOVETO:
+ newY = canvasPtr->scrollY1 - canvasPtr->inset + (int) (
+ fraction*(canvasPtr->scrollY2-canvasPtr->scrollY1) + 0.5);
+ break;
+ case TK_SCROLL_PAGES:
+ newY = (int) (canvasPtr->yOrigin + count * .9
+ * (Tk_Height(canvasPtr->tkwin) - 2*canvasPtr->inset));
+ break;
+ case TK_SCROLL_UNITS:
+ if (canvasPtr->yScrollIncrement > 0) {
+ newY = canvasPtr->yOrigin + count*canvasPtr->yScrollIncrement;
+ } else {
+ newY = (int) (canvasPtr->yOrigin + count * .1
+ * (Tk_Height(canvasPtr->tkwin) - 2*canvasPtr->inset));
+ }
+ break;
+ }
+ CanvasSetOrigin(canvasPtr, canvasPtr->xOrigin, newY);
+ break;
+ }
+ }
+
+ done:
+#ifndef USE_OLD_TAG_SEARCH
+ TagSearchDestroy(searchPtr);
+#endif /* not USE_OLD_TAG_SEARCH */
+ Tcl_Release(canvasPtr);
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyCanvas --
+ *
+ * This function is invoked by Tcl_EventuallyFree or Tcl_Release to clean
+ * up the internal structure of a canvas at a safe time (when no-one is
+ * using it anymore).
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Everything associated with the canvas is freed up.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DestroyCanvas(
+ char *memPtr) /* Info about canvas widget. */
+{
+ TkCanvas *canvasPtr = (TkCanvas *) memPtr;
+ Tk_Item *itemPtr;
+#ifndef USE_OLD_TAG_SEARCH
+ TagSearchExpr *expr, *next;
+#endif
+
+ /*
+ * Free up all of the items in the canvas.
+ */
+
+ for (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;
+ itemPtr = canvasPtr->firstItemPtr) {
+ canvasPtr->firstItemPtr = itemPtr->nextPtr;
+ ItemDelete(canvasPtr, itemPtr);
+ if (itemPtr->tagPtr != itemPtr->staticTagSpace) {
+ ckfree(itemPtr->tagPtr);
+ }
+ ckfree(itemPtr);
+ }
+
+ /*
+ * Free up all the stuff that requires special handling, then let
+ * Tk_FreeOptions handle all the standard option-related stuff.
+ */
+
+ Tcl_DeleteHashTable(&canvasPtr->idTable);
+ if (canvasPtr->pixmapGC != NULL) {
+ Tk_FreeGC(canvasPtr->display, canvasPtr->pixmapGC);
+ }
+#ifndef USE_OLD_TAG_SEARCH
+ expr = canvasPtr->bindTagExprs;
+ while (expr) {
+ next = expr->next;
+ TagSearchExprDestroy(expr);
+ expr = next;
+ }
+#endif /* USE_OLD_TAG_SEARCH */
+ Tcl_DeleteTimerHandler(canvasPtr->insertBlinkHandler);
+ if (canvasPtr->bindingTable != NULL) {
+ Tk_DeleteBindingTable(canvasPtr->bindingTable);
+ }
+ Tk_FreeOptions(configSpecs, (char *) canvasPtr, canvasPtr->display, 0);
+ canvasPtr->tkwin = NULL;
+ ckfree(canvasPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConfigureCanvas --
+ *
+ * This function is called to process an objv/objc list, plus the Tk
+ * option database, in order to configure (or reconfigure) a canvas
+ * widget.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If TCL_ERROR is returned,
+ * then the interp's result contains an error message.
+ *
+ * Side effects:
+ * Configuration information, such as colors, border width, etc. get set
+ * for canvasPtr; old resources get freed, if there were any.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ConfigureCanvas(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ TkCanvas *canvasPtr, /* Information about widget; may or may not
+ * already have values for some fields. */
+ int objc, /* Number of valid entries in objv. */
+ Tcl_Obj *const objv[], /* Argument objects. */
+ int flags) /* Flags to pass to Tk_ConfigureWidget. */
+{
+ XGCValues gcValues;
+ GC newGC;
+ Tk_State old_canvas_state=canvasPtr->canvas_state;
+
+ if (Tk_ConfigureWidget(interp, canvasPtr->tkwin, configSpecs,
+ objc, (const char **) objv, (char *) canvasPtr,
+ flags|TK_CONFIG_OBJS) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * A few options need special processing, such as setting the background
+ * from a 3-D border and creating a GC for copying bits to the screen.
+ */
+
+ Tk_SetBackgroundFromBorder(canvasPtr->tkwin, canvasPtr->bgBorder);
+
+ if (canvasPtr->highlightWidth < 0) {
+ canvasPtr->highlightWidth = 0;
+ }
+ canvasPtr->inset = canvasPtr->borderWidth + canvasPtr->highlightWidth;
+
+ gcValues.function = GXcopy;
+ gcValues.graphics_exposures = False;
+ gcValues.foreground = Tk_3DBorderColor(canvasPtr->bgBorder)->pixel;
+ newGC = Tk_GetGC(canvasPtr->tkwin,
+ GCFunction|GCGraphicsExposures|GCForeground, &gcValues);
+ if (canvasPtr->pixmapGC != NULL) {
+ Tk_FreeGC(canvasPtr->display, canvasPtr->pixmapGC);
+ }
+ canvasPtr->pixmapGC = newGC;
+
+ /*
+ * Reconfigure items to reflect changed state disabled/normal.
+ */
+
+ if ( old_canvas_state != canvasPtr->canvas_state ) {
+ Tk_Item *itemPtr;
+ int result;
+
+ for ( itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;
+ itemPtr = itemPtr->nextPtr) {
+ if ( itemPtr->state == TK_STATE_NULL ) {
+ result = (*itemPtr->typePtr->configProc)(canvasPtr->interp,
+ (Tk_Canvas) canvasPtr, itemPtr, 0, NULL,
+ TK_CONFIG_ARGV_ONLY);
+ if (result != TCL_OK) {
+ Tcl_ResetResult(canvasPtr->interp);
+ }
+ }
+ }
+ }
+
+ /*
+ * Reset the desired dimensions for the window.
+ */
+
+ Tk_GeometryRequest(canvasPtr->tkwin, canvasPtr->width + 2*canvasPtr->inset,
+ canvasPtr->height + 2*canvasPtr->inset);
+
+ /*
+ * Restart the cursor timing sequence in case the on-time or off-time just
+ * changed.
+ */
+
+ if (canvasPtr->textInfo.gotFocus) {
+ CanvasFocusProc(canvasPtr, 1);
+ }
+
+ /*
+ * Recompute the scroll region.
+ */
+
+ canvasPtr->scrollX1 = 0;
+ canvasPtr->scrollY1 = 0;
+ canvasPtr->scrollX2 = 0;
+ canvasPtr->scrollY2 = 0;
+ if (canvasPtr->regionString != NULL) {
+ int argc2;
+ const char **argv2;
+
+ if (Tcl_SplitList(canvasPtr->interp, canvasPtr->regionString,
+ &argc2, &argv2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (argc2 != 4) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad scrollRegion \"%s\"", canvasPtr->regionString));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "SCROLL_REGION", NULL);
+ badRegion:
+ ckfree(canvasPtr->regionString);
+ ckfree(argv2);
+ canvasPtr->regionString = NULL;
+ return TCL_ERROR;
+ }
+ if ((Tk_GetPixels(canvasPtr->interp, canvasPtr->tkwin,
+ argv2[0], &canvasPtr->scrollX1) != TCL_OK)
+ || (Tk_GetPixels(canvasPtr->interp, canvasPtr->tkwin,
+ argv2[1], &canvasPtr->scrollY1) != TCL_OK)
+ || (Tk_GetPixels(canvasPtr->interp, canvasPtr->tkwin,
+ argv2[2], &canvasPtr->scrollX2) != TCL_OK)
+ || (Tk_GetPixels(canvasPtr->interp, canvasPtr->tkwin,
+ argv2[3], &canvasPtr->scrollY2) != TCL_OK)) {
+ goto badRegion;
+ }
+ ckfree(argv2);
+ }
+
+ flags = canvasPtr->tsoffset.flags;
+ if (flags & TK_OFFSET_LEFT) {
+ canvasPtr->tsoffset.xoffset = 0;
+ } else if (flags & TK_OFFSET_CENTER) {
+ canvasPtr->tsoffset.xoffset = canvasPtr->width/2;
+ } else if (flags & TK_OFFSET_RIGHT) {
+ canvasPtr->tsoffset.xoffset = canvasPtr->width;
+ }
+ if (flags & TK_OFFSET_TOP) {
+ canvasPtr->tsoffset.yoffset = 0;
+ } else if (flags & TK_OFFSET_MIDDLE) {
+ canvasPtr->tsoffset.yoffset = canvasPtr->height/2;
+ } else if (flags & TK_OFFSET_BOTTOM) {
+ canvasPtr->tsoffset.yoffset = canvasPtr->height;
+ }
+
+ /*
+ * Reset the canvas's origin (this is a no-op unless confine mode has just
+ * been turned on or the scroll region has changed).
+ */
+
+ CanvasSetOrigin(canvasPtr, canvasPtr->xOrigin, canvasPtr->yOrigin);
+ canvasPtr->flags |= UPDATE_SCROLLBARS|REDRAW_BORDERS;
+ Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
+ canvasPtr->xOrigin, canvasPtr->yOrigin,
+ canvasPtr->xOrigin + Tk_Width(canvasPtr->tkwin),
+ canvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CanvasWorldChanged --
+ *
+ * This function is called when the world has changed in some way and the
+ * widget needs to recompute all its graphics contexts and determine its
+ * new geometry.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Configures all items in the canvas with a empty argc/argv, for the
+ * side effect of causing all the items to recompute their geometry and
+ * to be redisplayed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+CanvasWorldChanged(
+ ClientData instanceData) /* Information about widget. */
+{
+ TkCanvas *canvasPtr = instanceData;
+ Tk_Item *itemPtr;
+
+ itemPtr = canvasPtr->firstItemPtr;
+ for ( ; itemPtr != NULL; itemPtr = itemPtr->nextPtr) {
+ if (ItemConfigure(canvasPtr, itemPtr, 0, NULL) != TCL_OK) {
+ Tcl_ResetResult(canvasPtr->interp);
+ }
+ }
+ canvasPtr->flags |= REPICK_NEEDED;
+ Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
+ canvasPtr->xOrigin, canvasPtr->yOrigin,
+ canvasPtr->xOrigin + Tk_Width(canvasPtr->tkwin),
+ canvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin));
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DisplayCanvas --
+ *
+ * This function redraws the contents of a canvas 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DisplayCanvas(
+ ClientData clientData) /* Information about widget. */
+{
+ TkCanvas *canvasPtr = clientData;
+ Tk_Window tkwin = canvasPtr->tkwin;
+ Tk_Item *itemPtr;
+ Pixmap pixmap;
+ int screenX1, screenX2, screenY1, screenY2, width, height;
+
+ if (canvasPtr->tkwin == NULL) {
+ return;
+ }
+
+ if (!Tk_IsMapped(tkwin)) {
+ goto done;
+ }
+
+#ifdef MAC_OSX_TK
+ /*
+ * If drawing is disabled, all we need to do is
+ * clear the REDRAW_PENDING flag.
+ */
+ TkWindow *winPtr = (TkWindow *)(canvasPtr->tkwin);
+ MacDrawable *macWin = winPtr->privatePtr;
+ if (macWin && (macWin->flags & TK_DO_NOT_DRAW)){
+ canvasPtr->flags &= ~REDRAW_PENDING;
+ return;
+ }
+#endif
+
+ /*
+ * Choose a new current item if that is needed (this could cause event
+ * handlers to be invoked).
+ */
+
+ while (canvasPtr->flags & REPICK_NEEDED) {
+ Tcl_Preserve(canvasPtr);
+ canvasPtr->flags &= ~REPICK_NEEDED;
+ PickCurrentItem(canvasPtr, &canvasPtr->pickEvent);
+ tkwin = canvasPtr->tkwin;
+ Tcl_Release(canvasPtr);
+ if (tkwin == NULL) {
+ return;
+ }
+ }
+
+ /*
+ * Scan through the item list, registering the bounding box for all items
+ * that didn't do that for the final coordinates yet. This can be
+ * determined by the FORCE_REDRAW flag.
+ */
+
+ for (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;
+ itemPtr = itemPtr->nextPtr) {
+ if (itemPtr->redraw_flags & FORCE_REDRAW) {
+ itemPtr->redraw_flags &= ~FORCE_REDRAW;
+ EventuallyRedrawItem(canvasPtr, itemPtr);
+ itemPtr->redraw_flags &= ~FORCE_REDRAW;
+ }
+ }
+
+ /*
+ * Compute the intersection between the area that needs redrawing and the
+ * area that's visible on the screen.
+ */
+
+ if ((canvasPtr->redrawX1 < canvasPtr->redrawX2)
+ && (canvasPtr->redrawY1 < canvasPtr->redrawY2)) {
+ screenX1 = canvasPtr->xOrigin + canvasPtr->inset;
+ screenY1 = canvasPtr->yOrigin + canvasPtr->inset;
+ screenX2 = canvasPtr->xOrigin + Tk_Width(tkwin) - canvasPtr->inset;
+ screenY2 = canvasPtr->yOrigin + Tk_Height(tkwin) - canvasPtr->inset;
+ if (canvasPtr->redrawX1 > screenX1) {
+ screenX1 = canvasPtr->redrawX1;
+ }
+ if (canvasPtr->redrawY1 > screenY1) {
+ screenY1 = canvasPtr->redrawY1;
+ }
+ if (canvasPtr->redrawX2 < screenX2) {
+ screenX2 = canvasPtr->redrawX2;
+ }
+ if (canvasPtr->redrawY2 < screenY2) {
+ screenY2 = canvasPtr->redrawY2;
+ }
+ if ((screenX1 >= screenX2) || (screenY1 >= screenY2)) {
+ goto borders;
+ }
+
+ width = screenX2 - screenX1;
+ height = screenY2 - screenY1;
+
+#ifndef TK_NO_DOUBLE_BUFFERING
+ /*
+ * Redrawing is done in a temporary pixmap that is allocated here and
+ * freed at the end of the function. All drawing is done to the
+ * pixmap, and the pixmap is copied to the screen at the end of the
+ * function. The temporary pixmap serves two purposes:
+ *
+ * 1. It provides a smoother visual effect (no clearing and gradual
+ * redraw will be visible to users).
+ * 2. It allows us to redraw only the objects that overlap the redraw
+ * area. Otherwise incorrect results could occur from redrawing
+ * things that stick outside of the redraw area (we'd have to
+ * redraw everything in order to make the overlaps look right).
+ *
+ * Some tricky points about the pixmap:
+ *
+ * 1. We only allocate a large enough pixmap to hold the area that has
+ * to be redisplayed. This saves time in in the X server for large
+ * objects that cover much more than the area being redisplayed:
+ * only the area of the pixmap will actually have to be redrawn.
+ * 2. Some X servers (e.g. the one for DECstations) have troubles with
+ * with characters that overlap an edge of the pixmap (on the DEC
+ * servers, as of 8/18/92, such characters are drawn one pixel too
+ * far to the right). To handle this problem, make the pixmap a bit
+ * larger than is absolutely needed so that for normal-sized fonts
+ * the characters that overlap the edge of the pixmap will be
+ * outside the area we care about.
+ */
+
+ canvasPtr->drawableXOrigin = screenX1 - 30;
+ canvasPtr->drawableYOrigin = screenY1 - 30;
+ pixmap = Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin),
+ (screenX2 + 30 - canvasPtr->drawableXOrigin),
+ (screenY2 + 30 - canvasPtr->drawableYOrigin),
+ Tk_Depth(tkwin));
+#else
+ canvasPtr->drawableXOrigin = canvasPtr->xOrigin;
+ canvasPtr->drawableYOrigin = canvasPtr->yOrigin;
+ pixmap = Tk_WindowId(tkwin);
+ TkpClipDrawableToRect(Tk_Display(tkwin), pixmap,
+ screenX1 - canvasPtr->xOrigin, screenY1 - canvasPtr->yOrigin,
+ width, height);
+#endif /* TK_NO_DOUBLE_BUFFERING */
+
+ /*
+ * Clear the area to be redrawn.
+ */
+
+ XFillRectangle(Tk_Display(tkwin), pixmap, canvasPtr->pixmapGC,
+ screenX1 - canvasPtr->drawableXOrigin,
+ screenY1 - canvasPtr->drawableYOrigin, (unsigned int) width,
+ (unsigned int) height);
+
+ /*
+ * Scan through the item list, redrawing those items that need it. An
+ * item must be redraw if either (a) it intersects the smaller
+ * on-screen area or (b) it intersects the full canvas area and its
+ * type requests that it be redrawn always (e.g. so subwindows can be
+ * unmapped when they move off-screen).
+ */
+
+ for (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;
+ itemPtr = itemPtr->nextPtr) {
+ if ((itemPtr->x1 >= screenX2)
+ || (itemPtr->y1 >= screenY2)
+ || (itemPtr->x2 < screenX1)
+ || (itemPtr->y2 < screenY1)) {
+ if (!AlwaysRedraw(itemPtr)
+ || (itemPtr->x1 >= canvasPtr->redrawX2)
+ || (itemPtr->y1 >= canvasPtr->redrawY2)
+ || (itemPtr->x2 < canvasPtr->redrawX1)
+ || (itemPtr->y2 < canvasPtr->redrawY1)) {
+ continue;
+ }
+ }
+ if (itemPtr->state == TK_STATE_HIDDEN ||
+ (itemPtr->state == TK_STATE_NULL &&
+ canvasPtr->canvas_state == TK_STATE_HIDDEN)) {
+ continue;
+ }
+ ItemDisplay(canvasPtr, itemPtr, pixmap, screenX1, screenY1, width,
+ height);
+ }
+
+#ifndef TK_NO_DOUBLE_BUFFERING
+ /*
+ * Copy from the temporary pixmap to the screen, then free up the
+ * temporary pixmap.
+ */
+
+ XCopyArea(Tk_Display(tkwin), pixmap, Tk_WindowId(tkwin),
+ canvasPtr->pixmapGC,
+ screenX1 - canvasPtr->drawableXOrigin,
+ screenY1 - canvasPtr->drawableYOrigin,
+ (unsigned int) width, (unsigned int) height,
+ screenX1 - canvasPtr->xOrigin, screenY1 - canvasPtr->yOrigin);
+ Tk_FreePixmap(Tk_Display(tkwin), pixmap);
+#else
+ TkpClipDrawableToRect(Tk_Display(tkwin), pixmap, 0, 0, -1, -1);
+#endif /* TK_NO_DOUBLE_BUFFERING */
+ }
+
+ /*
+ * Draw the window borders, if needed.
+ */
+
+ borders:
+ if (canvasPtr->flags & REDRAW_BORDERS) {
+ canvasPtr->flags &= ~REDRAW_BORDERS;
+ if (canvasPtr->borderWidth > 0) {
+ Tk_Draw3DRectangle(tkwin, Tk_WindowId(tkwin),
+ canvasPtr->bgBorder, canvasPtr->highlightWidth,
+ canvasPtr->highlightWidth,
+ Tk_Width(tkwin) - 2*canvasPtr->highlightWidth,
+ Tk_Height(tkwin) - 2*canvasPtr->highlightWidth,
+ canvasPtr->borderWidth, canvasPtr->relief);
+ }
+ if (canvasPtr->highlightWidth != 0) {
+ GC fgGC, bgGC;
+
+ bgGC = Tk_GCForColor(canvasPtr->highlightBgColorPtr,
+ Tk_WindowId(tkwin));
+ if (canvasPtr->textInfo.gotFocus) {
+ fgGC = Tk_GCForColor(canvasPtr->highlightColorPtr,
+ Tk_WindowId(tkwin));
+ TkpDrawHighlightBorder(tkwin, fgGC, bgGC,
+ canvasPtr->highlightWidth, Tk_WindowId(tkwin));
+ } else {
+ TkpDrawHighlightBorder(tkwin, bgGC, bgGC,
+ canvasPtr->highlightWidth, Tk_WindowId(tkwin));
+ }
+ }
+ }
+
+ done:
+ canvasPtr->flags &= ~(REDRAW_PENDING|BBOX_NOT_EMPTY);
+ canvasPtr->redrawX1 = canvasPtr->redrawX2 = 0;
+ canvasPtr->redrawY1 = canvasPtr->redrawY2 = 0;
+ if (canvasPtr->flags & UPDATE_SCROLLBARS) {
+ CanvasUpdateScrollbars(canvasPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CanvasEventProc --
+ *
+ * This function is invoked by the Tk dispatcher for various events on
+ * canvases.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * When the window gets deleted, internal structures get cleaned up. When
+ * it gets exposed, it is redisplayed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+CanvasEventProc(
+ ClientData clientData, /* Information about window. */
+ XEvent *eventPtr) /* Information about event. */
+{
+ TkCanvas *canvasPtr = clientData;
+
+ if (eventPtr->type == Expose) {
+ int x, y;
+
+ x = eventPtr->xexpose.x + canvasPtr->xOrigin;
+ y = eventPtr->xexpose.y + canvasPtr->yOrigin;
+ Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr, x, y,
+ x + eventPtr->xexpose.width,
+ y + eventPtr->xexpose.height);
+ if ((eventPtr->xexpose.x < canvasPtr->inset)
+ || (eventPtr->xexpose.y < canvasPtr->inset)
+ || ((eventPtr->xexpose.x + eventPtr->xexpose.width)
+ > (Tk_Width(canvasPtr->tkwin) - canvasPtr->inset))
+ || ((eventPtr->xexpose.y + eventPtr->xexpose.height)
+ > (Tk_Height(canvasPtr->tkwin) - canvasPtr->inset))) {
+ canvasPtr->flags |= REDRAW_BORDERS;
+ }
+ } else if (eventPtr->type == DestroyNotify) {
+ if (canvasPtr->tkwin != NULL) {
+ canvasPtr->tkwin = NULL;
+ Tcl_DeleteCommandFromToken(canvasPtr->interp,
+ canvasPtr->widgetCmd);
+ }
+ if (canvasPtr->flags & REDRAW_PENDING) {
+ Tcl_CancelIdleCall(DisplayCanvas, canvasPtr);
+ }
+ Tcl_EventuallyFree(canvasPtr, (Tcl_FreeProc *) DestroyCanvas);
+ } else if (eventPtr->type == ConfigureNotify) {
+ canvasPtr->flags |= UPDATE_SCROLLBARS;
+
+ /*
+ * The call below is needed in order to recenter the canvas if it's
+ * confined and its scroll region is smaller than the window.
+ */
+
+ CanvasSetOrigin(canvasPtr, canvasPtr->xOrigin, canvasPtr->yOrigin);
+ Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr, canvasPtr->xOrigin,
+ canvasPtr->yOrigin,
+ canvasPtr->xOrigin + Tk_Width(canvasPtr->tkwin),
+ canvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin));
+ canvasPtr->flags |= REDRAW_BORDERS;
+ } else if (eventPtr->type == FocusIn) {
+ if (eventPtr->xfocus.detail != NotifyInferior) {
+ CanvasFocusProc(canvasPtr, 1);
+ }
+ } else if (eventPtr->type == FocusOut) {
+ if (eventPtr->xfocus.detail != NotifyInferior) {
+ CanvasFocusProc(canvasPtr, 0);
+ }
+ } else if (eventPtr->type == UnmapNotify) {
+ Tk_Item *itemPtr;
+
+ /*
+ * Special hack: if the canvas is unmapped, then must notify all items
+ * with "alwaysRedraw" set, so that they know that they are no longer
+ * displayed.
+ */
+
+ for (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;
+ itemPtr = itemPtr->nextPtr) {
+ if (AlwaysRedraw(itemPtr)) {
+ ItemDisplay(canvasPtr, itemPtr, None, 0, 0, 0, 0);
+ }
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CanvasCmdDeletedProc --
+ *
+ * This function is invoked when a widget command is deleted. If the
+ * widget isn't already in the process of being destroyed, this command
+ * destroys it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The widget is destroyed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+CanvasCmdDeletedProc(
+ ClientData clientData) /* Pointer to widget record for widget. */
+{
+ TkCanvas *canvasPtr = clientData;
+ Tk_Window tkwin = canvasPtr->tkwin;
+
+ /*
+ * This function could be invoked either because the window was destroyed
+ * and the command was then deleted (in which case tkwin is NULL) or
+ * because the command was deleted, and then this function destroys the
+ * widget.
+ */
+
+ if (tkwin != NULL) {
+ canvasPtr->tkwin = NULL;
+ Tk_DestroyWindow(tkwin);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_CanvasEventuallyRedraw --
+ *
+ * Arrange for part or all of a canvas widget to redrawn at some
+ * convenient time in the future.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The screen will eventually be refreshed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_CanvasEventuallyRedraw(
+ Tk_Canvas canvas, /* Information about widget. */
+ int x1, int y1, /* Upper left corner of area to redraw. Pixels
+ * on edge are redrawn. */
+ int x2, int y2) /* Lower right corner of area to redraw.
+ * Pixels on edge are not redrawn. */
+{
+ TkCanvas *canvasPtr = Canvas(canvas);
+
+ /*
+ * If tkwin is NULL, the canvas has been destroyed, so we can't really
+ * redraw it.
+ */
+
+ if (canvasPtr->tkwin == NULL) {
+ return;
+ }
+
+ if ((x1 >= x2) || (y1 >= y2) ||
+ (x2 < canvasPtr->xOrigin) || (y2 < canvasPtr->yOrigin) ||
+ (x1 >= canvasPtr->xOrigin + Tk_Width(canvasPtr->tkwin)) ||
+ (y1 >= canvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin))) {
+ return;
+ }
+ if (canvasPtr->flags & BBOX_NOT_EMPTY) {
+ if (x1 <= canvasPtr->redrawX1) {
+ canvasPtr->redrawX1 = x1;
+ }
+ if (y1 <= canvasPtr->redrawY1) {
+ canvasPtr->redrawY1 = y1;
+ }
+ if (x2 >= canvasPtr->redrawX2) {
+ canvasPtr->redrawX2 = x2;
+ }
+ if (y2 >= canvasPtr->redrawY2) {
+ canvasPtr->redrawY2 = y2;
+ }
+ } else {
+ canvasPtr->redrawX1 = x1;
+ canvasPtr->redrawY1 = y1;
+ canvasPtr->redrawX2 = x2;
+ canvasPtr->redrawY2 = y2;
+ canvasPtr->flags |= BBOX_NOT_EMPTY;
+ }
+ if (!(canvasPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DisplayCanvas, canvasPtr);
+ canvasPtr->flags |= REDRAW_PENDING;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EventuallyRedrawItem --
+ *
+ * Arrange for part or all of a canvas widget to redrawn at some
+ * convenient time in the future.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The screen will eventually be refreshed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+EventuallyRedrawItem(
+ TkCanvas *canvasPtr, /* Information about widget. */
+ Tk_Item *itemPtr) /* Item to be redrawn. May be NULL, in which
+ * case nothing happens. */
+{
+ if (itemPtr == NULL) {
+ return;
+ }
+ if ((itemPtr->x1 >= itemPtr->x2) || (itemPtr->y1 >= itemPtr->y2) ||
+ (itemPtr->x2 < canvasPtr->xOrigin) ||
+ (itemPtr->y2 < canvasPtr->yOrigin) ||
+ (itemPtr->x1 >= canvasPtr->xOrigin+Tk_Width(canvasPtr->tkwin)) ||
+ (itemPtr->y1 >= canvasPtr->yOrigin+Tk_Height(canvasPtr->tkwin))) {
+ if (!AlwaysRedraw(itemPtr)) {
+ return;
+ }
+ }
+ if (!(itemPtr->redraw_flags & FORCE_REDRAW)) {
+ if (canvasPtr->flags & BBOX_NOT_EMPTY) {
+ if (itemPtr->x1 <= canvasPtr->redrawX1) {
+ canvasPtr->redrawX1 = itemPtr->x1;
+ }
+ if (itemPtr->y1 <= canvasPtr->redrawY1) {
+ canvasPtr->redrawY1 = itemPtr->y1;
+ }
+ if (itemPtr->x2 >= canvasPtr->redrawX2) {
+ canvasPtr->redrawX2 = itemPtr->x2;
+ }
+ if (itemPtr->y2 >= canvasPtr->redrawY2) {
+ canvasPtr->redrawY2 = itemPtr->y2;
+ }
+ } else {
+ canvasPtr->redrawX1 = itemPtr->x1;
+ canvasPtr->redrawY1 = itemPtr->y1;
+ canvasPtr->redrawX2 = itemPtr->x2;
+ canvasPtr->redrawY2 = itemPtr->y2;
+ canvasPtr->flags |= BBOX_NOT_EMPTY;
+ }
+ itemPtr->redraw_flags |= FORCE_REDRAW;
+ }
+ if (!(canvasPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DisplayCanvas, canvasPtr);
+ canvasPtr->flags |= REDRAW_PENDING;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_CreateItemType --
+ *
+ * This function may be invoked to add a new kind of canvas element to
+ * the core item types supported by Tk.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * From now on, the new item type will be useable in canvas widgets
+ * (e.g. typePtr->name can be used as the item type in "create" widget
+ * commands). If there was already a type with the same name as in
+ * typePtr, it is replaced with the new type.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_CreateItemType(
+ Tk_ItemType *typePtr) /* Information about item type; storage must
+ * be statically allocated (must live
+ * forever). */
+{
+ Tk_ItemType *typePtr2, *prevPtr;
+
+ if (typeList == NULL) {
+ InitCanvas();
+ }
+
+ /*
+ * If there's already an item type with the given name, remove it.
+ */
+
+ Tcl_MutexLock(&typeListMutex);
+ for (typePtr2 = typeList, prevPtr = NULL; typePtr2 != NULL;
+ prevPtr = typePtr2, typePtr2 = typePtr2->nextPtr) {
+ if (strcmp(typePtr2->name, typePtr->name) == 0) {
+ if (prevPtr == NULL) {
+ typeList = typePtr2->nextPtr;
+ } else {
+ prevPtr->nextPtr = typePtr2->nextPtr;
+ }
+ break;
+ }
+ }
+ typePtr->nextPtr = typeList;
+ typeList = typePtr;
+ Tcl_MutexUnlock(&typeListMutex);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetItemTypes --
+ *
+ * This function returns a pointer to the list of all item types. Note
+ * that this is inherently thread-unsafe, but since item types are only
+ * ever registered very rarely this is unlikely to be a problem in
+ * practice.
+ *
+ * Results:
+ * The return value is a pointer to the first in the list of item types
+ * currently supported by canvases.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_ItemType *
+Tk_GetItemTypes(void)
+{
+ if (typeList == NULL) {
+ InitCanvas();
+ }
+ return typeList;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InitCanvas --
+ *
+ * This function is invoked to perform once-only-ever initialization for
+ * the module, such as setting up the type table.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+InitCanvas(void)
+{
+ Tcl_MutexLock(&typeListMutex);
+ if (typeList != NULL) {
+ Tcl_MutexUnlock(&typeListMutex);
+ return;
+ }
+ typeList = &tkRectangleType;
+ tkRectangleType.nextPtr = &tkTextType;
+ tkTextType.nextPtr = &tkLineType;
+ tkLineType.nextPtr = &tkPolygonType;
+ tkPolygonType.nextPtr = &tkImageType;
+ tkImageType.nextPtr = &tkOvalType;
+ tkOvalType.nextPtr = &tkBitmapType;
+ tkBitmapType.nextPtr = &tkArcType;
+ tkArcType.nextPtr = &tkWindowType;
+ tkWindowType.nextPtr = NULL;
+ Tcl_MutexUnlock(&typeListMutex);
+}
+
+#ifdef USE_OLD_TAG_SEARCH
+/*
+ *--------------------------------------------------------------
+ *
+ * StartTagSearch --
+ *
+ * This function is called to initiate an enumeration of all items in a
+ * given canvas that contain a given tag.
+ *
+ * Results:
+ * The return value is a pointer to the first item in canvasPtr that
+ * matches tag, or NULL if there is no such item. The information at
+ * *searchPtr is initialized such that successive calls to NextItem will
+ * return successive items that match tag.
+ *
+ * Side effects:
+ * SearchPtr is linked into a list of searches in progress on canvasPtr,
+ * so that elements can safely be deleted while the search is in
+ * progress. EndTagSearch must be called at the end of the search to
+ * unlink searchPtr from this list.
+ *
+ *--------------------------------------------------------------
+ */
+
+static Tk_Item *
+StartTagSearch(
+ TkCanvas *canvasPtr, /* Canvas whose items are to be searched. */
+ Tcl_Obj *tagObj, /* Object giving tag value. */
+ TagSearch *searchPtr) /* Record describing tag search; will be
+ * initialized here. */
+{
+ int id;
+ Tk_Item *itemPtr, *lastPtr;
+ Tk_Uid *tagPtr;
+ Tk_Uid uid;
+ char *tag = Tcl_GetString(tagObj);
+ int count;
+ TkWindow *tkwin = (TkWindow *) canvasPtr->tkwin;
+ TkDisplay *dispPtr = tkwin->dispPtr;
+
+ /*
+ * Initialize the search.
+ */
+
+ searchPtr->canvasPtr = canvasPtr;
+ searchPtr->searchOver = 0;
+
+ /*
+ * Find the first matching item in one of several ways. If the tag is a
+ * number then it selects the single item with the matching identifier.
+ * In this case see if the item being requested is the hot item, in which
+ * case the search can be skipped.
+ */
+
+ if (isdigit(UCHAR(*tag))) {
+ char *end;
+ Tcl_HashEntry *entryPtr;
+
+ dispPtr->numIdSearches++;
+ id = strtoul(tag, &end, 0);
+ if (*end == 0) {
+ itemPtr = canvasPtr->hotPtr;
+ lastPtr = canvasPtr->hotPrevPtr;
+ if ((itemPtr == NULL) || (itemPtr->id != id) || (lastPtr == NULL)
+ || (lastPtr->nextPtr != itemPtr)) {
+ dispPtr->numSlowSearches++;
+ entryPtr = Tcl_FindHashEntry(&canvasPtr->idTable, (char*) id);
+ if (entryPtr != NULL) {
+ itemPtr = Tcl_GetHashValue(entryPtr);
+ lastPtr = itemPtr->prevPtr;
+ } else {
+ lastPtr = itemPtr = NULL;
+ }
+ }
+ searchPtr->lastPtr = lastPtr;
+ searchPtr->searchOver = 1;
+ canvasPtr->hotPtr = itemPtr;
+ canvasPtr->hotPrevPtr = lastPtr;
+ return itemPtr;
+ }
+ }
+
+ searchPtr->tag = uid = Tk_GetUid(tag);
+ if (uid == Tk_GetUid("all")) {
+ /*
+ * All items match.
+ */
+
+ searchPtr->tag = NULL;
+ searchPtr->lastPtr = NULL;
+ searchPtr->currentPtr = canvasPtr->firstItemPtr;
+ return canvasPtr->firstItemPtr;
+ }
+
+ /*
+ * None of the above. Search for an item with a matching tag.
+ */
+
+ for (lastPtr = NULL, itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;
+ lastPtr = itemPtr, itemPtr = itemPtr->nextPtr) {
+ for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags;
+ count > 0; tagPtr++, count--) {
+ if (*tagPtr == uid) {
+ searchPtr->lastPtr = lastPtr;
+ searchPtr->currentPtr = itemPtr;
+ return itemPtr;
+ }
+ }
+ }
+ searchPtr->lastPtr = lastPtr;
+ searchPtr->searchOver = 1;
+ return NULL;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * NextItem --
+ *
+ * This function returns successive items that match a given tag; it
+ * should be called only after StartTagSearch has been used to begin a
+ * search.
+ *
+ * Results:
+ * The return value is a pointer to the next item that matches the tag
+ * specified to StartTagSearch, or NULL if no such item exists.
+ * *SearchPtr is updated so that the next call to this function will
+ * return the next item.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static Tk_Item *
+NextItem(
+ TagSearch *searchPtr) /* Record describing search in progress. */
+{
+ Tk_Item *itemPtr, *lastPtr;
+ int count;
+ Tk_Uid uid;
+ Tk_Uid *tagPtr;
+
+ /*
+ * Find next item in list (this may not actually be a suitable one to
+ * return), and return if there are no items left.
+ */
+
+ lastPtr = searchPtr->lastPtr;
+ if (lastPtr == NULL) {
+ itemPtr = searchPtr->canvasPtr->firstItemPtr;
+ } else {
+ itemPtr = lastPtr->nextPtr;
+ }
+ if ((itemPtr == NULL) || (searchPtr->searchOver)) {
+ searchPtr->searchOver = 1;
+ return NULL;
+ }
+ if (itemPtr != searchPtr->currentPtr) {
+ /*
+ * The structure of the list has changed. Probably the previously-
+ * returned item was removed from the list. In this case, don't
+ * advance lastPtr; just return its new successor (i.e. do nothing
+ * here).
+ */
+ } else {
+ lastPtr = itemPtr;
+ itemPtr = lastPtr->nextPtr;
+ }
+
+ /*
+ * Handle special case of "all" search by returning next item.
+ */
+
+ uid = searchPtr->tag;
+ if (uid == NULL) {
+ searchPtr->lastPtr = lastPtr;
+ searchPtr->currentPtr = itemPtr;
+ return itemPtr;
+ }
+
+ /*
+ * Look for an item with a particular tag.
+ */
+
+ for ( ; itemPtr != NULL; lastPtr = itemPtr, itemPtr = itemPtr->nextPtr) {
+ for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags;
+ count > 0; tagPtr++, count--) {
+ if (*tagPtr == uid) {
+ searchPtr->lastPtr = lastPtr;
+ searchPtr->currentPtr = itemPtr;
+ return itemPtr;
+ }
+ }
+ }
+ searchPtr->lastPtr = lastPtr;
+ searchPtr->searchOver = 1;
+ return NULL;
+}
+
+#else /* !USE_OLD_TAG_SEARCH */
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetStaticUids --
+ *
+ * This function is invoked to return a structure filled with the Uids
+ * used when doing tag searching. If it was never before called in the
+ * current thread, it initializes the structure for that thread (uids are
+ * only ever local to one thread [Bug 1114977]).
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static SearchUids *
+GetStaticUids(void)
+{
+ SearchUids *searchUids =
+ Tcl_GetThreadData(&dataKey, sizeof(SearchUids));
+
+ if (searchUids->allUid == NULL) {
+ searchUids->allUid = Tk_GetUid("all");
+ searchUids->currentUid = Tk_GetUid("current");
+ searchUids->andUid = Tk_GetUid("&&");
+ searchUids->orUid = Tk_GetUid("||");
+ searchUids->xorUid = Tk_GetUid("^");
+ searchUids->parenUid = Tk_GetUid("(");
+ searchUids->endparenUid = Tk_GetUid(")");
+ searchUids->negparenUid = Tk_GetUid("!(");
+ searchUids->tagvalUid = Tk_GetUid("!!");
+ searchUids->negtagvalUid = Tk_GetUid("!");
+ }
+ return searchUids;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TagSearchExprInit --
+ *
+ * This function allocates and initializes one TagSearchExpr struct.
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+TagSearchExprInit(
+ TagSearchExpr **exprPtrPtr)
+{
+ TagSearchExpr *expr = *exprPtrPtr;
+
+ if (expr == NULL) {
+ expr = ckalloc(sizeof(TagSearchExpr));
+ expr->allocated = 0;
+ expr->uids = NULL;
+ expr->next = NULL;
+ }
+ expr->uid = NULL;
+ expr->index = 0;
+ expr->length = 0;
+ *exprPtrPtr = expr;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TagSearchExprDestroy --
+ *
+ * This function destroys one TagSearchExpr structure.
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+TagSearchExprDestroy(
+ TagSearchExpr *expr)
+{
+ if (expr != NULL) {
+ if (expr->uids) {
+ ckfree(expr->uids);
+ }
+ ckfree(expr);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TagSearchScan --
+ *
+ * This function is called to initiate an enumeration of all items in a
+ * given canvas that contain a tag that matches the tagOrId expression.
+ *
+ * Results:
+ * The return value indicates if the tagOrId expression was successfully
+ * scanned (syntax). The information at *searchPtr is initialized such
+ * that a call to TagSearchFirst, followed by successive calls to
+ * TagSearchNext will return items that match tag.
+ *
+ * Side effects:
+ * SearchPtr is linked into a list of searches in progress on canvasPtr,
+ * so that elements can safely be deleted while the search is in
+ * progress.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+TagSearchScan(
+ TkCanvas *canvasPtr, /* Canvas whose items are to be searched. */
+ Tcl_Obj *tagObj, /* Object giving tag value. */
+ TagSearch **searchPtrPtr) /* Record describing tag search; will be
+ * initialized here. */
+{
+ const char *tag = Tcl_GetString(tagObj);
+ int i;
+ TagSearch *searchPtr;
+
+ /*
+ * Initialize the search.
+ */
+
+ if (*searchPtrPtr != NULL) {
+ searchPtr = *searchPtrPtr;
+ } else {
+ /*
+ * Allocate primary search struct on first call.
+ */
+
+ *searchPtrPtr = searchPtr = ckalloc(sizeof(TagSearch));
+ searchPtr->expr = NULL;
+
+ /*
+ * Allocate buffer for rewritten tags (after de-escaping).
+ */
+
+ searchPtr->rewritebufferAllocated = 100;
+ searchPtr->rewritebuffer = ckalloc(searchPtr->rewritebufferAllocated);
+ }
+ TagSearchExprInit(&searchPtr->expr);
+
+ /*
+ * How long is the tagOrId?
+ */
+
+ searchPtr->stringLength = strlen(tag);
+
+ /*
+ * Make sure there is enough buffer to hold rewritten tags.
+ */
+
+ if ((unsigned) searchPtr->stringLength >=
+ searchPtr->rewritebufferAllocated) {
+ searchPtr->rewritebufferAllocated = searchPtr->stringLength + 100;
+ searchPtr->rewritebuffer =
+ ckrealloc(searchPtr->rewritebuffer,
+ searchPtr->rewritebufferAllocated);
+ }
+
+ /*
+ * Initialize search.
+ */
+
+ searchPtr->canvasPtr = canvasPtr;
+ searchPtr->searchOver = 0;
+ searchPtr->type = SEARCH_TYPE_EMPTY;
+
+ /*
+ * Find the first matching item in one of several ways. If the tag is a
+ * number then it selects the single item with the matching identifier.
+ * In this case see if the item being requested is the hot item, in which
+ * case the search can be skipped.
+ */
+
+ if (searchPtr->stringLength && isdigit(UCHAR(*tag))) {
+ char *end;
+
+ searchPtr->id = strtoul(tag, &end, 0);
+ if (*end == 0) {
+ searchPtr->type = SEARCH_TYPE_ID;
+ return TCL_OK;
+ }
+ }
+
+ /*
+ * For all other tags and tag expressions convert to a UID. This UID is
+ * kept forever, but this should be thought of as a cache rather than as a
+ * memory leak.
+ */
+
+ searchPtr->expr->uid = Tk_GetUid(tag);
+
+ /*
+ * Short circuit impossible searches for null tags.
+ */
+
+ if (searchPtr->stringLength == 0) {
+ return TCL_OK;
+ }
+
+ /*
+ * Pre-scan tag for at least one unquoted "&&" "||" "^" "!"; if not found
+ * then use string as simple tag.
+ */
+
+ for (i = 0; i < searchPtr->stringLength ; i++) {
+ if (tag[i] == '"') {
+ i++;
+ for ( ; i < searchPtr->stringLength; i++) {
+ if (tag[i] == '\\') {
+ i++;
+ continue;
+ }
+ if (tag[i] == '"') {
+ break;
+ }
+ }
+ } else if ((tag[i] == '&' && tag[i+1] == '&')
+ || (tag[i] == '|' && tag[i+1] == '|')
+ || (tag[i] == '^')
+ || (tag[i] == '!')) {
+ searchPtr->type = SEARCH_TYPE_EXPR;
+ break;
+ }
+ }
+
+ searchPtr->string = tag;
+ searchPtr->stringIndex = 0;
+ if (searchPtr->type == SEARCH_TYPE_EXPR) {
+ /*
+ * An operator was found in the prescan, so now compile the tag
+ * expression into array of Tk_Uid flagging any syntax errors found.
+ */
+
+ if (TagSearchScanExpr(canvasPtr->interp, searchPtr,
+ searchPtr->expr) != TCL_OK) {
+ /*
+ * Syntax error in tag expression. The result message was set by
+ * TagSearchScanExpr.
+ */
+
+ return TCL_ERROR;
+ }
+ searchPtr->expr->length = searchPtr->expr->index;
+ } else if (searchPtr->expr->uid == GetStaticUids()->allUid) {
+ /*
+ * All items match.
+ */
+
+ searchPtr->type = SEARCH_TYPE_ALL;
+ } else {
+ /*
+ * Optimized single-tag search
+ */
+
+ searchPtr->type = SEARCH_TYPE_TAG;
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TagSearchDestroy --
+ *
+ * This function destroys any dynamic structures that may have been
+ * allocated by TagSearchScan.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * Deallocates memory.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+TagSearchDestroy(
+ TagSearch *searchPtr) /* Record describing tag search. */
+{
+ if (searchPtr) {
+ TagSearchExprDestroy(searchPtr->expr);
+ ckfree(searchPtr->rewritebuffer);
+ ckfree(searchPtr);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TagSearchScanExpr --
+ *
+ * This recursive function is called to scan a tag expression and compile
+ * it into an array of Tk_Uids.
+ *
+ * Results:
+ * The return value indicates if the tagOrId expression was successfully
+ * scanned (syntax). The information at *searchPtr is initialized such
+ * that a call to TagSearchFirst, followed by successive calls to
+ * TagSearchNext will return items that match tag.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+TagSearchScanExpr(
+ Tcl_Interp *interp, /* Current interpreter. */
+ TagSearch *searchPtr, /* Search data. */
+ TagSearchExpr *expr) /* Compiled expression result. */
+{
+ int looking_for_tag; /* When true, scanner expects next char(s) to
+ * be a tag, else operand expected. */
+ int found_tag; /* One or more tags found. */
+ int found_endquote; /* For quoted tag string parsing. */
+ int negate_result; /* Pending negation of next tag value. */
+ char *tag; /* Tag from tag expression string. */
+ char c;
+ SearchUids *searchUids; /* Collection of uids for basic search
+ * expression terms. */
+
+ searchUids = GetStaticUids();
+ negate_result = 0;
+ found_tag = 0;
+ looking_for_tag = 1;
+ while (searchPtr->stringIndex < searchPtr->stringLength) {
+ c = searchPtr->string[searchPtr->stringIndex++];
+
+ /*
+ * Need two slots free at this point, not one. [Bug 2931374]
+ */
+
+ if (expr->index >= expr->allocated-1) {
+ expr->allocated += 15;
+ if (expr->uids) {
+ expr->uids = ckrealloc(expr->uids,
+ expr->allocated * sizeof(Tk_Uid));
+ } else {
+ expr->uids = ckalloc(expr->allocated * sizeof(Tk_Uid));
+ }
+ }
+
+ if (looking_for_tag) {
+ switch (c) {
+ case ' ': /* Ignore unquoted whitespace */
+ case '\t':
+ case '\n':
+ case '\r':
+ break;
+
+ case '!': /* Negate next tag or subexpr */
+ if (looking_for_tag > 1) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "too many '!' in tag search expression", -1));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "SEARCH",
+ "COMPLEXITY", NULL);
+ return TCL_ERROR;
+ }
+ looking_for_tag++;
+ negate_result = 1;
+ break;
+
+ case '(': /* Scan (negated) subexpr recursively */
+ if (negate_result) {
+ expr->uids[expr->index++] = searchUids->negparenUid;
+ negate_result = 0;
+ } else {
+ expr->uids[expr->index++] = searchUids->parenUid;
+ }
+ if (TagSearchScanExpr(interp, searchPtr, expr) != TCL_OK) {
+ /*
+ * Result string should be already set by nested call to
+ * tag_expr_scan()
+ */
+
+ return TCL_ERROR;
+ }
+ looking_for_tag = 0;
+ found_tag = 1;
+ break;
+
+ case '"': /* Quoted tag string */
+ if (negate_result) {
+ expr->uids[expr->index++] = searchUids->negtagvalUid;
+ negate_result = 0;
+ } else {
+ expr->uids[expr->index++] = searchUids->tagvalUid;
+ }
+ tag = searchPtr->rewritebuffer;
+ found_endquote = 0;
+ while (searchPtr->stringIndex < searchPtr->stringLength) {
+ c = searchPtr->string[searchPtr->stringIndex++];
+ if (c == '\\') {
+ c = searchPtr->string[searchPtr->stringIndex++];
+ }
+ if (c == '"') {
+ found_endquote = 1;
+ break;
+ }
+ *tag++ = c;
+ }
+ if (!found_endquote) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "missing endquote in tag search expression", -1));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "SEARCH",
+ "ENDQUOTE", NULL);
+ return TCL_ERROR;
+ }
+ if (!(tag - searchPtr->rewritebuffer)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "null quoted tag string in tag search expression",
+ -1));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "SEARCH",
+ "EMPTY", NULL);
+ return TCL_ERROR;
+ }
+ *tag++ = '\0';
+ expr->uids[expr->index++] =
+ Tk_GetUid(searchPtr->rewritebuffer);
+ looking_for_tag = 0;
+ found_tag = 1;
+ break;
+
+ case '&': /* Illegal chars when looking for tag */
+ case '|':
+ case '^':
+ case ')':
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "unexpected operator in tag search expression", -1));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "SEARCH",
+ "UNEXPECTED", NULL);
+ return TCL_ERROR;
+
+ default: /* Unquoted tag string */
+ if (negate_result) {
+ expr->uids[expr->index++] = searchUids->negtagvalUid;
+ negate_result = 0;
+ } else {
+ expr->uids[expr->index++] = searchUids->tagvalUid;
+ }
+ tag = searchPtr->rewritebuffer;
+ *tag++ = c;
+
+ /*
+ * Copy rest of tag, including any embedded whitespace.
+ */
+
+ while (searchPtr->stringIndex < searchPtr->stringLength) {
+ c = searchPtr->string[searchPtr->stringIndex];
+ if (c == '!' || c == '&' || c == '|' || c == '^'
+ || c == '(' || c == ')' || c == '"') {
+ break;
+ }
+ *tag++ = c;
+ searchPtr->stringIndex++;
+ }
+
+ /*
+ * Remove trailing whitespace.
+ */
+
+ while (1) {
+ c = *--tag;
+
+ /*
+ * There must have been one non-whitespace char, so this
+ * will terminate.
+ */
+
+ if (c != ' ' && c != '\t' && c != '\n' && c != '\r') {
+ break;
+ }
+ }
+ *++tag = '\0';
+ expr->uids[expr->index++] =
+ Tk_GetUid(searchPtr->rewritebuffer);
+ looking_for_tag = 0;
+ found_tag = 1;
+ }
+
+ } else { /* ! looking_for_tag */
+ switch (c) {
+ case ' ': /* Ignore whitespace */
+ case '\t':
+ case '\n':
+ case '\r':
+ break;
+
+ case '&': /* AND operator */
+ c = searchPtr->string[searchPtr->stringIndex++];
+ if (c != '&') {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "singleton '&' in tag search expression", -1));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "SEARCH",
+ "INCOMPLETE_OP", NULL);
+ return TCL_ERROR;
+ }
+ expr->uids[expr->index++] = searchUids->andUid;
+ looking_for_tag = 1;
+ break;
+
+ case '|': /* OR operator */
+ c = searchPtr->string[searchPtr->stringIndex++];
+ if (c != '|') {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "singleton '|' in tag search expression", -1));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "SEARCH",
+ "INCOMPLETE_OP", NULL);
+ return TCL_ERROR;
+ }
+ expr->uids[expr->index++] = searchUids->orUid;
+ looking_for_tag = 1;
+ break;
+
+ case '^': /* XOR operator */
+ expr->uids[expr->index++] = searchUids->xorUid;
+ looking_for_tag = 1;
+ break;
+
+ case ')': /* End subexpression */
+ expr->uids[expr->index++] = searchUids->endparenUid;
+ goto breakwhile;
+
+ default: /* syntax error */
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "invalid boolean operator in tag search expression",
+ -1));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "SEARCH", "BAD_OP",
+ NULL);
+ return TCL_ERROR;
+ }
+ }
+ }
+
+ breakwhile:
+ if (found_tag && !looking_for_tag) {
+ return TCL_OK;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "missing tag in tag search expression", -1));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "SEARCH", "NO_TAG", NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TagSearchEvalExpr --
+ *
+ * This recursive function is called to eval a tag expression.
+ *
+ * Results:
+ * The return value indicates if the tagOrId expression successfully
+ * matched the tags of the current item.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+TagSearchEvalExpr(
+ TagSearchExpr *expr, /* Search expression */
+ Tk_Item *itemPtr) /* Item being test for match */
+{
+ int looking_for_tag; /* When true, scanner expects next char(s) to
+ * be a tag, else operand expected. */
+ int negate_result; /* Pending negation of next tag value */
+ Tk_Uid uid;
+ Tk_Uid *tagPtr;
+ int count;
+ int result; /* Value of expr so far */
+ int parendepth;
+ SearchUids *searchUids; /* Collection of uids for basic search
+ * expression terms. */
+
+ searchUids = GetStaticUids();
+ result = 0; /* Just to keep the compiler quiet. */
+
+ negate_result = 0;
+ looking_for_tag = 1;
+ while (expr->index < expr->length) {
+ uid = expr->uids[expr->index++];
+ if (looking_for_tag) {
+ if (uid == searchUids->tagvalUid) {
+/*
+ * assert(expr->index < expr->length);
+ */
+ uid = expr->uids[expr->index++];
+ result = 0;
+
+ /*
+ * set result 1 if tag is found in item's tags
+ */
+
+ for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags;
+ count > 0; tagPtr++, count--) {
+ if (*tagPtr == uid) {
+ result = 1;
+ break;
+ }
+ }
+
+ } else if (uid == searchUids->negtagvalUid) {
+ negate_result = ! negate_result;
+/*
+ * assert(expr->index < expr->length);
+ */
+ uid = expr->uids[expr->index++];
+ result = 0;
+
+ /*
+ * set result 1 if tag is found in item's tags.
+ */
+
+ for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags;
+ count > 0; tagPtr++, count--) {
+ if (*tagPtr == uid) {
+ result = 1;
+ break;
+ }
+ }
+
+ } else if (uid == searchUids->parenUid) {
+ /*
+ * Evaluate subexpressions with recursion.
+ */
+
+ result = TagSearchEvalExpr(expr, itemPtr);
+
+ } else if (uid == searchUids->negparenUid) {
+ negate_result = !negate_result;
+
+ /*
+ * Evaluate subexpressions with recursion.
+ */
+
+ result = TagSearchEvalExpr(expr, itemPtr);
+ }
+ if (negate_result) {
+ result = ! result;
+ negate_result = 0;
+ }
+ looking_for_tag = 0;
+ } else { /* ! looking_for_tag */
+ if (((uid == searchUids->andUid) && (!result)) ||
+ ((uid == searchUids->orUid) && result)) {
+ /*
+ * Short circuit expression evaluation.
+ *
+ * if result before && is 0, or result before || is 1, then
+ * the expression is decided and no further evaluation is
+ * needed.
+ */
+
+ parendepth = 0;
+ while (expr->index < expr->length) {
+ uid = expr->uids[expr->index++];
+ if (uid == searchUids->tagvalUid ||
+ uid == searchUids->negtagvalUid) {
+ expr->index++;
+ continue;
+ }
+ if (uid == searchUids->parenUid ||
+ uid == searchUids->negparenUid) {
+ parendepth++;
+ continue;
+ }
+ if (uid == searchUids->endparenUid) {
+ parendepth--;
+ if (parendepth < 0) {
+ break;
+ }
+ }
+ }
+ return result;
+
+ } else if (uid == searchUids->xorUid) {
+ /*
+ * If the previous result was 1 then negate the next result.
+ */
+
+ negate_result = result;
+
+ } else if (uid == searchUids->endparenUid) {
+ return result;
+ }
+ looking_for_tag = 1;
+ }
+ }
+/*
+ * assert(!looking_for_tag);
+ */
+ return result;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TagSearchFirst --
+ *
+ * This function is called to get the first item item that matches a
+ * preestablished search predicate that was set by TagSearchScan.
+ *
+ * Results:
+ * The return value is a pointer to the first item, or NULL if there is
+ * no such item. The information at *searchPtr is updated such that
+ * successive calls to TagSearchNext will return successive items.
+ *
+ * Side effects:
+ * SearchPtr is linked into a list of searches in progress on canvasPtr,
+ * so that elements can safely be deleted while the search is in
+ * progress.
+ *
+ *--------------------------------------------------------------
+ */
+
+static Tk_Item *
+TagSearchFirst(
+ TagSearch *searchPtr) /* Record describing tag search */
+{
+ Tk_Item *itemPtr, *lastPtr;
+ Tk_Uid uid, *tagPtr;
+ int count;
+
+ /*
+ * Short circuit impossible searches for null tags.
+ */
+
+ if (searchPtr->stringLength == 0) {
+ return NULL;
+ }
+
+ /*
+ * Find the first matching item in one of several ways. If the tag is a
+ * number then it selects the single item with the matching identifier.
+ * In this case see if the item being requested is the hot item, in which
+ * case the search can be skipped.
+ */
+
+ if (searchPtr->type == SEARCH_TYPE_ID) {
+ Tcl_HashEntry *entryPtr;
+
+ itemPtr = searchPtr->canvasPtr->hotPtr;
+ lastPtr = searchPtr->canvasPtr->hotPrevPtr;
+ if ((itemPtr == NULL) || (itemPtr->id != searchPtr->id)
+ || (lastPtr == NULL) || (lastPtr->nextPtr != itemPtr)) {
+ entryPtr = Tcl_FindHashEntry(&searchPtr->canvasPtr->idTable,
+ (char *) INT2PTR(searchPtr->id));
+ if (entryPtr != NULL) {
+ itemPtr = Tcl_GetHashValue(entryPtr);
+ lastPtr = itemPtr->prevPtr;
+ } else {
+ lastPtr = itemPtr = NULL;
+ }
+ }
+ searchPtr->lastPtr = lastPtr;
+ searchPtr->searchOver = 1;
+ searchPtr->canvasPtr->hotPtr = itemPtr;
+ searchPtr->canvasPtr->hotPrevPtr = lastPtr;
+ return itemPtr;
+ }
+
+ if (searchPtr->type == SEARCH_TYPE_ALL) {
+ /*
+ * All items match.
+ */
+
+ searchPtr->lastPtr = NULL;
+ searchPtr->currentPtr = searchPtr->canvasPtr->firstItemPtr;
+ return searchPtr->canvasPtr->firstItemPtr;
+ }
+
+ if (searchPtr->type == SEARCH_TYPE_TAG) {
+ /*
+ * Optimized single-tag search
+ */
+
+ uid = searchPtr->expr->uid;
+ for (lastPtr = NULL, itemPtr = searchPtr->canvasPtr->firstItemPtr;
+ itemPtr != NULL; lastPtr=itemPtr, itemPtr=itemPtr->nextPtr) {
+ for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags;
+ count > 0; tagPtr++, count--) {
+ if (*tagPtr == uid) {
+ searchPtr->lastPtr = lastPtr;
+ searchPtr->currentPtr = itemPtr;
+ return itemPtr;
+ }
+ }
+ }
+ } else {
+ /*
+ * None of the above. Search for an item matching the tag expression.
+ */
+
+ for (lastPtr = NULL, itemPtr = searchPtr->canvasPtr->firstItemPtr;
+ itemPtr != NULL; lastPtr = itemPtr, itemPtr = itemPtr->nextPtr) {
+ searchPtr->expr->index = 0;
+ if (TagSearchEvalExpr(searchPtr->expr, itemPtr)) {
+ searchPtr->lastPtr = lastPtr;
+ searchPtr->currentPtr = itemPtr;
+ return itemPtr;
+ }
+ }
+ }
+ searchPtr->lastPtr = lastPtr;
+ searchPtr->searchOver = 1;
+ return NULL;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TagSearchNext --
+ *
+ * This function returns successive items that match a given tag; it
+ * should be called only after TagSearchFirst has been used to begin a
+ * search.
+ *
+ * Results:
+ * The return value is a pointer to the next item that matches the tag
+ * expr specified to TagSearchScan, or NULL if no such item exists.
+ * *SearchPtr is updated so that the next call to this function will
+ * return the next item.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static Tk_Item *
+TagSearchNext(
+ TagSearch *searchPtr) /* Record describing search in progress. */
+{
+ Tk_Item *itemPtr, *lastPtr;
+ Tk_Uid uid, *tagPtr;
+ int count;
+
+ /*
+ * Find next item in list (this may not actually be a suitable one to
+ * return), and return if there are no items left.
+ */
+
+ lastPtr = searchPtr->lastPtr;
+ if (lastPtr == NULL) {
+ itemPtr = searchPtr->canvasPtr->firstItemPtr;
+ } else {
+ itemPtr = lastPtr->nextPtr;
+ }
+ if ((itemPtr == NULL) || (searchPtr->searchOver)) {
+ searchPtr->searchOver = 1;
+ return NULL;
+ }
+ if (itemPtr != searchPtr->currentPtr) {
+ /*
+ * The structure of the list has changed. Probably the previously-
+ * returned item was removed from the list. In this case, don't
+ * advance lastPtr; just return its new successor (i.e. do nothing
+ * here).
+ */
+ } else {
+ lastPtr = itemPtr;
+ itemPtr = lastPtr->nextPtr;
+ }
+
+ if (searchPtr->type == SEARCH_TYPE_ALL) {
+ /*
+ * All items match.
+ */
+
+ searchPtr->lastPtr = lastPtr;
+ searchPtr->currentPtr = itemPtr;
+ return itemPtr;
+ }
+
+ if (searchPtr->type == SEARCH_TYPE_TAG) {
+ /*
+ * Optimized single-tag search
+ */
+
+ uid = searchPtr->expr->uid;
+ for (; itemPtr != NULL; lastPtr = itemPtr, itemPtr = itemPtr->nextPtr) {
+ for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags;
+ count > 0; tagPtr++, count--) {
+ if (*tagPtr == uid) {
+ searchPtr->lastPtr = lastPtr;
+ searchPtr->currentPtr = itemPtr;
+ return itemPtr;
+ }
+ }
+ }
+ searchPtr->lastPtr = lastPtr;
+ searchPtr->searchOver = 1;
+ return NULL;
+ }
+
+ /*
+ * Else.... evaluate tag expression
+ */
+
+ for ( ; itemPtr != NULL; lastPtr = itemPtr, itemPtr = itemPtr->nextPtr) {
+ searchPtr->expr->index = 0;
+ if (TagSearchEvalExpr(searchPtr->expr, itemPtr)) {
+ searchPtr->lastPtr = lastPtr;
+ searchPtr->currentPtr = itemPtr;
+ return itemPtr;
+ }
+ }
+ searchPtr->lastPtr = lastPtr;
+ searchPtr->searchOver = 1;
+ return NULL;
+}
+#endif /* USE_OLD_TAG_SEARCH */
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DoItem --
+ *
+ * This is a utility function called by FindItems. It either adds
+ * itemPtr's id to the list being constructed, or it adds a new tag to
+ * itemPtr, depending on the value of tag.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If tag is NULL then itemPtr's id is added as an element to the
+ * supplied object; otherwise tag is added to itemPtr's list of tags.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+DoItem(
+ Tcl_Obj *accumObj, /* Object in which to (possibly) record item
+ * id. */
+ Tk_Item *itemPtr, /* Item to (possibly) modify. */
+ Tk_Uid tag) /* Tag to add to those already present for
+ * item, or NULL. */
+{
+ Tk_Uid *tagPtr;
+ int count;
+
+ /*
+ * Handle the "add-to-result" case and return, if appropriate.
+ */
+
+ if (tag == NULL) {
+ Tcl_ListObjAppendElement(NULL, accumObj, Tcl_NewIntObj(itemPtr->id));
+ return;
+ }
+
+ for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags;
+ count > 0; tagPtr++, count--) {
+ if (tag == *tagPtr) {
+ return;
+ }
+ }
+
+ /*
+ * Grow the tag space if there's no more room left in the current block.
+ */
+
+ if (itemPtr->tagSpace == itemPtr->numTags) {
+ Tk_Uid *newTagPtr;
+
+ itemPtr->tagSpace += 5;
+ newTagPtr = ckalloc(itemPtr->tagSpace * sizeof(Tk_Uid));
+ memcpy((void *) newTagPtr, itemPtr->tagPtr,
+ itemPtr->numTags * sizeof(Tk_Uid));
+ if (itemPtr->tagPtr != itemPtr->staticTagSpace) {
+ ckfree(itemPtr->tagPtr);
+ }
+ itemPtr->tagPtr = newTagPtr;
+ tagPtr = &itemPtr->tagPtr[itemPtr->numTags];
+ }
+
+ /*
+ * Add in the new tag.
+ */
+
+ *tagPtr = tag;
+ itemPtr->numTags++;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * FindItems --
+ *
+ * This function does all the work of implementing the "find" and
+ * "addtag" options of the canvas widget command, which locate items that
+ * have certain features (location, tags, position in display list, etc.)
+ *
+ * Results:
+ * A standard Tcl return value. If newTag is NULL, then a list of ids
+ * from all the items that match objc/objv is returned in the interp's
+ * result. If newTag is NULL, then the normal the interp's result is an
+ * empty string. If an error occurs, then the interp's result will hold
+ * an error message.
+ *
+ * Side effects:
+ * If newTag is non-NULL, then all the items that match the information
+ * in objc/objv have that tag added to their lists of tags.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+FindItems(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ TkCanvas *canvasPtr, /* Canvas whose items are to be searched. */
+ int objc, /* Number of entries in argv. Must be greater
+ * than zero. */
+ Tcl_Obj *const *objv, /* Arguments that describe what items to
+ * search for (see user doc on "find" and
+ * "addtag" options). */
+ Tcl_Obj *newTag, /* If non-NULL, gives new tag to set on all
+ * found items; if NULL, then ids of found
+ * items are returned in the interp's
+ * result. */
+ int first /* For error messages: gives number of
+ * elements of objv which are already
+ * handled. */
+#ifndef USE_OLD_TAG_SEARCH
+ ,TagSearch **searchPtrPtr /* From CanvasWidgetCmd local vars*/
+#endif /* not USE_OLD_TAG_SEARCH */
+ )
+{
+#ifdef USE_OLD_TAG_SEARCH
+ TagSearch search;
+#endif /* USE_OLD_TAG_SEARCH */
+ Tk_Item *itemPtr;
+ Tk_Uid uid;
+ int index, result;
+ Tcl_Obj *resultObj;
+ static const char *const optionStrings[] = {
+ "above", "all", "below", "closest",
+ "enclosed", "overlapping", "withtag", NULL
+ };
+ enum options {
+ CANV_ABOVE, CANV_ALL, CANV_BELOW, CANV_CLOSEST,
+ CANV_ENCLOSED, CANV_OVERLAPPING, CANV_WITHTAG
+ };
+
+ if (newTag != NULL) {
+ uid = Tk_GetUid(Tcl_GetString(newTag));
+ } else {
+ uid = NULL;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[first], optionStrings,
+ "search command", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch ((enum options) index) {
+ case CANV_ABOVE: {
+ Tk_Item *lastPtr = NULL;
+
+ if (objc != first+2) {
+ Tcl_WrongNumArgs(interp, first+1, objv, "tagOrId");
+ return TCL_ERROR;
+ }
+ FOR_EVERY_CANVAS_ITEM_MATCHING(objv[first+1], searchPtrPtr,
+ return TCL_ERROR) {
+ lastPtr = itemPtr;
+ }
+ if ((lastPtr != NULL) && (lastPtr->nextPtr != NULL)) {
+ resultObj = Tcl_NewObj();
+ DoItem(resultObj, lastPtr->nextPtr, uid);
+ Tcl_SetObjResult(interp, resultObj);
+ }
+ break;
+ }
+ case CANV_ALL:
+ if (objc != first+1) {
+ Tcl_WrongNumArgs(interp, first+1, objv, NULL);
+ return TCL_ERROR;
+ }
+
+ resultObj = Tcl_NewObj();
+ for (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;
+ itemPtr = itemPtr->nextPtr) {
+ DoItem(resultObj, itemPtr, uid);
+ }
+ Tcl_SetObjResult(interp, resultObj);
+ break;
+
+ case CANV_BELOW:
+ if (objc != first+2) {
+ Tcl_WrongNumArgs(interp, first+1, objv, "tagOrId");
+ return TCL_ERROR;
+ }
+ FIRST_CANVAS_ITEM_MATCHING(objv[first+1], searchPtrPtr,
+ return TCL_ERROR);
+ if ((itemPtr != NULL) && (itemPtr->prevPtr != NULL)) {
+ resultObj = Tcl_NewObj();
+ DoItem(resultObj, itemPtr->prevPtr, uid);
+ Tcl_SetObjResult(interp, resultObj);
+ }
+ break;
+ case CANV_CLOSEST: {
+ double closestDist;
+ Tk_Item *startPtr, *closestPtr;
+ double coords[2], halo;
+ int x1, y1, x2, y2;
+
+ if ((objc < first+3) || (objc > first+5)) {
+ Tcl_WrongNumArgs(interp, first+1, objv, "x y ?halo? ?start?");
+ return TCL_ERROR;
+ }
+ if (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr,
+ objv[first+1], &coords[0]) != TCL_OK
+ || Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr,
+ objv[first+2], &coords[1]) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (objc > first+3) {
+ if (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr,
+ objv[first+3], &halo) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (halo < 0.0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't have negative halo value \"%f\"", halo));
+ return TCL_ERROR;
+ }
+ } else {
+ halo = 0.0;
+ }
+
+ /*
+ * Find the item at which to start the search.
+ */
+
+ startPtr = canvasPtr->firstItemPtr;
+ if (objc == first+5) {
+ FIRST_CANVAS_ITEM_MATCHING(objv[first+4], searchPtrPtr,
+ return TCL_ERROR);
+ if (itemPtr != NULL) {
+ startPtr = itemPtr;
+ }
+ }
+
+ /*
+ * The code below is optimized so that it can eliminate most items
+ * without having to call their item-specific functions. This is done
+ * by keeping a bounding box (x1, y1, x2, y2) that an item's bbox must
+ * overlap if the item is to have any chance of being closer than the
+ * closest so far.
+ */
+
+ itemPtr = startPtr;
+ while(itemPtr && (itemPtr->state == TK_STATE_HIDDEN ||
+ (itemPtr->state == TK_STATE_NULL &&
+ canvasPtr->canvas_state == TK_STATE_HIDDEN))) {
+ itemPtr = itemPtr->nextPtr;
+ }
+ if (itemPtr == NULL) {
+ return TCL_OK;
+ }
+ closestDist = ItemPoint(canvasPtr, itemPtr, coords, halo);
+ while (1) {
+ double newDist;
+
+ /*
+ * Update the bounding box using itemPtr, which is the new closest
+ * item.
+ */
+
+ x1 = (int) (coords[0] - closestDist - halo - 1);
+ y1 = (int) (coords[1] - closestDist - halo - 1);
+ x2 = (int) (coords[0] + closestDist + halo + 1);
+ y2 = (int) (coords[1] + closestDist + halo + 1);
+ closestPtr = itemPtr;
+
+ /*
+ * Search for an item that beats the current closest one. Work
+ * circularly through the canvas's item list until getting back to
+ * the starting item.
+ */
+
+ while (1) {
+ itemPtr = itemPtr->nextPtr;
+ if (itemPtr == NULL) {
+ itemPtr = canvasPtr->firstItemPtr;
+ }
+ if (itemPtr == startPtr) {
+ resultObj = Tcl_NewObj();
+ DoItem(resultObj, closestPtr, uid);
+ Tcl_SetObjResult(interp, resultObj);
+ return TCL_OK;
+ }
+ if (itemPtr->state == TK_STATE_HIDDEN ||
+ (itemPtr->state == TK_STATE_NULL &&
+ canvasPtr->canvas_state == TK_STATE_HIDDEN)) {
+ continue;
+ }
+ if ((itemPtr->x1 >= x2) || (itemPtr->x2 <= x1)
+ || (itemPtr->y1 >= y2) || (itemPtr->y2 <= y1)) {
+ continue;
+ }
+ newDist = ItemPoint(canvasPtr, itemPtr, coords, halo);
+ if (newDist <= closestDist) {
+ closestDist = newDist;
+ break;
+ }
+ }
+ }
+ break;
+ }
+ case CANV_ENCLOSED:
+ if (objc != first+5) {
+ Tcl_WrongNumArgs(interp, first+1, objv, "x1 y1 x2 y2");
+ return TCL_ERROR;
+ }
+ return FindArea(interp, canvasPtr, objv+first+1, uid, 1);
+ case CANV_OVERLAPPING:
+ if (objc != first+5) {
+ Tcl_WrongNumArgs(interp, first+1, objv, "x1 y1 x2 y2");
+ return TCL_ERROR;
+ }
+ return FindArea(interp, canvasPtr, objv+first+1, uid, 0);
+ case CANV_WITHTAG:
+ if (objc != first+2) {
+ Tcl_WrongNumArgs(interp, first+1, objv, "tagOrId");
+ return TCL_ERROR;
+ }
+ resultObj = Tcl_NewObj();
+ FOR_EVERY_CANVAS_ITEM_MATCHING(objv[first+1], searchPtrPtr,
+ goto badWithTagSearch) {
+ DoItem(resultObj, itemPtr, uid);
+ }
+ Tcl_SetObjResult(interp, resultObj);
+ return TCL_OK;
+ badWithTagSearch:
+ Tcl_DecrRefCount(resultObj);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * FindArea --
+ *
+ * This function implements area searches for the "find" and "addtag"
+ * options.
+ *
+ * Results:
+ * A standard Tcl return value. If newTag is NULL, then a list of ids
+ * from all the items overlapping or enclosed by the rectangle given by
+ * objc is returned in the interp's result. If newTag is NULL, then the
+ * normal the interp's result is an empty string. If an error occurs,
+ * then the interp's result will hold an error message.
+ *
+ * Side effects:
+ * If uid is non-NULL, then all the items overlapping or enclosed by the
+ * area in objv have that tag added to their lists of tags.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+FindArea(
+ Tcl_Interp *interp, /* Interpreter for error reporting and result
+ * storing. */
+ TkCanvas *canvasPtr, /* Canvas whose items are to be searched. */
+ Tcl_Obj *const *objv, /* Array of four arguments that give the
+ * coordinates of the rectangular area to
+ * search. */
+ Tk_Uid uid, /* If non-NULL, gives new tag to set on all
+ * found items; if NULL, then ids of found
+ * items are returned in the interp's
+ * result. */
+ int enclosed) /* 0 means overlapping or enclosed items are
+ * OK, 1 means only enclosed items are OK. */
+{
+ double rect[4], tmp;
+ int x1, y1, x2, y2;
+ Tk_Item *itemPtr;
+ Tcl_Obj *resultObj;
+
+ if ((Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr, objv[0],
+ &rect[0]) != TCL_OK)
+ || (Tk_CanvasGetCoordFromObj(interp,(Tk_Canvas)canvasPtr,objv[1],
+ &rect[1]) != TCL_OK)
+ || (Tk_CanvasGetCoordFromObj(interp,(Tk_Canvas)canvasPtr,objv[2],
+ &rect[2]) != TCL_OK)
+ || (Tk_CanvasGetCoordFromObj(interp,(Tk_Canvas)canvasPtr,objv[3],
+ &rect[3]) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ if (rect[0] > rect[2]) {
+ tmp = rect[0]; rect[0] = rect[2]; rect[2] = tmp;
+ }
+ if (rect[1] > rect[3]) {
+ tmp = rect[1]; rect[1] = rect[3]; rect[3] = tmp;
+ }
+
+ /*
+ * Use an integer bounding box for a quick test, to avoid calling
+ * item-specific code except for items that are close.
+ */
+
+ x1 = (int) (rect[0] - 1.0);
+ y1 = (int) (rect[1] - 1.0);
+ x2 = (int) (rect[2] + 1.0);
+ y2 = (int) (rect[3] + 1.0);
+ resultObj = Tcl_NewObj();
+ for (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;
+ itemPtr = itemPtr->nextPtr) {
+ if (itemPtr->state == TK_STATE_HIDDEN ||
+ (itemPtr->state == TK_STATE_NULL
+ && canvasPtr->canvas_state == TK_STATE_HIDDEN)) {
+ continue;
+ }
+ if ((itemPtr->x1 >= x2) || (itemPtr->x2 <= x1)
+ || (itemPtr->y1 >= y2) || (itemPtr->y2 <= y1)) {
+ continue;
+ }
+ if (ItemOverlap(canvasPtr, itemPtr, rect) >= enclosed) {
+ DoItem(resultObj, itemPtr, uid);
+ }
+ }
+ Tcl_SetObjResult(interp, resultObj);
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * RelinkItems --
+ *
+ * Move one or more items to a different place in the display order for a
+ * canvas.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The items identified by "tag" are moved so that they are all together
+ * in the display list and immediately after prevPtr. The order of the
+ * moved items relative to each other is not changed.
+ *
+ *--------------------------------------------------------------
+ */
+
+#ifdef USE_OLD_TAG_SEARCH
+static void
+RelinkItems(
+ TkCanvas *canvasPtr, /* Canvas to be modified. */
+ Tcl_Obj *tag, /* Tag identifying items to be moved in the
+ * redisplay list. */
+ Tk_Item *prevPtr) /* Reposition the items so that they go just
+ * after this item (NULL means put at
+ * beginning of list). */
+#else /* USE_OLD_TAG_SEARCH */
+static int
+RelinkItems(
+ TkCanvas *canvasPtr, /* Canvas to be modified. */
+ Tcl_Obj *tag, /* Tag identifying items to be moved in the
+ * redisplay list. */
+ Tk_Item *prevPtr, /* Reposition the items so that they go just
+ * after this item (NULL means put at
+ * beginning of list). */
+ TagSearch **searchPtrPtr) /* From CanvasWidgetCmd local vars */
+#endif /* USE_OLD_TAG_SEARCH */
+{
+ Tk_Item *itemPtr;
+#ifdef USE_OLD_TAG_SEARCH
+ TagSearch search;
+#endif /* USE_OLD_TAG_SEARCH */
+ Tk_Item *firstMovePtr, *lastMovePtr;
+ int result;
+
+ /*
+ * Find all of the items to be moved and remove them from the list, making
+ * an auxiliary list running from firstMovePtr to lastMovePtr. Record
+ * their areas for redisplay.
+ */
+
+ firstMovePtr = lastMovePtr = NULL;
+ FOR_EVERY_CANVAS_ITEM_MATCHING(tag, searchPtrPtr, return TCL_ERROR) {
+ if (itemPtr == prevPtr) {
+ /*
+ * Item after which insertion is to occur is being moved! Switch
+ * to insert after its predecessor.
+ */
+
+ prevPtr = prevPtr->prevPtr;
+ }
+ if (itemPtr->prevPtr == NULL) {
+ if (itemPtr->nextPtr != NULL) {
+ itemPtr->nextPtr->prevPtr = NULL;
+ }
+ canvasPtr->firstItemPtr = itemPtr->nextPtr;
+ } else {
+ if (itemPtr->nextPtr != NULL) {
+ itemPtr->nextPtr->prevPtr = itemPtr->prevPtr;
+ }
+ itemPtr->prevPtr->nextPtr = itemPtr->nextPtr;
+ }
+ if (canvasPtr->lastItemPtr == itemPtr) {
+ canvasPtr->lastItemPtr = itemPtr->prevPtr;
+ }
+ if (firstMovePtr == NULL) {
+ itemPtr->prevPtr = NULL;
+ firstMovePtr = itemPtr;
+ } else {
+ itemPtr->prevPtr = lastMovePtr;
+ lastMovePtr->nextPtr = itemPtr;
+ }
+ lastMovePtr = itemPtr;
+ EventuallyRedrawItem(canvasPtr, itemPtr);
+ canvasPtr->flags |= REPICK_NEEDED;
+ }
+
+ /*
+ * Insert the list of to-be-moved items back into the canvas's at the
+ * desired position.
+ */
+
+ if (firstMovePtr == NULL) {
+#ifdef USE_OLD_TAG_SEARCH
+ return;
+#else /* USE_OLD_TAG_SEARCH */
+ return TCL_OK;
+#endif /* USE_OLD_TAG_SEARCH */
+ }
+ if (prevPtr == NULL) {
+ if (canvasPtr->firstItemPtr != NULL) {
+ canvasPtr->firstItemPtr->prevPtr = lastMovePtr;
+ }
+ lastMovePtr->nextPtr = canvasPtr->firstItemPtr;
+ canvasPtr->firstItemPtr = firstMovePtr;
+ } else {
+ if (prevPtr->nextPtr != NULL) {
+ prevPtr->nextPtr->prevPtr = lastMovePtr;
+ }
+ lastMovePtr->nextPtr = prevPtr->nextPtr;
+ if (firstMovePtr != NULL) {
+ firstMovePtr->prevPtr = prevPtr;
+ }
+ prevPtr->nextPtr = firstMovePtr;
+ }
+ if (canvasPtr->lastItemPtr == prevPtr) {
+ canvasPtr->lastItemPtr = lastMovePtr;
+ }
+#ifndef USE_OLD_TAG_SEARCH
+ return TCL_OK;
+#endif /* not USE_OLD_TAG_SEARCH */
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * CanvasBindProc --
+ *
+ * This function is invoked by the Tk dispatcher to handle events
+ * associated with bindings on items.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Depends on the command invoked as part of the binding (if there was
+ * any).
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+CanvasBindProc(
+ ClientData clientData, /* Pointer to canvas structure. */
+ XEvent *eventPtr) /* Pointer to X event that just happened. */
+{
+ TkCanvas *canvasPtr = clientData;
+ int mask;
+
+ Tcl_Preserve(canvasPtr);
+
+ /*
+ * This code below keeps track of the current modifier state in
+ * canvasPtr>state. This information is used to defer repicks of the
+ * current item while buttons are down.
+ */
+
+ switch (eventPtr->type) {
+ case ButtonPress:
+ case ButtonRelease:
+ switch (eventPtr->xbutton.button) {
+ case Button1:
+ mask = Button1Mask;
+ break;
+ case Button2:
+ mask = Button2Mask;
+ break;
+ case Button3:
+ mask = Button3Mask;
+ break;
+ case Button4:
+ mask = Button4Mask;
+ break;
+ case Button5:
+ mask = Button5Mask;
+ break;
+ default:
+ mask = 0;
+ break;
+ }
+
+ /*
+ * For button press events, repick the current item using the button
+ * state before the event, then process the event. For button release
+ * events, first process the event, then repick the current item using
+ * the button state *after* the event (the button has logically gone
+ * up before we change the current item).
+ */
+
+ if (eventPtr->type == ButtonPress) {
+ /*
+ * On a button press, first repick the current item using the
+ * button state before the event, the process the event.
+ */
+
+ canvasPtr->state = eventPtr->xbutton.state;
+ PickCurrentItem(canvasPtr, eventPtr);
+ canvasPtr->state ^= mask;
+ CanvasDoEvent(canvasPtr, eventPtr);
+ } else {
+ /*
+ * Button release: first process the event, with the button still
+ * considered to be down. Then repick the current item under the
+ * assumption that the button is no longer down.
+ */
+
+ canvasPtr->state = eventPtr->xbutton.state;
+ CanvasDoEvent(canvasPtr, eventPtr);
+ eventPtr->xbutton.state ^= mask;
+ canvasPtr->state = eventPtr->xbutton.state;
+ PickCurrentItem(canvasPtr, eventPtr);
+ eventPtr->xbutton.state ^= mask;
+ }
+ break;
+ case EnterNotify:
+ case LeaveNotify:
+ canvasPtr->state = eventPtr->xcrossing.state;
+ PickCurrentItem(canvasPtr, eventPtr);
+ break;
+ case MotionNotify:
+ canvasPtr->state = eventPtr->xmotion.state;
+ PickCurrentItem(canvasPtr, eventPtr);
+ /* fallthrough */
+ default:
+ CanvasDoEvent(canvasPtr, eventPtr);
+ }
+
+ Tcl_Release(canvasPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * PickCurrentItem --
+ *
+ * Find the topmost item in a canvas that contains a given location and
+ * mark the the current item. If the current item has changed, generate a
+ * fake exit event on the old current item, a fake enter event on the new
+ * current item item and force a redraw of the two items. Canvas items
+ * that are hidden or disabled are ignored.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The current item for canvasPtr may change. If it does, then the
+ * commands associated with item entry and exit could do just about
+ * anything. A binding script could delete the canvas, so callers should
+ * protect themselves with Tcl_Preserve and Tcl_Release.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+PickCurrentItem(
+ TkCanvas *canvasPtr, /* Canvas widget in which to select current
+ * item. */
+ XEvent *eventPtr) /* Event describing location of mouse cursor.
+ * Must be EnterWindow, LeaveWindow,
+ * ButtonRelease, or MotionNotify. */
+{
+ double coords[2];
+ int buttonDown;
+ Tk_Item *prevItemPtr;
+#ifndef USE_OLD_TAG_SEARCH
+ SearchUids *searchUids = GetStaticUids();
+#endif
+
+ /*
+ * Check whether or not a button is down. If so, we'll log entry and exit
+ * into and out of the current item, but not entry into any other item.
+ * This implements a form of grabbing equivalent to what the X server does
+ * for windows.
+ */
+
+ buttonDown = canvasPtr->state
+ & (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask);
+
+ /*
+ * Save information about this event in the canvas. The event in the
+ * canvas is used for two purposes:
+ *
+ * 1. Event bindings: if the current item changes, fake events are
+ * generated to allow item-enter and item-leave bindings to trigger.
+ * 2. Reselection: if the current item gets deleted, can use the saved
+ * event to find a new current item.
+ *
+ * Translate MotionNotify events into EnterNotify events, since that's
+ * what gets reported to item handlers.
+ */
+
+ if (eventPtr != &canvasPtr->pickEvent) {
+ if ((eventPtr->type == MotionNotify)
+ || (eventPtr->type == ButtonRelease)) {
+ canvasPtr->pickEvent.xcrossing.type = EnterNotify;
+ canvasPtr->pickEvent.xcrossing.serial = eventPtr->xmotion.serial;
+ canvasPtr->pickEvent.xcrossing.send_event
+ = eventPtr->xmotion.send_event;
+ canvasPtr->pickEvent.xcrossing.display = eventPtr->xmotion.display;
+ canvasPtr->pickEvent.xcrossing.window = eventPtr->xmotion.window;
+ canvasPtr->pickEvent.xcrossing.root = eventPtr->xmotion.root;
+ canvasPtr->pickEvent.xcrossing.subwindow = None;
+ canvasPtr->pickEvent.xcrossing.time = eventPtr->xmotion.time;
+ canvasPtr->pickEvent.xcrossing.x = eventPtr->xmotion.x;
+ canvasPtr->pickEvent.xcrossing.y = eventPtr->xmotion.y;
+ canvasPtr->pickEvent.xcrossing.x_root = eventPtr->xmotion.x_root;
+ canvasPtr->pickEvent.xcrossing.y_root = eventPtr->xmotion.y_root;
+ canvasPtr->pickEvent.xcrossing.mode = NotifyNormal;
+ canvasPtr->pickEvent.xcrossing.detail = NotifyNonlinear;
+ canvasPtr->pickEvent.xcrossing.same_screen =
+ eventPtr->xmotion.same_screen;
+ canvasPtr->pickEvent.xcrossing.focus = False;
+ canvasPtr->pickEvent.xcrossing.state = eventPtr->xmotion.state;
+ } else {
+ canvasPtr->pickEvent = *eventPtr;
+ }
+ }
+
+ /*
+ * If this is a recursive call (there's already a partially completed call
+ * pending on the stack; it's in the middle of processing a Leave event
+ * handler for the old current item) then just return; the pending call
+ * will do everything that's needed.
+ */
+
+ if (canvasPtr->flags & REPICK_IN_PROGRESS) {
+ return;
+ }
+
+ /*
+ * A LeaveNotify event automatically means that there's no current object,
+ * so the check for closest item can be skipped.
+ */
+
+ coords[0] = canvasPtr->pickEvent.xcrossing.x + canvasPtr->xOrigin;
+ coords[1] = canvasPtr->pickEvent.xcrossing.y + canvasPtr->yOrigin;
+ if (canvasPtr->pickEvent.type != LeaveNotify) {
+ canvasPtr->newCurrentPtr = CanvasFindClosest(canvasPtr, coords);
+ } else {
+ canvasPtr->newCurrentPtr = NULL;
+ }
+
+ if ((canvasPtr->newCurrentPtr == canvasPtr->currentItemPtr)
+ && !(canvasPtr->flags & LEFT_GRABBED_ITEM)) {
+ /*
+ * Nothing to do: the current item hasn't changed.
+ */
+
+ return;
+ }
+
+ if (!buttonDown) {
+ canvasPtr->flags &= ~LEFT_GRABBED_ITEM;
+ }
+
+ /*
+ * Simulate a LeaveNotify event on the previous current item and an
+ * EnterNotify event on the new current item. Remove the "current" tag
+ * from the previous current item and place it on the new current item.
+ */
+
+ if ((canvasPtr->newCurrentPtr != canvasPtr->currentItemPtr)
+ && (canvasPtr->currentItemPtr != NULL)
+ && !(canvasPtr->flags & LEFT_GRABBED_ITEM)) {
+ XEvent event;
+ Tk_Item *itemPtr = canvasPtr->currentItemPtr;
+ int i;
+
+ event = canvasPtr->pickEvent;
+ event.type = LeaveNotify;
+
+ /*
+ * If the event's detail happens to be NotifyInferior the binding
+ * mechanism will discard the event. To be consistent, always use
+ * NotifyAncestor.
+ */
+
+ event.xcrossing.detail = NotifyAncestor;
+ canvasPtr->flags |= REPICK_IN_PROGRESS;
+ CanvasDoEvent(canvasPtr, &event);
+ canvasPtr->flags &= ~REPICK_IN_PROGRESS;
+
+ /*
+ * The check below is needed because there could be an event handler
+ * for <LeaveNotify> that deletes the current item.
+ */
+
+ if ((itemPtr == canvasPtr->currentItemPtr) && !buttonDown) {
+ for (i = itemPtr->numTags-1; i >= 0; i--) {
+#ifdef USE_OLD_TAG_SEARCH
+ if (itemPtr->tagPtr[i] == Tk_GetUid("current"))
+#else /* USE_OLD_TAG_SEARCH */
+ if (itemPtr->tagPtr[i] == searchUids->currentUid)
+#endif /* USE_OLD_TAG_SEARCH */
+ /* then */ {
+ itemPtr->tagPtr[i] = itemPtr->tagPtr[itemPtr->numTags-1];
+ itemPtr->numTags--;
+ break;
+ }
+ }
+ }
+
+ /*
+ * Note: during CanvasDoEvent above, it's possible that
+ * canvasPtr->newCurrentPtr got reset to NULL because the item was
+ * deleted.
+ */
+ }
+ if ((canvasPtr->newCurrentPtr!=canvasPtr->currentItemPtr) && buttonDown) {
+ canvasPtr->flags |= LEFT_GRABBED_ITEM;
+ return;
+ }
+
+ /*
+ * Special note: it's possible that canvasPtr->newCurrentPtr ==
+ * canvasPtr->currentItemPtr here. This can happen, for example, if
+ * LEFT_GRABBED_ITEM was set.
+ */
+
+ prevItemPtr = canvasPtr->currentItemPtr;
+ canvasPtr->flags &= ~LEFT_GRABBED_ITEM;
+ canvasPtr->currentItemPtr = canvasPtr->newCurrentPtr;
+ if (prevItemPtr != NULL && prevItemPtr != canvasPtr->currentItemPtr &&
+ (prevItemPtr->redraw_flags & TK_ITEM_STATE_DEPENDANT)) {
+ EventuallyRedrawItem(canvasPtr, prevItemPtr);
+ ItemConfigure(canvasPtr, prevItemPtr, 0, NULL);
+ }
+ if (canvasPtr->currentItemPtr != NULL) {
+ XEvent event;
+
+#ifdef USE_OLD_TAG_SEARCH
+ DoItem(NULL, canvasPtr->currentItemPtr, Tk_GetUid("current"));
+#else /* USE_OLD_TAG_SEARCH */
+ DoItem(NULL, canvasPtr->currentItemPtr, searchUids->currentUid);
+#endif /* USE_OLD_TAG_SEARCH */
+ if ((canvasPtr->currentItemPtr->redraw_flags & TK_ITEM_STATE_DEPENDANT
+ && prevItemPtr != canvasPtr->currentItemPtr)) {
+ ItemConfigure(canvasPtr, canvasPtr->currentItemPtr, 0, NULL);
+ EventuallyRedrawItem(canvasPtr, canvasPtr->currentItemPtr);
+ }
+ event = canvasPtr->pickEvent;
+ event.type = EnterNotify;
+ event.xcrossing.detail = NotifyAncestor;
+ CanvasDoEvent(canvasPtr, &event);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CanvasFindClosest --
+ *
+ * Given x and y coordinates, find the topmost canvas item that is
+ * "close" to the coordinates. Canvas items that are hidden or disabled
+ * are ignored.
+ *
+ * Results:
+ * The return value is a pointer to the topmost item that is close to
+ * (x,y), or NULL if no item is close.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tk_Item *
+CanvasFindClosest(
+ TkCanvas *canvasPtr, /* Canvas widget to search. */
+ double coords[2]) /* Desired x,y position in canvas, not screen,
+ * coordinates.) */
+{
+ Tk_Item *itemPtr;
+ Tk_Item *bestPtr;
+ int x1, y1, x2, y2;
+
+ x1 = (int) (coords[0] - canvasPtr->closeEnough);
+ y1 = (int) (coords[1] - canvasPtr->closeEnough);
+ x2 = (int) (coords[0] + canvasPtr->closeEnough);
+ y2 = (int) (coords[1] + canvasPtr->closeEnough);
+
+ bestPtr = NULL;
+ for (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;
+ itemPtr = itemPtr->nextPtr) {
+ if (itemPtr->state == TK_STATE_HIDDEN ||
+ itemPtr->state==TK_STATE_DISABLED ||
+ (itemPtr->state == TK_STATE_NULL &&
+ (canvasPtr->canvas_state == TK_STATE_HIDDEN ||
+ canvasPtr->canvas_state == TK_STATE_DISABLED))) {
+ continue;
+ }
+ if ((itemPtr->x1 > x2) || (itemPtr->x2 < x1)
+ || (itemPtr->y1 > y2) || (itemPtr->y2 < y1)) {
+ continue;
+ }
+ if (ItemPoint(canvasPtr,itemPtr,coords,0) <= canvasPtr->closeEnough) {
+ bestPtr = itemPtr;
+ }
+ }
+ return bestPtr;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * CanvasDoEvent --
+ *
+ * This function is called to invoke binding processing for a new event
+ * that is associated with the current item for a canvas.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Depends on the bindings for the canvas. A binding script could delete
+ * the canvas, so callers should protect themselves with Tcl_Preserve and
+ * Tcl_Release.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+CanvasDoEvent(
+ TkCanvas *canvasPtr, /* Canvas widget in which event occurred. */
+ XEvent *eventPtr) /* Real or simulated X event that is to be
+ * processed. */
+{
+#define NUM_STATIC 3
+ ClientData staticObjects[NUM_STATIC];
+ ClientData *objectPtr;
+ int numObjects, i;
+ Tk_Item *itemPtr;
+#ifndef USE_OLD_TAG_SEARCH
+ TagSearchExpr *expr;
+ int numExprs;
+ SearchUids *searchUids = GetStaticUids();
+#endif /* not USE_OLD_TAG_SEARCH */
+
+ if (canvasPtr->bindingTable == NULL) {
+ return;
+ }
+
+ itemPtr = canvasPtr->currentItemPtr;
+ if ((eventPtr->type == KeyPress) || (eventPtr->type == KeyRelease)) {
+ itemPtr = canvasPtr->textInfo.focusItemPtr;
+ }
+ if (itemPtr == NULL) {
+ return;
+ }
+
+#ifdef USE_OLD_TAG_SEARCH
+ /*
+ * Set up an array with all the relevant objects for processing this
+ * event. The relevant objects are (a) the event's item, (b) the tags
+ * associated with the event's item, and (c) the tag "all". If there are a
+ * lot of tags then malloc an array to hold all of the objects.
+ */
+
+ numObjects = itemPtr->numTags + 2;
+#else /* USE_OLD_TAG_SEARCH */
+ /*
+ * Set up an array with all the relevant objects for processing this
+ * event. The relevant objects are:
+ * (a) the event's item,
+ * (b) the tags associated with the event's item,
+ * (c) the expressions that are true for the event's item's tags, and
+ * (d) the tag "all".
+ *
+ * If there are a lot of tags then malloc an array to hold all of the
+ * objects.
+ */
+
+ /*
+ * Flag and count all expressions that match item's tags.
+ */
+
+ numExprs = 0;
+ expr = canvasPtr->bindTagExprs;
+ while (expr) {
+ expr->index = 0;
+ expr->match = TagSearchEvalExpr(expr, itemPtr);
+ if (expr->match) {
+ numExprs++;
+ }
+ expr = expr->next;
+ }
+
+ numObjects = itemPtr->numTags + numExprs + 2;
+#endif /* not USE_OLD_TAG_SEARCH */
+ if (numObjects <= NUM_STATIC) {
+ objectPtr = staticObjects;
+ } else {
+ objectPtr = ckalloc(numObjects * sizeof(ClientData));
+ }
+#ifdef USE_OLD_TAG_SEARCH
+ objectPtr[0] = (ClientData) Tk_GetUid("all");
+#else /* USE_OLD_TAG_SEARCH */
+ objectPtr[0] = (ClientData) searchUids->allUid;
+#endif /* USE_OLD_TAG_SEARCH */
+ for (i = itemPtr->numTags-1; i >= 0; i--) {
+ objectPtr[i+1] = (ClientData) itemPtr->tagPtr[i];
+ }
+ objectPtr[itemPtr->numTags+1] = itemPtr;
+
+#ifndef USE_OLD_TAG_SEARCH
+ /*
+ * Copy uids of matching expressions into object array
+ */
+
+ i = itemPtr->numTags+2;
+ expr = canvasPtr->bindTagExprs;
+ while (expr) {
+ if (expr->match) {
+ objectPtr[i++] = (int *) expr->uid;
+ }
+ expr = expr->next;
+ }
+#endif /* not USE_OLD_TAG_SEARCH */
+
+ /*
+ * Invoke the binding system, then free up the object array if it was
+ * malloc-ed.
+ */
+
+ if (canvasPtr->tkwin != NULL) {
+ Tk_BindEvent(canvasPtr->bindingTable, eventPtr, canvasPtr->tkwin,
+ numObjects, objectPtr);
+ }
+ if (objectPtr != staticObjects) {
+ ckfree(objectPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CanvasBlinkProc --
+ *
+ * This function is called as a timer handler to blink the insertion
+ * cursor off and on.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The cursor gets turned on or off, redisplay gets invoked, and this
+ * function reschedules itself.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+CanvasBlinkProc(
+ ClientData clientData) /* Pointer to record describing entry. */
+{
+ TkCanvas *canvasPtr = clientData;
+
+ if (!canvasPtr->textInfo.gotFocus || (canvasPtr->insertOffTime == 0)) {
+ return;
+ }
+ if (canvasPtr->textInfo.cursorOn) {
+ canvasPtr->textInfo.cursorOn = 0;
+ canvasPtr->insertBlinkHandler = Tcl_CreateTimerHandler(
+ canvasPtr->insertOffTime, CanvasBlinkProc, canvasPtr);
+ } else {
+ canvasPtr->textInfo.cursorOn = 1;
+ canvasPtr->insertBlinkHandler = Tcl_CreateTimerHandler(
+ canvasPtr->insertOnTime, CanvasBlinkProc, canvasPtr);
+ }
+ EventuallyRedrawItem(canvasPtr, canvasPtr->textInfo.focusItemPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CanvasFocusProc --
+ *
+ * This function is called whenever a canvas gets or loses the input
+ * focus. It's also called whenever the window is reconfigured while it
+ * has the focus.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The cursor gets turned on or off.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+CanvasFocusProc(
+ TkCanvas *canvasPtr, /* Canvas that just got or lost focus. */
+ int gotFocus) /* 1 means window is getting focus, 0 means
+ * it's losing it. */
+{
+ Tcl_DeleteTimerHandler(canvasPtr->insertBlinkHandler);
+ if (gotFocus) {
+ canvasPtr->textInfo.gotFocus = 1;
+ canvasPtr->textInfo.cursorOn = 1;
+ if (canvasPtr->insertOffTime != 0) {
+ canvasPtr->insertBlinkHandler = Tcl_CreateTimerHandler(
+ canvasPtr->insertOffTime, CanvasBlinkProc, canvasPtr);
+ }
+ } else {
+ canvasPtr->textInfo.gotFocus = 0;
+ canvasPtr->textInfo.cursorOn = 0;
+ canvasPtr->insertBlinkHandler = NULL;
+ }
+ EventuallyRedrawItem(canvasPtr, canvasPtr->textInfo.focusItemPtr);
+ if (canvasPtr->highlightWidth > 0) {
+ canvasPtr->flags |= REDRAW_BORDERS;
+ if (!(canvasPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DisplayCanvas, canvasPtr);
+ canvasPtr->flags |= REDRAW_PENDING;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CanvasSelectTo --
+ *
+ * Modify the selection by moving its un-anchored end. This could make
+ * the selection either larger or smaller.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The selection changes.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+CanvasSelectTo(
+ TkCanvas *canvasPtr, /* Information about widget. */
+ Tk_Item *itemPtr, /* Item that is to hold selection. */
+ int index) /* Index of element that is to become the
+ * "other" end of the selection. */
+{
+ int oldFirst, oldLast;
+ Tk_Item *oldSelPtr;
+
+ oldFirst = canvasPtr->textInfo.selectFirst;
+ oldLast = canvasPtr->textInfo.selectLast;
+ oldSelPtr = canvasPtr->textInfo.selItemPtr;
+
+ /*
+ * Grab the selection if we don't own it already.
+ */
+
+ if (canvasPtr->textInfo.selItemPtr == NULL) {
+ Tk_OwnSelection(canvasPtr->tkwin, XA_PRIMARY, CanvasLostSelection,
+ canvasPtr);
+ } else if (canvasPtr->textInfo.selItemPtr != itemPtr) {
+ EventuallyRedrawItem(canvasPtr, canvasPtr->textInfo.selItemPtr);
+ }
+ canvasPtr->textInfo.selItemPtr = itemPtr;
+
+ if (canvasPtr->textInfo.anchorItemPtr != itemPtr) {
+ canvasPtr->textInfo.anchorItemPtr = itemPtr;
+ canvasPtr->textInfo.selectAnchor = index;
+ }
+ if (canvasPtr->textInfo.selectAnchor <= index) {
+ canvasPtr->textInfo.selectFirst = canvasPtr->textInfo.selectAnchor;
+ canvasPtr->textInfo.selectLast = index;
+ } else {
+ canvasPtr->textInfo.selectFirst = index;
+ canvasPtr->textInfo.selectLast = canvasPtr->textInfo.selectAnchor - 1;
+ }
+ if ((canvasPtr->textInfo.selectFirst != oldFirst)
+ || (canvasPtr->textInfo.selectLast != oldLast)
+ || (itemPtr != oldSelPtr)) {
+ EventuallyRedrawItem(canvasPtr, itemPtr);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * CanvasFetchSelection --
+ *
+ * This function is invoked by Tk to return part or all of the selection,
+ * when the selection is in a canvas widget. This function always returns
+ * the selection as a STRING.
+ *
+ * Results:
+ * The return value is the number of non-NULL bytes stored at buffer.
+ * Buffer is filled (or partially filled) with a NULL-terminated string
+ * containing part or all of the selection, as given by offset and
+ * maxBytes.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+CanvasFetchSelection(
+ ClientData clientData, /* Information about canvas widget. */
+ int offset, /* Offset within selection of first character
+ * to be returned. */
+ char *buffer, /* Location in which to place selection. */
+ int maxBytes) /* Maximum number of bytes to place at buffer,
+ * not including terminating NULL
+ * character. */
+{
+ TkCanvas *canvasPtr = clientData;
+
+ return ItemSelection(canvasPtr, canvasPtr->textInfo.selItemPtr, offset,
+ buffer, maxBytes);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CanvasLostSelection --
+ *
+ * This function is called back by Tk when the selection is grabbed away
+ * from a canvas widget.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The existing selection is unhighlighted, and the window is marked as
+ * not containing a selection.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+CanvasLostSelection(
+ ClientData clientData) /* Information about entry widget. */
+{
+ TkCanvas *canvasPtr = clientData;
+
+ EventuallyRedrawItem(canvasPtr, canvasPtr->textInfo.selItemPtr);
+ canvasPtr->textInfo.selItemPtr = NULL;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * GridAlign --
+ *
+ * Given a coordinate and a grid spacing, this function computes the
+ * location of the nearest grid line to the coordinate.
+ *
+ * Results:
+ * The return value is the location of the grid line nearest to coord.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static double
+GridAlign(
+ double coord, /* Coordinate to grid-align. */
+ double spacing) /* Spacing between grid lines. If <= 0 then no
+ * alignment is done. */
+{
+ if (spacing <= 0.0) {
+ return coord;
+ }
+ if (coord < 0) {
+ return -((int) ((-coord)/spacing + 0.5)) * spacing;
+ }
+ return ((int) (coord/spacing + 0.5)) * spacing;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ScrollFractions --
+ *
+ * Given the range that's visible in the window and the "100% range" for
+ * what's in the canvas, return a list of two doubles representing the
+ * scroll fractions. This function is used for both x and y scrolling.
+ *
+ * Results:
+ * A List Tcl_Obj with two real numbers (Double Tcl_Objs) containing the
+ * scroll fractions (between 0 and 1) corresponding to the other
+ * arguments.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj *
+ScrollFractions(
+ int screen1, /* Lowest coordinate visible in the window. */
+ int screen2, /* Highest coordinate visible in the window. */
+ int object1, /* Lowest coordinate in the object. */
+ int object2) /* Highest coordinate in the object. */
+{
+ Tcl_Obj *buffer[2];
+ double range, f1, f2;
+
+ range = object2 - object1;
+ if (range <= 0) {
+ f1 = 0;
+ f2 = 1.0;
+ } else {
+ f1 = (screen1 - object1)/range;
+ if (f1 < 0) {
+ f1 = 0.0;
+ }
+ f2 = (screen2 - object1)/range;
+ if (f2 > 1.0) {
+ f2 = 1.0;
+ }
+ if (f2 < f1) {
+ f2 = f1;
+ }
+ }
+ buffer[0] = Tcl_NewDoubleObj(f1);
+ buffer[1] = Tcl_NewDoubleObj(f2);
+ return Tcl_NewListObj(2, buffer);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * CanvasUpdateScrollbars --
+ *
+ * This function is invoked whenever a canvas has changed in a way that
+ * requires scrollbars to be redisplayed (e.g. the view in the canvas has
+ * changed).
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If there are scrollbars associated with the canvas, then their
+ * scrolling commands are invoked to cause them to redisplay. If errors
+ * occur, additional Tcl commands may be invoked to process the errors.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+CanvasUpdateScrollbars(
+ TkCanvas *canvasPtr) /* Information about canvas. */
+{
+ int result;
+ Tcl_Interp *interp;
+ int xOrigin, yOrigin, inset, width, height;
+ int scrollX1, scrollX2, scrollY1, scrollY2;
+ char *xScrollCmd, *yScrollCmd;
+ Tcl_DString buf;
+
+ /*
+ * Save all the relevant values from the canvasPtr, because it might be
+ * deleted as part of either of the two calls to Tcl_VarEval below.
+ */
+
+ interp = canvasPtr->interp;
+ Tcl_Preserve(interp);
+ xScrollCmd = canvasPtr->xScrollCmd;
+ if (xScrollCmd != NULL) {
+ Tcl_Preserve(xScrollCmd);
+ }
+ yScrollCmd = canvasPtr->yScrollCmd;
+ if (yScrollCmd != NULL) {
+ Tcl_Preserve(yScrollCmd);
+ }
+ xOrigin = canvasPtr->xOrigin;
+ yOrigin = canvasPtr->yOrigin;
+ inset = canvasPtr->inset;
+ width = Tk_Width(canvasPtr->tkwin);
+ height = Tk_Height(canvasPtr->tkwin);
+ scrollX1 = canvasPtr->scrollX1;
+ scrollX2 = canvasPtr->scrollX2;
+ scrollY1 = canvasPtr->scrollY1;
+ scrollY2 = canvasPtr->scrollY2;
+ canvasPtr->flags &= ~UPDATE_SCROLLBARS;
+ if (canvasPtr->xScrollCmd != NULL) {
+ Tcl_Obj *fractions = ScrollFractions(xOrigin + inset,
+ xOrigin + width - inset, scrollX1, scrollX2);
+
+ Tcl_DStringInit(&buf);
+ Tcl_DStringAppend(&buf, xScrollCmd, -1);
+ Tcl_DStringAppend(&buf, " ", -1);
+ Tcl_DStringAppend(&buf, Tcl_GetString(fractions), -1);
+ result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0);
+ Tcl_DStringFree(&buf);
+ Tcl_DecrRefCount(fractions);
+ if (result != TCL_OK) {
+ Tcl_BackgroundException(interp, result);
+ }
+ Tcl_ResetResult(interp);
+ Tcl_Release(xScrollCmd);
+ }
+
+ if (yScrollCmd != NULL) {
+ Tcl_Obj *fractions = ScrollFractions(yOrigin + inset,
+ yOrigin + height - inset, scrollY1, scrollY2);
+
+ Tcl_DStringInit(&buf);
+ Tcl_DStringAppend(&buf, yScrollCmd, -1);
+ Tcl_DStringAppend(&buf, " ", -1);
+ Tcl_DStringAppend(&buf, Tcl_GetString(fractions), -1);
+ result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0);
+ Tcl_DStringFree(&buf);
+ Tcl_DecrRefCount(fractions);
+ if (result != TCL_OK) {
+ Tcl_BackgroundException(interp, result);
+ }
+ Tcl_ResetResult(interp);
+ Tcl_Release(yScrollCmd);
+ }
+ Tcl_Release(interp);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * CanvasSetOrigin --
+ *
+ * This function is invoked to change the mapping between canvas
+ * coordinates and screen coordinates in the canvas window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The canvas will be redisplayed to reflect the change in view. In
+ * addition, scrollbars will be updated if there are any.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+CanvasSetOrigin(
+ TkCanvas *canvasPtr, /* Information about canvas. */
+ int xOrigin, /* New X origin for canvas (canvas x-coord
+ * corresponding to left edge of canvas
+ * window). */
+ int yOrigin) /* New Y origin for canvas (canvas y-coord
+ * corresponding to top edge of canvas
+ * window). */
+{
+ int left, right, top, bottom, delta;
+
+ /*
+ * If scroll increments have been set, round the window origin to the
+ * nearest multiple of the increments. Remember, the origin is the place
+ * just inside the borders, not the upper left corner.
+ */
+
+ if (canvasPtr->xScrollIncrement > 0) {
+ if (xOrigin >= 0) {
+ xOrigin += canvasPtr->xScrollIncrement/2;
+ xOrigin -= (xOrigin + canvasPtr->inset)
+ % canvasPtr->xScrollIncrement;
+ } else {
+ xOrigin = (-xOrigin) + canvasPtr->xScrollIncrement/2;
+ xOrigin = -(xOrigin - (xOrigin - canvasPtr->inset)
+ % canvasPtr->xScrollIncrement);
+ }
+ }
+ if (canvasPtr->yScrollIncrement > 0) {
+ if (yOrigin >= 0) {
+ yOrigin += canvasPtr->yScrollIncrement/2;
+ yOrigin -= (yOrigin + canvasPtr->inset)
+ % canvasPtr->yScrollIncrement;
+ } else {
+ yOrigin = (-yOrigin) + canvasPtr->yScrollIncrement/2;
+ yOrigin = -(yOrigin - (yOrigin - canvasPtr->inset)
+ % canvasPtr->yScrollIncrement);
+ }
+ }
+
+ /*
+ * Adjust the origin if necessary to keep as much as possible of the
+ * canvas in the view. The variables left, right, etc. keep track of how
+ * much extra space there is on each side of the view before it will stick
+ * out past the scroll region. If one side sticks out past the edge of the
+ * scroll region, adjust the view to bring that side back to the edge of
+ * the scrollregion (but don't move it so much that the other side sticks
+ * out now). If scroll increments are in effect, be sure to adjust only by
+ * full increments.
+ */
+
+ if ((canvasPtr->confine) && (canvasPtr->regionString != NULL)) {
+ left = xOrigin + canvasPtr->inset - canvasPtr->scrollX1;
+ right = canvasPtr->scrollX2
+ - (xOrigin + Tk_Width(canvasPtr->tkwin) - canvasPtr->inset);
+ top = yOrigin + canvasPtr->inset - canvasPtr->scrollY1;
+ bottom = canvasPtr->scrollY2
+ - (yOrigin + Tk_Height(canvasPtr->tkwin) - canvasPtr->inset);
+ if ((left < 0) && (right > 0)) {
+ delta = (right > -left) ? -left : right;
+ if (canvasPtr->xScrollIncrement > 0) {
+ delta -= delta % canvasPtr->xScrollIncrement;
+ }
+ xOrigin += delta;
+ } else if ((right < 0) && (left > 0)) {
+ delta = (left > -right) ? -right : left;
+ if (canvasPtr->xScrollIncrement > 0) {
+ delta -= delta % canvasPtr->xScrollIncrement;
+ }
+ xOrigin -= delta;
+ }
+ if ((top < 0) && (bottom > 0)) {
+ delta = (bottom > -top) ? -top : bottom;
+ if (canvasPtr->yScrollIncrement > 0) {
+ delta -= delta % canvasPtr->yScrollIncrement;
+ }
+ yOrigin += delta;
+ } else if ((bottom < 0) && (top > 0)) {
+ delta = (top > -bottom) ? -bottom : top;
+ if (canvasPtr->yScrollIncrement > 0) {
+ delta -= delta % canvasPtr->yScrollIncrement;
+ }
+ yOrigin -= delta;
+ }
+ }
+
+ if ((xOrigin == canvasPtr->xOrigin) && (yOrigin == canvasPtr->yOrigin)) {
+ return;
+ }
+
+ /*
+ * Tricky point: must redisplay not only everything that's visible in the
+ * window's final configuration, but also everything that was visible in
+ * the initial configuration. This is needed because some item types, like
+ * windows, need to know when they move off-screen so they can explicitly
+ * undisplay themselves.
+ */
+
+ Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
+ canvasPtr->xOrigin, canvasPtr->yOrigin,
+ canvasPtr->xOrigin + Tk_Width(canvasPtr->tkwin),
+ canvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin));
+ canvasPtr->xOrigin = xOrigin;
+ canvasPtr->yOrigin = yOrigin;
+ canvasPtr->flags |= UPDATE_SCROLLBARS;
+ Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
+ canvasPtr->xOrigin, canvasPtr->yOrigin,
+ canvasPtr->xOrigin + Tk_Width(canvasPtr->tkwin),
+ canvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin));
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkGetStringsFromObjs --
+ *
+ * Results:
+ * Converts object list into string list.
+ *
+ * Side effects:
+ * Memory is allocated for the objv array, which must be freed using
+ * ckfree() when no longer needed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+/* ARGSUSED */
+static const char **
+TkGetStringsFromObjs(
+ int objc,
+ Tcl_Obj *const objv[])
+{
+ register int i;
+ const char **argv;
+
+ if (objc <= 0) {
+ return NULL;
+ }
+ argv = ckalloc((objc+1) * sizeof(char *));
+ for (i = 0; i < objc; i++) {
+ argv[i] = Tcl_GetString(objv[i]);
+ }
+ argv[objc] = 0;
+ return argv;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CanvasPsColor --
+ *
+ * This function is called by individual canvas items when they want to
+ * set a color value for output. Given information about an X color, this
+ * function will generate Postscript commands to set up an appropriate
+ * color in Postscript.
+ *
+ * Results:
+ * Returns a standard Tcl return value. If an error occurs then an error
+ * message will be left in interp->result. If no error occurs, then
+ * additional Postscript will be appended to interp->result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_CanvasPsColor(
+ Tcl_Interp *interp, /* Interpreter for returning Postscript or
+ * error message. */
+ Tk_Canvas canvas, /* Information about canvas. */
+ XColor *colorPtr) /* Information about color. */
+{
+ return Tk_PostscriptColor(interp, Canvas(canvas)->psInfo, colorPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CanvasPsFont --
+ *
+ * This function is called by individual canvas items when they want to
+ * output text. Given information about an X font, this function will
+ * generate Postscript commands to set up an appropriate font in
+ * Postscript.
+ *
+ * Results:
+ * Returns a standard Tcl return value. If an error occurs then an error
+ * message will be left in interp->result. If no error occurs, then
+ * additional Postscript will be appended to the interp->result.
+ *
+ * Side effects:
+ * The Postscript font name is entered into psInfoPtr->fontTable if it
+ * wasn't already there.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_CanvasPsFont(
+ Tcl_Interp *interp, /* Interpreter for returning Postscript or
+ * error message. */
+ Tk_Canvas canvas, /* Information about canvas. */
+ Tk_Font tkfont) /* Information about font in which text is to
+ * be printed. */
+{
+ return Tk_PostscriptFont(interp, Canvas(canvas)->psInfo, tkfont);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CanvasPsBitmap --
+ *
+ * This function is called to output the contents of a sub-region of a
+ * bitmap in proper image data format for Postscript (i.e. data between
+ * angle brackets, one bit per pixel).
+ *
+ * Results:
+ * Returns a standard Tcl return value. If an error occurs then an error
+ * message will be left in interp->result. If no error occurs, then
+ * additional Postscript will be appended to interp->result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_CanvasPsBitmap(
+ Tcl_Interp *interp, /* Interpreter for returning Postscript or
+ * error message. */
+ Tk_Canvas canvas, /* Information about canvas. */
+ Pixmap bitmap, /* Bitmap for which to generate Postscript. */
+ int startX, int startY, /* Coordinates of upper-left corner of
+ * rectangular region to output. */
+ int width, int height) /* Size of rectangular region. */
+{
+ return Tk_PostscriptBitmap(interp, Canvas(canvas)->tkwin,
+ Canvas(canvas)->psInfo, bitmap, startX, startY, width, height);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CanvasPsStipple --
+ *
+ * This function is called by individual canvas items when they have
+ * created a path that they'd like to be filled with a stipple pattern.
+ * Given information about an X bitmap, this function will generate
+ * Postscript commands to fill the current clip region using a stipple
+ * pattern defined by the bitmap.
+ *
+ * Results:
+ * Returns a standard Tcl return value. If an error occurs then an error
+ * message will be left in interp->result. If no error occurs, then
+ * additional Postscript will be appended to interp->result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_CanvasPsStipple(
+ Tcl_Interp *interp, /* Interpreter for returning Postscript or
+ * error message. */
+ Tk_Canvas canvas, /* Information about canvas. */
+ Pixmap bitmap) /* Bitmap to use for stippling. */
+{
+ return Tk_PostscriptStipple(interp, Canvas(canvas)->tkwin,
+ Canvas(canvas)->psInfo, bitmap);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CanvasPsY --
+ *
+ * Given a y-coordinate in canvas coordinates, this function returns a
+ * y-coordinate to use for Postscript output.
+ *
+ * Results:
+ * Returns the Postscript coordinate that corresponds to "y".
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+double
+Tk_CanvasPsY(
+ Tk_Canvas canvas, /* Token for canvas on whose behalf Postscript
+ * is being generated. */
+ double y) /* Y-coordinate in canvas coords. */
+{
+ return Tk_PostscriptY(y, Canvas(canvas)->psInfo);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CanvasPsPath --
+ *
+ * Given an array of points for a path, generate Postscript commands to
+ * create the path.
+ *
+ * Results:
+ * Postscript commands get appended to what's in interp->result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_CanvasPsPath(
+ Tcl_Interp *interp, /* Put generated Postscript in this
+ * interpreter's result field. */
+ Tk_Canvas canvas, /* Canvas on whose behalf Postscript is being
+ * generated. */
+ double *coordPtr, /* Pointer to first in array of 2*numPoints
+ * coordinates giving points for path. */
+ int numPoints) /* Number of points at *coordPtr. */
+{
+ Tk_PostscriptPath(interp, Canvas(canvas)->psInfo, coordPtr, numPoints);
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkCanvas.h b/tk8.6/generic/tkCanvas.h
new file mode 100644
index 0000000..e2221a8
--- /dev/null
+++ b/tk8.6/generic/tkCanvas.h
@@ -0,0 +1,312 @@
+/*
+ * tkCanvas.h --
+ *
+ * Declarations shared among all the files that implement canvas widgets.
+ *
+ * Copyright (c) 1991-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ * Copyright (c) 1998 by Scriptics Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef _TKCANVAS
+#define _TKCANVAS
+
+#ifndef _TK
+#include "tk.h"
+#endif
+
+#ifndef USE_OLD_TAG_SEARCH
+typedef struct TagSearchExpr_s TagSearchExpr;
+
+struct TagSearchExpr_s {
+ TagSearchExpr *next; /* For linked lists of expressions - used in
+ * bindings. */
+ Tk_Uid uid; /* The uid of the whole expression. */
+ Tk_Uid *uids; /* Expresion compiled to an array of uids. */
+ int allocated; /* Available space for array of uids. */
+ int length; /* Length of expression. */
+ int index; /* Current position in expression
+ * evaluation. */
+ int match; /* This expression matches event's item's
+ * tags. */
+};
+#endif /* not USE_OLD_TAG_SEARCH */
+
+/*
+ * The record below describes a canvas widget. It is made available to the
+ * item functions so they can access certain shared fields such as the overall
+ * displacement and scale factor for the canvas.
+ */
+
+typedef struct TkCanvas {
+ Tk_Window tkwin; /* Window that embodies the canvas. NULL means
+ * that the window has been destroyed but the
+ * data structures haven't yet been cleaned
+ * up.*/
+ Display *display; /* Display containing widget; needed, among
+ * other things, to release resources after
+ * tkwin has already gone away. */
+ Tcl_Interp *interp; /* Interpreter associated with canvas. */
+ Tcl_Command widgetCmd; /* Token for canvas's widget command. */
+ Tk_Item *firstItemPtr; /* First in list of all items in canvas, or
+ * NULL if canvas empty. */
+ Tk_Item *lastItemPtr; /* Last in list of all items in canvas, or
+ * NULL if canvas empty. */
+
+ /*
+ * Information used when displaying widget:
+ */
+
+ int borderWidth; /* Width of 3-D border around window. */
+ Tk_3DBorder bgBorder; /* Used for canvas background. */
+ int relief; /* Indicates whether window as a whole is
+ * raised, sunken, or flat. */
+ int highlightWidth; /* Width in pixels of highlight to draw around
+ * widget when it has the focus. <= 0 means
+ * don't draw a highlight. */
+ XColor *highlightBgColorPtr;
+ /* Color for drawing traversal highlight area
+ * when highlight is off. */
+ XColor *highlightColorPtr; /* Color for drawing traversal highlight. */
+ int inset; /* Total width of all borders, including
+ * traversal highlight and 3-D border.
+ * Indicates how much interior stuff must be
+ * offset from outside edges to leave room for
+ * borders. */
+ GC pixmapGC; /* Used to copy bits from a pixmap to the
+ * screen and also to clear the pixmap. */
+ int width, height; /* Dimensions to request for canvas window,
+ * specified in pixels. */
+ int redrawX1, redrawY1; /* Upper left corner of area to redraw, in
+ * pixel coordinates. Border pixels are
+ * included. Only valid if REDRAW_PENDING flag
+ * is set. */
+ int redrawX2, redrawY2; /* Lower right corner of area to redraw, in
+ * integer canvas coordinates. Border pixels
+ * will *not* be redrawn. */
+ int confine; /* Non-zero means constrain view to keep as
+ * much of canvas visible as possible. */
+
+ /*
+ * Information used to manage the selection and insertion cursor:
+ */
+
+ Tk_CanvasTextInfo textInfo; /* Contains lots of fields; see tk.h for
+ * details. This structure is shared with the
+ * code that implements individual items. */
+ int insertOnTime; /* Number of milliseconds cursor should spend
+ * in "on" state for each blink. */
+ int insertOffTime; /* Number of milliseconds cursor should spend
+ * in "off" state for each blink. */
+ Tcl_TimerToken insertBlinkHandler;
+ /* Timer handler used to blink cursor on and
+ * off. */
+
+ /*
+ * Transformation applied to canvas as a whole: to compute screen
+ * coordinates (X,Y) from canvas coordinates (x,y), do the following:
+ *
+ * X = x - xOrigin;
+ * Y = y - yOrigin;
+ */
+
+ int xOrigin, yOrigin; /* Canvas coordinates corresponding to
+ * upper-left corner of window, given in
+ * canvas pixel units. */
+ int drawableXOrigin, drawableYOrigin;
+ /* During redisplay, these fields give the
+ * canvas coordinates corresponding to the
+ * upper-left corner of the drawable where
+ * items are actually being drawn (typically a
+ * pixmap smaller than the whole window). */
+
+ /*
+ * Information used for event bindings associated with items.
+ */
+
+ Tk_BindingTable bindingTable;
+ /* Table of all bindings currently defined for
+ * this canvas. NULL means that no bindings
+ * exist, so the table hasn't been created.
+ * Each "object" used for this table is either
+ * a Tk_Uid for a tag or the address of an
+ * item named by id. */
+ Tk_Item *currentItemPtr; /* The item currently containing the mouse
+ * pointer, or NULL if none. */
+ Tk_Item *newCurrentPtr; /* The item that is about to become the
+ * current one, or NULL. This field is used to
+ * detect deletions of the new current item
+ * pointer that occur during Leave processing
+ * of the previous current item. */
+ double closeEnough; /* The mouse is assumed to be inside an item
+ * if it is this close to it. */
+ XEvent pickEvent; /* The event upon which the current choice of
+ * currentItem is based. Must be saved so that
+ * if the currentItem is deleted, can pick
+ * another. */
+ int state; /* Last known modifier state. Used to defer
+ * picking a new current object while buttons
+ * are down. */
+
+ /*
+ * Information used for managing scrollbars:
+ */
+
+ char *xScrollCmd; /* Command prefix for communicating with
+ * horizontal scrollbar. NULL means no
+ * horizontal scrollbar. Malloc'ed. */
+ char *yScrollCmd; /* Command prefix for communicating with
+ * vertical scrollbar. NULL means no vertical
+ * scrollbar. Malloc'ed. */
+ int scrollX1, scrollY1, scrollX2, scrollY2;
+ /* These four coordinates define the region
+ * that is the 100% area for scrolling (i.e.
+ * these numbers determine the size and
+ * location of the sliders on scrollbars).
+ * Units are pixels in canvas coords. */
+ char *regionString; /* The option string from which scrollX1 etc.
+ * are derived. Malloc'ed. */
+ int xScrollIncrement; /* If >0, defines a grid for horizontal
+ * scrolling. This is the size of the "unit",
+ * and the left edge of the screen will always
+ * lie on an even unit boundary. */
+ int yScrollIncrement; /* If >0, defines a grid for horizontal
+ * scrolling. This is the size of the "unit",
+ * and the left edge of the screen will always
+ * lie on an even unit boundary. */
+
+ /*
+ * Information used for scanning:
+ */
+
+ int scanX; /* X-position at which scan started (e.g.
+ * button was pressed here). */
+ int scanXOrigin; /* Value of xOrigin field when scan started. */
+ int scanY; /* Y-position at which scan started (e.g.
+ * button was pressed here). */
+ int scanYOrigin; /* Value of yOrigin field when scan started. */
+
+ /*
+ * Information used to speed up searches by remembering the last item
+ * created or found with an item id search.
+ */
+
+ Tk_Item *hotPtr; /* Pointer to "hot" item (one that's been
+ * recently used. NULL means there's no hot
+ * item. */
+ Tk_Item *hotPrevPtr; /* Pointer to predecessor to hotPtr (NULL
+ * means item is first in list). This is only
+ * a hint and may not really be hotPtr's
+ * predecessor. */
+
+ /*
+ * Miscellaneous information:
+ */
+
+ Tk_Cursor cursor; /* Current cursor for window, or NULL. */
+ char *takeFocus; /* Value of -takefocus option; not used in the
+ * C code, but used by keyboard traversal
+ * scripts. Malloc'ed, but may be NULL. */
+ double pixelsPerMM; /* Scale factor between MM and pixels; used
+ * when converting coordinates. */
+ int flags; /* Various flags; see below for
+ * definitions. */
+ int nextId; /* Number to use as id for next item created
+ * in widget. */
+ Tk_PostscriptInfo psInfo; /* Pointer to information used for generating
+ * Postscript for the canvas. NULL means no
+ * Postscript is currently being generated. */
+ Tcl_HashTable idTable; /* Table of integer indices. */
+
+ /*
+ * Additional information, added by the 'dash'-patch
+ */
+
+ void *reserved1;
+ Tk_State canvas_state; /* State of canvas. */
+ void *reserved2;
+ void *reserved3;
+ Tk_TSOffset tsoffset;
+#ifndef USE_OLD_TAG_SEARCH
+ TagSearchExpr *bindTagExprs;/* Linked list of tag expressions used in
+ * bindings. */
+#endif
+} TkCanvas;
+
+/*
+ * Flag bits for canvases:
+ *
+ * REDRAW_PENDING - 1 means a DoWhenIdle handler has already been
+ * created to redraw some or all of the canvas.
+ * REDRAW_BORDERS - 1 means that the borders need to be redrawn
+ * during the next redisplay operation.
+ * REPICK_NEEDED - 1 means DisplayCanvas should pick a new
+ * current item before redrawing the canvas.
+ * GOT_FOCUS - 1 means the focus is currently in this widget,
+ * so should draw the insertion cursor and
+ * traversal highlight.
+ * CURSOR_ON - 1 means the insertion cursor is in the "on"
+ * phase of its blink cycle. 0 means either we
+ * don't have the focus or the cursor is in the
+ * "off" phase of its cycle.
+ * UPDATE_SCROLLBARS - 1 means the scrollbars should get updated as
+ * part of the next display operation.
+ * LEFT_GRABBED_ITEM - 1 means that the mouse left the current item
+ * while a grab was in effect, so we didn't
+ * change canvasPtr->currentItemPtr.
+ * REPICK_IN_PROGRESS - 1 means PickCurrentItem is currently
+ * executing. If it should be called recursively,
+ * it should simply return immediately.
+ * BBOX_NOT_EMPTY - 1 means that the bounding box of the area that
+ * should be redrawn is not empty.
+ */
+
+#define REDRAW_PENDING 1
+#define REDRAW_BORDERS 2
+#define REPICK_NEEDED 4
+#define GOT_FOCUS 8
+#define CURSOR_ON 0x10
+#define UPDATE_SCROLLBARS 0x20
+#define LEFT_GRABBED_ITEM 0x40
+#define REPICK_IN_PROGRESS 0x100
+#define BBOX_NOT_EMPTY 0x200
+
+/*
+ * Flag bits for canvas items (redraw_flags):
+ *
+ * FORCE_REDRAW - 1 means that the new coordinates of some item
+ * are not yet registered using
+ * Tk_CanvasEventuallyRedraw(). It should still
+ * be done by the general canvas code.
+ */
+
+#define FORCE_REDRAW 8
+
+/*
+ * Canvas-related functions that are shared among Tk modules but not exported
+ * to the outside world:
+ */
+
+MODULE_SCOPE int TkCanvPostscriptCmd(TkCanvas *canvasPtr,
+ Tcl_Interp *interp, int argc, const char **argv);
+MODULE_SCOPE int TkCanvTranslatePath(TkCanvas *canvPtr,
+ int numVertex, double *coordPtr, int closed,
+ XPoint *outPtr);
+/*
+ * Standard item types provided by Tk:
+ */
+
+MODULE_SCOPE Tk_ItemType tkArcType, tkBitmapType, tkImageType, tkLineType;
+MODULE_SCOPE Tk_ItemType tkOvalType, tkPolygonType;
+MODULE_SCOPE Tk_ItemType tkRectangleType, tkTextType, tkWindowType;
+
+/*
+ * Convenience macro.
+ */
+
+#define Canvas(canvas) ((TkCanvas *) (canvas))
+
+#endif /* _TKCANVAS */
diff --git a/tk8.6/generic/tkClipboard.c b/tk8.6/generic/tkClipboard.c
new file mode 100644
index 0000000..b902625
--- /dev/null
+++ b/tk8.6/generic/tkClipboard.c
@@ -0,0 +1,721 @@
+/*
+ * tkClipboard.c --
+ *
+ * This file manages the clipboard for the Tk toolkit, maintaining a
+ * collection of data buffers that will be supplied on demand to
+ * requesting applications.
+ *
+ * Copyright (c) 1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "tkInt.h"
+#include "tkSelect.h"
+
+/*
+ * Prototypes for functions used only in this file:
+ */
+
+static int ClipboardAppHandler(ClientData clientData,
+ int offset, char *buffer, int maxBytes);
+static int ClipboardHandler(ClientData clientData,
+ int offset, char *buffer, int maxBytes);
+static int ClipboardWindowHandler(ClientData clientData,
+ int offset, char *buffer, int maxBytes);
+static void ClipboardLostSel(ClientData clientData);
+static int ClipboardGetProc(ClientData clientData,
+ Tcl_Interp *interp, const char *portion);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ClipboardHandler --
+ *
+ * This function acts as selection handler for the clipboard manager. It
+ * extracts the required chunk of data from the buffer chain for a given
+ * selection target.
+ *
+ * Results:
+ * The return value is a count of the number of bytes actually stored at
+ * buffer.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ClipboardHandler(
+ ClientData clientData, /* Information about data to fetch. */
+ int offset, /* Return selection bytes starting at this
+ * offset. */
+ char *buffer, /* Place to store converted selection. */
+ int maxBytes) /* Maximum # of bytes to store at buffer. */
+{
+ TkClipboardTarget *targetPtr = clientData;
+ TkClipboardBuffer *cbPtr;
+ char *srcPtr, *destPtr;
+ size_t count = 0;
+ int scanned = 0;
+ size_t length, freeCount;
+
+ /*
+ * Skip to buffer containing offset byte
+ */
+
+ for (cbPtr = targetPtr->firstBufferPtr; ; cbPtr = cbPtr->nextPtr) {
+ if (cbPtr == NULL) {
+ return 0;
+ }
+ if (scanned + cbPtr->length > offset) {
+ break;
+ }
+ scanned += cbPtr->length;
+ }
+
+ /*
+ * Copy up to maxBytes or end of list, switching buffers as needed.
+ */
+
+ freeCount = maxBytes;
+ srcPtr = cbPtr->buffer + (offset - scanned);
+ destPtr = buffer;
+ length = cbPtr->length - (offset - scanned);
+ while (1) {
+ if (length > freeCount) {
+ strncpy(destPtr, srcPtr, freeCount);
+ return maxBytes;
+ } else {
+ strncpy(destPtr, srcPtr, length);
+ destPtr += length;
+ count += length;
+ freeCount -= length;
+ }
+ cbPtr = cbPtr->nextPtr;
+ if (cbPtr == NULL) {
+ break;
+ }
+ srcPtr = cbPtr->buffer;
+ length = cbPtr->length;
+ }
+ return (int)count;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ClipboardAppHandler --
+ *
+ * This function acts as selection handler for retrievals of type
+ * TK_APPLICATION. It returns the name of the application that owns the
+ * clipboard. Note: we can't use the default Tk selection handler for
+ * this selection type, because the clipboard window isn't a "real"
+ * window and doesn't have the necessary information.
+ *
+ * Results:
+ * The return value is a count of the number of bytes actually stored at
+ * buffer.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ClipboardAppHandler(
+ ClientData clientData, /* Pointer to TkDisplay structure. */
+ int offset, /* Return selection bytes starting at this
+ * offset. */
+ char *buffer, /* Place to store converted selection. */
+ int maxBytes) /* Maximum # of bytes to store at buffer. */
+{
+ TkDisplay *dispPtr = clientData;
+ size_t length;
+ const char *p;
+
+ p = dispPtr->clipboardAppPtr->winPtr->nameUid;
+ length = strlen(p);
+ length -= offset;
+ if (length <= 0) {
+ return 0;
+ }
+ if (length > (size_t) maxBytes) {
+ length = maxBytes;
+ }
+ strncpy(buffer, p, length);
+ return (int)length;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ClipboardWindowHandler --
+ *
+ * This function acts as selection handler for retrievals of type
+ * TK_WINDOW. Since the clipboard doesn't correspond to any particular
+ * window, we just return ".". We can't use Tk's default handler for this
+ * selection type, because the clipboard window isn't a valid window.
+ *
+ * Results:
+ * The return value is 1, the number of non-null bytes stored at buffer.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ClipboardWindowHandler(
+ ClientData clientData, /* Not used. */
+ int offset, /* Return selection bytes starting at this
+ * offset. */
+ char *buffer, /* Place to store converted selection. */
+ int maxBytes) /* Maximum # of bytes to store at buffer. */
+{
+ buffer[0] = '.';
+ buffer[1] = 0;
+ return 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ClipboardLostSel --
+ *
+ * This function is invoked whenever clipboard ownership is claimed by
+ * another window. It just sets a flag so that we know the clipboard was
+ * taken away.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The clipboard is marked as inactive.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ClipboardLostSel(
+ ClientData clientData) /* Pointer to TkDisplay structure. */
+{
+ TkDisplay *dispPtr = clientData;
+
+ dispPtr->clipboardActive = 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_ClipboardClear --
+ *
+ * Take control of the clipboard and clear out the previous contents.
+ * This function must be invoked before any calls to Tk_ClipboardAppend.
+ *
+ * Results:
+ * A standard Tcl result. If an error occurs, an error message is left in
+ * the interp's result.
+ *
+ * Side effects:
+ * From now on, requests for the CLIPBOARD selection will be directed to
+ * the clipboard manager routines associated with clipWindow for the
+ * display of tkwin. In order to guarantee atomicity, no event handling
+ * should occur between Tk_ClipboardClear and the following
+ * Tk_ClipboardAppend calls. This function may cause a user-defined
+ * LostSel command to be invoked when the CLIPBOARD is claimed, so any
+ * calling function should be reentrant at the point Tk_ClipboardClear is
+ * invoked.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_ClipboardClear(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting. */
+ Tk_Window tkwin) /* Window in application that is clearing
+ * clipboard; identifies application and
+ * display. */
+{
+ TkWindow *winPtr = (TkWindow *) tkwin;
+ TkDisplay *dispPtr = winPtr->dispPtr;
+ TkClipboardTarget *targetPtr, *nextTargetPtr;
+ TkClipboardBuffer *cbPtr, *nextCbPtr;
+
+ if (dispPtr->clipWindow == NULL) {
+ int result;
+
+ result = TkClipInit(interp, dispPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+ }
+
+ /*
+ * Discard any existing clipboard data and delete the selection handler(s)
+ * associated with that data.
+ */
+
+ for (targetPtr = dispPtr->clipTargetPtr; targetPtr != NULL;
+ targetPtr = nextTargetPtr) {
+ for (cbPtr = targetPtr->firstBufferPtr; cbPtr != NULL;
+ cbPtr = nextCbPtr) {
+ ckfree(cbPtr->buffer);
+ nextCbPtr = cbPtr->nextPtr;
+ ckfree(cbPtr);
+ }
+ nextTargetPtr = targetPtr->nextPtr;
+ Tk_DeleteSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom,
+ targetPtr->type);
+ ckfree(targetPtr);
+ }
+ dispPtr->clipTargetPtr = NULL;
+
+ /*
+ * Reclaim the clipboard selection if we lost it.
+ */
+
+ if (!dispPtr->clipboardActive) {
+ Tk_OwnSelection(dispPtr->clipWindow, dispPtr->clipboardAtom,
+ ClipboardLostSel, dispPtr);
+ dispPtr->clipboardActive = 1;
+ }
+ dispPtr->clipboardAppPtr = winPtr->mainPtr;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_ClipboardAppend --
+ *
+ * Append a buffer of data to the clipboard. The first buffer of a given
+ * type determines the format for that type. Any successive appends to
+ * that type must have the same format or an error will be returned.
+ * Tk_ClipboardClear must be called before a sequence of
+ * Tk_ClipboardAppend calls can be issued. In order to guarantee
+ * atomicity, no event handling should occur between Tk_ClipboardClear
+ * and the following Tk_ClipboardAppend calls.
+ *
+ * Results:
+ * A standard Tcl result. If an error is returned, an error message is
+ * left in the interp's result.
+ *
+ * Side effects:
+ * The specified buffer will be copied onto the end of the clipboard.
+ * The clipboard maintains a list of buffers which will be used to supply
+ * the data for a selection get request. The first time a given type is
+ * appended, Tk_ClipboardAppend will register a selection handler of the
+ * appropriate type.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_ClipboardAppend(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tk_Window tkwin, /* Window that selects a display. */
+ Atom type, /* The desired conversion type for this
+ * clipboard item, e.g. STRING or LENGTH. */
+ Atom format, /* Format in which the selection information
+ * should be returned to the requestor. */
+ const char *buffer) /* NULL terminated string containing the data
+ * to be added to the clipboard. */
+{
+ TkWindow *winPtr = (TkWindow *) tkwin;
+ TkDisplay *dispPtr = winPtr->dispPtr;
+ TkClipboardTarget *targetPtr;
+ TkClipboardBuffer *cbPtr;
+
+ /*
+ * If this application doesn't already own the clipboard, clear the
+ * clipboard. If we don't own the clipboard selection, claim it.
+ */
+
+ if (dispPtr->clipboardAppPtr != winPtr->mainPtr) {
+ Tk_ClipboardClear(interp, tkwin);
+ } else if (!dispPtr->clipboardActive) {
+ Tk_OwnSelection(dispPtr->clipWindow, dispPtr->clipboardAtom,
+ ClipboardLostSel, dispPtr);
+ dispPtr->clipboardActive = 1;
+ }
+
+ /*
+ * Check to see if the specified target is already present on the
+ * clipboard. If it isn't, we need to create a new target; otherwise, we
+ * just append the new buffer to the clipboard list.
+ */
+
+ for (targetPtr = dispPtr->clipTargetPtr; targetPtr != NULL;
+ targetPtr = targetPtr->nextPtr) {
+ if (targetPtr->type == type) {
+ break;
+ }
+ }
+ if (targetPtr == NULL) {
+ targetPtr = ckalloc(sizeof(TkClipboardTarget));
+ targetPtr->type = type;
+ targetPtr->format = format;
+ targetPtr->firstBufferPtr = targetPtr->lastBufferPtr = NULL;
+ targetPtr->nextPtr = dispPtr->clipTargetPtr;
+ dispPtr->clipTargetPtr = targetPtr;
+ Tk_CreateSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom,
+ type, ClipboardHandler, targetPtr, format);
+ } else if (targetPtr->format != format) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "format \"%s\" does not match current format \"%s\" for %s",
+ Tk_GetAtomName(tkwin, format),
+ Tk_GetAtomName(tkwin, targetPtr->format),
+ Tk_GetAtomName(tkwin, type)));
+ Tcl_SetErrorCode(interp, "TK", "CLIPBOARD", "FORMAT_MISMATCH", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Append a new buffer to the buffer chain.
+ */
+
+ cbPtr = ckalloc(sizeof(TkClipboardBuffer));
+ cbPtr->nextPtr = NULL;
+ if (targetPtr->lastBufferPtr != NULL) {
+ targetPtr->lastBufferPtr->nextPtr = cbPtr;
+ } else {
+ targetPtr->firstBufferPtr = cbPtr;
+ }
+ targetPtr->lastBufferPtr = cbPtr;
+
+ cbPtr->length = strlen(buffer);
+ cbPtr->buffer = ckalloc(cbPtr->length + 1);
+ strcpy(cbPtr->buffer, buffer);
+
+ TkSelUpdateClipboard((TkWindow *) dispPtr->clipWindow, targetPtr);
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_ClipboardObjCmd --
+ *
+ * This function is invoked to process the "clipboard" 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_ClipboardObjCmd(
+ ClientData clientData, /* Main window associated with interpreter. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument strings. */
+{
+ Tk_Window tkwin = (Tk_Window) clientData;
+ const char *path = NULL;
+ Atom selection;
+ static const char *const optionStrings[] = { "append", "clear", "get", NULL };
+ enum options { CLIPBOARD_APPEND, CLIPBOARD_CLEAR, CLIPBOARD_GET };
+ int index, i;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch ((enum options) index) {
+ case CLIPBOARD_APPEND: {
+ Atom target, format;
+ const char *targetName = NULL;
+ const char *formatName = NULL;
+ const char *string;
+ static const char *const appendOptionStrings[] = {
+ "-displayof", "-format", "-type", NULL
+ };
+ enum appendOptions { APPEND_DISPLAYOF, APPEND_FORMAT, APPEND_TYPE };
+ int subIndex, length;
+
+ for (i = 2; i < objc - 1; i++) {
+ string = Tcl_GetStringFromObj(objv[i], &length);
+ if (string[0] != '-') {
+ break;
+ }
+
+ /*
+ * If the argument is "--", it signifies the end of arguments.
+ */
+ if (string[1] == '-' && length == 2) {
+ i++;
+ break;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[i], appendOptionStrings,
+ "option", 0, &subIndex) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Increment i so that it points to the value for the flag instead
+ * of the flag itself.
+ */
+
+ i++;
+ if (i >= objc) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "value for \"%s\" missing", string));
+ Tcl_SetErrorCode(interp, "TK", "CLIPBOARD", "VALUE", NULL);
+ return TCL_ERROR;
+ }
+ switch ((enum appendOptions) subIndex) {
+ case APPEND_DISPLAYOF:
+ path = Tcl_GetString(objv[i]);
+ break;
+ case APPEND_FORMAT:
+ formatName = Tcl_GetString(objv[i]);
+ break;
+ case APPEND_TYPE:
+ targetName = Tcl_GetString(objv[i]);
+ break;
+ }
+ }
+ if (objc - i != 1) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?-option value ...? data");
+ return TCL_ERROR;
+ }
+ if (path != NULL) {
+ tkwin = Tk_NameToWindow(interp, path, tkwin);
+ }
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ if (targetName != NULL) {
+ target = Tk_InternAtom(tkwin, targetName);
+ } else {
+ target = XA_STRING;
+ }
+ if (formatName != NULL) {
+ format = Tk_InternAtom(tkwin, formatName);
+ } else {
+ format = XA_STRING;
+ }
+ return Tk_ClipboardAppend(interp, tkwin, target, format,
+ Tcl_GetString(objv[i]));
+ }
+ case CLIPBOARD_CLEAR: {
+ static const char *const clearOptionStrings[] = { "-displayof", NULL };
+ enum clearOptions { CLEAR_DISPLAYOF };
+ int subIndex;
+
+ if (objc != 2 && objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?-displayof window?");
+ return TCL_ERROR;
+ }
+
+ if (objc == 4) {
+ if (Tcl_GetIndexFromObj(interp, objv[2], clearOptionStrings,
+ "option", 0, &subIndex) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((enum clearOptions) subIndex == CLEAR_DISPLAYOF) {
+ path = Tcl_GetString(objv[3]);
+ }
+ }
+ if (path != NULL) {
+ tkwin = Tk_NameToWindow(interp, path, tkwin);
+ }
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ return Tk_ClipboardClear(interp, tkwin);
+ }
+ case CLIPBOARD_GET: {
+ Atom target;
+ const char *targetName = NULL;
+ Tcl_DString selBytes;
+ int result;
+ const char *string;
+ static const char *const getOptionStrings[] = {
+ "-displayof", "-type", NULL
+ };
+ enum getOptions { APPEND_DISPLAYOF, APPEND_TYPE };
+ int subIndex;
+
+ for (i = 2; i < objc; i++) {
+ string = Tcl_GetString(objv[i]);
+ if (string[0] != '-') {
+ break;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[i], getOptionStrings,
+ "option", 0, &subIndex) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ i++;
+ if (i >= objc) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "value for \"%s\" missing", string));
+ Tcl_SetErrorCode(interp, "TK", "CLIPBOARD", "VALUE", NULL);
+ return TCL_ERROR;
+ }
+ switch ((enum getOptions) subIndex) {
+ case APPEND_DISPLAYOF:
+ path = Tcl_GetString(objv[i]);
+ break;
+ case APPEND_TYPE:
+ targetName = Tcl_GetString(objv[i]);
+ break;
+ }
+ }
+ if (path != NULL) {
+ tkwin = Tk_NameToWindow(interp, path, tkwin);
+ }
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ selection = Tk_InternAtom(tkwin, "CLIPBOARD");
+
+ if (objc - i > 1) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?-option value ...?");
+ return TCL_ERROR;
+ } else if (objc - i == 1) {
+ target = Tk_InternAtom(tkwin, Tcl_GetString(objv[i]));
+ } else if (targetName != NULL) {
+ target = Tk_InternAtom(tkwin, targetName);
+ } else {
+ target = XA_STRING;
+ }
+
+ Tcl_DStringInit(&selBytes);
+ result = Tk_GetSelection(interp, tkwin, selection, target,
+ ClipboardGetProc, &selBytes);
+ if (result == TCL_OK) {
+ Tcl_DStringResult(interp, &selBytes);
+ } else {
+ Tcl_DStringFree(&selBytes);
+ }
+ return result;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkClipInit --
+ *
+ * This function is called to initialize the window for claiming
+ * clipboard ownership and for receiving selection get results. This
+ * function is called from tkSelect.c as well as tkClipboard.c.
+ *
+ * Results:
+ * The result is a standard Tcl return value, which is normally TCL_OK.
+ * If an error occurs then an error message is left in the interp's
+ * result and TCL_ERROR is returned.
+ *
+ * Side effects:
+ * Sets up the clipWindow and related data structures.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkClipInit(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting. */
+ register TkDisplay *dispPtr)/* Display to initialize. */
+{
+ XSetWindowAttributes atts;
+
+ dispPtr->clipTargetPtr = NULL;
+ dispPtr->clipboardActive = 0;
+ dispPtr->clipboardAppPtr = NULL;
+
+ /*
+ * Create the window used for clipboard ownership and selection retrieval,
+ * and set up an event handler for it.
+ */
+
+ dispPtr->clipWindow = (Tk_Window) TkAllocWindow(dispPtr,
+ DefaultScreen(dispPtr->display), NULL);
+ Tcl_Preserve(dispPtr->clipWindow);
+ ((TkWindow *) dispPtr->clipWindow)->flags |=
+ TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED;
+ TkWmNewWindow((TkWindow *) dispPtr->clipWindow);
+ atts.override_redirect = True;
+ Tk_ChangeWindowAttributes(dispPtr->clipWindow, CWOverrideRedirect, &atts);
+ Tk_MakeWindowExist(dispPtr->clipWindow);
+
+ if (dispPtr->multipleAtom == None) {
+ /*
+ * Need to invoke selection initialization to make sure that atoms we
+ * depend on below are defined.
+ */
+
+ TkSelInit(dispPtr->clipWindow);
+ }
+
+ /*
+ * Create selection handlers for types TK_APPLICATION and TK_WINDOW on
+ * this window. Can't use the default handlers for these types because
+ * this isn't a full-fledged window.
+ */
+
+ Tk_CreateSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom,
+ dispPtr->applicationAtom, ClipboardAppHandler, dispPtr,XA_STRING);
+ Tk_CreateSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom,
+ dispPtr->windowAtom, ClipboardWindowHandler, dispPtr, XA_STRING);
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ClipboardGetProc --
+ *
+ * This function is invoked to process pieces of the selection as they
+ * arrive during "clipboard get" commands.
+ *
+ * Results:
+ * Always returns TCL_OK.
+ *
+ * Side effects:
+ * Bytes get appended to the dynamic string pointed to by the clientData
+ * argument.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+ClipboardGetProc(
+ ClientData clientData, /* Dynamic string holding partially assembled
+ * selection. */
+ Tcl_Interp *interp, /* Interpreter used for error reporting (not
+ * used). */
+ const char *portion) /* New information to be appended. */
+{
+ Tcl_DStringAppend((Tcl_DString *) clientData, portion, -1);
+ return TCL_OK;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkCmds.c b/tk8.6/generic/tkCmds.c
new file mode 100644
index 0000000..a64d2e1
--- /dev/null
+++ b/tk8.6/generic/tkCmds.c
@@ -0,0 +1,2166 @@
+/*
+ * tkCmds.c --
+ *
+ * This file contains a collection of Tk-related Tcl commands that didn't
+ * fit in any particular file of the toolkit.
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 2000 Scriptics Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkInt.h"
+
+#if defined(_WIN32)
+#include "tkWinInt.h"
+#elif defined(MAC_OSX_TK)
+#include "tkMacOSXInt.h"
+#else
+#include "tkUnixInt.h"
+#endif
+
+/*
+ * Forward declarations for functions defined later in this file:
+ */
+
+static TkWindow * GetTopHierarchy(Tk_Window tkwin);
+static char * WaitVariableProc(ClientData clientData,
+ Tcl_Interp *interp, const char *name1,
+ const char *name2, int flags);
+static void WaitVisibilityProc(ClientData clientData,
+ XEvent *eventPtr);
+static void WaitWindowProc(ClientData clientData,
+ XEvent *eventPtr);
+static int AppnameCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv);
+static int CaretCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv);
+static int InactiveCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv);
+static int ScalingCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv);
+static int UseinputmethodsCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv);
+static int WindowingsystemCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv);
+
+#if defined(_WIN32) || defined(MAC_OSX_TK)
+MODULE_SCOPE const TkEnsemble tkFontchooserEnsemble[];
+#else
+#define tkFontchooserEnsemble NULL
+#endif
+
+/*
+ * Table of tk subcommand names and implementations.
+ */
+
+static const TkEnsemble tkCmdMap[] = {
+ {"appname", AppnameCmd, NULL },
+ {"busy", Tk_BusyObjCmd, NULL },
+ {"caret", CaretCmd, NULL },
+ {"inactive", InactiveCmd, NULL },
+ {"scaling", ScalingCmd, NULL },
+ {"useinputmethods", UseinputmethodsCmd, NULL },
+ {"windowingsystem", WindowingsystemCmd, NULL },
+ {"fontchooser", NULL, tkFontchooserEnsemble},
+ {NULL, NULL, NULL}
+};
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_BellObjCmd --
+ *
+ * This function is invoked to process the "bell" 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_BellObjCmd(
+ ClientData clientData, /* Main window associated with interpreter. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ static const char *const bellOptions[] = {
+ "-displayof", "-nice", NULL
+ };
+ enum options { TK_BELL_DISPLAYOF, TK_BELL_NICE };
+ Tk_Window tkwin = clientData;
+ int i, index, nice = 0;
+ Tk_ErrorHandler handler;
+
+ if (objc > 4) {
+ wrongArgs:
+ Tcl_WrongNumArgs(interp, 1, objv, "?-displayof window? ?-nice?");
+ return TCL_ERROR;
+ }
+
+ for (i = 1; i < objc; i++) {
+ if (Tcl_GetIndexFromObjStruct(interp, objv[i], bellOptions,
+ sizeof(char *), "option", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch ((enum options) index) {
+ case TK_BELL_DISPLAYOF:
+ if (++i >= objc) {
+ goto wrongArgs;
+ }
+ tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[i]), tkwin);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ break;
+ case TK_BELL_NICE:
+ nice = 1;
+ break;
+ }
+ }
+ handler = Tk_CreateErrorHandler(Tk_Display(tkwin), -1, -1, -1, NULL, NULL);
+ XBell(Tk_Display(tkwin), 0);
+ if (!nice) {
+ XForceScreenSaver(Tk_Display(tkwin), ScreenSaverReset);
+ }
+ XFlush(Tk_Display(tkwin));
+ Tk_DeleteErrorHandler(handler);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_BindObjCmd --
+ *
+ * This function is invoked to process the "bind" 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_BindObjCmd(
+ 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 = clientData;
+ TkWindow *winPtr;
+ ClientData object;
+ const char *string;
+
+ if ((objc < 2) || (objc > 4)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "window ?pattern? ?command?");
+ return TCL_ERROR;
+ }
+ string = Tcl_GetString(objv[1]);
+
+ /*
+ * Bind tags either a window name or a tag name for the first argument.
+ * If the argument starts with ".", assume it is a window; otherwise, it
+ * is a tag.
+ */
+
+ if (string[0] == '.') {
+ winPtr = (TkWindow *) Tk_NameToWindow(interp, string, tkwin);
+ if (winPtr == NULL) {
+ return TCL_ERROR;
+ }
+ object = (ClientData) winPtr->pathName;
+ } else {
+ winPtr = clientData;
+ object = (ClientData) Tk_GetUid(string);
+ }
+
+ /*
+ * If there are four arguments, the command is modifying a binding. If
+ * there are three arguments, the command is querying a binding. If there
+ * are only two arguments, the command is querying all the bindings for
+ * the given tag/window.
+ */
+
+ if (objc == 4) {
+ int append = 0;
+ unsigned long mask;
+ const char *sequence = Tcl_GetString(objv[2]);
+ const char *script = Tcl_GetString(objv[3]);
+
+ /*
+ * If the script is null, just delete the binding.
+ */
+
+ if (script[0] == 0) {
+ return Tk_DeleteBinding(interp, winPtr->mainPtr->bindingTable,
+ object, sequence);
+ }
+
+ /*
+ * If the script begins with "+", append this script to the existing
+ * binding.
+ */
+
+ if (script[0] == '+') {
+ script++;
+ append = 1;
+ }
+ mask = Tk_CreateBinding(interp, winPtr->mainPtr->bindingTable,
+ object, sequence, script, append);
+ if (mask == 0) {
+ return TCL_ERROR;
+ }
+ } else if (objc == 3) {
+ const char *command;
+
+ command = Tk_GetBinding(interp, winPtr->mainPtr->bindingTable,
+ object, Tcl_GetString(objv[2]));
+ if (command == NULL) {
+ Tcl_ResetResult(interp);
+ return TCL_OK;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(command, -1));
+ } else {
+ Tk_GetAllBindings(interp, winPtr->mainPtr->bindingTable, object);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkBindEventProc --
+ *
+ * This function is invoked by Tk_HandleEvent for each event; it causes
+ * any appropriate bindings for that event to be invoked.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Depends on what bindings have been established with the "bind"
+ * command.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkBindEventProc(
+ TkWindow *winPtr, /* Pointer to info about window. */
+ XEvent *eventPtr) /* Information about event. */
+{
+#define MAX_OBJS 20
+ ClientData objects[MAX_OBJS], *objPtr;
+ TkWindow *topLevPtr;
+ int i, count;
+ const char *p;
+ Tcl_HashEntry *hPtr;
+
+ if ((winPtr->mainPtr == NULL) || (winPtr->mainPtr->bindingTable == NULL)) {
+ return;
+ }
+
+ objPtr = objects;
+ if (winPtr->numTags != 0) {
+ /*
+ * Make a copy of the tags for the window, replacing window names with
+ * pointers to the pathName from the appropriate window.
+ */
+
+ if (winPtr->numTags > MAX_OBJS) {
+ objPtr = ckalloc(winPtr->numTags * sizeof(ClientData));
+ }
+ for (i = 0; i < winPtr->numTags; i++) {
+ p = winPtr->tagPtr[i];
+ if (*p == '.') {
+ hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->nameTable, p);
+ if (hPtr != NULL) {
+ p = ((TkWindow *) Tcl_GetHashValue(hPtr))->pathName;
+ } else {
+ p = NULL;
+ }
+ }
+ objPtr[i] = (ClientData) p;
+ }
+ count = winPtr->numTags;
+ } else {
+ objPtr[0] = (ClientData) winPtr->pathName;
+ objPtr[1] = (ClientData) winPtr->classUid;
+ for (topLevPtr = winPtr;
+ (topLevPtr != NULL) && !(topLevPtr->flags & TK_TOP_HIERARCHY);
+ topLevPtr = topLevPtr->parentPtr) {
+ /* Empty loop body. */
+ }
+ if ((winPtr != topLevPtr) && (topLevPtr != NULL)) {
+ count = 4;
+ objPtr[2] = (ClientData) topLevPtr->pathName;
+ } else {
+ count = 3;
+ }
+ objPtr[count-1] = (ClientData) Tk_GetUid("all");
+ }
+ Tk_BindEvent(winPtr->mainPtr->bindingTable, eventPtr, (Tk_Window) winPtr,
+ count, objPtr);
+ if (objPtr != objects) {
+ ckfree(objPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_BindtagsObjCmd --
+ *
+ * This function is invoked to process the "bindtags" 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_BindtagsObjCmd(
+ 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 = clientData;
+ TkWindow *winPtr, *winPtr2;
+ int i, length;
+ const char *p;
+ Tcl_Obj *listPtr, **tags;
+
+ if ((objc < 2) || (objc > 3)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "window ?taglist?");
+ return TCL_ERROR;
+ }
+ winPtr = (TkWindow *) Tk_NameToWindow(interp, Tcl_GetString(objv[1]),
+ tkwin);
+ if (winPtr == NULL) {
+ return TCL_ERROR;
+ }
+ if (objc == 2) {
+ listPtr = Tcl_NewObj();
+ if (winPtr->numTags == 0) {
+ Tcl_ListObjAppendElement(NULL, listPtr,
+ Tcl_NewStringObj(winPtr->pathName, -1));
+ Tcl_ListObjAppendElement(NULL, listPtr,
+ Tcl_NewStringObj(winPtr->classUid, -1));
+ winPtr2 = winPtr;
+ while ((winPtr2 != NULL) && !(Tk_TopWinHierarchy(winPtr2))) {
+ winPtr2 = winPtr2->parentPtr;
+ }
+ if ((winPtr != winPtr2) && (winPtr2 != NULL)) {
+ Tcl_ListObjAppendElement(NULL, listPtr,
+ Tcl_NewStringObj(winPtr2->pathName, -1));
+ }
+ Tcl_ListObjAppendElement(NULL, listPtr,
+ Tcl_NewStringObj("all", -1));
+ } else {
+ for (i = 0; i < winPtr->numTags; i++) {
+ Tcl_ListObjAppendElement(NULL, listPtr,
+ Tcl_NewStringObj((char *) winPtr->tagPtr[i], -1));
+ }
+ }
+ Tcl_SetObjResult(interp, listPtr);
+ return TCL_OK;
+ }
+ if (winPtr->tagPtr != NULL) {
+ TkFreeBindingTags(winPtr);
+ }
+ if (Tcl_ListObjGetElements(interp, objv[2], &length, &tags) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (length == 0) {
+ return TCL_OK;
+ }
+
+ winPtr->numTags = length;
+ winPtr->tagPtr = ckalloc(length * sizeof(ClientData));
+ for (i = 0; i < length; i++) {
+ p = Tcl_GetString(tags[i]);
+ if (p[0] == '.') {
+ char *copy;
+
+ /*
+ * Handle names starting with "." specially: store a malloc'ed
+ * string, rather than a Uid; at event time we'll look up the name
+ * in the window table and use the corresponding window, if there
+ * is one.
+ */
+
+ copy = ckalloc(strlen(p) + 1);
+ strcpy(copy, p);
+ winPtr->tagPtr[i] = (ClientData) copy;
+ } else {
+ winPtr->tagPtr[i] = (ClientData) Tk_GetUid(p);
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkFreeBindingTags --
+ *
+ * This function is called to free all of the binding tags associated
+ * with a window; typically it is only invoked where there are
+ * window-specific tags.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Any binding tags for winPtr are freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkFreeBindingTags(
+ TkWindow *winPtr) /* Window whose tags are to be released. */
+{
+ int i;
+ const char *p;
+
+ for (i = 0; i < winPtr->numTags; i++) {
+ p = winPtr->tagPtr[i];
+ if (*p == '.') {
+ /*
+ * Names starting with "." are malloced rather than Uids, so they
+ * have to be freed.
+ */
+
+ ckfree((char *)p);
+ }
+ }
+ ckfree(winPtr->tagPtr);
+ winPtr->numTags = 0;
+ winPtr->tagPtr = NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_DestroyObjCmd --
+ *
+ * This function is invoked to process the "destroy" 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_DestroyObjCmd(
+ 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 window;
+ Tk_Window tkwin = clientData;
+ int i;
+
+ for (i = 1; i < objc; i++) {
+ window = Tk_NameToWindow(interp, Tcl_GetString(objv[i]), tkwin);
+ if (window == NULL) {
+ Tcl_ResetResult(interp);
+ continue;
+ }
+ Tk_DestroyWindow(window);
+ if (window == tkwin) {
+ /*
+ * We just deleted the main window for the application! This makes
+ * it impossible to do anything more (tkwin isn't valid anymore).
+ */
+
+ break;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_LowerObjCmd --
+ *
+ * This function is invoked to process the "lower" 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_LowerObjCmd(
+ 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 mainwin = clientData;
+ Tk_Window tkwin, other;
+
+ if ((objc != 2) && (objc != 3)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "window ?belowThis?");
+ return TCL_ERROR;
+ }
+
+ tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[1]), mainwin);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ if (objc == 2) {
+ other = NULL;
+ } else {
+ other = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), mainwin);
+ if (other == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ if (Tk_RestackWindow(tkwin, Below, other) != TCL_OK) {
+ if (other) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't lower \"%s\" below \"%s\"",
+ Tcl_GetString(objv[1]), Tcl_GetString(objv[2])));
+ } else {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't lower \"%s\" to bottom", Tcl_GetString(objv[1])));
+ }
+ Tcl_SetErrorCode(interp, "TK", "RESTACK", "LOWER", NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_RaiseObjCmd --
+ *
+ * This function is invoked to process the "raise" 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_RaiseObjCmd(
+ 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 mainwin = clientData;
+ Tk_Window tkwin, other;
+
+ if ((objc != 2) && (objc != 3)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "window ?aboveThis?");
+ return TCL_ERROR;
+ }
+
+ tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[1]), mainwin);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ if (objc == 2) {
+ other = NULL;
+ } else {
+ other = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), mainwin);
+ if (other == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ if (Tk_RestackWindow(tkwin, Above, other) != TCL_OK) {
+ if (other) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't raise \"%s\" above \"%s\"",
+ Tcl_GetString(objv[1]), Tcl_GetString(objv[2])));
+ } else {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't raise \"%s\" to top", Tcl_GetString(objv[1])));
+ }
+ Tcl_SetErrorCode(interp, "TK", "RESTACK", "RAISE", NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * TkInitTkCmd --
+ *
+ * Set up the tk ensemble.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ * ----------------------------------------------------------------------
+ */
+
+int
+TkInitTkCmd(
+ Tcl_Interp *interp,
+ ClientData clientData)
+{
+ TkMakeEnsemble(interp, "::", "tk", clientData, tkCmdMap);
+#if defined(_WIN32) || defined(MAC_OSX_TK)
+ TkInitFontchooser(interp, clientData);
+#endif
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AppnameCmd, CaretCmd, ScalingCmd, UseinputmethodsCmd,
+ * WindowingsystemCmd, InactiveCmd --
+ *
+ * These functions are invoked to process the "tk" ensemble subcommands.
+ * See the user documentation for details on what they do.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+AppnameCmd(
+ 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 = clientData;
+ TkWindow *winPtr;
+ const char *string;
+
+ if (Tcl_IsSafe(interp)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "appname not accessible in a safe interpreter", -1));
+ Tcl_SetErrorCode(interp, "TK", "SAFE", "APPLICATION", NULL);
+ return TCL_ERROR;
+ }
+
+ winPtr = (TkWindow *) tkwin;
+
+ if (objc > 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "?newName?");
+ return TCL_ERROR;
+ }
+ if (objc == 2) {
+ string = Tcl_GetString(objv[1]);
+ winPtr->nameUid = Tk_GetUid(Tk_SetAppName(tkwin, string));
+ }
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(winPtr->nameUid, -1));
+ return TCL_OK;
+}
+
+int
+CaretCmd(
+ 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 = clientData;
+ int index;
+ Tcl_Obj *objPtr;
+ TkCaret *caretPtr;
+ Tk_Window window;
+ static const char *const caretStrings[] = {
+ "-x", "-y", "-height", NULL
+ };
+ enum caretOptions {
+ TK_CARET_X, TK_CARET_Y, TK_CARET_HEIGHT
+ };
+
+ if ((objc < 2) || ((objc > 3) && !!(objc & 1))) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "window ?-x x? ?-y y? ?-height height?");
+ return TCL_ERROR;
+ }
+ window = Tk_NameToWindow(interp, Tcl_GetString(objv[1]), tkwin);
+ if (window == NULL) {
+ return TCL_ERROR;
+ }
+ caretPtr = &(((TkWindow *) window)->dispPtr->caret);
+ if (objc == 2) {
+ /*
+ * Return all the current values
+ */
+
+ objPtr = Tcl_NewObj();
+ Tcl_ListObjAppendElement(interp, objPtr,
+ Tcl_NewStringObj("-height", 7));
+ Tcl_ListObjAppendElement(interp, objPtr,
+ Tcl_NewIntObj(caretPtr->height));
+ Tcl_ListObjAppendElement(interp, objPtr,
+ Tcl_NewStringObj("-x", 2));
+ Tcl_ListObjAppendElement(interp, objPtr,
+ Tcl_NewIntObj(caretPtr->x));
+ Tcl_ListObjAppendElement(interp, objPtr,
+ Tcl_NewStringObj("-y", 2));
+ Tcl_ListObjAppendElement(interp, objPtr,
+ Tcl_NewIntObj(caretPtr->y));
+ Tcl_SetObjResult(interp, objPtr);
+ } else if (objc == 3) {
+ int value;
+
+ /*
+ * Return the current value of the selected option
+ */
+
+ if (Tcl_GetIndexFromObj(interp, objv[2], caretStrings,
+ "caret option", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (index == TK_CARET_X) {
+ value = caretPtr->x;
+ } else if (index == TK_CARET_Y) {
+ value = caretPtr->y;
+ } else /* if (index == TK_CARET_HEIGHT) -- last case */ {
+ value = caretPtr->height;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(value));
+ } else {
+ int i, value, x = 0, y = 0, height = -1;
+
+ for (i = 2; i < objc; i += 2) {
+ if ((Tcl_GetIndexFromObj(interp, objv[i], caretStrings,
+ "caret option", 0, &index) != TCL_OK) ||
+ Tcl_GetIntFromObj(interp,objv[i+1],&value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (index == TK_CARET_X) {
+ x = value;
+ } else if (index == TK_CARET_Y) {
+ y = value;
+ } else /* if (index == TK_CARET_HEIGHT) -- last case */ {
+ height = value;
+ }
+ }
+ if (height < 0) {
+ height = Tk_Height(window);
+ }
+ Tk_SetCaretPos(window, x, y, height);
+ }
+ return TCL_OK;
+}
+
+int
+ScalingCmd(
+ 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 = clientData;
+ Screen *screenPtr;
+ int skip, width, height;
+ double d;
+
+ if (Tcl_IsSafe(interp)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "scaling not accessible in a safe interpreter", -1));
+ Tcl_SetErrorCode(interp, "TK", "SAFE", "SCALING", NULL);
+ return TCL_ERROR;
+ }
+
+ skip = TkGetDisplayOf(interp, objc - 1, objv + 1, &tkwin);
+ if (skip < 0) {
+ return TCL_ERROR;
+ }
+ screenPtr = Tk_Screen(tkwin);
+ if (objc - skip == 1) {
+ d = 25.4 / 72;
+ d *= WidthOfScreen(screenPtr);
+ d /= WidthMMOfScreen(screenPtr);
+ Tcl_SetObjResult(interp, Tcl_NewDoubleObj(d));
+ } else if (objc - skip == 2) {
+ if (Tcl_GetDoubleFromObj(interp, objv[1+skip], &d) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ d = (25.4 / 72) / d;
+ width = (int) (d * WidthOfScreen(screenPtr) + 0.5);
+ if (width <= 0) {
+ width = 1;
+ }
+ height = (int) (d * HeightOfScreen(screenPtr) + 0.5);
+ if (height <= 0) {
+ height = 1;
+ }
+ WidthMMOfScreen(screenPtr) = width;
+ HeightMMOfScreen(screenPtr) = height;
+ } else {
+ Tcl_WrongNumArgs(interp, 1, objv, "?-displayof window? ?factor?");
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+int
+UseinputmethodsCmd(
+ 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 = clientData;
+ TkDisplay *dispPtr;
+ int skip;
+
+ if (Tcl_IsSafe(interp)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "useinputmethods not accessible in a safe interpreter", -1));
+ Tcl_SetErrorCode(interp, "TK", "SAFE", "INPUT_METHODS", NULL);
+ return TCL_ERROR;
+ }
+
+ skip = TkGetDisplayOf(interp, objc-1, objv+1, &tkwin);
+ if (skip < 0) {
+ return TCL_ERROR;
+ }
+ dispPtr = ((TkWindow *) tkwin)->dispPtr;
+ if ((objc - skip) == 2) {
+ /*
+ * In the case where TK_USE_INPUT_METHODS is not defined, this
+ * will be ignored and we will always return 0. That will indicate
+ * to the user that input methods are just not available.
+ */
+
+ int boolVal;
+
+ if (Tcl_GetBooleanFromObj(interp, objv[1+skip],
+ &boolVal) != TCL_OK) {
+ return TCL_ERROR;
+ }
+#ifdef TK_USE_INPUT_METHODS
+ if (boolVal) {
+ dispPtr->flags |= TK_DISPLAY_USE_IM;
+ } else {
+ dispPtr->flags &= ~TK_DISPLAY_USE_IM;
+ }
+#endif /* TK_USE_INPUT_METHODS */
+ } else if ((objc - skip) != 1) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "?-displayof window? ?boolean?");
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp,
+ Tcl_NewBooleanObj(dispPtr->flags & TK_DISPLAY_USE_IM));
+ return TCL_OK;
+}
+
+int
+WindowingsystemCmd(
+ ClientData clientData, /* Main window associated with interpreter. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ const char *windowingsystem;
+
+ if (objc != 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, NULL);
+ return TCL_ERROR;
+ }
+#if defined(_WIN32)
+ windowingsystem = "win32";
+#elif defined(MAC_OSX_TK)
+ windowingsystem = "aqua";
+#else
+ windowingsystem = "x11";
+#endif
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(windowingsystem, -1));
+ return TCL_OK;
+}
+
+int
+InactiveCmd(
+ 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 = clientData;
+ int skip = TkGetDisplayOf(interp, objc - 1, objv + 1, &tkwin);
+
+ if (skip < 0) {
+ return TCL_ERROR;
+ }
+ if (objc - skip == 1) {
+ long inactive;
+
+ inactive = (Tcl_IsSafe(interp) ? -1 :
+ Tk_GetUserInactiveTime(Tk_Display(tkwin)));
+ Tcl_SetObjResult(interp, Tcl_NewLongObj(inactive));
+ } else if (objc - skip == 2) {
+ const char *string;
+
+ string = Tcl_GetString(objv[objc-1]);
+ if (strcmp(string, "reset") != 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad option \"%s\": must be reset", string));
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "option",
+ string, NULL);
+ return TCL_ERROR;
+ }
+ if (Tcl_IsSafe(interp)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "resetting the user inactivity timer "
+ "is not allowed in a safe interpreter", -1));
+ Tcl_SetErrorCode(interp, "TK", "SAFE", "INACTIVITY_TIMER", NULL);
+ return TCL_ERROR;
+ }
+ Tk_ResetUserInactiveTime(Tk_Display(tkwin));
+ Tcl_ResetResult(interp);
+ } else {
+ Tcl_WrongNumArgs(interp, 1, objv, "?-displayof window? ?reset?");
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_TkwaitObjCmd --
+ *
+ * This function is invoked to process the "tkwait" 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_TkwaitObjCmd(
+ 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 = clientData;
+ int done, index;
+ int code = TCL_OK;
+ static const char *const optionStrings[] = {
+ "variable", "visibility", "window", NULL
+ };
+ enum options {
+ TKWAIT_VARIABLE, TKWAIT_VISIBILITY, TKWAIT_WINDOW
+ };
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "variable|visibility|window name");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch ((enum options) index) {
+ case TKWAIT_VARIABLE:
+ if (Tcl_TraceVar2(interp, Tcl_GetString(objv[2]),
+ NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ WaitVariableProc, &done) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ done = 0;
+ while (!done) {
+ if (Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG) == TCL_ERROR) {
+ code = TCL_ERROR;
+ break;
+ }
+ Tcl_DoOneEvent(0);
+ }
+ Tcl_UntraceVar2(interp, Tcl_GetString(objv[2]),
+ NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ WaitVariableProc, &done);
+ break;
+
+ case TKWAIT_VISIBILITY: {
+ Tk_Window window;
+
+ window = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin);
+ if (window == NULL) {
+ return TCL_ERROR;
+ }
+ Tk_CreateEventHandler(window,
+ VisibilityChangeMask|StructureNotifyMask,
+ WaitVisibilityProc, &done);
+ done = 0;
+ while (!done) {
+ if (Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG) == TCL_ERROR) {
+ code = TCL_ERROR;
+ break;
+ }
+ Tcl_DoOneEvent(0);
+ }
+ if ((done != 0) && (done != 1)) {
+ /*
+ * Note that we do not delete the event handler because it was
+ * deleted automatically when the window was destroyed.
+ */
+
+ Tcl_ResetResult(interp);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "window \"%s\" was deleted before its visibility changed",
+ Tcl_GetString(objv[2])));
+ Tcl_SetErrorCode(interp, "TK", "WAIT", "PREMATURE", NULL);
+ return TCL_ERROR;
+ }
+ Tk_DeleteEventHandler(window,
+ VisibilityChangeMask|StructureNotifyMask,
+ WaitVisibilityProc, &done);
+ break;
+ }
+
+ case TKWAIT_WINDOW: {
+ Tk_Window window;
+
+ window = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin);
+ if (window == NULL) {
+ return TCL_ERROR;
+ }
+ Tk_CreateEventHandler(window, StructureNotifyMask,
+ WaitWindowProc, &done);
+ done = 0;
+ while (!done) {
+ if (Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG) == TCL_ERROR) {
+ code = TCL_ERROR;
+ break;
+ }
+ Tcl_DoOneEvent(0);
+ }
+
+ /*
+ * Note: normally there's no need to delete the event handler. It was
+ * deleted automatically when the window was destroyed; however, if
+ * the wait operation was canceled, we need to delete it.
+ */
+
+ if (done == 0) {
+ Tk_DeleteEventHandler(window, StructureNotifyMask,
+ WaitWindowProc, &done);
+ }
+ break;
+ }
+ }
+
+ /*
+ * Clear out the interpreter's result, since it may have been set by event
+ * handlers. This is skipped if an error occurred above, such as the wait
+ * operation being canceled.
+ */
+
+ if (code == TCL_OK)
+ Tcl_ResetResult(interp);
+
+ return code;
+}
+
+ /* ARGSUSED */
+static char *
+WaitVariableProc(
+ ClientData clientData, /* Pointer to integer to set to 1. */
+ Tcl_Interp *interp, /* Interpreter containing variable. */
+ const char *name1, /* Name of variable. */
+ const char *name2, /* Second part of variable name. */
+ int flags) /* Information about what happened. */
+{
+ int *donePtr = clientData;
+
+ *donePtr = 1;
+ return NULL;
+}
+
+ /*ARGSUSED*/
+static void
+WaitVisibilityProc(
+ ClientData clientData, /* Pointer to integer to set to 1. */
+ XEvent *eventPtr) /* Information about event (not used). */
+{
+ int *donePtr = clientData;
+
+ if (eventPtr->type == VisibilityNotify) {
+ *donePtr = 1;
+ } else if (eventPtr->type == DestroyNotify) {
+ *donePtr = 2;
+ }
+}
+
+static void
+WaitWindowProc(
+ ClientData clientData, /* Pointer to integer to set to 1. */
+ XEvent *eventPtr) /* Information about event. */
+{
+ int *donePtr = clientData;
+
+ if (eventPtr->type == DestroyNotify) {
+ *donePtr = 1;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_UpdateObjCmd --
+ *
+ * This function is invoked to process the "update" 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_UpdateObjCmd(
+ ClientData clientData, /* Main window associated with interpreter. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ static const char *const updateOptions[] = {"idletasks", NULL};
+ int flags, index;
+ TkDisplay *dispPtr;
+ int code = TCL_OK;
+
+ if (objc == 1) {
+ flags = TCL_DONT_WAIT;
+ } else if (objc == 2) {
+ if (Tcl_GetIndexFromObj(interp, objv[1], updateOptions, "option", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ flags = TCL_IDLE_EVENTS;
+ } else {
+ Tcl_WrongNumArgs(interp, 1, objv, "?idletasks?");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Handle all pending events, sync all displays, and repeat over and over
+ * again until all pending events have been handled. Special note: it's
+ * possible that the entire application could be destroyed by an event
+ * handler that occurs during the update. Thus, don't use any information
+ * from tkwin after calling Tcl_DoOneEvent.
+ */
+
+ while (1) {
+ while (Tcl_DoOneEvent(flags) != 0) {
+ if (Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG) == TCL_ERROR) {
+ code = TCL_ERROR;
+ break;
+ }
+ }
+
+ /*
+ * If event processing was canceled proceed no further.
+ */
+
+ if (code == TCL_ERROR)
+ break;
+
+ for (dispPtr = TkGetDisplayList(); dispPtr != NULL;
+ dispPtr = dispPtr->nextPtr) {
+ XSync(dispPtr->display, False);
+ }
+
+ /*
+ * Check again if event processing has been canceled because the inner
+ * loop (above) may not have checked (i.e. no events were processed and
+ * the loop body was skipped).
+ */
+
+ if (Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG) == TCL_ERROR) {
+ code = TCL_ERROR;
+ break;
+ }
+
+ if (Tcl_DoOneEvent(flags) == 0) {
+ break;
+ }
+ }
+
+ /*
+ * Must clear the interpreter's result because event handlers could have
+ * executed commands. This is skipped if an error occurred above, such as
+ * the wait operation being canceled.
+ */
+
+ if (code == TCL_OK)
+ Tcl_ResetResult(interp);
+
+ return code;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_WinfoObjCmd --
+ *
+ * This function is invoked to process the "winfo" 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_WinfoObjCmd(
+ ClientData clientData, /* Main window associated with interpreter. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ int index, x, y, width, height, useX, useY, class, skip;
+ const char *string;
+ TkWindow *winPtr;
+ Tk_Window tkwin = clientData;
+
+ static const TkStateMap visualMap[] = {
+ {PseudoColor, "pseudocolor"},
+ {GrayScale, "grayscale"},
+ {DirectColor, "directcolor"},
+ {TrueColor, "truecolor"},
+ {StaticColor, "staticcolor"},
+ {StaticGray, "staticgray"},
+ {-1, NULL}
+ };
+ static const char *const optionStrings[] = {
+ "cells", "children", "class", "colormapfull",
+ "depth", "geometry", "height", "id",
+ "ismapped", "manager", "name", "parent",
+ "pointerx", "pointery", "pointerxy", "reqheight",
+ "reqwidth", "rootx", "rooty", "screen",
+ "screencells", "screendepth", "screenheight", "screenwidth",
+ "screenmmheight","screenmmwidth","screenvisual","server",
+ "toplevel", "viewable", "visual", "visualid",
+ "vrootheight", "vrootwidth", "vrootx", "vrooty",
+ "width", "x", "y",
+
+ "atom", "atomname", "containing", "interps",
+ "pathname",
+
+ "exists", "fpixels", "pixels", "rgb",
+ "visualsavailable",
+
+ NULL
+ };
+ enum options {
+ WIN_CELLS, WIN_CHILDREN, WIN_CLASS, WIN_COLORMAPFULL,
+ WIN_DEPTH, WIN_GEOMETRY, WIN_HEIGHT, WIN_ID,
+ WIN_ISMAPPED, WIN_MANAGER, WIN_NAME, WIN_PARENT,
+ WIN_POINTERX, WIN_POINTERY, WIN_POINTERXY, WIN_REQHEIGHT,
+ WIN_REQWIDTH, WIN_ROOTX, WIN_ROOTY, WIN_SCREEN,
+ WIN_SCREENCELLS,WIN_SCREENDEPTH,WIN_SCREENHEIGHT,WIN_SCREENWIDTH,
+ WIN_SCREENMMHEIGHT,WIN_SCREENMMWIDTH,WIN_SCREENVISUAL,WIN_SERVER,
+ WIN_TOPLEVEL, WIN_VIEWABLE, WIN_VISUAL, WIN_VISUALID,
+ WIN_VROOTHEIGHT,WIN_VROOTWIDTH, WIN_VROOTX, WIN_VROOTY,
+ WIN_WIDTH, WIN_X, WIN_Y,
+
+ WIN_ATOM, WIN_ATOMNAME, WIN_CONTAINING, WIN_INTERPS,
+ WIN_PATHNAME,
+
+ WIN_EXISTS, WIN_FPIXELS, WIN_PIXELS, WIN_RGB,
+ WIN_VISUALSAVAILABLE
+ };
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (index < WIN_ATOM) {
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window");
+ return TCL_ERROR;
+ }
+ string = Tcl_GetString(objv[2]);
+ tkwin = Tk_NameToWindow(interp, string, tkwin);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ winPtr = (TkWindow *) tkwin;
+
+ switch ((enum options) index) {
+ case WIN_CELLS:
+ Tcl_SetObjResult(interp,
+ Tcl_NewIntObj(Tk_Visual(tkwin)->map_entries));
+ break;
+ case WIN_CHILDREN: {
+ Tcl_Obj *strPtr, *resultPtr = Tcl_NewObj();
+
+ winPtr = winPtr->childList;
+ for ( ; winPtr != NULL; winPtr = winPtr->nextPtr) {
+ if (!(winPtr->flags & TK_ANONYMOUS_WINDOW)) {
+ strPtr = Tcl_NewStringObj(winPtr->pathName, -1);
+ Tcl_ListObjAppendElement(NULL, resultPtr, strPtr);
+ }
+ }
+ Tcl_SetObjResult(interp, resultPtr);
+ break;
+ }
+ case WIN_CLASS:
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(Tk_Class(tkwin), -1));
+ break;
+ case WIN_COLORMAPFULL:
+ Tcl_SetObjResult(interp,
+ Tcl_NewBooleanObj(TkpCmapStressed(tkwin,Tk_Colormap(tkwin))));
+ break;
+ case WIN_DEPTH:
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(Tk_Depth(tkwin)));
+ break;
+ case WIN_GEOMETRY:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf("%dx%d+%d+%d",
+ Tk_Width(tkwin), Tk_Height(tkwin), Tk_X(tkwin), Tk_Y(tkwin)));
+ break;
+ case WIN_HEIGHT:
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(Tk_Height(tkwin)));
+ break;
+ case WIN_ID: {
+ char buf[TCL_INTEGER_SPACE];
+
+ Tk_MakeWindowExist(tkwin);
+ TkpPrintWindowId(buf, Tk_WindowId(tkwin));
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1));
+ break;
+ }
+ case WIN_ISMAPPED:
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(Tk_IsMapped(tkwin)));
+ break;
+ case WIN_MANAGER:
+ if (winPtr->geomMgrPtr != NULL) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj(winPtr->geomMgrPtr->name, -1));
+ }
+ break;
+ case WIN_NAME:
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(Tk_Name(tkwin), -1));
+ break;
+ case WIN_PARENT:
+ if (winPtr->parentPtr != NULL) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj(winPtr->parentPtr->pathName, -1));
+ }
+ break;
+ case WIN_POINTERX:
+ useX = 1;
+ useY = 0;
+ goto pointerxy;
+ case WIN_POINTERY:
+ useX = 0;
+ useY = 1;
+ goto pointerxy;
+ case WIN_POINTERXY:
+ useX = 1;
+ useY = 1;
+
+ pointerxy:
+ winPtr = GetTopHierarchy(tkwin);
+ if (winPtr == NULL) {
+ x = -1;
+ y = -1;
+ } else {
+ TkGetPointerCoords((Tk_Window) winPtr, &x, &y);
+ }
+ if (useX & useY) {
+ Tcl_Obj *xyObj[2];
+
+ xyObj[0] = Tcl_NewIntObj(x);
+ xyObj[1] = Tcl_NewIntObj(y);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(2, xyObj));
+ } else if (useX) {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(x));
+ } else {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(y));
+ }
+ break;
+ case WIN_REQHEIGHT:
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(Tk_ReqHeight(tkwin)));
+ break;
+ case WIN_REQWIDTH:
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(Tk_ReqWidth(tkwin)));
+ break;
+ case WIN_ROOTX:
+ Tk_GetRootCoords(tkwin, &x, &y);
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(x));
+ break;
+ case WIN_ROOTY:
+ Tk_GetRootCoords(tkwin, &x, &y);
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(y));
+ break;
+ case WIN_SCREEN:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf("%s.%d",
+ Tk_DisplayName(tkwin), Tk_ScreenNumber(tkwin)));
+ break;
+ case WIN_SCREENCELLS:
+ Tcl_SetObjResult(interp,
+ Tcl_NewIntObj(CellsOfScreen(Tk_Screen(tkwin))));
+ break;
+ case WIN_SCREENDEPTH:
+ Tcl_SetObjResult(interp,
+ Tcl_NewIntObj(DefaultDepthOfScreen(Tk_Screen(tkwin))));
+ break;
+ case WIN_SCREENHEIGHT:
+ Tcl_SetObjResult(interp,
+ Tcl_NewIntObj(HeightOfScreen(Tk_Screen(tkwin))));
+ break;
+ case WIN_SCREENWIDTH:
+ Tcl_SetObjResult(interp,
+ Tcl_NewIntObj(WidthOfScreen(Tk_Screen(tkwin))));
+ break;
+ case WIN_SCREENMMHEIGHT:
+ Tcl_SetObjResult(interp,
+ Tcl_NewIntObj(HeightMMOfScreen(Tk_Screen(tkwin))));
+ break;
+ case WIN_SCREENMMWIDTH:
+ Tcl_SetObjResult(interp,
+ Tcl_NewIntObj(WidthMMOfScreen(Tk_Screen(tkwin))));
+ break;
+ case WIN_SCREENVISUAL:
+ class = DefaultVisualOfScreen(Tk_Screen(tkwin))->class;
+ goto visual;
+ case WIN_SERVER:
+ TkGetServerInfo(interp, tkwin);
+ break;
+ case WIN_TOPLEVEL:
+ winPtr = GetTopHierarchy(tkwin);
+ if (winPtr != NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(winPtr->pathName, -1));
+ }
+ break;
+ case WIN_VIEWABLE: {
+ int viewable = 0;
+
+ for ( ; ; winPtr = winPtr->parentPtr) {
+ if ((winPtr == NULL) || !(winPtr->flags & TK_MAPPED)) {
+ break;
+ }
+ if (winPtr->flags & TK_TOP_HIERARCHY) {
+ viewable = 1;
+ break;
+ }
+ }
+
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(viewable));
+ break;
+ }
+ case WIN_VISUAL:
+ class = Tk_Visual(tkwin)->class;
+
+ visual:
+ string = TkFindStateString(visualMap, class);
+ if (string == NULL) {
+ string = "unknown";
+ }
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(string, -1));
+ break;
+ case WIN_VISUALID:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf("0x%x", (unsigned)
+ XVisualIDFromVisual(Tk_Visual(tkwin))));
+ break;
+ case WIN_VROOTHEIGHT:
+ Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height);
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(height));
+ break;
+ case WIN_VROOTWIDTH:
+ Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height);
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(width));
+ break;
+ case WIN_VROOTX:
+ Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height);
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(x));
+ break;
+ case WIN_VROOTY:
+ Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height);
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(y));
+ break;
+ case WIN_WIDTH:
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(Tk_Width(tkwin)));
+ break;
+ case WIN_X:
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(Tk_X(tkwin)));
+ break;
+ case WIN_Y:
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(Tk_Y(tkwin)));
+ break;
+
+ /*
+ * Uses -displayof.
+ */
+
+ case WIN_ATOM:
+ skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin);
+ if (skip < 0) {
+ return TCL_ERROR;
+ }
+ if (objc - skip != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?-displayof window? name");
+ return TCL_ERROR;
+ }
+ objv += skip;
+ string = Tcl_GetString(objv[2]);
+ Tcl_SetObjResult(interp,
+ Tcl_NewLongObj((long) Tk_InternAtom(tkwin, string)));
+ break;
+ case WIN_ATOMNAME: {
+ const char *name;
+ long id;
+
+ skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin);
+ if (skip < 0) {
+ return TCL_ERROR;
+ }
+ if (objc - skip != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?-displayof window? id");
+ return TCL_ERROR;
+ }
+ objv += skip;
+ if (Tcl_GetLongFromObj(interp, objv[2], &id) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ name = Tk_GetAtomName(tkwin, (Atom) id);
+ if (strcmp(name, "?bad atom?") == 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "no atom exists with id \"%s\"", Tcl_GetString(objv[2])));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "ATOM",
+ Tcl_GetString(objv[2]), NULL);
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(name, -1));
+ break;
+ }
+ case WIN_CONTAINING:
+ skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin);
+ if (skip < 0) {
+ return TCL_ERROR;
+ }
+ if (objc - skip != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-displayof window? rootX rootY");
+ return TCL_ERROR;
+ }
+ objv += skip;
+ string = Tcl_GetString(objv[2]);
+ if (Tk_GetPixels(interp, tkwin, string, &x) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ string = Tcl_GetString(objv[3]);
+ if (Tk_GetPixels(interp, tkwin, string, &y) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ tkwin = Tk_CoordsToWindow(x, y, tkwin);
+ if (tkwin != NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(Tk_PathName(tkwin),-1));
+ }
+ break;
+ case WIN_INTERPS:
+ skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin);
+ if (skip < 0) {
+ return TCL_ERROR;
+ }
+ if (objc - skip != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?-displayof window?");
+ return TCL_ERROR;
+ }
+ return TkGetInterpNames(interp, tkwin);
+ case WIN_PATHNAME: {
+ Window id;
+
+ skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin);
+ if (skip < 0) {
+ return TCL_ERROR;
+ }
+ if (objc - skip != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?-displayof window? id");
+ return TCL_ERROR;
+ }
+ string = Tcl_GetString(objv[2 + skip]);
+ if (TkpScanWindowId(interp, string, &id) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ winPtr = (TkWindow *) Tk_IdToWindow(Tk_Display(tkwin), id);
+ if ((winPtr == NULL) ||
+ (winPtr->mainPtr != ((TkWindow *) tkwin)->mainPtr)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "window id \"%s\" doesn't exist in this application",
+ string));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "WINDOW", string, NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * If the window is a utility window with no associated path (such as
+ * a wrapper window or send communication window), just return an
+ * empty string.
+ */
+
+ tkwin = (Tk_Window) winPtr;
+ if (Tk_PathName(tkwin) != NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(Tk_PathName(tkwin),-1));
+ }
+ break;
+ }
+
+ /*
+ * objv[3] is window.
+ */
+
+ case WIN_EXISTS: {
+ int alive;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window");
+ return TCL_ERROR;
+ }
+ string = Tcl_GetString(objv[2]);
+ winPtr = (TkWindow *) Tk_NameToWindow(interp, string, tkwin);
+ Tcl_ResetResult(interp);
+
+ alive = 1;
+ if ((winPtr == NULL) || (winPtr->flags & TK_ALREADY_DEAD)) {
+ alive = 0;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(alive));
+ break;
+ }
+ case WIN_FPIXELS: {
+ double mm, pixels;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window number");
+ return TCL_ERROR;
+ }
+ if (TkGetWindowFromObj(interp, tkwin, objv[2], &tkwin) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ string = Tcl_GetString(objv[3]);
+ if (Tk_GetScreenMM(interp, tkwin, string, &mm) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ pixels = mm * WidthOfScreen(Tk_Screen(tkwin))
+ / WidthMMOfScreen(Tk_Screen(tkwin));
+ Tcl_SetObjResult(interp, Tcl_NewDoubleObj(pixels));
+ break;
+ }
+ case WIN_PIXELS: {
+ int pixels;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window number");
+ return TCL_ERROR;
+ }
+ if (TkGetWindowFromObj(interp, tkwin, objv[2], &tkwin) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ string = Tcl_GetString(objv[3]);
+ if (Tk_GetPixels(interp, tkwin, string, &pixels) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(pixels));
+ break;
+ }
+ case WIN_RGB: {
+ XColor *colorPtr;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window colorName");
+ return TCL_ERROR;
+ }
+ if (TkGetWindowFromObj(interp, tkwin, objv[2], &tkwin) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ colorPtr = Tk_GetColor(interp, tkwin, Tcl_GetString(objv[3]));
+ if (colorPtr == NULL) {
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf("%d %d %d",
+ colorPtr->red, colorPtr->green, colorPtr->blue));
+ Tk_FreeColor(colorPtr);
+ break;
+ }
+ case WIN_VISUALSAVAILABLE: {
+ XVisualInfo template, *visInfoPtr;
+ int count, i;
+ int includeVisualId;
+ Tcl_Obj *strPtr, *resultPtr;
+ char buf[16 + TCL_INTEGER_SPACE];
+ char visualIdString[TCL_INTEGER_SPACE];
+
+ if (objc == 3) {
+ includeVisualId = 0;
+ } else if ((objc == 4)
+ && (strcmp(Tcl_GetString(objv[3]), "includeids") == 0)) {
+ includeVisualId = 1;
+ } else {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?includeids?");
+ return TCL_ERROR;
+ }
+
+ if (TkGetWindowFromObj(interp, tkwin, objv[2], &tkwin) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ template.screen = Tk_ScreenNumber(tkwin);
+ visInfoPtr = XGetVisualInfo(Tk_Display(tkwin), VisualScreenMask,
+ &template, &count);
+ if (visInfoPtr == NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "can't find any visuals for screen", -1));
+ Tcl_SetErrorCode(interp, "TK", "VISUAL", "NONE", NULL);
+ return TCL_ERROR;
+ }
+ resultPtr = Tcl_NewObj();
+ for (i = 0; i < count; i++) {
+ string = TkFindStateString(visualMap, visInfoPtr[i].class);
+ if (string == NULL) {
+ strcpy(buf, "unknown");
+ } else {
+ sprintf(buf, "%s %d", string, visInfoPtr[i].depth);
+ }
+ if (includeVisualId) {
+ sprintf(visualIdString, " 0x%x",
+ (unsigned) visInfoPtr[i].visualid);
+ strcat(buf, visualIdString);
+ }
+ strPtr = Tcl_NewStringObj(buf, -1);
+ Tcl_ListObjAppendElement(NULL, resultPtr, strPtr);
+ }
+ Tcl_SetObjResult(interp, resultPtr);
+ XFree((char *) visInfoPtr);
+ break;
+ }
+ }
+ return TCL_OK;
+}
+
+#if 0
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_WmObjCmd --
+ *
+ * This function 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;
+ TkWindow *winPtr;
+
+ static const char *const optionStrings[] = {
+ "aspect", "client", "command", "deiconify",
+ "focusmodel", "frame", "geometry", "grid",
+ "group", "iconbitmap", "iconify", "iconmask",
+ "iconname", "iconposition", "iconwindow", "maxsize",
+ "minsize", "overrideredirect", "positionfrom", "protocol",
+ "resizable", "sizefrom", "state", "title",
+ "tracing", "transient", "withdraw", NULL
+ };
+ enum options {
+ TKWM_ASPECT, TKWM_CLIENT, TKWM_COMMAND, TKWM_DEICONIFY,
+ TKWM_FOCUSMOD, TKWM_FRAME, TKWM_GEOMETRY, TKWM_GRID,
+ TKWM_GROUP, TKWM_ICONBMP, TKWM_ICONIFY, TKWM_ICONMASK,
+ TKWM_ICONNAME, TKWM_ICONPOS, TKWM_ICONWIN, TKWM_MAXSIZE,
+ TKWM_MINSIZE, TKWM_OVERRIDE, TKWM_POSFROM, TKWM_PROTOCOL,
+ TKWM_RESIZABLE, TKWM_SIZEFROM, TKWM_STATE, TKWM_TITLE,
+ TKWM_TRACING, TKWM_TRANSIENT, TKWM_WITHDRAW
+ };
+
+ tkwin = (Tk_Window) clientData;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option window ?arg?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (index == TKWM_TRACING) {
+ int wmTracing;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+
+ if ((objc != 2) && (objc != 3)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "tracing ?boolean?");
+ return TCL_ERROR;
+ }
+ if (objc == 2) {
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
+ dispPtr->flags & TK_DISPLAY_WM_TRACING));
+ return TCL_OK;
+ }
+ if (Tcl_GetBooleanFromObj(interp, objv[2], &wmTracing) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (wmTracing) {
+ dispPtr->flags |= TK_DISPLAY_WM_TRACING;
+ } else {
+ dispPtr->flags &= ~TK_DISPLAY_WM_TRACING;
+ }
+ return TCL_OK;
+ }
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?arg?");
+ return TCL_ERROR;
+ }
+
+ winPtr = (TkWindow *) Tk_NameToWindow(interp,
+ Tcl_GetString(objv[2]), tkwin);
+ if (winPtr == NULL) {
+ return TCL_ERROR;
+ }
+ if (!(winPtr->flags & TK_TOP_LEVEL)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "window \"%s\" isn't a top-level window", winPtr->pathName));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "TOPLEVEL", winPtr->pathName,
+ NULL);
+ return TCL_ERROR;
+ }
+
+ switch ((enum options) index) {
+ case TKWM_ASPECT:
+ TkpWmAspectCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ case TKWM_CLIENT:
+ TkpWmClientCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ case TKWM_COMMAND:
+ TkpWmCommandCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ case TKWM_DEICONIFY:
+ TkpWmDeiconifyCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ case TKWM_FOCUSMOD:
+ TkpWmFocusmodCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ case TKWM_FRAME:
+ TkpWmFrameCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ case TKWM_GEOMETRY:
+ TkpWmGeometryCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ case TKWM_GRID:
+ TkpWmGridCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ case TKWM_GROUP:
+ TkpWmGroupCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ case TKWM_ICONBMP:
+ TkpWmIconbitmapCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ case TKWM_ICONIFY:
+ TkpWmIconifyCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ case TKWM_ICONMASK:
+ TkpWmIconmaskCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ case TKWM_ICONNAME:
+ /*
+ * Slight Unix variation.
+ */
+ TkpWmIconnameCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ case TKWM_ICONPOS:
+ /*
+ * nearly same - 1 line more on Unix.
+ */
+ TkpWmIconpositionCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ case TKWM_ICONWIN:
+ TkpWmIconwindowCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ case TKWM_MAXSIZE:
+ /*
+ * Nearly same, win diffs.
+ */
+ TkpWmMaxsizeCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ case TKWM_MINSIZE:
+ /*
+ * Nearly same, win diffs
+ */
+ TkpWmMinsizeCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ case TKWM_OVERRIDE:
+ /*
+ * Almost same.
+ */
+ TkpWmOverrideCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ case TKWM_POSFROM:
+ /*
+ * Equal across platforms
+ */
+ TkpWmPositionfromCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ case TKWM_PROTOCOL:
+ /*
+ * Equal across platforms
+ */
+ TkpWmProtocolCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ case TKWM_RESIZABLE:
+ /*
+ * Almost same
+ */
+ TkpWmResizableCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ case TKWM_SIZEFROM:
+ /*
+ * Equal across platforms
+ */
+ TkpWmSizefromCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ case TKWM_STATE:
+ TkpWmStateCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ case TKWM_TITLE:
+ TkpWmTitleCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ case TKWM_TRANSIENT:
+ TkpWmTransientCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ case TKWM_WITHDRAW:
+ TkpWmWithdrawCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ }
+
+ updateGeom:
+ if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {
+ Tcl_DoWhenIdle(UpdateGeometryInfo, winPtr);
+ wmPtr->flags |= WM_UPDATE_PENDING;
+ }
+ return TCL_OK;
+}
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkGetDisplayOf --
+ *
+ * Parses a "-displayof window" option for various commands. If present,
+ * the literal "-displayof" should be in objv[0] and the window name in
+ * objv[1].
+ *
+ * Results:
+ * The return value is 0 if the argument strings did not contain the
+ * "-displayof" option. The return value is 2 if the argument strings
+ * contained both the "-displayof" option and a valid window name.
+ * Otherwise, the return value is -1 if the window name was missing or
+ * did not specify a valid window.
+ *
+ * If the return value was 2, *tkwinPtr is filled with the token for the
+ * window specified on the command line. If the return value was -1, an
+ * error message is left in interp's result object.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkGetDisplayOf(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[], /* Argument objects. If it is present,
+ * "-displayof" should be in objv[0] and
+ * objv[1] the name of a window. */
+ Tk_Window *tkwinPtr) /* On input, contains main window of
+ * application associated with interp. On
+ * output, filled with window specified as
+ * option to "-displayof" argument, or
+ * unmodified if "-displayof" argument was not
+ * present. */
+{
+ const char *string;
+ int length;
+
+ if (objc < 1) {
+ return 0;
+ }
+ string = Tcl_GetStringFromObj(objv[0], &length);
+ if ((length >= 2) &&
+ (strncmp(string, "-displayof", (unsigned) length) == 0)) {
+ if (objc < 2) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "value for \"-displayof\" missing", -1));
+ Tcl_SetErrorCode(interp, "TK", "NO_VALUE", "DISPLAYOF", NULL);
+ return -1;
+ }
+ *tkwinPtr = Tk_NameToWindow(interp, Tcl_GetString(objv[1]), *tkwinPtr);
+ if (*tkwinPtr == NULL) {
+ return -1;
+ }
+ return 2;
+ }
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkDeadAppObjCmd --
+ *
+ * If an application has been deleted then all Tk commands will be
+ * re-bound to this function.
+ *
+ * Results:
+ * A standard Tcl error is reported to let the user know that the
+ * application is dead.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+int
+TkDeadAppObjCmd(
+ ClientData clientData, /* Dummy. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument strings. */
+{
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't invoke \"%s\" command: application has been destroyed",
+ Tcl_GetString(objv[0])));
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetTopHierarchy --
+ *
+ * Retrieves the top-of-hierarchy window which is the nearest ancestor of
+ * the specified window.
+ *
+ * Results:
+ * Returns the top-of-hierarchy window, or NULL if the window has no
+ * ancestor which is at the top of a physical window hierarchy.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static TkWindow *
+GetTopHierarchy(
+ Tk_Window tkwin) /* Window for which the top-of-hierarchy
+ * ancestor should be deterined. */
+{
+ TkWindow *winPtr = (TkWindow *) tkwin;
+
+ while ((winPtr != NULL) && !(winPtr->flags & TK_TOP_HIERARCHY)) {
+ winPtr = winPtr->parentPtr;
+ }
+ return winPtr;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkColor.c b/tk8.6/generic/tkColor.c
new file mode 100644
index 0000000..f6650f9
--- /dev/null
+++ b/tk8.6/generic/tkColor.c
@@ -0,0 +1,947 @@
+/*
+ * tkColor.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-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.
+ */
+
+#include "tkInt.h"
+#include "tkColor.h"
+
+/*
+ * Structures of the following following type are used as keys for
+ * colorValueTable (in TkDisplay).
+ */
+
+typedef struct {
+ int red, green, blue; /* Values for desired color. */
+ Colormap colormap; /* Colormap from which color will be
+ * allocated. */
+ Display *display; /* Display for colormap. */
+} ValueKey;
+
+/*
+ * The structure below is used to allocate thread-local data.
+ */
+
+typedef struct {
+ char rgbString[20]; /* */
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+
+/*
+ * Forward declarations for functions defined in this file:
+ */
+
+static void ColorInit(TkDisplay *dispPtr);
+static void DupColorObjProc(Tcl_Obj *srcObjPtr,Tcl_Obj *dupObjPtr);
+static void FreeColorObj(Tcl_Obj *objPtr);
+static void FreeColorObjProc(Tcl_Obj *objPtr);
+static void InitColorObj(Tcl_Obj *objPtr);
+
+/*
+ * The following structure defines the implementation of the "color" Tcl
+ * object, which maps a string color name to a TkColor object. The ptr1 field
+ * of the Tcl_Obj points to a TkColor object.
+ */
+
+const Tcl_ObjType tkColorObjType = {
+ "color", /* name */
+ FreeColorObjProc, /* freeIntRepProc */
+ DupColorObjProc, /* dupIntRepProc */
+ NULL, /* updateStringProc */
+ NULL /* setFromAnyProc */
+};
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_AllocColorFromObj --
+ *
+ * Given a Tcl_Obj *, map the value to a corresponding XColor structure
+ * based on the tkwin given.
+ *
+ * Results:
+ * The return value is a pointer to an XColor structure that indicates
+ * the red, blue, and green intensities for the color given by the string
+ * in objPtr, and also specifies a pixel value to use to draw in that
+ * color. If an error occurs, NULL is returned and an error message will
+ * be left in interp's result (unless interp is NULL).
+ *
+ * Side effects:
+ * The color is added to an internal database with a reference count. For
+ * each call to this function, there should eventually be a call to
+ * Tk_FreeColorFromObj so that the database is cleaned up when colors
+ * aren't in use anymore.
+ *
+ *----------------------------------------------------------------------
+ */
+
+XColor *
+Tk_AllocColorFromObj(
+ Tcl_Interp *interp, /* Used only for error reporting. If NULL,
+ * then no messages are provided. */
+ Tk_Window tkwin, /* Window in which the color will be used.*/
+ Tcl_Obj *objPtr) /* Object that describes the color; string
+ * value is a color name such as "red" or
+ * "#ff0000".*/
+{
+ TkColor *tkColPtr;
+
+ if (objPtr->typePtr != &tkColorObjType) {
+ InitColorObj(objPtr);
+ }
+ tkColPtr = (TkColor *) objPtr->internalRep.twoPtrValue.ptr1;
+
+ /*
+ * If the object currently points to a TkColor, see if it's the one we
+ * want. If so, increment its reference count and return.
+ */
+
+ if (tkColPtr != NULL) {
+ if (tkColPtr->resourceRefCount == 0) {
+ /*
+ * This is a stale reference: it refers to a TkColor that's no
+ * longer in use. Clear the reference.
+ */
+
+ FreeColorObj(objPtr);
+ tkColPtr = NULL;
+ } else if ((Tk_Screen(tkwin) == tkColPtr->screen)
+ && (Tk_Colormap(tkwin) == tkColPtr->colormap)) {
+ tkColPtr->resourceRefCount++;
+ return (XColor *) tkColPtr;
+ }
+ }
+
+ /*
+ * The object didn't point to the TkColor that we wanted. Search the list
+ * of TkColors with the same name to see if one of the other TkColors is
+ * the right one.
+ */
+
+ if (tkColPtr != NULL) {
+ TkColor *firstColorPtr = Tcl_GetHashValue(tkColPtr->hashPtr);
+
+ FreeColorObj(objPtr);
+ for (tkColPtr = firstColorPtr; tkColPtr != NULL;
+ tkColPtr = tkColPtr->nextPtr) {
+ if ((Tk_Screen(tkwin) == tkColPtr->screen)
+ && (Tk_Colormap(tkwin) == tkColPtr->colormap)) {
+ tkColPtr->resourceRefCount++;
+ tkColPtr->objRefCount++;
+ objPtr->internalRep.twoPtrValue.ptr1 = tkColPtr;
+ return (XColor *) tkColPtr;
+ }
+ }
+ }
+
+ /*
+ * Still no luck. Call Tk_GetColor to allocate a new TkColor object.
+ */
+
+ tkColPtr = (TkColor *) Tk_GetColor(interp, tkwin, Tcl_GetString(objPtr));
+ objPtr->internalRep.twoPtrValue.ptr1 = tkColPtr;
+ if (tkColPtr != NULL) {
+ tkColPtr->objRefCount++;
+ }
+ return (XColor *) tkColPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetColor --
+ *
+ * Given a string name for a color, map the name to a corresponding
+ * XColor structure.
+ *
+ * Results:
+ * The return value is a pointer to an XColor structure that indicates
+ * the red, blue, and green intensities for the color given by "name",
+ * and also specifies a pixel value to use to draw in that color. If an
+ * error occurs, NULL is returned and an error message will be left in
+ * the interp's result.
+ *
+ * Side effects:
+ * The color is added to an internal database with a reference count. For
+ * each call to this function, there should eventually be a call to
+ * Tk_FreeColor so that the database is cleaned up when colors aren't in
+ * use anymore.
+ *
+ *----------------------------------------------------------------------
+ */
+
+XColor *
+Tk_GetColor(
+ Tcl_Interp *interp, /* Place to leave error message if color can't
+ * be found. */
+ Tk_Window tkwin, /* Window in which color will be used. */
+ Tk_Uid name) /* Name of color to be allocated (in form
+ * suitable for passing to XParseColor). */
+{
+ Tcl_HashEntry *nameHashPtr;
+ int isNew;
+ TkColor *tkColPtr;
+ TkColor *existingColPtr;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+
+ if (!dispPtr->colorInit) {
+ ColorInit(dispPtr);
+ }
+
+ /*
+ * First, check to see if there's already a mapping for this color name.
+ */
+
+ nameHashPtr = Tcl_CreateHashEntry(&dispPtr->colorNameTable, name, &isNew);
+ if (!isNew) {
+ existingColPtr = Tcl_GetHashValue(nameHashPtr);
+ for (tkColPtr = existingColPtr; tkColPtr != NULL;
+ tkColPtr = tkColPtr->nextPtr) {
+ if ((tkColPtr->screen == Tk_Screen(tkwin))
+ && (Tk_Colormap(tkwin) == tkColPtr->colormap)) {
+ tkColPtr->resourceRefCount++;
+ return &tkColPtr->color;
+ }
+ }
+ } else {
+ existingColPtr = NULL;
+ }
+
+ /*
+ * The name isn't currently known. Map from the name to a pixel value.
+ */
+
+ tkColPtr = TkpGetColor(tkwin, name);
+ if (tkColPtr == NULL) {
+ if (interp != NULL) {
+ if (*name == '#') {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "invalid color name \"%s\"", name));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "COLOR", NULL);
+ } else {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "unknown color name \"%s\"", name));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "COLOR", name, NULL);
+ }
+ }
+ if (isNew) {
+ Tcl_DeleteHashEntry(nameHashPtr);
+ }
+ return NULL;
+ }
+
+ /*
+ * Now create a new TkColor structure and add it to colorNameTable (in
+ * TkDisplay).
+ */
+
+ tkColPtr->magic = COLOR_MAGIC;
+ tkColPtr->gc = NULL;
+ tkColPtr->screen = Tk_Screen(tkwin);
+ tkColPtr->colormap = Tk_Colormap(tkwin);
+ tkColPtr->visual = Tk_Visual(tkwin);
+ tkColPtr->resourceRefCount = 1;
+ tkColPtr->objRefCount = 0;
+ tkColPtr->type = TK_COLOR_BY_NAME;
+ tkColPtr->hashPtr = nameHashPtr;
+ tkColPtr->nextPtr = existingColPtr;
+ Tcl_SetHashValue(nameHashPtr, tkColPtr);
+
+ return &tkColPtr->color;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetColorByValue --
+ *
+ * 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 XColor 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:
+ * The color is added to an internal database with a reference count. For
+ * each call to this function, there should eventually be a call to
+ * Tk_FreeColor, so that the database is cleaned up when colors aren't in
+ * use anymore.
+ *
+ *----------------------------------------------------------------------
+ */
+
+XColor *
+Tk_GetColorByValue(
+ Tk_Window tkwin, /* Window where color will be used. */
+ XColor *colorPtr) /* Red, green, and blue fields indicate
+ * desired color. */
+{
+ ValueKey valueKey;
+ Tcl_HashEntry *valueHashPtr;
+ int isNew;
+ TkColor *tkColPtr;
+ Display *display = Tk_Display(tkwin);
+ TkDisplay *dispPtr = TkGetDisplay(display);
+
+ if (!dispPtr->colorInit) {
+ ColorInit(dispPtr);
+ }
+
+ /*
+ * First, check to see if there's already a mapping for this color name.
+ * Must clear the structure first; it's not tightly packed on 64-bit
+ * systems. [Bug 2911570]
+ */
+
+ memset(&valueKey, 0, sizeof(ValueKey));
+ valueKey.red = colorPtr->red;
+ valueKey.green = colorPtr->green;
+ valueKey.blue = colorPtr->blue;
+ valueKey.colormap = Tk_Colormap(tkwin);
+ valueKey.display = display;
+ valueHashPtr = Tcl_CreateHashEntry(&dispPtr->colorValueTable,
+ (char *) &valueKey, &isNew);
+ if (!isNew) {
+ tkColPtr = Tcl_GetHashValue(valueHashPtr);
+ tkColPtr->resourceRefCount++;
+ return &tkColPtr->color;
+ }
+
+ /*
+ * The name isn't currently known. Find a pixel value for this color and
+ * add a new structure to colorValueTable (in TkDisplay).
+ */
+
+ tkColPtr = TkpGetColorByValue(tkwin, colorPtr);
+ tkColPtr->magic = COLOR_MAGIC;
+ tkColPtr->gc = NULL;
+ tkColPtr->screen = Tk_Screen(tkwin);
+ tkColPtr->colormap = valueKey.colormap;
+ tkColPtr->visual = Tk_Visual(tkwin);
+ tkColPtr->resourceRefCount = 1;
+ tkColPtr->objRefCount = 0;
+ tkColPtr->type = TK_COLOR_BY_VALUE;
+ tkColPtr->hashPtr = valueHashPtr;
+ tkColPtr->nextPtr = NULL;
+ Tcl_SetHashValue(valueHashPtr, tkColPtr);
+ return &tkColPtr->color;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_NameOfColor --
+ *
+ * Given a color, return a textual string identifying the color.
+ *
+ * Results:
+ * If colorPtr was created by Tk_GetColor, then the return value is the
+ * "string" that was used to create it. Otherwise the return value is a
+ * string that could have been passed to Tk_GetColor to allocate that
+ * color. The storage for the returned string is only guaranteed to
+ * persist up until the next call to this function.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+const char *
+Tk_NameOfColor(
+ XColor *colorPtr) /* Color whose name is desired. */
+{
+ register TkColor *tkColPtr = (TkColor *) colorPtr;
+
+ if (tkColPtr->magic==COLOR_MAGIC && tkColPtr->type==TK_COLOR_BY_NAME) {
+ return tkColPtr->hashPtr->key.string;
+ } else {
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ sprintf(tsdPtr->rgbString, "#%04x%04x%04x", colorPtr->red,
+ colorPtr->green, colorPtr->blue);
+
+ /*
+ * If the string has the form #RSRSTUTUVWVW (where equal letters
+ * denote equal hexdigits) then this is equivalent to #RSTUVW. Then
+ * output the shorter form.
+ */
+
+ if ((tsdPtr->rgbString[1] == tsdPtr->rgbString[3])
+ && (tsdPtr->rgbString[2] == tsdPtr->rgbString[4])
+ && (tsdPtr->rgbString[5] == tsdPtr->rgbString[7])
+ && (tsdPtr->rgbString[6] == tsdPtr->rgbString[8])
+ && (tsdPtr->rgbString[9] == tsdPtr->rgbString[11])
+ && (tsdPtr->rgbString[10] == tsdPtr->rgbString[12])) {
+ tsdPtr->rgbString[3] = tsdPtr->rgbString[5];
+ tsdPtr->rgbString[4] = tsdPtr->rgbString[6];
+ tsdPtr->rgbString[5] = tsdPtr->rgbString[9];
+ tsdPtr->rgbString[6] = tsdPtr->rgbString[10];
+ tsdPtr->rgbString[7] = '\0';
+ }
+ return tsdPtr->rgbString;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GCForColor --
+ *
+ * Given a color allocated from this module, this function returns a GC
+ * that can be used for simple drawing with that color.
+ *
+ * Results:
+ * The return value is a GC with color set as its foreground color and
+ * all other fields defaulted. This GC is only valid as long as the color
+ * exists; it is freed automatically when the last reference to the color
+ * is freed.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+GC
+Tk_GCForColor(
+ XColor *colorPtr, /* Color for which a GC is desired. Must have
+ * been allocated by Tk_GetColor. */
+ Drawable drawable) /* Drawable in which the color will be used
+ * (must have same screen and depth as the one
+ * for which the color was allocated). */
+{
+ TkColor *tkColPtr = (TkColor *) colorPtr;
+ XGCValues gcValues;
+
+ /*
+ * Do a quick sanity check to make sure this color was really allocated by
+ * Tk_GetColor.
+ */
+
+ if (tkColPtr->magic != COLOR_MAGIC) {
+ Tcl_Panic("Tk_GCForColor called with bogus color");
+ }
+
+ if (tkColPtr->gc == NULL) {
+ gcValues.foreground = tkColPtr->color.pixel;
+ tkColPtr->gc = XCreateGC(DisplayOfScreen(tkColPtr->screen), drawable,
+ GCForeground, &gcValues);
+ }
+ return tkColPtr->gc;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_FreeColor --
+ *
+ * This function is called to release a color allocated by Tk_GetColor.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The reference count associated with colorPtr is deleted, and the color
+ * is released to X if there are no remaining uses for it.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_FreeColor(
+ XColor *colorPtr) /* Color to be released. Must have been
+ * allocated by Tk_GetColor or
+ * Tk_GetColorByValue. */
+{
+ TkColor *tkColPtr = (TkColor *) colorPtr;
+ Screen *screen = tkColPtr->screen;
+ TkColor *prevPtr;
+
+ /*
+ * Do a quick sanity check to make sure this color was really allocated by
+ * Tk_GetColor.
+ */
+
+ if (tkColPtr->magic != COLOR_MAGIC) {
+ Tcl_Panic("Tk_FreeColor called with bogus color");
+ }
+
+ tkColPtr->resourceRefCount--;
+ if (tkColPtr->resourceRefCount > 0) {
+ return;
+ }
+
+ /*
+ * This color is no longer being actively used, so free the color
+ * resources associated with it and remove it from the hash table. No
+ * longer any objects referencing it.
+ */
+
+ if (tkColPtr->gc != NULL) {
+ XFreeGC(DisplayOfScreen(screen), tkColPtr->gc);
+ tkColPtr->gc = NULL;
+ }
+ TkpFreeColor(tkColPtr);
+
+ prevPtr = Tcl_GetHashValue(tkColPtr->hashPtr);
+ if (prevPtr == tkColPtr) {
+ if (tkColPtr->nextPtr == NULL) {
+ Tcl_DeleteHashEntry(tkColPtr->hashPtr);
+ } else {
+ Tcl_SetHashValue(tkColPtr->hashPtr, tkColPtr->nextPtr);
+ }
+ } else {
+ while (prevPtr->nextPtr != tkColPtr) {
+ prevPtr = prevPtr->nextPtr;
+ }
+ prevPtr->nextPtr = tkColPtr->nextPtr;
+ }
+
+ /*
+ * Free the TkColor structure if there are no objects referencing it.
+ * However, if there are objects referencing it then keep the structure
+ * around; it will get freed when the last reference is cleared
+ */
+
+ if (tkColPtr->objRefCount == 0) {
+ ckfree(tkColPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_FreeColorFromObj --
+ *
+ * This function is called to release a color allocated by
+ * Tk_AllocColorFromObj. It does not throw away the Tcl_Obj *; it only
+ * gets rid of the hash table entry for this color and clears the cached
+ * value that is normally stored in the object.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The reference count associated with the color represented by objPtr is
+ * decremented, and the color is released to X if there are no remaining
+ * uses for it.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_FreeColorFromObj(
+ Tk_Window tkwin, /* The window this color lives in. Needed for
+ * the screen and colormap values. */
+ Tcl_Obj *objPtr) /* The Tcl_Obj * to be freed. */
+{
+ Tk_FreeColor(Tk_GetColorFromObj(tkwin, objPtr));
+ FreeColorObj(objPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FreeColorObjProc, FreeColorObj --
+ *
+ * This proc is called to release an object reference to a color. Called
+ * when the object's internal rep is released or when the cached tkColPtr
+ * needs to be changed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The object reference count is decremented. When both it and the hash
+ * ref count go to zero, the color's resources are released.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+FreeColorObjProc(
+ Tcl_Obj *objPtr) /* The object we are releasing. */
+{
+ FreeColorObj(objPtr);
+ objPtr->typePtr = NULL;
+}
+
+static void
+FreeColorObj(
+ Tcl_Obj *objPtr) /* The object we are releasing. */
+{
+ TkColor *tkColPtr = objPtr->internalRep.twoPtrValue.ptr1;
+
+ if (tkColPtr != NULL) {
+ tkColPtr->objRefCount--;
+ if ((tkColPtr->objRefCount == 0)
+ && (tkColPtr->resourceRefCount == 0)) {
+ ckfree(tkColPtr);
+ }
+ objPtr->internalRep.twoPtrValue.ptr1 = NULL;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DupColorObjProc --
+ *
+ * When a cached color object is duplicated, this is called to update the
+ * internal reps.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The color's objRefCount is incremented and the internal rep of the
+ * copy is set to point to it.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+DupColorObjProc(
+ Tcl_Obj *srcObjPtr, /* The object we are copying from. */
+ Tcl_Obj *dupObjPtr) /* The object we are copying to. */
+{
+ TkColor *tkColPtr = srcObjPtr->internalRep.twoPtrValue.ptr1;
+
+ dupObjPtr->typePtr = srcObjPtr->typePtr;
+ dupObjPtr->internalRep.twoPtrValue.ptr1 = tkColPtr;
+
+ if (tkColPtr != NULL) {
+ tkColPtr->objRefCount++;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetColorFromObj --
+ *
+ * Returns the color referred to by a Tcl object. The color must already
+ * have been allocated via a call to Tk_AllocColorFromObj or Tk_GetColor.
+ *
+ * Results:
+ * Returns the XColor * that matches the tkwin and the string rep of
+ * objPtr.
+ *
+ * Side effects:
+ * If the object is not already a color, the conversion will free any old
+ * internal representation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+XColor *
+Tk_GetColorFromObj(
+ Tk_Window tkwin, /* The window in which the color will be
+ * used. */
+ Tcl_Obj *objPtr) /* String value contains the name of the
+ * desired color. */
+{
+ TkColor *tkColPtr;
+ Tcl_HashEntry *hashPtr;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+
+ if (objPtr->typePtr != &tkColorObjType) {
+ InitColorObj(objPtr);
+ }
+
+ /*
+ * First check to see if the internal representation of the object is
+ * defined and is a color that is valid for the current screen and color
+ * map. If it is, we are done.
+ */
+
+ tkColPtr = objPtr->internalRep.twoPtrValue.ptr1;
+ if ((tkColPtr != NULL)
+ && (tkColPtr->resourceRefCount > 0)
+ && (Tk_Screen(tkwin) == tkColPtr->screen)
+ && (Tk_Colormap(tkwin) == tkColPtr->colormap)) {
+ /*
+ * The object already points to the right TkColor structure. Just
+ * return it.
+ */
+
+ return (XColor *) tkColPtr;
+ }
+
+ /*
+ * If we reach this point, it means that the TkColor structure that we
+ * have cached in the internal representation is not valid for the current
+ * screen and colormap. But there is a list of other TkColor structures
+ * attached to the TkDisplay. Walk this list looking for the right TkColor
+ * structure.
+ */
+
+ hashPtr = Tcl_FindHashEntry(&dispPtr->colorNameTable,
+ Tcl_GetString(objPtr));
+ if (hashPtr == NULL) {
+ goto error;
+ }
+ for (tkColPtr = Tcl_GetHashValue(hashPtr);
+ (tkColPtr != NULL); tkColPtr = tkColPtr->nextPtr) {
+ if ((Tk_Screen(tkwin) == tkColPtr->screen)
+ && (Tk_Colormap(tkwin) == tkColPtr->colormap)) {
+ FreeColorObj(objPtr);
+ objPtr->internalRep.twoPtrValue.ptr1 = tkColPtr;
+ tkColPtr->objRefCount++;
+ return (XColor *) tkColPtr;
+ }
+ }
+
+ error:
+ Tcl_Panic("Tk_GetColorFromObj called with non-existent color!");
+ /*
+ * The following code isn't reached; it's just there to please compilers.
+ */
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InitColorObj --
+ *
+ * Bookeeping function to change an objPtr to a color type.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The old internal rep of the object is freed. The object's type is set
+ * to color with a NULL TkColor pointer (the pointer will be set later by
+ * either Tk_AllocColorFromObj or Tk_GetColorFromObj).
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+InitColorObj(
+ Tcl_Obj *objPtr) /* The object to convert. */
+{
+ const Tcl_ObjType *typePtr;
+
+ /*
+ * Free the old internalRep before setting the new one.
+ */
+
+ Tcl_GetString(objPtr);
+ typePtr = objPtr->typePtr;
+ if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
+ typePtr->freeIntRepProc(objPtr);
+ }
+ objPtr->typePtr = &tkColorObjType;
+ objPtr->internalRep.twoPtrValue.ptr1 = NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ColorInit --
+ *
+ * Initialize the structure used for color management.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Read the code.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ColorInit(
+ TkDisplay *dispPtr)
+{
+ if (!dispPtr->colorInit) {
+ dispPtr->colorInit = 1;
+ Tcl_InitHashTable(&dispPtr->colorNameTable, TCL_STRING_KEYS);
+ Tcl_InitHashTable(&dispPtr->colorValueTable,
+ sizeof(ValueKey)/sizeof(int));
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkDebugColor --
+ *
+ * This function returns debugging information about a color.
+ *
+ * Results:
+ * The return value is a list with one sublist for each TkColor
+ * corresponding to "name". Each sublist has two elements that contain
+ * the resourceRefCount and objRefCount fields from the TkColor
+ * structure.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TkDebugColor(
+ Tk_Window tkwin, /* The window in which the color will be used
+ * (not currently used). */
+ const char *name) /* Name of the desired color. */
+{
+ Tcl_HashEntry *hashPtr;
+ Tcl_Obj *resultPtr;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+
+ resultPtr = Tcl_NewObj();
+ hashPtr = Tcl_FindHashEntry(&dispPtr->colorNameTable, name);
+ if (hashPtr != NULL) {
+ TkColor *tkColPtr = Tcl_GetHashValue(hashPtr);
+
+ if (tkColPtr == NULL) {
+ Tcl_Panic("TkDebugColor found empty hash table entry");
+ }
+ for ( ; (tkColPtr != NULL); tkColPtr = tkColPtr->nextPtr) {
+ Tcl_Obj *objPtr = Tcl_NewObj();
+
+ Tcl_ListObjAppendElement(NULL, objPtr,
+ Tcl_NewIntObj(tkColPtr->resourceRefCount));
+ Tcl_ListObjAppendElement(NULL, objPtr,
+ Tcl_NewIntObj(tkColPtr->objRefCount));
+ Tcl_ListObjAppendElement(NULL, resultPtr, objPtr);
+ }
+ }
+ return resultPtr;
+}
+
+#ifndef _WIN32
+
+/* This function is not necessary for Win32,
+ * since XParseColor already does the right thing */
+
+#undef XParseColor
+
+const char *const tkWebColors[20] = {
+ /* 'a' */ "qua\0#0000ffffffff",
+ /* 'b' */ NULL,
+ /* 'c' */ "rimson\0#dcdc14143c3c",
+ /* 'd' */ NULL,
+ /* 'e' */ NULL,
+ /* 'f' */ "uchsia\0#ffff0000ffff",
+ /* 'g' */ "reen\0#000080800000",
+ /* 'h' */ NULL,
+ /* 'i' */ "ndigo\0#4b4b00008282",
+ /* 'j' */ NULL,
+ /* 'k' */ NULL,
+ /* 'l' */ "ime\0#0000ffff0000",
+ /* 'm' */ "aroon\0#808000000000",
+ /* 'n' */ NULL,
+ /* 'o' */ "live\0#808080800000",
+ /* 'p' */ "urple\0#808000008080",
+ /* 'q' */ NULL,
+ /* 'r' */ NULL,
+ /* 's' */ "ilver\0#c0c0c0c0c0c0",
+ /* 't' */ "eal\0#000080808080"
+};
+
+Status
+TkParseColor(
+ Display *display, /* The display */
+ Colormap map, /* Color map */
+ const char *name, /* String to be parsed */
+ XColor *color)
+{
+ char buf[14];
+ if (*name == '#') {
+ buf[0] = '#'; buf[13] = '\0';
+ if (!*(++name) || !*(++name) || !*(++name)) {
+ /* Not at least 3 hex digits, so invalid */
+ return 0;
+ } else if (!*(++name)) {
+ /* Exactly 3 hex digits */
+ buf[9] = buf[10] = buf[11] = buf[12] = *(--name);
+ buf[5] = buf[6] = buf[7] = buf[8] = *(--name);
+ buf[1] = buf[2] = buf[3] = buf[4] = *(--name);
+ name = buf;
+ } else if (!*(++name) || !*(++name)) {
+ /* Not at least 6 hex digits, so invalid */
+ return 0;
+ } else if (!*(++name)) {
+ /* Exactly 6 hex digits */
+ buf[10] = buf[12] = *(--name);
+ buf[9] = buf[11] = *(--name);
+ buf[6] = buf[8] = *(--name);
+ buf[5] = buf[7] = *(--name);
+ buf[2] = buf[4] = *(--name);
+ buf[1] = buf[3] = *(--name);
+ name = buf;
+ } else if (!*(++name) || !*(++name)) {
+ /* Not at least 9 hex digits, so invalid */
+ return 0;
+ } else if (!*(++name)) {
+ /* Exactly 9 hex digits */
+ buf[11] = *(--name);
+ buf[10] = *(--name);
+ buf[9] = buf[12] = *(--name);
+ buf[7] = *(--name);
+ buf[6] = *(--name);
+ buf[5] = buf[8] = *(--name);
+ buf[3] = *(--name);
+ buf[2] = *(--name);
+ buf[1] = buf[4] = *(--name);
+ name = buf;
+ } else if (!*(++name) || !*(++name) || *(++name)) {
+ /* Not exactly 12 hex digits, so invalid */
+ return 0;
+ } else {
+ name -= 13;
+ }
+ goto done;
+ } else if (((*name - 'A') & 0xdf) < sizeof(tkWebColors)/sizeof(tkWebColors[0])) {
+ if (!((name[0] - 'G') & 0xdf) && !((name[1] - 'R') & 0xdf)
+ && !((name[2] - 'A') & 0xdb) && !((name[3] - 'Y') & 0xdf)
+ && !name[4]) {
+ name = "#808080808080";
+ goto done;
+ } else {
+ const char *p = tkWebColors[((*name - 'A') & 0x1f)];
+ if (p) {
+ const char *q = name;
+ while (!((*p - *(++q)) & 0xdf)) {
+ if (!*p++) {
+ name = p;
+ goto done;
+ }
+ }
+ }
+ }
+ }
+ if (strlen(name) > 99) {
+ return 0;
+ }
+done:
+ return XParseColor(display, map, name, color);
+}
+#endif /* _WIN32 */
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkColor.h b/tk8.6/generic/tkColor.h
new file mode 100644
index 0000000..54e8cdc
--- /dev/null
+++ b/tk8.6/generic/tkColor.h
@@ -0,0 +1,75 @@
+/*
+ * tkColor.h --
+ *
+ * Declarations of data types and functions used by the Tk color module.
+ *
+ * Copyright (c) 1996-1997 by Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef _TKCOLOR
+#define _TKCOLOR
+
+#include "tkInt.h"
+
+/*
+ * One of the following data structures is used to keep track of each color
+ * that is being used by the application; typically there is a colormap entry
+ * allocated for each of these colors.
+ */
+
+#define TK_COLOR_BY_NAME 1
+#define TK_COLOR_BY_VALUE 2
+
+#define COLOR_MAGIC ((unsigned int) 0x46140277)
+
+typedef struct TkColor {
+ XColor color; /* Information about this color. */
+ unsigned int magic; /* Used for quick integrity check on this
+ * structure. Must always have the value
+ * COLOR_MAGIC. */
+ GC gc; /* Simple gc with this color as foreground
+ * color and all other fields defaulted. May
+ * be NULL. */
+ Screen *screen; /* Screen where this color is valid. Used to
+ * delete it, and to find its display. */
+ Colormap colormap; /* Colormap from which this entry was
+ * allocated. */
+ Visual *visual; /* Visual associated with colormap. */
+ int resourceRefCount; /* Number of active uses of this color (each
+ * active use corresponds to a call to
+ * Tk_AllocColorFromObj or Tk_GetColor). If
+ * this count is 0, then this TkColor
+ * structure is no longer valid and it isn't
+ * present in a hash table: it is being kept
+ * around only because there are objects
+ * referring to it. The structure is freed
+ * when resourceRefCount and objRefCount are
+ * both 0. */
+ int objRefCount; /* The number of Tcl objects that reference
+ * this structure. */
+ int type; /* TK_COLOR_BY_NAME or TK_COLOR_BY_VALUE. */
+ Tcl_HashEntry *hashPtr; /* Pointer to hash table entry for this
+ * structure. (for use in deleting entry). */
+ struct TkColor *nextPtr; /* Points to the next TkColor structure with
+ * the same color name. Colors with the same
+ * name but different screens or colormaps are
+ * chained together off a single entry in
+ * nameTable. For colors in valueTable (those
+ * allocated by Tk_GetColorByValue) this field
+ * is always NULL. */
+} TkColor;
+
+/*
+ * Common APIs exported from all platform-specific implementations.
+ */
+
+#ifndef TkpFreeColor
+MODULE_SCOPE void TkpFreeColor(TkColor *tkColPtr);
+#endif
+MODULE_SCOPE TkColor * TkpGetColor(Tk_Window tkwin, Tk_Uid name);
+MODULE_SCOPE TkColor * TkpGetColorByValue(Tk_Window tkwin, XColor *colorPtr);
+
+#endif /* _TKCOLOR */
diff --git a/tk8.6/generic/tkConfig.c b/tk8.6/generic/tkConfig.c
new file mode 100644
index 0000000..f1a5176
--- /dev/null
+++ b/tk8.6/generic/tkConfig.c
@@ -0,0 +1,2114 @@
+/*
+ * tkConfig.c --
+ *
+ * This file contains functions that manage configuration options for
+ * widgets and other things.
+ *
+ * Copyright (c) 1997-1998 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+/*
+ * Temporary flag for working on new config package.
+ */
+
+#if 0
+
+/*
+ * used only for removing the old config code
+ */
+
+#define __NO_OLD_CONFIG
+#endif
+
+#include "tkInt.h"
+#include "tkFont.h"
+
+/*
+ * The following definition keeps track of all of
+ * the option tables that have been created for a thread.
+ */
+
+typedef struct {
+ int initialized; /* 0 means table below needs initializing. */
+ Tcl_HashTable hashTable;
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+
+
+/*
+ * The following two structures are used along with Tk_OptionSpec structures
+ * to manage configuration options. Tk_OptionSpec is static templates that are
+ * compiled into the code of a widget or other object manager. However, to
+ * look up options efficiently we need to supplement the static information
+ * with additional dynamic information, and this dynamic information may be
+ * different for each application. Thus we create structures of the following
+ * two types to hold all of the dynamic information; this is done by
+ * Tk_CreateOptionTable.
+ *
+ * One of the following structures corresponds to each Tk_OptionSpec. These
+ * structures exist as arrays inside TkOptionTable structures.
+ */
+
+typedef struct TkOption {
+ const Tk_OptionSpec *specPtr;
+ /* The original spec from the template passed
+ * to Tk_CreateOptionTable.*/
+ Tk_Uid dbNameUID; /* The Uid form of the option database
+ * name. */
+ Tk_Uid dbClassUID; /* The Uid form of the option database class
+ * name. */
+ Tcl_Obj *defaultPtr; /* Default value for this option. */
+ union {
+ Tcl_Obj *monoColorPtr; /* For color and border options, this is an
+ * alternate default value to use on
+ * monochrome displays. */
+ struct TkOption *synonymPtr;
+ /* For synonym options, this points to the
+ * master entry. */
+ const struct Tk_ObjCustomOption *custom;
+ /* For TK_OPTION_CUSTOM. */
+ } extra;
+ int flags; /* Miscellaneous flag values; see below for
+ * definitions. */
+} Option;
+
+/*
+ * Flag bits defined for Option structures:
+ *
+ * OPTION_NEEDS_FREEING - 1 means that FreeResources must be invoked to
+ * free resources associated with the option when
+ * it is no longer needed.
+ */
+
+#define OPTION_NEEDS_FREEING 1
+
+/*
+ * One of the following exists for each Tk_OptionSpec array that has been
+ * passed to Tk_CreateOptionTable.
+ */
+
+typedef struct OptionTable {
+ int refCount; /* Counts the number of uses of this table
+ * (the number of times Tk_CreateOptionTable
+ * has returned it). This can be greater than
+ * 1 if it is shared along several option
+ * table chains, or if the same table is used
+ * for multiple purposes. */
+ Tcl_HashEntry *hashEntryPtr;/* Hash table entry that refers to this table;
+ * used to delete the entry. */
+ struct OptionTable *nextPtr;/* If templatePtr was part of a chain of
+ * templates, this points to the table
+ * corresponding to the next template in the
+ * chain. */
+ int numOptions; /* The number of items in the options array
+ * below. */
+ Option options[1]; /* Information about the individual options in
+ * the table. This must be the last field in
+ * the structure: the actual size of the array
+ * will be numOptions, not 1. */
+} OptionTable;
+
+/*
+ * Forward declarations for functions defined later in this file:
+ */
+
+static int DoObjConfig(Tcl_Interp *interp, char *recordPtr,
+ Option *optionPtr, Tcl_Obj *valuePtr,
+ Tk_Window tkwin, Tk_SavedOption *savePtr);
+static void FreeResources(Option *optionPtr, Tcl_Obj *objPtr,
+ char *internalPtr, Tk_Window tkwin);
+static Tcl_Obj * GetConfigList(char *recordPtr,
+ Option *optionPtr, Tk_Window tkwin);
+static Tcl_Obj * GetObjectForOption(char *recordPtr,
+ Option *optionPtr, Tk_Window tkwin);
+static Option * GetOption(const char *name, OptionTable *tablePtr);
+static Option * GetOptionFromObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, OptionTable *tablePtr);
+static int ObjectIsEmpty(Tcl_Obj *objPtr);
+static void FreeOptionInternalRep(Tcl_Obj *objPtr);
+static void DupOptionInternalRep(Tcl_Obj *, Tcl_Obj *);
+
+/*
+ * The structure below defines an object type that is used to cache the result
+ * of looking up an option name. If an object has this type, then its
+ * internalPtr1 field points to the OptionTable in which it was looked up, and
+ * the internalPtr2 field points to the entry that matched.
+ */
+
+static const Tcl_ObjType optionObjType = {
+ "option", /* name */
+ FreeOptionInternalRep, /* freeIntRepProc */
+ DupOptionInternalRep, /* dupIntRepProc */
+ NULL, /* updateStringProc */
+ NULL /* setFromAnyProc */
+};
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CreateOptionTable --
+ *
+ * Given a template for configuration options, this function creates a
+ * table that may be used to look up options efficiently.
+ *
+ * Results:
+ * Returns a token to a structure that can be passed to functions such as
+ * Tk_InitOptions, Tk_SetOptions, and Tk_FreeConfigOptions.
+ *
+ * Side effects:
+ * Storage is allocated.
+ *
+ *--------------------------------------------------------------
+ */
+
+Tk_OptionTable
+Tk_CreateOptionTable(
+ Tcl_Interp *interp, /* Interpreter associated with the application
+ * in which this table will be used. */
+ const Tk_OptionSpec *templatePtr)
+ /* Static information about the configuration
+ * options. */
+{
+ Tcl_HashEntry *hashEntryPtr;
+ int newEntry;
+ OptionTable *tablePtr;
+ const Tk_OptionSpec *specPtr, *specPtr2;
+ Option *optionPtr;
+ int numOptions, i;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ /*
+ * We use an TSD in the thread to keep a hash table of
+ * all the option tables we've created for this application. This is
+ * used for allowing us to share the tables (e.g. in several chains).
+ * The code below finds the hash table or creates a new one if it
+ * doesn't already exist.
+ */
+
+ if (!tsdPtr->initialized) {
+ Tcl_InitHashTable(&tsdPtr->hashTable, TCL_ONE_WORD_KEYS);
+ tsdPtr->initialized = 1;
+ }
+
+ /*
+ * See if a table has already been created for this template. If so, just
+ * reuse the existing table.
+ */
+
+ hashEntryPtr = Tcl_CreateHashEntry(&tsdPtr->hashTable, (char *) templatePtr,
+ &newEntry);
+ if (!newEntry) {
+ tablePtr = Tcl_GetHashValue(hashEntryPtr);
+ tablePtr->refCount++;
+ return (Tk_OptionTable) tablePtr;
+ }
+
+ /*
+ * Count the number of options in the template, then create the table
+ * structure.
+ */
+
+ numOptions = 0;
+ for (specPtr = templatePtr; specPtr->type != TK_OPTION_END; specPtr++) {
+ numOptions++;
+ }
+ tablePtr = ckalloc(sizeof(OptionTable) + (numOptions * sizeof(Option)));
+ tablePtr->refCount = 1;
+ tablePtr->hashEntryPtr = hashEntryPtr;
+ tablePtr->nextPtr = NULL;
+ tablePtr->numOptions = numOptions;
+
+ /*
+ * Initialize all of the Option structures in the table.
+ */
+
+ for (specPtr = templatePtr, optionPtr = tablePtr->options;
+ specPtr->type != TK_OPTION_END; specPtr++, optionPtr++) {
+ optionPtr->specPtr = specPtr;
+ optionPtr->dbNameUID = NULL;
+ optionPtr->dbClassUID = NULL;
+ optionPtr->defaultPtr = NULL;
+ optionPtr->extra.monoColorPtr = NULL;
+ optionPtr->flags = 0;
+
+ if (specPtr->type == TK_OPTION_SYNONYM) {
+ /*
+ * This is a synonym option; find the master option that it refers
+ * to and create a pointer from the synonym to the master.
+ */
+
+ for (specPtr2 = templatePtr, i = 0; ; specPtr2++, i++) {
+ if (specPtr2->type == TK_OPTION_END) {
+ Tcl_Panic("Tk_CreateOptionTable couldn't find synonym");
+ }
+ if (strcmp(specPtr2->optionName,
+ (char *) specPtr->clientData) == 0) {
+ optionPtr->extra.synonymPtr = tablePtr->options + i;
+ break;
+ }
+ }
+ } else {
+ if (specPtr->dbName != NULL) {
+ optionPtr->dbNameUID = Tk_GetUid(specPtr->dbName);
+ }
+ if (specPtr->dbClass != NULL) {
+ optionPtr->dbClassUID = Tk_GetUid(specPtr->dbClass);
+ }
+ if (specPtr->defValue != NULL) {
+ optionPtr->defaultPtr = Tcl_NewStringObj(specPtr->defValue,-1);
+ Tcl_IncrRefCount(optionPtr->defaultPtr);
+ }
+ if (((specPtr->type == TK_OPTION_COLOR)
+ || (specPtr->type == TK_OPTION_BORDER))
+ && (specPtr->clientData != NULL)) {
+ optionPtr->extra.monoColorPtr =
+ Tcl_NewStringObj(specPtr->clientData, -1);
+ Tcl_IncrRefCount(optionPtr->extra.monoColorPtr);
+ }
+
+ if (specPtr->type == TK_OPTION_CUSTOM) {
+ /*
+ * Get the custom parsing, etc., functions.
+ */
+
+ optionPtr->extra.custom = specPtr->clientData;
+ }
+ }
+ if (((specPtr->type == TK_OPTION_STRING)
+ && (specPtr->internalOffset >= 0))
+ || (specPtr->type == TK_OPTION_COLOR)
+ || (specPtr->type == TK_OPTION_FONT)
+ || (specPtr->type == TK_OPTION_BITMAP)
+ || (specPtr->type == TK_OPTION_BORDER)
+ || (specPtr->type == TK_OPTION_CURSOR)
+ || (specPtr->type == TK_OPTION_CUSTOM)) {
+ optionPtr->flags |= OPTION_NEEDS_FREEING;
+ }
+ }
+ tablePtr->hashEntryPtr = hashEntryPtr;
+ Tcl_SetHashValue(hashEntryPtr, tablePtr);
+
+ /*
+ * Finally, check to see if this template chains to another template with
+ * additional options. If so, call ourselves recursively to create the
+ * next table(s).
+ */
+
+ if (specPtr->clientData != NULL) {
+ tablePtr->nextPtr = (OptionTable *)
+ Tk_CreateOptionTable(interp, specPtr->clientData);
+ }
+
+ return (Tk_OptionTable) tablePtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_DeleteOptionTable --
+ *
+ * Called to release resources used by an option table when the table is
+ * no longer needed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The option table and associated resources (such as additional option
+ * tables chained off it) are destroyed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_DeleteOptionTable(
+ Tk_OptionTable optionTable) /* The option table to delete. */
+{
+ OptionTable *tablePtr = (OptionTable *) optionTable;
+ Option *optionPtr;
+ int count;
+
+ tablePtr->refCount--;
+ if (tablePtr->refCount > 0) {
+ return;
+ }
+
+ if (tablePtr->nextPtr != NULL) {
+ Tk_DeleteOptionTable((Tk_OptionTable) tablePtr->nextPtr);
+ }
+
+ for (count = tablePtr->numOptions, optionPtr = tablePtr->options;
+ count > 0; count--, optionPtr++) {
+ if (optionPtr->defaultPtr != NULL) {
+ Tcl_DecrRefCount(optionPtr->defaultPtr);
+ }
+ if (((optionPtr->specPtr->type == TK_OPTION_COLOR)
+ || (optionPtr->specPtr->type == TK_OPTION_BORDER))
+ && (optionPtr->extra.monoColorPtr != NULL)) {
+ Tcl_DecrRefCount(optionPtr->extra.monoColorPtr);
+ }
+ }
+ Tcl_DeleteHashEntry(tablePtr->hashEntryPtr);
+ ckfree(tablePtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_InitOptions --
+ *
+ * This function is invoked when an object such as a widget is created.
+ * It supplies an initial value for each configuration option (the value
+ * may come from the option database, a system default, or the default in
+ * the option table).
+ *
+ * Results:
+ * The return value is TCL_OK if the function completed successfully, and
+ * TCL_ERROR if one of the initial values was bogus. If an error occurs
+ * and interp isn't NULL, then an error message will be left in its
+ * result.
+ *
+ * Side effects:
+ * Fields of recordPtr are filled in with initial values.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_InitOptions(
+ Tcl_Interp *interp, /* Interpreter for error reporting. NULL means
+ * don't leave an error message. */
+ char *recordPtr, /* Pointer to the record to configure. Note:
+ * the caller should have properly initialized
+ * the record with NULL pointers for each
+ * option value. */
+ Tk_OptionTable optionTable, /* The token which matches the config specs
+ * for the widget in question. */
+ Tk_Window tkwin) /* Certain options types (such as
+ * TK_OPTION_COLOR) need fields out of the
+ * window they are used in to be able to
+ * calculate their values. Not needed unless
+ * one of these options is in the configSpecs
+ * record. */
+{
+ OptionTable *tablePtr = (OptionTable *) optionTable;
+ Option *optionPtr;
+ int count;
+ Tk_Uid value;
+ Tcl_Obj *valuePtr;
+ enum {
+ OPTION_DATABASE, SYSTEM_DEFAULT, TABLE_DEFAULT
+ } source;
+
+ /*
+ * If this table chains to other tables, handle their initialization
+ * first. That way, if both tables refer to the same field of the record,
+ * the value in the first table will win.
+ */
+
+ if (tablePtr->nextPtr != NULL) {
+ if (Tk_InitOptions(interp, recordPtr,
+ (Tk_OptionTable) tablePtr->nextPtr, tkwin) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * Iterate over all of the options in the table, initializing each in
+ * turn.
+ */
+
+ for (optionPtr = tablePtr->options, count = tablePtr->numOptions;
+ count > 0; optionPtr++, count--) {
+ /*
+ * If we specify TK_OPTION_DONT_SET_DEFAULT, then the user has
+ * processed and set a default for this already.
+ */
+
+ if ((optionPtr->specPtr->type == TK_OPTION_SYNONYM) ||
+ (optionPtr->specPtr->flags & TK_OPTION_DONT_SET_DEFAULT)) {
+ continue;
+ }
+ source = TABLE_DEFAULT;
+
+ /*
+ * We look in three places for the initial value, using the first
+ * non-NULL value that we find. First, check the option database.
+ */
+
+ valuePtr = NULL;
+ if (optionPtr->dbNameUID != NULL) {
+ value = Tk_GetOption(tkwin, optionPtr->dbNameUID,
+ optionPtr->dbClassUID);
+ if (value != NULL) {
+ valuePtr = Tcl_NewStringObj(value, -1);
+ source = OPTION_DATABASE;
+ }
+ }
+
+ /*
+ * Second, check for a system-specific default value.
+ */
+
+ if ((valuePtr == NULL)
+ && (optionPtr->dbNameUID != NULL)) {
+ valuePtr = TkpGetSystemDefault(tkwin, optionPtr->dbNameUID,
+ optionPtr->dbClassUID);
+ if (valuePtr != NULL) {
+ source = SYSTEM_DEFAULT;
+ }
+ }
+
+ /*
+ * Third and last, use the default value supplied by the option table.
+ * In the case of color objects, we pick one of two values depending
+ * on whether the screen is mono or color.
+ */
+
+ if (valuePtr == NULL) {
+ if ((tkwin != NULL)
+ && ((optionPtr->specPtr->type == TK_OPTION_COLOR)
+ || (optionPtr->specPtr->type == TK_OPTION_BORDER))
+ && (Tk_Depth(tkwin) <= 1)
+ && (optionPtr->extra.monoColorPtr != NULL)) {
+ valuePtr = optionPtr->extra.monoColorPtr;
+ } else {
+ valuePtr = optionPtr->defaultPtr;
+ }
+ }
+
+ if (valuePtr == NULL) {
+ continue;
+ }
+
+ /*
+ * Bump the reference count on valuePtr, so that it is strongly
+ * referenced here, and will be properly free'd when finished,
+ * regardless of what DoObjConfig does.
+ */
+
+ Tcl_IncrRefCount(valuePtr);
+
+ if (DoObjConfig(interp, recordPtr, optionPtr, valuePtr, tkwin,
+ NULL) != TCL_OK) {
+ if (interp != NULL) {
+ char msg[200];
+
+ switch (source) {
+ case OPTION_DATABASE:
+ sprintf(msg, "\n (database entry for \"%.50s\")",
+ optionPtr->specPtr->optionName);
+ break;
+ case SYSTEM_DEFAULT:
+ sprintf(msg, "\n (system default for \"%.50s\")",
+ optionPtr->specPtr->optionName);
+ break;
+ case TABLE_DEFAULT:
+ sprintf(msg, "\n (default value for \"%.50s\")",
+ optionPtr->specPtr->optionName);
+ }
+ if (tkwin != NULL) {
+ sprintf(msg + strlen(msg) - 1, " in widget \"%.50s\")",
+ Tk_PathName(tkwin));
+ }
+ Tcl_AddErrorInfo(interp, msg);
+ }
+ Tcl_DecrRefCount(valuePtr);
+ return TCL_ERROR;
+ }
+ Tcl_DecrRefCount(valuePtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DoObjConfig --
+ *
+ * This function applies a new value for a configuration option to the
+ * record being configured.
+ *
+ * Results:
+ * The return value is TCL_OK if the function completed successfully. If
+ * an error occurred then TCL_ERROR is returned and an error message is
+ * left in interp's result, if interp isn't NULL. In addition, if
+ * oldValuePtrPtr isn't NULL then it *oldValuePtrPtr is filled in with a
+ * pointer to the option's old value.
+ *
+ * Side effects:
+ * RecordPtr gets modified to hold the new value in the form of a
+ * Tcl_Obj, an internal representation, or both. The old value is freed
+ * if oldValuePtrPtr is NULL.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+DoObjConfig(
+ Tcl_Interp *interp, /* Interpreter for error reporting. If NULL,
+ * then no message is left if an error
+ * occurs. */
+ char *recordPtr, /* The record to modify to hold the new option
+ * value. */
+ Option *optionPtr, /* Pointer to information about the option. */
+ Tcl_Obj *valuePtr, /* New value for option. */
+ Tk_Window tkwin, /* Window in which option will be used (needed
+ * to allocate resources for some options).
+ * May be NULL if the option doesn't require
+ * window-related resources. */
+ Tk_SavedOption *savedOptionPtr)
+ /* If NULL, the old value for the option will
+ * be freed. If non-NULL, the old value will
+ * be stored here, and it becomes the property
+ * of the caller (the caller must eventually
+ * free the old value). */
+{
+ Tcl_Obj **slotPtrPtr, *oldPtr;
+ char *internalPtr; /* Points to location in record where internal
+ * representation of value should be stored,
+ * or NULL. */
+ char *oldInternalPtr; /* Points to location in which to save old
+ * internal representation of value. */
+ Tk_SavedOption internal; /* Used to save the old internal
+ * representation of the value if
+ * savedOptionPtr is NULL. */
+ const Tk_OptionSpec *specPtr;
+ int nullOK;
+
+ /*
+ * Save the old object form for the value, if there is one.
+ */
+
+ specPtr = optionPtr->specPtr;
+ if (specPtr->objOffset >= 0) {
+ slotPtrPtr = (Tcl_Obj **) (recordPtr + specPtr->objOffset);
+ oldPtr = *slotPtrPtr;
+ } else {
+ slotPtrPtr = NULL;
+ oldPtr = NULL;
+ }
+
+ /*
+ * Apply the new value in a type-specific way. Also remember the old
+ * object and internal forms, if they exist.
+ */
+
+ if (specPtr->internalOffset >= 0) {
+ internalPtr = recordPtr + specPtr->internalOffset;
+ } else {
+ internalPtr = NULL;
+ }
+ if (savedOptionPtr != NULL) {
+ savedOptionPtr->optionPtr = optionPtr;
+ savedOptionPtr->valuePtr = oldPtr;
+ oldInternalPtr = (char *) &savedOptionPtr->internalForm;
+ } else {
+ oldInternalPtr = (char *) &internal.internalForm;
+ }
+ nullOK = (optionPtr->specPtr->flags & TK_OPTION_NULL_OK);
+ switch (optionPtr->specPtr->type) {
+ case TK_OPTION_BOOLEAN: {
+ int newBool;
+
+ if (Tcl_GetBooleanFromObj(interp, valuePtr, &newBool) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (internalPtr != NULL) {
+ *((int *) oldInternalPtr) = *((int *) internalPtr);
+ *((int *) internalPtr) = newBool;
+ }
+ break;
+ }
+ case TK_OPTION_INT: {
+ int newInt;
+
+ if (Tcl_GetIntFromObj(interp, valuePtr, &newInt) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (internalPtr != NULL) {
+ *((int *) oldInternalPtr) = *((int *) internalPtr);
+ *((int *) internalPtr) = newInt;
+ }
+ break;
+ }
+ case TK_OPTION_DOUBLE: {
+ double newDbl;
+
+ if (nullOK && ObjectIsEmpty(valuePtr)) {
+ valuePtr = NULL;
+ newDbl = 0;
+ } else {
+ if (Tcl_GetDoubleFromObj(interp, valuePtr, &newDbl) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+
+ if (internalPtr != NULL) {
+ *((double *) oldInternalPtr) = *((double *) internalPtr);
+ *((double *) internalPtr) = newDbl;
+ }
+ break;
+ }
+ case TK_OPTION_STRING: {
+ char *newStr;
+ const char *value;
+ int length;
+
+ if (nullOK && ObjectIsEmpty(valuePtr)) {
+ valuePtr = NULL;
+ }
+ if (internalPtr != NULL) {
+ if (valuePtr != NULL) {
+ value = Tcl_GetStringFromObj(valuePtr, &length);
+ newStr = ckalloc(length + 1);
+ strcpy(newStr, value);
+ } else {
+ newStr = NULL;
+ }
+ *((char **) oldInternalPtr) = *((char **) internalPtr);
+ *((char **) internalPtr) = newStr;
+ }
+ break;
+ }
+ case TK_OPTION_STRING_TABLE: {
+ int newValue;
+
+ if (Tcl_GetIndexFromObjStruct(interp, valuePtr,
+ optionPtr->specPtr->clientData, sizeof(char *),
+ optionPtr->specPtr->optionName+1, 0, &newValue) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (internalPtr != NULL) {
+ *((int *) oldInternalPtr) = *((int *) internalPtr);
+ *((int *) internalPtr) = newValue;
+ }
+ break;
+ }
+ case TK_OPTION_COLOR: {
+ XColor *newPtr;
+
+ if (nullOK && ObjectIsEmpty(valuePtr)) {
+ valuePtr = NULL;
+ newPtr = NULL;
+ } else {
+ newPtr = Tk_AllocColorFromObj(interp, tkwin, valuePtr);
+ if (newPtr == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ if (internalPtr != NULL) {
+ *((XColor **) oldInternalPtr) = *((XColor **) internalPtr);
+ *((XColor **) internalPtr) = newPtr;
+ }
+ break;
+ }
+ case TK_OPTION_FONT: {
+ Tk_Font newFont;
+
+ if (nullOK && ObjectIsEmpty(valuePtr)) {
+ valuePtr = NULL;
+ newFont = NULL;
+ } else {
+ newFont = Tk_AllocFontFromObj(interp, tkwin, valuePtr);
+ if (newFont == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ if (internalPtr != NULL) {
+ *((Tk_Font *) oldInternalPtr) = *((Tk_Font *) internalPtr);
+ *((Tk_Font *) internalPtr) = newFont;
+ }
+ break;
+ }
+ case TK_OPTION_STYLE: {
+ Tk_Style newStyle;
+
+ if (nullOK && ObjectIsEmpty(valuePtr)) {
+ valuePtr = NULL;
+ newStyle = NULL;
+ } else {
+ newStyle = Tk_AllocStyleFromObj(interp, valuePtr);
+ if (newStyle == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ if (internalPtr != NULL) {
+ *((Tk_Style *) oldInternalPtr) = *((Tk_Style *) internalPtr);
+ *((Tk_Style *) internalPtr) = newStyle;
+ }
+ break;
+ }
+ case TK_OPTION_BITMAP: {
+ Pixmap newBitmap;
+
+ if (nullOK && ObjectIsEmpty(valuePtr)) {
+ valuePtr = NULL;
+ newBitmap = None;
+ } else {
+ newBitmap = Tk_AllocBitmapFromObj(interp, tkwin, valuePtr);
+ if (newBitmap == None) {
+ return TCL_ERROR;
+ }
+ }
+ if (internalPtr != NULL) {
+ *((Pixmap *) oldInternalPtr) = *((Pixmap *) internalPtr);
+ *((Pixmap *) internalPtr) = newBitmap;
+ }
+ break;
+ }
+ case TK_OPTION_BORDER: {
+ Tk_3DBorder newBorder;
+
+ if (nullOK && ObjectIsEmpty(valuePtr)) {
+ valuePtr = NULL;
+ newBorder = NULL;
+ } else {
+ newBorder = Tk_Alloc3DBorderFromObj(interp, tkwin, valuePtr);
+ if (newBorder == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ if (internalPtr != NULL) {
+ *((Tk_3DBorder *) oldInternalPtr) = *((Tk_3DBorder *) internalPtr);
+ *((Tk_3DBorder *) internalPtr) = newBorder;
+ }
+ break;
+ }
+ case TK_OPTION_RELIEF: {
+ int newRelief;
+
+ if (nullOK && ObjectIsEmpty(valuePtr)) {
+ valuePtr = NULL;
+ newRelief = TK_RELIEF_NULL;
+ } else {
+ if (Tk_GetReliefFromObj(interp, valuePtr, &newRelief) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (internalPtr != NULL) {
+ *((int *) oldInternalPtr) = *((int *) internalPtr);
+ *((int *) internalPtr) = newRelief;
+ }
+ break;
+ }
+ case TK_OPTION_CURSOR: {
+ Tk_Cursor newCursor;
+
+ if (nullOK && ObjectIsEmpty(valuePtr)) {
+ newCursor = NULL;
+ valuePtr = NULL;
+ } else {
+ newCursor = Tk_AllocCursorFromObj(interp, tkwin, valuePtr);
+ if (newCursor == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ if (internalPtr != NULL) {
+ *((Tk_Cursor *) oldInternalPtr) = *((Tk_Cursor *) internalPtr);
+ *((Tk_Cursor *) internalPtr) = newCursor;
+ }
+ Tk_DefineCursor(tkwin, newCursor);
+ break;
+ }
+ case TK_OPTION_JUSTIFY: {
+ Tk_Justify newJustify;
+
+ if (Tk_GetJustifyFromObj(interp, valuePtr, &newJustify) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (internalPtr != NULL) {
+ *((Tk_Justify *) oldInternalPtr) = *((Tk_Justify *) internalPtr);
+ *((Tk_Justify *) internalPtr) = newJustify;
+ }
+ break;
+ }
+ case TK_OPTION_ANCHOR: {
+ Tk_Anchor newAnchor;
+
+ if (Tk_GetAnchorFromObj(interp, valuePtr, &newAnchor) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (internalPtr != NULL) {
+ *((Tk_Anchor *) oldInternalPtr) = *((Tk_Anchor *) internalPtr);
+ *((Tk_Anchor *) internalPtr) = newAnchor;
+ }
+ break;
+ }
+ case TK_OPTION_PIXELS: {
+ int newPixels;
+
+ if (nullOK && ObjectIsEmpty(valuePtr)) {
+ valuePtr = NULL;
+ newPixels = 0;
+ } else {
+ if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr,
+ &newPixels) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (internalPtr != NULL) {
+ *((int *) oldInternalPtr) = *((int *) internalPtr);
+ *((int *) internalPtr) = newPixels;
+ }
+ break;
+ }
+ case TK_OPTION_WINDOW: {
+ Tk_Window newWin;
+
+ if (nullOK && ObjectIsEmpty(valuePtr)) {
+ valuePtr = NULL;
+ newWin = NULL;
+ } else {
+ if (TkGetWindowFromObj(interp, tkwin, valuePtr,
+ &newWin) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (internalPtr != NULL) {
+ *((Tk_Window *) oldInternalPtr) = *((Tk_Window *) internalPtr);
+ *((Tk_Window *) internalPtr) = newWin;
+ }
+ break;
+ }
+ case TK_OPTION_CUSTOM: {
+ const Tk_ObjCustomOption *custom = optionPtr->extra.custom;
+
+ if (custom->setProc(custom->clientData, interp, tkwin,
+ &valuePtr, recordPtr, optionPtr->specPtr->internalOffset,
+ (char *)oldInternalPtr, optionPtr->specPtr->flags) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+ }
+
+ default:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad config table: unknown type %d",
+ optionPtr->specPtr->type));
+ Tcl_SetErrorCode(interp, "TK", "BAD_CONFIG", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Release resources associated with the old value, if we're not returning
+ * it to the caller, then install the new object value into the record.
+ */
+
+ if (savedOptionPtr == NULL) {
+ if (optionPtr->flags & OPTION_NEEDS_FREEING) {
+ FreeResources(optionPtr, oldPtr, oldInternalPtr, tkwin);
+ }
+ if (oldPtr != NULL) {
+ Tcl_DecrRefCount(oldPtr);
+ }
+ }
+ if (slotPtrPtr != NULL) {
+ *slotPtrPtr = valuePtr;
+ if (valuePtr != NULL) {
+ Tcl_IncrRefCount(valuePtr);
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ObjectIsEmpty --
+ *
+ * This function tests whether the string value of an object is empty.
+ *
+ * Results:
+ * The return value is 1 if the string value of objPtr has length zero,
+ * and 0 otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ObjectIsEmpty(
+ Tcl_Obj *objPtr) /* Object to test. May be NULL. */
+{
+ if (objPtr == NULL) {
+ return 1;
+ }
+ if (objPtr->bytes == NULL) {
+ Tcl_GetString(objPtr);
+ }
+ return (objPtr->length == 0);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetOption --
+ *
+ * This function searches through a chained option table to find the
+ * entry for a particular option name.
+ *
+ * Results:
+ * The return value is a pointer to the matching entry, or NULL if no
+ * matching entry could be found. Note: if the matching entry is a
+ * synonym then this function returns a pointer to the synonym entry,
+ * *not* the "real" entry that the synonym refers to.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Option *
+GetOption(
+ const char *name, /* String balue to be looked up in the option
+ * table. */
+ OptionTable *tablePtr) /* Table in which to look up name. */
+{
+ Option *bestPtr, *optionPtr;
+ OptionTable *tablePtr2;
+ const char *p1, *p2;
+ int count;
+
+ /*
+ * Search through all of the option tables in the chain to find the best
+ * match. Some tricky aspects:
+ *
+ * 1. We have to accept unique abbreviations.
+ * 2. The same name could appear in different tables in the chain. If this
+ * happens, we use the entry from the first table. We have to be
+ * careful to distinguish this case from an ambiguous abbreviation.
+ */
+
+ bestPtr = NULL;
+ for (tablePtr2 = tablePtr; tablePtr2 != NULL;
+ tablePtr2 = tablePtr2->nextPtr) {
+ for (optionPtr = tablePtr2->options, count = tablePtr2->numOptions;
+ count > 0; optionPtr++, count--) {
+ for (p1 = name, p2 = optionPtr->specPtr->optionName;
+ *p1 == *p2; p1++, p2++) {
+ if (*p1 == 0) {
+ /*
+ * This is an exact match. We're done.
+ */
+
+ return optionPtr;
+ }
+ }
+ if (*p1 == 0) {
+ /*
+ * The name is an abbreviation for this option. Keep to make
+ * sure that the abbreviation only matches one option name.
+ * If we've already found a match in the past, then it is an
+ * error unless the full names for the two options are
+ * identical; in this case, the first option overrides the
+ * second.
+ */
+
+ if (bestPtr == NULL) {
+ bestPtr = optionPtr;
+ } else if (strcmp(bestPtr->specPtr->optionName,
+ optionPtr->specPtr->optionName) != 0) {
+ return NULL;
+ }
+ }
+ }
+ }
+
+ /*
+ * Return whatever we have found, which could be NULL if nothing
+ * matched. The multiple-matching case is handled above.
+ */
+
+ return bestPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetOptionFromObj --
+ *
+ * This function searches through a chained option table to find the
+ * entry for a particular option name.
+ *
+ * Results:
+ * The return value is a pointer to the matching entry, or NULL if no
+ * matching entry could be found. If NULL is returned and interp is not
+ * NULL than an error message is left in its result. Note: if the
+ * matching entry is a synonym then this function returns a pointer to
+ * the synonym entry, *not* the "real" entry that the synonym refers to.
+ *
+ * Side effects:
+ * Information about the matching entry is cached in the object
+ * containing the name, so that future lookups can proceed more quickly.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Option *
+GetOptionFromObj(
+ Tcl_Interp *interp, /* Used only for error reporting; if NULL no
+ * message is left after an error. */
+ Tcl_Obj *objPtr, /* Object whose string value is to be looked
+ * up in the option table. */
+ OptionTable *tablePtr) /* Table in which to look up objPtr. */
+{
+ Option *bestPtr;
+ const char *name;
+
+ /*
+ * First, check to see if the object already has the answer cached.
+ */
+
+ if (objPtr->typePtr == &optionObjType) {
+ if (objPtr->internalRep.twoPtrValue.ptr1 == (void *) tablePtr) {
+ return (Option *) objPtr->internalRep.twoPtrValue.ptr2;
+ }
+ }
+
+ /*
+ * The answer isn't cached.
+ */
+
+ name = Tcl_GetString(objPtr);
+ bestPtr = GetOption(name, tablePtr);
+ if (bestPtr == NULL) {
+ goto error;
+ }
+
+ if ((objPtr->typePtr != NULL)
+ && (objPtr->typePtr->freeIntRepProc != NULL)) {
+ objPtr->typePtr->freeIntRepProc(objPtr);
+ }
+ objPtr->internalRep.twoPtrValue.ptr1 = (void *) tablePtr;
+ objPtr->internalRep.twoPtrValue.ptr2 = (void *) bestPtr;
+ objPtr->typePtr = &optionObjType;
+ tablePtr->refCount++;
+ return bestPtr;
+
+ error:
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "unknown option \"%s\"", name));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "OPTION", name, NULL);
+ }
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkGetOptionSpec --
+ *
+ * This function searches through a chained option table to find the
+ * option spec for a particular option name.
+ *
+ * Results:
+ * The return value is a pointer to the option spec of the matching
+ * entry, or NULL if no matching entry could be found. Note: if the
+ * matching entry is a synonym then this function returns a pointer to
+ * the option spec of the synonym entry, *not* the "real" entry that the
+ * synonym refers to. Note: this call is primarily used by the style
+ * management code (tkStyle.c) to look up an element's option spec into a
+ * widget's option table.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+const Tk_OptionSpec *
+TkGetOptionSpec(
+ const char *name, /* String value to be looked up. */
+ Tk_OptionTable optionTable) /* Table in which to look up name. */
+{
+ Option *optionPtr;
+
+ optionPtr = GetOption(name, (OptionTable *) optionTable);
+ if (optionPtr == NULL) {
+ return NULL;
+ }
+ return optionPtr->specPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeOptionInternalRep --
+ *
+ * Part of the option Tcl object type implementation. Frees the storage
+ * associated with a option object's internal representation unless it
+ * is still in use.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The option object's internal rep is marked invalid and its memory
+ * gets freed unless it is still in use somewhere. In that case the
+ * cleanup is delayed until the last reference goes away.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FreeOptionInternalRep(
+ register Tcl_Obj *objPtr) /* Object whose internal rep to free. */
+{
+ register Tk_OptionTable tablePtr = (Tk_OptionTable) objPtr->internalRep.twoPtrValue.ptr1;
+
+ Tk_DeleteOptionTable(tablePtr);
+ objPtr->typePtr = NULL;
+ objPtr->internalRep.twoPtrValue.ptr1 = NULL;
+ objPtr->internalRep.twoPtrValue.ptr2 = NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DupOptionInternalRep --
+ *
+ * When a cached option object is duplicated, this is called to update the
+ * internal reps.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+DupOptionInternalRep(
+ Tcl_Obj *srcObjPtr, /* The object we are copying from. */
+ Tcl_Obj *dupObjPtr) /* The object we are copying to. */
+{
+ register OptionTable *tablePtr = (OptionTable *) srcObjPtr->internalRep.twoPtrValue.ptr1;
+ tablePtr->refCount++;
+ dupObjPtr->typePtr = srcObjPtr->typePtr;
+ dupObjPtr->internalRep = srcObjPtr->internalRep;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_SetOptions --
+ *
+ * Process one or more name-value pairs for configuration options and
+ * fill in fields of a record with new values.
+ *
+ * Results:
+ * If all goes well then TCL_OK is returned and the old values of any
+ * modified objects are saved in *savePtr, if it isn't NULL (the caller
+ * must eventually call Tk_RestoreSavedOptions or Tk_FreeSavedOptions to
+ * free the contents of *savePtr). In addition, if maskPtr isn't NULL
+ * then *maskPtr is filled in with the OR of the typeMask bits from all
+ * modified options. If an error occurs then TCL_ERROR is returned and a
+ * message is left in interp's result unless interp is NULL; nothing is
+ * saved in *savePtr or *maskPtr in this case.
+ *
+ * Side effects:
+ * The fields of recordPtr get filled in with object pointers from
+ * objc/objv. Old information in widgRec's fields gets recycled.
+ * Information may be left at *savePtr.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_SetOptions(
+ Tcl_Interp *interp, /* Interpreter for error reporting. If NULL,
+ * then no error message is returned.*/
+ char *recordPtr, /* The record to configure. */
+ Tk_OptionTable optionTable, /* Describes valid options. */
+ int objc, /* The number of elements in objv. */
+ Tcl_Obj *const objv[], /* Contains one or more name-value pairs. */
+ Tk_Window tkwin, /* Window associated with the thing being
+ * configured; needed for some options (such
+ * as colors). */
+ Tk_SavedOptions *savePtr, /* If non-NULL, the old values of modified
+ * options are saved here so that they can be
+ * restored after an error. */
+ int *maskPtr) /* It non-NULL, this word is modified on a
+ * successful return to hold the bit-wise OR
+ * of the typeMask fields of all options that
+ * were modified by this call. Used by the
+ * caller to figure out which options actually
+ * changed. */
+{
+ OptionTable *tablePtr = (OptionTable *) optionTable;
+ Option *optionPtr;
+ Tk_SavedOptions *lastSavePtr, *newSavePtr;
+ int mask;
+
+ if (savePtr != NULL) {
+ savePtr->recordPtr = recordPtr;
+ savePtr->tkwin = tkwin;
+ savePtr->numItems = 0;
+ savePtr->nextPtr = NULL;
+ }
+ lastSavePtr = savePtr;
+
+ /*
+ * Scan through all of the arguments, processing those that match entries
+ * in the option table.
+ */
+
+ mask = 0;
+ for ( ; objc > 0; objc -= 2, objv += 2) {
+ optionPtr = GetOptionFromObj(interp, objv[0], tablePtr);
+ if (optionPtr == NULL) {
+ goto error;
+ }
+ if (optionPtr->specPtr->type == TK_OPTION_SYNONYM) {
+ optionPtr = optionPtr->extra.synonymPtr;
+ }
+
+ if (objc < 2) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "value for \"%s\" missing",
+ Tcl_GetString(*objv)));
+ Tcl_SetErrorCode(interp, "TK", "VALUE_MISSING", NULL);
+ goto error;
+ }
+ }
+ if ((savePtr != NULL)
+ && (lastSavePtr->numItems >= TK_NUM_SAVED_OPTIONS)) {
+ /*
+ * We've run out of space for saving old option values. Allocate
+ * more space.
+ */
+
+ newSavePtr = ckalloc(sizeof(Tk_SavedOptions));
+ newSavePtr->recordPtr = recordPtr;
+ newSavePtr->tkwin = tkwin;
+ newSavePtr->numItems = 0;
+ newSavePtr->nextPtr = NULL;
+ lastSavePtr->nextPtr = newSavePtr;
+ lastSavePtr = newSavePtr;
+ }
+ if (DoObjConfig(interp, recordPtr, optionPtr, objv[1], tkwin,
+ (savePtr != NULL) ? &lastSavePtr->items[lastSavePtr->numItems]
+ : NULL) != TCL_OK) {
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (processing \"%.40s\" option)",
+ Tcl_GetString(*objv)));
+ goto error;
+ }
+ if (savePtr != NULL) {
+ lastSavePtr->numItems++;
+ }
+ mask |= optionPtr->specPtr->typeMask;
+ }
+ if (maskPtr != NULL) {
+ *maskPtr = mask;
+ }
+ return TCL_OK;
+
+ error:
+ if (savePtr != NULL) {
+ Tk_RestoreSavedOptions(savePtr);
+ }
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_RestoreSavedOptions --
+ *
+ * This function undoes the effect of a previous call to Tk_SetOptions by
+ * restoring all of the options to their value before the call to
+ * Tk_SetOptions.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The configutation record is restored and all the information stored in
+ * savePtr is freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_RestoreSavedOptions(
+ Tk_SavedOptions *savePtr) /* Holds saved option information; must have
+ * been passed to Tk_SetOptions. */
+{
+ int i;
+ Option *optionPtr;
+ Tcl_Obj *newPtr; /* New object value of option, which we
+ * replace with old value and free. Taken from
+ * record. */
+ char *internalPtr; /* Points to internal value of option in
+ * record. */
+ const Tk_OptionSpec *specPtr;
+
+ /*
+ * Be sure to restore the options in the opposite order they were set.
+ * This is important because it's possible that the same option name was
+ * used twice in a single call to Tk_SetOptions.
+ */
+
+ if (savePtr->nextPtr != NULL) {
+ Tk_RestoreSavedOptions(savePtr->nextPtr);
+ ckfree(savePtr->nextPtr);
+ savePtr->nextPtr = NULL;
+ }
+ for (i = savePtr->numItems - 1; i >= 0; i--) {
+ optionPtr = savePtr->items[i].optionPtr;
+ specPtr = optionPtr->specPtr;
+
+ /*
+ * First free the new value of the option, which is currently in the
+ * record.
+ */
+
+ if (specPtr->objOffset >= 0) {
+ newPtr = *((Tcl_Obj **) (savePtr->recordPtr + specPtr->objOffset));
+ } else {
+ newPtr = NULL;
+ }
+ if (specPtr->internalOffset >= 0) {
+ internalPtr = savePtr->recordPtr + specPtr->internalOffset;
+ } else {
+ internalPtr = NULL;
+ }
+ if (optionPtr->flags & OPTION_NEEDS_FREEING) {
+ FreeResources(optionPtr, newPtr, internalPtr, savePtr->tkwin);
+ }
+ if (newPtr != NULL) {
+ Tcl_DecrRefCount(newPtr);
+ }
+
+ /*
+ * Now restore the old value of the option.
+ */
+
+ if (specPtr->objOffset >= 0) {
+ *((Tcl_Obj **) (savePtr->recordPtr + specPtr->objOffset))
+ = savePtr->items[i].valuePtr;
+ }
+ if (specPtr->internalOffset >= 0) {
+ register char *ptr = (char *) &savePtr->items[i].internalForm;
+
+ CLANG_ASSERT(internalPtr);
+ switch (specPtr->type) {
+ case TK_OPTION_BOOLEAN:
+ *((int *) internalPtr) = *((int *) ptr);
+ break;
+ case TK_OPTION_INT:
+ *((int *) internalPtr) = *((int *) ptr);
+ break;
+ case TK_OPTION_DOUBLE:
+ *((double *) internalPtr) = *((double *) ptr);
+ break;
+ case TK_OPTION_STRING:
+ *((char **) internalPtr) = *((char **) ptr);
+ break;
+ case TK_OPTION_STRING_TABLE:
+ *((int *) internalPtr) = *((int *) ptr);
+ break;
+ case TK_OPTION_COLOR:
+ *((XColor **) internalPtr) = *((XColor **) ptr);
+ break;
+ case TK_OPTION_FONT:
+ *((Tk_Font *) internalPtr) = *((Tk_Font *) ptr);
+ break;
+ case TK_OPTION_STYLE:
+ *((Tk_Style *) internalPtr) = *((Tk_Style *) ptr);
+ break;
+ case TK_OPTION_BITMAP:
+ *((Pixmap *) internalPtr) = *((Pixmap *) ptr);
+ break;
+ case TK_OPTION_BORDER:
+ *((Tk_3DBorder *) internalPtr) = *((Tk_3DBorder *) ptr);
+ break;
+ case TK_OPTION_RELIEF:
+ *((int *) internalPtr) = *((int *) ptr);
+ break;
+ case TK_OPTION_CURSOR:
+ *((Tk_Cursor *) internalPtr) = *((Tk_Cursor *) ptr);
+ Tk_DefineCursor(savePtr->tkwin, *((Tk_Cursor *) internalPtr));
+ break;
+ case TK_OPTION_JUSTIFY:
+ *((Tk_Justify *) internalPtr) = *((Tk_Justify *) ptr);
+ break;
+ case TK_OPTION_ANCHOR:
+ *((Tk_Anchor *) internalPtr) = *((Tk_Anchor *) ptr);
+ break;
+ case TK_OPTION_PIXELS:
+ *((int *) internalPtr) = *((int *) ptr);
+ break;
+ case TK_OPTION_WINDOW:
+ *((Tk_Window *) internalPtr) = *((Tk_Window *) ptr);
+ break;
+ case TK_OPTION_CUSTOM: {
+ const Tk_ObjCustomOption *custom = optionPtr->extra.custom;
+
+ if (custom->restoreProc != NULL) {
+ custom->restoreProc(custom->clientData, savePtr->tkwin,
+ internalPtr, ptr);
+ }
+ break;
+ }
+ default:
+ Tcl_Panic("bad option type in Tk_RestoreSavedOptions");
+ }
+ }
+ }
+ savePtr->numItems = 0;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_FreeSavedOptions --
+ *
+ * Free all of the saved configuration option values from a previous call
+ * to Tk_SetOptions.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Storage and system resources are freed.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_FreeSavedOptions(
+ Tk_SavedOptions *savePtr) /* Contains options saved in a previous call
+ * to Tk_SetOptions. */
+{
+ int count;
+ Tk_SavedOption *savedOptionPtr;
+
+ if (savePtr->nextPtr != NULL) {
+ Tk_FreeSavedOptions(savePtr->nextPtr);
+ ckfree(savePtr->nextPtr);
+ }
+ for (count = savePtr->numItems,
+ savedOptionPtr = &savePtr->items[savePtr->numItems-1];
+ count > 0; count--, savedOptionPtr--) {
+ if (savedOptionPtr->optionPtr->flags & OPTION_NEEDS_FREEING) {
+ FreeResources(savedOptionPtr->optionPtr, savedOptionPtr->valuePtr,
+ (char *) &savedOptionPtr->internalForm, savePtr->tkwin);
+ }
+ if (savedOptionPtr->valuePtr != NULL) {
+ Tcl_DecrRefCount(savedOptionPtr->valuePtr);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_FreeConfigOptions --
+ *
+ * Free all resources associated with configuration options.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * All of the Tcl_Obj's in recordPtr that are controlled by configuration
+ * options in optionTable are freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+void
+Tk_FreeConfigOptions(
+ char *recordPtr, /* Record whose fields contain current values
+ * for options. */
+ Tk_OptionTable optionTable, /* Describes legal options. */
+ Tk_Window tkwin) /* Window associated with recordPtr; needed
+ * for freeing some options. */
+{
+ OptionTable *tablePtr;
+ Option *optionPtr;
+ int count;
+ Tcl_Obj **oldPtrPtr, *oldPtr;
+ char *oldInternalPtr;
+ const Tk_OptionSpec *specPtr;
+
+ for (tablePtr = (OptionTable *) optionTable; tablePtr != NULL;
+ tablePtr = tablePtr->nextPtr) {
+ for (optionPtr = tablePtr->options, count = tablePtr->numOptions;
+ count > 0; optionPtr++, count--) {
+ specPtr = optionPtr->specPtr;
+ if (specPtr->type == TK_OPTION_SYNONYM) {
+ continue;
+ }
+ if (specPtr->objOffset >= 0) {
+ oldPtrPtr = (Tcl_Obj **) (recordPtr + specPtr->objOffset);
+ oldPtr = *oldPtrPtr;
+ *oldPtrPtr = NULL;
+ } else {
+ oldPtr = NULL;
+ }
+ if (specPtr->internalOffset >= 0) {
+ oldInternalPtr = recordPtr + specPtr->internalOffset;
+ } else {
+ oldInternalPtr = NULL;
+ }
+ if (optionPtr->flags & OPTION_NEEDS_FREEING) {
+ FreeResources(optionPtr, oldPtr, oldInternalPtr, tkwin);
+ }
+ if (oldPtr != NULL) {
+ Tcl_DecrRefCount(oldPtr);
+ }
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeResources --
+ *
+ * Free system resources associated with a configuration option, such as
+ * colors or fonts.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Any system resources associated with objPtr are released. However,
+ * objPtr itself is not freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FreeResources(
+ Option *optionPtr, /* Description of the configuration option. */
+ Tcl_Obj *objPtr, /* The current value of the option, specified
+ * as an object. */
+ char *internalPtr, /* A pointer to an internal representation for
+ * the option's value, such as an int or
+ * (XColor *). Only valid if
+ * optionPtr->specPtr->internalOffset >= 0. */
+ Tk_Window tkwin) /* The window in which this option is used. */
+{
+ int internalFormExists;
+
+ /*
+ * If there exists an internal form for the value, use it to free
+ * resources (also zero out the internal form). If there is no internal
+ * form, then use the object form.
+ */
+
+ internalFormExists = optionPtr->specPtr->internalOffset >= 0;
+ switch (optionPtr->specPtr->type) {
+ case TK_OPTION_STRING:
+ if (internalFormExists) {
+ if (*((char **) internalPtr) != NULL) {
+ ckfree(*((char **) internalPtr));
+ *((char **) internalPtr) = NULL;
+ }
+ }
+ break;
+ case TK_OPTION_COLOR:
+ if (internalFormExists) {
+ if (*((XColor **) internalPtr) != NULL) {
+ Tk_FreeColor(*((XColor **) internalPtr));
+ *((XColor **) internalPtr) = NULL;
+ }
+ } else if (objPtr != NULL) {
+ Tk_FreeColorFromObj(tkwin, objPtr);
+ }
+ break;
+ case TK_OPTION_FONT:
+ if (internalFormExists) {
+ Tk_FreeFont(*((Tk_Font *) internalPtr));
+ *((Tk_Font *) internalPtr) = NULL;
+ } else if (objPtr != NULL) {
+ Tk_FreeFontFromObj(tkwin, objPtr);
+ }
+ break;
+ case TK_OPTION_STYLE:
+ if (internalFormExists) {
+ Tk_FreeStyle(*((Tk_Style *) internalPtr));
+ *((Tk_Style *) internalPtr) = NULL;
+ } else if (objPtr != NULL) {
+ Tk_FreeStyleFromObj(objPtr);
+ }
+ break;
+ case TK_OPTION_BITMAP:
+ if (internalFormExists) {
+ if (*((Pixmap *) internalPtr) != None) {
+ Tk_FreeBitmap(Tk_Display(tkwin), *((Pixmap *) internalPtr));
+ *((Pixmap *) internalPtr) = None;
+ }
+ } else if (objPtr != NULL) {
+ Tk_FreeBitmapFromObj(tkwin, objPtr);
+ }
+ break;
+ case TK_OPTION_BORDER:
+ if (internalFormExists) {
+ if (*((Tk_3DBorder *) internalPtr) != NULL) {
+ Tk_Free3DBorder(*((Tk_3DBorder *) internalPtr));
+ *((Tk_3DBorder *) internalPtr) = NULL;
+ }
+ } else if (objPtr != NULL) {
+ Tk_Free3DBorderFromObj(tkwin, objPtr);
+ }
+ break;
+ case TK_OPTION_CURSOR:
+ if (internalFormExists) {
+ if (*((Tk_Cursor *) internalPtr) != NULL) {
+ Tk_FreeCursor(Tk_Display(tkwin), *((Tk_Cursor *) internalPtr));
+ *((Tk_Cursor *) internalPtr) = NULL;
+ }
+ } else if (objPtr != NULL) {
+ Tk_FreeCursorFromObj(tkwin, objPtr);
+ }
+ break;
+ case TK_OPTION_CUSTOM: {
+ const Tk_ObjCustomOption *custom = optionPtr->extra.custom;
+ if (internalFormExists && custom->freeProc != NULL) {
+ custom->freeProc(custom->clientData, tkwin, internalPtr);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_GetOptionInfo --
+ *
+ * Returns a list object containing complete information about either a
+ * single option or all the configuration options in a table.
+ *
+ * Results:
+ * This function normally returns a pointer to an object. If namePtr
+ * isn't NULL, then the result object is a list with five elements: the
+ * option's name, its database name, database class, default value, and
+ * current value. If the option is a synonym then the list will contain
+ * only two values: the option name and the name of the option it refers
+ * to. If namePtr is NULL, then information is returned for every option
+ * in the option table: the result will have one sub-list (in the form
+ * described above) for each option in the table. If an error occurs
+ * (e.g. because namePtr isn't valid) then NULL is returned and an error
+ * message will be left in interp's result unless interp is NULL.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+Tcl_Obj *
+Tk_GetOptionInfo(
+ Tcl_Interp *interp, /* Interpreter for error reporting. If NULL,
+ * then no error message is created. */
+ char *recordPtr, /* Record whose fields contain current values
+ * for options. */
+ Tk_OptionTable optionTable, /* Describes all the legal options. */
+ Tcl_Obj *namePtr, /* If non-NULL, the string value selects a
+ * single option whose info is to be returned.
+ * Otherwise info is returned for all options
+ * in optionTable. */
+ Tk_Window tkwin) /* Window associated with recordPtr; needed to
+ * compute correct default value for some
+ * options. */
+{
+ Tcl_Obj *resultPtr;
+ OptionTable *tablePtr = (OptionTable *) optionTable;
+ Option *optionPtr;
+ int count;
+
+ /*
+ * If information is only wanted for a single configuration spec, then
+ * handle that one spec specially.
+ */
+
+ if (namePtr != NULL) {
+ optionPtr = GetOptionFromObj(interp, namePtr, tablePtr);
+ if (optionPtr == NULL) {
+ return NULL;
+ }
+ if (optionPtr->specPtr->type == TK_OPTION_SYNONYM) {
+ optionPtr = optionPtr->extra.synonymPtr;
+ }
+ return GetConfigList(recordPtr, optionPtr, tkwin);
+ }
+
+ /*
+ * Loop through all the specs, creating a big list with all their
+ * information.
+ */
+
+ resultPtr = Tcl_NewListObj(0, NULL);
+ for (; tablePtr != NULL; tablePtr = tablePtr->nextPtr) {
+ for (optionPtr = tablePtr->options, count = tablePtr->numOptions;
+ count > 0; optionPtr++, count--) {
+ Tcl_ListObjAppendElement(interp, resultPtr,
+ GetConfigList(recordPtr, optionPtr, tkwin));
+ }
+ }
+ return resultPtr;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * GetConfigList --
+ *
+ * Create a valid Tcl list holding the configuration information for a
+ * single configuration option.
+ *
+ * Results:
+ * A Tcl list, dynamically allocated. The caller is expected to arrange
+ * for this list to be freed eventually.
+ *
+ * Side effects:
+ * Memory is allocated.
+ *
+ *--------------------------------------------------------------
+ */
+
+static Tcl_Obj *
+GetConfigList(
+ char *recordPtr, /* Pointer to record holding current values of
+ * configuration options. */
+ Option *optionPtr, /* Pointer to information describing a
+ * particular option. */
+ Tk_Window tkwin) /* Window corresponding to recordPtr. */
+{
+ Tcl_Obj *listPtr, *elementPtr;
+
+ listPtr = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(NULL, listPtr,
+ Tcl_NewStringObj(optionPtr->specPtr->optionName, -1));
+
+ if (optionPtr->specPtr->type == TK_OPTION_SYNONYM) {
+ elementPtr = Tcl_NewStringObj(
+ optionPtr->extra.synonymPtr->specPtr->optionName, -1);
+ Tcl_ListObjAppendElement(NULL, listPtr, elementPtr);
+ } else {
+ if (optionPtr->dbNameUID == NULL) {
+ elementPtr = Tcl_NewObj();
+ } else {
+ elementPtr = Tcl_NewStringObj(optionPtr->dbNameUID, -1);
+ }
+ Tcl_ListObjAppendElement(NULL, listPtr, elementPtr);
+
+ if (optionPtr->dbClassUID == NULL) {
+ elementPtr = Tcl_NewObj();
+ } else {
+ elementPtr = Tcl_NewStringObj(optionPtr->dbClassUID, -1);
+ }
+ Tcl_ListObjAppendElement(NULL, listPtr, elementPtr);
+
+ if ((tkwin != NULL) && ((optionPtr->specPtr->type == TK_OPTION_COLOR)
+ || (optionPtr->specPtr->type == TK_OPTION_BORDER))
+ && (Tk_Depth(tkwin) <= 1)
+ && (optionPtr->extra.monoColorPtr != NULL)) {
+ elementPtr = optionPtr->extra.monoColorPtr;
+ } else if (optionPtr->defaultPtr != NULL) {
+ elementPtr = optionPtr->defaultPtr;
+ } else {
+ elementPtr = Tcl_NewObj();
+ }
+ Tcl_ListObjAppendElement(NULL, listPtr, elementPtr);
+
+ if (optionPtr->specPtr->objOffset >= 0) {
+ elementPtr = *((Tcl_Obj **) (recordPtr
+ + optionPtr->specPtr->objOffset));
+ if (elementPtr == NULL) {
+ elementPtr = Tcl_NewObj();
+ }
+ } else {
+ elementPtr = GetObjectForOption(recordPtr, optionPtr, tkwin);
+ }
+ Tcl_ListObjAppendElement(NULL, listPtr, elementPtr);
+ }
+ return listPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetObjectForOption --
+ *
+ * This function is called to create an object that contains the value
+ * for an option. It is invoked by GetConfigList and Tk_GetOptionValue
+ * when only the internal form of an option is stored in the record.
+ *
+ * Results:
+ * The return value is a pointer to a Tcl object. The caller must call
+ * Tcl_IncrRefCount on this object to preserve it.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj *
+GetObjectForOption(
+ char *recordPtr, /* Pointer to record holding current values of
+ * configuration options. */
+ Option *optionPtr, /* Pointer to information describing an option
+ * whose internal value is stored in
+ * *recordPtr. */
+ Tk_Window tkwin) /* Window corresponding to recordPtr. */
+{
+ Tcl_Obj *objPtr;
+ char *internalPtr; /* Points to internal value of option in
+ * record. */
+
+ internalPtr = recordPtr + optionPtr->specPtr->internalOffset;
+ objPtr = NULL;
+ switch (optionPtr->specPtr->type) {
+ case TK_OPTION_BOOLEAN:
+ objPtr = Tcl_NewIntObj(*((int *) internalPtr));
+ break;
+ case TK_OPTION_INT:
+ objPtr = Tcl_NewIntObj(*((int *) internalPtr));
+ break;
+ case TK_OPTION_DOUBLE:
+ objPtr = Tcl_NewDoubleObj(*((double *) internalPtr));
+ break;
+ case TK_OPTION_STRING:
+ objPtr = Tcl_NewStringObj(*((char **) internalPtr), -1);
+ break;
+ case TK_OPTION_STRING_TABLE:
+ objPtr = Tcl_NewStringObj(((char **) optionPtr->specPtr->clientData)[
+ *((int *) internalPtr)], -1);
+ break;
+ case TK_OPTION_COLOR: {
+ XColor *colorPtr = *((XColor **) internalPtr);
+
+ if (colorPtr != NULL) {
+ objPtr = Tcl_NewStringObj(Tk_NameOfColor(colorPtr), -1);
+ }
+ break;
+ }
+ case TK_OPTION_FONT: {
+ Tk_Font tkfont = *((Tk_Font *) internalPtr);
+
+ if (tkfont != NULL) {
+ objPtr = Tcl_NewStringObj(Tk_NameOfFont(tkfont), -1);
+ }
+ break;
+ }
+ case TK_OPTION_STYLE: {
+ Tk_Style style = *((Tk_Style *) internalPtr);
+
+ if (style != NULL) {
+ objPtr = Tcl_NewStringObj(Tk_NameOfStyle(style), -1);
+ }
+ break;
+ }
+ case TK_OPTION_BITMAP: {
+ Pixmap pixmap = *((Pixmap *) internalPtr);
+
+ if (pixmap != None) {
+ objPtr = Tcl_NewStringObj(
+ Tk_NameOfBitmap(Tk_Display(tkwin), pixmap), -1);
+ }
+ break;
+ }
+ case TK_OPTION_BORDER: {
+ Tk_3DBorder border = *((Tk_3DBorder *) internalPtr);
+
+ if (border != NULL) {
+ objPtr = Tcl_NewStringObj(Tk_NameOf3DBorder(border), -1);
+ }
+ break;
+ }
+ case TK_OPTION_RELIEF:
+ objPtr = Tcl_NewStringObj(Tk_NameOfRelief(*((int *) internalPtr)), -1);
+ break;
+ case TK_OPTION_CURSOR: {
+ Tk_Cursor cursor = *((Tk_Cursor *) internalPtr);
+
+ if (cursor != NULL) {
+ objPtr = Tcl_NewStringObj(
+ Tk_NameOfCursor(Tk_Display(tkwin), cursor), -1);
+ }
+ break;
+ }
+ case TK_OPTION_JUSTIFY:
+ objPtr = Tcl_NewStringObj(Tk_NameOfJustify(
+ *((Tk_Justify *) internalPtr)), -1);
+ break;
+ case TK_OPTION_ANCHOR:
+ objPtr = Tcl_NewStringObj(Tk_NameOfAnchor(
+ *((Tk_Anchor *) internalPtr)), -1);
+ break;
+ case TK_OPTION_PIXELS:
+ objPtr = Tcl_NewIntObj(*((int *) internalPtr));
+ break;
+ case TK_OPTION_WINDOW: {
+ Tk_Window tkwin = *((Tk_Window *) internalPtr);
+
+ if (tkwin != NULL) {
+ objPtr = Tcl_NewStringObj(Tk_PathName(tkwin), -1);
+ }
+ break;
+ }
+ case TK_OPTION_CUSTOM: {
+ const Tk_ObjCustomOption *custom = optionPtr->extra.custom;
+
+ objPtr = custom->getProc(custom->clientData, tkwin, recordPtr,
+ optionPtr->specPtr->internalOffset);
+ break;
+ }
+ default:
+ Tcl_Panic("bad option type in GetObjectForOption");
+ }
+ if (objPtr == NULL) {
+ objPtr = Tcl_NewObj();
+ }
+ return objPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetOptionValue --
+ *
+ * This function returns the current value of a configuration option.
+ *
+ * Results:
+ * The return value is the object holding the current value of the option
+ * given by namePtr. If no such option exists, then the return value is
+ * NULL and an error message is left in interp's result (if interp isn't
+ * NULL).
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+Tk_GetOptionValue(
+ Tcl_Interp *interp, /* Interpreter for error reporting. If NULL
+ * then no messages are provided for
+ * errors. */
+ char *recordPtr, /* Record whose fields contain current values
+ * for options. */
+ Tk_OptionTable optionTable, /* Describes legal options. */
+ Tcl_Obj *namePtr, /* Gives the command-line name for the option
+ * whose value is to be returned. */
+ Tk_Window tkwin) /* Window corresponding to recordPtr. */
+{
+ OptionTable *tablePtr = (OptionTable *) optionTable;
+ Option *optionPtr;
+ Tcl_Obj *resultPtr;
+
+ optionPtr = GetOptionFromObj(interp, namePtr, tablePtr);
+ if (optionPtr == NULL) {
+ return NULL;
+ }
+ if (optionPtr->specPtr->type == TK_OPTION_SYNONYM) {
+ optionPtr = optionPtr->extra.synonymPtr;
+ }
+ if (optionPtr->specPtr->objOffset >= 0) {
+ resultPtr = *((Tcl_Obj **) (recordPtr+optionPtr->specPtr->objOffset));
+ if (resultPtr == NULL) {
+ /*
+ * This option has a null value and is represented by a null
+ * object pointer. We can't return the null pointer, since that
+ * would indicate an error. Instead, return a new empty object.
+ */
+
+ resultPtr = Tcl_NewObj();
+ }
+ } else {
+ resultPtr = GetObjectForOption(recordPtr, optionPtr, tkwin);
+ }
+ return resultPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkDebugConfig --
+ *
+ * This is a debugging function that returns information about one of the
+ * configuration tables that currently exists for an interpreter.
+ *
+ * Results:
+ * If the specified table exists in the given interpreter, then a list is
+ * returned describing the table and any other tables that it chains to:
+ * for each table there will be three list elements giving the reference
+ * count for the table, the number of elements in the table, and the
+ * command-line name for the first option in the table. If the table
+ * doesn't exist in the interpreter then an empty object is returned.
+ * The reference count for the returned object is 0.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TkDebugConfig(
+ Tcl_Interp *interp, /* Interpreter in which the table is
+ * defined. */
+ Tk_OptionTable table) /* Table about which information is to be
+ * returned. May not necessarily exist in the
+ * interpreter anymore. */
+{
+ OptionTable *tablePtr = (OptionTable *) table;
+ Tcl_HashEntry *hashEntryPtr;
+ Tcl_HashSearch search;
+ Tcl_Obj *objPtr;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ objPtr = Tcl_NewObj();
+ if (!tablePtr || !tsdPtr->initialized) {
+ return objPtr;
+ }
+
+ /*
+ * Scan all the tables for this interpreter to make sure that the one we
+ * want still is valid.
+ */
+
+ for (hashEntryPtr = Tcl_FirstHashEntry(&tsdPtr->hashTable, &search);
+ hashEntryPtr != NULL;
+ hashEntryPtr = Tcl_NextHashEntry(&search)) {
+ if (tablePtr == (OptionTable *) Tcl_GetHashValue(hashEntryPtr)) {
+ for ( ; tablePtr != NULL; tablePtr = tablePtr->nextPtr) {
+ Tcl_ListObjAppendElement(NULL, objPtr,
+ Tcl_NewIntObj(tablePtr->refCount));
+ Tcl_ListObjAppendElement(NULL, objPtr,
+ Tcl_NewIntObj(tablePtr->numOptions));
+ Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewStringObj(
+ tablePtr->options[0].specPtr->optionName, -1));
+ }
+ break;
+ }
+ }
+ return objPtr;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkConsole.c b/tk8.6/generic/tkConsole.c
new file mode 100644
index 0000000..a6a8cbf
--- /dev/null
+++ b/tk8.6/generic/tkConsole.c
@@ -0,0 +1,968 @@
+/*
+ * tkConsole.c --
+ *
+ * This file implements a Tcl console for systems that may not otherwise
+ * have access to a console. It uses the Text widget and provides special
+ * access via a console command.
+ *
+ * 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.
+ */
+
+#include "tkInt.h"
+
+/*
+ * Each console is associated with an instance of the ConsoleInfo struct.
+ * It keeps track of what interp holds the Tk application that displays
+ * the console, and what interp is controlled by the interactions in that
+ * console. A refCount permits the struct to be shared as instance data
+ * by commands and by channels.
+ */
+
+typedef struct ConsoleInfo {
+ Tcl_Interp *consoleInterp; /* Interpreter displaying the console. */
+ Tcl_Interp *interp; /* Interpreter controlled by console. */
+ int refCount;
+} ConsoleInfo;
+
+/*
+ * Each console channel holds an instance of the ChannelData struct as
+ * its instance data. It contains ConsoleInfo, so the channel can work
+ * with the appropriate console window, and a type value to distinguish
+ * the stdout channel from the stderr channel.
+ */
+
+typedef struct ChannelData {
+ ConsoleInfo *info;
+ int type; /* TCL_STDOUT or TCL_STDERR */
+} ChannelData;
+
+/*
+ * Prototypes for local procedures defined in this file:
+ */
+
+static int ConsoleClose(ClientData instanceData, Tcl_Interp *interp);
+static void ConsoleDeleteProc(ClientData clientData);
+static void ConsoleEventProc(ClientData clientData, XEvent *eventPtr);
+static int ConsoleHandle(ClientData instanceData, int direction,
+ ClientData *handlePtr);
+static int ConsoleInput(ClientData instanceData, char *buf, int toRead,
+ int *errorCode);
+static int ConsoleObjCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int ConsoleOutput(ClientData instanceData, const char *buf,
+ int toWrite, int *errorCode);
+static void ConsoleWatch(ClientData instanceData, int mask);
+static void DeleteConsoleInterp(ClientData clientData);
+static void InterpDeleteProc(ClientData clientData, Tcl_Interp *interp);
+static int InterpreterObjCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+
+/*
+ * This structure describes the channel type structure for file based IO:
+ */
+
+static const Tcl_ChannelType consoleChannelType = {
+ "console", /* Type name. */
+ TCL_CHANNEL_VERSION_4, /* v4 channel */
+ ConsoleClose, /* Close proc. */
+ ConsoleInput, /* Input proc. */
+ ConsoleOutput, /* Output proc. */
+ NULL, /* Seek proc. */
+ NULL, /* Set option proc. */
+ NULL, /* Get option proc. */
+ ConsoleWatch, /* Watch for events on console. */
+ ConsoleHandle, /* Get a handle from the device. */
+ NULL, /* close2proc. */
+ NULL, /* Always non-blocking.*/
+ NULL, /* flush proc. */
+ NULL, /* handler proc. */
+ NULL, /* wide seek proc */
+ NULL, /* thread action proc */
+ NULL
+};
+
+#ifdef _WIN32
+#include <windows.h>
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ShouldUseConsoleChannel
+ *
+ * Check to see if console window should be used for a given standard
+ * channel.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Creates the console channel and installs it as the standard channels.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ShouldUseConsoleChannel(
+ int type)
+{
+ DWORD handleId; /* Standard handle to retrieve. */
+ DCB dcb;
+ DWORD consoleParams;
+ DWORD fileType;
+ HANDLE handle;
+
+ switch (type) {
+ case TCL_STDIN:
+ handleId = STD_INPUT_HANDLE;
+ break;
+ case TCL_STDOUT:
+ handleId = STD_OUTPUT_HANDLE;
+ break;
+ case TCL_STDERR:
+ handleId = STD_ERROR_HANDLE;
+ break;
+ default:
+ return 0;
+ break;
+ }
+
+ handle = GetStdHandle(handleId);
+
+ /*
+ * Note that we need to check for 0 because Windows will return 0 if this
+ * is not a console mode application, even though this is not a valid
+ * handle.
+ */
+
+ if ((handle == INVALID_HANDLE_VALUE) || (handle == 0)) {
+ return 1;
+ }
+
+ /*
+ * Win2K BUG: GetStdHandle(STD_OUTPUT_HANDLE) can return what appears to
+ * be a valid handle. See TclpGetDefaultStdChannel() for this change
+ * implemented. We didn't change it here because GetFileType() [below]
+ * will catch this with FILE_TYPE_UNKNOWN and appropriately return a value
+ * of 1, anyways.
+ *
+ * char dummyBuff[1];
+ * DWORD dummyWritten;
+ *
+ * if ((type == TCL_STDOUT)
+ * && !WriteFile(handle, dummyBuff, 0, &dummyWritten, NULL)) {
+ * return 1;
+ * }
+ */
+
+ fileType = GetFileType(handle);
+
+ /*
+ * If the file is a character device, we need to try to figure out whether
+ * it is a serial port, a console, or something else. We test for the
+ * console case first because this is more common.
+ */
+
+ if (fileType == FILE_TYPE_CHAR) {
+ dcb.DCBlength = sizeof(DCB);
+ if (!GetConsoleMode(handle, &consoleParams) &&
+ !GetCommState(handle, &dcb)) {
+ /*
+ * Don't use a CHAR type channel for stdio, otherwise Tk runs into
+ * trouble with the MS DevStudio debugger.
+ */
+
+ return 1;
+ }
+ } else if (fileType == FILE_TYPE_UNKNOWN) {
+ return 1;
+ } else if (Tcl_GetStdChannel(type) == NULL) {
+ return 1;
+ }
+
+ return 0;
+}
+#else
+/*
+ * Mac should always use a console channel, Unix should if it's trying to
+ */
+
+#define ShouldUseConsoleChannel(chan) (1)
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_InitConsoleChannels --
+ *
+ * Create the console channels and install them as the standard channels.
+ * All I/O will be discarded until Tk_CreateConsoleWindow is called to
+ * attach the console to a text widget.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Creates the console channel and installs it as the standard channels.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_InitConsoleChannels(
+ Tcl_Interp *interp)
+{
+ static Tcl_ThreadDataKey consoleInitKey;
+ int *consoleInitPtr, doIn, doOut, doErr;
+ ConsoleInfo *info;
+ Tcl_Channel consoleChannel;
+
+ /*
+ * Ensure that we are getting a compatible version of Tcl.
+ */
+
+ if (Tcl_InitStubs(interp, "8.6", 0) == NULL) {
+ return;
+ }
+
+ consoleInitPtr = Tcl_GetThreadData(&consoleInitKey, (int) sizeof(int));
+ if (*consoleInitPtr) {
+ /*
+ * We've already initialized console channels in this thread.
+ */
+
+ return;
+ }
+ *consoleInitPtr = 1;
+
+ doIn = ShouldUseConsoleChannel(TCL_STDIN);
+ doOut = ShouldUseConsoleChannel(TCL_STDOUT);
+ doErr = ShouldUseConsoleChannel(TCL_STDERR);
+
+ if (!(doIn || doOut || doErr)) {
+ /*
+ * No std channels should be tied to the console; thus, no need to
+ * create the console.
+ */
+
+ return;
+ }
+
+ /*
+ * At least one std channel wants to be tied to the console, so create the
+ * interp for it to live in.
+ */
+
+ info = ckalloc(sizeof(ConsoleInfo));
+ info->consoleInterp = NULL;
+ info->interp = NULL;
+ info->refCount = 0;
+
+ if (doIn) {
+ ChannelData *data = ckalloc(sizeof(ChannelData));
+
+ data->info = info;
+ data->info->refCount++;
+ data->type = TCL_STDIN;
+ consoleChannel = Tcl_CreateChannel(&consoleChannelType, "console0",
+ data, TCL_READABLE);
+ if (consoleChannel != NULL) {
+ Tcl_SetChannelOption(NULL, consoleChannel, "-translation", "lf");
+ Tcl_SetChannelOption(NULL, consoleChannel, "-buffering", "none");
+ Tcl_SetChannelOption(NULL, consoleChannel, "-encoding", "utf-8");
+ }
+ Tcl_SetStdChannel(consoleChannel, TCL_STDIN);
+ Tcl_RegisterChannel(NULL, consoleChannel);
+ }
+
+ if (doOut) {
+ ChannelData *data = ckalloc(sizeof(ChannelData));
+
+ data->info = info;
+ data->info->refCount++;
+ data->type = TCL_STDOUT;
+ consoleChannel = Tcl_CreateChannel(&consoleChannelType, "console1",
+ data, TCL_WRITABLE);
+ if (consoleChannel != NULL) {
+ Tcl_SetChannelOption(NULL, consoleChannel, "-translation", "lf");
+ Tcl_SetChannelOption(NULL, consoleChannel, "-buffering", "none");
+ Tcl_SetChannelOption(NULL, consoleChannel, "-encoding", "utf-8");
+ }
+ Tcl_SetStdChannel(consoleChannel, TCL_STDOUT);
+ Tcl_RegisterChannel(NULL, consoleChannel);
+ }
+
+ if (doErr) {
+ ChannelData *data = ckalloc(sizeof(ChannelData));
+
+ data->info = info;
+ data->info->refCount++;
+ data->type = TCL_STDERR;
+ consoleChannel = Tcl_CreateChannel(&consoleChannelType, "console2",
+ data, TCL_WRITABLE);
+ if (consoleChannel != NULL) {
+ Tcl_SetChannelOption(NULL, consoleChannel, "-translation", "lf");
+ Tcl_SetChannelOption(NULL, consoleChannel, "-buffering", "none");
+ Tcl_SetChannelOption(NULL, consoleChannel, "-encoding", "utf-8");
+ }
+ Tcl_SetStdChannel(consoleChannel, TCL_STDERR);
+ Tcl_RegisterChannel(NULL, consoleChannel);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_CreateConsoleWindow --
+ *
+ * Initialize the console. This code actually creates a new application
+ * and associated interpreter. This effectively hides the implementation
+ * from the main application.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A new console it created.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_CreateConsoleWindow(
+ Tcl_Interp *interp) /* Interpreter to use for prompting. */
+{
+ Tcl_Channel chan;
+ ConsoleInfo *info;
+ Tk_Window mainWindow;
+ Tcl_Command token;
+ int result = TCL_OK;
+ int haveConsoleChannel = 1;
+
+ /* Init an interp with Tcl and Tk */
+ Tcl_Interp *consoleInterp = Tcl_CreateInterp();
+ if (Tcl_Init(consoleInterp) != TCL_OK) {
+ Tcl_Obj *result_obj = Tcl_GetObjResult(consoleInterp);
+ Tcl_SetObjResult(interp, result_obj);
+ goto error;
+ }
+ if (Tk_Init(consoleInterp) != TCL_OK) {
+ Tcl_Obj *result_obj = Tcl_GetObjResult(consoleInterp);
+ Tcl_SetObjResult(interp, result_obj);
+ goto error;
+ }
+
+ /*
+ * Fetch the instance data from whatever std channel is a
+ * console channel. If none, create fresh instance data.
+ */
+
+ if (Tcl_GetChannelType(chan = Tcl_GetStdChannel(TCL_STDIN))
+ == &consoleChannelType) {
+ } else if (Tcl_GetChannelType(chan = Tcl_GetStdChannel(TCL_STDOUT))
+ == &consoleChannelType) {
+ } else if (Tcl_GetChannelType(chan = Tcl_GetStdChannel(TCL_STDERR))
+ == &consoleChannelType) {
+ } else {
+ haveConsoleChannel = 0;
+ }
+
+ if (haveConsoleChannel) {
+ ChannelData *data = (ChannelData *) Tcl_GetChannelInstanceData(chan);
+ info = data->info;
+ if (info->consoleInterp) {
+ /*
+ * New ConsoleInfo for a new console window.
+ */
+
+ info = ckalloc(sizeof(ConsoleInfo));
+ info->refCount = 0;
+
+ /*
+ * Update any console channels to make use of the new console.
+ */
+
+ if (Tcl_GetChannelType(chan = Tcl_GetStdChannel(TCL_STDIN))
+ == &consoleChannelType) {
+ data = (ChannelData *) Tcl_GetChannelInstanceData(chan);
+ data->info->refCount--;
+ data->info = info;
+ data->info->refCount++;
+ }
+ if (Tcl_GetChannelType(chan = Tcl_GetStdChannel(TCL_STDOUT))
+ == &consoleChannelType) {
+ data = (ChannelData *) Tcl_GetChannelInstanceData(chan);
+ data->info->refCount--;
+ data->info = info;
+ data->info->refCount++;
+ }
+ if (Tcl_GetChannelType(chan = Tcl_GetStdChannel(TCL_STDERR))
+ == &consoleChannelType) {
+ data = (ChannelData *) Tcl_GetChannelInstanceData(chan);
+ data->info->refCount--;
+ data->info = info;
+ data->info->refCount++;
+ }
+ }
+ } else {
+ info = ckalloc(sizeof(ConsoleInfo));
+ info->refCount = 0;
+ }
+
+ info->consoleInterp = consoleInterp;
+ info->interp = interp;
+
+ Tcl_CallWhenDeleted(consoleInterp, InterpDeleteProc, info);
+ info->refCount++;
+ Tcl_CreateThreadExitHandler(DeleteConsoleInterp, consoleInterp);
+
+ /*
+ * Add console commands to the interp
+ */
+
+ token = Tcl_CreateObjCommand(interp, "console", ConsoleObjCmd, info,
+ ConsoleDeleteProc);
+ info->refCount++;
+
+ /*
+ * We don't have to count the ref held by the [consoleinterp] command
+ * in the consoleInterp. The ref held by the consoleInterp delete
+ * handler takes care of us.
+ */
+ Tcl_CreateObjCommand(consoleInterp, "consoleinterp", InterpreterObjCmd,
+ info, NULL);
+
+ mainWindow = Tk_MainWindow(interp);
+ if (mainWindow) {
+ Tk_CreateEventHandler(mainWindow, StructureNotifyMask,
+ ConsoleEventProc, info);
+ info->refCount++;
+ }
+
+ Tcl_Preserve(consoleInterp);
+ result = Tcl_EvalEx(consoleInterp, "source $tk_library/console.tcl",
+ -1, TCL_EVAL_GLOBAL);
+ if (result == TCL_ERROR) {
+ Tcl_SetReturnOptions(interp,
+ Tcl_GetReturnOptions(consoleInterp, result));
+ Tcl_SetObjResult(interp, Tcl_GetObjResult(consoleInterp));
+ }
+ Tcl_Release(consoleInterp);
+ if (result == TCL_ERROR) {
+ Tcl_DeleteCommandFromToken(interp, token);
+ mainWindow = Tk_MainWindow(interp);
+ if (mainWindow) {
+ Tk_DeleteEventHandler(mainWindow, StructureNotifyMask,
+ ConsoleEventProc, info);
+ if (--info->refCount <= 0) {
+ ckfree(info);
+ }
+ }
+ goto error;
+ }
+ return TCL_OK;
+
+ error:
+ Tcl_AddErrorInfo(interp, "\n (creating console window)");
+ if (!Tcl_InterpDeleted(consoleInterp)) {
+ Tcl_DeleteInterp(consoleInterp);
+ }
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConsoleOutput--
+ *
+ * Writes the given output on the IO channel. Returns count of how many
+ * characters were actually written, and an error indication.
+ *
+ * Results:
+ * A count of how many characters were written is returned and an error
+ * indication is returned in an output argument.
+ *
+ * Side effects:
+ * Writes output on the actual channel.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ConsoleOutput(
+ ClientData instanceData, /* Indicates which device to use. */
+ const char *buf, /* The data buffer. */
+ int toWrite, /* How many bytes to write? */
+ int *errorCode) /* Where to store error code. */
+{
+ ChannelData *data = instanceData;
+ ConsoleInfo *info = data->info;
+
+ *errorCode = 0;
+ Tcl_SetErrno(0);
+
+ if (info) {
+ Tcl_Interp *consoleInterp = info->consoleInterp;
+
+ if (consoleInterp && !Tcl_InterpDeleted(consoleInterp)) {
+ Tcl_DString ds;
+ Tcl_Encoding utf8 = Tcl_GetEncoding(NULL, "utf-8");
+
+ /*
+ * Not checking for utf8 == NULL. Did not check for TCL_ERROR
+ * from Tcl_SetChannelOption() in Tk_InitConsoleChannels() either.
+ * Assumption is utf-8 Tcl_Encoding is reliably present.
+ */
+
+ const char *bytes
+ = Tcl_ExternalToUtfDString(utf8, buf, toWrite, &ds);
+ int numBytes = Tcl_DStringLength(&ds);
+ Tcl_Obj *cmd = Tcl_NewStringObj("tk::ConsoleOutput", -1);
+
+ Tcl_FreeEncoding(utf8);
+
+ if (data->type == TCL_STDERR) {
+ Tcl_ListObjAppendElement(NULL, cmd,
+ Tcl_NewStringObj("stderr", -1));
+ } else {
+ Tcl_ListObjAppendElement(NULL, cmd,
+ Tcl_NewStringObj("stdout", -1));
+ }
+ Tcl_ListObjAppendElement(NULL, cmd,
+ Tcl_NewStringObj(bytes, numBytes));
+
+ Tcl_DStringFree(&ds);
+ Tcl_IncrRefCount(cmd);
+ Tcl_EvalObjEx(consoleInterp, cmd, TCL_EVAL_GLOBAL);
+ Tcl_DecrRefCount(cmd);
+ }
+ }
+ return toWrite;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConsoleInput --
+ *
+ * Read input from the console. Not currently implemented.
+ *
+ * Results:
+ * Always returns EOF.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+ConsoleInput(
+ ClientData instanceData, /* Unused. */
+ char *buf, /* Where to store data read. */
+ int bufSize, /* How much space is available in the
+ * buffer? */
+ int *errorCode) /* Where to store error code. */
+{
+ return 0; /* Always return EOF. */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConsoleClose --
+ *
+ * Closes the IO channel.
+ *
+ * Results:
+ * Always returns 0 (success).
+ *
+ * Side effects:
+ * Frees the dummy file associated with the channel.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+ConsoleClose(
+ ClientData instanceData, /* Unused. */
+ Tcl_Interp *interp) /* Unused. */
+{
+ ChannelData *data = instanceData;
+ ConsoleInfo *info = data->info;
+
+ if (info) {
+ if (--info->refCount <= 0) {
+ /*
+ * Assuming the Tcl_Interp * fields must already be NULL.
+ */
+
+ ckfree(info);
+ }
+ }
+ ckfree(data);
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConsoleWatch --
+ *
+ * Called by the notifier to set up the console device so that events
+ * will be noticed. Since there are no events on the console, this
+ * routine just returns without doing anything.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static void
+ConsoleWatch(
+ ClientData instanceData, /* Device ID for the channel. */
+ int mask) /* OR-ed combination of TCL_READABLE,
+ * TCL_WRITABLE and TCL_EXCEPTION, for the
+ * events we are interested in. */
+{
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConsoleHandle --
+ *
+ * Invoked by the generic IO layer to get a handle from a channel.
+ * Because console channels are not devices, this function always fails.
+ *
+ * Results:
+ * Always returns TCL_ERROR.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+ConsoleHandle(
+ ClientData instanceData, /* Device ID for the channel. */
+ int direction, /* TCL_READABLE or TCL_WRITABLE to indicate
+ * which direction of the channel is being
+ * requested. */
+ ClientData *handlePtr) /* Where to store handle */
+{
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConsoleObjCmd --
+ *
+ * The console command implements a Tcl interface to the various console
+ * options.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ConsoleObjCmd(
+ ClientData clientData, /* Access to the console interp */
+ Tcl_Interp *interp, /* Current interpreter */
+ int objc, /* Number of arguments */
+ Tcl_Obj *const objv[]) /* Argument objects */
+{
+ int index, result;
+ static const char *const options[] = {
+ "eval", "hide", "show", "title", NULL};
+ enum option {CON_EVAL, CON_HIDE, CON_SHOW, CON_TITLE};
+ Tcl_Obj *cmd = NULL;
+ ConsoleInfo *info = clientData;
+ Tcl_Interp *consoleInterp = info->consoleInterp;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObjStruct(interp, objv[1], options,
+ sizeof(char *), "option", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch ((enum option) index) {
+ case CON_EVAL:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "script");
+ return TCL_ERROR;
+ }
+ cmd = objv[2];
+ break;
+ case CON_HIDE:
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ return TCL_ERROR;
+ }
+ cmd = Tcl_NewStringObj("wm withdraw .", -1);
+ break;
+ case CON_SHOW:
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ return TCL_ERROR;
+ }
+ cmd = Tcl_NewStringObj("wm deiconify .", -1);
+ break;
+ case CON_TITLE:
+ if (objc > 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?title?");
+ return TCL_ERROR;
+ }
+ cmd = Tcl_NewStringObj("wm title .", -1);
+ if (objc == 3) {
+ Tcl_ListObjAppendElement(NULL, cmd, objv[2]);
+ }
+ break;
+ default:
+ CLANG_ASSERT(0);
+ }
+
+ Tcl_IncrRefCount(cmd);
+ if (consoleInterp && !Tcl_InterpDeleted(consoleInterp)) {
+ Tcl_Preserve(consoleInterp);
+ result = Tcl_EvalObjEx(consoleInterp, cmd, TCL_EVAL_GLOBAL);
+ Tcl_SetReturnOptions(interp,
+ Tcl_GetReturnOptions(consoleInterp, result));
+ Tcl_SetObjResult(interp, Tcl_GetObjResult(consoleInterp));
+ Tcl_Release(consoleInterp);
+ } else {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "no active console interp", -1));
+ Tcl_SetErrorCode(interp, "TK", "CONSOLE", "NONE", NULL);
+ result = TCL_ERROR;
+ }
+ Tcl_DecrRefCount(cmd);
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InterpreterObjCmd --
+ *
+ * This command allows the console interp to communicate with the main
+ * interpreter.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+InterpreterObjCmd(
+ ClientData clientData, /* */
+ Tcl_Interp *interp, /* Current interpreter */
+ int objc, /* Number of arguments */
+ Tcl_Obj *const objv[]) /* Argument objects */
+{
+ int index, result = TCL_OK;
+ static const char *const options[] = {"eval", "record", NULL};
+ enum option {OTHER_EVAL, OTHER_RECORD};
+ ConsoleInfo *info = clientData;
+ Tcl_Interp *otherInterp = info->interp;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option arg");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObjStruct(interp, objv[1], options,
+ sizeof(char *), "option", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "script");
+ return TCL_ERROR;
+ }
+
+ if ((otherInterp == NULL) || Tcl_InterpDeleted(otherInterp)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "no active master interp", -1));
+ Tcl_SetErrorCode(interp, "TK", "CONSOLE", "NO_INTERP", NULL);
+ return TCL_ERROR;
+ }
+
+ Tcl_Preserve(otherInterp);
+ switch ((enum option) index) {
+ case OTHER_EVAL:
+ result = Tcl_EvalObjEx(otherInterp, objv[2], TCL_EVAL_GLOBAL);
+
+ /*
+ * TODO: Should exceptions be filtered here?
+ */
+
+ Tcl_SetReturnOptions(interp,
+ Tcl_GetReturnOptions(otherInterp, result));
+ Tcl_SetObjResult(interp, Tcl_GetObjResult(otherInterp));
+ break;
+ case OTHER_RECORD:
+ Tcl_RecordAndEvalObj(otherInterp, objv[2], TCL_EVAL_GLOBAL);
+
+ /*
+ * By not setting result, we discard any exceptions or errors here and
+ * always return TCL_OK. All the caller wants is the interp result to
+ * display, whether that's result or error message.
+ */
+
+ Tcl_SetObjResult(interp, Tcl_GetObjResult(otherInterp));
+ break;
+ }
+ Tcl_Release(otherInterp);
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DeleteConsoleInterp --
+ *
+ * Thread exit handler to destroy a console interp when the thread it
+ * lives in gets torn down.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DeleteConsoleInterp(
+ ClientData clientData)
+{
+ Tcl_Interp *interp = clientData;
+
+ Tcl_DeleteInterp(interp);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InterpDeleteProc --
+ *
+ * React when the interp in which the console is displayed is deleted for
+ * any reason.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A new console it created.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+InterpDeleteProc(
+ ClientData clientData,
+ Tcl_Interp *interp)
+{
+ ConsoleInfo *info = clientData;
+
+ if (info->consoleInterp == interp) {
+ Tcl_DeleteThreadExitHandler(DeleteConsoleInterp, info->consoleInterp);
+ info->consoleInterp = NULL;
+ }
+ if (--info->refCount <= 0) {
+ ckfree(info);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConsoleDeleteProc --
+ *
+ * If the console command is deleted we destroy the console window and
+ * all associated data structures.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A new console it created.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ConsoleDeleteProc(
+ ClientData clientData)
+{
+ ConsoleInfo *info = clientData;
+
+ if (info->consoleInterp) {
+ Tcl_DeleteInterp(info->consoleInterp);
+ }
+ if (--info->refCount <= 0) {
+ ckfree(info);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConsoleEventProc --
+ *
+ * This event function is registered on the main window of the slave
+ * interpreter. If the user or a running script causes the main window to
+ * be destroyed, then we need to inform the console interpreter by
+ * invoking "::tk::ConsoleExit".
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Invokes the "::tk::ConsoleExit" command in the console interp.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ConsoleEventProc(
+ ClientData clientData,
+ XEvent *eventPtr)
+{
+ if (eventPtr->type == DestroyNotify) {
+ ConsoleInfo *info = clientData;
+ Tcl_Interp *consoleInterp = info->consoleInterp;
+
+ if (consoleInterp && !Tcl_InterpDeleted(consoleInterp)) {
+ Tcl_EvalEx(consoleInterp, "tk::ConsoleExit", -1, TCL_EVAL_GLOBAL);
+ }
+
+ if (--info->refCount <= 0) {
+ ckfree(info);
+ }
+ }
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkCursor.c b/tk8.6/generic/tkCursor.c
new file mode 100644
index 0000000..ff66d17
--- /dev/null
+++ b/tk8.6/generic/tkCursor.c
@@ -0,0 +1,882 @@
+/*
+ * tkCursor.c --
+ *
+ * This file maintains a database of read-only cursors for the Tk
+ * toolkit. This allows cursors to be shared between widgets and also
+ * avoids round-trips to the X server.
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "tkInt.h"
+
+/*
+ * A TkCursor structure exists for each cursor that is currently active. Each
+ * structure is indexed with two hash tables defined below. One of the tables
+ * is cursorIdTable, and the other is either cursorNameTable or
+ * cursorDataTable, each of which are stored in the TkDisplay structure for
+ * the current thread.
+ */
+
+typedef struct {
+ const char *source; /* Cursor bits. */
+ const char *mask; /* Mask bits. */
+ int width, height; /* Dimensions of cursor (and data and
+ * mask). */
+ int xHot, yHot; /* Location of cursor hot-spot. */
+ Tk_Uid fg, bg; /* Colors for cursor. */
+ Display *display; /* Display on which cursor will be used. */
+} DataKey;
+
+/*
+ * Forward declarations for functions defined in this file:
+ */
+
+static void CursorInit(TkDisplay *dispPtr);
+static void DupCursorObjProc(Tcl_Obj *srcObjPtr,
+ Tcl_Obj *dupObjPtr);
+static void FreeCursor(TkCursor *cursorPtr);
+static void FreeCursorObj(Tcl_Obj *objPtr);
+static void FreeCursorObjProc(Tcl_Obj *objPtr);
+static TkCursor * TkcGetCursor(Tcl_Interp *interp, Tk_Window tkwin,
+ const char *name);
+static TkCursor * GetCursorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr);
+static void InitCursorObj(Tcl_Obj *objPtr);
+
+/*
+ * The following structure defines the implementation of the "cursor" Tcl
+ * object, used for drawing. The color object remembers the hash table
+ * entry associated with a color. The actual allocation and deallocation
+ * of the color should be done by the configuration package when the cursor
+ * option is set.
+ */
+
+Tcl_ObjType const tkCursorObjType = {
+ "cursor", /* name */
+ FreeCursorObjProc, /* freeIntRepProc */
+ DupCursorObjProc, /* dupIntRepProc */
+ NULL, /* updateStringProc */
+ NULL /* setFromAnyProc */
+};
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_AllocCursorFromObj --
+ *
+ * Given a Tcl_Obj *, map the value to a corresponding Tk_Cursor
+ * structure based on the tkwin given.
+ *
+ * Results:
+ * The return value is the X identifer for the desired cursor, unless
+ * objPtr couldn't be parsed correctly. In this case, None is returned
+ * and an error message is left in the interp's result. The caller should
+ * never modify the cursor that is returned, and should eventually call
+ * Tk_FreeCursorFromObj when the cursor is no longer needed.
+ *
+ * Side effects:
+ * The cursor is added to an internal database with a reference count.
+ * For each call to this function, there should eventually be a call to
+ * Tk_FreeCursorFromObj, so that the database can be cleaned up when
+ * cursors aren't needed anymore.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_Cursor
+Tk_AllocCursorFromObj(
+ Tcl_Interp *interp, /* Interp for error results. */
+ Tk_Window tkwin, /* Window in which the cursor will be used.*/
+ Tcl_Obj *objPtr) /* Object describing cursor; see manual entry
+ * for description of legal syntax of this
+ * obj's string rep. */
+{
+ TkCursor *cursorPtr;
+
+ if (objPtr->typePtr != &tkCursorObjType) {
+ InitCursorObj(objPtr);
+ }
+ cursorPtr = objPtr->internalRep.twoPtrValue.ptr1;
+
+ /*
+ * If the object currently points to a TkCursor, see if it's the one we
+ * want. If so, increment its reference count and return.
+ */
+
+ if (cursorPtr != NULL) {
+ if (cursorPtr->resourceRefCount == 0) {
+ /*
+ * This is a stale reference: it refers to a TkCursor that's no
+ * longer in use. Clear the reference.
+ */
+
+ FreeCursorObj(objPtr);
+ cursorPtr = NULL;
+ } else if (Tk_Display(tkwin) == cursorPtr->display) {
+ cursorPtr->resourceRefCount++;
+ return cursorPtr->cursor;
+ }
+ }
+
+ /*
+ * The object didn't point to the TkCursor that we wanted. Search the list
+ * of TkCursors with the same name to see if one of the other TkCursors is
+ * the right one.
+ */
+
+ if (cursorPtr != NULL) {
+ TkCursor *firstCursorPtr = Tcl_GetHashValue(cursorPtr->hashPtr);
+
+ FreeCursorObj(objPtr);
+ for (cursorPtr = firstCursorPtr; cursorPtr != NULL;
+ cursorPtr = cursorPtr->nextPtr) {
+ if (Tk_Display(tkwin) == cursorPtr->display) {
+ cursorPtr->resourceRefCount++;
+ cursorPtr->objRefCount++;
+ objPtr->internalRep.twoPtrValue.ptr1 = cursorPtr;
+ return cursorPtr->cursor;
+ }
+ }
+ }
+
+ /*
+ * Still no luck. Call TkcGetCursor to allocate a new TkCursor object.
+ */
+
+ cursorPtr = TkcGetCursor(interp, tkwin, Tcl_GetString(objPtr));
+ objPtr->internalRep.twoPtrValue.ptr1 = cursorPtr;
+ if (cursorPtr == NULL) {
+ return NULL;
+ }
+ cursorPtr->objRefCount++;
+ return cursorPtr->cursor;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetCursor --
+ *
+ * Given a string describing a cursor, locate (or create if necessary) a
+ * cursor that fits the description.
+ *
+ * Results:
+ * The return value is the X identifer for the desired cursor, unless
+ * string couldn't be parsed correctly. In this case, None is returned
+ * and an error message is left in the interp's result. The caller should
+ * never modify the cursor that is returned, and should eventually call
+ * Tk_FreeCursor when the cursor is no longer needed.
+ *
+ * Side effects:
+ * The cursor is added to an internal database with a reference count.
+ * For each call to this function, there should eventually be a call to
+ * Tk_FreeCursor, so that the database can be cleaned up when cursors
+ * aren't needed anymore.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_Cursor
+Tk_GetCursor(
+ 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. */
+{
+ TkCursor *cursorPtr = TkcGetCursor(interp, tkwin, string);
+
+ if (cursorPtr == NULL) {
+ return NULL;
+ }
+ return cursorPtr->cursor;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkcGetCursor --
+ *
+ * Given a string describing a cursor, locate (or create if necessary) a
+ * cursor that fits the description. This routine returns the internal
+ * data structure for the cursor, which avoids extra hash table lookups
+ * in Tk_AllocCursorFromObj.
+ *
+ * Results:
+ * The return value is a pointer to the TkCursor for the desired cursor,
+ * unless string couldn't be parsed correctly. In this case, NULL is
+ * returned and an error message is left in the interp's result. The
+ * caller should never modify the cursor that is returned, and should
+ * eventually call Tk_FreeCursor when the cursor is no longer needed.
+ *
+ * Side effects:
+ * The cursor is added to an internal database with a reference count.
+ * For each call to this function, there should eventually be a call to
+ * Tk_FreeCursor, so that the database can be cleaned up when cursors
+ * aren't needed anymore.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static TkCursor *
+TkcGetCursor(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting. */
+ Tk_Window tkwin, /* Window in which cursor will be used. */
+ const char *string) /* Description of cursor. See manual entry for
+ * details on legal syntax. */
+{
+ Tcl_HashEntry *nameHashPtr;
+ register TkCursor *cursorPtr;
+ TkCursor *existingCursorPtr = NULL;
+ int isNew;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+
+ if (!dispPtr->cursorInit) {
+ CursorInit(dispPtr);
+ }
+
+ nameHashPtr = Tcl_CreateHashEntry(&dispPtr->cursorNameTable,
+ string, &isNew);
+ if (!isNew) {
+ existingCursorPtr = Tcl_GetHashValue(nameHashPtr);
+ for (cursorPtr = existingCursorPtr; cursorPtr != NULL;
+ cursorPtr = cursorPtr->nextPtr) {
+ if (Tk_Display(tkwin) == cursorPtr->display) {
+ cursorPtr->resourceRefCount++;
+ return cursorPtr;
+ }
+ }
+ } else {
+ existingCursorPtr = NULL;
+ }
+
+ cursorPtr = TkGetCursorByName(interp, tkwin, string);
+
+ if (cursorPtr == NULL) {
+ if (isNew) {
+ Tcl_DeleteHashEntry(nameHashPtr);
+ }
+ return NULL;
+ }
+
+ /*
+ * Add information about this cursor to our database.
+ */
+
+ cursorPtr->display = Tk_Display(tkwin);
+ cursorPtr->resourceRefCount = 1;
+ cursorPtr->objRefCount = 0;
+ cursorPtr->otherTable = &dispPtr->cursorNameTable;
+ cursorPtr->hashPtr = nameHashPtr;
+ cursorPtr->nextPtr = existingCursorPtr;
+ cursorPtr->idHashPtr = Tcl_CreateHashEntry(&dispPtr->cursorIdTable,
+ (char *) cursorPtr->cursor, &isNew);
+ if (!isNew) {
+ Tcl_Panic("cursor already registered in Tk_GetCursor");
+ }
+ Tcl_SetHashValue(nameHashPtr, cursorPtr);
+ Tcl_SetHashValue(cursorPtr->idHashPtr, cursorPtr);
+
+ return cursorPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetCursorFromData --
+ *
+ * Given a description of the bits and colors for a cursor, make a cursor
+ * that has the given properties.
+ *
+ * Results:
+ * The return value is the X identifer for the desired cursor, unless it
+ * couldn't be created properly. In this case, None is returned and an
+ * error message is left in the interp's result. The caller should never
+ * modify the cursor that is returned, and should eventually call
+ * Tk_FreeCursor when the cursor is no longer needed.
+ *
+ * Side effects:
+ * The cursor is added to an internal database with a reference count.
+ * For each call to this function, there should eventually be a call to
+ * Tk_FreeCursor, so that the database can be cleaned up when cursors
+ * aren't needed anymore.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_Cursor
+Tk_GetCursorFromData(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting. */
+ 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. */
+ Tk_Uid fg, /* Foreground color for cursor. */
+ Tk_Uid bg) /* Background color for cursor. */
+{
+ DataKey dataKey;
+ Tcl_HashEntry *dataHashPtr;
+ register TkCursor *cursorPtr;
+ int isNew;
+ XColor fgColor, bgColor;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+
+ if (!dispPtr->cursorInit) {
+ CursorInit(dispPtr);
+ }
+
+ dataKey.source = source;
+ dataKey.mask = mask;
+ dataKey.width = width;
+ dataKey.height = height;
+ dataKey.xHot = xHot;
+ dataKey.yHot = yHot;
+ dataKey.fg = fg;
+ dataKey.bg = bg;
+ dataKey.display = Tk_Display(tkwin);
+ dataHashPtr = Tcl_CreateHashEntry(&dispPtr->cursorDataTable,
+ (char *) &dataKey, &isNew);
+ if (!isNew) {
+ cursorPtr = Tcl_GetHashValue(dataHashPtr);
+ cursorPtr->resourceRefCount++;
+ return cursorPtr->cursor;
+ }
+
+ /*
+ * No suitable cursor exists yet. Make one using the data available and
+ * add it to the database.
+ */
+
+ if (TkParseColor(dataKey.display, Tk_Colormap(tkwin), fg, &fgColor) == 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "invalid color name \"%s\"", fg));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "CURSOR", "COLOR", NULL);
+ goto error;
+ }
+ if (TkParseColor(dataKey.display, Tk_Colormap(tkwin), bg, &bgColor) == 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "invalid color name \"%s\"", bg));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "CURSOR", "COLOR", NULL);
+ goto error;
+ }
+
+ cursorPtr = TkCreateCursorFromData(tkwin, source, mask, width, height,
+ xHot, yHot, fgColor, bgColor);
+
+ if (cursorPtr == NULL) {
+ goto error;
+ }
+
+ cursorPtr->resourceRefCount = 1;
+ cursorPtr->otherTable = &dispPtr->cursorDataTable;
+ cursorPtr->hashPtr = dataHashPtr;
+ cursorPtr->objRefCount = 0;
+ cursorPtr->idHashPtr = Tcl_CreateHashEntry(&dispPtr->cursorIdTable,
+ (char *) cursorPtr->cursor, &isNew);
+ cursorPtr->nextPtr = NULL;
+
+ if (!isNew) {
+ Tcl_Panic("cursor already registered in Tk_GetCursorFromData");
+ }
+ Tcl_SetHashValue(dataHashPtr, cursorPtr);
+ Tcl_SetHashValue(cursorPtr->idHashPtr, cursorPtr);
+ return cursorPtr->cursor;
+
+ error:
+ Tcl_DeleteHashEntry(dataHashPtr);
+ return NULL;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_NameOfCursor --
+ *
+ * Given a cursor, return a textual string identifying it.
+ *
+ * Results:
+ * If cursor was created by Tk_GetCursor, then the return value is the
+ * "string" that was used to create it. Otherwise the return value is a
+ * string giving the X identifier for the cursor. The storage for the
+ * returned string is only guaranteed to persist up until the next call
+ * to this function.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+const char *
+Tk_NameOfCursor(
+ Display *display, /* Display for which cursor was allocated. */
+ Tk_Cursor cursor) /* Identifier for cursor whose name is
+ * wanted. */
+{
+ Tcl_HashEntry *idHashPtr;
+ TkCursor *cursorPtr;
+ TkDisplay *dispPtr;
+
+ dispPtr = TkGetDisplay(display);
+
+ if (!dispPtr->cursorInit) {
+ printid:
+ sprintf(dispPtr->cursorString, "cursor id %p", cursor);
+ return dispPtr->cursorString;
+ }
+ idHashPtr = Tcl_FindHashEntry(&dispPtr->cursorIdTable, (char *) cursor);
+ if (idHashPtr == NULL) {
+ goto printid;
+ }
+ cursorPtr = Tcl_GetHashValue(idHashPtr);
+ if (cursorPtr->otherTable != &dispPtr->cursorNameTable) {
+ goto printid;
+ }
+ return cursorPtr->hashPtr->key.string;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeCursor --
+ *
+ * This function is invoked by both Tk_FreeCursorFromObj and
+ * Tk_FreeCursor; it does all the real work of deallocating a cursor.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The reference count associated with cursor is decremented, and it is
+ * officially deallocated if no-one is using it anymore.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FreeCursor(
+ TkCursor *cursorPtr) /* Cursor to be released. */
+{
+ TkCursor *prevPtr;
+
+ cursorPtr->resourceRefCount--;
+ if (cursorPtr->resourceRefCount > 0) {
+ return;
+ }
+
+ Tcl_DeleteHashEntry(cursorPtr->idHashPtr);
+ prevPtr = Tcl_GetHashValue(cursorPtr->hashPtr);
+ if (prevPtr == cursorPtr) {
+ if (cursorPtr->nextPtr == NULL) {
+ Tcl_DeleteHashEntry(cursorPtr->hashPtr);
+ } else {
+ Tcl_SetHashValue(cursorPtr->hashPtr, cursorPtr->nextPtr);
+ }
+ } else {
+ while (prevPtr->nextPtr != cursorPtr) {
+ prevPtr = prevPtr->nextPtr;
+ }
+ prevPtr->nextPtr = cursorPtr->nextPtr;
+ }
+ TkpFreeCursor(cursorPtr);
+ if (cursorPtr->objRefCount == 0) {
+ ckfree(cursorPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_FreeCursor --
+ *
+ * This function is called to release a cursor allocated by Tk_GetCursor
+ * or TkGetCursorFromData.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The reference count associated with cursor is decremented, and it is
+ * officially deallocated if no-one is using it anymore.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_FreeCursor(
+ Display *display, /* Display for which cursor was allocated. */
+ Tk_Cursor cursor) /* Identifier for cursor to be released. */
+{
+ Tcl_HashEntry *idHashPtr;
+ TkDisplay *dispPtr = TkGetDisplay(display);
+
+ if (!dispPtr->cursorInit) {
+ Tcl_Panic("Tk_FreeCursor called before Tk_GetCursor");
+ }
+
+ idHashPtr = Tcl_FindHashEntry(&dispPtr->cursorIdTable, (char *) cursor);
+ if (idHashPtr == NULL) {
+ Tcl_Panic("Tk_FreeCursor received unknown cursor argument");
+ }
+ FreeCursor(Tcl_GetHashValue(idHashPtr));
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_FreeCursorFromObj --
+ *
+ * This function is called to release a cursor allocated by
+ * Tk_AllocCursorFromObj. It does not throw away the Tcl_Obj *; it only
+ * gets rid of the hash table entry for this cursor and clears the cached
+ * value that is normally stored in the object.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The reference count associated with the cursor represented by objPtr
+ * is decremented, and the cursor is released to X if there are no
+ * remaining uses for it.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_FreeCursorFromObj(
+ Tk_Window tkwin, /* The window this cursor lives in. Needed for
+ * the display value. */
+ Tcl_Obj *objPtr) /* The Tcl_Obj * to be freed. */
+{
+ FreeCursor(GetCursorFromObj(tkwin, objPtr));
+ FreeCursorObj(objPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FreeCursorObjProc, FreeCursorObj --
+ *
+ * This proc is called to release an object reference to a cursor.
+ * Called when the object's internal rep is released or when the cached
+ * tkColPtr needs to be changed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The object reference count is decremented. When both it and the hash
+ * ref count go to zero, the color's resources are released.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+FreeCursorObjProc(
+ Tcl_Obj *objPtr) /* The object we are releasing. */
+{
+ FreeCursorObj(objPtr);
+ objPtr->typePtr = NULL;
+}
+
+static void
+FreeCursorObj(
+ Tcl_Obj *objPtr) /* The object we are releasing. */
+{
+ TkCursor *cursorPtr = objPtr->internalRep.twoPtrValue.ptr1;
+
+ if (cursorPtr != NULL) {
+ cursorPtr->objRefCount--;
+ if ((cursorPtr->objRefCount == 0)
+ && (cursorPtr->resourceRefCount == 0)) {
+ ckfree(cursorPtr);
+ }
+ objPtr->internalRep.twoPtrValue.ptr1 = NULL;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DupCursorObjProc --
+ *
+ * When a cached cursor object is duplicated, this is called to update
+ * the internal reps.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The color's objRefCount is incremented and the internal rep of the
+ * copy is set to point to it.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+DupCursorObjProc(
+ Tcl_Obj *srcObjPtr, /* The object we are copying from. */
+ Tcl_Obj *dupObjPtr) /* The object we are copying to. */
+{
+ TkCursor *cursorPtr = srcObjPtr->internalRep.twoPtrValue.ptr1;
+
+ dupObjPtr->typePtr = srcObjPtr->typePtr;
+ dupObjPtr->internalRep.twoPtrValue.ptr1 = cursorPtr;
+
+ if (cursorPtr != NULL) {
+ cursorPtr->objRefCount++;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetCursorFromObj --
+ *
+ * Returns the cursor referred to buy a Tcl object. The cursor must
+ * already have been allocated via a call to Tk_AllocCursorFromObj or
+ * Tk_GetCursor.
+ *
+ * Results:
+ * Returns the Tk_Cursor that matches the tkwin and the string rep of the
+ * name of the cursor given in objPtr.
+ *
+ * Side effects:
+ * If the object is not already a cursor, the conversion will free any
+ * old internal representation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_Cursor
+Tk_GetCursorFromObj(
+ Tk_Window tkwin,
+ Tcl_Obj *objPtr) /* The object from which to get pixels. */
+{
+ TkCursor *cursorPtr = GetCursorFromObj(tkwin, objPtr);
+
+ /*
+ * GetCursorFromObj should never return NULL
+ */
+
+ return cursorPtr->cursor;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetCursorFromObj --
+ *
+ * Returns the cursor referred to by a Tcl object. The cursor must
+ * already have been allocated via a call to Tk_AllocCursorFromObj or
+ * Tk_GetCursor.
+ *
+ * Results:
+ * Returns the TkCursor * that matches the tkwin and the string rep of
+ * the name of the cursor given in objPtr.
+ *
+ * Side effects:
+ * If the object is not already a cursor, the conversion will free any
+ * old internal representation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static TkCursor *
+GetCursorFromObj(
+ Tk_Window tkwin, /* Window in which the cursor will be used. */
+ Tcl_Obj *objPtr) /* The object that describes the desired
+ * cursor. */
+{
+ TkCursor *cursorPtr;
+ Tcl_HashEntry *hashPtr;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+
+ if (objPtr->typePtr != &tkCursorObjType) {
+ InitCursorObj(objPtr);
+ }
+
+ /*
+ * The internal representation is a cache of the last cursor used with the
+ * given name. But there can be lots different cursors for each cursor
+ * name; one cursor for each display. Check to see if the cursor we have
+ * cached is the one that is needed.
+ */
+
+ cursorPtr = objPtr->internalRep.twoPtrValue.ptr1;
+ if ((cursorPtr != NULL) && (Tk_Display(tkwin) == cursorPtr->display)) {
+ return cursorPtr;
+ }
+
+ /*
+ * If we get to here, it means the cursor we need is not in the cache.
+ * Try to look up the cursor in the TkDisplay structure of the window.
+ */
+
+ hashPtr = Tcl_FindHashEntry(&dispPtr->cursorNameTable,
+ Tcl_GetString(objPtr));
+ if (hashPtr == NULL) {
+ goto error;
+ }
+ for (cursorPtr = Tcl_GetHashValue(hashPtr);
+ cursorPtr != NULL; cursorPtr = cursorPtr->nextPtr) {
+ if (Tk_Display(tkwin) == cursorPtr->display) {
+ FreeCursorObj(objPtr);
+ objPtr->internalRep.twoPtrValue.ptr1 = cursorPtr;
+ cursorPtr->objRefCount++;
+ return cursorPtr;
+ }
+ }
+
+ error:
+ Tcl_Panic("GetCursorFromObj called with non-existent cursor!");
+ /*
+ * The following code isn't reached; it's just there to please compilers.
+ */
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InitCursorObj --
+ *
+ * Bookeeping function to change an objPtr to a cursor type.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The old internal rep of the object is freed. The internal rep is
+ * cleared. The final form of the object is set by either
+ * Tk_AllocCursorFromObj or GetCursorFromObj.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+InitCursorObj(
+ Tcl_Obj *objPtr) /* The object to convert. */
+{
+ const Tcl_ObjType *typePtr;
+
+ /*
+ * Free the old internalRep before setting the new one.
+ */
+
+ Tcl_GetString(objPtr);
+ typePtr = objPtr->typePtr;
+ if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
+ typePtr->freeIntRepProc(objPtr);
+ }
+ objPtr->typePtr = &tkCursorObjType;
+ objPtr->internalRep.twoPtrValue.ptr1 = NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CursorInit --
+ *
+ * Initialize the structures used for cursor management.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Read the code.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+CursorInit(
+ TkDisplay *dispPtr) /* Display used to store thread-specific
+ * data. */
+{
+ Tcl_InitHashTable(&dispPtr->cursorNameTable, TCL_STRING_KEYS);
+ Tcl_InitHashTable(&dispPtr->cursorDataTable, sizeof(DataKey)/sizeof(int));
+
+ /*
+ * The call below is tricky: can't use sizeof(IdKey) because it gets
+ * padded with extra unpredictable bytes on some 64-bit machines.
+ */
+
+ /*
+ * Old code....
+ * Tcl_InitHashTable(&dispPtr->cursorIdTable, sizeof(Display *)
+ * /sizeof(int));
+ *
+ * The comment above doesn't make sense. However, XIDs should only be 32
+ * bits, by the definition of X, so the code above causes Tk to crash.
+ * Here is the real code:
+ */
+
+ Tcl_InitHashTable(&dispPtr->cursorIdTable, TCL_ONE_WORD_KEYS);
+
+ dispPtr->cursorInit = 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkDebugCursor --
+ *
+ * This function returns debugging information about a cursor.
+ *
+ * Results:
+ * The return value is a list with one sublist for each TkCursor
+ * corresponding to "name". Each sublist has two elements that contain
+ * the resourceRefCount and objRefCount fields from the TkCursor
+ * structure.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TkDebugCursor(
+ Tk_Window tkwin, /* The window in which the cursor will be used
+ * (not currently used). */
+ const char *name) /* Name of the desired color. */
+{
+ TkCursor *cursorPtr;
+ Tcl_HashEntry *hashPtr;
+ Tcl_Obj *resultPtr, *objPtr;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+
+ if (!dispPtr->cursorInit) {
+ CursorInit(dispPtr);
+ }
+ resultPtr = Tcl_NewObj();
+ hashPtr = Tcl_FindHashEntry(&dispPtr->cursorNameTable, name);
+ if (hashPtr != NULL) {
+ cursorPtr = Tcl_GetHashValue(hashPtr);
+ if (cursorPtr == NULL) {
+ Tcl_Panic("TkDebugCursor found empty hash table entry");
+ }
+ for ( ; (cursorPtr != NULL); cursorPtr = cursorPtr->nextPtr) {
+ objPtr = Tcl_NewObj();
+ Tcl_ListObjAppendElement(NULL, objPtr,
+ Tcl_NewIntObj(cursorPtr->resourceRefCount));
+ Tcl_ListObjAppendElement(NULL, objPtr,
+ Tcl_NewIntObj(cursorPtr->objRefCount));
+ Tcl_ListObjAppendElement(NULL, resultPtr, objPtr);
+ }
+ }
+ return resultPtr;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkDecls.h b/tk8.6/generic/tkDecls.h
new file mode 100644
index 0000000..64c32cd
--- /dev/null
+++ b/tk8.6/generic/tkDecls.h
@@ -0,0 +1,1733 @@
+/*
+ * tkDecls.h --
+ *
+ * Declarations of functions in the platform independent public Tcl API.
+ *
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef _TKDECLS
+#define _TKDECLS
+
+#ifdef BUILD_tk
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLEXPORT
+#endif
+
+/*
+ * WARNING: This file is automatically generated by the tools/genStubs.tcl
+ * script. Any modifications to the function declarations below should be made
+ * in the generic/tk.decls script.
+ */
+
+/* !BEGIN!: Do not edit below this line. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Exported function declarations:
+ */
+
+/* 0 */
+EXTERN void Tk_MainLoop(void);
+/* 1 */
+EXTERN XColor * Tk_3DBorderColor(Tk_3DBorder border);
+/* 2 */
+EXTERN GC Tk_3DBorderGC(Tk_Window tkwin, Tk_3DBorder border,
+ int which);
+/* 3 */
+EXTERN void Tk_3DHorizontalBevel(Tk_Window tkwin,
+ Drawable drawable, Tk_3DBorder border, int x,
+ int y, int width, int height, int leftIn,
+ int rightIn, int topBevel, int relief);
+/* 4 */
+EXTERN void Tk_3DVerticalBevel(Tk_Window tkwin,
+ Drawable drawable, Tk_3DBorder border, int x,
+ int y, int width, int height, int leftBevel,
+ int relief);
+/* 5 */
+EXTERN void Tk_AddOption(Tk_Window tkwin, const char *name,
+ const char *value, int priority);
+/* 6 */
+EXTERN void Tk_BindEvent(Tk_BindingTable bindingTable,
+ XEvent *eventPtr, Tk_Window tkwin,
+ int numObjects, ClientData *objectPtr);
+/* 7 */
+EXTERN void Tk_CanvasDrawableCoords(Tk_Canvas canvas, double x,
+ double y, short *drawableXPtr,
+ short *drawableYPtr);
+/* 8 */
+EXTERN void Tk_CanvasEventuallyRedraw(Tk_Canvas canvas, int x1,
+ int y1, int x2, int y2);
+/* 9 */
+EXTERN int Tk_CanvasGetCoord(Tcl_Interp *interp,
+ Tk_Canvas canvas, const char *str,
+ double *doublePtr);
+/* 10 */
+EXTERN Tk_CanvasTextInfo * Tk_CanvasGetTextInfo(Tk_Canvas canvas);
+/* 11 */
+EXTERN int Tk_CanvasPsBitmap(Tcl_Interp *interp,
+ Tk_Canvas canvas, Pixmap bitmap, int x,
+ int y, int width, int height);
+/* 12 */
+EXTERN int Tk_CanvasPsColor(Tcl_Interp *interp,
+ Tk_Canvas canvas, XColor *colorPtr);
+/* 13 */
+EXTERN int Tk_CanvasPsFont(Tcl_Interp *interp, Tk_Canvas canvas,
+ Tk_Font font);
+/* 14 */
+EXTERN void Tk_CanvasPsPath(Tcl_Interp *interp, Tk_Canvas canvas,
+ double *coordPtr, int numPoints);
+/* 15 */
+EXTERN int Tk_CanvasPsStipple(Tcl_Interp *interp,
+ Tk_Canvas canvas, Pixmap bitmap);
+/* 16 */
+EXTERN double Tk_CanvasPsY(Tk_Canvas canvas, double y);
+/* 17 */
+EXTERN void Tk_CanvasSetStippleOrigin(Tk_Canvas canvas, GC gc);
+/* 18 */
+EXTERN int Tk_CanvasTagsParseProc(ClientData clientData,
+ Tcl_Interp *interp, Tk_Window tkwin,
+ const char *value, char *widgRec, int offset);
+/* 19 */
+EXTERN CONST86 char * Tk_CanvasTagsPrintProc(ClientData clientData,
+ Tk_Window tkwin, char *widgRec, int offset,
+ Tcl_FreeProc **freeProcPtr);
+/* 20 */
+EXTERN Tk_Window Tk_CanvasTkwin(Tk_Canvas canvas);
+/* 21 */
+EXTERN void Tk_CanvasWindowCoords(Tk_Canvas canvas, double x,
+ double y, short *screenXPtr,
+ short *screenYPtr);
+/* 22 */
+EXTERN void Tk_ChangeWindowAttributes(Tk_Window tkwin,
+ unsigned long valueMask,
+ XSetWindowAttributes *attsPtr);
+/* 23 */
+EXTERN int Tk_CharBbox(Tk_TextLayout layout, int index,
+ int *xPtr, int *yPtr, int *widthPtr,
+ int *heightPtr);
+/* 24 */
+EXTERN void Tk_ClearSelection(Tk_Window tkwin, Atom selection);
+/* 25 */
+EXTERN int Tk_ClipboardAppend(Tcl_Interp *interp,
+ Tk_Window tkwin, Atom target, Atom format,
+ const char *buffer);
+/* 26 */
+EXTERN int Tk_ClipboardClear(Tcl_Interp *interp,
+ Tk_Window tkwin);
+/* 27 */
+EXTERN int Tk_ConfigureInfo(Tcl_Interp *interp, Tk_Window tkwin,
+ const Tk_ConfigSpec *specs, char *widgRec,
+ const char *argvName, int flags);
+/* 28 */
+EXTERN int Tk_ConfigureValue(Tcl_Interp *interp,
+ Tk_Window tkwin, const Tk_ConfigSpec *specs,
+ char *widgRec, const char *argvName,
+ int flags);
+/* 29 */
+EXTERN int Tk_ConfigureWidget(Tcl_Interp *interp,
+ Tk_Window tkwin, const Tk_ConfigSpec *specs,
+ int argc, CONST84 char **argv, char *widgRec,
+ int flags);
+/* 30 */
+EXTERN void Tk_ConfigureWindow(Tk_Window tkwin,
+ unsigned int valueMask,
+ XWindowChanges *valuePtr);
+/* 31 */
+EXTERN Tk_TextLayout Tk_ComputeTextLayout(Tk_Font font, const char *str,
+ int numChars, int wrapLength,
+ Tk_Justify justify, int flags, int *widthPtr,
+ int *heightPtr);
+/* 32 */
+EXTERN Tk_Window Tk_CoordsToWindow(int rootX, int rootY,
+ Tk_Window tkwin);
+/* 33 */
+EXTERN unsigned long Tk_CreateBinding(Tcl_Interp *interp,
+ Tk_BindingTable bindingTable,
+ ClientData object, const char *eventStr,
+ const char *script, int append);
+/* 34 */
+EXTERN Tk_BindingTable Tk_CreateBindingTable(Tcl_Interp *interp);
+/* 35 */
+EXTERN Tk_ErrorHandler Tk_CreateErrorHandler(Display *display, int errNum,
+ int request, int minorCode,
+ Tk_ErrorProc *errorProc,
+ ClientData clientData);
+/* 36 */
+EXTERN void Tk_CreateEventHandler(Tk_Window token,
+ unsigned long mask, Tk_EventProc *proc,
+ ClientData clientData);
+/* 37 */
+EXTERN void Tk_CreateGenericHandler(Tk_GenericProc *proc,
+ ClientData clientData);
+/* 38 */
+EXTERN void Tk_CreateImageType(const Tk_ImageType *typePtr);
+/* 39 */
+EXTERN void Tk_CreateItemType(Tk_ItemType *typePtr);
+/* 40 */
+EXTERN void Tk_CreatePhotoImageFormat(
+ const Tk_PhotoImageFormat *formatPtr);
+/* 41 */
+EXTERN void Tk_CreateSelHandler(Tk_Window tkwin, Atom selection,
+ Atom target, Tk_SelectionProc *proc,
+ ClientData clientData, Atom format);
+/* 42 */
+EXTERN Tk_Window Tk_CreateWindow(Tcl_Interp *interp, Tk_Window parent,
+ const char *name, const char *screenName);
+/* 43 */
+EXTERN Tk_Window Tk_CreateWindowFromPath(Tcl_Interp *interp,
+ Tk_Window tkwin, const char *pathName,
+ const char *screenName);
+/* 44 */
+EXTERN int Tk_DefineBitmap(Tcl_Interp *interp, const char *name,
+ const void *source, int width, int height);
+/* 45 */
+EXTERN void Tk_DefineCursor(Tk_Window window, Tk_Cursor cursor);
+/* 46 */
+EXTERN void Tk_DeleteAllBindings(Tk_BindingTable bindingTable,
+ ClientData object);
+/* 47 */
+EXTERN int Tk_DeleteBinding(Tcl_Interp *interp,
+ Tk_BindingTable bindingTable,
+ ClientData object, const char *eventStr);
+/* 48 */
+EXTERN void Tk_DeleteBindingTable(Tk_BindingTable bindingTable);
+/* 49 */
+EXTERN void Tk_DeleteErrorHandler(Tk_ErrorHandler handler);
+/* 50 */
+EXTERN void Tk_DeleteEventHandler(Tk_Window token,
+ unsigned long mask, Tk_EventProc *proc,
+ ClientData clientData);
+/* 51 */
+EXTERN void Tk_DeleteGenericHandler(Tk_GenericProc *proc,
+ ClientData clientData);
+/* 52 */
+EXTERN void Tk_DeleteImage(Tcl_Interp *interp, const char *name);
+/* 53 */
+EXTERN void Tk_DeleteSelHandler(Tk_Window tkwin, Atom selection,
+ Atom target);
+/* 54 */
+EXTERN void Tk_DestroyWindow(Tk_Window tkwin);
+/* 55 */
+EXTERN CONST84_RETURN char * Tk_DisplayName(Tk_Window tkwin);
+/* 56 */
+EXTERN int Tk_DistanceToTextLayout(Tk_TextLayout layout, int x,
+ int y);
+/* 57 */
+EXTERN void Tk_Draw3DPolygon(Tk_Window tkwin, Drawable drawable,
+ Tk_3DBorder border, XPoint *pointPtr,
+ int numPoints, int borderWidth,
+ int leftRelief);
+/* 58 */
+EXTERN void Tk_Draw3DRectangle(Tk_Window tkwin,
+ Drawable drawable, Tk_3DBorder border, int x,
+ int y, int width, int height,
+ int borderWidth, int relief);
+/* 59 */
+EXTERN void Tk_DrawChars(Display *display, Drawable drawable,
+ GC gc, Tk_Font tkfont, const char *source,
+ int numBytes, int x, int y);
+/* 60 */
+EXTERN void Tk_DrawFocusHighlight(Tk_Window tkwin, GC gc,
+ int width, Drawable drawable);
+/* 61 */
+EXTERN void Tk_DrawTextLayout(Display *display,
+ Drawable drawable, GC gc,
+ Tk_TextLayout layout, int x, int y,
+ int firstChar, int lastChar);
+/* 62 */
+EXTERN void Tk_Fill3DPolygon(Tk_Window tkwin, Drawable drawable,
+ Tk_3DBorder border, XPoint *pointPtr,
+ int numPoints, int borderWidth,
+ int leftRelief);
+/* 63 */
+EXTERN void Tk_Fill3DRectangle(Tk_Window tkwin,
+ Drawable drawable, Tk_3DBorder border, int x,
+ int y, int width, int height,
+ int borderWidth, int relief);
+/* 64 */
+EXTERN Tk_PhotoHandle Tk_FindPhoto(Tcl_Interp *interp,
+ const char *imageName);
+/* 65 */
+EXTERN Font Tk_FontId(Tk_Font font);
+/* 66 */
+EXTERN void Tk_Free3DBorder(Tk_3DBorder border);
+/* 67 */
+EXTERN void Tk_FreeBitmap(Display *display, Pixmap bitmap);
+/* 68 */
+EXTERN void Tk_FreeColor(XColor *colorPtr);
+/* 69 */
+EXTERN void Tk_FreeColormap(Display *display, Colormap colormap);
+/* 70 */
+EXTERN void Tk_FreeCursor(Display *display, Tk_Cursor cursor);
+/* 71 */
+EXTERN void Tk_FreeFont(Tk_Font f);
+/* 72 */
+EXTERN void Tk_FreeGC(Display *display, GC gc);
+/* 73 */
+EXTERN void Tk_FreeImage(Tk_Image image);
+/* 74 */
+EXTERN void Tk_FreeOptions(const Tk_ConfigSpec *specs,
+ char *widgRec, Display *display,
+ int needFlags);
+/* 75 */
+EXTERN void Tk_FreePixmap(Display *display, Pixmap pixmap);
+/* 76 */
+EXTERN void Tk_FreeTextLayout(Tk_TextLayout textLayout);
+/* 77 */
+EXTERN void Tk_FreeXId(Display *display, XID xid);
+/* 78 */
+EXTERN GC Tk_GCForColor(XColor *colorPtr, Drawable drawable);
+/* 79 */
+EXTERN void Tk_GeometryRequest(Tk_Window tkwin, int reqWidth,
+ int reqHeight);
+/* 80 */
+EXTERN Tk_3DBorder Tk_Get3DBorder(Tcl_Interp *interp, Tk_Window tkwin,
+ Tk_Uid colorName);
+/* 81 */
+EXTERN void Tk_GetAllBindings(Tcl_Interp *interp,
+ Tk_BindingTable bindingTable,
+ ClientData object);
+/* 82 */
+EXTERN int Tk_GetAnchor(Tcl_Interp *interp, const char *str,
+ Tk_Anchor *anchorPtr);
+/* 83 */
+EXTERN CONST84_RETURN char * Tk_GetAtomName(Tk_Window tkwin, Atom atom);
+/* 84 */
+EXTERN CONST84_RETURN char * Tk_GetBinding(Tcl_Interp *interp,
+ Tk_BindingTable bindingTable,
+ ClientData object, const char *eventStr);
+/* 85 */
+EXTERN Pixmap Tk_GetBitmap(Tcl_Interp *interp, Tk_Window tkwin,
+ const char *str);
+/* 86 */
+EXTERN Pixmap Tk_GetBitmapFromData(Tcl_Interp *interp,
+ Tk_Window tkwin, const void *source,
+ int width, int height);
+/* 87 */
+EXTERN int Tk_GetCapStyle(Tcl_Interp *interp, const char *str,
+ int *capPtr);
+/* 88 */
+EXTERN XColor * Tk_GetColor(Tcl_Interp *interp, Tk_Window tkwin,
+ Tk_Uid name);
+/* 89 */
+EXTERN XColor * Tk_GetColorByValue(Tk_Window tkwin, XColor *colorPtr);
+/* 90 */
+EXTERN Colormap Tk_GetColormap(Tcl_Interp *interp, Tk_Window tkwin,
+ const char *str);
+/* 91 */
+EXTERN Tk_Cursor Tk_GetCursor(Tcl_Interp *interp, Tk_Window tkwin,
+ Tk_Uid str);
+/* 92 */
+EXTERN Tk_Cursor Tk_GetCursorFromData(Tcl_Interp *interp,
+ Tk_Window tkwin, const char *source,
+ const char *mask, int width, int height,
+ int xHot, int yHot, Tk_Uid fg, Tk_Uid bg);
+/* 93 */
+EXTERN Tk_Font Tk_GetFont(Tcl_Interp *interp, Tk_Window tkwin,
+ const char *str);
+/* 94 */
+EXTERN Tk_Font Tk_GetFontFromObj(Tk_Window tkwin, Tcl_Obj *objPtr);
+/* 95 */
+EXTERN void Tk_GetFontMetrics(Tk_Font font,
+ Tk_FontMetrics *fmPtr);
+/* 96 */
+EXTERN GC Tk_GetGC(Tk_Window tkwin, unsigned long valueMask,
+ XGCValues *valuePtr);
+/* 97 */
+EXTERN Tk_Image Tk_GetImage(Tcl_Interp *interp, Tk_Window tkwin,
+ const char *name,
+ Tk_ImageChangedProc *changeProc,
+ ClientData clientData);
+/* 98 */
+EXTERN ClientData Tk_GetImageMasterData(Tcl_Interp *interp,
+ const char *name,
+ CONST86 Tk_ImageType **typePtrPtr);
+/* 99 */
+EXTERN Tk_ItemType * Tk_GetItemTypes(void);
+/* 100 */
+EXTERN int Tk_GetJoinStyle(Tcl_Interp *interp, const char *str,
+ int *joinPtr);
+/* 101 */
+EXTERN int Tk_GetJustify(Tcl_Interp *interp, const char *str,
+ Tk_Justify *justifyPtr);
+/* 102 */
+EXTERN int Tk_GetNumMainWindows(void);
+/* 103 */
+EXTERN Tk_Uid Tk_GetOption(Tk_Window tkwin, const char *name,
+ const char *className);
+/* 104 */
+EXTERN int Tk_GetPixels(Tcl_Interp *interp, Tk_Window tkwin,
+ const char *str, int *intPtr);
+/* 105 */
+EXTERN Pixmap Tk_GetPixmap(Display *display, Drawable d, int width,
+ int height, int depth);
+/* 106 */
+EXTERN int Tk_GetRelief(Tcl_Interp *interp, const char *name,
+ int *reliefPtr);
+/* 107 */
+EXTERN void Tk_GetRootCoords(Tk_Window tkwin, int *xPtr,
+ int *yPtr);
+/* 108 */
+EXTERN int Tk_GetScrollInfo(Tcl_Interp *interp, int argc,
+ CONST84 char **argv, double *dblPtr,
+ int *intPtr);
+/* 109 */
+EXTERN int Tk_GetScreenMM(Tcl_Interp *interp, Tk_Window tkwin,
+ const char *str, double *doublePtr);
+/* 110 */
+EXTERN int Tk_GetSelection(Tcl_Interp *interp, Tk_Window tkwin,
+ Atom selection, Atom target,
+ Tk_GetSelProc *proc, ClientData clientData);
+/* 111 */
+EXTERN Tk_Uid Tk_GetUid(const char *str);
+/* 112 */
+EXTERN Visual * Tk_GetVisual(Tcl_Interp *interp, Tk_Window tkwin,
+ const char *str, int *depthPtr,
+ Colormap *colormapPtr);
+/* 113 */
+EXTERN void Tk_GetVRootGeometry(Tk_Window tkwin, int *xPtr,
+ int *yPtr, int *widthPtr, int *heightPtr);
+/* 114 */
+EXTERN int Tk_Grab(Tcl_Interp *interp, Tk_Window tkwin,
+ int grabGlobal);
+/* 115 */
+EXTERN void Tk_HandleEvent(XEvent *eventPtr);
+/* 116 */
+EXTERN Tk_Window Tk_IdToWindow(Display *display, Window window);
+/* 117 */
+EXTERN void Tk_ImageChanged(Tk_ImageMaster master, int x, int y,
+ int width, int height, int imageWidth,
+ int imageHeight);
+/* 118 */
+EXTERN int Tk_Init(Tcl_Interp *interp);
+/* 119 */
+EXTERN Atom Tk_InternAtom(Tk_Window tkwin, const char *name);
+/* 120 */
+EXTERN int Tk_IntersectTextLayout(Tk_TextLayout layout, int x,
+ int y, int width, int height);
+/* 121 */
+EXTERN void Tk_MaintainGeometry(Tk_Window slave,
+ Tk_Window master, int x, int y, int width,
+ int height);
+/* 122 */
+EXTERN Tk_Window Tk_MainWindow(Tcl_Interp *interp);
+/* 123 */
+EXTERN void Tk_MakeWindowExist(Tk_Window tkwin);
+/* 124 */
+EXTERN void Tk_ManageGeometry(Tk_Window tkwin,
+ const Tk_GeomMgr *mgrPtr,
+ ClientData clientData);
+/* 125 */
+EXTERN void Tk_MapWindow(Tk_Window tkwin);
+/* 126 */
+EXTERN int Tk_MeasureChars(Tk_Font tkfont, const char *source,
+ int numBytes, int maxPixels, int flags,
+ int *lengthPtr);
+/* 127 */
+EXTERN void Tk_MoveResizeWindow(Tk_Window tkwin, int x, int y,
+ int width, int height);
+/* 128 */
+EXTERN void Tk_MoveWindow(Tk_Window tkwin, int x, int y);
+/* 129 */
+EXTERN void Tk_MoveToplevelWindow(Tk_Window tkwin, int x, int y);
+/* 130 */
+EXTERN CONST84_RETURN char * Tk_NameOf3DBorder(Tk_3DBorder border);
+/* 131 */
+EXTERN CONST84_RETURN char * Tk_NameOfAnchor(Tk_Anchor anchor);
+/* 132 */
+EXTERN CONST84_RETURN char * Tk_NameOfBitmap(Display *display, Pixmap bitmap);
+/* 133 */
+EXTERN CONST84_RETURN char * Tk_NameOfCapStyle(int cap);
+/* 134 */
+EXTERN CONST84_RETURN char * Tk_NameOfColor(XColor *colorPtr);
+/* 135 */
+EXTERN CONST84_RETURN char * Tk_NameOfCursor(Display *display,
+ Tk_Cursor cursor);
+/* 136 */
+EXTERN CONST84_RETURN char * Tk_NameOfFont(Tk_Font font);
+/* 137 */
+EXTERN CONST84_RETURN char * Tk_NameOfImage(Tk_ImageMaster imageMaster);
+/* 138 */
+EXTERN CONST84_RETURN char * Tk_NameOfJoinStyle(int join);
+/* 139 */
+EXTERN CONST84_RETURN char * Tk_NameOfJustify(Tk_Justify justify);
+/* 140 */
+EXTERN CONST84_RETURN char * Tk_NameOfRelief(int relief);
+/* 141 */
+EXTERN Tk_Window Tk_NameToWindow(Tcl_Interp *interp,
+ const char *pathName, Tk_Window tkwin);
+/* 142 */
+EXTERN void Tk_OwnSelection(Tk_Window tkwin, Atom selection,
+ Tk_LostSelProc *proc, ClientData clientData);
+/* 143 */
+EXTERN int Tk_ParseArgv(Tcl_Interp *interp, Tk_Window tkwin,
+ int *argcPtr, CONST84 char **argv,
+ const Tk_ArgvInfo *argTable, int flags);
+/* 144 */
+EXTERN void Tk_PhotoPutBlock_NoComposite(Tk_PhotoHandle handle,
+ Tk_PhotoImageBlock *blockPtr, int x, int y,
+ int width, int height);
+/* 145 */
+EXTERN void Tk_PhotoPutZoomedBlock_NoComposite(
+ Tk_PhotoHandle handle,
+ Tk_PhotoImageBlock *blockPtr, int x, int y,
+ int width, int height, int zoomX, int zoomY,
+ int subsampleX, int subsampleY);
+/* 146 */
+EXTERN int Tk_PhotoGetImage(Tk_PhotoHandle handle,
+ Tk_PhotoImageBlock *blockPtr);
+/* 147 */
+EXTERN void Tk_PhotoBlank(Tk_PhotoHandle handle);
+/* 148 */
+EXTERN void Tk_PhotoExpand_Panic(Tk_PhotoHandle handle,
+ int width, int height);
+/* 149 */
+EXTERN void Tk_PhotoGetSize(Tk_PhotoHandle handle, int *widthPtr,
+ int *heightPtr);
+/* 150 */
+EXTERN void Tk_PhotoSetSize_Panic(Tk_PhotoHandle handle,
+ int width, int height);
+/* 151 */
+EXTERN int Tk_PointToChar(Tk_TextLayout layout, int x, int y);
+/* 152 */
+EXTERN int Tk_PostscriptFontName(Tk_Font tkfont,
+ Tcl_DString *dsPtr);
+/* 153 */
+EXTERN void Tk_PreserveColormap(Display *display,
+ Colormap colormap);
+/* 154 */
+EXTERN void Tk_QueueWindowEvent(XEvent *eventPtr,
+ Tcl_QueuePosition position);
+/* 155 */
+EXTERN void Tk_RedrawImage(Tk_Image image, int imageX,
+ int imageY, int width, int height,
+ Drawable drawable, int drawableX,
+ int drawableY);
+/* 156 */
+EXTERN void Tk_ResizeWindow(Tk_Window tkwin, int width,
+ int height);
+/* 157 */
+EXTERN int Tk_RestackWindow(Tk_Window tkwin, int aboveBelow,
+ Tk_Window other);
+/* 158 */
+EXTERN Tk_RestrictProc * Tk_RestrictEvents(Tk_RestrictProc *proc,
+ ClientData arg, ClientData *prevArgPtr);
+/* 159 */
+EXTERN int Tk_SafeInit(Tcl_Interp *interp);
+/* 160 */
+EXTERN const char * Tk_SetAppName(Tk_Window tkwin, const char *name);
+/* 161 */
+EXTERN void Tk_SetBackgroundFromBorder(Tk_Window tkwin,
+ Tk_3DBorder border);
+/* 162 */
+EXTERN void Tk_SetClass(Tk_Window tkwin, const char *className);
+/* 163 */
+EXTERN void Tk_SetGrid(Tk_Window tkwin, int reqWidth,
+ int reqHeight, int gridWidth, int gridHeight);
+/* 164 */
+EXTERN void Tk_SetInternalBorder(Tk_Window tkwin, int width);
+/* 165 */
+EXTERN void Tk_SetWindowBackground(Tk_Window tkwin,
+ unsigned long pixel);
+/* 166 */
+EXTERN void Tk_SetWindowBackgroundPixmap(Tk_Window tkwin,
+ Pixmap pixmap);
+/* 167 */
+EXTERN void Tk_SetWindowBorder(Tk_Window tkwin,
+ unsigned long pixel);
+/* 168 */
+EXTERN void Tk_SetWindowBorderWidth(Tk_Window tkwin, int width);
+/* 169 */
+EXTERN void Tk_SetWindowBorderPixmap(Tk_Window tkwin,
+ Pixmap pixmap);
+/* 170 */
+EXTERN void Tk_SetWindowColormap(Tk_Window tkwin,
+ Colormap colormap);
+/* 171 */
+EXTERN int Tk_SetWindowVisual(Tk_Window tkwin, Visual *visual,
+ int depth, Colormap colormap);
+/* 172 */
+EXTERN void Tk_SizeOfBitmap(Display *display, Pixmap bitmap,
+ int *widthPtr, int *heightPtr);
+/* 173 */
+EXTERN void Tk_SizeOfImage(Tk_Image image, int *widthPtr,
+ int *heightPtr);
+/* 174 */
+EXTERN int Tk_StrictMotif(Tk_Window tkwin);
+/* 175 */
+EXTERN void Tk_TextLayoutToPostscript(Tcl_Interp *interp,
+ Tk_TextLayout layout);
+/* 176 */
+EXTERN int Tk_TextWidth(Tk_Font font, const char *str,
+ int numBytes);
+/* 177 */
+EXTERN void Tk_UndefineCursor(Tk_Window window);
+/* 178 */
+EXTERN void Tk_UnderlineChars(Display *display,
+ Drawable drawable, GC gc, Tk_Font tkfont,
+ const char *source, int x, int y,
+ int firstByte, int lastByte);
+/* 179 */
+EXTERN void Tk_UnderlineTextLayout(Display *display,
+ Drawable drawable, GC gc,
+ Tk_TextLayout layout, int x, int y,
+ int underline);
+/* 180 */
+EXTERN void Tk_Ungrab(Tk_Window tkwin);
+/* 181 */
+EXTERN void Tk_UnmaintainGeometry(Tk_Window slave,
+ Tk_Window master);
+/* 182 */
+EXTERN void Tk_UnmapWindow(Tk_Window tkwin);
+/* 183 */
+EXTERN void Tk_UnsetGrid(Tk_Window tkwin);
+/* 184 */
+EXTERN void Tk_UpdatePointer(Tk_Window tkwin, int x, int y,
+ int state);
+/* 185 */
+EXTERN Pixmap Tk_AllocBitmapFromObj(Tcl_Interp *interp,
+ Tk_Window tkwin, Tcl_Obj *objPtr);
+/* 186 */
+EXTERN Tk_3DBorder Tk_Alloc3DBorderFromObj(Tcl_Interp *interp,
+ Tk_Window tkwin, Tcl_Obj *objPtr);
+/* 187 */
+EXTERN XColor * Tk_AllocColorFromObj(Tcl_Interp *interp,
+ Tk_Window tkwin, Tcl_Obj *objPtr);
+/* 188 */
+EXTERN Tk_Cursor Tk_AllocCursorFromObj(Tcl_Interp *interp,
+ Tk_Window tkwin, Tcl_Obj *objPtr);
+/* 189 */
+EXTERN Tk_Font Tk_AllocFontFromObj(Tcl_Interp *interp,
+ Tk_Window tkwin, Tcl_Obj *objPtr);
+/* 190 */
+EXTERN Tk_OptionTable Tk_CreateOptionTable(Tcl_Interp *interp,
+ const Tk_OptionSpec *templatePtr);
+/* 191 */
+EXTERN void Tk_DeleteOptionTable(Tk_OptionTable optionTable);
+/* 192 */
+EXTERN void Tk_Free3DBorderFromObj(Tk_Window tkwin,
+ Tcl_Obj *objPtr);
+/* 193 */
+EXTERN void Tk_FreeBitmapFromObj(Tk_Window tkwin,
+ Tcl_Obj *objPtr);
+/* 194 */
+EXTERN void Tk_FreeColorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr);
+/* 195 */
+EXTERN void Tk_FreeConfigOptions(char *recordPtr,
+ Tk_OptionTable optionToken, Tk_Window tkwin);
+/* 196 */
+EXTERN void Tk_FreeSavedOptions(Tk_SavedOptions *savePtr);
+/* 197 */
+EXTERN void Tk_FreeCursorFromObj(Tk_Window tkwin,
+ Tcl_Obj *objPtr);
+/* 198 */
+EXTERN void Tk_FreeFontFromObj(Tk_Window tkwin, Tcl_Obj *objPtr);
+/* 199 */
+EXTERN Tk_3DBorder Tk_Get3DBorderFromObj(Tk_Window tkwin,
+ Tcl_Obj *objPtr);
+/* 200 */
+EXTERN int Tk_GetAnchorFromObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, Tk_Anchor *anchorPtr);
+/* 201 */
+EXTERN Pixmap Tk_GetBitmapFromObj(Tk_Window tkwin, Tcl_Obj *objPtr);
+/* 202 */
+EXTERN XColor * Tk_GetColorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr);
+/* 203 */
+EXTERN Tk_Cursor Tk_GetCursorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr);
+/* 204 */
+EXTERN Tcl_Obj * Tk_GetOptionInfo(Tcl_Interp *interp, char *recordPtr,
+ Tk_OptionTable optionTable, Tcl_Obj *namePtr,
+ Tk_Window tkwin);
+/* 205 */
+EXTERN Tcl_Obj * Tk_GetOptionValue(Tcl_Interp *interp,
+ char *recordPtr, Tk_OptionTable optionTable,
+ Tcl_Obj *namePtr, Tk_Window tkwin);
+/* 206 */
+EXTERN int Tk_GetJustifyFromObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, Tk_Justify *justifyPtr);
+/* 207 */
+EXTERN int Tk_GetMMFromObj(Tcl_Interp *interp, Tk_Window tkwin,
+ Tcl_Obj *objPtr, double *doublePtr);
+/* 208 */
+EXTERN int Tk_GetPixelsFromObj(Tcl_Interp *interp,
+ Tk_Window tkwin, Tcl_Obj *objPtr,
+ int *intPtr);
+/* 209 */
+EXTERN int Tk_GetReliefFromObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, int *resultPtr);
+/* 210 */
+EXTERN int Tk_GetScrollInfoObj(Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[], double *dblPtr,
+ int *intPtr);
+/* 211 */
+EXTERN int Tk_InitOptions(Tcl_Interp *interp, char *recordPtr,
+ Tk_OptionTable optionToken, Tk_Window tkwin);
+/* 212 */
+EXTERN void Tk_MainEx(int argc, char **argv,
+ Tcl_AppInitProc *appInitProc,
+ Tcl_Interp *interp);
+/* 213 */
+EXTERN void Tk_RestoreSavedOptions(Tk_SavedOptions *savePtr);
+/* 214 */
+EXTERN int Tk_SetOptions(Tcl_Interp *interp, char *recordPtr,
+ Tk_OptionTable optionTable, int objc,
+ Tcl_Obj *const objv[], Tk_Window tkwin,
+ Tk_SavedOptions *savePtr, int *maskPtr);
+/* 215 */
+EXTERN void Tk_InitConsoleChannels(Tcl_Interp *interp);
+/* 216 */
+EXTERN int Tk_CreateConsoleWindow(Tcl_Interp *interp);
+/* 217 */
+EXTERN void Tk_CreateSmoothMethod(Tcl_Interp *interp,
+ const Tk_SmoothMethod *method);
+/* Slot 218 is reserved */
+/* Slot 219 is reserved */
+/* 220 */
+EXTERN int Tk_GetDash(Tcl_Interp *interp, const char *value,
+ Tk_Dash *dash);
+/* 221 */
+EXTERN void Tk_CreateOutline(Tk_Outline *outline);
+/* 222 */
+EXTERN void Tk_DeleteOutline(Display *display,
+ Tk_Outline *outline);
+/* 223 */
+EXTERN int Tk_ConfigOutlineGC(XGCValues *gcValues,
+ Tk_Canvas canvas, Tk_Item *item,
+ Tk_Outline *outline);
+/* 224 */
+EXTERN int Tk_ChangeOutlineGC(Tk_Canvas canvas, Tk_Item *item,
+ Tk_Outline *outline);
+/* 225 */
+EXTERN int Tk_ResetOutlineGC(Tk_Canvas canvas, Tk_Item *item,
+ Tk_Outline *outline);
+/* 226 */
+EXTERN int Tk_CanvasPsOutline(Tk_Canvas canvas, Tk_Item *item,
+ Tk_Outline *outline);
+/* 227 */
+EXTERN void Tk_SetTSOrigin(Tk_Window tkwin, GC gc, int x, int y);
+/* 228 */
+EXTERN int Tk_CanvasGetCoordFromObj(Tcl_Interp *interp,
+ Tk_Canvas canvas, Tcl_Obj *obj,
+ double *doublePtr);
+/* 229 */
+EXTERN void Tk_CanvasSetOffset(Tk_Canvas canvas, GC gc,
+ Tk_TSOffset *offset);
+/* 230 */
+EXTERN void Tk_DitherPhoto(Tk_PhotoHandle handle, int x, int y,
+ int width, int height);
+/* 231 */
+EXTERN int Tk_PostscriptBitmap(Tcl_Interp *interp,
+ Tk_Window tkwin, Tk_PostscriptInfo psInfo,
+ Pixmap bitmap, int startX, int startY,
+ int width, int height);
+/* 232 */
+EXTERN int Tk_PostscriptColor(Tcl_Interp *interp,
+ Tk_PostscriptInfo psInfo, XColor *colorPtr);
+/* 233 */
+EXTERN int Tk_PostscriptFont(Tcl_Interp *interp,
+ Tk_PostscriptInfo psInfo, Tk_Font font);
+/* 234 */
+EXTERN int Tk_PostscriptImage(Tk_Image image,
+ Tcl_Interp *interp, Tk_Window tkwin,
+ Tk_PostscriptInfo psinfo, int x, int y,
+ int width, int height, int prepass);
+/* 235 */
+EXTERN void Tk_PostscriptPath(Tcl_Interp *interp,
+ Tk_PostscriptInfo psInfo, double *coordPtr,
+ int numPoints);
+/* 236 */
+EXTERN int Tk_PostscriptStipple(Tcl_Interp *interp,
+ Tk_Window tkwin, Tk_PostscriptInfo psInfo,
+ Pixmap bitmap);
+/* 237 */
+EXTERN double Tk_PostscriptY(double y, Tk_PostscriptInfo psInfo);
+/* 238 */
+EXTERN int Tk_PostscriptPhoto(Tcl_Interp *interp,
+ Tk_PhotoImageBlock *blockPtr,
+ Tk_PostscriptInfo psInfo, int width,
+ int height);
+/* 239 */
+EXTERN void Tk_CreateClientMessageHandler(
+ Tk_ClientMessageProc *proc);
+/* 240 */
+EXTERN void Tk_DeleteClientMessageHandler(
+ Tk_ClientMessageProc *proc);
+/* 241 */
+EXTERN Tk_Window Tk_CreateAnonymousWindow(Tcl_Interp *interp,
+ Tk_Window parent, const char *screenName);
+/* 242 */
+EXTERN void Tk_SetClassProcs(Tk_Window tkwin,
+ const Tk_ClassProcs *procs,
+ ClientData instanceData);
+/* 243 */
+EXTERN void Tk_SetInternalBorderEx(Tk_Window tkwin, int left,
+ int right, int top, int bottom);
+/* 244 */
+EXTERN void Tk_SetMinimumRequestSize(Tk_Window tkwin,
+ int minWidth, int minHeight);
+/* 245 */
+EXTERN void Tk_SetCaretPos(Tk_Window tkwin, int x, int y,
+ int height);
+/* 246 */
+EXTERN void Tk_PhotoPutBlock_Panic(Tk_PhotoHandle handle,
+ Tk_PhotoImageBlock *blockPtr, int x, int y,
+ int width, int height, int compRule);
+/* 247 */
+EXTERN void Tk_PhotoPutZoomedBlock_Panic(Tk_PhotoHandle handle,
+ Tk_PhotoImageBlock *blockPtr, int x, int y,
+ int width, int height, int zoomX, int zoomY,
+ int subsampleX, int subsampleY, int compRule);
+/* 248 */
+EXTERN int Tk_CollapseMotionEvents(Display *display,
+ int collapse);
+/* 249 */
+EXTERN Tk_StyleEngine Tk_RegisterStyleEngine(const char *name,
+ Tk_StyleEngine parent);
+/* 250 */
+EXTERN Tk_StyleEngine Tk_GetStyleEngine(const char *name);
+/* 251 */
+EXTERN int Tk_RegisterStyledElement(Tk_StyleEngine engine,
+ Tk_ElementSpec *templatePtr);
+/* 252 */
+EXTERN int Tk_GetElementId(const char *name);
+/* 253 */
+EXTERN Tk_Style Tk_CreateStyle(const char *name,
+ Tk_StyleEngine engine, ClientData clientData);
+/* 254 */
+EXTERN Tk_Style Tk_GetStyle(Tcl_Interp *interp, const char *name);
+/* 255 */
+EXTERN void Tk_FreeStyle(Tk_Style style);
+/* 256 */
+EXTERN const char * Tk_NameOfStyle(Tk_Style style);
+/* 257 */
+EXTERN Tk_Style Tk_AllocStyleFromObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr);
+/* 258 */
+EXTERN Tk_Style Tk_GetStyleFromObj(Tcl_Obj *objPtr);
+/* 259 */
+EXTERN void Tk_FreeStyleFromObj(Tcl_Obj *objPtr);
+/* 260 */
+EXTERN Tk_StyledElement Tk_GetStyledElement(Tk_Style style, int elementId,
+ Tk_OptionTable optionTable);
+/* 261 */
+EXTERN void Tk_GetElementSize(Tk_Style style,
+ Tk_StyledElement element, char *recordPtr,
+ Tk_Window tkwin, int width, int height,
+ int inner, int *widthPtr, int *heightPtr);
+/* 262 */
+EXTERN void Tk_GetElementBox(Tk_Style style,
+ Tk_StyledElement element, char *recordPtr,
+ Tk_Window tkwin, int x, int y, int width,
+ int height, int inner, int *xPtr, int *yPtr,
+ int *widthPtr, int *heightPtr);
+/* 263 */
+EXTERN int Tk_GetElementBorderWidth(Tk_Style style,
+ Tk_StyledElement element, char *recordPtr,
+ Tk_Window tkwin);
+/* 264 */
+EXTERN void Tk_DrawElement(Tk_Style style,
+ Tk_StyledElement element, char *recordPtr,
+ Tk_Window tkwin, Drawable d, int x, int y,
+ int width, int height, int state);
+/* 265 */
+EXTERN int Tk_PhotoExpand(Tcl_Interp *interp,
+ Tk_PhotoHandle handle, int width, int height);
+/* 266 */
+EXTERN int Tk_PhotoPutBlock(Tcl_Interp *interp,
+ Tk_PhotoHandle handle,
+ Tk_PhotoImageBlock *blockPtr, int x, int y,
+ int width, int height, int compRule);
+/* 267 */
+EXTERN int Tk_PhotoPutZoomedBlock(Tcl_Interp *interp,
+ Tk_PhotoHandle handle,
+ Tk_PhotoImageBlock *blockPtr, int x, int y,
+ int width, int height, int zoomX, int zoomY,
+ int subsampleX, int subsampleY, int compRule);
+/* 268 */
+EXTERN int Tk_PhotoSetSize(Tcl_Interp *interp,
+ Tk_PhotoHandle handle, int width, int height);
+/* 269 */
+EXTERN long Tk_GetUserInactiveTime(Display *dpy);
+/* 270 */
+EXTERN void Tk_ResetUserInactiveTime(Display *dpy);
+/* 271 */
+EXTERN Tcl_Interp * Tk_Interp(Tk_Window tkwin);
+/* 272 */
+EXTERN void Tk_CreateOldImageType(const Tk_ImageType *typePtr);
+/* 273 */
+EXTERN void Tk_CreateOldPhotoImageFormat(
+ const Tk_PhotoImageFormat *formatPtr);
+
+typedef struct {
+ const struct TkPlatStubs *tkPlatStubs;
+ const struct TkIntStubs *tkIntStubs;
+ const struct TkIntPlatStubs *tkIntPlatStubs;
+ const struct TkIntXlibStubs *tkIntXlibStubs;
+} TkStubHooks;
+
+typedef struct TkStubs {
+ int magic;
+ const TkStubHooks *hooks;
+
+ void (*tk_MainLoop) (void); /* 0 */
+ XColor * (*tk_3DBorderColor) (Tk_3DBorder border); /* 1 */
+ GC (*tk_3DBorderGC) (Tk_Window tkwin, Tk_3DBorder border, int which); /* 2 */
+ void (*tk_3DHorizontalBevel) (Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, int x, int y, int width, int height, int leftIn, int rightIn, int topBevel, int relief); /* 3 */
+ void (*tk_3DVerticalBevel) (Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, int x, int y, int width, int height, int leftBevel, int relief); /* 4 */
+ void (*tk_AddOption) (Tk_Window tkwin, const char *name, const char *value, int priority); /* 5 */
+ void (*tk_BindEvent) (Tk_BindingTable bindingTable, XEvent *eventPtr, Tk_Window tkwin, int numObjects, ClientData *objectPtr); /* 6 */
+ void (*tk_CanvasDrawableCoords) (Tk_Canvas canvas, double x, double y, short *drawableXPtr, short *drawableYPtr); /* 7 */
+ void (*tk_CanvasEventuallyRedraw) (Tk_Canvas canvas, int x1, int y1, int x2, int y2); /* 8 */
+ int (*tk_CanvasGetCoord) (Tcl_Interp *interp, Tk_Canvas canvas, const char *str, double *doublePtr); /* 9 */
+ Tk_CanvasTextInfo * (*tk_CanvasGetTextInfo) (Tk_Canvas canvas); /* 10 */
+ int (*tk_CanvasPsBitmap) (Tcl_Interp *interp, Tk_Canvas canvas, Pixmap bitmap, int x, int y, int width, int height); /* 11 */
+ int (*tk_CanvasPsColor) (Tcl_Interp *interp, Tk_Canvas canvas, XColor *colorPtr); /* 12 */
+ int (*tk_CanvasPsFont) (Tcl_Interp *interp, Tk_Canvas canvas, Tk_Font font); /* 13 */
+ void (*tk_CanvasPsPath) (Tcl_Interp *interp, Tk_Canvas canvas, double *coordPtr, int numPoints); /* 14 */
+ int (*tk_CanvasPsStipple) (Tcl_Interp *interp, Tk_Canvas canvas, Pixmap bitmap); /* 15 */
+ double (*tk_CanvasPsY) (Tk_Canvas canvas, double y); /* 16 */
+ void (*tk_CanvasSetStippleOrigin) (Tk_Canvas canvas, GC gc); /* 17 */
+ int (*tk_CanvasTagsParseProc) (ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset); /* 18 */
+ CONST86 char * (*tk_CanvasTagsPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 19 */
+ Tk_Window (*tk_CanvasTkwin) (Tk_Canvas canvas); /* 20 */
+ void (*tk_CanvasWindowCoords) (Tk_Canvas canvas, double x, double y, short *screenXPtr, short *screenYPtr); /* 21 */
+ void (*tk_ChangeWindowAttributes) (Tk_Window tkwin, unsigned long valueMask, XSetWindowAttributes *attsPtr); /* 22 */
+ int (*tk_CharBbox) (Tk_TextLayout layout, int index, int *xPtr, int *yPtr, int *widthPtr, int *heightPtr); /* 23 */
+ void (*tk_ClearSelection) (Tk_Window tkwin, Atom selection); /* 24 */
+ int (*tk_ClipboardAppend) (Tcl_Interp *interp, Tk_Window tkwin, Atom target, Atom format, const char *buffer); /* 25 */
+ int (*tk_ClipboardClear) (Tcl_Interp *interp, Tk_Window tkwin); /* 26 */
+ int (*tk_ConfigureInfo) (Tcl_Interp *interp, Tk_Window tkwin, const Tk_ConfigSpec *specs, char *widgRec, const char *argvName, int flags); /* 27 */
+ int (*tk_ConfigureValue) (Tcl_Interp *interp, Tk_Window tkwin, const Tk_ConfigSpec *specs, char *widgRec, const char *argvName, int flags); /* 28 */
+ int (*tk_ConfigureWidget) (Tcl_Interp *interp, Tk_Window tkwin, const Tk_ConfigSpec *specs, int argc, CONST84 char **argv, char *widgRec, int flags); /* 29 */
+ void (*tk_ConfigureWindow) (Tk_Window tkwin, unsigned int valueMask, XWindowChanges *valuePtr); /* 30 */
+ Tk_TextLayout (*tk_ComputeTextLayout) (Tk_Font font, const char *str, int numChars, int wrapLength, Tk_Justify justify, int flags, int *widthPtr, int *heightPtr); /* 31 */
+ Tk_Window (*tk_CoordsToWindow) (int rootX, int rootY, Tk_Window tkwin); /* 32 */
+ unsigned long (*tk_CreateBinding) (Tcl_Interp *interp, Tk_BindingTable bindingTable, ClientData object, const char *eventStr, const char *script, int append); /* 33 */
+ Tk_BindingTable (*tk_CreateBindingTable) (Tcl_Interp *interp); /* 34 */
+ Tk_ErrorHandler (*tk_CreateErrorHandler) (Display *display, int errNum, int request, int minorCode, Tk_ErrorProc *errorProc, ClientData clientData); /* 35 */
+ void (*tk_CreateEventHandler) (Tk_Window token, unsigned long mask, Tk_EventProc *proc, ClientData clientData); /* 36 */
+ void (*tk_CreateGenericHandler) (Tk_GenericProc *proc, ClientData clientData); /* 37 */
+ void (*tk_CreateImageType) (const Tk_ImageType *typePtr); /* 38 */
+ void (*tk_CreateItemType) (Tk_ItemType *typePtr); /* 39 */
+ void (*tk_CreatePhotoImageFormat) (const Tk_PhotoImageFormat *formatPtr); /* 40 */
+ void (*tk_CreateSelHandler) (Tk_Window tkwin, Atom selection, Atom target, Tk_SelectionProc *proc, ClientData clientData, Atom format); /* 41 */
+ Tk_Window (*tk_CreateWindow) (Tcl_Interp *interp, Tk_Window parent, const char *name, const char *screenName); /* 42 */
+ Tk_Window (*tk_CreateWindowFromPath) (Tcl_Interp *interp, Tk_Window tkwin, const char *pathName, const char *screenName); /* 43 */
+ int (*tk_DefineBitmap) (Tcl_Interp *interp, const char *name, const void *source, int width, int height); /* 44 */
+ void (*tk_DefineCursor) (Tk_Window window, Tk_Cursor cursor); /* 45 */
+ void (*tk_DeleteAllBindings) (Tk_BindingTable bindingTable, ClientData object); /* 46 */
+ int (*tk_DeleteBinding) (Tcl_Interp *interp, Tk_BindingTable bindingTable, ClientData object, const char *eventStr); /* 47 */
+ void (*tk_DeleteBindingTable) (Tk_BindingTable bindingTable); /* 48 */
+ void (*tk_DeleteErrorHandler) (Tk_ErrorHandler handler); /* 49 */
+ void (*tk_DeleteEventHandler) (Tk_Window token, unsigned long mask, Tk_EventProc *proc, ClientData clientData); /* 50 */
+ void (*tk_DeleteGenericHandler) (Tk_GenericProc *proc, ClientData clientData); /* 51 */
+ void (*tk_DeleteImage) (Tcl_Interp *interp, const char *name); /* 52 */
+ void (*tk_DeleteSelHandler) (Tk_Window tkwin, Atom selection, Atom target); /* 53 */
+ void (*tk_DestroyWindow) (Tk_Window tkwin); /* 54 */
+ CONST84_RETURN char * (*tk_DisplayName) (Tk_Window tkwin); /* 55 */
+ int (*tk_DistanceToTextLayout) (Tk_TextLayout layout, int x, int y); /* 56 */
+ void (*tk_Draw3DPolygon) (Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, XPoint *pointPtr, int numPoints, int borderWidth, int leftRelief); /* 57 */
+ void (*tk_Draw3DRectangle) (Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, int x, int y, int width, int height, int borderWidth, int relief); /* 58 */
+ void (*tk_DrawChars) (Display *display, Drawable drawable, GC gc, Tk_Font tkfont, const char *source, int numBytes, int x, int y); /* 59 */
+ void (*tk_DrawFocusHighlight) (Tk_Window tkwin, GC gc, int width, Drawable drawable); /* 60 */
+ void (*tk_DrawTextLayout) (Display *display, Drawable drawable, GC gc, Tk_TextLayout layout, int x, int y, int firstChar, int lastChar); /* 61 */
+ void (*tk_Fill3DPolygon) (Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, XPoint *pointPtr, int numPoints, int borderWidth, int leftRelief); /* 62 */
+ void (*tk_Fill3DRectangle) (Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, int x, int y, int width, int height, int borderWidth, int relief); /* 63 */
+ Tk_PhotoHandle (*tk_FindPhoto) (Tcl_Interp *interp, const char *imageName); /* 64 */
+ Font (*tk_FontId) (Tk_Font font); /* 65 */
+ void (*tk_Free3DBorder) (Tk_3DBorder border); /* 66 */
+ void (*tk_FreeBitmap) (Display *display, Pixmap bitmap); /* 67 */
+ void (*tk_FreeColor) (XColor *colorPtr); /* 68 */
+ void (*tk_FreeColormap) (Display *display, Colormap colormap); /* 69 */
+ void (*tk_FreeCursor) (Display *display, Tk_Cursor cursor); /* 70 */
+ void (*tk_FreeFont) (Tk_Font f); /* 71 */
+ void (*tk_FreeGC) (Display *display, GC gc); /* 72 */
+ void (*tk_FreeImage) (Tk_Image image); /* 73 */
+ void (*tk_FreeOptions) (const Tk_ConfigSpec *specs, char *widgRec, Display *display, int needFlags); /* 74 */
+ void (*tk_FreePixmap) (Display *display, Pixmap pixmap); /* 75 */
+ void (*tk_FreeTextLayout) (Tk_TextLayout textLayout); /* 76 */
+ void (*tk_FreeXId) (Display *display, XID xid); /* 77 */
+ GC (*tk_GCForColor) (XColor *colorPtr, Drawable drawable); /* 78 */
+ void (*tk_GeometryRequest) (Tk_Window tkwin, int reqWidth, int reqHeight); /* 79 */
+ Tk_3DBorder (*tk_Get3DBorder) (Tcl_Interp *interp, Tk_Window tkwin, Tk_Uid colorName); /* 80 */
+ void (*tk_GetAllBindings) (Tcl_Interp *interp, Tk_BindingTable bindingTable, ClientData object); /* 81 */
+ int (*tk_GetAnchor) (Tcl_Interp *interp, const char *str, Tk_Anchor *anchorPtr); /* 82 */
+ CONST84_RETURN char * (*tk_GetAtomName) (Tk_Window tkwin, Atom atom); /* 83 */
+ CONST84_RETURN char * (*tk_GetBinding) (Tcl_Interp *interp, Tk_BindingTable bindingTable, ClientData object, const char *eventStr); /* 84 */
+ Pixmap (*tk_GetBitmap) (Tcl_Interp *interp, Tk_Window tkwin, const char *str); /* 85 */
+ Pixmap (*tk_GetBitmapFromData) (Tcl_Interp *interp, Tk_Window tkwin, const void *source, int width, int height); /* 86 */
+ int (*tk_GetCapStyle) (Tcl_Interp *interp, const char *str, int *capPtr); /* 87 */
+ XColor * (*tk_GetColor) (Tcl_Interp *interp, Tk_Window tkwin, Tk_Uid name); /* 88 */
+ XColor * (*tk_GetColorByValue) (Tk_Window tkwin, XColor *colorPtr); /* 89 */
+ Colormap (*tk_GetColormap) (Tcl_Interp *interp, Tk_Window tkwin, const char *str); /* 90 */
+ Tk_Cursor (*tk_GetCursor) (Tcl_Interp *interp, Tk_Window tkwin, Tk_Uid str); /* 91 */
+ Tk_Cursor (*tk_GetCursorFromData) (Tcl_Interp *interp, Tk_Window tkwin, const char *source, const char *mask, int width, int height, int xHot, int yHot, Tk_Uid fg, Tk_Uid bg); /* 92 */
+ Tk_Font (*tk_GetFont) (Tcl_Interp *interp, Tk_Window tkwin, const char *str); /* 93 */
+ Tk_Font (*tk_GetFontFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 94 */
+ void (*tk_GetFontMetrics) (Tk_Font font, Tk_FontMetrics *fmPtr); /* 95 */
+ GC (*tk_GetGC) (Tk_Window tkwin, unsigned long valueMask, XGCValues *valuePtr); /* 96 */
+ Tk_Image (*tk_GetImage) (Tcl_Interp *interp, Tk_Window tkwin, const char *name, Tk_ImageChangedProc *changeProc, ClientData clientData); /* 97 */
+ ClientData (*tk_GetImageMasterData) (Tcl_Interp *interp, const char *name, CONST86 Tk_ImageType **typePtrPtr); /* 98 */
+ Tk_ItemType * (*tk_GetItemTypes) (void); /* 99 */
+ int (*tk_GetJoinStyle) (Tcl_Interp *interp, const char *str, int *joinPtr); /* 100 */
+ int (*tk_GetJustify) (Tcl_Interp *interp, const char *str, Tk_Justify *justifyPtr); /* 101 */
+ int (*tk_GetNumMainWindows) (void); /* 102 */
+ Tk_Uid (*tk_GetOption) (Tk_Window tkwin, const char *name, const char *className); /* 103 */
+ int (*tk_GetPixels) (Tcl_Interp *interp, Tk_Window tkwin, const char *str, int *intPtr); /* 104 */
+ Pixmap (*tk_GetPixmap) (Display *display, Drawable d, int width, int height, int depth); /* 105 */
+ int (*tk_GetRelief) (Tcl_Interp *interp, const char *name, int *reliefPtr); /* 106 */
+ void (*tk_GetRootCoords) (Tk_Window tkwin, int *xPtr, int *yPtr); /* 107 */
+ int (*tk_GetScrollInfo) (Tcl_Interp *interp, int argc, CONST84 char **argv, double *dblPtr, int *intPtr); /* 108 */
+ int (*tk_GetScreenMM) (Tcl_Interp *interp, Tk_Window tkwin, const char *str, double *doublePtr); /* 109 */
+ int (*tk_GetSelection) (Tcl_Interp *interp, Tk_Window tkwin, Atom selection, Atom target, Tk_GetSelProc *proc, ClientData clientData); /* 110 */
+ Tk_Uid (*tk_GetUid) (const char *str); /* 111 */
+ Visual * (*tk_GetVisual) (Tcl_Interp *interp, Tk_Window tkwin, const char *str, int *depthPtr, Colormap *colormapPtr); /* 112 */
+ void (*tk_GetVRootGeometry) (Tk_Window tkwin, int *xPtr, int *yPtr, int *widthPtr, int *heightPtr); /* 113 */
+ int (*tk_Grab) (Tcl_Interp *interp, Tk_Window tkwin, int grabGlobal); /* 114 */
+ void (*tk_HandleEvent) (XEvent *eventPtr); /* 115 */
+ Tk_Window (*tk_IdToWindow) (Display *display, Window window); /* 116 */
+ void (*tk_ImageChanged) (Tk_ImageMaster master, int x, int y, int width, int height, int imageWidth, int imageHeight); /* 117 */
+ int (*tk_Init) (Tcl_Interp *interp); /* 118 */
+ Atom (*tk_InternAtom) (Tk_Window tkwin, const char *name); /* 119 */
+ int (*tk_IntersectTextLayout) (Tk_TextLayout layout, int x, int y, int width, int height); /* 120 */
+ void (*tk_MaintainGeometry) (Tk_Window slave, Tk_Window master, int x, int y, int width, int height); /* 121 */
+ Tk_Window (*tk_MainWindow) (Tcl_Interp *interp); /* 122 */
+ void (*tk_MakeWindowExist) (Tk_Window tkwin); /* 123 */
+ void (*tk_ManageGeometry) (Tk_Window tkwin, const Tk_GeomMgr *mgrPtr, ClientData clientData); /* 124 */
+ void (*tk_MapWindow) (Tk_Window tkwin); /* 125 */
+ int (*tk_MeasureChars) (Tk_Font tkfont, const char *source, int numBytes, int maxPixels, int flags, int *lengthPtr); /* 126 */
+ void (*tk_MoveResizeWindow) (Tk_Window tkwin, int x, int y, int width, int height); /* 127 */
+ void (*tk_MoveWindow) (Tk_Window tkwin, int x, int y); /* 128 */
+ void (*tk_MoveToplevelWindow) (Tk_Window tkwin, int x, int y); /* 129 */
+ CONST84_RETURN char * (*tk_NameOf3DBorder) (Tk_3DBorder border); /* 130 */
+ CONST84_RETURN char * (*tk_NameOfAnchor) (Tk_Anchor anchor); /* 131 */
+ CONST84_RETURN char * (*tk_NameOfBitmap) (Display *display, Pixmap bitmap); /* 132 */
+ CONST84_RETURN char * (*tk_NameOfCapStyle) (int cap); /* 133 */
+ CONST84_RETURN char * (*tk_NameOfColor) (XColor *colorPtr); /* 134 */
+ CONST84_RETURN char * (*tk_NameOfCursor) (Display *display, Tk_Cursor cursor); /* 135 */
+ CONST84_RETURN char * (*tk_NameOfFont) (Tk_Font font); /* 136 */
+ CONST84_RETURN char * (*tk_NameOfImage) (Tk_ImageMaster imageMaster); /* 137 */
+ CONST84_RETURN char * (*tk_NameOfJoinStyle) (int join); /* 138 */
+ CONST84_RETURN char * (*tk_NameOfJustify) (Tk_Justify justify); /* 139 */
+ CONST84_RETURN char * (*tk_NameOfRelief) (int relief); /* 140 */
+ Tk_Window (*tk_NameToWindow) (Tcl_Interp *interp, const char *pathName, Tk_Window tkwin); /* 141 */
+ void (*tk_OwnSelection) (Tk_Window tkwin, Atom selection, Tk_LostSelProc *proc, ClientData clientData); /* 142 */
+ int (*tk_ParseArgv) (Tcl_Interp *interp, Tk_Window tkwin, int *argcPtr, CONST84 char **argv, const Tk_ArgvInfo *argTable, int flags); /* 143 */
+ void (*tk_PhotoPutBlock_NoComposite) (Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height); /* 144 */
+ void (*tk_PhotoPutZoomedBlock_NoComposite) (Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int zoomX, int zoomY, int subsampleX, int subsampleY); /* 145 */
+ int (*tk_PhotoGetImage) (Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr); /* 146 */
+ void (*tk_PhotoBlank) (Tk_PhotoHandle handle); /* 147 */
+ void (*tk_PhotoExpand_Panic) (Tk_PhotoHandle handle, int width, int height); /* 148 */
+ void (*tk_PhotoGetSize) (Tk_PhotoHandle handle, int *widthPtr, int *heightPtr); /* 149 */
+ void (*tk_PhotoSetSize_Panic) (Tk_PhotoHandle handle, int width, int height); /* 150 */
+ int (*tk_PointToChar) (Tk_TextLayout layout, int x, int y); /* 151 */
+ int (*tk_PostscriptFontName) (Tk_Font tkfont, Tcl_DString *dsPtr); /* 152 */
+ void (*tk_PreserveColormap) (Display *display, Colormap colormap); /* 153 */
+ void (*tk_QueueWindowEvent) (XEvent *eventPtr, Tcl_QueuePosition position); /* 154 */
+ void (*tk_RedrawImage) (Tk_Image image, int imageX, int imageY, int width, int height, Drawable drawable, int drawableX, int drawableY); /* 155 */
+ void (*tk_ResizeWindow) (Tk_Window tkwin, int width, int height); /* 156 */
+ int (*tk_RestackWindow) (Tk_Window tkwin, int aboveBelow, Tk_Window other); /* 157 */
+ Tk_RestrictProc * (*tk_RestrictEvents) (Tk_RestrictProc *proc, ClientData arg, ClientData *prevArgPtr); /* 158 */
+ int (*tk_SafeInit) (Tcl_Interp *interp); /* 159 */
+ const char * (*tk_SetAppName) (Tk_Window tkwin, const char *name); /* 160 */
+ void (*tk_SetBackgroundFromBorder) (Tk_Window tkwin, Tk_3DBorder border); /* 161 */
+ void (*tk_SetClass) (Tk_Window tkwin, const char *className); /* 162 */
+ void (*tk_SetGrid) (Tk_Window tkwin, int reqWidth, int reqHeight, int gridWidth, int gridHeight); /* 163 */
+ void (*tk_SetInternalBorder) (Tk_Window tkwin, int width); /* 164 */
+ void (*tk_SetWindowBackground) (Tk_Window tkwin, unsigned long pixel); /* 165 */
+ void (*tk_SetWindowBackgroundPixmap) (Tk_Window tkwin, Pixmap pixmap); /* 166 */
+ void (*tk_SetWindowBorder) (Tk_Window tkwin, unsigned long pixel); /* 167 */
+ void (*tk_SetWindowBorderWidth) (Tk_Window tkwin, int width); /* 168 */
+ void (*tk_SetWindowBorderPixmap) (Tk_Window tkwin, Pixmap pixmap); /* 169 */
+ void (*tk_SetWindowColormap) (Tk_Window tkwin, Colormap colormap); /* 170 */
+ int (*tk_SetWindowVisual) (Tk_Window tkwin, Visual *visual, int depth, Colormap colormap); /* 171 */
+ void (*tk_SizeOfBitmap) (Display *display, Pixmap bitmap, int *widthPtr, int *heightPtr); /* 172 */
+ void (*tk_SizeOfImage) (Tk_Image image, int *widthPtr, int *heightPtr); /* 173 */
+ int (*tk_StrictMotif) (Tk_Window tkwin); /* 174 */
+ void (*tk_TextLayoutToPostscript) (Tcl_Interp *interp, Tk_TextLayout layout); /* 175 */
+ int (*tk_TextWidth) (Tk_Font font, const char *str, int numBytes); /* 176 */
+ void (*tk_UndefineCursor) (Tk_Window window); /* 177 */
+ void (*tk_UnderlineChars) (Display *display, Drawable drawable, GC gc, Tk_Font tkfont, const char *source, int x, int y, int firstByte, int lastByte); /* 178 */
+ void (*tk_UnderlineTextLayout) (Display *display, Drawable drawable, GC gc, Tk_TextLayout layout, int x, int y, int underline); /* 179 */
+ void (*tk_Ungrab) (Tk_Window tkwin); /* 180 */
+ void (*tk_UnmaintainGeometry) (Tk_Window slave, Tk_Window master); /* 181 */
+ void (*tk_UnmapWindow) (Tk_Window tkwin); /* 182 */
+ void (*tk_UnsetGrid) (Tk_Window tkwin); /* 183 */
+ void (*tk_UpdatePointer) (Tk_Window tkwin, int x, int y, int state); /* 184 */
+ Pixmap (*tk_AllocBitmapFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr); /* 185 */
+ Tk_3DBorder (*tk_Alloc3DBorderFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr); /* 186 */
+ XColor * (*tk_AllocColorFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr); /* 187 */
+ Tk_Cursor (*tk_AllocCursorFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr); /* 188 */
+ Tk_Font (*tk_AllocFontFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr); /* 189 */
+ Tk_OptionTable (*tk_CreateOptionTable) (Tcl_Interp *interp, const Tk_OptionSpec *templatePtr); /* 190 */
+ void (*tk_DeleteOptionTable) (Tk_OptionTable optionTable); /* 191 */
+ void (*tk_Free3DBorderFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 192 */
+ void (*tk_FreeBitmapFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 193 */
+ void (*tk_FreeColorFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 194 */
+ void (*tk_FreeConfigOptions) (char *recordPtr, Tk_OptionTable optionToken, Tk_Window tkwin); /* 195 */
+ void (*tk_FreeSavedOptions) (Tk_SavedOptions *savePtr); /* 196 */
+ void (*tk_FreeCursorFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 197 */
+ void (*tk_FreeFontFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 198 */
+ Tk_3DBorder (*tk_Get3DBorderFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 199 */
+ int (*tk_GetAnchorFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tk_Anchor *anchorPtr); /* 200 */
+ Pixmap (*tk_GetBitmapFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 201 */
+ XColor * (*tk_GetColorFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 202 */
+ Tk_Cursor (*tk_GetCursorFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 203 */
+ Tcl_Obj * (*tk_GetOptionInfo) (Tcl_Interp *interp, char *recordPtr, Tk_OptionTable optionTable, Tcl_Obj *namePtr, Tk_Window tkwin); /* 204 */
+ Tcl_Obj * (*tk_GetOptionValue) (Tcl_Interp *interp, char *recordPtr, Tk_OptionTable optionTable, Tcl_Obj *namePtr, Tk_Window tkwin); /* 205 */
+ int (*tk_GetJustifyFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tk_Justify *justifyPtr); /* 206 */
+ int (*tk_GetMMFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, double *doublePtr); /* 207 */
+ int (*tk_GetPixelsFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, int *intPtr); /* 208 */
+ int (*tk_GetReliefFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *resultPtr); /* 209 */
+ int (*tk_GetScrollInfoObj) (Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], double *dblPtr, int *intPtr); /* 210 */
+ int (*tk_InitOptions) (Tcl_Interp *interp, char *recordPtr, Tk_OptionTable optionToken, Tk_Window tkwin); /* 211 */
+ void (*tk_MainEx) (int argc, char **argv, Tcl_AppInitProc *appInitProc, Tcl_Interp *interp); /* 212 */
+ void (*tk_RestoreSavedOptions) (Tk_SavedOptions *savePtr); /* 213 */
+ int (*tk_SetOptions) (Tcl_Interp *interp, char *recordPtr, Tk_OptionTable optionTable, int objc, Tcl_Obj *const objv[], Tk_Window tkwin, Tk_SavedOptions *savePtr, int *maskPtr); /* 214 */
+ void (*tk_InitConsoleChannels) (Tcl_Interp *interp); /* 215 */
+ int (*tk_CreateConsoleWindow) (Tcl_Interp *interp); /* 216 */
+ void (*tk_CreateSmoothMethod) (Tcl_Interp *interp, const Tk_SmoothMethod *method); /* 217 */
+ void (*reserved218)(void);
+ void (*reserved219)(void);
+ int (*tk_GetDash) (Tcl_Interp *interp, const char *value, Tk_Dash *dash); /* 220 */
+ void (*tk_CreateOutline) (Tk_Outline *outline); /* 221 */
+ void (*tk_DeleteOutline) (Display *display, Tk_Outline *outline); /* 222 */
+ int (*tk_ConfigOutlineGC) (XGCValues *gcValues, Tk_Canvas canvas, Tk_Item *item, Tk_Outline *outline); /* 223 */
+ int (*tk_ChangeOutlineGC) (Tk_Canvas canvas, Tk_Item *item, Tk_Outline *outline); /* 224 */
+ int (*tk_ResetOutlineGC) (Tk_Canvas canvas, Tk_Item *item, Tk_Outline *outline); /* 225 */
+ int (*tk_CanvasPsOutline) (Tk_Canvas canvas, Tk_Item *item, Tk_Outline *outline); /* 226 */
+ void (*tk_SetTSOrigin) (Tk_Window tkwin, GC gc, int x, int y); /* 227 */
+ int (*tk_CanvasGetCoordFromObj) (Tcl_Interp *interp, Tk_Canvas canvas, Tcl_Obj *obj, double *doublePtr); /* 228 */
+ void (*tk_CanvasSetOffset) (Tk_Canvas canvas, GC gc, Tk_TSOffset *offset); /* 229 */
+ void (*tk_DitherPhoto) (Tk_PhotoHandle handle, int x, int y, int width, int height); /* 230 */
+ int (*tk_PostscriptBitmap) (Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo psInfo, Pixmap bitmap, int startX, int startY, int width, int height); /* 231 */
+ int (*tk_PostscriptColor) (Tcl_Interp *interp, Tk_PostscriptInfo psInfo, XColor *colorPtr); /* 232 */
+ int (*tk_PostscriptFont) (Tcl_Interp *interp, Tk_PostscriptInfo psInfo, Tk_Font font); /* 233 */
+ int (*tk_PostscriptImage) (Tk_Image image, Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo psinfo, int x, int y, int width, int height, int prepass); /* 234 */
+ void (*tk_PostscriptPath) (Tcl_Interp *interp, Tk_PostscriptInfo psInfo, double *coordPtr, int numPoints); /* 235 */
+ int (*tk_PostscriptStipple) (Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo psInfo, Pixmap bitmap); /* 236 */
+ double (*tk_PostscriptY) (double y, Tk_PostscriptInfo psInfo); /* 237 */
+ int (*tk_PostscriptPhoto) (Tcl_Interp *interp, Tk_PhotoImageBlock *blockPtr, Tk_PostscriptInfo psInfo, int width, int height); /* 238 */
+ void (*tk_CreateClientMessageHandler) (Tk_ClientMessageProc *proc); /* 239 */
+ void (*tk_DeleteClientMessageHandler) (Tk_ClientMessageProc *proc); /* 240 */
+ Tk_Window (*tk_CreateAnonymousWindow) (Tcl_Interp *interp, Tk_Window parent, const char *screenName); /* 241 */
+ void (*tk_SetClassProcs) (Tk_Window tkwin, const Tk_ClassProcs *procs, ClientData instanceData); /* 242 */
+ void (*tk_SetInternalBorderEx) (Tk_Window tkwin, int left, int right, int top, int bottom); /* 243 */
+ void (*tk_SetMinimumRequestSize) (Tk_Window tkwin, int minWidth, int minHeight); /* 244 */
+ void (*tk_SetCaretPos) (Tk_Window tkwin, int x, int y, int height); /* 245 */
+ void (*tk_PhotoPutBlock_Panic) (Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int compRule); /* 246 */
+ void (*tk_PhotoPutZoomedBlock_Panic) (Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int zoomX, int zoomY, int subsampleX, int subsampleY, int compRule); /* 247 */
+ int (*tk_CollapseMotionEvents) (Display *display, int collapse); /* 248 */
+ Tk_StyleEngine (*tk_RegisterStyleEngine) (const char *name, Tk_StyleEngine parent); /* 249 */
+ Tk_StyleEngine (*tk_GetStyleEngine) (const char *name); /* 250 */
+ int (*tk_RegisterStyledElement) (Tk_StyleEngine engine, Tk_ElementSpec *templatePtr); /* 251 */
+ int (*tk_GetElementId) (const char *name); /* 252 */
+ Tk_Style (*tk_CreateStyle) (const char *name, Tk_StyleEngine engine, ClientData clientData); /* 253 */
+ Tk_Style (*tk_GetStyle) (Tcl_Interp *interp, const char *name); /* 254 */
+ void (*tk_FreeStyle) (Tk_Style style); /* 255 */
+ const char * (*tk_NameOfStyle) (Tk_Style style); /* 256 */
+ Tk_Style (*tk_AllocStyleFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr); /* 257 */
+ Tk_Style (*tk_GetStyleFromObj) (Tcl_Obj *objPtr); /* 258 */
+ void (*tk_FreeStyleFromObj) (Tcl_Obj *objPtr); /* 259 */
+ Tk_StyledElement (*tk_GetStyledElement) (Tk_Style style, int elementId, Tk_OptionTable optionTable); /* 260 */
+ void (*tk_GetElementSize) (Tk_Style style, Tk_StyledElement element, char *recordPtr, Tk_Window tkwin, int width, int height, int inner, int *widthPtr, int *heightPtr); /* 261 */
+ void (*tk_GetElementBox) (Tk_Style style, Tk_StyledElement element, char *recordPtr, Tk_Window tkwin, int x, int y, int width, int height, int inner, int *xPtr, int *yPtr, int *widthPtr, int *heightPtr); /* 262 */
+ int (*tk_GetElementBorderWidth) (Tk_Style style, Tk_StyledElement element, char *recordPtr, Tk_Window tkwin); /* 263 */
+ void (*tk_DrawElement) (Tk_Style style, Tk_StyledElement element, char *recordPtr, Tk_Window tkwin, Drawable d, int x, int y, int width, int height, int state); /* 264 */
+ int (*tk_PhotoExpand) (Tcl_Interp *interp, Tk_PhotoHandle handle, int width, int height); /* 265 */
+ int (*tk_PhotoPutBlock) (Tcl_Interp *interp, Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int compRule); /* 266 */
+ int (*tk_PhotoPutZoomedBlock) (Tcl_Interp *interp, Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int zoomX, int zoomY, int subsampleX, int subsampleY, int compRule); /* 267 */
+ int (*tk_PhotoSetSize) (Tcl_Interp *interp, Tk_PhotoHandle handle, int width, int height); /* 268 */
+ long (*tk_GetUserInactiveTime) (Display *dpy); /* 269 */
+ void (*tk_ResetUserInactiveTime) (Display *dpy); /* 270 */
+ Tcl_Interp * (*tk_Interp) (Tk_Window tkwin); /* 271 */
+ void (*tk_CreateOldImageType) (const Tk_ImageType *typePtr); /* 272 */
+ void (*tk_CreateOldPhotoImageFormat) (const Tk_PhotoImageFormat *formatPtr); /* 273 */
+} TkStubs;
+
+extern const TkStubs *tkStubsPtr;
+
+#ifdef __cplusplus
+}
+#endif
+
+#if defined(USE_TK_STUBS)
+
+/*
+ * Inline function declarations:
+ */
+
+#define Tk_MainLoop \
+ (tkStubsPtr->tk_MainLoop) /* 0 */
+#define Tk_3DBorderColor \
+ (tkStubsPtr->tk_3DBorderColor) /* 1 */
+#define Tk_3DBorderGC \
+ (tkStubsPtr->tk_3DBorderGC) /* 2 */
+#define Tk_3DHorizontalBevel \
+ (tkStubsPtr->tk_3DHorizontalBevel) /* 3 */
+#define Tk_3DVerticalBevel \
+ (tkStubsPtr->tk_3DVerticalBevel) /* 4 */
+#define Tk_AddOption \
+ (tkStubsPtr->tk_AddOption) /* 5 */
+#define Tk_BindEvent \
+ (tkStubsPtr->tk_BindEvent) /* 6 */
+#define Tk_CanvasDrawableCoords \
+ (tkStubsPtr->tk_CanvasDrawableCoords) /* 7 */
+#define Tk_CanvasEventuallyRedraw \
+ (tkStubsPtr->tk_CanvasEventuallyRedraw) /* 8 */
+#define Tk_CanvasGetCoord \
+ (tkStubsPtr->tk_CanvasGetCoord) /* 9 */
+#define Tk_CanvasGetTextInfo \
+ (tkStubsPtr->tk_CanvasGetTextInfo) /* 10 */
+#define Tk_CanvasPsBitmap \
+ (tkStubsPtr->tk_CanvasPsBitmap) /* 11 */
+#define Tk_CanvasPsColor \
+ (tkStubsPtr->tk_CanvasPsColor) /* 12 */
+#define Tk_CanvasPsFont \
+ (tkStubsPtr->tk_CanvasPsFont) /* 13 */
+#define Tk_CanvasPsPath \
+ (tkStubsPtr->tk_CanvasPsPath) /* 14 */
+#define Tk_CanvasPsStipple \
+ (tkStubsPtr->tk_CanvasPsStipple) /* 15 */
+#define Tk_CanvasPsY \
+ (tkStubsPtr->tk_CanvasPsY) /* 16 */
+#define Tk_CanvasSetStippleOrigin \
+ (tkStubsPtr->tk_CanvasSetStippleOrigin) /* 17 */
+#define Tk_CanvasTagsParseProc \
+ (tkStubsPtr->tk_CanvasTagsParseProc) /* 18 */
+#define Tk_CanvasTagsPrintProc \
+ (tkStubsPtr->tk_CanvasTagsPrintProc) /* 19 */
+#define Tk_CanvasTkwin \
+ (tkStubsPtr->tk_CanvasTkwin) /* 20 */
+#define Tk_CanvasWindowCoords \
+ (tkStubsPtr->tk_CanvasWindowCoords) /* 21 */
+#define Tk_ChangeWindowAttributes \
+ (tkStubsPtr->tk_ChangeWindowAttributes) /* 22 */
+#define Tk_CharBbox \
+ (tkStubsPtr->tk_CharBbox) /* 23 */
+#define Tk_ClearSelection \
+ (tkStubsPtr->tk_ClearSelection) /* 24 */
+#define Tk_ClipboardAppend \
+ (tkStubsPtr->tk_ClipboardAppend) /* 25 */
+#define Tk_ClipboardClear \
+ (tkStubsPtr->tk_ClipboardClear) /* 26 */
+#define Tk_ConfigureInfo \
+ (tkStubsPtr->tk_ConfigureInfo) /* 27 */
+#define Tk_ConfigureValue \
+ (tkStubsPtr->tk_ConfigureValue) /* 28 */
+#define Tk_ConfigureWidget \
+ (tkStubsPtr->tk_ConfigureWidget) /* 29 */
+#define Tk_ConfigureWindow \
+ (tkStubsPtr->tk_ConfigureWindow) /* 30 */
+#define Tk_ComputeTextLayout \
+ (tkStubsPtr->tk_ComputeTextLayout) /* 31 */
+#define Tk_CoordsToWindow \
+ (tkStubsPtr->tk_CoordsToWindow) /* 32 */
+#define Tk_CreateBinding \
+ (tkStubsPtr->tk_CreateBinding) /* 33 */
+#define Tk_CreateBindingTable \
+ (tkStubsPtr->tk_CreateBindingTable) /* 34 */
+#define Tk_CreateErrorHandler \
+ (tkStubsPtr->tk_CreateErrorHandler) /* 35 */
+#define Tk_CreateEventHandler \
+ (tkStubsPtr->tk_CreateEventHandler) /* 36 */
+#define Tk_CreateGenericHandler \
+ (tkStubsPtr->tk_CreateGenericHandler) /* 37 */
+#define Tk_CreateImageType \
+ (tkStubsPtr->tk_CreateImageType) /* 38 */
+#define Tk_CreateItemType \
+ (tkStubsPtr->tk_CreateItemType) /* 39 */
+#define Tk_CreatePhotoImageFormat \
+ (tkStubsPtr->tk_CreatePhotoImageFormat) /* 40 */
+#define Tk_CreateSelHandler \
+ (tkStubsPtr->tk_CreateSelHandler) /* 41 */
+#define Tk_CreateWindow \
+ (tkStubsPtr->tk_CreateWindow) /* 42 */
+#define Tk_CreateWindowFromPath \
+ (tkStubsPtr->tk_CreateWindowFromPath) /* 43 */
+#define Tk_DefineBitmap \
+ (tkStubsPtr->tk_DefineBitmap) /* 44 */
+#define Tk_DefineCursor \
+ (tkStubsPtr->tk_DefineCursor) /* 45 */
+#define Tk_DeleteAllBindings \
+ (tkStubsPtr->tk_DeleteAllBindings) /* 46 */
+#define Tk_DeleteBinding \
+ (tkStubsPtr->tk_DeleteBinding) /* 47 */
+#define Tk_DeleteBindingTable \
+ (tkStubsPtr->tk_DeleteBindingTable) /* 48 */
+#define Tk_DeleteErrorHandler \
+ (tkStubsPtr->tk_DeleteErrorHandler) /* 49 */
+#define Tk_DeleteEventHandler \
+ (tkStubsPtr->tk_DeleteEventHandler) /* 50 */
+#define Tk_DeleteGenericHandler \
+ (tkStubsPtr->tk_DeleteGenericHandler) /* 51 */
+#define Tk_DeleteImage \
+ (tkStubsPtr->tk_DeleteImage) /* 52 */
+#define Tk_DeleteSelHandler \
+ (tkStubsPtr->tk_DeleteSelHandler) /* 53 */
+#define Tk_DestroyWindow \
+ (tkStubsPtr->tk_DestroyWindow) /* 54 */
+#define Tk_DisplayName \
+ (tkStubsPtr->tk_DisplayName) /* 55 */
+#define Tk_DistanceToTextLayout \
+ (tkStubsPtr->tk_DistanceToTextLayout) /* 56 */
+#define Tk_Draw3DPolygon \
+ (tkStubsPtr->tk_Draw3DPolygon) /* 57 */
+#define Tk_Draw3DRectangle \
+ (tkStubsPtr->tk_Draw3DRectangle) /* 58 */
+#define Tk_DrawChars \
+ (tkStubsPtr->tk_DrawChars) /* 59 */
+#define Tk_DrawFocusHighlight \
+ (tkStubsPtr->tk_DrawFocusHighlight) /* 60 */
+#define Tk_DrawTextLayout \
+ (tkStubsPtr->tk_DrawTextLayout) /* 61 */
+#define Tk_Fill3DPolygon \
+ (tkStubsPtr->tk_Fill3DPolygon) /* 62 */
+#define Tk_Fill3DRectangle \
+ (tkStubsPtr->tk_Fill3DRectangle) /* 63 */
+#define Tk_FindPhoto \
+ (tkStubsPtr->tk_FindPhoto) /* 64 */
+#define Tk_FontId \
+ (tkStubsPtr->tk_FontId) /* 65 */
+#define Tk_Free3DBorder \
+ (tkStubsPtr->tk_Free3DBorder) /* 66 */
+#define Tk_FreeBitmap \
+ (tkStubsPtr->tk_FreeBitmap) /* 67 */
+#define Tk_FreeColor \
+ (tkStubsPtr->tk_FreeColor) /* 68 */
+#define Tk_FreeColormap \
+ (tkStubsPtr->tk_FreeColormap) /* 69 */
+#define Tk_FreeCursor \
+ (tkStubsPtr->tk_FreeCursor) /* 70 */
+#define Tk_FreeFont \
+ (tkStubsPtr->tk_FreeFont) /* 71 */
+#define Tk_FreeGC \
+ (tkStubsPtr->tk_FreeGC) /* 72 */
+#define Tk_FreeImage \
+ (tkStubsPtr->tk_FreeImage) /* 73 */
+#define Tk_FreeOptions \
+ (tkStubsPtr->tk_FreeOptions) /* 74 */
+#define Tk_FreePixmap \
+ (tkStubsPtr->tk_FreePixmap) /* 75 */
+#define Tk_FreeTextLayout \
+ (tkStubsPtr->tk_FreeTextLayout) /* 76 */
+#define Tk_FreeXId \
+ (tkStubsPtr->tk_FreeXId) /* 77 */
+#define Tk_GCForColor \
+ (tkStubsPtr->tk_GCForColor) /* 78 */
+#define Tk_GeometryRequest \
+ (tkStubsPtr->tk_GeometryRequest) /* 79 */
+#define Tk_Get3DBorder \
+ (tkStubsPtr->tk_Get3DBorder) /* 80 */
+#define Tk_GetAllBindings \
+ (tkStubsPtr->tk_GetAllBindings) /* 81 */
+#define Tk_GetAnchor \
+ (tkStubsPtr->tk_GetAnchor) /* 82 */
+#define Tk_GetAtomName \
+ (tkStubsPtr->tk_GetAtomName) /* 83 */
+#define Tk_GetBinding \
+ (tkStubsPtr->tk_GetBinding) /* 84 */
+#define Tk_GetBitmap \
+ (tkStubsPtr->tk_GetBitmap) /* 85 */
+#define Tk_GetBitmapFromData \
+ (tkStubsPtr->tk_GetBitmapFromData) /* 86 */
+#define Tk_GetCapStyle \
+ (tkStubsPtr->tk_GetCapStyle) /* 87 */
+#define Tk_GetColor \
+ (tkStubsPtr->tk_GetColor) /* 88 */
+#define Tk_GetColorByValue \
+ (tkStubsPtr->tk_GetColorByValue) /* 89 */
+#define Tk_GetColormap \
+ (tkStubsPtr->tk_GetColormap) /* 90 */
+#define Tk_GetCursor \
+ (tkStubsPtr->tk_GetCursor) /* 91 */
+#define Tk_GetCursorFromData \
+ (tkStubsPtr->tk_GetCursorFromData) /* 92 */
+#define Tk_GetFont \
+ (tkStubsPtr->tk_GetFont) /* 93 */
+#define Tk_GetFontFromObj \
+ (tkStubsPtr->tk_GetFontFromObj) /* 94 */
+#define Tk_GetFontMetrics \
+ (tkStubsPtr->tk_GetFontMetrics) /* 95 */
+#define Tk_GetGC \
+ (tkStubsPtr->tk_GetGC) /* 96 */
+#define Tk_GetImage \
+ (tkStubsPtr->tk_GetImage) /* 97 */
+#define Tk_GetImageMasterData \
+ (tkStubsPtr->tk_GetImageMasterData) /* 98 */
+#define Tk_GetItemTypes \
+ (tkStubsPtr->tk_GetItemTypes) /* 99 */
+#define Tk_GetJoinStyle \
+ (tkStubsPtr->tk_GetJoinStyle) /* 100 */
+#define Tk_GetJustify \
+ (tkStubsPtr->tk_GetJustify) /* 101 */
+#define Tk_GetNumMainWindows \
+ (tkStubsPtr->tk_GetNumMainWindows) /* 102 */
+#define Tk_GetOption \
+ (tkStubsPtr->tk_GetOption) /* 103 */
+#define Tk_GetPixels \
+ (tkStubsPtr->tk_GetPixels) /* 104 */
+#define Tk_GetPixmap \
+ (tkStubsPtr->tk_GetPixmap) /* 105 */
+#define Tk_GetRelief \
+ (tkStubsPtr->tk_GetRelief) /* 106 */
+#define Tk_GetRootCoords \
+ (tkStubsPtr->tk_GetRootCoords) /* 107 */
+#define Tk_GetScrollInfo \
+ (tkStubsPtr->tk_GetScrollInfo) /* 108 */
+#define Tk_GetScreenMM \
+ (tkStubsPtr->tk_GetScreenMM) /* 109 */
+#define Tk_GetSelection \
+ (tkStubsPtr->tk_GetSelection) /* 110 */
+#define Tk_GetUid \
+ (tkStubsPtr->tk_GetUid) /* 111 */
+#define Tk_GetVisual \
+ (tkStubsPtr->tk_GetVisual) /* 112 */
+#define Tk_GetVRootGeometry \
+ (tkStubsPtr->tk_GetVRootGeometry) /* 113 */
+#define Tk_Grab \
+ (tkStubsPtr->tk_Grab) /* 114 */
+#define Tk_HandleEvent \
+ (tkStubsPtr->tk_HandleEvent) /* 115 */
+#define Tk_IdToWindow \
+ (tkStubsPtr->tk_IdToWindow) /* 116 */
+#define Tk_ImageChanged \
+ (tkStubsPtr->tk_ImageChanged) /* 117 */
+#define Tk_Init \
+ (tkStubsPtr->tk_Init) /* 118 */
+#define Tk_InternAtom \
+ (tkStubsPtr->tk_InternAtom) /* 119 */
+#define Tk_IntersectTextLayout \
+ (tkStubsPtr->tk_IntersectTextLayout) /* 120 */
+#define Tk_MaintainGeometry \
+ (tkStubsPtr->tk_MaintainGeometry) /* 121 */
+#define Tk_MainWindow \
+ (tkStubsPtr->tk_MainWindow) /* 122 */
+#define Tk_MakeWindowExist \
+ (tkStubsPtr->tk_MakeWindowExist) /* 123 */
+#define Tk_ManageGeometry \
+ (tkStubsPtr->tk_ManageGeometry) /* 124 */
+#define Tk_MapWindow \
+ (tkStubsPtr->tk_MapWindow) /* 125 */
+#define Tk_MeasureChars \
+ (tkStubsPtr->tk_MeasureChars) /* 126 */
+#define Tk_MoveResizeWindow \
+ (tkStubsPtr->tk_MoveResizeWindow) /* 127 */
+#define Tk_MoveWindow \
+ (tkStubsPtr->tk_MoveWindow) /* 128 */
+#define Tk_MoveToplevelWindow \
+ (tkStubsPtr->tk_MoveToplevelWindow) /* 129 */
+#define Tk_NameOf3DBorder \
+ (tkStubsPtr->tk_NameOf3DBorder) /* 130 */
+#define Tk_NameOfAnchor \
+ (tkStubsPtr->tk_NameOfAnchor) /* 131 */
+#define Tk_NameOfBitmap \
+ (tkStubsPtr->tk_NameOfBitmap) /* 132 */
+#define Tk_NameOfCapStyle \
+ (tkStubsPtr->tk_NameOfCapStyle) /* 133 */
+#define Tk_NameOfColor \
+ (tkStubsPtr->tk_NameOfColor) /* 134 */
+#define Tk_NameOfCursor \
+ (tkStubsPtr->tk_NameOfCursor) /* 135 */
+#define Tk_NameOfFont \
+ (tkStubsPtr->tk_NameOfFont) /* 136 */
+#define Tk_NameOfImage \
+ (tkStubsPtr->tk_NameOfImage) /* 137 */
+#define Tk_NameOfJoinStyle \
+ (tkStubsPtr->tk_NameOfJoinStyle) /* 138 */
+#define Tk_NameOfJustify \
+ (tkStubsPtr->tk_NameOfJustify) /* 139 */
+#define Tk_NameOfRelief \
+ (tkStubsPtr->tk_NameOfRelief) /* 140 */
+#define Tk_NameToWindow \
+ (tkStubsPtr->tk_NameToWindow) /* 141 */
+#define Tk_OwnSelection \
+ (tkStubsPtr->tk_OwnSelection) /* 142 */
+#define Tk_ParseArgv \
+ (tkStubsPtr->tk_ParseArgv) /* 143 */
+#define Tk_PhotoPutBlock_NoComposite \
+ (tkStubsPtr->tk_PhotoPutBlock_NoComposite) /* 144 */
+#define Tk_PhotoPutZoomedBlock_NoComposite \
+ (tkStubsPtr->tk_PhotoPutZoomedBlock_NoComposite) /* 145 */
+#define Tk_PhotoGetImage \
+ (tkStubsPtr->tk_PhotoGetImage) /* 146 */
+#define Tk_PhotoBlank \
+ (tkStubsPtr->tk_PhotoBlank) /* 147 */
+#define Tk_PhotoExpand_Panic \
+ (tkStubsPtr->tk_PhotoExpand_Panic) /* 148 */
+#define Tk_PhotoGetSize \
+ (tkStubsPtr->tk_PhotoGetSize) /* 149 */
+#define Tk_PhotoSetSize_Panic \
+ (tkStubsPtr->tk_PhotoSetSize_Panic) /* 150 */
+#define Tk_PointToChar \
+ (tkStubsPtr->tk_PointToChar) /* 151 */
+#define Tk_PostscriptFontName \
+ (tkStubsPtr->tk_PostscriptFontName) /* 152 */
+#define Tk_PreserveColormap \
+ (tkStubsPtr->tk_PreserveColormap) /* 153 */
+#define Tk_QueueWindowEvent \
+ (tkStubsPtr->tk_QueueWindowEvent) /* 154 */
+#define Tk_RedrawImage \
+ (tkStubsPtr->tk_RedrawImage) /* 155 */
+#define Tk_ResizeWindow \
+ (tkStubsPtr->tk_ResizeWindow) /* 156 */
+#define Tk_RestackWindow \
+ (tkStubsPtr->tk_RestackWindow) /* 157 */
+#define Tk_RestrictEvents \
+ (tkStubsPtr->tk_RestrictEvents) /* 158 */
+#define Tk_SafeInit \
+ (tkStubsPtr->tk_SafeInit) /* 159 */
+#define Tk_SetAppName \
+ (tkStubsPtr->tk_SetAppName) /* 160 */
+#define Tk_SetBackgroundFromBorder \
+ (tkStubsPtr->tk_SetBackgroundFromBorder) /* 161 */
+#define Tk_SetClass \
+ (tkStubsPtr->tk_SetClass) /* 162 */
+#define Tk_SetGrid \
+ (tkStubsPtr->tk_SetGrid) /* 163 */
+#define Tk_SetInternalBorder \
+ (tkStubsPtr->tk_SetInternalBorder) /* 164 */
+#define Tk_SetWindowBackground \
+ (tkStubsPtr->tk_SetWindowBackground) /* 165 */
+#define Tk_SetWindowBackgroundPixmap \
+ (tkStubsPtr->tk_SetWindowBackgroundPixmap) /* 166 */
+#define Tk_SetWindowBorder \
+ (tkStubsPtr->tk_SetWindowBorder) /* 167 */
+#define Tk_SetWindowBorderWidth \
+ (tkStubsPtr->tk_SetWindowBorderWidth) /* 168 */
+#define Tk_SetWindowBorderPixmap \
+ (tkStubsPtr->tk_SetWindowBorderPixmap) /* 169 */
+#define Tk_SetWindowColormap \
+ (tkStubsPtr->tk_SetWindowColormap) /* 170 */
+#define Tk_SetWindowVisual \
+ (tkStubsPtr->tk_SetWindowVisual) /* 171 */
+#define Tk_SizeOfBitmap \
+ (tkStubsPtr->tk_SizeOfBitmap) /* 172 */
+#define Tk_SizeOfImage \
+ (tkStubsPtr->tk_SizeOfImage) /* 173 */
+#define Tk_StrictMotif \
+ (tkStubsPtr->tk_StrictMotif) /* 174 */
+#define Tk_TextLayoutToPostscript \
+ (tkStubsPtr->tk_TextLayoutToPostscript) /* 175 */
+#define Tk_TextWidth \
+ (tkStubsPtr->tk_TextWidth) /* 176 */
+#define Tk_UndefineCursor \
+ (tkStubsPtr->tk_UndefineCursor) /* 177 */
+#define Tk_UnderlineChars \
+ (tkStubsPtr->tk_UnderlineChars) /* 178 */
+#define Tk_UnderlineTextLayout \
+ (tkStubsPtr->tk_UnderlineTextLayout) /* 179 */
+#define Tk_Ungrab \
+ (tkStubsPtr->tk_Ungrab) /* 180 */
+#define Tk_UnmaintainGeometry \
+ (tkStubsPtr->tk_UnmaintainGeometry) /* 181 */
+#define Tk_UnmapWindow \
+ (tkStubsPtr->tk_UnmapWindow) /* 182 */
+#define Tk_UnsetGrid \
+ (tkStubsPtr->tk_UnsetGrid) /* 183 */
+#define Tk_UpdatePointer \
+ (tkStubsPtr->tk_UpdatePointer) /* 184 */
+#define Tk_AllocBitmapFromObj \
+ (tkStubsPtr->tk_AllocBitmapFromObj) /* 185 */
+#define Tk_Alloc3DBorderFromObj \
+ (tkStubsPtr->tk_Alloc3DBorderFromObj) /* 186 */
+#define Tk_AllocColorFromObj \
+ (tkStubsPtr->tk_AllocColorFromObj) /* 187 */
+#define Tk_AllocCursorFromObj \
+ (tkStubsPtr->tk_AllocCursorFromObj) /* 188 */
+#define Tk_AllocFontFromObj \
+ (tkStubsPtr->tk_AllocFontFromObj) /* 189 */
+#define Tk_CreateOptionTable \
+ (tkStubsPtr->tk_CreateOptionTable) /* 190 */
+#define Tk_DeleteOptionTable \
+ (tkStubsPtr->tk_DeleteOptionTable) /* 191 */
+#define Tk_Free3DBorderFromObj \
+ (tkStubsPtr->tk_Free3DBorderFromObj) /* 192 */
+#define Tk_FreeBitmapFromObj \
+ (tkStubsPtr->tk_FreeBitmapFromObj) /* 193 */
+#define Tk_FreeColorFromObj \
+ (tkStubsPtr->tk_FreeColorFromObj) /* 194 */
+#define Tk_FreeConfigOptions \
+ (tkStubsPtr->tk_FreeConfigOptions) /* 195 */
+#define Tk_FreeSavedOptions \
+ (tkStubsPtr->tk_FreeSavedOptions) /* 196 */
+#define Tk_FreeCursorFromObj \
+ (tkStubsPtr->tk_FreeCursorFromObj) /* 197 */
+#define Tk_FreeFontFromObj \
+ (tkStubsPtr->tk_FreeFontFromObj) /* 198 */
+#define Tk_Get3DBorderFromObj \
+ (tkStubsPtr->tk_Get3DBorderFromObj) /* 199 */
+#define Tk_GetAnchorFromObj \
+ (tkStubsPtr->tk_GetAnchorFromObj) /* 200 */
+#define Tk_GetBitmapFromObj \
+ (tkStubsPtr->tk_GetBitmapFromObj) /* 201 */
+#define Tk_GetColorFromObj \
+ (tkStubsPtr->tk_GetColorFromObj) /* 202 */
+#define Tk_GetCursorFromObj \
+ (tkStubsPtr->tk_GetCursorFromObj) /* 203 */
+#define Tk_GetOptionInfo \
+ (tkStubsPtr->tk_GetOptionInfo) /* 204 */
+#define Tk_GetOptionValue \
+ (tkStubsPtr->tk_GetOptionValue) /* 205 */
+#define Tk_GetJustifyFromObj \
+ (tkStubsPtr->tk_GetJustifyFromObj) /* 206 */
+#define Tk_GetMMFromObj \
+ (tkStubsPtr->tk_GetMMFromObj) /* 207 */
+#define Tk_GetPixelsFromObj \
+ (tkStubsPtr->tk_GetPixelsFromObj) /* 208 */
+#define Tk_GetReliefFromObj \
+ (tkStubsPtr->tk_GetReliefFromObj) /* 209 */
+#define Tk_GetScrollInfoObj \
+ (tkStubsPtr->tk_GetScrollInfoObj) /* 210 */
+#define Tk_InitOptions \
+ (tkStubsPtr->tk_InitOptions) /* 211 */
+#define Tk_MainEx \
+ (tkStubsPtr->tk_MainEx) /* 212 */
+#define Tk_RestoreSavedOptions \
+ (tkStubsPtr->tk_RestoreSavedOptions) /* 213 */
+#define Tk_SetOptions \
+ (tkStubsPtr->tk_SetOptions) /* 214 */
+#define Tk_InitConsoleChannels \
+ (tkStubsPtr->tk_InitConsoleChannels) /* 215 */
+#define Tk_CreateConsoleWindow \
+ (tkStubsPtr->tk_CreateConsoleWindow) /* 216 */
+#define Tk_CreateSmoothMethod \
+ (tkStubsPtr->tk_CreateSmoothMethod) /* 217 */
+/* Slot 218 is reserved */
+/* Slot 219 is reserved */
+#define Tk_GetDash \
+ (tkStubsPtr->tk_GetDash) /* 220 */
+#define Tk_CreateOutline \
+ (tkStubsPtr->tk_CreateOutline) /* 221 */
+#define Tk_DeleteOutline \
+ (tkStubsPtr->tk_DeleteOutline) /* 222 */
+#define Tk_ConfigOutlineGC \
+ (tkStubsPtr->tk_ConfigOutlineGC) /* 223 */
+#define Tk_ChangeOutlineGC \
+ (tkStubsPtr->tk_ChangeOutlineGC) /* 224 */
+#define Tk_ResetOutlineGC \
+ (tkStubsPtr->tk_ResetOutlineGC) /* 225 */
+#define Tk_CanvasPsOutline \
+ (tkStubsPtr->tk_CanvasPsOutline) /* 226 */
+#define Tk_SetTSOrigin \
+ (tkStubsPtr->tk_SetTSOrigin) /* 227 */
+#define Tk_CanvasGetCoordFromObj \
+ (tkStubsPtr->tk_CanvasGetCoordFromObj) /* 228 */
+#define Tk_CanvasSetOffset \
+ (tkStubsPtr->tk_CanvasSetOffset) /* 229 */
+#define Tk_DitherPhoto \
+ (tkStubsPtr->tk_DitherPhoto) /* 230 */
+#define Tk_PostscriptBitmap \
+ (tkStubsPtr->tk_PostscriptBitmap) /* 231 */
+#define Tk_PostscriptColor \
+ (tkStubsPtr->tk_PostscriptColor) /* 232 */
+#define Tk_PostscriptFont \
+ (tkStubsPtr->tk_PostscriptFont) /* 233 */
+#define Tk_PostscriptImage \
+ (tkStubsPtr->tk_PostscriptImage) /* 234 */
+#define Tk_PostscriptPath \
+ (tkStubsPtr->tk_PostscriptPath) /* 235 */
+#define Tk_PostscriptStipple \
+ (tkStubsPtr->tk_PostscriptStipple) /* 236 */
+#define Tk_PostscriptY \
+ (tkStubsPtr->tk_PostscriptY) /* 237 */
+#define Tk_PostscriptPhoto \
+ (tkStubsPtr->tk_PostscriptPhoto) /* 238 */
+#define Tk_CreateClientMessageHandler \
+ (tkStubsPtr->tk_CreateClientMessageHandler) /* 239 */
+#define Tk_DeleteClientMessageHandler \
+ (tkStubsPtr->tk_DeleteClientMessageHandler) /* 240 */
+#define Tk_CreateAnonymousWindow \
+ (tkStubsPtr->tk_CreateAnonymousWindow) /* 241 */
+#define Tk_SetClassProcs \
+ (tkStubsPtr->tk_SetClassProcs) /* 242 */
+#define Tk_SetInternalBorderEx \
+ (tkStubsPtr->tk_SetInternalBorderEx) /* 243 */
+#define Tk_SetMinimumRequestSize \
+ (tkStubsPtr->tk_SetMinimumRequestSize) /* 244 */
+#define Tk_SetCaretPos \
+ (tkStubsPtr->tk_SetCaretPos) /* 245 */
+#define Tk_PhotoPutBlock_Panic \
+ (tkStubsPtr->tk_PhotoPutBlock_Panic) /* 246 */
+#define Tk_PhotoPutZoomedBlock_Panic \
+ (tkStubsPtr->tk_PhotoPutZoomedBlock_Panic) /* 247 */
+#define Tk_CollapseMotionEvents \
+ (tkStubsPtr->tk_CollapseMotionEvents) /* 248 */
+#define Tk_RegisterStyleEngine \
+ (tkStubsPtr->tk_RegisterStyleEngine) /* 249 */
+#define Tk_GetStyleEngine \
+ (tkStubsPtr->tk_GetStyleEngine) /* 250 */
+#define Tk_RegisterStyledElement \
+ (tkStubsPtr->tk_RegisterStyledElement) /* 251 */
+#define Tk_GetElementId \
+ (tkStubsPtr->tk_GetElementId) /* 252 */
+#define Tk_CreateStyle \
+ (tkStubsPtr->tk_CreateStyle) /* 253 */
+#define Tk_GetStyle \
+ (tkStubsPtr->tk_GetStyle) /* 254 */
+#define Tk_FreeStyle \
+ (tkStubsPtr->tk_FreeStyle) /* 255 */
+#define Tk_NameOfStyle \
+ (tkStubsPtr->tk_NameOfStyle) /* 256 */
+#define Tk_AllocStyleFromObj \
+ (tkStubsPtr->tk_AllocStyleFromObj) /* 257 */
+#define Tk_GetStyleFromObj \
+ (tkStubsPtr->tk_GetStyleFromObj) /* 258 */
+#define Tk_FreeStyleFromObj \
+ (tkStubsPtr->tk_FreeStyleFromObj) /* 259 */
+#define Tk_GetStyledElement \
+ (tkStubsPtr->tk_GetStyledElement) /* 260 */
+#define Tk_GetElementSize \
+ (tkStubsPtr->tk_GetElementSize) /* 261 */
+#define Tk_GetElementBox \
+ (tkStubsPtr->tk_GetElementBox) /* 262 */
+#define Tk_GetElementBorderWidth \
+ (tkStubsPtr->tk_GetElementBorderWidth) /* 263 */
+#define Tk_DrawElement \
+ (tkStubsPtr->tk_DrawElement) /* 264 */
+#define Tk_PhotoExpand \
+ (tkStubsPtr->tk_PhotoExpand) /* 265 */
+#define Tk_PhotoPutBlock \
+ (tkStubsPtr->tk_PhotoPutBlock) /* 266 */
+#define Tk_PhotoPutZoomedBlock \
+ (tkStubsPtr->tk_PhotoPutZoomedBlock) /* 267 */
+#define Tk_PhotoSetSize \
+ (tkStubsPtr->tk_PhotoSetSize) /* 268 */
+#define Tk_GetUserInactiveTime \
+ (tkStubsPtr->tk_GetUserInactiveTime) /* 269 */
+#define Tk_ResetUserInactiveTime \
+ (tkStubsPtr->tk_ResetUserInactiveTime) /* 270 */
+#define Tk_Interp \
+ (tkStubsPtr->tk_Interp) /* 271 */
+#define Tk_CreateOldImageType \
+ (tkStubsPtr->tk_CreateOldImageType) /* 272 */
+#define Tk_CreateOldPhotoImageFormat \
+ (tkStubsPtr->tk_CreateOldPhotoImageFormat) /* 273 */
+
+#endif /* defined(USE_TK_STUBS) */
+
+/* !END!: Do not edit above this line. */
+
+/* Functions that don't belong in the stub table */
+#undef Tk_MainEx
+#undef Tk_Init
+#undef Tk_SafeInit
+#undef Tk_CreateConsoleWindow
+
+#if defined(_WIN32) && defined(UNICODE)
+# define Tk_MainEx Tk_MainExW
+ EXTERN void Tk_MainExW(int argc, wchar_t **argv,
+ Tcl_AppInitProc *appInitProc, Tcl_Interp *interp);
+#endif
+
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLIMPORT
+
+#endif /* _TKDECLS */
diff --git a/tk8.6/generic/tkEntry.c b/tk8.6/generic/tkEntry.c
new file mode 100644
index 0000000..a7bc5a0
--- /dev/null
+++ b/tk8.6/generic/tkEntry.c
@@ -0,0 +1,4518 @@
+/*
+ * tkEntry.c --
+ *
+ * This module implements entry and spinbox widgets for the Tk toolkit.
+ * An entry displays a string and allows the string to be edited. A
+ * spinbox expands on the entry by adding up/down buttons that control
+ * the value of the entry widget.
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 2000 Ajuba Solutions.
+ * Copyright (c) 2002 ActiveState Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkInt.h"
+#include "default.h"
+#include "tkEntry.h"
+
+/*
+ * The following macro defines how many extra pixels to leave on each side of
+ * the text in the entry.
+ */
+
+#define XPAD 1
+#define YPAD 1
+
+/*
+ * A comparison function for double values. For Spinboxes.
+ */
+
+#define MIN_DBL_VAL 1E-9
+#define DOUBLES_EQ(d1, d2) (fabs((d1) - (d2)) < MIN_DBL_VAL)
+
+
+static const char *const stateStrings[] = {
+ "disabled", "normal", "readonly", NULL
+};
+
+/*
+ * Definitions for -validate option values:
+ */
+
+static const char *const validateStrings[] = {
+ "all", "key", "focus", "focusin", "focusout", "none", NULL
+};
+enum validateType {
+ VALIDATE_ALL, VALIDATE_KEY, VALIDATE_FOCUS,
+ VALIDATE_FOCUSIN, VALIDATE_FOCUSOUT, VALIDATE_NONE,
+ /*
+ * These extra enums are for use with EntryValidateChange
+ */
+ VALIDATE_FORCED, VALIDATE_DELETE, VALIDATE_INSERT, VALIDATE_BUTTON
+};
+#define DEF_ENTRY_VALIDATE "none"
+#define DEF_ENTRY_INVALIDCMD ""
+
+/*
+ * Information used for Entry objv parsing.
+ */
+
+static const Tk_OptionSpec entryOptSpec[] = {
+ {TK_OPTION_BORDER, "-background", "background", "Background",
+ DEF_ENTRY_BG_COLOR, -1, Tk_Offset(Entry, normalBorder),
+ 0, DEF_ENTRY_BG_MONO, 0},
+ {TK_OPTION_SYNONYM, "-bd", NULL, NULL,
+ NULL, 0, -1, 0, "-borderwidth", 0},
+ {TK_OPTION_SYNONYM, "-bg", NULL, NULL,
+ NULL, 0, -1, 0, "-background", 0},
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ DEF_ENTRY_BORDER_WIDTH, -1, Tk_Offset(Entry, borderWidth), 0, 0, 0},
+ {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
+ DEF_ENTRY_CURSOR, -1, Tk_Offset(Entry, cursor),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_BORDER, "-disabledbackground", "disabledBackground",
+ "DisabledBackground", DEF_ENTRY_DISABLED_BG_COLOR, -1,
+ Tk_Offset(Entry, disabledBorder), TK_OPTION_NULL_OK,
+ (ClientData) DEF_ENTRY_DISABLED_BG_MONO, 0},
+ {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
+ "DisabledForeground", DEF_ENTRY_DISABLED_FG, -1,
+ Tk_Offset(Entry, dfgColorPtr), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_BOOLEAN, "-exportselection", "exportSelection",
+ "ExportSelection", DEF_ENTRY_EXPORT_SELECTION, -1,
+ Tk_Offset(Entry, exportSelection), 0, 0, 0},
+ {TK_OPTION_SYNONYM, "-fg", "foreground", NULL,
+ NULL, 0, -1, 0, "-foreground", 0},
+ {TK_OPTION_FONT, "-font", "font", "Font",
+ DEF_ENTRY_FONT, -1, Tk_Offset(Entry, tkfont), 0, 0, 0},
+ {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
+ DEF_ENTRY_FG, -1, Tk_Offset(Entry, fgColorPtr), 0, 0, 0},
+ {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground",
+ "HighlightBackground", DEF_ENTRY_HIGHLIGHT_BG,
+ -1, Tk_Offset(Entry, highlightBgColorPtr), 0, 0, 0},
+ {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
+ DEF_ENTRY_HIGHLIGHT, -1, Tk_Offset(Entry, highlightColorPtr), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
+ "HighlightThickness", DEF_ENTRY_HIGHLIGHT_WIDTH, -1,
+ Tk_Offset(Entry, highlightWidth), 0, 0, 0},
+ {TK_OPTION_BORDER, "-insertbackground", "insertBackground", "Foreground",
+ DEF_ENTRY_INSERT_BG, -1, Tk_Offset(Entry, insertBorder), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-insertborderwidth", "insertBorderWidth",
+ "BorderWidth", DEF_ENTRY_INSERT_BD_COLOR, -1,
+ Tk_Offset(Entry, insertBorderWidth), 0,
+ (ClientData) DEF_ENTRY_INSERT_BD_MONO, 0},
+ {TK_OPTION_INT, "-insertofftime", "insertOffTime", "OffTime",
+ DEF_ENTRY_INSERT_OFF_TIME, -1, Tk_Offset(Entry, insertOffTime),
+ 0, 0, 0},
+ {TK_OPTION_INT, "-insertontime", "insertOnTime", "OnTime",
+ DEF_ENTRY_INSERT_ON_TIME, -1, Tk_Offset(Entry, insertOnTime), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-insertwidth", "insertWidth", "InsertWidth",
+ DEF_ENTRY_INSERT_WIDTH, -1, Tk_Offset(Entry, insertWidth), 0, 0, 0},
+ {TK_OPTION_STRING, "-invalidcommand", "invalidCommand", "InvalidCommand",
+ DEF_ENTRY_INVALIDCMD, -1, Tk_Offset(Entry, invalidCmd),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_SYNONYM, "-invcmd", NULL, NULL,
+ NULL, 0, -1, 0, "-invalidcommand", 0},
+ {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
+ DEF_ENTRY_JUSTIFY, -1, Tk_Offset(Entry, justify), 0, 0, 0},
+ {TK_OPTION_BORDER, "-readonlybackground", "readonlyBackground",
+ "ReadonlyBackground", DEF_ENTRY_READONLY_BG_COLOR, -1,
+ Tk_Offset(Entry, readonlyBorder), TK_OPTION_NULL_OK,
+ (ClientData) DEF_ENTRY_READONLY_BG_MONO, 0},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ DEF_ENTRY_RELIEF, -1, Tk_Offset(Entry, relief), 0, 0, 0},
+ {TK_OPTION_BORDER, "-selectbackground", "selectBackground", "Foreground",
+ DEF_ENTRY_SELECT_COLOR, -1, Tk_Offset(Entry, selBorder),
+ 0, DEF_ENTRY_SELECT_MONO, 0},
+ {TK_OPTION_PIXELS, "-selectborderwidth", "selectBorderWidth",
+ "BorderWidth", DEF_ENTRY_SELECT_BD_COLOR, -1,
+ Tk_Offset(Entry, selBorderWidth),
+ 0, DEF_ENTRY_SELECT_BD_MONO, 0},
+ {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background",
+ DEF_ENTRY_SELECT_FG_COLOR, -1, Tk_Offset(Entry, selFgColorPtr),
+ TK_OPTION_NULL_OK, DEF_ENTRY_SELECT_FG_MONO, 0},
+ {TK_OPTION_STRING, "-show", "show", "Show",
+ DEF_ENTRY_SHOW, -1, Tk_Offset(Entry, showChar),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-state", "state", "State",
+ DEF_ENTRY_STATE, -1, Tk_Offset(Entry, state),
+ 0, stateStrings, 0},
+ {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
+ DEF_ENTRY_TAKE_FOCUS, -1, Tk_Offset(Entry, takeFocus),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
+ DEF_ENTRY_TEXT_VARIABLE, -1, Tk_Offset(Entry, textVarName),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-validate", "validate", "Validate",
+ DEF_ENTRY_VALIDATE, -1, Tk_Offset(Entry, validate),
+ 0, validateStrings, 0},
+ {TK_OPTION_STRING, "-validatecommand", "validateCommand","ValidateCommand",
+ NULL, -1, Tk_Offset(Entry, validateCmd), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_SYNONYM, "-vcmd", NULL, NULL,
+ NULL, 0, -1, 0, "-validatecommand", 0},
+ {TK_OPTION_INT, "-width", "width", "Width",
+ DEF_ENTRY_WIDTH, -1, Tk_Offset(Entry, prefWidth), 0, 0, 0},
+ {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
+ DEF_ENTRY_SCROLL_COMMAND, -1, Tk_Offset(Entry, scrollCmd),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0}
+};
+
+/*
+ * Information used for Spinbox objv parsing.
+ */
+
+#define DEF_SPINBOX_REPEAT_DELAY "400"
+#define DEF_SPINBOX_REPEAT_INTERVAL "100"
+
+#define DEF_SPINBOX_CMD ""
+
+#define DEF_SPINBOX_FROM "0"
+#define DEF_SPINBOX_TO "0"
+#define DEF_SPINBOX_INCREMENT "1"
+#define DEF_SPINBOX_FORMAT ""
+
+#define DEF_SPINBOX_VALUES ""
+#define DEF_SPINBOX_WRAP "0"
+
+static const Tk_OptionSpec sbOptSpec[] = {
+ {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Background",
+ DEF_BUTTON_ACTIVE_BG_COLOR, -1, Tk_Offset(Spinbox, activeBorder),
+ 0, DEF_BUTTON_ACTIVE_BG_MONO, 0},
+ {TK_OPTION_BORDER, "-background", "background", "Background",
+ DEF_ENTRY_BG_COLOR, -1, Tk_Offset(Entry, normalBorder),
+ 0, DEF_ENTRY_BG_MONO, 0},
+ {TK_OPTION_SYNONYM, "-bd", NULL, NULL,
+ NULL, 0, -1, 0, "-borderwidth", 0},
+ {TK_OPTION_SYNONYM, "-bg", NULL, NULL,
+ NULL, 0, -1, 0, "-background", 0},
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ DEF_ENTRY_BORDER_WIDTH, -1, Tk_Offset(Entry, borderWidth), 0, 0, 0},
+ {TK_OPTION_BORDER, "-buttonbackground", "Button.background", "Background",
+ DEF_BUTTON_BG_COLOR, -1, Tk_Offset(Spinbox, buttonBorder),
+ 0, DEF_BUTTON_BG_MONO, 0},
+ {TK_OPTION_CURSOR, "-buttoncursor", "Button.cursor", "Cursor",
+ DEF_BUTTON_CURSOR, -1, Tk_Offset(Spinbox, bCursor),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_RELIEF, "-buttondownrelief", "Button.relief", "Relief",
+ DEF_BUTTON_RELIEF, -1, Tk_Offset(Spinbox, bdRelief), 0, 0, 0},
+ {TK_OPTION_RELIEF, "-buttonuprelief", "Button.relief", "Relief",
+ DEF_BUTTON_RELIEF, -1, Tk_Offset(Spinbox, buRelief), 0, 0, 0},
+ {TK_OPTION_STRING, "-command", "command", "Command",
+ DEF_SPINBOX_CMD, -1, Tk_Offset(Spinbox, command),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
+ DEF_ENTRY_CURSOR, -1, Tk_Offset(Entry, cursor),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_BORDER, "-disabledbackground", "disabledBackground",
+ "DisabledBackground", DEF_ENTRY_DISABLED_BG_COLOR, -1,
+ Tk_Offset(Entry, disabledBorder), TK_OPTION_NULL_OK,
+ (ClientData) DEF_ENTRY_DISABLED_BG_MONO, 0},
+ {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
+ "DisabledForeground", DEF_ENTRY_DISABLED_FG, -1,
+ Tk_Offset(Entry, dfgColorPtr), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_BOOLEAN, "-exportselection", "exportSelection",
+ "ExportSelection", DEF_ENTRY_EXPORT_SELECTION, -1,
+ Tk_Offset(Entry, exportSelection), 0, 0, 0},
+ {TK_OPTION_SYNONYM, "-fg", "foreground", NULL,
+ NULL, 0, -1, 0, "-foreground", 0},
+ {TK_OPTION_FONT, "-font", "font", "Font",
+ DEF_ENTRY_FONT, -1, Tk_Offset(Entry, tkfont), 0, 0, 0},
+ {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
+ DEF_ENTRY_FG, -1, Tk_Offset(Entry, fgColorPtr), 0, 0, 0},
+ {TK_OPTION_STRING, "-format", "format", "Format",
+ DEF_SPINBOX_FORMAT, -1, Tk_Offset(Spinbox, reqFormat),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_DOUBLE, "-from", "from", "From",
+ DEF_SPINBOX_FROM, -1, Tk_Offset(Spinbox, fromValue), 0, 0, 0},
+ {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground",
+ "HighlightBackground", DEF_ENTRY_HIGHLIGHT_BG,
+ -1, Tk_Offset(Entry, highlightBgColorPtr), 0, 0, 0},
+ {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
+ DEF_ENTRY_HIGHLIGHT, -1, Tk_Offset(Entry, highlightColorPtr), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
+ "HighlightThickness", DEF_ENTRY_HIGHLIGHT_WIDTH, -1,
+ Tk_Offset(Entry, highlightWidth), 0, 0, 0},
+ {TK_OPTION_DOUBLE, "-increment", "increment", "Increment",
+ DEF_SPINBOX_INCREMENT, -1, Tk_Offset(Spinbox, increment), 0, 0, 0},
+ {TK_OPTION_BORDER, "-insertbackground", "insertBackground", "Foreground",
+ DEF_ENTRY_INSERT_BG, -1, Tk_Offset(Entry, insertBorder), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-insertborderwidth", "insertBorderWidth",
+ "BorderWidth", DEF_ENTRY_INSERT_BD_COLOR, -1,
+ Tk_Offset(Entry, insertBorderWidth), 0,
+ (ClientData) DEF_ENTRY_INSERT_BD_MONO, 0},
+ {TK_OPTION_INT, "-insertofftime", "insertOffTime", "OffTime",
+ DEF_ENTRY_INSERT_OFF_TIME, -1, Tk_Offset(Entry, insertOffTime),
+ 0, 0, 0},
+ {TK_OPTION_INT, "-insertontime", "insertOnTime", "OnTime",
+ DEF_ENTRY_INSERT_ON_TIME, -1, Tk_Offset(Entry, insertOnTime), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-insertwidth", "insertWidth", "InsertWidth",
+ DEF_ENTRY_INSERT_WIDTH, -1, Tk_Offset(Entry, insertWidth), 0, 0, 0},
+ {TK_OPTION_STRING, "-invalidcommand", "invalidCommand", "InvalidCommand",
+ DEF_ENTRY_INVALIDCMD, -1, Tk_Offset(Entry, invalidCmd),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_SYNONYM, "-invcmd", NULL, NULL,
+ NULL, 0, -1, 0, "-invalidcommand", 0},
+ {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
+ DEF_ENTRY_JUSTIFY, -1, Tk_Offset(Entry, justify), 0, 0, 0},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ DEF_ENTRY_RELIEF, -1, Tk_Offset(Entry, relief), 0, 0, 0},
+ {TK_OPTION_BORDER, "-readonlybackground", "readonlyBackground",
+ "ReadonlyBackground", DEF_ENTRY_READONLY_BG_COLOR, -1,
+ Tk_Offset(Entry, readonlyBorder), TK_OPTION_NULL_OK,
+ (ClientData) DEF_ENTRY_READONLY_BG_MONO, 0},
+ {TK_OPTION_INT, "-repeatdelay", "repeatDelay", "RepeatDelay",
+ DEF_SPINBOX_REPEAT_DELAY, -1, Tk_Offset(Spinbox, repeatDelay),
+ 0, 0, 0},
+ {TK_OPTION_INT, "-repeatinterval", "repeatInterval", "RepeatInterval",
+ DEF_SPINBOX_REPEAT_INTERVAL, -1, Tk_Offset(Spinbox, repeatInterval),
+ 0, 0, 0},
+ {TK_OPTION_BORDER, "-selectbackground", "selectBackground", "Foreground",
+ DEF_ENTRY_SELECT_COLOR, -1, Tk_Offset(Entry, selBorder),
+ 0, DEF_ENTRY_SELECT_MONO, 0},
+ {TK_OPTION_PIXELS, "-selectborderwidth", "selectBorderWidth",
+ "BorderWidth", DEF_ENTRY_SELECT_BD_COLOR, -1,
+ Tk_Offset(Entry, selBorderWidth),
+ 0, DEF_ENTRY_SELECT_BD_MONO, 0},
+ {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background",
+ DEF_ENTRY_SELECT_FG_COLOR, -1, Tk_Offset(Entry, selFgColorPtr),
+ TK_OPTION_NULL_OK, DEF_ENTRY_SELECT_FG_MONO, 0},
+ {TK_OPTION_STRING_TABLE, "-state", "state", "State",
+ DEF_ENTRY_STATE, -1, Tk_Offset(Entry, state),
+ 0, stateStrings, 0},
+ {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
+ DEF_ENTRY_TAKE_FOCUS, -1, Tk_Offset(Entry, takeFocus),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
+ DEF_ENTRY_TEXT_VARIABLE, -1, Tk_Offset(Entry, textVarName),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_DOUBLE, "-to", "to", "To",
+ DEF_SPINBOX_TO, -1, Tk_Offset(Spinbox, toValue), 0, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-validate", "validate", "Validate",
+ DEF_ENTRY_VALIDATE, -1, Tk_Offset(Entry, validate),
+ 0, validateStrings, 0},
+ {TK_OPTION_STRING, "-validatecommand", "validateCommand","ValidateCommand",
+ NULL, -1, Tk_Offset(Entry, validateCmd), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-values", "values", "Values",
+ DEF_SPINBOX_VALUES, -1, Tk_Offset(Spinbox, valueStr),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_SYNONYM, "-vcmd", NULL, NULL,
+ NULL, 0, -1, 0, "-validatecommand", 0},
+ {TK_OPTION_INT, "-width", "width", "Width",
+ DEF_ENTRY_WIDTH, -1, Tk_Offset(Entry, prefWidth), 0, 0, 0},
+ {TK_OPTION_BOOLEAN, "-wrap", "wrap", "Wrap",
+ DEF_SPINBOX_WRAP, -1, Tk_Offset(Spinbox, wrap), 0, 0, 0},
+ {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
+ DEF_ENTRY_SCROLL_COMMAND, -1, Tk_Offset(Entry, scrollCmd),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0}
+};
+
+/*
+ * The following tables define the entry widget commands (and sub-commands)
+ * and map the indexes into the string tables into enumerated types used to
+ * dispatch the entry widget command.
+ */
+
+static const char *const entryCmdNames[] = {
+ "bbox", "cget", "configure", "delete", "get", "icursor", "index",
+ "insert", "scan", "selection", "validate", "xview", NULL
+};
+
+enum entryCmd {
+ COMMAND_BBOX, COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DELETE,
+ COMMAND_GET, COMMAND_ICURSOR, COMMAND_INDEX, COMMAND_INSERT,
+ COMMAND_SCAN, COMMAND_SELECTION, COMMAND_VALIDATE, COMMAND_XVIEW
+};
+
+static const char *const selCmdNames[] = {
+ "adjust", "clear", "from", "present", "range", "to", NULL
+};
+
+enum selCmd {
+ SELECTION_ADJUST, SELECTION_CLEAR, SELECTION_FROM,
+ SELECTION_PRESENT, SELECTION_RANGE, SELECTION_TO
+};
+
+/*
+ * The following tables define the spinbox widget commands (and sub-commands)
+ * and map the indexes into the string tables into enumerated types used to
+ * dispatch the spinbox widget command.
+ */
+
+static const char *const sbCmdNames[] = {
+ "bbox", "cget", "configure", "delete", "get", "icursor", "identify",
+ "index", "insert", "invoke", "scan", "selection", "set",
+ "validate", "xview", NULL
+};
+
+enum sbCmd {
+ SB_CMD_BBOX, SB_CMD_CGET, SB_CMD_CONFIGURE, SB_CMD_DELETE,
+ SB_CMD_GET, SB_CMD_ICURSOR, SB_CMD_IDENTIFY, SB_CMD_INDEX,
+ SB_CMD_INSERT, SB_CMD_INVOKE, SB_CMD_SCAN, SB_CMD_SELECTION,
+ SB_CMD_SET, SB_CMD_VALIDATE, SB_CMD_XVIEW
+};
+
+static const char *const sbSelCmdNames[] = {
+ "adjust", "clear", "element", "from", "present", "range", "to", NULL
+};
+
+enum sbselCmd {
+ SB_SEL_ADJUST, SB_SEL_CLEAR, SB_SEL_ELEMENT, SB_SEL_FROM,
+ SB_SEL_PRESENT, SB_SEL_RANGE, SB_SEL_TO
+};
+
+/*
+ * Extra for selection of elements
+ */
+
+/*
+ * This is the string array corresponding to the enum in selelement. If you
+ * modify them, you must modify the strings here.
+ */
+
+static const char *const selElementNames[] = {
+ "none", "buttondown", "buttonup", NULL, "entry"
+};
+
+/*
+ * Flags for GetEntryIndex function:
+ */
+
+#define ZERO_OK 1
+#define LAST_PLUS_ONE_OK 2
+
+/*
+ * Forward declarations for functions defined later in this file:
+ */
+
+static int ConfigureEntry(Tcl_Interp *interp, Entry *entryPtr,
+ int objc, Tcl_Obj *const objv[]);
+static int DeleteChars(Entry *entryPtr, int index, int count);
+static void DestroyEntry(void *memPtr);
+static void DisplayEntry(ClientData clientData);
+static void EntryBlinkProc(ClientData clientData);
+static void EntryCmdDeletedProc(ClientData clientData);
+static void EntryComputeGeometry(Entry *entryPtr);
+static void EntryEventProc(ClientData clientData,
+ XEvent *eventPtr);
+static void EntryFocusProc(Entry *entryPtr, int gotFocus);
+static int EntryFetchSelection(ClientData clientData, int offset,
+ char *buffer, int maxBytes);
+static void EntryLostSelection(ClientData clientData);
+static void EventuallyRedraw(Entry *entryPtr);
+static void EntryScanTo(Entry *entryPtr, int y);
+static void EntrySetValue(Entry *entryPtr, const char *value);
+static void EntrySelectTo(Entry *entryPtr, int index);
+static char * EntryTextVarProc(ClientData clientData,
+ Tcl_Interp *interp, const char *name1,
+ const char *name2, int flags);
+static void EntryUpdateScrollbar(Entry *entryPtr);
+static int EntryValidate(Entry *entryPtr, char *cmd);
+static int EntryValidateChange(Entry *entryPtr, const char *change,
+ const char *newStr, int index, int type);
+static void ExpandPercents(Entry *entryPtr, const char *before,
+ const char *change, const char *newStr, int index,
+ int type, Tcl_DString *dsPtr);
+static int EntryValueChanged(Entry *entryPtr,
+ const char *newValue);
+static void EntryVisibleRange(Entry *entryPtr,
+ double *firstPtr, double *lastPtr);
+static int EntryWidgetObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static void EntryWorldChanged(ClientData instanceData);
+static int GetEntryIndex(Tcl_Interp *interp, Entry *entryPtr,
+ const char *string, int *indexPtr);
+static int InsertChars(Entry *entryPtr, int index, const char *string);
+
+/*
+ * These forward declarations are the spinbox specific ones:
+ */
+
+static int SpinboxWidgetObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int GetSpinboxElement(Spinbox *sbPtr, int x, int y);
+static int SpinboxInvoke(Tcl_Interp *interp, Spinbox *sbPtr,
+ int element);
+static int ComputeFormat(Spinbox *sbPtr);
+
+/*
+ * The structure below defines widget class behavior by means of functions
+ * that can be invoked from generic window code.
+ */
+
+static const Tk_ClassProcs entryClass = {
+ sizeof(Tk_ClassProcs), /* size */
+ EntryWorldChanged, /* worldChangedProc */
+ NULL, /* createProc */
+ NULL /* modalProc */
+};
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_EntryObjCmd --
+ *
+ * This function is invoked to process the "entry" 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_EntryObjCmd(
+ ClientData clientData, /* NULL. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ register Entry *entryPtr;
+ Tk_OptionTable optionTable;
+ Tk_Window tkwin;
+ char *tmp;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?");
+ return TCL_ERROR;
+ }
+
+ tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),
+ Tcl_GetString(objv[1]), NULL);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Create the option table for this widget class. If it has already been
+ * created, Tk will return the cached value.
+ */
+
+ optionTable = Tk_CreateOptionTable(interp, entryOptSpec);
+
+ /*
+ * Initialize the fields of the structure that won't be initialized by
+ * ConfigureEntry, or that ConfigureEntry requires to be initialized
+ * already (e.g. resource pointers). Only the non-NULL/0 data must be
+ * initialized as memset covers the rest.
+ */
+
+ entryPtr = ckalloc(sizeof(Entry));
+ memset(entryPtr, 0, sizeof(Entry));
+
+ entryPtr->tkwin = tkwin;
+ entryPtr->display = Tk_Display(tkwin);
+ entryPtr->interp = interp;
+ entryPtr->widgetCmd = Tcl_CreateObjCommand(interp,
+ Tk_PathName(entryPtr->tkwin), EntryWidgetObjCmd, entryPtr,
+ EntryCmdDeletedProc);
+ entryPtr->optionTable = optionTable;
+ entryPtr->type = TK_ENTRY;
+ tmp = ckalloc(1);
+ tmp[0] = '\0';
+ entryPtr->string = tmp;
+ entryPtr->selectFirst = -1;
+ entryPtr->selectLast = -1;
+
+ entryPtr->cursor = NULL;
+ entryPtr->exportSelection = 1;
+ entryPtr->justify = TK_JUSTIFY_LEFT;
+ entryPtr->relief = TK_RELIEF_FLAT;
+ entryPtr->state = STATE_NORMAL;
+ entryPtr->displayString = entryPtr->string;
+ entryPtr->inset = XPAD;
+ entryPtr->textGC = NULL;
+ entryPtr->selTextGC = NULL;
+ entryPtr->highlightGC = NULL;
+ entryPtr->avgWidth = 1;
+ entryPtr->validate = VALIDATE_NONE;
+
+ /*
+ * Keep a hold of the associated tkwin until we destroy the entry,
+ * otherwise Tk might free it while we still need it.
+ */
+
+ Tcl_Preserve(entryPtr->tkwin);
+
+ Tk_SetClass(entryPtr->tkwin, "Entry");
+ Tk_SetClassProcs(entryPtr->tkwin, &entryClass, entryPtr);
+ Tk_CreateEventHandler(entryPtr->tkwin,
+ ExposureMask|StructureNotifyMask|FocusChangeMask,
+ EntryEventProc, entryPtr);
+ Tk_CreateSelHandler(entryPtr->tkwin, XA_PRIMARY, XA_STRING,
+ EntryFetchSelection, entryPtr, XA_STRING);
+
+ if ((Tk_InitOptions(interp, (char *) entryPtr, optionTable, tkwin)
+ != TCL_OK) ||
+ (ConfigureEntry(interp, entryPtr, objc-2, objv+2) != TCL_OK)) {
+ Tk_DestroyWindow(entryPtr->tkwin);
+ return TCL_ERROR;
+ }
+
+ Tcl_SetObjResult(interp, TkNewWindowObj(entryPtr->tkwin));
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EntryWidgetObjCmd --
+ *
+ * This function is invoked to process the Tcl command that corresponds
+ * to a widget managed by this module. See the user documentation for
+ * details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+EntryWidgetObjCmd(
+ ClientData clientData, /* Information about entry widget. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Entry *entryPtr = clientData;
+ int cmdIndex, selIndex, result;
+ Tcl_Obj *objPtr;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Parse the widget command by looking up the second token in the list of
+ * valid command names.
+ */
+
+ result = Tcl_GetIndexFromObj(interp, objv[1], entryCmdNames, "option", 0,
+ &cmdIndex);
+ if (result != TCL_OK) {
+ return result;
+ }
+
+ Tcl_Preserve(entryPtr);
+ switch ((enum entryCmd) cmdIndex) {
+ case COMMAND_BBOX: {
+ int index, x, y, width, height;
+ Tcl_Obj *bbox[4];
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index");
+ goto error;
+ }
+ if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]),
+ &index) != TCL_OK) {
+ goto error;
+ }
+ if ((index == entryPtr->numChars) && (index > 0)) {
+ index--;
+ }
+ Tk_CharBbox(entryPtr->textLayout, index, &x, &y, &width, &height);
+ bbox[0] = Tcl_NewIntObj(x + entryPtr->layoutX);
+ bbox[1] = Tcl_NewIntObj(y + entryPtr->layoutY);
+ bbox[2] = Tcl_NewIntObj(width);
+ bbox[3] = Tcl_NewIntObj(height);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(4, bbox));
+ break;
+ }
+
+ case COMMAND_CGET:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option");
+ goto error;
+ }
+
+ objPtr = Tk_GetOptionValue(interp, (char *) entryPtr,
+ entryPtr->optionTable, objv[2], entryPtr->tkwin);
+ if (objPtr == NULL) {
+ goto error;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ break;
+
+ case COMMAND_CONFIGURE:
+ if (objc <= 3) {
+ objPtr = Tk_GetOptionInfo(interp, (char *) entryPtr,
+ entryPtr->optionTable,
+ (objc == 3) ? objv[2] : NULL,
+ entryPtr->tkwin);
+ if (objPtr == NULL) {
+ goto error;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ } else {
+ result = ConfigureEntry(interp, entryPtr, objc-2, objv+2);
+ }
+ break;
+
+ case COMMAND_DELETE: {
+ int first, last, code;
+
+ if ((objc < 3) || (objc > 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "firstIndex ?lastIndex?");
+ goto error;
+ }
+ if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]),
+ &first) != TCL_OK) {
+ goto error;
+ }
+ if (objc == 3) {
+ last = first + 1;
+ } else if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[3]),
+ &last) != TCL_OK) {
+ goto error;
+ }
+ if ((last >= first) && (entryPtr->state == STATE_NORMAL)) {
+ code = DeleteChars(entryPtr, first, last - first);
+ if (code != TCL_OK) {
+ goto error;
+ }
+ }
+ break;
+ }
+
+ case COMMAND_GET:
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ goto error;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(entryPtr->string, -1));
+ break;
+
+ case COMMAND_ICURSOR:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "pos");
+ goto error;
+ }
+ if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]),
+ &entryPtr->insertPos) != TCL_OK) {
+ goto error;
+ }
+ EventuallyRedraw(entryPtr);
+ break;
+
+ case COMMAND_INDEX: {
+ int index;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "string");
+ goto error;
+ }
+ if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]),
+ &index) != TCL_OK) {
+ goto error;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(index));
+ break;
+ }
+
+ case COMMAND_INSERT: {
+ int index, code;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index text");
+ goto error;
+ }
+ if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]),
+ &index) != TCL_OK) {
+ goto error;
+ }
+ if (entryPtr->state == STATE_NORMAL) {
+ code = InsertChars(entryPtr, index, Tcl_GetString(objv[3]));
+ if (code != TCL_OK) {
+ goto error;
+ }
+ }
+ break;
+ }
+
+ case COMMAND_SCAN: {
+ int x;
+ const char *minorCmd;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "mark|dragto x");
+ goto error;
+ }
+ if (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) {
+ goto error;
+ }
+
+ minorCmd = Tcl_GetString(objv[2]);
+ if (minorCmd[0] == 'm'
+ && (strncmp(minorCmd, "mark", strlen(minorCmd)) == 0)) {
+ entryPtr->scanMarkX = x;
+ entryPtr->scanMarkIndex = entryPtr->leftIndex;
+ } else if ((minorCmd[0] == 'd')
+ && (strncmp(minorCmd, "dragto", strlen(minorCmd)) == 0)) {
+ EntryScanTo(entryPtr, x);
+ } else {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad scan option \"%s\": must be mark or dragto",
+ minorCmd));
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "scan option",
+ minorCmd, NULL);
+ goto error;
+ }
+ break;
+ }
+
+ case COMMAND_SELECTION: {
+ int index, index2;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option ?index?");
+ goto error;
+ }
+
+ /*
+ * Parse the selection sub-command, using the command table
+ * "selCmdNames" defined above.
+ */
+
+ result = Tcl_GetIndexFromObj(interp, objv[2], selCmdNames,
+ "selection option", 0, &selIndex);
+ if (result != TCL_OK) {
+ goto error;
+ }
+
+ /*
+ * Disabled entries don't allow the selection to be modified, but
+ * 'selection present' must return a boolean.
+ */
+
+ if ((entryPtr->state == STATE_DISABLED)
+ && (selIndex != SELECTION_PRESENT)) {
+ goto done;
+ }
+
+ switch (selIndex) {
+ case SELECTION_ADJUST:
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index");
+ goto error;
+ }
+ if (GetEntryIndex(interp, entryPtr,
+ Tcl_GetString(objv[3]), &index) != TCL_OK) {
+ goto error;
+ }
+ if (entryPtr->selectFirst >= 0) {
+ int half1, half2;
+
+ half1 = (entryPtr->selectFirst + entryPtr->selectLast)/2;
+ half2 = (entryPtr->selectFirst + entryPtr->selectLast + 1)/2;
+ if (index < half1) {
+ entryPtr->selectAnchor = entryPtr->selectLast;
+ } else if (index > half2) {
+ entryPtr->selectAnchor = entryPtr->selectFirst;
+ } else {
+ /*
+ * We're at about the halfway point in the selection; just
+ * keep the existing anchor.
+ */
+ }
+ }
+ EntrySelectTo(entryPtr, index);
+ break;
+
+ case SELECTION_CLEAR:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ goto error;
+ }
+ if (entryPtr->selectFirst >= 0) {
+ entryPtr->selectFirst = -1;
+ entryPtr->selectLast = -1;
+ EventuallyRedraw(entryPtr);
+ }
+ goto done;
+
+ case SELECTION_FROM:
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index");
+ goto error;
+ }
+ if (GetEntryIndex(interp, entryPtr,
+ Tcl_GetString(objv[3]), &index) != TCL_OK) {
+ goto error;
+ }
+ entryPtr->selectAnchor = index;
+ break;
+
+ case SELECTION_PRESENT:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ goto error;
+ }
+ Tcl_SetObjResult(interp,
+ Tcl_NewBooleanObj(entryPtr->selectFirst >= 0));
+ goto done;
+
+ case SELECTION_RANGE:
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 3, objv, "start end");
+ goto error;
+ }
+ if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[3]),
+ &index) != TCL_OK) {
+ goto error;
+ }
+ if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[4]),
+ &index2) != TCL_OK) {
+ goto error;
+ }
+ if (index >= index2) {
+ entryPtr->selectFirst = -1;
+ entryPtr->selectLast = -1;
+ } else {
+ entryPtr->selectFirst = index;
+ entryPtr->selectLast = index2;
+ }
+ if (!(entryPtr->flags & GOT_SELECTION)
+ && (entryPtr->exportSelection)
+ && (!Tcl_IsSafe(entryPtr->interp))) {
+ Tk_OwnSelection(entryPtr->tkwin, XA_PRIMARY,
+ EntryLostSelection, entryPtr);
+ entryPtr->flags |= GOT_SELECTION;
+ }
+ EventuallyRedraw(entryPtr);
+ break;
+
+ case SELECTION_TO:
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index");
+ goto error;
+ }
+ if (GetEntryIndex(interp, entryPtr,
+ Tcl_GetString(objv[3]), &index) != TCL_OK) {
+ goto error;
+ }
+ EntrySelectTo(entryPtr, index);
+ break;
+ }
+ break;
+ }
+
+ case COMMAND_VALIDATE: {
+ int code;
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ goto error;
+ }
+ selIndex = entryPtr->validate;
+ entryPtr->validate = VALIDATE_ALL;
+ code = EntryValidateChange(entryPtr, NULL, entryPtr->string,
+ -1, VALIDATE_FORCED);
+ if (entryPtr->validate != VALIDATE_NONE) {
+ entryPtr->validate = selIndex;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(code == TCL_OK));
+ break;
+ }
+
+ case COMMAND_XVIEW: {
+ int index;
+
+ if (objc == 2) {
+ double first, last;
+ Tcl_Obj *span[2];
+
+ EntryVisibleRange(entryPtr, &first, &last);
+ span[0] = Tcl_NewDoubleObj(first);
+ span[1] = Tcl_NewDoubleObj(last);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(2, span));
+ goto done;
+ } else if (objc == 3) {
+ if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]),
+ &index) != TCL_OK) {
+ goto error;
+ }
+ } else {
+ double fraction;
+ int count;
+
+ index = entryPtr->leftIndex;
+ switch (Tk_GetScrollInfoObj(interp, objc, objv, &fraction,
+ &count)) {
+ case TK_SCROLL_ERROR:
+ goto error;
+ case TK_SCROLL_MOVETO:
+ index = (int) ((fraction * entryPtr->numChars) + 0.5);
+ break;
+ case TK_SCROLL_PAGES: {
+ int charsPerPage;
+
+ charsPerPage = ((Tk_Width(entryPtr->tkwin)
+ - 2 * entryPtr->inset) / entryPtr->avgWidth) - 2;
+ if (charsPerPage < 1) {
+ charsPerPage = 1;
+ }
+ index += count * charsPerPage;
+ break;
+ }
+ case TK_SCROLL_UNITS:
+ index += count;
+ break;
+ }
+ }
+ if (index >= entryPtr->numChars) {
+ index = entryPtr->numChars - 1;
+ }
+ if (index < 0) {
+ index = 0;
+ }
+ entryPtr->leftIndex = index;
+ entryPtr->flags |= UPDATE_SCROLLBAR;
+ EntryComputeGeometry(entryPtr);
+ EventuallyRedraw(entryPtr);
+ break;
+ }
+ }
+
+ done:
+ Tcl_Release(entryPtr);
+ return result;
+
+ error:
+ Tcl_Release(entryPtr);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyEntry --
+ *
+ * This function is invoked by Tcl_EventuallyFree or Tcl_Release to clean
+ * up the internal structure of an entry at a safe time (when no-one is
+ * using it anymore).
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Everything associated with the entry is freed up.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DestroyEntry(
+ void *memPtr) /* Info about entry widget. */
+{
+ Entry *entryPtr = memPtr;
+
+ /*
+ * Free up all the stuff that requires special handling, then let
+ * Tk_FreeOptions handle all the standard option-related stuff.
+ */
+
+ ckfree((char *)entryPtr->string);
+ if (entryPtr->textVarName != NULL) {
+ Tcl_UntraceVar2(entryPtr->interp, entryPtr->textVarName,
+ NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ EntryTextVarProc, entryPtr);
+ entryPtr->flags &= ~ENTRY_VAR_TRACED;
+ }
+ if (entryPtr->textGC != NULL) {
+ Tk_FreeGC(entryPtr->display, entryPtr->textGC);
+ }
+ if (entryPtr->selTextGC != NULL) {
+ Tk_FreeGC(entryPtr->display, entryPtr->selTextGC);
+ }
+ Tcl_DeleteTimerHandler(entryPtr->insertBlinkHandler);
+ if (entryPtr->displayString != entryPtr->string) {
+ ckfree((char *)entryPtr->displayString);
+ }
+ if (entryPtr->type == TK_SPINBOX) {
+ Spinbox *sbPtr = (Spinbox *) entryPtr;
+
+ if (sbPtr->listObj != NULL) {
+ Tcl_DecrRefCount(sbPtr->listObj);
+ sbPtr->listObj = NULL;
+ }
+ if (sbPtr->formatBuf) {
+ ckfree(sbPtr->formatBuf);
+ }
+ }
+ Tk_FreeTextLayout(entryPtr->textLayout);
+ Tk_FreeConfigOptions((char *) entryPtr, entryPtr->optionTable,
+ entryPtr->tkwin);
+ Tcl_Release(entryPtr->tkwin);
+ entryPtr->tkwin = NULL;
+
+ ckfree(entryPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConfigureEntry --
+ *
+ * This function is called to process an argv/argc list, plus the Tk
+ * option database, in order to configure (or reconfigure) an entry
+ * widget.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If TCL_ERROR is returned,
+ * then the interp's result contains an error message.
+ *
+ * Side effects:
+ * Configuration information, such as colors, border width, etc. get set
+ * for entryPtr; old resources get freed, if there were any.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ConfigureEntry(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Entry *entryPtr, /* Information about widget; may or may not
+ * already have values for some fields. */
+ int objc, /* Number of valid entries in argv. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Tk_SavedOptions savedOptions;
+ Tk_3DBorder border;
+ Tcl_Obj *errorResult = NULL;
+ Spinbox *sbPtr = (Spinbox *) entryPtr;
+ /* Only used when this widget is of type
+ * TK_SPINBOX */
+ char *oldValues = NULL; /* lint initialization */
+ char *oldFormat = NULL; /* lint initialization */
+ int error;
+ int oldExport = 0; /* lint initialization */
+ int valuesChanged = 0; /* lint initialization */
+ double oldFrom = 0.0; /* lint initialization */
+ double oldTo = 0.0; /* lint initialization */
+ int code;
+
+ /*
+ * Eliminate any existing trace on a variable monitored by the entry.
+ */
+
+ if ((entryPtr->textVarName != NULL)
+ && (entryPtr->flags & ENTRY_VAR_TRACED)) {
+ Tcl_UntraceVar2(interp, entryPtr->textVarName, NULL,
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ EntryTextVarProc, entryPtr);
+ entryPtr->flags &= ~ENTRY_VAR_TRACED;
+ }
+
+ /*
+ * Store old values that we need to effect certain behavior if they change
+ * value.
+ */
+
+ oldExport = (entryPtr->exportSelection) && (!Tcl_IsSafe(entryPtr->interp));
+ if (entryPtr->type == TK_SPINBOX) {
+ oldValues = sbPtr->valueStr;
+ oldFormat = sbPtr->reqFormat;
+ oldFrom = sbPtr->fromValue;
+ oldTo = sbPtr->toValue;
+ }
+
+ for (error = 0; error <= 1; error++) {
+ if (!error) {
+ /*
+ * First pass: set options to new values.
+ */
+
+ if (Tk_SetOptions(interp, (char *) entryPtr,
+ entryPtr->optionTable, objc, objv,
+ entryPtr->tkwin, &savedOptions, NULL) != TCL_OK) {
+ continue;
+ }
+ } else {
+ /*
+ * Second pass: restore options to old values.
+ */
+
+ errorResult = Tcl_GetObjResult(interp);
+ Tcl_IncrRefCount(errorResult);
+ Tk_RestoreSavedOptions(&savedOptions);
+ }
+
+ /*
+ * A few other options also need special processing, such as parsing
+ * the geometry and setting the background from a 3-D border.
+ */
+
+ if ((entryPtr->state == STATE_DISABLED) &&
+ (entryPtr->disabledBorder != NULL)) {
+ border = entryPtr->disabledBorder;
+ } else if ((entryPtr->state == STATE_READONLY) &&
+ (entryPtr->readonlyBorder != NULL)) {
+ border = entryPtr->readonlyBorder;
+ } else {
+ border = entryPtr->normalBorder;
+ }
+ Tk_SetBackgroundFromBorder(entryPtr->tkwin, border);
+
+ if (entryPtr->insertWidth <= 0) {
+ entryPtr->insertWidth = 2;
+ }
+ if (entryPtr->insertBorderWidth > entryPtr->insertWidth/2) {
+ entryPtr->insertBorderWidth = entryPtr->insertWidth/2;
+ }
+
+ if (entryPtr->type == TK_SPINBOX) {
+ if (sbPtr->fromValue > sbPtr->toValue) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "-to value must be greater than -from value",
+ -1));
+ Tcl_SetErrorCode(interp, "TK", "SPINBOX", "RANGE_SANITY",
+ NULL);
+ continue;
+ }
+
+ if (sbPtr->reqFormat && (oldFormat != sbPtr->reqFormat)) {
+ /*
+ * Make sure that the given format is somewhat correct, and
+ * calculate the minimum space we'll need for the values as
+ * strings.
+ */
+
+ int min, max;
+ size_t formatLen, formatSpace = TCL_DOUBLE_SPACE;
+ char fbuf[4], *fmt = sbPtr->reqFormat;
+
+ formatLen = strlen(fmt);
+ if ((fmt[0] != '%') || (fmt[formatLen-1] != 'f')) {
+ badFormatOpt:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad spinbox format specifier \"%s\"",
+ sbPtr->reqFormat));
+ Tcl_SetErrorCode(interp, "TK", "SPINBOX", "FORMAT_SANITY",
+ NULL);
+ continue;
+ }
+ if ((sscanf(fmt, "%%%d.%d%[f]", &min, &max, fbuf) == 3)
+ && (max >= 0)) {
+ formatSpace = min + max + 1;
+ } else if (((sscanf(fmt, "%%.%d%[f]", &min, fbuf) == 2)
+ || (sscanf(fmt, "%%%d%[f]", &min, fbuf) == 2)
+ || (sscanf(fmt, "%%%d.%[f]", &min, fbuf) == 2))
+ && (min >= 0)) {
+ formatSpace = min + 1;
+ } else {
+ goto badFormatOpt;
+ }
+ if (formatSpace < TCL_DOUBLE_SPACE) {
+ formatSpace = TCL_DOUBLE_SPACE;
+ }
+ sbPtr->formatBuf = ckrealloc(sbPtr->formatBuf, formatSpace);
+
+ /*
+ * We perturb the value of oldFrom to allow us to go into the
+ * branch below that will reformat the displayed value.
+ */
+
+ oldFrom = sbPtr->fromValue - 1;
+ }
+
+ /*
+ * See if we have to rearrange our listObj data.
+ */
+
+ if (oldValues != sbPtr->valueStr) {
+ if (sbPtr->listObj != NULL) {
+ Tcl_DecrRefCount(sbPtr->listObj);
+ }
+ sbPtr->listObj = NULL;
+ if (sbPtr->valueStr != NULL) {
+ Tcl_Obj *newObjPtr;
+ int nelems;
+
+ newObjPtr = Tcl_NewStringObj(sbPtr->valueStr, -1);
+ if (Tcl_ListObjLength(interp, newObjPtr, &nelems)
+ != TCL_OK) {
+ valuesChanged = -1;
+ continue;
+ }
+ sbPtr->listObj = newObjPtr;
+ Tcl_IncrRefCount(sbPtr->listObj);
+ sbPtr->nElements = nelems;
+ sbPtr->eIndex = 0;
+ valuesChanged++;
+ }
+ }
+ }
+
+ /*
+ * Restart the cursor timing sequence in case the on-time or off-time
+ * just changed. Set validate temporarily to none, so the configure
+ * doesn't cause it to be triggered.
+ */
+
+ if (entryPtr->flags & GOT_FOCUS) {
+ int validate = entryPtr->validate;
+
+ entryPtr->validate = VALIDATE_NONE;
+ EntryFocusProc(entryPtr, 1);
+ entryPtr->validate = validate;
+ }
+
+ /*
+ * Claim the selection if we've suddenly started exporting it.
+ */
+
+ if (entryPtr->exportSelection && (!oldExport)
+ && (!Tcl_IsSafe(entryPtr->interp))
+ && (entryPtr->selectFirst != -1)
+ && !(entryPtr->flags & GOT_SELECTION)) {
+ Tk_OwnSelection(entryPtr->tkwin, XA_PRIMARY, EntryLostSelection,
+ entryPtr);
+ entryPtr->flags |= GOT_SELECTION;
+ }
+
+ /*
+ * Recompute the window's geometry and arrange for it to be
+ * redisplayed.
+ */
+
+ Tk_SetInternalBorder(entryPtr->tkwin,
+ entryPtr->borderWidth + entryPtr->highlightWidth);
+ if (entryPtr->highlightWidth <= 0) {
+ entryPtr->highlightWidth = 0;
+ }
+ entryPtr->inset = entryPtr->highlightWidth
+ + entryPtr->borderWidth + XPAD;
+ break;
+ }
+ if (!error) {
+ Tk_FreeSavedOptions(&savedOptions);
+ }
+
+ /*
+ * If the entry is tied to the value of a variable, create the variable if
+ * it doesn't exist, and set the entry's value from the variable's value.
+ */
+
+ if (entryPtr->textVarName != NULL) {
+ const char *value;
+
+ value = Tcl_GetVar2(interp, entryPtr->textVarName, NULL, TCL_GLOBAL_ONLY);
+ if (value == NULL) {
+
+ /*
+ * Since any trace on the textvariable was eliminated above,
+ * the only possible reason for EntryValueChanged to return
+ * an error is that the textvariable lives in a namespace
+ * that does not (yet) exist. Indeed, namespaces are not
+ * automatically created as needed. Don't trap this error
+ * here, better do it below when attempting to trace the
+ * variable.
+ */
+
+ EntryValueChanged(entryPtr, NULL);
+ } else {
+ EntrySetValue(entryPtr, value);
+ }
+ }
+
+ if (entryPtr->type == TK_SPINBOX) {
+ ComputeFormat(sbPtr);
+
+ if (valuesChanged > 0) {
+ Tcl_Obj *objPtr;
+
+ /*
+ * No check for error return, because there shouldn't be one given
+ * the check for valid list above.
+ */
+
+ Tcl_ListObjIndex(interp, sbPtr->listObj, 0, &objPtr);
+
+ /*
+ * No check for error return here as well, because any possible
+ * error will be trapped below when attempting tracing.
+ */
+
+ EntryValueChanged(entryPtr, Tcl_GetString(objPtr));
+ } else if ((sbPtr->valueStr == NULL)
+ && !DOUBLES_EQ(sbPtr->fromValue, sbPtr->toValue)
+ && (!DOUBLES_EQ(sbPtr->fromValue, oldFrom)
+ || !DOUBLES_EQ(sbPtr->toValue, oldTo))) {
+ /*
+ * If the valueStr is empty and -from && -to are specified, check
+ * to see if the current string is within the range. If not, it
+ * will be constrained to the nearest edge. If the current string
+ * isn't a double value, we set it to -from.
+ */
+
+ double dvalue;
+
+ if (sscanf(entryPtr->string, "%lf", &dvalue) <= 0) {
+ /* Scan failure */
+ dvalue = sbPtr->fromValue;
+ } else if (dvalue > sbPtr->toValue) {
+ dvalue = sbPtr->toValue;
+ } else if (dvalue < sbPtr->fromValue) {
+ dvalue = sbPtr->fromValue;
+ }
+ sprintf(sbPtr->formatBuf, sbPtr->valueFormat, dvalue);
+
+ /*
+ * No check for error return here as well, because any possible
+ * error will be trapped below when attempting tracing.
+ */
+
+ EntryValueChanged(entryPtr, sbPtr->formatBuf);
+ }
+ }
+
+ /*
+ * Set up a trace on the variable's value after we've possibly constrained
+ * the value according to new -from/-to values.
+ */
+
+ if ((entryPtr->textVarName != NULL)
+ && !(entryPtr->flags & ENTRY_VAR_TRACED)) {
+ code = Tcl_TraceVar2(interp, entryPtr->textVarName,
+ NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ EntryTextVarProc, entryPtr);
+ if (code != TCL_OK) {
+ return TCL_ERROR;
+ }
+ entryPtr->flags |= ENTRY_VAR_TRACED;
+ }
+
+ EntryWorldChanged(entryPtr);
+ if (error) {
+ Tcl_SetObjResult(interp, errorResult);
+ Tcl_DecrRefCount(errorResult);
+ return TCL_ERROR;
+ } else {
+ return TCL_OK;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * EntryWorldChanged --
+ *
+ * This function is called when the world has changed in some way and the
+ * widget needs to recompute all its graphics contexts and determine its
+ * new geometry.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Entry will be relayed out and redisplayed.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+EntryWorldChanged(
+ ClientData instanceData) /* Information about widget. */
+{
+ XGCValues gcValues;
+ GC gc = NULL;
+ unsigned long mask;
+ Tk_3DBorder border;
+ XColor *colorPtr;
+ Entry *entryPtr = instanceData;
+
+ entryPtr->avgWidth = Tk_TextWidth(entryPtr->tkfont, "0", 1);
+ if (entryPtr->avgWidth == 0) {
+ entryPtr->avgWidth = 1;
+ }
+
+ if (entryPtr->type == TK_SPINBOX) {
+ /*
+ * Compute the button width for a spinbox
+ */
+
+ entryPtr->xWidth = entryPtr->avgWidth + 2 * (1+XPAD);
+ if (entryPtr->xWidth < 11) {
+ entryPtr->xWidth = 11; /* we want a min visible size */
+ }
+ }
+
+ /*
+ * Default background and foreground are from the normal state. In a
+ * disabled state, both of those may be overridden; in the readonly state,
+ * the background may be overridden.
+ */
+
+ border = entryPtr->normalBorder;
+ colorPtr = entryPtr->fgColorPtr;
+ switch (entryPtr->state) {
+ case STATE_DISABLED:
+ if (entryPtr->disabledBorder != NULL) {
+ border = entryPtr->disabledBorder;
+ }
+ if (entryPtr->dfgColorPtr != NULL) {
+ colorPtr = entryPtr->dfgColorPtr;
+ }
+ break;
+ case STATE_READONLY:
+ if (entryPtr->readonlyBorder != NULL) {
+ border = entryPtr->readonlyBorder;
+ }
+ break;
+ }
+
+ Tk_SetBackgroundFromBorder(entryPtr->tkwin, border);
+ gcValues.foreground = colorPtr->pixel;
+ gcValues.font = Tk_FontId(entryPtr->tkfont);
+ gcValues.graphics_exposures = False;
+ mask = GCForeground | GCFont | GCGraphicsExposures;
+ gc = Tk_GetGC(entryPtr->tkwin, mask, &gcValues);
+ if (entryPtr->textGC != NULL) {
+ Tk_FreeGC(entryPtr->display, entryPtr->textGC);
+ }
+ entryPtr->textGC = gc;
+
+ if (entryPtr->selFgColorPtr != NULL) {
+ gcValues.foreground = entryPtr->selFgColorPtr->pixel;
+ }
+ gcValues.font = Tk_FontId(entryPtr->tkfont);
+ mask = GCForeground | GCFont;
+ gc = Tk_GetGC(entryPtr->tkwin, mask, &gcValues);
+ if (entryPtr->selTextGC != NULL) {
+ Tk_FreeGC(entryPtr->display, entryPtr->selTextGC);
+ }
+ entryPtr->selTextGC = gc;
+
+ /*
+ * Recompute the window's geometry and arrange for it to be redisplayed.
+ */
+
+ EntryComputeGeometry(entryPtr);
+ entryPtr->flags |= UPDATE_SCROLLBAR;
+ EventuallyRedraw(entryPtr);
+}
+
+#ifndef MAC_OSX_TK
+/*
+ *--------------------------------------------------------------
+ *
+ * TkpDrawEntryBorderAndFocus --
+ *
+ * This function redraws the border of an entry widget. It overrides the
+ * generic border drawing code if the entry widget parameters are such
+ * that the native widget drawing is a good fit. This version just
+ * returns 0, so platforms that don't do special native drawing don't
+ * have to implement it.
+ *
+ * Results:
+ * 1 if it has drawn the border, 0 if not.
+ *
+ * Side effects:
+ * May draw the entry border into pixmap.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkpDrawEntryBorderAndFocus(
+ Entry *entryPtr,
+ Drawable pixmap,
+ int isSpinbox)
+{
+ return 0;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkpDrawSpinboxButtons --
+ *
+ * This function redraws the buttons of an spinbox widget. It overrides
+ * the generic button drawing code if the spinbox widget parameters are
+ * such that the native widget drawing is a good fit. This version just
+ * returns 0, so platforms that don't do special native drawing don't
+ * have to implement it.
+ *
+ * Results:
+ * 1 if it has drawn the border, 0 if not.
+ *
+ * Side effects:
+ * May draw the entry border into pixmap.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkpDrawSpinboxButtons(
+ Spinbox *sbPtr,
+ Pixmap pixmap)
+{
+ return 0;
+}
+#endif /* Not MAC_OSX_TK */
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DisplayEntry --
+ *
+ * This function redraws the contents of an entry window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Information appears on the screen.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+DisplayEntry(
+ ClientData clientData) /* Information about window. */
+{
+ Entry *entryPtr = clientData;
+ Tk_Window tkwin = entryPtr->tkwin;
+ int baseY, selStartX, selEndX, cursorX;
+ int showSelection, xBound;
+ Tk_FontMetrics fm;
+ Pixmap pixmap;
+ Tk_3DBorder border;
+
+ entryPtr->flags &= ~REDRAW_PENDING;
+ if ((entryPtr->flags & ENTRY_DELETED) || !Tk_IsMapped(tkwin)) {
+ return;
+ }
+
+ Tk_GetFontMetrics(entryPtr->tkfont, &fm);
+
+ /*
+ * Update the scrollbar if that's needed.
+ */
+
+ if (entryPtr->flags & UPDATE_SCROLLBAR) {
+ entryPtr->flags &= ~UPDATE_SCROLLBAR;
+
+ /*
+ * Preserve/Release because updating the scrollbar can have the
+ * side-effect of destroying or unmapping the entry widget.
+ */
+
+ Tcl_Preserve(entryPtr);
+ EntryUpdateScrollbar(entryPtr);
+
+ if ((entryPtr->flags & ENTRY_DELETED) || !Tk_IsMapped(tkwin)) {
+ Tcl_Release(entryPtr);
+ return;
+ }
+ Tcl_Release(entryPtr);
+ }
+
+#ifndef TK_NO_DOUBLE_BUFFERING
+ /*
+ * In order to avoid screen flashes, this function redraws the textual
+ * area of the entry into off-screen memory, then copies it back on-screen
+ * in a single operation. This means there's no point in time where the
+ * on-screen image has been cleared.
+ */
+
+ pixmap = Tk_GetPixmap(entryPtr->display, Tk_WindowId(tkwin),
+ Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));
+#else
+ pixmap = Tk_WindowId(tkwin);
+#endif /* TK_NO_DOUBLE_BUFFERING */
+
+ /*
+ * Compute x-coordinate of the pixel just after last visible one, plus
+ * vertical position of baseline of text.
+ */
+
+ xBound = Tk_Width(tkwin) - entryPtr->inset - entryPtr->xWidth;
+ baseY = (Tk_Height(tkwin) + fm.ascent - fm.descent) / 2;
+
+ /*
+ * Hide the selection whenever we don't have the focus, unless we
+ * always want to show selection.
+ */
+ if (TkpAlwaysShowSelection(entryPtr->tkwin)) {
+ showSelection = 1;
+ } else {
+ showSelection = (entryPtr->flags & GOT_FOCUS);
+ }
+
+ /*
+ * Draw the background in three layers. From bottom to top the layers are:
+ * normal background, selection background, and insertion cursor
+ * background.
+ */
+
+ if ((entryPtr->state == STATE_DISABLED) &&
+ (entryPtr->disabledBorder != NULL)) {
+ border = entryPtr->disabledBorder;
+ } else if ((entryPtr->state == STATE_READONLY) &&
+ (entryPtr->readonlyBorder != NULL)) {
+ border = entryPtr->readonlyBorder;
+ } else {
+ border = entryPtr->normalBorder;
+ }
+ Tk_Fill3DRectangle(tkwin, pixmap, border,
+ 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);
+
+ if (showSelection && (entryPtr->state != STATE_DISABLED)
+ && (entryPtr->selectLast > entryPtr->leftIndex)) {
+ if (entryPtr->selectFirst <= entryPtr->leftIndex) {
+ selStartX = entryPtr->leftX;
+ } else {
+ Tk_CharBbox(entryPtr->textLayout, entryPtr->selectFirst,
+ &selStartX, NULL, NULL, NULL);
+ selStartX += entryPtr->layoutX;
+ }
+ if ((selStartX - entryPtr->selBorderWidth) < xBound) {
+ Tk_CharBbox(entryPtr->textLayout, entryPtr->selectLast,
+ &selEndX, NULL, NULL, NULL);
+ selEndX += entryPtr->layoutX;
+ Tk_Fill3DRectangle(tkwin, pixmap, entryPtr->selBorder,
+ selStartX - entryPtr->selBorderWidth,
+ baseY - fm.ascent - entryPtr->selBorderWidth,
+ (selEndX - selStartX) + 2*entryPtr->selBorderWidth,
+ (fm.ascent + fm.descent) + 2*entryPtr->selBorderWidth,
+ entryPtr->selBorderWidth,
+#ifndef MAC_OSX_TK
+ TK_RELIEF_RAISED
+#else
+ MAC_OSX_ENTRY_SELECT_RELIEF
+#endif
+ );
+ }
+ }
+
+ /*
+ * Draw a special background for the insertion cursor, overriding even the
+ * selection background. As a special hack to keep the cursor visible when
+ * the insertion cursor color is the same as the color for selected text
+ * (e.g., on mono displays), write background in the cursor area (instead
+ * of nothing) when the cursor isn't on. Otherwise the selection would
+ * hide the cursor.
+ */
+
+ if ((entryPtr->state == STATE_NORMAL) && (entryPtr->flags & GOT_FOCUS)) {
+ Tk_CharBbox(entryPtr->textLayout, entryPtr->insertPos, &cursorX, NULL,
+ NULL, NULL);
+ cursorX += entryPtr->layoutX;
+ cursorX -= (entryPtr->insertWidth == 1) ? 1 : (entryPtr->insertWidth)/2;
+ Tk_SetCaretPos(entryPtr->tkwin, cursorX, baseY - fm.ascent,
+ fm.ascent + fm.descent);
+ if (entryPtr->insertPos >= entryPtr->leftIndex && cursorX < xBound) {
+ if (entryPtr->flags & CURSOR_ON) {
+ Tk_Fill3DRectangle(tkwin, pixmap, entryPtr->insertBorder,
+ cursorX, baseY - fm.ascent, entryPtr->insertWidth,
+ fm.ascent + fm.descent, entryPtr->insertBorderWidth,
+ TK_RELIEF_RAISED);
+ } else if (entryPtr->insertBorder == entryPtr->selBorder) {
+ Tk_Fill3DRectangle(tkwin, pixmap, border, cursorX,
+ baseY - fm.ascent, entryPtr->insertWidth,
+ fm.ascent + fm.descent, 0, TK_RELIEF_FLAT);
+ }
+ }
+ }
+
+ /*
+ * Draw the text in two pieces: first the unselected portion, then the
+ * selected portion on top of it.
+ */
+
+ Tk_DrawTextLayout(entryPtr->display, pixmap, entryPtr->textGC,
+ entryPtr->textLayout, entryPtr->layoutX, entryPtr->layoutY,
+ entryPtr->leftIndex, entryPtr->numChars);
+
+ if (showSelection && (entryPtr->state != STATE_DISABLED)
+ && (entryPtr->selTextGC != entryPtr->textGC)
+ && (entryPtr->selectFirst < entryPtr->selectLast)) {
+ int selFirst;
+
+ if (entryPtr->selectFirst < entryPtr->leftIndex) {
+ selFirst = entryPtr->leftIndex;
+ } else {
+ selFirst = entryPtr->selectFirst;
+ }
+ Tk_DrawTextLayout(entryPtr->display, pixmap, entryPtr->selTextGC,
+ entryPtr->textLayout, entryPtr->layoutX, entryPtr->layoutY,
+ selFirst, entryPtr->selectLast);
+ }
+
+ if (entryPtr->type == TK_SPINBOX) {
+ int startx, height, inset, pad, tHeight, xWidth;
+ Spinbox *sbPtr = (Spinbox *) entryPtr;
+
+ /*
+ * Draw the spin button controls.
+ */
+
+ if (TkpDrawSpinboxButtons(sbPtr, pixmap) == 0) {
+ xWidth = entryPtr->xWidth;
+ pad = XPAD + 1;
+ inset = entryPtr->inset - XPAD;
+ startx = Tk_Width(tkwin) - (xWidth + inset);
+ height = (Tk_Height(tkwin) - 2*inset)/2;
+#if 0
+ Tk_Fill3DRectangle(tkwin, pixmap, sbPtr->buttonBorder,
+ startx, inset, xWidth, height, 1, sbPtr->buRelief);
+ Tk_Fill3DRectangle(tkwin, pixmap, sbPtr->buttonBorder,
+ startx, inset+height, xWidth, height, 1, sbPtr->bdRelief);
+#else
+ Tk_Fill3DRectangle(tkwin, pixmap, sbPtr->buttonBorder,
+ startx, inset, xWidth, height, 1,
+ (sbPtr->selElement == SEL_BUTTONUP) ?
+ TK_RELIEF_SUNKEN : TK_RELIEF_RAISED);
+ Tk_Fill3DRectangle(tkwin, pixmap, sbPtr->buttonBorder,
+ startx, inset+height, xWidth, height, 1,
+ (sbPtr->selElement == SEL_BUTTONDOWN) ?
+ TK_RELIEF_SUNKEN : TK_RELIEF_RAISED);
+#endif
+
+ xWidth -= 2*pad;
+
+ /*
+ * Only draw the triangles if we have enough display space
+ */
+
+ if ((xWidth > 1)) {
+ XPoint points[3];
+ int starty, space, offset;
+
+ space = height - 2*pad;
+
+ /*
+ * Ensure width of triangle is odd to guarantee a sharp tip
+ */
+
+ if (!(xWidth % 2)) {
+ xWidth++;
+ }
+ tHeight = (xWidth + 1) / 2;
+ if (tHeight > space) {
+ tHeight = space;
+ }
+ space = (space - tHeight) / 2;
+ startx += pad;
+ starty = inset + height - pad - space;
+ offset = (sbPtr->selElement == SEL_BUTTONUP);
+
+ /*
+ * The points are slightly different for the up and down
+ * arrows because (for *.x), we need to account for a bug in
+ * the way XFillPolygon draws triangles, and we want to shift
+ * the arrows differently when allowing for depressed
+ * behavior.
+ */
+
+ points[0].x = startx + offset;
+ points[0].y = starty + (offset ? 0 : -1);
+ points[1].x = startx + xWidth/2 + offset;
+ points[1].y = starty - tHeight + (offset ? 0 : -1);
+ points[2].x = startx + xWidth + offset;
+ points[2].y = points[0].y;
+ XFillPolygon(entryPtr->display, pixmap, entryPtr->textGC,
+ points, 3, Convex, CoordModeOrigin);
+
+ starty = inset + height + pad + space;
+ offset = (sbPtr->selElement == SEL_BUTTONDOWN);
+ points[0].x = startx + 1 + offset;
+ points[0].y = starty + (offset ? 1 : 0);
+ points[1].x = startx + xWidth/2 + offset;
+ points[1].y = starty + tHeight + (offset ? 0 : -1);
+ points[2].x = startx - 1 + xWidth + offset;
+ points[2].y = points[0].y;
+ XFillPolygon(entryPtr->display, pixmap, entryPtr->textGC,
+ points, 3, Convex, CoordModeOrigin);
+ }
+ }
+ }
+
+ /*
+ * Draw the border and focus highlight last, so they will overwrite any
+ * text that extends past the viewable part of the window.
+ */
+
+ if (!TkpDrawEntryBorderAndFocus(entryPtr, pixmap,
+ (entryPtr->type == TK_SPINBOX))) {
+ xBound = entryPtr->highlightWidth;
+ if (entryPtr->relief != TK_RELIEF_FLAT) {
+ Tk_Draw3DRectangle(tkwin, pixmap, border, xBound, xBound,
+ Tk_Width(tkwin) - 2 * xBound,
+ Tk_Height(tkwin) - 2 * xBound,
+ entryPtr->borderWidth, entryPtr->relief);
+ }
+ if (xBound > 0) {
+ GC fgGC, bgGC;
+
+ bgGC = Tk_GCForColor(entryPtr->highlightBgColorPtr, pixmap);
+ if (entryPtr->flags & GOT_FOCUS) {
+ fgGC = Tk_GCForColor(entryPtr->highlightColorPtr, pixmap);
+ TkpDrawHighlightBorder(tkwin, fgGC, bgGC, xBound, pixmap);
+ } else {
+ TkpDrawHighlightBorder(tkwin, bgGC, bgGC, xBound, pixmap);
+ }
+ }
+ }
+
+#ifndef TK_NO_DOUBLE_BUFFERING
+ /*
+ * Everything's been redisplayed; now copy the pixmap onto the screen and
+ * free up the pixmap.
+ */
+
+ XCopyArea(entryPtr->display, pixmap, Tk_WindowId(tkwin), entryPtr->textGC,
+ 0, 0, (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin),
+ 0, 0);
+ Tk_FreePixmap(entryPtr->display, pixmap);
+#endif /* TK_NO_DOUBLE_BUFFERING */
+ entryPtr->flags &= ~BORDER_NEEDED;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EntryComputeGeometry --
+ *
+ * This function is invoked to recompute information about where in its
+ * window an entry's string will be displayed. It also computes the
+ * requested size for the window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The leftX and tabOrigin fields are recomputed for entryPtr, and
+ * leftIndex may be adjusted. Tk_GeometryRequest is called to register
+ * the desired dimensions for the window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+EntryComputeGeometry(
+ Entry *entryPtr) /* Widget record for entry. */
+{
+ int totalLength, overflow, maxOffScreen, rightX;
+ int height, width, i;
+ Tk_FontMetrics fm;
+ char *p;
+
+ if (entryPtr->displayString != entryPtr->string) {
+ ckfree((char *)entryPtr->displayString);
+ entryPtr->displayString = entryPtr->string;
+ entryPtr->numDisplayBytes = entryPtr->numBytes;
+ }
+
+ /*
+ * If we're displaying a special character instead of the value of the
+ * entry, recompute the displayString.
+ */
+
+ if (entryPtr->showChar != NULL) {
+ int ch;
+ char buf[6];
+ int size;
+
+ /*
+ * Normalize the special character so we can safely duplicate it in
+ * the display string. If we didn't do this, then two malformed
+ * characters might end up looking like one valid UTF character in the
+ * resulting string.
+ */
+
+ TkUtfToUniChar(entryPtr->showChar, &ch);
+ size = TkUniCharToUtf(ch, buf);
+
+ entryPtr->numDisplayBytes = entryPtr->numChars * size;
+ p = ckalloc(entryPtr->numDisplayBytes + 1);
+ entryPtr->displayString = p;
+
+ for (i = entryPtr->numChars; --i >= 0; ) {
+ memcpy(p, buf, size);
+ p += size;
+ }
+ *p = '\0';
+ }
+
+ Tk_FreeTextLayout(entryPtr->textLayout);
+ entryPtr->textLayout = Tk_ComputeTextLayout(entryPtr->tkfont,
+ entryPtr->displayString, entryPtr->numChars, 0,
+ entryPtr->justify, TK_IGNORE_NEWLINES, &totalLength, &height);
+
+ entryPtr->layoutY = (Tk_Height(entryPtr->tkwin) - height) / 2;
+
+ /*
+ * Recompute where the leftmost character on the display will be drawn
+ * (entryPtr->leftX) and adjust leftIndex if necessary so that we don't
+ * let characters hang off the edge of the window unless the entire window
+ * is full.
+ */
+
+ overflow = totalLength -
+ (Tk_Width(entryPtr->tkwin) - 2*entryPtr->inset - entryPtr->xWidth);
+ if (overflow <= 0) {
+ entryPtr->leftIndex = 0;
+ if (entryPtr->justify == TK_JUSTIFY_LEFT) {
+ entryPtr->leftX = entryPtr->inset;
+ } else if (entryPtr->justify == TK_JUSTIFY_RIGHT) {
+ entryPtr->leftX = Tk_Width(entryPtr->tkwin) - entryPtr->inset
+ - entryPtr->xWidth - totalLength;
+ } else {
+ entryPtr->leftX = (Tk_Width(entryPtr->tkwin)
+ - entryPtr->xWidth - totalLength)/2;
+ }
+ entryPtr->layoutX = entryPtr->leftX;
+ } else {
+ /*
+ * The whole string can't fit in the window. Compute the maximum
+ * number of characters that may be off-screen to the left without
+ * leaving empty space on the right of the window, then don't let
+ * leftIndex be any greater than that.
+ */
+
+ maxOffScreen = Tk_PointToChar(entryPtr->textLayout, overflow, 0);
+ Tk_CharBbox(entryPtr->textLayout, maxOffScreen,
+ &rightX, NULL, NULL, NULL);
+ if (rightX < overflow) {
+ maxOffScreen++;
+ }
+ if (entryPtr->leftIndex > maxOffScreen) {
+ entryPtr->leftIndex = maxOffScreen;
+ }
+ Tk_CharBbox(entryPtr->textLayout, entryPtr->leftIndex, &rightX,
+ NULL, NULL, NULL);
+ entryPtr->leftX = entryPtr->inset;
+ entryPtr->layoutX = entryPtr->leftX - rightX;
+ }
+
+ Tk_GetFontMetrics(entryPtr->tkfont, &fm);
+ height = fm.linespace + 2*entryPtr->inset + 2*(YPAD-XPAD);
+ if (entryPtr->prefWidth > 0) {
+ width = entryPtr->prefWidth*entryPtr->avgWidth + 2*entryPtr->inset;
+ } else if (totalLength == 0) {
+ width = entryPtr->avgWidth + 2*entryPtr->inset;
+ } else {
+ width = totalLength + 2*entryPtr->inset;
+ }
+
+ /*
+ * Add one extra length for the spin buttons
+ */
+ width += entryPtr->xWidth;
+
+ Tk_GeometryRequest(entryPtr->tkwin, width, height);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InsertChars --
+ *
+ * Add new characters to an entry widget.
+ *
+ * Results:
+ * A standard Tcl result. If an error occurred then an error message is
+ * left in the interp's result.
+ *
+ * Side effects:
+ * New information gets added to entryPtr; it will be redisplayed soon,
+ * but not necessarily immediately.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+InsertChars(
+ Entry *entryPtr, /* Entry that is to get the new elements. */
+ int index, /* Add the new elements before this character
+ * index. */
+ const char *value) /* New characters to add (NULL-terminated
+ * string). */
+{
+ ptrdiff_t byteIndex;
+ size_t byteCount, newByteCount;
+ int oldChars, charsAdded;
+ const char *string;
+ char *newStr;
+
+ string = entryPtr->string;
+ byteIndex = Tcl_UtfAtIndex(string, index) - string;
+ byteCount = strlen(value);
+ if (byteCount == 0) {
+ return TCL_OK;
+ }
+
+ newByteCount = entryPtr->numBytes + byteCount + 1;
+ newStr = ckalloc(newByteCount);
+ memcpy(newStr, string, byteIndex);
+ strcpy(newStr + byteIndex, value);
+ strcpy(newStr + byteIndex + byteCount, string + byteIndex);
+
+ if ((entryPtr->validate == VALIDATE_KEY ||
+ entryPtr->validate == VALIDATE_ALL) &&
+ EntryValidateChange(entryPtr, value, newStr, index,
+ VALIDATE_INSERT) != TCL_OK) {
+ ckfree(newStr);
+ return TCL_OK;
+ }
+
+ ckfree((char *)string);
+ entryPtr->string = newStr;
+
+ /*
+ * The following construction is used because inserting improperly formed
+ * UTF-8 sequences between other improperly formed UTF-8 sequences could
+ * result in actually forming valid UTF-8 sequences; the number of
+ * characters added may not be Tcl_NumUtfChars(string, -1), because of
+ * context. The actual number of characters added is how many characters
+ * are in the string now minus the number that used to be there.
+ */
+
+ oldChars = entryPtr->numChars;
+ entryPtr->numChars = Tcl_NumUtfChars(newStr, -1);
+ charsAdded = entryPtr->numChars - oldChars;
+ entryPtr->numBytes += byteCount;
+
+ if (entryPtr->displayString == string) {
+ entryPtr->displayString = newStr;
+ entryPtr->numDisplayBytes = entryPtr->numBytes;
+ }
+
+ /*
+ * Inserting characters invalidates all indexes into the string. Touch up
+ * the indexes so that they still refer to the same characters (at new
+ * positions). When updating the selection end-points, don't include the
+ * new text in the selection unless it was completely surrounded by the
+ * selection.
+ */
+
+ if (entryPtr->selectFirst >= index) {
+ entryPtr->selectFirst += charsAdded;
+ }
+ if (entryPtr->selectLast > index) {
+ entryPtr->selectLast += charsAdded;
+ }
+ if ((entryPtr->selectAnchor > index) || (entryPtr->selectFirst >= index)) {
+ entryPtr->selectAnchor += charsAdded;
+ }
+ if (entryPtr->leftIndex > index) {
+ entryPtr->leftIndex += charsAdded;
+ }
+ if (entryPtr->insertPos >= index) {
+ entryPtr->insertPos += charsAdded;
+ }
+ return EntryValueChanged(entryPtr, NULL);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DeleteChars --
+ *
+ * Remove one or more characters from an entry widget.
+ *
+ * Results:
+ * A standard Tcl result. If an error occurred then an error message is
+ * left in the interp's result.
+ *
+ * Side effects:
+ * Memory gets freed, the entry gets modified and (eventually)
+ * redisplayed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DeleteChars(
+ Entry *entryPtr, /* Entry widget to modify. */
+ int index, /* Index of first character to delete. */
+ int count) /* How many characters to delete. */
+{
+ int byteIndex, byteCount, newByteCount;
+ const char *string;
+ char *newStr, *toDelete;
+
+ if ((index + count) > entryPtr->numChars) {
+ count = entryPtr->numChars - index;
+ }
+ if (count <= 0) {
+ return TCL_OK;
+ }
+
+ string = entryPtr->string;
+ byteIndex = Tcl_UtfAtIndex(string, index) - string;
+ byteCount = Tcl_UtfAtIndex(string + byteIndex, count) - (string+byteIndex);
+
+ newByteCount = entryPtr->numBytes + 1 - byteCount;
+ newStr = ckalloc(newByteCount);
+ memcpy(newStr, string, (size_t) byteIndex);
+ strcpy(newStr + byteIndex, string + byteIndex + byteCount);
+
+ toDelete = ckalloc(byteCount + 1);
+ memcpy(toDelete, string + byteIndex, (size_t) byteCount);
+ toDelete[byteCount] = '\0';
+
+ if ((entryPtr->validate == VALIDATE_KEY ||
+ entryPtr->validate == VALIDATE_ALL) &&
+ EntryValidateChange(entryPtr, toDelete, newStr, index,
+ VALIDATE_DELETE) != TCL_OK) {
+ ckfree(newStr);
+ ckfree(toDelete);
+ return TCL_OK;
+ }
+
+ ckfree(toDelete);
+ ckfree((char *)entryPtr->string);
+ entryPtr->string = newStr;
+ entryPtr->numChars -= count;
+ entryPtr->numBytes -= byteCount;
+
+ if (entryPtr->displayString == string) {
+ entryPtr->displayString = newStr;
+ entryPtr->numDisplayBytes = entryPtr->numBytes;
+ }
+
+ /*
+ * Deleting characters results in the remaining characters being
+ * renumbered. Update the various indexes into the string to reflect this
+ * change.
+ */
+
+ if (entryPtr->selectFirst >= index) {
+ if (entryPtr->selectFirst >= (index + count)) {
+ entryPtr->selectFirst -= count;
+ } else {
+ entryPtr->selectFirst = index;
+ }
+ }
+ if (entryPtr->selectLast >= index) {
+ if (entryPtr->selectLast >= (index + count)) {
+ entryPtr->selectLast -= count;
+ } else {
+ entryPtr->selectLast = index;
+ }
+ }
+ if (entryPtr->selectLast <= entryPtr->selectFirst) {
+ entryPtr->selectFirst = -1;
+ entryPtr->selectLast = -1;
+ }
+ if (entryPtr->selectAnchor >= index) {
+ if (entryPtr->selectAnchor >= (index+count)) {
+ entryPtr->selectAnchor -= count;
+ } else {
+ entryPtr->selectAnchor = index;
+ }
+ }
+ if (entryPtr->leftIndex > index) {
+ if (entryPtr->leftIndex >= (index + count)) {
+ entryPtr->leftIndex -= count;
+ } else {
+ entryPtr->leftIndex = index;
+ }
+ }
+ if (entryPtr->insertPos >= index) {
+ if (entryPtr->insertPos >= (index + count)) {
+ entryPtr->insertPos -= count;
+ } else {
+ entryPtr->insertPos = index;
+ }
+ }
+ return EntryValueChanged(entryPtr, NULL);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EntryValueChanged --
+ *
+ * This function is invoked when characters are inserted into an entry or
+ * deleted from it. It updates the entry's associated variable, if there
+ * is one, and does other bookkeeping such as arranging for redisplay.
+ *
+ * Results:
+ * A standard Tcl result. If an error occurred then an error message is
+ * left in the interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+EntryValueChanged(
+ Entry *entryPtr, /* Entry whose value just changed. */
+ const char *newValue) /* If this value is not NULL, we first force
+ * the value of the entry to this. */
+{
+ if (newValue != NULL) {
+ EntrySetValue(entryPtr, newValue);
+ }
+
+ if (entryPtr->textVarName == NULL) {
+ newValue = NULL;
+ } else {
+ newValue = Tcl_SetVar2(entryPtr->interp, entryPtr->textVarName,
+ NULL, entryPtr->string, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG);
+ }
+
+ if ((newValue != NULL) && (strcmp(newValue, entryPtr->string) != 0)) {
+ /*
+ * The value of the variable is different than what we asked for.
+ * This means that a trace on the variable modified it. In this case
+ * our trace function wasn't invoked since the modification came while
+ * a trace was already active on the variable. So, update our value to
+ * reflect the variable's latest value.
+ */
+
+ EntrySetValue(entryPtr, newValue);
+ } else {
+ /*
+ * Arrange for redisplay.
+ */
+
+ entryPtr->flags |= UPDATE_SCROLLBAR;
+ EntryComputeGeometry(entryPtr);
+ EventuallyRedraw(entryPtr);
+ }
+
+ /*
+ * An error may have happened when setting the textvariable in case there
+ * is a trace on that variable and the trace proc triggered an error.
+ * Another possibility is that the textvariable is in a namespace that
+ * does not (yet) exist.
+ * Signal this error.
+ */
+
+ if ((entryPtr->textVarName != NULL) && (newValue == NULL)) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EntrySetValue --
+ *
+ * Replace the contents of a text entry with a given value. This function
+ * is invoked when updating the entry from the entry's associated
+ * variable.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The string displayed in the entry will change. The selection,
+ * insertion point, and view may have to be adjusted to keep them within
+ * the bounds of the new string. Note: this function does *not* update
+ * the entry's associated variable, since that could result in an
+ * infinite loop.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+EntrySetValue(
+ Entry *entryPtr, /* Entry whose value is to be changed. */
+ const char *value) /* New text to display in entry. */
+{
+ const char *oldSource;
+ int valueLen, malloced = 0;
+
+ if (strcmp(value, entryPtr->string) == 0) {
+ return;
+ }
+ valueLen = strlen(value);
+
+ if (entryPtr->flags & VALIDATE_VAR) {
+ entryPtr->flags |= VALIDATE_ABORT;
+ } else {
+ /*
+ * If we validate, we create a copy of the value, as it may point to
+ * volatile memory, like the value of the -textvar which may get freed
+ * during validation
+ */
+
+ char *tmp = ckalloc(valueLen + 1);
+
+ strcpy(tmp, value);
+ value = tmp;
+ malloced = 1;
+
+ entryPtr->flags |= VALIDATE_VAR;
+ (void) EntryValidateChange(entryPtr, NULL, value, -1,
+ VALIDATE_FORCED);
+ entryPtr->flags &= ~VALIDATE_VAR;
+
+ /*
+ * If VALIDATE_ABORT has been set, then this operation should be
+ * aborted because the validatecommand did something else instead
+ */
+
+ if (entryPtr->flags & VALIDATE_ABORT) {
+ entryPtr->flags &= ~VALIDATE_ABORT;
+ ckfree((char *)value);
+ return;
+ }
+ }
+
+ oldSource = entryPtr->string;
+ ckfree((char *)entryPtr->string);
+
+ if (malloced) {
+ entryPtr->string = value;
+ } else {
+ char *tmp = ckalloc(valueLen + 1);
+
+ strcpy(tmp, value);
+ entryPtr->string = tmp;
+ }
+ entryPtr->numBytes = valueLen;
+ entryPtr->numChars = Tcl_NumUtfChars(value, valueLen);
+
+ if (entryPtr->displayString == oldSource) {
+ entryPtr->displayString = entryPtr->string;
+ entryPtr->numDisplayBytes = entryPtr->numBytes;
+ }
+
+ if (entryPtr->selectFirst >= 0) {
+ if (entryPtr->selectFirst >= entryPtr->numChars) {
+ entryPtr->selectFirst = -1;
+ entryPtr->selectLast = -1;
+ } else if (entryPtr->selectLast > entryPtr->numChars) {
+ entryPtr->selectLast = entryPtr->numChars;
+ }
+ }
+ if (entryPtr->leftIndex >= entryPtr->numChars) {
+ if (entryPtr->numChars > 0) {
+ entryPtr->leftIndex = entryPtr->numChars - 1;
+ } else {
+ entryPtr->leftIndex = 0;
+ }
+ }
+ if (entryPtr->insertPos > entryPtr->numChars) {
+ entryPtr->insertPos = entryPtr->numChars;
+ }
+
+ entryPtr->flags |= UPDATE_SCROLLBAR;
+ EntryComputeGeometry(entryPtr);
+ EventuallyRedraw(entryPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EntryEventProc --
+ *
+ * This function is invoked by the Tk dispatcher for various events on
+ * entries.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * When the window gets deleted, internal structures get cleaned up.
+ * When it gets exposed, it is redisplayed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+EntryEventProc(
+ ClientData clientData, /* Information about window. */
+ XEvent *eventPtr) /* Information about event. */
+{
+ Entry *entryPtr = clientData;
+
+ if ((entryPtr->type == TK_SPINBOX) && (eventPtr->type == MotionNotify)) {
+ Spinbox *sbPtr = clientData;
+ int elem;
+
+ elem = GetSpinboxElement(sbPtr, eventPtr->xmotion.x,
+ eventPtr->xmotion.y);
+ if (elem != sbPtr->curElement) {
+ Tk_Cursor cursor;
+
+ sbPtr->curElement = elem;
+ if (elem == SEL_ENTRY) {
+ cursor = entryPtr->cursor;
+ } else if ((elem == SEL_BUTTONDOWN) || (elem == SEL_BUTTONUP)) {
+ cursor = sbPtr->bCursor;
+ } else {
+ cursor = NULL;
+ }
+ if (cursor != NULL) {
+ Tk_DefineCursor(entryPtr->tkwin, cursor);
+ } else {
+ Tk_UndefineCursor(entryPtr->tkwin);
+ }
+ }
+ return;
+ }
+
+ switch (eventPtr->type) {
+ case Expose:
+ EventuallyRedraw(entryPtr);
+ entryPtr->flags |= BORDER_NEEDED;
+ break;
+ case DestroyNotify:
+ if (!(entryPtr->flags & ENTRY_DELETED)) {
+ entryPtr->flags |= (ENTRY_DELETED | VALIDATE_ABORT);
+ Tcl_DeleteCommandFromToken(entryPtr->interp, entryPtr->widgetCmd);
+ if (entryPtr->flags & REDRAW_PENDING) {
+ Tcl_CancelIdleCall(DisplayEntry, clientData);
+ }
+ Tcl_EventuallyFree(clientData, (Tcl_FreeProc *) DestroyEntry);
+ }
+ break;
+ case ConfigureNotify:
+ Tcl_Preserve(entryPtr);
+ entryPtr->flags |= UPDATE_SCROLLBAR;
+ EntryComputeGeometry(entryPtr);
+ EventuallyRedraw(entryPtr);
+ Tcl_Release(entryPtr);
+ break;
+ case FocusIn:
+ case FocusOut:
+ if (eventPtr->xfocus.detail != NotifyInferior) {
+ EntryFocusProc(entryPtr, (eventPtr->type == FocusIn));
+ }
+ break;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EntryCmdDeletedProc --
+ *
+ * This function is invoked when a widget command is deleted. If the
+ * widget isn't already in the process of being destroyed, this command
+ * destroys it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The widget is destroyed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+EntryCmdDeletedProc(
+ ClientData clientData) /* Pointer to widget record for widget. */
+{
+ Entry *entryPtr = clientData;
+
+ /*
+ * This function could be invoked either because the window was destroyed
+ * and the command was then deleted (in which case tkwin is NULL) or
+ * because the command was deleted, and then this function destroys the
+ * widget.
+ */
+
+ if (!(entryPtr->flags & ENTRY_DELETED)) {
+ Tk_DestroyWindow(entryPtr->tkwin);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GetEntryIndex --
+ *
+ * Parse an index into an entry and return either its value or an error.
+ *
+ * Results:
+ * A standard Tcl result. If all went well, then *indexPtr is filled in
+ * with the character index (into entryPtr) corresponding to string. The
+ * index value is guaranteed to lie between 0 and the number of
+ * characters in the string, inclusive. If an error occurs then an error
+ * message is left in the interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static int
+GetEntryIndex(
+ Tcl_Interp *interp, /* For error messages. */
+ Entry *entryPtr, /* Entry for which the index is being
+ * specified. */
+ const char *string, /* Specifies character in entryPtr. */
+ int *indexPtr) /* Where to store converted character index */
+{
+ size_t length;
+
+ length = strlen(string);
+
+ switch (string[0]) {
+ case 'a':
+ if (strncmp(string, "anchor", length) != 0) {
+ goto badIndex;
+ }
+ *indexPtr = entryPtr->selectAnchor;
+ break;
+ case 'e':
+ if (strncmp(string, "end", length) != 0) {
+ goto badIndex;
+ }
+ *indexPtr = entryPtr->numChars;
+ break;
+ case 'i':
+ if (strncmp(string, "insert", length) != 0) {
+ goto badIndex;
+ }
+ *indexPtr = entryPtr->insertPos;
+ break;
+ case 's':
+ if (entryPtr->selectFirst < 0) {
+ Tcl_ResetResult(interp);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "selection isn't in widget %s",
+ Tk_PathName(entryPtr->tkwin)));
+ Tcl_SetErrorCode(interp, "TK",
+ (entryPtr->type == TK_ENTRY) ? "ENTRY" : "SPINBOX",
+ "NO_SELECTION", NULL);
+ return TCL_ERROR;
+ }
+ if (length < 5) {
+ goto badIndex;
+ }
+ if (strncmp(string, "sel.first", length) == 0) {
+ *indexPtr = entryPtr->selectFirst;
+ } else if (strncmp(string, "sel.last", length) == 0) {
+ *indexPtr = entryPtr->selectLast;
+ } else {
+ goto badIndex;
+ }
+ break;
+ case '@': {
+ int x, roundUp, maxWidth;
+
+ if (Tcl_GetInt(NULL, string + 1, &x) != TCL_OK) {
+ goto badIndex;
+ }
+ if (x < entryPtr->inset) {
+ x = entryPtr->inset;
+ }
+ roundUp = 0;
+ maxWidth = Tk_Width(entryPtr->tkwin) - entryPtr->inset
+ - entryPtr->xWidth - 1;
+ if (x > maxWidth) {
+ x = maxWidth;
+ roundUp = 1;
+ }
+ *indexPtr = Tk_PointToChar(entryPtr->textLayout,
+ x - entryPtr->layoutX, 0);
+
+ /*
+ * Special trick: if the x-position was off-screen to the right, round
+ * the index up to refer to the character just after the last visible
+ * one on the screen. This is needed to enable the last character to
+ * be selected, for example.
+ */
+
+ if (roundUp && (*indexPtr < entryPtr->numChars)) {
+ *indexPtr += 1;
+ }
+ break;
+ }
+ default:
+ if (Tcl_GetInt(NULL, string, indexPtr) != TCL_OK) {
+ goto badIndex;
+ }
+ if (*indexPtr < 0){
+ *indexPtr = 0;
+ } else if (*indexPtr > entryPtr->numChars) {
+ *indexPtr = entryPtr->numChars;
+ }
+ }
+ return TCL_OK;
+
+ badIndex:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad %s index \"%s\"",
+ (entryPtr->type == TK_ENTRY) ? "entry" : "spinbox", string));
+ Tcl_SetErrorCode(interp, "TK",
+ (entryPtr->type == TK_ENTRY) ? "ENTRY" : "SPINBOX",
+ "BAD_INDEX", NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EntryScanTo --
+ *
+ * Given a y-coordinate (presumably of the curent mouse location) drag
+ * the view in the window to implement the scan operation.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The view in the window may change.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+EntryScanTo(
+ Entry *entryPtr, /* Information about widget. */
+ int x) /* X-coordinate to use for scan operation. */
+{
+ int newLeftIndex;
+
+ /*
+ * Compute new leftIndex for entry by amplifying the difference between
+ * the current position and the place where the scan started (the "mark"
+ * position). If we run off the left or right side of the entry, then
+ * reset the mark point so that the current position continues to
+ * correspond to the edge of the window. This means that the picture will
+ * start dragging as soon as the mouse reverses direction (without this
+ * reset, might have to slide mouse a long ways back before the picture
+ * starts moving again).
+ */
+
+ newLeftIndex = entryPtr->scanMarkIndex
+ - (10 * (x - entryPtr->scanMarkX)) / entryPtr->avgWidth;
+ if (newLeftIndex >= entryPtr->numChars) {
+ newLeftIndex = entryPtr->scanMarkIndex = entryPtr->numChars - 1;
+ entryPtr->scanMarkX = x;
+ }
+ if (newLeftIndex < 0) {
+ newLeftIndex = entryPtr->scanMarkIndex = 0;
+ entryPtr->scanMarkX = x;
+ }
+
+ if (newLeftIndex != entryPtr->leftIndex) {
+ entryPtr->leftIndex = newLeftIndex;
+ entryPtr->flags |= UPDATE_SCROLLBAR;
+ EntryComputeGeometry(entryPtr);
+ if (newLeftIndex != entryPtr->leftIndex) {
+ entryPtr->scanMarkIndex = entryPtr->leftIndex;
+ entryPtr->scanMarkX = x;
+ }
+ EventuallyRedraw(entryPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EntrySelectTo --
+ *
+ * Modify the selection by moving its un-anchored end. This could make
+ * the selection either larger or smaller.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The selection changes.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+EntrySelectTo(
+ Entry *entryPtr, /* Information about widget. */
+ int index) /* Character index of element that is to
+ * become the "other" end of the selection. */
+{
+ int newFirst, newLast;
+
+ /*
+ * Grab the selection if we don't own it already.
+ */
+
+ if (!(entryPtr->flags & GOT_SELECTION) && (entryPtr->exportSelection)
+ && (!Tcl_IsSafe(entryPtr->interp))) {
+ Tk_OwnSelection(entryPtr->tkwin, XA_PRIMARY, EntryLostSelection,
+ entryPtr);
+ entryPtr->flags |= GOT_SELECTION;
+ }
+
+ /*
+ * Pick new starting and ending points for the selection.
+ */
+
+ if (entryPtr->selectAnchor > entryPtr->numChars) {
+ entryPtr->selectAnchor = entryPtr->numChars;
+ }
+ if (entryPtr->selectAnchor <= index) {
+ newFirst = entryPtr->selectAnchor;
+ newLast = index;
+ } else {
+ newFirst = index;
+ newLast = entryPtr->selectAnchor;
+ if (newLast < 0) {
+ newFirst = newLast = -1;
+ }
+ }
+ if ((entryPtr->selectFirst == newFirst)
+ && (entryPtr->selectLast == newLast)) {
+ return;
+ }
+ entryPtr->selectFirst = newFirst;
+ entryPtr->selectLast = newLast;
+ EventuallyRedraw(entryPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EntryFetchSelection --
+ *
+ * This function is called back by Tk when the selection is requested by
+ * someone. It returns part or all of the selection in a buffer provided
+ * by the caller.
+ *
+ * Results:
+ * The return value is the number of non-NULL bytes stored at buffer.
+ * Buffer is filled (or partially filled) with a NULL-terminated string
+ * containing part or all of the selection, as given by offset and
+ * maxBytes.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+EntryFetchSelection(
+ ClientData clientData, /* Information about entry widget. */
+ int offset, /* Byte offset within selection of first
+ * character to be returned. */
+ char *buffer, /* Location in which to place selection. */
+ int maxBytes) /* Maximum number of bytes to place at buffer,
+ * not including terminating NUL character. */
+{
+ Entry *entryPtr = clientData;
+ int byteCount;
+ const char *string;
+ const char *selStart, *selEnd;
+
+ if ((entryPtr->selectFirst < 0) || (!entryPtr->exportSelection)
+ || Tcl_IsSafe(entryPtr->interp)) {
+ return -1;
+ }
+ string = entryPtr->displayString;
+ selStart = Tcl_UtfAtIndex(string, entryPtr->selectFirst);
+ selEnd = Tcl_UtfAtIndex(selStart,
+ entryPtr->selectLast - entryPtr->selectFirst);
+ byteCount = selEnd - selStart - offset;
+ if (byteCount > maxBytes) {
+ byteCount = maxBytes;
+ }
+ if (byteCount <= 0) {
+ return 0;
+ }
+ memcpy(buffer, selStart + offset, (size_t) byteCount);
+ buffer[byteCount] = '\0';
+ return byteCount;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EntryLostSelection --
+ *
+ * This function is called back by Tk when the selection is grabbed away
+ * from an entry widget.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The existing selection is unhighlighted, and the window is marked as
+ * not containing a selection.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+EntryLostSelection(
+ ClientData clientData) /* Information about entry widget. */
+{
+ Entry *entryPtr = clientData;
+
+ entryPtr->flags &= ~GOT_SELECTION;
+
+ /*
+ * On Windows and Mac systems, we want to remember the selection for the
+ * next time the focus enters the window. On Unix, we need to clear the
+ * selection since it is always visible.
+ * This is controlled by ::tk::AlwaysShowSelection.
+ */
+
+ if (TkpAlwaysShowSelection(entryPtr->tkwin)
+ && (entryPtr->selectFirst >= 0) && entryPtr->exportSelection
+ && (!Tcl_IsSafe(entryPtr->interp))) {
+ entryPtr->selectFirst = -1;
+ entryPtr->selectLast = -1;
+ EventuallyRedraw(entryPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EventuallyRedraw --
+ *
+ * Ensure that an entry is eventually redrawn on the display.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Information gets redisplayed. Right now we don't do selective
+ * redisplays: the whole window will be redrawn. This doesn't seem to
+ * hurt performance noticeably, but if it does then this could be
+ * changed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+EventuallyRedraw(
+ Entry *entryPtr) /* Information about widget. */
+{
+ if ((entryPtr->flags & ENTRY_DELETED) || !Tk_IsMapped(entryPtr->tkwin)) {
+ return;
+ }
+
+ /*
+ * Right now we don't do selective redisplays: the whole window will be
+ * redrawn. This doesn't seem to hurt performance noticeably, but if it
+ * does then this could be changed.
+ */
+
+ if (!(entryPtr->flags & REDRAW_PENDING)) {
+ entryPtr->flags |= REDRAW_PENDING;
+ Tcl_DoWhenIdle(DisplayEntry, entryPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EntryVisibleRange --
+ *
+ * Return information about the range of the entry that is currently
+ * visible.
+ *
+ * Results:
+ * *firstPtr and *lastPtr are modified to hold fractions between 0 and 1
+ * identifying the range of characters visible in the entry.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+EntryVisibleRange(
+ Entry *entryPtr, /* Information about widget. */
+ double *firstPtr, /* Return position of first visible character
+ * in widget. */
+ double *lastPtr) /* Return position of char just after last
+ * visible one. */
+{
+ int charsInWindow;
+
+ if (entryPtr->numChars == 0) {
+ *firstPtr = 0.0;
+ *lastPtr = 1.0;
+ } else {
+ charsInWindow = Tk_PointToChar(entryPtr->textLayout,
+ Tk_Width(entryPtr->tkwin) - entryPtr->inset
+ - entryPtr->xWidth - entryPtr->layoutX - 1, 0);
+ if (charsInWindow < entryPtr->numChars) {
+ charsInWindow++;
+ }
+ charsInWindow -= entryPtr->leftIndex;
+ if (charsInWindow == 0) {
+ charsInWindow = 1;
+ }
+
+ *firstPtr = (double) entryPtr->leftIndex / entryPtr->numChars;
+ *lastPtr = (double) (entryPtr->leftIndex + charsInWindow)
+ / entryPtr->numChars;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EntryUpdateScrollbar --
+ *
+ * This function is invoked whenever information has changed in an entry
+ * in a way that would invalidate a scrollbar display. If there is an
+ * associated scrollbar, then this function updates it by invoking a Tcl
+ * command.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A Tcl command is invoked, and an additional command may be
+ * invoked to process errors in the command.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+EntryUpdateScrollbar(
+ Entry *entryPtr) /* Information about widget. */
+{
+ char firstStr[TCL_DOUBLE_SPACE], lastStr[TCL_DOUBLE_SPACE];
+ int code;
+ double first, last;
+ Tcl_Interp *interp;
+ Tcl_DString buf;
+
+ if (entryPtr->scrollCmd == NULL) {
+ return;
+ }
+
+ interp = entryPtr->interp;
+ Tcl_Preserve(interp);
+ EntryVisibleRange(entryPtr, &first, &last);
+ Tcl_PrintDouble(NULL, first, firstStr);
+ Tcl_PrintDouble(NULL, last, lastStr);
+ Tcl_DStringInit(&buf);
+ Tcl_DStringAppend(&buf, entryPtr->scrollCmd, -1);
+ Tcl_DStringAppend(&buf, " ", -1);
+ Tcl_DStringAppend(&buf, firstStr, -1);
+ Tcl_DStringAppend(&buf, " ", -1);
+ Tcl_DStringAppend(&buf, lastStr, -1);
+ code = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0);
+ Tcl_DStringFree(&buf);
+ if (code != TCL_OK) {
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (horizontal scrolling command executed by %s)",
+ Tk_PathName(entryPtr->tkwin)));
+ Tcl_BackgroundException(interp, code);
+ }
+ Tcl_ResetResult(interp);
+ Tcl_Release(interp);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EntryBlinkProc --
+ *
+ * This function is called as a timer handler to blink the insertion
+ * cursor off and on.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The cursor gets turned on or off, redisplay gets invoked, and this
+ * function reschedules itself.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+EntryBlinkProc(
+ ClientData clientData) /* Pointer to record describing entry. */
+{
+ Entry *entryPtr = clientData;
+
+ if ((entryPtr->state == STATE_DISABLED) ||
+ (entryPtr->state == STATE_READONLY) ||
+ !(entryPtr->flags & GOT_FOCUS) || (entryPtr->insertOffTime == 0)) {
+ return;
+ }
+ if (entryPtr->flags & CURSOR_ON) {
+ entryPtr->flags &= ~CURSOR_ON;
+ entryPtr->insertBlinkHandler = Tcl_CreateTimerHandler(
+ entryPtr->insertOffTime, EntryBlinkProc, entryPtr);
+ } else {
+ entryPtr->flags |= CURSOR_ON;
+ entryPtr->insertBlinkHandler = Tcl_CreateTimerHandler(
+ entryPtr->insertOnTime, EntryBlinkProc, entryPtr);
+ }
+ EventuallyRedraw(entryPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EntryFocusProc --
+ *
+ * This function is called whenever the entry gets or loses the input
+ * focus. It's also called whenever the window is reconfigured while it
+ * has the focus.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The cursor gets turned on or off.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+EntryFocusProc(
+ Entry *entryPtr, /* Entry that got or lost focus. */
+ int gotFocus) /* 1 means window is getting focus, 0 means
+ * it's losing it. */
+{
+ Tcl_DeleteTimerHandler(entryPtr->insertBlinkHandler);
+ if (gotFocus) {
+ entryPtr->flags |= GOT_FOCUS | CURSOR_ON;
+ if (entryPtr->insertOffTime != 0) {
+ entryPtr->insertBlinkHandler = Tcl_CreateTimerHandler(
+ entryPtr->insertOnTime, EntryBlinkProc, entryPtr);
+ }
+ if (entryPtr->validate == VALIDATE_ALL ||
+ entryPtr->validate == VALIDATE_FOCUS ||
+ entryPtr->validate == VALIDATE_FOCUSIN) {
+ EntryValidateChange(entryPtr, NULL, entryPtr->string, -1,
+ VALIDATE_FOCUSIN);
+ }
+ } else {
+ entryPtr->flags &= ~(GOT_FOCUS | CURSOR_ON);
+ entryPtr->insertBlinkHandler = NULL;
+ if (entryPtr->validate == VALIDATE_ALL ||
+ entryPtr->validate == VALIDATE_FOCUS ||
+ entryPtr->validate == VALIDATE_FOCUSOUT) {
+ EntryValidateChange(entryPtr, NULL, entryPtr->string, -1,
+ VALIDATE_FOCUSOUT);
+ }
+ }
+ EventuallyRedraw(entryPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EntryTextVarProc --
+ *
+ * This function is invoked when someone changes the variable whose
+ * contents are to be displayed in an entry.
+ *
+ * Results:
+ * NULL is always returned.
+ *
+ * Side effects:
+ * The text displayed in the entry will change to match the variable.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static char *
+EntryTextVarProc(
+ ClientData clientData, /* Information about button. */
+ Tcl_Interp *interp, /* Interpreter containing variable. */
+ const char *name1, /* Not used. */
+ const char *name2, /* Not used. */
+ int flags) /* Information about what happened. */
+{
+ Entry *entryPtr = clientData;
+ const char *value;
+
+ if (entryPtr->flags & ENTRY_DELETED) {
+ /*
+ * Just abort early if we entered here while being deleted.
+ */
+ return NULL;
+ }
+
+ /*
+ * If the variable is unset, then immediately recreate it unless the whole
+ * interpreter is going away.
+ */
+
+ if (flags & TCL_TRACE_UNSETS) {
+ if (!Tcl_InterpDeleted(interp) && entryPtr->textVarName) {
+ ClientData probe = NULL;
+
+ do {
+ probe = Tcl_VarTraceInfo(interp,
+ entryPtr->textVarName,
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ EntryTextVarProc, probe);
+ if (probe == (ClientData)entryPtr) {
+ break;
+ }
+ } while (probe);
+ if (probe) {
+ /*
+ * We were able to fetch the unset trace for our
+ * textVarName, which means it is not unset and not
+ * the cause of this unset trace. Instead some outdated
+ * former variable must be, and we should ignore it.
+ */
+ return NULL;
+ }
+ Tcl_SetVar2(interp, entryPtr->textVarName, NULL,
+ entryPtr->string, TCL_GLOBAL_ONLY);
+ Tcl_TraceVar2(interp, entryPtr->textVarName, NULL,
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ EntryTextVarProc, clientData);
+ entryPtr->flags |= ENTRY_VAR_TRACED;
+ }
+ return NULL;
+ }
+
+ /*
+ * Update the entry's text with the value of the variable, unless the
+ * entry already has that value (this happens when the variable changes
+ * value because we changed it because someone typed in the entry).
+ */
+
+ value = Tcl_GetVar2(interp, entryPtr->textVarName, NULL, TCL_GLOBAL_ONLY);
+ if (value == NULL) {
+ value = "";
+ }
+ EntrySetValue(entryPtr, value);
+ return NULL;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EntryValidate --
+ *
+ * This function is invoked when any character is added or removed from
+ * the entry widget, or a focus has trigerred validation.
+ *
+ * Results:
+
+ * TCL_OK if the validatecommand passes the new string. TCL_BREAK if the
+ * vcmd executed OK, but rejects the string. TCL_ERROR if an error
+ * occurred while executing the vcmd or a valid Tcl_Bool is not returned.
+ *
+ * Side effects:
+ * An error condition may arise
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+EntryValidate(
+ register Entry *entryPtr, /* Entry that needs validation. */
+ register char *cmd) /* Validation command (NULL-terminated
+ * string). */
+{
+ register Tcl_Interp *interp = entryPtr->interp;
+ int code, bool;
+
+ code = Tcl_EvalEx(interp, cmd, -1, TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT);
+
+ /*
+ * We accept TCL_OK and TCL_RETURN as valid return codes from the command
+ * callback.
+ */
+
+ if (code != TCL_OK && code != TCL_RETURN) {
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (in validation command executed by %s)",
+ Tk_PathName(entryPtr->tkwin)));
+ Tcl_BackgroundException(interp, code);
+ return TCL_ERROR;
+ }
+
+ /*
+ * The command callback should return an acceptable Tcl boolean.
+ */
+
+ if (Tcl_GetBooleanFromObj(interp, Tcl_GetObjResult(interp),
+ &bool) != TCL_OK) {
+ Tcl_AddErrorInfo(interp,
+ "\n (invalid boolean result from validation command)");
+ Tcl_BackgroundException(interp, TCL_ERROR);
+ Tcl_ResetResult(interp);
+ return TCL_ERROR;
+ }
+
+ Tcl_ResetResult(interp);
+ return (bool ? TCL_OK : TCL_BREAK);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EntryValidateChange --
+ *
+ * This function is invoked when any character is added or removed from
+ * the entry widget, or a focus has trigerred validation.
+ *
+ * Results:
+ * TCL_OK if the validatecommand accepts the new string, TCL_ERROR if any
+ * problems occured with validatecommand.
+ *
+ * Side effects:
+ * The insertion/deletion may be aborted, and the validatecommand might
+ * turn itself off (if an error or loop condition arises).
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+EntryValidateChange(
+ register Entry *entryPtr, /* Entry that needs validation. */
+ const char *change, /* Characters to be added/deleted
+ * (NUL-terminated string). */
+ const char *newValue, /* Potential new value of entry string */
+ int index, /* index of insert/delete, -1 otherwise */
+ int type) /* forced, delete, insert, focusin or
+ * focusout */
+{
+ int code, varValidate = (entryPtr->flags & VALIDATE_VAR);
+ char *p;
+ Tcl_DString script;
+
+ if (entryPtr->validateCmd == NULL ||
+ entryPtr->validate == VALIDATE_NONE) {
+ return (varValidate ? TCL_ERROR : TCL_OK);
+ }
+
+ /*
+ * If we're already validating, then we're hitting a loop condition Return
+ * and set validate to 0 to disallow further validations and prevent
+ * current validation from finishing
+ */
+
+ if (entryPtr->flags & VALIDATING) {
+ entryPtr->validate = VALIDATE_NONE;
+ return (varValidate ? TCL_ERROR : TCL_OK);
+ }
+
+ entryPtr->flags |= VALIDATING;
+
+ /*
+ * Now form command string and run through the -validatecommand
+ */
+
+ Tcl_DStringInit(&script);
+ ExpandPercents(entryPtr, entryPtr->validateCmd,
+ change, newValue, index, type, &script);
+ Tcl_DStringAppend(&script, "", 1);
+
+ p = Tcl_DStringValue(&script);
+ code = EntryValidate(entryPtr, p);
+ Tcl_DStringFree(&script);
+
+ /*
+ * If e->validate has become VALIDATE_NONE during the validation, or we
+ * now have VALIDATE_VAR set (from EntrySetValue) and didn't before, it
+ * means that a loop condition almost occured. Do not allow this
+ * validation result to finish.
+ */
+
+ if (entryPtr->validate == VALIDATE_NONE
+ || (!varValidate && (entryPtr->flags & VALIDATE_VAR))) {
+ code = TCL_ERROR;
+ }
+
+ /*
+ * It's possible that the user deleted the entry during validation. In
+ * that case, abort future validation and return an error.
+ */
+
+ if (entryPtr->flags & ENTRY_DELETED) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * If validate will return ERROR, then disallow further validations
+ * Otherwise, if it didn't accept the new string (returned TCL_BREAK) then
+ * eval the invalidCmd (if it's set)
+ */
+
+ if (code == TCL_ERROR) {
+ entryPtr->validate = VALIDATE_NONE;
+ } else if (code == TCL_BREAK) {
+ /*
+ * If we were doing forced validation (like via a variable trace) and
+ * the command returned 0, the we turn off validation because we
+ * assume that textvariables have precedence in managing the value.
+ * We also don't call the invcmd, as it may want to do entry
+ * manipulation which the setting of the var will later wipe anyway.
+ */
+
+ if (varValidate) {
+ entryPtr->validate = VALIDATE_NONE;
+ } else if (entryPtr->invalidCmd != NULL) {
+ int result;
+
+ Tcl_DStringInit(&script);
+ ExpandPercents(entryPtr, entryPtr->invalidCmd,
+ change, newValue, index, type, &script);
+ Tcl_DStringAppend(&script, "", 1);
+ p = Tcl_DStringValue(&script);
+ result = Tcl_EvalEx(entryPtr->interp, p, -1,
+ TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT);
+ if (result != TCL_OK) {
+ Tcl_AddErrorInfo(entryPtr->interp,
+ "\n (in invalidcommand executed by entry)");
+ Tcl_BackgroundException(entryPtr->interp, result);
+ code = TCL_ERROR;
+ entryPtr->validate = VALIDATE_NONE;
+ }
+ Tcl_DStringFree(&script);
+
+ /*
+ * It's possible that the user deleted the entry during
+ * validation. In that case, abort future validation and return an
+ * error.
+ */
+
+ if (entryPtr->flags & ENTRY_DELETED) {
+ return TCL_ERROR;
+ }
+ }
+ }
+
+ entryPtr->flags &= ~VALIDATING;
+
+ return code;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ExpandPercents --
+ *
+ * Given a command and an event, produce a new command by replacing %
+ * constructs in the original command with information from the X event.
+ *
+ * Results:
+ * The new expanded command is appended to the dynamic string given by
+ * dsPtr.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ExpandPercents(
+ register Entry *entryPtr, /* Entry that needs validation. */
+ register const char *before,
+ /* Command containing percent expressions to
+ * be replaced. */
+ const char *change, /* Characters to added/deleted (NUL-terminated
+ * string). */
+ const char *newValue, /* Potential new value of entry string */
+ int index, /* index of insert/delete */
+ int type, /* INSERT or DELETE */
+ Tcl_DString *dsPtr) /* Dynamic string in which to append new
+ * command. */
+{
+ int spaceNeeded, cvtFlags; /* Used to substitute string as proper Tcl
+ * list element. */
+ int number, length;
+ register const char *string;
+ int ch;
+ char numStorage[2*TCL_INTEGER_SPACE];
+
+ while (1) {
+ if (*before == '\0') {
+ break;
+ }
+ /*
+ * Find everything up to the next % character and append it to the
+ * result string.
+ */
+
+ string = before;
+
+ /*
+ * No need to convert '%', as it is in ascii range.
+ */
+
+ string = Tcl_UtfFindFirst(before, '%');
+ if (string == NULL) {
+ Tcl_DStringAppend(dsPtr, before, -1);
+ break;
+ } else if (string != before) {
+ Tcl_DStringAppend(dsPtr, before, string-before);
+ before = string;
+ }
+
+ /*
+ * There's a percent sequence here. Process it.
+ */
+
+ before++; /* skip over % */
+ if (*before != '\0') {
+ before += TkUtfToUniChar(before, &ch);
+ } else {
+ ch = '%';
+ }
+ if (type == VALIDATE_BUTTON) {
+ /*
+ * -command %-substitution
+ */
+
+ switch (ch) {
+ case 's': /* Current string value of spinbox */
+ string = entryPtr->string;
+ break;
+ case 'd': /* direction, up or down */
+ string = change;
+ break;
+ case 'W': /* widget name */
+ string = Tk_PathName(entryPtr->tkwin);
+ break;
+ default:
+ length = TkUniCharToUtf(ch, numStorage);
+ numStorage[length] = '\0';
+ string = numStorage;
+ break;
+ }
+ } else {
+ /*
+ * -validatecommand / -invalidcommand %-substitution
+ */
+
+ switch (ch) {
+ case 'd': /* Type of call that caused validation */
+ switch (type) {
+ case VALIDATE_INSERT:
+ number = 1;
+ break;
+ case VALIDATE_DELETE:
+ number = 0;
+ break;
+ default:
+ number = -1;
+ break;
+ }
+ sprintf(numStorage, "%d", number);
+ string = numStorage;
+ break;
+ case 'i': /* index of insert/delete */
+ sprintf(numStorage, "%d", index);
+ string = numStorage;
+ break;
+ case 'P': /* 'Peeked' new value of the string */
+ string = newValue;
+ break;
+ case 's': /* Current string value of spinbox */
+ string = entryPtr->string;
+ break;
+ case 'S': /* string to be inserted/deleted, if any */
+ string = change;
+ break;
+ case 'v': /* type of validation currently set */
+ string = validateStrings[entryPtr->validate];
+ break;
+ case 'V': /* type of validation in effect */
+ switch (type) {
+ case VALIDATE_INSERT:
+ case VALIDATE_DELETE:
+ string = validateStrings[VALIDATE_KEY];
+ break;
+ case VALIDATE_FORCED:
+ string = "forced";
+ break;
+ default:
+ string = validateStrings[type];
+ break;
+ }
+ break;
+ case 'W': /* widget name */
+ string = Tk_PathName(entryPtr->tkwin);
+ break;
+ default:
+ length = TkUniCharToUtf(ch, numStorage);
+ numStorage[length] = '\0';
+ string = numStorage;
+ break;
+ }
+ }
+
+ spaceNeeded = Tcl_ScanCountedElement(string, -1, &cvtFlags);
+ length = Tcl_DStringLength(dsPtr);
+ Tcl_DStringSetLength(dsPtr, length + spaceNeeded);
+ spaceNeeded = Tcl_ConvertCountedElement(string, -1,
+ Tcl_DStringValue(dsPtr) + length,
+ cvtFlags | TCL_DONT_USE_BRACES);
+ Tcl_DStringSetLength(dsPtr, length + spaceNeeded);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_SpinboxObjCmd --
+ *
+ * This function is invoked to process the "spinbox" 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_SpinboxObjCmd(
+ ClientData clientData, /* NULL. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ register Entry *entryPtr;
+ register Spinbox *sbPtr;
+ Tk_OptionTable optionTable;
+ Tk_Window tkwin;
+ char *tmp;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?");
+ return TCL_ERROR;
+ }
+
+ tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),
+ Tcl_GetString(objv[1]), NULL);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Create the option table for this widget class. If it has already been
+ * created, Tk will return the cached value.
+ */
+
+ optionTable = Tk_CreateOptionTable(interp, sbOptSpec);
+
+ /*
+ * Initialize the fields of the structure that won't be initialized by
+ * ConfigureEntry, or that ConfigureEntry requires to be initialized
+ * already (e.g. resource pointers). Only the non-NULL/0 data must be
+ * initialized as memset covers the rest.
+ */
+
+ sbPtr = ckalloc(sizeof(Spinbox));
+ entryPtr = (Entry *) sbPtr;
+ memset(sbPtr, 0, sizeof(Spinbox));
+
+ entryPtr->tkwin = tkwin;
+ entryPtr->display = Tk_Display(tkwin);
+ entryPtr->interp = interp;
+ entryPtr->widgetCmd = Tcl_CreateObjCommand(interp,
+ Tk_PathName(entryPtr->tkwin), SpinboxWidgetObjCmd, sbPtr,
+ EntryCmdDeletedProc);
+ entryPtr->optionTable = optionTable;
+ entryPtr->type = TK_SPINBOX;
+ tmp = ckalloc(1);
+ tmp[0] = '\0';
+ entryPtr->string = tmp;
+ entryPtr->selectFirst = -1;
+ entryPtr->selectLast = -1;
+
+ entryPtr->cursor = NULL;
+ entryPtr->exportSelection = 1;
+ entryPtr->justify = TK_JUSTIFY_LEFT;
+ entryPtr->relief = TK_RELIEF_FLAT;
+ entryPtr->state = STATE_NORMAL;
+ entryPtr->displayString = entryPtr->string;
+ entryPtr->inset = XPAD;
+ entryPtr->textGC = NULL;
+ entryPtr->selTextGC = NULL;
+ entryPtr->highlightGC = NULL;
+ entryPtr->avgWidth = 1;
+ entryPtr->validate = VALIDATE_NONE;
+
+ sbPtr->selElement = SEL_NONE;
+ sbPtr->curElement = SEL_NONE;
+ sbPtr->bCursor = NULL;
+ sbPtr->repeatDelay = 400;
+ sbPtr->repeatInterval = 100;
+ sbPtr->fromValue = 0.0;
+ sbPtr->toValue = 100.0;
+ sbPtr->increment = 1.0;
+ sbPtr->formatBuf = ckalloc(TCL_DOUBLE_SPACE);
+ sbPtr->bdRelief = TK_RELIEF_FLAT;
+ sbPtr->buRelief = TK_RELIEF_FLAT;
+
+ /*
+ * Keep a hold of the associated tkwin until we destroy the spinbox,
+ * otherwise Tk might free it while we still need it.
+ */
+
+ Tcl_Preserve(entryPtr->tkwin);
+
+ Tk_SetClass(entryPtr->tkwin, "Spinbox");
+ Tk_SetClassProcs(entryPtr->tkwin, &entryClass, entryPtr);
+ Tk_CreateEventHandler(entryPtr->tkwin,
+ PointerMotionMask|ExposureMask|StructureNotifyMask|FocusChangeMask,
+ EntryEventProc, entryPtr);
+ Tk_CreateSelHandler(entryPtr->tkwin, XA_PRIMARY, XA_STRING,
+ EntryFetchSelection, entryPtr, XA_STRING);
+
+ if (Tk_InitOptions(interp, (char *) sbPtr, optionTable, tkwin)
+ != TCL_OK) {
+ Tk_DestroyWindow(entryPtr->tkwin);
+ return TCL_ERROR;
+ }
+ if (ConfigureEntry(interp, entryPtr, objc-2, objv+2) != TCL_OK) {
+ goto error;
+ }
+
+ Tcl_SetObjResult(interp, TkNewWindowObj(entryPtr->tkwin));
+ return TCL_OK;
+
+ error:
+ Tk_DestroyWindow(entryPtr->tkwin);
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * SpinboxWidgetObjCmd --
+ *
+ * This function is invoked to process the Tcl command that corresponds
+ * to a widget managed by this module. See the user documentation for
+ * details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+SpinboxWidgetObjCmd(
+ ClientData clientData, /* Information about spinbox widget. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Entry *entryPtr = clientData;
+ Spinbox *sbPtr = clientData;
+ int cmdIndex, selIndex, result;
+ Tcl_Obj *objPtr;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Parse the widget command by looking up the second token in the list of
+ * valid command names.
+ */
+
+ result = Tcl_GetIndexFromObj(interp, objv[1], sbCmdNames,
+ "option", 0, &cmdIndex);
+ if (result != TCL_OK) {
+ return result;
+ }
+
+ Tcl_Preserve(entryPtr);
+ switch ((enum sbCmd) cmdIndex) {
+ case SB_CMD_BBOX: {
+ int index, x, y, width, height;
+ Tcl_Obj *bbox[4];
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index");
+ goto error;
+ }
+ if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]),
+ &index) != TCL_OK) {
+ goto error;
+ }
+ if ((index == entryPtr->numChars) && (index > 0)) {
+ index--;
+ }
+ Tk_CharBbox(entryPtr->textLayout, index, &x, &y, &width, &height);
+ bbox[0] = Tcl_NewIntObj(x + entryPtr->layoutX);
+ bbox[1] = Tcl_NewIntObj(y + entryPtr->layoutY);
+ bbox[2] = Tcl_NewIntObj(width);
+ bbox[3] = Tcl_NewIntObj(height);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(4, bbox));
+ break;
+ }
+
+ case SB_CMD_CGET:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option");
+ goto error;
+ }
+
+ objPtr = Tk_GetOptionValue(interp, (char *) entryPtr,
+ entryPtr->optionTable, objv[2], entryPtr->tkwin);
+ if (objPtr == NULL) {
+ goto error;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ break;
+
+ case SB_CMD_CONFIGURE:
+ if (objc <= 3) {
+ objPtr = Tk_GetOptionInfo(interp, (char *) entryPtr,
+ entryPtr->optionTable, (objc == 3) ? objv[2] : NULL,
+ entryPtr->tkwin);
+ if (objPtr == NULL) {
+ goto error;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ } else {
+ result = ConfigureEntry(interp, entryPtr, objc-2, objv+2);
+ }
+ break;
+
+ case SB_CMD_DELETE: {
+ int first, last, code;
+
+ if ((objc < 3) || (objc > 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "firstIndex ?lastIndex?");
+ goto error;
+ }
+ if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]),
+ &first) != TCL_OK) {
+ goto error;
+ }
+ if (objc == 3) {
+ last = first + 1;
+ } else {
+ if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[3]),
+ &last) != TCL_OK) {
+ goto error;
+ }
+ }
+ if ((last >= first) && (entryPtr->state == STATE_NORMAL)) {
+ code = DeleteChars(entryPtr, first, last - first);
+ if (code != TCL_OK) {
+ goto error;
+ }
+ }
+ break;
+ }
+
+ case SB_CMD_GET:
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ goto error;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(entryPtr->string, -1));
+ break;
+
+ case SB_CMD_ICURSOR:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "pos");
+ goto error;
+ }
+ if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]),
+ &entryPtr->insertPos) != TCL_OK) {
+ goto error;
+ }
+ EventuallyRedraw(entryPtr);
+ break;
+
+ case SB_CMD_IDENTIFY: {
+ int x, y, elem;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "x y");
+ goto error;
+ }
+ if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK) ||
+ (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {
+ goto error;
+ }
+ elem = GetSpinboxElement(sbPtr, x, y);
+ if (elem != SEL_NONE) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj(selElementNames[elem], -1));
+ }
+ break;
+ }
+
+ case SB_CMD_INDEX: {
+ int index;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "string");
+ goto error;
+ }
+ if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]),
+ &index) != TCL_OK) {
+ goto error;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(index));
+ break;
+ }
+
+ case SB_CMD_INSERT: {
+ int index, code;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index text");
+ goto error;
+ }
+ if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]),
+ &index) != TCL_OK) {
+ goto error;
+ }
+ if (entryPtr->state == STATE_NORMAL) {
+ code = InsertChars(entryPtr, index, Tcl_GetString(objv[3]));
+ if (code != TCL_OK) {
+ goto error;
+ }
+ }
+ break;
+ }
+
+ case SB_CMD_INVOKE:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "elemName");
+ goto error;
+ }
+ result = Tcl_GetIndexFromObj(interp, objv[2],
+ selElementNames, "element", 0, &cmdIndex);
+ if (result != TCL_OK) {
+ goto error;
+ }
+ if (entryPtr->state != STATE_DISABLED) {
+ if (SpinboxInvoke(interp, sbPtr, cmdIndex) != TCL_OK) {
+ goto error;
+ }
+ }
+ break;
+
+ case SB_CMD_SCAN: {
+ int x;
+ const char *minorCmd;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "mark|dragto x");
+ goto error;
+ }
+ if (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) {
+ goto error;
+ }
+
+ minorCmd = Tcl_GetString(objv[2]);
+ if (minorCmd[0] == 'm'
+ && (strncmp(minorCmd, "mark", strlen(minorCmd)) == 0)) {
+ entryPtr->scanMarkX = x;
+ entryPtr->scanMarkIndex = entryPtr->leftIndex;
+ } else if ((minorCmd[0] == 'd')
+ && (strncmp(minorCmd, "dragto", strlen(minorCmd)) == 0)) {
+ EntryScanTo(entryPtr, x);
+ } else {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad scan option \"%s\": must be mark or dragto",
+ minorCmd));
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "scan option",
+ minorCmd, NULL);
+ goto error;
+ }
+ break;
+ }
+
+ case SB_CMD_SELECTION: {
+ int index, index2;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option ?index?");
+ goto error;
+ }
+
+ /*
+ * Parse the selection sub-command, using the command table
+ * "sbSelCmdNames" defined above.
+ */
+
+ result = Tcl_GetIndexFromObj(interp, objv[2], sbSelCmdNames,
+ "selection option", 0, &selIndex);
+ if (result != TCL_OK) {
+ goto error;
+ }
+
+ /*
+ * Disabled entries don't allow the selection to be modified, but
+ * 'selection present' must return a boolean.
+ */
+
+ if ((entryPtr->state == STATE_DISABLED)
+ && (selIndex != SB_SEL_PRESENT)) {
+ goto done;
+ }
+
+ switch (selIndex) {
+ case SB_SEL_ADJUST:
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index");
+ goto error;
+ }
+ if (GetEntryIndex(interp, entryPtr,
+ Tcl_GetString(objv[3]), &index) != TCL_OK) {
+ goto error;
+ }
+ if (entryPtr->selectFirst >= 0) {
+ int half1, half2;
+
+ half1 = (entryPtr->selectFirst + entryPtr->selectLast)/2;
+ half2 = (entryPtr->selectFirst + entryPtr->selectLast + 1)/2;
+ if (index < half1) {
+ entryPtr->selectAnchor = entryPtr->selectLast;
+ } else if (index > half2) {
+ entryPtr->selectAnchor = entryPtr->selectFirst;
+ } else {
+ /*
+ * We're at about the halfway point in the selection; just
+ * keep the existing anchor.
+ */
+ }
+ }
+ EntrySelectTo(entryPtr, index);
+ break;
+
+ case SB_SEL_CLEAR:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ goto error;
+ }
+ if (entryPtr->selectFirst >= 0) {
+ entryPtr->selectFirst = -1;
+ entryPtr->selectLast = -1;
+ EventuallyRedraw(entryPtr);
+ }
+ goto done;
+
+ case SB_SEL_FROM:
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index");
+ goto error;
+ }
+ if (GetEntryIndex(interp, entryPtr,
+ Tcl_GetString(objv[3]), &index) != TCL_OK) {
+ goto error;
+ }
+ entryPtr->selectAnchor = index;
+ break;
+
+ case SB_SEL_PRESENT:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ goto error;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
+ entryPtr->selectFirst >= 0));
+ goto done;
+
+ case SB_SEL_RANGE:
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 3, objv, "start end");
+ goto error;
+ }
+ if (GetEntryIndex(interp, entryPtr,
+ Tcl_GetString(objv[3]), &index) != TCL_OK) {
+ goto error;
+ }
+ if (GetEntryIndex(interp, entryPtr,
+ Tcl_GetString(objv[4]),& index2) != TCL_OK) {
+ goto error;
+ }
+ if (index >= index2) {
+ entryPtr->selectFirst = -1;
+ entryPtr->selectLast = -1;
+ } else {
+ entryPtr->selectFirst = index;
+ entryPtr->selectLast = index2;
+ }
+ if (!(entryPtr->flags & GOT_SELECTION)
+ && entryPtr->exportSelection
+ && (!Tcl_IsSafe(entryPtr->interp))) {
+ Tk_OwnSelection(entryPtr->tkwin, XA_PRIMARY,
+ EntryLostSelection, entryPtr);
+ entryPtr->flags |= GOT_SELECTION;
+ }
+ EventuallyRedraw(entryPtr);
+ break;
+
+ case SB_SEL_TO:
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index");
+ goto error;
+ }
+ if (GetEntryIndex(interp, entryPtr,
+ Tcl_GetString(objv[3]), &index) != TCL_OK) {
+ goto error;
+ }
+ EntrySelectTo(entryPtr, index);
+ break;
+
+ case SB_SEL_ELEMENT:
+ if ((objc < 3) || (objc > 4)) {
+ Tcl_WrongNumArgs(interp, 3, objv, "?elemName?");
+ goto error;
+ }
+ if (objc == 3) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ selElementNames[sbPtr->selElement], -1));
+ } else {
+ int lastElement = sbPtr->selElement;
+
+ result = Tcl_GetIndexFromObj(interp, objv[3], selElementNames,
+ "selection element", 0, &(sbPtr->selElement));
+ if (result != TCL_OK) {
+ goto error;
+ }
+ if (lastElement != sbPtr->selElement) {
+ EventuallyRedraw(entryPtr);
+ }
+ }
+ break;
+ }
+ break;
+ }
+
+ case SB_CMD_SET: {
+ int code = TCL_OK;
+
+ if (objc > 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?string?");
+ goto error;
+ }
+ if (objc == 3) {
+ code = EntryValueChanged(entryPtr, Tcl_GetString(objv[2]));
+ if (code != TCL_OK) {
+ goto error;
+ }
+ }
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(entryPtr->string, -1));
+ break;
+ }
+
+ case SB_CMD_VALIDATE: {
+ int code;
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ goto error;
+ }
+ selIndex = entryPtr->validate;
+ entryPtr->validate = VALIDATE_ALL;
+ code = EntryValidateChange(entryPtr, NULL, entryPtr->string,
+ -1, VALIDATE_FORCED);
+ if (entryPtr->validate != VALIDATE_NONE) {
+ entryPtr->validate = selIndex;
+ }
+
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(code == TCL_OK));
+ break;
+ }
+
+ case SB_CMD_XVIEW: {
+ int index;
+
+ if (objc == 2) {
+ double first, last;
+ Tcl_Obj *span[2];
+
+ EntryVisibleRange(entryPtr, &first, &last);
+ span[0] = Tcl_NewDoubleObj(first);
+ span[1] = Tcl_NewDoubleObj(last);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(2, span));
+ goto done;
+ } else if (objc == 3) {
+ if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]),
+ &index) != TCL_OK) {
+ goto error;
+ }
+ } else {
+ double fraction;
+ int count;
+
+ index = entryPtr->leftIndex;
+ switch (Tk_GetScrollInfoObj(interp, objc, objv, &fraction,
+ &count)) {
+ case TK_SCROLL_ERROR:
+ goto error;
+ case TK_SCROLL_MOVETO:
+ index = (int) ((fraction * entryPtr->numChars) + 0.5);
+ break;
+ case TK_SCROLL_PAGES: {
+ int charsPerPage;
+
+ charsPerPage = ((Tk_Width(entryPtr->tkwin)
+ - 2 * entryPtr->inset - entryPtr->xWidth)
+ / entryPtr->avgWidth) - 2;
+ if (charsPerPage < 1) {
+ charsPerPage = 1;
+ }
+ index += count * charsPerPage;
+ break;
+ }
+ case TK_SCROLL_UNITS:
+ index += count;
+ break;
+ }
+ }
+ if (index >= entryPtr->numChars) {
+ index = entryPtr->numChars - 1;
+ }
+ if (index < 0) {
+ index = 0;
+ }
+ entryPtr->leftIndex = index;
+ entryPtr->flags |= UPDATE_SCROLLBAR;
+ EntryComputeGeometry(entryPtr);
+ EventuallyRedraw(entryPtr);
+ break;
+ }
+ }
+
+ done:
+ Tcl_Release(entryPtr);
+ return result;
+
+ error:
+ Tcl_Release(entryPtr);
+ return TCL_ERROR;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GetSpinboxElement --
+ *
+ * Return the element associated with an x,y coord.
+ *
+ * Results:
+ * Element type as enum selelement.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static int
+GetSpinboxElement(
+ Spinbox *sbPtr, /* Spinbox for which the index is being
+ * specified. */
+ int x, int y) /* Widget-relative coordinates. */
+{
+ Entry *entryPtr = (Entry *) sbPtr;
+
+ if ((x < 0) || (y < 0) || (y > Tk_Height(entryPtr->tkwin))
+ || (x > Tk_Width(entryPtr->tkwin))) {
+ return SEL_NONE;
+ }
+
+ if (x > (Tk_Width(entryPtr->tkwin) - entryPtr->inset - entryPtr->xWidth)) {
+ if (y > (Tk_Height(entryPtr->tkwin) / 2)) {
+ return SEL_BUTTONDOWN;
+ } else {
+ return SEL_BUTTONUP;
+ }
+ }
+ return SEL_ENTRY;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * SpinboxInvoke --
+ *
+ * This function is invoked when the invoke method for the widget is
+ * called.
+ *
+ * Results:
+ * TCL_OK.
+ *
+ * Side effects:
+ * A background error condition may arise when invoking the callback.
+ * The widget value may change.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+SpinboxInvoke(
+ register Tcl_Interp *interp,/* Current interpreter. */
+ register Spinbox *sbPtr, /* Spinbox to invoke. */
+ int element) /* Element to invoke, either the "up" or
+ * "down" button. */
+{
+ Entry *entryPtr = (Entry *) sbPtr;
+ const char *type;
+ int code, up;
+ Tcl_DString script;
+
+ switch (element) {
+ case SEL_BUTTONUP:
+ type = "up";
+ up = 1;
+ break;
+ case SEL_BUTTONDOWN:
+ type = "down";
+ up = 0;
+ break;
+ default:
+ return TCL_OK;
+ }
+
+ code = TCL_OK;
+ if (fabs(sbPtr->increment) > MIN_DBL_VAL) {
+ if (sbPtr->listObj != NULL) {
+ Tcl_Obj *objPtr;
+
+ Tcl_ListObjIndex(interp, sbPtr->listObj, sbPtr->eIndex, &objPtr);
+ if (strcmp(Tcl_GetString(objPtr), entryPtr->string)) {
+ /*
+ * Somehow the string changed from what we expected, so let's
+ * do a search on the list to see if the current value is
+ * there. If not, move to the first element of the list.
+ */
+
+ int i, listc, elemLen, length = entryPtr->numChars;
+ const char *bytes;
+ Tcl_Obj **listv;
+
+ Tcl_ListObjGetElements(interp, sbPtr->listObj, &listc, &listv);
+ for (i = 0; i < listc; i++) {
+ bytes = Tcl_GetStringFromObj(listv[i], &elemLen);
+ if ((length == elemLen) &&
+ (memcmp(bytes, entryPtr->string,
+ (size_t) length) == 0)) {
+ sbPtr->eIndex = i;
+ break;
+ }
+ }
+ }
+ if (up) {
+ if (++sbPtr->eIndex >= sbPtr->nElements) {
+ if (sbPtr->wrap) {
+ sbPtr->eIndex = 0;
+ } else {
+ sbPtr->eIndex = sbPtr->nElements-1;
+ }
+ }
+ } else {
+ if (--sbPtr->eIndex < 0) {
+ if (sbPtr->wrap) {
+ sbPtr->eIndex = sbPtr->nElements-1;
+ } else {
+ sbPtr->eIndex = 0;
+ }
+ }
+ }
+ Tcl_ListObjIndex(interp, sbPtr->listObj, sbPtr->eIndex, &objPtr);
+ code = EntryValueChanged(entryPtr, Tcl_GetString(objPtr));
+ } else if (!DOUBLES_EQ(sbPtr->fromValue, sbPtr->toValue)) {
+ double dvalue;
+
+ if (sscanf(entryPtr->string, "%lf", &dvalue) <= 0) {
+ /*
+ * If the string doesn't scan as a double value, just
+ * use the -from value
+ */
+
+ dvalue = sbPtr->fromValue;
+ } else if (up) {
+ dvalue += sbPtr->increment;
+ if (dvalue > sbPtr->toValue) {
+ if (sbPtr->wrap) {
+ dvalue = sbPtr->fromValue;
+ } else {
+ dvalue = sbPtr->toValue;
+ }
+ } else if (dvalue < sbPtr->fromValue) {
+ /*
+ * It's possible that when pressing up, we are still less
+ * than the fromValue, because the user may have
+ * manipulated the value by hand.
+ */
+
+ dvalue = sbPtr->fromValue;
+ }
+ } else {
+ dvalue -= sbPtr->increment;
+ if (dvalue < sbPtr->fromValue) {
+ if (sbPtr->wrap) {
+ dvalue = sbPtr->toValue;
+ } else {
+ dvalue = sbPtr->fromValue;
+ }
+ } else if (dvalue > sbPtr->toValue) {
+ /*
+ * It's possible that when pressing down, we are still
+ * greater than the toValue, because the user may have
+ * manipulated the value by hand.
+ */
+
+ dvalue = sbPtr->toValue;
+ }
+ }
+ sprintf(sbPtr->formatBuf, sbPtr->valueFormat, dvalue);
+ code = EntryValueChanged(entryPtr, sbPtr->formatBuf);
+ }
+ }
+ if (code != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (sbPtr->command != NULL) {
+ Tcl_DStringInit(&script);
+ ExpandPercents(entryPtr, sbPtr->command, type, "", 0,
+ VALIDATE_BUTTON, &script);
+ Tcl_DStringAppend(&script, "", 1);
+
+ code = Tcl_EvalEx(interp, Tcl_DStringValue(&script), -1,
+ TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT);
+ Tcl_DStringFree(&script);
+
+ if (code != TCL_OK) {
+ Tcl_AddErrorInfo(interp,
+ "\n (in command executed by spinbox)");
+ Tcl_BackgroundException(interp, code);
+
+ /*
+ * Yes, it's an error, but a bg one, so we return OK
+ */
+
+ return TCL_OK;
+ }
+
+ Tcl_ResetResult(interp);
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ComputeFormat --
+ *
+ * This function is invoked to recompute the "format" fields of a
+ * spinbox's widget record, which determines how the value of the dial is
+ * converted to a string.
+ *
+ * Results:
+ * Tcl result code.
+ *
+ * Side effects:
+ * The format fields of the spinbox are modified.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ComputeFormat(
+ Spinbox *sbPtr) /* Information about dial widget. */
+{
+ double maxValue, x;
+ int mostSigDigit, numDigits, leastSigDigit, afterDecimal;
+ int eDigits, fDigits;
+
+ /*
+ * Compute the displacement from the decimal of the most significant digit
+ * required for any number in the dial's range.
+ */
+
+ if (sbPtr->reqFormat) {
+ sbPtr->valueFormat = sbPtr->reqFormat;
+ return TCL_OK;
+ }
+
+ maxValue = fabs(sbPtr->fromValue);
+ x = fabs(sbPtr->toValue);
+ if (x > maxValue) {
+ maxValue = x;
+ }
+ if (maxValue == 0) {
+ maxValue = 1;
+ }
+ mostSigDigit = (int) floor(log10(maxValue));
+
+ if (fabs(sbPtr->increment) > MIN_DBL_VAL) {
+ /*
+ * A increment was specified, so use it.
+ */
+
+ leastSigDigit = (int) floor(log10(sbPtr->increment));
+ } else {
+ leastSigDigit = 0;
+ }
+ numDigits = mostSigDigit - leastSigDigit + 1;
+ if (numDigits < 1) {
+ numDigits = 1;
+ }
+
+ /*
+ * Compute the number of characters required using "e" format and "f"
+ * format, and then choose whichever one takes fewer characters.
+ */
+
+ eDigits = numDigits + 4;
+ if (numDigits > 1) {
+ eDigits++; /* Decimal point. */
+ }
+ afterDecimal = numDigits - mostSigDigit - 1;
+ if (afterDecimal < 0) {
+ afterDecimal = 0;
+ }
+ fDigits = (mostSigDigit >= 0) ? mostSigDigit + afterDecimal : afterDecimal;
+ if (afterDecimal > 0) {
+ fDigits++; /* Decimal point. */
+ }
+ if (mostSigDigit < 0) {
+ fDigits++; /* Zero to left of decimal point. */
+ }
+ if (fDigits <= eDigits) {
+ sprintf(sbPtr->digitFormat, "%%.%df", afterDecimal);
+ } else {
+ sprintf(sbPtr->digitFormat, "%%.%de", numDigits-1);
+ }
+ sbPtr->valueFormat = sbPtr->digitFormat;
+ return TCL_OK;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkEntry.h b/tk8.6/generic/tkEntry.h
new file mode 100644
index 0000000..6b1bf87
--- /dev/null
+++ b/tk8.6/generic/tkEntry.h
@@ -0,0 +1,298 @@
+/*
+ * tkEntry.h --
+ *
+ * This module defined the structures for the Entry & SpinBox widgets.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Copyright (c) 2002 Apple Inc.
+ */
+
+#ifndef _TKENTRY
+#define _TKENTRY
+
+#ifndef _TKINT
+#include "tkInt.h"
+#endif
+
+enum EntryType {
+ TK_ENTRY, TK_SPINBOX
+};
+
+/*
+ * A data structure of the following type is kept for each Entry widget
+ * managed by this file:
+ */
+
+typedef struct {
+ Tk_Window tkwin; /* Window that embodies the entry. NULL means
+ * that the window has been destroyed but the
+ * data structures haven't yet been cleaned
+ * up.*/
+ Display *display; /* Display containing widget. Used, among
+ * other things, so that resources can be
+ * freed even after tkwin has gone away. */
+ Tcl_Interp *interp; /* Interpreter associated with entry. */
+ Tcl_Command widgetCmd; /* Token for entry's widget command. */
+ Tk_OptionTable optionTable; /* Table that defines configuration options
+ * available for this widget. */
+ enum EntryType type; /* Specialized type of Entry widget */
+
+ /*
+ * Fields that are set by widget commands other than "configure".
+ */
+
+ const char *string; /* Pointer to storage for string;
+ * NULL-terminated; malloc-ed. */
+ int insertPos; /* Character index before which next typed
+ * character will be inserted. */
+
+ /*
+ * Information about what's selected, if any.
+ */
+
+ int selectFirst; /* Character index of first selected character
+ * (-1 means nothing selected. */
+ int selectLast; /* Character index just after last selected
+ * character (-1 means nothing selected. */
+ int selectAnchor; /* Fixed end of selection (i.e. "select to"
+ * operation will use this as one end of the
+ * selection). */
+
+ /*
+ * Information for scanning:
+ */
+
+ int scanMarkX; /* X-position at which scan started (e.g.
+ * button was pressed here). */
+ int scanMarkIndex; /* Character index of character that was at
+ * left of window when scan started. */
+
+ /*
+ * Configuration settings that are updated by Tk_ConfigureWidget.
+ */
+
+ Tk_3DBorder normalBorder; /* Used for drawing border around whole
+ * window, plus used for background. */
+ Tk_3DBorder disabledBorder; /* Used for drawing border around whole window
+ * in disabled state, plus used for
+ * background. */
+ Tk_3DBorder readonlyBorder; /* Used for drawing border around whole window
+ * in readonly state, plus used for
+ * background. */
+ int borderWidth; /* Width of 3-D border around window. */
+ Tk_Cursor cursor; /* Current cursor for window, or NULL. */
+ int exportSelection; /* Non-zero means tie internal entry selection
+ * to X selection. */
+ Tk_Font tkfont; /* Information about text font, or NULL. */
+ XColor *fgColorPtr; /* Text color in normal mode. */
+ XColor *dfgColorPtr; /* Text color in disabled mode. */
+ XColor *highlightBgColorPtr;/* Color for drawing traversal highlight area
+ * when highlight is off. */
+ XColor *highlightColorPtr; /* Color for drawing traversal highlight. */
+ int highlightWidth; /* Width in pixels of highlight to draw around
+ * widget when it has the focus. <= 0 means
+ * don't draw a highlight. */
+ Tk_3DBorder insertBorder; /* Used to draw vertical bar for insertion
+ * cursor. */
+ int insertBorderWidth; /* Width of 3-D border around insert cursor. */
+ int insertOffTime; /* Number of milliseconds cursor should spend
+ * in "off" state for each blink. */
+ int insertOnTime; /* Number of milliseconds cursor should spend
+ * in "on" state for each blink. */
+ int insertWidth; /* Total width of insert cursor. */
+ Tk_Justify justify; /* Justification to use for text within
+ * window. */
+ int relief; /* 3-D effect: TK_RELIEF_RAISED, etc. */
+ Tk_3DBorder selBorder; /* Border and background for selected
+ * characters. */
+ int selBorderWidth; /* Width of border around selection. */
+ XColor *selFgColorPtr; /* Foreground color for selected text. */
+ int state; /* Normal or disabled. Entry is read-only when
+ * disabled. */
+ char *textVarName; /* Name of variable (malloc'ed) or NULL. If
+ * non-NULL, entry's string tracks the
+ * contents of this variable and vice
+ * versa. */
+ char *takeFocus; /* Value of -takefocus option; not used in the
+ * C code, but used by keyboard traversal
+ * scripts. Malloc'ed, but may be NULL. */
+ int prefWidth; /* Desired width of window, measured in
+ * average characters. */
+ char *scrollCmd; /* Command prefix for communicating with
+ * scrollbar(s). Malloc'ed. NULL means no
+ * command to issue. */
+ char *showChar; /* Value of -show option. If non-NULL, first
+ * character is used for displaying all
+ * characters in entry. Malloc'ed. This is
+ * only used by the Entry widget. */
+
+ /*
+ * Fields whose values are derived from the current values of the
+ * configuration settings above.
+ */
+
+ const char *displayString; /* String to use when displaying. This may be
+ * a pointer to string, or a pointer to
+ * malloced memory with the same character
+ * length as string but whose characters are
+ * all equal to showChar. */
+ int numBytes; /* Length of string in bytes. */
+ int numChars; /* Length of string in characters. Both string
+ * and displayString have the same character
+ * length, but may have different byte lengths
+ * due to being made from different UTF-8
+ * characters. */
+ int numDisplayBytes; /* Length of displayString in bytes. */
+ int inset; /* Number of pixels on the left and right
+ * sides that are taken up by XPAD,
+ * borderWidth (if any), and highlightWidth
+ * (if any). */
+ Tk_TextLayout textLayout; /* Cached text layout information. */
+ int layoutX, layoutY; /* Origin for layout. */
+ int leftX; /* X position at which character at leftIndex
+ * is drawn (varies depending on justify). */
+ int leftIndex; /* Character index of left-most character
+ * visible in window. */
+ Tcl_TimerToken insertBlinkHandler;
+ /* Timer handler used to blink cursor on and
+ * off. */
+ GC textGC; /* For drawing normal text. */
+ GC selTextGC; /* For drawing selected text. */
+ GC highlightGC; /* For drawing traversal highlight. */
+ int avgWidth; /* Width of average character. */
+ int xWidth; /* Extra width to reserve for widget. Used by
+ * spinboxes for button space. */
+ int flags; /* Miscellaneous flags; see below for
+ * definitions. */
+
+ int validate; /* Non-zero means try to validate */
+ char *validateCmd; /* Command prefix to use when invoking
+ * validate command. NULL means don't invoke
+ * commands. Malloc'ed. */
+ char *invalidCmd; /* Command called when a validation returns 0
+ * (successfully fails), defaults to {}. */
+} Entry;
+
+/*
+ * A data structure of the following type is kept for each spinbox widget
+ * managed by this file:
+ */
+
+typedef struct {
+ Entry entry; /* A pointer to the generic entry structure.
+ * This must be the first element of the
+ * Spinbox. */
+
+ /*
+ * Spinbox specific configuration settings.
+ */
+
+ Tk_3DBorder activeBorder; /* Used for drawing border around active
+ * buttons. */
+ Tk_3DBorder buttonBorder; /* Used for drawing border around buttons. */
+ Tk_Cursor bCursor; /* cursor for buttons, or NULL. */
+ int bdRelief; /* 3-D effect: TK_RELIEF_RAISED, etc. */
+ int buRelief; /* 3-D effect: TK_RELIEF_RAISED, etc. */
+ char *command; /* Command to invoke for spin buttons. NULL
+ * means no command to issue. */
+
+ /*
+ * Spinbox specific fields for use with configuration settings above.
+ */
+
+ int wrap; /* whether to wrap around when spinning */
+
+ int selElement; /* currently selected control */
+ int curElement; /* currently mouseover control */
+
+ int repeatDelay; /* repeat delay */
+ int repeatInterval; /* repeat interval */
+
+ double fromValue; /* Value corresponding to left/top of dial */
+ double toValue; /* Value corresponding to right/bottom of
+ * dial */
+ double increment; /* If > 0, all values are rounded to an even
+ * multiple of this value. */
+ char *formatBuf; /* string into which to format value.
+ * Malloc'ed. */
+ char *reqFormat; /* Sprintf conversion specifier used for the
+ * value that the users requests. Malloc'ed */
+ char *valueFormat; /* Sprintf conversion specifier used for the
+ * value. */
+ char digitFormat[16]; /* Sprintf conversion specifier computed from
+ * digits and other information; used for the
+ * value. */
+
+ char *valueStr; /* Values List. Malloc'ed. */
+ Tcl_Obj *listObj; /* Pointer to the list object being used */
+ int eIndex; /* Holds the current index into elements */
+ int nElements; /* Holds the current count of elements */
+} Spinbox;
+
+/*
+ * Assigned bits of "flags" fields of Entry structures, and what those bits
+ * mean:
+ *
+ * REDRAW_PENDING: Non-zero means a DoWhenIdle handler has
+ * already been queued to redisplay the entry.
+ * BORDER_NEEDED: Non-zero means 3-D border must be redrawn
+ * around window during redisplay. Normally only
+ * text portion needs to be redrawn.
+ * CURSOR_ON: Non-zero means insert cursor is displayed at
+ * present. 0 means it isn't displayed.
+ * GOT_FOCUS: Non-zero means this window has the input
+ * focus.
+ * UPDATE_SCROLLBAR: Non-zero means scrollbar should be updated
+ * during next redisplay operation.
+ * GOT_SELECTION: Non-zero means we've claimed the selection.
+ * ENTRY_DELETED: This entry has been effectively destroyed.
+ * VALIDATING: Non-zero means we are in a validateCmd
+ * VALIDATE_VAR: Non-zero means we are attempting to validate
+ * the entry's textvariable with validateCmd
+ * VALIDATE_ABORT: Non-zero if validatecommand signals an abort
+ * for current procedure and make no changes
+ * ENTRY_VAR_TRACED: Non-zero if a var trace is set.
+ */
+
+#define REDRAW_PENDING 1
+#define BORDER_NEEDED 2
+#define CURSOR_ON 4
+#define GOT_FOCUS 8
+#define UPDATE_SCROLLBAR 0x10
+#define GOT_SELECTION 0x20
+#define ENTRY_DELETED 0x40
+#define VALIDATING 0x80
+#define VALIDATE_VAR 0x100
+#define VALIDATE_ABORT 0x200
+#define ENTRY_VAR_TRACED 0x400
+
+/*
+ * The following enum is used to define a type for the -state option of the
+ * Entry widget. These values are used as indices into the string table below.
+ */
+
+enum state {
+ STATE_DISABLED, STATE_NORMAL, STATE_READONLY
+};
+
+/*
+ * This is the element index corresponding to the strings in selElementNames.
+ * If you modify them, you must modify the numbers here.
+ */
+
+enum selelement {
+ SEL_NONE, SEL_BUTTONDOWN, SEL_BUTTONUP, SEL_NULL, SEL_ENTRY
+};
+
+/*
+ * Declaration of functions used in the implementation of the native side of
+ * the Entry widget.
+ */
+
+MODULE_SCOPE int TkpDrawEntryBorderAndFocus(Entry *entryPtr,
+ Drawable d, int isSpinbox);
+MODULE_SCOPE int TkpDrawSpinboxButtons(Spinbox *sbPtr, Drawable d);
+
+#endif /* _TKENTRY */
diff --git a/tk8.6/generic/tkError.c b/tk8.6/generic/tkError.c
new file mode 100644
index 0000000..277d7f0
--- /dev/null
+++ b/tk8.6/generic/tkError.c
@@ -0,0 +1,299 @@
+/*
+ * tkError.c --
+ *
+ * This file provides a high-performance mechanism for selectively
+ * dealing with errors that occur in talking to the X server. This is
+ * useful, for example, when communicating with a window that may not
+ * exist.
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkInt.h"
+
+/*
+ * The default X error handler gets saved here, so that it can be invoked if
+ * an error occurs that we can't handle.
+ */
+
+typedef int (*TkXErrorHandler)(Display *display, XErrorEvent *eventPtr);
+static TkXErrorHandler defaultHandler = NULL;
+
+/*
+ * Forward references to procedures declared later in this file:
+ */
+
+static int ErrorProc(Display *display, XErrorEvent *errEventPtr);
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CreateErrorHandler --
+ *
+ * Arrange for all a given procedure to be invoked whenever certain
+ * errors occur.
+ *
+ * Results:
+ * The return value is a token identifying the handler; it must be passed
+ * to Tk_DeleteErrorHandler to delete the handler.
+ *
+ * Side effects:
+ * If an X error occurs that matches the error, request, and minor
+ * arguments, then errorProc will be invoked. ErrorProc should have the
+ * following structure:
+ *
+ * int
+ * errorProc(caddr_t clientData, XErrorEvent *errorEventPtr) {
+ * }
+ *
+ * The clientData argument will be the same as the clientData argument to
+ * this procedure, and errorEvent will describe the error. If errorProc
+ * returns 0, it means that it completely "handled" the error: no further
+ * processing should be done. If errorProc returns 1, it means that it
+ * didn't know how to deal with the error, so we should look for other
+ * error handlers, or invoke the default error handler if no other
+ * handler returns zero. Handlers are invoked in order of age: youngest
+ * handler first.
+ *
+ * Note: errorProc will only be called for errors associated with X
+ * requests made AFTER this call, but BEFORE the handler is deleted by
+ * calling Tk_DeleteErrorHandler.
+ *
+ *--------------------------------------------------------------
+ */
+
+Tk_ErrorHandler
+Tk_CreateErrorHandler(
+ Display *display, /* Display for which to handle errors. */
+ int error, /* Consider only errors with this error_code
+ * (-1 means consider all errors). */
+ int request, /* Consider only errors with this major
+ * request code (-1 means consider all major
+ * codes). */
+ int minorCode, /* Consider only errors with this minor
+ * request code (-1 means consider all minor
+ * codes). */
+ Tk_ErrorProc *errorProc, /* Procedure to invoke when a matching error
+ * occurs. NULL means just ignore matching
+ * errors. */
+ ClientData clientData) /* Arbitrary value to pass to errorProc. */
+{
+ TkErrorHandler *errorPtr;
+ TkDisplay *dispPtr;
+
+ /*
+ * Find the display. If Tk doesn't know about this display then it's an
+ * error: panic.
+ */
+
+ dispPtr = TkGetDisplay(display);
+ if (dispPtr == NULL) {
+ Tcl_Panic("Unknown display passed to Tk_CreateErrorHandler");
+ }
+
+ /*
+ * Make sure that X calls us whenever errors occur.
+ */
+
+ if (defaultHandler == NULL) {
+ defaultHandler = XSetErrorHandler(ErrorProc);
+ }
+
+ /*
+ * Create the handler record.
+ */
+
+ errorPtr = ckalloc(sizeof(TkErrorHandler));
+ errorPtr->dispPtr = dispPtr;
+ errorPtr->firstRequest = NextRequest(display);
+ errorPtr->lastRequest = (unsigned) -1;
+ errorPtr->error = error;
+ errorPtr->request = request;
+ errorPtr->minorCode = minorCode;
+ errorPtr->errorProc = errorProc;
+ errorPtr->clientData = clientData;
+ errorPtr->nextPtr = dispPtr->errorPtr;
+ dispPtr->errorPtr = errorPtr;
+
+ return (Tk_ErrorHandler) errorPtr;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_DeleteErrorHandler --
+ *
+ * Do not use an error handler anymore.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The handler denoted by the "handler" argument will not be invoked for
+ * any X errors associated with requests made after this call. However,
+ * if errors arrive later for requests made BEFORE this call, then the
+ * handler will still be invoked. Call XSync if you want to be sure that
+ * all outstanding errors have been received and processed.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_DeleteErrorHandler(
+ Tk_ErrorHandler handler) /* Token for handler to delete; was previous
+ * return value from Tk_CreateErrorHandler. */
+{
+ TkErrorHandler *errorPtr = (TkErrorHandler *) handler;
+ TkDisplay *dispPtr = errorPtr->dispPtr;
+
+ errorPtr->lastRequest = NextRequest(dispPtr->display) - 1;
+
+ /*
+ * Every once-in-a-while, cleanup handlers that are no longer active. We
+ * probably won't be able to free the handler that was just deleted (need
+ * to wait for any outstanding requests to be processed by server), but
+ * there may be previously-deleted handlers that are now ready for garbage
+ * collection. To reduce the cost of the cleanup, let a few dead handlers
+ * pile up, then clean them all at once. This adds a bit of overhead to
+ * errors that might occur while the dead handlers are hanging around, but
+ * reduces the overhead of scanning the list to clean up (particularly if
+ * there are many handlers that stay around forever).
+ */
+
+ dispPtr->deleteCount += 1;
+ if (dispPtr->deleteCount >= 10) {
+ TkErrorHandler *prevPtr;
+ TkErrorHandler *nextPtr;
+ int lastSerial = LastKnownRequestProcessed(dispPtr->display);
+
+ /*
+ * Last chance to catch errors for this handler: if no event/error
+ * processing took place to follow up the end of this error handler
+ * we need a round trip with the X server now.
+ */
+
+ if (errorPtr->lastRequest > (unsigned long) lastSerial) {
+ XSync(dispPtr->display, False);
+ }
+ dispPtr->deleteCount = 0;
+ errorPtr = dispPtr->errorPtr;
+ for (prevPtr = NULL; errorPtr != NULL; errorPtr = nextPtr) {
+ nextPtr = errorPtr->nextPtr;
+ if ((errorPtr->lastRequest != (unsigned long) -1)
+ && (errorPtr->lastRequest <= (unsigned long) lastSerial)) {
+ if (prevPtr == NULL) {
+ dispPtr->errorPtr = nextPtr;
+ } else {
+ prevPtr->nextPtr = nextPtr;
+ }
+ ckfree(errorPtr);
+ continue;
+ }
+ prevPtr = errorPtr;
+ }
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ErrorProc --
+ *
+ * This procedure is invoked by the X system when error events arrive.
+ *
+ * Results:
+ * If it returns, the return value is zero. However, it is possible that
+ * one of the error handlers may just exit.
+ *
+ * Side effects:
+ * This procedure does two things. First, it uses the serial # in the
+ * error event to eliminate handlers whose expiration serials are now in
+ * the past. Second, it invokes any handlers that want to deal with the
+ * error.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+ErrorProc(
+ Display *display, /* Display for which error occurred. */
+ XErrorEvent *errEventPtr)
+ /* Information about error. */
+{
+ TkDisplay *dispPtr;
+ TkErrorHandler *errorPtr;
+
+ /*
+ * See if we know anything about the display. If not, then invoke the
+ * default error handler.
+ */
+
+ dispPtr = TkGetDisplay(display);
+ if (dispPtr == NULL) {
+ goto couldntHandle;
+ }
+
+ /*
+ * Otherwise invoke any relevant handlers for the error, in order.
+ */
+
+ for (errorPtr = dispPtr->errorPtr; errorPtr != NULL;
+ errorPtr = errorPtr->nextPtr) {
+ if ((errorPtr->firstRequest > errEventPtr->serial)
+ || ((errorPtr->error != -1)
+ && (errorPtr->error != errEventPtr->error_code))
+ || ((errorPtr->request != -1)
+ && (errorPtr->request != errEventPtr->request_code))
+ || ((errorPtr->minorCode != -1)
+ && (errorPtr->minorCode != errEventPtr->minor_code))
+ || ((errorPtr->lastRequest != (unsigned long) -1)
+ && (errorPtr->lastRequest < errEventPtr->serial))) {
+ continue;
+ }
+ if (errorPtr->errorProc == NULL ||
+ errorPtr->errorProc(errorPtr->clientData, errEventPtr) == 0) {
+ return 0;
+ }
+ }
+
+ /*
+ * See if the error is a BadWindow error. If so, and it refers to a window
+ * that still exists in our window table, then ignore the error. Errors
+ * like this can occur if a window owned by us is deleted by someone
+ * externally, like a window manager. We'll ignore the errors at least
+ * long enough to clean up internally and remove the entry from the window
+ * table.
+ *
+ * NOTE: For embedding, we must also check whether the window was recently
+ * deleted. If so, it may be that Tk generated operations on windows that
+ * were deleted by the container. Now we are getting the errors
+ * (BadWindow) after Tk already deleted the window itself.
+ */
+
+ if (errEventPtr->error_code == BadWindow) {
+ Window w = (Window) errEventPtr->resourceid;
+
+ if (Tk_IdToWindow(display, w) != NULL) {
+ return 0;
+ }
+ }
+
+ /*
+ * We couldn't handle the error. Use the default handler.
+ */
+
+ couldntHandle:
+ return defaultHandler(display, errEventPtr);
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkEvent.c b/tk8.6/generic/tkEvent.c
new file mode 100644
index 0000000..b36d5de
--- /dev/null
+++ b/tk8.6/generic/tkEvent.c
@@ -0,0 +1,2158 @@
+/*
+ * tkEvent.c --
+ *
+ * This file provides basic low-level facilities for managing X events in
+ * Tk.
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ * Copyright (c) 1998-2000 Ajuba Solutions.
+ * Copyright (c) 2004 George Peter Staplin
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkInt.h"
+
+/*
+ * There's a potential problem if a handler is deleted while it's current
+ * (i.e. its function is executing), since Tk_HandleEvent will need to read
+ * the handler's "nextPtr" field when the function returns. To handle this
+ * problem, structures of the type below indicate the next handler to be
+ * processed for any (recursively nested) dispatches in progress. The
+ * nextHandler fields get updated if the handlers pointed to are deleted.
+ * Tk_HandleEvent also needs to know if the entire window gets deleted; the
+ * winPtr field is set to zero if that particular window gets deleted.
+ */
+
+typedef struct InProgress {
+ XEvent *eventPtr; /* Event currently being handled. */
+ TkWindow *winPtr; /* Window for event. Gets set to None if
+ * window is deleted while event is being
+ * handled. */
+ TkEventHandler *nextHandler;/* Next handler in search. */
+ struct InProgress *nextPtr; /* Next higher nested search. */
+} InProgress;
+
+/*
+ * For each call to Tk_CreateGenericHandler or Tk_CreateClientMessageHandler,
+ * an instance of the following structure will be created. All of the active
+ * handlers are linked into a list.
+ */
+
+typedef struct GenericHandler {
+ Tk_GenericProc *proc; /* Function to dispatch on all X events. */
+ ClientData clientData; /* Client data to pass to function. */
+ int deleteFlag; /* Flag to set when this handler is
+ * deleted. */
+ struct GenericHandler *nextPtr;
+ /* Next handler in list of all generic
+ * handlers, or NULL for end of list. */
+} GenericHandler;
+
+/*
+ * There's a potential problem if Tk_HandleEvent is entered recursively. A
+ * handler cannot be deleted physically until we have returned from calling
+ * it. Otherwise, we're looking at unallocated memory in advancing to its
+ * `next' entry. We deal with the problem by using the `delete flag' and
+ * deleting handlers only when it's known that there's no handler active.
+ */
+
+/*
+ * The following structure is used for queueing X-style events on the Tcl
+ * event queue.
+ */
+
+typedef struct TkWindowEvent {
+ Tcl_Event header; /* Standard information for all events. */
+ XEvent event; /* The X event. */
+} TkWindowEvent;
+
+/*
+ * Array of event masks corresponding to each X event:
+ */
+
+static const unsigned long realEventMasks[MappingNotify+1] = {
+ 0,
+ 0,
+ KeyPressMask, /* KeyPress */
+ KeyReleaseMask, /* KeyRelease */
+ ButtonPressMask, /* ButtonPress */
+ ButtonReleaseMask, /* ButtonRelease */
+ PointerMotionMask|PointerMotionHintMask|ButtonMotionMask
+ |Button1MotionMask|Button2MotionMask|Button3MotionMask
+ |Button4MotionMask|Button5MotionMask,
+ /* MotionNotify */
+ EnterWindowMask, /* EnterNotify */
+ LeaveWindowMask, /* LeaveNotify */
+ FocusChangeMask, /* FocusIn */
+ FocusChangeMask, /* FocusOut */
+ KeymapStateMask, /* KeymapNotify */
+ ExposureMask, /* Expose */
+ ExposureMask, /* GraphicsExpose */
+ ExposureMask, /* NoExpose */
+ VisibilityChangeMask, /* VisibilityNotify */
+ SubstructureNotifyMask, /* CreateNotify */
+ StructureNotifyMask, /* DestroyNotify */
+ StructureNotifyMask, /* UnmapNotify */
+ StructureNotifyMask, /* MapNotify */
+ SubstructureRedirectMask, /* MapRequest */
+ StructureNotifyMask, /* ReparentNotify */
+ StructureNotifyMask, /* ConfigureNotify */
+ SubstructureRedirectMask, /* ConfigureRequest */
+ StructureNotifyMask, /* GravityNotify */
+ ResizeRedirectMask, /* ResizeRequest */
+ StructureNotifyMask, /* CirculateNotify */
+ SubstructureRedirectMask, /* CirculateRequest */
+ PropertyChangeMask, /* PropertyNotify */
+ 0, /* SelectionClear */
+ 0, /* SelectionRequest */
+ 0, /* SelectionNotify */
+ ColormapChangeMask, /* ColormapNotify */
+ 0, /* ClientMessage */
+ 0 /* Mapping Notify */
+};
+
+static const unsigned long virtualEventMasks[TK_LASTEVENT-VirtualEvent] = {
+ VirtualEventMask, /* VirtualEvents */
+ ActivateMask, /* ActivateNotify */
+ ActivateMask, /* DeactivateNotify */
+ MouseWheelMask /* MouseWheelEvent */
+};
+
+/*
+ * For each exit handler created with a call to TkCreateExitHandler or
+ * TkCreateThreadExitHandler there is a structure of the following type:
+ */
+
+typedef struct ExitHandler {
+ Tcl_ExitProc *proc; /* Function to call when process exits. */
+ ClientData clientData; /* One word of information to pass to proc. */
+ struct ExitHandler *nextPtr;/* Next in list of all exit handlers for this
+ * application, or NULL for end of list. */
+} ExitHandler;
+
+/*
+ * The structure below is used to store Data for the Event module that must be
+ * kept thread-local. The "dataKey" is used to fetch the thread-specific
+ * storage for the current thread.
+ */
+
+typedef struct {
+ int handlersActive; /* The following variable has a non-zero value
+ * when a handler is active. */
+ InProgress *pendingPtr; /* Topmost search in progress, or NULL if
+ * none. */
+
+ /*
+ * List of generic handler records.
+ */
+
+ GenericHandler *genericList;/* First handler in the list, or NULL. */
+ GenericHandler *lastGenericPtr;
+ /* Last handler in list. */
+
+ /*
+ * List of client message handler records.
+ */
+
+ GenericHandler *cmList; /* First handler in the list, or NULL. */
+ GenericHandler *lastCmPtr; /* Last handler in list. */
+
+ /*
+ * If someone has called Tk_RestrictEvents, the information below keeps
+ * track of it.
+ */
+
+ Tk_RestrictProc *restrictProc;
+ /* Function to call. NULL means no
+ * restrictProc is currently in effect. */
+ ClientData restrictArg; /* Argument to pass to restrictProc. */
+ ExitHandler *firstExitPtr; /* First in list of all exit handlers for this
+ * thread. */
+ int inExit; /* True when this thread is exiting. This is
+ * used as a hack to decide to close the
+ * standard channels. */
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+
+/*
+ * There are both per-process and per-thread exit handlers. The first list is
+ * controlled by a mutex. The other is in thread local storage.
+ */
+
+static ExitHandler *firstExitPtr = NULL;
+ /* First in list of all exit handlers for
+ * application. */
+TCL_DECLARE_MUTEX(exitMutex)
+
+/*
+ * Prototypes for functions that are only referenced locally within this file.
+ */
+
+static void CleanUpTkEvent(XEvent *eventPtr);
+static void DelayedMotionProc(ClientData clientData);
+static int GetButtonMask(unsigned int Button);
+static unsigned long GetEventMaskFromXEvent(XEvent *eventPtr);
+static TkWindow * GetTkWindowFromXEvent(XEvent *eventPtr);
+static void InvokeClientMessageHandlers(ThreadSpecificData *tsdPtr,
+ Tk_Window tkwin, XEvent *eventPtr);
+static int InvokeFocusHandlers(TkWindow **winPtrPtr,
+ unsigned long mask, XEvent *eventPtr);
+static int InvokeGenericHandlers(ThreadSpecificData *tsdPtr,
+ XEvent *eventPtr);
+static int InvokeMouseHandlers(TkWindow *winPtr,
+ unsigned long mask, XEvent *eventPtr);
+static Window ParentXId(Display *display, Window w);
+static int RefreshKeyboardMappingIfNeeded(XEvent *eventPtr);
+static int TkXErrorHandler(ClientData clientData,
+ XErrorEvent *errEventPtr);
+static void UpdateButtonEventState(XEvent *eventPtr);
+static int WindowEventProc(Tcl_Event *evPtr, int flags);
+#ifdef TK_USE_INPUT_METHODS
+static void CreateXIC(TkWindow *winPtr);
+#endif /* TK_USE_INPUT_METHODS */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InvokeFocusHandlers --
+ *
+ * Call focus-related code to look at FocusIn, FocusOut, Enter, and Leave
+ * events; depending on its return value, ignore the event.
+ *
+ * Results:
+ * 0 further processing can be done on the event.
+ * 1 we are done with the event passed.
+ *
+ * Side effects:
+ * The *winPtrPtr in the caller may be changed to the TkWindow for the
+ * window with focus.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+InvokeFocusHandlers(
+ TkWindow **winPtrPtr,
+ unsigned long mask,
+ XEvent *eventPtr)
+{
+ if ((mask & (FocusChangeMask|EnterWindowMask|LeaveWindowMask))
+ && (TkFocusFilterEvent(*winPtrPtr, eventPtr) == 0)) {
+ return 1;
+ }
+
+ /*
+ * Only key-related events are directed according to the focus.
+ */
+
+ if (mask & (KeyPressMask|KeyReleaseMask)) {
+ (*winPtrPtr)->dispPtr->lastEventTime = eventPtr->xkey.time;
+ *winPtrPtr = TkFocusKeyEvent(*winPtrPtr, eventPtr);
+ if (*winPtrPtr == NULL) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InvokeMouseHandlers --
+ *
+ * Call a grab-related function to do special processing on pointer
+ * events.
+ *
+ * Results:
+ * 0 further processing can be done on the event.
+ * 1 we are done with the event passed.
+ *
+ * Side effects:
+ * New events may be queued from TkPointerEvent and grabs may be added
+ * and/or removed. The eventPtr may be changed by TkPointerEvent in some
+ * cases.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+InvokeMouseHandlers(
+ TkWindow *winPtr,
+ unsigned long mask,
+ XEvent *eventPtr)
+{
+ if (mask & (ButtonPressMask|ButtonReleaseMask|PointerMotionMask
+ |EnterWindowMask|LeaveWindowMask)) {
+
+ if (mask & (ButtonPressMask|ButtonReleaseMask)) {
+ winPtr->dispPtr->lastEventTime = eventPtr->xbutton.time;
+ } else if (mask & PointerMotionMask) {
+ winPtr->dispPtr->lastEventTime = eventPtr->xmotion.time;
+ } else {
+ winPtr->dispPtr->lastEventTime = eventPtr->xcrossing.time;
+ }
+
+ if (TkPointerEvent(eventPtr, winPtr) == 0) {
+ /*
+ * The event should be ignored to make grab work correctly (as the
+ * comment for TkPointerEvent states).
+ */
+
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CreateXIC --
+ *
+ * Create the X input context for our winPtr.
+ * XIM is only ever enabled on Unix.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifdef TK_USE_INPUT_METHODS
+static void
+CreateXIC(
+ TkWindow *winPtr)
+{
+ TkDisplay *dispPtr = winPtr->dispPtr;
+ long im_event_mask = 0L;
+ const char *preedit_attname = NULL;
+ XVaNestedList preedit_attlist = NULL;
+
+ if (dispPtr->inputStyle & XIMPreeditPosition) {
+ XPoint spot = {0, 0};
+
+ preedit_attname = XNPreeditAttributes;
+ preedit_attlist = XVaCreateNestedList(0,
+ XNSpotLocation, &spot,
+ XNFontSet, dispPtr->inputXfs,
+ NULL);
+ }
+
+ winPtr->inputContext = XCreateIC(dispPtr->inputMethod,
+ XNInputStyle, dispPtr->inputStyle,
+ XNClientWindow, winPtr->window,
+ XNFocusWindow, winPtr->window,
+ preedit_attname, preedit_attlist,
+ NULL);
+
+ if (preedit_attlist) {
+ XFree(preedit_attlist);
+ }
+
+
+ if (winPtr->inputContext == NULL) {
+ /* XCreateIC failed. */
+ return;
+ }
+ winPtr->ximGeneration = dispPtr->ximGeneration;
+
+ /*
+ * Adjust the window's event mask if the IM requires it.
+ */
+ XGetICValues(winPtr->inputContext, XNFilterEvents, &im_event_mask, NULL);
+ if ((winPtr->atts.event_mask & im_event_mask) != im_event_mask) {
+ winPtr->atts.event_mask |= im_event_mask;
+ XSelectInput(winPtr->display, winPtr->window, winPtr->atts.event_mask);
+ }
+}
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetTkWindowFromXEvent --
+ *
+ * Attempt to find which TkWindow is associated with an event. If it
+ * fails we attempt to get the TkWindow from the parent for a property
+ * notification.
+ *
+ * Results:
+ * The TkWindow associated with the event or NULL.
+ *
+ * Side effects:
+ * TkSelPropProc may influence selection on windows not known to Tk.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static TkWindow *
+GetTkWindowFromXEvent(
+ XEvent *eventPtr)
+{
+ TkWindow *winPtr;
+ Window parentXId, handlerWindow = eventPtr->xany.window;
+
+ if ((eventPtr->xany.type == StructureNotifyMask)
+ && (eventPtr->xmap.event != eventPtr->xmap.window)) {
+ handlerWindow = eventPtr->xmap.event;
+ }
+
+ winPtr = (TkWindow *) Tk_IdToWindow(eventPtr->xany.display, handlerWindow);
+
+ if (winPtr == NULL) {
+ /*
+ * There isn't a TkWindow structure for this window. However, if the
+ * event is a PropertyNotify event then call the selection manager (it
+ * deals beneath-the-table with certain properties). Also, if the
+ * window's parent is a Tk window that has the TK_PROP_PROPCHANGE flag
+ * set, then we must propagate the PropertyNotify event up to the
+ * parent.
+ */
+
+ if (eventPtr->type != PropertyNotify) {
+ return NULL;
+ }
+ TkSelPropProc(eventPtr);
+ parentXId = ParentXId(eventPtr->xany.display, handlerWindow);
+ if (parentXId == None) {
+ return NULL;
+ }
+ winPtr = (TkWindow *) Tk_IdToWindow(eventPtr->xany.display, parentXId);
+ if (winPtr == NULL) {
+ return NULL;
+ }
+ if (!(winPtr->flags & TK_PROP_PROPCHANGE)) {
+ return NULL;
+ }
+ }
+ return winPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetEventMaskFromXEvent --
+ *
+ * The event type is looked up in our eventMasks tables, and may be
+ * changed to a different mask depending on the state of the event and
+ * window members.
+ *
+ * Results:
+ * The mask for the event.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static unsigned long
+GetEventMaskFromXEvent(
+ XEvent *eventPtr)
+{
+ unsigned long mask;
+
+ /*
+ * Get the event mask from the correct table. Note that there are two
+ * tables here because that means we no longer need this code to rely on
+ * the exact value of VirtualEvent, which has caused us problems in the
+ * past when X11 changed the value of LASTEvent. [Bug ???]
+ */
+
+ if (eventPtr->xany.type <= MappingNotify) {
+ mask = realEventMasks[eventPtr->xany.type];
+ } else if (eventPtr->xany.type >= VirtualEvent
+ && eventPtr->xany.type<TK_LASTEVENT) {
+ mask = virtualEventMasks[eventPtr->xany.type - VirtualEvent];
+ } else {
+ mask = 0;
+ }
+
+ /*
+ * Events selected by StructureNotify require special handling. They look
+ * the same as those selected by SubstructureNotify. The only difference
+ * is whether the "event" and "window" fields are the same. Compare the
+ * two fields and convert StructureNotify to SubstructureNotify if
+ * necessary.
+ */
+
+ if (mask == StructureNotifyMask) {
+ if (eventPtr->xmap.event != eventPtr->xmap.window) {
+ mask = SubstructureNotifyMask;
+ }
+ }
+ return mask;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * RefreshKeyboardMappingIfNeeded --
+ *
+ * If the event is a MappingNotify event, find its display and refresh
+ * the keyboard mapping information for the display.
+ *
+ * Results:
+ * 0 if the event was not a MappingNotify event
+ * 1 if the event was a MappingNotify event
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+RefreshKeyboardMappingIfNeeded(
+ XEvent *eventPtr)
+{
+ TkDisplay *dispPtr;
+
+ if (eventPtr->type == MappingNotify) {
+ dispPtr = TkGetDisplay(eventPtr->xmapping.display);
+ if (dispPtr != NULL) {
+ XRefreshKeyboardMapping(&eventPtr->xmapping);
+ dispPtr->bindInfoStale = 1;
+ }
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetButtonMask --
+ *
+ * Return the proper Button${n}Mask for the button.
+ *
+ * Results:
+ * A button mask.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GetButtonMask(
+ unsigned int button)
+{
+ switch (button) {
+ case 1:
+ return Button1Mask;
+ case 2:
+ return Button2Mask;
+ case 3:
+ return Button3Mask;
+ case 4:
+ return Button4Mask;
+ case 5:
+ return Button5Mask;
+ }
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UpdateButtonEventState --
+ *
+ * Update the button event state in our TkDisplay using the XEvent
+ * passed. We also may modify the the XEvent passed to fit some aspects
+ * of our TkDisplay.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The TkDisplay's private button state may be modified. The eventPtr's
+ * state may be updated to reflect masks stored in our TkDisplay that the
+ * event doesn't contain. The eventPtr may also be modified to not
+ * contain a button state for the window in which it was not pressed in.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UpdateButtonEventState(
+ XEvent *eventPtr)
+{
+ TkDisplay *dispPtr;
+ int allButtonsMask = Button1Mask | Button2Mask | Button3Mask
+ | Button4Mask | Button5Mask;
+
+ switch (eventPtr->type) {
+ case ButtonPress:
+ dispPtr = TkGetDisplay(eventPtr->xbutton.display);
+ dispPtr->mouseButtonWindow = eventPtr->xbutton.window;
+ eventPtr->xbutton.state |= dispPtr->mouseButtonState;
+
+ dispPtr->mouseButtonState |= GetButtonMask(eventPtr->xbutton.button);
+ break;
+
+ case ButtonRelease:
+ dispPtr = TkGetDisplay(eventPtr->xbutton.display);
+ dispPtr->mouseButtonWindow = None;
+ dispPtr->mouseButtonState &= ~GetButtonMask(eventPtr->xbutton.button);
+ eventPtr->xbutton.state |= dispPtr->mouseButtonState;
+ break;
+
+ case MotionNotify:
+ dispPtr = TkGetDisplay(eventPtr->xmotion.display);
+ if (dispPtr->mouseButtonState & allButtonsMask) {
+ if (eventPtr->xbutton.window != dispPtr->mouseButtonWindow) {
+ /*
+ * This motion event should not be interpreted as a button
+ * press + motion event since this is not the same window the
+ * button was pressed down in.
+ */
+
+ dispPtr->mouseButtonState &= ~allButtonsMask;
+ dispPtr->mouseButtonWindow = None;
+ } else {
+ eventPtr->xmotion.state |= dispPtr->mouseButtonState;
+ }
+ }
+ break;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InvokeClientMessageHandlers --
+ *
+ * Iterate the list of handlers and invoke the function pointer for each.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Handlers may be deleted and events may be sent to handlers.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+InvokeClientMessageHandlers(
+ ThreadSpecificData *tsdPtr,
+ Tk_Window tkwin,
+ XEvent *eventPtr)
+{
+ GenericHandler *prevPtr, *tmpPtr, *curPtr = tsdPtr->cmList;
+
+ for (prevPtr = NULL; curPtr != NULL; ) {
+ if (curPtr->deleteFlag) {
+ if (!tsdPtr->handlersActive) {
+ /*
+ * This handler needs to be deleted and there are no calls
+ * pending through any handlers, so now is a safe time to
+ * delete it.
+ */
+
+ tmpPtr = curPtr->nextPtr;
+ if (prevPtr == NULL) {
+ tsdPtr->cmList = tmpPtr;
+ } else {
+ prevPtr->nextPtr = tmpPtr;
+ }
+ if (tmpPtr == NULL) {
+ tsdPtr->lastCmPtr = prevPtr;
+ }
+ ckfree(curPtr);
+ curPtr = tmpPtr;
+ continue;
+ }
+ } else {
+ int done;
+
+ tsdPtr->handlersActive++;
+ done = (*(Tk_ClientMessageProc *)curPtr->proc)(tkwin, eventPtr);
+ tsdPtr->handlersActive--;
+ if (done) {
+ break;
+ }
+ }
+ prevPtr = curPtr;
+ curPtr = curPtr->nextPtr;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InvokeGenericHandlers --
+ *
+ * Iterate the list of handlers and invoke the function pointer for each.
+ * If the handler invoked returns a non-zero value then we are done.
+ *
+ * Results:
+ * 0 when the event wasn't handled by a handler. Non-zero when it was
+ * processed and handled by a handler.
+ *
+ * Side effects:
+ * Handlers may be deleted and events may be sent to handlers.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+InvokeGenericHandlers(
+ ThreadSpecificData *tsdPtr,
+ XEvent *eventPtr)
+{
+ GenericHandler *prevPtr, *tmpPtr, *curPtr = tsdPtr->genericList;
+
+ for (prevPtr = NULL; curPtr != NULL; ) {
+ if (curPtr->deleteFlag) {
+ if (!tsdPtr->handlersActive) {
+ /*
+ * This handler needs to be deleted and there are no calls
+ * pending through the handler, so now is a safe time to
+ * delete it.
+ */
+
+ tmpPtr = curPtr->nextPtr;
+ if (prevPtr == NULL) {
+ tsdPtr->genericList = tmpPtr;
+ } else {
+ prevPtr->nextPtr = tmpPtr;
+ }
+ if (tmpPtr == NULL) {
+ tsdPtr->lastGenericPtr = prevPtr;
+ }
+ ckfree(curPtr);
+ curPtr = tmpPtr;
+ continue;
+ }
+ } else {
+ int done;
+
+ tsdPtr->handlersActive++;
+ done = curPtr->proc(curPtr->clientData, eventPtr);
+ tsdPtr->handlersActive--;
+ if (done) {
+ return done;
+ }
+ }
+ prevPtr = curPtr;
+ curPtr = curPtr->nextPtr;
+ }
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_CreateEventHandler --
+ *
+ * Arrange for a given function to be invoked whenever events from a
+ * given class occur in a given window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * From now on, whenever an event of the type given by mask occurs for
+ * token and is processed by Tk_HandleEvent, proc will be called. See the
+ * manual entry for details of the calling sequence and return value for
+ * proc.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_CreateEventHandler(
+ Tk_Window token, /* Token for window in which to create
+ * handler. */
+ unsigned long mask, /* Events for which proc should be called. */
+ Tk_EventProc *proc, /* Function to call for each selected event */
+ ClientData clientData) /* Arbitrary data to pass to proc. */
+{
+ register TkEventHandler *handlerPtr;
+ register TkWindow *winPtr = (TkWindow *) token;
+
+ /*
+ * Skim through the list of existing handlers to (a) compute the overall
+ * event mask for the window (so we can pass this new value to the X
+ * system) and (b) see if there's already a handler declared with the same
+ * callback and clientData (if so, just change the mask). If no existing
+ * handler matches, then create a new handler.
+ */
+
+ if (winPtr->handlerList == NULL) {
+ /*
+ * No event handlers defined at all, so must create.
+ */
+
+ handlerPtr = ckalloc(sizeof(TkEventHandler));
+ winPtr->handlerList = handlerPtr;
+ } else {
+ int found = 0;
+
+ for (handlerPtr = winPtr->handlerList; ;
+ handlerPtr = handlerPtr->nextPtr) {
+ if ((handlerPtr->proc == proc)
+ && (handlerPtr->clientData == clientData)) {
+ handlerPtr->mask = mask;
+ found = 1;
+ }
+ if (handlerPtr->nextPtr == NULL) {
+ break;
+ }
+ }
+
+ /*
+ * If we found anything, we're done because we do not need to use
+ * XSelectInput; Tk always selects on all events anyway in order to
+ * support binding on classes, 'all' and other bind-tags.
+ */
+
+ if (found) {
+ return;
+ }
+
+ /*
+ * No event handler matched, so create a new one.
+ */
+
+ handlerPtr->nextPtr = ckalloc(sizeof(TkEventHandler));
+ handlerPtr = handlerPtr->nextPtr;
+ }
+
+ /*
+ * Initialize the new event handler.
+ */
+
+ handlerPtr->mask = mask;
+ handlerPtr->proc = proc;
+ handlerPtr->clientData = clientData;
+ handlerPtr->nextPtr = NULL;
+
+ /*
+ * No need to call XSelectInput: Tk always selects on all events for all
+ * windows (needed to support bindings on classes and "all").
+ */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_DeleteEventHandler --
+ *
+ * Delete a previously-created handler.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If there existed a handler as described by the parameters, the handler
+ * is deleted so that proc will not be invoked again.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_DeleteEventHandler(
+ Tk_Window token, /* Same as corresponding arguments passed */
+ unsigned long mask, /* previously to Tk_CreateEventHandler. */
+ Tk_EventProc *proc,
+ ClientData clientData)
+{
+ register TkEventHandler *handlerPtr;
+ register InProgress *ipPtr;
+ TkEventHandler *prevPtr;
+ register TkWindow *winPtr = (TkWindow *) token;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ /*
+ * Find the event handler to be deleted, or return immediately if it
+ * doesn't exist.
+ */
+
+ for (handlerPtr = winPtr->handlerList, prevPtr = NULL; ;
+ prevPtr = handlerPtr, handlerPtr = handlerPtr->nextPtr) {
+ if (handlerPtr == NULL) {
+ return;
+ }
+ if ((handlerPtr->mask == mask) && (handlerPtr->proc == proc)
+ && (handlerPtr->clientData == clientData)) {
+ break;
+ }
+ }
+
+ /*
+ * If Tk_HandleEvent is about to process this handler, tell it to process
+ * the next one instead.
+ */
+
+ for (ipPtr = tsdPtr->pendingPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
+ if (ipPtr->nextHandler == handlerPtr) {
+ ipPtr->nextHandler = handlerPtr->nextPtr;
+ }
+ }
+
+ /*
+ * Free resources associated with the handler.
+ */
+
+ if (prevPtr == NULL) {
+ winPtr->handlerList = handlerPtr->nextPtr;
+ } else {
+ prevPtr->nextPtr = handlerPtr->nextPtr;
+ }
+ ckfree(handlerPtr);
+
+ /*
+ * No need to call XSelectInput: Tk always selects on all events for all
+ * windows (needed to support bindings on classes and "all").
+ */
+}
+
+/*----------------------------------------------------------------------
+ *
+ * Tk_CreateGenericHandler --
+ *
+ * Register a function to be called on each X event, regardless of
+ * display or window. Generic handlers are useful for capturing events
+ * that aren't associated with windows, or events for windows not managed
+ * by Tk.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * From now on, whenever an X event is given to Tk_HandleEvent, invoke
+ * proc, giving it clientData and the event as arguments.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_CreateGenericHandler(
+ Tk_GenericProc *proc, /* Function to call on every event. */
+ ClientData clientData) /* One-word value to pass to proc. */
+{
+ GenericHandler *handlerPtr;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ handlerPtr = ckalloc(sizeof(GenericHandler));
+
+ handlerPtr->proc = proc;
+ handlerPtr->clientData = clientData;
+ handlerPtr->deleteFlag = 0;
+ handlerPtr->nextPtr = NULL;
+ if (tsdPtr->genericList == NULL) {
+ tsdPtr->genericList = handlerPtr;
+ } else {
+ tsdPtr->lastGenericPtr->nextPtr = handlerPtr;
+ }
+ tsdPtr->lastGenericPtr = handlerPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_DeleteGenericHandler --
+ *
+ * Delete a previously-created generic handler.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * If there existed a handler as described by the parameters, that
+ * handler is logically deleted so that proc will not be invoked again.
+ * The physical deletion happens in the event loop in Tk_HandleEvent.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_DeleteGenericHandler(
+ Tk_GenericProc *proc,
+ ClientData clientData)
+{
+ GenericHandler * handler;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ for (handler=tsdPtr->genericList ; handler ; handler=handler->nextPtr) {
+ if ((handler->proc == proc) && (handler->clientData == clientData)) {
+ handler->deleteFlag = 1;
+ }
+ }
+}
+
+/*----------------------------------------------------------------------
+ *
+ * Tk_CreateClientMessageHandler --
+ *
+ * Register a function to be called on each ClientMessage event.
+ * ClientMessage handlers are useful for Drag&Drop extensions.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * From now on, whenever a ClientMessage event is received that isn't a
+ * WM_PROTOCOL event or SelectionEvent, invoke proc, giving it tkwin and
+ * the event as arguments.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_CreateClientMessageHandler(
+ Tk_ClientMessageProc *proc) /* Function to call on event. */
+{
+ GenericHandler *handlerPtr;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ /*
+ * We use a GenericHandler struct, because it's basically the same, except
+ * with an extra clientData field we'll never use.
+ */
+
+ handlerPtr = ckalloc(sizeof(GenericHandler));
+
+ handlerPtr->proc = (Tk_GenericProc *) proc;
+ handlerPtr->clientData = NULL; /* never used */
+ handlerPtr->deleteFlag = 0;
+ handlerPtr->nextPtr = NULL;
+ if (tsdPtr->cmList == NULL) {
+ tsdPtr->cmList = handlerPtr;
+ } else {
+ tsdPtr->lastCmPtr->nextPtr = handlerPtr;
+ }
+ tsdPtr->lastCmPtr = handlerPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_DeleteClientMessageHandler --
+ *
+ * Delete a previously-created ClientMessage handler.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * If there existed a handler as described by the parameters, that
+ * handler is logically deleted so that proc will not be invoked again.
+ * The physical deletion happens in the event loop in
+ * TkClientMessageEventProc.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_DeleteClientMessageHandler(
+ Tk_ClientMessageProc *proc)
+{
+ GenericHandler * handler;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ for (handler=tsdPtr->cmList ; handler!=NULL ; handler=handler->nextPtr) {
+ if (handler->proc == (Tk_GenericProc *) proc) {
+ handler->deleteFlag = 1;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkEventInit --
+ *
+ * This functions initializes all the event module structures used by the
+ * current thread. It must be called before any other function in this
+ * file is called.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkEventInit(void)
+{
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ tsdPtr->handlersActive = 0;
+ tsdPtr->pendingPtr = NULL;
+ tsdPtr->genericList = NULL;
+ tsdPtr->lastGenericPtr = NULL;
+ tsdPtr->cmList = NULL;
+ tsdPtr->lastCmPtr = NULL;
+ tsdPtr->restrictProc = NULL;
+ tsdPtr->restrictArg = NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkXErrorHandler --
+ *
+ * TkXErrorHandler is an error handler, to be installed via
+ * Tk_CreateErrorHandler, that will set a flag if an X error occurred.
+ *
+ * Results:
+ * Always returns 0, indicating that the X error was handled.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TkXErrorHandler(
+ ClientData clientData, /* Pointer to flag we set. */
+ XErrorEvent *errEventPtr) /* X error info. */
+{
+ int *error = clientData;
+
+ *error = 1;
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ParentXId --
+ *
+ * Returns the parent of the given window, or "None" if the window
+ * doesn't exist.
+ *
+ * Results:
+ * Returns an X window ID.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Window
+ParentXId(
+ Display *display,
+ Window w)
+{
+ Tk_ErrorHandler handler;
+ int gotXError;
+ Status status;
+ Window parent;
+ Window root;
+ Window *childList;
+ unsigned int nChildren;
+
+ /*
+ * Handle errors ourselves.
+ */
+
+ gotXError = 0;
+ handler = Tk_CreateErrorHandler(display, -1, -1, -1,
+ TkXErrorHandler, &gotXError);
+
+ /*
+ * Get the parent window.
+ */
+
+ status = XQueryTree(display, w, &root, &parent, &childList, &nChildren);
+
+ /*
+ * Do some cleanup; gotta return "None" if we got an error.
+ */
+
+ Tk_DeleteErrorHandler(handler);
+ XSync(display, False);
+ if (status != 0 && childList != NULL) {
+ XFree(childList);
+ }
+ if (status == 0) {
+ parent = None;
+ }
+
+ return parent;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_HandleEvent --
+ *
+ * Given an event, invoke all the handlers that have been registered for
+ * the event.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Depends on the handlers.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_HandleEvent(
+ XEvent *eventPtr) /* Event to dispatch. */
+{
+ register TkEventHandler *handlerPtr;
+ TkWindow *winPtr;
+ unsigned long mask;
+ InProgress ip;
+ Tcl_Interp *interp = NULL;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ UpdateButtonEventState(eventPtr);
+
+ /*
+ * If the generic handler processed this event we are done and can return.
+ */
+
+ if (InvokeGenericHandlers(tsdPtr, eventPtr)) {
+ goto releaseEventResources;
+ }
+
+ if (RefreshKeyboardMappingIfNeeded(eventPtr)) {
+ /*
+ * We are done with a MappingNotify event.
+ */
+
+ goto releaseEventResources;
+ }
+
+ mask = GetEventMaskFromXEvent(eventPtr);
+ winPtr = GetTkWindowFromXEvent(eventPtr);
+
+ if (winPtr == NULL) {
+ goto releaseEventResources;
+ }
+
+ /*
+ * Once a window has started getting deleted, don't process any more
+ * events for it except for the DestroyNotify event. This check is needed
+ * because a DestroyNotify handler could re-invoke the event loop, causing
+ * other pending events to be handled for the window (the window doesn't
+ * get totally expunged from our tables until after the DestroyNotify
+ * event has been completely handled).
+ */
+
+ if ((winPtr->flags & TK_ALREADY_DEAD)
+ && (eventPtr->type != DestroyNotify)) {
+ goto releaseEventResources;
+ }
+
+ if (winPtr->mainPtr != NULL) {
+ int result;
+
+ interp = winPtr->mainPtr->interp;
+
+ /*
+ * Protect interpreter for this window from possible deletion while we
+ * are dealing with the event for this window. Thus, widget writers do
+ * not have to worry about protecting the interpreter in their own
+ * code.
+ */
+
+ Tcl_Preserve(interp);
+
+ result = ((InvokeFocusHandlers(&winPtr, mask, eventPtr))
+ || (InvokeMouseHandlers(winPtr, mask, eventPtr)));
+
+ if (result) {
+ goto releaseInterpreter;
+ }
+ }
+
+ /*
+ * Create the input context for the window if it hasn't already been done
+ * (XFilterEvent needs this context). When the event is a FocusIn event,
+ * set the input context focus to the receiving window. This code is only
+ * ever active for X11.
+ */
+
+#ifdef TK_USE_INPUT_METHODS
+ /*
+ * If the XIC has been invalidated, it must be recreated.
+ */
+ if (winPtr->dispPtr->ximGeneration != winPtr->ximGeneration) {
+ winPtr->flags &= ~TK_CHECKED_IC;
+ winPtr->inputContext = NULL;
+ }
+
+ if ((winPtr->dispPtr->flags & TK_DISPLAY_USE_IM)) {
+ if (!(winPtr->flags & (TK_CHECKED_IC|TK_ALREADY_DEAD))) {
+ winPtr->flags |= TK_CHECKED_IC;
+ if (winPtr->dispPtr->inputMethod != NULL) {
+ CreateXIC(winPtr);
+ }
+ }
+ if ((eventPtr->type == FocusIn) &&
+ (winPtr->dispPtr->inputMethod != NULL) &&
+ (winPtr->inputContext != NULL)) {
+ XSetICFocus(winPtr->inputContext);
+ }
+ }
+#endif /*TK_USE_INPUT_METHODS*/
+
+ /*
+ * For events where it hasn't already been done, update the current time
+ * in the display.
+ */
+
+ if (eventPtr->type == PropertyNotify) {
+ winPtr->dispPtr->lastEventTime = eventPtr->xproperty.time;
+ }
+
+ /*
+ * There's a potential interaction here with Tk_DeleteEventHandler. Read
+ * the documentation for pendingPtr.
+ */
+
+ ip.eventPtr = eventPtr;
+ ip.winPtr = winPtr;
+ ip.nextHandler = NULL;
+ ip.nextPtr = tsdPtr->pendingPtr;
+ tsdPtr->pendingPtr = &ip;
+ if (mask == 0) {
+ if ((eventPtr->type == SelectionClear)
+ || (eventPtr->type == SelectionRequest)
+ || (eventPtr->type == SelectionNotify)) {
+ TkSelEventProc((Tk_Window) winPtr, eventPtr);
+ } else if (eventPtr->type == ClientMessage) {
+ if (eventPtr->xclient.message_type ==
+ Tk_InternAtom((Tk_Window) winPtr, "WM_PROTOCOLS")) {
+ TkWmProtocolEventProc(winPtr, eventPtr);
+ } else {
+ InvokeClientMessageHandlers(tsdPtr, (Tk_Window) winPtr,
+ eventPtr);
+ }
+ }
+ } else {
+ for (handlerPtr = winPtr->handlerList; handlerPtr != NULL; ) {
+ if (handlerPtr->mask & mask) {
+ ip.nextHandler = handlerPtr->nextPtr;
+ handlerPtr->proc(handlerPtr->clientData, eventPtr);
+ handlerPtr = ip.nextHandler;
+ } else {
+ handlerPtr = handlerPtr->nextPtr;
+ }
+ }
+
+ /*
+ * Pass the event to the "bind" command mechanism. But, don't do this
+ * for SubstructureNotify events. The "bind" command doesn't support
+ * them anyway, and it's easier to filter out these events here than
+ * in the lower-level functions.
+ */
+
+ /*
+ * ...well, except when we use the tkwm patches, in which case we DO
+ * handle CreateNotify events, so we gotta pass 'em through.
+ */
+
+ if ((ip.winPtr != NULL)
+ && ((mask != SubstructureNotifyMask)
+ || (eventPtr->type == CreateNotify))) {
+ TkBindEventProc(winPtr, eventPtr);
+ }
+ }
+ tsdPtr->pendingPtr = ip.nextPtr;
+
+ /*
+ * Release the interpreter for this window so that it can be potentially
+ * deleted if requested.
+ */
+
+ releaseInterpreter:
+ if (interp != NULL) {
+ Tcl_Release(interp);
+ }
+
+ /*
+ * Release the user_data from the event (if it is a virtual event and the
+ * field was non-NULL in the first place.) Note that this is done using a
+ * Tcl_Obj interface, and we set the field back to NULL afterwards out of
+ * paranoia. Also clean up any cached %A substitutions from key events.
+ */
+
+ releaseEventResources:
+ CleanUpTkEvent(eventPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkEventDeadWindow --
+ *
+ * This function is invoked when it is determined that a window is dead.
+ * It cleans up event-related information about the window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Various things get cleaned up and recycled.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkEventDeadWindow(
+ TkWindow *winPtr) /* Information about the window that is being
+ * deleted. */
+{
+ register TkEventHandler *handlerPtr;
+ register InProgress *ipPtr;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ /*
+ * While deleting all the handlers, be careful to check for Tk_HandleEvent
+ * being about to process one of the deleted handlers. If it is, tell it
+ * to quit (all of the handlers are being deleted).
+ */
+
+ while (winPtr->handlerList != NULL) {
+ handlerPtr = winPtr->handlerList;
+ winPtr->handlerList = handlerPtr->nextPtr;
+ for (ipPtr = tsdPtr->pendingPtr; ipPtr != NULL;
+ ipPtr = ipPtr->nextPtr) {
+ if (ipPtr->nextHandler == handlerPtr) {
+ ipPtr->nextHandler = NULL;
+ }
+ if (ipPtr->winPtr == winPtr) {
+ ipPtr->winPtr = NULL;
+ }
+ }
+ ckfree(handlerPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkCurrentTime --
+ *
+ * Try to deduce the current time. "Current time" means the time of the
+ * event that led to the current code being executed, which means the
+ * time in the most recently-nested invocation of Tk_HandleEvent.
+ *
+ * Results:
+ * The return value is the time from the current event, or CurrentTime if
+ * there is no current event or if the current event contains no time.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Time
+TkCurrentTime(
+ TkDisplay *dispPtr) /* Display for which the time is desired. */
+{
+ register XEvent *eventPtr;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (tsdPtr->pendingPtr == NULL) {
+ return dispPtr->lastEventTime;
+ }
+ eventPtr = tsdPtr->pendingPtr->eventPtr;
+ switch (eventPtr->type) {
+ case ButtonPress:
+ case ButtonRelease:
+ return eventPtr->xbutton.time;
+ case KeyPress:
+ case KeyRelease:
+ return eventPtr->xkey.time;
+ case MotionNotify:
+ return eventPtr->xmotion.time;
+ case EnterNotify:
+ case LeaveNotify:
+ return eventPtr->xcrossing.time;
+ case PropertyNotify:
+ return eventPtr->xproperty.time;
+ }
+ return dispPtr->lastEventTime;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_RestrictEvents --
+ *
+ * This function is used to globally restrict the set of events that will
+ * be dispatched. The restriction is done by filtering all incoming X
+ * events through a function that determines whether they are to be
+ * processed immediately, deferred, or discarded.
+ *
+ * Results:
+ * The return value is the previous restriction function in effect, if
+ * there was one, or NULL if there wasn't.
+ *
+ * Side effects:
+ * From now on, proc will be called to determine whether to process,
+ * defer or discard each incoming X event.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_RestrictProc *
+Tk_RestrictEvents(
+ Tk_RestrictProc *proc, /* Function to call for each incoming event */
+ ClientData arg, /* Arbitrary argument to pass to proc. */
+ ClientData *prevArgPtr) /* Place to store information about previous
+ * argument. */
+{
+ Tk_RestrictProc *prev;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ prev = tsdPtr->restrictProc;
+ *prevArgPtr = tsdPtr->restrictArg;
+ tsdPtr->restrictProc = proc;
+ tsdPtr->restrictArg = arg;
+ return prev;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_CollapseMotionEvents --
+ *
+ * This function controls whether we collapse motion events in a
+ * particular display or not.
+ *
+ * Results:
+ * The return value is the previous collapse value in effect.
+ *
+ * Side effects:
+ * Filtering of motion events may be changed after calling this.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_CollapseMotionEvents(
+ Display *display, /* Display handling these events. */
+ int collapse) /* Boolean value that specifies whether motion
+ * events should be collapsed. */
+{
+ TkDisplay *dispPtr = (TkDisplay *) display;
+ int prev = (dispPtr->flags & TK_DISPLAY_COLLAPSE_MOTION_EVENTS);
+
+ if (collapse) {
+ dispPtr->flags |= TK_DISPLAY_COLLAPSE_MOTION_EVENTS;
+ } else {
+ dispPtr->flags &= ~TK_DISPLAY_COLLAPSE_MOTION_EVENTS;
+ }
+ return prev;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_QueueWindowEvent --
+ *
+ * Given an X-style window event, this function adds it to the Tcl event
+ * queue at the given position. This function also performs mouse motion
+ * event collapsing if possible.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Adds stuff to the event queue, which will eventually be processed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_QueueWindowEvent(
+ XEvent *eventPtr, /* Event to add to queue. This function copies
+ * it before adding it to the queue. */
+ Tcl_QueuePosition position) /* Where to put it on the queue:
+ * TCL_QUEUE_TAIL, TCL_QUEUE_HEAD, or
+ * TCL_QUEUE_MARK. */
+{
+ TkWindowEvent *wevPtr;
+ TkDisplay *dispPtr;
+
+ /*
+ * Find our display structure for the event's display.
+ */
+
+ for (dispPtr = TkGetDisplayList(); ; dispPtr = dispPtr->nextPtr) {
+ if (dispPtr == NULL) {
+ return;
+ }
+ if (dispPtr->display == eventPtr->xany.display) {
+ break;
+ }
+ }
+
+ /*
+ * Don't filter motion events if the user defaulting to true (1), which
+ * could be set to false (0) when the user wishes to receive all the
+ * motion data)
+ */
+
+ if (!(dispPtr->flags & TK_DISPLAY_COLLAPSE_MOTION_EVENTS)) {
+ wevPtr = ckalloc(sizeof(TkWindowEvent));
+ wevPtr->header.proc = WindowEventProc;
+ wevPtr->event = *eventPtr;
+ Tcl_QueueEvent(&wevPtr->header, position);
+ return;
+ }
+
+ if ((dispPtr->delayedMotionPtr != NULL) && (position == TCL_QUEUE_TAIL)) {
+ if ((eventPtr->type == MotionNotify) && (eventPtr->xmotion.window
+ == dispPtr->delayedMotionPtr->event.xmotion.window)) {
+ /*
+ * The new event is a motion event in the same window as the saved
+ * motion event. Just replace the saved event with the new one.
+ */
+
+ dispPtr->delayedMotionPtr->event = *eventPtr;
+ return;
+ } else if ((eventPtr->type != GraphicsExpose)
+ && (eventPtr->type != NoExpose)
+ && (eventPtr->type != Expose)) {
+ /*
+ * The new event may conflict with the saved motion event. Queue
+ * the saved motion event now so that it will be processed before
+ * the new event.
+ */
+
+ Tcl_QueueEvent(&dispPtr->delayedMotionPtr->header, position);
+ dispPtr->delayedMotionPtr = NULL;
+ Tcl_CancelIdleCall(DelayedMotionProc, dispPtr);
+ }
+ }
+
+ wevPtr = ckalloc(sizeof(TkWindowEvent));
+ wevPtr->header.proc = WindowEventProc;
+ wevPtr->event = *eventPtr;
+ if ((eventPtr->type == MotionNotify) && (position == TCL_QUEUE_TAIL)) {
+ /*
+ * The new event is a motion event so don't queue it immediately; save
+ * it around in case another motion event arrives that it can be
+ * collapsed with.
+ */
+
+ if (dispPtr->delayedMotionPtr != NULL) {
+ Tcl_Panic("Tk_QueueWindowEvent found unexpected delayed motion event");
+ }
+ dispPtr->delayedMotionPtr = wevPtr;
+ Tcl_DoWhenIdle(DelayedMotionProc, dispPtr);
+ } else {
+ Tcl_QueueEvent(&wevPtr->header, position);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkQueueEventForAllChildren --
+ *
+ * Given an XEvent, recursively queue the event for this window and all
+ * non-toplevel children of the given window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Events queued.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkQueueEventForAllChildren(
+ TkWindow *winPtr, /* Window to which event is sent. */
+ XEvent *eventPtr) /* The event to be sent. */
+{
+ TkWindow *childPtr;
+
+ if (!Tk_IsMapped(winPtr)) {
+ return;
+ }
+
+ eventPtr->xany.window = winPtr->window;
+ Tk_QueueWindowEvent(eventPtr, TCL_QUEUE_TAIL);
+
+ childPtr = winPtr->childList;
+ while (childPtr != NULL) {
+ if (!Tk_TopWinHierarchy(childPtr)) {
+ TkQueueEventForAllChildren(childPtr, eventPtr);
+ }
+ childPtr = childPtr->nextPtr;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WindowEventProc --
+ *
+ * This function is called by Tcl_DoOneEvent when a window event reaches
+ * the front of the event queue. This function is responsible for
+ * actually handling the event.
+ *
+ * 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 event isn't handled if the TCL_WINDOW_EVENTS
+ * bit isn't set in flags, if a restrict proc prevents the event from
+ * being handled.
+ *
+ * Side effects:
+ * Whatever the event handlers for the event do.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WindowEventProc(
+ Tcl_Event *evPtr, /* Event to service. */
+ int flags) /* Flags that indicate what events to handle,
+ * such as TCL_WINDOW_EVENTS. */
+{
+ TkWindowEvent *wevPtr = (TkWindowEvent *) evPtr;
+ Tk_RestrictAction result;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (!(flags & TCL_WINDOW_EVENTS)) {
+ return 0;
+ }
+ if (tsdPtr->restrictProc != NULL) {
+ result = tsdPtr->restrictProc(tsdPtr->restrictArg, &wevPtr->event);
+ if (result != TK_PROCESS_EVENT) {
+ if (result == TK_DEFER_EVENT) {
+ return 0;
+ } else {
+ /*
+ * TK_DELETE_EVENT: return and say we processed the event,
+ * even though we didn't do anything at all.
+ */
+
+ CleanUpTkEvent(&wevPtr->event);
+ return 1;
+ }
+ }
+ }
+ Tk_HandleEvent(&wevPtr->event);
+ CleanUpTkEvent(&wevPtr->event);
+ return 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CleanUpTkEvent --
+ *
+ * This function is called to remove and deallocate any information in
+ * the event which is not directly in the event structure itself. It may
+ * be called multiple times per event, so it takes care to set the
+ * cleared pointer fields to NULL afterwards.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Makes the event no longer have any external resources.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+CleanUpTkEvent(
+ XEvent *eventPtr)
+{
+ switch (eventPtr->type) {
+ case KeyPress:
+ case KeyRelease: {
+ TkKeyEvent *kePtr = (TkKeyEvent *) eventPtr;
+
+ if (kePtr->charValuePtr != NULL) {
+ ckfree(kePtr->charValuePtr);
+ kePtr->charValuePtr = NULL;
+ kePtr->charValueLen = 0;
+ }
+ break;
+ }
+
+ case VirtualEvent: {
+ XVirtualEvent *vePtr = (XVirtualEvent *) eventPtr;
+
+ if (vePtr->user_data != NULL) {
+ Tcl_DecrRefCount(vePtr->user_data);
+ vePtr->user_data = NULL;
+ }
+ break;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DelayedMotionProc --
+ *
+ * This function is invoked as an idle handler when a mouse motion event
+ * has been delayed. It queues the delayed event so that it will finally
+ * be serviced.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The delayed mouse motion event gets added to the Tcl event queue for
+ * servicing.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DelayedMotionProc(
+ ClientData clientData) /* Pointer to display containing a delayed
+ * motion event to be serviced. */
+{
+ TkDisplay *dispPtr = clientData;
+
+ if (dispPtr->delayedMotionPtr == NULL) {
+ Tcl_Panic("DelayedMotionProc found no delayed mouse motion event");
+ }
+ Tcl_QueueEvent(&dispPtr->delayedMotionPtr->header, TCL_QUEUE_TAIL);
+ dispPtr->delayedMotionPtr = NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkCreateExitHandler --
+ *
+ * Same as Tcl_CreateExitHandler, but private to Tk.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects.
+ * Sets a handler with Tcl_CreateExitHandler if this is the first call.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkCreateExitHandler(
+ Tcl_ExitProc *proc, /* Function to invoke. */
+ ClientData clientData) /* Arbitrary value to pass to proc. */
+{
+ ExitHandler *exitPtr;
+
+ exitPtr = ckalloc(sizeof(ExitHandler));
+ exitPtr->proc = proc;
+ exitPtr->clientData = clientData;
+ Tcl_MutexLock(&exitMutex);
+
+ /*
+ * The call to TclInExit() is disabled here. That's a private Tcl routine,
+ * and calling it is causing some trouble with portability of building Tk.
+ * We should avoid private Tcl routines generally.
+ *
+ * In this case, the TclInExit() call is being used only to prevent a
+ * Tcl_CreateExitHandler() call when Tcl finalization is in progress.
+ * That's a situation that shouldn't happen anyway. Recent changes within
+ * Tcl_Finalize now cause a Tcl_Panic() to happen if exit handlers get
+ * added after exit handling is complete. By disabling the guard here,
+ * that panic will serve to help us find the buggy conditions and correct
+ * them.
+ *
+ * We can restore this guard if we find we must (hopefully getting public
+ * access to TclInExit() if we discover extensions really do need this),
+ * but during alpha development, this is a good time to dig in and find
+ * the root causes of finalization bugs.
+ */
+
+ if (firstExitPtr == NULL/* && !TclInExit()*/) {
+ Tcl_CreateExitHandler(TkFinalize, NULL);
+ }
+ exitPtr->nextPtr = firstExitPtr;
+ firstExitPtr = exitPtr;
+ Tcl_MutexUnlock(&exitMutex);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkDeleteExitHandler --
+ *
+ * Same as Tcl_DeleteExitHandler, but private to Tk.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects.
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkDeleteExitHandler(
+ Tcl_ExitProc *proc, /* Function that was previously registered. */
+ ClientData clientData) /* Arbitrary value to pass to proc. */
+{
+ ExitHandler *exitPtr, *prevPtr;
+
+ Tcl_MutexLock(&exitMutex);
+ for (prevPtr = NULL, exitPtr = firstExitPtr; exitPtr != NULL;
+ prevPtr = exitPtr, exitPtr = exitPtr->nextPtr) {
+ if ((exitPtr->proc == proc)
+ && (exitPtr->clientData == clientData)) {
+ if (prevPtr == NULL) {
+ firstExitPtr = exitPtr->nextPtr;
+ } else {
+ prevPtr->nextPtr = exitPtr->nextPtr;
+ }
+ ckfree(exitPtr);
+ break;
+ }
+ }
+ Tcl_MutexUnlock(&exitMutex);
+ return;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkCreateThreadExitHandler --
+ *
+ * Same as Tcl_CreateThreadExitHandler, but private to Tk.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Proc will be invoked with clientData as argument when the application
+ * exits.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkCreateThreadExitHandler(
+ Tcl_ExitProc *proc, /* Function to invoke. */
+ ClientData clientData) /* Arbitrary value to pass to proc. */
+{
+ ExitHandler *exitPtr;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ exitPtr = ckalloc(sizeof(ExitHandler));
+ exitPtr->proc = proc;
+ exitPtr->clientData = clientData;
+
+ /*
+ * See comments in TkCreateExitHandler().
+ */
+
+ if (tsdPtr->firstExitPtr == NULL/* && !TclInExit()*/) {
+ Tcl_CreateThreadExitHandler(TkFinalizeThread, NULL);
+ }
+ exitPtr->nextPtr = tsdPtr->firstExitPtr;
+ tsdPtr->firstExitPtr = exitPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkDeleteThreadExitHandler --
+ *
+ * Same as Tcl_DeleteThreadExitHandler, but private to Tk.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If there is an exit handler corresponding to proc and clientData then
+ * it is cancelled; if no such handler exists then nothing happens.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkDeleteThreadExitHandler(
+ Tcl_ExitProc *proc, /* Function that was previously registered. */
+ ClientData clientData) /* Arbitrary value to pass to proc. */
+{
+ ExitHandler *exitPtr, *prevPtr;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ for (prevPtr = NULL, exitPtr = tsdPtr->firstExitPtr; exitPtr != NULL;
+ prevPtr = exitPtr, exitPtr = exitPtr->nextPtr) {
+ if ((exitPtr->proc == proc)
+ && (exitPtr->clientData == clientData)) {
+ if (prevPtr == NULL) {
+ tsdPtr->firstExitPtr = exitPtr->nextPtr;
+ } else {
+ prevPtr->nextPtr = exitPtr->nextPtr;
+ }
+ ckfree(exitPtr);
+ return;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkFinalize --
+ *
+ * Runs our private exit handlers and removes itself from Tcl. This is
+ * benificial should we want to protect from dangling pointers should the
+ * Tk shared library be unloaded prior to Tcl which can happen on windows
+ * should the process be forcefully exiting from an exception handler.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects.
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkFinalize(
+ ClientData clientData) /* Arbitrary value to pass to proc. */
+{
+ ExitHandler *exitPtr;
+
+#if defined(_WIN32) && !defined(STATIC_BUILD)
+ if (!tclStubsPtr) {
+ return;
+ }
+#endif
+
+ Tcl_DeleteExitHandler(TkFinalize, NULL);
+
+ Tcl_MutexLock(&exitMutex);
+ for (exitPtr = firstExitPtr; exitPtr != NULL; exitPtr = firstExitPtr) {
+ /*
+ * Be careful to remove the handler from the list before invoking its
+ * callback. This protects us against double-freeing if the callback
+ * should call TkDeleteExitHandler on itself.
+ */
+
+ firstExitPtr = exitPtr->nextPtr;
+ Tcl_MutexUnlock(&exitMutex);
+ exitPtr->proc(exitPtr->clientData);
+ ckfree(exitPtr);
+ Tcl_MutexLock(&exitMutex);
+ }
+ firstExitPtr = NULL;
+ Tcl_MutexUnlock(&exitMutex);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkFinalizeThread --
+ *
+ * Runs our private thread exit handlers and removes itself from Tcl.
+ * This is beneficial should we want to protect from dangling pointers
+ * should the Tk shared library be unloaded prior to Tcl which can happen
+ * on Windows should the process be forcefully exiting from an exception
+ * handler.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects.
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkFinalizeThread(
+ ClientData clientData) /* Arbitrary value to pass to proc. */
+{
+ ExitHandler *exitPtr;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ Tcl_DeleteThreadExitHandler(TkFinalizeThread, NULL);
+
+ if (tsdPtr != NULL) {
+ tsdPtr->inExit = 1;
+
+ for (exitPtr = tsdPtr->firstExitPtr; exitPtr != NULL;
+ exitPtr = tsdPtr->firstExitPtr) {
+ /*
+ * Be careful to remove the handler from the list before invoking
+ * its callback. This protects us against double-freeing if the
+ * callback should call TkDeleteThreadExitHandler on itself.
+ */
+
+ tsdPtr->firstExitPtr = exitPtr->nextPtr;
+ exitPtr->proc(exitPtr->clientData);
+ ckfree(exitPtr);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_MainLoop --
+ *
+ * Call Tcl_DoOneEvent over and over again in an infinite loop as long as
+ * there exist any main windows.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Arbitrary; depends on handlers for events.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_MainLoop(void)
+{
+ while (Tk_GetNumMainWindows() > 0) {
+ Tcl_DoOneEvent(0);
+ }
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkFileFilter.c b/tk8.6/generic/tkFileFilter.c
new file mode 100644
index 0000000..8588d70
--- /dev/null
+++ b/tk8.6/generic/tkFileFilter.c
@@ -0,0 +1,473 @@
+/*
+ * tkFileFilter.c --
+ *
+ * Process the -filetypes option for the file dialogs on Windows and the
+ * Mac.
+ *
+ * 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.
+ */
+
+#include "tkInt.h"
+#include "tkFileFilter.h"
+
+static int AddClause(Tcl_Interp *interp, FileFilter *filterPtr,
+ Tcl_Obj *patternsObj, Tcl_Obj *ostypesObj,
+ int isWindows);
+static FileFilter * GetFilter(FileFilterList *flistPtr, const char *name);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkInitFileFilters --
+ *
+ * Initializes a FileFilterList data structure. A FileFilterList must be
+ * initialized EXACTLY ONCE before any calls to TkGetFileFilters() is
+ * made. The usual flow of control is:
+ * TkInitFileFilters(&flist);
+ * TkGetFileFilters(&flist, ...);
+ * TkGetFileFilters(&flist, ...);
+ * ...
+ * TkFreeFileFilters(&flist);
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The fields in flistPtr are initialized.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkInitFileFilters(
+ FileFilterList *flistPtr) /* The structure to be initialized. */
+{
+ flistPtr->filters = NULL;
+ flistPtr->filtersTail = NULL;
+ flistPtr->numFilters = 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkGetFileFilters --
+ *
+ * This function is called by the Mac and Windows implementation of
+ * tk_getOpenFile and tk_getSaveFile to translate the string value of the
+ * -filetypes option into an easy-to-parse C structure (flistPtr). The
+ * caller of this function will then use flistPtr to perform filetype
+ * matching in a platform specific way.
+ *
+ * flistPtr must be initialized (See comments in TkInitFileFilters).
+ *
+ * Results:
+ * A standard TCL return value.
+ *
+ * Side effects:
+ * The fields in flistPtr are changed according to 'types'.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkGetFileFilters(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting. */
+ FileFilterList *flistPtr, /* Stores the list of file filters. */
+ Tcl_Obj *types, /* Value of the -filetypes option. */
+ int isWindows) /* True if we are running on Windows. */
+{
+ int listObjc;
+ Tcl_Obj ** listObjv = NULL;
+ int i;
+
+ if (types == NULL) {
+ return TCL_OK;
+ }
+
+ if (Tcl_ListObjGetElements(interp, types, &listObjc,
+ &listObjv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (listObjc == 0) {
+ return TCL_OK;
+ }
+
+ /*
+ * Free the filter information that have been allocated the previous time;
+ * the -filefilters option may have been used more than once in the
+ * command line.
+ */
+
+ TkFreeFileFilters(flistPtr);
+
+ for (i = 0; i<listObjc; i++) {
+ /*
+ * Each file type should have two or three elements: the first one is
+ * the name of the type and the second is the filter of the type. The
+ * third is the Mac OSType ID, but we don't care about them here.
+ */
+
+ int count;
+ FileFilter *filterPtr;
+ Tcl_Obj **typeInfo;
+
+ if (Tcl_ListObjGetElements(interp, listObjv[i], &count,
+ &typeInfo) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (count != 2 && count != 3) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad file type \"%s\", should be "
+ "\"typeName {extension ?extensions ...?} "
+ "?{macType ?macTypes ...?}?\"",
+ Tcl_GetString(listObjv[i])));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "FILE_TYPE", NULL);
+ return TCL_ERROR;
+ }
+
+ filterPtr = GetFilter(flistPtr, Tcl_GetString(typeInfo[0]));
+
+ if (AddClause(interp, filterPtr, typeInfo[1],
+ (count==2 ? NULL : typeInfo[2]), isWindows) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkFreeFileFilters --
+ *
+ * Frees the malloc'ed file filter information.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The fields allocated by TkGetFileFilters() are freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkFreeFileFilters(
+ FileFilterList *flistPtr) /* List of file filters to free */
+{
+ FileFilter *filterPtr;
+ FileFilterClause *clausePtr;
+ GlobPattern *globPtr;
+ MacFileType *mfPtr;
+ register void *toFree; /* A pointer that we are about to free. */
+
+ for (filterPtr = flistPtr->filters; filterPtr != NULL; ) {
+ for (clausePtr = filterPtr->clauses; clausePtr != NULL; ) {
+ /*
+ * Squelch each of the glob patterns.
+ */
+
+ for (globPtr = clausePtr->patterns; globPtr != NULL; ) {
+ ckfree(globPtr->pattern);
+ toFree = globPtr;
+ globPtr = globPtr->next;
+ ckfree(toFree);
+ }
+
+ /*
+ * Squelch each of the Mac file type codes.
+ */
+
+ for (mfPtr = clausePtr->macTypes; mfPtr != NULL; ) {
+ toFree = mfPtr;
+ mfPtr = mfPtr->next;
+ ckfree(toFree);
+ }
+ toFree = clausePtr;
+ clausePtr = clausePtr->next;
+ ckfree(toFree);
+ }
+
+ /*
+ * Squelch the name of the filter and the overall structure.
+ */
+
+ ckfree(filterPtr->name);
+ toFree = filterPtr;
+ filterPtr = filterPtr->next;
+ ckfree(toFree);
+ }
+ flistPtr->filters = NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AddClause --
+ *
+ * Add one FileFilterClause to filterPtr.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ * Side effects:
+ * The list of filter clauses are updated in filterPtr.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+AddClause(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting. */
+ FileFilter *filterPtr, /* Stores the new filter clause */
+ Tcl_Obj *patternsObj, /* A Tcl list of glob patterns. */
+ Tcl_Obj *ostypesObj, /* A Tcl list of Mac OSType strings. */
+ int isWindows) /* True if we are running on Windows; False if
+ * we are running on the Mac; Glob patterns
+ * need to be processed differently on these
+ * two platforms */
+{
+ Tcl_Obj **globList = NULL, **ostypeList = NULL;
+ int globCount, ostypeCount, i, code = TCL_OK;
+ FileFilterClause *clausePtr;
+ Tcl_Encoding macRoman = NULL;
+
+ if (Tcl_ListObjGetElements(interp, patternsObj,
+ &globCount, &globList) != TCL_OK) {
+ code = TCL_ERROR;
+ goto done;
+ }
+ if (ostypesObj != NULL) {
+ if (Tcl_ListObjGetElements(interp, ostypesObj,
+ &ostypeCount, &ostypeList) != TCL_OK) {
+ code = TCL_ERROR;
+ goto done;
+ }
+
+ /*
+ * We probably need this encoding now...
+ */
+
+ macRoman = Tcl_GetEncoding(NULL, "macRoman");
+
+ /*
+ * Might be cleaner to use 'Tcl_GetOSTypeFromObj' but that is actually
+ * static to the MacOS X/Darwin version of Tcl, and would therefore
+ * require further code refactoring.
+ */
+
+ for (i=0; i<ostypeCount; i++) {
+ int len;
+ const char *strType = Tcl_GetStringFromObj(ostypeList[i], &len);
+
+ /*
+ * If len is < 4, it is definitely an error. If equal or longer,
+ * we need to use the macRoman encoding to determine the correct
+ * length (assuming there may be non-ascii characters, e.g.,
+ * embedded nulls or accented characters in the string, the
+ * macRoman length will be different).
+ *
+ * If we couldn't load the encoding, then we can't actually check
+ * the correct length. But here we assume we're probably operating
+ * on unix/windows with a minimal set of encodings and so don't
+ * care about MacOS types. So we won't signal an error.
+ */
+
+ if (len >= 4 && macRoman != NULL) {
+ Tcl_DString osTypeDS;
+
+ /*
+ * Convert utf to macRoman, since MacOS types are defined to
+ * be 4 macRoman characters long
+ */
+
+ Tcl_UtfToExternalDString(macRoman, strType, len, &osTypeDS);
+ len = Tcl_DStringLength(&osTypeDS);
+ Tcl_DStringFree(&osTypeDS);
+ }
+ if (len != 4) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad Macintosh file type \"%s\"",
+ Tcl_GetString(ostypeList[i])));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "MAC_TYPE", NULL);
+ code = TCL_ERROR;
+ goto done;
+ }
+ }
+ }
+
+ /*
+ * Add the clause into the list of clauses
+ */
+
+ clausePtr = ckalloc(sizeof(FileFilterClause));
+ clausePtr->patterns = NULL;
+ clausePtr->patternsTail = NULL;
+ clausePtr->macTypes = NULL;
+ clausePtr->macTypesTail = NULL;
+
+ if (filterPtr->clauses == NULL) {
+ filterPtr->clauses = filterPtr->clausesTail = clausePtr;
+ } else {
+ filterPtr->clausesTail->next = clausePtr;
+ filterPtr->clausesTail = clausePtr;
+ }
+ clausePtr->next = NULL;
+
+ if (globCount > 0 && globList != NULL) {
+ for (i=0; i<globCount; i++) {
+ GlobPattern *globPtr = ckalloc(sizeof(GlobPattern));
+ int len;
+ const char *str = Tcl_GetStringFromObj(globList[i], &len);
+
+ len = (len + 1) * sizeof(char);
+ if (str[0] && str[0] != '*') {
+ /*
+ * Prepend a "*" to patterns that do not have a leading "*"
+ */
+
+ globPtr->pattern = ckalloc(len + 1);
+ globPtr->pattern[0] = '*';
+ strcpy(globPtr->pattern+1, str);
+ } else if (isWindows) {
+ if (strcmp(str, "*") == 0) {
+ globPtr->pattern = ckalloc(4);
+ strcpy(globPtr->pattern, "*.*");
+ } else if (strcmp(str, "") == 0) {
+ /*
+ * An empty string means "match all files with no
+ * extensions"
+ * TODO: "*." actually matches with all files on Win95
+ */
+
+ globPtr->pattern = ckalloc(3);
+ strcpy(globPtr->pattern, "*.");
+ } else {
+ globPtr->pattern = ckalloc(len);
+ strcpy(globPtr->pattern, str);
+ }
+ } else {
+ globPtr->pattern = ckalloc(len);
+ strcpy(globPtr->pattern, str);
+ }
+
+ /*
+ * Add the glob pattern into the list of patterns.
+ */
+
+ if (clausePtr->patterns == NULL) {
+ clausePtr->patterns = clausePtr->patternsTail = globPtr;
+ } else {
+ clausePtr->patternsTail->next = globPtr;
+ clausePtr->patternsTail = globPtr;
+ }
+ globPtr->next = NULL;
+ }
+ }
+ if (ostypeList != NULL && ostypeCount > 0) {
+ if (macRoman == NULL) {
+ macRoman = Tcl_GetEncoding(NULL, "macRoman");
+ }
+ for (i=0; i<ostypeCount; i++) {
+ Tcl_DString osTypeDS;
+ int len;
+ MacFileType *mfPtr = ckalloc(sizeof(MacFileType));
+ const char *strType = Tcl_GetStringFromObj(ostypeList[i], &len);
+ char *string;
+
+ /*
+ * Convert utf to macRoman, since MacOS types are defined to be 4
+ * macRoman characters long
+ */
+
+ Tcl_UtfToExternalDString(macRoman, strType, len, &osTypeDS);
+ string = Tcl_DStringValue(&osTypeDS);
+ mfPtr->type = (OSType) string[0] << 24 | (OSType) string[1] << 16 |
+ (OSType) string[2] << 8 | (OSType) string[3];
+ Tcl_DStringFree(&osTypeDS);
+
+ /*
+ * Add the Mac type pattern into the list of Mac types
+ */
+
+ if (clausePtr->macTypes == NULL) {
+ clausePtr->macTypes = clausePtr->macTypesTail = mfPtr;
+ } else {
+ clausePtr->macTypesTail->next = mfPtr;
+ clausePtr->macTypesTail = mfPtr;
+ }
+ mfPtr->next = NULL;
+ }
+ }
+
+ done:
+ if (macRoman != NULL) {
+ Tcl_FreeEncoding(macRoman);
+ }
+ return code;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetFilter --
+ *
+ * Add one FileFilter to flistPtr.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ * Side effects:
+ * The list of filters are updated in flistPtr.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static FileFilter *
+GetFilter(
+ FileFilterList *flistPtr, /* The FileFilterList that contains the newly
+ * created filter */
+ const char *name) /* Name of the filter. It is usually displayed
+ * in the "File Types" listbox in the file
+ * dialogs. */
+{
+ FileFilter *filterPtr = flistPtr->filters;
+ size_t len;
+
+ for (; filterPtr; filterPtr=filterPtr->next) {
+ if (strcmp(filterPtr->name, name) == 0) {
+ return filterPtr;
+ }
+ }
+
+ filterPtr = ckalloc(sizeof(FileFilter));
+ filterPtr->clauses = NULL;
+ filterPtr->clausesTail = NULL;
+ len = strlen(name) + 1;
+ filterPtr->name = ckalloc(len);
+ memcpy(filterPtr->name, name, len);
+
+ if (flistPtr->filters == NULL) {
+ flistPtr->filters = flistPtr->filtersTail = filterPtr;
+ } else {
+ flistPtr->filtersTail->next = filterPtr;
+ flistPtr->filtersTail = filterPtr;
+ }
+ filterPtr->next = NULL;
+
+ ++flistPtr->numFilters;
+ return filterPtr;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkFileFilter.h b/tk8.6/generic/tkFileFilter.h
new file mode 100644
index 0000000..131e423
--- /dev/null
+++ b/tk8.6/generic/tkFileFilter.h
@@ -0,0 +1,78 @@
+/*
+ * tkFileFilter.h --
+ *
+ * Declarations for the file filter processing routines needed by the
+ * file selection dialogs.
+ *
+ * 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.
+ */
+
+#ifndef _TK_FILE_FILTER
+#define _TK_FILE_FILTER
+
+#define OSType long
+
+typedef struct GlobPattern {
+ struct GlobPattern *next; /* Chains to the next glob pattern in a glob
+ * pattern list */
+ char *pattern; /* String value of the pattern, such as
+ * "*.txt" or "*.*" */
+} GlobPattern;
+
+typedef struct MacFileType {
+ struct MacFileType *next; /* Chains to the next mac file type in a mac
+ * file type list */
+ OSType type; /* Mac file type, such as 'TEXT' or 'GIFF' */
+} MacFileType;
+
+typedef struct FileFilterClause {
+ struct FileFilterClause *next;
+ /* Chains to the next clause in a clause
+ * list */
+ GlobPattern *patterns; /* Head of glob pattern type list */
+ GlobPattern *patternsTail; /* Tail of glob pattern type list */
+ MacFileType *macTypes; /* Head of mac file type list */
+ MacFileType *macTypesTail; /* Tail of mac file type list */
+} FileFilterClause;
+
+typedef struct FileFilter {
+ struct FileFilter *next; /* Chains to the next filter in a filter
+ * list */
+ char *name; /* Name of the file filter, such as "Text
+ * Documents" */
+ FileFilterClause *clauses; /* Head of the clauses list */
+ FileFilterClause *clausesTail;
+ /* Tail of the clauses list */
+} FileFilter;
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileFilterList --
+ *
+ * The routine TkGetFileFilters() translates the string value of the
+ * -filefilters option into a FileFilterList structure, which consists of
+ * a list of file filters.
+ *
+ * Each file filter consists of one or more clauses. Each clause has one
+ * or more glob patterns and/or one or more Mac file types
+ *
+ *----------------------------------------------------------------------
+ */
+
+typedef struct FileFilterList {
+ FileFilter *filters; /* Head of the filter list */
+ FileFilter *filtersTail; /* Tail of the filter list */
+ int numFilters; /* number of filters in the list */
+} FileFilterList;
+
+MODULE_SCOPE void TkFreeFileFilters(FileFilterList *flistPtr);
+MODULE_SCOPE void TkInitFileFilters(FileFilterList *flistPtr);
+MODULE_SCOPE int TkGetFileFilters(Tcl_Interp *interp,
+ FileFilterList *flistPtr, Tcl_Obj *valuePtr,
+ int isWindows);
+
+#endif /* _TK_FILE_FILTER */
diff --git a/tk8.6/generic/tkFocus.c b/tk8.6/generic/tkFocus.c
new file mode 100644
index 0000000..eae981e
--- /dev/null
+++ b/tk8.6/generic/tkFocus.c
@@ -0,0 +1,1215 @@
+/*
+ * tkFocus.c --
+ *
+ * This file contains functions that manage the input focus for Tk.
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "tkInt.h"
+
+/*
+ * For each top-level window that has ever received the focus, there is a
+ * record of the following type:
+ */
+
+typedef struct TkToplevelFocusInfo {
+ TkWindow *topLevelPtr; /* Information about top-level window. */
+ TkWindow *focusWinPtr; /* The next time the focus comes to this
+ * top-level, it will be given to this
+ * window. */
+ struct TkToplevelFocusInfo *nextPtr;
+ /* Next in list of all toplevel focus records
+ * for a given application. */
+} ToplevelFocusInfo;
+
+/*
+ * One of the following structures exists for each display used by each
+ * application. These are linked together from the TkMainInfo structure.
+ * These structures are needed because it isn't sufficient to store a single
+ * piece of focus information in each display or in each application: we need
+ * the cross-product. There needs to be separate information for each display,
+ * because it's possible to have multiple focus windows active simultaneously
+ * on different displays. There also needs to be separate information for each
+ * application, because of embedding: if an embedded application has the
+ * focus, its container application also has the focus. Thus we keep a list of
+ * structures for each application: the same display can appear in structures
+ * for several applications at once.
+ */
+
+typedef struct TkDisplayFocusInfo {
+ TkDisplay *dispPtr; /* Display that this information pertains
+ * to. */
+ struct TkWindow *focusWinPtr;
+ /* Window that currently has the focus for
+ * this application on this display, or NULL
+ * if none. */
+ struct TkWindow *focusOnMapPtr;
+ /* This points to a toplevel window that is
+ * supposed to receive the X input focus as
+ * soon as it is mapped (needed to handle the
+ * fact that X won't allow the focus on an
+ * unmapped window). NULL means no delayed
+ * focus op in progress for this display. */
+ int forceFocus; /* Associated with focusOnMapPtr: non-zero
+ * means claim the focus even if some other
+ * application currently has it. */
+ unsigned long focusSerial; /* Serial number of last request this
+ * application made to change the focus on
+ * this display. Used to identify stale focus
+ * notifications coming from the X server. */
+ struct TkDisplayFocusInfo *nextPtr;
+ /* Next in list of all display focus records
+ * for a given application. */
+} DisplayFocusInfo;
+
+/*
+ * Debugging support...
+ */
+
+#define DEBUG(dispPtr, arguments) \
+ if ((dispPtr)->focusDebug) { \
+ printf arguments; \
+ }
+
+/*
+ * Forward declarations for functions defined in this file:
+ */
+
+static DisplayFocusInfo*FindDisplayFocusInfo(TkMainInfo *mainPtr,
+ TkDisplay *dispPtr);
+static void FocusMapProc(ClientData clientData, XEvent *eventPtr);
+static void GenerateFocusEvents(TkWindow *sourcePtr,
+ TkWindow *destPtr);
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_FocusObjCmd --
+ *
+ * This function is invoked to process the "focus" 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_FocusObjCmd(
+ ClientData clientData, /* Main window associated with interpreter. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ static const char *const focusOptions[] = {
+ "-displayof", "-force", "-lastfor", NULL
+ };
+ Tk_Window tkwin = clientData;
+ TkWindow *winPtr = clientData;
+ TkWindow *newPtr, *topLevelPtr;
+ ToplevelFocusInfo *tlFocusPtr;
+ const char *windowName;
+ int index;
+
+ /*
+ * If invoked with no arguments, just return the current focus window.
+ */
+
+ if (objc == 1) {
+ Tk_Window focusWin = (Tk_Window) TkGetFocusWin(winPtr);
+
+ if (focusWin != NULL) {
+ Tcl_SetObjResult(interp, TkNewWindowObj(focusWin));
+ }
+ return TCL_OK;
+ }
+
+ /*
+ * If invoked with a single argument beginning with "." then focus on that
+ * window.
+ */
+
+ if (objc == 2) {
+ windowName = Tcl_GetString(objv[1]);
+
+ /*
+ * The empty string case exists for backwards compatibility.
+ */
+
+ if (windowName[0] == '\0') {
+ return TCL_OK;
+ }
+ if (windowName[0] == '.') {
+ newPtr = (TkWindow *) Tk_NameToWindow(interp, windowName, tkwin);
+ if (newPtr == NULL) {
+ return TCL_ERROR;
+ }
+ TkSetFocusWin(newPtr, 0);
+ return TCL_OK;
+ }
+ }
+
+ /*
+ * We have a subcommand to parse and act upon.
+ */
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[1], focusOptions,
+ sizeof(char *), "option", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window");
+ return TCL_ERROR;
+ }
+ switch (index) {
+ case 0: /* -displayof */
+ windowName = Tcl_GetString(objv[2]);
+ newPtr = (TkWindow *) Tk_NameToWindow(interp, windowName, tkwin);
+ if (newPtr == NULL) {
+ return TCL_ERROR;
+ }
+ newPtr = TkGetFocusWin(newPtr);
+ if (newPtr != NULL) {
+ Tcl_SetObjResult(interp, TkNewWindowObj((Tk_Window) newPtr));
+ }
+ break;
+ case 1: /* -force */
+ windowName = Tcl_GetString(objv[2]);
+
+ /*
+ * The empty string case exists for backwards compatibility.
+ */
+
+ if (windowName[0] == '\0') {
+ return TCL_OK;
+ }
+ newPtr = (TkWindow *) Tk_NameToWindow(interp, windowName, tkwin);
+ if (newPtr == NULL) {
+ return TCL_ERROR;
+ }
+ TkSetFocusWin(newPtr, 1);
+ break;
+ case 2: /* -lastfor */
+ windowName = Tcl_GetString(objv[2]);
+ newPtr = (TkWindow *) Tk_NameToWindow(interp, windowName, tkwin);
+ if (newPtr == NULL) {
+ return TCL_ERROR;
+ }
+ for (topLevelPtr = newPtr; topLevelPtr != NULL;
+ topLevelPtr = topLevelPtr->parentPtr) {
+ if (!(topLevelPtr->flags & TK_TOP_HIERARCHY)) {
+ continue;
+ }
+ for (tlFocusPtr = newPtr->mainPtr->tlFocusPtr; tlFocusPtr != NULL;
+ tlFocusPtr = tlFocusPtr->nextPtr) {
+ if (tlFocusPtr->topLevelPtr == topLevelPtr) {
+ Tcl_SetObjResult(interp, TkNewWindowObj((Tk_Window)
+ tlFocusPtr->focusWinPtr));
+ return TCL_OK;
+ }
+ }
+ Tcl_SetObjResult(interp, TkNewWindowObj((Tk_Window) topLevelPtr));
+ return TCL_OK;
+ }
+ break;
+ default:
+ Tcl_Panic("bad const entries to focusOptions in focus command");
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkFocusFilterEvent --
+ *
+ * This function is invoked by Tk_HandleEvent when it encounters a
+ * FocusIn, FocusOut, Enter, or Leave event.
+ *
+ * Results:
+ * A return value of 1 means that Tk_HandleEvent should process the event
+ * normally (i.e. event handlers should be invoked). A return value of 0
+ * means that this event should be ignored.
+ *
+ * Side effects:
+ * Additional events may be generated, and the focus may switch.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkFocusFilterEvent(
+ TkWindow *winPtr, /* Window that focus event is directed to. */
+ XEvent *eventPtr) /* FocusIn, FocusOut, Enter, or Leave
+ * event. */
+{
+ /*
+ * Design notes: the window manager and X server work together to transfer
+ * the focus among top-level windows. This function takes care of
+ * transferring the focus from a top-level or wrapper window to the actual
+ * window within that top-level that has the focus. We do this by
+ * synthesizing X events to move the focus around. None of the FocusIn and
+ * FocusOut events generated by X are ever used outside of this function;
+ * only the synthesized events get through to the rest of the application.
+ * At one point (e.g. Tk4.0b1) Tk used to call X to move the focus from a
+ * top-level to one of its descendants, then just pass through the events
+ * generated by X. This approach didn't work very well, for a variety of
+ * reasons. For example, if X generates the events they go at the back of
+ * the event queue, which could cause problems if other things have
+ * already happened, such as moving the focus to yet another window.
+ */
+
+ ToplevelFocusInfo *tlFocusPtr;
+ DisplayFocusInfo *displayFocusPtr;
+ TkDisplay *dispPtr = winPtr->dispPtr;
+ TkWindow *newFocusPtr;
+ int retValue, delta;
+
+ /*
+ * If this was a generated event, just turn off the generated flag and
+ * pass the event through to Tk bindings.
+ */
+
+ if (eventPtr->xfocus.send_event == GENERATED_FOCUS_EVENT_MAGIC) {
+ eventPtr->xfocus.send_event = 0;
+ return 1;
+ }
+
+ /*
+ * Check for special events generated by embedded applications to request
+ * the input focus. If this is one of those events, make the change in
+ * focus and return without any additional processing of the event (note:
+ * the "detail" field of the event indicates whether to claim the focus
+ * even if we don't already have it).
+ */
+
+ if ((eventPtr->xfocus.mode == EMBEDDED_APP_WANTS_FOCUS)
+ && (eventPtr->type == FocusIn)) {
+ TkSetFocusWin(winPtr, eventPtr->xfocus.detail);
+ return 0;
+ }
+
+ /*
+ * This was not a generated event. We'll return 1 (so that the event will
+ * be processed) if it's an Enter or Leave event, and 0 (so that the event
+ * won't be processed) if it's a FocusIn or FocusOut event.
+ */
+
+ retValue = 0;
+ displayFocusPtr = FindDisplayFocusInfo(winPtr->mainPtr, winPtr->dispPtr);
+ if (eventPtr->type == FocusIn) {
+ /*
+ * Skip FocusIn events that cause confusion
+ * NotifyVirtual and NotifyNonlinearVirtual - Virtual events occur on
+ * windows in between the origin and destination of the focus
+ * change. For FocusIn we may see this when focus goes into an
+ * embedded child. We don't care about this, although we may end
+ * up getting a NotifyPointer later.
+ * NotifyInferior - focus is coming to us from an embedded child. When
+ * focus is on an embeded focus, we still think we have the
+ * focus, too, so this message doesn't change our state.
+ * NotifyPointerRoot - should never happen because this is sent to the
+ * root window.
+ *
+ * Interesting FocusIn events are
+ * NotifyAncestor - focus is coming from our parent, probably the root.
+ * NotifyNonlinear - focus is coming from a different branch, probably
+ * another toplevel.
+ * NotifyPointer - implicit focus because of the mouse position. This
+ * is only interesting on toplevels, when it means that the focus
+ * has been set to the root window but the mouse is over this
+ * toplevel. We take the focus implicitly (probably no window
+ * manager)
+ */
+
+ if ((eventPtr->xfocus.detail == NotifyVirtual)
+ || (eventPtr->xfocus.detail == NotifyNonlinearVirtual)
+ || (eventPtr->xfocus.detail == NotifyPointerRoot)
+ || (eventPtr->xfocus.detail == NotifyInferior)) {
+ return retValue;
+ }
+ } else if (eventPtr->type == FocusOut) {
+ /*
+ * Skip FocusOut events that cause confusion.
+ * NotifyPointer - the pointer is in us or a child, and we are losing
+ * focus because of an XSetInputFocus. Other focus events will
+ * set our state properly.
+ * NotifyPointerRoot - should never happen because this is sent to the
+ * root window.
+ * NotifyInferior - focus leaving us for an embedded child. We retain
+ * a notion of focus when an embedded child has focus.
+ *
+ * Interesting events are:
+ * NotifyAncestor - focus is going to root.
+ * NotifyNonlinear - focus is going to another branch, probably
+ * another toplevel.
+ * NotifyVirtual, NotifyNonlinearVirtual - focus is passing through,
+ * and we need to make sure we track this.
+ */
+
+ if ((eventPtr->xfocus.detail == NotifyPointer)
+ || (eventPtr->xfocus.detail == NotifyPointerRoot)
+ || (eventPtr->xfocus.detail == NotifyInferior)) {
+ return retValue;
+ }
+ } else {
+ retValue = 1;
+ if (eventPtr->xcrossing.detail == NotifyInferior) {
+ return retValue;
+ }
+ }
+
+ /*
+ * If winPtr isn't a top-level window than just ignore the event.
+ */
+
+ winPtr = TkWmFocusToplevel(winPtr);
+ if (winPtr == NULL) {
+ return retValue;
+ }
+
+ /*
+ * If there is a grab in effect and this window is outside the grabbed
+ * tree, then ignore the event.
+ */
+
+ if (TkGrabState(winPtr) == TK_GRAB_EXCLUDED) {
+ return retValue;
+ }
+
+ /*
+ * It is possible that there were outstanding FocusIn and FocusOut events
+ * on their way to us at the time the focus was changed internally with
+ * the "focus" command. If so, these events could potentially cause us to
+ * lose the focus (switch it to the window of the last FocusIn event) even
+ * though the focus change occurred after those events. The following code
+ * detects this and ignores the stale events.
+ *
+ * Note: the focusSerial is only generated by TkpChangeFocus, whereas in
+ * Tk 4.2 there was always a nop marker generated.
+ */
+
+ delta = eventPtr->xfocus.serial - displayFocusPtr->focusSerial;
+ if (delta < 0) {
+ return retValue;
+ }
+
+ /*
+ * Find the ToplevelFocusInfo structure for the window, and make a new one
+ * if there isn't one already.
+ */
+
+ for (tlFocusPtr = winPtr->mainPtr->tlFocusPtr; tlFocusPtr != NULL;
+ tlFocusPtr = tlFocusPtr->nextPtr) {
+ if (tlFocusPtr->topLevelPtr == winPtr) {
+ break;
+ }
+ }
+ if (tlFocusPtr == NULL) {
+ tlFocusPtr = ckalloc(sizeof(ToplevelFocusInfo));
+ tlFocusPtr->topLevelPtr = tlFocusPtr->focusWinPtr = winPtr;
+ tlFocusPtr->nextPtr = winPtr->mainPtr->tlFocusPtr;
+ winPtr->mainPtr->tlFocusPtr = tlFocusPtr;
+ }
+ newFocusPtr = tlFocusPtr->focusWinPtr;
+
+ /*
+ * Ignore event if newFocus window is already dead!
+ */
+
+ if (newFocusPtr->flags & TK_ALREADY_DEAD) {
+ return retValue;
+ }
+
+ if (eventPtr->type == FocusIn) {
+ GenerateFocusEvents(displayFocusPtr->focusWinPtr, newFocusPtr);
+ displayFocusPtr->focusWinPtr = newFocusPtr;
+ dispPtr->focusPtr = newFocusPtr;
+
+ /*
+ * NotifyPointer gets set when the focus has been set to the root
+ * window but we have the pointer. We'll treat this like an implicit
+ * focus in event so that upon Leave events we release focus.
+ */
+
+ if (!(winPtr->flags & TK_EMBEDDED)) {
+ if (eventPtr->xfocus.detail == NotifyPointer) {
+ dispPtr->implicitWinPtr = winPtr;
+ } else {
+ dispPtr->implicitWinPtr = NULL;
+ }
+ }
+ } else if (eventPtr->type == FocusOut) {
+ GenerateFocusEvents(displayFocusPtr->focusWinPtr, NULL);
+
+ /*
+ * Reset dispPtr->focusPtr, but only if it currently is the same as
+ * this application's focusWinPtr: this check is needed to handle
+ * embedded applications in the same process.
+ */
+
+ if (dispPtr->focusPtr == displayFocusPtr->focusWinPtr) {
+ dispPtr->focusPtr = NULL;
+ }
+ displayFocusPtr->focusWinPtr = NULL;
+ } else if (eventPtr->type == EnterNotify) {
+ /*
+ * If there is no window manager, or if the window manager isn't
+ * moving the focus around (e.g. the disgusting "NoTitleFocus" option
+ * has been selected in twm), then we won't get FocusIn or FocusOut
+ * events. Instead, the "focus" field will be set in an Enter event to
+ * indicate that we've already got the focus when the mouse enters the
+ * window (even though we didn't get a FocusIn event). Watch for this
+ * and grab the focus when it happens. Note: if this is an embedded
+ * application then don't accept the focus implicitly like this; the
+ * container application will give us the focus explicitly if it wants
+ * us to have it.
+ */
+
+ if (eventPtr->xcrossing.focus &&
+ (displayFocusPtr->focusWinPtr == NULL)
+ && !(winPtr->flags & TK_EMBEDDED)) {
+ DEBUG(dispPtr,
+ ("Focussed implicitly on %s\n", newFocusPtr->pathName));
+
+ GenerateFocusEvents(displayFocusPtr->focusWinPtr, newFocusPtr);
+ displayFocusPtr->focusWinPtr = newFocusPtr;
+ dispPtr->implicitWinPtr = winPtr;
+ dispPtr->focusPtr = newFocusPtr;
+ }
+ } else if (eventPtr->type == LeaveNotify) {
+ /*
+ * If the pointer just left a window for which we automatically
+ * claimed the focus on enter, move the focus back to the root window,
+ * where it was before we claimed it above. Note:
+ * dispPtr->implicitWinPtr may not be the same as
+ * displayFocusPtr->focusWinPtr (e.g. because the "focus" command was
+ * used to redirect the focus after it arrived at
+ * dispPtr->implicitWinPtr)!! In addition, we generate events because
+ * the window manager won't give us a FocusOut event when we focus on
+ * the root.
+ */
+
+ if ((dispPtr->implicitWinPtr != NULL)
+ && !(winPtr->flags & TK_EMBEDDED)) {
+ DEBUG(dispPtr, ("Defocussed implicit Async\n"));
+ GenerateFocusEvents(displayFocusPtr->focusWinPtr, NULL);
+ XSetInputFocus(dispPtr->display, PointerRoot, RevertToPointerRoot,
+ CurrentTime);
+ displayFocusPtr->focusWinPtr = NULL;
+ dispPtr->implicitWinPtr = NULL;
+ }
+ }
+ return retValue;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkSetFocusWin --
+ *
+ * This function is invoked to change the focus window for a given
+ * display in a given application.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Event handlers may be invoked to process the change of
+ * focus.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkSetFocusWin(
+ TkWindow *winPtr, /* Window that is to be the new focus for its
+ * display and application. */
+ int force) /* If non-zero, set the X focus to this window
+ * even if the application doesn't currently
+ * have the X focus. */
+{
+ ToplevelFocusInfo *tlFocusPtr;
+ DisplayFocusInfo *displayFocusPtr;
+ TkWindow *topLevelPtr;
+ int allMapped, serial;
+
+ /*
+ * Don't set focus if window is already dead. [Bug 3574708]
+ */
+
+ if (winPtr->flags & TK_ALREADY_DEAD) {
+ return;
+ }
+
+ /*
+ * Get the current focus window with the same display and application
+ * as winPtr.
+ */
+
+ displayFocusPtr = FindDisplayFocusInfo(winPtr->mainPtr, winPtr->dispPtr);
+
+ /*
+ * Do nothing if the window already has focus and force is not set. If
+ * force is set, we need to grab the focus, since under Windows or macOS
+ * this may involve taking control away from another application.
+ */
+
+ if (winPtr == displayFocusPtr->focusWinPtr && !force) {
+ return;
+ }
+
+ /*
+ * Find the toplevel window for winPtr, then find (or create) a record
+ * for the toplevel. Also see whether winPtr and all its ancestors are
+ * mapped.
+ */
+
+ allMapped = 1;
+ for (topLevelPtr = winPtr; ; topLevelPtr = topLevelPtr->parentPtr) {
+ if (topLevelPtr == NULL) {
+
+ /*
+ * The window is being deleted. No point in worrying about giving
+ * it the focus.
+ */
+
+ return;
+ }
+ if (!(topLevelPtr->flags & TK_MAPPED)) {
+ allMapped = 0;
+ }
+ if (topLevelPtr->flags & TK_TOP_HIERARCHY) {
+ break;
+ }
+ }
+
+ /*
+ * If any ancestor of the new focus window isn't mapped, then we can't set
+ * focus for it (X will generate an error, for example). Instead, create
+ * an event handler that will set the focus to this window once it gets
+ * mapped. At the same time, delete any old handler that might be around;
+ * it's no longer relevant.
+ */
+
+ if (displayFocusPtr->focusOnMapPtr != NULL) {
+ Tk_DeleteEventHandler((Tk_Window) displayFocusPtr->focusOnMapPtr,
+ StructureNotifyMask, FocusMapProc,
+ displayFocusPtr->focusOnMapPtr);
+ displayFocusPtr->focusOnMapPtr = NULL;
+ }
+ if (!allMapped) {
+ Tk_CreateEventHandler((Tk_Window) winPtr, VisibilityChangeMask,
+ FocusMapProc, winPtr);
+ displayFocusPtr->focusOnMapPtr = winPtr;
+ displayFocusPtr->forceFocus = force;
+ return;
+ }
+
+ for (tlFocusPtr = winPtr->mainPtr->tlFocusPtr; tlFocusPtr != NULL;
+ tlFocusPtr = tlFocusPtr->nextPtr) {
+ if (tlFocusPtr->topLevelPtr == topLevelPtr) {
+ break;
+ }
+ }
+ if (tlFocusPtr == NULL) {
+ tlFocusPtr = ckalloc(sizeof(ToplevelFocusInfo));
+ tlFocusPtr->topLevelPtr = topLevelPtr;
+ tlFocusPtr->nextPtr = winPtr->mainPtr->tlFocusPtr;
+ winPtr->mainPtr->tlFocusPtr = tlFocusPtr;
+ }
+ tlFocusPtr->focusWinPtr = winPtr;
+
+ if (topLevelPtr->flags & TK_EMBEDDED) {
+
+ /*
+ * We are assigning focus to an embedded toplevel. The platform
+ * specific function TkpClaimFocus needs to handle the job of
+ * assigning focus to the container, since we have no way to find the
+ * contaiuner.
+ */
+
+ TkpClaimFocus(topLevelPtr, force);
+ } else if ((displayFocusPtr->focusWinPtr != NULL) || force) {
+
+ /*
+ * If we are forcing removal of focus from a container hosting a
+ * toplevel from a different application, clear the focus in that
+ * application.
+ */
+
+ if (force) {
+ TkWindow *focusPtr = winPtr->dispPtr->focusPtr;
+ if (focusPtr && focusPtr->mainPtr != winPtr->mainPtr) {
+ DisplayFocusInfo *displayFocusPtr2 = FindDisplayFocusInfo(
+ focusPtr->mainPtr, focusPtr->dispPtr);
+ displayFocusPtr2->focusWinPtr = NULL;
+ }
+ }
+
+ /*
+ * Call the platform specific function TkpChangeFocus to move the
+ * window manager's focus to a new toplevel.
+ */
+
+ serial = TkpChangeFocus(TkpGetWrapperWindow(topLevelPtr), force);
+ if (serial != 0) {
+ displayFocusPtr->focusSerial = serial;
+ }
+ GenerateFocusEvents(displayFocusPtr->focusWinPtr, winPtr);
+ displayFocusPtr->focusWinPtr = winPtr;
+ winPtr->dispPtr->focusPtr = winPtr;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkGetFocusWin --
+ *
+ * Given a window, this function returns the current focus window for its
+ * application and display.
+ *
+ * Results:
+ * The return value is a pointer to the window that currently has the
+ * input focus for the specified application and display, or NULL if
+ * none.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkWindow *
+TkGetFocusWin(
+ TkWindow *winPtr) /* Window that selects an application and a
+ * display. */
+{
+ DisplayFocusInfo *displayFocusPtr;
+
+ if (winPtr == NULL) {
+ return NULL;
+ }
+
+ displayFocusPtr = FindDisplayFocusInfo(winPtr->mainPtr, winPtr->dispPtr);
+ return displayFocusPtr->focusWinPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkFocusKeyEvent --
+ *
+ * Given a window and a key press or release event that arrived for the
+ * window, use information about the keyboard focus to compute which
+ * window should really get the event. In addition, update the event to
+ * refer to its new window.
+ *
+ * Results:
+ * The return value is a pointer to the window that has the input focus
+ * in winPtr's application, or NULL if winPtr's application doesn't have
+ * the input focus. If a non-NULL value is returned, eventPtr will be
+ * updated to refer properly to the focus window.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkWindow *
+TkFocusKeyEvent(
+ TkWindow *winPtr, /* Window that selects an application and a
+ * display. */
+ XEvent *eventPtr) /* X event to redirect (should be KeyPress or
+ * KeyRelease). */
+{
+ DisplayFocusInfo *displayFocusPtr;
+ TkWindow *focusWinPtr;
+ int focusX, focusY;
+
+ displayFocusPtr = FindDisplayFocusInfo(winPtr->mainPtr, winPtr->dispPtr);
+ focusWinPtr = displayFocusPtr->focusWinPtr;
+
+ /*
+ * The code below is a debugging aid to make sure that dispPtr->focusPtr
+ * is kept properly in sync with the "truth", which is the value in
+ * displayFocusPtr->focusWinPtr.
+ */
+
+#ifdef TCL_MEM_DEBUG
+ if (focusWinPtr != winPtr->dispPtr->focusPtr) {
+ printf("TkFocusKeyEvent found dispPtr->focusPtr out of sync:\n");
+ printf("expected %s, got %s\n",
+ (focusWinPtr != NULL) ? focusWinPtr->pathName : "??",
+ (winPtr->dispPtr->focusPtr != NULL) ?
+ winPtr->dispPtr->focusPtr->pathName : "??");
+ }
+#endif
+
+ if ((focusWinPtr != NULL) && (focusWinPtr->mainPtr == winPtr->mainPtr)) {
+ /*
+ * Map the x and y coordinates to make sense in the context of the
+ * focus window, if possible (make both -1 if the map-from and map-to
+ * windows don't share the same screen).
+ */
+
+ if ((focusWinPtr->display != winPtr->display)
+ || (focusWinPtr->screenNum != winPtr->screenNum)) {
+ eventPtr->xkey.x = -1;
+ eventPtr->xkey.y = -1;
+ } else {
+ Tk_GetRootCoords((Tk_Window) focusWinPtr, &focusX, &focusY);
+ eventPtr->xkey.x = eventPtr->xkey.x_root - focusX;
+ eventPtr->xkey.y = eventPtr->xkey.y_root - focusY;
+ }
+ eventPtr->xkey.window = focusWinPtr->window;
+ return focusWinPtr;
+ }
+
+ /*
+ * The event doesn't belong to us. Perhaps, due to embedding, it really
+ * belongs to someone else. Give the embedding code a chance to redirect
+ * the event.
+ */
+
+ TkpRedirectKeyEvent(winPtr, eventPtr);
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkFocusDeadWindow --
+ *
+ * This function is invoked when it is determined that a window is dead.
+ * It cleans up focus-related information about the window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Various things get cleaned up and recycled.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkFocusDeadWindow(
+ register TkWindow *winPtr) /* Information about the window that is being
+ * deleted. */
+{
+ ToplevelFocusInfo *tlFocusPtr, *prevPtr;
+ DisplayFocusInfo *displayFocusPtr;
+ TkDisplay *dispPtr = winPtr->dispPtr;
+
+ /*
+ * Certain special windows like those used for send and clipboard have no
+ * mainPtr.
+ */
+
+ if (winPtr->mainPtr == NULL) {
+ return;
+ }
+
+ /*
+ * Search for focus records that refer to this window either as the
+ * top-level window or the current focus window.
+ */
+
+ displayFocusPtr = FindDisplayFocusInfo(winPtr->mainPtr, winPtr->dispPtr);
+ for (prevPtr = NULL, tlFocusPtr = winPtr->mainPtr->tlFocusPtr;
+ tlFocusPtr != NULL;
+ prevPtr = tlFocusPtr, tlFocusPtr = tlFocusPtr->nextPtr) {
+ if (winPtr == tlFocusPtr->topLevelPtr) {
+ /*
+ * The top-level window is the one being deleted: free the focus
+ * record and release the focus back to PointerRoot if we acquired
+ * it implicitly.
+ */
+
+ if (dispPtr->implicitWinPtr == winPtr) {
+ DEBUG(dispPtr, ("releasing focus to root after %s died\n",
+ tlFocusPtr->topLevelPtr->pathName));
+ dispPtr->implicitWinPtr = NULL;
+ displayFocusPtr->focusWinPtr = NULL;
+ dispPtr->focusPtr = NULL;
+ }
+ if (displayFocusPtr->focusWinPtr == tlFocusPtr->focusWinPtr) {
+ displayFocusPtr->focusWinPtr = NULL;
+ dispPtr->focusPtr = NULL;
+ }
+ if (prevPtr == NULL) {
+ winPtr->mainPtr->tlFocusPtr = tlFocusPtr->nextPtr;
+ } else {
+ prevPtr->nextPtr = tlFocusPtr->nextPtr;
+ }
+ ckfree(tlFocusPtr);
+ break;
+ } else if (winPtr == tlFocusPtr->focusWinPtr) {
+ /*
+ * The deleted window had the focus for its top-level: move the
+ * focus to the top-level itself.
+ */
+
+ tlFocusPtr->focusWinPtr = tlFocusPtr->topLevelPtr;
+ if ((displayFocusPtr->focusWinPtr == winPtr)
+ && !(tlFocusPtr->topLevelPtr->flags & TK_ALREADY_DEAD)) {
+ DEBUG(dispPtr, ("forwarding focus to %s after %s died\n",
+ tlFocusPtr->topLevelPtr->pathName, winPtr->pathName));
+ GenerateFocusEvents(displayFocusPtr->focusWinPtr,
+ tlFocusPtr->topLevelPtr);
+ displayFocusPtr->focusWinPtr = tlFocusPtr->topLevelPtr;
+ dispPtr->focusPtr = tlFocusPtr->topLevelPtr;
+ }
+ break;
+ }
+ }
+
+ /*
+ * Occasionally, things can become unsynchronized. Move them back into
+ * synch now. [Bug 2496114]
+ */
+
+ if (displayFocusPtr->focusWinPtr == winPtr) {
+ DEBUG(dispPtr, ("focus cleared after %s died\n", winPtr->pathName));
+ displayFocusPtr->focusWinPtr = NULL;
+ }
+
+ if (displayFocusPtr->focusOnMapPtr == winPtr) {
+ displayFocusPtr->focusOnMapPtr = NULL;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GenerateFocusEvents --
+ *
+ * This function is called to create FocusIn and FocusOut events to move
+ * the input focus from one window to another.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * FocusIn and FocusOut events are generated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GenerateFocusEvents(
+ TkWindow *sourcePtr, /* Window that used to have the focus (may be
+ * NULL). */
+ TkWindow *destPtr) /* New window to have the focus (may be
+ * NULL). */
+{
+ XEvent event;
+ TkWindow *winPtr;
+
+ winPtr = sourcePtr;
+ if (winPtr == NULL) {
+ winPtr = destPtr;
+ if (winPtr == NULL) {
+ return;
+ }
+ }
+
+ event.xfocus.serial = LastKnownRequestProcessed(winPtr->display);
+ event.xfocus.send_event = GENERATED_FOCUS_EVENT_MAGIC;
+ event.xfocus.display = winPtr->display;
+ event.xfocus.mode = NotifyNormal;
+ TkInOutEvents(&event, sourcePtr, destPtr, FocusOut, FocusIn,
+ TCL_QUEUE_MARK);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FocusMapProc --
+ *
+ * This function is called as an event handler for VisibilityNotify
+ * events, if a window receives the focus at a time when its toplevel
+ * isn't mapped. The function is needed because X won't allow the focus
+ * to be set to an unmapped window; we detect when the toplevel is mapped
+ * and set the focus to it then.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If this is a map event, the focus gets set to the toplevel given by
+ * clientData.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FocusMapProc(
+ ClientData clientData, /* Toplevel window. */
+ XEvent *eventPtr) /* Information about event. */
+{
+ TkWindow *winPtr = clientData;
+ DisplayFocusInfo *displayFocusPtr;
+
+ if (eventPtr->type == VisibilityNotify) {
+ displayFocusPtr = FindDisplayFocusInfo(winPtr->mainPtr,
+ winPtr->dispPtr);
+ DEBUG(winPtr->dispPtr, ("auto-focussing on %s, force %d\n",
+ winPtr->pathName, displayFocusPtr->forceFocus));
+ Tk_DeleteEventHandler((Tk_Window) winPtr, VisibilityChangeMask,
+ FocusMapProc, clientData);
+ displayFocusPtr->focusOnMapPtr = NULL;
+ TkSetFocusWin(winPtr, displayFocusPtr->forceFocus);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FindDisplayFocusInfo --
+ *
+ * Given an application and a display, this function locate the focus
+ * record for that combination. If no such record exists, it creates a
+ * new record and initializes it.
+ *
+ * Results:
+ * The return value is a pointer to the record.
+ *
+ * Side effects:
+ * A new record will be allocated if there wasn't one already.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static DisplayFocusInfo *
+FindDisplayFocusInfo(
+ TkMainInfo *mainPtr, /* Record that identifies a particular
+ * application. */
+ TkDisplay *dispPtr) /* Display whose focus information is
+ * needed. */
+{
+ DisplayFocusInfo *displayFocusPtr;
+
+ for (displayFocusPtr = mainPtr->displayFocusPtr;
+ displayFocusPtr != NULL;
+ displayFocusPtr = displayFocusPtr->nextPtr) {
+ if (displayFocusPtr->dispPtr == dispPtr) {
+ return displayFocusPtr;
+ }
+ }
+
+ /*
+ * The record doesn't exist yet. Make a new one.
+ */
+
+ displayFocusPtr = ckalloc(sizeof(DisplayFocusInfo));
+ displayFocusPtr->dispPtr = dispPtr;
+ displayFocusPtr->focusWinPtr = NULL;
+ displayFocusPtr->focusOnMapPtr = NULL;
+ displayFocusPtr->forceFocus = 0;
+ displayFocusPtr->focusSerial = 0;
+ displayFocusPtr->nextPtr = mainPtr->displayFocusPtr;
+ mainPtr->displayFocusPtr = displayFocusPtr;
+ return displayFocusPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkFocusFree --
+ *
+ * Free resources associated with maintaining the focus.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * This mainPtr should no long access focus information.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkFocusFree(
+ TkMainInfo *mainPtr) /* Record that identifies a particular
+ * application. */
+{
+ while (mainPtr->displayFocusPtr != NULL) {
+ DisplayFocusInfo *displayFocusPtr = mainPtr->displayFocusPtr;
+
+ mainPtr->displayFocusPtr = mainPtr->displayFocusPtr->nextPtr;
+ ckfree(displayFocusPtr);
+ }
+ while (mainPtr->tlFocusPtr != NULL) {
+ ToplevelFocusInfo *tlFocusPtr = mainPtr->tlFocusPtr;
+
+ mainPtr->tlFocusPtr = mainPtr->tlFocusPtr->nextPtr;
+ ckfree(tlFocusPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkFocusSplit --
+ *
+ * Adjust focus window for a newly managed toplevel, thus splitting the
+ * toplevel into two toplevels.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A new record is allocated for the new toplevel window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkFocusSplit(
+ TkWindow *winPtr) /* Window is the new toplevel. Any focus point
+ * at or below window must be moved to this
+ * new toplevel. */
+{
+ ToplevelFocusInfo *tlFocusPtr;
+ TkWindow *topLevelPtr, *subWinPtr;
+
+ FindDisplayFocusInfo(winPtr->mainPtr, winPtr->dispPtr);
+
+ /*
+ * Find the top-level window for winPtr, then find (or create) a record
+ * for the top-level. Also see whether winPtr and all its ancestors are
+ * mapped.
+ */
+
+ for (topLevelPtr = winPtr; ; topLevelPtr = topLevelPtr->parentPtr) {
+ if (topLevelPtr == NULL) {
+ /*
+ * The window is being deleted. No point in worrying about giving
+ * it the focus.
+ */
+
+ return;
+ }
+ if (topLevelPtr->flags & TK_TOP_HIERARCHY) {
+ break;
+ }
+ }
+
+ /*
+ * Search all focus records to find child windows of winPtr.
+ */
+
+ for (tlFocusPtr = winPtr->mainPtr->tlFocusPtr; tlFocusPtr != NULL;
+ tlFocusPtr = tlFocusPtr->nextPtr) {
+ if (tlFocusPtr->topLevelPtr == topLevelPtr) {
+ break;
+ }
+ }
+
+ if (tlFocusPtr == NULL) {
+ /*
+ * No focus record for this toplevel, nothing to do.
+ */
+
+ return;
+ }
+
+ /*
+ * See if current focusWin is child of the new toplevel.
+ */
+
+ for (subWinPtr = tlFocusPtr->focusWinPtr;
+ subWinPtr && subWinPtr != winPtr && subWinPtr != topLevelPtr;
+ subWinPtr = subWinPtr->parentPtr) {
+ /* EMPTY */
+ }
+
+ if (subWinPtr == winPtr) {
+ /*
+ * Move focus to new toplevel.
+ */
+
+ ToplevelFocusInfo *newTlFocusPtr = ckalloc(sizeof(ToplevelFocusInfo));
+
+ newTlFocusPtr->topLevelPtr = winPtr;
+ newTlFocusPtr->focusWinPtr = tlFocusPtr->focusWinPtr;
+ newTlFocusPtr->nextPtr = winPtr->mainPtr->tlFocusPtr;
+ winPtr->mainPtr->tlFocusPtr = newTlFocusPtr;
+
+ /*
+ * Move old toplevel's focus to the toplevel itself.
+ */
+
+ tlFocusPtr->focusWinPtr = topLevelPtr;
+ }
+
+ /*
+ * If it's not, then let focus progress naturally.
+ */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkFocusJoin --
+ *
+ * Remove the focus record for this window that is nolonger managed
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A tlFocusPtr record is removed
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkFocusJoin(
+ TkWindow *winPtr) /* Window is no longer a toplevel. */
+{
+ ToplevelFocusInfo *tlFocusPtr, *tmpPtr;
+
+ /*
+ * Remove old toplevel record
+ */
+
+ if (winPtr && winPtr->mainPtr && winPtr->mainPtr->tlFocusPtr
+ && winPtr->mainPtr->tlFocusPtr->topLevelPtr == winPtr) {
+ tmpPtr = winPtr->mainPtr->tlFocusPtr;
+ winPtr->mainPtr->tlFocusPtr = tmpPtr->nextPtr;
+ ckfree(tmpPtr);
+ } else if (winPtr && winPtr->mainPtr) {
+ for (tlFocusPtr = winPtr->mainPtr->tlFocusPtr; tlFocusPtr != NULL;
+ tlFocusPtr = tlFocusPtr->nextPtr) {
+ if (tlFocusPtr->nextPtr &&
+ tlFocusPtr->nextPtr->topLevelPtr == winPtr) {
+ tmpPtr = tlFocusPtr->nextPtr;
+ tlFocusPtr->nextPtr = tmpPtr->nextPtr;
+ ckfree(tmpPtr);
+ break;
+ }
+ }
+ }
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkFont.c b/tk8.6/generic/tkFont.c
new file mode 100644
index 0000000..86fdd87
--- /dev/null
+++ b/tk8.6/generic/tkFont.c
@@ -0,0 +1,4269 @@
+/*
+ * tkFont.c --
+ *
+ * This file maintains a database of fonts for the Tk toolkit. It also
+ * provides several utility functions for measuring and displaying text.
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1998 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkInt.h"
+#include "tkFont.h"
+
+/*
+ * The following structure is used to keep track of all the fonts that exist
+ * in the current application. It must be stored in the TkMainInfo for the
+ * application.
+ */
+
+typedef struct TkFontInfo {
+ Tcl_HashTable fontCache; /* Map a string to an existing Tk_Font. Keys
+ * are string font names, values are TkFont
+ * pointers. */
+ Tcl_HashTable namedTable; /* Map a name to a set of attributes for a
+ * font, used when constructing a Tk_Font from
+ * a named font description. Keys are strings,
+ * values are NamedFont pointers. */
+ TkMainInfo *mainPtr; /* Application that owns this structure. */
+ int updatePending; /* Non-zero when a World Changed event has
+ * already been queued to handle a change to a
+ * named font. */
+} TkFontInfo;
+
+/*
+ * The following data structure is used to keep track of the font attributes
+ * for each named font that has been defined. The named font is only deleted
+ * when the last reference to it goes away.
+ */
+
+typedef struct NamedFont {
+ int refCount; /* Number of users of named font. */
+ int deletePending; /* Non-zero if font should be deleted when
+ * last reference goes away. */
+ TkFontAttributes fa; /* Desired attributes for named font. */
+} NamedFont;
+
+/*
+ * The following two structures are used to keep track of string measurement
+ * information when using the text layout facilities.
+ *
+ * A LayoutChunk represents a contiguous range of text that can be measured
+ * and displayed by low-level text calls. In general, chunks will be delimited
+ * by newlines and tabs. Low-level, platform-specific things like kerning and
+ * non-integer character widths may occur between the characters in a single
+ * chunk, but not between characters in different chunks.
+ *
+ * A TextLayout is a collection of LayoutChunks. It can be displayed with
+ * respect to any origin. It is the implementation of the Tk_TextLayout opaque
+ * token.
+ */
+
+typedef struct LayoutChunk {
+ const char *start; /* Pointer to simple string to be displayed.
+ * This is a pointer into the TkTextLayout's
+ * string. */
+ int numBytes; /* The number of bytes in this chunk. */
+ int numChars; /* The number of characters in this chunk. */
+ int numDisplayChars; /* The number of characters to display when
+ * this chunk is displayed. Can be less than
+ * numChars if extra space characters were
+ * absorbed by the end of the chunk. This will
+ * be < 0 if this is a chunk that is holding a
+ * tab or newline. */
+ int x, y; /* The origin of the first character in this
+ * chunk with respect to the upper-left hand
+ * corner of the TextLayout. */
+ int totalWidth; /* Width in pixels of this chunk. Used when
+ * hit testing the invisible spaces at the end
+ * of a chunk. */
+ int displayWidth; /* Width in pixels of the displayable
+ * characters in this chunk. Can be less than
+ * width if extra space characters were
+ * absorbed by the end of the chunk. */
+} LayoutChunk;
+
+typedef struct TextLayout {
+ Tk_Font tkfont; /* The font used when laying out the text. */
+ const char *string; /* The string that was layed out. */
+ int width; /* The maximum width of all lines in the text
+ * layout. */
+ int numChunks; /* Number of chunks actually used in following
+ * array. */
+ LayoutChunk chunks[1]; /* Array of chunks. The actual size will be
+ * maxChunks. THIS FIELD MUST BE THE LAST IN
+ * THE STRUCTURE. */
+} TextLayout;
+
+/*
+ * The following structures are used as two-way maps between the values for
+ * the fields in the TkFontAttributes structure and the strings used in Tcl,
+ * when parsing both option-value format and style-list format font name
+ * strings.
+ */
+
+static const TkStateMap weightMap[] = {
+ {TK_FW_NORMAL, "normal"},
+ {TK_FW_BOLD, "bold"},
+ {TK_FW_UNKNOWN, NULL}
+};
+
+static const TkStateMap slantMap[] = {
+ {TK_FS_ROMAN, "roman"},
+ {TK_FS_ITALIC, "italic"},
+ {TK_FS_UNKNOWN, NULL}
+};
+
+static const TkStateMap underlineMap[] = {
+ {1, "underline"},
+ {0, NULL}
+};
+
+static const TkStateMap overstrikeMap[] = {
+ {1, "overstrike"},
+ {0, NULL}
+};
+
+/*
+ * The following structures are used when parsing XLFD's into a set of
+ * TkFontAttributes.
+ */
+
+static const TkStateMap xlfdWeightMap[] = {
+ {TK_FW_NORMAL, "normal"},
+ {TK_FW_NORMAL, "medium"},
+ {TK_FW_NORMAL, "book"},
+ {TK_FW_NORMAL, "light"},
+ {TK_FW_BOLD, "bold"},
+ {TK_FW_BOLD, "demi"},
+ {TK_FW_BOLD, "demibold"},
+ {TK_FW_NORMAL, NULL} /* Assume anything else is "normal". */
+};
+
+static const TkStateMap xlfdSlantMap[] = {
+ {TK_FS_ROMAN, "r"},
+ {TK_FS_ITALIC, "i"},
+ {TK_FS_OBLIQUE, "o"},
+ {TK_FS_ROMAN, NULL} /* Assume anything else is "roman". */
+};
+
+static const TkStateMap xlfdSetwidthMap[] = {
+ {TK_SW_NORMAL, "normal"},
+ {TK_SW_CONDENSE, "narrow"},
+ {TK_SW_CONDENSE, "semicondensed"},
+ {TK_SW_CONDENSE, "condensed"},
+ {TK_SW_UNKNOWN, NULL}
+};
+
+/*
+ * The following structure and defines specify the valid builtin options when
+ * configuring a set of font attributes.
+ */
+
+static const char *const fontOpt[] = {
+ "-family",
+ "-size",
+ "-weight",
+ "-slant",
+ "-underline",
+ "-overstrike",
+ NULL
+};
+
+#define FONT_FAMILY 0
+#define FONT_SIZE 1
+#define FONT_WEIGHT 2
+#define FONT_SLANT 3
+#define FONT_UNDERLINE 4
+#define FONT_OVERSTRIKE 5
+#define FONT_NUMFIELDS 6
+
+/*
+ * Hardcoded font aliases. These are used to describe (mostly) identical fonts
+ * whose names differ from platform to platform. If the user-supplied font
+ * name matches any of the names in one of the alias lists, the other names in
+ * the alias list are also automatically tried.
+ */
+
+static const char *const timesAliases[] = {
+ "Times", /* Unix. */
+ "Times New Roman", /* Windows. */
+ "New York", /* Mac. */
+ NULL
+};
+
+static const char *const helveticaAliases[] = {
+ "Helvetica", /* Unix. */
+ "Arial", /* Windows. */
+ "Geneva", /* Mac. */
+ NULL
+};
+
+static const char *const courierAliases[] = {
+ "Courier", /* Unix and Mac. */
+ "Courier New", /* Windows. */
+ NULL
+};
+
+static const char *const minchoAliases[] = {
+ "mincho", /* Unix. */
+ "\357\274\255\357\274\263 \346\230\216\346\234\235",
+ /* Windows (MS mincho). */
+ "\346\234\254\346\230\216\346\234\235\342\210\222\357\274\255",
+ /* Mac (honmincho-M). */
+ NULL
+};
+
+static const char *const gothicAliases[] = {
+ "gothic", /* Unix. */
+ "\357\274\255\357\274\263 \343\202\264\343\202\267\343\203\203\343\202\257",
+ /* Windows (MS goshikku). */
+ "\344\270\270\343\202\264\343\202\267\343\203\203\343\202\257\342\210\222\357\274\255",
+ /* Mac (goshikku-M). */
+ NULL
+};
+
+static const char *const dingbatsAliases[] = {
+ "dingbats", "zapfdingbats", "itc zapfdingbats",
+ /* Unix. */
+ /* Windows. */
+ "zapf dingbats", /* Mac. */
+ NULL
+};
+
+static const char *const *const fontAliases[] = {
+ timesAliases,
+ helveticaAliases,
+ courierAliases,
+ minchoAliases,
+ gothicAliases,
+ dingbatsAliases,
+ NULL
+};
+
+/*
+ * Hardcoded font classes. If the character cannot be found in the base font,
+ * the classes are examined in order to see if some other similar font should
+ * be examined also.
+ */
+
+static const char *const systemClass[] = {
+ "fixed", /* Unix. */
+ /* Windows. */
+ "chicago", "osaka", "sistemny",
+ /* Mac. */
+ NULL
+};
+
+static const char *const serifClass[] = {
+ "times", "palatino", "mincho",
+ /* All platforms. */
+ "song ti", /* Unix. */
+ "ms serif", "simplified arabic",
+ /* Windows. */
+ "latinski", /* Mac. */
+ NULL
+};
+
+static const char *const sansClass[] = {
+ "helvetica", "gothic", /* All platforms. */
+ /* Unix. */
+ "ms sans serif", "traditional arabic",
+ /* Windows. */
+ "bastion", /* Mac. */
+ NULL
+};
+
+static const char *const monoClass[] = {
+ "courier", "gothic", /* All platforms. */
+ "fangsong ti", /* Unix. */
+ "simplified arabic fixed", /* Windows. */
+ "monaco", "pryamoy", /* Mac. */
+ NULL
+};
+
+static const char *const symbolClass[] = {
+ "symbol", "dingbats", "wingdings", NULL
+};
+
+static const char *const *const fontFallbacks[] = {
+ systemClass,
+ serifClass,
+ sansClass,
+ monoClass,
+ symbolClass,
+ NULL
+};
+
+/*
+ * Global fallbacks. If the character could not be found in the preferred
+ * fallback list, this list is examined. If the character still cannot be
+ * found, all font families in the system are examined.
+ */
+
+static const char *const globalFontClass[] = {
+ "symbol", /* All platforms. */
+ /* Unix. */
+ "lucida sans unicode", /* Windows. */
+ "bitstream cyberbit", /* Windows popular CJK font */
+ "chicago", /* Mac. */
+ NULL
+};
+
+#define GetFontAttributes(tkfont) \
+ ((const TkFontAttributes *) &((TkFont *) (tkfont))->fa)
+
+#define GetFontMetrics(tkfont) \
+ ((const TkFontMetrics *) &((TkFont *) (tkfont))->fm)
+
+
+static int ConfigAttributesObj(Tcl_Interp *interp,
+ Tk_Window tkwin, int objc, Tcl_Obj *const objv[],
+ TkFontAttributes *faPtr);
+static void DupFontObjProc(Tcl_Obj *srcObjPtr, Tcl_Obj *dupObjPtr);
+static int FieldSpecified(const char *field);
+static void FreeFontObj(Tcl_Obj *objPtr);
+static void FreeFontObjProc(Tcl_Obj *objPtr);
+static int GetAttributeInfoObj(Tcl_Interp *interp,
+ const TkFontAttributes *faPtr, Tcl_Obj *objPtr);
+static LayoutChunk * NewChunk(TextLayout **layoutPtrPtr, int *maxPtr,
+ const char *start, int numChars, int curX,
+ int newX, int y);
+static int ParseFontNameObj(Tcl_Interp *interp, Tk_Window tkwin,
+ Tcl_Obj *objPtr, TkFontAttributes *faPtr);
+static void RecomputeWidgets(TkWindow *winPtr);
+static int SetFontFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
+static void TheWorldHasChanged(ClientData clientData);
+static void UpdateDependentFonts(TkFontInfo *fiPtr,
+ Tk_Window tkwin, Tcl_HashEntry *namedHashPtr);
+
+/*
+ * The following structure defines the implementation of the "font" Tcl
+ * object, used for drawing. The internalRep.twoPtrValue.ptr1 field of each
+ * font object points to the TkFont structure for the font, or NULL.
+ */
+
+const Tcl_ObjType tkFontObjType = {
+ "font", /* name */
+ FreeFontObjProc, /* freeIntRepProc */
+ DupFontObjProc, /* dupIntRepProc */
+ NULL, /* updateStringProc */
+ SetFontFromAny /* setFromAnyProc */
+};
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkFontPkgInit --
+ *
+ * This function is called when an application is created. It initializes
+ * all the structures that are used by the font package on a per
+ * application basis.
+ *
+ * Results:
+ * Stores a token in the mainPtr to hold information needed by this
+ * package on a per application basis.
+ *
+ * Side effects:
+ * Memory allocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+TkFontPkgInit(
+ TkMainInfo *mainPtr) /* The application being created. */
+{
+ TkFontInfo *fiPtr = ckalloc(sizeof(TkFontInfo));
+
+ Tcl_InitHashTable(&fiPtr->fontCache, TCL_STRING_KEYS);
+ Tcl_InitHashTable(&fiPtr->namedTable, TCL_STRING_KEYS);
+ fiPtr->mainPtr = mainPtr;
+ fiPtr->updatePending = 0;
+ mainPtr->fontInfoPtr = fiPtr;
+
+ TkpFontPkgInit(mainPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkFontPkgFree --
+ *
+ * This function is called when an application is deleted. It deletes all
+ * the structures that were used by the font package for this
+ * application.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory freed.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+TkFontPkgFree(
+ TkMainInfo *mainPtr) /* The application being deleted. */
+{
+ TkFontInfo *fiPtr = mainPtr->fontInfoPtr;
+ Tcl_HashEntry *hPtr, *searchPtr;
+ Tcl_HashSearch search;
+ int fontsLeft = 0;
+
+ for (searchPtr = Tcl_FirstHashEntry(&fiPtr->fontCache, &search);
+ searchPtr != NULL;
+ searchPtr = Tcl_NextHashEntry(&search)) {
+ fontsLeft++;
+#ifdef DEBUG_FONTS
+ fprintf(stderr, "Font %s still in cache.\n",
+ (char *) Tcl_GetHashKey(&fiPtr->fontCache, searchPtr));
+#endif
+ }
+
+#ifdef PURIFY
+ if (fontsLeft) {
+ Tcl_Panic("TkFontPkgFree: all fonts should have been freed already");
+ }
+#endif
+
+ Tcl_DeleteHashTable(&fiPtr->fontCache);
+
+ hPtr = Tcl_FirstHashEntry(&fiPtr->namedTable, &search);
+ while (hPtr != NULL) {
+ ckfree(Tcl_GetHashValue(hPtr));
+ hPtr = Tcl_NextHashEntry(&search);
+ }
+ Tcl_DeleteHashTable(&fiPtr->namedTable);
+ if (fiPtr->updatePending) {
+ Tcl_CancelIdleCall(TheWorldHasChanged, fiPtr);
+ }
+ ckfree(fiPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_FontObjCmd --
+ *
+ * This function is implemented to process the "font" 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_FontObjCmd(
+ ClientData clientData, /* Main window associated with interpreter. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ int index;
+ Tk_Window tkwin = clientData;
+ TkFontInfo *fiPtr = ((TkWindow *) tkwin)->mainPtr->fontInfoPtr;
+ static const char *const optionStrings[] = {
+ "actual", "configure", "create", "delete",
+ "families", "measure", "metrics", "names",
+ NULL
+ };
+ enum options {
+ FONT_ACTUAL, FONT_CONFIGURE, FONT_CREATE, FONT_DELETE,
+ FONT_FAMILIES, FONT_MEASURE, FONT_METRICS, FONT_NAMES
+ };
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch ((enum options) index) {
+ case FONT_ACTUAL: {
+ int skip, result, n;
+ const char *s;
+ Tk_Font tkfont;
+ Tcl_Obj *optPtr, *charPtr, *resultPtr;
+ int uniChar = 0;
+ const TkFontAttributes *faPtr;
+ TkFontAttributes fa;
+
+ /*
+ * Params 0 and 1 are 'font actual'. Param 2 is the font name. 3-4 may
+ * be '-displayof $window'
+ */
+
+ skip = TkGetDisplayOf(interp, objc - 3, objv + 3, &tkwin);
+ if (skip < 0) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Next parameter may be an option.
+ */
+
+ n = skip + 3;
+ optPtr = NULL;
+ charPtr = NULL;
+ if (n < objc) {
+ s = Tcl_GetString(objv[n]);
+ if (s[0] == '-' && s[1] != '-') {
+ optPtr = objv[n];
+ n++;
+ } else {
+ optPtr = NULL;
+ }
+ }
+
+ /*
+ * Next parameter may be '--' to mark end of options.
+ */
+
+ if (n < objc) {
+ if (!strcmp(Tcl_GetString(objv[n]), "--")) {
+ n++;
+ }
+ }
+
+ /*
+ * Next parameter is the character to get font information for.
+ */
+
+ if (n < objc) {
+ charPtr = objv[n];
+ n++;
+ }
+
+ /*
+ * If there were fewer than 3 args, or args remain, that's an error.
+ */
+
+ if (objc < 3 || n < objc) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "font ?-displayof window? ?option? ?--? ?char?");
+ return TCL_ERROR;
+ }
+
+ /*
+ * The 'charPtr' arg must be a single Unicode.
+ */
+
+ if (charPtr != NULL) {
+ const char *string = Tcl_GetString(charPtr);
+ int len = TkUtfToUniChar(string, &uniChar);
+
+ if (len != charPtr->length) {
+ resultPtr = Tcl_NewStringObj(
+ "expected a single character but got \"", -1);
+ Tcl_AppendLimitedToObj(resultPtr, string,
+ -1, 40, "...");
+ Tcl_AppendToObj(resultPtr, "\"", -1);
+ Tcl_SetObjResult(interp, resultPtr);
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "FONT_SAMPLE", NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * Find the font.
+ */
+
+ tkfont = Tk_AllocFontFromObj(interp, tkwin, objv[2]);
+ if (tkfont == NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Determine the font attributes.
+ */
+
+ if (charPtr == NULL) {
+ faPtr = GetFontAttributes(tkfont);
+ } else {
+ TkpGetFontAttrsForChar(tkwin, tkfont, uniChar, &fa);
+ faPtr = &fa;
+ }
+ result = GetAttributeInfoObj(interp, faPtr, optPtr);
+
+ Tk_FreeFont(tkfont);
+ return result;
+ }
+ case FONT_CONFIGURE: {
+ int result;
+ const char *string;
+ Tcl_Obj *objPtr;
+ NamedFont *nfPtr;
+ Tcl_HashEntry *namedHashPtr;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "fontname ?-option value ...?");
+ return TCL_ERROR;
+ }
+ string = Tcl_GetString(objv[2]);
+ namedHashPtr = Tcl_FindHashEntry(&fiPtr->namedTable, string);
+ nfPtr = NULL; /* lint. */
+ if (namedHashPtr != NULL) {
+ nfPtr = Tcl_GetHashValue(namedHashPtr);
+ }
+ if ((namedHashPtr == NULL) || nfPtr->deletePending) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "named font \"%s\" doesn't exist", string));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "FONT", string, NULL);
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ objPtr = NULL;
+ } else if (objc == 4) {
+ objPtr = objv[3];
+ } else {
+ result = ConfigAttributesObj(interp, tkwin, objc - 3, objv + 3,
+ &nfPtr->fa);
+ UpdateDependentFonts(fiPtr, tkwin, namedHashPtr);
+ return result;
+ }
+ return GetAttributeInfoObj(interp, &nfPtr->fa, objPtr);
+ }
+ case FONT_CREATE: {
+ int skip = 3, i;
+ const char *name;
+ char buf[16 + TCL_INTEGER_SPACE];
+ TkFontAttributes fa;
+ Tcl_HashEntry *namedHashPtr;
+
+ if (objc < 3) {
+ name = NULL;
+ } else {
+ name = Tcl_GetString(objv[2]);
+ if (name[0] == '-') {
+ name = NULL;
+ }
+ }
+ if (name == NULL) {
+ /*
+ * No font name specified. Generate one of the form "fontX".
+ */
+
+ for (i = 1; ; i++) {
+ sprintf(buf, "font%d", i);
+ namedHashPtr = Tcl_FindHashEntry(&fiPtr->namedTable, buf);
+ if (namedHashPtr == NULL) {
+ break;
+ }
+ }
+ name = buf;
+ skip = 2;
+ }
+ TkInitFontAttributes(&fa);
+ if (ConfigAttributesObj(interp, tkwin, objc - skip, objv + skip,
+ &fa) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (TkCreateNamedFont(interp, tkwin, name, &fa) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(name, -1));
+ break;
+ }
+ case FONT_DELETE: {
+ int i, result = TCL_OK;
+ const char *string;
+
+ /*
+ * Delete the named font. If there are still widgets using this font,
+ * then it isn't deleted right away.
+ */
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "fontname ?fontname ...?");
+ return TCL_ERROR;
+ }
+ for (i = 2; (i < objc) && (result == TCL_OK); i++) {
+ string = Tcl_GetString(objv[i]);
+ result = TkDeleteNamedFont(interp, tkwin, string);
+ }
+ return result;
+ }
+ case FONT_FAMILIES: {
+ int skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin);
+
+ if (skip < 0) {
+ return TCL_ERROR;
+ }
+ if (objc - skip != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?-displayof window?");
+ return TCL_ERROR;
+ }
+ TkpGetFontFamilies(interp, tkwin);
+ break;
+ }
+ case FONT_MEASURE: {
+ const char *string;
+ Tk_Font tkfont;
+ int length = 0, skip = 0;
+
+ if (objc > 4) {
+ skip = TkGetDisplayOf(interp, objc - 3, objv + 3, &tkwin);
+ if (skip < 0) {
+ return TCL_ERROR;
+ }
+ }
+ if (objc - skip != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "font ?-displayof window? text");
+ return TCL_ERROR;
+ }
+ tkfont = Tk_AllocFontFromObj(interp, tkwin, objv[2]);
+ if (tkfont == NULL) {
+ return TCL_ERROR;
+ }
+ string = Tcl_GetStringFromObj(objv[3 + skip], &length);
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(
+ Tk_TextWidth(tkfont, string, length)));
+ Tk_FreeFont(tkfont);
+ break;
+ }
+ case FONT_METRICS: {
+ Tk_Font tkfont;
+ int skip, index, i;
+ const TkFontMetrics *fmPtr;
+ static const char *const switches[] = {
+ "-ascent", "-descent", "-linespace", "-fixed", NULL
+ };
+
+ skip = TkGetDisplayOf(interp, objc - 3, objv + 3, &tkwin);
+ if (skip < 0) {
+ return TCL_ERROR;
+ }
+ if ((objc < 3) || ((objc - skip) > 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "font ?-displayof window? ?option?");
+ return TCL_ERROR;
+ }
+ tkfont = Tk_AllocFontFromObj(interp, tkwin, objv[2]);
+ if (tkfont == NULL) {
+ return TCL_ERROR;
+ }
+ objc -= skip;
+ objv += skip;
+ fmPtr = GetFontMetrics(tkfont);
+ if (objc == 3) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "-ascent %d -descent %d -linespace %d -fixed %d",
+ fmPtr->ascent, fmPtr->descent,
+ fmPtr->ascent + fmPtr->descent, fmPtr->fixed));
+ } else {
+ if (Tcl_GetIndexFromObj(interp, objv[3], switches, "metric", 0,
+ &index) != TCL_OK) {
+ Tk_FreeFont(tkfont);
+ return TCL_ERROR;
+ }
+ i = 0; /* Needed only to prevent compiler warning. */
+ switch (index) {
+ case 0: i = fmPtr->ascent; break;
+ case 1: i = fmPtr->descent; break;
+ case 2: i = fmPtr->ascent + fmPtr->descent; break;
+ case 3: i = fmPtr->fixed; break;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(i));
+ }
+ Tk_FreeFont(tkfont);
+ break;
+ }
+ case FONT_NAMES: {
+ Tcl_HashSearch search;
+ Tcl_HashEntry *namedHashPtr;
+ Tcl_Obj *resultPtr;
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "names");
+ return TCL_ERROR;
+ }
+ resultPtr = Tcl_NewObj();
+ namedHashPtr = Tcl_FirstHashEntry(&fiPtr->namedTable, &search);
+ while (namedHashPtr != NULL) {
+ NamedFont *nfPtr = Tcl_GetHashValue(namedHashPtr);
+
+ if (!nfPtr->deletePending) {
+ char *string = Tcl_GetHashKey(&fiPtr->namedTable,
+ namedHashPtr);
+
+ Tcl_ListObjAppendElement(NULL, resultPtr,
+ Tcl_NewStringObj(string, -1));
+ }
+ namedHashPtr = Tcl_NextHashEntry(&search);
+ }
+ Tcl_SetObjResult(interp, resultPtr);
+ break;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * UpdateDependentFonts, TheWorldHasChanged, RecomputeWidgets --
+ *
+ * Called when the attributes of a named font changes. Updates all the
+ * instantiated fonts that depend on that named font and then uses the
+ * brute force approach and prepares every widget to recompute its
+ * geometry.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Things get queued for redisplay.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+UpdateDependentFonts(
+ TkFontInfo *fiPtr, /* Info about application's fonts. */
+ Tk_Window tkwin, /* A window in the application. */
+ Tcl_HashEntry *namedHashPtr)/* The named font that is changing. */
+{
+ Tcl_HashEntry *cacheHashPtr;
+ Tcl_HashSearch search;
+ TkFont *fontPtr;
+ NamedFont *nfPtr = Tcl_GetHashValue(namedHashPtr);
+
+ if (nfPtr->refCount == 0) {
+ /*
+ * Well nobody's using this named font, so don't have to tell any
+ * widgets to recompute themselves.
+ */
+
+ return;
+ }
+
+ cacheHashPtr = Tcl_FirstHashEntry(&fiPtr->fontCache, &search);
+ while (cacheHashPtr != NULL) {
+ for (fontPtr = Tcl_GetHashValue(cacheHashPtr);
+ fontPtr != NULL; fontPtr = fontPtr->nextPtr) {
+ if (fontPtr->namedHashPtr == namedHashPtr) {
+ TkpGetFontFromAttributes(fontPtr, tkwin, &nfPtr->fa);
+ if (!fiPtr->updatePending) {
+ fiPtr->updatePending = 1;
+ Tcl_DoWhenIdle(TheWorldHasChanged, fiPtr);
+ }
+ }
+ }
+ cacheHashPtr = Tcl_NextHashEntry(&search);
+ }
+}
+
+static void
+TheWorldHasChanged(
+ ClientData clientData) /* Info about application's fonts. */
+{
+ TkFontInfo *fiPtr = clientData;
+
+ fiPtr->updatePending = 0;
+ RecomputeWidgets(fiPtr->mainPtr->winPtr);
+}
+
+static void
+RecomputeWidgets(
+ TkWindow *winPtr) /* Window to which command is sent. */
+{
+ Tk_ClassWorldChangedProc *proc =
+ Tk_GetClassProc(winPtr->classProcsPtr, worldChangedProc);
+
+ if (proc != NULL) {
+ proc(winPtr->instanceData);
+ }
+
+ /*
+ * Notify all the descendants of this window that the world has changed.
+ *
+ * This could be done recursively or iteratively. The recursive version is
+ * easier to implement and understand, and typically, windows with a -font
+ * option will be leaf nodes in the widget heirarchy (buttons, labels,
+ * etc.), so the recursion depth will be shallow.
+ *
+ * However, the additional overhead of the recursive calls may become a
+ * performance problem if typical usage alters such that -font'ed widgets
+ * appear high in the heirarchy, causing deep recursion. This could happen
+ * with text widgets, or more likely with the (not yet existant) labeled
+ * frame widget. With these widgets it is possible, even likely, that a
+ * -font'ed widget (text or labeled frame) will not be a leaf node, but
+ * will instead have many descendants. If this is ever found to cause a
+ * performance problem, it may be worth investigating an iterative version
+ * of the code below.
+ */
+
+ for (winPtr=winPtr->childList ; winPtr!=NULL ; winPtr=winPtr->nextPtr) {
+ RecomputeWidgets(winPtr);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkCreateNamedFont --
+ *
+ * Create the specified named font with the given attributes in the named
+ * font table associated with the interp.
+ *
+ * Results:
+ * Returns TCL_OK if the font was successfully created, or TCL_ERROR if
+ * the named font already existed. If TCL_ERROR is returned, an error
+ * message is left in the interp's result.
+ *
+ * Side effects:
+ * Assume there used to exist a named font by the specified name, and
+ * that the named font had been deleted, but there were still some
+ * widgets using the named font at the time it was deleted. If a new
+ * named font is created with the same name, all those widgets that were
+ * using the old named font will be redisplayed using the new named
+ * font's attributes.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TkCreateNamedFont(
+ Tcl_Interp *interp, /* Interp for error return (can be NULL). */
+ Tk_Window tkwin, /* A window associated with interp. */
+ const char *name, /* Name for the new named font. */
+ TkFontAttributes *faPtr) /* Attributes for the new named font. */
+{
+ TkFontInfo *fiPtr = ((TkWindow *) tkwin)->mainPtr->fontInfoPtr;
+ Tcl_HashEntry *namedHashPtr;
+ int isNew;
+ NamedFont *nfPtr;
+
+ namedHashPtr = Tcl_CreateHashEntry(&fiPtr->namedTable, name, &isNew);
+ if (!isNew) {
+ nfPtr = Tcl_GetHashValue(namedHashPtr);
+ if (!nfPtr->deletePending) {
+ if (interp) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "named font \"%s\" already exists", name));
+ Tcl_SetErrorCode(interp, "TK", "FONT", "EXISTS", NULL);
+ }
+ return TCL_ERROR;
+ }
+
+ /*
+ * Recreating a named font with the same name as a previous named
+ * font. Some widgets were still using that named font, so they need
+ * to get redisplayed.
+ */
+
+ nfPtr->fa = *faPtr;
+ nfPtr->deletePending = 0;
+ UpdateDependentFonts(fiPtr, tkwin, namedHashPtr);
+ return TCL_OK;
+ }
+
+ nfPtr = ckalloc(sizeof(NamedFont));
+ nfPtr->deletePending = 0;
+ Tcl_SetHashValue(namedHashPtr, nfPtr);
+ nfPtr->fa = *faPtr;
+ nfPtr->refCount = 0;
+ nfPtr->deletePending = 0;
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkDeleteNamedFont --
+ *
+ * Delete the named font. If there are still widgets using this font,
+ * then it isn't deleted right away.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TkDeleteNamedFont(
+ Tcl_Interp *interp, /* Interp for error return (can be NULL). */
+ Tk_Window tkwin, /* A window associated with interp. */
+ const char *name) /* Name for the new named font. */
+{
+ TkFontInfo *fiPtr = ((TkWindow *) tkwin)->mainPtr->fontInfoPtr;
+ NamedFont *nfPtr;
+ Tcl_HashEntry *namedHashPtr;
+
+ namedHashPtr = Tcl_FindHashEntry(&fiPtr->namedTable, name);
+ if (namedHashPtr == NULL) {
+ if (interp) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "named font \"%s\" doesn't exist", name));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "FONT", name, NULL);
+ }
+ return TCL_ERROR;
+ }
+ nfPtr = Tcl_GetHashValue(namedHashPtr);
+ if (nfPtr->refCount != 0) {
+ nfPtr->deletePending = 1;
+ } else {
+ Tcl_DeleteHashEntry(namedHashPtr);
+ ckfree(nfPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_GetFont --
+ *
+ * Given a string description of a font, map the description to a
+ * corresponding Tk_Font that represents the font.
+ *
+ * Results:
+ * The return value is token for the font, or NULL if an error prevented
+ * the font from being created. If NULL is returned, an error message
+ * will be left in the interp's result.
+ *
+ * Side effects:
+ * The font is added to an internal database with a reference count. For
+ * each call to this function, there should eventually be a call to
+ * Tk_FreeFont() or Tk_FreeFontFromObj() so that the database is cleaned
+ * up when fonts aren't in use anymore.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tk_Font
+Tk_GetFont(
+ Tcl_Interp *interp, /* Interp for database and error return. */
+ Tk_Window tkwin, /* For display on which font will be used. */
+ const char *string) /* String describing font, as: named font,
+ * native format, or parseable string. */
+{
+ Tk_Font tkfont;
+ Tcl_Obj *strPtr;
+
+ strPtr = Tcl_NewStringObj(string, -1);
+ Tcl_IncrRefCount(strPtr);
+ tkfont = Tk_AllocFontFromObj(interp, tkwin, strPtr);
+ Tcl_DecrRefCount(strPtr);
+ return tkfont;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_AllocFontFromObj --
+ *
+ * Given a string description of a font, map the description to a
+ * corresponding Tk_Font that represents the font.
+ *
+ * Results:
+ * The return value is token for the font, or NULL if an error prevented
+ * the font from being created. If NULL is returned, an error message
+ * will be left in interp's result object.
+ *
+ * Side effects:
+ * The font is added to an internal database with a reference count. For
+ * each call to this function, there should eventually be a call to
+ * Tk_FreeFont() or Tk_FreeFontFromObj() so that the database is cleaned
+ * up when fonts aren't in use anymore.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tk_Font
+Tk_AllocFontFromObj(
+ Tcl_Interp *interp, /* Interp for database and error return. */
+ Tk_Window tkwin, /* For screen on which font will be used. */
+ Tcl_Obj *objPtr) /* Object describing font, as: named font,
+ * native format, or parseable string. */
+{
+ TkFontInfo *fiPtr = ((TkWindow *) tkwin)->mainPtr->fontInfoPtr;
+ Tcl_HashEntry *cacheHashPtr, *namedHashPtr;
+ TkFont *fontPtr, *firstFontPtr, *oldFontPtr;
+ int isNew, descent;
+ NamedFont *nfPtr;
+
+ if (objPtr->typePtr != &tkFontObjType
+ || objPtr->internalRep.twoPtrValue.ptr2 != fiPtr) {
+ SetFontFromAny(interp, objPtr);
+ }
+
+ oldFontPtr = objPtr->internalRep.twoPtrValue.ptr1;
+ if (oldFontPtr != NULL) {
+ if (oldFontPtr->resourceRefCount == 0) {
+ /*
+ * This is a stale reference: it refers to a TkFont that's no
+ * longer in use. Clear the reference.
+ */
+
+ FreeFontObj(objPtr);
+ oldFontPtr = NULL;
+ } else if (Tk_Screen(tkwin) == oldFontPtr->screen) {
+ oldFontPtr->resourceRefCount++;
+ return (Tk_Font) oldFontPtr;
+ }
+ }
+
+ /*
+ * Next, search the list of fonts that have the name we want, to see if
+ * one of them is for the right screen.
+ */
+
+ isNew = 0;
+ if (oldFontPtr != NULL) {
+ cacheHashPtr = oldFontPtr->cacheHashPtr;
+ FreeFontObj(objPtr);
+ } else {
+ cacheHashPtr = Tcl_CreateHashEntry(&fiPtr->fontCache,
+ Tcl_GetString(objPtr), &isNew);
+ }
+ firstFontPtr = Tcl_GetHashValue(cacheHashPtr);
+ for (fontPtr = firstFontPtr; (fontPtr != NULL);
+ fontPtr = fontPtr->nextPtr) {
+ if (Tk_Screen(tkwin) == fontPtr->screen) {
+ fontPtr->resourceRefCount++;
+ fontPtr->objRefCount++;
+ objPtr->internalRep.twoPtrValue.ptr1 = fontPtr;
+ objPtr->internalRep.twoPtrValue.ptr2 = fiPtr;
+ return (Tk_Font) fontPtr;
+ }
+ }
+
+ /*
+ * The desired font isn't in the table. Make a new one.
+ */
+
+ namedHashPtr = Tcl_FindHashEntry(&fiPtr->namedTable,
+ Tcl_GetString(objPtr));
+ if (namedHashPtr != NULL) {
+ /*
+ * Construct a font based on a named font.
+ */
+
+ nfPtr = Tcl_GetHashValue(namedHashPtr);
+ nfPtr->refCount++;
+
+ fontPtr = TkpGetFontFromAttributes(NULL, tkwin, &nfPtr->fa);
+ } else {
+ /*
+ * Native font?
+ */
+
+ fontPtr = TkpGetNativeFont(tkwin, Tcl_GetString(objPtr));
+ if (fontPtr == NULL) {
+ TkFontAttributes fa;
+ Tcl_Obj *dupObjPtr = Tcl_DuplicateObj(objPtr);
+
+ if (ParseFontNameObj(interp, tkwin, dupObjPtr, &fa) != TCL_OK) {
+ if (isNew) {
+ Tcl_DeleteHashEntry(cacheHashPtr);
+ }
+ Tcl_DecrRefCount(dupObjPtr);
+ return NULL;
+ }
+ Tcl_DecrRefCount(dupObjPtr);
+
+ /*
+ * String contained the attributes inline.
+ */
+
+ fontPtr = TkpGetFontFromAttributes(NULL, tkwin, &fa);
+ }
+ }
+
+ /*
+ * Detect the system font engine going wrong and fail more gracefully.
+ */
+
+ if (fontPtr == NULL) {
+ if (isNew) {
+ Tcl_DeleteHashEntry(cacheHashPtr);
+ }
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "failed to allocate font due to internal system font engine"
+ " problem", -1));
+ Tcl_SetErrorCode(interp, "TK", "FONT", "INTERNAL_PROBLEM", NULL);
+ return NULL;
+ }
+
+ fontPtr->resourceRefCount = 1;
+ fontPtr->objRefCount = 1;
+ fontPtr->cacheHashPtr = cacheHashPtr;
+ fontPtr->namedHashPtr = namedHashPtr;
+ fontPtr->screen = Tk_Screen(tkwin);
+ fontPtr->nextPtr = firstFontPtr;
+ Tcl_SetHashValue(cacheHashPtr, fontPtr);
+
+ Tk_MeasureChars((Tk_Font) fontPtr, "0", 1, -1, 0, &fontPtr->tabWidth);
+ if (fontPtr->tabWidth == 0) {
+ fontPtr->tabWidth = fontPtr->fm.maxWidth;
+ }
+ fontPtr->tabWidth *= 8;
+
+ /*
+ * Make sure the tab width isn't zero (some fonts may not have enough
+ * information to set a reasonable tab width).
+ */
+
+ if (fontPtr->tabWidth == 0) {
+ fontPtr->tabWidth = 1;
+ }
+
+ /*
+ * Get information used for drawing underlines in generic code on a
+ * non-underlined font.
+ */
+
+ descent = fontPtr->fm.descent;
+ fontPtr->underlinePos = descent / 2;
+ fontPtr->underlineHeight = (int) (TkFontGetPixels(tkwin, fontPtr->fa.size) / 10 + 0.5);
+ if (fontPtr->underlineHeight == 0) {
+ fontPtr->underlineHeight = 1;
+ }
+ if (fontPtr->underlinePos + fontPtr->underlineHeight > descent) {
+ /*
+ * If this set of values would cause the bottom of the underline bar
+ * to stick below the descent of the font, jack the underline up a bit
+ * higher.
+ */
+
+ fontPtr->underlineHeight = descent - fontPtr->underlinePos;
+ if (fontPtr->underlineHeight == 0) {
+ fontPtr->underlinePos--;
+ fontPtr->underlineHeight = 1;
+ }
+ }
+
+ objPtr->internalRep.twoPtrValue.ptr1 = fontPtr;
+ objPtr->internalRep.twoPtrValue.ptr2 = fiPtr;
+ return (Tk_Font) fontPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetFontFromObj --
+ *
+ * Find the font that corresponds to a given object. The font must have
+ * already been created by Tk_GetFont or Tk_AllocFontFromObj.
+ *
+ * Results:
+ * The return value is a token for the font that matches objPtr and is
+ * suitable for use in tkwin.
+ *
+ * Side effects:
+ * If the object is not already a font ref, the conversion will free any
+ * old internal representation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_Font
+Tk_GetFontFromObj(
+ Tk_Window tkwin, /* The window that the font will be used
+ * in. */
+ Tcl_Obj *objPtr) /* The object from which to get the font. */
+{
+ TkFontInfo *fiPtr = ((TkWindow *) tkwin)->mainPtr->fontInfoPtr;
+ TkFont *fontPtr;
+ Tcl_HashEntry *hashPtr;
+
+ if (objPtr->typePtr != &tkFontObjType
+ || objPtr->internalRep.twoPtrValue.ptr2 != fiPtr) {
+ SetFontFromAny(NULL, objPtr);
+ }
+
+ fontPtr = objPtr->internalRep.twoPtrValue.ptr1;
+ if (fontPtr != NULL) {
+ if (fontPtr->resourceRefCount == 0) {
+ /*
+ * This is a stale reference: it refers to a TkFont that's no
+ * longer in use. Clear the reference.
+ */
+
+ FreeFontObj(objPtr);
+ fontPtr = NULL;
+ } else if (Tk_Screen(tkwin) == fontPtr->screen) {
+ return (Tk_Font) fontPtr;
+ }
+ }
+
+ /*
+ * Next, search the list of fonts that have the name we want, to see if
+ * one of them is for the right screen.
+ */
+
+ if (fontPtr != NULL) {
+ hashPtr = fontPtr->cacheHashPtr;
+ FreeFontObj(objPtr);
+ } else {
+ hashPtr = Tcl_FindHashEntry(&fiPtr->fontCache, Tcl_GetString(objPtr));
+ }
+ if (hashPtr != NULL) {
+ for (fontPtr = Tcl_GetHashValue(hashPtr); fontPtr != NULL;
+ fontPtr = fontPtr->nextPtr) {
+ if (Tk_Screen(tkwin) == fontPtr->screen) {
+ fontPtr->objRefCount++;
+ objPtr->internalRep.twoPtrValue.ptr1 = fontPtr;
+ objPtr->internalRep.twoPtrValue.ptr2 = fiPtr;
+ return (Tk_Font) fontPtr;
+ }
+ }
+ }
+
+ Tcl_Panic("Tk_GetFontFromObj called with non-existent font!");
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetFontFromAny --
+ *
+ * Convert the internal representation of a Tcl object to the font
+ * internal form.
+ *
+ * Results:
+ * Always returns TCL_OK.
+ *
+ * Side effects:
+ * The object is left with its typePtr pointing to tkFontObjType. The
+ * TkFont pointer is NULL.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetFontFromAny(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ Tcl_Obj *objPtr) /* The object to convert. */
+{
+ const Tcl_ObjType *typePtr;
+
+ /*
+ * Free the old internalRep before setting the new one.
+ */
+
+ Tcl_GetString(objPtr);
+ typePtr = objPtr->typePtr;
+ if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
+ typePtr->freeIntRepProc(objPtr);
+ }
+ objPtr->typePtr = &tkFontObjType;
+ objPtr->internalRep.twoPtrValue.ptr1 = NULL;
+ objPtr->internalRep.twoPtrValue.ptr2 = NULL;
+
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_NameOfFont --
+ *
+ * Given a font, return a textual string identifying it.
+ *
+ * Results:
+ * The return value is the description that was passed to Tk_GetFont() to
+ * create the font. The storage for the returned string is only
+ * guaranteed to persist until the font is deleted. The caller should not
+ * modify this string.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+const char *
+Tk_NameOfFont(
+ Tk_Font tkfont) /* Font whose name is desired. */
+{
+ TkFont *fontPtr = (TkFont *) tkfont;
+
+ return fontPtr->cacheHashPtr->key.string;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_FreeFont --
+ *
+ * Called to release a font allocated by Tk_GetFont().
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The reference count associated with font is decremented, and only
+ * deallocated when no one is using it.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+Tk_FreeFont(
+ Tk_Font tkfont) /* Font to be released. */
+{
+ TkFont *fontPtr = (TkFont *) tkfont, *prevPtr;
+ NamedFont *nfPtr;
+
+ if (fontPtr == NULL) {
+ return;
+ }
+ fontPtr->resourceRefCount--;
+ if (fontPtr->resourceRefCount > 0) {
+ return;
+ }
+ if (fontPtr->namedHashPtr != NULL) {
+ /*
+ * This font derived from a named font. Reduce the reference count on
+ * the named font and free it if no-one else is using it.
+ */
+
+ nfPtr = Tcl_GetHashValue(fontPtr->namedHashPtr);
+ nfPtr->refCount--;
+ if ((nfPtr->refCount == 0) && nfPtr->deletePending) {
+ Tcl_DeleteHashEntry(fontPtr->namedHashPtr);
+ ckfree(nfPtr);
+ }
+ }
+
+ prevPtr = Tcl_GetHashValue(fontPtr->cacheHashPtr);
+ if (prevPtr == fontPtr) {
+ if (fontPtr->nextPtr == NULL) {
+ Tcl_DeleteHashEntry(fontPtr->cacheHashPtr);
+ } else {
+ Tcl_SetHashValue(fontPtr->cacheHashPtr, fontPtr->nextPtr);
+ }
+ } else {
+ while (prevPtr->nextPtr != fontPtr) {
+ prevPtr = prevPtr->nextPtr;
+ }
+ prevPtr->nextPtr = fontPtr->nextPtr;
+ }
+
+ TkpDeleteFont(fontPtr);
+ if (fontPtr->objRefCount == 0) {
+ ckfree(fontPtr);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_FreeFontFromObj --
+ *
+ * Called to release a font inside a Tcl_Obj *. Decrements the refCount
+ * of the font and removes it from the hash tables if necessary.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The reference count associated with font is decremented, and only
+ * deallocated when no one is using it.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+Tk_FreeFontFromObj(
+ Tk_Window tkwin, /* The window this font lives in. Needed for
+ * the screen value. */
+ Tcl_Obj *objPtr) /* The Tcl_Obj * to be freed. */
+{
+ Tk_FreeFont(Tk_GetFontFromObj(tkwin, objPtr));
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FreeFontObjProc, FreeFontObj --
+ *
+ * This proc is called to release an object reference to a font. Called
+ * when the object's internal rep is released or when the cached fontPtr
+ * needs to be changed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The object reference count is decremented. When both it and the hash
+ * ref count go to zero, the font's resources are released.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+FreeFontObjProc(
+ Tcl_Obj *objPtr) /* The object we are releasing. */
+{
+ FreeFontObj(objPtr);
+ objPtr->typePtr = NULL;
+}
+
+static void
+FreeFontObj(
+ Tcl_Obj *objPtr) /* The object we are releasing. */
+{
+ TkFont *fontPtr = objPtr->internalRep.twoPtrValue.ptr1;
+
+ if (fontPtr != NULL) {
+ fontPtr->objRefCount--;
+ if ((fontPtr->resourceRefCount == 0) && (fontPtr->objRefCount == 0)) {
+ ckfree(fontPtr);
+ }
+ objPtr->internalRep.twoPtrValue.ptr1 = NULL;
+ objPtr->internalRep.twoPtrValue.ptr2 = NULL;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DupFontObjProc --
+ *
+ * When a cached font object is duplicated, this is called to update the
+ * internal reps.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The font's objRefCount is incremented and the internal rep of the copy
+ * is set to point to it.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+DupFontObjProc(
+ Tcl_Obj *srcObjPtr, /* The object we are copying from. */
+ Tcl_Obj *dupObjPtr) /* The object we are copying to. */
+{
+ TkFont *fontPtr = srcObjPtr->internalRep.twoPtrValue.ptr1;
+
+ dupObjPtr->typePtr = srcObjPtr->typePtr;
+ dupObjPtr->internalRep.twoPtrValue.ptr1 = fontPtr;
+ dupObjPtr->internalRep.twoPtrValue.ptr2
+ = srcObjPtr->internalRep.twoPtrValue.ptr2;
+
+ if (fontPtr != NULL) {
+ fontPtr->objRefCount++;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_FontId --
+ *
+ * Given a font, return an opaque handle that should be selected into the
+ * XGCValues structure in order to get the constructed gc to use this
+ * font. This function would go away if the XGCValues structure were
+ * replaced with a TkGCValues structure.
+ *
+ * Results:
+ * As above.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Font
+Tk_FontId(
+ Tk_Font tkfont) /* Font that is going to be selected into
+ * GC. */
+{
+ TkFont *fontPtr = (TkFont *) tkfont;
+
+ return fontPtr->fid;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_GetFontMetrics --
+ *
+ * Returns overall ascent and descent metrics for the given font. These
+ * values can be used to space multiple lines of text and to align the
+ * baselines of text in different fonts.
+ *
+ * Results:
+ * If *heightPtr is non-NULL, it is filled with the overall height of the
+ * font, which is the sum of the ascent and descent. If *ascentPtr or
+ * *descentPtr is non-NULL, they are filled with the ascent and/or
+ * descent information for the font.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+Tk_GetFontMetrics(
+ Tk_Font tkfont, /* Font in which metrics are calculated. */
+ Tk_FontMetrics *fmPtr) /* Pointer to structure in which font metrics
+ * for tkfont will be stored. */
+{
+ TkFont *fontPtr = (TkFont *) tkfont;
+
+ fmPtr->ascent = fontPtr->fm.ascent;
+ fmPtr->descent = fontPtr->fm.descent;
+ fmPtr->linespace = fontPtr->fm.ascent + fontPtr->fm.descent;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_PostscriptFontName --
+ *
+ * Given a Tk_Font, return the name of the corresponding Postscript font.
+ *
+ * Results:
+ * The return value is the pointsize of the given Tk_Font. The name of
+ * the Postscript font is appended to dsPtr.
+ *
+ * Side effects:
+ * If the font does not exist on the printer, the print job will fail at
+ * print time. Given a "reasonable" Postscript printer, the following
+ * Tk_Font font families should print correctly:
+ *
+ * Avant Garde, Arial, Bookman, Courier, Courier New, Geneva,
+ * Helvetica, Monaco, New Century Schoolbook, New York,
+ * Palatino, Symbol, Times, Times New Roman, Zapf Chancery,
+ * and Zapf Dingbats.
+ *
+ * Any other Tk_Font font families may not print correctly because the
+ * computed Postscript font name may be incorrect.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+Tk_PostscriptFontName(
+ Tk_Font tkfont, /* Font in which text will be printed. */
+ Tcl_DString *dsPtr) /* Pointer to an initialized Tcl_DString to
+ * which the name of the Postscript font that
+ * corresponds to tkfont will be appended. */
+{
+ TkFont *fontPtr = (TkFont *) tkfont;
+ Tk_Uid family, weightString, slantString;
+ char *src, *dest;
+ int upper, len;
+
+ len = Tcl_DStringLength(dsPtr);
+
+ /*
+ * Convert the case-insensitive Tk_Font family name to the case-sensitive
+ * Postscript family name. Take out any spaces and capitalize the first
+ * letter of each word.
+ */
+
+ family = fontPtr->fa.family;
+ if (strncasecmp(family, "itc ", 4) == 0) {
+ family = family + 4;
+ }
+ if ((strcasecmp(family, "Arial") == 0)
+ || (strcasecmp(family, "Geneva") == 0)) {
+ family = "Helvetica";
+ } else if ((strcasecmp(family, "Times New Roman") == 0)
+ || (strcasecmp(family, "New York") == 0)) {
+ family = "Times";
+ } else if ((strcasecmp(family, "Courier New") == 0)
+ || (strcasecmp(family, "Monaco") == 0)) {
+ family = "Courier";
+ } else if (strcasecmp(family, "AvantGarde") == 0) {
+ family = "AvantGarde";
+ } else if (strcasecmp(family, "ZapfChancery") == 0) {
+ family = "ZapfChancery";
+ } else if (strcasecmp(family, "ZapfDingbats") == 0) {
+ family = "ZapfDingbats";
+ } else {
+ int ch;
+
+ /*
+ * Inline, capitalize the first letter of each word, lowercase the
+ * rest of the letters in each word, and then take out the spaces
+ * between the words. This may make the DString shorter, which is safe
+ * to do.
+ */
+
+ Tcl_DStringAppend(dsPtr, family, -1);
+
+ src = dest = Tcl_DStringValue(dsPtr) + len;
+ upper = 1;
+ for (; *src != '\0'; ) {
+ while (isspace(UCHAR(*src))) { /* INTL: ISO space */
+ src++;
+ upper = 1;
+ }
+ src += TkUtfToUniChar(src, &ch);
+ if (ch <= 0xffff) {
+ if (upper) {
+ ch = Tcl_UniCharToUpper(ch);
+ upper = 0;
+ } else {
+ ch = Tcl_UniCharToLower(ch);
+ }
+ } else {
+ upper = 0;
+ }
+ dest += TkUniCharToUtf(ch, dest);
+ }
+ *dest = '\0';
+ Tcl_DStringSetLength(dsPtr, dest - Tcl_DStringValue(dsPtr));
+ family = Tcl_DStringValue(dsPtr) + len;
+ }
+ if (family != Tcl_DStringValue(dsPtr) + len) {
+ Tcl_DStringAppend(dsPtr, family, -1);
+ family = Tcl_DStringValue(dsPtr) + len;
+ }
+
+ if (strcasecmp(family, "NewCenturySchoolbook") == 0) {
+ Tcl_DStringSetLength(dsPtr, len);
+ Tcl_DStringAppend(dsPtr, "NewCenturySchlbk", -1);
+ family = Tcl_DStringValue(dsPtr) + len;
+ }
+
+ /*
+ * Get the string to use for the weight.
+ */
+
+ weightString = NULL;
+ if (fontPtr->fa.weight == TK_FW_NORMAL) {
+ if (strcmp(family, "Bookman") == 0) {
+ weightString = "Light";
+ } else if (strcmp(family, "AvantGarde") == 0) {
+ weightString = "Book";
+ } else if (strcmp(family, "ZapfChancery") == 0) {
+ weightString = "Medium";
+ }
+ } else {
+ if ((strcmp(family, "Bookman") == 0)
+ || (strcmp(family, "AvantGarde") == 0)) {
+ weightString = "Demi";
+ } else {
+ weightString = "Bold";
+ }
+ }
+
+ /*
+ * Get the string to use for the slant.
+ */
+
+ slantString = NULL;
+ if (fontPtr->fa.slant == TK_FS_ROMAN) {
+ /* Do nothing */
+ } else if ((strcmp(family, "Helvetica") == 0)
+ || (strcmp(family, "Courier") == 0)
+ || (strcmp(family, "AvantGarde") == 0)) {
+ slantString = "Oblique";
+ } else {
+ slantString = "Italic";
+ }
+
+ /*
+ * The string "Roman" needs to be added to some fonts that are not bold
+ * and not italic.
+ */
+
+ if ((slantString == NULL) && (weightString == NULL)) {
+ if ((strcmp(family, "Times") == 0)
+ || (strcmp(family, "NewCenturySchlbk") == 0)
+ || (strcmp(family, "Palatino") == 0)) {
+ Tcl_DStringAppend(dsPtr, "-Roman", -1);
+ }
+ } else {
+ Tcl_DStringAppend(dsPtr, "-", -1);
+ if (weightString != NULL) {
+ Tcl_DStringAppend(dsPtr, weightString, -1);
+ }
+ if (slantString != NULL) {
+ Tcl_DStringAppend(dsPtr, slantString, -1);
+ }
+ }
+
+ return (int)(fontPtr->fa.size + 0.5);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_TextWidth --
+ *
+ * A wrapper function for the more complicated interface of
+ * Tk_MeasureChars. Computes how much space the given simple string
+ * needs.
+ *
+ * Results:
+ * The return value is the width (in pixels) of the given string.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+Tk_TextWidth(
+ Tk_Font tkfont, /* Font in which text will be measured. */
+ const char *string, /* String whose width will be computed. */
+ int numBytes) /* Number of bytes to consider from string, or
+ * < 0 for strlen(). */
+{
+ int width;
+
+ if (numBytes < 0) {
+ numBytes = strlen(string);
+ }
+ Tk_MeasureChars(tkfont, string, numBytes, -1, 0, &width);
+ return width;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_UnderlineChars, TkUnderlineCharsInContext --
+ *
+ * These procedures draw an underline for a given range of characters in
+ * a given string. They don't draw the characters (which are assumed to
+ * have been displayed previously); they just draw the underline. These
+ * procedures would mainly be used to quickly underline a few characters
+ * without having to construct an underlined font. To produce properly
+ * underlined text, the appropriate underlined font should be constructed
+ * and used.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Information gets displayed in "drawable".
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_UnderlineChars(
+ Display *display, /* Display on which to draw. */
+ Drawable drawable, /* Window or pixmap in which to draw. */
+ GC gc, /* Graphics context for actually drawing
+ * line. */
+ Tk_Font tkfont, /* Font used in GC; must have been allocated
+ * by Tk_GetFont(). Used for character
+ * dimensions, etc. */
+ const char *string, /* String containing characters to be
+ * underlined or overstruck. */
+ int x, int y, /* Coordinates at which first character of
+ * string is drawn. */
+ int firstByte, /* Index of first byte of first character. */
+ int lastByte) /* Index of first byte after the last
+ * character. */
+{
+ TkUnderlineCharsInContext(display, drawable, gc, tkfont, string,
+ lastByte, x, y, firstByte, lastByte);
+}
+
+void
+TkUnderlineCharsInContext(
+ Display *display, /* Display on which to draw. */
+ Drawable drawable, /* Window or pixmap in which to draw. */
+ GC gc, /* Graphics context for actually drawing
+ * line. */
+ Tk_Font tkfont, /* Font used in GC; must have been allocated
+ * by Tk_GetFont(). Used for character
+ * dimensions, etc. */
+ const char *string, /* String containing characters to be
+ * underlined or overstruck. */
+ int numBytes, /* Number of bytes in string. */
+ int x, int y, /* Coordinates at which the first character of
+ * the whole string would be drawn. */
+ int firstByte, /* Index of first byte of first character. */
+ int lastByte) /* Index of first byte after the last
+ * character. */
+{
+ TkFont *fontPtr = (TkFont *) tkfont;
+ int startX, endX;
+
+ TkpMeasureCharsInContext(tkfont, string, numBytes, 0, firstByte, -1, 0,
+ &startX);
+ TkpMeasureCharsInContext(tkfont, string, numBytes, 0, lastByte, -1, 0,
+ &endX);
+
+ XFillRectangle(display, drawable, gc, x + startX,
+ y + fontPtr->underlinePos, (unsigned) (endX - startX),
+ (unsigned) fontPtr->underlineHeight);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_ComputeTextLayout --
+ *
+ * Computes the amount of screen space needed to display a multi-line,
+ * justified string of text. Records all the measurements that were done
+ * to determine to size and positioning of the individual lines of text;
+ * this information can be used by the Tk_DrawTextLayout() function to
+ * display the text quickly (without remeasuring it).
+ *
+ * This function is useful for simple widgets that want to display
+ * single-font, multi-line text and want Tk to handle the details.
+ *
+ * Results:
+ * The return value is a Tk_TextLayout token that holds the measurement
+ * information for the given string. The token is only valid for the
+ * given string. If the string is freed, the token is no longer valid and
+ * must also be freed. To free the token, call Tk_FreeTextLayout().
+ *
+ * The dimensions of the screen area needed to display the text are
+ * stored in *widthPtr and *heightPtr.
+ *
+ * Side effects:
+ * Memory is allocated to hold the measurement information.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tk_TextLayout
+Tk_ComputeTextLayout(
+ Tk_Font tkfont, /* Font that will be used to display text. */
+ const char *string, /* String whose dimensions are to be
+ * computed. */
+ int numChars, /* Number of characters to consider from
+ * string, or < 0 for strlen(). */
+ int wrapLength, /* Longest permissible line length, in pixels.
+ * <= 0 means no automatic wrapping: just let
+ * lines get as long as needed. */
+ Tk_Justify justify, /* How to justify lines. */
+ int flags, /* Flag bits OR-ed together. TK_IGNORE_TABS
+ * means that tab characters should not be
+ * expanded. TK_IGNORE_NEWLINES means that
+ * newline characters should not cause a line
+ * break. */
+ int *widthPtr, /* Filled with width of string. */
+ int *heightPtr) /* Filled with height of string. */
+{
+ TkFont *fontPtr = (TkFont *) tkfont;
+ const char *start, *end, *special;
+ int n, y, bytesThisChunk, maxChunks, curLine, layoutHeight;
+ int baseline, height, curX, newX, maxWidth, *lineLengths;
+ TextLayout *layoutPtr;
+ LayoutChunk *chunkPtr;
+ const TkFontMetrics *fmPtr;
+ Tcl_DString lineBuffer;
+
+ Tcl_DStringInit(&lineBuffer);
+
+ if ((fontPtr == NULL) || (string == NULL)) {
+ if (widthPtr != NULL) {
+ *widthPtr = 0;
+ }
+ if (heightPtr != NULL) {
+ *heightPtr = 0;
+ }
+ return NULL;
+ }
+
+ fmPtr = &fontPtr->fm;
+
+ height = fmPtr->ascent + fmPtr->descent;
+
+ if (numChars < 0) {
+ numChars = Tcl_NumUtfChars(string, -1);
+ }
+ if (wrapLength == 0) {
+ wrapLength = -1;
+ }
+
+ maxChunks = 1;
+
+ layoutPtr = ckalloc(sizeof(TextLayout)
+ + (maxChunks-1) * sizeof(LayoutChunk));
+ layoutPtr->tkfont = tkfont;
+ layoutPtr->string = string;
+ layoutPtr->numChunks = 0;
+
+ baseline = fmPtr->ascent;
+ maxWidth = 0;
+
+ /*
+ * Divide the string up into simple strings and measure each string.
+ */
+
+ curX = 0;
+
+ end = Tcl_UtfAtIndex(string, numChars);
+ special = string;
+
+ flags &= TK_IGNORE_TABS | TK_IGNORE_NEWLINES;
+ flags |= TK_WHOLE_WORDS | TK_AT_LEAST_ONE;
+ for (start = string; start < end; ) {
+ if (start >= special) {
+ /*
+ * Find the next special character in the string.
+ *
+ * INTL: Note that it is safe to increment by byte, because we are
+ * looking for 7-bit characters that will appear unchanged in
+ * UTF-8. At some point we may need to support the full Unicode
+ * whitespace set.
+ */
+
+ for (special = start; special < end; special++) {
+ if (!(flags & TK_IGNORE_NEWLINES)) {
+ if ((*special == '\n') || (*special == '\r')) {
+ break;
+ }
+ }
+ if (!(flags & TK_IGNORE_TABS)) {
+ if (*special == '\t') {
+ break;
+ }
+ }
+ }
+ }
+
+ /*
+ * Special points at the next special character (or the end of the
+ * string). Process characters between start and special.
+ */
+
+ chunkPtr = NULL;
+ if (start < special) {
+ bytesThisChunk = Tk_MeasureChars(tkfont, start, special - start,
+ wrapLength - curX, flags, &newX);
+ newX += curX;
+ flags &= ~TK_AT_LEAST_ONE;
+ if (bytesThisChunk > 0) {
+ chunkPtr = NewChunk(&layoutPtr, &maxChunks, start,
+ bytesThisChunk, curX, newX, baseline);
+
+ start += bytesThisChunk;
+ curX = newX;
+ }
+ }
+
+ if ((start == special) && (special < end)) {
+ /*
+ * Handle the special character.
+ *
+ * INTL: Special will be pointing at a 7-bit character so we can
+ * safely treat it as a single byte.
+ */
+
+ chunkPtr = NULL;
+ if (*special == '\t') {
+ newX = curX + fontPtr->tabWidth;
+ newX -= newX % fontPtr->tabWidth;
+ NewChunk(&layoutPtr, &maxChunks, start, 1, curX, newX,
+ baseline)->numDisplayChars = -1;
+ start++;
+ curX = newX;
+ flags &= ~TK_AT_LEAST_ONE;
+ if ((start < end) &&
+ ((wrapLength <= 0) || (newX <= wrapLength))) {
+ /*
+ * More chars can still fit on this line.
+ */
+
+ continue;
+ }
+ } else {
+ NewChunk(&layoutPtr, &maxChunks, start, 1, curX, curX,
+ baseline)->numDisplayChars = -1;
+ start++;
+ goto wrapLine;
+ }
+ }
+
+ /*
+ * No more characters are going to go on this line, either because no
+ * more characters can fit or there are no more characters left.
+ * Consume all extra spaces at end of line.
+ */
+
+ while ((start < end) && isspace(UCHAR(*start))) { /* INTL: ISO space */
+ if (!(flags & TK_IGNORE_NEWLINES)) {
+ if ((*start == '\n') || (*start == '\r')) {
+ break;
+ }
+ }
+ if (!(flags & TK_IGNORE_TABS)) {
+ if (*start == '\t') {
+ break;
+ }
+ }
+ start++;
+ }
+ if (chunkPtr != NULL) {
+ const char *end;
+
+ /*
+ * Append all the extra spaces on this line to the end of the last
+ * text chunk. This is a little tricky because we are switching
+ * back and forth between characters and bytes.
+ */
+
+ end = chunkPtr->start + chunkPtr->numBytes;
+ bytesThisChunk = start - end;
+ if (bytesThisChunk > 0) {
+ bytesThisChunk = Tk_MeasureChars(tkfont, end, bytesThisChunk,
+ -1, 0, &chunkPtr->totalWidth);
+ chunkPtr->numBytes += bytesThisChunk;
+ chunkPtr->numChars += Tcl_NumUtfChars(end, bytesThisChunk);
+ chunkPtr->totalWidth += curX;
+ }
+ }
+
+ wrapLine:
+ flags |= TK_AT_LEAST_ONE;
+
+ /*
+ * Save current line length, then move current position to start of
+ * next line.
+ */
+
+ if (curX > maxWidth) {
+ maxWidth = curX;
+ }
+
+ /*
+ * Remember width of this line, so that all chunks on this line can be
+ * centered or right justified, if necessary.
+ */
+
+ Tcl_DStringAppend(&lineBuffer, (char *) &curX, sizeof(curX));
+
+ curX = 0;
+ baseline += height;
+ }
+
+ /*
+ * If last line ends with a newline, then we need to make a 0 width chunk
+ * on the next line. Otherwise "Hello" and "Hello\n" are the same height.
+ */
+
+ if ((layoutPtr->numChunks > 0) && !(flags & TK_IGNORE_NEWLINES)) {
+ if (layoutPtr->chunks[layoutPtr->numChunks - 1].start[0] == '\n') {
+ chunkPtr = NewChunk(&layoutPtr, &maxChunks, start, 0, curX,
+ curX, baseline);
+ chunkPtr->numDisplayChars = -1;
+ Tcl_DStringAppend(&lineBuffer, (char *) &curX, sizeof(curX));
+ baseline += height;
+ }
+ }
+
+ layoutPtr->width = maxWidth;
+ layoutHeight = baseline - fmPtr->ascent;
+ if (layoutPtr->numChunks == 0) {
+ layoutHeight = height;
+
+ /*
+ * This fake chunk is used by the other functions so that they can
+ * pretend that there is a chunk with no chars in it, which makes the
+ * coding simpler.
+ */
+
+ layoutPtr->numChunks = 1;
+ layoutPtr->chunks[0].start = string;
+ layoutPtr->chunks[0].numBytes = 0;
+ layoutPtr->chunks[0].numChars = 0;
+ layoutPtr->chunks[0].numDisplayChars = -1;
+ layoutPtr->chunks[0].x = 0;
+ layoutPtr->chunks[0].y = fmPtr->ascent;
+ layoutPtr->chunks[0].totalWidth = 0;
+ layoutPtr->chunks[0].displayWidth = 0;
+ } else {
+ /*
+ * Using maximum line length, shift all the chunks so that the lines
+ * are all justified correctly.
+ */
+
+ curLine = 0;
+ chunkPtr = layoutPtr->chunks;
+ y = chunkPtr->y;
+ lineLengths = (int *) Tcl_DStringValue(&lineBuffer);
+ for (n = 0; n < layoutPtr->numChunks; n++) {
+ int extra;
+
+ if (chunkPtr->y != y) {
+ curLine++;
+ y = chunkPtr->y;
+ }
+ extra = maxWidth - lineLengths[curLine];
+ if (justify == TK_JUSTIFY_CENTER) {
+ chunkPtr->x += extra / 2;
+ } else if (justify == TK_JUSTIFY_RIGHT) {
+ chunkPtr->x += extra;
+ }
+ chunkPtr++;
+ }
+ }
+
+ if (widthPtr != NULL) {
+ *widthPtr = layoutPtr->width;
+ }
+ if (heightPtr != NULL) {
+ *heightPtr = layoutHeight;
+ }
+ Tcl_DStringFree(&lineBuffer);
+
+ return (Tk_TextLayout) layoutPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_FreeTextLayout --
+ *
+ * This function is called to release the storage associated with a
+ * Tk_TextLayout when it is no longer needed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory is freed.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+Tk_FreeTextLayout(
+ Tk_TextLayout textLayout) /* The text layout to be released. */
+{
+ TextLayout *layoutPtr = (TextLayout *) textLayout;
+
+ if (layoutPtr != NULL) {
+ ckfree(layoutPtr);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_DrawTextLayout --
+ *
+ * Use the information in the Tk_TextLayout token to display a
+ * multi-line, justified string of text.
+ *
+ * This function is useful for simple widgets that need to display
+ * single-font, multi-line text and want Tk to handle the details.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Text drawn on the screen.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+Tk_DrawTextLayout(
+ Display *display, /* Display on which to draw. */
+ Drawable drawable, /* Window or pixmap in which to draw. */
+ GC gc, /* Graphics context to use for drawing
+ * text. */
+ Tk_TextLayout layout, /* Layout information, from a previous call to
+ * Tk_ComputeTextLayout(). */
+ int x, int y, /* Upper-left hand corner of rectangle in
+ * which to draw (pixels). */
+ int firstChar, /* The index of the first character to draw
+ * from the given text item. 0 specfies the
+ * beginning. */
+ int lastChar) /* The index just after the last character to
+ * draw from the given text item. A number < 0
+ * means to draw all characters. */
+{
+ TextLayout *layoutPtr = (TextLayout *) layout;
+ int i, numDisplayChars, drawX;
+ const char *firstByte, *lastByte;
+ LayoutChunk *chunkPtr;
+
+ if (layoutPtr == NULL) {
+ return;
+ }
+
+ if (lastChar < 0) {
+ lastChar = 100000000;
+ }
+ chunkPtr = layoutPtr->chunks;
+ for (i = 0; i < layoutPtr->numChunks; i++) {
+ numDisplayChars = chunkPtr->numDisplayChars;
+ if ((numDisplayChars > 0) && (firstChar < numDisplayChars)) {
+ if (firstChar <= 0) {
+ drawX = 0;
+ firstChar = 0;
+ firstByte = chunkPtr->start;
+ } else {
+ firstByte = Tcl_UtfAtIndex(chunkPtr->start, firstChar);
+ Tk_MeasureChars(layoutPtr->tkfont, chunkPtr->start,
+ firstByte - chunkPtr->start, -1, 0, &drawX);
+ }
+ if (lastChar < numDisplayChars) {
+ numDisplayChars = lastChar;
+ }
+ lastByte = Tcl_UtfAtIndex(chunkPtr->start, numDisplayChars);
+ Tk_DrawChars(display, drawable, gc, layoutPtr->tkfont, firstByte,
+ lastByte - firstByte, x+chunkPtr->x+drawX, y+chunkPtr->y);
+ }
+ firstChar -= chunkPtr->numChars;
+ lastChar -= chunkPtr->numChars;
+ if (lastChar <= 0) {
+ break;
+ }
+ chunkPtr++;
+ }
+}
+
+void
+TkDrawAngledTextLayout(
+ Display *display, /* Display on which to draw. */
+ Drawable drawable, /* Window or pixmap in which to draw. */
+ GC gc, /* Graphics context to use for drawing
+ * text. */
+ Tk_TextLayout layout, /* Layout information, from a previous call to
+ * Tk_ComputeTextLayout(). */
+ int x, int y, /* Upper-left hand corner of rectangle in
+ * which to draw (pixels). */
+ double angle,
+ int firstChar, /* The index of the first character to draw
+ * from the given text item. 0 specfies the
+ * beginning. */
+ int lastChar) /* The index just after the last character to
+ * draw from the given text item. A number < 0
+ * means to draw all characters. */
+{
+ TextLayout *layoutPtr = (TextLayout *) layout;
+ int i, numDisplayChars, drawX;
+ const char *firstByte, *lastByte;
+ LayoutChunk *chunkPtr;
+ double sinA = sin(angle * PI/180.0), cosA = cos(angle * PI/180.0);
+
+ if (layoutPtr == NULL) {
+ return;
+ }
+
+ if (lastChar < 0) {
+ lastChar = 100000000;
+ }
+ chunkPtr = layoutPtr->chunks;
+ for (i = 0; i < layoutPtr->numChunks; i++) {
+ numDisplayChars = chunkPtr->numDisplayChars;
+ if ((numDisplayChars > 0) && (firstChar < numDisplayChars)) {
+ double dx, dy;
+
+ if (firstChar <= 0) {
+ drawX = 0;
+ firstChar = 0;
+ firstByte = chunkPtr->start;
+ } else {
+ firstByte = Tcl_UtfAtIndex(chunkPtr->start, firstChar);
+ Tk_MeasureChars(layoutPtr->tkfont, chunkPtr->start,
+ firstByte - chunkPtr->start, -1, 0, &drawX);
+ }
+ if (lastChar < numDisplayChars) {
+ numDisplayChars = lastChar;
+ }
+ lastByte = Tcl_UtfAtIndex(chunkPtr->start, numDisplayChars);
+ dx = cosA * (chunkPtr->x + drawX) + sinA * (chunkPtr->y);
+ dy = -sinA * (chunkPtr->x + drawX) + cosA * (chunkPtr->y);
+ if (angle == 0.0) {
+ Tk_DrawChars(display, drawable, gc, layoutPtr->tkfont,
+ firstByte, lastByte - firstByte,
+ (int)(x + dx), (int)(y + dy));
+ } else {
+ TkDrawAngledChars(display, drawable, gc, layoutPtr->tkfont,
+ firstByte, lastByte - firstByte, x+dx, y+dy, angle);
+ }
+ }
+ firstChar -= chunkPtr->numChars;
+ lastChar -= chunkPtr->numChars;
+ if (lastChar <= 0) {
+ break;
+ }
+ chunkPtr++;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_UnderlineTextLayout --
+ *
+ * Use the information in the Tk_TextLayout token to display an underline
+ * below an individual character. This function does not draw the text,
+ * just the underline.
+ *
+ * This function is useful for simple widgets that need to display
+ * single-font, multi-line text with an individual character underlined
+ * and want Tk to handle the details. To display larger amounts of
+ * underlined text, construct and use an underlined font.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Underline drawn on the screen.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+Tk_UnderlineTextLayout(
+ Display *display, /* Display on which to draw. */
+ Drawable drawable, /* Window or pixmap in which to draw. */
+ GC gc, /* Graphics context to use for drawing text. */
+ Tk_TextLayout layout, /* Layout information, from a previous call to
+ * Tk_ComputeTextLayout(). */
+ int x, int y, /* Upper-left hand corner of rectangle in
+ * which to draw (pixels). */
+ int underline) /* Index of the single character to underline,
+ * or -1 for no underline. */
+{
+ int xx, yy, width, height;
+
+ if ((Tk_CharBbox(layout, underline, &xx, &yy, &width, &height) != 0)
+ && (width != 0)) {
+ TextLayout *layoutPtr = (TextLayout *) layout;
+ TkFont *fontPtr = (TkFont *) layoutPtr->tkfont;
+
+ XFillRectangle(display, drawable, gc, x + xx,
+ y + yy + fontPtr->fm.ascent + fontPtr->underlinePos,
+ (unsigned) width, (unsigned) fontPtr->underlineHeight);
+ }
+}
+
+void
+TkUnderlineAngledTextLayout(
+ Display *display, /* Display on which to draw. */
+ Drawable drawable, /* Window or pixmap in which to draw. */
+ GC gc, /* Graphics context to use for drawing
+ * text. */
+ Tk_TextLayout layout, /* Layout information, from a previous call to
+ * Tk_ComputeTextLayout(). */
+ int x, int y, /* Upper-left hand corner of rectangle in
+ * which to draw (pixels). */
+ double angle,
+ int underline) /* Index of the single character to underline,
+ * or -1 for no underline. */
+{
+ int xx, yy, width, height;
+
+ if (angle == 0.0) {
+ Tk_UnderlineTextLayout(display, drawable, gc, layout, x,y, underline);
+ return;
+ }
+
+ if ((Tk_CharBbox(layout, underline, &xx, &yy, &width, &height) != 0)
+ && (width != 0)) {
+ TextLayout *layoutPtr = (TextLayout *) layout;
+ TkFont *fontPtr = (TkFont *) layoutPtr->tkfont;
+ double sinA = sin(angle*PI/180), cosA = cos(angle*PI/180);
+ double dy = yy + fontPtr->fm.ascent + fontPtr->underlinePos;
+ XPoint points[5];
+
+ /*
+ * Note that we're careful to only round a double value once, which
+ * minimizes roundoff errors.
+ */
+
+ points[0].x = x + ROUND16(xx*cosA + dy*sinA);
+ points[0].y = y + ROUND16(dy*cosA - xx*sinA);
+ points[1].x = x + ROUND16(xx*cosA + dy*sinA + width*cosA);
+ points[1].y = y + ROUND16(dy*cosA - xx*sinA - width*sinA);
+ if (fontPtr->underlineHeight == 1) {
+ /*
+ * Thin underlines look better when rotated when drawn as a line
+ * rather than a rectangle; the rasterizer copes better.
+ */
+
+ XDrawLines(display, drawable, gc, points, 2, CoordModeOrigin);
+ } else {
+ points[2].x = x + ROUND16(xx*cosA + dy*sinA + width*cosA
+ + fontPtr->underlineHeight*sinA);
+ points[2].y = y + ROUND16(dy*cosA - xx*sinA - width*sinA
+ + fontPtr->underlineHeight*cosA);
+ points[3].x = x + ROUND16(xx*cosA + dy*sinA
+ + fontPtr->underlineHeight*sinA);
+ points[3].y = y + ROUND16(dy*cosA - xx*sinA
+ + fontPtr->underlineHeight*cosA);
+ points[4].x = points[0].x;
+ points[4].y = points[0].y;
+ XFillPolygon(display, drawable, gc, points, 5, Complex,
+ CoordModeOrigin);
+ XDrawLines(display, drawable, gc, points, 5, CoordModeOrigin);
+ }
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_PointToChar --
+ *
+ * Use the information in the Tk_TextLayout token to determine the
+ * character closest to the given point. The point must be specified with
+ * respect to the upper-left hand corner of the text layout, which is
+ * considered to be located at (0, 0).
+ *
+ * Any point whose y-value is less that 0 will be considered closest to
+ * the first character in the text layout; any point whose y-value is
+ * greater than the height of the text layout will be considered closest
+ * to the last character in the text layout.
+ *
+ * Any point whose x-value is less than 0 will be considered closest to
+ * the first character on that line; any point whose x-value is greater
+ * than the width of the text layout will be considered closest to the
+ * last character on that line.
+ *
+ * Results:
+ * The return value is the index of the character that was closest to the
+ * point. Given a text layout with no characters, the value 0 will always
+ * be returned, referring to a hypothetical zero-width placeholder
+ * character.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+Tk_PointToChar(
+ Tk_TextLayout layout, /* Layout information, from a previous call to
+ * Tk_ComputeTextLayout(). */
+ int x, int y) /* Coordinates of point to check, with respect
+ * to the upper-left corner of the text
+ * layout. */
+{
+ TextLayout *layoutPtr = (TextLayout *) layout;
+ LayoutChunk *chunkPtr, *lastPtr;
+ TkFont *fontPtr;
+ int i, n, dummy, baseline, pos, numChars;
+
+ if (y < 0) {
+ /*
+ * Point lies above any line in this layout. Return the index of the
+ * first char.
+ */
+
+ return 0;
+ }
+
+ /*
+ * Find which line contains the point.
+ */
+
+ fontPtr = (TkFont *) layoutPtr->tkfont;
+ lastPtr = chunkPtr = layoutPtr->chunks;
+ numChars = 0;
+ for (i = 0; i < layoutPtr->numChunks; i++) {
+ baseline = chunkPtr->y;
+ if (y < baseline + fontPtr->fm.descent) {
+ if (x < chunkPtr->x) {
+ /*
+ * Point is to the left of all chunks on this line. Return the
+ * index of the first character on this line.
+ */
+
+ return numChars;
+ }
+ if (x >= layoutPtr->width) {
+ /*
+ * If point lies off right side of the text layout, return the
+ * last char in the last chunk on this line. Without this, it
+ * might return the index of the first char that was located
+ * outside of the text layout.
+ */
+
+ x = INT_MAX;
+ }
+
+ /*
+ * Examine all chunks on this line to see which one contains the
+ * specified point.
+ */
+
+ lastPtr = chunkPtr;
+ while ((i < layoutPtr->numChunks) && (chunkPtr->y == baseline)) {
+ if (x < chunkPtr->x + chunkPtr->totalWidth) {
+ /*
+ * Point falls on one of the characters in this chunk.
+ */
+
+ if (chunkPtr->numDisplayChars < 0) {
+ /*
+ * This is a special chunk that encapsulates a single
+ * tab or newline char.
+ */
+
+ return numChars;
+ }
+ n = Tk_MeasureChars((Tk_Font) fontPtr, chunkPtr->start,
+ chunkPtr->numBytes, x - chunkPtr->x, 0, &dummy);
+ return numChars + Tcl_NumUtfChars(chunkPtr->start, n);
+ }
+ numChars += chunkPtr->numChars;
+ lastPtr = chunkPtr;
+ chunkPtr++;
+ i++;
+ }
+
+ /*
+ * Point is to the right of all chars in all the chunks on this
+ * line. Return the index just past the last char in the last
+ * chunk on this line.
+ */
+
+ pos = numChars;
+ if (i < layoutPtr->numChunks) {
+ pos--;
+ }
+ return pos;
+ }
+ numChars += chunkPtr->numChars;
+ lastPtr = chunkPtr;
+ chunkPtr++;
+ }
+
+ /*
+ * Point lies below any line in this text layout. Return the index just
+ * past the last char.
+ */
+
+ return (lastPtr->start + lastPtr->numChars) - layoutPtr->string;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_CharBbox --
+ *
+ * Use the information in the Tk_TextLayout token to return the bounding
+ * box for the character specified by index.
+ *
+ * The width of the bounding box is the advance width of the character,
+ * and does not include and left- or right-bearing. Any character that
+ * extends partially outside of the text layout is considered to be
+ * truncated at the edge. Any character which is located completely
+ * outside of the text layout is considered to be zero-width and pegged
+ * against the edge.
+ *
+ * The height of the bounding box is the line height for this font,
+ * extending from the top of the ascent to the bottom of the descent.
+ * Information about the actual height of the individual letter is not
+ * available.
+ *
+ * A text layout that contains no characters is considered to contain a
+ * single zero-width placeholder character.
+ *
+ * Results:
+ * The return value is 0 if the index did not specify a character in the
+ * text layout, or non-zero otherwise. In that case, *bbox is filled with
+ * the bounding box of the character.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+Tk_CharBbox(
+ Tk_TextLayout layout, /* Layout information, from a previous call to
+ * Tk_ComputeTextLayout(). */
+ int index, /* The index of the character whose bbox is
+ * desired. */
+ int *xPtr, int *yPtr, /* Filled with the upper-left hand corner, in
+ * pixels, of the bounding box for the
+ * character specified by index, if
+ * non-NULL. */
+ int *widthPtr, int *heightPtr)
+ /* Filled with the width and height of the
+ * bounding box for the character specified by
+ * index, if non-NULL. */
+{
+ TextLayout *layoutPtr = (TextLayout *) layout;
+ LayoutChunk *chunkPtr;
+ int i, x = 0, w;
+ Tk_Font tkfont;
+ TkFont *fontPtr;
+ const char *end;
+
+ if (index < 0) {
+ return 0;
+ }
+
+ chunkPtr = layoutPtr->chunks;
+ tkfont = layoutPtr->tkfont;
+ fontPtr = (TkFont *) tkfont;
+
+ for (i = 0; i < layoutPtr->numChunks; i++) {
+ if (chunkPtr->numDisplayChars < 0) {
+ if (index == 0) {
+ x = chunkPtr->x;
+ w = chunkPtr->totalWidth;
+ goto check;
+ }
+ } else if (index < chunkPtr->numChars) {
+ end = Tcl_UtfAtIndex(chunkPtr->start, index);
+ if (xPtr != NULL) {
+ Tk_MeasureChars(tkfont, chunkPtr->start,
+ end - chunkPtr->start, -1, 0, &x);
+ x += chunkPtr->x;
+ }
+ if (widthPtr != NULL) {
+ Tk_MeasureChars(tkfont, end, Tcl_UtfNext(end) - end,
+ -1, 0, &w);
+ }
+ goto check;
+ }
+ index -= chunkPtr->numChars;
+ chunkPtr++;
+ }
+ if (index != 0) {
+ return 0;
+ }
+
+ /*
+ * Special case to get location just past last char in layout.
+ */
+
+ chunkPtr--;
+ x = chunkPtr->x + chunkPtr->totalWidth;
+ w = 0;
+
+ /*
+ * Ensure that the bbox lies within the text layout. This forces all chars
+ * that extend off the right edge of the text layout to have truncated
+ * widths, and all chars that are completely off the right edge of the
+ * text layout to peg to the edge and have 0 width.
+ */
+
+ check:
+ if (yPtr != NULL) {
+ *yPtr = chunkPtr->y - fontPtr->fm.ascent;
+ }
+ if (heightPtr != NULL) {
+ *heightPtr = fontPtr->fm.ascent + fontPtr->fm.descent;
+ }
+
+ if (x > layoutPtr->width) {
+ x = layoutPtr->width;
+ }
+ if (xPtr != NULL) {
+ *xPtr = x;
+ }
+ if (widthPtr != NULL) {
+ if (x + w > layoutPtr->width) {
+ w = layoutPtr->width - x;
+ }
+ *widthPtr = w;
+ }
+
+ return 1;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_DistanceToTextLayout --
+ *
+ * Computes the distance in pixels from the given point to the given text
+ * layout. Non-displaying space characters that occur at the end of
+ * individual lines in the text layout are ignored for hit detection
+ * purposes.
+ *
+ * Results:
+ * The return value is 0 if the point (x, y) is inside the text layout.
+ * If the point isn't inside the text layout then the return value is the
+ * distance in pixels from the point to the text item.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+Tk_DistanceToTextLayout(
+ Tk_TextLayout layout, /* Layout information, from a previous call
+ * to Tk_ComputeTextLayout(). */
+ int x, int y) /* Coordinates of point to check, with respect
+ * to the upper-left corner of the text layout
+ * (in pixels). */
+{
+ int i, x1, x2, y1, y2, xDiff, yDiff, dist, minDist, ascent, descent;
+ TextLayout *layoutPtr = (TextLayout *) layout;
+ LayoutChunk *chunkPtr;
+ TkFont *fontPtr;
+
+ fontPtr = (TkFont *) layoutPtr->tkfont;
+ ascent = fontPtr->fm.ascent;
+ descent = fontPtr->fm.descent;
+
+ minDist = 0;
+ chunkPtr = layoutPtr->chunks;
+ for (i = 0; i < layoutPtr->numChunks; i++) {
+ if (chunkPtr->start[0] == '\n') {
+ /*
+ * Newline characters are not counted when computing distance (but
+ * tab characters would still be considered).
+ */
+
+ chunkPtr++;
+ continue;
+ }
+
+ x1 = chunkPtr->x;
+ y1 = chunkPtr->y - ascent;
+ x2 = chunkPtr->x + chunkPtr->displayWidth;
+ y2 = chunkPtr->y + descent;
+
+ if (x < x1) {
+ xDiff = x1 - x;
+ } else if (x >= x2) {
+ xDiff = x - x2 + 1;
+ } else {
+ xDiff = 0;
+ }
+
+ if (y < y1) {
+ yDiff = y1 - y;
+ } else if (y >= y2) {
+ yDiff = y - y2 + 1;
+ } else {
+ yDiff = 0;
+ }
+ if ((xDiff == 0) && (yDiff == 0)) {
+ return 0;
+ }
+ dist = (int) hypot((double) xDiff, (double) yDiff);
+ if ((dist < minDist) || (minDist == 0)) {
+ minDist = dist;
+ }
+ chunkPtr++;
+ }
+ return minDist;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_IntersectTextLayout --
+ *
+ * Determines whether a text layout lies entirely inside, entirely
+ * outside, or overlaps a given rectangle. Non-displaying space
+ * characters that occur at the end of individual lines in the text
+ * layout are ignored for intersection calculations.
+ *
+ * Results:
+ * The return value is -1 if the text layout is entirely outside of the
+ * rectangle, 0 if it overlaps, and 1 if it is entirely inside of the
+ * rectangle.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+Tk_IntersectTextLayout(
+ Tk_TextLayout layout, /* Layout information, from a previous call to
+ * Tk_ComputeTextLayout(). */
+ int x, int y, /* Upper-left hand corner, in pixels, of
+ * rectangular area to compare with text
+ * layout. Coordinates are with respect to the
+ * upper-left hand corner of the text layout
+ * itself. */
+ int width, int height) /* The width and height of the above
+ * rectangular area, in pixels. */
+{
+ int result, i, x1, y1, x2, y2;
+ TextLayout *layoutPtr = (TextLayout *) layout;
+ LayoutChunk *chunkPtr;
+ TkFont *fontPtr;
+ int left, top, right, bottom;
+
+ /*
+ * Scan the chunks one at a time, seeing whether each is entirely in,
+ * entirely out, or overlapping the rectangle. If an overlap is detected,
+ * return immediately; otherwise wait until all chunks have been processed
+ * and see if they were all inside or all outside.
+ */
+
+ chunkPtr = layoutPtr->chunks;
+ fontPtr = (TkFont *) layoutPtr->tkfont;
+
+ left = x;
+ top = y;
+ right = x + width;
+ bottom = y + height;
+
+ result = 0;
+ for (i = 0; i < layoutPtr->numChunks; i++) {
+ if ((chunkPtr->start[0] == '\n') || (chunkPtr->numBytes == 0)) {
+ /*
+ * Newline characters and empty chunks are not counted when
+ * computing area intersection (but tab characters would still be
+ * considered).
+ */
+
+ chunkPtr++;
+ continue;
+ }
+
+ x1 = chunkPtr->x;
+ y1 = chunkPtr->y - fontPtr->fm.ascent;
+ x2 = chunkPtr->x + chunkPtr->displayWidth;
+ y2 = chunkPtr->y + fontPtr->fm.descent;
+
+ if ((right < x1) || (left >= x2)
+ || (bottom < y1) || (top >= y2)) {
+ if (result == 1) {
+ return 0;
+ }
+ result = -1;
+ } else if ((x1 < left) || (x2 >= right)
+ || (y1 < top) || (y2 >= bottom)) {
+ return 0;
+ } else if (result == -1) {
+ return 0;
+ } else {
+ result = 1;
+ }
+ chunkPtr++;
+ }
+ return result;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkIntersectAngledTextLayout --
+ *
+ * Determines whether a text layout that has been turned by an angle
+ * about its top-left coordinae lies entirely inside, entirely outside,
+ * or overlaps a given rectangle. Non-displaying space characters that
+ * occur at the end of individual lines in the text layout are ignored
+ * for intersection calculations.
+ *
+ * Results:
+ * The return value is -1 if the text layout is entirely outside of the
+ * rectangle, 0 if it overlaps, and 1 if it is entirely inside of the
+ * rectangle.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static inline int
+PointInQuadrilateral(
+ double qx[],
+ double qy[],
+ double x,
+ double y)
+{
+ int i;
+
+ for (i=0 ; i<4 ; i++) {
+ double sideDX = qx[(i+1)%4] - qx[i];
+ double sideDY = qy[(i+1)%4] - qy[i];
+ double dx = x - qx[i];
+ double dy = y - qy[i];
+
+ if (sideDX*dy < sideDY*dx) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static inline int
+SidesIntersect(
+ double ax1, double ay1, double ax2, double ay2,
+ double bx1, double by1, double bx2, double by2)
+{
+#if 0
+/* http://www.freelunchdesign.com/cgi-bin/codwiki.pl?DiscussionTopics/CollideMeUpBaby */
+
+ double a1, b1, c1, a2, b2, c2, r1, r2, r3, r4, denom;
+
+ a1 = ay2 - ay1;
+ b1 = ax1 - ax2;
+ c1 = (ax2 * ay1) - (ax1 * ay2);
+ r3 = (a1 * bx1) + (b1 * by1) + c1;
+ r4 = (a1 * bx2) + (b1 * by2) + c1;
+ if ((r3 != 0.0) && (r4 != 0.0) && (r3*r4 > 0.0)) {
+ return 0;
+ }
+
+ a2 = by2 - by1;
+ b2 = bx1 - bx2;
+ c2 = (bx2 * by1) - (bx1 * by2);
+ r1 = (a2 * ax1) + (b2 * ay1) + c2;
+ r2 = (a2 * ax2) + (b2 * ay2) + c2;
+ if ((r1 != 0.0) && (r2 != 0.0) && (r1*r2 > 0.0)) {
+ return 0;
+ }
+
+ denom = (a1 * b2) - (a2 * b1);
+ return (denom != 0.0);
+#else
+ /*
+ * A more efficient version. Two line segments intersect if, when seen
+ * from the perspective of one line, the two endpoints of the other
+ * segment lie on opposite sides of the line, and vice versa. "Lie on
+ * opposite sides" is computed by taking the cross products and seeing if
+ * they are of opposite signs.
+ */
+
+ double dx, dy, dx1, dy1;
+
+ dx = ax2 - ax1;
+ dy = ay2 - ay1;
+ dx1 = bx1 - ax1;
+ dy1 = by1 - ay1;
+ if ((dx*dy1-dy*dx1 > 0.0) == (dx*(by2-ay1)-dy*(bx2-ax1) > 0.0)) {
+ return 0;
+ }
+ dx = bx2 - bx1;
+ dy = by2 - by1;
+ if ((dy*dx1-dx*dy1 > 0.0) == (dx*(ay2-by1)-dy*(ax2-bx1) > 0.0)) {
+ return 0;
+ }
+ return 1;
+#endif
+}
+
+int
+TkIntersectAngledTextLayout(
+ Tk_TextLayout layout, /* Layout information, from a previous call to
+ * Tk_ComputeTextLayout(). */
+ int x, int y, /* Upper-left hand corner, in pixels, of
+ * rectangular area to compare with text
+ * layout. Coordinates are with respect to the
+ * upper-left hand corner of the text layout
+ * itself. */
+ int width, int height, /* The width and height of the above
+ * rectangular area, in pixels. */
+ double angle)
+{
+ int i, x1, y1, x2, y2;
+ TextLayout *layoutPtr;
+ LayoutChunk *chunkPtr;
+ TkFont *fontPtr;
+ double c = cos(angle * PI/180.0), s = sin(angle * PI/180.0);
+ double rx[4], ry[4];
+
+ if (angle == 0.0) {
+ return Tk_IntersectTextLayout(layout, x, y, width, height);
+ }
+
+ /*
+ * Compute the coordinates of the rectangle, rotated into text layout
+ * space.
+ */
+
+ rx[0] = x*c - y*s;
+ ry[0] = y*c + x*s;
+ rx[1] = (x+width)*c - y*s;
+ ry[1] = y*c + (x+width)*s;
+ rx[2] = (x+width)*c - (y+height)*s;
+ ry[2] = (y+height)*c + (x+width)*s;
+ rx[3] = x*c - (y+height)*s;
+ ry[3] = (y+height)*c + x*s;
+
+ /*
+ * Want to know if all chunks are inside the rectangle, or if there is any
+ * overlap. First, we check to see if all chunks are inside; if and only
+ * if they are, we're in the "inside" case.
+ */
+
+ layoutPtr = (TextLayout *) layout;
+ chunkPtr = layoutPtr->chunks;
+ fontPtr = (TkFont *) layoutPtr->tkfont;
+
+ for (i=0 ; i<layoutPtr->numChunks ; i++,chunkPtr++) {
+ if (chunkPtr->start[0] == '\n') {
+ /*
+ * Newline characters are not counted when computing area
+ * intersection (but tab characters would still be considered).
+ */
+
+ continue;
+ }
+
+ x1 = chunkPtr->x;
+ y1 = chunkPtr->y - fontPtr->fm.ascent;
+ x2 = chunkPtr->x + chunkPtr->displayWidth;
+ y2 = chunkPtr->y + fontPtr->fm.descent;
+ if ( !PointInQuadrilateral(rx, ry, x1, y1) ||
+ !PointInQuadrilateral(rx, ry, x2, y1) ||
+ !PointInQuadrilateral(rx, ry, x2, y2) ||
+ !PointInQuadrilateral(rx, ry, x1, y2)) {
+ goto notInside;
+ }
+ }
+ return 1;
+
+ /*
+ * Next, check to see if all the points of the rectangle are inside a
+ * single chunk; if they are, we're in an "overlap" case.
+ */
+
+ notInside:
+ chunkPtr = layoutPtr->chunks;
+
+ for (i=0 ; i<layoutPtr->numChunks ; i++,chunkPtr++) {
+ double cx[4], cy[4];
+
+ if (chunkPtr->start[0] == '\n') {
+ /*
+ * Newline characters are not counted when computing area
+ * intersection (but tab characters would still be considered).
+ */
+
+ continue;
+ }
+
+ cx[0] = cx[3] = chunkPtr->x;
+ cy[0] = cy[1] = chunkPtr->y - fontPtr->fm.ascent;
+ cx[1] = cx[2] = chunkPtr->x + chunkPtr->displayWidth;
+ cy[2] = cy[3] = chunkPtr->y + fontPtr->fm.descent;
+ if ( PointInQuadrilateral(cx, cy, rx[0], ry[0]) &&
+ PointInQuadrilateral(cx, cy, rx[1], ry[1]) &&
+ PointInQuadrilateral(cx, cy, rx[2], ry[2]) &&
+ PointInQuadrilateral(cx, cy, rx[3], ry[3])) {
+ return 0;
+ }
+ }
+
+ /*
+ * If we're overlapping now, we must be partially in and out of at least
+ * one chunk. If that is the case, there must be one line segment of the
+ * rectangle that is touching or crossing a line segment of a chunk.
+ */
+
+ chunkPtr = layoutPtr->chunks;
+
+ for (i=0 ; i<layoutPtr->numChunks ; i++,chunkPtr++) {
+ int j;
+
+ if (chunkPtr->start[0] == '\n') {
+ /*
+ * Newline characters are not counted when computing area
+ * intersection (but tab characters would still be considered).
+ */
+
+ continue;
+ }
+
+ x1 = chunkPtr->x;
+ y1 = chunkPtr->y - fontPtr->fm.ascent;
+ x2 = chunkPtr->x + chunkPtr->displayWidth;
+ y2 = chunkPtr->y + fontPtr->fm.descent;
+
+ for (j=0 ; j<4 ; j++) {
+ int k = (j+1) % 4;
+
+ if ( SidesIntersect(rx[j],ry[j], rx[k],ry[k], x1,y1, x2,y1) ||
+ SidesIntersect(rx[j],ry[j], rx[k],ry[k], x2,y1, x2,y2) ||
+ SidesIntersect(rx[j],ry[j], rx[k],ry[k], x2,y2, x1,y2) ||
+ SidesIntersect(rx[j],ry[j], rx[k],ry[k], x1,y2, x1,y1)) {
+ return 0;
+ }
+ }
+ }
+
+ /*
+ * They must be wholly non-overlapping.
+ */
+
+ return -1;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_TextLayoutToPostscript --
+ *
+ * Outputs the contents of a text layout in Postscript format. The set of
+ * lines in the text layout will be rendered by the user supplied
+ * Postscript function. The function should be of the form:
+ *
+ * justify x y string function --
+ *
+ * Justify is -1, 0, or 1, depending on whether the following string
+ * should be left, center, or right justified, x and y is the location
+ * for the origin of the string, string is the sequence of characters to
+ * be printed, and function is the name of the caller-provided function;
+ * the function should leave nothing on the stack.
+ *
+ * The meaning of the origin of the string (x and y) depends on the
+ * justification. For left justification, x is where the left edge of the
+ * string should appear. For center justification, x is where the center
+ * of the string should appear. And for right justification, x is where
+ * the right edge of the string should appear. This behavior is necessary
+ * because, for example, right justified text on the screen is justified
+ * with screen metrics. The same string needs to be justified with
+ * printer metrics on the printer to appear in the correct place with
+ * respect to other similarly justified strings. In all circumstances, y
+ * is the location of the baseline for the string.
+ *
+ * Results:
+ * The interp's result is modified to hold the Postscript code that will
+ * render the text layout.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+Tk_TextLayoutToPostscript(
+ Tcl_Interp *interp, /* Filled with Postscript code. */
+ Tk_TextLayout layout) /* The layout to be rendered. */
+{
+ TextLayout *layoutPtr = (TextLayout *) layout;
+ LayoutChunk *chunkPtr = layoutPtr->chunks;
+ int baseline = chunkPtr->y;
+ Tcl_Obj *psObj = Tcl_NewObj();
+ int i, j, len;
+ const char *p, *glyphname;
+ char uindex[5], c, *ps;
+ int ch;
+
+ Tcl_AppendToObj(psObj, "[(", -1);
+ for (i = 0; i < layoutPtr->numChunks; i++, chunkPtr++) {
+ if (baseline != chunkPtr->y) {
+ Tcl_AppendToObj(psObj, ")]\n[(", -1);
+ baseline = chunkPtr->y;
+ }
+ if (chunkPtr->numDisplayChars <= 0) {
+ if (chunkPtr->start[0] == '\t') {
+ Tcl_AppendToObj(psObj, "\\t", -1);
+ }
+ continue;
+ }
+
+ for (p=chunkPtr->start, j=0; j<chunkPtr->numDisplayChars; j++) {
+ /*
+ * INTL: We only handle symbols that have an encoding as a glyph
+ * from the standard set defined by Adobe. The rest get punted.
+ * Eventually this should be revised to handle more sophsticiated
+ * international postscript fonts.
+ */
+
+ p += TkUtfToUniChar(p, &ch);
+ if ((ch == '(') || (ch == ')') || (ch == '\\') || (ch < 0x20)) {
+ /*
+ * Tricky point: the "03" is necessary in the sprintf below,
+ * so that a full three digits of octal are always generated.
+ * Without the "03", a number following this sequence could be
+ * interpreted by Postscript as part of this sequence.
+ */
+
+ Tcl_AppendPrintfToObj(psObj, "\\%03o", ch);
+ continue;
+ } else if (ch <= 0x7f) {
+ /*
+ * Normal ASCII character.
+ */
+
+ c = (char) ch;
+ Tcl_AppendToObj(psObj, &c, 1);
+ continue;
+ }
+
+ /*
+ * This character doesn't belong to the ASCII character set, so we
+ * use the full glyph name.
+ */
+
+ if (ch > 0xffff) {
+ goto noMapping;
+ }
+ sprintf(uindex, "%04X", ch); /* endianness? */
+ glyphname = Tcl_GetVar2(interp, "::tk::psglyphs", uindex, 0);
+ if (glyphname) {
+ ps = Tcl_GetStringFromObj(psObj, &len);
+ if (ps[len-1] == '(') {
+ /*
+ * In-place edit. Ewww!
+ */
+
+ ps[len-1] = '/';
+ } else {
+ Tcl_AppendToObj(psObj, ")/", -1);
+ }
+ Tcl_AppendToObj(psObj, glyphname, -1);
+ Tcl_AppendToObj(psObj, "(", -1);
+ } else {
+ /*
+ * No known mapping for the character into the space of
+ * PostScript glyphs. Ignore it. :-(
+ */
+noMapping: ;
+
+#ifdef TK_DEBUG_POSTSCRIPT_OUTPUT
+ fprintf(stderr, "Warning: no mapping to PostScript "
+ "glyphs for \\u%04x\n", ch);
+#endif
+ }
+ }
+ }
+ Tcl_AppendToObj(psObj, ")]\n", -1);
+ Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj);
+ Tcl_DecrRefCount(psObj);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ConfigAttributesObj --
+ *
+ * Process command line options to fill in fields of a properly
+ * initialized font attributes structure.
+ *
+ * Results:
+ * A standard Tcl return value. If TCL_ERROR is returned, an error
+ * message will be left in interp's result object.
+ *
+ * Side effects:
+ * The fields of the font attributes structure get filled in with
+ * information from argc/argv. If an error occurs while parsing, the font
+ * attributes structure will contain all modifications specified in the
+ * command line options up to the point of the error.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static int
+ConfigAttributesObj(
+ Tcl_Interp *interp, /* Interp for error return. */
+ Tk_Window tkwin, /* For display on which font will be used. */
+ int objc, /* Number of elements in argv. */
+ Tcl_Obj *const objv[], /* Command line options. */
+ TkFontAttributes *faPtr) /* Font attributes structure whose fields are
+ * to be modified. Structure must already be
+ * properly initialized. */
+{
+ int i, n, index;
+ Tcl_Obj *optionPtr, *valuePtr;
+ const char *value;
+
+ for (i = 0; i < objc; i += 2) {
+ optionPtr = objv[i];
+
+ if (Tcl_GetIndexFromObj(interp, optionPtr, fontOpt, "option", 1,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((i+2 >= objc) && (objc & 1)) {
+ /*
+ * This test occurs after Tcl_GetIndexFromObj() so that "font
+ * create xyz -xyz" will return the error message that "-xyz" is a
+ * bad option, rather than that the value for "-xyz" is missing.
+ */
+
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "value for \"%s\" option missing",
+ Tcl_GetString(optionPtr)));
+ Tcl_SetErrorCode(interp, "TK", "FONT", "NO_ATTRIBUTE", NULL);
+ }
+ return TCL_ERROR;
+ }
+ valuePtr = objv[i + 1];
+
+ switch (index) {
+ case FONT_FAMILY:
+ value = Tcl_GetString(valuePtr);
+ faPtr->family = Tk_GetUid(value);
+ break;
+ case FONT_SIZE:
+ if (Tcl_GetIntFromObj(interp, valuePtr, &n) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ faPtr->size = (double)n;
+ break;
+ case FONT_WEIGHT:
+ n = TkFindStateNumObj(interp, optionPtr, weightMap, valuePtr);
+ if (n == TK_FW_UNKNOWN) {
+ return TCL_ERROR;
+ }
+ faPtr->weight = n;
+ break;
+ case FONT_SLANT:
+ n = TkFindStateNumObj(interp, optionPtr, slantMap, valuePtr);
+ if (n == TK_FS_UNKNOWN) {
+ return TCL_ERROR;
+ }
+ faPtr->slant = n;
+ break;
+ case FONT_UNDERLINE:
+ if (Tcl_GetBooleanFromObj(interp, valuePtr, &n) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ faPtr->underline = n;
+ break;
+ case FONT_OVERSTRIKE:
+ if (Tcl_GetBooleanFromObj(interp, valuePtr, &n) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ faPtr->overstrike = n;
+ break;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GetAttributeInfoObj --
+ *
+ * Return information about the font attributes as a Tcl list.
+ *
+ * Results:
+ * The return value is TCL_OK if the objPtr was non-NULL and specified a
+ * valid font attribute, TCL_ERROR otherwise. If TCL_OK is returned, the
+ * interp's result object is modified to hold a description of either the
+ * current value of a single option, or a list of all options and their
+ * current values for the given font attributes. If TCL_ERROR is
+ * returned, the interp's result is set to an error message describing
+ * that the objPtr did not refer to a valid option.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static int
+GetAttributeInfoObj(
+ Tcl_Interp *interp, /* Interp to hold result. */
+ const TkFontAttributes *faPtr,
+ /* The font attributes to inspect. */
+ Tcl_Obj *objPtr) /* If non-NULL, indicates the single option
+ * whose value is to be returned. Otherwise
+ * information is returned for all options. */
+{
+ int i, index, start, end;
+ const char *str;
+ Tcl_Obj *valuePtr, *resultPtr = NULL;
+
+ start = 0;
+ end = FONT_NUMFIELDS;
+ if (objPtr != NULL) {
+ if (Tcl_GetIndexFromObj(interp, objPtr, fontOpt, "option", TCL_EXACT,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ start = index;
+ end = index + 1;
+ }
+
+ valuePtr = NULL;
+ if (objPtr == NULL) {
+ resultPtr = Tcl_NewObj();
+ }
+ for (i = start; i < end; i++) {
+ switch (i) {
+ case FONT_FAMILY:
+ str = faPtr->family;
+ valuePtr = Tcl_NewStringObj(str, ((str == NULL) ? 0 : -1));
+ break;
+
+ case FONT_SIZE:
+ if (faPtr->size >= 0.0) {
+ valuePtr = Tcl_NewIntObj((int)(faPtr->size + 0.5));
+ } else {
+ valuePtr = Tcl_NewIntObj(-(int)(-faPtr->size + 0.5));
+ }
+ break;
+
+ case FONT_WEIGHT:
+ str = TkFindStateString(weightMap, faPtr->weight);
+ valuePtr = Tcl_NewStringObj(str, -1);
+ break;
+
+ case FONT_SLANT:
+ str = TkFindStateString(slantMap, faPtr->slant);
+ valuePtr = Tcl_NewStringObj(str, -1);
+ break;
+
+ case FONT_UNDERLINE:
+ valuePtr = Tcl_NewBooleanObj(faPtr->underline);
+ break;
+
+ case FONT_OVERSTRIKE:
+ valuePtr = Tcl_NewBooleanObj(faPtr->overstrike);
+ break;
+ }
+ if (objPtr != NULL) {
+ Tcl_SetObjResult(interp, valuePtr);
+ return TCL_OK;
+ }
+ Tcl_ListObjAppendElement(NULL, resultPtr,
+ Tcl_NewStringObj(fontOpt[i], -1));
+ Tcl_ListObjAppendElement(NULL, resultPtr, valuePtr);
+ }
+ Tcl_SetObjResult(interp, resultPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ParseFontNameObj --
+ *
+ * Converts a object into a set of font attributes that can be used to
+ * construct a font.
+ *
+ * The string rep of the object can be one of the following forms:
+ * XLFD (see X documentation)
+ * "family [size] [style1 [style2 ...]"
+ * "-option value [-option value ...]"
+ *
+ * Results:
+ * The return value is TCL_ERROR if the object was syntactically invalid.
+ * In that case an error message is left in interp's result object.
+ * Otherwise, fills the font attribute buffer with the values parsed from
+ * the string and returns TCL_OK;
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static int
+ParseFontNameObj(
+ Tcl_Interp *interp, /* Interp for error return. */
+ Tk_Window tkwin, /* For display on which font is used. */
+ Tcl_Obj *objPtr, /* Parseable font description object. */
+ TkFontAttributes *faPtr) /* Filled with attributes parsed from font
+ * name. Any attributes that were not
+ * specified in font name are filled with
+ * default values. */
+{
+ char *dash;
+ int objc, result, i, n;
+ Tcl_Obj **objv;
+ const char *string;
+
+ TkInitFontAttributes(faPtr);
+
+ string = Tcl_GetString(objPtr);
+ if (*string == '-') {
+ /*
+ * This may be an XLFD or an "-option value" string.
+ *
+ * If the string begins with "-*" or a "-foundry-family-*" pattern,
+ * then consider it an XLFD.
+ */
+
+ if (string[1] == '*') {
+ goto xlfd;
+ }
+ dash = strchr(string + 1, '-');
+ if ((dash != NULL)
+ && !isspace(UCHAR(dash[-1]))) { /* INTL: ISO space */
+ goto xlfd;
+ }
+
+ if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ return ConfigAttributesObj(interp, tkwin, objc, objv, faPtr);
+ }
+
+ if (*string == '*') {
+ /*
+ * This is appears to be an XLFD. Under Unix, all valid XLFDs were
+ * already handled by TkpGetNativeFont. If we are here, either we have
+ * something that initially looks like an XLFD but isn't or we have
+ * encountered an XLFD on Windows or Mac.
+ */
+
+ xlfd:
+ result = TkFontParseXLFD(string, faPtr, NULL);
+ if (result == TCL_OK) {
+ return TCL_OK;
+ }
+
+ /*
+ * If the string failed to parse but was considered to be a XLFD
+ * then it may be a "-option value" string with a hyphenated family
+ * name as per bug 2791352
+ */
+
+ if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (ConfigAttributesObj(interp, tkwin, objc, objv, faPtr) == TCL_OK) {
+ return TCL_OK;
+ }
+ }
+
+ /*
+ * Wasn't an XLFD or "-option value" string. Try it as a "font size style"
+ * list.
+ */
+
+ if ((Tcl_ListObjGetElements(NULL, objPtr, &objc, &objv) != TCL_OK)
+ || (objc < 1)) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "font \"%s\" doesn't exist", string));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "FONT", string, NULL);
+ }
+ return TCL_ERROR;
+ }
+
+ faPtr->family = Tk_GetUid(Tcl_GetString(objv[0]));
+ if (objc > 1) {
+ if (Tcl_GetIntFromObj(interp, objv[1], &n) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ faPtr->size = (double)n;
+ }
+
+ i = 2;
+ if (objc == 3) {
+ if (Tcl_ListObjGetElements(interp, objv[2], &objc, &objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ i = 0;
+ }
+ for ( ; i < objc; i++) {
+ n = TkFindStateNumObj(NULL, NULL, weightMap, objv[i]);
+ if (n != TK_FW_UNKNOWN) {
+ faPtr->weight = n;
+ continue;
+ }
+ n = TkFindStateNumObj(NULL, NULL, slantMap, objv[i]);
+ if (n != TK_FS_UNKNOWN) {
+ faPtr->slant = n;
+ continue;
+ }
+ n = TkFindStateNumObj(NULL, NULL, underlineMap, objv[i]);
+ if (n != 0) {
+ faPtr->underline = n;
+ continue;
+ }
+ n = TkFindStateNumObj(NULL, NULL, overstrikeMap, objv[i]);
+ if (n != 0) {
+ faPtr->overstrike = n;
+ continue;
+ }
+
+ /*
+ * Unknown style.
+ */
+
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "unknown font style \"%s\"", Tcl_GetString(objv[i])));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "FONT_STYLE",
+ Tcl_GetString(objv[i]), NULL);
+ }
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * NewChunk --
+ *
+ * Helper function for Tk_ComputeTextLayout(). Encapsulates a measured
+ * set of characters in a chunk that can be quickly drawn.
+ *
+ * Results:
+ * A pointer to the new chunk in the text layout.
+ *
+ * Side effects:
+ * The text layout is reallocated to hold more chunks as necessary.
+ *
+ * Currently, Tk_ComputeTextLayout() stores contiguous ranges of "normal"
+ * characters in a chunk, along with individual tab and newline chars in
+ * their own chunks. All characters in the text layout are accounted for.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static LayoutChunk *
+NewChunk(
+ TextLayout **layoutPtrPtr,
+ int *maxPtr,
+ const char *start,
+ int numBytes,
+ int curX,
+ int newX,
+ int y)
+{
+ TextLayout *layoutPtr;
+ LayoutChunk *chunkPtr;
+ int maxChunks, numChars;
+ size_t s;
+
+ layoutPtr = *layoutPtrPtr;
+ maxChunks = *maxPtr;
+ if (layoutPtr->numChunks == maxChunks) {
+ maxChunks *= 2;
+ s = sizeof(TextLayout) + ((maxChunks - 1) * sizeof(LayoutChunk));
+ layoutPtr = ckrealloc(layoutPtr, s);
+
+ *layoutPtrPtr = layoutPtr;
+ *maxPtr = maxChunks;
+ }
+ numChars = Tcl_NumUtfChars(start, numBytes);
+ chunkPtr = &layoutPtr->chunks[layoutPtr->numChunks];
+ chunkPtr->start = start;
+ chunkPtr->numBytes = numBytes;
+ chunkPtr->numChars = numChars;
+ chunkPtr->numDisplayChars = numChars;
+ chunkPtr->x = curX;
+ chunkPtr->y = y;
+ chunkPtr->totalWidth = newX - curX;
+ chunkPtr->displayWidth = newX - curX;
+ layoutPtr->numChunks++;
+
+ return chunkPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkFontParseXLFD --
+ *
+ * Break up a fully specified XLFD into a set of font attributes.
+ *
+ * Results:
+ * Return value is TCL_ERROR if string was not a fully specified XLFD.
+ * Otherwise, fills font attribute buffer with the values parsed from the
+ * XLFD and returns TCL_OK.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TkFontParseXLFD(
+ const char *string, /* Parseable font description string. */
+ TkFontAttributes *faPtr, /* Filled with attributes parsed from font
+ * name. Any attributes that were not
+ * specified in font name are filled with
+ * default values. */
+ TkXLFDAttributes *xaPtr) /* Filled with X-specific attributes parsed
+ * from font name. Any attributes that were
+ * not specified in font name are filled with
+ * default values. May be NULL if such
+ * information is not desired. */
+{
+ char *src;
+ const char *str;
+ int i, j;
+ char *field[XLFD_NUMFIELDS + 2];
+ Tcl_DString ds;
+ TkXLFDAttributes xa;
+
+ if (xaPtr == NULL) {
+ xaPtr = &xa;
+ }
+ TkInitFontAttributes(faPtr);
+ TkInitXLFDAttributes(xaPtr);
+
+ memset(field, '\0', sizeof(field));
+
+ str = string;
+ if (*str == '-') {
+ str++;
+ }
+
+ Tcl_DStringInit(&ds);
+ Tcl_DStringAppend(&ds, str, -1);
+ src = Tcl_DStringValue(&ds);
+
+ field[0] = src;
+ for (i = 0; *src != '\0'; src++) {
+ if (!(*src & 0x80)
+ && Tcl_UniCharIsUpper(UCHAR(*src))) {
+ *src = (char) Tcl_UniCharToLower(UCHAR(*src));
+ }
+ if (*src == '-') {
+ i++;
+ if (i == XLFD_NUMFIELDS) {
+ continue;
+ }
+ *src = '\0';
+ field[i] = src + 1;
+ if (i > XLFD_NUMFIELDS) {
+ break;
+ }
+ }
+ }
+
+ /*
+ * An XLFD of the form -adobe-times-medium-r-*-12-*-* is pretty common,
+ * but it is (strictly) malformed, because the first * is eliding both the
+ * Setwidth and the Addstyle fields. If the Addstyle field is a number,
+ * then assume the above incorrect form was used and shift all the rest of
+ * the fields right by one, so the number gets interpreted as a pixelsize.
+ * This fix is so that we don't get a million reports that "it works under
+ * X (as a native font name), but gives a syntax error under Windows (as a
+ * parsed set of attributes)".
+ */
+
+ if ((i > XLFD_ADD_STYLE) && FieldSpecified(field[XLFD_ADD_STYLE])) {
+ if (atoi(field[XLFD_ADD_STYLE]) != 0) {
+ for (j = XLFD_NUMFIELDS - 1; j >= XLFD_ADD_STYLE; j--) {
+ field[j + 1] = field[j];
+ }
+ field[XLFD_ADD_STYLE] = NULL;
+ i++;
+ }
+ }
+
+ /*
+ * Bail if we don't have enough of the fields (up to pointsize).
+ */
+
+ if (i < XLFD_FAMILY) {
+ Tcl_DStringFree(&ds);
+ return TCL_ERROR;
+ }
+
+ if (FieldSpecified(field[XLFD_FOUNDRY])) {
+ xaPtr->foundry = Tk_GetUid(field[XLFD_FOUNDRY]);
+ }
+
+ if (FieldSpecified(field[XLFD_FAMILY])) {
+ faPtr->family = Tk_GetUid(field[XLFD_FAMILY]);
+ }
+ if (FieldSpecified(field[XLFD_WEIGHT])) {
+ faPtr->weight = TkFindStateNum(NULL, NULL, xlfdWeightMap,
+ field[XLFD_WEIGHT]);
+ }
+ if (FieldSpecified(field[XLFD_SLANT])) {
+ xaPtr->slant = TkFindStateNum(NULL, NULL, xlfdSlantMap,
+ field[XLFD_SLANT]);
+ if (xaPtr->slant == TK_FS_ROMAN) {
+ faPtr->slant = TK_FS_ROMAN;
+ } else {
+ faPtr->slant = TK_FS_ITALIC;
+ }
+ }
+ if (FieldSpecified(field[XLFD_SETWIDTH])) {
+ xaPtr->setwidth = TkFindStateNum(NULL, NULL, xlfdSetwidthMap,
+ field[XLFD_SETWIDTH]);
+ }
+
+ /* XLFD_ADD_STYLE ignored. */
+
+ /*
+ * Pointsize in tenths of a point, but treat it as tenths of a pixel for
+ * historical compatibility.
+ */
+
+ faPtr->size = 12.0;
+
+ if (FieldSpecified(field[XLFD_POINT_SIZE])) {
+ if (field[XLFD_POINT_SIZE][0] == '[') {
+ /*
+ * Some X fonts have the point size specified as follows:
+ *
+ * [ N1 N2 N3 N4 ]
+ *
+ * where N1 is the point size (in points, not decipoints!), and
+ * N2, N3, and N4 are some additional numbers that I don't know
+ * the purpose of, so I ignore them.
+ */
+
+ faPtr->size = atof(field[XLFD_POINT_SIZE] + 1);
+ } else if (Tcl_GetInt(NULL, field[XLFD_POINT_SIZE],
+ &i) == TCL_OK) {
+ faPtr->size = i/10.0;
+ } else {
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * Pixel height of font. If specified, overrides pointsize.
+ */
+
+ if (FieldSpecified(field[XLFD_PIXEL_SIZE])) {
+ if (field[XLFD_PIXEL_SIZE][0] == '[') {
+ /*
+ * Some X fonts have the pixel size specified as follows:
+ *
+ * [ N1 N2 N3 N4 ]
+ *
+ * where N1 is the pixel size, and where N2, N3, and N4 are some
+ * additional numbers that I don't know the purpose of, so I
+ * ignore them.
+ */
+
+ faPtr->size = atof(field[XLFD_PIXEL_SIZE] + 1);
+ } else if (Tcl_GetInt(NULL, field[XLFD_PIXEL_SIZE],
+ &i) == TCL_OK) {
+ faPtr->size = (double)i;
+ } else {
+ return TCL_ERROR;
+ }
+ }
+
+ faPtr->size = -faPtr->size;
+
+ /* XLFD_RESOLUTION_X ignored. */
+
+ /* XLFD_RESOLUTION_Y ignored. */
+
+ /* XLFD_SPACING ignored. */
+
+ /* XLFD_AVERAGE_WIDTH ignored. */
+
+ if (FieldSpecified(field[XLFD_CHARSET])) {
+ xaPtr->charset = Tk_GetUid(field[XLFD_CHARSET]);
+ } else {
+ xaPtr->charset = Tk_GetUid("iso8859-1");
+ }
+ Tcl_DStringFree(&ds);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FieldSpecified --
+ *
+ * Helper function for TkParseXLFD(). Determines if a field in the XLFD
+ * was set to a non-null, non-don't-care value.
+ *
+ * Results:
+ * The return value is 0 if the field in the XLFD was not set and should
+ * be ignored, non-zero otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static int
+FieldSpecified(
+ const char *field) /* The field of the XLFD to check. Strictly
+ * speaking, only when the string is "*" does
+ * it mean don't-care. However, an unspecified
+ * or question mark is also interpreted as
+ * don't-care. */
+{
+ char ch;
+
+ if (field == NULL) {
+ return 0;
+ }
+ ch = field[0];
+ return (ch != '*' && ch != '?');
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkFontGetPixels --
+ *
+ * Given a font size specification (as described in the TkFontAttributes
+ * structure) return the number of pixels it represents.
+ *
+ * Results:
+ * As above.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+double
+TkFontGetPixels(
+ Tk_Window tkwin, /* For point->pixel conversion factor. */
+ double size) /* Font size. */
+{
+ double d;
+
+ if (size <= 0.0) {
+ return -size;
+ }
+
+ d = size * 25.4 / 72.0;
+ d *= WidthOfScreen(Tk_Screen(tkwin));
+ d /= WidthMMOfScreen(Tk_Screen(tkwin));
+ return d;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkFontGetPoints --
+ *
+ * Given a font size specification (as described in the TkFontAttributes
+ * structure) return the number of points it represents.
+ *
+ * Results:
+ * As above.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+double
+TkFontGetPoints(
+ Tk_Window tkwin, /* For pixel->point conversion factor. */
+ double size) /* Font size. */
+{
+ double d;
+
+ if (size >= 0.0) {
+ return size;
+ }
+
+ d = -size * 72.0 / 25.4;
+ d *= WidthMMOfScreen(Tk_Screen(tkwin));
+ d /= WidthOfScreen(Tk_Screen(tkwin));
+ return d;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * TkFontGetAliasList --
+ *
+ * Given a font name, find the list of all aliases for that font name.
+ * One of the names in this list will probably be the name that this
+ * platform expects when asking for the font.
+ *
+ * Results:
+ * As above. The return value is NULL if the font name has no aliases.
+ *
+ * Side effects:
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+const char *const *
+TkFontGetAliasList(
+ const char *faceName) /* Font name to test for aliases. */
+{
+ int i, j;
+
+ for (i = 0; fontAliases[i] != NULL; i++) {
+ for (j = 0; fontAliases[i][j] != NULL; j++) {
+ if (strcasecmp(faceName, fontAliases[i][j]) == 0) {
+ return fontAliases[i];
+ }
+ }
+ }
+ return NULL;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * TkFontGetFallbacks --
+ *
+ * Get the list of font fallbacks that the platform-specific code can use
+ * to try to find the closest matching font the name requested.
+ *
+ * Results:
+ * As above.
+ *
+ * Side effects:
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+const char *const *const *
+TkFontGetFallbacks(void)
+{
+ return fontFallbacks;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * TkFontGetGlobalClass --
+ *
+ * Get the list of fonts to try if the requested font name does not
+ * exist and no fallbacks for that font name could be used either.
+ * The names in this list are considered preferred over all the other
+ * font names in the system when looking for a last-ditch fallback.
+ *
+ * Results:
+ * As above.
+ *
+ * Side effects:
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+const char *const *
+TkFontGetGlobalClass(void)
+{
+ return globalFontClass;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * TkFontGetSymbolClass --
+ *
+ * Get the list of fonts that are symbolic; used if the operating system
+ * cannot apriori identify symbolic fonts on its own.
+ *
+ * Results:
+ * As above.
+ *
+ * Side effects:
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+const char *const *
+TkFontGetSymbolClass(void)
+{
+ return symbolClass;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkDebugFont --
+ *
+ * This function returns debugging information about a font.
+ *
+ * Results:
+ * The return value is a list with one sublist for each TkFont
+ * corresponding to "name". Each sublist has two elements that contain
+ * the resourceRefCount and objRefCount fields from the TkFont structure.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TkDebugFont(
+ Tk_Window tkwin, /* The window in which the font will be used
+ * (not currently used). */
+ const char *name) /* Name of the desired color. */
+{
+ TkFont *fontPtr;
+ Tcl_HashEntry *hashPtr;
+ Tcl_Obj *resultPtr, *objPtr;
+
+ resultPtr = Tcl_NewObj();
+ hashPtr = Tcl_FindHashEntry(
+ &((TkWindow *) tkwin)->mainPtr->fontInfoPtr->fontCache, name);
+ if (hashPtr != NULL) {
+ fontPtr = Tcl_GetHashValue(hashPtr);
+ if (fontPtr == NULL) {
+ Tcl_Panic("TkDebugFont found empty hash table entry");
+ }
+ for ( ; (fontPtr != NULL); fontPtr = fontPtr->nextPtr) {
+ objPtr = Tcl_NewObj();
+ Tcl_ListObjAppendElement(NULL, objPtr,
+ Tcl_NewIntObj(fontPtr->resourceRefCount));
+ Tcl_ListObjAppendElement(NULL, objPtr,
+ Tcl_NewIntObj(fontPtr->objRefCount));
+ Tcl_ListObjAppendElement(NULL, resultPtr, objPtr);
+ }
+ }
+ return resultPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkFontGetFirstTextLayout --
+ *
+ * This function returns the first chunk of a Tk_TextLayout, i.e. until
+ * the first font change on the first line (or the whole first line if
+ * there is no such font change).
+ *
+ * Results:
+ * The return value is the byte length of the chunk, the chunk itself is
+ * copied into dst and its Tk_Font into font.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkFontGetFirstTextLayout(
+ Tk_TextLayout layout, /* Layout information, from a previous call to
+ * Tk_ComputeTextLayout(). */
+ Tk_Font *font,
+ char *dst)
+{
+ TextLayout *layoutPtr = (TextLayout *) layout;
+ LayoutChunk *chunkPtr;
+ int numBytesInChunk;
+
+ if ((layoutPtr == NULL) || (layoutPtr->numChunks == 0)
+ || (layoutPtr->chunks->numDisplayChars <= 0)) {
+ dst[0] = '\0';
+ return 0;
+ }
+ chunkPtr = layoutPtr->chunks;
+ numBytesInChunk = chunkPtr->numBytes;
+ strncpy(dst, chunkPtr->start, (size_t) numBytesInChunk);
+ *font = layoutPtr->tkfont;
+ return numBytesInChunk;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkFont.h b/tk8.6/generic/tkFont.h
new file mode 100644
index 0000000..de479bf
--- /dev/null
+++ b/tk8.6/generic/tkFont.h
@@ -0,0 +1,224 @@
+/*
+ * tkFont.h --
+ *
+ * Declarations for interfaces between the generic and platform-specific
+ * parts of the font package. This information is not visible outside of
+ * the font package.
+ *
+ * Copyright (c) 1996-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.
+ */
+
+#ifndef _TKFONT
+#define _TKFONT
+
+/*
+ * The following structure keeps track of the attributes of a font. It can be
+ * used to keep track of either the desired attributes or the actual
+ * attributes gotten when the font was instantiated.
+ */
+
+struct TkFontAttributes {
+ Tk_Uid family; /* Font family, or NULL to represent plaform-
+ * specific default system font. */
+ double size; /* Pointsize of font, 0.0 for default size, or
+ * negative number meaning pixel size. */
+ int weight; /* Weight flag; see below for def'n. */
+ int slant; /* Slant flag; see below for def'n. */
+ int underline; /* Non-zero for underline font. */
+ int overstrike; /* Non-zero for overstrike font. */
+};
+
+/*
+ * Possible values for the "weight" field in a TkFontAttributes structure.
+ * Weight is a subjective term and depends on what the company that created
+ * the font considers bold.
+ */
+
+#define TK_FW_NORMAL 0
+#define TK_FW_BOLD 1
+
+#define TK_FW_UNKNOWN -1 /* Unknown weight. This value is used for
+ * error checking and is never actually stored
+ * in the weight field. */
+
+/*
+ * Possible values for the "slant" field in a TkFontAttributes structure.
+ */
+
+#define TK_FS_ROMAN 0
+#define TK_FS_ITALIC 1
+#define TK_FS_OBLIQUE 2 /* This value is only used when parsing X font
+ * names to determine the closest match. It is
+ * only stored in the XLFDAttributes
+ * structure, never in the slant field of the
+ * TkFontAttributes. */
+
+#define TK_FS_UNKNOWN -1 /* Unknown slant. This value is used for error
+ * checking and is never actually stored in
+ * the slant field. */
+
+/*
+ * The following structure keeps track of the metrics for an instantiated
+ * font. The metrics are the physical properties of the font itself.
+ */
+
+typedef struct TkFontMetrics {
+ int ascent; /* From baseline to top of font. */
+ int descent; /* From baseline to bottom of font. */
+ int maxWidth; /* Width of widest character in font. */
+ int fixed; /* Non-zero if this is a fixed-width font,
+ * 0 otherwise. */
+} TkFontMetrics;
+
+/*
+ * The following structure is used to keep track of the generic information
+ * about a font. Each platform-specific font is represented by a structure
+ * with the following structure at its beginning, plus any platform-specific
+ * stuff after that.
+ */
+
+typedef struct TkFont {
+ /*
+ * Fields used and maintained exclusively by generic code.
+ */
+
+ int resourceRefCount; /* Number of active uses of this font (each
+ * active use corresponds to a call to
+ * Tk_AllocFontFromTable or Tk_GetFont). If
+ * this count is 0, then this TkFont structure
+ * is no longer valid and it isn't present in
+ * a hash table: it is being kept around only
+ * because there are objects referring to it.
+ * The structure is freed when
+ * resourceRefCount and objRefCount are both
+ * 0. */
+ int objRefCount; /* The number of Tcl objects that reference
+ * this structure. */
+ Tcl_HashEntry *cacheHashPtr;/* Entry in font cache for this structure,
+ * used when deleting it. */
+ Tcl_HashEntry *namedHashPtr;/* Pointer to hash table entry that
+ * corresponds to the named font that the
+ * tkfont was based on, or NULL if the tkfont
+ * was not based on a named font. */
+ Screen *screen; /* The screen where this font is valid. */
+ int tabWidth; /* Width of tabs in this font (pixels). */
+ int underlinePos; /* Offset from baseline to origin of underline
+ * bar (used for drawing underlines on a
+ * non-underlined font). */
+ int underlineHeight; /* Height of underline bar (used for drawing
+ * underlines on a non-underlined font). */
+
+ /*
+ * Fields used in the generic code that are filled in by
+ * platform-specific code.
+ */
+
+ Font fid; /* For backwards compatibility with XGCValues
+ * structures. Remove when TkGCValues is
+ * implemented. */
+ TkFontAttributes fa; /* Actual font attributes obtained when the
+ * the font was created, as opposed to the
+ * desired attributes passed in to
+ * TkpGetFontFromAttributes(). The desired
+ * metrics can be determined from the string
+ * that was used to create this font. */
+ TkFontMetrics fm; /* Font metrics determined when font was
+ * created. */
+ struct TkFont *nextPtr; /* Points to the next TkFont structure with
+ * the same name. All fonts with the same name
+ * (but different displays) are chained
+ * together off a single entry in a hash
+ * table. */
+} TkFont;
+
+/*
+ * The following structure is used to return attributes when parsing an XLFD.
+ * The extra information is of interest to the Unix-specific code when
+ * attempting to find the closest matching font.
+ */
+
+typedef struct TkXLFDAttributes {
+ Tk_Uid foundry; /* The foundry of the font. */
+ int slant; /* The tristate value for the slant, which is
+ * significant under X. */
+ int setwidth; /* The proportionate width, see below for
+ * definition. */
+ Tk_Uid charset; /* The actual charset string. */
+} TkXLFDAttributes;
+
+/*
+ * Possible values for the "setwidth" field in a TkXLFDAttributes structure.
+ * The setwidth is whether characters are considered wider or narrower than
+ * normal.
+ */
+
+#define TK_SW_NORMAL 0
+#define TK_SW_CONDENSE 1
+#define TK_SW_EXPAND 2
+#define TK_SW_UNKNOWN 3 /* Unknown setwidth. This value may be stored
+ * in the setwidth field. */
+
+/*
+ * The following defines specify the meaning of the fields in a fully
+ * qualified XLFD.
+ */
+
+#define XLFD_FOUNDRY 0
+#define XLFD_FAMILY 1
+#define XLFD_WEIGHT 2
+#define XLFD_SLANT 3
+#define XLFD_SETWIDTH 4
+#define XLFD_ADD_STYLE 5
+#define XLFD_PIXEL_SIZE 6
+#define XLFD_POINT_SIZE 7
+#define XLFD_RESOLUTION_X 8
+#define XLFD_RESOLUTION_Y 9
+#define XLFD_SPACING 10
+#define XLFD_AVERAGE_WIDTH 11
+#define XLFD_CHARSET 12
+#define XLFD_NUMFIELDS 13 /* Number of fields in XLFD. */
+
+/*
+ * Helper macro. How to correctly round a double to a short.
+ */
+
+#define ROUND16(x) ((short) floor((x) + 0.5))
+
+/*
+ * Low-level API exported by generic code to platform-specific code.
+ */
+
+#define TkInitFontAttributes(fa) memset((fa), 0, sizeof(TkFontAttributes));
+#define TkInitXLFDAttributes(xa) memset((xa), 0, sizeof(TkXLFDAttributes));
+
+MODULE_SCOPE int TkFontParseXLFD(const char *string,
+ TkFontAttributes *faPtr, TkXLFDAttributes *xaPtr);
+MODULE_SCOPE const char *const * TkFontGetAliasList(const char *faceName);
+MODULE_SCOPE const char *const *const * TkFontGetFallbacks(void);
+MODULE_SCOPE double TkFontGetPixels(Tk_Window tkwin, double size);
+MODULE_SCOPE double TkFontGetPoints(Tk_Window tkwin, double size);
+MODULE_SCOPE const char *const * TkFontGetGlobalClass(void);
+MODULE_SCOPE const char *const * TkFontGetSymbolClass(void);
+MODULE_SCOPE int TkCreateNamedFont(Tcl_Interp *interp, Tk_Window tkwin,
+ const char *name, TkFontAttributes *faPtr);
+MODULE_SCOPE int TkDeleteNamedFont(Tcl_Interp *interp,
+ Tk_Window tkwin, const char *name);
+MODULE_SCOPE int TkFontGetFirstTextLayout(Tk_TextLayout layout,
+ Tk_Font *font, char *dst);
+
+/*
+ * Low-level API exported by platform-specific code to generic code.
+ */
+
+MODULE_SCOPE void TkpDeleteFont(TkFont *tkFontPtr);
+MODULE_SCOPE void TkpFontPkgInit(TkMainInfo *mainPtr);
+MODULE_SCOPE TkFont * TkpGetFontFromAttributes(TkFont *tkFontPtr,
+ Tk_Window tkwin, const TkFontAttributes *faPtr);
+MODULE_SCOPE void TkpGetFontFamilies(Tcl_Interp *interp,
+ Tk_Window tkwin);
+MODULE_SCOPE TkFont * TkpGetNativeFont(Tk_Window tkwin, const char *name);
+
+#endif /* _TKFONT */
diff --git a/tk8.6/generic/tkFrame.c b/tk8.6/generic/tkFrame.c
new file mode 100644
index 0000000..ce7dc8c
--- /dev/null
+++ b/tk8.6/generic/tkFrame.c
@@ -0,0 +1,2038 @@
+/*
+ * tkFrame.c --
+ *
+ * This module implements "frame", "labelframe" and "toplevel" widgets
+ * for the Tk toolkit. Frames are windows with a background color and
+ * possibly a 3-D effect, but not much else in the way of attributes.
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "default.h"
+#include "tkInt.h"
+
+/*
+ * The following enum is used to define the type of the frame.
+ */
+
+enum FrameType {
+ TYPE_FRAME, TYPE_TOPLEVEL, TYPE_LABELFRAME
+};
+
+/*
+ * A data structure of the following type is kept for each
+ * frame that currently exists for this process:
+ */
+
+typedef struct {
+ Tk_Window tkwin; /* Window that embodies the frame. NULL means
+ * that the window has been destroyed but the
+ * data structures haven't yet been cleaned
+ * up. */
+ Display *display; /* Display containing widget. Used, among
+ * other things, so that resources can be
+ * freed even after tkwin has gone away. */
+ Tcl_Interp *interp; /* Interpreter associated with widget. Used to
+ * delete widget command. */
+ Tcl_Command widgetCmd; /* Token for frame's widget command. */
+ Tk_OptionTable optionTable; /* Table that defines configuration options
+ * available for this widget. */
+ char *className; /* Class name for widget (from configuration
+ * option). Malloc-ed. */
+ enum FrameType type; /* Type of widget, such as TYPE_FRAME. */
+ char *screenName; /* Screen on which widget is created. Non-null
+ * only for top-levels. Malloc-ed, may be
+ * NULL. */
+ char *visualName; /* Textual description of visual for window,
+ * from -visual option. Malloc-ed, may be
+ * NULL. */
+ char *colormapName; /* Textual description of colormap for window,
+ * from -colormap option. Malloc-ed, may be
+ * NULL. */
+ char *menuName; /* Textual description of menu to use for
+ * menubar. Malloc-ed, may be NULL. */
+ Colormap colormap; /* If not None, identifies a colormap
+ * allocated for this window, which must be
+ * freed when the window is deleted. */
+ Tk_3DBorder border; /* Structure used to draw 3-D border and
+ * background. NULL means no background or
+ * border. */
+ int borderWidth; /* Width of 3-D border (if any). */
+ int relief; /* 3-d effect: TK_RELIEF_RAISED etc. */
+ int highlightWidth; /* Width in pixels of highlight to draw around
+ * widget when it has the focus. 0 means don't
+ * draw a highlight. */
+ XColor *highlightBgColorPtr;
+ /* Color for drawing traversal highlight area
+ * when highlight is off. */
+ XColor *highlightColorPtr; /* Color for drawing traversal highlight. */
+ int width; /* Width to request for window. <= 0 means
+ * don't request any size. */
+ int height; /* Height to request for window. <= 0 means
+ * don't request any size. */
+ Tk_Cursor cursor; /* Current cursor for window, or None. */
+ char *takeFocus; /* Value of -takefocus option; not used in the
+ * C code, but used by keyboard traversal
+ * scripts. Malloc'ed, but may be NULL. */
+ int isContainer; /* 1 means this window is a container, 0 means
+ * that it isn't. */
+ char *useThis; /* If the window is embedded, this points to
+ * the name of the window in which it is
+ * embedded (malloc'ed). For non-embedded
+ * windows this is NULL. */
+ int flags; /* Various flags; see below for
+ * definitions. */
+ Tcl_Obj *padXPtr; /* Value of -padx option: specifies how many
+ * pixels of extra space to leave on left and
+ * right of child area. */
+ int padX; /* Integer value corresponding to padXPtr. */
+ Tcl_Obj *padYPtr; /* Value of -padx option: specifies how many
+ * pixels of extra space to leave above and
+ * below child area. */
+ int padY; /* Integer value corresponding to padYPtr. */
+} Frame;
+
+/*
+ * A data structure of the following type is kept for each labelframe widget
+ * managed by this file:
+ */
+
+typedef struct {
+ Frame frame; /* A pointer to the generic frame structure.
+ * This must be the first element of the
+ * Labelframe. */
+ /*
+ * Labelframe specific configuration settings.
+ */
+ Tcl_Obj *textPtr; /* Value of -text option: specifies text to
+ * display in button. */
+ Tk_Font tkfont; /* Value of -font option: specifies font to
+ * use for display text. */
+ XColor *textColorPtr; /* Value of -fg option: specifies foreground
+ * color in normal mode. */
+ int labelAnchor; /* Value of -labelanchor option: specifies
+ * where to place the label. */
+ Tk_Window labelWin; /* Value of -labelwidget option: Window to use
+ * as label for the frame. */
+ /*
+ * Labelframe specific fields for use with configuration settings above.
+ */
+ GC textGC; /* GC for drawing text in normal mode. */
+ Tk_TextLayout textLayout; /* Stored text layout information. */
+ XRectangle labelBox; /* The label's actual size and position. */
+ int labelReqWidth; /* The label's requested width. */
+ int labelReqHeight; /* The label's requested height. */
+ int labelTextX, labelTextY; /* Position of the text to be drawn. */
+} Labelframe;
+
+/*
+ * The following macros define how many extra pixels to leave around a label's
+ * text.
+ */
+
+#define LABELSPACING 1
+#define LABELMARGIN 4
+
+/*
+ * Flag bits for frames:
+ *
+ * REDRAW_PENDING: Non-zero means a DoWhenIdle handler has
+ * already been queued to redraw this window.
+ * GOT_FOCUS: Non-zero means this widget currently has the
+ * input focus.
+ */
+
+#define REDRAW_PENDING 1
+#define GOT_FOCUS 4
+
+/*
+ * The following enum is used to define a type for the -labelanchor option of
+ * the Labelframe widget. These values are used as indices into the string
+ * table below.
+ */
+
+enum labelanchor {
+ LABELANCHOR_E, LABELANCHOR_EN, LABELANCHOR_ES,
+ LABELANCHOR_N, LABELANCHOR_NE, LABELANCHOR_NW,
+ LABELANCHOR_S, LABELANCHOR_SE, LABELANCHOR_SW,
+ LABELANCHOR_W, LABELANCHOR_WN, LABELANCHOR_WS
+};
+
+static const char *const labelAnchorStrings[] = {
+ "e", "en", "es", "n", "ne", "nw", "s", "se", "sw", "w", "wn", "ws",
+ NULL
+};
+
+/*
+ * Information used for parsing configuration options. There are one common
+ * table used by all and one table for each widget class.
+ */
+
+static const Tk_OptionSpec commonOptSpec[] = {
+ {TK_OPTION_BORDER, "-background", "background", "Background",
+ DEF_FRAME_BG_COLOR, -1, Tk_Offset(Frame, border),
+ TK_OPTION_NULL_OK, DEF_FRAME_BG_MONO, 0},
+ {TK_OPTION_SYNONYM, "-bg", NULL, NULL,
+ NULL, 0, -1, 0, "-background", 0},
+ {TK_OPTION_STRING, "-colormap", "colormap", "Colormap",
+ DEF_FRAME_COLORMAP, -1, Tk_Offset(Frame, colormapName),
+ TK_OPTION_NULL_OK, 0, 0},
+ /*
+ * Having -container is useless in a labelframe since a container has
+ * no border. It should be deprecated.
+ */
+ {TK_OPTION_BOOLEAN, "-container", "container", "Container",
+ DEF_FRAME_CONTAINER, -1, Tk_Offset(Frame, isContainer), 0, 0, 0},
+ {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
+ DEF_FRAME_CURSOR, -1, Tk_Offset(Frame, cursor),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-height", "height", "Height",
+ DEF_FRAME_HEIGHT, -1, Tk_Offset(Frame, height), 0, 0, 0},
+ {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground",
+ "HighlightBackground", DEF_FRAME_HIGHLIGHT_BG, -1,
+ Tk_Offset(Frame, highlightBgColorPtr), 0, 0, 0},
+ {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
+ DEF_FRAME_HIGHLIGHT, -1, Tk_Offset(Frame, highlightColorPtr),
+ 0, 0, 0},
+ {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
+ "HighlightThickness", DEF_FRAME_HIGHLIGHT_WIDTH, -1,
+ Tk_Offset(Frame, highlightWidth), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
+ DEF_FRAME_PADX, Tk_Offset(Frame, padXPtr),
+ Tk_Offset(Frame, padX), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
+ DEF_FRAME_PADY, Tk_Offset(Frame, padYPtr),
+ Tk_Offset(Frame, padY), 0, 0, 0},
+ {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
+ DEF_FRAME_TAKE_FOCUS, -1, Tk_Offset(Frame, takeFocus),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-visual", "visual", "Visual",
+ DEF_FRAME_VISUAL, -1, Tk_Offset(Frame, visualName),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-width", "width", "Width",
+ DEF_FRAME_WIDTH, -1, Tk_Offset(Frame, width), 0, 0, 0},
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}
+};
+
+static const Tk_OptionSpec frameOptSpec[] = {
+ {TK_OPTION_SYNONYM, "-bd", NULL, NULL,
+ NULL, 0, -1, 0, "-borderwidth", 0},
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ DEF_FRAME_BORDER_WIDTH, -1, Tk_Offset(Frame, borderWidth), 0, 0, 0},
+ {TK_OPTION_STRING, "-class", "class", "Class",
+ DEF_FRAME_CLASS, -1, Tk_Offset(Frame, className), 0, 0, 0},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ DEF_FRAME_RELIEF, -1, Tk_Offset(Frame, relief), 0, 0, 0},
+ {TK_OPTION_END, NULL, NULL, NULL,
+ NULL, 0, 0, 0, commonOptSpec, 0}
+};
+
+static const Tk_OptionSpec toplevelOptSpec[] = {
+ {TK_OPTION_SYNONYM, "-bd", NULL, NULL,
+ NULL, 0, -1, 0, "-borderwidth", 0},
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ DEF_FRAME_BORDER_WIDTH, -1, Tk_Offset(Frame, borderWidth), 0, 0, 0},
+ {TK_OPTION_STRING, "-class", "class", "Class",
+ DEF_TOPLEVEL_CLASS, -1, Tk_Offset(Frame, className), 0, 0, 0},
+ {TK_OPTION_STRING, "-menu", "menu", "Menu",
+ DEF_TOPLEVEL_MENU, -1, Tk_Offset(Frame, menuName),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ DEF_FRAME_RELIEF, -1, Tk_Offset(Frame, relief), 0, 0, 0},
+ {TK_OPTION_STRING, "-screen", "screen", "Screen",
+ DEF_TOPLEVEL_SCREEN, -1, Tk_Offset(Frame, screenName),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-use", "use", "Use",
+ DEF_TOPLEVEL_USE, -1, Tk_Offset(Frame, useThis),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_END, NULL, NULL, NULL,
+ NULL, 0, 0, 0, commonOptSpec, 0}
+};
+
+static const Tk_OptionSpec labelframeOptSpec[] = {
+ {TK_OPTION_SYNONYM, "-bd", NULL, NULL,
+ NULL, 0, -1, 0, "-borderwidth", 0},
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ DEF_LABELFRAME_BORDER_WIDTH, -1, Tk_Offset(Frame, borderWidth),
+ 0, 0, 0},
+ {TK_OPTION_STRING, "-class", "class", "Class",
+ DEF_LABELFRAME_CLASS, -1, Tk_Offset(Frame, className), 0, 0, 0},
+ {TK_OPTION_SYNONYM, "-fg", "foreground", NULL,
+ NULL, 0, -1, 0, "-foreground", 0},
+ {TK_OPTION_FONT, "-font", "font", "Font",
+ DEF_LABELFRAME_FONT, -1, Tk_Offset(Labelframe, tkfont), 0, 0, 0},
+ {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
+ DEF_LABELFRAME_FG, -1, Tk_Offset(Labelframe, textColorPtr), 0, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-labelanchor", "labelAnchor", "LabelAnchor",
+ DEF_LABELFRAME_LABELANCHOR, -1, Tk_Offset(Labelframe, labelAnchor),
+ 0, labelAnchorStrings, 0},
+ {TK_OPTION_WINDOW, "-labelwidget", "labelWidget", "LabelWidget",
+ NULL, -1, Tk_Offset(Labelframe, labelWin), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ DEF_LABELFRAME_RELIEF, -1, Tk_Offset(Frame, relief), 0, 0, 0},
+ {TK_OPTION_STRING, "-text", "text", "Text",
+ DEF_LABELFRAME_TEXT, Tk_Offset(Labelframe, textPtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_END, NULL, NULL, NULL,
+ NULL, 0, 0, 0, commonOptSpec, 0}
+};
+
+/*
+ * Class names for widgets, indexed by FrameType.
+ */
+
+static const char *const classNames[] = {"Frame", "Toplevel", "Labelframe"};
+
+/*
+ * The following table maps from FrameType to the option template for that
+ * class of widgets.
+ */
+
+static const Tk_OptionSpec *const optionSpecs[] = {
+ frameOptSpec,
+ toplevelOptSpec,
+ labelframeOptSpec,
+};
+
+/*
+ * Forward declarations for functions defined later in this file:
+ */
+
+static void ComputeFrameGeometry(Frame *framePtr);
+static int ConfigureFrame(Tcl_Interp *interp, Frame *framePtr,
+ int objc, Tcl_Obj *const objv[]);
+static int CreateFrame(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const argv[],
+ enum FrameType type, const char *appName);
+static void DestroyFrame(void *memPtr);
+static void DestroyFramePartly(Frame *framePtr);
+static void DisplayFrame(ClientData clientData);
+static void FrameCmdDeletedProc(ClientData clientData);
+static void FrameEventProc(ClientData clientData,
+ XEvent *eventPtr);
+static void FrameLostSlaveProc(ClientData clientData,
+ Tk_Window tkwin);
+static void FrameRequestProc(ClientData clientData,
+ Tk_Window tkwin);
+static void FrameStructureProc(ClientData clientData,
+ XEvent *eventPtr);
+static int FrameWidgetObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static void FrameWorldChanged(ClientData instanceData);
+static void MapFrame(ClientData clientData);
+
+/*
+ * The structure below defines frame class behavior by means of functions that
+ * can be invoked from generic window code.
+ */
+
+static const Tk_ClassProcs frameClass = {
+ sizeof(Tk_ClassProcs), /* size */
+ FrameWorldChanged, /* worldChangedProc */
+ NULL, /* createProc */
+ NULL /* modalProc */
+};
+
+/*
+ * The structure below defines the official type record for the labelframe's
+ * geometry manager:
+ */
+
+static const Tk_GeomMgr frameGeomType = {
+ "labelframe", /* name */
+ FrameRequestProc, /* requestProc */
+ FrameLostSlaveProc /* lostSlaveProc */
+};
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_FrameObjCmd, Tk_ToplevelObjCmd, Tk_LabelframeObjCmd --
+ *
+ * These functions are invoked to process the "frame", "toplevel" and
+ * "labelframe" Tcl commands. See the user documentation for details on
+ * what they do.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation. These functions are just wrappers; they
+ * call CreateFrame to do all of the real work.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_FrameObjCmd(
+ ClientData clientData, /* Either NULL or pointer to option table. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ return CreateFrame(clientData, interp, objc, objv, TYPE_FRAME, NULL);
+}
+
+int
+Tk_ToplevelObjCmd(
+ ClientData clientData, /* Either NULL or pointer to option table. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ return CreateFrame(clientData, interp, objc, objv, TYPE_TOPLEVEL, NULL);
+}
+
+int
+Tk_LabelframeObjCmd(
+ ClientData clientData, /* Either NULL or pointer to option table. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ return CreateFrame(clientData, interp, objc, objv, TYPE_LABELFRAME, NULL);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkCreateFrame --
+ *
+ * This function is the old command function for the "frame" and
+ * "toplevel" commands. Now it is used directly by Tk_Init to create a
+ * new main window. See the user documentation for the "frame" and
+ * "toplevel" commands for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkCreateFrame(
+ ClientData clientData, /* Either NULL or pointer to option table. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char *const *argv, /* Argument strings. */
+ int toplevel, /* Non-zero means create a toplevel window,
+ * zero means create a frame. */
+ const char *appName) /* Should only be non-NULL if there is no main
+ * window associated with the interpreter.
+ * Gives the base name to use for the new
+ * application. */
+{
+ int result, i;
+ Tcl_Obj **objv = ckalloc((argc+1) * sizeof(Tcl_Obj **));
+
+ for (i=0; i<argc; i++) {
+ objv[i] = Tcl_NewStringObj(argv[i], -1);
+ Tcl_IncrRefCount(objv[i]);
+ }
+ objv[argc] = NULL;
+ result = CreateFrame(clientData, interp, argc, objv,
+ toplevel ? TYPE_TOPLEVEL : TYPE_FRAME, appName);
+ for (i=0; i<argc; i++) {
+ Tcl_DecrRefCount(objv[i]);
+ }
+ ckfree(objv);
+ return result;
+}
+
+int
+TkListCreateFrame(
+ ClientData clientData, /* Either NULL or pointer to option table. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ Tcl_Obj *listObj, /* List of arguments. */
+ int toplevel, /* Non-zero means create a toplevel window,
+ * zero means create a frame. */
+ Tcl_Obj *nameObj) /* Should only be non-NULL if there is no main
+ * window associated with the interpreter.
+ * Gives the base name to use for the new
+ * application. */
+{
+ int objc;
+ Tcl_Obj **objv;
+
+ if (TCL_OK != Tcl_ListObjGetElements(interp, listObj, &objc, &objv)) {
+ return TCL_ERROR;
+ }
+ return CreateFrame(clientData, interp, objc, objv,
+ toplevel ? TYPE_TOPLEVEL : TYPE_FRAME,
+ nameObj ? Tcl_GetString(nameObj) : NULL);
+}
+
+static int
+CreateFrame(
+ ClientData clientData, /* NULL. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[], /* Argument objects. */
+ enum FrameType type, /* What widget type to create. */
+ const char *appName) /* Should only be non-NULL if there are no
+ * Main window associated with the
+ * interpreter. Gives the base name to use for
+ * the new application. */
+{
+ Tk_Window tkwin;
+ Frame *framePtr;
+ Tk_OptionTable optionTable;
+ Tk_Window newWin;
+ const char *className, *screenName, *visualName, *colormapName;
+ const char *arg, *useOption;
+ int i, length, depth;
+ unsigned int mask;
+ Colormap colormap;
+ Visual *visual;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Create the option table for this widget class. If it has already been
+ * created, the cached pointer will be returned.
+ */
+
+ optionTable = Tk_CreateOptionTable(interp, optionSpecs[type]);
+
+ /*
+ * Pre-process the argument list. Scan through it to find any "-class",
+ * "-screen", "-visual", and "-colormap" options. These arguments need to
+ * be processed specially, before the window is configured using the usual
+ * Tk mechanisms.
+ */
+
+ className = colormapName = screenName = visualName = useOption = NULL;
+ colormap = None;
+ for (i = 2; i < objc; i += 2) {
+ arg = Tcl_GetStringFromObj(objv[i], &length);
+ if (length < 2) {
+ continue;
+ }
+ if ((arg[1] == 'c') && (length >= 3)
+ && (strncmp(arg, "-class", (unsigned) length) == 0)) {
+ className = Tcl_GetString(objv[i+1]);
+ } else if ((arg[1] == 'c') && (length >= 3)
+ && (strncmp(arg, "-colormap", (unsigned) length) == 0)) {
+ colormapName = Tcl_GetString(objv[i+1]);
+ } else if ((arg[1] == 's') && (type == TYPE_TOPLEVEL)
+ && (strncmp(arg, "-screen", (unsigned) length) == 0)) {
+ screenName = Tcl_GetString(objv[i+1]);
+ } else if ((arg[1] == 'u') && (type == TYPE_TOPLEVEL)
+ && (strncmp(arg, "-use", (unsigned) length) == 0)) {
+ useOption = Tcl_GetString(objv[i+1]);
+ } else if ((arg[1] == 'v')
+ && (strncmp(arg, "-visual", (unsigned) length) == 0)) {
+ visualName = Tcl_GetString(objv[i+1]);
+ }
+ }
+
+ /*
+ * Create the window, and deal with the special options -use, -classname,
+ * -colormap, -screenname, and -visual. These options must be handle
+ * before calling ConfigureFrame below, and they must also be processed in
+ * a particular order, for the following reasons:
+ * 1. Must set the window's class before calling ConfigureFrame, so that
+ * unspecified options are looked up in the option database using the
+ * correct class.
+ * 2. Must set visual information before calling ConfigureFrame so that
+ * colors are allocated in a proper colormap.
+ * 3. Must call TkpUseWindow before setting non-default visual
+ * information, since TkpUseWindow changes the defaults.
+ */
+
+ if (screenName == NULL) {
+ screenName = (type == TYPE_TOPLEVEL) ? "" : NULL;
+ }
+
+ /*
+ * Main window associated with interpreter. If we're called by Tk_Init to
+ * create a new application, then this is NULL.
+ */
+
+ tkwin = Tk_MainWindow(interp);
+ if (tkwin != NULL) {
+ newWin = Tk_CreateWindowFromPath(interp, tkwin, Tcl_GetString(objv[1]),
+ screenName);
+ } else if (appName == NULL) {
+ /*
+ * This occurs when someone tried to create a frame/toplevel while we
+ * are being destroyed. Let an error be thrown.
+ */
+
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "unable to create widget \"%s\"", Tcl_GetString(objv[1])));
+ Tcl_SetErrorCode(interp, "TK", "APPLICATION_GONE", NULL);
+ return TCL_ERROR;
+ } else {
+ /*
+ * We were called from Tk_Init; create a new application.
+ */
+
+ newWin = TkCreateMainWindow(interp, screenName, appName);
+ }
+ if (newWin == NULL) {
+ goto error;
+ }
+
+ /*
+ * Mark Tk frames as suitable candidates for [wm manage].
+ */
+
+ ((TkWindow *) newWin)->flags |= TK_WM_MANAGEABLE;
+
+ if (className == NULL) {
+ className = Tk_GetOption(newWin, "class", "Class");
+ if (className == NULL) {
+ className = classNames[type];
+ }
+ }
+ Tk_SetClass(newWin, className);
+ if (useOption == NULL) {
+ useOption = Tk_GetOption(newWin, "use", "Use");
+ }
+ if ((useOption != NULL) && (*useOption != 0)
+ && (TkpUseWindow(interp, newWin, useOption) != TCL_OK)) {
+ goto error;
+ }
+ if (visualName == NULL) {
+ visualName = Tk_GetOption(newWin, "visual", "Visual");
+ }
+ if (colormapName == NULL) {
+ colormapName = Tk_GetOption(newWin, "colormap", "Colormap");
+ }
+ if ((colormapName != NULL) && (*colormapName == 0)) {
+ colormapName = NULL;
+ }
+ if (visualName != NULL) {
+ visual = Tk_GetVisual(interp, newWin, visualName, &depth,
+ (colormapName == NULL) ? &colormap : NULL);
+ if (visual == NULL) {
+ goto error;
+ }
+ Tk_SetWindowVisual(newWin, visual, depth, colormap);
+ }
+ if (colormapName != NULL) {
+ colormap = Tk_GetColormap(interp, newWin, colormapName);
+ if (colormap == None) {
+ goto error;
+ }
+ Tk_SetWindowColormap(newWin, colormap);
+ }
+
+ /*
+ * For top-level windows, provide an initial geometry request of 200x200,
+ * just so the window looks nicer on the screen if it doesn't request a
+ * size for itself.
+ */
+
+ if (type == TYPE_TOPLEVEL) {
+ Tk_GeometryRequest(newWin, 200, 200);
+ }
+
+ /*
+ * Create the widget record, process configuration options, and create
+ * event handlers. Then fill in a few additional fields in the widget
+ * record from the special options.
+ */
+
+ if (type == TYPE_LABELFRAME) {
+ framePtr = ckalloc(sizeof(Labelframe));
+ memset(framePtr, 0, sizeof(Labelframe));
+ } else {
+ framePtr = ckalloc(sizeof(Frame));
+ memset(framePtr, 0, sizeof(Frame));
+ }
+ framePtr->tkwin = newWin;
+ framePtr->display = Tk_Display(newWin);
+ framePtr->interp = interp;
+ framePtr->widgetCmd = Tcl_CreateObjCommand(interp, Tk_PathName(newWin),
+ FrameWidgetObjCmd, framePtr, FrameCmdDeletedProc);
+ framePtr->optionTable = optionTable;
+ framePtr->type = type;
+ framePtr->colormap = colormap;
+ framePtr->relief = TK_RELIEF_FLAT;
+ framePtr->cursor = NULL;
+
+ if (framePtr->type == TYPE_LABELFRAME) {
+ Labelframe *labelframePtr = (Labelframe *) framePtr;
+
+ labelframePtr->labelAnchor = LABELANCHOR_NW;
+ labelframePtr->textGC = NULL;
+ }
+
+ /*
+ * Store backreference to frame widget in window structure.
+ */
+
+ Tk_SetClassProcs(newWin, &frameClass, framePtr);
+
+ mask = ExposureMask | StructureNotifyMask | FocusChangeMask;
+ if (type == TYPE_TOPLEVEL) {
+ mask |= ActivateMask;
+ }
+ Tk_CreateEventHandler(newWin, mask, FrameEventProc, framePtr);
+ if ((Tk_InitOptions(interp, (char *) framePtr, optionTable, newWin)
+ != TCL_OK) ||
+ (ConfigureFrame(interp, framePtr, objc-2, objv+2) != TCL_OK)) {
+ goto error;
+ }
+ if (framePtr->isContainer) {
+ if (framePtr->useThis != NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "windows cannot have both the -use and the -container"
+ " option set", -1));
+ Tcl_SetErrorCode(interp, "TK", "FRAME", "CONTAINMENT", NULL);
+ goto error;
+ }
+ TkpMakeContainer(framePtr->tkwin);
+ }
+ if (type == TYPE_TOPLEVEL) {
+ Tcl_DoWhenIdle(MapFrame, framePtr);
+ }
+ Tcl_SetObjResult(interp, TkNewWindowObj(newWin));
+ return TCL_OK;
+
+ error:
+ if (newWin != NULL) {
+ Tk_DestroyWindow(newWin);
+ }
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * FrameWidgetObjCmd --
+ *
+ * This function is invoked to process the Tcl command that corresponds
+ * to a frame widget. See the user documentation for details on what it
+ * does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+FrameWidgetObjCmd(
+ ClientData clientData, /* Information about frame widget. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ static const char *const frameOptions[] = {
+ "cget", "configure", NULL
+ };
+ enum options {
+ FRAME_CGET, FRAME_CONFIGURE
+ };
+ register Frame *framePtr = clientData;
+ int result = TCL_OK, index;
+ int c, i, length;
+ Tcl_Obj *objPtr;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObjStruct(interp, objv[1], frameOptions,
+ sizeof(char *), "option", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_Preserve(framePtr);
+ switch ((enum options) index) {
+ case FRAME_CGET:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option");
+ result = TCL_ERROR;
+ goto done;
+ }
+ objPtr = Tk_GetOptionValue(interp, (char *) framePtr,
+ framePtr->optionTable, objv[2], framePtr->tkwin);
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ goto done;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ break;
+ case FRAME_CONFIGURE:
+ if (objc <= 3) {
+ objPtr = Tk_GetOptionInfo(interp, (char *) framePtr,
+ framePtr->optionTable, (objc == 3) ? objv[2] : NULL,
+ framePtr->tkwin);
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ goto done;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ } else {
+ /*
+ * Don't allow the options -class, -colormap, -container, -screen,
+ * -use, or -visual to be changed.
+ */
+
+ for (i = 2; i < objc; i++) {
+ const char *arg = Tcl_GetStringFromObj(objv[i], &length);
+
+ if (length < 2) {
+ continue;
+ }
+ c = arg[1];
+ if (((c == 'c') && (length >= 2)
+ && (strncmp(arg, "-class", (unsigned)length) == 0))
+ || ((c == 'c') && (length >= 3)
+ && (strncmp(arg, "-colormap", (unsigned)length) == 0))
+ || ((c == 'c') && (length >= 3)
+ && (strncmp(arg, "-container", (unsigned)length) == 0))
+ || ((c == 's') && (framePtr->type == TYPE_TOPLEVEL)
+ && (strncmp(arg, "-screen", (unsigned)length) == 0))
+ || ((c == 'u') && (framePtr->type == TYPE_TOPLEVEL)
+ && (strncmp(arg, "-use", (unsigned)length) == 0))
+ || ((c == 'v')
+ && (strncmp(arg, "-visual", (unsigned)length) == 0))) {
+
+#ifdef SUPPORT_CONFIG_EMBEDDED
+ if (c == 'u') {
+ const char *string = Tcl_GetString(objv[i+1]);
+
+ if (TkpUseWindow(interp, framePtr->tkwin,
+ string) != TCL_OK) {
+ result = TCL_ERROR;
+ goto done;
+ }
+ continue;
+ }
+#endif
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't modify %s option after widget is created",
+ arg));
+ Tcl_SetErrorCode(interp, "TK", "FRAME", "CREATE_ONLY",
+ NULL);
+ result = TCL_ERROR;
+ goto done;
+ }
+ }
+ result = ConfigureFrame(interp, framePtr, objc-2, objv+2);
+ }
+ break;
+ }
+
+ done:
+ Tcl_Release(framePtr);
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyFrame --
+ *
+ * This function is invoked by Tcl_EventuallyFree or Tcl_Release to clean
+ * up the internal structure of a frame at a safe time (when no-one is
+ * using it anymore).
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Everything associated with the frame is freed up.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DestroyFrame(
+ void *memPtr) /* Info about frame widget. */
+{
+ register Frame *framePtr = memPtr;
+ register Labelframe *labelframePtr = memPtr;
+
+ if (framePtr->type == TYPE_LABELFRAME) {
+ Tk_FreeTextLayout(labelframePtr->textLayout);
+ if (labelframePtr->textGC != NULL) {
+ Tk_FreeGC(framePtr->display, labelframePtr->textGC);
+ }
+ }
+ if (framePtr->colormap != None) {
+ Tk_FreeColormap(framePtr->display, framePtr->colormap);
+ }
+ ckfree(framePtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyFramePartly --
+ *
+ * This function is invoked to clean up everything that needs tkwin to be
+ * defined when deleted. During the destruction process tkwin is always
+ * set to NULL and this function must be called before that happens.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Some things associated with the frame are freed up.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DestroyFramePartly(
+ Frame *framePtr) /* Info about frame widget. */
+{
+ register Labelframe *labelframePtr = (Labelframe *) framePtr;
+
+ if (framePtr->type == TYPE_LABELFRAME && labelframePtr->labelWin != NULL) {
+ Tk_DeleteEventHandler(labelframePtr->labelWin, StructureNotifyMask,
+ FrameStructureProc, framePtr);
+ Tk_ManageGeometry(labelframePtr->labelWin, NULL, NULL);
+ if (framePtr->tkwin != Tk_Parent(labelframePtr->labelWin)) {
+ Tk_UnmaintainGeometry(labelframePtr->labelWin, framePtr->tkwin);
+ }
+ Tk_UnmapWindow(labelframePtr->labelWin);
+ labelframePtr->labelWin = NULL;
+ }
+
+ Tk_FreeConfigOptions((char *) framePtr, framePtr->optionTable,
+ framePtr->tkwin);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConfigureFrame --
+ *
+ * This function is called to process an objv/objc list, plus the Tk
+ * option database, in order to configure (or reconfigure) a frame
+ * widget.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If TCL_ERROR is returned,
+ * then the interp's result contains an error message.
+ *
+ * Side effects:
+ * Configuration information, such as text string, colors, font, etc. get
+ * set for framePtr; old resources get freed, if there were any.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ConfigureFrame(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ register Frame *framePtr, /* Information about widget; may or may not
+ * already have values for some fields. */
+ int objc, /* Number of valid entries in objv. */
+ Tcl_Obj *const objv[]) /* Arguments. */
+{
+ Tk_SavedOptions savedOptions;
+ char *oldMenuName;
+ Tk_Window oldWindow = NULL;
+ Labelframe *labelframePtr = (Labelframe *) framePtr;
+
+ /*
+ * Need the old menubar name for the menu code to delete it.
+ */
+
+ if (framePtr->menuName == NULL) {
+ oldMenuName = NULL;
+ } else {
+ oldMenuName = ckalloc(strlen(framePtr->menuName) + 1);
+ strcpy(oldMenuName, framePtr->menuName);
+ }
+
+ if (framePtr->type == TYPE_LABELFRAME) {
+ oldWindow = labelframePtr->labelWin;
+ }
+ if (Tk_SetOptions(interp, (char *) framePtr,
+ framePtr->optionTable, objc, objv,
+ framePtr->tkwin, &savedOptions, NULL) != TCL_OK) {
+ if (oldMenuName != NULL) {
+ ckfree(oldMenuName);
+ }
+ return TCL_ERROR;
+ }
+ Tk_FreeSavedOptions(&savedOptions);
+
+ /*
+ * A few of the options require additional processing.
+ */
+
+ if ((((oldMenuName == NULL) && (framePtr->menuName != NULL))
+ || ((oldMenuName != NULL) && (framePtr->menuName == NULL))
+ || ((oldMenuName != NULL) && (framePtr->menuName != NULL)
+ && strcmp(oldMenuName, framePtr->menuName) != 0))
+ && framePtr->type == TYPE_TOPLEVEL) {
+ TkSetWindowMenuBar(interp, framePtr->tkwin, oldMenuName,
+ framePtr->menuName);
+ }
+
+ if (oldMenuName != NULL) {
+ ckfree(oldMenuName);
+ }
+
+ if (framePtr->border != NULL) {
+ Tk_SetBackgroundFromBorder(framePtr->tkwin, framePtr->border);
+ } else {
+ Tk_SetWindowBackgroundPixmap(framePtr->tkwin, None);
+ }
+
+ if (framePtr->highlightWidth < 0) {
+ framePtr->highlightWidth = 0;
+ }
+ if (framePtr->padX < 0) {
+ framePtr->padX = 0;
+ }
+ if (framePtr->padY < 0) {
+ framePtr->padY = 0;
+ }
+
+ /*
+ * If a -labelwidget is specified, check that it is valid and set up
+ * geometry management for it.
+ */
+
+ if (framePtr->type == TYPE_LABELFRAME) {
+ if (oldWindow != labelframePtr->labelWin) {
+ if (oldWindow != NULL) {
+ Tk_DeleteEventHandler(oldWindow, StructureNotifyMask,
+ FrameStructureProc, framePtr);
+ Tk_ManageGeometry(oldWindow, NULL, NULL);
+ Tk_UnmaintainGeometry(oldWindow, framePtr->tkwin);
+ Tk_UnmapWindow(oldWindow);
+ }
+ if (labelframePtr->labelWin != NULL) {
+ Tk_Window ancestor, parent, sibling = NULL;
+
+ /*
+ * Make sure that the frame is either the parent of the window
+ * used as label or a descendant of that parent. Also, don't
+ * allow a top-level window to be managed inside the frame.
+ */
+
+ parent = Tk_Parent(labelframePtr->labelWin);
+ for (ancestor = framePtr->tkwin; ;
+ ancestor = Tk_Parent(ancestor)) {
+ if (ancestor == parent) {
+ break;
+ }
+ sibling = ancestor;
+ if (Tk_IsTopLevel(ancestor)) {
+ goto badLabelWindow;
+ }
+ }
+ if (Tk_IsTopLevel(labelframePtr->labelWin)) {
+ goto badLabelWindow;
+ }
+ if (labelframePtr->labelWin == framePtr->tkwin) {
+ goto badLabelWindow;
+ }
+ Tk_CreateEventHandler(labelframePtr->labelWin,
+ StructureNotifyMask, FrameStructureProc, framePtr);
+ Tk_ManageGeometry(labelframePtr->labelWin, &frameGeomType,
+ framePtr);
+
+ /*
+ * If the frame is not parent to the label, make sure the
+ * label is above its sibling in the stacking order.
+ */
+
+ if (sibling != NULL) {
+ Tk_RestackWindow(labelframePtr->labelWin, Above, sibling);
+ }
+ }
+ }
+ }
+
+ FrameWorldChanged(framePtr);
+ return TCL_OK;
+
+ badLabelWindow:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't use %s as label in this frame",
+ Tk_PathName(labelframePtr->labelWin)));
+ Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "HIERARCHY", NULL);
+ labelframePtr->labelWin = NULL;
+ return TCL_ERROR;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FrameWorldChanged --
+ *
+ * This function is called when the world has changed in some way and the
+ * widget needs to recompute all its graphics contexts and determine its
+ * new geometry.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Frame will be relayed out and redisplayed.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+FrameWorldChanged(
+ ClientData instanceData) /* Information about widget. */
+{
+ Frame *framePtr = instanceData;
+ Labelframe *labelframePtr = instanceData;
+ Tk_Window tkwin = framePtr->tkwin;
+ XGCValues gcValues;
+ GC gc;
+ int anyTextLabel, anyWindowLabel;
+ int bWidthLeft, bWidthRight, bWidthTop, bWidthBottom;
+ const char *labelText;
+
+ anyTextLabel = (framePtr->type == TYPE_LABELFRAME) &&
+ (labelframePtr->textPtr != NULL) &&
+ (labelframePtr->labelWin == NULL);
+ anyWindowLabel = (framePtr->type == TYPE_LABELFRAME) &&
+ (labelframePtr->labelWin != NULL);
+
+ if (framePtr->type == TYPE_LABELFRAME) {
+ /*
+ * The textGC is needed even in the labelWin case, so it's always
+ * created for a labelframe.
+ */
+
+ gcValues.font = Tk_FontId(labelframePtr->tkfont);
+ gcValues.foreground = labelframePtr->textColorPtr->pixel;
+ gcValues.graphics_exposures = False;
+ gc = Tk_GetGC(tkwin, GCForeground | GCFont | GCGraphicsExposures,
+ &gcValues);
+ if (labelframePtr->textGC != NULL) {
+ Tk_FreeGC(framePtr->display, labelframePtr->textGC);
+ }
+ labelframePtr->textGC = gc;
+
+ /*
+ * Calculate label size.
+ */
+
+ labelframePtr->labelReqWidth = labelframePtr->labelReqHeight = 0;
+
+ if (anyTextLabel) {
+ labelText = Tcl_GetString(labelframePtr->textPtr);
+ Tk_FreeTextLayout(labelframePtr->textLayout);
+ labelframePtr->textLayout =
+ Tk_ComputeTextLayout(labelframePtr->tkfont,
+ labelText, -1, 0, TK_JUSTIFY_CENTER, 0,
+ &labelframePtr->labelReqWidth,
+ &labelframePtr->labelReqHeight);
+ labelframePtr->labelReqWidth += 2 * LABELSPACING;
+ labelframePtr->labelReqHeight += 2 * LABELSPACING;
+ } else if (anyWindowLabel) {
+ labelframePtr->labelReqWidth = Tk_ReqWidth(labelframePtr->labelWin);
+ labelframePtr->labelReqHeight =
+ Tk_ReqHeight(labelframePtr->labelWin);
+ }
+
+ /*
+ * Make sure label size is at least as big as the border. This
+ * simplifies later calculations and gives a better appearance with
+ * thick borders.
+ */
+
+ if ((labelframePtr->labelAnchor >= LABELANCHOR_N) &&
+ (labelframePtr->labelAnchor <= LABELANCHOR_SW)) {
+ if (labelframePtr->labelReqHeight < framePtr->borderWidth) {
+ labelframePtr->labelReqHeight = framePtr->borderWidth;
+ }
+ } else {
+ if (labelframePtr->labelReqWidth < framePtr->borderWidth) {
+ labelframePtr->labelReqWidth = framePtr->borderWidth;
+ }
+ }
+ }
+
+ /*
+ * Calculate individual border widths.
+ */
+
+ bWidthBottom = bWidthTop = bWidthRight = bWidthLeft =
+ framePtr->borderWidth + framePtr->highlightWidth;
+
+ bWidthLeft += framePtr->padX;
+ bWidthRight += framePtr->padX;
+ bWidthTop += framePtr->padY;
+ bWidthBottom += framePtr->padY;
+
+ if (anyTextLabel || anyWindowLabel) {
+ switch (labelframePtr->labelAnchor) {
+ case LABELANCHOR_E:
+ case LABELANCHOR_EN:
+ case LABELANCHOR_ES:
+ bWidthRight += labelframePtr->labelReqWidth -
+ framePtr->borderWidth;
+ break;
+ case LABELANCHOR_N:
+ case LABELANCHOR_NE:
+ case LABELANCHOR_NW:
+ bWidthTop += labelframePtr->labelReqHeight - framePtr->borderWidth;
+ break;
+ case LABELANCHOR_S:
+ case LABELANCHOR_SE:
+ case LABELANCHOR_SW:
+ bWidthBottom += labelframePtr->labelReqHeight -
+ framePtr->borderWidth;
+ break;
+ default:
+ bWidthLeft += labelframePtr->labelReqWidth - framePtr->borderWidth;
+ break;
+ }
+ }
+
+ Tk_SetInternalBorderEx(tkwin, bWidthLeft, bWidthRight, bWidthTop,
+ bWidthBottom);
+
+ ComputeFrameGeometry(framePtr);
+
+ /*
+ * A labelframe should request size for its label.
+ */
+
+ if (framePtr->type == TYPE_LABELFRAME) {
+ int minwidth = labelframePtr->labelReqWidth;
+ int minheight = labelframePtr->labelReqHeight;
+ int padding = framePtr->highlightWidth;
+
+ if (framePtr->borderWidth > 0) {
+ padding += framePtr->borderWidth + LABELMARGIN;
+ }
+ padding *= 2;
+ if ((labelframePtr->labelAnchor >= LABELANCHOR_N) &&
+ (labelframePtr->labelAnchor <= LABELANCHOR_SW)) {
+ minwidth += padding;
+ minheight += framePtr->borderWidth + framePtr->highlightWidth;
+ } else {
+ minheight += padding;
+ minwidth += framePtr->borderWidth + framePtr->highlightWidth;
+ }
+ Tk_SetMinimumRequestSize(tkwin, minwidth, minheight);
+ }
+
+ if ((framePtr->width > 0) || (framePtr->height > 0)) {
+ Tk_GeometryRequest(tkwin, framePtr->width, framePtr->height);
+ }
+
+ if (Tk_IsMapped(tkwin)) {
+ if (!(framePtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DisplayFrame, framePtr);
+ }
+ framePtr->flags |= REDRAW_PENDING;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ComputeFrameGeometry --
+ *
+ * This function is called to compute various geometrical information for
+ * a frame, such as where various things get displayed. It's called when
+ * the window is reconfigured.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Display-related numbers get changed in *framePtr.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ComputeFrameGeometry(
+ register Frame *framePtr) /* Information about widget. */
+{
+ int otherWidth, otherHeight, otherWidthT, otherHeightT, padding;
+ int maxWidth, maxHeight;
+ Tk_Window tkwin;
+ Labelframe *labelframePtr = (Labelframe *) framePtr;
+
+ /*
+ * We have nothing to do here unless there is a label.
+ */
+
+ if (framePtr->type != TYPE_LABELFRAME) {
+ return;
+ }
+ if (labelframePtr->textPtr == NULL && labelframePtr->labelWin == NULL) {
+ return;
+ }
+
+ tkwin = framePtr->tkwin;
+
+ /*
+ * Calculate the available size for the label
+ */
+
+ labelframePtr->labelBox.width = labelframePtr->labelReqWidth;
+ labelframePtr->labelBox.height = labelframePtr->labelReqHeight;
+
+ padding = framePtr->highlightWidth;
+ if (framePtr->borderWidth > 0) {
+ padding += framePtr->borderWidth + LABELMARGIN;
+ }
+ padding *= 2;
+
+ maxHeight = Tk_Height(tkwin);
+ maxWidth = Tk_Width(tkwin);
+
+ if ((labelframePtr->labelAnchor >= LABELANCHOR_N) &&
+ (labelframePtr->labelAnchor <= LABELANCHOR_SW)) {
+ maxWidth -= padding;
+ if (maxWidth < 1) {
+ maxWidth = 1;
+ }
+ } else {
+ maxHeight -= padding;
+ if (maxHeight < 1) {
+ maxHeight = 1;
+ }
+ }
+ if (labelframePtr->labelBox.width > maxWidth) {
+ labelframePtr->labelBox.width = maxWidth;
+ }
+ if (labelframePtr->labelBox.height > maxHeight) {
+ labelframePtr->labelBox.height = maxHeight;
+ }
+
+ /*
+ * Calculate label and text position. The text's position is based on the
+ * requested size (= the text's real size) to get proper alignment if the
+ * text does not fit.
+ */
+
+ otherWidth = Tk_Width(tkwin) - labelframePtr->labelBox.width;
+ otherHeight = Tk_Height(tkwin) - labelframePtr->labelBox.height;
+ otherWidthT = Tk_Width(tkwin) - labelframePtr->labelReqWidth;
+ otherHeightT = Tk_Height(tkwin) - labelframePtr->labelReqHeight;
+ padding = framePtr->highlightWidth;
+
+ switch (labelframePtr->labelAnchor) {
+ case LABELANCHOR_E:
+ case LABELANCHOR_EN:
+ case LABELANCHOR_ES:
+ labelframePtr->labelTextX = otherWidthT - padding;
+ labelframePtr->labelBox.x = otherWidth - padding;
+ break;
+ case LABELANCHOR_N:
+ case LABELANCHOR_NE:
+ case LABELANCHOR_NW:
+ labelframePtr->labelTextY = padding;
+ labelframePtr->labelBox.y = padding;
+ break;
+ case LABELANCHOR_S:
+ case LABELANCHOR_SE:
+ case LABELANCHOR_SW:
+ labelframePtr->labelTextY = otherHeightT - padding;
+ labelframePtr->labelBox.y = otherHeight - padding;
+ break;
+ default:
+ labelframePtr->labelTextX = padding;
+ labelframePtr->labelBox.x = padding;
+ break;
+ }
+
+ if (framePtr->borderWidth > 0) {
+ padding += framePtr->borderWidth + LABELMARGIN;
+ }
+
+ switch (labelframePtr->labelAnchor) {
+ case LABELANCHOR_NW:
+ case LABELANCHOR_SW:
+ labelframePtr->labelTextX = padding;
+ labelframePtr->labelBox.x = padding;
+ break;
+ case LABELANCHOR_N:
+ case LABELANCHOR_S:
+ labelframePtr->labelTextX = otherWidthT / 2;
+ labelframePtr->labelBox.x = otherWidth / 2;
+ break;
+ case LABELANCHOR_NE:
+ case LABELANCHOR_SE:
+ labelframePtr->labelTextX = otherWidthT - padding;
+ labelframePtr->labelBox.x = otherWidth - padding;
+ break;
+ case LABELANCHOR_EN:
+ case LABELANCHOR_WN:
+ labelframePtr->labelTextY = padding;
+ labelframePtr->labelBox.y = padding;
+ break;
+ case LABELANCHOR_E:
+ case LABELANCHOR_W:
+ labelframePtr->labelTextY = otherHeightT / 2;
+ labelframePtr->labelBox.y = otherHeight / 2;
+ break;
+ default:
+ labelframePtr->labelTextY = otherHeightT - padding;
+ labelframePtr->labelBox.y = otherHeight - padding;
+ break;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DisplayFrame --
+ *
+ * This function is invoked to display a frame widget.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Commands are output to X to display the frame in its current mode.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DisplayFrame(
+ ClientData clientData) /* Information about widget. */
+{
+ register Frame *framePtr = clientData;
+ register Tk_Window tkwin = framePtr->tkwin;
+ int bdX1, bdY1, bdX2, bdY2, hlWidth;
+ Pixmap pixmap;
+ TkRegion clipRegion = NULL;
+
+ framePtr->flags &= ~REDRAW_PENDING;
+ if ((framePtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
+ return;
+ }
+
+ /*
+ * Highlight shall always be drawn if it exists, so do that first.
+ */
+
+ hlWidth = framePtr->highlightWidth;
+
+ if (hlWidth != 0) {
+ GC fgGC, bgGC;
+
+ bgGC = Tk_GCForColor(framePtr->highlightBgColorPtr,
+ Tk_WindowId(tkwin));
+ if (framePtr->flags & GOT_FOCUS) {
+ fgGC = Tk_GCForColor(framePtr->highlightColorPtr,
+ Tk_WindowId(tkwin));
+ TkpDrawHighlightBorder(tkwin, fgGC, bgGC, hlWidth,
+ Tk_WindowId(tkwin));
+ } else {
+ TkpDrawHighlightBorder(tkwin, bgGC, bgGC, hlWidth,
+ Tk_WindowId(tkwin));
+ }
+ }
+
+ /*
+ * If -background is set to "", no interior is drawn.
+ */
+
+ if (framePtr->border == NULL) {
+ return;
+ }
+
+ if (framePtr->type != TYPE_LABELFRAME) {
+ /*
+ * Pass to platform specific draw function. In general, it just draws
+ * a simple rectangle, but it may "theme" the background.
+ */
+
+ noLabel:
+ TkpDrawFrame(tkwin, framePtr->border, hlWidth,
+ framePtr->borderWidth, framePtr->relief);
+ } else {
+ Labelframe *labelframePtr = (Labelframe *) framePtr;
+
+ if ((labelframePtr->textPtr == NULL) &&
+ (labelframePtr->labelWin == NULL)) {
+ goto noLabel;
+ }
+
+#ifndef TK_NO_DOUBLE_BUFFERING
+ /*
+ * In order to avoid screen flashes, this function redraws the frame
+ * into off-screen memory, then copies it back on-screen in a single
+ * operation. This means there's no point in time where the on-screen
+ * image has been cleared.
+ */
+
+ pixmap = Tk_GetPixmap(framePtr->display, Tk_WindowId(tkwin),
+ Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));
+#else
+ pixmap = Tk_WindowId(tkwin);
+#endif /* TK_NO_DOUBLE_BUFFERING */
+
+ /*
+ * Clear the pixmap.
+ */
+
+ Tk_Fill3DRectangle(tkwin, pixmap, framePtr->border, 0, 0,
+ Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);
+
+ /*
+ * Calculate how the label affects the border's position.
+ */
+
+ bdX1 = bdY1 = hlWidth;
+ bdX2 = Tk_Width(tkwin) - hlWidth;
+ bdY2 = Tk_Height(tkwin) - hlWidth;
+
+ switch (labelframePtr->labelAnchor) {
+ case LABELANCHOR_E:
+ case LABELANCHOR_EN:
+ case LABELANCHOR_ES:
+ bdX2 -= (labelframePtr->labelBox.width-framePtr->borderWidth) / 2;
+ break;
+ case LABELANCHOR_N:
+ case LABELANCHOR_NE:
+ case LABELANCHOR_NW:
+ /*
+ * Since the glyphs of the text tend to be in the lower part we
+ * favor a lower border position by rounding up.
+ */
+
+ bdY1 += (labelframePtr->labelBox.height-framePtr->borderWidth+1)/2;
+ break;
+ case LABELANCHOR_S:
+ case LABELANCHOR_SE:
+ case LABELANCHOR_SW:
+ bdY2 -= (labelframePtr->labelBox.height-framePtr->borderWidth) / 2;
+ break;
+ default:
+ bdX1 += (labelframePtr->labelBox.width-framePtr->borderWidth) / 2;
+ break;
+ }
+
+ /*
+ * Draw border
+ */
+
+ Tk_Draw3DRectangle(tkwin, pixmap, framePtr->border, bdX1, bdY1,
+ bdX2 - bdX1, bdY2 - bdY1, framePtr->borderWidth,
+ framePtr->relief);
+
+ if (labelframePtr->labelWin == NULL) {
+ /*
+ * Clear behind the label
+ */
+
+ Tk_Fill3DRectangle(tkwin, pixmap,
+ framePtr->border, labelframePtr->labelBox.x,
+ labelframePtr->labelBox.y, labelframePtr->labelBox.width,
+ labelframePtr->labelBox.height, 0, TK_RELIEF_FLAT);
+
+ /*
+ * Draw label. If there is not room for the entire label, use
+ * clipping to get a nice appearance.
+ */
+
+ if ((labelframePtr->labelBox.width < labelframePtr->labelReqWidth)
+ || (labelframePtr->labelBox.height <
+ labelframePtr->labelReqHeight)) {
+ clipRegion = TkCreateRegion();
+ TkUnionRectWithRegion(&labelframePtr->labelBox, clipRegion,
+ clipRegion);
+ TkSetRegion(framePtr->display, labelframePtr->textGC,
+ clipRegion);
+ }
+
+ Tk_DrawTextLayout(framePtr->display, pixmap,
+ labelframePtr->textGC, labelframePtr->textLayout,
+ labelframePtr->labelTextX + LABELSPACING,
+ labelframePtr->labelTextY + LABELSPACING, 0, -1);
+
+ if (clipRegion != NULL) {
+ XSetClipMask(framePtr->display, labelframePtr->textGC, None);
+ TkDestroyRegion(clipRegion);
+ }
+ } else {
+ /*
+ * Reposition and map the window (but in different ways depending
+ * on whether the frame is the window's parent).
+ */
+
+ if (framePtr->tkwin == Tk_Parent(labelframePtr->labelWin)) {
+ if ((labelframePtr->labelBox.x != Tk_X(labelframePtr->labelWin))
+ || (labelframePtr->labelBox.y !=
+ Tk_Y(labelframePtr->labelWin))
+ || (labelframePtr->labelBox.width !=
+ Tk_Width(labelframePtr->labelWin))
+ || (labelframePtr->labelBox.height !=
+ Tk_Height(labelframePtr->labelWin))) {
+ Tk_MoveResizeWindow(labelframePtr->labelWin,
+ labelframePtr->labelBox.x,
+ labelframePtr->labelBox.y,
+ labelframePtr->labelBox.width,
+ labelframePtr->labelBox.height);
+ }
+ Tk_MapWindow(labelframePtr->labelWin);
+ } else {
+ Tk_MaintainGeometry(labelframePtr->labelWin, framePtr->tkwin,
+ labelframePtr->labelBox.x, labelframePtr->labelBox.y,
+ labelframePtr->labelBox.width,
+ labelframePtr->labelBox.height);
+ }
+ }
+
+#ifndef TK_NO_DOUBLE_BUFFERING
+ /*
+ * Everything's been redisplayed; now copy the pixmap onto the screen
+ * and free up the pixmap.
+ */
+
+ XCopyArea(framePtr->display, pixmap, Tk_WindowId(tkwin),
+ labelframePtr->textGC, hlWidth, hlWidth,
+ (unsigned) (Tk_Width(tkwin) - 2 * hlWidth),
+ (unsigned) (Tk_Height(tkwin) - 2 * hlWidth),
+ hlWidth, hlWidth);
+ Tk_FreePixmap(framePtr->display, pixmap);
+#endif /* TK_NO_DOUBLE_BUFFERING */
+ }
+
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * FrameEventProc --
+ *
+ * This function is invoked by the Tk dispatcher on structure changes to
+ * a frame. For frames with 3D borders, this function is also invoked for
+ * exposures.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * When the window gets deleted, internal structures get cleaned up.
+ * When it gets exposed, it is redisplayed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+FrameEventProc(
+ ClientData clientData, /* Information about window. */
+ register XEvent *eventPtr) /* Information about event. */
+{
+ register Frame *framePtr = clientData;
+
+ if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {
+ goto redraw;
+ } else if (eventPtr->type == ConfigureNotify) {
+ ComputeFrameGeometry(framePtr);
+ goto redraw;
+ } else if (eventPtr->type == DestroyNotify) {
+ if (framePtr->menuName != NULL) {
+ TkSetWindowMenuBar(framePtr->interp, framePtr->tkwin,
+ framePtr->menuName, NULL);
+ ckfree(framePtr->menuName);
+ framePtr->menuName = NULL;
+ }
+ if (framePtr->tkwin != NULL) {
+ /*
+ * If this window is a container, then this event could be coming
+ * from the embedded application, in which case Tk_DestroyWindow
+ * hasn't been called yet. When Tk_DestroyWindow is called later,
+ * then another destroy event will be generated. We need to be
+ * sure we ignore the second event, since the frame could be gone
+ * by then. To do so, delete the event handler explicitly
+ * (normally it's done implicitly by Tk_DestroyWindow).
+ */
+
+ /*
+ * Since the tkwin pointer will be gone when we reach
+ * DestroyFrame, we must free all options now.
+ */
+
+ DestroyFramePartly(framePtr);
+
+ Tk_DeleteEventHandler(framePtr->tkwin,
+ ExposureMask|StructureNotifyMask|FocusChangeMask,
+ FrameEventProc, framePtr);
+ framePtr->tkwin = NULL;
+ Tcl_DeleteCommandFromToken(framePtr->interp, framePtr->widgetCmd);
+ }
+ if (framePtr->flags & REDRAW_PENDING) {
+ Tcl_CancelIdleCall(DisplayFrame, framePtr);
+ }
+ Tcl_CancelIdleCall(MapFrame, framePtr);
+ Tcl_EventuallyFree(framePtr, (Tcl_FreeProc *) DestroyFrame);
+ } else if (eventPtr->type == FocusIn) {
+ if (eventPtr->xfocus.detail != NotifyInferior) {
+ framePtr->flags |= GOT_FOCUS;
+ if (framePtr->highlightWidth > 0) {
+ goto redraw;
+ }
+ }
+ } else if (eventPtr->type == FocusOut) {
+ if (eventPtr->xfocus.detail != NotifyInferior) {
+ framePtr->flags &= ~GOT_FOCUS;
+ if (framePtr->highlightWidth > 0) {
+ goto redraw;
+ }
+ }
+ } else if (eventPtr->type == ActivateNotify) {
+ TkpSetMainMenubar(framePtr->interp, framePtr->tkwin,
+ framePtr->menuName);
+ }
+ return;
+
+ redraw:
+ if ((framePtr->tkwin != NULL) && !(framePtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DisplayFrame, framePtr);
+ framePtr->flags |= REDRAW_PENDING;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FrameCmdDeletedProc --
+ *
+ * This function is invoked when a widget command is deleted. If the
+ * widget isn't already in the process of being destroyed, this command
+ * destroys it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The widget is destroyed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FrameCmdDeletedProc(
+ ClientData clientData) /* Pointer to widget record for widget. */
+{
+ Frame *framePtr = clientData;
+ Tk_Window tkwin = framePtr->tkwin;
+
+ if (framePtr->menuName != NULL) {
+ TkSetWindowMenuBar(framePtr->interp, framePtr->tkwin,
+ framePtr->menuName, NULL);
+ ckfree(framePtr->menuName);
+ framePtr->menuName = NULL;
+ }
+
+ /*
+ * This function could be invoked either because the window was destroyed
+ * and the command was then deleted (in which case tkwin is NULL) or
+ * because the command was deleted, and then this function destroys the
+ * widget.
+ */
+
+ if (tkwin != NULL) {
+ /*
+ * Some options need tkwin to be freed, so we free them here, before
+ * setting tkwin to NULL.
+ */
+
+ DestroyFramePartly(framePtr);
+
+ framePtr->tkwin = NULL;
+ Tk_DestroyWindow(tkwin);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MapFrame --
+ *
+ * This function is invoked as a when-idle handler to map a newly-created
+ * top-level frame.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The frame given by the clientData argument is mapped.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+MapFrame(
+ ClientData clientData) /* Pointer to frame structure. */
+{
+ Frame *framePtr = clientData;
+
+ /*
+ * Wait for all other background events to be processed before mapping
+ * window. This ensures that the window's correct geometry will have been
+ * determined before it is first mapped, so that the window manager
+ * doesn't get a false idea of its desired geometry.
+ */
+
+ Tcl_Preserve(framePtr);
+ while (1) {
+ if (Tcl_DoOneEvent(TCL_IDLE_EVENTS) == 0) {
+ break;
+ }
+
+ /*
+ * After each event, make sure that the window still exists and quit
+ * if the window has been destroyed.
+ */
+
+ if (framePtr->tkwin == NULL) {
+ Tcl_Release(framePtr);
+ return;
+ }
+ }
+ Tk_MapWindow(framePtr->tkwin);
+ Tcl_Release(framePtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkInstallFrameMenu --
+ *
+ * This function is needed when a Windows HWND is created and a menubar
+ * has been set to the window with a system menu. It notifies the menu
+ * package so that the system menu can be rebuilt.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The system menu (if any) is created for the menubar associated with
+ * this frame.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkInstallFrameMenu(
+ Tk_Window tkwin) /* The window that was just created. */
+{
+ TkWindow *winPtr = (TkWindow *) tkwin;
+
+ if (winPtr->mainPtr != NULL) {
+ Frame *framePtr = winPtr->instanceData;
+
+ if (framePtr == NULL) {
+ Tcl_Panic("TkInstallFrameMenu couldn't get frame pointer");
+ }
+ TkpMenuNotifyToplevelCreate(winPtr->mainPtr->interp,
+ framePtr->menuName);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * FrameStructureProc --
+ *
+ * This function is invoked whenever StructureNotify events occur for a
+ * window that's managed as label for the frame. This procudure's only
+ * purpose is to clean up when windows are deleted.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The window is disassociated from the frame when it is deleted.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+FrameStructureProc(
+ ClientData clientData, /* Pointer to record describing frame. */
+ XEvent *eventPtr) /* Describes what just happened. */
+{
+ Labelframe *labelframePtr = clientData;
+
+ if (eventPtr->type == DestroyNotify) {
+ /*
+ * This should only happen in a labelframe but it doesn't hurt to be
+ * careful.
+ */
+
+ if (labelframePtr->frame.type == TYPE_LABELFRAME) {
+ labelframePtr->labelWin = NULL;
+ FrameWorldChanged(labelframePtr);
+ }
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * FrameRequestProc --
+ *
+ * This function is invoked whenever a window that's associated with a
+ * frame changes its requested dimensions.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The size and location on the screen of the window may change depending
+ * on the options specified for the frame.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+FrameRequestProc(
+ ClientData clientData, /* Pointer to record for frame. */
+ Tk_Window tkwin) /* Window that changed its desired size. */
+{
+ Frame *framePtr = clientData;
+
+ FrameWorldChanged(framePtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * FrameLostSlaveProc --
+ *
+ * This function is invoked by Tk whenever some other geometry claims
+ * control over a slave that used to be managed by us.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Forgets all frame-related information about the slave.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+FrameLostSlaveProc(
+ ClientData clientData, /* Frame structure for slave window that was
+ * stolen away. */
+ Tk_Window tkwin) /* Tk's handle for the slave window. */
+{
+ Frame *framePtr = clientData;
+ Labelframe *labelframePtr = clientData;
+
+ /*
+ * This should only happen in a labelframe but it doesn't hurt to be
+ * careful.
+ */
+
+ if (labelframePtr->frame.type == TYPE_LABELFRAME) {
+ Tk_DeleteEventHandler(labelframePtr->labelWin, StructureNotifyMask,
+ FrameStructureProc, labelframePtr);
+ if (framePtr->tkwin != Tk_Parent(labelframePtr->labelWin)) {
+ Tk_UnmaintainGeometry(labelframePtr->labelWin, framePtr->tkwin);
+ }
+ Tk_UnmapWindow(labelframePtr->labelWin);
+ labelframePtr->labelWin = NULL;
+ }
+ FrameWorldChanged(framePtr);
+}
+
+void
+TkMapTopFrame(
+ Tk_Window tkwin)
+{
+ Frame *framePtr = ((TkWindow *) tkwin)->instanceData;
+ Tk_OptionTable optionTable;
+
+ if (Tk_IsTopLevel(tkwin) && framePtr->type == TYPE_FRAME) {
+ framePtr->type = TYPE_TOPLEVEL;
+ Tcl_DoWhenIdle(MapFrame, framePtr);
+ if (framePtr->menuName != NULL) {
+ TkSetWindowMenuBar(framePtr->interp, framePtr->tkwin, NULL,
+ framePtr->menuName);
+ }
+ } else if (!Tk_IsTopLevel(tkwin) && framePtr->type == TYPE_TOPLEVEL) {
+ framePtr->type = TYPE_FRAME;
+ } else {
+ /*
+ * Not a frame or toplevel, skip it.
+ */
+
+ return;
+ }
+
+ /*
+ * The option table has already been created so the cached pointer will be
+ * returned.
+ */
+
+ optionTable = Tk_CreateOptionTable(framePtr->interp,
+ optionSpecs[framePtr->type]);
+ framePtr->optionTable = optionTable;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkToplevelWindowFromCommandToken --
+ *
+ * If the given command name to the command for a toplevel window in the
+ * given interpreter, return the tkwin for that toplevel window. Note
+ * that this lookup can't be done using the standard tkwin internal table
+ * because the command might have been renamed.
+ *
+ * Results:
+ * A Tk_Window token, or NULL if the name does not refer to a toplevel
+ * window.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+Tk_Window
+TkToplevelWindowForCommand(
+ Tcl_Interp *interp,
+ const char *cmdName)
+{
+ Tcl_CmdInfo cmdInfo;
+ Frame *framePtr;
+
+ if (Tcl_GetCommandInfo(interp, cmdName, &cmdInfo) == 0) {
+ return NULL;
+ }
+ if (cmdInfo.objProc != FrameWidgetObjCmd) {
+ return NULL;
+ }
+ framePtr = cmdInfo.objClientData;
+ if (framePtr->type != TYPE_TOPLEVEL) {
+ return NULL;
+ }
+ return framePtr->tkwin;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkGC.c b/tk8.6/generic/tkGC.c
new file mode 100644
index 0000000..c424e30
--- /dev/null
+++ b/tk8.6/generic/tkGC.c
@@ -0,0 +1,397 @@
+/*
+ * tkGC.c --
+ *
+ * This file maintains a database of read-only graphics contexts for the
+ * Tk toolkit, in order to allow GC's to be shared.
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkInt.h"
+
+/*
+ * One of the following data structures exists for each GC that is currently
+ * active. The structure is indexed with two hash tables, one based on the
+ * values in the graphics context and the other based on the display and GC
+ * identifier.
+ */
+
+typedef struct {
+ GC gc; /* Graphics context. */
+ Display *display; /* Display to which gc belongs. */
+ int refCount; /* Number of active uses of gc. */
+ Tcl_HashEntry *valueHashPtr;/* Entry in valueTable (needed when deleting
+ * this structure). */
+} TkGC;
+
+typedef struct {
+ XGCValues values; /* Desired values for GC. */
+ Display *display; /* Display for which GC is valid. */
+ int screenNum; /* screen number of display */
+ int depth; /* and depth for which GC is valid. */
+} ValueKey;
+
+/*
+ * Forward declarations for functions defined in this file:
+ */
+
+static void GCInit(TkDisplay *dispPtr);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetGC --
+ *
+ * Given a desired set of values for a graphics context, find a read-only
+ * graphics context with the desired values.
+ *
+ * Results:
+ * The return value is the X identifer for the desired graphics context.
+ * The caller should never modify this GC, and should call Tk_FreeGC when
+ * the GC is no longer needed.
+ *
+ * Side effects:
+ * The GC is added to an internal database with a reference count. For
+ * each call to this function, there should eventually be a call to
+ * Tk_FreeGC, so that the database can be cleaned up when GC's aren't
+ * needed anymore.
+ *
+ *----------------------------------------------------------------------
+ */
+
+GC
+Tk_GetGC(
+ Tk_Window tkwin, /* Window in which GC will be used. */
+ register unsigned long valueMask,
+ /* 1 bits correspond to values specified in
+ * *valuesPtr; other values are set from
+ * defaults. */
+ register XGCValues *valuePtr)
+ /* Values are specified here for bits set in
+ * valueMask. */
+{
+ ValueKey valueKey;
+ Tcl_HashEntry *valueHashPtr, *idHashPtr;
+ register TkGC *gcPtr;
+ int isNew;
+ Drawable d, freeDrawable;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+
+ if (dispPtr->gcInit <= 0) {
+ GCInit(dispPtr);
+ }
+
+ /*
+ * Must zero valueKey at start to clear out pad bytes that may be part of
+ * structure on some systems.
+ */
+
+ memset(&valueKey, 0, sizeof(valueKey));
+
+ /*
+ * First, check to see if there's already a GC that will work for this
+ * request (exact matches only, sorry).
+ */
+
+ if (valueMask & GCFunction) {
+ valueKey.values.function = valuePtr->function;
+ } else {
+ valueKey.values.function = GXcopy;
+ }
+ if (valueMask & GCPlaneMask) {
+ valueKey.values.plane_mask = valuePtr->plane_mask;
+ } else {
+ valueKey.values.plane_mask = (unsigned) ~0;
+ }
+ if (valueMask & GCForeground) {
+ valueKey.values.foreground = valuePtr->foreground;
+ } else {
+ valueKey.values.foreground = 0;
+ }
+ if (valueMask & GCBackground) {
+ valueKey.values.background = valuePtr->background;
+ } else {
+ valueKey.values.background = 1;
+ }
+ if (valueMask & GCLineWidth) {
+ valueKey.values.line_width = valuePtr->line_width;
+ } else {
+ valueKey.values.line_width = 0;
+ }
+ if (valueMask & GCLineStyle) {
+ valueKey.values.line_style = valuePtr->line_style;
+ } else {
+ valueKey.values.line_style = LineSolid;
+ }
+ if (valueMask & GCCapStyle) {
+ valueKey.values.cap_style = valuePtr->cap_style;
+ } else {
+ valueKey.values.cap_style = CapButt;
+ }
+ if (valueMask & GCJoinStyle) {
+ valueKey.values.join_style = valuePtr->join_style;
+ } else {
+ valueKey.values.join_style = JoinMiter;
+ }
+ if (valueMask & GCFillStyle) {
+ valueKey.values.fill_style = valuePtr->fill_style;
+ } else {
+ valueKey.values.fill_style = FillSolid;
+ }
+ if (valueMask & GCFillRule) {
+ valueKey.values.fill_rule = valuePtr->fill_rule;
+ } else {
+ valueKey.values.fill_rule = EvenOddRule;
+ }
+ if (valueMask & GCArcMode) {
+ valueKey.values.arc_mode = valuePtr->arc_mode;
+ } else {
+ valueKey.values.arc_mode = ArcPieSlice;
+ }
+ if (valueMask & GCTile) {
+ valueKey.values.tile = valuePtr->tile;
+ } else {
+ valueKey.values.tile = None;
+ }
+ if (valueMask & GCStipple) {
+ valueKey.values.stipple = valuePtr->stipple;
+ } else {
+ valueKey.values.stipple = None;
+ }
+ if (valueMask & GCTileStipXOrigin) {
+ valueKey.values.ts_x_origin = valuePtr->ts_x_origin;
+ } else {
+ valueKey.values.ts_x_origin = 0;
+ }
+ if (valueMask & GCTileStipYOrigin) {
+ valueKey.values.ts_y_origin = valuePtr->ts_y_origin;
+ } else {
+ valueKey.values.ts_y_origin = 0;
+ }
+ if (valueMask & GCFont) {
+ valueKey.values.font = valuePtr->font;
+ } else {
+ valueKey.values.font = None;
+ }
+ if (valueMask & GCSubwindowMode) {
+ valueKey.values.subwindow_mode = valuePtr->subwindow_mode;
+ } else {
+ valueKey.values.subwindow_mode = ClipByChildren;
+ }
+ if (valueMask & GCGraphicsExposures) {
+ valueKey.values.graphics_exposures = valuePtr->graphics_exposures;
+ } else {
+ valueKey.values.graphics_exposures = True;
+ }
+ if (valueMask & GCClipXOrigin) {
+ valueKey.values.clip_x_origin = valuePtr->clip_x_origin;
+ } else {
+ valueKey.values.clip_x_origin = 0;
+ }
+ if (valueMask & GCClipYOrigin) {
+ valueKey.values.clip_y_origin = valuePtr->clip_y_origin;
+ } else {
+ valueKey.values.clip_y_origin = 0;
+ }
+ if (valueMask & GCClipMask) {
+ valueKey.values.clip_mask = valuePtr->clip_mask;
+ } else {
+ valueKey.values.clip_mask = None;
+ }
+ if (valueMask & GCDashOffset) {
+ valueKey.values.dash_offset = valuePtr->dash_offset;
+ } else {
+ valueKey.values.dash_offset = 0;
+ }
+ if (valueMask & GCDashList) {
+ valueKey.values.dashes = valuePtr->dashes;
+ } else {
+ valueKey.values.dashes = 4;
+ }
+ valueKey.display = Tk_Display(tkwin);
+ valueKey.screenNum = Tk_ScreenNumber(tkwin);
+ valueKey.depth = Tk_Depth(tkwin);
+ valueHashPtr = Tcl_CreateHashEntry(&dispPtr->gcValueTable,
+ (char *) &valueKey, &isNew);
+ if (!isNew) {
+ gcPtr = Tcl_GetHashValue(valueHashPtr);
+ gcPtr->refCount++;
+ return gcPtr->gc;
+ }
+
+ /*
+ * No GC is currently available for this set of values. Allocate a new GC
+ * and add a new structure to the database.
+ */
+
+ gcPtr = ckalloc(sizeof(TkGC));
+
+ /*
+ * Find or make a drawable to use to specify the screen and depth of the
+ * GC. We may have to make a small pixmap, to avoid doing
+ * Tk_MakeWindowExist on the window.
+ */
+
+ freeDrawable = None;
+ if (Tk_WindowId(tkwin) != None) {
+ d = Tk_WindowId(tkwin);
+ } else if (valueKey.depth ==
+ DefaultDepth(valueKey.display, valueKey.screenNum)) {
+ d = RootWindow(valueKey.display, valueKey.screenNum);
+ } else {
+ d = Tk_GetPixmap(valueKey.display,
+ RootWindow(valueKey.display, valueKey.screenNum),
+ 1, 1, valueKey.depth);
+ freeDrawable = d;
+ }
+
+ gcPtr->gc = XCreateGC(valueKey.display, d, valueMask, &valueKey.values);
+ gcPtr->display = valueKey.display;
+ gcPtr->refCount = 1;
+ gcPtr->valueHashPtr = valueHashPtr;
+ idHashPtr = Tcl_CreateHashEntry(&dispPtr->gcIdTable,
+ (char *) gcPtr->gc, &isNew);
+ if (!isNew) {
+ Tcl_Panic("GC already registered in Tk_GetGC");
+ }
+ Tcl_SetHashValue(valueHashPtr, gcPtr);
+ Tcl_SetHashValue(idHashPtr, gcPtr);
+ if (freeDrawable != None) {
+ Tk_FreePixmap(valueKey.display, freeDrawable);
+ }
+
+ return gcPtr->gc;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_FreeGC --
+ *
+ * This function is called to release a graphics context allocated by
+ * Tk_GetGC.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The reference count associated with gc is decremented, and gc is
+ * officially deallocated if no-one is using it anymore.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_FreeGC(
+ Display *display, /* Display for which gc was allocated. */
+ GC gc) /* Graphics context to be released. */
+{
+ Tcl_HashEntry *idHashPtr;
+ register TkGC *gcPtr;
+ TkDisplay *dispPtr = TkGetDisplay(display);
+
+ if (!dispPtr->gcInit) {
+ Tcl_Panic("Tk_FreeGC called before Tk_GetGC");
+ }
+ if (dispPtr->gcInit < 0) {
+ /*
+ * The GCCleanup has been called, and remaining GCs have been freed.
+ * This may still get called by other things shutting down, but the
+ * GCs should no longer be in use.
+ */
+
+ return;
+ }
+
+ idHashPtr = Tcl_FindHashEntry(&dispPtr->gcIdTable, (char *) gc);
+ if (idHashPtr == NULL) {
+ Tcl_Panic("Tk_FreeGC received unknown gc argument");
+ }
+ gcPtr = Tcl_GetHashValue(idHashPtr);
+ gcPtr->refCount--;
+ if (gcPtr->refCount == 0) {
+ XFreeGC(gcPtr->display, gcPtr->gc);
+ Tcl_DeleteHashEntry(gcPtr->valueHashPtr);
+ Tcl_DeleteHashEntry(idHashPtr);
+ ckfree(gcPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkGCCleanup --
+ *
+ * Frees the structures used for GC management. We need to have it called
+ * near the end, when other cleanup that calls Tk_FreeGC is all done.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * GC resources are freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkGCCleanup(
+ TkDisplay *dispPtr) /* display to clean up resources in */
+{
+ Tcl_HashEntry *entryPtr;
+ Tcl_HashSearch search;
+ TkGC *gcPtr;
+
+ for (entryPtr = Tcl_FirstHashEntry(&dispPtr->gcIdTable, &search);
+ entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&search)) {
+ gcPtr = Tcl_GetHashValue(entryPtr);
+
+ XFreeGC(gcPtr->display, gcPtr->gc);
+ Tcl_DeleteHashEntry(gcPtr->valueHashPtr);
+ Tcl_DeleteHashEntry(entryPtr);
+ ckfree(gcPtr);
+ }
+ Tcl_DeleteHashTable(&dispPtr->gcValueTable);
+ Tcl_DeleteHashTable(&dispPtr->gcIdTable);
+ dispPtr->gcInit = -1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GCInit --
+ *
+ * Initialize the structures used for GC management.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Read the code.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GCInit(
+ TkDisplay *dispPtr)
+{
+ if (dispPtr->gcInit < 0) {
+ Tcl_Panic("called GCInit after GCCleanup");
+ }
+ dispPtr->gcInit = 1;
+ Tcl_InitHashTable(&dispPtr->gcValueTable, sizeof(ValueKey)/sizeof(int));
+ Tcl_InitHashTable(&dispPtr->gcIdTable, TCL_ONE_WORD_KEYS);
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkGeometry.c b/tk8.6/generic/tkGeometry.c
new file mode 100644
index 0000000..5249aaf
--- /dev/null
+++ b/tk8.6/generic/tkGeometry.c
@@ -0,0 +1,790 @@
+/*
+ * tkGeometry.c --
+ *
+ * This file contains generic Tk code for geometry management (stuff
+ * that's used by all geometry managers).
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkInt.h"
+
+/*
+ * Data structures of the following type are used by Tk_MaintainGeometry. For
+ * each slave managed by Tk_MaintainGeometry, there is one of these structures
+ * associated with its master.
+ */
+
+typedef struct MaintainSlave {
+ Tk_Window slave; /* The slave window being positioned. */
+ Tk_Window master; /* The master that determines slave's
+ * position; it must be a descendant of
+ * slave's parent. */
+ int x, y; /* Desired position of slave relative to
+ * master. */
+ int width, height; /* Desired dimensions of slave. */
+ struct MaintainSlave *nextPtr;
+ /* Next in list of Maintains associated with
+ * master. */
+} MaintainSlave;
+
+/*
+ * For each window that has been specified as a master to Tk_MaintainGeometry,
+ * there is a structure of the following type:
+ */
+
+typedef struct MaintainMaster {
+ Tk_Window ancestor; /* The lowest ancestor of this window for
+ * which we have *not* created a
+ * StructureNotify handler. May be the same as
+ * the window itself. */
+ int checkScheduled; /* Non-zero means that there is already a call
+ * to MaintainCheckProc scheduled as an idle
+ * handler. */
+ MaintainSlave *slavePtr; /* First in list of all slaves associated with
+ * this master. */
+} MaintainMaster;
+
+/*
+ * Prototypes for static procedures in this file:
+ */
+
+static void MaintainCheckProc(ClientData clientData);
+static void MaintainMasterProc(ClientData clientData,
+ XEvent *eventPtr);
+static void MaintainSlaveProc(ClientData clientData,
+ XEvent *eventPtr);
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_ManageGeometry --
+ *
+ * Arrange for a particular procedure to manage the geometry of a given
+ * slave window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Proc becomes the new geometry manager for tkwin, replacing any
+ * previous geometry manager. The geometry manager will be notified (by
+ * calling procedures in *mgrPtr) when interesting things happen in the
+ * future. If there was an existing geometry manager for tkwin different
+ * from the new one, it is notified by calling its lostSlaveProc.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_ManageGeometry(
+ Tk_Window tkwin, /* Window whose geometry is to be managed by
+ * proc. */
+ const Tk_GeomMgr *mgrPtr, /* Static structure describing the geometry
+ * manager. This structure must never go
+ * away. */
+ ClientData clientData) /* Arbitrary one-word argument to pass to
+ * geometry manager procedures. */
+{
+ register TkWindow *winPtr = (TkWindow *) tkwin;
+
+ if ((winPtr->geomMgrPtr != NULL) && (mgrPtr != NULL)
+ && ((winPtr->geomMgrPtr != mgrPtr)
+ || (winPtr->geomData != clientData))
+ && (winPtr->geomMgrPtr->lostSlaveProc != NULL)) {
+ winPtr->geomMgrPtr->lostSlaveProc(winPtr->geomData, tkwin);
+ }
+
+ winPtr->geomMgrPtr = mgrPtr;
+ winPtr->geomData = clientData;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_GeometryRequest --
+ *
+ * This procedure is invoked by widget code to indicate its preferences
+ * about the size of a window it manages. In general, widget code should
+ * call this procedure rather than Tk_ResizeWindow.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The geometry manager for tkwin (if any) is invoked to handle the
+ * request. If possible, it will reconfigure tkwin and/or other windows
+ * to satisfy the request. The caller gets no indication of success or
+ * failure, but it will get X events if the window size was actually
+ * changed.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_GeometryRequest(
+ Tk_Window tkwin, /* Window that geometry information pertains
+ * to. */
+ int reqWidth, int reqHeight)/* Minimum desired dimensions for window, in
+ * pixels. */
+{
+ register TkWindow *winPtr = (TkWindow *) tkwin;
+
+ /*
+ * X gets very upset if a window requests a width or height of zero, so
+ * rounds requested sizes up to at least 1.
+ */
+
+ if (reqWidth <= 0) {
+ reqWidth = 1;
+ }
+ if (reqHeight <= 0) {
+ reqHeight = 1;
+ }
+ if ((reqWidth == winPtr->reqWidth) && (reqHeight == winPtr->reqHeight)) {
+ return;
+ }
+ winPtr->reqWidth = reqWidth;
+ winPtr->reqHeight = reqHeight;
+ if ((winPtr->geomMgrPtr != NULL)
+ && (winPtr->geomMgrPtr->requestProc != NULL)) {
+ winPtr->geomMgrPtr->requestProc(winPtr->geomData, tkwin);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_SetInternalBorderEx --
+ *
+ * Notify relevant geometry managers that a window has an internal border
+ * of a given width and that child windows should not be placed on that
+ * border.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The border widths are recorded for the window, and all geometry
+ * managers of all children are notified so that can re-layout, if
+ * necessary.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_SetInternalBorderEx(
+ Tk_Window tkwin, /* Window that will have internal border. */
+ int left, int right, /* Width of internal border, in pixels. */
+ int top, int bottom)
+{
+ register TkWindow *winPtr = (TkWindow *) tkwin;
+ register int changed = 0;
+
+ if (left < 0) {
+ left = 0;
+ }
+ if (left != winPtr->internalBorderLeft) {
+ winPtr->internalBorderLeft = left;
+ changed = 1;
+ }
+
+ if (right < 0) {
+ right = 0;
+ }
+ if (right != winPtr->internalBorderRight) {
+ winPtr->internalBorderRight = right;
+ changed = 1;
+ }
+
+ if (top < 0) {
+ top = 0;
+ }
+ if (top != winPtr->internalBorderTop) {
+ winPtr->internalBorderTop = top;
+ changed = 1;
+ }
+
+ if (bottom < 0) {
+ bottom = 0;
+ }
+ if (bottom != winPtr->internalBorderBottom) {
+ winPtr->internalBorderBottom = bottom;
+ changed = 1;
+ }
+
+ /*
+ * All the slaves for which this is the master window must now be
+ * repositioned to take account of the new internal border width. To
+ * signal all the geometry managers to do this, just resize the window to
+ * its current size. The ConfigureNotify event will cause geometry
+ * managers to recompute everything.
+ */
+
+ if (changed) {
+ Tk_ResizeWindow(tkwin, Tk_Width(tkwin), Tk_Height(tkwin));
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_SetInternalBorder --
+ *
+ * Notify relevant geometry managers that a window has an internal border
+ * of a given width and that child windows should not be placed on that
+ * border.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The border width is recorded for the window, and all geometry managers
+ * of all children are notified so that can re-layout, if necessary.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_SetInternalBorder(
+ Tk_Window tkwin, /* Window that will have internal border. */
+ int width) /* Width of internal border, in pixels. */
+{
+ Tk_SetInternalBorderEx(tkwin, width, width, width, width);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_SetMinimumRequestSize --
+ *
+ * Notify relevant geometry managers that a window has a minimum request
+ * size.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The minimum request size is recorded for the window, and a new size is
+ * requested for the window, if necessary.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_SetMinimumRequestSize(
+ Tk_Window tkwin, /* Window that will have internal border. */
+ int minWidth, int minHeight)/* Minimum requested size, in pixels. */
+{
+ register TkWindow *winPtr = (TkWindow *) tkwin;
+
+ if ((winPtr->minReqWidth == minWidth) &&
+ (winPtr->minReqHeight == minHeight)) {
+ return;
+ }
+
+ winPtr->minReqWidth = minWidth;
+ winPtr->minReqHeight = minHeight;
+
+ /*
+ * The changed min size may cause geometry managers to get a different
+ * result, so make them recompute. To signal all the geometry managers to
+ * do this, just resize the window to its current size. The
+ * ConfigureNotify event will cause geometry managers to recompute
+ * everything.
+ */
+
+ Tk_ResizeWindow(tkwin, Tk_Width(tkwin), Tk_Height(tkwin));
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkSetGeometryMaster --
+ *
+ * Set a geometry master for this window. Only one master may own
+ * a window at any time.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * The geometry master is recorded for the window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkSetGeometryMaster(
+ Tcl_Interp *interp, /* Current interpreter, for error. */
+ Tk_Window tkwin, /* Window that will have geometry master
+ * set. */
+ const char *master) /* The master identity. */
+{
+ register TkWindow *winPtr = (TkWindow *) tkwin;
+
+ if (winPtr->geomMgrName != NULL &&
+ strcmp(winPtr->geomMgrName, master) == 0) {
+ return TCL_OK;
+ }
+ if (winPtr->geomMgrName != NULL) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "cannot use geometry manager %s inside %s which already"
+ " has slaves managed by %s",
+ master, Tk_PathName(tkwin), winPtr->geomMgrName));
+ Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "FIGHT", NULL);
+ }
+ return TCL_ERROR;
+ }
+
+ winPtr->geomMgrName = ckalloc(strlen(master) + 1);
+ strcpy(winPtr->geomMgrName, master);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkFreeGeometryMaster --
+ *
+ * Remove a geometry master for this window. Only one master may own
+ * a window at any time.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The geometry master is cleared for the window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkFreeGeometryMaster(
+ Tk_Window tkwin, /* Window that will have geometry master
+ * cleared. */
+ const char *master) /* The master identity. */
+{
+ register TkWindow *winPtr = (TkWindow *) tkwin;
+
+ if (winPtr->geomMgrName != NULL &&
+ strcmp(winPtr->geomMgrName, master) != 0) {
+ Tcl_Panic("Trying to free %s from geometry manager %s",
+ winPtr->geomMgrName, master);
+ }
+ if (winPtr->geomMgrName != NULL) {
+ ckfree(winPtr->geomMgrName);
+ winPtr->geomMgrName = NULL;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_MaintainGeometry --
+ *
+ * This procedure is invoked by geometry managers to handle slaves whose
+ * master's are not their parents. It translates the desired geometry for
+ * the slave into the coordinate system of the parent and respositions
+ * the slave if it isn't already at the right place. Furthermore, it sets
+ * up event handlers so that if the master (or any of its ancestors up to
+ * the slave's parent) is mapped, unmapped, or moved, then the slave will
+ * be adjusted to match.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Event handlers are created and state is allocated to keep track of
+ * slave. Note: if slave was already managed for master by
+ * Tk_MaintainGeometry, then the previous information is replaced with
+ * the new information. The caller must eventually call
+ * Tk_UnmaintainGeometry to eliminate the correspondence (or, the state
+ * is automatically freed when either window is destroyed).
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_MaintainGeometry(
+ Tk_Window slave, /* Slave for geometry management. */
+ Tk_Window master, /* Master for slave; must be a descendant of
+ * slave's parent. */
+ int x, int y, /* Desired position of slave within master. */
+ int width, int height) /* Desired dimensions for slave. */
+{
+ Tcl_HashEntry *hPtr;
+ MaintainMaster *masterPtr;
+ register MaintainSlave *slavePtr;
+ int isNew, map;
+ Tk_Window ancestor, parent;
+ TkDisplay *dispPtr = ((TkWindow *) master)->dispPtr;
+
+ ((TkWindow *)slave)->maintainerPtr = (TkWindow *)master;
+
+ ((TkWindow *)slave)->maintainerPtr = (TkWindow *)master;
+ if (master == Tk_Parent(slave)) {
+ /*
+ * If the slave is a direct descendant of the master, don't bother
+ * setting up the extra infrastructure for management, just make a
+ * call to Tk_MoveResizeWindow; the parent/child relationship will
+ * take care of the rest.
+ */
+
+ Tk_MoveResizeWindow(slave, x, y, width, height);
+
+ /*
+ * Map the slave if the master is already mapped; otherwise, wait
+ * until the master is mapped later (in which case mapping the slave
+ * is taken care of elsewhere).
+ */
+
+ if (Tk_IsMapped(master)) {
+ Tk_MapWindow(slave);
+ }
+ return;
+ }
+
+ if (!dispPtr->geomInit) {
+ dispPtr->geomInit = 1;
+ Tcl_InitHashTable(&dispPtr->maintainHashTable, TCL_ONE_WORD_KEYS);
+ }
+
+ /*
+ * See if there is already a MaintainMaster structure for the master; if
+ * not, then create one.
+ */
+
+ parent = Tk_Parent(slave);
+ hPtr = Tcl_CreateHashEntry(&dispPtr->maintainHashTable,
+ (char *) master, &isNew);
+ if (!isNew) {
+ masterPtr = Tcl_GetHashValue(hPtr);
+ } else {
+ masterPtr = ckalloc(sizeof(MaintainMaster));
+ masterPtr->ancestor = master;
+ masterPtr->checkScheduled = 0;
+ masterPtr->slavePtr = NULL;
+ Tcl_SetHashValue(hPtr, masterPtr);
+ }
+
+ /*
+ * Create a MaintainSlave structure for the slave if there isn't already
+ * one.
+ */
+
+ for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
+ slavePtr = slavePtr->nextPtr) {
+ if (slavePtr->slave == slave) {
+ goto gotSlave;
+ }
+ }
+ slavePtr = ckalloc(sizeof(MaintainSlave));
+ slavePtr->slave = slave;
+ slavePtr->master = master;
+ slavePtr->nextPtr = masterPtr->slavePtr;
+ masterPtr->slavePtr = slavePtr;
+ Tk_CreateEventHandler(slave, StructureNotifyMask, MaintainSlaveProc,
+ slavePtr);
+
+ /*
+ * Make sure that there are event handlers registered for all the windows
+ * between master and slave's parent (including master but not slave's
+ * parent). There may already be handlers for master and some of its
+ * ancestors (masterPtr->ancestor tells how many).
+ */
+
+ for (ancestor = master; ancestor != parent;
+ ancestor = Tk_Parent(ancestor)) {
+ if (ancestor == masterPtr->ancestor) {
+ Tk_CreateEventHandler(ancestor, StructureNotifyMask,
+ MaintainMasterProc, masterPtr);
+ masterPtr->ancestor = Tk_Parent(ancestor);
+ }
+ }
+
+ /*
+ * Fill in up-to-date information in the structure, then update the window
+ * if it's not currently in the right place or state.
+ */
+
+ gotSlave:
+ slavePtr->x = x;
+ slavePtr->y = y;
+ slavePtr->width = width;
+ slavePtr->height = height;
+ map = 1;
+ for (ancestor = slavePtr->master; ; ancestor = Tk_Parent(ancestor)) {
+ if (!Tk_IsMapped(ancestor) && (ancestor != parent)) {
+ map = 0;
+ }
+ if (ancestor == parent) {
+ if ((x != Tk_X(slavePtr->slave))
+ || (y != Tk_Y(slavePtr->slave))
+ || (width != Tk_Width(slavePtr->slave))
+ || (height != Tk_Height(slavePtr->slave))) {
+ Tk_MoveResizeWindow(slavePtr->slave, x, y, width, height);
+ }
+ if (map) {
+ Tk_MapWindow(slavePtr->slave);
+ } else {
+ Tk_UnmapWindow(slavePtr->slave);
+ }
+ break;
+ }
+ x += Tk_X(ancestor) + Tk_Changes(ancestor)->border_width;
+ y += Tk_Y(ancestor) + Tk_Changes(ancestor)->border_width;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_UnmaintainGeometry --
+ *
+ * This procedure cancels a previous Tk_MaintainGeometry call, so that
+ * the relationship between slave and master is no longer maintained.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The slave is unmapped and state is released, so that slave won't track
+ * master any more. If we weren't previously managing slave relative to
+ * master, then this procedure has no effect.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_UnmaintainGeometry(
+ Tk_Window slave, /* Slave for geometry management. */
+ Tk_Window master) /* Master for slave; must be a descendant of
+ * slave's parent. */
+{
+ Tcl_HashEntry *hPtr;
+ MaintainMaster *masterPtr;
+ register MaintainSlave *slavePtr, *prevPtr;
+ Tk_Window ancestor;
+ TkDisplay *dispPtr = ((TkWindow *) slave)->dispPtr;
+
+ ((TkWindow *)slave)->maintainerPtr = NULL;
+
+ ((TkWindow *)slave)->maintainerPtr = NULL;
+ if (master == Tk_Parent(slave)) {
+ /*
+ * If the slave is a direct descendant of the master,
+ * Tk_MaintainGeometry will not have set up any of the extra
+ * infrastructure. Don't even bother to look for it, just return.
+ */
+ return;
+ }
+
+ if (!dispPtr->geomInit) {
+ dispPtr->geomInit = 1;
+ Tcl_InitHashTable(&dispPtr->maintainHashTable, TCL_ONE_WORD_KEYS);
+ }
+
+ if (!(((TkWindow *) slave)->flags & TK_ALREADY_DEAD)) {
+ Tk_UnmapWindow(slave);
+ }
+ hPtr = Tcl_FindHashEntry(&dispPtr->maintainHashTable, (char *) master);
+ if (hPtr == NULL) {
+ return;
+ }
+ masterPtr = Tcl_GetHashValue(hPtr);
+ slavePtr = masterPtr->slavePtr;
+ if (slavePtr->slave == slave) {
+ masterPtr->slavePtr = slavePtr->nextPtr;
+ } else {
+ for (prevPtr = slavePtr, slavePtr = slavePtr->nextPtr; ;
+ prevPtr = slavePtr, slavePtr = slavePtr->nextPtr) {
+ if (slavePtr == NULL) {
+ return;
+ }
+ if (slavePtr->slave == slave) {
+ prevPtr->nextPtr = slavePtr->nextPtr;
+ break;
+ }
+ }
+ }
+ Tk_DeleteEventHandler(slavePtr->slave, StructureNotifyMask,
+ MaintainSlaveProc, slavePtr);
+ ckfree(slavePtr);
+ if (masterPtr->slavePtr == NULL) {
+ if (masterPtr->ancestor != NULL) {
+ for (ancestor = master; ; ancestor = Tk_Parent(ancestor)) {
+ Tk_DeleteEventHandler(ancestor, StructureNotifyMask,
+ MaintainMasterProc, masterPtr);
+ if (ancestor == masterPtr->ancestor) {
+ break;
+ }
+ }
+ }
+ if (masterPtr->checkScheduled) {
+ Tcl_CancelIdleCall(MaintainCheckProc, masterPtr);
+ }
+ Tcl_DeleteHashEntry(hPtr);
+ ckfree(masterPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MaintainMasterProc --
+ *
+ * This procedure is invoked by the Tk event dispatcher in response to
+ * StructureNotify events on the master or one of its ancestors, on
+ * behalf of Tk_MaintainGeometry.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * It schedules a call to MaintainCheckProc, which will eventually caused
+ * the postions and mapped states to be recalculated for all the
+ * maintained slaves of the master. Or, if the master window is being
+ * deleted then state is cleaned up.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+MaintainMasterProc(
+ ClientData clientData, /* Pointer to MaintainMaster structure for the
+ * master window. */
+ XEvent *eventPtr) /* Describes what just happened. */
+{
+ MaintainMaster *masterPtr = clientData;
+ MaintainSlave *slavePtr;
+ int done;
+
+ if ((eventPtr->type == ConfigureNotify)
+ || (eventPtr->type == MapNotify)
+ || (eventPtr->type == UnmapNotify)) {
+ if (!masterPtr->checkScheduled) {
+ masterPtr->checkScheduled = 1;
+ Tcl_DoWhenIdle(MaintainCheckProc, masterPtr);
+ }
+ } else if (eventPtr->type == DestroyNotify) {
+ /*
+ * Delete all of the state associated with this master, but be careful
+ * not to use masterPtr after the last slave is deleted, since its
+ * memory will have been freed.
+ */
+
+ done = 0;
+ do {
+ slavePtr = masterPtr->slavePtr;
+ if (slavePtr->nextPtr == NULL) {
+ done = 1;
+ }
+ Tk_UnmaintainGeometry(slavePtr->slave, slavePtr->master);
+ } while (!done);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MaintainSlaveProc --
+ *
+ * This procedure is invoked by the Tk event dispatcher in response to
+ * StructureNotify events on a slave being managed by
+ * Tk_MaintainGeometry.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If the event is a DestroyNotify event then the Maintain state and
+ * event handlers for this slave are deleted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+MaintainSlaveProc(
+ ClientData clientData, /* Pointer to MaintainSlave structure for
+ * master-slave pair. */
+ XEvent *eventPtr) /* Describes what just happened. */
+{
+ MaintainSlave *slavePtr = clientData;
+
+ if (eventPtr->type == DestroyNotify) {
+ Tk_UnmaintainGeometry(slavePtr->slave, slavePtr->master);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MaintainCheckProc --
+ *
+ * This procedure is invoked by the Tk event dispatcher as an idle
+ * handler, when a master or one of its ancestors has been reconfigured,
+ * mapped, or unmapped. Its job is to scan all of the slaves for the
+ * master and reposition them, map them, or unmap them as needed to
+ * maintain their geometry relative to the master.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Slaves can get repositioned, mapped, or unmapped.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+MaintainCheckProc(
+ ClientData clientData) /* Pointer to MaintainMaster structure for the
+ * master window. */
+{
+ MaintainMaster *masterPtr = clientData;
+ MaintainSlave *slavePtr;
+ Tk_Window ancestor, parent;
+ int x, y, map;
+
+ masterPtr->checkScheduled = 0;
+ for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
+ slavePtr = slavePtr->nextPtr) {
+ parent = Tk_Parent(slavePtr->slave);
+ x = slavePtr->x;
+ y = slavePtr->y;
+ map = 1;
+ for (ancestor = slavePtr->master; ; ancestor = Tk_Parent(ancestor)) {
+ if (!Tk_IsMapped(ancestor) && (ancestor != parent)) {
+ map = 0;
+ }
+ if (ancestor == parent) {
+ if ((x != Tk_X(slavePtr->slave))
+ || (y != Tk_Y(slavePtr->slave))) {
+ Tk_MoveWindow(slavePtr->slave, x, y);
+ }
+ if (map) {
+ Tk_MapWindow(slavePtr->slave);
+ } else {
+ Tk_UnmapWindow(slavePtr->slave);
+ }
+ break;
+ }
+ x += Tk_X(ancestor) + Tk_Changes(ancestor)->border_width;
+ y += Tk_Y(ancestor) + Tk_Changes(ancestor)->border_width;
+ }
+ }
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkGet.c b/tk8.6/generic/tkGet.c
new file mode 100644
index 0000000..6eff3a3
--- /dev/null
+++ b/tk8.6/generic/tkGet.c
@@ -0,0 +1,752 @@
+/*
+ * tkGet.c --
+ *
+ * This file contains a number of "Tk_GetXXX" procedures, which parse
+ * text strings into useful forms for Tk. This file has the simpler
+ * functions, like Tk_GetDirection and Tk_GetUid. The more complex
+ * functions like Tk_GetColor are in separate files.
+ *
+ * Copyright (c) 1991-1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "tkInt.h"
+
+/*
+ * One of these structures is created per thread to store thread-specific
+ * data. In this case, it is used to house the Tk_Uid structs used by each
+ * thread. The "dataKey" below is used to locate the ThreadSpecificData for
+ * the current thread.
+ */
+
+typedef struct {
+ int initialized;
+ Tcl_HashTable uidTable;
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+
+static void FreeUidThreadExitProc(ClientData clientData);
+
+/*
+ * The following tables defines the string values for reliefs, which are
+ * used by Tk_GetAnchorFromObj and Tk_GetJustifyFromObj.
+ */
+
+static const char *const anchorStrings[] = {
+ "n", "ne", "e", "se", "s", "sw", "w", "nw", "center", NULL
+};
+static const char *const justifyStrings[] = {
+ "left", "right", "center", NULL
+};
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetAnchorFromObj --
+ *
+ * Return a Tk_Anchor value based on the value of the objPtr.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If an error occurs during
+ * conversion, an error message is left in the interpreter's result
+ * unless "interp" is NULL.
+ *
+ * Side effects:
+ * The object gets converted by Tcl_GetIndexFromObj.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_GetAnchorFromObj(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Obj *objPtr, /* The object we are trying to get the value
+ * from. */
+ Tk_Anchor *anchorPtr) /* Where to place the Tk_Anchor that
+ * corresponds to the string value of
+ * objPtr. */
+{
+ int index, code;
+
+ code = Tcl_GetIndexFromObj(interp, objPtr, anchorStrings, "anchor", 0,
+ &index);
+ if (code == TCL_OK) {
+ *anchorPtr = (Tk_Anchor) index;
+ }
+ return code;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_GetAnchor --
+ *
+ * Given a string, return the corresponding Tk_Anchor.
+ *
+ * Results:
+ * The return value is a standard Tcl return result. If TCL_OK is
+ * returned, then everything went well and the position is stored at
+ * *anchorPtr; otherwise TCL_ERROR is returned and an error message is
+ * left in the interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_GetAnchor(
+ Tcl_Interp *interp, /* Use this for error reporting. */
+ const char *string, /* String describing a direction. */
+ Tk_Anchor *anchorPtr) /* Where to store Tk_Anchor corresponding to
+ * string. */
+{
+ switch (string[0]) {
+ case 'n':
+ if (string[1] == 0) {
+ *anchorPtr = TK_ANCHOR_N;
+ return TCL_OK;
+ } else if ((string[1] == 'e') && (string[2] == 0)) {
+ *anchorPtr = TK_ANCHOR_NE;
+ return TCL_OK;
+ } else if ((string[1] == 'w') && (string[2] == 0)) {
+ *anchorPtr = TK_ANCHOR_NW;
+ return TCL_OK;
+ }
+ goto error;
+ case 's':
+ if (string[1] == 0) {
+ *anchorPtr = TK_ANCHOR_S;
+ return TCL_OK;
+ } else if ((string[1] == 'e') && (string[2] == 0)) {
+ *anchorPtr = TK_ANCHOR_SE;
+ return TCL_OK;
+ } else if ((string[1] == 'w') && (string[2] == 0)) {
+ *anchorPtr = TK_ANCHOR_SW;
+ return TCL_OK;
+ } else {
+ goto error;
+ }
+ case 'e':
+ if (string[1] == 0) {
+ *anchorPtr = TK_ANCHOR_E;
+ return TCL_OK;
+ }
+ goto error;
+ case 'w':
+ if (string[1] == 0) {
+ *anchorPtr = TK_ANCHOR_W;
+ return TCL_OK;
+ }
+ goto error;
+ case 'c':
+ if (strncmp(string, "center", strlen(string)) == 0) {
+ *anchorPtr = TK_ANCHOR_CENTER;
+ return TCL_OK;
+ }
+ goto error;
+ }
+
+ error:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad anchor position \"%s\": must be"
+ " n, ne, e, se, s, sw, w, nw, or center", string));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "ANCHOR", NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_NameOfAnchor --
+ *
+ * Given a Tk_Anchor, return the string that corresponds to it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+const char *
+Tk_NameOfAnchor(
+ Tk_Anchor anchor) /* Anchor for which identifying string is
+ * desired. */
+{
+ switch (anchor) {
+ case TK_ANCHOR_N: return "n";
+ case TK_ANCHOR_NE: return "ne";
+ case TK_ANCHOR_E: return "e";
+ case TK_ANCHOR_SE: return "se";
+ case TK_ANCHOR_S: return "s";
+ case TK_ANCHOR_SW: return "sw";
+ case TK_ANCHOR_W: return "w";
+ case TK_ANCHOR_NW: return "nw";
+ case TK_ANCHOR_CENTER: return "center";
+ }
+ return "unknown anchor position";
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_GetJoinStyle --
+ *
+ * Given a string, return the corresponding Tk JoinStyle.
+ *
+ * Results:
+ * The return value is a standard Tcl return result. If TCL_OK is
+ * returned, then everything went well and the justification is stored at
+ * *joinPtr; otherwise TCL_ERROR is returned and an error message is left
+ * in the interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_GetJoinStyle(
+ Tcl_Interp *interp, /* Use this for error reporting. */
+ const char *string, /* String describing a justification style. */
+ int *joinPtr) /* Where to store join style corresponding to
+ * string. */
+{
+ int c;
+ size_t length;
+
+ c = string[0];
+ length = strlen(string);
+
+ if ((c == 'b') && (strncmp(string, "bevel", length) == 0)) {
+ *joinPtr = JoinBevel;
+ return TCL_OK;
+ }
+ if ((c == 'm') && (strncmp(string, "miter", length) == 0)) {
+ *joinPtr = JoinMiter;
+ return TCL_OK;
+ }
+ if ((c == 'r') && (strncmp(string, "round", length) == 0)) {
+ *joinPtr = JoinRound;
+ return TCL_OK;
+ }
+
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad join style \"%s\": must be bevel, miter, or round",
+ string));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "JOIN", NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_NameOfJoinStyle --
+ *
+ * Given a Tk JoinStyle, return the string that corresponds to it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+const char *
+Tk_NameOfJoinStyle(
+ int join) /* Join style for which identifying string is
+ * desired. */
+{
+ switch (join) {
+ case JoinBevel: return "bevel";
+ case JoinMiter: return "miter";
+ case JoinRound: return "round";
+ }
+ return "unknown join style";
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_GetCapStyle --
+ *
+ * Given a string, return the corresponding Tk CapStyle.
+ *
+ * Results:
+ * The return value is a standard Tcl return result. If TCL_OK is
+ * returned, then everything went well and the justification is stored at
+ * *capPtr; otherwise TCL_ERROR is returned and an error message is left
+ * in the interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_GetCapStyle(
+ Tcl_Interp *interp, /* Use this for error reporting. */
+ const char *string, /* String describing a justification style. */
+ int *capPtr) /* Where to store cap style corresponding to
+ * string. */
+{
+ int c;
+ size_t length;
+
+ c = string[0];
+ length = strlen(string);
+
+ if ((c == 'b') && (strncmp(string, "butt", length) == 0)) {
+ *capPtr = CapButt;
+ return TCL_OK;
+ }
+ if ((c == 'p') && (strncmp(string, "projecting", length) == 0)) {
+ *capPtr = CapProjecting;
+ return TCL_OK;
+ }
+ if ((c == 'r') && (strncmp(string, "round", length) == 0)) {
+ *capPtr = CapRound;
+ return TCL_OK;
+ }
+
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad cap style \"%s\": must be butt, projecting, or round",
+ string));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "CAP", NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_NameOfCapStyle --
+ *
+ * Given a Tk CapStyle, return the string that corresponds to it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+const char *
+Tk_NameOfCapStyle(
+ int cap) /* Cap style for which identifying string is
+ * desired. */
+{
+ switch (cap) {
+ case CapButt: return "butt";
+ case CapProjecting: return "projecting";
+ case CapRound: return "round";
+ }
+ return "unknown cap style";
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetJustifyFromObj --
+ *
+ * Return a Tk_Justify value based on the value of the objPtr.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If an error occurs during
+ * conversion, an error message is left in the interpreter's result
+ * unless "interp" is NULL.
+ *
+ * Side effects:
+ * The object gets converted by Tcl_GetIndexFromObj.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_GetJustifyFromObj(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Obj *objPtr, /* The object we are trying to get the value
+ * from. */
+ Tk_Justify *justifyPtr) /* Where to place the Tk_Justify that
+ * corresponds to the string value of
+ * objPtr. */
+{
+ int index, code;
+
+ code = Tcl_GetIndexFromObj(interp, objPtr, justifyStrings,
+ "justification", 0, &index);
+ if (code == TCL_OK) {
+ *justifyPtr = (Tk_Justify) index;
+ }
+ return code;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_GetJustify --
+ *
+ * Given a string, return the corresponding Tk_Justify.
+ *
+ * Results:
+ * The return value is a standard Tcl return result. If TCL_OK is
+ * returned, then everything went well and the justification is stored at
+ * *justifyPtr; otherwise TCL_ERROR is returned and an error message is
+ * left in the interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_GetJustify(
+ Tcl_Interp *interp, /* Use this for error reporting. */
+ const char *string, /* String describing a justification style. */
+ Tk_Justify *justifyPtr) /* Where to store Tk_Justify corresponding to
+ * string. */
+{
+ int c;
+ size_t length;
+
+ c = string[0];
+ length = strlen(string);
+
+ if ((c == 'l') && (strncmp(string, "left", length) == 0)) {
+ *justifyPtr = TK_JUSTIFY_LEFT;
+ return TCL_OK;
+ }
+ if ((c == 'r') && (strncmp(string, "right", length) == 0)) {
+ *justifyPtr = TK_JUSTIFY_RIGHT;
+ return TCL_OK;
+ }
+ if ((c == 'c') && (strncmp(string, "center", length) == 0)) {
+ *justifyPtr = TK_JUSTIFY_CENTER;
+ return TCL_OK;
+ }
+
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad justification \"%s\": must be left, right, or center",
+ string));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "JUSTIFY", NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_NameOfJustify --
+ *
+ * Given a Tk_Justify, return the string that corresponds
+ * to it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+const char *
+Tk_NameOfJustify(
+ Tk_Justify justify) /* Justification style for which identifying
+ * string is desired. */
+{
+ switch (justify) {
+ case TK_JUSTIFY_LEFT: return "left";
+ case TK_JUSTIFY_RIGHT: return "right";
+ case TK_JUSTIFY_CENTER: return "center";
+ }
+ return "unknown justification style";
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeUidThreadExitProc --
+ *
+ * Cleans up memory used for Tk_Uids in the thread.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * All information in the identifier table is deleted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FreeUidThreadExitProc(
+ ClientData clientData) /* Not used. */
+{
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ Tcl_DeleteHashTable(&tsdPtr->uidTable);
+ tsdPtr->initialized = 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetUid --
+ *
+ * Given a string, this function returns a unique identifier for the
+ * string.
+ *
+ * Results:
+ * This function returns a Tk_Uid corresponding to the "string" argument.
+ * The Tk_Uid has a string value identical to string (strcmp will return
+ * 0), but it's guaranteed that any other calls to this function with a
+ * string equal to "string" will return exactly the same result (i.e. can
+ * compare Tk_Uid *values* directly, without having to call strcmp on
+ * what they point to).
+ *
+ * Side effects:
+ * New information may be entered into the identifier table.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_Uid
+Tk_GetUid(
+ const char *string) /* String to convert. */
+{
+ int dummy;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ Tcl_HashTable *tablePtr = &tsdPtr->uidTable;
+
+ if (!tsdPtr->initialized) {
+ Tcl_InitHashTable(tablePtr, TCL_STRING_KEYS);
+ Tcl_CreateThreadExitHandler(FreeUidThreadExitProc, NULL);
+ tsdPtr->initialized = 1;
+ }
+ return (Tk_Uid) Tcl_GetHashKey(tablePtr,
+ Tcl_CreateHashEntry(tablePtr, string, &dummy));
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_GetScreenMM --
+ *
+ * Given a string, returns the number of screen millimeters corresponding
+ * to that string.
+ *
+ * Results:
+ * The return value is a standard Tcl return result. If TCL_OK is
+ * returned, then everything went well and the screen distance is stored
+ * at *doublePtr; otherwise TCL_ERROR is returned and an error message is
+ * left in the interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_GetScreenMM(
+ Tcl_Interp *interp, /* Use this for error reporting. */
+ Tk_Window tkwin, /* Window whose screen determines conversion
+ * from centimeters and other absolute
+ * units. */
+ const char *string, /* String describing a screen distance. */
+ double *doublePtr) /* Place to store converted result. */
+{
+ char *end;
+ double d;
+
+ d = strtod(string, &end);
+ if (end == string) {
+ goto error;
+ }
+ while ((*end != '\0') && isspace(UCHAR(*end))) {
+ end++;
+ }
+ switch (*end) {
+ case 0:
+ d /= WidthOfScreen(Tk_Screen(tkwin));
+ d *= WidthMMOfScreen(Tk_Screen(tkwin));
+ break;
+ case 'c':
+ d *= 10;
+ end++;
+ break;
+ case 'i':
+ d *= 25.4;
+ end++;
+ break;
+ case 'm':
+ end++;
+ break;
+ case 'p':
+ d *= 25.4/72.0;
+ end++;
+ break;
+ default:
+ goto error;
+ }
+ while ((*end != '\0') && isspace(UCHAR(*end))) {
+ end++;
+ }
+ if (*end != 0) {
+ goto error;
+ }
+ *doublePtr = d;
+ return TCL_OK;
+
+ error:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad screen distance \"%s\"", string));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "SCREEN_DISTANCE", NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_GetPixels --
+ *
+ * Given a string, returns the number of pixels corresponding to that
+ * string.
+ *
+ * Results:
+ * The return value is a standard Tcl return result. If TCL_OK is
+ * returned, then everything went well and the rounded pixel distance is
+ * stored at *intPtr; otherwise TCL_ERROR is returned and an error
+ * message is left in the interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_GetPixels(
+ Tcl_Interp *interp, /* Use this for error reporting. */
+ Tk_Window tkwin, /* Window whose screen determines conversion
+ * from centimeters and other absolute
+ * units. */
+ const char *string, /* String describing a number of pixels. */
+ int *intPtr) /* Place to store converted result. */
+{
+ double d;
+
+ if (TkGetDoublePixels(interp, tkwin, string, &d) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (d < 0) {
+ *intPtr = (int) (d - 0.5);
+ } else {
+ *intPtr = (int) (d + 0.5);
+ }
+ return TCL_OK;
+}
+/*
+ *--------------------------------------------------------------
+ *
+ * TkGetDoublePixels --
+ *
+ * Given a string, returns the number of pixels corresponding to that
+ * string.
+ *
+ * Results:
+ * The return value is a standard Tcl return result. If TCL_OK is
+ * returned, then everything went well and the pixel distance is stored
+ * at *doublePtr; otherwise TCL_ERROR is returned and an error message is
+ * left in interp->result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkGetDoublePixels(
+ Tcl_Interp *interp, /* Use this for error reporting. */
+ Tk_Window tkwin, /* Window whose screen determines conversion
+ * from centimeters and other absolute
+ * units. */
+ const char *string, /* String describing a number of pixels. */
+ double *doublePtr) /* Place to store converted result. */
+{
+ char *end;
+ double d;
+
+ d = strtod((char *) string, &end);
+ if (end == string) {
+ goto error;
+ }
+ while ((*end != '\0') && isspace(UCHAR(*end))) {
+ end++;
+ }
+ switch (*end) {
+ case 0:
+ break;
+ case 'c':
+ d *= 10*WidthOfScreen(Tk_Screen(tkwin));
+ d /= WidthMMOfScreen(Tk_Screen(tkwin));
+ end++;
+ break;
+ case 'i':
+ d *= 25.4*WidthOfScreen(Tk_Screen(tkwin));
+ d /= WidthMMOfScreen(Tk_Screen(tkwin));
+ end++;
+ break;
+ case 'm':
+ d *= WidthOfScreen(Tk_Screen(tkwin));
+ d /= WidthMMOfScreen(Tk_Screen(tkwin));
+ end++;
+ break;
+ case 'p':
+ d *= (25.4/72.0)*WidthOfScreen(Tk_Screen(tkwin));
+ d /= WidthMMOfScreen(Tk_Screen(tkwin));
+ end++;
+ break;
+ default:
+ goto error;
+ }
+ while ((*end != '\0') && isspace(UCHAR(*end))) {
+ end++;
+ }
+ if (*end != 0) {
+ goto error;
+ }
+ *doublePtr = d;
+ return TCL_OK;
+
+ error:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad screen distance \"%s\"", string));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "FRACTIONAL_PIXELS", NULL);
+ return TCL_ERROR;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkGrab.c b/tk8.6/generic/tkGrab.c
new file mode 100644
index 0000000..dc0e8fc
--- /dev/null
+++ b/tk8.6/generic/tkGrab.c
@@ -0,0 +1,1591 @@
+/*
+ * tkGrab.c --
+ *
+ * This file provides functions that implement grabs for Tk.
+ *
+ * Copyright (c) 1992-1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "tkInt.h"
+
+#ifdef _WIN32
+#include "tkWinInt.h"
+#elif !defined(MAC_OSX_TK)
+#include "tkUnixInt.h"
+#endif
+
+/*
+ * The grab state machine has four states: ungrabbed, button pressed, grabbed,
+ * and button pressed while grabbed. In addition, there are three pieces of
+ * grab state information: the current grab window, the current restrict
+ * window, and whether the mouse is captured.
+ *
+ * The current grab window specifies the point in the Tk window heirarchy
+ * above which pointer events will not be reported. Any window within the
+ * subtree below the grab window will continue to receive events as normal.
+ * Events outside of the grab tree will be reported to the grab window.
+ *
+ * If the current restrict window is set, then all pointer events will be
+ * reported only to the restrict window. The restrict window is normally set
+ * during an automatic button grab.
+ *
+ * The mouse capture state specifies whether the window system will report
+ * mouse events outside of any Tk toplevels. This is set during a global grab
+ * or an automatic button grab.
+ *
+ * The transitions between different states is given in the following table:
+ *
+ * Event\State U B G GB
+ * ----------- -- -- -- --
+ * FirstPress B B GB GB
+ * Press B B G GB
+ * Release U B G GB
+ * LastRelease U U G G
+ * Grab G G G G
+ * Ungrab U B U U
+ *
+ * Note: U=Ungrabbed, B=Button, G=Grabbed, GB=Grab and Button
+ *
+ * In addition, the following conditions are always true:
+ *
+ * State\Variable Grab Restrict Capture
+ * -------------- ---- -------- -------
+ * Ungrabbed 0 0 0
+ * Button 0 1 1
+ * Grabbed 1 0 b/g
+ * Grab and Button 1 1 1
+ *
+ * Note: 0 means variable is set to NULL, 1 means variable is set to some
+ * window, b/g means the variable is set to a window if a button is currently
+ * down or a global grab is in effect.
+ *
+ * The final complication to all of this is enter and leave events. In order
+ * to correctly handle all of the various cases, Tk cannot rely on X
+ * enter/leave events in all situations. The following describes the correct
+ * sequence of enter and leave events that should be observed by Tk scripts:
+ *
+ * Event(state) Enter/Leave From -> To
+ * ------------ ----------------------
+ * LastRelease(B | GB): restrict window -> anc(grab window, event window)
+ * Grab(U | B): event window -> anc(grab window, event window)
+ * Grab(G): anc(old grab window, event window) ->
+ * anc(new grab window, event window)
+ * Grab(GB): restrict window -> anc(new grab window, event window)
+ * Ungrab(G): anc(grab window, event window) -> event window
+ * Ungrab(GB): restrict window -> event window
+ *
+ * Note: anc(x,y) returns the least ancestor of y that is in the tree of x,
+ * terminating at toplevels.
+ */
+
+/*
+ * The following structure is used to pass information to GrabRestrictProc
+ * from EatGrabEvents.
+ */
+
+typedef struct {
+ Display *display; /* Display from which to discard events. */
+ unsigned int serial; /* Serial number with which to compare. */
+} GrabInfo;
+
+/*
+ * Bit definitions for grabFlags field of TkDisplay structures:
+ *
+ * GRAB_GLOBAL 1 means this is a global grab (we grabbed via
+ * the server so all applications are locked out).
+ * 0 means this is a local grab that affects only
+ * this application.
+ * GRAB_TEMP_GLOBAL 1 means we've temporarily grabbed via the
+ * server because a button is down and we want to
+ * make sure that we get the button-up event. The
+ * grab will be released when the last mouse
+ * button goes up.
+ */
+
+#define GRAB_GLOBAL 1
+#define GRAB_TEMP_GLOBAL 4
+
+/*
+ * The following structure is a Tcl_Event that triggers a change in the
+ * grabWinPtr field of a display. This event guarantees that the change occurs
+ * in the proper order relative to enter and leave events.
+ */
+
+typedef struct NewGrabWinEvent {
+ Tcl_Event header; /* Standard information for all Tcl events. */
+ TkDisplay *dispPtr; /* Display whose grab window is to change. */
+ Window grabWindow; /* New grab window for display. This is
+ * recorded instead of a (TkWindow *) because
+ * it will allow us to detect cases where the
+ * window is destroyed before this event is
+ * processed. */
+} NewGrabWinEvent;
+
+/*
+ * The following magic value is stored in the "send_event" field of
+ * EnterNotify and LeaveNotify events that are generated in this file. This
+ * allows us to separate "real" events coming from the server from those that
+ * we generated.
+ */
+
+#define GENERATED_GRAB_EVENT_MAGIC ((Bool) 0x147321ac)
+
+/*
+ * Mask that selects any of the state bits corresponding to buttons, plus
+ * masks that select individual buttons' bits:
+ */
+
+#define ALL_BUTTONS \
+ (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask)
+static const unsigned int buttonStates[] = {
+ Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask
+};
+
+/*
+ * Forward declarations for functions declared later in this file:
+ */
+
+static void EatGrabEvents(TkDisplay *dispPtr, unsigned int serial);
+static TkWindow * FindCommonAncestor(TkWindow *winPtr1,
+ TkWindow *winPtr2, int *countPtr1, int *countPtr2);
+static Tk_RestrictProc GrabRestrictProc;
+static int GrabWinEventProc(Tcl_Event *evPtr, int flags);
+static void MovePointer2(TkWindow *sourcePtr, TkWindow *destPtr,
+ int mode, int leaveEvents, int EnterEvents);
+static void QueueGrabWindowChange(TkDisplay *dispPtr,
+ TkWindow *grabWinPtr);
+static void ReleaseButtonGrab(TkDisplay *dispPtr);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GrabObjCmd --
+ *
+ * This function is invoked to process the "grab" 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_GrabObjCmd(
+ ClientData clientData, /* Main window associated with interpreter. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ int globalGrab;
+ Tk_Window tkwin;
+ TkDisplay *dispPtr;
+ const char *arg;
+ int index;
+ int len;
+ static const char *const optionStrings[] = {
+ "current", "release", "set", "status", NULL
+ };
+ static const char *const flagStrings[] = {
+ "-global", NULL
+ };
+ enum options {
+ GRABCMD_CURRENT, GRABCMD_RELEASE, GRABCMD_SET, GRABCMD_STATUS
+ };
+
+ if (objc < 2) {
+ /*
+ * Can't use Tcl_WrongNumArgs here because we want the message to
+ * read:
+ * wrong # args: should be "cmd ?-global? window" or "cmd option
+ * ?arg ...?"
+ * We can fake it with Tcl_WrongNumArgs if we assume the command name
+ * is "grab", but if it has been aliased, the message will be
+ * incorrect.
+ */
+
+ Tcl_WrongNumArgs(interp, 1, objv, "?-global? window");
+ Tcl_AppendResult(interp, " or \"", Tcl_GetString(objv[0]),
+ " option ?arg ...?\"", NULL);
+ /* This API not exposed:
+ *
+ ((Interp *) interp)->flags |= INTERP_ALTERNATE_WRONG_ARGS;
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ */
+ return TCL_ERROR;
+ }
+
+ /*
+ * First check for a window name or "-global" as the first argument.
+ */
+
+ arg = Tcl_GetStringFromObj(objv[1], &len);
+ if (arg[0] == '.') {
+ /* [grab window] */
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "?-global? window");
+ return TCL_ERROR;
+ }
+ tkwin = Tk_NameToWindow(interp, arg, clientData);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ return Tk_Grab(interp, tkwin, 0);
+ } else if (arg[0] == '-' && len > 1) {
+ if (Tcl_GetIndexFromObj(interp, objv[1], flagStrings, "option", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /* [grab -global window] */
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "?-global? window");
+ return TCL_ERROR;
+ }
+ tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), clientData);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ return Tk_Grab(interp, tkwin, 1);
+ }
+
+ /*
+ * First argument is not a window name and not "-global", find out which
+ * option it is.
+ */
+
+ if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch ((enum options) index) {
+ case GRABCMD_CURRENT:
+ /* [grab current ?window?] */
+ if (objc > 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "current ?window?");
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]),
+ clientData);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ dispPtr = ((TkWindow *) tkwin)->dispPtr;
+ if (dispPtr->eventualGrabWinPtr != NULL) {
+ Tcl_SetObjResult(interp, TkNewWindowObj((Tk_Window)
+ dispPtr->eventualGrabWinPtr));
+ }
+ } else {
+ Tcl_Obj *resultObj = Tcl_NewObj();
+
+ for (dispPtr = TkGetDisplayList(); dispPtr != NULL;
+ dispPtr = dispPtr->nextPtr) {
+ if (dispPtr->eventualGrabWinPtr != NULL) {
+ Tcl_ListObjAppendElement(NULL, resultObj, TkNewWindowObj(
+ (Tk_Window) dispPtr->eventualGrabWinPtr));
+ }
+ }
+ Tcl_SetObjResult(interp, resultObj);
+ }
+ return TCL_OK;
+
+ case GRABCMD_RELEASE:
+ /* [grab release window] */
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "release window");
+ return TCL_ERROR;
+ }
+ tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), clientData);
+ if (tkwin == NULL) {
+ Tcl_ResetResult(interp);
+ } else {
+ Tk_Ungrab(tkwin);
+ }
+ break;
+
+ case GRABCMD_SET:
+ /* [grab set ?-global? window] */
+ if ((objc != 3) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "set ?-global? window");
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ globalGrab = 0;
+ tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]),
+ clientData);
+ } else {
+ globalGrab = 1;
+
+ /*
+ * We could just test the argument by hand instead of using
+ * Tcl_GetIndexFromObj; the benefit of using the function is that
+ * it sets up the error message for us, so we are certain to be
+ * consistant with the rest of Tcl.
+ */
+
+ if (Tcl_GetIndexFromObj(interp, objv[2], flagStrings, "option",
+ 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[3]),
+ clientData);
+ }
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ return Tk_Grab(interp, tkwin, globalGrab);
+
+ case GRABCMD_STATUS: {
+ /* [grab status window] */
+ TkWindow *winPtr;
+ const char *statusString;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "status window");
+ return TCL_ERROR;
+ }
+ winPtr = (TkWindow *) Tk_NameToWindow(interp, Tcl_GetString(objv[2]),
+ clientData);
+ if (winPtr == NULL) {
+ return TCL_ERROR;
+ }
+ dispPtr = winPtr->dispPtr;
+ if (dispPtr->eventualGrabWinPtr != winPtr) {
+ statusString = "none";
+ } else if (dispPtr->grabFlags & GRAB_GLOBAL) {
+ statusString = "global";
+ } else {
+ statusString = "local";
+ }
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(statusString, -1));
+ break;
+ }
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_Grab --
+ *
+ * Grabs the pointer and keyboard, so that mouse-related events are only
+ * reported relative to a given window and its descendants.
+ *
+ * Results:
+ * A standard Tcl result is returned. TCL_OK is the normal return value;
+ * if the grab could not be set then TCL_ERROR is returned and the
+ * interp's result will hold an error message.
+ *
+ * Side effects:
+ * Once this call completes successfully, no window outside the tree
+ * rooted at tkwin will receive pointer- or keyboard-related events until
+ * the next call to Tk_Ungrab. If a previous grab was in effect within
+ * this application, then it is replaced with a new one.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_Grab(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tk_Window tkwin, /* Window on whose behalf the pointer is to be
+ * grabbed. */
+ int grabGlobal) /* Non-zero means issue a grab to the server
+ * so that no other application gets mouse or
+ * keyboard events. Zero means the grab only
+ * applies within this application. */
+{
+ int grabResult, numTries;
+ TkWindow *winPtr = (TkWindow *) tkwin;
+ TkDisplay *dispPtr = winPtr->dispPtr;
+ TkWindow *winPtr2;
+ unsigned int serial;
+
+ ReleaseButtonGrab(dispPtr);
+ if (dispPtr->eventualGrabWinPtr != NULL) {
+ if ((dispPtr->eventualGrabWinPtr == winPtr)
+ && (grabGlobal == ((dispPtr->grabFlags & GRAB_GLOBAL) != 0))) {
+ return TCL_OK;
+ }
+ if (dispPtr->eventualGrabWinPtr->mainPtr != winPtr->mainPtr) {
+ goto alreadyGrabbed;
+ }
+ Tk_Ungrab((Tk_Window) dispPtr->eventualGrabWinPtr);
+ }
+
+ Tk_MakeWindowExist(tkwin);
+ if (!grabGlobal) {
+ Window dummy1, dummy2;
+ int dummy3, dummy4, dummy5, dummy6;
+ unsigned int state;
+
+ /*
+ * Local grab. However, if any mouse buttons are down, turn it into a
+ * global grab temporarily, until the last button goes up. This does
+ * two things: (a) it makes sure that we see the button-up event; and
+ * (b) it allows us to track mouse motion among all of the windows of
+ * this application.
+ */
+
+ dispPtr->grabFlags &= ~(GRAB_GLOBAL|GRAB_TEMP_GLOBAL);
+ XQueryPointer(dispPtr->display, winPtr->window, &dummy1,
+ &dummy2, &dummy3, &dummy4, &dummy5, &dummy6, &state);
+ if (state & ALL_BUTTONS) {
+ dispPtr->grabFlags |= GRAB_TEMP_GLOBAL;
+ goto setGlobalGrab;
+ }
+ } else {
+ dispPtr->grabFlags |= GRAB_GLOBAL;
+ setGlobalGrab:
+
+ /*
+ * Tricky point: must ungrab before grabbing. This is needed in case
+ * there is a button auto-grab already in effect. If there is, and the
+ * mouse has moved to a different window, X won't generate enter and
+ * leave events to move the mouse if we grab without ungrabbing.
+ */
+
+ XUngrabPointer(dispPtr->display, CurrentTime);
+ serial = NextRequest(dispPtr->display);
+
+ /*
+ * Another tricky point: there are races with some window managers
+ * that can cause grabs to fail because the window manager hasn't
+ * released its grab quickly enough. To work around this problem,
+ * retry a few times after AlreadyGrabbed errors to give the grab
+ * release enough time to register with the server.
+ */
+
+ grabResult = 0; /* Needed only to prevent gcc compiler
+ * warnings. */
+ for (numTries = 0; numTries < 10; numTries++) {
+ grabResult = XGrabPointer(dispPtr->display, winPtr->window,
+ True, ButtonPressMask|ButtonReleaseMask|ButtonMotionMask
+ |PointerMotionMask, GrabModeAsync, GrabModeAsync, None,
+ None, CurrentTime);
+ if (grabResult != AlreadyGrabbed) {
+ break;
+ }
+ Tcl_Sleep(100);
+ }
+ if (grabResult != 0) {
+ goto grabError;
+ }
+ grabResult = XGrabKeyboard(dispPtr->display, Tk_WindowId(tkwin),
+ False, GrabModeAsync, GrabModeAsync, CurrentTime);
+ if (grabResult != 0) {
+ XUngrabPointer(dispPtr->display, CurrentTime);
+ goto grabError;
+ }
+
+ /*
+ * Eat up any grab-related events generated by the server for the
+ * grab. There are several reasons for doing this:
+ *
+ * 1. We have to synthesize the events for local grabs anyway, since
+ * the server doesn't participate in them.
+ * 2. The server doesn't always generate the right events for global
+ * grabs (e.g. it generates events even if the current window is in
+ * the grab tree, which we don't want).
+ * 3. We want all the grab-related events to be processed immediately
+ * (before other events that are already queued); events coming
+ * from the server will be in the wrong place, but events we
+ * synthesize here will go to the front of the queue.
+ */
+
+ EatGrabEvents(dispPtr, serial);
+ }
+
+ /*
+ * Synthesize leave events to move the pointer from its current window up
+ * to the lowest ancestor that it has in common with the grab window.
+ * However, only do this if the pointer is outside the grab window's
+ * subtree but inside the grab window's application.
+ */
+
+ if ((dispPtr->serverWinPtr != NULL)
+ && (dispPtr->serverWinPtr->mainPtr == winPtr->mainPtr)) {
+ for (winPtr2 = dispPtr->serverWinPtr; ; winPtr2 = winPtr2->parentPtr) {
+ if (winPtr2 == winPtr) {
+ break;
+ }
+ if (winPtr2 == NULL) {
+ MovePointer2(dispPtr->serverWinPtr, winPtr, NotifyGrab, 1, 0);
+ break;
+ }
+ }
+ }
+ QueueGrabWindowChange(dispPtr, winPtr);
+ return TCL_OK;
+
+ grabError:
+ if (grabResult == GrabNotViewable) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "grab failed: window not viewable", -1));
+ Tcl_SetErrorCode(interp, "TK", "GRAB", "UNVIEWABLE", NULL);
+ } else if (grabResult == AlreadyGrabbed) {
+ alreadyGrabbed:
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "grab failed: another application has grab", -1));
+ Tcl_SetErrorCode(interp, "TK", "GRAB", "GRABBED", NULL);
+ } else if (grabResult == GrabFrozen) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "grab failed: keyboard or pointer frozen", -1));
+ Tcl_SetErrorCode(interp, "TK", "GRAB", "FROZEN", NULL);
+ } else if (grabResult == GrabInvalidTime) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "grab failed: invalid time", -1));
+ Tcl_SetErrorCode(interp, "TK", "GRAB", "BAD_TIME", NULL);
+ } else {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "grab failed for unknown reason (code %d)", grabResult));
+ Tcl_SetErrorCode(interp, "TK", "GRAB", "UNKNOWN", NULL);
+ }
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_Ungrab --
+ *
+ * Releases a grab on the mouse pointer and keyboard, if there is one set
+ * on the specified window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Pointer and keyboard events will start being delivered to other
+ * windows again.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_Ungrab(
+ Tk_Window tkwin) /* Window whose grab should be released. */
+{
+ TkDisplay *dispPtr;
+ TkWindow *grabWinPtr, *winPtr;
+ unsigned int serial;
+
+ grabWinPtr = (TkWindow *) tkwin;
+ dispPtr = grabWinPtr->dispPtr;
+ if (grabWinPtr != dispPtr->eventualGrabWinPtr) {
+ return;
+ }
+ ReleaseButtonGrab(dispPtr);
+ QueueGrabWindowChange(dispPtr, NULL);
+ if (dispPtr->grabFlags & (GRAB_GLOBAL|GRAB_TEMP_GLOBAL)) {
+ dispPtr->grabFlags &= ~(GRAB_GLOBAL|GRAB_TEMP_GLOBAL);
+ serial = NextRequest(dispPtr->display);
+ XUngrabPointer(dispPtr->display, CurrentTime);
+ XUngrabKeyboard(dispPtr->display, CurrentTime);
+ EatGrabEvents(dispPtr, serial);
+ }
+
+ /*
+ * Generate events to move the pointer back to the window where it really
+ * is. Some notes:
+ * 1. As with grabs, only do this if the "real" window is not a descendant
+ * of the grab window, since in this case the pointer is already where
+ * it's supposed to be.
+ * 2. If the "real" window is in some other application then don't
+ * generate any events at all, since everything's already been reported
+ * correctly.
+ * 3. Only generate enter events. Don't generate leave events, because we
+ * never told the lower-level windows that they had the pointer in the
+ * first place.
+ */
+
+ for (winPtr = dispPtr->serverWinPtr; ; winPtr = winPtr->parentPtr) {
+ if (winPtr == grabWinPtr) {
+ break;
+ }
+ if (winPtr == NULL) {
+ if ((dispPtr->serverWinPtr == NULL) ||
+ (dispPtr->serverWinPtr->mainPtr == grabWinPtr->mainPtr)) {
+ MovePointer2(grabWinPtr, dispPtr->serverWinPtr,
+ NotifyUngrab, 0, 1);
+ }
+ break;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ReleaseButtonGrab --
+ *
+ * This function is called to release a simulated button grab, if there
+ * is one in effect. A button grab is present whenever
+ * dispPtr->buttonWinPtr is non-NULL or when the GRAB_TEMP_GLOBAL flag is
+ * set.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * DispPtr->buttonWinPtr is reset to NULL, and enter and leave events are
+ * generated if necessary to move the pointer from the button grab window
+ * to its current window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ReleaseButtonGrab(
+ register TkDisplay *dispPtr)/* Display whose button grab is to be
+ * released. */
+{
+ unsigned int serial;
+
+ if (dispPtr->buttonWinPtr != NULL) {
+ if (dispPtr->buttonWinPtr != dispPtr->serverWinPtr) {
+ MovePointer2(dispPtr->buttonWinPtr, dispPtr->serverWinPtr,
+ NotifyUngrab, 1, 1);
+ }
+ dispPtr->buttonWinPtr = NULL;
+ }
+ if (dispPtr->grabFlags & GRAB_TEMP_GLOBAL) {
+ dispPtr->grabFlags &= ~GRAB_TEMP_GLOBAL;
+ serial = NextRequest(dispPtr->display);
+ XUngrabPointer(dispPtr->display, CurrentTime);
+ XUngrabKeyboard(dispPtr->display, CurrentTime);
+ EatGrabEvents(dispPtr, serial);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkPointerEvent --
+ *
+ * This function is called for each pointer-related event, before the
+ * event has been processed. It does various things to make grabs work
+ * correctly.
+ *
+ * Results:
+ * If the return value is 1 it means the event should be processed (event
+ * handlers should be invoked). If the return value is 0 it means the
+ * event should be ignored in order to make grabs work correctly. In some
+ * cases this function modifies the event.
+ *
+ * Side effects:
+ * Grab state information may be updated. New events may also be pushed
+ * back onto the event queue to replace or augment the one passed in
+ * here.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkPointerEvent(
+ register XEvent *eventPtr, /* Pointer to the event. */
+ TkWindow *winPtr) /* Tk's information for window where event was
+ * reported. */
+{
+ register TkWindow *winPtr2;
+ TkDisplay *dispPtr = winPtr->dispPtr;
+ unsigned int serial;
+ int outsideGrabTree = 0;
+ int ancestorOfGrab = 0;
+ int appGrabbed = 0; /* Non-zero means event is being reported to
+ * an application that is affected by the
+ * grab. */
+
+ /*
+ * Collect information about the grab (if any).
+ */
+
+ switch (TkGrabState(winPtr)) {
+ case TK_GRAB_IN_TREE:
+ appGrabbed = 1;
+ break;
+ case TK_GRAB_ANCESTOR:
+ appGrabbed = 1;
+ outsideGrabTree = 1;
+ ancestorOfGrab = 1;
+ break;
+ case TK_GRAB_EXCLUDED:
+ appGrabbed = 1;
+ outsideGrabTree = 1;
+ break;
+ }
+
+ if ((eventPtr->type == EnterNotify) || (eventPtr->type == LeaveNotify)) {
+ /*
+ * Keep track of what window the mouse is *really* over. Any events
+ * that we generate have a special send_event value, which is detected
+ * below and used to ignore the event for purposes of setting
+ * serverWinPtr.
+ */
+
+ if (eventPtr->xcrossing.send_event != GENERATED_GRAB_EVENT_MAGIC) {
+ if ((eventPtr->type == LeaveNotify) &&
+ (winPtr->flags & TK_TOP_HIERARCHY)) {
+ dispPtr->serverWinPtr = NULL;
+ } else {
+ dispPtr->serverWinPtr = winPtr;
+ }
+ }
+
+ /*
+ * When a grab is active, X continues to report enter and leave events
+ * for windows outside the tree of the grab window:
+ * 1. Detect these events and ignore them except for windows above the
+ * grab window.
+ * 2. Allow Enter and Leave events to pass through the windows above
+ * the grab window, but never let them end up with the pointer *in*
+ * one of those windows.
+ */
+
+ if (dispPtr->grabWinPtr != NULL) {
+ if (outsideGrabTree && appGrabbed) {
+ if (!ancestorOfGrab) {
+ return 0;
+ }
+ switch (eventPtr->xcrossing.detail) {
+ case NotifyInferior:
+ return 0;
+ case NotifyAncestor:
+ eventPtr->xcrossing.detail = NotifyVirtual;
+ break;
+ case NotifyNonlinear:
+ eventPtr->xcrossing.detail = NotifyNonlinearVirtual;
+ break;
+ }
+ }
+
+ /*
+ * Make buttons have the same grab-like behavior inside a grab as
+ * they do outside a grab: do this by ignoring enter and leave
+ * events except for the window in which the button was pressed.
+ */
+
+ if ((dispPtr->buttonWinPtr != NULL)
+ && (winPtr != dispPtr->buttonWinPtr)) {
+ return 0;
+ }
+ }
+ return 1;
+ }
+
+ if (!appGrabbed) {
+ return 1;
+ }
+
+ if (eventPtr->type == MotionNotify) {
+ /*
+ * When grabs are active, X reports motion events relative to the
+ * window under the pointer. Instead, it should report the events
+ * relative to the window the button went down in, if there is a
+ * button down. Otherwise, if the pointer window is outside the
+ * subtree of the grab window, the events should be reported relative
+ * to the grab window. Otherwise, the event should be reported to the
+ * pointer window.
+ */
+
+ winPtr2 = winPtr;
+ if (dispPtr->buttonWinPtr != NULL) {
+ winPtr2 = dispPtr->buttonWinPtr;
+ } else if (outsideGrabTree || (dispPtr->serverWinPtr == NULL)) {
+ winPtr2 = dispPtr->grabWinPtr;
+ }
+ if (winPtr2 != winPtr) {
+ TkChangeEventWindow(eventPtr, winPtr2);
+ Tk_QueueWindowEvent(eventPtr, TCL_QUEUE_HEAD);
+ return 0;
+ }
+ return 1;
+ }
+
+ /*
+ * Process ButtonPress and ButtonRelease events:
+ * 1. Keep track of whether a button is down and what window it went down
+ * in.
+ * 2. If the first button goes down outside the grab tree, pretend it went
+ * down in the grab window. Note: it's important to redirect events to
+ * the grab window like this in order to make things like menus work,
+ * where button presses outside the grabbed menu need to be seen. An
+ * application can always ignore the events if they occur outside its
+ * window.
+ * 3. If a button press or release occurs outside the window where the
+ * first button was pressed, retarget the event so it's reported to the
+ * window where the first button was pressed.
+ * 4. If the last button is released in a window different than where the
+ * first button was pressed, generate Enter/Leave events to move the
+ * mouse from the button window to its current window.
+ * 5. If the grab is set at a time when a button is already down, or if
+ * the window where the button was pressed was deleted, then
+ * dispPtr->buttonWinPtr will stay NULL. Just forget about the
+ * auto-grab for the button press; events will go to whatever window
+ * contains the pointer. If this window isn't in the grab tree then
+ * redirect events to the grab window.
+ * 6. When a button is pressed during a local grab, the X server sets a
+ * grab of its own, since it doesn't even know about our local grab.
+ * This causes enter and leave events no longer to be generated in the
+ * same way as for global grabs. To eliminate this problem, set a
+ * temporary global grab when the first button goes down and release it
+ * when the last button comes up.
+ */
+
+ if ((eventPtr->type == ButtonPress) || (eventPtr->type == ButtonRelease)) {
+ winPtr2 = dispPtr->buttonWinPtr;
+ if (winPtr2 == NULL) {
+ if (outsideGrabTree) {
+ winPtr2 = dispPtr->grabWinPtr; /* Note 5. */
+ } else {
+ winPtr2 = winPtr; /* Note 5. */
+ }
+ }
+ if (eventPtr->type == ButtonPress) {
+ if (!(eventPtr->xbutton.state & ALL_BUTTONS)) {
+ if (outsideGrabTree) {
+ TkChangeEventWindow(eventPtr, dispPtr->grabWinPtr);
+ Tk_QueueWindowEvent(eventPtr, TCL_QUEUE_HEAD);
+ return 0; /* Note 2. */
+ }
+ if (!(dispPtr->grabFlags & GRAB_GLOBAL)) { /* Note 6. */
+ serial = NextRequest(dispPtr->display);
+ if (XGrabPointer(dispPtr->display,
+ dispPtr->grabWinPtr->window, True,
+ ButtonPressMask|ButtonReleaseMask|ButtonMotionMask,
+ GrabModeAsync, GrabModeAsync, None, None,
+ CurrentTime) == 0) {
+ EatGrabEvents(dispPtr, serial);
+ if (XGrabKeyboard(dispPtr->display, winPtr->window,
+ False, GrabModeAsync, GrabModeAsync,
+ CurrentTime) == 0) {
+ dispPtr->grabFlags |= GRAB_TEMP_GLOBAL;
+ } else {
+ XUngrabPointer(dispPtr->display, CurrentTime);
+ }
+ }
+ }
+ dispPtr->buttonWinPtr = winPtr;
+ return 1;
+ }
+ } else {
+ if (eventPtr->xbutton.button != AnyButton &&
+ ((eventPtr->xbutton.state & ALL_BUTTONS)
+ == buttonStates[eventPtr->xbutton.button - Button1])) {
+ ReleaseButtonGrab(dispPtr); /* Note 4. */
+ }
+ }
+ if (winPtr2 != winPtr) {
+ TkChangeEventWindow(eventPtr, winPtr2);
+ Tk_QueueWindowEvent(eventPtr, TCL_QUEUE_HEAD);
+ return 0; /* Note 3. */
+ }
+ }
+
+ return 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkChangeEventWindow --
+ *
+ * Given an event and a new window to which the event should be
+ * retargeted, modify fields of the event so that the event is properly
+ * retargeted to the new window.
+ *
+ * Results:
+ * The following fields of eventPtr are modified: window, subwindow, x,
+ * y, same_screen.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkChangeEventWindow(
+ register XEvent *eventPtr, /* Event to retarget. Must have type
+ * ButtonPress, ButtonRelease, KeyPress,
+ * KeyRelease, MotionNotify, EnterNotify, or
+ * LeaveNotify. */
+ TkWindow *winPtr) /* New target window for event. */
+{
+ int x, y, sameScreen, bd;
+ register TkWindow *childPtr;
+
+ eventPtr->xmotion.window = Tk_WindowId(winPtr);
+ if (eventPtr->xmotion.root ==
+ RootWindow(winPtr->display, winPtr->screenNum)) {
+ Tk_GetRootCoords((Tk_Window) winPtr, &x, &y);
+ eventPtr->xmotion.x = eventPtr->xmotion.x_root - x;
+ eventPtr->xmotion.y = eventPtr->xmotion.y_root - y;
+ eventPtr->xmotion.subwindow = None;
+ for (childPtr = winPtr->childList; childPtr != NULL;
+ childPtr = childPtr->nextPtr) {
+ if (childPtr->flags & TK_TOP_HIERARCHY) {
+ continue;
+ }
+ x = eventPtr->xmotion.x - childPtr->changes.x;
+ y = eventPtr->xmotion.y - childPtr->changes.y;
+ bd = childPtr->changes.border_width;
+ if ((x >= -bd) && (y >= -bd)
+ && (x < (childPtr->changes.width + bd))
+ && (y < (childPtr->changes.height + bd))) {
+ eventPtr->xmotion.subwindow = childPtr->window;
+ }
+ }
+ sameScreen = 1;
+ } else {
+ eventPtr->xmotion.x = 0;
+ eventPtr->xmotion.y = 0;
+ eventPtr->xmotion.subwindow = None;
+ sameScreen = 0;
+ }
+ if (eventPtr->type == MotionNotify) {
+ eventPtr->xmotion.same_screen = sameScreen;
+ } else {
+ eventPtr->xbutton.same_screen = sameScreen;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkInOutEvents --
+ *
+ * This function synthesizes EnterNotify and LeaveNotify events to
+ * correctly transfer the pointer from one window to another. It can also
+ * be used to generate FocusIn and FocusOut events to move the input
+ * focus.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Synthesized events may be pushed back onto the event queue. The event
+ * pointed to by eventPtr is modified.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkInOutEvents(
+ XEvent *eventPtr, /* A template X event. Must have all fields
+ * properly set except for type, window,
+ * subwindow, x, y, detail, and same_screen.
+ * (Not all of these fields are valid for
+ * FocusIn/FocusOut events; x_root and y_root
+ * must be valid for Enter/Leave events, even
+ * though x and y needn't be valid). */
+ TkWindow *sourcePtr, /* Window that used to have the pointer or
+ * focus (NULL means it was not in a window
+ * managed by this process). */
+ TkWindow *destPtr, /* Window that is to end up with the pointer
+ * or focus (NULL means it's not one managed
+ * by this process). */
+ int leaveType, /* Type of events to generate for windows
+ * being left (LeaveNotify or FocusOut). 0
+ * means don't generate leave events. */
+ int enterType, /* Type of events to generate for windows
+ * being entered (EnterNotify or FocusIn). 0
+ * means don't generate enter events. */
+ Tcl_QueuePosition position) /* Position at which events are added to the
+ * system event queue. */
+{
+ register TkWindow *winPtr;
+ int upLevels, downLevels, i, j, focus;
+
+ /*
+ * There are four possible cases to deal with:
+ *
+ * 1. SourcePtr and destPtr are the same. There's nothing to do in this
+ * case.
+ * 2. SourcePtr is an ancestor of destPtr in the same top-level window.
+ * Must generate events down the window tree from source to dest.
+ * 3. DestPtr is an ancestor of sourcePtr in the same top-level window.
+ * Must generate events up the window tree from sourcePtr to destPtr.
+ * 4. All other cases. Must first generate events up the window tree from
+ * sourcePtr to its top-level, then down from destPtr's top-level to
+ * destPtr. This form is called "non-linear."
+ *
+ * The call to FindCommonAncestor separates these four cases and decides
+ * how many levels up and down events have to be generated for.
+ */
+
+ if (sourcePtr == destPtr) {
+ return;
+ }
+ if ((leaveType == FocusOut) || (enterType == FocusIn)) {
+ focus = 1;
+ } else {
+ focus = 0;
+ }
+ FindCommonAncestor(sourcePtr, destPtr, &upLevels, &downLevels);
+
+ /*
+ * Generate enter/leave events and add them to the grab event queue.
+ */
+
+#define QUEUE(w, t, d) \
+ if (w->window != None) { \
+ eventPtr->type = t; \
+ if (focus) { \
+ eventPtr->xfocus.window = w->window; \
+ eventPtr->xfocus.detail = d; \
+ } else { \
+ eventPtr->xcrossing.detail = d; \
+ TkChangeEventWindow(eventPtr, w); \
+ } \
+ Tk_QueueWindowEvent(eventPtr, position); \
+ }
+
+ if (downLevels == 0) {
+ /*
+ * SourcePtr is an inferior of destPtr.
+ */
+
+ if (leaveType != 0) {
+ QUEUE(sourcePtr, leaveType, NotifyAncestor);
+ for (winPtr = sourcePtr->parentPtr, i = upLevels-1; i > 0;
+ winPtr = winPtr->parentPtr, i--) {
+ QUEUE(winPtr, leaveType, NotifyVirtual);
+ }
+ }
+ if ((enterType != 0) && (destPtr != NULL)) {
+ QUEUE(destPtr, enterType, NotifyInferior);
+ }
+ } else if (upLevels == 0) {
+ /*
+ * DestPtr is an inferior of sourcePtr.
+ */
+
+ if ((leaveType != 0) && (sourcePtr != NULL)) {
+ QUEUE(sourcePtr, leaveType, NotifyInferior);
+ }
+ if (enterType != 0) {
+ for (i = downLevels-1; i > 0; i--) {
+ for (winPtr = destPtr->parentPtr, j = 1; j < i;
+ winPtr = winPtr->parentPtr, j++) {
+ /* empty */
+ }
+ QUEUE(winPtr, enterType, NotifyVirtual);
+ }
+ if (destPtr != NULL) {
+ QUEUE(destPtr, enterType, NotifyAncestor);
+ }
+ }
+ } else {
+ /*
+ * Non-linear: neither window is an inferior of the other.
+ */
+
+ if (leaveType != 0) {
+ QUEUE(sourcePtr, leaveType, NotifyNonlinear);
+ for (winPtr = sourcePtr->parentPtr, i = upLevels-1; i > 0;
+ winPtr = winPtr->parentPtr, i--) {
+ QUEUE(winPtr, leaveType, NotifyNonlinearVirtual);
+ }
+ }
+ if (enterType != 0) {
+ for (i = downLevels-1; i > 0; i--) {
+ for (winPtr = destPtr->parentPtr, j = 1; j < i;
+ winPtr = winPtr->parentPtr, j++) {
+ }
+ QUEUE(winPtr, enterType, NotifyNonlinearVirtual);
+ }
+ if (destPtr != NULL) {
+ QUEUE(destPtr, enterType, NotifyNonlinear);
+ }
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MovePointer2 --
+ *
+ * This function synthesizes EnterNotify and LeaveNotify events to
+ * correctly transfer the pointer from one window to another. It is
+ * different from TkInOutEvents in that no template X event needs to be
+ * supplied; this function generates the template event and calls
+ * TkInOutEvents.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Synthesized events may be pushed back onto the event queue.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+MovePointer2(
+ TkWindow *sourcePtr, /* Window currently containing pointer (NULL
+ * means it's not one managed by this
+ * process). */
+ TkWindow *destPtr, /* Window that is to end up containing the
+ * pointer (NULL means it's not one managed by
+ * this process). */
+ int mode, /* Mode for enter/leave events, such as
+ * NotifyNormal or NotifyUngrab. */
+ int leaveEvents, /* Non-zero means generate leave events for
+ * the windows being left. Zero means don't
+ * generate leave events. */
+ int enterEvents) /* Non-zero means generate enter events for
+ * the windows being entered. Zero means don't
+ * generate enter events. */
+{
+ XEvent event;
+ Window dummy1, dummy2;
+ int dummy3, dummy4;
+ TkWindow *winPtr;
+
+ winPtr = sourcePtr;
+ if ((winPtr == NULL) || (winPtr->window == None)) {
+ winPtr = destPtr;
+ if ((winPtr == NULL) || (winPtr->window == None)) {
+ return;
+ }
+ }
+
+ event.xcrossing.serial = LastKnownRequestProcessed(winPtr->display);
+ event.xcrossing.send_event = GENERATED_GRAB_EVENT_MAGIC;
+ event.xcrossing.display = winPtr->display;
+ event.xcrossing.root = RootWindow(winPtr->display, winPtr->screenNum);
+ event.xcrossing.time = TkCurrentTime(winPtr->dispPtr);
+ XQueryPointer(winPtr->display, winPtr->window, &dummy1, &dummy2,
+ &event.xcrossing.x_root, &event.xcrossing.y_root,
+ &dummy3, &dummy4, &event.xcrossing.state);
+ event.xcrossing.mode = mode;
+ event.xcrossing.focus = False;
+ TkInOutEvents(&event, sourcePtr, destPtr, (leaveEvents) ? LeaveNotify : 0,
+ (enterEvents) ? EnterNotify : 0, TCL_QUEUE_MARK);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkGrabDeadWindow --
+ *
+ * This function is invoked whenever a window is deleted, so that
+ * grab-related cleanup can be performed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Various cleanups happen, such as generating events to move the pointer
+ * back to its "natural" window as if an ungrab had been done. See the
+ * code.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkGrabDeadWindow(
+ register TkWindow *winPtr) /* Window that is in the process of being
+ * deleted. */
+{
+ TkDisplay *dispPtr = winPtr->dispPtr;
+
+ if (dispPtr->eventualGrabWinPtr == winPtr) {
+ /*
+ * Grab window was deleted. Release the grab.
+ */
+
+ Tk_Ungrab((Tk_Window) dispPtr->eventualGrabWinPtr);
+ } else if (dispPtr->buttonWinPtr == winPtr) {
+ ReleaseButtonGrab(dispPtr);
+ }
+ if (dispPtr->serverWinPtr == winPtr) {
+ if (winPtr->flags & TK_TOP_HIERARCHY) {
+ dispPtr->serverWinPtr = NULL;
+ } else {
+ dispPtr->serverWinPtr = winPtr->parentPtr;
+ }
+ }
+ if (dispPtr->grabWinPtr == winPtr) {
+ dispPtr->grabWinPtr = NULL;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EatGrabEvents --
+ *
+ * This function is called to eliminate any Enter, Leave, FocusIn, or
+ * FocusOut events in the event queue for a display that have mode
+ * NotifyGrab or NotifyUngrab and have a serial number no less than a
+ * given value and are not generated by the grab module.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * DispPtr's display gets sync-ed, and some of the events get removed
+ * from the Tk event queue.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+EatGrabEvents(
+ TkDisplay *dispPtr, /* Display from which to consume events. */
+ unsigned int serial) /* Only discard events that have a serial
+ * number at least this great. */
+{
+ Tk_RestrictProc *prevProc;
+ GrabInfo info;
+ ClientData prevArg;
+
+ info.display = dispPtr->display;
+ info.serial = serial;
+ TkpSync(info.display);
+ prevProc = Tk_RestrictEvents(GrabRestrictProc, &info, &prevArg);
+ while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS)) {
+ /* EMPTY */
+ }
+ Tk_RestrictEvents(prevProc, prevArg, &prevArg);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GrabRestrictProc --
+ *
+ * A Tk_RestrictProc used by EatGrabEvents to eliminate any Enter, Leave,
+ * FocusIn, or FocusOut events in the event queue for a display that has
+ * mode NotifyGrab or NotifyUngrab and have a serial number no less than
+ * a given value.
+ *
+ * Results:
+ * Returns either TK_DISCARD_EVENT or TK_DEFER_EVENT.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tk_RestrictAction
+GrabRestrictProc(
+ ClientData arg,
+ XEvent *eventPtr)
+{
+ GrabInfo *info = arg;
+ int mode, diff;
+
+ /*
+ * The diff caculation is trickier than it may seem. Don't forget that
+ * serial numbers can wrap around, so can't compare the two serial numbers
+ * directly.
+ */
+
+ diff = eventPtr->xany.serial - info->serial;
+ if ((eventPtr->type == EnterNotify)
+ || (eventPtr->type == LeaveNotify)) {
+ mode = eventPtr->xcrossing.mode;
+ } else if ((eventPtr->type == FocusIn)
+ || (eventPtr->type == FocusOut)) {
+ mode = eventPtr->xfocus.mode;
+ } else {
+ mode = NotifyNormal;
+ }
+ if ((info->display != eventPtr->xany.display) || (mode == NotifyNormal)
+ || (diff < 0)) {
+ return TK_DEFER_EVENT;
+ } else {
+ return TK_DISCARD_EVENT;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * QueueGrabWindowChange --
+ *
+ * This function queues a special event in the Tcl event queue, which
+ * will cause the "grabWinPtr" field for the display to get modified when
+ * the event is processed. This is needed to make sure that the grab
+ * window changes at the proper time relative to grab-related enter and
+ * leave events that are also in the queue. In particular, this approach
+ * works even when multiple grabs and ungrabs happen back-to-back.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * DispPtr->grabWinPtr will be modified later (by GrabWinEventProc) when
+ * the event is removed from the grab event queue.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+QueueGrabWindowChange(
+ TkDisplay *dispPtr, /* Display on which to change the grab
+ * window. */
+ TkWindow *grabWinPtr) /* Window that is to become the new grab
+ * window (may be NULL). */
+{
+ NewGrabWinEvent *grabEvPtr;
+
+ grabEvPtr = ckalloc(sizeof(NewGrabWinEvent));
+ grabEvPtr->header.proc = GrabWinEventProc;
+ grabEvPtr->dispPtr = dispPtr;
+ if (grabWinPtr == NULL) {
+ grabEvPtr->grabWindow = None;
+ } else {
+ grabEvPtr->grabWindow = grabWinPtr->window;
+ }
+ Tcl_QueueEvent(&grabEvPtr->header, TCL_QUEUE_MARK);
+ dispPtr->eventualGrabWinPtr = grabWinPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GrabWinEventProc --
+ *
+ * This function is invoked as a handler for Tcl_Events of type
+ * NewGrabWinEvent. It updates the current grab window field in a
+ * display.
+ *
+ * Results:
+ * Returns 1 if the event was processed, 0 if it should be deferred for
+ * processing later.
+ *
+ * Side effects:
+ * The grabWinPtr field is modified in the display associated with the
+ * event.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GrabWinEventProc(
+ Tcl_Event *evPtr, /* Event of type NewGrabWinEvent. */
+ int flags) /* Flags argument to Tcl_DoOneEvent: indicates
+ * what kinds of events are being processed
+ * right now. */
+{
+ NewGrabWinEvent *grabEvPtr = (NewGrabWinEvent *) evPtr;
+
+ grabEvPtr->dispPtr->grabWinPtr = (TkWindow *) Tk_IdToWindow(
+ grabEvPtr->dispPtr->display, grabEvPtr->grabWindow);
+ return 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FindCommonAncestor --
+ *
+ * Given two windows, this function finds their least common ancestor and
+ * also computes how many levels up this ancestor is from each of the
+ * original windows.
+ *
+ * Results:
+ * If the windows are in different applications or top-level windows,
+ * then NULL is returned and *countPtr1 and *countPtr2 are set to the
+ * depths of the two windows in their respective top-level windows (1
+ * means the window is a top-level, 2 means its parent is a top-level,
+ * and so on). Otherwise, the return value is a pointer to the common
+ * ancestor and the counts are set to the distance of winPtr1 and winPtr2
+ * from this ancestor (1 means they're children, 2 means grand-children,
+ * etc.).
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static TkWindow *
+FindCommonAncestor(
+ TkWindow *winPtr1, /* First window. May be NULL. */
+ TkWindow *winPtr2, /* Second window. May be NULL. */
+ int *countPtr1, /* Store nesting level of winPtr1 within
+ * common ancestor here. */
+ int *countPtr2) /* Store nesting level of winPtr2 within
+ * common ancestor here. */
+{
+ register TkWindow *winPtr;
+ TkWindow *ancestorPtr;
+ int count1, count2, i;
+
+ /*
+ * Mark winPtr1 and all of its ancestors with a special flag bit.
+ */
+
+ if (winPtr1 != NULL) {
+ for (winPtr = winPtr1; winPtr != NULL; winPtr = winPtr->parentPtr) {
+ winPtr->flags |= TK_GRAB_FLAG;
+ if (winPtr->flags & TK_TOP_HIERARCHY) {
+ break;
+ }
+ }
+ }
+
+ /*
+ * Search upwards from winPtr2 until an ancestor of winPtr1 is found or a
+ * top-level window is reached.
+ */
+
+ winPtr = winPtr2;
+ count2 = 0;
+ ancestorPtr = NULL;
+ if (winPtr2 != NULL) {
+ for (; winPtr != NULL; count2++, winPtr = winPtr->parentPtr) {
+ if (winPtr->flags & TK_GRAB_FLAG) {
+ ancestorPtr = winPtr;
+ break;
+ }
+ if (winPtr->flags & TK_TOP_HIERARCHY) {
+ count2++;
+ break;
+ }
+ }
+ }
+
+ /*
+ * Search upwards from winPtr1 again, clearing the flag bits and
+ * remembering how many levels up we had to go.
+ */
+
+ if (winPtr1 == NULL) {
+ count1 = 0;
+ } else {
+ count1 = -1;
+ for (i = 0, winPtr = winPtr1; winPtr != NULL;
+ i++, winPtr = winPtr->parentPtr) {
+ winPtr->flags &= ~TK_GRAB_FLAG;
+ if (winPtr == ancestorPtr) {
+ count1 = i;
+ }
+ if (winPtr->flags & TK_TOP_HIERARCHY) {
+ if (count1 == -1) {
+ count1 = i+1;
+ }
+ break;
+ }
+ }
+ }
+
+ *countPtr1 = count1;
+ *countPtr2 = count2;
+ return ancestorPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkPositionInTree --
+ *
+ * Compute where the given window is relative to a particular subtree of
+ * the window hierarchy.
+ *
+ * Results:
+ * Returns TK_GRAB_IN_TREE if the window is contained in the subtree.
+ * Returns TK_GRAB_ANCESTOR if the window is an ancestor of the subtree,
+ * in the same toplevel. Otherwise it returns TK_GRAB_EXCLUDED.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkPositionInTree(
+ TkWindow *winPtr, /* Window to be checked. */
+ TkWindow *treePtr) /* Root of tree to compare against. */
+{
+ TkWindow *winPtr2;
+
+ for (winPtr2 = winPtr; winPtr2 != treePtr;
+ winPtr2 = winPtr2->parentPtr) {
+ if (winPtr2 == NULL) {
+ for (winPtr2 = treePtr; winPtr2 != NULL;
+ winPtr2 = winPtr2->parentPtr) {
+ if (winPtr2 == winPtr) {
+ return TK_GRAB_ANCESTOR;
+ }
+ if (winPtr2->flags & TK_TOP_HIERARCHY) {
+ break;
+ }
+ }
+ return TK_GRAB_EXCLUDED;
+ }
+ }
+ return TK_GRAB_IN_TREE;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkGrabState --
+ *
+ * Given a window, this function returns a value that indicates the grab
+ * state of the application relative to the window.
+ *
+ * Results:
+ * The return value is one of three things:
+ * TK_GRAB_NONE - no grab is in effect.
+ * TK_GRAB_IN_TREE - there is a grab in effect, and winPtr is in
+ * the grabbed subtree.
+ * TK_GRAB_ANCESTOR - there is a grab in effect; winPtr is an
+ * ancestor of the grabbed window, in the same
+ * toplevel.
+ * TK_GRAB_EXCLUDED - there is a grab in effect; winPtr is outside
+ * the tree of the grab and is not an ancestor of
+ * the grabbed window in the same toplevel.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkGrabState(
+ TkWindow *winPtr) /* Window for which grab information is
+ * needed. */
+{
+ TkWindow *grabWinPtr = winPtr->dispPtr->grabWinPtr;
+
+ if (grabWinPtr == NULL) {
+ return TK_GRAB_NONE;
+ }
+ if ((winPtr->mainPtr != grabWinPtr->mainPtr)
+ && !(winPtr->dispPtr->grabFlags & GRAB_GLOBAL)) {
+ return TK_GRAB_NONE;
+ }
+
+ return TkPositionInTree(winPtr, grabWinPtr);
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkGrid.c b/tk8.6/generic/tkGrid.c
new file mode 100644
index 0000000..be15c14
--- /dev/null
+++ b/tk8.6/generic/tkGrid.c
@@ -0,0 +1,3678 @@
+/*
+ * tkGrid.c --
+ *
+ * Grid based geometry manager.
+ *
+ * Copyright (c) 1996-1997 by Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkInt.h"
+
+/*
+ * Convenience Macros
+ */
+
+#ifdef MAX
+# undef MAX
+#endif
+#define MAX(x,y) ((x) > (y) ? (x) : (y))
+
+#define COLUMN (1) /* Working on column offsets. */
+#define ROW (2) /* Working on row offsets. */
+
+#define CHECK_ONLY (1) /* Check max slot constraint. */
+#define CHECK_SPACE (2) /* Alloc more space, don't change max. */
+
+/*
+ * Pre-allocate enough row and column slots for "typical" sized tables this
+ * value should be chosen so by the time the extra malloc's are required, the
+ * layout calculations overwehlm them. [A "slot" contains information for
+ * either a row or column, depending upon the context.]
+ */
+
+#define TYPICAL_SIZE 25 /* (Arbitrary guess) */
+#define PREALLOC 10 /* Extra slots to allocate. */
+
+/*
+ * Pre-allocate room for uniform groups during layout.
+ */
+
+#define UNIFORM_PREALLOC 10
+
+/*
+ * Data structures are allocated dynamically to support arbitrary sized
+ * tables. However, the space is proportional to the highest numbered slot
+ * with some non-default property. This limit is used to head off mistakes and
+ * denial of service attacks by limiting the amount of storage required.
+ */
+
+#define MAX_ELEMENT 10000
+
+/*
+ * Special characters to support relative layouts.
+ */
+
+#define REL_SKIP 'x' /* Skip this column. */
+#define REL_HORIZ '-' /* Extend previous widget horizontally. */
+#define REL_VERT '^' /* Extend widget from row above. */
+
+/*
+ * Default value for 'grid anchor'.
+ */
+
+#define GRID_DEFAULT_ANCHOR TK_ANCHOR_NW
+
+/*
+ * Structure to hold information for grid masters. A slot is either a row or
+ * column.
+ */
+
+typedef struct SlotInfo {
+ int minSize; /* The minimum size of this slot (in pixels).
+ * It is set via the rowconfigure or
+ * columnconfigure commands. */
+ int weight; /* The resize weight of this slot. (0) means
+ * this slot doesn't resize. Extra space in
+ * the layout is given distributed among slots
+ * inproportion to their weights. */
+ int pad; /* Extra padding, in pixels, required for this
+ * slot. This amount is "added" to the largest
+ * slave in the slot. */
+ Tk_Uid uniform; /* Value of -uniform option. It is used to
+ * group slots that should have the same
+ * size. */
+ int offset; /* This is a cached value used for
+ * introspection. It is the pixel offset of
+ * the right or bottom edge of this slot from
+ * the beginning of the layout. */
+ int temp; /* This is a temporary value used for
+ * calculating adjusted weights when shrinking
+ * the layout below its nominal size. */
+} SlotInfo;
+
+/*
+ * Structure to hold information during layout calculations. There is one of
+ * these for each slot, an array for each of the rows or columns.
+ */
+
+typedef struct GridLayout {
+ struct Gridder *binNextPtr; /* The next slave window in this bin. Each bin
+ * contains a list of all slaves whose spans
+ * are >1 and whose right edges fall in this
+ * slot. */
+ int minSize; /* Minimum size needed for this slot, in
+ * pixels. This is the space required to hold
+ * any slaves contained entirely in this slot,
+ * adjusted for any slot constrants, such as
+ * size or padding. */
+ int pad; /* Padding needed for this slot */
+ int weight; /* Slot weight, controls resizing. */
+ Tk_Uid uniform; /* Value of -uniform option. It is used to
+ * group slots that should have the same
+ * size. */
+ int minOffset; /* The minimum offset, in pixels, from the
+ * beginning of the layout to the bottom/right
+ * edge of the slot calculated from top/left
+ * to bottom/right. */
+ int maxOffset; /* The maximum offset, in pixels, from the
+ * beginning of the layout to the bottom/right
+ * edge of the slot calculated from
+ * bottom/right to top/left. */
+} GridLayout;
+
+/*
+ * Keep one of these for each geometry master.
+ */
+
+typedef struct {
+ SlotInfo *columnPtr; /* Pointer to array of column constraints. */
+ SlotInfo *rowPtr; /* Pointer to array of row constraints. */
+ int columnEnd; /* The last column occupied by any slave. */
+ int columnMax; /* The number of columns with constraints. */
+ int columnSpace; /* The number of slots currently allocated for
+ * column constraints. */
+ int rowEnd; /* The last row occupied by any slave. */
+ int rowMax; /* The number of rows with constraints. */
+ int rowSpace; /* The number of slots currently allocated for
+ * row constraints. */
+ int startX; /* Pixel offset of this layout within its
+ * master. */
+ int startY; /* Pixel offset of this layout within its
+ * master. */
+ Tk_Anchor anchor; /* Value of anchor option: specifies where a
+ * grid without weight should be placed. */
+} GridMaster;
+
+/*
+ * For each window that the grid cares about (either because the window is
+ * managed by the grid or because the window has slaves that are managed by
+ * the grid), there is a structure of the following type:
+ */
+
+typedef struct Gridder {
+ Tk_Window tkwin; /* Tk token for window. NULL means that the
+ * window has been deleted, but the gridder
+ * hasn't had a chance to clean up yet because
+ * the structure is still in use. */
+ struct Gridder *masterPtr; /* Master window within which this window is
+ * managed (NULL means this window isn't
+ * managed by the gridder). */
+ struct Gridder *nextPtr; /* Next window managed within same master.
+ * List order doesn't matter. */
+ struct Gridder *slavePtr; /* First in list of slaves managed inside this
+ * window (NULL means no grid slaves). */
+ GridMaster *masterDataPtr; /* Additional data for geometry master. */
+ Tcl_Obj *in; /* Store master name when removed. */
+ int column, row; /* Location in the grid (starting from
+ * zero). */
+ int numCols, numRows; /* Number of columns or rows this slave spans.
+ * Should be at least 1. */
+ int padX, padY; /* Total additional pixels to leave around the
+ * window. Some is of this space is on each
+ * side. This is space *outside* the window:
+ * we'll allocate extra space in frame but
+ * won't enlarge window). */
+ int padLeft, padTop; /* The part of padX or padY to use on the left
+ * or top of the widget, respectively. By
+ * default, this is half of padX or padY. */
+ int iPadX, iPadY; /* Total extra pixels to allocate inside the
+ * window (half this amount will appear on
+ * each side). */
+ int sticky; /* which sides of its cavity this window
+ * sticks to. See below for definitions */
+ int doubleBw; /* Twice the window's last known border width.
+ * If this changes, the window must be
+ * re-arranged within its master. */
+ int *abortPtr; /* If non-NULL, it means that there is a
+ * nested call to ArrangeGrid already working
+ * on this window. *abortPtr may be set to 1
+ * to abort that nested call. This happens,
+ * for example, if tkwin or any of its slaves
+ * is deleted. */
+ int flags; /* Miscellaneous flags; see below for
+ * definitions. */
+
+ /*
+ * These fields are used temporarily for layout calculations only.
+ */
+
+ struct Gridder *binNextPtr; /* Link to next span>1 slave in this bin. */
+ int size; /* Nominal size (width or height) in pixels of
+ * the slave. This includes the padding. */
+} Gridder;
+
+/*
+ * Flag values for "sticky"ness. The 16 combinations subsume the packer's
+ * notion of anchor and fill.
+ *
+ * STICK_NORTH This window sticks to the top of its cavity.
+ * STICK_EAST This window sticks to the right edge of its
+ * cavity.
+ * STICK_SOUTH This window sticks to the bottom of its cavity.
+ * STICK_WEST This window sticks to the left edge of its
+ * cavity.
+ */
+
+#define STICK_NORTH 1
+#define STICK_EAST 2
+#define STICK_SOUTH 4
+#define STICK_WEST 8
+
+
+/*
+ * Structure to gather information about uniform groups during layout.
+ */
+
+typedef struct UniformGroup {
+ Tk_Uid group;
+ int minSize;
+} UniformGroup;
+
+/*
+ * Flag values for Grid structures:
+ *
+ * REQUESTED_RELAYOUT 1 means a Tcl_DoWhenIdle request has already
+ * been made to re-arrange all the slaves of this
+ * window.
+ * DONT_PROPAGATE 1 means don't set this window's requested
+ * size. 0 means if this window is a master then
+ * Tk will set its requested size to fit the
+ * needs of its slaves.
+ * ALLOCED_MASTER 1 means that Grid has allocated itself as
+ * geometry master for this window.
+ */
+
+#define REQUESTED_RELAYOUT 1
+#define DONT_PROPAGATE 2
+#define ALLOCED_MASTER 4
+
+/*
+ * Prototypes for procedures used only in this file:
+ */
+
+static void AdjustForSticky(Gridder *slavePtr, int *xPtr,
+ int *yPtr, int *widthPtr, int *heightPtr);
+static int AdjustOffsets(int width, int elements,
+ SlotInfo *slotPtr);
+static void ArrangeGrid(ClientData clientData);
+static int CheckSlotData(Gridder *masterPtr, int slot,
+ int slotType, int checkOnly);
+static int ConfigureSlaves(Tcl_Interp *interp, Tk_Window tkwin,
+ int objc, Tcl_Obj *const objv[]);
+static void DestroyGrid(void *memPtr);
+static Gridder * GetGrid(Tk_Window tkwin);
+static int GridAnchorCommand(Tk_Window tkwin, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int GridBboxCommand(Tk_Window tkwin, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int GridForgetRemoveCommand(Tk_Window tkwin,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int GridInfoCommand(Tk_Window tkwin, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int GridLocationCommand(Tk_Window tkwin,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int GridPropagateCommand(Tk_Window tkwin,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int GridRowColumnConfigureCommand(Tk_Window tkwin,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int GridSizeCommand(Tk_Window tkwin, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int GridSlavesCommand(Tk_Window tkwin, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static void GridStructureProc(ClientData clientData,
+ XEvent *eventPtr);
+static void GridLostSlaveProc(ClientData clientData,
+ Tk_Window tkwin);
+static void GridReqProc(ClientData clientData, Tk_Window tkwin);
+static void InitMasterData(Gridder *masterPtr);
+static Tcl_Obj * NewPairObj(int, int);
+static Tcl_Obj * NewQuadObj(int, int, int, int);
+static int ResolveConstraints(Gridder *gridPtr, int rowOrColumn,
+ int maxOffset);
+static void SetGridSize(Gridder *gridPtr);
+static int SetSlaveColumn(Tcl_Interp *interp, Gridder *slavePtr,
+ int column, int numCols);
+static int SetSlaveRow(Tcl_Interp *interp, Gridder *slavePtr,
+ int row, int numRows);
+static Tcl_Obj * StickyToObj(int flags);
+static int StringToSticky(const char *string);
+static void Unlink(Gridder *gridPtr);
+
+static const Tk_GeomMgr gridMgrType = {
+ "grid", /* name */
+ GridReqProc, /* requestProc */
+ GridLostSlaveProc, /* lostSlaveProc */
+};
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GridCmd --
+ *
+ * This procedure is invoked to process the "grid" 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_GridObjCmd(
+ 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 = clientData;
+ static const char *const optionStrings[] = {
+ "anchor", "bbox", "columnconfigure", "configure",
+ "forget", "info", "location", "propagate", "remove",
+ "rowconfigure", "size", "slaves", NULL
+ };
+ enum options {
+ GRID_ANCHOR, GRID_BBOX, GRID_COLUMNCONFIGURE, GRID_CONFIGURE,
+ GRID_FORGET, GRID_INFO, GRID_LOCATION, GRID_PROPAGATE, GRID_REMOVE,
+ GRID_ROWCONFIGURE, GRID_SIZE, GRID_SLAVES
+ };
+ int index;
+
+ if (objc >= 2) {
+ const char *argv1 = Tcl_GetString(objv[1]);
+
+ if ((argv1[0] == '.') || (argv1[0] == REL_SKIP) ||
+ (argv1[0] == REL_VERT)) {
+ return ConfigureSlaves(interp, tkwin, objc-1, objv+1);
+ }
+ }
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings,
+ sizeof(char *), "option", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch ((enum options) index) {
+ case GRID_ANCHOR:
+ return GridAnchorCommand(tkwin, interp, objc, objv);
+ case GRID_BBOX:
+ return GridBboxCommand(tkwin, interp, objc, objv);
+ case GRID_CONFIGURE:
+ return ConfigureSlaves(interp, tkwin, objc-2, objv+2);
+ case GRID_FORGET:
+ case GRID_REMOVE:
+ return GridForgetRemoveCommand(tkwin, interp, objc, objv);
+ case GRID_INFO:
+ return GridInfoCommand(tkwin, interp, objc, objv);
+ case GRID_LOCATION:
+ return GridLocationCommand(tkwin, interp, objc, objv);
+ case GRID_PROPAGATE:
+ return GridPropagateCommand(tkwin, interp, objc, objv);
+ case GRID_SIZE:
+ return GridSizeCommand(tkwin, interp, objc, objv);
+ case GRID_SLAVES:
+ return GridSlavesCommand(tkwin, interp, objc, objv);
+
+ /*
+ * Sample argument combinations:
+ * grid columnconfigure <master> <index> -option
+ * grid columnconfigure <master> <index> -option value -option value
+ * grid rowconfigure <master> <index>
+ * grid rowconfigure <master> <index> -option
+ * grid rowconfigure <master> <index> -option value -option value.
+ */
+
+ case GRID_COLUMNCONFIGURE:
+ case GRID_ROWCONFIGURE:
+ return GridRowColumnConfigureCommand(tkwin, interp, objc, objv);
+ }
+
+ /* This should not happen */
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("internal error in grid", -1));
+ Tcl_SetErrorCode(interp, "TK", "API_ABUSE", NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GridAnchorCommand --
+ *
+ * Implementation of the [grid anchor] subcommand. See the user
+ * documentation for details on what it does.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * May recompute grid geometry.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GridAnchorCommand(
+ Tk_Window tkwin, /* Main window of the application. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Tk_Window master;
+ Gridder *masterPtr;
+ GridMaster *gridPtr;
+ Tk_Anchor old;
+
+ if (objc > 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?anchor?");
+ return TCL_ERROR;
+ }
+
+ if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ masterPtr = GetGrid(master);
+
+ if (objc == 3) {
+ gridPtr = masterPtr->masterDataPtr;
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ Tk_NameOfAnchor(gridPtr?gridPtr->anchor:GRID_DEFAULT_ANCHOR),
+ -1));
+ return TCL_OK;
+ }
+
+ InitMasterData(masterPtr);
+ gridPtr = masterPtr->masterDataPtr;
+ old = gridPtr->anchor;
+ if (Tk_GetAnchorFromObj(interp, objv[3], &gridPtr->anchor) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Only request a relayout if the anchor changes.
+ */
+
+ if (old != gridPtr->anchor) {
+ if (masterPtr->abortPtr != NULL) {
+ *masterPtr->abortPtr = 1;
+ }
+ if (!(masterPtr->flags & REQUESTED_RELAYOUT)) {
+ masterPtr->flags |= REQUESTED_RELAYOUT;
+ Tcl_DoWhenIdle(ArrangeGrid, masterPtr);
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GridBboxCommand --
+ *
+ * Implementation of the [grid bbox] subcommand.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * Places bounding box information in the interp's result field.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GridBboxCommand(
+ Tk_Window tkwin, /* Main window of the application. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Tk_Window master;
+ Gridder *masterPtr; /* master grid record */
+ GridMaster *gridPtr; /* pointer to grid data */
+ int row, column; /* origin for bounding box */
+ int row2, column2; /* end of bounding box */
+ int endX, endY; /* last column/row in the layout */
+ int x=0, y=0; /* starting pixels for this bounding box */
+ int width, height; /* size of the bounding box */
+
+ if (objc!=3 && objc != 5 && objc != 7) {
+ Tcl_WrongNumArgs(interp, 2, objv, "master ?column row ?column row??");
+ return TCL_ERROR;
+ }
+
+ if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ masterPtr = GetGrid(master);
+
+ if (objc >= 5) {
+ if (Tcl_GetIntFromObj(interp, objv[3], &column) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIntFromObj(interp, objv[4], &row) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ column2 = column;
+ row2 = row;
+ }
+
+ if (objc == 7) {
+ if (Tcl_GetIntFromObj(interp, objv[5], &column2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIntFromObj(interp, objv[6], &row2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+
+ gridPtr = masterPtr->masterDataPtr;
+ if (gridPtr == NULL) {
+ Tcl_SetObjResult(interp, NewQuadObj(0, 0, 0, 0));
+ return TCL_OK;
+ }
+
+ SetGridSize(masterPtr);
+ endX = MAX(gridPtr->columnEnd, gridPtr->columnMax);
+ endY = MAX(gridPtr->rowEnd, gridPtr->rowMax);
+
+ if ((endX == 0) || (endY == 0)) {
+ Tcl_SetObjResult(interp, NewQuadObj(0, 0, 0, 0));
+ return TCL_OK;
+ }
+ if (objc == 3) {
+ row = 0;
+ column = 0;
+ row2 = endY;
+ column2 = endX;
+ }
+
+ if (column > column2) {
+ int temp = column;
+
+ column = column2;
+ column2 = temp;
+ }
+ if (row > row2) {
+ int temp = row;
+
+ row = row2;
+ row2 = temp;
+ }
+
+ if (column > 0 && column < endX) {
+ x = gridPtr->columnPtr[column-1].offset;
+ } else if (column > 0) {
+ x = gridPtr->columnPtr[endX-1].offset;
+ }
+
+ if (row > 0 && row < endY) {
+ y = gridPtr->rowPtr[row-1].offset;
+ } else if (row > 0) {
+ y = gridPtr->rowPtr[endY-1].offset;
+ }
+
+ if (column2 < 0) {
+ width = 0;
+ } else if (column2 >= endX) {
+ width = gridPtr->columnPtr[endX-1].offset - x;
+ } else {
+ width = gridPtr->columnPtr[column2].offset - x;
+ }
+
+ if (row2 < 0) {
+ height = 0;
+ } else if (row2 >= endY) {
+ height = gridPtr->rowPtr[endY-1].offset - y;
+ } else {
+ height = gridPtr->rowPtr[row2].offset - y;
+ }
+
+ Tcl_SetObjResult(interp, NewQuadObj(
+ x + gridPtr->startX, y + gridPtr->startY, width, height));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GridForgetRemoveCommand --
+ *
+ * Implementation of the [grid forget]/[grid remove] subcommands. See the
+ * user documentation for details on what these do.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * Removes a window from a grid layout.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GridForgetRemoveCommand(
+ Tk_Window tkwin, /* Main window of the application. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Tk_Window slave;
+ Gridder *slavePtr;
+ int i;
+ const char *string = Tcl_GetString(objv[1]);
+ char c = string[0];
+
+ for (i = 2; i < objc; i++) {
+ if (TkGetWindowFromObj(interp, tkwin, objv[i], &slave) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ slavePtr = GetGrid(slave);
+ if (slavePtr->masterPtr != NULL) {
+ /*
+ * For "forget", reset all the settings to their defaults
+ */
+
+ if (c == 'f') {
+ slavePtr->column = -1;
+ slavePtr->row = -1;
+ slavePtr->numCols = 1;
+ slavePtr->numRows = 1;
+ slavePtr->padX = 0;
+ slavePtr->padY = 0;
+ slavePtr->padLeft = 0;
+ slavePtr->padTop = 0;
+ slavePtr->iPadX = 0;
+ slavePtr->iPadY = 0;
+ if (slavePtr->in != NULL) {
+ Tcl_DecrRefCount(slavePtr->in);
+ slavePtr->in = NULL;
+ }
+ slavePtr->doubleBw = 2*Tk_Changes(tkwin)->border_width;
+ if (slavePtr->flags & REQUESTED_RELAYOUT) {
+ Tcl_CancelIdleCall(ArrangeGrid, slavePtr);
+ }
+ slavePtr->flags = 0;
+ slavePtr->sticky = 0;
+ } else {
+ /*
+ * When removing, store name of master to be able to
+ * restore it later, even if the master is recreated.
+ */
+
+ if (slavePtr->in != NULL) {
+ Tcl_DecrRefCount(slavePtr->in);
+ slavePtr->in = NULL;
+ }
+ if (slavePtr->masterPtr != NULL) {
+ slavePtr->in = Tcl_NewStringObj(
+ Tk_PathName(slavePtr->masterPtr->tkwin), -1);
+ Tcl_IncrRefCount(slavePtr->in);
+ }
+ }
+ Tk_ManageGeometry(slave, NULL, NULL);
+ if (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin)) {
+ Tk_UnmaintainGeometry(slavePtr->tkwin,
+ slavePtr->masterPtr->tkwin);
+ }
+ Unlink(slavePtr);
+ Tk_UnmapWindow(slavePtr->tkwin);
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GridInfoCommand --
+ *
+ * Implementation of the [grid info] subcommand. See the user
+ * documentation for details on what it does.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * Puts gridding information in the interpreter's result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GridInfoCommand(
+ Tk_Window tkwin, /* Main window of the application. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ register Gridder *slavePtr;
+ Tk_Window slave;
+ Tcl_Obj *infoObj;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window");
+ return TCL_ERROR;
+ }
+ if (TkGetWindowFromObj(interp, tkwin, objv[2], &slave) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ slavePtr = GetGrid(slave);
+ if (slavePtr->masterPtr == NULL) {
+ Tcl_ResetResult(interp);
+ return TCL_OK;
+ }
+
+ infoObj = Tcl_NewObj();
+ Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-in", -1),
+ TkNewWindowObj(slavePtr->masterPtr->tkwin));
+ Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-column", -1),
+ Tcl_NewIntObj(slavePtr->column));
+ Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-row", -1),
+ Tcl_NewIntObj(slavePtr->row));
+ Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-columnspan", -1),
+ Tcl_NewIntObj(slavePtr->numCols));
+ Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-rowspan", -1),
+ Tcl_NewIntObj(slavePtr->numRows));
+ TkAppendPadAmount(infoObj, "-ipadx", slavePtr->iPadX/2, slavePtr->iPadX);
+ TkAppendPadAmount(infoObj, "-ipady", slavePtr->iPadY/2, slavePtr->iPadY);
+ TkAppendPadAmount(infoObj, "-padx", slavePtr->padLeft, slavePtr->padX);
+ TkAppendPadAmount(infoObj, "-pady", slavePtr->padTop, slavePtr->padY);
+ Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-sticky", -1),
+ StickyToObj(slavePtr->sticky));
+ Tcl_SetObjResult(interp, infoObj);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GridLocationCommand --
+ *
+ * Implementation of the [grid location] subcommand. See the user
+ * documentation for details on what it does.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * Puts location information in the interpreter's result field.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GridLocationCommand(
+ Tk_Window tkwin, /* Main window of the application. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Tk_Window master;
+ Gridder *masterPtr; /* Master grid record. */
+ GridMaster *gridPtr; /* Pointer to grid data. */
+ register SlotInfo *slotPtr;
+ int x, y; /* Offset in pixels, from edge of master. */
+ int i, j; /* Corresponding column and row indeces. */
+ int endX, endY; /* End of grid. */
+
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 2, objv, "master x y");
+ return TCL_ERROR;
+ }
+
+ if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (Tk_GetPixelsFromObj(interp, master, objv[3], &x) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tk_GetPixelsFromObj(interp, master, objv[4], &y) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ masterPtr = GetGrid(master);
+ if (masterPtr->masterDataPtr == NULL) {
+ Tcl_SetObjResult(interp, NewPairObj(-1, -1));
+ return TCL_OK;
+ }
+ gridPtr = masterPtr->masterDataPtr;
+
+ /*
+ * Update any pending requests. This is not always the steady state value,
+ * as more configure events could be in the pipeline, but its as close as
+ * its easy to get.
+ */
+
+ while (masterPtr->flags & REQUESTED_RELAYOUT) {
+ Tcl_CancelIdleCall(ArrangeGrid, masterPtr);
+ ArrangeGrid(masterPtr);
+ }
+ SetGridSize(masterPtr);
+ endX = MAX(gridPtr->columnEnd, gridPtr->columnMax);
+ endY = MAX(gridPtr->rowEnd, gridPtr->rowMax);
+
+ slotPtr = masterPtr->masterDataPtr->columnPtr;
+ if (x < masterPtr->masterDataPtr->startX) {
+ i = -1;
+ } else {
+ x -= masterPtr->masterDataPtr->startX;
+ for (i = 0; slotPtr[i].offset < x && i < endX; i++) {
+ /* null body */
+ }
+ }
+
+ slotPtr = masterPtr->masterDataPtr->rowPtr;
+ if (y < masterPtr->masterDataPtr->startY) {
+ j = -1;
+ } else {
+ y -= masterPtr->masterDataPtr->startY;
+ for (j = 0; slotPtr[j].offset < y && j < endY; j++) {
+ /* null body */
+ }
+ }
+
+ Tcl_SetObjResult(interp, NewPairObj(i, j));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GridPropagateCommand --
+ *
+ * Implementation of the [grid propagate] subcommand. See the user
+ * documentation for details on what it does.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * May alter geometry propagation for a widget.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GridPropagateCommand(
+ Tk_Window tkwin, /* Main window of the application. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Tk_Window master;
+ Gridder *masterPtr;
+ int propagate, old;
+
+ if (objc > 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?boolean?");
+ return TCL_ERROR;
+ }
+
+ if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ masterPtr = GetGrid(master);
+ if (objc == 3) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewBooleanObj(!(masterPtr->flags & DONT_PROPAGATE)));
+ return TCL_OK;
+ }
+ if (Tcl_GetBooleanFromObj(interp, objv[3], &propagate) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Only request a relayout if the propagation bit changes.
+ */
+
+ old = !(masterPtr->flags & DONT_PROPAGATE);
+ if (propagate != old) {
+ if (propagate) {
+ /*
+ * If we have slaves, we need to register as geometry master.
+ */
+
+ if (masterPtr->slavePtr != NULL) {
+ if (TkSetGeometryMaster(interp, master, "grid") != TCL_OK) {
+ return TCL_ERROR;
+ }
+ masterPtr->flags |= ALLOCED_MASTER;
+ }
+ masterPtr->flags &= ~DONT_PROPAGATE;
+ } else {
+ if (masterPtr->flags & ALLOCED_MASTER) {
+ TkFreeGeometryMaster(master, "grid");
+ masterPtr->flags &= ~ALLOCED_MASTER;
+ }
+ masterPtr->flags |= DONT_PROPAGATE;
+ }
+
+ /*
+ * Re-arrange the master to allow new geometry information to
+ * propagate upwards to the master's master.
+ */
+
+ if (masterPtr->abortPtr != NULL) {
+ *masterPtr->abortPtr = 1;
+ }
+ if (!(masterPtr->flags & REQUESTED_RELAYOUT)) {
+ masterPtr->flags |= REQUESTED_RELAYOUT;
+ Tcl_DoWhenIdle(ArrangeGrid, masterPtr);
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GridRowColumnConfigureCommand --
+ *
+ * Implementation of the [grid rowconfigure] and [grid columnconfigure]
+ * subcommands. See the user documentation for details on what these do.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * Depends on arguments; see user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GridRowColumnConfigureCommand(
+ Tk_Window tkwin, /* Main window of the application. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Tk_Window master, slave;
+ Gridder *masterPtr, *slavePtr;
+ SlotInfo *slotPtr = NULL;
+ int slot; /* the column or row number */
+ int slotType; /* COLUMN or ROW */
+ int size; /* the configuration value */
+ int lObjc; /* Number of items in index list */
+ Tcl_Obj **lObjv; /* array of indices */
+ int ok; /* temporary TCL result code */
+ int i, j, first, last;
+ const char *string;
+ static const char *const optionStrings[] = {
+ "-minsize", "-pad", "-uniform", "-weight", NULL
+ };
+ enum options {
+ ROWCOL_MINSIZE, ROWCOL_PAD, ROWCOL_UNIFORM, ROWCOL_WEIGHT
+ };
+ int index;
+ Tcl_Obj *listCopy;
+
+ if (((objc % 2 != 0) && (objc > 6)) || (objc < 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "master index ?-option value ...?");
+ return TCL_ERROR;
+ }
+
+ if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ listCopy = Tcl_DuplicateObj(objv[3]);
+ Tcl_IncrRefCount(listCopy);
+ if (Tcl_ListObjGetElements(interp, listCopy, &lObjc, &lObjv) != TCL_OK) {
+ Tcl_DecrRefCount(listCopy);
+ return TCL_ERROR;
+ }
+
+ string = Tcl_GetString(objv[1]);
+ slotType = (*string == 'c') ? COLUMN : ROW;
+ if (lObjc == 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf("no %s indices specified",
+ (slotType == COLUMN) ? "column" : "row"));
+ Tcl_SetErrorCode(interp, "TK", "GRID", "NO_INDEX", NULL);
+ Tcl_DecrRefCount(listCopy);
+ return TCL_ERROR;
+ }
+
+ masterPtr = GetGrid(master);
+ first = 0; /* lint */
+ last = 0; /* lint */
+
+ if ((objc == 4) || (objc == 5)) {
+ if (lObjc != 1) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "must specify a single element on retrieval", -1));
+ Tcl_SetErrorCode(interp, "TK", "GRID", "USAGE", NULL);
+ Tcl_DecrRefCount(listCopy);
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIntFromObj(interp, lObjv[0], &slot) != TCL_OK) {
+ Tcl_AppendResult(interp,
+ " (when retrieving options only integer indices are "
+ "allowed)", NULL);
+ Tcl_SetErrorCode(interp, "TK", "GRID", "INDEX_FORMAT", NULL);
+ Tcl_DecrRefCount(listCopy);
+ return TCL_ERROR;
+ }
+ ok = CheckSlotData(masterPtr, slot, slotType, /* checkOnly */ 1);
+ if (ok == TCL_OK) {
+ slotPtr = (slotType == COLUMN) ?
+ masterPtr->masterDataPtr->columnPtr :
+ masterPtr->masterDataPtr->rowPtr;
+ }
+
+ /*
+ * Return all of the options for this row or column. If the request is
+ * out of range, return all 0's.
+ */
+
+ if (objc == 4) {
+ int minsize = 0, pad = 0, weight = 0;
+ Tk_Uid uniform = NULL;
+ Tcl_Obj *res = Tcl_NewListObj(0, NULL);
+
+ if (ok == TCL_OK) {
+ minsize = slotPtr[slot].minSize;
+ pad = slotPtr[slot].pad;
+ weight = slotPtr[slot].weight;
+ uniform = slotPtr[slot].uniform;
+ }
+
+ Tcl_ListObjAppendElement(interp, res,
+ Tcl_NewStringObj("-minsize", -1));
+ Tcl_ListObjAppendElement(interp, res, Tcl_NewIntObj(minsize));
+ Tcl_ListObjAppendElement(interp, res,
+ Tcl_NewStringObj("-pad", -1));
+ Tcl_ListObjAppendElement(interp, res, Tcl_NewIntObj(pad));
+ Tcl_ListObjAppendElement(interp, res,
+ Tcl_NewStringObj("-uniform", -1));
+ Tcl_ListObjAppendElement(interp, res,
+ Tcl_NewStringObj(uniform == NULL ? "" : uniform, -1));
+ Tcl_ListObjAppendElement(interp, res,
+ Tcl_NewStringObj("-weight", -1));
+ Tcl_ListObjAppendElement(interp, res, Tcl_NewIntObj(weight));
+ Tcl_SetObjResult(interp, res);
+ Tcl_DecrRefCount(listCopy);
+ return TCL_OK;
+ }
+
+ /*
+ * If only one option is given, with no value, the current value is
+ * returned.
+ */
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[4], optionStrings,
+ sizeof(char *), "option", 0, &index) != TCL_OK) {
+ Tcl_DecrRefCount(listCopy);
+ return TCL_ERROR;
+ }
+ if (index == ROWCOL_MINSIZE) {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(
+ (ok == TCL_OK) ? slotPtr[slot].minSize : 0));
+ } else if (index == ROWCOL_WEIGHT) {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(
+ (ok == TCL_OK) ? slotPtr[slot].weight : 0));
+ } else if (index == ROWCOL_UNIFORM) {
+ Tk_Uid value = (ok == TCL_OK) ? slotPtr[slot].uniform : "";
+
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ (value == NULL) ? "" : value, -1));
+ } else if (index == ROWCOL_PAD) {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(
+ (ok == TCL_OK) ? slotPtr[slot].pad : 0));
+ }
+ Tcl_DecrRefCount(listCopy);
+ return TCL_OK;
+ }
+
+ for (j = 0; j < lObjc; j++) {
+ int allSlaves = 0;
+
+ if (Tcl_GetIntFromObj(NULL, lObjv[j], &slot) == TCL_OK) {
+ first = slot;
+ last = slot;
+ slavePtr = NULL;
+ } else if (strcmp(Tcl_GetString(lObjv[j]), "all") == 0) {
+ /*
+ * Make sure master is initialised.
+ */
+
+ InitMasterData(masterPtr);
+
+ slavePtr = masterPtr->slavePtr;
+ if (slavePtr == NULL) {
+ continue;
+ }
+ allSlaves = 1;
+ } else if (TkGetWindowFromObj(NULL, tkwin, lObjv[j], &slave)
+ == TCL_OK) {
+ /*
+ * Is it gridded in this master?
+ */
+
+ slavePtr = GetGrid(slave);
+ if (slavePtr->masterPtr != masterPtr) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "the window \"%s\" is not managed by \"%s\"",
+ Tcl_GetString(lObjv[j]), Tcl_GetString(objv[2])));
+ Tcl_SetErrorCode(interp, "TK", "GRID", "NOT_MASTER", NULL);
+ Tcl_DecrRefCount(listCopy);
+ return TCL_ERROR;
+ }
+ } else {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "illegal index \"%s\"", Tcl_GetString(lObjv[j])));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "GRID_INDEX", NULL);
+ Tcl_DecrRefCount(listCopy);
+ return TCL_ERROR;
+ }
+
+ /*
+ * The outer loop is only to handle "all".
+ */
+
+ do {
+ if (slavePtr != NULL) {
+ first = (slotType == COLUMN) ?
+ slavePtr->column : slavePtr->row;
+ last = first - 1 + ((slotType == COLUMN) ?
+ slavePtr->numCols : slavePtr->numRows);
+ }
+
+ for (slot = first; slot <= last; slot++) {
+ ok = CheckSlotData(masterPtr, slot, slotType, /*checkOnly*/ 0);
+ if (ok != TCL_OK) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "\"%s\" is out of range",
+ Tcl_GetString(lObjv[j])));
+ Tcl_SetErrorCode(interp, "TK", "GRID", "INDEX_RANGE",
+ NULL);
+ Tcl_DecrRefCount(listCopy);
+ return TCL_ERROR;
+ }
+ slotPtr = (slotType == COLUMN) ?
+ masterPtr->masterDataPtr->columnPtr :
+ masterPtr->masterDataPtr->rowPtr;
+
+ /*
+ * Loop through each option value pair, setting the values as
+ * required.
+ */
+
+ for (i = 4; i < objc; i += 2) {
+ if (Tcl_GetIndexFromObjStruct(interp, objv[i], optionStrings,
+ sizeof(char *), "option", 0, &index) != TCL_OK) {
+ Tcl_DecrRefCount(listCopy);
+ return TCL_ERROR;
+ }
+ if (index == ROWCOL_MINSIZE) {
+ if (Tk_GetPixelsFromObj(interp, master, objv[i+1],
+ &size) != TCL_OK) {
+ Tcl_DecrRefCount(listCopy);
+ return TCL_ERROR;
+ } else {
+ slotPtr[slot].minSize = size;
+ }
+ } else if (index == ROWCOL_WEIGHT) {
+ int wt;
+
+ if (Tcl_GetIntFromObj(interp,objv[i+1],&wt)!=TCL_OK) {
+ Tcl_DecrRefCount(listCopy);
+ return TCL_ERROR;
+ } else if (wt < 0) {
+ Tcl_DecrRefCount(listCopy);
+ goto negativeIndex;
+ } else {
+ slotPtr[slot].weight = wt;
+ }
+ } else if (index == ROWCOL_UNIFORM) {
+ slotPtr[slot].uniform =
+ Tk_GetUid(Tcl_GetString(objv[i+1]));
+ if (slotPtr[slot].uniform != NULL &&
+ slotPtr[slot].uniform[0] == 0) {
+ slotPtr[slot].uniform = NULL;
+ }
+ } else if (index == ROWCOL_PAD) {
+ if (Tk_GetPixelsFromObj(interp, master, objv[i+1],
+ &size) != TCL_OK) {
+ Tcl_DecrRefCount(listCopy);
+ return TCL_ERROR;
+ } else if (size < 0) {
+ Tcl_DecrRefCount(listCopy);
+ goto negativeIndex;
+ } else {
+ slotPtr[slot].pad = size;
+ }
+ }
+ }
+ }
+ if (slavePtr != NULL) {
+ slavePtr = slavePtr->nextPtr;
+ }
+ } while ((allSlaves == 1) && (slavePtr != NULL));
+ }
+ Tcl_DecrRefCount(listCopy);
+
+ /*
+ * We changed a property, re-arrange the table, and check for constraint
+ * shrinkage. A null slotPtr will occur for 'all' checks.
+ */
+
+ if (slotPtr != NULL) {
+ if (slotType == ROW) {
+ int last = masterPtr->masterDataPtr->rowMax - 1;
+
+ while ((last >= 0) && (slotPtr[last].weight == 0)
+ && (slotPtr[last].pad == 0) && (slotPtr[last].minSize == 0)
+ && (slotPtr[last].uniform == NULL)) {
+ last--;
+ }
+ masterPtr->masterDataPtr->rowMax = last+1;
+ } else {
+ int last = masterPtr->masterDataPtr->columnMax - 1;
+
+ while ((last >= 0) && (slotPtr[last].weight == 0)
+ && (slotPtr[last].pad == 0) && (slotPtr[last].minSize == 0)
+ && (slotPtr[last].uniform == NULL)) {
+ last--;
+ }
+ masterPtr->masterDataPtr->columnMax = last + 1;
+ }
+ }
+
+ if (masterPtr->abortPtr != NULL) {
+ *masterPtr->abortPtr = 1;
+ }
+ if (!(masterPtr->flags & REQUESTED_RELAYOUT)) {
+ masterPtr->flags |= REQUESTED_RELAYOUT;
+ Tcl_DoWhenIdle(ArrangeGrid, masterPtr);
+ }
+ return TCL_OK;
+
+ negativeIndex:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "invalid arg \"%s\": should be non-negative",
+ Tcl_GetString(objv[i])));
+ Tcl_SetErrorCode(interp, "TK", "GRID", "NEG_INDEX", NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GridSizeCommand --
+ *
+ * Implementation of the [grid size] subcommand. See the user
+ * documentation for details on what it does.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * Puts grid size information in the interpreter's result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GridSizeCommand(
+ Tk_Window tkwin, /* Main window of the application. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Tk_Window master;
+ Gridder *masterPtr;
+ GridMaster *gridPtr; /* pointer to grid data */
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window");
+ return TCL_ERROR;
+ }
+
+ if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ masterPtr = GetGrid(master);
+
+ if (masterPtr->masterDataPtr != NULL) {
+ SetGridSize(masterPtr);
+ gridPtr = masterPtr->masterDataPtr;
+ Tcl_SetObjResult(interp, NewPairObj(
+ MAX(gridPtr->columnEnd, gridPtr->columnMax),
+ MAX(gridPtr->rowEnd, gridPtr->rowMax)));
+ } else {
+ Tcl_SetObjResult(interp, NewPairObj(0, 0));
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GridSlavesCommand --
+ *
+ * Implementation of the [grid slaves] subcommand. See the user
+ * documentation for details on what it does.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * Places a list of slaves of the specified window in the interpreter's
+ * result field.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GridSlavesCommand(
+ Tk_Window tkwin, /* Main window of the application. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Tk_Window master;
+ Gridder *masterPtr; /* master grid record */
+ Gridder *slavePtr;
+ int i, value, index;
+ int row = -1, column = -1;
+ static const char *const optionStrings[] = {
+ "-column", "-row", NULL
+ };
+ enum options { SLAVES_COLUMN, SLAVES_ROW };
+ Tcl_Obj *res;
+
+ if ((objc < 3) || ((objc % 2) == 0)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?-option value ...?");
+ return TCL_ERROR;
+ }
+
+ for (i = 3; i < objc; i += 2) {
+ if (Tcl_GetIndexFromObjStruct(interp, objv[i], optionStrings,
+ sizeof(char *), "option", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIntFromObj(interp, objv[i+1], &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (value < 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "%d is an invalid value: should NOT be < 0", value));
+ Tcl_SetErrorCode(interp, "TK", "GRID", "NEG_INDEX", NULL);
+ return TCL_ERROR;
+ }
+ if (index == SLAVES_COLUMN) {
+ column = value;
+ } else {
+ row = value;
+ }
+ }
+
+ if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ masterPtr = GetGrid(master);
+
+ res = Tcl_NewListObj(0, NULL);
+ for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
+ slavePtr = slavePtr->nextPtr) {
+ if ((column >= 0) && (slavePtr->column > column
+ || slavePtr->column+slavePtr->numCols-1 < column)) {
+ continue;
+ }
+ if ((row >= 0) && (slavePtr->row > row ||
+ slavePtr->row+slavePtr->numRows-1 < row)) {
+ continue;
+ }
+ Tcl_ListObjAppendElement(interp,res, TkNewWindowObj(slavePtr->tkwin));
+ }
+ Tcl_SetObjResult(interp, res);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GridReqProc --
+ *
+ * This procedure is invoked by Tk_GeometryRequest for windows managed by
+ * the grid.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Arranges for tkwin, and all its managed siblings, to be re-arranged at
+ * the next idle point.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GridReqProc(
+ ClientData clientData, /* Grid's information about window that got
+ * new preferred geometry. */
+ Tk_Window tkwin) /* Other Tk-related information about the
+ * window. */
+{
+ register Gridder *gridPtr = clientData;
+
+ gridPtr = gridPtr->masterPtr;
+ if (gridPtr && !(gridPtr->flags & REQUESTED_RELAYOUT)) {
+ gridPtr->flags |= REQUESTED_RELAYOUT;
+ Tcl_DoWhenIdle(ArrangeGrid, gridPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GridLostSlaveProc --
+ *
+ * This procedure is invoked by Tk whenever some other geometry claims
+ * control over a slave that used to be managed by us.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Forgets all grid-related information about the slave.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GridLostSlaveProc(
+ ClientData clientData, /* Grid structure for slave window that was
+ * stolen away. */
+ Tk_Window tkwin) /* Tk's handle for the slave window. */
+{
+ register Gridder *slavePtr = clientData;
+
+ if (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin)) {
+ Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin);
+ }
+ Unlink(slavePtr);
+ Tk_UnmapWindow(slavePtr->tkwin);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AdjustOffsets --
+ *
+ * This procedure adjusts the size of the layout to fit in the space
+ * provided. If it needs more space, the extra is added according to the
+ * weights. If it needs less, the space is removed according to the
+ * weights, but at no time does the size drop below the minsize specified
+ * for that slot.
+ *
+ * Results:
+ * The size used by the layout.
+ *
+ * Side effects:
+ * The slot offsets are modified to shrink the layout.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+AdjustOffsets(
+ int size, /* The total layout size (in pixels). */
+ int slots, /* Number of slots. */
+ register SlotInfo *slotPtr) /* Pointer to slot array. */
+{
+ register int slot; /* Current slot. */
+ int diff; /* Extra pixels needed to add to the layout. */
+ int totalWeight; /* Sum of the weights for all the slots. */
+ int weight; /* Sum of the weights so far. */
+ int minSize; /* Minimum possible layout size. */
+ int newDiff; /* The most pixels that can be added on the
+ * current pass. */
+
+ diff = size - slotPtr[slots-1].offset;
+
+ /*
+ * The layout is already the correct size; all done.
+ */
+
+ if (diff == 0) {
+ return size;
+ }
+
+ /*
+ * If all the weights are zero, there is nothing more to do.
+ */
+
+ totalWeight = 0;
+ for (slot = 0; slot < slots; slot++) {
+ totalWeight += slotPtr[slot].weight;
+ }
+
+ if (totalWeight == 0) {
+ return slotPtr[slots-1].offset;
+ }
+
+ /*
+ * Add extra space according to the slot weights. This is done
+ * cumulatively to prevent round-off error accumulation.
+ */
+
+ if (diff > 0) {
+ weight = 0;
+ for (slot = 0; slot < slots; slot++) {
+ weight += slotPtr[slot].weight;
+ slotPtr[slot].offset += diff * weight / totalWeight;
+ }
+ return size;
+ }
+
+ /*
+ * The layout must shrink below its requested size. Compute the minimum
+ * possible size by looking at the slot minSizes. Store each slot's
+ * minimum size in temp.
+ */
+
+ minSize = 0;
+ for (slot = 0; slot < slots; slot++) {
+ if (slotPtr[slot].weight > 0) {
+ slotPtr[slot].temp = slotPtr[slot].minSize;
+ } else if (slot > 0) {
+ slotPtr[slot].temp = slotPtr[slot].offset - slotPtr[slot-1].offset;
+ } else {
+ slotPtr[slot].temp = slotPtr[slot].offset;
+ }
+ minSize += slotPtr[slot].temp;
+ }
+
+ /*
+ * If the requested size is less than the minimum required size, set the
+ * slot sizes to their minimum values.
+ */
+
+ if (size <= minSize) {
+ int offset = 0;
+
+ for (slot = 0; slot < slots; slot++) {
+ offset += slotPtr[slot].temp;
+ slotPtr[slot].offset = offset;
+ }
+ return minSize;
+ }
+
+ /*
+ * Remove space from slots according to their weights. The weights get
+ * renormalized anytime a slot shrinks to its minimum size.
+ */
+
+ while (diff < 0) {
+ /*
+ * Find the total weight for the shrinkable slots.
+ */
+
+ totalWeight = 0;
+ for (slot = 0; slot < slots; slot++) {
+ int current = (slot == 0) ? slotPtr[slot].offset :
+ slotPtr[slot].offset - slotPtr[slot-1].offset;
+
+ if (current > slotPtr[slot].minSize) {
+ totalWeight += slotPtr[slot].weight;
+ slotPtr[slot].temp = slotPtr[slot].weight;
+ } else {
+ slotPtr[slot].temp = 0;
+ }
+ }
+ if (totalWeight == 0) {
+ break;
+ }
+
+ /*
+ * Find the maximum amount of space we can distribute this pass.
+ */
+
+ newDiff = diff;
+ for (slot = 0; slot < slots; slot++) {
+ int current; /* Current size of this slot. */
+ int maxDiff; /* Maximum diff that would cause this slot to
+ * equal its minsize. */
+
+ if (slotPtr[slot].temp == 0) {
+ continue;
+ }
+ current = (slot == 0) ? slotPtr[slot].offset :
+ slotPtr[slot].offset - slotPtr[slot-1].offset;
+ maxDiff = totalWeight * (slotPtr[slot].minSize - current)
+ / slotPtr[slot].temp;
+ if (maxDiff > newDiff) {
+ newDiff = maxDiff;
+ }
+ }
+
+ /*
+ * Now distribute the space.
+ */
+
+ weight = 0;
+ for (slot = 0; slot < slots; slot++) {
+ weight += slotPtr[slot].temp;
+ slotPtr[slot].offset += newDiff * weight / totalWeight;
+ }
+ diff -= newDiff;
+ }
+ return size;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AdjustForSticky --
+ *
+ * This procedure adjusts the size of a slave in its cavity based on its
+ * "sticky" flags.
+ *
+ * Results:
+ * The input x, y, width, and height are changed to represent the desired
+ * coordinates of the slave.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+AdjustForSticky(
+ Gridder *slavePtr, /* Slave window to arrange in its cavity. */
+ int *xPtr, /* Pixel location of the left edge of the cavity. */
+ int *yPtr, /* Pixel location of the top edge of the cavity. */
+ int *widthPtr, /* Width of the cavity (in pixels). */
+ int *heightPtr) /* Height of the cavity (in pixels). */
+{
+ int diffx = 0; /* Cavity width - slave width. */
+ int diffy = 0; /* Cavity hight - slave height. */
+ int sticky = slavePtr->sticky;
+
+ *xPtr += slavePtr->padLeft;
+ *widthPtr -= slavePtr->padX;
+ *yPtr += slavePtr->padTop;
+ *heightPtr -= slavePtr->padY;
+
+ if (*widthPtr > (Tk_ReqWidth(slavePtr->tkwin) + slavePtr->iPadX)) {
+ diffx = *widthPtr - (Tk_ReqWidth(slavePtr->tkwin) + slavePtr->iPadX);
+ *widthPtr = Tk_ReqWidth(slavePtr->tkwin) + slavePtr->iPadX;
+ }
+
+ if (*heightPtr > (Tk_ReqHeight(slavePtr->tkwin) + slavePtr->iPadY)) {
+ diffy = *heightPtr - (Tk_ReqHeight(slavePtr->tkwin) + slavePtr->iPadY);
+ *heightPtr = Tk_ReqHeight(slavePtr->tkwin) + slavePtr->iPadY;
+ }
+
+ if (sticky&STICK_EAST && sticky&STICK_WEST) {
+ *widthPtr += diffx;
+ }
+ if (sticky&STICK_NORTH && sticky&STICK_SOUTH) {
+ *heightPtr += diffy;
+ }
+ if (!(sticky&STICK_WEST)) {
+ *xPtr += (sticky&STICK_EAST) ? diffx : diffx/2;
+ }
+ if (!(sticky&STICK_NORTH)) {
+ *yPtr += (sticky&STICK_SOUTH) ? diffy : diffy/2;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ArrangeGrid --
+ *
+ * This procedure is invoked (using the Tcl_DoWhenIdle mechanism) to
+ * re-layout a set of windows managed by the grid. It is invoked at idle
+ * time so that a series of grid requests can be merged into a single
+ * layout operation.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The slaves of masterPtr may get resized or moved.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ArrangeGrid(
+ ClientData clientData) /* Structure describing master whose slaves
+ * are to be re-layed out. */
+{
+ register Gridder *masterPtr = clientData;
+ register Gridder *slavePtr;
+ GridMaster *slotPtr = masterPtr->masterDataPtr;
+ int abort;
+ int width, height; /* Requested size of layout, in pixels. */
+ int realWidth, realHeight; /* Actual size layout should take-up. */
+ int usedX, usedY;
+
+ masterPtr->flags &= ~REQUESTED_RELAYOUT;
+
+ /*
+ * If the master has no slaves anymore, then don't do anything at all:
+ * just leave the master's size as-is. Otherwise there is no way to
+ * "relinquish" control over the master so another geometry manager can
+ * take over.
+ */
+
+ if (masterPtr->slavePtr == NULL) {
+ return;
+ }
+
+ if (masterPtr->masterDataPtr == NULL) {
+ return;
+ }
+
+ /*
+ * Abort any nested call to ArrangeGrid for this window, since we'll do
+ * everything necessary here, and set up so this call can be aborted if
+ * necessary.
+ */
+
+ if (masterPtr->abortPtr != NULL) {
+ *masterPtr->abortPtr = 1;
+ }
+ masterPtr->abortPtr = &abort;
+ abort = 0;
+ Tcl_Preserve(masterPtr);
+
+ /*
+ * Call the constraint engine to fill in the row and column offsets.
+ */
+
+ SetGridSize(masterPtr);
+ width = ResolveConstraints(masterPtr, COLUMN, 0);
+ height = ResolveConstraints(masterPtr, ROW, 0);
+ width += Tk_InternalBorderLeft(masterPtr->tkwin) +
+ Tk_InternalBorderRight(masterPtr->tkwin);
+ height += Tk_InternalBorderTop(masterPtr->tkwin) +
+ Tk_InternalBorderBottom(masterPtr->tkwin);
+
+ if (width < Tk_MinReqWidth(masterPtr->tkwin)) {
+ width = Tk_MinReqWidth(masterPtr->tkwin);
+ }
+ if (height < Tk_MinReqHeight(masterPtr->tkwin)) {
+ height = Tk_MinReqHeight(masterPtr->tkwin);
+ }
+
+ if (((width != Tk_ReqWidth(masterPtr->tkwin))
+ || (height != Tk_ReqHeight(masterPtr->tkwin)))
+ && !(masterPtr->flags & DONT_PROPAGATE)) {
+ Tk_GeometryRequest(masterPtr->tkwin, width, height);
+ if (width>1 && height>1) {
+ masterPtr->flags |= REQUESTED_RELAYOUT;
+ Tcl_DoWhenIdle(ArrangeGrid, masterPtr);
+ }
+ masterPtr->abortPtr = NULL;
+ Tcl_Release(masterPtr);
+ return;
+ }
+
+ /*
+ * If the currently requested layout size doesn't match the master's
+ * window size, then adjust the slot offsets according to the weights. If
+ * all of the weights are zero, place the layout according to the anchor
+ * value.
+ */
+
+ realWidth = Tk_Width(masterPtr->tkwin) -
+ Tk_InternalBorderLeft(masterPtr->tkwin) -
+ Tk_InternalBorderRight(masterPtr->tkwin);
+ realHeight = Tk_Height(masterPtr->tkwin) -
+ Tk_InternalBorderTop(masterPtr->tkwin) -
+ Tk_InternalBorderBottom(masterPtr->tkwin);
+ usedX = AdjustOffsets(realWidth,
+ MAX(slotPtr->columnEnd, slotPtr->columnMax), slotPtr->columnPtr);
+ usedY = AdjustOffsets(realHeight, MAX(slotPtr->rowEnd, slotPtr->rowMax),
+ slotPtr->rowPtr);
+ TkComputeAnchor(masterPtr->masterDataPtr->anchor, masterPtr->tkwin,
+ 0, 0, usedX, usedY, &slotPtr->startX, &slotPtr->startY);
+
+ /*
+ * Now adjust the actual size of the slave to its cavity by computing the
+ * cavity size, and adjusting the widget according to its stickyness.
+ */
+
+ for (slavePtr = masterPtr->slavePtr; slavePtr != NULL && !abort;
+ slavePtr = slavePtr->nextPtr) {
+ int x, y; /* Top left coordinate */
+ int width, height; /* Slot or slave size */
+ int col = slavePtr->column;
+ int row = slavePtr->row;
+
+ x = (col>0) ? slotPtr->columnPtr[col-1].offset : 0;
+ y = (row>0) ? slotPtr->rowPtr[row-1].offset : 0;
+
+ width = slotPtr->columnPtr[slavePtr->numCols+col-1].offset - x;
+ height = slotPtr->rowPtr[slavePtr->numRows+row-1].offset - y;
+
+ x += slotPtr->startX;
+ y += slotPtr->startY;
+
+ AdjustForSticky(slavePtr, &x, &y, &width, &height);
+
+ /*
+ * Now put the window in the proper spot. (This was taken directly
+ * from tkPack.c.) If the slave is a child of the master, then do this
+ * here. Otherwise let Tk_MaintainGeometry do the work.
+ */
+
+ if (masterPtr->tkwin == Tk_Parent(slavePtr->tkwin)) {
+ if ((width <= 0) || (height <= 0)) {
+ Tk_UnmapWindow(slavePtr->tkwin);
+ } else {
+ if ((x != Tk_X(slavePtr->tkwin))
+ || (y != Tk_Y(slavePtr->tkwin))
+ || (width != Tk_Width(slavePtr->tkwin))
+ || (height != Tk_Height(slavePtr->tkwin))) {
+ Tk_MoveResizeWindow(slavePtr->tkwin, x, y, width, height);
+ }
+ if (abort) {
+ break;
+ }
+
+ /*
+ * Don't map the slave if the master isn't mapped: wait until
+ * the master gets mapped later.
+ */
+
+ if (Tk_IsMapped(masterPtr->tkwin)) {
+ Tk_MapWindow(slavePtr->tkwin);
+ }
+ }
+ } else if ((width <= 0) || (height <= 0)) {
+ Tk_UnmaintainGeometry(slavePtr->tkwin, masterPtr->tkwin);
+ Tk_UnmapWindow(slavePtr->tkwin);
+ } else {
+ Tk_MaintainGeometry(slavePtr->tkwin, masterPtr->tkwin, x, y,
+ width, height);
+ }
+ }
+
+ masterPtr->abortPtr = NULL;
+ Tcl_Release(masterPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ResolveConstraints --
+ *
+ * Resolve all of the column and row boundaries. Most of the calculations
+ * are identical for rows and columns, so this procedure is called twice,
+ * once for rows, and again for columns.
+ *
+ * Results:
+ * The offset (in pixels) from the left/top edge of this layout is
+ * returned.
+ *
+ * Side effects:
+ * The slot offsets are copied into the SlotInfo structure for the
+ * geometry master.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ResolveConstraints(
+ Gridder *masterPtr, /* The geometry master for this grid. */
+ int slotType, /* Either ROW or COLUMN. */
+ int maxOffset) /* The actual maximum size of this layout in
+ * pixels, or 0 (not currently used). */
+{
+ register SlotInfo *slotPtr; /* Pointer to row/col constraints. */
+ register Gridder *slavePtr; /* List of slave windows in this grid. */
+ int constraintCount; /* Count of rows or columns that have
+ * constraints. */
+ int slotCount; /* Last occupied row or column. */
+ int gridCount; /* The larger of slotCount and
+ * constraintCount. */
+ GridLayout *layoutPtr; /* Temporary layout structure. */
+ int requiredSize; /* The natural size of the grid (pixels).
+ * This is the minimum size needed to
+ * accommodate all of the slaves at their
+ * requested sizes. */
+ int offset; /* The pixel offset of the right edge of the
+ * current slot from the beginning of the
+ * layout. */
+ int slot; /* The current slot. */
+ int start; /* The first slot of a contiguous set whose
+ * constraints are not yet fully resolved. */
+ int end; /* The Last slot of a contiguous set whose
+ * constraints are not yet fully resolved. */
+ UniformGroup uniformPre[UNIFORM_PREALLOC];
+ /* Pre-allocated space for uniform groups. */
+ UniformGroup *uniformGroupPtr;
+ /* Uniform groups data. */
+ int uniformGroups; /* Number of currently used uniform groups. */
+ int uniformGroupsAlloced; /* Size of allocated space for uniform
+ * groups. */
+ int weight, minSize;
+ int prevGrow, accWeight, grow;
+
+ /*
+ * For typical sized tables, we'll use stack space for the layout data to
+ * avoid the overhead of a malloc and free for every layout.
+ */
+
+ GridLayout layoutData[TYPICAL_SIZE + 1];
+
+ if (slotType == COLUMN) {
+ constraintCount = masterPtr->masterDataPtr->columnMax;
+ slotCount = masterPtr->masterDataPtr->columnEnd;
+ slotPtr = masterPtr->masterDataPtr->columnPtr;
+ } else {
+ constraintCount = masterPtr->masterDataPtr->rowMax;
+ slotCount = masterPtr->masterDataPtr->rowEnd;
+ slotPtr = masterPtr->masterDataPtr->rowPtr;
+ }
+
+ /*
+ * Make sure there is enough memory for the layout.
+ */
+
+ gridCount = MAX(constraintCount, slotCount);
+ if (gridCount >= TYPICAL_SIZE) {
+ layoutPtr = ckalloc(sizeof(GridLayout) * (1+gridCount));
+ } else {
+ layoutPtr = layoutData;
+ }
+
+ /*
+ * Allocate an extra layout slot to represent the left/top edge of the 0th
+ * slot to make it easier to calculate slot widths from offsets without
+ * special case code.
+ *
+ * Initialize the "dummy" slot to the left/top of the table. This slot
+ * avoids special casing the first slot.
+ */
+
+ layoutPtr->minOffset = 0;
+ layoutPtr->maxOffset = 0;
+ layoutPtr++;
+
+ /*
+ * Step 1.
+ * Copy the slot constraints into the layout structure, and initialize the
+ * rest of the fields.
+ */
+
+ for (slot=0; slot < constraintCount; slot++) {
+ layoutPtr[slot].minSize = slotPtr[slot].minSize;
+ layoutPtr[slot].weight = slotPtr[slot].weight;
+ layoutPtr[slot].uniform = slotPtr[slot].uniform;
+ layoutPtr[slot].pad = slotPtr[slot].pad;
+ layoutPtr[slot].binNextPtr = NULL;
+ }
+ for (; slot<gridCount; slot++) {
+ layoutPtr[slot].minSize = 0;
+ layoutPtr[slot].weight = 0;
+ layoutPtr[slot].uniform = NULL;
+ layoutPtr[slot].pad = 0;
+ layoutPtr[slot].binNextPtr = NULL;
+ }
+
+ /*
+ * Step 2.
+ * Slaves with a span of 1 are used to determine the minimum size of each
+ * slot. Slaves whose span is two or more slots don't contribute to the
+ * minimum size of each slot directly, but can cause slots to grow if
+ * their size exceeds the the sizes of the slots they span.
+ *
+ * Bin all slaves whose spans are > 1 by their right edges. This allows
+ * the computation on minimum and maximum possible layout sizes at each
+ * slot boundary, without the need to re-sort the slaves.
+ */
+
+ switch (slotType) {
+ case COLUMN:
+ for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
+ slavePtr = slavePtr->nextPtr) {
+ int rightEdge = slavePtr->column + slavePtr->numCols - 1;
+
+ slavePtr->size = Tk_ReqWidth(slavePtr->tkwin) + slavePtr->padX
+ + slavePtr->iPadX + slavePtr->doubleBw;
+ if (slavePtr->numCols > 1) {
+ slavePtr->binNextPtr = layoutPtr[rightEdge].binNextPtr;
+ layoutPtr[rightEdge].binNextPtr = slavePtr;
+ } else if (rightEdge >= 0) {
+ int size = slavePtr->size + layoutPtr[rightEdge].pad;
+
+ if (size > layoutPtr[rightEdge].minSize) {
+ layoutPtr[rightEdge].minSize = size;
+ }
+ }
+ }
+ break;
+ case ROW:
+ for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
+ slavePtr = slavePtr->nextPtr) {
+ int rightEdge = slavePtr->row + slavePtr->numRows - 1;
+
+ slavePtr->size = Tk_ReqHeight(slavePtr->tkwin) + slavePtr->padY
+ + slavePtr->iPadY + slavePtr->doubleBw;
+ if (slavePtr->numRows > 1) {
+ slavePtr->binNextPtr = layoutPtr[rightEdge].binNextPtr;
+ layoutPtr[rightEdge].binNextPtr = slavePtr;
+ } else if (rightEdge >= 0) {
+ int size = slavePtr->size + layoutPtr[rightEdge].pad;
+
+ if (size > layoutPtr[rightEdge].minSize) {
+ layoutPtr[rightEdge].minSize = size;
+ }
+ }
+ }
+ break;
+ }
+
+ /*
+ * Step 2b.
+ * Consider demands on uniform sizes.
+ */
+
+ uniformGroupPtr = uniformPre;
+ uniformGroupsAlloced = UNIFORM_PREALLOC;
+ uniformGroups = 0;
+
+ for (slot = 0; slot < gridCount; slot++) {
+ if (layoutPtr[slot].uniform != NULL) {
+ for (start = 0; start < uniformGroups; start++) {
+ if (uniformGroupPtr[start].group == layoutPtr[slot].uniform) {
+ break;
+ }
+ }
+ if (start >= uniformGroups) {
+ /*
+ * Have not seen that group before, set up data for it.
+ */
+
+ if (uniformGroups >= uniformGroupsAlloced) {
+ /*
+ * We need to allocate more space.
+ */
+
+ size_t oldSize = uniformGroupsAlloced
+ * sizeof(UniformGroup);
+ size_t newSize = (uniformGroupsAlloced + UNIFORM_PREALLOC)
+ * sizeof(UniformGroup);
+ UniformGroup *newUG = ckalloc(newSize);
+ UniformGroup *oldUG = uniformGroupPtr;
+
+ memcpy(newUG, oldUG, oldSize);
+ if (oldUG != uniformPre) {
+ ckfree(oldUG);
+ }
+ uniformGroupPtr = newUG;
+ uniformGroupsAlloced += UNIFORM_PREALLOC;
+ }
+ uniformGroups++;
+ uniformGroupPtr[start].group = layoutPtr[slot].uniform;
+ uniformGroupPtr[start].minSize = 0;
+ }
+ weight = layoutPtr[slot].weight;
+ weight = weight > 0 ? weight : 1;
+ minSize = (layoutPtr[slot].minSize + weight - 1) / weight;
+ if (minSize > uniformGroupPtr[start].minSize) {
+ uniformGroupPtr[start].minSize = minSize;
+ }
+ }
+ }
+
+ /*
+ * Data has been gathered about uniform groups. Now relayout accordingly.
+ */
+
+ if (uniformGroups > 0) {
+ for (slot = 0; slot < gridCount; slot++) {
+ if (layoutPtr[slot].uniform != NULL) {
+ for (start = 0; start < uniformGroups; start++) {
+ if (uniformGroupPtr[start].group ==
+ layoutPtr[slot].uniform) {
+ weight = layoutPtr[slot].weight;
+ weight = weight > 0 ? weight : 1;
+ layoutPtr[slot].minSize =
+ uniformGroupPtr[start].minSize * weight;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (uniformGroupPtr != uniformPre) {
+ ckfree(uniformGroupPtr);
+ }
+
+ /*
+ * Step 3.
+ * Determine the minimum slot offsets going from left to right that would
+ * fit all of the slaves. This determines the minimum
+ */
+
+ for (offset=0,slot=0; slot < gridCount; slot++) {
+ layoutPtr[slot].minOffset = layoutPtr[slot].minSize + offset;
+ for (slavePtr = layoutPtr[slot].binNextPtr; slavePtr != NULL;
+ slavePtr = slavePtr->binNextPtr) {
+ int span = (slotType == COLUMN) ?
+ slavePtr->numCols : slavePtr->numRows;
+ int required = slavePtr->size + layoutPtr[slot - span].minOffset;
+
+ if (required > layoutPtr[slot].minOffset) {
+ layoutPtr[slot].minOffset = required;
+ }
+ }
+ offset = layoutPtr[slot].minOffset;
+ }
+
+ /*
+ * At this point, we know the minimum required size of the entire layout.
+ * It might be prudent to stop here if our "master" will resize itself to
+ * this size.
+ */
+
+ requiredSize = offset;
+ if (maxOffset > offset) {
+ offset=maxOffset;
+ }
+
+ /*
+ * Step 4.
+ * Determine the minimum slot offsets going from right to left, bounding
+ * the pixel range of each slot boundary. Pre-fill all of the right
+ * offsets with the actual size of the table; they will be reduced as
+ * required.
+ */
+
+ for (slot=0; slot < gridCount; slot++) {
+ layoutPtr[slot].maxOffset = offset;
+ }
+ for (slot=gridCount-1; slot > 0;) {
+ for (slavePtr = layoutPtr[slot].binNextPtr; slavePtr != NULL;
+ slavePtr = slavePtr->binNextPtr) {
+ int span = (slotType == COLUMN) ?
+ slavePtr->numCols : slavePtr->numRows;
+ int require = offset - slavePtr->size;
+ int startSlot = slot - span;
+
+ if (startSlot >=0 && require < layoutPtr[startSlot].maxOffset) {
+ layoutPtr[startSlot].maxOffset = require;
+ }
+ }
+ offset -= layoutPtr[slot].minSize;
+ slot--;
+ if (layoutPtr[slot].maxOffset < offset) {
+ offset = layoutPtr[slot].maxOffset;
+ } else {
+ layoutPtr[slot].maxOffset = offset;
+ }
+ }
+
+ /*
+ * Step 5.
+ * At this point, each slot boundary has a range of values that will
+ * satisfy the overall layout size. Make repeated passes over the layout
+ * structure looking for spans of slot boundaries where the minOffsets are
+ * less than the maxOffsets, and adjust the offsets according to the slot
+ * weights. At each pass, at least one slot boundary will have its range
+ * of possible values fixed at a single value.
+ */
+
+ for (start = 0; start < gridCount;) {
+ int totalWeight = 0; /* Sum of the weights for all of the slots in
+ * this span. */
+ int need = 0; /* The minimum space needed to layout this
+ * span. */
+ int have; /* The actual amount of space that will be
+ * taken up by this span. */
+ int weight; /* Cumulative weights of the columns in this
+ * span. */
+ int noWeights = 0; /* True if the span has no weights. */
+
+ /*
+ * Find a span by identifying ranges of slots whose edges are already
+ * constrained at fixed offsets, but whose internal slot boundaries
+ * have a range of possible positions.
+ */
+
+ if (layoutPtr[start].minOffset == layoutPtr[start].maxOffset) {
+ start++;
+ continue;
+ }
+
+ for (end = start + 1; end < gridCount; end++) {
+ if (layoutPtr[end].minOffset == layoutPtr[end].maxOffset) {
+ break;
+ }
+ }
+
+ /*
+ * We found a span. Compute the total weight, minumum space required,
+ * for this span, and the actual amount of space the span should use.
+ */
+
+ for (slot = start; slot <= end; slot++) {
+ totalWeight += layoutPtr[slot].weight;
+ need += layoutPtr[slot].minSize;
+ }
+ have = layoutPtr[end].maxOffset - layoutPtr[start-1].minOffset;
+
+ /*
+ * If all the weights in the span are zero, then distribute the extra
+ * space evenly.
+ */
+
+ if (totalWeight == 0) {
+ noWeights++;
+ totalWeight = end - start + 1;
+ }
+
+ /*
+ * It might not be possible to give the span all of the space
+ * available on this pass without violating the size constraints of
+ * one or more of the internal slot boundaries. Try to determine the
+ * maximum amount of space that when added to the entire span, would
+ * cause a slot boundary to have its possible range reduced to one
+ * value, and reduce the amount of extra space allocated on this pass
+ * accordingly.
+ *
+ * The calculation is done cumulatively to avoid accumulating roundoff
+ * errors.
+ */
+
+ do {
+ int prevMinOffset = layoutPtr[start - 1].minOffset;
+
+ prevGrow = 0;
+ accWeight = 0;
+ for (slot = start; slot <= end; slot++) {
+ weight = noWeights ? 1 : layoutPtr[slot].weight;
+ accWeight += weight;
+ grow = (have - need) * accWeight / totalWeight - prevGrow;
+ prevGrow += grow;
+
+ if ((weight > 0) &&
+ ((prevMinOffset + layoutPtr[slot].minSize + grow)
+ > layoutPtr[slot].maxOffset)) {
+ int newHave;
+
+ /*
+ * There is not enough room to grow that much. Calculate
+ * how much this slot can grow and how much "have" that
+ * corresponds to.
+ */
+
+ grow = layoutPtr[slot].maxOffset -
+ layoutPtr[slot].minSize - prevMinOffset;
+ newHave = grow * totalWeight / weight;
+ if (newHave > totalWeight) {
+ /*
+ * By distributing multiples of totalWeight we
+ * minimize rounding errors since they will only
+ * happen in the last loop(s).
+ */
+
+ newHave = newHave / totalWeight * totalWeight;
+ }
+ if (newHave <= 0) {
+ /*
+ * We can end up with a "have" of 0 here if the
+ * previous slots have taken all the space. In that
+ * case we cannot guess an appropriate "have" so we
+ * just try some lower "have" that is >= 1, to make
+ * sure this terminates.
+ */
+
+ newHave = (have - need) - 1;
+ if (newHave > (3 * totalWeight)) {
+ /*
+ * Go down 25% for large values.
+ */
+ newHave = newHave * 3 / 4;
+ }
+
+ if (newHave > totalWeight) {
+ /*
+ * Round down to a multiple of totalWeight.
+ */
+ newHave = newHave / totalWeight * totalWeight;
+ }
+
+ if (newHave <= 0) {
+ newHave = 1;
+ }
+ }
+ have = newHave + need;
+
+ /*
+ * Restart loop to check if the new "have" will fit.
+ */
+
+ break;
+ }
+ prevMinOffset += layoutPtr[slot].minSize + grow;
+ if (prevMinOffset < layoutPtr[slot].minOffset) {
+ prevMinOffset = layoutPtr[slot].minOffset;
+ }
+ }
+
+ /*
+ * Quit the outer loop if the inner loop ran all the way.
+ */
+ } while (slot <= end);
+
+ /*
+ * Now distribute the extra space among the slots by adjusting the
+ * minSizes and minOffsets.
+ */
+
+ prevGrow = 0;
+ accWeight = 0;
+ for (slot = start; slot <= end; slot++) {
+ accWeight += noWeights ? 1 : layoutPtr[slot].weight;
+ grow = (have - need) * accWeight / totalWeight - prevGrow;
+ prevGrow += grow;
+ layoutPtr[slot].minSize += grow;
+ if ((layoutPtr[slot-1].minOffset + layoutPtr[slot].minSize)
+ > layoutPtr[slot].minOffset) {
+ layoutPtr[slot].minOffset = layoutPtr[slot-1].minOffset +
+ layoutPtr[slot].minSize;
+ }
+ }
+
+ /*
+ * Having pushed the top/left boundaries of the slots to take up extra
+ * space, the bottom/right space is recalculated to propagate the new
+ * space allocation.
+ */
+
+ for (slot = end; slot > start; slot--) {
+ /*
+ * maxOffset may not go up.
+ */
+
+ if ((layoutPtr[slot].maxOffset-layoutPtr[slot].minSize)
+ < layoutPtr[slot-1].maxOffset) {
+ layoutPtr[slot-1].maxOffset =
+ layoutPtr[slot].maxOffset-layoutPtr[slot].minSize;
+ }
+ }
+ }
+
+ /*
+ * Step 6.
+ * All of the space has been apportioned; copy the layout information back
+ * into the master.
+ */
+
+ for (slot=0; slot < gridCount; slot++) {
+ slotPtr[slot].offset = layoutPtr[slot].minOffset;
+ }
+
+ --layoutPtr;
+ if (layoutPtr != layoutData) {
+ ckfree(layoutPtr);
+ }
+ return requiredSize;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetGrid --
+ *
+ * This internal procedure is used to locate a Grid structure for a given
+ * window, creating one if one doesn't exist already.
+ *
+ * Results:
+ * The return value is a pointer to the Grid structure corresponding to
+ * tkwin.
+ *
+ * Side effects:
+ * A new grid structure may be created. If so, then a callback is set up
+ * to clean things up when the window is deleted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Gridder *
+GetGrid(
+ Tk_Window tkwin) /* Token for window for which grid structure
+ * is desired. */
+{
+ register Gridder *gridPtr;
+ Tcl_HashEntry *hPtr;
+ int isNew;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+
+ if (!dispPtr->gridInit) {
+ Tcl_InitHashTable(&dispPtr->gridHashTable, TCL_ONE_WORD_KEYS);
+ dispPtr->gridInit = 1;
+ }
+
+ /*
+ * See if there's already grid for this window. If not, then create a new
+ * one.
+ */
+
+ hPtr = Tcl_CreateHashEntry(&dispPtr->gridHashTable, (char*) tkwin, &isNew);
+ if (!isNew) {
+ return Tcl_GetHashValue(hPtr);
+ }
+ gridPtr = ckalloc(sizeof(Gridder));
+ gridPtr->tkwin = tkwin;
+ gridPtr->masterPtr = NULL;
+ gridPtr->masterDataPtr = NULL;
+ gridPtr->nextPtr = NULL;
+ gridPtr->slavePtr = NULL;
+ gridPtr->binNextPtr = NULL;
+
+ gridPtr->column = -1;
+ gridPtr->row = -1;
+ gridPtr->numCols = 1;
+ gridPtr->numRows = 1;
+
+ gridPtr->padX = 0;
+ gridPtr->padY = 0;
+ gridPtr->padLeft = 0;
+ gridPtr->padTop = 0;
+ gridPtr->iPadX = 0;
+ gridPtr->iPadY = 0;
+ gridPtr->doubleBw = 2 * Tk_Changes(tkwin)->border_width;
+ gridPtr->abortPtr = NULL;
+ gridPtr->flags = 0;
+ gridPtr->sticky = 0;
+ gridPtr->size = 0;
+ gridPtr->in = NULL;
+ gridPtr->masterDataPtr = NULL;
+ Tcl_SetHashValue(hPtr, gridPtr);
+ Tk_CreateEventHandler(tkwin, StructureNotifyMask,
+ GridStructureProc, gridPtr);
+ return gridPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetGridSize --
+ *
+ * This internal procedure sets the size of the grid occupied by slaves.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * The width and height arguments are filled in the master data
+ * structure. Additional space is allocated for the constraints to
+ * accommodate the offsets.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+SetGridSize(
+ Gridder *masterPtr) /* The geometry master for this grid. */
+{
+ register Gridder *slavePtr; /* Current slave window. */
+ int maxX = 0, maxY = 0;
+
+ for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
+ slavePtr = slavePtr->nextPtr) {
+ maxX = MAX(maxX, slavePtr->numCols + slavePtr->column);
+ maxY = MAX(maxY, slavePtr->numRows + slavePtr->row);
+ }
+ masterPtr->masterDataPtr->columnEnd = maxX;
+ masterPtr->masterDataPtr->rowEnd = maxY;
+ CheckSlotData(masterPtr, maxX, COLUMN, CHECK_SPACE);
+ CheckSlotData(masterPtr, maxY, ROW, CHECK_SPACE);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetSlaveColumn --
+ *
+ * Update column data for a slave, checking that MAX_ELEMENT bound
+ * is not passed.
+ *
+ * Results:
+ * TCL_ERROR if out of bounds, TCL_OK otherwise
+ *
+ * Side effects:
+ * Slave fields are updated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetSlaveColumn(
+ Tcl_Interp *interp, /* Interp for error message. */
+ Gridder *slavePtr, /* Slave to be updated. */
+ int column, /* New column or -1 to be unchanged. */
+ int numCols) /* New columnspan or -1 to be unchanged. */
+{
+ int newColumn, newNumCols, lastCol;
+
+ newColumn = (column >= 0) ? column : slavePtr->column;
+ newNumCols = (numCols >= 1) ? numCols : slavePtr->numCols;
+
+ lastCol = ((newColumn >= 0) ? newColumn : 0) + newNumCols;
+ if (lastCol >= MAX_ELEMENT) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("column out of bounds",-1));
+ Tcl_SetErrorCode(interp, "TK", "GRID", "BAD_COLUMN", NULL);
+ return TCL_ERROR;
+ }
+
+ slavePtr->column = newColumn;
+ slavePtr->numCols = newNumCols;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetSlaveRow --
+ *
+ * Update row data for a slave, checking that MAX_ELEMENT bound
+ * is not passed.
+ *
+ * Results:
+ * TCL_ERROR if out of bounds, TCL_OK otherwise
+ *
+ * Side effects:
+ * Slave fields are updated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetSlaveRow(
+ Tcl_Interp *interp, /* Interp for error message. */
+ Gridder *slavePtr, /* Slave to be updated. */
+ int row, /* New row or -1 to be unchanged. */
+ int numRows) /* New rowspan or -1 to be unchanged. */
+{
+ int newRow, newNumRows, lastRow;
+
+ newRow = (row >= 0) ? row : slavePtr->row;
+ newNumRows = (numRows >= 1) ? numRows : slavePtr->numRows;
+
+ lastRow = ((newRow >= 0) ? newRow : 0) + newNumRows;
+ if (lastRow >= MAX_ELEMENT) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("row out of bounds", -1));
+ Tcl_SetErrorCode(interp, "TK", "GRID", "BAD_ROW", NULL);
+ return TCL_ERROR;
+ }
+
+ slavePtr->row = newRow;
+ slavePtr->numRows = newNumRows;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CheckSlotData --
+ *
+ * This internal procedure is used to manage the storage for row and
+ * column (slot) constraints.
+ *
+ * Results:
+ * TRUE if the index is OK, False otherwise.
+ *
+ * Side effects:
+ * A new master grid structure may be created. If so, then it is
+ * initialized. In addition, additional storage for a row or column
+ * constraints may be allocated, and the constraint maximums are
+ * adjusted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CheckSlotData(
+ Gridder *masterPtr, /* The geometry master for this grid. */
+ int slot, /* Which slot to look at. */
+ int slotType, /* ROW or COLUMN. */
+ int checkOnly) /* Don't allocate new space if true. */
+{
+ int numSlot; /* Number of slots already allocated (Space) */
+ int end; /* Last used constraint. */
+
+ /*
+ * If slot is out of bounds, return immediately.
+ */
+
+ if (slot < 0 || slot >= MAX_ELEMENT) {
+ return TCL_ERROR;
+ }
+
+ if ((checkOnly == CHECK_ONLY) && (masterPtr->masterDataPtr == NULL)) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * If we need to allocate more space, allocate a little extra to avoid
+ * repeated re-alloc's for large tables. We need enough space to hold all
+ * of the offsets as well.
+ */
+
+ InitMasterData(masterPtr);
+ end = (slotType == ROW) ? masterPtr->masterDataPtr->rowMax :
+ masterPtr->masterDataPtr->columnMax;
+ if (checkOnly == CHECK_ONLY) {
+ return ((end < slot) ? TCL_ERROR : TCL_OK);
+ } else {
+ numSlot = (slotType == ROW) ? masterPtr->masterDataPtr->rowSpace
+ : masterPtr->masterDataPtr->columnSpace;
+ if (slot >= numSlot) {
+ int newNumSlot = slot + PREALLOC;
+ size_t oldSize = numSlot * sizeof(SlotInfo);
+ size_t newSize = newNumSlot * sizeof(SlotInfo);
+ SlotInfo *newSI = ckalloc(newSize);
+ SlotInfo *oldSI = (slotType == ROW)
+ ? masterPtr->masterDataPtr->rowPtr
+ : masterPtr->masterDataPtr->columnPtr;
+
+ memcpy(newSI, oldSI, oldSize);
+ memset(newSI+numSlot, 0, newSize - oldSize);
+ ckfree(oldSI);
+ if (slotType == ROW) {
+ masterPtr->masterDataPtr->rowPtr = newSI;
+ masterPtr->masterDataPtr->rowSpace = newNumSlot;
+ } else {
+ masterPtr->masterDataPtr->columnPtr = newSI;
+ masterPtr->masterDataPtr->columnSpace = newNumSlot;
+ }
+ }
+ if (slot >= end && checkOnly != CHECK_SPACE) {
+ if (slotType == ROW) {
+ masterPtr->masterDataPtr->rowMax = slot+1;
+ } else {
+ masterPtr->masterDataPtr->columnMax = slot+1;
+ }
+ }
+ return TCL_OK;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InitMasterData --
+ *
+ * This internal procedure is used to allocate and initialize the data
+ * for a geometry master, if the data doesn't exist already.
+ *
+ * Results:
+ * none
+ *
+ * Side effects:
+ * A new master grid structure may be created. If so, then it is
+ * initialized.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+InitMasterData(
+ Gridder *masterPtr)
+{
+ if (masterPtr->masterDataPtr == NULL) {
+ GridMaster *gridPtr = masterPtr->masterDataPtr =
+ ckalloc(sizeof(GridMaster));
+ size_t size = sizeof(SlotInfo) * TYPICAL_SIZE;
+
+ gridPtr->columnEnd = 0;
+ gridPtr->columnMax = 0;
+ gridPtr->columnPtr = ckalloc(size);
+ gridPtr->columnSpace = TYPICAL_SIZE;
+ gridPtr->rowEnd = 0;
+ gridPtr->rowMax = 0;
+ gridPtr->rowPtr = ckalloc(size);
+ gridPtr->rowSpace = TYPICAL_SIZE;
+ gridPtr->startX = 0;
+ gridPtr->startY = 0;
+ gridPtr->anchor = GRID_DEFAULT_ANCHOR;
+
+ memset(gridPtr->columnPtr, 0, size);
+ memset(gridPtr->rowPtr, 0, size);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Unlink --
+ *
+ * Remove a grid from its master's list of slaves.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The master will be scheduled for re-arranging, and the size of the
+ * grid will be adjusted accordingly
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+Unlink(
+ register Gridder *slavePtr) /* Window to unlink. */
+{
+ register Gridder *masterPtr, *slavePtr2;
+
+ masterPtr = slavePtr->masterPtr;
+ if (masterPtr == NULL) {
+ return;
+ }
+
+ if (masterPtr->slavePtr == slavePtr) {
+ masterPtr->slavePtr = slavePtr->nextPtr;
+ } else {
+ for (slavePtr2=masterPtr->slavePtr ; ; slavePtr2=slavePtr2->nextPtr) {
+ if (slavePtr2 == NULL) {
+ Tcl_Panic("Unlink couldn't find previous window");
+ }
+ if (slavePtr2->nextPtr == slavePtr) {
+ slavePtr2->nextPtr = slavePtr->nextPtr;
+ break;
+ }
+ }
+ }
+ if (!(masterPtr->flags & REQUESTED_RELAYOUT)) {
+ masterPtr->flags |= REQUESTED_RELAYOUT;
+ Tcl_DoWhenIdle(ArrangeGrid, masterPtr);
+ }
+ if (masterPtr->abortPtr != NULL) {
+ *masterPtr->abortPtr = 1;
+ }
+
+ SetGridSize(slavePtr->masterPtr);
+ slavePtr->masterPtr = NULL;
+
+ /*
+ * If we have emptied this master from slaves it means we are no longer
+ * handling it and should mark it as free.
+ */
+
+ if ((masterPtr->slavePtr == NULL) && (masterPtr->flags & ALLOCED_MASTER)) {
+ TkFreeGeometryMaster(masterPtr->tkwin, "grid");
+ masterPtr->flags &= ~ALLOCED_MASTER;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyGrid --
+ *
+ * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release to
+ * clean up the internal structure of a grid at a safe time (when no-one
+ * is using it anymore). Cleaning up the grid involves freeing the main
+ * structure for all windows and the master structure for geometry
+ * managers.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Everything associated with the grid is freed up.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DestroyGrid(
+ void *memPtr) /* Info about window that is now dead. */
+{
+ register Gridder *gridPtr = memPtr;
+
+ if (gridPtr->masterDataPtr != NULL) {
+ if (gridPtr->masterDataPtr->rowPtr != NULL) {
+ ckfree(gridPtr->masterDataPtr -> rowPtr);
+ }
+ if (gridPtr->masterDataPtr->columnPtr != NULL) {
+ ckfree(gridPtr->masterDataPtr -> columnPtr);
+ }
+ ckfree(gridPtr->masterDataPtr);
+ }
+ if (gridPtr->in != NULL) {
+ Tcl_DecrRefCount(gridPtr->in);
+ }
+ ckfree(gridPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GridStructureProc --
+ *
+ * This procedure is invoked by the Tk event dispatcher in response to
+ * StructureNotify events.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If a window was just deleted, clean up all its grid-related
+ * information. If it was just resized, re-configure its slaves, if any.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GridStructureProc(
+ ClientData clientData, /* Our information about window referred to by
+ * eventPtr. */
+ XEvent *eventPtr) /* Describes what just happened. */
+{
+ register Gridder *gridPtr = clientData;
+ TkDisplay *dispPtr = ((TkWindow *) gridPtr->tkwin)->dispPtr;
+
+ if (eventPtr->type == ConfigureNotify) {
+ if ((gridPtr->slavePtr != NULL)
+ && !(gridPtr->flags & REQUESTED_RELAYOUT)) {
+ gridPtr->flags |= REQUESTED_RELAYOUT;
+ Tcl_DoWhenIdle(ArrangeGrid, gridPtr);
+ }
+ if ((gridPtr->masterPtr != NULL) &&
+ (gridPtr->doubleBw != 2*Tk_Changes(gridPtr->tkwin)->border_width)) {
+ if (!(gridPtr->masterPtr->flags & REQUESTED_RELAYOUT)) {
+ gridPtr->doubleBw = 2*Tk_Changes(gridPtr->tkwin)->border_width;
+ gridPtr->masterPtr->flags |= REQUESTED_RELAYOUT;
+ Tcl_DoWhenIdle(ArrangeGrid, gridPtr->masterPtr);
+ }
+ }
+ } else if (eventPtr->type == DestroyNotify) {
+ register Gridder *slavePtr, *nextPtr;
+
+ if (gridPtr->masterPtr != NULL) {
+ Unlink(gridPtr);
+ }
+ for (slavePtr = gridPtr->slavePtr; slavePtr != NULL;
+ slavePtr = nextPtr) {
+ Tk_ManageGeometry(slavePtr->tkwin, NULL, NULL);
+ Tk_UnmapWindow(slavePtr->tkwin);
+ slavePtr->masterPtr = NULL;
+ nextPtr = slavePtr->nextPtr;
+ slavePtr->nextPtr = NULL;
+ }
+ Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->gridHashTable,
+ (char *) gridPtr->tkwin));
+ if (gridPtr->flags & REQUESTED_RELAYOUT) {
+ Tcl_CancelIdleCall(ArrangeGrid, gridPtr);
+ }
+ gridPtr->tkwin = NULL;
+ Tcl_EventuallyFree(gridPtr, (Tcl_FreeProc *)DestroyGrid);
+ } else if (eventPtr->type == MapNotify) {
+ if ((gridPtr->slavePtr != NULL)
+ && !(gridPtr->flags & REQUESTED_RELAYOUT)) {
+ gridPtr->flags |= REQUESTED_RELAYOUT;
+ Tcl_DoWhenIdle(ArrangeGrid, gridPtr);
+ }
+ } else if (eventPtr->type == UnmapNotify) {
+ register Gridder *slavePtr;
+
+ for (slavePtr = gridPtr->slavePtr; slavePtr != NULL;
+ slavePtr = slavePtr->nextPtr) {
+ Tk_UnmapWindow(slavePtr->tkwin);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConfigureSlaves --
+ *
+ * This implements the guts of the "grid configure" command. Given a list
+ * of slaves and configuration options, it arranges for the grid to
+ * manage the slaves and sets the specified options. Arguments consist
+ * of windows or window shortcuts followed by "-option value" pairs.
+ *
+ * Results:
+ * TCL_OK is returned if all went well. Otherwise, TCL_ERROR is returned
+ * and the interp's result is set to contain an error message.
+ *
+ * Side effects:
+ * Slave windows get taken over by the grid.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ConfigureSlaves(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Tk_Window tkwin, /* Any window in application containing
+ * slaves. Used to look up slave names. */
+ int objc, /* Number of elements in argv. */
+ Tcl_Obj *const objv[]) /* Argument objects: contains one or more
+ * window names followed by any number of
+ * "option value" pairs. Caller must make sure
+ * that there is at least one window name. */
+{
+ Gridder *masterPtr = NULL;
+ Gridder *slavePtr;
+ Tk_Window other, slave, parent, ancestor;
+ TkWindow *master;
+ int i, j, tmp;
+ int numWindows;
+ int width;
+ int defaultRow = -1;
+ int defaultColumn = 0; /* Default column number */
+ int defaultColumnSpan = 1; /* Default number of columns */
+ const char *lastWindow; /* Use this window to base current row/col
+ * on */
+ int numSkip; /* Number of 'x' found */
+ static const char *const optionStrings[] = {
+ "-column", "-columnspan", "-in", "-ipadx", "-ipady",
+ "-padx", "-pady", "-row", "-rowspan", "-sticky", NULL
+ };
+ enum options {
+ CONF_COLUMN, CONF_COLUMNSPAN, CONF_IN, CONF_IPADX, CONF_IPADY,
+ CONF_PADX, CONF_PADY, CONF_ROW, CONF_ROWSPAN, CONF_STICKY };
+ int index;
+ const char *string;
+ char firstChar;
+ int positionGiven;
+
+ /*
+ * Count the number of windows, or window short-cuts.
+ */
+
+ firstChar = 0;
+ for (numWindows=0, i=0; i < objc; i++) {
+ int length;
+ char prevChar = firstChar;
+
+ string = Tcl_GetStringFromObj(objv[i], &length);
+ firstChar = string[0];
+
+ if (firstChar == '.') {
+ /*
+ * Check that windows are valid, and locate the first slave's
+ * parent window (default for -in).
+ */
+
+ if (TkGetWindowFromObj(interp, tkwin, objv[i], &slave) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (masterPtr == NULL) {
+ /*
+ * Is there any saved -in from a removed slave?
+ * If there is, it becomes default for -in.
+ * If the stored master does not exist, just ignore it.
+ */
+
+ struct Gridder *slavePtr = GetGrid(slave);
+ if (slavePtr->in != NULL) {
+ if (TkGetWindowFromObj(interp, slave, slavePtr->in, &parent)
+ == TCL_OK) {
+ masterPtr = GetGrid(parent);
+ InitMasterData(masterPtr);
+ }
+ }
+ }
+ if (masterPtr == NULL) {
+ parent = Tk_Parent(slave);
+ if (parent != NULL) {
+ masterPtr = GetGrid(parent);
+ InitMasterData(masterPtr);
+ }
+ }
+ numWindows++;
+ continue;
+ }
+ if (length > 1 && i == 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad argument \"%s\": must be name of window", string));
+ Tcl_SetErrorCode(interp, "TK", "GRID", "BAD_PARAMETER", NULL);
+ return TCL_ERROR;
+ }
+ if (length > 1 && firstChar == '-') {
+ break;
+ }
+ if (length > 1) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "unexpected parameter \"%s\" in configure list:"
+ " should be window name or option", string));
+ Tcl_SetErrorCode(interp, "TK", "GRID", "BAD_PARAMETER", NULL);
+ return TCL_ERROR;
+ }
+
+ if ((firstChar == REL_HORIZ) && ((numWindows == 0) ||
+ (prevChar == REL_SKIP) || (prevChar == REL_VERT))) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "must specify window before shortcut '-'", -1));
+ Tcl_SetErrorCode(interp, "TK", "GRID", "SHORTCUT_USAGE", NULL);
+ return TCL_ERROR;
+ }
+
+ if ((firstChar == REL_VERT) || (firstChar == REL_SKIP)
+ || (firstChar == REL_HORIZ)) {
+ continue;
+ }
+
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "invalid window shortcut, \"%s\" should be '-', 'x', or '^'",
+ string));
+ Tcl_SetErrorCode(interp, "TK", "GRID", "SHORTCUT_USAGE", NULL);
+ return TCL_ERROR;
+ }
+ numWindows = i;
+
+ if ((objc - numWindows) & 1) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "extra option or option with no value", -1));
+ Tcl_SetErrorCode(interp, "TK", "GRID", "BAD_PARAMETER", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Go through all options looking for -in and -row, which are needed to be
+ * found first to handle the special case where ^ is used on a row without
+ * windows names, but with an -in option. Since all options are checked
+ * here, we do not need to handle the error case again later.
+ */
+
+ for (i = numWindows; i < objc; i += 2) {
+ if (Tcl_GetIndexFromObjStruct(interp, objv[i], optionStrings,
+ sizeof(char *), "option", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (index == CONF_IN) {
+ if (TkGetWindowFromObj(interp, tkwin, objv[i+1], &other) !=
+ TCL_OK) {
+ return TCL_ERROR;
+ }
+ masterPtr = GetGrid(other);
+ InitMasterData(masterPtr);
+ } else if (index == CONF_ROW) {
+ if (Tcl_GetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK
+ || tmp < 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad row value \"%s\": must be a non-negative integer",
+ Tcl_GetString(objv[i+1])));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "POSITIVE_INT", NULL);
+ return TCL_ERROR;
+ }
+ defaultRow = tmp;
+ }
+ }
+
+ /*
+ * If no -row is given, use the next row after the highest occupied row
+ * of the master.
+ */
+
+ if (defaultRow < 0) {
+ if (masterPtr != NULL && masterPtr->masterDataPtr != NULL) {
+ SetGridSize(masterPtr);
+ defaultRow = masterPtr->masterDataPtr->rowEnd;
+ } else {
+ defaultRow = 0;
+ }
+ }
+
+ /*
+ * Iterate over all of the slave windows and short-cuts, parsing options
+ * for each slave. It's a bit wasteful to re-parse the options for each
+ * slave, but things get too messy if we try to parse the arguments just
+ * once at the beginning. For example, if a slave already is managed we
+ * want to just change a few existing values without resetting everything.
+ * If there are multiple windows, the -in option only gets processed for
+ * the first window.
+ */
+
+ positionGiven = 0;
+ for (j = 0; j < numWindows; j++) {
+ string = Tcl_GetString(objv[j]);
+ firstChar = string[0];
+
+ /*
+ * '^' and 'x' cause us to skip a column. '-' is processed as part of
+ * its preceeding slave.
+ */
+
+ if ((firstChar == REL_VERT) || (firstChar == REL_SKIP)) {
+ defaultColumn++;
+ continue;
+ }
+ if (firstChar == REL_HORIZ) {
+ continue;
+ }
+
+ for (defaultColumnSpan = 1; j + defaultColumnSpan < numWindows;
+ defaultColumnSpan++) {
+ const char *string = Tcl_GetString(objv[j + defaultColumnSpan]);
+
+ if (*string != REL_HORIZ) {
+ break;
+ }
+ }
+
+ if (TkGetWindowFromObj(interp, tkwin, objv[j], &slave) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (Tk_TopWinHierarchy(slave)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't manage \"%s\": it's a top-level window",
+ Tcl_GetString(objv[j])));
+ Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "TOPLEVEL", NULL);
+ return TCL_ERROR;
+ }
+ slavePtr = GetGrid(slave);
+
+ /*
+ * The following statement is taken from tkPack.c:
+ *
+ * "If the slave isn't currently managed, reset all of its
+ * configuration information to default values (there could be old
+ * values left from a previous packer)."
+ *
+ * I [D.S.] disagree with this statement. If a slave is disabled
+ * (using "forget") and then re-enabled, I submit that 90% of the time
+ * the programmer will want it to retain its old configuration
+ * information. If the programmer doesn't want this behavior, then the
+ * defaults can be reestablished by hand, without having to worry
+ * about keeping track of the old state.
+ */
+
+ for (i = numWindows; i < objc; i += 2) {
+ Tcl_GetIndexFromObjStruct(interp, objv[i], optionStrings,
+ sizeof(char *), "option", 0, &index);
+ switch ((enum options) index) {
+ case CONF_COLUMN:
+ if (Tcl_GetIntFromObj(NULL, objv[i+1], &tmp) != TCL_OK
+ || tmp < 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad column value \"%s\": must be a non-negative integer",
+ Tcl_GetString(objv[i+1])));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "COLUMN", NULL);
+ return TCL_ERROR;
+ }
+ if (SetSlaveColumn(interp, slavePtr, tmp, -1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+ case CONF_COLUMNSPAN:
+ if (Tcl_GetIntFromObj(NULL, objv[i+1], &tmp) != TCL_OK
+ || tmp <= 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad columnspan value \"%s\": must be a positive integer",
+ Tcl_GetString(objv[i+1])));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "SPAN", NULL);
+ return TCL_ERROR;
+ }
+ if (SetSlaveColumn(interp, slavePtr, -1, tmp) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+ case CONF_IN:
+ if (TkGetWindowFromObj(interp, tkwin, objv[i+1],
+ &other) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (other == slave) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "window can't be managed in itself", -1));
+ Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "SELF", NULL);
+ return TCL_ERROR;
+ }
+ positionGiven = 1;
+ masterPtr = GetGrid(other);
+ InitMasterData(masterPtr);
+ break;
+ case CONF_STICKY: {
+ int sticky = StringToSticky(Tcl_GetString(objv[i+1]));
+
+ if (sticky == -1) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad stickyness value \"%s\": must be"
+ " a string containing n, e, s, and/or w",
+ Tcl_GetString(objv[i+1])));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "STICKY", NULL);
+ return TCL_ERROR;
+ }
+ slavePtr->sticky = sticky;
+ break;
+ }
+ case CONF_IPADX:
+ if ((Tk_GetPixelsFromObj(NULL, slave, objv[i+1],
+ &tmp) != TCL_OK) || (tmp < 0)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad ipadx value \"%s\": must be positive screen distance",
+ Tcl_GetString(objv[i+1])));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "INT_PAD", NULL);
+ return TCL_ERROR;
+ }
+ slavePtr->iPadX = tmp * 2;
+ break;
+ case CONF_IPADY:
+ if ((Tk_GetPixelsFromObj(NULL, slave, objv[i+1],
+ &tmp) != TCL_OK) || (tmp < 0)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad ipady value \"%s\": must be positive screen distance",
+ Tcl_GetString(objv[i+1])));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "INT_PAD", NULL);
+ return TCL_ERROR;
+ }
+ slavePtr->iPadY = tmp * 2;
+ break;
+ case CONF_PADX:
+ if (TkParsePadAmount(interp, tkwin, objv[i+1],
+ &slavePtr->padLeft, &slavePtr->padX) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+ case CONF_PADY:
+ if (TkParsePadAmount(interp, tkwin, objv[i+1],
+ &slavePtr->padTop, &slavePtr->padY) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+ case CONF_ROW:
+ if (Tcl_GetIntFromObj(NULL, objv[i+1], &tmp) != TCL_OK
+ || tmp < 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad row value \"%s\": must be a non-negative integer",
+ Tcl_GetString(objv[i+1])));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "COLUMN", NULL);
+ return TCL_ERROR;
+ }
+ if (SetSlaveRow(interp, slavePtr, tmp, -1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+ case CONF_ROWSPAN:
+ if ((Tcl_GetIntFromObj(NULL, objv[i+1], &tmp) != TCL_OK)
+ || tmp <= 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad rowspan value \"%s\": must be a positive integer",
+ Tcl_GetString(objv[i+1])));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "SPAN", NULL);
+ return TCL_ERROR;
+ }
+ if (SetSlaveRow(interp, slavePtr, -1, tmp) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+ }
+ }
+
+ /*
+ * If no position was specified via -in and the slave is already
+ * packed, then leave it in its current location.
+ */
+
+ if (!positionGiven && (slavePtr->masterPtr != NULL)) {
+ masterPtr = slavePtr->masterPtr;
+ goto scheduleLayout;
+ }
+
+ /*
+ * If the same -in window is passed in again, then just leave it in
+ * its current location.
+ */
+
+ if (positionGiven && (masterPtr == slavePtr->masterPtr)) {
+ goto scheduleLayout;
+ }
+
+ /*
+ * Make sure we have a geometry master. We look at:
+ * 1) the -in flag
+ * 2) the parent of the first slave.
+ */
+
+ parent = Tk_Parent(slave);
+ if (masterPtr == NULL) {
+ masterPtr = GetGrid(parent);
+ InitMasterData(masterPtr);
+ }
+
+ if (slavePtr->masterPtr != NULL && slavePtr->masterPtr != masterPtr) {
+ if (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin)) {
+ Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin);
+ }
+ Unlink(slavePtr);
+ slavePtr->masterPtr = NULL;
+ }
+
+ if (slavePtr->masterPtr == NULL) {
+ Gridder *tempPtr = masterPtr->slavePtr;
+
+ slavePtr->masterPtr = masterPtr;
+ masterPtr->slavePtr = slavePtr;
+ slavePtr->nextPtr = tempPtr;
+ }
+
+ /*
+ * Make sure that the slave's parent is either the master or an
+ * ancestor of the master, and that the master and slave aren't the
+ * same.
+ */
+
+ for (ancestor = masterPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) {
+ if (ancestor == parent) {
+ break;
+ }
+ if (Tk_TopWinHierarchy(ancestor)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't put %s inside %s", Tcl_GetString(objv[j]),
+ Tk_PathName(masterPtr->tkwin)));
+ Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "HIERARCHY", NULL);
+ Unlink(slavePtr);
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * Check for management loops.
+ */
+
+ for (master = (TkWindow *)masterPtr->tkwin; master != NULL;
+ master = (TkWindow *)TkGetGeomMaster(master)) {
+ if (master == (TkWindow *)slave) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't put %s inside %s, would cause management loop",
+ Tcl_GetString(objv[j]), Tk_PathName(masterPtr->tkwin)));
+ Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "LOOP", NULL);
+ Unlink(slavePtr);
+ return TCL_ERROR;
+ }
+ }
+ if (masterPtr->tkwin != Tk_Parent(slave)) {
+ ((TkWindow *)slave)->maintainerPtr = (TkWindow *)masterPtr->tkwin;
+ }
+
+ Tk_ManageGeometry(slave, &gridMgrType, slavePtr);
+
+ if (!(masterPtr->flags & DONT_PROPAGATE)) {
+ if (TkSetGeometryMaster(interp, masterPtr->tkwin, "grid")
+ != TCL_OK) {
+ Tk_ManageGeometry(slave, NULL, NULL);
+ Unlink(slavePtr);
+ return TCL_ERROR;
+ }
+ masterPtr->flags |= ALLOCED_MASTER;
+ }
+
+ /*
+ * Assign default position information.
+ */
+
+ if (slavePtr->column == -1) {
+ if (SetSlaveColumn(interp, slavePtr, defaultColumn,-1) != TCL_OK){
+ return TCL_ERROR;
+ }
+ }
+ if (SetSlaveColumn(interp, slavePtr, -1,
+ slavePtr->numCols + defaultColumnSpan - 1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (slavePtr->row == -1) {
+ if (SetSlaveRow(interp, slavePtr, defaultRow, -1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ defaultColumn += slavePtr->numCols;
+ defaultColumnSpan = 1;
+
+ /*
+ * Arrange for the master to be re-arranged at the first idle moment.
+ */
+
+ scheduleLayout:
+ if (masterPtr->abortPtr != NULL) {
+ *masterPtr->abortPtr = 1;
+ }
+ if (!(masterPtr->flags & REQUESTED_RELAYOUT)) {
+ masterPtr->flags |= REQUESTED_RELAYOUT;
+ Tcl_DoWhenIdle(ArrangeGrid, masterPtr);
+ }
+ }
+
+ /*
+ * Now look for all the "^"'s.
+ */
+
+ lastWindow = NULL;
+ numSkip = 0;
+ for (j = 0; j < numWindows; j++) {
+ struct Gridder *otherPtr;
+ int match; /* Found a match for the ^ */
+ int lastRow, lastColumn; /* Implied end of table. */
+
+ string = Tcl_GetString(objv[j]);
+ firstChar = string[0];
+
+ if (firstChar == '.') {
+ lastWindow = string;
+ numSkip = 0;
+ }
+ if (firstChar == REL_SKIP) {
+ numSkip++;
+ }
+ if (firstChar != REL_VERT) {
+ continue;
+ }
+
+ if (masterPtr == NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "can't use '^', cant find master", -1));
+ Tcl_SetErrorCode(interp, "TK", "GRID", "SHORTCUT_USAGE", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Count the number of consecutive ^'s starting from this position.
+ */
+
+ for (width = 1; width + j < numWindows; width++) {
+ const char *string = Tcl_GetString(objv[j+width]);
+
+ if (*string != REL_VERT) {
+ break;
+ }
+ }
+
+ /*
+ * Find the implied grid location of the ^
+ */
+
+ if (lastWindow == NULL) {
+ lastRow = defaultRow - 1;
+ lastColumn = 0;
+ } else {
+ other = Tk_NameToWindow(interp, lastWindow, tkwin);
+ otherPtr = GetGrid(other);
+ lastRow = otherPtr->row + otherPtr->numRows - 2;
+ lastColumn = otherPtr->column + otherPtr->numCols;
+ }
+
+ lastColumn += numSkip;
+
+ match = 0;
+ for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
+ slavePtr = slavePtr->nextPtr) {
+
+ if (slavePtr->column == lastColumn
+ && slavePtr->row + slavePtr->numRows - 1 == lastRow) {
+ if (slavePtr->numCols <= width) {
+ if (SetSlaveRow(interp, slavePtr, -1,
+ slavePtr->numRows + 1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ match++;
+ j += slavePtr->numCols - 1;
+ lastWindow = Tk_PathName(slavePtr->tkwin);
+ numSkip = 0;
+ break;
+ }
+ }
+ }
+ if (!match) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "can't find slave to extend with \"^\"", -1));
+ Tcl_SetErrorCode(interp, "TK", "GRID", "SHORTCUT_USAGE", NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ if (masterPtr == NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "can't determine master window", -1));
+ Tcl_SetErrorCode(interp, "TK", "GRID", "SHORTCUT_USAGE", NULL);
+ return TCL_ERROR;
+ }
+ SetGridSize(masterPtr);
+
+ /*
+ * If we have emptied this master from slaves it means we are no longer
+ * handling it and should mark it as free.
+ */
+
+ if (masterPtr->slavePtr == NULL && masterPtr->flags & ALLOCED_MASTER) {
+ TkFreeGeometryMaster(masterPtr->tkwin, "grid");
+ masterPtr->flags &= ~ALLOCED_MASTER;
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * StickyToObj
+ *
+ * Converts the internal boolean combination of "sticky" bits onto a Tcl
+ * list element containing zero or more of n, s, e, or w.
+ *
+ * Results:
+ * A new object is returned that holds the sticky representation.
+ *
+ * Side effects:
+ * none.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj *
+StickyToObj(
+ int flags) /* The sticky flags. */
+{
+ int count = 0;
+ char buffer[4];
+
+ if (flags & STICK_NORTH) {
+ buffer[count++] = 'n';
+ }
+ if (flags & STICK_EAST) {
+ buffer[count++] = 'e';
+ }
+ if (flags & STICK_SOUTH) {
+ buffer[count++] = 's';
+ }
+ if (flags & STICK_WEST) {
+ buffer[count++] = 'w';
+ }
+ return Tcl_NewStringObj(buffer, count);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * StringToSticky --
+ *
+ * Converts an ascii string representing a widgets stickyness into the
+ * boolean result.
+ *
+ * Results:
+ * The boolean combination of the "sticky" bits is retuned. If an error
+ * occurs, such as an invalid character, -1 is returned instead.
+ *
+ * Side effects:
+ * none
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+StringToSticky(
+ const char *string)
+{
+ int sticky = 0;
+ char c;
+
+ while ((c = *string++) != '\0') {
+ switch (c) {
+ case 'n': case 'N':
+ sticky |= STICK_NORTH;
+ break;
+ case 'e': case 'E':
+ sticky |= STICK_EAST;
+ break;
+ case 's': case 'S':
+ sticky |= STICK_SOUTH;
+ break;
+ case 'w': case 'W':
+ sticky |= STICK_WEST;
+ break;
+ case ' ': case ',': case '\t': case '\r': case '\n':
+ break;
+ default:
+ return -1;
+ }
+ }
+ return sticky;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NewPairObj --
+ *
+ * Creates a new list object and fills it with two integer objects.
+ *
+ * Results:
+ * The newly created list object is returned.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj *
+NewPairObj(
+ int val1, int val2)
+{
+ Tcl_Obj *ary[2];
+
+ ary[0] = Tcl_NewIntObj(val1);
+ ary[1] = Tcl_NewIntObj(val2);
+ return Tcl_NewListObj(2, ary);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NewQuadObj --
+ *
+ * Creates a new list object and fills it with four integer objects.
+ *
+ * Results:
+ * The newly created list object is returned.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj *
+NewQuadObj(
+ int val1, int val2, int val3, int val4)
+{
+ Tcl_Obj *ary[4];
+
+ ary[0] = Tcl_NewIntObj(val1);
+ ary[1] = Tcl_NewIntObj(val2);
+ ary[2] = Tcl_NewIntObj(val3);
+ ary[3] = Tcl_NewIntObj(val4);
+ return Tcl_NewListObj(4, ary);
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkImage.c b/tk8.6/generic/tkImage.c
new file mode 100644
index 0000000..dc4e8e0
--- /dev/null
+++ b/tk8.6/generic/tkImage.c
@@ -0,0 +1,1142 @@
+/*
+ * tkImage.c --
+ *
+ * This module implements the image protocol, which allows lots of
+ * different kinds of images to be used in lots of different widgets.
+ *
+ * Copyright (c) 1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "tkInt.h"
+
+/*
+ * Each call to Tk_GetImage returns a pointer to one of the following
+ * structures, which is used as a token by clients (widgets) that display
+ * images.
+ */
+
+typedef struct Image {
+ Tk_Window tkwin; /* Window passed to Tk_GetImage (needed to
+ * "re-get" the image later if the manager
+ * changes). */
+ Display *display; /* Display for tkwin. Needed because when the
+ * image is eventually freed tkwin may not
+ * exist anymore. */
+ struct ImageMaster *masterPtr;
+ /* Master for this image (identifiers image
+ * manager, for example). */
+ ClientData instanceData; /* One word argument to pass to image manager
+ * when dealing with this image instance. */
+ Tk_ImageChangedProc *changeProc;
+ /* Code in widget to call when image changes
+ * in a way that affects redisplay. */
+ ClientData widgetClientData;/* Argument to pass to changeProc. */
+ struct Image *nextPtr; /* Next in list of all image instances
+ * associated with the same name. */
+} Image;
+
+/*
+ * For each image master there is one of the following structures, which
+ * represents a name in the image table and all of the images instantiated
+ * from it. Entries in mainPtr->imageTable point to these structures.
+ */
+
+typedef struct ImageMaster {
+ Tk_ImageType *typePtr; /* Information about image type. NULL means
+ * that no image manager owns this image: the
+ * image was deleted. */
+ ClientData masterData; /* One-word argument to pass to image mgr when
+ * dealing with the master, as opposed to
+ * instances. */
+ int width, height; /* Last known dimensions for image. */
+ Tcl_HashTable *tablePtr; /* Pointer to hash table containing image (the
+ * imageTable field in some TkMainInfo
+ * structure). */
+ Tcl_HashEntry *hPtr; /* Hash entry in mainPtr->imageTable for this
+ * structure (used to delete the hash
+ * entry). */
+ Image *instancePtr; /* Pointer to first in list of instances
+ * derived from this name. */
+ int deleted; /* Flag set when image is being deleted. */
+ TkWindow *winPtr; /* Main window of interpreter (used to detect
+ * when the world is falling apart.) */
+} ImageMaster;
+
+typedef struct {
+ Tk_ImageType *imageTypeList;/* First in a list of all known image
+ * types. */
+ Tk_ImageType *oldImageTypeList;
+ /* First in a list of all known old-style
+ * image types. */
+ int initialized; /* Set to 1 if we've initialized the
+ * structure. */
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+
+/*
+ * Prototypes for local functions:
+ */
+
+static void ImageTypeThreadExitProc(ClientData clientData);
+static void DeleteImage(ImageMaster *masterPtr);
+static void EventuallyDeleteImage(ImageMaster *masterPtr,
+ int forgetImageHashNow);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImageTypeThreadExitProc --
+ *
+ * Clean up the registered list of image types.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The thread's linked lists of photo image formats is deleted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ImageTypeThreadExitProc(
+ ClientData clientData) /* not used */
+{
+ Tk_ImageType *freePtr;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ while (tsdPtr->oldImageTypeList != NULL) {
+ freePtr = tsdPtr->oldImageTypeList;
+ tsdPtr->oldImageTypeList = tsdPtr->oldImageTypeList->nextPtr;
+ ckfree(freePtr);
+ }
+ while (tsdPtr->imageTypeList != NULL) {
+ freePtr = tsdPtr->imageTypeList;
+ tsdPtr->imageTypeList = tsdPtr->imageTypeList->nextPtr;
+ ckfree(freePtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_CreateOldImageType, Tk_CreateImageType --
+ *
+ * This function is invoked by an image manager to tell Tk about a new
+ * kind of image and the functions that manage the new type. The function
+ * is typically invoked during Tcl_AppInit.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The new image type is entered into a table used in the "image create"
+ * command.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_CreateOldImageType(
+ const Tk_ImageType *typePtr)
+ /* Structure describing the type. All of the
+ * fields except "nextPtr" must be filled in
+ * by caller. */
+{
+ Tk_ImageType *copyPtr;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (!tsdPtr->initialized) {
+ tsdPtr->initialized = 1;
+ Tcl_CreateThreadExitHandler(ImageTypeThreadExitProc, NULL);
+ }
+ copyPtr = ckalloc(sizeof(Tk_ImageType));
+ *copyPtr = *typePtr;
+ copyPtr->nextPtr = tsdPtr->oldImageTypeList;
+ tsdPtr->oldImageTypeList = copyPtr;
+}
+
+void
+Tk_CreateImageType(
+ const Tk_ImageType *typePtr)
+ /* Structure describing the type. All of the
+ * fields except "nextPtr" must be filled in
+ * by caller. */
+{
+ Tk_ImageType *copyPtr;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (!tsdPtr->initialized) {
+ tsdPtr->initialized = 1;
+ Tcl_CreateThreadExitHandler(ImageTypeThreadExitProc, NULL);
+ }
+ copyPtr = ckalloc(sizeof(Tk_ImageType));
+ *copyPtr = *typePtr;
+ copyPtr->nextPtr = tsdPtr->imageTypeList;
+ tsdPtr->imageTypeList = copyPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_ImageObjCmd --
+ *
+ * This function is invoked to process the "image" 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_ImageObjCmd(
+ ClientData clientData, /* Main window associated with interpreter. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument strings. */
+{
+ static const char *const imageOptions[] = {
+ "create", "delete", "height", "inuse", "names", "type", "types",
+ "width", NULL
+ };
+ enum options {
+ IMAGE_CREATE, IMAGE_DELETE, IMAGE_HEIGHT, IMAGE_INUSE, IMAGE_NAMES,
+ IMAGE_TYPE, IMAGE_TYPES, IMAGE_WIDTH
+ };
+ TkWindow *winPtr = clientData;
+ int i, isNew, firstOption, index;
+ Tk_ImageType *typePtr;
+ ImageMaster *masterPtr;
+ Image *imagePtr;
+ Tcl_HashEntry *hPtr;
+ Tcl_HashSearch search;
+ char idString[16 + TCL_INTEGER_SPACE];
+ TkDisplay *dispPtr = winPtr->dispPtr;
+ const char *arg, *name;
+ Tcl_Obj *resultObj;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?args?");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[1], imageOptions,
+ sizeof(char *), "option", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch ((enum options) index) {
+ case IMAGE_CREATE: {
+ Tcl_Obj **args;
+ int oldimage = 0;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "type ?name? ?-option value ...?");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Look up the image type.
+ */
+
+ arg = Tcl_GetString(objv[2]);
+ for (typePtr = tsdPtr->imageTypeList; typePtr != NULL;
+ typePtr = typePtr->nextPtr) {
+ if ((*arg == typePtr->name[0])
+ && (strcmp(arg, typePtr->name) == 0)) {
+ break;
+ }
+ }
+ if (typePtr == NULL) {
+ oldimage = 1;
+ for (typePtr = tsdPtr->oldImageTypeList; typePtr != NULL;
+ typePtr = typePtr->nextPtr) {
+ if ((*arg == typePtr->name[0])
+ && (strcmp(arg, typePtr->name) == 0)) {
+ break;
+ }
+ }
+ }
+ if (typePtr == NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "image type \"%s\" doesn't exist", arg));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "IMAGE_TYPE", arg, NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Figure out a name to use for the new image.
+ */
+
+ if ((objc == 3) || (*(arg = Tcl_GetString(objv[3])) == '-')) {
+ do {
+ dispPtr->imageId++;
+ sprintf(idString, "image%d", dispPtr->imageId);
+ name = idString;
+ } while (Tcl_FindCommand(interp, name, NULL, 0) != NULL);
+ firstOption = 3;
+ } else {
+ TkWindow *topWin;
+
+ name = arg;
+ firstOption = 4;
+
+ /*
+ * Need to check if the _command_ that we are about to create is
+ * the name of the current master widget command (normally "." but
+ * could have been renamed) and fail in that case before a really
+ * nasty and hard to stop crash happens.
+ */
+
+ topWin = (TkWindow *) TkToplevelWindowForCommand(interp, name);
+ if (topWin != NULL && winPtr->mainPtr->winPtr == topWin) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "images may not be named the same as the main window",
+ -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "SMASH_MAIN", NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * Create the data structure for the new image.
+ */
+
+ hPtr = Tcl_CreateHashEntry(&winPtr->mainPtr->imageTable, name, &isNew);
+ if (isNew) {
+ masterPtr = ckalloc(sizeof(ImageMaster));
+ masterPtr->typePtr = NULL;
+ masterPtr->masterData = NULL;
+ masterPtr->width = masterPtr->height = 1;
+ masterPtr->tablePtr = &winPtr->mainPtr->imageTable;
+ masterPtr->hPtr = hPtr;
+ masterPtr->instancePtr = NULL;
+ masterPtr->deleted = 0;
+ masterPtr->winPtr = winPtr->mainPtr->winPtr;
+ Tcl_Preserve(masterPtr->winPtr);
+ Tcl_SetHashValue(hPtr, masterPtr);
+ } else {
+ /*
+ * An image already exists by this name. Disconnect the instances
+ * from the master.
+ */
+
+ masterPtr = Tcl_GetHashValue(hPtr);
+ if (masterPtr->typePtr != NULL) {
+ for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
+ imagePtr = imagePtr->nextPtr) {
+ masterPtr->typePtr->freeProc(imagePtr->instanceData,
+ imagePtr->display);
+ imagePtr->changeProc(imagePtr->widgetClientData, 0, 0,
+ masterPtr->width, masterPtr->height,
+ masterPtr->width, masterPtr->height);
+ }
+ masterPtr->typePtr->deleteProc(masterPtr->masterData);
+ masterPtr->typePtr = NULL;
+ }
+ masterPtr->deleted = 0;
+ }
+
+ /*
+ * Call the image type manager so that it can perform its own
+ * initialization, then re-"get" for any existing instances of the
+ * image.
+ */
+
+ objv += firstOption;
+ objc -= firstOption;
+ args = (Tcl_Obj **) objv;
+ if (oldimage) {
+ int i;
+
+ args = ckalloc((objc+1) * sizeof(char *));
+ for (i = 0; i < objc; i++) {
+ args[i] = (Tcl_Obj *) Tcl_GetString(objv[i]);
+ }
+ args[objc] = NULL;
+ }
+ Tcl_Preserve(masterPtr);
+ if (typePtr->createProc(interp, name, objc, args, typePtr,
+ (Tk_ImageMaster)masterPtr, &masterPtr->masterData) != TCL_OK){
+ EventuallyDeleteImage(masterPtr, 0);
+ Tcl_Release(masterPtr);
+ if (oldimage) {
+ ckfree(args);
+ }
+ return TCL_ERROR;
+ }
+ Tcl_Release(masterPtr);
+ if (oldimage) {
+ ckfree(args);
+ }
+ masterPtr->typePtr = typePtr;
+ for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
+ imagePtr = imagePtr->nextPtr) {
+ imagePtr->instanceData = typePtr->getProc(imagePtr->tkwin,
+ masterPtr->masterData);
+ }
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ Tcl_GetHashKey(&winPtr->mainPtr->imageTable, hPtr), -1));
+ break;
+ }
+ case IMAGE_DELETE:
+ for (i = 2; i < objc; i++) {
+ arg = Tcl_GetString(objv[i]);
+ hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg);
+ if (hPtr == NULL) {
+ goto alreadyDeleted;
+ }
+ masterPtr = Tcl_GetHashValue(hPtr);
+ if (masterPtr->deleted) {
+ goto alreadyDeleted;
+ }
+ DeleteImage(masterPtr);
+ }
+ break;
+ case IMAGE_NAMES:
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ return TCL_ERROR;
+ }
+ hPtr = Tcl_FirstHashEntry(&winPtr->mainPtr->imageTable, &search);
+ resultObj = Tcl_NewObj();
+ for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
+ masterPtr = Tcl_GetHashValue(hPtr);
+ if (masterPtr->deleted) {
+ continue;
+ }
+ Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(
+ Tcl_GetHashKey(&winPtr->mainPtr->imageTable, hPtr), -1));
+ }
+ Tcl_SetObjResult(interp, resultObj);
+ break;
+ case IMAGE_TYPES:
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ return TCL_ERROR;
+ }
+ resultObj = Tcl_NewObj();
+ for (typePtr = tsdPtr->imageTypeList; typePtr != NULL;
+ typePtr = typePtr->nextPtr) {
+ Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(
+ typePtr->name, -1));
+ }
+ for (typePtr = tsdPtr->oldImageTypeList; typePtr != NULL;
+ typePtr = typePtr->nextPtr) {
+ Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(
+ typePtr->name, -1));
+ }
+ Tcl_SetObjResult(interp, resultObj);
+ break;
+
+ case IMAGE_HEIGHT:
+ case IMAGE_INUSE:
+ case IMAGE_TYPE:
+ case IMAGE_WIDTH:
+ /*
+ * These operations all parse virtually identically. First check to
+ * see if three args are given. Then get a non-deleted master from the
+ * third arg.
+ */
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "name");
+ return TCL_ERROR;
+ }
+
+ arg = Tcl_GetString(objv[2]);
+ hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg);
+ if (hPtr == NULL) {
+ goto alreadyDeleted;
+ }
+ masterPtr = Tcl_GetHashValue(hPtr);
+ if (masterPtr->deleted) {
+ goto alreadyDeleted;
+ }
+
+ /*
+ * Now we read off the specific piece of data we were asked for.
+ */
+
+ switch ((enum options) index) {
+ case IMAGE_HEIGHT:
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(masterPtr->height));
+ break;
+ case IMAGE_INUSE:
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
+ masterPtr->typePtr && masterPtr->instancePtr));
+ break;
+ case IMAGE_TYPE:
+ if (masterPtr->typePtr != NULL) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj(masterPtr->typePtr->name, -1));
+ }
+ break;
+ case IMAGE_WIDTH:
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(masterPtr->width));
+ break;
+ default:
+ Tcl_Panic("can't happen");
+ }
+ break;
+ }
+ return TCL_OK;
+
+ alreadyDeleted:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf("image \"%s\" doesn't exist",arg));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "IMAGE", arg, NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_ImageChanged --
+ *
+ * This function is called by an image manager whenever something has
+ * happened that requires the image to be redrawn (some of its pixels
+ * have changed, or its size has changed).
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Any widgets that display the image are notified so that they can
+ * redisplay themselves as appropriate.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_ImageChanged(
+ Tk_ImageMaster imageMaster, /* Image that needs redisplay. */
+ int x, int y, /* Coordinates of upper-left pixel of region
+ * of image that needs to be redrawn. */
+ int width, int height, /* Dimensions (in pixels) of region of image
+ * to redraw. If either dimension is zero then
+ * the image doesn't need to be redrawn
+ * (perhaps all that happened is that its size
+ * changed). */
+ int imageWidth, int imageHeight)
+ /* New dimensions of image. */
+{
+ ImageMaster *masterPtr = (ImageMaster *) imageMaster;
+ Image *imagePtr;
+
+ masterPtr->width = imageWidth;
+ masterPtr->height = imageHeight;
+ for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
+ imagePtr = imagePtr->nextPtr) {
+ imagePtr->changeProc(imagePtr->widgetClientData, x, y, width, height,
+ imageWidth, imageHeight);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_NameOfImage --
+ *
+ * Given a token for an image master, this function returns the name of
+ * the image.
+ *
+ * Results:
+ * The return value is the string name for imageMaster.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+const char *
+Tk_NameOfImage(
+ Tk_ImageMaster imageMaster) /* Token for image. */
+{
+ ImageMaster *masterPtr = (ImageMaster *) imageMaster;
+
+ if (masterPtr->hPtr == NULL) {
+ return NULL;
+ }
+ return Tcl_GetHashKey(masterPtr->tablePtr, masterPtr->hPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetImage --
+ *
+ * This function is invoked by a widget when it wants to use a particular
+ * image in a particular window.
+ *
+ * Results:
+ * The return value is a token for the image. If there is no image by the
+ * given name, then NULL is returned and an error message is left in the
+ * interp's result.
+ *
+ * Side effects:
+ * Tk records the fact that the widget is using the image, and it will
+ * invoke changeProc later if the widget needs redisplay (i.e. its size
+ * changes or some of its pixels change). The caller must eventually
+ * invoke Tk_FreeImage when it no longer needs the image.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_Image
+Tk_GetImage(
+ Tcl_Interp *interp, /* Place to leave error message if image can't
+ * be found. */
+ Tk_Window tkwin, /* Token for window in which image will be
+ * used. */
+ const char *name, /* Name of desired image. */
+ Tk_ImageChangedProc *changeProc,
+ /* Function to invoke when redisplay is needed
+ * because image's pixels or size changed. */
+ ClientData clientData) /* One-word argument to pass to damageProc. */
+{
+ Tcl_HashEntry *hPtr;
+ ImageMaster *masterPtr;
+ Image *imagePtr;
+
+ hPtr = Tcl_FindHashEntry(&((TkWindow *) tkwin)->mainPtr->imageTable, name);
+ if (hPtr == NULL) {
+ goto noSuchImage;
+ }
+ masterPtr = Tcl_GetHashValue(hPtr);
+ if (masterPtr->typePtr == NULL) {
+ goto noSuchImage;
+ }
+ if (masterPtr->deleted) {
+ goto noSuchImage;
+ }
+ imagePtr = ckalloc(sizeof(Image));
+ imagePtr->tkwin = tkwin;
+ imagePtr->display = Tk_Display(tkwin);
+ imagePtr->masterPtr = masterPtr;
+ imagePtr->instanceData =
+ masterPtr->typePtr->getProc(tkwin, masterPtr->masterData);
+ imagePtr->changeProc = changeProc;
+ imagePtr->widgetClientData = clientData;
+ imagePtr->nextPtr = masterPtr->instancePtr;
+ masterPtr->instancePtr = imagePtr;
+ return (Tk_Image) imagePtr;
+
+ noSuchImage:
+ if (interp) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "image \"%s\" doesn't exist", name));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "IMAGE", name, NULL);
+ }
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_FreeImage --
+ *
+ * This function is invoked by a widget when it no longer needs an image
+ * acquired by a previous call to Tk_GetImage. For each call to
+ * Tk_GetImage there must be exactly one call to Tk_FreeImage.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The association between the image and the widget is removed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_FreeImage(
+ Tk_Image image) /* Token for image that is no longer needed by
+ * a widget. */
+{
+ Image *imagePtr = (Image *) image;
+ ImageMaster *masterPtr = imagePtr->masterPtr;
+ Image *prevPtr;
+
+ /*
+ * Clean up the particular instance.
+ */
+
+ if (masterPtr->typePtr != NULL) {
+ masterPtr->typePtr->freeProc(imagePtr->instanceData,
+ imagePtr->display);
+ }
+ prevPtr = masterPtr->instancePtr;
+ if (prevPtr == imagePtr) {
+ masterPtr->instancePtr = imagePtr->nextPtr;
+ } else {
+ while (prevPtr->nextPtr != imagePtr) {
+ prevPtr = prevPtr->nextPtr;
+ }
+ prevPtr->nextPtr = imagePtr->nextPtr;
+ }
+ ckfree(imagePtr);
+
+ /*
+ * If there are no more instances left for the master, and if the master
+ * image has been deleted, then delete the master too.
+ */
+
+ if ((masterPtr->typePtr == NULL) && (masterPtr->instancePtr == NULL)) {
+ if (masterPtr->hPtr != NULL) {
+ Tcl_DeleteHashEntry(masterPtr->hPtr);
+ }
+ Tcl_Release(masterPtr->winPtr);
+ ckfree(masterPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_PostscriptImage --
+ *
+ * This function is called by widgets that contain images in order to
+ * redisplay an image on the screen or an off-screen pixmap.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The image's manager is notified, and it redraws the desired portion of
+ * the image before returning.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_PostscriptImage(
+ Tk_Image image, /* Token for image to redisplay. */
+ Tcl_Interp *interp,
+ Tk_Window tkwin,
+ Tk_PostscriptInfo psinfo, /* postscript info */
+ int x, int y, /* Upper-left pixel of region in image that
+ * needs to be redisplayed. */
+ int width, int height, /* Dimensions of region to redraw. */
+ int prepass)
+{
+ Image *imagePtr = (Image *) image;
+ int result;
+ XImage *ximage;
+ Pixmap pmap;
+ GC newGC;
+ XGCValues gcValues;
+
+ if (imagePtr->masterPtr->typePtr == NULL) {
+ /*
+ * No master for image, so nothing to display on postscript.
+ */
+
+ return TCL_OK;
+ }
+
+ /*
+ * Check if an image specific postscript-generation function exists;
+ * otherwise go on with generic code.
+ */
+
+ if (imagePtr->masterPtr->typePtr->postscriptProc != NULL) {
+ return imagePtr->masterPtr->typePtr->postscriptProc(
+ imagePtr->masterPtr->masterData, interp, tkwin, psinfo,
+ x, y, width, height, prepass);
+ }
+
+ if (prepass) {
+ return TCL_OK;
+ }
+
+ /*
+ * Create a Pixmap, tell the image to redraw itself there, and then
+ * generate an XImage from the Pixmap. We can then read pixel values out
+ * of the XImage.
+ */
+
+ pmap = Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin), width, height,
+ Tk_Depth(tkwin));
+
+ gcValues.foreground = WhitePixelOfScreen(Tk_Screen(tkwin));
+ newGC = Tk_GetGC(tkwin, GCForeground, &gcValues);
+ if (newGC != NULL) {
+ XFillRectangle(Tk_Display(tkwin), pmap, newGC, 0, 0,
+ (unsigned) width, (unsigned) height);
+ Tk_FreeGC(Tk_Display(tkwin), newGC);
+ }
+
+ Tk_RedrawImage(image, x, y, width, height, pmap, 0, 0);
+
+ ximage = XGetImage(Tk_Display(tkwin), pmap, 0, 0,
+ (unsigned) width, (unsigned) height, AllPlanes, ZPixmap);
+
+ Tk_FreePixmap(Tk_Display(tkwin), pmap);
+
+ if (ximage == NULL) {
+ /*
+ * The XGetImage() function is apparently not implemented on this
+ * system. Just ignore it.
+ */
+
+ return TCL_OK;
+ }
+ result = TkPostscriptImage(interp, tkwin, psinfo, ximage, x, y,
+ width, height);
+
+ XDestroyImage(ximage);
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_RedrawImage --
+ *
+ * This function is called by widgets that contain images in order to
+ * redisplay an image on the screen or an off-screen pixmap.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The image's manager is notified, and it redraws the desired portion of
+ * the image before returning.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_RedrawImage(
+ Tk_Image image, /* Token for image to redisplay. */
+ int imageX, int imageY, /* Upper-left pixel of region in image that
+ * needs to be redisplayed. */
+ int width, int height, /* Dimensions of region to redraw. */
+ Drawable drawable, /* Drawable in which to display image (window
+ * or pixmap). If this is a pixmap, it must
+ * have the same depth as the window used in
+ * the Tk_GetImage call for the image. */
+ int drawableX, int drawableY)
+ /* Coordinates in drawable that correspond to
+ * imageX and imageY. */
+{
+ Image *imagePtr = (Image *) image;
+
+ if (imagePtr->masterPtr->typePtr == NULL) {
+ /*
+ * No master for image, so nothing to display.
+ */
+
+ return;
+ }
+
+ /*
+ * Clip the redraw area to the area of the image.
+ */
+
+ if (imageX < 0) {
+ width += imageX;
+ drawableX -= imageX;
+ imageX = 0;
+ }
+ if (imageY < 0) {
+ height += imageY;
+ drawableY -= imageY;
+ imageY = 0;
+ }
+ if ((imageX + width) > imagePtr->masterPtr->width) {
+ width = imagePtr->masterPtr->width - imageX;
+ }
+ if ((imageY + height) > imagePtr->masterPtr->height) {
+ height = imagePtr->masterPtr->height - imageY;
+ }
+ imagePtr->masterPtr->typePtr->displayProc(imagePtr->instanceData,
+ imagePtr->display, drawable, imageX, imageY, width, height,
+ drawableX, drawableY);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_SizeOfImage --
+ *
+ * This function returns the current dimensions of an image.
+ *
+ * Results:
+ * The width and height of the image are returned in *widthPtr and
+ * *heightPtr.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_SizeOfImage(
+ Tk_Image image, /* Token for image whose size is wanted. */
+ int *widthPtr, /* Return width of image here. */
+ int *heightPtr) /* Return height of image here. */
+{
+ Image *imagePtr = (Image *) image;
+
+ *widthPtr = imagePtr->masterPtr->width;
+ *heightPtr = imagePtr->masterPtr->height;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_DeleteImage --
+ *
+ * Given the name of an image, this function destroys the image.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The image is destroyed; existing instances will display as blank
+ * areas. If no such image exists then the function does nothing.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_DeleteImage(
+ Tcl_Interp *interp, /* Interpreter in which the image was
+ * created. */
+ const char *name) /* Name of image. */
+{
+ Tcl_HashEntry *hPtr;
+ TkWindow *winPtr;
+
+ winPtr = (TkWindow *) Tk_MainWindow(interp);
+ if (winPtr == NULL) {
+ return;
+ }
+ hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, name);
+ if (hPtr == NULL) {
+ return;
+ }
+ DeleteImage(Tcl_GetHashValue(hPtr));
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DeleteImage --
+ *
+ * This function is responsible for deleting an image.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The connection is dropped between instances of this image and an image
+ * master. Image instances will redisplay themselves as empty areas, but
+ * existing instances will not be deleted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DeleteImage(
+ ImageMaster *masterPtr) /* Pointer to main data structure for image. */
+{
+ Image *imagePtr;
+ Tk_ImageType *typePtr;
+
+ typePtr = masterPtr->typePtr;
+ masterPtr->typePtr = NULL;
+ if (typePtr != NULL) {
+ for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
+ imagePtr = imagePtr->nextPtr) {
+ typePtr->freeProc(imagePtr->instanceData, imagePtr->display);
+ imagePtr->changeProc(imagePtr->widgetClientData, 0, 0,
+ masterPtr->width, masterPtr->height, masterPtr->width,
+ masterPtr->height);
+ }
+ typePtr->deleteProc(masterPtr->masterData);
+ }
+ if (masterPtr->instancePtr == NULL) {
+ if (masterPtr->hPtr != NULL) {
+ Tcl_DeleteHashEntry(masterPtr->hPtr);
+ }
+ Tcl_Release(masterPtr->winPtr);
+ ckfree(masterPtr);
+ } else {
+ masterPtr->deleted = 1;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EventuallyDeleteImage --
+ *
+ * Arrange for an image to be deleted when it is safe to do so.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Image will get freed, though not until it is no longer Tcl_Preserve()d
+ * by anything. May be called multiple times on the same image without
+ * ill effects.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+EventuallyDeleteImage(
+ ImageMaster *masterPtr, /* Pointer to main data structure for image. */
+ int forgetImageHashNow) /* Flag to say whether the hash table is about
+ * to vanish. */
+{
+ if (forgetImageHashNow) {
+ masterPtr->hPtr = NULL;
+ }
+ if (!masterPtr->deleted) {
+ masterPtr->deleted = 1;
+ Tcl_EventuallyFree(masterPtr, (Tcl_FreeProc *) DeleteImage);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkDeleteAllImages --
+ *
+ * This function is called when an application is deleted. It calls back
+ * all of the managers for all images so that they can cleanup, then it
+ * deletes all of Tk's internal information about images.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * All information for all images gets deleted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkDeleteAllImages(
+ TkMainInfo *mainPtr) /* Structure describing application that is
+ * going away. */
+{
+ Tcl_HashSearch search;
+ Tcl_HashEntry *hPtr;
+
+ for (hPtr = Tcl_FirstHashEntry(&mainPtr->imageTable, &search);
+ hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
+ EventuallyDeleteImage(Tcl_GetHashValue(hPtr), 1);
+ }
+ Tcl_DeleteHashTable(&mainPtr->imageTable);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetImageMasterData --
+ *
+ * Given the name of an image, this function returns the type of the
+ * image and the clientData associated with its master.
+ *
+ * Results:
+ * If there is no image by the given name, then NULL is returned and a
+ * NULL value is stored at *typePtrPtr. Otherwise the return value is the
+ * clientData returned by the createProc when the image was created and a
+ * pointer to the type structure for the image is stored at *typePtrPtr.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ClientData
+Tk_GetImageMasterData(
+ Tcl_Interp *interp, /* Interpreter in which the image was
+ * created. */
+ const char *name, /* Name of image. */
+ const Tk_ImageType **typePtrPtr)
+ /* Points to location to fill in with pointer
+ * to type information for image. */
+{
+ TkWindow *winPtr = (TkWindow *) Tk_MainWindow(interp);
+ Tcl_HashEntry *hPtr;
+ ImageMaster *masterPtr;
+
+ hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, name);
+ if (hPtr == NULL) {
+ *typePtrPtr = NULL;
+ return NULL;
+ }
+ masterPtr = Tcl_GetHashValue(hPtr);
+ if (masterPtr->deleted) {
+ *typePtrPtr = NULL;
+ return NULL;
+ }
+ *typePtrPtr = masterPtr->typePtr;
+ return masterPtr->masterData;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_SetTSOrigin --
+ *
+ * Set the pattern origin of the tile to a common point (i.e. the origin
+ * (0,0) of the top level window) so that tiles from two different
+ * widgets will match up. This done by setting the GCTileStipOrigin field
+ * is set to the translated origin of the toplevel window in the
+ * hierarchy.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * The GCTileStipOrigin is reset in the GC. This will cause the tile
+ * origin to change when the GC is used for drawing.
+ *
+ *----------------------------------------------------------------------
+ */
+
+/*ARGSUSED*/
+void
+Tk_SetTSOrigin(
+ Tk_Window tkwin,
+ GC gc,
+ int x, int y)
+{
+ while (!Tk_TopWinHierarchy(tkwin)) {
+ x -= Tk_X(tkwin) + Tk_Changes(tkwin)->border_width;
+ y -= Tk_Y(tkwin) + Tk_Changes(tkwin)->border_width;
+ tkwin = Tk_Parent(tkwin);
+ }
+ XSetTSOrigin(Tk_Display(tkwin), gc, x, y);
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkImgBmap.c b/tk8.6/generic/tkImgBmap.c
new file mode 100644
index 0000000..f4ee407
--- /dev/null
+++ b/tk8.6/generic/tkImgBmap.c
@@ -0,0 +1,1323 @@
+/*
+ * tkImgBmap.c --
+ *
+ * This procedure implements images of type "bitmap" for Tk.
+ *
+ * Copyright (c) 1994 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1999 by Scriptics Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkInt.h"
+
+/*
+ * The following data structure represents the master for a bitmap
+ * image:
+ */
+
+typedef struct BitmapMaster {
+ Tk_ImageMaster tkMaster; /* Tk's token for image master. NULL means the
+ * image is being deleted. */
+ Tcl_Interp *interp; /* Interpreter for application that is using
+ * image. */
+ Tcl_Command imageCmd; /* Token for image command (used to delete it
+ * when the image goes away). NULL means the
+ * image command has already been deleted. */
+ int width, height; /* Dimensions of image. */
+ char *data; /* Data comprising bitmap (suitable for input
+ * to XCreateBitmapFromData). May be NULL if
+ * no data. Malloc'ed. */
+ char *maskData; /* Data for bitmap's mask (suitable for input
+ * to XCreateBitmapFromData). Malloc'ed. */
+ Tk_Uid fgUid; /* Value of -foreground option (malloc'ed). */
+ Tk_Uid bgUid; /* Value of -background option (malloc'ed). */
+ char *fileString; /* Value of -file option (malloc'ed). */
+ char *dataString; /* Value of -data option (malloc'ed). */
+ char *maskFileString; /* Value of -maskfile option (malloc'ed). */
+ char *maskDataString; /* Value of -maskdata option (malloc'ed). */
+ struct BitmapInstance *instancePtr;
+ /* First in list of all instances associated
+ * with this master. */
+} BitmapMaster;
+
+/*
+ * The following data structure represents all of the instances of an image
+ * that lie within a particular window:
+ */
+
+typedef struct BitmapInstance {
+ int refCount; /* Number of instances that share this data
+ * structure. */
+ BitmapMaster *masterPtr; /* Pointer to master for image. */
+ Tk_Window tkwin; /* Window in which the instances will be
+ * displayed. */
+ XColor *fg; /* Foreground color for displaying image. */
+ XColor *bg; /* Background color for displaying image. */
+ Pixmap bitmap; /* The bitmap to display. */
+ Pixmap mask; /* Mask: only display bitmap pixels where
+ * there are 1's here. */
+ GC gc; /* Graphics context for displaying bitmap.
+ * None means there was an error while setting
+ * up the instance, so it cannot be
+ * displayed. */
+ struct BitmapInstance *nextPtr;
+ /* Next in list of all instance structures
+ * associated with masterPtr (NULL means end
+ * of list). */
+} BitmapInstance;
+
+/*
+ * The type record for bitmap images:
+ */
+
+static int GetByte(Tcl_Channel chan);
+static int ImgBmapCreate(Tcl_Interp *interp,
+ const char *name, int argc, Tcl_Obj *const objv[],
+ const Tk_ImageType *typePtr, Tk_ImageMaster master,
+ ClientData *clientDataPtr);
+static ClientData ImgBmapGet(Tk_Window tkwin, ClientData clientData);
+static void ImgBmapDisplay(ClientData clientData,
+ Display *display, Drawable drawable,
+ int imageX, int imageY, int width, int height,
+ int drawableX, int drawableY);
+static void ImgBmapFree(ClientData clientData, Display *display);
+static void ImgBmapDelete(ClientData clientData);
+static int ImgBmapPostscript(ClientData clientData,
+ Tcl_Interp *interp, Tk_Window tkwin,
+ Tk_PostscriptInfo psinfo, int x, int y,
+ int width, int height, int prepass);
+
+Tk_ImageType tkBitmapImageType = {
+ "bitmap", /* name */
+ ImgBmapCreate, /* createProc */
+ ImgBmapGet, /* getProc */
+ ImgBmapDisplay, /* displayProc */
+ ImgBmapFree, /* freeProc */
+ ImgBmapDelete, /* deleteProc */
+ ImgBmapPostscript, /* postscriptProc */
+ NULL, /* nextPtr */
+ NULL
+};
+
+/*
+ * Information used for parsing configuration specs:
+ */
+
+static const Tk_ConfigSpec configSpecs[] = {
+ {TK_CONFIG_UID, "-background", NULL, NULL,
+ "", Tk_Offset(BitmapMaster, bgUid), 0, NULL},
+ {TK_CONFIG_STRING, "-data", NULL, NULL,
+ NULL, Tk_Offset(BitmapMaster, dataString), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_STRING, "-file", NULL, NULL,
+ NULL, Tk_Offset(BitmapMaster, fileString), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_UID, "-foreground", NULL, NULL,
+ "#000000", Tk_Offset(BitmapMaster, fgUid), 0, NULL},
+ {TK_CONFIG_STRING, "-maskdata", NULL, NULL,
+ NULL, Tk_Offset(BitmapMaster, maskDataString), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_STRING, "-maskfile", NULL, NULL,
+ NULL, Tk_Offset(BitmapMaster, maskFileString), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}
+};
+
+/*
+ * The following data structure is used to describe the state of parsing a
+ * bitmap file or string. It is used for communication between TkGetBitmapData
+ * and NextBitmapWord.
+ */
+
+#define MAX_WORD_LENGTH 100
+typedef struct ParseInfo {
+ const char *string; /* Next character of string data for bitmap,
+ * or NULL if bitmap is being read from
+ * file. */
+ Tcl_Channel chan; /* File containing bitmap data, or NULL if no
+ * file. */
+ char word[MAX_WORD_LENGTH+1];
+ /* Current word of bitmap data, NULL
+ * terminated. */
+ int wordLength; /* Number of non-NULL bytes in word. */
+} ParseInfo;
+
+/*
+ * Prototypes for procedures used only locally in this file:
+ */
+
+static int ImgBmapCmd(ClientData clientData, Tcl_Interp *interp,
+ int argc, Tcl_Obj *const objv[]);
+static void ImgBmapCmdDeletedProc(ClientData clientData);
+static void ImgBmapConfigureInstance(BitmapInstance *instancePtr);
+static int ImgBmapConfigureMaster(BitmapMaster *masterPtr,
+ int argc, Tcl_Obj *const objv[], int flags);
+static int NextBitmapWord(ParseInfo *parseInfoPtr);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImgBmapCreate --
+ *
+ * This procedure is called by the Tk image code to create "test" images.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * The data structure for a new image is allocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+ImgBmapCreate(
+ Tcl_Interp *interp, /* Interpreter for application containing
+ * image. */
+ const char *name, /* Name to use for image. */
+ int argc, /* Number of arguments. */
+ Tcl_Obj *const argv[], /* Argument objects for options (doesn't
+ * include image name or type). */
+ const Tk_ImageType *typePtr,/* Pointer to our type record (not used). */
+ Tk_ImageMaster master, /* Token for image, to be used by us in later
+ * callbacks. */
+ ClientData *clientDataPtr) /* Store manager's token for image here; it
+ * will be returned in later callbacks. */
+{
+ BitmapMaster *masterPtr = ckalloc(sizeof(BitmapMaster));
+
+ masterPtr->tkMaster = master;
+ masterPtr->interp = interp;
+ masterPtr->imageCmd = Tcl_CreateObjCommand(interp, name, ImgBmapCmd,
+ masterPtr, ImgBmapCmdDeletedProc);
+ masterPtr->width = masterPtr->height = 0;
+ masterPtr->data = NULL;
+ masterPtr->maskData = NULL;
+ masterPtr->fgUid = NULL;
+ masterPtr->bgUid = NULL;
+ masterPtr->fileString = NULL;
+ masterPtr->dataString = NULL;
+ masterPtr->maskFileString = NULL;
+ masterPtr->maskDataString = NULL;
+ masterPtr->instancePtr = NULL;
+ if (ImgBmapConfigureMaster(masterPtr, argc, argv, 0) != TCL_OK) {
+ ImgBmapDelete(masterPtr);
+ return TCL_ERROR;
+ }
+ *clientDataPtr = masterPtr;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImgBmapConfigureMaster --
+ *
+ * This procedure is called when a bitmap image is created or
+ * reconfigured. It process configuration options and resets any
+ * instances of the image.
+ *
+ * Results:
+ * A standard Tcl return value. If TCL_ERROR is returned then an error
+ * message is left in the masterPtr->interp's result.
+ *
+ * Side effects:
+ * Existing instances of the image will be redisplayed to match the new
+ * configuration options.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ImgBmapConfigureMaster(
+ BitmapMaster *masterPtr, /* Pointer to data structure describing
+ * overall bitmap image to (reconfigure). */
+ int objc, /* Number of entries in objv. */
+ Tcl_Obj *const objv[], /* Pairs of configuration options for image. */
+ int flags) /* Flags to pass to Tk_ConfigureWidget, such
+ * as TK_CONFIG_ARGV_ONLY. */
+{
+ BitmapInstance *instancePtr;
+ int maskWidth, maskHeight, dummy1, dummy2;
+ const char **argv = ckalloc((objc+1) * sizeof(char *));
+
+ for (dummy1 = 0; dummy1 < objc; dummy1++) {
+ argv[dummy1] = Tcl_GetString(objv[dummy1]);
+ }
+ argv[objc] = NULL;
+
+ if (Tk_ConfigureWidget(masterPtr->interp, Tk_MainWindow(masterPtr->interp),
+ configSpecs, objc, argv, (char *) masterPtr, flags) != TCL_OK) {
+ ckfree(argv);
+ return TCL_ERROR;
+ }
+ ckfree(argv);
+
+ /*
+ * Parse the bitmap and/or mask to create binary data. Make sure that the
+ * bitmap and mask have the same dimensions.
+ */
+
+ if (masterPtr->data != NULL) {
+ ckfree(masterPtr->data);
+ masterPtr->data = NULL;
+ }
+ if ((masterPtr->fileString != NULL) || (masterPtr->dataString != NULL)) {
+ masterPtr->data = TkGetBitmapData(masterPtr->interp,
+ masterPtr->dataString, masterPtr->fileString,
+ &masterPtr->width, &masterPtr->height, &dummy1, &dummy2);
+ if (masterPtr->data == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ if (masterPtr->maskData != NULL) {
+ ckfree(masterPtr->maskData);
+ masterPtr->maskData = NULL;
+ }
+ if ((masterPtr->maskFileString != NULL)
+ || (masterPtr->maskDataString != NULL)) {
+ if (masterPtr->data == NULL) {
+ Tcl_SetObjResult(masterPtr->interp, Tcl_NewStringObj(
+ "can't have mask without bitmap", -1));
+ Tcl_SetErrorCode(masterPtr->interp, "TK", "IMAGE", "BITMAP",
+ "NO_BITMAP", NULL);
+ return TCL_ERROR;
+ }
+ masterPtr->maskData = TkGetBitmapData(masterPtr->interp,
+ masterPtr->maskDataString, masterPtr->maskFileString,
+ &maskWidth, &maskHeight, &dummy1, &dummy2);
+ if (masterPtr->maskData == NULL) {
+ return TCL_ERROR;
+ }
+ if ((maskWidth != masterPtr->width)
+ || (maskHeight != masterPtr->height)) {
+ ckfree(masterPtr->maskData);
+ masterPtr->maskData = NULL;
+ Tcl_SetObjResult(masterPtr->interp, Tcl_NewStringObj(
+ "bitmap and mask have different sizes", -1));
+ Tcl_SetErrorCode(masterPtr->interp, "TK", "IMAGE", "BITMAP",
+ "MASK_SIZE", NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * Cycle through all of the instances of this image, regenerating the
+ * information for each instance. Then force the image to be redisplayed
+ * everywhere that it is used.
+ */
+
+ for (instancePtr = masterPtr->instancePtr; instancePtr != NULL;
+ instancePtr = instancePtr->nextPtr) {
+ ImgBmapConfigureInstance(instancePtr);
+ }
+ Tk_ImageChanged(masterPtr->tkMaster, 0, 0, masterPtr->width,
+ masterPtr->height, masterPtr->width, masterPtr->height);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImgBmapConfigureInstance --
+ *
+ * This procedure is called to create displaying information for a bitmap
+ * image instance based on the configuration information in the master.
+ * It is invoked both when new instances are created and when the master
+ * is reconfigured.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Generates errors via Tcl_BackgroundException if there are problems in
+ * setting up the instance.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ImgBmapConfigureInstance(
+ BitmapInstance *instancePtr)/* Instance to reconfigure. */
+{
+ BitmapMaster *masterPtr = instancePtr->masterPtr;
+ XColor *colorPtr;
+ XGCValues gcValues;
+ GC gc;
+ unsigned int mask;
+ Pixmap oldBitmap, oldMask;
+
+ /*
+ * For each of the options in masterPtr, translate the string form into an
+ * internal form appropriate for instancePtr.
+ */
+
+ if (*masterPtr->bgUid != 0) {
+ colorPtr = Tk_GetColor(masterPtr->interp, instancePtr->tkwin,
+ masterPtr->bgUid);
+ if (colorPtr == NULL) {
+ goto error;
+ }
+ } else {
+ colorPtr = NULL;
+ }
+ if (instancePtr->bg != NULL) {
+ Tk_FreeColor(instancePtr->bg);
+ }
+ instancePtr->bg = colorPtr;
+
+ colorPtr = Tk_GetColor(masterPtr->interp, instancePtr->tkwin,
+ masterPtr->fgUid);
+ if (colorPtr == NULL) {
+ goto error;
+ }
+ if (instancePtr->fg != NULL) {
+ Tk_FreeColor(instancePtr->fg);
+ }
+ instancePtr->fg = colorPtr;
+
+ /*
+ * Careful: We have to allocate new Pixmaps before deleting the old ones.
+ * Otherwise, The XID allocator will always return the same XID for the
+ * new Pixmaps as was used for the old Pixmaps. And that will prevent the
+ * data and/or mask from changing in the GC below.
+ */
+
+ oldBitmap = instancePtr->bitmap;
+ instancePtr->bitmap = None;
+ oldMask = instancePtr->mask;
+ instancePtr->mask = None;
+
+ if (masterPtr->data != NULL) {
+ instancePtr->bitmap = XCreateBitmapFromData(
+ Tk_Display(instancePtr->tkwin),
+ RootWindowOfScreen(Tk_Screen(instancePtr->tkwin)),
+ masterPtr->data, (unsigned) masterPtr->width,
+ (unsigned) masterPtr->height);
+ }
+ if (masterPtr->maskData != NULL) {
+ instancePtr->mask = XCreateBitmapFromData(
+ Tk_Display(instancePtr->tkwin),
+ RootWindowOfScreen(Tk_Screen(instancePtr->tkwin)),
+ masterPtr->maskData, (unsigned) masterPtr->width,
+ (unsigned) masterPtr->height);
+ }
+
+ if (oldMask != None) {
+ Tk_FreePixmap(Tk_Display(instancePtr->tkwin), oldMask);
+ }
+ if (oldBitmap != None) {
+ Tk_FreePixmap(Tk_Display(instancePtr->tkwin), oldBitmap);
+ }
+
+ if (masterPtr->data != NULL) {
+ gcValues.foreground = instancePtr->fg->pixel;
+ gcValues.graphics_exposures = False;
+ mask = GCForeground|GCGraphicsExposures;
+ if (instancePtr->bg != NULL) {
+ gcValues.background = instancePtr->bg->pixel;
+ mask |= GCBackground;
+ if (instancePtr->mask != None) {
+ gcValues.clip_mask = instancePtr->mask;
+ mask |= GCClipMask;
+ }
+ } else {
+ gcValues.clip_mask = instancePtr->bitmap;
+ mask |= GCClipMask;
+ }
+ gc = Tk_GetGC(instancePtr->tkwin, mask, &gcValues);
+ } else {
+ gc = NULL;
+ }
+ if (instancePtr->gc != NULL) {
+ Tk_FreeGC(Tk_Display(instancePtr->tkwin), instancePtr->gc);
+ }
+ instancePtr->gc = gc;
+ return;
+
+ error:
+ /*
+ * An error occurred: clear the graphics context in the instance to make
+ * it clear that this instance cannot be displayed. Then report the error.
+ */
+
+ if (instancePtr->gc != NULL) {
+ Tk_FreeGC(Tk_Display(instancePtr->tkwin), instancePtr->gc);
+ }
+ instancePtr->gc = NULL;
+ Tcl_AppendObjToErrorInfo(masterPtr->interp, Tcl_ObjPrintf(
+ "\n (while configuring image \"%s\")", Tk_NameOfImage(
+ masterPtr->tkMaster)));
+ Tcl_BackgroundException(masterPtr->interp, TCL_ERROR);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkGetBitmapData --
+ *
+ * Given a file name or ASCII string, this procedure parses the file or
+ * string contents to produce binary data for a bitmap.
+ *
+ * Results:
+ * If the bitmap description was parsed successfully then the return
+ * value is a malloc-ed array containing the bitmap data. The dimensions
+ * of the data are stored in *widthPtr and *heightPtr. *hotXPtr and
+ * *hotYPtr are set to the bitmap hotspot if one is defined, otherwise
+ * they are set to -1, -1. If an error occurred, NULL is returned and an
+ * error message is left in the interp's result.
+ *
+ * Side effects:
+ * A bitmap is created.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+TkGetBitmapData(
+ Tcl_Interp *interp, /* For reporting errors, or NULL. */
+ const char *string, /* String describing bitmap. May be NULL. */
+ const char *fileName, /* Name of file containing bitmap description.
+ * Used only if string is NULL. Must not be
+ * NULL if string is NULL. */
+ int *widthPtr, int *heightPtr,
+ /* Dimensions of bitmap get returned here. */
+ int *hotXPtr, int *hotYPtr) /* Position of hot spot or -1,-1. */
+{
+ int width, height, numBytes, hotX, hotY;
+ const char *expandedFileName;
+ char *p, *end;
+ ParseInfo pi;
+ char *data = NULL;
+ Tcl_DString buffer;
+
+ pi.string = string;
+ if (string == NULL) {
+ if ((interp != NULL) && Tcl_IsSafe(interp)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "can't get bitmap data from a file in a safe interpreter",
+ -1));
+ Tcl_SetErrorCode(interp, "TK", "SAFE", "BITMAP_FILE", NULL);
+ return NULL;
+ }
+ expandedFileName = Tcl_TranslateFileName(interp, fileName, &buffer);
+ if (expandedFileName == NULL) {
+ return NULL;
+ }
+ pi.chan = Tcl_OpenFileChannel(interp, expandedFileName, "r", 0);
+ Tcl_DStringFree(&buffer);
+ if (pi.chan == NULL) {
+ if (interp != NULL) {
+ Tcl_ResetResult(interp);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "couldn't read bitmap file \"%s\": %s",
+ fileName, Tcl_PosixError(interp)));
+ }
+ return NULL;
+ }
+
+ if (Tcl_SetChannelOption(interp, pi.chan, "-translation", "binary")
+ != TCL_OK) {
+ return NULL;
+ }
+ if (Tcl_SetChannelOption(interp, pi.chan, "-encoding", "binary")
+ != TCL_OK) {
+ return NULL;
+ }
+ } else {
+ pi.chan = NULL;
+ }
+
+ /*
+ * Parse the lines that define the dimensions of the bitmap, plus the
+ * first line that defines the bitmap data (it declares the name of a data
+ * variable but doesn't include any actual data). These lines look
+ * something like the following:
+ *
+ * #define foo_width 16
+ * #define foo_height 16
+ * #define foo_x_hot 3
+ * #define foo_y_hot 3
+ * static char foo_bits[] = {
+ *
+ * The x_hot and y_hot lines may or may not be present. It's important to
+ * check for "char" in the last line, in order to reject old X10-style
+ * bitmaps that used shorts.
+ */
+
+ width = 0;
+ height = 0;
+ hotX = -1;
+ hotY = -1;
+ while (1) {
+ if (NextBitmapWord(&pi) != TCL_OK) {
+ goto error;
+ }
+ if ((pi.wordLength >= 6) && (pi.word[pi.wordLength-6] == '_')
+ && (strcmp(pi.word+pi.wordLength-6, "_width") == 0)) {
+ if (NextBitmapWord(&pi) != TCL_OK) {
+ goto error;
+ }
+ width = strtol(pi.word, &end, 0);
+ if ((end == pi.word) || (*end != 0)) {
+ goto error;
+ }
+ } else if ((pi.wordLength >= 7) && (pi.word[pi.wordLength-7] == '_')
+ && (strcmp(pi.word+pi.wordLength-7, "_height") == 0)) {
+ if (NextBitmapWord(&pi) != TCL_OK) {
+ goto error;
+ }
+ height = strtol(pi.word, &end, 0);
+ if ((end == pi.word) || (*end != 0)) {
+ goto error;
+ }
+ } else if ((pi.wordLength >= 6) && (pi.word[pi.wordLength-6] == '_')
+ && (strcmp(pi.word+pi.wordLength-6, "_x_hot") == 0)) {
+ if (NextBitmapWord(&pi) != TCL_OK) {
+ goto error;
+ }
+ hotX = strtol(pi.word, &end, 0);
+ if ((end == pi.word) || (*end != 0)) {
+ goto error;
+ }
+ } else if ((pi.wordLength >= 6) && (pi.word[pi.wordLength-6] == '_')
+ && (strcmp(pi.word+pi.wordLength-6, "_y_hot") == 0)) {
+ if (NextBitmapWord(&pi) != TCL_OK) {
+ goto error;
+ }
+ hotY = strtol(pi.word, &end, 0);
+ if ((end == pi.word) || (*end != 0)) {
+ goto error;
+ }
+ } else if ((pi.word[0] == 'c') && (strcmp(pi.word, "char") == 0)) {
+ while (1) {
+ if (NextBitmapWord(&pi) != TCL_OK) {
+ goto error;
+ }
+ if ((pi.word[0] == '{') && (pi.word[1] == 0)) {
+ goto getData;
+ }
+ }
+ } else if ((pi.word[0] == '{') && (pi.word[1] == 0)) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "format error in bitmap data; looks like it's an"
+ " obsolete X10 bitmap file", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "BITMAP", "OBSOLETE",
+ NULL);
+ }
+ goto errorCleanup;
+ }
+ }
+
+ /*
+ * Now we've read everything but the data. Allocate an array and read in
+ * the data.
+ */
+
+ getData:
+ if ((width <= 0) || (height <= 0)) {
+ goto error;
+ }
+ numBytes = ((width+7)/8) * height;
+ data = ckalloc(numBytes);
+ for (p = data; numBytes > 0; p++, numBytes--) {
+ if (NextBitmapWord(&pi) != TCL_OK) {
+ goto error;
+ }
+ *p = (char) strtol(pi.word, &end, 0);
+ if (end == pi.word) {
+ goto error;
+ }
+ }
+
+ /*
+ * All done. Clean up and return.
+ */
+
+ if (pi.chan != NULL) {
+ Tcl_Close(NULL, pi.chan);
+ }
+ *widthPtr = width;
+ *heightPtr = height;
+ *hotXPtr = hotX;
+ *hotYPtr = hotY;
+ return data;
+
+ error:
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "format error in bitmap data", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "BITMAP", "FORMAT", NULL);
+ }
+
+ errorCleanup:
+ if (data != NULL) {
+ ckfree(data);
+ }
+ if (pi.chan != NULL) {
+ Tcl_Close(NULL, pi.chan);
+ }
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NextBitmapWord --
+ *
+ * This procedure retrieves the next word of information (stuff between
+ * commas or white space) from a bitmap description.
+ *
+ * Results:
+ * Returns TCL_OK if all went well. In this case the next word, and its
+ * length, will be availble in *parseInfoPtr. If the end of the bitmap
+ * description was reached then TCL_ERROR is returned.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+NextBitmapWord(
+ ParseInfo *parseInfoPtr) /* Describes what we're reading and where we
+ * are in it. */
+{
+ const char *src;
+ char *dst;
+ int c;
+
+ parseInfoPtr->wordLength = 0;
+ dst = parseInfoPtr->word;
+ if (parseInfoPtr->string != NULL) {
+ for (src = parseInfoPtr->string; isspace(UCHAR(*src)) || (*src == ',');
+ src++) {
+ if (*src == 0) {
+ return TCL_ERROR;
+ }
+ }
+ for ( ; !isspace(UCHAR(*src)) && (*src != ',') && (*src != 0); src++) {
+ *dst = *src;
+ dst++;
+ parseInfoPtr->wordLength++;
+ if (parseInfoPtr->wordLength > MAX_WORD_LENGTH) {
+ return TCL_ERROR;
+ }
+ }
+ parseInfoPtr->string = src;
+ } else {
+ for (c = GetByte(parseInfoPtr->chan); isspace(UCHAR(c)) || (c == ',');
+ c = GetByte(parseInfoPtr->chan)) {
+ if (c == EOF) {
+ return TCL_ERROR;
+ }
+ }
+ for ( ; !isspace(UCHAR(c)) && (c != ',') && (c != EOF);
+ c = GetByte(parseInfoPtr->chan)) {
+ *dst = c;
+ dst++;
+ parseInfoPtr->wordLength++;
+ if (parseInfoPtr->wordLength > MAX_WORD_LENGTH) {
+ return TCL_ERROR;
+ }
+ }
+ }
+ if (parseInfoPtr->wordLength == 0) {
+ return TCL_ERROR;
+ }
+ parseInfoPtr->word[parseInfoPtr->wordLength] = 0;
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ImgBmapCmd --
+ *
+ * This procedure is invoked to process the Tcl command that corresponds
+ * to an image managed by this module. See the user documentation for
+ * details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+ImgBmapCmd(
+ ClientData clientData, /* Information about the image master. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ static const char *const bmapOptions[] = {"cget", "configure", NULL};
+ BitmapMaster *masterPtr = clientData;
+ int index;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObjStruct(interp, objv[1], bmapOptions,
+ sizeof(char *), "option", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch (index) {
+ case 0: /* cget */
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option");
+ return TCL_ERROR;
+ }
+ return Tk_ConfigureValue(interp, Tk_MainWindow(interp), configSpecs,
+ (char *) masterPtr, Tcl_GetString(objv[2]), 0);
+ case 1: /* configure */
+ if (objc == 2) {
+ return Tk_ConfigureInfo(interp, Tk_MainWindow(interp),
+ configSpecs, (char *) masterPtr, NULL, 0);
+ } else if (objc == 3) {
+ return Tk_ConfigureInfo(interp, Tk_MainWindow(interp),
+ configSpecs, (char *) masterPtr,
+ Tcl_GetString(objv[2]), 0);
+ } else {
+ return ImgBmapConfigureMaster(masterPtr, objc-2, objv+2,
+ TK_CONFIG_ARGV_ONLY);
+ }
+ default:
+ Tcl_Panic("bad const entries to bmapOptions in ImgBmapCmd");
+ return TCL_OK;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImgBmapGet --
+ *
+ * This procedure is called for each use of a bitmap image in a widget.
+ *
+ * Results:
+ * The return value is a token for the instance, which is passed back to
+ * us in calls to ImgBmapDisplay and ImgBmapFree.
+ *
+ * Side effects:
+ * A data structure is set up for the instance (or, an existing instance
+ * is re-used for the new one).
+ *
+ *----------------------------------------------------------------------
+ */
+
+static ClientData
+ImgBmapGet(
+ Tk_Window tkwin, /* Window in which the instance will be
+ * used. */
+ ClientData masterData) /* Pointer to our master structure for the
+ * image. */
+{
+ BitmapMaster *masterPtr = masterData;
+ BitmapInstance *instancePtr;
+
+ /*
+ * See if there is already an instance for this window. If so then just
+ * re-use it.
+ */
+
+ for (instancePtr = masterPtr->instancePtr; instancePtr != NULL;
+ instancePtr = instancePtr->nextPtr) {
+ if (instancePtr->tkwin == tkwin) {
+ instancePtr->refCount++;
+ return instancePtr;
+ }
+ }
+
+ /*
+ * The image isn't already in use in this window. Make a new instance of
+ * the image.
+ */
+
+ instancePtr = ckalloc(sizeof(BitmapInstance));
+ instancePtr->refCount = 1;
+ instancePtr->masterPtr = masterPtr;
+ instancePtr->tkwin = tkwin;
+ instancePtr->fg = NULL;
+ instancePtr->bg = NULL;
+ instancePtr->bitmap = None;
+ instancePtr->mask = None;
+ instancePtr->gc = NULL;
+ instancePtr->nextPtr = masterPtr->instancePtr;
+ masterPtr->instancePtr = instancePtr;
+ ImgBmapConfigureInstance(instancePtr);
+
+ /*
+ * If this is the first instance, must set the size of the image.
+ */
+
+ if (instancePtr->nextPtr == NULL) {
+ Tk_ImageChanged(masterPtr->tkMaster, 0, 0, 0, 0, masterPtr->width,
+ masterPtr->height);
+ }
+
+ return instancePtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImgBmapDisplay --
+ *
+ * This procedure is invoked to draw a bitmap image.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A portion of the image gets rendered in a pixmap or window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ImgBmapDisplay(
+ ClientData clientData, /* Pointer to BitmapInstance structure for
+ * instance to be displayed. */
+ Display *display, /* Display on which to draw image. */
+ Drawable drawable, /* Pixmap or window in which to draw image. */
+ int imageX, int imageY, /* Upper-left corner of region within image to
+ * draw. */
+ int width, int height, /* Dimensions of region within image to draw. */
+ int drawableX, int drawableY)
+ /* Coordinates within drawable that correspond
+ * to imageX and imageY. */
+{
+ BitmapInstance *instancePtr = clientData;
+ int masking;
+
+ /*
+ * If there's no graphics context, it means that an error occurred while
+ * creating the image instance so it can't be displayed.
+ */
+
+ if (instancePtr->gc == NULL) {
+ return;
+ }
+
+ /*
+ * If masking is in effect, must modify the mask origin within the
+ * graphics context to line up with the image's origin. Then draw the
+ * image and reset the clip origin, if there's a mask.
+ */
+
+ masking = (instancePtr->mask != None) || (instancePtr->bg == NULL);
+ if (masking) {
+ XSetClipOrigin(display, instancePtr->gc, drawableX - imageX,
+ drawableY - imageY);
+ }
+ XCopyPlane(display, instancePtr->bitmap, drawable, instancePtr->gc,
+ imageX, imageY, (unsigned) width, (unsigned) height,
+ drawableX, drawableY, 1);
+ if (masking) {
+ XSetClipOrigin(display, instancePtr->gc, 0, 0);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImgBmapFree --
+ *
+ * This procedure is called when a widget ceases to use a particular
+ * instance of an image.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Internal data structures get cleaned up.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ImgBmapFree(
+ ClientData clientData, /* Pointer to BitmapInstance structure for
+ * instance to be displayed. */
+ Display *display) /* Display containing window that used image. */
+{
+ BitmapInstance *instancePtr = clientData;
+ BitmapInstance *prevPtr;
+
+ instancePtr->refCount--;
+ if (instancePtr->refCount > 0) {
+ return;
+ }
+
+ /*
+ * There are no more uses of the image within this widget. Free the
+ * instance structure.
+ */
+
+ if (instancePtr->fg != NULL) {
+ Tk_FreeColor(instancePtr->fg);
+ }
+ if (instancePtr->bg != NULL) {
+ Tk_FreeColor(instancePtr->bg);
+ }
+ if (instancePtr->bitmap != None) {
+ Tk_FreePixmap(display, instancePtr->bitmap);
+ }
+ if (instancePtr->mask != None) {
+ Tk_FreePixmap(display, instancePtr->mask);
+ }
+ if (instancePtr->gc != NULL) {
+ Tk_FreeGC(display, instancePtr->gc);
+ }
+ if (instancePtr->masterPtr->instancePtr == instancePtr) {
+ instancePtr->masterPtr->instancePtr = instancePtr->nextPtr;
+ } else {
+ for (prevPtr = instancePtr->masterPtr->instancePtr;
+ prevPtr->nextPtr != instancePtr; prevPtr = prevPtr->nextPtr) {
+ /* Empty loop body */
+ }
+ prevPtr->nextPtr = instancePtr->nextPtr;
+ }
+ ckfree(instancePtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImgBmapDelete --
+ *
+ * This procedure is called by the image code to delete the master
+ * structure for an image.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Resources associated with the image get freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ImgBmapDelete(
+ ClientData masterData) /* Pointer to BitmapMaster structure for
+ * image. Must not have any more instances. */
+{
+ BitmapMaster *masterPtr = masterData;
+
+ if (masterPtr->instancePtr != NULL) {
+ Tcl_Panic("tried to delete bitmap image when instances still exist");
+ }
+ masterPtr->tkMaster = NULL;
+ if (masterPtr->imageCmd != NULL) {
+ Tcl_DeleteCommandFromToken(masterPtr->interp, masterPtr->imageCmd);
+ }
+ if (masterPtr->data != NULL) {
+ ckfree(masterPtr->data);
+ }
+ if (masterPtr->maskData != NULL) {
+ ckfree(masterPtr->maskData);
+ }
+ Tk_FreeOptions(configSpecs, (char *) masterPtr, NULL, 0);
+ ckfree(masterPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImgBmapCmdDeletedProc --
+ *
+ * This procedure is invoked when the image command for an image is
+ * deleted. It deletes the image.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The image is deleted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ImgBmapCmdDeletedProc(
+ ClientData clientData) /* Pointer to BitmapMaster structure for
+ * image. */
+{
+ BitmapMaster *masterPtr = clientData;
+
+ masterPtr->imageCmd = NULL;
+ if (masterPtr->tkMaster != NULL) {
+ Tk_DeleteImage(masterPtr->interp, Tk_NameOfImage(masterPtr->tkMaster));
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetByte --
+ *
+ * Get the next byte from the open channel.
+ *
+ * Results:
+ * The next byte or EOF.
+ *
+ * Side effects:
+ * We read from the channel.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GetByte(
+ Tcl_Channel chan) /* The channel we read from. */
+{
+ char buffer;
+ int size;
+
+ size = Tcl_Read(chan, &buffer, 1);
+ if (size <= 0) {
+ return EOF;
+ } else {
+ return buffer;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImgBmapPsImagemask --
+ *
+ * This procedure generates postscript suitable for rendering a single
+ * bitmap of an image. A single bitmap image might contain both a
+ * foreground and a background bitmap. This routine is called once for
+ * each such bitmap in a bitmap image.
+ *
+ * Prior to invoking this routine, the following setup has occurred:
+ *
+ * 1. The postscript foreground color has been set to the color used
+ * to render the bitmap.
+ *
+ * 2. The origin of the postscript coordinate system is set to the
+ * lower left corner of the bitmap.
+ *
+ * 3. The postscript coordinate system has been scaled so that the
+ * entire bitmap is one unit squared.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Postscript code is appended to psObj.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ImgBmapPsImagemask(
+ Tcl_Obj *psObj, /* Append postscript to this buffer. */
+ int width, int height, /* Width and height of the bitmap in pixels */
+ char *data) /* Data for the bitmap. */
+{
+ int i, j, nBytePerRow;
+
+ /*
+ * The bit order of bitmaps in Tk is the opposite of the bit order that
+ * postscript uses. (In Tk, the least significant bit is on the right side
+ * of the bitmap and in postscript the least significant bit is shown on
+ * the left.) The following array is used to reverse the order of bits
+ * within a byte so that the bits will be in the order postscript expects.
+ */
+
+ static const unsigned char bit_reverse[] = {
+ 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
+ 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
+ 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
+ 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
+ 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
+ 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
+ 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
+ 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
+ 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
+ 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
+ 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
+ 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
+ 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
+ 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
+ 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
+ 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255,
+ };
+
+ Tcl_AppendPrintfToObj(psObj,
+ "0 0 moveto %d %d true [%d 0 0 %d 0 %d] {<\n",
+ width, height, width, -height, height);
+
+ nBytePerRow = (width + 7) / 8;
+ for (i=0; i<height; i++) {
+ for (j=0; j<nBytePerRow; j++) {
+ Tcl_AppendPrintfToObj(psObj, " %02x",
+ bit_reverse[0xff & data[i*nBytePerRow + j]]);
+ }
+ Tcl_AppendToObj(psObj, "\n", -1);
+ }
+
+ Tcl_AppendToObj(psObj, ">} imagemask \n", -1);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImgBmapPostscript --
+ *
+ * This procedure generates postscript for rendering a bitmap image.
+ *
+ * Results:
+ * On success, this routine writes postscript code into interp->result
+ * and returns TCL_OK TCL_ERROR is returned and an error message is left
+ * in interp->result if anything goes wrong.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ImgBmapPostscript(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ Tk_Window tkwin,
+ Tk_PostscriptInfo psinfo,
+ int x, int y, int width, int height,
+ int prepass)
+{
+ BitmapMaster *masterPtr = clientData;
+ Tcl_InterpState interpState;
+ Tcl_Obj *psObj;
+
+ if (prepass) {
+ return TCL_OK;
+ }
+
+ /*
+ * There is nothing to do for bitmaps with zero width or height.
+ */
+
+ if (width<=0 || height<=0 || masterPtr->width<=0 || masterPtr->height<=0){
+ return TCL_OK;
+ }
+
+ /*
+ * Some postscript implementations cannot handle bitmap strings longer
+ * than about 60k characters. If the bitmap data is that big or bigger,
+ * we bail out.
+ */
+
+ if (masterPtr->width*masterPtr->height > 60000) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "unable to generate postscript for bitmaps larger than 60000"
+ " pixels", -1));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "PS", "MEMLIMIT", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Make our working space.
+ */
+
+ psObj = Tcl_NewObj();
+ interpState = Tcl_SaveInterpState(interp, TCL_OK);
+
+ /*
+ * Translate the origin of the coordinate system to be the lower-left
+ * corner of the bitmap and adjust the scale of the coordinate system so
+ * that entire bitmap covers one square unit of the page. The calling
+ * function put a "gsave" into the postscript and will add a "grestore" at
+ * after this routine returns, so it is safe to make whatever changes are
+ * necessary here.
+ */
+
+ if (x != 0 || y != 0) {
+ Tcl_AppendPrintfToObj(psObj, "%d %d moveto\n", x, y);
+ }
+ if (width != 1 || height != 1) {
+ Tcl_AppendPrintfToObj(psObj, "%d %d scale\n", width, height);
+ }
+
+ /*
+ * Color the background, if there is one. This step is skipped if the
+ * background is transparent. If the background is not transparent and
+ * there is no background mask, then color the complete rectangle that
+ * encloses the bitmap. If there is a background mask, then only apply
+ * color to the bits specified by the mask.
+ */
+
+ if ((masterPtr->bgUid != NULL) && (masterPtr->bgUid[0] != '\000')) {
+ XColor color;
+
+ TkParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), masterPtr->bgUid,
+ &color);
+ Tcl_ResetResult(interp);
+ if (Tk_PostscriptColor(interp, psinfo, &color) != TCL_OK) {
+ goto error;
+ }
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+
+ if (masterPtr->maskData == NULL) {
+ Tcl_AppendToObj(psObj,
+ "0 0 moveto 1 0 rlineto 0 1 rlineto -1 0 rlineto "
+ "closepath fill\n", -1);
+ } else {
+ ImgBmapPsImagemask(psObj, masterPtr->width, masterPtr->height,
+ masterPtr->maskData);
+ }
+ }
+
+ /*
+ * Draw the bitmap foreground, assuming there is one.
+ */
+
+ if ((masterPtr->fgUid != NULL) && (masterPtr->data != NULL)) {
+ XColor color;
+
+ TkParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), masterPtr->fgUid,
+ &color);
+ Tcl_ResetResult(interp);
+ if (Tk_PostscriptColor(interp, psinfo, &color) != TCL_OK) {
+ goto error;
+ }
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+
+ ImgBmapPsImagemask(psObj, masterPtr->width, masterPtr->height,
+ masterPtr->data);
+ }
+
+ /*
+ * Plug the accumulated postscript back into the result.
+ */
+
+ (void) Tcl_RestoreInterpState(interp, interpState);
+ Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj);
+ Tcl_DecrRefCount(psObj);
+ return TCL_OK;
+
+ error:
+ Tcl_DiscardInterpState(interpState);
+ Tcl_DecrRefCount(psObj);
+ return TCL_ERROR;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkImgGIF.c b/tk8.6/generic/tkImgGIF.c
new file mode 100644
index 0000000..76e48d4
--- /dev/null
+++ b/tk8.6/generic/tkImgGIF.c
@@ -0,0 +1,2255 @@
+/*
+ * tkImgGIF.c --
+ *
+ * A photo image file handler for GIF files. Reads 87a and 89a GIF files.
+ * At present, there only is a file write function. GIF images may be
+ * read using the -data option of the photo image. The data may be given
+ * as a binary string in a Tcl_Obj or by representing the data as BASE64
+ * encoded ascii. Derived from the giftoppm code found in the pbmplus
+ * package and tkImgFmtPPM.c in the tk4.0b2 distribution.
+ *
+ * Copyright (c) Reed Wade (wade@cs.utk.edu), University of Tennessee
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1997 Australian National University
+ * Copyright (c) 2005-2010 Donal K. Fellows
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * This file also contains code from the giftoppm program, which is
+ * copyrighted as follows:
+ *
+ * +--------------------------------------------------------------------+
+ * | Copyright 1990, David Koblas. |
+ * | Permission to use, copy, modify, and distribute this software |
+ * | and its documentation for any purpose and without fee is hereby |
+ * | granted, provided that the above copyright notice appear in all |
+ * | copies and that both that copyright notice and this permission |
+ * | notice appear in supporting documentation. This software is |
+ * | provided "as is" without express or implied warranty. |
+ * +--------------------------------------------------------------------+
+ */
+
+#include "tkInt.h"
+
+/*
+ * GIF's are represented as data in either binary or base64 format. base64
+ * strings consist of 4 6-bit characters -> 3 8 bit bytes. A-Z, a-z, 0-9, +
+ * and / represent the 64 values (in order). '=' is a trailing padding char
+ * when the un-encoded data is not a multiple of 3 bytes. We'll ignore white
+ * space when encountered. Any other invalid character is treated as an EOF
+ */
+
+#define GIF_SPECIAL (256)
+#define GIF_PAD (GIF_SPECIAL+1)
+#define GIF_SPACE (GIF_SPECIAL+2)
+#define GIF_BAD (GIF_SPECIAL+3)
+#define GIF_DONE (GIF_SPECIAL+4)
+
+/*
+ * structure to "mimic" FILE for Mread, so we can look like fread. The decoder
+ * state keeps track of which byte we are about to read, or EOF.
+ */
+
+typedef struct mFile {
+ unsigned char *data; /* mmencoded source string */
+ int c; /* bits left over from previous character */
+ int state; /* decoder state (0-4 or GIF_DONE) */
+ int length; /* Total amount of bytes in data */
+} MFile;
+
+/*
+ * Non-ASCII encoding support:
+ * Most data in a GIF image is binary and is treated as such. However, a few
+ * key bits are stashed in ASCII. If we try to compare those pieces to the
+ * char they represent, it will fail on any non-ASCII (eg, EBCDIC) system. To
+ * accommodate these systems, we test against the numeric value of the ASCII
+ * characters instead of the characters themselves. This is encoding
+ * independent.
+ */
+
+static const char GIF87a[] = { /* ASCII GIF87a */
+ 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x00
+};
+static const char GIF89a[] = { /* ASCII GIF89a */
+ 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x00
+};
+#define GIF_TERMINATOR 0x3b /* ASCII ; */
+#define GIF_EXTENSION 0x21 /* ASCII ! */
+#define GIF_START 0x2c /* ASCII , */
+
+/*
+ * Flags used to notify that we've got inline data instead of a file to read
+ * from. Note that we need to figure out which type of inline data we've got
+ * before handing off to the GIF reading code; this is done in StringReadGIF.
+ */
+
+#define INLINE_DATA_BINARY ((const char *) 0x01)
+#define INLINE_DATA_BASE64 ((const char *) 0x02)
+
+/*
+ * HACK ALERT!! HACK ALERT!! HACK ALERT!!
+ * This code is hard-wired for reading from files. In order to read from a
+ * data stream, we'll trick fread so we can reuse the same code. 0==from file;
+ * 1==from base64 encoded data; 2==from binary data
+ */
+
+typedef struct {
+ const char *fromData;
+ unsigned char workingBuffer[280];
+ struct {
+ int bytes;
+ int done;
+ unsigned int window;
+ int bitsInWindow;
+ unsigned char *c;
+ } reader;
+} GIFImageConfig;
+
+/*
+ * Type of a function used to do the writing to a file or buffer when
+ * serializing in the GIF format.
+ */
+
+typedef int (WriteBytesFunc) (ClientData clientData, const char *bytes,
+ int byteCount);
+
+/*
+ * The format record for the GIF file format:
+ */
+
+static int FileMatchGIF(Tcl_Channel chan, const char *fileName,
+ Tcl_Obj *format, int *widthPtr, int *heightPtr,
+ Tcl_Interp *interp);
+static int FileReadGIF(Tcl_Interp *interp, Tcl_Channel chan,
+ const char *fileName, Tcl_Obj *format,
+ Tk_PhotoHandle imageHandle, int destX, int destY,
+ int width, int height, int srcX, int srcY);
+static int StringMatchGIF(Tcl_Obj *dataObj, Tcl_Obj *format,
+ int *widthPtr, int *heightPtr, Tcl_Interp *interp);
+static int StringReadGIF(Tcl_Interp *interp, Tcl_Obj *dataObj,
+ Tcl_Obj *format, Tk_PhotoHandle imageHandle,
+ int destX, int destY, int width, int height,
+ int srcX, int srcY);
+static int FileWriteGIF(Tcl_Interp *interp, const char *filename,
+ Tcl_Obj *format, Tk_PhotoImageBlock *blockPtr);
+static int StringWriteGIF(Tcl_Interp *interp, Tcl_Obj *format,
+ Tk_PhotoImageBlock *blockPtr);
+static int CommonWriteGIF(Tcl_Interp *interp, ClientData clientData,
+ WriteBytesFunc *writeProc, Tcl_Obj *format,
+ Tk_PhotoImageBlock *blockPtr);
+
+Tk_PhotoImageFormat tkImgFmtGIF = {
+ "gif", /* name */
+ FileMatchGIF, /* fileMatchProc */
+ StringMatchGIF, /* stringMatchProc */
+ FileReadGIF, /* fileReadProc */
+ StringReadGIF, /* stringReadProc */
+ FileWriteGIF, /* fileWriteProc */
+ StringWriteGIF, /* stringWriteProc */
+ NULL
+};
+
+#define INTERLACE 0x40
+#define LOCALCOLORMAP 0x80
+#define BitSet(byte, bit) (((byte) & (bit)) == (bit))
+#define MAXCOLORMAPSIZE 256
+#define CM_RED 0
+#define CM_GREEN 1
+#define CM_BLUE 2
+#define CM_ALPHA 3
+#define MAX_LWZ_BITS 12
+#define LM_to_uint(a,b) (((b)<<8)|(a))
+
+/*
+ * Prototypes for local functions defined in this file:
+ */
+
+static int DoExtension(GIFImageConfig *gifConfPtr,
+ Tcl_Channel chan, int label, unsigned char *buffer,
+ int *transparent);
+static int GetCode(Tcl_Channel chan, int code_size, int flag,
+ GIFImageConfig *gifConfPtr);
+static int GetDataBlock(GIFImageConfig *gifConfPtr,
+ Tcl_Channel chan, unsigned char *buf);
+static int ReadColorMap(GIFImageConfig *gifConfPtr,
+ Tcl_Channel chan, int number,
+ unsigned char buffer[MAXCOLORMAPSIZE][4]);
+static int ReadGIFHeader(GIFImageConfig *gifConfPtr,
+ Tcl_Channel chan, int *widthPtr, int *heightPtr);
+static int ReadImage(GIFImageConfig *gifConfPtr,
+ Tcl_Interp *interp, unsigned char *imagePtr,
+ Tcl_Channel chan, int len, int rows,
+ unsigned char cmap[MAXCOLORMAPSIZE][4], int srcX,
+ int srcY, int interlace, int transparent);
+
+/*
+ * these are for the BASE64 image reader code only
+ */
+
+static int Fread(GIFImageConfig *gifConfPtr, unsigned char *dst,
+ size_t size, size_t count, Tcl_Channel chan);
+static int Mread(unsigned char *dst, size_t size, size_t count,
+ MFile *handle);
+static int Mgetc(MFile *handle);
+static int char64(int c);
+static void mInit(unsigned char *string, MFile *handle,
+ int length);
+
+/*
+ * Types, defines and variables needed to write and compress a GIF.
+ */
+
+#define LSB(a) ((unsigned char) (((short)(a)) & 0x00FF))
+#define MSB(a) ((unsigned char) (((short)(a)) >> 8))
+
+#define GIFBITS 12
+#define HSIZE 5003 /* 80% occupancy */
+
+#define DEFAULT_BACKGROUND_VALUE 0xD9
+
+typedef struct {
+ int ssize;
+ int csize;
+ int rsize;
+ unsigned char *pixelOffset;
+ int pixelSize;
+ int pixelPitch;
+ int greenOffset;
+ int blueOffset;
+ int alphaOffset;
+ int num;
+ unsigned char mapa[MAXCOLORMAPSIZE][3];
+} GifWriterState;
+
+typedef int (* ifunptr) (GifWriterState *statePtr);
+
+/*
+ * Support for compression of GIFs.
+ */
+
+#define MAXCODE(numBits) (((long) 1 << (numBits)) - 1)
+
+#ifdef SIGNED_COMPARE_SLOW
+#define U(x) ((unsigned) (x))
+#else
+#define U(x) (x)
+#endif
+
+typedef struct {
+ int numBits; /* Number of bits/code. */
+ long maxCode; /* Maximum code, given numBits. */
+ int hashTable[HSIZE];
+ unsigned int codeTable[HSIZE];
+ long hSize; /* For dynamic table sizing. */
+
+ /*
+ * To save much memory, we overlay the table used by compress() with those
+ * used by decompress(). The tab_prefix table is the same size and type as
+ * the codeTable. The tab_suffix table needs 2**GIFBITS characters. We get
+ * this from the beginning of hashTable. The output stack uses the rest of
+ * hashTable, and contains characters. There is plenty of room for any
+ * possible stack (stack used to be 8000 characters).
+ */
+
+ int freeEntry; /* First unused entry. */
+
+ /*
+ * Block compression parameters. After all codes are used up, and
+ * compression rate changes, start over.
+ */
+
+ int clearFlag;
+
+ int offset;
+ unsigned int inCount; /* Length of input */
+ unsigned int outCount; /* # of codes output (for debugging) */
+
+ /*
+ * Algorithm: use open addressing double hashing (no chaining) on the
+ * prefix code / next character combination. We do a variant of Knuth's
+ * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
+ * secondary probe. Here, the modular division first probe is gives way to
+ * a faster exclusive-or manipulation. Also do block compression with an
+ * adaptive reset, whereby the code table is cleared when the compression
+ * ratio decreases, but after the table fills. The variable-length output
+ * codes are re-sized at this point, and a special CLEAR code is generated
+ * for the decompressor. Late addition: construct the table according to
+ * file size for noticeable speed improvement on small files. Please
+ * direct questions about this implementation to ames!jaw.
+ */
+
+ int initialBits;
+ ClientData destination;
+ WriteBytesFunc *writeProc;
+
+ int clearCode;
+ int eofCode;
+
+ unsigned long currentAccumulated;
+ int currentBits;
+
+ /*
+ * Number of characters so far in this 'packet'
+ */
+
+ int accumulatedByteCount;
+
+ /*
+ * Define the storage for the packet accumulator
+ */
+
+ unsigned char packetAccumulator[256];
+} GIFState_t;
+
+/*
+ * Definition of new functions to write GIFs
+ */
+
+static int ColorNumber(GifWriterState *statePtr,
+ int red, int green, int blue);
+static void Compress(int initBits, ClientData handle,
+ WriteBytesFunc *writeProc, ifunptr readValue,
+ GifWriterState *statePtr);
+static int IsNewColor(GifWriterState *statePtr,
+ int red, int green, int blue);
+static void SaveMap(GifWriterState *statePtr,
+ Tk_PhotoImageBlock *blockPtr);
+static int ReadValue(GifWriterState *statePtr);
+static WriteBytesFunc WriteToChannel;
+static WriteBytesFunc WriteToByteArray;
+static void Output(GIFState_t *statePtr, long code);
+static void ClearForBlock(GIFState_t *statePtr);
+static void ClearHashTable(GIFState_t *statePtr, int hSize);
+static void CharInit(GIFState_t *statePtr);
+static void CharOut(GIFState_t *statePtr, int c);
+static void FlushChar(GIFState_t *statePtr);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileMatchGIF --
+ *
+ * This function is invoked by the photo image type to see if a file
+ * contains image data in GIF format.
+ *
+ * Results:
+ * The return value is 1 if the first characters in file f look like GIF
+ * data, and 0 otherwise.
+ *
+ * Side effects:
+ * The access position in f may change.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+FileMatchGIF(
+ Tcl_Channel chan, /* The image file, open for reading. */
+ const char *fileName, /* The name of the image file. */
+ Tcl_Obj *format, /* User-specified format object, or NULL. */
+ int *widthPtr, int *heightPtr,
+ /* The dimensions of the image are returned
+ * here if the file is a valid raw GIF file. */
+ Tcl_Interp *interp) /* not used */
+{
+ GIFImageConfig gifConf;
+
+ memset(&gifConf, 0, sizeof(GIFImageConfig));
+ return ReadGIFHeader(&gifConf, chan, widthPtr, heightPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileReadGIF --
+ *
+ * This function is called by the photo image type to read GIF format
+ * data from a file and write it into a given photo image.
+ *
+ * Results:
+ * A standard TCL completion code. If TCL_ERROR is returned then an error
+ * message is left in the interp's result.
+ *
+ * Side effects:
+ * The access position in file f is changed, and new data is added to the
+ * image given by imageHandle.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+FileReadGIF(
+ Tcl_Interp *interp, /* Interpreter to use for reporting errors. */
+ Tcl_Channel chan, /* The image file, open for reading. */
+ const char *fileName, /* The name of the image file. */
+ Tcl_Obj *format, /* User-specified format object, or NULL. */
+ Tk_PhotoHandle imageHandle, /* The photo image to write into. */
+ int destX, int destY, /* Coordinates of top-left pixel in photo
+ * image to be written to. */
+ int width, int height, /* Dimensions of block of photo image to be
+ * written to. */
+ int srcX, int srcY) /* Coordinates of top-left pixel to be used in
+ * image being read. */
+{
+ int fileWidth, fileHeight, imageWidth, imageHeight;
+ unsigned int nBytes;
+ int index = 0, argc = 0, i, result = TCL_ERROR;
+ Tcl_Obj **objv;
+ unsigned char buf[100];
+ unsigned char *trashBuffer = NULL;
+ int bitPixel;
+ unsigned char colorMap[MAXCOLORMAPSIZE][4];
+ int transparent = -1;
+ static const char *const optionStrings[] = {
+ "-index", NULL
+ };
+ GIFImageConfig gifConf, *gifConfPtr = &gifConf;
+
+ /*
+ * Decode the magic used to convey when we're sourcing data from a string
+ * source and not a file.
+ */
+
+ memset(colorMap, 0, MAXCOLORMAPSIZE*4);
+ memset(gifConfPtr, 0, sizeof(GIFImageConfig));
+ if (fileName == INLINE_DATA_BINARY || fileName == INLINE_DATA_BASE64) {
+ gifConfPtr->fromData = fileName;
+ fileName = "inline data";
+ }
+
+ /*
+ * Parse the format string to get options.
+ */
+
+ if (format && Tcl_ListObjGetElements(interp, format,
+ &argc, &objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ for (i = 1; i < argc; i++) {
+ int optionIdx;
+ if (Tcl_GetIndexFromObjStruct(interp, objv[i], optionStrings,
+ sizeof(char *), "option name", 0, &optionIdx) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (i == (argc-1)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "no value given for \"%s\" option",
+ Tcl_GetString(objv[i])));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "GIF", "OPT_VALUE", NULL);
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIntFromObj(interp, objv[++i], &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * Read the GIF file header and check for some sanity.
+ */
+
+ if (!ReadGIFHeader(gifConfPtr, chan, &fileWidth, &fileHeight)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "couldn't read GIF header from file \"%s\"", fileName));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "GIF", "HEADER", NULL);
+ return TCL_ERROR;
+ }
+ if ((fileWidth <= 0) || (fileHeight <= 0)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "GIF image file \"%s\" has dimension(s) <= 0", fileName));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "GIF", "BOGUS_SIZE", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Get the general colormap information.
+ */
+
+ if (Fread(gifConfPtr, buf, 1, 3, chan) != 3) {
+ return TCL_OK;
+ }
+ bitPixel = 2 << (buf[0] & 0x07);
+
+ if (BitSet(buf[0], LOCALCOLORMAP)) { /* Global Colormap */
+ if (!ReadColorMap(gifConfPtr, chan, bitPixel, colorMap)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "error reading color map", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "GIF", "COLOR_MAP", NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ if ((srcX + width) > fileWidth) {
+ width = fileWidth - srcX;
+ }
+ if ((srcY + height) > fileHeight) {
+ height = fileHeight - srcY;
+ }
+ if ((width <= 0) || (height <= 0)
+ || (srcX >= fileWidth) || (srcY >= fileHeight)) {
+ return TCL_OK;
+ }
+
+ /*
+ * Make sure we have enough space in the photo image to hold the data from
+ * the GIF.
+ */
+
+ if (Tk_PhotoExpand(interp, imageHandle,
+ destX + width, destY + height) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Search for the frame from the GIF to display.
+ */
+
+ while (1) {
+ if (Fread(gifConfPtr, buf, 1, 1, chan) != 1) {
+ /*
+ * Premature end of image.
+ */
+
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "premature end of image data for this index", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "GIF", "PREMATURE_END",
+ NULL);
+ goto error;
+ }
+
+ switch (buf[0]) {
+ case GIF_TERMINATOR:
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "no image data for this index", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "GIF", "NO_DATA", NULL);
+ goto error;
+
+ case GIF_EXTENSION:
+ /*
+ * This is a GIF extension.
+ */
+
+ if (Fread(gifConfPtr, buf, 1, 1, chan) != 1) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "error reading extension function code in GIF image",
+ -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "GIF", "BAD_EXT",
+ NULL);
+ goto error;
+ }
+ if (DoExtension(gifConfPtr, chan, buf[0],
+ gifConfPtr->workingBuffer, &transparent) < 0) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "error reading extension in GIF image", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "GIF", "BAD_EXT",
+ NULL);
+ goto error;
+ }
+ continue;
+ case GIF_START:
+ if (Fread(gifConfPtr, buf, 1, 9, chan) != 9) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "couldn't read left/top/width/height in GIF image",
+ -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "GIF", "DIMENSIONS",
+ NULL);
+ goto error;
+ }
+ break;
+ default:
+ /*
+ * Not a valid start character; ignore it.
+ */
+
+ continue;
+ }
+
+ /*
+ * We've read the header for a GIF frame. Work out what we are going
+ * to do about it.
+ */
+
+ imageWidth = LM_to_uint(buf[4], buf[5]);
+ imageHeight = LM_to_uint(buf[6], buf[7]);
+ bitPixel = 1 << ((buf[8] & 0x07) + 1);
+
+ if (index--) {
+ /*
+ * This is not the GIF frame we want to read: skip it.
+ */
+
+ if (BitSet(buf[8], LOCALCOLORMAP)) {
+ if (!ReadColorMap(gifConfPtr, chan, bitPixel, colorMap)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "error reading color map", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "GIF",
+ "COLOR_MAP", NULL);
+ goto error;
+ }
+ }
+
+ /*
+ * If we've not yet allocated a trash buffer, do so now.
+ */
+
+ if (trashBuffer == NULL) {
+ if (fileWidth > (int)((UINT_MAX/3)/fileHeight)) {
+ goto error;
+ }
+ nBytes = fileWidth * fileHeight * 3;
+ trashBuffer = ckalloc(nBytes);
+ if (trashBuffer) {
+ memset(trashBuffer, 0, nBytes);
+ }
+ }
+
+ /*
+ * Slurp! Process the data for this image and stuff it in a trash
+ * buffer.
+ *
+ * Yes, it might be more efficient here to *not* store the data
+ * (we're just going to throw it away later). However, I elected
+ * to implement it this way for good reasons. First, I wanted to
+ * avoid duplicating the (fairly complex) LWZ decoder in
+ * ReadImage. Fine, you say, why didn't you just modify it to
+ * allow the use of a NULL specifier for the output buffer? I
+ * tried that, but it negatively impacted the performance of what
+ * I think will be the common case: reading the first image in the
+ * file. Rather than marginally improve the speed of the less
+ * frequent case, I chose to maintain high performance for the
+ * common case.
+ */
+
+ if (ReadImage(gifConfPtr, interp, trashBuffer, chan, imageWidth,
+ imageHeight, colorMap, 0, 0, 0, -1) != TCL_OK) {
+ goto error;
+ }
+ continue;
+ }
+ break;
+ }
+
+ /*
+ * Found the frame we want to read. Next, check for a local color map for
+ * this frame.
+ */
+
+ if (BitSet(buf[8], LOCALCOLORMAP)) {
+ if (!ReadColorMap(gifConfPtr, chan, bitPixel, colorMap)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "error reading color map", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "GIF", "COLOR_MAP", NULL);
+ goto error;
+ }
+ }
+
+ /*
+ * Extract the location within the overall visible image to put the data
+ * in this frame, together with the size of this frame.
+ */
+
+ index = LM_to_uint(buf[0], buf[1]);
+ srcX -= index;
+ if (srcX<0) {
+ destX -= srcX; width += srcX;
+ srcX = 0;
+ }
+
+ if (width > imageWidth) {
+ width = imageWidth;
+ }
+
+ index = LM_to_uint(buf[2], buf[3]);
+ srcY -= index;
+ if (index > srcY) {
+ destY -= srcY; height += srcY;
+ srcY = 0;
+ }
+ if (height > imageHeight) {
+ height = imageHeight;
+ }
+
+ if ((width > 0) && (height > 0)) {
+ Tk_PhotoImageBlock block;
+
+ /*
+ * Read the data and put it into the photo buffer for display by the
+ * general image machinery.
+ */
+
+ block.width = width;
+ block.height = height;
+ block.pixelSize = (transparent>=0) ? 4 : 3;
+ block.offset[0] = 0;
+ block.offset[1] = 1;
+ block.offset[2] = 2;
+ block.offset[3] = (transparent>=0) ? 3 : 0;
+ if (imageWidth > INT_MAX/block.pixelSize) {
+ goto error;
+ }
+ block.pitch = block.pixelSize * imageWidth;
+ if (imageHeight > (int)(UINT_MAX/block.pitch)) {
+ goto error;
+ }
+ nBytes = block.pitch * imageHeight;
+ block.pixelPtr = ckalloc(nBytes);
+ if (block.pixelPtr) {
+ memset(block.pixelPtr, 0, nBytes);
+ }
+
+ if (ReadImage(gifConfPtr, interp, block.pixelPtr, chan, imageWidth,
+ imageHeight, colorMap, srcX, srcY, BitSet(buf[8], INTERLACE),
+ transparent) != TCL_OK) {
+ ckfree(block.pixelPtr);
+ goto error;
+ }
+ if (Tk_PhotoPutBlock(interp, imageHandle, &block, destX, destY,
+ width, height, TK_PHOTO_COMPOSITE_SET) != TCL_OK) {
+ ckfree(block.pixelPtr);
+ goto error;
+ }
+ ckfree(block.pixelPtr);
+ }
+
+ /*
+ * We've successfully read the GIF frame (or there was nothing to read,
+ * which suits as well). We're done.
+ */
+
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(tkImgFmtGIF.name, -1));
+ result = TCL_OK;
+
+ error:
+ /*
+ * If a trash buffer has been allocated, free it now.
+ */
+
+ if (trashBuffer != NULL) {
+ ckfree(trashBuffer);
+ }
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * StringMatchGIF --
+ *
+ * This function is invoked by the photo image type to see if an object
+ * contains image data in GIF format.
+ *
+ * Results:
+ * The return value is 1 if the first characters in the data are like GIF
+ * data, and 0 otherwise.
+ *
+ * Side effects:
+ * The size of the image is placed in widthPtr and heightPtr.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+StringMatchGIF(
+ Tcl_Obj *dataObj, /* the object containing the image data */
+ Tcl_Obj *format, /* the image format object, or NULL */
+ int *widthPtr, /* where to put the string width */
+ int *heightPtr, /* where to put the string height */
+ Tcl_Interp *interp) /* not used */
+{
+ unsigned char *data, header[10];
+ int got, length;
+ MFile handle;
+
+ data = Tcl_GetByteArrayFromObj(dataObj, &length);
+
+ /*
+ * Header is a minimum of 10 bytes.
+ */
+
+ if (length < 10) {
+ return 0;
+ }
+
+ /*
+ * Check whether the data is Base64 encoded.
+ */
+
+ if ((strncmp(GIF87a, (char *) data, 6) != 0) &&
+ (strncmp(GIF89a, (char *) data, 6) != 0)) {
+ /*
+ * Try interpreting the data as Base64 encoded
+ */
+
+ mInit((unsigned char *) data, &handle, length);
+ got = Mread(header, 10, 1, &handle);
+ if (got != 10 ||
+ ((strncmp(GIF87a, (char *) header, 6) != 0)
+ && (strncmp(GIF89a, (char *) header, 6) != 0))) {
+ return 0;
+ }
+ } else {
+ memcpy(header, data, 10);
+ }
+ *widthPtr = LM_to_uint(header[6], header[7]);
+ *heightPtr = LM_to_uint(header[8], header[9]);
+ return 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * StringReadGIF --
+ *
+ * This function is called by the photo image type to read GIF format
+ * data from an object, optionally base64 encoded, and give it to the
+ * photo image.
+ *
+ * Results:
+ * A standard TCL completion code. If TCL_ERROR is returned then an error
+ * message is left in the interp's result.
+ *
+ * Side effects:
+ * New data is added to the image given by imageHandle. This function
+ * calls FileReadGIF by redefining the operation of fprintf temporarily.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+StringReadGIF(
+ Tcl_Interp *interp, /* interpreter for reporting errors in */
+ Tcl_Obj *dataObj, /* object containing the image */
+ Tcl_Obj *format, /* format object, or NULL */
+ Tk_PhotoHandle imageHandle, /* the image to write this data into */
+ int destX, int destY, /* The rectangular region of the */
+ int width, int height, /* image to copy */
+ int srcX, int srcY)
+{
+ MFile handle, *hdlPtr = &handle;
+ int length;
+ const char *xferFormat;
+ unsigned char *data = Tcl_GetByteArrayFromObj(dataObj, &length);
+
+ mInit(data, hdlPtr, length);
+
+ /*
+ * Check whether the data is Base64 encoded by doing a character-by-
+ * charcter comparison with the binary-format headers; BASE64-encoded
+ * never matches (matching the other way is harder because of potential
+ * padding of the BASE64 data).
+ */
+
+ if (strncmp(GIF87a, (char *) data, 6)
+ && strncmp(GIF89a, (char *) data, 6)) {
+ xferFormat = INLINE_DATA_BASE64;
+ } else {
+ xferFormat = INLINE_DATA_BINARY;
+ }
+
+ /*
+ * Fall through to the file reader now that we have a correctly-configured
+ * pseudo-channel to pull the data from.
+ */
+
+ return FileReadGIF(interp, (Tcl_Channel) hdlPtr, xferFormat, format,
+ imageHandle, destX, destY, width, height, srcX, srcY);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ReadGIFHeader --
+ *
+ * This function reads the GIF header from the beginning of a GIF file
+ * and returns the dimensions of the image.
+ *
+ * Results:
+ * The return value is 1 if file "f" appears to start with a valid GIF
+ * header, 0 otherwise. If the header is valid, then *widthPtr and
+ * *heightPtr are modified to hold the dimensions of the image.
+ *
+ * Side effects:
+ * The access position in f advances.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ReadGIFHeader(
+ GIFImageConfig *gifConfPtr,
+ Tcl_Channel chan, /* Image file to read the header from */
+ int *widthPtr, int *heightPtr)
+ /* The dimensions of the image are returned
+ * here. */
+{
+ unsigned char buf[7];
+
+ if ((Fread(gifConfPtr, buf, 1, 6, chan) != 6)
+ || ((strncmp(GIF87a, (char *) buf, 6) != 0)
+ && (strncmp(GIF89a, (char *) buf, 6) != 0))) {
+ return 0;
+ }
+
+ if (Fread(gifConfPtr, buf, 1, 4, chan) != 4) {
+ return 0;
+ }
+
+ *widthPtr = LM_to_uint(buf[0], buf[1]);
+ *heightPtr = LM_to_uint(buf[2], buf[3]);
+ return 1;
+}
+
+/*
+ *-----------------------------------------------------------------
+ * The code below is copied from the giftoppm program and modified just
+ * slightly.
+ *-----------------------------------------------------------------
+ */
+
+static int
+ReadColorMap(
+ GIFImageConfig *gifConfPtr,
+ Tcl_Channel chan,
+ int number,
+ unsigned char buffer[MAXCOLORMAPSIZE][4])
+{
+ int i;
+ unsigned char rgb[3];
+
+ for (i = 0; i < number; ++i) {
+ if (Fread(gifConfPtr, rgb, sizeof(rgb), 1, chan) <= 0) {
+ return 0;
+ }
+
+ if (buffer) {
+ buffer[i][CM_RED] = rgb[0];
+ buffer[i][CM_GREEN] = rgb[1];
+ buffer[i][CM_BLUE] = rgb[2];
+ buffer[i][CM_ALPHA] = 255;
+ }
+ }
+ return 1;
+}
+
+static int
+DoExtension(
+ GIFImageConfig *gifConfPtr,
+ Tcl_Channel chan,
+ int label,
+ unsigned char *buf,
+ int *transparent)
+{
+ int count;
+
+ switch (label) {
+ case 0x01: /* Plain Text Extension */
+ break;
+
+ case 0xff: /* Application Extension */
+ break;
+
+ case 0xfe: /* Comment Extension */
+ do {
+ count = GetDataBlock(gifConfPtr, chan, buf);
+ } while (count > 0);
+ return count;
+
+ case 0xf9: /* Graphic Control Extension */
+ count = GetDataBlock(gifConfPtr, chan, buf);
+ if (count < 0) {
+ return 1;
+ }
+ if ((buf[0] & 0x1) != 0) {
+ *transparent = buf[3];
+ }
+
+ do {
+ count = GetDataBlock(gifConfPtr, chan, buf);
+ } while (count > 0);
+ return count;
+ }
+
+ do {
+ count = GetDataBlock(gifConfPtr, chan, buf);
+ } while (count > 0);
+ return count;
+}
+
+static int
+GetDataBlock(
+ GIFImageConfig *gifConfPtr,
+ Tcl_Channel chan,
+ unsigned char *buf)
+{
+ unsigned char count;
+
+ if (Fread(gifConfPtr, &count, 1, 1, chan) <= 0) {
+ return -1;
+ }
+
+ if ((count != 0) && (Fread(gifConfPtr, buf, count, 1, chan) <= 0)) {
+ return -1;
+ }
+
+ return count;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ReadImage --
+ *
+ * Process a GIF image from a given source, with a given height, width,
+ * transparency, etc.
+ *
+ * This code is based on the code found in the ImageMagick GIF decoder,
+ * which is (c) 2000 ImageMagick Studio.
+ *
+ * Some thoughts on our implementation:
+ * It sure would be nice if ReadImage didn't take 11 parameters! I think
+ * that if we were smarter, we could avoid doing that.
+ *
+ * Possible further optimizations: we could pull the GetCode function
+ * directly into ReadImage, which would improve our speed.
+ *
+ * Results:
+ * Processes a GIF image and loads the pixel data into a memory array.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ReadImage(
+ GIFImageConfig *gifConfPtr,
+ Tcl_Interp *interp,
+ unsigned char *imagePtr,
+ Tcl_Channel chan,
+ int len, int rows,
+ unsigned char cmap[MAXCOLORMAPSIZE][4],
+ int srcX, int srcY,
+ int interlace,
+ int transparent)
+{
+ unsigned char initialCodeSize;
+ int xpos = 0, ypos = 0, pass = 0, i, count;
+ register unsigned char *pixelPtr;
+ static const int interlaceStep[] = { 8, 8, 4, 2 };
+ static const int interlaceStart[] = { 0, 4, 2, 1 };
+ unsigned short prefix[(1 << MAX_LWZ_BITS)];
+ unsigned char append[(1 << MAX_LWZ_BITS)];
+ unsigned char stack[(1 << MAX_LWZ_BITS)*2];
+ register unsigned char *top;
+ int codeSize, clearCode, inCode, endCode, oldCode, maxCode;
+ int code, firstCode, v;
+
+ /*
+ * Initialize the decoder
+ */
+
+ if (Fread(gifConfPtr, &initialCodeSize, 1, 1, chan) <= 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "error reading GIF image: %s", Tcl_PosixError(interp)));
+ return TCL_ERROR;
+ }
+
+ if (initialCodeSize > MAX_LWZ_BITS) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("malformed image", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "GIF", "MALFORMED", NULL);
+ return TCL_ERROR;
+ }
+
+ if (transparent != -1) {
+ cmap[transparent][CM_RED] = 0;
+ cmap[transparent][CM_GREEN] = 0;
+ cmap[transparent][CM_BLUE] = 0;
+ cmap[transparent][CM_ALPHA] = 0;
+ }
+
+ pixelPtr = imagePtr;
+
+ /*
+ * Initialize the decoder.
+ *
+ * Set values for "special" numbers:
+ * clear code reset the decoder
+ * end code stop decoding
+ * code size size of the next code to retrieve
+ * max code next available table position
+ */
+
+ clearCode = 1 << (int) initialCodeSize;
+ endCode = clearCode + 1;
+ codeSize = (int) initialCodeSize + 1;
+ maxCode = clearCode + 2;
+ oldCode = -1;
+ firstCode = -1;
+
+ memset(prefix, 0, (1 << MAX_LWZ_BITS) * sizeof(short));
+ memset(append, 0, (1 << MAX_LWZ_BITS) * sizeof(char));
+ for (i = 0; i < clearCode; i++) {
+ append[i] = i;
+ }
+ top = stack;
+
+ GetCode(chan, 0, 1, gifConfPtr);
+
+ /*
+ * Read until we finish the image
+ */
+
+ for (i = 0, ypos = 0; i < rows; i++) {
+ for (xpos = 0; xpos < len; ) {
+ if (top == stack) {
+ /*
+ * Bummer - our stack is empty. Now we have to work!
+ */
+
+ code = GetCode(chan, codeSize, 0, gifConfPtr);
+ if (code < 0) {
+ return TCL_OK;
+ }
+
+ if (code > maxCode || code == endCode) {
+ /*
+ * If we're doing things right, we should never receive a
+ * code that is greater than our current maximum code. If
+ * we do, bail, because our decoder does not yet have that
+ * code set up.
+ *
+ * If the code is the magic endCode value, quit.
+ */
+
+ return TCL_OK;
+ }
+
+ if (code == clearCode) {
+ /*
+ * Reset the decoder.
+ */
+
+ codeSize = initialCodeSize + 1;
+ maxCode = clearCode + 2;
+ oldCode = -1;
+ continue;
+ }
+
+ if (oldCode == -1) {
+ /*
+ * Last pass reset the decoder, so the first code we see
+ * must be a singleton. Seed the stack with it, and set up
+ * the old/first code pointers for insertion into the
+ * codes table. We can't just roll this into the clearCode
+ * test above, because at that point we have not yet read
+ * the next code.
+ */
+
+ *top++ = append[code];
+ oldCode = code;
+ firstCode = code;
+ continue;
+ }
+
+ inCode = code;
+
+ if ((code == maxCode) && (maxCode < (1 << MAX_LWZ_BITS))) {
+ /*
+ * maxCode is always one bigger than our highest assigned
+ * code. If the code we see is equal to maxCode, then we
+ * are about to add a new entry to the codes table.
+ */
+
+ *top++ = firstCode;
+ code = oldCode;
+ }
+
+ while (code > clearCode) {
+ /*
+ * Populate the stack by tracing the code in the codes
+ * table from its tail to its head
+ */
+
+ *top++ = append[code];
+ code = prefix[code];
+ }
+ firstCode = append[code];
+
+ /*
+ * Push the head of the code onto the stack.
+ */
+
+ *top++ = firstCode;
+
+ if (maxCode < (1 << MAX_LWZ_BITS)) {
+ /*
+ * If there's still room in our codes table, add a new entry.
+ * Otherwise don't, and keep using the current table.
+ * See DEFERRED CLEAR CODE IN LZW COMPRESSION in the GIF89a
+ * specification.
+ */
+
+ prefix[maxCode] = oldCode;
+ append[maxCode] = firstCode;
+ maxCode++;
+ }
+
+ /*
+ * maxCode tells us the maximum code value we can accept. If
+ * we see that we need more bits to represent it than we are
+ * requesting from the unpacker, we need to increase the
+ * number we ask for.
+ */
+
+ if ((maxCode >= (1 << codeSize))
+ && (maxCode < (1<<MAX_LWZ_BITS))) {
+ codeSize++;
+ }
+ oldCode = inCode;
+ }
+
+ /*
+ * Pop the next color index off the stack.
+ */
+
+ v = *(--top);
+ if (v < 0) {
+ return TCL_OK;
+ }
+
+ /*
+ * If pixelPtr is null, we're skipping this image (presumably
+ * there are more in the file and we will be called to read one of
+ * them later)
+ */
+
+ *pixelPtr++ = cmap[v][CM_RED];
+ *pixelPtr++ = cmap[v][CM_GREEN];
+ *pixelPtr++ = cmap[v][CM_BLUE];
+ if (transparent >= 0) {
+ *pixelPtr++ = cmap[v][CM_ALPHA];
+ }
+ xpos++;
+
+ }
+
+ /*
+ * If interlacing, the next ypos is not just +1.
+ */
+
+ if (interlace) {
+ ypos += interlaceStep[pass];
+ while (ypos >= rows) {
+ pass++;
+ if (pass > 3) {
+ return TCL_OK;
+ }
+ ypos = interlaceStart[pass];
+ }
+ } else {
+ ypos++;
+ }
+ pixelPtr = imagePtr + (ypos) * len * ((transparent>=0)?4:3);
+ }
+
+ /*
+ * Now read until the final zero byte.
+ * It was observed that there might be 1 length blocks
+ * (test imgPhoto-14.1) which are not read.
+ *
+ * The field "stack" is abused for temporary buffer. it has 4096 bytes
+ * and we need 256.
+ *
+ * Loop until we hit a 0 length block which is the end sign.
+ */
+ while ( 0 < (count = GetDataBlock(gifConfPtr, chan, stack)))
+ {
+ if (-1 == count ) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "error reading GIF image: %s", Tcl_PosixError(interp)));
+ return TCL_ERROR;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetCode --
+ *
+ * Extract the next compression code from the file. In GIF's, the
+ * compression codes are between 3 and 12 bits long and are then packed
+ * into 8 bit bytes, left to right, for example:
+ * bbbaaaaa
+ * dcccccbb
+ * eeeedddd
+ * ...
+ * We use a byte buffer read from the file and a sliding window to unpack
+ * the bytes. Thanks to ImageMagick for the sliding window idea.
+ * args: chan the channel to read from
+ * code_size size of the code to extract
+ * flag boolean indicating whether the extractor should be
+ * reset or not
+ *
+ * Results:
+ * code the next compression code
+ *
+ * Side effects:
+ * May consume more input from chan.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GetCode(
+ Tcl_Channel chan,
+ int code_size,
+ int flag,
+ GIFImageConfig *gifConfPtr)
+{
+ int ret;
+
+ if (flag) {
+ /*
+ * Initialize the decoder.
+ */
+
+ gifConfPtr->reader.bitsInWindow = 0;
+ gifConfPtr->reader.bytes = 0;
+ gifConfPtr->reader.window = 0;
+ gifConfPtr->reader.done = 0;
+ gifConfPtr->reader.c = NULL;
+ return 0;
+ }
+
+ while (gifConfPtr->reader.bitsInWindow < code_size) {
+ /*
+ * Not enough bits in our window to cover the request.
+ */
+
+ if (gifConfPtr->reader.done) {
+ return -1;
+ }
+ if (gifConfPtr->reader.bytes == 0) {
+ /*
+ * Not enough bytes in our buffer to add to the window.
+ */
+
+ gifConfPtr->reader.bytes =
+ GetDataBlock(gifConfPtr, chan, gifConfPtr->workingBuffer);
+ gifConfPtr->reader.c = gifConfPtr->workingBuffer;
+ if (gifConfPtr->reader.bytes <= 0) {
+ gifConfPtr->reader.done = 1;
+ break;
+ }
+ }
+
+ /*
+ * Tack another byte onto the window, see if that's enough.
+ */
+
+ gifConfPtr->reader.window +=
+ (*gifConfPtr->reader.c) << gifConfPtr->reader.bitsInWindow;
+ gifConfPtr->reader.c++;
+ gifConfPtr->reader.bitsInWindow += 8;
+ gifConfPtr->reader.bytes--;
+ }
+
+ /*
+ * The next code will always be the last code_size bits of the window.
+ */
+
+ ret = gifConfPtr->reader.window & ((1 << code_size) - 1);
+
+ /*
+ * Shift data in the window to put the next code at the end.
+ */
+
+ gifConfPtr->reader.window >>= code_size;
+ gifConfPtr->reader.bitsInWindow -= code_size;
+ return ret;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Minit -- --
+ *
+ * This function initializes a base64 decoder handle
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * The base64 handle is initialized
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+mInit(
+ unsigned char *string, /* string containing initial mmencoded data */
+ MFile *handle, /* mmdecode "file" handle */
+ int length) /* Number of bytes in string */
+{
+ handle->data = string;
+ handle->state = 0;
+ handle->c = 0;
+ handle->length = length;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Mread --
+ *
+ * This function is invoked by the GIF file reader as a temporary
+ * replacement for "fread", to get GIF data out of a string (using
+ * Mgetc).
+ *
+ * Results:
+ * The return value is the number of characters "read"
+ *
+ * Side effects:
+ * The base64 handle will change state.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+Mread(
+ unsigned char *dst, /* where to put the result */
+ size_t chunkSize, /* size of each transfer */
+ size_t numChunks, /* number of chunks */
+ MFile *handle) /* mmdecode "file" handle */
+{
+ register int i, c;
+ int count = chunkSize * numChunks;
+
+ for (i=0; i<count && (c=Mgetc(handle)) != GIF_DONE; i++) {
+ *dst++ = c;
+ }
+ return i;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Mgetc --
+ *
+ * This function gets the next decoded character from an mmencode handle.
+ * This causes at least 1 character to be "read" from the encoded string.
+ *
+ * Results:
+ * The next byte (or GIF_DONE) is returned.
+ *
+ * Side effects:
+ * The base64 handle will change state.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+Mgetc(
+ MFile *handle) /* Handle containing decoder data and state */
+{
+ int c;
+ int result = 0; /* Initialization needed only to prevent gcc
+ * compiler warning. */
+
+ if (handle->state == GIF_DONE) {
+ return GIF_DONE;
+ }
+
+ do {
+ if (handle->length-- <= 0) {
+ return GIF_DONE;
+ }
+ c = char64(*handle->data);
+ handle->data++;
+ } while (c == GIF_SPACE);
+
+ if (c > GIF_SPECIAL) {
+ handle->state = GIF_DONE;
+ return handle->c;
+ }
+
+ switch (handle->state++) {
+ case 0:
+ handle->c = c<<2;
+ result = Mgetc(handle);
+ break;
+ case 1:
+ result = handle->c | (c>>4);
+ handle->c = (c&0xF)<<4;
+ break;
+ case 2:
+ result = handle->c | (c>>2);
+ handle->c = (c&0x3) << 6;
+ break;
+ case 3:
+ result = handle->c | c;
+ handle->state = 0;
+ break;
+ }
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * char64 --
+ *
+ * This function converts a base64 ascii character into its binary
+ * equivalent. This code is a slightly modified version of the char64
+ * function in N. Borenstein's metamail decoder.
+ *
+ * Results:
+ * The binary value, or an error code.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+char64(
+ int c)
+{
+ switch(c) {
+ case 'A': return 0; case 'B': return 1; case 'C': return 2;
+ case 'D': return 3; case 'E': return 4; case 'F': return 5;
+ case 'G': return 6; case 'H': return 7; case 'I': return 8;
+ case 'J': return 9; case 'K': return 10; case 'L': return 11;
+ case 'M': return 12; case 'N': return 13; case 'O': return 14;
+ case 'P': return 15; case 'Q': return 16; case 'R': return 17;
+ case 'S': return 18; case 'T': return 19; case 'U': return 20;
+ case 'V': return 21; case 'W': return 22; case 'X': return 23;
+ case 'Y': return 24; case 'Z': return 25; case 'a': return 26;
+ case 'b': return 27; case 'c': return 28; case 'd': return 29;
+ case 'e': return 30; case 'f': return 31; case 'g': return 32;
+ case 'h': return 33; case 'i': return 34; case 'j': return 35;
+ case 'k': return 36; case 'l': return 37; case 'm': return 38;
+ case 'n': return 39; case 'o': return 40; case 'p': return 41;
+ case 'q': return 42; case 'r': return 43; case 's': return 44;
+ case 't': return 45; case 'u': return 46; case 'v': return 47;
+ case 'w': return 48; case 'x': return 49; case 'y': return 50;
+ case 'z': return 51; case '0': return 52; case '1': return 53;
+ case '2': return 54; case '3': return 55; case '4': return 56;
+ case '5': return 57; case '6': return 58; case '7': return 59;
+ case '8': return 60; case '9': return 61; case '+': return 62;
+ case '/': return 63;
+
+ case ' ': case '\t': case '\n': case '\r': case '\f':
+ return GIF_SPACE;
+ case '=':
+ return GIF_PAD;
+ case '\0':
+ return GIF_DONE;
+ default:
+ return GIF_BAD;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Fread --
+ *
+ * This function calls either fread or Mread to read data from a file or
+ * a base64 encoded string.
+ *
+ * Results: - same as POSIX fread() or Tcl Tcl_Read()
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+Fread(
+ GIFImageConfig *gifConfPtr,
+ unsigned char *dst, /* where to put the result */
+ size_t hunk, size_t count, /* how many */
+ Tcl_Channel chan)
+{
+ if (gifConfPtr->fromData == INLINE_DATA_BASE64) {
+ return Mread(dst, hunk, count, (MFile *) chan);
+ }
+
+ if (gifConfPtr->fromData == INLINE_DATA_BINARY) {
+ MFile *handle = (MFile *) chan;
+
+ if (handle->length <= 0 || (size_t) handle->length < hunk*count) {
+ return -1;
+ }
+ memcpy(dst, handle->data, (size_t) (hunk * count));
+ handle->data += hunk * count;
+ handle->length -= hunk * count;
+ return (int)(hunk * count);
+ }
+
+ /*
+ * Otherwise we've got a real file to read.
+ */
+
+ return Tcl_Read(chan, (char *) dst, (int) (hunk * count));
+}
+
+/*
+ * ChanWriteGIF - writes a image in GIF format.
+ *-------------------------------------------------------------------------
+ * Author: Lolo
+ * Engeneering Projects Area
+ * Department of Mining
+ * University of Oviedo
+ * e-mail zz11425958@zeus.etsimo.uniovi.es
+ * lolo@pcsig22.etsimo.uniovi.es
+ * Date: Fri September 20 1996
+ *
+ * Modified for transparency handling (gif89a)
+ * by Jan Nijtmans <nijtmans@users.sourceforge.net>
+ *
+ *----------------------------------------------------------------------
+ * FileWriteGIF-
+ *
+ * This function is called by the photo image type to write GIF format
+ * data from a photo image into a given file
+ *
+ * Results:
+ * A standard TCL completion code. If TCL_ERROR is returned then an
+ * error message is left in the interp's result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+
+static int
+FileWriteGIF(
+ Tcl_Interp *interp, /* Interpreter to use for reporting errors. */
+ const char *filename,
+ Tcl_Obj *format,
+ Tk_PhotoImageBlock *blockPtr)
+{
+ Tcl_Channel chan = NULL;
+ int result;
+
+ chan = Tcl_OpenFileChannel(interp, (char *) filename, "w", 0644);
+ if (!chan) {
+ return TCL_ERROR;
+ }
+ if (Tcl_SetChannelOption(interp, chan, "-translation",
+ "binary") != TCL_OK) {
+ Tcl_Close(NULL, chan);
+ return TCL_ERROR;
+ }
+
+ result = CommonWriteGIF(interp, chan, WriteToChannel, format, blockPtr);
+
+ if (Tcl_Close(interp, chan) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ return result;
+}
+
+static int
+StringWriteGIF(
+ Tcl_Interp *interp, /* Interpreter to use for reporting errors and
+ * returning the GIF data. */
+ Tcl_Obj *format,
+ Tk_PhotoImageBlock *blockPtr)
+{
+ int result;
+ Tcl_Obj *objPtr = Tcl_NewObj();
+
+ Tcl_IncrRefCount(objPtr);
+ result = CommonWriteGIF(interp, objPtr, WriteToByteArray, format,
+ blockPtr);
+ if (result == TCL_OK) {
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ Tcl_DecrRefCount(objPtr);
+ return result;
+}
+
+static int
+WriteToChannel(
+ ClientData clientData,
+ const char *bytes,
+ int byteCount)
+{
+ Tcl_Channel handle = clientData;
+
+ return Tcl_Write(handle, bytes, byteCount);
+}
+
+static int
+WriteToByteArray(
+ ClientData clientData,
+ const char *bytes,
+ int byteCount)
+{
+ Tcl_Obj *objPtr = clientData;
+ Tcl_Obj *tmpObj = Tcl_NewByteArrayObj((unsigned char *) bytes, byteCount);
+
+ Tcl_IncrRefCount(tmpObj);
+ Tcl_AppendObjToObj(objPtr, tmpObj);
+ Tcl_DecrRefCount(tmpObj);
+ return byteCount;
+}
+
+static int
+CommonWriteGIF(
+ Tcl_Interp *interp,
+ ClientData handle,
+ WriteBytesFunc *writeProc,
+ Tcl_Obj *format,
+ Tk_PhotoImageBlock *blockPtr)
+{
+ GifWriterState state;
+ int resolution;
+ long width, height, x;
+ unsigned char c;
+ unsigned int top, left;
+
+ top = 0;
+ left = 0;
+
+ memset(&state, 0, sizeof(state));
+
+ state.pixelSize = blockPtr->pixelSize;
+ state.greenOffset = blockPtr->offset[1]-blockPtr->offset[0];
+ state.blueOffset = blockPtr->offset[2]-blockPtr->offset[0];
+ state.alphaOffset = blockPtr->offset[0];
+ if (state.alphaOffset < blockPtr->offset[2]) {
+ state.alphaOffset = blockPtr->offset[2];
+ }
+ if (++state.alphaOffset < state.pixelSize) {
+ state.alphaOffset -= blockPtr->offset[0];
+ } else {
+ state.alphaOffset = 0;
+ }
+
+ writeProc(handle, (char *) (state.alphaOffset ? GIF89a : GIF87a), 6);
+
+ for (x = 0; x < MAXCOLORMAPSIZE ;x++) {
+ state.mapa[x][CM_RED] = 255;
+ state.mapa[x][CM_GREEN] = 255;
+ state.mapa[x][CM_BLUE] = 255;
+ }
+
+ width = blockPtr->width;
+ height = blockPtr->height;
+ state.pixelOffset = blockPtr->pixelPtr + blockPtr->offset[0];
+ state.pixelPitch = blockPtr->pitch;
+ SaveMap(&state, blockPtr);
+ if (state.num >= MAXCOLORMAPSIZE) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("too many colors", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "GIF", "COLORFUL", NULL);
+ return TCL_ERROR;
+ }
+ if (state.num<2) {
+ state.num = 2;
+ }
+ c = LSB(width);
+ writeProc(handle, (char *) &c, 1);
+ c = MSB(width);
+ writeProc(handle, (char *) &c, 1);
+ c = LSB(height);
+ writeProc(handle, (char *) &c, 1);
+ c = MSB(height);
+ writeProc(handle, (char *) &c, 1);
+
+ resolution = 0;
+ while (state.num >> resolution) {
+ resolution++;
+ }
+ c = 111 + resolution * 17;
+ writeProc(handle, (char *) &c, 1);
+
+ state.num = 1 << resolution;
+
+ /*
+ * Background color
+ */
+
+ c = 0;
+ writeProc(handle, (char *) &c, 1);
+
+ /*
+ * Zero for future expansion.
+ */
+
+ writeProc(handle, (char *) &c, 1);
+
+ for (x = 0; x < state.num; x++) {
+ c = state.mapa[x][CM_RED];
+ writeProc(handle, (char *) &c, 1);
+ c = state.mapa[x][CM_GREEN];
+ writeProc(handle, (char *) &c, 1);
+ c = state.mapa[x][CM_BLUE];
+ writeProc(handle, (char *) &c, 1);
+ }
+
+ /*
+ * Write out extension for transparent colour index, if necessary.
+ */
+
+ if (state.alphaOffset) {
+ c = GIF_EXTENSION;
+ writeProc(handle, (char *) &c, 1);
+ writeProc(handle, "\371\4\1\0\0\0", 7);
+ }
+
+ c = GIF_START;
+ writeProc(handle, (char *) &c, 1);
+ c = LSB(top);
+ writeProc(handle, (char *) &c, 1);
+ c = MSB(top);
+ writeProc(handle, (char *) &c, 1);
+ c = LSB(left);
+ writeProc(handle, (char *) &c, 1);
+ c = MSB(left);
+ writeProc(handle, (char *) &c, 1);
+
+ c = LSB(width);
+ writeProc(handle, (char *) &c, 1);
+ c = MSB(width);
+ writeProc(handle, (char *) &c, 1);
+
+ c = LSB(height);
+ writeProc(handle, (char *) &c, 1);
+ c = MSB(height);
+ writeProc(handle, (char *) &c, 1);
+
+ c = 0;
+ writeProc(handle, (char *) &c, 1);
+ c = resolution;
+ writeProc(handle, (char *) &c, 1);
+
+ state.ssize = state.rsize = blockPtr->width;
+ state.csize = blockPtr->height;
+ Compress(resolution+1, handle, writeProc, ReadValue, &state);
+
+ c = 0;
+ writeProc(handle, (char *) &c, 1);
+ c = GIF_TERMINATOR;
+ writeProc(handle, (char *) &c, 1);
+
+ return TCL_OK;
+}
+
+static int
+ColorNumber(
+ GifWriterState *statePtr,
+ int red, int green, int blue)
+{
+ int x = (statePtr->alphaOffset != 0);
+
+ for (; x <= MAXCOLORMAPSIZE; x++) {
+ if ((statePtr->mapa[x][CM_RED] == red) &&
+ (statePtr->mapa[x][CM_GREEN] == green) &&
+ (statePtr->mapa[x][CM_BLUE] == blue)) {
+ return x;
+ }
+ }
+ return -1;
+}
+
+static int
+IsNewColor(
+ GifWriterState *statePtr,
+ int red, int green, int blue)
+{
+ int x = (statePtr->alphaOffset != 0);
+
+ for (; x<=statePtr->num ; x++) {
+ if ((statePtr->mapa[x][CM_RED] == red) &&
+ (statePtr->mapa[x][CM_GREEN] == green) &&
+ (statePtr->mapa[x][CM_BLUE] == blue)) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static void
+SaveMap(
+ GifWriterState *statePtr,
+ Tk_PhotoImageBlock *blockPtr)
+{
+ unsigned char *colores;
+ int x, y;
+ unsigned char red, green, blue;
+
+ if (statePtr->alphaOffset) {
+ statePtr->num = 0;
+ statePtr->mapa[0][CM_RED] = DEFAULT_BACKGROUND_VALUE;
+ statePtr->mapa[0][CM_GREEN] = DEFAULT_BACKGROUND_VALUE;
+ statePtr->mapa[0][CM_BLUE] = DEFAULT_BACKGROUND_VALUE;
+ } else {
+ statePtr->num = -1;
+ }
+
+ for (y=0 ; y<blockPtr->height ; y++) {
+ colores = blockPtr->pixelPtr + blockPtr->offset[0] + y*blockPtr->pitch;
+ for (x=0 ; x<blockPtr->width ; x++) {
+ if (!statePtr->alphaOffset || colores[statePtr->alphaOffset]!=0) {
+ red = colores[0];
+ green = colores[statePtr->greenOffset];
+ blue = colores[statePtr->blueOffset];
+ if (IsNewColor(statePtr, red, green, blue)) {
+ statePtr->num++;
+ if (statePtr->num >= MAXCOLORMAPSIZE) {
+ return;
+ }
+ statePtr->mapa[statePtr->num][CM_RED] = red;
+ statePtr->mapa[statePtr->num][CM_GREEN] = green;
+ statePtr->mapa[statePtr->num][CM_BLUE] = blue;
+ }
+ }
+ colores += statePtr->pixelSize;
+ }
+ }
+}
+
+static int
+ReadValue(
+ GifWriterState *statePtr)
+{
+ unsigned int col;
+
+ if (statePtr->csize == 0) {
+ return EOF;
+ }
+ if (statePtr->alphaOffset
+ && (statePtr->pixelOffset[statePtr->alphaOffset]==0)) {
+ col = 0;
+ } else {
+ col = ColorNumber(statePtr, statePtr->pixelOffset[0],
+ statePtr->pixelOffset[statePtr->greenOffset],
+ statePtr->pixelOffset[statePtr->blueOffset]);
+ }
+ statePtr->pixelOffset += statePtr->pixelSize;
+ if (--statePtr->ssize <= 0) {
+ statePtr->ssize = statePtr->rsize;
+ statePtr->csize--;
+ statePtr->pixelOffset += statePtr->pixelPitch
+ - (statePtr->rsize * statePtr->pixelSize);
+ }
+
+ return col;
+}
+
+/*
+ * GIF Image compression - modified 'Compress'
+ *
+ * Based on: compress.c - File compression ala IEEE Computer, June 1984.
+ *
+ * By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
+ * Jim McKie (decvax!mcvax!jim)
+ * Steve Davies (decvax!vax135!petsd!peora!srd)
+ * Ken Turkowski (decvax!decwrl!turtlevax!ken)
+ * James A. Woods (decvax!ihnp4!ames!jaw)
+ * Joe Orost (decvax!vax135!petsd!joe)
+ */
+
+static void
+Compress(
+ int initialBits,
+ ClientData handle,
+ WriteBytesFunc *writeProc,
+ ifunptr readValue,
+ GifWriterState *statePtr)
+{
+ long fcode, ent, disp, hSize, i = 0;
+ int c, hshift;
+ GIFState_t state;
+
+ memset(&state, 0, sizeof(state));
+
+ /*
+ * Set up the globals: initialBits - initial number of bits
+ * outChannel - pointer to output file
+ */
+
+ state.initialBits = initialBits;
+ state.destination = handle;
+ state.writeProc = writeProc;
+
+ /*
+ * Set up the necessary values.
+ */
+
+ state.offset = 0;
+ state.hSize = HSIZE;
+ state.outCount = 0;
+ state.clearFlag = 0;
+ state.inCount = 1;
+ state.maxCode = MAXCODE(state.numBits = state.initialBits);
+ state.clearCode = 1 << (initialBits - 1);
+ state.eofCode = state.clearCode + 1;
+ state.freeEntry = state.clearCode + 2;
+ CharInit(&state);
+
+ ent = readValue(statePtr);
+
+ hshift = 0;
+ for (fcode = (long) state.hSize; fcode < 65536L; fcode *= 2L) {
+ hshift++;
+ }
+ hshift = 8 - hshift; /* Set hash code range bound */
+
+ hSize = state.hSize;
+ ClearHashTable(&state, (int) hSize); /* Clear hash table */
+
+ Output(&state, (long) state.clearCode);
+
+ while (U(c = readValue(statePtr)) != U(EOF)) {
+ state.inCount++;
+
+ fcode = (long) (((long) c << GIFBITS) + ent);
+ i = ((long)c << hshift) ^ ent; /* XOR hashing */
+
+ if (state.hashTable[i] == fcode) {
+ ent = state.codeTable[i];
+ continue;
+ } else if ((long) state.hashTable[i] < 0) { /* Empty slot */
+ goto nomatch;
+ }
+
+ disp = hSize - i; /* Secondary hash (after G. Knott) */
+ if (i == 0) {
+ disp = 1;
+ }
+
+ probe:
+ if ((i -= disp) < 0) {
+ i += hSize;
+ }
+
+ if (state.hashTable[i] == fcode) {
+ ent = state.codeTable[i];
+ continue;
+ }
+ if ((long) state.hashTable[i] > 0) {
+ goto probe;
+ }
+
+ nomatch:
+ Output(&state, (long) ent);
+ state.outCount++;
+ ent = c;
+ if (U(state.freeEntry) < U((long)1 << GIFBITS)) {
+ state.codeTable[i] = state.freeEntry++; /* code -> hashtable */
+ state.hashTable[i] = fcode;
+ } else {
+ ClearForBlock(&state);
+ }
+ }
+
+ /*
+ * Put out the final code.
+ */
+
+ Output(&state, (long) ent);
+ state.outCount++;
+ Output(&state, (long) state.eofCode);
+}
+
+/*****************************************************************
+ * Output --
+ * Output the given code.
+ *
+ * Inputs:
+ * code: A numBits-bit integer. If == -1, then EOF. This assumes that
+ * numBits =< (long) wordsize - 1.
+ * Outputs:
+ * Outputs code to the file.
+ * Assumptions:
+ * Chars are 8 bits long.
+ * Algorithm:
+ * Maintain a GIFBITS character long buffer (so that 8 codes will fit in
+ * it exactly). Use the VAX insv instruction to insert each code in turn.
+ * When the buffer fills up empty it and start over.
+ */
+
+static void
+Output(
+ GIFState_t *statePtr,
+ long code)
+{
+ static const unsigned long masks[] = {
+ 0x0000,
+ 0x0001, 0x0003, 0x0007, 0x000F,
+ 0x001F, 0x003F, 0x007F, 0x00FF,
+ 0x01FF, 0x03FF, 0x07FF, 0x0FFF,
+ 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF
+ };
+
+ statePtr->currentAccumulated &= masks[statePtr->currentBits];
+ if (statePtr->currentBits > 0) {
+ statePtr->currentAccumulated |= ((long) code << statePtr->currentBits);
+ } else {
+ statePtr->currentAccumulated = code;
+ }
+ statePtr->currentBits += statePtr->numBits;
+
+ while (statePtr->currentBits >= 8) {
+ CharOut(statePtr, (unsigned) (statePtr->currentAccumulated & 0xff));
+ statePtr->currentAccumulated >>= 8;
+ statePtr->currentBits -= 8;
+ }
+
+ /*
+ * If the next entry is going to be too big for the code size, then
+ * increase it, if possible.
+ */
+
+ if ((statePtr->freeEntry > statePtr->maxCode) || statePtr->clearFlag) {
+ if (statePtr->clearFlag) {
+ statePtr->maxCode = MAXCODE(
+ statePtr->numBits = statePtr->initialBits);
+ statePtr->clearFlag = 0;
+ } else {
+ statePtr->numBits++;
+ if (statePtr->numBits == GIFBITS) {
+ statePtr->maxCode = (long)1 << GIFBITS;
+ } else {
+ statePtr->maxCode = MAXCODE(statePtr->numBits);
+ }
+ }
+ }
+
+ if (code == statePtr->eofCode) {
+ /*
+ * At EOF, write the rest of the buffer.
+ */
+
+ while (statePtr->currentBits > 0) {
+ CharOut(statePtr,
+ (unsigned) (statePtr->currentAccumulated & 0xff));
+ statePtr->currentAccumulated >>= 8;
+ statePtr->currentBits -= 8;
+ }
+ FlushChar(statePtr);
+ }
+}
+
+/*
+ * Clear out the hash table
+ */
+
+static void
+ClearForBlock( /* Table clear for block compress. */
+ GIFState_t *statePtr)
+{
+ ClearHashTable(statePtr, (int) statePtr->hSize);
+ statePtr->freeEntry = statePtr->clearCode + 2;
+ statePtr->clearFlag = 1;
+
+ Output(statePtr, (long) statePtr->clearCode);
+}
+
+static void
+ClearHashTable( /* Reset code table. */
+ GIFState_t *statePtr,
+ int hSize)
+{
+ register int *hashTablePtr = statePtr->hashTable + hSize;
+ register long i;
+ register long m1 = -1;
+
+ i = hSize - 16;
+ do { /* might use Sys V memset(3) here */
+ *(hashTablePtr-16) = m1;
+ *(hashTablePtr-15) = m1;
+ *(hashTablePtr-14) = m1;
+ *(hashTablePtr-13) = m1;
+ *(hashTablePtr-12) = m1;
+ *(hashTablePtr-11) = m1;
+ *(hashTablePtr-10) = m1;
+ *(hashTablePtr-9) = m1;
+ *(hashTablePtr-8) = m1;
+ *(hashTablePtr-7) = m1;
+ *(hashTablePtr-6) = m1;
+ *(hashTablePtr-5) = m1;
+ *(hashTablePtr-4) = m1;
+ *(hashTablePtr-3) = m1;
+ *(hashTablePtr-2) = m1;
+ *(hashTablePtr-1) = m1;
+ hashTablePtr -= 16;
+ } while ((i -= 16) >= 0);
+
+ for (i += 16; i > 0; i--) {
+ *--hashTablePtr = m1;
+ }
+}
+
+/*
+ *****************************************************************************
+ *
+ * GIF Specific routines
+ *
+ *****************************************************************************
+ */
+
+/*
+ * Set up the 'byte output' routine
+ */
+
+static void
+CharInit(
+ GIFState_t *statePtr)
+{
+ statePtr->accumulatedByteCount = 0;
+ statePtr->currentAccumulated = 0;
+ statePtr->currentBits = 0;
+}
+
+/*
+ * Add a character to the end of the current packet, and if it is 254
+ * characters, flush the packet to disk.
+ */
+
+static void
+CharOut(
+ GIFState_t *statePtr,
+ int c)
+{
+ statePtr->packetAccumulator[statePtr->accumulatedByteCount++] = c;
+ if (statePtr->accumulatedByteCount >= 254) {
+ FlushChar(statePtr);
+ }
+}
+
+/*
+ * Flush the packet to disk, and reset the accumulator
+ */
+
+static void
+FlushChar(
+ GIFState_t *statePtr)
+{
+ unsigned char c;
+
+ if (statePtr->accumulatedByteCount > 0) {
+ c = statePtr->accumulatedByteCount;
+ statePtr->writeProc(statePtr->destination, (const char *) &c, 1);
+ statePtr->writeProc(statePtr->destination,
+ (const char *) statePtr->packetAccumulator,
+ statePtr->accumulatedByteCount);
+ statePtr->accumulatedByteCount = 0;
+ }
+}
+
+/* The End */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkImgPNG.c b/tk8.6/generic/tkImgPNG.c
new file mode 100644
index 0000000..bfb2457
--- /dev/null
+++ b/tk8.6/generic/tkImgPNG.c
@@ -0,0 +1,3563 @@
+/*
+ * tkImgPNG.c --
+ *
+ * A Tk photo image file handler for PNG files.
+ *
+ * Copyright (c) 2006-2008 Muonics, Inc.
+ * Copyright (c) 2008 Donal K. Fellows
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "assert.h"
+#include "tkInt.h"
+
+#define PNG_INT32(a,b,c,d) \
+ (((long)(a) << 24) | ((long)(b) << 16) | ((long)(c) << 8) | (long)(d))
+#define PNG_BLOCK_SZ 1024 /* Process up to 1k at a time. */
+#define PNG_MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+/*
+ * Every PNG image starts with the following 8-byte signature.
+ */
+
+#define PNG_SIG_SZ 8
+static const unsigned char pngSignature[] = {
+ 137, 80, 78, 71, 13, 10, 26, 10
+};
+
+static const int startLine[8] = {
+ 0, 0, 0, 4, 0, 2, 0, 1
+};
+
+/*
+ * Chunk type flags.
+ */
+
+#define PNG_CF_ANCILLARY 0x20000000L /* Non-critical chunk (can ignore). */
+#define PNG_CF_PRIVATE 0x00100000L /* Application-specific chunk. */
+#define PNG_CF_RESERVED 0x00001000L /* Not used. */
+#define PNG_CF_COPYSAFE 0x00000010L /* Opaque data safe for copying. */
+
+/*
+ * Chunk types, not all of which have support implemented. Note that there are
+ * others in the official extension set which we will never support (as they
+ * are officially deprecated).
+ */
+
+#define CHUNK_IDAT PNG_INT32('I','D','A','T') /* Pixel data. */
+#define CHUNK_IEND PNG_INT32('I','E','N','D') /* End of Image. */
+#define CHUNK_IHDR PNG_INT32('I','H','D','R') /* Header. */
+#define CHUNK_PLTE PNG_INT32('P','L','T','E') /* Palette. */
+
+#define CHUNK_bKGD PNG_INT32('b','K','G','D') /* Background Color */
+#define CHUNK_cHRM PNG_INT32('c','H','R','M') /* Chroma values. */
+#define CHUNK_gAMA PNG_INT32('g','A','M','A') /* Gamma. */
+#define CHUNK_hIST PNG_INT32('h','I','S','T') /* Histogram. */
+#define CHUNK_iCCP PNG_INT32('i','C','C','P') /* Color profile. */
+#define CHUNK_iTXt PNG_INT32('i','T','X','t') /* Internationalized
+ * text (comments,
+ * etc.) */
+#define CHUNK_oFFs PNG_INT32('o','F','F','s') /* Image offset. */
+#define CHUNK_pCAL PNG_INT32('p','C','A','L') /* Pixel calibration
+ * data. */
+#define CHUNK_pHYs PNG_INT32('p','H','Y','s') /* Physical pixel
+ * dimensions. */
+#define CHUNK_sBIT PNG_INT32('s','B','I','T') /* Significant bits */
+#define CHUNK_sCAL PNG_INT32('s','C','A','L') /* Physical scale. */
+#define CHUNK_sPLT PNG_INT32('s','P','L','T') /* Suggested
+ * palette. */
+#define CHUNK_sRGB PNG_INT32('s','R','G','B') /* Standard RGB space
+ * declaration. */
+#define CHUNK_tEXt PNG_INT32('t','E','X','t') /* Plain Latin-1
+ * text. */
+#define CHUNK_tIME PNG_INT32('t','I','M','E') /* Time stamp. */
+#define CHUNK_tRNS PNG_INT32('t','R','N','S') /* Transparency. */
+#define CHUNK_zTXt PNG_INT32('z','T','X','t') /* Compressed Latin-1
+ * text. */
+
+/*
+ * Color flags.
+ */
+
+#define PNG_COLOR_INDEXED 1
+#define PNG_COLOR_USED 2
+#define PNG_COLOR_ALPHA 4
+
+/*
+ * Actual color types.
+ */
+
+#define PNG_COLOR_GRAY 0
+#define PNG_COLOR_RGB (PNG_COLOR_USED)
+#define PNG_COLOR_PLTE (PNG_COLOR_USED | PNG_COLOR_INDEXED)
+#define PNG_COLOR_GRAYALPHA (PNG_COLOR_GRAY | PNG_COLOR_ALPHA)
+#define PNG_COLOR_RGBA (PNG_COLOR_USED | PNG_COLOR_ALPHA)
+
+/*
+ * Compression Methods.
+ */
+
+#define PNG_COMPRESS_DEFLATE 0
+
+/*
+ * Filter Methods.
+ */
+
+#define PNG_FILTMETH_STANDARD 0
+
+/*
+ * Interlacing Methods.
+ */
+
+#define PNG_INTERLACE_NONE 0
+#define PNG_INTERLACE_ADAM7 1
+
+/*
+ * State information, used to store everything about the PNG image being
+ * currently parsed or created.
+ */
+
+typedef struct {
+ /*
+ * PNG data source/destination channel/object/byte array.
+ */
+
+ Tcl_Channel channel; /* Channel for from-file reads. */
+ Tcl_Obj *objDataPtr;
+ unsigned char *strDataBuf; /* Raw source data for from-string reads. */
+ int strDataLen; /* Length of source data. */
+ unsigned char *base64Data; /* base64 encoded string data. */
+ unsigned char base64Bits; /* Remaining bits from last base64 read. */
+ unsigned char base64State; /* Current state of base64 decoder. */
+ double alpha; /* Alpha from -format option. */
+
+ /*
+ * Image header information.
+ */
+
+ unsigned char bitDepth; /* Number of bits per pixel. */
+ unsigned char colorType; /* Grayscale, TrueColor, etc. */
+ unsigned char compression; /* Compression Mode (always zlib). */
+ unsigned char filter; /* Filter mode (0 - 3). */
+ unsigned char interlace; /* Type of interlacing (if any). */
+ unsigned char numChannels; /* Number of channels per pixel. */
+ unsigned char bytesPerPixel;/* Bytes per pixel in scan line. */
+ int bitScale; /* Scale factor for RGB/Gray depths < 8. */
+ int currentLine; /* Current line being unfiltered. */
+ unsigned char phase; /* Interlacing phase (0..6). */
+ Tk_PhotoImageBlock block;
+ int blockLen; /* Number of bytes in Tk image pixels. */
+
+ /*
+ * For containing data read from PLTE (palette) and tRNS (transparency)
+ * chunks.
+ */
+
+ int paletteLen; /* Number of PLTE entries (1..256). */
+ int useTRNS; /* Flag to indicate whether there was a
+ * palette given. */
+ struct {
+ unsigned char red;
+ unsigned char green;
+ unsigned char blue;
+ unsigned char alpha;
+ } palette[256]; /* Palette RGB/Transparency table. */
+ unsigned char transVal[6]; /* Fully-transparent RGB/Gray Value. */
+
+ /*
+ * For compressing and decompressing IDAT chunks.
+ */
+
+ Tcl_ZlibStream stream; /* Inflating or deflating stream; this one is
+ * not bound to a Tcl command. */
+ Tcl_Obj *lastLineObj; /* Last line of pixels, for unfiltering. */
+ Tcl_Obj *thisLineObj; /* Current line of pixels to process. */
+ int lineSize; /* Number of bytes in a PNG line. */
+ int phaseSize; /* Number of bytes/line in current phase. */
+} PNGImage;
+
+/*
+ * Maximum size of various chunks.
+ */
+
+#define PNG_PLTE_MAXSZ 768 /* 3 bytes/RGB entry, 256 entries max */
+#define PNG_TRNS_MAXSZ 256 /* 1-byte alpha, 256 entries max */
+
+/*
+ * Forward declarations of non-global functions defined in this file:
+ */
+
+static void ApplyAlpha(PNGImage *pngPtr);
+static int CheckColor(Tcl_Interp *interp, PNGImage *pngPtr);
+static inline int CheckCRC(Tcl_Interp *interp, PNGImage *pngPtr,
+ unsigned long calculated);
+static void CleanupPNGImage(PNGImage *pngPtr);
+static int DecodeLine(Tcl_Interp *interp, PNGImage *pngPtr);
+static int DecodePNG(Tcl_Interp *interp, PNGImage *pngPtr,
+ Tcl_Obj *fmtObj, Tk_PhotoHandle imageHandle,
+ int destX, int destY);
+static int EncodePNG(Tcl_Interp *interp,
+ Tk_PhotoImageBlock *blockPtr, PNGImage *pngPtr);
+static int FileMatchPNG(Tcl_Channel chan, const char *fileName,
+ Tcl_Obj *fmtObj, int *widthPtr, int *heightPtr,
+ Tcl_Interp *interp);
+static int FileReadPNG(Tcl_Interp *interp, Tcl_Channel chan,
+ const char *fileName, Tcl_Obj *fmtObj,
+ Tk_PhotoHandle imageHandle, int destX, int destY,
+ int width, int height, int srcX, int srcY);
+static int FileWritePNG(Tcl_Interp *interp, const char *filename,
+ Tcl_Obj *fmtObj, Tk_PhotoImageBlock *blockPtr);
+static int InitPNGImage(Tcl_Interp *interp, PNGImage *pngPtr,
+ Tcl_Channel chan, Tcl_Obj *objPtr, int dir);
+static inline unsigned char Paeth(int a, int b, int c);
+static int ParseFormat(Tcl_Interp *interp, Tcl_Obj *fmtObj,
+ PNGImage *pngPtr);
+static int ReadBase64(Tcl_Interp *interp, PNGImage *pngPtr,
+ unsigned char *destPtr, int destSz,
+ unsigned long *crcPtr);
+static int ReadByteArray(Tcl_Interp *interp, PNGImage *pngPtr,
+ unsigned char *destPtr, int destSz,
+ unsigned long *crcPtr);
+static int ReadData(Tcl_Interp *interp, PNGImage *pngPtr,
+ unsigned char *destPtr, int destSz,
+ unsigned long *crcPtr);
+static int ReadChunkHeader(Tcl_Interp *interp, PNGImage *pngPtr,
+ int *sizePtr, unsigned long *typePtr,
+ unsigned long *crcPtr);
+static int ReadIDAT(Tcl_Interp *interp, PNGImage *pngPtr,
+ int chunkSz, unsigned long crc);
+static int ReadIHDR(Tcl_Interp *interp, PNGImage *pngPtr);
+static inline int ReadInt32(Tcl_Interp *interp, PNGImage *pngPtr,
+ unsigned long *resultPtr, unsigned long *crcPtr);
+static int ReadPLTE(Tcl_Interp *interp, PNGImage *pngPtr,
+ int chunkSz, unsigned long crc);
+static int ReadTRNS(Tcl_Interp *interp, PNGImage *pngPtr,
+ int chunkSz, unsigned long crc);
+static int SkipChunk(Tcl_Interp *interp, PNGImage *pngPtr,
+ int chunkSz, unsigned long crc);
+static int StringMatchPNG(Tcl_Obj *dataObj, Tcl_Obj *fmtObj,
+ int *widthPtr, int *heightPtr,
+ Tcl_Interp *interp);
+static int StringReadPNG(Tcl_Interp *interp, Tcl_Obj *dataObj,
+ Tcl_Obj *fmtObj, Tk_PhotoHandle imageHandle,
+ int destX, int destY, int width, int height,
+ int srcX, int srcY);
+static int StringWritePNG(Tcl_Interp *interp, Tcl_Obj *fmtObj,
+ Tk_PhotoImageBlock *blockPtr);
+static int UnfilterLine(Tcl_Interp *interp, PNGImage *pngPtr);
+static inline int WriteByte(Tcl_Interp *interp, PNGImage *pngPtr,
+ unsigned char c, unsigned long *crcPtr);
+static inline int WriteChunk(Tcl_Interp *interp, PNGImage *pngPtr,
+ unsigned long chunkType,
+ const unsigned char *dataPtr, int dataSize);
+static int WriteData(Tcl_Interp *interp, PNGImage *pngPtr,
+ const unsigned char *srcPtr, int srcSz,
+ unsigned long *crcPtr);
+static int WriteExtraChunks(Tcl_Interp *interp,
+ PNGImage *pngPtr);
+static int WriteIHDR(Tcl_Interp *interp, PNGImage *pngPtr,
+ Tk_PhotoImageBlock *blockPtr);
+static int WriteIDAT(Tcl_Interp *interp, PNGImage *pngPtr,
+ Tk_PhotoImageBlock *blockPtr);
+static inline int WriteInt32(Tcl_Interp *interp, PNGImage *pngPtr,
+ unsigned long l, unsigned long *crcPtr);
+
+/*
+ * The format record for the PNG file format:
+ */
+
+Tk_PhotoImageFormat tkImgFmtPNG = {
+ "png", /* name */
+ FileMatchPNG, /* fileMatchProc */
+ StringMatchPNG, /* stringMatchProc */
+ FileReadPNG, /* fileReadProc */
+ StringReadPNG, /* stringReadProc */
+ FileWritePNG, /* fileWriteProc */
+ StringWritePNG, /* stringWriteProc */
+ NULL
+};
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InitPNGImage --
+ *
+ * This function is invoked by each of the Tk image handler procs
+ * (MatchStringProc, etc.) to initialize state information used during
+ * the course of encoding or decoding a PNG image.
+ *
+ * Results:
+ * TCL_OK, or TCL_ERROR if initialization failed.
+ *
+ * Side effects:
+ * The reference count of the -data Tcl_Obj*, if any, is incremented.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+InitPNGImage(
+ Tcl_Interp *interp,
+ PNGImage *pngPtr,
+ Tcl_Channel chan,
+ Tcl_Obj *objPtr,
+ int dir)
+{
+ memset(pngPtr, 0, sizeof(PNGImage));
+
+ pngPtr->channel = chan;
+ pngPtr->alpha = 1.0;
+
+ /*
+ * If decoding from a -data string object, increment its reference count
+ * for the duration of the decode and get its length and byte array for
+ * reading with ReadData().
+ */
+
+ if (objPtr) {
+ Tcl_IncrRefCount(objPtr);
+ pngPtr->objDataPtr = objPtr;
+ pngPtr->strDataBuf =
+ Tcl_GetByteArrayFromObj(objPtr, &pngPtr->strDataLen);
+ }
+
+ /*
+ * Initialize the palette transparency table to fully opaque.
+ */
+
+ memset(pngPtr->palette, 255, sizeof(pngPtr->palette));
+
+ /*
+ * Initialize Zlib inflate/deflate stream.
+ */
+
+ if (Tcl_ZlibStreamInit(NULL, dir, TCL_ZLIB_FORMAT_ZLIB,
+ TCL_ZLIB_COMPRESS_DEFAULT, NULL, &pngPtr->stream) != TCL_OK) {
+ if (interp) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "zlib initialization failed", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "ZLIB_INIT", NULL);
+ }
+ if (objPtr) {
+ Tcl_DecrRefCount(objPtr);
+ }
+ return TCL_ERROR;
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CleanupPNGImage --
+ *
+ * This function is invoked by each of the Tk image handler procs
+ * (MatchStringProc, etc.) prior to returning to Tcl in order to clean up
+ * any allocated memory and call other cleanup handlers such as zlib's
+ * inflateEnd/deflateEnd.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The reference count of the -data Tcl_Obj*, if any, is decremented.
+ * Buffers are freed, streams are closed. The PNGImage should not be used
+ * for any purpose without being reinitialized post-cleanup.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+CleanupPNGImage(
+ PNGImage *pngPtr)
+{
+ /*
+ * Don't need the object containing the -data value anymore.
+ */
+
+ if (pngPtr->objDataPtr) {
+ Tcl_DecrRefCount(pngPtr->objDataPtr);
+ }
+
+ /*
+ * Discard pixel buffer.
+ */
+
+ if (pngPtr->stream) {
+ Tcl_ZlibStreamClose(pngPtr->stream);
+ }
+
+ if (pngPtr->block.pixelPtr) {
+ ckfree(pngPtr->block.pixelPtr);
+ }
+ if (pngPtr->thisLineObj) {
+ Tcl_DecrRefCount(pngPtr->thisLineObj);
+ }
+ if (pngPtr->lastLineObj) {
+ Tcl_DecrRefCount(pngPtr->lastLineObj);
+ }
+
+ memset(pngPtr, 0, sizeof(PNGImage));
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ReadBase64 --
+ *
+ * This function is invoked to read the specified number of bytes from
+ * base-64 encoded image data.
+ *
+ * Note: It would be better if the Tk_PhotoImage stuff handled this by
+ * creating a channel from the -data value, which would take care of
+ * base64 decoding and made the data readable as if it were coming from a
+ * file.
+ *
+ * Results:
+ * TCL_OK, or TCL_ERROR if an I/O error occurs.
+ *
+ * Side effects:
+ * The file position will change. The running CRC is updated if a pointer
+ * to it is provided.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ReadBase64(
+ Tcl_Interp *interp,
+ PNGImage *pngPtr,
+ unsigned char *destPtr,
+ int destSz,
+ unsigned long *crcPtr)
+{
+ static const unsigned char from64[] = {
+ 0x82, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x80, 0x80,
+ 0x83, 0x80, 0x80, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
+ 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x80,
+ 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x3e,
+ 0x83, 0x83, 0x83, 0x3f, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a,
+ 0x3b, 0x3c, 0x3d, 0x83, 0x83, 0x83, 0x81, 0x83, 0x83, 0x83, 0x00,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
+ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+ 0x17, 0x18, 0x19, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x1a, 0x1b,
+ 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+ 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31,
+ 0x32, 0x33, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
+ 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
+ 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
+ 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
+ 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
+ 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
+ 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
+ 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
+ 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
+ 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
+ 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
+ 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
+ 0x83, 0x83
+ };
+
+ /*
+ * Definitions for the base-64 decoder.
+ */
+
+#define PNG64_SPECIAL 0x80 /* Flag bit */
+#define PNG64_SPACE 0x80 /* Whitespace */
+#define PNG64_PAD 0x81 /* Padding */
+#define PNG64_DONE 0x82 /* End of data */
+#define PNG64_BAD 0x83 /* Ooooh, naughty! */
+
+ while (destSz && pngPtr->strDataLen) {
+ unsigned char c = 0;
+ unsigned char c64 = from64[*pngPtr->strDataBuf++];
+
+ pngPtr->strDataLen--;
+
+ if (PNG64_SPACE == c64) {
+ continue;
+ }
+
+ if (c64 & PNG64_SPECIAL) {
+ c = (unsigned char) pngPtr->base64Bits;
+ } else {
+ switch (pngPtr->base64State++) {
+ case 0:
+ pngPtr->base64Bits = c64 << 2;
+ continue;
+ case 1:
+ c = (unsigned char) (pngPtr->base64Bits | (c64 >> 4));
+ pngPtr->base64Bits = (c64 & 0xF) << 4;
+ break;
+ case 2:
+ c = (unsigned char) (pngPtr->base64Bits | (c64 >> 2));
+ pngPtr->base64Bits = (c64 & 0x3) << 6;
+ break;
+ case 3:
+ c = (unsigned char) (pngPtr->base64Bits | c64);
+ pngPtr->base64State = 0;
+ pngPtr->base64Bits = 0;
+ break;
+ }
+ }
+
+ if (crcPtr) {
+ *crcPtr = Tcl_ZlibCRC32(*crcPtr, &c, 1);
+ }
+
+ if (destPtr) {
+ *destPtr++ = c;
+ }
+
+ destSz--;
+
+ if (c64 & PNG64_SPECIAL) {
+ break;
+ }
+ }
+
+ if (destSz) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "unexpected end of image data", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "EARLY_END", NULL);
+ return TCL_ERROR;
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ReadByteArray --
+ *
+ * This function is invoked to read the specified number of bytes from a
+ * non-base64-encoded byte array provided via the -data option.
+ *
+ * Note: It would be better if the Tk_PhotoImage stuff handled this by
+ * creating a channel from the -data value and made the data readable as
+ * if it were coming from a file.
+ *
+ * Results:
+ * TCL_OK, or TCL_ERROR if an I/O error occurs.
+ *
+ * Side effects:
+ * The file position will change. The running CRC is updated if a pointer
+ * to it is provided.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ReadByteArray(
+ Tcl_Interp *interp,
+ PNGImage *pngPtr,
+ unsigned char *destPtr,
+ int destSz,
+ unsigned long *crcPtr)
+{
+ /*
+ * Check to make sure the number of requested bytes are available.
+ */
+
+ if (pngPtr->strDataLen < destSz) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "unexpected end of image data", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "EARLY_END", NULL);
+ return TCL_ERROR;
+ }
+
+ while (destSz) {
+ int blockSz = PNG_MIN(destSz, PNG_BLOCK_SZ);
+
+ memcpy(destPtr, pngPtr->strDataBuf, blockSz);
+
+ pngPtr->strDataBuf += blockSz;
+ pngPtr->strDataLen -= blockSz;
+
+ if (crcPtr) {
+ *crcPtr = Tcl_ZlibCRC32(*crcPtr, destPtr, blockSz);
+ }
+
+ destPtr += blockSz;
+ destSz -= blockSz;
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ReadData --
+ *
+ * This function is invoked to read the specified number of bytes from
+ * the image file or data. It is a wrapper around the choice of byte
+ * array Tcl_Obj or Tcl_Channel which depends on whether the image data
+ * is coming from a file or -data.
+ *
+ * Results:
+ * TCL_OK, or TCL_ERROR if an I/O error occurs.
+ *
+ * Side effects:
+ * The file position will change. The running CRC is updated if a pointer
+ * to it is provided.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ReadData(
+ Tcl_Interp *interp,
+ PNGImage *pngPtr,
+ unsigned char *destPtr,
+ int destSz,
+ unsigned long *crcPtr)
+{
+ if (pngPtr->base64Data) {
+ return ReadBase64(interp, pngPtr, destPtr, destSz, crcPtr);
+ } else if (pngPtr->strDataBuf) {
+ return ReadByteArray(interp, pngPtr, destPtr, destSz, crcPtr);
+ }
+
+ while (destSz) {
+ int blockSz = PNG_MIN(destSz, PNG_BLOCK_SZ);
+
+ blockSz = Tcl_Read(pngPtr->channel, (char *)destPtr, blockSz);
+ if (blockSz < 0) {
+ /* TODO: failure info... */
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "channel read failed: %s", Tcl_PosixError(interp)));
+ return TCL_ERROR;
+ }
+
+ /*
+ * Update CRC, pointer, and remaining count if anything was read.
+ */
+
+ if (blockSz) {
+ if (crcPtr) {
+ *crcPtr = Tcl_ZlibCRC32(*crcPtr, destPtr, blockSz);
+ }
+
+ destPtr += blockSz;
+ destSz -= blockSz;
+ }
+
+ /*
+ * Check for EOF before all desired data was read.
+ */
+
+ if (destSz && Tcl_Eof(pngPtr->channel)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "unexpected end of file", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "EOF", NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ReadInt32 --
+ *
+ * This function is invoked to read a 32-bit integer in network byte
+ * order from the image data and return the value in host byte order.
+ * This is used, for example, to read the 32-bit CRC value for a chunk
+ * stored in the image file for comparison with the calculated CRC value.
+ *
+ * Results:
+ * TCL_OK, or TCL_ERROR if an I/O error occurs.
+ *
+ * Side effects:
+ * The file position will change. The running CRC is updated if a pointer
+ * to it is provided.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static inline int
+ReadInt32(
+ Tcl_Interp *interp,
+ PNGImage *pngPtr,
+ unsigned long *resultPtr,
+ unsigned long *crcPtr)
+{
+ unsigned char p[4];
+
+ if (ReadData(interp, pngPtr, p, 4, crcPtr) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ *resultPtr = PNG_INT32(p[0], p[1], p[2], p[3]);
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CheckCRC --
+ *
+ * This function is reads the final 4-byte integer CRC from a chunk and
+ * compares it to the running CRC calculated over the chunk type and data
+ * fields.
+ *
+ * Results:
+ * TCL_OK, or TCL_ERROR if an I/O error or CRC mismatch occurs.
+ *
+ * Side effects:
+ * The file position will change.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static inline int
+CheckCRC(
+ Tcl_Interp *interp,
+ PNGImage *pngPtr,
+ unsigned long calculated)
+{
+ unsigned long chunked;
+
+ /*
+ * Read the CRC field at the end of the chunk.
+ */
+
+ if (ReadInt32(interp, pngPtr, &chunked, NULL) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Compare the read CRC to what we calculate to make sure they match.
+ */
+
+ if (calculated != chunked) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("CRC check failed", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "CRC", NULL);
+ return TCL_ERROR;
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SkipChunk --
+ *
+ * This function is used to skip a PNG chunk that is not used by this
+ * implementation. Given the input stream has had the chunk length and
+ * chunk type fields already read, this function will read the number of
+ * bytes indicated by the chunk length, plus four for the CRC, and will
+ * verify that CRC is correct for the skipped data.
+ *
+ * Results:
+ * TCL_OK, or TCL_ERROR if an I/O error or CRC mismatch occurs.
+ *
+ * Side effects:
+ * The file position will change.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SkipChunk(
+ Tcl_Interp *interp,
+ PNGImage *pngPtr,
+ int chunkSz,
+ unsigned long crc)
+{
+ unsigned char buffer[PNG_BLOCK_SZ];
+
+ /*
+ * Skip data in blocks until none is left. Read up to PNG_BLOCK_SZ bytes
+ * at a time, rather than trusting the claimed chunk size, which may not
+ * be trustworthy.
+ */
+
+ while (chunkSz) {
+ int blockSz = PNG_MIN(chunkSz, PNG_BLOCK_SZ);
+
+ if (ReadData(interp, pngPtr, buffer, blockSz, &crc) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ chunkSz -= blockSz;
+ }
+
+ if (CheckCRC(interp, pngPtr, crc) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ return TCL_OK;
+}
+
+/*
+ * 4.3. Summary of standard chunks
+ *
+ * This table summarizes some properties of the standard chunk types.
+ *
+ * Critical chunks (must appear in this order, except PLTE is optional):
+ *
+ * Name Multiple Ordering constraints OK?
+ *
+ * IHDR No Must be first
+ * PLTE No Before IDAT
+ * IDAT Yes Multiple IDATs must be consecutive
+ * IEND No Must be last
+ *
+ * Ancillary chunks (need not appear in this order):
+ *
+ * Name Multiple Ordering constraints OK?
+ *
+ * cHRM No Before PLTE and IDAT
+ * gAMA No Before PLTE and IDAT
+ * iCCP No Before PLTE and IDAT
+ * sBIT No Before PLTE and IDAT
+ * sRGB No Before PLTE and IDAT
+ * bKGD No After PLTE; before IDAT
+ * hIST No After PLTE; before IDAT
+ * tRNS No After PLTE; before IDAT
+ * pHYs No Before IDAT
+ * sPLT Yes Before IDAT
+ * tIME No None
+ * iTXt Yes None
+ * tEXt Yes None
+ * zTXt Yes None
+ *
+ * [From the PNG specification.]
+ */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ReadChunkHeader --
+ *
+ * This function is used at the start of each chunk to extract the
+ * four-byte chunk length and four-byte chunk type fields. It will
+ * continue reading until it finds a chunk type that is handled by this
+ * implementation, checking the CRC of any chunks it skips.
+ *
+ * Results:
+ * TCL_OK, or TCL_ERROR if an I/O error occurs or an unknown critical
+ * chunk type is encountered.
+ *
+ * Side effects:
+ * The file position will change. The running CRC is updated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ReadChunkHeader(
+ Tcl_Interp *interp,
+ PNGImage *pngPtr,
+ int *sizePtr,
+ unsigned long *typePtr,
+ unsigned long *crcPtr)
+{
+ unsigned long chunkType = 0;
+ int chunkSz = 0;
+ unsigned long crc = 0;
+
+ /*
+ * Continue until finding a chunk type that is handled.
+ */
+
+ while (!chunkType) {
+ unsigned long temp;
+ unsigned char pc[4];
+ int i;
+
+ /*
+ * Read the 4-byte length field for the chunk. The length field is not
+ * included in the CRC calculation, so the running CRC must be reset
+ * afterward. Limit chunk lengths to INT_MAX, to align with the
+ * maximum size for Tcl_Read, Tcl_GetByteArrayFromObj, etc.
+ */
+
+ if (ReadData(interp, pngPtr, pc, 4, NULL) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ temp = PNG_INT32(pc[0], pc[1], pc[2], pc[3]);
+
+ if (temp > INT_MAX) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "chunk size is out of supported range on this architecture",
+ -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "OUTSIZE", NULL);
+ return TCL_ERROR;
+ }
+
+ chunkSz = (int) temp;
+ crc = Tcl_ZlibCRC32(0, NULL, 0);
+
+ /*
+ * Read the 4-byte chunk type.
+ */
+
+ if (ReadData(interp, pngPtr, pc, 4, &crc) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Convert it to a host-order integer for simple comparison.
+ */
+
+ chunkType = PNG_INT32(pc[0], pc[1], pc[2], pc[3]);
+
+ /*
+ * Check to see if this is a known/supported chunk type. Note that the
+ * PNG specs require non-critical (i.e., ancillary) chunk types that
+ * are not recognized to be ignored, rather than be treated as an
+ * error. It does, however, recommend that an unknown critical chunk
+ * type be treated as a failure.
+ *
+ * This switch/loop acts as a filter of sorts for undesired chunk
+ * types. The chunk type should still be checked elsewhere for
+ * determining it is in the correct order.
+ */
+
+ switch (chunkType) {
+ /*
+ * These chunk types are required and/or supported.
+ */
+
+ case CHUNK_IDAT:
+ case CHUNK_IEND:
+ case CHUNK_IHDR:
+ case CHUNK_PLTE:
+ case CHUNK_tRNS:
+ break;
+
+ /*
+ * These chunk types are part of the standard, but are not used by
+ * this implementation (at least not yet). Note that these are all
+ * ancillary chunks (lowercase first letter).
+ */
+
+ case CHUNK_bKGD:
+ case CHUNK_cHRM:
+ case CHUNK_gAMA:
+ case CHUNK_hIST:
+ case CHUNK_iCCP:
+ case CHUNK_iTXt:
+ case CHUNK_oFFs:
+ case CHUNK_pCAL:
+ case CHUNK_pHYs:
+ case CHUNK_sBIT:
+ case CHUNK_sCAL:
+ case CHUNK_sPLT:
+ case CHUNK_sRGB:
+ case CHUNK_tEXt:
+ case CHUNK_tIME:
+ case CHUNK_zTXt:
+ /*
+ * TODO: might want to check order here.
+ */
+
+ if (SkipChunk(interp, pngPtr, chunkSz, crc) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ chunkType = 0;
+ break;
+
+ default:
+ /*
+ * Unknown chunk type. If it's critical, we can't continue.
+ */
+
+ if (!(chunkType & PNG_CF_ANCILLARY)) {
+ if (chunkType & PNG_INT32(128,128,128,128)) {
+ /*
+ * No nice ASCII conversion; shouldn't happen either, but
+ * we'll be doubly careful.
+ */
+
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "encountered an unsupported critical chunk type",
+ -1));
+ } else {
+ char typeString[5];
+
+ typeString[0] = (char) ((chunkType >> 24) & 255);
+ typeString[1] = (char) ((chunkType >> 16) & 255);
+ typeString[2] = (char) ((chunkType >> 8) & 255);
+ typeString[3] = (char) (chunkType & 255);
+ typeString[4] = '\0';
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "encountered an unsupported critical chunk type"
+ " \"%s\"", typeString));
+ }
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG",
+ "UNSUPPORTED_CRITICAL", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Check to see if the chunk type has legal bytes.
+ */
+
+ for (i=0 ; i<4 ; i++) {
+ if ((pc[i] < 65) || (pc[i] > 122) ||
+ ((pc[i] > 90) && (pc[i] < 97))) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "invalid chunk type", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG",
+ "INVALID_CHUNK", NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * It seems to be an otherwise legally labelled ancillary chunk
+ * that we don't want, so skip it after at least checking its CRC.
+ */
+
+ if (SkipChunk(interp, pngPtr, chunkSz, crc) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ chunkType = 0;
+ }
+ }
+
+ /*
+ * Found a known chunk type that's handled, albiet possibly not in the
+ * right order. Send back the chunk type (for further checking or
+ * handling), the chunk size and the current CRC for the rest of the
+ * calculation.
+ */
+
+ *typePtr = chunkType;
+ *sizePtr = chunkSz;
+ *crcPtr = crc;
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CheckColor --
+ *
+ * Do validation on color type, depth, and related information, and
+ * calculates storage requirements and offsets based on image dimensions
+ * and color.
+ *
+ * Results:
+ * TCL_OK, or TCL_ERROR if color information is invalid or some other
+ * failure occurs.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CheckColor(
+ Tcl_Interp *interp,
+ PNGImage *pngPtr)
+{
+ int offset;
+
+ /*
+ * Verify the color type is valid and the bit depth is allowed.
+ */
+
+ switch (pngPtr->colorType) {
+ case PNG_COLOR_GRAY:
+ pngPtr->numChannels = 1;
+ if ((1 != pngPtr->bitDepth) && (2 != pngPtr->bitDepth) &&
+ (4 != pngPtr->bitDepth) && (8 != pngPtr->bitDepth) &&
+ (16 != pngPtr->bitDepth)) {
+ goto unsupportedDepth;
+ }
+ break;
+
+ case PNG_COLOR_RGB:
+ pngPtr->numChannels = 3;
+ if ((8 != pngPtr->bitDepth) && (16 != pngPtr->bitDepth)) {
+ goto unsupportedDepth;
+ }
+ break;
+
+ case PNG_COLOR_PLTE:
+ pngPtr->numChannels = 1;
+ if ((1 != pngPtr->bitDepth) && (2 != pngPtr->bitDepth) &&
+ (4 != pngPtr->bitDepth) && (8 != pngPtr->bitDepth)) {
+ goto unsupportedDepth;
+ }
+ break;
+
+ case PNG_COLOR_GRAYALPHA:
+ pngPtr->numChannels = 2;
+ if ((8 != pngPtr->bitDepth) && (16 != pngPtr->bitDepth)) {
+ goto unsupportedDepth;
+ }
+ break;
+
+ case PNG_COLOR_RGBA:
+ pngPtr->numChannels = 4;
+ if ((8 != pngPtr->bitDepth) && (16 != pngPtr->bitDepth)) {
+ unsupportedDepth:
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "bit depth is not allowed for given color type", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "BAD_DEPTH", NULL);
+ return TCL_ERROR;
+ }
+ break;
+
+ default:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "unknown color type field %d", pngPtr->colorType));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "UNKNOWN_COLOR", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Set up the Tk photo block's pixel size and channel offsets. offset
+ * array elements should already be 0 from the memset during InitPNGImage.
+ */
+
+ offset = (pngPtr->bitDepth > 8) ? 2 : 1;
+
+ if (pngPtr->colorType & PNG_COLOR_USED) {
+ pngPtr->block.pixelSize = offset * 4;
+ pngPtr->block.offset[1] = offset;
+ pngPtr->block.offset[2] = offset * 2;
+ pngPtr->block.offset[3] = offset * 3;
+ } else {
+ pngPtr->block.pixelSize = offset * 2;
+ pngPtr->block.offset[3] = offset;
+ }
+
+ /*
+ * Calculate the block pitch, which is the number of bytes per line in the
+ * image, given image width and depth of color. Make sure that it it isn't
+ * larger than Tk can handle.
+ */
+
+ if (pngPtr->block.width > INT_MAX / pngPtr->block.pixelSize) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "image pitch is out of supported range on this architecture",
+ -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "PITCH", NULL);
+ return TCL_ERROR;
+ }
+
+ pngPtr->block.pitch = pngPtr->block.pixelSize * pngPtr->block.width;
+
+ /*
+ * Calculate the total size of the image as represented to Tk given pitch
+ * and image height. Make sure that it isn't larger than Tk can handle.
+ */
+
+ if (pngPtr->block.height > INT_MAX / pngPtr->block.pitch) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "image total size is out of supported range on this architecture",
+ -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "SIZE", NULL);
+ return TCL_ERROR;
+ }
+
+ pngPtr->blockLen = pngPtr->block.height * pngPtr->block.pitch;
+
+ /*
+ * Determine number of bytes per pixel in the source for later use.
+ */
+
+ switch (pngPtr->colorType) {
+ case PNG_COLOR_GRAY:
+ pngPtr->bytesPerPixel = (pngPtr->bitDepth > 8) ? 2 : 1;
+ break;
+ case PNG_COLOR_RGB:
+ pngPtr->bytesPerPixel = (pngPtr->bitDepth > 8) ? 6 : 3;
+ break;
+ case PNG_COLOR_PLTE:
+ pngPtr->bytesPerPixel = 1;
+ break;
+ case PNG_COLOR_GRAYALPHA:
+ pngPtr->bytesPerPixel = (pngPtr->bitDepth > 8) ? 4 : 2;
+ break;
+ case PNG_COLOR_RGBA:
+ pngPtr->bytesPerPixel = (pngPtr->bitDepth > 8) ? 8 : 4;
+ break;
+ default:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "unknown color type %d", pngPtr->colorType));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "UNKNOWN_COLOR", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Calculate scale factor for bit depths less than 8, in order to adjust
+ * them to a minimum of 8 bits per pixel in the Tk image.
+ */
+
+ if (pngPtr->bitDepth < 8) {
+ pngPtr->bitScale = 255 / (int)(pow(2, pngPtr->bitDepth) - 1);
+ } else {
+ pngPtr->bitScale = 1;
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ReadIHDR --
+ *
+ * This function reads the PNG header from the beginning of a PNG file
+ * and returns the dimensions of the image.
+ *
+ * Results:
+ * The return value is 1 if file "f" appears to start with a valid PNG
+ * header, 0 otherwise. If the header is valid, then *widthPtr and
+ * *heightPtr are modified to hold the dimensions of the image.
+ *
+ * Side effects:
+ * The access position in f advances.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ReadIHDR(
+ Tcl_Interp *interp,
+ PNGImage *pngPtr)
+{
+ unsigned char sigBuf[PNG_SIG_SZ];
+ unsigned long chunkType;
+ int chunkSz;
+ unsigned long crc;
+ unsigned long width, height;
+ int mismatch;
+
+ /*
+ * Read the appropriate number of bytes for the PNG signature.
+ */
+
+ if (ReadData(interp, pngPtr, sigBuf, PNG_SIG_SZ, NULL) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Compare the read bytes to the expected signature.
+ */
+
+ mismatch = memcmp(sigBuf, pngSignature, PNG_SIG_SZ);
+
+ /*
+ * If reading from string, reset position and try base64 decode.
+ */
+
+ if (mismatch && pngPtr->strDataBuf) {
+ pngPtr->strDataBuf = Tcl_GetByteArrayFromObj(pngPtr->objDataPtr,
+ &pngPtr->strDataLen);
+ pngPtr->base64Data = pngPtr->strDataBuf;
+
+ if (ReadData(interp, pngPtr, sigBuf, PNG_SIG_SZ, NULL) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ mismatch = memcmp(sigBuf, pngSignature, PNG_SIG_SZ);
+ }
+
+ if (mismatch) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "data stream does not have a PNG signature", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "NO_SIG", NULL);
+ return TCL_ERROR;
+ }
+
+ if (ReadChunkHeader(interp, pngPtr, &chunkSz, &chunkType,
+ &crc) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Read in the IHDR (header) chunk for width, height, etc.
+ *
+ * The first chunk in the file must be the IHDR (headr) chunk.
+ */
+
+ if (chunkType != CHUNK_IHDR) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "expected IHDR chunk type", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "NO_IHDR", NULL);
+ return TCL_ERROR;
+ }
+
+ if (chunkSz != 13) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "invalid IHDR chunk size", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "BAD_IHDR", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Read and verify the image width and height to be sure Tk can handle its
+ * dimensions. The PNG specification does not permit zero-width or
+ * zero-height images.
+ */
+
+ if (ReadInt32(interp, pngPtr, &width, &crc) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ if (ReadInt32(interp, pngPtr, &height, &crc) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ if (!width || !height || (width > INT_MAX) || (height > INT_MAX)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "image dimensions are invalid or beyond architecture limits",
+ -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "DIMENSIONS", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Set height and width for the Tk photo block.
+ */
+
+ pngPtr->block.width = (int) width;
+ pngPtr->block.height = (int) height;
+
+ /*
+ * Read and the Bit Depth and Color Type.
+ */
+
+ if (ReadData(interp, pngPtr, &pngPtr->bitDepth, 1, &crc) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ if (ReadData(interp, pngPtr, &pngPtr->colorType, 1, &crc) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Verify that the color type is valid, the bit depth is allowed for the
+ * color type, and calculate the number of channels and pixel depth (bits
+ * per pixel * channels). Also set up offsets and sizes in the Tk photo
+ * block for the pixel data.
+ */
+
+ if (CheckColor(interp, pngPtr) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Only one compression method is currently defined by the standard.
+ */
+
+ if (ReadData(interp, pngPtr, &pngPtr->compression, 1, &crc) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ if (pngPtr->compression != PNG_COMPRESS_DEFLATE) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "unknown compression method %d", pngPtr->compression));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "BAD_COMPRESS", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Only one filter method is currently defined by the standard; the method
+ * has five actual filter types associated with it.
+ */
+
+ if (ReadData(interp, pngPtr, &pngPtr->filter, 1, &crc) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ if (pngPtr->filter != PNG_FILTMETH_STANDARD) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "unknown filter method %d", pngPtr->filter));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "BAD_FILTER", NULL);
+ return TCL_ERROR;
+ }
+
+ if (ReadData(interp, pngPtr, &pngPtr->interlace, 1, &crc) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ switch (pngPtr->interlace) {
+ case PNG_INTERLACE_NONE:
+ case PNG_INTERLACE_ADAM7:
+ break;
+
+ default:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "unknown interlace method %d", pngPtr->interlace));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "BAD_INTERLACE", NULL);
+ return TCL_ERROR;
+ }
+
+ return CheckCRC(interp, pngPtr, crc);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ReadPLTE --
+ *
+ * This function reads the PLTE (indexed color palette) chunk data from
+ * the PNG file and populates the palette table in the PNGImage
+ * structure.
+ *
+ * Results:
+ * TCL_OK, or TCL_ERROR if an I/O error occurs or the PLTE chunk is
+ * invalid.
+ *
+ * Side effects:
+ * The access position in f advances.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ReadPLTE(
+ Tcl_Interp *interp,
+ PNGImage *pngPtr,
+ int chunkSz,
+ unsigned long crc)
+{
+ unsigned char buffer[PNG_PLTE_MAXSZ];
+ int i, c;
+
+ /*
+ * This chunk is mandatory for color type 3 and forbidden for 2 and 6.
+ */
+
+ switch (pngPtr->colorType) {
+ case PNG_COLOR_GRAY:
+ case PNG_COLOR_GRAYALPHA:
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "PLTE chunk type forbidden for grayscale", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "PLTE_UNEXPECTED",
+ NULL);
+ return TCL_ERROR;
+
+ default:
+ break;
+ }
+
+ /*
+ * The palette chunk contains from 1 to 256 palette entries. Each entry
+ * consists of a 3-byte RGB value. It must therefore contain a non-zero
+ * multiple of 3 bytes, up to 768.
+ */
+
+ if (!chunkSz || (chunkSz > PNG_PLTE_MAXSZ) || (chunkSz % 3)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "invalid palette chunk size", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "BAD_PLTE", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Read the palette contents and stash them for later, possibly.
+ */
+
+ if (ReadData(interp, pngPtr, buffer, chunkSz, &crc) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ if (CheckCRC(interp, pngPtr, crc) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Stash away the palette entries and entry count for later mapping each
+ * pixel's palette index to its color.
+ */
+
+ for (i=0, c=0 ; c<chunkSz ; i++) {
+ pngPtr->palette[i].red = buffer[c++];
+ pngPtr->palette[i].green = buffer[c++];
+ pngPtr->palette[i].blue = buffer[c++];
+ }
+
+ pngPtr->paletteLen = i;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ReadTRNS --
+ *
+ * This function reads the tRNS (transparency) chunk data from the PNG
+ * file and populates the alpha field of the palette table in the
+ * PNGImage structure or the single color transparency, as appropriate
+ * for the color type.
+ *
+ * Results:
+ * TCL_OK, or TCL_ERROR if an I/O error occurs or the tRNS chunk is
+ * invalid.
+ *
+ * Side effects:
+ * The access position in f advances.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ReadTRNS(
+ Tcl_Interp *interp,
+ PNGImage *pngPtr,
+ int chunkSz,
+ unsigned long crc)
+{
+ unsigned char buffer[PNG_TRNS_MAXSZ];
+ int i;
+
+ if (pngPtr->colorType & PNG_COLOR_ALPHA) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "tRNS chunk not allowed color types with a full alpha channel",
+ -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "INVALID_TRNS", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * For indexed color, there is up to one single-byte transparency value
+ * per palette entry (thus a max of 256).
+ */
+
+ if (chunkSz > PNG_TRNS_MAXSZ) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "invalid tRNS chunk size", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "BAD_TRNS", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Read in the raw transparency information.
+ */
+
+ if (ReadData(interp, pngPtr, buffer, chunkSz, &crc) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ if (CheckCRC(interp, pngPtr, crc) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ switch (pngPtr->colorType) {
+ case PNG_COLOR_GRAYALPHA:
+ case PNG_COLOR_RGBA:
+ break;
+
+ case PNG_COLOR_PLTE:
+ /*
+ * The number of tRNS entries must be less than or equal to the number
+ * of PLTE entries, and consists of a single-byte alpha level for the
+ * corresponding PLTE entry.
+ */
+
+ if (chunkSz > pngPtr->paletteLen) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "size of tRNS chunk is too large for the palette", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "TRNS_SIZE", NULL);
+ return TCL_ERROR;
+ }
+
+ for (i=0 ; i<chunkSz ; i++) {
+ pngPtr->palette[i].alpha = buffer[i];
+ }
+ break;
+
+ case PNG_COLOR_GRAY:
+ /*
+ * Grayscale uses a single 2-byte gray level, which we'll store in
+ * palette index 0, since we're not using the palette.
+ */
+
+ if (chunkSz != 2) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "invalid tRNS chunk size - must 2 bytes for grayscale",
+ -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "BAD_TRNS", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * According to the PNG specs, if the bit depth is less than 16, then
+ * only the lower byte is used.
+ */
+
+ if (16 == pngPtr->bitDepth) {
+ pngPtr->transVal[0] = buffer[0];
+ pngPtr->transVal[1] = buffer[1];
+ } else {
+ pngPtr->transVal[0] = buffer[1];
+ }
+ pngPtr->useTRNS = 1;
+ break;
+
+ case PNG_COLOR_RGB:
+ /*
+ * TrueColor uses a single RRGGBB triplet.
+ */
+
+ if (chunkSz != 6) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "invalid tRNS chunk size - must 6 bytes for RGB", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "BAD_TRNS", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * According to the PNG specs, if the bit depth is less than 16, then
+ * only the lower byte is used. But the tRNS chunk still contains two
+ * bytes per channel.
+ */
+
+ if (16 == pngPtr->bitDepth) {
+ memcpy(pngPtr->transVal, buffer, 6);
+ } else {
+ pngPtr->transVal[0] = buffer[1];
+ pngPtr->transVal[1] = buffer[3];
+ pngPtr->transVal[2] = buffer[5];
+ }
+ pngPtr->useTRNS = 1;
+ break;
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Paeth --
+ *
+ * Utility function for applying the Paeth filter to a pixel. The Paeth
+ * filter is a linear function of the pixel to be filtered and the pixels
+ * to the left, above, and above-left of the pixel to be unfiltered.
+ *
+ * Results:
+ * Result of the Paeth function for the left, above, and above-left
+ * pixels.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static inline unsigned char
+Paeth(
+ int a,
+ int b,
+ int c)
+{
+ int pa = abs(b - c);
+ int pb = abs(a - c);
+ int pc = abs(a + b - c - c);
+
+ if ((pa <= pb) && (pa <= pc)) {
+ return (unsigned char) a;
+ }
+
+ if (pb <= pc) {
+ return (unsigned char) b;
+ }
+
+ return (unsigned char) c;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UnfilterLine --
+ *
+ * Applies the filter algorithm specified in first byte of a line to the
+ * line of pixels being read from a PNG image.
+ *
+ * PNG specifies four filter algorithms (Sub, Up, Average, and Paeth)
+ * that combine a pixel's value with those of other pixels in the same
+ * and/or previous lines. Filtering is intended to make an image more
+ * compressible.
+ *
+ * Results:
+ * TCL_OK, or TCL_ERROR if the filter type is not recognized.
+ *
+ * Side effects:
+ * Pixel data in thisLineObj are modified.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+UnfilterLine(
+ Tcl_Interp *interp,
+ PNGImage *pngPtr)
+{
+ unsigned char *thisLine =
+ Tcl_GetByteArrayFromObj(pngPtr->thisLineObj, NULL);
+ unsigned char *lastLine =
+ Tcl_GetByteArrayFromObj(pngPtr->lastLineObj, NULL);
+
+#define PNG_FILTER_NONE 0
+#define PNG_FILTER_SUB 1
+#define PNG_FILTER_UP 2
+#define PNG_FILTER_AVG 3
+#define PNG_FILTER_PAETH 4
+
+ switch (*thisLine) {
+ case PNG_FILTER_NONE: /* Nothing to do */
+ break;
+ case PNG_FILTER_SUB: { /* Sub(x) = Raw(x) - Raw(x-bpp) */
+ unsigned char *rawBpp = thisLine + 1;
+ unsigned char *raw = rawBpp + pngPtr->bytesPerPixel;
+ unsigned char *end = thisLine + pngPtr->phaseSize;
+
+ while (raw < end) {
+ *raw++ += *rawBpp++;
+ }
+ break;
+ }
+ case PNG_FILTER_UP: /* Up(x) = Raw(x) - Prior(x) */
+ if (pngPtr->currentLine > startLine[pngPtr->phase]) {
+ unsigned char *prior = lastLine + 1;
+ unsigned char *raw = thisLine + 1;
+ unsigned char *end = thisLine + pngPtr->phaseSize;
+
+ while (raw < end) {
+ *raw++ += *prior++;
+ }
+ }
+ break;
+ case PNG_FILTER_AVG:
+ /* Avg(x) = Raw(x) - floor((Raw(x-bpp)+Prior(x))/2) */
+ if (pngPtr->currentLine > startLine[pngPtr->phase]) {
+ unsigned char *prior = lastLine + 1;
+ unsigned char *rawBpp = thisLine + 1;
+ unsigned char *raw = rawBpp;
+ unsigned char *end = thisLine + pngPtr->phaseSize;
+ unsigned char *end2 = raw + pngPtr->bytesPerPixel;
+
+ while ((raw < end2) && (raw < end)) {
+ *raw++ += *prior++ / 2;
+ }
+
+ while (raw < end) {
+ *raw++ += (unsigned char)
+ (((int) *rawBpp++ + (int) *prior++) / 2);
+ }
+ } else {
+ unsigned char *rawBpp = thisLine + 1;
+ unsigned char *raw = rawBpp + pngPtr->bytesPerPixel;
+ unsigned char *end = thisLine + pngPtr->phaseSize;
+
+ while (raw < end) {
+ *raw++ += *rawBpp++ / 2;
+ }
+ }
+ break;
+ case PNG_FILTER_PAETH:
+ /* Paeth(x) = Raw(x) - PaethPredictor(Raw(x-bpp), Prior(x), Prior(x-bpp)) */
+ if (pngPtr->currentLine > startLine[pngPtr->phase]) {
+ unsigned char *priorBpp = lastLine + 1;
+ unsigned char *prior = priorBpp;
+ unsigned char *rawBpp = thisLine + 1;
+ unsigned char *raw = rawBpp;
+ unsigned char *end = thisLine + pngPtr->phaseSize;
+ unsigned char *end2 = rawBpp + pngPtr->bytesPerPixel;
+
+ while ((raw < end) && (raw < end2)) {
+ *raw++ += *prior++;
+ }
+
+ while (raw < end) {
+ *raw++ += Paeth(*rawBpp++, *prior++, *priorBpp++);
+ }
+ } else {
+ unsigned char *rawBpp = thisLine + 1;
+ unsigned char *raw = rawBpp + pngPtr->bytesPerPixel;
+ unsigned char *end = thisLine + pngPtr->phaseSize;
+
+ while (raw < end) {
+ *raw++ += *rawBpp++;
+ }
+ }
+ break;
+ default:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "invalid filter type %d", *thisLine));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "BAD_FILTER", NULL);
+ return TCL_ERROR;
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DecodeLine --
+ *
+ * Unfilters a line of pixels from the PNG source data and decodes the
+ * data into the Tk_PhotoImageBlock for later copying into the Tk image.
+ *
+ * Results:
+ * TCL_OK, or TCL_ERROR if the filter type is not recognized.
+ *
+ * Side effects:
+ * Pixel data in thisLine and block are modified and state information
+ * updated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DecodeLine(
+ Tcl_Interp *interp,
+ PNGImage *pngPtr)
+{
+ unsigned char *pixelPtr = pngPtr->block.pixelPtr;
+ int colNum = 0; /* Current pixel column */
+ unsigned char chan = 0; /* Current channel (0..3) = (R, G, B, A) */
+ unsigned char readByte = 0; /* Current scan line byte */
+ int haveBits = 0; /* Number of bits remaining in current byte */
+ unsigned char pixBits = 0; /* Extracted bits for current channel */
+ int shifts = 0; /* Number of channels extracted from byte */
+ int offset = 0; /* Current offset into pixelPtr */
+ int colStep = 1; /* Column increment each pass */
+ int pixStep = 0; /* extra pixelPtr increment each pass */
+ unsigned char lastPixel[6];
+ unsigned char *p = Tcl_GetByteArrayFromObj(pngPtr->thisLineObj, NULL);
+
+ p++;
+ if (UnfilterLine(interp, pngPtr) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ if (pngPtr->currentLine >= pngPtr->block.height) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "PNG image data overflow"));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "DATA_OVERFLOW", NULL);
+ return TCL_ERROR;
+ }
+
+
+ if (pngPtr->interlace) {
+ switch (pngPtr->phase) {
+ case 1: /* Phase 1: */
+ colStep = 8; /* 1 pixel per block of 8 per line */
+ break; /* Start at column 0 */
+ case 2: /* Phase 2: */
+ colStep = 8; /* 1 pixels per block of 8 per line */
+ colNum = 4; /* Start at column 4 */
+ break;
+ case 3: /* Phase 3: */
+ colStep = 4; /* 2 pixels per block of 8 per line */
+ break; /* Start at column 0 */
+ case 4: /* Phase 4: */
+ colStep = 4; /* 2 pixels per block of 8 per line */
+ colNum = 2; /* Start at column 2 */
+ break;
+ case 5: /* Phase 5: */
+ colStep = 2; /* 4 pixels per block of 8 per line */
+ break; /* Start at column 0 */
+ case 6: /* Phase 6: */
+ colStep = 2; /* 4 pixels per block of 8 per line */
+ colNum = 1; /* Start at column 1 */
+ break;
+ /* Phase 7: */
+ /* 8 pixels per block of 8 per line */
+ /* Start at column 0 */
+ }
+ }
+
+ /*
+ * Calculate offset into pixelPtr for the first pixel of the line.
+ */
+
+ offset = pngPtr->currentLine * pngPtr->block.pitch;
+
+ /*
+ * Adjust up for the starting pixel of the line.
+ */
+
+ offset += colNum * pngPtr->block.pixelSize;
+
+ /*
+ * Calculate the extra number of bytes to skip between columns.
+ */
+
+ pixStep = (colStep - 1) * pngPtr->block.pixelSize;
+
+ for ( ; colNum < pngPtr->block.width ; colNum += colStep) {
+ if (haveBits < (pngPtr->bitDepth * pngPtr->numChannels)) {
+ haveBits = 0;
+ }
+
+ for (chan = 0 ; chan < pngPtr->numChannels ; chan++) {
+ if (!haveBits) {
+ shifts = 0;
+ readByte = *p++;
+ haveBits += 8;
+ }
+
+ if (16 == pngPtr->bitDepth) {
+ pngPtr->block.pixelPtr[offset++] = readByte;
+
+ if (pngPtr->useTRNS) {
+ lastPixel[chan * 2] = readByte;
+ }
+
+ readByte = *p++;
+
+ if (pngPtr->useTRNS) {
+ lastPixel[(chan * 2) + 1] = readByte;
+ }
+
+ pngPtr->block.pixelPtr[offset++] = readByte;
+
+ haveBits = 0;
+ continue;
+ }
+
+ switch (pngPtr->bitDepth) {
+ case 1:
+ pixBits = (unsigned char)((readByte >> (7-shifts)) & 0x01);
+ break;
+ case 2:
+ pixBits = (unsigned char)((readByte >> (6-shifts*2)) & 0x03);
+ break;
+ case 4:
+ pixBits = (unsigned char)((readByte >> (4-shifts*4)) & 0x0f);
+ break;
+ case 8:
+ pixBits = readByte;
+ break;
+ }
+
+ if (PNG_COLOR_PLTE == pngPtr->colorType) {
+ pixelPtr[offset++] = pngPtr->palette[pixBits].red;
+ pixelPtr[offset++] = pngPtr->palette[pixBits].green;
+ pixelPtr[offset++] = pngPtr->palette[pixBits].blue;
+ pixelPtr[offset++] = pngPtr->palette[pixBits].alpha;
+ chan += 2;
+ } else {
+ pixelPtr[offset++] = (unsigned char)
+ (pixBits * pngPtr->bitScale);
+
+ if (pngPtr->useTRNS) {
+ lastPixel[chan] = pixBits;
+ }
+ }
+
+ haveBits -= pngPtr->bitDepth;
+ shifts++;
+ }
+
+ /*
+ * Apply boolean transparency via tRNS data if necessary (where
+ * necessary means a tRNS chunk was provided and we're not using an
+ * alpha channel or indexed alpha).
+ */
+
+ if ((PNG_COLOR_PLTE != pngPtr->colorType) &&
+ !(pngPtr->colorType & PNG_COLOR_ALPHA)) {
+ unsigned char alpha;
+
+ if (pngPtr->useTRNS) {
+ if (memcmp(lastPixel, pngPtr->transVal,
+ pngPtr->bytesPerPixel) == 0) {
+ alpha = 0x00;
+ } else {
+ alpha = 0xff;
+ }
+ } else {
+ alpha = 0xff;
+ }
+
+ pixelPtr[offset++] = alpha;
+
+ if (16 == pngPtr->bitDepth) {
+ pixelPtr[offset++] = alpha;
+ }
+ }
+
+ offset += pixStep;
+ }
+
+ if (pngPtr->interlace) {
+ /* Skip lines */
+
+ switch (pngPtr->phase) {
+ case 1: case 2: case 3:
+ pngPtr->currentLine += 8;
+ break;
+ case 4: case 5:
+ pngPtr->currentLine += 4;
+ break;
+ case 6: case 7:
+ pngPtr->currentLine += 2;
+ break;
+ }
+
+ /*
+ * Start the next phase if there are no more lines to do.
+ */
+
+ if (pngPtr->currentLine >= pngPtr->block.height) {
+ unsigned long pixels = 0;
+
+ while ((!pixels || (pngPtr->currentLine >= pngPtr->block.height))
+ && (pngPtr->phase < 7)) {
+ pngPtr->phase++;
+
+ switch (pngPtr->phase) {
+ case 2:
+ pixels = (pngPtr->block.width + 3) >> 3;
+ pngPtr->currentLine = 0;
+ break;
+ case 3:
+ pixels = (pngPtr->block.width + 3) >> 2;
+ pngPtr->currentLine = 4;
+ break;
+ case 4:
+ pixels = (pngPtr->block.width + 1) >> 2;
+ pngPtr->currentLine = 0;
+ break;
+ case 5:
+ pixels = (pngPtr->block.width + 1) >> 1;
+ pngPtr->currentLine = 2;
+ break;
+ case 6:
+ pixels = pngPtr->block.width >> 1;
+ pngPtr->currentLine = 0;
+ break;
+ case 7:
+ pngPtr->currentLine = 1;
+ pixels = pngPtr->block.width;
+ break;
+ }
+ }
+
+ if (16 == pngPtr->bitDepth) {
+ pngPtr->phaseSize = 1 + (pngPtr->numChannels * pixels * 2);
+ } else {
+ pngPtr->phaseSize = 1 + ((pngPtr->numChannels * pixels *
+ pngPtr->bitDepth + 7) >> 3);
+ }
+ }
+ } else {
+ pngPtr->currentLine++;
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ReadIDAT --
+ *
+ * This function reads the IDAT (pixel data) chunk from the PNG file to
+ * build the image. It will continue reading until all IDAT chunks have
+ * been processed or an error occurs.
+ *
+ * Results:
+ * TCL_OK, or TCL_ERROR if an I/O error occurs or an IDAT chunk is
+ * invalid.
+ *
+ * Side effects:
+ * The access position in f advances. Memory may be allocated by zlib
+ * through PNGZAlloc.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ReadIDAT(
+ Tcl_Interp *interp,
+ PNGImage *pngPtr,
+ int chunkSz,
+ unsigned long crc)
+{
+ /*
+ * Process IDAT contents until there is no more in this chunk.
+ */
+
+ while (chunkSz && !Tcl_ZlibStreamEof(pngPtr->stream)) {
+ int len1, len2;
+
+ /*
+ * Read another block of input into the zlib stream if data remains.
+ */
+
+ if (chunkSz) {
+ Tcl_Obj *inputObj = NULL;
+ int blockSz = PNG_MIN(chunkSz, PNG_BLOCK_SZ);
+ unsigned char *inputPtr = NULL;
+
+ /*
+ * Check for end of zlib stream.
+ */
+
+ if (Tcl_ZlibStreamEof(pngPtr->stream)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "extra data after end of zlib stream", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "EXTRA_DATA",
+ NULL);
+ return TCL_ERROR;
+ }
+
+ inputObj = Tcl_NewObj();
+ Tcl_IncrRefCount(inputObj);
+ inputPtr = Tcl_SetByteArrayLength(inputObj, blockSz);
+
+ /*
+ * Read the next bit of IDAT chunk data, up to read buffer size.
+ */
+
+ if (ReadData(interp, pngPtr, inputPtr, blockSz,
+ &crc) == TCL_ERROR) {
+ Tcl_DecrRefCount(inputObj);
+ return TCL_ERROR;
+ }
+
+ chunkSz -= blockSz;
+
+ Tcl_ZlibStreamPut(pngPtr->stream, inputObj, TCL_ZLIB_NO_FLUSH);
+ Tcl_DecrRefCount(inputObj);
+ }
+
+ /*
+ * Inflate, processing each output buffer's worth as a line of pixels,
+ * until we cannot fill the buffer any more.
+ */
+
+ getNextLine:
+ Tcl_GetByteArrayFromObj(pngPtr->thisLineObj, &len1);
+ if (Tcl_ZlibStreamGet(pngPtr->stream, pngPtr->thisLineObj,
+ pngPtr->phaseSize - len1) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ Tcl_GetByteArrayFromObj(pngPtr->thisLineObj, &len2);
+
+ if (len2 == pngPtr->phaseSize) {
+ if (pngPtr->phase > 7) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "extra data after final scan line of final phase",
+ -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "EXTRA_DATA",
+ NULL);
+ return TCL_ERROR;
+ }
+
+ if (DecodeLine(interp, pngPtr) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Swap the current/last lines so that we always have the last
+ * line processed available, which is necessary for filtering.
+ */
+
+ {
+ Tcl_Obj *temp = pngPtr->lastLineObj;
+
+ pngPtr->lastLineObj = pngPtr->thisLineObj;
+ pngPtr->thisLineObj = temp;
+ }
+ Tcl_SetByteArrayLength(pngPtr->thisLineObj, 0);
+
+ /*
+ * Try to read another line of pixels out of the buffer
+ * immediately, but don't allow write past end of block.
+ */
+
+ if (pngPtr->currentLine < pngPtr->block.height) {
+ goto getNextLine;
+ }
+
+ }
+
+ /*
+ * Got less than a whole buffer-load of pixels. Either we're going to
+ * be getting more data from the next IDAT, or we've done what we can
+ * here.
+ */
+ }
+
+ /*
+ * Ensure that if we've got to the end of the compressed data, we've
+ * also got to the end of the compressed stream. This sanity check is
+ * enforced by most PNG readers.
+ */
+
+ if (chunkSz != 0) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "compressed data after stream finalize in PNG data", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "EXTRA_DATA", NULL);
+ return TCL_ERROR;
+ }
+
+ return CheckCRC(interp, pngPtr, crc);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ApplyAlpha --
+ *
+ * Applies an overall alpha value to a complete image that has been read.
+ * This alpha value is specified using the -format option to [image
+ * create photo].
+ *
+ * Results:
+ * N/A
+ *
+ * Side effects:
+ * The access position in f may change.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ApplyAlpha(
+ PNGImage *pngPtr)
+{
+ if (pngPtr->alpha != 1.0) {
+ register unsigned char *p = pngPtr->block.pixelPtr;
+ unsigned char *endPtr = p + pngPtr->blockLen;
+ int offset = pngPtr->block.offset[3];
+
+ p += offset;
+
+ if (16 == pngPtr->bitDepth) {
+ register unsigned int channel;
+
+ while (p < endPtr) {
+ channel = (unsigned int)
+ (((p[0] << 8) | p[1]) * pngPtr->alpha);
+
+ *p++ = (unsigned char) (channel >> 8);
+ *p++ = (unsigned char) (channel & 0xff);
+
+ p += offset;
+ }
+ } else {
+ while (p < endPtr) {
+ p[0] = (unsigned char) (pngPtr->alpha * p[0]);
+ p += 1 + offset;
+ }
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ParseFormat --
+ *
+ * This function parses the -format string that can be specified to the
+ * [image create photo] command to extract options for postprocessing of
+ * loaded images. Currently, this just allows specifying and applying an
+ * overall alpha value to the loaded image (for example, to make it
+ * entirely 50% as transparent as the actual image file).
+ *
+ * Results:
+ * TCL_OK, or TCL_ERROR if the format specification is invalid.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ParseFormat(
+ Tcl_Interp *interp,
+ Tcl_Obj *fmtObj,
+ PNGImage *pngPtr)
+{
+ Tcl_Obj **objv = NULL;
+ int objc = 0;
+ static const char *const fmtOptions[] = {
+ "-alpha", NULL
+ };
+ enum fmtOptions {
+ OPT_ALPHA
+ };
+
+ /*
+ * Extract elements of format specification as a list.
+ */
+
+ if (fmtObj &&
+ Tcl_ListObjGetElements(interp, fmtObj, &objc, &objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ for (; objc>0 ; objc--, objv++) {
+ int optIndex;
+
+ /*
+ * Ignore the "png" part of the format specification.
+ */
+
+ if (!strcasecmp(Tcl_GetString(objv[0]), "png")) {
+ continue;
+ }
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[0], fmtOptions,
+ sizeof(char *), "option", 0, &optIndex) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "value");
+ return TCL_ERROR;
+ }
+
+ objc--;
+ objv++;
+
+ switch ((enum fmtOptions) optIndex) {
+ case OPT_ALPHA:
+ if (Tcl_GetDoubleFromObj(interp, objv[0],
+ &pngPtr->alpha) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ if ((pngPtr->alpha < 0.0) || (pngPtr->alpha > 1.0)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "-alpha value must be between 0.0 and 1.0", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "BAD_ALPHA",
+ NULL);
+ return TCL_ERROR;
+ }
+ break;
+ }
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DecodePNG --
+ *
+ * This function handles the entirety of reading a PNG file (or data)
+ * from the first byte to the last.
+ *
+ * Results:
+ * TCL_OK, or TCL_ERROR if an I/O error occurs or any problems are
+ * detected in the PNG file.
+ *
+ * Side effects:
+ * The access position in f advances. Memory may be allocated and image
+ * dimensions and contents may change.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DecodePNG(
+ Tcl_Interp *interp,
+ PNGImage *pngPtr,
+ Tcl_Obj *fmtObj,
+ Tk_PhotoHandle imageHandle,
+ int destX,
+ int destY)
+{
+ unsigned long chunkType;
+ int chunkSz;
+ unsigned long crc;
+
+ /*
+ * Parse the PNG signature and IHDR (header) chunk.
+ */
+
+ if (ReadIHDR(interp, pngPtr) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Extract alpha value from -format object, if specified.
+ */
+
+ if (ParseFormat(interp, fmtObj, pngPtr) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * The next chunk may either be a PLTE (Palette) chunk or the first of at
+ * least one IDAT (data) chunks. It could also be one of a number of
+ * ancillary chunks, but those are skipped for us by the switch in
+ * ReadChunkHeader().
+ *
+ * PLTE is mandatory for color type 3 and forbidden for 2 and 6
+ */
+
+ if (ReadChunkHeader(interp, pngPtr, &chunkSz, &chunkType,
+ &crc) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ if (CHUNK_PLTE == chunkType) {
+ /*
+ * Finish parsing the PLTE chunk.
+ */
+
+ if (ReadPLTE(interp, pngPtr, chunkSz, crc) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Begin the next chunk.
+ */
+
+ if (ReadChunkHeader(interp, pngPtr, &chunkSz, &chunkType,
+ &crc) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ } else if (PNG_COLOR_PLTE == pngPtr->colorType) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "PLTE chunk required for indexed color", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "NEED_PLTE", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * The next chunk may be a tRNS (palette transparency) chunk, depending on
+ * the color type. It must come after the PLTE chunk and before the IDAT
+ * chunk, but can be present if there is no PLTE chunk because it can be
+ * used for Grayscale and TrueColor in lieu of an alpha channel.
+ */
+
+ if (CHUNK_tRNS == chunkType) {
+ /*
+ * Finish parsing the tRNS chunk.
+ */
+
+ if (ReadTRNS(interp, pngPtr, chunkSz, crc) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Begin the next chunk.
+ */
+
+ if (ReadChunkHeader(interp, pngPtr, &chunkSz, &chunkType,
+ &crc) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * Other ancillary chunk types could appear here, but for now we're only
+ * interested in IDAT. The others should have been skipped.
+ */
+
+ if (chunkType != CHUNK_IDAT) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "at least one IDAT chunk is required", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "NEED_IDAT", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Expand the photo size (if not set by the user) to provide enough space
+ * for the image being parsed. It does not matter if width or height wrap
+ * to negative here: Tk will not shrink the image.
+ */
+
+ if (Tk_PhotoExpand(interp, imageHandle, destX + pngPtr->block.width,
+ destY + pngPtr->block.height) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * A scan line consists of one byte for a filter type, plus the number of
+ * bits per color sample times the number of color samples per pixel.
+ */
+
+ if (pngPtr->block.width > ((INT_MAX - 1) / (pngPtr->numChannels * 2))) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "line size is out of supported range on this architecture",
+ -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "LINE_SIZE", NULL);
+ return TCL_ERROR;
+ }
+
+ if (16 == pngPtr->bitDepth) {
+ pngPtr->lineSize = 1 + (pngPtr->numChannels * pngPtr->block.width*2);
+ } else {
+ pngPtr->lineSize = 1 + ((pngPtr->numChannels * pngPtr->block.width) /
+ (8 / pngPtr->bitDepth));
+ if (pngPtr->block.width % (8 / pngPtr->bitDepth)) {
+ pngPtr->lineSize++;
+ }
+ }
+
+ /*
+ * Allocate space for decoding the scan lines.
+ */
+
+ pngPtr->lastLineObj = Tcl_NewObj();
+ Tcl_IncrRefCount(pngPtr->lastLineObj);
+ pngPtr->thisLineObj = Tcl_NewObj();
+ Tcl_IncrRefCount(pngPtr->thisLineObj);
+
+ pngPtr->block.pixelPtr = attemptckalloc(pngPtr->blockLen);
+ if (!pngPtr->block.pixelPtr) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "memory allocation failed", -1));
+ Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Determine size of the first phase if interlaced. Phase size should
+ * always be <= line size, so probably not necessary to check for
+ * arithmetic overflow here: should be covered by line size check.
+ */
+
+ if (pngPtr->interlace) {
+ /*
+ * Only one pixel per block of 8 per line in the first phase.
+ */
+
+ unsigned int pixels = (pngPtr->block.width + 7) >> 3;
+
+ pngPtr->phase = 1;
+ if (16 == pngPtr->bitDepth) {
+ pngPtr->phaseSize = 1 + pngPtr->numChannels*pixels*2;
+ } else {
+ pngPtr->phaseSize = 1 +
+ ((pngPtr->numChannels*pixels*pngPtr->bitDepth + 7) >> 3);
+ }
+ } else {
+ pngPtr->phaseSize = pngPtr->lineSize;
+ }
+
+ /*
+ * All of the IDAT (data) chunks must be consecutive.
+ */
+
+ while (CHUNK_IDAT == chunkType) {
+ if (ReadIDAT(interp, pngPtr, chunkSz, crc) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ if (ReadChunkHeader(interp, pngPtr, &chunkSz, &chunkType,
+ &crc) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * Ensure that we've got to the end of the compressed stream now that
+ * there are no more IDAT segments. This sanity check is enforced by most
+ * PNG readers.
+ */
+
+ if (!Tcl_ZlibStreamEof(pngPtr->stream)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "unfinalized data stream in PNG data", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "EXTRA_DATA", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Now skip the remaining chunks which we're also not interested in.
+ */
+
+ while (CHUNK_IEND != chunkType) {
+ if (SkipChunk(interp, pngPtr, chunkSz, crc) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ if (ReadChunkHeader(interp, pngPtr, &chunkSz, &chunkType,
+ &crc) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * Got the IEND (end of image) chunk. Do some final checks...
+ */
+
+ if (chunkSz) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "IEND chunk contents must be empty", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "BAD_IEND", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Check the CRC on the IEND chunk.
+ */
+
+ if (CheckCRC(interp, pngPtr, crc) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * TODO: verify that nothing else comes after the IEND chunk, or do we
+ * really care?
+ */
+
+#if 0
+ if (ReadData(interp, pngPtr, &c, 1, NULL) != TCL_ERROR) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "extra data following IEND chunk", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "BAD_IEND", NULL);
+ return TCL_ERROR;
+ }
+#endif
+
+ /*
+ * Apply overall image alpha if specified.
+ */
+
+ ApplyAlpha(pngPtr);
+
+ /*
+ * Copy the decoded image block into the Tk photo image.
+ */
+
+ if (Tk_PhotoPutBlock(interp, imageHandle, &pngPtr->block, destX, destY,
+ pngPtr->block.width, pngPtr->block.height,
+ TK_PHOTO_COMPOSITE_SET) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileMatchPNG --
+ *
+ * This function is invoked by the photo image type to see if a file
+ * contains image data in PNG format.
+ *
+ * Results:
+ * The return value is 1 if the first characters in file f look like PNG
+ * data, and 0 otherwise.
+ *
+ * Side effects:
+ * The access position in f may change.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+FileMatchPNG(
+ Tcl_Channel chan,
+ const char *fileName,
+ Tcl_Obj *fmtObj,
+ int *widthPtr,
+ int *heightPtr,
+ Tcl_Interp *interp)
+{
+ PNGImage png;
+ int match = 0;
+
+ InitPNGImage(NULL, &png, chan, NULL, TCL_ZLIB_STREAM_INFLATE);
+
+ if (ReadIHDR(interp, &png) == TCL_OK) {
+ *widthPtr = png.block.width;
+ *heightPtr = png.block.height;
+ match = 1;
+ }
+
+ CleanupPNGImage(&png);
+
+ return match;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileReadPNG --
+ *
+ * This function is called by the photo image type to read PNG format
+ * data from a file and write it into a given photo image.
+ *
+ * Results:
+ * A standard TCL completion code. If TCL_ERROR is returned then an error
+ * message is left in the interp's result.
+ *
+ * Side effects:
+ * The access position in file f is changed, and new data is added to the
+ * image given by imageHandle.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+FileReadPNG(
+ Tcl_Interp *interp,
+ Tcl_Channel chan,
+ const char *fileName,
+ Tcl_Obj *fmtObj,
+ Tk_PhotoHandle imageHandle,
+ int destX,
+ int destY,
+ int width,
+ int height,
+ int srcX,
+ int srcY)
+{
+ PNGImage png;
+ int result = TCL_ERROR;
+
+ result = InitPNGImage(interp, &png, chan, NULL, TCL_ZLIB_STREAM_INFLATE);
+
+ if (TCL_OK == result) {
+ result = DecodePNG(interp, &png, fmtObj, imageHandle, destX, destY);
+ }
+
+ CleanupPNGImage(&png);
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * StringMatchPNG --
+ *
+ * This function is invoked by the photo image type to see if an object
+ * contains image data in PNG format.
+ *
+ * Results:
+ * The return value is 1 if the first characters in the data are like PNG
+ * data, and 0 otherwise.
+ *
+ * Side effects:
+ * The size of the image is placed in widthPre and heightPtr.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+StringMatchPNG(
+ Tcl_Obj *pObjData,
+ Tcl_Obj *fmtObj,
+ int *widthPtr,
+ int *heightPtr,
+ Tcl_Interp *interp)
+{
+ PNGImage png;
+ int match = 0;
+
+ InitPNGImage(NULL, &png, NULL, pObjData, TCL_ZLIB_STREAM_INFLATE);
+
+ png.strDataBuf = Tcl_GetByteArrayFromObj(pObjData, &png.strDataLen);
+
+ if (ReadIHDR(interp, &png) == TCL_OK) {
+ *widthPtr = png.block.width;
+ *heightPtr = png.block.height;
+ match = 1;
+ }
+
+ CleanupPNGImage(&png);
+ return match;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * StringReadPNG --
+ *
+ * This function is called by the photo image type to read PNG format
+ * data from an object and give it to the photo image.
+ *
+ * Results:
+ * A standard TCL completion code. If TCL_ERROR is returned then an error
+ * message is left in the interp's result.
+ *
+ * Side effects:
+ * New data is added to the image given by imageHandle.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+StringReadPNG(
+ Tcl_Interp *interp,
+ Tcl_Obj *pObjData,
+ Tcl_Obj *fmtObj,
+ Tk_PhotoHandle imageHandle,
+ int destX,
+ int destY,
+ int width,
+ int height,
+ int srcX,
+ int srcY)
+{
+ PNGImage png;
+ int result = TCL_ERROR;
+
+ result = InitPNGImage(interp, &png, NULL, pObjData,
+ TCL_ZLIB_STREAM_INFLATE);
+
+ if (TCL_OK == result) {
+ result = DecodePNG(interp, &png, fmtObj, imageHandle, destX, destY);
+ }
+
+ CleanupPNGImage(&png);
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WriteData --
+ *
+ * This function writes a bytes from a buffer out to the PNG image.
+ *
+ * Results:
+ * TCL_OK, or TCL_ERROR if the write fails.
+ *
+ * Side effects:
+ * File or buffer will be modified.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WriteData(
+ Tcl_Interp *interp,
+ PNGImage *pngPtr,
+ const unsigned char *srcPtr,
+ int srcSz,
+ unsigned long *crcPtr)
+{
+ if (!srcPtr || !srcSz) {
+ return TCL_OK;
+ }
+
+ if (crcPtr) {
+ *crcPtr = Tcl_ZlibCRC32(*crcPtr, srcPtr, srcSz);
+ }
+
+ /*
+ * TODO: is Tcl_AppendObjToObj faster here? i.e., does Tcl join the
+ * objects immediately or store them in a multi-object rep?
+ */
+
+ if (pngPtr->objDataPtr) {
+ int objSz;
+ unsigned char *destPtr;
+
+ Tcl_GetByteArrayFromObj(pngPtr->objDataPtr, &objSz);
+
+ if (objSz > INT_MAX - srcSz) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "image too large to store completely in byte array", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "TOO_LARGE", NULL);
+ return TCL_ERROR;
+ }
+
+ destPtr = Tcl_SetByteArrayLength(pngPtr->objDataPtr, objSz + srcSz);
+
+ if (!destPtr) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "memory allocation failed", -1));
+ Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL);
+ return TCL_ERROR;
+ }
+
+ memcpy(destPtr+objSz, srcPtr, srcSz);
+ } else if (Tcl_Write(pngPtr->channel, (const char *) srcPtr, srcSz) < 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "write to channel failed: %s", Tcl_PosixError(interp)));
+ return TCL_ERROR;
+ }
+
+ return TCL_OK;
+}
+
+static inline int
+WriteByte(
+ Tcl_Interp *interp,
+ PNGImage *pngPtr,
+ unsigned char c,
+ unsigned long *crcPtr)
+{
+ return WriteData(interp, pngPtr, &c, 1, crcPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WriteInt32 --
+ *
+ * This function writes a 32-bit integer value out to the PNG image as
+ * four bytes in network byte order.
+ *
+ * Results:
+ * TCL_OK, or TCL_ERROR if the write fails.
+ *
+ * Side effects:
+ * File or buffer will be modified.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static inline int
+WriteInt32(
+ Tcl_Interp *interp,
+ PNGImage *pngPtr,
+ unsigned long l,
+ unsigned long *crcPtr)
+{
+ unsigned char pc[4];
+
+ pc[0] = (unsigned char) ((l & 0xff000000) >> 24);
+ pc[1] = (unsigned char) ((l & 0x00ff0000) >> 16);
+ pc[2] = (unsigned char) ((l & 0x0000ff00) >> 8);
+ pc[3] = (unsigned char) ((l & 0x000000ff) >> 0);
+
+ return WriteData(interp, pngPtr, pc, 4, crcPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WriteChunk --
+ *
+ * Writes a complete chunk to the PNG image, including chunk type,
+ * length, contents, and CRC.
+ *
+ * Results:
+ * TCL_OK, or TCL_ERROR if the write fails.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static inline int
+WriteChunk(
+ Tcl_Interp *interp,
+ PNGImage *pngPtr,
+ unsigned long chunkType,
+ const unsigned char *dataPtr,
+ int dataSize)
+{
+ unsigned long crc = Tcl_ZlibCRC32(0, NULL, 0);
+ int result = TCL_OK;
+
+ /*
+ * Write the length field for the chunk.
+ */
+
+ result = WriteInt32(interp, pngPtr, dataSize, NULL);
+
+ /*
+ * Write the Chunk Type.
+ */
+
+ if (TCL_OK == result) {
+ result = WriteInt32(interp, pngPtr, chunkType, &crc);
+ }
+
+ /*
+ * Write the contents (if any).
+ */
+
+ if (TCL_OK == result) {
+ result = WriteData(interp, pngPtr, dataPtr, dataSize, &crc);
+ }
+
+ /*
+ * Write out the CRC at the end of the chunk.
+ */
+
+ if (TCL_OK == result) {
+ result = WriteInt32(interp, pngPtr, crc, NULL);
+ }
+
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WriteIHDR --
+ *
+ * This function writes the PNG header at the beginning of a PNG file,
+ * which includes information such as dimensions and color type.
+ *
+ * Results:
+ * TCL_OK, or TCL_ERROR if the write fails.
+ *
+ * Side effects:
+ * File or buffer will be modified.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WriteIHDR(
+ Tcl_Interp *interp,
+ PNGImage *pngPtr,
+ Tk_PhotoImageBlock *blockPtr)
+{
+ unsigned long crc = Tcl_ZlibCRC32(0, NULL, 0);
+ int result = TCL_OK;
+
+ /*
+ * The IHDR (header) chunk has a fixed size of 13 bytes.
+ */
+
+ result = WriteInt32(interp, pngPtr, 13, NULL);
+
+ /*
+ * Write the IHDR Chunk Type.
+ */
+
+ if (TCL_OK == result) {
+ result = WriteInt32(interp, pngPtr, CHUNK_IHDR, &crc);
+ }
+
+ /*
+ * Write the image width, height.
+ */
+
+ if (TCL_OK == result) {
+ result = WriteInt32(interp, pngPtr, (unsigned long) blockPtr->width,
+ &crc);
+ }
+
+ if (TCL_OK == result) {
+ result = WriteInt32(interp, pngPtr, (unsigned long) blockPtr->height,
+ &crc);
+ }
+
+ /*
+ * Write bit depth. Although the PNG format supports 16 bits per channel,
+ * Tk supports only 8 in the internal representation, which blockPtr
+ * points to.
+ */
+
+ if (TCL_OK == result) {
+ result = WriteByte(interp, pngPtr, 8, &crc);
+ }
+
+ /*
+ * Write out the color type, previously determined.
+ */
+
+ if (TCL_OK == result) {
+ result = WriteByte(interp, pngPtr, pngPtr->colorType, &crc);
+ }
+
+ /*
+ * Write compression method (only one method is defined).
+ */
+
+ if (TCL_OK == result) {
+ result = WriteByte(interp, pngPtr, PNG_COMPRESS_DEFLATE, &crc);
+ }
+
+ /*
+ * Write filter method (only one method is defined).
+ */
+
+ if (TCL_OK == result) {
+ result = WriteByte(interp, pngPtr, PNG_FILTMETH_STANDARD, &crc);
+ }
+
+ /*
+ * Write interlace method as not interlaced.
+ *
+ * TODO: support interlace through -format?
+ */
+
+ if (TCL_OK == result) {
+ result = WriteByte(interp, pngPtr, PNG_INTERLACE_NONE, &crc);
+ }
+
+ /*
+ * Write out the CRC at the end of the chunk.
+ */
+
+ if (TCL_OK == result) {
+ result = WriteInt32(interp, pngPtr, crc, NULL);
+ }
+
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WriteIDAT --
+ *
+ * Writes the IDAT (data) chunk to the PNG image, containing the pixel
+ * channel data. Currently, image lines are not filtered and writing
+ * interlaced pixels is not supported.
+ *
+ * Results:
+ * TCL_OK, or TCL_ERROR if the write fails.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WriteIDAT(
+ Tcl_Interp *interp,
+ PNGImage *pngPtr,
+ Tk_PhotoImageBlock *blockPtr)
+{
+ int rowNum, flush = TCL_ZLIB_NO_FLUSH, outputSize, result;
+ Tcl_Obj *outputObj;
+ unsigned char *outputBytes;
+
+ /*
+ * Filter and compress each row one at a time.
+ */
+
+ for (rowNum=0 ; rowNum < blockPtr->height ; rowNum++) {
+ int colNum;
+ unsigned char *srcPtr, *destPtr;
+
+ srcPtr = blockPtr->pixelPtr + (rowNum * blockPtr->pitch);
+ destPtr = Tcl_SetByteArrayLength(pngPtr->thisLineObj,
+ pngPtr->lineSize);
+
+ /*
+ * TODO: use Paeth filtering.
+ */
+
+ *destPtr++ = PNG_FILTER_NONE;
+
+ /*
+ * Copy each pixel into the destination buffer after the filter type
+ * before filtering.
+ */
+
+ for (colNum = 0 ; colNum < blockPtr->width ; colNum++) {
+ /*
+ * Copy red or gray channel.
+ */
+
+ *destPtr++ = srcPtr[blockPtr->offset[0]];
+
+ /*
+ * If not grayscale, copy the green and blue channels.
+ */
+
+ if (pngPtr->colorType & PNG_COLOR_USED) {
+ *destPtr++ = srcPtr[blockPtr->offset[1]];
+ *destPtr++ = srcPtr[blockPtr->offset[2]];
+ }
+
+ /*
+ * Copy the alpha channel, if used.
+ */
+
+ if (pngPtr->colorType & PNG_COLOR_ALPHA) {
+ *destPtr++ = srcPtr[blockPtr->offset[3]];
+ }
+
+ /*
+ * Point to the start of the next pixel.
+ */
+
+ srcPtr += blockPtr->pixelSize;
+ }
+
+ /*
+ * Compress the line of pixels into the destination. If this is the
+ * last line, finalize the compressor at the same time. Note that this
+ * can't be just a flush; that leads to a file that some PNG readers
+ * choke on. [Bug 2984787]
+ */
+
+ if (rowNum + 1 == blockPtr->height) {
+ flush = TCL_ZLIB_FINALIZE;
+ }
+ if (Tcl_ZlibStreamPut(pngPtr->stream, pngPtr->thisLineObj,
+ flush) != TCL_OK) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "deflate() returned error", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "DEFLATE", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Swap line buffers to keep the last around for filtering next.
+ */
+
+ {
+ Tcl_Obj *temp = pngPtr->lastLineObj;
+
+ pngPtr->lastLineObj = pngPtr->thisLineObj;
+ pngPtr->thisLineObj = temp;
+ }
+ }
+
+ /*
+ * Now get the compressed data and write it as one big IDAT chunk.
+ */
+
+ outputObj = Tcl_NewObj();
+ (void) Tcl_ZlibStreamGet(pngPtr->stream, outputObj, -1);
+ outputBytes = Tcl_GetByteArrayFromObj(outputObj, &outputSize);
+ result = WriteChunk(interp, pngPtr, CHUNK_IDAT, outputBytes, outputSize);
+ Tcl_DecrRefCount(outputObj);
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WriteExtraChunks --
+ *
+ * Writes an sBIT and a tEXt chunks to the PNG image, describing a bunch
+ * of not very important metadata that many readers seem to need anyway.
+ *
+ * Results:
+ * TCL_OK, or TCL_ERROR if the write fails.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WriteExtraChunks(
+ Tcl_Interp *interp,
+ PNGImage *pngPtr)
+{
+ static const unsigned char sBIT_contents[] = {
+ 8, 8, 8, 8
+ };
+ int sBIT_length = 4;
+ Tcl_DString buf;
+
+ /*
+ * Each byte of each channel is always significant; we always write RGBA
+ * images with 8 bits per channel as that is what the photo image's basic
+ * data model is.
+ */
+
+ switch (pngPtr->colorType) {
+ case PNG_COLOR_GRAY:
+ sBIT_length = 1;
+ break;
+ case PNG_COLOR_GRAYALPHA:
+ sBIT_length = 2;
+ break;
+ case PNG_COLOR_RGB:
+ case PNG_COLOR_PLTE:
+ sBIT_length = 3;
+ break;
+ case PNG_COLOR_RGBA:
+ sBIT_length = 4;
+ break;
+ }
+ if (WriteChunk(interp, pngPtr, CHUNK_sBIT, sBIT_contents, sBIT_length)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Say that it is Tk that made the PNG. Note that we *need* the NUL at the
+ * end of "Software" to be transferred; do *not* change the length
+ * parameter to -1 there!
+ */
+
+ Tcl_DStringInit(&buf);
+ Tcl_DStringAppend(&buf, "Software", 9);
+ Tcl_DStringAppend(&buf, "Tk Toolkit v", -1);
+ Tcl_DStringAppend(&buf, TK_PATCH_LEVEL, -1);
+ if (WriteChunk(interp, pngPtr, CHUNK_tEXt,
+ (unsigned char *) Tcl_DStringValue(&buf),
+ Tcl_DStringLength(&buf)) != TCL_OK) {
+ Tcl_DStringFree(&buf);
+ return TCL_ERROR;
+ }
+ Tcl_DStringFree(&buf);
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EncodePNG --
+ *
+ * This function handles the entirety of writing a PNG file (or data)
+ * from the first byte to the last. No effort is made to optimize the
+ * image data for best compression.
+ *
+ * Results:
+ * TCL_OK, or TCL_ERROR if an I/O or memory error occurs.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+EncodePNG(
+ Tcl_Interp *interp,
+ Tk_PhotoImageBlock *blockPtr,
+ PNGImage *pngPtr)
+{
+ int greenOffset, blueOffset, alphaOffset;
+
+ /*
+ * Determine appropriate color type based on color usage (e.g., only red
+ * and maybe alpha channel = grayscale).
+ *
+ * TODO: Check whether this is doing any good; Tk might just be pushing
+ * full RGBA data all the time through here, even though the actual image
+ * doesn't need it...
+ */
+
+ greenOffset = blockPtr->offset[1] - blockPtr->offset[0];
+ blueOffset = blockPtr->offset[2] - blockPtr->offset[0];
+ alphaOffset = blockPtr->offset[3];
+ if ((alphaOffset >= blockPtr->pixelSize) || (alphaOffset < 0)) {
+ alphaOffset = 0;
+ } else {
+ alphaOffset -= blockPtr->offset[0];
+ }
+
+ if ((greenOffset != 0) || (blueOffset != 0)) {
+ if (alphaOffset) {
+ pngPtr->colorType = PNG_COLOR_RGBA;
+ pngPtr->bytesPerPixel = 4;
+ } else {
+ pngPtr->colorType = PNG_COLOR_RGB;
+ pngPtr->bytesPerPixel = 3;
+ }
+ } else {
+ if (alphaOffset) {
+ pngPtr->colorType = PNG_COLOR_GRAYALPHA;
+ pngPtr->bytesPerPixel = 2;
+ } else {
+ pngPtr->colorType = PNG_COLOR_GRAY;
+ pngPtr->bytesPerPixel = 1;
+ }
+ }
+
+ /*
+ * Allocate buffers for lines for filtering and compressed data.
+ */
+
+ pngPtr->lineSize = 1 + (pngPtr->bytesPerPixel * blockPtr->width);
+ pngPtr->blockLen = pngPtr->lineSize * blockPtr->height;
+
+ if ((blockPtr->width > (INT_MAX - 1) / (pngPtr->bytesPerPixel)) ||
+ (blockPtr->height > INT_MAX / pngPtr->lineSize)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "image is too large to encode pixel data", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "TOO_LARGE", NULL);
+ return TCL_ERROR;
+ }
+
+ pngPtr->lastLineObj = Tcl_NewObj();
+ Tcl_IncrRefCount(pngPtr->lastLineObj);
+ pngPtr->thisLineObj = Tcl_NewObj();
+ Tcl_IncrRefCount(pngPtr->thisLineObj);
+
+ /*
+ * Write out the PNG Signature that all PNGs begin with.
+ */
+
+ if (WriteData(interp, pngPtr, pngSignature, PNG_SIG_SZ,
+ NULL) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Write out the IHDR (header) chunk containing image dimensions, color
+ * type, etc.
+ */
+
+ if (WriteIHDR(interp, pngPtr, blockPtr) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Write out the extra chunks containing metadata that is of interest to
+ * other programs more than us.
+ */
+
+ if (WriteExtraChunks(interp, pngPtr) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Write out the image pixels in the IDAT (data) chunk.
+ */
+
+ if (WriteIDAT(interp, pngPtr, blockPtr) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Write out the IEND chunk that all PNGs end with.
+ */
+
+ return WriteChunk(interp, pngPtr, CHUNK_IEND, NULL, 0);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileWritePNG --
+ *
+ * This function is called by the photo image type to write PNG format
+ * data to a file.
+ *
+ * Results:
+ * A standard TCL completion code. If TCL_ERROR is returned then an error
+ * message is left in the interp's result.
+ *
+ * Side effects:
+ * The specified file is overwritten.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+FileWritePNG(
+ Tcl_Interp *interp,
+ const char *filename,
+ Tcl_Obj *fmtObj,
+ Tk_PhotoImageBlock *blockPtr)
+{
+ Tcl_Channel chan;
+ PNGImage png;
+ int result = TCL_ERROR;
+
+ /*
+ * Open a Tcl file channel where the image data will be stored. Tk ought
+ * to take care of this, and just provide a channel, but it doesn't.
+ */
+
+ chan = Tcl_OpenFileChannel(interp, filename, "w", 0644);
+
+ if (!chan) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Initalize PNGImage instance for encoding.
+ */
+
+ if (InitPNGImage(interp, &png, chan, NULL,
+ TCL_ZLIB_STREAM_DEFLATE) == TCL_ERROR) {
+ goto cleanup;
+ }
+
+ /*
+ * Set the translation mode to binary so that CR and LF are not to the
+ * platform's EOL sequence.
+ */
+
+ if (Tcl_SetChannelOption(interp, chan, "-translation",
+ "binary") != TCL_OK) {
+ goto cleanup;
+ }
+
+ /*
+ * Write the raw PNG data out to the file.
+ */
+
+ result = EncodePNG(interp, blockPtr, &png);
+
+ cleanup:
+ Tcl_Close(interp, chan);
+ CleanupPNGImage(&png);
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * StringWritePNG --
+ *
+ * This function is called by the photo image type to write PNG format
+ * data to a Tcl object and return it in the result.
+ *
+ * Results:
+ * A standard TCL completion code. If TCL_ERROR is returned then an error
+ * message is left in the interp's result.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+StringWritePNG(
+ Tcl_Interp *interp,
+ Tcl_Obj *fmtObj,
+ Tk_PhotoImageBlock *blockPtr)
+{
+ Tcl_Obj *resultObj = Tcl_NewObj();
+ PNGImage png;
+ int result = TCL_ERROR;
+
+ /*
+ * Initalize PNGImage instance for encoding.
+ */
+
+ if (InitPNGImage(interp, &png, NULL, resultObj,
+ TCL_ZLIB_STREAM_DEFLATE) == TCL_ERROR) {
+ goto cleanup;
+ }
+
+ /*
+ * Write the raw PNG data into the prepared Tcl_Obj buffer. Set the result
+ * back to the interpreter if successful.
+ */
+
+ result = EncodePNG(interp, blockPtr, &png);
+
+ if (TCL_OK == result) {
+ Tcl_SetObjResult(interp, png.objDataPtr);
+ }
+
+ cleanup:
+ CleanupPNGImage(&png);
+ return result;
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkImgPPM.c b/tk8.6/generic/tkImgPPM.c
new file mode 100644
index 0000000..6f084f0
--- /dev/null
+++ b/tk8.6/generic/tkImgPPM.c
@@ -0,0 +1,854 @@
+/*
+ * tkImgPPM.c --
+ *
+ * A photo image file handler for PPM (Portable PixMap) files.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * Copyright (c) 1994-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.
+ *
+ * Author: Paul Mackerras (paulus@cs.anu.edu.au),
+ * Department of Computer Science,
+ * Australian National University.
+ */
+
+#include "tkInt.h"
+
+/*
+ * The maximum amount of memory to allocate for data read from the file. If we
+ * need more than this, we do it in pieces.
+ */
+
+#define MAX_MEMORY 10000 /* don't allocate > 10KB */
+
+/*
+ * Define PGM and PPM, i.e. gray images and color images.
+ */
+
+#define PGM 1
+#define PPM 2
+
+/*
+ * The format record for the PPM file format:
+ */
+
+static int FileMatchPPM(Tcl_Channel chan, const char *fileName,
+ Tcl_Obj *format, int *widthPtr, int *heightPtr,
+ Tcl_Interp *interp);
+static int FileReadPPM(Tcl_Interp *interp, Tcl_Channel chan,
+ const char *fileName, Tcl_Obj *format,
+ Tk_PhotoHandle imageHandle, int destX, int destY,
+ int width, int height, int srcX, int srcY);
+static int FileWritePPM(Tcl_Interp *interp, const char *fileName,
+ Tcl_Obj *format, Tk_PhotoImageBlock *blockPtr);
+static int StringWritePPM(Tcl_Interp *interp, Tcl_Obj *format,
+ Tk_PhotoImageBlock *blockPtr);
+static int StringMatchPPM(Tcl_Obj *dataObj, Tcl_Obj *format,
+ int *widthPtr, int *heightPtr, Tcl_Interp *interp);
+static int StringReadPPM(Tcl_Interp *interp, Tcl_Obj *dataObj,
+ Tcl_Obj *format, Tk_PhotoHandle imageHandle,
+ int destX, int destY, int width, int height,
+ int srcX, int srcY);
+
+Tk_PhotoImageFormat tkImgFmtPPM = {
+ "ppm", /* name */
+ FileMatchPPM, /* fileMatchProc */
+ StringMatchPPM, /* stringMatchProc */
+ FileReadPPM, /* fileReadProc */
+ StringReadPPM, /* stringReadProc */
+ FileWritePPM, /* fileWriteProc */
+ StringWritePPM, /* stringWriteProc */
+ NULL
+};
+
+/*
+ * Prototypes for local functions defined in this file:
+ */
+
+static int ReadPPMFileHeader(Tcl_Channel chan, int *widthPtr,
+ int *heightPtr, int *maxIntensityPtr);
+static int ReadPPMStringHeader(Tcl_Obj *dataObj, int *widthPtr,
+ int *heightPtr, int *maxIntensityPtr,
+ unsigned char **dataBufferPtr, int *dataSizePtr);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileMatchPPM --
+ *
+ * This function is invoked by the photo image type to see if a file
+ * contains image data in PPM format.
+ *
+ * Results:
+ * The return value is >0 if the first characters in file "f" look like
+ * PPM data, and 0 otherwise.
+ *
+ * Side effects:
+ * The access position in f may change.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+FileMatchPPM(
+ Tcl_Channel chan, /* The image file, open for reading. */
+ const char *fileName, /* The name of the image file. */
+ Tcl_Obj *format, /* User-specified format string, or NULL. */
+ int *widthPtr, int *heightPtr,
+ /* The dimensions of the image are returned
+ * here if the file is a valid raw PPM
+ * file. */
+ Tcl_Interp *interp) /* unused */
+{
+ int dummy;
+
+ return ReadPPMFileHeader(chan, widthPtr, heightPtr, &dummy);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileReadPPM --
+ *
+ * This function is called by the photo image type to read PPM format
+ * data from a file and write it into a given photo image.
+ *
+ * Results:
+ * A standard TCL completion code. If TCL_ERROR is returned then an error
+ * message is left in the interp's result.
+ *
+ * Side effects:
+ * The access position in file f is changed, and new data is added to the
+ * image given by imageHandle.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+FileReadPPM(
+ Tcl_Interp *interp, /* Interpreter to use for reporting errors. */
+ Tcl_Channel chan, /* The image file, open for reading. */
+ const char *fileName, /* The name of the image file. */
+ Tcl_Obj *format, /* User-specified format string, or NULL. */
+ Tk_PhotoHandle imageHandle, /* The photo image to write into. */
+ int destX, int destY, /* Coordinates of top-left pixel in photo
+ * image to be written to. */
+ int width, int height, /* Dimensions of block of photo image to be
+ * written to. */
+ int srcX, int srcY) /* Coordinates of top-left pixel to be used in
+ * image being read. */
+{
+ int fileWidth, fileHeight, maxIntensity;
+ int nLines, nBytes, h, type, count, bytesPerChannel = 1;
+ unsigned char *pixelPtr;
+ Tk_PhotoImageBlock block;
+
+ type = ReadPPMFileHeader(chan, &fileWidth, &fileHeight, &maxIntensity);
+ if (type == 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "couldn't read raw PPM header from file \"%s\"", fileName));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PPM", "NO_HEADER", NULL);
+ return TCL_ERROR;
+ }
+ if ((fileWidth <= 0) || (fileHeight <= 0)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "PPM image file \"%s\" has dimension(s) <= 0", fileName));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PPM", "DIMENSIONS", NULL);
+ return TCL_ERROR;
+ }
+ if ((maxIntensity <= 0) || (maxIntensity > 0xffff)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "PPM image file \"%s\" has bad maximum intensity value %d",
+ fileName, maxIntensity));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PPM", "INTENSITY", NULL);
+ return TCL_ERROR;
+ } else if (maxIntensity > 0x00ff) {
+ bytesPerChannel = 2;
+ }
+
+ if ((srcX + width) > fileWidth) {
+ width = fileWidth - srcX;
+ }
+ if ((srcY + height) > fileHeight) {
+ height = fileHeight - srcY;
+ }
+ if ((width <= 0) || (height <= 0)
+ || (srcX >= fileWidth) || (srcY >= fileHeight)) {
+ return TCL_OK;
+ }
+
+ if (type == PGM) {
+ block.pixelSize = 1 * bytesPerChannel;
+ block.offset[0] = 0;
+ block.offset[1] = 0;
+ block.offset[2] = 0;
+ } else {
+ block.pixelSize = 3 * bytesPerChannel;
+ block.offset[0] = 0;
+ block.offset[1] = 1 * bytesPerChannel;
+ block.offset[2] = 2 * bytesPerChannel;
+ }
+ block.offset[3] = 0;
+ block.width = width;
+ block.pitch = block.pixelSize * fileWidth;
+
+ if (Tk_PhotoExpand(interp, imageHandle,
+ destX + width, destY + height) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (srcY > 0) {
+ Tcl_Seek(chan, (Tcl_WideInt)(srcY * block.pitch), SEEK_CUR);
+ }
+
+ nLines = (MAX_MEMORY + block.pitch - 1) / block.pitch;
+ if (nLines > height) {
+ nLines = height;
+ }
+ if (nLines <= 0) {
+ nLines = 1;
+ }
+ nBytes = nLines * block.pitch;
+ pixelPtr = ckalloc(nBytes);
+ block.pixelPtr = pixelPtr + srcX * block.pixelSize;
+
+ for (h = height; h > 0; h -= nLines) {
+ if (nLines > h) {
+ nLines = h;
+ nBytes = nLines * block.pitch;
+ }
+ count = Tcl_Read(chan, (char *) pixelPtr, nBytes);
+ if (count != nBytes) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "error reading PPM image file \"%s\": %s", fileName,
+ Tcl_Eof(chan)?"not enough data":Tcl_PosixError(interp)));
+ if (Tcl_Eof(chan)) {
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PPM", "EOF", NULL);
+ }
+ ckfree(pixelPtr);
+ return TCL_ERROR;
+ }
+ if (maxIntensity < 0x00ff) {
+ unsigned char *p;
+
+ for (p = pixelPtr; count > 0; count--, p++) {
+ *p = (((int) *p) * 255)/maxIntensity;
+ }
+ } else if (maxIntensity > 0x00ff) {
+ unsigned char *p;
+ unsigned int value;
+
+ for (p = pixelPtr; count > 0; count--, p += 2) {
+ value = ((unsigned int) p[0]) * 256 + ((unsigned int) p[1]);
+ value = value * 255 / maxIntensity;
+ p[0] = p[1] = (unsigned char) value;
+ }
+ }
+ block.height = nLines;
+ if (Tk_PhotoPutBlock(interp, imageHandle, &block, destX, destY,
+ width, nLines, TK_PHOTO_COMPOSITE_SET) != TCL_OK) {
+ ckfree(pixelPtr);
+ return TCL_ERROR;
+ }
+ destY += nLines;
+ }
+
+ ckfree(pixelPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileWritePPM --
+ *
+ * This function is invoked to write image data to a file in PPM format
+ * (although we can read PGM files, we never write them).
+ *
+ * Results:
+ * A standard TCL completion code. If TCL_ERROR is returned then an error
+ * message is left in the interp's result.
+ *
+ * Side effects:
+ * Data is written to the file given by "fileName".
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+FileWritePPM(
+ Tcl_Interp *interp,
+ const char *fileName,
+ Tcl_Obj *format,
+ Tk_PhotoImageBlock *blockPtr)
+{
+ Tcl_Channel chan;
+ int w, h, greenOffset, blueOffset, nBytes;
+ unsigned char *pixelPtr, *pixLinePtr;
+ char header[16 + TCL_INTEGER_SPACE * 2];
+
+ chan = Tcl_OpenFileChannel(interp, fileName, "w", 0666);
+ if (chan == NULL) {
+ return TCL_ERROR;
+ }
+
+ if (Tcl_SetChannelOption(interp, chan, "-translation", "binary")
+ != TCL_OK) {
+ Tcl_Close(NULL, chan);
+ return TCL_ERROR;
+ }
+ if (Tcl_SetChannelOption(interp, chan, "-encoding", "binary")
+ != TCL_OK) {
+ Tcl_Close(NULL, chan);
+ return TCL_ERROR;
+ }
+
+ sprintf(header, "P6\n%d %d\n255\n", blockPtr->width, blockPtr->height);
+ Tcl_Write(chan, header, -1);
+
+ pixLinePtr = blockPtr->pixelPtr + blockPtr->offset[0];
+ greenOffset = blockPtr->offset[1] - blockPtr->offset[0];
+ blueOffset = blockPtr->offset[2] - blockPtr->offset[0];
+
+ if ((greenOffset == 1) && (blueOffset == 2) && (blockPtr->pixelSize == 3)
+ && (blockPtr->pitch == (blockPtr->width * 3))) {
+ nBytes = blockPtr->height * blockPtr->pitch;
+ if (Tcl_Write(chan, (char *) pixLinePtr, nBytes) != nBytes) {
+ goto writeerror;
+ }
+ } else {
+ for (h = blockPtr->height; h > 0; h--) {
+ pixelPtr = pixLinePtr;
+ for (w = blockPtr->width; w > 0; w--) {
+ if ( Tcl_Write(chan,(char *)&pixelPtr[0], 1) == -1 ||
+ Tcl_Write(chan,(char *)&pixelPtr[greenOffset],1)==-1 ||
+ Tcl_Write(chan,(char *)&pixelPtr[blueOffset],1) ==-1) {
+ goto writeerror;
+ }
+ pixelPtr += blockPtr->pixelSize;
+ }
+ pixLinePtr += blockPtr->pitch;
+ }
+ }
+
+ if (Tcl_Close(NULL, chan) == 0) {
+ return TCL_OK;
+ }
+ chan = NULL;
+
+ writeerror:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf("error writing \"%s\": %s",
+ fileName, Tcl_PosixError(interp)));
+ if (chan != NULL) {
+ Tcl_Close(NULL, chan);
+ }
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * StringWritePPM --
+ *
+ * This function is invoked to write image data to a string in PPM
+ * format.
+ *
+ * Results:
+ * A standard TCL completion code. If TCL_ERROR is returned then an error
+ * message is left in the interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+StringWritePPM(
+ Tcl_Interp *interp,
+ Tcl_Obj *format,
+ Tk_PhotoImageBlock *blockPtr)
+{
+ int w, h, size, greenOffset, blueOffset;
+ unsigned char *pixLinePtr, *byteArray;
+ char header[16 + TCL_INTEGER_SPACE * 2];
+ Tcl_Obj *byteArrayObj;
+
+ sprintf(header, "P6\n%d %d\n255\n", blockPtr->width, blockPtr->height);
+
+ /*
+ * Construct a byte array of the right size with the header and
+ * get a pointer to the data part of it.
+ */
+
+ size = strlen(header);
+ byteArrayObj = Tcl_NewByteArrayObj((unsigned char *)header, size);
+ byteArray = Tcl_SetByteArrayLength(byteArrayObj,
+ size + 3*blockPtr->width*blockPtr->height);
+ byteArray += size;
+
+ pixLinePtr = blockPtr->pixelPtr + blockPtr->offset[0];
+ greenOffset = blockPtr->offset[1] - blockPtr->offset[0];
+ blueOffset = blockPtr->offset[2] - blockPtr->offset[0];
+
+ /*
+ * Check if we can do the data move in single action.
+ */
+
+ if ((greenOffset == 1) && (blueOffset == 2) && (blockPtr->pixelSize == 3)
+ && (blockPtr->pitch == (blockPtr->width * 3))) {
+ memcpy(byteArray, pixLinePtr,
+ (unsigned)blockPtr->height * blockPtr->pitch);
+ } else {
+ for (h = blockPtr->height; h > 0; h--) {
+ unsigned char *pixelPtr = pixLinePtr;
+
+ for (w = blockPtr->width; w > 0; w--) {
+ *byteArray++ = pixelPtr[0];
+ *byteArray++ = pixelPtr[greenOffset];
+ *byteArray++ = pixelPtr[blueOffset];
+ pixelPtr += blockPtr->pixelSize;
+ }
+ pixLinePtr += blockPtr->pitch;
+ }
+ }
+
+ /*
+ * Return the object in the interpreter result.
+ */
+
+ Tcl_SetObjResult(interp, byteArrayObj);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * StringMatchPPM --
+ *
+ * This function is invoked by the photo image type to see if a string
+ * contains image data in PPM format.
+ *
+ * Results:
+ * The return value is >0 if the first characters in file "f" look like
+ * PPM data, and 0 otherwise.
+ *
+ * Side effects:
+ * The access position in f may change.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+StringMatchPPM(
+ Tcl_Obj *dataObj, /* The image data. */
+ Tcl_Obj *format, /* User-specified format string, or NULL. */
+ int *widthPtr, int *heightPtr,
+ /* The dimensions of the image are returned
+ * here if the file is a valid raw PPM
+ * file. */
+ Tcl_Interp *interp) /* unused */
+{
+ int dummy;
+
+ return ReadPPMStringHeader(dataObj, widthPtr, heightPtr,
+ &dummy, NULL, NULL);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * StringReadPPM --
+ *
+ * This function is called by the photo image type to read PPM format
+ * data from a string and write it into a given photo image.
+ *
+ * Results:
+ * A standard TCL completion code. If TCL_ERROR is returned then an error
+ * message is left in the interp's result.
+ *
+ * Side effects:
+ * New data is added to the image given by imageHandle.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+StringReadPPM(
+ Tcl_Interp *interp, /* Interpreter to use for reporting errors. */
+ Tcl_Obj *dataObj, /* The image data. */
+ Tcl_Obj *format, /* User-specified format string, or NULL. */
+ Tk_PhotoHandle imageHandle, /* The photo image to write into. */
+ int destX, int destY, /* Coordinates of top-left pixel in photo
+ * image to be written to. */
+ int width, int height, /* Dimensions of block of photo image to be
+ * written to. */
+ int srcX, int srcY) /* Coordinates of top-left pixel to be used in
+ * image being read. */
+{
+ int fileWidth, fileHeight, maxIntensity;
+ int nLines, nBytes, h, type, count, dataSize, bytesPerChannel = 1;
+ unsigned char *pixelPtr, *dataBuffer;
+ Tk_PhotoImageBlock block;
+
+ type = ReadPPMStringHeader(dataObj, &fileWidth, &fileHeight,
+ &maxIntensity, &dataBuffer, &dataSize);
+ if (type == 0) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "couldn't read raw PPM header from string", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PPM", "NO_HEADER", NULL);
+ return TCL_ERROR;
+ }
+ if ((fileWidth <= 0) || (fileHeight <= 0)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "PPM image data has dimension(s) <= 0", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PPM", "DIMENSIONS", NULL);
+ return TCL_ERROR;
+ }
+ if ((maxIntensity <= 0) || (maxIntensity > 0xffff)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "PPM image data has bad maximum intensity value %d",
+ maxIntensity));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PPM", "INTENSITY", NULL);
+ return TCL_ERROR;
+ } else if (maxIntensity > 0x00ff) {
+ bytesPerChannel = 2;
+ }
+
+ if ((srcX + width) > fileWidth) {
+ width = fileWidth - srcX;
+ }
+ if ((srcY + height) > fileHeight) {
+ height = fileHeight - srcY;
+ }
+ if ((width <= 0) || (height <= 0)
+ || (srcX >= fileWidth) || (srcY >= fileHeight)) {
+ return TCL_OK;
+ }
+
+ if (type == PGM) {
+ block.pixelSize = 1 * bytesPerChannel;
+ block.offset[0] = 0;
+ block.offset[1] = 0;
+ block.offset[2] = 0;
+ } else {
+ block.pixelSize = 3 * bytesPerChannel;
+ block.offset[0] = 0;
+ block.offset[1] = 1 * bytesPerChannel;
+ block.offset[2] = 2 * bytesPerChannel;
+ }
+ block.offset[3] = 0;
+ block.width = width;
+ block.pitch = block.pixelSize * fileWidth;
+
+ if (srcY > 0) {
+ dataBuffer += srcY * block.pitch;
+ dataSize -= srcY * block.pitch;
+ }
+
+ if (maxIntensity == 0x00ff) {
+ /*
+ * We have all the data in memory, so write everything in one go.
+ */
+
+ if (block.pitch*height > dataSize) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "truncated PPM data", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PPM", "TRUNCATED", NULL);
+ return TCL_ERROR;
+ }
+ block.pixelPtr = dataBuffer + srcX * block.pixelSize;
+ block.height = height;
+ return Tk_PhotoPutBlock(interp, imageHandle, &block, destX, destY,
+ width, height, TK_PHOTO_COMPOSITE_SET);
+ }
+
+ if (Tk_PhotoExpand(interp, imageHandle,
+ destX + width, destY + height) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ nLines = (MAX_MEMORY + block.pitch - 1) / block.pitch;
+ if (nLines > height) {
+ nLines = height;
+ }
+ if (nLines <= 0) {
+ nLines = 1;
+ }
+ nBytes = nLines * block.pitch;
+ pixelPtr = ckalloc(nBytes);
+ block.pixelPtr = pixelPtr + srcX * block.pixelSize;
+
+ for (h = height; h > 0; h -= nLines) {
+ unsigned char *p;
+
+ if (nLines > h) {
+ nLines = h;
+ nBytes = nLines * block.pitch;
+ }
+ if (dataSize < nBytes) {
+ ckfree(pixelPtr);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "truncated PPM data", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PPM", "TRUNCATED", NULL);
+ return TCL_ERROR;
+ }
+ if (maxIntensity < 0x00ff) {
+ for (p=pixelPtr,count=nBytes ; count>0 ; count--,p++,dataBuffer++) {
+ *p = (((int) *dataBuffer) * 255)/maxIntensity;
+ }
+ } else {
+ unsigned char *p;
+ unsigned int value;
+
+ for (p = pixelPtr,count=nBytes; count > 1; count-=2, p += 2) {
+ value = ((unsigned int) p[0]) * 256 + ((unsigned int) p[1]);
+ value = value * 255 / maxIntensity;
+ p[0] = p[1] = (unsigned char) value;
+ }
+ }
+ dataSize -= nBytes;
+ block.height = nLines;
+ if (Tk_PhotoPutBlock(interp, imageHandle, &block, destX, destY,
+ width, nLines, TK_PHOTO_COMPOSITE_SET) != TCL_OK) {
+ ckfree(pixelPtr);
+ return TCL_ERROR;
+ }
+ destY += nLines;
+ }
+
+ ckfree(pixelPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ReadPPMFileHeader --
+ *
+ * This function reads the PPM header from the beginning of a PPM file
+ * and returns information from the header.
+ *
+ * Results:
+ * The return value is PGM if file "f" appears to start with a valid PGM
+ * header, PPM if "f" appears to start with a valid PPM header, and 0
+ * otherwise. If the header is valid, then *widthPtr and *heightPtr are
+ * modified to hold the dimensions of the image and *maxIntensityPtr is
+ * modified to hold the value of a "fully on" intensity value.
+ *
+ * Side effects:
+ * The access position in f advances.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ReadPPMFileHeader(
+ Tcl_Channel chan, /* Image file to read the header from. */
+ int *widthPtr, int *heightPtr,
+ /* The dimensions of the image are returned
+ * here. */
+ int *maxIntensityPtr) /* The maximum intensity value for the image
+ * is stored here. */
+{
+#define BUFFER_SIZE 1000
+ char buffer[BUFFER_SIZE], c;
+ int i, numFields, type = 0;
+
+ /*
+ * Read 4 space-separated fields from the file, ignoring comments (any
+ * line that starts with "#").
+ */
+
+ if (Tcl_Read(chan, &c, 1) != 1) {
+ return 0;
+ }
+ i = 0;
+ for (numFields = 0; numFields < 4; numFields++) {
+ /*
+ * Skip comments and white space.
+ */
+
+ while (1) {
+ while (isspace(UCHAR(c))) {
+ if (Tcl_Read(chan, &c, 1) != 1) {
+ return 0;
+ }
+ }
+ if (c != '#') {
+ break;
+ }
+ do {
+ if (Tcl_Read(chan, &c, 1) != 1) {
+ return 0;
+ }
+ } while (c != '\n');
+ }
+
+ /*
+ * Read a field (everything up to the next white space).
+ */
+
+ while (!isspace(UCHAR(c))) {
+ if (i < (BUFFER_SIZE-2)) {
+ buffer[i] = c;
+ i++;
+ }
+ if (Tcl_Read(chan, &c, 1) != 1) {
+ goto done;
+ }
+ }
+ if (i < (BUFFER_SIZE-1)) {
+ buffer[i] = ' ';
+ i++;
+ }
+ }
+
+ done:
+ buffer[i] = 0;
+
+ /*
+ * Parse the fields, which are: id, width, height, maxIntensity.
+ */
+
+ if (strncmp(buffer, "P6 ", 3) == 0) {
+ type = PPM;
+ } else if (strncmp(buffer, "P5 ", 3) == 0) {
+ type = PGM;
+ } else {
+ return 0;
+ }
+ if (sscanf(buffer+3, "%d %d %d", widthPtr, heightPtr, maxIntensityPtr)
+ != 3) {
+ return 0;
+ }
+ return type;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ReadPPMStringHeader --
+ *
+ * This function reads the PPM header from the beginning of a PPM-format
+ * string and returns information from the header.
+ *
+ * Results:
+ * The return value is PGM if the string appears to start with a valid
+ * PGM header, PPM if the string appears to start with a valid PPM
+ * header, and 0 otherwise. If the header is valid, then *widthPtr and
+ * *heightPtr are modified to hold the dimensions of the image and
+ * *maxIntensityPtr is modified to hold the value of a "fully on"
+ * intensity value.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ReadPPMStringHeader(
+ Tcl_Obj *dataPtr, /* Object to read the header from. */
+ int *widthPtr, int *heightPtr,
+ /* The dimensions of the image are returned
+ * here. */
+ int *maxIntensityPtr, /* The maximum intensity value for the image
+ * is stored here. */
+ unsigned char **dataBufferPtr,
+ int *dataSizePtr)
+{
+#define BUFFER_SIZE 1000
+ char buffer[BUFFER_SIZE], c;
+ int i, numFields, dataSize, type = 0;
+ unsigned char *dataBuffer;
+
+ dataBuffer = Tcl_GetByteArrayFromObj(dataPtr, &dataSize);
+
+ /*
+ * Read 4 space-separated fields from the string, ignoring comments (any
+ * line that starts with "#").
+ */
+
+ if (dataSize-- < 1) {
+ return 0;
+ }
+ c = (char) (*dataBuffer++);
+ i = 0;
+ for (numFields = 0; numFields < 4; numFields++) {
+ /*
+ * Skip comments and white space.
+ */
+
+ while (1) {
+ while (isspace(UCHAR(c))) {
+ if (dataSize-- < 1) {
+ return 0;
+ }
+ c = (char) (*dataBuffer++);
+ }
+ if (c != '#') {
+ break;
+ }
+ do {
+ if (dataSize-- < 1) {
+ return 0;
+ }
+ c = (char) (*dataBuffer++);
+ } while (c != '\n');
+ }
+
+ /*
+ * Read a field (everything up to the next white space).
+ */
+
+ while (!isspace(UCHAR(c))) {
+ if (i < (BUFFER_SIZE-2)) {
+ buffer[i] = c;
+ i++;
+ }
+ if (dataSize-- < 1) {
+ goto done;
+ }
+ c = (char) (*dataBuffer++);
+ }
+ if (i < (BUFFER_SIZE-1)) {
+ buffer[i] = ' ';
+ i++;
+ }
+ }
+
+ done:
+ buffer[i] = 0;
+
+ /*
+ * Parse the fields, which are: id, width, height, maxIntensity.
+ */
+
+ if (strncmp(buffer, "P6 ", 3) == 0) {
+ type = PPM;
+ } else if (strncmp(buffer, "P5 ", 3) == 0) {
+ type = PGM;
+ } else {
+ return 0;
+ }
+ if (sscanf(buffer+3, "%d %d %d", widthPtr, heightPtr, maxIntensityPtr)
+ != 3) {
+ return 0;
+ }
+ if (dataBufferPtr != NULL) {
+ *dataBufferPtr = dataBuffer;
+ *dataSizePtr = dataSize;
+ }
+ return type;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkImgPhInstance.c b/tk8.6/generic/tkImgPhInstance.c
new file mode 100644
index 0000000..72ebcb8
--- /dev/null
+++ b/tk8.6/generic/tkImgPhInstance.c
@@ -0,0 +1,1997 @@
+/*
+ * tkImgPhInstance.c --
+ *
+ * Implements the rendering of images of type "photo" for Tk. Photo
+ * images are stored in full color (32 bits per pixel including alpha
+ * channel) and displayed using dithering if necessary.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 2002-2008 Donal K. Fellows
+ * Copyright (c) 2003 ActiveState Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Author: Paul Mackerras (paulus@cs.anu.edu.au),
+ * Department of Computer Science,
+ * Australian National University.
+ */
+
+#include "tkImgPhoto.h"
+#ifdef MAC_OSX_TK
+#define TKPUTIMAGE_CAN_BLEND
+#endif
+
+/*
+ * Declaration for internal Xlib function used here:
+ */
+
+extern int _XInitImageFuncPtrs(XImage *image);
+
+/*
+ * Forward declarations
+ */
+
+#ifndef TKPUTIMAGE_CAN_BLEND
+static void BlendComplexAlpha(XImage *bgImg, PhotoInstance *iPtr,
+ int xOffset, int yOffset, int width, int height);
+#endif
+static int IsValidPalette(PhotoInstance *instancePtr,
+ const char *palette);
+static int CountBits(pixel mask);
+static void GetColorTable(PhotoInstance *instancePtr);
+static void FreeColorTable(ColorTable *colorPtr, int force);
+static void AllocateColors(ColorTable *colorPtr);
+static void DisposeColorTable(ClientData clientData);
+static int ReclaimColors(ColorTableId *id, int numColors);
+
+/*
+ * Hash table used to hash from (display, colormap, palette, gamma) to
+ * ColorTable address.
+ */
+
+static Tcl_HashTable imgPhotoColorHash;
+static int imgPhotoColorHashInitialized;
+#define N_COLOR_HASH (sizeof(ColorTableId) / sizeof(int))
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkImgPhotoConfigureInstance --
+ *
+ * This function is called to create displaying information for a photo
+ * image instance based on the configuration information in the master.
+ * It is invoked both when new instances are created and when the master
+ * is reconfigured.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Generates errors via Tcl_BackgroundException if there are problems in
+ * setting up the instance.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkImgPhotoConfigureInstance(
+ PhotoInstance *instancePtr) /* Instance to reconfigure. */
+{
+ PhotoMaster *masterPtr = instancePtr->masterPtr;
+ XImage *imagePtr;
+ int bitsPerPixel;
+ ColorTable *colorTablePtr;
+ XRectangle validBox;
+
+ /*
+ * If the -palette configuration option has been set for the master, use
+ * the value specified for our palette, but only if it is a valid palette
+ * for our windows. Use the gamma value specified the master.
+ */
+
+ if ((masterPtr->palette && masterPtr->palette[0])
+ && IsValidPalette(instancePtr, masterPtr->palette)) {
+ instancePtr->palette = masterPtr->palette;
+ } else {
+ instancePtr->palette = instancePtr->defaultPalette;
+ }
+ instancePtr->gamma = masterPtr->gamma;
+
+ /*
+ * If we don't currently have a color table, or if the one we have no
+ * longer applies (e.g. because our palette or gamma has changed), get a
+ * new one.
+ */
+
+ colorTablePtr = instancePtr->colorTablePtr;
+ if ((colorTablePtr == NULL)
+ || (instancePtr->colormap != colorTablePtr->id.colormap)
+ || (instancePtr->palette != colorTablePtr->id.palette)
+ || (instancePtr->gamma != colorTablePtr->id.gamma)) {
+ /*
+ * Free up our old color table, and get a new one.
+ */
+
+ if (colorTablePtr != NULL) {
+ colorTablePtr->liveRefCount -= 1;
+ FreeColorTable(colorTablePtr, 0);
+ }
+ GetColorTable(instancePtr);
+
+ /*
+ * Create a new XImage structure for sending data to the X server, if
+ * necessary.
+ */
+
+ if (instancePtr->colorTablePtr->flags & BLACK_AND_WHITE) {
+ bitsPerPixel = 1;
+ } else {
+ bitsPerPixel = instancePtr->visualInfo.depth;
+ }
+
+ if ((instancePtr->imagePtr == NULL)
+ || (instancePtr->imagePtr->bits_per_pixel != bitsPerPixel)) {
+ if (instancePtr->imagePtr != NULL) {
+ XDestroyImage(instancePtr->imagePtr);
+ }
+ imagePtr = XCreateImage(instancePtr->display,
+ instancePtr->visualInfo.visual, (unsigned) bitsPerPixel,
+ (bitsPerPixel > 1? ZPixmap: XYBitmap), 0, NULL,
+ 1, 1, 32, 0);
+ instancePtr->imagePtr = imagePtr;
+
+ /*
+ * We create images using the local host's endianness, rather than
+ * the endianness of the server; otherwise we would have to
+ * byte-swap any 16 or 32 bit values that we store in the image
+ * if the server's endianness is different from ours.
+ */
+
+ if (imagePtr != NULL) {
+#ifdef WORDS_BIGENDIAN
+ imagePtr->byte_order = MSBFirst;
+#else
+ imagePtr->byte_order = LSBFirst;
+#endif
+ _XInitImageFuncPtrs(imagePtr);
+ }
+ }
+ }
+
+ /*
+ * If the user has specified a width and/or height for the master which is
+ * different from our current width/height, set the size to the values
+ * specified by the user. If we have no pixmap, we do this also, since it
+ * has the side effect of allocating a pixmap for us.
+ */
+
+ if ((instancePtr->pixels == None) || (instancePtr->error == NULL)
+ || (instancePtr->width != masterPtr->width)
+ || (instancePtr->height != masterPtr->height)) {
+ TkImgPhotoInstanceSetSize(instancePtr);
+ }
+
+ /*
+ * Redither this instance if necessary.
+ */
+
+ if ((masterPtr->flags & IMAGE_CHANGED)
+ || (instancePtr->colorTablePtr != colorTablePtr)) {
+ TkClipBox(masterPtr->validRegion, &validBox);
+ if ((validBox.width > 0) && (validBox.height > 0)) {
+ TkImgDitherInstance(instancePtr, validBox.x, validBox.y,
+ validBox.width, validBox.height);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkImgPhotoGet --
+ *
+ * This function is called for each use of a photo image in a widget.
+ *
+ * Results:
+ * The return value is a token for the instance, which is passed back to
+ * us in calls to TkImgPhotoDisplay and ImgPhotoFree.
+ *
+ * Side effects:
+ * A data structure is set up for the instance (or, an existing instance
+ * is re-used for the new one).
+ *
+ *----------------------------------------------------------------------
+ */
+
+ClientData
+TkImgPhotoGet(
+ Tk_Window tkwin, /* Window in which the instance will be
+ * used. */
+ ClientData masterData) /* Pointer to our master structure for the
+ * image. */
+{
+ PhotoMaster *masterPtr = masterData;
+ PhotoInstance *instancePtr;
+ Colormap colormap;
+ int mono, nRed, nGreen, nBlue, numVisuals;
+ XVisualInfo visualInfo, *visInfoPtr;
+ char buf[TCL_INTEGER_SPACE * 3];
+ XColor *white, *black;
+ XGCValues gcValues;
+
+ /*
+ * Table of "best" choices for palette for PseudoColor displays with
+ * between 3 and 15 bits/pixel.
+ */
+
+ static const int paletteChoice[13][3] = {
+ /* #red, #green, #blue */
+ {2, 2, 2, /* 3 bits, 8 colors */},
+ {2, 3, 2, /* 4 bits, 12 colors */},
+ {3, 4, 2, /* 5 bits, 24 colors */},
+ {4, 5, 3, /* 6 bits, 60 colors */},
+ {5, 6, 4, /* 7 bits, 120 colors */},
+ {7, 7, 4, /* 8 bits, 198 colors */},
+ {8, 10, 6, /* 9 bits, 480 colors */},
+ {10, 12, 8, /* 10 bits, 960 colors */},
+ {14, 15, 9, /* 11 bits, 1890 colors */},
+ {16, 20, 12, /* 12 bits, 3840 colors */},
+ {20, 24, 16, /* 13 bits, 7680 colors */},
+ {26, 30, 20, /* 14 bits, 15600 colors */},
+ {32, 32, 30, /* 15 bits, 30720 colors */}
+ };
+
+ /*
+ * See if there is already an instance for windows using the same
+ * colormap. If so then just re-use it.
+ */
+
+ colormap = Tk_Colormap(tkwin);
+ for (instancePtr = masterPtr->instancePtr; instancePtr != NULL;
+ instancePtr = instancePtr->nextPtr) {
+ if ((colormap == instancePtr->colormap)
+ && (Tk_Display(tkwin) == instancePtr->display)) {
+ /*
+ * Re-use this instance.
+ */
+
+ if (instancePtr->refCount == 0) {
+ /*
+ * We are resurrecting this instance.
+ */
+
+ Tcl_CancelIdleCall(TkImgDisposeInstance, instancePtr);
+ if (instancePtr->colorTablePtr != NULL) {
+ FreeColorTable(instancePtr->colorTablePtr, 0);
+ }
+ GetColorTable(instancePtr);
+ }
+ instancePtr->refCount++;
+ return instancePtr;
+ }
+ }
+
+ /*
+ * The image isn't already in use in a window with the same colormap. Make
+ * a new instance of the image.
+ */
+
+ instancePtr = ckalloc(sizeof(PhotoInstance));
+ instancePtr->masterPtr = masterPtr;
+ instancePtr->display = Tk_Display(tkwin);
+ instancePtr->colormap = Tk_Colormap(tkwin);
+ Tk_PreserveColormap(instancePtr->display, instancePtr->colormap);
+ instancePtr->refCount = 1;
+ instancePtr->colorTablePtr = NULL;
+ instancePtr->pixels = None;
+ instancePtr->error = NULL;
+ instancePtr->width = 0;
+ instancePtr->height = 0;
+ instancePtr->imagePtr = 0;
+ instancePtr->nextPtr = masterPtr->instancePtr;
+ masterPtr->instancePtr = instancePtr;
+
+ /*
+ * Obtain information about the visual and decide on the default palette.
+ */
+
+ visualInfo.screen = Tk_ScreenNumber(tkwin);
+ visualInfo.visualid = XVisualIDFromVisual(Tk_Visual(tkwin));
+ visInfoPtr = XGetVisualInfo(Tk_Display(tkwin),
+ VisualScreenMask | VisualIDMask, &visualInfo, &numVisuals);
+ if (visInfoPtr == NULL) {
+ Tcl_Panic("TkImgPhotoGet couldn't find visual for window");
+ }
+
+ nRed = 2;
+ nGreen = nBlue = 0;
+ mono = 1;
+ instancePtr->visualInfo = *visInfoPtr;
+ switch (visInfoPtr->class) {
+ case DirectColor:
+ case TrueColor:
+ nRed = 1 << CountBits(visInfoPtr->red_mask);
+ nGreen = 1 << CountBits(visInfoPtr->green_mask);
+ nBlue = 1 << CountBits(visInfoPtr->blue_mask);
+ mono = 0;
+ break;
+ case PseudoColor:
+ case StaticColor:
+ if (visInfoPtr->depth > 15) {
+ nRed = 32;
+ nGreen = 32;
+ nBlue = 32;
+ mono = 0;
+ } else if (visInfoPtr->depth >= 3) {
+ const int *ip = paletteChoice[visInfoPtr->depth - 3];
+
+ nRed = ip[0];
+ nGreen = ip[1];
+ nBlue = ip[2];
+ mono = 0;
+ }
+ break;
+ case GrayScale:
+ case StaticGray:
+ nRed = 1 << visInfoPtr->depth;
+ break;
+ }
+ XFree((char *) visInfoPtr);
+
+ if (mono) {
+ sprintf(buf, "%d", nRed);
+ } else {
+ sprintf(buf, "%d/%d/%d", nRed, nGreen, nBlue);
+ }
+ instancePtr->defaultPalette = Tk_GetUid(buf);
+
+ /*
+ * Make a GC with background = black and foreground = white.
+ */
+
+ white = Tk_GetColor(masterPtr->interp, tkwin, "white");
+ black = Tk_GetColor(masterPtr->interp, tkwin, "black");
+ gcValues.foreground = (white != NULL)? white->pixel:
+ WhitePixelOfScreen(Tk_Screen(tkwin));
+ gcValues.background = (black != NULL)? black->pixel:
+ BlackPixelOfScreen(Tk_Screen(tkwin));
+ Tk_FreeColor(white);
+ Tk_FreeColor(black);
+ gcValues.graphics_exposures = False;
+ instancePtr->gc = Tk_GetGC(tkwin,
+ GCForeground|GCBackground|GCGraphicsExposures, &gcValues);
+
+ /*
+ * Set configuration options and finish the initialization of the
+ * instance. This will also dither the image if necessary.
+ */
+
+ TkImgPhotoConfigureInstance(instancePtr);
+
+ /*
+ * If this is the first instance, must set the size of the image.
+ */
+
+ if (instancePtr->nextPtr == NULL) {
+ Tk_ImageChanged(masterPtr->tkMaster, 0, 0, 0, 0,
+ masterPtr->width, masterPtr->height);
+ }
+
+ return instancePtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * BlendComplexAlpha --
+ *
+ * This function is called when an image with partially transparent
+ * pixels must be drawn over another image. It blends the photo data onto
+ * a local copy of the surface that we are drawing on, *including* the
+ * pixels drawn by everything that should be drawn underneath the image.
+ *
+ * Much of this code has hard-coded values in for speed because this
+ * routine is performance critical for complex image drawing.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Background image passed in gets drawn over with image data.
+ *
+ * Notes:
+ * This should work on all platforms that set mask and shift data
+ * properly from the visualInfo. RGB is really only a 24+ bpp version
+ * whereas RGB15 is the correct version and works for 15bpp+, but it
+ * slower, so it's only used for 15bpp+.
+ *
+ * Note that Win32 pre-defines those operations that we really need.
+ *
+ * Note that on MacOS, if the background comes from a Retina display
+ * then it will be twice as wide and twice as high as the photoimage.
+ *
+ *----------------------------------------------------------------------
+ */
+#ifndef TKPUTIMAGE_CAN_BLEND
+#ifndef _WIN32
+#define GetRValue(rgb) (UCHAR(((rgb) & red_mask) >> red_shift))
+#define GetGValue(rgb) (UCHAR(((rgb) & green_mask) >> green_shift))
+#define GetBValue(rgb) (UCHAR(((rgb) & blue_mask) >> blue_shift))
+#define RGB(r, g, b) ((unsigned)( \
+ (UCHAR(r) << red_shift) | \
+ (UCHAR(g) << green_shift) | \
+ (UCHAR(b) << blue_shift) ))
+#define RGB15(r, g, b) ((unsigned)( \
+ (((r) * red_mask / 255) & red_mask) | \
+ (((g) * green_mask / 255) & green_mask) | \
+ (((b) * blue_mask / 255) & blue_mask) ))
+#endif /* !_WIN32 */
+
+static void
+BlendComplexAlpha(
+ XImage *bgImg, /* Background image to draw on. */
+ PhotoInstance *iPtr, /* Image instance to draw. */
+ int xOffset, int yOffset, /* X & Y offset into image instance to
+ * draw. */
+ int width, int height) /* Width & height of image to draw. */
+{
+ int x, y, line;
+ unsigned long pixel;
+ unsigned char r, g, b, alpha, unalpha, *masterPtr;
+ unsigned char *alphaAr = iPtr->masterPtr->pix32;
+
+ /*
+ * This blending is an integer version of the Source-Over compositing rule
+ * (see Porter&Duff, "Compositing Digital Images", proceedings of SIGGRAPH
+ * 1984) that has been hard-coded (for speed) to work with targetting a
+ * solid surface.
+ *
+ * The 'unalpha' field must be 255-alpha; it is separated out to encourage
+ * more efficient compilation.
+ */
+
+#define ALPHA_BLEND(bgPix, imgPix, alpha, unalpha) \
+ ((bgPix * unalpha + imgPix * alpha) / 255)
+
+ /*
+ * We have to get the mask and shift info from the visual on non-Win32 so
+ * that the macros Get*Value(), RGB() and RGB15() work correctly. This
+ * might be cached for better performance.
+ */
+
+#ifndef _WIN32
+ unsigned long red_mask, green_mask, blue_mask;
+ unsigned long red_shift, green_shift, blue_shift;
+ Visual *visual = iPtr->visualInfo.visual;
+
+ red_mask = visual->red_mask;
+ green_mask = visual->green_mask;
+ blue_mask = visual->blue_mask;
+ red_shift = 0;
+ green_shift = 0;
+ blue_shift = 0;
+ while ((0x0001 & (red_mask >> red_shift)) == 0) {
+ red_shift++;
+ }
+ while ((0x0001 & (green_mask >> green_shift)) == 0) {
+ green_shift++;
+ }
+ while ((0x0001 & (blue_mask >> blue_shift)) == 0) {
+ blue_shift++;
+ }
+#endif /* !_WIN32 */
+
+ /*
+ * Only UNIX requires the special case for <24bpp. It varies with 3 extra
+ * shifts and uses RGB15. The 24+bpp version could also then be further
+ * optimized.
+ */
+
+#if !defined(_WIN32)
+ if (bgImg->depth < 24) {
+ unsigned char red_mlen, green_mlen, blue_mlen;
+
+ red_mlen = 8 - CountBits(red_mask >> red_shift);
+ green_mlen = 8 - CountBits(green_mask >> green_shift);
+ blue_mlen = 8 - CountBits(blue_mask >> blue_shift);
+ for (y = 0; y < height; y++) {
+ line = (y + yOffset) * iPtr->masterPtr->width;
+ for (x = 0; x < width; x++) {
+ masterPtr = alphaAr + ((line + x + xOffset) * 4);
+ alpha = masterPtr[3];
+
+ /*
+ * Ignore pixels that are fully transparent
+ */
+
+ if (alpha) {
+ /*
+ * We could perhaps be more efficient than XGetPixel for
+ * 24 and 32 bit displays, but this seems "fast enough".
+ */
+
+ r = masterPtr[0];
+ g = masterPtr[1];
+ b = masterPtr[2];
+ if (alpha != 255) {
+ /*
+ * Only blend pixels that have some transparency
+ */
+
+ unsigned char ra, ga, ba;
+
+ pixel = XGetPixel(bgImg, x, y);
+ ra = GetRValue(pixel) << red_mlen;
+ ga = GetGValue(pixel) << green_mlen;
+ ba = GetBValue(pixel) << blue_mlen;
+ unalpha = 255 - alpha; /* Calculate once. */
+ r = ALPHA_BLEND(ra, r, alpha, unalpha);
+ g = ALPHA_BLEND(ga, g, alpha, unalpha);
+ b = ALPHA_BLEND(ba, b, alpha, unalpha);
+ }
+ XPutPixel(bgImg, x, y, RGB15(r, g, b));
+ }
+ }
+ }
+ return;
+ }
+#endif /* !_WIN32 */
+
+ for (y = 0; y < height; y++) {
+ line = (y + yOffset) * iPtr->masterPtr->width;
+ for (x = 0; x < width; x++) {
+ masterPtr = alphaAr + ((line + x + xOffset) * 4);
+ alpha = masterPtr[3];
+
+ /*
+ * Ignore pixels that are fully transparent
+ */
+
+ if (alpha) {
+ /*
+ * We could perhaps be more efficient than XGetPixel for 24
+ * and 32 bit displays, but this seems "fast enough".
+ */
+
+ r = masterPtr[0];
+ g = masterPtr[1];
+ b = masterPtr[2];
+ if (alpha != 255) {
+ /*
+ * Only blend pixels that have some transparency
+ */
+
+ unsigned char ra, ga, ba;
+
+ pixel = XGetPixel(bgImg, x, y);
+ ra = GetRValue(pixel);
+ ga = GetGValue(pixel);
+ ba = GetBValue(pixel);
+ unalpha = 255 - alpha; /* Calculate once. */
+ r = ALPHA_BLEND(ra, r, alpha, unalpha);
+ g = ALPHA_BLEND(ga, g, alpha, unalpha);
+ b = ALPHA_BLEND(ba, b, alpha, unalpha);
+ }
+ XPutPixel(bgImg, x, y, RGB(r, g, b));
+ }
+ }
+ }
+#undef ALPHA_BLEND
+}
+#endif /* TKPUTIMAGE_CAN_BLEND */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkImgPhotoDisplay --
+ *
+ * This function is invoked to draw a photo image.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A portion of the image gets rendered in a pixmap or window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkImgPhotoDisplay(
+ ClientData clientData, /* Pointer to PhotoInstance structure for
+ * instance to be displayed. */
+ Display *display, /* Display on which to draw image. */
+ Drawable drawable, /* Pixmap or window in which to draw image. */
+ int imageX, int imageY, /* Upper-left corner of region within image to
+ * draw. */
+ int width, int height, /* Dimensions of region within image to
+ * draw. */
+ int drawableX,int drawableY)/* Coordinates within drawable that correspond
+ * to imageX and imageY. */
+{
+ PhotoInstance *instancePtr = clientData;
+#ifndef TKPUTIMAGE_CAN_BLEND
+ XVisualInfo visInfo = instancePtr->visualInfo;
+#endif
+
+ /*
+ * If there's no pixmap, it means that an error occurred while creating
+ * the image instance so it can't be displayed.
+ */
+
+ if (instancePtr->pixels == None) {
+ return;
+ }
+
+#ifdef TKPUTIMAGE_CAN_BLEND
+ /*
+ * If TkPutImage can handle RGBA Ximages directly there is
+ * no need to call XGetImage or to do the Porter-Duff compositing by hand.
+ */
+
+ unsigned char *rgbaPixels = instancePtr->masterPtr->pix32;
+ XImage *photo = XCreateImage(display, NULL, 32, ZPixmap, 0, (char*)rgbaPixels,
+ (unsigned int)instancePtr->width,
+ (unsigned int)instancePtr->height,
+ 0, (unsigned int)(4 * instancePtr->width));
+ TkPutImage(NULL, 0, display, drawable, instancePtr->gc,
+ photo, imageX, imageY, drawableX, drawableY,
+ (unsigned int) width, (unsigned int) height);
+ photo->data = NULL;
+ XDestroyImage(photo);
+#else
+
+ if ((instancePtr->masterPtr->flags & COMPLEX_ALPHA)
+ && visInfo.depth >= 15
+ && (visInfo.class == DirectColor || visInfo.class == TrueColor)) {
+ Tk_ErrorHandler handler;
+ XImage *bgImg = NULL;
+
+ /*
+ * Create an error handler to suppress the case where the input was
+ * not properly constrained, which can cause an X error. [Bug 979239]
+ */
+
+ handler = Tk_CreateErrorHandler(display, -1, -1, -1, NULL, NULL);
+
+ /*
+ * Pull the current background from the display to blend with
+ */
+
+ bgImg = XGetImage(display, drawable, drawableX, drawableY,
+ (unsigned int)width, (unsigned int)height, AllPlanes, ZPixmap);
+ if (bgImg == NULL) {
+ Tk_DeleteErrorHandler(handler);
+ /* We failed to get the image, so draw without blending alpha.
+ * It's the best we can do.
+ */
+ goto fallBack;
+ }
+
+ BlendComplexAlpha(bgImg, instancePtr, imageX, imageY, width, height);
+
+ /*
+ * Color info is unimportant as we only do this operation for depth >=
+ * 15.
+ */
+
+ TkPutImage(NULL, 0, display, drawable, instancePtr->gc,
+ bgImg, 0, 0, drawableX, drawableY,
+ (unsigned int) width, (unsigned int) height);
+ XDestroyImage(bgImg);
+ Tk_DeleteErrorHandler(handler);
+ } else {
+ /*
+ * masterPtr->region describes which parts of the image contain valid
+ * data. We set this region as the clip mask for the gc, setting its
+ * origin appropriately, and use it when drawing the image.
+ */
+
+ fallBack:
+ TkSetRegion(display, instancePtr->gc,
+ instancePtr->masterPtr->validRegion);
+ XSetClipOrigin(display, instancePtr->gc, drawableX - imageX,
+ drawableY - imageY);
+ XCopyArea(display, instancePtr->pixels, drawable, instancePtr->gc,
+ imageX, imageY, (unsigned) width, (unsigned) height,
+ drawableX, drawableY);
+ XSetClipMask(display, instancePtr->gc, None);
+ XSetClipOrigin(display, instancePtr->gc, 0, 0);
+ }
+ XFlush(display);
+#endif
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkImgPhotoFree --
+ *
+ * This function is called when a widget ceases to use a particular
+ * instance of an image. We don't actually get rid of the instance until
+ * later because we may be about to get this instance again.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Internal data structures get cleaned up, later.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkImgPhotoFree(
+ ClientData clientData, /* Pointer to PhotoInstance structure for
+ * instance to be displayed. */
+ Display *display) /* Display containing window that used
+ * image. */
+{
+ PhotoInstance *instancePtr = clientData;
+ ColorTable *colorPtr;
+
+ if (instancePtr->refCount-- > 1) {
+ return;
+ }
+
+ /*
+ * There are no more uses of the image within this widget. Decrement the
+ * count of live uses of its color table, so that its colors can be
+ * reclaimed if necessary, and set up an idle call to free the instance
+ * structure.
+ */
+
+ colorPtr = instancePtr->colorTablePtr;
+ if (colorPtr != NULL) {
+ colorPtr->liveRefCount -= 1;
+ }
+
+ Tcl_DoWhenIdle(TkImgDisposeInstance, instancePtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkImgPhotoInstanceSetSize --
+ *
+ * This function reallocates the instance pixmap and dithering error
+ * array for a photo instance, as necessary, to change the image's size
+ * to `width' x `height' pixels.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Storage gets reallocated, here and in the X server.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkImgPhotoInstanceSetSize(
+ PhotoInstance *instancePtr) /* Instance whose size is to be changed. */
+{
+ PhotoMaster *masterPtr;
+ schar *newError, *errSrcPtr, *errDestPtr;
+ int h, offset;
+ XRectangle validBox;
+ Pixmap newPixmap;
+
+ masterPtr = instancePtr->masterPtr;
+ TkClipBox(masterPtr->validRegion, &validBox);
+
+ if ((instancePtr->width != masterPtr->width)
+ || (instancePtr->height != masterPtr->height)
+ || (instancePtr->pixels == None)) {
+ newPixmap = Tk_GetPixmap(instancePtr->display,
+ RootWindow(instancePtr->display,
+ instancePtr->visualInfo.screen),
+ (masterPtr->width > 0) ? masterPtr->width: 1,
+ (masterPtr->height > 0) ? masterPtr->height: 1,
+ instancePtr->visualInfo.depth);
+ if (!newPixmap) {
+ Tcl_Panic("Fail to create pixmap with Tk_GetPixmap in TkImgPhotoInstanceSetSize");
+ }
+
+ /*
+ * The following is a gross hack needed to properly support colormaps
+ * under Windows. Before the pixels can be copied to the pixmap, the
+ * relevent colormap must be associated with the drawable. Normally we
+ * can infer this association from the window that was used to create
+ * the pixmap. However, in this case we're using the root window, so
+ * we have to be more explicit.
+ */
+
+ TkSetPixmapColormap(newPixmap, instancePtr->colormap);
+
+ if (instancePtr->pixels != None) {
+ /*
+ * Copy any common pixels from the old pixmap and free it.
+ */
+
+ XCopyArea(instancePtr->display, instancePtr->pixels, newPixmap,
+ instancePtr->gc, validBox.x, validBox.y,
+ validBox.width, validBox.height, validBox.x, validBox.y);
+ Tk_FreePixmap(instancePtr->display, instancePtr->pixels);
+ }
+ instancePtr->pixels = newPixmap;
+ }
+
+ if ((instancePtr->width != masterPtr->width)
+ || (instancePtr->height != masterPtr->height)
+ || (instancePtr->error == NULL)) {
+ if (masterPtr->height > 0 && masterPtr->width > 0) {
+ /*
+ * TODO: use attemptckalloc() here once there is a strategy that
+ * will allow us to recover from failure. Right now, there's no
+ * such possibility.
+ */
+
+ newError = ckalloc(masterPtr->height * masterPtr->width
+ * 3 * sizeof(schar));
+
+ /*
+ * Zero the new array so that we don't get bogus error values
+ * propagating into areas we dither later.
+ */
+
+ if ((instancePtr->error != NULL)
+ && ((instancePtr->width == masterPtr->width)
+ || (validBox.width == masterPtr->width))) {
+ if (validBox.y > 0) {
+ memset(newError, 0, (size_t)
+ validBox.y * masterPtr->width * 3 * sizeof(schar));
+ }
+ h = validBox.y + validBox.height;
+ if (h < masterPtr->height) {
+ memset(newError + h*masterPtr->width*3, 0,
+ (size_t) (masterPtr->height - h)
+ * masterPtr->width * 3 * sizeof(schar));
+ }
+ } else {
+ memset(newError, 0, (size_t)
+ masterPtr->height * masterPtr->width *3*sizeof(schar));
+ }
+ } else {
+ newError = NULL;
+ }
+
+ if (instancePtr->error != NULL) {
+ /*
+ * Copy the common area over to the new array and free the old
+ * array.
+ */
+
+ if (masterPtr->width == instancePtr->width) {
+ offset = validBox.y * masterPtr->width * 3;
+ memcpy(newError + offset, instancePtr->error + offset,
+ (size_t) (validBox.height
+ * masterPtr->width * 3 * sizeof(schar)));
+
+ } else if (validBox.width > 0 && validBox.height > 0) {
+ errDestPtr = newError +
+ (validBox.y * masterPtr->width + validBox.x) * 3;
+ errSrcPtr = instancePtr->error +
+ (validBox.y * instancePtr->width + validBox.x) * 3;
+
+ for (h = validBox.height; h > 0; --h) {
+ memcpy(errDestPtr, errSrcPtr,
+ validBox.width * 3 * sizeof(schar));
+ errDestPtr += masterPtr->width * 3;
+ errSrcPtr += instancePtr->width * 3;
+ }
+ }
+ ckfree(instancePtr->error);
+ }
+
+ instancePtr->error = newError;
+ }
+
+ instancePtr->width = masterPtr->width;
+ instancePtr->height = masterPtr->height;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * IsValidPalette --
+ *
+ * This function is called to check whether a value given for the
+ * -palette option is valid for a particular instance of a photo image.
+ *
+ * Results:
+ * A boolean value: 1 if the palette is acceptable, 0 otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+IsValidPalette(
+ PhotoInstance *instancePtr, /* Instance to which the palette specification
+ * is to be applied. */
+ const char *palette) /* Palette specification string. */
+{
+ int nRed, nGreen, nBlue, mono, numColors;
+ char *endp;
+
+ /*
+ * First parse the specification: it must be of the form %d or %d/%d/%d.
+ */
+
+ nRed = strtol(palette, &endp, 10);
+ if ((endp == palette) || ((*endp != 0) && (*endp != '/'))
+ || (nRed < 2) || (nRed > 256)) {
+ return 0;
+ }
+
+ if (*endp == 0) {
+ mono = 1;
+ nGreen = nBlue = nRed;
+ } else {
+ palette = endp + 1;
+ nGreen = strtol(palette, &endp, 10);
+ if ((endp == palette) || (*endp != '/') || (nGreen < 2)
+ || (nGreen > 256)) {
+ return 0;
+ }
+ palette = endp + 1;
+ nBlue = strtol(palette, &endp, 10);
+ if ((endp == palette) || (*endp != 0) || (nBlue < 2)
+ || (nBlue > 256)) {
+ return 0;
+ }
+ mono = 0;
+ }
+
+ switch (instancePtr->visualInfo.class) {
+ case DirectColor:
+ case TrueColor:
+ if ((nRed > (1 << CountBits(instancePtr->visualInfo.red_mask)))
+ || (nGreen>(1<<CountBits(instancePtr->visualInfo.green_mask)))
+ || (nBlue>(1<<CountBits(instancePtr->visualInfo.blue_mask)))) {
+ return 0;
+ }
+ break;
+ case PseudoColor:
+ case StaticColor:
+ numColors = nRed;
+ if (!mono) {
+ numColors *= nGreen * nBlue;
+ }
+ if (numColors > (1 << instancePtr->visualInfo.depth)) {
+ return 0;
+ }
+ break;
+ case GrayScale:
+ case StaticGray:
+ if (!mono || (nRed > (1 << instancePtr->visualInfo.depth))) {
+ return 0;
+ }
+ break;
+ }
+
+ return 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CountBits --
+ *
+ * This function counts how many bits are set to 1 in `mask'.
+ *
+ * Results:
+ * The integer number of bits.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CountBits(
+ pixel mask) /* Value to count the 1 bits in. */
+{
+ int n;
+
+ for (n=0 ; mask!=0 ; mask&=mask-1) {
+ n++;
+ }
+ return n;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetColorTable --
+ *
+ * This function is called to allocate a table of colormap information
+ * for an instance of a photo image. Only one such table is allocated for
+ * all photo instances using the same display, colormap, palette and
+ * gamma values, so that the application need only request a set of
+ * colors from the X server once for all such photo widgets. This
+ * function maintains a hash table to find previously-allocated
+ * ColorTables.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A new ColorTable may be allocated and placed in the hash table, and
+ * have colors allocated for it.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GetColorTable(
+ PhotoInstance *instancePtr) /* Instance needing a color table. */
+{
+ ColorTable *colorPtr;
+ Tcl_HashEntry *entry;
+ ColorTableId id;
+ int isNew;
+
+ /*
+ * Look for an existing ColorTable in the hash table.
+ */
+
+ memset(&id, 0, sizeof(id));
+ id.display = instancePtr->display;
+ id.colormap = instancePtr->colormap;
+ id.palette = instancePtr->palette;
+ id.gamma = instancePtr->gamma;
+ if (!imgPhotoColorHashInitialized) {
+ Tcl_InitHashTable(&imgPhotoColorHash, N_COLOR_HASH);
+ imgPhotoColorHashInitialized = 1;
+ }
+ entry = Tcl_CreateHashEntry(&imgPhotoColorHash, (char *) &id, &isNew);
+
+ if (!isNew) {
+ /*
+ * Re-use the existing entry.
+ */
+
+ colorPtr = Tcl_GetHashValue(entry);
+ } else {
+ /*
+ * No color table currently available; need to make one.
+ */
+
+ colorPtr = ckalloc(sizeof(ColorTable));
+
+ /*
+ * The following line of code should not normally be needed due to the
+ * assignment in the following line. However, it compensates for bugs
+ * in some compilers (HP, for example) where sizeof(ColorTable) is 24
+ * but the assignment only copies 20 bytes, leaving 4 bytes
+ * uninitialized; these cause problems when using the id for lookups
+ * in imgPhotoColorHash, and can result in core dumps.
+ */
+
+ memset(&colorPtr->id, 0, sizeof(ColorTableId));
+ colorPtr->id = id;
+ Tk_PreserveColormap(colorPtr->id.display, colorPtr->id.colormap);
+ colorPtr->flags = 0;
+ colorPtr->refCount = 0;
+ colorPtr->liveRefCount = 0;
+ colorPtr->numColors = 0;
+ colorPtr->visualInfo = instancePtr->visualInfo;
+ colorPtr->pixelMap = NULL;
+ Tcl_SetHashValue(entry, colorPtr);
+ }
+
+ colorPtr->refCount++;
+ colorPtr->liveRefCount++;
+ instancePtr->colorTablePtr = colorPtr;
+ if (colorPtr->flags & DISPOSE_PENDING) {
+ Tcl_CancelIdleCall(DisposeColorTable, colorPtr);
+ colorPtr->flags &= ~DISPOSE_PENDING;
+ }
+
+ /*
+ * Allocate colors for this color table if necessary.
+ */
+
+ if ((colorPtr->numColors == 0) && !(colorPtr->flags & BLACK_AND_WHITE)) {
+ AllocateColors(colorPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeColorTable --
+ *
+ * This function is called when an instance ceases using a color table.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If no other instances are using this color table, a when-idle handler
+ * is registered to free up the color table and the colors allocated for
+ * it.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FreeColorTable(
+ ColorTable *colorPtr, /* Pointer to the color table which is no
+ * longer required by an instance. */
+ int force) /* Force free to happen immediately. */
+{
+ colorPtr->refCount--;
+ if (colorPtr->refCount > 0) {
+ return;
+ }
+
+ if (force) {
+ if (colorPtr->flags & DISPOSE_PENDING) {
+ Tcl_CancelIdleCall(DisposeColorTable, colorPtr);
+ colorPtr->flags &= ~DISPOSE_PENDING;
+ }
+ DisposeColorTable(colorPtr);
+ } else if (!(colorPtr->flags & DISPOSE_PENDING)) {
+ Tcl_DoWhenIdle(DisposeColorTable, colorPtr);
+ colorPtr->flags |= DISPOSE_PENDING;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AllocateColors --
+ *
+ * This function allocates the colors required by a color table, and sets
+ * up the fields in the color table data structure which are used in
+ * dithering.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Colors are allocated from the X server. Fields in the color table data
+ * structure are updated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+AllocateColors(
+ ColorTable *colorPtr) /* Pointer to the color table requiring colors
+ * to be allocated. */
+{
+ int i, r, g, b, rMult, mono;
+ int numColors, nRed, nGreen, nBlue;
+ double fr, fg, fb, igam;
+ XColor *colors;
+ unsigned long *pixels;
+
+ /*
+ * 16-bit intensity value for i/n of full intensity.
+ */
+#define CFRAC(i, n) ((i) * 65535 / (n))
+
+ /* As for CFRAC, but apply exponent of g. */
+#define CGFRAC(i, n, g) ((int)(65535 * pow((double)(i) / (n), (g))))
+
+ /*
+ * First parse the palette specification to get the required number of
+ * shades of each primary.
+ */
+
+ mono = sscanf(colorPtr->id.palette, "%d/%d/%d", &nRed, &nGreen, &nBlue)
+ <= 1;
+ igam = 1.0 / colorPtr->id.gamma;
+
+ /*
+ * Each time around this loop, we reduce the number of colors we're trying
+ * to allocate until we succeed in allocating all of the colors we need.
+ */
+
+ for (;;) {
+ /*
+ * If we are using 1 bit/pixel, we don't need to allocate any colors
+ * (we just use the foreground and background colors in the GC).
+ */
+
+ if (mono && (nRed <= 2)) {
+ colorPtr->flags |= BLACK_AND_WHITE;
+ return;
+ }
+
+ /*
+ * Calculate the RGB coordinates of the colors we want to allocate and
+ * store them in *colors.
+ */
+
+ if ((colorPtr->visualInfo.class == DirectColor)
+ || (colorPtr->visualInfo.class == TrueColor)) {
+
+ /*
+ * Direct/True Color: allocate shades of red, green, blue
+ * independently.
+ */
+
+ if (mono) {
+ numColors = nGreen = nBlue = nRed;
+ } else {
+ numColors = MAX(MAX(nRed, nGreen), nBlue);
+ }
+ colors = ckalloc(numColors * sizeof(XColor));
+
+ for (i = 0; i < numColors; ++i) {
+ if (igam == 1.0) {
+ colors[i].red = CFRAC(i, nRed - 1);
+ colors[i].green = CFRAC(i, nGreen - 1);
+ colors[i].blue = CFRAC(i, nBlue - 1);
+ } else {
+ colors[i].red = CGFRAC(i, nRed - 1, igam);
+ colors[i].green = CGFRAC(i, nGreen - 1, igam);
+ colors[i].blue = CGFRAC(i, nBlue - 1, igam);
+ }
+ }
+ } else {
+ /*
+ * PseudoColor, StaticColor, GrayScale or StaticGray visual: we
+ * have to allocate each color in the color cube separately.
+ */
+
+ numColors = (mono) ? nRed: (nRed * nGreen * nBlue);
+ colors = ckalloc(numColors * sizeof(XColor));
+
+ if (!mono) {
+ /*
+ * Color display using a PseudoColor or StaticColor visual.
+ */
+
+ i = 0;
+ for (r = 0; r < nRed; ++r) {
+ for (g = 0; g < nGreen; ++g) {
+ for (b = 0; b < nBlue; ++b) {
+ if (igam == 1.0) {
+ colors[i].red = CFRAC(r, nRed - 1);
+ colors[i].green = CFRAC(g, nGreen - 1);
+ colors[i].blue = CFRAC(b, nBlue - 1);
+ } else {
+ colors[i].red = CGFRAC(r, nRed - 1, igam);
+ colors[i].green = CGFRAC(g, nGreen - 1, igam);
+ colors[i].blue = CGFRAC(b, nBlue - 1, igam);
+ }
+ i++;
+ }
+ }
+ }
+ } else {
+ /*
+ * Monochrome display - allocate the shades of gray we want.
+ */
+
+ for (i = 0; i < numColors; ++i) {
+ if (igam == 1.0) {
+ r = CFRAC(i, numColors - 1);
+ } else {
+ r = CGFRAC(i, numColors - 1, igam);
+ }
+ colors[i].red = colors[i].green = colors[i].blue = r;
+ }
+ }
+ }
+
+ /*
+ * Now try to allocate the colors we've calculated.
+ */
+
+ pixels = ckalloc(numColors * sizeof(unsigned long));
+ for (i = 0; i < numColors; ++i) {
+ if (!XAllocColor(colorPtr->id.display, colorPtr->id.colormap,
+ &colors[i])) {
+ /*
+ * Can't get all the colors we want in the default colormap;
+ * first try freeing colors from other unused color tables.
+ */
+
+ if (!ReclaimColors(&colorPtr->id, numColors - i)
+ || !XAllocColor(colorPtr->id.display,
+ colorPtr->id.colormap, &colors[i])) {
+ /*
+ * Still can't allocate the color.
+ */
+
+ break;
+ }
+ }
+ pixels[i] = colors[i].pixel;
+ }
+
+ /*
+ * If we didn't get all of the colors, reduce the resolution of the
+ * color cube, free the ones we got, and try again.
+ */
+
+ if (i >= numColors) {
+ break;
+ }
+ XFreeColors(colorPtr->id.display, colorPtr->id.colormap, pixels, i, 0);
+ ckfree(colors);
+ ckfree(pixels);
+
+ if (!mono) {
+ if ((nRed == 2) && (nGreen == 2) && (nBlue == 2)) {
+ /*
+ * Fall back to 1-bit monochrome display.
+ */
+
+ mono = 1;
+ } else {
+ /*
+ * Reduce the number of shades of each primary to about 3/4 of
+ * the previous value. This should reduce the total number of
+ * colors required to about half the previous value for
+ * PseudoColor displays.
+ */
+
+ nRed = (nRed * 3 + 2) / 4;
+ nGreen = (nGreen * 3 + 2) / 4;
+ nBlue = (nBlue * 3 + 2) / 4;
+ }
+ } else {
+ /*
+ * Reduce the number of shades of gray to about 1/2.
+ */
+
+ nRed = nRed / 2;
+ }
+ }
+
+ /*
+ * We have allocated all of the necessary colors: fill in various fields
+ * of the ColorTable record.
+ */
+
+ if (!mono) {
+ colorPtr->flags |= COLOR_WINDOW;
+
+ /*
+ * The following is a hairy hack. We only want to index into the
+ * pixelMap on colormap displays. However, if the display is on
+ * Windows, then we actually want to store the index not the value
+ * since we will be passing the color table into the TkPutImage call.
+ */
+
+#ifndef _WIN32
+ if ((colorPtr->visualInfo.class != DirectColor)
+ && (colorPtr->visualInfo.class != TrueColor)) {
+ colorPtr->flags |= MAP_COLORS;
+ }
+#endif /* _WIN32 */
+ }
+
+ colorPtr->numColors = numColors;
+ colorPtr->pixelMap = pixels;
+
+ /*
+ * Set up quantization tables for dithering.
+ */
+
+ rMult = nGreen * nBlue;
+ for (i = 0; i < 256; ++i) {
+ r = (i * (nRed - 1) + 127) / 255;
+ if (mono) {
+ fr = (double) colors[r].red / 65535.0;
+ if (colorPtr->id.gamma != 1.0 ) {
+ fr = pow(fr, colorPtr->id.gamma);
+ }
+ colorPtr->colorQuant[0][i] = (int)(fr * 255.99);
+ colorPtr->redValues[i] = colors[r].pixel;
+ } else {
+ g = (i * (nGreen - 1) + 127) / 255;
+ b = (i * (nBlue - 1) + 127) / 255;
+ if ((colorPtr->visualInfo.class == DirectColor)
+ || (colorPtr->visualInfo.class == TrueColor)) {
+ colorPtr->redValues[i] =
+ colors[r].pixel & colorPtr->visualInfo.red_mask;
+ colorPtr->greenValues[i] =
+ colors[g].pixel & colorPtr->visualInfo.green_mask;
+ colorPtr->blueValues[i] =
+ colors[b].pixel & colorPtr->visualInfo.blue_mask;
+ } else {
+ r *= rMult;
+ g *= nBlue;
+ colorPtr->redValues[i] = r;
+ colorPtr->greenValues[i] = g;
+ colorPtr->blueValues[i] = b;
+ }
+ fr = (double) colors[r].red / 65535.0;
+ fg = (double) colors[g].green / 65535.0;
+ fb = (double) colors[b].blue / 65535.0;
+ if (colorPtr->id.gamma != 1.0) {
+ fr = pow(fr, colorPtr->id.gamma);
+ fg = pow(fg, colorPtr->id.gamma);
+ fb = pow(fb, colorPtr->id.gamma);
+ }
+ colorPtr->colorQuant[0][i] = (int)(fr * 255.99);
+ colorPtr->colorQuant[1][i] = (int)(fg * 255.99);
+ colorPtr->colorQuant[2][i] = (int)(fb * 255.99);
+ }
+ }
+
+ ckfree(colors);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DisposeColorTable --
+ *
+ * Release a color table and its associated resources.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The colors in the argument color table are freed, as is the color
+ * table structure itself. The color table is removed from the hash table
+ * which is used to locate color tables.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DisposeColorTable(
+ ClientData clientData) /* Pointer to the ColorTable whose
+ * colors are to be released. */
+{
+ ColorTable *colorPtr = clientData;
+ Tcl_HashEntry *entry;
+
+ if (colorPtr->pixelMap != NULL) {
+ if (colorPtr->numColors > 0) {
+ XFreeColors(colorPtr->id.display, colorPtr->id.colormap,
+ colorPtr->pixelMap, colorPtr->numColors, 0);
+ Tk_FreeColormap(colorPtr->id.display, colorPtr->id.colormap);
+ }
+ ckfree(colorPtr->pixelMap);
+ }
+
+ entry = Tcl_FindHashEntry(&imgPhotoColorHash, (char *) &colorPtr->id);
+ if (entry == NULL) {
+ Tcl_Panic("DisposeColorTable couldn't find hash entry");
+ }
+ Tcl_DeleteHashEntry(entry);
+
+ ckfree(colorPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ReclaimColors --
+ *
+ * This function is called to try to free up colors in the colormap used
+ * by a color table. It looks for other color tables with the same
+ * colormap and with a zero live reference count, and frees their colors.
+ * It only does so if there is the possibility of freeing up at least
+ * `numColors' colors.
+ *
+ * Results:
+ * The return value is TRUE if any colors were freed, FALSE otherwise.
+ *
+ * Side effects:
+ * ColorTables which are not currently in use may lose their color
+ * allocations.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ReclaimColors(
+ ColorTableId *id, /* Pointer to information identifying
+ * the color table which needs more colors. */
+ int numColors) /* Number of colors required. */
+{
+ Tcl_HashSearch srch;
+ Tcl_HashEntry *entry;
+ ColorTable *colorPtr;
+ int nAvail = 0;
+
+ /*
+ * First scan through the color hash table to get an upper bound on how
+ * many colors we might be able to free.
+ */
+
+ entry = Tcl_FirstHashEntry(&imgPhotoColorHash, &srch);
+ while (entry != NULL) {
+ colorPtr = Tcl_GetHashValue(entry);
+ if ((colorPtr->id.display == id->display)
+ && (colorPtr->id.colormap == id->colormap)
+ && (colorPtr->liveRefCount == 0 )&& (colorPtr->numColors != 0)
+ && ((colorPtr->id.palette != id->palette)
+ || (colorPtr->id.gamma != id->gamma))) {
+ /*
+ * We could take this guy's colors off him.
+ */
+
+ nAvail += colorPtr->numColors;
+ }
+ entry = Tcl_NextHashEntry(&srch);
+ }
+
+ /*
+ * nAvail is an (over)estimate of the number of colors we could free.
+ */
+
+ if (nAvail < numColors) {
+ return 0;
+ }
+
+ /*
+ * Scan through a second time freeing colors.
+ */
+
+ entry = Tcl_FirstHashEntry(&imgPhotoColorHash, &srch);
+ while ((entry != NULL) && (numColors > 0)) {
+ colorPtr = Tcl_GetHashValue(entry);
+ if ((colorPtr->id.display == id->display)
+ && (colorPtr->id.colormap == id->colormap)
+ && (colorPtr->liveRefCount == 0) && (colorPtr->numColors != 0)
+ && ((colorPtr->id.palette != id->palette)
+ || (colorPtr->id.gamma != id->gamma))) {
+ /*
+ * Free the colors that this ColorTable has.
+ */
+
+ XFreeColors(colorPtr->id.display, colorPtr->id.colormap,
+ colorPtr->pixelMap, colorPtr->numColors, 0);
+ numColors -= colorPtr->numColors;
+ colorPtr->numColors = 0;
+ ckfree(colorPtr->pixelMap);
+ colorPtr->pixelMap = NULL;
+ }
+
+ entry = Tcl_NextHashEntry(&srch);
+ }
+ return 1; /* We freed some colors. */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkImgDisposeInstance --
+ *
+ * This function is called to finally free up an instance of a photo
+ * image which is no longer required.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The instance data structure and the resources it references are freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkImgDisposeInstance(
+ ClientData clientData) /* Pointer to the instance whose resources are
+ * to be released. */
+{
+ PhotoInstance *instancePtr = clientData;
+ PhotoInstance *prevPtr;
+
+ if (instancePtr->pixels != None) {
+ Tk_FreePixmap(instancePtr->display, instancePtr->pixels);
+ }
+ if (instancePtr->gc != NULL) {
+ Tk_FreeGC(instancePtr->display, instancePtr->gc);
+ }
+ if (instancePtr->imagePtr != NULL) {
+ XDestroyImage(instancePtr->imagePtr);
+ }
+ if (instancePtr->error != NULL) {
+ ckfree(instancePtr->error);
+ }
+ if (instancePtr->colorTablePtr != NULL) {
+ FreeColorTable(instancePtr->colorTablePtr, 1);
+ }
+
+ if (instancePtr->masterPtr->instancePtr == instancePtr) {
+ instancePtr->masterPtr->instancePtr = instancePtr->nextPtr;
+ } else {
+ for (prevPtr = instancePtr->masterPtr->instancePtr;
+ prevPtr->nextPtr != instancePtr; prevPtr = prevPtr->nextPtr) {
+ /* Empty loop body. */
+ }
+ prevPtr->nextPtr = instancePtr->nextPtr;
+ }
+ Tk_FreeColormap(instancePtr->display, instancePtr->colormap);
+ ckfree(instancePtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkImgDitherInstance --
+ *
+ * This function is called to update an area of an instance's pixmap by
+ * dithering the corresponding area of the master.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The instance's pixmap gets updated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkImgDitherInstance(
+ PhotoInstance *instancePtr, /* The instance to be updated. */
+ int xStart, int yStart, /* Coordinates of the top-left pixel in the
+ * block to be dithered. */
+ int width, int height) /* Dimensions of the block to be dithered. */
+{
+ PhotoMaster *masterPtr = instancePtr->masterPtr;
+ ColorTable *colorPtr = instancePtr->colorTablePtr;
+ XImage *imagePtr;
+ int nLines, bigEndian, i, c, x, y, xEnd, doDithering = 1;
+ int bitsPerPixel, bytesPerLine, lineLength;
+ unsigned char *srcLinePtr;
+ schar *errLinePtr;
+ pixel firstBit, word, mask;
+
+ /*
+ * Turn dithering off in certain cases where it is not needed (TrueColor,
+ * DirectColor with many colors).
+ */
+
+ if ((colorPtr->visualInfo.class == DirectColor)
+ || (colorPtr->visualInfo.class == TrueColor)) {
+ int nRed, nGreen, nBlue, result;
+
+ result = sscanf(colorPtr->id.palette, "%d/%d/%d", &nRed,
+ &nGreen, &nBlue);
+ if ((nRed >= 256)
+ && ((result == 1) || ((nGreen >= 256) && (nBlue >= 256)))) {
+ doDithering = 0;
+ }
+ }
+
+ /*
+ * First work out how many lines to do at a time, then how many bytes
+ * we'll need for pixel storage, and allocate it.
+ */
+
+ nLines = (MAX_PIXELS + width - 1) / width;
+ if (nLines < 1) {
+ nLines = 1;
+ }
+ if (nLines > height ) {
+ nLines = height;
+ }
+
+ imagePtr = instancePtr->imagePtr;
+ if (imagePtr == NULL) {
+ return; /* We must be really tight on memory. */
+ }
+ bitsPerPixel = imagePtr->bits_per_pixel;
+ bytesPerLine = ((bitsPerPixel * width + 31) >> 3) & ~3;
+ imagePtr->width = width;
+ imagePtr->height = nLines;
+ imagePtr->bytes_per_line = bytesPerLine;
+
+ /*
+ * TODO: use attemptckalloc() here once we have some strategy for
+ * recovering from the failure.
+ */
+
+ imagePtr->data = ckalloc(imagePtr->bytes_per_line * nLines);
+ bigEndian = imagePtr->bitmap_bit_order == MSBFirst;
+ firstBit = bigEndian? (1 << (imagePtr->bitmap_unit - 1)): 1;
+
+ lineLength = masterPtr->width * 3;
+ srcLinePtr = masterPtr->pix32 + (yStart * masterPtr->width + xStart) * 4;
+ errLinePtr = instancePtr->error + yStart * lineLength + xStart * 3;
+ xEnd = xStart + width;
+
+ /*
+ * Loop over the image, doing at most nLines lines before updating the
+ * screen image.
+ */
+
+ for (; height > 0; height -= nLines) {
+ unsigned char *dstLinePtr = (unsigned char *) imagePtr->data;
+ int yEnd;
+
+ if (nLines > height) {
+ nLines = height;
+ }
+ yEnd = yStart + nLines;
+ for (y = yStart; y < yEnd; ++y) {
+ unsigned char *srcPtr = srcLinePtr;
+ schar *errPtr = errLinePtr;
+ unsigned char *destBytePtr = dstLinePtr;
+ pixel *destLongPtr = (pixel *) dstLinePtr;
+
+ if (colorPtr->flags & COLOR_WINDOW) {
+ /*
+ * Color window. We dither the three components independently,
+ * using Floyd-Steinberg dithering, which propagates errors
+ * from the quantization of pixels to the pixels below and to
+ * the right.
+ */
+
+ for (x = xStart; x < xEnd; ++x) {
+ int col[3];
+
+ if (doDithering) {
+ for (i = 0; i < 3; ++i) {
+ /*
+ * Compute the error propagated into this pixel
+ * for this component. If e[x,y] is the array of
+ * quantization error values, we compute
+ * 7/16 * e[x-1,y] + 1/16 * e[x-1,y-1]
+ * + 5/16 * e[x,y-1] + 3/16 * e[x+1,y-1]
+ * and round it to an integer.
+ *
+ * The expression ((c + 2056) >> 4) - 128 computes
+ * round(c / 16), and works correctly on machines
+ * without a sign-extending right shift.
+ */
+
+ c = (x > 0) ? errPtr[-3] * 7: 0;
+ if (y > 0) {
+ if (x > 0) {
+ c += errPtr[-lineLength-3];
+ }
+ c += errPtr[-lineLength] * 5;
+ if ((x + 1) < masterPtr->width) {
+ c += errPtr[-lineLength+3] * 3;
+ }
+ }
+
+ /*
+ * Add the propagated error to the value of this
+ * component, quantize it, and store the
+ * quantization error.
+ */
+
+ c = ((c + 2056) >> 4) - 128 + *srcPtr++;
+ if (c < 0) {
+ c = 0;
+ } else if (c > 255) {
+ c = 255;
+ }
+ col[i] = colorPtr->colorQuant[i][c];
+ *errPtr++ = c - col[i];
+ }
+ } else {
+ /*
+ * Output is virtually continuous in this case, so
+ * don't bother dithering.
+ */
+
+ col[0] = *srcPtr++;
+ col[1] = *srcPtr++;
+ col[2] = *srcPtr++;
+ }
+ srcPtr++;
+
+ /*
+ * Translate the quantized component values into an X
+ * pixel value, and store it in the image.
+ */
+
+ i = colorPtr->redValues[col[0]]
+ + colorPtr->greenValues[col[1]]
+ + colorPtr->blueValues[col[2]];
+ if (colorPtr->flags & MAP_COLORS) {
+ i = colorPtr->pixelMap[i];
+ }
+ switch (bitsPerPixel) {
+ case NBBY:
+ *destBytePtr++ = i;
+ break;
+#ifndef _WIN32
+ /*
+ * This case is not valid for Windows because the
+ * image format is different from the pixel format in
+ * Win32. Eventually we need to fix the image code in
+ * Tk to use the Windows native image ordering. This
+ * would speed up the image code for all of the common
+ * sizes.
+ */
+
+ case NBBY * sizeof(pixel):
+ *destLongPtr++ = i;
+ break;
+#endif
+ default:
+ XPutPixel(imagePtr, x - xStart, y - yStart,
+ (unsigned) i);
+ }
+ }
+
+ } else if (bitsPerPixel > 1) {
+ /*
+ * Multibit monochrome window. The operation here is similar
+ * to the color window case above, except that there is only
+ * one component. If the master image is in color, use the
+ * luminance computed as
+ * 0.344 * red + 0.5 * green + 0.156 * blue.
+ */
+
+ for (x = xStart; x < xEnd; ++x) {
+ c = (x > 0) ? errPtr[-1] * 7: 0;
+ if (y > 0) {
+ if (x > 0) {
+ c += errPtr[-lineLength-1];
+ }
+ c += errPtr[-lineLength] * 5;
+ if (x + 1 < masterPtr->width) {
+ c += errPtr[-lineLength+1] * 3;
+ }
+ }
+ c = ((c + 2056) >> 4) - 128;
+
+ if (masterPtr->flags & COLOR_IMAGE) {
+ c += (unsigned) (srcPtr[0] * 11 + srcPtr[1] * 16
+ + srcPtr[2] * 5 + 16) >> 5;
+ } else {
+ c += srcPtr[0];
+ }
+ srcPtr += 4;
+
+ if (c < 0) {
+ c = 0;
+ } else if (c > 255) {
+ c = 255;
+ }
+ i = colorPtr->colorQuant[0][c];
+ *errPtr++ = c - i;
+ i = colorPtr->redValues[i];
+ switch (bitsPerPixel) {
+ case NBBY:
+ *destBytePtr++ = i;
+ break;
+#ifndef _WIN32
+ /*
+ * This case is not valid for Windows because the
+ * image format is different from the pixel format in
+ * Win32. Eventually we need to fix the image code in
+ * Tk to use the Windows native image ordering. This
+ * would speed up the image code for all of the common
+ * sizes.
+ */
+
+ case NBBY * sizeof(pixel):
+ *destLongPtr++ = i;
+ break;
+#endif
+ default:
+ XPutPixel(imagePtr, x - xStart, y - yStart,
+ (unsigned) i);
+ }
+ }
+ } else {
+ /*
+ * 1-bit monochrome window. This is similar to the multibit
+ * monochrome case above, except that the quantization is
+ * simpler (we only have black = 0 and white = 255), and we
+ * produce an XY-Bitmap.
+ */
+
+ word = 0;
+ mask = firstBit;
+ for (x = xStart; x < xEnd; ++x) {
+ /*
+ * If we have accumulated a whole word, store it in the
+ * image and start a new word.
+ */
+
+ if (mask == 0) {
+ *destLongPtr++ = word;
+ mask = firstBit;
+ word = 0;
+ }
+
+ c = (x > 0) ? errPtr[-1] * 7: 0;
+ if (y > 0) {
+ if (x > 0) {
+ c += errPtr[-lineLength-1];
+ }
+ c += errPtr[-lineLength] * 5;
+ if (x + 1 < masterPtr->width) {
+ c += errPtr[-lineLength+1] * 3;
+ }
+ }
+ c = ((c + 2056) >> 4) - 128;
+
+ if (masterPtr->flags & COLOR_IMAGE) {
+ c += (unsigned)(srcPtr[0] * 11 + srcPtr[1] * 16
+ + srcPtr[2] * 5 + 16) >> 5;
+ } else {
+ c += srcPtr[0];
+ }
+ srcPtr += 4;
+
+ if (c < 0) {
+ c = 0;
+ } else if (c > 255) {
+ c = 255;
+ }
+ if (c >= 128) {
+ word |= mask;
+ *errPtr++ = c - 255;
+ } else {
+ *errPtr++ = c;
+ }
+ mask = bigEndian? (mask >> 1): (mask << 1);
+ }
+ *destLongPtr = word;
+ }
+ srcLinePtr += masterPtr->width * 4;
+ errLinePtr += lineLength;
+ dstLinePtr += bytesPerLine;
+ }
+
+ /*
+ * Update the pixmap for this instance with the block of pixels that
+ * we have just computed.
+ */
+
+ TkPutImage(colorPtr->pixelMap, colorPtr->numColors,
+ instancePtr->display, instancePtr->pixels,
+ instancePtr->gc, imagePtr, 0, 0, xStart, yStart,
+ (unsigned) width, (unsigned) nLines);
+ yStart = yEnd;
+ }
+
+ ckfree(imagePtr->data);
+ imagePtr->data = NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkImgResetDither --
+ *
+ * This function is called to eliminate the content of a photo instance's
+ * dither error buffer. It's called when the overall image is blanked.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The instance's dither buffer gets cleared.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkImgResetDither(
+ PhotoInstance *instancePtr)
+{
+ if (instancePtr->error) {
+ memset(instancePtr->error, 0,
+ /*(size_t)*/ (instancePtr->masterPtr->width
+ * instancePtr->masterPtr->height * 3 * sizeof(schar)));
+ }
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkImgPhoto.c b/tk8.6/generic/tkImgPhoto.c
new file mode 100644
index 0000000..03b3731
--- /dev/null
+++ b/tk8.6/generic/tkImgPhoto.c
@@ -0,0 +1,4174 @@
+/*
+ * tkImgPhoto.c --
+ *
+ * Implements images of type "photo" for Tk. Photo images are stored in
+ * full color (32 bits per pixel including alpha channel) and displayed
+ * using dithering if necessary.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 2002-2003 Donal K. Fellows
+ * Copyright (c) 2003 ActiveState Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Author: Paul Mackerras (paulus@cs.anu.edu.au),
+ * Department of Computer Science,
+ * Australian National University.
+ */
+
+#include "tkImgPhoto.h"
+
+/*
+ * The following data structure is used to return information from
+ * ParseSubcommandOptions:
+ */
+
+struct SubcommandOptions {
+ int options; /* Individual bits indicate which options were
+ * specified - see below. */
+ Tcl_Obj *name; /* Name specified without an option. */
+ int fromX, fromY; /* Values specified for -from option. */
+ int fromX2, fromY2; /* Second coordinate pair for -from option. */
+ int toX, toY; /* Values specified for -to option. */
+ int toX2, toY2; /* Second coordinate pair for -to option. */
+ int zoomX, zoomY; /* Values specified for -zoom option. */
+ int subsampleX, subsampleY; /* Values specified for -subsample option. */
+ Tcl_Obj *format; /* Value specified for -format option. */
+ XColor *background; /* Value specified for -background option. */
+ int compositingRule; /* Value specified for -compositingrule
+ * option. */
+};
+
+/*
+ * Bit definitions for use with ParseSubcommandOptions: each bit is set in the
+ * allowedOptions parameter on a call to ParseSubcommandOptions if that option
+ * is allowed for the current photo image subcommand. On return, the bit is
+ * set in the options field of the SubcommandOptions structure if that option
+ * was specified.
+ *
+ * OPT_BACKGROUND: Set if -format option allowed/specified.
+ * OPT_COMPOSITE: Set if -compositingrule option allowed/spec'd.
+ * OPT_FORMAT: Set if -format option allowed/specified.
+ * OPT_FROM: Set if -from option allowed/specified.
+ * OPT_GRAYSCALE: Set if -grayscale option allowed/specified.
+ * OPT_SHRINK: Set if -shrink option allowed/specified.
+ * OPT_SUBSAMPLE: Set if -subsample option allowed/spec'd.
+ * OPT_TO: Set if -to option allowed/specified.
+ * OPT_ZOOM: Set if -zoom option allowed/specified.
+ */
+
+#define OPT_BACKGROUND 1
+#define OPT_COMPOSITE 2
+#define OPT_FORMAT 4
+#define OPT_FROM 8
+#define OPT_GRAYSCALE 0x10
+#define OPT_SHRINK 0x20
+#define OPT_SUBSAMPLE 0x40
+#define OPT_TO 0x80
+#define OPT_ZOOM 0x100
+
+/*
+ * List of option names. The order here must match the order of declarations
+ * of the OPT_* constants above.
+ */
+
+static const char *const optionNames[] = {
+ "-background",
+ "-compositingrule",
+ "-format",
+ "-from",
+ "-grayscale",
+ "-shrink",
+ "-subsample",
+ "-to",
+ "-zoom",
+ NULL
+};
+
+/*
+ * Message to generate when an attempt to resize an image fails due to memory
+ * problems.
+ */
+
+#define TK_PHOTO_ALLOC_FAILURE_MESSAGE \
+ "not enough free memory for image buffer"
+
+/*
+ * Functions used in the type record for photo images.
+ */
+
+static int ImgPhotoCreate(Tcl_Interp *interp, const char *name,
+ int objc, Tcl_Obj *const objv[],
+ const Tk_ImageType *typePtr, Tk_ImageMaster master,
+ ClientData *clientDataPtr);
+static void ImgPhotoDelete(ClientData clientData);
+static int ImgPhotoPostscript(ClientData clientData,
+ Tcl_Interp *interp, Tk_Window tkwin,
+ Tk_PostscriptInfo psInfo, int x, int y, int width,
+ int height, int prepass);
+
+/*
+ * The type record itself for photo images:
+ */
+
+Tk_ImageType tkPhotoImageType = {
+ "photo", /* name */
+ ImgPhotoCreate, /* createProc */
+ TkImgPhotoGet, /* getProc */
+ TkImgPhotoDisplay, /* displayProc */
+ TkImgPhotoFree, /* freeProc */
+ ImgPhotoDelete, /* deleteProc */
+ ImgPhotoPostscript, /* postscriptProc */
+ NULL, /* nextPtr */
+ NULL
+};
+
+typedef struct {
+ Tk_PhotoImageFormat *formatList;
+ /* Pointer to the first in the list of known
+ * photo image formats.*/
+ Tk_PhotoImageFormat *oldFormatList;
+ /* Pointer to the first in the list of known
+ * photo image formats.*/
+ int initialized; /* Set to 1 if we've initialized the
+ * structure. */
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+
+/*
+ * Default configuration
+ */
+
+#define DEF_PHOTO_GAMMA "1"
+#define DEF_PHOTO_HEIGHT "0"
+#define DEF_PHOTO_PALETTE ""
+#define DEF_PHOTO_WIDTH "0"
+
+/*
+ * Information used for parsing configuration specifications:
+ */
+
+static const Tk_ConfigSpec configSpecs[] = {
+ {TK_CONFIG_STRING, "-file", NULL, NULL,
+ NULL, Tk_Offset(PhotoMaster, fileString), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_DOUBLE, "-gamma", NULL, NULL,
+ DEF_PHOTO_GAMMA, Tk_Offset(PhotoMaster, gamma), 0, NULL},
+ {TK_CONFIG_INT, "-height", NULL, NULL,
+ DEF_PHOTO_HEIGHT, Tk_Offset(PhotoMaster, userHeight), 0, NULL},
+ {TK_CONFIG_UID, "-palette", NULL, NULL,
+ DEF_PHOTO_PALETTE, Tk_Offset(PhotoMaster, palette), 0, NULL},
+ {TK_CONFIG_INT, "-width", NULL, NULL,
+ DEF_PHOTO_WIDTH, Tk_Offset(PhotoMaster, userWidth), 0, NULL},
+ {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}
+};
+
+/*
+ * Forward declarations
+ */
+
+static void PhotoFormatThreadExitProc(ClientData clientData);
+static int ImgPhotoCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int ParseSubcommandOptions(
+ struct SubcommandOptions *optPtr,
+ Tcl_Interp *interp, int allowedOptions,
+ int *indexPtr, int objc, Tcl_Obj *const objv[]);
+static void ImgPhotoCmdDeletedProc(ClientData clientData);
+static int ImgPhotoConfigureMaster(Tcl_Interp *interp,
+ PhotoMaster *masterPtr, int objc,
+ Tcl_Obj *const objv[], int flags);
+static int ToggleComplexAlphaIfNeeded(PhotoMaster *mPtr);
+static int ImgPhotoSetSize(PhotoMaster *masterPtr, int width,
+ int height);
+static int ImgStringWrite(Tcl_Interp *interp,
+ Tcl_Obj *formatString,
+ Tk_PhotoImageBlock *blockPtr);
+static char * ImgGetPhoto(PhotoMaster *masterPtr,
+ Tk_PhotoImageBlock *blockPtr,
+ struct SubcommandOptions *optPtr);
+static int MatchFileFormat(Tcl_Interp *interp, Tcl_Channel chan,
+ const char *fileName, Tcl_Obj *formatString,
+ Tk_PhotoImageFormat **imageFormatPtr,
+ int *widthPtr, int *heightPtr, int *oldformat);
+static int MatchStringFormat(Tcl_Interp *interp, Tcl_Obj *data,
+ Tcl_Obj *formatString,
+ Tk_PhotoImageFormat **imageFormatPtr,
+ int *widthPtr, int *heightPtr, int *oldformat);
+static const char * GetExtension(const char *path);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PhotoFormatThreadExitProc --
+ *
+ * Clean up the registered list of photo formats.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The thread's linked lists of photo image formats is deleted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+PhotoFormatThreadExitProc(
+ ClientData clientData) /* not used */
+{
+ Tk_PhotoImageFormat *freePtr;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ while (tsdPtr->oldFormatList != NULL) {
+ freePtr = tsdPtr->oldFormatList;
+ tsdPtr->oldFormatList = tsdPtr->oldFormatList->nextPtr;
+ ckfree(freePtr);
+ }
+ while (tsdPtr->formatList != NULL) {
+ freePtr = tsdPtr->formatList;
+ tsdPtr->formatList = tsdPtr->formatList->nextPtr;
+ ckfree((char *)freePtr->name);
+ ckfree(freePtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_CreateOldPhotoImageFormat, Tk_CreatePhotoImageFormat --
+ *
+ * This function is invoked by an image file handler to register a new
+ * photo image format and the functions that handle the new format. The
+ * function is typically invoked during Tcl_AppInit.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The new image file format is entered into a table used in the photo
+ * image "read" and "write" subcommands.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_CreateOldPhotoImageFormat(
+ const Tk_PhotoImageFormat *formatPtr)
+ /* Structure describing the format. All of the
+ * fields except "nextPtr" must be filled in
+ * by caller. */
+{
+ Tk_PhotoImageFormat *copyPtr;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (!tsdPtr->initialized) {
+ tsdPtr->initialized = 1;
+ Tcl_CreateThreadExitHandler(PhotoFormatThreadExitProc, NULL);
+ }
+ copyPtr = ckalloc(sizeof(Tk_PhotoImageFormat));
+ *copyPtr = *formatPtr;
+ copyPtr->nextPtr = tsdPtr->oldFormatList;
+ tsdPtr->oldFormatList = copyPtr;
+}
+
+void
+Tk_CreatePhotoImageFormat(
+ const Tk_PhotoImageFormat *formatPtr)
+ /* Structure describing the format. All of the
+ * fields except "nextPtr" must be filled in
+ * by caller. */
+{
+ Tk_PhotoImageFormat *copyPtr;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (!tsdPtr->initialized) {
+ tsdPtr->initialized = 1;
+ Tcl_CreateThreadExitHandler(PhotoFormatThreadExitProc, NULL);
+ }
+ copyPtr = ckalloc(sizeof(Tk_PhotoImageFormat));
+ *copyPtr = *formatPtr;
+ if (isupper((unsigned char) *formatPtr->name)) {
+ copyPtr->nextPtr = tsdPtr->oldFormatList;
+ tsdPtr->oldFormatList = copyPtr;
+ } else {
+ /* for compatibility with aMSN: make a copy of formatPtr->name */
+ char *name = ckalloc(strlen(formatPtr->name) + 1);
+ strcpy(name, formatPtr->name);
+ copyPtr->name = name;
+ copyPtr->nextPtr = tsdPtr->formatList;
+ tsdPtr->formatList = copyPtr;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImgPhotoCreate --
+ *
+ * This function is called by the Tk image code to create a new photo
+ * image.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * The data structure for a new photo image is allocated and initialized.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ImgPhotoCreate(
+ Tcl_Interp *interp, /* Interpreter for application containing
+ * image. */
+ const char *name, /* Name to use for image. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[], /* Argument objects for options (doesn't
+ * include image name or type). */
+ const Tk_ImageType *typePtr,/* Pointer to our type record (not used). */
+ Tk_ImageMaster master, /* Token for image, to be used by us in later
+ * callbacks. */
+ ClientData *clientDataPtr) /* Store manager's token for image here; it
+ * will be returned in later callbacks. */
+{
+ PhotoMaster *masterPtr;
+
+ /*
+ * Allocate and initialize the photo image master record.
+ */
+
+ masterPtr = ckalloc(sizeof(PhotoMaster));
+ memset(masterPtr, 0, sizeof(PhotoMaster));
+ masterPtr->tkMaster = master;
+ masterPtr->interp = interp;
+ masterPtr->imageCmd = Tcl_CreateObjCommand(interp, name, ImgPhotoCmd,
+ masterPtr, ImgPhotoCmdDeletedProc);
+ masterPtr->palette = NULL;
+ masterPtr->pix32 = NULL;
+ masterPtr->instancePtr = NULL;
+ masterPtr->validRegion = TkCreateRegion();
+
+ /*
+ * Process configuration options given in the image create command.
+ */
+
+ if (ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, 0) != TCL_OK) {
+ ImgPhotoDelete(masterPtr);
+ return TCL_ERROR;
+ }
+
+ *clientDataPtr = masterPtr;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImgPhotoCmd --
+ *
+ * This function is invoked to process the Tcl command that corresponds
+ * to a photo image. See the user documentation for details on what it
+ * does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ImgPhotoCmd(
+ ClientData clientData, /* Information about photo master. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ static const char *const photoOptions[] = {
+ "blank", "cget", "configure", "copy", "data", "get", "put",
+ "read", "redither", "transparency", "write", NULL
+ };
+ enum PhotoOptions {
+ PHOTO_BLANK, PHOTO_CGET, PHOTO_CONFIGURE, PHOTO_COPY, PHOTO_DATA,
+ PHOTO_GET, PHOTO_PUT, PHOTO_READ, PHOTO_REDITHER, PHOTO_TRANS,
+ PHOTO_WRITE
+ };
+
+ PhotoMaster *masterPtr = clientData;
+ int result, index, x, y, width, height, dataWidth, dataHeight, listObjc;
+ struct SubcommandOptions options;
+ Tcl_Obj **listObjv, **srcObjv;
+ unsigned char *pixelPtr;
+ Tk_PhotoImageBlock block;
+ Tk_Window tkwin;
+ Tk_PhotoImageFormat *imageFormat;
+ size_t length;
+ int imageWidth, imageHeight, matched, oldformat = 0;
+ Tcl_Channel chan;
+ Tk_PhotoHandle srcHandle;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObj(interp, objv[1], photoOptions, "option", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch ((enum PhotoOptions) index) {
+ case PHOTO_BLANK:
+ /*
+ * photo blank command - just call Tk_PhotoBlank.
+ */
+
+ if (objc == 2) {
+ Tk_PhotoBlank(masterPtr);
+ return TCL_OK;
+ } else {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ return TCL_ERROR;
+ }
+
+ case PHOTO_CGET: {
+ const char *arg;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option");
+ return TCL_ERROR;
+ }
+ arg = Tcl_GetString(objv[2]);
+ length = objv[2]->length;
+ if (strncmp(arg,"-data", length) == 0) {
+ if (masterPtr->dataString) {
+ Tcl_SetObjResult(interp, masterPtr->dataString);
+ }
+ } else if (strncmp(arg,"-format", length) == 0) {
+ if (masterPtr->format) {
+ Tcl_SetObjResult(interp, masterPtr->format);
+ }
+ } else {
+ Tk_ConfigureValue(interp, Tk_MainWindow(interp), configSpecs,
+ (char *) masterPtr, Tcl_GetString(objv[2]), 0);
+ }
+ return TCL_OK;
+ }
+
+ case PHOTO_CONFIGURE:
+ /*
+ * photo configure command - handle this in the standard way.
+ */
+
+ if (objc == 2) {
+ Tcl_Obj *obj, *subobj;
+
+ result = Tk_ConfigureInfo(interp, Tk_MainWindow(interp),
+ configSpecs, (char *) masterPtr, NULL, 0);
+ if (result != TCL_OK) {
+ return result;
+ }
+ obj = Tcl_NewObj();
+ subobj = Tcl_NewStringObj("-data {} {} {}", 14);
+ if (masterPtr->dataString) {
+ Tcl_ListObjAppendElement(NULL, subobj, masterPtr->dataString);
+ } else {
+ Tcl_AppendStringsToObj(subobj, " {}", NULL);
+ }
+ Tcl_ListObjAppendElement(interp, obj, subobj);
+ subobj = Tcl_NewStringObj("-format {} {} {}", 16);
+ if (masterPtr->format) {
+ Tcl_ListObjAppendElement(NULL, subobj, masterPtr->format);
+ } else {
+ Tcl_AppendStringsToObj(subobj, " {}", NULL);
+ }
+ Tcl_ListObjAppendElement(interp, obj, subobj);
+ Tcl_ListObjAppendList(interp, obj, Tcl_GetObjResult(interp));
+ Tcl_SetObjResult(interp, obj);
+ return TCL_OK;
+
+ } else if (objc == 3) {
+ const char *arg = Tcl_GetString(objv[2]);
+
+ length = objv[2]->length;
+ if (length > 1 && !strncmp(arg, "-data", length)) {
+ Tcl_AppendResult(interp, "-data {} {} {}", NULL);
+ if (masterPtr->dataString) {
+ /*
+ * TODO: Modifying result is bad!
+ */
+
+ Tcl_ListObjAppendElement(NULL, Tcl_GetObjResult(interp),
+ masterPtr->dataString);
+ } else {
+ Tcl_AppendResult(interp, " {}", NULL);
+ }
+ return TCL_OK;
+ } else if (length > 1 &&
+ !strncmp(arg, "-format", length)) {
+ Tcl_AppendResult(interp, "-format {} {} {}", NULL);
+ if (masterPtr->format) {
+ /*
+ * TODO: Modifying result is bad!
+ */
+
+ Tcl_ListObjAppendElement(NULL, Tcl_GetObjResult(interp),
+ masterPtr->format);
+ } else {
+ Tcl_AppendResult(interp, " {}", NULL);
+ }
+ return TCL_OK;
+ } else {
+ return Tk_ConfigureInfo(interp, Tk_MainWindow(interp),
+ configSpecs, (char *) masterPtr, arg, 0);
+ }
+ } else {
+ return ImgPhotoConfigureMaster(interp, masterPtr, objc-2, objv+2,
+ TK_CONFIG_ARGV_ONLY);
+ }
+
+ case PHOTO_COPY:
+ /*
+ * photo copy command - first parse options.
+ */
+
+ index = 2;
+ memset(&options, 0, sizeof(options));
+ options.zoomX = options.zoomY = 1;
+ options.subsampleX = options.subsampleY = 1;
+ options.name = NULL;
+ options.compositingRule = TK_PHOTO_COMPOSITE_OVERLAY;
+ if (ParseSubcommandOptions(&options, interp,
+ OPT_FROM | OPT_TO | OPT_ZOOM | OPT_SUBSAMPLE | OPT_SHRINK |
+ OPT_COMPOSITE, &index, objc, objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (options.name == NULL || index < objc) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "source-image ?-compositingrule rule? ?-from x1 y1 x2 y2? ?-to x1 y1 x2 y2? ?-zoom x y? ?-subsample x y?");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Look for the source image and get a pointer to its image data.
+ * Check the values given for the -from option.
+ */
+
+ srcHandle = Tk_FindPhoto(interp, Tcl_GetString(options.name));
+ if (srcHandle == NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "image \"%s\" doesn't exist or is not a photo image",
+ Tcl_GetString(options.name)));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "PHOTO",
+ Tcl_GetString(options.name), NULL);
+ return TCL_ERROR;
+ }
+ Tk_PhotoGetImage(srcHandle, &block);
+ if ((options.fromX2 > block.width) || (options.fromY2 > block.height)
+ || (options.fromX2 > block.width)
+ || (options.fromY2 > block.height)) {
+ if (options.background) {
+ Tk_FreeColor(options.background);
+ }
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "coordinates for -from option extend outside source image",
+ -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "BAD_FROM", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Hack to pass through the message that the place we're coming from
+ * has a simple alpha channel.
+ */
+
+ if (!(((PhotoMaster *) srcHandle)->flags & COMPLEX_ALPHA)) {
+ options.compositingRule |= SOURCE_IS_SIMPLE_ALPHA_PHOTO;
+ }
+
+ /*
+ * Fill in default values for unspecified parameters.
+ */
+
+ if (!(options.options & OPT_FROM) || (options.fromX2 < 0)) {
+ options.fromX2 = block.width;
+ options.fromY2 = block.height;
+ }
+ if (!(options.options & OPT_TO) || (options.toX2 < 0)) {
+ width = options.fromX2 - options.fromX;
+ if (options.subsampleX > 0) {
+ width = (width + options.subsampleX - 1) / options.subsampleX;
+ } else if (options.subsampleX == 0) {
+ width = 0;
+ } else {
+ width = (width - options.subsampleX - 1) / -options.subsampleX;
+ }
+ options.toX2 = options.toX + width * options.zoomX;
+
+ height = options.fromY2 - options.fromY;
+ if (options.subsampleY > 0) {
+ height = (height + options.subsampleY - 1)
+ / options.subsampleY;
+ } else if (options.subsampleY == 0) {
+ height = 0;
+ } else {
+ height = (height - options.subsampleY - 1)
+ / -options.subsampleY;
+ }
+ options.toY2 = options.toY + height * options.zoomY;
+ }
+
+ /*
+ * Copy the image data over using Tk_PhotoPutZoomedBlock.
+ */
+
+ block.pixelPtr += options.fromX * block.pixelSize
+ + options.fromY * block.pitch;
+ block.width = options.fromX2 - options.fromX;
+ block.height = options.fromY2 - options.fromY;
+ result = Tk_PhotoPutZoomedBlock(interp, (Tk_PhotoHandle) masterPtr,
+ &block, options.toX, options.toY, options.toX2 - options.toX,
+ options.toY2 - options.toY, options.zoomX, options.zoomY,
+ options.subsampleX, options.subsampleY,
+ options.compositingRule);
+
+ /*
+ * Set the destination image size if the -shrink option was specified.
+ * This has to be done _after_ copying the data. Otherwise, if source
+ * and destination are the same image, block.pixelPtr would point to
+ * an invalid memory block (bug [5239fd749b]).
+ */
+
+ if (options.options & OPT_SHRINK) {
+ if (ImgPhotoSetSize(masterPtr, options.toX2,
+ options.toY2) != TCL_OK) {
+ if (options.background) {
+ Tk_FreeColor(options.background);
+ }
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1));
+ Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL);
+ return TCL_ERROR;
+ }
+ }
+ Tk_ImageChanged(masterPtr->tkMaster, 0, 0, 0, 0,
+ masterPtr->width, masterPtr->height);
+ if (options.background) {
+ Tk_FreeColor(options.background);
+ }
+ return result;
+
+ case PHOTO_DATA: {
+ char *data;
+
+ /*
+ * photo data command - first parse and check any options given.
+ */
+
+ Tk_ImageStringWriteProc *stringWriteProc = NULL;
+
+ index = 2;
+ memset(&options, 0, sizeof(options));
+ options.name = NULL;
+ options.format = NULL;
+ options.fromX = 0;
+ options.fromY = 0;
+ if (ParseSubcommandOptions(&options, interp,
+ OPT_FORMAT | OPT_FROM | OPT_GRAYSCALE | OPT_BACKGROUND,
+ &index, objc, objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((options.name != NULL) || (index < objc)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?-option value ...?");
+ return TCL_ERROR;
+ }
+ if ((options.fromX > masterPtr->width)
+ || (options.fromY > masterPtr->height)
+ || (options.fromX2 > masterPtr->width)
+ || (options.fromY2 > masterPtr->height)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "coordinates for -from option extend outside image", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "BAD_FROM", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Fill in default values for unspecified parameters.
+ */
+
+ if (!(options.options & OPT_FROM) || (options.fromX2 < 0)) {
+ options.fromX2 = masterPtr->width;
+ options.fromY2 = masterPtr->height;
+ }
+
+ /*
+ * Search for an appropriate image string format handler.
+ */
+
+ if (options.options & OPT_FORMAT) {
+ matched = 0;
+ for (imageFormat = tsdPtr->formatList; imageFormat != NULL;
+ imageFormat = imageFormat->nextPtr) {
+ if ((strncasecmp(Tcl_GetString(options.format),
+ imageFormat->name, strlen(imageFormat->name)) == 0)) {
+ matched = 1;
+ if (imageFormat->stringWriteProc != NULL) {
+ stringWriteProc = imageFormat->stringWriteProc;
+ break;
+ }
+ }
+ }
+ if (stringWriteProc == NULL) {
+ oldformat = 1;
+ for (imageFormat = tsdPtr->oldFormatList; imageFormat != NULL;
+ imageFormat = imageFormat->nextPtr) {
+ if ((strncasecmp(Tcl_GetString(options.format),
+ imageFormat->name,
+ strlen(imageFormat->name)) == 0)) {
+ matched = 1;
+ if (imageFormat->stringWriteProc != NULL) {
+ stringWriteProc = imageFormat->stringWriteProc;
+ break;
+ }
+ }
+ }
+ }
+ if (stringWriteProc == NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "image string format \"%s\" is %s",
+ Tcl_GetString(options.format),
+ (matched ? "not supported" : "unknown")));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "PHOTO_FORMAT",
+ Tcl_GetString(options.format), NULL);
+ return TCL_ERROR;
+ }
+ } else {
+ stringWriteProc = ImgStringWrite;
+ }
+
+ /*
+ * Call the handler's string write function to write out the image.
+ */
+
+ data = ImgGetPhoto(masterPtr, &block, &options);
+
+ if (oldformat) {
+ Tcl_DString buffer;
+ typedef int (*OldStringWriteProc)(Tcl_Interp *interp,
+ Tcl_DString *dataPtr, const char *formatString,
+ Tk_PhotoImageBlock *blockPtr);
+
+ Tcl_DStringInit(&buffer);
+ result = ((OldStringWriteProc) stringWriteProc)(interp, &buffer,
+ Tcl_GetString(options.format), &block);
+ if (result == TCL_OK) {
+ Tcl_DStringResult(interp, &buffer);
+ } else {
+ Tcl_DStringFree(&buffer);
+ }
+ } else {
+ typedef int (*NewStringWriteProc)(Tcl_Interp *interp,
+ Tcl_Obj *formatString, Tk_PhotoImageBlock *blockPtr,
+ void *dummy);
+
+ result = ((NewStringWriteProc) stringWriteProc)(interp,
+ options.format, &block, NULL);
+ }
+ if (options.background) {
+ Tk_FreeColor(options.background);
+ }
+ if (data) {
+ ckfree(data);
+ }
+ return result;
+ }
+
+ case PHOTO_GET: {
+ /*
+ * photo get command - first parse and check parameters.
+ */
+
+ Tcl_Obj *channels[3];
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "x y");
+ return TCL_ERROR;
+ }
+ if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ if ((x < 0) || (x >= masterPtr->width)
+ || (y < 0) || (y >= masterPtr->height)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "%s get: coordinates out of range",
+ Tcl_GetString(objv[0])));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "COORDINATES",
+ NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Extract the value of the desired pixel and format it as a string.
+ */
+
+ pixelPtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4;
+ channels[0] = Tcl_NewIntObj(pixelPtr[0]);
+ channels[1] = Tcl_NewIntObj(pixelPtr[1]);
+ channels[2] = Tcl_NewIntObj(pixelPtr[2]);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(3, channels));
+ return TCL_OK;
+ }
+
+ case PHOTO_PUT:
+ /*
+ * photo put command - first parse the options and colors specified.
+ */
+
+ index = 2;
+ memset(&options, 0, sizeof(options));
+ options.name = NULL;
+ if (ParseSubcommandOptions(&options, interp, OPT_TO|OPT_FORMAT,
+ &index, objc, objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((options.name == NULL) || (index < objc)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "data ?-option value ...?");
+ return TCL_ERROR;
+ }
+
+ if (MatchStringFormat(interp, options.name ? objv[2]:NULL,
+ options.format, &imageFormat, &imageWidth,
+ &imageHeight, &oldformat) == TCL_OK) {
+ Tcl_Obj *format, *data;
+
+ if (!(options.options & OPT_TO) || (options.toX2 < 0)) {
+ options.toX2 = options.toX + imageWidth;
+ options.toY2 = options.toY + imageHeight;
+ }
+ if (imageWidth > options.toX2 - options.toX) {
+ imageWidth = options.toX2 - options.toX;
+ }
+ if (imageHeight > options.toY2 - options.toY) {
+ imageHeight = options.toY2 - options.toY;
+ }
+ format = options.format;
+ data = objv[2];
+ if (oldformat) {
+ if (format) {
+ format = (Tcl_Obj *) Tcl_GetString(format);
+ }
+ data = (Tcl_Obj *) Tcl_GetString(data);
+ }
+ if (imageFormat->stringReadProc(interp, data, format,
+ (Tk_PhotoHandle) masterPtr, options.toX, options.toY,
+ imageWidth, imageHeight, 0, 0) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ masterPtr->flags |= IMAGE_CHANGED;
+ return TCL_OK;
+ }
+ if (options.options & OPT_FORMAT) {
+ return TCL_ERROR;
+ }
+ Tcl_ResetResult(interp);
+ if (Tcl_ListObjGetElements(interp, options.name,
+ &dataHeight, &srcObjv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ tkwin = Tk_MainWindow(interp);
+ block.pixelPtr = NULL;
+ dataWidth = 0;
+ pixelPtr = NULL;
+ for (y = 0; y < dataHeight; ++y) {
+ if (Tcl_ListObjGetElements(interp, srcObjv[y],
+ &listObjc, &listObjv) != TCL_OK) {
+ break;
+ }
+
+ if (y == 0) {
+ if (listObjc == 0) {
+ /*
+ * Lines must be non-empty...
+ */
+
+ break;
+ }
+ dataWidth = listObjc;
+ /*
+ * Memory allocation overflow protection.
+ * May not be able to trigger/ demo / test this.
+ */
+
+ if (dataWidth > (int)((UINT_MAX/3) / dataHeight)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "photo image dimensions exceed Tcl memory limits", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO",
+ "OVERFLOW", NULL);
+ break;
+ }
+
+ pixelPtr = ckalloc(dataWidth * dataHeight * 3);
+ block.pixelPtr = pixelPtr;
+ } else if (listObjc != dataWidth) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "all elements of color list must have the same"
+ " number of elements", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO",
+ "NON_RECTANGULAR", NULL);
+ break;
+ }
+
+ for (x = 0; x < dataWidth; ++x) {
+ const char *colorString = Tcl_GetString(listObjv[x]);
+ XColor color;
+ int tmpr, tmpg, tmpb;
+
+ /*
+ * We do not use Tk_GetColorFromObj() because we absolutely do
+ * not want to invoke the fallback code.
+ */
+
+ if (colorString[0] == '#') {
+ if (isxdigit(UCHAR(colorString[1])) &&
+ isxdigit(UCHAR(colorString[2])) &&
+ isxdigit(UCHAR(colorString[3]))) {
+ if (colorString[4] == '\0') {
+ /* Got #rgb */
+ sscanf(colorString+1, "%1x%1x%1x",
+ &tmpr, &tmpg, &tmpb);
+ *pixelPtr++ = tmpr * 0x11;
+ *pixelPtr++ = tmpg * 0x11;
+ *pixelPtr++ = tmpb * 0x11;
+ continue;
+ } else if (isxdigit(UCHAR(colorString[4])) &&
+ isxdigit(UCHAR(colorString[5])) &&
+ isxdigit(UCHAR(colorString[6])) &&
+ colorString[7] == '\0') {
+ /* Got #rrggbb */
+ sscanf(colorString+1, "%2x%2x%2x",
+ &tmpr, &tmpg, &tmpb);
+ *pixelPtr++ = tmpr;
+ *pixelPtr++ = tmpg;
+ *pixelPtr++ = tmpb;
+ continue;
+ }
+ }
+ }
+
+ if (!TkParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin),
+ colorString, &color)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't parse color \"%s\"", colorString));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "COLOR", NULL);
+ break;
+ }
+ *pixelPtr++ = color.red >> 8;
+ *pixelPtr++ = color.green >> 8;
+ *pixelPtr++ = color.blue >> 8;
+ }
+ if (x < dataWidth) {
+ break;
+ }
+ }
+ if (y < dataHeight || dataHeight == 0 || dataWidth == 0) {
+ if (block.pixelPtr != NULL) {
+ ckfree(block.pixelPtr);
+ }
+ if (y < dataHeight) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+ }
+
+ /*
+ * Fill in default values for the -to option, then copy the block in
+ * using Tk_PhotoPutBlock.
+ */
+
+ if (!(options.options & OPT_TO) || (options.toX2 < 0)) {
+ options.toX2 = options.toX + dataWidth;
+ options.toY2 = options.toY + dataHeight;
+ }
+ block.width = dataWidth;
+ block.height = dataHeight;
+ block.pitch = dataWidth * 3;
+ block.pixelSize = 3;
+ block.offset[0] = 0;
+ block.offset[1] = 1;
+ block.offset[2] = 2;
+ block.offset[3] = 0;
+ result = Tk_PhotoPutBlock(interp, masterPtr, &block,
+ options.toX, options.toY, options.toX2 - options.toX,
+ options.toY2 - options.toY,
+ TK_PHOTO_COMPOSITE_SET);
+ ckfree(block.pixelPtr);
+ return result;
+
+ case PHOTO_READ: {
+ Tcl_Obj *format;
+
+ /*
+ * photo read command - first parse the options specified.
+ */
+
+ index = 2;
+ memset(&options, 0, sizeof(options));
+ options.name = NULL;
+ options.format = NULL;
+ if (ParseSubcommandOptions(&options, interp,
+ OPT_FORMAT | OPT_FROM | OPT_TO | OPT_SHRINK,
+ &index, objc, objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((options.name == NULL) || (index < objc)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "fileName ?-option value ...?");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Prevent file system access in safe interpreters.
+ */
+
+ if (Tcl_IsSafe(interp)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "can't get image from a file in a safe interpreter", -1));
+ Tcl_SetErrorCode(interp, "TK", "SAFE", "PHOTO_FILE", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Open the image file and look for a handler for it.
+ */
+
+ chan = Tcl_OpenFileChannel(interp,
+ Tcl_GetString(options.name), "r", 0);
+ if (chan == NULL) {
+ return TCL_ERROR;
+ }
+ if (Tcl_SetChannelOption(interp, chan, "-translation", "binary")
+ != TCL_OK) {
+ Tcl_Close(NULL, chan);
+ return TCL_ERROR;
+ }
+ if (Tcl_SetChannelOption(interp, chan, "-encoding", "binary")
+ != TCL_OK) {
+ Tcl_Close(NULL, chan);
+ return TCL_ERROR;
+ }
+
+ if (MatchFileFormat(interp, chan,
+ Tcl_GetString(options.name), options.format, &imageFormat,
+ &imageWidth, &imageHeight, &oldformat) != TCL_OK) {
+ Tcl_Close(NULL, chan);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Check the values given for the -from option.
+ */
+
+ if ((options.fromX > imageWidth) || (options.fromY > imageHeight)
+ || (options.fromX2 > imageWidth)
+ || (options.fromY2 > imageHeight)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "coordinates for -from option extend outside source image",
+ -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "BAD_FROM", NULL);
+ Tcl_Close(NULL, chan);
+ return TCL_ERROR;
+ }
+ if (!(options.options & OPT_FROM) || (options.fromX2 < 0)) {
+ width = imageWidth - options.fromX;
+ height = imageHeight - options.fromY;
+ } else {
+ width = options.fromX2 - options.fromX;
+ height = options.fromY2 - options.fromY;
+ }
+
+ /*
+ * If the -shrink option was specified, set the size of the image.
+ */
+
+ if (options.options & OPT_SHRINK) {
+ if (ImgPhotoSetSize(masterPtr, options.toX + width,
+ options.toY + height) != TCL_OK) {
+ Tcl_ResetResult(interp);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1));
+ Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * Call the handler's file read function to read the data into the
+ * image.
+ */
+
+ format = options.format;
+ if (oldformat && format) {
+ format = (Tcl_Obj *) Tcl_GetString(format);
+ }
+ result = imageFormat->fileReadProc(interp, chan,
+ Tcl_GetString(options.name),
+ format, (Tk_PhotoHandle) masterPtr, options.toX,
+ options.toY, width, height, options.fromX, options.fromY);
+ if (chan != NULL) {
+ Tcl_Close(NULL, chan);
+ }
+ return result;
+ }
+
+ case PHOTO_REDITHER:
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Call Dither if any part of the image is not correctly dithered at
+ * present.
+ */
+
+ x = masterPtr->ditherX;
+ y = masterPtr->ditherY;
+ if (masterPtr->ditherX != 0) {
+ Tk_DitherPhoto((Tk_PhotoHandle) masterPtr, x, y,
+ masterPtr->width - x, 1);
+ }
+ if (masterPtr->ditherY < masterPtr->height) {
+ x = 0;
+ Tk_DitherPhoto((Tk_PhotoHandle)masterPtr, 0,
+ masterPtr->ditherY, masterPtr->width,
+ masterPtr->height - masterPtr->ditherY);
+ }
+
+ if (y < masterPtr->height) {
+ /*
+ * Tell the core image code that part of the image has changed.
+ */
+
+ Tk_ImageChanged(masterPtr->tkMaster, x, y,
+ (masterPtr->width - x), (masterPtr->height - y),
+ masterPtr->width, masterPtr->height);
+ }
+ return TCL_OK;
+
+ case PHOTO_TRANS: {
+ static const char *const photoTransOptions[] = {
+ "get", "set", NULL
+ };
+ enum transOptions {
+ PHOTO_TRANS_GET, PHOTO_TRANS_SET
+ };
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[2], photoTransOptions, "option",
+ 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch ((enum transOptions) index) {
+ case PHOTO_TRANS_GET: {
+ XRectangle testBox;
+ TkRegion testRegion;
+
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 3, objv, "x y");
+ return TCL_ERROR;
+ }
+ if ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ if ((x < 0) || (x >= masterPtr->width)
+ || (y < 0) || (y >= masterPtr->height)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "%s transparency get: coordinates out of range",
+ Tcl_GetString(objv[0])));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "COORDINATES",
+ NULL);
+ return TCL_ERROR;
+ }
+
+ testBox.x = x;
+ testBox.y = y;
+ testBox.width = 1;
+ testBox.height = 1;
+ /* What a way to do a test! */
+ testRegion = TkCreateRegion();
+ TkUnionRectWithRegion(&testBox, testRegion, testRegion);
+ TkIntersectRegion(testRegion, masterPtr->validRegion, testRegion);
+ TkClipBox(testRegion, &testBox);
+ TkDestroyRegion(testRegion);
+
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
+ testBox.width==0 && testBox.height==0));
+ return TCL_OK;
+ }
+
+ case PHOTO_TRANS_SET: {
+ int transFlag;
+ XRectangle setBox;
+
+ if (objc != 6) {
+ Tcl_WrongNumArgs(interp, 3, objv, "x y boolean");
+ return TCL_ERROR;
+ }
+ if ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)
+ || (Tcl_GetBooleanFromObj(interp, objv[5],
+ &transFlag) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ if ((x < 0) || (x >= masterPtr->width)
+ || (y < 0) || (y >= masterPtr->height)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "%s transparency set: coordinates out of range",
+ Tcl_GetString(objv[0])));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "COORDINATES",
+ NULL);
+ return TCL_ERROR;
+ }
+
+ setBox.x = x;
+ setBox.y = y;
+ setBox.width = 1;
+ setBox.height = 1;
+ pixelPtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4;
+
+ if (transFlag) {
+ /*
+ * Make pixel transparent.
+ */
+
+ TkRegion clearRegion = TkCreateRegion();
+
+ TkUnionRectWithRegion(&setBox, clearRegion, clearRegion);
+ TkSubtractRegion(masterPtr->validRegion, clearRegion,
+ masterPtr->validRegion);
+ TkDestroyRegion(clearRegion);
+
+ /*
+ * Set the alpha value correctly.
+ */
+
+ pixelPtr[3] = 0;
+ } else {
+ /*
+ * Make pixel opaque.
+ */
+
+ TkUnionRectWithRegion(&setBox, masterPtr->validRegion,
+ masterPtr->validRegion);
+ pixelPtr[3] = 255;
+ }
+
+ /*
+ * Inform the generic image code that the image
+ * has (potentially) changed.
+ */
+
+ Tk_ImageChanged(masterPtr->tkMaster, x, y, 1, 1,
+ masterPtr->width, masterPtr->height);
+ masterPtr->flags &= ~IMAGE_CHANGED;
+ return TCL_OK;
+ }
+
+ }
+ Tcl_Panic("unexpected fallthrough");
+ }
+
+ case PHOTO_WRITE: {
+ char *data;
+ const char *fmtString;
+ Tcl_Obj *format;
+ int usedExt;
+
+ /*
+ * Prevent file system access in safe interpreters.
+ */
+
+ if (Tcl_IsSafe(interp)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "can't write image to a file in a safe interpreter", -1));
+ Tcl_SetErrorCode(interp, "TK", "SAFE", "PHOTO_FILE", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * photo write command - first parse and check any options given.
+ */
+
+ index = 2;
+ memset(&options, 0, sizeof(options));
+ options.name = NULL;
+ options.format = NULL;
+ if (ParseSubcommandOptions(&options, interp,
+ OPT_FORMAT | OPT_FROM | OPT_GRAYSCALE | OPT_BACKGROUND,
+ &index, objc, objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((options.name == NULL) || (index < objc)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "fileName ?-option value ...?");
+ return TCL_ERROR;
+ }
+ if ((options.fromX > masterPtr->width)
+ || (options.fromY > masterPtr->height)
+ || (options.fromX2 > masterPtr->width)
+ || (options.fromY2 > masterPtr->height)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "coordinates for -from option extend outside image", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "BAD_FROM", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Fill in default values for unspecified parameters. Note that a
+ * missing -format flag results in us having a guess from the file
+ * extension. [Bug 2983824]
+ */
+
+ if (!(options.options & OPT_FROM) || (options.fromX2 < 0)) {
+ options.fromX2 = masterPtr->width;
+ options.fromY2 = masterPtr->height;
+ }
+ if (options.format == NULL) {
+ fmtString = GetExtension(Tcl_GetString(options.name));
+ usedExt = (fmtString != NULL);
+ } else {
+ fmtString = Tcl_GetString(options.format);
+ usedExt = 0;
+ }
+
+ /*
+ * Search for an appropriate image file format handler, and give an
+ * error if none is found.
+ */
+
+ matched = 0;
+ redoFormatLookup:
+ for (imageFormat = tsdPtr->formatList; imageFormat != NULL;
+ imageFormat = imageFormat->nextPtr) {
+ if ((fmtString == NULL)
+ || (strncasecmp(fmtString, imageFormat->name,
+ strlen(imageFormat->name)) == 0)) {
+ matched = 1;
+ if (imageFormat->fileWriteProc != NULL) {
+ break;
+ }
+ }
+ }
+ if (imageFormat == NULL) {
+ oldformat = 1;
+ for (imageFormat = tsdPtr->oldFormatList; imageFormat != NULL;
+ imageFormat = imageFormat->nextPtr) {
+ if ((fmtString == NULL)
+ || (strncasecmp(fmtString, imageFormat->name,
+ strlen(imageFormat->name)) == 0)) {
+ matched = 1;
+ if (imageFormat->fileWriteProc != NULL) {
+ break;
+ }
+ }
+ }
+ }
+ if (usedExt && !matched) {
+ /*
+ * If we didn't find one and we're using file extensions as the
+ * basis for the guessing, go back and look again without
+ * prejudice. Supports old broken code.
+ */
+
+ usedExt = 0;
+ fmtString = NULL;
+ goto redoFormatLookup;
+ }
+ if (imageFormat == NULL) {
+ if (fmtString == NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "no available image file format has file writing"
+ " capability", -1));
+ } else if (!matched) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "image file format \"%s\" is unknown", fmtString));
+ } else {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "image file format \"%s\" has no file writing capability",
+ fmtString));
+ }
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "PHOTO_FORMAT",
+ fmtString, NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Call the handler's file write function to write out the image.
+ */
+
+ data = ImgGetPhoto(masterPtr, &block, &options);
+ format = options.format;
+ if (oldformat && format) {
+ format = (Tcl_Obj *) Tcl_GetString(options.format);
+ }
+ result = imageFormat->fileWriteProc(interp,
+ Tcl_GetString(options.name), format, &block);
+ if (options.background) {
+ Tk_FreeColor(options.background);
+ }
+ if (data) {
+ ckfree(data);
+ }
+ return result;
+ }
+
+ }
+ Tcl_Panic("unexpected fallthrough");
+ return TCL_ERROR; /* NOT REACHED */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetExtension --
+ *
+ * Return the extension part of a path, or NULL if there is no extension.
+ * The returned string will be a substring of the argument string, so
+ * should not be ckfree()d directly. No side effects.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static const char *
+GetExtension(
+ const char *path)
+{
+ char c;
+ const char *extension = NULL;
+
+ for (; (c=*path++) != '\0' ;) {
+ if (c == '.') {
+ extension = path;
+ }
+ }
+ if (extension != NULL && extension[0] == '\0') {
+ extension = NULL;
+ }
+ return extension;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ParseSubcommandOptions --
+ *
+ * This function is invoked to process one of the options which may be
+ * specified for the photo image subcommands, namely, -from, -to, -zoom,
+ * -subsample, -format, -shrink, and -compositingrule.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * Fields in *optPtr get filled in.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ParseSubcommandOptions(
+ struct SubcommandOptions *optPtr,
+ /* Information about the options specified and
+ * the values given is returned here. */
+ Tcl_Interp *interp, /* Interpreter to use for reporting errors. */
+ int allowedOptions, /* Indicates which options are valid for the
+ * current command. */
+ int *optIndexPtr, /* Points to a variable containing the current
+ * index in objv; this variable is updated by
+ * this function. */
+ int objc, /* Number of arguments in objv[]. */
+ Tcl_Obj *const objv[]) /* Arguments to be parsed. */
+{
+ static const char *const compositingRules[] = {
+ "overlay", "set", /* Note that these must match the
+ * TK_PHOTO_COMPOSITE_* constants. */
+ NULL
+ };
+ size_t length;
+ int index, c, bit, currentBit;
+ int values[4], numValues, maxValues, argIndex;
+ const char *option, *expandedOption, *needed;
+ const char *const *listPtr;
+ Tcl_Obj *msgObj;
+
+ for (index = *optIndexPtr; index < objc; *optIndexPtr = ++index) {
+ /*
+ * We can have one value specified without an option; it goes into
+ * optPtr->name.
+ */
+
+ expandedOption = option = Tcl_GetString(objv[index]);
+ length = objv[index]->length;
+ if (option[0] != '-') {
+ if (optPtr->name == NULL) {
+ optPtr->name = objv[index];
+ continue;
+ }
+ break;
+ }
+
+ /*
+ * Work out which option this is.
+ */
+
+ c = option[0];
+ bit = 0;
+ currentBit = 1;
+ for (listPtr = optionNames; *listPtr != NULL; ++listPtr) {
+ if ((c == *listPtr[0])
+ && (strncmp(option, *listPtr, length) == 0)) {
+ expandedOption = *listPtr;
+ if (bit != 0) {
+ goto unknownOrAmbiguousOption;
+ }
+ bit = currentBit;
+ }
+ currentBit <<= 1;
+ }
+
+ /*
+ * If this option is not recognized and allowed, put an error message
+ * in the interpreter and return.
+ */
+
+ if (!(allowedOptions & bit)) {
+ if (optPtr->name != NULL) {
+ goto unknownOrAmbiguousOption;
+ }
+ optPtr->name = objv[index];
+ continue;
+ }
+
+ /*
+ * For the -from, -to, -zoom and -subsample options, parse the values
+ * given. Report an error if too few or too many values are given.
+ */
+
+ if (bit == OPT_BACKGROUND) {
+ /*
+ * The -background option takes a single XColor value.
+ */
+
+ if (index + 1 >= objc) {
+ goto oneValueRequired;
+ }
+ *optIndexPtr = ++index;
+ optPtr->background = Tk_GetColor(interp, Tk_MainWindow(interp),
+ Tk_GetUid(Tcl_GetString(objv[index])));
+ if (!optPtr->background) {
+ return TCL_ERROR;
+ }
+ } else if (bit == OPT_FORMAT) {
+ /*
+ * The -format option takes a single string value. Note that
+ * parsing this is outside the scope of this function.
+ */
+
+ if (index + 1 >= objc) {
+ goto oneValueRequired;
+ }
+ *optIndexPtr = ++index;
+ optPtr->format = objv[index];
+ } else if (bit == OPT_COMPOSITE) {
+ /*
+ * The -compositingrule option takes a single value from a
+ * well-known set.
+ */
+
+ if (index + 1 >= objc) {
+ goto oneValueRequired;
+ }
+ index++;
+ if (Tcl_GetIndexFromObj(interp, objv[index], compositingRules,
+ "compositing rule", 0, &optPtr->compositingRule)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *optIndexPtr = index;
+ } else if ((bit != OPT_SHRINK) && (bit != OPT_GRAYSCALE)) {
+ const char *val;
+
+ maxValues = ((bit == OPT_FROM) || (bit == OPT_TO)) ? 4 : 2;
+ argIndex = index + 1;
+ for (numValues = 0; numValues < maxValues; ++numValues) {
+ if (argIndex >= objc) {
+ break;
+ }
+ val = Tcl_GetString(objv[argIndex]);
+ if ((argIndex < objc) && (isdigit(UCHAR(val[0]))
+ || ((val[0] == '-') && isdigit(UCHAR(val[1]))))) {
+ if (Tcl_GetInt(interp, val, &values[numValues])
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ } else {
+ break;
+ }
+ argIndex++;
+ }
+
+ if (numValues == 0) {
+ goto manyValuesRequired;
+ }
+ *optIndexPtr = (index += numValues);
+
+ /*
+ * Y values default to the corresponding X value if not specified.
+ */
+
+ if (numValues == 1) {
+ values[1] = values[0];
+ }
+ if (numValues == 3) {
+ values[3] = values[2];
+ }
+
+ /*
+ * Check the values given and put them in the appropriate field of
+ * the SubcommandOptions structure.
+ */
+
+ switch (bit) {
+ case OPT_FROM:
+ if ((values[0] < 0) || (values[1] < 0) || ((numValues > 2)
+ && ((values[2] < 0) || (values[3] < 0)))) {
+ needed = "non-negative";
+ goto numberOutOfRange;
+ }
+ if (numValues <= 2) {
+ optPtr->fromX = values[0];
+ optPtr->fromY = values[1];
+ optPtr->fromX2 = -1;
+ optPtr->fromY2 = -1;
+ } else {
+ optPtr->fromX = MIN(values[0], values[2]);
+ optPtr->fromY = MIN(values[1], values[3]);
+ optPtr->fromX2 = MAX(values[0], values[2]);
+ optPtr->fromY2 = MAX(values[1], values[3]);
+ }
+ break;
+ case OPT_SUBSAMPLE:
+ optPtr->subsampleX = values[0];
+ optPtr->subsampleY = values[1];
+ break;
+ case OPT_TO:
+ if ((values[0] < 0) || (values[1] < 0) || ((numValues > 2)
+ && ((values[2] < 0) || (values[3] < 0)))) {
+ needed = "non-negative";
+ goto numberOutOfRange;
+ }
+ if (numValues <= 2) {
+ optPtr->toX = values[0];
+ optPtr->toY = values[1];
+ optPtr->toX2 = -1;
+ optPtr->toY2 = -1;
+ } else {
+ optPtr->toX = MIN(values[0], values[2]);
+ optPtr->toY = MIN(values[1], values[3]);
+ optPtr->toX2 = MAX(values[0], values[2]);
+ optPtr->toY2 = MAX(values[1], values[3]);
+ }
+ break;
+ case OPT_ZOOM:
+ if ((values[0] <= 0) || (values[1] <= 0)) {
+ needed = "positive";
+ goto numberOutOfRange;
+ }
+ optPtr->zoomX = values[0];
+ optPtr->zoomY = values[1];
+ break;
+ }
+ }
+
+ /*
+ * Remember that we saw this option.
+ */
+
+ optPtr->options |= bit;
+ }
+ return TCL_OK;
+
+ /*
+ * Exception generation.
+ */
+
+ oneValueRequired:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "the \"%s\" option requires a value", expandedOption));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "MISSING_VALUE", NULL);
+ return TCL_ERROR;
+
+ manyValuesRequired:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "the \"%s\" option requires one %s integer values",
+ expandedOption, (maxValues == 2) ? "or two": "to four"));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "MISSING_VALUE", NULL);
+ return TCL_ERROR;
+
+ numberOutOfRange:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "value(s) for the %s option must be %s", expandedOption, needed));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "BAD_VALUE", NULL);
+ return TCL_ERROR;
+
+ unknownOrAmbiguousOption:
+ msgObj = Tcl_ObjPrintf("unrecognized option \"%s\": must be ", option);
+ bit = 1;
+ for (listPtr = optionNames; *listPtr != NULL; ++listPtr) {
+ if (allowedOptions & bit) {
+ if (allowedOptions & (bit - 1)) {
+ if (allowedOptions & ~((bit << 1) - 1)) {
+ Tcl_AppendToObj(msgObj, ", ", -1);
+ } else {
+ Tcl_AppendToObj(msgObj, ", or ", -1);
+ }
+ }
+ Tcl_AppendToObj(msgObj, *listPtr, -1);
+ }
+ bit <<= 1;
+ }
+ Tcl_SetObjResult(interp, msgObj);
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "BAD_OPTION", NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImgPhotoConfigureMaster --
+ *
+ * This function is called when a photo image is created or reconfigured.
+ * It processes configuration options and resets any instances of the
+ * image.
+ *
+ * Results:
+ * A standard Tcl return value. If TCL_ERROR is returned then an error
+ * message is left in the masterPtr->interp's result.
+ *
+ * Side effects:
+ * Existing instances of the image will be redisplayed to match the new
+ * configuration options.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ImgPhotoConfigureMaster(
+ Tcl_Interp *interp, /* Interpreter to use for reporting errors. */
+ PhotoMaster *masterPtr, /* Pointer to data structure describing
+ * overall photo image to (re)configure. */
+ int objc, /* Number of entries in objv. */
+ Tcl_Obj *const objv[], /* Pairs of configuration options for image. */
+ int flags) /* Flags to pass to Tk_ConfigureWidget, such
+ * as TK_CONFIG_ARGV_ONLY. */
+{
+ PhotoInstance *instancePtr;
+ const char *oldFileString, *oldPaletteString;
+ Tcl_Obj *oldData, *data = NULL, *oldFormat, *format = NULL;
+ Tcl_Obj *tempdata, *tempformat;
+ size_t length;
+ int i, j, result, imageWidth, imageHeight, oldformat;
+ double oldGamma;
+ Tcl_Channel chan;
+ Tk_PhotoImageFormat *imageFormat;
+ const char **args;
+
+ args = ckalloc((objc + 1) * sizeof(char *));
+ for (i = 0, j = 0; i < objc; i++,j++) {
+ args[j] = Tcl_GetString(objv[i]);
+ length = objv[i]->length;
+ if ((length > 1) && (args[j][0] == '-')) {
+ if ((args[j][1] == 'd') &&
+ !strncmp(args[j], "-data", length)) {
+ if (++i < objc) {
+ data = objv[i];
+ j--;
+ } else {
+ ckfree(args);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "value for \"-data\" missing", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO",
+ "MISSING_VALUE", NULL);
+ return TCL_ERROR;
+ }
+ } else if ((args[j][1] == 'f') &&
+ !strncmp(args[j], "-format", length)) {
+ if (++i < objc) {
+ format = objv[i];
+ j--;
+ } else {
+ ckfree(args);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "value for \"-format\" missing", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO",
+ "MISSING_VALUE", NULL);
+ return TCL_ERROR;
+ }
+ }
+ }
+ }
+
+ /*
+ * Save the current values for fileString and dataString, so we can tell
+ * if the user specifies them anew. IMPORTANT: if the format changes we
+ * have to interpret "-file" and "-data" again as well! It might be that
+ * the format string influences how "-data" or "-file" is interpreted.
+ */
+
+ oldFileString = masterPtr->fileString;
+ if (oldFileString == NULL) {
+ oldData = masterPtr->dataString;
+ if (oldData != NULL) {
+ Tcl_IncrRefCount(oldData);
+ }
+ } else {
+ oldData = NULL;
+ }
+ oldFormat = masterPtr->format;
+ if (oldFormat != NULL) {
+ Tcl_IncrRefCount(oldFormat);
+ }
+ oldPaletteString = masterPtr->palette;
+ oldGamma = masterPtr->gamma;
+
+ /*
+ * Process the configuration options specified.
+ */
+
+ if (Tk_ConfigureWidget(interp, Tk_MainWindow(interp), configSpecs,
+ j, args, (char *) masterPtr, flags) != TCL_OK) {
+ ckfree(args);
+ goto errorExit;
+ }
+ ckfree(args);
+
+ /*
+ * Regard the empty string for -file, -data or -format as the null value.
+ */
+
+ if ((masterPtr->fileString != NULL) && (masterPtr->fileString[0] == 0)) {
+ ckfree(masterPtr->fileString);
+ masterPtr->fileString = NULL;
+ }
+ if (data) {
+ /*
+ * Force into ByteArray format, which most (all) image handlers will
+ * use anyway. Empty length means ignore the -data option.
+ */
+ int bytesize;
+
+ (void) Tcl_GetByteArrayFromObj(data, &bytesize);
+ if (bytesize) {
+ Tcl_IncrRefCount(data);
+ } else {
+ data = NULL;
+ }
+ if (masterPtr->dataString) {
+ Tcl_DecrRefCount(masterPtr->dataString);
+ }
+ masterPtr->dataString = data;
+ }
+ if (format) {
+ /*
+ * Stringify to ignore -format "". It may come in as a list or other
+ * object.
+ */
+
+ (void) Tcl_GetString(format);
+ if (format->length) {
+ Tcl_IncrRefCount(format);
+ } else {
+ format = NULL;
+ }
+ if (masterPtr->format) {
+ Tcl_DecrRefCount(masterPtr->format);
+ }
+ masterPtr->format = format;
+ }
+ /*
+ * Set the image to the user-requested size, if any, and make sure storage
+ * is correctly allocated for this image.
+ */
+
+ if (ImgPhotoSetSize(masterPtr, masterPtr->width,
+ masterPtr->height) != TCL_OK) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1));
+ Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL);
+ goto errorExit;
+ }
+
+ /*
+ * Read in the image from the file or string if the user has specified the
+ * -file or -data option.
+ */
+
+ if ((masterPtr->fileString != NULL)
+ && ((masterPtr->fileString != oldFileString)
+ || (masterPtr->format != oldFormat))) {
+ /*
+ * Prevent file system access in a safe interpreter.
+ */
+
+ if (Tcl_IsSafe(interp)) {
+ Tcl_ResetResult(interp);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "can't get image from a file in a safe interpreter",
+ -1));
+ Tcl_SetErrorCode(interp, "TK", "SAFE", "PHOTO_FILE", NULL);
+ goto errorExit;
+ }
+
+ chan = Tcl_OpenFileChannel(interp, masterPtr->fileString, "r", 0);
+ if (chan == NULL) {
+ goto errorExit;
+ }
+
+ /*
+ * -translation binary also sets -encoding binary
+ */
+
+ if ((Tcl_SetChannelOption(interp, chan,
+ "-translation", "binary") != TCL_OK) ||
+ (MatchFileFormat(interp, chan, masterPtr->fileString,
+ masterPtr->format, &imageFormat, &imageWidth,
+ &imageHeight, &oldformat) != TCL_OK)) {
+ Tcl_Close(NULL, chan);
+ goto errorExit;
+ }
+ result = ImgPhotoSetSize(masterPtr, imageWidth, imageHeight);
+ if (result != TCL_OK) {
+ Tcl_Close(NULL, chan);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1));
+ Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL);
+ goto errorExit;
+ }
+ tempformat = masterPtr->format;
+ if (oldformat && tempformat) {
+ tempformat = (Tcl_Obj *) Tcl_GetString(tempformat);
+ }
+ result = imageFormat->fileReadProc(interp, chan,
+ masterPtr->fileString, tempformat, (Tk_PhotoHandle) masterPtr,
+ 0, 0, imageWidth, imageHeight, 0, 0);
+ Tcl_Close(NULL, chan);
+ if (result != TCL_OK) {
+ goto errorExit;
+ }
+
+ Tcl_ResetResult(interp);
+ masterPtr->flags |= IMAGE_CHANGED;
+ }
+
+ if ((masterPtr->fileString == NULL) && (masterPtr->dataString != NULL)
+ && ((masterPtr->dataString != oldData)
+ || (masterPtr->format != oldFormat))) {
+
+ if (MatchStringFormat(interp, masterPtr->dataString,
+ masterPtr->format, &imageFormat, &imageWidth,
+ &imageHeight, &oldformat) != TCL_OK) {
+ goto errorExit;
+ }
+ if (ImgPhotoSetSize(masterPtr, imageWidth, imageHeight) != TCL_OK) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1));
+ Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL);
+ goto errorExit;
+ }
+ tempformat = masterPtr->format;
+ tempdata = masterPtr->dataString;
+ if (oldformat) {
+ if (tempformat) {
+ tempformat = (Tcl_Obj *) Tcl_GetString(tempformat);
+ }
+ tempdata = (Tcl_Obj *) Tcl_GetString(tempdata);
+ }
+ if (imageFormat->stringReadProc(interp, tempdata, tempformat,
+ (Tk_PhotoHandle) masterPtr, 0, 0, imageWidth, imageHeight,
+ 0, 0) != TCL_OK) {
+ goto errorExit;
+ }
+
+ Tcl_ResetResult(interp);
+ masterPtr->flags |= IMAGE_CHANGED;
+ }
+
+ /*
+ * Enforce a reasonable value for gamma.
+ */
+
+ if (masterPtr->gamma <= 0) {
+ masterPtr->gamma = 1.0;
+ }
+
+ if ((masterPtr->gamma != oldGamma)
+ || (masterPtr->palette != oldPaletteString)) {
+ masterPtr->flags |= IMAGE_CHANGED;
+ }
+
+ /*
+ * Cycle through all of the instances of this image, regenerating the
+ * information for each instance. Then force the image to be redisplayed
+ * everywhere that it is used.
+ */
+
+ for (instancePtr = masterPtr->instancePtr; instancePtr != NULL;
+ instancePtr = instancePtr->nextPtr) {
+ TkImgPhotoConfigureInstance(instancePtr);
+ }
+
+ /*
+ * Inform the generic image code that the image has (potentially) changed.
+ */
+
+ Tk_ImageChanged(masterPtr->tkMaster, 0, 0, masterPtr->width,
+ masterPtr->height, masterPtr->width, masterPtr->height);
+ masterPtr->flags &= ~IMAGE_CHANGED;
+
+ if (oldData != NULL) {
+ Tcl_DecrRefCount(oldData);
+ }
+ if (oldFormat != NULL) {
+ Tcl_DecrRefCount(oldFormat);
+ }
+
+ ToggleComplexAlphaIfNeeded(masterPtr);
+
+ return TCL_OK;
+
+ errorExit:
+ if (oldData != NULL) {
+ Tcl_DecrRefCount(oldData);
+ }
+ if (oldFormat != NULL) {
+ Tcl_DecrRefCount(oldFormat);
+ }
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ToggleComplexAlphaIfNeeded --
+ *
+ * This function is called when an image is modified to check if any
+ * partially transparent pixels exist, which requires blending instead of
+ * straight copy.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * (Re)sets COMPLEX_ALPHA flag of master.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ToggleComplexAlphaIfNeeded(
+ PhotoMaster *mPtr)
+{
+ size_t len = (size_t)MAX(mPtr->userWidth, mPtr->width) *
+ (size_t)MAX(mPtr->userHeight, mPtr->height) * 4;
+ unsigned char *c = mPtr->pix32;
+ unsigned char *end = c + len;
+
+ /*
+ * Set the COMPLEX_ALPHA flag if we have an image with partially
+ * transparent bits.
+ */
+
+ mPtr->flags &= ~COMPLEX_ALPHA;
+ if (c == NULL) {
+ return 0;
+ }
+ c += 3; /* Start at first alpha byte. */
+ for (; c < end; c += 4) {
+ if (*c && *c != 255) {
+ mPtr->flags |= COMPLEX_ALPHA;
+ break;
+ }
+ }
+ return (mPtr->flags & COMPLEX_ALPHA);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImgPhotoDelete --
+ *
+ * This function is called by the image code to delete the master
+ * structure for an image.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Resources associated with the image get freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ImgPhotoDelete(
+ ClientData masterData) /* Pointer to PhotoMaster structure for image.
+ * Must not have any more instances. */
+{
+ PhotoMaster *masterPtr = masterData;
+ PhotoInstance *instancePtr;
+
+ while ((instancePtr = masterPtr->instancePtr) != NULL) {
+ if (instancePtr->refCount > 0) {
+ Tcl_Panic("tried to delete photo image when instances still exist");
+ }
+ Tcl_CancelIdleCall(TkImgDisposeInstance, instancePtr);
+ TkImgDisposeInstance(instancePtr);
+ }
+ masterPtr->tkMaster = NULL;
+ if (masterPtr->imageCmd != NULL) {
+ Tcl_DeleteCommandFromToken(masterPtr->interp, masterPtr->imageCmd);
+ }
+ if (masterPtr->pix32 != NULL) {
+ ckfree(masterPtr->pix32);
+ }
+ if (masterPtr->validRegion != NULL) {
+ TkDestroyRegion(masterPtr->validRegion);
+ }
+ if (masterPtr->dataString != NULL) {
+ Tcl_DecrRefCount(masterPtr->dataString);
+ }
+ if (masterPtr->format != NULL) {
+ Tcl_DecrRefCount(masterPtr->format);
+ }
+ Tk_FreeOptions(configSpecs, (char *) masterPtr, NULL, 0);
+ ckfree(masterPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImgPhotoCmdDeletedProc --
+ *
+ * This function is invoked when the image command for an image is
+ * deleted. It deletes the image.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The image is deleted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ImgPhotoCmdDeletedProc(
+ ClientData clientData) /* Pointer to PhotoMaster structure for
+ * image. */
+{
+ PhotoMaster *masterPtr = clientData;
+
+ masterPtr->imageCmd = NULL;
+ if (masterPtr->tkMaster != NULL) {
+ Tk_DeleteImage(masterPtr->interp, Tk_NameOfImage(masterPtr->tkMaster));
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImgPhotoSetSize --
+ *
+ * This function reallocates the image storage and instance pixmaps for a
+ * photo image, as necessary, to change the image's size to `width' x
+ * `height' pixels.
+ *
+ * Results:
+ * TCL_OK if successful, TCL_ERROR if failure occurred (currently just
+ * with memory allocation.)
+ *
+ * Side effects:
+ * Storage gets reallocated, for the master and all its instances.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ImgPhotoSetSize(
+ PhotoMaster *masterPtr,
+ int width, int height)
+{
+ unsigned char *newPix32 = NULL;
+ int h, offset, pitch;
+ unsigned char *srcPtr, *destPtr;
+ XRectangle validBox, clipBox;
+ TkRegion clipRegion;
+ PhotoInstance *instancePtr;
+
+ if (masterPtr->userWidth > 0) {
+ width = masterPtr->userWidth;
+ }
+ if (masterPtr->userHeight > 0) {
+ height = masterPtr->userHeight;
+ }
+
+ if (width > INT_MAX / 4) {
+ /* Pitch overflows int */
+ return TCL_ERROR;
+ }
+ pitch = width * 4;
+
+ /*
+ * Test if we're going to (re)allocate the main buffer now, so that any
+ * failures will leave the photo unchanged.
+ */
+
+ if ((width != masterPtr->width) || (height != masterPtr->height)
+ || (masterPtr->pix32 == NULL)) {
+ unsigned newPixSize;
+
+ if (pitch && height > (int)(UINT_MAX / pitch)) {
+ return TCL_ERROR;
+ }
+ newPixSize = height * pitch;
+
+ /*
+ * Some mallocs() really hate allocating zero bytes. [Bug 619544]
+ */
+
+ if (newPixSize == 0) {
+ newPix32 = NULL;
+ } else {
+ newPix32 = attemptckalloc(newPixSize);
+ if (newPix32 == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ }
+
+ /*
+ * We have to trim the valid region if it is currently larger than the new
+ * image size.
+ */
+
+ TkClipBox(masterPtr->validRegion, &validBox);
+ if ((validBox.x + validBox.width > width)
+ || (validBox.y + validBox.height > height)) {
+ clipBox.x = 0;
+ clipBox.y = 0;
+ clipBox.width = width;
+ clipBox.height = height;
+ clipRegion = TkCreateRegion();
+ TkUnionRectWithRegion(&clipBox, clipRegion, clipRegion);
+ TkIntersectRegion(masterPtr->validRegion, clipRegion,
+ masterPtr->validRegion);
+ TkDestroyRegion(clipRegion);
+ TkClipBox(masterPtr->validRegion, &validBox);
+ }
+
+ /*
+ * Use the reallocated storage (allocation above) for the 32-bit image and
+ * copy over valid regions. Note that this test is true precisely when the
+ * allocation has already been done.
+ */
+
+ if (newPix32 != NULL) {
+ /*
+ * Zero the new array. The dithering code shouldn't read the areas
+ * outside validBox, but they might be copied to another photo image
+ * or written to a file.
+ */
+
+ if ((masterPtr->pix32 != NULL)
+ && ((width == masterPtr->width) || (width == validBox.width))) {
+ if (validBox.y > 0) {
+ memset(newPix32, 0, ((size_t) validBox.y * pitch));
+ }
+ h = validBox.y + validBox.height;
+ if (h < height) {
+ memset(newPix32 + h*pitch, 0, ((size_t) (height - h) * pitch));
+ }
+ } else {
+ memset(newPix32, 0, ((size_t)height * pitch));
+ }
+
+ if (masterPtr->pix32 != NULL) {
+ /*
+ * Copy the common area over to the new array array and free the
+ * old array.
+ */
+
+ if (width == masterPtr->width) {
+
+ /*
+ * The region to be copied is contiguous.
+ */
+
+ offset = validBox.y * pitch;
+ memcpy(newPix32 + offset, masterPtr->pix32 + offset,
+ ((size_t)validBox.height * pitch));
+
+ } else if ((validBox.width > 0) && (validBox.height > 0)) {
+ /*
+ * Area to be copied is not contiguous - copy line by line.
+ */
+
+ destPtr = newPix32 + (validBox.y * width + validBox.x) * 4;
+ srcPtr = masterPtr->pix32 + (validBox.y * masterPtr->width
+ + validBox.x) * 4;
+ for (h = validBox.height; h > 0; h--) {
+ memcpy(destPtr, srcPtr, ((size_t)validBox.width * 4));
+ destPtr += width * 4;
+ srcPtr += masterPtr->width * 4;
+ }
+ }
+
+ ckfree(masterPtr->pix32);
+ }
+
+ masterPtr->pix32 = newPix32;
+ masterPtr->width = width;
+ masterPtr->height = height;
+
+ /*
+ * Dithering will be correct up to the end of the last pre-existing
+ * complete scanline.
+ */
+
+ if ((validBox.x > 0) || (validBox.y > 0)) {
+ masterPtr->ditherX = 0;
+ masterPtr->ditherY = 0;
+ } else if (validBox.width == width) {
+ if ((int) validBox.height < masterPtr->ditherY) {
+ masterPtr->ditherX = 0;
+ masterPtr->ditherY = validBox.height;
+ }
+ } else if ((masterPtr->ditherY > 0)
+ || ((int) validBox.width < masterPtr->ditherX)) {
+ masterPtr->ditherX = validBox.width;
+ masterPtr->ditherY = 0;
+ }
+ }
+
+ ToggleComplexAlphaIfNeeded(masterPtr);
+
+ /*
+ * Now adjust the sizes of the pixmaps for all of the instances.
+ */
+
+ for (instancePtr = masterPtr->instancePtr; instancePtr != NULL;
+ instancePtr = instancePtr->nextPtr) {
+ TkImgPhotoInstanceSetSize(instancePtr);
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MatchFileFormat --
+ *
+ * This function is called to find a photo image file format handler
+ * which can parse the image data in the given file. If a user-specified
+ * format string is provided, only handlers whose names match a prefix of
+ * the format string are tried.
+ *
+ * Results:
+ * A standard TCL return value. If the return value is TCL_OK, a pointer
+ * to the image format record is returned in *imageFormatPtr, and the
+ * width and height of the image are returned in *widthPtr and
+ * *heightPtr.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+MatchFileFormat(
+ Tcl_Interp *interp, /* Interpreter to use for reporting errors. */
+ Tcl_Channel chan, /* The image file, open for reading. */
+ const char *fileName, /* The name of the image file. */
+ Tcl_Obj *formatObj, /* User-specified format string, or NULL. */
+ Tk_PhotoImageFormat **imageFormatPtr,
+ /* A pointer to the photo image format record
+ * is returned here. */
+ int *widthPtr, int *heightPtr,
+ /* The dimensions of the image are returned
+ * here. */
+ int *oldformat) /* Returns 1 if the old image API is used. */
+{
+ int matched = 0, useoldformat = 0;
+ Tk_PhotoImageFormat *formatPtr;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ const char *formatString = NULL;
+
+ if (formatObj) {
+ formatString = Tcl_GetString(formatObj);
+ }
+
+ /*
+ * Scan through the table of file format handlers to find one which can
+ * handle the image.
+ */
+
+ for (formatPtr = tsdPtr->formatList; formatPtr != NULL;
+ formatPtr = formatPtr->nextPtr) {
+ if (formatObj != NULL) {
+ if (strncasecmp(formatString,
+ formatPtr->name, strlen(formatPtr->name)) != 0) {
+ continue;
+ }
+ matched = 1;
+ if (formatPtr->fileMatchProc == NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "-file option isn't supported for %s images",
+ formatString));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO",
+ "NOT_FILE_FORMAT", NULL);
+ return TCL_ERROR;
+ }
+ }
+ if (formatPtr->fileMatchProc != NULL) {
+ (void) Tcl_Seek(chan, Tcl_LongAsWide(0L), SEEK_SET);
+
+ if (formatPtr->fileMatchProc(chan, fileName, formatObj,
+ widthPtr, heightPtr, interp)) {
+ if (*widthPtr < 1) {
+ *widthPtr = 1;
+ }
+ if (*heightPtr < 1) {
+ *heightPtr = 1;
+ }
+ break;
+ }
+ }
+ }
+ if (formatPtr == NULL) {
+ useoldformat = 1;
+ for (formatPtr = tsdPtr->oldFormatList; formatPtr != NULL;
+ formatPtr = formatPtr->nextPtr) {
+ if (formatString != NULL) {
+ if (strncasecmp(formatString,
+ formatPtr->name, strlen(formatPtr->name)) != 0) {
+ continue;
+ }
+ matched = 1;
+ if (formatPtr->fileMatchProc == NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "-file option isn't supported for %s images",
+ formatString));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO",
+ "NOT_FILE_FORMAT", NULL);
+ return TCL_ERROR;
+ }
+ }
+ if (formatPtr->fileMatchProc != NULL) {
+ (void) Tcl_Seek(chan, Tcl_LongAsWide(0L), SEEK_SET);
+ if (formatPtr->fileMatchProc(chan, fileName, (Tcl_Obj *)
+ formatString, widthPtr, heightPtr, interp)) {
+ if (*widthPtr < 1) {
+ *widthPtr = 1;
+ }
+ if (*heightPtr < 1) {
+ *heightPtr = 1;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ if (formatPtr == NULL) {
+ if ((formatObj != NULL) && !matched) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "image file format \"%s\" is not supported",
+ formatString));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "PHOTO_FORMAT",
+ formatString, NULL);
+ } else {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "couldn't recognize data in image file \"%s\"",
+ fileName));
+ Tcl_SetErrorCode(interp, "TK", "PHOTO", "IMAGE",
+ "UNRECOGNIZED_DATA", NULL);
+ }
+ return TCL_ERROR;
+ }
+
+ *imageFormatPtr = formatPtr;
+ *oldformat = useoldformat;
+ (void) Tcl_Seek(chan, Tcl_LongAsWide(0L), SEEK_SET);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MatchStringFormat --
+ *
+ * This function is called to find a photo image file format handler
+ * which can parse the image data in the given string. If a
+ * user-specified format string is provided, only handlers whose names
+ * match a prefix of the format string are tried.
+ *
+ * Results:
+ * A standard TCL return value. If the return value is TCL_OK, a pointer
+ * to the image format record is returned in *imageFormatPtr, and the
+ * width and height of the image are returned in *widthPtr and
+ * *heightPtr.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+MatchStringFormat(
+ Tcl_Interp *interp, /* Interpreter to use for reporting errors. */
+ Tcl_Obj *data, /* Object containing the image data. */
+ Tcl_Obj *formatObj, /* User-specified format string, or NULL. */
+ Tk_PhotoImageFormat **imageFormatPtr,
+ /* A pointer to the photo image format record
+ * is returned here. */
+ int *widthPtr, int *heightPtr,
+ /* The dimensions of the image are returned
+ * here. */
+ int *oldformat) /* Returns 1 if the old image API is used. */
+{
+ int matched = 0, useoldformat = 0;
+ Tk_PhotoImageFormat *formatPtr;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ const char *formatString = NULL;
+
+ if (formatObj) {
+ formatString = Tcl_GetString(formatObj);
+ }
+
+ /*
+ * Scan through the table of file format handlers to find one which can
+ * handle the image.
+ */
+
+ for (formatPtr = tsdPtr->formatList; formatPtr != NULL;
+ formatPtr = formatPtr->nextPtr) {
+ if (formatObj != NULL) {
+ if (strncasecmp(formatString,
+ formatPtr->name, strlen(formatPtr->name)) != 0) {
+ continue;
+ }
+ matched = 1;
+ if (formatPtr->stringMatchProc == NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "-data option isn't supported for %s images",
+ formatString));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO",
+ "NOT_DATA_FORMAT", NULL);
+ return TCL_ERROR;
+ }
+ }
+ if ((formatPtr->stringMatchProc != NULL)
+ && (formatPtr->stringReadProc != NULL)
+ && formatPtr->stringMatchProc(data, formatObj,
+ widthPtr, heightPtr, interp)) {
+ break;
+ }
+ }
+
+ if (formatPtr == NULL) {
+ useoldformat = 1;
+ for (formatPtr = tsdPtr->oldFormatList; formatPtr != NULL;
+ formatPtr = formatPtr->nextPtr) {
+ if (formatObj != NULL) {
+ if (strncasecmp(formatString,
+ formatPtr->name, strlen(formatPtr->name)) != 0) {
+ continue;
+ }
+ matched = 1;
+ if (formatPtr->stringMatchProc == NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "-data option isn't supported for %s images",
+ formatString));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO",
+ "NOT_DATA_FORMAT", NULL);
+ return TCL_ERROR;
+ }
+ }
+ if ((formatPtr->stringMatchProc != NULL)
+ && (formatPtr->stringReadProc != NULL)
+ && formatPtr->stringMatchProc(
+ (Tcl_Obj *) Tcl_GetString(data),
+ (Tcl_Obj *) formatString,
+ widthPtr, heightPtr, interp)) {
+ break;
+ }
+ }
+ }
+ if (formatPtr == NULL) {
+ if ((formatObj != NULL) && !matched) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "image format \"%s\" is not supported", formatString));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "PHOTO_FORMAT",
+ formatString, NULL);
+ } else {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "couldn't recognize image data", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO",
+ "UNRECOGNIZED_DATA", NULL);
+ }
+ return TCL_ERROR;
+ }
+
+ *imageFormatPtr = formatPtr;
+ *oldformat = useoldformat;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_FindPhoto --
+ *
+ * This function is called to get an opaque handle (actually a
+ * PhotoMaster *) for a given image, which can be used in subsequent
+ * calls to Tk_PhotoPutBlock, etc. The `name' parameter is the name of
+ * the image.
+ *
+ * Results:
+ * The handle for the photo image, or NULL if there is no photo image
+ * with the name given.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_PhotoHandle
+Tk_FindPhoto(
+ Tcl_Interp *interp, /* Interpreter (application) in which image
+ * exists. */
+ const char *imageName) /* Name of the desired photo image. */
+{
+ const Tk_ImageType *typePtr;
+ ClientData clientData =
+ Tk_GetImageMasterData(interp, imageName, &typePtr);
+
+ if ((typePtr == NULL) || (typePtr->name != tkPhotoImageType.name)) {
+ return NULL;
+ }
+ return clientData;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_PhotoPutBlock --
+ *
+ * This function is called to put image data into a photo image.
+ *
+ * Results:
+ * A standard Tcl result code.
+ *
+ * Side effects:
+ * The image data is stored. The image may be expanded. The Tk image code
+ * is informed that the image has changed. If the result code is
+ * TCL_ERROR, an error message will be placed in the interpreter (if
+ * non-NULL).
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_PhotoPutBlock(
+ Tcl_Interp *interp, /* Interpreter for passing back error
+ * messages, or NULL. */
+ Tk_PhotoHandle handle, /* Opaque handle for the photo image to be
+ * updated. */
+ Tk_PhotoImageBlock *blockPtr,
+ /* Pointer to a structure describing the pixel
+ * data to be copied into the image. */
+ int x, int y, /* Coordinates of the top-left pixel to be
+ * updated in the image. */
+ int width, int height, /* Dimensions of the area of the image to be
+ * updated. */
+ int compRule) /* Compositing rule to use when processing
+ * transparent pixels. */
+{
+ register PhotoMaster *masterPtr = (PhotoMaster *) handle;
+ Tk_PhotoImageBlock sourceBlock;
+ unsigned char *memToFree;
+ int xEnd, yEnd, greenOffset, blueOffset, alphaOffset;
+ int wLeft, hLeft, wCopy, hCopy, pitch;
+ unsigned char *srcPtr, *srcLinePtr, *destPtr, *destLinePtr;
+ int sourceIsSimplePhoto = compRule & SOURCE_IS_SIMPLE_ALPHA_PHOTO;
+ XRectangle rect;
+
+ /*
+ * Zero-sized blocks never cause any changes. [Bug 3078902]
+ */
+
+ if (blockPtr->height == 0 || blockPtr->width == 0) {
+ return TCL_OK;
+ }
+
+ compRule &= ~SOURCE_IS_SIMPLE_ALPHA_PHOTO;
+
+ if ((masterPtr->userWidth != 0) && ((x + width) > masterPtr->userWidth)) {
+ width = masterPtr->userWidth - x;
+ }
+ if ((masterPtr->userHeight != 0)
+ && ((y + height) > masterPtr->userHeight)) {
+ height = masterPtr->userHeight - y;
+ }
+ if ((width <= 0) || (height <= 0)) {
+ return TCL_OK;
+ }
+
+ /*
+ * Fix for bug e4336bef5d:
+ *
+ * Make a local copy of *blockPtr, as we might have to change some
+ * of its fields and don't want to interfere with the caller's data.
+ *
+ * If source and destination are the same image, create a copy of the
+ * source data in our local sourceBlock.
+ *
+ * To find out, just comparing the pointers is not enough - they might have
+ * different values and still point to the same block of memory. (e.g.
+ * if the -from option was passed to [imageName copy])
+ */
+ sourceBlock = *blockPtr;
+ memToFree = NULL;
+ if (sourceBlock.pixelPtr >= masterPtr->pix32
+ && sourceBlock.pixelPtr <= masterPtr->pix32 + masterPtr->width
+ * masterPtr->height * 4) {
+ sourceBlock.pixelPtr = attemptckalloc(sourceBlock.height
+ * sourceBlock.pitch);
+ if (sourceBlock.pixelPtr == NULL) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1));
+ Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL);
+ }
+ return TCL_ERROR;
+ }
+ memToFree = sourceBlock.pixelPtr;
+ memcpy(sourceBlock.pixelPtr, blockPtr->pixelPtr, sourceBlock.height
+ * sourceBlock.pitch);
+ }
+
+
+ xEnd = x + width;
+ yEnd = y + height;
+ if ((xEnd > masterPtr->width) || (yEnd > masterPtr->height)) {
+ if (ImgPhotoSetSize(masterPtr, MAX(xEnd, masterPtr->width),
+ MAX(yEnd, masterPtr->height)) == TCL_ERROR) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1));
+ Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL);
+ }
+ goto errorExit;
+ }
+ }
+
+ if ((y < masterPtr->ditherY) || ((y == masterPtr->ditherY)
+ && (x < masterPtr->ditherX))) {
+ /*
+ * The dithering isn't correct past the start of this block.
+ */
+
+ masterPtr->ditherX = x;
+ masterPtr->ditherY = y;
+ }
+
+ /*
+ * If this image block could have different red, green and blue
+ * components, mark it as a color image.
+ */
+
+ greenOffset = sourceBlock.offset[1] - sourceBlock.offset[0];
+ blueOffset = sourceBlock.offset[2] - sourceBlock.offset[0];
+ alphaOffset = sourceBlock.offset[3];
+ if ((alphaOffset >= sourceBlock.pixelSize) || (alphaOffset < 0)) {
+ alphaOffset = 0;
+ sourceIsSimplePhoto = 1;
+ } else {
+ alphaOffset -= sourceBlock.offset[0];
+ }
+ if ((greenOffset != 0) || (blueOffset != 0)) {
+ masterPtr->flags |= COLOR_IMAGE;
+ }
+
+ /*
+ * Copy the data into our local 32-bit/pixel array. If we can do it with a
+ * single memmove, we do.
+ */
+
+ destLinePtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4;
+ pitch = masterPtr->width * 4;
+
+ /*
+ * Test to see if we can do the whole write in a single copy. This test is
+ * probably too restrictive. We should also be able to do a memmove if
+ * pixelSize == 3 and alphaOffset == 0. Maybe other cases too.
+ */
+
+ if ((sourceBlock.pixelSize == 4)
+ && (greenOffset == 1) && (blueOffset == 2) && (alphaOffset == 3)
+ && (width <= sourceBlock.width) && (height <= sourceBlock.height)
+ && ((height == 1) || ((x == 0) && (width == masterPtr->width)
+ && (sourceBlock.pitch == pitch)))
+ && (compRule == TK_PHOTO_COMPOSITE_SET)) {
+ memmove(destLinePtr, sourceBlock.pixelPtr + sourceBlock.offset[0],
+ ((size_t)height * width * 4));
+
+ /*
+ * We know there's an alpha offset and we're setting the data, so skip
+ * directly to the point when we recompute the photo validity region.
+ */
+
+ goto recalculateValidRegion;
+ }
+
+ /*
+ * Copy and merge pixels according to the compositing rule.
+ */
+
+ for (hLeft = height; hLeft > 0;) {
+ int pixelSize = sourceBlock.pixelSize;
+ int compRuleSet = (compRule == TK_PHOTO_COMPOSITE_SET);
+
+ srcLinePtr = sourceBlock.pixelPtr + sourceBlock.offset[0];
+ hCopy = MIN(hLeft, sourceBlock.height);
+ hLeft -= hCopy;
+ for (; hCopy > 0; --hCopy) {
+ /*
+ * If the layout of the source line matches our memory layout and
+ * we're setting, we can just copy the bytes directly, which is
+ * much faster.
+ */
+
+ if ((pixelSize == 4) && (greenOffset == 1)
+ && (blueOffset == 2) && (alphaOffset == 3)
+ && (width <= sourceBlock.width)
+ && compRuleSet) {
+ memcpy(destLinePtr, srcLinePtr, ((size_t)width * 4));
+ srcLinePtr += sourceBlock.pitch;
+ destLinePtr += pitch;
+ continue;
+ }
+
+ /*
+ * Have to copy the slow way.
+ */
+
+ destPtr = destLinePtr;
+ for (wLeft = width; wLeft > 0;) {
+ wCopy = MIN(wLeft, sourceBlock.width);
+ wLeft -= wCopy;
+ srcPtr = srcLinePtr;
+
+ /*
+ * But we might be lucky and be able to use fairly fast loops.
+ * It's worth checking...
+ */
+
+ if (alphaOffset == 0) {
+ /*
+ * This is the non-alpha case, so can still be fairly
+ * fast. Note that in the non-alpha-source case, the
+ * compositing rule doesn't apply.
+ */
+
+ for (; wCopy>0 ; --wCopy, srcPtr+=pixelSize) {
+ *destPtr++ = srcPtr[0];
+ *destPtr++ = srcPtr[greenOffset];
+ *destPtr++ = srcPtr[blueOffset];
+ *destPtr++ = 255;
+ }
+ continue;
+ } else if (compRuleSet) {
+ /*
+ * This is the SET compositing rule, which just replaces
+ * what was there before with the new data. This is
+ * another fairly fast case. No point in doing a memcpy();
+ * the order of channels is probably wrong.
+ */
+
+ for (; wCopy>0 ; --wCopy, srcPtr+=pixelSize) {
+ *destPtr++ = srcPtr[0];
+ *destPtr++ = srcPtr[greenOffset];
+ *destPtr++ = srcPtr[blueOffset];
+ *destPtr++ = srcPtr[alphaOffset];
+ }
+ continue;
+ }
+
+ /*
+ * Bother; need to consider the alpha value of each pixel to
+ * know what to do.
+ */
+
+ for (; wCopy>0 ; --wCopy, srcPtr+=pixelSize) {
+ int alpha = srcPtr[alphaOffset];
+
+ if (alpha == 255 || !destPtr[3]) {
+ /*
+ * Either the source is 100% opaque, or the
+ * destination is entirely blank. In all cases, we
+ * just set the destination to the source.
+ */
+
+ *destPtr++ = srcPtr[0];
+ *destPtr++ = srcPtr[greenOffset];
+ *destPtr++ = srcPtr[blueOffset];
+ *destPtr++ = alpha;
+ continue;
+ }
+
+ /*
+ * Can still skip doing work if the source is 100%
+ * transparent at this point.
+ */
+
+ if (alpha) {
+ int Alpha = destPtr[3];
+
+ /*
+ * OK, there's real work to be done. Luckily, there's
+ * a substantial literature on what to do in this
+ * case. In particular, Porter and Duff have done a
+ * taxonomy of compositing rules, and the right one is
+ * the "Source Over" rule. This code implements that.
+ */
+
+ destPtr[0] = PD_SRC_OVER(srcPtr[0], alpha, destPtr[0],
+ Alpha);
+ destPtr[1] = PD_SRC_OVER(srcPtr[greenOffset], alpha,
+ destPtr[1], Alpha);
+ destPtr[2] = PD_SRC_OVER(srcPtr[blueOffset], alpha,
+ destPtr[2], Alpha);
+ destPtr[3] = PD_SRC_OVER_ALPHA(alpha, Alpha);
+ }
+
+ destPtr += 4;
+ }
+ }
+ srcLinePtr += sourceBlock.pitch;
+ destLinePtr += pitch;
+ }
+ }
+
+ /*
+ * Add this new block to the region which specifies which data is valid.
+ */
+
+ if (alphaOffset) {
+ /*
+ * This block is grossly inefficient. For each row in the image, it
+ * finds each continguous string of nontransparent pixels, then marks
+ * those areas as valid in the validRegion mask. This makes drawing
+ * very efficient, because of the way we use X: we just say, here's
+ * your mask, and here's your data. We need not worry about the
+ * current background color, etc. But this costs us a lot on the image
+ * setup. Still, image setup only happens once, whereas the drawing
+ * happens many times, so this might be the best way to go.
+ *
+ * An alternative might be to not set up this mask, and instead, at
+ * drawing time, for each transparent pixel, set its color to the
+ * color of the background behind that pixel. This is what I suspect
+ * most of programs do. However, they don't have to deal with the
+ * canvas, which could have many different background colors.
+ * Determining the correct bg color for a given pixel might be
+ * expensive.
+ */
+
+ if (compRule != TK_PHOTO_COMPOSITE_OVERLAY) {
+ TkRegion workRgn;
+
+ /*
+ * Don't need this when using the OVERLAY compositing rule, which
+ * always strictly increases the valid region.
+ */
+
+ recalculateValidRegion:
+ workRgn = TkCreateRegion();
+ rect.x = x;
+ rect.y = y;
+ rect.width = width;
+ rect.height = height;
+ TkUnionRectWithRegion(&rect, workRgn, workRgn);
+ TkSubtractRegion(masterPtr->validRegion, workRgn,
+ masterPtr->validRegion);
+ TkDestroyRegion(workRgn);
+ }
+
+ /*
+ * Factorize out the main part of the building of the region data to
+ * allow for more efficient per-platform implementations. [Bug 919066]
+ */
+
+ TkpBuildRegionFromAlphaData(masterPtr->validRegion, (unsigned) x,
+ (unsigned) y, (unsigned) width, (unsigned) height,
+ masterPtr->pix32 + (y * masterPtr->width + x) * 4 + 3,
+ 4, (unsigned) masterPtr->width * 4);
+ } else {
+ rect.x = x;
+ rect.y = y;
+ rect.width = width;
+ rect.height = height;
+ TkUnionRectWithRegion(&rect, masterPtr->validRegion,
+ masterPtr->validRegion);
+ }
+
+ /*
+ * Check if display code needs alpha blending...
+ */
+
+ if (!sourceIsSimplePhoto && (height == 1)) {
+ /*
+ * Optimize the single span case if we can. This speeds up code that
+ * builds up large simple-alpha images by scan-lines or individual
+ * pixels. We don't negate COMPLEX_ALPHA in this case. [Bug 1409140]
+ * [Patch 1539990]
+ */
+
+ if (!(masterPtr->flags & COMPLEX_ALPHA)) {
+ register int x1;
+
+ for (x1=x ; x1<x+width ; x1++) {
+ register unsigned char newAlpha;
+
+ destLinePtr = masterPtr->pix32 + (y*masterPtr->width + x1)*4;
+ newAlpha = destLinePtr[3];
+ if (newAlpha && newAlpha != 255) {
+ masterPtr->flags |= COMPLEX_ALPHA;
+ break;
+ }
+ }
+ }
+ } else if ((alphaOffset != 0) || (masterPtr->flags & COMPLEX_ALPHA)) {
+ /*
+ * Check for partial transparency if alpha pixels are specified, or
+ * rescan if we already knew such pixels existed. To restrict this
+ * Toggle to only checking the changed pixels requires knowing where
+ * the alpha pixels are.
+ */
+
+ ToggleComplexAlphaIfNeeded(masterPtr);
+ }
+
+ /*
+ * Update each instance.
+ */
+
+ Tk_DitherPhoto((Tk_PhotoHandle)masterPtr, x, y, width, height);
+
+ /*
+ * Tell the core image code that this image has changed.
+ */
+
+ Tk_ImageChanged(masterPtr->tkMaster, x, y, width, height,
+ masterPtr->width, masterPtr->height);
+
+ if (memToFree) ckfree(memToFree);
+
+ return TCL_OK;
+
+ errorExit:
+ if (memToFree) ckfree(memToFree);
+
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_PhotoPutZoomedBlock --
+ *
+ * This function is called to put image data into a photo image, with
+ * possible subsampling and/or zooming of the pixels.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The image data is stored. The image may be expanded. The Tk image code
+ * is informed that the image has changed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_PhotoPutZoomedBlock(
+ Tcl_Interp *interp, /* Interpreter for passing back error
+ * messages, or NULL. */
+ Tk_PhotoHandle handle, /* Opaque handle for the photo image to be
+ * updated. */
+ Tk_PhotoImageBlock *blockPtr,
+ /* Pointer to a structure describing the pixel
+ * data to be copied into the image. */
+ int x, int y, /* Coordinates of the top-left pixel to be
+ * updated in the image. */
+ int width, int height, /* Dimensions of the area of the image to be
+ * updated. */
+ int zoomX, int zoomY, /* Zoom factors for the X and Y axes. */
+ int subsampleX, int subsampleY,
+ /* Subsampling factors for the X and Y
+ * axes. */
+ int compRule) /* Compositing rule to use when processing
+ * transparent pixels. */
+{
+ register PhotoMaster *masterPtr = (PhotoMaster *) handle;
+ register Tk_PhotoImageBlock sourceBlock;
+ unsigned char *memToFree;
+ int xEnd, yEnd, greenOffset, blueOffset, alphaOffset;
+ int wLeft, hLeft, wCopy, hCopy, blockWid, blockHt;
+ unsigned char *srcPtr, *srcLinePtr, *srcOrigPtr, *destPtr, *destLinePtr;
+ int pitch, xRepeat, yRepeat, blockXSkip, blockYSkip, sourceIsSimplePhoto;
+ XRectangle rect;
+
+ /*
+ * Zero-sized blocks never cause any changes. [Bug 3078902]
+ */
+
+ if (blockPtr->height == 0 || blockPtr->width == 0) {
+ return TCL_OK;
+ }
+
+ if (zoomX==1 && zoomY==1 && subsampleX==1 && subsampleY==1) {
+ return Tk_PhotoPutBlock(interp, handle, blockPtr, x, y, width, height,
+ compRule);
+ }
+
+ sourceIsSimplePhoto = compRule & SOURCE_IS_SIMPLE_ALPHA_PHOTO;
+ compRule &= ~SOURCE_IS_SIMPLE_ALPHA_PHOTO;
+
+ if (zoomX <= 0 || zoomY <= 0) {
+ return TCL_OK;
+ }
+ if ((masterPtr->userWidth != 0) && ((x + width) > masterPtr->userWidth)) {
+ width = masterPtr->userWidth - x;
+ }
+ if ((masterPtr->userHeight != 0)
+ && ((y + height) > masterPtr->userHeight)) {
+ height = masterPtr->userHeight - y;
+ }
+ if (width <= 0 || height <= 0) {
+ return TCL_OK;
+ }
+
+ /*
+ * Fix for Bug e4336bef5d:
+ * Make a local copy of *blockPtr, as we might have to change some
+ * of its fields and don't want to interfere with the caller's data.
+ *
+ * If source and destination are the same image, create a copy of the
+ * source data in our local sourceBlock.
+ *
+ * To find out, just comparing the pointers is not enough - they might have
+ * different values and still point to the same block of memory. (e.g.
+ * if the -from option was passed to [imageName copy])
+ */
+ sourceBlock = *blockPtr;
+ memToFree = NULL;
+ if (sourceBlock.pixelPtr >= masterPtr->pix32
+ && sourceBlock.pixelPtr <= masterPtr->pix32 + masterPtr->width
+ * masterPtr->height * 4) {
+ sourceBlock.pixelPtr = attemptckalloc(sourceBlock.height
+ * sourceBlock.pitch);
+ if (sourceBlock.pixelPtr == NULL) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1));
+ Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL);
+ }
+ return TCL_ERROR;
+ }
+ memToFree = sourceBlock.pixelPtr;
+ memcpy(sourceBlock.pixelPtr, blockPtr->pixelPtr, sourceBlock.height
+ * sourceBlock.pitch);
+ }
+
+ xEnd = x + width;
+ yEnd = y + height;
+ if ((xEnd > masterPtr->width) || (yEnd > masterPtr->height)) {
+ if (ImgPhotoSetSize(masterPtr, MAX(xEnd, masterPtr->width),
+ MAX(yEnd, masterPtr->height)) == TCL_ERROR) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1));
+ Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL);
+ }
+ goto errorExit;
+ }
+ }
+
+ if ((y < masterPtr->ditherY) || ((y == masterPtr->ditherY)
+ && (x < masterPtr->ditherX))) {
+ /*
+ * The dithering isn't correct past the start of this block.
+ */
+
+ masterPtr->ditherX = x;
+ masterPtr->ditherY = y;
+ }
+
+ /*
+ * If this image block could have different red, green and blue
+ * components, mark it as a color image.
+ */
+
+ greenOffset = sourceBlock.offset[1] - sourceBlock.offset[0];
+ blueOffset = sourceBlock.offset[2] - sourceBlock.offset[0];
+ alphaOffset = sourceBlock.offset[3];
+ if ((alphaOffset >= sourceBlock.pixelSize) || (alphaOffset < 0)) {
+ alphaOffset = 0;
+ sourceIsSimplePhoto = 1;
+ } else {
+ alphaOffset -= sourceBlock.offset[0];
+ }
+ if ((greenOffset != 0) || (blueOffset != 0)) {
+ masterPtr->flags |= COLOR_IMAGE;
+ }
+
+ /*
+ * Work out what area the pixel data in the block expands to after
+ * subsampling and zooming.
+ */
+
+ blockXSkip = subsampleX * sourceBlock.pixelSize;
+ blockYSkip = subsampleY * sourceBlock.pitch;
+ if (subsampleX > 0) {
+ blockWid = ((sourceBlock.width + subsampleX - 1) / subsampleX) * zoomX;
+ } else if (subsampleX == 0) {
+ blockWid = width;
+ } else {
+ blockWid = ((sourceBlock.width - subsampleX - 1) / -subsampleX) * zoomX;
+ }
+ if (subsampleY > 0) {
+ blockHt = ((sourceBlock.height + subsampleY - 1) / subsampleY) * zoomY;
+ } else if (subsampleY == 0) {
+ blockHt = height;
+ } else {
+ blockHt = ((sourceBlock.height - subsampleY - 1) / -subsampleY) * zoomY;
+ }
+
+ /*
+ * Copy the data into our local 32-bit/pixel array.
+ */
+
+ destLinePtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4;
+ srcOrigPtr = sourceBlock.pixelPtr + sourceBlock.offset[0];
+ if (subsampleX < 0) {
+ srcOrigPtr += (sourceBlock.width - 1) * sourceBlock.pixelSize;
+ }
+ if (subsampleY < 0) {
+ srcOrigPtr += (sourceBlock.height - 1) * sourceBlock.pitch;
+ }
+
+ pitch = masterPtr->width * 4;
+ for (hLeft = height; hLeft > 0; ) {
+ hCopy = MIN(hLeft, blockHt);
+ hLeft -= hCopy;
+ yRepeat = zoomY;
+ srcLinePtr = srcOrigPtr;
+ for (; hCopy > 0; --hCopy) {
+ destPtr = destLinePtr;
+ for (wLeft = width; wLeft > 0;) {
+ wCopy = MIN(wLeft, blockWid);
+ wLeft -= wCopy;
+ srcPtr = srcLinePtr;
+ for (; wCopy > 0; wCopy -= zoomX) {
+ for (xRepeat = MIN(wCopy, zoomX); xRepeat > 0; xRepeat--) {
+ int alpha = srcPtr[alphaOffset];/* Source alpha. */
+
+ /*
+ * Common case (solid pixels) first
+ */
+
+ if (!alphaOffset || (alpha == 255)) {
+ *destPtr++ = srcPtr[0];
+ *destPtr++ = srcPtr[greenOffset];
+ *destPtr++ = srcPtr[blueOffset];
+ *destPtr++ = 255;
+ continue;
+ }
+
+ if (compRule==TK_PHOTO_COMPOSITE_SET || !destPtr[3]) {
+ /*
+ * Either this is the SET rule (we overwrite
+ * whatever is there) or the destination is
+ * entirely blank. In both cases, we just set the
+ * destination to the source.
+ */
+
+ *destPtr++ = srcPtr[0];
+ *destPtr++ = srcPtr[greenOffset];
+ *destPtr++ = srcPtr[blueOffset];
+ *destPtr++ = alpha;
+ } else if (alpha) {
+ int Alpha = destPtr[3]; /* Destination
+ * alpha. */
+
+ destPtr[0] = PD_SRC_OVER(srcPtr[0], alpha,
+ destPtr[0], Alpha);
+ destPtr[1] = PD_SRC_OVER(srcPtr[greenOffset],alpha,
+ destPtr[1], Alpha);
+ destPtr[2] = PD_SRC_OVER(srcPtr[blueOffset], alpha,
+ destPtr[2], Alpha);
+ destPtr[3] = PD_SRC_OVER_ALPHA(alpha, Alpha);
+
+ destPtr += 4;
+ } else {
+ destPtr += 4;
+ }
+ }
+ srcPtr += blockXSkip;
+ }
+ }
+ destLinePtr += pitch;
+ yRepeat--;
+ if (yRepeat <= 0) {
+ srcLinePtr += blockYSkip;
+ yRepeat = zoomY;
+ }
+ }
+ }
+
+ /*
+ * Recompute the region of data for which we have valid pixels to plot.
+ */
+
+ if (alphaOffset) {
+ if (compRule != TK_PHOTO_COMPOSITE_OVERLAY) {
+ /*
+ * Don't need this when using the OVERLAY compositing rule, which
+ * always strictly increases the valid region.
+ */
+
+ TkRegion workRgn = TkCreateRegion();
+
+ rect.x = x;
+ rect.y = y;
+ rect.width = width;
+ rect.height = 1;
+ TkUnionRectWithRegion(&rect, workRgn, workRgn);
+ TkSubtractRegion(masterPtr->validRegion, workRgn,
+ masterPtr->validRegion);
+ TkDestroyRegion(workRgn);
+ }
+
+ TkpBuildRegionFromAlphaData(masterPtr->validRegion,
+ (unsigned)x, (unsigned)y, (unsigned)width, (unsigned)height,
+ &masterPtr->pix32[(y * masterPtr->width + x) * 4 + 3], 4,
+ (unsigned) masterPtr->width * 4);
+ } else {
+ rect.x = x;
+ rect.y = y;
+ rect.width = width;
+ rect.height = height;
+ TkUnionRectWithRegion(&rect, masterPtr->validRegion,
+ masterPtr->validRegion);
+ }
+
+ /*
+ * Check if display code needs alpha blending...
+ */
+
+ if (!sourceIsSimplePhoto && (width == 1) && (height == 1)) {
+ /*
+ * Optimize the single pixel case if we can. This speeds up code that
+ * builds up large simple-alpha images by single pixels. We don't
+ * negate COMPLEX_ALPHA in this case. [Bug 1409140]
+ */
+ if (!(masterPtr->flags & COMPLEX_ALPHA)) {
+ unsigned char newAlpha;
+
+ destLinePtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4;
+ newAlpha = destLinePtr[3];
+
+ if (newAlpha && newAlpha != 255) {
+ masterPtr->flags |= COMPLEX_ALPHA;
+ }
+ }
+ } else if ((alphaOffset != 0) || (masterPtr->flags & COMPLEX_ALPHA)) {
+ /*
+ * Check for partial transparency if alpha pixels are specified, or
+ * rescan if we already knew such pixels existed. To restrict this
+ * Toggle to only checking the changed pixels requires knowing where
+ * the alpha pixels are.
+ */
+ ToggleComplexAlphaIfNeeded(masterPtr);
+ }
+
+ /*
+ * Update each instance.
+ */
+
+ Tk_DitherPhoto((Tk_PhotoHandle) masterPtr, x, y, width, height);
+
+ /*
+ * Tell the core image code that this image has changed.
+ */
+
+ Tk_ImageChanged(masterPtr->tkMaster, x, y, width, height, masterPtr->width,
+ masterPtr->height);
+
+ if (memToFree) ckfree(memToFree);
+
+ return TCL_OK;
+
+ errorExit:
+ if (memToFree) ckfree(memToFree);
+
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_DitherPhoto --
+ *
+ * This function is called to update an area of each instance's pixmap by
+ * dithering the corresponding area of the image master.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The pixmap of each instance of this image gets updated. The fields in
+ * *masterPtr indicating which area of the image is correctly dithered
+ * get updated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_DitherPhoto(
+ Tk_PhotoHandle photo, /* Image master whose instances are to be
+ * updated. */
+ int x, int y, /* Coordinates of the top-left pixel in the
+ * area to be dithered. */
+ int width, int height) /* Dimensions of the area to be dithered. */
+{
+ PhotoMaster *masterPtr = (PhotoMaster *) photo;
+ PhotoInstance *instancePtr;
+
+ if ((width <= 0) || (height <= 0)) {
+ return;
+ }
+
+ for (instancePtr = masterPtr->instancePtr; instancePtr != NULL;
+ instancePtr = instancePtr->nextPtr) {
+ TkImgDitherInstance(instancePtr, x, y, width, height);
+ }
+
+ /*
+ * Work out whether this block will be correctly dithered and whether it
+ * will extend the correctly dithered region.
+ */
+
+ if (((y < masterPtr->ditherY)
+ || ((y == masterPtr->ditherY) && (x <= masterPtr->ditherX)))
+ && ((y + height) > (masterPtr->ditherY))) {
+ /*
+ * This block starts inside (or immediately after) the correctly
+ * dithered region, so the first scan line at least will be right.
+ * Furthermore this block extends into scanline masterPtr->ditherY.
+ */
+
+ if ((x == 0) && (width == masterPtr->width)) {
+ /*
+ * We are doing the full width, therefore the dithering will be
+ * correct to the end.
+ */
+
+ masterPtr->ditherX = 0;
+ masterPtr->ditherY = y + height;
+ } else {
+ /*
+ * We are doing partial scanlines, therefore the
+ * correctly-dithered region will be extended by at most one scan
+ * line.
+ */
+
+ if (x <= masterPtr->ditherX) {
+ masterPtr->ditherX = x + width;
+ if (masterPtr->ditherX >= masterPtr->width) {
+ masterPtr->ditherX = 0;
+ masterPtr->ditherY++;
+ }
+ }
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_PhotoBlank --
+ *
+ * This function is called to clear an entire photo image.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The valid region for the image is set to the null region. The generic
+ * image code is notified that the image has changed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_PhotoBlank(
+ Tk_PhotoHandle handle) /* Handle for the image to be blanked. */
+{
+ PhotoMaster *masterPtr = (PhotoMaster *) handle;
+ PhotoInstance *instancePtr;
+
+ masterPtr->ditherX = masterPtr->ditherY = 0;
+ masterPtr->flags = 0;
+
+ /*
+ * The image has valid data nowhere.
+ */
+
+ if (masterPtr->validRegion != NULL) {
+ TkDestroyRegion(masterPtr->validRegion);
+ }
+ masterPtr->validRegion = TkCreateRegion();
+
+ /*
+ * Clear out the 32-bit pixel storage array. Clear out the dithering error
+ * arrays for each instance.
+ */
+
+ memset(masterPtr->pix32, 0,
+ ((size_t)masterPtr->width * masterPtr->height * 4));
+ for (instancePtr = masterPtr->instancePtr; instancePtr != NULL;
+ instancePtr = instancePtr->nextPtr) {
+ TkImgResetDither(instancePtr);
+ }
+
+ /*
+ * Tell the core image code that this image has changed.
+ */
+
+ Tk_ImageChanged(masterPtr->tkMaster, 0, 0, masterPtr->width,
+ masterPtr->height, masterPtr->width, masterPtr->height);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_PhotoExpand --
+ *
+ * This function is called to request that a photo image be expanded if
+ * necessary to be at least `width' pixels wide and `height' pixels high.
+ * If the user has declared a definite image size (using the -width and
+ * -height configuration options) then this call has no effect.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The size of the photo image may change; if so the generic image code
+ * is informed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_PhotoExpand(
+ Tcl_Interp *interp, /* Interpreter for passing back error
+ * messages, or NULL. */
+ Tk_PhotoHandle handle, /* Handle for the image to be expanded. */
+ int width, int height) /* Desired minimum dimensions of the image. */
+{
+ PhotoMaster *masterPtr = (PhotoMaster *) handle;
+
+ if (width <= masterPtr->width) {
+ width = masterPtr->width;
+ }
+ if (height <= masterPtr->height) {
+ height = masterPtr->height;
+ }
+ if ((width != masterPtr->width) || (height != masterPtr->height)) {
+ if (ImgPhotoSetSize(masterPtr, MAX(width, masterPtr->width),
+ MAX(height, masterPtr->height)) == TCL_ERROR) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1));
+ Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL);
+ }
+ return TCL_ERROR;
+ }
+ Tk_ImageChanged(masterPtr->tkMaster, 0, 0, 0, 0, masterPtr->width,
+ masterPtr->height);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_PhotoGetSize --
+ *
+ * This function is called to obtain the current size of a photo image.
+ *
+ * Results:
+ * The image's width and height are returned in *widthp and *heightp.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_PhotoGetSize(
+ Tk_PhotoHandle handle, /* Handle for the image whose dimensions are
+ * requested. */
+ int *widthPtr, int *heightPtr)
+ /* The dimensions of the image are returned
+ * here. */
+{
+ PhotoMaster *masterPtr = (PhotoMaster *) handle;
+
+ *widthPtr = masterPtr->width;
+ *heightPtr = masterPtr->height;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_PhotoSetSize --
+ *
+ * This function is called to set size of a photo image. This call is
+ * equivalent to using the -width and -height configuration options.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The size of the image may change; if so the generic image code is
+ * informed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_PhotoSetSize(
+ Tcl_Interp *interp, /* Interpreter for passing back error
+ * messages, or NULL. */
+ Tk_PhotoHandle handle, /* Handle for the image whose size is to be
+ * set. */
+ int width, int height) /* New dimensions for the image. */
+{
+ PhotoMaster *masterPtr = (PhotoMaster *) handle;
+
+ masterPtr->userWidth = width;
+ masterPtr->userHeight = height;
+ if (ImgPhotoSetSize(masterPtr, ((width > 0) ? width: masterPtr->width),
+ ((height > 0) ? height: masterPtr->height)) == TCL_ERROR) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1));
+ Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL);
+ }
+ return TCL_ERROR;
+ }
+ Tk_ImageChanged(masterPtr->tkMaster, 0, 0, 0, 0,
+ masterPtr->width, masterPtr->height);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkGetPhotoValidRegion --
+ *
+ * This function is called to get the part of the photo where there is
+ * valid data. Or, conversely, the part of the photo which is
+ * transparent.
+ *
+ * Results:
+ * A TkRegion value that indicates the current area of the photo that is
+ * valid. This value should not be used after any modification to the
+ * photo image.
+ *
+ * Side Effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkRegion
+TkPhotoGetValidRegion(
+ Tk_PhotoHandle handle) /* Handle for the image whose valid region is
+ * to obtained. */
+{
+ PhotoMaster *masterPtr = (PhotoMaster *) handle;
+
+ return masterPtr->validRegion;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImgGetPhoto --
+ *
+ * This function is called to obtain image data from a photo image. This
+ * function fills in the Tk_PhotoImageBlock structure pointed to by
+ * `blockPtr' with details of the address and layout of the image data in
+ * memory.
+ *
+ * Results:
+ * A pointer to the allocated data which should be freed later. NULL if
+ * there is no need to free data because blockPtr->pixelPtr points
+ * directly to the image data.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static char *
+ImgGetPhoto(
+ PhotoMaster *masterPtr, /* Handle for the photo image from which image
+ * data is desired. */
+ Tk_PhotoImageBlock *blockPtr,
+ /* Information about the address and layout of
+ * the image data is returned here. */
+ struct SubcommandOptions *optPtr)
+{
+ unsigned char *pixelPtr;
+ int x, y, greenOffset, blueOffset, alphaOffset;
+
+ Tk_PhotoGetImage((Tk_PhotoHandle) masterPtr, blockPtr);
+ blockPtr->pixelPtr += optPtr->fromY * blockPtr->pitch
+ + optPtr->fromX * blockPtr->pixelSize;
+ blockPtr->width = optPtr->fromX2 - optPtr->fromX;
+ blockPtr->height = optPtr->fromY2 - optPtr->fromY;
+
+ if (!(masterPtr->flags & COLOR_IMAGE) &&
+ (!(optPtr->options & OPT_BACKGROUND)
+ || ((optPtr->background->red == optPtr->background->green)
+ && (optPtr->background->red == optPtr->background->blue)))) {
+ blockPtr->offset[0] = blockPtr->offset[1] = blockPtr->offset[2];
+ }
+ alphaOffset = 0;
+ for (y = 0; y < blockPtr->height; y++) {
+ pixelPtr = blockPtr->pixelPtr + (y * blockPtr->pitch)
+ + blockPtr->pixelSize - 1;
+ for (x = 0; x < blockPtr->width; x++) {
+ if (*pixelPtr != 255) {
+ alphaOffset = 3;
+ break;
+ }
+ pixelPtr += blockPtr->pixelSize;
+ }
+ if (alphaOffset) {
+ break;
+ }
+ }
+ if (!alphaOffset) {
+ blockPtr->offset[3]= -1; /* Tell caller alpha need not be read */
+ }
+ greenOffset = blockPtr->offset[1] - blockPtr->offset[0];
+ blueOffset = blockPtr->offset[2] - blockPtr->offset[0];
+ if (((optPtr->options & OPT_BACKGROUND) && alphaOffset) ||
+ ((optPtr->options & OPT_GRAYSCALE) && (greenOffset||blueOffset))) {
+ int newPixelSize,x,y;
+ unsigned char *srcPtr, *destPtr;
+ char *data;
+
+ newPixelSize = (!(optPtr->options & OPT_BACKGROUND) && alphaOffset)
+ ? 2 : 1;
+ if ((greenOffset||blueOffset) && !(optPtr->options & OPT_GRAYSCALE)) {
+ newPixelSize += 2;
+ }
+
+ if (blockPtr->height > (int)((UINT_MAX/newPixelSize)/blockPtr->width)) {
+ return NULL;
+ }
+ data = attemptckalloc(newPixelSize*blockPtr->width*blockPtr->height);
+ if (data == NULL) {
+ return NULL;
+ }
+ srcPtr = blockPtr->pixelPtr + blockPtr->offset[0];
+ destPtr = (unsigned char *) data;
+ if (!greenOffset && !blueOffset) {
+ for (y = blockPtr->height; y > 0; y--) {
+ for (x = blockPtr->width; x > 0; x--) {
+ *destPtr = *srcPtr;
+ srcPtr += blockPtr->pixelSize;
+ destPtr += newPixelSize;
+ }
+ srcPtr += blockPtr->pitch -
+ blockPtr->width * blockPtr->pixelSize;
+ }
+ } else if (optPtr->options & OPT_GRAYSCALE) {
+ for (y = blockPtr->height; y > 0; y--) {
+ for (x = blockPtr->width; x > 0; x--) {
+ *destPtr = (unsigned char) ((srcPtr[0]*11 + srcPtr[1]*16
+ + srcPtr[2]*5 + 16) >> 5);
+ srcPtr += blockPtr->pixelSize;
+ destPtr += newPixelSize;
+ }
+ srcPtr += blockPtr->pitch -
+ blockPtr->width * blockPtr->pixelSize;
+ }
+ } else {
+ for (y = blockPtr->height; y > 0; y--) {
+ for (x = blockPtr->width; x > 0; x--) {
+ destPtr[0] = srcPtr[0];
+ destPtr[1] = srcPtr[1];
+ destPtr[2] = srcPtr[2];
+ srcPtr += blockPtr->pixelSize;
+ destPtr += newPixelSize;
+ }
+ srcPtr += blockPtr->pitch -
+ blockPtr->width * blockPtr->pixelSize;
+ }
+ }
+ srcPtr = blockPtr->pixelPtr + alphaOffset;
+ destPtr = (unsigned char *) data;
+ if (!alphaOffset) {
+ /*
+ * Nothing to be done.
+ */
+ } else if (optPtr->options & OPT_BACKGROUND) {
+ if (newPixelSize > 2) {
+ int red = optPtr->background->red>>8;
+ int green = optPtr->background->green>>8;
+ int blue = optPtr->background->blue>>8;
+
+ for (y = blockPtr->height; y > 0; y--) {
+ for (x = blockPtr->width; x > 0; x--) {
+ destPtr[0] += (unsigned char) (((255 - *srcPtr) *
+ (red-destPtr[0])) / 255);
+ destPtr[1] += (unsigned char) (((255 - *srcPtr) *
+ (green-destPtr[1])) / 255);
+ destPtr[2] += (unsigned char) (((255 - *srcPtr) *
+ (blue-destPtr[2])) / 255);
+ srcPtr += blockPtr->pixelSize;
+ destPtr += newPixelSize;
+ }
+ srcPtr += blockPtr->pitch -
+ blockPtr->width * blockPtr->pixelSize;
+ }
+ } else {
+ int gray = (unsigned char) (((optPtr->background->red>>8) * 11
+ + (optPtr->background->green>>8) * 16
+ + (optPtr->background->blue>>8) * 5 + 16) >> 5);
+
+ for (y = blockPtr->height; y > 0; y--) {
+ for (x = blockPtr->width; x > 0; x--) {
+ destPtr[0] += ((255 - *srcPtr) *
+ (gray-destPtr[0])) / 255;
+ srcPtr += blockPtr->pixelSize;
+ destPtr += newPixelSize;
+ }
+ srcPtr += blockPtr->pitch -
+ blockPtr->width * blockPtr->pixelSize;
+ }
+ }
+ } else {
+ destPtr += newPixelSize-1;
+ for (y = blockPtr->height; y > 0; y--) {
+ for (x = blockPtr->width; x > 0; x--) {
+ *destPtr = *srcPtr;
+ srcPtr += blockPtr->pixelSize;
+ destPtr += newPixelSize;
+ }
+ srcPtr += blockPtr->pitch -
+ blockPtr->width * blockPtr->pixelSize;
+ }
+ }
+ blockPtr->pixelPtr = (unsigned char *) data;
+ blockPtr->pixelSize = newPixelSize;
+ blockPtr->pitch = newPixelSize * blockPtr->width;
+ blockPtr->offset[0] = 0;
+ if (newPixelSize > 2) {
+ blockPtr->offset[1] = 1;
+ blockPtr->offset[2] = 2;
+ blockPtr->offset[3]= 3;
+ } else {
+ blockPtr->offset[1] = 0;
+ blockPtr->offset[2] = 0;
+ blockPtr->offset[3]= 1;
+ }
+ return data;
+ }
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImgStringWrite --
+ *
+ * Default string write function. The data is formatted in the default
+ * format as accepted by the "<img> put" command.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ImgStringWrite(
+ Tcl_Interp *interp,
+ Tcl_Obj *formatString,
+ Tk_PhotoImageBlock *blockPtr)
+{
+ int greenOffset, blueOffset;
+ Tcl_Obj *data;
+
+ greenOffset = blockPtr->offset[1] - blockPtr->offset[0];
+ blueOffset = blockPtr->offset[2] - blockPtr->offset[0];
+
+ data = Tcl_NewObj();
+ if ((blockPtr->width > 0) && (blockPtr->height > 0)) {
+ int row, col;
+
+ for (row=0; row<blockPtr->height; row++) {
+ Tcl_Obj *line = Tcl_NewObj();
+ unsigned char *pixelPtr = blockPtr->pixelPtr + blockPtr->offset[0]
+ + row * blockPtr->pitch;
+
+ for (col=0; col<blockPtr->width; col++) {
+ Tcl_AppendPrintfToObj(line, "%s#%02x%02x%02x",
+ col ? " " : "", *pixelPtr,
+ pixelPtr[greenOffset], pixelPtr[blueOffset]);
+ pixelPtr += blockPtr->pixelSize;
+ }
+ Tcl_ListObjAppendElement(NULL, data, line);
+ }
+ }
+ Tcl_SetObjResult(interp, data);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_PhotoGetImage --
+ *
+ * This function is called to obtain image data from a photo image. This
+ * function fills in the Tk_PhotoImageBlock structure pointed to by
+ * `blockPtr' with details of the address and layout of the image data in
+ * memory.
+ *
+ * Results:
+ * TRUE (1) indicating that image data is available, for backwards
+ * compatibility with the old photo widget.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_PhotoGetImage(
+ Tk_PhotoHandle handle, /* Handle for the photo image from which image
+ * data is desired. */
+ Tk_PhotoImageBlock *blockPtr)
+ /* Information about the address and layout of
+ * the image data is returned here. */
+{
+ PhotoMaster *masterPtr = (PhotoMaster *) handle;
+
+ blockPtr->pixelPtr = masterPtr->pix32;
+ blockPtr->width = masterPtr->width;
+ blockPtr->height = masterPtr->height;
+ blockPtr->pitch = masterPtr->width * 4;
+ blockPtr->pixelSize = 4;
+ blockPtr->offset[0] = 0;
+ blockPtr->offset[1] = 1;
+ blockPtr->offset[2] = 2;
+ blockPtr->offset[3] = 3;
+ return 1;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkPostscriptPhoto --
+ *
+ * This function is called to output the contents of a photo image in
+ * Postscript by calling the Tk_PostscriptPhoto function.
+ *
+ * Results:
+ * Returns a standard Tcl return value.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+ImgPhotoPostscript(
+ ClientData clientData, /* Handle for the photo image. */
+ Tcl_Interp *interp, /* Interpreter. */
+ Tk_Window tkwin, /* (unused) */
+ Tk_PostscriptInfo psInfo, /* Postscript info. */
+ int x, int y, /* First pixel to output. */
+ int width, int height, /* Width and height of area. */
+ int prepass) /* (unused) */
+{
+ Tk_PhotoImageBlock block;
+
+ Tk_PhotoGetImage(clientData, &block);
+ block.pixelPtr += y * block.pitch + x * block.pixelSize;
+
+ return Tk_PostscriptPhoto(interp, &block, psInfo, width, height);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_PhotoPutBlock_NoComposite, Tk_PhotoPutZoomedBlock_NoComposite --
+ *
+ * These backward-compatability functions just exist to fill slots in stubs
+ * table. For the behaviour of *_NoComposite, refer to the corresponding
+ * function without the extra suffix, except that the compositing rule is
+ * always "overlay" and the function always panics on memory-allocation
+ * failure.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_PhotoPutBlock_NoComposite(
+ Tk_PhotoHandle handle,
+ Tk_PhotoImageBlock *blockPtr,
+ int x, int y, int width, int height)
+{
+ if (Tk_PhotoPutBlock(NULL, handle, blockPtr, x, y, width, height,
+ TK_PHOTO_COMPOSITE_OVERLAY) != TCL_OK) {
+ Tcl_Panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE);
+ }
+}
+
+void
+Tk_PhotoPutZoomedBlock_NoComposite(
+ Tk_PhotoHandle handle,
+ Tk_PhotoImageBlock *blockPtr,
+ int x, int y, int width, int height,
+ int zoomX, int zoomY, int subsampleX, int subsampleY)
+{
+ if (Tk_PhotoPutZoomedBlock(NULL, handle, blockPtr, x, y, width, height,
+ zoomX, zoomY, subsampleX, subsampleY,
+ TK_PHOTO_COMPOSITE_OVERLAY) != TCL_OK) {
+ Tcl_Panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_PhotoExpand_Panic, Tk_PhotoPutBlock_Panic,
+ * Tk_PhotoPutZoomedBlock_Panic, Tk_PhotoSetSize_Panic
+ *
+ * Backward compatability functions for preserving the old behaviour (i.e.
+ * panic on memory allocation failure) so that extensions do not need to be
+ * significantly updated to take account of TIP #116. These call the new
+ * interface (i.e. the interface without the extra suffix), but panic if an
+ * error condition is returned.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_PhotoExpand_Panic(
+ Tk_PhotoHandle handle,
+ int width, int height)
+{
+ if (Tk_PhotoExpand(NULL, handle, width, height) != TCL_OK) {
+ Tcl_Panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE);
+ }
+}
+
+void
+Tk_PhotoPutBlock_Panic(
+ Tk_PhotoHandle handle,
+ Tk_PhotoImageBlock *blockPtr,
+ int x, int y, int width, int height, int compRule)
+{
+ if (Tk_PhotoPutBlock(NULL, handle, blockPtr, x, y, width, height,
+ compRule) != TCL_OK) {
+ Tcl_Panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE);
+ }
+}
+
+void
+Tk_PhotoPutZoomedBlock_Panic(
+ Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr,
+ int x, int y, int width, int height,
+ int zoomX, int zoomY, int subsampleX, int subsampleY,
+ int compRule)
+{
+ if (Tk_PhotoPutZoomedBlock(NULL, handle, blockPtr, x, y, width, height,
+ zoomX, zoomY, subsampleX, subsampleY, compRule) != TCL_OK) {
+ Tcl_Panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE);
+ }
+}
+
+void
+Tk_PhotoSetSize_Panic(
+ Tk_PhotoHandle handle,
+ int width, int height)
+{
+ if (Tk_PhotoSetSize(NULL, handle, width, height) != TCL_OK) {
+ Tcl_Panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE);
+ }
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkImgPhoto.h b/tk8.6/generic/tkImgPhoto.h
new file mode 100644
index 0000000..36bc6cb
--- /dev/null
+++ b/tk8.6/generic/tkImgPhoto.h
@@ -0,0 +1,262 @@
+/*
+ * tkImgPhoto.h --
+ *
+ * Declarations for images of type "photo" for Tk.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 2002-2008 Donal K. Fellows
+ * Copyright (c) 2003 ActiveState Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Author: Paul Mackerras (paulus@cs.anu.edu.au),
+ * Department of Computer Science,
+ * Australian National University.
+ */
+
+#include "tkInt.h"
+#ifdef _WIN32
+#include "tkWinInt.h"
+#elif defined(__CYGWIN__)
+#include "tkUnixInt.h"
+#endif
+
+/*
+ * Forward declarations of the structures we define.
+ */
+
+typedef struct ColorTableId ColorTableId;
+typedef struct ColorTable ColorTable;
+typedef struct PhotoInstance PhotoInstance;
+typedef struct PhotoMaster PhotoMaster;
+
+/*
+ * A signed 8-bit integral type. If chars are unsigned and the compiler isn't
+ * an ANSI one, then we have to use short instead (which wastes space) to get
+ * signed behavior.
+ */
+
+#if defined(__STDC__) || defined(_AIX)
+ typedef signed char schar;
+#else
+# ifndef __CHAR_UNSIGNED__
+ typedef char schar;
+# else
+ typedef short schar;
+# endif
+#endif
+
+/*
+ * An unsigned 32-bit integral type, used for pixel values. We use int rather
+ * than long here to accommodate those systems where longs are 64 bits.
+ */
+
+typedef unsigned int pixel;
+
+/*
+ * The maximum number of pixels to transmit to the server in a single
+ * XPutImage call.
+ */
+
+#define MAX_PIXELS 65536
+
+/*
+ * The set of colors required to display a photo image in a window depends on:
+ * - the visual used by the window
+ * - the palette, which specifies how many levels of each primary color to
+ * use, and
+ * - the gamma value for the image.
+ *
+ * Pixel values allocated for specific colors are valid only for the colormap
+ * in which they were allocated. Sets of pixel values allocated for displaying
+ * photos are re-used in other windows if possible, that is, if the display,
+ * colormap, palette and gamma values match. A hash table is used to locate
+ * these sets of pixel values, using the following data structure as key:
+ */
+
+struct ColorTableId {
+ Display *display; /* Qualifies the colormap resource ID. */
+ Colormap colormap; /* Colormap that the windows are using. */
+ double gamma; /* Gamma exponent value for images. */
+ Tk_Uid palette; /* Specifies how many shades of each primary
+ * we want to allocate. */
+};
+
+/*
+ * For a particular (display, colormap, palette, gamma) combination, a data
+ * structure of the following type is used to store the allocated pixel values
+ * and other information:
+ */
+
+struct ColorTable {
+ ColorTableId id; /* Information used in selecting this color
+ * table. */
+ int flags; /* See below. */
+ int refCount; /* Number of instances using this map. */
+ int liveRefCount; /* Number of instances which are actually in
+ * use, using this map. */
+ int numColors; /* Number of colors allocated for this map. */
+
+ XVisualInfo visualInfo; /* Information about the visual for windows
+ * using this color table. */
+
+ pixel redValues[256]; /* Maps 8-bit values of red intensity to a
+ * pixel value or index in pixelMap. */
+ pixel greenValues[256]; /* Ditto for green intensity. */
+ pixel blueValues[256]; /* Ditto for blue intensity. */
+ unsigned long *pixelMap; /* Actual pixel values allocated. */
+
+ unsigned char colorQuant[3][256];
+ /* Maps 8-bit intensities to quantized
+ * intensities. The first index is 0 for red,
+ * 1 for green, 2 for blue. */
+};
+
+/*
+ * Bit definitions for the flags field of a ColorTable.
+ * BLACK_AND_WHITE: 1 means only black and white colors are
+ * available.
+ * COLOR_WINDOW: 1 means a full 3-D color cube has been
+ * allocated.
+ * DISPOSE_PENDING: 1 means a call to DisposeColorTable has been
+ * scheduled as an idle handler, but it hasn't
+ * been invoked yet.
+ * MAP_COLORS: 1 means pixel values should be mapped through
+ * pixelMap.
+ */
+
+#ifdef COLOR_WINDOW
+#undef COLOR_WINDOW
+#endif
+
+#define BLACK_AND_WHITE 1
+#define COLOR_WINDOW 2
+#define DISPOSE_PENDING 4
+#define MAP_COLORS 8
+
+/*
+ * Definition of the data associated with each photo image master.
+ */
+
+struct PhotoMaster {
+ Tk_ImageMaster tkMaster; /* Tk's token for image master. NULL means the
+ * image is being deleted. */
+ Tcl_Interp *interp; /* Interpreter associated with the application
+ * using this image. */
+ Tcl_Command imageCmd; /* Token for image command (used to delete it
+ * when the image goes away). NULL means the
+ * image command has already been deleted. */
+ int flags; /* Sundry flags, defined below. */
+ int width, height; /* Dimensions of image. */
+ int userWidth, userHeight; /* User-declared image dimensions. */
+ Tk_Uid palette; /* User-specified default palette for
+ * instances of this image. */
+ double gamma; /* Display gamma value to correct for. */
+ char *fileString; /* Name of file to read into image. */
+ Tcl_Obj *dataString; /* Object to use as contents of image. */
+ Tcl_Obj *format; /* User-specified format of data in image file
+ * or string value. */
+ unsigned char *pix32; /* Local storage for 32-bit image. */
+ int ditherX, ditherY; /* Location of first incorrectly dithered
+ * pixel in image. */
+ TkRegion validRegion; /* Tk region indicating which parts of the
+ * image have valid image data. */
+ PhotoInstance *instancePtr; /* First in the list of instances associated
+ * with this master. */
+};
+
+/*
+ * Bit definitions for the flags field of a PhotoMaster.
+ * COLOR_IMAGE: 1 means that the image has different color
+ * components.
+ * IMAGE_CHANGED: 1 means that the instances of this image need
+ * to be redithered.
+ * COMPLEX_ALPHA: 1 means that the instances of this image have
+ * alpha values that aren't 0 or 255, and so need
+ * the copy-merge-replace renderer .
+ */
+
+#define COLOR_IMAGE 1
+#define IMAGE_CHANGED 2
+#define COMPLEX_ALPHA 4
+
+/*
+ * Flag to OR with the compositing rule to indicate that the source, despite
+ * having an alpha channel, has simple alpha.
+ */
+
+#define SOURCE_IS_SIMPLE_ALPHA_PHOTO 0x10000000
+
+/*
+ * The following data structure represents all of the instances of a photo
+ * image in windows on a given screen that are using the same colormap.
+ */
+
+struct PhotoInstance {
+ PhotoMaster *masterPtr; /* Pointer to master for image. */
+ Display *display; /* Display for windows using this instance. */
+ Colormap colormap; /* The image may only be used in windows with
+ * this particular colormap. */
+ PhotoInstance *nextPtr; /* Pointer to the next instance in the list of
+ * instances associated with this master. */
+ int refCount; /* Number of instances using this structure. */
+ Tk_Uid palette; /* Palette for these particular instances. */
+ double gamma; /* Gamma value for these instances. */
+ Tk_Uid defaultPalette; /* Default palette to use if a palette is not
+ * specified for the master. */
+ ColorTable *colorTablePtr; /* Pointer to information about colors
+ * allocated for image display in windows like
+ * this one. */
+ Pixmap pixels; /* X pixmap containing dithered image. */
+ int width, height; /* Dimensions of the pixmap. */
+ schar *error; /* Error image, used in dithering. */
+ XImage *imagePtr; /* Image structure for converted pixels. */
+ XVisualInfo visualInfo; /* Information about the visual that these
+ * windows are using. */
+ GC gc; /* Graphics context for writing images to the
+ * pixmap. */
+};
+
+/*
+ * Implementation of the Porter-Duff Source-Over compositing rule.
+ */
+
+#define PD_SRC_OVER(srcColor, srcAlpha, dstColor, dstAlpha) \
+ (srcColor*srcAlpha/255) + dstAlpha*(255-srcAlpha)/255*dstColor/255
+#define PD_SRC_OVER_ALPHA(srcAlpha, dstAlpha) \
+ (srcAlpha + (255-srcAlpha)*dstAlpha/255)
+
+#undef MIN
+#define MIN(a, b) ((a) < (b)? (a): (b))
+#undef MAX
+#define MAX(a, b) ((a) > (b)? (a): (b))
+
+/*
+ * Declarations of functions shared between the different parts of the
+ * photo image implementation.
+ */
+
+MODULE_SCOPE void TkImgPhotoConfigureInstance(
+ PhotoInstance *instancePtr);
+MODULE_SCOPE void TkImgDisposeInstance(ClientData clientData);
+MODULE_SCOPE void TkImgPhotoInstanceSetSize(PhotoInstance *instancePtr);
+MODULE_SCOPE ClientData TkImgPhotoGet(Tk_Window tkwin, ClientData clientData);
+MODULE_SCOPE void TkImgDitherInstance(PhotoInstance *instancePtr, int x,
+ int y, int width, int height);
+MODULE_SCOPE void TkImgPhotoDisplay(ClientData clientData,
+ Display *display, Drawable drawable,
+ int imageX, int imageY, int width, int height,
+ int drawableX, int drawableY);
+MODULE_SCOPE void TkImgPhotoFree(ClientData clientData,
+ Display *display);
+MODULE_SCOPE void TkImgResetDither(PhotoInstance *instancePtr);
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkImgUtil.c b/tk8.6/generic/tkImgUtil.c
new file mode 100644
index 0000000..5487165
--- /dev/null
+++ b/tk8.6/generic/tkImgUtil.c
@@ -0,0 +1,83 @@
+/*
+ * tkImgUtil.c --
+ *
+ * This file contains image related utility functions.
+ *
+ * Copyright (c) 1995 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkInt.h"
+#include "xbytes.h"
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkAlignImageData --
+ *
+ * This function takes an image and copies the data into an aligned
+ * buffer, performing any necessary bit swapping.
+ *
+ * Results:
+ * Returns a newly allocated buffer that should be freed by the caller.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+TkAlignImageData(
+ XImage *image, /* Image to be aligned. */
+ int alignment, /* Number of bytes to which the data should be
+ * aligned (e.g. 2 or 4) */
+ int bitOrder) /* Desired bit order: LSBFirst or MSBFirst. */
+{
+ long dataWidth;
+ char *data, *srcPtr, *destPtr;
+ int i, j;
+
+ if (image->bits_per_pixel != 1) {
+ Tcl_Panic(
+ "TkAlignImageData: Can't handle image depths greater than 1.");
+ }
+
+ /*
+ * Compute line width for output data buffer.
+ */
+
+ dataWidth = image->bytes_per_line;
+ if (dataWidth % alignment) {
+ dataWidth += (alignment - (dataWidth % alignment));
+ }
+
+ data = ckalloc(dataWidth * image->height);
+
+ destPtr = data;
+ for (i = 0; i < image->height; i++) {
+ srcPtr = &image->data[i * image->bytes_per_line];
+ for (j = 0; j < dataWidth; j++) {
+ if (j >= image->bytes_per_line) {
+ *destPtr = 0;
+ } else if (image->bitmap_bit_order != bitOrder) {
+ *destPtr = xBitReverseTable[(unsigned char)(*(srcPtr++))];
+ } else {
+ *destPtr = *(srcPtr++);
+ }
+ destPtr++;
+ }
+ }
+ return data;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkInt.decls b/tk8.6/generic/tkInt.decls
new file mode 100644
index 0000000..a3e1f98
--- /dev/null
+++ b/tk8.6/generic/tkInt.decls
@@ -0,0 +1,1822 @@
+# tkInt.decls --
+#
+# This file contains the declarations for all unsupported functions that
+# are exported by the Tk library. This file is used to generate the
+# tkIntDecls.h, tkIntPlatDecls.h, tkIntStub.c, and tkPlatStub.c files.
+#
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+library tk
+
+##############################################################################
+
+# Define the unsupported generic interfaces.
+
+interface tkInt
+scspec EXTERN
+
+# Declare each of the functions in the unsupported internal Tcl interface.
+# These interfaces are allowed to changed between versions. Use at your own
+# risk. Note that the position of functions should not be changed between
+# versions to avoid gratuitous incompatibilities.
+
+declare 0 {
+ TkWindow *TkAllocWindow(TkDisplay *dispPtr, int screenNum,
+ TkWindow *parentPtr)
+}
+declare 1 {
+ void TkBezierPoints(double control[], int numSteps, double *coordPtr)
+}
+declare 2 {
+ void TkBezierScreenPoints(Tk_Canvas canvas, double control[],
+ int numSteps, XPoint *xPointPtr)
+}
+#
+# Slot 3 unused (WAS: TkBindDeadWindow)
+#
+declare 4 {
+ void TkBindEventProc(TkWindow *winPtr, XEvent *eventPtr)
+}
+declare 5 {
+ void TkBindFree(TkMainInfo *mainPtr)
+}
+declare 6 {
+ void TkBindInit(TkMainInfo *mainPtr)
+}
+declare 7 {
+ void TkChangeEventWindow(XEvent *eventPtr, TkWindow *winPtr)
+}
+declare 8 {
+ int TkClipInit(Tcl_Interp *interp, TkDisplay *dispPtr)
+}
+declare 9 {
+ void TkComputeAnchor(Tk_Anchor anchor, Tk_Window tkwin, int padX, int padY,
+ int innerWidth, int innerHeight, int *xPtr, int *yPtr)
+}
+#
+# Slot 10 unused (WAS: TkCopyAndGlobalEval)
+# Slot 11 unused (WAS: TkCreateBindingProcedure)
+#
+declare 12 {
+ TkCursor *TkCreateCursorFromData(Tk_Window tkwin,
+ const char *source, const char *mask, int width, int height,
+ int xHot, int yHot, XColor fg, XColor bg)
+}
+declare 13 {
+ int TkCreateFrame(ClientData clientData, Tcl_Interp *interp,
+ int argc, const char *const *argv, int toplevel, const char *appName)
+}
+declare 14 {
+ Tk_Window TkCreateMainWindow(Tcl_Interp *interp,
+ const char *screenName, const char *baseName)
+}
+declare 15 {
+ Time TkCurrentTime(TkDisplay *dispPtr)
+}
+declare 16 {
+ void TkDeleteAllImages(TkMainInfo *mainPtr)
+}
+declare 17 {
+ void TkDoConfigureNotify(TkWindow *winPtr)
+}
+declare 18 {
+ void TkDrawInsetFocusHighlight(Tk_Window tkwin, GC gc, int width,
+ Drawable drawable, int padding)
+}
+declare 19 {
+ void TkEventDeadWindow(TkWindow *winPtr)
+}
+declare 20 {
+ void TkFillPolygon(Tk_Canvas canvas, double *coordPtr, int numPoints,
+ Display *display, Drawable drawable, GC gc, GC outlineGC)
+}
+declare 21 {
+ int TkFindStateNum(Tcl_Interp *interp, const char *option,
+ const TkStateMap *mapPtr, const char *strKey)
+}
+declare 22 {
+ CONST86 char *TkFindStateString(const TkStateMap *mapPtr, int numKey)
+}
+declare 23 {
+ void TkFocusDeadWindow(TkWindow *winPtr)
+}
+declare 24 {
+ int TkFocusFilterEvent(TkWindow *winPtr, XEvent *eventPtr)
+}
+declare 25 {
+ TkWindow *TkFocusKeyEvent(TkWindow *winPtr, XEvent *eventPtr)
+}
+declare 26 {
+ void TkFontPkgInit(TkMainInfo *mainPtr)
+}
+declare 27 {
+ void TkFontPkgFree(TkMainInfo *mainPtr)
+}
+declare 28 {
+ void TkFreeBindingTags(TkWindow *winPtr)
+}
+
+# Name change only, TkFreeCursor in Tcl 8.0.x now TkpFreeCursor
+declare 29 {
+ void TkpFreeCursor(TkCursor *cursorPtr)
+}
+declare 30 {
+ char *TkGetBitmapData(Tcl_Interp *interp, const char *string,
+ const char *fileName, int *widthPtr, int *heightPtr,
+ int *hotXPtr, int *hotYPtr)
+}
+declare 31 {
+ void TkGetButtPoints(double p1[], double p2[],
+ double width, int project, double m1[], double m2[])
+}
+declare 32 {
+ TkCursor *TkGetCursorByName(Tcl_Interp *interp,
+ Tk_Window tkwin, Tk_Uid string)
+}
+declare 33 {
+ const char *TkGetDefaultScreenName(Tcl_Interp *interp,
+ const char *screenName)
+}
+declare 34 {
+ TkDisplay *TkGetDisplay(Display *display)
+}
+declare 35 {
+ int TkGetDisplayOf(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[],
+ Tk_Window *tkwinPtr)
+}
+declare 36 {
+ TkWindow *TkGetFocusWin(TkWindow *winPtr)
+}
+declare 37 {
+ int TkGetInterpNames(Tcl_Interp *interp, Tk_Window tkwin)
+}
+declare 38 {
+ int TkGetMiterPoints(double p1[], double p2[], double p3[],
+ double width, double m1[], double m2[])
+}
+declare 39 {
+ void TkGetPointerCoords(Tk_Window tkwin, int *xPtr, int *yPtr)
+}
+declare 40 {
+ void TkGetServerInfo(Tcl_Interp *interp, Tk_Window tkwin)
+}
+declare 41 {
+ void TkGrabDeadWindow(TkWindow *winPtr)
+}
+declare 42 {
+ int TkGrabState(TkWindow *winPtr)
+}
+declare 43 {
+ void TkIncludePoint(Tk_Item *itemPtr, double *pointPtr)
+}
+declare 44 {
+ void TkInOutEvents(XEvent *eventPtr, TkWindow *sourcePtr,
+ TkWindow *destPtr, int leaveType, int enterType,
+ Tcl_QueuePosition position)
+}
+declare 45 {
+ void TkInstallFrameMenu(Tk_Window tkwin)
+}
+declare 46 {
+ CONST86 char *TkKeysymToString(KeySym keysym)
+}
+declare 47 {
+ int TkLineToArea(double end1Ptr[], double end2Ptr[], double rectPtr[])
+}
+declare 48 {
+ double TkLineToPoint(double end1Ptr[], double end2Ptr[], double pointPtr[])
+}
+declare 49 {
+ int TkMakeBezierCurve(Tk_Canvas canvas, double *pointPtr, int numPoints,
+ int numSteps, XPoint xPoints[], double dblPoints[])
+}
+declare 50 {
+ void TkMakeBezierPostscript(Tcl_Interp *interp,
+ Tk_Canvas canvas, double *pointPtr, int numPoints)
+}
+declare 51 {
+ void TkOptionClassChanged(TkWindow *winPtr)
+}
+declare 52 {
+ void TkOptionDeadWindow(TkWindow *winPtr)
+}
+declare 53 {
+ int TkOvalToArea(double *ovalPtr, double *rectPtr)
+}
+declare 54 {
+ double TkOvalToPoint(double ovalPtr[],
+ double width, int filled, double pointPtr[])
+}
+declare 55 {
+ int TkpChangeFocus(TkWindow *winPtr, int force)
+}
+declare 56 {
+ void TkpCloseDisplay(TkDisplay *dispPtr)
+}
+declare 57 {
+ void TkpClaimFocus(TkWindow *topLevelPtr, int force)
+}
+declare 58 {
+ void TkpDisplayWarning(const char *msg, const char *title)
+}
+declare 59 {
+ void TkpGetAppName(Tcl_Interp *interp, Tcl_DString *name)
+}
+declare 60 {
+ TkWindow *TkpGetOtherWindow(TkWindow *winPtr)
+}
+declare 61 {
+ TkWindow *TkpGetWrapperWindow(TkWindow *winPtr)
+}
+declare 62 {
+ int TkpInit(Tcl_Interp *interp)
+}
+declare 63 {
+ void TkpInitializeMenuBindings(Tcl_Interp *interp,
+ Tk_BindingTable bindingTable)
+}
+declare 64 {
+ void TkpMakeContainer(Tk_Window tkwin)
+}
+declare 65 {
+ void TkpMakeMenuWindow(Tk_Window tkwin, int transient)
+}
+declare 66 {
+ Window TkpMakeWindow(TkWindow *winPtr, Window parent)
+}
+declare 67 {
+ void TkpMenuNotifyToplevelCreate(Tcl_Interp *interp, const char *menuName)
+}
+declare 68 {
+ TkDisplay *TkpOpenDisplay(const char *display_name)
+}
+declare 69 {
+ int TkPointerEvent(XEvent *eventPtr, TkWindow *winPtr)
+}
+declare 70 {
+ int TkPolygonToArea(double *polyPtr, int numPoints, double *rectPtr)
+}
+declare 71 {
+ double TkPolygonToPoint(double *polyPtr, int numPoints, double *pointPtr)
+}
+declare 72 {
+ int TkPositionInTree(TkWindow *winPtr, TkWindow *treePtr)
+}
+declare 73 {
+ void TkpRedirectKeyEvent(TkWindow *winPtr, XEvent *eventPtr)
+}
+declare 74 {
+ void TkpSetMainMenubar(Tcl_Interp *interp, Tk_Window tkwin, const char *menuName)
+}
+declare 75 {
+ int TkpUseWindow(Tcl_Interp *interp, Tk_Window tkwin, const char *string)
+}
+#
+# Slot 76 unused (WAS: TkpWindowWasRecentlyDeleted)
+#
+declare 77 {
+ void TkQueueEventForAllChildren(TkWindow *winPtr, XEvent *eventPtr)
+}
+declare 78 {
+ int TkReadBitmapFile(Display *display, Drawable d, const char *filename,
+ unsigned int *width_return, unsigned int *height_return,
+ Pixmap *bitmap_return, int *x_hot_return, int *y_hot_return)
+}
+declare 79 {
+ int TkScrollWindow(Tk_Window tkwin, GC gc, int x, int y,
+ int width, int height, int dx, int dy, TkRegion damageRgn)
+}
+declare 80 {
+ void TkSelDeadWindow(TkWindow *winPtr)
+}
+declare 81 {
+ void TkSelEventProc(Tk_Window tkwin, XEvent *eventPtr)
+}
+declare 82 {
+ void TkSelInit(Tk_Window tkwin)
+}
+declare 83 {
+ void TkSelPropProc(XEvent *eventPtr)
+}
+
+# Exported publically as Tk_SetClassProcs in 8.4a2
+#declare 84 {
+# void TkSetClassProcs(Tk_Window tkwin,
+# TkClassProcs *procs, ClientData instanceData)
+#}
+declare 85 {
+ void TkSetWindowMenuBar(Tcl_Interp *interp, Tk_Window tkwin,
+ const char *oldMenuName, const char *menuName)
+}
+declare 86 {
+ KeySym TkStringToKeysym(const char *name)
+}
+declare 87 {
+ int TkThickPolyLineToArea(double *coordPtr, int numPoints,
+ double width, int capStyle, int joinStyle, double *rectPtr)
+}
+declare 88 {
+ void TkWmAddToColormapWindows(TkWindow *winPtr)
+}
+declare 89 {
+ void TkWmDeadWindow(TkWindow *winPtr)
+}
+declare 90 {
+ TkWindow *TkWmFocusToplevel(TkWindow *winPtr)
+}
+declare 91 {
+ void TkWmMapWindow(TkWindow *winPtr)
+}
+declare 92 {
+ void TkWmNewWindow(TkWindow *winPtr)
+}
+declare 93 {
+ void TkWmProtocolEventProc(TkWindow *winPtr, XEvent *evenvPtr)
+}
+declare 94 {
+ void TkWmRemoveFromColormapWindows(TkWindow *winPtr)
+}
+declare 95 {
+ void TkWmRestackToplevel(TkWindow *winPtr, int aboveBelow,
+ TkWindow *otherPtr)
+}
+declare 96 {
+ void TkWmSetClass(TkWindow *winPtr)
+}
+declare 97 {
+ void TkWmUnmapWindow(TkWindow *winPtr)
+}
+
+# new for 8.1
+
+declare 98 {
+ Tcl_Obj *TkDebugBitmap(Tk_Window tkwin, const char *name)
+}
+declare 99 {
+ Tcl_Obj *TkDebugBorder(Tk_Window tkwin, const char *name)
+}
+declare 100 {
+ Tcl_Obj *TkDebugCursor(Tk_Window tkwin, const char *name)
+}
+declare 101 {
+ Tcl_Obj *TkDebugColor(Tk_Window tkwin, const char *name)
+}
+declare 102 {
+ Tcl_Obj *TkDebugConfig(Tcl_Interp *interp, Tk_OptionTable table)
+}
+declare 103 {
+ Tcl_Obj *TkDebugFont(Tk_Window tkwin, const char *name)
+}
+declare 104 {
+ int TkFindStateNumObj(Tcl_Interp *interp, Tcl_Obj *optionPtr,
+ const TkStateMap *mapPtr, Tcl_Obj *keyPtr)
+}
+declare 105 {
+ Tcl_HashTable *TkGetBitmapPredefTable(void)
+}
+declare 106 {
+ TkDisplay *TkGetDisplayList(void)
+}
+declare 107 {
+ TkMainInfo *TkGetMainInfoList(void)
+}
+declare 108 {
+ int TkGetWindowFromObj(Tcl_Interp *interp, Tk_Window tkwin,
+ Tcl_Obj *objPtr, Tk_Window *windowPtr)
+}
+declare 109 {
+ CONST86 char *TkpGetString(TkWindow *winPtr, XEvent *eventPtr, Tcl_DString *dsPtr)
+}
+declare 110 {
+ void TkpGetSubFonts(Tcl_Interp *interp, Tk_Font tkfont)
+}
+declare 111 {
+ Tcl_Obj *TkpGetSystemDefault(Tk_Window tkwin,
+ const char *dbName, const char *className)
+}
+declare 112 {
+ void TkpMenuThreadInit(void)
+}
+declare 113 {
+ void TkClipBox(TkRegion rgn, XRectangle *rect_return)
+}
+declare 114 {
+ TkRegion TkCreateRegion(void)
+}
+declare 115 {
+ void TkDestroyRegion(TkRegion rgn)
+}
+declare 116 {
+ void TkIntersectRegion(TkRegion sra, TkRegion srcb, TkRegion dr_return)
+}
+declare 117 {
+ int TkRectInRegion(TkRegion rgn, int x, int y, unsigned int width,
+ unsigned int height)
+}
+declare 118 {
+ void TkSetRegion(Display *display, GC gc, TkRegion rgn)
+}
+declare 119 {
+ void TkUnionRectWithRegion(XRectangle *rect,
+ TkRegion src, TkRegion dr_return)
+}
+declare 121 aqua {
+ Pixmap TkpCreateNativeBitmap(Display *display, const void *source)
+}
+declare 122 aqua {
+ void TkpDefineNativeBitmaps(void)
+}
+declare 124 aqua {
+ Pixmap TkpGetNativeAppBitmap(Display *display,
+ const char *name, int *width, int *height)
+}
+declare 135 {
+ void TkpDrawHighlightBorder(Tk_Window tkwin, GC fgGC, GC bgGC,
+ int highlightWidth, Drawable drawable)
+}
+declare 136 {
+ void TkSetFocusWin(TkWindow *winPtr, int force)
+}
+declare 137 {
+ void TkpSetKeycodeAndState(Tk_Window tkwin, KeySym keySym,
+ XEvent *eventPtr)
+}
+declare 138 {
+ KeySym TkpGetKeySym(TkDisplay *dispPtr, XEvent *eventPtr)
+}
+declare 139 {
+ void TkpInitKeymapInfo(TkDisplay *dispPtr)
+}
+declare 140 {
+ TkRegion TkPhotoGetValidRegion(Tk_PhotoHandle handle)
+}
+declare 141 {
+ TkWindow **TkWmStackorderToplevel(TkWindow *parentPtr)
+}
+declare 142 {
+ void TkFocusFree(TkMainInfo *mainPtr)
+}
+declare 143 {
+ void TkClipCleanup(TkDisplay *dispPtr)
+}
+declare 144 {
+ void TkGCCleanup(TkDisplay *dispPtr)
+}
+declare 145 {
+ void TkSubtractRegion(TkRegion sra, TkRegion srcb, TkRegion dr_return)
+}
+declare 146 {
+ void TkStylePkgInit(TkMainInfo *mainPtr)
+}
+declare 147 {
+ void TkStylePkgFree(TkMainInfo *mainPtr)
+}
+declare 148 {
+ Tk_Window TkToplevelWindowForCommand(Tcl_Interp *interp,
+ const char *cmdName)
+}
+declare 149 {
+ const Tk_OptionSpec *TkGetOptionSpec(const char *name,
+ Tk_OptionTable optionTable)
+}
+
+# TIP#168
+declare 150 {
+ int TkMakeRawCurve(Tk_Canvas canvas, double *pointPtr, int numPoints,
+ int numSteps, XPoint xPoints[], double dblPoints[])
+}
+declare 151 {
+ void TkMakeRawCurvePostscript(Tcl_Interp *interp,
+ Tk_Canvas canvas, double *pointPtr, int numPoints)
+}
+declare 152 {
+ void TkpDrawFrame(Tk_Window tkwin, Tk_3DBorder border,
+ int highlightWidth, int borderWidth, int relief)
+}
+declare 153 {
+ void TkCreateThreadExitHandler(Tcl_ExitProc *proc, ClientData clientData)
+}
+declare 154 {
+ void TkDeleteThreadExitHandler(Tcl_ExitProc *proc, ClientData clientData)
+}
+
+# entries needed only by tktest:
+declare 156 {
+ int TkpTestembedCmd(ClientData clientData, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[])
+}
+declare 157 {
+ int TkpTesttextCmd(ClientData dummy, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[])
+}
+declare 158 {
+ int TkSelGetSelection(Tcl_Interp *interp, Tk_Window tkwin,
+ Atom selection, Atom target, Tk_GetSelProc *proc,
+ ClientData clientData)
+}
+declare 159 {
+ int TkTextGetIndex(Tcl_Interp *interp, struct TkText *textPtr,
+ const char *string, struct TkTextIndex *indexPtr)
+}
+declare 160 {
+ int TkTextIndexBackBytes(const struct TkText *textPtr,
+ const struct TkTextIndex *srcPtr, int count,
+ struct TkTextIndex *dstPtr)
+}
+declare 161 {
+ int TkTextIndexForwBytes(const struct TkText *textPtr,
+ const struct TkTextIndex *srcPtr, int count,
+ struct TkTextIndex *dstPtr)
+}
+declare 162 {
+ struct TkTextIndex *TkTextMakeByteIndex(TkTextBTree tree,
+ const struct TkText *textPtr, int lineIndex,
+ int byteIndex, struct TkTextIndex *indexPtr)
+}
+declare 163 {
+ int TkTextPrintIndex(const struct TkText *textPtr,
+ const struct TkTextIndex *indexPtr, char *string)
+}
+declare 164 {
+ struct TkTextSegment *TkTextSetMark(struct TkText *textPtr,
+ const char *name, struct TkTextIndex *indexPtr)
+}
+declare 165 {
+ int TkTextXviewCmd(struct TkText *textPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 166 {
+ void TkTextChanged(struct TkSharedText *sharedTextPtr,
+ struct TkText *textPtr, const struct TkTextIndex *index1Ptr,
+ const struct TkTextIndex *index2Ptr)
+}
+declare 167 {
+ int TkBTreeNumLines(TkTextBTree tree,
+ const struct TkText *textPtr)
+}
+declare 168 {
+ void TkTextInsertDisplayProc(struct TkText *textPtr,
+ struct TkTextDispChunk *chunkPtr, int x, int y,
+ int height, int baseline, Display *display,
+ Drawable dst, int screenY)
+}
+# Next group of functions exposed due to [Bug 2768945].
+declare 169 {
+ int TkStateParseProc(ClientData clientData, Tcl_Interp *interp,
+ Tk_Window tkwin, const char *value, char *widgRec, int offset)
+}
+declare 170 {
+ CONST86 char *TkStatePrintProc(ClientData clientData, Tk_Window tkwin,
+ char *widgRec, int offset, Tcl_FreeProc **freeProcPtr)
+}
+declare 171 {
+ int TkCanvasDashParseProc(ClientData clientData, Tcl_Interp *interp,
+ Tk_Window tkwin, const char *value, char *widgRec, int offset)
+}
+declare 172 {
+ CONST86 char *TkCanvasDashPrintProc(ClientData clientData, Tk_Window tkwin,
+ char *widgRec, int offset, Tcl_FreeProc **freeProcPtr)
+}
+declare 173 {
+ int TkOffsetParseProc(ClientData clientData, Tcl_Interp *interp,
+ Tk_Window tkwin, const char *value, char *widgRec, int offset)
+}
+declare 174 {
+ CONST86 char *TkOffsetPrintProc(ClientData clientData, Tk_Window tkwin,
+ char *widgRec, int offset, Tcl_FreeProc **freeProcPtr)
+}
+declare 175 {
+ int TkPixelParseProc(ClientData clientData, Tcl_Interp *interp,
+ Tk_Window tkwin, const char *value, char *widgRec, int offset)
+}
+declare 176 {
+ CONST86 char *TkPixelPrintProc(ClientData clientData, Tk_Window tkwin,
+ char *widgRec, int offset, Tcl_FreeProc **freeProcPtr)
+}
+declare 177 {
+ int TkOrientParseProc(ClientData clientData, Tcl_Interp *interp,
+ Tk_Window tkwin, const char *value, char *widgRec, int offset)
+}
+declare 178 {
+ CONST86 char *TkOrientPrintProc(ClientData clientData, Tk_Window tkwin,
+ char *widgRec, int offset, Tcl_FreeProc **freeProcPtr)
+}
+declare 179 {
+ int TkSmoothParseProc(ClientData clientData, Tcl_Interp *interp,
+ Tk_Window tkwin, const char *value, char *widgRec, int offset)
+}
+declare 180 {
+ CONST86 char *TkSmoothPrintProc(ClientData clientData, Tk_Window tkwin,
+ char *widgRec, int offset, Tcl_FreeProc **freeProcPtr)
+}
+
+# Angled text API, exposed for Emiliano Gavilán's RBC work.
+declare 181 {
+ void TkDrawAngledTextLayout(Display *display, Drawable drawable, GC gc,
+ Tk_TextLayout layout, int x, int y, double angle, int firstChar,
+ int lastChar)
+}
+declare 182 {
+ void TkUnderlineAngledTextLayout(Display *display, Drawable drawable,
+ GC gc, Tk_TextLayout layout, int x, int y, double angle,
+ int underline)
+}
+declare 183 {
+ int TkIntersectAngledTextLayout(Tk_TextLayout layout, int x, int y,
+ int width, int height, double angle)
+}
+declare 184 {
+ void TkDrawAngledChars(Display *display,Drawable drawable, GC gc,
+ Tk_Font tkfont, const char *source, int numBytes, double x,
+ double y, double angle)
+}
+
+##############################################################################
+
+# Define the platform specific internal Tcl interface. These functions are
+# only available on the designated platform.
+
+interface tkIntPlat
+
+################################
+# Unix specific functions
+
+declare 0 x11 {
+ void TkCreateXEventSource(void)
+}
+#
+# Slot 1 unused (WAS: TkFreeWindowId)
+# Slot 2 unused (WAS: TkInitXId)
+#
+declare 3 x11 {
+ int TkpCmapStressed(Tk_Window tkwin, Colormap colormap)
+}
+declare 4 x11 {
+ void TkpSync(Display *display)
+}
+declare 5 x11 {
+ Window TkUnixContainerId(TkWindow *winPtr)
+}
+declare 6 x11 {
+ int TkUnixDoOneXEvent(Tcl_Time *timePtr)
+}
+declare 7 x11 {
+ void TkUnixSetMenubar(Tk_Window tkwin, Tk_Window menubar)
+}
+declare 8 x11 {
+ int TkpScanWindowId(Tcl_Interp *interp, const char *string, Window *idPtr)
+}
+declare 9 x11 {
+ void TkWmCleanup(TkDisplay *dispPtr)
+}
+declare 10 x11 {
+ void TkSendCleanup(TkDisplay *dispPtr)
+}
+#
+# Slot 11 unused (WAS: TkFreeXId)
+#
+declare 12 x11 {
+ int TkpWmSetState(TkWindow *winPtr, int state)
+}
+# only needed by tktest:
+declare 13 x11 {
+ int TkpTestsendCmd(ClientData clientData, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[])
+}
+
+################################
+# Windows specific functions
+
+declare 0 win {
+ char *TkAlignImageData(XImage *image, int alignment, int bitOrder)
+}
+declare 2 win {
+ void TkGenerateActivateEvents(TkWindow *winPtr, int active)
+}
+declare 3 win {
+ unsigned long TkpGetMS(void)
+}
+declare 4 win {
+ void TkPointerDeadWindow(TkWindow *winPtr)
+}
+declare 5 win {
+ void TkpPrintWindowId(char *buf, Window window)
+}
+declare 6 win {
+ int TkpScanWindowId(Tcl_Interp *interp, const char *string, Window *idPtr)
+}
+declare 7 win {
+ void TkpSetCapture(TkWindow *winPtr)
+}
+declare 8 win {
+ void TkpSetCursor(TkpCursor cursor)
+}
+declare 9 win {
+ int TkpWmSetState(TkWindow *winPtr, int state)
+}
+declare 10 win {
+ void TkSetPixmapColormap(Pixmap pixmap, Colormap colormap)
+}
+declare 11 win {
+ void TkWinCancelMouseTimer(void)
+}
+declare 12 win {
+ void TkWinClipboardRender(TkDisplay *dispPtr, UINT format)
+}
+declare 13 win {
+ LRESULT TkWinEmbeddedEventProc(HWND hwnd, UINT message,
+ WPARAM wParam, LPARAM lParam)
+}
+declare 14 win {
+ void TkWinFillRect(HDC dc, int x, int y, int width, int height, int pixel)
+}
+declare 15 win {
+ COLORREF TkWinGetBorderPixels(Tk_Window tkwin, Tk_3DBorder border,
+ int which)
+}
+declare 16 win {
+ HDC TkWinGetDrawableDC(Display *display, Drawable d, TkWinDCState *state)
+}
+declare 17 win {
+ int TkWinGetModifierState(void)
+}
+declare 18 win {
+ HPALETTE TkWinGetSystemPalette(void)
+}
+declare 19 win {
+ HWND TkWinGetWrapperWindow(Tk_Window tkwin)
+}
+declare 20 win {
+ int TkWinHandleMenuEvent(HWND *phwnd, UINT *pMessage, WPARAM *pwParam,
+ LPARAM *plParam, LRESULT *plResult)
+}
+declare 21 win {
+ int TkWinIndexOfColor(XColor *colorPtr)
+}
+declare 22 win {
+ void TkWinReleaseDrawableDC(Drawable d, HDC hdc, TkWinDCState *state)
+}
+declare 23 win {
+ LRESULT TkWinResendEvent(WNDPROC wndproc, HWND hwnd, XEvent *eventPtr)
+}
+declare 24 win {
+ HPALETTE TkWinSelectPalette(HDC dc, Colormap colormap)
+}
+declare 25 win {
+ void TkWinSetMenu(Tk_Window tkwin, HMENU hMenu)
+}
+declare 26 win {
+ void TkWinSetWindowPos(HWND hwnd, HWND siblingHwnd, int pos)
+}
+declare 27 win {
+ void TkWinWmCleanup(HINSTANCE hInstance)
+}
+declare 28 win {
+ void TkWinXCleanup(ClientData clientData)
+}
+declare 29 win {
+ void TkWinXInit(HINSTANCE hInstance)
+}
+
+# new for 8.1
+
+declare 30 win {
+ void TkWinSetForegroundWindow(TkWindow *winPtr)
+}
+declare 31 win {
+ void TkWinDialogDebug(int debug)
+}
+declare 32 win {
+ Tcl_Obj *TkWinGetMenuSystemDefault(Tk_Window tkwin,
+ const char *dbName, const char *className)
+}
+declare 33 win {
+ int TkWinGetPlatformId(void)
+}
+
+# new for 8.4.1
+
+declare 34 win {
+ void TkWinSetHINSTANCE(HINSTANCE hInstance)
+}
+declare 35 win {
+ int TkWinGetPlatformTheme(void)
+}
+
+# Exported through stub table since Tk 8.4.20/8.5.9
+
+declare 36 win {
+ LRESULT __stdcall TkWinChildProc(HWND hwnd,
+ UINT message, WPARAM wParam, LPARAM lParam)
+}
+
+# new for 8.4.20+/8.5.12+, Cygwin only
+declare 37 win {
+ void TkCreateXEventSource(void)
+}
+declare 38 win {
+ int TkpCmapStressed(Tk_Window tkwin, Colormap colormap)
+}
+declare 39 win {
+ void TkpSync(Display *display)
+}
+declare 40 win {
+ Window TkUnixContainerId(TkWindow *winPtr)
+}
+declare 41 win {
+ int TkUnixDoOneXEvent(Tcl_Time *timePtr)
+}
+declare 42 win {
+ void TkUnixSetMenubar(Tk_Window tkwin, Tk_Window menubar)
+}
+declare 43 win {
+ void TkWmCleanup(TkDisplay *dispPtr)
+}
+declare 44 win {
+ void TkSendCleanup(TkDisplay *dispPtr)
+}
+# only needed by tktest:
+declare 45 win {
+ int TkpTestsendCmd(ClientData clientData, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[])
+}
+
+################################
+# Aqua specific functions
+
+declare 0 aqua {
+ void TkGenerateActivateEvents(TkWindow *winPtr, int active)
+}
+
+# removed duplicates from tkInt table
+#declare 1 aqua {
+# Pixmap TkpCreateNativeBitmap(Display *display, const void *source)
+#}
+#
+#declare 2 aqua {
+# void TkpDefineNativeBitmaps(void)
+#}
+
+declare 3 aqua {
+ void TkPointerDeadWindow(TkWindow *winPtr)
+}
+declare 4 aqua {
+ void TkpSetCapture(TkWindow *winPtr)
+}
+declare 5 aqua {
+ void TkpSetCursor(TkpCursor cursor)
+}
+declare 6 aqua {
+ void TkpWmSetState(TkWindow *winPtr, int state)
+}
+declare 7 aqua {
+ void TkAboutDlg(void)
+}
+declare 8 aqua {
+ unsigned int TkMacOSXButtonKeyState(void)
+}
+declare 9 aqua {
+ void TkMacOSXClearMenubarActive(void)
+}
+declare 10 aqua {
+ int TkMacOSXDispatchMenuEvent(int menuID, int index)
+}
+declare 11 aqua {
+ void TkMacOSXInstallCursor(int resizeOverride)
+}
+declare 12 aqua {
+ void TkMacOSXHandleTearoffMenu(void)
+}
+
+# removed duplicate from tkPlat table(tk.decls)
+#declare 13 aqua {
+# void TkMacOSXInvalClipRgns(TkWindow *winPtr)
+#}
+
+declare 14 aqua {
+ int TkMacOSXDoHLEvent(void *theEvent)
+}
+
+# removed duplicate from tkPlat table(tk.decls)
+#declare 15 aqua {
+# void *TkMacOSXGetDrawablePort(Drawable drawable)
+#}
+
+declare 16 aqua {
+ Window TkMacOSXGetXWindow(void *macWinPtr)
+}
+declare 17 aqua {
+ int TkMacOSXGrowToplevel(void *whichWindow, XPoint start)
+}
+declare 18 aqua {
+ void TkMacOSXHandleMenuSelect(short theMenu, unsigned short theItem,
+ int optionKeyPressed)
+}
+
+# removed duplicates from tkPlat table(tk.decls)
+#declare 19 aqua {
+# void TkMacOSXInitAppleEvents(Tcl_Interp *interp)
+#}
+#
+#declare 20 aqua {
+# void TkMacOSXInitMenus(Tcl_Interp *interp)
+#}
+
+declare 21 aqua {
+ void TkMacOSXInvalidateWindow(MacDrawable *macWin, int flag)
+}
+declare 22 aqua {
+ int TkMacOSXIsCharacterMissing(Tk_Font tkfont, unsigned int searchChar)
+}
+declare 23 aqua {
+ void TkMacOSXMakeRealWindowExist(TkWindow *winPtr)
+}
+declare 24 aqua {
+ void *TkMacOSXMakeStippleMap(Drawable d1, Drawable d2)
+}
+declare 25 aqua {
+ void TkMacOSXMenuClick(void)
+}
+declare 26 aqua {
+ void TkMacOSXRegisterOffScreenWindow(Window window, void *portPtr)
+}
+declare 27 aqua {
+ int TkMacOSXResizable(TkWindow *winPtr)
+}
+declare 28 aqua {
+ void TkMacOSXSetHelpMenuItemCount(void)
+}
+declare 29 aqua {
+ void TkMacOSXSetScrollbarGrow(TkWindow *winPtr, int flag)
+}
+declare 30 aqua {
+ void TkMacOSXSetUpClippingRgn(Drawable drawable)
+}
+declare 31 aqua {
+ void TkMacOSXSetUpGraphicsPort(GC gc, void *destPort)
+}
+declare 32 aqua {
+ void TkMacOSXUpdateClipRgn(TkWindow *winPtr)
+}
+declare 33 aqua {
+ void TkMacOSXUnregisterMacWindow(void *portPtr)
+}
+declare 34 aqua {
+ int TkMacOSXUseMenuID(short macID)
+}
+declare 35 aqua {
+ TkRegion TkMacOSXVisableClipRgn(TkWindow *winPtr)
+}
+declare 36 aqua {
+ void TkMacOSXWinBounds(TkWindow *winPtr, void *geometry)
+}
+declare 37 aqua {
+ void TkMacOSXWindowOffset(void *wRef, int *xOffset, int *yOffset)
+}
+declare 38 aqua {
+ int TkSetMacColor(unsigned long pixel, void *macColor)
+}
+declare 39 aqua {
+ void TkSetWMName(TkWindow *winPtr, Tk_Uid titleUid)
+}
+#
+# Slot 40 unused (WAS: TkSuspendClipboard)
+#
+declare 41 aqua {
+ int TkMacOSXZoomToplevel(void *whichWindow, short zoomPart)
+}
+declare 42 aqua {
+ Tk_Window Tk_TopCoordsToWindow(Tk_Window tkwin, int rootX, int rootY,
+ int *newX, int *newY)
+}
+declare 43 aqua {
+ MacDrawable *TkMacOSXContainerId(TkWindow *winPtr)
+}
+declare 44 aqua {
+ MacDrawable *TkMacOSXGetHostToplevel(TkWindow *winPtr)
+}
+declare 45 aqua {
+ void TkMacOSXPreprocessMenu(void)
+}
+declare 46 aqua {
+ int TkpIsWindowFloating(void *window)
+}
+declare 47 aqua {
+ Tk_Window TkMacOSXGetCapture(void)
+}
+declare 49 aqua {
+ Tk_Window TkGetTransientMaster(TkWindow *winPtr)
+}
+declare 50 aqua {
+ int TkGenerateButtonEvent(int x, int y, Window window, unsigned int state)
+}
+declare 51 aqua {
+ void TkGenWMDestroyEvent(Tk_Window tkwin)
+}
+declare 52 aqua {
+ void TkMacOSXSetDrawingEnabled(TkWindow *winPtr, int flag)
+}
+
+# removed duplicate from tkPlat table (tk.decls)
+#declare 52 aqua {
+# void TkGenWMConfigureEvent(Tk_Window tkwin, int x, int y,
+# int width, int height, int flags)
+#}
+
+declare 53 aqua {
+ unsigned long TkpGetMS(void)
+}
+
+# For Canvas3d, requested by Sean Woods
+declare 54 aqua {
+ void *TkMacOSXDrawable(Drawable drawable)
+}
+declare 55 aqua {
+ int TkpScanWindowId(Tcl_Interp *interp, const char *string, Window *idPtr)
+}
+
+##############################################################################
+
+# Define the platform specific internal Xlib interfaces. These functions are
+# only available on the designated platform.
+
+interface tkIntXlib
+
+################################
+# X functions for Windows
+
+declare 0 win {
+ int XSetDashes(Display *display, GC gc, int dash_offset,
+ _Xconst char *dash_list, int n)
+}
+declare 1 win {
+ XModifierKeymap *XGetModifierMapping(Display *d)
+}
+declare 2 win {
+ XImage *XCreateImage(Display *d, Visual *v, unsigned int ui1, int i1,
+ int i2, char *cp, unsigned int ui2, unsigned int ui3, int i3,
+ int i4)
+}
+declare 3 win {
+ XImage *XGetImage(Display *d, Drawable dr, int i1, int i2,
+ unsigned int ui1, unsigned int ui2, unsigned long ul, int i3)
+}
+declare 4 win {
+ char *XGetAtomName(Display *d, Atom a)
+}
+declare 5 win {
+ char *XKeysymToString(KeySym k)
+}
+declare 6 win {
+ Colormap XCreateColormap(Display *d, Window w, Visual *v, int i)
+}
+declare 7 win {
+ Cursor XCreatePixmapCursor(Display *d, Pixmap p1, Pixmap p2,
+ XColor *x1, XColor *x2, unsigned int ui1, unsigned int ui2)
+}
+declare 8 win {
+ Cursor XCreateGlyphCursor(Display *d, Font f1, Font f2,
+ unsigned int ui1, unsigned int ui2, XColor _Xconst *x1,
+ XColor _Xconst *x2)
+}
+declare 9 win {
+ GContext XGContextFromGC(GC g)
+}
+declare 10 win {
+ XHostAddress *XListHosts(Display *d, int *i, Bool *b)
+}
+# second parameter was of type KeyCode
+declare 11 win {
+ KeySym XKeycodeToKeysym(Display *d, unsigned int k, int i)
+}
+declare 12 win {
+ KeySym XStringToKeysym(_Xconst char *c)
+}
+declare 13 win {
+ Window XRootWindow(Display *d, int i)
+}
+declare 14 win {
+ XErrorHandler XSetErrorHandler(XErrorHandler x)
+}
+declare 15 win {
+ Status XIconifyWindow(Display *d, Window w, int i)
+}
+declare 16 win {
+ Status XWithdrawWindow(Display *d, Window w, int i)
+}
+declare 17 win {
+ Status XGetWMColormapWindows(Display *d, Window w, Window **wpp, int *ip)
+}
+declare 18 win {
+ Status XAllocColor(Display *d, Colormap c, XColor *xp)
+}
+declare 19 win {
+ int XBell(Display *d, int i)
+}
+declare 20 win {
+ int XChangeProperty(Display *d, Window w, Atom a1, Atom a2, int i1,
+ int i2, _Xconst unsigned char *c, int i3)
+}
+declare 21 win {
+ int XChangeWindowAttributes(Display *d, Window w, unsigned long ul,
+ XSetWindowAttributes *x)
+}
+declare 22 win {
+ int XClearWindow(Display *d, Window w)
+}
+declare 23 win {
+ int XConfigureWindow(Display *d, Window w, unsigned int i,
+ XWindowChanges *x)
+}
+declare 24 win {
+ int XCopyArea(Display *d, Drawable dr1, Drawable dr2, GC g, int i1,
+ int i2, unsigned int ui1, unsigned int ui2, int i3, int i4)
+}
+declare 25 win {
+ int XCopyPlane(Display *d, Drawable dr1, Drawable dr2, GC g, int i1,
+ int i2, unsigned int ui1, unsigned int ui2,
+ int i3, int i4, unsigned long ul)
+}
+declare 26 win {
+ Pixmap XCreateBitmapFromData(Display *display, Drawable d,
+ _Xconst char *data, unsigned int width, unsigned int height)
+}
+declare 27 win {
+ int XDefineCursor(Display *d, Window w, Cursor c)
+}
+declare 28 win {
+ int XDeleteProperty(Display *d, Window w, Atom a)
+}
+declare 29 win {
+ int XDestroyWindow(Display *d, Window w)
+}
+declare 30 win {
+ int XDrawArc(Display *d, Drawable dr, GC g, int i1, int i2,
+ unsigned int ui1, unsigned int ui2, int i3, int i4)
+}
+declare 31 win {
+ int XDrawLines(Display *d, Drawable dr, GC g, XPoint *x, int i1, int i2)
+}
+declare 32 win {
+ int XDrawRectangle(Display *d, Drawable dr, GC g, int i1, int i2,
+ unsigned int ui1, unsigned int ui2)
+}
+declare 33 win {
+ int XFillArc(Display *d, Drawable dr, GC g, int i1, int i2,
+ unsigned int ui1, unsigned int ui2, int i3, int i4)
+}
+declare 34 win {
+ int XFillPolygon(Display *d, Drawable dr, GC g, XPoint *x,
+ int i1, int i2, int i3)
+}
+declare 35 win {
+ int XFillRectangles(Display *d, Drawable dr, GC g, XRectangle *x, int i)
+}
+declare 36 win {
+ int XForceScreenSaver(Display *d, int i)
+}
+declare 37 win {
+ int XFreeColormap(Display *d, Colormap c)
+}
+declare 38 win {
+ int XFreeColors(Display *d, Colormap c,
+ unsigned long *ulp, int i, unsigned long ul)
+}
+declare 39 win {
+ int XFreeCursor(Display *d, Cursor c)
+}
+declare 40 win {
+ int XFreeModifiermap(XModifierKeymap *x)
+}
+declare 41 win {
+ Status XGetGeometry(Display *d, Drawable dr, Window *w, int *i1,
+ int *i2, unsigned int *ui1, unsigned int *ui2, unsigned int *ui3,
+ unsigned int *ui4)
+}
+declare 42 win {
+ int XGetInputFocus(Display *d, Window *w, int *i)
+}
+declare 43 win {
+ int XGetWindowProperty(Display *d, Window w, Atom a1, long l1, long l2,
+ Bool b, Atom a2, Atom *ap, int *ip, unsigned long *ulp1,
+ unsigned long *ulp2, unsigned char **cpp)
+}
+declare 44 win {
+ Status XGetWindowAttributes(Display *d, Window w, XWindowAttributes *x)
+}
+declare 45 win {
+ int XGrabKeyboard(Display *d, Window w, Bool b, int i1, int i2, Time t)
+}
+declare 46 win {
+ int XGrabPointer(Display *d, Window w1, Bool b, unsigned int ui,
+ int i1, int i2, Window w2, Cursor c, Time t)
+}
+declare 47 win {
+ KeyCode XKeysymToKeycode(Display *d, KeySym k)
+}
+declare 48 win {
+ Status XLookupColor(Display *d, Colormap c1, _Xconst char *c2,
+ XColor *x1, XColor *x2)
+}
+declare 49 win {
+ int XMapWindow(Display *d, Window w)
+}
+declare 50 win {
+ int XMoveResizeWindow(Display *d, Window w, int i1, int i2,
+ unsigned int ui1, unsigned int ui2)
+}
+declare 51 win {
+ int XMoveWindow(Display *d, Window w, int i1, int i2)
+}
+declare 52 win {
+ int XNextEvent(Display *d, XEvent *x)
+}
+declare 53 win {
+ int XPutBackEvent(Display *d, XEvent *x)
+}
+declare 54 win {
+ int XQueryColors(Display *d, Colormap c, XColor *x, int i)
+}
+declare 55 win {
+ Bool XQueryPointer(Display *d, Window w1, Window *w2, Window *w3,
+ int *i1, int *i2, int *i3, int *i4, unsigned int *ui)
+}
+declare 56 win {
+ Status XQueryTree(Display *d, Window w1, Window *w2, Window *w3,
+ Window **w4, unsigned int *ui)
+}
+declare 57 win {
+ int XRaiseWindow(Display *d, Window w)
+}
+declare 58 win {
+ int XRefreshKeyboardMapping(XMappingEvent *x)
+}
+declare 59 win {
+ int XResizeWindow(Display *d, Window w, unsigned int ui1,
+ unsigned int ui2)
+}
+declare 60 win {
+ int XSelectInput(Display *d, Window w, long l)
+}
+declare 61 win {
+ Status XSendEvent(Display *d, Window w, Bool b, long l, XEvent *x)
+}
+declare 62 win {
+ int XSetCommand(Display *d, Window w, char **c, int i)
+}
+declare 63 win {
+ int XSetIconName(Display *d, Window w, _Xconst char *c)
+}
+declare 64 win {
+ int XSetInputFocus(Display *d, Window w, int i, Time t)
+}
+declare 65 win {
+ int XSetSelectionOwner(Display *d, Atom a, Window w, Time t)
+}
+declare 66 win {
+ int XSetWindowBackground(Display *d, Window w, unsigned long ul)
+}
+declare 67 win {
+ int XSetWindowBackgroundPixmap(Display *d, Window w, Pixmap p)
+}
+declare 68 win {
+ int XSetWindowBorder(Display *d, Window w, unsigned long ul)
+}
+declare 69 win {
+ int XSetWindowBorderPixmap(Display *d, Window w, Pixmap p)
+}
+declare 70 win {
+ int XSetWindowBorderWidth(Display *d, Window w, unsigned int ui)
+}
+declare 71 win {
+ int XSetWindowColormap(Display *d, Window w, Colormap c)
+}
+declare 72 win {
+ Bool XTranslateCoordinates(Display *d, Window w1, Window w2, int i1,
+ int i2, int *i3, int *i4, Window *w3)
+}
+declare 73 win {
+ int XUngrabKeyboard(Display *d, Time t)
+}
+declare 74 win {
+ int XUngrabPointer(Display *d, Time t)
+}
+declare 75 win {
+ int XUnmapWindow(Display *d, Window w)
+}
+declare 76 win {
+ int XWindowEvent(Display *d, Window w, long l, XEvent *x)
+}
+declare 77 win {
+ void XDestroyIC(XIC x)
+}
+declare 78 win {
+ Bool XFilterEvent(XEvent *x, Window w)
+}
+declare 79 win {
+ int XmbLookupString(XIC xi, XKeyPressedEvent *xk, char *c, int i,
+ KeySym *k, Status *s)
+}
+declare 80 win {
+ int TkPutImage(unsigned long *colors, int ncolors, Display *display,
+ Drawable d, GC gc, XImage *image, int src_x, int src_y,
+ int dest_x, int dest_y, unsigned int width, unsigned int height)
+}
+# This slot is reserved for use by the clipping rectangle patch:
+# declare 81 win {
+# XSetClipRectangles(Display *display, GC gc, int clip_x_origin,
+# int clip_y_origin, XRectangle rectangles[], int n, int ordering)
+# }
+
+declare 82 win {
+ Status XParseColor(Display *display, Colormap map,
+ _Xconst char *spec, XColor *colorPtr)
+}
+declare 83 win {
+ GC XCreateGC(Display *display, Drawable d,
+ unsigned long valuemask, XGCValues *values)
+}
+declare 84 win {
+ int XFreeGC(Display *display, GC gc)
+}
+declare 85 win {
+ Atom XInternAtom(Display *display, _Xconst char *atom_name,
+ Bool only_if_exists)
+}
+declare 86 win {
+ int XSetBackground(Display *display, GC gc, unsigned long foreground)
+}
+declare 87 win {
+ int XSetForeground(Display *display, GC gc, unsigned long foreground)
+}
+declare 88 win {
+ int XSetClipMask(Display *display, GC gc, Pixmap pixmap)
+}
+declare 89 win {
+ int XSetClipOrigin(Display *display, GC gc,
+ int clip_x_origin, int clip_y_origin)
+}
+declare 90 win {
+ int XSetTSOrigin(Display *display, GC gc,
+ int ts_x_origin, int ts_y_origin)
+}
+declare 91 win {
+ int XChangeGC(Display *d, GC gc, unsigned long mask, XGCValues *values)
+}
+declare 92 win {
+ int XSetFont(Display *display, GC gc, Font font)
+}
+declare 93 win {
+ int XSetArcMode(Display *display, GC gc, int arc_mode)
+}
+declare 94 win {
+ int XSetStipple(Display *display, GC gc, Pixmap stipple)
+}
+declare 95 win {
+ int XSetFillRule(Display *display, GC gc, int fill_rule)
+}
+declare 96 win {
+ int XSetFillStyle(Display *display, GC gc, int fill_style)
+}
+declare 97 win {
+ int XSetFunction(Display *display, GC gc, int function)
+}
+declare 98 win {
+ int XSetLineAttributes(Display *display, GC gc, unsigned int line_width,
+ int line_style, int cap_style, int join_style)
+}
+declare 99 win {
+ int _XInitImageFuncPtrs(XImage *image)
+}
+declare 100 win {
+ XIC XCreateIC(XIM xim, ...)
+}
+declare 101 win {
+ XVisualInfo *XGetVisualInfo(Display *display, long vinfo_mask,
+ XVisualInfo *vinfo_template, int *nitems_return)
+}
+declare 102 win {
+ void XSetWMClientMachine(Display *display, Window w,
+ XTextProperty *text_prop)
+}
+declare 103 win {
+ Status XStringListToTextProperty(char **list, int count,
+ XTextProperty *text_prop_return)
+}
+declare 104 win {
+ int XDrawLine(Display *d, Drawable dr, GC g, int x1, int y1,
+ int x2, int y2)
+}
+declare 105 win {
+ int XWarpPointer(Display *d, Window s, Window dw, int sx, int sy,
+ unsigned int sw, unsigned int sh, int dx, int dy)
+}
+declare 106 win {
+ int XFillRectangle(Display *display, Drawable d, GC gc,
+ int x, int y, unsigned int width, unsigned int height)
+}
+
+# New in Tk 8.6
+declare 107 win {
+ int XFlush(Display *display)
+}
+declare 108 win {
+ int XGrabServer(Display *display)
+}
+declare 109 win {
+ int XUngrabServer(Display *display)
+}
+declare 110 win {
+ int XFree(void *data)
+}
+declare 111 win {
+ int XNoOp(Display *display)
+}
+declare 112 win {
+ XAfterFunction XSynchronize(Display *display, Bool onoff)
+}
+declare 113 win {
+ int XSync(Display *display, Bool discard)
+}
+declare 114 win {
+ VisualID XVisualIDFromVisual(Visual *visual)
+}
+
+# For tktreectrl
+declare 120 win {
+ int XOffsetRegion(Region rgn, int dx, int dy)
+}
+declare 121 win {
+ int XUnionRegion(Region srca, Region srcb, Region dr_return)
+}
+
+# For 3dcanvas
+declare 122 win {
+ Window XCreateWindow(Display *display, Window parent, int x, int y,
+ unsigned int width, unsigned int height,
+ unsigned int border_width, int depth, unsigned int clazz,
+ Visual *visual, unsigned long value_mask,
+ XSetWindowAttributes *attributes)
+}
+
+# Various, e.g. for stub-enabled BLT
+declare 129 win {
+ int XLowerWindow(Display *d, Window w)
+}
+declare 130 win {
+ int XFillArcs(Display *d, Drawable dr, GC gc, XArc *a, int n)
+}
+declare 131 win {
+ int XDrawArcs(Display *d, Drawable dr, GC gc, XArc *a, int n)
+}
+declare 132 win {
+ int XDrawRectangles(Display *d, Drawable dr, GC gc, XRectangle *r, int n)
+}
+declare 133 win {
+ int XDrawSegments(Display *d, Drawable dr, GC gc, XSegment *s, int n)
+}
+declare 134 win {
+ int XDrawPoint(Display *d, Drawable dr, GC gc, int x, int y)
+}
+declare 135 win {
+ int XDrawPoints(Display *d, Drawable dr, GC gc, XPoint *p, int n, int m)
+}
+declare 136 win {
+ int XReparentWindow(Display *d, Window w, Window p, int x, int y)
+}
+declare 137 win {
+ int XPutImage(Display *d, Drawable dr, GC gc, XImage *im,
+ int sx, int sy, int dx, int dy,
+ unsigned int w, unsigned int h)
+}
+
+################################
+# X functions for Aqua
+
+declare 0 aqua {
+ int XSetDashes(Display *display, GC gc, int dash_offset,
+ _Xconst char *dash_list, int n)
+}
+declare 1 aqua {
+ XModifierKeymap *XGetModifierMapping(Display *d)
+}
+declare 2 aqua {
+ XImage *XCreateImage(Display *d, Visual *v, unsigned int ui1, int i1,
+ int i2, char *cp, unsigned int ui2, unsigned int ui3, int i3,
+ int i4)
+}
+declare 3 aqua {
+ XImage *XGetImage(Display *d, Drawable dr, int i1, int i2,
+ unsigned int ui1, unsigned int ui2, unsigned long ul, int i3)
+}
+declare 4 aqua {
+ char *XGetAtomName(Display *d, Atom a)
+}
+declare 5 aqua {
+ char *XKeysymToString(KeySym k)
+}
+declare 6 aqua {
+ Colormap XCreateColormap(Display *d, Window w, Visual *v, int i)
+}
+declare 7 aqua {
+ GContext XGContextFromGC(GC g)
+}
+declare 8 aqua {
+ KeySym XKeycodeToKeysym(Display *d, KeyCode k, int i)
+}
+declare 9 aqua {
+ KeySym XStringToKeysym(_Xconst char *c)
+}
+declare 10 aqua {
+ Window XRootWindow(Display *d, int i)
+}
+declare 11 aqua {
+ XErrorHandler XSetErrorHandler(XErrorHandler x)
+}
+declare 12 aqua {
+ Status XAllocColor(Display *d, Colormap c, XColor *xp)
+}
+declare 13 aqua {
+ int XBell(Display *d, int i)
+}
+declare 14 aqua {
+ void XChangeProperty(Display *d, Window w, Atom a1, Atom a2, int i1,
+ int i2, _Xconst unsigned char *c, int i3)
+}
+declare 15 aqua {
+ void XChangeWindowAttributes(Display *d, Window w, unsigned long ul,
+ XSetWindowAttributes *x)
+}
+declare 16 aqua {
+ void XConfigureWindow(Display *d, Window w, unsigned int i,
+ XWindowChanges *x)
+}
+declare 17 aqua {
+ void XCopyArea(Display *d, Drawable dr1, Drawable dr2, GC g, int i1,
+ int i2, unsigned int ui1, unsigned int ui2, int i3, int i4)
+}
+declare 18 aqua {
+ void XCopyPlane(Display *d, Drawable dr1, Drawable dr2, GC g, int i1,
+ int i2, unsigned int ui1,
+ unsigned int ui2, int i3, int i4, unsigned long ul)
+}
+declare 19 aqua {
+ Pixmap XCreateBitmapFromData(Display *display, Drawable d,
+ _Xconst char *data, unsigned int width, unsigned int height)
+}
+declare 20 aqua {
+ int XDefineCursor(Display *d, Window w, Cursor c)
+}
+declare 21 aqua {
+ void XDestroyWindow(Display *d, Window w)
+}
+declare 22 aqua {
+ void XDrawArc(Display *d, Drawable dr, GC g, int i1, int i2,
+ unsigned int ui1, unsigned int ui2, int i3, int i4)
+}
+declare 23 aqua {
+ int XDrawLines(Display *d, Drawable dr, GC g, XPoint *x, int i1, int i2)
+}
+declare 24 aqua {
+ void XDrawRectangle(Display *d, Drawable dr, GC g, int i1, int i2,
+ unsigned int ui1, unsigned int ui2)
+}
+declare 25 aqua {
+ void XFillArc(Display *d, Drawable dr, GC g, int i1, int i2,
+ unsigned int ui1, unsigned int ui2, int i3, int i4)
+}
+declare 26 aqua {
+ void XFillPolygon(Display *d, Drawable dr, GC g, XPoint *x,
+ int i1, int i2, int i3)
+}
+declare 27 aqua {
+ int XFillRectangles(Display *d, Drawable dr, GC g, XRectangle *x, int i)
+}
+declare 28 aqua {
+ int XFreeColormap(Display *d, Colormap c)
+}
+declare 29 aqua {
+ int XFreeColors(Display *d, Colormap c,
+ unsigned long *ulp, int i, unsigned long ul)
+}
+declare 30 aqua {
+ int XFreeModifiermap(XModifierKeymap *x)
+}
+declare 31 aqua {
+ Status XGetGeometry(Display *d, Drawable dr, Window *w, int *i1,
+ int *i2, unsigned int *ui1, unsigned int *ui2, unsigned int *ui3,
+ unsigned int *ui4)
+}
+declare 32 aqua {
+ int XGetWindowProperty(Display *d, Window w, Atom a1, long l1, long l2,
+ Bool b, Atom a2, Atom *ap, int *ip, unsigned long *ulp1,
+ unsigned long *ulp2, unsigned char **cpp)
+}
+declare 33 aqua {
+ int XGrabKeyboard(Display *d, Window w, Bool b, int i1, int i2, Time t)
+}
+declare 34 aqua {
+ int XGrabPointer(Display *d, Window w1, Bool b, unsigned int ui,
+ int i1, int i2, Window w2, Cursor c, Time t)
+}
+declare 35 aqua {
+ KeyCode XKeysymToKeycode(Display *d, KeySym k)
+}
+declare 36 aqua {
+ void XMapWindow(Display *d, Window w)
+}
+declare 37 aqua {
+ void XMoveResizeWindow(Display *d, Window w, int i1, int i2,
+ unsigned int ui1, unsigned int ui2)
+}
+declare 38 aqua {
+ void XMoveWindow(Display *d, Window w, int i1, int i2)
+}
+declare 39 aqua {
+ Bool XQueryPointer(Display *d, Window w1, Window *w2, Window *w3,
+ int *i1, int *i2, int *i3, int *i4, unsigned int *ui)
+}
+declare 40 aqua {
+ void XRaiseWindow(Display *d, Window w)
+}
+declare 41 aqua {
+ void XRefreshKeyboardMapping(XMappingEvent *x)
+}
+declare 42 aqua {
+ void XResizeWindow(Display *d, Window w, unsigned int ui1,
+ unsigned int ui2)
+}
+declare 43 aqua {
+ void XSelectInput(Display *d, Window w, long l)
+}
+declare 44 aqua {
+ Status XSendEvent(Display *d, Window w, Bool b, long l, XEvent *x)
+}
+declare 45 aqua {
+ void XSetIconName(Display *d, Window w, _Xconst char *c)
+}
+declare 46 aqua {
+ void XSetInputFocus(Display *d, Window w, int i, Time t)
+}
+declare 47 aqua {
+ int XSetSelectionOwner(Display *d, Atom a, Window w, Time t)
+}
+declare 48 aqua {
+ void XSetWindowBackground(Display *d, Window w, unsigned long ul)
+}
+declare 49 aqua {
+ void XSetWindowBackgroundPixmap(Display *d, Window w, Pixmap p)
+}
+declare 50 aqua {
+ void XSetWindowBorder(Display *d, Window w, unsigned long ul)
+}
+declare 51 aqua {
+ void XSetWindowBorderPixmap(Display *d, Window w, Pixmap p)
+}
+declare 52 aqua {
+ void XSetWindowBorderWidth(Display *d, Window w, unsigned int ui)
+}
+declare 53 aqua {
+ void XSetWindowColormap(Display *d, Window w, Colormap c)
+}
+declare 54 aqua {
+ void XUngrabKeyboard(Display *d, Time t)
+}
+declare 55 aqua {
+ int XUngrabPointer(Display *d, Time t)
+}
+declare 56 aqua {
+ void XUnmapWindow(Display *d, Window w)
+}
+declare 57 aqua {
+ int TkPutImage(unsigned long *colors, int ncolors, Display *display,
+ Drawable d, GC gc, XImage *image, int src_x, int src_y,
+ int dest_x, int dest_y, unsigned int width, unsigned int height)
+}
+declare 58 aqua {
+ Status XParseColor(Display *display, Colormap map,
+ _Xconst char *spec, XColor *colorPtr)
+}
+declare 59 aqua {
+ GC XCreateGC(Display *display, Drawable d,
+ unsigned long valuemask, XGCValues *values)
+}
+declare 60 aqua {
+ int XFreeGC(Display *display, GC gc)
+}
+declare 61 aqua {
+ Atom XInternAtom(Display *display, _Xconst char *atom_name,
+ Bool only_if_exists)
+}
+declare 62 aqua {
+ int XSetBackground(Display *display, GC gc, unsigned long foreground)
+}
+declare 63 aqua {
+ int XSetForeground(Display *display, GC gc, unsigned long foreground)
+}
+declare 64 aqua {
+ int XSetClipMask(Display *display, GC gc, Pixmap pixmap)
+}
+declare 65 aqua {
+ int XSetClipOrigin(Display *display, GC gc,
+ int clip_x_origin, int clip_y_origin)
+}
+declare 66 aqua {
+ int XSetTSOrigin(Display *display, GC gc,
+ int ts_x_origin, int ts_y_origin)
+}
+declare 67 aqua {
+ int XChangeGC(Display *d, GC gc, unsigned long mask, XGCValues *values)
+}
+declare 68 aqua {
+ int XSetFont(Display *display, GC gc, Font font)
+}
+declare 69 aqua {
+ int XSetArcMode(Display *display, GC gc, int arc_mode)
+}
+declare 70 aqua {
+ int XSetStipple(Display *display, GC gc, Pixmap stipple)
+}
+declare 71 aqua {
+ int XSetFillRule(Display *display, GC gc, int fill_rule)
+}
+declare 72 aqua {
+ int XSetFillStyle(Display *display, GC gc, int fill_style)
+}
+declare 73 aqua {
+ int XSetFunction(Display *display, GC gc, int function)
+}
+declare 74 aqua {
+ int XSetLineAttributes(Display *display, GC gc, unsigned int line_width,
+ int line_style, int cap_style, int join_style)
+}
+declare 75 aqua {
+ int _XInitImageFuncPtrs(XImage *image)
+}
+declare 76 aqua {
+ XIC XCreateIC(void)
+}
+declare 77 aqua {
+ XVisualInfo *XGetVisualInfo(Display *display, long vinfo_mask,
+ XVisualInfo *vinfo_template, int *nitems_return)
+}
+declare 78 aqua {
+ void XSetWMClientMachine(Display *display, Window w,
+ XTextProperty *text_prop)
+}
+declare 79 aqua {
+ Status XStringListToTextProperty(char **list, int count,
+ XTextProperty *text_prop_return)
+}
+declare 80 aqua {
+ int XDrawSegments(Display *display, Drawable d, GC gc,
+ XSegment *segments, int nsegments)
+}
+declare 81 aqua {
+ void XForceScreenSaver(Display *display, int mode)
+}
+declare 82 aqua {
+ int XDrawLine(Display *d, Drawable dr, GC g, int x1, int y1,
+ int x2, int y2)
+}
+declare 83 aqua {
+ int XFillRectangle(Display *display, Drawable d, GC gc,
+ int x, int y, unsigned int width, unsigned int height)
+}
+declare 84 aqua {
+ void XClearWindow(Display *d, Window w)
+}
+declare 85 aqua {
+ int XDrawPoint(Display *display, Drawable d, GC gc, int x, int y)
+}
+declare 86 aqua {
+ int XDrawPoints(Display *display, Drawable d, GC gc, XPoint *points,
+ int npoints, int mode)
+}
+declare 87 aqua {
+ int 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)
+}
+declare 88 aqua {
+ void XQueryColor(Display *display, Colormap colormap, XColor *def_in_out)
+}
+declare 89 aqua {
+ void XQueryColors(Display *display, Colormap colormap,
+ XColor *defs_in_out, int ncolors)
+}
+declare 90 aqua {
+ Status XQueryTree(Display *d, Window w1, Window *w2, Window *w3,
+ Window **w4, unsigned int *ui)
+}
+declare 91 aqua {
+ int XSync(Display *display, Bool flag)
+}
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tk8.6/generic/tkInt.h b/tk8.6/generic/tkInt.h
new file mode 100644
index 0000000..a80d209
--- /dev/null
+++ b/tk8.6/generic/tkInt.h
@@ -0,0 +1,1287 @@
+/*
+ * tkInt.h --
+ *
+ * Declarations for things used internally by the Tk functions but not
+ * exported outside the module.
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1998 by Scriptics Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef _TKINT
+#define _TKINT
+
+#ifndef _TKPORT
+#include "tkPort.h"
+#endif
+
+/*
+ * Ensure WORDS_BIGENDIAN is defined correctly:
+ * Needs to happen here in addition to configure to work with fat compiles on
+ * Darwin (where configure runs only once for multiple architectures).
+ */
+
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+#ifdef BYTE_ORDER
+# ifdef BIG_ENDIAN
+# if BYTE_ORDER == BIG_ENDIAN
+# undef WORDS_BIGENDIAN
+# define WORDS_BIGENDIAN 1
+# endif
+# endif
+# ifdef LITTLE_ENDIAN
+# if BYTE_ORDER == LITTLE_ENDIAN
+# undef WORDS_BIGENDIAN
+# endif
+# endif
+#endif
+
+/*
+ * Used to tag functions that are only to be visible within the module being
+ * built and not outside it (where this is supported by the linker).
+ */
+
+#ifndef MODULE_SCOPE
+# ifdef __cplusplus
+# define MODULE_SCOPE extern "C"
+# else
+# define MODULE_SCOPE extern
+# endif
+#endif
+
+/*
+ * Macros used to cast between pointers and integers (e.g. when storing an int
+ * in ClientData), on 64-bit architectures they avoid gcc warning about "cast
+ * to/from pointer from/to integer of different size".
+ */
+
+#if !defined(INT2PTR) && !defined(PTR2INT)
+# if defined(HAVE_INTPTR_T) || defined(intptr_t)
+# define INT2PTR(p) ((void*)(intptr_t)(p))
+# define PTR2INT(p) ((int)(intptr_t)(p))
+# else
+# define INT2PTR(p) ((void*)(p))
+# define PTR2INT(p) ((int)(p))
+# endif
+#endif
+#if !defined(UINT2PTR) && !defined(PTR2UINT)
+# if defined(HAVE_UINTPTR_T) || defined(uintptr_t)
+# define UINT2PTR(p) ((void*)(uintptr_t)(p))
+# define PTR2UINT(p) ((unsigned int)(uintptr_t)(p))
+# else
+# define UINT2PTR(p) ((void*)(p))
+# define PTR2UINT(p) ((unsigned int)(p))
+# endif
+#endif
+
+/*
+ * Opaque type declarations:
+ */
+
+typedef struct TkColormap TkColormap;
+typedef struct TkFontAttributes TkFontAttributes;
+typedef struct TkGrabEvent TkGrabEvent;
+typedef struct TkpCursor_ *TkpCursor;
+typedef struct TkRegion_ *TkRegion;
+typedef struct TkStressedCmap TkStressedCmap;
+typedef struct TkBindInfo_ *TkBindInfo;
+typedef struct Busy *TkBusy;
+
+/*
+ * One of the following structures is maintained for each cursor in use in the
+ * system. This structure is used by tkCursor.c and the various system-
+ * specific cursor files.
+ */
+
+typedef struct TkCursor {
+ Tk_Cursor cursor; /* System specific identifier for cursor. */
+ Display *display; /* Display containing cursor. Needed for
+ * disposal and retrieval of cursors. */
+ int resourceRefCount; /* Number of active uses of this cursor (each
+ * active use corresponds to a call to
+ * Tk_AllocPreserveFromObj or Tk_Preserve). If
+ * this count is 0, then this structure is no
+ * longer valid and it isn't present in a hash
+ * table: it is being kept around only because
+ * there are objects referring to it. The
+ * structure is freed when resourceRefCount
+ * and objRefCount are both 0. */
+ int objRefCount; /* Number of Tcl objects that reference this
+ * structure.. */
+ Tcl_HashTable *otherTable; /* Second table (other than idTable) used to
+ * index this entry. */
+ Tcl_HashEntry *hashPtr; /* Entry in otherTable for this structure
+ * (needed when deleting). */
+ Tcl_HashEntry *idHashPtr; /* Entry in idTable for this structure (needed
+ * when deleting). */
+ struct TkCursor *nextPtr; /* Points to the next TkCursor structure with
+ * the same name. Cursors with the same name
+ * but different displays are chained together
+ * off a single hash table entry. */
+} TkCursor;
+
+/*
+ * The following structure is kept one-per-TkDisplay to maintain information
+ * about the caret (cursor location) on this display. This is used to dictate
+ * global focus location (Windows Accessibility guidelines) and to position
+ * the IME or XIM over-the-spot window.
+ */
+
+typedef struct TkCaret {
+ struct TkWindow *winPtr; /* The window on which we requested caret
+ * placement. */
+ int x; /* Relative x coord of the caret. */
+ int y; /* Relative y coord of the caret. */
+ int height; /* Specified height of the window. */
+} TkCaret;
+
+/*
+ * One of the following structures is maintained for each display containing a
+ * window managed by Tk. In part, the structure is used to store thread-
+ * specific data, since each thread will have its own TkDisplay structure.
+ */
+
+typedef struct TkDisplay {
+ Display *display; /* Xlib's info about display. */
+ struct TkDisplay *nextPtr; /* Next in list of all displays. */
+ char *name; /* Name of display (with any screen identifier
+ * removed). Malloc-ed. */
+ Time lastEventTime; /* Time of last event received for this
+ * display. */
+
+ /*
+ * Information used primarily by tk3d.c:
+ */
+
+ int borderInit; /* 0 means borderTable needs initializing. */
+ Tcl_HashTable borderTable; /* Maps from color name to TkBorder
+ * structure. */
+
+ /*
+ * Information used by tkAtom.c only:
+ */
+
+ int atomInit; /* 0 means stuff below hasn't been initialized
+ * yet. */
+ Tcl_HashTable nameTable; /* Maps from names to Atom's. */
+ Tcl_HashTable atomTable; /* Maps from Atom's back to names. */
+
+ /*
+ * Information used primarily by tkBind.c:
+ */
+
+ int bindInfoStale; /* Non-zero means the variables in this part
+ * of the structure are potentially incorrect
+ * and should be recomputed. */
+ unsigned int modeModMask; /* Has one bit set to indicate the modifier
+ * corresponding to "mode shift". If no such
+ * modifier, than this is zero. */
+ unsigned int metaModMask; /* Has one bit set to indicate the modifier
+ * corresponding to the "Meta" key. If no such
+ * modifier, then this is zero. */
+ unsigned int altModMask; /* Has one bit set to indicate the modifier
+ * corresponding to the "Meta" key. If no such
+ * modifier, then this is zero. */
+ enum {LU_IGNORE, LU_CAPS, LU_SHIFT} lockUsage;
+ /* Indicates how to interpret lock
+ * modifier. */
+ int numModKeyCodes; /* Number of entries in modKeyCodes array
+ * below. */
+ KeyCode *modKeyCodes; /* Pointer to an array giving keycodes for all
+ * of the keys that have modifiers associated
+ * with them. Malloc'ed, but may be NULL. */
+
+ /*
+ * Information used by tkBitmap.c only:
+ */
+
+ int bitmapInit; /* 0 means tables above need initializing. */
+ int bitmapAutoNumber; /* Used to number bitmaps. */
+ Tcl_HashTable bitmapNameTable;
+ /* Maps from name of bitmap to the first
+ * TkBitmap record for that name. */
+ Tcl_HashTable bitmapIdTable;/* Maps from bitmap id to the TkBitmap
+ * structure for the bitmap. */
+ Tcl_HashTable bitmapDataTable;
+ /* Used by Tk_GetBitmapFromData to map from a
+ * collection of in-core data about a bitmap
+ * to a reference giving an automatically-
+ * generated name for the bitmap. */
+
+ /*
+ * Information used by tkCanvas.c only:
+ */
+
+ int numIdSearches;
+ int numSlowSearches;
+
+ /*
+ * Used by tkColor.c only:
+ */
+
+ int colorInit; /* 0 means color module needs initializing. */
+ TkStressedCmap *stressPtr; /* First in list of colormaps that have filled
+ * up, so we have to pick an approximate
+ * color. */
+ Tcl_HashTable colorNameTable;
+ /* Maps from color name to TkColor structure
+ * for that color. */
+ Tcl_HashTable colorValueTable;
+ /* Maps from integer RGB values to TkColor
+ * structures. */
+
+ /*
+ * Used by tkCursor.c only:
+ */
+
+ int cursorInit; /* 0 means cursor module need initializing. */
+ Tcl_HashTable cursorNameTable;
+ /* Maps from a string name to a cursor to the
+ * TkCursor record for the cursor. */
+ Tcl_HashTable cursorDataTable;
+ /* Maps from a collection of in-core data
+ * about a cursor to a TkCursor structure. */
+ Tcl_HashTable cursorIdTable;
+ /* Maps from a cursor id to the TkCursor
+ * structure for the cursor. */
+ char cursorString[20]; /* Used to store a cursor id string. */
+ Font cursorFont; /* Font to use for standard cursors. None
+ * means font not loaded yet. */
+
+ /*
+ * Information used by tkError.c only:
+ */
+
+ struct TkErrorHandler *errorPtr;
+ /* First in list of error handlers for this
+ * display. NULL means no handlers exist at
+ * present. */
+ int deleteCount; /* Counts # of handlers deleted since last
+ * time inactive handlers were garbage-
+ * collected. When this number gets big,
+ * handlers get cleaned up. */
+
+ /*
+ * Used by tkEvent.c only:
+ */
+
+ struct TkWindowEvent *delayedMotionPtr;
+ /* Points to a malloc-ed motion event whose
+ * processing has been delayed in the hopes
+ * that another motion event will come along
+ * right away and we can merge the two of them
+ * together. NULL means that there is no
+ * delayed motion event. */
+
+ /*
+ * Information used by tkFocus.c only:
+ */
+
+ int focusDebug; /* 1 means collect focus debugging
+ * statistics. */
+ struct TkWindow *implicitWinPtr;
+ /* If the focus arrived at a toplevel window
+ * implicitly via an Enter event (rather than
+ * via a FocusIn event), this points to the
+ * toplevel window. Otherwise it is NULL. */
+ struct TkWindow *focusPtr; /* Points to the window on this display that
+ * should be receiving keyboard events. When
+ * multiple applications on the display have
+ * the focus, this will refer to the innermost
+ * window in the innermost application. This
+ * information isn't used on Windows, but it's
+ * needed on the Mac, and also on X11 when XIM
+ * processing is being done. */
+
+ /*
+ * Information used by tkGC.c only:
+ */
+
+ Tcl_HashTable gcValueTable; /* Maps from a GC's values to a TkGC structure
+ * describing a GC with those values. */
+ Tcl_HashTable gcIdTable; /* Maps from a GC to a TkGC. */
+ int gcInit; /* 0 means the tables below need
+ * initializing. */
+
+ /*
+ * Information used by tkGeometry.c only:
+ */
+
+ Tcl_HashTable maintainHashTable;
+ /* Hash table that maps from a master's
+ * Tk_Window token to a list of slaves managed
+ * by that master. */
+ int geomInit;
+
+#define TkGetGeomMaster(tkwin) (((TkWindow *)tkwin)->maintainerPtr != NULL ? \
+ ((TkWindow *)tkwin)->maintainerPtr : ((TkWindow *)tkwin)->parentPtr)
+
+ /*
+ * Information used by tkGet.c only:
+ */
+
+ Tcl_HashTable uidTable; /* Stores all Tk_Uid used in a thread. */
+ int uidInit; /* 0 means uidTable needs initializing. */
+
+ /*
+ * Information used by tkGrab.c only:
+ */
+
+ struct TkWindow *grabWinPtr;/* Window in which the pointer is currently
+ * grabbed, or NULL if none. */
+ struct TkWindow *eventualGrabWinPtr;
+ /* Value that grabWinPtr will have once the
+ * grab event queue (below) has been
+ * completely emptied. */
+ struct TkWindow *buttonWinPtr;
+ /* Window in which first mouse button was
+ * pressed while grab was in effect, or NULL
+ * if no such press in effect. */
+ struct TkWindow *serverWinPtr;
+ /* If no application contains the pointer then
+ * this is NULL. Otherwise it contains the
+ * last window for which we've gotten an Enter
+ * or Leave event from the server (i.e. the
+ * last window known to have contained the
+ * pointer). Doesn't reflect events that were
+ * synthesized in tkGrab.c. */
+ TkGrabEvent *firstGrabEventPtr;
+ /* First in list of enter/leave events
+ * synthesized by grab code. These events must
+ * be processed in order before any other
+ * events are processed. NULL means no such
+ * events. */
+ TkGrabEvent *lastGrabEventPtr;
+ /* Last in list of synthesized events, or NULL
+ * if list is empty. */
+ int grabFlags; /* Miscellaneous flag values. See definitions
+ * in tkGrab.c. */
+
+ /*
+ * Information used by tkGrid.c only:
+ */
+
+ int gridInit; /* 0 means table below needs initializing. */
+ Tcl_HashTable gridHashTable;/* Maps from Tk_Window tokens to corresponding
+ * Grid structures. */
+
+ /*
+ * Information used by tkImage.c only:
+ */
+
+ int imageId; /* Value used to number image ids. */
+
+ /*
+ * Information used by tkMacWinMenu.c only:
+ */
+
+ int postCommandGeneration;
+
+ /*
+ * Information used by tkPack.c only.
+ */
+
+ int packInit; /* 0 means table below needs initializing. */
+ Tcl_HashTable packerHashTable;
+ /* Maps from Tk_Window tokens to corresponding
+ * Packer structures. */
+
+ /*
+ * Information used by tkPlace.c only.
+ */
+
+ int placeInit; /* 0 means tables below need initializing. */
+ Tcl_HashTable masterTable; /* Maps from Tk_Window toke to the Master
+ * structure for the window, if it exists. */
+ Tcl_HashTable slaveTable; /* Maps from Tk_Window toke to the Slave
+ * structure for the window, if it exists. */
+
+ /*
+ * Information used by tkSelect.c and tkClipboard.c only:
+ */
+
+ struct TkSelectionInfo *selectionInfoPtr;
+ /* First in list of selection information
+ * records. Each entry contains information
+ * about the current owner of a particular
+ * selection on this display. */
+ Atom multipleAtom; /* Atom for MULTIPLE. None means selection
+ * stuff isn't initialized. */
+ Atom incrAtom; /* Atom for INCR. */
+ Atom targetsAtom; /* Atom for TARGETS. */
+ Atom timestampAtom; /* Atom for TIMESTAMP. */
+ Atom textAtom; /* Atom for TEXT. */
+ Atom compoundTextAtom; /* Atom for COMPOUND_TEXT. */
+ Atom applicationAtom; /* Atom for TK_APPLICATION. */
+ Atom windowAtom; /* Atom for TK_WINDOW. */
+ Atom clipboardAtom; /* Atom for CLIPBOARD. */
+ Atom utf8Atom; /* Atom for UTF8_STRING. */
+ Atom atomPairAtom; /* Atom for ATOM_PAIR. */
+
+ Tk_Window clipWindow; /* Window used for clipboard ownership and to
+ * retrieve selections between processes. NULL
+ * means clipboard info hasn't been
+ * initialized. */
+ int clipboardActive; /* 1 means we currently own the clipboard
+ * selection, 0 means we don't. */
+ struct TkMainInfo *clipboardAppPtr;
+ /* Last application that owned clipboard. */
+ struct TkClipboardTarget *clipTargetPtr;
+ /* First in list of clipboard type information
+ * records. Each entry contains information
+ * about the buffers for a given selection
+ * target. */
+
+ /*
+ * Information used by tkSend.c only:
+ */
+
+ Tk_Window commTkwin; /* Window used for communication between
+ * interpreters during "send" commands. NULL
+ * means send info hasn't been initialized
+ * yet. */
+ Atom commProperty; /* X's name for comm property. */
+ Atom registryProperty; /* X's name for property containing registry
+ * of interpreter names. */
+ Atom appNameProperty; /* X's name for property used to hold the
+ * application name on each comm window. */
+
+ /*
+ * Information used by tkUnixWm.c and tkWinWm.c only:
+ */
+
+ struct TkWmInfo *firstWmPtr;/* Points to first top-level window. */
+ struct TkWmInfo *foregroundWmPtr;
+ /* Points to the foreground window. */
+
+ /*
+ * Information used by tkVisual.c only:
+ */
+
+ TkColormap *cmapPtr; /* First in list of all non-default colormaps
+ * allocated for this display. */
+
+ /*
+ * Miscellaneous information:
+ */
+
+#ifdef TK_USE_INPUT_METHODS
+ XIM inputMethod; /* Input method for this display. */
+ XIMStyle inputStyle; /* Input style selected for this display. */
+ XFontSet inputXfs; /* XFontSet cached for over-the-spot XIM. */
+#endif /* TK_USE_INPUT_METHODS */
+ Tcl_HashTable winTable; /* Maps from X window ids to TkWindow ptrs. */
+
+ int refCount; /* Reference count of how many Tk applications
+ * are using this display. Used to clean up
+ * the display when we no longer have any Tk
+ * applications using it. */
+
+ /*
+ * The following field were all added for Tk8.3
+ */
+
+ int mouseButtonState; /* Current mouse button state for this
+ * display. */
+ Window mouseButtonWindow; /* Window the button state was set in, added
+ * in Tk 8.4. */
+ Tk_Window warpWindow;
+ Tk_Window warpMainwin; /* For finding the root window for warping
+ * purposes. */
+ int warpX;
+ int warpY;
+
+ /*
+ * The following field(s) were all added for Tk8.4
+ */
+
+ unsigned int flags; /* Various flag values: these are all defined
+ * in below. */
+ TkCaret caret; /* Information about the caret for this
+ * display. This is not a pointer. */
+
+ int iconDataSize; /* Size of default iconphoto image data. */
+ unsigned char *iconDataPtr; /* Default iconphoto image data, if set. */
+#ifdef TK_USE_INPUT_METHODS
+ int ximGeneration; /* Used to invalidate XIC */
+#endif /* TK_USE_INPUT_METHODS */
+} TkDisplay;
+
+/*
+ * Flag values for TkDisplay flags.
+ * TK_DISPLAY_COLLAPSE_MOTION_EVENTS: (default on)
+ * Indicates that we should collapse motion events on this display
+ * TK_DISPLAY_USE_IM: (default on, set via tk.tcl)
+ * Whether to use input methods for this display
+ * TK_DISPLAY_WM_TRACING: (default off)
+ * Whether we should do wm tracing on this display.
+ * TK_DISPLAY_IN_WARP: (default off)
+ * Indicates that we are in a pointer warp
+ */
+
+#define TK_DISPLAY_COLLAPSE_MOTION_EVENTS (1 << 0)
+#define TK_DISPLAY_USE_IM (1 << 1)
+#define TK_DISPLAY_WM_TRACING (1 << 3)
+#define TK_DISPLAY_IN_WARP (1 << 4)
+#define TK_DISPLAY_USE_XKB (1 << 5)
+
+/*
+ * One of the following structures exists for each error handler created by a
+ * call to Tk_CreateErrorHandler. The structure is managed by tkError.c.
+ */
+
+typedef struct TkErrorHandler {
+ TkDisplay *dispPtr; /* Display to which handler applies. */
+ unsigned long firstRequest; /* Only errors with serial numbers >= to this
+ * are considered. */
+ unsigned long lastRequest; /* Only errors with serial numbers <= to this
+ * are considered. This field is filled in
+ * when XUnhandle is called. -1 means
+ * XUnhandle hasn't been called yet. */
+ int error; /* Consider only errors with this error_code
+ * (-1 means consider all errors). */
+ int request; /* Consider only errors with this major
+ * request code (-1 means consider all major
+ * codes). */
+ int minorCode; /* Consider only errors with this minor
+ * request code (-1 means consider all minor
+ * codes). */
+ Tk_ErrorProc *errorProc; /* Function to invoke when a matching error
+ * occurs. NULL means just ignore errors. */
+ ClientData clientData; /* Arbitrary value to pass to errorProc. */
+ struct TkErrorHandler *nextPtr;
+ /* Pointer to next older handler for this
+ * display, or NULL for end of list. */
+} TkErrorHandler;
+
+/*
+ * One of the following structures exists for each event handler created by
+ * calling Tk_CreateEventHandler. This information is used by tkEvent.c only.
+ */
+
+typedef struct TkEventHandler {
+ unsigned long mask; /* Events for which to invoke proc. */
+ Tk_EventProc *proc; /* Function to invoke when an event in mask
+ * occurs. */
+ ClientData clientData; /* Argument to pass to proc. */
+ struct TkEventHandler *nextPtr;
+ /* Next in list of handlers associated with
+ * window (NULL means end of list). */
+} TkEventHandler;
+
+/*
+ * Tk keeps one of the following data structures for each main window (created
+ * by a call to TkCreateMainWindow). It stores information that is shared by
+ * all of the windows associated with a particular main window.
+ */
+
+typedef struct TkMainInfo {
+ int refCount; /* Number of windows whose "mainPtr" fields
+ * point here. When this becomes zero, can
+ * free up the structure (the reference count
+ * is zero because windows can get deleted in
+ * almost any order; the main window isn't
+ * necessarily the last one deleted). */
+ struct TkWindow *winPtr; /* Pointer to main window. */
+ Tcl_Interp *interp; /* Interpreter associated with application. */
+ Tcl_HashTable nameTable; /* Hash table mapping path names to TkWindow
+ * structs for all windows related to this
+ * main window. Managed by tkWindow.c. */
+ long deletionEpoch; /* Incremented by window deletions. */
+ Tk_BindingTable bindingTable;
+ /* Used in conjunction with "bind" command to
+ * bind events to Tcl commands. */
+ TkBindInfo bindInfo; /* Information used by tkBind.c on a per
+ * application basis. */
+ struct TkFontInfo *fontInfoPtr;
+ /* Information used by tkFont.c on a per
+ * application basis. */
+
+ /*
+ * Information used only by tkFocus.c and tk*Embed.c:
+ */
+
+ struct TkToplevelFocusInfo *tlFocusPtr;
+ /* First in list of records containing focus
+ * information for each top-level in the
+ * application. Used only by tkFocus.c. */
+ struct TkDisplayFocusInfo *displayFocusPtr;
+ /* First in list of records containing focus
+ * information for each display that this
+ * application has ever used. Used only by
+ * tkFocus.c. */
+
+ struct ElArray *optionRootPtr;
+ /* Top level of option hierarchy for this main
+ * window. NULL means uninitialized. Managed
+ * by tkOption.c. */
+ Tcl_HashTable imageTable; /* Maps from image names to Tk_ImageMaster
+ * structures. Managed by tkImage.c. */
+ int strictMotif; /* This is linked to the tk_strictMotif global
+ * variable. */
+ int alwaysShowSelection; /* This is linked to the
+ * ::tk::AlwaysShowSelection variable. */
+ struct TkMainInfo *nextPtr; /* Next in list of all main windows managed by
+ * this process. */
+ Tcl_HashTable busyTable; /* Information used by [tk busy] command. */
+} TkMainInfo;
+
+/*
+ * Tk keeps the following data structure for each of it's builtin bitmaps.
+ * This structure is only used by tkBitmap.c and other platform specific
+ * bitmap files.
+ */
+
+typedef struct {
+ const void *source; /* Bits for bitmap. */
+ int width, height; /* Dimensions of bitmap. */
+ int native; /* 0 means generic (X style) bitmap, 1 means
+ * native style bitmap. */
+} TkPredefBitmap;
+
+/*
+ * Tk keeps one of the following structures for each window. Some of the
+ * information (like size and location) is a shadow of information managed by
+ * the X server, and some is special information used here, such as event and
+ * geometry management information. This information is (mostly) managed by
+ * tkWindow.c. WARNING: the declaration below must be kept consistent with the
+ * Tk_FakeWin structure in tk.h. If you change one, be sure to change the
+ * other!
+ */
+
+typedef struct TkWindow {
+ /*
+ * Structural information:
+ */
+
+ Display *display; /* Display containing window. */
+ TkDisplay *dispPtr; /* Tk's information about display for
+ * window. */
+ int screenNum; /* Index of screen for window, among all those
+ * for dispPtr. */
+ Visual *visual; /* Visual to use for window. If not default,
+ * MUST be set before X window is created. */
+ int depth; /* Number of bits/pixel. */
+ Window window; /* X's id for window. NULL means window hasn't
+ * actually been created yet, or it's been
+ * deleted. */
+ struct TkWindow *childList; /* First in list of child windows, or NULL if
+ * no children. List is in stacking order,
+ * lowest window first.*/
+ struct TkWindow *lastChildPtr;
+ /* Last in list of child windows (highest in
+ * stacking order), or NULL if no children. */
+ struct TkWindow *parentPtr; /* Pointer to parent window (logical parent,
+ * not necessarily X parent). NULL means
+ * either this is the main window, or the
+ * window's parent has already been deleted. */
+ struct TkWindow *nextPtr; /* Next higher sibling (in stacking order) in
+ * list of children with same parent. NULL
+ * means end of list. */
+ TkMainInfo *mainPtr; /* Information shared by all windows
+ * associated with a particular main window.
+ * NULL means this window is a rogue that is
+ * not associated with any application (at
+ * present, this only happens for the dummy
+ * windows used for "send" communication). */
+
+ /*
+ * Name and type information for the window:
+ */
+
+ char *pathName; /* Path name of window (concatenation of all
+ * names between this window and its top-level
+ * ancestor). This is a pointer into an entry
+ * in mainPtr->nameTable. NULL means that the
+ * window hasn't been completely created
+ * yet. */
+ Tk_Uid nameUid; /* Name of the window within its parent
+ * (unique within the parent). */
+ Tk_Uid classUid; /* Class of the window. NULL means window
+ * hasn't been given a class yet. */
+
+ /*
+ * Geometry and other attributes of window. This information may not be
+ * updated on the server immediately; stuff that hasn't been reflected in
+ * the server yet is called "dirty". At present, information can be dirty
+ * only if the window hasn't yet been created.
+ */
+
+ XWindowChanges changes; /* Geometry and other info about window. */
+ unsigned int dirtyChanges; /* Bits indicate fields of "changes" that are
+ * dirty. */
+ XSetWindowAttributes atts; /* Current attributes of window. */
+ unsigned long dirtyAtts; /* Bits indicate fields of "atts" that are
+ * dirty. */
+
+ unsigned int flags; /* Various flag values: these are all defined
+ * in tk.h (confusing, but they're needed
+ * there for some query macros). */
+
+ /*
+ * Information kept by the event manager (tkEvent.c):
+ */
+
+ TkEventHandler *handlerList;/* First in list of event handlers declared
+ * for this window, or NULL if none. */
+#ifdef TK_USE_INPUT_METHODS
+ XIC inputContext; /* XIM input context. */
+#endif /* TK_USE_INPUT_METHODS */
+
+ /*
+ * Information used for event bindings (see "bind" and "bindtags" commands
+ * in tkCmds.c):
+ */
+
+ ClientData *tagPtr; /* Points to array of tags used for bindings
+ * on this window. Each tag is a Tk_Uid.
+ * Malloc'ed. NULL means no tags. */
+ int numTags; /* Number of tags at *tagPtr. */
+
+ /*
+ * Information used by tkOption.c to manage options for the window.
+ */
+
+ int optionLevel; /* -1 means no option information is currently
+ * cached for this window. Otherwise this
+ * gives the level in the option stack at
+ * which info is cached. */
+ /*
+ * Information used by tkSelect.c to manage the selection.
+ */
+
+ struct TkSelHandler *selHandlerList;
+ /* First in list of handlers for returning the
+ * selection in various forms. */
+
+ /*
+ * Information used by tkGeometry.c for geometry management.
+ */
+
+ const Tk_GeomMgr *geomMgrPtr;
+ /* Information about geometry manager for this
+ * window. */
+ ClientData geomData; /* Argument for geometry manager functions. */
+ int reqWidth, reqHeight; /* Arguments from last call to
+ * Tk_GeometryRequest, or 0's if
+ * Tk_GeometryRequest hasn't been called. */
+ int internalBorderLeft; /* Width of internal border of window (0 means
+ * no internal border). Geometry managers
+ * should not normally place children on top
+ * of the border. Fields for the other three
+ * sides are found below. */
+
+ /*
+ * Information maintained by tkWm.c for window manager communication.
+ */
+
+ struct TkWmInfo *wmInfoPtr; /* For top-level windows (and also for special
+ * Unix menubar and wrapper windows), points
+ * to structure with wm-related info (see
+ * tkWm.c). For other windows, this is
+ * NULL. */
+
+ /*
+ * Information used by widget classes.
+ */
+
+ const Tk_ClassProcs *classProcsPtr;
+ ClientData instanceData;
+
+ /*
+ * Platform specific information private to each port.
+ */
+
+ struct TkWindowPrivate *privatePtr;
+
+ /*
+ * More information used by tkGeometry.c for geometry management.
+ */
+
+ /* The remaining fields of internal border. */
+ int internalBorderRight;
+ int internalBorderTop;
+ int internalBorderBottom;
+
+ int minReqWidth; /* Minimum requested width. */
+ int minReqHeight; /* Minimum requested height. */
+#ifdef TK_USE_INPUT_METHODS
+ int ximGeneration; /* Used to invalidate XIC */
+#endif /* TK_USE_INPUT_METHODS */
+ char *geomMgrName; /* Records the name of the geometry manager. */
+ struct TkWindow *maintainerPtr;
+ /* The geometry master for this window. The
+ * value is NULL if the window has no master or
+ * if its master is its parent. */
+} TkWindow;
+
+/*
+ * Real definition of some events. Note that these events come from outside
+ * but have internally generated pieces added to them.
+ */
+
+typedef struct {
+ XKeyEvent keyEvent; /* The real event from X11. */
+ char *charValuePtr; /* A pointer to a string that holds the key's
+ * %A substitution text (before backslash
+ * adding), or NULL if that has not been
+ * computed yet. If non-NULL, this string was
+ * allocated with ckalloc(). */
+ int charValueLen; /* Length of string in charValuePtr when that
+ * is non-NULL. */
+ KeySym keysym; /* Key symbol computed after input methods
+ * have been invoked */
+} TkKeyEvent;
+
+/*
+ * Flags passed to TkpMakeMenuWindow's 'transient' argument.
+ */
+
+#define TK_MAKE_MENU_TEAROFF 0 /* Only non-transient case. */
+#define TK_MAKE_MENU_POPUP 1
+#define TK_MAKE_MENU_DROPDOWN 2
+
+/*
+ * The following structure is used with TkMakeEnsemble to create ensemble
+ * commands and optionally to create sub-ensembles.
+ */
+
+typedef struct TkEnsemble {
+ const char *name;
+ Tcl_ObjCmdProc *proc;
+ const struct TkEnsemble *subensemble;
+} TkEnsemble;
+
+/*
+ * The following structure is used as a two way map between integers and
+ * strings, usually to map between an internal C representation and the
+ * strings used in Tcl.
+ */
+
+typedef struct TkStateMap {
+ int numKey; /* Integer representation of a value. */
+ const char *strKey; /* String representation of a value. */
+} TkStateMap;
+
+/*
+ * This structure is used by the Mac and Window porting layers as the internal
+ * representation of a clip_mask in a GC.
+ */
+
+typedef struct TkpClipMask {
+ int type; /* TKP_CLIP_PIXMAP or TKP_CLIP_REGION. */
+ union {
+ Pixmap pixmap;
+ TkRegion region;
+ } value;
+} TkpClipMask;
+
+#define TKP_CLIP_PIXMAP 0
+#define TKP_CLIP_REGION 1
+
+/*
+ * Return values from TkGrabState:
+ */
+
+#define TK_GRAB_NONE 0
+#define TK_GRAB_IN_TREE 1
+#define TK_GRAB_ANCESTOR 2
+#define TK_GRAB_EXCLUDED 3
+
+/*
+ * Additional flag for TkpMeasureCharsInContext. Coordinate with other flags
+ * for this routine, but don't make public until TkpMeasureCharsInContext is
+ * made public, too.
+ */
+
+#define TK_ISOLATE_END 32
+
+/*
+ * The macro below is used to modify a "char" value (e.g. by casting it to an
+ * unsigned character) so that it can be used safely with macros such as
+ * isspace().
+ */
+
+#define UCHAR(c) ((unsigned char) (c))
+
+/*
+ * The following symbol is used in the mode field of FocusIn events generated
+ * by an embedded application to request the input focus from its container.
+ */
+
+#define EMBEDDED_APP_WANTS_FOCUS (NotifyNormal + 20)
+
+/*
+ * The following special modifier mask bits are defined, to indicate logical
+ * modifiers such as Meta and Alt that may float among the actual modifier
+ * bits.
+ */
+
+#define META_MASK (AnyModifier<<1)
+#define ALT_MASK (AnyModifier<<2)
+#define EXTENDED_MASK (AnyModifier<<3)
+
+/*
+ * Object types not declared in tkObj.c need to be mentioned here so they can
+ * be properly registered with Tcl:
+ */
+
+MODULE_SCOPE const Tcl_ObjType tkBorderObjType;
+MODULE_SCOPE const Tcl_ObjType tkBitmapObjType;
+MODULE_SCOPE const Tcl_ObjType tkColorObjType;
+MODULE_SCOPE const Tcl_ObjType tkCursorObjType;
+MODULE_SCOPE const Tcl_ObjType tkFontObjType;
+MODULE_SCOPE const Tcl_ObjType tkStateKeyObjType;
+MODULE_SCOPE const Tcl_ObjType tkTextIndexType;
+
+/*
+ * Miscellaneous variables shared among Tk modules but not exported to the
+ * outside world:
+ */
+
+MODULE_SCOPE const Tk_SmoothMethod tkBezierSmoothMethod;
+MODULE_SCOPE Tk_ImageType tkBitmapImageType;
+MODULE_SCOPE Tk_PhotoImageFormat tkImgFmtGIF;
+MODULE_SCOPE void (*tkHandleEventProc) (XEvent* eventPtr);
+MODULE_SCOPE Tk_PhotoImageFormat tkImgFmtPNG;
+MODULE_SCOPE Tk_PhotoImageFormat tkImgFmtPPM;
+MODULE_SCOPE TkMainInfo *tkMainWindowList;
+MODULE_SCOPE Tk_ImageType tkPhotoImageType;
+MODULE_SCOPE Tcl_HashTable tkPredefBitmapTable;
+
+MODULE_SCOPE const char *const tkWebColors[20];
+
+/*
+ * The definition of pi, at least from the perspective of double-precision
+ * floats.
+ */
+
+#ifndef PI
+#ifdef M_PI
+#define PI M_PI
+#else
+#define PI 3.14159265358979323846
+#endif
+#endif
+
+/*
+ * Support for Clang Static Analyzer <http://clang-analyzer.llvm.org>
+ */
+
+#if defined(PURIFY) && defined(__clang__)
+#if __has_feature(attribute_analyzer_noreturn) && \
+ !defined(Tcl_Panic) && defined(Tcl_Panic_TCL_DECLARED)
+void Tcl_Panic(const char *, ...) __attribute__((analyzer_noreturn));
+#endif
+#if !defined(CLANG_ASSERT)
+#include <assert.h>
+#define CLANG_ASSERT(x) assert(x)
+#endif
+#elif !defined(CLANG_ASSERT)
+#define CLANG_ASSERT(x)
+#endif /* PURIFY && __clang__ */
+
+/*
+ * The following magic value is stored in the "send_event" field of FocusIn
+ * and FocusOut events. This allows us to separate "real" events coming from
+ * the server from those that we generated.
+ */
+
+#define GENERATED_FOCUS_EVENT_MAGIC ((Bool) 0x547321ac)
+
+/*
+ * Exported internals.
+ */
+
+#include "tkIntDecls.h"
+
+/*
+ * Themed widget set init function:
+ */
+
+MODULE_SCOPE int Ttk_Init(Tcl_Interp *interp);
+
+/*
+ * Internal functions shared among Tk modules but not exported to the outside
+ * world:
+ */
+
+MODULE_SCOPE int Tk_BellObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_BindObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_BindtagsObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_BusyObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_ButtonObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_CanvasObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int argc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_CheckbuttonObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_ClipboardObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_ChooseColorObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_ChooseDirectoryObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_DestroyObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_EntryObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_EventObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_FrameObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_FocusObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_FontObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_GetOpenFileObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_GetSaveFileObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_GrabObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_GridObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_ImageObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_LabelObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_LabelframeObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_ListboxObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_LowerObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_MenuObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_MenubuttonObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_MessageBoxObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_MessageObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_PanedWindowObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_OptionObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_PackObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_PlaceObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_RadiobuttonObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_RaiseObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_ScaleObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_ScrollbarObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_SelectionObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_SendObjCmd(ClientData clientData,
+ Tcl_Interp *interp,int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_SendObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_SpinboxObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_TextObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_TkwaitObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_ToplevelObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_UpdateObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_WinfoObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tk_WmObjCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+
+MODULE_SCOPE int Tk_GetDoublePixelsFromObj(Tcl_Interp *interp,
+ Tk_Window tkwin, Tcl_Obj *objPtr,
+ double *doublePtr);
+MODULE_SCOPE int TkSetGeometryMaster(Tcl_Interp *interp,
+ Tk_Window tkwin, const char *master);
+MODULE_SCOPE void TkFreeGeometryMaster(Tk_Window tkwin,
+ const char *master);
+
+MODULE_SCOPE void TkEventInit(void);
+MODULE_SCOPE void TkRegisterObjTypes(void);
+MODULE_SCOPE int TkDeadAppObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *const argv[]);
+MODULE_SCOPE int TkCanvasGetCoordObj(Tcl_Interp *interp,
+ Tk_Canvas canvas, Tcl_Obj *obj,
+ double *doublePtr);
+MODULE_SCOPE int TkGetDoublePixels(Tcl_Interp *interp, Tk_Window tkwin,
+ const char *string, double *doublePtr);
+MODULE_SCOPE int TkPostscriptImage(Tcl_Interp *interp, Tk_Window tkwin,
+ Tk_PostscriptInfo psInfo, XImage *ximage,
+ int x, int y, int width, int height);
+MODULE_SCOPE void TkMapTopFrame(Tk_Window tkwin);
+MODULE_SCOPE XEvent * TkpGetBindingXEvent(Tcl_Interp *interp);
+MODULE_SCOPE void TkCreateExitHandler(Tcl_ExitProc *proc,
+ ClientData clientData);
+MODULE_SCOPE void TkDeleteExitHandler(Tcl_ExitProc *proc,
+ ClientData clientData);
+MODULE_SCOPE Tcl_ExitProc TkFinalize;
+MODULE_SCOPE Tcl_ExitProc TkFinalizeThread;
+MODULE_SCOPE void TkpBuildRegionFromAlphaData(TkRegion region,
+ unsigned x, unsigned y, unsigned width,
+ unsigned height, unsigned char *dataPtr,
+ unsigned pixelStride, unsigned lineStride);
+MODULE_SCOPE void TkAppendPadAmount(Tcl_Obj *bufferObj,
+ const char *buffer, int pad1, int pad2);
+MODULE_SCOPE int TkParsePadAmount(Tcl_Interp *interp,
+ Tk_Window tkwin, Tcl_Obj *objPtr,
+ int *pad1Ptr, int *pad2Ptr);
+MODULE_SCOPE void TkFocusSplit(TkWindow *winPtr);
+MODULE_SCOPE void TkFocusJoin(TkWindow *winPtr);
+MODULE_SCOPE int TkpAlwaysShowSelection(Tk_Window tkwin);
+MODULE_SCOPE void TkpDrawCharsInContext(Display * display,
+ Drawable drawable, GC gc, Tk_Font tkfont,
+ const char *source, int numBytes, int rangeStart,
+ int rangeLength, int x, int y);
+MODULE_SCOPE int TkpMeasureCharsInContext(Tk_Font tkfont,
+ const char *source, int numBytes, int rangeStart,
+ int rangeLength, int maxLength, int flags,
+ int *lengthPtr);
+MODULE_SCOPE void TkUnderlineCharsInContext(Display *display,
+ Drawable drawable, GC gc, Tk_Font tkfont,
+ const char *string, int numBytes, int x, int y,
+ int firstByte, int lastByte);
+MODULE_SCOPE void TkpGetFontAttrsForChar(Tk_Window tkwin, Tk_Font tkfont,
+ int c, struct TkFontAttributes *faPtr);
+MODULE_SCOPE Tcl_Obj * TkNewWindowObj(Tk_Window tkwin);
+MODULE_SCOPE void TkpShowBusyWindow(TkBusy busy);
+MODULE_SCOPE void TkpHideBusyWindow(TkBusy busy);
+MODULE_SCOPE void TkpMakeTransparentWindowExist(Tk_Window tkwin,
+ Window parent);
+MODULE_SCOPE void TkpCreateBusy(Tk_FakeWin *winPtr, Tk_Window tkRef,
+ Window *parentPtr, Tk_Window tkParent,
+ TkBusy busy);
+MODULE_SCOPE int TkBackgroundEvalObjv(Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv, int flags);
+MODULE_SCOPE void TkSendVirtualEvent(Tk_Window tgtWin,
+ const char *eventName, Tcl_Obj *detail);
+MODULE_SCOPE Tcl_Command TkMakeEnsemble(Tcl_Interp *interp,
+ const char *nsname, const char *name,
+ ClientData clientData, const TkEnsemble *map);
+MODULE_SCOPE int TkInitTkCmd(Tcl_Interp *interp,
+ ClientData clientData);
+MODULE_SCOPE int TkInitFontchooser(Tcl_Interp *interp,
+ ClientData clientData);
+MODULE_SCOPE void TkpWarpPointer(TkDisplay *dispPtr);
+MODULE_SCOPE void TkpCancelWarp(TkDisplay *dispPtr);
+MODULE_SCOPE int TkListCreateFrame(ClientData clientData,
+ Tcl_Interp *interp, Tcl_Obj *listObj,
+ int toplevel, Tcl_Obj *nameObj);
+
+#ifdef _WIN32
+#define TkParseColor XParseColor
+#else
+MODULE_SCOPE Status TkParseColor (Display * display,
+ Colormap map, const char* spec,
+ XColor * colorPtr);
+#endif
+#ifdef HAVE_XFT
+MODULE_SCOPE void TkUnixSetXftClipRegion(TkRegion clipRegion);
+#endif
+
+#if TCL_UTF_MAX > 4
+# define TkUtfToUniChar Tcl_UtfToUniChar
+# define TkUniCharToUtf Tcl_UniCharToUtf
+#else
+ MODULE_SCOPE int TkUtfToUniChar(const char *, int *);
+ MODULE_SCOPE int TkUniCharToUtf(int, char *);
+#endif
+
+/*
+ * Unsupported commands.
+ */
+
+MODULE_SCOPE int TkUnsupported1ObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+
+/*
+ * For Tktest.
+ */
+MODULE_SCOPE int SquareObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj * const objv[]);
+MODULE_SCOPE int TkOldTestInit(Tcl_Interp *interp);
+#if !(defined(_WIN32) || defined(MAC_OSX_TK))
+#define TkplatformtestInit(x) TCL_OK
+#else
+MODULE_SCOPE int TkplatformtestInit(Tcl_Interp *interp);
+#endif
+
+#endif /* _TKINT */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkIntDecls.h b/tk8.6/generic/tkIntDecls.h
new file mode 100644
index 0000000..b8addbd
--- /dev/null
+++ b/tk8.6/generic/tkIntDecls.h
@@ -0,0 +1,1179 @@
+/*
+ * tkIntDecls.h --
+ *
+ * This file contains the declarations for all unsupported
+ * functions that are exported by the Tk library. These
+ * interfaces are not guaranteed to remain the same between
+ * versions. Use at your own risk.
+ *
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef _TKINTDECLS
+#define _TKINTDECLS
+
+#ifdef BUILD_tk
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLEXPORT
+#endif
+
+struct TkText;
+typedef struct TkTextBTree_ *TkTextBTree;
+struct TkTextDispChunk;
+struct TkTextIndex;
+struct TkTextSegment;
+struct TkSharedText;
+
+/*
+ * WARNING: This file is automatically generated by the tools/genStubs.tcl
+ * script. Any modifications to the function declarations below should be made
+ * in the generic/tkInt.decls script.
+ */
+
+/* !BEGIN!: Do not edit below this line. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Exported function declarations:
+ */
+
+/* 0 */
+EXTERN TkWindow * TkAllocWindow(TkDisplay *dispPtr, int screenNum,
+ TkWindow *parentPtr);
+/* 1 */
+EXTERN void TkBezierPoints(double control[], int numSteps,
+ double *coordPtr);
+/* 2 */
+EXTERN void TkBezierScreenPoints(Tk_Canvas canvas,
+ double control[], int numSteps,
+ XPoint *xPointPtr);
+/* Slot 3 is reserved */
+/* 4 */
+EXTERN void TkBindEventProc(TkWindow *winPtr, XEvent *eventPtr);
+/* 5 */
+EXTERN void TkBindFree(TkMainInfo *mainPtr);
+/* 6 */
+EXTERN void TkBindInit(TkMainInfo *mainPtr);
+/* 7 */
+EXTERN void TkChangeEventWindow(XEvent *eventPtr,
+ TkWindow *winPtr);
+/* 8 */
+EXTERN int TkClipInit(Tcl_Interp *interp, TkDisplay *dispPtr);
+/* 9 */
+EXTERN void TkComputeAnchor(Tk_Anchor anchor, Tk_Window tkwin,
+ int padX, int padY, int innerWidth,
+ int innerHeight, int *xPtr, int *yPtr);
+/* Slot 10 is reserved */
+/* Slot 11 is reserved */
+/* 12 */
+EXTERN TkCursor * TkCreateCursorFromData(Tk_Window tkwin,
+ const char *source, const char *mask,
+ int width, int height, int xHot, int yHot,
+ XColor fg, XColor bg);
+/* 13 */
+EXTERN int TkCreateFrame(ClientData clientData,
+ Tcl_Interp *interp, int argc,
+ const char *const *argv, int toplevel,
+ const char *appName);
+/* 14 */
+EXTERN Tk_Window TkCreateMainWindow(Tcl_Interp *interp,
+ const char *screenName, const char *baseName);
+/* 15 */
+EXTERN Time TkCurrentTime(TkDisplay *dispPtr);
+/* 16 */
+EXTERN void TkDeleteAllImages(TkMainInfo *mainPtr);
+/* 17 */
+EXTERN void TkDoConfigureNotify(TkWindow *winPtr);
+/* 18 */
+EXTERN void TkDrawInsetFocusHighlight(Tk_Window tkwin, GC gc,
+ int width, Drawable drawable, int padding);
+/* 19 */
+EXTERN void TkEventDeadWindow(TkWindow *winPtr);
+/* 20 */
+EXTERN void TkFillPolygon(Tk_Canvas canvas, double *coordPtr,
+ int numPoints, Display *display,
+ Drawable drawable, GC gc, GC outlineGC);
+/* 21 */
+EXTERN int TkFindStateNum(Tcl_Interp *interp,
+ const char *option, const TkStateMap *mapPtr,
+ const char *strKey);
+/* 22 */
+EXTERN CONST86 char * TkFindStateString(const TkStateMap *mapPtr,
+ int numKey);
+/* 23 */
+EXTERN void TkFocusDeadWindow(TkWindow *winPtr);
+/* 24 */
+EXTERN int TkFocusFilterEvent(TkWindow *winPtr,
+ XEvent *eventPtr);
+/* 25 */
+EXTERN TkWindow * TkFocusKeyEvent(TkWindow *winPtr, XEvent *eventPtr);
+/* 26 */
+EXTERN void TkFontPkgInit(TkMainInfo *mainPtr);
+/* 27 */
+EXTERN void TkFontPkgFree(TkMainInfo *mainPtr);
+/* 28 */
+EXTERN void TkFreeBindingTags(TkWindow *winPtr);
+/* 29 */
+EXTERN void TkpFreeCursor(TkCursor *cursorPtr);
+/* 30 */
+EXTERN char * TkGetBitmapData(Tcl_Interp *interp,
+ const char *string, const char *fileName,
+ int *widthPtr, int *heightPtr, int *hotXPtr,
+ int *hotYPtr);
+/* 31 */
+EXTERN void TkGetButtPoints(double p1[], double p2[],
+ double width, int project, double m1[],
+ double m2[]);
+/* 32 */
+EXTERN TkCursor * TkGetCursorByName(Tcl_Interp *interp,
+ Tk_Window tkwin, Tk_Uid string);
+/* 33 */
+EXTERN const char * TkGetDefaultScreenName(Tcl_Interp *interp,
+ const char *screenName);
+/* 34 */
+EXTERN TkDisplay * TkGetDisplay(Display *display);
+/* 35 */
+EXTERN int TkGetDisplayOf(Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[], Tk_Window *tkwinPtr);
+/* 36 */
+EXTERN TkWindow * TkGetFocusWin(TkWindow *winPtr);
+/* 37 */
+EXTERN int TkGetInterpNames(Tcl_Interp *interp, Tk_Window tkwin);
+/* 38 */
+EXTERN int TkGetMiterPoints(double p1[], double p2[],
+ double p3[], double width, double m1[],
+ double m2[]);
+/* 39 */
+EXTERN void TkGetPointerCoords(Tk_Window tkwin, int *xPtr,
+ int *yPtr);
+/* 40 */
+EXTERN void TkGetServerInfo(Tcl_Interp *interp, Tk_Window tkwin);
+/* 41 */
+EXTERN void TkGrabDeadWindow(TkWindow *winPtr);
+/* 42 */
+EXTERN int TkGrabState(TkWindow *winPtr);
+/* 43 */
+EXTERN void TkIncludePoint(Tk_Item *itemPtr, double *pointPtr);
+/* 44 */
+EXTERN void TkInOutEvents(XEvent *eventPtr, TkWindow *sourcePtr,
+ TkWindow *destPtr, int leaveType,
+ int enterType, Tcl_QueuePosition position);
+/* 45 */
+EXTERN void TkInstallFrameMenu(Tk_Window tkwin);
+/* 46 */
+EXTERN CONST86 char * TkKeysymToString(KeySym keysym);
+/* 47 */
+EXTERN int TkLineToArea(double end1Ptr[], double end2Ptr[],
+ double rectPtr[]);
+/* 48 */
+EXTERN double TkLineToPoint(double end1Ptr[], double end2Ptr[],
+ double pointPtr[]);
+/* 49 */
+EXTERN int TkMakeBezierCurve(Tk_Canvas canvas, double *pointPtr,
+ int numPoints, int numSteps,
+ XPoint xPoints[], double dblPoints[]);
+/* 50 */
+EXTERN void TkMakeBezierPostscript(Tcl_Interp *interp,
+ Tk_Canvas canvas, double *pointPtr,
+ int numPoints);
+/* 51 */
+EXTERN void TkOptionClassChanged(TkWindow *winPtr);
+/* 52 */
+EXTERN void TkOptionDeadWindow(TkWindow *winPtr);
+/* 53 */
+EXTERN int TkOvalToArea(double *ovalPtr, double *rectPtr);
+/* 54 */
+EXTERN double TkOvalToPoint(double ovalPtr[], double width,
+ int filled, double pointPtr[]);
+/* 55 */
+EXTERN int TkpChangeFocus(TkWindow *winPtr, int force);
+/* 56 */
+EXTERN void TkpCloseDisplay(TkDisplay *dispPtr);
+/* 57 */
+EXTERN void TkpClaimFocus(TkWindow *topLevelPtr, int force);
+/* 58 */
+EXTERN void TkpDisplayWarning(const char *msg, const char *title);
+/* 59 */
+EXTERN void TkpGetAppName(Tcl_Interp *interp, Tcl_DString *name);
+/* 60 */
+EXTERN TkWindow * TkpGetOtherWindow(TkWindow *winPtr);
+/* 61 */
+EXTERN TkWindow * TkpGetWrapperWindow(TkWindow *winPtr);
+/* 62 */
+EXTERN int TkpInit(Tcl_Interp *interp);
+/* 63 */
+EXTERN void TkpInitializeMenuBindings(Tcl_Interp *interp,
+ Tk_BindingTable bindingTable);
+/* 64 */
+EXTERN void TkpMakeContainer(Tk_Window tkwin);
+/* 65 */
+EXTERN void TkpMakeMenuWindow(Tk_Window tkwin, int transient);
+/* 66 */
+EXTERN Window TkpMakeWindow(TkWindow *winPtr, Window parent);
+/* 67 */
+EXTERN void TkpMenuNotifyToplevelCreate(Tcl_Interp *interp,
+ const char *menuName);
+/* 68 */
+EXTERN TkDisplay * TkpOpenDisplay(const char *display_name);
+/* 69 */
+EXTERN int TkPointerEvent(XEvent *eventPtr, TkWindow *winPtr);
+/* 70 */
+EXTERN int TkPolygonToArea(double *polyPtr, int numPoints,
+ double *rectPtr);
+/* 71 */
+EXTERN double TkPolygonToPoint(double *polyPtr, int numPoints,
+ double *pointPtr);
+/* 72 */
+EXTERN int TkPositionInTree(TkWindow *winPtr, TkWindow *treePtr);
+/* 73 */
+EXTERN void TkpRedirectKeyEvent(TkWindow *winPtr,
+ XEvent *eventPtr);
+/* 74 */
+EXTERN void TkpSetMainMenubar(Tcl_Interp *interp,
+ Tk_Window tkwin, const char *menuName);
+/* 75 */
+EXTERN int TkpUseWindow(Tcl_Interp *interp, Tk_Window tkwin,
+ const char *string);
+/* Slot 76 is reserved */
+/* 77 */
+EXTERN void TkQueueEventForAllChildren(TkWindow *winPtr,
+ XEvent *eventPtr);
+/* 78 */
+EXTERN int TkReadBitmapFile(Display *display, Drawable d,
+ const char *filename,
+ unsigned int *width_return,
+ unsigned int *height_return,
+ Pixmap *bitmap_return, int *x_hot_return,
+ int *y_hot_return);
+/* 79 */
+EXTERN int TkScrollWindow(Tk_Window tkwin, GC gc, int x, int y,
+ int width, int height, int dx, int dy,
+ TkRegion damageRgn);
+/* 80 */
+EXTERN void TkSelDeadWindow(TkWindow *winPtr);
+/* 81 */
+EXTERN void TkSelEventProc(Tk_Window tkwin, XEvent *eventPtr);
+/* 82 */
+EXTERN void TkSelInit(Tk_Window tkwin);
+/* 83 */
+EXTERN void TkSelPropProc(XEvent *eventPtr);
+/* Slot 84 is reserved */
+/* 85 */
+EXTERN void TkSetWindowMenuBar(Tcl_Interp *interp,
+ Tk_Window tkwin, const char *oldMenuName,
+ const char *menuName);
+/* 86 */
+EXTERN KeySym TkStringToKeysym(const char *name);
+/* 87 */
+EXTERN int TkThickPolyLineToArea(double *coordPtr,
+ int numPoints, double width, int capStyle,
+ int joinStyle, double *rectPtr);
+/* 88 */
+EXTERN void TkWmAddToColormapWindows(TkWindow *winPtr);
+/* 89 */
+EXTERN void TkWmDeadWindow(TkWindow *winPtr);
+/* 90 */
+EXTERN TkWindow * TkWmFocusToplevel(TkWindow *winPtr);
+/* 91 */
+EXTERN void TkWmMapWindow(TkWindow *winPtr);
+/* 92 */
+EXTERN void TkWmNewWindow(TkWindow *winPtr);
+/* 93 */
+EXTERN void TkWmProtocolEventProc(TkWindow *winPtr,
+ XEvent *evenvPtr);
+/* 94 */
+EXTERN void TkWmRemoveFromColormapWindows(TkWindow *winPtr);
+/* 95 */
+EXTERN void TkWmRestackToplevel(TkWindow *winPtr, int aboveBelow,
+ TkWindow *otherPtr);
+/* 96 */
+EXTERN void TkWmSetClass(TkWindow *winPtr);
+/* 97 */
+EXTERN void TkWmUnmapWindow(TkWindow *winPtr);
+/* 98 */
+EXTERN Tcl_Obj * TkDebugBitmap(Tk_Window tkwin, const char *name);
+/* 99 */
+EXTERN Tcl_Obj * TkDebugBorder(Tk_Window tkwin, const char *name);
+/* 100 */
+EXTERN Tcl_Obj * TkDebugCursor(Tk_Window tkwin, const char *name);
+/* 101 */
+EXTERN Tcl_Obj * TkDebugColor(Tk_Window tkwin, const char *name);
+/* 102 */
+EXTERN Tcl_Obj * TkDebugConfig(Tcl_Interp *interp,
+ Tk_OptionTable table);
+/* 103 */
+EXTERN Tcl_Obj * TkDebugFont(Tk_Window tkwin, const char *name);
+/* 104 */
+EXTERN int TkFindStateNumObj(Tcl_Interp *interp,
+ Tcl_Obj *optionPtr, const TkStateMap *mapPtr,
+ Tcl_Obj *keyPtr);
+/* 105 */
+EXTERN Tcl_HashTable * TkGetBitmapPredefTable(void);
+/* 106 */
+EXTERN TkDisplay * TkGetDisplayList(void);
+/* 107 */
+EXTERN TkMainInfo * TkGetMainInfoList(void);
+/* 108 */
+EXTERN int TkGetWindowFromObj(Tcl_Interp *interp,
+ Tk_Window tkwin, Tcl_Obj *objPtr,
+ Tk_Window *windowPtr);
+/* 109 */
+EXTERN CONST86 char * TkpGetString(TkWindow *winPtr, XEvent *eventPtr,
+ Tcl_DString *dsPtr);
+/* 110 */
+EXTERN void TkpGetSubFonts(Tcl_Interp *interp, Tk_Font tkfont);
+/* 111 */
+EXTERN Tcl_Obj * TkpGetSystemDefault(Tk_Window tkwin,
+ const char *dbName, const char *className);
+/* 112 */
+EXTERN void TkpMenuThreadInit(void);
+/* 113 */
+EXTERN void TkClipBox(TkRegion rgn, XRectangle *rect_return);
+/* 114 */
+EXTERN TkRegion TkCreateRegion(void);
+/* 115 */
+EXTERN void TkDestroyRegion(TkRegion rgn);
+/* 116 */
+EXTERN void TkIntersectRegion(TkRegion sra, TkRegion srcb,
+ TkRegion dr_return);
+/* 117 */
+EXTERN int TkRectInRegion(TkRegion rgn, int x, int y,
+ unsigned int width, unsigned int height);
+/* 118 */
+EXTERN void TkSetRegion(Display *display, GC gc, TkRegion rgn);
+/* 119 */
+EXTERN void TkUnionRectWithRegion(XRectangle *rect, TkRegion src,
+ TkRegion dr_return);
+/* Slot 120 is reserved */
+#ifdef MAC_OSX_TK /* AQUA */
+/* 121 */
+EXTERN Pixmap TkpCreateNativeBitmap(Display *display,
+ const void *source);
+#endif /* AQUA */
+#ifdef MAC_OSX_TK /* AQUA */
+/* 122 */
+EXTERN void TkpDefineNativeBitmaps(void);
+#endif /* AQUA */
+/* Slot 123 is reserved */
+#ifdef MAC_OSX_TK /* AQUA */
+/* 124 */
+EXTERN Pixmap TkpGetNativeAppBitmap(Display *display,
+ const char *name, int *width, int *height);
+#endif /* AQUA */
+/* Slot 125 is reserved */
+/* Slot 126 is reserved */
+/* Slot 127 is reserved */
+/* Slot 128 is reserved */
+/* Slot 129 is reserved */
+/* Slot 130 is reserved */
+/* Slot 131 is reserved */
+/* Slot 132 is reserved */
+/* Slot 133 is reserved */
+/* Slot 134 is reserved */
+/* 135 */
+EXTERN void TkpDrawHighlightBorder(Tk_Window tkwin, GC fgGC,
+ GC bgGC, int highlightWidth,
+ Drawable drawable);
+/* 136 */
+EXTERN void TkSetFocusWin(TkWindow *winPtr, int force);
+/* 137 */
+EXTERN void TkpSetKeycodeAndState(Tk_Window tkwin, KeySym keySym,
+ XEvent *eventPtr);
+/* 138 */
+EXTERN KeySym TkpGetKeySym(TkDisplay *dispPtr, XEvent *eventPtr);
+/* 139 */
+EXTERN void TkpInitKeymapInfo(TkDisplay *dispPtr);
+/* 140 */
+EXTERN TkRegion TkPhotoGetValidRegion(Tk_PhotoHandle handle);
+/* 141 */
+EXTERN TkWindow ** TkWmStackorderToplevel(TkWindow *parentPtr);
+/* 142 */
+EXTERN void TkFocusFree(TkMainInfo *mainPtr);
+/* 143 */
+EXTERN void TkClipCleanup(TkDisplay *dispPtr);
+/* 144 */
+EXTERN void TkGCCleanup(TkDisplay *dispPtr);
+/* 145 */
+EXTERN void TkSubtractRegion(TkRegion sra, TkRegion srcb,
+ TkRegion dr_return);
+/* 146 */
+EXTERN void TkStylePkgInit(TkMainInfo *mainPtr);
+/* 147 */
+EXTERN void TkStylePkgFree(TkMainInfo *mainPtr);
+/* 148 */
+EXTERN Tk_Window TkToplevelWindowForCommand(Tcl_Interp *interp,
+ const char *cmdName);
+/* 149 */
+EXTERN const Tk_OptionSpec * TkGetOptionSpec(const char *name,
+ Tk_OptionTable optionTable);
+/* 150 */
+EXTERN int TkMakeRawCurve(Tk_Canvas canvas, double *pointPtr,
+ int numPoints, int numSteps,
+ XPoint xPoints[], double dblPoints[]);
+/* 151 */
+EXTERN void TkMakeRawCurvePostscript(Tcl_Interp *interp,
+ Tk_Canvas canvas, double *pointPtr,
+ int numPoints);
+/* 152 */
+EXTERN void TkpDrawFrame(Tk_Window tkwin, Tk_3DBorder border,
+ int highlightWidth, int borderWidth,
+ int relief);
+/* 153 */
+EXTERN void TkCreateThreadExitHandler(Tcl_ExitProc *proc,
+ ClientData clientData);
+/* 154 */
+EXTERN void TkDeleteThreadExitHandler(Tcl_ExitProc *proc,
+ ClientData clientData);
+/* Slot 155 is reserved */
+/* 156 */
+EXTERN int TkpTestembedCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 157 */
+EXTERN int TkpTesttextCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+/* 158 */
+EXTERN int TkSelGetSelection(Tcl_Interp *interp,
+ Tk_Window tkwin, Atom selection, Atom target,
+ Tk_GetSelProc *proc, ClientData clientData);
+/* 159 */
+EXTERN int TkTextGetIndex(Tcl_Interp *interp,
+ struct TkText *textPtr, const char *string,
+ struct TkTextIndex *indexPtr);
+/* 160 */
+EXTERN int TkTextIndexBackBytes(const struct TkText *textPtr,
+ const struct TkTextIndex *srcPtr, int count,
+ struct TkTextIndex *dstPtr);
+/* 161 */
+EXTERN int TkTextIndexForwBytes(const struct TkText *textPtr,
+ const struct TkTextIndex *srcPtr, int count,
+ struct TkTextIndex *dstPtr);
+/* 162 */
+EXTERN struct TkTextIndex * TkTextMakeByteIndex(TkTextBTree tree,
+ const struct TkText *textPtr, int lineIndex,
+ int byteIndex, struct TkTextIndex *indexPtr);
+/* 163 */
+EXTERN int TkTextPrintIndex(const struct TkText *textPtr,
+ const struct TkTextIndex *indexPtr,
+ char *string);
+/* 164 */
+EXTERN struct TkTextSegment * TkTextSetMark(struct TkText *textPtr,
+ const char *name,
+ struct TkTextIndex *indexPtr);
+/* 165 */
+EXTERN int TkTextXviewCmd(struct TkText *textPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 166 */
+EXTERN void TkTextChanged(struct TkSharedText *sharedTextPtr,
+ struct TkText *textPtr,
+ const struct TkTextIndex *index1Ptr,
+ const struct TkTextIndex *index2Ptr);
+/* 167 */
+EXTERN int TkBTreeNumLines(TkTextBTree tree,
+ const struct TkText *textPtr);
+/* 168 */
+EXTERN void TkTextInsertDisplayProc(struct TkText *textPtr,
+ struct TkTextDispChunk *chunkPtr, int x,
+ int y, int height, int baseline,
+ Display *display, Drawable dst, int screenY);
+/* 169 */
+EXTERN int TkStateParseProc(ClientData clientData,
+ Tcl_Interp *interp, Tk_Window tkwin,
+ const char *value, char *widgRec, int offset);
+/* 170 */
+EXTERN CONST86 char * TkStatePrintProc(ClientData clientData,
+ Tk_Window tkwin, char *widgRec, int offset,
+ Tcl_FreeProc **freeProcPtr);
+/* 171 */
+EXTERN int TkCanvasDashParseProc(ClientData clientData,
+ Tcl_Interp *interp, Tk_Window tkwin,
+ const char *value, char *widgRec, int offset);
+/* 172 */
+EXTERN CONST86 char * TkCanvasDashPrintProc(ClientData clientData,
+ Tk_Window tkwin, char *widgRec, int offset,
+ Tcl_FreeProc **freeProcPtr);
+/* 173 */
+EXTERN int TkOffsetParseProc(ClientData clientData,
+ Tcl_Interp *interp, Tk_Window tkwin,
+ const char *value, char *widgRec, int offset);
+/* 174 */
+EXTERN CONST86 char * TkOffsetPrintProc(ClientData clientData,
+ Tk_Window tkwin, char *widgRec, int offset,
+ Tcl_FreeProc **freeProcPtr);
+/* 175 */
+EXTERN int TkPixelParseProc(ClientData clientData,
+ Tcl_Interp *interp, Tk_Window tkwin,
+ const char *value, char *widgRec, int offset);
+/* 176 */
+EXTERN CONST86 char * TkPixelPrintProc(ClientData clientData,
+ Tk_Window tkwin, char *widgRec, int offset,
+ Tcl_FreeProc **freeProcPtr);
+/* 177 */
+EXTERN int TkOrientParseProc(ClientData clientData,
+ Tcl_Interp *interp, Tk_Window tkwin,
+ const char *value, char *widgRec, int offset);
+/* 178 */
+EXTERN CONST86 char * TkOrientPrintProc(ClientData clientData,
+ Tk_Window tkwin, char *widgRec, int offset,
+ Tcl_FreeProc **freeProcPtr);
+/* 179 */
+EXTERN int TkSmoothParseProc(ClientData clientData,
+ Tcl_Interp *interp, Tk_Window tkwin,
+ const char *value, char *widgRec, int offset);
+/* 180 */
+EXTERN CONST86 char * TkSmoothPrintProc(ClientData clientData,
+ Tk_Window tkwin, char *widgRec, int offset,
+ Tcl_FreeProc **freeProcPtr);
+/* 181 */
+EXTERN void TkDrawAngledTextLayout(Display *display,
+ Drawable drawable, GC gc,
+ Tk_TextLayout layout, int x, int y,
+ double angle, int firstChar, int lastChar);
+/* 182 */
+EXTERN void TkUnderlineAngledTextLayout(Display *display,
+ Drawable drawable, GC gc,
+ Tk_TextLayout layout, int x, int y,
+ double angle, int underline);
+/* 183 */
+EXTERN int TkIntersectAngledTextLayout(Tk_TextLayout layout,
+ int x, int y, int width, int height,
+ double angle);
+/* 184 */
+EXTERN void TkDrawAngledChars(Display *display,
+ Drawable drawable, GC gc, Tk_Font tkfont,
+ const char *source, int numBytes, double x,
+ double y, double angle);
+
+typedef struct TkIntStubs {
+ int magic;
+ void *hooks;
+
+ TkWindow * (*tkAllocWindow) (TkDisplay *dispPtr, int screenNum, TkWindow *parentPtr); /* 0 */
+ void (*tkBezierPoints) (double control[], int numSteps, double *coordPtr); /* 1 */
+ void (*tkBezierScreenPoints) (Tk_Canvas canvas, double control[], int numSteps, XPoint *xPointPtr); /* 2 */
+ void (*reserved3)(void);
+ void (*tkBindEventProc) (TkWindow *winPtr, XEvent *eventPtr); /* 4 */
+ void (*tkBindFree) (TkMainInfo *mainPtr); /* 5 */
+ void (*tkBindInit) (TkMainInfo *mainPtr); /* 6 */
+ void (*tkChangeEventWindow) (XEvent *eventPtr, TkWindow *winPtr); /* 7 */
+ int (*tkClipInit) (Tcl_Interp *interp, TkDisplay *dispPtr); /* 8 */
+ void (*tkComputeAnchor) (Tk_Anchor anchor, Tk_Window tkwin, int padX, int padY, int innerWidth, int innerHeight, int *xPtr, int *yPtr); /* 9 */
+ void (*reserved10)(void);
+ void (*reserved11)(void);
+ TkCursor * (*tkCreateCursorFromData) (Tk_Window tkwin, const char *source, const char *mask, int width, int height, int xHot, int yHot, XColor fg, XColor bg); /* 12 */
+ int (*tkCreateFrame) (ClientData clientData, Tcl_Interp *interp, int argc, const char *const *argv, int toplevel, const char *appName); /* 13 */
+ Tk_Window (*tkCreateMainWindow) (Tcl_Interp *interp, const char *screenName, const char *baseName); /* 14 */
+ Time (*tkCurrentTime) (TkDisplay *dispPtr); /* 15 */
+ void (*tkDeleteAllImages) (TkMainInfo *mainPtr); /* 16 */
+ void (*tkDoConfigureNotify) (TkWindow *winPtr); /* 17 */
+ void (*tkDrawInsetFocusHighlight) (Tk_Window tkwin, GC gc, int width, Drawable drawable, int padding); /* 18 */
+ void (*tkEventDeadWindow) (TkWindow *winPtr); /* 19 */
+ void (*tkFillPolygon) (Tk_Canvas canvas, double *coordPtr, int numPoints, Display *display, Drawable drawable, GC gc, GC outlineGC); /* 20 */
+ int (*tkFindStateNum) (Tcl_Interp *interp, const char *option, const TkStateMap *mapPtr, const char *strKey); /* 21 */
+ CONST86 char * (*tkFindStateString) (const TkStateMap *mapPtr, int numKey); /* 22 */
+ void (*tkFocusDeadWindow) (TkWindow *winPtr); /* 23 */
+ int (*tkFocusFilterEvent) (TkWindow *winPtr, XEvent *eventPtr); /* 24 */
+ TkWindow * (*tkFocusKeyEvent) (TkWindow *winPtr, XEvent *eventPtr); /* 25 */
+ void (*tkFontPkgInit) (TkMainInfo *mainPtr); /* 26 */
+ void (*tkFontPkgFree) (TkMainInfo *mainPtr); /* 27 */
+ void (*tkFreeBindingTags) (TkWindow *winPtr); /* 28 */
+ void (*tkpFreeCursor) (TkCursor *cursorPtr); /* 29 */
+ char * (*tkGetBitmapData) (Tcl_Interp *interp, const char *string, const char *fileName, int *widthPtr, int *heightPtr, int *hotXPtr, int *hotYPtr); /* 30 */
+ void (*tkGetButtPoints) (double p1[], double p2[], double width, int project, double m1[], double m2[]); /* 31 */
+ TkCursor * (*tkGetCursorByName) (Tcl_Interp *interp, Tk_Window tkwin, Tk_Uid string); /* 32 */
+ const char * (*tkGetDefaultScreenName) (Tcl_Interp *interp, const char *screenName); /* 33 */
+ TkDisplay * (*tkGetDisplay) (Display *display); /* 34 */
+ int (*tkGetDisplayOf) (Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], Tk_Window *tkwinPtr); /* 35 */
+ TkWindow * (*tkGetFocusWin) (TkWindow *winPtr); /* 36 */
+ int (*tkGetInterpNames) (Tcl_Interp *interp, Tk_Window tkwin); /* 37 */
+ int (*tkGetMiterPoints) (double p1[], double p2[], double p3[], double width, double m1[], double m2[]); /* 38 */
+ void (*tkGetPointerCoords) (Tk_Window tkwin, int *xPtr, int *yPtr); /* 39 */
+ void (*tkGetServerInfo) (Tcl_Interp *interp, Tk_Window tkwin); /* 40 */
+ void (*tkGrabDeadWindow) (TkWindow *winPtr); /* 41 */
+ int (*tkGrabState) (TkWindow *winPtr); /* 42 */
+ void (*tkIncludePoint) (Tk_Item *itemPtr, double *pointPtr); /* 43 */
+ void (*tkInOutEvents) (XEvent *eventPtr, TkWindow *sourcePtr, TkWindow *destPtr, int leaveType, int enterType, Tcl_QueuePosition position); /* 44 */
+ void (*tkInstallFrameMenu) (Tk_Window tkwin); /* 45 */
+ CONST86 char * (*tkKeysymToString) (KeySym keysym); /* 46 */
+ int (*tkLineToArea) (double end1Ptr[], double end2Ptr[], double rectPtr[]); /* 47 */
+ double (*tkLineToPoint) (double end1Ptr[], double end2Ptr[], double pointPtr[]); /* 48 */
+ int (*tkMakeBezierCurve) (Tk_Canvas canvas, double *pointPtr, int numPoints, int numSteps, XPoint xPoints[], double dblPoints[]); /* 49 */
+ void (*tkMakeBezierPostscript) (Tcl_Interp *interp, Tk_Canvas canvas, double *pointPtr, int numPoints); /* 50 */
+ void (*tkOptionClassChanged) (TkWindow *winPtr); /* 51 */
+ void (*tkOptionDeadWindow) (TkWindow *winPtr); /* 52 */
+ int (*tkOvalToArea) (double *ovalPtr, double *rectPtr); /* 53 */
+ double (*tkOvalToPoint) (double ovalPtr[], double width, int filled, double pointPtr[]); /* 54 */
+ int (*tkpChangeFocus) (TkWindow *winPtr, int force); /* 55 */
+ void (*tkpCloseDisplay) (TkDisplay *dispPtr); /* 56 */
+ void (*tkpClaimFocus) (TkWindow *topLevelPtr, int force); /* 57 */
+ void (*tkpDisplayWarning) (const char *msg, const char *title); /* 58 */
+ void (*tkpGetAppName) (Tcl_Interp *interp, Tcl_DString *name); /* 59 */
+ TkWindow * (*tkpGetOtherWindow) (TkWindow *winPtr); /* 60 */
+ TkWindow * (*tkpGetWrapperWindow) (TkWindow *winPtr); /* 61 */
+ int (*tkpInit) (Tcl_Interp *interp); /* 62 */
+ void (*tkpInitializeMenuBindings) (Tcl_Interp *interp, Tk_BindingTable bindingTable); /* 63 */
+ void (*tkpMakeContainer) (Tk_Window tkwin); /* 64 */
+ void (*tkpMakeMenuWindow) (Tk_Window tkwin, int transient); /* 65 */
+ Window (*tkpMakeWindow) (TkWindow *winPtr, Window parent); /* 66 */
+ void (*tkpMenuNotifyToplevelCreate) (Tcl_Interp *interp, const char *menuName); /* 67 */
+ TkDisplay * (*tkpOpenDisplay) (const char *display_name); /* 68 */
+ int (*tkPointerEvent) (XEvent *eventPtr, TkWindow *winPtr); /* 69 */
+ int (*tkPolygonToArea) (double *polyPtr, int numPoints, double *rectPtr); /* 70 */
+ double (*tkPolygonToPoint) (double *polyPtr, int numPoints, double *pointPtr); /* 71 */
+ int (*tkPositionInTree) (TkWindow *winPtr, TkWindow *treePtr); /* 72 */
+ void (*tkpRedirectKeyEvent) (TkWindow *winPtr, XEvent *eventPtr); /* 73 */
+ void (*tkpSetMainMenubar) (Tcl_Interp *interp, Tk_Window tkwin, const char *menuName); /* 74 */
+ int (*tkpUseWindow) (Tcl_Interp *interp, Tk_Window tkwin, const char *string); /* 75 */
+ void (*reserved76)(void);
+ void (*tkQueueEventForAllChildren) (TkWindow *winPtr, XEvent *eventPtr); /* 77 */
+ int (*tkReadBitmapFile) (Display *display, Drawable d, const char *filename, unsigned int *width_return, unsigned int *height_return, Pixmap *bitmap_return, int *x_hot_return, int *y_hot_return); /* 78 */
+ int (*tkScrollWindow) (Tk_Window tkwin, GC gc, int x, int y, int width, int height, int dx, int dy, TkRegion damageRgn); /* 79 */
+ void (*tkSelDeadWindow) (TkWindow *winPtr); /* 80 */
+ void (*tkSelEventProc) (Tk_Window tkwin, XEvent *eventPtr); /* 81 */
+ void (*tkSelInit) (Tk_Window tkwin); /* 82 */
+ void (*tkSelPropProc) (XEvent *eventPtr); /* 83 */
+ void (*reserved84)(void);
+ void (*tkSetWindowMenuBar) (Tcl_Interp *interp, Tk_Window tkwin, const char *oldMenuName, const char *menuName); /* 85 */
+ KeySym (*tkStringToKeysym) (const char *name); /* 86 */
+ int (*tkThickPolyLineToArea) (double *coordPtr, int numPoints, double width, int capStyle, int joinStyle, double *rectPtr); /* 87 */
+ void (*tkWmAddToColormapWindows) (TkWindow *winPtr); /* 88 */
+ void (*tkWmDeadWindow) (TkWindow *winPtr); /* 89 */
+ TkWindow * (*tkWmFocusToplevel) (TkWindow *winPtr); /* 90 */
+ void (*tkWmMapWindow) (TkWindow *winPtr); /* 91 */
+ void (*tkWmNewWindow) (TkWindow *winPtr); /* 92 */
+ void (*tkWmProtocolEventProc) (TkWindow *winPtr, XEvent *evenvPtr); /* 93 */
+ void (*tkWmRemoveFromColormapWindows) (TkWindow *winPtr); /* 94 */
+ void (*tkWmRestackToplevel) (TkWindow *winPtr, int aboveBelow, TkWindow *otherPtr); /* 95 */
+ void (*tkWmSetClass) (TkWindow *winPtr); /* 96 */
+ void (*tkWmUnmapWindow) (TkWindow *winPtr); /* 97 */
+ Tcl_Obj * (*tkDebugBitmap) (Tk_Window tkwin, const char *name); /* 98 */
+ Tcl_Obj * (*tkDebugBorder) (Tk_Window tkwin, const char *name); /* 99 */
+ Tcl_Obj * (*tkDebugCursor) (Tk_Window tkwin, const char *name); /* 100 */
+ Tcl_Obj * (*tkDebugColor) (Tk_Window tkwin, const char *name); /* 101 */
+ Tcl_Obj * (*tkDebugConfig) (Tcl_Interp *interp, Tk_OptionTable table); /* 102 */
+ Tcl_Obj * (*tkDebugFont) (Tk_Window tkwin, const char *name); /* 103 */
+ int (*tkFindStateNumObj) (Tcl_Interp *interp, Tcl_Obj *optionPtr, const TkStateMap *mapPtr, Tcl_Obj *keyPtr); /* 104 */
+ Tcl_HashTable * (*tkGetBitmapPredefTable) (void); /* 105 */
+ TkDisplay * (*tkGetDisplayList) (void); /* 106 */
+ TkMainInfo * (*tkGetMainInfoList) (void); /* 107 */
+ int (*tkGetWindowFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, Tk_Window *windowPtr); /* 108 */
+ CONST86 char * (*tkpGetString) (TkWindow *winPtr, XEvent *eventPtr, Tcl_DString *dsPtr); /* 109 */
+ void (*tkpGetSubFonts) (Tcl_Interp *interp, Tk_Font tkfont); /* 110 */
+ Tcl_Obj * (*tkpGetSystemDefault) (Tk_Window tkwin, const char *dbName, const char *className); /* 111 */
+ void (*tkpMenuThreadInit) (void); /* 112 */
+ void (*tkClipBox) (TkRegion rgn, XRectangle *rect_return); /* 113 */
+ TkRegion (*tkCreateRegion) (void); /* 114 */
+ void (*tkDestroyRegion) (TkRegion rgn); /* 115 */
+ void (*tkIntersectRegion) (TkRegion sra, TkRegion srcb, TkRegion dr_return); /* 116 */
+ int (*tkRectInRegion) (TkRegion rgn, int x, int y, unsigned int width, unsigned int height); /* 117 */
+ void (*tkSetRegion) (Display *display, GC gc, TkRegion rgn); /* 118 */
+ void (*tkUnionRectWithRegion) (XRectangle *rect, TkRegion src, TkRegion dr_return); /* 119 */
+ void (*reserved120)(void);
+#if !(defined(_WIN32) || defined(MAC_OSX_TK)) /* X11 */
+ void (*reserved121)(void);
+#endif /* X11 */
+#if defined(_WIN32) /* WIN */
+ void (*reserved121)(void);
+#endif /* WIN */
+#ifdef MAC_OSX_TK /* AQUA */
+ void (*reserved121)(void); /* Dummy entry for stubs table backwards compatibility */
+ Pixmap (*tkpCreateNativeBitmap) (Display *display, const void *source); /* 121 */
+#endif /* AQUA */
+#if !(defined(_WIN32) || defined(MAC_OSX_TK)) /* X11 */
+ void (*reserved122)(void);
+#endif /* X11 */
+#if defined(_WIN32) /* WIN */
+ void (*reserved122)(void);
+#endif /* WIN */
+#ifdef MAC_OSX_TK /* AQUA */
+ void (*reserved122)(void); /* Dummy entry for stubs table backwards compatibility */
+ void (*tkpDefineNativeBitmaps) (void); /* 122 */
+#endif /* AQUA */
+ void (*reserved123)(void);
+#if !(defined(_WIN32) || defined(MAC_OSX_TK)) /* X11 */
+ void (*reserved124)(void);
+#endif /* X11 */
+#if defined(_WIN32) /* WIN */
+ void (*reserved124)(void);
+#endif /* WIN */
+#ifdef MAC_OSX_TK /* AQUA */
+ void (*reserved124)(void); /* Dummy entry for stubs table backwards compatibility */
+ Pixmap (*tkpGetNativeAppBitmap) (Display *display, const char *name, int *width, int *height); /* 124 */
+#endif /* AQUA */
+ void (*reserved125)(void);
+ void (*reserved126)(void);
+ void (*reserved127)(void);
+ void (*reserved128)(void);
+ void (*reserved129)(void);
+ void (*reserved130)(void);
+ void (*reserved131)(void);
+ void (*reserved132)(void);
+ void (*reserved133)(void);
+ void (*reserved134)(void);
+ void (*tkpDrawHighlightBorder) (Tk_Window tkwin, GC fgGC, GC bgGC, int highlightWidth, Drawable drawable); /* 135 */
+ void (*tkSetFocusWin) (TkWindow *winPtr, int force); /* 136 */
+ void (*tkpSetKeycodeAndState) (Tk_Window tkwin, KeySym keySym, XEvent *eventPtr); /* 137 */
+ KeySym (*tkpGetKeySym) (TkDisplay *dispPtr, XEvent *eventPtr); /* 138 */
+ void (*tkpInitKeymapInfo) (TkDisplay *dispPtr); /* 139 */
+ TkRegion (*tkPhotoGetValidRegion) (Tk_PhotoHandle handle); /* 140 */
+ TkWindow ** (*tkWmStackorderToplevel) (TkWindow *parentPtr); /* 141 */
+ void (*tkFocusFree) (TkMainInfo *mainPtr); /* 142 */
+ void (*tkClipCleanup) (TkDisplay *dispPtr); /* 143 */
+ void (*tkGCCleanup) (TkDisplay *dispPtr); /* 144 */
+ void (*tkSubtractRegion) (TkRegion sra, TkRegion srcb, TkRegion dr_return); /* 145 */
+ void (*tkStylePkgInit) (TkMainInfo *mainPtr); /* 146 */
+ void (*tkStylePkgFree) (TkMainInfo *mainPtr); /* 147 */
+ Tk_Window (*tkToplevelWindowForCommand) (Tcl_Interp *interp, const char *cmdName); /* 148 */
+ const Tk_OptionSpec * (*tkGetOptionSpec) (const char *name, Tk_OptionTable optionTable); /* 149 */
+ int (*tkMakeRawCurve) (Tk_Canvas canvas, double *pointPtr, int numPoints, int numSteps, XPoint xPoints[], double dblPoints[]); /* 150 */
+ void (*tkMakeRawCurvePostscript) (Tcl_Interp *interp, Tk_Canvas canvas, double *pointPtr, int numPoints); /* 151 */
+ void (*tkpDrawFrame) (Tk_Window tkwin, Tk_3DBorder border, int highlightWidth, int borderWidth, int relief); /* 152 */
+ void (*tkCreateThreadExitHandler) (Tcl_ExitProc *proc, ClientData clientData); /* 153 */
+ void (*tkDeleteThreadExitHandler) (Tcl_ExitProc *proc, ClientData clientData); /* 154 */
+ void (*reserved155)(void);
+ int (*tkpTestembedCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 156 */
+ int (*tkpTesttextCmd) (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 157 */
+ int (*tkSelGetSelection) (Tcl_Interp *interp, Tk_Window tkwin, Atom selection, Atom target, Tk_GetSelProc *proc, ClientData clientData); /* 158 */
+ int (*tkTextGetIndex) (Tcl_Interp *interp, struct TkText *textPtr, const char *string, struct TkTextIndex *indexPtr); /* 159 */
+ int (*tkTextIndexBackBytes) (const struct TkText *textPtr, const struct TkTextIndex *srcPtr, int count, struct TkTextIndex *dstPtr); /* 160 */
+ int (*tkTextIndexForwBytes) (const struct TkText *textPtr, const struct TkTextIndex *srcPtr, int count, struct TkTextIndex *dstPtr); /* 161 */
+ struct TkTextIndex * (*tkTextMakeByteIndex) (TkTextBTree tree, const struct TkText *textPtr, int lineIndex, int byteIndex, struct TkTextIndex *indexPtr); /* 162 */
+ int (*tkTextPrintIndex) (const struct TkText *textPtr, const struct TkTextIndex *indexPtr, char *string); /* 163 */
+ struct TkTextSegment * (*tkTextSetMark) (struct TkText *textPtr, const char *name, struct TkTextIndex *indexPtr); /* 164 */
+ int (*tkTextXviewCmd) (struct TkText *textPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 165 */
+ void (*tkTextChanged) (struct TkSharedText *sharedTextPtr, struct TkText *textPtr, const struct TkTextIndex *index1Ptr, const struct TkTextIndex *index2Ptr); /* 166 */
+ int (*tkBTreeNumLines) (TkTextBTree tree, const struct TkText *textPtr); /* 167 */
+ void (*tkTextInsertDisplayProc) (struct TkText *textPtr, struct TkTextDispChunk *chunkPtr, int x, int y, int height, int baseline, Display *display, Drawable dst, int screenY); /* 168 */
+ int (*tkStateParseProc) (ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset); /* 169 */
+ CONST86 char * (*tkStatePrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 170 */
+ int (*tkCanvasDashParseProc) (ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset); /* 171 */
+ CONST86 char * (*tkCanvasDashPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 172 */
+ int (*tkOffsetParseProc) (ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset); /* 173 */
+ CONST86 char * (*tkOffsetPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 174 */
+ int (*tkPixelParseProc) (ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset); /* 175 */
+ CONST86 char * (*tkPixelPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 176 */
+ int (*tkOrientParseProc) (ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset); /* 177 */
+ CONST86 char * (*tkOrientPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 178 */
+ int (*tkSmoothParseProc) (ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset); /* 179 */
+ CONST86 char * (*tkSmoothPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 180 */
+ void (*tkDrawAngledTextLayout) (Display *display, Drawable drawable, GC gc, Tk_TextLayout layout, int x, int y, double angle, int firstChar, int lastChar); /* 181 */
+ void (*tkUnderlineAngledTextLayout) (Display *display, Drawable drawable, GC gc, Tk_TextLayout layout, int x, int y, double angle, int underline); /* 182 */
+ int (*tkIntersectAngledTextLayout) (Tk_TextLayout layout, int x, int y, int width, int height, double angle); /* 183 */
+ void (*tkDrawAngledChars) (Display *display, Drawable drawable, GC gc, Tk_Font tkfont, const char *source, int numBytes, double x, double y, double angle); /* 184 */
+} TkIntStubs;
+
+extern const TkIntStubs *tkIntStubsPtr;
+
+#ifdef __cplusplus
+}
+#endif
+
+#if defined(USE_TK_STUBS)
+
+/*
+ * Inline function declarations:
+ */
+
+#define TkAllocWindow \
+ (tkIntStubsPtr->tkAllocWindow) /* 0 */
+#define TkBezierPoints \
+ (tkIntStubsPtr->tkBezierPoints) /* 1 */
+#define TkBezierScreenPoints \
+ (tkIntStubsPtr->tkBezierScreenPoints) /* 2 */
+/* Slot 3 is reserved */
+#define TkBindEventProc \
+ (tkIntStubsPtr->tkBindEventProc) /* 4 */
+#define TkBindFree \
+ (tkIntStubsPtr->tkBindFree) /* 5 */
+#define TkBindInit \
+ (tkIntStubsPtr->tkBindInit) /* 6 */
+#define TkChangeEventWindow \
+ (tkIntStubsPtr->tkChangeEventWindow) /* 7 */
+#define TkClipInit \
+ (tkIntStubsPtr->tkClipInit) /* 8 */
+#define TkComputeAnchor \
+ (tkIntStubsPtr->tkComputeAnchor) /* 9 */
+/* Slot 10 is reserved */
+/* Slot 11 is reserved */
+#define TkCreateCursorFromData \
+ (tkIntStubsPtr->tkCreateCursorFromData) /* 12 */
+#define TkCreateFrame \
+ (tkIntStubsPtr->tkCreateFrame) /* 13 */
+#define TkCreateMainWindow \
+ (tkIntStubsPtr->tkCreateMainWindow) /* 14 */
+#define TkCurrentTime \
+ (tkIntStubsPtr->tkCurrentTime) /* 15 */
+#define TkDeleteAllImages \
+ (tkIntStubsPtr->tkDeleteAllImages) /* 16 */
+#define TkDoConfigureNotify \
+ (tkIntStubsPtr->tkDoConfigureNotify) /* 17 */
+#define TkDrawInsetFocusHighlight \
+ (tkIntStubsPtr->tkDrawInsetFocusHighlight) /* 18 */
+#define TkEventDeadWindow \
+ (tkIntStubsPtr->tkEventDeadWindow) /* 19 */
+#define TkFillPolygon \
+ (tkIntStubsPtr->tkFillPolygon) /* 20 */
+#define TkFindStateNum \
+ (tkIntStubsPtr->tkFindStateNum) /* 21 */
+#define TkFindStateString \
+ (tkIntStubsPtr->tkFindStateString) /* 22 */
+#define TkFocusDeadWindow \
+ (tkIntStubsPtr->tkFocusDeadWindow) /* 23 */
+#define TkFocusFilterEvent \
+ (tkIntStubsPtr->tkFocusFilterEvent) /* 24 */
+#define TkFocusKeyEvent \
+ (tkIntStubsPtr->tkFocusKeyEvent) /* 25 */
+#define TkFontPkgInit \
+ (tkIntStubsPtr->tkFontPkgInit) /* 26 */
+#define TkFontPkgFree \
+ (tkIntStubsPtr->tkFontPkgFree) /* 27 */
+#define TkFreeBindingTags \
+ (tkIntStubsPtr->tkFreeBindingTags) /* 28 */
+#define TkpFreeCursor \
+ (tkIntStubsPtr->tkpFreeCursor) /* 29 */
+#define TkGetBitmapData \
+ (tkIntStubsPtr->tkGetBitmapData) /* 30 */
+#define TkGetButtPoints \
+ (tkIntStubsPtr->tkGetButtPoints) /* 31 */
+#define TkGetCursorByName \
+ (tkIntStubsPtr->tkGetCursorByName) /* 32 */
+#define TkGetDefaultScreenName \
+ (tkIntStubsPtr->tkGetDefaultScreenName) /* 33 */
+#define TkGetDisplay \
+ (tkIntStubsPtr->tkGetDisplay) /* 34 */
+#define TkGetDisplayOf \
+ (tkIntStubsPtr->tkGetDisplayOf) /* 35 */
+#define TkGetFocusWin \
+ (tkIntStubsPtr->tkGetFocusWin) /* 36 */
+#define TkGetInterpNames \
+ (tkIntStubsPtr->tkGetInterpNames) /* 37 */
+#define TkGetMiterPoints \
+ (tkIntStubsPtr->tkGetMiterPoints) /* 38 */
+#define TkGetPointerCoords \
+ (tkIntStubsPtr->tkGetPointerCoords) /* 39 */
+#define TkGetServerInfo \
+ (tkIntStubsPtr->tkGetServerInfo) /* 40 */
+#define TkGrabDeadWindow \
+ (tkIntStubsPtr->tkGrabDeadWindow) /* 41 */
+#define TkGrabState \
+ (tkIntStubsPtr->tkGrabState) /* 42 */
+#define TkIncludePoint \
+ (tkIntStubsPtr->tkIncludePoint) /* 43 */
+#define TkInOutEvents \
+ (tkIntStubsPtr->tkInOutEvents) /* 44 */
+#define TkInstallFrameMenu \
+ (tkIntStubsPtr->tkInstallFrameMenu) /* 45 */
+#define TkKeysymToString \
+ (tkIntStubsPtr->tkKeysymToString) /* 46 */
+#define TkLineToArea \
+ (tkIntStubsPtr->tkLineToArea) /* 47 */
+#define TkLineToPoint \
+ (tkIntStubsPtr->tkLineToPoint) /* 48 */
+#define TkMakeBezierCurve \
+ (tkIntStubsPtr->tkMakeBezierCurve) /* 49 */
+#define TkMakeBezierPostscript \
+ (tkIntStubsPtr->tkMakeBezierPostscript) /* 50 */
+#define TkOptionClassChanged \
+ (tkIntStubsPtr->tkOptionClassChanged) /* 51 */
+#define TkOptionDeadWindow \
+ (tkIntStubsPtr->tkOptionDeadWindow) /* 52 */
+#define TkOvalToArea \
+ (tkIntStubsPtr->tkOvalToArea) /* 53 */
+#define TkOvalToPoint \
+ (tkIntStubsPtr->tkOvalToPoint) /* 54 */
+#define TkpChangeFocus \
+ (tkIntStubsPtr->tkpChangeFocus) /* 55 */
+#define TkpCloseDisplay \
+ (tkIntStubsPtr->tkpCloseDisplay) /* 56 */
+#define TkpClaimFocus \
+ (tkIntStubsPtr->tkpClaimFocus) /* 57 */
+#define TkpDisplayWarning \
+ (tkIntStubsPtr->tkpDisplayWarning) /* 58 */
+#define TkpGetAppName \
+ (tkIntStubsPtr->tkpGetAppName) /* 59 */
+#define TkpGetOtherWindow \
+ (tkIntStubsPtr->tkpGetOtherWindow) /* 60 */
+#define TkpGetWrapperWindow \
+ (tkIntStubsPtr->tkpGetWrapperWindow) /* 61 */
+#define TkpInit \
+ (tkIntStubsPtr->tkpInit) /* 62 */
+#define TkpInitializeMenuBindings \
+ (tkIntStubsPtr->tkpInitializeMenuBindings) /* 63 */
+#define TkpMakeContainer \
+ (tkIntStubsPtr->tkpMakeContainer) /* 64 */
+#define TkpMakeMenuWindow \
+ (tkIntStubsPtr->tkpMakeMenuWindow) /* 65 */
+#define TkpMakeWindow \
+ (tkIntStubsPtr->tkpMakeWindow) /* 66 */
+#define TkpMenuNotifyToplevelCreate \
+ (tkIntStubsPtr->tkpMenuNotifyToplevelCreate) /* 67 */
+#define TkpOpenDisplay \
+ (tkIntStubsPtr->tkpOpenDisplay) /* 68 */
+#define TkPointerEvent \
+ (tkIntStubsPtr->tkPointerEvent) /* 69 */
+#define TkPolygonToArea \
+ (tkIntStubsPtr->tkPolygonToArea) /* 70 */
+#define TkPolygonToPoint \
+ (tkIntStubsPtr->tkPolygonToPoint) /* 71 */
+#define TkPositionInTree \
+ (tkIntStubsPtr->tkPositionInTree) /* 72 */
+#define TkpRedirectKeyEvent \
+ (tkIntStubsPtr->tkpRedirectKeyEvent) /* 73 */
+#define TkpSetMainMenubar \
+ (tkIntStubsPtr->tkpSetMainMenubar) /* 74 */
+#define TkpUseWindow \
+ (tkIntStubsPtr->tkpUseWindow) /* 75 */
+/* Slot 76 is reserved */
+#define TkQueueEventForAllChildren \
+ (tkIntStubsPtr->tkQueueEventForAllChildren) /* 77 */
+#define TkReadBitmapFile \
+ (tkIntStubsPtr->tkReadBitmapFile) /* 78 */
+#define TkScrollWindow \
+ (tkIntStubsPtr->tkScrollWindow) /* 79 */
+#define TkSelDeadWindow \
+ (tkIntStubsPtr->tkSelDeadWindow) /* 80 */
+#define TkSelEventProc \
+ (tkIntStubsPtr->tkSelEventProc) /* 81 */
+#define TkSelInit \
+ (tkIntStubsPtr->tkSelInit) /* 82 */
+#define TkSelPropProc \
+ (tkIntStubsPtr->tkSelPropProc) /* 83 */
+/* Slot 84 is reserved */
+#define TkSetWindowMenuBar \
+ (tkIntStubsPtr->tkSetWindowMenuBar) /* 85 */
+#define TkStringToKeysym \
+ (tkIntStubsPtr->tkStringToKeysym) /* 86 */
+#define TkThickPolyLineToArea \
+ (tkIntStubsPtr->tkThickPolyLineToArea) /* 87 */
+#define TkWmAddToColormapWindows \
+ (tkIntStubsPtr->tkWmAddToColormapWindows) /* 88 */
+#define TkWmDeadWindow \
+ (tkIntStubsPtr->tkWmDeadWindow) /* 89 */
+#define TkWmFocusToplevel \
+ (tkIntStubsPtr->tkWmFocusToplevel) /* 90 */
+#define TkWmMapWindow \
+ (tkIntStubsPtr->tkWmMapWindow) /* 91 */
+#define TkWmNewWindow \
+ (tkIntStubsPtr->tkWmNewWindow) /* 92 */
+#define TkWmProtocolEventProc \
+ (tkIntStubsPtr->tkWmProtocolEventProc) /* 93 */
+#define TkWmRemoveFromColormapWindows \
+ (tkIntStubsPtr->tkWmRemoveFromColormapWindows) /* 94 */
+#define TkWmRestackToplevel \
+ (tkIntStubsPtr->tkWmRestackToplevel) /* 95 */
+#define TkWmSetClass \
+ (tkIntStubsPtr->tkWmSetClass) /* 96 */
+#define TkWmUnmapWindow \
+ (tkIntStubsPtr->tkWmUnmapWindow) /* 97 */
+#define TkDebugBitmap \
+ (tkIntStubsPtr->tkDebugBitmap) /* 98 */
+#define TkDebugBorder \
+ (tkIntStubsPtr->tkDebugBorder) /* 99 */
+#define TkDebugCursor \
+ (tkIntStubsPtr->tkDebugCursor) /* 100 */
+#define TkDebugColor \
+ (tkIntStubsPtr->tkDebugColor) /* 101 */
+#define TkDebugConfig \
+ (tkIntStubsPtr->tkDebugConfig) /* 102 */
+#define TkDebugFont \
+ (tkIntStubsPtr->tkDebugFont) /* 103 */
+#define TkFindStateNumObj \
+ (tkIntStubsPtr->tkFindStateNumObj) /* 104 */
+#define TkGetBitmapPredefTable \
+ (tkIntStubsPtr->tkGetBitmapPredefTable) /* 105 */
+#define TkGetDisplayList \
+ (tkIntStubsPtr->tkGetDisplayList) /* 106 */
+#define TkGetMainInfoList \
+ (tkIntStubsPtr->tkGetMainInfoList) /* 107 */
+#define TkGetWindowFromObj \
+ (tkIntStubsPtr->tkGetWindowFromObj) /* 108 */
+#define TkpGetString \
+ (tkIntStubsPtr->tkpGetString) /* 109 */
+#define TkpGetSubFonts \
+ (tkIntStubsPtr->tkpGetSubFonts) /* 110 */
+#define TkpGetSystemDefault \
+ (tkIntStubsPtr->tkpGetSystemDefault) /* 111 */
+#define TkpMenuThreadInit \
+ (tkIntStubsPtr->tkpMenuThreadInit) /* 112 */
+#define TkClipBox \
+ (tkIntStubsPtr->tkClipBox) /* 113 */
+#define TkCreateRegion \
+ (tkIntStubsPtr->tkCreateRegion) /* 114 */
+#define TkDestroyRegion \
+ (tkIntStubsPtr->tkDestroyRegion) /* 115 */
+#define TkIntersectRegion \
+ (tkIntStubsPtr->tkIntersectRegion) /* 116 */
+#define TkRectInRegion \
+ (tkIntStubsPtr->tkRectInRegion) /* 117 */
+#define TkSetRegion \
+ (tkIntStubsPtr->tkSetRegion) /* 118 */
+#define TkUnionRectWithRegion \
+ (tkIntStubsPtr->tkUnionRectWithRegion) /* 119 */
+/* Slot 120 is reserved */
+#ifdef MAC_OSX_TK /* AQUA */
+#define TkpCreateNativeBitmap \
+ (tkIntStubsPtr->tkpCreateNativeBitmap) /* 121 */
+#endif /* AQUA */
+#ifdef MAC_OSX_TK /* AQUA */
+#define TkpDefineNativeBitmaps \
+ (tkIntStubsPtr->tkpDefineNativeBitmaps) /* 122 */
+#endif /* AQUA */
+/* Slot 123 is reserved */
+#ifdef MAC_OSX_TK /* AQUA */
+#define TkpGetNativeAppBitmap \
+ (tkIntStubsPtr->tkpGetNativeAppBitmap) /* 124 */
+#endif /* AQUA */
+/* Slot 125 is reserved */
+/* Slot 126 is reserved */
+/* Slot 127 is reserved */
+/* Slot 128 is reserved */
+/* Slot 129 is reserved */
+/* Slot 130 is reserved */
+/* Slot 131 is reserved */
+/* Slot 132 is reserved */
+/* Slot 133 is reserved */
+/* Slot 134 is reserved */
+#define TkpDrawHighlightBorder \
+ (tkIntStubsPtr->tkpDrawHighlightBorder) /* 135 */
+#define TkSetFocusWin \
+ (tkIntStubsPtr->tkSetFocusWin) /* 136 */
+#define TkpSetKeycodeAndState \
+ (tkIntStubsPtr->tkpSetKeycodeAndState) /* 137 */
+#define TkpGetKeySym \
+ (tkIntStubsPtr->tkpGetKeySym) /* 138 */
+#define TkpInitKeymapInfo \
+ (tkIntStubsPtr->tkpInitKeymapInfo) /* 139 */
+#define TkPhotoGetValidRegion \
+ (tkIntStubsPtr->tkPhotoGetValidRegion) /* 140 */
+#define TkWmStackorderToplevel \
+ (tkIntStubsPtr->tkWmStackorderToplevel) /* 141 */
+#define TkFocusFree \
+ (tkIntStubsPtr->tkFocusFree) /* 142 */
+#define TkClipCleanup \
+ (tkIntStubsPtr->tkClipCleanup) /* 143 */
+#define TkGCCleanup \
+ (tkIntStubsPtr->tkGCCleanup) /* 144 */
+#define TkSubtractRegion \
+ (tkIntStubsPtr->tkSubtractRegion) /* 145 */
+#define TkStylePkgInit \
+ (tkIntStubsPtr->tkStylePkgInit) /* 146 */
+#define TkStylePkgFree \
+ (tkIntStubsPtr->tkStylePkgFree) /* 147 */
+#define TkToplevelWindowForCommand \
+ (tkIntStubsPtr->tkToplevelWindowForCommand) /* 148 */
+#define TkGetOptionSpec \
+ (tkIntStubsPtr->tkGetOptionSpec) /* 149 */
+#define TkMakeRawCurve \
+ (tkIntStubsPtr->tkMakeRawCurve) /* 150 */
+#define TkMakeRawCurvePostscript \
+ (tkIntStubsPtr->tkMakeRawCurvePostscript) /* 151 */
+#define TkpDrawFrame \
+ (tkIntStubsPtr->tkpDrawFrame) /* 152 */
+#define TkCreateThreadExitHandler \
+ (tkIntStubsPtr->tkCreateThreadExitHandler) /* 153 */
+#define TkDeleteThreadExitHandler \
+ (tkIntStubsPtr->tkDeleteThreadExitHandler) /* 154 */
+/* Slot 155 is reserved */
+#define TkpTestembedCmd \
+ (tkIntStubsPtr->tkpTestembedCmd) /* 156 */
+#define TkpTesttextCmd \
+ (tkIntStubsPtr->tkpTesttextCmd) /* 157 */
+#define TkSelGetSelection \
+ (tkIntStubsPtr->tkSelGetSelection) /* 158 */
+#define TkTextGetIndex \
+ (tkIntStubsPtr->tkTextGetIndex) /* 159 */
+#define TkTextIndexBackBytes \
+ (tkIntStubsPtr->tkTextIndexBackBytes) /* 160 */
+#define TkTextIndexForwBytes \
+ (tkIntStubsPtr->tkTextIndexForwBytes) /* 161 */
+#define TkTextMakeByteIndex \
+ (tkIntStubsPtr->tkTextMakeByteIndex) /* 162 */
+#define TkTextPrintIndex \
+ (tkIntStubsPtr->tkTextPrintIndex) /* 163 */
+#define TkTextSetMark \
+ (tkIntStubsPtr->tkTextSetMark) /* 164 */
+#define TkTextXviewCmd \
+ (tkIntStubsPtr->tkTextXviewCmd) /* 165 */
+#define TkTextChanged \
+ (tkIntStubsPtr->tkTextChanged) /* 166 */
+#define TkBTreeNumLines \
+ (tkIntStubsPtr->tkBTreeNumLines) /* 167 */
+#define TkTextInsertDisplayProc \
+ (tkIntStubsPtr->tkTextInsertDisplayProc) /* 168 */
+#define TkStateParseProc \
+ (tkIntStubsPtr->tkStateParseProc) /* 169 */
+#define TkStatePrintProc \
+ (tkIntStubsPtr->tkStatePrintProc) /* 170 */
+#define TkCanvasDashParseProc \
+ (tkIntStubsPtr->tkCanvasDashParseProc) /* 171 */
+#define TkCanvasDashPrintProc \
+ (tkIntStubsPtr->tkCanvasDashPrintProc) /* 172 */
+#define TkOffsetParseProc \
+ (tkIntStubsPtr->tkOffsetParseProc) /* 173 */
+#define TkOffsetPrintProc \
+ (tkIntStubsPtr->tkOffsetPrintProc) /* 174 */
+#define TkPixelParseProc \
+ (tkIntStubsPtr->tkPixelParseProc) /* 175 */
+#define TkPixelPrintProc \
+ (tkIntStubsPtr->tkPixelPrintProc) /* 176 */
+#define TkOrientParseProc \
+ (tkIntStubsPtr->tkOrientParseProc) /* 177 */
+#define TkOrientPrintProc \
+ (tkIntStubsPtr->tkOrientPrintProc) /* 178 */
+#define TkSmoothParseProc \
+ (tkIntStubsPtr->tkSmoothParseProc) /* 179 */
+#define TkSmoothPrintProc \
+ (tkIntStubsPtr->tkSmoothPrintProc) /* 180 */
+#define TkDrawAngledTextLayout \
+ (tkIntStubsPtr->tkDrawAngledTextLayout) /* 181 */
+#define TkUnderlineAngledTextLayout \
+ (tkIntStubsPtr->tkUnderlineAngledTextLayout) /* 182 */
+#define TkIntersectAngledTextLayout \
+ (tkIntStubsPtr->tkIntersectAngledTextLayout) /* 183 */
+#define TkDrawAngledChars \
+ (tkIntStubsPtr->tkDrawAngledChars) /* 184 */
+
+#endif /* defined(USE_TK_STUBS) */
+
+/* !END!: Do not edit above this line. */
+
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLIMPORT
+
+/*
+ * On X11, these macros are just wrappers for the equivalent X Region calls.
+ */
+#if !(defined(_WIN32) || defined(__CYGWIN__) || defined(MAC_OSX_TK)) /* X11 */
+
+#undef TkClipBox
+#undef TkCreateRegion
+#undef TkDestroyRegion
+#undef TkIntersectRegion
+#undef TkRectInRegion
+#undef TkSetRegion
+#undef TkSubtractRegion
+#undef TkUnionRectWithRegion
+
+#define TkClipBox(rgn, rect) XClipBox((Region) rgn, rect)
+#define TkCreateRegion() (TkRegion) XCreateRegion()
+#define TkDestroyRegion(rgn) XDestroyRegion((Region) rgn)
+#define TkIntersectRegion(a, b, r) XIntersectRegion((Region) a, \
+ (Region) b, (Region) r)
+#define TkRectInRegion(r, x, y, w, h) XRectInRegion((Region) r, x, y, w, h)
+#define TkSetRegion(d, gc, rgn) XSetRegion(d, gc, (Region) rgn)
+#define TkSubtractRegion(a, b, r) XSubtractRegion((Region) a, \
+ (Region) b, (Region) r)
+#define TkUnionRectWithRegion(rect, src, ret) XUnionRectWithRegion(rect, \
+ (Region) src, (Region) ret)
+
+#endif /* UNIX */
+
+#endif /* _TKINTDECLS */
+
diff --git a/tk8.6/generic/tkIntPlatDecls.h b/tk8.6/generic/tkIntPlatDecls.h
new file mode 100644
index 0000000..26a5f46
--- /dev/null
+++ b/tk8.6/generic/tkIntPlatDecls.h
@@ -0,0 +1,667 @@
+/*
+ * tkIntPlatDecls.h --
+ *
+ * This file contains the declarations for all platform dependent
+ * unsupported functions that are exported by the Tk library. These
+ * interfaces are not guaranteed to remain the same between
+ * versions. Use at your own risk.
+ *
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
+ * All rights reserved.
+ */
+
+#ifndef _TKINTPLATDECLS
+#define _TKINTPLATDECLS
+
+#ifdef BUILD_tk
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLEXPORT
+#endif
+
+/*
+ * WARNING: This file is automatically generated by the tools/genStubs.tcl
+ * script. Any modifications to the function declarations below should be made
+ * in the generic/tkInt.decls script.
+ */
+
+/* !BEGIN!: Do not edit below this line. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Exported function declarations:
+ */
+
+#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
+/* 0 */
+EXTERN char * TkAlignImageData(XImage *image, int alignment,
+ int bitOrder);
+/* Slot 1 is reserved */
+/* 2 */
+EXTERN void TkGenerateActivateEvents(TkWindow *winPtr,
+ int active);
+/* 3 */
+EXTERN unsigned long TkpGetMS(void);
+/* 4 */
+EXTERN void TkPointerDeadWindow(TkWindow *winPtr);
+/* 5 */
+EXTERN void TkpPrintWindowId(char *buf, Window window);
+/* 6 */
+EXTERN int TkpScanWindowId(Tcl_Interp *interp,
+ const char *string, Window *idPtr);
+/* 7 */
+EXTERN void TkpSetCapture(TkWindow *winPtr);
+/* 8 */
+EXTERN void TkpSetCursor(TkpCursor cursor);
+/* 9 */
+EXTERN int TkpWmSetState(TkWindow *winPtr, int state);
+/* 10 */
+EXTERN void TkSetPixmapColormap(Pixmap pixmap, Colormap colormap);
+/* 11 */
+EXTERN void TkWinCancelMouseTimer(void);
+/* 12 */
+EXTERN void TkWinClipboardRender(TkDisplay *dispPtr, UINT format);
+/* 13 */
+EXTERN LRESULT TkWinEmbeddedEventProc(HWND hwnd, UINT message,
+ WPARAM wParam, LPARAM lParam);
+/* 14 */
+EXTERN void TkWinFillRect(HDC dc, int x, int y, int width,
+ int height, int pixel);
+/* 15 */
+EXTERN COLORREF TkWinGetBorderPixels(Tk_Window tkwin,
+ Tk_3DBorder border, int which);
+/* 16 */
+EXTERN HDC TkWinGetDrawableDC(Display *display, Drawable d,
+ TkWinDCState *state);
+/* 17 */
+EXTERN int TkWinGetModifierState(void);
+/* 18 */
+EXTERN HPALETTE TkWinGetSystemPalette(void);
+/* 19 */
+EXTERN HWND TkWinGetWrapperWindow(Tk_Window tkwin);
+/* 20 */
+EXTERN int TkWinHandleMenuEvent(HWND *phwnd, UINT *pMessage,
+ WPARAM *pwParam, LPARAM *plParam,
+ LRESULT *plResult);
+/* 21 */
+EXTERN int TkWinIndexOfColor(XColor *colorPtr);
+/* 22 */
+EXTERN void TkWinReleaseDrawableDC(Drawable d, HDC hdc,
+ TkWinDCState *state);
+/* 23 */
+EXTERN LRESULT TkWinResendEvent(WNDPROC wndproc, HWND hwnd,
+ XEvent *eventPtr);
+/* 24 */
+EXTERN HPALETTE TkWinSelectPalette(HDC dc, Colormap colormap);
+/* 25 */
+EXTERN void TkWinSetMenu(Tk_Window tkwin, HMENU hMenu);
+/* 26 */
+EXTERN void TkWinSetWindowPos(HWND hwnd, HWND siblingHwnd,
+ int pos);
+/* 27 */
+EXTERN void TkWinWmCleanup(HINSTANCE hInstance);
+/* 28 */
+EXTERN void TkWinXCleanup(ClientData clientData);
+/* 29 */
+EXTERN void TkWinXInit(HINSTANCE hInstance);
+/* 30 */
+EXTERN void TkWinSetForegroundWindow(TkWindow *winPtr);
+/* 31 */
+EXTERN void TkWinDialogDebug(int debug);
+/* 32 */
+EXTERN Tcl_Obj * TkWinGetMenuSystemDefault(Tk_Window tkwin,
+ const char *dbName, const char *className);
+/* 33 */
+EXTERN int TkWinGetPlatformId(void);
+/* 34 */
+EXTERN void TkWinSetHINSTANCE(HINSTANCE hInstance);
+/* 35 */
+EXTERN int TkWinGetPlatformTheme(void);
+/* 36 */
+EXTERN LRESULT __stdcall TkWinChildProc(HWND hwnd, UINT message,
+ WPARAM wParam, LPARAM lParam);
+/* 37 */
+EXTERN void TkCreateXEventSource(void);
+/* 38 */
+EXTERN int TkpCmapStressed(Tk_Window tkwin, Colormap colormap);
+/* 39 */
+EXTERN void TkpSync(Display *display);
+/* 40 */
+EXTERN Window TkUnixContainerId(TkWindow *winPtr);
+/* 41 */
+EXTERN int TkUnixDoOneXEvent(Tcl_Time *timePtr);
+/* 42 */
+EXTERN void TkUnixSetMenubar(Tk_Window tkwin, Tk_Window menubar);
+/* 43 */
+EXTERN void TkWmCleanup(TkDisplay *dispPtr);
+/* 44 */
+EXTERN void TkSendCleanup(TkDisplay *dispPtr);
+/* 45 */
+EXTERN int TkpTestsendCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+#endif /* WIN */
+#ifdef MAC_OSX_TK /* AQUA */
+/* 0 */
+EXTERN void TkGenerateActivateEvents(TkWindow *winPtr,
+ int active);
+/* Slot 1 is reserved */
+/* Slot 2 is reserved */
+/* 3 */
+EXTERN void TkPointerDeadWindow(TkWindow *winPtr);
+/* 4 */
+EXTERN void TkpSetCapture(TkWindow *winPtr);
+/* 5 */
+EXTERN void TkpSetCursor(TkpCursor cursor);
+/* 6 */
+EXTERN void TkpWmSetState(TkWindow *winPtr, int state);
+/* 7 */
+EXTERN void TkAboutDlg(void);
+/* 8 */
+EXTERN unsigned int TkMacOSXButtonKeyState(void);
+/* 9 */
+EXTERN void TkMacOSXClearMenubarActive(void);
+/* 10 */
+EXTERN int TkMacOSXDispatchMenuEvent(int menuID, int index);
+/* 11 */
+EXTERN void TkMacOSXInstallCursor(int resizeOverride);
+/* 12 */
+EXTERN void TkMacOSXHandleTearoffMenu(void);
+/* Slot 13 is reserved */
+/* 14 */
+EXTERN int TkMacOSXDoHLEvent(void *theEvent);
+/* Slot 15 is reserved */
+/* 16 */
+EXTERN Window TkMacOSXGetXWindow(void *macWinPtr);
+/* 17 */
+EXTERN int TkMacOSXGrowToplevel(void *whichWindow, XPoint start);
+/* 18 */
+EXTERN void TkMacOSXHandleMenuSelect(short theMenu,
+ unsigned short theItem, int optionKeyPressed);
+/* Slot 19 is reserved */
+/* Slot 20 is reserved */
+/* 21 */
+EXTERN void TkMacOSXInvalidateWindow(MacDrawable *macWin,
+ int flag);
+/* 22 */
+EXTERN int TkMacOSXIsCharacterMissing(Tk_Font tkfont,
+ unsigned int searchChar);
+/* 23 */
+EXTERN void TkMacOSXMakeRealWindowExist(TkWindow *winPtr);
+/* 24 */
+EXTERN void * TkMacOSXMakeStippleMap(Drawable d1, Drawable d2);
+/* 25 */
+EXTERN void TkMacOSXMenuClick(void);
+/* 26 */
+EXTERN void TkMacOSXRegisterOffScreenWindow(Window window,
+ void *portPtr);
+/* 27 */
+EXTERN int TkMacOSXResizable(TkWindow *winPtr);
+/* 28 */
+EXTERN void TkMacOSXSetHelpMenuItemCount(void);
+/* 29 */
+EXTERN void TkMacOSXSetScrollbarGrow(TkWindow *winPtr, int flag);
+/* 30 */
+EXTERN void TkMacOSXSetUpClippingRgn(Drawable drawable);
+/* 31 */
+EXTERN void TkMacOSXSetUpGraphicsPort(GC gc, void *destPort);
+/* 32 */
+EXTERN void TkMacOSXUpdateClipRgn(TkWindow *winPtr);
+/* 33 */
+EXTERN void TkMacOSXUnregisterMacWindow(void *portPtr);
+/* 34 */
+EXTERN int TkMacOSXUseMenuID(short macID);
+/* 35 */
+EXTERN TkRegion TkMacOSXVisableClipRgn(TkWindow *winPtr);
+/* 36 */
+EXTERN void TkMacOSXWinBounds(TkWindow *winPtr, void *geometry);
+/* 37 */
+EXTERN void TkMacOSXWindowOffset(void *wRef, int *xOffset,
+ int *yOffset);
+/* 38 */
+EXTERN int TkSetMacColor(unsigned long pixel, void *macColor);
+/* 39 */
+EXTERN void TkSetWMName(TkWindow *winPtr, Tk_Uid titleUid);
+/* Slot 40 is reserved */
+/* 41 */
+EXTERN int TkMacOSXZoomToplevel(void *whichWindow,
+ short zoomPart);
+/* 42 */
+EXTERN Tk_Window Tk_TopCoordsToWindow(Tk_Window tkwin, int rootX,
+ int rootY, int *newX, int *newY);
+/* 43 */
+EXTERN MacDrawable * TkMacOSXContainerId(TkWindow *winPtr);
+/* 44 */
+EXTERN MacDrawable * TkMacOSXGetHostToplevel(TkWindow *winPtr);
+/* 45 */
+EXTERN void TkMacOSXPreprocessMenu(void);
+/* 46 */
+EXTERN int TkpIsWindowFloating(void *window);
+/* 47 */
+EXTERN Tk_Window TkMacOSXGetCapture(void);
+/* Slot 48 is reserved */
+/* 49 */
+EXTERN Tk_Window TkGetTransientMaster(TkWindow *winPtr);
+/* 50 */
+EXTERN int TkGenerateButtonEvent(int x, int y, Window window,
+ unsigned int state);
+/* 51 */
+EXTERN void TkGenWMDestroyEvent(Tk_Window tkwin);
+/* 52 */
+EXTERN void TkMacOSXSetDrawingEnabled(TkWindow *winPtr, int flag);
+/* 53 */
+EXTERN unsigned long TkpGetMS(void);
+/* 54 */
+EXTERN void * TkMacOSXDrawable(Drawable drawable);
+/* 55 */
+EXTERN int TkpScanWindowId(Tcl_Interp *interp,
+ const char *string, Window *idPtr);
+#endif /* AQUA */
+#if !(defined(_WIN32) || defined(__CYGWIN__) || defined(MAC_OSX_TK)) /* X11 */
+/* 0 */
+EXTERN void TkCreateXEventSource(void);
+/* Slot 1 is reserved */
+/* Slot 2 is reserved */
+/* 3 */
+EXTERN int TkpCmapStressed(Tk_Window tkwin, Colormap colormap);
+/* 4 */
+EXTERN void TkpSync(Display *display);
+/* 5 */
+EXTERN Window TkUnixContainerId(TkWindow *winPtr);
+/* 6 */
+EXTERN int TkUnixDoOneXEvent(Tcl_Time *timePtr);
+/* 7 */
+EXTERN void TkUnixSetMenubar(Tk_Window tkwin, Tk_Window menubar);
+/* 8 */
+EXTERN int TkpScanWindowId(Tcl_Interp *interp,
+ const char *string, Window *idPtr);
+/* 9 */
+EXTERN void TkWmCleanup(TkDisplay *dispPtr);
+/* 10 */
+EXTERN void TkSendCleanup(TkDisplay *dispPtr);
+/* Slot 11 is reserved */
+/* 12 */
+EXTERN int TkpWmSetState(TkWindow *winPtr, int state);
+/* 13 */
+EXTERN int TkpTestsendCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+#endif /* X11 */
+
+typedef struct TkIntPlatStubs {
+ int magic;
+ void *hooks;
+
+#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
+ char * (*tkAlignImageData) (XImage *image, int alignment, int bitOrder); /* 0 */
+ void (*reserved1)(void);
+ void (*tkGenerateActivateEvents) (TkWindow *winPtr, int active); /* 2 */
+ unsigned long (*tkpGetMS) (void); /* 3 */
+ void (*tkPointerDeadWindow) (TkWindow *winPtr); /* 4 */
+ void (*tkpPrintWindowId) (char *buf, Window window); /* 5 */
+ int (*tkpScanWindowId) (Tcl_Interp *interp, const char *string, Window *idPtr); /* 6 */
+ void (*tkpSetCapture) (TkWindow *winPtr); /* 7 */
+ void (*tkpSetCursor) (TkpCursor cursor); /* 8 */
+ int (*tkpWmSetState) (TkWindow *winPtr, int state); /* 9 */
+ void (*tkSetPixmapColormap) (Pixmap pixmap, Colormap colormap); /* 10 */
+ void (*tkWinCancelMouseTimer) (void); /* 11 */
+ void (*tkWinClipboardRender) (TkDisplay *dispPtr, UINT format); /* 12 */
+ LRESULT (*tkWinEmbeddedEventProc) (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); /* 13 */
+ void (*tkWinFillRect) (HDC dc, int x, int y, int width, int height, int pixel); /* 14 */
+ COLORREF (*tkWinGetBorderPixels) (Tk_Window tkwin, Tk_3DBorder border, int which); /* 15 */
+ HDC (*tkWinGetDrawableDC) (Display *display, Drawable d, TkWinDCState *state); /* 16 */
+ int (*tkWinGetModifierState) (void); /* 17 */
+ HPALETTE (*tkWinGetSystemPalette) (void); /* 18 */
+ HWND (*tkWinGetWrapperWindow) (Tk_Window tkwin); /* 19 */
+ int (*tkWinHandleMenuEvent) (HWND *phwnd, UINT *pMessage, WPARAM *pwParam, LPARAM *plParam, LRESULT *plResult); /* 20 */
+ int (*tkWinIndexOfColor) (XColor *colorPtr); /* 21 */
+ void (*tkWinReleaseDrawableDC) (Drawable d, HDC hdc, TkWinDCState *state); /* 22 */
+ LRESULT (*tkWinResendEvent) (WNDPROC wndproc, HWND hwnd, XEvent *eventPtr); /* 23 */
+ HPALETTE (*tkWinSelectPalette) (HDC dc, Colormap colormap); /* 24 */
+ void (*tkWinSetMenu) (Tk_Window tkwin, HMENU hMenu); /* 25 */
+ void (*tkWinSetWindowPos) (HWND hwnd, HWND siblingHwnd, int pos); /* 26 */
+ void (*tkWinWmCleanup) (HINSTANCE hInstance); /* 27 */
+ void (*tkWinXCleanup) (ClientData clientData); /* 28 */
+ void (*tkWinXInit) (HINSTANCE hInstance); /* 29 */
+ void (*tkWinSetForegroundWindow) (TkWindow *winPtr); /* 30 */
+ void (*tkWinDialogDebug) (int debug); /* 31 */
+ Tcl_Obj * (*tkWinGetMenuSystemDefault) (Tk_Window tkwin, const char *dbName, const char *className); /* 32 */
+ int (*tkWinGetPlatformId) (void); /* 33 */
+ void (*tkWinSetHINSTANCE) (HINSTANCE hInstance); /* 34 */
+ int (*tkWinGetPlatformTheme) (void); /* 35 */
+ LRESULT (__stdcall *tkWinChildProc) (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); /* 36 */
+ void (*tkCreateXEventSource) (void); /* 37 */
+ int (*tkpCmapStressed) (Tk_Window tkwin, Colormap colormap); /* 38 */
+ void (*tkpSync) (Display *display); /* 39 */
+ Window (*tkUnixContainerId) (TkWindow *winPtr); /* 40 */
+ int (*tkUnixDoOneXEvent) (Tcl_Time *timePtr); /* 41 */
+ void (*tkUnixSetMenubar) (Tk_Window tkwin, Tk_Window menubar); /* 42 */
+ void (*tkWmCleanup) (TkDisplay *dispPtr); /* 43 */
+ void (*tkSendCleanup) (TkDisplay *dispPtr); /* 44 */
+ int (*tkpTestsendCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 45 */
+#endif /* WIN */
+#ifdef MAC_OSX_TK /* AQUA */
+ void (*tkGenerateActivateEvents) (TkWindow *winPtr, int active); /* 0 */
+ void (*reserved1)(void);
+ void (*reserved2)(void);
+ void (*tkPointerDeadWindow) (TkWindow *winPtr); /* 3 */
+ void (*tkpSetCapture) (TkWindow *winPtr); /* 4 */
+ void (*tkpSetCursor) (TkpCursor cursor); /* 5 */
+ void (*tkpWmSetState) (TkWindow *winPtr, int state); /* 6 */
+ void (*tkAboutDlg) (void); /* 7 */
+ unsigned int (*tkMacOSXButtonKeyState) (void); /* 8 */
+ void (*tkMacOSXClearMenubarActive) (void); /* 9 */
+ int (*tkMacOSXDispatchMenuEvent) (int menuID, int index); /* 10 */
+ void (*tkMacOSXInstallCursor) (int resizeOverride); /* 11 */
+ void (*tkMacOSXHandleTearoffMenu) (void); /* 12 */
+ void (*reserved13)(void);
+ int (*tkMacOSXDoHLEvent) (void *theEvent); /* 14 */
+ void (*reserved15)(void);
+ Window (*tkMacOSXGetXWindow) (void *macWinPtr); /* 16 */
+ int (*tkMacOSXGrowToplevel) (void *whichWindow, XPoint start); /* 17 */
+ void (*tkMacOSXHandleMenuSelect) (short theMenu, unsigned short theItem, int optionKeyPressed); /* 18 */
+ void (*reserved19)(void);
+ void (*reserved20)(void);
+ void (*tkMacOSXInvalidateWindow) (MacDrawable *macWin, int flag); /* 21 */
+ int (*tkMacOSXIsCharacterMissing) (Tk_Font tkfont, unsigned int searchChar); /* 22 */
+ void (*tkMacOSXMakeRealWindowExist) (TkWindow *winPtr); /* 23 */
+ void * (*tkMacOSXMakeStippleMap) (Drawable d1, Drawable d2); /* 24 */
+ void (*tkMacOSXMenuClick) (void); /* 25 */
+ void (*tkMacOSXRegisterOffScreenWindow) (Window window, void *portPtr); /* 26 */
+ int (*tkMacOSXResizable) (TkWindow *winPtr); /* 27 */
+ void (*tkMacOSXSetHelpMenuItemCount) (void); /* 28 */
+ void (*tkMacOSXSetScrollbarGrow) (TkWindow *winPtr, int flag); /* 29 */
+ void (*tkMacOSXSetUpClippingRgn) (Drawable drawable); /* 30 */
+ void (*tkMacOSXSetUpGraphicsPort) (GC gc, void *destPort); /* 31 */
+ void (*tkMacOSXUpdateClipRgn) (TkWindow *winPtr); /* 32 */
+ void (*tkMacOSXUnregisterMacWindow) (void *portPtr); /* 33 */
+ int (*tkMacOSXUseMenuID) (short macID); /* 34 */
+ TkRegion (*tkMacOSXVisableClipRgn) (TkWindow *winPtr); /* 35 */
+ void (*tkMacOSXWinBounds) (TkWindow *winPtr, void *geometry); /* 36 */
+ void (*tkMacOSXWindowOffset) (void *wRef, int *xOffset, int *yOffset); /* 37 */
+ int (*tkSetMacColor) (unsigned long pixel, void *macColor); /* 38 */
+ void (*tkSetWMName) (TkWindow *winPtr, Tk_Uid titleUid); /* 39 */
+ void (*reserved40)(void);
+ int (*tkMacOSXZoomToplevel) (void *whichWindow, short zoomPart); /* 41 */
+ Tk_Window (*tk_TopCoordsToWindow) (Tk_Window tkwin, int rootX, int rootY, int *newX, int *newY); /* 42 */
+ MacDrawable * (*tkMacOSXContainerId) (TkWindow *winPtr); /* 43 */
+ MacDrawable * (*tkMacOSXGetHostToplevel) (TkWindow *winPtr); /* 44 */
+ void (*tkMacOSXPreprocessMenu) (void); /* 45 */
+ int (*tkpIsWindowFloating) (void *window); /* 46 */
+ Tk_Window (*tkMacOSXGetCapture) (void); /* 47 */
+ void (*reserved48)(void);
+ Tk_Window (*tkGetTransientMaster) (TkWindow *winPtr); /* 49 */
+ int (*tkGenerateButtonEvent) (int x, int y, Window window, unsigned int state); /* 50 */
+ void (*tkGenWMDestroyEvent) (Tk_Window tkwin); /* 51 */
+ void (*tkMacOSXSetDrawingEnabled) (TkWindow *winPtr, int flag); /* 52 */
+ unsigned long (*tkpGetMS) (void); /* 53 */
+ void * (*tkMacOSXDrawable) (Drawable drawable); /* 54 */
+ int (*tkpScanWindowId) (Tcl_Interp *interp, const char *string, Window *idPtr); /* 55 */
+#endif /* AQUA */
+#if !(defined(_WIN32) || defined(__CYGWIN__) || defined(MAC_OSX_TK)) /* X11 */
+ void (*tkCreateXEventSource) (void); /* 0 */
+ void (*reserved1)(void);
+ void (*reserved2)(void);
+ int (*tkpCmapStressed) (Tk_Window tkwin, Colormap colormap); /* 3 */
+ void (*tkpSync) (Display *display); /* 4 */
+ Window (*tkUnixContainerId) (TkWindow *winPtr); /* 5 */
+ int (*tkUnixDoOneXEvent) (Tcl_Time *timePtr); /* 6 */
+ void (*tkUnixSetMenubar) (Tk_Window tkwin, Tk_Window menubar); /* 7 */
+ int (*tkpScanWindowId) (Tcl_Interp *interp, const char *string, Window *idPtr); /* 8 */
+ void (*tkWmCleanup) (TkDisplay *dispPtr); /* 9 */
+ void (*tkSendCleanup) (TkDisplay *dispPtr); /* 10 */
+ void (*reserved11)(void);
+ int (*tkpWmSetState) (TkWindow *winPtr, int state); /* 12 */
+ int (*tkpTestsendCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 13 */
+#endif /* X11 */
+} TkIntPlatStubs;
+
+extern const TkIntPlatStubs *tkIntPlatStubsPtr;
+
+#ifdef __cplusplus
+}
+#endif
+
+#if defined(USE_TK_STUBS)
+
+/*
+ * Inline function declarations:
+ */
+
+#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
+#define TkAlignImageData \
+ (tkIntPlatStubsPtr->tkAlignImageData) /* 0 */
+/* Slot 1 is reserved */
+#define TkGenerateActivateEvents \
+ (tkIntPlatStubsPtr->tkGenerateActivateEvents) /* 2 */
+#define TkpGetMS \
+ (tkIntPlatStubsPtr->tkpGetMS) /* 3 */
+#define TkPointerDeadWindow \
+ (tkIntPlatStubsPtr->tkPointerDeadWindow) /* 4 */
+#define TkpPrintWindowId \
+ (tkIntPlatStubsPtr->tkpPrintWindowId) /* 5 */
+#define TkpScanWindowId \
+ (tkIntPlatStubsPtr->tkpScanWindowId) /* 6 */
+#define TkpSetCapture \
+ (tkIntPlatStubsPtr->tkpSetCapture) /* 7 */
+#define TkpSetCursor \
+ (tkIntPlatStubsPtr->tkpSetCursor) /* 8 */
+#define TkpWmSetState \
+ (tkIntPlatStubsPtr->tkpWmSetState) /* 9 */
+#define TkSetPixmapColormap \
+ (tkIntPlatStubsPtr->tkSetPixmapColormap) /* 10 */
+#define TkWinCancelMouseTimer \
+ (tkIntPlatStubsPtr->tkWinCancelMouseTimer) /* 11 */
+#define TkWinClipboardRender \
+ (tkIntPlatStubsPtr->tkWinClipboardRender) /* 12 */
+#define TkWinEmbeddedEventProc \
+ (tkIntPlatStubsPtr->tkWinEmbeddedEventProc) /* 13 */
+#define TkWinFillRect \
+ (tkIntPlatStubsPtr->tkWinFillRect) /* 14 */
+#define TkWinGetBorderPixels \
+ (tkIntPlatStubsPtr->tkWinGetBorderPixels) /* 15 */
+#define TkWinGetDrawableDC \
+ (tkIntPlatStubsPtr->tkWinGetDrawableDC) /* 16 */
+#define TkWinGetModifierState \
+ (tkIntPlatStubsPtr->tkWinGetModifierState) /* 17 */
+#define TkWinGetSystemPalette \
+ (tkIntPlatStubsPtr->tkWinGetSystemPalette) /* 18 */
+#define TkWinGetWrapperWindow \
+ (tkIntPlatStubsPtr->tkWinGetWrapperWindow) /* 19 */
+#define TkWinHandleMenuEvent \
+ (tkIntPlatStubsPtr->tkWinHandleMenuEvent) /* 20 */
+#define TkWinIndexOfColor \
+ (tkIntPlatStubsPtr->tkWinIndexOfColor) /* 21 */
+#define TkWinReleaseDrawableDC \
+ (tkIntPlatStubsPtr->tkWinReleaseDrawableDC) /* 22 */
+#define TkWinResendEvent \
+ (tkIntPlatStubsPtr->tkWinResendEvent) /* 23 */
+#define TkWinSelectPalette \
+ (tkIntPlatStubsPtr->tkWinSelectPalette) /* 24 */
+#define TkWinSetMenu \
+ (tkIntPlatStubsPtr->tkWinSetMenu) /* 25 */
+#define TkWinSetWindowPos \
+ (tkIntPlatStubsPtr->tkWinSetWindowPos) /* 26 */
+#define TkWinWmCleanup \
+ (tkIntPlatStubsPtr->tkWinWmCleanup) /* 27 */
+#define TkWinXCleanup \
+ (tkIntPlatStubsPtr->tkWinXCleanup) /* 28 */
+#define TkWinXInit \
+ (tkIntPlatStubsPtr->tkWinXInit) /* 29 */
+#define TkWinSetForegroundWindow \
+ (tkIntPlatStubsPtr->tkWinSetForegroundWindow) /* 30 */
+#define TkWinDialogDebug \
+ (tkIntPlatStubsPtr->tkWinDialogDebug) /* 31 */
+#define TkWinGetMenuSystemDefault \
+ (tkIntPlatStubsPtr->tkWinGetMenuSystemDefault) /* 32 */
+#define TkWinGetPlatformId \
+ (tkIntPlatStubsPtr->tkWinGetPlatformId) /* 33 */
+#define TkWinSetHINSTANCE \
+ (tkIntPlatStubsPtr->tkWinSetHINSTANCE) /* 34 */
+#define TkWinGetPlatformTheme \
+ (tkIntPlatStubsPtr->tkWinGetPlatformTheme) /* 35 */
+#define TkWinChildProc \
+ (tkIntPlatStubsPtr->tkWinChildProc) /* 36 */
+#define TkCreateXEventSource \
+ (tkIntPlatStubsPtr->tkCreateXEventSource) /* 37 */
+#define TkpCmapStressed \
+ (tkIntPlatStubsPtr->tkpCmapStressed) /* 38 */
+#define TkpSync \
+ (tkIntPlatStubsPtr->tkpSync) /* 39 */
+#define TkUnixContainerId \
+ (tkIntPlatStubsPtr->tkUnixContainerId) /* 40 */
+#define TkUnixDoOneXEvent \
+ (tkIntPlatStubsPtr->tkUnixDoOneXEvent) /* 41 */
+#define TkUnixSetMenubar \
+ (tkIntPlatStubsPtr->tkUnixSetMenubar) /* 42 */
+#define TkWmCleanup \
+ (tkIntPlatStubsPtr->tkWmCleanup) /* 43 */
+#define TkSendCleanup \
+ (tkIntPlatStubsPtr->tkSendCleanup) /* 44 */
+#define TkpTestsendCmd \
+ (tkIntPlatStubsPtr->tkpTestsendCmd) /* 45 */
+#endif /* WIN */
+#ifdef MAC_OSX_TK /* AQUA */
+#define TkGenerateActivateEvents \
+ (tkIntPlatStubsPtr->tkGenerateActivateEvents) /* 0 */
+/* Slot 1 is reserved */
+/* Slot 2 is reserved */
+#define TkPointerDeadWindow \
+ (tkIntPlatStubsPtr->tkPointerDeadWindow) /* 3 */
+#define TkpSetCapture \
+ (tkIntPlatStubsPtr->tkpSetCapture) /* 4 */
+#define TkpSetCursor \
+ (tkIntPlatStubsPtr->tkpSetCursor) /* 5 */
+#define TkpWmSetState \
+ (tkIntPlatStubsPtr->tkpWmSetState) /* 6 */
+#define TkAboutDlg \
+ (tkIntPlatStubsPtr->tkAboutDlg) /* 7 */
+#define TkMacOSXButtonKeyState \
+ (tkIntPlatStubsPtr->tkMacOSXButtonKeyState) /* 8 */
+#define TkMacOSXClearMenubarActive \
+ (tkIntPlatStubsPtr->tkMacOSXClearMenubarActive) /* 9 */
+#define TkMacOSXDispatchMenuEvent \
+ (tkIntPlatStubsPtr->tkMacOSXDispatchMenuEvent) /* 10 */
+#define TkMacOSXInstallCursor \
+ (tkIntPlatStubsPtr->tkMacOSXInstallCursor) /* 11 */
+#define TkMacOSXHandleTearoffMenu \
+ (tkIntPlatStubsPtr->tkMacOSXHandleTearoffMenu) /* 12 */
+/* Slot 13 is reserved */
+#define TkMacOSXDoHLEvent \
+ (tkIntPlatStubsPtr->tkMacOSXDoHLEvent) /* 14 */
+/* Slot 15 is reserved */
+#define TkMacOSXGetXWindow \
+ (tkIntPlatStubsPtr->tkMacOSXGetXWindow) /* 16 */
+#define TkMacOSXGrowToplevel \
+ (tkIntPlatStubsPtr->tkMacOSXGrowToplevel) /* 17 */
+#define TkMacOSXHandleMenuSelect \
+ (tkIntPlatStubsPtr->tkMacOSXHandleMenuSelect) /* 18 */
+/* Slot 19 is reserved */
+/* Slot 20 is reserved */
+#define TkMacOSXInvalidateWindow \
+ (tkIntPlatStubsPtr->tkMacOSXInvalidateWindow) /* 21 */
+#define TkMacOSXIsCharacterMissing \
+ (tkIntPlatStubsPtr->tkMacOSXIsCharacterMissing) /* 22 */
+#define TkMacOSXMakeRealWindowExist \
+ (tkIntPlatStubsPtr->tkMacOSXMakeRealWindowExist) /* 23 */
+#define TkMacOSXMakeStippleMap \
+ (tkIntPlatStubsPtr->tkMacOSXMakeStippleMap) /* 24 */
+#define TkMacOSXMenuClick \
+ (tkIntPlatStubsPtr->tkMacOSXMenuClick) /* 25 */
+#define TkMacOSXRegisterOffScreenWindow \
+ (tkIntPlatStubsPtr->tkMacOSXRegisterOffScreenWindow) /* 26 */
+#define TkMacOSXResizable \
+ (tkIntPlatStubsPtr->tkMacOSXResizable) /* 27 */
+#define TkMacOSXSetHelpMenuItemCount \
+ (tkIntPlatStubsPtr->tkMacOSXSetHelpMenuItemCount) /* 28 */
+#define TkMacOSXSetScrollbarGrow \
+ (tkIntPlatStubsPtr->tkMacOSXSetScrollbarGrow) /* 29 */
+#define TkMacOSXSetUpClippingRgn \
+ (tkIntPlatStubsPtr->tkMacOSXSetUpClippingRgn) /* 30 */
+#define TkMacOSXSetUpGraphicsPort \
+ (tkIntPlatStubsPtr->tkMacOSXSetUpGraphicsPort) /* 31 */
+#define TkMacOSXUpdateClipRgn \
+ (tkIntPlatStubsPtr->tkMacOSXUpdateClipRgn) /* 32 */
+#define TkMacOSXUnregisterMacWindow \
+ (tkIntPlatStubsPtr->tkMacOSXUnregisterMacWindow) /* 33 */
+#define TkMacOSXUseMenuID \
+ (tkIntPlatStubsPtr->tkMacOSXUseMenuID) /* 34 */
+#define TkMacOSXVisableClipRgn \
+ (tkIntPlatStubsPtr->tkMacOSXVisableClipRgn) /* 35 */
+#define TkMacOSXWinBounds \
+ (tkIntPlatStubsPtr->tkMacOSXWinBounds) /* 36 */
+#define TkMacOSXWindowOffset \
+ (tkIntPlatStubsPtr->tkMacOSXWindowOffset) /* 37 */
+#define TkSetMacColor \
+ (tkIntPlatStubsPtr->tkSetMacColor) /* 38 */
+#define TkSetWMName \
+ (tkIntPlatStubsPtr->tkSetWMName) /* 39 */
+/* Slot 40 is reserved */
+#define TkMacOSXZoomToplevel \
+ (tkIntPlatStubsPtr->tkMacOSXZoomToplevel) /* 41 */
+#define Tk_TopCoordsToWindow \
+ (tkIntPlatStubsPtr->tk_TopCoordsToWindow) /* 42 */
+#define TkMacOSXContainerId \
+ (tkIntPlatStubsPtr->tkMacOSXContainerId) /* 43 */
+#define TkMacOSXGetHostToplevel \
+ (tkIntPlatStubsPtr->tkMacOSXGetHostToplevel) /* 44 */
+#define TkMacOSXPreprocessMenu \
+ (tkIntPlatStubsPtr->tkMacOSXPreprocessMenu) /* 45 */
+#define TkpIsWindowFloating \
+ (tkIntPlatStubsPtr->tkpIsWindowFloating) /* 46 */
+#define TkMacOSXGetCapture \
+ (tkIntPlatStubsPtr->tkMacOSXGetCapture) /* 47 */
+/* Slot 48 is reserved */
+#define TkGetTransientMaster \
+ (tkIntPlatStubsPtr->tkGetTransientMaster) /* 49 */
+#define TkGenerateButtonEvent \
+ (tkIntPlatStubsPtr->tkGenerateButtonEvent) /* 50 */
+#define TkGenWMDestroyEvent \
+ (tkIntPlatStubsPtr->tkGenWMDestroyEvent) /* 51 */
+#define TkMacOSXSetDrawingEnabled \
+ (tkIntPlatStubsPtr->tkMacOSXSetDrawingEnabled) /* 52 */
+#define TkpGetMS \
+ (tkIntPlatStubsPtr->tkpGetMS) /* 53 */
+#define TkMacOSXDrawable \
+ (tkIntPlatStubsPtr->tkMacOSXDrawable) /* 54 */
+#define TkpScanWindowId \
+ (tkIntPlatStubsPtr->tkpScanWindowId) /* 55 */
+#endif /* AQUA */
+#if !(defined(_WIN32) || defined(__CYGWIN__) || defined(MAC_OSX_TK)) /* X11 */
+#define TkCreateXEventSource \
+ (tkIntPlatStubsPtr->tkCreateXEventSource) /* 0 */
+/* Slot 1 is reserved */
+/* Slot 2 is reserved */
+#define TkpCmapStressed \
+ (tkIntPlatStubsPtr->tkpCmapStressed) /* 3 */
+#define TkpSync \
+ (tkIntPlatStubsPtr->tkpSync) /* 4 */
+#define TkUnixContainerId \
+ (tkIntPlatStubsPtr->tkUnixContainerId) /* 5 */
+#define TkUnixDoOneXEvent \
+ (tkIntPlatStubsPtr->tkUnixDoOneXEvent) /* 6 */
+#define TkUnixSetMenubar \
+ (tkIntPlatStubsPtr->tkUnixSetMenubar) /* 7 */
+#define TkpScanWindowId \
+ (tkIntPlatStubsPtr->tkpScanWindowId) /* 8 */
+#define TkWmCleanup \
+ (tkIntPlatStubsPtr->tkWmCleanup) /* 9 */
+#define TkSendCleanup \
+ (tkIntPlatStubsPtr->tkSendCleanup) /* 10 */
+/* Slot 11 is reserved */
+#define TkpWmSetState \
+ (tkIntPlatStubsPtr->tkpWmSetState) /* 12 */
+#define TkpTestsendCmd \
+ (tkIntPlatStubsPtr->tkpTestsendCmd) /* 13 */
+#endif /* X11 */
+
+#endif /* defined(USE_TK_STUBS) */
+
+/* !END!: Do not edit above this line. */
+
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLIMPORT
+
+#endif /* _TKINTPLATDECLS */
diff --git a/tk8.6/generic/tkIntXlibDecls.h b/tk8.6/generic/tkIntXlibDecls.h
new file mode 100644
index 0000000..de44068
--- /dev/null
+++ b/tk8.6/generic/tkIntXlibDecls.h
@@ -0,0 +1,1394 @@
+/*
+ * tkIntXlibDecls.h --
+ *
+ * This file contains the declarations for all platform dependent
+ * unsupported functions that are exported by the Tk library. These
+ * interfaces are not guaranteed to remain the same between
+ * versions. Use at your own risk.
+ *
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
+ * All rights reserved.
+ */
+
+#ifndef _TKINTXLIBDECLS
+#define _TKINTXLIBDECLS
+
+/*
+ * WARNING: This file is automatically generated by the tools/genStubs.tcl
+ * script. Any modifications to the function declarations below should be made
+ * in the generic/tkInt.decls script.
+ */
+
+#ifndef _TCL
+# include <tcl.h>
+#endif
+
+/* Some (older) versions of X11/Xutil.h have a wrong signature of those
+ two functions, so move them out of the way temporarly. */
+#define XOffsetRegion _XOffsetRegion
+#define XUnionRegion _XUnionRegion
+#include "X11/Xutil.h"
+#undef XOffsetRegion
+#undef XUnionRegion
+
+#ifdef BUILD_tk
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLEXPORT
+#endif
+
+typedef int (*XAfterFunction) ( /* WARNING, this type not in Xlib spec */
+ Display* /* display */
+);
+
+/* !BEGIN!: Do not edit below this line. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Exported function declarations:
+ */
+
+#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
+/* 0 */
+EXTERN int XSetDashes(Display *display, GC gc, int dash_offset,
+ _Xconst char *dash_list, int n);
+/* 1 */
+EXTERN XModifierKeymap * XGetModifierMapping(Display *d);
+/* 2 */
+EXTERN XImage * XCreateImage(Display *d, Visual *v, unsigned int ui1,
+ int i1, int i2, char *cp, unsigned int ui2,
+ unsigned int ui3, int i3, int i4);
+/* 3 */
+EXTERN XImage * XGetImage(Display *d, Drawable dr, int i1, int i2,
+ unsigned int ui1, unsigned int ui2,
+ unsigned long ul, int i3);
+/* 4 */
+EXTERN char * XGetAtomName(Display *d, Atom a);
+/* 5 */
+EXTERN char * XKeysymToString(KeySym k);
+/* 6 */
+EXTERN Colormap XCreateColormap(Display *d, Window w, Visual *v,
+ int i);
+/* 7 */
+EXTERN Cursor XCreatePixmapCursor(Display *d, Pixmap p1, Pixmap p2,
+ XColor *x1, XColor *x2, unsigned int ui1,
+ unsigned int ui2);
+/* 8 */
+EXTERN Cursor XCreateGlyphCursor(Display *d, Font f1, Font f2,
+ unsigned int ui1, unsigned int ui2,
+ XColor _Xconst *x1, XColor _Xconst *x2);
+/* 9 */
+EXTERN GContext XGContextFromGC(GC g);
+/* 10 */
+EXTERN XHostAddress * XListHosts(Display *d, int *i, Bool *b);
+/* 11 */
+EXTERN KeySym XKeycodeToKeysym(Display *d, unsigned int k, int i);
+/* 12 */
+EXTERN KeySym XStringToKeysym(_Xconst char *c);
+/* 13 */
+EXTERN Window XRootWindow(Display *d, int i);
+/* 14 */
+EXTERN XErrorHandler XSetErrorHandler(XErrorHandler x);
+/* 15 */
+EXTERN Status XIconifyWindow(Display *d, Window w, int i);
+/* 16 */
+EXTERN Status XWithdrawWindow(Display *d, Window w, int i);
+/* 17 */
+EXTERN Status XGetWMColormapWindows(Display *d, Window w,
+ Window **wpp, int *ip);
+/* 18 */
+EXTERN Status XAllocColor(Display *d, Colormap c, XColor *xp);
+/* 19 */
+EXTERN int XBell(Display *d, int i);
+/* 20 */
+EXTERN int XChangeProperty(Display *d, Window w, Atom a1,
+ Atom a2, int i1, int i2,
+ _Xconst unsigned char *c, int i3);
+/* 21 */
+EXTERN int XChangeWindowAttributes(Display *d, Window w,
+ unsigned long ul, XSetWindowAttributes *x);
+/* 22 */
+EXTERN int XClearWindow(Display *d, Window w);
+/* 23 */
+EXTERN int XConfigureWindow(Display *d, Window w,
+ unsigned int i, XWindowChanges *x);
+/* 24 */
+EXTERN int XCopyArea(Display *d, Drawable dr1, Drawable dr2,
+ GC g, int i1, int i2, unsigned int ui1,
+ unsigned int ui2, int i3, int i4);
+/* 25 */
+EXTERN int XCopyPlane(Display *d, Drawable dr1, Drawable dr2,
+ GC g, int i1, int i2, unsigned int ui1,
+ unsigned int ui2, int i3, int i4,
+ unsigned long ul);
+/* 26 */
+EXTERN Pixmap XCreateBitmapFromData(Display *display, Drawable d,
+ _Xconst char *data, unsigned int width,
+ unsigned int height);
+/* 27 */
+EXTERN int XDefineCursor(Display *d, Window w, Cursor c);
+/* 28 */
+EXTERN int XDeleteProperty(Display *d, Window w, Atom a);
+/* 29 */
+EXTERN int XDestroyWindow(Display *d, Window w);
+/* 30 */
+EXTERN int XDrawArc(Display *d, Drawable dr, GC g, int i1,
+ int i2, unsigned int ui1, unsigned int ui2,
+ int i3, int i4);
+/* 31 */
+EXTERN int XDrawLines(Display *d, Drawable dr, GC g, XPoint *x,
+ int i1, int i2);
+/* 32 */
+EXTERN int XDrawRectangle(Display *d, Drawable dr, GC g, int i1,
+ int i2, unsigned int ui1, unsigned int ui2);
+/* 33 */
+EXTERN int XFillArc(Display *d, Drawable dr, GC g, int i1,
+ int i2, unsigned int ui1, unsigned int ui2,
+ int i3, int i4);
+/* 34 */
+EXTERN int XFillPolygon(Display *d, Drawable dr, GC g,
+ XPoint *x, int i1, int i2, int i3);
+/* 35 */
+EXTERN int XFillRectangles(Display *d, Drawable dr, GC g,
+ XRectangle *x, int i);
+/* 36 */
+EXTERN int XForceScreenSaver(Display *d, int i);
+/* 37 */
+EXTERN int XFreeColormap(Display *d, Colormap c);
+/* 38 */
+EXTERN int XFreeColors(Display *d, Colormap c,
+ unsigned long *ulp, int i, unsigned long ul);
+/* 39 */
+EXTERN int XFreeCursor(Display *d, Cursor c);
+/* 40 */
+EXTERN int XFreeModifiermap(XModifierKeymap *x);
+/* 41 */
+EXTERN Status XGetGeometry(Display *d, Drawable dr, Window *w,
+ int *i1, int *i2, unsigned int *ui1,
+ unsigned int *ui2, unsigned int *ui3,
+ unsigned int *ui4);
+/* 42 */
+EXTERN int XGetInputFocus(Display *d, Window *w, int *i);
+/* 43 */
+EXTERN int XGetWindowProperty(Display *d, Window w, Atom a1,
+ long l1, long l2, Bool b, Atom a2, Atom *ap,
+ int *ip, unsigned long *ulp1,
+ unsigned long *ulp2, unsigned char **cpp);
+/* 44 */
+EXTERN Status XGetWindowAttributes(Display *d, Window w,
+ XWindowAttributes *x);
+/* 45 */
+EXTERN int XGrabKeyboard(Display *d, Window w, Bool b, int i1,
+ int i2, Time t);
+/* 46 */
+EXTERN int XGrabPointer(Display *d, Window w1, Bool b,
+ unsigned int ui, int i1, int i2, Window w2,
+ Cursor c, Time t);
+/* 47 */
+EXTERN KeyCode XKeysymToKeycode(Display *d, KeySym k);
+/* 48 */
+EXTERN Status XLookupColor(Display *d, Colormap c1,
+ _Xconst char *c2, XColor *x1, XColor *x2);
+/* 49 */
+EXTERN int XMapWindow(Display *d, Window w);
+/* 50 */
+EXTERN int XMoveResizeWindow(Display *d, Window w, int i1,
+ int i2, unsigned int ui1, unsigned int ui2);
+/* 51 */
+EXTERN int XMoveWindow(Display *d, Window w, int i1, int i2);
+/* 52 */
+EXTERN int XNextEvent(Display *d, XEvent *x);
+/* 53 */
+EXTERN int XPutBackEvent(Display *d, XEvent *x);
+/* 54 */
+EXTERN int XQueryColors(Display *d, Colormap c, XColor *x,
+ int i);
+/* 55 */
+EXTERN Bool XQueryPointer(Display *d, Window w1, Window *w2,
+ Window *w3, int *i1, int *i2, int *i3,
+ int *i4, unsigned int *ui);
+/* 56 */
+EXTERN Status XQueryTree(Display *d, Window w1, Window *w2,
+ Window *w3, Window **w4, unsigned int *ui);
+/* 57 */
+EXTERN int XRaiseWindow(Display *d, Window w);
+/* 58 */
+EXTERN int XRefreshKeyboardMapping(XMappingEvent *x);
+/* 59 */
+EXTERN int XResizeWindow(Display *d, Window w, unsigned int ui1,
+ unsigned int ui2);
+/* 60 */
+EXTERN int XSelectInput(Display *d, Window w, long l);
+/* 61 */
+EXTERN Status XSendEvent(Display *d, Window w, Bool b, long l,
+ XEvent *x);
+/* 62 */
+EXTERN int XSetCommand(Display *d, Window w, char **c, int i);
+/* 63 */
+EXTERN int XSetIconName(Display *d, Window w, _Xconst char *c);
+/* 64 */
+EXTERN int XSetInputFocus(Display *d, Window w, int i, Time t);
+/* 65 */
+EXTERN int XSetSelectionOwner(Display *d, Atom a, Window w,
+ Time t);
+/* 66 */
+EXTERN int XSetWindowBackground(Display *d, Window w,
+ unsigned long ul);
+/* 67 */
+EXTERN int XSetWindowBackgroundPixmap(Display *d, Window w,
+ Pixmap p);
+/* 68 */
+EXTERN int XSetWindowBorder(Display *d, Window w,
+ unsigned long ul);
+/* 69 */
+EXTERN int XSetWindowBorderPixmap(Display *d, Window w,
+ Pixmap p);
+/* 70 */
+EXTERN int XSetWindowBorderWidth(Display *d, Window w,
+ unsigned int ui);
+/* 71 */
+EXTERN int XSetWindowColormap(Display *d, Window w, Colormap c);
+/* 72 */
+EXTERN Bool XTranslateCoordinates(Display *d, Window w1,
+ Window w2, int i1, int i2, int *i3, int *i4,
+ Window *w3);
+/* 73 */
+EXTERN int XUngrabKeyboard(Display *d, Time t);
+/* 74 */
+EXTERN int XUngrabPointer(Display *d, Time t);
+/* 75 */
+EXTERN int XUnmapWindow(Display *d, Window w);
+/* 76 */
+EXTERN int XWindowEvent(Display *d, Window w, long l, XEvent *x);
+/* 77 */
+EXTERN void XDestroyIC(XIC x);
+/* 78 */
+EXTERN Bool XFilterEvent(XEvent *x, Window w);
+/* 79 */
+EXTERN int XmbLookupString(XIC xi, XKeyPressedEvent *xk,
+ char *c, int i, KeySym *k, Status *s);
+/* 80 */
+EXTERN int TkPutImage(unsigned long *colors, int ncolors,
+ Display *display, Drawable d, GC gc,
+ XImage *image, int src_x, int src_y,
+ int dest_x, int dest_y, unsigned int width,
+ unsigned int height);
+/* Slot 81 is reserved */
+/* 82 */
+EXTERN Status XParseColor(Display *display, Colormap map,
+ _Xconst char *spec, XColor *colorPtr);
+/* 83 */
+EXTERN GC XCreateGC(Display *display, Drawable d,
+ unsigned long valuemask, XGCValues *values);
+/* 84 */
+EXTERN int XFreeGC(Display *display, GC gc);
+/* 85 */
+EXTERN Atom XInternAtom(Display *display,
+ _Xconst char *atom_name, Bool only_if_exists);
+/* 86 */
+EXTERN int XSetBackground(Display *display, GC gc,
+ unsigned long foreground);
+/* 87 */
+EXTERN int XSetForeground(Display *display, GC gc,
+ unsigned long foreground);
+/* 88 */
+EXTERN int XSetClipMask(Display *display, GC gc, Pixmap pixmap);
+/* 89 */
+EXTERN int XSetClipOrigin(Display *display, GC gc,
+ int clip_x_origin, int clip_y_origin);
+/* 90 */
+EXTERN int XSetTSOrigin(Display *display, GC gc,
+ int ts_x_origin, int ts_y_origin);
+/* 91 */
+EXTERN int XChangeGC(Display *d, GC gc, unsigned long mask,
+ XGCValues *values);
+/* 92 */
+EXTERN int XSetFont(Display *display, GC gc, Font font);
+/* 93 */
+EXTERN int XSetArcMode(Display *display, GC gc, int arc_mode);
+/* 94 */
+EXTERN int XSetStipple(Display *display, GC gc, Pixmap stipple);
+/* 95 */
+EXTERN int XSetFillRule(Display *display, GC gc, int fill_rule);
+/* 96 */
+EXTERN int XSetFillStyle(Display *display, GC gc,
+ int fill_style);
+/* 97 */
+EXTERN int XSetFunction(Display *display, GC gc, int function);
+/* 98 */
+EXTERN int XSetLineAttributes(Display *display, GC gc,
+ unsigned int line_width, int line_style,
+ int cap_style, int join_style);
+/* 99 */
+EXTERN int _XInitImageFuncPtrs(XImage *image);
+/* 100 */
+EXTERN XIC XCreateIC(XIM xim, ...);
+/* 101 */
+EXTERN XVisualInfo * XGetVisualInfo(Display *display, long vinfo_mask,
+ XVisualInfo *vinfo_template,
+ int *nitems_return);
+/* 102 */
+EXTERN void XSetWMClientMachine(Display *display, Window w,
+ XTextProperty *text_prop);
+/* 103 */
+EXTERN Status XStringListToTextProperty(char **list, int count,
+ XTextProperty *text_prop_return);
+/* 104 */
+EXTERN int XDrawLine(Display *d, Drawable dr, GC g, int x1,
+ int y1, int x2, int y2);
+/* 105 */
+EXTERN int XWarpPointer(Display *d, Window s, Window dw, int sx,
+ int sy, unsigned int sw, unsigned int sh,
+ int dx, int dy);
+/* 106 */
+EXTERN int XFillRectangle(Display *display, Drawable d, GC gc,
+ int x, int y, unsigned int width,
+ unsigned int height);
+/* 107 */
+EXTERN int XFlush(Display *display);
+/* 108 */
+EXTERN int XGrabServer(Display *display);
+/* 109 */
+EXTERN int XUngrabServer(Display *display);
+/* 110 */
+EXTERN int XFree(void *data);
+/* 111 */
+EXTERN int XNoOp(Display *display);
+/* 112 */
+EXTERN XAfterFunction XSynchronize(Display *display, Bool onoff);
+/* 113 */
+EXTERN int XSync(Display *display, Bool discard);
+/* 114 */
+EXTERN VisualID XVisualIDFromVisual(Visual *visual);
+/* Slot 115 is reserved */
+/* Slot 116 is reserved */
+/* Slot 117 is reserved */
+/* Slot 118 is reserved */
+/* Slot 119 is reserved */
+/* 120 */
+EXTERN int XOffsetRegion(Region rgn, int dx, int dy);
+/* 121 */
+EXTERN int XUnionRegion(Region srca, Region srcb,
+ Region dr_return);
+/* 122 */
+EXTERN Window XCreateWindow(Display *display, Window parent, int x,
+ int y, unsigned int width,
+ unsigned int height,
+ unsigned int border_width, int depth,
+ unsigned int clazz, Visual *visual,
+ unsigned long value_mask,
+ XSetWindowAttributes *attributes);
+/* Slot 123 is reserved */
+/* Slot 124 is reserved */
+/* Slot 125 is reserved */
+/* Slot 126 is reserved */
+/* Slot 127 is reserved */
+/* Slot 128 is reserved */
+/* 129 */
+EXTERN int XLowerWindow(Display *d, Window w);
+/* 130 */
+EXTERN int XFillArcs(Display *d, Drawable dr, GC gc, XArc *a,
+ int n);
+/* 131 */
+EXTERN int XDrawArcs(Display *d, Drawable dr, GC gc, XArc *a,
+ int n);
+/* 132 */
+EXTERN int XDrawRectangles(Display *d, Drawable dr, GC gc,
+ XRectangle *r, int n);
+/* 133 */
+EXTERN int XDrawSegments(Display *d, Drawable dr, GC gc,
+ XSegment *s, int n);
+/* 134 */
+EXTERN int XDrawPoint(Display *d, Drawable dr, GC gc, int x,
+ int y);
+/* 135 */
+EXTERN int XDrawPoints(Display *d, Drawable dr, GC gc,
+ XPoint *p, int n, int m);
+/* 136 */
+EXTERN int XReparentWindow(Display *d, Window w, Window p,
+ int x, int y);
+/* 137 */
+EXTERN int XPutImage(Display *d, Drawable dr, GC gc, XImage *im,
+ int sx, int sy, int dx, int dy,
+ unsigned int w, unsigned int h);
+#endif /* WIN */
+#ifdef MAC_OSX_TK /* AQUA */
+/* 0 */
+EXTERN int XSetDashes(Display *display, GC gc, int dash_offset,
+ _Xconst char *dash_list, int n);
+/* 1 */
+EXTERN XModifierKeymap * XGetModifierMapping(Display *d);
+/* 2 */
+EXTERN XImage * XCreateImage(Display *d, Visual *v, unsigned int ui1,
+ int i1, int i2, char *cp, unsigned int ui2,
+ unsigned int ui3, int i3, int i4);
+/* 3 */
+EXTERN XImage * XGetImage(Display *d, Drawable dr, int i1, int i2,
+ unsigned int ui1, unsigned int ui2,
+ unsigned long ul, int i3);
+/* 4 */
+EXTERN char * XGetAtomName(Display *d, Atom a);
+/* 5 */
+EXTERN char * XKeysymToString(KeySym k);
+/* 6 */
+EXTERN Colormap XCreateColormap(Display *d, Window w, Visual *v,
+ int i);
+/* 7 */
+EXTERN GContext XGContextFromGC(GC g);
+/* 8 */
+EXTERN KeySym XKeycodeToKeysym(Display *d, KeyCode k, int i);
+/* 9 */
+EXTERN KeySym XStringToKeysym(_Xconst char *c);
+/* 10 */
+EXTERN Window XRootWindow(Display *d, int i);
+/* 11 */
+EXTERN XErrorHandler XSetErrorHandler(XErrorHandler x);
+/* 12 */
+EXTERN Status XAllocColor(Display *d, Colormap c, XColor *xp);
+/* 13 */
+EXTERN int XBell(Display *d, int i);
+/* 14 */
+EXTERN void XChangeProperty(Display *d, Window w, Atom a1,
+ Atom a2, int i1, int i2,
+ _Xconst unsigned char *c, int i3);
+/* 15 */
+EXTERN void XChangeWindowAttributes(Display *d, Window w,
+ unsigned long ul, XSetWindowAttributes *x);
+/* 16 */
+EXTERN void XConfigureWindow(Display *d, Window w,
+ unsigned int i, XWindowChanges *x);
+/* 17 */
+EXTERN void XCopyArea(Display *d, Drawable dr1, Drawable dr2,
+ GC g, int i1, int i2, unsigned int ui1,
+ unsigned int ui2, int i3, int i4);
+/* 18 */
+EXTERN void XCopyPlane(Display *d, Drawable dr1, Drawable dr2,
+ GC g, int i1, int i2, unsigned int ui1,
+ unsigned int ui2, int i3, int i4,
+ unsigned long ul);
+/* 19 */
+EXTERN Pixmap XCreateBitmapFromData(Display *display, Drawable d,
+ _Xconst char *data, unsigned int width,
+ unsigned int height);
+/* 20 */
+EXTERN int XDefineCursor(Display *d, Window w, Cursor c);
+/* 21 */
+EXTERN void XDestroyWindow(Display *d, Window w);
+/* 22 */
+EXTERN void XDrawArc(Display *d, Drawable dr, GC g, int i1,
+ int i2, unsigned int ui1, unsigned int ui2,
+ int i3, int i4);
+/* 23 */
+EXTERN int XDrawLines(Display *d, Drawable dr, GC g, XPoint *x,
+ int i1, int i2);
+/* 24 */
+EXTERN void XDrawRectangle(Display *d, Drawable dr, GC g, int i1,
+ int i2, unsigned int ui1, unsigned int ui2);
+/* 25 */
+EXTERN void XFillArc(Display *d, Drawable dr, GC g, int i1,
+ int i2, unsigned int ui1, unsigned int ui2,
+ int i3, int i4);
+/* 26 */
+EXTERN void XFillPolygon(Display *d, Drawable dr, GC g,
+ XPoint *x, int i1, int i2, int i3);
+/* 27 */
+EXTERN int XFillRectangles(Display *d, Drawable dr, GC g,
+ XRectangle *x, int i);
+/* 28 */
+EXTERN int XFreeColormap(Display *d, Colormap c);
+/* 29 */
+EXTERN int XFreeColors(Display *d, Colormap c,
+ unsigned long *ulp, int i, unsigned long ul);
+/* 30 */
+EXTERN int XFreeModifiermap(XModifierKeymap *x);
+/* 31 */
+EXTERN Status XGetGeometry(Display *d, Drawable dr, Window *w,
+ int *i1, int *i2, unsigned int *ui1,
+ unsigned int *ui2, unsigned int *ui3,
+ unsigned int *ui4);
+/* 32 */
+EXTERN int XGetWindowProperty(Display *d, Window w, Atom a1,
+ long l1, long l2, Bool b, Atom a2, Atom *ap,
+ int *ip, unsigned long *ulp1,
+ unsigned long *ulp2, unsigned char **cpp);
+/* 33 */
+EXTERN int XGrabKeyboard(Display *d, Window w, Bool b, int i1,
+ int i2, Time t);
+/* 34 */
+EXTERN int XGrabPointer(Display *d, Window w1, Bool b,
+ unsigned int ui, int i1, int i2, Window w2,
+ Cursor c, Time t);
+/* 35 */
+EXTERN KeyCode XKeysymToKeycode(Display *d, KeySym k);
+/* 36 */
+EXTERN void XMapWindow(Display *d, Window w);
+/* 37 */
+EXTERN void XMoveResizeWindow(Display *d, Window w, int i1,
+ int i2, unsigned int ui1, unsigned int ui2);
+/* 38 */
+EXTERN void XMoveWindow(Display *d, Window w, int i1, int i2);
+/* 39 */
+EXTERN Bool XQueryPointer(Display *d, Window w1, Window *w2,
+ Window *w3, int *i1, int *i2, int *i3,
+ int *i4, unsigned int *ui);
+/* 40 */
+EXTERN void XRaiseWindow(Display *d, Window w);
+/* 41 */
+EXTERN void XRefreshKeyboardMapping(XMappingEvent *x);
+/* 42 */
+EXTERN void XResizeWindow(Display *d, Window w, unsigned int ui1,
+ unsigned int ui2);
+/* 43 */
+EXTERN void XSelectInput(Display *d, Window w, long l);
+/* 44 */
+EXTERN Status XSendEvent(Display *d, Window w, Bool b, long l,
+ XEvent *x);
+/* 45 */
+EXTERN void XSetIconName(Display *d, Window w, _Xconst char *c);
+/* 46 */
+EXTERN void XSetInputFocus(Display *d, Window w, int i, Time t);
+/* 47 */
+EXTERN int XSetSelectionOwner(Display *d, Atom a, Window w,
+ Time t);
+/* 48 */
+EXTERN void XSetWindowBackground(Display *d, Window w,
+ unsigned long ul);
+/* 49 */
+EXTERN void XSetWindowBackgroundPixmap(Display *d, Window w,
+ Pixmap p);
+/* 50 */
+EXTERN void XSetWindowBorder(Display *d, Window w,
+ unsigned long ul);
+/* 51 */
+EXTERN void XSetWindowBorderPixmap(Display *d, Window w,
+ Pixmap p);
+/* 52 */
+EXTERN void XSetWindowBorderWidth(Display *d, Window w,
+ unsigned int ui);
+/* 53 */
+EXTERN void XSetWindowColormap(Display *d, Window w, Colormap c);
+/* 54 */
+EXTERN void XUngrabKeyboard(Display *d, Time t);
+/* 55 */
+EXTERN int XUngrabPointer(Display *d, Time t);
+/* 56 */
+EXTERN void XUnmapWindow(Display *d, Window w);
+/* 57 */
+EXTERN int TkPutImage(unsigned long *colors, int ncolors,
+ Display *display, Drawable d, GC gc,
+ XImage *image, int src_x, int src_y,
+ int dest_x, int dest_y, unsigned int width,
+ unsigned int height);
+/* 58 */
+EXTERN Status XParseColor(Display *display, Colormap map,
+ _Xconst char *spec, XColor *colorPtr);
+/* 59 */
+EXTERN GC XCreateGC(Display *display, Drawable d,
+ unsigned long valuemask, XGCValues *values);
+/* 60 */
+EXTERN int XFreeGC(Display *display, GC gc);
+/* 61 */
+EXTERN Atom XInternAtom(Display *display,
+ _Xconst char *atom_name, Bool only_if_exists);
+/* 62 */
+EXTERN int XSetBackground(Display *display, GC gc,
+ unsigned long foreground);
+/* 63 */
+EXTERN int XSetForeground(Display *display, GC gc,
+ unsigned long foreground);
+/* 64 */
+EXTERN int XSetClipMask(Display *display, GC gc, Pixmap pixmap);
+/* 65 */
+EXTERN int XSetClipOrigin(Display *display, GC gc,
+ int clip_x_origin, int clip_y_origin);
+/* 66 */
+EXTERN int XSetTSOrigin(Display *display, GC gc,
+ int ts_x_origin, int ts_y_origin);
+/* 67 */
+EXTERN int XChangeGC(Display *d, GC gc, unsigned long mask,
+ XGCValues *values);
+/* 68 */
+EXTERN int XSetFont(Display *display, GC gc, Font font);
+/* 69 */
+EXTERN int XSetArcMode(Display *display, GC gc, int arc_mode);
+/* 70 */
+EXTERN int XSetStipple(Display *display, GC gc, Pixmap stipple);
+/* 71 */
+EXTERN int XSetFillRule(Display *display, GC gc, int fill_rule);
+/* 72 */
+EXTERN int XSetFillStyle(Display *display, GC gc,
+ int fill_style);
+/* 73 */
+EXTERN int XSetFunction(Display *display, GC gc, int function);
+/* 74 */
+EXTERN int XSetLineAttributes(Display *display, GC gc,
+ unsigned int line_width, int line_style,
+ int cap_style, int join_style);
+/* 75 */
+EXTERN int _XInitImageFuncPtrs(XImage *image);
+/* 76 */
+EXTERN XIC XCreateIC(void);
+/* 77 */
+EXTERN XVisualInfo * XGetVisualInfo(Display *display, long vinfo_mask,
+ XVisualInfo *vinfo_template,
+ int *nitems_return);
+/* 78 */
+EXTERN void XSetWMClientMachine(Display *display, Window w,
+ XTextProperty *text_prop);
+/* 79 */
+EXTERN Status XStringListToTextProperty(char **list, int count,
+ XTextProperty *text_prop_return);
+/* 80 */
+EXTERN int XDrawSegments(Display *display, Drawable d, GC gc,
+ XSegment *segments, int nsegments);
+/* 81 */
+EXTERN void XForceScreenSaver(Display *display, int mode);
+/* 82 */
+EXTERN int XDrawLine(Display *d, Drawable dr, GC g, int x1,
+ int y1, int x2, int y2);
+/* 83 */
+EXTERN int XFillRectangle(Display *display, Drawable d, GC gc,
+ int x, int y, unsigned int width,
+ unsigned int height);
+/* 84 */
+EXTERN void XClearWindow(Display *d, Window w);
+/* 85 */
+EXTERN int XDrawPoint(Display *display, Drawable d, GC gc,
+ int x, int y);
+/* 86 */
+EXTERN int XDrawPoints(Display *display, Drawable d, GC gc,
+ XPoint *points, int npoints, int mode);
+/* 87 */
+EXTERN int 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);
+/* 88 */
+EXTERN void XQueryColor(Display *display, Colormap colormap,
+ XColor *def_in_out);
+/* 89 */
+EXTERN void XQueryColors(Display *display, Colormap colormap,
+ XColor *defs_in_out, int ncolors);
+/* 90 */
+EXTERN Status XQueryTree(Display *d, Window w1, Window *w2,
+ Window *w3, Window **w4, unsigned int *ui);
+/* 91 */
+EXTERN int XSync(Display *display, Bool flag);
+#endif /* AQUA */
+
+typedef struct TkIntXlibStubs {
+ int magic;
+ void *hooks;
+
+#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
+ int (*xSetDashes) (Display *display, GC gc, int dash_offset, _Xconst char *dash_list, int n); /* 0 */
+ XModifierKeymap * (*xGetModifierMapping) (Display *d); /* 1 */
+ XImage * (*xCreateImage) (Display *d, Visual *v, unsigned int ui1, int i1, int i2, char *cp, unsigned int ui2, unsigned int ui3, int i3, int i4); /* 2 */
+ XImage * (*xGetImage) (Display *d, Drawable dr, int i1, int i2, unsigned int ui1, unsigned int ui2, unsigned long ul, int i3); /* 3 */
+ char * (*xGetAtomName) (Display *d, Atom a); /* 4 */
+ char * (*xKeysymToString) (KeySym k); /* 5 */
+ Colormap (*xCreateColormap) (Display *d, Window w, Visual *v, int i); /* 6 */
+ Cursor (*xCreatePixmapCursor) (Display *d, Pixmap p1, Pixmap p2, XColor *x1, XColor *x2, unsigned int ui1, unsigned int ui2); /* 7 */
+ Cursor (*xCreateGlyphCursor) (Display *d, Font f1, Font f2, unsigned int ui1, unsigned int ui2, XColor _Xconst *x1, XColor _Xconst *x2); /* 8 */
+ GContext (*xGContextFromGC) (GC g); /* 9 */
+ XHostAddress * (*xListHosts) (Display *d, int *i, Bool *b); /* 10 */
+ KeySym (*xKeycodeToKeysym) (Display *d, unsigned int k, int i); /* 11 */
+ KeySym (*xStringToKeysym) (_Xconst char *c); /* 12 */
+ Window (*xRootWindow) (Display *d, int i); /* 13 */
+ XErrorHandler (*xSetErrorHandler) (XErrorHandler x); /* 14 */
+ Status (*xIconifyWindow) (Display *d, Window w, int i); /* 15 */
+ Status (*xWithdrawWindow) (Display *d, Window w, int i); /* 16 */
+ Status (*xGetWMColormapWindows) (Display *d, Window w, Window **wpp, int *ip); /* 17 */
+ Status (*xAllocColor) (Display *d, Colormap c, XColor *xp); /* 18 */
+ int (*xBell) (Display *d, int i); /* 19 */
+ int (*xChangeProperty) (Display *d, Window w, Atom a1, Atom a2, int i1, int i2, _Xconst unsigned char *c, int i3); /* 20 */
+ int (*xChangeWindowAttributes) (Display *d, Window w, unsigned long ul, XSetWindowAttributes *x); /* 21 */
+ int (*xClearWindow) (Display *d, Window w); /* 22 */
+ int (*xConfigureWindow) (Display *d, Window w, unsigned int i, XWindowChanges *x); /* 23 */
+ int (*xCopyArea) (Display *d, Drawable dr1, Drawable dr2, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4); /* 24 */
+ int (*xCopyPlane) (Display *d, Drawable dr1, Drawable dr2, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4, unsigned long ul); /* 25 */
+ Pixmap (*xCreateBitmapFromData) (Display *display, Drawable d, _Xconst char *data, unsigned int width, unsigned int height); /* 26 */
+ int (*xDefineCursor) (Display *d, Window w, Cursor c); /* 27 */
+ int (*xDeleteProperty) (Display *d, Window w, Atom a); /* 28 */
+ int (*xDestroyWindow) (Display *d, Window w); /* 29 */
+ int (*xDrawArc) (Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4); /* 30 */
+ int (*xDrawLines) (Display *d, Drawable dr, GC g, XPoint *x, int i1, int i2); /* 31 */
+ int (*xDrawRectangle) (Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2); /* 32 */
+ int (*xFillArc) (Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4); /* 33 */
+ int (*xFillPolygon) (Display *d, Drawable dr, GC g, XPoint *x, int i1, int i2, int i3); /* 34 */
+ int (*xFillRectangles) (Display *d, Drawable dr, GC g, XRectangle *x, int i); /* 35 */
+ int (*xForceScreenSaver) (Display *d, int i); /* 36 */
+ int (*xFreeColormap) (Display *d, Colormap c); /* 37 */
+ int (*xFreeColors) (Display *d, Colormap c, unsigned long *ulp, int i, unsigned long ul); /* 38 */
+ int (*xFreeCursor) (Display *d, Cursor c); /* 39 */
+ int (*xFreeModifiermap) (XModifierKeymap *x); /* 40 */
+ Status (*xGetGeometry) (Display *d, Drawable dr, Window *w, int *i1, int *i2, unsigned int *ui1, unsigned int *ui2, unsigned int *ui3, unsigned int *ui4); /* 41 */
+ int (*xGetInputFocus) (Display *d, Window *w, int *i); /* 42 */
+ int (*xGetWindowProperty) (Display *d, Window w, Atom a1, long l1, long l2, Bool b, Atom a2, Atom *ap, int *ip, unsigned long *ulp1, unsigned long *ulp2, unsigned char **cpp); /* 43 */
+ Status (*xGetWindowAttributes) (Display *d, Window w, XWindowAttributes *x); /* 44 */
+ int (*xGrabKeyboard) (Display *d, Window w, Bool b, int i1, int i2, Time t); /* 45 */
+ int (*xGrabPointer) (Display *d, Window w1, Bool b, unsigned int ui, int i1, int i2, Window w2, Cursor c, Time t); /* 46 */
+ KeyCode (*xKeysymToKeycode) (Display *d, KeySym k); /* 47 */
+ Status (*xLookupColor) (Display *d, Colormap c1, _Xconst char *c2, XColor *x1, XColor *x2); /* 48 */
+ int (*xMapWindow) (Display *d, Window w); /* 49 */
+ int (*xMoveResizeWindow) (Display *d, Window w, int i1, int i2, unsigned int ui1, unsigned int ui2); /* 50 */
+ int (*xMoveWindow) (Display *d, Window w, int i1, int i2); /* 51 */
+ int (*xNextEvent) (Display *d, XEvent *x); /* 52 */
+ int (*xPutBackEvent) (Display *d, XEvent *x); /* 53 */
+ int (*xQueryColors) (Display *d, Colormap c, XColor *x, int i); /* 54 */
+ Bool (*xQueryPointer) (Display *d, Window w1, Window *w2, Window *w3, int *i1, int *i2, int *i3, int *i4, unsigned int *ui); /* 55 */
+ Status (*xQueryTree) (Display *d, Window w1, Window *w2, Window *w3, Window **w4, unsigned int *ui); /* 56 */
+ int (*xRaiseWindow) (Display *d, Window w); /* 57 */
+ int (*xRefreshKeyboardMapping) (XMappingEvent *x); /* 58 */
+ int (*xResizeWindow) (Display *d, Window w, unsigned int ui1, unsigned int ui2); /* 59 */
+ int (*xSelectInput) (Display *d, Window w, long l); /* 60 */
+ Status (*xSendEvent) (Display *d, Window w, Bool b, long l, XEvent *x); /* 61 */
+ int (*xSetCommand) (Display *d, Window w, char **c, int i); /* 62 */
+ int (*xSetIconName) (Display *d, Window w, _Xconst char *c); /* 63 */
+ int (*xSetInputFocus) (Display *d, Window w, int i, Time t); /* 64 */
+ int (*xSetSelectionOwner) (Display *d, Atom a, Window w, Time t); /* 65 */
+ int (*xSetWindowBackground) (Display *d, Window w, unsigned long ul); /* 66 */
+ int (*xSetWindowBackgroundPixmap) (Display *d, Window w, Pixmap p); /* 67 */
+ int (*xSetWindowBorder) (Display *d, Window w, unsigned long ul); /* 68 */
+ int (*xSetWindowBorderPixmap) (Display *d, Window w, Pixmap p); /* 69 */
+ int (*xSetWindowBorderWidth) (Display *d, Window w, unsigned int ui); /* 70 */
+ int (*xSetWindowColormap) (Display *d, Window w, Colormap c); /* 71 */
+ Bool (*xTranslateCoordinates) (Display *d, Window w1, Window w2, int i1, int i2, int *i3, int *i4, Window *w3); /* 72 */
+ int (*xUngrabKeyboard) (Display *d, Time t); /* 73 */
+ int (*xUngrabPointer) (Display *d, Time t); /* 74 */
+ int (*xUnmapWindow) (Display *d, Window w); /* 75 */
+ int (*xWindowEvent) (Display *d, Window w, long l, XEvent *x); /* 76 */
+ void (*xDestroyIC) (XIC x); /* 77 */
+ Bool (*xFilterEvent) (XEvent *x, Window w); /* 78 */
+ int (*xmbLookupString) (XIC xi, XKeyPressedEvent *xk, char *c, int i, KeySym *k, Status *s); /* 79 */
+ int (*tkPutImage) (unsigned long *colors, int ncolors, Display *display, Drawable d, GC gc, XImage *image, int src_x, int src_y, int dest_x, int dest_y, unsigned int width, unsigned int height); /* 80 */
+ void (*reserved81)(void);
+ Status (*xParseColor) (Display *display, Colormap map, _Xconst char *spec, XColor *colorPtr); /* 82 */
+ GC (*xCreateGC) (Display *display, Drawable d, unsigned long valuemask, XGCValues *values); /* 83 */
+ int (*xFreeGC) (Display *display, GC gc); /* 84 */
+ Atom (*xInternAtom) (Display *display, _Xconst char *atom_name, Bool only_if_exists); /* 85 */
+ int (*xSetBackground) (Display *display, GC gc, unsigned long foreground); /* 86 */
+ int (*xSetForeground) (Display *display, GC gc, unsigned long foreground); /* 87 */
+ int (*xSetClipMask) (Display *display, GC gc, Pixmap pixmap); /* 88 */
+ int (*xSetClipOrigin) (Display *display, GC gc, int clip_x_origin, int clip_y_origin); /* 89 */
+ int (*xSetTSOrigin) (Display *display, GC gc, int ts_x_origin, int ts_y_origin); /* 90 */
+ int (*xChangeGC) (Display *d, GC gc, unsigned long mask, XGCValues *values); /* 91 */
+ int (*xSetFont) (Display *display, GC gc, Font font); /* 92 */
+ int (*xSetArcMode) (Display *display, GC gc, int arc_mode); /* 93 */
+ int (*xSetStipple) (Display *display, GC gc, Pixmap stipple); /* 94 */
+ int (*xSetFillRule) (Display *display, GC gc, int fill_rule); /* 95 */
+ int (*xSetFillStyle) (Display *display, GC gc, int fill_style); /* 96 */
+ int (*xSetFunction) (Display *display, GC gc, int function); /* 97 */
+ int (*xSetLineAttributes) (Display *display, GC gc, unsigned int line_width, int line_style, int cap_style, int join_style); /* 98 */
+ int (*_XInitImageFuncPtrs) (XImage *image); /* 99 */
+ XIC (*xCreateIC) (XIM xim, ...); /* 100 */
+ XVisualInfo * (*xGetVisualInfo) (Display *display, long vinfo_mask, XVisualInfo *vinfo_template, int *nitems_return); /* 101 */
+ void (*xSetWMClientMachine) (Display *display, Window w, XTextProperty *text_prop); /* 102 */
+ Status (*xStringListToTextProperty) (char **list, int count, XTextProperty *text_prop_return); /* 103 */
+ int (*xDrawLine) (Display *d, Drawable dr, GC g, int x1, int y1, int x2, int y2); /* 104 */
+ int (*xWarpPointer) (Display *d, Window s, Window dw, int sx, int sy, unsigned int sw, unsigned int sh, int dx, int dy); /* 105 */
+ int (*xFillRectangle) (Display *display, Drawable d, GC gc, int x, int y, unsigned int width, unsigned int height); /* 106 */
+ int (*xFlush) (Display *display); /* 107 */
+ int (*xGrabServer) (Display *display); /* 108 */
+ int (*xUngrabServer) (Display *display); /* 109 */
+ int (*xFree) (void *data); /* 110 */
+ int (*xNoOp) (Display *display); /* 111 */
+ XAfterFunction (*xSynchronize) (Display *display, Bool onoff); /* 112 */
+ int (*xSync) (Display *display, Bool discard); /* 113 */
+ VisualID (*xVisualIDFromVisual) (Visual *visual); /* 114 */
+ void (*reserved115)(void);
+ void (*reserved116)(void);
+ void (*reserved117)(void);
+ void (*reserved118)(void);
+ void (*reserved119)(void);
+ int (*xOffsetRegion) (Region rgn, int dx, int dy); /* 120 */
+ int (*xUnionRegion) (Region srca, Region srcb, Region dr_return); /* 121 */
+ Window (*xCreateWindow) (Display *display, Window parent, int x, int y, unsigned int width, unsigned int height, unsigned int border_width, int depth, unsigned int clazz, Visual *visual, unsigned long value_mask, XSetWindowAttributes *attributes); /* 122 */
+ void (*reserved123)(void);
+ void (*reserved124)(void);
+ void (*reserved125)(void);
+ void (*reserved126)(void);
+ void (*reserved127)(void);
+ void (*reserved128)(void);
+ int (*xLowerWindow) (Display *d, Window w); /* 129 */
+ int (*xFillArcs) (Display *d, Drawable dr, GC gc, XArc *a, int n); /* 130 */
+ int (*xDrawArcs) (Display *d, Drawable dr, GC gc, XArc *a, int n); /* 131 */
+ int (*xDrawRectangles) (Display *d, Drawable dr, GC gc, XRectangle *r, int n); /* 132 */
+ int (*xDrawSegments) (Display *d, Drawable dr, GC gc, XSegment *s, int n); /* 133 */
+ int (*xDrawPoint) (Display *d, Drawable dr, GC gc, int x, int y); /* 134 */
+ int (*xDrawPoints) (Display *d, Drawable dr, GC gc, XPoint *p, int n, int m); /* 135 */
+ int (*xReparentWindow) (Display *d, Window w, Window p, int x, int y); /* 136 */
+ int (*xPutImage) (Display *d, Drawable dr, GC gc, XImage *im, int sx, int sy, int dx, int dy, unsigned int w, unsigned int h); /* 137 */
+#endif /* WIN */
+#ifdef MAC_OSX_TK /* AQUA */
+ int (*xSetDashes) (Display *display, GC gc, int dash_offset, _Xconst char *dash_list, int n); /* 0 */
+ XModifierKeymap * (*xGetModifierMapping) (Display *d); /* 1 */
+ XImage * (*xCreateImage) (Display *d, Visual *v, unsigned int ui1, int i1, int i2, char *cp, unsigned int ui2, unsigned int ui3, int i3, int i4); /* 2 */
+ XImage * (*xGetImage) (Display *d, Drawable dr, int i1, int i2, unsigned int ui1, unsigned int ui2, unsigned long ul, int i3); /* 3 */
+ char * (*xGetAtomName) (Display *d, Atom a); /* 4 */
+ char * (*xKeysymToString) (KeySym k); /* 5 */
+ Colormap (*xCreateColormap) (Display *d, Window w, Visual *v, int i); /* 6 */
+ GContext (*xGContextFromGC) (GC g); /* 7 */
+ KeySym (*xKeycodeToKeysym) (Display *d, KeyCode k, int i); /* 8 */
+ KeySym (*xStringToKeysym) (_Xconst char *c); /* 9 */
+ Window (*xRootWindow) (Display *d, int i); /* 10 */
+ XErrorHandler (*xSetErrorHandler) (XErrorHandler x); /* 11 */
+ Status (*xAllocColor) (Display *d, Colormap c, XColor *xp); /* 12 */
+ int (*xBell) (Display *d, int i); /* 13 */
+ void (*xChangeProperty) (Display *d, Window w, Atom a1, Atom a2, int i1, int i2, _Xconst unsigned char *c, int i3); /* 14 */
+ void (*xChangeWindowAttributes) (Display *d, Window w, unsigned long ul, XSetWindowAttributes *x); /* 15 */
+ void (*xConfigureWindow) (Display *d, Window w, unsigned int i, XWindowChanges *x); /* 16 */
+ void (*xCopyArea) (Display *d, Drawable dr1, Drawable dr2, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4); /* 17 */
+ void (*xCopyPlane) (Display *d, Drawable dr1, Drawable dr2, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4, unsigned long ul); /* 18 */
+ Pixmap (*xCreateBitmapFromData) (Display *display, Drawable d, _Xconst char *data, unsigned int width, unsigned int height); /* 19 */
+ int (*xDefineCursor) (Display *d, Window w, Cursor c); /* 20 */
+ void (*xDestroyWindow) (Display *d, Window w); /* 21 */
+ void (*xDrawArc) (Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4); /* 22 */
+ int (*xDrawLines) (Display *d, Drawable dr, GC g, XPoint *x, int i1, int i2); /* 23 */
+ void (*xDrawRectangle) (Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2); /* 24 */
+ void (*xFillArc) (Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4); /* 25 */
+ void (*xFillPolygon) (Display *d, Drawable dr, GC g, XPoint *x, int i1, int i2, int i3); /* 26 */
+ int (*xFillRectangles) (Display *d, Drawable dr, GC g, XRectangle *x, int i); /* 27 */
+ int (*xFreeColormap) (Display *d, Colormap c); /* 28 */
+ int (*xFreeColors) (Display *d, Colormap c, unsigned long *ulp, int i, unsigned long ul); /* 29 */
+ int (*xFreeModifiermap) (XModifierKeymap *x); /* 30 */
+ Status (*xGetGeometry) (Display *d, Drawable dr, Window *w, int *i1, int *i2, unsigned int *ui1, unsigned int *ui2, unsigned int *ui3, unsigned int *ui4); /* 31 */
+ int (*xGetWindowProperty) (Display *d, Window w, Atom a1, long l1, long l2, Bool b, Atom a2, Atom *ap, int *ip, unsigned long *ulp1, unsigned long *ulp2, unsigned char **cpp); /* 32 */
+ int (*xGrabKeyboard) (Display *d, Window w, Bool b, int i1, int i2, Time t); /* 33 */
+ int (*xGrabPointer) (Display *d, Window w1, Bool b, unsigned int ui, int i1, int i2, Window w2, Cursor c, Time t); /* 34 */
+ KeyCode (*xKeysymToKeycode) (Display *d, KeySym k); /* 35 */
+ void (*xMapWindow) (Display *d, Window w); /* 36 */
+ void (*xMoveResizeWindow) (Display *d, Window w, int i1, int i2, unsigned int ui1, unsigned int ui2); /* 37 */
+ void (*xMoveWindow) (Display *d, Window w, int i1, int i2); /* 38 */
+ Bool (*xQueryPointer) (Display *d, Window w1, Window *w2, Window *w3, int *i1, int *i2, int *i3, int *i4, unsigned int *ui); /* 39 */
+ void (*xRaiseWindow) (Display *d, Window w); /* 40 */
+ void (*xRefreshKeyboardMapping) (XMappingEvent *x); /* 41 */
+ void (*xResizeWindow) (Display *d, Window w, unsigned int ui1, unsigned int ui2); /* 42 */
+ void (*xSelectInput) (Display *d, Window w, long l); /* 43 */
+ Status (*xSendEvent) (Display *d, Window w, Bool b, long l, XEvent *x); /* 44 */
+ void (*xSetIconName) (Display *d, Window w, _Xconst char *c); /* 45 */
+ void (*xSetInputFocus) (Display *d, Window w, int i, Time t); /* 46 */
+ int (*xSetSelectionOwner) (Display *d, Atom a, Window w, Time t); /* 47 */
+ void (*xSetWindowBackground) (Display *d, Window w, unsigned long ul); /* 48 */
+ void (*xSetWindowBackgroundPixmap) (Display *d, Window w, Pixmap p); /* 49 */
+ void (*xSetWindowBorder) (Display *d, Window w, unsigned long ul); /* 50 */
+ void (*xSetWindowBorderPixmap) (Display *d, Window w, Pixmap p); /* 51 */
+ void (*xSetWindowBorderWidth) (Display *d, Window w, unsigned int ui); /* 52 */
+ void (*xSetWindowColormap) (Display *d, Window w, Colormap c); /* 53 */
+ void (*xUngrabKeyboard) (Display *d, Time t); /* 54 */
+ int (*xUngrabPointer) (Display *d, Time t); /* 55 */
+ void (*xUnmapWindow) (Display *d, Window w); /* 56 */
+ int (*tkPutImage) (unsigned long *colors, int ncolors, Display *display, Drawable d, GC gc, XImage *image, int src_x, int src_y, int dest_x, int dest_y, unsigned int width, unsigned int height); /* 57 */
+ Status (*xParseColor) (Display *display, Colormap map, _Xconst char *spec, XColor *colorPtr); /* 58 */
+ GC (*xCreateGC) (Display *display, Drawable d, unsigned long valuemask, XGCValues *values); /* 59 */
+ int (*xFreeGC) (Display *display, GC gc); /* 60 */
+ Atom (*xInternAtom) (Display *display, _Xconst char *atom_name, Bool only_if_exists); /* 61 */
+ int (*xSetBackground) (Display *display, GC gc, unsigned long foreground); /* 62 */
+ int (*xSetForeground) (Display *display, GC gc, unsigned long foreground); /* 63 */
+ int (*xSetClipMask) (Display *display, GC gc, Pixmap pixmap); /* 64 */
+ int (*xSetClipOrigin) (Display *display, GC gc, int clip_x_origin, int clip_y_origin); /* 65 */
+ int (*xSetTSOrigin) (Display *display, GC gc, int ts_x_origin, int ts_y_origin); /* 66 */
+ int (*xChangeGC) (Display *d, GC gc, unsigned long mask, XGCValues *values); /* 67 */
+ int (*xSetFont) (Display *display, GC gc, Font font); /* 68 */
+ int (*xSetArcMode) (Display *display, GC gc, int arc_mode); /* 69 */
+ int (*xSetStipple) (Display *display, GC gc, Pixmap stipple); /* 70 */
+ int (*xSetFillRule) (Display *display, GC gc, int fill_rule); /* 71 */
+ int (*xSetFillStyle) (Display *display, GC gc, int fill_style); /* 72 */
+ int (*xSetFunction) (Display *display, GC gc, int function); /* 73 */
+ int (*xSetLineAttributes) (Display *display, GC gc, unsigned int line_width, int line_style, int cap_style, int join_style); /* 74 */
+ int (*_XInitImageFuncPtrs) (XImage *image); /* 75 */
+ XIC (*xCreateIC) (void); /* 76 */
+ XVisualInfo * (*xGetVisualInfo) (Display *display, long vinfo_mask, XVisualInfo *vinfo_template, int *nitems_return); /* 77 */
+ void (*xSetWMClientMachine) (Display *display, Window w, XTextProperty *text_prop); /* 78 */
+ Status (*xStringListToTextProperty) (char **list, int count, XTextProperty *text_prop_return); /* 79 */
+ int (*xDrawSegments) (Display *display, Drawable d, GC gc, XSegment *segments, int nsegments); /* 80 */
+ void (*xForceScreenSaver) (Display *display, int mode); /* 81 */
+ int (*xDrawLine) (Display *d, Drawable dr, GC g, int x1, int y1, int x2, int y2); /* 82 */
+ int (*xFillRectangle) (Display *display, Drawable d, GC gc, int x, int y, unsigned int width, unsigned int height); /* 83 */
+ void (*xClearWindow) (Display *d, Window w); /* 84 */
+ int (*xDrawPoint) (Display *display, Drawable d, GC gc, int x, int y); /* 85 */
+ int (*xDrawPoints) (Display *display, Drawable d, GC gc, XPoint *points, int npoints, int mode); /* 86 */
+ int (*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); /* 87 */
+ void (*xQueryColor) (Display *display, Colormap colormap, XColor *def_in_out); /* 88 */
+ void (*xQueryColors) (Display *display, Colormap colormap, XColor *defs_in_out, int ncolors); /* 89 */
+ Status (*xQueryTree) (Display *d, Window w1, Window *w2, Window *w3, Window **w4, unsigned int *ui); /* 90 */
+ int (*xSync) (Display *display, Bool flag); /* 91 */
+#endif /* AQUA */
+} TkIntXlibStubs;
+
+extern const TkIntXlibStubs *tkIntXlibStubsPtr;
+
+#ifdef __cplusplus
+}
+#endif
+
+#if defined(USE_TK_STUBS)
+
+/*
+ * Inline function declarations:
+ */
+
+#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
+#define XSetDashes \
+ (tkIntXlibStubsPtr->xSetDashes) /* 0 */
+#define XGetModifierMapping \
+ (tkIntXlibStubsPtr->xGetModifierMapping) /* 1 */
+#define XCreateImage \
+ (tkIntXlibStubsPtr->xCreateImage) /* 2 */
+#define XGetImage \
+ (tkIntXlibStubsPtr->xGetImage) /* 3 */
+#define XGetAtomName \
+ (tkIntXlibStubsPtr->xGetAtomName) /* 4 */
+#define XKeysymToString \
+ (tkIntXlibStubsPtr->xKeysymToString) /* 5 */
+#define XCreateColormap \
+ (tkIntXlibStubsPtr->xCreateColormap) /* 6 */
+#define XCreatePixmapCursor \
+ (tkIntXlibStubsPtr->xCreatePixmapCursor) /* 7 */
+#define XCreateGlyphCursor \
+ (tkIntXlibStubsPtr->xCreateGlyphCursor) /* 8 */
+#define XGContextFromGC \
+ (tkIntXlibStubsPtr->xGContextFromGC) /* 9 */
+#define XListHosts \
+ (tkIntXlibStubsPtr->xListHosts) /* 10 */
+#define XKeycodeToKeysym \
+ (tkIntXlibStubsPtr->xKeycodeToKeysym) /* 11 */
+#define XStringToKeysym \
+ (tkIntXlibStubsPtr->xStringToKeysym) /* 12 */
+#define XRootWindow \
+ (tkIntXlibStubsPtr->xRootWindow) /* 13 */
+#define XSetErrorHandler \
+ (tkIntXlibStubsPtr->xSetErrorHandler) /* 14 */
+#define XIconifyWindow \
+ (tkIntXlibStubsPtr->xIconifyWindow) /* 15 */
+#define XWithdrawWindow \
+ (tkIntXlibStubsPtr->xWithdrawWindow) /* 16 */
+#define XGetWMColormapWindows \
+ (tkIntXlibStubsPtr->xGetWMColormapWindows) /* 17 */
+#define XAllocColor \
+ (tkIntXlibStubsPtr->xAllocColor) /* 18 */
+#define XBell \
+ (tkIntXlibStubsPtr->xBell) /* 19 */
+#define XChangeProperty \
+ (tkIntXlibStubsPtr->xChangeProperty) /* 20 */
+#define XChangeWindowAttributes \
+ (tkIntXlibStubsPtr->xChangeWindowAttributes) /* 21 */
+#define XClearWindow \
+ (tkIntXlibStubsPtr->xClearWindow) /* 22 */
+#define XConfigureWindow \
+ (tkIntXlibStubsPtr->xConfigureWindow) /* 23 */
+#define XCopyArea \
+ (tkIntXlibStubsPtr->xCopyArea) /* 24 */
+#define XCopyPlane \
+ (tkIntXlibStubsPtr->xCopyPlane) /* 25 */
+#define XCreateBitmapFromData \
+ (tkIntXlibStubsPtr->xCreateBitmapFromData) /* 26 */
+#define XDefineCursor \
+ (tkIntXlibStubsPtr->xDefineCursor) /* 27 */
+#define XDeleteProperty \
+ (tkIntXlibStubsPtr->xDeleteProperty) /* 28 */
+#define XDestroyWindow \
+ (tkIntXlibStubsPtr->xDestroyWindow) /* 29 */
+#define XDrawArc \
+ (tkIntXlibStubsPtr->xDrawArc) /* 30 */
+#define XDrawLines \
+ (tkIntXlibStubsPtr->xDrawLines) /* 31 */
+#define XDrawRectangle \
+ (tkIntXlibStubsPtr->xDrawRectangle) /* 32 */
+#define XFillArc \
+ (tkIntXlibStubsPtr->xFillArc) /* 33 */
+#define XFillPolygon \
+ (tkIntXlibStubsPtr->xFillPolygon) /* 34 */
+#define XFillRectangles \
+ (tkIntXlibStubsPtr->xFillRectangles) /* 35 */
+#define XForceScreenSaver \
+ (tkIntXlibStubsPtr->xForceScreenSaver) /* 36 */
+#define XFreeColormap \
+ (tkIntXlibStubsPtr->xFreeColormap) /* 37 */
+#define XFreeColors \
+ (tkIntXlibStubsPtr->xFreeColors) /* 38 */
+#define XFreeCursor \
+ (tkIntXlibStubsPtr->xFreeCursor) /* 39 */
+#define XFreeModifiermap \
+ (tkIntXlibStubsPtr->xFreeModifiermap) /* 40 */
+#define XGetGeometry \
+ (tkIntXlibStubsPtr->xGetGeometry) /* 41 */
+#define XGetInputFocus \
+ (tkIntXlibStubsPtr->xGetInputFocus) /* 42 */
+#define XGetWindowProperty \
+ (tkIntXlibStubsPtr->xGetWindowProperty) /* 43 */
+#define XGetWindowAttributes \
+ (tkIntXlibStubsPtr->xGetWindowAttributes) /* 44 */
+#define XGrabKeyboard \
+ (tkIntXlibStubsPtr->xGrabKeyboard) /* 45 */
+#define XGrabPointer \
+ (tkIntXlibStubsPtr->xGrabPointer) /* 46 */
+#define XKeysymToKeycode \
+ (tkIntXlibStubsPtr->xKeysymToKeycode) /* 47 */
+#define XLookupColor \
+ (tkIntXlibStubsPtr->xLookupColor) /* 48 */
+#define XMapWindow \
+ (tkIntXlibStubsPtr->xMapWindow) /* 49 */
+#define XMoveResizeWindow \
+ (tkIntXlibStubsPtr->xMoveResizeWindow) /* 50 */
+#define XMoveWindow \
+ (tkIntXlibStubsPtr->xMoveWindow) /* 51 */
+#define XNextEvent \
+ (tkIntXlibStubsPtr->xNextEvent) /* 52 */
+#define XPutBackEvent \
+ (tkIntXlibStubsPtr->xPutBackEvent) /* 53 */
+#define XQueryColors \
+ (tkIntXlibStubsPtr->xQueryColors) /* 54 */
+#define XQueryPointer \
+ (tkIntXlibStubsPtr->xQueryPointer) /* 55 */
+#define XQueryTree \
+ (tkIntXlibStubsPtr->xQueryTree) /* 56 */
+#define XRaiseWindow \
+ (tkIntXlibStubsPtr->xRaiseWindow) /* 57 */
+#define XRefreshKeyboardMapping \
+ (tkIntXlibStubsPtr->xRefreshKeyboardMapping) /* 58 */
+#define XResizeWindow \
+ (tkIntXlibStubsPtr->xResizeWindow) /* 59 */
+#define XSelectInput \
+ (tkIntXlibStubsPtr->xSelectInput) /* 60 */
+#define XSendEvent \
+ (tkIntXlibStubsPtr->xSendEvent) /* 61 */
+#define XSetCommand \
+ (tkIntXlibStubsPtr->xSetCommand) /* 62 */
+#define XSetIconName \
+ (tkIntXlibStubsPtr->xSetIconName) /* 63 */
+#define XSetInputFocus \
+ (tkIntXlibStubsPtr->xSetInputFocus) /* 64 */
+#define XSetSelectionOwner \
+ (tkIntXlibStubsPtr->xSetSelectionOwner) /* 65 */
+#define XSetWindowBackground \
+ (tkIntXlibStubsPtr->xSetWindowBackground) /* 66 */
+#define XSetWindowBackgroundPixmap \
+ (tkIntXlibStubsPtr->xSetWindowBackgroundPixmap) /* 67 */
+#define XSetWindowBorder \
+ (tkIntXlibStubsPtr->xSetWindowBorder) /* 68 */
+#define XSetWindowBorderPixmap \
+ (tkIntXlibStubsPtr->xSetWindowBorderPixmap) /* 69 */
+#define XSetWindowBorderWidth \
+ (tkIntXlibStubsPtr->xSetWindowBorderWidth) /* 70 */
+#define XSetWindowColormap \
+ (tkIntXlibStubsPtr->xSetWindowColormap) /* 71 */
+#define XTranslateCoordinates \
+ (tkIntXlibStubsPtr->xTranslateCoordinates) /* 72 */
+#define XUngrabKeyboard \
+ (tkIntXlibStubsPtr->xUngrabKeyboard) /* 73 */
+#define XUngrabPointer \
+ (tkIntXlibStubsPtr->xUngrabPointer) /* 74 */
+#define XUnmapWindow \
+ (tkIntXlibStubsPtr->xUnmapWindow) /* 75 */
+#define XWindowEvent \
+ (tkIntXlibStubsPtr->xWindowEvent) /* 76 */
+#define XDestroyIC \
+ (tkIntXlibStubsPtr->xDestroyIC) /* 77 */
+#define XFilterEvent \
+ (tkIntXlibStubsPtr->xFilterEvent) /* 78 */
+#define XmbLookupString \
+ (tkIntXlibStubsPtr->xmbLookupString) /* 79 */
+#define TkPutImage \
+ (tkIntXlibStubsPtr->tkPutImage) /* 80 */
+/* Slot 81 is reserved */
+#define XParseColor \
+ (tkIntXlibStubsPtr->xParseColor) /* 82 */
+#define XCreateGC \
+ (tkIntXlibStubsPtr->xCreateGC) /* 83 */
+#define XFreeGC \
+ (tkIntXlibStubsPtr->xFreeGC) /* 84 */
+#define XInternAtom \
+ (tkIntXlibStubsPtr->xInternAtom) /* 85 */
+#define XSetBackground \
+ (tkIntXlibStubsPtr->xSetBackground) /* 86 */
+#define XSetForeground \
+ (tkIntXlibStubsPtr->xSetForeground) /* 87 */
+#define XSetClipMask \
+ (tkIntXlibStubsPtr->xSetClipMask) /* 88 */
+#define XSetClipOrigin \
+ (tkIntXlibStubsPtr->xSetClipOrigin) /* 89 */
+#define XSetTSOrigin \
+ (tkIntXlibStubsPtr->xSetTSOrigin) /* 90 */
+#define XChangeGC \
+ (tkIntXlibStubsPtr->xChangeGC) /* 91 */
+#define XSetFont \
+ (tkIntXlibStubsPtr->xSetFont) /* 92 */
+#define XSetArcMode \
+ (tkIntXlibStubsPtr->xSetArcMode) /* 93 */
+#define XSetStipple \
+ (tkIntXlibStubsPtr->xSetStipple) /* 94 */
+#define XSetFillRule \
+ (tkIntXlibStubsPtr->xSetFillRule) /* 95 */
+#define XSetFillStyle \
+ (tkIntXlibStubsPtr->xSetFillStyle) /* 96 */
+#define XSetFunction \
+ (tkIntXlibStubsPtr->xSetFunction) /* 97 */
+#define XSetLineAttributes \
+ (tkIntXlibStubsPtr->xSetLineAttributes) /* 98 */
+#define _XInitImageFuncPtrs \
+ (tkIntXlibStubsPtr->_XInitImageFuncPtrs) /* 99 */
+#define XCreateIC \
+ (tkIntXlibStubsPtr->xCreateIC) /* 100 */
+#define XGetVisualInfo \
+ (tkIntXlibStubsPtr->xGetVisualInfo) /* 101 */
+#define XSetWMClientMachine \
+ (tkIntXlibStubsPtr->xSetWMClientMachine) /* 102 */
+#define XStringListToTextProperty \
+ (tkIntXlibStubsPtr->xStringListToTextProperty) /* 103 */
+#define XDrawLine \
+ (tkIntXlibStubsPtr->xDrawLine) /* 104 */
+#define XWarpPointer \
+ (tkIntXlibStubsPtr->xWarpPointer) /* 105 */
+#define XFillRectangle \
+ (tkIntXlibStubsPtr->xFillRectangle) /* 106 */
+#define XFlush \
+ (tkIntXlibStubsPtr->xFlush) /* 107 */
+#define XGrabServer \
+ (tkIntXlibStubsPtr->xGrabServer) /* 108 */
+#define XUngrabServer \
+ (tkIntXlibStubsPtr->xUngrabServer) /* 109 */
+#define XFree \
+ (tkIntXlibStubsPtr->xFree) /* 110 */
+#define XNoOp \
+ (tkIntXlibStubsPtr->xNoOp) /* 111 */
+#define XSynchronize \
+ (tkIntXlibStubsPtr->xSynchronize) /* 112 */
+#define XSync \
+ (tkIntXlibStubsPtr->xSync) /* 113 */
+#define XVisualIDFromVisual \
+ (tkIntXlibStubsPtr->xVisualIDFromVisual) /* 114 */
+/* Slot 115 is reserved */
+/* Slot 116 is reserved */
+/* Slot 117 is reserved */
+/* Slot 118 is reserved */
+/* Slot 119 is reserved */
+#define XOffsetRegion \
+ (tkIntXlibStubsPtr->xOffsetRegion) /* 120 */
+#define XUnionRegion \
+ (tkIntXlibStubsPtr->xUnionRegion) /* 121 */
+#define XCreateWindow \
+ (tkIntXlibStubsPtr->xCreateWindow) /* 122 */
+/* Slot 123 is reserved */
+/* Slot 124 is reserved */
+/* Slot 125 is reserved */
+/* Slot 126 is reserved */
+/* Slot 127 is reserved */
+/* Slot 128 is reserved */
+#define XLowerWindow \
+ (tkIntXlibStubsPtr->xLowerWindow) /* 129 */
+#define XFillArcs \
+ (tkIntXlibStubsPtr->xFillArcs) /* 130 */
+#define XDrawArcs \
+ (tkIntXlibStubsPtr->xDrawArcs) /* 131 */
+#define XDrawRectangles \
+ (tkIntXlibStubsPtr->xDrawRectangles) /* 132 */
+#define XDrawSegments \
+ (tkIntXlibStubsPtr->xDrawSegments) /* 133 */
+#define XDrawPoint \
+ (tkIntXlibStubsPtr->xDrawPoint) /* 134 */
+#define XDrawPoints \
+ (tkIntXlibStubsPtr->xDrawPoints) /* 135 */
+#define XReparentWindow \
+ (tkIntXlibStubsPtr->xReparentWindow) /* 136 */
+#define XPutImage \
+ (tkIntXlibStubsPtr->xPutImage) /* 137 */
+#endif /* WIN */
+#ifdef MAC_OSX_TK /* AQUA */
+#define XSetDashes \
+ (tkIntXlibStubsPtr->xSetDashes) /* 0 */
+#define XGetModifierMapping \
+ (tkIntXlibStubsPtr->xGetModifierMapping) /* 1 */
+#define XCreateImage \
+ (tkIntXlibStubsPtr->xCreateImage) /* 2 */
+#define XGetImage \
+ (tkIntXlibStubsPtr->xGetImage) /* 3 */
+#define XGetAtomName \
+ (tkIntXlibStubsPtr->xGetAtomName) /* 4 */
+#define XKeysymToString \
+ (tkIntXlibStubsPtr->xKeysymToString) /* 5 */
+#define XCreateColormap \
+ (tkIntXlibStubsPtr->xCreateColormap) /* 6 */
+#define XGContextFromGC \
+ (tkIntXlibStubsPtr->xGContextFromGC) /* 7 */
+#define XKeycodeToKeysym \
+ (tkIntXlibStubsPtr->xKeycodeToKeysym) /* 8 */
+#define XStringToKeysym \
+ (tkIntXlibStubsPtr->xStringToKeysym) /* 9 */
+#define XRootWindow \
+ (tkIntXlibStubsPtr->xRootWindow) /* 10 */
+#define XSetErrorHandler \
+ (tkIntXlibStubsPtr->xSetErrorHandler) /* 11 */
+#define XAllocColor \
+ (tkIntXlibStubsPtr->xAllocColor) /* 12 */
+#define XBell \
+ (tkIntXlibStubsPtr->xBell) /* 13 */
+#define XChangeProperty \
+ (tkIntXlibStubsPtr->xChangeProperty) /* 14 */
+#define XChangeWindowAttributes \
+ (tkIntXlibStubsPtr->xChangeWindowAttributes) /* 15 */
+#define XConfigureWindow \
+ (tkIntXlibStubsPtr->xConfigureWindow) /* 16 */
+#define XCopyArea \
+ (tkIntXlibStubsPtr->xCopyArea) /* 17 */
+#define XCopyPlane \
+ (tkIntXlibStubsPtr->xCopyPlane) /* 18 */
+#define XCreateBitmapFromData \
+ (tkIntXlibStubsPtr->xCreateBitmapFromData) /* 19 */
+#define XDefineCursor \
+ (tkIntXlibStubsPtr->xDefineCursor) /* 20 */
+#define XDestroyWindow \
+ (tkIntXlibStubsPtr->xDestroyWindow) /* 21 */
+#define XDrawArc \
+ (tkIntXlibStubsPtr->xDrawArc) /* 22 */
+#define XDrawLines \
+ (tkIntXlibStubsPtr->xDrawLines) /* 23 */
+#define XDrawRectangle \
+ (tkIntXlibStubsPtr->xDrawRectangle) /* 24 */
+#define XFillArc \
+ (tkIntXlibStubsPtr->xFillArc) /* 25 */
+#define XFillPolygon \
+ (tkIntXlibStubsPtr->xFillPolygon) /* 26 */
+#define XFillRectangles \
+ (tkIntXlibStubsPtr->xFillRectangles) /* 27 */
+#define XFreeColormap \
+ (tkIntXlibStubsPtr->xFreeColormap) /* 28 */
+#define XFreeColors \
+ (tkIntXlibStubsPtr->xFreeColors) /* 29 */
+#define XFreeModifiermap \
+ (tkIntXlibStubsPtr->xFreeModifiermap) /* 30 */
+#define XGetGeometry \
+ (tkIntXlibStubsPtr->xGetGeometry) /* 31 */
+#define XGetWindowProperty \
+ (tkIntXlibStubsPtr->xGetWindowProperty) /* 32 */
+#define XGrabKeyboard \
+ (tkIntXlibStubsPtr->xGrabKeyboard) /* 33 */
+#define XGrabPointer \
+ (tkIntXlibStubsPtr->xGrabPointer) /* 34 */
+#define XKeysymToKeycode \
+ (tkIntXlibStubsPtr->xKeysymToKeycode) /* 35 */
+#define XMapWindow \
+ (tkIntXlibStubsPtr->xMapWindow) /* 36 */
+#define XMoveResizeWindow \
+ (tkIntXlibStubsPtr->xMoveResizeWindow) /* 37 */
+#define XMoveWindow \
+ (tkIntXlibStubsPtr->xMoveWindow) /* 38 */
+#define XQueryPointer \
+ (tkIntXlibStubsPtr->xQueryPointer) /* 39 */
+#define XRaiseWindow \
+ (tkIntXlibStubsPtr->xRaiseWindow) /* 40 */
+#define XRefreshKeyboardMapping \
+ (tkIntXlibStubsPtr->xRefreshKeyboardMapping) /* 41 */
+#define XResizeWindow \
+ (tkIntXlibStubsPtr->xResizeWindow) /* 42 */
+#define XSelectInput \
+ (tkIntXlibStubsPtr->xSelectInput) /* 43 */
+#define XSendEvent \
+ (tkIntXlibStubsPtr->xSendEvent) /* 44 */
+#define XSetIconName \
+ (tkIntXlibStubsPtr->xSetIconName) /* 45 */
+#define XSetInputFocus \
+ (tkIntXlibStubsPtr->xSetInputFocus) /* 46 */
+#define XSetSelectionOwner \
+ (tkIntXlibStubsPtr->xSetSelectionOwner) /* 47 */
+#define XSetWindowBackground \
+ (tkIntXlibStubsPtr->xSetWindowBackground) /* 48 */
+#define XSetWindowBackgroundPixmap \
+ (tkIntXlibStubsPtr->xSetWindowBackgroundPixmap) /* 49 */
+#define XSetWindowBorder \
+ (tkIntXlibStubsPtr->xSetWindowBorder) /* 50 */
+#define XSetWindowBorderPixmap \
+ (tkIntXlibStubsPtr->xSetWindowBorderPixmap) /* 51 */
+#define XSetWindowBorderWidth \
+ (tkIntXlibStubsPtr->xSetWindowBorderWidth) /* 52 */
+#define XSetWindowColormap \
+ (tkIntXlibStubsPtr->xSetWindowColormap) /* 53 */
+#define XUngrabKeyboard \
+ (tkIntXlibStubsPtr->xUngrabKeyboard) /* 54 */
+#define XUngrabPointer \
+ (tkIntXlibStubsPtr->xUngrabPointer) /* 55 */
+#define XUnmapWindow \
+ (tkIntXlibStubsPtr->xUnmapWindow) /* 56 */
+#define TkPutImage \
+ (tkIntXlibStubsPtr->tkPutImage) /* 57 */
+#define XParseColor \
+ (tkIntXlibStubsPtr->xParseColor) /* 58 */
+#define XCreateGC \
+ (tkIntXlibStubsPtr->xCreateGC) /* 59 */
+#define XFreeGC \
+ (tkIntXlibStubsPtr->xFreeGC) /* 60 */
+#define XInternAtom \
+ (tkIntXlibStubsPtr->xInternAtom) /* 61 */
+#define XSetBackground \
+ (tkIntXlibStubsPtr->xSetBackground) /* 62 */
+#define XSetForeground \
+ (tkIntXlibStubsPtr->xSetForeground) /* 63 */
+#define XSetClipMask \
+ (tkIntXlibStubsPtr->xSetClipMask) /* 64 */
+#define XSetClipOrigin \
+ (tkIntXlibStubsPtr->xSetClipOrigin) /* 65 */
+#define XSetTSOrigin \
+ (tkIntXlibStubsPtr->xSetTSOrigin) /* 66 */
+#define XChangeGC \
+ (tkIntXlibStubsPtr->xChangeGC) /* 67 */
+#define XSetFont \
+ (tkIntXlibStubsPtr->xSetFont) /* 68 */
+#define XSetArcMode \
+ (tkIntXlibStubsPtr->xSetArcMode) /* 69 */
+#define XSetStipple \
+ (tkIntXlibStubsPtr->xSetStipple) /* 70 */
+#define XSetFillRule \
+ (tkIntXlibStubsPtr->xSetFillRule) /* 71 */
+#define XSetFillStyle \
+ (tkIntXlibStubsPtr->xSetFillStyle) /* 72 */
+#define XSetFunction \
+ (tkIntXlibStubsPtr->xSetFunction) /* 73 */
+#define XSetLineAttributes \
+ (tkIntXlibStubsPtr->xSetLineAttributes) /* 74 */
+#define _XInitImageFuncPtrs \
+ (tkIntXlibStubsPtr->_XInitImageFuncPtrs) /* 75 */
+#define XCreateIC \
+ (tkIntXlibStubsPtr->xCreateIC) /* 76 */
+#define XGetVisualInfo \
+ (tkIntXlibStubsPtr->xGetVisualInfo) /* 77 */
+#define XSetWMClientMachine \
+ (tkIntXlibStubsPtr->xSetWMClientMachine) /* 78 */
+#define XStringListToTextProperty \
+ (tkIntXlibStubsPtr->xStringListToTextProperty) /* 79 */
+#define XDrawSegments \
+ (tkIntXlibStubsPtr->xDrawSegments) /* 80 */
+#define XForceScreenSaver \
+ (tkIntXlibStubsPtr->xForceScreenSaver) /* 81 */
+#define XDrawLine \
+ (tkIntXlibStubsPtr->xDrawLine) /* 82 */
+#define XFillRectangle \
+ (tkIntXlibStubsPtr->xFillRectangle) /* 83 */
+#define XClearWindow \
+ (tkIntXlibStubsPtr->xClearWindow) /* 84 */
+#define XDrawPoint \
+ (tkIntXlibStubsPtr->xDrawPoint) /* 85 */
+#define XDrawPoints \
+ (tkIntXlibStubsPtr->xDrawPoints) /* 86 */
+#define XWarpPointer \
+ (tkIntXlibStubsPtr->xWarpPointer) /* 87 */
+#define XQueryColor \
+ (tkIntXlibStubsPtr->xQueryColor) /* 88 */
+#define XQueryColors \
+ (tkIntXlibStubsPtr->xQueryColors) /* 89 */
+#define XQueryTree \
+ (tkIntXlibStubsPtr->xQueryTree) /* 90 */
+#define XSync \
+ (tkIntXlibStubsPtr->xSync) /* 91 */
+#endif /* AQUA */
+
+#endif /* defined(USE_TK_STUBS) */
+
+/* !END!: Do not edit above this line. */
+
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLIMPORT
+
+#endif /* _TKINTXLIBDECLS */
diff --git a/tk8.6/generic/tkListbox.c b/tk8.6/generic/tkListbox.c
new file mode 100644
index 0000000..d92325f
--- /dev/null
+++ b/tk8.6/generic/tkListbox.c
@@ -0,0 +1,3670 @@
+/*
+ * tkListbox.c --
+ *
+ * This module implements listbox widgets for the Tk toolkit. A listbox
+ * displays a collection of strings, one per line, and provides scrolling
+ * and selection.
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "default.h"
+#include "tkInt.h"
+
+#ifdef _WIN32
+#include "tkWinInt.h"
+#endif
+
+typedef struct {
+ Tk_OptionTable listboxOptionTable;
+ /* Table defining configuration options
+ * available for the listbox. */
+ Tk_OptionTable itemAttrOptionTable;
+ /* Table defining configuration options
+ * available for listbox items. */
+} ListboxOptionTables;
+
+/*
+ * A data structure of the following type is kept for each listbox widget
+ * managed by this file:
+ */
+
+typedef struct {
+ Tk_Window tkwin; /* Window that embodies the listbox. NULL
+ * means that the window has been destroyed
+ * but the data structures haven't yet been
+ * cleaned up. */
+ Display *display; /* Display containing widget. Used, among
+ * other things, so that resources can be
+ * freed even after tkwin has gone away. */
+ Tcl_Interp *interp; /* Interpreter associated with listbox. */
+ Tcl_Command widgetCmd; /* Token for listbox's widget command. */
+ Tk_OptionTable optionTable; /* Table that defines configuration options
+ * available for this widget. */
+ Tk_OptionTable itemAttrOptionTable;
+ /* Table that defines configuration options
+ * available for listbox items. */
+ char *listVarName; /* List variable name */
+ Tcl_Obj *listObj; /* Pointer to the list object being used */
+ int nElements; /* Holds the current count of elements */
+ Tcl_HashTable *selection; /* Tracks selection */
+ Tcl_HashTable *itemAttrTable;
+ /* Tracks item attributes */
+
+ /*
+ * Information used when displaying widget:
+ */
+
+ Tk_3DBorder normalBorder; /* Used for drawing border around whole
+ * window, plus used for background. */
+ int borderWidth; /* Width of 3-D border around window. */
+ int relief; /* 3-D effect: TK_RELIEF_RAISED, etc. */
+ int highlightWidth; /* Width in pixels of highlight to draw around
+ * widget when it has the focus. <= 0 means
+ * don't draw a highlight. */
+ XColor *highlightBgColorPtr;
+ /* Color for drawing traversal highlight area
+ * when highlight is off. */
+ XColor *highlightColorPtr; /* Color for drawing traversal highlight. */
+ int inset; /* Total width of all borders, including
+ * traversal highlight and 3-D border.
+ * Indicates how much interior stuff must be
+ * offset from outside edges to leave room for
+ * borders. */
+ Tk_Font tkfont; /* Information about text font, or NULL. */
+ XColor *fgColorPtr; /* Text color in normal mode. */
+ XColor *dfgColorPtr; /* Text color in disabled mode. */
+ GC textGC; /* For drawing normal text. */
+ Tk_3DBorder selBorder; /* Borders and backgrounds for selected
+ * elements. */
+ int selBorderWidth; /* Width of border around selection. */
+ XColor *selFgColorPtr; /* Foreground color for selected elements. */
+ GC selTextGC; /* For drawing selected text. */
+ int width; /* Desired width of window, in characters. */
+ int height; /* Desired height of window, in lines. */
+ int lineHeight; /* Number of pixels allocated for each line in
+ * display. */
+ int topIndex; /* Index of top-most element visible in
+ * window. */
+ int fullLines; /* Number of lines that are completely
+ * visible in window. There may be one
+ * additional line at the bottom that is
+ * partially visible. */
+ int partialLine; /* 0 means that the window holds exactly
+ * fullLines lines. 1 means that there is one
+ * additional line that is partially
+ * visible. */
+ int setGrid; /* Non-zero means pass gridding information to
+ * window manager. */
+
+ /*
+ * Information to support horizontal scrolling:
+ */
+
+ int maxWidth; /* Width (in pixels) of widest string in
+ * listbox. */
+ int xScrollUnit; /* Number of pixels in one "unit" for
+ * horizontal scrolling (window scrolls
+ * horizontally in increments of this size).
+ * This is an average character size. */
+ int xOffset; /* The left edge of each string in the listbox
+ * is offset to the left by this many pixels
+ * (0 means no offset, positive means there is
+ * an offset). This is x scrolling information
+ * is not linked to justification. */
+
+ /*
+ * Information about what's selected or active, if any.
+ */
+
+ Tk_Uid selectMode; /* Selection style: single, browse, multiple,
+ * or extended. This value isn't used in C
+ * code, but the Tcl bindings use it. */
+ int numSelected; /* Number of elements currently selected. */
+ int selectAnchor; /* Fixed end of selection (i.e. element at
+ * which selection was started.) */
+ int exportSelection; /* Non-zero means tie internal listbox to X
+ * selection. */
+ int active; /* Index of "active" element (the one that has
+ * been selected by keyboard traversal). -1
+ * means none. */
+ int activeStyle; /* Style in which to draw the active element.
+ * One of: underline, none, dotbox */
+
+ /*
+ * Information for scanning:
+ */
+
+ int scanMarkX; /* X-position at which scan started (e.g.
+ * button was pressed here). */
+ int scanMarkY; /* Y-position at which scan started (e.g.
+ * button was pressed here). */
+ int scanMarkXOffset; /* Value of "xOffset" field when scan
+ * started. */
+ int scanMarkYIndex; /* Index of line that was at top of window
+ * when scan started. */
+
+ /*
+ * Miscellaneous information:
+ */
+
+ Tk_Cursor cursor; /* Current cursor for window, or None. */
+ char *takeFocus; /* Value of -takefocus option; not used in the
+ * C code, but used by keyboard traversal
+ * scripts. Malloc'ed, but may be NULL. */
+ char *yScrollCmd; /* Command prefix for communicating with
+ * vertical scrollbar. NULL means no command
+ * to issue. Malloc'ed. */
+ char *xScrollCmd; /* Command prefix for communicating with
+ * horizontal scrollbar. NULL means no command
+ * to issue. Malloc'ed. */
+ int state; /* Listbox state. */
+ Pixmap gray; /* Pixmap for displaying disabled text. */
+ int flags; /* Various flag bits: see below for
+ * definitions. */
+ Tk_Justify justify; /* Justification. */
+} Listbox;
+
+/*
+ * How to encode the keys for the hash tables used to store what items are
+ * selected and what the attributes are.
+ */
+
+#define KEY(i) ((char *) INT2PTR(i))
+
+/*
+ * ItemAttr structures are used to store item configuration information for
+ * the items in a listbox
+ */
+
+typedef struct {
+ Tk_3DBorder border; /* Used for drawing background around text */
+ Tk_3DBorder selBorder; /* Used for selected text */
+ XColor *fgColor; /* Text color in normal mode. */
+ XColor *selFgColor; /* Text color in selected mode. */
+} ItemAttr;
+
+/*
+ * Flag bits for listboxes:
+ *
+ * REDRAW_PENDING: Non-zero means a DoWhenIdle handler has
+ * already been queued to redraw this window.
+ * UPDATE_V_SCROLLBAR: Non-zero means vertical scrollbar needs to be
+ * updated.
+ * UPDATE_H_SCROLLBAR: Non-zero means horizontal scrollbar needs to
+ * be updated.
+ * GOT_FOCUS: Non-zero means this widget currently has the
+ * input focus.
+ * MAXWIDTH_IS_STALE: Stored maxWidth may be out-of-date.
+ * LISTBOX_DELETED: This listbox has been effectively destroyed.
+ */
+
+#define REDRAW_PENDING 1
+#define UPDATE_V_SCROLLBAR 2
+#define UPDATE_H_SCROLLBAR 4
+#define GOT_FOCUS 8
+#define MAXWIDTH_IS_STALE 16
+#define LISTBOX_DELETED 32
+
+/*
+ * The following enum is used to define a type for the -state option of the
+ * Listbox widget. These values are used as indices into the string table
+ * below.
+ */
+
+enum state {
+ STATE_DISABLED, STATE_NORMAL
+};
+
+static const char *const stateStrings[] = {
+ "disabled", "normal", NULL
+};
+
+enum activeStyle {
+ ACTIVE_STYLE_DOTBOX, ACTIVE_STYLE_NONE, ACTIVE_STYLE_UNDERLINE
+};
+
+static const char *const activeStyleStrings[] = {
+ "dotbox", "none", "underline", NULL
+};
+
+/*
+ * The optionSpecs table defines the valid configuration options for the
+ * listbox widget.
+ */
+
+static const Tk_OptionSpec optionSpecs[] = {
+ {TK_OPTION_STRING_TABLE, "-activestyle", "activeStyle", "ActiveStyle",
+ DEF_LISTBOX_ACTIVE_STYLE, -1, Tk_Offset(Listbox, activeStyle),
+ 0, activeStyleStrings, 0},
+ {TK_OPTION_BORDER, "-background", "background", "Background",
+ DEF_LISTBOX_BG_COLOR, -1, Tk_Offset(Listbox, normalBorder),
+ 0, DEF_LISTBOX_BG_MONO, 0},
+ {TK_OPTION_SYNONYM, "-bd", NULL, NULL,
+ NULL, 0, -1, 0, "-borderwidth", 0},
+ {TK_OPTION_SYNONYM, "-bg", NULL, NULL,
+ NULL, 0, -1, 0, "-background", 0},
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ DEF_LISTBOX_BORDER_WIDTH, -1, Tk_Offset(Listbox, borderWidth),
+ 0, 0, 0},
+ {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
+ DEF_LISTBOX_CURSOR, -1, Tk_Offset(Listbox, cursor),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
+ "DisabledForeground", DEF_LISTBOX_DISABLED_FG, -1,
+ Tk_Offset(Listbox, dfgColorPtr), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_BOOLEAN, "-exportselection", "exportSelection",
+ "ExportSelection", DEF_LISTBOX_EXPORT_SELECTION, -1,
+ Tk_Offset(Listbox, exportSelection), 0, 0, 0},
+ {TK_OPTION_SYNONYM, "-fg", "foreground", NULL,
+ NULL, 0, -1, 0, "-foreground", 0},
+ {TK_OPTION_FONT, "-font", "font", "Font",
+ DEF_LISTBOX_FONT, -1, Tk_Offset(Listbox, tkfont), 0, 0, 0},
+ {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
+ DEF_LISTBOX_FG, -1, Tk_Offset(Listbox, fgColorPtr), 0, 0, 0},
+ {TK_OPTION_INT, "-height", "height", "Height",
+ DEF_LISTBOX_HEIGHT, -1, Tk_Offset(Listbox, height), 0, 0, 0},
+ {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground",
+ "HighlightBackground", DEF_LISTBOX_HIGHLIGHT_BG, -1,
+ Tk_Offset(Listbox, highlightBgColorPtr), 0, 0, 0},
+ {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
+ DEF_LISTBOX_HIGHLIGHT, -1, Tk_Offset(Listbox, highlightColorPtr),
+ 0, 0, 0},
+ {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
+ "HighlightThickness", DEF_LISTBOX_HIGHLIGHT_WIDTH, -1,
+ Tk_Offset(Listbox, highlightWidth), 0, 0, 0},
+ {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
+ DEF_LISTBOX_JUSTIFY, -1, Tk_Offset(Listbox, justify), 0, 0, 0},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ DEF_LISTBOX_RELIEF, -1, Tk_Offset(Listbox, relief), 0, 0, 0},
+ {TK_OPTION_BORDER, "-selectbackground", "selectBackground", "Foreground",
+ DEF_LISTBOX_SELECT_COLOR, -1, Tk_Offset(Listbox, selBorder),
+ 0, DEF_LISTBOX_SELECT_MONO, 0},
+ {TK_OPTION_PIXELS, "-selectborderwidth", "selectBorderWidth",
+ "BorderWidth", DEF_LISTBOX_SELECT_BD, -1,
+ Tk_Offset(Listbox, selBorderWidth), 0, 0, 0},
+ {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background",
+ DEF_LISTBOX_SELECT_FG_COLOR, -1, Tk_Offset(Listbox, selFgColorPtr),
+ TK_OPTION_NULL_OK, DEF_LISTBOX_SELECT_FG_MONO, 0},
+ {TK_OPTION_STRING, "-selectmode", "selectMode", "SelectMode",
+ DEF_LISTBOX_SELECT_MODE, -1, Tk_Offset(Listbox, selectMode),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_BOOLEAN, "-setgrid", "setGrid", "SetGrid",
+ DEF_LISTBOX_SET_GRID, -1, Tk_Offset(Listbox, setGrid), 0, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-state", "state", "State",
+ DEF_LISTBOX_STATE, -1, Tk_Offset(Listbox, state),
+ 0, stateStrings, 0},
+ {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
+ DEF_LISTBOX_TAKE_FOCUS, -1, Tk_Offset(Listbox, takeFocus),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_INT, "-width", "width", "Width",
+ DEF_LISTBOX_WIDTH, -1, Tk_Offset(Listbox, width), 0, 0, 0},
+ {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
+ DEF_LISTBOX_SCROLL_COMMAND, -1, Tk_Offset(Listbox, xScrollCmd),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand",
+ DEF_LISTBOX_SCROLL_COMMAND, -1, Tk_Offset(Listbox, yScrollCmd),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-listvariable", "listVariable", "Variable",
+ DEF_LISTBOX_LIST_VARIABLE, -1, Tk_Offset(Listbox, listVarName),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0}
+};
+
+/*
+ * The itemAttrOptionSpecs table defines the valid configuration options for
+ * listbox items.
+ */
+
+static const Tk_OptionSpec itemAttrOptionSpecs[] = {
+ {TK_OPTION_BORDER, "-background", "background", "Background",
+ NULL, -1, Tk_Offset(ItemAttr, border),
+ TK_OPTION_NULL_OK|TK_OPTION_DONT_SET_DEFAULT,
+ DEF_LISTBOX_BG_MONO, 0},
+ {TK_OPTION_SYNONYM, "-bg", NULL, NULL,
+ NULL, 0, -1, 0, "-background", 0},
+ {TK_OPTION_SYNONYM, "-fg", "foreground", NULL,
+ NULL, 0, -1, 0, "-foreground", 0},
+ {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
+ NULL, -1, Tk_Offset(ItemAttr, fgColor),
+ TK_OPTION_NULL_OK|TK_OPTION_DONT_SET_DEFAULT, 0, 0},
+ {TK_OPTION_BORDER, "-selectbackground", "selectBackground", "Foreground",
+ NULL, -1, Tk_Offset(ItemAttr, selBorder),
+ TK_OPTION_NULL_OK|TK_OPTION_DONT_SET_DEFAULT,
+ DEF_LISTBOX_SELECT_MONO, 0},
+ {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background",
+ NULL, -1, Tk_Offset(ItemAttr, selFgColor),
+ TK_OPTION_NULL_OK|TK_OPTION_DONT_SET_DEFAULT,
+ DEF_LISTBOX_SELECT_FG_MONO, 0},
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0}
+};
+
+/*
+ * The following tables define the listbox widget commands (and sub-commands)
+ * and map the indexes into the string tables into enumerated types used to
+ * dispatch the listbox widget command.
+ */
+
+static const char *const commandNames[] = {
+ "activate", "bbox", "cget", "configure", "curselection", "delete", "get",
+ "index", "insert", "itemcget", "itemconfigure", "nearest", "scan",
+ "see", "selection", "size", "xview", "yview", NULL
+};
+enum command {
+ COMMAND_ACTIVATE, COMMAND_BBOX, COMMAND_CGET, COMMAND_CONFIGURE,
+ COMMAND_CURSELECTION, COMMAND_DELETE, COMMAND_GET, COMMAND_INDEX,
+ COMMAND_INSERT, COMMAND_ITEMCGET, COMMAND_ITEMCONFIGURE,
+ COMMAND_NEAREST, COMMAND_SCAN, COMMAND_SEE, COMMAND_SELECTION,
+ COMMAND_SIZE, COMMAND_XVIEW, COMMAND_YVIEW
+};
+
+static const char *const selCommandNames[] = {
+ "anchor", "clear", "includes", "set", NULL
+};
+enum selcommand {
+ SELECTION_ANCHOR, SELECTION_CLEAR, SELECTION_INCLUDES, SELECTION_SET
+};
+
+static const char *const scanCommandNames[] = {
+ "mark", "dragto", NULL
+};
+enum scancommand {
+ SCAN_MARK, SCAN_DRAGTO
+};
+
+static const char *const indexNames[] = {
+ "active", "anchor", "end", NULL
+};
+enum indices {
+ INDEX_ACTIVE, INDEX_ANCHOR, INDEX_END
+};
+
+/*
+ * Declarations for procedures defined later in this file.
+ */
+
+static void ChangeListboxOffset(Listbox *listPtr, int offset);
+static void ChangeListboxView(Listbox *listPtr, int index);
+static int ConfigureListbox(Tcl_Interp *interp, Listbox *listPtr,
+ int objc, Tcl_Obj *const objv[]);
+static int ConfigureListboxItem(Tcl_Interp *interp,
+ Listbox *listPtr, ItemAttr *attrs, int objc,
+ Tcl_Obj *const objv[], int index);
+static int ListboxDeleteSubCmd(Listbox *listPtr,
+ int first, int last);
+static void DestroyListbox(void *memPtr);
+static void DestroyListboxOptionTables(ClientData clientData,
+ Tcl_Interp *interp);
+static void DisplayListbox(ClientData clientData);
+static int GetListboxIndex(Tcl_Interp *interp, Listbox *listPtr,
+ Tcl_Obj *index, int endIsSize, int *indexPtr);
+static int ListboxInsertSubCmd(Listbox *listPtr,
+ int index, int objc, Tcl_Obj *const objv[]);
+static void ListboxCmdDeletedProc(ClientData clientData);
+static void ListboxComputeGeometry(Listbox *listPtr,
+ int fontChanged, int maxIsStale, int updateGrid);
+static void ListboxEventProc(ClientData clientData,
+ XEvent *eventPtr);
+static int ListboxFetchSelection(ClientData clientData,
+ int offset, char *buffer, int maxBytes);
+static void ListboxLostSelection(ClientData clientData);
+static void GenerateListboxSelectEvent(Listbox *listPtr);
+static void EventuallyRedrawRange(Listbox *listPtr,
+ int first, int last);
+static void ListboxScanTo(Listbox *listPtr, int x, int y);
+static int ListboxSelect(Listbox *listPtr,
+ int first, int last, int select);
+static void ListboxUpdateHScrollbar(Listbox *listPtr);
+static void ListboxUpdateVScrollbar(Listbox *listPtr);
+static int ListboxWidgetObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int ListboxBboxSubCmd(Tcl_Interp *interp,
+ Listbox *listPtr, int index);
+static int ListboxSelectionSubCmd(Tcl_Interp *interp,
+ Listbox *listPtr, int objc, Tcl_Obj *const objv[]);
+static int ListboxXviewSubCmd(Tcl_Interp *interp,
+ Listbox *listPtr, int objc, Tcl_Obj *const objv[]);
+static int ListboxYviewSubCmd(Tcl_Interp *interp,
+ Listbox *listPtr, int objc, Tcl_Obj *const objv[]);
+static ItemAttr * ListboxGetItemAttributes(Tcl_Interp *interp,
+ Listbox *listPtr, int index);
+static void ListboxWorldChanged(ClientData instanceData);
+static int NearestListboxElement(Listbox *listPtr, int y);
+static char * ListboxListVarProc(ClientData clientData,
+ Tcl_Interp *interp, const char *name1,
+ const char *name2, int flags);
+static void MigrateHashEntries(Tcl_HashTable *table,
+ int first, int last, int offset);
+static int GetMaxOffset(Listbox *listPtr);
+
+/*
+ * The structure below defines button class behavior by means of procedures
+ * that can be invoked from generic window code.
+ */
+
+static const Tk_ClassProcs listboxClass = {
+ sizeof(Tk_ClassProcs), /* size */
+ ListboxWorldChanged, /* worldChangedProc */
+ NULL, /* createProc */
+ NULL /* modalProc */
+};
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_ListboxObjCmd --
+ *
+ * This procedure is invoked to process the "listbox" 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_ListboxObjCmd(
+ ClientData clientData, /* NULL. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ register Listbox *listPtr;
+ Tk_Window tkwin;
+ ListboxOptionTables *optionTables;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?");
+ return TCL_ERROR;
+ }
+
+ tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),
+ Tcl_GetString(objv[1]), NULL);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+
+ optionTables = Tcl_GetAssocData(interp, "ListboxOptionTables", NULL);
+ if (optionTables == NULL) {
+ /*
+ * We haven't created the option tables for this widget class yet. Do
+ * it now and save the a pointer to them as the ClientData for the
+ * command, so future invocations will have access to it.
+ */
+
+ optionTables = ckalloc(sizeof(ListboxOptionTables));
+
+ /*
+ * Set up an exit handler to free the optionTables struct.
+ */
+
+ Tcl_SetAssocData(interp, "ListboxOptionTables",
+ DestroyListboxOptionTables, optionTables);
+
+ /*
+ * Create the listbox option table and the listbox item option table.
+ */
+
+ optionTables->listboxOptionTable =
+ Tk_CreateOptionTable(interp, optionSpecs);
+ optionTables->itemAttrOptionTable =
+ Tk_CreateOptionTable(interp, itemAttrOptionSpecs);
+ }
+
+ /*
+ * Initialize the fields of the structure that won't be initialized by
+ * ConfigureListbox, or that ConfigureListbox requires to be initialized
+ * already (e.g. resource pointers).
+ */
+
+ listPtr = ckalloc(sizeof(Listbox));
+ memset(listPtr, 0, sizeof(Listbox));
+
+ listPtr->tkwin = tkwin;
+ listPtr->display = Tk_Display(tkwin);
+ listPtr->interp = interp;
+ listPtr->widgetCmd = Tcl_CreateObjCommand(interp,
+ Tk_PathName(listPtr->tkwin), ListboxWidgetObjCmd, listPtr,
+ ListboxCmdDeletedProc);
+ listPtr->optionTable = optionTables->listboxOptionTable;
+ listPtr->itemAttrOptionTable = optionTables->itemAttrOptionTable;
+ listPtr->selection = ckalloc(sizeof(Tcl_HashTable));
+ Tcl_InitHashTable(listPtr->selection, TCL_ONE_WORD_KEYS);
+ listPtr->itemAttrTable = ckalloc(sizeof(Tcl_HashTable));
+ Tcl_InitHashTable(listPtr->itemAttrTable, TCL_ONE_WORD_KEYS);
+ listPtr->relief = TK_RELIEF_RAISED;
+ listPtr->textGC = NULL;
+ listPtr->selFgColorPtr = NULL;
+ listPtr->selTextGC = NULL;
+ listPtr->fullLines = 1;
+ listPtr->xScrollUnit = 1;
+ listPtr->exportSelection = 1;
+ listPtr->cursor = NULL;
+ listPtr->state = STATE_NORMAL;
+ listPtr->gray = None;
+ listPtr->justify = TK_JUSTIFY_LEFT;
+
+ /*
+ * Keep a hold of the associated tkwin until we destroy the listbox,
+ * otherwise Tk might free it while we still need it.
+ */
+
+ Tcl_Preserve(listPtr->tkwin);
+
+ Tk_SetClass(listPtr->tkwin, "Listbox");
+ Tk_SetClassProcs(listPtr->tkwin, &listboxClass, listPtr);
+ Tk_CreateEventHandler(listPtr->tkwin,
+ ExposureMask|StructureNotifyMask|FocusChangeMask,
+ ListboxEventProc, listPtr);
+ Tk_CreateSelHandler(listPtr->tkwin, XA_PRIMARY, XA_STRING,
+ ListboxFetchSelection, listPtr, XA_STRING);
+ if (Tk_InitOptions(interp, (char *)listPtr,
+ optionTables->listboxOptionTable, tkwin) != TCL_OK) {
+ Tk_DestroyWindow(listPtr->tkwin);
+ return TCL_ERROR;
+ }
+
+ if (ConfigureListbox(interp, listPtr, objc-2, objv+2) != TCL_OK) {
+ Tk_DestroyWindow(listPtr->tkwin);
+ return TCL_ERROR;
+ }
+
+ Tcl_SetObjResult(interp, TkNewWindowObj(listPtr->tkwin));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListboxWidgetObjCmd --
+ *
+ * This Tcl_Obj based procedure is invoked to process the Tcl command
+ * that corresponds to a widget managed by this module. See the user
+ * documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ListboxWidgetObjCmd(
+ ClientData clientData, /* Information about listbox widget. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Arguments as Tcl_Obj's. */
+{
+ register Listbox *listPtr = clientData;
+ int cmdIndex, index;
+ int result = TCL_OK;
+ Tcl_Obj *objPtr;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Parse the command by looking up the second argument in the list of
+ * valid subcommand names.
+ */
+
+ result = Tcl_GetIndexFromObj(interp, objv[1], commandNames,
+ "option", 0, &cmdIndex);
+ if (result != TCL_OK) {
+ return result;
+ }
+
+ Tcl_Preserve(listPtr);
+
+ /*
+ * The subcommand was valid, so continue processing.
+ */
+
+ switch (cmdIndex) {
+ case COMMAND_ACTIVATE:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index");
+ result = TCL_ERROR;
+ break;
+ }
+ result = GetListboxIndex(interp, listPtr, objv[2], 0, &index);
+ if (result != TCL_OK) {
+ break;
+ }
+
+ if (!(listPtr->state & STATE_NORMAL)) {
+ break;
+ }
+
+ if (index >= listPtr->nElements) {
+ index = listPtr->nElements-1;
+ }
+ if (index < 0) {
+ index = 0;
+ }
+ listPtr->active = index;
+ EventuallyRedrawRange(listPtr, listPtr->active, listPtr->active);
+ result = TCL_OK;
+ break;
+
+ case COMMAND_BBOX:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index");
+ result = TCL_ERROR;
+ break;
+ }
+ result = GetListboxIndex(interp, listPtr, objv[2], 0, &index);
+ if (result != TCL_OK) {
+ break;
+ }
+
+ result = ListboxBboxSubCmd(interp, listPtr, index);
+ break;
+
+ case COMMAND_CGET:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option");
+ result = TCL_ERROR;
+ break;
+ }
+
+ objPtr = Tk_GetOptionValue(interp, (char *) listPtr,
+ listPtr->optionTable, objv[2], listPtr->tkwin);
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ break;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ result = TCL_OK;
+ break;
+
+ case COMMAND_CONFIGURE:
+ if (objc <= 3) {
+ objPtr = Tk_GetOptionInfo(interp, (char *) listPtr,
+ listPtr->optionTable,
+ (objc == 3) ? objv[2] : NULL, listPtr->tkwin);
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ break;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ result = TCL_OK;
+ } else {
+ result = ConfigureListbox(interp, listPtr, objc-2, objv+2);
+ }
+ break;
+
+ case COMMAND_CURSELECTION: {
+ int i;
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ result = TCL_ERROR;
+ break;
+ }
+
+ /*
+ * Of course, it would be more efficient to use the Tcl_HashTable
+ * search functions (Tcl_FirstHashEntry, Tcl_NextHashEntry), but then
+ * the result wouldn't be in sorted order. So instead we loop through
+ * the indices in order, adding them to the result if they are
+ * selected.
+ */
+
+ objPtr = Tcl_NewObj();
+ for (i = 0; i < listPtr->nElements; i++) {
+ if (Tcl_FindHashEntry(listPtr->selection, KEY(i))) {
+ Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewIntObj(i));
+ }
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ result = TCL_OK;
+ break;
+ }
+
+ case COMMAND_DELETE: {
+ int first, last;
+
+ if ((objc < 3) || (objc > 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "firstIndex ?lastIndex?");
+ result = TCL_ERROR;
+ break;
+ }
+
+ result = GetListboxIndex(interp, listPtr, objv[2], 0, &first);
+ if (result != TCL_OK) {
+ break;
+ }
+
+ if (!(listPtr->state & STATE_NORMAL)) {
+ break;
+ }
+
+ if (first < listPtr->nElements) {
+ /*
+ * if a "last index" was given, get it now; otherwise, use the
+ * first index as the last index.
+ */
+
+ if (objc == 4) {
+ result = GetListboxIndex(interp, listPtr, objv[3], 0, &last);
+ if (result != TCL_OK) {
+ break;
+ }
+ } else {
+ last = first;
+ }
+ if (last >= listPtr->nElements) {
+ last = listPtr->nElements - 1;
+ }
+ result = ListboxDeleteSubCmd(listPtr, first, last);
+ } else {
+ result = TCL_OK;
+ }
+ break;
+ }
+
+ case COMMAND_GET: {
+ int first, last, listLen;
+ Tcl_Obj **elemPtrs;
+
+ if (objc != 3 && objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "firstIndex ?lastIndex?");
+ result = TCL_ERROR;
+ break;
+ }
+ result = GetListboxIndex(interp, listPtr, objv[2], 0, &first);
+ if (result != TCL_OK) {
+ break;
+ }
+ last = first;
+ if (objc == 4) {
+ result = GetListboxIndex(interp, listPtr, objv[3], 0, &last);
+ if (result != TCL_OK) {
+ break;
+ }
+ }
+ if (first >= listPtr->nElements) {
+ result = TCL_OK;
+ break;
+ }
+ if (last >= listPtr->nElements) {
+ last = listPtr->nElements - 1;
+ }
+ if (first < 0) {
+ first = 0;
+ }
+ if (first > last) {
+ result = TCL_OK;
+ break;
+ }
+ result = Tcl_ListObjGetElements(interp, listPtr->listObj, &listLen,
+ &elemPtrs);
+ if (result != TCL_OK) {
+ break;
+ }
+ if (objc == 3) {
+ /*
+ * One element request - we return a string
+ */
+
+ Tcl_SetObjResult(interp, elemPtrs[first]);
+ } else {
+ Tcl_SetObjResult(interp,
+ Tcl_NewListObj(last-first+1, elemPtrs+first));
+ }
+ result = TCL_OK;
+ break;
+ }
+
+ case COMMAND_INDEX:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index");
+ result = TCL_ERROR;
+ break;
+ }
+ result = GetListboxIndex(interp, listPtr, objv[2], 1, &index);
+ if (result != TCL_OK) {
+ break;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(index));
+ result = TCL_OK;
+ break;
+
+ case COMMAND_INSERT:
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index ?element ...?");
+ result = TCL_ERROR;
+ break;
+ }
+
+ result = GetListboxIndex(interp, listPtr, objv[2], 1, &index);
+ if (result != TCL_OK) {
+ break;
+ }
+
+ if (!(listPtr->state & STATE_NORMAL)) {
+ break;
+ }
+
+ result = ListboxInsertSubCmd(listPtr, index, objc-3, objv+3);
+ break;
+
+ case COMMAND_ITEMCGET: {
+ ItemAttr *attrPtr;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index option");
+ result = TCL_ERROR;
+ break;
+ }
+
+ result = GetListboxIndex(interp, listPtr, objv[2], 0, &index);
+ if (result != TCL_OK) {
+ break;
+ }
+
+ if (index < 0 || index >= listPtr->nElements) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "item number \"%s\" out of range",
+ Tcl_GetString(objv[2])));
+ Tcl_SetErrorCode(interp, "TK", "LISTBOX", "ITEM_INDEX", NULL);
+ result = TCL_ERROR;
+ break;
+ }
+
+ attrPtr = ListboxGetItemAttributes(interp, listPtr, index);
+
+ objPtr = Tk_GetOptionValue(interp, (char *) attrPtr,
+ listPtr->itemAttrOptionTable, objv[3], listPtr->tkwin);
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ break;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ result = TCL_OK;
+ break;
+ }
+
+ case COMMAND_ITEMCONFIGURE: {
+ ItemAttr *attrPtr;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "index ?-option? ?value? ?-option value ...?");
+ result = TCL_ERROR;
+ break;
+ }
+
+ result = GetListboxIndex(interp, listPtr, objv[2], 0, &index);
+ if (result != TCL_OK) {
+ break;
+ }
+
+ if (index < 0 || index >= listPtr->nElements) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "item number \"%s\" out of range",
+ Tcl_GetString(objv[2])));
+ Tcl_SetErrorCode(interp, "TK", "LISTBOX", "ITEM_INDEX", NULL);
+ result = TCL_ERROR;
+ break;
+ }
+
+ attrPtr = ListboxGetItemAttributes(interp, listPtr, index);
+ if (objc <= 4) {
+ objPtr = Tk_GetOptionInfo(interp, (char *) attrPtr,
+ listPtr->itemAttrOptionTable,
+ (objc == 4) ? objv[3] : NULL, listPtr->tkwin);
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ break;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ result = TCL_OK;
+ } else {
+ result = ConfigureListboxItem(interp, listPtr, attrPtr,
+ objc-3, objv+3, index);
+ }
+ break;
+ }
+
+ case COMMAND_NEAREST: {
+ int y;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "y");
+ result = TCL_ERROR;
+ break;
+ }
+
+ result = Tcl_GetIntFromObj(interp, objv[2], &y);
+ if (result != TCL_OK) {
+ break;
+ }
+ index = NearestListboxElement(listPtr, y);
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(index));
+ result = TCL_OK;
+ break;
+ }
+
+ case COMMAND_SCAN: {
+ int x, y, scanCmdIndex;
+
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 2, objv, "mark|dragto x y");
+ result = TCL_ERROR;
+ break;
+ }
+
+ if (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK
+ || Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK) {
+ result = TCL_ERROR;
+ break;
+ }
+
+ result = Tcl_GetIndexFromObj(interp, objv[2], scanCommandNames,
+ "option", 0, &scanCmdIndex);
+ if (result != TCL_OK) {
+ break;
+ }
+ switch (scanCmdIndex) {
+ case SCAN_MARK:
+ listPtr->scanMarkX = x;
+ listPtr->scanMarkY = y;
+ listPtr->scanMarkXOffset = listPtr->xOffset;
+ listPtr->scanMarkYIndex = listPtr->topIndex;
+ break;
+ case SCAN_DRAGTO:
+ ListboxScanTo(listPtr, x, y);
+ break;
+ }
+ result = TCL_OK;
+ break;
+ }
+
+ case COMMAND_SEE: {
+ int diff;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index");
+ result = TCL_ERROR;
+ break;
+ }
+ result = GetListboxIndex(interp, listPtr, objv[2], 0, &index);
+ if (result != TCL_OK) {
+ break;
+ }
+ if (index >= listPtr->nElements) {
+ index = listPtr->nElements - 1;
+ }
+ if (index < 0) {
+ index = 0;
+ }
+ diff = listPtr->topIndex - index;
+ if (diff > 0) {
+ if (diff <= listPtr->fullLines / 3) {
+ ChangeListboxView(listPtr, index);
+ } else {
+ ChangeListboxView(listPtr, index - (listPtr->fullLines-1)/2);
+ }
+ } else {
+ diff = index - (listPtr->topIndex + listPtr->fullLines - 1);
+ if (diff > 0) {
+ if (diff <= listPtr->fullLines / 3) {
+ ChangeListboxView(listPtr, listPtr->topIndex + diff);
+ } else {
+ ChangeListboxView(listPtr, index-(listPtr->fullLines-1)/2);
+ }
+ }
+ }
+ result = TCL_OK;
+ break;
+ }
+
+ case COMMAND_SELECTION:
+ result = ListboxSelectionSubCmd(interp, listPtr, objc, objv);
+ break;
+ case COMMAND_SIZE:
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ result = TCL_ERROR;
+ break;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(listPtr->nElements));
+ result = TCL_OK;
+ break;
+ case COMMAND_XVIEW:
+ result = ListboxXviewSubCmd(interp, listPtr, objc, objv);
+ break;
+ case COMMAND_YVIEW:
+ result = ListboxYviewSubCmd(interp, listPtr, objc, objv);
+ break;
+ }
+ Tcl_Release(listPtr);
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListboxBboxSubCmd --
+ *
+ * This procedure is invoked to process a listbox bbox request. See the
+ * user documentation for more information.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * For valid indices, places the bbox of the requested element in the
+ * interpreter's result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ListboxBboxSubCmd(
+ Tcl_Interp *interp, /* Pointer to the calling Tcl interpreter */
+ Listbox *listPtr, /* Information about the listbox */
+ int index) /* Index of the element to get bbox info on */
+{
+ register Tk_Window tkwin = listPtr->tkwin;
+ int lastVisibleIndex;
+
+ /*
+ * Determine the index of the last visible item in the listbox.
+ */
+
+ lastVisibleIndex = listPtr->topIndex + listPtr->fullLines
+ + listPtr->partialLine;
+ if (listPtr->nElements < lastVisibleIndex) {
+ lastVisibleIndex = listPtr->nElements;
+ }
+
+ /*
+ * Only allow bbox requests for indices that are visible.
+ */
+
+ if ((listPtr->topIndex <= index) && (index < lastVisibleIndex)) {
+ Tcl_Obj *el, *results[4];
+ const char *stringRep;
+ int pixelWidth, stringLen, x, y, result;
+ Tk_FontMetrics fm;
+
+ /*
+ * Compute the pixel width of the requested element.
+ */
+
+ result = Tcl_ListObjIndex(interp, listPtr->listObj, index, &el);
+ if (result != TCL_OK) {
+ return result;
+ }
+
+ stringRep = Tcl_GetStringFromObj(el, &stringLen);
+ Tk_GetFontMetrics(listPtr->tkfont, &fm);
+ pixelWidth = Tk_TextWidth(listPtr->tkfont, stringRep, stringLen);
+
+ if (listPtr->justify == TK_JUSTIFY_LEFT) {
+ x = (listPtr->inset + listPtr->selBorderWidth) - listPtr->xOffset;
+ } else if (listPtr->justify == TK_JUSTIFY_RIGHT) {
+ x = Tk_Width(tkwin) - (listPtr->inset + listPtr->selBorderWidth)
+ - pixelWidth - listPtr->xOffset + GetMaxOffset(listPtr);
+ } else {
+ x = (Tk_Width(tkwin) - pixelWidth)/2
+ - listPtr->xOffset + GetMaxOffset(listPtr)/2;
+ }
+ y = ((index - listPtr->topIndex)*listPtr->lineHeight)
+ + listPtr->inset + listPtr->selBorderWidth;
+ results[0] = Tcl_NewIntObj(x);
+ results[1] = Tcl_NewIntObj(y);
+ results[2] = Tcl_NewIntObj(pixelWidth);
+ results[3] = Tcl_NewIntObj(fm.linespace);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(4, results));
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListboxSelectionSubCmd --
+ *
+ * This procedure is invoked to process the selection sub command for
+ * listbox widgets.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * May set the interpreter's result field.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ListboxSelectionSubCmd(
+ Tcl_Interp *interp, /* Pointer to the calling Tcl interpreter */
+ Listbox *listPtr, /* Information about the listbox */
+ int objc, /* Number of arguments in the objv array */
+ Tcl_Obj *const objv[]) /* Array of arguments to the procedure */
+{
+ int selCmdIndex, first, last;
+ int result = TCL_OK;
+
+ if (objc != 4 && objc != 5) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option index ?index?");
+ return TCL_ERROR;
+ }
+ result = GetListboxIndex(interp, listPtr, objv[3], 0, &first);
+ if (result != TCL_OK) {
+ return result;
+ }
+ last = first;
+ if (objc == 5) {
+ result = GetListboxIndex(interp, listPtr, objv[4], 0, &last);
+ if (result != TCL_OK) {
+ return result;
+ }
+ }
+ result = Tcl_GetIndexFromObj(interp, objv[2], selCommandNames,
+ "option", 0, &selCmdIndex);
+ if (result != TCL_OK) {
+ return result;
+ }
+
+ /*
+ * Only allow 'selection includes' to respond if disabled. [Bug #632514]
+ */
+
+ if ((listPtr->state == STATE_DISABLED)
+ && (selCmdIndex != SELECTION_INCLUDES)) {
+ return TCL_OK;
+ }
+
+ switch (selCmdIndex) {
+ case SELECTION_ANCHOR:
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index");
+ return TCL_ERROR;
+ }
+ if (first >= listPtr->nElements) {
+ first = listPtr->nElements - 1;
+ }
+ if (first < 0) {
+ first = 0;
+ }
+ listPtr->selectAnchor = first;
+ result = TCL_OK;
+ break;
+ case SELECTION_CLEAR:
+ result = ListboxSelect(listPtr, first, last, 0);
+ break;
+ case SELECTION_INCLUDES:
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index");
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
+ Tcl_FindHashEntry(listPtr->selection, KEY(first)) != NULL));
+ result = TCL_OK;
+ break;
+ case SELECTION_SET:
+ result = ListboxSelect(listPtr, first, last, 1);
+ break;
+ }
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListboxXviewSubCmd --
+ *
+ * Process the listbox "xview" subcommand.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * May change the listbox viewing area; may set the interpreter's result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ListboxXviewSubCmd(
+ Tcl_Interp *interp, /* Pointer to the calling Tcl interpreter */
+ Listbox *listPtr, /* Information about the listbox */
+ int objc, /* Number of arguments in the objv array */
+ Tcl_Obj *const objv[]) /* Array of arguments to the procedure */
+{
+ int index, count, windowWidth, windowUnits;
+ int offset = 0; /* Initialized to stop gcc warnings. */
+ double fraction;
+
+ windowWidth = Tk_Width(listPtr->tkwin)
+ - 2*(listPtr->inset + listPtr->selBorderWidth);
+ if (objc == 2) {
+ Tcl_Obj *results[2];
+
+ if (listPtr->maxWidth == 0) {
+ results[0] = Tcl_NewDoubleObj(0.0);
+ results[1] = Tcl_NewDoubleObj(1.0);
+ } else {
+ double fraction2;
+
+ fraction = listPtr->xOffset / (double) listPtr->maxWidth;
+ fraction2 = (listPtr->xOffset + windowWidth)
+ / (double) listPtr->maxWidth;
+ if (fraction2 > 1.0) {
+ fraction2 = 1.0;
+ }
+ results[0] = Tcl_NewDoubleObj(fraction);
+ results[1] = Tcl_NewDoubleObj(fraction2);
+ }
+ Tcl_SetObjResult(interp, Tcl_NewListObj(2, results));
+ } else if (objc == 3) {
+ if (Tcl_GetIntFromObj(interp, objv[2], &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ ChangeListboxOffset(listPtr, index*listPtr->xScrollUnit);
+ } else {
+ switch (Tk_GetScrollInfoObj(interp, objc, objv, &fraction, &count)) {
+ case TK_SCROLL_ERROR:
+ return TCL_ERROR;
+ case TK_SCROLL_MOVETO:
+ offset = (int) (fraction*listPtr->maxWidth + 0.5);
+ break;
+ case TK_SCROLL_PAGES:
+ windowUnits = windowWidth / listPtr->xScrollUnit;
+ if (windowUnits > 2) {
+ offset = listPtr->xOffset
+ + count*listPtr->xScrollUnit*(windowUnits-2);
+ } else {
+ offset = listPtr->xOffset + count*listPtr->xScrollUnit;
+ }
+ break;
+ case TK_SCROLL_UNITS:
+ offset = listPtr->xOffset + count*listPtr->xScrollUnit;
+ break;
+ }
+ ChangeListboxOffset(listPtr, offset);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListboxYviewSubCmd --
+ *
+ * Process the listbox "yview" subcommand.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * May change the listbox viewing area; may set the interpreter's result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ListboxYviewSubCmd(
+ Tcl_Interp *interp, /* Pointer to the calling Tcl interpreter */
+ Listbox *listPtr, /* Information about the listbox */
+ int objc, /* Number of arguments in the objv array */
+ Tcl_Obj *const objv[]) /* Array of arguments to the procedure */
+{
+ int index, count;
+ double fraction;
+
+ if (objc == 2) {
+ Tcl_Obj *results[2];
+
+ if (listPtr->nElements == 0) {
+ results[0] = Tcl_NewDoubleObj(0.0);
+ results[1] = Tcl_NewDoubleObj(1.0);
+ } else {
+ double fraction2, numEls = (double) listPtr->nElements;
+
+ fraction = listPtr->topIndex / numEls;
+ fraction2 = (listPtr->topIndex+listPtr->fullLines) / numEls;
+ if (fraction2 > 1.0) {
+ fraction2 = 1.0;
+ }
+ results[0] = Tcl_NewDoubleObj(fraction);
+ results[1] = Tcl_NewDoubleObj(fraction2);
+ }
+ Tcl_SetObjResult(interp, Tcl_NewListObj(2, results));
+ } else if (objc == 3) {
+ if (GetListboxIndex(interp, listPtr, objv[2], 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ ChangeListboxView(listPtr, index);
+ } else {
+ switch (Tk_GetScrollInfoObj(interp, objc, objv, &fraction, &count)) {
+ case TK_SCROLL_MOVETO:
+ index = (int) (listPtr->nElements*fraction + 0.5);
+ break;
+ case TK_SCROLL_PAGES:
+ if (listPtr->fullLines > 2) {
+ index = listPtr->topIndex + count*(listPtr->fullLines-2);
+ } else {
+ index = listPtr->topIndex + count;
+ }
+ break;
+ case TK_SCROLL_UNITS:
+ index = listPtr->topIndex + count;
+ break;
+ case TK_SCROLL_ERROR:
+ default:
+ return TCL_ERROR;
+ }
+ ChangeListboxView(listPtr, index);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListboxGetItemAttributes --
+ *
+ * Returns a pointer to the ItemAttr record for a given index, creating
+ * one if it does not already exist.
+ *
+ * Results:
+ * Pointer to an ItemAttr record.
+ *
+ * Side effects:
+ * Memory may be allocated for the ItemAttr record.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static ItemAttr *
+ListboxGetItemAttributes(
+ Tcl_Interp *interp, /* Pointer to the calling Tcl interpreter */
+ Listbox *listPtr, /* Information about the listbox */
+ int index) /* Index of the item to retrieve attributes
+ * for. */
+{
+ int isNew;
+ Tcl_HashEntry *entry;
+ ItemAttr *attrs;
+
+ entry = Tcl_CreateHashEntry(listPtr->itemAttrTable, KEY(index), &isNew);
+ if (isNew) {
+ attrs = ckalloc(sizeof(ItemAttr));
+ attrs->border = NULL;
+ attrs->selBorder = NULL;
+ attrs->fgColor = NULL;
+ attrs->selFgColor = NULL;
+ Tk_InitOptions(interp, (char *)attrs, listPtr->itemAttrOptionTable,
+ listPtr->tkwin);
+ Tcl_SetHashValue(entry, attrs);
+ } else {
+ attrs = Tcl_GetHashValue(entry);
+ }
+ return attrs;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyListbox --
+ *
+ * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release to
+ * clean up the internal structure of a listbox at a safe time (when
+ * no-one is using it anymore).
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Everything associated with the listbox is freed up.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DestroyListbox(
+ void *memPtr) /* Info about listbox widget. */
+{
+ register Listbox *listPtr = memPtr;
+ Tcl_HashEntry *entry;
+ Tcl_HashSearch search;
+
+ /*
+ * If we have an internal list object, free it.
+ */
+
+ if (listPtr->listObj != NULL) {
+ Tcl_DecrRefCount(listPtr->listObj);
+ listPtr->listObj = NULL;
+ }
+
+ if (listPtr->listVarName != NULL) {
+ Tcl_UntraceVar2(listPtr->interp, listPtr->listVarName, NULL,
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ ListboxListVarProc, listPtr);
+ }
+
+ /*
+ * Free the selection hash table.
+ */
+
+ Tcl_DeleteHashTable(listPtr->selection);
+ ckfree(listPtr->selection);
+
+ /*
+ * Free the item attribute hash table.
+ */
+
+ for (entry = Tcl_FirstHashEntry(listPtr->itemAttrTable, &search);
+ entry != NULL; entry = Tcl_NextHashEntry(&search)) {
+ ckfree(Tcl_GetHashValue(entry));
+ }
+ Tcl_DeleteHashTable(listPtr->itemAttrTable);
+ ckfree(listPtr->itemAttrTable);
+
+ /*
+ * Free up all the stuff that requires special handling, then let
+ * Tk_FreeOptions handle all the standard option-related stuff.
+ */
+
+ if (listPtr->textGC != NULL) {
+ Tk_FreeGC(listPtr->display, listPtr->textGC);
+ }
+ if (listPtr->selTextGC != NULL) {
+ Tk_FreeGC(listPtr->display, listPtr->selTextGC);
+ }
+ if (listPtr->gray != None) {
+ Tk_FreeBitmap(Tk_Display(listPtr->tkwin), listPtr->gray);
+ }
+
+ Tk_FreeConfigOptions((char *) listPtr, listPtr->optionTable,
+ listPtr->tkwin);
+ Tcl_Release(listPtr->tkwin);
+ listPtr->tkwin = NULL;
+ ckfree(listPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyListboxOptionTables --
+ *
+ * This procedure is registered as an exit callback when the listbox
+ * command is first called. It cleans up the OptionTables structure
+ * allocated by that command.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Frees memory.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DestroyListboxOptionTables(
+ ClientData clientData, /* Pointer to the OptionTables struct */
+ Tcl_Interp *interp) /* Pointer to the calling interp */
+{
+ ckfree(clientData);
+ return;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConfigureListbox --
+ *
+ * This procedure is called to process an objv/objc list, plus the Tk
+ * option database, in order to configure (or reconfigure) a listbox
+ * widget.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If TCL_ERROR is returned,
+ * then the interp's result contains an error message.
+ *
+ * Side effects:
+ * Configuration information, such as colors, border width, etc. get set
+ * for listPtr; old resources get freed, if there were any.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ConfigureListbox(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ register Listbox *listPtr, /* Information about widget; may or may not
+ * already have values for some fields. */
+ int objc, /* Number of valid entries in argv. */
+ Tcl_Obj *const objv[]) /* Arguments. */
+{
+ Tk_SavedOptions savedOptions;
+ Tcl_Obj *oldListObj = NULL;
+ Tcl_Obj *errorResult = NULL;
+ int oldExport, error;
+
+ oldExport = (listPtr->exportSelection) && (!Tcl_IsSafe(listPtr->interp));
+ if (listPtr->listVarName != NULL) {
+ Tcl_UntraceVar2(interp, listPtr->listVarName, NULL,
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ ListboxListVarProc, listPtr);
+ }
+
+ for (error = 0; error <= 1; error++) {
+ if (!error) {
+ /*
+ * First pass: set options to new values.
+ */
+
+ if (Tk_SetOptions(interp, (char *) listPtr,
+ listPtr->optionTable, objc, objv,
+ listPtr->tkwin, &savedOptions, NULL) != TCL_OK) {
+ continue;
+ }
+ } else {
+ /*
+ * Second pass: restore options to old values.
+ */
+
+ errorResult = Tcl_GetObjResult(interp);
+ Tcl_IncrRefCount(errorResult);
+ Tk_RestoreSavedOptions(&savedOptions);
+ }
+
+ /*
+ * A few options need special processing, such as setting the
+ * background from a 3-D border.
+ */
+
+ Tk_SetBackgroundFromBorder(listPtr->tkwin, listPtr->normalBorder);
+
+ if (listPtr->highlightWidth < 0) {
+ listPtr->highlightWidth = 0;
+ }
+ listPtr->inset = listPtr->highlightWidth + listPtr->borderWidth;
+
+ /*
+ * Claim the selection if we've suddenly started exporting it and
+ * there is a selection to export and this interp is unsafe.
+ */
+
+ if (listPtr->exportSelection && (!oldExport)
+ && (!Tcl_IsSafe(listPtr->interp))
+ && (listPtr->numSelected != 0)) {
+ Tk_OwnSelection(listPtr->tkwin, XA_PRIMARY,
+ ListboxLostSelection, listPtr);
+ }
+
+ /*
+ * Verify the current status of the list var.
+ * PREVIOUS STATE | NEW STATE | ACTION
+ * ---------------+------------+----------------------------------
+ * no listvar | listvar | If listvar does not exist, create it
+ * and copy the internal list obj's
+ * content to the new var. If it does
+ * exist, toss the internal list obj.
+ *
+ * listvar | no listvar | Copy old listvar content to the
+ * internal list obj
+ *
+ * listvar | listvar | no special action
+ *
+ * no listvar | no listvar | no special action
+ */
+
+ oldListObj = listPtr->listObj;
+ if (listPtr->listVarName != NULL) {
+ Tcl_Obj *listVarObj = Tcl_GetVar2Ex(interp, listPtr->listVarName,
+ NULL, TCL_GLOBAL_ONLY);
+ int dummy;
+
+ if (listVarObj == NULL) {
+ listVarObj = (oldListObj ? oldListObj : Tcl_NewObj());
+ if (Tcl_SetVar2Ex(interp, listPtr->listVarName, NULL,
+ listVarObj, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
+ == NULL) {
+ continue;
+ }
+ }
+
+ /*
+ * Make sure the object is a good list object.
+ */
+
+ if (Tcl_ListObjLength(listPtr->interp, listVarObj, &dummy)
+ != TCL_OK) {
+ Tcl_AppendResult(listPtr->interp,
+ ": invalid -listvariable value", NULL);
+ continue;
+ }
+
+ listPtr->listObj = listVarObj;
+ Tcl_TraceVar2(listPtr->interp, listPtr->listVarName,
+ NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ ListboxListVarProc, listPtr);
+ } else if (listPtr->listObj == NULL) {
+ listPtr->listObj = Tcl_NewObj();
+ }
+ Tcl_IncrRefCount(listPtr->listObj);
+ if (oldListObj != NULL) {
+ Tcl_DecrRefCount(oldListObj);
+ }
+ break;
+ }
+ if (!error) {
+ Tk_FreeSavedOptions(&savedOptions);
+ }
+
+ /*
+ * Make sure that the list length is correct.
+ */
+
+ Tcl_ListObjLength(listPtr->interp, listPtr->listObj, &listPtr->nElements);
+
+ if (error) {
+ Tcl_SetObjResult(interp, errorResult);
+ Tcl_DecrRefCount(errorResult);
+ return TCL_ERROR;
+ }
+ ListboxWorldChanged(listPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConfigureListboxItem --
+ *
+ * This procedure is called to process an objv/objc list, plus the Tk
+ * option database, in order to configure (or reconfigure) a listbox
+ * item.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If TCL_ERROR is returned,
+ * then the interp's result contains an error message.
+ *
+ * Side effects:
+ * Configuration information, such as colors, border width, etc. get set
+ * for a listbox item; old resources get freed, if there were any.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ConfigureListboxItem(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ register Listbox *listPtr, /* Information about widget; may or may not
+ * already have values for some fields. */
+ ItemAttr *attrs, /* Information about the item to configure */
+ int objc, /* Number of valid entries in argv. */
+ Tcl_Obj *const objv[], /* Arguments. */
+ int index) /* Index of the listbox item being configure */
+{
+ Tk_SavedOptions savedOptions;
+
+ if (Tk_SetOptions(interp, (char *)attrs,
+ listPtr->itemAttrOptionTable, objc, objv, listPtr->tkwin,
+ &savedOptions, NULL) != TCL_OK) {
+ Tk_RestoreSavedOptions(&savedOptions);
+ return TCL_ERROR;
+ }
+ Tk_FreeSavedOptions(&savedOptions);
+
+ /*
+ * Redraw this index - ListboxWorldChanged would need to be called if item
+ * attributes were checked in the "world".
+ */
+
+ EventuallyRedrawRange(listPtr, index, index);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ListboxWorldChanged --
+ *
+ * This procedure is called when the world has changed in some way and
+ * the widget needs to recompute all its graphics contexts and determine
+ * its new geometry.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Listbox will be relayed out and redisplayed.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+ListboxWorldChanged(
+ ClientData instanceData) /* Information about widget. */
+{
+ XGCValues gcValues;
+ GC gc;
+ unsigned long mask;
+ Listbox *listPtr = instanceData;
+
+ if (listPtr->state & STATE_NORMAL) {
+ gcValues.foreground = listPtr->fgColorPtr->pixel;
+ gcValues.graphics_exposures = False;
+ mask = GCForeground | GCFont | GCGraphicsExposures;
+ } else if (listPtr->dfgColorPtr != NULL) {
+ gcValues.foreground = listPtr->dfgColorPtr->pixel;
+ gcValues.graphics_exposures = False;
+ mask = GCForeground | GCFont | GCGraphicsExposures;
+ } else {
+ gcValues.foreground = listPtr->fgColorPtr->pixel;
+ mask = GCForeground | GCFont;
+ if (listPtr->gray == None) {
+ listPtr->gray = Tk_GetBitmap(NULL, listPtr->tkwin, "gray50");
+ }
+ if (listPtr->gray != None) {
+ gcValues.fill_style = FillStippled;
+ gcValues.stipple = listPtr->gray;
+ mask |= GCFillStyle | GCStipple;
+ }
+ }
+
+ gcValues.font = Tk_FontId(listPtr->tkfont);
+ gc = Tk_GetGC(listPtr->tkwin, mask, &gcValues);
+ if (listPtr->textGC != NULL) {
+ Tk_FreeGC(listPtr->display, listPtr->textGC);
+ }
+ listPtr->textGC = gc;
+
+ if (listPtr->selFgColorPtr != NULL) {
+ gcValues.foreground = listPtr->selFgColorPtr->pixel;
+ }
+ gcValues.font = Tk_FontId(listPtr->tkfont);
+ mask = GCForeground | GCFont;
+ gc = Tk_GetGC(listPtr->tkwin, mask, &gcValues);
+ if (listPtr->selTextGC != NULL) {
+ Tk_FreeGC(listPtr->display, listPtr->selTextGC);
+ }
+ listPtr->selTextGC = gc;
+
+ /*
+ * Register the desired geometry for the window and arrange for the window
+ * to be redisplayed.
+ */
+
+ ListboxComputeGeometry(listPtr, 1, 1, 1);
+ listPtr->flags |= UPDATE_V_SCROLLBAR|UPDATE_H_SCROLLBAR;
+ EventuallyRedrawRange(listPtr, 0, listPtr->nElements-1);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DisplayListbox --
+ *
+ * This procedure redraws the contents of a listbox window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Information appears on the screen.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+DisplayListbox(
+ ClientData clientData) /* Information about window. */
+{
+ register Listbox *listPtr = clientData;
+ register Tk_Window tkwin = listPtr->tkwin;
+ GC gc;
+ int i, limit, x, y, prevSelected, freeGC, stringLen;
+ Tk_FontMetrics fm;
+ Tcl_Obj *curElement;
+ Tcl_HashEntry *entry;
+ const char *stringRep;
+ ItemAttr *attrs;
+ Tk_3DBorder selectedBg;
+ XGCValues gcValues;
+ unsigned long mask;
+ int left, right; /* Non-zero values here indicate that the left
+ * or right edge of the listbox is
+ * off-screen. */
+ Pixmap pixmap;
+ int textWidth;
+
+ listPtr->flags &= ~REDRAW_PENDING;
+ if (listPtr->flags & LISTBOX_DELETED) {
+ return;
+ }
+
+ if (listPtr->flags & MAXWIDTH_IS_STALE) {
+ ListboxComputeGeometry(listPtr, 0, 1, 0);
+ listPtr->flags &= ~MAXWIDTH_IS_STALE;
+ listPtr->flags |= UPDATE_H_SCROLLBAR;
+ }
+
+ Tcl_Preserve(listPtr);
+ if (listPtr->flags & UPDATE_V_SCROLLBAR) {
+ ListboxUpdateVScrollbar(listPtr);
+ if ((listPtr->flags & LISTBOX_DELETED) || !Tk_IsMapped(tkwin)) {
+ Tcl_Release(listPtr);
+ return;
+ }
+ }
+ if (listPtr->flags & UPDATE_H_SCROLLBAR) {
+ ListboxUpdateHScrollbar(listPtr);
+ if ((listPtr->flags & LISTBOX_DELETED) || !Tk_IsMapped(tkwin)) {
+ Tcl_Release(listPtr);
+ return;
+ }
+ }
+ listPtr->flags &= ~(REDRAW_PENDING|UPDATE_V_SCROLLBAR|UPDATE_H_SCROLLBAR);
+ Tcl_Release(listPtr);
+
+#ifndef TK_NO_DOUBLE_BUFFERING
+ /*
+ * Redrawing is done in a temporary pixmap that is allocated here and
+ * freed at the end of the procedure. All drawing is done to the pixmap,
+ * and the pixmap is copied to the screen at the end of the procedure.
+ * This provides the smoothest possible visual effects (no flashing on the
+ * screen).
+ */
+
+ pixmap = Tk_GetPixmap(listPtr->display, Tk_WindowId(tkwin),
+ Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));
+#else
+ pixmap = Tk_WindowId(tkwin);
+#endif /* TK_NO_DOUBLE_BUFFERING */
+ Tk_Fill3DRectangle(tkwin, pixmap, listPtr->normalBorder, 0, 0,
+ Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);
+
+ /*
+ * Display each item in the listbox.
+ */
+
+ limit = listPtr->topIndex + listPtr->fullLines + listPtr->partialLine - 1;
+ if (limit >= listPtr->nElements) {
+ limit = listPtr->nElements-1;
+ }
+ left = right = 0;
+ if (listPtr->xOffset > 0) {
+ left = listPtr->selBorderWidth+1;
+ }
+ if ((listPtr->maxWidth - listPtr->xOffset) > (Tk_Width(listPtr->tkwin)
+ - 2*(listPtr->inset + listPtr->selBorderWidth))) {
+ right = listPtr->selBorderWidth+1;
+ }
+ prevSelected = 0;
+
+ for (i = listPtr->topIndex; i <= limit; i++) {
+ int width = Tk_Width(tkwin); /* zeroth approx to silence warning */
+
+ x = listPtr->inset;
+ y = ((i - listPtr->topIndex) * listPtr->lineHeight) + listPtr->inset;
+ gc = listPtr->textGC;
+ freeGC = 0;
+
+ /*
+ * Lookup this item in the item attributes table, to see if it has
+ * special foreground/background colors.
+ */
+
+ entry = Tcl_FindHashEntry(listPtr->itemAttrTable, KEY(i));
+
+ /*
+ * If the listbox is enabled, items may be drawn differently; they may
+ * be drawn selected, or they may have special foreground or
+ * background colors.
+ */
+
+ if (listPtr->state & STATE_NORMAL) {
+ if (Tcl_FindHashEntry(listPtr->selection, KEY(i))) {
+ /*
+ * Selected items are drawn differently.
+ */
+
+ gc = listPtr->selTextGC;
+ width = Tk_Width(tkwin) - 2*listPtr->inset;
+ selectedBg = listPtr->selBorder;
+
+ /*
+ * If there is attribute information for this item, adjust the
+ * drawing accordingly.
+ */
+
+ if (entry != NULL) {
+ attrs = Tcl_GetHashValue(entry);
+
+ /*
+ * Default GC has the values from the widget at large.
+ */
+
+ if (listPtr->selFgColorPtr) {
+ gcValues.foreground = listPtr->selFgColorPtr->pixel;
+ } else {
+ gcValues.foreground = listPtr->fgColorPtr->pixel;
+ }
+ gcValues.font = Tk_FontId(listPtr->tkfont);
+ gcValues.graphics_exposures = False;
+ mask = GCForeground | GCFont | GCGraphicsExposures;
+
+ if (attrs->selBorder != NULL) {
+ selectedBg = attrs->selBorder;
+ }
+
+ if (attrs->selFgColor != NULL) {
+ gcValues.foreground = attrs->selFgColor->pixel;
+ gc = Tk_GetGC(listPtr->tkwin, mask, &gcValues);
+ freeGC = 1;
+ }
+ }
+
+ Tk_Fill3DRectangle(tkwin, pixmap, selectedBg, x, y,
+ width, listPtr->lineHeight, 0, TK_RELIEF_FLAT);
+
+ /*
+ * Draw beveled edges around the selection, if there are
+ * visible edges next to this element. Special considerations:
+ *
+ * 1. The left and right bevels may not be visible if
+ * horizontal scrolling is enabled (the "left" & "right"
+ * variables are zero to indicate that the corresponding
+ * bevel is visible).
+ * 2. Top and bottom bevels are only drawn if this is the
+ * first or last seleted item.
+ * 3. If the left or right bevel isn't visible, then the
+ * "left" & "right" vars, computed above, have non-zero
+ * values that extend the top and bottom bevels so that
+ * the mitered corners are off-screen.
+ */
+
+ /* Draw left bevel */
+ if (left == 0) {
+ Tk_3DVerticalBevel(tkwin, pixmap, selectedBg,
+ x, y, listPtr->selBorderWidth, listPtr->lineHeight,
+ 1, TK_RELIEF_RAISED);
+ }
+ /* Draw right bevel */
+ if (right == 0) {
+ Tk_3DVerticalBevel(tkwin, pixmap, selectedBg,
+ x + width - listPtr->selBorderWidth, y,
+ listPtr->selBorderWidth, listPtr->lineHeight,
+ 0, TK_RELIEF_RAISED);
+ }
+ /* Draw top bevel */
+ if (!prevSelected) {
+ Tk_3DHorizontalBevel(tkwin, pixmap, selectedBg,
+ x-left, y, width+left+right,
+ listPtr->selBorderWidth,
+ 1, 1, 1, TK_RELIEF_RAISED);
+ }
+ /* Draw bottom bevel */
+ if (i + 1 == listPtr->nElements ||
+ !Tcl_FindHashEntry(listPtr->selection, KEY(i + 1))) {
+ Tk_3DHorizontalBevel(tkwin, pixmap, selectedBg, x-left,
+ y + listPtr->lineHeight - listPtr->selBorderWidth,
+ width+left+right, listPtr->selBorderWidth, 0, 0, 0,
+ TK_RELIEF_RAISED);
+ }
+ prevSelected = 1;
+ } else {
+ /*
+ * If there is an item attributes record for this item, draw
+ * the background box and set the foreground color accordingly.
+ */
+
+ if (entry != NULL) {
+ attrs = Tcl_GetHashValue(entry);
+ gcValues.foreground = listPtr->fgColorPtr->pixel;
+ gcValues.font = Tk_FontId(listPtr->tkfont);
+ gcValues.graphics_exposures = False;
+ mask = GCForeground | GCFont | GCGraphicsExposures;
+
+ /*
+ * If the item has its own background color, draw it now.
+ */
+
+ if (attrs->border != NULL) {
+ width = Tk_Width(tkwin) - 2*listPtr->inset;
+ Tk_Fill3DRectangle(tkwin, pixmap, attrs->border, x, y,
+ width, listPtr->lineHeight, 0, TK_RELIEF_FLAT);
+ }
+
+ /*
+ * If the item has its own foreground, use it to override
+ * the value in the gcValues structure.
+ */
+
+ if ((listPtr->state & STATE_NORMAL)
+ && attrs->fgColor != NULL) {
+ gcValues.foreground = attrs->fgColor->pixel;
+ gc = Tk_GetGC(listPtr->tkwin, mask, &gcValues);
+ freeGC = 1;
+ }
+ }
+ prevSelected = 0;
+ }
+ }
+
+ /*
+ * Draw the actual text of this item.
+ */
+
+ Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i, &curElement);
+ stringRep = Tcl_GetStringFromObj(curElement, &stringLen);
+ textWidth = Tk_TextWidth(listPtr->tkfont, stringRep, stringLen);
+
+ Tk_GetFontMetrics(listPtr->tkfont, &fm);
+ y += fm.ascent + listPtr->selBorderWidth;
+
+ if (listPtr->justify == TK_JUSTIFY_LEFT) {
+ x = (listPtr->inset + listPtr->selBorderWidth) - listPtr->xOffset;
+ } else if (listPtr->justify == TK_JUSTIFY_RIGHT) {
+ x = Tk_Width(tkwin) - (listPtr->inset + listPtr->selBorderWidth)
+ - textWidth - listPtr->xOffset + GetMaxOffset(listPtr);
+ } else {
+ x = (Tk_Width(tkwin) - textWidth)/2
+ - listPtr->xOffset + GetMaxOffset(listPtr)/2;
+ }
+
+ Tk_DrawChars(listPtr->display, pixmap, gc, listPtr->tkfont,
+ stringRep, stringLen, x, y);
+
+ /*
+ * If this is the active element, apply the activestyle to it.
+ */
+
+ if ((i == listPtr->active) && (listPtr->flags & GOT_FOCUS)) {
+ if (listPtr->activeStyle == ACTIVE_STYLE_UNDERLINE) {
+ /*
+ * Underline the text.
+ */
+
+ Tk_UnderlineChars(listPtr->display, pixmap, gc,
+ listPtr->tkfont, stringRep, x, y, 0, stringLen);
+ } else if (listPtr->activeStyle == ACTIVE_STYLE_DOTBOX) {
+#ifdef _WIN32
+ /*
+ * This provides for exact default look and feel on Windows.
+ */
+
+ TkWinDCState state;
+ HDC dc;
+ RECT rect;
+
+ dc = TkWinGetDrawableDC(listPtr->display, pixmap, &state);
+ rect.left = listPtr->inset;
+ rect.top = ((i - listPtr->topIndex) * listPtr->lineHeight)
+ + listPtr->inset;
+ rect.right = rect.left + width;
+ rect.bottom = rect.top + listPtr->lineHeight;
+ DrawFocusRect(dc, &rect);
+ TkWinReleaseDrawableDC(pixmap, dc, &state);
+#else /* !_WIN32 */
+ /*
+ * Draw a dotted box around the text.
+ */
+
+ x = listPtr->inset;
+ y = ((i - listPtr->topIndex) * listPtr->lineHeight)
+ + listPtr->inset;
+ width = Tk_Width(tkwin) - 2*listPtr->inset - 1;
+
+ gcValues.line_style = LineOnOffDash;
+ gcValues.line_width = listPtr->selBorderWidth;
+ if (gcValues.line_width <= 0) {
+ gcValues.line_width = 1;
+ }
+ gcValues.dash_offset = 0;
+ gcValues.dashes = 1;
+
+ /*
+ * You would think the XSetDashes was necessary, but it
+ * appears that the default dotting for just saying we want
+ * dashes appears to work correctly.
+ static char dashList[] = { 1 };
+ static int dashLen = sizeof(dashList);
+ XSetDashes(listPtr->display, gc, 0, dashList, dashLen);
+ */
+
+ mask = GCLineWidth | GCLineStyle | GCDashList | GCDashOffset;
+ XChangeGC(listPtr->display, gc, mask, &gcValues);
+ XDrawRectangle(listPtr->display, pixmap, gc, x, y,
+ (unsigned) width, (unsigned) listPtr->lineHeight - 1);
+ if (!freeGC) {
+ /*
+ * Don't bother changing if it is about to be freed.
+ */
+
+ gcValues.line_style = LineSolid;
+ XChangeGC(listPtr->display, gc, GCLineStyle, &gcValues);
+ }
+#endif /* _WIN32 */
+ }
+ }
+
+ if (freeGC) {
+ Tk_FreeGC(listPtr->display, gc);
+ }
+ }
+
+ /*
+ * Redraw the border for the listbox to make sure that it's on top of any
+ * of the text of the listbox entries.
+ */
+
+ Tk_Draw3DRectangle(tkwin, pixmap, listPtr->normalBorder,
+ listPtr->highlightWidth, listPtr->highlightWidth,
+ Tk_Width(tkwin) - 2*listPtr->highlightWidth,
+ Tk_Height(tkwin) - 2*listPtr->highlightWidth,
+ listPtr->borderWidth, listPtr->relief);
+ if (listPtr->highlightWidth > 0) {
+ GC fgGC, bgGC;
+
+ bgGC = Tk_GCForColor(listPtr->highlightBgColorPtr, pixmap);
+ if (listPtr->flags & GOT_FOCUS) {
+ fgGC = Tk_GCForColor(listPtr->highlightColorPtr, pixmap);
+ TkpDrawHighlightBorder(tkwin, fgGC, bgGC,
+ listPtr->highlightWidth, pixmap);
+ } else {
+ TkpDrawHighlightBorder(tkwin, bgGC, bgGC,
+ listPtr->highlightWidth, pixmap);
+ }
+ }
+#ifndef TK_NO_DOUBLE_BUFFERING
+ XCopyArea(listPtr->display, pixmap, Tk_WindowId(tkwin),
+ listPtr->textGC, 0, 0, (unsigned) Tk_Width(tkwin),
+ (unsigned) Tk_Height(tkwin), 0, 0);
+ Tk_FreePixmap(listPtr->display, pixmap);
+#endif /* TK_NO_DOUBLE_BUFFERING */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListboxComputeGeometry --
+ *
+ * This procedure is invoked to recompute geometry information such as
+ * the sizes of the elements and the overall dimensions desired for the
+ * listbox.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Geometry information is updated and a new requested size is registered
+ * for the widget. Internal border and gridding information is also set.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ListboxComputeGeometry(
+ Listbox *listPtr, /* Listbox whose geometry is to be
+ * recomputed. */
+ int fontChanged, /* Non-zero means the font may have changed so
+ * per-element width information also has to
+ * be computed. */
+ int maxIsStale, /* Non-zero means the "maxWidth" field may no
+ * longer be up-to-date and must be
+ * recomputed. If fontChanged is 1 then this
+ * must be 1. */
+ int updateGrid) /* Non-zero means call Tk_SetGrid or
+ * Tk_UnsetGrid to update gridding for the
+ * window. */
+{
+ int width, height, pixelWidth, pixelHeight, textLength, i, result;
+ Tk_FontMetrics fm;
+ Tcl_Obj *element;
+ const char *text;
+
+ if (fontChanged || maxIsStale) {
+ listPtr->xScrollUnit = Tk_TextWidth(listPtr->tkfont, "0", 1);
+ if (listPtr->xScrollUnit == 0) {
+ listPtr->xScrollUnit = 1;
+ }
+ listPtr->maxWidth = 0;
+ for (i = 0; i < listPtr->nElements; i++) {
+ /*
+ * Compute the pixel width of the current element.
+ */
+
+ result = Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i,
+ &element);
+ if (result != TCL_OK) {
+ continue;
+ }
+ text = Tcl_GetStringFromObj(element, &textLength);
+ Tk_GetFontMetrics(listPtr->tkfont, &fm);
+ pixelWidth = Tk_TextWidth(listPtr->tkfont, text, textLength);
+ if (pixelWidth > listPtr->maxWidth) {
+ listPtr->maxWidth = pixelWidth;
+ }
+ }
+ }
+
+ Tk_GetFontMetrics(listPtr->tkfont, &fm);
+ listPtr->lineHeight = fm.linespace + 1 + 2*listPtr->selBorderWidth;
+ width = listPtr->width;
+ if (width <= 0) {
+ width = (listPtr->maxWidth + listPtr->xScrollUnit - 1)
+ / listPtr->xScrollUnit;
+ if (width < 1) {
+ width = 1;
+ }
+ }
+ pixelWidth = width*listPtr->xScrollUnit + 2*listPtr->inset
+ + 2*listPtr->selBorderWidth;
+ height = listPtr->height;
+ if (listPtr->height <= 0) {
+ height = listPtr->nElements;
+ if (height < 1) {
+ height = 1;
+ }
+ }
+ pixelHeight = height*listPtr->lineHeight + 2*listPtr->inset;
+ Tk_GeometryRequest(listPtr->tkwin, pixelWidth, pixelHeight);
+ Tk_SetInternalBorder(listPtr->tkwin, listPtr->inset);
+ if (updateGrid) {
+ if (listPtr->setGrid) {
+ Tk_SetGrid(listPtr->tkwin, width, height, listPtr->xScrollUnit,
+ listPtr->lineHeight);
+ } else {
+ Tk_UnsetGrid(listPtr->tkwin);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListboxInsertSubCmd --
+ *
+ * This procedure is invoked to handle the listbox "insert" subcommand.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * New elements are added to the listbox pointed to by listPtr; a refresh
+ * callback is registered for the listbox.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ListboxInsertSubCmd(
+ register Listbox *listPtr, /* Listbox that is to get the new elements. */
+ int index, /* Add the new elements before this
+ * element. */
+ int objc, /* Number of new elements to add. */
+ Tcl_Obj *const objv[]) /* New elements (one per entry). */
+{
+ int i, oldMaxWidth, pixelWidth, result, length;
+ Tcl_Obj *newListObj;
+ const char *stringRep;
+
+ oldMaxWidth = listPtr->maxWidth;
+ for (i = 0; i < objc; i++) {
+ /*
+ * Check if any of the new elements are wider than the current widest;
+ * if so, update our notion of "widest."
+ */
+
+ stringRep = Tcl_GetStringFromObj(objv[i], &length);
+ pixelWidth = Tk_TextWidth(listPtr->tkfont, stringRep, length);
+ if (pixelWidth > listPtr->maxWidth) {
+ listPtr->maxWidth = pixelWidth;
+ }
+ }
+
+ /*
+ * Adjust selection and attribute information for every index after the
+ * first index.
+ */
+
+ MigrateHashEntries(listPtr->selection, index, listPtr->nElements-1, objc);
+ MigrateHashEntries(listPtr->itemAttrTable, index, listPtr->nElements-1,
+ objc);
+
+ /*
+ * If the object is shared, duplicate it before writing to it.
+ */
+
+ if (Tcl_IsShared(listPtr->listObj)) {
+ newListObj = Tcl_DuplicateObj(listPtr->listObj);
+ } else {
+ newListObj = listPtr->listObj;
+ }
+ result = Tcl_ListObjReplace(listPtr->interp, newListObj, index, 0,
+ objc, objv);
+ if (result != TCL_OK) {
+ return result;
+ }
+
+ /*
+ * Replace the current object and set attached listvar, if any. This may
+ * error if listvar points to a var in a deleted namespace, but we ignore
+ * those errors. If the namespace is recreated, it will auto-sync with the
+ * current value. [Bug 1424513]
+ */
+
+ Tcl_IncrRefCount(newListObj);
+ Tcl_DecrRefCount(listPtr->listObj);
+ listPtr->listObj = newListObj;
+ if (listPtr->listVarName != NULL) {
+ Tcl_SetVar2Ex(listPtr->interp, listPtr->listVarName, NULL,
+ listPtr->listObj, TCL_GLOBAL_ONLY);
+ }
+
+ /*
+ * Get the new list length.
+ */
+
+ Tcl_ListObjLength(listPtr->interp, listPtr->listObj, &listPtr->nElements);
+
+ /*
+ * Update the "special" indices (anchor, topIndex, active) to account for
+ * the renumbering that just occurred. Then arrange for the new
+ * information to be displayed.
+ */
+
+ if (index <= listPtr->selectAnchor) {
+ listPtr->selectAnchor += objc;
+ }
+ if (index < listPtr->topIndex) {
+ listPtr->topIndex += objc;
+ }
+ if (index <= listPtr->active) {
+ listPtr->active += objc;
+ if ((listPtr->active >= listPtr->nElements) &&
+ (listPtr->nElements > 0)) {
+ listPtr->active = listPtr->nElements-1;
+ }
+ }
+ listPtr->flags |= UPDATE_V_SCROLLBAR;
+ if (listPtr->maxWidth != oldMaxWidth) {
+ listPtr->flags |= UPDATE_H_SCROLLBAR;
+ }
+ ListboxComputeGeometry(listPtr, 0, 0, 0);
+ EventuallyRedrawRange(listPtr, index, listPtr->nElements-1);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListboxDeleteSubCmd --
+ *
+ * Process a listbox "delete" subcommand by removing one or more elements
+ * from a listbox widget.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * The listbox will be modified and (eventually) redisplayed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ListboxDeleteSubCmd(
+ register Listbox *listPtr, /* Listbox widget to modify. */
+ int first, /* Index of first element to delete. */
+ int last) /* Index of last element to delete. */
+{
+ int count, i, widthChanged, length, result, pixelWidth;
+ Tcl_Obj *newListObj, *element;
+ const char *stringRep;
+ Tcl_HashEntry *entry;
+
+ /*
+ * Adjust the range to fit within the existing elements of the listbox,
+ * and make sure there's something to delete.
+ */
+
+ if (first < 0) {
+ first = 0;
+ }
+ if (last >= listPtr->nElements) {
+ last = listPtr->nElements-1;
+ }
+ count = last + 1 - first;
+ if (count <= 0) {
+ return TCL_OK;
+ }
+
+ /*
+ * Foreach deleted index we must:
+ * a) remove selection information,
+ * b) check the width of the element; if it is equal to the max, set
+ * widthChanged to 1, because it may be the only element with that
+ * width.
+ */
+
+ widthChanged = 0;
+ for (i = first; i <= last; i++) {
+ /*
+ * Remove selection information.
+ */
+
+ entry = Tcl_FindHashEntry(listPtr->selection, KEY(i));
+ if (entry != NULL) {
+ listPtr->numSelected--;
+ Tcl_DeleteHashEntry(entry);
+ }
+
+ entry = Tcl_FindHashEntry(listPtr->itemAttrTable, KEY(i));
+ if (entry != NULL) {
+ ckfree(Tcl_GetHashValue(entry));
+ Tcl_DeleteHashEntry(entry);
+ }
+
+ /*
+ * Check width of the element. We only have to check if widthChanged
+ * has not already been set to 1, because we only need one maxWidth
+ * element to disappear for us to have to recompute the width.
+ */
+
+ if (widthChanged == 0) {
+ Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i, &element);
+ stringRep = Tcl_GetStringFromObj(element, &length);
+ pixelWidth = Tk_TextWidth(listPtr->tkfont, stringRep, length);
+ if (pixelWidth == listPtr->maxWidth) {
+ widthChanged = 1;
+ }
+ }
+ }
+
+ /*
+ * Adjust selection and attribute info for indices after lastIndex.
+ */
+
+ MigrateHashEntries(listPtr->selection, last+1,
+ listPtr->nElements-1, count*-1);
+ MigrateHashEntries(listPtr->itemAttrTable, last+1,
+ listPtr->nElements-1, count*-1);
+
+ /*
+ * Delete the requested elements.
+ */
+
+ if (Tcl_IsShared(listPtr->listObj)) {
+ newListObj = Tcl_DuplicateObj(listPtr->listObj);
+ } else {
+ newListObj = listPtr->listObj;
+ }
+ result = Tcl_ListObjReplace(listPtr->interp,
+ newListObj, first, count, 0, NULL);
+ if (result != TCL_OK) {
+ return result;
+ }
+
+ /*
+ * Replace the current object and set attached listvar, if any. This may
+ * error if listvar points to a var in a deleted namespace, but we ignore
+ * those errors. If the namespace is recreated, it will auto-sync with the
+ * current value. [Bug 1424513]
+ */
+
+ Tcl_IncrRefCount(newListObj);
+ Tcl_DecrRefCount(listPtr->listObj);
+ listPtr->listObj = newListObj;
+ if (listPtr->listVarName != NULL) {
+ Tcl_SetVar2Ex(listPtr->interp, listPtr->listVarName, NULL,
+ listPtr->listObj, TCL_GLOBAL_ONLY);
+ }
+
+ /*
+ * Get the new list length.
+ */
+
+ Tcl_ListObjLength(listPtr->interp, listPtr->listObj, &listPtr->nElements);
+
+ /*
+ * Update the selection and viewing information to reflect the change in
+ * the element numbering, and redisplay to slide information up over the
+ * elements that were deleted.
+ */
+
+ if (first <= listPtr->selectAnchor) {
+ listPtr->selectAnchor -= count;
+ if (listPtr->selectAnchor < first) {
+ listPtr->selectAnchor = first;
+ }
+ }
+ if (first <= listPtr->topIndex) {
+ listPtr->topIndex -= count;
+ if (listPtr->topIndex < first) {
+ listPtr->topIndex = first;
+ }
+ }
+ if (listPtr->topIndex > (listPtr->nElements - listPtr->fullLines)) {
+ listPtr->topIndex = listPtr->nElements - listPtr->fullLines;
+ if (listPtr->topIndex < 0) {
+ listPtr->topIndex = 0;
+ }
+ }
+ if (listPtr->active > last) {
+ listPtr->active -= count;
+ } else if (listPtr->active >= first) {
+ listPtr->active = first;
+ if ((listPtr->active >= listPtr->nElements) &&
+ (listPtr->nElements > 0)) {
+ listPtr->active = listPtr->nElements-1;
+ }
+ }
+ listPtr->flags |= UPDATE_V_SCROLLBAR;
+ ListboxComputeGeometry(listPtr, 0, widthChanged, 0);
+ if (widthChanged) {
+ listPtr->flags |= UPDATE_H_SCROLLBAR;
+ }
+ EventuallyRedrawRange(listPtr, first, listPtr->nElements-1);
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ListboxEventProc --
+ *
+ * This procedure is invoked by the Tk dispatcher for various events on
+ * listboxes.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * When the window gets deleted, internal structures get cleaned up. When
+ * it gets exposed, it is redisplayed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ListboxEventProc(
+ ClientData clientData, /* Information about window. */
+ XEvent *eventPtr) /* Information about event. */
+{
+ Listbox *listPtr = clientData;
+
+ if (eventPtr->type == Expose) {
+ EventuallyRedrawRange(listPtr,
+ NearestListboxElement(listPtr, eventPtr->xexpose.y),
+ NearestListboxElement(listPtr, eventPtr->xexpose.y
+ + eventPtr->xexpose.height));
+ } else if (eventPtr->type == DestroyNotify) {
+ if (!(listPtr->flags & LISTBOX_DELETED)) {
+ listPtr->flags |= LISTBOX_DELETED;
+ Tcl_DeleteCommandFromToken(listPtr->interp, listPtr->widgetCmd);
+ if (listPtr->setGrid) {
+ Tk_UnsetGrid(listPtr->tkwin);
+ }
+ if (listPtr->flags & REDRAW_PENDING) {
+ Tcl_CancelIdleCall(DisplayListbox, clientData);
+ }
+ Tcl_EventuallyFree(clientData, (Tcl_FreeProc *) DestroyListbox);
+ }
+ } else if (eventPtr->type == ConfigureNotify) {
+ int vertSpace;
+
+ vertSpace = Tk_Height(listPtr->tkwin) - 2*listPtr->inset;
+ listPtr->fullLines = vertSpace / listPtr->lineHeight;
+ if ((listPtr->fullLines*listPtr->lineHeight) < vertSpace) {
+ listPtr->partialLine = 1;
+ } else {
+ listPtr->partialLine = 0;
+ }
+ listPtr->flags |= UPDATE_V_SCROLLBAR|UPDATE_H_SCROLLBAR;
+ ChangeListboxView(listPtr, listPtr->topIndex);
+ ChangeListboxOffset(listPtr, listPtr->xOffset);
+
+ /*
+ * Redraw the whole listbox. It's hard to tell what needs to be
+ * redrawn (e.g. if the listbox has shrunk then we may only need to
+ * redraw the borders), so just redraw everything for safety.
+ */
+
+ EventuallyRedrawRange(listPtr, 0, listPtr->nElements-1);
+ } else if (eventPtr->type == FocusIn) {
+ if (eventPtr->xfocus.detail != NotifyInferior) {
+ listPtr->flags |= GOT_FOCUS;
+ EventuallyRedrawRange(listPtr, 0, listPtr->nElements-1);
+ }
+ } else if (eventPtr->type == FocusOut) {
+ if (eventPtr->xfocus.detail != NotifyInferior) {
+ listPtr->flags &= ~GOT_FOCUS;
+ EventuallyRedrawRange(listPtr, 0, listPtr->nElements-1);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListboxCmdDeletedProc --
+ *
+ * This procedure is invoked when a widget command is deleted. If the
+ * widget isn't already in the process of being destroyed, this command
+ * destroys it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The widget is destroyed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ListboxCmdDeletedProc(
+ ClientData clientData) /* Pointer to widget record for widget. */
+{
+ Listbox *listPtr = clientData;
+
+ /*
+ * This procedure could be invoked either because the window was destroyed
+ * and the command was then deleted (in which case tkwin is NULL) or
+ * because the command was deleted, and then this procedure destroys the
+ * widget.
+ */
+
+ if (!(listPtr->flags & LISTBOX_DELETED)) {
+ Tk_DestroyWindow(listPtr->tkwin);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * GetListboxIndex --
+ *
+ * Parse an index into a listbox and return either its value or an error.
+ *
+ * Results:
+ * A standard Tcl result. If all went well, then *indexPtr is filled in
+ * with the index (into listPtr) corresponding to string. Otherwise an
+ * error message is left in the interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+GetListboxIndex(
+ Tcl_Interp *interp, /* For error messages. */
+ Listbox *listPtr, /* Listbox for which the index is being
+ * specified. */
+ Tcl_Obj *indexObj, /* Specifies an element in the listbox. */
+ int endIsSize, /* If 1, "end" refers to the number of entries
+ * in the listbox. If 0, "end" refers to 1
+ * less than the number of entries. */
+ int *indexPtr) /* Where to store converted index. */
+{
+ int result, index;
+ const char *stringRep;
+
+ /*
+ * First see if the index is one of the named indices.
+ */
+
+ result = Tcl_GetIndexFromObj(NULL, indexObj, indexNames, "", 0, &index);
+ if (result == TCL_OK) {
+ switch (index) {
+ case INDEX_ACTIVE:
+ /* "active" index */
+ *indexPtr = listPtr->active;
+ break;
+ case INDEX_ANCHOR:
+ /* "anchor" index */
+ *indexPtr = listPtr->selectAnchor;
+ break;
+ case INDEX_END:
+ /* "end" index */
+ if (endIsSize) {
+ *indexPtr = listPtr->nElements;
+ } else {
+ *indexPtr = listPtr->nElements - 1;
+ }
+ break;
+ }
+ return TCL_OK;
+ }
+
+ /*
+ * The index didn't match any of the named indices; maybe it's an @x,y
+ */
+
+ stringRep = Tcl_GetString(indexObj);
+ if (stringRep[0] == '@') {
+
+ /*
+ * @x,y index
+ */
+
+ int y;
+ const char *start;
+ char *end;
+
+ start = stringRep + 1;
+ y = strtol(start, &end, 0);
+ if ((start == end) || (*end != ',')) {
+ goto badIndex;
+ }
+ start = end+1;
+ y = strtol(start, &end, 0);
+ if ((start == end) || (*end != '\0')) {
+ goto badIndex;
+ }
+ *indexPtr = NearestListboxElement(listPtr, y);
+ return TCL_OK;
+ }
+
+ /*
+ * Maybe the index is just an integer.
+ */
+
+ if (Tcl_GetIntFromObj(interp, indexObj, indexPtr) == TCL_OK) {
+ return TCL_OK;
+ }
+
+ /*
+ * Everything failed, nothing matched. Throw up an error message.
+ */
+
+ badIndex:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad listbox index \"%s\": must be active, anchor, end, @x,y,"
+ " or a number", Tcl_GetString(indexObj)));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "LISTBOX_INDEX", NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ChangeListboxView --
+ *
+ * Change the view on a listbox widget so that a given element is
+ * displayed at the top.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * What's displayed on the screen is changed. If there is a scrollbar
+ * associated with this widget, then the scrollbar is instructed to
+ * change its display too.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ChangeListboxView(
+ register Listbox *listPtr, /* Information about widget. */
+ int index) /* Index of element in listPtr that should now
+ * appear at the top of the listbox. */
+{
+ if (index >= (listPtr->nElements - listPtr->fullLines)) {
+ index = listPtr->nElements - listPtr->fullLines;
+ }
+ if (index < 0) {
+ index = 0;
+ }
+ if (listPtr->topIndex != index) {
+ listPtr->topIndex = index;
+ EventuallyRedrawRange(listPtr, 0, listPtr->nElements-1);
+ listPtr->flags |= UPDATE_V_SCROLLBAR;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ChangListboxOffset --
+ *
+ * Change the horizontal offset for a listbox.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The listbox may be redrawn to reflect its new horizontal offset.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ChangeListboxOffset(
+ register Listbox *listPtr, /* Information about widget. */
+ int offset) /* Desired new "xOffset" for listbox. */
+{
+ int maxOffset;
+
+ /*
+ * Make sure that the new offset is within the allowable range, and round
+ * it off to an even multiple of xScrollUnit.
+ *
+ * Add half a scroll unit to do entry/text-like synchronization. [Bug
+ * #225025]
+ */
+
+ offset += listPtr->xScrollUnit / 2;
+ maxOffset = GetMaxOffset(listPtr);
+ if (offset > maxOffset) {
+ offset = maxOffset;
+ }
+ if (offset < 0) {
+ offset = 0;
+ }
+ offset -= offset % listPtr->xScrollUnit;
+ if (offset != listPtr->xOffset) {
+ listPtr->xOffset = offset;
+ listPtr->flags |= UPDATE_H_SCROLLBAR;
+ EventuallyRedrawRange(listPtr, 0, listPtr->nElements-1);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListboxScanTo --
+ *
+ * Given a point (presumably of the curent mouse location) drag the view
+ * in the window to implement the scan operation.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The view in the window may change.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ListboxScanTo(
+ register Listbox *listPtr, /* Information about widget. */
+ int x, /* X-coordinate to use for scan operation. */
+ int y) /* Y-coordinate to use for scan operation. */
+{
+ int newTopIndex, newOffset, maxIndex, maxOffset;
+
+ maxIndex = listPtr->nElements - listPtr->fullLines;
+ maxOffset = GetMaxOffset(listPtr);
+
+ /*
+ * Compute new top line for screen by amplifying the difference between
+ * the current position and the place where the scan started (the "mark"
+ * position). If we run off the top or bottom of the list, then reset the
+ * mark point so that the current position continues to correspond to the
+ * edge of the window. This means that the picture will start dragging as
+ * soon as the mouse reverses direction (without this reset, might have to
+ * slide mouse a long ways back before the picture starts moving again).
+ */
+
+ newTopIndex = listPtr->scanMarkYIndex
+ - (10*(y - listPtr->scanMarkY)) / listPtr->lineHeight;
+ if (newTopIndex > maxIndex) {
+ newTopIndex = listPtr->scanMarkYIndex = maxIndex;
+ listPtr->scanMarkY = y;
+ } else if (newTopIndex < 0) {
+ newTopIndex = listPtr->scanMarkYIndex = 0;
+ listPtr->scanMarkY = y;
+ }
+ ChangeListboxView(listPtr, newTopIndex);
+
+ /*
+ * Compute new left edge for display in a similar fashion by amplifying
+ * the difference between the current position and the place where the
+ * scan started.
+ */
+
+ newOffset = listPtr->scanMarkXOffset - 10*(x - listPtr->scanMarkX);
+ if (newOffset > maxOffset) {
+ newOffset = listPtr->scanMarkXOffset = maxOffset;
+ listPtr->scanMarkX = x;
+ } else if (newOffset < 0) {
+ newOffset = listPtr->scanMarkXOffset = 0;
+ listPtr->scanMarkX = x;
+ }
+ ChangeListboxOffset(listPtr, newOffset);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NearestListboxElement --
+ *
+ * Given a y-coordinate inside a listbox, compute the index of the
+ * element under that y-coordinate (or closest to that y-coordinate).
+ *
+ * Results:
+ * The return value is an index of an element of listPtr. If listPtr has
+ * no elements, then 0 is always returned.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+NearestListboxElement(
+ register Listbox *listPtr, /* Information about widget. */
+ int y) /* Y-coordinate in listPtr's window. */
+{
+ int index;
+
+ index = (y - listPtr->inset) / listPtr->lineHeight;
+ if (index >= (listPtr->fullLines + listPtr->partialLine)) {
+ index = listPtr->fullLines + listPtr->partialLine - 1;
+ }
+ if (index < 0) {
+ index = 0;
+ }
+ index += listPtr->topIndex;
+ if (index >= listPtr->nElements) {
+ index = listPtr->nElements-1;
+ }
+ return index;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListboxSelect --
+ *
+ * Select or deselect one or more elements in a listbox..
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * All of the elements in the range between first and last are marked as
+ * either selected or deselected, depending on the "select" argument. Any
+ * items whose state changes are redisplayed. The selection is claimed
+ * from X when the number of selected elements changes from zero to
+ * non-zero.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ListboxSelect(
+ register Listbox *listPtr, /* Information about widget. */
+ int first, /* Index of first element to select or
+ * deselect. */
+ int last, /* Index of last element to select or
+ * deselect. */
+ int select) /* 1 means select items, 0 means deselect
+ * them. */
+{
+ int i, firstRedisplay, oldCount, isNew;
+ Tcl_HashEntry *entry;
+
+ if (last < first) {
+ i = first;
+ first = last;
+ last = i;
+ }
+ if ((last < 0) || (first >= listPtr->nElements)) {
+ return TCL_OK;
+ }
+ if (first < 0) {
+ first = 0;
+ }
+ if (last >= listPtr->nElements) {
+ last = listPtr->nElements - 1;
+ }
+ oldCount = listPtr->numSelected;
+ firstRedisplay = -1;
+
+ /*
+ * For each index in the range, find it in our selection hash table. If
+ * it's not there but should be, add it. If it's there but shouldn't be,
+ * remove it.
+ */
+
+ for (i = first; i <= last; i++) {
+ entry = Tcl_FindHashEntry(listPtr->selection, KEY(i));
+ if (entry != NULL) {
+ if (!select) {
+ Tcl_DeleteHashEntry(entry);
+ listPtr->numSelected--;
+ if (firstRedisplay < 0) {
+ firstRedisplay = i;
+ }
+ }
+ } else {
+ if (select) {
+ entry = Tcl_CreateHashEntry(listPtr->selection, KEY(i),
+ &isNew);
+ Tcl_SetHashValue(entry, NULL);
+ listPtr->numSelected++;
+ if (firstRedisplay < 0) {
+ firstRedisplay = i;
+ }
+ }
+ }
+ }
+
+ if (firstRedisplay >= 0) {
+ EventuallyRedrawRange(listPtr, first, last);
+ }
+ if ((oldCount == 0) && (listPtr->numSelected > 0)
+ && (listPtr->exportSelection)
+ && (!Tcl_IsSafe(listPtr->interp))) {
+ Tk_OwnSelection(listPtr->tkwin, XA_PRIMARY,
+ ListboxLostSelection, listPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListboxFetchSelection --
+ *
+ * This procedure is called back by Tk when the selection is requested by
+ * someone. It returns part or all of the selection in a buffer provided
+ * by the caller.
+ *
+ * Results:
+ * The return value is the number of non-NULL bytes stored at buffer.
+ * Buffer is filled (or partially filled) with a NULL-terminated string
+ * containing part or all of the selection, as given by offset and
+ * maxBytes. The selection is returned as a Tcl list with one list
+ * element for each element in the listbox.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ListboxFetchSelection(
+ ClientData clientData, /* Information about listbox widget. */
+ int offset, /* Offset within selection of first byte to be
+ * returned. */
+ char *buffer, /* Location in which to place selection. */
+ int maxBytes) /* Maximum number of bytes to place at buffer,
+ * not including terminating NULL
+ * character. */
+{
+ register Listbox *listPtr = clientData;
+ Tcl_DString selection;
+ int length, count, needNewline, stringLen, i;
+ Tcl_Obj *curElement;
+ const char *stringRep;
+ Tcl_HashEntry *entry;
+
+ if ((!listPtr->exportSelection) || Tcl_IsSafe(listPtr->interp)) {
+ return -1;
+ }
+
+ /*
+ * Use a dynamic string to accumulate the contents of the selection.
+ */
+
+ needNewline = 0;
+ Tcl_DStringInit(&selection);
+ for (i = 0; i < listPtr->nElements; i++) {
+ entry = Tcl_FindHashEntry(listPtr->selection, KEY(i));
+ if (entry != NULL) {
+ if (needNewline) {
+ Tcl_DStringAppend(&selection, "\n", 1);
+ }
+ Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i,
+ &curElement);
+ stringRep = Tcl_GetStringFromObj(curElement, &stringLen);
+ Tcl_DStringAppend(&selection, stringRep, stringLen);
+ needNewline = 1;
+ }
+ }
+
+ length = Tcl_DStringLength(&selection);
+ if (length == 0) {
+ return -1;
+ }
+
+ /*
+ * Copy the requested portion of the selection to the buffer.
+ */
+
+ count = length - offset;
+ if (count <= 0) {
+ count = 0;
+ } else {
+ if (count > maxBytes) {
+ count = maxBytes;
+ }
+ memcpy(buffer, Tcl_DStringValue(&selection) + offset, (size_t) count);
+ }
+ buffer[count] = '\0';
+ Tcl_DStringFree(&selection);
+ return count;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListboxLostSelection --
+ *
+ * This procedure is called back by Tk when the selection is grabbed away
+ * from a listbox widget.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The existing selection is unhighlighted, and the window is marked as
+ * not containing a selection.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ListboxLostSelection(
+ ClientData clientData) /* Information about listbox widget. */
+{
+ register Listbox *listPtr = clientData;
+
+ if ((listPtr->exportSelection) && (!Tcl_IsSafe(listPtr->interp))
+ && (listPtr->nElements > 0)) {
+ ListboxSelect(listPtr, 0, listPtr->nElements-1, 0);
+ GenerateListboxSelectEvent(listPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GenerateListboxSelectEvent --
+ *
+ * Send an event that the listbox selection was updated. This is
+ * equivalent to event generate $listboxWidget <<ListboxSelect>>
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * Any side effect possible, depending on bindings to this event.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GenerateListboxSelectEvent(
+ Listbox *listPtr) /* Information about widget. */
+{
+ TkSendVirtualEvent(listPtr->tkwin, "ListboxSelect", NULL);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EventuallyRedrawRange --
+ *
+ * Ensure that a given range of elements is eventually redrawn on the
+ * display (if those elements in fact appear on the display).
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Information gets redisplayed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+EventuallyRedrawRange(
+ register Listbox *listPtr, /* Information about widget. */
+ int first, /* Index of first element in list that needs
+ * to be redrawn. */
+ int last) /* Index of last element in list that needs to
+ * be redrawn. May be less than first; these
+ * just bracket a range. */
+{
+ /*
+ * We don't have to register a redraw callback if one is already pending,
+ * or if the window doesn't exist, or if the window isn't mapped.
+ */
+
+ if ((listPtr->flags & REDRAW_PENDING)
+ || (listPtr->flags & LISTBOX_DELETED)
+ || !Tk_IsMapped(listPtr->tkwin)) {
+ return;
+ }
+ listPtr->flags |= REDRAW_PENDING;
+ Tcl_DoWhenIdle(DisplayListbox, listPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListboxUpdateVScrollbar --
+ *
+ * This procedure is invoked whenever information has changed in a
+ * listbox in a way that would invalidate a vertical scrollbar display.
+ * If there is an associated scrollbar, then this command updates it by
+ * invoking a Tcl command.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A Tcl command is invoked, and an additional command may be invoked to
+ * process errors in the command.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ListboxUpdateVScrollbar(
+ register Listbox *listPtr) /* Information about widget. */
+{
+ char firstStr[TCL_DOUBLE_SPACE], lastStr[TCL_DOUBLE_SPACE];
+ double first, last;
+ int result;
+ Tcl_Interp *interp;
+ Tcl_DString buf;
+
+ if (listPtr->yScrollCmd == NULL) {
+ return;
+ }
+ if (listPtr->nElements == 0) {
+ first = 0.0;
+ last = 1.0;
+ } else {
+ first = listPtr->topIndex / (double) listPtr->nElements;
+ last = (listPtr->topIndex + listPtr->fullLines)
+ / (double) listPtr->nElements;
+ if (last > 1.0) {
+ last = 1.0;
+ }
+ }
+ Tcl_PrintDouble(NULL, first, firstStr);
+ Tcl_PrintDouble(NULL, last, lastStr);
+
+ /*
+ * We must hold onto the interpreter from the listPtr because the data at
+ * listPtr might be freed as a result of the Tcl_VarEval.
+ */
+
+ interp = listPtr->interp;
+ Tcl_Preserve(interp);
+ Tcl_DStringInit(&buf);
+ Tcl_DStringAppend(&buf, listPtr->yScrollCmd, -1);
+ Tcl_DStringAppend(&buf, " ", -1);
+ Tcl_DStringAppend(&buf, firstStr, -1);
+ Tcl_DStringAppend(&buf, " ", -1);
+ Tcl_DStringAppend(&buf, lastStr, -1);
+ result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0);
+ Tcl_DStringFree(&buf);
+ if (result != TCL_OK) {
+ Tcl_AddErrorInfo(interp,
+ "\n (vertical scrolling command executed by listbox)");
+ Tcl_BackgroundException(interp, result);
+ }
+ Tcl_Release(interp);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListboxUpdateHScrollbar --
+ *
+ * This procedure is invoked whenever information has changed in a
+ * listbox in a way that would invalidate a horizontal scrollbar display.
+ * If there is an associated horizontal scrollbar, then this command
+ * updates it by invoking a Tcl command.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A Tcl command is invoked, and an additional command may be invoked to
+ * process errors in the command.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ListboxUpdateHScrollbar(
+ register Listbox *listPtr) /* Information about widget. */
+{
+ char firstStr[TCL_DOUBLE_SPACE], lastStr[TCL_DOUBLE_SPACE];
+ int result, windowWidth;
+ double first, last;
+ Tcl_Interp *interp;
+ Tcl_DString buf;
+
+ if (listPtr->xScrollCmd == NULL) {
+ return;
+ }
+
+ windowWidth = Tk_Width(listPtr->tkwin)
+ - 2*(listPtr->inset + listPtr->selBorderWidth);
+ if (listPtr->maxWidth == 0) {
+ first = 0;
+ last = 1.0;
+ } else {
+ first = listPtr->xOffset / (double) listPtr->maxWidth;
+ last = (listPtr->xOffset + windowWidth) / (double) listPtr->maxWidth;
+ if (last > 1.0) {
+ last = 1.0;
+ }
+ }
+ Tcl_PrintDouble(NULL, first, firstStr);
+ Tcl_PrintDouble(NULL, last, lastStr);
+
+ /*
+ * We must hold onto the interpreter because the data referred to at
+ * listPtr might be freed as a result of the call to Tcl_VarEval.
+ */
+
+ interp = listPtr->interp;
+ Tcl_Preserve(interp);
+ Tcl_DStringInit(&buf);
+ Tcl_DStringAppend(&buf, listPtr->xScrollCmd, -1);
+ Tcl_DStringAppend(&buf, " ", -1);
+ Tcl_DStringAppend(&buf, firstStr, -1);
+ Tcl_DStringAppend(&buf, " ", -1);
+ Tcl_DStringAppend(&buf, lastStr, -1);
+ result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0);
+ Tcl_DStringFree(&buf);
+ if (result != TCL_OK) {
+ Tcl_AddErrorInfo(interp,
+ "\n (horizontal scrolling command executed by listbox)");
+ Tcl_BackgroundException(interp, result);
+ }
+ Tcl_Release(interp);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListboxListVarProc --
+ *
+ * Called whenever the trace on the listbox list var fires.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static char *
+ListboxListVarProc(
+ ClientData clientData, /* Information about button. */
+ Tcl_Interp *interp, /* Interpreter containing variable. */
+ const char *name1, /* Not used. */
+ const char *name2, /* Not used. */
+ int flags) /* Information about what happened. */
+{
+ Listbox *listPtr = clientData;
+ Tcl_Obj *oldListObj, *varListObj;
+ int oldLength, i;
+ Tcl_HashEntry *entry;
+
+ /*
+ * Bwah hahahaha! Puny mortal, you can't unset a -listvar'd variable!
+ */
+
+ if (flags & TCL_TRACE_UNSETS) {
+
+ if (!Tcl_InterpDeleted(interp) && listPtr->listVarName) {
+ ClientData probe = NULL;
+
+ do {
+ probe = Tcl_VarTraceInfo(interp,
+ listPtr->listVarName,
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ ListboxListVarProc, probe);
+ if (probe == (ClientData)listPtr) {
+ break;
+ }
+ } while (probe);
+ if (probe) {
+ /*
+ * We were able to fetch the unset trace for our
+ * listVarName, which means it is not unset and not
+ * the cause of this unset trace. Instead some outdated
+ * former variable must be, and we should ignore it.
+ */
+ return NULL;
+ }
+ Tcl_SetVar2Ex(interp, listPtr->listVarName, NULL,
+ listPtr->listObj, TCL_GLOBAL_ONLY);
+ Tcl_TraceVar2(interp, listPtr->listVarName,
+ NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ ListboxListVarProc, clientData);
+ return NULL;
+ }
+ } else {
+ oldListObj = listPtr->listObj;
+ varListObj = Tcl_GetVar2Ex(listPtr->interp, listPtr->listVarName,
+ NULL, TCL_GLOBAL_ONLY);
+
+ /*
+ * Make sure the new value is a good list; if it's not, disallow the
+ * change - the fact that it is a listvar means that it must always be
+ * a valid list - and return an error message.
+ */
+
+ if (Tcl_ListObjLength(listPtr->interp, varListObj, &i) != TCL_OK) {
+ Tcl_SetVar2Ex(interp, listPtr->listVarName, NULL, oldListObj,
+ TCL_GLOBAL_ONLY);
+ return (char *) "invalid listvar value";
+ }
+
+ listPtr->listObj = varListObj;
+
+ /*
+ * Incr the obj ref count so it doesn't vanish if the var is unset.
+ */
+
+ Tcl_IncrRefCount(listPtr->listObj);
+
+ /*
+ * Clean up the ref to our old list obj.
+ */
+
+ Tcl_DecrRefCount(oldListObj);
+ }
+
+ /*
+ * If the list length has decreased, then we should clean up selection and
+ * attributes information for elements past the end of the new list.
+ */
+
+ oldLength = listPtr->nElements;
+ Tcl_ListObjLength(listPtr->interp, listPtr->listObj, &listPtr->nElements);
+ if (listPtr->nElements < oldLength) {
+ for (i = listPtr->nElements; i < oldLength; i++) {
+ /*
+ * Clean up selection.
+ */
+
+ entry = Tcl_FindHashEntry(listPtr->selection, KEY(i));
+ if (entry != NULL) {
+ listPtr->numSelected--;
+ Tcl_DeleteHashEntry(entry);
+ }
+
+ /*
+ * Clean up attributes.
+ */
+
+ entry = Tcl_FindHashEntry(listPtr->itemAttrTable, KEY(i));
+ if (entry != NULL) {
+ ckfree(Tcl_GetHashValue(entry));
+ Tcl_DeleteHashEntry(entry);
+ }
+ }
+ }
+
+ if (oldLength != listPtr->nElements) {
+ listPtr->flags |= UPDATE_V_SCROLLBAR;
+ if (listPtr->topIndex > (listPtr->nElements - listPtr->fullLines)) {
+ listPtr->topIndex = listPtr->nElements - listPtr->fullLines;
+ if (listPtr->topIndex < 0) {
+ listPtr->topIndex = 0;
+ }
+ }
+ }
+
+ /*
+ * The computed maxWidth may have changed as a result of this operation.
+ * However, we don't want to recompute it every time this trace fires
+ * (imagine the user doing 1000 lappends to the listvar). Therefore, set
+ * the MAXWIDTH_IS_STALE flag, which will cause the width to be recomputed
+ * next time the list is redrawn.
+ */
+
+ listPtr->flags |= MAXWIDTH_IS_STALE;
+
+ EventuallyRedrawRange(listPtr, 0, listPtr->nElements-1);
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MigrateHashEntries --
+ *
+ * Given a hash table with entries keyed by a single integer value, move
+ * all entries in a given range by a fixed amount, so that if in the
+ * original table there was an entry with key n and the offset was i, in
+ * the new table that entry would have key n + i.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Rekeys some hash table entries.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+MigrateHashEntries(
+ Tcl_HashTable *table,
+ int first,
+ int last,
+ int offset)
+{
+ int i, isNew;
+ Tcl_HashEntry *entry;
+ ClientData clientData;
+
+ if (offset == 0) {
+ return;
+ }
+
+ /*
+ * It's more efficient to do one if/else and nest the for loops inside,
+ * although we could avoid some code duplication if we nested the if/else
+ * inside the for loops.
+ */
+
+ if (offset > 0) {
+ for (i = last; i >= first; i--) {
+ entry = Tcl_FindHashEntry(table, KEY(i));
+ if (entry != NULL) {
+ clientData = Tcl_GetHashValue(entry);
+ Tcl_DeleteHashEntry(entry);
+ entry = Tcl_CreateHashEntry(table, KEY(i + offset), &isNew);
+ Tcl_SetHashValue(entry, clientData);
+ }
+ }
+ } else {
+ for (i = first; i <= last; i++) {
+ entry = Tcl_FindHashEntry(table, KEY(i));
+ if (entry != NULL) {
+ clientData = Tcl_GetHashValue(entry);
+ Tcl_DeleteHashEntry(entry);
+ entry = Tcl_CreateHashEntry(table, KEY(i + offset), &isNew);
+ Tcl_SetHashValue(entry, clientData);
+ }
+ }
+ }
+ return;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetMaxOffset --
+ *
+ * Passing in a listbox pointer, returns the maximum offset for the box,
+ * i.e. the maximum possible horizontal scrolling value (in pixels).
+ *
+ * Results:
+ * Listbox's maxOffset.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+*/
+static int GetMaxOffset(
+ register Listbox *listPtr)
+{
+ int maxOffset;
+
+ maxOffset = listPtr->maxWidth -
+ (Tk_Width(listPtr->tkwin) - 2*listPtr->inset -
+ 2*listPtr->selBorderWidth) + listPtr->xScrollUnit - 1;
+ if (maxOffset < 0) {
+
+ /*
+ * Listbox is larger in width than its largest width item.
+ */
+
+ maxOffset = 0;
+ }
+ maxOffset -= maxOffset % listPtr->xScrollUnit;
+
+ return maxOffset;
+}
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkMacWinMenu.c b/tk8.6/generic/tkMacWinMenu.c
new file mode 100644
index 0000000..ab92fec
--- /dev/null
+++ b/tk8.6/generic/tkMacWinMenu.c
@@ -0,0 +1,146 @@
+/*
+ * tkMacWinMenu.c --
+ *
+ * This module implements the common elements of the Mac and Windows
+ * specific features of menus. This file is not used for UNIX.
+ *
+ * Copyright (c) 1996-1997 by Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkInt.h"
+#include "tkMenu.h"
+
+typedef struct {
+ int postCommandGeneration;
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+
+static int PreprocessMenu(TkMenu *menuPtr);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PreprocessMenu --
+ *
+ * The guts of the preprocessing. Recursive.
+ *
+ * Results:
+ * The return value is a standard Tcl result (errors can occur while the
+ * postcommands are being processed).
+ *
+ * Side effects:
+ * Since commands can get executed while this routine is being executed,
+ * the entire world can change.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+PreprocessMenu(
+ TkMenu *menuPtr)
+{
+ int index, result, finished;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ Tcl_Preserve(menuPtr);
+
+ /*
+ * First, let's process the post command on ourselves. If this command
+ * destroys this menu, or if there was an error, we are done.
+ */
+
+ result = TkPostCommand(menuPtr);
+ if ((result != TCL_OK) || (menuPtr->tkwin == NULL)) {
+ goto done;
+ }
+
+ /*
+ * Now, we go through structure and process all of the commands. Since the
+ * structure is changing, we stop after we do one command, and start over.
+ * When we get through without doing any, we are done.
+ */
+
+ do {
+ finished = 1;
+ for (index = 0; index < menuPtr->numEntries; index++) {
+ register TkMenuEntry *entryPtr = menuPtr->entries[index];
+
+ if ((entryPtr->type == CASCADE_ENTRY)
+ && (entryPtr->namePtr != NULL)
+ && (entryPtr->childMenuRefPtr != NULL)
+ && (entryPtr->childMenuRefPtr->menuPtr != NULL)) {
+ TkMenu *cascadeMenuPtr = entryPtr->childMenuRefPtr->menuPtr;
+
+ if (cascadeMenuPtr->postCommandGeneration !=
+ tsdPtr->postCommandGeneration) {
+ cascadeMenuPtr->postCommandGeneration =
+ tsdPtr->postCommandGeneration;
+ result = PreprocessMenu(cascadeMenuPtr);
+ if (result != TCL_OK) {
+ goto done;
+ }
+ finished = 0;
+ break;
+ }
+ }
+ }
+ } while (!finished);
+
+ done:
+ Tcl_Release(menuPtr);
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkPreprocessMenu --
+ *
+ * On the Mac and on Windows, all of the postcommand processing has to be
+ * done on the entire tree underneath the main window to be posted. This
+ * means that we have to traverse the menu tree and issue the
+ * postcommands for all of the menus that have cascades attached. Since
+ * the postcommands can change the menu structure while we are
+ * traversing, we have to be extremely careful. Basically, the idea is to
+ * traverse the structure until we succesfully process one postcommand.
+ * Then we start over, and do it again until we traverse the whole
+ * structure without processing any postcommands.
+ *
+ * We are also going to set up the cascade back pointers in here since we
+ * have to traverse the entire structure underneath the menu anyway. We
+ * can clear the postcommand marks while we do that.
+ *
+ * Results:
+ * The return value is a standard Tcl result (errors can occur while the
+ * postcommands are being processed).
+ *
+ * Side effects:
+ * Since commands can get executed while this routine is being executed,
+ * the entire world can change.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkPreprocessMenu(
+ TkMenu *menuPtr)
+{
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ tsdPtr->postCommandGeneration++;
+ menuPtr->postCommandGeneration = tsdPtr->postCommandGeneration;
+ return PreprocessMenu(menuPtr);
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkMain.c b/tk8.6/generic/tkMain.c
new file mode 100644
index 0000000..b80ce4d
--- /dev/null
+++ b/tk8.6/generic/tkMain.c
@@ -0,0 +1,562 @@
+/*
+ * tkMain.c --
+ *
+ * This file contains a generic main program for Tk-based applications.
+ * It can be used as-is for many applications, just by supplying a
+ * different appInitProc function for each specific application. Or, it
+ * can be used as a template for creating new main programs for Tk
+ * applications.
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+/**
+ * On Windows, this file needs to be compiled twice, once with
+ * TK_ASCII_MAIN defined. This way both Tk_MainEx and Tk_MainExW
+ * can be implemented, sharing the same source code.
+ */
+#if defined(TK_ASCII_MAIN)
+# ifdef UNICODE
+# undef UNICODE
+# undef _UNICODE
+# else
+# define UNICODE
+# define _UNICODE
+# endif
+#endif
+
+#include "tkInt.h"
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#ifdef NO_STDLIB_H
+# include "../compat/stdlib.h"
+#else
+# include <stdlib.h>
+#endif
+
+extern int TkCygwinMainEx(int, char **, Tcl_AppInitProc *, Tcl_Interp *);
+
+/*
+ * The default prompt used when the user has not overridden it.
+ */
+
+static const char DEFAULT_PRIMARY_PROMPT[] = "% ";
+
+/*
+ * This file can be compiled on Windows in UNICODE mode, as well as
+ * on all other platforms using the native encoding. This is done
+ * by using the normal Windows functions like _tcscmp, but on
+ * platforms which don't have <tchar.h> we have to translate that
+ * to strcmp here.
+ */
+#ifdef _WIN32
+/* Little hack to eliminate the need for "tclInt.h" here:
+ Just copy a small portion of TclIntPlatStubs, just
+ enough to make it work. See [600b72bfbc] */
+typedef struct {
+ int magic;
+ void *hooks;
+ void (*dummy[16]) (void); /* dummy entries 0-15, not used */
+ int (*tclpIsAtty) (int fd); /* 16 */
+} TclIntPlatStubs;
+extern const TclIntPlatStubs *tclIntPlatStubsPtr;
+# include "tkWinInt.h"
+#else
+# define TCHAR char
+# define TEXT(arg) arg
+# define _tcscmp strcmp
+# define _tcslen strlen
+# define _tcsncmp strncmp
+#endif
+
+#ifdef MAC_OSX_TK
+#include "tkMacOSXInt.h"
+#endif
+
+/*
+ * Further on, in UNICODE mode we just use Tcl_NewUnicodeObj, otherwise
+ * NewNativeObj is needed (which provides proper conversion from native
+ * encoding to UTF-8).
+ */
+
+static inline Tcl_Obj *
+NewNativeObj(
+ TCHAR *string,
+ int length)
+{
+ Tcl_Obj *obj;
+ Tcl_DString ds;
+
+#ifdef UNICODE
+ if (length > 0) {
+ length *= sizeof(WCHAR);
+ }
+ Tcl_WinTCharToUtf(string, length, &ds);
+#else
+ Tcl_ExternalToUtfDString(NULL, (char *) string, length, &ds);
+#endif
+ obj = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));
+ Tcl_DStringFree(&ds);
+ return obj;
+}
+
+/*
+ * Declarations for various library functions and variables (don't want to
+ * include tkInt.h or tkPort.h here, because people might copy this file out
+ * of the Tk source directory to make their own modified versions). Note: do
+ * not declare "exit" here even though a declaration is really needed, because
+ * it will conflict with a declaration elsewhere on some systems.
+ */
+
+#if defined(_WIN32)
+#define isatty WinIsTty
+static int WinIsTty(int fd) {
+ HANDLE handle;
+
+ /*
+ * For now, under Windows, we assume we are not running as a console mode
+ * app, so we need to use the GUI console. In order to enable this, we
+ * always claim to be running on a tty. This probably isn't the right way
+ * to do it.
+ */
+
+#if !defined(STATIC_BUILD)
+ if (tclStubsPtr->reserved9 && tclIntPlatStubsPtr->tclpIsAtty) {
+ /* We are running on Cygwin */
+ return tclIntPlatStubsPtr->tclpIsAtty(fd);
+ }
+#endif
+ handle = GetStdHandle(STD_INPUT_HANDLE + fd);
+ /*
+ * If it's a bad or closed handle, then it's been connected to a wish
+ * console window. A character file handle is a tty by definition.
+ */
+ return (handle == INVALID_HANDLE_VALUE) || (handle == 0)
+ || (GetFileType(handle) == FILE_TYPE_UNKNOWN)
+ || (GetFileType(handle) == FILE_TYPE_CHAR);
+}
+#else
+extern int isatty(int fd);
+#endif
+
+typedef struct InteractiveState {
+ Tcl_Channel input; /* The standard input channel from which lines
+ * are read. */
+ int tty; /* Non-zero means standard input is a
+ * terminal-like device. Zero means it's a
+ * file. */
+ Tcl_DString command; /* Used to assemble lines of terminal input
+ * into Tcl commands. */
+ Tcl_DString line; /* Used to read the next line from the
+ * terminal input. */
+ int gotPartial;
+ Tcl_Interp *interp; /* Interpreter that evaluates interactive
+ * commands. */
+} InteractiveState;
+
+/*
+ * Forward declarations for functions defined later in this file.
+ */
+
+static void Prompt(Tcl_Interp *interp, InteractiveState *isPtr);
+static void StdinProc(ClientData clientData, int mask);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_MainEx --
+ *
+ * Main program for Wish and most other Tk-based applications.
+ *
+ * Results:
+ * None. This function never returns (it exits the process when it's
+ * done).
+ *
+ * Side effects:
+ * This function initializes the Tk world and then starts interpreting
+ * commands; almost anything could happen, depending on the script being
+ * interpreted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_MainEx(
+ int argc, /* Number of arguments. */
+ TCHAR **argv, /* Array of argument strings. */
+ Tcl_AppInitProc *appInitProc,
+ /* Application-specific initialization
+ * function to call after most initialization
+ * but before starting to execute commands. */
+ Tcl_Interp *interp)
+{
+ Tcl_Obj *path, *argvPtr, *appName;
+ const char *encodingName;
+ int code, nullStdin = 0;
+ Tcl_Channel chan;
+ InteractiveState is;
+
+ /*
+ * Ensure that we are getting a compatible version of Tcl.
+ */
+
+ if (Tcl_InitStubs(interp, "8.6", 0) == NULL) {
+ if (Tcl_InitStubs(interp, "8.1", 0) == NULL) {
+ abort();
+ } else {
+ Tcl_Panic("%s", Tcl_GetString(Tcl_GetObjResult(interp)));
+ }
+ }
+
+#if defined(_WIN32) && !defined(UNICODE) && !defined(STATIC_BUILD)
+
+ if (tclStubsPtr->reserved9) {
+ /* We are running win32 Tk under Cygwin, so let's check
+ * whether the env("DISPLAY") variable or the -display
+ * argument is set. If so, we really want to run the
+ * Tk_MainEx function of libtk8.?.dll, not this one. */
+ if (Tcl_GetVar2(interp, "env", "DISPLAY", TCL_GLOBAL_ONLY)) {
+ loadCygwinTk:
+ if (TkCygwinMainEx(argc, argv, appInitProc, interp)) {
+ /* Should never reach here. */
+ return;
+ }
+ } else {
+ int i;
+
+ for (i = 1; i < argc; ++i) {
+ if (!_tcscmp(argv[i], TEXT("-display"))) {
+ goto loadCygwinTk;
+ }
+ }
+ }
+ }
+#endif
+
+ Tcl_InitMemory(interp);
+
+ is.interp = interp;
+ is.gotPartial = 0;
+ Tcl_Preserve(interp);
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#if !defined(STATIC_BUILD)
+ /* If compiled for Win32 but running on Cygwin, don't use console */
+ if (!tclStubsPtr->reserved9)
+#endif
+ Tk_InitConsoleChannels(interp);
+#endif
+
+#ifdef MAC_OSX_TK
+ if (Tcl_GetStartupScript(NULL) == NULL) {
+ TkMacOSXDefaultStartupScript();
+ }
+#endif
+
+ /*
+ * If the application has not already set a startup script, parse the
+ * first few command line arguments to determine the script path and
+ * encoding.
+ */
+
+ if (NULL == Tcl_GetStartupScript(NULL)) {
+ size_t length;
+
+ /*
+ * Check whether first 3 args (argv[1] - argv[3]) look like
+ * -encoding ENCODING FILENAME
+ * or like
+ * FILENAME
+ * or like
+ * -file FILENAME (ancient history support only)
+ */
+
+ if ((argc > 3) && (0 == _tcscmp(TEXT("-encoding"), argv[1]))
+ && (TEXT('-') != argv[3][0])) {
+ Tcl_Obj *value = NewNativeObj(argv[2], -1);
+ Tcl_SetStartupScript(NewNativeObj(argv[3], -1), Tcl_GetString(value));
+ Tcl_DecrRefCount(value);
+ argc -= 3;
+ argv += 3;
+ } else if ((argc > 1) && (TEXT('-') != argv[1][0])) {
+ Tcl_SetStartupScript(NewNativeObj(argv[1], -1), NULL);
+ argc--;
+ argv++;
+ } else if ((argc > 2) && (length = _tcslen(argv[1]))
+ && (length > 1) && (0 == _tcsncmp(TEXT("-file"), argv[1], length))
+ && (TEXT('-') != argv[2][0])) {
+ Tcl_SetStartupScript(NewNativeObj(argv[2], -1), NULL);
+ argc -= 2;
+ argv += 2;
+ }
+ }
+
+ path = Tcl_GetStartupScript(&encodingName);
+ if (path == NULL) {
+ appName = NewNativeObj(argv[0], -1);
+ } else {
+ appName = path;
+ }
+ Tcl_SetVar2Ex(interp, "argv0", NULL, appName, TCL_GLOBAL_ONLY);
+ argc--;
+ argv++;
+
+ Tcl_SetVar2Ex(interp, "argc", NULL, Tcl_NewIntObj(argc), TCL_GLOBAL_ONLY);
+
+ argvPtr = Tcl_NewListObj(0, NULL);
+ while (argc--) {
+ Tcl_ListObjAppendElement(NULL, argvPtr, NewNativeObj(*argv++, -1));
+ }
+ Tcl_SetVar2Ex(interp, "argv", NULL, argvPtr, TCL_GLOBAL_ONLY);
+
+ /*
+ * Set the "tcl_interactive" variable.
+ */
+
+ is.tty = isatty(0);
+#if defined(MAC_OSX_TK)
+ /*
+ * On TkAqua, if we don't have a TTY and stdin is a special character file
+ * of length 0, (e.g. /dev/null, which is what Finder sets when double
+ * clicking Wish) then use the GUI console.
+ */
+
+ if (!is.tty) {
+ struct stat st;
+
+ nullStdin = fstat(0, &st) || (S_ISCHR(st.st_mode) && !st.st_blocks);
+ }
+#endif
+ Tcl_SetVar2Ex(interp, "tcl_interactive", NULL,
+ Tcl_NewIntObj(!path && (is.tty || nullStdin)), TCL_GLOBAL_ONLY);
+
+ /*
+ * Invoke application-specific initialization.
+ */
+
+ if (appInitProc(interp) != TCL_OK) {
+ TkpDisplayWarning(Tcl_GetString(Tcl_GetObjResult(interp)),
+ "application-specific initialization failed");
+ }
+
+ /*
+ * Invoke the script specified on the command line, if any. Must fetch it
+ * again, as the appInitProc might have reset it.
+ */
+
+ path = Tcl_GetStartupScript(&encodingName);
+ if (path != NULL) {
+ Tcl_ResetResult(interp);
+ code = Tcl_FSEvalFileEx(interp, path, encodingName);
+ if (code != TCL_OK) {
+ /*
+ * The following statement guarantees that the errorInfo variable
+ * is set properly.
+ */
+
+ Tcl_AddErrorInfo(interp, "");
+ TkpDisplayWarning(Tcl_GetVar2(interp, "errorInfo", NULL,
+ TCL_GLOBAL_ONLY), "Error in startup script");
+ Tcl_DeleteInterp(interp);
+ Tcl_Exit(1);
+ }
+ is.tty = 0;
+ } else {
+
+ /*
+ * Evaluate the .rc file, if one has been specified.
+ */
+
+ Tcl_SourceRCFile(interp);
+
+ /*
+ * Establish a channel handler for stdin.
+ */
+
+ is.input = Tcl_GetStdChannel(TCL_STDIN);
+ if (is.input) {
+ Tcl_CreateChannelHandler(is.input, TCL_READABLE, StdinProc, &is);
+ }
+ if (is.tty) {
+ Prompt(interp, &is);
+ }
+ }
+
+ chan = Tcl_GetStdChannel(TCL_STDOUT);
+ if (chan) {
+ Tcl_Flush(chan);
+ }
+ Tcl_DStringInit(&is.command);
+ Tcl_DStringInit(&is.line);
+ Tcl_ResetResult(interp);
+
+ /*
+ * Loop infinitely, waiting for commands to execute. When there are no
+ * windows left, Tk_MainLoop returns and we exit.
+ */
+
+ Tk_MainLoop();
+ Tcl_DeleteInterp(interp);
+ Tcl_Release(interp);
+ Tcl_SetStartupScript(NULL, NULL);
+ Tcl_Exit(0);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * StdinProc --
+ *
+ * This function is invoked by the event dispatcher whenever standard
+ * input becomes readable. It grabs the next line of input characters,
+ * adds them to a command being assembled, and executes the command if
+ * it's complete.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Could be almost arbitrary, depending on the command that's typed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static void
+StdinProc(
+ ClientData clientData, /* The state of interactive cmd line */
+ int mask) /* Not used. */
+{
+ char *cmd;
+ int code, count;
+ InteractiveState *isPtr = clientData;
+ Tcl_Channel chan = isPtr->input;
+ Tcl_Interp *interp = isPtr->interp;
+
+ count = Tcl_Gets(chan, &isPtr->line);
+
+ if (count < 0 && !isPtr->gotPartial) {
+ if (isPtr->tty) {
+ Tcl_Exit(0);
+ } else {
+ Tcl_DeleteChannelHandler(chan, StdinProc, isPtr);
+ }
+ return;
+ }
+
+ Tcl_DStringAppend(&isPtr->command, Tcl_DStringValue(&isPtr->line), -1);
+ cmd = Tcl_DStringAppend(&isPtr->command, "\n", -1);
+ Tcl_DStringFree(&isPtr->line);
+ if (!Tcl_CommandComplete(cmd)) {
+ isPtr->gotPartial = 1;
+ goto prompt;
+ }
+ isPtr->gotPartial = 0;
+
+ /*
+ * Disable the stdin channel handler while evaluating the command;
+ * otherwise if the command re-enters the event loop we might process
+ * commands from stdin before the current command is finished. Among other
+ * things, this will trash the text of the command being evaluated.
+ */
+
+ Tcl_CreateChannelHandler(chan, 0, StdinProc, isPtr);
+ code = Tcl_RecordAndEval(interp, cmd, TCL_EVAL_GLOBAL);
+
+ isPtr->input = Tcl_GetStdChannel(TCL_STDIN);
+ if (isPtr->input) {
+ Tcl_CreateChannelHandler(isPtr->input, TCL_READABLE, StdinProc, isPtr);
+ }
+ Tcl_DStringFree(&isPtr->command);
+ if (Tcl_GetString(Tcl_GetObjResult(interp))[0] != '\0') {
+ if ((code != TCL_OK) || (isPtr->tty)) {
+ chan = Tcl_GetStdChannel((code != TCL_OK) ? TCL_STDERR : TCL_STDOUT);
+ if (chan) {
+ Tcl_WriteObj(chan, Tcl_GetObjResult(interp));
+ Tcl_WriteChars(chan, "\n", 1);
+ }
+ }
+ }
+
+ /*
+ * If a tty stdin is still around, output a prompt.
+ */
+
+ prompt:
+ if (isPtr->tty && (isPtr->input != NULL)) {
+ Prompt(interp, isPtr);
+ }
+ Tcl_ResetResult(interp);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Prompt --
+ *
+ * Issue a prompt on standard output, or invoke a script to issue the
+ * prompt.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A prompt gets output, and a Tcl script may be evaluated in interp.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+Prompt(
+ Tcl_Interp *interp, /* Interpreter to use for prompting. */
+ InteractiveState *isPtr) /* InteractiveState. */
+{
+ Tcl_Obj *promptCmdPtr;
+ int code;
+ Tcl_Channel chan;
+
+ promptCmdPtr = Tcl_GetVar2Ex(interp,
+ isPtr->gotPartial ? "tcl_prompt2" : "tcl_prompt1", NULL, TCL_GLOBAL_ONLY);
+ if (promptCmdPtr == NULL) {
+ defaultPrompt:
+ if (!isPtr->gotPartial) {
+ chan = Tcl_GetStdChannel(TCL_STDOUT);
+ if (chan != NULL) {
+ Tcl_WriteChars(chan, DEFAULT_PRIMARY_PROMPT,
+ sizeof(DEFAULT_PRIMARY_PROMPT) - 1);
+ }
+ }
+ } else {
+ code = Tcl_EvalObjEx(interp, promptCmdPtr, TCL_EVAL_GLOBAL);
+ if (code != TCL_OK) {
+ Tcl_AddErrorInfo(interp,
+ "\n (script that generates prompt)");
+ if (Tcl_GetString(Tcl_GetObjResult(interp))[0] != '\0') {
+ chan = Tcl_GetStdChannel(TCL_STDERR);
+ if (chan != NULL) {
+ Tcl_WriteObj(chan, Tcl_GetObjResult(interp));
+ Tcl_WriteChars(chan, "\n", 1);
+ }
+ }
+ goto defaultPrompt;
+ }
+ }
+
+ chan = Tcl_GetStdChannel(TCL_STDOUT);
+ if (chan != NULL) {
+ Tcl_Flush(chan);
+ }
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkMenu.c b/tk8.6/generic/tkMenu.c
new file mode 100644
index 0000000..5fd8b80
--- /dev/null
+++ b/tk8.6/generic/tkMenu.c
@@ -0,0 +1,3639 @@
+/*
+ * tkMenu.c --
+ *
+ * This file contains most of the code for implementing menus in Tk. It takes
+ * care of all of the generic (platform-independent) parts of menus, and is
+ * supplemented by platform-specific files. The geometry calculation and
+ * drawing code for menus is in the file tkMenuDraw.c
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1998 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+/*
+ * Notes on implementation of menus:
+ *
+ * Menus can be used in three ways:
+ * - as a popup menu, either as part of a menubutton or standalone.
+ * - as a menubar. The menu's cascade items are arranged according to the
+ * specific platform to provide the user access to the menus at all times
+ * - as a tearoff palette. This is a window with the menu's items in it.
+ *
+ * The goal is to provide the Tk developer with a way to use a common set of
+ * menus for all of these tasks.
+ *
+ * In order to make the bindings for cascade menus work properly under Unix,
+ * the cascade menus' pathnames must be proper children of the menu that they
+ * are cascade from. So if there is a menu .m, and it has two cascades
+ * labelled "File" and "Edit", the cascade menus might have the pathnames
+ * .m.file and .m.edit. Another constraint is that the menus used for menubars
+ * must be children of the toplevel widget that they are attached to. And on
+ * the Macintosh, the platform specific menu handle for cascades attached to a
+ * menu bar must have a title that matches the label for the cascade menu.
+ *
+ * To handle all of the constraints, Tk menubars and tearoff menus are
+ * implemented using menu clones. Menu clones are full menus in their own
+ * right; they have a Tk window and pathname associated with them; they have a
+ * TkMenu structure and array of entries. However, they are linked with the
+ * original menu that they were cloned from. The reflect the attributes of the
+ * original, or "master", menu. So if an item is added to a menu, and that
+ * menu has clones, then the item must be added to all of its clones also.
+ * Menus are cloned when a menu is torn-off or when a menu is assigned as a
+ * menubar using the "-menu" option of the toplevel's pathname configure
+ * subcommand. When a clone is destroyed, only the clone is destroyed, but
+ * when the master menu is destroyed, all clones are also destroyed. This
+ * allows the developer to just deal with one set of menus when creating and
+ * destroying.
+ *
+ * Clones are rather tricky when a menu with cascade entries is cloned (such
+ * as a menubar). Not only does the menu have to be cloned, but each cascade
+ * entry's corresponding menu must also be cloned. This maintains the pathname
+ * parent-child hierarchy necessary for menubars and toplevels to work. This
+ * leads to several special cases:
+ *
+ * 1. When a new menu is created, and it is pointed to by cascade entries in
+ * cloned menus, the new menu has to be cloned to parallel the cascade
+ * structure.
+ * 2. When a cascade item is added to a menu that has been cloned, and the
+ * menu that the cascade item points to exists, that menu has to be cloned.
+ * 3. When the menu that a cascade entry points to is changed, the old cloned
+ * cascade menu has to be discarded, and the new one has to be cloned.
+ */
+
+#if 0
+
+/*
+ * used only to test for old config code
+ */
+
+#define __NO_OLD_CONFIG
+#endif
+
+#include "tkInt.h"
+#include "tkMenu.h"
+
+#define MENU_HASH_KEY "tkMenus"
+
+typedef struct {
+ int menusInitialized; /* Flag indicates whether thread-specific
+ * elements of the Windows Menu module have
+ * been initialized. */
+ Tk_OptionTable menuOptionTable;
+ /* The option table for menus. */
+ Tk_OptionTable entryOptionTables[6];
+ /* The tables for menu entries. */
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+
+/*
+ * The following flag indicates whether the process-wide state for the Menu
+ * module has been initialized. The Mutex protects access to that flag.
+ */
+
+static int menusInitialized;
+TCL_DECLARE_MUTEX(menuMutex)
+
+/*
+ * Configuration specs for individual menu entries. If this changes, be sure
+ * to update code in TkpMenuInit that changes the font string entry.
+ */
+
+static const char *const menuStateStrings[] = {"active", "normal", "disabled", NULL};
+
+static const char *const menuEntryTypeStrings[] = {
+ "cascade", "checkbutton", "command", "radiobutton", "separator", NULL
+};
+
+/*
+ * The following table defines the legal values for the -compound option. It
+ * is used with the "enum compound" declaration in tkMenu.h
+ */
+
+static const char *const compoundStrings[] = {
+ "bottom", "center", "left", "none", "right", "top", NULL
+};
+
+static const Tk_OptionSpec tkBasicMenuEntryConfigSpecs[] = {
+ {TK_OPTION_BORDER, "-activebackground", NULL, NULL,
+ DEF_MENU_ENTRY_ACTIVE_BG, Tk_Offset(TkMenuEntry, activeBorderPtr), -1,
+ TK_OPTION_NULL_OK, NULL, 0},
+ {TK_OPTION_COLOR, "-activeforeground", NULL, NULL,
+ DEF_MENU_ENTRY_ACTIVE_FG,
+ Tk_Offset(TkMenuEntry, activeFgPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
+ {TK_OPTION_STRING, "-accelerator", NULL, NULL,
+ DEF_MENU_ENTRY_ACCELERATOR,
+ Tk_Offset(TkMenuEntry, accelPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
+ {TK_OPTION_BORDER, "-background", NULL, NULL,
+ DEF_MENU_ENTRY_BG,
+ Tk_Offset(TkMenuEntry, borderPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
+ {TK_OPTION_BITMAP, "-bitmap", NULL, NULL,
+ DEF_MENU_ENTRY_BITMAP,
+ Tk_Offset(TkMenuEntry, bitmapPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
+ {TK_OPTION_BOOLEAN, "-columnbreak", NULL, NULL,
+ DEF_MENU_ENTRY_COLUMN_BREAK,
+ -1, Tk_Offset(TkMenuEntry, columnBreak), 0, NULL, 0},
+ {TK_OPTION_STRING, "-command", NULL, NULL,
+ DEF_MENU_ENTRY_COMMAND,
+ Tk_Offset(TkMenuEntry, commandPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
+ {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound",
+ DEF_MENU_ENTRY_COMPOUND, -1, Tk_Offset(TkMenuEntry, compound), 0,
+ (ClientData) compoundStrings, 0},
+ {TK_OPTION_FONT, "-font", NULL, NULL,
+ DEF_MENU_ENTRY_FONT,
+ Tk_Offset(TkMenuEntry, fontPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
+ {TK_OPTION_COLOR, "-foreground", NULL, NULL,
+ DEF_MENU_ENTRY_FG,
+ Tk_Offset(TkMenuEntry, fgPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
+ {TK_OPTION_BOOLEAN, "-hidemargin", NULL, NULL,
+ DEF_MENU_ENTRY_HIDE_MARGIN,
+ -1, Tk_Offset(TkMenuEntry, hideMargin), 0, NULL, 0},
+ {TK_OPTION_STRING, "-image", NULL, NULL,
+ DEF_MENU_ENTRY_IMAGE,
+ Tk_Offset(TkMenuEntry, imagePtr), -1, TK_OPTION_NULL_OK, NULL, 0},
+ {TK_OPTION_STRING, "-label", NULL, NULL,
+ DEF_MENU_ENTRY_LABEL,
+ Tk_Offset(TkMenuEntry, labelPtr), -1, 0, NULL, 0},
+ {TK_OPTION_STRING_TABLE, "-state", NULL, NULL,
+ DEF_MENU_ENTRY_STATE,
+ -1, Tk_Offset(TkMenuEntry, state), 0,
+ (ClientData) menuStateStrings, 0},
+ {TK_OPTION_INT, "-underline", NULL, NULL,
+ DEF_MENU_ENTRY_UNDERLINE, -1, Tk_Offset(TkMenuEntry, underline), 0, NULL, 0},
+ {TK_OPTION_END, NULL, NULL, NULL, 0, 0, 0, 0, NULL, 0}
+};
+
+static const Tk_OptionSpec tkSeparatorEntryConfigSpecs[] = {
+ {TK_OPTION_BORDER, "-background", NULL, NULL,
+ DEF_MENU_ENTRY_BG,
+ Tk_Offset(TkMenuEntry, borderPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
+ {TK_OPTION_END, NULL, NULL, NULL, 0, 0, 0, 0, NULL, 0}
+};
+
+static const Tk_OptionSpec tkCheckButtonEntryConfigSpecs[] = {
+ {TK_OPTION_BOOLEAN, "-indicatoron", NULL, NULL,
+ DEF_MENU_ENTRY_INDICATOR,
+ -1, Tk_Offset(TkMenuEntry, indicatorOn), 0, NULL, 0},
+ {TK_OPTION_STRING, "-offvalue", NULL, NULL,
+ DEF_MENU_ENTRY_OFF_VALUE,
+ Tk_Offset(TkMenuEntry, offValuePtr), -1, 0, NULL, 0},
+ {TK_OPTION_STRING, "-onvalue", NULL, NULL,
+ DEF_MENU_ENTRY_ON_VALUE,
+ Tk_Offset(TkMenuEntry, onValuePtr), -1, 0, NULL, 0},
+ {TK_OPTION_COLOR, "-selectcolor", NULL, NULL,
+ DEF_MENU_ENTRY_SELECT,
+ Tk_Offset(TkMenuEntry, indicatorFgPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
+ {TK_OPTION_STRING, "-selectimage", NULL, NULL,
+ DEF_MENU_ENTRY_SELECT_IMAGE,
+ Tk_Offset(TkMenuEntry, selectImagePtr), -1, TK_OPTION_NULL_OK, NULL, 0},
+ {TK_OPTION_STRING, "-variable", NULL, NULL,
+ DEF_MENU_ENTRY_CHECK_VARIABLE,
+ Tk_Offset(TkMenuEntry, namePtr), -1, TK_OPTION_NULL_OK, NULL, 0},
+ {TK_OPTION_END, NULL, NULL, NULL,
+ NULL, 0, -1, 0, tkBasicMenuEntryConfigSpecs, 0}
+};
+
+static const Tk_OptionSpec tkRadioButtonEntryConfigSpecs[] = {
+ {TK_OPTION_BOOLEAN, "-indicatoron", NULL, NULL,
+ DEF_MENU_ENTRY_INDICATOR,
+ -1, Tk_Offset(TkMenuEntry, indicatorOn), 0, NULL, 0},
+ {TK_OPTION_COLOR, "-selectcolor", NULL, NULL,
+ DEF_MENU_ENTRY_SELECT,
+ Tk_Offset(TkMenuEntry, indicatorFgPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
+ {TK_OPTION_STRING, "-selectimage", NULL, NULL,
+ DEF_MENU_ENTRY_SELECT_IMAGE,
+ Tk_Offset(TkMenuEntry, selectImagePtr), -1, TK_OPTION_NULL_OK, NULL, 0},
+ {TK_OPTION_STRING, "-value", NULL, NULL,
+ DEF_MENU_ENTRY_VALUE,
+ Tk_Offset(TkMenuEntry, onValuePtr), -1, TK_OPTION_NULL_OK, NULL, 0},
+ {TK_OPTION_STRING, "-variable", NULL, NULL,
+ DEF_MENU_ENTRY_RADIO_VARIABLE,
+ Tk_Offset(TkMenuEntry, namePtr), -1, 0, NULL, 0},
+ {TK_OPTION_END, NULL, NULL, NULL,
+ NULL, 0, -1, 0, tkBasicMenuEntryConfigSpecs, 0}
+};
+
+static const Tk_OptionSpec tkCascadeEntryConfigSpecs[] = {
+ {TK_OPTION_STRING, "-menu", NULL, NULL,
+ DEF_MENU_ENTRY_MENU,
+ Tk_Offset(TkMenuEntry, namePtr), -1, TK_OPTION_NULL_OK, NULL, 0},
+ {TK_OPTION_END, NULL, NULL, NULL,
+ NULL, 0, -1, 0, tkBasicMenuEntryConfigSpecs, 0}
+};
+
+static const Tk_OptionSpec tkTearoffEntryConfigSpecs[] = {
+ {TK_OPTION_BORDER, "-background", NULL, NULL,
+ DEF_MENU_ENTRY_BG,
+ Tk_Offset(TkMenuEntry, borderPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
+ {TK_OPTION_STRING_TABLE, "-state", NULL, NULL,
+ DEF_MENU_ENTRY_STATE, -1, Tk_Offset(TkMenuEntry, state), 0,
+ (ClientData) menuStateStrings, 0},
+ {TK_OPTION_END, NULL, NULL, NULL, 0, 0, 0, 0, NULL, 0}
+};
+
+static const Tk_OptionSpec *specsArray[] = {
+ tkCascadeEntryConfigSpecs, tkCheckButtonEntryConfigSpecs,
+ tkBasicMenuEntryConfigSpecs, tkRadioButtonEntryConfigSpecs,
+ tkSeparatorEntryConfigSpecs, tkTearoffEntryConfigSpecs
+};
+
+/*
+ * Menu type strings for use with Tcl_GetIndexFromObj.
+ */
+
+static const char *const menuTypeStrings[] = {
+ "normal", "tearoff", "menubar", NULL
+};
+
+static const Tk_OptionSpec tkMenuConfigSpecs[] = {
+ {TK_OPTION_BORDER, "-activebackground", "activeBackground",
+ "Foreground", DEF_MENU_ACTIVE_BG_COLOR,
+ Tk_Offset(TkMenu, activeBorderPtr), -1, 0,
+ (ClientData) DEF_MENU_ACTIVE_BG_MONO, 0},
+ {TK_OPTION_PIXELS, "-activeborderwidth", "activeBorderWidth",
+ "BorderWidth", DEF_MENU_ACTIVE_BORDER_WIDTH,
+ Tk_Offset(TkMenu, activeBorderWidthPtr), -1, 0, NULL, 0},
+ {TK_OPTION_COLOR, "-activeforeground", "activeForeground",
+ "Background", DEF_MENU_ACTIVE_FG_COLOR,
+ Tk_Offset(TkMenu, activeFgPtr), -1, 0,
+ (ClientData) DEF_MENU_ACTIVE_FG_MONO, 0},
+ {TK_OPTION_BORDER, "-background", "background", "Background",
+ DEF_MENU_BG_COLOR, Tk_Offset(TkMenu, borderPtr), -1, 0,
+ (ClientData) DEF_MENU_BG_MONO, 0},
+ {TK_OPTION_SYNONYM, "-bd", NULL, NULL,
+ NULL, 0, -1, 0, "-borderwidth", 0},
+ {TK_OPTION_SYNONYM, "-bg", NULL, NULL,
+ NULL, 0, -1, 0, "-background", 0},
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ DEF_MENU_BORDER_WIDTH,
+ Tk_Offset(TkMenu, borderWidthPtr), -1, 0, NULL, 0},
+ {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
+ DEF_MENU_CURSOR,
+ Tk_Offset(TkMenu, cursorPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
+ {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
+ "DisabledForeground", DEF_MENU_DISABLED_FG_COLOR,
+ Tk_Offset(TkMenu, disabledFgPtr), -1, TK_OPTION_NULL_OK,
+ (ClientData) DEF_MENU_DISABLED_FG_MONO, 0},
+ {TK_OPTION_SYNONYM, "-fg", NULL, NULL,
+ NULL, 0, -1, 0, "-foreground", 0},
+ {TK_OPTION_FONT, "-font", "font", "Font",
+ DEF_MENU_FONT, Tk_Offset(TkMenu, fontPtr), -1, 0, NULL, 0},
+ {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
+ DEF_MENU_FG, Tk_Offset(TkMenu, fgPtr), -1, 0, NULL, 0},
+ {TK_OPTION_STRING, "-postcommand", "postCommand", "Command",
+ DEF_MENU_POST_COMMAND,
+ Tk_Offset(TkMenu, postCommandPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ DEF_MENU_RELIEF, Tk_Offset(TkMenu, reliefPtr), -1, 0, NULL, 0},
+ {TK_OPTION_COLOR, "-selectcolor", "selectColor", "Background",
+ DEF_MENU_SELECT_COLOR, Tk_Offset(TkMenu, indicatorFgPtr), -1, 0,
+ (ClientData) DEF_MENU_SELECT_MONO, 0},
+ {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
+ DEF_MENU_TAKE_FOCUS,
+ Tk_Offset(TkMenu, takeFocusPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
+ {TK_OPTION_BOOLEAN, "-tearoff", "tearOff", "TearOff",
+ DEF_MENU_TEAROFF, -1, Tk_Offset(TkMenu, tearoff), 0, NULL, 0},
+ {TK_OPTION_STRING, "-tearoffcommand", "tearOffCommand",
+ "TearOffCommand", DEF_MENU_TEAROFF_CMD,
+ Tk_Offset(TkMenu, tearoffCommandPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
+ {TK_OPTION_STRING, "-title", "title", "Title",
+ DEF_MENU_TITLE, Tk_Offset(TkMenu, titlePtr), -1,
+ TK_OPTION_NULL_OK, NULL, 0},
+ {TK_OPTION_STRING_TABLE, "-type", "type", "Type",
+ DEF_MENU_TYPE, Tk_Offset(TkMenu, menuTypePtr), -1, TK_OPTION_NULL_OK,
+ (ClientData) menuTypeStrings, 0},
+ {TK_OPTION_END, NULL, NULL, NULL, 0, 0, 0, 0, NULL, 0}
+};
+
+/*
+ * Command line options. Put here because MenuCmd has to look at them along
+ * with MenuWidgetObjCmd.
+ */
+
+static const char *const menuOptions[] = {
+ "activate", "add", "cget", "clone", "configure", "delete", "entrycget",
+ "entryconfigure", "index", "insert", "invoke", "post", "postcascade",
+ "type", "unpost", "xposition", "yposition", NULL
+};
+enum options {
+ MENU_ACTIVATE, MENU_ADD, MENU_CGET, MENU_CLONE, MENU_CONFIGURE,
+ MENU_DELETE, MENU_ENTRYCGET, MENU_ENTRYCONFIGURE, MENU_INDEX,
+ MENU_INSERT, MENU_INVOKE, MENU_POST, MENU_POSTCASCADE, MENU_TYPE,
+ MENU_UNPOST, MENU_XPOSITION, MENU_YPOSITION
+};
+
+/*
+ * Prototypes for static functions in this file:
+ */
+
+static int CloneMenu(TkMenu *menuPtr, Tcl_Obj *newMenuName,
+ Tcl_Obj *newMenuTypeString);
+static int ConfigureMenu(Tcl_Interp *interp, TkMenu *menuPtr,
+ int objc, Tcl_Obj *const objv[]);
+static int ConfigureMenuCloneEntries(Tcl_Interp *interp,
+ TkMenu *menuPtr, int index,
+ int objc, Tcl_Obj *const objv[]);
+static int ConfigureMenuEntry(TkMenuEntry *mePtr,
+ int objc, Tcl_Obj *const objv[]);
+static void DeleteMenuCloneEntries(TkMenu *menuPtr,
+ int first, int last);
+static void DestroyMenuHashTable(ClientData clientData,
+ Tcl_Interp *interp);
+static void DestroyMenuInstance(TkMenu *menuPtr);
+static void DestroyMenuEntry(void *memPtr);
+static int GetIndexFromCoords(Tcl_Interp *interp,
+ TkMenu *menuPtr, const char *string,
+ int *indexPtr);
+static int MenuDoYPosition(Tcl_Interp *interp,
+ TkMenu *menuPtr, Tcl_Obj *objPtr);
+static int MenuDoXPosition(Tcl_Interp *interp,
+ TkMenu *menuPtr, Tcl_Obj *objPtr);
+static int MenuAddOrInsert(Tcl_Interp *interp,
+ TkMenu *menuPtr, Tcl_Obj *indexPtr, int objc,
+ Tcl_Obj *const objv[]);
+static void MenuCmdDeletedProc(ClientData clientData);
+static TkMenuEntry * MenuNewEntry(TkMenu *menuPtr, int index, int type);
+static char * MenuVarProc(ClientData clientData,
+ Tcl_Interp *interp, const char *name1,
+ const char *name2, int flags);
+static int MenuWidgetObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static void MenuWorldChanged(ClientData instanceData);
+static int PostProcessEntry(TkMenuEntry *mePtr);
+static void RecursivelyDeleteMenu(TkMenu *menuPtr);
+static void UnhookCascadeEntry(TkMenuEntry *mePtr);
+static void TkMenuCleanup(ClientData unused);
+
+/*
+ * The structure below is a list of procs that respond to certain window
+ * manager events. One of these includes a font change, which forces the
+ * geometry proc to be called.
+ */
+
+static const Tk_ClassProcs menuClass = {
+ sizeof(Tk_ClassProcs), /* size */
+ MenuWorldChanged, /* worldChangedProc */
+ NULL, /* createProc */
+ NULL /* modalProc */
+};
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_MenuObjCmd --
+ *
+ * This function is invoked to process the "menu" 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_MenuObjCmd(
+ ClientData clientData, /* Main window associated with interpreter. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument strings. */
+{
+ Tk_Window tkwin = clientData;
+ Tk_Window newWin;
+ register TkMenu *menuPtr;
+ TkMenuReferences *menuRefPtr;
+ int i, index, toplevel;
+ const char *windowName;
+ static const char *const typeStringList[] = {"-type", NULL};
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?");
+ return TCL_ERROR;
+ }
+
+ TkMenuInit();
+
+ toplevel = 1;
+ for (i = 2; i < (objc - 1); i++) {
+ if (Tcl_GetIndexFromObjStruct(NULL, objv[i], typeStringList,
+ sizeof(char *), NULL, 0, &index) != TCL_ERROR) {
+ if ((Tcl_GetIndexFromObjStruct(NULL, objv[i + 1], menuTypeStrings,
+ sizeof(char *), NULL, 0, &index) == TCL_OK) && (index == MENUBAR)) {
+ toplevel = 0;
+ }
+ break;
+ }
+ }
+
+ windowName = Tcl_GetString(objv[1]);
+ newWin = Tk_CreateWindowFromPath(interp, tkwin, windowName,
+ toplevel ? "" : NULL);
+ if (newWin == NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Initialize the data structure for the menu. Note that the menuPtr is
+ * eventually freed in 'TkMenuEventProc' in tkMenuDraw.c, when
+ * Tcl_EventuallyFree is called.
+ */
+
+ menuPtr = ckalloc(sizeof(TkMenu));
+ memset(menuPtr, 0, sizeof(TkMenu));
+ menuPtr->tkwin = newWin;
+ menuPtr->display = Tk_Display(newWin);
+ menuPtr->interp = interp;
+ menuPtr->widgetCmd = Tcl_CreateObjCommand(interp,
+ Tk_PathName(menuPtr->tkwin), MenuWidgetObjCmd, menuPtr,
+ MenuCmdDeletedProc);
+ menuPtr->active = -1;
+ menuPtr->cursorPtr = NULL;
+ menuPtr->masterMenuPtr = menuPtr;
+ menuPtr->menuType = UNKNOWN_TYPE;
+ TkMenuInitializeDrawingFields(menuPtr);
+
+ Tk_SetClass(menuPtr->tkwin, "Menu");
+ Tk_SetClassProcs(menuPtr->tkwin, &menuClass, menuPtr);
+ Tk_CreateEventHandler(newWin,
+ ExposureMask|StructureNotifyMask|ActivateMask,
+ TkMenuEventProc, menuPtr);
+ if (Tk_InitOptions(interp, (char *) menuPtr,
+ tsdPtr->menuOptionTable, menuPtr->tkwin)
+ != TCL_OK) {
+ Tk_DestroyWindow(menuPtr->tkwin);
+ return TCL_ERROR;
+ }
+
+
+ menuRefPtr = TkCreateMenuReferences(menuPtr->interp,
+ Tk_PathName(menuPtr->tkwin));
+ menuRefPtr->menuPtr = menuPtr;
+ menuPtr->menuRefPtr = menuRefPtr;
+ if (TCL_OK != TkpNewMenu(menuPtr)) {
+ Tk_DestroyWindow(menuPtr->tkwin);
+ return TCL_ERROR;
+ }
+
+ if (ConfigureMenu(interp, menuPtr, objc - 2, objv + 2) != TCL_OK) {
+ Tk_DestroyWindow(menuPtr->tkwin);
+ return TCL_ERROR;
+ }
+
+ /*
+ * If a menu has a parent menu pointing to it as a cascade entry, the
+ * parent menu needs to be told that this menu now exists so that the
+ * platform-part of the menu is correctly updated.
+ *
+ * If a menu has an instance and has cascade entries, then each cascade
+ * menu must also have a parallel instance. This is especially true on the
+ * Mac, where each menu has to have a separate title everytime it is in a
+ * menubar. For instance, say you have a menu .m1 with a cascade entry for
+ * .m2, where .m2 does not exist yet. You then put .m1 into a menubar.
+ * This creates a menubar instance for .m1, but since .m2 is not there,
+ * nothing else happens. When we go to create .m2, we hook it up properly
+ * with .m1. However, we now need to clone .m2 and assign the clone of .m2
+ * to be the cascade entry for the clone of .m1. This is special case #1
+ * listed in the introductory comment.
+ */
+
+ if (menuRefPtr->parentEntryPtr != NULL) {
+ TkMenuEntry *cascadeListPtr = menuRefPtr->parentEntryPtr;
+ TkMenuEntry *nextCascadePtr;
+ Tcl_Obj *newMenuName, *newObjv[2];
+
+ while (cascadeListPtr != NULL) {
+ nextCascadePtr = cascadeListPtr->nextCascadePtr;
+
+ /*
+ * If we have a new master menu, and an existing cloned menu
+ * points to this menu in a cascade entry, we have to clone the
+ * new menu and point the entry to the clone instead of the menu
+ * we are creating. Otherwise, ConfigureMenuEntry will hook up the
+ * platform-specific cascade linkages now that the menu we are
+ * creating exists.
+ */
+
+ if ((menuPtr->masterMenuPtr != menuPtr)
+ || ((menuPtr->masterMenuPtr == menuPtr)
+ && ((cascadeListPtr->menuPtr->masterMenuPtr
+ == cascadeListPtr->menuPtr)))) {
+ newObjv[0] = Tcl_NewStringObj("-menu", -1);
+ newObjv[1] = Tcl_NewStringObj(Tk_PathName(menuPtr->tkwin),-1);
+ Tcl_IncrRefCount(newObjv[0]);
+ Tcl_IncrRefCount(newObjv[1]);
+ ConfigureMenuEntry(cascadeListPtr, 2, newObjv);
+ Tcl_DecrRefCount(newObjv[0]);
+ Tcl_DecrRefCount(newObjv[1]);
+ } else {
+ Tcl_Obj *normalPtr = Tcl_NewStringObj("normal", -1);
+ Tcl_Obj *windowNamePtr = Tcl_NewStringObj(
+ Tk_PathName(cascadeListPtr->menuPtr->tkwin), -1);
+
+ Tcl_IncrRefCount(normalPtr);
+ Tcl_IncrRefCount(windowNamePtr);
+ newMenuName = TkNewMenuName(menuPtr->interp,
+ windowNamePtr, menuPtr);
+ Tcl_IncrRefCount(newMenuName);
+ CloneMenu(menuPtr, newMenuName, normalPtr);
+
+ /*
+ * Now we can set the new menu instance to be the cascade
+ * entry of the parent's instance.
+ */
+
+ newObjv[0] = Tcl_NewStringObj("-menu", -1);
+ newObjv[1] = newMenuName;
+ Tcl_IncrRefCount(newObjv[0]);
+ ConfigureMenuEntry(cascadeListPtr, 2, newObjv);
+ Tcl_DecrRefCount(normalPtr);
+ Tcl_DecrRefCount(newObjv[0]);
+ Tcl_DecrRefCount(newObjv[1]);
+ Tcl_DecrRefCount(windowNamePtr);
+ }
+ cascadeListPtr = nextCascadePtr;
+ }
+ }
+
+ /*
+ * If there already exist toplevel widgets that refer to this menu, find
+ * them and notify them so that they can reconfigure their geometry to
+ * reflect the menu.
+ */
+
+ if (menuRefPtr->topLevelListPtr != NULL) {
+ TkMenuTopLevelList *topLevelListPtr = menuRefPtr->topLevelListPtr;
+ TkMenuTopLevelList *nextPtr;
+ Tk_Window listtkwin;
+
+ while (topLevelListPtr != NULL) {
+ /*
+ * Need to get the next pointer first. TkSetWindowMenuBar changes
+ * the list, so that the next pointer is different after calling
+ * it.
+ */
+
+ nextPtr = topLevelListPtr->nextPtr;
+ listtkwin = topLevelListPtr->tkwin;
+ TkSetWindowMenuBar(menuPtr->interp, listtkwin,
+ Tk_PathName(menuPtr->tkwin), Tk_PathName(menuPtr->tkwin));
+ topLevelListPtr = nextPtr;
+ }
+ }
+
+ Tcl_SetObjResult(interp, TkNewWindowObj(menuPtr->tkwin));
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * MenuWidgetObjCmd --
+ *
+ * This function is invoked to process the Tcl command that corresponds
+ * to a widget managed by this module. See the user documentation for
+ * details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+MenuWidgetObjCmd(
+ ClientData clientData, /* Information about menu widget. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument strings. */
+{
+ register TkMenu *menuPtr = clientData;
+ register TkMenuEntry *mePtr;
+ int result = TCL_OK;
+ int option;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObjStruct(interp, objv[1], menuOptions,
+ sizeof(char *), "option", 0, &option) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_Preserve(menuPtr);
+
+ switch ((enum options) option) {
+ case MENU_ACTIVATE: {
+ int index;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index");
+ goto error;
+ }
+ if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
+ goto error;
+ }
+ if (menuPtr->active == index) {
+ goto done;
+ }
+ if ((index >= 0) && ((menuPtr->entries[index]->type==SEPARATOR_ENTRY)
+ || (menuPtr->entries[index]->state == ENTRY_DISABLED))) {
+ index = -1;
+ }
+ result = TkActivateMenuEntry(menuPtr, index);
+ break;
+ }
+ case MENU_ADD:
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "type ?-option value ...?");
+ goto error;
+ }
+
+ if (MenuAddOrInsert(interp, menuPtr, NULL, objc-2, objv+2) != TCL_OK){
+ goto error;
+ }
+ break;
+ case MENU_CGET: {
+ Tcl_Obj *resultPtr;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option");
+ goto error;
+ }
+ resultPtr = Tk_GetOptionValue(interp, (char *) menuPtr,
+ tsdPtr->menuOptionTable, objv[2],
+ menuPtr->tkwin);
+ if (resultPtr == NULL) {
+ goto error;
+ }
+ Tcl_SetObjResult(interp, resultPtr);
+ break;
+ }
+ case MENU_CLONE:
+ if ((objc < 3) || (objc > 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "newMenuName ?menuType?");
+ goto error;
+ }
+ result = CloneMenu(menuPtr, objv[2], (objc == 3) ? NULL : objv[3]);
+ break;
+ case MENU_CONFIGURE: {
+ Tcl_Obj *resultPtr;
+
+ if (objc == 2) {
+ resultPtr = Tk_GetOptionInfo(interp, (char *) menuPtr,
+ tsdPtr->menuOptionTable, NULL,
+ menuPtr->tkwin);
+ if (resultPtr == NULL) {
+ result = TCL_ERROR;
+ } else {
+ result = TCL_OK;
+ Tcl_SetObjResult(interp, resultPtr);
+ }
+ } else if (objc == 3) {
+ resultPtr = Tk_GetOptionInfo(interp, (char *) menuPtr,
+ tsdPtr->menuOptionTable, objv[2],
+ menuPtr->tkwin);
+ if (resultPtr == NULL) {
+ result = TCL_ERROR;
+ } else {
+ result = TCL_OK;
+ Tcl_SetObjResult(interp, resultPtr);
+ }
+ } else {
+ result = ConfigureMenu(interp, menuPtr, objc - 2, objv + 2);
+ }
+ if (result != TCL_OK) {
+ goto error;
+ }
+ break;
+ }
+ case MENU_DELETE: {
+ int first, last;
+
+ if ((objc != 3) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "first ?last?");
+ goto error;
+ }
+
+ /*
+ * If 'first' explicitly refers to past the end of the menu, we don't
+ * do anything. [Bug 220950]
+ */
+
+ if (isdigit(UCHAR(Tcl_GetString(objv[2])[0]))
+ && Tcl_GetIntFromObj(NULL, objv[2], &first) == TCL_OK) {
+ if (first >= menuPtr->numEntries) {
+ goto done;
+ }
+ } else if (TkGetMenuIndex(interp,menuPtr,objv[2],0,&first) != TCL_OK){
+ goto error;
+ }
+ if (objc == 3) {
+ last = first;
+ } else if (TkGetMenuIndex(interp,menuPtr,objv[3],0,&last) != TCL_OK) {
+ goto error;
+ }
+
+ if (menuPtr->tearoff && (first == 0)) {
+ /*
+ * Sorry, can't delete the tearoff entry; must reconfigure the
+ * menu.
+ */
+
+ first = 1;
+ }
+ if ((first < 0) || (last < first)) {
+ goto done;
+ }
+ DeleteMenuCloneEntries(menuPtr, first, last);
+ break;
+ }
+ case MENU_ENTRYCGET: {
+ int index;
+ Tcl_Obj *resultPtr;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index option");
+ goto error;
+ }
+ if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
+ goto error;
+ }
+ if (index < 0) {
+ goto done;
+ }
+ mePtr = menuPtr->entries[index];
+ Tcl_Preserve(mePtr);
+ resultPtr = Tk_GetOptionValue(interp, (char *) mePtr,
+ mePtr->optionTable, objv[3], menuPtr->tkwin);
+ Tcl_Release(mePtr);
+ if (resultPtr == NULL) {
+ goto error;
+ }
+ Tcl_SetObjResult(interp, resultPtr);
+ break;
+ }
+ case MENU_ENTRYCONFIGURE: {
+ int index;
+ Tcl_Obj *resultPtr;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index ?-option value ...?");
+ goto error;
+ }
+ if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
+ goto error;
+ }
+ if (index < 0) {
+ goto done;
+ }
+ mePtr = menuPtr->entries[index];
+ Tcl_Preserve(mePtr);
+ if (objc == 3) {
+ resultPtr = Tk_GetOptionInfo(interp, (char *) mePtr,
+ mePtr->optionTable, NULL, menuPtr->tkwin);
+ if (resultPtr == NULL) {
+ result = TCL_ERROR;
+ } else {
+ result = TCL_OK;
+ Tcl_SetObjResult(interp, resultPtr);
+ }
+ } else if (objc == 4) {
+ resultPtr = Tk_GetOptionInfo(interp, (char *) mePtr,
+ mePtr->optionTable, objv[3], menuPtr->tkwin);
+ if (resultPtr == NULL) {
+ result = TCL_ERROR;
+ } else {
+ result = TCL_OK;
+ Tcl_SetObjResult(interp, resultPtr);
+ }
+ } else {
+ result = ConfigureMenuCloneEntries(interp, menuPtr, index,
+ objc-3, objv+3);
+ }
+ Tcl_Release(mePtr);
+ break;
+ }
+ case MENU_INDEX: {
+ int index;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "string");
+ goto error;
+ }
+ if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
+ goto error;
+ }
+ if (index < 0) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("none", -1));
+ } else {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(index));
+ }
+ break;
+ }
+ case MENU_INSERT:
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "index type ?-option value ...?");
+ goto error;
+ }
+ if (MenuAddOrInsert(interp,menuPtr,objv[2],objc-3,objv+3) != TCL_OK) {
+ goto error;
+ }
+ break;
+ case MENU_INVOKE: {
+ int index;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index");
+ goto error;
+ }
+ if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
+ goto error;
+ }
+ if (index < 0) {
+ goto done;
+ }
+ result = TkInvokeMenu(interp, menuPtr, index);
+ break;
+ }
+ case MENU_POST: {
+ int x, y, index = -1;
+
+ if (objc != 4 && objc != 5) {
+ Tcl_WrongNumArgs(interp, 2, objv, "x y ?index?");
+ goto error;
+ }
+ if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {
+ goto error;
+ }
+ if (objc == 5) {
+ if (TkGetMenuIndex(interp, menuPtr, objv[4], 0, &index) != TCL_OK) {
+ goto error;
+ }
+ }
+
+ /*
+ * Tearoff menus are the same as ordinary menus on the Mac and are
+ * posted differently on Windows than non-tearoffs. TkpPostMenu
+ * does not actually map the menu's window on those platforms, and
+ * popup menus have to be handled specially. Also, menubar menus are
+ * not intended to be posted (bug 1567681, 2160206).
+ */
+
+ if (menuPtr->menuType == MENUBAR) {
+ Tcl_AppendResult(interp, "a menubar menu cannot be posted", NULL);
+ return TCL_ERROR;
+ } else if (menuPtr->menuType != TEAROFF_MENU) {
+ result = TkpPostMenu(interp, menuPtr, x, y, index);
+ } else {
+ result = TkpPostTearoffMenu(interp, menuPtr, x, y, index);
+ }
+ break;
+ }
+ case MENU_POSTCASCADE: {
+ int index;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index");
+ goto error;
+ }
+
+ if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
+ goto error;
+ }
+ if ((index < 0) || (menuPtr->entries[index]->type != CASCADE_ENTRY)) {
+ result = TkPostSubmenu(interp, menuPtr, NULL);
+ } else {
+ result = TkPostSubmenu(interp, menuPtr, menuPtr->entries[index]);
+ }
+ break;
+ }
+ case MENU_TYPE: {
+ int index;
+ const char *typeStr;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index");
+ goto error;
+ }
+ if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
+ goto error;
+ }
+ if (index < 0) {
+ goto done;
+ }
+ if (menuPtr->entries[index]->type == TEAROFF_ENTRY) {
+ typeStr = "tearoff";
+ } else {
+ typeStr = menuEntryTypeStrings[menuPtr->entries[index]->type];
+ }
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(typeStr, -1));
+ break;
+ }
+ case MENU_UNPOST:
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ goto error;
+ }
+ Tk_UnmapWindow(menuPtr->tkwin);
+ result = TkPostSubmenu(interp, menuPtr, NULL);
+ break;
+ case MENU_XPOSITION:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index");
+ goto error;
+ }
+ result = MenuDoXPosition(interp, menuPtr, objv[2]);
+ break;
+ case MENU_YPOSITION:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index");
+ goto error;
+ }
+ result = MenuDoYPosition(interp, menuPtr, objv[2]);
+ break;
+ }
+ done:
+ Tcl_Release(menuPtr);
+ return result;
+
+ error:
+ Tcl_Release(menuPtr);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkInvokeMenu --
+ *
+ * Given a menu and an index, takes the appropriate action for the entry
+ * associated with that index.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * Commands may get excecuted; variables may get set; sub-menus may get
+ * posted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkInvokeMenu(
+ Tcl_Interp *interp, /* The interp that the menu lives in. */
+ TkMenu *menuPtr, /* The menu we are invoking. */
+ int index) /* The zero based index of the item we are
+ * invoking. */
+{
+ int result = TCL_OK;
+ TkMenuEntry *mePtr;
+
+ if (index < 0) {
+ goto done;
+ }
+ mePtr = menuPtr->entries[index];
+ if (mePtr->state == ENTRY_DISABLED) {
+ goto done;
+ }
+
+ Tcl_Preserve(mePtr);
+ if (mePtr->type == TEAROFF_ENTRY) {
+ Tcl_DString ds;
+
+ Tcl_DStringInit(&ds);
+ Tcl_DStringAppend(&ds, "tk::TearOffMenu ", -1);
+ Tcl_DStringAppend(&ds, Tk_PathName(menuPtr->tkwin), -1);
+ result = Tcl_EvalEx(interp, Tcl_DStringValue(&ds), -1, 0);
+ Tcl_DStringFree(&ds);
+ } else if ((mePtr->type == CHECK_BUTTON_ENTRY)
+ && (mePtr->namePtr != NULL)) {
+ Tcl_Obj *valuePtr;
+
+ if (mePtr->entryFlags & ENTRY_SELECTED) {
+ valuePtr = mePtr->offValuePtr;
+ } else {
+ valuePtr = mePtr->onValuePtr;
+ }
+ if (valuePtr == NULL) {
+ valuePtr = Tcl_NewObj();
+ }
+ Tcl_IncrRefCount(valuePtr);
+ if (Tcl_ObjSetVar2(interp, mePtr->namePtr, NULL, valuePtr,
+ TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
+ result = TCL_ERROR;
+ }
+ Tcl_DecrRefCount(valuePtr);
+ } else if ((mePtr->type == RADIO_BUTTON_ENTRY)
+ && (mePtr->namePtr != NULL)) {
+ Tcl_Obj *valuePtr = mePtr->onValuePtr;
+
+ if (valuePtr == NULL) {
+ valuePtr = Tcl_NewObj();
+ }
+ Tcl_IncrRefCount(valuePtr);
+ if (Tcl_ObjSetVar2(interp, mePtr->namePtr, NULL, valuePtr,
+ TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
+ result = TCL_ERROR;
+ }
+ Tcl_DecrRefCount(valuePtr);
+ }
+
+ /*
+ * We check numEntries in addition to whether the menu entry has a command
+ * because that goes to zero if the menu gets deleted (e.g., during
+ * command evaluation).
+ */
+
+ if ((menuPtr->numEntries != 0) && (result == TCL_OK)
+ && (mePtr->commandPtr != NULL)) {
+ Tcl_Obj *commandPtr = mePtr->commandPtr;
+
+ Tcl_IncrRefCount(commandPtr);
+ result = Tcl_EvalObjEx(interp, commandPtr, TCL_EVAL_GLOBAL);
+ Tcl_DecrRefCount(commandPtr);
+ }
+ Tcl_Release(mePtr);
+
+ done:
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyMenuInstance --
+ *
+ * This function is invoked by TkDestroyMenu to clean up the internal
+ * structure of a menu at a safe time (when no-one is using it anymore).
+ * Only takes care of one instance of the menu.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Everything associated with the menu is freed up.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DestroyMenuInstance(
+ TkMenu *menuPtr) /* Info about menu widget. */
+{
+ int i;
+ TkMenu *menuInstancePtr;
+ TkMenuEntry *cascadePtr, *nextCascadePtr;
+ Tcl_Obj *newObjv[2];
+ TkMenu *parentMasterMenuPtr;
+ TkMenuEntry *parentMasterEntryPtr;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ /*
+ * If the menu has any cascade menu entries pointing to it, the cascade
+ * entries need to be told that the menu is going away. We need to clear
+ * the menu ptr field in the menu reference at this point in the code so
+ * that everything else can forget about this menu properly. We also need
+ * to reset -menu field of all entries that are not master menus back to
+ * this entry name if this is a master menu pointed to by another master
+ * menu. If there is a clone menu that points to this menu, then this menu
+ * is itself a clone, so when this menu goes away, the -menu field of the
+ * pointing entry must be set back to this menu's master menu name so that
+ * later if another menu is created the cascade hierarchy can be
+ * maintained.
+ */
+
+ TkpDestroyMenu(menuPtr);
+ if (menuPtr->menuRefPtr == NULL) {
+ return;
+ }
+ cascadePtr = menuPtr->menuRefPtr->parentEntryPtr;
+ menuPtr->menuRefPtr->menuPtr = NULL;
+ if (TkFreeMenuReferences(menuPtr->menuRefPtr)) {
+ menuPtr->menuRefPtr = NULL;
+ }
+
+ for (; cascadePtr != NULL; cascadePtr = nextCascadePtr) {
+ nextCascadePtr = cascadePtr->nextCascadePtr;
+
+ if (menuPtr->masterMenuPtr != menuPtr) {
+ Tcl_Obj *menuNamePtr = Tcl_NewStringObj("-menu", -1);
+
+ parentMasterMenuPtr = cascadePtr->menuPtr->masterMenuPtr;
+ parentMasterEntryPtr =
+ parentMasterMenuPtr->entries[cascadePtr->index];
+ newObjv[0] = menuNamePtr;
+ newObjv[1] = parentMasterEntryPtr->namePtr;
+
+ /*
+ * It is possible that the menu info is out of sync, and these
+ * things point to NULL, so verify existence [Bug: 3402]
+ */
+
+ if (newObjv[0] && newObjv[1]) {
+ Tcl_IncrRefCount(newObjv[0]);
+ Tcl_IncrRefCount(newObjv[1]);
+ ConfigureMenuEntry(cascadePtr, 2, newObjv);
+ Tcl_DecrRefCount(newObjv[0]);
+ Tcl_DecrRefCount(newObjv[1]);
+ }
+ } else {
+ ConfigureMenuEntry(cascadePtr, 0, NULL);
+ }
+ }
+
+ if (menuPtr->masterMenuPtr != menuPtr) {
+ for (menuInstancePtr = menuPtr->masterMenuPtr;
+ menuInstancePtr != NULL;
+ menuInstancePtr = menuInstancePtr->nextInstancePtr) {
+ if (menuInstancePtr->nextInstancePtr == menuPtr) {
+ menuInstancePtr->nextInstancePtr =
+ menuInstancePtr->nextInstancePtr->nextInstancePtr;
+ break;
+ }
+ }
+ } else if (menuPtr->nextInstancePtr != NULL) {
+ Tcl_Panic("Attempting to delete master menu when there are still clones");
+ }
+
+ /*
+ * Free up all the stuff that requires special handling, then let
+ * Tk_FreeConfigOptions handle all the standard option-related stuff.
+ */
+
+ for (i = menuPtr->numEntries; --i >= 0; ) {
+ /*
+ * As each menu entry is deleted from the end of the array of entries,
+ * decrement menuPtr->numEntries. Otherwise, the act of deleting menu
+ * entry i will dereference freed memory attempting to queue a redraw
+ * for menu entries (i+1)...numEntries.
+ */
+
+ DestroyMenuEntry(menuPtr->entries[i]);
+ menuPtr->numEntries = i;
+ }
+ if (menuPtr->entries != NULL) {
+ ckfree(menuPtr->entries);
+ }
+ TkMenuFreeDrawOptions(menuPtr);
+ Tk_FreeConfigOptions((char *) menuPtr,
+ tsdPtr->menuOptionTable, menuPtr->tkwin);
+ if (menuPtr->tkwin != NULL) {
+ Tk_Window tkwin = menuPtr->tkwin;
+
+ menuPtr->tkwin = NULL;
+ Tk_DestroyWindow(tkwin);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkDestroyMenu --
+ *
+ * This function is invoked by Tcl_EventuallyFree or Tcl_Release to clean
+ * up the internal structure of a menu at a safe time (when no-one is
+ * using it anymore). If called on a master instance, destroys all of the
+ * slave instances. If called on a non-master instance, just destroys
+ * that instance.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Everything associated with the menu is freed up.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkDestroyMenu(
+ TkMenu *menuPtr) /* Info about menu widget. */
+{
+ TkMenu *menuInstancePtr;
+ TkMenuTopLevelList *topLevelListPtr, *nextTopLevelPtr;
+
+ if (menuPtr->menuFlags & MENU_DELETION_PENDING) {
+ return;
+ }
+
+ Tcl_Preserve(menuPtr);
+
+ /*
+ * Now destroy all non-tearoff instances of this menu if this is a parent
+ * menu. Is this loop safe enough? Are there going to be destroy bindings
+ * on child menus which kill the parent? If not, we have to do a slightly
+ * more complex scheme.
+ */
+
+ menuPtr->menuFlags |= MENU_DELETION_PENDING;
+ if (menuPtr->menuRefPtr != NULL) {
+ /*
+ * If any toplevel widgets have this menu as their menubar, the
+ * geometry of the window may have to be recalculated.
+ */
+
+ topLevelListPtr = menuPtr->menuRefPtr->topLevelListPtr;
+ while (topLevelListPtr != NULL) {
+ nextTopLevelPtr = topLevelListPtr->nextPtr;
+ TkpSetWindowMenuBar(topLevelListPtr->tkwin, NULL);
+ topLevelListPtr = nextTopLevelPtr;
+ }
+ }
+ if (menuPtr->masterMenuPtr == menuPtr) {
+ while (menuPtr->nextInstancePtr != NULL) {
+ menuInstancePtr = menuPtr->nextInstancePtr;
+ menuPtr->nextInstancePtr = menuInstancePtr->nextInstancePtr;
+ if (menuInstancePtr->tkwin != NULL) {
+ Tk_Window tkwin = menuInstancePtr->tkwin;
+
+ /*
+ * Note: it may be desirable to NULL out the tkwin field of
+ * menuInstancePtr here:
+ * menuInstancePtr->tkwin = NULL;
+ */
+
+ Tk_DestroyWindow(tkwin);
+ }
+ }
+ }
+
+ DestroyMenuInstance(menuPtr);
+
+ Tcl_Release(menuPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UnhookCascadeEntry --
+ *
+ * This entry is removed from the list of entries that point to the
+ * cascade menu. This is done in preparation for changing the menu that
+ * this entry points to.
+ *
+ * At the end of this function, the menu entry no longer contains a
+ * reference to a 'TkMenuReferences' structure, and therefore no such
+ * structure contains a reference to this menu entry either.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * The appropriate lists are modified.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UnhookCascadeEntry(
+ TkMenuEntry *mePtr) /* The cascade entry we are removing from the
+ * cascade list. */
+{
+ TkMenuEntry *cascadeEntryPtr;
+ TkMenuEntry *prevCascadePtr;
+ TkMenuReferences *menuRefPtr;
+
+ menuRefPtr = mePtr->childMenuRefPtr;
+ if (menuRefPtr == NULL) {
+ return;
+ }
+
+ cascadeEntryPtr = menuRefPtr->parentEntryPtr;
+ if (cascadeEntryPtr == NULL) {
+ TkFreeMenuReferences(menuRefPtr);
+ mePtr->childMenuRefPtr = NULL;
+ return;
+ }
+
+ /*
+ * Singularly linked list deletion. The two special cases are 1. one
+ * element; 2. The first element is the one we want.
+ */
+
+ if (cascadeEntryPtr == mePtr) {
+ if (cascadeEntryPtr->nextCascadePtr == NULL) {
+ /*
+ * This is the last menu entry which points to this menu, so we
+ * need to clear out the list pointer in the cascade itself.
+ */
+
+ menuRefPtr->parentEntryPtr = NULL;
+
+ /*
+ * The original field is set to zero below, after it is freed.
+ */
+
+ TkFreeMenuReferences(menuRefPtr);
+ } else {
+ menuRefPtr->parentEntryPtr = cascadeEntryPtr->nextCascadePtr;
+ }
+ mePtr->nextCascadePtr = NULL;
+ } else {
+ for (prevCascadePtr = cascadeEntryPtr,
+ cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr;
+ cascadeEntryPtr != NULL;
+ prevCascadePtr = cascadeEntryPtr,
+ cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) {
+ if (cascadeEntryPtr == mePtr){
+ prevCascadePtr->nextCascadePtr =
+ cascadeEntryPtr->nextCascadePtr;
+ cascadeEntryPtr->nextCascadePtr = NULL;
+ break;
+ }
+ }
+ mePtr->nextCascadePtr = NULL;
+ }
+ mePtr->childMenuRefPtr = NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyMenuEntry --
+ *
+ * This function is invoked by Tcl_EventuallyFree or Tcl_Release to clean
+ * up the internal structure of a menu entry at a safe time (when no-one
+ * is using it anymore).
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Everything associated with the menu entry is freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DestroyMenuEntry(
+ void *memPtr) /* Pointer to entry to be freed. */
+{
+ register TkMenuEntry *mePtr = memPtr;
+ TkMenu *menuPtr = mePtr->menuPtr;
+
+ if (menuPtr->postedCascade == mePtr) {
+ /*
+ * Ignore errors while unposting the menu, since it's possible that
+ * the menu has already been deleted and the unpost will generate an
+ * error.
+ */
+
+ TkPostSubmenu(menuPtr->interp, menuPtr, NULL);
+ }
+
+ /*
+ * Free up all the stuff that requires special handling, then let
+ * Tk_FreeConfigOptions handle all the standard option-related stuff.
+ */
+
+ if (mePtr->type == CASCADE_ENTRY) {
+ if (menuPtr->masterMenuPtr != menuPtr) {
+ TkMenu *destroyThis = NULL;
+ TkMenuReferences *menuRefPtr = mePtr->childMenuRefPtr;
+
+ /*
+ * The menu as a whole is a clone. We must delete the clone of the
+ * cascaded menu for the particular entry we are destroying.
+ */
+
+ if (menuRefPtr != NULL) {
+ destroyThis = menuRefPtr->menuPtr;
+
+ /*
+ * But only if it is a clone. What can happen is that we are
+ * in the middle of deleting a menu and this menu pointer has
+ * already been reset to point to the original menu. In that
+ * case we have nothing special to do.
+ */
+
+ if ((destroyThis != NULL)
+ && (destroyThis->masterMenuPtr == destroyThis)) {
+ destroyThis = NULL;
+ }
+ }
+ UnhookCascadeEntry(mePtr);
+ menuRefPtr = mePtr->childMenuRefPtr;
+ if (menuRefPtr != NULL) {
+ if (menuRefPtr->menuPtr == destroyThis) {
+ menuRefPtr->menuPtr = NULL;
+ }
+ }
+ if (destroyThis != NULL) {
+ TkDestroyMenu(destroyThis);
+ }
+ } else {
+ UnhookCascadeEntry(mePtr);
+ }
+ }
+ if (mePtr->image != NULL) {
+ Tk_FreeImage(mePtr->image);
+ }
+ if (mePtr->selectImage != NULL) {
+ Tk_FreeImage(mePtr->selectImage);
+ }
+ if (((mePtr->type == CHECK_BUTTON_ENTRY)
+ || (mePtr->type == RADIO_BUTTON_ENTRY))
+ && (mePtr->namePtr != NULL)) {
+ const char *varName = Tcl_GetString(mePtr->namePtr);
+
+ Tcl_UntraceVar2(menuPtr->interp, varName, NULL,
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ MenuVarProc, mePtr);
+ }
+ TkpDestroyMenuEntry(mePtr);
+ TkMenuEntryFreeDrawOptions(mePtr);
+ Tk_FreeConfigOptions((char *) mePtr, mePtr->optionTable, menuPtr->tkwin);
+ ckfree(mePtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MenuWorldChanged --
+ *
+ * This function is called when the world has changed in some way (such
+ * as the fonts in the system changing) and the widget needs to recompute
+ * all its graphics contexts and determine its new geometry.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Menu will be relayed out and redisplayed.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+MenuWorldChanged(
+ ClientData instanceData) /* Information about widget. */
+{
+ TkMenu *menuPtr = instanceData;
+ int i;
+
+ TkMenuConfigureDrawOptions(menuPtr);
+ for (i = 0; i < menuPtr->numEntries; i++) {
+ TkMenuConfigureEntryDrawOptions(menuPtr->entries[i],
+ menuPtr->entries[i]->index);
+ TkpConfigureMenuEntry(menuPtr->entries[i]);
+ }
+ TkEventuallyRecomputeMenu(menuPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConfigureMenu --
+ *
+ * This function is called to process an argv/argc list, plus the Tk
+ * option database, in order to configure (or reconfigure) a menu widget.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If TCL_ERROR is returned,
+ * then the interp's result contains an error message.
+ *
+ * Side effects:
+ * Configuration information, such as colors, font, etc. get set for
+ * menuPtr; old resources get freed, if there were any.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ConfigureMenu(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ register TkMenu *menuPtr, /* Information about widget; may or may not
+ * already have values for some fields. */
+ int objc, /* Number of valid entries in argv. */
+ Tcl_Obj *const objv[]) /* Arguments. */
+{
+ int i;
+ TkMenu *menuListPtr, *cleanupPtr;
+ int result;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ for (menuListPtr = menuPtr->masterMenuPtr; menuListPtr != NULL;
+ menuListPtr = menuListPtr->nextInstancePtr) {
+ menuListPtr->errorStructPtr = ckalloc(sizeof(Tk_SavedOptions));
+ result = Tk_SetOptions(interp, (char *) menuListPtr,
+ tsdPtr->menuOptionTable, objc, objv,
+ menuListPtr->tkwin, menuListPtr->errorStructPtr, NULL);
+ if (result != TCL_OK) {
+ for (cleanupPtr = menuPtr->masterMenuPtr;
+ cleanupPtr != menuListPtr;
+ cleanupPtr = cleanupPtr->nextInstancePtr) {
+ Tk_RestoreSavedOptions(cleanupPtr->errorStructPtr);
+ ckfree(cleanupPtr->errorStructPtr);
+ cleanupPtr->errorStructPtr = NULL;
+ }
+ if (menuListPtr->errorStructPtr != NULL) {
+ Tk_RestoreSavedOptions(menuListPtr->errorStructPtr);
+ ckfree(menuListPtr->errorStructPtr);
+ menuListPtr->errorStructPtr = NULL;
+ }
+ return TCL_ERROR;
+ }
+
+ /*
+ * When a menu is created, the type is in all of the arguments to the
+ * menu command. Let Tk_ConfigureWidget take care of parsing them, and
+ * then set the type after we can look at the type string. Once set, a
+ * menu's type cannot be changed
+ */
+
+ if (menuListPtr->menuType == UNKNOWN_TYPE) {
+ Tcl_GetIndexFromObjStruct(NULL, menuListPtr->menuTypePtr,
+ menuTypeStrings, sizeof(char *), NULL, 0, &menuListPtr->menuType);
+
+ /*
+ * Configure the new window to be either a pop-up menu or a
+ * tear-off menu. We don't do this for menubars since they are not
+ * toplevel windows. Also, since this gets called before CloneMenu
+ * has a chance to set the menuType field, we have to look at the
+ * menuTypeName field to tell that this is a menu bar.
+ */
+
+ if (menuListPtr->menuType == MASTER_MENU) {
+ int typeFlag = TK_MAKE_MENU_POPUP;
+ Tk_Window tkwin = menuPtr->tkwin;
+
+ /*
+ * Work out if we are the child of a menubar or a popup.
+ */
+
+ while (1) {
+ Tk_Window parent = Tk_Parent(tkwin);
+
+ if (Tk_Class(parent) != Tk_Class(menuPtr->tkwin)) {
+ break;
+ }
+ tkwin = parent;
+ }
+ if (((TkMenu *) tkwin)->menuType == MENUBAR) {
+ typeFlag = TK_MAKE_MENU_DROPDOWN;
+ }
+
+ TkpMakeMenuWindow(menuListPtr->tkwin, typeFlag);
+ } else if (menuListPtr->menuType == TEAROFF_MENU) {
+ TkpMakeMenuWindow(menuListPtr->tkwin, TK_MAKE_MENU_TEAROFF);
+ }
+ }
+
+ /*
+ * Depending on the -tearOff option, make sure that there is or isn't
+ * an initial tear-off entry at the beginning of the menu.
+ */
+
+ if (menuListPtr->tearoff) {
+ if ((menuListPtr->numEntries == 0)
+ || (menuListPtr->entries[0]->type != TEAROFF_ENTRY)) {
+ if (MenuNewEntry(menuListPtr, 0, TEAROFF_ENTRY) == NULL) {
+ for (cleanupPtr = menuPtr->masterMenuPtr;
+ cleanupPtr != menuListPtr;
+ cleanupPtr = cleanupPtr->nextInstancePtr) {
+ Tk_RestoreSavedOptions(cleanupPtr->errorStructPtr);
+ ckfree(cleanupPtr->errorStructPtr);
+ cleanupPtr->errorStructPtr = NULL;
+ }
+ if (menuListPtr->errorStructPtr != NULL) {
+ Tk_RestoreSavedOptions(menuListPtr->errorStructPtr);
+ ckfree(menuListPtr->errorStructPtr);
+ menuListPtr->errorStructPtr = NULL;
+ }
+ return TCL_ERROR;
+ }
+ }
+ } else if ((menuListPtr->numEntries > 0)
+ && (menuListPtr->entries[0]->type == TEAROFF_ENTRY)) {
+ int i;
+
+ Tcl_EventuallyFree(menuListPtr->entries[0], (Tcl_FreeProc *) DestroyMenuEntry);
+
+ for (i = 0; i < menuListPtr->numEntries - 1; i++) {
+ menuListPtr->entries[i] = menuListPtr->entries[i + 1];
+ menuListPtr->entries[i]->index = i;
+ }
+ menuListPtr->numEntries--;
+ if (menuListPtr->numEntries == 0) {
+ ckfree(menuListPtr->entries);
+ menuListPtr->entries = NULL;
+ }
+ }
+
+ TkMenuConfigureDrawOptions(menuListPtr);
+
+ /*
+ * After reconfiguring a menu, we need to reconfigure all of the
+ * entries in the menu, since some of the things in the children (such
+ * as graphics contexts) may have to change to reflect changes in the
+ * parent.
+ */
+
+ for (i = 0; i < menuListPtr->numEntries; i++) {
+ TkMenuEntry *mePtr;
+
+ mePtr = menuListPtr->entries[i];
+ ConfigureMenuEntry(mePtr, 0, NULL);
+ }
+
+ TkEventuallyRecomputeMenu(menuListPtr);
+ }
+
+ for (cleanupPtr = menuPtr->masterMenuPtr; cleanupPtr != NULL;
+ cleanupPtr = cleanupPtr->nextInstancePtr) {
+ Tk_FreeSavedOptions(cleanupPtr->errorStructPtr);
+ ckfree(cleanupPtr->errorStructPtr);
+ cleanupPtr->errorStructPtr = NULL;
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PostProcessEntry --
+ *
+ * This is called by ConfigureMenuEntry to do all of the configuration
+ * after Tk_SetOptions is called. This is separate so that error handling
+ * is easier.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If TCL_ERROR is returned,
+ * then the interp's result contains an error message.
+ *
+ * Side effects:
+ * Configuration information such as label and accelerator get set for
+ * mePtr; old resources get freed, if there were any.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+PostProcessEntry(
+ TkMenuEntry *mePtr) /* The entry we are configuring. */
+{
+ TkMenu *menuPtr = mePtr->menuPtr;
+ int index = mePtr->index;
+ const char *name;
+ Tk_Image image;
+
+ /*
+ * The code below handles special configuration stuff not taken care of by
+ * Tk_ConfigureWidget, such as special processing for defaults, sizing
+ * strings, graphics contexts, etc.
+ */
+
+ if (mePtr->labelPtr == NULL) {
+ mePtr->labelLength = 0;
+ } else {
+ Tcl_GetStringFromObj(mePtr->labelPtr, &mePtr->labelLength);
+ }
+ if (mePtr->accelPtr == NULL) {
+ mePtr->accelLength = 0;
+ } else {
+ Tcl_GetStringFromObj(mePtr->accelPtr, &mePtr->accelLength);
+ }
+
+ /*
+ * If this is a cascade entry, the platform-specific data of the child
+ * menu has to be updated. Also, the links that point to parents and
+ * cascades have to be updated.
+ */
+
+ if ((mePtr->type == CASCADE_ENTRY) && (mePtr->namePtr != NULL)) {
+ TkMenuEntry *cascadeEntryPtr;
+ int alreadyThere;
+ TkMenuReferences *menuRefPtr;
+ char *oldHashKey = NULL; /* Initialization only needed to
+ * prevent compiler warning. */
+
+ /*
+ * This is a cascade entry. If the menu that the cascade entry is
+ * pointing to has changed, we need to remove this entry from the list
+ * of entries pointing to the old menu, and add a cascade reference to
+ * the list of entries pointing to the new menu.
+ *
+ * BUG: We are not recloning for special case #3 yet.
+ */
+
+ name = Tcl_GetString(mePtr->namePtr);
+ if (mePtr->childMenuRefPtr != NULL) {
+ oldHashKey = Tcl_GetHashKey(TkGetMenuHashTable(menuPtr->interp),
+ mePtr->childMenuRefPtr->hashEntryPtr);
+ if (strcmp(oldHashKey, name) != 0) {
+ UnhookCascadeEntry(mePtr);
+ }
+ }
+
+ if ((mePtr->childMenuRefPtr == NULL)
+ || (strcmp(oldHashKey, name) != 0)) {
+ menuRefPtr = TkCreateMenuReferences(menuPtr->interp, name);
+ mePtr->childMenuRefPtr = menuRefPtr;
+
+ if (menuRefPtr->parentEntryPtr == NULL) {
+ menuRefPtr->parentEntryPtr = mePtr;
+ } else {
+ alreadyThere = 0;
+ for (cascadeEntryPtr = menuRefPtr->parentEntryPtr;
+ cascadeEntryPtr != NULL;
+ cascadeEntryPtr =
+ cascadeEntryPtr->nextCascadePtr) {
+ if (cascadeEntryPtr == mePtr) {
+ alreadyThere = 1;
+ break;
+ }
+ }
+
+ /*
+ * Put the item at the front of the list.
+ */
+
+ if (!alreadyThere) {
+ mePtr->nextCascadePtr = menuRefPtr->parentEntryPtr;
+ menuRefPtr->parentEntryPtr = mePtr;
+ }
+ }
+ }
+ }
+
+ if (TkMenuConfigureEntryDrawOptions(mePtr, index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Get the images for the entry, if there are any. Allocate the new images
+ * before freeing the old ones, so that the reference counts don't go to
+ * zero and cause image data to be discarded.
+ */
+
+ if (mePtr->imagePtr != NULL) {
+ const char *imageString = Tcl_GetString(mePtr->imagePtr);
+
+ image = Tk_GetImage(menuPtr->interp, menuPtr->tkwin, imageString,
+ TkMenuImageProc, mePtr);
+ if (image == NULL) {
+ return TCL_ERROR;
+ }
+ } else {
+ image = NULL;
+ }
+ if (mePtr->image != NULL) {
+ Tk_FreeImage(mePtr->image);
+ }
+ mePtr->image = image;
+ if (mePtr->selectImagePtr != NULL) {
+ const char *selectImageString = Tcl_GetString(mePtr->selectImagePtr);
+
+ image = Tk_GetImage(menuPtr->interp, menuPtr->tkwin, selectImageString,
+ TkMenuSelectImageProc, mePtr);
+ if (image == NULL) {
+ return TCL_ERROR;
+ }
+ } else {
+ image = NULL;
+ }
+ if (mePtr->selectImage != NULL) {
+ Tk_FreeImage(mePtr->selectImage);
+ }
+ mePtr->selectImage = image;
+
+ if ((mePtr->type == CHECK_BUTTON_ENTRY)
+ || (mePtr->type == RADIO_BUTTON_ENTRY)) {
+ Tcl_Obj *valuePtr;
+ const char *name;
+
+ if (mePtr->namePtr == NULL) {
+ if (mePtr->labelPtr == NULL) {
+ mePtr->namePtr = NULL;
+ } else {
+ mePtr->namePtr = Tcl_DuplicateObj(mePtr->labelPtr);
+ Tcl_IncrRefCount(mePtr->namePtr);
+ }
+ }
+ if (mePtr->onValuePtr == NULL) {
+ if (mePtr->labelPtr == NULL) {
+ mePtr->onValuePtr = NULL;
+ } else {
+ mePtr->onValuePtr = Tcl_DuplicateObj(mePtr->labelPtr);
+ Tcl_IncrRefCount(mePtr->onValuePtr);
+ }
+ }
+
+ /*
+ * Select the entry if the associated variable has the appropriate
+ * value, initialize the variable if it doesn't exist, then set a
+ * trace on the variable to monitor future changes to its value.
+ */
+
+ if (mePtr->namePtr != NULL) {
+ valuePtr = Tcl_ObjGetVar2(menuPtr->interp, mePtr->namePtr, NULL,
+ TCL_GLOBAL_ONLY);
+ } else {
+ valuePtr = NULL;
+ }
+ mePtr->entryFlags &= ~ENTRY_SELECTED;
+ if (valuePtr != NULL) {
+ if (mePtr->onValuePtr != NULL) {
+ const char *value = Tcl_GetString(valuePtr);
+ const char *onValue = Tcl_GetString(mePtr->onValuePtr);
+
+ if (strcmp(value, onValue) == 0) {
+ mePtr->entryFlags |= ENTRY_SELECTED;
+ }
+ }
+ } else {
+ if (mePtr->namePtr != NULL) {
+ Tcl_ObjSetVar2(menuPtr->interp, mePtr->namePtr, NULL,
+ (mePtr->type == CHECK_BUTTON_ENTRY)
+ ? mePtr->offValuePtr : Tcl_NewObj(), TCL_GLOBAL_ONLY);
+ }
+ }
+ if (mePtr->namePtr != NULL) {
+ name = Tcl_GetString(mePtr->namePtr);
+ Tcl_TraceVar2(menuPtr->interp, name,
+ NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ MenuVarProc, mePtr);
+ }
+ }
+
+ if (TkpConfigureMenuEntry(mePtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConfigureMenuEntry --
+ *
+ * This function is called to process an argv/argc list in order to
+ * configure (or reconfigure) one entry in a menu.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If TCL_ERROR is returned,
+ * then the interp's result contains an error message.
+ *
+ * Side effects:
+ * Configuration information such as label and accelerator get set for
+ * mePtr; old resources get freed, if there were any.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ConfigureMenuEntry(
+ register TkMenuEntry *mePtr,/* Information about menu entry; may or may
+ * not already have values for some fields. */
+ int objc, /* Number of valid entries in argv. */
+ Tcl_Obj *const objv[]) /* Arguments. */
+{
+ TkMenu *menuPtr = mePtr->menuPtr;
+ Tk_SavedOptions errorStruct;
+ int result;
+
+ /*
+ * If this entry is a check button or radio button, then remove its old
+ * trace function.
+ */
+
+ if ((mePtr->namePtr != NULL)
+ && ((mePtr->type == CHECK_BUTTON_ENTRY)
+ || (mePtr->type == RADIO_BUTTON_ENTRY))) {
+ const char *name = Tcl_GetString(mePtr->namePtr);
+
+ Tcl_UntraceVar2(menuPtr->interp, name, NULL,
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ MenuVarProc, mePtr);
+ }
+
+ result = TCL_OK;
+ if (menuPtr->tkwin != NULL) {
+ if (Tk_SetOptions(menuPtr->interp, (char *) mePtr,
+ mePtr->optionTable, objc, objv, menuPtr->tkwin,
+ &errorStruct, NULL) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ result = PostProcessEntry(mePtr);
+ if (result != TCL_OK) {
+ Tk_RestoreSavedOptions(&errorStruct);
+ PostProcessEntry(mePtr);
+ }
+ Tk_FreeSavedOptions(&errorStruct);
+ }
+
+ TkEventuallyRecomputeMenu(menuPtr);
+
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConfigureMenuCloneEntries --
+ *
+ * Calls ConfigureMenuEntry for each menu in the clone chain.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If TCL_ERROR is returned,
+ * then the interp's result contains an error message.
+ *
+ * Side effects:
+ * Configuration information such as label and accelerator get set for
+ * mePtr; old resources get freed, if there were any.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ConfigureMenuCloneEntries(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ TkMenu *menuPtr, /* Information about whole menu. */
+ int index, /* Index of mePtr within menuPtr's entries. */
+ int objc, /* Number of valid entries in argv. */
+ Tcl_Obj *const objv[]) /* Arguments. */
+{
+ TkMenuEntry *mePtr;
+ TkMenu *menuListPtr;
+ int cascadeEntryChanged = 0;
+ TkMenuReferences *oldCascadeMenuRefPtr, *cascadeMenuRefPtr = NULL;
+ Tcl_Obj *oldCascadePtr = NULL;
+ const char *newCascadeName;
+
+ /*
+ * Cascades are kind of tricky here. This is special case #3 in the
+ * comment at the top of this file. Basically, if a menu is the master
+ * menu of a clone chain, and has an entry with a cascade menu, the clones
+ * of the menu will point to clones of the cascade menu. We have to
+ * destroy the clones of the cascades, clone the new cascade menu, and
+ * configure the entry to point to the new clone.
+ */
+
+ mePtr = menuPtr->masterMenuPtr->entries[index];
+ if (mePtr->type == CASCADE_ENTRY) {
+ oldCascadePtr = mePtr->namePtr;
+ if (oldCascadePtr != NULL) {
+ Tcl_IncrRefCount(oldCascadePtr);
+ }
+ }
+
+ if (ConfigureMenuEntry(mePtr, objc, objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (mePtr->type == CASCADE_ENTRY) {
+ const char *oldCascadeName;
+
+ if (mePtr->namePtr != NULL) {
+ newCascadeName = Tcl_GetString(mePtr->namePtr);
+ } else {
+ newCascadeName = NULL;
+ }
+
+ if ((oldCascadePtr == NULL) && (mePtr->namePtr == NULL)) {
+ cascadeEntryChanged = 0;
+ } else if (((oldCascadePtr == NULL) && (mePtr->namePtr != NULL))
+ || ((oldCascadePtr != NULL)
+ && (mePtr->namePtr == NULL))) {
+ cascadeEntryChanged = 1;
+ } else {
+ oldCascadeName = Tcl_GetString(oldCascadePtr);
+ cascadeEntryChanged = (strcmp(oldCascadeName, newCascadeName)
+ != 0);
+ }
+ if (oldCascadePtr != NULL) {
+ Tcl_DecrRefCount(oldCascadePtr);
+ }
+ }
+
+ if (cascadeEntryChanged) {
+ if (mePtr->namePtr != NULL) {
+ newCascadeName = Tcl_GetString(mePtr->namePtr);
+ cascadeMenuRefPtr = TkFindMenuReferences(menuPtr->interp,
+ newCascadeName);
+ }
+ }
+
+ for (menuListPtr = menuPtr->masterMenuPtr->nextInstancePtr;
+ menuListPtr != NULL;
+ menuListPtr = menuListPtr->nextInstancePtr) {
+
+ mePtr = menuListPtr->entries[index];
+
+ if (cascadeEntryChanged && (mePtr->namePtr != NULL)) {
+ oldCascadeMenuRefPtr = TkFindMenuReferencesObj(menuPtr->interp,
+ mePtr->namePtr);
+
+ if ((oldCascadeMenuRefPtr != NULL)
+ && (oldCascadeMenuRefPtr->menuPtr != NULL)) {
+ RecursivelyDeleteMenu(oldCascadeMenuRefPtr->menuPtr);
+ }
+ }
+
+ if (ConfigureMenuEntry(mePtr, objc, objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (cascadeEntryChanged && (mePtr->namePtr != NULL)) {
+ if (cascadeMenuRefPtr && cascadeMenuRefPtr->menuPtr != NULL) {
+ Tcl_Obj *newObjv[2];
+ Tcl_Obj *newCloneNamePtr;
+ Tcl_Obj *pathNamePtr = Tcl_NewStringObj(
+ Tk_PathName(menuListPtr->tkwin), -1);
+ Tcl_Obj *normalPtr = Tcl_NewStringObj("normal", -1);
+ Tcl_Obj *menuObjPtr = Tcl_NewStringObj("-menu", -1);
+
+ Tcl_IncrRefCount(pathNamePtr);
+ newCloneNamePtr = TkNewMenuName(menuPtr->interp,
+ pathNamePtr,
+ cascadeMenuRefPtr->menuPtr);
+ Tcl_IncrRefCount(newCloneNamePtr);
+ Tcl_IncrRefCount(normalPtr);
+ CloneMenu(cascadeMenuRefPtr->menuPtr, newCloneNamePtr,
+ normalPtr);
+
+ newObjv[0] = menuObjPtr;
+ newObjv[1] = newCloneNamePtr;
+ Tcl_IncrRefCount(menuObjPtr);
+ ConfigureMenuEntry(mePtr, 2, newObjv);
+ Tcl_DecrRefCount(newCloneNamePtr);
+ Tcl_DecrRefCount(pathNamePtr);
+ Tcl_DecrRefCount(normalPtr);
+ Tcl_DecrRefCount(menuObjPtr);
+ }
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkGetMenuIndex --
+ *
+ * Parse a textual index into a menu and return the numerical index of
+ * the indicated entry.
+ *
+ * Results:
+ * A standard Tcl result. If all went well, then *indexPtr is filled in
+ * with the entry index corresponding to string (ranges from -1 to the
+ * number of entries in the menu minus one). Otherwise an error message
+ * is left in the interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkGetMenuIndex(
+ Tcl_Interp *interp, /* For error messages. */
+ TkMenu *menuPtr, /* Menu for which the index is being
+ * specified. */
+ Tcl_Obj *objPtr, /* Specification of an entry in menu. See
+ * manual entry for valid .*/
+ int lastOK, /* Non-zero means its OK to return index just
+ * *after* last entry. */
+ int *indexPtr) /* Where to store converted index. */
+{
+ int i;
+ const char *string = Tcl_GetString(objPtr);
+
+ if ((string[0] == 'a') && (strcmp(string, "active") == 0)) {
+ *indexPtr = menuPtr->active;
+ goto success;
+ }
+
+ if (((string[0] == 'l') && (strcmp(string, "last") == 0))
+ || ((string[0] == 'e') && (strcmp(string, "end") == 0))) {
+ *indexPtr = menuPtr->numEntries - ((lastOK) ? 0 : 1);
+ goto success;
+ }
+
+ if ((string[0] == 'n') && (strcmp(string, "none") == 0)) {
+ *indexPtr = -1;
+ goto success;
+ }
+
+ if (string[0] == '@') {
+ if (GetIndexFromCoords(interp, menuPtr, string, indexPtr)
+ == TCL_OK) {
+ goto success;
+ }
+ }
+
+ if (isdigit(UCHAR(string[0]))) {
+ if (Tcl_GetInt(interp, string, &i) == TCL_OK) {
+ if (i >= menuPtr->numEntries) {
+ if (lastOK) {
+ i = menuPtr->numEntries;
+ } else {
+ i = menuPtr->numEntries-1;
+ }
+ } else if (i < 0) {
+ i = -1;
+ }
+ *indexPtr = i;
+ goto success;
+ }
+ Tcl_ResetResult(interp);
+ }
+
+ for (i = 0; i < menuPtr->numEntries; i++) {
+ Tcl_Obj *labelPtr = menuPtr->entries[i]->labelPtr;
+ const char *label = (labelPtr == NULL) ? NULL : Tcl_GetString(labelPtr);
+
+ if ((label != NULL) && (Tcl_StringMatch(label, string))) {
+ *indexPtr = i;
+ goto success;
+ }
+ }
+
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad menu entry index \"%s\"", string));
+ Tcl_SetErrorCode(interp, "TK", "MENU", "INDEX", NULL);
+ return TCL_ERROR;
+
+ success:
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MenuCmdDeletedProc --
+ *
+ * This function is invoked when a widget command is deleted. If the
+ * widget isn't already in the process of being destroyed, this command
+ * destroys it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The widget is destroyed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+MenuCmdDeletedProc(
+ ClientData clientData) /* Pointer to widget record for widget. */
+{
+ TkMenu *menuPtr = clientData;
+ Tk_Window tkwin = menuPtr->tkwin;
+
+ /*
+ * This function could be invoked either because the window was destroyed
+ * and the command was then deleted (in which case tkwin is NULL) or
+ * because the command was deleted, and then this function destroys the
+ * widget.
+ */
+
+ if (tkwin != NULL) {
+ /*
+ * Note: it may be desirable to NULL out the tkwin field of menuPtr
+ * here:
+ * menuPtr->tkwin = NULL;
+ */
+
+ Tk_DestroyWindow(tkwin);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MenuNewEntry --
+ *
+ * This function allocates and initializes a new menu entry.
+ *
+ * Results:
+ * The return value is a pointer to a new menu entry structure, which has
+ * been malloc-ed, initialized, and entered into the entry array for the
+ * menu.
+ *
+ * Side effects:
+ * Storage gets allocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static TkMenuEntry *
+MenuNewEntry(
+ TkMenu *menuPtr, /* Menu that will hold the new entry. */
+ int index, /* Where in the menu the new entry is to
+ * go. */
+ int type) /* The type of the new entry. */
+{
+ TkMenuEntry *mePtr;
+ TkMenuEntry **newEntries;
+ int i;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ /*
+ * Create a new array of entries with an empty slot for the new entry.
+ */
+
+ newEntries = ckalloc((menuPtr->numEntries+1) * sizeof(TkMenuEntry *));
+ for (i = 0; i < index; i++) {
+ newEntries[i] = menuPtr->entries[i];
+ }
+ for (; i < menuPtr->numEntries; i++) {
+ newEntries[i+1] = menuPtr->entries[i];
+ newEntries[i+1]->index = i + 1;
+ }
+ if (menuPtr->numEntries != 0) {
+ ckfree(menuPtr->entries);
+ }
+ menuPtr->entries = newEntries;
+ menuPtr->numEntries++;
+ mePtr = ckalloc(sizeof(TkMenuEntry));
+ menuPtr->entries[index] = mePtr;
+ mePtr->type = type;
+ mePtr->optionTable = tsdPtr->entryOptionTables[type];
+ mePtr->menuPtr = menuPtr;
+ mePtr->labelPtr = NULL;
+ mePtr->labelLength = 0;
+ mePtr->underline = -1;
+ mePtr->bitmapPtr = NULL;
+ mePtr->imagePtr = NULL;
+ mePtr->image = NULL;
+ mePtr->selectImagePtr = NULL;
+ mePtr->selectImage = NULL;
+ mePtr->accelPtr = NULL;
+ mePtr->accelLength = 0;
+ mePtr->state = ENTRY_DISABLED;
+ mePtr->borderPtr = NULL;
+ mePtr->fgPtr = NULL;
+ mePtr->activeBorderPtr = NULL;
+ mePtr->activeFgPtr = NULL;
+ mePtr->fontPtr = NULL;
+ mePtr->indicatorOn = 0;
+ mePtr->indicatorFgPtr = NULL;
+ mePtr->columnBreak = 0;
+ mePtr->hideMargin = 0;
+ mePtr->commandPtr = NULL;
+ mePtr->namePtr = NULL;
+ mePtr->childMenuRefPtr = NULL;
+ mePtr->onValuePtr = NULL;
+ mePtr->offValuePtr = NULL;
+ mePtr->entryFlags = 0;
+ mePtr->index = index;
+ mePtr->nextCascadePtr = NULL;
+ if (Tk_InitOptions(menuPtr->interp, (char *) mePtr,
+ mePtr->optionTable, menuPtr->tkwin) != TCL_OK) {
+ ckfree(mePtr);
+ return NULL;
+ }
+ TkMenuInitializeEntryDrawingFields(mePtr);
+ if (TkpMenuNewEntry(mePtr) != TCL_OK) {
+ Tk_FreeConfigOptions((char *) mePtr, mePtr->optionTable,
+ menuPtr->tkwin);
+ ckfree(mePtr);
+ return NULL;
+ }
+
+ return mePtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MenuAddOrInsert --
+ *
+ * This function does all of the work of the "add" and "insert" widget
+ * commands, allowing the code for these to be shared.
+ *
+ * Results:
+ * A standard Tcl return value.
+ *
+ * Side effects:
+ * A new menu entry is created in menuPtr.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+MenuAddOrInsert(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ TkMenu *menuPtr, /* Widget in which to create new entry. */
+ Tcl_Obj *indexPtr, /* Object describing index at which to insert.
+ * NULL means insert at end. */
+ int objc, /* Number of elements in objv. */
+ Tcl_Obj *const objv[]) /* Arguments to command: first arg is type of
+ * entry, others are config options. */
+{
+ int type, index;
+ TkMenuEntry *mePtr;
+ TkMenu *menuListPtr;
+
+ if (indexPtr != NULL) {
+ if (TkGetMenuIndex(interp, menuPtr, indexPtr, 1, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ } else {
+ index = menuPtr->numEntries;
+ }
+ if (index < 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad index \"%s\"", Tcl_GetString(indexPtr)));
+ Tcl_SetErrorCode(interp, "TK", "MENU", "INDEX", NULL);
+ return TCL_ERROR;
+ }
+ if (menuPtr->tearoff && (index == 0)) {
+ index = 1;
+ }
+
+ /*
+ * Figure out the type of the new entry.
+ */
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[0], menuEntryTypeStrings,
+ sizeof(char *), "menu entry type", 0, &type) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Now we have to add an entry for every instance related to this menu.
+ */
+
+ for (menuListPtr = menuPtr->masterMenuPtr; menuListPtr != NULL;
+ menuListPtr = menuListPtr->nextInstancePtr) {
+
+ mePtr = MenuNewEntry(menuListPtr, index, type);
+ if (mePtr == NULL) {
+ return TCL_ERROR;
+ }
+ if (ConfigureMenuEntry(mePtr, objc - 1, objv + 1) != TCL_OK) {
+ TkMenu *errorMenuPtr;
+ int i;
+
+ for (errorMenuPtr = menuPtr->masterMenuPtr;
+ errorMenuPtr != NULL;
+ errorMenuPtr = errorMenuPtr->nextInstancePtr) {
+ Tcl_EventuallyFree(errorMenuPtr->entries[index],
+ (Tcl_FreeProc *) DestroyMenuEntry);
+ for (i = index; i < errorMenuPtr->numEntries - 1; i++) {
+ errorMenuPtr->entries[i] = errorMenuPtr->entries[i + 1];
+ errorMenuPtr->entries[i]->index = i;
+ }
+ errorMenuPtr->numEntries--;
+ if (errorMenuPtr->numEntries == 0) {
+ ckfree(errorMenuPtr->entries);
+ errorMenuPtr->entries = NULL;
+ }
+ if (errorMenuPtr == menuListPtr) {
+ break;
+ }
+ }
+ return TCL_ERROR;
+ }
+
+ /*
+ * If a menu has cascades, then every instance of the menu has to have
+ * its own parallel cascade structure. So adding an entry to a menu
+ * with clones means that the menu that the entry points to has to be
+ * cloned for every clone the master menu has. This is special case #2
+ * in the comment at the top of this file.
+ */
+
+ if ((menuPtr != menuListPtr) && (type == CASCADE_ENTRY)) {
+ if ((mePtr->namePtr != NULL)
+ && (mePtr->childMenuRefPtr != NULL)
+ && (mePtr->childMenuRefPtr->menuPtr != NULL)) {
+ TkMenu *cascadeMenuPtr =
+ mePtr->childMenuRefPtr->menuPtr->masterMenuPtr;
+ Tcl_Obj *newCascadePtr, *newObjv[2];
+ Tcl_Obj *menuNamePtr = Tcl_NewStringObj("-menu", -1);
+ Tcl_Obj *windowNamePtr =
+ Tcl_NewStringObj(Tk_PathName(menuListPtr->tkwin), -1);
+ Tcl_Obj *normalPtr = Tcl_NewStringObj("normal", -1);
+ TkMenuReferences *menuRefPtr;
+
+ Tcl_IncrRefCount(windowNamePtr);
+ newCascadePtr = TkNewMenuName(menuListPtr->interp,
+ windowNamePtr, cascadeMenuPtr);
+ Tcl_IncrRefCount(newCascadePtr);
+ Tcl_IncrRefCount(normalPtr);
+ CloneMenu(cascadeMenuPtr, newCascadePtr, normalPtr);
+
+ menuRefPtr = TkFindMenuReferencesObj(menuListPtr->interp,
+ newCascadePtr);
+ if (menuRefPtr == NULL) {
+ Tcl_Panic("CloneMenu failed inside of MenuAddOrInsert");
+ }
+ newObjv[0] = menuNamePtr;
+ newObjv[1] = newCascadePtr;
+ Tcl_IncrRefCount(menuNamePtr);
+ Tcl_IncrRefCount(newCascadePtr);
+ ConfigureMenuEntry(mePtr, 2, newObjv);
+ Tcl_DecrRefCount(newCascadePtr);
+ Tcl_DecrRefCount(menuNamePtr);
+ Tcl_DecrRefCount(windowNamePtr);
+ Tcl_DecrRefCount(normalPtr);
+ }
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * MenuVarProc --
+ *
+ * This function is invoked when someone changes the state variable
+ * associated with a radiobutton or checkbutton menu entry. The entry's
+ * selected state is set to match the value of the variable.
+ *
+ * Results:
+ * NULL is always returned.
+ *
+ * Side effects:
+ * The menu entry may become selected or deselected.
+ *
+ *--------------------------------------------------------------
+ */
+
+static char *
+MenuVarProc(
+ ClientData clientData, /* Information about menu entry. */
+ Tcl_Interp *interp, /* Interpreter containing variable. */
+ const char *name1, /* First part of variable's name. */
+ const char *name2, /* Second part of variable's name. */
+ int flags) /* Describes what just happened. */
+{
+ TkMenuEntry *mePtr = clientData;
+ TkMenu *menuPtr;
+ const char *value;
+ const char *name, *onValue;
+
+ if (Tcl_InterpDeleted(interp) || (mePtr->namePtr == NULL)) {
+ /*
+ * Do nothing if the interpreter is going away or we have
+ * no variable name.
+ */
+
+ return NULL;
+ }
+
+ menuPtr = mePtr->menuPtr;
+
+ if (menuPtr->menuFlags & MENU_DELETION_PENDING) {
+ return NULL;
+ }
+
+ name = Tcl_GetString(mePtr->namePtr);
+
+ /*
+ * If the variable is being unset, then re-establish the trace.
+ */
+
+ if (flags & TCL_TRACE_UNSETS) {
+ ClientData probe = NULL;
+ mePtr->entryFlags &= ~ENTRY_SELECTED;
+
+ do {
+ probe = Tcl_VarTraceInfo(interp, name,
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ MenuVarProc, probe);
+ if (probe == (ClientData)mePtr) {
+ break;
+ }
+ } while (probe);
+ if (probe) {
+ /*
+ * We were able to fetch the unset trace for our
+ * namePtr, which means it is not unset and not
+ * the cause of this unset trace. Instead some outdated
+ * former variable must be, and we should ignore it.
+ */
+ return NULL;
+ }
+ Tcl_TraceVar2(interp, name, NULL,
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ MenuVarProc, clientData);
+ TkpConfigureMenuEntry(mePtr);
+ TkEventuallyRedrawMenu(menuPtr, NULL);
+ return NULL;
+ }
+
+ /*
+ * Use the value of the variable to update the selected status of the menu
+ * entry.
+ */
+
+ value = Tcl_GetVar2(interp, name, NULL, TCL_GLOBAL_ONLY);
+ if (value == NULL) {
+ value = "";
+ }
+ if (mePtr->onValuePtr != NULL) {
+ onValue = Tcl_GetString(mePtr->onValuePtr);
+ if (strcmp(value, onValue) == 0) {
+ if (mePtr->entryFlags & ENTRY_SELECTED) {
+ return NULL;
+ }
+ mePtr->entryFlags |= ENTRY_SELECTED;
+ } else if (mePtr->entryFlags & ENTRY_SELECTED) {
+ mePtr->entryFlags &= ~ENTRY_SELECTED;
+ } else {
+ return NULL;
+ }
+ } else {
+ return NULL;
+ }
+ TkpConfigureMenuEntry(mePtr);
+ TkEventuallyRedrawMenu(menuPtr, mePtr);
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkActivateMenuEntry --
+ *
+ * This function is invoked to make a particular menu entry the active
+ * one, deactivating any other entry that might currently be active.
+ *
+ * Results:
+ * The return value is a standard Tcl result (errors can occur while
+ * posting and unposting submenus).
+ *
+ * Side effects:
+ * Menu entries get redisplayed, and the active entry changes. Submenus
+ * may get posted and unposted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkActivateMenuEntry(
+ register TkMenu *menuPtr, /* Menu in which to activate. */
+ int index) /* Index of entry to activate, or -1 to
+ * deactivate all entries. */
+{
+ register TkMenuEntry *mePtr;
+ int result = TCL_OK;
+
+ if (menuPtr->active >= 0) {
+ mePtr = menuPtr->entries[menuPtr->active];
+
+ /*
+ * Don't change the state unless it's currently active (state might
+ * already have been changed to disabled).
+ */
+
+ if (mePtr->state == ENTRY_ACTIVE) {
+ mePtr->state = ENTRY_NORMAL;
+ }
+ TkEventuallyRedrawMenu(menuPtr, menuPtr->entries[menuPtr->active]);
+ }
+ menuPtr->active = index;
+ if (index >= 0) {
+ mePtr = menuPtr->entries[index];
+ mePtr->state = ENTRY_ACTIVE;
+ TkEventuallyRedrawMenu(menuPtr, mePtr);
+ }
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkPostCommand --
+ *
+ * Execute the postcommand for the given menu.
+ *
+ * Results:
+ * The return value is a standard Tcl result (errors can occur while the
+ * postcommands are being processed).
+ *
+ * Side effects:
+ * Since commands can get executed while this routine is being executed,
+ * the entire world can change.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkPostCommand(
+ TkMenu *menuPtr)
+{
+ int result;
+
+ /*
+ * If there is a command for the menu, execute it. This may change the
+ * size of the menu, so be sure to recompute the menu's geometry if
+ * needed.
+ */
+
+ if (menuPtr->postCommandPtr != NULL) {
+ Tcl_Obj *postCommandPtr = menuPtr->postCommandPtr;
+
+ Tcl_IncrRefCount(postCommandPtr);
+ result = Tcl_EvalObjEx(menuPtr->interp, postCommandPtr,
+ TCL_EVAL_GLOBAL);
+ Tcl_DecrRefCount(postCommandPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+ TkRecomputeMenu(menuPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * CloneMenu --
+ *
+ * Creates a child copy of the menu. It will be inserted into the menu's
+ * instance chain. All attributes and entry attributes will be
+ * duplicated.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * Allocates storage. After the menu is created, any configuration done
+ * with this menu or any related one will be reflected in all of them.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+CloneMenu(
+ TkMenu *menuPtr, /* The menu we are going to clone. */
+ Tcl_Obj *newMenuNamePtr, /* The name to give the new menu. */
+ Tcl_Obj *newMenuTypePtr) /* What kind of menu is this, a normal menu a
+ * menubar, or a tearoff? */
+{
+ int returnResult;
+ int menuType, i;
+ TkMenuReferences *menuRefPtr;
+ Tcl_Obj *menuDupCommandArray[4];
+
+ if (newMenuTypePtr == NULL) {
+ menuType = MASTER_MENU;
+ } else {
+ if (Tcl_GetIndexFromObjStruct(menuPtr->interp, newMenuTypePtr,
+ menuTypeStrings, sizeof(char *), "menu type", 0, &menuType) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+
+ menuDupCommandArray[0] = Tcl_NewStringObj("tk::MenuDup", -1);
+ menuDupCommandArray[1] = Tcl_NewStringObj(Tk_PathName(menuPtr->tkwin), -1);
+ menuDupCommandArray[2] = newMenuNamePtr;
+ if (newMenuTypePtr == NULL) {
+ menuDupCommandArray[3] = Tcl_NewStringObj("normal", -1);
+ } else {
+ menuDupCommandArray[3] = newMenuTypePtr;
+ }
+ for (i = 0; i < 4; i++) {
+ Tcl_IncrRefCount(menuDupCommandArray[i]);
+ }
+ Tcl_Preserve(menuPtr);
+ returnResult = Tcl_EvalObjv(menuPtr->interp, 4, menuDupCommandArray, 0);
+ for (i = 0; i < 4; i++) {
+ Tcl_DecrRefCount(menuDupCommandArray[i]);
+ }
+
+ /*
+ * Make sure the tcl command actually created the clone.
+ */
+
+ if ((returnResult == TCL_OK) &&
+ ((menuRefPtr = TkFindMenuReferencesObj(menuPtr->interp,
+ newMenuNamePtr)) != NULL)
+ && (menuPtr->numEntries == menuRefPtr->menuPtr->numEntries)) {
+ TkMenu *newMenuPtr = menuRefPtr->menuPtr;
+ Tcl_Obj *newObjv[3];
+ int i, numElements;
+
+ /*
+ * Now put this newly created menu into the parent menu's instance
+ * chain.
+ */
+
+ if (menuPtr->nextInstancePtr == NULL) {
+ menuPtr->nextInstancePtr = newMenuPtr;
+ newMenuPtr->masterMenuPtr = menuPtr->masterMenuPtr;
+ } else {
+ TkMenu *masterMenuPtr;
+
+ masterMenuPtr = menuPtr->masterMenuPtr;
+ newMenuPtr->nextInstancePtr = masterMenuPtr->nextInstancePtr;
+ masterMenuPtr->nextInstancePtr = newMenuPtr;
+ newMenuPtr->masterMenuPtr = masterMenuPtr;
+ }
+
+ /*
+ * Add the master menu's window to the bind tags for this window after
+ * this window's tag. This is so the user can bind to either this
+ * clone (which may not be easy to do) or the entire menu clone
+ * structure.
+ */
+
+ newObjv[0] = Tcl_NewStringObj("bindtags", -1);
+ newObjv[1] = Tcl_NewStringObj(Tk_PathName(newMenuPtr->tkwin), -1);
+ Tcl_IncrRefCount(newObjv[0]);
+ Tcl_IncrRefCount(newObjv[1]);
+ if (Tk_BindtagsObjCmd(newMenuPtr->tkwin, newMenuPtr->interp, 2,
+ newObjv) == TCL_OK) {
+ const char *windowName;
+ Tcl_Obj *bindingsPtr =
+ Tcl_DuplicateObj(Tcl_GetObjResult(newMenuPtr->interp));
+ Tcl_Obj *elementPtr;
+
+ Tcl_IncrRefCount(bindingsPtr);
+ Tcl_ListObjLength(newMenuPtr->interp, bindingsPtr, &numElements);
+ for (i = 0; i < numElements; i++) {
+ Tcl_ListObjIndex(newMenuPtr->interp, bindingsPtr, i,
+ &elementPtr);
+ windowName = Tcl_GetString(elementPtr);
+ if (strcmp(windowName, Tk_PathName(newMenuPtr->tkwin))
+ == 0) {
+ Tcl_Obj *newElementPtr = Tcl_NewStringObj(
+ Tk_PathName(newMenuPtr->masterMenuPtr->tkwin), -1);
+
+ /*
+ * The newElementPtr will have its refCount incremented
+ * here, so we don't need to worry about it any more.
+ */
+
+ Tcl_ListObjReplace(menuPtr->interp, bindingsPtr,
+ i + 1, 0, 1, &newElementPtr);
+ newObjv[2] = bindingsPtr;
+ Tk_BindtagsObjCmd(newMenuPtr->tkwin, menuPtr->interp, 3,
+ newObjv);
+ break;
+ }
+ }
+ Tcl_DecrRefCount(bindingsPtr);
+ }
+ Tcl_DecrRefCount(newObjv[0]);
+ Tcl_DecrRefCount(newObjv[1]);
+ Tcl_ResetResult(menuPtr->interp);
+
+ /*
+ * Clone all of the cascade menus that this menu points to.
+ */
+
+ for (i = 0; i < menuPtr->numEntries; i++) {
+ TkMenuReferences *cascadeRefPtr;
+ TkMenu *oldCascadePtr;
+
+ if ((menuPtr->entries[i]->type == CASCADE_ENTRY)
+ && (menuPtr->entries[i]->namePtr != NULL)) {
+ cascadeRefPtr =
+ TkFindMenuReferencesObj(menuPtr->interp,
+ menuPtr->entries[i]->namePtr);
+ if ((cascadeRefPtr != NULL) && (cascadeRefPtr->menuPtr)) {
+ Tcl_Obj *windowNamePtr =
+ Tcl_NewStringObj(Tk_PathName(newMenuPtr->tkwin),
+ -1);
+ Tcl_Obj *newCascadePtr;
+
+ oldCascadePtr = cascadeRefPtr->menuPtr;
+
+ Tcl_IncrRefCount(windowNamePtr);
+ newCascadePtr = TkNewMenuName(menuPtr->interp,
+ windowNamePtr, oldCascadePtr);
+ Tcl_IncrRefCount(newCascadePtr);
+ CloneMenu(oldCascadePtr, newCascadePtr, NULL);
+
+ newObjv[0] = Tcl_NewStringObj("-menu", -1);
+ newObjv[1] = newCascadePtr;
+ Tcl_IncrRefCount(newObjv[0]);
+ ConfigureMenuEntry(newMenuPtr->entries[i], 2, newObjv);
+ Tcl_DecrRefCount(newObjv[0]);
+ Tcl_DecrRefCount(newCascadePtr);
+ Tcl_DecrRefCount(windowNamePtr);
+ }
+ }
+ }
+
+ returnResult = TCL_OK;
+ } else {
+ returnResult = TCL_ERROR;
+ }
+ Tcl_Release(menuPtr);
+ return returnResult;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MenuDoXPosition --
+ *
+ * Given arguments from an option command line, returns the X position.
+ *
+ * Results:
+ * Returns TCL_OK or TCL_Error
+ *
+ * Side effects:
+ * xPosition is set to the X-position of the menu entry.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+MenuDoXPosition(
+ Tcl_Interp *interp,
+ TkMenu *menuPtr,
+ Tcl_Obj *objPtr)
+{
+ int index;
+
+ TkRecomputeMenu(menuPtr);
+ if (TkGetMenuIndex(interp, menuPtr, objPtr, 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_ResetResult(interp);
+ if (index < 0) {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
+ } else {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(menuPtr->entries[index]->x));
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MenuDoYPosition --
+ *
+ * Given arguments from an option command line, returns the Y position.
+ *
+ * Results:
+ * Returns TCL_OK or TCL_Error
+ *
+ * Side effects:
+ * yPosition is set to the Y-position of the menu entry.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+MenuDoYPosition(
+ Tcl_Interp *interp,
+ TkMenu *menuPtr,
+ Tcl_Obj *objPtr)
+{
+ int index;
+
+ TkRecomputeMenu(menuPtr);
+ if (TkGetMenuIndex(interp, menuPtr, objPtr, 0, &index) != TCL_OK) {
+ goto error;
+ }
+ Tcl_ResetResult(interp);
+ if (index < 0) {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
+ } else {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(menuPtr->entries[index]->y));
+ }
+
+ return TCL_OK;
+
+ error:
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetIndexFromCoords --
+ *
+ * Given a string of the form "@integer", return the menu item
+ * corresponding to the provided y-coordinate in the menu window.
+ *
+ * Results:
+ * If int is a valid number, *indexPtr will be the number of the
+ * menuentry that is the correct height. If int is invalid, *indexPtr
+ * will be unchanged. Returns appropriate Tcl error number.
+ *
+ * Side effects:
+ * If int is invalid, interp's result will be set to NULL.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GetIndexFromCoords(
+ Tcl_Interp *interp, /* Interpreter of menu. */
+ TkMenu *menuPtr, /* The menu we are searching. */
+ const char *string, /* The @string we are parsing. */
+ int *indexPtr) /* The index of the item that matches. */
+{
+ int x, y, i;
+ const char *p;
+ char *end;
+ int x2, borderwidth, max;
+
+ TkRecomputeMenu(menuPtr);
+ p = string + 1;
+ y = strtol(p, &end, 0);
+ if (end == p) {
+ goto error;
+ }
+ Tk_GetPixelsFromObj(interp, menuPtr->tkwin,
+ menuPtr->borderWidthPtr, &borderwidth);
+ if (*end == ',') {
+ x = y;
+ p = end + 1;
+ y = strtol(p, &end, 0);
+ if (end == p) {
+ goto error;
+ }
+ } else {
+ x = borderwidth;
+ }
+
+ *indexPtr = -1;
+
+ /* set the width of the final column to the remainder of the window
+ * being aware of windows that may not be mapped yet.
+ */
+ max = Tk_IsMapped(menuPtr->tkwin)
+ ? Tk_Width(menuPtr->tkwin) : Tk_ReqWidth(menuPtr->tkwin);
+ max -= borderwidth;
+
+ for (i = 0; i < menuPtr->numEntries; i++) {
+ if (menuPtr->entries[i]->entryFlags & ENTRY_LAST_COLUMN) {
+ x2 = max;
+ } else {
+ x2 = menuPtr->entries[i]->x + menuPtr->entries[i]->width;
+ }
+ if ((x >= menuPtr->entries[i]->x) && (y >= menuPtr->entries[i]->y)
+ && (x < x2)
+ && (y < (menuPtr->entries[i]->y
+ + menuPtr->entries[i]->height))) {
+ *indexPtr = i;
+ break;
+ }
+ }
+ return TCL_OK;
+
+ error:
+ Tcl_ResetResult(interp);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * RecursivelyDeleteMenu --
+ *
+ * Deletes a menu and any cascades underneath it. Used for deleting
+ * instances when a menu is no longer being used as a menubar, for
+ * instance.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Destroys the menu and all cascade menus underneath it.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+RecursivelyDeleteMenu(
+ TkMenu *menuPtr) /* The menubar instance we are deleting. */
+{
+ int i;
+ TkMenuEntry *mePtr;
+
+ /*
+ * It is not 100% clear that this preserve/release pair is required, but
+ * we have added them for safety in this very complex code.
+ */
+
+ Tcl_Preserve(menuPtr);
+
+ for (i = 0; i < menuPtr->numEntries; i++) {
+ mePtr = menuPtr->entries[i];
+ if ((mePtr->type == CASCADE_ENTRY)
+ && (mePtr->childMenuRefPtr != NULL)
+ && (mePtr->childMenuRefPtr->menuPtr != NULL)) {
+ RecursivelyDeleteMenu(mePtr->childMenuRefPtr->menuPtr);
+ }
+ }
+ if (menuPtr->tkwin != NULL) {
+ Tk_DestroyWindow(menuPtr->tkwin);
+ }
+
+ Tcl_Release(menuPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkNewMenuName --
+ *
+ * Makes a new unique name for a cloned menu. Will be a child of oldName.
+ *
+ * Results:
+ * Returns a char * which has been allocated; caller must free.
+ *
+ * Side effects:
+ * Memory is allocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TkNewMenuName(
+ Tcl_Interp *interp, /* The interp the new name has to live in.*/
+ Tcl_Obj *parentPtr, /* The prefix path of the new name. */
+ TkMenu *menuPtr) /* The menu we are cloning. */
+{
+ Tcl_Obj *resultPtr = NULL; /* Initialization needed only to prevent
+ * compiler warning. */
+ Tcl_Obj *childPtr;
+ char *destString;
+ int i;
+ int doDot;
+ Tcl_HashTable *nameTablePtr = NULL;
+ TkWindow *winPtr = (TkWindow *) menuPtr->tkwin;
+ const char *parentName = Tcl_GetString(parentPtr);
+
+ if (winPtr->mainPtr != NULL) {
+ nameTablePtr = &(winPtr->mainPtr->nameTable);
+ }
+
+ doDot = parentName[strlen(parentName) - 1] != '.';
+
+ childPtr = Tcl_NewStringObj(Tk_PathName(menuPtr->tkwin), -1);
+ for (destString = Tcl_GetString(childPtr);
+ *destString != '\0'; destString++) {
+ if (*destString == '.') {
+ *destString = '#';
+ }
+ }
+
+ for (i = 0; ; i++) {
+ if (i == 0) {
+ resultPtr = Tcl_DuplicateObj(parentPtr);
+ if (doDot) {
+ Tcl_AppendToObj(resultPtr, ".", -1);
+ }
+ Tcl_AppendObjToObj(resultPtr, childPtr);
+ } else {
+ Tcl_Obj *intPtr;
+
+ Tcl_DecrRefCount(resultPtr);
+ resultPtr = Tcl_DuplicateObj(parentPtr);
+ if (doDot) {
+ Tcl_AppendToObj(resultPtr, ".", -1);
+ }
+ Tcl_AppendObjToObj(resultPtr, childPtr);
+ intPtr = Tcl_NewIntObj(i);
+ Tcl_AppendObjToObj(resultPtr, intPtr);
+ Tcl_DecrRefCount(intPtr);
+ }
+ destString = Tcl_GetString(resultPtr);
+ if ((Tcl_FindCommand(interp, destString, NULL, 0) == NULL)
+ && ((nameTablePtr == NULL)
+ || (Tcl_FindHashEntry(nameTablePtr, destString) == NULL))) {
+ break;
+ }
+ }
+ Tcl_DecrRefCount(childPtr);
+ return resultPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkSetWindowMenuBar --
+ *
+ * Associates a menu with a window. Called by ConfigureFrame in in
+ * response to a "-menu .foo" configuration option for a top level.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The old menu clones for the menubar are thrown away, and a handler is
+ * set up to allocate the new ones.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkSetWindowMenuBar(
+ Tcl_Interp *interp, /* The interpreter the toplevel lives in. */
+ Tk_Window tkwin, /* The toplevel window. */
+ const char *oldMenuName, /* The name of the menubar previously set in
+ * this toplevel. NULL means no menu was set
+ * previously. */
+ const char *menuName) /* The name of the new menubar that the
+ * toplevel needs to be set to. NULL means
+ * that their is no menu now. */
+{
+ TkMenuTopLevelList *topLevelListPtr, *prevTopLevelPtr;
+ TkMenu *menuPtr;
+ TkMenuReferences *menuRefPtr;
+
+ /*
+ * Destroy the menubar instances of the old menu. Take this window out of
+ * the old menu's top level reference list.
+ */
+
+ if (oldMenuName != NULL) {
+ menuRefPtr = TkFindMenuReferences(interp, oldMenuName);
+ if (menuRefPtr != NULL) {
+ /*
+ * Find the menubar instance that is to be removed. Destroy it and
+ * all of the cascades underneath it.
+ */
+
+ if (menuRefPtr->menuPtr != NULL) {
+ TkMenu *instancePtr;
+
+ menuPtr = menuRefPtr->menuPtr;
+
+ for (instancePtr = menuPtr->masterMenuPtr;
+ instancePtr != NULL;
+ instancePtr = instancePtr->nextInstancePtr) {
+ if (instancePtr->menuType == MENUBAR
+ && instancePtr->parentTopLevelPtr == tkwin) {
+ RecursivelyDeleteMenu(instancePtr);
+ break;
+ }
+ }
+ }
+
+ /*
+ * Now we need to remove this toplevel from the list of toplevels
+ * that reference this menu.
+ */
+
+ topLevelListPtr = menuRefPtr->topLevelListPtr;
+ prevTopLevelPtr = NULL;
+
+ while ((topLevelListPtr != NULL)
+ && (topLevelListPtr->tkwin != tkwin)) {
+ prevTopLevelPtr = topLevelListPtr;
+ topLevelListPtr = topLevelListPtr->nextPtr;
+ }
+
+ /*
+ * Now we have found the toplevel reference that matches the
+ * tkwin; remove this reference from the list.
+ */
+
+ if (topLevelListPtr != NULL) {
+ if (prevTopLevelPtr == NULL) {
+ menuRefPtr->topLevelListPtr =
+ menuRefPtr->topLevelListPtr->nextPtr;
+ } else {
+ prevTopLevelPtr->nextPtr = topLevelListPtr->nextPtr;
+ }
+ ckfree(topLevelListPtr);
+ TkFreeMenuReferences(menuRefPtr);
+ }
+ }
+ }
+
+ /*
+ * Now, add the clone references for the new menu.
+ */
+
+ if (menuName != NULL && menuName[0] != 0) {
+ TkMenu *menuBarPtr = NULL;
+
+ menuRefPtr = TkCreateMenuReferences(interp, menuName);
+
+ menuPtr = menuRefPtr->menuPtr;
+ if (menuPtr != NULL) {
+ Tcl_Obj *cloneMenuPtr;
+ TkMenuReferences *cloneMenuRefPtr;
+ Tcl_Obj *newObjv[4];
+ Tcl_Obj *windowNamePtr = Tcl_NewStringObj(Tk_PathName(tkwin),
+ -1);
+ Tcl_Obj *menubarPtr = Tcl_NewStringObj("menubar", -1);
+
+ /*
+ * Clone the menu and all of the cascades underneath it.
+ */
+
+ Tcl_IncrRefCount(windowNamePtr);
+ cloneMenuPtr = TkNewMenuName(interp, windowNamePtr,
+ menuPtr);
+ Tcl_IncrRefCount(cloneMenuPtr);
+ Tcl_IncrRefCount(menubarPtr);
+ CloneMenu(menuPtr, cloneMenuPtr, menubarPtr);
+
+ cloneMenuRefPtr = TkFindMenuReferencesObj(interp, cloneMenuPtr);
+ if ((cloneMenuRefPtr != NULL)
+ && (cloneMenuRefPtr->menuPtr != NULL)) {
+ Tcl_Obj *cursorPtr = Tcl_NewStringObj("-cursor", -1);
+ Tcl_Obj *nullPtr = Tcl_NewObj();
+
+ cloneMenuRefPtr->menuPtr->parentTopLevelPtr = tkwin;
+ menuBarPtr = cloneMenuRefPtr->menuPtr;
+ newObjv[0] = cursorPtr;
+ newObjv[1] = nullPtr;
+ Tcl_IncrRefCount(cursorPtr);
+ Tcl_IncrRefCount(nullPtr);
+ ConfigureMenu(menuPtr->interp, cloneMenuRefPtr->menuPtr,
+ 2, newObjv);
+ Tcl_DecrRefCount(cursorPtr);
+ Tcl_DecrRefCount(nullPtr);
+ }
+
+ TkpSetWindowMenuBar(tkwin, menuBarPtr);
+ Tcl_DecrRefCount(cloneMenuPtr);
+ Tcl_DecrRefCount(menubarPtr);
+ Tcl_DecrRefCount(windowNamePtr);
+ } else {
+ TkpSetWindowMenuBar(tkwin, NULL);
+ }
+
+ /*
+ * Add this window to the menu's list of windows that refer to this
+ * menu.
+ */
+
+ topLevelListPtr = ckalloc(sizeof(TkMenuTopLevelList));
+ topLevelListPtr->tkwin = tkwin;
+ topLevelListPtr->nextPtr = menuRefPtr->topLevelListPtr;
+ menuRefPtr->topLevelListPtr = topLevelListPtr;
+ } else {
+ TkpSetWindowMenuBar(tkwin, NULL);
+ }
+ TkpSetMainMenubar(interp, tkwin, menuName);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyMenuHashTable --
+ *
+ * Called when an interp is deleted and a menu hash table has been set in
+ * it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The hash table is destroyed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DestroyMenuHashTable(
+ ClientData clientData, /* The menu hash table we are destroying. */
+ Tcl_Interp *interp) /* The interpreter we are destroying. */
+{
+ Tcl_DeleteHashTable(clientData);
+ ckfree(clientData);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkGetMenuHashTable --
+ *
+ * For a given interp, give back the menu hash table that goes with it.
+ * If the hash table does not exist, it is created.
+ *
+ * Results:
+ * Returns a hash table pointer.
+ *
+ * Side effects:
+ * A new hash table is created if there were no table in the interp
+ * originally.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_HashTable *
+TkGetMenuHashTable(
+ Tcl_Interp *interp) /* The interp we need the hash table in.*/
+{
+ Tcl_HashTable *menuTablePtr =
+ Tcl_GetAssocData(interp, MENU_HASH_KEY, NULL);
+
+ if (menuTablePtr == NULL) {
+ menuTablePtr = ckalloc(sizeof(Tcl_HashTable));
+ Tcl_InitHashTable(menuTablePtr, TCL_STRING_KEYS);
+ Tcl_SetAssocData(interp, MENU_HASH_KEY, DestroyMenuHashTable,
+ menuTablePtr);
+ }
+ return menuTablePtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkCreateMenuReferences --
+ *
+ * Given a pathname, gives back a pointer to a TkMenuReferences
+ * structure. If a reference is not already in the hash table, one is
+ * created.
+ *
+ * Results:
+ * Returns a pointer to a menu reference structure. Should not be freed
+ * by calller; when a field of the reference is cleared,
+ * TkFreeMenuReferences should be called.
+ *
+ * Side effects:
+ * A new hash table entry is created if there were no references to the
+ * menu originally.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkMenuReferences *
+TkCreateMenuReferences(
+ Tcl_Interp *interp,
+ const char *pathName) /* The path of the menu widget. */
+{
+ Tcl_HashEntry *hashEntryPtr;
+ TkMenuReferences *menuRefPtr;
+ int newEntry;
+ Tcl_HashTable *menuTablePtr = TkGetMenuHashTable(interp);
+
+ hashEntryPtr = Tcl_CreateHashEntry(menuTablePtr, pathName, &newEntry);
+ if (newEntry) {
+ menuRefPtr = ckalloc(sizeof(TkMenuReferences));
+ menuRefPtr->menuPtr = NULL;
+ menuRefPtr->topLevelListPtr = NULL;
+ menuRefPtr->parentEntryPtr = NULL;
+ menuRefPtr->hashEntryPtr = hashEntryPtr;
+ Tcl_SetHashValue(hashEntryPtr, menuRefPtr);
+ } else {
+ menuRefPtr = Tcl_GetHashValue(hashEntryPtr);
+ }
+ return menuRefPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkFindMenuReferences --
+ *
+ * Given a pathname, gives back a pointer to the TkMenuReferences
+ * structure.
+ *
+ * Results:
+ * Returns a pointer to a menu reference structure. Should not be freed
+ * by calller; when a field of the reference is cleared,
+ * TkFreeMenuReferences should be called. Returns NULL if no reference
+ * with this pathname exists.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkMenuReferences *
+TkFindMenuReferences(
+ Tcl_Interp *interp, /* The interp the menu is living in. */
+ const char *pathName) /* The path of the menu widget. */
+{
+ Tcl_HashEntry *hashEntryPtr;
+ TkMenuReferences *menuRefPtr = NULL;
+ Tcl_HashTable *menuTablePtr;
+
+ menuTablePtr = TkGetMenuHashTable(interp);
+ hashEntryPtr = Tcl_FindHashEntry(menuTablePtr, pathName);
+ if (hashEntryPtr != NULL) {
+ menuRefPtr = Tcl_GetHashValue(hashEntryPtr);
+ }
+ return menuRefPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkFindMenuReferencesObj --
+ *
+ * Given a pathname, gives back a pointer to the TkMenuReferences
+ * structure.
+ *
+ * Results:
+ * Returns a pointer to a menu reference structure. Should not be freed
+ * by calller; when a field of the reference is cleared,
+ * TkFreeMenuReferences should be called. Returns NULL if no reference
+ * with this pathname exists.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkMenuReferences *
+TkFindMenuReferencesObj(
+ Tcl_Interp *interp, /* The interp the menu is living in. */
+ Tcl_Obj *objPtr) /* The path of the menu widget. */
+{
+ const char *pathName = Tcl_GetString(objPtr);
+
+ return TkFindMenuReferences(interp, pathName);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkFreeMenuReferences --
+ *
+ * This is called after one of the fields in a menu reference is cleared.
+ * It cleans up the ref if it is now empty.
+ *
+ * Results:
+ * Returns 1 if the references structure was freed, and 0 otherwise.
+ *
+ * Side effects:
+ * If this is the last field to be cleared, the menu ref is taken out of
+ * the hash table.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkFreeMenuReferences(
+ TkMenuReferences *menuRefPtr)
+ /* The menu reference to free. */
+{
+ if ((menuRefPtr->menuPtr == NULL)
+ && (menuRefPtr->parentEntryPtr == NULL)
+ && (menuRefPtr->topLevelListPtr == NULL)) {
+ Tcl_DeleteHashEntry(menuRefPtr->hashEntryPtr);
+ ckfree(menuRefPtr);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DeleteMenuCloneEntries --
+ *
+ * For every clone in this clone chain, delete the menu entries given by
+ * the parameters.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The appropriate entries are deleted from all clones of this menu.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DeleteMenuCloneEntries(
+ TkMenu *menuPtr, /* The menu the command was issued with. */
+ int first, /* The zero-based first entry in the set of
+ * entries to delete. */
+ int last) /* The zero-based last entry. */
+{
+ TkMenu *menuListPtr;
+ int numDeleted, i, j;
+
+ numDeleted = last + 1 - first;
+ for (menuListPtr = menuPtr->masterMenuPtr; menuListPtr != NULL;
+ menuListPtr = menuListPtr->nextInstancePtr) {
+ for (i = last; i >= first; i--) {
+ Tcl_EventuallyFree(menuListPtr->entries[i], (Tcl_FreeProc *) DestroyMenuEntry);
+ }
+ for (i = last + 1; i < menuListPtr->numEntries; i++) {
+ j = i - numDeleted;
+ menuListPtr->entries[j] = menuListPtr->entries[i];
+ menuListPtr->entries[j]->index = j;
+ }
+ menuListPtr->numEntries -= numDeleted;
+ if (menuListPtr->numEntries == 0) {
+ ckfree(menuListPtr->entries);
+ menuListPtr->entries = NULL;
+ }
+ if ((menuListPtr->active >= first)
+ && (menuListPtr->active <= last)) {
+ menuListPtr->active = -1;
+ } else if (menuListPtr->active > last) {
+ menuListPtr->active -= numDeleted;
+ }
+ TkEventuallyRecomputeMenu(menuListPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMenuCleanup --
+ *
+ * Resets menusInitialized to allow Tk to be finalized and reused without
+ * the DLL being unloaded.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+TkMenuCleanup(
+ ClientData unused)
+{
+ menusInitialized = 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMenuInit --
+ *
+ * Sets up the hash tables and the variables used by the menu package.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * lastMenuID gets initialized, and the parent hash and the command hash
+ * are allocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMenuInit(void)
+{
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (!menusInitialized) {
+ Tcl_MutexLock(&menuMutex);
+ if (!menusInitialized) {
+ TkpMenuInit();
+ menusInitialized = 1;
+ }
+
+ /*
+ * Make sure we cleanup on finalize.
+ */
+
+ TkCreateExitHandler((Tcl_ExitProc *) TkMenuCleanup, NULL);
+ Tcl_MutexUnlock(&menuMutex);
+ }
+ if (!tsdPtr->menusInitialized) {
+ TkpMenuThreadInit();
+ tsdPtr->menuOptionTable =
+ Tk_CreateOptionTable(NULL, tkMenuConfigSpecs);
+ tsdPtr->entryOptionTables[TEAROFF_ENTRY] =
+ Tk_CreateOptionTable(NULL, specsArray[TEAROFF_ENTRY]);
+ tsdPtr->entryOptionTables[COMMAND_ENTRY] =
+ Tk_CreateOptionTable(NULL, specsArray[COMMAND_ENTRY]);
+ tsdPtr->entryOptionTables[CASCADE_ENTRY] =
+ Tk_CreateOptionTable(NULL, specsArray[CASCADE_ENTRY]);
+ tsdPtr->entryOptionTables[SEPARATOR_ENTRY] =
+ Tk_CreateOptionTable(NULL, specsArray[SEPARATOR_ENTRY]);
+ tsdPtr->entryOptionTables[RADIO_BUTTON_ENTRY] =
+ Tk_CreateOptionTable(NULL, specsArray[RADIO_BUTTON_ENTRY]);
+ tsdPtr->entryOptionTables[CHECK_BUTTON_ENTRY] =
+ Tk_CreateOptionTable(NULL, specsArray[CHECK_BUTTON_ENTRY]);
+ tsdPtr->menusInitialized = 1;
+ }
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkMenu.h b/tk8.6/generic/tkMenu.h
new file mode 100644
index 0000000..ae69d96
--- /dev/null
+++ b/tk8.6/generic/tkMenu.h
@@ -0,0 +1,551 @@
+/*
+ * tkMenu.h --
+ *
+ * Declarations shared among all of the files that implement menu
+ * widgets.
+ *
+ * Copyright (c) 1996-1998 by Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef _TKMENU
+#define _TKMENU
+
+#ifndef _TK
+#include "tk.h"
+#endif
+
+#ifndef _TKINT
+#include "tkInt.h"
+#endif
+
+#ifndef _DEFAULT
+#include "default.h"
+#endif
+
+/*
+ * Dummy types used by the platform menu code.
+ */
+
+typedef struct TkMenuPlatformData_ *TkMenuPlatformData;
+typedef struct TkMenuPlatformEntryData_ *TkMenuPlatformEntryData;
+
+/*
+ * Legal values for the "compound" field of TkMenuEntry and TkMenuButton
+ * records.
+ */
+
+enum compound {
+ COMPOUND_BOTTOM, COMPOUND_CENTER, COMPOUND_LEFT, COMPOUND_NONE,
+ COMPOUND_RIGHT, COMPOUND_TOP
+};
+
+/*
+ * Additional menu entry drawing parameters for Windows platform.
+ * DRAW_MENU_ENTRY_ARROW makes TkpDrawMenuEntry draw the arrow
+ * itself when cascade entry is disabled.
+ * DRAW_MENU_ENTRY_NOUNDERLINE forbids underline when ODS_NOACCEL
+ * is set, thus obeying the system-wide Windows UI setting.
+ */
+
+enum drawingParameters {
+ DRAW_MENU_ENTRY_ARROW = (1<<0),
+ DRAW_MENU_ENTRY_NOUNDERLINE = (1<<1)
+};
+
+/*
+ * One of the following data structures is kept for each entry of each menu
+ * managed by this file:
+ */
+
+typedef struct TkMenuEntry {
+ int type; /* Type of menu entry; see below for valid
+ * types. */
+ struct TkMenu *menuPtr; /* Menu with which this entry is
+ * associated. */
+ Tk_OptionTable optionTable; /* Option table for this menu entry. */
+ Tcl_Obj *labelPtr; /* Main text label displayed in entry (NULL if
+ * no label). */
+ int labelLength; /* Number of non-NULL characters in label. */
+ int state; /* State of button for display purposes:
+ * normal, active, or disabled. */
+ int underline; /* Value of -underline option: specifies index
+ * of character to underline (<0 means don't
+ * underline anything). */
+ Tcl_Obj *underlinePtr; /* Index of character to underline. */
+ Tcl_Obj *bitmapPtr; /* Bitmap to display in menu entry, or NULL.
+ * If not NULL then label is ignored. */
+ Tcl_Obj *imagePtr; /* Name of image to display, or NULL. If not
+ * NULL, bitmap, text, and textVarName are
+ * ignored. */
+ Tk_Image image; /* Image to display in menu entry, or NULL if
+ * none. */
+ Tcl_Obj *selectImagePtr; /* Name of image to display when selected, or
+ * NULL. */
+ Tk_Image selectImage; /* Image to display in entry when selected, or
+ * NULL if none. Ignored if image is NULL. */
+ Tcl_Obj *accelPtr; /* Accelerator string displayed at right of
+ * menu entry. NULL means no such accelerator.
+ * Malloc'ed. */
+ int accelLength; /* Number of non-NULL characters in
+ * accelerator. */
+ int indicatorOn; /* True means draw indicator, false means
+ * don't draw it. This field is ignored unless
+ * the entry is a radio or check button. */
+ /*
+ * Display attributes
+ */
+
+ Tcl_Obj *borderPtr; /* Structure used to draw background for
+ * entry. NULL means use overall border for
+ * menu. */
+ Tcl_Obj *fgPtr; /* Foreground color to use for entry. NULL
+ * means use foreground color from menu. */
+ Tcl_Obj *activeBorderPtr; /* Used to draw background and border when
+ * element is active. NULL means use
+ * activeBorder from menu. */
+ Tcl_Obj *activeFgPtr; /* Foreground color to use when entry is
+ * active. NULL means use active foreground
+ * from menu. */
+ Tcl_Obj *indicatorFgPtr; /* Color for indicators in radio and check
+ * button entries. NULL means use indicatorFg
+ * GC from menu. */
+ Tcl_Obj *fontPtr; /* Text font for menu entries. NULL means use
+ * overall font for menu. */
+ int columnBreak; /* If this is 0, this item appears below the
+ * item in front of it. If this is 1, this
+ * item starts a new column. This field is
+ * always 0 for tearoff and separator
+ * entries. */
+ int hideMargin; /* If this is 0, then the item has enough
+ * margin to accommodate a standard check mark
+ * and a default right margin. If this is 1,
+ * then the item has no such margins, and
+ * checkbuttons and radiobuttons with this set
+ * will have a rectangle drawn in the
+ * indicator around the item if the item is
+ * checked. This is useful for palette menus.
+ * This field is ignored for separators and
+ * tearoffs. */
+ int indicatorSpace; /* The width of the indicator space for this
+ * entry. */
+ int labelWidth; /* Number of pixels to allow for displaying
+ * labels in menu entries. */
+ int compound; /* Value of -compound option; specifies
+ * whether the entry should show both an image
+ * and text, and, if so, how. */
+
+ /*
+ * Information used to implement this entry's action:
+ */
+
+ Tcl_Obj *commandPtr; /* Command to invoke when entry is invoked.
+ * Malloc'ed. */
+ Tcl_Obj *namePtr; /* Name of variable (for check buttons and
+ * radio buttons) or menu (for cascade
+ * entries). Malloc'ed. */
+ Tcl_Obj *onValuePtr; /* Value to store in variable when selected
+ * (only for radio and check buttons).
+ * Malloc'ed. */
+ Tcl_Obj *offValuePtr; /* Value to store in variable when not
+ * selected (only for check buttons).
+ * Malloc'ed. */
+
+ /*
+ * Information used for drawing this menu entry.
+ */
+
+ int width; /* Number of pixels occupied by entry in
+ * horizontal dimension. Not used except in
+ * menubars. The width of norma menus is
+ * dependent on the rest of the menu. */
+ int x; /* X-coordinate of leftmost pixel in entry. */
+ int height; /* Number of pixels occupied by entry in
+ * vertical dimension, including raised border
+ * drawn around entry when active. */
+ int y; /* Y-coordinate of topmost pixel in entry. */
+ GC textGC; /* GC for drawing text in entry. NULL means
+ * use overall textGC for menu. */
+ GC activeGC; /* GC for drawing text in entry when active.
+ * NULL means use overall activeGC for
+ * menu. */
+ GC disabledGC; /* Used to produce disabled effect for entry.
+ * NULL means use overall disabledGC from menu
+ * structure. See comments for disabledFg in
+ * menu structure for more information. */
+ GC indicatorGC; /* For drawing indicators. NULL means use GC
+ * from menu. */
+
+ /*
+ * Miscellaneous fields.
+ */
+
+ int entryFlags; /* Various flags. See below for
+ * definitions. */
+ int index; /* Need to know which index we are. This is
+ * zero-based. This is the top-left entry of
+ * the menu. */
+
+ /*
+ * Bookeeping for master menus and cascade menus.
+ */
+
+ struct TkMenuReferences *childMenuRefPtr;
+ /* A pointer to the hash table entry for the
+ * child menu. Stored here when the menu entry
+ * is configured so that a hash lookup is not
+ * necessary later.*/
+ struct TkMenuEntry *nextCascadePtr;
+ /* The next cascade entry that is a parent of
+ * this entry's child cascade menu. NULL end
+ * of list, this is not a cascade entry, or
+ * the menu that this entry point to does not
+ * yet exist. */
+ TkMenuPlatformEntryData platformEntryData;
+ /* The data for the specific type of menu.
+ * Depends on platform and menu type what kind
+ * of options are in this structure. */
+} TkMenuEntry;
+
+/*
+ * Flag values defined for menu entries:
+ *
+ * ENTRY_SELECTED: Non-zero means this is a radio or check button
+ * and that it should be drawn in the "selected"
+ * state.
+ * ENTRY_NEEDS_REDISPLAY: Non-zero means the entry should be redisplayed.
+ * ENTRY_LAST_COLUMN: Used by the drawing code. If the entry is in
+ * the last column, the space to its right needs
+ * to be filled.
+ * ENTRY_PLATFORM_FLAG1 - 4 These flags are reserved for use by the
+ * platform-dependent implementation of menus
+ * and should not be used by anything else.
+ */
+
+#define ENTRY_SELECTED 1
+#define ENTRY_NEEDS_REDISPLAY 2
+#define ENTRY_LAST_COLUMN 4
+#define ENTRY_PLATFORM_FLAG1 (1 << 30)
+#define ENTRY_PLATFORM_FLAG2 (1 << 29)
+#define ENTRY_PLATFORM_FLAG3 (1 << 28)
+#define ENTRY_PLATFORM_FLAG4 (1 << 27)
+
+/*
+ * Types defined for MenuEntries:
+ */
+
+#define CASCADE_ENTRY 0
+#define CHECK_BUTTON_ENTRY 1
+#define COMMAND_ENTRY 2
+#define RADIO_BUTTON_ENTRY 3
+#define SEPARATOR_ENTRY 4
+#define TEAROFF_ENTRY 5
+
+/*
+ * Menu states
+ */
+
+#define ENTRY_ACTIVE 0
+#define ENTRY_NORMAL 1
+#define ENTRY_DISABLED 2
+
+/*
+ * A data structure of the following type is kept for each menu widget:
+ */
+
+typedef struct TkMenu {
+ Tk_Window tkwin; /* Window that embodies the pane. NULL means
+ * that the window has been destroyed but the
+ * data structures haven't yet been cleaned
+ * up. */
+ Display *display; /* Display containing widget. Needed, among
+ * other things, so that resources can be
+ * freed up even after tkwin has gone away. */
+ Tcl_Interp *interp; /* Interpreter associated with menu. */
+ Tcl_Command widgetCmd; /* Token for menu's widget command. */
+ TkMenuEntry **entries; /* Array of pointers to all the entries in the
+ * menu. NULL means no entries. */
+ int numEntries; /* Number of elements in entries. */
+ int active; /* Index of active entry. -1 means nothing
+ * active. */
+ int menuType; /* MASTER_MENU, TEAROFF_MENU, or MENUBAR. See
+ * below for definitions. */
+ Tcl_Obj *menuTypePtr; /* Used to control whether created tkwin is a
+ * toplevel or not. "normal", "menubar", or
+ * "toplevel" */
+
+ /*
+ * Information used when displaying widget:
+ */
+
+ Tcl_Obj *borderPtr; /* Structure used to draw 3-D border and
+ * background for menu. */
+ Tcl_Obj *borderWidthPtr; /* Width of border around whole menu. */
+ Tcl_Obj *activeBorderPtr; /* Used to draw background and border for
+ * active element (if any). */
+ Tcl_Obj *activeBorderWidthPtr;
+ /* Width of border around active element. */
+ Tcl_Obj *reliefPtr; /* 3-d effect: TK_RELIEF_RAISED, etc. */
+ Tcl_Obj *fontPtr; /* Text font for menu entries. */
+ Tcl_Obj *fgPtr; /* Foreground color for entries. */
+ Tcl_Obj *disabledFgPtr; /* Foreground color when disabled. NULL means
+ * use normalFg with a 50% stipple instead. */
+ Tcl_Obj *activeFgPtr; /* Foreground color for active entry. */
+ Tcl_Obj *indicatorFgPtr; /* Color for indicators in radio and check
+ * button entries. */
+ Pixmap gray; /* Bitmap for drawing disabled entries in a
+ * stippled fashion. None means not allocated
+ * yet. */
+ GC textGC; /* GC for drawing text and other features of
+ * menu entries. */
+ GC disabledGC; /* Used to produce disabled effect. If
+ * disabledFg isn't NULL, this GC is used to
+ * draw text and icons for disabled entries.
+ * Otherwise text and icons are drawn with
+ * normalGC and this GC is used to stipple
+ * background across them. */
+ GC activeGC; /* GC for drawing active entry. */
+ GC indicatorGC; /* For drawing indicators. */
+ GC disabledImageGC; /* Used for drawing disabled images. They have
+ * to be stippled. This is created when the
+ * image is about to be drawn the first
+ * time. */
+
+ /*
+ * Information about geometry of menu.
+ */
+
+ int totalWidth; /* Width of entire menu. */
+ int totalHeight; /* Height of entire menu. */
+
+ /*
+ * Miscellaneous information:
+ */
+
+ int tearoff; /* 1 means this menu can be torn off. On some
+ * platforms, the user can drag an outline of
+ * the menu by just dragging outside of the
+ * menu, and the tearoff is created where the
+ * mouse is released. On others, an indicator
+ * (such as a dashed stripe) is drawn, and
+ * when the menu is selected, the tearoff is
+ * created. */
+ Tcl_Obj *titlePtr; /* The title to use when this menu is torn
+ * off. If this is NULL, a default scheme will
+ * be used to generate a title for tearoff. */
+ Tcl_Obj *tearoffCommandPtr; /* If non-NULL, points to a command to run
+ * whenever the menu is torn-off. */
+ Tcl_Obj *takeFocusPtr; /* Value of -takefocus option; not used in the
+ * C code, but used by keyboard traversal
+ * scripts. Malloc'ed, but may be NULL. */
+ Tcl_Obj *cursorPtr; /* Current cursor for window, or NULL. */
+ Tcl_Obj *postCommandPtr; /* Used to detect cycles in cascade hierarchy
+ * trees when preprocessing postcommands on
+ * some platforms. See PostMenu for more
+ * details. */
+ int postCommandGeneration; /* Need to do pre-invocation post command
+ * traversal. */
+ int menuFlags; /* Flags for use by X; see below for
+ * definition. */
+ TkMenuEntry *postedCascade; /* Points to menu entry for cascaded submenu
+ * that is currently posted or NULL if no
+ * submenu posted. */
+ struct TkMenu *nextInstancePtr;
+ /* The next instance of this menu in the
+ * chain. */
+ struct TkMenu *masterMenuPtr;
+ /* A pointer to the original menu for this
+ * clone chain. Points back to this structure
+ * if this menu is a master menu. */
+ void *reserved1; /* not used any more. */
+ Tk_Window parentTopLevelPtr;/* If this menu is a menubar, this is the
+ * toplevel that owns the menu. Only
+ * applicable for menubar clones. */
+ struct TkMenuReferences *menuRefPtr;
+ /* Each menu is hashed into a table with the
+ * name of the menu's window as the key. The
+ * information in this hash table includes a
+ * pointer to the menu (so that cascades can
+ * find this menu), a pointer to the list of
+ * toplevel widgets that have this menu as its
+ * menubar, and a list of menu entries that
+ * have this menu specified as a cascade. */
+ TkMenuPlatformData platformData;
+ /* The data for the specific type of menu.
+ * Depends on platform and menu type what kind
+ * of options are in this structure. */
+ Tk_OptionSpec *extensionPtr;/* Needed by the configuration package for
+ * this widget to be extended. */
+ Tk_SavedOptions *errorStructPtr;
+ /* We actually have to allocate these because
+ * multiple menus get changed during one
+ * ConfigureMenu call. */
+} TkMenu;
+
+/*
+ * When the toplevel configure -menu command is executed, the menu may not
+ * exist yet. We need to keep a linked list of windows that reference a
+ * particular menu.
+ */
+
+typedef struct TkMenuTopLevelList {
+ struct TkMenuTopLevelList *nextPtr;
+ /* The next window in the list. */
+ Tk_Window tkwin; /* The window that has this menu as its
+ * menubar. */
+} TkMenuTopLevelList;
+
+/*
+ * The following structure is used to keep track of things which reference a
+ * menu. It is created when:
+ * - a menu is created.
+ * - a cascade entry is added to a menu with a non-null name
+ * - the "-menu" configuration option is used on a toplevel widget with a
+ * non-null parameter.
+ *
+ * One of these three fields must be non-NULL, but any of the fields may be
+ * NULL. This structure makes it easy to determine whether or not anything
+ * like recalculating platform data or geometry is necessary when one of the
+ * three actions above is performed.
+ */
+
+typedef struct TkMenuReferences {
+ struct TkMenu *menuPtr; /* The menu data structure. This is NULL if
+ * the menu does not exist. */
+ TkMenuTopLevelList *topLevelListPtr;
+ /* First in the list of all toplevels that
+ * have this menu as its menubar. NULL if no
+ * toplevel widgets have this menu as its
+ * menubar. */
+ TkMenuEntry *parentEntryPtr;/* First in the list of all cascade menu
+ * entries that have this menu as their child.
+ * NULL means no cascade entries. */
+ Tcl_HashEntry *hashEntryPtr;/* This is needed because the pathname of the
+ * window (which is what we hash on) may not
+ * be around when we are deleting. */
+} TkMenuReferences;
+
+/*
+ * Flag bits for menus:
+ *
+ * REDRAW_PENDING: Non-zero means a DoWhenIdle handler has
+ * already been queued to redraw this window.
+ * RESIZE_PENDING: Non-zero means a call to ComputeMenuGeometry
+ * has already been scheduled.
+ * MENU_DELETION_PENDING Non-zero means that we are currently
+ * destroying this menu's internal structures.
+ * This is useful when we are in the middle of
+ * cleaning this master menu's chain of menus up
+ * when TkDestroyMenu was called again on this
+ * menu (via a destroy binding or somesuch).
+ * MENU_WIN_DESTRUCTION_PENDING Non-zero means we are in the middle of
+ * destroying this menu's Tk_Window.
+ * MENU_PLATFORM_FLAG1... Reserved for use by the platform-specific menu
+ * code.
+ */
+
+#define REDRAW_PENDING 1
+#define RESIZE_PENDING 2
+#define MENU_DELETION_PENDING 4
+#define MENU_WIN_DESTRUCTION_PENDING 8
+#define MENU_PLATFORM_FLAG1 (1 << 30)
+#define MENU_PLATFORM_FLAG2 (1 << 29)
+#define MENU_PLATFORM_FLAG3 (1 << 28)
+
+/*
+ * Each menu created by the user is a MASTER_MENU. When a menu is torn off, a
+ * TEAROFF_MENU instance is created. When a menu is assigned to a toplevel as
+ * a menu bar, a MENUBAR instance is created. All instances have the same
+ * configuration information. If the master instance is deleted, all instances
+ * are deleted. If one of the other instances is deleted, only that instance
+ * is deleted.
+ */
+
+#define UNKNOWN_TYPE -1
+#define MASTER_MENU 0
+#define TEAROFF_MENU 1
+#define MENUBAR 2
+
+/*
+ * Various geometry definitions:
+ */
+
+#define CASCADE_ARROW_HEIGHT 10
+#define CASCADE_ARROW_WIDTH 8
+#define DECORATION_BORDER_WIDTH 2
+
+/*
+ * Menu-related functions that are shared among Tk modules but not exported to
+ * the outside world:
+ */
+
+MODULE_SCOPE int TkActivateMenuEntry(TkMenu *menuPtr, int index);
+MODULE_SCOPE void TkBindMenu(Tk_Window tkwin, TkMenu *menuPtr);
+MODULE_SCOPE TkMenuReferences*TkCreateMenuReferences(Tcl_Interp *interp,
+ const char *name);
+MODULE_SCOPE void TkDestroyMenu(TkMenu *menuPtr);
+MODULE_SCOPE void TkEventuallyRecomputeMenu(TkMenu *menuPtr);
+MODULE_SCOPE void TkEventuallyRedrawMenu(TkMenu *menuPtr,
+ TkMenuEntry *mePtr);
+MODULE_SCOPE TkMenuReferences*TkFindMenuReferences(Tcl_Interp *interp, const char *name);
+MODULE_SCOPE TkMenuReferences*TkFindMenuReferencesObj(Tcl_Interp *interp,
+ Tcl_Obj *namePtr);
+MODULE_SCOPE int TkFreeMenuReferences(TkMenuReferences *menuRefPtr);
+MODULE_SCOPE Tcl_HashTable *TkGetMenuHashTable(Tcl_Interp *interp);
+MODULE_SCOPE int TkGetMenuIndex(Tcl_Interp *interp, TkMenu *menuPtr,
+ Tcl_Obj *objPtr, int lastOK, int *indexPtr);
+MODULE_SCOPE void TkMenuInitializeDrawingFields(TkMenu *menuPtr);
+MODULE_SCOPE void TkMenuInitializeEntryDrawingFields(TkMenuEntry *mePtr);
+MODULE_SCOPE int TkInvokeMenu(Tcl_Interp *interp, TkMenu *menuPtr,
+ int index);
+MODULE_SCOPE void TkMenuConfigureDrawOptions(TkMenu *menuPtr);
+MODULE_SCOPE int TkMenuConfigureEntryDrawOptions(
+ TkMenuEntry *mePtr, int index);
+MODULE_SCOPE void TkMenuFreeDrawOptions(TkMenu *menuPtr);
+MODULE_SCOPE void TkMenuEntryFreeDrawOptions(TkMenuEntry *mePtr);
+MODULE_SCOPE void TkMenuEventProc(ClientData clientData,
+ XEvent *eventPtr);
+MODULE_SCOPE void TkMenuImageProc(ClientData clientData, int x, int y,
+ int width, int height, int imgWidth,
+ int imgHeight);
+MODULE_SCOPE void TkMenuInit(void);
+MODULE_SCOPE void TkMenuSelectImageProc(ClientData clientData, int x,
+ int y, int width, int height, int imgWidth,
+ int imgHeight);
+MODULE_SCOPE Tcl_Obj * TkNewMenuName(Tcl_Interp *interp,
+ Tcl_Obj *parentNamePtr, TkMenu *menuPtr);
+MODULE_SCOPE int TkPostCommand(TkMenu *menuPtr);
+MODULE_SCOPE int TkPostSubmenu(Tcl_Interp *interp, TkMenu *menuPtr,
+ TkMenuEntry *mePtr);
+MODULE_SCOPE int TkPostTearoffMenu(Tcl_Interp *interp, TkMenu *menuPtr,
+ int x, int y);
+MODULE_SCOPE int TkPreprocessMenu(TkMenu *menuPtr);
+MODULE_SCOPE void TkRecomputeMenu(TkMenu *menuPtr);
+
+/*
+ * These routines are the platform-dependent routines called by the common
+ * code.
+ */
+
+MODULE_SCOPE void TkpComputeMenubarGeometry(TkMenu *menuPtr);
+MODULE_SCOPE void TkpComputeStandardMenuGeometry(TkMenu *menuPtr);
+MODULE_SCOPE int TkpConfigureMenuEntry(TkMenuEntry *mePtr);
+MODULE_SCOPE void TkpDestroyMenu(TkMenu *menuPtr);
+MODULE_SCOPE void TkpDestroyMenuEntry(TkMenuEntry *mEntryPtr);
+MODULE_SCOPE void TkpDrawMenuEntry(TkMenuEntry *mePtr,
+ Drawable d, Tk_Font tkfont,
+ const Tk_FontMetrics *menuMetricsPtr, int x,
+ int y, int width, int height, int strictMotif,
+ int drawingParameters);
+MODULE_SCOPE void TkpMenuInit(void);
+MODULE_SCOPE int TkpMenuNewEntry(TkMenuEntry *mePtr);
+MODULE_SCOPE int TkpNewMenu(TkMenu *menuPtr);
+MODULE_SCOPE int TkpPostMenu(Tcl_Interp *interp, TkMenu *menuPtr,
+ int x, int y, int index);
+MODULE_SCOPE int TkpPostTearoffMenu(Tcl_Interp *interp, TkMenu *menuPtr,
+ int x, int y, int index);
+MODULE_SCOPE void TkpSetWindowMenuBar(Tk_Window tkwin, TkMenu *menuPtr);
+
+#endif /* _TKMENU */
diff --git a/tk8.6/generic/tkMenuDraw.c b/tk8.6/generic/tkMenuDraw.c
new file mode 100644
index 0000000..d91bc11
--- /dev/null
+++ b/tk8.6/generic/tkMenuDraw.c
@@ -0,0 +1,977 @@
+/*
+ * tkMenuDraw.c --
+ *
+ * This module implements the platform-independent drawing and geometry
+ * calculations of menu widgets.
+ *
+ * Copyright (c) 1996-1997 by Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkInt.h"
+#include "tkMenu.h"
+
+/*
+ * Forward declarations for functions defined later in this file:
+ */
+
+static void AdjustMenuCoords(TkMenu *menuPtr, TkMenuEntry *mePtr,
+ int *xPtr, int *yPtr);
+static void ComputeMenuGeometry(ClientData clientData);
+static void DisplayMenu(ClientData clientData);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMenuInitializeDrawingFields --
+ *
+ * Fills in drawing fields of a new menu. Called when new menu is created
+ * by MenuCmd.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * menuPtr fields are initialized.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMenuInitializeDrawingFields(
+ TkMenu *menuPtr) /* The menu we are initializing. */
+{
+ menuPtr->textGC = NULL;
+ menuPtr->gray = None;
+ menuPtr->disabledGC = NULL;
+ menuPtr->activeGC = NULL;
+ menuPtr->indicatorGC = NULL;
+ menuPtr->disabledImageGC = NULL;
+ menuPtr->totalWidth = menuPtr->totalHeight = 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMenuInitializeEntryDrawingFields --
+ *
+ * Fills in drawing fields of a new menu entry. Called when an entry is
+ * created.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMenuInitializeEntryDrawingFields(
+ TkMenuEntry *mePtr) /* The menu we are initializing. */
+{
+ mePtr->width = 0;
+ mePtr->height = 0;
+ mePtr->x = 0;
+ mePtr->y = 0;
+ mePtr->indicatorSpace = 0;
+ mePtr->labelWidth = 0;
+ mePtr->textGC = NULL;
+ mePtr->activeGC = NULL;
+ mePtr->disabledGC = NULL;
+ mePtr->indicatorGC = NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMenuFreeDrawOptions --
+ *
+ * Frees up any structures allocated for the drawing of a menu. Called
+ * when menu is deleted.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Storage is released.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMenuFreeDrawOptions(
+ TkMenu *menuPtr)
+{
+ if (menuPtr->textGC != NULL) {
+ Tk_FreeGC(menuPtr->display, menuPtr->textGC);
+ }
+ if (menuPtr->disabledImageGC != NULL) {
+ Tk_FreeGC(menuPtr->display, menuPtr->disabledImageGC);
+ }
+ if (menuPtr->gray != None) {
+ Tk_FreeBitmap(menuPtr->display, menuPtr->gray);
+ }
+ if (menuPtr->disabledGC != NULL) {
+ Tk_FreeGC(menuPtr->display, menuPtr->disabledGC);
+ }
+ if (menuPtr->activeGC != NULL) {
+ Tk_FreeGC(menuPtr->display, menuPtr->activeGC);
+ }
+ if (menuPtr->indicatorGC != NULL) {
+ Tk_FreeGC(menuPtr->display, menuPtr->indicatorGC);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMenuEntryFreeDrawOptions --
+ *
+ * Frees up drawing structures for a menu entry. Called when menu entry
+ * is freed.
+ *
+ * RESULTS:
+ * None.
+ *
+ * Side effects:
+ * Storage is freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMenuEntryFreeDrawOptions(
+ TkMenuEntry *mePtr)
+{
+ if (mePtr->textGC != NULL) {
+ Tk_FreeGC(mePtr->menuPtr->display, mePtr->textGC);
+ }
+ if (mePtr->disabledGC != NULL) {
+ Tk_FreeGC(mePtr->menuPtr->display, mePtr->disabledGC);
+ }
+ if (mePtr->activeGC != NULL) {
+ Tk_FreeGC(mePtr->menuPtr->display, mePtr->activeGC);
+ }
+ if (mePtr->indicatorGC != NULL) {
+ Tk_FreeGC(mePtr->menuPtr->display, mePtr->indicatorGC);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMenuConfigureDrawOptions --
+ *
+ * Sets the menu's drawing attributes in preparation for drawing the
+ * menu.
+ *
+ * RESULTS:
+ * None.
+ *
+ * Side effects:
+ * Storage is allocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMenuConfigureDrawOptions(
+ TkMenu *menuPtr) /* The menu we are configuring. */
+{
+ XGCValues gcValues;
+ GC newGC;
+ unsigned long mask;
+ Tk_3DBorder border, activeBorder;
+ Tk_Font tkfont;
+ XColor *fg, *activeFg, *indicatorFg;
+
+ /*
+ * A few options need special processing, such as setting the background
+ * from a 3-D border, or filling in complicated defaults that couldn't be
+ * specified to Tk_ConfigureWidget.
+ */
+
+ border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr);
+ Tk_SetBackgroundFromBorder(menuPtr->tkwin, border);
+
+ tkfont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
+ gcValues.font = Tk_FontId(tkfont);
+ fg = Tk_GetColorFromObj(menuPtr->tkwin, menuPtr->fgPtr);
+ gcValues.foreground = fg->pixel;
+ gcValues.background = Tk_3DBorderColor(border)->pixel;
+ newGC = Tk_GetGC(menuPtr->tkwin, GCForeground|GCBackground|GCFont,
+ &gcValues);
+ if (menuPtr->textGC != NULL) {
+ Tk_FreeGC(menuPtr->display, menuPtr->textGC);
+ }
+ menuPtr->textGC = newGC;
+
+ gcValues.font = Tk_FontId(tkfont);
+ gcValues.background = Tk_3DBorderColor(border)->pixel;
+ if (menuPtr->disabledFgPtr != NULL) {
+ XColor *disabledFg;
+
+ disabledFg = Tk_GetColorFromObj(menuPtr->tkwin,
+ menuPtr->disabledFgPtr);
+ gcValues.foreground = disabledFg->pixel;
+ mask = GCForeground|GCBackground|GCFont;
+ } else {
+ gcValues.foreground = gcValues.background;
+ mask = GCForeground;
+ if (menuPtr->gray == None) {
+ menuPtr->gray = Tk_GetBitmap(menuPtr->interp, menuPtr->tkwin,
+ "gray50");
+ }
+ if (menuPtr->gray != None) {
+ gcValues.fill_style = FillStippled;
+ gcValues.stipple = menuPtr->gray;
+ mask = GCForeground|GCFillStyle|GCStipple;
+ }
+ }
+ newGC = Tk_GetGC(menuPtr->tkwin, mask, &gcValues);
+ if (menuPtr->disabledGC != NULL) {
+ Tk_FreeGC(menuPtr->display, menuPtr->disabledGC);
+ }
+ menuPtr->disabledGC = newGC;
+
+ gcValues.foreground = Tk_3DBorderColor(border)->pixel;
+ if (menuPtr->gray == None) {
+ menuPtr->gray = Tk_GetBitmap(menuPtr->interp, menuPtr->tkwin,
+ "gray50");
+ }
+ if (menuPtr->gray != None) {
+ gcValues.fill_style = FillStippled;
+ gcValues.stipple = menuPtr->gray;
+ newGC = Tk_GetGC(menuPtr->tkwin,
+ GCForeground|GCFillStyle|GCStipple, &gcValues);
+ }
+ if (menuPtr->disabledImageGC != NULL) {
+ Tk_FreeGC(menuPtr->display, menuPtr->disabledImageGC);
+ }
+ menuPtr->disabledImageGC = newGC;
+
+ gcValues.font = Tk_FontId(tkfont);
+ activeFg = Tk_GetColorFromObj(menuPtr->tkwin, menuPtr->activeFgPtr);
+ gcValues.foreground = activeFg->pixel;
+ activeBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin,
+ menuPtr->activeBorderPtr);
+ gcValues.background = Tk_3DBorderColor(activeBorder)->pixel;
+ newGC = Tk_GetGC(menuPtr->tkwin, GCForeground|GCBackground|GCFont,
+ &gcValues);
+ if (menuPtr->activeGC != NULL) {
+ Tk_FreeGC(menuPtr->display, menuPtr->activeGC);
+ }
+ menuPtr->activeGC = newGC;
+
+ indicatorFg = Tk_GetColorFromObj(menuPtr->tkwin,
+ menuPtr->indicatorFgPtr);
+ gcValues.foreground = indicatorFg->pixel;
+ gcValues.background = Tk_3DBorderColor(border)->pixel;
+ newGC = Tk_GetGC(menuPtr->tkwin, GCForeground|GCBackground|GCFont,
+ &gcValues);
+ if (menuPtr->indicatorGC != NULL) {
+ Tk_FreeGC(menuPtr->display, menuPtr->indicatorGC);
+ }
+ menuPtr->indicatorGC = newGC;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMenuConfigureEntryDrawOptions --
+ *
+ * Calculates any entry-specific draw options for the given menu entry.
+ *
+ * Results:
+ * Returns a standard Tcl error.
+ *
+ * Side effects:
+ * Storage may be allocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkMenuConfigureEntryDrawOptions(
+ TkMenuEntry *mePtr,
+ int index)
+{
+ XGCValues gcValues;
+ GC newGC, newActiveGC, newDisabledGC, newIndicatorGC;
+ unsigned long mask;
+ Tk_Font tkfont;
+ TkMenu *menuPtr = mePtr->menuPtr;
+
+ tkfont = Tk_GetFontFromObj(menuPtr->tkwin,
+ (mePtr->fontPtr != NULL) ? mePtr->fontPtr : menuPtr->fontPtr);
+
+ if (mePtr->state == ENTRY_ACTIVE) {
+ if (index != menuPtr->active) {
+ TkActivateMenuEntry(menuPtr, index);
+ }
+ } else {
+ if (index == menuPtr->active) {
+ TkActivateMenuEntry(menuPtr, -1);
+ }
+ }
+
+ if ((mePtr->fontPtr != NULL)
+ || (mePtr->borderPtr != NULL)
+ || (mePtr->fgPtr != NULL)
+ || (mePtr->activeBorderPtr != NULL)
+ || (mePtr->activeFgPtr != NULL)
+ || (mePtr->indicatorFgPtr != NULL)) {
+ XColor *fg, *indicatorFg, *activeFg;
+ Tk_3DBorder border, activeBorder;
+
+ fg = Tk_GetColorFromObj(menuPtr->tkwin, (mePtr->fgPtr != NULL)
+ ? mePtr->fgPtr : menuPtr->fgPtr);
+ gcValues.foreground = fg->pixel;
+ border = Tk_Get3DBorderFromObj(menuPtr->tkwin,
+ (mePtr->borderPtr != NULL) ? mePtr->borderPtr
+ : menuPtr->borderPtr);
+ gcValues.background = Tk_3DBorderColor(border)->pixel;
+
+ gcValues.font = Tk_FontId(tkfont);
+
+ /*
+ * Note: disable GraphicsExpose events; we know there won't be
+ * obscured areas when copying from an off-screen pixmap to the screen
+ * and this gets rid of unnecessary events.
+ */
+
+ gcValues.graphics_exposures = False;
+ newGC = Tk_GetGC(menuPtr->tkwin,
+ GCForeground|GCBackground|GCFont|GCGraphicsExposures,
+ &gcValues);
+
+ indicatorFg = Tk_GetColorFromObj(menuPtr->tkwin,
+ (mePtr->indicatorFgPtr != NULL) ? mePtr->indicatorFgPtr
+ : menuPtr->indicatorFgPtr);
+ gcValues.foreground = indicatorFg->pixel;
+ newIndicatorGC = Tk_GetGC(menuPtr->tkwin,
+ GCForeground|GCBackground|GCGraphicsExposures,
+ &gcValues);
+
+ if ((menuPtr->disabledFgPtr != NULL) || (mePtr->image != NULL)) {
+ XColor *disabledFg;
+
+ disabledFg = Tk_GetColorFromObj(menuPtr->tkwin,
+ menuPtr->disabledFgPtr);
+ gcValues.foreground = disabledFg->pixel;
+ mask = GCForeground|GCBackground|GCFont|GCGraphicsExposures;
+ } else {
+ gcValues.foreground = gcValues.background;
+ gcValues.fill_style = FillStippled;
+ gcValues.stipple = menuPtr->gray;
+ mask = GCForeground|GCFillStyle|GCStipple;
+ }
+ newDisabledGC = Tk_GetGC(menuPtr->tkwin, mask, &gcValues);
+
+ activeFg = Tk_GetColorFromObj(menuPtr->tkwin,
+ (mePtr->activeFgPtr != NULL) ? mePtr->activeFgPtr
+ : menuPtr->activeFgPtr);
+ activeBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin,
+ (mePtr->activeBorderPtr != NULL) ? mePtr->activeBorderPtr
+ : menuPtr->activeBorderPtr);
+
+ gcValues.foreground = activeFg->pixel;
+ gcValues.background = Tk_3DBorderColor(activeBorder)->pixel;
+ newActiveGC = Tk_GetGC(menuPtr->tkwin,
+ GCForeground|GCBackground|GCFont|GCGraphicsExposures,
+ &gcValues);
+ } else {
+ newGC = NULL;
+ newActiveGC = NULL;
+ newDisabledGC = NULL;
+ newIndicatorGC = NULL;
+ }
+ if (mePtr->textGC != NULL) {
+ Tk_FreeGC(menuPtr->display, mePtr->textGC);
+ }
+ mePtr->textGC = newGC;
+ if (mePtr->activeGC != NULL) {
+ Tk_FreeGC(menuPtr->display, mePtr->activeGC);
+ }
+ mePtr->activeGC = newActiveGC;
+ if (mePtr->disabledGC != NULL) {
+ Tk_FreeGC(menuPtr->display, mePtr->disabledGC);
+ }
+ mePtr->disabledGC = newDisabledGC;
+ if (mePtr->indicatorGC != NULL) {
+ Tk_FreeGC(menuPtr->display, mePtr->indicatorGC);
+ }
+ mePtr->indicatorGC = newIndicatorGC;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkEventuallyRecomputeMenu --
+ *
+ * Tells Tcl to redo the geometry because this menu has changed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Menu geometry is recomputed at idle time, and the menu will be
+ * redisplayed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkEventuallyRecomputeMenu(
+ TkMenu *menuPtr)
+{
+ if (!(menuPtr->menuFlags & RESIZE_PENDING)) {
+ menuPtr->menuFlags |= RESIZE_PENDING;
+ Tcl_DoWhenIdle(ComputeMenuGeometry, menuPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkRecomputeMenu --
+ *
+ * Tells Tcl to redo the geometry because this menu has changed. Does it
+ * now; removes any ComputeMenuGeometries from the idler.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Menu geometry is immediately reconfigured.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkRecomputeMenu(
+ TkMenu *menuPtr)
+{
+ if (menuPtr->menuFlags & RESIZE_PENDING) {
+ Tcl_CancelIdleCall(ComputeMenuGeometry, menuPtr);
+ ComputeMenuGeometry(menuPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkEventuallyRedrawMenu --
+ *
+ * Arrange for an entry of a menu, or the whole menu, to be redisplayed
+ * at some point in the future.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A when-idle handler is scheduled to do the redisplay, if there isn't
+ * one already scheduled.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkEventuallyRedrawMenu(
+ register TkMenu *menuPtr, /* Information about menu to redraw. */
+ register TkMenuEntry *mePtr)/* Entry to redraw. NULL means redraw all the
+ * entries in the menu. */
+{
+ int i;
+
+ if (menuPtr->tkwin == NULL) {
+ return;
+ }
+ if (mePtr != NULL) {
+ mePtr->entryFlags |= ENTRY_NEEDS_REDISPLAY;
+ } else {
+ for (i = 0; i < menuPtr->numEntries; i++) {
+ menuPtr->entries[i]->entryFlags |= ENTRY_NEEDS_REDISPLAY;
+ }
+ }
+ if (!Tk_IsMapped(menuPtr->tkwin)
+ || (menuPtr->menuFlags & REDRAW_PENDING)) {
+ return;
+ }
+ Tcl_DoWhenIdle(DisplayMenu, menuPtr);
+ menuPtr->menuFlags |= REDRAW_PENDING;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ComputeMenuGeometry --
+ *
+ * This function is invoked to recompute the size and layout of a menu.
+ * It is called as a when-idle handler so that it only gets done once,
+ * even if a group of changes is made to the menu.
+ *
+ * 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.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ComputeMenuGeometry(
+ ClientData clientData) /* Structure describing menu. */
+{
+ TkMenu *menuPtr = clientData;
+
+ if (menuPtr->tkwin == NULL) {
+ return;
+ }
+
+ if (menuPtr->menuType == MENUBAR) {
+ TkpComputeMenubarGeometry(menuPtr);
+ } else {
+ TkpComputeStandardMenuGeometry(menuPtr);
+ }
+
+ if ((menuPtr->totalWidth != Tk_ReqWidth(menuPtr->tkwin)) ||
+ (menuPtr->totalHeight != Tk_ReqHeight(menuPtr->tkwin))) {
+ Tk_GeometryRequest(menuPtr->tkwin, menuPtr->totalWidth,
+ menuPtr->totalHeight);
+ }
+
+ /*
+ * Must always force a redisplay here if the window is mapped (even if the
+ * size didn't change, something else might have changed in the menu, such
+ * as a label or accelerator). The resize will force a redisplay above.
+ */
+
+ TkEventuallyRedrawMenu(menuPtr, NULL);
+
+ menuPtr->menuFlags &= ~RESIZE_PENDING;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMenuSelectImageProc --
+ *
+ * This function is invoked by the image code whenever the manager for an
+ * image does something that affects the size of contents of an image
+ * displayed in a menu entry when it is selected.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Arranges for the menu to get redisplayed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMenuSelectImageProc(
+ ClientData clientData, /* Pointer to widget record. */
+ int x, int y, /* Upper left pixel (within image) that must
+ * be redisplayed. */
+ int width, int height, /* Dimensions of area to redisplay (may be
+ * <=0). */
+ int imgWidth, int imgHeight)/* New dimensions of image. */
+{
+ register TkMenuEntry *mePtr = clientData;
+
+ if ((mePtr->entryFlags & ENTRY_SELECTED)
+ && !(mePtr->menuPtr->menuFlags & REDRAW_PENDING)) {
+ mePtr->menuPtr->menuFlags |= REDRAW_PENDING;
+ Tcl_DoWhenIdle(DisplayMenu, mePtr->menuPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DisplayMenu --
+ *
+ * This function is invoked to display a menu widget.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Commands are output to X to display the menu in its current mode.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DisplayMenu(
+ ClientData clientData) /* Information about widget. */
+{
+ register TkMenu *menuPtr = clientData;
+ register TkMenuEntry *mePtr;
+ register Tk_Window tkwin = menuPtr->tkwin;
+ int index, strictMotif;
+ Tk_Font tkfont;
+ Tk_FontMetrics menuMetrics;
+ int width;
+ int borderWidth;
+ Tk_3DBorder border;
+ int relief;
+
+
+ menuPtr->menuFlags &= ~REDRAW_PENDING;
+ if ((menuPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
+ return;
+ }
+
+ Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr,
+ &borderWidth);
+ border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr);
+
+ if (menuPtr->menuType == MENUBAR) {
+ Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, borderWidth,
+ borderWidth, Tk_Width(tkwin) - 2 * borderWidth,
+ Tk_Height(tkwin) - 2 * borderWidth, 0, TK_RELIEF_FLAT);
+ }
+
+ strictMotif = Tk_StrictMotif(menuPtr->tkwin);
+
+ /*
+ * See note in ComputeMenuGeometry. We don't want to be doing font metrics
+ * all of the time.
+ */
+
+ tkfont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
+ Tk_GetFontMetrics(tkfont, &menuMetrics);
+
+ /*
+ * Loop through all of the entries, drawing them one at a time.
+ */
+
+ for (index = 0; index < menuPtr->numEntries; index++) {
+ mePtr = menuPtr->entries[index];
+ if (menuPtr->menuType != MENUBAR) {
+ if (!(mePtr->entryFlags & ENTRY_NEEDS_REDISPLAY)) {
+ continue;
+ }
+ }
+ mePtr->entryFlags &= ~ENTRY_NEEDS_REDISPLAY;
+
+ TkpDrawMenuEntry(mePtr, Tk_WindowId(menuPtr->tkwin), tkfont,
+ &menuMetrics, mePtr->x, mePtr->y, mePtr->width,
+ mePtr->height, strictMotif, 1);
+ if ((index > 0) && (menuPtr->menuType != MENUBAR)
+ && mePtr->columnBreak) {
+ mePtr = menuPtr->entries[index - 1];
+ Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border,
+ mePtr->x, mePtr->y + mePtr->height, mePtr->width,
+ Tk_Height(tkwin) - mePtr->y - mePtr->height - borderWidth,
+ 0, TK_RELIEF_FLAT);
+ }
+ }
+
+ if (menuPtr->menuType != MENUBAR) {
+ int x, y, height;
+
+ if (menuPtr->numEntries == 0) {
+ x = y = borderWidth;
+ width = Tk_Width(tkwin) - 2 * borderWidth;
+ height = Tk_Height(tkwin) - 2 * borderWidth;
+ } else {
+ mePtr = menuPtr->entries[menuPtr->numEntries - 1];
+ Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin),
+ border, mePtr->x, mePtr->y + mePtr->height, mePtr->width,
+ Tk_Height(tkwin) - mePtr->y - mePtr->height - borderWidth,
+ 0, TK_RELIEF_FLAT);
+ x = mePtr->x + mePtr->width;
+ y = mePtr->y + mePtr->height;
+ width = Tk_Width(tkwin) - x - borderWidth;
+ height = Tk_Height(tkwin) - y - borderWidth;
+ }
+ Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, x, y,
+ width, height, 0, TK_RELIEF_FLAT);
+ }
+
+ Tk_GetReliefFromObj(NULL, menuPtr->reliefPtr, &relief);
+ Tk_Draw3DRectangle(menuPtr->tkwin, Tk_WindowId(tkwin),
+ border, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), borderWidth,
+ relief);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkMenuEventProc --
+ *
+ * This function is invoked by the Tk dispatcher for various events on
+ * menus.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * When the window gets deleted, internal structures get cleaned up. When
+ * it gets exposed, it is redisplayed.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkMenuEventProc(
+ ClientData clientData, /* Information about window. */
+ XEvent *eventPtr) /* Information about event. */
+{
+ TkMenu *menuPtr = clientData;
+
+ if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {
+ TkEventuallyRedrawMenu(menuPtr, NULL);
+ } else if (eventPtr->type == ConfigureNotify) {
+ TkEventuallyRecomputeMenu(menuPtr);
+ TkEventuallyRedrawMenu(menuPtr, NULL);
+ } else if (eventPtr->type == ActivateNotify) {
+ if (menuPtr->menuType == TEAROFF_MENU) {
+ TkpSetMainMenubar(menuPtr->interp, menuPtr->tkwin, NULL);
+ }
+ } else if (eventPtr->type == DestroyNotify) {
+ if (menuPtr->tkwin != NULL) {
+ if (!(menuPtr->menuFlags & MENU_DELETION_PENDING)) {
+ TkDestroyMenu(menuPtr);
+ }
+ menuPtr->tkwin = NULL;
+ }
+ if (menuPtr->menuFlags & MENU_WIN_DESTRUCTION_PENDING) {
+ return;
+ }
+ menuPtr->menuFlags |= MENU_WIN_DESTRUCTION_PENDING;
+ if (menuPtr->widgetCmd != NULL) {
+ Tcl_DeleteCommandFromToken(menuPtr->interp, menuPtr->widgetCmd);
+ menuPtr->widgetCmd = NULL;
+ }
+ if (menuPtr->menuFlags & REDRAW_PENDING) {
+ Tcl_CancelIdleCall(DisplayMenu, menuPtr);
+ menuPtr->menuFlags &= ~REDRAW_PENDING;
+ }
+ if (menuPtr->menuFlags & RESIZE_PENDING) {
+ Tcl_CancelIdleCall(ComputeMenuGeometry, menuPtr);
+ menuPtr->menuFlags &= ~RESIZE_PENDING;
+ }
+ Tcl_EventuallyFree(menuPtr, TCL_DYNAMIC);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMenuImageProc --
+ *
+ * This function is invoked by the image code whenever the manager for an
+ * image does something that affects the size of contents of an image
+ * displayed in a menu entry.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Arranges for the menu to get redisplayed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMenuImageProc(
+ ClientData clientData, /* Pointer to widget record. */
+ int x, int y, /* Upper left pixel (within image) that must
+ * be redisplayed. */
+ int width, int height, /* Dimensions of area to redisplay (may be
+ * <=0). */
+ int imgWidth, int imgHeight)/* New dimensions of image. */
+{
+ register TkMenu *menuPtr = ((TkMenuEntry *) clientData)->menuPtr;
+
+ if ((menuPtr->tkwin != NULL) && !(menuPtr->menuFlags & RESIZE_PENDING)) {
+ menuPtr->menuFlags |= RESIZE_PENDING;
+ Tcl_DoWhenIdle(ComputeMenuGeometry, menuPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkPostTearoffMenu --
+ *
+ * Posts a tearoff menu on the screen. Adjusts the menu's position so
+ * that it fits on the screen, and maps and raises the menu.
+ *
+ * Results:
+ * Returns a standard Tcl Error.
+ *
+ * Side effects:
+ * The menu is posted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkPostTearoffMenu(
+ Tcl_Interp *interp, /* The interpreter of the menu */
+ TkMenu *menuPtr, /* The menu we are posting */
+ int x, int y) /* The root X,Y coordinates where we are
+ * posting */
+{
+ return TkpPostTearoffMenu(interp, menuPtr, x, y, -1);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkPostSubmenu --
+ *
+ * This function arranges for a particular submenu (i.e. the menu
+ * corresponding to a given cascade entry) to be posted.
+ *
+ * Results:
+ * A standard Tcl return result. Errors may occur in the Tcl commands
+ * generated to post and unpost submenus.
+ *
+ * Side effects:
+ * If there is already a submenu posted, it is unposted. The new submenu
+ * is then posted.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkPostSubmenu(
+ Tcl_Interp *interp, /* Used for invoking sub-commands and
+ * reporting errors. */
+ register TkMenu *menuPtr, /* Information about menu as a whole. */
+ register TkMenuEntry *mePtr)/* Info about submenu that is to be posted.
+ * NULL means make sure that no submenu is
+ * posted. */
+{
+ int result, x, y;
+ Tcl_Obj *subary[4];
+
+ if (mePtr == menuPtr->postedCascade) {
+ return TCL_OK;
+ }
+
+ if (menuPtr->postedCascade != NULL) {
+ /*
+ * Note: when unposting a submenu, we have to redraw the entire parent
+ * menu. This is because of a combination of the following things:
+ * (a) the submenu partially overlaps the parent.
+ * (b) the submenu specifies "save under", which causes the X server
+ * to make a copy of the information under it when it is posted.
+ * When the submenu is unposted, the X server copies this data
+ * back and doesn't generate any Expose events for the parent.
+ * (c) the parent may have redisplayed itself after the submenu was
+ * posted, in which case the saved information is no longer
+ * correct.
+ * The simplest solution is just force a complete redisplay of the
+ * parent.
+ */
+
+ subary[0] = menuPtr->postedCascade->namePtr;
+ subary[1] = Tcl_NewStringObj("unpost", -1);
+ Tcl_IncrRefCount(subary[1]);
+ TkEventuallyRedrawMenu(menuPtr, NULL);
+ result = Tcl_EvalObjv(interp, 2, subary, 0);
+ Tcl_DecrRefCount(subary[1]);
+ menuPtr->postedCascade = NULL;
+ if (result != TCL_OK) {
+ return result;
+ }
+ }
+
+ if ((mePtr != NULL) && (mePtr->namePtr != NULL)
+ && Tk_IsMapped(menuPtr->tkwin)) {
+ /*
+ * Position the cascade with its upper left corner slightly below and
+ * to the left of the upper right corner of the menu entry (this is an
+ * attempt to match Motif behavior).
+ *
+ * The menu has to redrawn so that the entry can change relief.
+ *
+ * Set postedCascade early to ensure tear-off submenus work on
+ * Windows. [Bug 873613]
+ */
+
+ Tk_GetRootCoords(menuPtr->tkwin, &x, &y);
+ AdjustMenuCoords(menuPtr, mePtr, &x, &y);
+
+ menuPtr->postedCascade = mePtr;
+ subary[0] = mePtr->namePtr;
+ subary[1] = Tcl_NewStringObj("post", -1);
+ subary[2] = Tcl_NewIntObj(x);
+ subary[3] = Tcl_NewIntObj(y);
+ Tcl_IncrRefCount(subary[1]);
+ Tcl_IncrRefCount(subary[2]);
+ Tcl_IncrRefCount(subary[3]);
+ result = Tcl_EvalObjv(interp, 4, subary, 0);
+ Tcl_DecrRefCount(subary[1]);
+ Tcl_DecrRefCount(subary[2]);
+ Tcl_DecrRefCount(subary[3]);
+ if (result != TCL_OK) {
+ menuPtr->postedCascade = NULL;
+ return result;
+ }
+ TkEventuallyRedrawMenu(menuPtr, mePtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AdjustMenuCoords --
+ *
+ * Adjusts the given coordinates down and the left to give a Motif look.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The menu is eventually redrawn if necessary.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+AdjustMenuCoords(
+ TkMenu *menuPtr,
+ TkMenuEntry *mePtr,
+ int *xPtr,
+ int *yPtr)
+{
+ if (menuPtr->menuType == MENUBAR) {
+ *xPtr += mePtr->x;
+ *yPtr += mePtr->y + mePtr->height;
+ } else {
+ int borderWidth, activeBorderWidth;
+
+ Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr,
+ &borderWidth);
+ Tk_GetPixelsFromObj(NULL, menuPtr->tkwin,
+ menuPtr->activeBorderWidthPtr, &activeBorderWidth);
+ *xPtr += Tk_Width(menuPtr->tkwin) - borderWidth - activeBorderWidth
+ - 2;
+ *yPtr += mePtr->y + activeBorderWidth + 2;
+ }
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkMenubutton.c b/tk8.6/generic/tkMenubutton.c
new file mode 100644
index 0000000..2228a2e
--- /dev/null
+++ b/tk8.6/generic/tkMenubutton.c
@@ -0,0 +1,984 @@
+/*
+ * tkMenubutton.c --
+ *
+ * This module implements button-like widgets that are used to invoke
+ * pull-down menus.
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "tkInt.h"
+#include "tkMenubutton.h"
+#include "default.h"
+
+/*
+ * The structure below defines menubutton class behavior by means of
+ * procedures that can be invoked from generic window code.
+ */
+
+static const Tk_ClassProcs menubuttonClass = {
+ sizeof(Tk_ClassProcs), /* size */
+ TkMenuButtonWorldChanged, /* worldChangedProc */
+ NULL, /* createProc */
+ NULL /* modalProc */
+};
+
+/*
+ * The following table defines the legal values for the -direction option. It
+ * is used together with the "enum direction" declaration in tkMenubutton.h.
+ */
+
+static const char *const directionStrings[] = {
+ "above", "below", "flush", "left", "right", NULL
+};
+
+/*
+ * The following table defines the legal values for the -state option. It is
+ * used together with the "enum state" declaration in tkMenubutton.h.
+ */
+
+static const char *const stateStrings[] = {
+ "active", "disabled", "normal", NULL
+};
+
+/*
+ * The following table defines the legal values for the -compound option. It
+ * is used with the "enum compound" declaration in tkMenuButton.h
+ */
+
+static const char *const compoundStrings[] = {
+ "bottom", "center", "left", "none", "right", "top", NULL
+};
+
+/*
+ * Information used for parsing configuration specs:
+ */
+
+static const Tk_OptionSpec optionSpecs[] = {
+ {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",
+ DEF_MENUBUTTON_ACTIVE_BG_COLOR, -1,
+ Tk_Offset(TkMenuButton, activeBorder), 0,
+ (ClientData) DEF_MENUBUTTON_ACTIVE_BG_MONO, 0},
+ {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background",
+ DEF_MENUBUTTON_ACTIVE_FG_COLOR, -1,
+ Tk_Offset(TkMenuButton, activeFg),
+ 0, DEF_MENUBUTTON_ACTIVE_FG_MONO, 0},
+ {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
+ DEF_MENUBUTTON_ANCHOR, -1,
+ Tk_Offset(TkMenuButton, anchor), 0, 0, 0},
+ {TK_OPTION_BORDER, "-background", "background", "Background",
+ DEF_MENUBUTTON_BG_COLOR, -1, Tk_Offset(TkMenuButton, normalBorder),
+ 0, DEF_MENUBUTTON_BG_MONO, 0},
+ {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL, 0, -1, 0,
+ (ClientData) "-borderwidth", 0},
+ {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, 0, -1, 0,
+ (ClientData) "-background", 0},
+ {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap",
+ DEF_MENUBUTTON_BITMAP, -1, Tk_Offset(TkMenuButton, bitmap),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ DEF_MENUBUTTON_BORDER_WIDTH, -1,
+ Tk_Offset(TkMenuButton, borderWidth), 0, 0, 0},
+ {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
+ DEF_MENUBUTTON_CURSOR, -1, Tk_Offset(TkMenuButton, cursor),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-direction", "direction", "Direction",
+ DEF_MENUBUTTON_DIRECTION, -1, Tk_Offset(TkMenuButton, direction),
+ 0, directionStrings, 0},
+ {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
+ "DisabledForeground", DEF_MENUBUTTON_DISABLED_FG_COLOR,
+ -1, Tk_Offset(TkMenuButton, disabledFg), TK_OPTION_NULL_OK,
+ (ClientData) DEF_MENUBUTTON_DISABLED_FG_MONO, 0},
+ {TK_OPTION_SYNONYM, "-fg", "foreground", NULL, NULL, 0, -1, 0,
+ (ClientData) "-foreground", 0},
+ {TK_OPTION_FONT, "-font", "font", "Font",
+ DEF_MENUBUTTON_FONT, -1, Tk_Offset(TkMenuButton, tkfont), 0, 0, 0},
+ {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
+ DEF_MENUBUTTON_FG, -1, Tk_Offset(TkMenuButton, normalFg), 0, 0, 0},
+ {TK_OPTION_STRING, "-height", "height", "Height",
+ DEF_MENUBUTTON_HEIGHT, -1, Tk_Offset(TkMenuButton, heightString),
+ 0, 0, 0},
+ {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground",
+ "HighlightBackground", DEF_MENUBUTTON_HIGHLIGHT_BG_COLOR,
+ -1, Tk_Offset(TkMenuButton, highlightBgColorPtr), 0, 0, 0},
+ {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
+ DEF_MENUBUTTON_HIGHLIGHT, -1,
+ Tk_Offset(TkMenuButton, highlightColorPtr), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
+ "HighlightThickness", DEF_MENUBUTTON_HIGHLIGHT_WIDTH,
+ -1, Tk_Offset(TkMenuButton, highlightWidth), 0, 0, 0},
+ {TK_OPTION_STRING, "-image", "image", "Image",
+ DEF_MENUBUTTON_IMAGE, -1, Tk_Offset(TkMenuButton, imageString),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_BOOLEAN, "-indicatoron", "indicatorOn", "IndicatorOn",
+ DEF_MENUBUTTON_INDICATOR, -1, Tk_Offset(TkMenuButton, indicatorOn),
+ 0, 0, 0},
+ {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
+ DEF_MENUBUTTON_JUSTIFY, -1, Tk_Offset(TkMenuButton, justify), 0, 0, 0},
+ {TK_OPTION_STRING, "-menu", "menu", "Menu",
+ DEF_MENUBUTTON_MENU, -1, Tk_Offset(TkMenuButton, menuName),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
+ DEF_MENUBUTTON_PADX, -1, Tk_Offset(TkMenuButton, padX),
+ 0, 0, 0},
+ {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
+ DEF_MENUBUTTON_PADY, -1, Tk_Offset(TkMenuButton, padY),
+ 0, 0, 0},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ DEF_MENUBUTTON_RELIEF, -1, Tk_Offset(TkMenuButton, relief),
+ 0, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound",
+ DEF_BUTTON_COMPOUND, -1, Tk_Offset(TkMenuButton, compound), 0,
+ compoundStrings, 0},
+ {TK_OPTION_STRING_TABLE, "-state", "state", "State",
+ DEF_MENUBUTTON_STATE, -1, Tk_Offset(TkMenuButton, state),
+ 0, stateStrings, 0},
+ {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
+ DEF_MENUBUTTON_TAKE_FOCUS, -1,
+ Tk_Offset(TkMenuButton, takeFocus), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-text", "text", "Text",
+ DEF_MENUBUTTON_TEXT, -1, Tk_Offset(TkMenuButton, text), 0, 0, 0},
+ {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
+ DEF_MENUBUTTON_TEXT_VARIABLE, -1,
+ Tk_Offset(TkMenuButton, textVarName), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_INT, "-underline", "underline", "Underline",
+ DEF_MENUBUTTON_UNDERLINE, -1, Tk_Offset(TkMenuButton, underline),
+ 0, 0, 0},
+ {TK_OPTION_STRING, "-width", "width", "Width",
+ DEF_MENUBUTTON_WIDTH, -1, Tk_Offset(TkMenuButton, widthString),
+ 0, 0, 0},
+ {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",
+ DEF_MENUBUTTON_WRAP_LENGTH, -1, Tk_Offset(TkMenuButton, wrapLength),
+ 0, 0, 0},
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}
+};
+
+/*
+ * The following tables define the menubutton widget commands and map the
+ * indexes into the string tables into a single enumerated type used to
+ * dispatch the scale widget command.
+ */
+
+static const char *const commandNames[] = {
+ "cget", "configure", NULL
+};
+
+enum command {
+ COMMAND_CGET, COMMAND_CONFIGURE
+};
+
+/*
+ * Forward declarations for functions defined later in this file:
+ */
+
+static void MenuButtonCmdDeletedProc(ClientData clientData);
+static void MenuButtonEventProc(ClientData clientData,
+ XEvent *eventPtr);
+static void MenuButtonImageProc(ClientData clientData,
+ int x, int y, int width, int height, int imgWidth,
+ int imgHeight);
+static char * MenuButtonTextVarProc(ClientData clientData,
+ Tcl_Interp *interp, const char *name1,
+ const char *name2, int flags);
+static int MenuButtonWidgetObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int ConfigureMenuButton(Tcl_Interp *interp,
+ TkMenuButton *mbPtr, int objc,
+ Tcl_Obj *const objv[]);
+static void DestroyMenuButton(char *memPtr);
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_MenubuttonObjCmd --
+ *
+ * This function is invoked to process the "button", "label",
+ * "radiobutton", and "checkbutton" Tcl commands. See the user
+ * documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_MenubuttonObjCmd(
+ ClientData clientData, /* NULL. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ register TkMenuButton *mbPtr;
+ Tk_OptionTable optionTable;
+ Tk_Window tkwin;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Create the new window.
+ */
+
+ tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),
+ Tcl_GetString(objv[1]), NULL);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Create the option table for this widget class. If it has already been
+ * created, the cached pointer will be returned.
+ */
+
+ optionTable = Tk_CreateOptionTable(interp, optionSpecs);
+
+ Tk_SetClass(tkwin, "Menubutton");
+ mbPtr = TkpCreateMenuButton(tkwin);
+
+ Tk_SetClassProcs(tkwin, &menubuttonClass, mbPtr);
+
+ /*
+ * Initialize the data structure for the button.
+ */
+
+ mbPtr->tkwin = tkwin;
+ mbPtr->display = Tk_Display(tkwin);
+ mbPtr->interp = interp;
+ mbPtr->widgetCmd = Tcl_CreateObjCommand(interp,
+ Tk_PathName(mbPtr->tkwin), MenuButtonWidgetObjCmd, mbPtr,
+ MenuButtonCmdDeletedProc);
+ mbPtr->optionTable = optionTable;
+ mbPtr->menuName = NULL;
+ mbPtr->text = NULL;
+ mbPtr->underline = -1;
+ mbPtr->textVarName = NULL;
+ mbPtr->bitmap = None;
+ mbPtr->imageString = NULL;
+ mbPtr->image = NULL;
+ mbPtr->state = STATE_NORMAL;
+ mbPtr->normalBorder = NULL;
+ mbPtr->activeBorder = NULL;
+ mbPtr->borderWidth = 0;
+ mbPtr->relief = TK_RELIEF_FLAT;
+ mbPtr->highlightWidth = 0;
+ mbPtr->highlightBgColorPtr = NULL;
+ mbPtr->highlightColorPtr = NULL;
+ mbPtr->inset = 0;
+ mbPtr->tkfont = NULL;
+ mbPtr->normalFg = NULL;
+ mbPtr->activeFg = NULL;
+ mbPtr->disabledFg = NULL;
+ mbPtr->normalTextGC = NULL;
+ mbPtr->activeTextGC = NULL;
+ mbPtr->gray = None;
+ mbPtr->disabledGC = NULL;
+ mbPtr->stippleGC = NULL;
+ mbPtr->leftBearing = 0;
+ mbPtr->rightBearing = 0;
+ mbPtr->widthString = NULL;
+ mbPtr->heightString = NULL;
+ mbPtr->width = 0;
+ mbPtr->width = 0;
+ mbPtr->wrapLength = 0;
+ mbPtr->padX = 0;
+ mbPtr->padY = 0;
+ mbPtr->anchor = TK_ANCHOR_CENTER;
+ mbPtr->justify = TK_JUSTIFY_CENTER;
+ mbPtr->textLayout = NULL;
+ mbPtr->indicatorOn = 0;
+ mbPtr->indicatorWidth = 0;
+ mbPtr->indicatorHeight = 0;
+ mbPtr->direction = DIRECTION_FLUSH;
+ mbPtr->cursor = NULL;
+ mbPtr->takeFocus = NULL;
+ mbPtr->flags = 0;
+
+ Tk_CreateEventHandler(mbPtr->tkwin,
+ ExposureMask|StructureNotifyMask|FocusChangeMask,
+ MenuButtonEventProc, mbPtr);
+
+ if (Tk_InitOptions(interp, (char *) mbPtr, optionTable, tkwin) != TCL_OK) {
+ Tk_DestroyWindow(mbPtr->tkwin);
+ return TCL_ERROR;
+ }
+
+ if (ConfigureMenuButton(interp, mbPtr, objc-2, objv+2) != TCL_OK) {
+ Tk_DestroyWindow(mbPtr->tkwin);
+ return TCL_ERROR;
+ }
+
+ Tcl_SetObjResult(interp, TkNewWindowObj(mbPtr->tkwin));
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * MenuButtonWidgetObjCmd --
+ *
+ * This function is invoked to process the Tcl command that corresponds
+ * to a widget managed by this module. See the user documentation for
+ * details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+MenuButtonWidgetObjCmd(
+ ClientData clientData, /* Information about button widget. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ register TkMenuButton *mbPtr = clientData;
+ int result, index;
+ Tcl_Obj *objPtr;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ result = Tcl_GetIndexFromObjStruct(interp, objv[1], commandNames,
+ sizeof(char *), "option", 0, &index);
+ if (result != TCL_OK) {
+ return result;
+ }
+ Tcl_Preserve(mbPtr);
+
+ switch (index) {
+ case COMMAND_CGET:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "cget option");
+ goto error;
+ }
+
+ objPtr = Tk_GetOptionValue(interp, (char *) mbPtr,
+ mbPtr->optionTable, objv[2], mbPtr->tkwin);
+ if (objPtr == NULL) {
+ goto error;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ break;
+
+ case COMMAND_CONFIGURE:
+ if (objc <= 3) {
+ objPtr = Tk_GetOptionInfo(interp, (char *) mbPtr,
+ mbPtr->optionTable, (objc == 3) ? objv[2] : NULL,
+ mbPtr->tkwin);
+ if (objPtr == NULL) {
+ goto error;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ } else {
+ result = ConfigureMenuButton(interp, mbPtr, objc-2, objv+2);
+ }
+ break;
+ }
+ Tcl_Release(mbPtr);
+ return result;
+
+ error:
+ Tcl_Release(mbPtr);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyMenuButton --
+ *
+ * This function is invoked to recycle all of the resources associated
+ * with a menubutton widget. It is invoked as a when-idle handler in
+ * order to make sure that there is no other use of the menubutton
+ * pending at the time of the deletion.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Everything associated with the widget is freed up.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DestroyMenuButton(
+ char *memPtr) /* Info about button widget. */
+{
+ register TkMenuButton *mbPtr = (TkMenuButton *) memPtr;
+ TkpDestroyMenuButton(mbPtr);
+
+ if (mbPtr->flags & REDRAW_PENDING) {
+ Tcl_CancelIdleCall(TkpDisplayMenuButton, mbPtr);
+ }
+
+ /*
+ * Free up all the stuff that requires special handling, then let
+ * Tk_FreeOptions handle all the standard option-related stuff.
+ */
+
+ Tcl_DeleteCommandFromToken(mbPtr->interp, mbPtr->widgetCmd);
+ if (mbPtr->textVarName != NULL) {
+ Tcl_UntraceVar2(mbPtr->interp, mbPtr->textVarName, NULL,
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ MenuButtonTextVarProc, mbPtr);
+ }
+ if (mbPtr->image != NULL) {
+ Tk_FreeImage(mbPtr->image);
+ }
+ if (mbPtr->normalTextGC != NULL) {
+ Tk_FreeGC(mbPtr->display, mbPtr->normalTextGC);
+ }
+ if (mbPtr->activeTextGC != NULL) {
+ Tk_FreeGC(mbPtr->display, mbPtr->activeTextGC);
+ }
+ if (mbPtr->disabledGC != NULL) {
+ Tk_FreeGC(mbPtr->display, mbPtr->disabledGC);
+ }
+ if (mbPtr->stippleGC != NULL) {
+ Tk_FreeGC(mbPtr->display, mbPtr->stippleGC);
+ }
+ if (mbPtr->gray != None) {
+ Tk_FreeBitmap(mbPtr->display, mbPtr->gray);
+ }
+ if (mbPtr->textLayout != NULL) {
+ Tk_FreeTextLayout(mbPtr->textLayout);
+ }
+ Tk_FreeConfigOptions((char *) mbPtr, mbPtr->optionTable, mbPtr->tkwin);
+ mbPtr->tkwin = NULL;
+ Tcl_EventuallyFree(mbPtr, TCL_DYNAMIC);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConfigureMenuButton --
+ *
+ * This function is called to process an argv/argc list, plus the Tk
+ * option database, in order to configure (or reconfigure) a menubutton
+ * widget.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If TCL_ERROR is returned,
+ * then the interp's result contains an error message.
+ *
+ * Side effects:
+ * Configuration information, such as text string, colors, font, etc. get
+ * set for mbPtr; old resources get freed, if there were any. The
+ * menubutton is redisplayed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ConfigureMenuButton(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ register TkMenuButton *mbPtr,
+ /* Information about widget; may or may not
+ * already have values for some fields. */
+ int objc, /* Number of valid entries in objv. */
+ Tcl_Obj *const objv[]) /* Arguments. */
+{
+ Tk_SavedOptions savedOptions;
+ Tcl_Obj *errorResult = NULL;
+ int error;
+ Tk_Image image;
+
+ /*
+ * Eliminate any existing trace on variables monitored by the menubutton.
+ */
+
+ if (mbPtr->textVarName != NULL) {
+ Tcl_UntraceVar2(interp, mbPtr->textVarName, NULL,
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ MenuButtonTextVarProc, mbPtr);
+ }
+
+ /*
+ * The following loop is potentially executed twice. During the first pass
+ * configuration options get set to their new values. If there is an error
+ * in this pass, we execute a second pass to restore all the options to
+ * their previous values.
+ */
+
+ for (error = 0; error <= 1; error++) {
+ if (!error) {
+ /*
+ * First pass: set options to new values.
+ */
+
+ if (Tk_SetOptions(interp, (char *) mbPtr,
+ mbPtr->optionTable, objc, objv,
+ mbPtr->tkwin, &savedOptions, NULL) != TCL_OK) {
+ continue;
+ }
+ } else {
+ /*
+ * Second pass: restore options to old values.
+ */
+
+ errorResult = Tcl_GetObjResult(interp);
+ Tcl_IncrRefCount(errorResult);
+ Tk_RestoreSavedOptions(&savedOptions);
+ }
+
+ /*
+ * A few options need special processing, such as setting the
+ * background from a 3-D border, or filling in complicated defaults
+ * that couldn't be specified to Tk_SetOptions.
+ */
+
+ if ((mbPtr->state == STATE_ACTIVE)
+ && !Tk_StrictMotif(mbPtr->tkwin)) {
+ Tk_SetBackgroundFromBorder(mbPtr->tkwin, mbPtr->activeBorder);
+ } else {
+ Tk_SetBackgroundFromBorder(mbPtr->tkwin, mbPtr->normalBorder);
+ }
+
+ if (mbPtr->highlightWidth < 0) {
+ mbPtr->highlightWidth = 0;
+ }
+
+ if (mbPtr->padX < 0) {
+ mbPtr->padX = 0;
+ }
+ if (mbPtr->padY < 0) {
+ mbPtr->padY = 0;
+ }
+
+ /*
+ * Get the image for the widget, if there is one. Allocate the new
+ * image before freeing the old one, so that the reference count
+ * doesn't go to zero and cause image data to be discarded.
+ */
+
+ if (mbPtr->imageString != NULL) {
+ image = Tk_GetImage(mbPtr->interp, mbPtr->tkwin,
+ mbPtr->imageString, MenuButtonImageProc, mbPtr);
+ if (image == NULL) {
+ return TCL_ERROR;
+ }
+ } else {
+ image = NULL;
+ }
+ if (mbPtr->image != NULL) {
+ Tk_FreeImage(mbPtr->image);
+ }
+ mbPtr->image = image;
+
+ /*
+ * Recompute the geometry for the button.
+ */
+
+ if ((mbPtr->bitmap != None) || (mbPtr->image != NULL)) {
+ if (Tk_GetPixels(interp, mbPtr->tkwin, mbPtr->widthString,
+ &mbPtr->width) != TCL_OK) {
+ widthError:
+ Tcl_AddErrorInfo(interp, "\n (processing -width option)");
+ continue;
+ }
+ if (Tk_GetPixels(interp, mbPtr->tkwin, mbPtr->heightString,
+ &mbPtr->height) != TCL_OK) {
+ heightError:
+ Tcl_AddErrorInfo(interp, "\n (processing -height option)");
+ continue;
+ }
+ } else {
+ if (Tcl_GetInt(interp, mbPtr->widthString, &mbPtr->width)
+ != TCL_OK) {
+ goto widthError;
+ }
+ if (Tcl_GetInt(interp, mbPtr->heightString, &mbPtr->height)
+ != TCL_OK) {
+ goto heightError;
+ }
+ }
+ break;
+ }
+
+ if (!error) {
+ Tk_FreeSavedOptions(&savedOptions);
+ }
+
+ if (mbPtr->textVarName != NULL) {
+ /*
+ * If no image or -compound is used, display the value of a variable.
+ * Set up a trace to watch for any changes in it, create the variable
+ * if it doesn't exist, and fetch its current value.
+ */
+ const char *value;
+
+ value = Tcl_GetVar2(interp, mbPtr->textVarName, NULL, TCL_GLOBAL_ONLY);
+ if (value == NULL) {
+ Tcl_SetVar2(interp, mbPtr->textVarName, NULL, mbPtr->text,
+ TCL_GLOBAL_ONLY);
+ } else {
+ if (mbPtr->text != NULL) {
+ ckfree(mbPtr->text);
+ }
+ mbPtr->text = ckalloc(strlen(value) + 1);
+ strcpy(mbPtr->text, value);
+ }
+ Tcl_TraceVar2(interp, mbPtr->textVarName, NULL,
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ MenuButtonTextVarProc, mbPtr);
+ }
+
+ TkMenuButtonWorldChanged(mbPtr);
+ if (error) {
+ Tcl_SetObjResult(interp, errorResult);
+ Tcl_DecrRefCount(errorResult);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkMenuButtonWorldChanged --
+ *
+ * This function is called when the world has changed in some way and the
+ * widget needs to recompute all its graphics contexts and determine its
+ * new geometry.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * TkMenuButton will be relayed out and redisplayed.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+TkMenuButtonWorldChanged(
+ ClientData instanceData) /* Information about widget. */
+{
+ XGCValues gcValues;
+ GC gc;
+ unsigned long mask;
+ TkMenuButton *mbPtr = instanceData;
+
+ gcValues.font = Tk_FontId(mbPtr->tkfont);
+ gcValues.foreground = mbPtr->normalFg->pixel;
+ gcValues.background = Tk_3DBorderColor(mbPtr->normalBorder)->pixel;
+
+ /*
+ * Note: GraphicsExpose events are disabled in GC's because they're used
+ * to copy stuff from an off-screen pixmap onto the screen (we know that
+ * there's no problem with obscured areas).
+ */
+
+ gcValues.graphics_exposures = False;
+ mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
+ gc = Tk_GetGC(mbPtr->tkwin, mask, &gcValues);
+ if (mbPtr->normalTextGC != NULL) {
+ Tk_FreeGC(mbPtr->display, mbPtr->normalTextGC);
+ }
+ mbPtr->normalTextGC = gc;
+
+ gcValues.foreground = mbPtr->activeFg->pixel;
+ gcValues.background = Tk_3DBorderColor(mbPtr->activeBorder)->pixel;
+ mask = GCForeground | GCBackground | GCFont;
+ gc = Tk_GetGC(mbPtr->tkwin, mask, &gcValues);
+ if (mbPtr->activeTextGC != NULL) {
+ Tk_FreeGC(mbPtr->display, mbPtr->activeTextGC);
+ }
+ mbPtr->activeTextGC = gc;
+
+ gcValues.background = Tk_3DBorderColor(mbPtr->normalBorder)->pixel;
+
+ /*
+ * Create the GC that can be used for stippling
+ */
+
+ if (mbPtr->stippleGC == NULL) {
+ gcValues.foreground = gcValues.background;
+ mask = GCForeground;
+ if (mbPtr->gray == None) {
+ mbPtr->gray = Tk_GetBitmap(NULL, mbPtr->tkwin, "gray50");
+ }
+ if (mbPtr->gray != None) {
+ gcValues.fill_style = FillStippled;
+ gcValues.stipple = mbPtr->gray;
+ mask |= GCFillStyle | GCStipple;
+ }
+ mbPtr->stippleGC = Tk_GetGC(mbPtr->tkwin, mask, &gcValues);
+ }
+
+ /*
+ * Allocate the disabled graphics context, for drawing text in its
+ * disabled state.
+ */
+
+ mask = GCForeground | GCBackground | GCFont;
+ if (mbPtr->disabledFg != NULL) {
+ gcValues.foreground = mbPtr->disabledFg->pixel;
+ } else {
+ gcValues.foreground = gcValues.background;
+ }
+ gc = Tk_GetGC(mbPtr->tkwin, mask, &gcValues);
+ if (mbPtr->disabledGC != NULL) {
+ Tk_FreeGC(mbPtr->display, mbPtr->disabledGC);
+ }
+ mbPtr->disabledGC = gc;
+
+ TkpComputeMenuButtonGeometry(mbPtr);
+
+ /*
+ * Lastly, arrange for the button to be redisplayed.
+ */
+
+ if (Tk_IsMapped(mbPtr->tkwin) && !(mbPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(TkpDisplayMenuButton, mbPtr);
+ mbPtr->flags |= REDRAW_PENDING;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * MenuButtonEventProc --
+ *
+ * This function is invoked by the Tk dispatcher for various events on
+ * buttons.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * When the window gets deleted, internal structures get cleaned up.
+ * When it gets exposed, it is redisplayed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+MenuButtonEventProc(
+ ClientData clientData, /* Information about window. */
+ XEvent *eventPtr) /* Information about event. */
+{
+ TkMenuButton *mbPtr = clientData;
+
+ if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {
+ goto redraw;
+ } else if (eventPtr->type == ConfigureNotify) {
+ /*
+ * Must redraw after size changes, since layout could have changed and
+ * borders will need to be redrawn.
+ */
+
+ goto redraw;
+ } else if (eventPtr->type == DestroyNotify) {
+ DestroyMenuButton((char *) mbPtr);
+ } else if (eventPtr->type == FocusIn) {
+ if (eventPtr->xfocus.detail != NotifyInferior) {
+ mbPtr->flags |= GOT_FOCUS;
+ if (mbPtr->highlightWidth > 0) {
+ goto redraw;
+ }
+ }
+ } else if (eventPtr->type == FocusOut) {
+ if (eventPtr->xfocus.detail != NotifyInferior) {
+ mbPtr->flags &= ~GOT_FOCUS;
+ if (mbPtr->highlightWidth > 0) {
+ goto redraw;
+ }
+ }
+ }
+ return;
+
+ redraw:
+ if ((mbPtr->tkwin != NULL) && !(mbPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(TkpDisplayMenuButton, mbPtr);
+ mbPtr->flags |= REDRAW_PENDING;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MenuButtonCmdDeletedProc --
+ *
+ * This function is invoked when a widget command is deleted. If the
+ * widget isn't already in the process of being destroyed, this command
+ * destroys it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The widget is destroyed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+MenuButtonCmdDeletedProc(
+ ClientData clientData) /* Pointer to widget record for widget. */
+{
+ TkMenuButton *mbPtr = clientData;
+ Tk_Window tkwin = mbPtr->tkwin;
+
+ /*
+ * This function could be invoked either because the window was destroyed
+ * and the command was then deleted (in which case tkwin is NULL) or
+ * because the command was deleted, and then this function destroys the
+ * widget.
+ */
+
+ if (tkwin != NULL) {
+ Tk_DestroyWindow(tkwin);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * MenuButtonTextVarProc --
+ *
+ * This function is invoked when someone changes the variable whose
+ * contents are to be displayed in a menu button.
+ *
+ * Results:
+ * NULL is always returned.
+ *
+ * Side effects:
+ * The text displayed in the menu button will change to match the
+ * variable.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static char *
+MenuButtonTextVarProc(
+ ClientData clientData, /* Information about button. */
+ Tcl_Interp *interp, /* Interpreter containing variable. */
+ const char *name1, /* Name of variable. */
+ const char *name2, /* Second part of variable name. */
+ int flags) /* Information about what happened. */
+{
+ register TkMenuButton *mbPtr = clientData;
+ const char *value;
+ unsigned len;
+
+ /*
+ * If the variable is unset, then immediately recreate it unless the whole
+ * interpreter is going away.
+ */
+
+ if (flags & TCL_TRACE_UNSETS) {
+ if (!Tcl_InterpDeleted(interp) && mbPtr->textVarName) {
+ ClientData probe = NULL;
+
+ do {
+ probe = Tcl_VarTraceInfo(interp,
+ mbPtr->textVarName,
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ MenuButtonTextVarProc, probe);
+ if (probe == (ClientData)mbPtr) {
+ break;
+ }
+ } while (probe);
+ if (probe) {
+ /*
+ * We were able to fetch the unset trace for our
+ * textVarName, which means it is not unset and not
+ * the cause of this unset trace. Instead some outdated
+ * former variable must be, and we should ignore it.
+ */
+ return NULL;
+ }
+ Tcl_SetVar2(interp, mbPtr->textVarName, NULL, mbPtr->text,
+ TCL_GLOBAL_ONLY);
+ Tcl_TraceVar2(interp, mbPtr->textVarName, NULL,
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ MenuButtonTextVarProc, clientData);
+ }
+ return NULL;
+ }
+
+ value = Tcl_GetVar2(interp, mbPtr->textVarName, NULL, TCL_GLOBAL_ONLY);
+ if (value == NULL) {
+ value = "";
+ }
+ if (mbPtr->text != NULL) {
+ ckfree(mbPtr->text);
+ }
+ len = 1 + (unsigned) strlen(value);
+ mbPtr->text = ckalloc(len);
+ memcpy(mbPtr->text, value, len);
+ TkpComputeMenuButtonGeometry(mbPtr);
+
+ if ((mbPtr->tkwin != NULL) && Tk_IsMapped(mbPtr->tkwin)
+ && !(mbPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(TkpDisplayMenuButton, mbPtr);
+ mbPtr->flags |= REDRAW_PENDING;
+ }
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MenuButtonImageProc --
+ *
+ * This function is invoked by the image code whenever the manager for an
+ * image does something that affects the size of contents of an image
+ * displayed in a button.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Arranges for the button to get redisplayed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+MenuButtonImageProc(
+ ClientData clientData, /* Pointer to widget record. */
+ int x, int y, /* Upper left pixel (within image) that must
+ * be redisplayed. */
+ int width, int height, /* Dimensions of area to redisplay (may be <=
+ * 0). */
+ int imgWidth, int imgHeight)/* New dimensions of image. */
+{
+ register TkMenuButton *mbPtr = clientData;
+
+ if (mbPtr->tkwin != NULL) {
+ TkpComputeMenuButtonGeometry(mbPtr);
+ if (Tk_IsMapped(mbPtr->tkwin) && !(mbPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(TkpDisplayMenuButton, mbPtr);
+ mbPtr->flags |= REDRAW_PENDING;
+ }
+ }
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkMenubutton.h b/tk8.6/generic/tkMenubutton.h
new file mode 100644
index 0000000..1dbacb3
--- /dev/null
+++ b/tk8.6/generic/tkMenubutton.h
@@ -0,0 +1,216 @@
+/*
+ * tkMenubutton.h --
+ *
+ * Declarations of types and functions used to implement the menubutton
+ * widget.
+ *
+ * Copyright (c) 1996-1997 by Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef _TKMENUBUTTON
+#define _TKMENUBUTTON
+
+#ifndef _TKINT
+#include "tkInt.h"
+#endif
+
+#ifndef _TKMENU
+#include "tkMenu.h"
+#endif
+
+/*
+ * Legal values for the "orient" field of TkMenubutton records.
+ */
+
+enum direction {
+ DIRECTION_ABOVE, DIRECTION_BELOW, DIRECTION_FLUSH,
+ DIRECTION_LEFT, DIRECTION_RIGHT
+};
+
+/*
+ * Legal values for the "state" field of TkMenubutton records.
+ */
+
+enum state {
+ STATE_ACTIVE, STATE_DISABLED, STATE_NORMAL
+};
+
+/*
+ * A data structure of the following type is kept for each widget managed by
+ * this file:
+ */
+
+typedef struct {
+ Tk_Window tkwin; /* Window that embodies the widget. NULL means
+ * that the window has been destroyed but the
+ * data structures haven't yet been cleaned
+ * up. */
+ Display *display; /* Display containing widget. Needed, among
+ * other things, so that resources can bee
+ * freed up even after tkwin has gone away. */
+ Tcl_Interp *interp; /* Interpreter associated with menubutton. */
+ Tcl_Command widgetCmd; /* Token for menubutton's widget command. */
+ Tk_OptionTable optionTable; /* Table that defines configuration options
+ * available for this widget. */
+ char *menuName; /* Name of menu associated with widget.
+ * Malloc-ed. */
+
+ /*
+ * Information about what's displayed in the menu button:
+ */
+
+ char *text; /* Text to display in button (malloc'ed) or
+ * NULL. */
+ int underline; /* Index of character to underline. */
+ char *textVarName; /* Name of variable (malloc'ed) or NULL. If
+ * non-NULL, button displays the contents of
+ * this variable. */
+ Pixmap bitmap; /* Bitmap to display or None. If not None then
+ * text and textVar and underline are
+ * ignored. */
+ char *imageString; /* Name of image to display (malloc'ed), or
+ * NULL. If non-NULL, bitmap, text, and
+ * textVarName are ignored. */
+ Tk_Image image; /* Image to display in window, or NULL if
+ * none. */
+
+ /*
+ * Information used when displaying widget:
+ */
+
+ enum state state; /* State of button for display purposes:
+ * normal, active, or disabled. */
+ Tk_3DBorder normalBorder; /* Structure used to draw 3-D border and
+ * background when window isn't active. NULL
+ * means no such border exists. */
+ Tk_3DBorder activeBorder; /* Structure used to draw 3-D border and
+ * background when window is active. NULL
+ * means no such border exists. */
+ int borderWidth; /* Width of border. */
+ int relief; /* 3-d effect: TK_RELIEF_RAISED, etc. */
+ int highlightWidth; /* Width in pixels of highlight to draw around
+ * widget when it has the focus. <= 0 means
+ * don't draw a highlight. */
+ XColor *highlightBgColorPtr;/* Color for drawing traversal highlight area
+ * when highlight is off. */
+ XColor *highlightColorPtr; /* Color for drawing traversal highlight. */
+ int inset; /* Total width of all borders, including
+ * traversal highlight and 3-D border.
+ * Indicates how much interior stuff must be
+ * offset from outside edges to leave room for
+ * borders. */
+ Tk_Font tkfont; /* Information about text font, or NULL. */
+ XColor *normalFg; /* Foreground color in normal mode. */
+ XColor *activeFg; /* Foreground color in active mode. NULL means
+ * use normalFg instead. */
+ XColor *disabledFg; /* Foreground color when disabled. NULL means
+ * use normalFg with a 50% stipple instead. */
+ GC normalTextGC; /* GC for drawing text in normal mode. */
+ GC activeTextGC; /* GC for drawing text in active mode (NULL
+ * means use normalTextGC). */
+ Pixmap gray; /* Pixmap for displaying disabled text/icon if
+ * disabledFg is NULL. */
+ GC disabledGC; /* Used to produce disabled effect for
+ * text. */
+ GC stippleGC; /* Used to produce disabled stipple effect for
+ * images when disabled. */
+ int leftBearing; /* Distance from text origin to leftmost drawn
+ * pixel (positive means to right). */
+ int rightBearing; /* Amount text sticks right from its
+ * origin. */
+ char *widthString; /* Value of -width option. Malloc'ed. */
+ char *heightString; /* Value of -height option. Malloc'ed. */
+ int width, height; /* If > 0, these specify dimensions to request
+ * for window, in characters for text and in
+ * pixels for bitmaps. In this case the actual
+ * size of the text string or bitmap is
+ * ignored in computing desired window
+ * size. */
+ int wrapLength; /* Line length (in pixels) at which to wrap
+ * onto next line. <= 0 means don't wrap
+ * except at newlines. */
+ int padX, padY; /* Extra space around text or bitmap (pixels
+ * on each side). */
+ Tk_Anchor anchor; /* Where text/bitmap should be displayed
+ * inside window region. */
+ Tk_Justify justify; /* Justification to use for multi-line
+ * text. */
+ int textWidth; /* Width needed to display text as requested,
+ * in pixels. */
+ int textHeight; /* Height needed to display text as requested,
+ * in pixels. */
+ Tk_TextLayout textLayout; /* Saved text layout information. */
+ int indicatorOn; /* Non-zero means display indicator; 0 means
+ * don't display. */
+ int indicatorHeight; /* Height of indicator in pixels. This same
+ * amount of extra space is also left on each
+ * side of the indicator. 0 if no
+ * indicator. */
+ int indicatorWidth; /* Width of indicator in pixels, including
+ * indicatorHeight in padding on each side. 0
+ * if no indicator. */
+
+ /*
+ * Miscellaneous information:
+ */
+
+ int compound; /* Value of -compound option; specifies
+ * whether the menubutton should show both an
+ * image and text, and, if so, how. */
+ enum direction direction; /* Direction for where to pop the menu. Valid
+ * directions are "above", "below", "left",
+ * "right", and "flush". "flush" means that
+ * the upper left corner of the menubutton is
+ * where the menu pops up. "above" and "below"
+ * will attempt to pop the menu compleletly
+ * above or below the menu respectively.
+ * "left" and "right" will pop the menu left
+ * or right, and the active item will be next
+ * to the button. */
+ Tk_Cursor cursor; /* Current cursor for window, or NULL. */
+ char *takeFocus; /* Value of -takefocus option; not used in the
+ * C code, but used by keyboard traversal
+ * scripts. Malloc'ed, but may be NULL. */
+ int flags; /* Various flags; see below for
+ * definitions. */
+} TkMenuButton;
+
+/*
+ * Flag bits for buttons:
+ *
+ * REDRAW_PENDING: Non-zero means a DoWhenIdle handler has
+ * already been queued to redraw this window.
+ * POSTED: Non-zero means that the menu associated with
+ * this button has been posted (typically because
+ * of an active button press).
+ * GOT_FOCUS: Non-zero means this button currently has the
+ * input focus.
+ */
+
+#define REDRAW_PENDING 1
+#define POSTED 2
+#define GOT_FOCUS 4
+
+/*
+ * The following constants define the dimensions of the cascade indicator,
+ * which is displayed if the "-indicatoron" option is true. The units for
+ * these options are 1/10 millimeters.
+ */
+
+#define INDICATOR_WIDTH 40
+#define INDICATOR_HEIGHT 17
+
+/*
+ * Declaration of procedures used in the implementation of the button widget.
+ */
+
+MODULE_SCOPE void TkpComputeMenuButtonGeometry(TkMenuButton *mbPtr);
+MODULE_SCOPE TkMenuButton *TkpCreateMenuButton(Tk_Window tkwin);
+MODULE_SCOPE void TkpDisplayMenuButton(ClientData clientData);
+MODULE_SCOPE void TkpDestroyMenuButton(TkMenuButton *mbPtr);
+MODULE_SCOPE void TkMenuButtonWorldChanged(ClientData instanceData);
+
+#endif /* _TKMENUBUTTON */
diff --git a/tk8.6/generic/tkMessage.c b/tk8.6/generic/tkMessage.c
new file mode 100644
index 0000000..1a3c6de
--- /dev/null
+++ b/tk8.6/generic/tkMessage.c
@@ -0,0 +1,903 @@
+/*
+ * tkMessage.c --
+ *
+ * This module implements a message widgets for the Tk toolkit. A message
+ * widget displays a multi-line string in a window according to a
+ * particular aspect ratio.
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1998-2000 by Ajuba Solutions.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "default.h"
+#include "tkInt.h"
+
+/*
+ * A data structure of the following type is kept for each message widget
+ * managed by this file:
+ */
+
+typedef struct {
+ Tk_Window tkwin; /* Window that embodies the message. NULL
+ * means that the window has been destroyed
+ * but the data structures haven't yet been
+ * cleaned up.*/
+ Tk_OptionTable optionTable; /* Table that defines options available for
+ * this widget. */
+ Display *display; /* Display containing widget. Used, among
+ * other things, so that resources can be
+ * freed even after tkwin has gone away. */
+ Tcl_Interp *interp; /* Interpreter associated with message. */
+ Tcl_Command widgetCmd; /* Token for message's widget command. */
+
+ /*
+ * Information used when displaying widget:
+ */
+
+ char *string; /* String displayed in message. */
+ int numChars; /* Number of characters in string, not
+ * including terminating NULL. */
+ char *textVarName; /* Name of variable (malloc'ed) or NULL.
+ * If non-NULL, message displays the contents
+ * of this variable. */
+ Tk_3DBorder border; /* Structure used to draw 3-D border and
+ * background. NULL means a border hasn't been
+ * created yet. */
+ int borderWidth; /* Width of border. */
+ int relief; /* 3-D effect: TK_RELIEF_RAISED, etc. */
+ int highlightWidth; /* Width in pixels of highlight to draw
+ * around widget when it has the focus.
+ * <= 0 means don't draw a highlight. */
+ XColor *highlightBgColorPtr;
+ /* Color for drawing traversal highlight
+ * area when highlight is off. */
+ XColor *highlightColorPtr; /* Color for drawing traversal highlight. */
+ Tk_Font tkfont; /* Information about text font, or NULL. */
+ XColor *fgColorPtr; /* Foreground color in normal mode. */
+ Tcl_Obj *padXPtr, *padYPtr; /* Tcl_Obj rep's of padX, padY values. */
+ int padX, padY; /* User-requested extra space around text. */
+ int width; /* User-requested width, in pixels. 0 means
+ * compute width using aspect ratio below. */
+ int aspect; /* Desired aspect ratio for window
+ * (100*width/height). */
+ int msgWidth; /* Width in pixels needed to display
+ * message. */
+ int msgHeight; /* Height in pixels needed to display
+ * message. */
+ Tk_Anchor anchor; /* Where to position text within window region
+ * if window is larger or smaller than
+ * needed. */
+ Tk_Justify justify; /* Justification for text. */
+
+ GC textGC; /* GC for drawing text in normal mode. */
+ Tk_TextLayout textLayout; /* Saved layout information. */
+
+ /*
+ * Miscellaneous information:
+ */
+
+ Tk_Cursor cursor; /* Current cursor for window, or None. */
+ char *takeFocus; /* Value of -takefocus option; not used in the
+ * C code, but used by keyboard traversal
+ * scripts. Malloc'ed, but may be NULL. */
+ int flags; /* Various flags; see below for
+ * definitions. */
+} Message;
+
+/*
+ * Flag bits for messages:
+ *
+ * REDRAW_PENDING: Non-zero means a DoWhenIdle handler
+ * has already been queued to redraw
+ * this window.
+ * GOT_FOCUS: Non-zero means this button currently
+ * has the input focus.
+ * MESSAGE_DELETED: The message has been effectively deleted.
+ */
+
+#define REDRAW_PENDING 1
+#define GOT_FOCUS 4
+#define MESSAGE_DELETED 8
+
+/*
+ * Information used for argv parsing.
+ */
+
+static const Tk_OptionSpec optionSpecs[] = {
+ {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", DEF_MESSAGE_ANCHOR,
+ -1, Tk_Offset(Message, anchor), 0, 0, 0},
+ {TK_OPTION_INT, "-aspect", "aspect", "Aspect", DEF_MESSAGE_ASPECT,
+ -1, Tk_Offset(Message, aspect), 0, 0, 0},
+ {TK_OPTION_BORDER, "-background", "background", "Background",
+ DEF_MESSAGE_BG_COLOR, -1, Tk_Offset(Message, border), 0,
+ DEF_MESSAGE_BG_MONO, 0},
+ {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL,
+ 0, -1, 0, "-borderwidth", 0},
+ {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL,
+ 0, -1, 0, "-background", 0},
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ DEF_MESSAGE_BORDER_WIDTH, -1,
+ Tk_Offset(Message, borderWidth), 0, 0, 0},
+ {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
+ DEF_MESSAGE_CURSOR, -1, Tk_Offset(Message, cursor),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_SYNONYM, "-fg", NULL, NULL, NULL,
+ 0, -1, 0, "-foreground", 0},
+ {TK_OPTION_FONT, "-font", "font", "Font",
+ DEF_MESSAGE_FONT, -1, Tk_Offset(Message, tkfont), 0, 0, 0},
+ {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
+ DEF_MESSAGE_FG, -1, Tk_Offset(Message, fgColorPtr), 0, 0, 0},
+ {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground",
+ "HighlightBackground", DEF_MESSAGE_HIGHLIGHT_BG, -1,
+ Tk_Offset(Message, highlightBgColorPtr), 0, 0, 0},
+ {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
+ DEF_MESSAGE_HIGHLIGHT, -1, Tk_Offset(Message, highlightColorPtr),
+ 0, 0, 0},
+ {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
+ "HighlightThickness", DEF_MESSAGE_HIGHLIGHT_WIDTH, -1,
+ Tk_Offset(Message, highlightWidth), 0, 0, 0},
+ {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
+ DEF_MESSAGE_JUSTIFY, -1, Tk_Offset(Message, justify), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
+ DEF_MESSAGE_PADX, Tk_Offset(Message, padXPtr),
+ Tk_Offset(Message, padX), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
+ DEF_MESSAGE_PADY, Tk_Offset(Message, padYPtr),
+ Tk_Offset(Message, padY), 0, 0, 0},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ DEF_MESSAGE_RELIEF, -1, Tk_Offset(Message, relief), 0, 0, 0},
+ {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
+ DEF_MESSAGE_TAKE_FOCUS, -1, Tk_Offset(Message, takeFocus),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-text", "text", "Text",
+ DEF_MESSAGE_TEXT, -1, Tk_Offset(Message, string), 0, 0, 0},
+ {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
+ DEF_MESSAGE_TEXT_VARIABLE, -1, Tk_Offset(Message, textVarName),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-width", "width", "Width",
+ DEF_MESSAGE_WIDTH, -1, Tk_Offset(Message, width), 0, 0 ,0},
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}
+};
+
+/*
+ * Forward declarations for functions defined later in this file:
+ */
+
+static void MessageCmdDeletedProc(ClientData clientData);
+static void MessageEventProc(ClientData clientData,
+ XEvent *eventPtr);
+static char * MessageTextVarProc(ClientData clientData,
+ Tcl_Interp *interp, const char *name1,
+ const char *name2, int flags);
+static int MessageWidgetObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static void MessageWorldChanged(ClientData instanceData);
+static void ComputeMessageGeometry(Message *msgPtr);
+static int ConfigureMessage(Tcl_Interp *interp, Message *msgPtr,
+ int objc, Tcl_Obj *const objv[], int flags);
+static void DestroyMessage(char *memPtr);
+static void DisplayMessage(ClientData clientData);
+
+/*
+ * The structure below defines message class behavior by means of functions
+ * that can be invoked from generic window code.
+ */
+
+static const Tk_ClassProcs messageClass = {
+ sizeof(Tk_ClassProcs), /* size */
+ MessageWorldChanged, /* worldChangedProc */
+ NULL, /* createProc */
+ NULL /* modalProc */
+};
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_MessageObjCmd --
+ *
+ * This function is invoked to process the "message" 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_MessageObjCmd(
+ ClientData clientData, /* NULL. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument strings. */
+{
+ register Message *msgPtr;
+ Tk_OptionTable optionTable;
+ Tk_Window tkwin;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?");
+ return TCL_ERROR;
+ }
+
+ tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),
+ Tcl_GetString(objv[1]), NULL);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Create the option table for this widget class. If it has already been
+ * created, the cached pointer will be returned.
+ */
+
+ optionTable = Tk_CreateOptionTable(interp, optionSpecs);
+
+ msgPtr = ckalloc(sizeof(Message));
+ memset(msgPtr, 0, (size_t) sizeof(Message));
+
+ /*
+ * Set values for those fields that don't take a 0 or NULL value.
+ */
+
+ msgPtr->tkwin = tkwin;
+ msgPtr->display = Tk_Display(tkwin);
+ msgPtr->interp = interp;
+ msgPtr->widgetCmd = Tcl_CreateObjCommand(interp,
+ Tk_PathName(msgPtr->tkwin), MessageWidgetObjCmd, msgPtr,
+ MessageCmdDeletedProc);
+ msgPtr->optionTable = optionTable;
+ msgPtr->relief = TK_RELIEF_FLAT;
+ msgPtr->textGC = NULL;
+ msgPtr->anchor = TK_ANCHOR_CENTER;
+ msgPtr->aspect = 150;
+ msgPtr->justify = TK_JUSTIFY_LEFT;
+ msgPtr->cursor = NULL;
+
+ Tk_SetClass(msgPtr->tkwin, "Message");
+ Tk_SetClassProcs(msgPtr->tkwin, &messageClass, msgPtr);
+ Tk_CreateEventHandler(msgPtr->tkwin,
+ ExposureMask|StructureNotifyMask|FocusChangeMask,
+ MessageEventProc, msgPtr);
+ if (Tk_InitOptions(interp, (char *)msgPtr, optionTable, tkwin) != TCL_OK) {
+ Tk_DestroyWindow(msgPtr->tkwin);
+ return TCL_ERROR;
+ }
+
+ if (ConfigureMessage(interp, msgPtr, objc-2, objv+2, 0) != TCL_OK) {
+ Tk_DestroyWindow(msgPtr->tkwin);
+ return TCL_ERROR;
+ }
+
+ Tcl_SetObjResult(interp, TkNewWindowObj(msgPtr->tkwin));
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * MessageWidgetObjCmd --
+ *
+ * This function is invoked to process the Tcl command that corresponds
+ * to a widget managed by this module. See the user documentation for
+ * details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+MessageWidgetObjCmd(
+ ClientData clientData, /* Information about message widget. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument strings. */
+{
+ register Message *msgPtr = clientData;
+ static const char *const optionStrings[] = { "cget", "configure", NULL };
+ enum options { MESSAGE_CGET, MESSAGE_CONFIGURE };
+ int index;
+ int result = TCL_OK;
+ Tcl_Obj *objPtr;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings,
+ sizeof(char *), "option", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ Tcl_Preserve(msgPtr);
+
+ switch ((enum options) index) {
+ case MESSAGE_CGET:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option");
+ result = TCL_ERROR;
+ } else {
+ objPtr = Tk_GetOptionValue(interp, (char *) msgPtr,
+ msgPtr->optionTable, objv[2], msgPtr->tkwin);
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ } else {
+ Tcl_SetObjResult(interp, objPtr);
+ result = TCL_OK;
+ }
+ }
+ break;
+ case MESSAGE_CONFIGURE:
+ if (objc <= 3) {
+ objPtr = Tk_GetOptionInfo(interp, (char *) msgPtr,
+ msgPtr->optionTable, (objc == 3) ? objv[2] : NULL,
+ msgPtr->tkwin);
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ } else {
+ Tcl_SetObjResult(interp, objPtr);
+ result = TCL_OK;
+ }
+ } else {
+ result = ConfigureMessage(interp, msgPtr, objc-2, objv+2, 0);
+ }
+ break;
+ }
+
+ Tcl_Release(msgPtr);
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyMessage --
+ *
+ * This function is invoked by Tcl_EventuallyFree or Tcl_Release to clean
+ * up the internal structure of a message at a safe time (when no-one is
+ * using it anymore).
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Everything associated with the message is freed up.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DestroyMessage(
+ char *memPtr) /* Info about message widget. */
+{
+ register Message *msgPtr = (Message *) memPtr;
+
+ msgPtr->flags |= MESSAGE_DELETED;
+
+ Tcl_DeleteCommandFromToken(msgPtr->interp, msgPtr->widgetCmd);
+ if (msgPtr->flags & REDRAW_PENDING) {
+ Tcl_CancelIdleCall(DisplayMessage, msgPtr);
+ }
+
+ /*
+ * Free up all the stuff that requires special handling, then let
+ * Tk_FreeConfigOptions handle all the standard option-related stuff.
+ */
+
+ if (msgPtr->textGC != NULL) {
+ Tk_FreeGC(msgPtr->display, msgPtr->textGC);
+ }
+ if (msgPtr->textLayout != NULL) {
+ Tk_FreeTextLayout(msgPtr->textLayout);
+ }
+ if (msgPtr->textVarName != NULL) {
+ Tcl_UntraceVar2(msgPtr->interp, msgPtr->textVarName, NULL,
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ MessageTextVarProc, msgPtr);
+ }
+ Tk_FreeConfigOptions((char *) msgPtr, msgPtr->optionTable, msgPtr->tkwin);
+ msgPtr->tkwin = NULL;
+ ckfree(msgPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConfigureMessage --
+ *
+ * This function is called to process an argv/argc list, plus the Tk
+ * option database, in order to configure (or reconfigure) a message
+ * widget.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If TCL_ERROR is returned,
+ * then the interp's result contains an error message.
+ *
+ * Side effects:
+ * Configuration information, such as text string, colors, font, etc. get
+ * set for msgPtr; old resources get freed, if there were any.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ConfigureMessage(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ register Message *msgPtr, /* Information about widget; may or may not
+ * already have values for some fields. */
+ int objc, /* Number of valid entries in argv. */
+ Tcl_Obj *const objv[], /* Arguments. */
+ int flags) /* Flags to pass to Tk_ConfigureWidget. */
+{
+ Tk_SavedOptions savedOptions;
+
+ /*
+ * Eliminate any existing trace on a variable monitored by the message.
+ */
+
+ if (msgPtr->textVarName != NULL) {
+ Tcl_UntraceVar2(interp, msgPtr->textVarName, NULL,
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ MessageTextVarProc, msgPtr);
+ }
+
+ if (Tk_SetOptions(interp, (char *) msgPtr, msgPtr->optionTable, objc, objv,
+ msgPtr->tkwin, &savedOptions, NULL) != TCL_OK) {
+ Tk_RestoreSavedOptions(&savedOptions);
+ return TCL_ERROR;
+ }
+
+ /*
+ * If the message is to display the value of a variable, then set up a
+ * trace on the variable's value, create the variable if it doesn't exist,
+ * and fetch its current value.
+ */
+
+ if (msgPtr->textVarName != NULL) {
+ const char *value;
+
+ value = Tcl_GetVar2(interp, msgPtr->textVarName, NULL, TCL_GLOBAL_ONLY);
+ if (value == NULL) {
+ Tcl_SetVar2(interp, msgPtr->textVarName, NULL, msgPtr->string,
+ TCL_GLOBAL_ONLY);
+ } else {
+ if (msgPtr->string != NULL) {
+ ckfree(msgPtr->string);
+ }
+ msgPtr->string = strcpy(ckalloc(strlen(value) + 1), value);
+ }
+ Tcl_TraceVar2(interp, msgPtr->textVarName, NULL,
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ MessageTextVarProc, msgPtr);
+ }
+
+ /*
+ * A few other options need special processing, such as setting the
+ * background from a 3-D border or handling special defaults that couldn't
+ * be specified to Tk_ConfigureWidget.
+ */
+
+ msgPtr->numChars = Tcl_NumUtfChars(msgPtr->string, -1);
+
+ if (msgPtr->highlightWidth < 0) {
+ msgPtr->highlightWidth = 0;
+ }
+
+ Tk_FreeSavedOptions(&savedOptions);
+ MessageWorldChanged(msgPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MessageWorldChanged --
+ *
+ * This function is called when the world has changed in some way and the
+ * widget needs to recompute all its graphics contexts and determine its
+ * new geometry.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Message will be relayed out and redisplayed.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+MessageWorldChanged(
+ ClientData instanceData) /* Information about widget. */
+{
+ XGCValues gcValues;
+ GC gc = NULL;
+ Tk_FontMetrics fm;
+ Message *msgPtr = instanceData;
+
+ if (msgPtr->border != NULL) {
+ Tk_SetBackgroundFromBorder(msgPtr->tkwin, msgPtr->border);
+ }
+
+ gcValues.font = Tk_FontId(msgPtr->tkfont);
+ gcValues.foreground = msgPtr->fgColorPtr->pixel;
+ gc = Tk_GetGC(msgPtr->tkwin, GCForeground | GCFont, &gcValues);
+ if (msgPtr->textGC != NULL) {
+ Tk_FreeGC(msgPtr->display, msgPtr->textGC);
+ }
+ msgPtr->textGC = gc;
+
+ Tk_GetFontMetrics(msgPtr->tkfont, &fm);
+ if (msgPtr->padX < 0) {
+ msgPtr->padX = fm.ascent / 2;
+ }
+ if (msgPtr->padY == -1) {
+ msgPtr->padY = fm.ascent / 4;
+ }
+
+ /*
+ * Recompute the desired geometry for the window, and arrange for the
+ * window to be redisplayed.
+ */
+
+ ComputeMessageGeometry(msgPtr);
+ if ((msgPtr->tkwin != NULL) && Tk_IsMapped(msgPtr->tkwin)
+ && !(msgPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DisplayMessage, msgPtr);
+ msgPtr->flags |= REDRAW_PENDING;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ComputeMessageGeometry --
+ *
+ * Compute the desired geometry for a message window, taking into account
+ * the desired aspect ratio for the window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Tk_GeometryRequest is called to inform the geometry manager of the
+ * desired geometry for this window.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ComputeMessageGeometry(
+ register Message *msgPtr) /* Information about window. */
+{
+ int width, inc, height;
+ int thisWidth, thisHeight, maxWidth;
+ int aspect, lowerBound, upperBound, inset;
+
+ Tk_FreeTextLayout(msgPtr->textLayout);
+
+ inset = msgPtr->borderWidth + msgPtr->highlightWidth;
+
+ /*
+ * Compute acceptable bounds for the final aspect ratio.
+ */
+
+ aspect = msgPtr->aspect/10;
+ if (aspect < 5) {
+ aspect = 5;
+ }
+ lowerBound = msgPtr->aspect - aspect;
+ upperBound = msgPtr->aspect + aspect;
+
+ /*
+ * Do the computation in multiple passes: start off with a very wide
+ * window, and compute its height. Then change the width and try again.
+ * Reduce the size of the change and iterate until dimensions are found
+ * that approximate the desired aspect ratio. Or, if the user gave an
+ * explicit width then just use that.
+ */
+
+ if (msgPtr->width > 0) {
+ width = msgPtr->width;
+ inc = 0;
+ } else {
+ width = WidthOfScreen(Tk_Screen(msgPtr->tkwin))/2;
+ inc = width/2;
+ }
+
+ for ( ; ; inc /= 2) {
+ msgPtr->textLayout = Tk_ComputeTextLayout(msgPtr->tkfont,
+ msgPtr->string, msgPtr->numChars, width, msgPtr->justify,
+ 0, &thisWidth, &thisHeight);
+ maxWidth = thisWidth + 2 * (inset + msgPtr->padX);
+ height = thisHeight + 2 * (inset + msgPtr->padY);
+
+ if (inc <= 2) {
+ break;
+ }
+ aspect = (100 * maxWidth) / height;
+
+ if (aspect < lowerBound) {
+ width += inc;
+ } else if (aspect > upperBound) {
+ width -= inc;
+ } else {
+ break;
+ }
+ Tk_FreeTextLayout(msgPtr->textLayout);
+ }
+ msgPtr->msgWidth = thisWidth;
+ msgPtr->msgHeight = thisHeight;
+ Tk_GeometryRequest(msgPtr->tkwin, maxWidth, height);
+ Tk_SetInternalBorder(msgPtr->tkwin, inset);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DisplayMessage --
+ *
+ * This function redraws the contents of a message window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Information appears on the screen.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+DisplayMessage(
+ ClientData clientData) /* Information about window. */
+{
+ register Message *msgPtr = clientData;
+ register Tk_Window tkwin = msgPtr->tkwin;
+ int x, y;
+ int borderWidth = msgPtr->highlightWidth;
+
+ msgPtr->flags &= ~REDRAW_PENDING;
+ if ((msgPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
+ return;
+ }
+ if (msgPtr->border != NULL) {
+ borderWidth += msgPtr->borderWidth;
+ }
+ if (msgPtr->relief == TK_RELIEF_FLAT) {
+ borderWidth = msgPtr->highlightWidth;
+ }
+ Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), msgPtr->border,
+ borderWidth, borderWidth,
+ Tk_Width(tkwin) - 2 * borderWidth,
+ Tk_Height(tkwin) - 2 * borderWidth,
+ 0, TK_RELIEF_FLAT);
+
+ /*
+ * Compute starting y-location for message based on message size and
+ * anchor option.
+ */
+
+ TkComputeAnchor(msgPtr->anchor, tkwin, msgPtr->padX, msgPtr->padY,
+ msgPtr->msgWidth, msgPtr->msgHeight, &x, &y);
+ Tk_DrawTextLayout(Tk_Display(tkwin), Tk_WindowId(tkwin), msgPtr->textGC,
+ msgPtr->textLayout, x, y, 0, -1);
+
+ if (borderWidth > msgPtr->highlightWidth) {
+ Tk_Draw3DRectangle(tkwin, Tk_WindowId(tkwin), msgPtr->border,
+ msgPtr->highlightWidth, msgPtr->highlightWidth,
+ Tk_Width(tkwin) - 2*msgPtr->highlightWidth,
+ Tk_Height(tkwin) - 2*msgPtr->highlightWidth,
+ msgPtr->borderWidth, msgPtr->relief);
+ }
+ if (msgPtr->highlightWidth != 0) {
+ GC fgGC, bgGC;
+
+ bgGC = Tk_GCForColor(msgPtr->highlightBgColorPtr, Tk_WindowId(tkwin));
+ if (msgPtr->flags & GOT_FOCUS) {
+ fgGC = Tk_GCForColor(msgPtr->highlightColorPtr,Tk_WindowId(tkwin));
+ TkpDrawHighlightBorder(tkwin, fgGC, bgGC, msgPtr->highlightWidth,
+ Tk_WindowId(tkwin));
+ } else {
+ TkpDrawHighlightBorder(tkwin, bgGC, bgGC, msgPtr->highlightWidth,
+ Tk_WindowId(tkwin));
+ }
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * MessageEventProc --
+ *
+ * This function is invoked by the Tk dispatcher for various events on
+ * messages.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * When the window gets deleted, internal structures get cleaned up.
+ * When it gets exposed, it is redisplayed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+MessageEventProc(
+ ClientData clientData, /* Information about window. */
+ XEvent *eventPtr) /* Information about event. */
+{
+ Message *msgPtr = clientData;
+
+ if (((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0))
+ || (eventPtr->type == ConfigureNotify)) {
+ goto redraw;
+ } else if (eventPtr->type == DestroyNotify) {
+ DestroyMessage(clientData);
+ } else if (eventPtr->type == FocusIn) {
+ if (eventPtr->xfocus.detail != NotifyInferior) {
+ msgPtr->flags |= GOT_FOCUS;
+ if (msgPtr->highlightWidth > 0) {
+ goto redraw;
+ }
+ }
+ } else if (eventPtr->type == FocusOut) {
+ if (eventPtr->xfocus.detail != NotifyInferior) {
+ msgPtr->flags &= ~GOT_FOCUS;
+ if (msgPtr->highlightWidth > 0) {
+ goto redraw;
+ }
+ }
+ }
+ return;
+
+ redraw:
+ if ((msgPtr->tkwin != NULL) && !(msgPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DisplayMessage, msgPtr);
+ msgPtr->flags |= REDRAW_PENDING;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MessageCmdDeletedProc --
+ *
+ * This function is invoked when a widget command is deleted. If the
+ * widget isn't already in the process of being destroyed, this command
+ * destroys it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The widget is destroyed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+MessageCmdDeletedProc(
+ ClientData clientData) /* Pointer to widget record for widget. */
+{
+ Message *msgPtr = clientData;
+
+ /*
+ * This function could be invoked either because the window was destroyed
+ * and the command was then deleted (in which case tkwin is NULL) or
+ * because the command was deleted, and then this function destroys the
+ * widget.
+ */
+
+ if (!(msgPtr->flags & MESSAGE_DELETED)) {
+ Tk_DestroyWindow(msgPtr->tkwin);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * MessageTextVarProc --
+ *
+ * This function is invoked when someone changes the variable whose
+ * contents are to be displayed in a message.
+ *
+ * Results:
+ * NULL is always returned.
+ *
+ * Side effects:
+ * The text displayed in the message will change to match the variable.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static char *
+MessageTextVarProc(
+ ClientData clientData, /* Information about message. */
+ Tcl_Interp *interp, /* Interpreter containing variable. */
+ const char *name1, /* Name of variable. */
+ const char *name2, /* Second part of variable name. */
+ int flags) /* Information about what happened. */
+{
+ register Message *msgPtr = clientData;
+ const char *value;
+
+ /*
+ * If the variable is unset, then immediately recreate it unless the whole
+ * interpreter is going away.
+ */
+
+ if (flags & TCL_TRACE_UNSETS) {
+ if (!Tcl_InterpDeleted(interp) && msgPtr->textVarName) {
+ ClientData probe = NULL;
+
+ do {
+ probe = Tcl_VarTraceInfo(interp,
+ msgPtr->textVarName,
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ MessageTextVarProc, probe);
+ if (probe == (ClientData)msgPtr) {
+ break;
+ }
+ } while (probe);
+ if (probe) {
+ /*
+ * We were able to fetch the unset trace for our
+ * textVarName, which means it is not unset and not
+ * the cause of this unset trace. Instead some outdated
+ * former variable must be, and we should ignore it.
+ */
+ return NULL;
+ }
+ Tcl_SetVar2(interp, msgPtr->textVarName, NULL, msgPtr->string,
+ TCL_GLOBAL_ONLY);
+ Tcl_TraceVar2(interp, msgPtr->textVarName, NULL,
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ MessageTextVarProc, clientData);
+ }
+ return NULL;
+ }
+
+ value = Tcl_GetVar2(interp, msgPtr->textVarName, NULL, TCL_GLOBAL_ONLY);
+ if (value == NULL) {
+ value = "";
+ }
+ if (msgPtr->string != NULL) {
+ ckfree(msgPtr->string);
+ }
+ msgPtr->numChars = Tcl_NumUtfChars(value, -1);
+ msgPtr->string = ckalloc(strlen(value) + 1);
+ strcpy(msgPtr->string, value);
+ ComputeMessageGeometry(msgPtr);
+
+ if ((msgPtr->tkwin != NULL) && Tk_IsMapped(msgPtr->tkwin)
+ && !(msgPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DisplayMessage, msgPtr);
+ msgPtr->flags |= REDRAW_PENDING;
+ }
+ return NULL;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkObj.c b/tk8.6/generic/tkObj.c
new file mode 100644
index 0000000..559f0e2
--- /dev/null
+++ b/tk8.6/generic/tkObj.c
@@ -0,0 +1,1153 @@
+/*
+ * tkObj.c --
+ *
+ * This file contains functions that implement the common Tk object types
+ *
+ * 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.
+ */
+
+#include "tkInt.h"
+
+/*
+ * The following structure is the internal representation for pixel objects.
+ */
+
+typedef struct PixelRep {
+ double value;
+ int units;
+ Tk_Window tkwin;
+ int returnValue;
+} PixelRep;
+
+#define SIMPLE_PIXELREP(objPtr) \
+ ((objPtr)->internalRep.twoPtrValue.ptr2 == 0)
+
+#define SET_SIMPLEPIXEL(objPtr, intval) \
+ (objPtr)->internalRep.twoPtrValue.ptr1 = INT2PTR(intval); \
+ (objPtr)->internalRep.twoPtrValue.ptr2 = 0
+
+#define GET_SIMPLEPIXEL(objPtr) \
+ (PTR2INT((objPtr)->internalRep.twoPtrValue.ptr1))
+
+#define SET_COMPLEXPIXEL(objPtr, repPtr) \
+ (objPtr)->internalRep.twoPtrValue.ptr1 = NULL; \
+ (objPtr)->internalRep.twoPtrValue.ptr2 = repPtr
+
+#define GET_COMPLEXPIXEL(objPtr) \
+ ((PixelRep *) (objPtr)->internalRep.twoPtrValue.ptr2)
+
+/*
+ * One of these structures is created per thread to store thread-specific
+ * data. In this case, it is used to contain references to selected
+ * Tcl_ObjTypes that we can use as screen distances without conversion. The
+ * "dataKey" below is used to locate the ThreadSpecificData for the current
+ * thread.
+ */
+
+typedef struct {
+ const Tcl_ObjType *doubleTypePtr;
+ const Tcl_ObjType *intTypePtr;
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+
+/*
+ * The following structure is the internal representation for mm objects.
+ */
+
+typedef struct MMRep {
+ double value;
+ int units;
+ Tk_Window tkwin;
+ double returnValue;
+} MMRep;
+
+/*
+ * The following structure is the internal representation for window objects.
+ * A WindowRep caches name-to-window lookups. The cache is invalid if tkwin is
+ * NULL or if mainPtr->deletionEpoch does not match epoch.
+ */
+
+typedef struct WindowRep {
+ Tk_Window tkwin; /* Cached window; NULL if not found. */
+ TkMainInfo *mainPtr; /* MainWindow associated with tkwin. */
+ long epoch; /* Value of mainPtr->deletionEpoch at last
+ * successful lookup. */
+} WindowRep;
+
+/*
+ * Prototypes for functions defined later in this file:
+ */
+
+static void DupMMInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr);
+static void DupPixelInternalRep(Tcl_Obj *srcPtr, Tcl_Obj*copyPtr);
+static void DupWindowInternalRep(Tcl_Obj *srcPtr,Tcl_Obj*copyPtr);
+static void FreeMMInternalRep(Tcl_Obj *objPtr);
+static void FreePixelInternalRep(Tcl_Obj *objPtr);
+static void FreeWindowInternalRep(Tcl_Obj *objPtr);
+static ThreadSpecificData *GetTypeCache(void);
+static void UpdateStringOfMM(Tcl_Obj *objPtr);
+static int SetMMFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
+static int SetPixelFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
+static int SetWindowFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
+
+/*
+ * The following structure defines the implementation of the "pixel" Tcl
+ * object, used for measuring distances. The pixel object remembers its
+ * initial display-independent settings.
+ */
+
+static const Tcl_ObjType pixelObjType = {
+ "pixel", /* name */
+ FreePixelInternalRep, /* freeIntRepProc */
+ DupPixelInternalRep, /* dupIntRepProc */
+ NULL, /* updateStringProc */
+ SetPixelFromAny /* setFromAnyProc */
+};
+
+/*
+ * The following structure defines the implementation of the "pixel" Tcl
+ * object, used for measuring distances. The pixel object remembers its
+ * initial display-independent settings.
+ */
+
+static const Tcl_ObjType mmObjType = {
+ "mm", /* name */
+ FreeMMInternalRep, /* freeIntRepProc */
+ DupMMInternalRep, /* dupIntRepProc */
+ UpdateStringOfMM, /* updateStringProc */
+ SetMMFromAny /* setFromAnyProc */
+};
+
+/*
+ * The following structure defines the implementation of the "window"
+ * Tcl object.
+ */
+
+static const Tcl_ObjType windowObjType = {
+ "window", /* name */
+ FreeWindowInternalRep, /* freeIntRepProc */
+ DupWindowInternalRep, /* dupIntRepProc */
+ NULL, /* updateStringProc */
+ SetWindowFromAny /* setFromAnyProc */
+};
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetTypeCache --
+ *
+ * Get (and build if necessary) the cache of useful Tcl object types for
+ * comparisons in the conversion functions. This allows optimized checks
+ * for standard cases.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static ThreadSpecificData *
+GetTypeCache(void)
+{
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (tsdPtr->doubleTypePtr == NULL) {
+ /* Smart initialization of doubleTypePtr/intTypePtr without
+ * hash-table lookup or creating complete Tcl_Obj's */
+ Tcl_Obj obj;
+ obj.length = 3;
+ obj.bytes = (char *)"0.0";
+ obj.typePtr = NULL;
+ Tcl_GetDoubleFromObj(NULL, &obj, &obj.internalRep.doubleValue);
+ tsdPtr->doubleTypePtr = obj.typePtr;
+ obj.bytes += 2;
+ obj.length = 1;
+ obj.typePtr = NULL;
+ Tcl_GetLongFromObj(NULL, &obj, &obj.internalRep.longValue);
+ tsdPtr->intTypePtr = obj.typePtr;
+ }
+ return tsdPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetPixelsFromObjEx --
+ *
+ * Attempt to return a pixel value from the Tcl object "objPtr". If the
+ * object is not already a pixel value, an attempt will be made to
+ * convert it to one.
+ *
+ * Results:
+ * The return value is a standard Tcl object result. If an error occurs
+ * during conversion, an error message is left in the interpreter's
+ * result unless "interp" is NULL.
+ *
+ * Side effects:
+ * If the object is not already a pixel, the conversion will free any old
+ * internal representation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static
+int
+GetPixelsFromObjEx(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ Tk_Window tkwin,
+ Tcl_Obj *objPtr, /* The object from which to get pixels. */
+ int *intPtr,
+ double *dblPtr) /* Places to store resulting pixels. */
+{
+ int result, fresh;
+ double d;
+ PixelRep *pixelPtr;
+ static const double bias[] = {
+ 1.0, 10.0, 25.4, 0.35278 /*25.4 / 72.0*/
+ };
+
+ /*
+ * Special hacks where the type of the object is known to be something
+ * that is just numeric and cannot require distance conversion. This pokes
+ * holes in Tcl's abstractions, but they are just for optimization, not
+ * semantics.
+ */
+
+ if (objPtr->typePtr != &pixelObjType) {
+ ThreadSpecificData *typeCache = GetTypeCache();
+
+ if (objPtr->typePtr == typeCache->doubleTypePtr) {
+ (void) Tcl_GetDoubleFromObj(interp, objPtr, &d);
+ if (dblPtr != NULL) {
+ *dblPtr = d;
+ }
+ *intPtr = (int) (d<0 ? d-0.5 : d+0.5);
+ return TCL_OK;
+ } else if (objPtr->typePtr == typeCache->intTypePtr) {
+ (void) Tcl_GetIntFromObj(interp, objPtr, intPtr);
+ if (dblPtr) {
+ *dblPtr = (double) (*intPtr);
+ }
+ return TCL_OK;
+ }
+ }
+
+ retry:
+ fresh = (objPtr->typePtr != &pixelObjType);
+ if (fresh) {
+ result = SetPixelFromAny(interp, objPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+ }
+
+ if (SIMPLE_PIXELREP(objPtr)) {
+ *intPtr = GET_SIMPLEPIXEL(objPtr);
+ if (dblPtr) {
+ *dblPtr = (double) (*intPtr);
+ }
+ } else {
+ pixelPtr = GET_COMPLEXPIXEL(objPtr);
+ if ((!fresh) && (pixelPtr->tkwin != tkwin)) {
+ /*
+ * In the case of exo-screen conversions of non-pixels, we force a
+ * recomputation from the string.
+ */
+
+ FreePixelInternalRep(objPtr);
+ goto retry;
+ }
+ if ((pixelPtr->tkwin != tkwin) || dblPtr) {
+ d = pixelPtr->value;
+ if (pixelPtr->units >= 0) {
+ d *= bias[pixelPtr->units] * WidthOfScreen(Tk_Screen(tkwin));
+ d /= WidthMMOfScreen(Tk_Screen(tkwin));
+ }
+ pixelPtr->returnValue = (int) (d<0 ? d-0.5 : d+0.5);
+ pixelPtr->tkwin = tkwin;
+ if (dblPtr) {
+ *dblPtr = d;
+ }
+ }
+ *intPtr = pixelPtr->returnValue;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetPixelsFromObj --
+ *
+ * Attempt to return a pixel value from the Tcl object "objPtr". If the
+ * object is not already a pixel value, an attempt will be made to
+ * convert it to one.
+ *
+ * Results:
+ * The return value is a standard Tcl object result. If an error occurs
+ * during conversion, an error message is left in the interpreter's
+ * result unless "interp" is NULL.
+ *
+ * Side effects:
+ * If the object is not already a pixel, the conversion will free any old
+ * internal representation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_GetPixelsFromObj(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ Tk_Window tkwin,
+ Tcl_Obj *objPtr, /* The object from which to get pixels. */
+ int *intPtr) /* Place to store resulting pixels. */
+{
+ return GetPixelsFromObjEx(interp, tkwin, objPtr, intPtr, NULL);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetDoublePixelsFromObj --
+ *
+ * Attempt to return a double pixel value from the Tcl object
+ * "objPtr". If the object is not already a pixel value, an attempt will
+ * be made to convert it to one, the internal unit being pixels.
+ *
+ * Results:
+ * The return value is a standard Tcl object result. If an error occurs
+ * during conversion, an error message is left in the interpreter's
+ * result unless "interp" is NULL.
+ *
+ * Side effects:
+ * If the object is not already a pixel, the conversion will free any old
+ * internal representation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_GetDoublePixelsFromObj(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ Tk_Window tkwin,
+ Tcl_Obj *objPtr, /* The object from which to get pixels. */
+ double *doublePtr) /* Place to store resulting pixels. */
+{
+ double d;
+ int result, val;
+
+ result = GetPixelsFromObjEx(interp, tkwin, objPtr, &val, &d);
+ if (result != TCL_OK) {
+ return result;
+ }
+ if (objPtr->typePtr == &pixelObjType && !SIMPLE_PIXELREP(objPtr)) {
+ PixelRep *pixelPtr = GET_COMPLEXPIXEL(objPtr);
+
+ if (pixelPtr->units >= 0) {
+ /*
+ * Internally "shimmer" to pixel units.
+ */
+
+ pixelPtr->units = -1;
+ pixelPtr->value = d;
+ }
+ }
+ *doublePtr = d;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreePixelInternalRep --
+ *
+ * Deallocate the storage associated with a pixel object's internal
+ * representation.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Frees objPtr's internal representation and sets objPtr's internalRep
+ * to NULL.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FreePixelInternalRep(
+ Tcl_Obj *objPtr) /* Pixel object with internal rep to free. */
+{
+ if (!SIMPLE_PIXELREP(objPtr)) {
+ PixelRep *pixelPtr = GET_COMPLEXPIXEL(objPtr);
+
+ ckfree(pixelPtr);
+ }
+ SET_SIMPLEPIXEL(objPtr, 0);
+ objPtr->typePtr = NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DupPixelInternalRep --
+ *
+ * Initialize the internal representation of a pixel Tcl_Obj to a copy of
+ * the internal representation of an existing pixel object.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * copyPtr's internal rep is set to the pixel corresponding to srcPtr's
+ * internal rep.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DupPixelInternalRep(
+ register Tcl_Obj *srcPtr, /* Object with internal rep to copy. */
+ register Tcl_Obj *copyPtr) /* Object with internal rep to set. */
+{
+ copyPtr->typePtr = srcPtr->typePtr;
+
+ if (SIMPLE_PIXELREP(srcPtr)) {
+ SET_SIMPLEPIXEL(copyPtr, GET_SIMPLEPIXEL(srcPtr));
+ } else {
+ PixelRep *oldPtr, *newPtr;
+
+ oldPtr = GET_COMPLEXPIXEL(srcPtr);
+ newPtr = ckalloc(sizeof(PixelRep));
+ newPtr->value = oldPtr->value;
+ newPtr->units = oldPtr->units;
+ newPtr->tkwin = oldPtr->tkwin;
+ newPtr->returnValue = oldPtr->returnValue;
+ SET_COMPLEXPIXEL(copyPtr, newPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetPixelFromAny --
+ *
+ * Attempt to generate a pixel internal form for the Tcl object "objPtr".
+ *
+ * Results:
+ * The return value is a standard Tcl result. If an error occurs during
+ * conversion, an error message is left in the interpreter's result
+ * unless "interp" is NULL.
+ *
+ * Side effects:
+ * If no error occurs, a pixel representation of the object is stored
+ * internally and the type of "objPtr" is set to pixel.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetPixelFromAny(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ Tcl_Obj *objPtr) /* The object to convert. */
+{
+ const Tcl_ObjType *typePtr;
+ const char *string;
+ char *rest;
+ double d;
+ int i, units;
+
+ string = Tcl_GetString(objPtr);
+
+ d = strtod(string, &rest);
+ if (rest == string) {
+ goto error;
+ }
+ while ((*rest != '\0') && isspace(UCHAR(*rest))) {
+ rest++;
+ }
+
+ switch (*rest) {
+ case '\0':
+ units = -1;
+ break;
+ case 'm':
+ units = 0;
+ break;
+ case 'c':
+ units = 1;
+ break;
+ case 'i':
+ units = 2;
+ break;
+ case 'p':
+ units = 3;
+ break;
+ default:
+ goto error;
+ }
+
+ /*
+ * Free the old internalRep before setting the new one.
+ */
+
+ typePtr = objPtr->typePtr;
+ if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
+ typePtr->freeIntRepProc(objPtr);
+ }
+
+ objPtr->typePtr = &pixelObjType;
+
+ i = (int) d;
+ if ((units < 0) && (i == d)) {
+ SET_SIMPLEPIXEL(objPtr, i);
+ } else {
+ PixelRep *pixelPtr = ckalloc(sizeof(PixelRep));
+
+ pixelPtr->value = d;
+ pixelPtr->units = units;
+ pixelPtr->tkwin = NULL;
+ pixelPtr->returnValue = i;
+ SET_COMPLEXPIXEL(objPtr, pixelPtr);
+ }
+ return TCL_OK;
+
+ error:
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad screen distance \"%.50s\"", string));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "PIXELS", NULL);
+ }
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetMMFromObj --
+ *
+ * Attempt to return an mm value from the Tcl object "objPtr". If the
+ * object is not already an mm value, an attempt will be made to convert
+ * it to one.
+ *
+ * Results:
+ * The return value is a standard Tcl object result. If an error occurs
+ * during conversion, an error message is left in the interpreter's
+ * result unless "interp" is NULL.
+ *
+ * Side effects:
+ * If the object is not already a pixel, the conversion will free any old
+ * internal representation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_GetMMFromObj(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ Tk_Window tkwin,
+ Tcl_Obj *objPtr, /* The object from which to get mms. */
+ double *doublePtr) /* Place to store resulting millimeters. */
+{
+ int result;
+ double d;
+ MMRep *mmPtr;
+ static const double bias[] = {
+ 10.0, 25.4, 1.0, 0.35278 /*25.4 / 72.0*/
+ };
+
+ if (objPtr->typePtr != &mmObjType) {
+ result = SetMMFromAny(interp, objPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+ }
+
+ mmPtr = objPtr->internalRep.twoPtrValue.ptr1;
+ if (mmPtr->tkwin != tkwin) {
+ d = mmPtr->value;
+ if (mmPtr->units == -1) {
+ d /= WidthOfScreen(Tk_Screen(tkwin));
+ d *= WidthMMOfScreen(Tk_Screen(tkwin));
+ } else {
+ d *= bias[mmPtr->units];
+ }
+ mmPtr->tkwin = tkwin;
+ mmPtr->returnValue = d;
+ }
+ *doublePtr = mmPtr->returnValue;
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeMMInternalRep --
+ *
+ * Deallocate the storage associated with a mm object's internal
+ * representation.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Frees objPtr's internal representation and sets objPtr's internalRep
+ * to NULL.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FreeMMInternalRep(
+ Tcl_Obj *objPtr) /* MM object with internal rep to free. */
+{
+ ckfree(objPtr->internalRep.twoPtrValue.ptr1);
+ objPtr->internalRep.twoPtrValue.ptr1 = NULL;
+ objPtr->typePtr = NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DupMMInternalRep --
+ *
+ * Initialize the internal representation of a pixel Tcl_Obj to a copy of
+ * the internal representation of an existing pixel object.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * copyPtr's internal rep is set to the pixel corresponding to srcPtr's
+ * internal rep.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DupMMInternalRep(
+ register Tcl_Obj *srcPtr, /* Object with internal rep to copy. */
+ register Tcl_Obj *copyPtr) /* Object with internal rep to set. */
+{
+ MMRep *oldPtr, *newPtr;
+
+ copyPtr->typePtr = srcPtr->typePtr;
+ oldPtr = srcPtr->internalRep.twoPtrValue.ptr1;
+ newPtr = ckalloc(sizeof(MMRep));
+ newPtr->value = oldPtr->value;
+ newPtr->units = oldPtr->units;
+ newPtr->tkwin = oldPtr->tkwin;
+ newPtr->returnValue = oldPtr->returnValue;
+ copyPtr->internalRep.twoPtrValue.ptr1 = newPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UpdateStringOfMM --
+ *
+ * Update the string representation for a pixel Tcl_Obj this function is
+ * only called, if the pixel Tcl_Obj has no unit, because with units the
+ * string representation is created by SetMMFromAny
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The object's string is set to a valid string that results from the
+ * double-to-string conversion.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UpdateStringOfMM(
+ register Tcl_Obj *objPtr) /* pixel obj with string rep to update. */
+{
+ MMRep *mmPtr;
+ char buffer[TCL_DOUBLE_SPACE];
+ size_t len;
+
+ mmPtr = objPtr->internalRep.twoPtrValue.ptr1;
+ /* assert( mmPtr->units == -1 && objPtr->bytes == NULL ); */
+ if ((mmPtr->units != -1) || (objPtr->bytes != NULL)) {
+ Tcl_Panic("UpdateStringOfMM: false precondition");
+ }
+
+ Tcl_PrintDouble(NULL, mmPtr->value, buffer);
+ len = strlen(buffer);
+
+ objPtr->bytes = ckalloc(len + 1);
+ strcpy(objPtr->bytes, buffer);
+ objPtr->length = len;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetMMFromAny --
+ *
+ * Attempt to generate a mm internal form for the Tcl object "objPtr".
+ *
+ * Results:
+ * The return value is a standard Tcl result. If an error occurs during
+ * conversion, an error message is left in the interpreter's result
+ * unless "interp" is NULL.
+ *
+ * Side effects:
+ * If no error occurs, a mm representation of the object is stored
+ * internally and the type of "objPtr" is set to mm.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetMMFromAny(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ Tcl_Obj *objPtr) /* The object to convert. */
+{
+ ThreadSpecificData *typeCache = GetTypeCache();
+ const Tcl_ObjType *typePtr;
+ const char *string;
+ char *rest;
+ double d;
+ int units;
+ MMRep *mmPtr;
+
+ if (objPtr->typePtr == typeCache->doubleTypePtr) {
+ Tcl_GetDoubleFromObj(interp, objPtr, &d);
+ units = -1;
+ } else if (objPtr->typePtr == typeCache->intTypePtr) {
+ Tcl_GetIntFromObj(interp, objPtr, &units);
+ d = (double) units;
+ units = -1;
+
+ /*
+ * In the case of ints, we need to ensure that a valid string exists
+ * in order for int-but-not-string objects to be converted back to
+ * ints again from mm obj types.
+ */
+
+ (void) Tcl_GetString(objPtr);
+ } else {
+ /*
+ * It wasn't a known int or double, so parse it.
+ */
+
+ string = Tcl_GetString(objPtr);
+
+ d = strtod(string, &rest);
+ if (rest == string) {
+ /*
+ * Must copy string before resetting the result in case a caller
+ * is trying to convert the interpreter's result to mms.
+ */
+
+ error:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad screen distance \"%s\"", string));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "DISTANCE", NULL);
+ return TCL_ERROR;
+ }
+ while ((*rest != '\0') && isspace(UCHAR(*rest))) {
+ rest++;
+ }
+
+ switch (*rest) {
+ case '\0':
+ units = -1;
+ break;
+ case 'c':
+ units = 0;
+ break;
+ case 'i':
+ units = 1;
+ break;
+ case 'm':
+ units = 2;
+ break;
+ case 'p':
+ units = 3;
+ break;
+ default:
+ goto error;
+ }
+ }
+
+ /*
+ * Free the old internalRep before setting the new one.
+ */
+
+ typePtr = objPtr->typePtr;
+ if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
+ typePtr->freeIntRepProc(objPtr);
+ }
+
+ objPtr->typePtr = &mmObjType;
+
+ mmPtr = ckalloc(sizeof(MMRep));
+ mmPtr->value = d;
+ mmPtr->units = units;
+ mmPtr->tkwin = NULL;
+ mmPtr->returnValue = d;
+
+ objPtr->internalRep.twoPtrValue.ptr1 = mmPtr;
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkGetWindowFromObj --
+ *
+ * Attempt to return a Tk_Window from the Tcl object "objPtr". If the
+ * object is not already a Tk_Window, an attempt will be made to convert
+ * it to one.
+ *
+ * Results:
+ * The return value is a standard Tcl object result. If an error occurs
+ * during conversion, an error message is left in the interpreter's
+ * result unless "interp" is NULL.
+ *
+ * Side effects:
+ * If the object is not already a Tk_Window, the conversion will free any
+ * old internal representation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkGetWindowFromObj(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ Tk_Window tkwin, /* A token to get the main window from. */
+ Tcl_Obj *objPtr, /* The object from which to get window. */
+ Tk_Window *windowPtr) /* Place to store resulting window. */
+{
+ TkMainInfo *mainPtr = ((TkWindow *) tkwin)->mainPtr;
+ register WindowRep *winPtr;
+
+ if (objPtr->typePtr != &windowObjType) {
+ int result = SetWindowFromAny(interp, objPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+ }
+
+ winPtr = objPtr->internalRep.twoPtrValue.ptr1;
+ if (winPtr->tkwin == NULL
+ || winPtr->mainPtr == NULL
+ || winPtr->mainPtr != mainPtr
+ || winPtr->epoch != mainPtr->deletionEpoch) {
+ /*
+ * Cache is invalid.
+ */
+
+ winPtr->tkwin = Tk_NameToWindow(interp,
+ Tcl_GetString(objPtr), tkwin);
+ if (winPtr->tkwin == NULL) {
+ /* ASSERT: Tk_NameToWindow has left error message in interp */
+ return TCL_ERROR;
+ }
+
+ winPtr->mainPtr = mainPtr;
+ winPtr->epoch = mainPtr ? mainPtr->deletionEpoch : 0;
+ }
+
+ *windowPtr = winPtr->tkwin;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetWindowFromAny --
+ *
+ * Generate a windowObj internal form for the Tcl object "objPtr".
+ *
+ * Results:
+ * Always returns TCL_OK.
+ *
+ * Side effects:
+ * Sets objPtr's internal representation to an uninitialized windowObj.
+ * Frees the old internal representation, if any.
+ *
+ * See also:
+ * TkGetWindowFromObj, which initializes the WindowRep cache.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetWindowFromAny(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ register Tcl_Obj *objPtr) /* The object to convert. */
+{
+ const Tcl_ObjType *typePtr;
+ WindowRep *winPtr;
+
+ /*
+ * Free the old internalRep before setting the new one.
+ */
+
+ Tcl_GetString(objPtr);
+ typePtr = objPtr->typePtr;
+ if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
+ typePtr->freeIntRepProc(objPtr);
+ }
+
+ winPtr = ckalloc(sizeof(WindowRep));
+ winPtr->tkwin = NULL;
+ winPtr->mainPtr = NULL;
+ winPtr->epoch = 0;
+
+ objPtr->internalRep.twoPtrValue.ptr1 = winPtr;
+ objPtr->typePtr = &windowObjType;
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DupWindowInternalRep --
+ *
+ * Initialize the internal representation of a window Tcl_Obj to a copy
+ * of the internal representation of an existing window object.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * copyPtr's internal rep is set to refer to the same window as srcPtr's
+ * internal rep.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DupWindowInternalRep(
+ register Tcl_Obj *srcPtr,
+ register Tcl_Obj *copyPtr)
+{
+ register WindowRep *oldPtr, *newPtr;
+
+ oldPtr = srcPtr->internalRep.twoPtrValue.ptr1;
+ newPtr = ckalloc(sizeof(WindowRep));
+ newPtr->tkwin = oldPtr->tkwin;
+ newPtr->mainPtr = oldPtr->mainPtr;
+ newPtr->epoch = oldPtr->epoch;
+ copyPtr->internalRep.twoPtrValue.ptr1 = newPtr;
+ copyPtr->typePtr = srcPtr->typePtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeWindowInternalRep --
+ *
+ * Deallocate the storage associated with a window object's internal
+ * representation.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Frees objPtr's internal representation and sets objPtr's internalRep
+ * to NULL.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FreeWindowInternalRep(
+ Tcl_Obj *objPtr) /* Window object with internal rep to free. */
+{
+ ckfree(objPtr->internalRep.twoPtrValue.ptr1);
+ objPtr->internalRep.twoPtrValue.ptr1 = NULL;
+ objPtr->typePtr = NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkNewWindowObj --
+ *
+ * This function allocates a new Tcl_Obj that refers to a particular to a
+ * particular Tk window.
+ *
+ * Results:
+ * A standard Tcl object reference, with refcount 0.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TkNewWindowObj(
+ Tk_Window tkwin)
+{
+ Tcl_Obj *objPtr = Tcl_NewStringObj(Tk_PathName(tkwin), -1);
+ TkMainInfo *mainPtr = ((TkWindow *) tkwin)->mainPtr;
+ register WindowRep *winPtr;
+
+ SetWindowFromAny(NULL, objPtr);
+
+ winPtr = objPtr->internalRep.twoPtrValue.ptr1;
+ winPtr->tkwin = tkwin;
+ winPtr->mainPtr = mainPtr;
+ winPtr->epoch = mainPtr->deletionEpoch;
+ return objPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkParsePadAmount --
+ *
+ * This function parses a padding specification and returns the
+ * appropriate padding values. A padding specification can be either a
+ * single pixel width, or a list of two pixel widths. If a single pixel
+ * width, the amount specified is used for padding on both sides. If two
+ * amounts are specified, then they specify the left/right or top/bottom
+ * padding.
+ *
+ * Results:
+ * A standard Tcl return value.
+ *
+ * Side effects:
+ * An error message is written to the interpreter if something is not
+ * right.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkParsePadAmount(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Tk_Window tkwin, /* A window. Needed by Tk_GetPixels() */
+ Tcl_Obj *specObj, /* The argument to "-padx", "-pady", "-ipadx",
+ * or "-ipady". The thing to be parsed. */
+ int *halfPtr, /* Write the left/top part of padding here */
+ int *allPtr) /* Write the total padding here */
+{
+ int firstInt, secondInt; /* The two components of the padding */
+ int objc; /* The length of the list (should be 1 or 2) */
+ Tcl_Obj **objv; /* The objects in the list */
+
+ /*
+ * Check for a common case where a single object would otherwise be
+ * shimmered between a list and a pixel spec.
+ */
+
+ if (specObj->typePtr == &pixelObjType) {
+ if (Tk_GetPixelsFromObj(interp, tkwin, specObj, &firstInt) != TCL_OK){
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad pad value \"%s\": must be positive screen distance",
+ Tcl_GetString(specObj)));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "PADDING", "DIST", NULL);
+ return TCL_ERROR;
+ }
+ secondInt = firstInt;
+ goto done;
+ }
+
+ /*
+ * Pad specifications are a list of one or two elements, each of which is
+ * a pixel specification.
+ */
+
+ if (Tcl_ListObjGetElements(interp, specObj, &objc, &objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (objc != 1 && objc != 2) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "wrong number of parts to pad specification", -1));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "PADDING", "PARTS", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Parse the first part.
+ */
+
+ if (Tk_GetPixelsFromObj(interp, tkwin, objv[0], &firstInt) != TCL_OK ||
+ (firstInt < 0)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad pad value \"%s\": must be positive screen distance",
+ Tcl_GetString(objv[0])));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "PADDING", "DIST", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Parse the second part if it exists, otherwise it is as if it was the
+ * same as the first part.
+ */
+
+ if (objc == 1) {
+ secondInt = firstInt;
+ } else if (Tk_GetPixelsFromObj(interp, tkwin, objv[1],
+ &secondInt) != TCL_OK || (secondInt < 0)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad 2nd pad value \"%s\": must be positive screen distance",
+ Tcl_GetString(objv[1])));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "PADDING", "DIST", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Write the parsed bits back into the receiving variables.
+ */
+
+ done:
+ if (halfPtr != 0) {
+ *halfPtr = firstInt;
+ }
+ *allPtr = firstInt + secondInt;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkRegisterObjTypes --
+ *
+ * Registers Tk's Tcl_ObjType structures with the Tcl run-time.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * All instances of Tcl_ObjType structures used in Tk are registered with
+ * Tcl.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkRegisterObjTypes(void)
+{
+ Tcl_RegisterObjType(&tkBorderObjType);
+ Tcl_RegisterObjType(&tkBitmapObjType);
+ Tcl_RegisterObjType(&tkColorObjType);
+ Tcl_RegisterObjType(&tkCursorObjType);
+ Tcl_RegisterObjType(&tkFontObjType);
+ Tcl_RegisterObjType(&mmObjType);
+ Tcl_RegisterObjType(&pixelObjType);
+ Tcl_RegisterObjType(&tkStateKeyObjType);
+ Tcl_RegisterObjType(&windowObjType);
+ Tcl_RegisterObjType(&tkTextIndexType);
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkOldConfig.c b/tk8.6/generic/tkOldConfig.c
new file mode 100644
index 0000000..f20f38f
--- /dev/null
+++ b/tk8.6/generic/tkOldConfig.c
@@ -0,0 +1,1184 @@
+/*
+ * tkOldConfig.c --
+ *
+ * This file contains the Tk_ConfigureWidget function. THIS FILE IS HERE
+ * FOR BACKWARD COMPATIBILITY; THE NEW CONFIGURATION PACKAGE SHOULD BE
+ * USED FOR NEW PROJECTS.
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "tkInt.h"
+
+/*
+ * Values for "flags" field of Tk_ConfigSpec structures. Be sure to coordinate
+ * these values with those defined in tk.h (TK_CONFIG_COLOR_ONLY, etc.) There
+ * must not be overlap!
+ *
+ * INIT - Non-zero means (char *) things have been converted to
+ * Tk_Uid's.
+ */
+
+#define INIT 0x20
+
+/*
+ * Forward declarations for functions defined later in this file:
+ */
+
+static int DoConfig(Tcl_Interp *interp, Tk_Window tkwin,
+ Tk_ConfigSpec *specPtr, Tk_Uid value,
+ int valueIsUid, char *widgRec);
+static Tk_ConfigSpec * FindConfigSpec(Tcl_Interp *interp,
+ Tk_ConfigSpec *specs, const char *argvName,
+ int needFlags, int hateFlags);
+static char * FormatConfigInfo(Tcl_Interp *interp, Tk_Window tkwin,
+ const Tk_ConfigSpec *specPtr, char *widgRec);
+static const char * FormatConfigValue(Tcl_Interp *interp, Tk_Window tkwin,
+ const Tk_ConfigSpec *specPtr, char *widgRec,
+ char *buffer, Tcl_FreeProc **freeProcPtr);
+static Tk_ConfigSpec * GetCachedSpecs(Tcl_Interp *interp,
+ const Tk_ConfigSpec *staticSpecs);
+static void DeleteSpecCacheTable(ClientData clientData,
+ Tcl_Interp *interp);
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_ConfigureWidget --
+ *
+ * Process command-line options and database options to fill in fields of
+ * a widget record with resources and other parameters.
+ *
+ * Results:
+ * A standard Tcl return value. In case of an error, the interp's result
+ * will hold an error message.
+ *
+ * Side effects:
+ * The fields of widgRec get filled in with information from argc/argv
+ * and the option database. Old information in widgRec's fields gets
+ * recycled. A copy of the spec-table is taken with (some of) the char*
+ * fields converted into Tk_Uid fields; this copy will be released when
+ * the interpreter terminates.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_ConfigureWidget(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Tk_Window tkwin, /* Window containing widget (needed to set up
+ * X resources). */
+ const Tk_ConfigSpec *specs, /* Describes legal options. */
+ int argc, /* Number of elements in argv. */
+ const char **argv, /* Command-line options. */
+ char *widgRec, /* Record whose fields are to be modified.
+ * Values must be properly initialized. */
+ int flags) /* Used to specify additional flags that must
+ * be present in config specs for them to be
+ * considered. Also, may have
+ * TK_CONFIG_ARGV_ONLY set. */
+{
+ register Tk_ConfigSpec *specPtr, *staticSpecs;
+ Tk_Uid value; /* Value of option from database. */
+ int needFlags; /* Specs must contain this set of flags or
+ * else they are not considered. */
+ int hateFlags; /* If a spec contains any bits here, it's not
+ * considered. */
+
+ if (tkwin == NULL) {
+ /*
+ * Either we're not really in Tk, or the main window was destroyed and
+ * we're on our way out of the application
+ */
+
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("NULL main window", -1));
+ Tcl_SetErrorCode(interp, "TK", "NO_MAIN_WINDOW", NULL);
+ return TCL_ERROR;
+ }
+
+ needFlags = flags & ~(TK_CONFIG_USER_BIT - 1);
+ if (Tk_Depth(tkwin) <= 1) {
+ hateFlags = TK_CONFIG_COLOR_ONLY;
+ } else {
+ hateFlags = TK_CONFIG_MONO_ONLY;
+ }
+
+ /*
+ * Get the build of the config for this interpreter.
+ */
+
+ staticSpecs = GetCachedSpecs(interp, specs);
+
+ for (specPtr = staticSpecs; specPtr->type != TK_CONFIG_END; specPtr++) {
+ specPtr->specFlags &= ~TK_CONFIG_OPTION_SPECIFIED;
+ }
+
+ /*
+ * Pass one: scan through all of the arguments, processing those that
+ * match entries in the specs.
+ */
+
+ for ( ; argc > 0; argc -= 2, argv += 2) {
+ const char *arg;
+
+ if (flags & TK_CONFIG_OBJS) {
+ arg = Tcl_GetString((Tcl_Obj *) *argv);
+ } else {
+ arg = *argv;
+ }
+ specPtr = FindConfigSpec(interp, staticSpecs, arg, needFlags, hateFlags);
+ if (specPtr == NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Process the entry.
+ */
+
+ if (argc < 2) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "value for \"%s\" missing", arg));
+ Tcl_SetErrorCode(interp, "TK", "VALUE_MISSING", NULL);
+ return TCL_ERROR;
+ }
+ if (flags & TK_CONFIG_OBJS) {
+ arg = Tcl_GetString((Tcl_Obj *) argv[1]);
+ } else {
+ arg = argv[1];
+ }
+ if (DoConfig(interp, tkwin, specPtr, arg, 0, widgRec) != TCL_OK) {
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (processing \"%.40s\" option)",specPtr->argvName));
+ return TCL_ERROR;
+ }
+ if (!(flags & TK_CONFIG_ARGV_ONLY)) {
+ specPtr->specFlags |= TK_CONFIG_OPTION_SPECIFIED;
+ }
+ }
+
+ /*
+ * Pass two: scan through all of the specs again; if no command-line
+ * argument matched a spec, then check for info in the option database.
+ * If there was nothing in the database, then use the default.
+ */
+
+ if (!(flags & TK_CONFIG_ARGV_ONLY)) {
+ for (specPtr = staticSpecs; specPtr->type != TK_CONFIG_END; specPtr++) {
+ if ((specPtr->specFlags & TK_CONFIG_OPTION_SPECIFIED)
+ || (specPtr->argvName == NULL)
+ || (specPtr->type == TK_CONFIG_SYNONYM)) {
+ continue;
+ }
+ if (((specPtr->specFlags & needFlags) != needFlags)
+ || (specPtr->specFlags & hateFlags)) {
+ continue;
+ }
+ value = NULL;
+ if (specPtr->dbName != NULL) {
+ value = Tk_GetOption(tkwin, specPtr->dbName, specPtr->dbClass);
+ }
+ if (value != NULL) {
+ if (DoConfig(interp, tkwin, specPtr, value, 1, widgRec) !=
+ TCL_OK) {
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (%s \"%.50s\" in widget \"%.50s\")",
+ "database entry for", specPtr->dbName,
+ Tk_PathName(tkwin)));
+ return TCL_ERROR;
+ }
+ } else {
+ if (specPtr->defValue != NULL) {
+ value = Tk_GetUid(specPtr->defValue);
+ } else {
+ value = NULL;
+ }
+ if ((value != NULL) && !(specPtr->specFlags
+ & TK_CONFIG_DONT_SET_DEFAULT)) {
+ if (DoConfig(interp, tkwin, specPtr, value, 1, widgRec) !=
+ TCL_OK) {
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (%s \"%.50s\" in widget \"%.50s\")",
+ "default value for", specPtr->dbName,
+ Tk_PathName(tkwin)));
+ return TCL_ERROR;
+ }
+ }
+ }
+ }
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * FindConfigSpec --
+ *
+ * Search through a table of configuration specs, looking for one that
+ * matches a given argvName.
+ *
+ * Results:
+ * The return value is a pointer to the matching entry, or NULL if
+ * nothing matched. In that case an error message is left in the interp's
+ * result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static Tk_ConfigSpec *
+FindConfigSpec(
+ Tcl_Interp *interp, /* Used for reporting errors. */
+ Tk_ConfigSpec *specs, /* Pointer to table of configuration
+ * specifications for a widget. */
+ const char *argvName, /* Name (suitable for use in a "config"
+ * command) identifying particular option. */
+ int needFlags, /* Flags that must be present in matching
+ * entry. */
+ int hateFlags) /* Flags that must NOT be present in matching
+ * entry. */
+{
+ register Tk_ConfigSpec *specPtr;
+ register char c; /* First character of current argument. */
+ Tk_ConfigSpec *matchPtr; /* Matching spec, or NULL. */
+ size_t length;
+
+ c = argvName[1];
+ length = strlen(argvName);
+ matchPtr = NULL;
+ for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) {
+ if (specPtr->argvName == NULL) {
+ continue;
+ }
+ if ((specPtr->argvName[1] != c)
+ || (strncmp(specPtr->argvName, argvName, length) != 0)) {
+ continue;
+ }
+ if (((specPtr->specFlags & needFlags) != needFlags)
+ || (specPtr->specFlags & hateFlags)) {
+ continue;
+ }
+ if (specPtr->argvName[length] == 0) {
+ matchPtr = specPtr;
+ goto gotMatch;
+ }
+ if (matchPtr != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "ambiguous option \"%s\"", argvName));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "OPTION", argvName,NULL);
+ return NULL;
+ }
+ matchPtr = specPtr;
+ }
+
+ if (matchPtr == NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "unknown option \"%s\"", argvName));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "OPTION", argvName, NULL);
+ return NULL;
+ }
+
+ /*
+ * Found a matching entry. If it's a synonym, then find the entry that
+ * it's a synonym for.
+ */
+
+ gotMatch:
+ specPtr = matchPtr;
+ if (specPtr->type == TK_CONFIG_SYNONYM) {
+ for (specPtr = specs; ; specPtr++) {
+ if (specPtr->type == TK_CONFIG_END) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "couldn't find synonym for option \"%s\"",
+ argvName));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "OPTION", argvName,
+ NULL);
+ return NULL;
+ }
+ if ((specPtr->dbName == matchPtr->dbName)
+ && (specPtr->type != TK_CONFIG_SYNONYM)
+ && ((specPtr->specFlags & needFlags) == needFlags)
+ && !(specPtr->specFlags & hateFlags)) {
+ break;
+ }
+ }
+ }
+ return specPtr;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DoConfig --
+ *
+ * This function applies a single configuration option to a widget
+ * record.
+ *
+ * Results:
+ * A standard Tcl return value.
+ *
+ * Side effects:
+ * WidgRec is modified as indicated by specPtr and value. The old value
+ * is recycled, if that is appropriate for the value type.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+DoConfig(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Tk_Window tkwin, /* Window containing widget (needed to set up
+ * X resources). */
+ Tk_ConfigSpec *specPtr, /* Specifier to apply. */
+ Tk_Uid value, /* Value to use to fill in widgRec. */
+ int valueIsUid, /* Non-zero means value is a Tk_Uid; zero
+ * means it's an ordinary string. */
+ char *widgRec) /* Record whose fields are to be modified.
+ * Values must be properly initialized. */
+{
+ char *ptr;
+ Tk_Uid uid;
+ int nullValue;
+
+ nullValue = 0;
+ if ((*value == 0) && (specPtr->specFlags & TK_CONFIG_NULL_OK)) {
+ nullValue = 1;
+ }
+
+ do {
+ ptr = widgRec + specPtr->offset;
+ switch (specPtr->type) {
+ case TK_CONFIG_BOOLEAN:
+ if (Tcl_GetBoolean(interp, value, (int *) ptr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+ case TK_CONFIG_INT:
+ if (Tcl_GetInt(interp, value, (int *) ptr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+ case TK_CONFIG_DOUBLE:
+ if (Tcl_GetDouble(interp, value, (double *) ptr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+ case TK_CONFIG_STRING: {
+ char *oldStr, *newStr;
+
+ if (nullValue) {
+ newStr = NULL;
+ } else {
+ newStr = ckalloc(strlen(value) + 1);
+ strcpy(newStr, value);
+ }
+ oldStr = *((char **) ptr);
+ if (oldStr != NULL) {
+ ckfree(oldStr);
+ }
+ *((char **) ptr) = newStr;
+ break;
+ }
+ case TK_CONFIG_UID:
+ if (nullValue) {
+ *((Tk_Uid *) ptr) = NULL;
+ } else {
+ uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
+ *((Tk_Uid *) ptr) = uid;
+ }
+ break;
+ case TK_CONFIG_COLOR: {
+ XColor *newPtr, *oldPtr;
+
+ if (nullValue) {
+ newPtr = NULL;
+ } else {
+ uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
+ newPtr = Tk_GetColor(interp, tkwin, uid);
+ if (newPtr == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ oldPtr = *((XColor **) ptr);
+ if (oldPtr != NULL) {
+ Tk_FreeColor(oldPtr);
+ }
+ *((XColor **) ptr) = newPtr;
+ break;
+ }
+ case TK_CONFIG_FONT: {
+ Tk_Font newFont;
+
+ if (nullValue) {
+ newFont = NULL;
+ } else {
+ newFont = Tk_GetFont(interp, tkwin, value);
+ if (newFont == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ Tk_FreeFont(*((Tk_Font *) ptr));
+ *((Tk_Font *) ptr) = newFont;
+ break;
+ }
+ case TK_CONFIG_BITMAP: {
+ Pixmap newBmp, oldBmp;
+
+ if (nullValue) {
+ newBmp = None;
+ } else {
+ uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
+ newBmp = Tk_GetBitmap(interp, tkwin, uid);
+ if (newBmp == None) {
+ return TCL_ERROR;
+ }
+ }
+ oldBmp = *((Pixmap *) ptr);
+ if (oldBmp != None) {
+ Tk_FreeBitmap(Tk_Display(tkwin), oldBmp);
+ }
+ *((Pixmap *) ptr) = newBmp;
+ break;
+ }
+ case TK_CONFIG_BORDER: {
+ Tk_3DBorder newBorder, oldBorder;
+
+ if (nullValue) {
+ newBorder = NULL;
+ } else {
+ uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
+ newBorder = Tk_Get3DBorder(interp, tkwin, uid);
+ if (newBorder == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ oldBorder = *((Tk_3DBorder *) ptr);
+ if (oldBorder != NULL) {
+ Tk_Free3DBorder(oldBorder);
+ }
+ *((Tk_3DBorder *) ptr) = newBorder;
+ break;
+ }
+ case TK_CONFIG_RELIEF:
+ uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
+ if (Tk_GetRelief(interp, uid, (int *) ptr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+ case TK_CONFIG_CURSOR:
+ case TK_CONFIG_ACTIVE_CURSOR: {
+ Tk_Cursor newCursor, oldCursor;
+
+ if (nullValue) {
+ newCursor = NULL;
+ } else {
+ uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
+ newCursor = Tk_GetCursor(interp, tkwin, uid);
+ if (newCursor == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ oldCursor = *((Tk_Cursor *) ptr);
+ if (oldCursor != NULL) {
+ Tk_FreeCursor(Tk_Display(tkwin), oldCursor);
+ }
+ *((Tk_Cursor *) ptr) = newCursor;
+ if (specPtr->type == TK_CONFIG_ACTIVE_CURSOR) {
+ Tk_DefineCursor(tkwin, newCursor);
+ }
+ break;
+ }
+ case TK_CONFIG_JUSTIFY:
+ uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
+ if (Tk_GetJustify(interp, uid, (Tk_Justify *) ptr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+ case TK_CONFIG_ANCHOR:
+ uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
+ if (Tk_GetAnchor(interp, uid, (Tk_Anchor *) ptr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+ case TK_CONFIG_CAP_STYLE:
+ uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
+ if (Tk_GetCapStyle(interp, uid, (int *) ptr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+ case TK_CONFIG_JOIN_STYLE:
+ uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
+ if (Tk_GetJoinStyle(interp, uid, (int *) ptr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+ case TK_CONFIG_PIXELS:
+ if (Tk_GetPixels(interp, tkwin, value, (int *) ptr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+ case TK_CONFIG_MM:
+ if (Tk_GetScreenMM(interp, tkwin, value, (double*)ptr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+ case TK_CONFIG_WINDOW: {
+ Tk_Window tkwin2;
+
+ if (nullValue) {
+ tkwin2 = NULL;
+ } else {
+ tkwin2 = Tk_NameToWindow(interp, value, tkwin);
+ if (tkwin2 == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ *((Tk_Window *) ptr) = tkwin2;
+ break;
+ }
+ case TK_CONFIG_CUSTOM:
+ if (specPtr->customPtr->parseProc(specPtr->customPtr->clientData,
+ interp, tkwin, value, widgRec, specPtr->offset)!=TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+ default:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad config table: unknown type %d", specPtr->type));
+ Tcl_SetErrorCode(interp, "TK", "BAD_CONFIG", NULL);
+ return TCL_ERROR;
+ }
+ specPtr++;
+ } while ((specPtr->argvName == NULL) && (specPtr->type != TK_CONFIG_END));
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_ConfigureInfo --
+ *
+ * Return information about the configuration options for a window, and
+ * their current values.
+ *
+ * Results:
+ * Always returns TCL_OK. The interp's result will be modified hold a
+ * description of either a single configuration option available for
+ * "widgRec" via "specs", or all the configuration options available. In
+ * the "all" case, the result will available for "widgRec" via "specs".
+ * The result will be a list, each of whose entries describes one option.
+ * Each entry will itself be a list containing the option's name for use
+ * on command lines, database name, database class, default value, and
+ * current value (empty string if none). For options that are synonyms,
+ * the list will contain only two values: name and synonym name. If the
+ * "name" argument is non-NULL, then the only information returned is
+ * that for the named argument (i.e. the corresponding entry in the
+ * overall list is returned).
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_ConfigureInfo(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Tk_Window tkwin, /* Window corresponding to widgRec. */
+ const Tk_ConfigSpec *specs, /* Describes legal options. */
+ char *widgRec, /* Record whose fields contain current values
+ * for options. */
+ const char *argvName, /* If non-NULL, indicates a single option
+ * whose info is to be returned. Otherwise
+ * info is returned for all options. */
+ int flags) /* Used to specify additional flags that must
+ * be present in config specs for them to be
+ * considered. */
+{
+ register Tk_ConfigSpec *specPtr, *staticSpecs;
+ int needFlags, hateFlags;
+ char *list;
+ const char *leader = "{";
+
+ needFlags = flags & ~(TK_CONFIG_USER_BIT - 1);
+ if (Tk_Depth(tkwin) <= 1) {
+ hateFlags = TK_CONFIG_COLOR_ONLY;
+ } else {
+ hateFlags = TK_CONFIG_MONO_ONLY;
+ }
+
+ /*
+ * Get the build of the config for this interpreter.
+ */
+
+ staticSpecs = GetCachedSpecs(interp, specs);
+
+ /*
+ * If information is only wanted for a single configuration spec, then
+ * handle that one spec specially.
+ */
+
+ Tcl_ResetResult(interp);
+ if (argvName != NULL) {
+ specPtr = FindConfigSpec(interp, staticSpecs, argvName, needFlags,
+ hateFlags);
+ if (specPtr == NULL) {
+ return TCL_ERROR;
+ }
+ list = FormatConfigInfo(interp, tkwin, specPtr, widgRec);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(list, -1));
+ ckfree(list);
+ return TCL_OK;
+ }
+
+ /*
+ * Loop through all the specs, creating a big list with all their
+ * information.
+ */
+
+ for (specPtr = staticSpecs; specPtr->type != TK_CONFIG_END; specPtr++) {
+ if ((argvName != NULL) && (specPtr->argvName != argvName)) {
+ continue;
+ }
+ if (((specPtr->specFlags & needFlags) != needFlags)
+ || (specPtr->specFlags & hateFlags)) {
+ continue;
+ }
+ if (specPtr->argvName == NULL) {
+ continue;
+ }
+ list = FormatConfigInfo(interp, tkwin, specPtr, widgRec);
+ Tcl_AppendResult(interp, leader, list, "}", NULL);
+ ckfree(list);
+ leader = " {";
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * FormatConfigInfo --
+ *
+ * Create a valid Tcl list holding the configuration information for a
+ * single configuration option.
+ *
+ * Results:
+ * A Tcl list, dynamically allocated. The caller is expected to arrange
+ * for this list to be freed eventually.
+ *
+ * Side effects:
+ * Memory is allocated.
+ *
+ *--------------------------------------------------------------
+ */
+
+static char *
+FormatConfigInfo(
+ Tcl_Interp *interp, /* Interpreter to use for things like
+ * floating-point precision. */
+ Tk_Window tkwin, /* Window corresponding to widget. */
+ register const Tk_ConfigSpec *specPtr,
+ /* Pointer to information describing
+ * option. */
+ char *widgRec) /* Pointer to record holding current values of
+ * info for widget. */
+{
+ const char *argv[6];
+ char *result;
+ char buffer[200];
+ Tcl_FreeProc *freeProc = NULL;
+
+ argv[0] = specPtr->argvName;
+ argv[1] = specPtr->dbName;
+ argv[2] = specPtr->dbClass;
+ argv[3] = specPtr->defValue;
+ if (specPtr->type == TK_CONFIG_SYNONYM) {
+ return Tcl_Merge(2, argv);
+ }
+ argv[4] = FormatConfigValue(interp, tkwin, specPtr, widgRec, buffer,
+ &freeProc);
+ if (argv[1] == NULL) {
+ argv[1] = "";
+ }
+ if (argv[2] == NULL) {
+ argv[2] = "";
+ }
+ if (argv[3] == NULL) {
+ argv[3] = "";
+ }
+ if (argv[4] == NULL) {
+ argv[4] = "";
+ }
+ result = Tcl_Merge(5, argv);
+ if (freeProc != NULL) {
+ if ((freeProc == TCL_DYNAMIC) || (freeProc == (Tcl_FreeProc *) free)) {
+ ckfree((char *) argv[4]);
+ } else {
+ freeProc((char *) argv[4]);
+ }
+ }
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FormatConfigValue --
+ *
+ * This function formats the current value of a configuration option.
+ *
+ * Results:
+ * The return value is the formatted value of the option given by specPtr
+ * and widgRec. If the value is static, so that it need not be freed,
+ * *freeProcPtr will be set to NULL; otherwise *freeProcPtr will be set
+ * to the address of a function to free the result, and the caller must
+ * invoke this function when it is finished with the result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static const char *
+FormatConfigValue(
+ Tcl_Interp *interp, /* Interpreter for use in real conversions. */
+ Tk_Window tkwin, /* Window corresponding to widget. */
+ const Tk_ConfigSpec *specPtr, /* Pointer to information describing option.
+ * Must not point to a synonym option. */
+ char *widgRec, /* Pointer to record holding current values of
+ * info for widget. */
+ char *buffer, /* Static buffer to use for small values.
+ * Must have at least 200 bytes of storage. */
+ Tcl_FreeProc **freeProcPtr) /* Pointer to word to fill in with address of
+ * function to free the result, or NULL if
+ * result is static. */
+{
+ const char *ptr, *result;
+
+ *freeProcPtr = NULL;
+ ptr = widgRec + specPtr->offset;
+ result = "";
+ switch (specPtr->type) {
+ case TK_CONFIG_BOOLEAN:
+ if (*((int *) ptr) == 0) {
+ result = "0";
+ } else {
+ result = "1";
+ }
+ break;
+ case TK_CONFIG_INT:
+ sprintf(buffer, "%d", *((int *) ptr));
+ result = buffer;
+ break;
+ case TK_CONFIG_DOUBLE:
+ Tcl_PrintDouble(interp, *((double *) ptr), buffer);
+ result = buffer;
+ break;
+ case TK_CONFIG_STRING:
+ result = (*(char **) ptr);
+ if (result == NULL) {
+ result = "";
+ }
+ break;
+ case TK_CONFIG_UID: {
+ Tk_Uid uid = *((Tk_Uid *) ptr);
+
+ if (uid != NULL) {
+ result = uid;
+ }
+ break;
+ }
+ case TK_CONFIG_COLOR: {
+ XColor *colorPtr = *((XColor **) ptr);
+
+ if (colorPtr != NULL) {
+ result = Tk_NameOfColor(colorPtr);
+ }
+ break;
+ }
+ case TK_CONFIG_FONT: {
+ Tk_Font tkfont = *((Tk_Font *) ptr);
+
+ if (tkfont != NULL) {
+ result = Tk_NameOfFont(tkfont);
+ }
+ break;
+ }
+ case TK_CONFIG_BITMAP: {
+ Pixmap pixmap = *((Pixmap *) ptr);
+
+ if (pixmap != None) {
+ result = Tk_NameOfBitmap(Tk_Display(tkwin), pixmap);
+ }
+ break;
+ }
+ case TK_CONFIG_BORDER: {
+ Tk_3DBorder border = *((Tk_3DBorder *) ptr);
+
+ if (border != NULL) {
+ result = Tk_NameOf3DBorder(border);
+ }
+ break;
+ }
+ case TK_CONFIG_RELIEF:
+ result = Tk_NameOfRelief(*((int *) ptr));
+ break;
+ case TK_CONFIG_CURSOR:
+ case TK_CONFIG_ACTIVE_CURSOR: {
+ Tk_Cursor cursor = *((Tk_Cursor *) ptr);
+
+ if (cursor != NULL) {
+ result = Tk_NameOfCursor(Tk_Display(tkwin), cursor);
+ }
+ break;
+ }
+ case TK_CONFIG_JUSTIFY:
+ result = Tk_NameOfJustify(*((Tk_Justify *) ptr));
+ break;
+ case TK_CONFIG_ANCHOR:
+ result = Tk_NameOfAnchor(*((Tk_Anchor *) ptr));
+ break;
+ case TK_CONFIG_CAP_STYLE:
+ result = Tk_NameOfCapStyle(*((int *) ptr));
+ break;
+ case TK_CONFIG_JOIN_STYLE:
+ result = Tk_NameOfJoinStyle(*((int *) ptr));
+ break;
+ case TK_CONFIG_PIXELS:
+ sprintf(buffer, "%d", *((int *) ptr));
+ result = buffer;
+ break;
+ case TK_CONFIG_MM:
+ Tcl_PrintDouble(interp, *((double *) ptr), buffer);
+ result = buffer;
+ break;
+ case TK_CONFIG_WINDOW: {
+ Tk_Window tkwin;
+
+ tkwin = *((Tk_Window *) ptr);
+ if (tkwin != NULL) {
+ result = Tk_PathName(tkwin);
+ }
+ break;
+ }
+ case TK_CONFIG_CUSTOM:
+ result = specPtr->customPtr->printProc(specPtr->customPtr->clientData,
+ tkwin, widgRec, specPtr->offset, freeProcPtr);
+ break;
+ default:
+ result = "?? unknown type ??";
+ }
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_ConfigureValue --
+ *
+ * This function returns the current value of a configuration option for
+ * a widget.
+ *
+ * Results:
+ * The return value is a standard Tcl completion code (TCL_OK or
+ * TCL_ERROR). The interp's result will be set to hold either the value
+ * of the option given by argvName (if TCL_OK is returned) or an error
+ * message (if TCL_ERROR is returned).
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_ConfigureValue(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Tk_Window tkwin, /* Window corresponding to widgRec. */
+ const Tk_ConfigSpec *specs, /* Describes legal options. */
+ char *widgRec, /* Record whose fields contain current values
+ * for options. */
+ const char *argvName, /* Gives the command-line name for the option
+ * whose value is to be returned. */
+ int flags) /* Used to specify additional flags that must
+ * be present in config specs for them to be
+ * considered. */
+{
+ Tk_ConfigSpec *specPtr;
+ int needFlags, hateFlags;
+ Tcl_FreeProc *freeProc;
+ const char *result;
+ char buffer[200];
+
+ needFlags = flags & ~(TK_CONFIG_USER_BIT - 1);
+ if (Tk_Depth(tkwin) <= 1) {
+ hateFlags = TK_CONFIG_COLOR_ONLY;
+ } else {
+ hateFlags = TK_CONFIG_MONO_ONLY;
+ }
+
+ /*
+ * Get the build of the config for this interpreter.
+ */
+
+ specPtr = GetCachedSpecs(interp, specs);
+
+ specPtr = FindConfigSpec(interp, specPtr, argvName, needFlags, hateFlags);
+ if (specPtr == NULL) {
+ return TCL_ERROR;
+ }
+ result = FormatConfigValue(interp, tkwin, specPtr, widgRec, buffer,
+ &freeProc);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(result, -1));
+ if (freeProc != NULL) {
+ if ((freeProc == TCL_DYNAMIC) || (freeProc == (Tcl_FreeProc *) free)) {
+ ckfree((char *) result);
+ } else {
+ freeProc((char *) result);
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_FreeOptions --
+ *
+ * Free up all resources associated with configuration options.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Any resource in widgRec that is controlled by a configuration option
+ * (e.g. a Tk_3DBorder or XColor) is freed in the appropriate fashion.
+ *
+ * Notes:
+ * Since this is not looking anything up, this uses the static version of
+ * the config specs.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+void
+Tk_FreeOptions(
+ const Tk_ConfigSpec *specs, /* Describes legal options. */
+ char *widgRec, /* Record whose fields contain current values
+ * for options. */
+ Display *display, /* X display; needed for freeing some
+ * resources. */
+ int needFlags) /* Used to specify additional flags that must
+ * be present in config specs for them to be
+ * considered. */
+{
+ register const Tk_ConfigSpec *specPtr;
+ char *ptr;
+
+ for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) {
+ if ((specPtr->specFlags & needFlags) != needFlags) {
+ continue;
+ }
+ ptr = widgRec + specPtr->offset;
+ switch (specPtr->type) {
+ case TK_CONFIG_STRING:
+ if (*((char **) ptr) != NULL) {
+ ckfree(*((char **) ptr));
+ *((char **) ptr) = NULL;
+ }
+ break;
+ case TK_CONFIG_COLOR:
+ if (*((XColor **) ptr) != NULL) {
+ Tk_FreeColor(*((XColor **) ptr));
+ *((XColor **) ptr) = NULL;
+ }
+ break;
+ case TK_CONFIG_FONT:
+ Tk_FreeFont(*((Tk_Font *) ptr));
+ *((Tk_Font *) ptr) = NULL;
+ break;
+ case TK_CONFIG_BITMAP:
+ if (*((Pixmap *) ptr) != None) {
+ Tk_FreeBitmap(display, *((Pixmap *) ptr));
+ *((Pixmap *) ptr) = None;
+ }
+ break;
+ case TK_CONFIG_BORDER:
+ if (*((Tk_3DBorder *) ptr) != NULL) {
+ Tk_Free3DBorder(*((Tk_3DBorder *) ptr));
+ *((Tk_3DBorder *) ptr) = NULL;
+ }
+ break;
+ case TK_CONFIG_CURSOR:
+ case TK_CONFIG_ACTIVE_CURSOR:
+ if (*((Tk_Cursor *) ptr) != NULL) {
+ Tk_FreeCursor(display, *((Tk_Cursor *) ptr));
+ *((Tk_Cursor *) ptr) = NULL;
+ }
+ }
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * GetCachedSpecs --
+ *
+ * Returns a writable per-interpreter (and hence thread-local) copy of
+ * the given spec-table with (some of) the char* fields converted into
+ * Tk_Uid fields; this copy will be released when the interpreter
+ * terminates (during AssocData cleanup).
+ *
+ * Results:
+ * A pointer to the copied table.
+ *
+ * Notes:
+ * The conversion to Tk_Uid is only done the first time, when the table
+ * copy is taken. After that, the table is assumed to have Tk_Uids where
+ * they are needed. The time of deletion of the caches isn't very
+ * important unless you've got a lot of code that uses Tk_ConfigureWidget
+ * (or *Info or *Value} when the interpreter is being deleted.
+ *
+ *--------------------------------------------------------------
+ */
+
+static Tk_ConfigSpec *
+GetCachedSpecs(
+ Tcl_Interp *interp, /* Interpreter in which to store the cache. */
+ const Tk_ConfigSpec *staticSpecs)
+ /* Value to cache a copy of; it is also used
+ * as a key into the cache. */
+{
+ Tk_ConfigSpec *cachedSpecs;
+ Tcl_HashTable *specCacheTablePtr;
+ Tcl_HashEntry *entryPtr;
+ int isNew;
+
+ /*
+ * Get (or allocate if it doesn't exist) the hash table that the writable
+ * copies of the widget specs are stored in. In effect, this is
+ * self-initializing code.
+ */
+
+ specCacheTablePtr =
+ Tcl_GetAssocData(interp, "tkConfigSpec.threadTable", NULL);
+ if (specCacheTablePtr == NULL) {
+ specCacheTablePtr = ckalloc(sizeof(Tcl_HashTable));
+ Tcl_InitHashTable(specCacheTablePtr, TCL_ONE_WORD_KEYS);
+ Tcl_SetAssocData(interp, "tkConfigSpec.threadTable",
+ DeleteSpecCacheTable, specCacheTablePtr);
+ }
+
+ /*
+ * Look up or create the hash entry that the constant specs are mapped to,
+ * which will have the writable specs as its associated value.
+ */
+
+ entryPtr = Tcl_CreateHashEntry(specCacheTablePtr, (char *) staticSpecs,
+ &isNew);
+ if (isNew) {
+ unsigned int entrySpace = sizeof(Tk_ConfigSpec);
+ const Tk_ConfigSpec *staticSpecPtr;
+ Tk_ConfigSpec *specPtr;
+
+ /*
+ * OK, no working copy in this interpreter so copy. Need to work out
+ * how much space to allocate first.
+ */
+
+ for (staticSpecPtr=staticSpecs; staticSpecPtr->type!=TK_CONFIG_END;
+ staticSpecPtr++) {
+ entrySpace += sizeof(Tk_ConfigSpec);
+ }
+
+ /*
+ * Now allocate our working copy's space and copy over the contents
+ * from the master copy.
+ */
+
+ cachedSpecs = ckalloc(entrySpace);
+ memcpy(cachedSpecs, staticSpecs, entrySpace);
+ Tcl_SetHashValue(entryPtr, cachedSpecs);
+
+ /*
+ * Finally, go through and replace database names, database classes
+ * and default values with Tk_Uids. This is the bit that has to be
+ * per-thread.
+ */
+
+ for (specPtr=cachedSpecs; specPtr->type!=TK_CONFIG_END; specPtr++) {
+ if (specPtr->argvName != NULL) {
+ if (specPtr->dbName != NULL) {
+ specPtr->dbName = Tk_GetUid(specPtr->dbName);
+ }
+ if (specPtr->dbClass != NULL) {
+ specPtr->dbClass = Tk_GetUid(specPtr->dbClass);
+ }
+ if (specPtr->defValue != NULL) {
+ specPtr->defValue = Tk_GetUid(specPtr->defValue);
+ }
+ }
+ }
+ } else {
+ cachedSpecs = Tcl_GetHashValue(entryPtr);
+ }
+
+ return cachedSpecs;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DeleteSpecCacheTable --
+ *
+ * Delete the per-interpreter copy of all the Tk_ConfigSpec tables which
+ * were stored in the interpreter's assoc-data store.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None (does *not* use any Tk API).
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+DeleteSpecCacheTable(
+ ClientData clientData,
+ Tcl_Interp *interp)
+{
+ Tcl_HashTable *tablePtr = clientData;
+ Tcl_HashEntry *entryPtr;
+ Tcl_HashSearch search;
+
+ for (entryPtr = Tcl_FirstHashEntry(tablePtr,&search); entryPtr != NULL;
+ entryPtr = Tcl_NextHashEntry(&search)) {
+ /*
+ * Someone else deallocates the Tk_Uids themselves.
+ */
+
+ ckfree(Tcl_GetHashValue(entryPtr));
+ }
+ Tcl_DeleteHashTable(tablePtr);
+ ckfree(tablePtr);
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkOldTest.c b/tk8.6/generic/tkOldTest.c
new file mode 100644
index 0000000..948883d
--- /dev/null
+++ b/tk8.6/generic/tkOldTest.c
@@ -0,0 +1,410 @@
+/*
+ * tkOldTest.c --
+ *
+ * This file contains C command functions for additional Tcl
+ * commands that are used to test Tk's support for legacy
+ * interfaces. These commands are not normally included in Tcl/Tk
+ * applications; they're only used for testing.
+ *
+ * Copyright (c) 1993-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
+ * Contributions by Don Porter, NIST, 2007. (not subject to US copyright)
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#define USE_OLD_IMAGE
+#ifndef USE_TCL_STUBS
+# define USE_TCL_STUBS
+#endif
+#ifndef USE_TK_STUBS
+# define USE_TK_STUBS
+#endif
+#include "tkInt.h"
+
+/*
+ * The following data structure represents the master for a test image:
+ */
+
+typedef struct TImageMaster {
+ Tk_ImageMaster master; /* Tk's token for image master. */
+ Tcl_Interp *interp; /* Interpreter for application. */
+ int width, height; /* Dimensions of image. */
+ char *imageName; /* Name of image (malloc-ed). */
+ char *varName; /* Name of variable in which to log events for
+ * image (malloc-ed). */
+} TImageMaster;
+
+/*
+ * The following data structure represents a particular use of a particular
+ * test image.
+ */
+
+typedef struct TImageInstance {
+ TImageMaster *masterPtr; /* Pointer to master for image. */
+ XColor *fg; /* Foreground color for drawing in image. */
+ GC gc; /* Graphics context for drawing in image. */
+} TImageInstance;
+
+/*
+ * The type record for test images:
+ */
+
+static int ImageCreate(Tcl_Interp *interp,
+ char *name, int argc, char **argv,
+ Tk_ImageType *typePtr, Tk_ImageMaster master,
+ ClientData *clientDataPtr);
+static ClientData ImageGet(Tk_Window tkwin, ClientData clientData);
+static void ImageDisplay(ClientData clientData,
+ Display *display, Drawable drawable,
+ int imageX, int imageY, int width,
+ int height, int drawableX,
+ int drawableY);
+static void ImageFree(ClientData clientData, Display *display);
+static void ImageDelete(ClientData clientData);
+
+static Tk_ImageType imageType = {
+ "oldtest", /* name */
+ (Tk_ImageCreateProc *) ImageCreate, /* createProc */
+ ImageGet, /* getProc */
+ ImageDisplay, /* displayProc */
+ ImageFree, /* freeProc */
+ ImageDelete, /* deleteProc */
+ NULL, /* postscriptPtr */
+ NULL, /* nextPtr */
+ NULL
+};
+
+/*
+ * Forward declarations for functions defined later in this file:
+ */
+
+static int ImageObjCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj * const objv[]);
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkOldTestInit --
+ *
+ * This function performs initialization for the Tk test suite
+ * extensions for testing support for legacy interfaces.
+ *
+ * Results:
+ * Returns a standard Tcl completion code, and leaves an error message in
+ * the interp's result if an error occurs.
+ *
+ * Side effects:
+ * Creates several test commands.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkOldTestInit(
+ Tcl_Interp *interp)
+{
+ static int initialized = 0;
+
+ if (!initialized) {
+ initialized = 1;
+ Tk_CreateImageType(&imageType);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImageCreate --
+ *
+ * This function is called by the Tk image code to create "oldtest" images.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * The data structure for a new image is allocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+ImageCreate(
+ Tcl_Interp *interp, /* Interpreter for application containing
+ * image. */
+ char *name, /* Name to use for image. */
+ int argc, /* Number of arguments. */
+ char **argv, /* Argument strings for options (doesn't
+ * include image name or type). */
+ Tk_ImageType *typePtr, /* Pointer to our type record (not used). */
+ Tk_ImageMaster master, /* Token for image, to be used by us in later
+ * callbacks. */
+ ClientData *clientDataPtr) /* Store manager's token for image here; it
+ * will be returned in later callbacks. */
+{
+ TImageMaster *timPtr;
+ const char *varName;
+ int i;
+
+ varName = "log";
+ for (i = 0; i < argc; i += 2) {
+ if (strcmp(argv[i], "-variable") != 0) {
+ Tcl_AppendResult(interp, "bad option name \"",
+ argv[i], "\"", NULL);
+ return TCL_ERROR;
+ }
+ if ((i+1) == argc) {
+ Tcl_AppendResult(interp, "no value given for \"",
+ argv[i], "\" option", NULL);
+ return TCL_ERROR;
+ }
+ varName = argv[i+1];
+ }
+
+ timPtr = ckalloc(sizeof(TImageMaster));
+ timPtr->master = master;
+ timPtr->interp = interp;
+ timPtr->width = 30;
+ timPtr->height = 15;
+ timPtr->imageName = ckalloc(strlen(name) + 1);
+ strcpy(timPtr->imageName, name);
+ timPtr->varName = ckalloc(strlen(varName) + 1);
+ strcpy(timPtr->varName, varName);
+ Tcl_CreateObjCommand(interp, name, ImageObjCmd, timPtr, NULL);
+ *clientDataPtr = timPtr;
+ Tk_ImageChanged(master, 0, 0, 30, 15, 30, 15);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImageObjCmd --
+ *
+ * This function implements the commands corresponding to individual
+ * images.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * Forces windows to be created.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+ImageObjCmd(
+ ClientData clientData, /* Main window for application. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument strings. */
+{
+ TImageMaster *timPtr = clientData;
+ int x, y, width, height;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ if (strcmp(Tcl_GetString(objv[1]), "changed") == 0) {
+ if (objc != 8) {
+ Tcl_WrongNumArgs(interp, 1, objv, "changed x y width height"
+ " imageWidth imageHeight");
+ return TCL_ERROR;
+ }
+ if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[4], &width) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[5], &height) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[6], &timPtr->width) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[7], &timPtr->height) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ Tk_ImageChanged(timPtr->master, x, y, width, height, timPtr->width,
+ timPtr->height);
+ } else {
+ Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[1]),
+ "\": must be changed", NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImageGet --
+ *
+ * This function is called by Tk to set things up for using a test image
+ * in a particular widget.
+ *
+ * Results:
+ * The return value is a token for the image instance, which is used in
+ * future callbacks to ImageDisplay and ImageFree.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static ClientData
+ImageGet(
+ Tk_Window tkwin, /* Token for window in which image will be
+ * used. */
+ ClientData clientData) /* Pointer to TImageMaster for image. */
+{
+ TImageMaster *timPtr = clientData;
+ TImageInstance *instPtr;
+ char buffer[100];
+ XGCValues gcValues;
+
+ sprintf(buffer, "%s get", timPtr->imageName);
+ Tcl_SetVar2(timPtr->interp, timPtr->varName, NULL, buffer,
+ TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
+
+ instPtr = ckalloc(sizeof(TImageInstance));
+ instPtr->masterPtr = timPtr;
+ instPtr->fg = Tk_GetColor(timPtr->interp, tkwin, "#ff0000");
+ gcValues.foreground = instPtr->fg->pixel;
+ instPtr->gc = Tk_GetGC(tkwin, GCForeground, &gcValues);
+ return instPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImageDisplay --
+ *
+ * This function is invoked to redisplay part or all of an image in a
+ * given drawable.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The image gets partially redrawn, as an "X" that shows the exact
+ * redraw area.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ImageDisplay(
+ ClientData clientData, /* Pointer to TImageInstance for image. */
+ Display *display, /* Display to use for drawing. */
+ Drawable drawable, /* Where to redraw image. */
+ int imageX, int imageY, /* Origin of area to redraw, relative to
+ * origin of image. */
+ int width, int height, /* Dimensions of area to redraw. */
+ int drawableX, int drawableY)
+ /* Coordinates in drawable corresponding to
+ * imageX and imageY. */
+{
+ TImageInstance *instPtr = clientData;
+ char buffer[200 + TCL_INTEGER_SPACE * 6];
+
+ sprintf(buffer, "%s display %d %d %d %d %d %d",
+ instPtr->masterPtr->imageName, imageX, imageY, width, height,
+ drawableX, drawableY);
+ Tcl_SetVar2(instPtr->masterPtr->interp, instPtr->masterPtr->varName, NULL,
+ buffer, TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
+ if (width > (instPtr->masterPtr->width - imageX)) {
+ width = instPtr->masterPtr->width - imageX;
+ }
+ if (height > (instPtr->masterPtr->height - imageY)) {
+ height = instPtr->masterPtr->height - imageY;
+ }
+ XDrawRectangle(display, drawable, instPtr->gc, drawableX, drawableY,
+ (unsigned) (width-1), (unsigned) (height-1));
+ XDrawLine(display, drawable, instPtr->gc, drawableX, drawableY,
+ (int) (drawableX + width - 1), (int) (drawableY + height - 1));
+ XDrawLine(display, drawable, instPtr->gc, drawableX,
+ (int) (drawableY + height - 1),
+ (int) (drawableX + width - 1), drawableY);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImageFree --
+ *
+ * This function is called when an instance of an image is no longer
+ * used.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Information related to the instance is freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ImageFree(
+ ClientData clientData, /* Pointer to TImageInstance for instance. */
+ Display *display) /* Display where image was to be drawn. */
+{
+ TImageInstance *instPtr = clientData;
+ char buffer[200];
+
+ sprintf(buffer, "%s free", instPtr->masterPtr->imageName);
+ Tcl_SetVar2(instPtr->masterPtr->interp, instPtr->masterPtr->varName, NULL,
+ buffer, TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
+ Tk_FreeColor(instPtr->fg);
+ Tk_FreeGC(display, instPtr->gc);
+ ckfree(instPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImageDelete --
+ *
+ * This function is called to clean up a test image when an application
+ * goes away.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Information about the image is deleted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ImageDelete(
+ ClientData clientData) /* Pointer to TImageMaster for image. When
+ * this function is called, no more instances
+ * exist. */
+{
+ TImageMaster *timPtr = clientData;
+ char buffer[100];
+
+ sprintf(buffer, "%s delete", timPtr->imageName);
+ Tcl_SetVar2(timPtr->interp, timPtr->varName, NULL, buffer,
+ TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
+
+ Tcl_DeleteCommand(timPtr->interp, timPtr->imageName);
+ ckfree(timPtr->imageName);
+ ckfree(timPtr->varName);
+ ckfree(timPtr);
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkOption.c b/tk8.6/generic/tkOption.c
new file mode 100644
index 0000000..713a6d5
--- /dev/null
+++ b/tk8.6/generic/tkOption.c
@@ -0,0 +1,1602 @@
+/*
+ * tkOption.c --
+ *
+ * This module contains functions to manage the option database, which
+ * allows various strings to be associated with windows either by name or
+ * by class or both.
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "tkInt.h"
+
+/*
+ * The option database is stored as one tree for each main window. Each name
+ * or class field in an option is associated with a node or leaf of the tree.
+ * For example, the options "x.y.z" and "x.y*a" each correspond to three nodes
+ * in the tree; they share the nodes "x" and "x.y", but have different leaf
+ * nodes. One of the following structures exists for each node or leaf in the
+ * option tree. It is actually stored as part of the parent node, and
+ * describes a particular child of the parent.
+ *
+ * The structure of the option db tree is a little confusing. There are four
+ * different kinds of nodes in the tree:
+ * interior class nodes
+ * interior name nodes
+ * leaf class nodes
+ * leaf name nodes
+ *
+ * All interior nodes refer to _window_ classes and names; all leaf nodes
+ * refer to _option_ classes and names. When looking for a particular option,
+ * therefore, you must compare interior node values to corresponding window
+ * values, and compare leaf node values to corresponding option values.
+ *
+ * The tree is actually stored in a collection of arrays; there is one each
+ * combination of WILDCARD/EXACT and CLASS/NAME and NODE/LEAF. The NODE arrays
+ * contain the interior nodes of the tree; each element has a pointer to an
+ * array of elements which are the leaves of the tree. The LEAF arrays, rather
+ * than holding the leaves of the tree, hold a cached subset of the option
+ * database, consisting of the values of all defined options for a single
+ * window, and some additional information about each ancestor of the window
+ * (since some options may be inherited from a parent), all the way back to
+ * the root window.
+ *
+ * Each time a call is made to Tk_GetOption, Tk will attempt to use the cached
+ * information to satisfy the lookup. If the call is for a window other than
+ * that for which options are currently cached, the portion of the cache that
+ * contains information for common ancestors of the two windows is retained
+ * and the remainder is discarded and rebuilt with new information for the new
+ * window.
+ */
+
+typedef struct Element {
+ Tk_Uid nameUid; /* Name or class from one element of an option
+ * spec. */
+ union {
+ struct ElArray *arrayPtr;
+ /* If this is an intermediate node, a pointer
+ * to a structure describing the remaining
+ * elements of all options whose prefixes are
+ * the same up through this element. */
+ Tk_Uid valueUid; /* For leaf nodes, this is the string value of
+ * the option. */
+ } child;
+ int priority; /* Used to select among matching options.
+ * Includes both the priority level and a
+ * serial #. Greater value means higher
+ * priority. Irrelevant except in leaf
+ * nodes. */
+ int flags; /* OR-ed combination of bits. See below for
+ * values. */
+} Element;
+
+/*
+ * Flags in Element structures:
+ *
+ * CLASS - Non-zero means this element refers to a class, zero
+ * means this element refers to a name.
+ * NODE - Zero means this is a leaf element (the child field is
+ * a value, not a pointer to another node). One means
+ * this is a node element.
+ * WILDCARD - Non-zero means this there was a star in the original
+ * specification just before this element. Zero means
+ * there was a dot.
+ */
+
+#define TYPE_MASK 0x7
+
+#define CLASS 0x1
+#define NODE 0x2
+#define WILDCARD 0x4
+
+#define EXACT_LEAF_NAME 0x0
+#define EXACT_LEAF_CLASS 0x1
+#define EXACT_NODE_NAME 0x2
+#define EXACT_NODE_CLASS 0x3
+#define WILDCARD_LEAF_NAME 0x4
+#define WILDCARD_LEAF_CLASS 0x5
+#define WILDCARD_NODE_NAME 0x6
+#define WILDCARD_NODE_CLASS 0x7
+
+/*
+ * The following structure is used to manage a dynamic array of Elements.
+ * These structures are used for two purposes: to store the contents of a node
+ * in the option tree, and for the option stacks described below.
+ */
+
+typedef struct ElArray {
+ int arraySize; /* Number of elements actually allocated in
+ * the "els" array. */
+ int numUsed; /* Number of elements currently in use out of
+ * els. */
+ Element *nextToUse; /* Pointer to &els[numUsed]. */
+ Element els[1]; /* Array of structures describing children of
+ * this node. The array will actually contain
+ * enough elements for all of the children
+ * (and even a few extras, perhaps). This must
+ * be the last field in the structure. */
+} ElArray;
+
+#define EL_ARRAY_SIZE(numEls) ((unsigned) (sizeof(ElArray) \
+ + ((numEls)-1)*sizeof(Element)))
+#define INITIAL_SIZE 5
+
+/*
+ * In addition to the option tree, which is a relatively static structure,
+ * there are eight additional structures called "stacks", which are used to
+ * speed up queries into the option database. The stack structures are
+ * designed for the situation where an individual widget makes repeated
+ * requests for its particular options. The requests differ only in their last
+ * name/class, so during the first request we extract all the options
+ * pertaining to the particular widget and save them in a stack-like cache;
+ * subsequent requests for the same widget can search the cache relatively
+ * quickly. In fact, the cache is a hierarchical one, storing a list of
+ * relevant options for this widget and all of its ancestors up to the
+ * application root; hence the name "stack".
+ *
+ * Each of the eight stacks consists of an array of Elements, ordered in terms
+ * of levels in the window hierarchy. All the elements relevant for the
+ * top-level widget appear first in the array, followed by all those from the
+ * next-level widget on the path to the current widget, etc. down to those for
+ * the current widget.
+ *
+ * Cached information is divided into eight stacks according to the CLASS,
+ * NODE, and WILDCARD flags. Leaf and non-leaf information is kept separate to
+ * speed up individual probes (non-leaf information is only relevant when
+ * building the stacks, but isn't relevant when making probes; similarly, only
+ * non-leaf information is relevant when the stacks are being extended to the
+ * next widget down in the widget hierarchy). Wildcard elements are handled
+ * separately from "exact" elements because once they appear at a particular
+ * level in the stack they remain active for all deeper levels; exact elements
+ * are only relevant at a particular level. For example, when searching for
+ * options relevant in a particular window, the entire wildcard stacks get
+ * checked, but only the portions of the exact stacks that pertain to the
+ * window's parent. Lastly, name and class stacks are kept separate because
+ * different search keys are used when searching them; keeping them separate
+ * speeds up the searches.
+ */
+
+#define NUM_STACKS 8
+
+/*
+ * One of the following structures is used to keep track of each level in the
+ * stacks.
+ */
+
+typedef struct StackLevel {
+ TkWindow *winPtr; /* Window corresponding to this stack
+ * level. */
+ int bases[NUM_STACKS]; /* For each stack, index of first element on
+ * stack corresponding to this level (used to
+ * restore "numUsed" fields when popping out
+ * of a level. */
+} StackLevel;
+
+typedef struct {
+ int initialized; /* 0 means the ThreadSpecific Data structure
+ * for the current thread needs to be
+ * initialized. */
+ ElArray *stacks[NUM_STACKS];
+ TkWindow *cachedWindow; /* Lowest-level window currently loaded in
+ * stacks at present. NULL means stacks have
+ * never been used, or have been invalidated
+ * because of a change to the database. */
+ /*
+ * Information about all of the stack levels that are currently active.
+ * This array grows dynamically to become as large as needed.
+ */
+
+ StackLevel *levels; /* Array describing current stack. */
+ int numLevels; /* Total space allocated. */
+ int curLevel; /* Highest level currently in use. Note:
+ * curLevel is never 0! (I don't remember why
+ * anymore...) */
+ int serial; /* A serial number for all options entered
+ * into the database so far. It increments on
+ * each addition to the option database. It is
+ * used in computing option priorities, so
+ * that the most recent entry wins when
+ * choosing between options at the same
+ * priority level. */
+ Element defaultMatch; /* Special "no match" Element to use as
+ * default for searches.*/
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+
+/*
+ * Forward declarations for functions defined in this file:
+ */
+
+static int AddFromString(Tcl_Interp *interp, Tk_Window tkwin,
+ char *string, int priority);
+static void ClearOptionTree(ElArray *arrayPtr);
+static ElArray * ExtendArray(ElArray *arrayPtr, Element *elPtr);
+static void ExtendStacks(ElArray *arrayPtr, int leaf);
+static int GetDefaultOptions(Tcl_Interp *interp,
+ TkWindow *winPtr);
+static ElArray * NewArray(int numEls);
+static void OptionThreadExitProc(ClientData clientData);
+static void OptionInit(TkMainInfo *mainPtr);
+static int ParsePriority(Tcl_Interp *interp, const char *string);
+static int ReadOptionFile(Tcl_Interp *interp, Tk_Window tkwin,
+ const char *fileName, int priority);
+static void SetupStacks(TkWindow *winPtr, int leaf);
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_AddOption --
+ *
+ * Add a new option to the option database.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Information is added to the option database.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_AddOption(
+ Tk_Window tkwin, /* Window token; option will be associated
+ * with main window for this window. */
+ const char *name, /* Multi-element name of option. */
+ const char *value, /* String value for option. */
+ int priority) /* Overall priority level to use for this
+ * option, such as TK_USER_DEFAULT_PRIO or
+ * TK_INTERACTIVE_PRIO. Must be between 0 and
+ * TK_MAX_PRIO. */
+{
+ TkWindow *winPtr = ((TkWindow *) tkwin)->mainPtr->winPtr;
+ register ElArray **arrayPtrPtr;
+ register Element *elPtr;
+ Element newEl;
+ register const char *p;
+ const char *field;
+ int count, firstField;
+ ptrdiff_t length;
+#define TMP_SIZE 100
+ char tmp[TMP_SIZE+1];
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (winPtr->mainPtr->optionRootPtr == NULL) {
+ OptionInit(winPtr->mainPtr);
+ }
+ tsdPtr->cachedWindow = NULL;/* Invalidate the cache. */
+
+ /*
+ * Compute the priority for the new element, including both the overall
+ * level and the serial number (to disambiguate with the level).
+ */
+
+ if (priority < 0) {
+ priority = 0;
+ } else if (priority > TK_MAX_PRIO) {
+ priority = TK_MAX_PRIO;
+ }
+ newEl.priority = (priority << 24) + tsdPtr->serial;
+ tsdPtr->serial++;
+
+ /*
+ * Parse the option one field at a time.
+ */
+
+ arrayPtrPtr = &(((TkWindow *) tkwin)->mainPtr->optionRootPtr);
+ p = name;
+ for (firstField = 1; ; firstField = 0) {
+ /*
+ * Scan the next field from the name and convert it to a Tk_Uid. Must
+ * copy the field before calling Tk_Uid, so that a terminating NULL
+ * may be added without modifying the source string.
+ */
+
+ if (*p == '*') {
+ newEl.flags = WILDCARD;
+ p++;
+ } else {
+ newEl.flags = 0;
+ }
+ field = p;
+ while ((*p != 0) && (*p != '.') && (*p != '*')) {
+ p++;
+ }
+ length = p - field;
+ if (length > TMP_SIZE) {
+ length = TMP_SIZE;
+ }
+ strncpy(tmp, field, (size_t) length);
+ tmp[length] = 0;
+ newEl.nameUid = Tk_GetUid(tmp);
+ if (isupper(UCHAR(*field))) {
+ newEl.flags |= CLASS;
+ }
+
+ if (*p != 0) {
+ /*
+ * New element will be a node. If this option can't possibly apply
+ * to this main window, then just skip it. Otherwise, add it to
+ * the parent, if it isn't already there, and descend into it.
+ */
+
+ newEl.flags |= NODE;
+ if (firstField && !(newEl.flags & WILDCARD)
+ && (newEl.nameUid != winPtr->nameUid)
+ && (newEl.nameUid != winPtr->classUid)) {
+ return;
+ }
+ for (elPtr = (*arrayPtrPtr)->els, count = (*arrayPtrPtr)->numUsed;
+ ; elPtr++, count--) {
+ if (count == 0) {
+ newEl.child.arrayPtr = NewArray(5);
+ *arrayPtrPtr = ExtendArray(*arrayPtrPtr, &newEl);
+ arrayPtrPtr = &((*arrayPtrPtr)
+ ->nextToUse[-1].child.arrayPtr);
+ break;
+ }
+ if ((elPtr->nameUid == newEl.nameUid)
+ && (elPtr->flags == newEl.flags)) {
+ arrayPtrPtr = &(elPtr->child.arrayPtr);
+ break;
+ }
+ }
+ if (*p == '.') {
+ p++;
+ }
+ } else {
+ /*
+ * New element is a leaf. Add it to the parent, if it isn't
+ * already there. If it exists already, keep whichever value has
+ * highest priority.
+ */
+
+ newEl.child.valueUid = Tk_GetUid(value);
+ for (elPtr = (*arrayPtrPtr)->els, count = (*arrayPtrPtr)->numUsed;
+ ; elPtr++, count--) {
+ if (count == 0) {
+ *arrayPtrPtr = ExtendArray(*arrayPtrPtr, &newEl);
+ return;
+ }
+ if ((elPtr->nameUid == newEl.nameUid)
+ && (elPtr->flags == newEl.flags)) {
+ if (elPtr->priority < newEl.priority) {
+ elPtr->priority = newEl.priority;
+ elPtr->child.valueUid = newEl.child.valueUid;
+ }
+ return;
+ }
+ }
+ }
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_GetOption --
+ *
+ * Retrieve an option from the option database.
+ *
+ * Results:
+ * The return value is the value specified in the option database for the
+ * given name and class on the given window. If there is nothing
+ * specified in the database for that option, then NULL is returned.
+ *
+ * Side effects:
+ * The internal caches used to speed up option mapping may be modified,
+ * if this tkwin is different from the last tkwin used for option
+ * retrieval.
+ *
+ *--------------------------------------------------------------
+ */
+
+Tk_Uid
+Tk_GetOption(
+ Tk_Window tkwin, /* Token for window that option is associated
+ * with. */
+ const char *name, /* Name of option. */
+ const char *className) /* Class of option. NULL means there is no
+ * class for this option: just check for
+ * name. */
+{
+ Tk_Uid nameId, classId = NULL;
+ char *masqName;
+ register Element *elPtr, *bestPtr;
+ register int count;
+ StackLevel *levelPtr;
+ int stackDepth[NUM_STACKS];
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ /*
+ * Note: no need to call OptionInit here: it will be done by the
+ * SetupStacks call below (squeeze out those nanoseconds).
+ */
+
+ if (tkwin != (Tk_Window) tsdPtr->cachedWindow) {
+ SetupStacks((TkWindow *) tkwin, 1);
+ }
+
+ /*
+ * Get a default "best" match.
+ */
+
+ bestPtr = &tsdPtr->defaultMatch;
+
+ /*
+ * For megawidget support, we want to have some widget options masquerade
+ * as options for other widgets. For example, a combobox has a button in
+ * it; this button ought to pick up the *Button.background, etc., options.
+ * But because the class of the widget is Combobox, our normal search
+ * won't get that option.
+ *
+ * To work around this, the option name field syntax was extended to allow
+ * for a "." in the name; if this character occurs in the name, then it
+ * indicates that this name contains a new window class and an option
+ * name, ie, "Button.foreground". If we see this form in the name field,
+ * we query the option database directly (since the option stacks will not
+ * have the information we need).
+ */
+
+ masqName = strchr(name, (int)'.');
+ if (masqName != NULL) {
+ /*
+ * This option is masquerading with a different window class. Search
+ * the stack to the depth it was before the current window's
+ * information was pushed (the value for which is stored in the bases
+ * field).
+ */
+
+ levelPtr = &tsdPtr->levels[tsdPtr->curLevel];
+ nameId = Tk_GetUid(masqName+1);
+ for (count = 0; count < NUM_STACKS; count++) {
+ stackDepth[count] = levelPtr->bases[count];
+ }
+ } else {
+ /*
+ * No option masquerading here. Just use the current level to get the
+ * stack depths.
+ */
+
+ nameId = Tk_GetUid(name);
+ for (count = 0; count < NUM_STACKS; count++) {
+ stackDepth[count] = tsdPtr->stacks[count]->numUsed;
+ }
+ }
+
+ /*
+ * Probe the stacks for matches.
+ */
+
+ for (elPtr = tsdPtr->stacks[EXACT_LEAF_NAME]->els,
+ count = stackDepth[EXACT_LEAF_NAME]; count > 0;
+ elPtr++, count--) {
+ if ((elPtr->nameUid == nameId)
+ && (elPtr->priority > bestPtr->priority)) {
+ bestPtr = elPtr;
+ }
+ }
+ for (elPtr = tsdPtr->stacks[WILDCARD_LEAF_NAME]->els,
+ count = stackDepth[WILDCARD_LEAF_NAME]; count > 0;
+ elPtr++, count--) {
+ if ((elPtr->nameUid == nameId)
+ && (elPtr->priority > bestPtr->priority)) {
+ bestPtr = elPtr;
+ }
+ }
+
+ if (className != NULL) {
+ classId = Tk_GetUid(className);
+ for (elPtr = tsdPtr->stacks[EXACT_LEAF_CLASS]->els,
+ count = stackDepth[EXACT_LEAF_CLASS]; count > 0;
+ elPtr++, count--) {
+ if ((elPtr->nameUid == classId)
+ && (elPtr->priority > bestPtr->priority)) {
+ bestPtr = elPtr;
+ }
+ }
+ for (elPtr = tsdPtr->stacks[WILDCARD_LEAF_CLASS]->els,
+ count = stackDepth[WILDCARD_LEAF_CLASS]; count > 0;
+ elPtr++, count--) {
+ if ((elPtr->nameUid == classId)
+ && (elPtr->priority > bestPtr->priority)) {
+ bestPtr = elPtr;
+ }
+ }
+ }
+
+ /*
+ * If this option was masquerading with a different window class, probe
+ * the option database now. Note that this will be inefficient if the
+ * option database is densely populated, or if the widget has many
+ * masquerading options.
+ */
+
+ if (masqName != NULL) {
+ char *masqClass;
+ Tk_Uid nodeId, winClassId, winNameId;
+ unsigned int classNameLength;
+ register Element *nodePtr, *leafPtr;
+ static const int searchOrder[] = {
+ EXACT_NODE_NAME, WILDCARD_NODE_NAME, EXACT_NODE_CLASS,
+ WILDCARD_NODE_CLASS, -1
+ };
+ const int *currentPtr;
+ int currentStack, leafCount;
+
+ /*
+ * Extract the masquerade class name from the name field.
+ */
+
+ classNameLength = (unsigned) (masqName - name);
+ masqClass = ckalloc(classNameLength + 1);
+ strncpy(masqClass, name, classNameLength);
+ masqClass[classNameLength] = '\0';
+
+ winClassId = Tk_GetUid(masqClass);
+ ckfree(masqClass);
+ winNameId = ((TkWindow *) tkwin)->nameUid;
+
+ levelPtr = &tsdPtr->levels[tsdPtr->curLevel];
+
+ for (currentPtr = searchOrder; *currentPtr != -1; currentPtr++) {
+ currentStack = *currentPtr;
+ nodePtr = tsdPtr->stacks[currentStack]->els;
+ count = levelPtr->bases[currentStack];
+
+ /*
+ * For wildcard stacks, check all entries; for non-wildcard
+ * stacks, only check things that matched in the parent.
+ */
+
+ if (!(currentStack & WILDCARD)) {
+ nodePtr += levelPtr[-1].bases[currentStack];
+ count -= levelPtr[-1].bases[currentStack];
+ }
+
+ if (currentStack & CLASS) {
+ nodeId = winClassId;
+ } else {
+ nodeId = winNameId;
+ }
+
+ for ( ; count > 0; nodePtr++, count--) {
+ if (nodePtr->nameUid == nodeId) {
+ leafPtr = nodePtr->child.arrayPtr->els;
+ leafCount = nodePtr->child.arrayPtr->numUsed;
+ for ( ; leafCount > 0; leafPtr++, leafCount--) {
+ if (leafPtr->flags & CLASS && className != NULL) {
+ if (leafPtr->nameUid == classId &&
+ leafPtr->priority > bestPtr->priority) {
+ bestPtr = leafPtr;
+ }
+ } else {
+ if (leafPtr->nameUid == nameId &&
+ leafPtr->priority > bestPtr->priority) {
+ bestPtr = leafPtr;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return bestPtr->child.valueUid;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_OptionObjCmd --
+ *
+ * This function is invoked to process the "option" 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_OptionObjCmd(
+ ClientData clientData, /* Main window associated with interpreter. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of Tcl_Obj arguments. */
+ Tcl_Obj *const objv[]) /* Tcl_Obj arguments. */
+{
+ Tk_Window tkwin = clientData;
+ int index, result;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ static const char *const optionCmds[] = {
+ "add", "clear", "get", "readfile", NULL
+ };
+ enum optionVals {
+ OPTION_ADD, OPTION_CLEAR, OPTION_GET, OPTION_READFILE
+ };
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "cmd arg ?arg ...?");
+ return TCL_ERROR;
+ }
+
+ result = Tcl_GetIndexFromObjStruct(interp, objv[1], optionCmds,
+ sizeof(char *), "option", 0, &index);
+ if (result != TCL_OK) {
+ return result;
+ }
+
+ result = TCL_OK;
+ switch ((enum optionVals) index) {
+ case OPTION_ADD: {
+ int priority;
+
+ if ((objc != 4) && (objc != 5)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "pattern value ?priority?");
+ return TCL_ERROR;
+ }
+
+ if (objc == 4) {
+ priority = TK_INTERACTIVE_PRIO;
+ } else {
+ priority = ParsePriority(interp, Tcl_GetString(objv[4]));
+ if (priority < 0) {
+ return TCL_ERROR;
+ }
+ }
+ Tk_AddOption(tkwin, Tcl_GetString(objv[2]), Tcl_GetString(objv[3]),
+ priority);
+ break;
+ }
+
+ case OPTION_CLEAR: {
+ TkMainInfo *mainPtr = ((TkWindow *) tkwin)->mainPtr;
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, "");
+ return TCL_ERROR;
+ }
+ if (mainPtr->optionRootPtr != NULL) {
+ ClearOptionTree(mainPtr->optionRootPtr);
+ mainPtr->optionRootPtr = NULL;
+ }
+ tsdPtr->cachedWindow = NULL;
+ break;
+ }
+
+ case OPTION_GET: {
+ Tk_Window window;
+ Tk_Uid value;
+
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window name class");
+ return TCL_ERROR;
+ }
+ window = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin);
+ if (window == NULL) {
+ return TCL_ERROR;
+ }
+ value = Tk_GetOption(window, Tcl_GetString(objv[3]),
+ Tcl_GetString(objv[4]));
+ if (value != NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(value, -1));
+ }
+ break;
+ }
+
+ case OPTION_READFILE: {
+ int priority;
+
+ if ((objc != 3) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "fileName ?priority?");
+ return TCL_ERROR;
+ }
+
+ if (objc == 4) {
+ priority = ParsePriority(interp, Tcl_GetString(objv[3]));
+ if (priority < 0) {
+ return TCL_ERROR;
+ }
+ } else {
+ priority = TK_INTERACTIVE_PRIO;
+ }
+ result = ReadOptionFile(interp, tkwin, Tcl_GetString(objv[2]),
+ priority);
+ break;
+ }
+ }
+ return result;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkOptionDeadWindow --
+ *
+ * This function is called whenever a window is deleted. It cleans up any
+ * option-related stuff associated with the window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Option-related resources are freed. See code below for details.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkOptionDeadWindow(
+ register TkWindow *winPtr) /* Window to be cleaned up. */
+{
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ /*
+ * If this window is in the option stacks, then clear the stacks.
+ *
+ * XXX: OptionThreadExitProc will be invoked before DeleteWindowsExitProc
+ * XXX: if it is thread-specific (which it should be), invalidating the
+ * XXX: tsd. Tk shutdown needs to be verified to handle this correctly.
+ */
+
+ if (tsdPtr->initialized && (winPtr->optionLevel != -1)) {
+ int i;
+
+ for (i = 1; i <= tsdPtr->curLevel; i++) {
+ tsdPtr->levels[i].winPtr->optionLevel = -1;
+ }
+ tsdPtr->curLevel = -1;
+ tsdPtr->cachedWindow = NULL;
+ }
+
+ /*
+ * If this window was a main window, then delete its option database.
+ */
+
+ if ((winPtr->mainPtr != NULL) && (winPtr->mainPtr->winPtr == winPtr)
+ && (winPtr->mainPtr->optionRootPtr != NULL)) {
+ ClearOptionTree(winPtr->mainPtr->optionRootPtr);
+ winPtr->mainPtr->optionRootPtr = NULL;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkOptionClassChanged --
+ *
+ * This function is invoked when a window's class changes. If the window
+ * is on the option cache, this function flushes any information for the
+ * window, since the new class could change what is relevant.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The option cache may be flushed in part or in whole.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkOptionClassChanged(
+ TkWindow *winPtr) /* Window whose class changed. */
+{
+ int i, j, *basePtr;
+ ElArray *arrayPtr;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (winPtr->optionLevel == -1) {
+ return;
+ }
+
+ /*
+ * Find the lowest stack level that refers to this window, then flush all
+ * of the levels above the matching one.
+ */
+
+ for (i = 1; i <= tsdPtr->curLevel; i++) {
+ if (tsdPtr->levels[i].winPtr == winPtr) {
+ for (j = i; j <= tsdPtr->curLevel; j++) {
+ tsdPtr->levels[j].winPtr->optionLevel = -1;
+ }
+ tsdPtr->curLevel = i-1;
+ basePtr = tsdPtr->levels[i].bases;
+ for (j = 0; j < NUM_STACKS; j++) {
+ arrayPtr = tsdPtr->stacks[j];
+ arrayPtr->numUsed = basePtr[j];
+ arrayPtr->nextToUse = &arrayPtr->els[arrayPtr->numUsed];
+ }
+ if (tsdPtr->curLevel <= 0) {
+ tsdPtr->cachedWindow = NULL;
+ } else {
+ tsdPtr->cachedWindow = tsdPtr->levels[tsdPtr->curLevel].winPtr;
+ }
+ break;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ParsePriority --
+ *
+ * Parse a string priority value.
+ *
+ * Results:
+ * The return value is the integer priority level corresponding to
+ * string, or -1 if string doesn't point to a valid priority level. In
+ * this case, an error message is left in the interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ParsePriority(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting. */
+ const char *string) /* Describes a priority level, either
+ * symbolically or numerically. */
+{
+ int priority, c;
+ size_t length;
+
+ c = string[0];
+ length = strlen(string);
+ if ((c == 'w')
+ && (strncmp(string, "widgetDefault", length) == 0)) {
+ return TK_WIDGET_DEFAULT_PRIO;
+ } else if ((c == 's')
+ && (strncmp(string, "startupFile", length) == 0)) {
+ return TK_STARTUP_FILE_PRIO;
+ } else if ((c == 'u')
+ && (strncmp(string, "userDefault", length) == 0)) {
+ return TK_USER_DEFAULT_PRIO;
+ } else if ((c == 'i')
+ && (strncmp(string, "interactive", length) == 0)) {
+ return TK_INTERACTIVE_PRIO;
+ } else {
+ char *end;
+
+ priority = strtoul(string, &end, 0);
+ if ((end == string) || (*end != 0) || (priority < 0)
+ || (priority > 100)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad priority level \"%s\": must be "
+ "widgetDefault, startupFile, userDefault, "
+ "interactive, or a number between 0 and 100", string));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "PRIORITY", NULL);
+ return -1;
+ }
+ }
+ return priority;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AddFromString --
+ *
+ * Given a string containing lines in the standard format for X resources
+ * (see other documentation for details on what this is), parse the
+ * resource specifications and enter them as options for tkwin's main
+ * window.
+ *
+ * Results:
+ * The return value is a standard Tcl return code. In the case of an
+ * error in parsing string, TCL_ERROR will be returned and an error
+ * message will be left in the interp's result. The memory at string is
+ * totally trashed by this function. If you care about its contents, make
+ * a copy before calling here.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+AddFromString(
+ Tcl_Interp *interp, /* Interpreter to use for reporting results. */
+ Tk_Window tkwin, /* Token for window: options are entered for
+ * this window's main window. */
+ char *string, /* String containing option specifiers. */
+ int priority) /* Priority level to use for options in this
+ * string, such as TK_USER_DEFAULT_PRIO or
+ * TK_INTERACTIVE_PRIO. Must be between 0 and
+ * TK_MAX_PRIO. */
+{
+ register char *src, *dst;
+ char *name, *value;
+ int lineNum;
+
+ src = string;
+ lineNum = 1;
+ while (1) {
+ /*
+ * Skip leading white space and empty lines and comment lines, and
+ * check for the end of the spec.
+ */
+
+ while ((*src == ' ') || (*src == '\t')) {
+ src++;
+ }
+ if ((*src == '#') || (*src == '!')) {
+ do {
+ src++;
+ if ((src[0] == '\\') && (src[1] == '\n')) {
+ src += 2;
+ lineNum++;
+ }
+ } while ((*src != '\n') && (*src != 0));
+ }
+ if (*src == '\n') {
+ src++;
+ lineNum++;
+ continue;
+ }
+ if (*src == '\0') {
+ break;
+ }
+
+ /*
+ * Parse off the option name, collapsing out backslash-newline
+ * sequences of course.
+ */
+
+ dst = name = src;
+ while (*src != ':') {
+ if ((*src == '\0') || (*src == '\n')) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "missing colon on line %d", lineNum));
+ Tcl_SetErrorCode(interp, "TK", "OPTIONDB", "COLON", NULL);
+ return TCL_ERROR;
+ }
+ if ((src[0] == '\\') && (src[1] == '\n')) {
+ src += 2;
+ lineNum++;
+ } else {
+ *dst = *src;
+ dst++;
+ src++;
+ }
+ }
+
+ /*
+ * Eliminate trailing white space on the name, and null-terminate
+ * it.
+ */
+
+ while ((dst != name) && ((dst[-1] == ' ') || (dst[-1] == '\t'))) {
+ dst--;
+ }
+ *dst = '\0';
+
+ /*
+ * Skip white space between the name and the value.
+ */
+
+ src++;
+ while ((*src == ' ') || (*src == '\t')) {
+ src++;
+ }
+ if (*src == '\\' && (src[1] == '\t' || src[1] == ' ')) {
+ src++;
+ }
+ if (*src == '\0') {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "missing value on line %d", lineNum));
+ Tcl_SetErrorCode(interp, "TK", "OPTIONDB", "VALUE", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Parse off the value, squeezing out backslash-newline sequences
+ * along the way.
+ */
+
+ dst = value = src;
+ while (*src != '\n') {
+ if (*src == '\0') {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "missing newline on line %d", lineNum));
+ Tcl_SetErrorCode(interp, "TK", "OPTIONDB", "NEWLINE", NULL);
+ return TCL_ERROR;
+ }
+ if (*src == '\\'){
+ if (src[1] == '\n') {
+ src += 2;
+ lineNum++;
+ continue;
+ } else if (src[1] == 'n') {
+ src += 2;
+ *dst++ = '\n';
+ continue;
+ } else if (src[1] == '\\') {
+ ++src;
+ } else if (src[1] >= '0' && src[1] <= '3' && src[2] >= '0' &&
+ src[2] <= '9' && src[3] >= '0' && src[3] <= '9') {
+ *dst++ = ((src[1]&7)<<6) | ((src[2]&7)<<3) | (src[3]&7);
+ src += 4;
+ continue;
+ }
+ }
+ *dst++ = *src++;
+ }
+ *dst = 0;
+
+ /*
+ * Enter the option into the database.
+ */
+
+ Tk_AddOption(tkwin, name, value, priority);
+ src++;
+ lineNum++;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ReadOptionFile --
+ *
+ * Read a file of options ("resources" in the old X terminology) and load
+ * them into the option database.
+ *
+ * Results:
+ * The return value is a standard Tcl return code. In the case of an
+ * error in parsing string, TCL_ERROR will be returned and an error
+ * message will be left in the interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ReadOptionFile(
+ Tcl_Interp *interp, /* Interpreter to use for reporting results. */
+ Tk_Window tkwin, /* Token for window: options are entered for
+ * this window's main window. */
+ const char *fileName, /* Name of file containing options. */
+ int priority) /* Priority level to use for options in this
+ * file, such as TK_USER_DEFAULT_PRIO or
+ * TK_INTERACTIVE_PRIO. Must be between 0 and
+ * TK_MAX_PRIO. */
+{
+ const char *realName;
+ Tcl_Obj *buffer;
+ int result, bufferSize;
+ Tcl_Channel chan;
+ Tcl_DString newName;
+
+ /*
+ * Prevent file system access in a safe interpreter.
+ */
+
+ if (Tcl_IsSafe(interp)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "can't read options from a file in a safe interpreter", -1));
+ Tcl_SetErrorCode(interp, "TK", "SAFE", "OPTION_FILE", NULL);
+ return TCL_ERROR;
+ }
+
+ realName = Tcl_TranslateFileName(interp, fileName, &newName);
+ if (realName == NULL) {
+ return TCL_ERROR;
+ }
+ chan = Tcl_OpenFileChannel(interp, realName, "r", 0);
+ Tcl_DStringFree(&newName);
+ if (chan == NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf("couldn't open \"%s\": %s",
+ fileName, Tcl_PosixError(interp)));
+ return TCL_ERROR;
+ }
+
+ buffer = Tcl_NewObj();
+ Tcl_IncrRefCount(buffer);
+ Tcl_SetChannelOption(NULL, chan, "-encoding", "utf-8");
+ bufferSize = Tcl_ReadChars(chan, buffer, -1, 0);
+ if (bufferSize < 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "error reading file \"%s\": %s",
+ fileName, Tcl_PosixError(interp)));
+ Tcl_Close(NULL, chan);
+ return TCL_ERROR;
+ }
+ Tcl_Close(NULL, chan);
+ result = AddFromString(interp, tkwin, Tcl_GetString(buffer), priority);
+ Tcl_DecrRefCount(buffer);
+ return result;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * NewArray --
+ *
+ * Create a new ElArray structure of a given size.
+ *
+ * Results:
+ * The return value is a pointer to a properly initialized element array
+ * with "numEls" space. The array is marked as having no active elements.
+ *
+ * Side effects:
+ * Memory is allocated.
+ *
+ *--------------------------------------------------------------
+ */
+
+static ElArray *
+NewArray(
+ int numEls) /* How many elements of space to allocate. */
+{
+ register ElArray *arrayPtr = ckalloc(EL_ARRAY_SIZE(numEls));
+
+ arrayPtr->arraySize = numEls;
+ arrayPtr->numUsed = 0;
+ arrayPtr->nextToUse = arrayPtr->els;
+ return arrayPtr;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ExtendArray --
+ *
+ * Add a new element to an array, extending the array if necessary.
+ *
+ * Results:
+ * The return value is a pointer to the new array, which will be
+ * different from arrayPtr if the array got expanded.
+ *
+ * Side effects:
+ * Memory may be allocated or freed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static ElArray *
+ExtendArray(
+ register ElArray *arrayPtr, /* Array to be extended. */
+ register Element *elPtr) /* Element to be copied into array. */
+{
+ /*
+ * If the current array has filled up, make it bigger.
+ */
+
+ if (arrayPtr->numUsed >= arrayPtr->arraySize) {
+ register int newSize = 2*arrayPtr->arraySize;
+
+ arrayPtr = ckrealloc(arrayPtr, EL_ARRAY_SIZE(newSize));
+ arrayPtr->arraySize = newSize;
+ arrayPtr->nextToUse = &arrayPtr->els[arrayPtr->numUsed];
+ }
+
+ *arrayPtr->nextToUse = *elPtr;
+ arrayPtr->nextToUse++;
+ arrayPtr->numUsed++;
+ return arrayPtr;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * SetupStacks --
+ *
+ * Arrange the stacks so that they cache all the option information for a
+ * particular window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The stacks are modified to hold information for tkwin and all its
+ * ancestors in the window hierarchy.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+SetupStacks(
+ TkWindow *winPtr, /* Window for which information is to be
+ * cached. */
+ int leaf) /* Non-zero means this is the leaf window
+ * being probed. Zero means this is an
+ * ancestor of the desired leaf. */
+{
+ int level, i;
+ const int *iPtr;
+ register StackLevel *levelPtr;
+ register ElArray *arrayPtr;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ /*
+ * The following array defines the order in which the current stacks are
+ * searched to find matching entries to add to the stacks. Given the
+ * current priority-based scheme, the order below is no longer relevant;
+ * all that matters is that an element is on the list *somewhere*. The
+ * ordering is a relic of the old days when priorities were determined
+ * differently.
+ */
+
+ static const int searchOrder[] = {WILDCARD_NODE_CLASS, WILDCARD_NODE_NAME,
+ EXACT_NODE_CLASS, EXACT_NODE_NAME, -1};
+
+ if (winPtr->mainPtr->optionRootPtr == NULL) {
+ OptionInit(winPtr->mainPtr);
+ }
+
+ /*
+ * Step 1: make sure that options are cached for this window's parent.
+ */
+
+ if (winPtr->parentPtr != NULL) {
+ level = winPtr->parentPtr->optionLevel;
+ if ((level == -1) || (tsdPtr->cachedWindow == NULL)) {
+ SetupStacks(winPtr->parentPtr, 0);
+ level = winPtr->parentPtr->optionLevel;
+ }
+ level++;
+ } else {
+ level = 1;
+ }
+
+ /*
+ * Step 2: pop extra unneeded information off the stacks and mark those
+ * windows as no longer having cached information.
+ */
+
+ if (tsdPtr->curLevel >= level) {
+ while (tsdPtr->curLevel >= level) {
+ tsdPtr->levels[tsdPtr->curLevel].winPtr->optionLevel = -1;
+ tsdPtr->curLevel--;
+ }
+ levelPtr = &tsdPtr->levels[level];
+ for (i = 0; i < NUM_STACKS; i++) {
+ arrayPtr = tsdPtr->stacks[i];
+ arrayPtr->numUsed = levelPtr->bases[i];
+ arrayPtr->nextToUse = &arrayPtr->els[arrayPtr->numUsed];
+ }
+ }
+ tsdPtr->curLevel = winPtr->optionLevel = level;
+
+ /*
+ * Step 3: if the root database information isn't loaded or isn't valid,
+ * initialize level 0 of the stack from the database root (this only
+ * happens if winPtr is a main window).
+ */
+
+ if ((tsdPtr->curLevel == 1)
+ && ((tsdPtr->cachedWindow == NULL)
+ || (tsdPtr->cachedWindow->mainPtr != winPtr->mainPtr))) {
+ for (i = 0; i < NUM_STACKS; i++) {
+ arrayPtr = tsdPtr->stacks[i];
+ arrayPtr->numUsed = 0;
+ arrayPtr->nextToUse = arrayPtr->els;
+ }
+ ExtendStacks(winPtr->mainPtr->optionRootPtr, 0);
+ }
+
+ /*
+ * Step 4: create a new stack level; grow the level array if we've run out
+ * of levels. Clear the stacks for EXACT_LEAF_NAME and EXACT_LEAF_CLASS
+ * (anything that was there is of no use any more).
+ */
+
+ if (tsdPtr->curLevel >= tsdPtr->numLevels) {
+ StackLevel *newLevels =
+ ckalloc(tsdPtr->numLevels * 2 * sizeof(StackLevel));
+
+ memcpy(newLevels, tsdPtr->levels,
+ tsdPtr->numLevels * sizeof(StackLevel));
+ ckfree(tsdPtr->levels);
+ tsdPtr->numLevels *= 2;
+ tsdPtr->levels = newLevels;
+ }
+ levelPtr = &tsdPtr->levels[tsdPtr->curLevel];
+ levelPtr->winPtr = winPtr;
+ arrayPtr = tsdPtr->stacks[EXACT_LEAF_NAME];
+ arrayPtr->numUsed = 0;
+ arrayPtr->nextToUse = arrayPtr->els;
+ arrayPtr = tsdPtr->stacks[EXACT_LEAF_CLASS];
+ arrayPtr->numUsed = 0;
+ arrayPtr->nextToUse = arrayPtr->els;
+ for (i = 0; i < NUM_STACKS; i++) {
+ levelPtr->bases[i] = tsdPtr->stacks[i]->numUsed;
+ }
+
+ /*
+ * Step 5: scan the current stack level looking for matches to this
+ * window's name or class; where found, add new information to the stacks.
+ */
+
+ for (iPtr = searchOrder; *iPtr != -1; iPtr++) {
+ register Element *elPtr;
+ int count;
+ Tk_Uid id;
+
+ i = *iPtr;
+ if (i & CLASS) {
+ id = winPtr->classUid;
+ } else {
+ id = winPtr->nameUid;
+ }
+ elPtr = tsdPtr->stacks[i]->els;
+ count = levelPtr->bases[i];
+
+ /*
+ * For wildcard stacks, check all entries; for non-wildcard stacks,
+ * only check things that matched in the parent.
+ */
+
+ if (!(i & WILDCARD)) {
+ elPtr += levelPtr[-1].bases[i];
+ count -= levelPtr[-1].bases[i];
+ }
+ for ( ; count > 0; elPtr++, count--) {
+ if (elPtr->nameUid != id) {
+ continue;
+ }
+ ExtendStacks(elPtr->child.arrayPtr, leaf);
+ }
+ }
+ tsdPtr->cachedWindow = winPtr;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ExtendStacks --
+ *
+ * Given an element array, copy all the elements from the array onto the
+ * system stacks (except for irrelevant leaf elements).
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The option stacks are extended.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ExtendStacks(
+ ElArray *arrayPtr, /* Array of elements to copy onto stacks. */
+ int leaf) /* If zero, then don't copy exact leaf
+ * elements. */
+{
+ register int count;
+ register Element *elPtr;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ for (elPtr = arrayPtr->els, count = arrayPtr->numUsed;
+ count > 0; elPtr++, count--) {
+ if (!(elPtr->flags & (NODE|WILDCARD)) && !leaf) {
+ continue;
+ }
+ tsdPtr->stacks[elPtr->flags] =
+ ExtendArray(tsdPtr->stacks[elPtr->flags], elPtr);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * OptionThreadExitProc --
+ *
+ * Free data structures for option handling.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Option-related data structures get freed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+OptionThreadExitProc(
+ ClientData clientData) /* not used */
+{
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (tsdPtr->initialized) {
+ int i;
+
+ for (i = 0; i < NUM_STACKS; i++) {
+ ckfree(tsdPtr->stacks[i]);
+ }
+ ckfree(tsdPtr->levels);
+ tsdPtr->initialized = 0;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * OptionInit --
+ *
+ * Initialize data structures for option handling.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Option-related data structures get initialized.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+OptionInit(
+ register TkMainInfo *mainPtr)
+ /* Top-level information about window that
+ * isn't initialized yet. */
+{
+ int i;
+ Tcl_Interp *interp;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ Element *defaultMatchPtr = &tsdPtr->defaultMatch;
+
+ /*
+ * First, once-only initialization.
+ */
+
+ if (tsdPtr->initialized == 0) {
+ tsdPtr->initialized = 1;
+ tsdPtr->cachedWindow = NULL;
+ tsdPtr->numLevels = 5;
+ tsdPtr->curLevel = -1;
+ tsdPtr->serial = 0;
+
+ tsdPtr->levels = ckalloc(5 * sizeof(StackLevel));
+ for (i = 0; i < NUM_STACKS; i++) {
+ tsdPtr->stacks[i] = NewArray(10);
+ tsdPtr->levels[0].bases[i] = 0;
+ }
+
+ defaultMatchPtr->nameUid = NULL;
+ defaultMatchPtr->child.valueUid = NULL;
+ defaultMatchPtr->priority = -1;
+ defaultMatchPtr->flags = 0;
+ Tcl_CreateThreadExitHandler(OptionThreadExitProc, NULL);
+ }
+
+ /*
+ * Then, per-main-window initialization. Create and delete dummy
+ * interpreter for message logging.
+ */
+
+ mainPtr->optionRootPtr = NewArray(20);
+ interp = Tcl_CreateInterp();
+ GetDefaultOptions(interp, mainPtr->winPtr);
+ Tcl_DeleteInterp(interp);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ClearOptionTree --
+ *
+ * This function is called to erase everything in a hierarchical option
+ * database.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * All the options associated with arrayPtr are deleted, along with all
+ * option subtrees. The space pointed to by arrayPtr is freed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ClearOptionTree(
+ ElArray *arrayPtr) /* Array of options; delete everything
+ * referred to recursively by this. */
+{
+ register Element *elPtr;
+ int count;
+
+ for (count = arrayPtr->numUsed, elPtr = arrayPtr->els; count > 0;
+ count--, elPtr++) {
+ if (elPtr->flags & NODE) {
+ ClearOptionTree(elPtr->child.arrayPtr);
+ }
+ }
+ ckfree(arrayPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * GetDefaultOptions --
+ *
+ * This function is invoked to load the default set of options for a
+ * window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Options are added to those for winPtr's main window. If there exists a
+ * RESOURCE_MANAGER proprety for winPtr's display, that is used.
+ * Otherwise, the .Xdefaults file in the user's home directory is used.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+GetDefaultOptions(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting. */
+ TkWindow *winPtr) /* Fetch option defaults for main window
+ * associated with this. */
+{
+ char *regProp, **regPropPtr = &regProp;
+ int result, actualFormat;
+ unsigned long numItems, bytesAfter;
+ Atom actualType;
+
+ /*
+ * Try the RESOURCE_MANAGER property on the root window first.
+ */
+
+ regProp = NULL;
+ result = XGetWindowProperty(winPtr->display,
+ RootWindow(winPtr->display, 0), XA_RESOURCE_MANAGER, 0, 100000,
+ False, XA_STRING, &actualType, &actualFormat, &numItems,
+ &bytesAfter, (unsigned char **) regPropPtr);
+
+ if ((result == Success) && (actualType == XA_STRING)
+ && (actualFormat == 8)) {
+ result = AddFromString(interp, (Tk_Window) winPtr, regProp,
+ TK_USER_DEFAULT_PRIO);
+ XFree(regProp);
+ return result;
+ }
+
+ /*
+ * No luck there. Try a .Xdefaults file in the user's home directory.
+ */
+
+ if (regProp != NULL) {
+ XFree(regProp);
+ }
+ result = ReadOptionFile(interp, (Tk_Window) winPtr, "~/.Xdefaults",
+ TK_USER_DEFAULT_PRIO);
+ return result;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkPack.c b/tk8.6/generic/tkPack.c
new file mode 100644
index 0000000..9005d7f
--- /dev/null
+++ b/tk8.6/generic/tkPack.c
@@ -0,0 +1,1878 @@
+/*
+ * tkPack.c --
+ *
+ * This file contains code to implement the "packer" geometry manager for
+ * Tk.
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "tkInt.h"
+
+typedef enum {TOP, BOTTOM, LEFT, RIGHT} Side;
+static const char *const sideNames[] = {
+ "top", "bottom", "left", "right", NULL
+};
+
+/*
+ * For each window that the packer cares about (either because the window is
+ * managed by the packer or because the window has slaves that are managed by
+ * the packer), there is a structure of the following type:
+ */
+
+typedef struct Packer {
+ Tk_Window tkwin; /* Tk token for window. NULL means that the
+ * window has been deleted, but the packet
+ * hasn't had a chance to clean up yet because
+ * the structure is still in use. */
+ struct Packer *masterPtr; /* Master window within which this window is
+ * packed (NULL means this window isn't
+ * managed by the packer). */
+ struct Packer *nextPtr; /* Next window packed within same master. List
+ * is priority-ordered: first on list gets
+ * packed first. */
+ struct Packer *slavePtr; /* First in list of slaves packed inside this
+ * window (NULL means no packed slaves). */
+ Side side; /* Side of master against which this window is
+ * packed. */
+ Tk_Anchor anchor; /* If frame allocated for window is larger
+ * than window needs, this indicates how where
+ * to position window in frame. */
+ int padX, padY; /* Total additional pixels to leave around the
+ * window. Some is of this space is on each
+ * side. This is space *outside* the window:
+ * we'll allocate extra space in frame but
+ * won't enlarge window). */
+ int padLeft, padTop; /* The part of padX or padY to use on the left
+ * or top of the widget, respectively. By
+ * default, this is half of padX or padY. */
+ int iPadX, iPadY; /* Total extra pixels to allocate inside the
+ * window (half of this amount will appear on
+ * each side). */
+ int doubleBw; /* Twice the window's last known border width.
+ * If this changes, the window must be
+ * repacked within its master. */
+ int *abortPtr; /* If non-NULL, it means that there is a
+ * nested call to ArrangePacking already
+ * working on this window. *abortPtr may be
+ * set to 1 to abort that nested call. This
+ * happens, for example, if tkwin or any of
+ * its slaves is deleted. */
+ int flags; /* Miscellaneous flags; see below for
+ * definitions. */
+} Packer;
+
+/*
+ * Flag values for Packer structures:
+ *
+ * REQUESTED_REPACK: 1 means a Tcl_DoWhenIdle request has already
+ * been made to repack all the slaves of this
+ * window.
+ * FILLX: 1 means if frame allocated for window is wider
+ * than window needs, expand window to fill
+ * frame. 0 means don't make window any larger
+ * than needed.
+ * FILLY: Same as FILLX, except for height.
+ * EXPAND: 1 means this window's frame will absorb any
+ * extra space in the master window.
+ * OLD_STYLE: 1 means this window is being managed with the
+ * old-style packer algorithms (before Tk version
+ * 3.3). The main difference is that padding and
+ * filling are done differently.
+ * DONT_PROPAGATE: 1 means don't set this window's requested
+ * size. 0 means if this window is a master then
+ * Tk will set its requested size to fit the
+ * needs of its slaves.
+ * ALLOCED_MASTER 1 means that Pack has allocated itself as
+ * geometry master for this window.
+ */
+
+#define REQUESTED_REPACK 1
+#define FILLX 2
+#define FILLY 4
+#define EXPAND 8
+#define OLD_STYLE 16
+#define DONT_PROPAGATE 32
+#define ALLOCED_MASTER 64
+
+/*
+ * The following structure is the official type record for the packer:
+ */
+
+static void PackReqProc(ClientData clientData, Tk_Window tkwin);
+static void PackLostSlaveProc(ClientData clientData,
+ Tk_Window tkwin);
+
+static const Tk_GeomMgr packerType = {
+ "pack", /* name */
+ PackReqProc, /* requestProc */
+ PackLostSlaveProc, /* lostSlaveProc */
+};
+
+/*
+ * Forward declarations for functions defined later in this file:
+ */
+
+static void ArrangePacking(ClientData clientData);
+static int ConfigureSlaves(Tcl_Interp *interp, Tk_Window tkwin,
+ int objc, Tcl_Obj *const objv[]);
+static void DestroyPacker(void *memPtr);
+static Packer * GetPacker(Tk_Window tkwin);
+static int PackAfter(Tcl_Interp *interp, Packer *prevPtr,
+ Packer *masterPtr, int objc,Tcl_Obj *const objv[]);
+static void PackStructureProc(ClientData clientData,
+ XEvent *eventPtr);
+static void Unlink(Packer *packPtr);
+static int XExpansion(Packer *slavePtr, int cavityWidth);
+static int YExpansion(Packer *slavePtr, int cavityHeight);
+
+/*
+ *------------------------------------------------------------------------
+ *
+ * TkAppendPadAmount --
+ *
+ * This function generates a text value that describes one of the -padx,
+ * -pady, -ipadx, or -ipady configuration options. The text value
+ * generated is appended to the given Tcl_Obj.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *------------------------------------------------------------------------
+ */
+
+void
+TkAppendPadAmount(
+ Tcl_Obj *bufferObj, /* The interpreter into which the result is
+ * written. */
+ const char *switchName, /* One of "padx", "pady", "ipadx" or
+ * "ipady" */
+ int halfSpace, /* The left or top padding amount */
+ int allSpace) /* The total amount of padding */
+{
+ Tcl_Obj *padding[2];
+
+ if (halfSpace*2 == allSpace) {
+ Tcl_DictObjPut(NULL, bufferObj, Tcl_NewStringObj(switchName, -1),
+ Tcl_NewIntObj(halfSpace));
+ } else {
+ padding[0] = Tcl_NewIntObj(halfSpace);
+ padding[1] = Tcl_NewIntObj(allSpace - halfSpace);
+ Tcl_DictObjPut(NULL, bufferObj, Tcl_NewStringObj(switchName, -1),
+ Tcl_NewListObj(2, padding));
+ }
+}
+
+/*
+ *------------------------------------------------------------------------
+ *
+ * Tk_PackCmd --
+ *
+ * This function is invoked to process the "pack" 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_PackObjCmd(
+ 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 = clientData;
+ const char *argv2;
+ static const char *const optionStrings[] = {
+ /* after, append, before and unpack are deprecated */
+ "after", "append", "before", "unpack",
+ "configure", "forget", "info", "propagate", "slaves", NULL };
+ enum options {
+ PACK_AFTER, PACK_APPEND, PACK_BEFORE, PACK_UNPACK,
+ PACK_CONFIGURE, PACK_FORGET, PACK_INFO, PACK_PROPAGATE, PACK_SLAVES };
+ int index;
+
+ if (objc >= 2) {
+ const char *string = Tcl_GetString(objv[1]);
+
+ if (string[0] == '.') {
+ return ConfigureSlaves(interp, tkwin, objc-1, objv+1);
+ }
+ }
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings,
+ sizeof(char *), "option", 0, &index) != TCL_OK) {
+ /*
+ * Call it again without the deprecated ones to get a proper error
+ * message. This works well since there can't be any ambiguity between
+ * deprecated and new options.
+ */
+
+ Tcl_ResetResult(interp);
+ Tcl_GetIndexFromObjStruct(interp, objv[1], &optionStrings[4],
+ sizeof(char *), "option", 0, &index);
+ return TCL_ERROR;
+ }
+
+ argv2 = Tcl_GetString(objv[2]);
+ switch ((enum options) index) {
+ case PACK_AFTER: {
+ Packer *prevPtr;
+ Tk_Window tkwin2;
+
+ if (TkGetWindowFromObj(interp, tkwin, objv[2], &tkwin2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ prevPtr = GetPacker(tkwin2);
+ if (prevPtr->masterPtr == NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "window \"%s\" isn't packed", argv2));
+ Tcl_SetErrorCode(interp, "TK", "PACK", "NOT_PACKED", NULL);
+ return TCL_ERROR;
+ }
+ return PackAfter(interp, prevPtr, prevPtr->masterPtr, objc-3, objv+3);
+ }
+ case PACK_APPEND: {
+ Packer *masterPtr;
+ register Packer *prevPtr;
+ Tk_Window tkwin2;
+
+ if (TkGetWindowFromObj(interp, tkwin, objv[2], &tkwin2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ masterPtr = GetPacker(tkwin2);
+ prevPtr = masterPtr->slavePtr;
+ if (prevPtr != NULL) {
+ while (prevPtr->nextPtr != NULL) {
+ prevPtr = prevPtr->nextPtr;
+ }
+ }
+ return PackAfter(interp, prevPtr, masterPtr, objc-3, objv+3);
+ }
+ case PACK_BEFORE: {
+ Packer *packPtr, *masterPtr;
+ register Packer *prevPtr;
+ Tk_Window tkwin2;
+
+ if (TkGetWindowFromObj(interp, tkwin, objv[2], &tkwin2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ packPtr = GetPacker(tkwin2);
+ if (packPtr->masterPtr == NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "window \"%s\" isn't packed", argv2));
+ Tcl_SetErrorCode(interp, "TK", "PACK", "NOT_PACKED", NULL);
+ return TCL_ERROR;
+ }
+ masterPtr = packPtr->masterPtr;
+ prevPtr = masterPtr->slavePtr;
+ if (prevPtr == packPtr) {
+ prevPtr = NULL;
+ } else {
+ for ( ; ; prevPtr = prevPtr->nextPtr) {
+ if (prevPtr == NULL) {
+ Tcl_Panic("\"pack before\" couldn't find predecessor");
+ }
+ if (prevPtr->nextPtr == packPtr) {
+ break;
+ }
+ }
+ }
+ return PackAfter(interp, prevPtr, masterPtr, objc-3, objv+3);
+ }
+ case PACK_CONFIGURE:
+ if (argv2[0] != '.') {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad argument \"%s\": must be name of window", argv2));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "WINDOW_PATH", NULL);
+ return TCL_ERROR;
+ }
+ return ConfigureSlaves(interp, tkwin, objc-2, objv+2);
+ case PACK_FORGET: {
+ Tk_Window slave;
+ Packer *slavePtr;
+ int i;
+
+ for (i = 2; i < objc; i++) {
+ if (TkGetWindowFromObj(interp, tkwin, objv[i], &slave) != TCL_OK) {
+ continue;
+ }
+ slavePtr = GetPacker(slave);
+ if ((slavePtr != NULL) && (slavePtr->masterPtr != NULL)) {
+ Tk_ManageGeometry(slave, NULL, NULL);
+ if (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin)) {
+ Tk_UnmaintainGeometry(slavePtr->tkwin,
+ slavePtr->masterPtr->tkwin);
+ }
+ Unlink(slavePtr);
+ Tk_UnmapWindow(slavePtr->tkwin);
+ }
+ }
+ break;
+ }
+ case PACK_INFO: {
+ register Packer *slavePtr;
+ Tk_Window slave;
+ Tcl_Obj *infoObj;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window");
+ return TCL_ERROR;
+ }
+ if (TkGetWindowFromObj(interp, tkwin, objv[2], &slave) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ slavePtr = GetPacker(slave);
+ if (slavePtr->masterPtr == NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "window \"%s\" isn't packed", argv2));
+ Tcl_SetErrorCode(interp, "TK", "PACK", "NOT_PACKED", NULL);
+ return TCL_ERROR;
+ }
+
+ infoObj = Tcl_NewObj();
+ Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-in", -1),
+ TkNewWindowObj(slavePtr->masterPtr->tkwin));
+ Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-anchor", -1),
+ Tcl_NewStringObj(Tk_NameOfAnchor(slavePtr->anchor), -1));
+ Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-expand", -1),
+ Tcl_NewBooleanObj(slavePtr->flags & EXPAND));
+ switch (slavePtr->flags & (FILLX|FILLY)) {
+ case 0:
+ Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-fill", -1),
+ Tcl_NewStringObj("none", -1));
+ break;
+ case FILLX:
+ Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-fill", -1),
+ Tcl_NewStringObj("x", -1));
+ break;
+ case FILLY:
+ Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-fill", -1),
+ Tcl_NewStringObj("y", -1));
+ break;
+ case FILLX|FILLY:
+ Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-fill", -1),
+ Tcl_NewStringObj("both", -1));
+ break;
+ }
+ TkAppendPadAmount(infoObj, "-ipadx", slavePtr->iPadX/2, slavePtr->iPadX);
+ TkAppendPadAmount(infoObj, "-ipady", slavePtr->iPadY/2, slavePtr->iPadY);
+ TkAppendPadAmount(infoObj, "-padx", slavePtr->padLeft,slavePtr->padX);
+ TkAppendPadAmount(infoObj, "-pady", slavePtr->padTop, slavePtr->padY);
+ Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-side", -1),
+ Tcl_NewStringObj(sideNames[slavePtr->side], -1));
+ Tcl_SetObjResult(interp, infoObj);
+ break;
+ }
+ case PACK_PROPAGATE: {
+ Tk_Window master;
+ Packer *masterPtr;
+ int propagate;
+
+ if (objc > 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?boolean?");
+ return TCL_ERROR;
+ }
+ if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ masterPtr = GetPacker(master);
+ if (objc == 3) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewBooleanObj(!(masterPtr->flags & DONT_PROPAGATE)));
+ return TCL_OK;
+ }
+ if (Tcl_GetBooleanFromObj(interp, objv[3], &propagate) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (propagate) {
+ /*
+ * If we have slaves, we need to register as geometry master.
+ */
+
+ if (masterPtr->slavePtr != NULL) {
+ if (TkSetGeometryMaster(interp, master, "pack") != TCL_OK) {
+ return TCL_ERROR;
+ }
+ masterPtr->flags |= ALLOCED_MASTER;
+ }
+ masterPtr->flags &= ~DONT_PROPAGATE;
+
+ /*
+ * Repack the master to allow new geometry information to
+ * propagate upwards to the master's master.
+ */
+
+ if (masterPtr->abortPtr != NULL) {
+ *masterPtr->abortPtr = 1;
+ }
+ if (!(masterPtr->flags & REQUESTED_REPACK)) {
+ masterPtr->flags |= REQUESTED_REPACK;
+ Tcl_DoWhenIdle(ArrangePacking, masterPtr);
+ }
+ } else {
+ if (masterPtr->flags & ALLOCED_MASTER) {
+ TkFreeGeometryMaster(master, "pack");
+ masterPtr->flags &= ~ALLOCED_MASTER;
+ }
+ masterPtr->flags |= DONT_PROPAGATE;
+ }
+ break;
+ }
+ case PACK_SLAVES: {
+ Tk_Window master;
+ Packer *masterPtr, *slavePtr;
+ Tcl_Obj *resultObj;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window");
+ return TCL_ERROR;
+ }
+ if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ resultObj = Tcl_NewObj();
+ masterPtr = GetPacker(master);
+ for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
+ slavePtr = slavePtr->nextPtr) {
+ Tcl_ListObjAppendElement(NULL, resultObj,
+ TkNewWindowObj(slavePtr->tkwin));
+ }
+ Tcl_SetObjResult(interp, resultObj);
+ break;
+ }
+ case PACK_UNPACK: {
+ Tk_Window tkwin2;
+ Packer *packPtr;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window");
+ return TCL_ERROR;
+ }
+ if (TkGetWindowFromObj(interp, tkwin, objv[2], &tkwin2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ packPtr = GetPacker(tkwin2);
+ if ((packPtr != NULL) && (packPtr->masterPtr != NULL)) {
+ Tk_ManageGeometry(tkwin2, NULL, NULL);
+ if (packPtr->masterPtr->tkwin != Tk_Parent(packPtr->tkwin)) {
+ Tk_UnmaintainGeometry(packPtr->tkwin,
+ packPtr->masterPtr->tkwin);
+ }
+ Unlink(packPtr);
+ Tk_UnmapWindow(packPtr->tkwin);
+ }
+ break;
+ }
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *------------------------------------------------------------------------
+ *
+ * PackReqProc --
+ *
+ * This function is invoked by Tk_GeometryRequest for windows managed by
+ * the packer.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Arranges for tkwin, and all its managed siblings, to be re-packed at
+ * the next idle point.
+ *
+ *------------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static void
+PackReqProc(
+ ClientData clientData, /* Packer's information about window that got
+ * new preferred geometry. */
+ Tk_Window tkwin) /* Other Tk-related information about the
+ * window. */
+{
+ register Packer *packPtr = clientData;
+
+ packPtr = packPtr->masterPtr;
+ if (!(packPtr->flags & REQUESTED_REPACK)) {
+ packPtr->flags |= REQUESTED_REPACK;
+ Tcl_DoWhenIdle(ArrangePacking, packPtr);
+ }
+}
+
+/*
+ *------------------------------------------------------------------------
+ *
+ * PackLostSlaveProc --
+ *
+ * This function is invoked by Tk whenever some other geometry claims
+ * control over a slave that used to be managed by us.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Forgets all packer-related information about the slave.
+ *
+ *------------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static void
+PackLostSlaveProc(
+ ClientData clientData, /* Packer structure for slave window that was
+ * stolen away. */
+ Tk_Window tkwin) /* Tk's handle for the slave window. */
+{
+ register Packer *slavePtr = clientData;
+
+ if (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin)) {
+ Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin);
+ }
+ Unlink(slavePtr);
+ Tk_UnmapWindow(slavePtr->tkwin);
+}
+
+/*
+ *------------------------------------------------------------------------
+ *
+ * ArrangePacking --
+ *
+ * This function is invoked (using the Tcl_DoWhenIdle mechanism) to
+ * re-layout a set of windows managed by the packer. It is invoked at
+ * idle time so that a series of packer requests can be merged into a
+ * single layout operation.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The packed slaves of masterPtr may get resized or moved.
+ *
+ *------------------------------------------------------------------------
+ */
+
+static void
+ArrangePacking(
+ ClientData clientData) /* Structure describing master whose slaves
+ * are to be re-layed out. */
+{
+ register Packer *masterPtr = clientData;
+ register Packer *slavePtr;
+ int cavityX, cavityY, cavityWidth, cavityHeight;
+ /* These variables keep track of the
+ * as-yet-unallocated space remaining in the
+ * middle of the master window. */
+ int frameX, frameY, frameWidth, frameHeight;
+ /* These variables keep track of the frame
+ * allocated to the current window. */
+ int x, y, width, height; /* These variables are used to hold the actual
+ * geometry of the current window. */
+ int abort; /* May get set to non-zero to abort this
+ * repacking operation. */
+ int borderX, borderY;
+ int borderTop, borderBtm;
+ int borderLeft, borderRight;
+ int maxWidth, maxHeight, tmp;
+
+ masterPtr->flags &= ~REQUESTED_REPACK;
+
+ /*
+ * If the master has no slaves anymore, then don't do anything at all:
+ * just leave the master's size as-is.
+ */
+
+ if (masterPtr->slavePtr == NULL) {
+ return;
+ }
+
+ /*
+ * Abort any nested call to ArrangePacking for this window, since we'll do
+ * everything necessary here, and set up so this call can be aborted if
+ * necessary.
+ */
+
+ if (masterPtr->abortPtr != NULL) {
+ *masterPtr->abortPtr = 1;
+ }
+ masterPtr->abortPtr = &abort;
+ abort = 0;
+ Tcl_Preserve(masterPtr);
+
+ /*
+ * Pass #1: scan all the slaves to figure out the total amount of space
+ * needed. Two separate width and height values are computed:
+ *
+ * width - Holds the sum of the widths (plus padding) of all the
+ * slaves seen so far that were packed LEFT or RIGHT.
+ * height - Holds the sum of the heights (plus padding) of all the
+ * slaves seen so far that were packed TOP or BOTTOM.
+ *
+ * maxWidth - Gradually builds up the width needed by the master to
+ * just barely satisfy all the slave's needs. For each
+ * slave, the code computes the width needed for all the
+ * slaves so far and updates maxWidth if the new value is
+ * greater.
+ * maxHeight - Same as maxWidth, except keeps height info.
+ */
+
+ width = maxWidth = Tk_InternalBorderLeft(masterPtr->tkwin) +
+ Tk_InternalBorderRight(masterPtr->tkwin);
+ height = maxHeight = Tk_InternalBorderTop(masterPtr->tkwin) +
+ Tk_InternalBorderBottom(masterPtr->tkwin);
+ for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
+ slavePtr = slavePtr->nextPtr) {
+ if ((slavePtr->side == TOP) || (slavePtr->side == BOTTOM)) {
+ tmp = Tk_ReqWidth(slavePtr->tkwin) + slavePtr->doubleBw
+ + slavePtr->padX + slavePtr->iPadX + width;
+ if (tmp > maxWidth) {
+ maxWidth = tmp;
+ }
+ height += Tk_ReqHeight(slavePtr->tkwin) + slavePtr->doubleBw
+ + slavePtr->padY + slavePtr->iPadY;
+ } else {
+ tmp = Tk_ReqHeight(slavePtr->tkwin) + slavePtr->doubleBw
+ + slavePtr->padY + slavePtr->iPadY + height;
+ if (tmp > maxHeight) {
+ maxHeight = tmp;
+ }
+ width += Tk_ReqWidth(slavePtr->tkwin) + slavePtr->doubleBw
+ + slavePtr->padX + slavePtr->iPadX;
+ }
+ }
+ if (width > maxWidth) {
+ maxWidth = width;
+ }
+ if (height > maxHeight) {
+ maxHeight = height;
+ }
+
+ if (maxWidth < Tk_MinReqWidth(masterPtr->tkwin)) {
+ maxWidth = Tk_MinReqWidth(masterPtr->tkwin);
+ }
+ if (maxHeight < Tk_MinReqHeight(masterPtr->tkwin)) {
+ maxHeight = Tk_MinReqHeight(masterPtr->tkwin);
+ }
+
+ /*
+ * If the total amount of space needed in the master window has changed,
+ * and if we're propagating geometry information, then notify the next
+ * geometry manager up and requeue ourselves to start again after the
+ * master has had a chance to resize us.
+ */
+
+ if (((maxWidth != Tk_ReqWidth(masterPtr->tkwin))
+ || (maxHeight != Tk_ReqHeight(masterPtr->tkwin)))
+ && !(masterPtr->flags & DONT_PROPAGATE)) {
+ Tk_GeometryRequest(masterPtr->tkwin, maxWidth, maxHeight);
+ masterPtr->flags |= REQUESTED_REPACK;
+ Tcl_DoWhenIdle(ArrangePacking, masterPtr);
+ goto done;
+ }
+
+ /*
+ * Pass #2: scan the slaves a second time assigning new sizes. The
+ * "cavity" variables keep track of the unclaimed space in the cavity of
+ * the window; this shrinks inward as we allocate windows around the
+ * edges. The "frame" variables keep track of the space allocated to the
+ * current window and its frame. The current window is then placed
+ * somewhere inside the frame, depending on anchor.
+ */
+
+ cavityX = x = Tk_InternalBorderLeft(masterPtr->tkwin);
+ cavityY = y = Tk_InternalBorderTop(masterPtr->tkwin);
+ cavityWidth = Tk_Width(masterPtr->tkwin) -
+ Tk_InternalBorderLeft(masterPtr->tkwin) -
+ Tk_InternalBorderRight(masterPtr->tkwin);
+ cavityHeight = Tk_Height(masterPtr->tkwin) -
+ Tk_InternalBorderTop(masterPtr->tkwin) -
+ Tk_InternalBorderBottom(masterPtr->tkwin);
+ for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
+ slavePtr = slavePtr->nextPtr) {
+ if ((slavePtr->side == TOP) || (slavePtr->side == BOTTOM)) {
+ frameWidth = cavityWidth;
+ frameHeight = Tk_ReqHeight(slavePtr->tkwin) + slavePtr->doubleBw
+ + slavePtr->padY + slavePtr->iPadY;
+ if (slavePtr->flags & EXPAND) {
+ frameHeight += YExpansion(slavePtr, cavityHeight);
+ }
+ cavityHeight -= frameHeight;
+ if (cavityHeight < 0) {
+ frameHeight += cavityHeight;
+ cavityHeight = 0;
+ }
+ frameX = cavityX;
+ if (slavePtr->side == TOP) {
+ frameY = cavityY;
+ cavityY += frameHeight;
+ } else {
+ frameY = cavityY + cavityHeight;
+ }
+ } else {
+ frameHeight = cavityHeight;
+ frameWidth = Tk_ReqWidth(slavePtr->tkwin) + slavePtr->doubleBw
+ + slavePtr->padX + slavePtr->iPadX;
+ if (slavePtr->flags & EXPAND) {
+ frameWidth += XExpansion(slavePtr, cavityWidth);
+ }
+ cavityWidth -= frameWidth;
+ if (cavityWidth < 0) {
+ frameWidth += cavityWidth;
+ cavityWidth = 0;
+ }
+ frameY = cavityY;
+ if (slavePtr->side == LEFT) {
+ frameX = cavityX;
+ cavityX += frameWidth;
+ } else {
+ frameX = cavityX + cavityWidth;
+ }
+ }
+
+ /*
+ * Now that we've got the size of the frame for the window, compute
+ * the window's actual size and location using the fill, padding, and
+ * frame factors. The variables "borderX" and "borderY" are used to
+ * handle the differences between old-style packing and the new style
+ * (in old-style, iPadX and iPadY are always zero and padding is
+ * completely ignored except when computing frame size).
+ */
+
+ if (slavePtr->flags & OLD_STYLE) {
+ borderX = borderY = 0;
+ borderTop = borderBtm = 0;
+ borderLeft = borderRight = 0;
+ } else {
+ borderX = slavePtr->padX;
+ borderY = slavePtr->padY;
+ borderLeft = slavePtr->padLeft;
+ borderRight = borderX - borderLeft;
+ borderTop = slavePtr->padTop;
+ borderBtm = borderY - borderTop;
+ }
+ width = Tk_ReqWidth(slavePtr->tkwin) + slavePtr->doubleBw
+ + slavePtr->iPadX;
+ if ((slavePtr->flags & FILLX)
+ || (width > (frameWidth - borderX))) {
+ width = frameWidth - borderX;
+ }
+ height = Tk_ReqHeight(slavePtr->tkwin) + slavePtr->doubleBw
+ + slavePtr->iPadY;
+ if ((slavePtr->flags & FILLY)
+ || (height > (frameHeight - borderY))) {
+ height = frameHeight - borderY;
+ }
+ switch (slavePtr->anchor) {
+ case TK_ANCHOR_N:
+ x = frameX + (borderLeft + frameWidth - width - borderRight)/2;
+ y = frameY + borderTop;
+ break;
+ case TK_ANCHOR_NE:
+ x = frameX + frameWidth - width - borderRight;
+ y = frameY + borderTop;
+ break;
+ case TK_ANCHOR_E:
+ x = frameX + frameWidth - width - borderRight;
+ y = frameY + (borderTop + frameHeight - height - borderBtm)/2;
+ break;
+ case TK_ANCHOR_SE:
+ x = frameX + frameWidth - width - borderRight;
+ y = frameY + frameHeight - height - borderBtm;
+ break;
+ case TK_ANCHOR_S:
+ x = frameX + (borderLeft + frameWidth - width - borderRight)/2;
+ y = frameY + frameHeight - height - borderBtm;
+ break;
+ case TK_ANCHOR_SW:
+ x = frameX + borderLeft;
+ y = frameY + frameHeight - height - borderBtm;
+ break;
+ case TK_ANCHOR_W:
+ x = frameX + borderLeft;
+ y = frameY + (borderTop + frameHeight - height - borderBtm)/2;
+ break;
+ case TK_ANCHOR_NW:
+ x = frameX + borderLeft;
+ y = frameY + borderTop;
+ break;
+ case TK_ANCHOR_CENTER:
+ x = frameX + (borderLeft + frameWidth - width - borderRight)/2;
+ y = frameY + (borderTop + frameHeight - height - borderBtm)/2;
+ break;
+ default:
+ Tcl_Panic("bad frame factor in ArrangePacking");
+ }
+ width -= slavePtr->doubleBw;
+ height -= slavePtr->doubleBw;
+
+ /*
+ * The final step is to set the position, size, and mapped/unmapped
+ * state of the slave. If the slave is a child of the master, then do
+ * this here. Otherwise let Tk_MaintainGeometry do the work.
+ */
+
+ if (masterPtr->tkwin == Tk_Parent(slavePtr->tkwin)) {
+ if ((width <= 0) || (height <= 0)) {
+ Tk_UnmapWindow(slavePtr->tkwin);
+ } else {
+ if ((x != Tk_X(slavePtr->tkwin))
+ || (y != Tk_Y(slavePtr->tkwin))
+ || (width != Tk_Width(slavePtr->tkwin))
+ || (height != Tk_Height(slavePtr->tkwin))) {
+ Tk_MoveResizeWindow(slavePtr->tkwin, x, y, width, height);
+ }
+ if (abort) {
+ goto done;
+ }
+
+ /*
+ * Don't map the slave if the master isn't mapped: wait until
+ * the master gets mapped later.
+ */
+
+ if (Tk_IsMapped(masterPtr->tkwin)) {
+ Tk_MapWindow(slavePtr->tkwin);
+ }
+ }
+ } else {
+ if ((width <= 0) || (height <= 0)) {
+ Tk_UnmaintainGeometry(slavePtr->tkwin, masterPtr->tkwin);
+ Tk_UnmapWindow(slavePtr->tkwin);
+ } else {
+ Tk_MaintainGeometry(slavePtr->tkwin, masterPtr->tkwin,
+ x, y, width, height);
+ }
+ }
+
+ /*
+ * Changes to the window's structure could cause almost anything to
+ * happen, including deleting the parent or child. If this happens,
+ * we'll be told to abort.
+ */
+
+ if (abort) {
+ goto done;
+ }
+ }
+
+ done:
+ masterPtr->abortPtr = NULL;
+ Tcl_Release(masterPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XExpansion --
+ *
+ * Given a list of packed slaves, the first of which is packed on the
+ * left or right and is expandable, compute how much to expand the child.
+ *
+ * Results:
+ * The return value is the number of additional pixels to give to the
+ * child.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+XExpansion(
+ register Packer *slavePtr, /* First in list of remaining slaves. */
+ int cavityWidth) /* Horizontal space left for all remaining
+ * slaves. */
+{
+ int numExpand, minExpand, curExpand;
+ int childWidth;
+
+ /*
+ * This function is tricky because windows packed top or bottom can be
+ * interspersed among expandable windows packed left or right. Scan
+ * through the list, keeping a running sum of the widths of all left and
+ * right windows (actually, count the cavity space not allocated) and a
+ * running count of all expandable left and right windows. At each top or
+ * bottom window, and at the end of the list, compute the expansion factor
+ * that seems reasonable at that point. Return the smallest factor seen at
+ * any of these points.
+ */
+
+ minExpand = cavityWidth;
+ numExpand = 0;
+ for ( ; slavePtr != NULL; slavePtr = slavePtr->nextPtr) {
+ childWidth = Tk_ReqWidth(slavePtr->tkwin) + slavePtr->doubleBw
+ + slavePtr->padX + slavePtr->iPadX;
+ if ((slavePtr->side == TOP) || (slavePtr->side == BOTTOM)) {
+ if (numExpand) {
+ curExpand = (cavityWidth - childWidth)/numExpand;
+ if (curExpand < minExpand) {
+ minExpand = curExpand;
+ }
+ }
+ } else {
+ cavityWidth -= childWidth;
+ if (slavePtr->flags & EXPAND) {
+ numExpand++;
+ }
+ }
+ }
+ if (numExpand) {
+ curExpand = cavityWidth/numExpand;
+ if (curExpand < minExpand) {
+ minExpand = curExpand;
+ }
+ }
+ return (minExpand < 0) ? 0 : minExpand;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * YExpansion --
+ *
+ * Given a list of packed slaves, the first of which is packed on the top
+ * or bottom and is expandable, compute how much to expand the child.
+ *
+ * Results:
+ * The return value is the number of additional pixels to give to the
+ * child.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+YExpansion(
+ register Packer *slavePtr, /* First in list of remaining slaves. */
+ int cavityHeight) /* Vertical space left for all remaining
+ * slaves. */
+{
+ int numExpand, minExpand, curExpand;
+ int childHeight;
+
+ /*
+ * See comments for XExpansion.
+ */
+
+ minExpand = cavityHeight;
+ numExpand = 0;
+ for ( ; slavePtr != NULL; slavePtr = slavePtr->nextPtr) {
+ childHeight = Tk_ReqHeight(slavePtr->tkwin) + slavePtr->doubleBw
+ + slavePtr->padY + slavePtr->iPadY;
+ if ((slavePtr->side == LEFT) || (slavePtr->side == RIGHT)) {
+ if (numExpand) {
+ curExpand = (cavityHeight - childHeight)/numExpand;
+ if (curExpand < minExpand) {
+ minExpand = curExpand;
+ }
+ }
+ } else {
+ cavityHeight -= childHeight;
+ if (slavePtr->flags & EXPAND) {
+ numExpand++;
+ }
+ }
+ }
+ if (numExpand) {
+ curExpand = cavityHeight/numExpand;
+ if (curExpand < minExpand) {
+ minExpand = curExpand;
+ }
+ }
+ return (minExpand < 0) ? 0 : minExpand;
+}
+
+/*
+ *------------------------------------------------------------------------
+ *
+ * GetPacker --
+ *
+ * This internal function is used to locate a Packer structure for a
+ * given window, creating one if one doesn't exist already.
+ *
+ * Results:
+ * The return value is a pointer to the Packer structure corresponding to
+ * tkwin.
+ *
+ * Side effects:
+ * A new packer structure may be created. If so, then a callback is set
+ * up to clean things up when the window is deleted.
+ *
+ *------------------------------------------------------------------------
+ */
+
+static Packer *
+GetPacker(
+ Tk_Window tkwin) /* Token for window for which packer structure
+ * is desired. */
+{
+ register Packer *packPtr;
+ Tcl_HashEntry *hPtr;
+ int isNew;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+
+ if (!dispPtr->packInit) {
+ dispPtr->packInit = 1;
+ Tcl_InitHashTable(&dispPtr->packerHashTable, TCL_ONE_WORD_KEYS);
+ }
+
+ /*
+ * See if there's already packer for this window. If not, then create a
+ * new one.
+ */
+
+ hPtr = Tcl_CreateHashEntry(&dispPtr->packerHashTable, (char *) tkwin,
+ &isNew);
+ if (!isNew) {
+ return Tcl_GetHashValue(hPtr);
+ }
+ packPtr = ckalloc(sizeof(Packer));
+ packPtr->tkwin = tkwin;
+ packPtr->masterPtr = NULL;
+ packPtr->nextPtr = NULL;
+ packPtr->slavePtr = NULL;
+ packPtr->side = TOP;
+ packPtr->anchor = TK_ANCHOR_CENTER;
+ packPtr->padX = packPtr->padY = 0;
+ packPtr->padLeft = packPtr->padTop = 0;
+ packPtr->iPadX = packPtr->iPadY = 0;
+ packPtr->doubleBw = 2*Tk_Changes(tkwin)->border_width;
+ packPtr->abortPtr = NULL;
+ packPtr->flags = 0;
+ Tcl_SetHashValue(hPtr, packPtr);
+ Tk_CreateEventHandler(tkwin, StructureNotifyMask,
+ PackStructureProc, packPtr);
+ return packPtr;
+}
+
+/*
+ *------------------------------------------------------------------------
+ *
+ * PackAfter --
+ *
+ * This function does most of the real work of adding one or more windows
+ * into the packing order for its master.
+ *
+ * Results:
+ * A standard Tcl return value.
+ *
+ * Side effects:
+ * The geometry of the specified windows may change, both now and again
+ * in the future.
+ *
+ *------------------------------------------------------------------------
+ */
+
+static int
+PackAfter(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Packer *prevPtr, /* Pack windows in argv just after this
+ * window; NULL means pack as first child of
+ * masterPtr. */
+ Packer *masterPtr, /* Master in which to pack windows. */
+ int objc, /* Number of elements in objv. */
+ Tcl_Obj *const objv[]) /* Array of lists, each containing 2 elements:
+ * window name and side against which to
+ * pack. */
+{
+ register Packer *packPtr;
+ Tk_Window tkwin, ancestor, parent;
+ Tcl_Obj **options;
+ int index, optionCount, c;
+
+ /*
+ * Iterate over all of the window specifiers, each consisting of two
+ * arguments. The first argument contains the window name and the
+ * additional arguments contain options such as "top" or "padx 20".
+ */
+
+ for ( ; objc > 0; objc -= 2, objv += 2, prevPtr = packPtr) {
+ if (objc < 2) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "wrong # args: window \"%s\" should be followed by options",
+ Tcl_GetString(objv[0])));
+ Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Find the packer for the window to be packed, and make sure that the
+ * window in which it will be packed is either its or a descendant of
+ * its parent.
+ */
+
+ if (TkGetWindowFromObj(interp, masterPtr->tkwin, objv[0], &tkwin)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ parent = Tk_Parent(tkwin);
+ for (ancestor = masterPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) {
+ if (ancestor == parent) {
+ break;
+ }
+ if (((Tk_FakeWin *) (ancestor))->flags & TK_TOP_HIERARCHY) {
+ badWindow:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't pack %s inside %s", Tcl_GetString(objv[0]),
+ Tk_PathName(masterPtr->tkwin)));
+ Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "HIERARCHY", NULL);
+ return TCL_ERROR;
+ }
+ }
+ if (((Tk_FakeWin *) (tkwin))->flags & TK_TOP_HIERARCHY) {
+ goto badWindow;
+ }
+ if (tkwin == masterPtr->tkwin) {
+ goto badWindow;
+ }
+ packPtr = GetPacker(tkwin);
+
+ /*
+ * Process options for this window.
+ */
+
+ if (Tcl_ListObjGetElements(interp, objv[1], &optionCount, &options)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ packPtr->side = TOP;
+ packPtr->anchor = TK_ANCHOR_CENTER;
+ packPtr->padX = packPtr->padY = 0;
+ packPtr->padLeft = packPtr->padTop = 0;
+ packPtr->iPadX = packPtr->iPadY = 0;
+ packPtr->flags &= ~(FILLX|FILLY|EXPAND);
+ packPtr->flags |= OLD_STYLE;
+ for (index = 0 ; index < optionCount; index++) {
+ Tcl_Obj *curOptPtr = options[index];
+ const char *curOpt = Tcl_GetString(curOptPtr);
+ size_t length = curOptPtr->length;
+
+ c = curOpt[0];
+
+ if ((c == 't')
+ && (strncmp(curOpt, "top", length)) == 0) {
+ packPtr->side = TOP;
+ } else if ((c == 'b')
+ && (strncmp(curOpt, "bottom", length)) == 0) {
+ packPtr->side = BOTTOM;
+ } else if ((c == 'l')
+ && (strncmp(curOpt, "left", length)) == 0) {
+ packPtr->side = LEFT;
+ } else if ((c == 'r')
+ && (strncmp(curOpt, "right", length)) == 0) {
+ packPtr->side = RIGHT;
+ } else if ((c == 'e')
+ && (strncmp(curOpt, "expand", length)) == 0) {
+ packPtr->flags |= EXPAND;
+ } else if ((c == 'f')
+ && (strcmp(curOpt, "fill")) == 0) {
+ packPtr->flags |= FILLX|FILLY;
+ } else if ((length == 5) && (strcmp(curOpt, "fillx")) == 0) {
+ packPtr->flags |= FILLX;
+ } else if ((length == 5) && (strcmp(curOpt, "filly")) == 0) {
+ packPtr->flags |= FILLY;
+ } else if ((c == 'p') && (strcmp(curOpt, "padx")) == 0) {
+ if (optionCount < (index+2)) {
+ missingPad:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "wrong # args: \"%s\" option must be"
+ " followed by screen distance", curOpt));
+ Tcl_SetErrorCode(interp, "TK", "OLDPACK", "BAD_PARAMETER",
+ NULL);
+ return TCL_ERROR;
+ }
+ if (TkParsePadAmount(interp, tkwin, options[index+1],
+ &packPtr->padLeft, &packPtr->padX) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ packPtr->padX /= 2;
+ packPtr->padLeft /= 2;
+ packPtr->iPadX = 0;
+ index++;
+ } else if ((c == 'p') && (strcmp(curOpt, "pady")) == 0) {
+ if (optionCount < (index+2)) {
+ goto missingPad;
+ }
+ if (TkParsePadAmount(interp, tkwin, options[index+1],
+ &packPtr->padTop, &packPtr->padY) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ packPtr->padY /= 2;
+ packPtr->padTop /= 2;
+ packPtr->iPadY = 0;
+ index++;
+ } else if ((c == 'f') && (length > 1)
+ && (strncmp(curOpt, "frame", (size_t) length) == 0)) {
+ if (optionCount < (index+2)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "wrong # args: \"frame\""
+ " option must be followed by anchor point", -1));
+ Tcl_SetErrorCode(interp, "TK", "OLDPACK", "BAD_PARAMETER",
+ NULL);
+ return TCL_ERROR;
+ }
+ if (Tk_GetAnchorFromObj(interp, options[index+1],
+ &packPtr->anchor) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ index++;
+ } else {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad option \"%s\": should be top, bottom, left,"
+ " right, expand, fill, fillx, filly, padx, pady, or"
+ " frame", curOpt));
+ Tcl_SetErrorCode(interp, "TK", "OLDPACK", "BAD_PARAMETER",
+ NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ if (packPtr != prevPtr) {
+ /*
+ * Unpack this window if it's currently packed.
+ */
+
+ if (packPtr->masterPtr != NULL) {
+ if ((packPtr->masterPtr != masterPtr) &&
+ (packPtr->masterPtr->tkwin
+ != Tk_Parent(packPtr->tkwin))) {
+ Tk_UnmaintainGeometry(packPtr->tkwin,
+ packPtr->masterPtr->tkwin);
+ }
+ Unlink(packPtr);
+ }
+
+ /*
+ * Add the window in the correct place in its master's packing
+ * order, then make sure that the window is managed by us.
+ */
+
+ packPtr->masterPtr = masterPtr;
+ if (prevPtr == NULL) {
+ packPtr->nextPtr = masterPtr->slavePtr;
+ masterPtr->slavePtr = packPtr;
+ } else {
+ packPtr->nextPtr = prevPtr->nextPtr;
+ prevPtr->nextPtr = packPtr;
+ }
+ Tk_ManageGeometry(tkwin, &packerType, packPtr);
+
+ if (!(masterPtr->flags & DONT_PROPAGATE)) {
+ if (TkSetGeometryMaster(interp, masterPtr->tkwin, "pack")
+ != TCL_OK) {
+ Tk_ManageGeometry(tkwin, NULL, NULL);
+ Unlink(packPtr);
+ return TCL_ERROR;
+ }
+ masterPtr->flags |= ALLOCED_MASTER;
+ }
+ }
+ }
+
+ /*
+ * Arrange for the master to be re-packed at the first idle moment.
+ */
+
+ if (masterPtr->abortPtr != NULL) {
+ *masterPtr->abortPtr = 1;
+ }
+ if (!(masterPtr->flags & REQUESTED_REPACK)) {
+ masterPtr->flags |= REQUESTED_REPACK;
+ Tcl_DoWhenIdle(ArrangePacking, masterPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Unlink --
+ *
+ * Remove a packer from its master's list of slaves.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The master will be scheduled for repacking.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+Unlink(
+ register Packer *packPtr) /* Window to unlink. */
+{
+ register Packer *masterPtr, *packPtr2;
+
+ masterPtr = packPtr->masterPtr;
+ if (masterPtr == NULL) {
+ return;
+ }
+ if (masterPtr->slavePtr == packPtr) {
+ masterPtr->slavePtr = packPtr->nextPtr;
+ } else {
+ for (packPtr2 = masterPtr->slavePtr; ; packPtr2 = packPtr2->nextPtr) {
+ if (packPtr2 == NULL) {
+ Tcl_Panic("Unlink couldn't find previous window");
+ }
+ if (packPtr2->nextPtr == packPtr) {
+ packPtr2->nextPtr = packPtr->nextPtr;
+ break;
+ }
+ }
+ }
+ if (!(masterPtr->flags & REQUESTED_REPACK)) {
+ masterPtr->flags |= REQUESTED_REPACK;
+ Tcl_DoWhenIdle(ArrangePacking, masterPtr);
+ }
+ if (masterPtr->abortPtr != NULL) {
+ *masterPtr->abortPtr = 1;
+ }
+
+ packPtr->masterPtr = NULL;
+
+ /*
+ * If we have emptied this master from slaves it means we are no longer
+ * handling it and should mark it as free.
+ */
+
+ if ((masterPtr->slavePtr == NULL) && (masterPtr->flags & ALLOCED_MASTER)) {
+ TkFreeGeometryMaster(masterPtr->tkwin, "pack");
+ masterPtr->flags &= ~ALLOCED_MASTER;
+ }
+
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyPacker --
+ *
+ * This function is invoked by Tcl_EventuallyFree or Tcl_Release to clean
+ * up the internal structure of a packer at a safe time (when no-one is
+ * using it anymore).
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Everything associated with the packer is freed up.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DestroyPacker(
+ void *memPtr) /* Info about packed window that is now
+ * dead. */
+{
+ register Packer *packPtr = memPtr;
+
+ ckfree(packPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PackStructureProc --
+ *
+ * This function is invoked by the Tk event dispatcher in response to
+ * StructureNotify events.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If a window was just deleted, clean up all its packer-related
+ * information. If it was just resized, repack its slaves, if any.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+PackStructureProc(
+ ClientData clientData, /* Our information about window referred to by
+ * eventPtr. */
+ XEvent *eventPtr) /* Describes what just happened. */
+{
+ register Packer *packPtr = clientData;
+
+ if (eventPtr->type == ConfigureNotify) {
+ if ((packPtr->slavePtr != NULL)
+ && !(packPtr->flags & REQUESTED_REPACK)) {
+ packPtr->flags |= REQUESTED_REPACK;
+ Tcl_DoWhenIdle(ArrangePacking, packPtr);
+ }
+ if ((packPtr->masterPtr != NULL)
+ && (packPtr->doubleBw != 2*Tk_Changes(packPtr->tkwin)->border_width)) {
+ if (!(packPtr->masterPtr->flags & REQUESTED_REPACK)) {
+ packPtr->doubleBw = 2*Tk_Changes(packPtr->tkwin)->border_width;
+ packPtr->masterPtr->flags |= REQUESTED_REPACK;
+ Tcl_DoWhenIdle(ArrangePacking, packPtr->masterPtr);
+ }
+ }
+ } else if (eventPtr->type == DestroyNotify) {
+ register Packer *slavePtr, *nextPtr;
+
+ if (packPtr->masterPtr != NULL) {
+ Unlink(packPtr);
+ }
+
+ for (slavePtr = packPtr->slavePtr; slavePtr != NULL;
+ slavePtr = nextPtr) {
+ Tk_ManageGeometry(slavePtr->tkwin, NULL, NULL);
+ Tk_UnmapWindow(slavePtr->tkwin);
+ slavePtr->masterPtr = NULL;
+ nextPtr = slavePtr->nextPtr;
+ slavePtr->nextPtr = NULL;
+ }
+
+ if (packPtr->tkwin != NULL) {
+ TkDisplay *dispPtr = ((TkWindow *) packPtr->tkwin)->dispPtr;
+ Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->packerHashTable,
+ (char *) packPtr->tkwin));
+ }
+
+ if (packPtr->flags & REQUESTED_REPACK) {
+ Tcl_CancelIdleCall(ArrangePacking, packPtr);
+ }
+ packPtr->tkwin = NULL;
+ Tcl_EventuallyFree(packPtr, (Tcl_FreeProc *) DestroyPacker);
+ } else if (eventPtr->type == MapNotify) {
+ /*
+ * When a master gets mapped, must redo the geometry computation so
+ * that all of its slaves get remapped.
+ */
+
+ if ((packPtr->slavePtr != NULL)
+ && !(packPtr->flags & REQUESTED_REPACK)) {
+ packPtr->flags |= REQUESTED_REPACK;
+ Tcl_DoWhenIdle(ArrangePacking, packPtr);
+ }
+ } else if (eventPtr->type == UnmapNotify) {
+ register Packer *packPtr2;
+
+ /*
+ * Unmap all of the slaves when the master gets unmapped, so that they
+ * don't bother to keep redisplaying themselves.
+ */
+
+ for (packPtr2 = packPtr->slavePtr; packPtr2 != NULL;
+ packPtr2 = packPtr2->nextPtr) {
+ Tk_UnmapWindow(packPtr2->tkwin);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConfigureSlaves --
+ *
+ * This implements the guts of the "pack configure" command. Given a list
+ * of slaves and configuration options, it arranges for the packer to
+ * manage the slaves and sets the specified options.
+ *
+ * Results:
+ * TCL_OK is returned if all went well. Otherwise, TCL_ERROR is returned
+ * and the interp's result is set to contain an error message.
+ *
+ * Side effects:
+ * Slave windows get taken over by the packer.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ConfigureSlaves(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Tk_Window tkwin, /* Any window in application containing
+ * slaves. Used to look up slave names. */
+ int objc, /* Number of elements in argv. */
+ Tcl_Obj *const objv[]) /* Argument objects: contains one or more
+ * window names followed by any number of
+ * "option value" pairs. Caller must make sure
+ * that there is at least one window name. */
+{
+ Packer *masterPtr, *slavePtr, *prevPtr, *otherPtr;
+ Tk_Window other, slave, parent, ancestor;
+ TkWindow *master;
+ int i, j, numWindows, tmp, positionGiven;
+ const char *string;
+ static const char *const optionStrings[] = {
+ "-after", "-anchor", "-before", "-expand", "-fill",
+ "-in", "-ipadx", "-ipady", "-padx", "-pady", "-side", NULL };
+ enum options {
+ CONF_AFTER, CONF_ANCHOR, CONF_BEFORE, CONF_EXPAND, CONF_FILL,
+ CONF_IN, CONF_IPADX, CONF_IPADY, CONF_PADX, CONF_PADY, CONF_SIDE };
+ int index, side;
+
+ /*
+ * Find out how many windows are specified.
+ */
+
+ for (numWindows = 0; numWindows < objc; numWindows++) {
+ string = Tcl_GetString(objv[numWindows]);
+ if (string[0] != '.') {
+ break;
+ }
+ }
+
+ /*
+ * Iterate over all of the slave windows, parsing the configuration
+ * options for each slave. It's a bit wasteful to re-parse the options for
+ * each slave, but things get too messy if we try to parse the arguments
+ * just once at the beginning. For example, if a slave already is packed
+ * we want to just change a few existing values without resetting
+ * everything. If there are multiple windows, the -after, -before, and -in
+ * options only get processed for the first window.
+ */
+
+ masterPtr = NULL;
+ prevPtr = NULL;
+ positionGiven = 0;
+ for (j = 0; j < numWindows; j++) {
+ if (TkGetWindowFromObj(interp, tkwin, objv[j], &slave) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tk_TopWinHierarchy(slave)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't pack \"%s\": it's a top-level window",
+ Tcl_GetString(objv[j])));
+ Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "TOPLEVEL", NULL);
+ return TCL_ERROR;
+ }
+ slavePtr = GetPacker(slave);
+ slavePtr->flags &= ~OLD_STYLE;
+
+ /*
+ * If the slave isn't currently packed, reset all of its configuration
+ * information to default values (there could be old values left from
+ * a previous packing).
+ */
+
+ if (slavePtr->masterPtr == NULL) {
+ slavePtr->side = TOP;
+ slavePtr->anchor = TK_ANCHOR_CENTER;
+ slavePtr->padX = slavePtr->padY = 0;
+ slavePtr->padLeft = slavePtr->padTop = 0;
+ slavePtr->iPadX = slavePtr->iPadY = 0;
+ slavePtr->flags &= ~(FILLX|FILLY|EXPAND);
+ }
+
+ for (i = numWindows; i < objc; i+=2) {
+ if ((i+2) > objc) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "extra option \"%s\" (option with no value?)",
+ Tcl_GetString(objv[i])));
+ Tcl_SetErrorCode(interp, "TK", "PACK", "BAD_PARAMETER", NULL);
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObjStruct(interp, objv[i], optionStrings,
+ sizeof(char *), "option", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch ((enum options) index) {
+ case CONF_AFTER:
+ if (j == 0) {
+ if (TkGetWindowFromObj(interp, tkwin, objv[i+1], &other)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ prevPtr = GetPacker(other);
+ if (prevPtr->masterPtr == NULL) {
+ notPacked:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "window \"%s\" isn't packed",
+ Tcl_GetString(objv[i+1])));
+ Tcl_SetErrorCode(interp, "TK", "PACK", "NOT_PACKED",
+ NULL);
+ return TCL_ERROR;
+ }
+ masterPtr = prevPtr->masterPtr;
+ positionGiven = 1;
+ }
+ break;
+ case CONF_ANCHOR:
+ if (Tk_GetAnchorFromObj(interp, objv[i+1], &slavePtr->anchor)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+ case CONF_BEFORE:
+ if (j == 0) {
+ if (TkGetWindowFromObj(interp, tkwin, objv[i+1], &other)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ otherPtr = GetPacker(other);
+ if (otherPtr->masterPtr == NULL) {
+ goto notPacked;
+ }
+ masterPtr = otherPtr->masterPtr;
+ prevPtr = masterPtr->slavePtr;
+ if (prevPtr == otherPtr) {
+ prevPtr = NULL;
+ } else {
+ while (prevPtr->nextPtr != otherPtr) {
+ prevPtr = prevPtr->nextPtr;
+ }
+ }
+ positionGiven = 1;
+ }
+ break;
+ case CONF_EXPAND:
+ if (Tcl_GetBooleanFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ slavePtr->flags &= ~EXPAND;
+ if (tmp) {
+ slavePtr->flags |= EXPAND;
+ }
+ break;
+ case CONF_FILL:
+ string = Tcl_GetString(objv[i+1]);
+ if (strcmp(string, "none") == 0) {
+ slavePtr->flags &= ~(FILLX|FILLY);
+ } else if (strcmp(string, "x") == 0) {
+ slavePtr->flags = (slavePtr->flags & ~FILLY) | FILLX;
+ } else if (strcmp(string, "y") == 0) {
+ slavePtr->flags = (slavePtr->flags & ~FILLX) | FILLY;
+ } else if (strcmp(string, "both") == 0) {
+ slavePtr->flags |= FILLX|FILLY;
+ } else {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad fill style \"%s\": must be "
+ "none, x, y, or both", string));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "FILL", NULL);
+ return TCL_ERROR;
+ }
+ break;
+ case CONF_IN:
+ if (j == 0) {
+ if (TkGetWindowFromObj(interp, tkwin, objv[i+1], &other)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ masterPtr = GetPacker(other);
+ prevPtr = masterPtr->slavePtr;
+ if (prevPtr != NULL) {
+ while (prevPtr->nextPtr != NULL) {
+ prevPtr = prevPtr->nextPtr;
+ }
+ }
+ positionGiven = 1;
+ }
+ break;
+ case CONF_IPADX:
+ if ((Tk_GetPixelsFromObj(interp, slave, objv[i+1], &tmp)
+ != TCL_OK) || (tmp < 0)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad ipadx value \"%s\": must be positive screen"
+ " distance", Tcl_GetString(objv[i+1])));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "INT_PAD", NULL);
+ return TCL_ERROR;
+ }
+ slavePtr->iPadX = tmp * 2;
+ break;
+ case CONF_IPADY:
+ if ((Tk_GetPixelsFromObj(interp, slave, objv[i+1], &tmp)
+ != TCL_OK) || (tmp < 0)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad ipady value \"%s\": must be positive screen"
+ " distance", Tcl_GetString(objv[i+1])));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "INT_PAD", NULL);
+ return TCL_ERROR;
+ }
+ slavePtr->iPadY = tmp * 2;
+ break;
+ case CONF_PADX:
+ if (TkParsePadAmount(interp, slave, objv[i+1],
+ &slavePtr->padLeft, &slavePtr->padX) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+ case CONF_PADY:
+ if (TkParsePadAmount(interp, slave, objv[i+1],
+ &slavePtr->padTop, &slavePtr->padY) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+ case CONF_SIDE:
+ if (Tcl_GetIndexFromObjStruct(interp, objv[i+1], sideNames,
+ sizeof(char *), "side", TCL_EXACT, &side) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ slavePtr->side = (Side) side;
+ break;
+ }
+ }
+
+ /*
+ * If no position in a packing list was specified and the slave is
+ * already packed, then leave it in its current location in its
+ * current packing list.
+ */
+
+ if (!positionGiven && (slavePtr->masterPtr != NULL)) {
+ masterPtr = slavePtr->masterPtr;
+ goto scheduleLayout;
+ }
+
+ /*
+ * If the slave is going to be put back after itself or the same -in
+ * window is passed in again, then just skip the whole operation,
+ * since it won't work anyway.
+ */
+
+ if (prevPtr == slavePtr) {
+ masterPtr = slavePtr->masterPtr;
+ goto scheduleLayout;
+ }
+
+ /*
+ * If none of the "-in", "-before", or "-after" options has been
+ * specified, arrange for the slave to go at the end of the order for
+ * its parent.
+ */
+
+ if (!positionGiven) {
+ masterPtr = GetPacker(Tk_Parent(slave));
+ prevPtr = masterPtr->slavePtr;
+ if (prevPtr != NULL) {
+ while (prevPtr->nextPtr != NULL) {
+ prevPtr = prevPtr->nextPtr;
+ }
+ }
+ }
+
+ /*
+ * Make sure that the slave's parent is either the master or an
+ * ancestor of the master, and that the master and slave aren't the
+ * same.
+ */
+
+ parent = Tk_Parent(slave);
+ for (ancestor = masterPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) {
+ if (ancestor == parent) {
+ break;
+ }
+ if (Tk_TopWinHierarchy(ancestor)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't pack %s inside %s", Tcl_GetString(objv[j]),
+ Tk_PathName(masterPtr->tkwin)));
+ Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "HIERARCHY", NULL);
+ return TCL_ERROR;
+ }
+ }
+ if (slave == masterPtr->tkwin) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't pack %s inside itself", Tcl_GetString(objv[j])));
+ Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "SELF", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Check for management loops.
+ */
+
+ for (master = (TkWindow *)masterPtr->tkwin; master != NULL;
+ master = (TkWindow *)TkGetGeomMaster(master)) {
+ if (master == (TkWindow *)slave) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't put %s inside %s, would cause management loop",
+ Tcl_GetString(objv[j]), Tk_PathName(masterPtr->tkwin)));
+ Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "LOOP", NULL);
+ return TCL_ERROR;
+ }
+ }
+ if (masterPtr->tkwin != Tk_Parent(slave)) {
+ ((TkWindow *)slave)->maintainerPtr = (TkWindow *)masterPtr->tkwin;
+ }
+
+ /*
+ * Unpack the slave if it's currently packed, then position it after
+ * prevPtr.
+ */
+
+ if (slavePtr->masterPtr != NULL) {
+ if ((slavePtr->masterPtr != masterPtr) &&
+ (slavePtr->masterPtr->tkwin
+ != Tk_Parent(slavePtr->tkwin))) {
+ Tk_UnmaintainGeometry(slavePtr->tkwin,
+ slavePtr->masterPtr->tkwin);
+ }
+ Unlink(slavePtr);
+ }
+
+ slavePtr->masterPtr = masterPtr;
+ if (prevPtr == NULL) {
+ slavePtr->nextPtr = masterPtr->slavePtr;
+ masterPtr->slavePtr = slavePtr;
+ } else {
+ slavePtr->nextPtr = prevPtr->nextPtr;
+ prevPtr->nextPtr = slavePtr;
+ }
+ Tk_ManageGeometry(slave, &packerType, slavePtr);
+ prevPtr = slavePtr;
+
+ if (!(masterPtr->flags & DONT_PROPAGATE)) {
+ if (TkSetGeometryMaster(interp, masterPtr->tkwin, "pack")
+ != TCL_OK) {
+ Tk_ManageGeometry(slave, NULL, NULL);
+ Unlink(slavePtr);
+ return TCL_ERROR;
+ }
+ masterPtr->flags |= ALLOCED_MASTER;
+ }
+
+ /*
+ * Arrange for the master to be re-packed at the first idle moment.
+ */
+
+ scheduleLayout:
+ if (masterPtr->abortPtr != NULL) {
+ *masterPtr->abortPtr = 1;
+ }
+ if (!(masterPtr->flags & REQUESTED_REPACK)) {
+ masterPtr->flags |= REQUESTED_REPACK;
+ Tcl_DoWhenIdle(ArrangePacking, masterPtr);
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkPanedWindow.c b/tk8.6/generic/tkPanedWindow.c
new file mode 100644
index 0000000..80ddb33
--- /dev/null
+++ b/tk8.6/generic/tkPanedWindow.c
@@ -0,0 +1,3157 @@
+/*
+ * tkPanedWindow.c --
+ *
+ * This module implements "paned window" widgets that are object based. A
+ * "paned window" is a widget that manages the geometry for some number
+ * of other widgets, placing a movable "sash" between them, which can be
+ * used to alter the relative sizes of adjacent widgets.
+ *
+ * Copyright (c) 1997 Sun Microsystems, Inc.
+ * Copyright (c) 2000 Ajuba Solutions.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "default.h"
+#include "tkInt.h"
+
+/*
+ * Flag values for "sticky"ness. The 16 combinations subsume the packer's
+ * notion of anchor and fill.
+ *
+ * STICK_NORTH This window sticks to the top of its cavity.
+ * STICK_EAST This window sticks to the right edge of its cavity.
+ * STICK_SOUTH This window sticks to the bottom of its cavity.
+ * STICK_WEST This window sticks to the left edge of its cavity.
+ */
+
+#define STICK_NORTH 1
+#define STICK_EAST 2
+#define STICK_SOUTH 4
+#define STICK_WEST 8
+
+/*
+ * The following table defines the legal values for the -orient option.
+ */
+
+static const char *const orientStrings[] = {
+ "horizontal", "vertical", NULL
+};
+
+enum orient { ORIENT_HORIZONTAL, ORIENT_VERTICAL };
+
+/*
+ * The following table defines the legal values for the -stretch option.
+ */
+
+static const char *const stretchStrings[] = {
+ "always", "first", "last", "middle", "never", NULL
+};
+
+enum stretch {
+ STRETCH_ALWAYS, /* Always give extra space to this pane. */
+ STRETCH_FIRST, /* Give extra space to pane if it is first. */
+ STRETCH_LAST, /* Give extra space to pane if it is last. */
+ STRETCH_MIDDLE, /* Give extra space to pane only if it is
+ * neither first nor last. */
+ STRETCH_NEVER /* Never give extra space to this pane. */
+};
+
+/*
+ * Codify the stretchiness rule in one place.
+ */
+
+#define IsStretchable(stretch,index,first,last) \
+ (((stretch) == STRETCH_ALWAYS) || \
+ ((stretch) == STRETCH_FIRST && (index) == (first)) || \
+ ((stretch) == STRETCH_LAST && (index) == (last)) || \
+ ((stretch) == STRETCH_MIDDLE && (index) != (first) && (index) != (last)))
+
+typedef struct {
+ Tk_OptionTable pwOptions; /* Token for paned window option table. */
+ Tk_OptionTable slaveOpts; /* Token for slave cget option table. */
+} OptionTables;
+
+/*
+ * One structure of the following type is kept for each window
+ * managed by a paned window widget.
+ */
+
+typedef struct Slave {
+ Tk_Window tkwin; /* Window being managed. */
+ int minSize; /* Minimum size of this pane, on the relevant
+ * axis, in pixels. */
+ int padx; /* Additional padding requested for slave, in
+ * the x dimension. */
+ int pady; /* Additional padding requested for slave, in
+ * the y dimension. */
+ Tcl_Obj *widthPtr, *heightPtr;
+ /* Tcl_Obj rep's of slave width/height, to
+ * allow for null values. */
+ int width; /* Slave width. */
+ int height; /* Slave height. */
+ int sticky; /* Sticky string. */
+ int x, y; /* Coordinates of the widget. */
+ int paneWidth, paneHeight; /* Pane dimensions (may be different from
+ * slave width/height). */
+ int sashx, sashy; /* Coordinates of the sash of the right or
+ * bottom of this pane. */
+ int markx, marky; /* Coordinates of the last mark set for the
+ * sash. */
+ int handlex, handley; /* Coordinates of the sash handle. */
+ enum stretch stretch; /* Controls how slave grows/shrinks */
+ int hide; /* Controls visibility of pane */
+ struct PanedWindow *masterPtr;
+ /* Paned window managing the window. */
+ Tk_Window after; /* Placeholder for parsing options. */
+ Tk_Window before; /* Placeholder for parsing options. */
+} Slave;
+
+/*
+ * A data structure of the following type is kept for each paned window widget
+ * managed by this file:
+ */
+
+typedef struct PanedWindow {
+ Tk_Window tkwin; /* Window that embodies the paned window. */
+ Tk_Window proxywin; /* Window for the resizing proxy. */
+ Display *display; /* X's token for the window's display. */
+ Tcl_Interp *interp; /* Interpreter associated with widget. */
+ Tcl_Command widgetCmd; /* Token for square's widget command. */
+ Tk_OptionTable optionTable; /* Token representing the configuration
+ * specifications. */
+ Tk_OptionTable slaveOpts; /* Token for slave cget table. */
+ Tk_3DBorder background; /* Background color. */
+ int borderWidth; /* Value of -borderwidth option. */
+ int relief; /* 3D border effect (TK_RELIEF_RAISED, etc) */
+ Tcl_Obj *widthPtr; /* Tcl_Obj rep for width. */
+ Tcl_Obj *heightPtr; /* Tcl_Obj rep for height. */
+ int width, height; /* Width and height of the widget. */
+ enum orient orient; /* Orientation of the widget. */
+ Tk_Cursor cursor; /* Current cursor for window, or None. */
+ int resizeOpaque; /* Boolean indicating whether resize should be
+ * opaque or rubberband style. */
+ int sashRelief; /* Relief used to draw sash. */
+ int sashWidth; /* Width of each sash, in pixels. */
+ Tcl_Obj *sashWidthPtr; /* Tcl_Obj rep for sash width. */
+ int sashPad; /* Additional padding around each sash. */
+ Tcl_Obj *sashPadPtr; /* Tcl_Obj rep for sash padding. */
+ int showHandle; /* Boolean indicating whether sash handles
+ * should be drawn. */
+ int handleSize; /* Size of one side of a sash handle (handles
+ * are square), in pixels. */
+ int handlePad; /* Distance from border to draw handle. */
+ Tcl_Obj *handleSizePtr; /* Tcl_Obj rep for handle size. */
+ Tk_Cursor sashCursor; /* Cursor used when mouse is above a sash. */
+ GC gc; /* Graphics context for copying from
+ * off-screen pixmap onto screen. */
+ int proxyx, proxyy; /* Proxy x,y coordinates. */
+ Tk_3DBorder proxyBackground;/* Background color used to draw proxy. If NULL, use background. */
+ Tcl_Obj *proxyBorderWidthPtr; /* Tcl_Obj rep for proxyBorderWidth */
+ int proxyBorderWidth; /* Borderwidth used to draw proxy. */
+ int proxyRelief; /* Relief used to draw proxy, if TK_RELIEF_NULL then use relief. */
+ Slave **slaves; /* Pointer to array of Slaves. */
+ int numSlaves; /* Number of slaves. */
+ int sizeofSlaves; /* Number of elements in the slaves array. */
+ int flags; /* Flags for widget; see below. */
+} PanedWindow;
+
+/*
+ * Flags used for paned windows:
+ *
+ * REDRAW_PENDING: Non-zero means a DoWhenIdle handler has been
+ * queued to redraw this window.
+ *
+ * WIDGET_DELETED: Non-zero means that the paned window has been,
+ * or is in the process of being, deleted.
+ *
+ * RESIZE_PENDING: Non-zero means that the window might need to
+ * change its size (or the size of its panes)
+ * because of a change in the size of one of its
+ * children.
+ */
+
+#define REDRAW_PENDING 0x0001
+#define WIDGET_DELETED 0x0002
+#define REQUESTED_RELAYOUT 0x0004
+#define RECOMPUTE_GEOMETRY 0x0008
+#define PROXY_REDRAW_PENDING 0x0010
+#define RESIZE_PENDING 0x0020
+
+/*
+ * Forward declarations for functions defined later in this file:
+ */
+
+int Tk_PanedWindowObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static void PanedWindowCmdDeletedProc(ClientData clientData);
+static int ConfigurePanedWindow(Tcl_Interp *interp,
+ PanedWindow *pwPtr, int objc,
+ Tcl_Obj *const objv[]);
+static void DestroyPanedWindow(PanedWindow *pwPtr);
+static void DisplayPanedWindow(ClientData clientData);
+static void PanedWindowEventProc(ClientData clientData,
+ XEvent *eventPtr);
+static void ProxyWindowEventProc(ClientData clientData,
+ XEvent *eventPtr);
+static void DisplayProxyWindow(ClientData clientData);
+static void PanedWindowWorldChanged(ClientData instanceData);
+static int PanedWindowWidgetObjCmd(ClientData clientData,
+ Tcl_Interp *, int objc, Tcl_Obj * const objv[]);
+static void PanedWindowLostSlaveProc(ClientData clientData,
+ Tk_Window tkwin);
+static void PanedWindowReqProc(ClientData clientData,
+ Tk_Window tkwin);
+static void ArrangePanes(ClientData clientData);
+static void Unlink(Slave *slavePtr);
+static Slave * GetPane(PanedWindow *pwPtr, Tk_Window tkwin);
+static void GetFirstLastVisiblePane(PanedWindow *pwPtr,
+ int *firstPtr, int *lastPtr);
+static void SlaveStructureProc(ClientData clientData,
+ XEvent *eventPtr);
+static int PanedWindowSashCommand(PanedWindow *pwPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj * const objv[]);
+static int PanedWindowProxyCommand(PanedWindow *pwPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj * const objv[]);
+static void ComputeGeometry(PanedWindow *pwPtr);
+static int ConfigureSlaves(PanedWindow *pwPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj * const objv[]);
+static void DestroyOptionTables(ClientData clientData,
+ Tcl_Interp *interp);
+static int SetSticky(ClientData clientData, Tcl_Interp *interp,
+ Tk_Window tkwin, Tcl_Obj **value, char *recordPtr,
+ int internalOffset, char *oldInternalPtr,
+ int flags);
+static Tcl_Obj * GetSticky(ClientData clientData, Tk_Window tkwin,
+ char *recordPtr, int internalOffset);
+static void RestoreSticky(ClientData clientData, Tk_Window tkwin,
+ char *internalPtr, char *oldInternalPtr);
+static void AdjustForSticky(int sticky, int cavityWidth,
+ int cavityHeight, int *xPtr, int *yPtr,
+ int *slaveWidthPtr, int *slaveHeightPtr);
+static void MoveSash(PanedWindow *pwPtr, int sash, int diff);
+static int ObjectIsEmpty(Tcl_Obj *objPtr);
+static char * ComputeSlotAddress(char *recordPtr, int offset);
+static int PanedWindowIdentifyCoords(PanedWindow *pwPtr,
+ Tcl_Interp *interp, int x, int y);
+
+/*
+ * Sashes are between panes only, so there is one less sash than slaves
+ */
+
+#define ValidSashIndex(pwPtr, sash) \
+ (((sash) >= 0) && ((sash) < ((pwPtr)->numSlaves-1)))
+
+static const Tk_GeomMgr panedWindowMgrType = {
+ "panedwindow", /* name */
+ PanedWindowReqProc, /* requestProc */
+ PanedWindowLostSlaveProc, /* lostSlaveProc */
+};
+
+/*
+ * Information used for objv parsing.
+ */
+
+#define GEOMETRY 0x0001
+
+/*
+ * The following structure contains pointers to functions used for processing
+ * the custom "-sticky" option for slave windows.
+ */
+
+static const Tk_ObjCustomOption stickyOption = {
+ "sticky", /* name */
+ SetSticky, /* setProc */
+ GetSticky, /* getProc */
+ RestoreSticky, /* restoreProc */
+ NULL, /* freeProc */
+ 0
+};
+
+static const Tk_OptionSpec optionSpecs[] = {
+ {TK_OPTION_BORDER, "-background", "background", "Background",
+ DEF_PANEDWINDOW_BG_COLOR, -1, Tk_Offset(PanedWindow, background), 0,
+ DEF_PANEDWINDOW_BG_MONO, 0},
+ {TK_OPTION_SYNONYM, "-bd", NULL, NULL,
+ NULL, 0, -1, 0, "-borderwidth", 0},
+ {TK_OPTION_SYNONYM, "-bg", NULL, NULL,
+ NULL, 0, -1, 0, "-background", 0},
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ DEF_PANEDWINDOW_BORDERWIDTH, -1, Tk_Offset(PanedWindow, borderWidth),
+ 0, 0, GEOMETRY},
+ {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
+ DEF_PANEDWINDOW_CURSOR, -1, Tk_Offset(PanedWindow, cursor),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-handlepad", "handlePad", "HandlePad",
+ DEF_PANEDWINDOW_HANDLEPAD, -1, Tk_Offset(PanedWindow, handlePad),
+ 0, 0, GEOMETRY},
+ {TK_OPTION_PIXELS, "-handlesize", "handleSize", "HandleSize",
+ DEF_PANEDWINDOW_HANDLESIZE, Tk_Offset(PanedWindow, handleSizePtr),
+ Tk_Offset(PanedWindow, handleSize), 0, 0, GEOMETRY},
+ {TK_OPTION_PIXELS, "-height", "height", "Height",
+ DEF_PANEDWINDOW_HEIGHT, Tk_Offset(PanedWindow, heightPtr),
+ Tk_Offset(PanedWindow, height), TK_OPTION_NULL_OK, 0, GEOMETRY},
+ {TK_OPTION_BOOLEAN, "-opaqueresize", "opaqueResize", "OpaqueResize",
+ DEF_PANEDWINDOW_OPAQUERESIZE, -1,
+ Tk_Offset(PanedWindow, resizeOpaque), 0, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient",
+ DEF_PANEDWINDOW_ORIENT, -1, Tk_Offset(PanedWindow, orient),
+ 0, orientStrings, GEOMETRY},
+ {TK_OPTION_BORDER, "-proxybackground", "proxyBackground", "ProxyBackground",
+ 0, -1, Tk_Offset(PanedWindow, proxyBackground), TK_OPTION_NULL_OK,
+ (ClientData) DEF_PANEDWINDOW_BG_MONO},
+ {TK_OPTION_PIXELS, "-proxyborderwidth", "proxyBorderWidth", "ProxyBorderWidth",
+ DEF_PANEDWINDOW_PROXYBORDER, Tk_Offset(PanedWindow, proxyBorderWidthPtr),
+ Tk_Offset(PanedWindow, proxyBorderWidth), 0, 0, GEOMETRY},
+ {TK_OPTION_RELIEF, "-proxyrelief", "proxyRelief", "Relief",
+ 0, -1, Tk_Offset(PanedWindow, proxyRelief),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ DEF_PANEDWINDOW_RELIEF, -1, Tk_Offset(PanedWindow, relief), 0, 0, 0},
+ {TK_OPTION_CURSOR, "-sashcursor", "sashCursor", "Cursor",
+ DEF_PANEDWINDOW_SASHCURSOR, -1, Tk_Offset(PanedWindow, sashCursor),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-sashpad", "sashPad", "SashPad",
+ DEF_PANEDWINDOW_SASHPAD, -1, Tk_Offset(PanedWindow, sashPad),
+ 0, 0, GEOMETRY},
+ {TK_OPTION_RELIEF, "-sashrelief", "sashRelief", "Relief",
+ DEF_PANEDWINDOW_SASHRELIEF, -1, Tk_Offset(PanedWindow, sashRelief),
+ 0, 0, 0},
+ {TK_OPTION_PIXELS, "-sashwidth", "sashWidth", "Width",
+ DEF_PANEDWINDOW_SASHWIDTH, Tk_Offset(PanedWindow, sashWidthPtr),
+ Tk_Offset(PanedWindow, sashWidth), 0, 0, GEOMETRY},
+ {TK_OPTION_BOOLEAN, "-showhandle", "showHandle", "ShowHandle",
+ DEF_PANEDWINDOW_SHOWHANDLE, -1, Tk_Offset(PanedWindow, showHandle),
+ 0, 0, GEOMETRY},
+ {TK_OPTION_PIXELS, "-width", "width", "Width",
+ DEF_PANEDWINDOW_WIDTH, Tk_Offset(PanedWindow, widthPtr),
+ Tk_Offset(PanedWindow, width), TK_OPTION_NULL_OK, 0, GEOMETRY},
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}
+};
+
+static const Tk_OptionSpec slaveOptionSpecs[] = {
+ {TK_OPTION_WINDOW, "-after", NULL, NULL,
+ DEF_PANEDWINDOW_PANE_AFTER, -1, Tk_Offset(Slave, after),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_WINDOW, "-before", NULL, NULL,
+ DEF_PANEDWINDOW_PANE_BEFORE, -1, Tk_Offset(Slave, before),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-height", NULL, NULL,
+ DEF_PANEDWINDOW_PANE_HEIGHT, Tk_Offset(Slave, heightPtr),
+ Tk_Offset(Slave, height), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_BOOLEAN, "-hide", "hide", "Hide",
+ DEF_PANEDWINDOW_PANE_HIDE, -1, Tk_Offset(Slave, hide), 0,0,GEOMETRY},
+ {TK_OPTION_PIXELS, "-minsize", NULL, NULL,
+ DEF_PANEDWINDOW_PANE_MINSIZE, -1, Tk_Offset(Slave, minSize), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-padx", NULL, NULL,
+ DEF_PANEDWINDOW_PANE_PADX, -1, Tk_Offset(Slave, padx), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-pady", NULL, NULL,
+ DEF_PANEDWINDOW_PANE_PADY, -1, Tk_Offset(Slave, pady), 0, 0, 0},
+ {TK_OPTION_CUSTOM, "-sticky", NULL, NULL,
+ DEF_PANEDWINDOW_PANE_STICKY, -1, Tk_Offset(Slave, sticky), 0,
+ &stickyOption, 0},
+ {TK_OPTION_STRING_TABLE, "-stretch", "stretch", "Stretch",
+ DEF_PANEDWINDOW_PANE_STRETCH, -1, Tk_Offset(Slave, stretch), 0,
+ (ClientData) stretchStrings, 0},
+ {TK_OPTION_PIXELS, "-width", NULL, NULL,
+ DEF_PANEDWINDOW_PANE_WIDTH, Tk_Offset(Slave, widthPtr),
+ Tk_Offset(Slave, width), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}
+};
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_PanedWindowObjCmd --
+ *
+ * This function is invoked to process the "panedwindow" Tcl command. It
+ * creates a new "panedwindow" widget.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * A new widget is created and configured.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_PanedWindowObjCmd(
+ ClientData clientData, /* NULL. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj * const objv[]) /* Argument objects. */
+{
+ PanedWindow *pwPtr;
+ Tk_Window tkwin, parent;
+ OptionTables *pwOpts;
+ XSetWindowAttributes atts;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?");
+ return TCL_ERROR;
+ }
+
+ tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),
+ Tcl_GetString(objv[1]), NULL);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+
+ pwOpts = (OptionTables *)
+ Tcl_GetAssocData(interp, "PanedWindowOptionTables", NULL);
+ if (pwOpts == NULL) {
+ /*
+ * The first time this function is invoked, the option tables will be
+ * NULL. We then create the option tables from the templates and store
+ * a pointer to the tables as the command's clinical so we'll have
+ * easy access to it in the future.
+ */
+
+ pwOpts = ckalloc(sizeof(OptionTables));
+
+ /*
+ * Set up an exit handler to free the optionTables struct.
+ */
+
+ Tcl_SetAssocData(interp, "PanedWindowOptionTables",
+ DestroyOptionTables, pwOpts);
+
+ /*
+ * Create the paned window option tables.
+ */
+
+ pwOpts->pwOptions = Tk_CreateOptionTable(interp, optionSpecs);
+ pwOpts->slaveOpts = Tk_CreateOptionTable(interp, slaveOptionSpecs);
+ }
+
+ Tk_SetClass(tkwin, "Panedwindow");
+
+ /*
+ * Allocate and initialize the widget record.
+ */
+
+ pwPtr = ckalloc(sizeof(PanedWindow));
+ memset((void *)pwPtr, 0, (sizeof(PanedWindow)));
+ pwPtr->tkwin = tkwin;
+ pwPtr->display = Tk_Display(tkwin);
+ pwPtr->interp = interp;
+ pwPtr->widgetCmd = Tcl_CreateObjCommand(interp,
+ Tk_PathName(pwPtr->tkwin), PanedWindowWidgetObjCmd, pwPtr,
+ PanedWindowCmdDeletedProc);
+ pwPtr->optionTable = pwOpts->pwOptions;
+ pwPtr->slaveOpts = pwOpts->slaveOpts;
+ pwPtr->relief = TK_RELIEF_RAISED;
+ pwPtr->gc = NULL;
+ pwPtr->cursor = NULL;
+ pwPtr->sashCursor = NULL;
+
+ /*
+ * Keep a hold of the associated tkwin until we destroy the widget,
+ * otherwise Tk might free it while we still need it.
+ */
+
+ Tcl_Preserve(pwPtr->tkwin);
+
+ if (Tk_InitOptions(interp, (char *) pwPtr, pwOpts->pwOptions,
+ tkwin) != TCL_OK) {
+ Tk_DestroyWindow(pwPtr->tkwin);
+ return TCL_ERROR;
+ }
+
+ Tk_CreateEventHandler(pwPtr->tkwin, ExposureMask|StructureNotifyMask,
+ PanedWindowEventProc, pwPtr);
+
+ /*
+ * Find the toplevel ancestor of the panedwindow, and make a proxy win as
+ * a child of that window; this way the proxy can always float above
+ * slaves in the panedwindow.
+ */
+
+ parent = Tk_Parent(pwPtr->tkwin);
+ while (!(Tk_IsTopLevel(parent))) {
+ parent = Tk_Parent(parent);
+ if (parent == NULL) {
+ parent = pwPtr->tkwin;
+ break;
+ }
+ }
+
+ pwPtr->proxywin = Tk_CreateAnonymousWindow(interp, parent, NULL);
+
+ /*
+ * The proxy window has to be able to share GCs with the main panedwindow
+ * despite being children of windows with potentially different
+ * characteristics, and it looks better that way too. [Bug 702230] Also
+ * set the X window save under attribute to avoid expose events as the
+ * proxy sash is dragged across the panes. [Bug 1036963]
+ */
+
+ Tk_SetWindowVisual(pwPtr->proxywin,
+ Tk_Visual(tkwin), Tk_Depth(tkwin), Tk_Colormap(tkwin));
+ Tk_CreateEventHandler(pwPtr->proxywin, ExposureMask, ProxyWindowEventProc,
+ pwPtr);
+ atts.save_under = True;
+ Tk_ChangeWindowAttributes(pwPtr->proxywin, CWSaveUnder, &atts);
+
+ if (ConfigurePanedWindow(interp, pwPtr, objc - 2, objv + 2) != TCL_OK) {
+ Tk_DestroyWindow(pwPtr->proxywin);
+ Tk_DestroyWindow(pwPtr->tkwin);
+ return TCL_ERROR;
+ }
+
+ Tcl_SetObjResult(interp, TkNewWindowObj(pwPtr->tkwin));
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * PanedWindowWidgetObjCmd --
+ *
+ * This function is invoked to process the Tcl command that corresponds
+ * to a widget managed by this module. See the user documentation for
+ * details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+PanedWindowWidgetObjCmd(
+ ClientData clientData, /* Information about square widget. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj * const objv[]) /* Argument objects. */
+{
+ PanedWindow *pwPtr = clientData;
+ int result = TCL_OK;
+ static const char *const optionStrings[] = {
+ "add", "cget", "configure", "forget", "identify", "panecget",
+ "paneconfigure", "panes", "proxy", "sash", NULL
+ };
+ enum options {
+ PW_ADD, PW_CGET, PW_CONFIGURE, PW_FORGET, PW_IDENTIFY, PW_PANECGET,
+ PW_PANECONFIGURE, PW_PANES, PW_PROXY, PW_SASH
+ };
+ Tcl_Obj *resultObj;
+ int index, count, i, x, y;
+ Tk_Window tkwin;
+ Slave *slavePtr;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg...?");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "command",
+ 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ Tcl_Preserve(pwPtr);
+
+ switch ((enum options) index) {
+ case PW_ADD:
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "widget ?widget ...?");
+ result = TCL_ERROR;
+ break;
+ }
+ result = ConfigureSlaves(pwPtr, interp, objc, objv);
+ break;
+
+ case PW_CGET:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option");
+ result = TCL_ERROR;
+ break;
+ }
+ resultObj = Tk_GetOptionValue(interp, (char *) pwPtr,
+ pwPtr->optionTable, objv[2], pwPtr->tkwin);
+ if (resultObj == NULL) {
+ result = TCL_ERROR;
+ } else {
+ Tcl_SetObjResult(interp, resultObj);
+ }
+ break;
+
+ case PW_CONFIGURE:
+ resultObj = NULL;
+ if (objc <= 3) {
+ resultObj = Tk_GetOptionInfo(interp, (char *) pwPtr,
+ pwPtr->optionTable,
+ (objc == 3) ? objv[2] : NULL, pwPtr->tkwin);
+ if (resultObj == NULL) {
+ result = TCL_ERROR;
+ } else {
+ Tcl_SetObjResult(interp, resultObj);
+ }
+ } else {
+ result = ConfigurePanedWindow(interp, pwPtr, objc - 2, objv + 2);
+ }
+ break;
+
+ case PW_FORGET: {
+ int i;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "widget ?widget ...?");
+ result = TCL_ERROR;
+ break;
+ }
+
+ /*
+ * Clean up each window named in the arg list.
+ */
+ for (count = 0, i = 2; i < objc; i++) {
+ Tk_Window slave = Tk_NameToWindow(interp, Tcl_GetString(objv[i]),
+ pwPtr->tkwin);
+
+ if (slave == NULL) {
+ continue;
+ }
+ slavePtr = GetPane(pwPtr, slave);
+ if ((slavePtr != NULL) && (slavePtr->masterPtr != NULL)) {
+ count++;
+ Tk_ManageGeometry(slave, NULL, NULL);
+ Tk_UnmaintainGeometry(slavePtr->tkwin, pwPtr->tkwin);
+ Tk_DeleteEventHandler(slavePtr->tkwin, StructureNotifyMask,
+ SlaveStructureProc, slavePtr);
+ Tk_UnmapWindow(slavePtr->tkwin);
+ Unlink(slavePtr);
+ }
+ if (count != 0) {
+ ComputeGeometry(pwPtr);
+ }
+ }
+ break;
+ }
+
+ case PW_IDENTIFY:
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "x y");
+ result = TCL_ERROR;
+ break;
+ }
+
+ if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {
+ result = TCL_ERROR;
+ break;
+ }
+ result = PanedWindowIdentifyCoords(pwPtr, interp, x, y);
+ break;
+
+ case PW_PANECGET:
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "pane option");
+ result = TCL_ERROR;
+ break;
+ }
+ tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), pwPtr->tkwin);
+ if (tkwin == NULL) {
+ result = TCL_ERROR;
+ break;
+ }
+ resultObj = NULL;
+ for (i = 0; i < pwPtr->numSlaves; i++) {
+ if (pwPtr->slaves[i]->tkwin == tkwin) {
+ resultObj = Tk_GetOptionValue(interp,
+ (char *) pwPtr->slaves[i], pwPtr->slaveOpts,
+ objv[3], tkwin);
+ }
+ }
+ if (resultObj == NULL) {
+ if (i == pwPtr->numSlaves) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "not managed by this window", -1));
+ Tcl_SetErrorCode(interp, "TK", "PANEDWINDOW", "UNMANAGED",
+ NULL);
+ }
+ result = TCL_ERROR;
+ } else {
+ Tcl_SetObjResult(interp, resultObj);
+ }
+ break;
+
+ case PW_PANECONFIGURE:
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "pane ?option? ?value option value ...?");
+ result = TCL_ERROR;
+ break;
+ }
+ resultObj = NULL;
+ if (objc <= 4) {
+ tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]),
+ pwPtr->tkwin);
+ if (tkwin == NULL) {
+ /*
+ * Just a plain old bad window; Tk_NameToWindow filled in an
+ * error message for us.
+ */
+
+ result = TCL_ERROR;
+ break;
+ }
+ for (i = 0; i < pwPtr->numSlaves; i++) {
+ if (pwPtr->slaves[i]->tkwin == tkwin) {
+ resultObj = Tk_GetOptionInfo(interp,
+ (char *) pwPtr->slaves[i], pwPtr->slaveOpts,
+ (objc == 4) ? objv[3] : NULL,
+ pwPtr->tkwin);
+ if (resultObj == NULL) {
+ result = TCL_ERROR;
+ } else {
+ Tcl_SetObjResult(interp, resultObj);
+ }
+ break;
+ }
+ }
+ } else {
+ result = ConfigureSlaves(pwPtr, interp, objc, objv);
+ }
+ break;
+
+ case PW_PANES:
+ resultObj = Tcl_NewObj();
+ for (i = 0; i < pwPtr->numSlaves; i++) {
+ Tcl_ListObjAppendElement(NULL, resultObj,
+ TkNewWindowObj(pwPtr->slaves[i]->tkwin));
+ }
+ Tcl_SetObjResult(interp, resultObj);
+ break;
+
+ case PW_PROXY:
+ result = PanedWindowProxyCommand(pwPtr, interp, objc, objv);
+ break;
+
+ case PW_SASH:
+ result = PanedWindowSashCommand(pwPtr, interp, objc, objv);
+ break;
+ }
+ Tcl_Release(pwPtr);
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConfigureSlaves --
+ *
+ * Add or alter the configuration options of a slave in a paned window.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * Depends on options; may add a slave to the paned window, may alter the
+ * geometry management options of a slave.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ConfigureSlaves(
+ PanedWindow *pwPtr, /* Information about paned window. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ int i, firstOptionArg, j, found, doubleBw, index, numNewSlaves, haveLoc;
+ int insertIndex;
+ Tk_Window tkwin = NULL, ancestor, parent;
+ Slave *slavePtr, **inserts, **newSlaves;
+ Slave options;
+ const char *arg;
+
+ /*
+ * Find the non-window name arguments; these are the configure options for
+ * the slaves. Also validate that the window names given are legitimate
+ * (ie, they are real windows, they are not the panedwindow itself, etc.).
+ */
+
+ for (i = 2; i < objc; i++) {
+ arg = Tcl_GetString(objv[i]);
+ if (arg[0] == '-') {
+ break;
+ } else {
+ tkwin = Tk_NameToWindow(interp, arg, pwPtr->tkwin);
+ if (tkwin == NULL) {
+ /*
+ * Just a plain old bad window; Tk_NameToWindow filled in an
+ * error message for us.
+ */
+
+ return TCL_ERROR;
+ } else if (tkwin == pwPtr->tkwin) {
+ /*
+ * A panedwindow cannot manage itself.
+ */
+
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't add %s to itself", arg));
+ Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "SELF", NULL);
+ return TCL_ERROR;
+ } else if (Tk_IsTopLevel(tkwin)) {
+ /*
+ * A panedwindow cannot manage a toplevel.
+ */
+
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't add toplevel %s to %s", arg,
+ Tk_PathName(pwPtr->tkwin)));
+ Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "TOPLEVEL", NULL);
+ return TCL_ERROR;
+ } else {
+ /*
+ * Make sure the panedwindow is the parent of the slave,
+ * or a descendant of the slave's parent.
+ */
+
+ parent = Tk_Parent(tkwin);
+ for (ancestor = pwPtr->tkwin;;ancestor = Tk_Parent(ancestor)) {
+ if (ancestor == parent) {
+ break;
+ }
+ if (Tk_IsTopLevel(ancestor)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't add %s to %s", arg,
+ Tk_PathName(pwPtr->tkwin)));
+ Tcl_SetErrorCode(interp, "TK", "GEOMETRY",
+ "HIERARCHY", NULL);
+ return TCL_ERROR;
+ }
+ }
+ }
+ }
+ }
+ firstOptionArg = i;
+
+ /*
+ * Pre-parse the configuration options, to get the before/after specifiers
+ * into an easy-to-find location (a local variable). Also, check the
+ * return from Tk_SetOptions once, here, so we can save a little bit of
+ * extra testing in the for loop below.
+ */
+
+ memset((void *)&options, 0, sizeof(Slave));
+ if (Tk_SetOptions(interp, (char *) &options, pwPtr->slaveOpts,
+ objc - firstOptionArg, objv + firstOptionArg,
+ pwPtr->tkwin, NULL, NULL) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * If either -after or -before was given, find the numerical index that
+ * corresponds to the given window. If both -after and -before are given,
+ * the option precedence is: -after, then -before.
+ */
+
+ index = -1;
+ haveLoc = 0;
+ if (options.after != NULL) {
+ tkwin = options.after;
+ haveLoc = 1;
+ for (i = 0; i < pwPtr->numSlaves; i++) {
+ if (options.after == pwPtr->slaves[i]->tkwin) {
+ index = i + 1;
+ break;
+ }
+ }
+ } else if (options.before != NULL) {
+ tkwin = options.before;
+ haveLoc = 1;
+ for (i = 0; i < pwPtr->numSlaves; i++) {
+ if (options.before == pwPtr->slaves[i]->tkwin) {
+ index = i;
+ break;
+ }
+ }
+ }
+
+ /*
+ * If a window was given for -after/-before, but it's not a window managed
+ * by the panedwindow, throw an error
+ */
+
+ if (haveLoc && index == -1) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "window \"%s\" is not managed by %s",
+ Tk_PathName(tkwin), Tk_PathName(pwPtr->tkwin)));
+ Tcl_SetErrorCode(interp, "TK", "PANEDWINDOW", "UNMANAGED", NULL);
+ Tk_FreeConfigOptions((char *) &options, pwPtr->slaveOpts,
+ pwPtr->tkwin);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Allocate an array to hold, in order, the pointers to the slave
+ * structures corresponding to the windows specified. Some of those
+ * structures may already have existed, some may be new.
+ */
+
+ inserts = ckalloc(sizeof(Slave *) * (firstOptionArg - 2));
+ insertIndex = 0;
+
+ /*
+ * Populate the inserts array, creating new slave structures as necessary,
+ * applying the options to each structure as we go, and, if necessary,
+ * marking the spot in the original slaves array as empty (for
+ * pre-existing slave structures).
+ */
+
+ for (i = 0, numNewSlaves = 0; i < firstOptionArg - 2; i++) {
+ /*
+ * We don't check that tkwin is NULL here, because the pre-pass above
+ * guarantees that the input at this stage is good.
+ */
+
+ tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[i + 2]),
+ pwPtr->tkwin);
+
+ found = 0;
+ for (j = 0; j < pwPtr->numSlaves; j++) {
+ if (pwPtr->slaves[j] != NULL && pwPtr->slaves[j]->tkwin == tkwin) {
+ Tk_SetOptions(interp, (char *) pwPtr->slaves[j],
+ pwPtr->slaveOpts, objc - firstOptionArg,
+ objv + firstOptionArg, pwPtr->tkwin, NULL, NULL);
+ if (pwPtr->slaves[j]->minSize < 0) {
+ pwPtr->slaves[j]->minSize = 0;
+ }
+ found = 1;
+
+ /*
+ * If the slave is supposed to move, add it to the inserts
+ * array now; otherwise, leave it where it is.
+ */
+
+ if (index != -1) {
+ inserts[insertIndex++] = pwPtr->slaves[j];
+ pwPtr->slaves[j] = NULL;
+ }
+ break;
+ }
+ }
+
+ if (found) {
+ continue;
+ }
+
+ /*
+ * Make sure this slave wasn't already put into the inserts array,
+ * i.e., when the user specifies the same window multiple times in a
+ * single add commaned.
+ */
+ for (j = 0; j < insertIndex; j++) {
+ if (inserts[j]->tkwin == tkwin) {
+ found = 1;
+ break;
+ }
+ }
+ if (found) {
+ continue;
+ }
+
+ /*
+ * Create a new slave structure and initialize it. All slaves start
+ * out with their "natural" dimensions.
+ */
+
+ slavePtr = ckalloc(sizeof(Slave));
+ memset(slavePtr, 0, sizeof(Slave));
+ Tk_InitOptions(interp, (char *)slavePtr, pwPtr->slaveOpts,
+ pwPtr->tkwin);
+ Tk_SetOptions(interp, (char *)slavePtr, pwPtr->slaveOpts,
+ objc - firstOptionArg, objv + firstOptionArg,
+ pwPtr->tkwin, NULL, NULL);
+ slavePtr->tkwin = tkwin;
+ slavePtr->masterPtr = pwPtr;
+ doubleBw = 2 * Tk_Changes(slavePtr->tkwin)->border_width;
+ if (slavePtr->width > 0) {
+ slavePtr->paneWidth = slavePtr->width;
+ } else {
+ slavePtr->paneWidth = Tk_ReqWidth(tkwin) + doubleBw;
+ }
+ if (slavePtr->height > 0) {
+ slavePtr->paneHeight = slavePtr->height;
+ } else {
+ slavePtr->paneHeight = Tk_ReqHeight(tkwin) + doubleBw;
+ }
+ if (slavePtr->minSize < 0) {
+ slavePtr->minSize = 0;
+ }
+
+ /*
+ * Set up the geometry management callbacks for this slave.
+ */
+
+ Tk_CreateEventHandler(slavePtr->tkwin, StructureNotifyMask,
+ SlaveStructureProc, slavePtr);
+ Tk_ManageGeometry(slavePtr->tkwin, &panedWindowMgrType, slavePtr);
+ inserts[insertIndex++] = slavePtr;
+ numNewSlaves++;
+ }
+
+ /*
+ * Allocate the new slaves array, then copy the slaves into it, in order.
+ */
+
+ i = sizeof(Slave *) * (pwPtr->numSlaves + numNewSlaves);
+ newSlaves = ckalloc(i);
+ memset(newSlaves, 0, (size_t) i);
+ if (index == -1) {
+ /*
+ * If none of the existing slaves have to be moved, just copy the old
+ * and append the new.
+ */
+ memcpy((void *)&(newSlaves[0]), pwPtr->slaves,
+ sizeof(Slave *) * pwPtr->numSlaves);
+ memcpy((void *)&(newSlaves[pwPtr->numSlaves]), inserts,
+ sizeof(Slave *) * numNewSlaves);
+ } else {
+ /*
+ * If some of the existing slaves were moved, the old slaves array
+ * will be partially populated, with some valid and some invalid
+ * entries. Walk through it, copying valid entries to the new slaves
+ * array as we go; when we get to the insert location for the new
+ * slaves, copy the inserts array over, then finish off the old slaves
+ * array.
+ */
+
+ for (i = 0, j = 0; i < index; i++) {
+ if (pwPtr->slaves[i] != NULL) {
+ newSlaves[j] = pwPtr->slaves[i];
+ j++;
+ }
+ }
+
+ memcpy((void *)&(newSlaves[j]), inserts, sizeof(Slave *)*insertIndex);
+ j += firstOptionArg - 2;
+
+ for (i = index; i < pwPtr->numSlaves; i++) {
+ if (pwPtr->slaves[i] != NULL) {
+ newSlaves[j] = pwPtr->slaves[i];
+ j++;
+ }
+ }
+ }
+
+ /*
+ * Make the new slaves array the paned window's slave array, and clean up.
+ */
+
+ ckfree(pwPtr->slaves);
+ ckfree(inserts);
+ pwPtr->slaves = newSlaves;
+
+ /*
+ * Set the paned window's slave count to the new value.
+ */
+
+ pwPtr->numSlaves += numNewSlaves;
+
+ Tk_FreeConfigOptions((char *) &options, pwPtr->slaveOpts, pwPtr->tkwin);
+
+ ComputeGeometry(pwPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PanedWindowSashCommand --
+ *
+ * Implementation of the panedwindow sash subcommand. See the user
+ * documentation for details on what it does.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * Depends on the arguments.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+PanedWindowSashCommand(
+ PanedWindow *pwPtr, /* Pointer to paned window information. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ static const char *const sashOptionStrings[] = {
+ "coord", "dragto", "mark", "place", NULL
+ };
+ enum sashOptions {
+ SASH_COORD, SASH_DRAGTO, SASH_MARK, SASH_PLACE
+ };
+ int index, sash, x, y, diff;
+ Tcl_Obj *coords[2];
+ Slave *slavePtr;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObj(interp, objv[2], sashOptionStrings, "option", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch ((enum sashOptions) index) {
+ case SASH_COORD:
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIntFromObj(interp, objv[3], &sash) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (!ValidSashIndex(pwPtr, sash)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "invalid sash index", -1));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "SASH_INDEX", NULL);
+ return TCL_ERROR;
+ }
+ slavePtr = pwPtr->slaves[sash];
+
+ coords[0] = Tcl_NewIntObj(slavePtr->sashx);
+ coords[1] = Tcl_NewIntObj(slavePtr->sashy);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(2, coords));
+ break;
+
+ case SASH_MARK:
+ if (objc != 6 && objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index ?x y?");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIntFromObj(interp, objv[3], &sash) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (!ValidSashIndex(pwPtr, sash)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "invalid sash index", -1));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "SASH_INDEX", NULL);
+ return TCL_ERROR;
+ }
+
+ if (objc == 6) {
+ if (Tcl_GetIntFromObj(interp, objv[4], &x) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIntFromObj(interp, objv[5], &y) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ pwPtr->slaves[sash]->markx = x;
+ pwPtr->slaves[sash]->marky = y;
+ } else {
+ coords[0] = Tcl_NewIntObj(pwPtr->slaves[sash]->markx);
+ coords[1] = Tcl_NewIntObj(pwPtr->slaves[sash]->marky);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(2, coords));
+ }
+ break;
+
+ case SASH_DRAGTO:
+ case SASH_PLACE:
+ if (objc != 6) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index x y");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIntFromObj(interp, objv[3], &sash) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (!ValidSashIndex(pwPtr, sash)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "invalid sash index", -1));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "SASH_INDEX", NULL);
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIntFromObj(interp, objv[4], &x) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIntFromObj(interp, objv[5], &y) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ slavePtr = pwPtr->slaves[sash];
+ if (pwPtr->orient == ORIENT_HORIZONTAL) {
+ if (index == SASH_PLACE) {
+ diff = x - pwPtr->slaves[sash]->sashx;
+ } else {
+ diff = x - pwPtr->slaves[sash]->markx;
+ }
+ } else {
+ if (index == SASH_PLACE) {
+ diff = y - pwPtr->slaves[sash]->sashy;
+ } else {
+ diff = y - pwPtr->slaves[sash]->marky;
+ }
+ }
+
+ MoveSash(pwPtr, sash, diff);
+ ComputeGeometry(pwPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConfigurePanedWindow --
+ *
+ * This function is called to process an argv/argc list in conjunction
+ * with the Tk option database to configure (or reconfigure) a paned
+ * window widget.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If TCL_ERROR is returned,
+ * then the interp's result contains an error message.
+ *
+ * Side effects:
+ * Configuration information, such as colors, border width, etc. get set
+ * for pwPtr; old resources get freed, if there were any.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ConfigurePanedWindow(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ PanedWindow *pwPtr, /* Information about widget. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument values. */
+{
+ Tk_SavedOptions savedOptions;
+ int typemask = 0;
+
+ if (Tk_SetOptions(interp, (char *) pwPtr, pwPtr->optionTable, objc, objv,
+ pwPtr->tkwin, &savedOptions, &typemask) != TCL_OK) {
+ Tk_RestoreSavedOptions(&savedOptions);
+ return TCL_ERROR;
+ }
+
+ Tk_FreeSavedOptions(&savedOptions);
+
+ PanedWindowWorldChanged(pwPtr);
+
+ /*
+ * If an option that affects geometry has changed, make a re-layout
+ * request.
+ */
+
+ if (typemask & GEOMETRY) {
+ ComputeGeometry(pwPtr);
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PanedWindowWorldChanged --
+ *
+ * This function is invoked anytime a paned window's world has changed in
+ * some way that causes the widget to have to recompute graphics contexts
+ * and geometry.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Paned window will be relayed out and redisplayed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+PanedWindowWorldChanged(
+ ClientData instanceData) /* Information about the paned window. */
+{
+ XGCValues gcValues;
+ GC newGC;
+ PanedWindow *pwPtr = instanceData;
+
+ /*
+ * Allocated a graphics context for drawing the paned window widget
+ * elements (background, sashes, etc.) and set the window background.
+ */
+
+ gcValues.background = Tk_3DBorderColor(pwPtr->background)->pixel;
+ newGC = Tk_GetGC(pwPtr->tkwin, GCBackground, &gcValues);
+ if (pwPtr->gc != NULL) {
+ Tk_FreeGC(pwPtr->display, pwPtr->gc);
+ }
+ pwPtr->gc = newGC;
+ Tk_SetWindowBackground(pwPtr->tkwin, gcValues.background);
+
+ /*
+ * Issue geometry size requests to Tk.
+ */
+
+ Tk_SetInternalBorder(pwPtr->tkwin, pwPtr->borderWidth);
+ if (pwPtr->width > 0 && pwPtr->height > 0) {
+ Tk_GeometryRequest(pwPtr->tkwin, pwPtr->width, pwPtr->height);
+ }
+
+ /*
+ * Arrange for the window to be redrawn, if neccessary.
+ */
+
+ if (Tk_IsMapped(pwPtr->tkwin) && !(pwPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DisplayPanedWindow, pwPtr);
+ pwPtr->flags |= REDRAW_PENDING;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * PanedWindowEventProc --
+ *
+ * This function is invoked by the Tk dispatcher for various events on
+ * paned windows.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * When the window gets deleted, internal structures get cleaned up. When
+ * it gets exposed, it is redisplayed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+PanedWindowEventProc(
+ ClientData clientData, /* Information about window. */
+ XEvent *eventPtr) /* Information about event. */
+{
+ PanedWindow *pwPtr = clientData;
+ int i;
+
+ if (eventPtr->type == Expose) {
+ if (pwPtr->tkwin != NULL && !(pwPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DisplayPanedWindow, pwPtr);
+ pwPtr->flags |= REDRAW_PENDING;
+ }
+ } else if (eventPtr->type == ConfigureNotify) {
+ pwPtr->flags |= REQUESTED_RELAYOUT;
+ if (pwPtr->tkwin != NULL && !(pwPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DisplayPanedWindow, pwPtr);
+ pwPtr->flags |= REDRAW_PENDING;
+ }
+ } else if (eventPtr->type == DestroyNotify) {
+ DestroyPanedWindow(pwPtr);
+ } else if (eventPtr->type == UnmapNotify) {
+ for (i = 0; i < pwPtr->numSlaves; i++) {
+ if (!pwPtr->slaves[i]->hide) {
+ Tk_UnmapWindow(pwPtr->slaves[i]->tkwin);
+ }
+ }
+ } else if (eventPtr->type == MapNotify) {
+ for (i = 0; i < pwPtr->numSlaves; i++) {
+ if (!pwPtr->slaves[i]->hide) {
+ Tk_MapWindow(pwPtr->slaves[i]->tkwin);
+ }
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PanedWindowCmdDeletedProc --
+ *
+ * This function is invoked when a widget command is deleted. If the
+ * widget isn't already in the process of being destroyed, this command
+ * destroys it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The widget is destroyed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+PanedWindowCmdDeletedProc(
+ ClientData clientData) /* Pointer to widget record for widget. */
+{
+ PanedWindow *pwPtr = clientData;
+
+ /*
+ * This function could be invoked either because the window was destroyed
+ * and the command was then deleted or because the command was deleted,
+ * and then this function destroys the widget. The WIDGET_DELETED flag
+ * distinguishes these cases.
+ */
+
+ if (!(pwPtr->flags & WIDGET_DELETED)) {
+ Tk_DestroyWindow(pwPtr->proxywin);
+ Tk_DestroyWindow(pwPtr->tkwin);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DisplayPanedWindow --
+ *
+ * This function redraws the contents of a paned window widget. 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.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+DisplayPanedWindow(
+ ClientData clientData) /* Information about window. */
+{
+ PanedWindow *pwPtr = clientData;
+ Slave *slavePtr;
+ Pixmap pixmap;
+ Tk_Window tkwin = pwPtr->tkwin;
+ int i, sashWidth, sashHeight;
+ const int horizontal = (pwPtr->orient == ORIENT_HORIZONTAL);
+ int first, last;
+
+ pwPtr->flags &= ~REDRAW_PENDING;
+ if ((pwPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
+ return;
+ }
+
+ if (pwPtr->flags & REQUESTED_RELAYOUT) {
+ ArrangePanes(clientData);
+ }
+
+#ifndef TK_NO_DOUBLE_BUFFERING
+ /*
+ * Create a pixmap for double-buffering, if necessary.
+ */
+
+ pixmap = Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin),
+ Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));
+#else
+ pixmap = Tk_WindowId(tkwin);
+#endif /* TK_NO_DOUBLE_BUFFERING */
+
+ /*
+ * Redraw the widget's background and border.
+ */
+
+ Tk_Fill3DRectangle(tkwin, pixmap, pwPtr->background, 0, 0,
+ Tk_Width(tkwin), Tk_Height(tkwin), pwPtr->borderWidth,
+ pwPtr->relief);
+
+ /*
+ * Set up boilerplate geometry values for sashes (width, height, common
+ * coordinates).
+ */
+
+ if (horizontal) {
+ sashHeight = Tk_Height(tkwin) - (2 * Tk_InternalBorderWidth(tkwin));
+ sashWidth = pwPtr->sashWidth;
+ } else {
+ sashWidth = Tk_Width(tkwin) - (2 * Tk_InternalBorderWidth(tkwin));
+ sashHeight = pwPtr->sashWidth;
+ }
+
+ /*
+ * Draw the sashes.
+ */
+
+ GetFirstLastVisiblePane(pwPtr, &first, &last);
+ for (i = 0; i < pwPtr->numSlaves - 1; i++) {
+ slavePtr = pwPtr->slaves[i];
+ if (slavePtr->hide || i == last) {
+ continue;
+ }
+ if (sashWidth > 0 && sashHeight > 0) {
+ Tk_Fill3DRectangle(tkwin, pixmap, pwPtr->background,
+ slavePtr->sashx, slavePtr->sashy, sashWidth, sashHeight,
+ 1, pwPtr->sashRelief);
+ }
+ if (pwPtr->showHandle) {
+ Tk_Fill3DRectangle(tkwin, pixmap, pwPtr->background,
+ slavePtr->handlex, slavePtr->handley,
+ pwPtr->handleSize, pwPtr->handleSize, 1,
+ TK_RELIEF_RAISED);
+ }
+ }
+
+#ifndef TK_NO_DOUBLE_BUFFERING
+ /*
+ * Copy the information from the off-screen pixmap onto the screen, then
+ * delete the pixmap.
+ */
+
+ XCopyArea(Tk_Display(tkwin), pixmap, Tk_WindowId(tkwin), pwPtr->gc, 0, 0,
+ (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin), 0, 0);
+ Tk_FreePixmap(Tk_Display(tkwin), pixmap);
+#endif /* TK_NO_DOUBLE_BUFFERING */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyPanedWindow --
+ *
+ * This function is invoked by PanedWindowEventProc to free the internal
+ * structure of a paned window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Everything associated with the paned window is freed up.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DestroyPanedWindow(
+ PanedWindow *pwPtr) /* Info about paned window widget. */
+{
+ int i;
+
+ /*
+ * First mark the widget as in the process of being deleted, so that any
+ * code that causes calls to other paned window functions will abort.
+ */
+
+ pwPtr->flags |= WIDGET_DELETED;
+
+ /*
+ * Cancel idle callbacks for redrawing the widget and for rearranging the
+ * panes.
+ */
+
+ if (pwPtr->flags & REDRAW_PENDING) {
+ Tcl_CancelIdleCall(DisplayPanedWindow, pwPtr);
+ }
+ if (pwPtr->flags & RESIZE_PENDING) {
+ Tcl_CancelIdleCall(ArrangePanes, pwPtr);
+ }
+
+ /*
+ * Clean up the slave list; foreach slave:
+ * o Cancel the slave's structure notification callback
+ * o Cancel geometry management for the slave.
+ * o Free memory for the slave
+ */
+
+ for (i = 0; i < pwPtr->numSlaves; i++) {
+ Tk_DeleteEventHandler(pwPtr->slaves[i]->tkwin, StructureNotifyMask,
+ SlaveStructureProc, pwPtr->slaves[i]);
+ Tk_ManageGeometry(pwPtr->slaves[i]->tkwin, NULL, NULL);
+ Tk_FreeConfigOptions((char *) pwPtr->slaves[i], pwPtr->slaveOpts,
+ pwPtr->tkwin);
+ ckfree(pwPtr->slaves[i]);
+ pwPtr->slaves[i] = NULL;
+ }
+ if (pwPtr->slaves) {
+ ckfree(pwPtr->slaves);
+ }
+
+ /*
+ * Remove the widget command from the interpreter.
+ */
+
+ Tcl_DeleteCommandFromToken(pwPtr->interp, pwPtr->widgetCmd);
+
+ /*
+ * Let Tk_FreeConfigOptions clean up the rest.
+ */
+
+ Tk_FreeConfigOptions((char *) pwPtr, pwPtr->optionTable, pwPtr->tkwin);
+ Tcl_Release(pwPtr->tkwin);
+ pwPtr->tkwin = NULL;
+
+ Tcl_EventuallyFree(pwPtr, TCL_DYNAMIC);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * PanedWindowReqProc --
+ *
+ * This function is invoked by Tk_GeometryRequest for windows managed by
+ * a paned window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Arranges for tkwin, and all its managed siblings, to be re-arranged at
+ * the next idle point.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+PanedWindowReqProc(
+ ClientData clientData, /* Paned window's information about window
+ * that got new preferred geometry. */
+ Tk_Window tkwin) /* Other Tk-related information about the
+ * window. */
+{
+ Slave *slavePtr = clientData;
+ PanedWindow *pwPtr = (PanedWindow *) slavePtr->masterPtr;
+
+ if (Tk_IsMapped(pwPtr->tkwin)) {
+ if (!(pwPtr->flags & RESIZE_PENDING)) {
+ pwPtr->flags |= RESIZE_PENDING;
+ Tcl_DoWhenIdle(ArrangePanes, pwPtr);
+ }
+ } else {
+ int doubleBw = 2 * Tk_Changes(slavePtr->tkwin)->border_width;
+
+ if (slavePtr->width <= 0) {
+ slavePtr->paneWidth = Tk_ReqWidth(slavePtr->tkwin) + doubleBw;
+ }
+ if (slavePtr->height <= 0) {
+ slavePtr->paneHeight = Tk_ReqHeight(slavePtr->tkwin) + doubleBw;
+ }
+ ComputeGeometry(pwPtr);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * PanedWindowLostSlaveProc --
+ *
+ * This function is invoked by Tk whenever some other geometry claims
+ * control over a slave that used to be managed by us.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Forgets all information about the slave. Causes geometry to be
+ * recomputed for the panedwindow.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+PanedWindowLostSlaveProc(
+ ClientData clientData, /* Grid structure for slave window that was
+ * stolen away. */
+ Tk_Window tkwin) /* Tk's handle for the slave window. */
+{
+ register Slave *slavePtr = clientData;
+ PanedWindow *pwPtr = (PanedWindow *) slavePtr->masterPtr;
+
+ if (pwPtr->tkwin != Tk_Parent(slavePtr->tkwin)) {
+ Tk_UnmaintainGeometry(slavePtr->tkwin, pwPtr->tkwin);
+ }
+ Unlink(slavePtr);
+ Tk_DeleteEventHandler(slavePtr->tkwin, StructureNotifyMask,
+ SlaveStructureProc, slavePtr);
+ Tk_UnmapWindow(slavePtr->tkwin);
+ slavePtr->tkwin = NULL;
+ ckfree(slavePtr);
+ ComputeGeometry(pwPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ArrangePanes --
+ *
+ * This function is invoked (using the Tcl_DoWhenIdle mechanism) to
+ * re-layout a set of windows managed by a paned window. It is invoked at
+ * idle time so that a series of pane requests can be merged into a
+ * single layout operation.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The slaves of masterPtr may get resized or moved.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ArrangePanes(
+ ClientData clientData) /* Structure describing parent whose slaves
+ * are to be re-layed out. */
+{
+ register PanedWindow *pwPtr = clientData;
+ register Slave *slavePtr;
+ int i, slaveWidth, slaveHeight, slaveX, slaveY;
+ int paneWidth, paneHeight, paneSize, paneMinSize;
+ int doubleBw;
+ int x, y;
+ int sashWidth, sashOffset, sashCount, handleOffset;
+ int sashReserve, sxReserve, syReserve;
+ int internalBW;
+ int paneDynSize, paneDynMinSize, pwHeight, pwWidth, pwSize;
+ int first, last;
+ int stretchReserve, stretchAmount;
+ const int horizontal = (pwPtr->orient == ORIENT_HORIZONTAL);
+
+ pwPtr->flags &= ~(REQUESTED_RELAYOUT|RESIZE_PENDING);
+
+ /*
+ * If the parent has no slaves anymore, then don't do anything at all:
+ * just leave the parent's size as-is. Otherwise there is no way to
+ * "relinquish" control over the parent so another geometry manager can
+ * take over.
+ */
+
+ if (pwPtr->numSlaves == 0) {
+ return;
+ }
+
+ Tcl_Preserve(pwPtr);
+
+ /*
+ * Find index of first and last visible panes.
+ */
+
+ GetFirstLastVisiblePane(pwPtr, &first, &last);
+
+ /*
+ * First pass; compute sizes
+ */
+
+ paneDynSize = paneDynMinSize = 0;
+ internalBW = Tk_InternalBorderWidth(pwPtr->tkwin);
+ pwHeight = Tk_Height(pwPtr->tkwin) - (2 * internalBW);
+ pwWidth = Tk_Width(pwPtr->tkwin) - (2 * internalBW);
+ x = y = internalBW;
+ stretchReserve = (horizontal ? pwWidth : pwHeight);
+
+ /*
+ * Calculate the sash width, including handle and padding, and the sash
+ * and handle offsets.
+ */
+
+ sashOffset = handleOffset = pwPtr->sashPad;
+ if (pwPtr->showHandle && pwPtr->handleSize > pwPtr->sashWidth) {
+ sashWidth = (2 * pwPtr->sashPad) + pwPtr->handleSize;
+ sashOffset = ((pwPtr->handleSize - pwPtr->sashWidth) / 2)
+ + pwPtr->sashPad;
+ } else {
+ sashWidth = (2 * pwPtr->sashPad) + pwPtr->sashWidth;
+ handleOffset = ((pwPtr->sashWidth - pwPtr->handleSize) / 2)
+ + pwPtr->sashPad;
+ }
+
+ for (i = sashCount = 0; i < pwPtr->numSlaves; i++) {
+ slavePtr = pwPtr->slaves[i];
+
+ if (slavePtr->hide) {
+ continue;
+ }
+
+ /*
+ * Compute the total size needed by all the slaves and the left-over,
+ * or shortage of space available.
+ */
+
+ if (horizontal) {
+ if (slavePtr->width > 0) {
+ paneSize = slavePtr->width;
+ } else {
+ paneSize = slavePtr->paneWidth;
+ }
+ stretchReserve -= paneSize + (2 * slavePtr->padx);
+ } else {
+ if (slavePtr->height > 0) {
+ paneSize = slavePtr->height;
+ } else {
+ paneSize = slavePtr->paneHeight;
+ }
+ stretchReserve -= paneSize + (2 * slavePtr->pady);
+ }
+ if (IsStretchable(slavePtr->stretch,i,first,last)
+ && Tk_IsMapped(pwPtr->tkwin)) {
+ paneDynSize += paneSize;
+ paneDynMinSize += slavePtr->minSize;
+ }
+ if (i != last) {
+ stretchReserve -= sashWidth;
+ sashCount++;
+ }
+ }
+
+ /*
+ * Second pass; adjust/arrange panes.
+ */
+
+ for (i = 0; i < pwPtr->numSlaves; i++) {
+ slavePtr = pwPtr->slaves[i];
+
+ if (slavePtr->hide) {
+ Tk_UnmaintainGeometry(slavePtr->tkwin, pwPtr->tkwin);
+ Tk_UnmapWindow(slavePtr->tkwin);
+ continue;
+ }
+
+ /*
+ * Compute the size of this slave. The algorithm (assuming a
+ * horizontal paned window) is:
+ *
+ * 1. Get "base" dimensions. If a width or height is specified for
+ * this slave, use those values; else use the ReqWidth/ReqHeight.
+ * 2. Using base dimensions, pane dimensions, and sticky values,
+ * determine the x and y, and actual width and height of the
+ * widget.
+ */
+
+ doubleBw = 2 * Tk_Changes(slavePtr->tkwin)->border_width;
+ slaveWidth = (slavePtr->width > 0 ? slavePtr->width :
+ Tk_ReqWidth(slavePtr->tkwin) + doubleBw);
+ slaveHeight = (slavePtr->height > 0 ? slavePtr->height :
+ Tk_ReqHeight(slavePtr->tkwin) + doubleBw);
+ paneMinSize = slavePtr->minSize;
+
+ /*
+ * Calculate pane width and height.
+ */
+
+ if (horizontal) {
+ if (slavePtr->width > 0) {
+ paneSize = slavePtr->width;
+ } else {
+ paneSize = slavePtr->paneWidth;
+ }
+ pwSize = pwWidth;
+ } else {
+ if (slavePtr->height > 0) {
+ paneSize = slavePtr->height;
+ } else {
+ paneSize = slavePtr->paneHeight;
+ }
+ pwSize = pwHeight;
+ }
+ if (IsStretchable(slavePtr->stretch, i, first, last)) {
+ double frac;
+
+ if (paneDynSize > 0) {
+ frac = (double)paneSize / (double)paneDynSize;
+ } else {
+ frac = (double)paneSize / (double)pwSize;
+ }
+
+ paneDynSize -= paneSize;
+ paneDynMinSize -= slavePtr->minSize;
+ stretchAmount = (int) (frac * stretchReserve);
+ if (paneSize + stretchAmount >= paneMinSize) {
+ stretchReserve -= stretchAmount;
+ paneSize += stretchAmount;
+ } else {
+ stretchReserve += paneSize - paneMinSize;
+ paneSize = paneMinSize;
+ }
+ if (i == last && stretchReserve > 0) {
+ paneSize += stretchReserve;
+ stretchReserve = 0;
+ }
+ } else if (paneDynSize - paneDynMinSize + stretchReserve < 0) {
+ if (paneSize + paneDynSize - paneDynMinSize + stretchReserve
+ <= paneMinSize) {
+ stretchReserve += paneSize - paneMinSize;
+ paneSize = paneMinSize;
+ } else {
+ paneSize += paneDynSize - paneDynMinSize + stretchReserve;
+ stretchReserve = paneDynMinSize - paneDynSize;
+ }
+ }
+ if (horizontal) {
+ paneWidth = paneSize;
+ paneHeight = pwHeight - (2 * slavePtr->pady);
+ } else {
+ paneWidth = pwWidth - (2 * slavePtr->padx);
+ paneHeight = paneSize;
+ }
+
+ /*
+ * Adjust for area reserved for sashes.
+ */
+
+ if (sashCount) {
+ sashReserve = sashWidth * sashCount;
+ if (horizontal) {
+ sxReserve = sashReserve;
+ syReserve = 0;
+ } else {
+ sxReserve = 0;
+ syReserve = sashReserve;
+ }
+ } else {
+ sxReserve = syReserve = 0;
+ }
+
+ if (pwWidth - sxReserve < x + paneWidth - internalBW) {
+ paneWidth = pwWidth - sxReserve - x + internalBW;
+ }
+ if (pwHeight - syReserve < y + paneHeight - internalBW) {
+ paneHeight = pwHeight - syReserve - y + internalBW;
+ }
+
+ if (slaveWidth > paneWidth) {
+ slaveWidth = paneWidth;
+ }
+ if (slaveHeight > paneHeight) {
+ slaveHeight = paneHeight;
+ }
+
+ slavePtr->x = x;
+ slavePtr->y = y;
+
+ /*
+ * Compute the location of the sash at the right or bottom of the
+ * parcel and the location of the next parcel.
+ */
+
+ if (horizontal) {
+ x += paneWidth + (2 * slavePtr->padx);
+ if (x < internalBW) {
+ x = internalBW;
+ }
+ slavePtr->sashx = x + sashOffset;
+ slavePtr->sashy = y;
+ slavePtr->handlex = x + handleOffset;
+ slavePtr->handley = y + pwPtr->handlePad;
+ x += sashWidth;
+ } else {
+ y += paneHeight + (2 * slavePtr->pady);
+ if (y < internalBW) {
+ y = internalBW;
+ }
+ slavePtr->sashx = x;
+ slavePtr->sashy = y + sashOffset;
+ slavePtr->handlex = x + pwPtr->handlePad;
+ slavePtr->handley = y + handleOffset;
+ y += sashWidth;
+ }
+
+ /*
+ * Compute the actual dimensions of the slave in the pane.
+ */
+
+ slaveX = slavePtr->x;
+ slaveY = slavePtr->y;
+ AdjustForSticky(slavePtr->sticky, paneWidth, paneHeight,
+ &slaveX, &slaveY, &slaveWidth, &slaveHeight);
+
+ slaveX += slavePtr->padx;
+ slaveY += slavePtr->pady;
+
+ /*
+ * Now put the window in the proper spot.
+ */
+
+ if (slaveWidth <= 0 || slaveHeight <= 0 ||
+ (horizontal ? slaveX - internalBW > pwWidth :
+ slaveY - internalBW > pwHeight)) {
+ Tk_UnmaintainGeometry(slavePtr->tkwin, pwPtr->tkwin);
+ Tk_UnmapWindow(slavePtr->tkwin);
+ } else {
+ Tk_MaintainGeometry(slavePtr->tkwin, pwPtr->tkwin,
+ slaveX, slaveY, slaveWidth, slaveHeight);
+ }
+ sashCount--;
+ }
+ Tcl_Release(pwPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Unlink --
+ *
+ * Remove a slave from a paned window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The paned window will be scheduled for re-arranging and redrawing.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+Unlink(
+ register Slave *slavePtr) /* Window to unlink. */
+{
+ register PanedWindow *masterPtr;
+ int i, j;
+
+ masterPtr = slavePtr->masterPtr;
+ if (masterPtr == NULL) {
+ return;
+ }
+
+ /*
+ * Find the specified slave in the panedwindow's list of slaves, then
+ * remove it from that list.
+ */
+
+ for (i = 0; i < masterPtr->numSlaves; i++) {
+ if (masterPtr->slaves[i] == slavePtr) {
+ for (j = i; j < masterPtr->numSlaves - 1; j++) {
+ masterPtr->slaves[j] = masterPtr->slaves[j + 1];
+ }
+ break;
+ }
+ }
+
+ /*
+ * Clean out any -after or -before references to this slave
+ */
+
+ for (i = 0; i < masterPtr->numSlaves; i++) {
+ if (masterPtr->slaves[i]->before == slavePtr->tkwin) {
+ masterPtr->slaves[i]->before = NULL;
+ }
+ if (masterPtr->slaves[i]->after == slavePtr->tkwin) {
+ masterPtr->slaves[i]->after = NULL;
+ }
+ }
+
+ masterPtr->flags |= REQUESTED_RELAYOUT;
+ if (!(masterPtr->flags & REDRAW_PENDING)) {
+ masterPtr->flags |= REDRAW_PENDING;
+ Tcl_DoWhenIdle(DisplayPanedWindow, masterPtr);
+ }
+
+ /*
+ * Set the slave's masterPtr to NULL, so that we can tell that the slave
+ * is no longer attached to any panedwindow.
+ */
+
+ slavePtr->masterPtr = NULL;
+
+ masterPtr->numSlaves--;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetPane --
+ *
+ * Given a token to a Tk window, find the pane that corresponds to that
+ * token in a given paned window.
+ *
+ * Results:
+ * Pointer to the slave structure, or NULL if the window is not managed
+ * by this paned window.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Slave *
+GetPane(
+ PanedWindow *pwPtr, /* Pointer to the paned window info. */
+ Tk_Window tkwin) /* Window to search for. */
+{
+ int i;
+
+ for (i = 0; i < pwPtr->numSlaves; i++) {
+ if (pwPtr->slaves[i]->tkwin == tkwin) {
+ return pwPtr->slaves[i];
+ }
+ }
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetFirstLastVisiblePane --
+ *
+ * Given panedwindow, find the index of the first and last visible panes
+ * of that paned window.
+ *
+ * Results:
+ * Index of the first and last visible panes.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GetFirstLastVisiblePane(
+ PanedWindow *pwPtr, /* Pointer to the paned window info. */
+ int *firstPtr, /* Returned index for first. */
+ int *lastPtr) /* Returned index for last. */
+{
+ int i;
+
+ for (i = 0, *lastPtr = 0, *firstPtr = -1; i < pwPtr->numSlaves; i++) {
+ if (pwPtr->slaves[i]->hide == 0) {
+ if (*firstPtr < 0) {
+ *firstPtr = i;
+ }
+ *lastPtr = i;
+ }
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * SlaveStructureProc --
+ *
+ * This function is invoked whenever StructureNotify events occur for a
+ * window that's managed by a paned window. This function's only purpose
+ * is to clean up when windows are deleted.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The paned window slave structure associated with the window
+ * is freed, and the slave is disassociated from the paned
+ * window which managed it.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+SlaveStructureProc(
+ ClientData clientData, /* Pointer to record describing window item. */
+ XEvent *eventPtr) /* Describes what just happened. */
+{
+ Slave *slavePtr = clientData;
+ PanedWindow *pwPtr = slavePtr->masterPtr;
+
+ if (eventPtr->type == DestroyNotify) {
+ Unlink(slavePtr);
+ slavePtr->tkwin = NULL;
+ ckfree(slavePtr);
+ ComputeGeometry(pwPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ComputeGeometry --
+ *
+ * Compute geometry for the paned window, including coordinates of all
+ * slave windows and each sash.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Recomputes geometry information for a paned window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ComputeGeometry(
+ PanedWindow *pwPtr) /* Pointer to the Paned Window structure. */
+{
+ int i, x, y, doubleBw, internalBw;
+ int sashWidth, sashOffset, handleOffset;
+ int reqWidth, reqHeight, dim;
+ Slave *slavePtr;
+ const int horizontal = (pwPtr->orient == ORIENT_HORIZONTAL);
+
+ pwPtr->flags |= REQUESTED_RELAYOUT;
+
+ x = y = internalBw = Tk_InternalBorderWidth(pwPtr->tkwin);
+ reqWidth = reqHeight = 0;
+
+ /*
+ * Sashes and handles share space on the display. To simplify processing
+ * below, precompute the x and y offsets of the handles and sashes within
+ * the space occupied by their combination; later, just add those offsets
+ * blindly (avoiding the extra showHandle, etc, checks).
+ */
+
+ sashOffset = handleOffset = pwPtr->sashPad;
+ if (pwPtr->showHandle && pwPtr->handleSize > pwPtr->sashWidth) {
+ sashWidth = (2 * pwPtr->sashPad) + pwPtr->handleSize;
+ sashOffset = ((pwPtr->handleSize - pwPtr->sashWidth) / 2)
+ + pwPtr->sashPad;
+ } else {
+ sashWidth = (2 * pwPtr->sashPad) + pwPtr->sashWidth;
+ handleOffset = ((pwPtr->sashWidth - pwPtr->handleSize) / 2)
+ + pwPtr->sashPad;
+ }
+
+ for (i = 0; i < pwPtr->numSlaves; i++) {
+ slavePtr = pwPtr->slaves[i];
+
+ if (slavePtr->hide) {
+ continue;
+ }
+
+ /*
+ * First set the coordinates for the top left corner of the slave's
+ * parcel.
+ */
+
+ slavePtr->x = x;
+ slavePtr->y = y;
+
+ /*
+ * Make sure the pane's paned dimension is at least minsize. This
+ * check may be redundant, since the only way to change a pane's size
+ * is by moving a sash, and that code checks the minsize.
+ */
+
+ if (horizontal) {
+ if (slavePtr->paneWidth < slavePtr->minSize) {
+ slavePtr->paneWidth = slavePtr->minSize;
+ }
+ } else {
+ if (slavePtr->paneHeight < slavePtr->minSize) {
+ slavePtr->paneHeight = slavePtr->minSize;
+ }
+ }
+
+ /*
+ * Compute the location of the sash at the right or bottom of the
+ * parcel.
+ */
+
+ if (horizontal) {
+ x += slavePtr->paneWidth + (2 * slavePtr->padx);
+ slavePtr->sashx = x + sashOffset;
+ slavePtr->sashy = y;
+ slavePtr->handlex = x + handleOffset;
+ slavePtr->handley = y + pwPtr->handlePad;
+ x += sashWidth;
+ } else {
+ y += slavePtr->paneHeight + (2 * slavePtr->pady);
+ slavePtr->sashx = x;
+ slavePtr->sashy = y + sashOffset;
+ slavePtr->handlex = x + pwPtr->handlePad;
+ slavePtr->handley = y + handleOffset;
+ y += sashWidth;
+ }
+
+ /*
+ * Find the maximum height/width of the slaves, for computing the
+ * requested height/width of the paned window.
+ */
+
+ if (horizontal) {
+ /*
+ * If the slave has an explicit height set, use that; otherwise,
+ * use the slave's requested height.
+ */
+
+ if (slavePtr->height > 0) {
+ dim = slavePtr->height;
+ } else {
+ doubleBw = 2 * Tk_Changes(slavePtr->tkwin)->border_width;
+ dim = Tk_ReqHeight(slavePtr->tkwin) + doubleBw;
+ }
+ dim += 2 * slavePtr->pady;
+ if (dim > reqHeight) {
+ reqHeight = dim;
+ }
+ } else {
+ /*
+ * If the slave has an explicit width set use that; otherwise, use
+ * the slave's requested width.
+ */
+
+ if (slavePtr->width > 0) {
+ dim = slavePtr->width;
+ } else {
+ doubleBw = 2 * Tk_Changes(slavePtr->tkwin)->border_width;
+ dim = Tk_ReqWidth(slavePtr->tkwin) + doubleBw;
+ }
+ dim += 2 * slavePtr->padx;
+ if (dim > reqWidth) {
+ reqWidth = dim;
+ }
+ }
+ }
+
+ /*
+ * The loop above should have left x (or y) equal to the sum of the widths
+ * (or heights) of the widgets, plus the size of one sash and the sash
+ * padding for each widget, plus the width of the left (or top) border of
+ * the paned window.
+ *
+ * The requested width (or height) is therefore x (or y) minus the size of
+ * one sash and padding, plus the width of the right (or bottom) border of
+ * the paned window.
+ *
+ * The height (or width) is equal to the maximum height (or width) of the
+ * slaves, plus the width of the border of the top and bottom (or left and
+ * right) of the paned window.
+ *
+ * If the panedwindow has an explicit width/height set use that;
+ * otherwise, use the requested width/height.
+ */
+
+ if (horizontal) {
+ reqWidth = (pwPtr->width > 0 ?
+ pwPtr->width : x - sashWidth + internalBw);
+ reqHeight = (pwPtr->height > 0 ?
+ pwPtr->height : reqHeight + (2 * internalBw));
+ } else {
+ reqWidth = (pwPtr->width > 0 ?
+ pwPtr->width : reqWidth + (2 * internalBw));
+ reqHeight = (pwPtr->height > 0 ?
+ pwPtr->height : y - sashWidth + internalBw);
+ }
+ Tk_GeometryRequest(pwPtr->tkwin, reqWidth, reqHeight);
+ if (Tk_IsMapped(pwPtr->tkwin) && !(pwPtr->flags & REDRAW_PENDING)) {
+ pwPtr->flags |= REDRAW_PENDING;
+ Tcl_DoWhenIdle(DisplayPanedWindow, pwPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyOptionTables --
+ *
+ * This function is registered as an exit callback when the paned window
+ * command is first called. It cleans up the OptionTables structure
+ * allocated by that command.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Frees memory.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DestroyOptionTables(
+ ClientData clientData, /* Pointer to the OptionTables struct */
+ Tcl_Interp *interp) /* Pointer to the calling interp */
+{
+ ckfree(clientData);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetSticky -
+ *
+ * Converts an internal boolean combination of "sticky" bits into a Tcl
+ * string obj containing zero or more of n, s, e, or w.
+ *
+ * Results:
+ * Tcl_Obj containing the string representation of the sticky value.
+ *
+ * Side effects:
+ * Creates a new Tcl_Obj.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj *
+GetSticky(
+ ClientData clientData,
+ Tk_Window tkwin,
+ char *recordPtr, /* Pointer to widget record. */
+ int internalOffset) /* Offset within *recordPtr containing the
+ * sticky value. */
+{
+ int sticky = *(int *)(recordPtr + internalOffset);
+ char buffer[5];
+ char *p = &buffer[0];
+
+ if (sticky & STICK_NORTH) {
+ *p++ = 'n';
+ }
+ if (sticky & STICK_EAST) {
+ *p++ = 'e';
+ }
+ if (sticky & STICK_SOUTH) {
+ *p++ = 's';
+ }
+ if (sticky & STICK_WEST) {
+ *p++ = 'w';
+ }
+ *p = '\0';
+
+ return Tcl_NewStringObj(buffer, -1);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetSticky --
+ *
+ * Converts a Tcl_Obj representing a widgets stickyness into an integer
+ * value.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * May store the integer value into the internal representation pointer.
+ * May change the pointer to the Tcl_Obj to NULL to indicate that the
+ * specified string was empty and that is acceptable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetSticky(
+ ClientData clientData,
+ Tcl_Interp *interp, /* Current interp; may be used for errors. */
+ Tk_Window tkwin, /* Window for which option is being set. */
+ Tcl_Obj **value, /* Pointer to the pointer to the value object.
+ * We use a pointer to the pointer because we
+ * may need to return a value (NULL). */
+ char *recordPtr, /* Pointer to storage for the widget record. */
+ int internalOffset, /* Offset within *recordPtr at which the
+ * internal value is to be stored. */
+ char *oldInternalPtr, /* Pointer to storage for the old value. */
+ int flags) /* Flags for the option, set Tk_SetOptions. */
+{
+ int sticky = 0;
+ char c, *internalPtr;
+ const char *string;
+
+ internalPtr = ComputeSlotAddress(recordPtr, internalOffset);
+
+ if (flags & TK_OPTION_NULL_OK && ObjectIsEmpty(*value)) {
+ *value = NULL;
+ } else {
+ /*
+ * Convert the sticky specifier into an integer value.
+ */
+
+ string = Tcl_GetString(*value);
+
+ while ((c = *string++) != '\0') {
+ switch (c) {
+ case 'n': case 'N':
+ sticky |= STICK_NORTH;
+ break;
+ case 'e': case 'E':
+ sticky |= STICK_EAST;
+ break;
+ case 's': case 'S':
+ sticky |= STICK_SOUTH;
+ break;
+ case 'w': case 'W':
+ sticky |= STICK_WEST;
+ break;
+ case ' ': case ',': case '\t': case '\r': case '\n':
+ break;
+ default:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad stickyness value \"%s\": must be a string"
+ " containing zero or more of n, e, s, and w",
+ Tcl_GetString(*value)));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "STICKY", NULL);
+ return TCL_ERROR;
+ }
+ }
+ }
+
+ if (internalPtr != NULL) {
+ *((int *) oldInternalPtr) = *((int *) internalPtr);
+ *((int *) internalPtr) = sticky;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * RestoreSticky --
+ *
+ * Restore a sticky option value from a saved value.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Restores the old value.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+RestoreSticky(
+ ClientData clientData,
+ Tk_Window tkwin,
+ char *internalPtr, /* Pointer to storage for value. */
+ char *oldInternalPtr) /* Pointer to old value. */
+{
+ *(int *)internalPtr = *(int *)oldInternalPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AdjustForSticky --
+ *
+ * Given the x,y coords of the top-left corner of a pane, the dimensions
+ * of that pane, and the dimensions of a slave, compute the x,y coords
+ * and actual dimensions of the slave based on the slave's sticky value.
+ *
+ * Results:
+ * No direct return; sets the x, y, slaveWidth and slaveHeight to correct
+ * values.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+AdjustForSticky(
+ int sticky, /* Sticky value; see top of file for
+ * definition. */
+ int cavityWidth, /* Width of the cavity. */
+ int cavityHeight, /* Height of the cavity. */
+ int *xPtr, int *yPtr, /* Initially, coordinates of the top-left
+ * corner of cavity; also return values for
+ * actual x, y coords of slave. */
+ int *slaveWidthPtr, /* Slave width. */
+ int *slaveHeightPtr) /* Slave height. */
+{
+ int diffx = 0; /* Cavity width - slave width. */
+ int diffy = 0; /* Cavity hight - slave height. */
+
+ if (cavityWidth > *slaveWidthPtr) {
+ diffx = cavityWidth - *slaveWidthPtr;
+ }
+
+ if (cavityHeight > *slaveHeightPtr) {
+ diffy = cavityHeight - *slaveHeightPtr;
+ }
+
+ if ((sticky & STICK_EAST) && (sticky & STICK_WEST)) {
+ *slaveWidthPtr += diffx;
+ }
+ if ((sticky & STICK_NORTH) && (sticky & STICK_SOUTH)) {
+ *slaveHeightPtr += diffy;
+ }
+ if (!(sticky & STICK_WEST)) {
+ *xPtr += (sticky & STICK_EAST) ? diffx : diffx/2;
+ }
+ if (!(sticky & STICK_NORTH)) {
+ *yPtr += (sticky & STICK_SOUTH) ? diffy : diffy/2;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MoveSash --
+ *
+ * Move the sash given by index the amount given.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Recomputes the sizes of the panes in a panedwindow.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+MoveSash(
+ PanedWindow *pwPtr,
+ int sash,
+ int diff)
+{
+ int i;
+ int expandPane, reduceFirst, reduceLast, reduceIncr, slaveSize, sashOffset;
+ Slave *slavePtr;
+ int stretchReserve = 0;
+ int nextSash = sash + 1;
+ const int horizontal = (pwPtr->orient == ORIENT_HORIZONTAL);
+
+ if (diff == 0)
+ return;
+
+ /*
+ * Update the slave sizes with their real sizes.
+ */
+
+ if (pwPtr->showHandle && pwPtr->handleSize > pwPtr->sashWidth) {
+ sashOffset = ((pwPtr->handleSize - pwPtr->sashWidth) / 2)
+ + pwPtr->sashPad;
+ } else {
+ sashOffset = pwPtr->sashPad;
+ }
+ for (i = 0; i < pwPtr->numSlaves; i++) {
+ slavePtr = pwPtr->slaves[i];
+ if (slavePtr->hide) {
+ continue;
+ }
+ if (horizontal) {
+ slavePtr->paneWidth = slavePtr->width = slavePtr->sashx
+ - sashOffset - slavePtr->x - (2 * slavePtr->padx);
+ } else {
+ slavePtr->paneHeight = slavePtr->height = slavePtr->sashy
+ - sashOffset - slavePtr->y - (2 * slavePtr->pady);
+ }
+ }
+
+ /*
+ * There must be a next sash since it is only possible to enter this
+ * routine when moving an actual sash which implies there exists a visible
+ * pane to either side of the sash.
+ */
+
+ while (nextSash < pwPtr->numSlaves-1 && pwPtr->slaves[nextSash]->hide) {
+ nextSash++;
+ }
+
+ /*
+ * Consolidate +/-diff variables to reduce duplicate code.
+ */
+
+ if (diff > 0) {
+ expandPane = sash;
+ reduceFirst = nextSash;
+ reduceLast = pwPtr->numSlaves;
+ reduceIncr = 1;
+ } else {
+ diff = abs(diff);
+ expandPane = nextSash;
+ reduceFirst = sash;
+ reduceLast = -1;
+ reduceIncr = -1;
+ }
+
+ /*
+ * Calculate how much room we have to stretch in and adjust diff value
+ * accordingly.
+ */
+
+ for (i = reduceFirst; i != reduceLast; i += reduceIncr) {
+ slavePtr = pwPtr->slaves[i];
+ if (slavePtr->hide) {
+ continue;
+ }
+ if (horizontal) {
+ stretchReserve += slavePtr->width - slavePtr->minSize;
+ } else {
+ stretchReserve += slavePtr->height - slavePtr->minSize;
+ }
+ }
+ if (stretchReserve <= 0) {
+ return;
+ }
+ if (diff > stretchReserve) {
+ diff = stretchReserve;
+ }
+
+ /*
+ * Expand pane by diff amount.
+ */
+
+ slavePtr = pwPtr->slaves[expandPane];
+ if (horizontal) {
+ slavePtr->paneWidth = slavePtr->width += diff;
+ } else {
+ slavePtr->paneHeight = slavePtr->height += diff;
+ }
+
+ /*
+ * Reduce panes, respecting minsize, until diff amount has been used.
+ */
+
+ for (i = reduceFirst; i != reduceLast; i += reduceIncr) {
+ slavePtr = pwPtr->slaves[i];
+ if (slavePtr->hide) {
+ continue;
+ }
+ if (horizontal) {
+ slaveSize = slavePtr->width;
+ } else {
+ slaveSize = slavePtr->height;
+ }
+ if (diff > (slaveSize - slavePtr->minSize)) {
+ diff -= slaveSize - slavePtr->minSize;
+ slaveSize = slavePtr->minSize;
+ } else {
+ slaveSize -= diff;
+ i = reduceLast - reduceIncr;
+ }
+ if (horizontal) {
+ slavePtr->paneWidth = slavePtr->width = slaveSize;
+ } else {
+ slavePtr->paneHeight = slavePtr->height = slaveSize;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ProxyWindowEventProc --
+ *
+ * This function is invoked by the Tk dispatcher for various events on
+ * paned window proxy windows.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * When the window gets deleted, internal structures get cleaned up. When
+ * it gets exposed, it is redisplayed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ProxyWindowEventProc(
+ ClientData clientData, /* Information about window. */
+ XEvent *eventPtr) /* Information about event. */
+{
+ PanedWindow *pwPtr = clientData;
+
+ if (eventPtr->type == Expose) {
+ if (pwPtr->proxywin != NULL &&!(pwPtr->flags & PROXY_REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DisplayProxyWindow, pwPtr);
+ pwPtr->flags |= PROXY_REDRAW_PENDING;
+ }
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DisplayProxyWindow --
+ *
+ * This function redraws a paned window proxy 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.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+DisplayProxyWindow(
+ ClientData clientData) /* Information about window. */
+{
+ PanedWindow *pwPtr = clientData;
+ Pixmap pixmap;
+ Tk_Window tkwin = pwPtr->proxywin;
+ pwPtr->flags &= ~PROXY_REDRAW_PENDING;
+ if ((tkwin == NULL) || !Tk_IsMapped(tkwin)) {
+ return;
+ }
+
+#ifndef TK_NO_DOUBLE_BUFFERING
+ /*
+ * Create a pixmap for double-buffering, if necessary.
+ */
+
+ pixmap = Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin),
+ Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));
+#else
+ pixmap = Tk_WindowId(tkwin);
+#endif /* TK_NO_DOUBLE_BUFFERING */
+
+ /*
+ * Redraw the widget's background and border.
+ */
+
+ Tk_Fill3DRectangle(tkwin, pixmap,
+ pwPtr->proxyBackground ? pwPtr->proxyBackground : pwPtr->background,
+ 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), pwPtr->proxyBorderWidth,
+ (pwPtr->proxyRelief != TK_RELIEF_NULL) ? pwPtr->proxyRelief : pwPtr->sashRelief);
+
+#ifndef TK_NO_DOUBLE_BUFFERING
+ /*
+ * Copy the pixmap to the display.
+ */
+
+ XCopyArea(Tk_Display(tkwin), pixmap, Tk_WindowId(tkwin), pwPtr->gc, 0, 0,
+ (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin), 0, 0);
+ Tk_FreePixmap(Tk_Display(tkwin), pixmap);
+#endif /* TK_NO_DOUBLE_BUFFERING */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PanedWindowProxyCommand --
+ *
+ * Handles the panedwindow proxy subcommand. See the user documentation
+ * for details.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * May map or unmap the proxy sash.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+PanedWindowProxyCommand(
+ PanedWindow *pwPtr, /* Pointer to paned window information. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ static const char *const optionStrings[] = {
+ "coord", "forget", "place", NULL
+ };
+ enum options {
+ PROXY_COORD, PROXY_FORGET, PROXY_PLACE
+ };
+ int index, x, y, sashWidth, sashHeight;
+ int internalBW, pwWidth, pwHeight;
+ Tcl_Obj *coords[2];
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObj(interp, objv[2], optionStrings, "option", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch ((enum options) index) {
+ case PROXY_COORD:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ return TCL_ERROR;
+ }
+
+ coords[0] = Tcl_NewIntObj(pwPtr->proxyx);
+ coords[1] = Tcl_NewIntObj(pwPtr->proxyy);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(2, coords));
+ break;
+
+ case PROXY_FORGET:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ return TCL_ERROR;
+ }
+ if (Tk_IsMapped(pwPtr->proxywin)) {
+ Tk_UnmapWindow(pwPtr->proxywin);
+ Tk_UnmaintainGeometry(pwPtr->proxywin, pwPtr->tkwin);
+ }
+ break;
+
+ case PROXY_PLACE:
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 3, objv, "x y");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ internalBW = Tk_InternalBorderWidth(pwPtr->tkwin);
+ if (pwPtr->orient == ORIENT_HORIZONTAL) {
+ if (x < 0) {
+ x = 0;
+ }
+ pwWidth = Tk_Width(pwPtr->tkwin) - (2 * internalBW);
+ if (x > pwWidth) {
+ x = pwWidth;
+ }
+ y = Tk_InternalBorderWidth(pwPtr->tkwin);
+ sashWidth = pwPtr->sashWidth;
+ sashHeight = Tk_Height(pwPtr->tkwin) -
+ (2 * Tk_InternalBorderWidth(pwPtr->tkwin));
+ } else {
+ if (y < 0) {
+ y = 0;
+ }
+ pwHeight = Tk_Height(pwPtr->tkwin) - (2 * internalBW);
+ if (y > pwHeight) {
+ y = pwHeight;
+ }
+ x = Tk_InternalBorderWidth(pwPtr->tkwin);
+ sashHeight = pwPtr->sashWidth;
+ sashWidth = Tk_Width(pwPtr->tkwin) -
+ (2 * Tk_InternalBorderWidth(pwPtr->tkwin));
+ }
+
+ if (sashWidth < 1) {
+ sashWidth = 1;
+ }
+ if (sashHeight < 1) {
+ sashHeight = 1;
+ }
+
+ /*
+ * Stash the proxy coordinates for future "proxy coord" calls.
+ */
+
+ pwPtr->proxyx = x;
+ pwPtr->proxyy = y;
+
+ /*
+ * Make sure the proxy window is higher in the stacking order than the
+ * slaves, so that it will be visible when drawn. It would be more
+ * correct to push the proxy window just high enough to appear above
+ * the highest slave, but it's much easier to just force it all the
+ * way to the top of the stacking order.
+ */
+
+ Tk_RestackWindow(pwPtr->proxywin, Above, NULL);
+
+ /*
+ * Let Tk_MaintainGeometry take care of placing the window at the
+ * right coordinates.
+ */
+
+ Tk_MaintainGeometry(pwPtr->proxywin, pwPtr->tkwin, x, y,
+ sashWidth, sashHeight);
+ break;
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ObjectIsEmpty --
+ *
+ * This function tests whether the string value of an object is empty.
+ *
+ * Results:
+ * The return value is 1 if the string value of objPtr has length zero,
+ * and 0 otherwise.
+ *
+ * Side effects:
+ * May cause object shimmering, since this function can force a
+ * conversion to a string object.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ObjectIsEmpty(
+ Tcl_Obj *objPtr) /* Object to test. May be NULL. */
+{
+ if (objPtr == NULL) {
+ return 1;
+ }
+ if (objPtr->bytes == NULL) {
+ Tcl_GetString(objPtr);
+ }
+ return (objPtr->length == 0);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ComputeInternalPointer --
+ *
+ * Given a pointer to the start of a record and the offset of a slot
+ * within that record, compute the address of that slot.
+ *
+ * Results:
+ * If offset is non-negative, returns the computed address; else, returns
+ * NULL.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static char *
+ComputeSlotAddress(
+ char *recordPtr, /* Pointer to the start of a record. */
+ int offset) /* Offset of a slot within that record; may be < 0. */
+{
+ if (offset >= 0) {
+ return recordPtr + offset;
+ } else {
+ return NULL;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PanedWindowIdentifyCoords --
+ *
+ * Given a pair of x,y coordinates, identify the panedwindow component at
+ * that point, if any.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * Modifies the interpreter's result to contain either an empty list, or
+ * a two element list of the form {sash n} or {handle n} to indicate that
+ * the point lies within the n'th sash or handle.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+PanedWindowIdentifyCoords(
+ PanedWindow *pwPtr, /* Information about the widget. */
+ Tcl_Interp *interp, /* Interpreter in which to store result. */
+ int x, int y) /* Coordinates of the point to identify. */
+{
+ int i, sashHeight, sashWidth, thisx, thisy;
+ int found, isHandle, lpad, rpad, tpad, bpad;
+ int first, last;
+
+ if (pwPtr->orient == ORIENT_HORIZONTAL) {
+ if (Tk_IsMapped(pwPtr->tkwin)) {
+ sashHeight = Tk_Height(pwPtr->tkwin);
+ } else {
+ sashHeight = Tk_ReqHeight(pwPtr->tkwin);
+ }
+ sashHeight -= 2 * Tk_InternalBorderWidth(pwPtr->tkwin);
+ if (pwPtr->showHandle && pwPtr->handleSize > pwPtr->sashWidth) {
+ sashWidth = pwPtr->handleSize;
+ lpad = (pwPtr->handleSize - pwPtr->sashWidth) / 2;
+ rpad = pwPtr->handleSize - lpad;
+ lpad += pwPtr->sashPad;
+ rpad += pwPtr->sashPad;
+ } else {
+ sashWidth = pwPtr->sashWidth;
+ lpad = rpad = pwPtr->sashPad;
+ }
+ tpad = bpad = 0;
+ } else {
+ if (pwPtr->showHandle && pwPtr->handleSize > pwPtr->sashWidth) {
+ sashHeight = pwPtr->handleSize;
+ tpad = (pwPtr->handleSize - pwPtr->sashWidth) / 2;
+ bpad = pwPtr->handleSize - tpad;
+ tpad += pwPtr->sashPad;
+ bpad += pwPtr->sashPad;
+ } else {
+ sashHeight = pwPtr->sashWidth;
+ tpad = bpad = pwPtr->sashPad;
+ }
+ if (Tk_IsMapped(pwPtr->tkwin)) {
+ sashWidth = Tk_Width(pwPtr->tkwin);
+ } else {
+ sashWidth = Tk_ReqWidth(pwPtr->tkwin);
+ }
+ sashWidth -= 2 * Tk_InternalBorderWidth(pwPtr->tkwin);
+ lpad = rpad = 0;
+ }
+
+ GetFirstLastVisiblePane(pwPtr, &first, &last);
+ isHandle = 0;
+ found = -1;
+ for (i = 0; i < pwPtr->numSlaves - 1; i++) {
+ if (pwPtr->slaves[i]->hide || i == last) {
+ continue;
+ }
+ thisx = pwPtr->slaves[i]->sashx;
+ thisy = pwPtr->slaves[i]->sashy;
+
+ if (((thisx - lpad) <= x && x <= (thisx + rpad + sashWidth)) &&
+ ((thisy - tpad) <= y && y <= (thisy + bpad + sashHeight))) {
+ found = i;
+
+ /*
+ * Determine if the point is over the handle or the sash.
+ */
+
+ if (pwPtr->showHandle) {
+ thisx = pwPtr->slaves[i]->handlex;
+ thisy = pwPtr->slaves[i]->handley;
+ if (pwPtr->orient == ORIENT_HORIZONTAL) {
+ if (thisy <= y && y <= (thisy + pwPtr->handleSize)) {
+ isHandle = 1;
+ }
+ } else {
+ if (thisx <= x && x <= (thisx + pwPtr->handleSize)) {
+ isHandle = 1;
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ /*
+ * Set results. Note that the empty string is the default (this function
+ * is called inside the implementation of a command).
+ */
+
+ if (found != -1) {
+ Tcl_Obj *list[2];
+
+ list[0] = Tcl_NewIntObj(found);
+ list[1] = Tcl_NewStringObj((isHandle ? "handle" : "sash"), -1);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(2, list));
+ }
+ return TCL_OK;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkPlace.c b/tk8.6/generic/tkPlace.c
new file mode 100644
index 0000000..59b8a2b
--- /dev/null
+++ b/tk8.6/generic/tkPlace.c
@@ -0,0 +1,1271 @@
+/*
+ * tkPlace.c --
+ *
+ * This file contains code to implement a simple geometry manager for Tk
+ * based on absolute placement or "rubber-sheet" placement.
+ *
+ * Copyright (c) 1992-1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "tkInt.h"
+
+/*
+ * Border modes for relative placement:
+ *
+ * BM_INSIDE: relative distances computed using area inside all
+ * borders of master window.
+ * BM_OUTSIDE: relative distances computed using outside area that
+ * includes all borders of master.
+ * BM_IGNORE: border issues are ignored: place relative to master's
+ * actual window size.
+ */
+
+static const char *const borderModeStrings[] = {
+ "inside", "outside", "ignore", NULL
+};
+
+typedef enum {BM_INSIDE, BM_OUTSIDE, BM_IGNORE} BorderMode;
+
+/*
+ * For each window whose geometry is managed by the placer there is a
+ * structure of the following type:
+ */
+
+typedef struct Slave {
+ Tk_Window tkwin; /* Tk's token for window. */
+ Tk_Window inTkwin; /* Token for the -in window. */
+ struct Master *masterPtr; /* Pointer to information for window relative
+ * to which tkwin is placed. This isn't
+ * necessarily the logical parent of tkwin.
+ * NULL means the master was deleted or never
+ * assigned. */
+ struct Slave *nextPtr; /* Next in list of windows placed relative to
+ * same master (NULL for end of list). */
+ Tk_OptionTable optionTable; /* Table that defines configuration options
+ * available for this command. */
+ /*
+ * Geometry information for window; where there are both relative and
+ * absolute values for the same attribute (e.g. x and relX) only one of
+ * them is actually used, depending on flags.
+ */
+
+ int x, y; /* X and Y pixel coordinates for tkwin. */
+ Tcl_Obj *xPtr, *yPtr; /* Tcl_Obj rep's of x, y coords, to keep pixel
+ * spec. information. */
+ double relX, relY; /* X and Y coordinates relative to size of
+ * master. */
+ int width, height; /* Absolute dimensions for tkwin. */
+ Tcl_Obj *widthPtr; /* Tcl_Obj rep of width, to keep pixel
+ * spec. */
+ Tcl_Obj *heightPtr; /* Tcl_Obj rep of height, to keep pixel
+ * spec. */
+ double relWidth, relHeight; /* Dimensions for tkwin relative to size of
+ * master. */
+ Tcl_Obj *relWidthPtr;
+ Tcl_Obj *relHeightPtr;
+ Tk_Anchor anchor; /* Which point on tkwin is placed at the given
+ * position. */
+ BorderMode borderMode; /* How to treat borders of master window. */
+ int flags; /* Various flags; see below for bit
+ * definitions. */
+} Slave;
+
+/*
+ * Type masks for options:
+ */
+
+#define IN_MASK 1
+
+static const Tk_OptionSpec optionSpecs[] = {
+ {TK_OPTION_ANCHOR, "-anchor", NULL, NULL, "nw", -1,
+ Tk_Offset(Slave, anchor), 0, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-bordermode", NULL, NULL, "inside", -1,
+ Tk_Offset(Slave, borderMode), 0, borderModeStrings, 0},
+ {TK_OPTION_PIXELS, "-height", NULL, NULL, "", Tk_Offset(Slave, heightPtr),
+ Tk_Offset(Slave, height), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_WINDOW, "-in", NULL, NULL, "", -1, Tk_Offset(Slave, inTkwin),
+ 0, 0, IN_MASK},
+ {TK_OPTION_DOUBLE, "-relheight", NULL, NULL, "",
+ Tk_Offset(Slave, relHeightPtr), Tk_Offset(Slave, relHeight),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_DOUBLE, "-relwidth", NULL, NULL, "",
+ Tk_Offset(Slave, relWidthPtr), Tk_Offset(Slave, relWidth),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_DOUBLE, "-relx", NULL, NULL, "0", -1,
+ Tk_Offset(Slave, relX), 0, 0, 0},
+ {TK_OPTION_DOUBLE, "-rely", NULL, NULL, "0", -1,
+ Tk_Offset(Slave, relY), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-width", NULL, NULL, "", Tk_Offset(Slave, widthPtr),
+ Tk_Offset(Slave, width), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-x", NULL, NULL, "0", Tk_Offset(Slave, xPtr),
+ Tk_Offset(Slave, x), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-y", NULL, NULL, "0", Tk_Offset(Slave, yPtr),
+ Tk_Offset(Slave, y), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0}
+};
+
+/*
+ * Flag definitions for Slave structures:
+ *
+ * CHILD_WIDTH - 1 means -width was specified;
+ * CHILD_REL_WIDTH - 1 means -relwidth was specified.
+ * CHILD_HEIGHT - 1 means -height was specified;
+ * CHILD_REL_HEIGHT - 1 means -relheight was specified.
+ */
+
+#define CHILD_WIDTH 1
+#define CHILD_REL_WIDTH 2
+#define CHILD_HEIGHT 4
+#define CHILD_REL_HEIGHT 8
+
+/*
+ * For each master window that has a slave managed by the placer there is a
+ * structure of the following form:
+ */
+
+typedef struct Master {
+ Tk_Window tkwin; /* Tk's token for master window. */
+ struct Slave *slavePtr; /* First in linked list of slaves placed
+ * relative to this master. */
+ int *abortPtr; /* If non-NULL, it means that there is a nested
+ * call to RecomputePlacement already working on
+ * this window. *abortPtr may be set to 1 to
+ * abort that nested call. This happens, for
+ * example, if tkwin or any of its slaves
+ * is deleted. */
+ int flags; /* See below for bit definitions. */
+} Master;
+
+/*
+ * Flag definitions for masters:
+ *
+ * PARENT_RECONFIG_PENDING - 1 means that a call to RecomputePlacement is
+ * already pending via a Do_When_Idle handler.
+ */
+
+#define PARENT_RECONFIG_PENDING 1
+
+/*
+ * The following structure is the official type record for the placer:
+ */
+
+static void PlaceRequestProc(ClientData clientData,
+ Tk_Window tkwin);
+static void PlaceLostSlaveProc(ClientData clientData,
+ Tk_Window tkwin);
+
+static const Tk_GeomMgr placerType = {
+ "place", /* name */
+ PlaceRequestProc, /* requestProc */
+ PlaceLostSlaveProc, /* lostSlaveProc */
+};
+
+/*
+ * Forward declarations for functions defined later in this file:
+ */
+
+static void SlaveStructureProc(ClientData clientData,
+ XEvent *eventPtr);
+static int ConfigureSlave(Tcl_Interp *interp, Tk_Window tkwin,
+ Tk_OptionTable table, int objc,
+ Tcl_Obj *const objv[]);
+static int PlaceInfoCommand(Tcl_Interp *interp, Tk_Window tkwin);
+static Slave * CreateSlave(Tk_Window tkwin, Tk_OptionTable table);
+static void FreeSlave(Slave *slavePtr);
+static Slave * FindSlave(Tk_Window tkwin);
+static Master * CreateMaster(Tk_Window tkwin);
+static Master * FindMaster(Tk_Window tkwin);
+static void MasterStructureProc(ClientData clientData,
+ XEvent *eventPtr);
+static void RecomputePlacement(ClientData clientData);
+static void UnlinkSlave(Slave *slavePtr);
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_PlaceObjCmd --
+ *
+ * This function is invoked to process the "place" Tcl commands. See the
+ * user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_PlaceObjCmd(
+ ClientData clientData, /* Interpreter main window. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Tk_Window main_win = clientData;
+ Tk_Window tkwin;
+ Slave *slavePtr;
+ TkDisplay *dispPtr;
+ Tk_OptionTable optionTable;
+ static const char *const optionStrings[] = {
+ "configure", "forget", "info", "slaves", NULL
+ };
+ enum options { PLACE_CONFIGURE, PLACE_FORGET, PLACE_INFO, PLACE_SLAVES };
+ int index;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option|pathName args");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Create the option table for this widget class. If it has already been
+ * created, the cached pointer will be returned.
+ */
+
+ optionTable = Tk_CreateOptionTable(interp, optionSpecs);
+
+ /*
+ * Handle special shortcut where window name is first argument.
+ */
+
+ if (Tcl_GetString(objv[1])[0] == '.') {
+ if (TkGetWindowFromObj(interp, main_win, objv[1],
+ &tkwin) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Initialize, if that hasn't been done yet.
+ */
+
+ dispPtr = ((TkWindow *) tkwin)->dispPtr;
+ if (!dispPtr->placeInit) {
+ Tcl_InitHashTable(&dispPtr->masterTable, TCL_ONE_WORD_KEYS);
+ Tcl_InitHashTable(&dispPtr->slaveTable, TCL_ONE_WORD_KEYS);
+ dispPtr->placeInit = 1;
+ }
+
+ return ConfigureSlave(interp, tkwin, optionTable, objc-2, objv+2);
+ }
+
+ /*
+ * Handle more general case of option followed by window name followed by
+ * possible additional arguments.
+ */
+
+ if (TkGetWindowFromObj(interp, main_win, objv[2],
+ &tkwin) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Initialize, if that hasn't been done yet.
+ */
+
+ dispPtr = ((TkWindow *) tkwin)->dispPtr;
+ if (!dispPtr->placeInit) {
+ Tcl_InitHashTable(&dispPtr->masterTable, TCL_ONE_WORD_KEYS);
+ Tcl_InitHashTable(&dispPtr->slaveTable, TCL_ONE_WORD_KEYS);
+ dispPtr->placeInit = 1;
+ }
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings,
+ sizeof(char *), "option", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch ((enum options) index) {
+ case PLACE_CONFIGURE:
+ if (objc == 3 || objc == 4) {
+ Tcl_Obj *objPtr;
+
+ slavePtr = FindSlave(tkwin);
+ if (slavePtr == NULL) {
+ return TCL_OK;
+ }
+ objPtr = Tk_GetOptionInfo(interp, (char *) slavePtr, optionTable,
+ (objc == 4) ? objv[3] : NULL, tkwin);
+ if (objPtr == NULL) {
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ return TCL_OK;
+ }
+ return ConfigureSlave(interp, tkwin, optionTable, objc-3, objv+3);
+
+ case PLACE_FORGET:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "pathName");
+ return TCL_ERROR;
+ }
+ slavePtr = FindSlave(tkwin);
+ if (slavePtr == NULL) {
+ return TCL_OK;
+ }
+ if ((slavePtr->masterPtr != NULL) &&
+ (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin))) {
+ Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin);
+ }
+ UnlinkSlave(slavePtr);
+ Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->slaveTable,
+ (char *) tkwin));
+ Tk_DeleteEventHandler(tkwin, StructureNotifyMask, SlaveStructureProc,
+ slavePtr);
+ Tk_ManageGeometry(tkwin, NULL, NULL);
+ Tk_UnmapWindow(tkwin);
+ FreeSlave(slavePtr);
+ break;
+
+ case PLACE_INFO:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "pathName");
+ return TCL_ERROR;
+ }
+ return PlaceInfoCommand(interp, tkwin);
+
+ case PLACE_SLAVES: {
+ Master *masterPtr;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "pathName");
+ return TCL_ERROR;
+ }
+ masterPtr = FindMaster(tkwin);
+ if (masterPtr != NULL) {
+ Tcl_Obj *listPtr = Tcl_NewObj();
+
+ for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
+ slavePtr = slavePtr->nextPtr) {
+ Tcl_ListObjAppendElement(NULL, listPtr,
+ TkNewWindowObj(slavePtr->tkwin));
+ }
+ Tcl_SetObjResult(interp, listPtr);
+ }
+ break;
+ }
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CreateSlave --
+ *
+ * Given a Tk_Window token, find the Slave structure corresponding to
+ * that token, creating a new one if necessary.
+ *
+ * Results:
+ * Pointer to the Slave structure.
+ *
+ * Side effects:
+ * A new Slave structure may be created.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Slave *
+CreateSlave(
+ Tk_Window tkwin, /* Token for desired slave. */
+ Tk_OptionTable table)
+{
+ Tcl_HashEntry *hPtr;
+ register Slave *slavePtr;
+ int isNew;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+
+ hPtr = Tcl_CreateHashEntry(&dispPtr->slaveTable, (char *) tkwin, &isNew);
+ if (!isNew) {
+ return Tcl_GetHashValue(hPtr);
+ }
+
+ /*
+ * No preexisting slave structure for that window, so make a new one and
+ * populate it with some default values.
+ */
+
+ slavePtr = ckalloc(sizeof(Slave));
+ memset(slavePtr, 0, sizeof(Slave));
+ slavePtr->tkwin = tkwin;
+ slavePtr->inTkwin = NULL;
+ slavePtr->anchor = TK_ANCHOR_NW;
+ slavePtr->borderMode = BM_INSIDE;
+ slavePtr->optionTable = table;
+ Tcl_SetHashValue(hPtr, slavePtr);
+ Tk_CreateEventHandler(tkwin, StructureNotifyMask, SlaveStructureProc,
+ slavePtr);
+ return slavePtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeSlave --
+ *
+ * Frees the resources held by a Slave structure.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * Memory are freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FreeSlave(
+ Slave *slavePtr)
+{
+ Tk_FreeConfigOptions((char *) slavePtr, slavePtr->optionTable,
+ slavePtr->tkwin);
+ ckfree(slavePtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FindSlave --
+ *
+ * Given a Tk_Window token, find the Slave structure corresponding to
+ * that token. This is purely a lookup function; it will not create a
+ * record if one does not yet exist.
+ *
+ * Results:
+ * Pointer to Slave structure; NULL if none exists.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Slave *
+FindSlave(
+ Tk_Window tkwin) /* Token for desired slave. */
+{
+ register Tcl_HashEntry *hPtr;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+
+ hPtr = Tcl_FindHashEntry(&dispPtr->slaveTable, (char *) tkwin);
+ if (hPtr == NULL) {
+ return NULL;
+ }
+ return Tcl_GetHashValue(hPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UnlinkSlave --
+ *
+ * This function removes a slave window from the chain of slaves in its
+ * master.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The slave list of slavePtr's master changes.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UnlinkSlave(
+ Slave *slavePtr) /* Slave structure to be unlinked. */
+{
+ register Master *masterPtr;
+ register Slave *prevPtr;
+
+ masterPtr = slavePtr->masterPtr;
+ if (masterPtr == NULL) {
+ return;
+ }
+ if (masterPtr->slavePtr == slavePtr) {
+ masterPtr->slavePtr = slavePtr->nextPtr;
+ } else {
+ for (prevPtr = masterPtr->slavePtr; ; prevPtr = prevPtr->nextPtr) {
+ if (prevPtr == NULL) {
+ Tcl_Panic("UnlinkSlave couldn't find slave to unlink");
+ }
+ if (prevPtr->nextPtr == slavePtr) {
+ prevPtr->nextPtr = slavePtr->nextPtr;
+ break;
+ }
+ }
+ }
+
+ if (masterPtr->abortPtr != NULL) {
+ *masterPtr->abortPtr = 1;
+ }
+ slavePtr->masterPtr = NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CreateMaster --
+ *
+ * Given a Tk_Window token, find the Master structure corresponding to
+ * that token, creating a new one if necessary.
+ *
+ * Results:
+ * Pointer to the Master structure.
+ *
+ * Side effects:
+ * A new Master structure may be created.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Master *
+CreateMaster(
+ Tk_Window tkwin) /* Token for desired master. */
+{
+ Tcl_HashEntry *hPtr;
+ register Master *masterPtr;
+ int isNew;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+
+ hPtr = Tcl_CreateHashEntry(&dispPtr->masterTable, (char *) tkwin, &isNew);
+ if (isNew) {
+ masterPtr = ckalloc(sizeof(Master));
+ masterPtr->tkwin = tkwin;
+ masterPtr->slavePtr = NULL;
+ masterPtr->abortPtr = NULL;
+ masterPtr->flags = 0;
+ Tcl_SetHashValue(hPtr, masterPtr);
+ Tk_CreateEventHandler(masterPtr->tkwin, StructureNotifyMask,
+ MasterStructureProc, masterPtr);
+ } else {
+ masterPtr = Tcl_GetHashValue(hPtr);
+ }
+ return masterPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FindMaster --
+ *
+ * Given a Tk_Window token, find the Master structure corresponding to
+ * that token. This is simply a lookup function; a new record will not be
+ * created if one does not already exist.
+ *
+ * Results:
+ * Pointer to the Master structure; NULL if one does not exist for the
+ * given Tk_Window token.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Master *
+FindMaster(
+ Tk_Window tkwin) /* Token for desired master. */
+{
+ register Tcl_HashEntry *hPtr;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+
+ hPtr = Tcl_FindHashEntry(&dispPtr->masterTable, (char *) tkwin);
+ if (hPtr == NULL) {
+ return NULL;
+ }
+ return Tcl_GetHashValue(hPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConfigureSlave --
+ *
+ * This function is called to process an argv/argc list to reconfigure
+ * the placement of a window.
+ *
+ * Results:
+ * A standard Tcl result. If an error occurs then a message is left in
+ * the interp's result.
+ *
+ * Side effects:
+ * Information in slavePtr may change, and slavePtr's master is scheduled
+ * for reconfiguration.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ConfigureSlave(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tk_Window tkwin, /* Token for the window to manipulate. */
+ Tk_OptionTable table, /* Token for option table. */
+ int objc, /* Number of config arguments. */
+ Tcl_Obj *const objv[]) /* Object values for arguments. */
+{
+ register Master *masterPtr;
+ Tk_SavedOptions savedOptions;
+ int mask;
+ Slave *slavePtr;
+ Tk_Window masterWin = NULL;
+ TkWindow *master;
+
+ if (Tk_TopWinHierarchy(tkwin)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't use placer on top-level window \"%s\"; use "
+ "wm command instead", Tk_PathName(tkwin)));
+ Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "TOPLEVEL", NULL);
+ return TCL_ERROR;
+ }
+
+ slavePtr = CreateSlave(tkwin, table);
+
+ if (Tk_SetOptions(interp, (char *) slavePtr, table, objc, objv,
+ slavePtr->tkwin, &savedOptions, &mask) != TCL_OK) {
+ goto error;
+ }
+
+ /*
+ * Set slave flags. First clear the field, then add bits as needed.
+ */
+
+ slavePtr->flags = 0;
+ if (slavePtr->heightPtr) {
+ slavePtr->flags |= CHILD_HEIGHT;
+ }
+
+ if (slavePtr->relHeightPtr) {
+ slavePtr->flags |= CHILD_REL_HEIGHT;
+ }
+
+ if (slavePtr->relWidthPtr) {
+ slavePtr->flags |= CHILD_REL_WIDTH;
+ }
+
+ if (slavePtr->widthPtr) {
+ slavePtr->flags |= CHILD_WIDTH;
+ }
+
+ if (!(mask & IN_MASK) && (slavePtr->masterPtr != NULL)) {
+ /*
+ * If no -in option was passed and the slave is already placed then
+ * just recompute the placement.
+ */
+
+ masterPtr = slavePtr->masterPtr;
+ goto scheduleLayout;
+ } else if (mask & IN_MASK) {
+ /* -in changed */
+ Tk_Window tkwin;
+ Tk_Window ancestor;
+
+ tkwin = slavePtr->inTkwin;
+
+ /*
+ * Make sure that the new master is either the logical parent of the
+ * slave or a descendant of that window, and that the master and slave
+ * aren't the same.
+ */
+
+ for (ancestor = tkwin; ; ancestor = Tk_Parent(ancestor)) {
+ if (ancestor == Tk_Parent(slavePtr->tkwin)) {
+ break;
+ }
+ if (Tk_TopWinHierarchy(ancestor)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't place %s relative to %s",
+ Tk_PathName(slavePtr->tkwin), Tk_PathName(tkwin)));
+ Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "HIERARCHY", NULL);
+ goto error;
+ }
+ }
+ if (slavePtr->tkwin == tkwin) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't place %s relative to itself",
+ Tk_PathName(slavePtr->tkwin)));
+ Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "LOOP", NULL);
+ goto error;
+ }
+
+ /*
+ * Check for management loops.
+ */
+
+ for (master = (TkWindow *)tkwin; master != NULL;
+ master = (TkWindow *)TkGetGeomMaster(master)) {
+ if (master == (TkWindow *)slavePtr->tkwin) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't put %s inside %s, would cause management loop",
+ Tk_PathName(slavePtr->tkwin), Tk_PathName(tkwin)));
+ Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "LOOP", NULL);
+ goto error;
+ }
+ }
+ if (tkwin != Tk_Parent(slavePtr->tkwin)) {
+ ((TkWindow *)slavePtr->tkwin)->maintainerPtr = (TkWindow *)tkwin;
+ }
+
+ if ((slavePtr->masterPtr != NULL)
+ && (slavePtr->masterPtr->tkwin == tkwin)) {
+ /*
+ * Re-using same old master. Nothing to do.
+ */
+
+ masterPtr = slavePtr->masterPtr;
+ goto scheduleLayout;
+ }
+ if ((slavePtr->masterPtr != NULL) &&
+ (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin))) {
+ Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin);
+ }
+ UnlinkSlave(slavePtr);
+ masterWin = tkwin;
+ }
+
+ /*
+ * If there's no master specified for this slave, use its Tk_Parent.
+ */
+
+ if (masterWin == NULL) {
+ masterWin = Tk_Parent(slavePtr->tkwin);
+ slavePtr->inTkwin = masterWin;
+ }
+
+ /*
+ * Manage the slave window in this master.
+ */
+
+ masterPtr = CreateMaster(masterWin);
+ slavePtr->masterPtr = masterPtr;
+ slavePtr->nextPtr = masterPtr->slavePtr;
+ masterPtr->slavePtr = slavePtr;
+ Tk_ManageGeometry(slavePtr->tkwin, &placerType, slavePtr);
+
+ /*
+ * Arrange for the master to be re-arranged at the first idle moment.
+ */
+
+ scheduleLayout:
+ Tk_FreeSavedOptions(&savedOptions);
+
+ if (!(masterPtr->flags & PARENT_RECONFIG_PENDING)) {
+ masterPtr->flags |= PARENT_RECONFIG_PENDING;
+ Tcl_DoWhenIdle(RecomputePlacement, masterPtr);
+ }
+ return TCL_OK;
+
+ /*
+ * Error while processing some option, cleanup and return.
+ */
+
+ error:
+ Tk_RestoreSavedOptions(&savedOptions);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PlaceInfoCommand --
+ *
+ * Implementation of the [place info] subcommand. See the user
+ * documentation for information on what it does.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * If the given tkwin is managed by the placer, this function will put
+ * information about that placement in the interp's result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+PlaceInfoCommand(
+ Tcl_Interp *interp, /* Interp into which to place result. */
+ Tk_Window tkwin) /* Token for the window to get info on. */
+{
+ Slave *slavePtr;
+ Tcl_Obj *infoObj;
+
+ slavePtr = FindSlave(tkwin);
+ if (slavePtr == NULL) {
+ return TCL_OK;
+ }
+ infoObj = Tcl_NewObj();
+ if (slavePtr->masterPtr != NULL) {
+ Tcl_AppendToObj(infoObj, "-in", -1);
+ Tcl_ListObjAppendElement(NULL, infoObj,
+ TkNewWindowObj(slavePtr->masterPtr->tkwin));
+ Tcl_AppendToObj(infoObj, " ", -1);
+ }
+ Tcl_AppendPrintfToObj(infoObj,
+ "-x %d -relx %.4g -y %d -rely %.4g",
+ slavePtr->x, slavePtr->relX, slavePtr->y, slavePtr->relY);
+ if (slavePtr->flags & CHILD_WIDTH) {
+ Tcl_AppendPrintfToObj(infoObj, " -width %d", slavePtr->width);
+ } else {
+ Tcl_AppendToObj(infoObj, " -width {}", -1);
+ }
+ if (slavePtr->flags & CHILD_REL_WIDTH) {
+ Tcl_AppendPrintfToObj(infoObj,
+ " -relwidth %.4g", slavePtr->relWidth);
+ } else {
+ Tcl_AppendToObj(infoObj, " -relwidth {}", -1);
+ }
+ if (slavePtr->flags & CHILD_HEIGHT) {
+ Tcl_AppendPrintfToObj(infoObj, " -height %d", slavePtr->height);
+ } else {
+ Tcl_AppendToObj(infoObj, " -height {}", -1);
+ }
+ if (slavePtr->flags & CHILD_REL_HEIGHT) {
+ Tcl_AppendPrintfToObj(infoObj,
+ " -relheight %.4g", slavePtr->relHeight);
+ } else {
+ Tcl_AppendToObj(infoObj, " -relheight {}", -1);
+ }
+
+ Tcl_AppendPrintfToObj(infoObj, " -anchor %s -bordermode %s",
+ Tk_NameOfAnchor(slavePtr->anchor),
+ borderModeStrings[slavePtr->borderMode]);
+ Tcl_SetObjResult(interp, infoObj);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * RecomputePlacement --
+ *
+ * This function is called as a when-idle handler. It recomputes the
+ * geometries of all the slaves of a given master.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Windows may change size or shape.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+RecomputePlacement(
+ ClientData clientData) /* Pointer to Master record. */
+{
+ register Master *masterPtr = clientData;
+ register Slave *slavePtr;
+ int x, y, width, height, tmp;
+ int masterWidth, masterHeight, masterX, masterY;
+ double x1, y1, x2, y2;
+ int abort; /* May get set to non-zero to abort this
+ * placement operation. */
+
+ masterPtr->flags &= ~PARENT_RECONFIG_PENDING;
+
+ /*
+ * Abort any nested call to RecomputePlacement for this window, since
+ * we'll do everything necessary here, and set up so this call can be
+ * aborted if necessary.
+ */
+
+ if (masterPtr->abortPtr != NULL) {
+ *masterPtr->abortPtr = 1;
+ }
+ masterPtr->abortPtr = &abort;
+ abort = 0;
+ Tcl_Preserve(masterPtr);
+
+ /*
+ * Iterate over all the slaves for the master. Each slave's geometry can
+ * be computed independently of the other slaves. Changes to the window's
+ * structure could cause almost anything to happen, including deleting the
+ * parent or child. If this happens, we'll be told to abort.
+ */
+
+ for (slavePtr = masterPtr->slavePtr; slavePtr != NULL && !abort;
+ slavePtr = slavePtr->nextPtr) {
+ /*
+ * Step 1: compute size and borderwidth of master, taking into account
+ * desired border mode.
+ */
+
+ masterX = masterY = 0;
+ masterWidth = Tk_Width(masterPtr->tkwin);
+ masterHeight = Tk_Height(masterPtr->tkwin);
+ if (slavePtr->borderMode == BM_INSIDE) {
+ masterX = Tk_InternalBorderLeft(masterPtr->tkwin);
+ masterY = Tk_InternalBorderTop(masterPtr->tkwin);
+ masterWidth -= masterX + Tk_InternalBorderRight(masterPtr->tkwin);
+ masterHeight -= masterY +
+ Tk_InternalBorderBottom(masterPtr->tkwin);
+ } else if (slavePtr->borderMode == BM_OUTSIDE) {
+ masterX = masterY = -Tk_Changes(masterPtr->tkwin)->border_width;
+ masterWidth -= 2 * masterX;
+ masterHeight -= 2 * masterY;
+ }
+
+ /*
+ * Step 2: compute size of slave (outside dimensions including border)
+ * and location of anchor point within master.
+ */
+
+ x1 = slavePtr->x + masterX + (slavePtr->relX*masterWidth);
+ x = (int) (x1 + ((x1 > 0) ? 0.5 : -0.5));
+ y1 = slavePtr->y + masterY + (slavePtr->relY*masterHeight);
+ y = (int) (y1 + ((y1 > 0) ? 0.5 : -0.5));
+ if (slavePtr->flags & (CHILD_WIDTH|CHILD_REL_WIDTH)) {
+ width = 0;
+ if (slavePtr->flags & CHILD_WIDTH) {
+ width += slavePtr->width;
+ }
+ if (slavePtr->flags & CHILD_REL_WIDTH) {
+ /*
+ * The code below is a bit tricky. In order to round correctly
+ * when both relX and relWidth are specified, compute the
+ * location of the right edge and round that, then compute
+ * width. If we compute the width and round it, rounding
+ * errors in relX and relWidth accumulate.
+ */
+
+ x2 = x1 + (slavePtr->relWidth*masterWidth);
+ tmp = (int) (x2 + ((x2 > 0) ? 0.5 : -0.5));
+ width += tmp - x;
+ }
+ } else {
+ width = Tk_ReqWidth(slavePtr->tkwin)
+ + 2*Tk_Changes(slavePtr->tkwin)->border_width;
+ }
+ if (slavePtr->flags & (CHILD_HEIGHT|CHILD_REL_HEIGHT)) {
+ height = 0;
+ if (slavePtr->flags & CHILD_HEIGHT) {
+ height += slavePtr->height;
+ }
+ if (slavePtr->flags & CHILD_REL_HEIGHT) {
+ /*
+ * See note above for rounding errors in width computation.
+ */
+
+ y2 = y1 + (slavePtr->relHeight*masterHeight);
+ tmp = (int) (y2 + ((y2 > 0) ? 0.5 : -0.5));
+ height += tmp - y;
+ }
+ } else {
+ height = Tk_ReqHeight(slavePtr->tkwin)
+ + 2*Tk_Changes(slavePtr->tkwin)->border_width;
+ }
+
+ /*
+ * Step 3: adjust the x and y positions so that the desired anchor
+ * point on the slave appears at that position. Also adjust for the
+ * border mode and master's border.
+ */
+
+ switch (slavePtr->anchor) {
+ case TK_ANCHOR_N:
+ x -= width/2;
+ break;
+ case TK_ANCHOR_NE:
+ x -= width;
+ break;
+ case TK_ANCHOR_E:
+ x -= width;
+ y -= height/2;
+ break;
+ case TK_ANCHOR_SE:
+ x -= width;
+ y -= height;
+ break;
+ case TK_ANCHOR_S:
+ x -= width/2;
+ y -= height;
+ break;
+ case TK_ANCHOR_SW:
+ y -= height;
+ break;
+ case TK_ANCHOR_W:
+ y -= height/2;
+ break;
+ case TK_ANCHOR_NW:
+ break;
+ case TK_ANCHOR_CENTER:
+ x -= width/2;
+ y -= height/2;
+ break;
+ }
+
+ /*
+ * Step 4: adjust width and height again to reflect inside dimensions
+ * of window rather than outside. Also make sure that the width and
+ * height aren't zero.
+ */
+
+ width -= 2*Tk_Changes(slavePtr->tkwin)->border_width;
+ height -= 2*Tk_Changes(slavePtr->tkwin)->border_width;
+ if (width <= 0) {
+ width = 1;
+ }
+ if (height <= 0) {
+ height = 1;
+ }
+
+ /*
+ * Step 5: reconfigure the window and map it if needed. If the slave
+ * is a child of the master, we do this ourselves. If the slave isn't
+ * a child of the master, let Tk_MaintainGeometry do the work (it will
+ * re-adjust things as relevant windows map, unmap, and move).
+ */
+
+ if (masterPtr->tkwin == Tk_Parent(slavePtr->tkwin)) {
+ if ((x != Tk_X(slavePtr->tkwin))
+ || (y != Tk_Y(slavePtr->tkwin))
+ || (width != Tk_Width(slavePtr->tkwin))
+ || (height != Tk_Height(slavePtr->tkwin))) {
+ Tk_MoveResizeWindow(slavePtr->tkwin, x, y, width, height);
+ }
+ if (abort) {
+ break;
+ }
+
+ /*
+ * Don't map the slave unless the master is mapped: the slave will
+ * get mapped later, when the master is mapped.
+ */
+
+ if (Tk_IsMapped(masterPtr->tkwin)) {
+ Tk_MapWindow(slavePtr->tkwin);
+ }
+ } else {
+ if ((width <= 0) || (height <= 0)) {
+ Tk_UnmaintainGeometry(slavePtr->tkwin, masterPtr->tkwin);
+ Tk_UnmapWindow(slavePtr->tkwin);
+ } else {
+ Tk_MaintainGeometry(slavePtr->tkwin, masterPtr->tkwin,
+ x, y, width, height);
+ }
+ }
+ }
+
+ masterPtr->abortPtr = NULL;
+ Tcl_Release(masterPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MasterStructureProc --
+ *
+ * This function is invoked by the Tk event handler when StructureNotify
+ * events occur for a master window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Structures get cleaned up if the window was deleted. If the window was
+ * resized then slave geometries get recomputed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+MasterStructureProc(
+ ClientData clientData, /* Pointer to Master structure for window
+ * referred to by eventPtr. */
+ XEvent *eventPtr) /* Describes what just happened. */
+{
+ register Master *masterPtr = clientData;
+ register Slave *slavePtr, *nextPtr;
+ TkDisplay *dispPtr = ((TkWindow *) masterPtr->tkwin)->dispPtr;
+
+ switch (eventPtr->type) {
+ case ConfigureNotify:
+ if ((masterPtr->slavePtr != NULL)
+ && !(masterPtr->flags & PARENT_RECONFIG_PENDING)) {
+ masterPtr->flags |= PARENT_RECONFIG_PENDING;
+ Tcl_DoWhenIdle(RecomputePlacement, masterPtr);
+ }
+ return;
+ case DestroyNotify:
+ for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
+ slavePtr = nextPtr) {
+ slavePtr->masterPtr = NULL;
+ nextPtr = slavePtr->nextPtr;
+ slavePtr->nextPtr = NULL;
+ }
+ Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->masterTable,
+ (char *) masterPtr->tkwin));
+ if (masterPtr->flags & PARENT_RECONFIG_PENDING) {
+ Tcl_CancelIdleCall(RecomputePlacement, masterPtr);
+ }
+ masterPtr->tkwin = NULL;
+ if (masterPtr->abortPtr != NULL) {
+ *masterPtr->abortPtr = 1;
+ }
+ Tcl_EventuallyFree(masterPtr, TCL_DYNAMIC);
+ return;
+ case MapNotify:
+ /*
+ * When a master gets mapped, must redo the geometry computation so
+ * that all of its slaves get remapped.
+ */
+
+ if ((masterPtr->slavePtr != NULL)
+ && !(masterPtr->flags & PARENT_RECONFIG_PENDING)) {
+ masterPtr->flags |= PARENT_RECONFIG_PENDING;
+ Tcl_DoWhenIdle(RecomputePlacement, masterPtr);
+ }
+ return;
+ case UnmapNotify:
+ /*
+ * Unmap all of the slaves when the master gets unmapped, so that they
+ * don't keep redisplaying themselves.
+ */
+
+ for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
+ slavePtr = slavePtr->nextPtr) {
+ Tk_UnmapWindow(slavePtr->tkwin);
+ }
+ return;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SlaveStructureProc --
+ *
+ * This function is invoked by the Tk event handler when StructureNotify
+ * events occur for a slave window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Structures get cleaned up if the window was deleted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+SlaveStructureProc(
+ ClientData clientData, /* Pointer to Slave structure for window
+ * referred to by eventPtr. */
+ XEvent *eventPtr) /* Describes what just happened. */
+{
+ register Slave *slavePtr = clientData;
+ TkDisplay *dispPtr = ((TkWindow *) slavePtr->tkwin)->dispPtr;
+
+ if (eventPtr->type == DestroyNotify) {
+ if (slavePtr->masterPtr != NULL) {
+ UnlinkSlave(slavePtr);
+ }
+ Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->slaveTable,
+ (char *) slavePtr->tkwin));
+ FreeSlave(slavePtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PlaceRequestProc --
+ *
+ * This function is invoked by Tk whenever a slave managed by us changes
+ * its requested geometry.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The window will get relayed out, if its requested size has anything to
+ * do with its actual size.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static void
+PlaceRequestProc(
+ ClientData clientData, /* Pointer to our record for slave. */
+ Tk_Window tkwin) /* Window that changed its desired size. */
+{
+ Slave *slavePtr = clientData;
+ Master *masterPtr;
+
+ if ((slavePtr->flags & (CHILD_WIDTH|CHILD_REL_WIDTH))
+ && (slavePtr->flags & (CHILD_HEIGHT|CHILD_REL_HEIGHT))) {
+ /*
+ * Send a ConfigureNotify to indicate that the size change
+ * request was rejected.
+ */
+
+ TkDoConfigureNotify((TkWindow *)(slavePtr->tkwin));
+ return;
+ }
+ masterPtr = slavePtr->masterPtr;
+ if (masterPtr == NULL) {
+ return;
+ }
+ if (!(masterPtr->flags & PARENT_RECONFIG_PENDING)) {
+ masterPtr->flags |= PARENT_RECONFIG_PENDING;
+ Tcl_DoWhenIdle(RecomputePlacement, masterPtr);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * PlaceLostSlaveProc --
+ *
+ * This function is invoked by Tk whenever some other geometry claims
+ * control over a slave that used to be managed by us.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Forgets all placer-related information about the slave.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static void
+PlaceLostSlaveProc(
+ ClientData clientData, /* Slave structure for slave window that was
+ * stolen away. */
+ Tk_Window tkwin) /* Tk's handle for the slave window. */
+{
+ register Slave *slavePtr = clientData;
+ TkDisplay *dispPtr = ((TkWindow *) slavePtr->tkwin)->dispPtr;
+
+ if (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin)) {
+ Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin);
+ }
+ Tk_UnmapWindow(tkwin);
+ UnlinkSlave(slavePtr);
+ Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->slaveTable,
+ (char *) tkwin));
+ Tk_DeleteEventHandler(tkwin, StructureNotifyMask, SlaveStructureProc,
+ slavePtr);
+ FreeSlave(slavePtr);
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkPlatDecls.h b/tk8.6/generic/tkPlatDecls.h
new file mode 100644
index 0000000..1e69c88
--- /dev/null
+++ b/tk8.6/generic/tkPlatDecls.h
@@ -0,0 +1,176 @@
+/*
+ * tkPlatDecls.h --
+ *
+ * Declarations of functions in the platform-specific public Tcl API.
+ *
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef _TKPLATDECLS
+#define _TKPLATDECLS
+
+#ifdef BUILD_tk
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLEXPORT
+#endif
+
+/*
+ * WARNING: This file is automatically generated by the tools/genStubs.tcl
+ * script. Any modifications to the function declarations below should be made
+ * in the generic/tk.decls script.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* !BEGIN!: Do not edit below this line. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Exported function declarations:
+ */
+
+#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
+/* 0 */
+EXTERN Window Tk_AttachHWND(Tk_Window tkwin, HWND hwnd);
+/* 1 */
+EXTERN HINSTANCE Tk_GetHINSTANCE(void);
+/* 2 */
+EXTERN HWND Tk_GetHWND(Window window);
+/* 3 */
+EXTERN Tk_Window Tk_HWNDToWindow(HWND hwnd);
+/* 4 */
+EXTERN void Tk_PointerEvent(HWND hwnd, int x, int y);
+/* 5 */
+EXTERN int Tk_TranslateWinEvent(HWND hwnd, UINT message,
+ WPARAM wParam, LPARAM lParam,
+ LRESULT *result);
+#endif /* WIN */
+#ifdef MAC_OSX_TK /* AQUA */
+/* 0 */
+EXTERN void Tk_MacOSXSetEmbedHandler(
+ Tk_MacOSXEmbedRegisterWinProc *registerWinProcPtr,
+ Tk_MacOSXEmbedGetGrafPortProc *getPortProcPtr,
+ Tk_MacOSXEmbedMakeContainerExistProc *containerExistProcPtr,
+ Tk_MacOSXEmbedGetClipProc *getClipProc,
+ Tk_MacOSXEmbedGetOffsetInParentProc *getOffsetProc);
+/* 1 */
+EXTERN void Tk_MacOSXTurnOffMenus(void);
+/* 2 */
+EXTERN void Tk_MacOSXTkOwnsCursor(int tkOwnsIt);
+/* 3 */
+EXTERN void TkMacOSXInitMenus(Tcl_Interp *interp);
+/* 4 */
+EXTERN void TkMacOSXInitAppleEvents(Tcl_Interp *interp);
+/* 5 */
+EXTERN void TkGenWMConfigureEvent(Tk_Window tkwin, int x, int y,
+ int width, int height, int flags);
+/* 6 */
+EXTERN void TkMacOSXInvalClipRgns(Tk_Window tkwin);
+/* 7 */
+EXTERN void * TkMacOSXGetDrawablePort(Drawable drawable);
+/* 8 */
+EXTERN void * TkMacOSXGetRootControl(Drawable drawable);
+/* 9 */
+EXTERN void Tk_MacOSXSetupTkNotifier(void);
+/* 10 */
+EXTERN int Tk_MacOSXIsAppInFront(void);
+#endif /* AQUA */
+
+typedef struct TkPlatStubs {
+ int magic;
+ void *hooks;
+
+#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
+ Window (*tk_AttachHWND) (Tk_Window tkwin, HWND hwnd); /* 0 */
+ HINSTANCE (*tk_GetHINSTANCE) (void); /* 1 */
+ HWND (*tk_GetHWND) (Window window); /* 2 */
+ Tk_Window (*tk_HWNDToWindow) (HWND hwnd); /* 3 */
+ void (*tk_PointerEvent) (HWND hwnd, int x, int y); /* 4 */
+ int (*tk_TranslateWinEvent) (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result); /* 5 */
+#endif /* WIN */
+#ifdef MAC_OSX_TK /* AQUA */
+ void (*tk_MacOSXSetEmbedHandler) (Tk_MacOSXEmbedRegisterWinProc *registerWinProcPtr, Tk_MacOSXEmbedGetGrafPortProc *getPortProcPtr, Tk_MacOSXEmbedMakeContainerExistProc *containerExistProcPtr, Tk_MacOSXEmbedGetClipProc *getClipProc, Tk_MacOSXEmbedGetOffsetInParentProc *getOffsetProc); /* 0 */
+ void (*tk_MacOSXTurnOffMenus) (void); /* 1 */
+ void (*tk_MacOSXTkOwnsCursor) (int tkOwnsIt); /* 2 */
+ void (*tkMacOSXInitMenus) (Tcl_Interp *interp); /* 3 */
+ void (*tkMacOSXInitAppleEvents) (Tcl_Interp *interp); /* 4 */
+ void (*tkGenWMConfigureEvent) (Tk_Window tkwin, int x, int y, int width, int height, int flags); /* 5 */
+ void (*tkMacOSXInvalClipRgns) (Tk_Window tkwin); /* 6 */
+ void * (*tkMacOSXGetDrawablePort) (Drawable drawable); /* 7 */
+ void * (*tkMacOSXGetRootControl) (Drawable drawable); /* 8 */
+ void (*tk_MacOSXSetupTkNotifier) (void); /* 9 */
+ int (*tk_MacOSXIsAppInFront) (void); /* 10 */
+#endif /* AQUA */
+} TkPlatStubs;
+
+extern const TkPlatStubs *tkPlatStubsPtr;
+
+#ifdef __cplusplus
+}
+#endif
+
+#if defined(USE_TK_STUBS)
+
+/*
+ * Inline function declarations:
+ */
+
+#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
+#define Tk_AttachHWND \
+ (tkPlatStubsPtr->tk_AttachHWND) /* 0 */
+#define Tk_GetHINSTANCE \
+ (tkPlatStubsPtr->tk_GetHINSTANCE) /* 1 */
+#define Tk_GetHWND \
+ (tkPlatStubsPtr->tk_GetHWND) /* 2 */
+#define Tk_HWNDToWindow \
+ (tkPlatStubsPtr->tk_HWNDToWindow) /* 3 */
+#define Tk_PointerEvent \
+ (tkPlatStubsPtr->tk_PointerEvent) /* 4 */
+#define Tk_TranslateWinEvent \
+ (tkPlatStubsPtr->tk_TranslateWinEvent) /* 5 */
+#endif /* WIN */
+#ifdef MAC_OSX_TK /* AQUA */
+#define Tk_MacOSXSetEmbedHandler \
+ (tkPlatStubsPtr->tk_MacOSXSetEmbedHandler) /* 0 */
+#define Tk_MacOSXTurnOffMenus \
+ (tkPlatStubsPtr->tk_MacOSXTurnOffMenus) /* 1 */
+#define Tk_MacOSXTkOwnsCursor \
+ (tkPlatStubsPtr->tk_MacOSXTkOwnsCursor) /* 2 */
+#define TkMacOSXInitMenus \
+ (tkPlatStubsPtr->tkMacOSXInitMenus) /* 3 */
+#define TkMacOSXInitAppleEvents \
+ (tkPlatStubsPtr->tkMacOSXInitAppleEvents) /* 4 */
+#define TkGenWMConfigureEvent \
+ (tkPlatStubsPtr->tkGenWMConfigureEvent) /* 5 */
+#define TkMacOSXInvalClipRgns \
+ (tkPlatStubsPtr->tkMacOSXInvalClipRgns) /* 6 */
+#define TkMacOSXGetDrawablePort \
+ (tkPlatStubsPtr->tkMacOSXGetDrawablePort) /* 7 */
+#define TkMacOSXGetRootControl \
+ (tkPlatStubsPtr->tkMacOSXGetRootControl) /* 8 */
+#define Tk_MacOSXSetupTkNotifier \
+ (tkPlatStubsPtr->tk_MacOSXSetupTkNotifier) /* 9 */
+#define Tk_MacOSXIsAppInFront \
+ (tkPlatStubsPtr->tk_MacOSXIsAppInFront) /* 10 */
+#endif /* AQUA */
+
+#endif /* defined(USE_TK_STUBS) */
+
+/* !END!: Do not edit above this line. */
+
+#ifdef __cplusplus
+}
+#endif
+
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLIMPORT
+
+#endif /* _TKPLATDECLS */
diff --git a/tk8.6/generic/tkPointer.c b/tk8.6/generic/tkPointer.c
new file mode 100644
index 0000000..6e87638
--- /dev/null
+++ b/tk8.6/generic/tkPointer.c
@@ -0,0 +1,647 @@
+/*
+ * tkPointer.c --
+ *
+ * This file contains functions for emulating the X server pointer and
+ * grab state machine. This file is used by the Mac and Windows platforms
+ * to generate appropriate enter/leave events, and to update the global
+ * grab window information.
+ *
+ * Copyright (c) 1996 by Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkInt.h"
+
+#ifdef _WIN32
+#include "tkWinInt.h"
+#endif
+
+#if defined(MAC_OSX_TK)
+#include "tkMacOSXInt.h"
+#define Cursor XCursor
+#endif
+
+/*
+ * Mask that selects any of the state bits corresponding to buttons, plus
+ * masks that select individual buttons' bits:
+ */
+
+#define ALL_BUTTONS \
+ (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask)
+static const unsigned int buttonMasks[] = {
+ Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask
+};
+#define ButtonMask(b) (buttonMasks[(b)-Button1])
+
+typedef struct {
+ TkWindow *grabWinPtr; /* Window that defines the top of the grab
+ * tree in a global grab. */
+ int lastState; /* Last known state flags. */
+ XPoint lastPos; /* Last reported mouse position. */
+ TkWindow *lastWinPtr; /* Last reported mouse window. */
+ TkWindow *restrictWinPtr; /* Window to which all mouse events will be
+ * reported. */
+ TkWindow *cursorWinPtr; /* Window that is currently controlling the
+ * global cursor. */
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+
+/*
+ * Forward declarations of procedures used in this file.
+ */
+
+static int GenerateEnterLeave(TkWindow *winPtr, int x, int y,
+ int state);
+static void InitializeEvent(XEvent *eventPtr, TkWindow *winPtr,
+ int type, int x, int y, int state, int detail);
+static void UpdateCursor(TkWindow *winPtr);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InitializeEvent --
+ *
+ * Initializes the common fields for several X events.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Fills in the specified event structure.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+InitializeEvent(
+ XEvent *eventPtr, /* Event structure to initialize. */
+ TkWindow *winPtr, /* Window to make event relative to. */
+ int type, /* Message type. */
+ int x, int y, /* Root coords of event. */
+ int state, /* State flags. */
+ int detail) /* Detail value. */
+{
+ eventPtr->type = type;
+ eventPtr->xany.serial = LastKnownRequestProcessed(winPtr->display);
+ eventPtr->xany.send_event = False;
+ eventPtr->xany.display = winPtr->display;
+
+ eventPtr->xcrossing.root = RootWindow(winPtr->display, winPtr->screenNum);
+ eventPtr->xcrossing.time = TkpGetMS();
+ eventPtr->xcrossing.x_root = x;
+ eventPtr->xcrossing.y_root = y;
+
+ switch (type) {
+ case EnterNotify:
+ case LeaveNotify:
+ eventPtr->xcrossing.mode = NotifyNormal;
+ eventPtr->xcrossing.state = state;
+ eventPtr->xcrossing.detail = detail;
+ eventPtr->xcrossing.focus = False;
+ break;
+ case MotionNotify:
+ eventPtr->xmotion.state = state;
+ eventPtr->xmotion.is_hint = detail;
+ break;
+ case ButtonPress:
+ case ButtonRelease:
+ eventPtr->xbutton.state = state;
+ eventPtr->xbutton.button = detail;
+ break;
+ }
+ TkChangeEventWindow(eventPtr, winPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GenerateEnterLeave --
+ *
+ * Update the current mouse window and position, and generate any
+ * enter/leave events that are needed.
+ *
+ * Results:
+ * Returns 1 if enter/leave events were generated.
+ *
+ * Side effects:
+ * May insert events into the Tk event queue.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GenerateEnterLeave(
+ TkWindow *winPtr, /* Current Tk window (or NULL). */
+ int x, int y, /* Current mouse position in root coords. */
+ int state) /* State flags. */
+{
+ int crossed = 0; /* 1 if mouse crossed a window boundary */
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ TkWindow *restrictWinPtr = tsdPtr->restrictWinPtr;
+ TkWindow *lastWinPtr = tsdPtr->lastWinPtr;
+
+ if (winPtr != tsdPtr->lastWinPtr) {
+ if (restrictWinPtr) {
+ int newPos, oldPos;
+
+ newPos = TkPositionInTree(winPtr, restrictWinPtr);
+ oldPos = TkPositionInTree(lastWinPtr, restrictWinPtr);
+
+ /*
+ * Check if the mouse crossed into or out of the restrict window.
+ * If so, we need to generate an Enter or Leave event.
+ */
+
+ if ((newPos != oldPos) && ((newPos == TK_GRAB_IN_TREE)
+ || (oldPos == TK_GRAB_IN_TREE))) {
+ XEvent event;
+ int type, detail;
+
+ if (newPos == TK_GRAB_IN_TREE) {
+ type = EnterNotify;
+ } else {
+ type = LeaveNotify;
+ }
+ if ((oldPos == TK_GRAB_ANCESTOR)
+ || (newPos == TK_GRAB_ANCESTOR)) {
+ detail = NotifyAncestor;
+ } else {
+ detail = NotifyVirtual;
+ }
+ InitializeEvent(&event, restrictWinPtr, type, x, y,
+ state, detail);
+ Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+ }
+
+ } else {
+ TkWindow *targetPtr;
+
+ if ((lastWinPtr == NULL)
+ || (lastWinPtr->window == None)) {
+ targetPtr = winPtr;
+ } else {
+ targetPtr = lastWinPtr;
+ }
+
+ if (targetPtr && (targetPtr->window != None)) {
+ XEvent event;
+
+ /*
+ * Generate appropriate Enter/Leave events.
+ */
+
+ InitializeEvent(&event, targetPtr, LeaveNotify, x, y, state,
+ NotifyNormal);
+
+ TkInOutEvents(&event, lastWinPtr, winPtr, LeaveNotify,
+ EnterNotify, TCL_QUEUE_TAIL);
+ crossed = 1;
+ }
+ }
+ tsdPtr->lastWinPtr = winPtr;
+ }
+
+ return crossed;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_UpdatePointer --
+ *
+ * This function updates the pointer state machine given an the current
+ * window, position and modifier state.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * May queue new events and update the grab state.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_UpdatePointer(
+ Tk_Window tkwin, /* Window to which pointer event is reported.
+ * May be NULL. */
+ int x, int y, /* Pointer location in root coords. */
+ int state) /* Modifier state mask. */
+{
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ TkWindow *winPtr = (TkWindow *)tkwin;
+ TkWindow *targetWinPtr;
+ XPoint pos;
+ XEvent event;
+ int changes = (state ^ tsdPtr->lastState) & ALL_BUTTONS;
+ int type, b, mask;
+
+ pos.x = x;
+ pos.y = y;
+
+ /*
+ * Use the current keyboard state, but the old mouse button state since we
+ * haven't generated the button events yet.
+ */
+
+ tsdPtr->lastState = (state & ~ALL_BUTTONS) | (tsdPtr->lastState
+ & ALL_BUTTONS);
+
+ /*
+ * Generate Enter/Leave events. If the pointer has crossed window
+ * boundaries, update the current mouse position so we don't generate
+ * redundant motion events.
+ */
+
+ if (GenerateEnterLeave(winPtr, x, y, tsdPtr->lastState)) {
+ tsdPtr->lastPos = pos;
+ }
+
+ /*
+ * Generate ButtonPress/ButtonRelease events based on the differences
+ * between the current button state and the last known button state.
+ */
+
+ for (b = Button1; b <= Button5; b++) {
+ mask = ButtonMask(b);
+ if (changes & mask) {
+ if (state & mask) {
+ type = ButtonPress;
+
+ /*
+ * ButtonPress - Set restrict window if we aren't grabbed, or
+ * if this is the first button down.
+ */
+
+ if (!tsdPtr->restrictWinPtr) {
+ if (!tsdPtr->grabWinPtr) {
+ /*
+ * Mouse is not grabbed, so set a button grab.
+ */
+
+ tsdPtr->restrictWinPtr = winPtr;
+ TkpSetCapture(tsdPtr->restrictWinPtr);
+
+ } else if (!(tsdPtr->lastState & ALL_BUTTONS)) {
+ /*
+ * Mouse is in a non-button grab, so ensure the button
+ * grab is inside the grab tree.
+ */
+
+ if (TkPositionInTree(winPtr, tsdPtr->grabWinPtr)
+ == TK_GRAB_IN_TREE) {
+ tsdPtr->restrictWinPtr = winPtr;
+ } else {
+ tsdPtr->restrictWinPtr = tsdPtr->grabWinPtr;
+ }
+ TkpSetCapture(tsdPtr->restrictWinPtr);
+ }
+ }
+
+ } else {
+ type = ButtonRelease;
+
+ /*
+ * ButtonRelease - Release the mouse capture and clear the
+ * restrict window when the last button is released. If we
+ * are in a global grab, restore the grab window capture.
+ */
+
+ if ((tsdPtr->lastState & ALL_BUTTONS) == mask) {
+ TkpSetCapture(tsdPtr->grabWinPtr);
+ }
+
+ /*
+ * If we are releasing a restrict window, then we need to send
+ * the button event followed by mouse motion from the restrict
+ * window to the current mouse position.
+ */
+
+ if (tsdPtr->restrictWinPtr) {
+ InitializeEvent(&event, tsdPtr->restrictWinPtr, type, x, y,
+ tsdPtr->lastState, b);
+ Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+ tsdPtr->lastState &= ~mask;
+ tsdPtr->lastWinPtr = tsdPtr->restrictWinPtr;
+ tsdPtr->restrictWinPtr = NULL;
+
+ GenerateEnterLeave(winPtr, x, y, tsdPtr->lastState);
+ tsdPtr->lastPos = pos;
+ continue;
+ }
+ }
+
+ /*
+ * If a restrict window is set, make sure the pointer event is
+ * reported relative to that window. Otherwise, if a global grab
+ * is in effect then events outside of windows managed by Tk
+ * should be reported to the grab window.
+ */
+
+ if (tsdPtr->restrictWinPtr) {
+ targetWinPtr = tsdPtr->restrictWinPtr;
+ } else if (tsdPtr->grabWinPtr && !winPtr) {
+ targetWinPtr = tsdPtr->grabWinPtr;
+ } else {
+ targetWinPtr = winPtr;
+ }
+
+ /*
+ * If we still have a target window, send the event.
+ */
+
+ if (targetWinPtr != NULL) {
+ InitializeEvent(&event, targetWinPtr, type, x, y,
+ tsdPtr->lastState, b);
+ Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+ }
+
+ /*
+ * Update the state for the next iteration.
+ */
+
+ tsdPtr->lastState = (type == ButtonPress)
+ ? (tsdPtr->lastState | mask) : (tsdPtr->lastState & ~mask);
+ tsdPtr->lastPos = pos;
+ }
+ }
+
+ /*
+ * Make sure the cursor window is up to date.
+ */
+
+ if (tsdPtr->restrictWinPtr) {
+ targetWinPtr = tsdPtr->restrictWinPtr;
+ } else if (tsdPtr->grabWinPtr) {
+ targetWinPtr = (TkPositionInTree(winPtr, tsdPtr->grabWinPtr)
+ == TK_GRAB_IN_TREE) ? winPtr : tsdPtr->grabWinPtr;
+ } else {
+ targetWinPtr = winPtr;
+ }
+ UpdateCursor(targetWinPtr);
+
+ /*
+ * If no other events caused the position to be updated, generate a motion
+ * event.
+ */
+
+ if (tsdPtr->lastPos.x != pos.x || tsdPtr->lastPos.y != pos.y) {
+ if (tsdPtr->restrictWinPtr) {
+ targetWinPtr = tsdPtr->restrictWinPtr;
+ } else if (tsdPtr->grabWinPtr && !winPtr) {
+ targetWinPtr = tsdPtr->grabWinPtr;
+ }
+
+ if (targetWinPtr != NULL) {
+ InitializeEvent(&event, targetWinPtr, MotionNotify, x, y,
+ tsdPtr->lastState, NotifyNormal);
+ Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+ }
+ tsdPtr->lastPos = pos;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XGrabPointer --
+ *
+ * Capture the mouse so event are reported outside of toplevels. Note
+ * that this is a very limited implementation that only supports
+ * GrabModeAsync and owner_events True.
+ *
+ * Results:
+ * Always returns GrabSuccess.
+ *
+ * Side effects:
+ * Turns on mouse capture, sets the global grab pointer, and clears any
+ * window restrictions.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+XGrabPointer(
+ Display *display,
+ Window grab_window,
+ Bool owner_events,
+ unsigned int event_mask,
+ int pointer_mode,
+ int keyboard_mode,
+ Window confine_to,
+ Cursor cursor,
+ Time time)
+{
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ display->request++;
+ tsdPtr->grabWinPtr = (TkWindow *) Tk_IdToWindow(display, grab_window);
+ tsdPtr->restrictWinPtr = NULL;
+ TkpSetCapture(tsdPtr->grabWinPtr);
+ if (TkPositionInTree(tsdPtr->lastWinPtr, tsdPtr->grabWinPtr)
+ != TK_GRAB_IN_TREE) {
+ UpdateCursor(tsdPtr->grabWinPtr);
+ }
+ return GrabSuccess;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XUngrabPointer --
+ *
+ * Release the current grab.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Releases the mouse capture.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+XUngrabPointer(
+ Display *display,
+ Time time)
+{
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ display->request++;
+ tsdPtr->grabWinPtr = NULL;
+ tsdPtr->restrictWinPtr = NULL;
+ TkpSetCapture(NULL);
+ UpdateCursor(tsdPtr->lastWinPtr);
+ return Success;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkPointerDeadWindow --
+ *
+ * Clean up pointer module state when a window is destroyed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * May release the current capture window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkPointerDeadWindow(
+ TkWindow *winPtr)
+{
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (winPtr == tsdPtr->lastWinPtr) {
+ tsdPtr->lastWinPtr = NULL;
+ }
+ if (winPtr == tsdPtr->grabWinPtr) {
+ tsdPtr->grabWinPtr = NULL;
+ }
+ if (winPtr == tsdPtr->restrictWinPtr) {
+ tsdPtr->restrictWinPtr = NULL;
+ }
+ if (!(tsdPtr->restrictWinPtr || tsdPtr->grabWinPtr)) {
+ TkpSetCapture(NULL);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UpdateCursor --
+ *
+ * Set the windows global cursor to the cursor associated with the given
+ * Tk window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Changes the mouse cursor.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UpdateCursor(
+ TkWindow *winPtr)
+{
+ Cursor cursor = None;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ /*
+ * A window inherits its cursor from its parent if it doesn't have one of
+ * its own. Top level windows inherit the default cursor.
+ */
+
+ tsdPtr->cursorWinPtr = winPtr;
+ while (winPtr != NULL) {
+ if (winPtr->atts.cursor != None) {
+ cursor = winPtr->atts.cursor;
+ break;
+ } else if (winPtr->flags & TK_TOP_HIERARCHY) {
+ break;
+ }
+ winPtr = winPtr->parentPtr;
+ }
+ TkpSetCursor((TkpCursor) cursor);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XDefineCursor --
+ *
+ * This function is called to update the cursor on a window. Since the
+ * mouse might be in the specified window, we need to check the specified
+ * window against the current mouse position and grab state.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * May update the cursor.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+XDefineCursor(
+ Display *display,
+ Window w,
+ Cursor cursor)
+{
+ TkWindow *winPtr = (TkWindow *) Tk_IdToWindow(display, w);
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (tsdPtr->cursorWinPtr == winPtr) {
+ UpdateCursor(winPtr);
+ }
+ display->request++;
+ return Success;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkGenerateActivateEvents --
+ *
+ * This function is called by the Mac and Windows window manager routines
+ * when a toplevel window is activated or deactivated.
+ * Activate/Deactivate events will be sent to every subwindow of the
+ * toplevel followed by a FocusIn/FocusOut message.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Generates X events.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkGenerateActivateEvents(
+ TkWindow *winPtr, /* Toplevel to activate. */
+ int active) /* Non-zero if the window is being activated,
+ * else 0.*/
+{
+ XEvent event;
+
+ /*
+ * Generate Activate and Deactivate events. This event is sent to every
+ * subwindow in a toplevel window.
+ */
+
+ event.xany.serial = winPtr->display->request++;
+ event.xany.send_event = False;
+ event.xany.display = winPtr->display;
+ event.xany.window = winPtr->window;
+
+ event.xany.type = active ? ActivateNotify : DeactivateNotify;
+ TkQueueEventForAllChildren(winPtr, &event);
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkPort.h b/tk8.6/generic/tkPort.h
new file mode 100644
index 0000000..d6db449
--- /dev/null
+++ b/tk8.6/generic/tkPort.h
@@ -0,0 +1,31 @@
+/*
+ * tkPort.h --
+ *
+ * This header file handles porting issues that occur because of
+ * differences between systems. It reads in platform specific
+ * portability files.
+ *
+ * Copyright (c) 1995 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef _TKPORT
+#define _TKPORT
+
+#if defined(_WIN32)
+# include "tkWinPort.h"
+#endif
+#ifndef _TK
+# include "tk.h"
+#endif
+#if !defined(_WIN32)
+# if defined(MAC_OSX_TK)
+# include "tkMacOSXPort.h"
+# else
+# include "tkUnixPort.h"
+# endif
+#endif
+
+#endif /* _TKPORT */
diff --git a/tk8.6/generic/tkRectOval.c b/tk8.6/generic/tkRectOval.c
new file mode 100644
index 0000000..359d3ef
--- /dev/null
+++ b/tk8.6/generic/tkRectOval.c
@@ -0,0 +1,1527 @@
+/*
+ * tkRectOval.c --
+ *
+ * This file implements rectangle and oval items for canvas widgets.
+ *
+ * Copyright (c) 1991-1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "tkInt.h"
+#include "tkCanvas.h"
+
+/*
+ * The structure below defines the record for each rectangle/oval item.
+ */
+
+typedef struct RectOvalItem {
+ Tk_Item header; /* Generic stuff that's the same for all
+ * types. MUST BE FIRST IN STRUCTURE. */
+ Tk_Outline outline; /* Outline structure */
+ double bbox[4]; /* Coordinates of bounding box for rectangle
+ * or oval (x1, y1, x2, y2). Item includes x1
+ * and x2 but not y1 and y2. */
+ Tk_TSOffset tsoffset;
+ XColor *fillColor; /* Color for filling rectangle/oval. */
+ XColor *activeFillColor; /* Color for filling rectangle/oval if state
+ * is active. */
+ XColor *disabledFillColor; /* Color for filling rectangle/oval if state
+ * is disabled. */
+ Pixmap fillStipple; /* Stipple bitmap for filling item. */
+ Pixmap activeFillStipple; /* Stipple bitmap for filling item if state is
+ * active. */
+ Pixmap disabledFillStipple; /* Stipple bitmap for filling item if state is
+ * disabled. */
+ GC fillGC; /* Graphics context for filling item. */
+} RectOvalItem;
+
+/*
+ * Information used for parsing configuration specs:
+ */
+
+static const Tk_CustomOption stateOption = {
+ TkStateParseProc, TkStatePrintProc, INT2PTR(2)
+};
+static const Tk_CustomOption tagsOption = {
+ Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL
+};
+static const Tk_CustomOption dashOption = {
+ TkCanvasDashParseProc, TkCanvasDashPrintProc, NULL
+};
+static const Tk_CustomOption offsetOption = {
+ TkOffsetParseProc, TkOffsetPrintProc, INT2PTR(TK_OFFSET_RELATIVE)
+};
+static const Tk_CustomOption pixelOption = {
+ TkPixelParseProc, TkPixelPrintProc, NULL
+};
+
+static const Tk_ConfigSpec configSpecs[] = {
+ {TK_CONFIG_CUSTOM, "-activedash", NULL, NULL,
+ NULL, Tk_Offset(RectOvalItem, outline.activeDash),
+ TK_CONFIG_NULL_OK, &dashOption},
+ {TK_CONFIG_COLOR, "-activefill", NULL, NULL,
+ NULL, Tk_Offset(RectOvalItem, activeFillColor), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_COLOR, "-activeoutline", NULL, NULL,
+ NULL, Tk_Offset(RectOvalItem, outline.activeColor), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_BITMAP, "-activeoutlinestipple", NULL, NULL,
+ NULL, Tk_Offset(RectOvalItem, outline.activeStipple),
+ TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_BITMAP, "-activestipple", NULL, NULL,
+ NULL, Tk_Offset(RectOvalItem, activeFillStipple), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_CUSTOM, "-activewidth", NULL, NULL,
+ "0.0", Tk_Offset(RectOvalItem, outline.activeWidth),
+ TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
+ {TK_CONFIG_CUSTOM, "-dash", NULL, NULL,
+ NULL, Tk_Offset(RectOvalItem, outline.dash),
+ TK_CONFIG_NULL_OK, &dashOption},
+ {TK_CONFIG_PIXELS, "-dashoffset", NULL, NULL,
+ "0", Tk_Offset(RectOvalItem, outline.offset),
+ TK_CONFIG_DONT_SET_DEFAULT, NULL},
+ {TK_CONFIG_CUSTOM, "-disableddash", NULL, NULL,
+ NULL, Tk_Offset(RectOvalItem, outline.disabledDash),
+ TK_CONFIG_NULL_OK, &dashOption},
+ {TK_CONFIG_COLOR, "-disabledfill", NULL, NULL,
+ NULL, Tk_Offset(RectOvalItem, disabledFillColor), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_COLOR, "-disabledoutline", NULL, NULL,
+ NULL, Tk_Offset(RectOvalItem, outline.disabledColor),
+ TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_BITMAP, "-disabledoutlinestipple", NULL, NULL,
+ NULL, Tk_Offset(RectOvalItem, outline.disabledStipple),
+ TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_BITMAP, "-disabledstipple", NULL, NULL,
+ NULL, Tk_Offset(RectOvalItem, disabledFillStipple), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_PIXELS, "-disabledwidth", NULL, NULL,
+ "0.0", Tk_Offset(RectOvalItem, outline.disabledWidth),
+ TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
+ {TK_CONFIG_COLOR, "-fill", NULL, NULL,
+ NULL, Tk_Offset(RectOvalItem, fillColor), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_CUSTOM, "-offset", NULL, NULL,
+ "0,0", Tk_Offset(RectOvalItem, tsoffset),
+ TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},
+ {TK_CONFIG_COLOR, "-outline", NULL, NULL,
+ "black", Tk_Offset(RectOvalItem, outline.color), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_CUSTOM, "-outlineoffset", NULL, NULL,
+ "0,0", Tk_Offset(RectOvalItem, outline.tsoffset),
+ TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},
+ {TK_CONFIG_BITMAP, "-outlinestipple", NULL, NULL,
+ NULL, Tk_Offset(RectOvalItem, outline.stipple), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_CUSTOM, "-state", NULL, NULL,
+ NULL, Tk_Offset(Tk_Item, state),TK_CONFIG_NULL_OK, &stateOption},
+ {TK_CONFIG_BITMAP, "-stipple", NULL, NULL,
+ NULL, Tk_Offset(RectOvalItem, fillStipple),TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_CUSTOM, "-tags", NULL, NULL,
+ NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
+ {TK_CONFIG_CUSTOM, "-width", NULL, NULL,
+ "1.0", Tk_Offset(RectOvalItem, outline.width),
+ TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
+ {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}
+};
+
+/*
+ * Prototypes for functions defined in this file:
+ */
+
+static void ComputeRectOvalBbox(Tk_Canvas canvas,
+ RectOvalItem *rectOvalPtr);
+static int ConfigureRectOval(Tcl_Interp *interp, Tk_Canvas canvas,
+ Tk_Item *itemPtr, int objc, Tcl_Obj *const objv[],
+ int flags);
+static int CreateRectOval(Tcl_Interp *interp, Tk_Canvas canvas,
+ Tk_Item *itemPtr, int objc, Tcl_Obj *const objv[]);
+static void DeleteRectOval(Tk_Canvas canvas, Tk_Item *itemPtr,
+ Display *display);
+static void DisplayRectOval(Tk_Canvas canvas, Tk_Item *itemPtr,
+ Display *display, Drawable dst, int x, int y,
+ int width, int height);
+static int OvalToArea(Tk_Canvas canvas, Tk_Item *itemPtr,
+ double *areaPtr);
+static double OvalToPoint(Tk_Canvas canvas, Tk_Item *itemPtr,
+ double *pointPtr);
+static int RectOvalCoords(Tcl_Interp *interp, Tk_Canvas canvas,
+ Tk_Item *itemPtr, int objc, Tcl_Obj *const objv[]);
+static int RectOvalToPostscript(Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr, int prepass);
+static int RectToArea(Tk_Canvas canvas, Tk_Item *itemPtr,
+ double *areaPtr);
+static double RectToPoint(Tk_Canvas canvas, Tk_Item *itemPtr,
+ double *pointPtr);
+static void ScaleRectOval(Tk_Canvas canvas, Tk_Item *itemPtr,
+ double originX, double originY,
+ double scaleX, double scaleY);
+static void TranslateRectOval(Tk_Canvas canvas, Tk_Item *itemPtr,
+ double deltaX, double deltaY);
+
+/*
+ * The structures below defines the rectangle and oval item types by means of
+ * functions that can be invoked by generic item code.
+ */
+
+Tk_ItemType tkRectangleType = {
+ "rectangle", /* name */
+ sizeof(RectOvalItem), /* itemSize */
+ CreateRectOval, /* createProc */
+ configSpecs, /* configSpecs */
+ ConfigureRectOval, /* configureProc */
+ RectOvalCoords, /* coordProc */
+ DeleteRectOval, /* deleteProc */
+ DisplayRectOval, /* displayProc */
+ TK_CONFIG_OBJS, /* flags */
+ RectToPoint, /* pointProc */
+ RectToArea, /* areaProc */
+ RectOvalToPostscript, /* postscriptProc */
+ ScaleRectOval, /* scaleProc */
+ TranslateRectOval, /* translateProc */
+ NULL, /* indexProc */
+ NULL, /* icursorProc */
+ NULL, /* selectionProc */
+ NULL, /* insertProc */
+ NULL, /* dTextProc */
+ NULL, /* nextPtr */
+ NULL, 0, NULL, NULL
+};
+
+Tk_ItemType tkOvalType = {
+ "oval", /* name */
+ sizeof(RectOvalItem), /* itemSize */
+ CreateRectOval, /* createProc */
+ configSpecs, /* configSpecs */
+ ConfigureRectOval, /* configureProc */
+ RectOvalCoords, /* coordProc */
+ DeleteRectOval, /* deleteProc */
+ DisplayRectOval, /* displayProc */
+ TK_CONFIG_OBJS, /* flags */
+ OvalToPoint, /* pointProc */
+ OvalToArea, /* areaProc */
+ RectOvalToPostscript, /* postscriptProc */
+ ScaleRectOval, /* scaleProc */
+ TranslateRectOval, /* translateProc */
+ NULL, /* indexProc */
+ NULL, /* cursorProc */
+ NULL, /* selectionProc */
+ NULL, /* insertProc */
+ NULL, /* dTextProc */
+ NULL, /* nextPtr */
+ NULL, 0, NULL, NULL
+};
+
+/*
+ *--------------------------------------------------------------
+ *
+ * CreateRectOval --
+ *
+ * This function is invoked to create a new rectangle or oval item in a
+ * canvas.
+ *
+ * Results:
+ * A standard Tcl return value. If an error occurred in creating the
+ * item, then an error message is left in the interp's result; in this
+ * case itemPtr is left uninitialized, so it can be safely freed by the
+ * caller.
+ *
+ * Side effects:
+ * A new rectangle or oval item is created.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+CreateRectOval(
+ Tcl_Interp *interp, /* For error reporting. */
+ Tk_Canvas canvas, /* Canvas to hold new item. */
+ Tk_Item *itemPtr, /* Record to hold new item; header has been
+ * initialized by caller. */
+ int objc, /* Number of arguments in objv. */
+ Tcl_Obj *const objv[]) /* Arguments describing rectangle. */
+{
+ RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
+ int i;
+
+ if (objc == 0) {
+ Tcl_Panic("canvas did not pass any coords");
+ }
+
+ /*
+ * Carry out initialization that is needed in order to clean up after
+ * errors during the the remainder of this function.
+ */
+
+ Tk_CreateOutline(&(rectOvalPtr->outline));
+ rectOvalPtr->tsoffset.flags = 0;
+ rectOvalPtr->tsoffset.xoffset = 0;
+ rectOvalPtr->tsoffset.yoffset = 0;
+ rectOvalPtr->fillColor = NULL;
+ rectOvalPtr->activeFillColor = NULL;
+ rectOvalPtr->disabledFillColor = NULL;
+ rectOvalPtr->fillStipple = None;
+ rectOvalPtr->activeFillStipple = None;
+ rectOvalPtr->disabledFillStipple = None;
+ rectOvalPtr->fillGC = NULL;
+
+ /*
+ * Process the arguments to fill in the item record.
+ */
+
+ for (i = 1; i < objc; i++) {
+ const char *arg = Tcl_GetString(objv[i]);
+
+ if ((arg[0] == '-') && (arg[1] >= 'a') && (arg[1] <= 'z')) {
+ break;
+ }
+ }
+ if ((RectOvalCoords(interp, canvas, itemPtr, i, objv) != TCL_OK)) {
+ goto error;
+ }
+ if (ConfigureRectOval(interp, canvas, itemPtr, objc-i, objv+i, 0)
+ == TCL_OK) {
+ return TCL_OK;
+ }
+
+ error:
+ DeleteRectOval(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * RectOvalCoords --
+ *
+ * This function is invoked to process the "coords" widget command on
+ * rectangles and ovals. See the user documentation for details on what
+ * it does.
+ *
+ * Results:
+ * Returns TCL_OK or TCL_ERROR, and sets the interp's result.
+ *
+ * Side effects:
+ * The coordinates for the given item may be changed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+RectOvalCoords(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item whose coordinates are to be read or
+ * modified. */
+ int objc, /* Number of coordinates supplied in objv. */
+ Tcl_Obj *const objv[]) /* Array of coordinates: x1,y1,x2,y2,... */
+{
+ RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
+
+ /*
+ * If no coordinates, return the current coordinates (i.e. bounding box).
+ */
+
+ if (objc == 0) {
+ Tcl_Obj *bbox[4];
+
+ bbox[0] = Tcl_NewDoubleObj(rectOvalPtr->bbox[0]);
+ bbox[1] = Tcl_NewDoubleObj(rectOvalPtr->bbox[1]);
+ bbox[2] = Tcl_NewDoubleObj(rectOvalPtr->bbox[2]);
+ bbox[3] = Tcl_NewDoubleObj(rectOvalPtr->bbox[3]);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(4, bbox));
+ return TCL_OK;
+ }
+
+ /*
+ * If one "coordinate", treat as list of coordinates.
+ */
+
+ if (objc == 1) {
+ if (Tcl_ListObjGetElements(interp, objv[0], &objc,
+ (Tcl_Obj ***) &objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * Better have four coordinates now. Spit out an error message otherwise.
+ */
+
+ if (objc != 4) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "wrong # coordinates: expected 0 or 4, got %d", objc));
+ Tcl_SetErrorCode(interp, "TK", "CANVAS", "COORDS",
+ (rectOvalPtr->header.typePtr == &tkRectangleType
+ ? "RECTANGLE" : "OVAL"), NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Parse the coordinates and update our bounding box.
+ */
+
+ if ((Tk_CanvasGetCoordFromObj(interp, canvas, objv[0],
+ &rectOvalPtr->bbox[0]) != TCL_OK)
+ || (Tk_CanvasGetCoordFromObj(interp, canvas, objv[1],
+ &rectOvalPtr->bbox[1]) != TCL_OK)
+ || (Tk_CanvasGetCoordFromObj(interp, canvas, objv[2],
+ &rectOvalPtr->bbox[2]) != TCL_OK)
+ || (Tk_CanvasGetCoordFromObj(interp, canvas, objv[3],
+ &rectOvalPtr->bbox[3]) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ ComputeRectOvalBbox(canvas, rectOvalPtr);
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ConfigureRectOval --
+ *
+ * This function is invoked to configure various aspects of a rectangle
+ * or oval item, such as its border and background colors.
+ *
+ * Results:
+ * A standard Tcl result code. If an error occurs, then an error message
+ * is left in the interp's result.
+ *
+ * Side effects:
+ * Configuration information, such as colors and stipple patterns, may be
+ * set for itemPtr.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+ConfigureRectOval(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tk_Canvas canvas, /* Canvas containing itemPtr. */
+ Tk_Item *itemPtr, /* Rectangle item to reconfigure. */
+ int objc, /* Number of elements in objv. */
+ Tcl_Obj *const objv[], /* Arguments describing things to configure. */
+ int flags) /* Flags to pass to Tk_ConfigureWidget. */
+{
+ RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
+ XGCValues gcValues;
+ GC newGC;
+ unsigned long mask;
+ Tk_Window tkwin;
+ Tk_TSOffset *tsoffset;
+ XColor *color;
+ Pixmap stipple;
+ Tk_State state;
+
+ tkwin = Tk_CanvasTkwin(canvas);
+
+ if (TCL_OK != Tk_ConfigureWidget(interp, tkwin, configSpecs, objc,
+ (const char **)objv, (char *) rectOvalPtr, flags|TK_CONFIG_OBJS)) {
+ return TCL_ERROR;
+ }
+ state = itemPtr->state;
+
+ /*
+ * A few of the options require additional processing, such as graphics
+ * contexts.
+ */
+
+ if (rectOvalPtr->outline.activeWidth > rectOvalPtr->outline.width ||
+ rectOvalPtr->outline.activeDash.number != 0 ||
+ rectOvalPtr->outline.activeColor != NULL ||
+ rectOvalPtr->outline.activeStipple != None ||
+ rectOvalPtr->activeFillColor != NULL ||
+ rectOvalPtr->activeFillStipple != None) {
+ itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;
+ } else {
+ itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;
+ }
+
+ tsoffset = &rectOvalPtr->outline.tsoffset;
+ flags = tsoffset->flags;
+ if (flags & TK_OFFSET_LEFT) {
+ tsoffset->xoffset = (int) (rectOvalPtr->bbox[0] + 0.5);
+ } else if (flags & TK_OFFSET_CENTER) {
+ tsoffset->xoffset = (int)
+ ((rectOvalPtr->bbox[0]+rectOvalPtr->bbox[2]+1)/2);
+ } else if (flags & TK_OFFSET_RIGHT) {
+ tsoffset->xoffset = (int) (rectOvalPtr->bbox[2] + 0.5);
+ }
+ if (flags & TK_OFFSET_TOP) {
+ tsoffset->yoffset = (int) (rectOvalPtr->bbox[1] + 0.5);
+ } else if (flags & TK_OFFSET_MIDDLE) {
+ tsoffset->yoffset = (int)
+ ((rectOvalPtr->bbox[1]+rectOvalPtr->bbox[3]+1)/2);
+ } else if (flags & TK_OFFSET_BOTTOM) {
+ tsoffset->yoffset = (int) (rectOvalPtr->bbox[2] + 0.5);
+ }
+
+ /*
+ * Configure the outline graphics context. If mask is non-zero, the gc has
+ * changed and must be reallocated, provided that the new settings specify
+ * a valid outline (non-zero width and non-NULL color)
+ */
+
+ mask = Tk_ConfigOutlineGC(&gcValues, canvas, itemPtr,
+ &(rectOvalPtr->outline));
+ if (mask && \
+ rectOvalPtr->outline.width != 0 && \
+ rectOvalPtr->outline.color != NULL) {
+ gcValues.cap_style = CapProjecting;
+ mask |= GCCapStyle;
+ newGC = Tk_GetGC(tkwin, mask, &gcValues);
+ } else {
+ newGC = NULL;
+ }
+ if (rectOvalPtr->outline.gc != NULL) {
+ Tk_FreeGC(Tk_Display(tkwin), rectOvalPtr->outline.gc);
+ }
+ rectOvalPtr->outline.gc = newGC;
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+ if (state == TK_STATE_HIDDEN) {
+ ComputeRectOvalBbox(canvas, rectOvalPtr);
+ return TCL_OK;
+ }
+
+ color = rectOvalPtr->fillColor;
+ stipple = rectOvalPtr->fillStipple;
+ if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (rectOvalPtr->activeFillColor!=NULL) {
+ color = rectOvalPtr->activeFillColor;
+ }
+ if (rectOvalPtr->activeFillStipple!=None) {
+ stipple = rectOvalPtr->activeFillStipple;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (rectOvalPtr->disabledFillColor!=NULL) {
+ color = rectOvalPtr->disabledFillColor;
+ }
+ if (rectOvalPtr->disabledFillStipple!=None) {
+ stipple = rectOvalPtr->disabledFillStipple;
+ }
+ }
+
+ if (color == NULL) {
+ newGC = NULL;
+ } else {
+ gcValues.foreground = color->pixel;
+ if (stipple != None) {
+ gcValues.stipple = stipple;
+ gcValues.fill_style = FillStippled;
+ mask = GCForeground|GCStipple|GCFillStyle;
+ } else {
+ mask = GCForeground;
+ }
+#ifdef MAC_OSX_TK
+ /*
+ * Mac OS X CG drawing needs access to the outline linewidth even for
+ * fills (as linewidth controls antialiasing).
+ */
+ gcValues.line_width = rectOvalPtr->outline.gc != NULL ?
+ rectOvalPtr->outline.gc->line_width : 0;
+ mask |= GCLineWidth;
+#endif
+ newGC = Tk_GetGC(tkwin, mask, &gcValues);
+ }
+ if (rectOvalPtr->fillGC != NULL) {
+ Tk_FreeGC(Tk_Display(tkwin), rectOvalPtr->fillGC);
+ }
+ rectOvalPtr->fillGC = newGC;
+
+ tsoffset = &rectOvalPtr->tsoffset;
+ flags = tsoffset->flags;
+ if (flags & TK_OFFSET_LEFT) {
+ tsoffset->xoffset = (int) (rectOvalPtr->bbox[0] + 0.5);
+ } else if (flags & TK_OFFSET_CENTER) {
+ tsoffset->xoffset = (int)
+ ((rectOvalPtr->bbox[0]+rectOvalPtr->bbox[2]+1)/2);
+ } else if (flags & TK_OFFSET_RIGHT) {
+ tsoffset->xoffset = (int) (rectOvalPtr->bbox[2] + 0.5);
+ }
+ if (flags & TK_OFFSET_TOP) {
+ tsoffset->yoffset = (int) (rectOvalPtr->bbox[1] + 0.5);
+ } else if (flags & TK_OFFSET_MIDDLE) {
+ tsoffset->yoffset = (int)
+ ((rectOvalPtr->bbox[1]+rectOvalPtr->bbox[3]+1)/2);
+ } else if (flags & TK_OFFSET_BOTTOM) {
+ tsoffset->yoffset = (int) (rectOvalPtr->bbox[3] + 0.5);
+ }
+
+ ComputeRectOvalBbox(canvas, rectOvalPtr);
+
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DeleteRectOval --
+ *
+ * This function is called to clean up the data structure associated with
+ * a rectangle or oval item.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Resources associated with itemPtr are released.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+DeleteRectOval(
+ Tk_Canvas canvas, /* Info about overall widget. */
+ Tk_Item *itemPtr, /* Item that is being deleted. */
+ Display *display) /* Display containing window for canvas. */
+{
+ RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
+
+ Tk_DeleteOutline(display, &(rectOvalPtr->outline));
+ if (rectOvalPtr->fillColor != NULL) {
+ Tk_FreeColor(rectOvalPtr->fillColor);
+ }
+ if (rectOvalPtr->activeFillColor != NULL) {
+ Tk_FreeColor(rectOvalPtr->activeFillColor);
+ }
+ if (rectOvalPtr->disabledFillColor != NULL) {
+ Tk_FreeColor(rectOvalPtr->disabledFillColor);
+ }
+ if (rectOvalPtr->fillStipple != None) {
+ Tk_FreeBitmap(display, rectOvalPtr->fillStipple);
+ }
+ if (rectOvalPtr->activeFillStipple != None) {
+ Tk_FreeBitmap(display, rectOvalPtr->activeFillStipple);
+ }
+ if (rectOvalPtr->disabledFillStipple != None) {
+ Tk_FreeBitmap(display, rectOvalPtr->disabledFillStipple);
+ }
+ if (rectOvalPtr->fillGC != NULL) {
+ Tk_FreeGC(display, rectOvalPtr->fillGC);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ComputeRectOvalBbox --
+ *
+ * This function is invoked to compute the bounding box of all the pixels
+ * that may be drawn as part of a rectangle or oval.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The fields x1, y1, x2, and y2 are updated in the header for itemPtr.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static void
+ComputeRectOvalBbox(
+ Tk_Canvas canvas, /* Canvas that contains item. */
+ RectOvalItem *rectOvalPtr) /* Item whose bbox is to be recomputed. */
+{
+ int bloat, tmp;
+ double dtmp, width;
+ Tk_State state = rectOvalPtr->header.state;
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+
+ width = rectOvalPtr->outline.width;
+ if (state == TK_STATE_HIDDEN) {
+ rectOvalPtr->header.x1 = rectOvalPtr->header.y1 =
+ rectOvalPtr->header.x2 = rectOvalPtr->header.y2 = -1;
+ return;
+ }
+ if (Canvas(canvas)->currentItemPtr == (Tk_Item *) rectOvalPtr) {
+ if (rectOvalPtr->outline.activeWidth>width) {
+ width = rectOvalPtr->outline.activeWidth;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (rectOvalPtr->outline.disabledWidth>0) {
+ width = rectOvalPtr->outline.disabledWidth;
+ }
+ }
+
+ /*
+ * Make sure that the first coordinates are the lowest ones.
+ */
+
+ if (rectOvalPtr->bbox[1] > rectOvalPtr->bbox[3]) {
+ double tmpY = rectOvalPtr->bbox[3];
+
+ rectOvalPtr->bbox[3] = rectOvalPtr->bbox[1];
+ rectOvalPtr->bbox[1] = tmpY;
+ }
+ if (rectOvalPtr->bbox[0] > rectOvalPtr->bbox[2]) {
+ double tmpX = rectOvalPtr->bbox[2];
+
+ rectOvalPtr->bbox[2] = rectOvalPtr->bbox[0];
+ rectOvalPtr->bbox[0] = tmpX;
+ }
+
+ if (rectOvalPtr->outline.gc == NULL) {
+ /*
+ * The Win32 switch was added for 8.3 to solve a problem with ovals
+ * leaving traces on bottom and right of 1 pixel. This may not be the
+ * correct place to solve it, but it works.
+ */
+
+#ifdef _WIN32
+ bloat = 1;
+#else
+ bloat = 0;
+#endif /* _WIN32 */
+ } else {
+#ifdef MAC_OSX_TK
+ /*
+ * Mac OS X CoreGraphics needs correct rounding here otherwise it will
+ * draw outside the bounding box. Probably correct on other platforms
+ * as well?
+ */
+
+ bloat = (int) (width+1.5)/2;
+#else
+ bloat = (int) (width+1)/2;
+#endif /* MAC_OSX_TK */
+ }
+
+ /*
+ * Special note: the rectangle is always drawn at least 1x1 in size, so
+ * round up the upper coordinates to be at least 1 unit greater than the
+ * lower ones.
+ */
+
+ tmp = (int) ((rectOvalPtr->bbox[0] >= 0) ? rectOvalPtr->bbox[0] + .5
+ : rectOvalPtr->bbox[0] - .5);
+ rectOvalPtr->header.x1 = tmp - bloat;
+ tmp = (int) ((rectOvalPtr->bbox[1] >= 0) ? rectOvalPtr->bbox[1] + .5
+ : rectOvalPtr->bbox[1] - .5);
+ rectOvalPtr->header.y1 = tmp - bloat;
+ dtmp = rectOvalPtr->bbox[2];
+ if (dtmp < (rectOvalPtr->bbox[0] + 1)) {
+ dtmp = rectOvalPtr->bbox[0] + 1;
+ }
+ tmp = (int) ((dtmp >= 0) ? dtmp + .5 : dtmp - .5);
+ rectOvalPtr->header.x2 = tmp + bloat;
+ dtmp = rectOvalPtr->bbox[3];
+ if (dtmp < (rectOvalPtr->bbox[1] + 1)) {
+ dtmp = rectOvalPtr->bbox[1] + 1;
+ }
+ tmp = (int) ((dtmp >= 0) ? dtmp + .5 : dtmp - .5);
+ rectOvalPtr->header.y2 = tmp + bloat;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DisplayRectOval --
+ *
+ * This function is invoked to draw a rectangle or oval item in a given
+ * drawable.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * ItemPtr is drawn in drawable using the transformation information in
+ * canvas.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+DisplayRectOval(
+ Tk_Canvas canvas, /* Canvas that contains item. */
+ Tk_Item *itemPtr, /* Item to be displayed. */
+ Display *display, /* Display on which to draw item. */
+ Drawable drawable, /* Pixmap or window in which to draw item. */
+ int x, int y, int width, int height)
+ /* Describes region of canvas that must be
+ * redisplayed (not used). */
+{
+ RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
+ short x1, y1, x2, y2;
+ Pixmap fillStipple;
+ Tk_State state = itemPtr->state;
+
+ /*
+ * Compute the screen coordinates of the bounding box for the item. Make
+ * sure that the bbox is at least one pixel large, since some X servers
+ * will die if it isn't.
+ */
+
+ Tk_CanvasDrawableCoords(canvas, rectOvalPtr->bbox[0],rectOvalPtr->bbox[1],
+ &x1, &y1);
+ Tk_CanvasDrawableCoords(canvas, rectOvalPtr->bbox[2],rectOvalPtr->bbox[3],
+ &x2, &y2);
+ if (x2 == x1) {
+
+ /*
+ * The width of the bounding box corresponds to less than one pixel
+ * on screen. Adjustment is needed to avoid drawing attempts with zero
+ * width items (which would draw nothing). The bounding box spans
+ * either 1 or 2 pixels. Select which pixel will be drawn.
+ */
+
+ short ix1 = (short) (rectOvalPtr->bbox[0]);
+ short ix2 = (short) (rectOvalPtr->bbox[2]);
+
+ if (ix1 == ix2) {
+
+ /*
+ * x1 and x2 are "within the same pixel". Use this pixel.
+ * Note: the degenerated case (bbox[0]==bbox[2]) of a completely
+ * flat box results in arbitrary selection of the pixel at the
+ * right (with positive coordinate) or left (with negative
+ * coordinate) of the box. There is no "best choice" here.
+ */
+
+ if (ix1 > 0) {
+ x2 += 1;
+ } else {
+ x1 -= 1;
+ }
+ } else {
+
+ /*
+ * (x1,x2) span two pixels. Select the one with the larger
+ * covered "area".
+ */
+
+ if (ix1 > 0) {
+ if ((rectOvalPtr->bbox[2] - ix2) > (ix2 - rectOvalPtr->bbox[0])) {
+ x2 += 1;
+ } else {
+ x1 -= 1;
+ }
+ } else {
+ if ((rectOvalPtr->bbox[2] - ix1) > (ix1 - rectOvalPtr->bbox[0])) {
+ x2 += 1;
+ } else {
+ x1 -= 1;
+ }
+ }
+ }
+ }
+ if (y2 == y1) {
+
+ /*
+ * The height of the bounding box corresponds to less than one pixel
+ * on screen. Adjustment is needed to avoid drawing attempts with zero
+ * height items (which would draw nothing). The bounding box spans
+ * either 1 or 2 pixels. Select which pixel will be drawn.
+ */
+
+ short iy1 = (short) (rectOvalPtr->bbox[1]);
+ short iy2 = (short) (rectOvalPtr->bbox[3]);
+
+ if (iy1 == iy2) {
+
+ /*
+ * y1 and y2 are "within the same pixel". Use this pixel.
+ * Note: the degenerated case (bbox[1]==bbox[3]) of a completely
+ * flat box results in arbitrary selection of the pixel below
+ * (with positive coordinate) or above (with negative coordinate)
+ * the box. There is no "best choice" here.
+ */
+
+ if (iy1 > 0) {
+ y2 += 1;
+ } else {
+ y1 -= 1;
+ }
+ } else {
+
+ /*
+ * (y1,y2) span two pixels. Select the one with the larger
+ * covered "area".
+ */
+
+ if (iy1 > 0) {
+ if ((rectOvalPtr->bbox[3] - iy2) > (iy2 - rectOvalPtr->bbox[1])) {
+ y2 += 1;
+ } else {
+ y1 -= 1;
+ }
+ } else {
+ if ((rectOvalPtr->bbox[3] - iy1) > (iy1 - rectOvalPtr->bbox[1])) {
+ y2 += 1;
+ } else {
+ y1 -= 1;
+ }
+ }
+ }
+ }
+
+ /*
+ * Display filled part first (if wanted), then outline. If we're
+ * stippling, then modify the stipple offset in the GC. Be sure to reset
+ * the offset when done, since the GC is supposed to be read-only.
+ */
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+ fillStipple = rectOvalPtr->fillStipple;
+ if (Canvas(canvas)->currentItemPtr == (Tk_Item *) rectOvalPtr) {
+ if (rectOvalPtr->activeFillStipple != None) {
+ fillStipple = rectOvalPtr->activeFillStipple;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (rectOvalPtr->disabledFillStipple != None) {
+ fillStipple = rectOvalPtr->disabledFillStipple;
+ }
+ }
+
+ if (rectOvalPtr->fillGC != NULL) {
+ if (fillStipple != None) {
+ Tk_TSOffset *tsoffset;
+ int w = 0, h = 0;
+
+ tsoffset = &rectOvalPtr->tsoffset;
+ if (tsoffset) {
+ int flags = tsoffset->flags;
+
+ if (flags & (TK_OFFSET_CENTER|TK_OFFSET_MIDDLE)) {
+ Tk_SizeOfBitmap(display, fillStipple, &w, &h);
+ if (flags & TK_OFFSET_CENTER) {
+ w /= 2;
+ } else {
+ w = 0;
+ }
+ if (flags & TK_OFFSET_MIDDLE) {
+ h /= 2;
+ } else {
+ h = 0;
+ }
+ }
+ tsoffset->xoffset -= w;
+ tsoffset->yoffset -= h;
+ }
+ Tk_CanvasSetOffset(canvas, rectOvalPtr->fillGC, tsoffset);
+ if (tsoffset) {
+ tsoffset->xoffset += w;
+ tsoffset->yoffset += h;
+ }
+ }
+ if (rectOvalPtr->header.typePtr == &tkRectangleType) {
+ XFillRectangle(display, drawable, rectOvalPtr->fillGC,
+ x1, y1, (unsigned int) (x2-x1), (unsigned int) (y2-y1));
+ } else {
+ XFillArc(display, drawable, rectOvalPtr->fillGC,
+ x1, y1, (unsigned) (x2-x1), (unsigned) (y2-y1),
+ 0, 360*64);
+ }
+ if (fillStipple != None) {
+ XSetTSOrigin(display, rectOvalPtr->fillGC, 0, 0);
+ }
+ }
+
+ if (rectOvalPtr->outline.gc != NULL) {
+ Tk_ChangeOutlineGC(canvas, itemPtr, &(rectOvalPtr->outline));
+ if (rectOvalPtr->header.typePtr == &tkRectangleType) {
+ XDrawRectangle(display, drawable, rectOvalPtr->outline.gc,
+ x1, y1, (unsigned) (x2-x1), (unsigned) (y2-y1));
+ } else {
+ XDrawArc(display, drawable, rectOvalPtr->outline.gc,
+ x1, y1, (unsigned) (x2-x1), (unsigned) (y2-y1), 0, 360*64);
+ }
+ Tk_ResetOutlineGC(canvas, itemPtr, &(rectOvalPtr->outline));
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * RectToPoint --
+ *
+ * Computes the distance from a given point to a given rectangle, in
+ * canvas units.
+ *
+ * Results:
+ * The return value is 0 if the point whose x and y coordinates are
+ * coordPtr[0] and coordPtr[1] is inside the rectangle. If the point
+ * isn't inside the rectangle then the return value is the distance from
+ * the point to the rectangle. If itemPtr is filled, then anywhere in the
+ * interior is considered "inside"; if itemPtr isn't filled, then
+ * "inside" means only the area occupied by the outline.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static double
+RectToPoint(
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item to check against point. */
+ double *pointPtr) /* Pointer to x and y coordinates. */
+{
+ RectOvalItem *rectPtr = (RectOvalItem *) itemPtr;
+ double xDiff, yDiff, x1, y1, x2, y2, inc, tmp;
+ double width;
+ Tk_State state = itemPtr->state;
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+
+ width = rectPtr->outline.width;
+ if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (rectPtr->outline.activeWidth>width) {
+ width = rectPtr->outline.activeWidth;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (rectPtr->outline.disabledWidth>0) {
+ width = rectPtr->outline.disabledWidth;
+ }
+ }
+
+ /*
+ * Generate a new larger rectangle that includes the border width, if
+ * there is one.
+ */
+
+ x1 = rectPtr->bbox[0];
+ y1 = rectPtr->bbox[1];
+ x2 = rectPtr->bbox[2];
+ y2 = rectPtr->bbox[3];
+ if (rectPtr->outline.gc != NULL) {
+ inc = width/2.0;
+ x1 -= inc;
+ y1 -= inc;
+ x2 += inc;
+ y2 += inc;
+ }
+
+ /*
+ * If the point is inside the rectangle, handle specially: distance is 0
+ * if rectangle is filled, otherwise compute distance to nearest edge of
+ * rectangle and subtract width of edge.
+ */
+
+ if ((pointPtr[0] >= x1) && (pointPtr[0] < x2)
+ && (pointPtr[1] >= y1) && (pointPtr[1] < y2)) {
+ if ((rectPtr->fillGC != NULL) || (rectPtr->outline.gc == NULL)) {
+ return 0.0;
+ }
+ xDiff = pointPtr[0] - x1;
+ tmp = x2 - pointPtr[0];
+ if (tmp < xDiff) {
+ xDiff = tmp;
+ }
+ yDiff = pointPtr[1] - y1;
+ tmp = y2 - pointPtr[1];
+ if (tmp < yDiff) {
+ yDiff = tmp;
+ }
+ if (yDiff < xDiff) {
+ xDiff = yDiff;
+ }
+ xDiff -= width;
+ if (xDiff < 0.0) {
+ return 0.0;
+ }
+ return xDiff;
+ }
+
+ /*
+ * Point is outside rectangle.
+ */
+
+ if (pointPtr[0] < x1) {
+ xDiff = x1 - pointPtr[0];
+ } else if (pointPtr[0] > x2) {
+ xDiff = pointPtr[0] - x2;
+ } else {
+ xDiff = 0;
+ }
+
+ if (pointPtr[1] < y1) {
+ yDiff = y1 - pointPtr[1];
+ } else if (pointPtr[1] > y2) {
+ yDiff = pointPtr[1] - y2;
+ } else {
+ yDiff = 0;
+ }
+
+ return hypot(xDiff, yDiff);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * OvalToPoint --
+ *
+ * Computes the distance from a given point to a given oval, in canvas
+ * units.
+ *
+ * Results:
+ * The return value is 0 if the point whose x and y coordinates are
+ * coordPtr[0] and coordPtr[1] is inside the oval. If the point isn't
+ * inside the oval then the return value is the distance from the point
+ * to the oval. If itemPtr is filled, then anywhere in the interior is
+ * considered "inside"; if itemPtr isn't filled, then "inside" means only
+ * the area occupied by the outline.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static double
+OvalToPoint(
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item to check against point. */
+ double *pointPtr) /* Pointer to x and y coordinates. */
+{
+ RectOvalItem *ovalPtr = (RectOvalItem *) itemPtr;
+ double width;
+ int filled;
+ Tk_State state = itemPtr->state;
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+
+ width = (double) ovalPtr->outline.width;
+ if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (ovalPtr->outline.activeWidth>width) {
+ width = (double) ovalPtr->outline.activeWidth;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (ovalPtr->outline.disabledWidth>0) {
+ width = (double) ovalPtr->outline.disabledWidth;
+ }
+ }
+
+
+ filled = ovalPtr->fillGC != NULL;
+ if (ovalPtr->outline.gc == NULL) {
+ width = 0.0;
+ filled = 1;
+ }
+ return TkOvalToPoint(ovalPtr->bbox, width, filled, pointPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * RectToArea --
+ *
+ * This function is called to determine whether an item lies entirely
+ * inside, entirely outside, or overlapping a given rectangle.
+ *
+ * Results:
+ * -1 is returned if the item is entirely outside the area given by
+ * rectPtr, 0 if it overlaps, and 1 if it is entirely inside the given
+ * area.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+RectToArea(
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item to check against rectangle. */
+ double *areaPtr) /* Pointer to array of four coordinates (x1,
+ * y1, x2, y2) describing rectangular area. */
+{
+ RectOvalItem *rectPtr = (RectOvalItem *) itemPtr;
+ double halfWidth;
+ double width;
+ Tk_State state = itemPtr->state;
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+
+ width = rectPtr->outline.width;
+ if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (rectPtr->outline.activeWidth > width) {
+ width = rectPtr->outline.activeWidth;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (rectPtr->outline.disabledWidth > 0) {
+ width = rectPtr->outline.disabledWidth;
+ }
+ }
+
+ halfWidth = width/2.0;
+ if (rectPtr->outline.gc == NULL) {
+ halfWidth = 0.0;
+ }
+
+ if ((areaPtr[2] <= (rectPtr->bbox[0] - halfWidth))
+ || (areaPtr[0] >= (rectPtr->bbox[2] + halfWidth))
+ || (areaPtr[3] <= (rectPtr->bbox[1] - halfWidth))
+ || (areaPtr[1] >= (rectPtr->bbox[3] + halfWidth))) {
+ return -1;
+ }
+ if ((rectPtr->fillGC == NULL) && (rectPtr->outline.gc != NULL)
+ && (areaPtr[0] >= (rectPtr->bbox[0] + halfWidth))
+ && (areaPtr[1] >= (rectPtr->bbox[1] + halfWidth))
+ && (areaPtr[2] <= (rectPtr->bbox[2] - halfWidth))
+ && (areaPtr[3] <= (rectPtr->bbox[3] - halfWidth))) {
+ return -1;
+ }
+ if ((areaPtr[0] <= (rectPtr->bbox[0] - halfWidth))
+ && (areaPtr[1] <= (rectPtr->bbox[1] - halfWidth))
+ && (areaPtr[2] >= (rectPtr->bbox[2] + halfWidth))
+ && (areaPtr[3] >= (rectPtr->bbox[3] + halfWidth))) {
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * OvalToArea --
+ *
+ * This function is called to determine whether an item lies entirely
+ * inside, entirely outside, or overlapping a given rectangular area.
+ *
+ * Results:
+ * -1 is returned if the item is entirely outside the area given by
+ * rectPtr, 0 if it overlaps, and 1 if it is entirely inside the given
+ * area.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+OvalToArea(
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item to check against oval. */
+ double *areaPtr) /* Pointer to array of four coordinates (x1,
+ * y1, x2, y2) describing rectangular area. */
+{
+ RectOvalItem *ovalPtr = (RectOvalItem *) itemPtr;
+ double oval[4], halfWidth, width;
+ int result;
+ Tk_State state = itemPtr->state;
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+
+ width = ovalPtr->outline.width;
+ if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (ovalPtr->outline.activeWidth > width) {
+ width = ovalPtr->outline.activeWidth;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (ovalPtr->outline.disabledWidth > 0) {
+ width = ovalPtr->outline.disabledWidth;
+ }
+ }
+
+ /*
+ * Expand the oval to include the width of the outline, if any.
+ */
+
+ halfWidth = width/2.0;
+ if (ovalPtr->outline.gc == NULL) {
+ halfWidth = 0.0;
+ }
+ oval[0] = ovalPtr->bbox[0] - halfWidth;
+ oval[1] = ovalPtr->bbox[1] - halfWidth;
+ oval[2] = ovalPtr->bbox[2] + halfWidth;
+ oval[3] = ovalPtr->bbox[3] + halfWidth;
+
+ result = TkOvalToArea(oval, areaPtr);
+
+ /*
+ * If the rectangle appears to overlap the oval and the oval isn't filled,
+ * do one more check to see if perhaps all four of the rectangle's corners
+ * are totally inside the oval's unfilled center, in which case we should
+ * return "outside".
+ */
+
+ if ((result == 0) && (ovalPtr->outline.gc != NULL)
+ && (ovalPtr->fillGC == NULL)) {
+ double centerX, centerY, height;
+ double xDelta1, yDelta1, xDelta2, yDelta2;
+
+ centerX = (ovalPtr->bbox[0] + ovalPtr->bbox[2])/2.0;
+ centerY = (ovalPtr->bbox[1] + ovalPtr->bbox[3])/2.0;
+ width = (ovalPtr->bbox[2] - ovalPtr->bbox[0])/2.0 - halfWidth;
+ height = (ovalPtr->bbox[3] - ovalPtr->bbox[1])/2.0 - halfWidth;
+ xDelta1 = (areaPtr[0] - centerX)/width;
+ xDelta1 *= xDelta1;
+ yDelta1 = (areaPtr[1] - centerY)/height;
+ yDelta1 *= yDelta1;
+ xDelta2 = (areaPtr[2] - centerX)/width;
+ xDelta2 *= xDelta2;
+ yDelta2 = (areaPtr[3] - centerY)/height;
+ yDelta2 *= yDelta2;
+ if (((xDelta1 + yDelta1) < 1.0)
+ && ((xDelta1 + yDelta2) < 1.0)
+ && ((xDelta2 + yDelta1) < 1.0)
+ && ((xDelta2 + yDelta2) < 1.0)) {
+ return -1;
+ }
+ }
+ return result;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ScaleRectOval --
+ *
+ * This function is invoked to rescale a rectangle or oval item.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The rectangle or oval referred to by itemPtr is rescaled so that the
+ * following transformation is applied to all point coordinates:
+ * x' = originX + scaleX*(x-originX)
+ * y' = originY + scaleY*(y-originY)
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ScaleRectOval(
+ Tk_Canvas canvas, /* Canvas containing rectangle. */
+ Tk_Item *itemPtr, /* Rectangle to be scaled. */
+ double originX, double originY,
+ /* Origin about which to scale rect. */
+ double scaleX, /* Amount to scale in X direction. */
+ double scaleY) /* Amount to scale in Y direction. */
+{
+ RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
+
+ rectOvalPtr->bbox[0] = originX + scaleX*(rectOvalPtr->bbox[0] - originX);
+ rectOvalPtr->bbox[1] = originY + scaleY*(rectOvalPtr->bbox[1] - originY);
+ rectOvalPtr->bbox[2] = originX + scaleX*(rectOvalPtr->bbox[2] - originX);
+ rectOvalPtr->bbox[3] = originY + scaleY*(rectOvalPtr->bbox[3] - originY);
+ ComputeRectOvalBbox(canvas, rectOvalPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TranslateRectOval --
+ *
+ * This function is called to move a rectangle or oval by a given amount.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The position of the rectangle or oval is offset by (xDelta, yDelta),
+ * and the bounding box is updated in the generic part of the item
+ * structure.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+TranslateRectOval(
+ Tk_Canvas canvas, /* Canvas containing item. */
+ Tk_Item *itemPtr, /* Item that is being moved. */
+ double deltaX, double deltaY)
+ /* Amount by which item is to be moved. */
+{
+ RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
+
+ rectOvalPtr->bbox[0] += deltaX;
+ rectOvalPtr->bbox[1] += deltaY;
+ rectOvalPtr->bbox[2] += deltaX;
+ rectOvalPtr->bbox[3] += deltaY;
+ ComputeRectOvalBbox(canvas, rectOvalPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * RectOvalToPostscript --
+ *
+ * This function is called to generate Postscript for rectangle and oval
+ * items.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If an error occurs in
+ * generating Postscript then an error message is left in the interp's
+ * result, replacing whatever used to be there. If no error occurs, then
+ * Postscript for the rectangle is appended to the result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+RectOvalToPostscript(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Tk_Canvas canvas, /* Information about overall canvas. */
+ Tk_Item *itemPtr, /* Item for which Postscript is wanted. */
+ int prepass) /* 1 means this is a prepass to collect font
+ * information; 0 means final Postscript is
+ * being created. */
+{
+ Tcl_Obj *pathObj, *psObj;
+ RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
+ double y1, y2;
+ XColor *color;
+ XColor *fillColor;
+ Pixmap fillStipple;
+ Tk_State state = itemPtr->state;
+ Tcl_InterpState interpState;
+
+ y1 = Tk_CanvasPsY(canvas, rectOvalPtr->bbox[1]);
+ y2 = Tk_CanvasPsY(canvas, rectOvalPtr->bbox[3]);
+
+ /*
+ * Generate a string that creates a path for the rectangle or oval. This
+ * is the only part of the function's code that is type-specific.
+ */
+
+ if (rectOvalPtr->header.typePtr == &tkRectangleType) {
+ pathObj = Tcl_ObjPrintf(
+ "%.15g %.15g moveto "
+ "%.15g 0 rlineto "
+ "0 %.15g rlineto "
+ "%.15g 0 rlineto "
+ "closepath\n",
+ rectOvalPtr->bbox[0], y1,
+ rectOvalPtr->bbox[2]-rectOvalPtr->bbox[0],
+ y2-y1,
+ rectOvalPtr->bbox[0]-rectOvalPtr->bbox[2]);
+ } else {
+ pathObj = Tcl_ObjPrintf(
+ "matrix currentmatrix\n"
+ "%.15g %.15g translate "
+ "%.15g %.15g scale "
+ "1 0 moveto 0 0 1 0 360 arc\n"
+ "setmatrix\n",
+ (rectOvalPtr->bbox[0] + rectOvalPtr->bbox[2])/2, (y1 + y2)/2,
+ (rectOvalPtr->bbox[2] - rectOvalPtr->bbox[0])/2, (y1 - y2)/2);
+ }
+
+ if (state == TK_STATE_NULL) {
+ state = Canvas(canvas)->canvas_state;
+ }
+ color = rectOvalPtr->outline.color;
+ fillColor = rectOvalPtr->fillColor;
+ fillStipple = rectOvalPtr->fillStipple;
+ if (Canvas(canvas)->currentItemPtr == itemPtr) {
+ if (rectOvalPtr->outline.activeColor!=NULL) {
+ color = rectOvalPtr->outline.activeColor;
+ }
+ if (rectOvalPtr->activeFillColor!=NULL) {
+ fillColor = rectOvalPtr->activeFillColor;
+ }
+ if (rectOvalPtr->activeFillStipple!=None) {
+ fillStipple = rectOvalPtr->activeFillStipple;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (rectOvalPtr->outline.disabledColor!=NULL) {
+ color = rectOvalPtr->outline.disabledColor;
+ }
+ if (rectOvalPtr->disabledFillColor!=NULL) {
+ fillColor = rectOvalPtr->disabledFillColor;
+ }
+ if (rectOvalPtr->disabledFillStipple!=None) {
+ fillStipple = rectOvalPtr->disabledFillStipple;
+ }
+ }
+
+ /*
+ * Make our working space.
+ */
+
+ psObj = Tcl_NewObj();
+ interpState = Tcl_SaveInterpState(interp, TCL_OK);
+
+ /*
+ * First draw the filled area of the rectangle.
+ */
+
+ if (fillColor != NULL) {
+ Tcl_AppendObjToObj(psObj, pathObj);
+
+ Tcl_ResetResult(interp);
+ if (Tk_CanvasPsColor(interp, canvas, fillColor) != TCL_OK) {
+ goto error;
+ }
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+
+ if (fillStipple != None) {
+ Tcl_AppendToObj(psObj, "clip ", -1);
+
+ Tcl_ResetResult(interp);
+ if (Tk_CanvasPsStipple(interp, canvas, fillStipple) != TCL_OK) {
+ goto error;
+ }
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+ if (color != NULL) {
+ Tcl_AppendToObj(psObj, "grestore gsave\n", -1);
+ }
+ } else {
+ Tcl_AppendToObj(psObj, "fill\n", -1);
+ }
+ }
+
+ /*
+ * Now draw the outline, if there is one.
+ */
+
+ if (color != NULL) {
+ Tcl_AppendObjToObj(psObj, pathObj);
+ Tcl_AppendToObj(psObj, "0 setlinejoin 2 setlinecap\n", -1);
+
+ Tcl_ResetResult(interp);
+ if (Tk_CanvasPsOutline(canvas, itemPtr,
+ &rectOvalPtr->outline)!= TCL_OK) {
+ goto error;
+ }
+ Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
+ }
+
+ /*
+ * Plug the accumulated postscript back into the result.
+ */
+
+ (void) Tcl_RestoreInterpState(interp, interpState);
+ Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj);
+ Tcl_DecrRefCount(psObj);
+ Tcl_DecrRefCount(pathObj);
+ return TCL_OK;
+
+ error:
+ Tcl_DiscardInterpState(interpState);
+ Tcl_DecrRefCount(psObj);
+ Tcl_DecrRefCount(pathObj);
+ return TCL_ERROR;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkScale.c b/tk8.6/generic/tkScale.c
new file mode 100644
index 0000000..5957b00
--- /dev/null
+++ b/tk8.6/generic/tkScale.c
@@ -0,0 +1,1627 @@
+/*
+ * tkScale.c --
+ *
+ * This module implements a scale widgets for the Tk toolkit. A scale
+ * displays a slider that can be adjusted to change a value; it also
+ * displays numeric labels and a textual label, if desired.
+ *
+ * The modifications to use floating-point values are based on an
+ * implementation by Paul Mackerras. The -variable option is due to
+ * Henning Schulzrinne. All of these are used with permission.
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1997 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.
+ */
+
+#include "default.h"
+#include "tkInt.h"
+#include "tkScale.h"
+
+#if defined(_WIN32)
+#define snprintf _snprintf
+#endif
+
+/*
+ * The following table defines the legal values for the -orient option. It is
+ * used together with the "enum orient" declaration in tkScale.h.
+ */
+
+static const char *const orientStrings[] = {
+ "horizontal", "vertical", NULL
+};
+
+/*
+ * The following table defines the legal values for the -state option. It is
+ * used together with the "enum state" declaration in tkScale.h.
+ */
+
+static const char *const stateStrings[] = {
+ "active", "disabled", "normal", NULL
+};
+
+static const Tk_OptionSpec optionSpecs[] = {
+ {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",
+ DEF_SCALE_ACTIVE_BG_COLOR, -1, Tk_Offset(TkScale, activeBorder),
+ 0, DEF_SCALE_ACTIVE_BG_MONO, 0},
+ {TK_OPTION_BORDER, "-background", "background", "Background",
+ DEF_SCALE_BG_COLOR, -1, Tk_Offset(TkScale, bgBorder),
+ 0, DEF_SCALE_BG_MONO, 0},
+ {TK_OPTION_DOUBLE, "-bigincrement", "bigIncrement", "BigIncrement",
+ DEF_SCALE_BIG_INCREMENT, -1, Tk_Offset(TkScale, bigIncrement),
+ 0, 0, 0},
+ {TK_OPTION_SYNONYM, "-bd", NULL, NULL,
+ NULL, 0, -1, 0, "-borderwidth", 0},
+ {TK_OPTION_SYNONYM, "-bg", NULL, NULL,
+ NULL, 0, -1, 0, "-background", 0},
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ DEF_SCALE_BORDER_WIDTH, -1, Tk_Offset(TkScale, borderWidth),
+ 0, 0, 0},
+ {TK_OPTION_STRING, "-command", "command", "Command",
+ DEF_SCALE_COMMAND, -1, Tk_Offset(TkScale, command),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
+ DEF_SCALE_CURSOR, -1, Tk_Offset(TkScale, cursor),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_INT, "-digits", "digits", "Digits",
+ DEF_SCALE_DIGITS, -1, Tk_Offset(TkScale, digits),
+ 0, 0, 0},
+ {TK_OPTION_SYNONYM, "-fg", "foreground", NULL,
+ NULL, 0, -1, 0, "-foreground", 0},
+ {TK_OPTION_FONT, "-font", "font", "Font",
+ DEF_SCALE_FONT, -1, Tk_Offset(TkScale, tkfont), 0, 0, 0},
+ {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
+ DEF_SCALE_FG_COLOR, -1, Tk_Offset(TkScale, textColorPtr), 0,
+ (ClientData) DEF_SCALE_FG_MONO, 0},
+ {TK_OPTION_DOUBLE, "-from", "from", "From", DEF_SCALE_FROM, -1,
+ Tk_Offset(TkScale, fromValue), 0, 0, 0},
+ {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground",
+ "HighlightBackground", DEF_SCALE_HIGHLIGHT_BG_COLOR,
+ -1, Tk_Offset(TkScale, highlightBorder),
+ 0, DEF_SCALE_HIGHLIGHT_BG_MONO, 0},
+ {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
+ DEF_SCALE_HIGHLIGHT, -1, Tk_Offset(TkScale, highlightColorPtr),
+ 0, 0, 0},
+ {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
+ "HighlightThickness", DEF_SCALE_HIGHLIGHT_WIDTH, -1,
+ Tk_Offset(TkScale, highlightWidth), 0, 0, 0},
+ {TK_OPTION_STRING, "-label", "label", "Label",
+ DEF_SCALE_LABEL, -1, Tk_Offset(TkScale, label),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-length", "length", "Length",
+ DEF_SCALE_LENGTH, -1, Tk_Offset(TkScale, length), 0, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient",
+ DEF_SCALE_ORIENT, -1, Tk_Offset(TkScale, orient),
+ 0, orientStrings, 0},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ DEF_SCALE_RELIEF, -1, Tk_Offset(TkScale, relief), 0, 0, 0},
+ {TK_OPTION_INT, "-repeatdelay", "repeatDelay", "RepeatDelay",
+ DEF_SCALE_REPEAT_DELAY, -1, Tk_Offset(TkScale, repeatDelay),
+ 0, 0, 0},
+ {TK_OPTION_INT, "-repeatinterval", "repeatInterval", "RepeatInterval",
+ DEF_SCALE_REPEAT_INTERVAL, -1, Tk_Offset(TkScale, repeatInterval),
+ 0, 0, 0},
+ {TK_OPTION_DOUBLE, "-resolution", "resolution", "Resolution",
+ DEF_SCALE_RESOLUTION, -1, Tk_Offset(TkScale, resolution),
+ 0, 0, 0},
+ {TK_OPTION_BOOLEAN, "-showvalue", "showValue", "ShowValue",
+ DEF_SCALE_SHOW_VALUE, -1, Tk_Offset(TkScale, showValue),
+ 0, 0, 0},
+ {TK_OPTION_PIXELS, "-sliderlength", "sliderLength", "SliderLength",
+ DEF_SCALE_SLIDER_LENGTH, -1, Tk_Offset(TkScale, sliderLength),
+ 0, 0, 0},
+ {TK_OPTION_RELIEF, "-sliderrelief", "sliderRelief", "SliderRelief",
+ DEF_SCALE_SLIDER_RELIEF, -1, Tk_Offset(TkScale, sliderRelief),
+ 0, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-state", "state", "State",
+ DEF_SCALE_STATE, -1, Tk_Offset(TkScale, state),
+ 0, stateStrings, 0},
+ {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
+ DEF_SCALE_TAKE_FOCUS, Tk_Offset(TkScale, takeFocusPtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_DOUBLE, "-tickinterval", "tickInterval", "TickInterval",
+ DEF_SCALE_TICK_INTERVAL, -1, Tk_Offset(TkScale, tickInterval),
+ 0, 0, 0},
+ {TK_OPTION_DOUBLE, "-to", "to", "To",
+ DEF_SCALE_TO, -1, Tk_Offset(TkScale, toValue), 0, 0, 0},
+ {TK_OPTION_COLOR, "-troughcolor", "troughColor", "Background",
+ DEF_SCALE_TROUGH_COLOR, -1, Tk_Offset(TkScale, troughColorPtr),
+ 0, DEF_SCALE_TROUGH_MONO, 0},
+ {TK_OPTION_STRING, "-variable", "variable", "Variable",
+ DEF_SCALE_VARIABLE, Tk_Offset(TkScale, varNamePtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-width", "width", "Width",
+ DEF_SCALE_WIDTH, -1, Tk_Offset(TkScale, width), 0, 0, 0},
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0}
+};
+
+/*
+ * The following tables define the scale widget commands and map the indexes
+ * into the string tables into a single enumerated type used to dispatch the
+ * scale widget command.
+ */
+
+static const char *const commandNames[] = {
+ "cget", "configure", "coords", "get", "identify", "set", NULL
+};
+
+enum command {
+ COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_COORDS, COMMAND_GET,
+ COMMAND_IDENTIFY, COMMAND_SET
+};
+
+/*
+ * Forward declarations for procedures defined later in this file:
+ */
+
+static void ComputeFormat(TkScale *scalePtr, int forTicks);
+static void ComputeScaleGeometry(TkScale *scalePtr);
+static int ConfigureScale(Tcl_Interp *interp, TkScale *scalePtr,
+ int objc, Tcl_Obj *const objv[]);
+static void DestroyScale(char *memPtr);
+static double MaxTickRoundingError(TkScale *scalePtr,
+ double tickResolution);
+static void ScaleCmdDeletedProc(ClientData clientData);
+static void ScaleEventProc(ClientData clientData,
+ XEvent *eventPtr);
+static char * ScaleVarProc(ClientData clientData,
+ Tcl_Interp *interp, const char *name1,
+ const char *name2, int flags);
+static int ScaleWidgetObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static void ScaleWorldChanged(ClientData instanceData);
+static void ScaleSetVariable(TkScale *scalePtr);
+
+/*
+ * The structure below defines scale class behavior by means of procedures
+ * that can be invoked from generic window code.
+ */
+
+static const Tk_ClassProcs scaleClass = {
+ sizeof(Tk_ClassProcs), /* size */
+ ScaleWorldChanged, /* worldChangedProc */
+ NULL, /* createProc */
+ NULL /* modalProc */
+};
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ScaleDigit, ScaleMax, ScaleMin, ScaleRound --
+ *
+ * Simple math helper functions, designed to be automatically inlined by
+ * the compiler most of the time.
+ *
+ *--------------------------------------------------------------
+ */
+
+static inline int
+ScaleDigit(
+ double value)
+{
+ return (int) floor(log10(fabs(value)));
+}
+
+static inline double
+ScaleMax(
+ double a,
+ double b)
+{
+ return (a > b) ? a : b;
+}
+
+static inline double
+ScaleMin(
+ double a,
+ double b)
+{
+ return (a < b) ? a : b;
+}
+
+static inline int
+ScaleRound(
+ double value)
+{
+ return (int) floor(value + 0.5);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_ScaleObjCmd --
+ *
+ * This procedure is invoked to process the "scale" 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_ScaleObjCmd(
+ ClientData clientData, /* NULL. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument values. */
+{
+ register TkScale *scalePtr;
+ Tk_OptionTable optionTable;
+ Tk_Window tkwin;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?");
+ return TCL_ERROR;
+ }
+
+ tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),
+ Tcl_GetString(objv[1]), NULL);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Create the option table for this widget class. If it has already been
+ * created, the cached pointer will be returned.
+ */
+
+ optionTable = Tk_CreateOptionTable(interp, optionSpecs);
+
+ Tk_SetClass(tkwin, "Scale");
+ scalePtr = TkpCreateScale(tkwin);
+
+ /*
+ * Initialize fields that won't be initialized by ConfigureScale, or which
+ * ConfigureScale expects to have reasonable values (e.g. resource
+ * pointers).
+ */
+
+ scalePtr->tkwin = tkwin;
+ scalePtr->display = Tk_Display(tkwin);
+ scalePtr->interp = interp;
+ scalePtr->widgetCmd = Tcl_CreateObjCommand(interp,
+ Tk_PathName(scalePtr->tkwin), ScaleWidgetObjCmd,
+ scalePtr, ScaleCmdDeletedProc);
+ scalePtr->optionTable = optionTable;
+ scalePtr->orient = ORIENT_VERTICAL;
+ scalePtr->width = 0;
+ scalePtr->length = 0;
+ scalePtr->value = 0.0;
+ scalePtr->varNamePtr = NULL;
+ scalePtr->fromValue = 0.0;
+ scalePtr->toValue = 0.0;
+ scalePtr->tickInterval = 0.0;
+ scalePtr->resolution = 1.0;
+ scalePtr->digits = 0;
+ scalePtr->bigIncrement = 0.0;
+ scalePtr->command = NULL;
+ scalePtr->repeatDelay = 0;
+ scalePtr->repeatInterval = 0;
+ scalePtr->label = NULL;
+ scalePtr->labelLength = 0;
+ scalePtr->state = STATE_NORMAL;
+ scalePtr->borderWidth = 0;
+ scalePtr->bgBorder = NULL;
+ scalePtr->activeBorder = NULL;
+ scalePtr->sliderRelief = TK_RELIEF_RAISED;
+ scalePtr->troughColorPtr = NULL;
+ scalePtr->troughGC = NULL;
+ scalePtr->copyGC = NULL;
+ scalePtr->tkfont = NULL;
+ scalePtr->textColorPtr = NULL;
+ scalePtr->textGC = NULL;
+ scalePtr->relief = TK_RELIEF_FLAT;
+ scalePtr->highlightWidth = 0;
+ scalePtr->highlightBorder = NULL;
+ scalePtr->highlightColorPtr = NULL;
+ scalePtr->inset = 0;
+ scalePtr->sliderLength = 0;
+ scalePtr->showValue = 0;
+ scalePtr->horizLabelY = 0;
+ scalePtr->horizValueY = 0;
+ scalePtr->horizTroughY = 0;
+ scalePtr->horizTickY = 0;
+ scalePtr->vertTickRightX = 0;
+ scalePtr->vertValueRightX = 0;
+ scalePtr->vertTroughX = 0;
+ scalePtr->vertLabelX = 0;
+ scalePtr->fontHeight = 0;
+ scalePtr->cursor = NULL;
+ scalePtr->takeFocusPtr = NULL;
+ scalePtr->flags = NEVER_SET;
+
+ Tk_SetClassProcs(scalePtr->tkwin, &scaleClass, scalePtr);
+ Tk_CreateEventHandler(scalePtr->tkwin,
+ ExposureMask|StructureNotifyMask|FocusChangeMask,
+ ScaleEventProc, scalePtr);
+
+ if ((Tk_InitOptions(interp, (char *) scalePtr, optionTable, tkwin)
+ != TCL_OK) ||
+ (ConfigureScale(interp, scalePtr, objc - 2, objv + 2) != TCL_OK)) {
+ Tk_DestroyWindow(scalePtr->tkwin);
+ return TCL_ERROR;
+ }
+
+ /*
+ * The widget was just created, no command callback must be invoked.
+ */
+
+ scalePtr->flags &= ~INVOKE_COMMAND;
+
+ Tcl_SetObjResult(interp, TkNewWindowObj(scalePtr->tkwin));
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ScaleWidgetObjCmd --
+ *
+ * This procedure is invoked to process the Tcl command that corresponds
+ * to a widget managed by this module. See the user documentation for
+ * details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+ScaleWidgetObjCmd(
+ ClientData clientData, /* Information about scale widget. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument strings. */
+{
+ TkScale *scalePtr = clientData;
+ Tcl_Obj *objPtr;
+ int index, result;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ result = Tcl_GetIndexFromObjStruct(interp, objv[1], commandNames,
+ sizeof(char *), "option", 0, &index);
+ if (result != TCL_OK) {
+ return result;
+ }
+ Tcl_Preserve(scalePtr);
+
+ switch (index) {
+ case COMMAND_CGET:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "cget option");
+ goto error;
+ }
+ objPtr = Tk_GetOptionValue(interp, (char *) scalePtr,
+ scalePtr->optionTable, objv[2], scalePtr->tkwin);
+ if (objPtr == NULL) {
+ goto error;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ break;
+ case COMMAND_CONFIGURE:
+ if (objc <= 3) {
+ objPtr = Tk_GetOptionInfo(interp, (char *) scalePtr,
+ scalePtr->optionTable,
+ (objc == 3) ? objv[2] : NULL, scalePtr->tkwin);
+ if (objPtr == NULL) {
+ goto error;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ } else {
+ result = ConfigureScale(interp, scalePtr, objc-2, objv+2);
+ }
+ break;
+ case COMMAND_COORDS: {
+ int x, y;
+ double value;
+ Tcl_Obj *coords[2];
+
+ if ((objc != 2) && (objc != 3)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "coords ?value?");
+ goto error;
+ }
+ if (objc == 3) {
+ if (Tcl_GetDoubleFromObj(interp, objv[2], &value) != TCL_OK) {
+ goto error;
+ }
+ } else {
+ value = scalePtr->value;
+ }
+ if (scalePtr->orient == ORIENT_VERTICAL) {
+ x = scalePtr->vertTroughX + scalePtr->width/2
+ + scalePtr->borderWidth;
+ y = TkScaleValueToPixel(scalePtr, value);
+ } else {
+ x = TkScaleValueToPixel(scalePtr, value);
+ y = scalePtr->horizTroughY + scalePtr->width/2
+ + scalePtr->borderWidth;
+ }
+ coords[0] = Tcl_NewIntObj(x);
+ coords[1] = Tcl_NewIntObj(y);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(2, coords));
+ break;
+ }
+ case COMMAND_GET: {
+ double value;
+ int x, y;
+
+ if ((objc != 2) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "get ?x y?");
+ goto error;
+ }
+ if (objc == 2) {
+ value = scalePtr->value;
+ } else {
+ if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK) ||
+ (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {
+ goto error;
+ }
+ value = TkScalePixelToValue(scalePtr, x, y);
+ }
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(scalePtr->valueFormat, value));
+ break;
+ }
+ case COMMAND_IDENTIFY: {
+ int x, y;
+ const char *zone = "";
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "identify x y");
+ goto error;
+ }
+ if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {
+ goto error;
+ }
+ switch (TkpScaleElement(scalePtr, x, y)) {
+ case TROUGH1: zone = "trough1"; break;
+ case SLIDER: zone = "slider"; break;
+ case TROUGH2: zone = "trough2"; break;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(zone, -1));
+ break;
+ }
+ case COMMAND_SET: {
+ double value;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "set value");
+ goto error;
+ }
+ if (Tcl_GetDoubleFromObj(interp, objv[2], &value) != TCL_OK) {
+ goto error;
+ }
+ if (scalePtr->state != STATE_DISABLED) {
+ TkScaleSetValue(scalePtr, value, 1, 1);
+ }
+ break;
+ }
+ }
+ Tcl_Release(scalePtr);
+ return result;
+
+ error:
+ Tcl_Release(scalePtr);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyScale --
+ *
+ * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release to
+ * clean up the internal structure of a button at a safe time (when
+ * no-one is using it anymore).
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Everything associated with the scale is freed up.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DestroyScale(
+ char *memPtr) /* Info about scale widget. */
+{
+ register TkScale *scalePtr = (TkScale *) memPtr;
+
+ scalePtr->flags |= SCALE_DELETED;
+
+ Tcl_DeleteCommandFromToken(scalePtr->interp, scalePtr->widgetCmd);
+ if (scalePtr->flags & REDRAW_PENDING) {
+ Tcl_CancelIdleCall(TkpDisplayScale, scalePtr);
+ }
+
+ /*
+ * Free up all the stuff that requires special handling, then let
+ * Tk_FreeOptions handle all the standard option-related stuff.
+ */
+
+ if (scalePtr->varNamePtr != NULL) {
+ Tcl_UntraceVar2(scalePtr->interp, Tcl_GetString(scalePtr->varNamePtr),
+ NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ ScaleVarProc, scalePtr);
+ }
+ if (scalePtr->troughGC != NULL) {
+ Tk_FreeGC(scalePtr->display, scalePtr->troughGC);
+ }
+ if (scalePtr->copyGC != NULL) {
+ Tk_FreeGC(scalePtr->display, scalePtr->copyGC);
+ }
+ if (scalePtr->textGC != NULL) {
+ Tk_FreeGC(scalePtr->display, scalePtr->textGC);
+ }
+ Tk_FreeConfigOptions((char *) scalePtr, scalePtr->optionTable,
+ scalePtr->tkwin);
+ scalePtr->tkwin = NULL;
+ TkpDestroyScale(scalePtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConfigureScale --
+ *
+ * This procedure is called to process an argv/argc list, plus the Tk
+ * option database, in order to configure (or reconfigure) a scale
+ * widget.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If TCL_ERROR is returned,
+ * then the interp's result contains an error message.
+ *
+ * Side effects:
+ * Configuration information, such as colors, border width, etc. get set
+ * for scalePtr; old resources get freed, if there were any.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ConfigureScale(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ register TkScale *scalePtr, /* Information about widget; may or may not
+ * already have values for some fields. */
+ int objc, /* Number of valid entries in objv. */
+ Tcl_Obj *const objv[]) /* Argument values. */
+{
+ Tk_SavedOptions savedOptions;
+ Tcl_Obj *errorResult = NULL;
+ int error;
+ double varValue;
+
+ /*
+ * Eliminate any existing trace on a variable monitored by the scale.
+ */
+
+ if (scalePtr->varNamePtr != NULL) {
+ Tcl_UntraceVar2(interp, Tcl_GetString(scalePtr->varNamePtr),
+ NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ ScaleVarProc, scalePtr);
+ }
+
+ for (error = 0; error <= 1; error++) {
+ if (!error) {
+ /*
+ * First pass: set options to new values.
+ */
+
+ if (Tk_SetOptions(interp, (char *) scalePtr,
+ scalePtr->optionTable, objc, objv, scalePtr->tkwin,
+ &savedOptions, NULL) != TCL_OK) {
+ continue;
+ }
+ } else {
+ /*
+ * Second pass: restore options to old values.
+ */
+
+ errorResult = Tcl_GetObjResult(interp);
+ Tcl_IncrRefCount(errorResult);
+ Tk_RestoreSavedOptions(&savedOptions);
+ }
+
+ /*
+ * If the scale is tied to the value of a variable, then set the
+ * scale's value from the value of the variable, if it exists and it
+ * holds a valid double value.
+ */
+
+ if (scalePtr->varNamePtr != NULL) {
+ double value;
+ Tcl_Obj *valuePtr;
+
+ valuePtr = Tcl_ObjGetVar2(interp, scalePtr->varNamePtr, NULL,
+ TCL_GLOBAL_ONLY);
+ if ((valuePtr != NULL) &&
+ (Tcl_GetDoubleFromObj(NULL, valuePtr, &value) == TCL_OK)) {
+ scalePtr->value = TkRoundValueToResolution(scalePtr, value);
+ }
+ }
+
+ /*
+ * Several options need special processing, such as parsing the
+ * orientation and creating GCs.
+ */
+
+ scalePtr->fromValue = TkRoundValueToResolution(scalePtr,
+ scalePtr->fromValue);
+ scalePtr->toValue = TkRoundValueToResolution(scalePtr, scalePtr->toValue);
+ scalePtr->tickInterval = TkRoundIntervalToResolution(scalePtr,
+ scalePtr->tickInterval);
+
+ /*
+ * Make sure that the tick interval has the right sign so that
+ * addition moves from fromValue to toValue.
+ */
+
+ if ((scalePtr->tickInterval < 0)
+ ^ ((scalePtr->toValue - scalePtr->fromValue) < 0)) {
+ scalePtr->tickInterval = -scalePtr->tickInterval;
+ }
+
+ ComputeFormat(scalePtr, 0);
+ ComputeFormat(scalePtr, 1);
+
+ scalePtr->labelLength = scalePtr->label ? (int)strlen(scalePtr->label) : 0;
+
+ Tk_SetBackgroundFromBorder(scalePtr->tkwin, scalePtr->bgBorder);
+
+ if (scalePtr->highlightWidth < 0) {
+ scalePtr->highlightWidth = 0;
+ }
+ scalePtr->inset = scalePtr->highlightWidth + scalePtr->borderWidth;
+ break;
+ }
+ if (!error) {
+ Tk_FreeSavedOptions(&savedOptions);
+ }
+
+ /*
+ * Set the scale value to itself; all this does is to make sure that the
+ * scale's value is within the new acceptable range for the scale. We
+ * don't set the var here because we need to make special checks for
+ * possibly changed varNamePtr.
+ */
+
+ TkScaleSetValue(scalePtr, scalePtr->value, 0, 1);
+
+ /*
+ * Reestablish the variable trace, if it is needed.
+ */
+
+ if (scalePtr->varNamePtr != NULL) {
+ Tcl_Obj *valuePtr;
+
+ /*
+ * Set the associated variable only when the new value differs from
+ * the current value, or the variable doesn't yet exist.
+ */
+
+ valuePtr = Tcl_ObjGetVar2(interp, scalePtr->varNamePtr, NULL,
+ TCL_GLOBAL_ONLY);
+ if ((valuePtr == NULL) || (Tcl_GetDoubleFromObj(NULL,
+ valuePtr, &varValue) != TCL_OK)) {
+ ScaleSetVariable(scalePtr);
+ } else {
+ char varString[TCL_DOUBLE_SPACE], scaleString[TCL_DOUBLE_SPACE];
+
+ Tcl_PrintDouble(NULL, varValue, varString);
+ Tcl_PrintDouble(NULL, scalePtr->value, scaleString);
+ if (strcmp(varString, scaleString)) {
+ ScaleSetVariable(scalePtr);
+ }
+ }
+ Tcl_TraceVar2(interp, Tcl_GetString(scalePtr->varNamePtr),
+ NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ ScaleVarProc, scalePtr);
+ }
+
+ ScaleWorldChanged(scalePtr);
+ if (error) {
+ Tcl_SetObjResult(interp, errorResult);
+ Tcl_DecrRefCount(errorResult);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ScaleWorldChanged --
+ *
+ * This procedure is called when the world has changed in some way and
+ * the widget needs to recompute all its graphics contexts and determine
+ * its new geometry.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Scale will be relayed out and redisplayed.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+ScaleWorldChanged(
+ ClientData instanceData) /* Information about widget. */
+{
+ XGCValues gcValues;
+ GC gc;
+ TkScale *scalePtr = instanceData;
+
+ gcValues.foreground = scalePtr->troughColorPtr->pixel;
+ gc = Tk_GetGC(scalePtr->tkwin, GCForeground, &gcValues);
+ if (scalePtr->troughGC != NULL) {
+ Tk_FreeGC(scalePtr->display, scalePtr->troughGC);
+ }
+ scalePtr->troughGC = gc;
+
+ gcValues.font = Tk_FontId(scalePtr->tkfont);
+ gcValues.foreground = scalePtr->textColorPtr->pixel;
+ gc = Tk_GetGC(scalePtr->tkwin, GCForeground | GCFont, &gcValues);
+ if (scalePtr->textGC != NULL) {
+ Tk_FreeGC(scalePtr->display, scalePtr->textGC);
+ }
+ scalePtr->textGC = gc;
+
+ if (scalePtr->copyGC == NULL) {
+ gcValues.graphics_exposures = False;
+ scalePtr->copyGC = Tk_GetGC(scalePtr->tkwin, GCGraphicsExposures,
+ &gcValues);
+ }
+ scalePtr->inset = scalePtr->highlightWidth + scalePtr->borderWidth;
+
+ /*
+ * Recompute display-related information, and let the geometry manager
+ * know how much space is needed now.
+ */
+
+ ComputeScaleGeometry(scalePtr);
+
+ TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);
+}
+
+ /*
+ *----------------------------------------------------------------------
+ *
+ * MaxTickRoundingError --
+ *
+ * Given the separation between values that can be displayed on ticks,
+ * this calculates the maximum magnitude of error for the displayed
+ * value. Tries to be clever by working out the increment in error
+ * between ticks rather than testing all of them, so may overestimate
+ * error if it is greater than 0.25 x the value separation.
+ *
+ * Results:
+ * Maximum error magnitude of tick numbers.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static double
+MaxTickRoundingError(
+ TkScale *scalePtr, /* Information about scale widget. */
+ double tickResolution) /* Separation between displayable values. */
+{
+ double tickPosn, firstTickError, lastTickError, intervalError;
+ int tickCount;
+
+ /*
+ * Compute the error for each tick-related measure.
+ */
+
+ tickPosn = scalePtr->fromValue / tickResolution;
+ firstTickError = tickPosn - ScaleRound(tickPosn);
+
+ tickPosn = scalePtr->tickInterval / tickResolution;
+ intervalError = tickPosn - ScaleRound(tickPosn);
+
+ tickCount = (int) ((scalePtr->toValue - scalePtr->fromValue) /
+ scalePtr->tickInterval); /* not including first */
+ lastTickError = ScaleMin(0.5,
+ fabs(firstTickError + tickCount * intervalError));
+
+ /*
+ * Compute the maximum cumulative rounding error.
+ */
+
+ return ScaleMax(fabs(firstTickError), lastTickError) * tickResolution;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ComputeFormat --
+ *
+ * This procedure is invoked to recompute the "valueFormat" or
+ * "tickFormat" field of a scale's widget record, which determines how
+ * the value of the scale or one of its ticks is converted to a string.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects: The valueFormat or tickFormat field of scalePtr is modified.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ComputeFormat(
+ TkScale *scalePtr, /* Information about scale widget. */
+ int forTicks) /* Do for ticks rather than value */
+{
+ double maxValue, x;
+ int mostSigDigit, numDigits, leastSigDigit, afterDecimal;
+ int eDigits, fDigits;
+
+ /*
+ * Compute the displacement from the decimal of the most significant digit
+ * required for any number in the scale's range.
+ */
+
+ maxValue = fabs(scalePtr->fromValue);
+ x = fabs(scalePtr->toValue);
+ if (x > maxValue) {
+ maxValue = x;
+ }
+ if (maxValue == 0) {
+ maxValue = 1;
+ }
+ mostSigDigit = ScaleDigit(maxValue);
+
+ if (forTicks) {
+ /*
+ * Display only enough digits to ensure adjacent ticks have different
+ * values.
+ */
+
+ if (scalePtr->tickInterval != 0) {
+ leastSigDigit = ScaleDigit(scalePtr->tickInterval);
+
+ /*
+ * Now add more digits until max error is less than
+ * TICK_VALUES_DISPLAY_ACCURACY intervals
+ */
+
+ while (MaxTickRoundingError(scalePtr, pow(10, leastSigDigit))
+ > fabs(TICK_VALUES_DISPLAY_ACCURACY * scalePtr->tickInterval)) {
+ --leastSigDigit;
+ }
+ numDigits = 1 + mostSigDigit - leastSigDigit;
+ } else {
+ numDigits = 1;
+ }
+ } else {
+ /*
+ * If the number of significant digits wasn't specified explicitly,
+ * compute it. It's the difference between the most significant digit
+ * needed to represent any number on the scale and the most
+ * significant digit of the smallest difference between numbers on the
+ * scale. In other words, display enough digits so that at least one
+ * digit will be different between any two adjacent positions of the
+ * scale.
+ */
+
+ numDigits = scalePtr->digits;
+ if (numDigits > TCL_MAX_PREC) {
+ numDigits = 0;
+ }
+ if (numDigits <= 0) {
+ if (scalePtr->resolution > 0) {
+ /*
+ * A resolution was specified for the scale, so just use it.
+ */
+
+ leastSigDigit = ScaleDigit(scalePtr->resolution);
+ } else {
+ /*
+ * No resolution was specified, so compute the difference in
+ * value between adjacent pixels and use it for the least
+ * significant digit.
+ */
+
+ x = fabs(scalePtr->fromValue - scalePtr->toValue);
+ if (scalePtr->length > 0) {
+ x /= scalePtr->length;
+ }
+ if (x > 0) {
+ leastSigDigit = ScaleDigit(x);
+ } else {
+ leastSigDigit = 0;
+ }
+ }
+ numDigits = mostSigDigit - leastSigDigit + 1;
+ if (numDigits < 1) {
+ numDigits = 1;
+ }
+ }
+ }
+
+ /*
+ * Compute the number of characters required using "e" format and "f"
+ * format, and then choose whichever one takes fewer characters.
+ */
+
+ eDigits = numDigits + 4;
+ if (numDigits > 1) {
+ eDigits++; /* Decimal point. */
+ }
+ afterDecimal = numDigits - mostSigDigit - 1;
+ if (afterDecimal < 0) {
+ afterDecimal = 0;
+ }
+ fDigits = (mostSigDigit >= 0) ? mostSigDigit + afterDecimal : afterDecimal;
+ if (afterDecimal > 0) {
+ fDigits++; /* Decimal point. */
+ }
+ if (mostSigDigit < 0) {
+ fDigits++; /* Zero to left of decimal point. */
+ }
+
+ if (forTicks) {
+ if (fDigits <= eDigits) {
+ sprintf(scalePtr->tickFormat, "%%.%df", afterDecimal);
+ } else {
+ sprintf(scalePtr->tickFormat, "%%.%de", numDigits - 1);
+ }
+ } else {
+ if (fDigits <= eDigits) {
+ sprintf(scalePtr->valueFormat, "%%.%df", afterDecimal);
+ } else {
+ sprintf(scalePtr->valueFormat, "%%.%de", numDigits - 1);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ComputeScaleGeometry --
+ *
+ * This procedure is called to compute various geometrical information
+ * for a scale, such as where various things get displayed. It's called
+ * when the window is reconfigured.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Display-related numbers get changed in *scalePtr. The geometry manager
+ * gets told about the window's preferred size.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ComputeScaleGeometry(
+ register TkScale *scalePtr) /* Information about widget. */
+{
+ char valueString[TCL_DOUBLE_SPACE];
+ int tmp, valuePixels, tickPixels, x, y, extraSpace;
+ Tk_FontMetrics fm;
+
+ Tk_GetFontMetrics(scalePtr->tkfont, &fm);
+ scalePtr->fontHeight = fm.linespace + SPACING;
+
+ /*
+ * Horizontal scales are simpler than vertical ones because all sizes are
+ * the same (the height of a line of text); handle them first and then
+ * quit.
+ */
+
+ if (scalePtr->orient == ORIENT_HORIZONTAL) {
+ y = scalePtr->inset;
+ extraSpace = 0;
+ if (scalePtr->labelLength != 0) {
+ scalePtr->horizLabelY = y + SPACING;
+ y += scalePtr->fontHeight;
+ extraSpace = SPACING;
+ }
+ if (scalePtr->showValue) {
+ scalePtr->horizValueY = y + SPACING;
+ y += scalePtr->fontHeight;
+ extraSpace = SPACING;
+ } else {
+ scalePtr->horizValueY = y;
+ }
+ y += extraSpace;
+ scalePtr->horizTroughY = y;
+ y += scalePtr->width + 2*scalePtr->borderWidth;
+ if (scalePtr->tickInterval != 0) {
+ scalePtr->horizTickY = y + SPACING;
+ y += scalePtr->fontHeight + SPACING;
+ }
+ Tk_GeometryRequest(scalePtr->tkwin,
+ scalePtr->length + 2*scalePtr->inset, y + scalePtr->inset);
+ Tk_SetInternalBorder(scalePtr->tkwin, scalePtr->inset);
+ return;
+ }
+
+ /*
+ * Vertical scale: compute the amount of space needed to display the
+ * scales value by formatting strings for the two end points; use
+ * whichever length is longer.
+ */
+
+ if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->valueFormat,
+ scalePtr->fromValue) < 0) {
+ valueString[TCL_DOUBLE_SPACE - 1] = '\0';
+ }
+ valuePixels = Tk_TextWidth(scalePtr->tkfont, valueString, -1);
+
+ if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->valueFormat,
+ scalePtr->toValue) < 0) {
+ valueString[TCL_DOUBLE_SPACE - 1] = '\0';
+ }
+ tmp = Tk_TextWidth(scalePtr->tkfont, valueString, -1);
+ if (valuePixels < tmp) {
+ valuePixels = tmp;
+ }
+
+ /*
+ * Now do the same thing for the tick values
+ */
+
+ if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->tickFormat,
+ scalePtr->fromValue) < 0) {
+ valueString[TCL_DOUBLE_SPACE - 1] = '\0';
+ }
+ tickPixels = Tk_TextWidth(scalePtr->tkfont, valueString, -1);
+
+ if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->tickFormat,
+ scalePtr->toValue) < 0) {
+ valueString[TCL_DOUBLE_SPACE - 1] = '\0';
+ }
+ tmp = Tk_TextWidth(scalePtr->tkfont, valueString, -1);
+ if (tickPixels < tmp) {
+ tickPixels = tmp;
+ }
+
+ /*
+ * Assign x-locations to the elements of the scale, working from left to
+ * right.
+ */
+
+ x = scalePtr->inset;
+ if ((scalePtr->tickInterval != 0) && (scalePtr->showValue)) {
+ scalePtr->vertTickRightX = x + SPACING + tickPixels;
+ scalePtr->vertValueRightX = scalePtr->vertTickRightX + valuePixels
+ + fm.ascent/2;
+ x = scalePtr->vertValueRightX + SPACING;
+ } else if (scalePtr->tickInterval != 0) {
+ scalePtr->vertTickRightX = x + SPACING + tickPixels;
+ scalePtr->vertValueRightX = scalePtr->vertTickRightX;
+ x = scalePtr->vertTickRightX + SPACING;
+ } else if (scalePtr->showValue) {
+ scalePtr->vertTickRightX = x;
+ scalePtr->vertValueRightX = x + SPACING + valuePixels;
+ x = scalePtr->vertValueRightX + SPACING;
+ } else {
+ scalePtr->vertTickRightX = x;
+ scalePtr->vertValueRightX = x;
+ }
+ scalePtr->vertTroughX = x;
+ x += 2*scalePtr->borderWidth + scalePtr->width;
+ if (scalePtr->labelLength == 0) {
+ scalePtr->vertLabelX = 0;
+ } else {
+ scalePtr->vertLabelX = x + fm.ascent/2;
+ x = scalePtr->vertLabelX + fm.ascent/2
+ + Tk_TextWidth(scalePtr->tkfont, scalePtr->label,
+ scalePtr->labelLength);
+ }
+ Tk_GeometryRequest(scalePtr->tkwin, x + scalePtr->inset,
+ scalePtr->length + 2*scalePtr->inset);
+ Tk_SetInternalBorder(scalePtr->tkwin, scalePtr->inset);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ScaleEventProc --
+ *
+ * This procedure is invoked by the Tk dispatcher for various 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
+ScaleEventProc(
+ ClientData clientData, /* Information about window. */
+ XEvent *eventPtr) /* Information about event. */
+{
+ TkScale *scalePtr = clientData;
+
+ if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {
+ TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);
+ } else if (eventPtr->type == DestroyNotify) {
+ DestroyScale(clientData);
+ } else if (eventPtr->type == ConfigureNotify) {
+ ComputeScaleGeometry(scalePtr);
+ TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);
+ } else if (eventPtr->type == FocusIn) {
+ if (eventPtr->xfocus.detail != NotifyInferior) {
+ scalePtr->flags |= GOT_FOCUS;
+ if (scalePtr->highlightWidth > 0) {
+ TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);
+ }
+ }
+ } else if (eventPtr->type == FocusOut) {
+ if (eventPtr->xfocus.detail != NotifyInferior) {
+ scalePtr->flags &= ~GOT_FOCUS;
+ if (scalePtr->highlightWidth > 0) {
+ TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);
+ }
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ScaleCmdDeletedProc --
+ *
+ * This procedure is invoked when a widget command is deleted. If the
+ * widget isn't already in the process of being destroyed, this command
+ * destroys it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The widget is destroyed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ScaleCmdDeletedProc(
+ ClientData clientData) /* Pointer to widget record for widget. */
+{
+ TkScale *scalePtr = clientData;
+ Tk_Window tkwin = scalePtr->tkwin;
+
+ /*
+ * This procedure could be invoked either because the window was destroyed
+ * and the command was then deleted (in which case tkwin is NULL) or
+ * because the command was deleted, and then this procedure destroys the
+ * widget.
+ */
+
+ if (!(scalePtr->flags & SCALE_DELETED)) {
+ scalePtr->flags |= SCALE_DELETED;
+ Tk_DestroyWindow(tkwin);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkEventuallyRedrawScale --
+ *
+ * Arrange for part or all of a scale widget to redrawn at the next
+ * convenient time in the future.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If "what" is REDRAW_SLIDER then just the slider and the value readout
+ * will be redrawn; if "what" is REDRAW_ALL then the entire widget will
+ * be redrawn.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkEventuallyRedrawScale(
+ register TkScale *scalePtr, /* Information about widget. */
+ int what) /* What to redraw: REDRAW_SLIDER or
+ * REDRAW_ALL. */
+{
+ if ((what == 0) || (scalePtr->tkwin == NULL)
+ || !Tk_IsMapped(scalePtr->tkwin)) {
+ return;
+ }
+ if (!(scalePtr->flags & REDRAW_PENDING)) {
+ scalePtr->flags |= REDRAW_PENDING;
+ Tcl_DoWhenIdle(TkpDisplayScale, scalePtr);
+ }
+ scalePtr->flags |= what;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkRoundValueToResolution, TkRoundIntervalToResolution --
+ *
+ * Round a given floating-point value to the nearest multiple of the
+ * scale's resolution.
+ * TkRoundValueToResolution rounds an absolute value based on the from
+ * value as a reference.
+ * TkRoundIntervalToResolution rounds a relative value without
+ * reference, i.e. it rounds an interval.
+ *
+ * Results:
+ * The return value is the rounded result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+double
+TkRoundValueToResolution(
+ TkScale *scalePtr, /* Information about scale widget. */
+ double value) /* Value to round. */
+{
+ return TkRoundIntervalToResolution(scalePtr, value - scalePtr->fromValue)
+ + scalePtr->fromValue;
+}
+
+double
+TkRoundIntervalToResolution(
+ TkScale *scalePtr, /* Information about scale widget. */
+ double value) /* Value to round. */
+{
+ double rem, rounded, tick;
+
+ if (scalePtr->resolution <= 0) {
+ return value;
+ }
+ tick = floor(value/scalePtr->resolution);
+ rounded = scalePtr->resolution * tick;
+ rem = value - rounded;
+ if (rem < 0) {
+ if (rem <= -scalePtr->resolution/2) {
+ rounded = (tick - 1.0) * scalePtr->resolution;
+ }
+ } else {
+ if (rem >= scalePtr->resolution/2) {
+ rounded = (tick + 1.0) * scalePtr->resolution;
+ }
+ }
+ return rounded;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ScaleVarProc --
+ *
+ * This procedure is invoked by Tcl whenever someone modifies a variable
+ * associated with a scale widget.
+ *
+ * Results:
+ * NULL is always returned.
+ *
+ * Side effects:
+ * The value displayed in the scale will change to match the variable's
+ * new value. If the variable has a bogus value then it is reset to the
+ * value of the scale.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static char *
+ScaleVarProc(
+ ClientData clientData, /* Information about button. */
+ Tcl_Interp *interp, /* Interpreter containing variable. */
+ const char *name1, /* Name of variable. */
+ const char *name2, /* Second part of variable name. */
+ int flags) /* Information about what happened. */
+{
+ register TkScale *scalePtr = clientData;
+ const char *resultStr;
+ double value;
+ Tcl_Obj *valuePtr;
+ int result;
+
+ /*
+ * If the variable is unset, then immediately recreate it unless the whole
+ * interpreter is going away.
+ */
+
+ if (flags & TCL_TRACE_UNSETS) {
+ if (!Tcl_InterpDeleted(interp) && scalePtr->varNamePtr) {
+ ClientData probe = NULL;
+
+ do {
+ probe = Tcl_VarTraceInfo(interp,
+ Tcl_GetString(scalePtr->varNamePtr),
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ ScaleVarProc, probe);
+ if (probe == (ClientData)scalePtr) {
+ break;
+ }
+ } while (probe);
+ if (probe) {
+ /*
+ * We were able to fetch the unset trace for our
+ * varNamePtr, which means it is not unset and not
+ * the cause of this unset trace. Instead some outdated
+ * former variable must be, and we should ignore it.
+ */
+ return NULL;
+ }
+ Tcl_TraceVar2(interp, Tcl_GetString(scalePtr->varNamePtr),
+ NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ ScaleVarProc, clientData);
+ scalePtr->flags |= NEVER_SET;
+ TkScaleSetValue(scalePtr, scalePtr->value, 1, 0);
+ }
+ return NULL;
+ }
+
+ /*
+ * If we came here because we updated the variable (in TkScaleSetValue),
+ * then ignore the trace. Otherwise update the scale with the value of the
+ * variable.
+ */
+
+ if (scalePtr->flags & SETTING_VAR) {
+ return NULL;
+ }
+ resultStr = NULL;
+ valuePtr = Tcl_ObjGetVar2(interp, scalePtr->varNamePtr, NULL,
+ TCL_GLOBAL_ONLY);
+ result = Tcl_GetDoubleFromObj(interp, valuePtr, &value);
+ if (result != TCL_OK) {
+ resultStr = "can't assign non-numeric value to scale variable";
+ ScaleSetVariable(scalePtr);
+ } else {
+ scalePtr->value = TkRoundValueToResolution(scalePtr, value);
+
+ /*
+ * This code is a bit tricky because it sets the scale's value before
+ * calling TkScaleSetValue. This way, TkScaleSetValue won't bother to
+ * set the variable again or to invoke the -command. However, it also
+ * won't redisplay the scale, so we have to ask for that explicitly.
+ */
+
+ TkScaleSetValue(scalePtr, scalePtr->value, 1, 0);
+ }
+ TkEventuallyRedrawScale(scalePtr, REDRAW_SLIDER);
+
+ return (char *) resultStr;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkScaleSetValue --
+ *
+ * This procedure changes the value of a scale and invokes a Tcl command
+ * to reflect the current position of a scale
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A Tcl command is invoked, and an additional error-processing command
+ * may also be invoked. The scale's slider is redrawn.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkScaleSetValue(
+ register TkScale *scalePtr, /* Info about widget. */
+ double value, /* New value for scale. Gets adjusted if it's
+ * off the scale. */
+ int setVar, /* Non-zero means reflect new value through to
+ * associated variable, if any. */
+ int invokeCommand) /* Non-zero means invoked -command option to
+ * notify of new value, 0 means don't. */
+{
+ value = TkRoundValueToResolution(scalePtr, value);
+ if ((value < scalePtr->fromValue)
+ ^ (scalePtr->toValue < scalePtr->fromValue)) {
+ value = scalePtr->fromValue;
+ }
+ if ((value > scalePtr->toValue)
+ ^ (scalePtr->toValue < scalePtr->fromValue)) {
+ value = scalePtr->toValue;
+ }
+ if (scalePtr->flags & NEVER_SET) {
+ scalePtr->flags &= ~NEVER_SET;
+ } else if (scalePtr->value == value) {
+ return;
+ }
+ scalePtr->value = value;
+
+ /*
+ * Schedule command callback invocation only if there is such a command
+ * already registered, otherwise the callback would trigger later when
+ * configuring the widget -command option even if the value did not change.
+ */
+
+ if ((invokeCommand) && (scalePtr->command != NULL)) {
+ scalePtr->flags |= INVOKE_COMMAND;
+ }
+ TkEventuallyRedrawScale(scalePtr, REDRAW_SLIDER);
+
+ if (setVar && scalePtr->varNamePtr) {
+ ScaleSetVariable(scalePtr);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ScaleSetVariable --
+ *
+ * This procedure sets the variable associated with a scale, if any.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Other write traces on the variable will trigger.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ScaleSetVariable(
+ register TkScale *scalePtr) /* Info about widget. */
+{
+ if (scalePtr->varNamePtr != NULL) {
+ char string[TCL_DOUBLE_SPACE];
+
+ if (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->valueFormat,
+ scalePtr->value) < 0) {
+ string[TCL_DOUBLE_SPACE - 1] = '\0';
+ }
+ scalePtr->flags |= SETTING_VAR;
+ Tcl_ObjSetVar2(scalePtr->interp, scalePtr->varNamePtr, NULL,
+ Tcl_NewStringObj(string, -1), TCL_GLOBAL_ONLY);
+ scalePtr->flags &= ~SETTING_VAR;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkScalePixelToValue --
+ *
+ * Given a pixel within a scale window, return the scale reading
+ * corresponding to that pixel.
+ *
+ * Results:
+ * A double-precision scale reading. If the value is outside the legal
+ * range for the scale then it's rounded to the nearest end of the scale.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+double
+TkScalePixelToValue(
+ register TkScale *scalePtr, /* Information about widget. */
+ int x, int y) /* Coordinates of point within window. */
+{
+ double value, pixelRange;
+
+ if (scalePtr->orient == ORIENT_VERTICAL) {
+ pixelRange = Tk_Height(scalePtr->tkwin) - scalePtr->sliderLength
+ - 2*scalePtr->inset - 2*scalePtr->borderWidth;
+ value = y;
+ } else {
+ pixelRange = Tk_Width(scalePtr->tkwin) - scalePtr->sliderLength
+ - 2*scalePtr->inset - 2*scalePtr->borderWidth;
+ value = x;
+ }
+
+ if (pixelRange <= 0) {
+ /*
+ * Not enough room for the slider to actually slide: just return the
+ * scale's current value.
+ */
+
+ return scalePtr->value;
+ }
+ value -= scalePtr->sliderLength/2 + scalePtr->inset
+ + scalePtr->borderWidth;
+ value /= pixelRange;
+ if (value < 0) {
+ value = 0;
+ }
+ if (value > 1) {
+ value = 1;
+ }
+ value = scalePtr->fromValue +
+ value * (scalePtr->toValue - scalePtr->fromValue);
+ return TkRoundValueToResolution(scalePtr, value);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkScaleValueToPixel --
+ *
+ * Given a reading of the scale, return the x-coordinate or y-coordinate
+ * corresponding to that reading, depending on whether the scale is
+ * vertical or horizontal, respectively.
+ *
+ * Results:
+ * An integer value giving the pixel location corresponding to reading.
+ * The value is restricted to lie within the defined range for the scale.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkScaleValueToPixel(
+ register TkScale *scalePtr, /* Information about widget. */
+ double value) /* Reading of the widget. */
+{
+ int y, pixelRange;
+ double valueRange;
+
+ valueRange = scalePtr->toValue - scalePtr->fromValue;
+ pixelRange = ((scalePtr->orient == ORIENT_VERTICAL)
+ ? Tk_Height(scalePtr->tkwin) : Tk_Width(scalePtr->tkwin))
+ - scalePtr->sliderLength - 2*scalePtr->inset - 2*scalePtr->borderWidth;
+ if (valueRange == 0) {
+ y = 0;
+ } else {
+ y = ScaleRound((value - scalePtr->fromValue) * pixelRange
+ / valueRange);
+ if (y < 0) {
+ y = 0;
+ } else if (y > pixelRange) {
+ y = pixelRange;
+ }
+ }
+ y += scalePtr->sliderLength/2 + scalePtr->inset + scalePtr->borderWidth;
+ return y;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkScale.h b/tk8.6/generic/tkScale.h
new file mode 100644
index 0000000..e68b786
--- /dev/null
+++ b/tk8.6/generic/tkScale.h
@@ -0,0 +1,243 @@
+/*
+ * tkScale.h --
+ *
+ * Declarations of types and functions used to implement the scale
+ * widget.
+ *
+ * Copyright (c) 1996 by Sun Microsystems, Inc.
+ * Copyright (c) 1999-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.
+ */
+
+#ifndef _TKSCALE
+#define _TKSCALE
+
+#ifndef _TKINT
+#include "tkInt.h"
+#endif
+
+/*
+ * Legal values for the "orient" field of TkScale records.
+ */
+
+enum orient {
+ ORIENT_HORIZONTAL, ORIENT_VERTICAL
+};
+
+/*
+ * Legal values for the "state" field of TkScale records.
+ */
+
+enum state {
+ STATE_ACTIVE, STATE_DISABLED, STATE_NORMAL
+};
+
+/*
+ * A data structure of the following type is kept for each scale widget
+ * managed by this file:
+ */
+
+typedef struct TkScale {
+ Tk_Window tkwin; /* Window that embodies the scale. NULL means
+ * that the window has been destroyed but the
+ * data structures haven't yet been cleaned
+ * up.*/
+ Display *display; /* Display containing widget. Used, among
+ * other things, so that resources can be
+ * freed even after tkwin has gone away. */
+ Tcl_Interp *interp; /* Interpreter associated with scale. */
+ Tcl_Command widgetCmd; /* Token for scale's widget command. */
+ Tk_OptionTable optionTable; /* Table that defines configuration options
+ * available for this widget. */
+ enum orient orient; /* Orientation for window (vertical or
+ * horizontal). */
+ int width; /* Desired narrow dimension of scale, in
+ * pixels. */
+ int length; /* Desired long dimension of scale, in
+ * pixels. */
+ double value; /* Current value of scale. */
+ Tcl_Obj *varNamePtr; /* Name of variable or NULL. If non-NULL,
+ * scale's value tracks the contents of this
+ * variable and vice versa. */
+ double fromValue; /* Value corresponding to left or top of
+ * scale. */
+ double toValue; /* Value corresponding to right or bottom of
+ * scale. */
+ double tickInterval; /* Distance between tick marks; 0 means don't
+ * display any tick marks. */
+ double resolution; /* If > 0, all values are rounded to an even
+ * multiple of this value. */
+ int digits; /* Number of significant digits to print in
+ * values. 0 means we get to choose the number
+ * based on resolution and/or the range of the
+ * scale. */
+ char valueFormat[16]; /* Sprintf conversion specifier computed from
+ * digits and other information. */
+ char tickFormat[16]; /* Sprintf conversion specifier computed from
+ * tick interval. */
+ double bigIncrement; /* Amount to use for large increments to scale
+ * value. (0 means we pick a value). */
+ char *command; /* Command prefix to use when invoking Tcl
+ * commands because the scale value changed.
+ * NULL means don't invoke commands. */
+ int repeatDelay; /* How long to wait before auto-repeating on
+ * scrolling actions (in ms). */
+ int repeatInterval; /* Interval between autorepeats (in ms). */
+ char *label; /* Label to display above or to right of
+ * scale; NULL means don't display a label. */
+ int labelLength; /* Number of non-NULL chars. in label. */
+ enum state state; /* Values are active, normal, or disabled.
+ * Value of scale cannot be changed when
+ * disabled. */
+
+ /*
+ * Information used when displaying widget:
+ */
+
+ int borderWidth; /* Width of 3-D border around window. */
+ Tk_3DBorder bgBorder; /* Used for drawing slider and other
+ * background areas. */
+ Tk_3DBorder activeBorder; /* For drawing the slider when active. */
+ int sliderRelief; /* Is slider to be drawn raised, sunken,
+ * etc. */
+ XColor *troughColorPtr; /* Color for drawing trough. */
+ GC troughGC; /* For drawing trough. */
+ GC copyGC; /* Used for copying from pixmap onto screen */
+ Tk_Font tkfont; /* Information about text font, or NULL. */
+ XColor *textColorPtr; /* Color for drawing text. */
+ GC textGC; /* GC for drawing text in normal mode. */
+ int relief; /* Indicates whether window as a whole is
+ * raised, sunken, or flat. */
+ int highlightWidth; /* Width in pixels of highlight to draw around
+ * widget when it has the focus. <= 0 means
+ * don't draw a highlight. */
+ Tk_3DBorder highlightBorder;/* Value of -highlightbackground option:
+ * specifies background with which to draw 3-D
+ * default ring and focus highlight area when
+ * highlight is off. */
+ XColor *highlightColorPtr; /* Color for drawing traversal highlight. */
+ int inset; /* Total width of all borders, including
+ * traversal highlight and 3-D border.
+ * Indicates how much interior stuff must be
+ * offset from outside edges to leave room for
+ * borders. */
+ int sliderLength; /* Length of slider, measured in pixels along
+ * long dimension of scale. */
+ int showValue; /* Non-zero means to display the scale value
+ * below or to the left of the slider; zero
+ * means don't display the value. */
+
+ /*
+ * Layout information for horizontal scales, assuming that window gets the
+ * size it requested:
+ */
+
+ int horizLabelY; /* Y-coord at which to draw label. */
+ int horizValueY; /* Y-coord at which to draw value text. */
+ int horizTroughY; /* Y-coord of top of slider trough. */
+ int horizTickY; /* Y-coord at which to draw tick text. */
+ /*
+ * Layout information for vertical scales, assuming that window gets the
+ * size it requested:
+ */
+
+ int vertTickRightX; /* X-location of right side of tick-marks. */
+ int vertValueRightX; /* X-location of right side of value string. */
+ int vertTroughX; /* X-location of scale's slider trough. */
+ int vertLabelX; /* X-location of origin of label. */
+
+ /*
+ * Miscellaneous information:
+ */
+
+ int fontHeight; /* Height of scale font. */
+ Tk_Cursor cursor; /* Current cursor for window, or NULL. */
+ Tcl_Obj *takeFocusPtr; /* Value of -takefocus option; not used in the
+ * C code, but used by keyboard traversal
+ * scripts. May be NULL. */
+ int flags; /* Various flags; see below for
+ * definitions. */
+} TkScale;
+
+/*
+ * Flag bits for scales:
+ *
+ * REDRAW_SLIDER - 1 means slider (and numerical readout) need to
+ * be redrawn.
+ * REDRAW_OTHER - 1 means other stuff besides slider and value
+ * need to be redrawn.
+ * REDRAW_ALL - 1 means the entire widget needs to be redrawn.
+ * REDRAW_PENDING - 1 means any sort of redraw is pending
+ * ACTIVE - 1 means the widget is active (the mouse is in
+ * its window).
+ * INVOKE_COMMAND - 1 means the scale's command needs to be
+ * invoked during the next redisplay (the value
+ * of the scale has changed since the last time
+ * the command was invoked).
+ * SETTING_VAR - 1 means that the associated variable is being
+ * set by us, so there's no need for ScaleVarProc
+ * to do anything.
+ * NEVER_SET - 1 means that the scale's value has never been
+ * set before (so must invoke -command and set
+ * associated variable even if the value doesn't
+ * appear to have changed).
+ * GOT_FOCUS - 1 means that the focus is currently in this
+ * widget.
+ * SCALE_DELETED - 1 means the scale widget is being deleted
+ */
+
+#define REDRAW_SLIDER (1<<0)
+#define REDRAW_OTHER (1<<1)
+#define REDRAW_ALL (REDRAW_OTHER|REDRAW_SLIDER)
+#define REDRAW_PENDING (1<<2)
+#define ACTIVE (1<<3)
+#define INVOKE_COMMAND (1<<4)
+#define SETTING_VAR (1<<5)
+#define NEVER_SET (1<<6)
+#define GOT_FOCUS (1<<7)
+#define SCALE_DELETED (1<<8)
+
+/*
+ * Symbolic values for the active parts of a slider. These are the values that
+ * may be returned by the ScaleElement procedure.
+ */
+
+#define OTHER 0
+#define TROUGH1 1
+#define SLIDER 2
+#define TROUGH2 3
+
+/*
+ * Space to leave between scale area and text, and between text and edge of
+ * window.
+ */
+
+#define SPACING 2
+
+/*
+ * The tick values are all displayed with the same number of decimal places.
+ * This number of decimal places is such that the displayed values are all
+ * accurate to within the following proportion of a tick interval.
+ */
+
+#define TICK_VALUES_DISPLAY_ACCURACY 0.2
+
+/*
+ * Declaration of procedures used in the implementation of the scale widget.
+ */
+
+MODULE_SCOPE void TkEventuallyRedrawScale(TkScale *scalePtr, int what);
+MODULE_SCOPE double TkRoundValueToResolution(TkScale *scalePtr, double value);
+MODULE_SCOPE double TkRoundIntervalToResolution(TkScale *scalePtr, double value);
+MODULE_SCOPE TkScale * TkpCreateScale(Tk_Window tkwin);
+MODULE_SCOPE void TkpDestroyScale(TkScale *scalePtr);
+MODULE_SCOPE void TkpDisplayScale(ClientData clientData);
+MODULE_SCOPE int TkpScaleElement(TkScale *scalePtr, int x, int y);
+MODULE_SCOPE void TkScaleSetValue(TkScale *scalePtr, double value,
+ int setVar, int invokeCommand);
+MODULE_SCOPE double TkScalePixelToValue(TkScale *scalePtr, int x, int y);
+MODULE_SCOPE int TkScaleValueToPixel(TkScale *scalePtr, double value);
+
+#endif /* _TKSCALE */
diff --git a/tk8.6/generic/tkScrollbar.c b/tk8.6/generic/tkScrollbar.c
new file mode 100644
index 0000000..9a85532
--- /dev/null
+++ b/tk8.6/generic/tkScrollbar.c
@@ -0,0 +1,703 @@
+/*
+ * tkScrollbar.c --
+ *
+ * This module implements a scrollbar widgets for the Tk toolkit. A
+ * scrollbar displays a slider and two arrows; mouse clicks on features
+ * within the scrollbar cause scrolling commands to be invoked.
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "tkInt.h"
+#include "tkScrollbar.h"
+#include "default.h"
+
+/*
+ * Custom option for handling "-orient"
+ */
+
+static const Tk_CustomOption orientOption = {
+ TkOrientParseProc, TkOrientPrintProc, NULL
+};
+
+/* non-const space for "-width" default value for scrollbars */
+char tkDefScrollbarWidth[TCL_INTEGER_SPACE] = DEF_SCROLLBAR_WIDTH;
+
+/*
+ * Information used for argv parsing.
+ */
+
+static const Tk_ConfigSpec configSpecs[] = {
+ {TK_CONFIG_BORDER, "-activebackground", "activeBackground", "Foreground",
+ DEF_SCROLLBAR_ACTIVE_BG_COLOR, Tk_Offset(TkScrollbar, activeBorder),
+ TK_CONFIG_COLOR_ONLY, NULL},
+ {TK_CONFIG_BORDER, "-activebackground", "activeBackground", "Foreground",
+ DEF_SCROLLBAR_ACTIVE_BG_MONO, Tk_Offset(TkScrollbar, activeBorder),
+ TK_CONFIG_MONO_ONLY, NULL},
+ {TK_CONFIG_RELIEF, "-activerelief", "activeRelief", "Relief",
+ DEF_SCROLLBAR_ACTIVE_RELIEF, Tk_Offset(TkScrollbar, activeRelief), 0, NULL},
+ {TK_CONFIG_BORDER, "-background", "background", "Background",
+ DEF_SCROLLBAR_BG_COLOR, Tk_Offset(TkScrollbar, bgBorder),
+ TK_CONFIG_COLOR_ONLY, NULL},
+ {TK_CONFIG_BORDER, "-background", "background", "Background",
+ DEF_SCROLLBAR_BG_MONO, Tk_Offset(TkScrollbar, bgBorder),
+ TK_CONFIG_MONO_ONLY, NULL},
+ {TK_CONFIG_SYNONYM, "-bd", "borderWidth", NULL, NULL, 0, 0, NULL},
+ {TK_CONFIG_SYNONYM, "-bg", "background", NULL, NULL, 0, 0, NULL},
+ {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ DEF_SCROLLBAR_BORDER_WIDTH, Tk_Offset(TkScrollbar, borderWidth), 0, NULL},
+ {TK_CONFIG_STRING, "-command", "command", "Command",
+ DEF_SCROLLBAR_COMMAND, Tk_Offset(TkScrollbar, command),
+ TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor",
+ DEF_SCROLLBAR_CURSOR, Tk_Offset(TkScrollbar, cursor), TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_PIXELS, "-elementborderwidth", "elementBorderWidth",
+ "BorderWidth", DEF_SCROLLBAR_EL_BORDER_WIDTH,
+ Tk_Offset(TkScrollbar, elementBorderWidth), 0, NULL},
+ {TK_CONFIG_COLOR, "-highlightbackground", "highlightBackground",
+ "HighlightBackground", DEF_SCROLLBAR_HIGHLIGHT_BG,
+ Tk_Offset(TkScrollbar, highlightBgColorPtr), 0, NULL},
+ {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
+ DEF_SCROLLBAR_HIGHLIGHT,
+ Tk_Offset(TkScrollbar, highlightColorPtr), 0, NULL},
+ {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness",
+ "HighlightThickness",
+ DEF_SCROLLBAR_HIGHLIGHT_WIDTH, Tk_Offset(TkScrollbar, highlightWidth), 0, NULL},
+ {TK_CONFIG_BOOLEAN, "-jump", "jump", "Jump",
+ DEF_SCROLLBAR_JUMP, Tk_Offset(TkScrollbar, jump), 0, NULL},
+ {TK_CONFIG_CUSTOM, "-orient", "orient", "Orient",
+ DEF_SCROLLBAR_ORIENT, Tk_Offset(TkScrollbar, vertical), 0,
+ &orientOption},
+ {TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
+ DEF_SCROLLBAR_RELIEF, Tk_Offset(TkScrollbar, relief), 0, NULL},
+ {TK_CONFIG_INT, "-repeatdelay", "repeatDelay", "RepeatDelay",
+ DEF_SCROLLBAR_REPEAT_DELAY, Tk_Offset(TkScrollbar, repeatDelay), 0, NULL},
+ {TK_CONFIG_INT, "-repeatinterval", "repeatInterval", "RepeatInterval",
+ DEF_SCROLLBAR_REPEAT_INTERVAL, Tk_Offset(TkScrollbar, repeatInterval), 0, NULL},
+ {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus",
+ DEF_SCROLLBAR_TAKE_FOCUS, Tk_Offset(TkScrollbar, takeFocus),
+ TK_CONFIG_NULL_OK, NULL},
+ {TK_CONFIG_COLOR, "-troughcolor", "troughColor", "Background",
+ DEF_SCROLLBAR_TROUGH_COLOR, Tk_Offset(TkScrollbar, troughColorPtr),
+ TK_CONFIG_COLOR_ONLY, NULL},
+ {TK_CONFIG_COLOR, "-troughcolor", "troughColor", "Background",
+ DEF_SCROLLBAR_TROUGH_MONO, Tk_Offset(TkScrollbar, troughColorPtr),
+ TK_CONFIG_MONO_ONLY, NULL},
+ {TK_CONFIG_PIXELS, "-width", "width", "Width",
+ tkDefScrollbarWidth, Tk_Offset(TkScrollbar, width), 0, NULL},
+ {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}
+};
+
+/*
+ * Forward declarations for functions defined later in this file:
+ */
+
+static int ConfigureScrollbar(Tcl_Interp *interp,
+ TkScrollbar *scrollPtr, int objc,
+ Tcl_Obj *const objv[], int flags);
+static void ScrollbarCmdDeletedProc(ClientData clientData);
+static int ScrollbarWidgetObjCmd(ClientData clientData,
+ Tcl_Interp *, int objc, Tcl_Obj *const objv[]);
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_ScrollbarObjCmd --
+ *
+ * This function is invoked to process the "scrollbar" 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_ScrollbarObjCmd(
+ ClientData clientData, /* Main window associated with interpreter. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument strings. */
+{
+ Tk_Window tkwin = clientData;
+ register TkScrollbar *scrollPtr;
+ Tk_Window newWin;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?");
+ return TCL_ERROR;
+ }
+
+ newWin = Tk_CreateWindowFromPath(interp, tkwin, Tcl_GetString(objv[1]), NULL);
+ if (newWin == NULL) {
+ return TCL_ERROR;
+ }
+
+ Tk_SetClass(newWin, "Scrollbar");
+ scrollPtr = TkpCreateScrollbar(newWin);
+
+ Tk_SetClassProcs(newWin, &tkpScrollbarProcs, scrollPtr);
+
+ /*
+ * Initialize fields that won't be initialized by ConfigureScrollbar, or
+ * which ConfigureScrollbar expects to have reasonable values (e.g.
+ * resource pointers).
+ */
+
+ scrollPtr->tkwin = newWin;
+ scrollPtr->display = Tk_Display(newWin);
+ scrollPtr->interp = interp;
+ scrollPtr->widgetCmd = Tcl_CreateObjCommand(interp,
+ Tk_PathName(scrollPtr->tkwin), ScrollbarWidgetObjCmd,
+ scrollPtr, ScrollbarCmdDeletedProc);
+ scrollPtr->vertical = 0;
+ scrollPtr->width = 0;
+ scrollPtr->command = NULL;
+ scrollPtr->commandSize = 0;
+ scrollPtr->repeatDelay = 0;
+ scrollPtr->repeatInterval = 0;
+ scrollPtr->borderWidth = 0;
+ scrollPtr->bgBorder = NULL;
+ scrollPtr->activeBorder = NULL;
+ scrollPtr->troughColorPtr = NULL;
+ scrollPtr->relief = TK_RELIEF_FLAT;
+ scrollPtr->highlightWidth = 0;
+ scrollPtr->highlightBgColorPtr = NULL;
+ scrollPtr->highlightColorPtr = NULL;
+ scrollPtr->inset = 0;
+ scrollPtr->elementBorderWidth = -1;
+ scrollPtr->arrowLength = 0;
+ scrollPtr->sliderFirst = 0;
+ scrollPtr->sliderLast = 0;
+ scrollPtr->activeField = 0;
+ scrollPtr->activeRelief = TK_RELIEF_RAISED;
+ scrollPtr->totalUnits = 0;
+ scrollPtr->windowUnits = 0;
+ scrollPtr->firstUnit = 0;
+ scrollPtr->lastUnit = 0;
+ scrollPtr->firstFraction = 0.0;
+ scrollPtr->lastFraction = 0.0;
+ scrollPtr->cursor = NULL;
+ scrollPtr->takeFocus = NULL;
+ scrollPtr->flags = 0;
+
+ if (ConfigureScrollbar(interp, scrollPtr, objc-2, objv+2, 0) != TCL_OK) {
+ Tk_DestroyWindow(scrollPtr->tkwin);
+ return TCL_ERROR;
+ }
+
+ Tcl_SetObjResult(interp, TkNewWindowObj(scrollPtr->tkwin));
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ScrollbarWidgetObjCmd --
+ *
+ * This function is invoked to process the Tcl command that corresponds
+ * to a widget managed by this module. See the user documentation for
+ * details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+ScrollbarWidgetObjCmd(
+ ClientData clientData, /* Information about scrollbar widget. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument strings. */
+{
+ register TkScrollbar *scrollPtr = clientData;
+ int result = TCL_OK;
+ int length, cmdIndex;
+ static const char *const commandNames[] = {
+ "activate", "cget", "configure", "delta", "fraction",
+ "get", "identify", "set", NULL
+ };
+ enum command {
+ COMMAND_ACTIVATE, COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DELTA,
+ COMMAND_FRACTION, COMMAND_GET, COMMAND_IDENTIFY, COMMAND_SET
+ };
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ /*
+ * Parse the command by looking up the second argument in the list of
+ * valid subcommand names
+ */
+
+ result = Tcl_GetIndexFromObj(interp, objv[1], commandNames,
+ "option", 0, &cmdIndex);
+ if (result != TCL_OK) {
+ return result;
+ }
+ Tcl_Preserve(scrollPtr);
+ switch (cmdIndex) {
+ case COMMAND_ACTIVATE: {
+ int oldActiveField, c;
+
+ if (objc == 2) {
+ const char *zone = "";
+
+ switch (scrollPtr->activeField) {
+ case TOP_ARROW: zone = "arrow1"; break;
+ case SLIDER: zone = "slider"; break;
+ case BOTTOM_ARROW: zone = "arrow2"; break;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(zone, -1));
+ goto done;
+ }
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "activate element");
+ goto error;
+ }
+ c = Tcl_GetStringFromObj(objv[2], &length)[0];
+ oldActiveField = scrollPtr->activeField;
+ if ((c == 'a') && (strcmp(Tcl_GetString(objv[2]), "arrow1") == 0)) {
+ scrollPtr->activeField = TOP_ARROW;
+ } else if ((c == 'a') && (strcmp(Tcl_GetString(objv[2]), "arrow2") == 0)) {
+ scrollPtr->activeField = BOTTOM_ARROW;
+ } else if ((c == 's') && (strncmp(Tcl_GetString(objv[2]), "slider", length) == 0)) {
+ scrollPtr->activeField = SLIDER;
+ } else {
+ scrollPtr->activeField = OUTSIDE;
+ }
+ if (oldActiveField != scrollPtr->activeField) {
+ TkScrollbarEventuallyRedraw(scrollPtr);
+ }
+ break;
+ }
+ case COMMAND_CGET: {
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "cget option");
+ goto error;
+ }
+ result = Tk_ConfigureValue(interp, scrollPtr->tkwin,
+ configSpecs, (char *) scrollPtr, Tcl_GetString(objv[2]), 0);
+ break;
+ }
+ case COMMAND_CONFIGURE: {
+ if (objc == 2) {
+ result = Tk_ConfigureInfo(interp, scrollPtr->tkwin,
+ configSpecs, (char *) scrollPtr, NULL, 0);
+ } else if (objc == 3) {
+ result = Tk_ConfigureInfo(interp, scrollPtr->tkwin,
+ configSpecs, (char *) scrollPtr, Tcl_GetString(objv[2]), 0);
+ } else {
+ result = ConfigureScrollbar(interp, scrollPtr, objc-2,
+ objv+2, TK_CONFIG_ARGV_ONLY);
+ }
+ break;
+ }
+ case COMMAND_DELTA: {
+ int xDelta, yDelta, pixels, length;
+ double fraction;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "delta xDelta yDelta");
+ goto error;
+ }
+ if ((Tcl_GetIntFromObj(interp, objv[2], &xDelta) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[3], &yDelta) != TCL_OK)) {
+ goto error;
+ }
+ if (scrollPtr->vertical) {
+ pixels = yDelta;
+ length = Tk_Height(scrollPtr->tkwin) - 1
+ - 2*(scrollPtr->arrowLength + scrollPtr->inset);
+ } else {
+ pixels = xDelta;
+ length = Tk_Width(scrollPtr->tkwin) - 1
+ - 2*(scrollPtr->arrowLength + scrollPtr->inset);
+ }
+ if (length == 0) {
+ fraction = 0.0;
+ } else {
+ fraction = ((double) pixels / (double) length);
+ }
+ Tcl_SetObjResult(interp, Tcl_NewDoubleObj(fraction));
+ break;
+ }
+ case COMMAND_FRACTION: {
+ int x, y, pos, length;
+ double fraction;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "fraction x y");
+ goto error;
+ }
+ if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {
+ goto error;
+ }
+ if (scrollPtr->vertical) {
+ pos = y - (scrollPtr->arrowLength + scrollPtr->inset);
+ length = Tk_Height(scrollPtr->tkwin) - 1
+ - 2*(scrollPtr->arrowLength + scrollPtr->inset);
+ } else {
+ pos = x - (scrollPtr->arrowLength + scrollPtr->inset);
+ length = Tk_Width(scrollPtr->tkwin) - 1
+ - 2*(scrollPtr->arrowLength + scrollPtr->inset);
+ }
+ if (length == 0) {
+ fraction = 0.0;
+ } else {
+ fraction = ((double) pos / (double) length);
+ }
+ if (fraction < 0) {
+ fraction = 0;
+ } else if (fraction > 1.0) {
+ fraction = 1.0;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewDoubleObj(fraction));
+ break;
+ }
+ case COMMAND_GET: {
+ Tcl_Obj *resObjs[4];
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "get");
+ goto error;
+ }
+ if (scrollPtr->flags & NEW_STYLE_COMMANDS) {
+ resObjs[0] = Tcl_NewDoubleObj(scrollPtr->firstFraction);
+ resObjs[1] = Tcl_NewDoubleObj(scrollPtr->lastFraction);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(2, resObjs));
+ } else {
+ resObjs[0] = Tcl_NewIntObj(scrollPtr->totalUnits);
+ resObjs[1] = Tcl_NewIntObj(scrollPtr->windowUnits);
+ resObjs[2] = Tcl_NewIntObj(scrollPtr->firstUnit);
+ resObjs[3] = Tcl_NewIntObj(scrollPtr->lastUnit);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(4, resObjs));
+ }
+ break;
+ }
+ case COMMAND_IDENTIFY: {
+ int x, y;
+ const char *zone = "";
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "identify x y");
+ goto error;
+ }
+ if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {
+ goto error;
+ }
+ switch (TkpScrollbarPosition(scrollPtr, x, y)) {
+ case TOP_ARROW: zone = "arrow1"; break;
+ case TOP_GAP: zone = "trough1"; break;
+ case SLIDER: zone = "slider"; break;
+ case BOTTOM_GAP: zone = "trough2"; break;
+ case BOTTOM_ARROW: zone = "arrow2"; break;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(zone, -1));
+ break;
+ }
+ case COMMAND_SET: {
+ int totalUnits, windowUnits, firstUnit, lastUnit;
+
+ if (objc == 4) {
+ double first, last;
+
+ if (Tcl_GetDoubleFromObj(interp, objv[2], &first) != TCL_OK) {
+ goto error;
+ }
+ if (Tcl_GetDoubleFromObj(interp, objv[3], &last) != TCL_OK) {
+ goto error;
+ }
+ if (first < 0) {
+ scrollPtr->firstFraction = 0;
+ } else if (first > 1.0) {
+ scrollPtr->firstFraction = 1.0;
+ } else {
+ scrollPtr->firstFraction = first;
+ }
+ if (last < scrollPtr->firstFraction) {
+ scrollPtr->lastFraction = scrollPtr->firstFraction;
+ } else if (last > 1.0) {
+ scrollPtr->lastFraction = 1.0;
+ } else {
+ scrollPtr->lastFraction = last;
+ }
+ scrollPtr->flags |= NEW_STYLE_COMMANDS;
+ } else if (objc == 6) {
+ if (Tcl_GetIntFromObj(interp, objv[2], &totalUnits) != TCL_OK) {
+ goto error;
+ }
+ if (totalUnits < 0) {
+ totalUnits = 0;
+ }
+ if (Tcl_GetIntFromObj(interp, objv[3], &windowUnits) != TCL_OK) {
+ goto error;
+ }
+ if (windowUnits < 0) {
+ windowUnits = 0;
+ }
+ if (Tcl_GetIntFromObj(interp, objv[4], &firstUnit) != TCL_OK) {
+ goto error;
+ }
+ if (Tcl_GetIntFromObj(interp, objv[5], &lastUnit) != TCL_OK) {
+ goto error;
+ }
+ if (totalUnits > 0) {
+ if (lastUnit < firstUnit) {
+ lastUnit = firstUnit;
+ }
+ } else {
+ firstUnit = lastUnit = 0;
+ }
+ scrollPtr->totalUnits = totalUnits;
+ scrollPtr->windowUnits = windowUnits;
+ scrollPtr->firstUnit = firstUnit;
+ scrollPtr->lastUnit = lastUnit;
+ if (scrollPtr->totalUnits == 0) {
+ scrollPtr->firstFraction = 0.0;
+ scrollPtr->lastFraction = 1.0;
+ } else {
+ scrollPtr->firstFraction = ((double) firstUnit)/totalUnits;
+ scrollPtr->lastFraction = ((double) (lastUnit+1))/totalUnits;
+ }
+ scrollPtr->flags &= ~NEW_STYLE_COMMANDS;
+ } else {
+ Tcl_WrongNumArgs(interp, 1, objv, "set firstFraction lastFraction");
+ Tcl_AppendResult(interp, " or \"", Tcl_GetString(objv[0]),
+ " set totalUnits windowUnits firstUnit lastUnit\"", NULL);
+ goto error;
+ }
+ TkpComputeScrollbarGeometry(scrollPtr);
+ TkScrollbarEventuallyRedraw(scrollPtr);
+ break;
+ }
+ }
+
+ done:
+ Tcl_Release(scrollPtr);
+ return result;
+
+ error:
+ Tcl_Release(scrollPtr);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConfigureScrollbar --
+ *
+ * This function is called to process an argv/argc list, plus the Tk
+ * option database, in order to configure (or reconfigure) a scrollbar
+ * widget.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If TCL_ERROR is returned,
+ * then the interp's result contains an error message.
+ *
+ * Side effects:
+ * Configuration information, such as colors, border width, etc. get set
+ * for scrollPtr; old resources get freed, if there were any.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ConfigureScrollbar(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ register TkScrollbar *scrollPtr,
+ /* Information about widget; may or may not
+ * already have values for some fields. */
+ int objc, /* Number of valid entries in argv. */
+ Tcl_Obj *const objv[], /* Arguments. */
+ int flags) /* Flags to pass to Tk_ConfigureWidget. */
+{
+ if (Tk_ConfigureWidget(interp, scrollPtr->tkwin, configSpecs, objc,
+ (const char **)objv, (char *) scrollPtr, flags|TK_CONFIG_OBJS) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * A few options need special processing, such as setting the background
+ * from a 3-D border.
+ */
+
+ if (scrollPtr->command != NULL) {
+ scrollPtr->commandSize = (int) strlen(scrollPtr->command);
+ } else {
+ scrollPtr->commandSize = 0;
+ }
+
+ /*
+ * Configure platform specific options.
+ */
+
+ TkpConfigureScrollbar(scrollPtr);
+
+ /*
+ * 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.
+ */
+
+ TkpComputeScrollbarGeometry(scrollPtr);
+ TkScrollbarEventuallyRedraw(scrollPtr);
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkScrollbarEventProc --
+ *
+ * This function 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.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkScrollbarEventProc(
+ ClientData clientData, /* Information about window. */
+ XEvent *eventPtr) /* Information about event. */
+{
+ TkScrollbar *scrollPtr = clientData;
+
+ if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {
+ TkScrollbarEventuallyRedraw(scrollPtr);
+ } else if (eventPtr->type == DestroyNotify) {
+ TkpDestroyScrollbar(scrollPtr);
+ if (scrollPtr->tkwin != NULL) {
+ scrollPtr->tkwin = NULL;
+ Tcl_DeleteCommandFromToken(scrollPtr->interp,
+ scrollPtr->widgetCmd);
+ }
+ if (scrollPtr->flags & REDRAW_PENDING) {
+ Tcl_CancelIdleCall(TkpDisplayScrollbar, scrollPtr);
+ }
+ /*
+ * Free up all the stuff that requires special handling, then let
+ * Tk_FreeOptions handle all the standard option-related stuff.
+ */
+
+ Tk_FreeOptions(configSpecs, (char*) scrollPtr, scrollPtr->display, 0);
+ Tcl_EventuallyFree(scrollPtr, TCL_DYNAMIC);
+ } else if (eventPtr->type == ConfigureNotify) {
+ TkpComputeScrollbarGeometry(scrollPtr);
+ TkScrollbarEventuallyRedraw(scrollPtr);
+ } else if (eventPtr->type == FocusIn) {
+ if (eventPtr->xfocus.detail != NotifyInferior) {
+ scrollPtr->flags |= GOT_FOCUS;
+ if (scrollPtr->highlightWidth > 0) {
+ TkScrollbarEventuallyRedraw(scrollPtr);
+ }
+ }
+ } else if (eventPtr->type == FocusOut) {
+ if (eventPtr->xfocus.detail != NotifyInferior) {
+ scrollPtr->flags &= ~GOT_FOCUS;
+ if (scrollPtr->highlightWidth > 0) {
+ TkScrollbarEventuallyRedraw(scrollPtr);
+ }
+ }
+ } else if (eventPtr->type == MapNotify) {
+ TkScrollbarEventuallyRedraw(scrollPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ScrollbarCmdDeletedProc --
+ *
+ * This function is invoked when a widget command is deleted. If the
+ * widget isn't already in the process of being destroyed, this command
+ * destroys it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The widget is destroyed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ScrollbarCmdDeletedProc(
+ ClientData clientData) /* Pointer to widget record for widget. */
+{
+ TkScrollbar *scrollPtr = clientData;
+ Tk_Window tkwin = scrollPtr->tkwin;
+
+ /*
+ * This function could be invoked either because the window was destroyed
+ * and the command was then deleted (in which case tkwin is NULL) or
+ * because the command was deleted, and then this function destroys the
+ * widget.
+ */
+
+ if (tkwin != NULL) {
+ scrollPtr->tkwin = NULL;
+ Tk_DestroyWindow(tkwin);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkScrollbarEventuallyRedraw --
+ *
+ * Arrange for one or more of the fields of a scrollbar to be redrawn.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkScrollbarEventuallyRedraw(
+ TkScrollbar *scrollPtr) /* Information about widget. */
+{
+ if ((scrollPtr->tkwin == NULL) || !Tk_IsMapped(scrollPtr->tkwin)) {
+ return;
+ }
+ if (!(scrollPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(TkpDisplayScrollbar, scrollPtr);
+ scrollPtr->flags |= REDRAW_PENDING;
+ }
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkScrollbar.h b/tk8.6/generic/tkScrollbar.h
new file mode 100644
index 0000000..2d521ae
--- /dev/null
+++ b/tk8.6/generic/tkScrollbar.h
@@ -0,0 +1,183 @@
+/*
+ * tkScrollbar.h --
+ *
+ * Declarations of types and functions used to implement the scrollbar
+ * widget.
+ *
+ * Copyright (c) 1996 by Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef _TKSCROLLBAR
+#define _TKSCROLLBAR
+
+#ifndef _TKINT
+#include "tkInt.h"
+#endif
+
+/*
+ * A data structure of the following type is kept for each scrollbar widget.
+ */
+
+typedef struct TkScrollbar {
+ Tk_Window tkwin; /* Window that embodies the scrollbar. NULL
+ * means that the window has been destroyed
+ * but the data structures haven't yet been
+ * cleaned up.*/
+ Display *display; /* Display containing widget. Used, among
+ * other things, so that resources can be
+ * freed even after tkwin has gone away. */
+ Tcl_Interp *interp; /* Interpreter associated with scrollbar. */
+ Tcl_Command widgetCmd; /* Token for scrollbar's widget command. */
+ int vertical; /* Non-zero means vertical orientation
+ * requested, zero means horizontal. */
+ int width; /* Desired narrow dimension of scrollbar, in
+ * pixels. */
+ char *command; /* Command prefix to use when invoking
+ * scrolling commands. NULL means don't invoke
+ * commands. Malloc'ed. */
+ int commandSize; /* Number of non-NULL bytes in command. */
+ int repeatDelay; /* How long to wait before auto-repeating on
+ * scrolling actions (in ms). */
+ int repeatInterval; /* Interval between autorepeats (in ms). */
+ int jump; /* Value of -jump option. */
+
+ /*
+ * Information used when displaying widget:
+ */
+
+ int borderWidth; /* Width of 3-D borders. */
+ Tk_3DBorder bgBorder; /* Used for drawing background (all flat
+ * surfaces except for trough). */
+ Tk_3DBorder activeBorder; /* For drawing backgrounds when active (i.e.
+ * when mouse is positioned over element). */
+ XColor *troughColorPtr; /* Color for drawing trough. */
+ int relief; /* Indicates whether window as a whole is
+ * raised, sunken, or flat. */
+ int highlightWidth; /* Width in pixels of highlight to draw around
+ * widget when it has the focus. <= 0 means
+ * don't draw a highlight. */
+ XColor *highlightBgColorPtr;
+ /* Color for drawing traversal highlight area
+ * when highlight is off. */
+ XColor *highlightColorPtr; /* Color for drawing traversal highlight. */
+ int inset; /* Total width of all borders, including
+ * traversal highlight and 3-D border.
+ * Indicates how much interior stuff must be
+ * offset from outside edges to leave room for
+ * borders. */
+ int elementBorderWidth; /* Width of border to draw around elements
+ * inside scrollbar (arrows and slider). -1
+ * means use borderWidth. */
+ int arrowLength; /* Length of arrows along long dimension of
+ * scrollbar, including space for a small gap
+ * between the arrow and the slider.
+ * Recomputed on window size changes. */
+ int sliderFirst; /* Pixel coordinate of top or left edge of
+ * slider area, including border. */
+ int sliderLast; /* Coordinate of pixel just after bottom or
+ * right edge of slider area, including
+ * border. */
+ int activeField; /* Names field to be displayed in active
+ * colors, such as TOP_ARROW, or 0 for no
+ * field. */
+ int activeRelief; /* Value of -activeRelief option: relief to
+ * use for active element. */
+
+ /*
+ * Information describing the application related to the scrollbar. This
+ * information is provided by the application by invoking the "set" widget
+ * command. This information can now be provided in two ways: the "old"
+ * form (totalUnits, windowUnits, firstUnit, and lastUnit), or the "new"
+ * form (firstFraction and lastFraction). FirstFraction and lastFraction
+ * will always be valid, but the old-style information is only valid if
+ * the NEW_STYLE_COMMANDS flag is 0.
+ */
+
+ int totalUnits; /* Total dimension of application, in units.
+ * Valid only if the NEW_STYLE_COMMANDS flag
+ * isn't set. */
+ int windowUnits; /* Maximum number of units that can be
+ * displayed in the window at once. Valid only
+ * if the NEW_STYLE_COMMANDS flag isn't set. */
+ int firstUnit; /* Number of last unit visible in
+ * application's window. Valid only if the
+ * NEW_STYLE_COMMANDS flag isn't set. */
+ int lastUnit; /* Index of last unit visible in window.
+ * Valid only if the NEW_STYLE_COMMANDS flag
+ * isn't set. */
+ double firstFraction; /* Position of first visible thing in window,
+ * specified as a fraction between 0 and
+ * 1.0. */
+ double lastFraction; /* Position of last visible thing in window,
+ * specified as a fraction between 0 and
+ * 1.0. */
+
+ /*
+ * Miscellaneous information:
+ */
+
+ Tk_Cursor cursor; /* Current cursor for window, or NULL. */
+ char *takeFocus; /* Value of -takefocus option; not used in the
+ * C code, but used by keyboard traversal
+ * scripts. Malloc'ed, but may be NULL. */
+ int flags; /* Various flags; see below for
+ * definitions. */
+} TkScrollbar;
+
+/*
+ * Legal values for "activeField" field of Scrollbar structures. These are
+ * also the return values from the ScrollbarPosition function.
+ */
+
+#define OUTSIDE 0
+#define TOP_ARROW 1
+#define TOP_GAP 2
+#define SLIDER 3
+#define BOTTOM_GAP 4
+#define BOTTOM_ARROW 5
+
+/*
+ * Flag bits for scrollbars:
+ *
+ * REDRAW_PENDING: Non-zero means a DoWhenIdle handler has
+ * already been queued to redraw this window.
+ * NEW_STYLE_COMMANDS: Non-zero means the new style of commands
+ * should be used to communicate with the widget:
+ * ".t yview scroll 2 lines", instead of
+ * ".t yview 40", for example.
+ * GOT_FOCUS: Non-zero means this window has the input
+ * focus.
+ */
+
+#define REDRAW_PENDING 1
+#define NEW_STYLE_COMMANDS 2
+#define GOT_FOCUS 4
+
+/*
+ * Declaration of scrollbar class functions structure
+ * and default scrollbar width, for use in configSpec.
+ */
+
+MODULE_SCOPE const Tk_ClassProcs tkpScrollbarProcs;
+MODULE_SCOPE char tkDefScrollbarWidth[TCL_INTEGER_SPACE];
+
+/*
+ * Declaration of functions used in the implementation of the scrollbar
+ * widget.
+ */
+
+MODULE_SCOPE void TkScrollbarEventProc(ClientData clientData,
+ XEvent *eventPtr);
+MODULE_SCOPE void TkScrollbarEventuallyRedraw(TkScrollbar *scrollPtr);
+MODULE_SCOPE void TkpComputeScrollbarGeometry(TkScrollbar *scrollPtr);
+MODULE_SCOPE TkScrollbar *TkpCreateScrollbar(Tk_Window tkwin);
+MODULE_SCOPE void TkpDestroyScrollbar(TkScrollbar *scrollPtr);
+MODULE_SCOPE void TkpDisplayScrollbar(ClientData clientData);
+MODULE_SCOPE void TkpConfigureScrollbar(TkScrollbar *scrollPtr);
+MODULE_SCOPE int TkpScrollbarPosition(TkScrollbar *scrollPtr,
+ int x, int y);
+
+#endif /* _TKSCROLLBAR */
diff --git a/tk8.6/generic/tkSelect.c b/tk8.6/generic/tkSelect.c
new file mode 100644
index 0000000..c64c93f
--- /dev/null
+++ b/tk8.6/generic/tkSelect.c
@@ -0,0 +1,1603 @@
+/*
+ * tkSelect.c --
+ *
+ * This file manages the selection for the Tk toolkit, translating
+ * between the standard X ICCCM conventions and Tcl commands.
+ *
+ * Copyright (c) 1990-1993 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "tkInt.h"
+#include "tkSelect.h"
+
+/*
+ * When a selection handler is set up by invoking "selection handle", one of
+ * the following data structures is set up to hold information about the
+ * command to invoke and its interpreter.
+ */
+
+typedef struct {
+ Tcl_Interp *interp; /* Interpreter in which to invoke command. */
+ int cmdLength; /* # of non-NULL bytes in command. */
+ int charOffset; /* The offset of the next char to retrieve. */
+ int byteOffset; /* The expected byte offset of the next
+ * chunk. */
+ char buffer[4]; /* A buffer to hold part of a UTF character
+ * that is split across chunks. */
+ char command[1]; /* Command to invoke. Actual space is
+ * allocated as large as necessary. This must
+ * be the last entry in the structure. */
+} CommandInfo;
+
+/*
+ * When selection ownership is claimed with the "selection own" Tcl command,
+ * one of the following structures is created to record the Tcl command to be
+ * executed when the selection is lost again.
+ */
+
+typedef struct LostCommand {
+ Tcl_Interp *interp; /* Interpreter in which to invoke command. */
+ Tcl_Obj *cmdObj; /* Reference to command to invoke. */
+} LostCommand;
+
+/*
+ * The structure below is used to keep each thread's pending list separate.
+ */
+
+typedef struct {
+ TkSelInProgress *pendingPtr;
+ /* Topmost search in progress, or NULL if
+ * none. */
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+
+/*
+ * Forward declarations for functions defined in this file:
+ */
+
+static int HandleTclCommand(ClientData clientData,
+ int offset, char *buffer, int maxBytes);
+static void LostSelection(ClientData clientData);
+static int SelGetProc(ClientData clientData,
+ Tcl_Interp *interp, const char *portion);
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CreateSelHandler --
+ *
+ * This function is called to register a function as the handler for
+ * selection requests of a particular target type on a particular window
+ * for a particular selection.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+
+ * In the future, whenever the selection is in tkwin's window and someone
+ * requests the selection in the form given by target, proc will be
+ * invoked to provide part or all of the selection in the given form. If
+ * there was already a handler declared for the given window, target and
+ * selection type, then it is replaced. Proc should have the following
+ * form:
+ *
+ * int
+ * proc(
+ * ClientData clientData,
+ * int offset,
+ * char *buffer,
+ * int maxBytes)
+ * {
+ * }
+ *
+ * The clientData argument to proc will be the same as the clientData
+ * argument to this function. The offset argument indicates which portion
+ * of the selection to return: skip the first offset bytes. Buffer is a
+ * pointer to an area in which to place the converted selection, and
+ * maxBytes gives the number of bytes available at buffer. Proc should
+ * place the selection in buffer as a string, and return a count of the
+ * number of bytes of selection actually placed in buffer (not including
+ * the terminating NULL character). If the return value equals maxBytes,
+ * this is a sign that there is probably still more selection information
+ * available.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_CreateSelHandler(
+ Tk_Window tkwin, /* Token for window. */
+ Atom selection, /* Selection to be handled. */
+ Atom target, /* The kind of selection conversions that can
+ * be handled by proc, e.g. TARGETS or
+ * STRING. */
+ Tk_SelectionProc *proc, /* Function to invoke to convert selection to
+ * type "target". */
+ ClientData clientData, /* Value to pass to proc. */
+ Atom format) /* Format in which the selection information
+ * should be returned to the requestor.
+ * XA_STRING is best by far, but anything
+ * listed in the ICCCM will be tolerated
+ * (blech). */
+{
+ register TkSelHandler *selPtr;
+ TkWindow *winPtr = (TkWindow *) tkwin;
+
+ if (winPtr->dispPtr->multipleAtom == None) {
+ TkSelInit(tkwin);
+ }
+
+ /*
+ * See if there's already a handler for this target and selection on this
+ * window. If so, re-use it. If not, create a new one.
+ */
+
+ for (selPtr = winPtr->selHandlerList; ; selPtr = selPtr->nextPtr) {
+ if (selPtr == NULL) {
+ selPtr = ckalloc(sizeof(TkSelHandler));
+ selPtr->nextPtr = winPtr->selHandlerList;
+ winPtr->selHandlerList = selPtr;
+ break;
+ }
+ if ((selPtr->selection == selection) && (selPtr->target == target)) {
+ /*
+ * Special case: when replacing handler created by "selection
+ * handle", free up memory. Should there be a callback to allow
+ * other clients to do this too?
+ */
+
+ if (selPtr->proc == HandleTclCommand) {
+ ckfree(selPtr->clientData);
+ }
+ break;
+ }
+ }
+ selPtr->selection = selection;
+ selPtr->target = target;
+ selPtr->format = format;
+ selPtr->proc = proc;
+ selPtr->clientData = clientData;
+ if (format == XA_STRING) {
+ selPtr->size = 8;
+ } else {
+ selPtr->size = 32;
+ }
+
+ if ((target == XA_STRING) && (winPtr->dispPtr->utf8Atom != (Atom) 0)) {
+ /*
+ * If the user asked for a STRING handler and we understand
+ * UTF8_STRING, we implicitly create a UTF8_STRING handler for them.
+ */
+
+ target = winPtr->dispPtr->utf8Atom;
+ for (selPtr = winPtr->selHandlerList; ; selPtr = selPtr->nextPtr) {
+ if (selPtr == NULL) {
+ selPtr = ckalloc(sizeof(TkSelHandler));
+ selPtr->nextPtr = winPtr->selHandlerList;
+ winPtr->selHandlerList = selPtr;
+ selPtr->selection = selection;
+ selPtr->target = target;
+ selPtr->format = target; /* We want UTF8_STRING format */
+ selPtr->proc = proc;
+ if (selPtr->proc == HandleTclCommand) {
+ /*
+ * The clientData is selection controlled memory, so we
+ * should make a copy for this selPtr.
+ */
+
+ unsigned cmdInfoLen = Tk_Offset(CommandInfo, command) + 1 +
+ ((CommandInfo *)clientData)->cmdLength;
+
+ selPtr->clientData = ckalloc(cmdInfoLen);
+ memcpy(selPtr->clientData, clientData, cmdInfoLen);
+ } else {
+ selPtr->clientData = clientData;
+ }
+ selPtr->size = 8;
+ break;
+ }
+ if (selPtr->selection==selection && selPtr->target==target) {
+ /*
+ * Looks like we had a utf-8 target already. Leave it alone.
+ */
+
+ break;
+ }
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_DeleteSelHandler --
+ *
+ * Remove the selection handler for a given window, target, and
+ * selection, if it exists.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The selection handler for tkwin and target is removed. If there is no
+ * such handler then nothing happens.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_DeleteSelHandler(
+ Tk_Window tkwin, /* Token for window. */
+ Atom selection, /* The selection whose handler is to be
+ * removed. */
+ Atom target) /* The target whose selection handler is to be
+ * removed. */
+{
+ TkWindow *winPtr = (TkWindow *) tkwin;
+ register TkSelHandler *selPtr, *prevPtr;
+ register TkSelInProgress *ipPtr;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ /*
+ * Find the selection handler to be deleted, or return if it doesn't
+ * exist.
+ */
+
+ for (selPtr = winPtr->selHandlerList, prevPtr = NULL; ;
+ prevPtr = selPtr, selPtr = selPtr->nextPtr) {
+ if (selPtr == NULL) {
+ return;
+ }
+ if ((selPtr->selection == selection) && (selPtr->target == target)) {
+ break;
+ }
+ }
+
+ /*
+ * If ConvertSelection is processing this handler, tell it that the
+ * handler is dead.
+ */
+
+ for (ipPtr = tsdPtr->pendingPtr; ipPtr != NULL;
+ ipPtr = ipPtr->nextPtr) {
+ if (ipPtr->selPtr == selPtr) {
+ ipPtr->selPtr = NULL;
+ }
+ }
+
+ /*
+ * Free resources associated with the handler.
+ */
+
+ if (prevPtr == NULL) {
+ winPtr->selHandlerList = selPtr->nextPtr;
+ } else {
+ prevPtr->nextPtr = selPtr->nextPtr;
+ }
+
+ if ((target == XA_STRING) && (winPtr->dispPtr->utf8Atom != (Atom) 0)) {
+ /*
+ * If the user asked for a STRING handler and we understand
+ * UTF8_STRING, we may have implicitly created a UTF8_STRING handler
+ * for them. Look for it and delete it as necessary.
+ */
+
+ TkSelHandler *utf8selPtr;
+
+ target = winPtr->dispPtr->utf8Atom;
+ for (utf8selPtr = winPtr->selHandlerList; utf8selPtr != NULL;
+ utf8selPtr = utf8selPtr->nextPtr) {
+ if ((utf8selPtr->selection == selection)
+ && (utf8selPtr->target == target)) {
+ break;
+ }
+ }
+ if (utf8selPtr != NULL) {
+ if ((utf8selPtr->format == target)
+ && (utf8selPtr->proc == selPtr->proc)
+ && (utf8selPtr->size == selPtr->size)) {
+ /*
+ * This recursive call is OK, because we've changed the value
+ * of 'target'.
+ */
+
+ Tk_DeleteSelHandler(tkwin, selection, target);
+ }
+ }
+ }
+
+ if (selPtr->proc == HandleTclCommand) {
+ /*
+ * Mark the CommandInfo as deleted and free it if we can.
+ */
+
+ ((CommandInfo *) selPtr->clientData)->interp = NULL;
+ Tcl_EventuallyFree(selPtr->clientData, TCL_DYNAMIC);
+ }
+ ckfree(selPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_OwnSelection --
+ *
+ * Arrange for tkwin to become the owner of a selection.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * From now on, requests for the selection will be directed to functions
+ * associated with tkwin (they must have been declared with calls to
+ * Tk_CreateSelHandler). When the selection is lost by this window, proc
+ * will be invoked (see the manual entry for details). This function may
+ * invoke callbacks, including Tcl scripts, so any calling function
+ * should be reentrant at the point where Tk_OwnSelection is invoked.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_OwnSelection(
+ Tk_Window tkwin, /* Window to become new selection owner. */
+ Atom selection, /* Selection that window should own. */
+ Tk_LostSelProc *proc, /* Function to call when selection is taken
+ * away from tkwin. */
+ ClientData clientData) /* Arbitrary one-word argument to pass to
+ * proc. */
+{
+ register TkWindow *winPtr = (TkWindow *) tkwin;
+ TkDisplay *dispPtr = winPtr->dispPtr;
+ TkSelectionInfo *infoPtr;
+ Tk_LostSelProc *clearProc = NULL;
+ ClientData clearData = NULL;/* Initialization needed only to prevent
+ * compiler warning. */
+
+ if (dispPtr->multipleAtom == None) {
+ TkSelInit(tkwin);
+ }
+ Tk_MakeWindowExist(tkwin);
+
+ /*
+ * This code is somewhat tricky. First, we find the specified selection on
+ * the selection list. If the previous owner is in this process, and is a
+ * different window, then we need to invoke the clearProc. However, it's
+ * dangerous to call the clearProc right now, because it could invoke a
+ * Tcl script that wrecks the current state (e.g. it could delete the
+ * window). To be safe, defer the call until the end of the function when
+ * we no longer care about the state.
+ */
+
+ for (infoPtr = dispPtr->selectionInfoPtr; infoPtr != NULL;
+ infoPtr = infoPtr->nextPtr) {
+ if (infoPtr->selection == selection) {
+ break;
+ }
+ }
+ if (infoPtr == NULL) {
+ infoPtr = ckalloc(sizeof(TkSelectionInfo));
+ infoPtr->selection = selection;
+ infoPtr->nextPtr = dispPtr->selectionInfoPtr;
+ dispPtr->selectionInfoPtr = infoPtr;
+ } else if (infoPtr->clearProc != NULL) {
+ if (infoPtr->owner != tkwin) {
+ clearProc = infoPtr->clearProc;
+ clearData = infoPtr->clearData;
+ } else if (infoPtr->clearProc == LostSelection) {
+ /*
+ * If the selection handler is one created by "selection own", be
+ * sure to free the record for it; otherwise there will be a
+ * memory leak.
+ */
+
+ ckfree(infoPtr->clearData);
+ }
+ }
+
+ infoPtr->owner = tkwin;
+ infoPtr->serial = NextRequest(winPtr->display);
+ infoPtr->clearProc = proc;
+ infoPtr->clearData = clientData;
+
+ /*
+ * Note that we are using CurrentTime, even though ICCCM recommends
+ * against this practice (the problem is that we don't necessarily have a
+ * valid time to use). We will not be able to retrieve a useful timestamp
+ * for the TIMESTAMP target later.
+ */
+
+ infoPtr->time = CurrentTime;
+
+ /*
+ * Note that we are not checking to see if the selection claim succeeded.
+ * If the ownership does not change, then the clearProc may never be
+ * invoked, and we will return incorrect information when queried for the
+ * current selection owner.
+ */
+
+ XSetSelectionOwner(winPtr->display, infoPtr->selection, winPtr->window,
+ infoPtr->time);
+
+ /*
+ * Now that we are done, we can invoke clearProc without running into
+ * reentrancy problems.
+ */
+
+ if (clearProc != NULL) {
+ clearProc(clearData);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_ClearSelection --
+ *
+ * Eliminate the specified selection on tkwin's display, if there is one.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The specified selection is cleared, so that future requests to
+ * retrieve it will fail until some application owns it again. This
+ * function invokes callbacks, possibly including Tcl scripts, so any
+ * calling function should be reentrant at the point Tk_ClearSelection is
+ * invoked.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_ClearSelection(
+ Tk_Window tkwin, /* Window that selects a display. */
+ Atom selection) /* Selection to be cancelled. */
+{
+ register TkWindow *winPtr = (TkWindow *) tkwin;
+ TkDisplay *dispPtr = winPtr->dispPtr;
+ TkSelectionInfo *infoPtr;
+ TkSelectionInfo *prevPtr;
+ TkSelectionInfo *nextPtr;
+ Tk_LostSelProc *clearProc = NULL;
+ ClientData clearData = NULL;/* Initialization needed only to prevent
+ * compiler warning. */
+
+ if (dispPtr->multipleAtom == None) {
+ TkSelInit(tkwin);
+ }
+
+ for (infoPtr = dispPtr->selectionInfoPtr, prevPtr = NULL;
+ infoPtr != NULL; infoPtr = nextPtr) {
+ nextPtr = infoPtr->nextPtr;
+ if (infoPtr->selection == selection) {
+ if (prevPtr == NULL) {
+ dispPtr->selectionInfoPtr = nextPtr;
+ } else {
+ prevPtr->nextPtr = nextPtr;
+ }
+ break;
+ }
+ prevPtr = infoPtr;
+ }
+
+ if (infoPtr != NULL) {
+ clearProc = infoPtr->clearProc;
+ clearData = infoPtr->clearData;
+ ckfree(infoPtr);
+ }
+ XSetSelectionOwner(winPtr->display, selection, None, CurrentTime);
+
+ if (clearProc != NULL) {
+ clearProc(clearData);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_GetSelection --
+ *
+ * Retrieve the value of a selection and pass it off (in pieces,
+ * possibly) to a given function.
+ *
+ * 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:
+ * The standard X11 protocols are used to retrieve the selection. When it
+ * arrives, it is passed to proc. If the selection is very large, it will
+ * be passed to proc in several pieces. Proc should have the following
+ * structure:
+ *
+ * int
+ * proc(
+ * ClientData clientData,
+ * Tcl_Interp *interp,
+ * char *portion)
+ * {
+ * }
+ *
+ * The interp and clientData arguments to proc will be the same as the
+ * corresponding arguments to Tk_GetSelection. The portion argument
+ * points to a character string containing part of the selection, and
+ * numBytes indicates the length of the portion, not including the
+ * terminating NULL character. If the selection arrives in several
+ * pieces, the "portion" arguments in separate calls will contain
+ * successive parts of the selection. Proc should normally return TCL_OK.
+ * If it detects an error then it should return TCL_ERROR and leave an
+ * error message in the interp's result; the remainder of the selection
+ * retrieval will be aborted.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_GetSelection(
+ 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, /* Function to call to process the selection,
+ * once it has been retrieved. */
+ ClientData clientData) /* Arbitrary value to pass to proc. */
+{
+ TkWindow *winPtr = (TkWindow *) tkwin;
+ TkDisplay *dispPtr = winPtr->dispPtr;
+ TkSelectionInfo *infoPtr;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (dispPtr->multipleAtom == None) {
+ TkSelInit(tkwin);
+ }
+
+ /*
+ * If the selection is owned by a window managed by this process, then
+ * call the retrieval function directly, rather than going through the X
+ * server (it's dangerous to go through the X server in this case because
+ * it could result in deadlock if an INCR-style selection results).
+ */
+
+ for (infoPtr = dispPtr->selectionInfoPtr; infoPtr != NULL;
+ infoPtr = infoPtr->nextPtr) {
+ if (infoPtr->selection == selection) {
+ break;
+ }
+ }
+ if (infoPtr != NULL) {
+ register TkSelHandler *selPtr;
+ int offset, result, count;
+ char buffer[TK_SEL_BYTES_AT_ONCE+1];
+ TkSelInProgress ip;
+
+ for (selPtr = ((TkWindow *) infoPtr->owner)->selHandlerList;
+ selPtr != NULL; selPtr = selPtr->nextPtr) {
+ if (selPtr->target==target && selPtr->selection==selection) {
+ break;
+ }
+ }
+ if (selPtr == NULL) {
+ Atom type;
+
+ count = TkSelDefaultSelection(infoPtr, target, buffer,
+ TK_SEL_BYTES_AT_ONCE, &type);
+ if (count > TK_SEL_BYTES_AT_ONCE) {
+ Tcl_Panic("selection handler returned too many bytes");
+ }
+ if (count < 0) {
+ goto cantget;
+ }
+ buffer[count] = 0;
+ result = proc(clientData, interp, buffer);
+ } else {
+ offset = 0;
+ result = TCL_OK;
+ ip.selPtr = selPtr;
+ ip.nextPtr = tsdPtr->pendingPtr;
+ tsdPtr->pendingPtr = &ip;
+ while (1) {
+ count = selPtr->proc(selPtr->clientData, offset, buffer,
+ TK_SEL_BYTES_AT_ONCE);
+ if ((count < 0) || (ip.selPtr == NULL)) {
+ tsdPtr->pendingPtr = ip.nextPtr;
+ goto cantget;
+ }
+ if (count > TK_SEL_BYTES_AT_ONCE) {
+ Tcl_Panic("selection handler returned too many bytes");
+ }
+ buffer[count] = '\0';
+ result = proc(clientData, interp, buffer);
+ if ((result != TCL_OK) || (count < TK_SEL_BYTES_AT_ONCE)
+ || (ip.selPtr == NULL)) {
+ break;
+ }
+ offset += count;
+ }
+ tsdPtr->pendingPtr = ip.nextPtr;
+ }
+ return result;
+ }
+
+ /*
+ * The selection is owned by some other process.
+ */
+
+ return TkSelGetSelection(interp, tkwin, selection, target, proc,
+ clientData);
+
+ cantget:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "%s selection doesn't exist or form \"%s\" not defined",
+ Tk_GetAtomName(tkwin, selection),
+ Tk_GetAtomName(tkwin, target)));
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_SelectionObjCmd --
+ *
+ * This function is invoked to process the "selection" 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_SelectionObjCmd(
+ 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 = clientData;
+ const char *path = NULL;
+ Atom selection;
+ const char *selName = NULL;
+ const char *string;
+ int count, index;
+ Tcl_Obj **objs;
+ static const char *const optionStrings[] = {
+ "clear", "get", "handle", "own", NULL
+ };
+ enum options {
+ SELECTION_CLEAR, SELECTION_GET, SELECTION_HANDLE, SELECTION_OWN
+ };
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch ((enum options) index) {
+ case SELECTION_CLEAR: {
+ static const char *const clearOptionStrings[] = {
+ "-displayof", "-selection", NULL
+ };
+ enum clearOptions { CLEAR_DISPLAYOF, CLEAR_SELECTION };
+ int clearIndex;
+
+ for (count = objc-2, objs = ((Tcl_Obj **)objv)+2; count > 0;
+ count-=2, objs+=2) {
+ string = Tcl_GetString(objs[0]);
+ if (string[0] != '-') {
+ break;
+ }
+ if (count < 2) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "value for \"%s\" missing", string));
+ Tcl_SetErrorCode(interp, "TK", "SELECTION", "VALUE", NULL);
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObj(interp, objs[0], clearOptionStrings,
+ "option", 0, &clearIndex) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch ((enum clearOptions) clearIndex) {
+ case CLEAR_DISPLAYOF:
+ path = Tcl_GetString(objs[1]);
+ break;
+ case CLEAR_SELECTION:
+ selName = Tcl_GetString(objs[1]);
+ break;
+ }
+ }
+
+ if (count == 1) {
+ path = Tcl_GetString(objs[0]);
+ } else if (count > 1) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?-option value ...?");
+ return TCL_ERROR;
+ }
+ if (path != NULL) {
+ tkwin = Tk_NameToWindow(interp, path, tkwin);
+ }
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ if (selName != NULL) {
+ selection = Tk_InternAtom(tkwin, selName);
+ } else {
+ selection = XA_PRIMARY;
+ }
+
+ Tk_ClearSelection(tkwin, selection);
+ break;
+ }
+
+ case SELECTION_GET: {
+ Atom target;
+ const char *targetName = NULL;
+ Tcl_DString selBytes;
+ int result;
+ static const char *const getOptionStrings[] = {
+ "-displayof", "-selection", "-type", NULL
+ };
+ enum getOptions { GET_DISPLAYOF, GET_SELECTION, GET_TYPE };
+ int getIndex;
+
+ for (count = objc-2, objs = ((Tcl_Obj **)objv)+2; count>0;
+ count-=2, objs+=2) {
+ string = Tcl_GetString(objs[0]);
+ if (string[0] != '-') {
+ break;
+ }
+ if (count < 2) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "value for \"%s\" missing", string));
+ Tcl_SetErrorCode(interp, "TK", "SELECTION", "VALUE", NULL);
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObj(interp, objs[0], getOptionStrings,
+ "option", 0, &getIndex) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch ((enum getOptions) getIndex) {
+ case GET_DISPLAYOF:
+ path = Tcl_GetString(objs[1]);
+ break;
+ case GET_SELECTION:
+ selName = Tcl_GetString(objs[1]);
+ break;
+ case GET_TYPE:
+ targetName = Tcl_GetString(objs[1]);
+ break;
+ }
+ }
+
+ if (path != NULL) {
+ tkwin = Tk_NameToWindow(interp, path, tkwin);
+ }
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ if (selName != NULL) {
+ selection = Tk_InternAtom(tkwin, selName);
+ } else {
+ selection = XA_PRIMARY;
+ }
+ if (count > 1) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?-option value ...?");
+ return TCL_ERROR;
+ } else if (count == 1) {
+ target = Tk_InternAtom(tkwin, Tcl_GetString(objs[0]));
+ } else if (targetName != NULL) {
+ target = Tk_InternAtom(tkwin, targetName);
+ } else {
+ target = XA_STRING;
+ }
+
+ Tcl_DStringInit(&selBytes);
+ result = Tk_GetSelection(interp, tkwin, selection, target,
+ SelGetProc, &selBytes);
+ if (result == TCL_OK) {
+ Tcl_DStringResult(interp, &selBytes);
+ } else {
+ Tcl_DStringFree(&selBytes);
+ }
+ return result;
+ }
+
+ case SELECTION_HANDLE: {
+ Atom target, format;
+ const char *targetName = NULL;
+ const char *formatName = NULL;
+ register CommandInfo *cmdInfoPtr;
+ int cmdLength;
+ static const char *const handleOptionStrings[] = {
+ "-format", "-selection", "-type", NULL
+ };
+ enum handleOptions {
+ HANDLE_FORMAT, HANDLE_SELECTION, HANDLE_TYPE
+ };
+ int handleIndex;
+
+ for (count = objc-2, objs = ((Tcl_Obj **)objv)+2; count > 0;
+ count-=2, objs+=2) {
+ string = Tcl_GetString(objs[0]);
+ if (string[0] != '-') {
+ break;
+ }
+ if (count < 2) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "value for \"%s\" missing", string));
+ Tcl_SetErrorCode(interp, "TK", "SELECTION", "VALUE", NULL);
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObj(interp, objs[0],handleOptionStrings,
+ "option", 0, &handleIndex) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch ((enum handleOptions) handleIndex) {
+ case HANDLE_FORMAT:
+ formatName = Tcl_GetString(objs[1]);
+ break;
+ case HANDLE_SELECTION:
+ selName = Tcl_GetString(objs[1]);
+ break;
+ case HANDLE_TYPE:
+ targetName = Tcl_GetString(objs[1]);
+ break;
+ }
+ }
+
+ if ((count < 2) || (count > 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-option value ...? window command");
+ return TCL_ERROR;
+ }
+ tkwin = Tk_NameToWindow(interp, Tcl_GetString(objs[0]), tkwin);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ if (selName != NULL) {
+ selection = Tk_InternAtom(tkwin, selName);
+ } else {
+ selection = XA_PRIMARY;
+ }
+
+ if (count > 2) {
+ target = Tk_InternAtom(tkwin, Tcl_GetString(objs[2]));
+ } else if (targetName != NULL) {
+ target = Tk_InternAtom(tkwin, targetName);
+ } else {
+ target = XA_STRING;
+ }
+ if (count > 3) {
+ format = Tk_InternAtom(tkwin, Tcl_GetString(objs[3]));
+ } else if (formatName != NULL) {
+ format = Tk_InternAtom(tkwin, formatName);
+ } else {
+ format = XA_STRING;
+ }
+ string = Tcl_GetStringFromObj(objs[1], &cmdLength);
+ if (cmdLength == 0) {
+ Tk_DeleteSelHandler(tkwin, selection, target);
+ } else {
+ cmdInfoPtr = ckalloc(Tk_Offset(CommandInfo, command)
+ + 1 + cmdLength);
+ cmdInfoPtr->interp = interp;
+ cmdInfoPtr->charOffset = 0;
+ cmdInfoPtr->byteOffset = 0;
+ cmdInfoPtr->buffer[0] = '\0';
+ cmdInfoPtr->cmdLength = cmdLength;
+ memcpy(cmdInfoPtr->command, string, cmdLength + 1);
+ Tk_CreateSelHandler(tkwin, selection, target, HandleTclCommand,
+ cmdInfoPtr, format);
+ }
+ return TCL_OK;
+ }
+
+ case SELECTION_OWN: {
+ register LostCommand *lostPtr;
+ Tcl_Obj *commandObj = NULL;
+ static const char *const ownOptionStrings[] = {
+ "-command", "-displayof", "-selection", NULL
+ };
+ enum ownOptions { OWN_COMMAND, OWN_DISPLAYOF, OWN_SELECTION };
+ int ownIndex;
+
+ for (count = objc-2, objs = ((Tcl_Obj **)objv)+2; count > 0;
+ count-=2, objs+=2) {
+ string = Tcl_GetString(objs[0]);
+ if (string[0] != '-') {
+ break;
+ }
+ if (count < 2) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "value for \"%s\" missing", string));
+ Tcl_SetErrorCode(interp, "TK", "SELECTION", "VALUE", NULL);
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObj(interp, objs[0], ownOptionStrings,
+ "option", 0, &ownIndex) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch ((enum ownOptions) ownIndex) {
+ case OWN_COMMAND:
+ commandObj = objs[1];
+ break;
+ case OWN_DISPLAYOF:
+ path = Tcl_GetString(objs[1]);
+ break;
+ case OWN_SELECTION:
+ selName = Tcl_GetString(objs[1]);
+ break;
+ }
+ }
+
+ if (count > 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?-option value ...? ?window?");
+ return TCL_ERROR;
+ }
+ if (selName != NULL) {
+ selection = Tk_InternAtom(tkwin, selName);
+ } else {
+ selection = XA_PRIMARY;
+ }
+
+ if (count == 0) {
+ TkSelectionInfo *infoPtr;
+ TkWindow *winPtr;
+
+ if (path != NULL) {
+ tkwin = Tk_NameToWindow(interp, path, tkwin);
+ }
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ winPtr = (TkWindow *) tkwin;
+ for (infoPtr = winPtr->dispPtr->selectionInfoPtr;
+ infoPtr != NULL; infoPtr = infoPtr->nextPtr) {
+ if (infoPtr->selection == selection) {
+ break;
+ }
+ }
+
+ /*
+ * Ignore the internal clipboard window.
+ */
+
+ if ((infoPtr != NULL)
+ && (infoPtr->owner != winPtr->dispPtr->clipWindow)) {
+ Tcl_SetObjResult(interp, TkNewWindowObj(infoPtr->owner));
+ }
+ return TCL_OK;
+ }
+
+ tkwin = Tk_NameToWindow(interp, Tcl_GetString(objs[0]), tkwin);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ if (count == 2) {
+ commandObj = objs[1];
+ }
+ if (commandObj == NULL) {
+ Tk_OwnSelection(tkwin, selection, NULL, NULL);
+ return TCL_OK;
+ }
+ lostPtr = ckalloc(sizeof(LostCommand));
+ lostPtr->interp = interp;
+ lostPtr->cmdObj = commandObj;
+ Tcl_IncrRefCount(commandObj);
+ Tk_OwnSelection(tkwin, selection, LostSelection, lostPtr);
+ return TCL_OK;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkSelGetInProgress --
+ *
+ * This function returns a pointer to the thread-local list of pending
+ * searches.
+ *
+ * Results:
+ * The return value is a pointer to the first search in progress, or NULL
+ * if there are none.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkSelInProgress *
+TkSelGetInProgress(void)
+{
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ return tsdPtr->pendingPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkSelSetInProgress --
+ *
+ * This function is used to set the thread-local list of pending
+ * searches. It is required because the pending list is kept in thread
+ * local storage.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+void
+TkSelSetInProgress(
+ TkSelInProgress *pendingPtr)
+{
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ tsdPtr->pendingPtr = pendingPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkSelDeadWindow --
+ *
+ * This function is invoked just before a TkWindow is deleted. It
+ * performs selection-related cleanup.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Frees up memory associated with the selection.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkSelDeadWindow(
+ register TkWindow *winPtr) /* Window that's being deleted. */
+{
+ register TkSelHandler *selPtr;
+ register TkSelInProgress *ipPtr;
+ TkSelectionInfo *infoPtr, *prevPtr, *nextPtr;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ /*
+ * While deleting all the handlers, be careful to check whether
+ * ConvertSelection or TkSelPropProc are about to process one of the
+ * deleted handlers.
+ */
+
+ while (winPtr->selHandlerList != NULL) {
+ selPtr = winPtr->selHandlerList;
+ winPtr->selHandlerList = selPtr->nextPtr;
+ for (ipPtr = tsdPtr->pendingPtr; ipPtr != NULL;
+ ipPtr = ipPtr->nextPtr) {
+ if (ipPtr->selPtr == selPtr) {
+ ipPtr->selPtr = NULL;
+ }
+ }
+ if (selPtr->proc == HandleTclCommand) {
+ /*
+ * Mark the CommandInfo as deleted and free it when we can.
+ */
+
+ ((CommandInfo *) selPtr->clientData)->interp = NULL;
+ Tcl_EventuallyFree(selPtr->clientData, TCL_DYNAMIC);
+ }
+ ckfree(selPtr);
+ }
+
+ /*
+ * Remove selections owned by window being deleted.
+ */
+
+ for (infoPtr = winPtr->dispPtr->selectionInfoPtr, prevPtr = NULL;
+ infoPtr != NULL; infoPtr = nextPtr) {
+ nextPtr = infoPtr->nextPtr;
+ if (infoPtr->owner == (Tk_Window) winPtr) {
+ if (infoPtr->clearProc == LostSelection) {
+ ckfree(infoPtr->clearData);
+ }
+ ckfree(infoPtr);
+ infoPtr = prevPtr;
+ if (prevPtr == NULL) {
+ winPtr->dispPtr->selectionInfoPtr = nextPtr;
+ } else {
+ prevPtr->nextPtr = nextPtr;
+ }
+ }
+ prevPtr = infoPtr;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkSelInit --
+ *
+ * Initialize selection-related information for a display.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Selection-related information is initialized.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkSelInit(
+ Tk_Window tkwin) /* Window token (used to find display to
+ * initialize). */
+{
+ register TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+
+ /*
+ * Fetch commonly-used atoms.
+ */
+
+ dispPtr->multipleAtom = Tk_InternAtom(tkwin, "MULTIPLE");
+ dispPtr->incrAtom = Tk_InternAtom(tkwin, "INCR");
+ dispPtr->targetsAtom = Tk_InternAtom(tkwin, "TARGETS");
+ dispPtr->timestampAtom = Tk_InternAtom(tkwin, "TIMESTAMP");
+ dispPtr->textAtom = Tk_InternAtom(tkwin, "TEXT");
+ dispPtr->compoundTextAtom = Tk_InternAtom(tkwin, "COMPOUND_TEXT");
+ dispPtr->applicationAtom = Tk_InternAtom(tkwin, "TK_APPLICATION");
+ dispPtr->windowAtom = Tk_InternAtom(tkwin, "TK_WINDOW");
+ dispPtr->clipboardAtom = Tk_InternAtom(tkwin, "CLIPBOARD");
+ dispPtr->atomPairAtom = Tk_InternAtom(tkwin, "ATOM_PAIR");
+
+ /*
+ * Using UTF8_STRING instead of the XA_UTF8_STRING macro allows us to
+ * support older X servers that didn't have UTF8_STRING yet. This is
+ * necessary on Unix systems. For more information, see:
+ * http://www.cl.cam.ac.uk/~mgk25/unicode.html#x11
+ */
+
+#if !defined(_WIN32)
+ dispPtr->utf8Atom = Tk_InternAtom(tkwin, "UTF8_STRING");
+#else
+ dispPtr->utf8Atom = (Atom) 0;
+#endif
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkSelClearSelection --
+ *
+ * This function is invoked to process a SelectionClear event.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Invokes the clear function for the window which lost the
+ * selection.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkSelClearSelection(
+ Tk_Window tkwin, /* Window for which event was targeted. */
+ register XEvent *eventPtr) /* X SelectionClear event. */
+{
+ register TkWindow *winPtr = (TkWindow *) tkwin;
+ TkDisplay *dispPtr = winPtr->dispPtr;
+ TkSelectionInfo *infoPtr;
+ TkSelectionInfo *prevPtr;
+
+ /*
+ * Invoke clear function for window that just lost the selection. This
+ * code is a bit tricky, because any callbacks due to selection changes
+ * between windows managed by the process have already been made. Thus,
+ * ignore the event unless it refers to the window that's currently the
+ * selection owner and the event was generated after the server saw the
+ * SetSelectionOwner request.
+ */
+
+ for (infoPtr = dispPtr->selectionInfoPtr, prevPtr = NULL;
+ infoPtr != NULL; infoPtr = infoPtr->nextPtr) {
+ if (infoPtr->selection == eventPtr->xselectionclear.selection) {
+ break;
+ }
+ prevPtr = infoPtr;
+ }
+
+ if (infoPtr != NULL && (infoPtr->owner == tkwin) &&
+ (eventPtr->xselectionclear.serial >= (unsigned) infoPtr->serial)) {
+ if (prevPtr == NULL) {
+ dispPtr->selectionInfoPtr = infoPtr->nextPtr;
+ } else {
+ prevPtr->nextPtr = infoPtr->nextPtr;
+ }
+
+ /*
+ * Because of reentrancy problems, calling clearProc must be done
+ * after the infoPtr has been removed from the selectionInfoPtr list
+ * (clearProc could modify the list, e.g. by creating a new
+ * selection).
+ */
+
+ if (infoPtr->clearProc != NULL) {
+ infoPtr->clearProc(infoPtr->clearData);
+ }
+ ckfree(infoPtr);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * SelGetProc --
+ *
+ * This function is invoked to process pieces of the selection as they
+ * arrive during "selection get" commands.
+ *
+ * Results:
+ * Always returns TCL_OK.
+ *
+ * Side effects:
+ * Bytes get appended to the dynamic string pointed to by the clientData
+ * argument.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+SelGetProc(
+ ClientData clientData, /* Dynamic string holding partially assembled
+ * selection. */
+ Tcl_Interp *interp, /* Interpreter used for error reporting (not
+ * used). */
+ const char *portion) /* New information to be appended. */
+{
+ Tcl_DStringAppend(clientData, portion, -1);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HandleTclCommand --
+ *
+ * This function acts as selection handler for handlers created by the
+ * "selection handle" command. It invokes a Tcl command to retrieve the
+ * selection.
+ *
+ * Results:
+ * The return value is a count of the number of bytes actually stored at
+ * buffer, or -1 if an error occurs while executing the Tcl command to
+ * retrieve the selection.
+ *
+ * Side effects:
+ * None except for things done by the Tcl command.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+HandleTclCommand(
+ ClientData clientData, /* Information about command to execute. */
+ int offset, /* Return selection bytes starting at this
+ * offset. */
+ char *buffer, /* Place to store converted selection. */
+ int maxBytes) /* Maximum # of bytes to store at buffer. */
+{
+ CommandInfo *cmdInfoPtr = clientData;
+ int length;
+ Tcl_Obj *command;
+ const char *string;
+ Tcl_Interp *interp = cmdInfoPtr->interp;
+ Tcl_InterpState savedState;
+ int extraBytes, charOffset, count, numChars, code;
+ const char *p;
+
+ /*
+ * We must also protect the interpreter and the command from being deleted
+ * too soon.
+ */
+
+ Tcl_Preserve(clientData);
+ Tcl_Preserve(interp);
+
+ /*
+ * Compute the proper byte offset in the case where the last chunk split a
+ * character.
+ */
+
+ if (offset == cmdInfoPtr->byteOffset) {
+ charOffset = cmdInfoPtr->charOffset;
+ extraBytes = strlen(cmdInfoPtr->buffer);
+ if (extraBytes > 0) {
+ strcpy(buffer, cmdInfoPtr->buffer);
+ maxBytes -= extraBytes;
+ buffer += extraBytes;
+ }
+ } else {
+ cmdInfoPtr->byteOffset = 0;
+ cmdInfoPtr->charOffset = 0;
+ extraBytes = 0;
+ charOffset = 0;
+ }
+
+ /*
+ * First, generate a command by taking the command string and appending
+ * the offset and maximum # of bytes.
+ */
+
+ command = Tcl_ObjPrintf("%s %d %d",
+ cmdInfoPtr->command, charOffset, maxBytes);
+ Tcl_IncrRefCount(command);
+
+ /*
+ * Execute the command. Be sure to restore the state of the interpreter
+ * after executing the command.
+ */
+
+ savedState = Tcl_SaveInterpState(interp, TCL_OK);
+ code = Tcl_EvalObjEx(interp, command, TCL_EVAL_GLOBAL);
+ Tcl_DecrRefCount(command);
+ if (code == TCL_OK) {
+ /*
+ * TODO: This assumes that bytes are characters; that's not true!
+ */
+
+ string = Tcl_GetStringFromObj(Tcl_GetObjResult(interp), &length);
+ count = (length > maxBytes) ? maxBytes : length;
+ memcpy(buffer, string, (size_t) count);
+ buffer[count] = '\0';
+
+ /*
+ * Update the partial character information for the next retrieval if
+ * the command has not been deleted.
+ */
+
+ if (cmdInfoPtr->interp != NULL) {
+ if (length <= maxBytes) {
+ cmdInfoPtr->charOffset += Tcl_NumUtfChars(string, -1);
+ cmdInfoPtr->buffer[0] = '\0';
+ } else {
+ p = string;
+ string += count;
+ numChars = 0;
+ while (p < string) {
+ p = Tcl_UtfNext(p);
+ numChars++;
+ }
+ cmdInfoPtr->charOffset += numChars;
+ length = p - string;
+ if (length > 0) {
+ strncpy(cmdInfoPtr->buffer, string, (size_t) length);
+ }
+ cmdInfoPtr->buffer[length] = '\0';
+ }
+ cmdInfoPtr->byteOffset += count + extraBytes;
+ }
+ count += extraBytes;
+ } else {
+ /*
+ * Something went wrong. Log errors as background errors, and silently
+ * drop everything else.
+ */
+
+ if (code == TCL_ERROR) {
+ Tcl_AddErrorInfo(interp, "\n (command handling selection)");
+ Tcl_BackgroundException(interp, code);
+ }
+ count = -1;
+ }
+ (void) Tcl_RestoreInterpState(interp, savedState);
+
+ Tcl_Release(clientData);
+ Tcl_Release(interp);
+ return count;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkSelDefaultSelection --
+ *
+ * This function is called to generate selection information for a few
+ * standard targets such as TIMESTAMP and TARGETS. It is invoked only if
+ * no handler has been declared by the application.
+ *
+ * Results:
+ * If "target" is a standard target understood by this function, the
+ * selection is converted to that form and stored as a character string
+ * in buffer. The type of the selection (e.g. STRING or ATOM) is stored
+ * in *typePtr, and the return value is a count of the # of non-NULL
+ * bytes at buffer. If the target wasn't understood, or if there isn't
+ * enough space at buffer to hold the entire selection (no INCR-mode
+ * transfers for this stuff!), then -1 is returned.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkSelDefaultSelection(
+ TkSelectionInfo *infoPtr, /* Info about selection being retrieved. */
+ Atom target, /* Desired form of selection. */
+ char *buffer, /* Place to put selection characters. */
+ int maxBytes, /* Maximum # of bytes to store at buffer. */
+ Atom *typePtr) /* Store here the type of the selection, for
+ * use in converting to proper X format. */
+{
+ register TkWindow *winPtr = (TkWindow *) infoPtr->owner;
+ TkDisplay *dispPtr = winPtr->dispPtr;
+
+ if (target == dispPtr->timestampAtom) {
+ if (maxBytes < 20) {
+ return -1;
+ }
+ sprintf(buffer, "0x%x", (unsigned int) infoPtr->time);
+ *typePtr = XA_INTEGER;
+ return strlen(buffer);
+ }
+
+ if (target == dispPtr->targetsAtom) {
+ register TkSelHandler *selPtr;
+ int length;
+ Tcl_DString ds;
+
+ if (maxBytes < 50) {
+ return -1;
+ }
+ Tcl_DStringInit(&ds);
+ Tcl_DStringAppend(&ds,
+ "MULTIPLE TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW", -1);
+ for (selPtr = winPtr->selHandlerList; selPtr != NULL;
+ selPtr = selPtr->nextPtr) {
+ if ((selPtr->selection == infoPtr->selection)
+ && (selPtr->target != dispPtr->applicationAtom)
+ && (selPtr->target != dispPtr->windowAtom)) {
+ const char *atomString = Tk_GetAtomName((Tk_Window) winPtr,
+ selPtr->target);
+
+ Tcl_DStringAppendElement(&ds, atomString);
+ }
+ }
+ length = Tcl_DStringLength(&ds);
+ if (length >= maxBytes) {
+ Tcl_DStringFree(&ds);
+ return -1;
+ }
+ memcpy(buffer, Tcl_DStringValue(&ds), (unsigned) (1+length));
+ Tcl_DStringFree(&ds);
+ *typePtr = XA_ATOM;
+ return length;
+ }
+
+ if (target == dispPtr->applicationAtom) {
+ int length;
+ Tk_Uid name = winPtr->mainPtr->winPtr->nameUid;
+
+ length = strlen(name);
+ if (maxBytes <= length) {
+ return -1;
+ }
+ strcpy(buffer, name);
+ *typePtr = XA_STRING;
+ return length;
+ }
+
+ if (target == dispPtr->windowAtom) {
+ int length;
+ char *name = winPtr->pathName;
+
+ length = strlen(name);
+ if (maxBytes <= length) {
+ return -1;
+ }
+ strcpy(buffer, name);
+ *typePtr = XA_STRING;
+ return length;
+ }
+
+ return -1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * LostSelection --
+ *
+ * This function is invoked when a window has lost ownership of the
+ * selection and the ownership was claimed with the command "selection
+ * own".
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A Tcl script is executed; it can do almost anything.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+LostSelection(
+ ClientData clientData) /* Pointer to LostCommand structure. */
+{
+ LostCommand *lostPtr = clientData;
+ Tcl_Interp *interp = lostPtr->interp;
+ Tcl_InterpState savedState;
+ int code;
+
+ Tcl_Preserve(interp);
+
+ /*
+ * Execute the command. Save the interpreter's result, if any, and restore
+ * it after executing the command.
+ */
+
+ savedState = Tcl_SaveInterpState(interp, TCL_OK);
+ Tcl_ResetResult(interp);
+ code = Tcl_EvalObjEx(interp, lostPtr->cmdObj, TCL_EVAL_GLOBAL);
+ if (code != TCL_OK) {
+ Tcl_BackgroundException(interp, code);
+ }
+ (void) Tcl_RestoreInterpState(interp, savedState);
+
+ /*
+ * Free the storage for the command, since we're done with it now.
+ */
+
+ Tcl_DecrRefCount(lostPtr->cmdObj);
+ ckfree(lostPtr);
+ Tcl_Release(interp);
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkSelect.h b/tk8.6/generic/tkSelect.h
new file mode 100644
index 0000000..74326d0
--- /dev/null
+++ b/tk8.6/generic/tkSelect.h
@@ -0,0 +1,167 @@
+/*
+ * tkSelect.h --
+ *
+ * Declarations of types shared among the files that implement selection
+ * support.
+ *
+ * Copyright (c) 1995 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef _TKSELECT
+#define _TKSELECT
+
+/*
+ * When a selection is owned by a window on a given display, one of the
+ * following structures is present on a list of current selections in the
+ * display structure. The structure is used to record the current owner of a
+ * selection for use in later retrieval requests. There is a list of such
+ * structures because a display can have multiple different selections active
+ * at the same time.
+ */
+
+typedef struct TkSelectionInfo {
+ Atom selection; /* Selection name, e.g. XA_PRIMARY. */
+ Tk_Window owner; /* Current owner of this selection. */
+ int serial; /* Serial number of last XSelectionSetOwner
+ * request made to server for this selection
+ * (used to filter out redundant
+ * SelectionClear events). */
+ Time time; /* Timestamp used to acquire selection. */
+ Tk_LostSelProc *clearProc; /* Procedure to call when owner loses
+ * selection. */
+ ClientData clearData; /* Info to pass to clearProc. */
+ struct TkSelectionInfo *nextPtr;
+ /* Next in list of current selections on this
+ * display. NULL means end of list. */
+} TkSelectionInfo;
+
+/*
+ * One of the following structures exists for each selection handler created
+ * for a window by calling Tk_CreateSelHandler. The handlers are linked in a
+ * list rooted in the TkWindow structure.
+ */
+
+typedef struct TkSelHandler {
+ Atom selection; /* Selection name, e.g. XA_PRIMARY. */
+ Atom target; /* Target type for selection conversion, such
+ * as TARGETS or STRING. */
+ Atom format; /* Format in which selection info will be
+ * returned, such as STRING or ATOM. */
+ Tk_SelectionProc *proc; /* Procedure to generate selection in this
+ * format. */
+ ClientData clientData; /* Argument to pass to proc. */
+ int size; /* Size of units returned by proc (8 for
+ * STRING, 32 for almost anything else). */
+ struct TkSelHandler *nextPtr;
+ /* Next selection handler associated with same
+ * window (NULL for end of list). */
+} TkSelHandler;
+
+/*
+ * When the selection is being retrieved, one of the following structures is
+ * present on a list of pending selection retrievals. The structure is used to
+ * communicate between the background procedure that requests the selection
+ * and the foreground event handler that processes the events in which the
+ * selection is returned. There is a list of such structures so that there can
+ * be multiple simultaneous selection retrievals (e.g. on different displays).
+ */
+
+typedef struct TkSelRetrievalInfo {
+ Tcl_Interp *interp; /* Interpreter for error reporting. */
+ TkWindow *winPtr; /* Window used as requestor for selection. */
+ Atom selection; /* Selection being requested. */
+ Atom property; /* Property where selection will appear. */
+ Atom target; /* Desired form for selection. */
+ Tk_GetSelProc *proc; /* Procedure to call to handle pieces of
+ * selection. */
+ ClientData clientData; /* Argument for proc. */
+ int result; /* Initially -1. Set to a Tcl return value
+ * once the selection has been retrieved. */
+ Tcl_TimerToken timeout; /* Token for current timeout procedure. */
+ int idleTime; /* Number of seconds that have gone by without
+ * hearing anything from the selection
+ * owner. */
+ Tcl_EncodingState encState; /* Holds intermediate state during translations
+ * of data that cross buffer boundaries. */
+ int encFlags; /* Encoding translation state flags. */
+ Tcl_DString buf; /* Buffer to hold translation data. */
+ struct TkSelRetrievalInfo *nextPtr;
+ /* Next in list of all pending selection
+ * retrievals. NULL means end of list. */
+} TkSelRetrievalInfo;
+
+/*
+ * The clipboard contains a list of buffers of various types and formats. All
+ * of the buffers of a given type will be returned in sequence when the
+ * CLIPBOARD selection is retrieved. All buffers of a given type on the same
+ * clipboard must have the same format. The TkClipboardTarget structure is
+ * used to record the information about a chain of buffers of the same type.
+ */
+
+typedef struct TkClipboardBuffer {
+ char *buffer; /* Null terminated data buffer. */
+ long length; /* Length of string in buffer. */
+ struct TkClipboardBuffer *nextPtr;
+ /* Next in list of buffers. NULL means end of
+ * list . */
+} TkClipboardBuffer;
+
+typedef struct TkClipboardTarget {
+ Atom type; /* Type conversion supported. */
+ Atom format; /* Representation used for data. */
+ TkClipboardBuffer *firstBufferPtr;
+ /* First in list of data buffers. */
+ TkClipboardBuffer *lastBufferPtr;
+ /* Last in list of clipboard buffers. Used to
+ * speed up appends. */
+ struct TkClipboardTarget *nextPtr;
+ /* Next in list of targets on clipboard. NULL
+ * means end of list. */
+} TkClipboardTarget;
+
+/*
+ * It is possible for a Tk_SelectionProc to delete the handler that it
+ * represents. If this happens, the code that is retrieving the selection
+ * needs to know about it so it doesn't use the now-defunct handler structure.
+ * One structure of the following form is created for each retrieval in
+ * progress, so that the retriever can find out if its handler is deleted. All
+ * of the pending retrievals (if there are more than one) are linked into a
+ * list.
+ */
+
+typedef struct TkSelInProgress {
+ TkSelHandler *selPtr; /* Handler being executed. If this handler is
+ * deleted, the field is set to NULL. */
+ struct TkSelInProgress *nextPtr;
+ /* Next higher nested search. */
+} TkSelInProgress;
+
+/*
+ * Chunk size for retrieving selection. It's defined both in words and in
+ * bytes; the word size is used to allocate buffer space that's guaranteed to
+ * be word-aligned and that has an extra character for the terminating NULL.
+ */
+
+#define TK_SEL_BYTES_AT_ONCE 4000
+#define TK_SEL_WORDS_AT_ONCE 1001
+
+/*
+ * Declarations for procedures that are used by the selection-related files
+ * but shouldn't be used anywhere else in Tk (or by Tk clients):
+ */
+
+MODULE_SCOPE TkSelInProgress *TkSelGetInProgress(void);
+MODULE_SCOPE void TkSelSetInProgress(TkSelInProgress *pendingPtr);
+MODULE_SCOPE void TkSelClearSelection(Tk_Window tkwin, XEvent *eventPtr);
+MODULE_SCOPE int TkSelDefaultSelection(TkSelectionInfo *infoPtr,
+ Atom target, char *buffer, int maxBytes,
+ Atom *typePtr);
+#ifndef TkSelUpdateClipboard
+MODULE_SCOPE void TkSelUpdateClipboard(TkWindow *winPtr,
+ TkClipboardTarget *targetPtr);
+#endif
+
+#endif /* _TKSELECT */
diff --git a/tk8.6/generic/tkSquare.c b/tk8.6/generic/tkSquare.c
new file mode 100644
index 0000000..e92c03c
--- /dev/null
+++ b/tk8.6/generic/tkSquare.c
@@ -0,0 +1,623 @@
+/*
+ * tkSquare.c --
+ *
+ * This module implements "square" widgets that are object based. A
+ * "square" is a widget that displays a single square that can be moved
+ * around and resized. This file is intended as an example of how to
+ * build a widget; it isn't included in the normal wish, but it is
+ * included in "tktest".
+ *
+ * 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.
+ */
+
+#if 0
+#define __NO_OLD_CONFIG
+#endif
+#ifndef USE_TCL_STUBS
+# define USE_TCL_STUBS
+#endif
+#ifndef USE_TK_STUBS
+# define USE_TK_STUBS
+#endif
+#include "tkInt.h"
+
+/*
+ * A data structure of the following type is kept for each square widget
+ * managed by this file:
+ */
+
+typedef struct {
+ Tk_Window tkwin; /* Window that embodies the square. NULL means
+ * window has been deleted but widget record
+ * hasn't been cleaned up yet. */
+ Display *display; /* X's token for the window's display. */
+ Tcl_Interp *interp; /* Interpreter associated with widget. */
+ Tcl_Command widgetCmd; /* Token for square's widget command. */
+ Tk_OptionTable optionTable; /* Token representing the configuration
+ * specifications. */
+ Tcl_Obj *xPtr, *yPtr; /* Position of square's upper-left corner
+ * within widget. */
+ int x, y;
+ Tcl_Obj *sizeObjPtr; /* Width and height of square. */
+
+ /*
+ * Information used when displaying widget:
+ */
+
+ Tcl_Obj *borderWidthPtr; /* Width of 3-D border around whole widget. */
+ Tcl_Obj *bgBorderPtr;
+ Tcl_Obj *fgBorderPtr;
+ Tcl_Obj *reliefPtr;
+ GC gc; /* Graphics context for copying from
+ * off-screen pixmap onto screen. */
+ Tcl_Obj *doubleBufferPtr; /* Non-zero means double-buffer redisplay with
+ * pixmap; zero means draw straight onto the
+ * display. */
+ int updatePending; /* Non-zero means a call to SquareDisplay has
+ * already been scheduled. */
+} Square;
+
+/*
+ * Information used for argv parsing.
+ */
+
+static const Tk_OptionSpec optionSpecs[] = {
+ {TK_OPTION_BORDER, "-background", "background", "Background",
+ "#d9d9d9", Tk_Offset(Square, bgBorderPtr), -1, 0,
+ "white", 0},
+ {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL, 0, -1, 0,
+ "-borderwidth", 0},
+ {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, 0, -1, 0,
+ "-background", 0},
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ "2", Tk_Offset(Square, borderWidthPtr), -1, 0, NULL, 0},
+ {TK_OPTION_BOOLEAN, "-dbl", "doubleBuffer", "DoubleBuffer",
+ "1", Tk_Offset(Square, doubleBufferPtr), -1, 0 , NULL, 0},
+ {TK_OPTION_SYNONYM, "-fg", NULL, NULL, NULL, 0, -1, 0,
+ "-foreground", 0},
+ {TK_OPTION_BORDER, "-foreground", "foreground", "Foreground",
+ "#b03060", Tk_Offset(Square, fgBorderPtr), -1, 0,
+ "black", 0},
+ {TK_OPTION_PIXELS, "-posx", "posx", "PosX", "0",
+ Tk_Offset(Square, xPtr), -1, 0, NULL, 0},
+ {TK_OPTION_PIXELS, "-posy", "posy", "PosY", "0",
+ Tk_Offset(Square, yPtr), -1, 0, NULL, 0},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ "raised", Tk_Offset(Square, reliefPtr), -1, 0, NULL, 0},
+ {TK_OPTION_PIXELS, "-size", "size", "Size", "20",
+ Tk_Offset(Square, sizeObjPtr), -1, 0, NULL, 0},
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}
+};
+
+/*
+ * Forward declarations for procedures defined later in this file:
+ */
+
+static void SquareDeletedProc(ClientData clientData);
+static int SquareConfigure(Tcl_Interp *interp, Square *squarePtr);
+static void SquareDestroy(void *memPtr);
+static void SquareDisplay(ClientData clientData);
+static void KeepInWindow(Square *squarePtr);
+static void SquareObjEventProc(ClientData clientData,
+ XEvent *eventPtr);
+static int SquareWidgetObjCmd(ClientData clientData,
+ Tcl_Interp *, int objc, Tcl_Obj * const objv[]);
+
+/*
+ *--------------------------------------------------------------
+ *
+ * SquareCmd --
+ *
+ * This procedure is invoked to process the "square" Tcl command. It
+ * creates a new "square" widget.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * A new widget is created and configured.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+SquareObjCmd(
+ ClientData clientData, /* NULL. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Square *squarePtr;
+ Tk_Window tkwin;
+ Tk_OptionTable optionTable;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?");
+ return TCL_ERROR;
+ }
+
+ tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),
+ Tcl_GetString(objv[1]), NULL);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ Tk_SetClass(tkwin, "Square");
+
+ /*
+ * Create the option table for this widget class. If it has already been
+ * created, the refcount will get bumped and just the pointer will be
+ * returned. The refcount getting bumped does not concern us, because Tk
+ * will ensure the table is deleted when the interpreter is destroyed.
+ */
+
+ optionTable = Tk_CreateOptionTable(interp, optionSpecs);
+
+ /*
+ * Allocate and initialize the widget record. The memset allows us to set
+ * just the non-NULL/0 items.
+ */
+
+ squarePtr = ckalloc(sizeof(Square));
+ memset(squarePtr, 0, sizeof(Square));
+
+ squarePtr->tkwin = tkwin;
+ squarePtr->display = Tk_Display(tkwin);
+ squarePtr->interp = interp;
+ squarePtr->widgetCmd = Tcl_CreateObjCommand(interp,
+ Tk_PathName(squarePtr->tkwin), SquareWidgetObjCmd, squarePtr,
+ SquareDeletedProc);
+ squarePtr->gc = NULL;
+ squarePtr->optionTable = optionTable;
+
+ if (Tk_InitOptions(interp, (char *) squarePtr, optionTable, tkwin)
+ != TCL_OK) {
+ Tk_DestroyWindow(squarePtr->tkwin);
+ ckfree(squarePtr);
+ return TCL_ERROR;
+ }
+
+ Tk_CreateEventHandler(squarePtr->tkwin, ExposureMask|StructureNotifyMask,
+ SquareObjEventProc, squarePtr);
+ if (Tk_SetOptions(interp, (char *) squarePtr, optionTable, objc - 2,
+ objv + 2, tkwin, NULL, NULL) != TCL_OK) {
+ goto error;
+ }
+ if (SquareConfigure(interp, squarePtr) != TCL_OK) {
+ goto error;
+ }
+
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj(Tk_PathName(squarePtr->tkwin), -1));
+ return TCL_OK;
+
+ error:
+ Tk_DestroyWindow(squarePtr->tkwin);
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * SquareWidgetObjCmd --
+ *
+ * This procedure is invoked to process the Tcl command that corresponds
+ * to a widget managed by this module. See the user documentation for
+ * details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+SquareWidgetObjCmd(
+ ClientData clientData, /* Information about square widget. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj * const objv[]) /* Argument objects. */
+{
+ Square *squarePtr = clientData;
+ int result = TCL_OK;
+ static const char *const squareOptions[] = {"cget", "configure", NULL};
+ enum {
+ SQUARE_CGET, SQUARE_CONFIGURE
+ };
+ Tcl_Obj *resultObjPtr;
+ int index;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg...?");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[1], squareOptions,
+ sizeof(char *), "command", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ Tcl_Preserve(squarePtr);
+
+ switch (index) {
+ case SQUARE_CGET:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option");
+ goto error;
+ }
+ resultObjPtr = Tk_GetOptionValue(interp, (char *) squarePtr,
+ squarePtr->optionTable, objv[2], squarePtr->tkwin);
+ if (resultObjPtr == NULL) {
+ result = TCL_ERROR;
+ } else {
+ Tcl_SetObjResult(interp, resultObjPtr);
+ }
+ break;
+ case SQUARE_CONFIGURE:
+ resultObjPtr = NULL;
+ if (objc == 2) {
+ resultObjPtr = Tk_GetOptionInfo(interp, (char *) squarePtr,
+ squarePtr->optionTable, NULL, squarePtr->tkwin);
+ if (resultObjPtr == NULL) {
+ result = TCL_ERROR;
+ }
+ } else if (objc == 3) {
+ resultObjPtr = Tk_GetOptionInfo(interp, (char *) squarePtr,
+ squarePtr->optionTable, objv[2], squarePtr->tkwin);
+ if (resultObjPtr == NULL) {
+ result = TCL_ERROR;
+ }
+ } else {
+ result = Tk_SetOptions(interp, (char *) squarePtr,
+ squarePtr->optionTable, objc - 2, objv + 2,
+ squarePtr->tkwin, NULL, NULL);
+ if (result == TCL_OK) {
+ result = SquareConfigure(interp, squarePtr);
+ }
+ if (!squarePtr->updatePending) {
+ Tcl_DoWhenIdle(SquareDisplay, squarePtr);
+ squarePtr->updatePending = 1;
+ }
+ }
+ if (resultObjPtr != NULL) {
+ Tcl_SetObjResult(interp, resultObjPtr);
+ }
+ }
+ Tcl_Release(squarePtr);
+ return result;
+
+ error:
+ Tcl_Release(squarePtr);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SquareConfigure --
+ *
+ * This procedure is called to process an argv/argc list in conjunction
+ * with the Tk option database to configure (or reconfigure) a square
+ * widget.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If TCL_ERROR is returned,
+ * then the interp's result contains an error message.
+ *
+ * Side effects:
+ * Configuration information, such as colors, border width, etc. get set
+ * for squarePtr; old resources get freed, if there were any.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SquareConfigure(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Square *squarePtr) /* Information about widget. */
+{
+ int borderWidth;
+ Tk_3DBorder bgBorder;
+ int doubleBuffer;
+
+ /*
+ * Set the background for the window and create a graphics context for use
+ * during redisplay.
+ */
+
+ bgBorder = Tk_Get3DBorderFromObj(squarePtr->tkwin,
+ squarePtr->bgBorderPtr);
+ Tk_SetWindowBackground(squarePtr->tkwin,
+ Tk_3DBorderColor(bgBorder)->pixel);
+ Tcl_GetBooleanFromObj(NULL, squarePtr->doubleBufferPtr, &doubleBuffer);
+ if ((squarePtr->gc == NULL) && doubleBuffer) {
+ XGCValues gcValues;
+ gcValues.function = GXcopy;
+ gcValues.graphics_exposures = False;
+ squarePtr->gc = Tk_GetGC(squarePtr->tkwin,
+ GCFunction|GCGraphicsExposures, &gcValues);
+ }
+
+ /*
+ * Register the desired geometry for the window. Then arrange for the
+ * window to be redisplayed.
+ */
+
+ Tk_GeometryRequest(squarePtr->tkwin, 200, 150);
+ Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->borderWidthPtr,
+ &borderWidth);
+ Tk_SetInternalBorder(squarePtr->tkwin, borderWidth);
+ if (!squarePtr->updatePending) {
+ Tcl_DoWhenIdle(SquareDisplay, squarePtr);
+ squarePtr->updatePending = 1;
+ }
+ KeepInWindow(squarePtr);
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * SquareObjEventProc --
+ *
+ * This procedure is invoked by the Tk dispatcher for various events on
+ * squares.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * When the window gets deleted, internal structures get cleaned up. When
+ * it gets exposed, it is redisplayed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+SquareObjEventProc(
+ ClientData clientData, /* Information about window. */
+ XEvent *eventPtr) /* Information about event. */
+{
+ Square *squarePtr = clientData;
+
+ if (eventPtr->type == Expose) {
+ if (!squarePtr->updatePending) {
+ Tcl_DoWhenIdle(SquareDisplay, squarePtr);
+ squarePtr->updatePending = 1;
+ }
+ } else if (eventPtr->type == ConfigureNotify) {
+ KeepInWindow(squarePtr);
+ if (!squarePtr->updatePending) {
+ Tcl_DoWhenIdle(SquareDisplay, squarePtr);
+ squarePtr->updatePending = 1;
+ }
+ } else if (eventPtr->type == DestroyNotify) {
+ if (squarePtr->tkwin != NULL) {
+ Tk_FreeConfigOptions((char *) squarePtr, squarePtr->optionTable,
+ squarePtr->tkwin);
+ if (squarePtr->gc != NULL) {
+ Tk_FreeGC(squarePtr->display, squarePtr->gc);
+ }
+ squarePtr->tkwin = NULL;
+ Tcl_DeleteCommandFromToken(squarePtr->interp,
+ squarePtr->widgetCmd);
+ }
+ if (squarePtr->updatePending) {
+ Tcl_CancelIdleCall(SquareDisplay, squarePtr);
+ }
+ Tcl_EventuallyFree(squarePtr, (Tcl_FreeProc *) SquareDestroy);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SquareDeletedProc --
+ *
+ * This procedure is invoked when a widget command is deleted. If the
+ * widget isn't already in the process of being destroyed, this command
+ * destroys it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The widget is destroyed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+SquareDeletedProc(
+ ClientData clientData) /* Pointer to widget record for widget. */
+{
+ Square *squarePtr = clientData;
+ Tk_Window tkwin = squarePtr->tkwin;
+
+ /*
+ * This procedure could be invoked either because the window was destroyed
+ * and the command was then deleted (in which case tkwin is NULL) or
+ * because the command was deleted, and then this procedure destroys the
+ * widget.
+ */
+
+ if (tkwin != NULL) {
+ Tk_DestroyWindow(tkwin);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * SquareDisplay --
+ *
+ * This procedure redraws the contents of a square 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.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+SquareDisplay(
+ ClientData clientData) /* Information about window. */
+{
+ Square *squarePtr = clientData;
+ Tk_Window tkwin = squarePtr->tkwin;
+ Pixmap pm = None;
+ Drawable d;
+ int borderWidth, size, relief;
+ Tk_3DBorder bgBorder, fgBorder;
+ int doubleBuffer;
+
+ squarePtr->updatePending = 0;
+ if (!Tk_IsMapped(tkwin)) {
+ return;
+ }
+
+ /*
+ * Create a pixmap for double-buffering, if necessary.
+ */
+
+ Tcl_GetBooleanFromObj(NULL, squarePtr->doubleBufferPtr, &doubleBuffer);
+ if (doubleBuffer) {
+ pm = Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin),
+ Tk_Width(tkwin), Tk_Height(tkwin),
+ DefaultDepthOfScreen(Tk_Screen(tkwin)));
+ d = pm;
+ } else {
+ d = Tk_WindowId(tkwin);
+ }
+
+ /*
+ * Redraw the widget's background and border.
+ */
+
+ Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->borderWidthPtr,
+ &borderWidth);
+ bgBorder = Tk_Get3DBorderFromObj(squarePtr->tkwin,
+ squarePtr->bgBorderPtr);
+ Tk_GetReliefFromObj(NULL, squarePtr->reliefPtr, &relief);
+ Tk_Fill3DRectangle(tkwin, d, bgBorder, 0, 0, Tk_Width(tkwin),
+ Tk_Height(tkwin), borderWidth, relief);
+
+ /*
+ * Display the square.
+ */
+
+ Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->sizeObjPtr, &size);
+ fgBorder = Tk_Get3DBorderFromObj(squarePtr->tkwin,
+ squarePtr->fgBorderPtr);
+ Tk_Fill3DRectangle(tkwin, d, fgBorder, squarePtr->x, squarePtr->y, size,
+ size, borderWidth, TK_RELIEF_RAISED);
+
+ /*
+ * If double-buffered, copy to the screen and release the pixmap.
+ */
+
+ if (doubleBuffer) {
+ XCopyArea(Tk_Display(tkwin), pm, Tk_WindowId(tkwin), squarePtr->gc,
+ 0, 0, (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin),
+ 0, 0);
+ Tk_FreePixmap(Tk_Display(tkwin), pm);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SquareDestroy --
+ *
+ * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release to
+ * clean up the internal structure of a square at a safe time (when
+ * no-one is using it anymore).
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Everything associated with the square is freed up.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+SquareDestroy(
+ void *memPtr) /* Info about square widget. */
+{
+ Square *squarePtr = memPtr;
+
+ ckfree(squarePtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * KeepInWindow --
+ *
+ * Adjust the position of the square if necessary to keep it in the
+ * widget's window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The x and y position of the square are adjusted if necessary to keep
+ * the square in the window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+KeepInWindow(
+ register Square *squarePtr) /* Pointer to widget record. */
+{
+ int i, bd, relief;
+ int borderWidth, size;
+
+ Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->borderWidthPtr,
+ &borderWidth);
+ Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->xPtr,
+ &squarePtr->x);
+ Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->yPtr,
+ &squarePtr->y);
+ Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->sizeObjPtr, &size);
+ Tk_GetReliefFromObj(NULL, squarePtr->reliefPtr, &relief);
+ bd = 0;
+ if (relief != TK_RELIEF_FLAT) {
+ bd = borderWidth;
+ }
+ i = (Tk_Width(squarePtr->tkwin) - bd) - (squarePtr->x + size);
+ if (i < 0) {
+ squarePtr->x += i;
+ }
+ i = (Tk_Height(squarePtr->tkwin) - bd) - (squarePtr->y + size);
+ if (i < 0) {
+ squarePtr->y += i;
+ }
+ if (squarePtr->x < bd) {
+ squarePtr->x = bd;
+ }
+ if (squarePtr->y < bd) {
+ squarePtr->y = bd;
+ }
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkStubInit.c b/tk8.6/generic/tkStubInit.c
new file mode 100644
index 0000000..7e02302
--- /dev/null
+++ b/tk8.6/generic/tkStubInit.c
@@ -0,0 +1,1136 @@
+/*
+ * tkStubInit.c --
+ *
+ * This file contains the initializers for the Tk stub vectors.
+ *
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkInt.h"
+
+#if !(defined(_WIN32) || defined(MAC_OSX_TK))
+/* UNIX */
+#define UNIX_TK
+#include "tkUnixInt.h"
+#endif
+
+#ifdef _WIN32
+#include "tkWinInt.h"
+#endif
+
+#if defined(MAC_OSX_TK)
+/* we could have used _TKMACINT */
+#include "tkMacOSXInt.h"
+#endif
+
+/* TODO: These ought to come in some other way */
+#include "tkPlatDecls.h"
+#include "tkIntXlibDecls.h"
+
+static const TkIntStubs tkIntStubs;
+MODULE_SCOPE const TkStubs tkStubs;
+
+/*
+ * Remove macro that might interfere with the definition below.
+ */
+
+#undef Tk_MainEx
+
+#ifdef _WIN32
+
+int
+TkpCmapStressed(Tk_Window tkwin, Colormap colormap)
+{
+ /* dummy implementation, no need to do anything */
+ return 0;
+}
+void
+TkpSync(Display *display)
+{
+ /* dummy implementation, no need to do anything */
+}
+
+void
+TkCreateXEventSource(void)
+{
+ TkWinXInit(Tk_GetHINSTANCE());
+}
+
+# define TkUnixContainerId 0
+# define TkUnixDoOneXEvent 0
+# define TkUnixSetMenubar 0
+# define XCreateWindow 0
+# define XOffsetRegion 0
+# define XUnionRegion 0
+# define TkWmCleanup (void (*)(TkDisplay *)) TkpSync
+# define TkSendCleanup (void (*)(TkDisplay *)) TkpSync
+# define TkpTestsendCmd 0
+
+#else /* !_WIN32 */
+
+/*
+ * Make sure that extensions which call XParseColor through the stub
+ * table, call TkParseColor instead. [Bug 3486474]
+ */
+# define XParseColor TkParseColor
+
+# ifdef __CYGWIN__
+
+/*
+ * Trick, so we don't have to include <windows.h> here, which in any
+ * case lacks this function anyway.
+ */
+
+#define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 0x00000004
+int __stdcall GetModuleHandleExW(unsigned int, const char *, void *);
+
+void *Tk_GetHINSTANCE()
+{
+ void *hInstance = NULL;
+
+ GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
+ (const char *) &tkIntStubs, &hInstance);
+ return hInstance;
+}
+
+void
+TkSetPixmapColormap(
+ Pixmap pixmap,
+ Colormap colormap)
+{
+}
+
+void
+TkpPrintWindowId(
+ char *buf, /* Pointer to string large enough to hold
+ * the hex representation of a pointer. */
+ Window window) /* Window to be printed into buffer. */
+{
+ sprintf(buf, "%#08lx", (unsigned long) (window));
+}
+
+int
+TkPutImage(
+ unsigned long *colors, /* Array of pixel values used by this image.
+ * May be NULL. */
+ int ncolors, /* Number of colors used, or 0. */
+ Display *display,
+ Drawable d, /* Destination drawable. */
+ GC gc,
+ XImage *image, /* Source image. */
+ int src_x, int src_y, /* Offset of subimage. */
+ int dest_x, int dest_y, /* Position of subimage origin in drawable. */
+ unsigned int width, unsigned int height)
+ /* Dimensions of subimage. */
+{
+ return XPutImage(display, d, gc, image, src_x, src_y, dest_x, dest_y, width, height);
+}
+
+TkRegion TkCreateRegion()
+{
+ return (TkRegion) XCreateRegion();
+}
+
+void TkDestroyRegion(TkRegion r)
+{
+ XDestroyRegion((Region)r);
+}
+
+void TkSetRegion(Display *d, GC g, TkRegion r)
+{
+ XSetRegion(d, g, (Region)r);
+}
+
+void TkUnionRectWithRegion(XRectangle *a, TkRegion b, TkRegion c)
+{
+ XUnionRectWithRegion(a, (Region) b, (Region) c);
+}
+
+void TkClipBox(TkRegion a, XRectangle *b)
+{
+ XClipBox((Region) a, b);
+}
+
+void TkIntersectRegion(TkRegion a, TkRegion b, TkRegion c)
+{
+ XIntersectRegion((Region) a, (Region) b, (Region) c);
+}
+
+int TkRectInRegion (TkRegion r, int a, int b, unsigned int c, unsigned int d)
+{
+ return XRectInRegion((Region) r, a, b, c, d);
+}
+
+void TkSubtractRegion (TkRegion a, TkRegion b, TkRegion c)
+{
+ XSubtractRegion((Region) a, (Region) b, (Region) c);
+}
+
+ /* TODO: To be implemented for Cygwin */
+# define Tk_AttachHWND 0
+# define Tk_GetHWND 0
+# define Tk_HWNDToWindow 0
+# define Tk_PointerEvent 0
+# define Tk_TranslateWinEvent 0
+# define TkAlignImageData 0
+# define TkGenerateActivateEvents 0
+# define TkpGetMS 0
+# define TkPointerDeadWindow 0
+# define TkpSetCapture 0
+# define TkpSetCursor 0
+# define TkWinCancelMouseTimer 0
+# define TkWinClipboardRender 0
+# define TkWinEmbeddedEventProc 0
+# define TkWinFillRect 0
+# define TkWinGetBorderPixels 0
+# define TkWinGetDrawableDC 0
+# define TkWinGetModifierState 0
+# define TkWinGetSystemPalette 0
+# define TkWinGetWrapperWindow 0
+# define TkWinHandleMenuEvent 0
+# define TkWinIndexOfColor 0
+# define TkWinReleaseDrawableDC 0
+# define TkWinResendEvent 0
+# define TkWinSelectPalette 0
+# define TkWinSetMenu 0
+# define TkWinSetWindowPos 0
+# define TkWinWmCleanup 0
+# define TkWinXCleanup 0
+# define TkWinXInit 0
+# define TkWinSetForegroundWindow 0
+# define TkWinDialogDebug 0
+# define TkWinGetMenuSystemDefault 0
+# define TkWinGetPlatformId 0
+# define TkWinSetHINSTANCE 0
+# define TkWinGetPlatformTheme 0
+# define TkWinChildProc 0
+
+# elif !defined(MAC_OSX_TK) /* UNIX */
+
+# undef TkClipBox
+# undef TkCreateRegion
+# undef TkDestroyRegion
+# undef TkIntersectRegion
+# undef TkRectInRegion
+# undef TkSetRegion
+# undef TkUnionRectWithRegion
+# undef TkSubtractRegion
+
+# define TkClipBox (void (*) (TkRegion, XRectangle *)) XClipBox
+# define TkCreateRegion (TkRegion (*) ()) XCreateRegion
+# define TkDestroyRegion (void (*) (TkRegion)) XDestroyRegion
+# define TkIntersectRegion (void (*) (TkRegion, TkRegion, TkRegion)) XIntersectRegion
+# define TkRectInRegion (int (*) (TkRegion, int, int, unsigned int, unsigned int)) XRectInRegion
+# define TkSetRegion (void (*) (Display *, GC, TkRegion)) XSetRegion
+# define TkUnionRectWithRegion (void (*) (XRectangle *, TkRegion, TkRegion)) XUnionRectWithRegion
+# define TkSubtractRegion (void (*) (TkRegion, TkRegion, TkRegion)) XSubtractRegion
+# endif
+#endif /* !_WIN32 */
+
+/*
+ * WARNING: The contents of this file is automatically generated by the
+ * tools/genStubs.tcl script. Any modifications to the function declarations
+ * below should be made in the generic/tk.decls script.
+ */
+
+/* !BEGIN!: Do not edit below this line. */
+
+static const TkIntStubs tkIntStubs = {
+ TCL_STUB_MAGIC,
+ 0,
+ TkAllocWindow, /* 0 */
+ TkBezierPoints, /* 1 */
+ TkBezierScreenPoints, /* 2 */
+ 0, /* 3 */
+ TkBindEventProc, /* 4 */
+ TkBindFree, /* 5 */
+ TkBindInit, /* 6 */
+ TkChangeEventWindow, /* 7 */
+ TkClipInit, /* 8 */
+ TkComputeAnchor, /* 9 */
+ 0, /* 10 */
+ 0, /* 11 */
+ TkCreateCursorFromData, /* 12 */
+ TkCreateFrame, /* 13 */
+ TkCreateMainWindow, /* 14 */
+ TkCurrentTime, /* 15 */
+ TkDeleteAllImages, /* 16 */
+ TkDoConfigureNotify, /* 17 */
+ TkDrawInsetFocusHighlight, /* 18 */
+ TkEventDeadWindow, /* 19 */
+ TkFillPolygon, /* 20 */
+ TkFindStateNum, /* 21 */
+ TkFindStateString, /* 22 */
+ TkFocusDeadWindow, /* 23 */
+ TkFocusFilterEvent, /* 24 */
+ TkFocusKeyEvent, /* 25 */
+ TkFontPkgInit, /* 26 */
+ TkFontPkgFree, /* 27 */
+ TkFreeBindingTags, /* 28 */
+ TkpFreeCursor, /* 29 */
+ TkGetBitmapData, /* 30 */
+ TkGetButtPoints, /* 31 */
+ TkGetCursorByName, /* 32 */
+ TkGetDefaultScreenName, /* 33 */
+ TkGetDisplay, /* 34 */
+ TkGetDisplayOf, /* 35 */
+ TkGetFocusWin, /* 36 */
+ TkGetInterpNames, /* 37 */
+ TkGetMiterPoints, /* 38 */
+ TkGetPointerCoords, /* 39 */
+ TkGetServerInfo, /* 40 */
+ TkGrabDeadWindow, /* 41 */
+ TkGrabState, /* 42 */
+ TkIncludePoint, /* 43 */
+ TkInOutEvents, /* 44 */
+ TkInstallFrameMenu, /* 45 */
+ TkKeysymToString, /* 46 */
+ TkLineToArea, /* 47 */
+ TkLineToPoint, /* 48 */
+ TkMakeBezierCurve, /* 49 */
+ TkMakeBezierPostscript, /* 50 */
+ TkOptionClassChanged, /* 51 */
+ TkOptionDeadWindow, /* 52 */
+ TkOvalToArea, /* 53 */
+ TkOvalToPoint, /* 54 */
+ TkpChangeFocus, /* 55 */
+ TkpCloseDisplay, /* 56 */
+ TkpClaimFocus, /* 57 */
+ TkpDisplayWarning, /* 58 */
+ TkpGetAppName, /* 59 */
+ TkpGetOtherWindow, /* 60 */
+ TkpGetWrapperWindow, /* 61 */
+ TkpInit, /* 62 */
+ TkpInitializeMenuBindings, /* 63 */
+ TkpMakeContainer, /* 64 */
+ TkpMakeMenuWindow, /* 65 */
+ TkpMakeWindow, /* 66 */
+ TkpMenuNotifyToplevelCreate, /* 67 */
+ TkpOpenDisplay, /* 68 */
+ TkPointerEvent, /* 69 */
+ TkPolygonToArea, /* 70 */
+ TkPolygonToPoint, /* 71 */
+ TkPositionInTree, /* 72 */
+ TkpRedirectKeyEvent, /* 73 */
+ TkpSetMainMenubar, /* 74 */
+ TkpUseWindow, /* 75 */
+ 0, /* 76 */
+ TkQueueEventForAllChildren, /* 77 */
+ TkReadBitmapFile, /* 78 */
+ TkScrollWindow, /* 79 */
+ TkSelDeadWindow, /* 80 */
+ TkSelEventProc, /* 81 */
+ TkSelInit, /* 82 */
+ TkSelPropProc, /* 83 */
+ 0, /* 84 */
+ TkSetWindowMenuBar, /* 85 */
+ TkStringToKeysym, /* 86 */
+ TkThickPolyLineToArea, /* 87 */
+ TkWmAddToColormapWindows, /* 88 */
+ TkWmDeadWindow, /* 89 */
+ TkWmFocusToplevel, /* 90 */
+ TkWmMapWindow, /* 91 */
+ TkWmNewWindow, /* 92 */
+ TkWmProtocolEventProc, /* 93 */
+ TkWmRemoveFromColormapWindows, /* 94 */
+ TkWmRestackToplevel, /* 95 */
+ TkWmSetClass, /* 96 */
+ TkWmUnmapWindow, /* 97 */
+ TkDebugBitmap, /* 98 */
+ TkDebugBorder, /* 99 */
+ TkDebugCursor, /* 100 */
+ TkDebugColor, /* 101 */
+ TkDebugConfig, /* 102 */
+ TkDebugFont, /* 103 */
+ TkFindStateNumObj, /* 104 */
+ TkGetBitmapPredefTable, /* 105 */
+ TkGetDisplayList, /* 106 */
+ TkGetMainInfoList, /* 107 */
+ TkGetWindowFromObj, /* 108 */
+ TkpGetString, /* 109 */
+ TkpGetSubFonts, /* 110 */
+ TkpGetSystemDefault, /* 111 */
+ TkpMenuThreadInit, /* 112 */
+ TkClipBox, /* 113 */
+ TkCreateRegion, /* 114 */
+ TkDestroyRegion, /* 115 */
+ TkIntersectRegion, /* 116 */
+ TkRectInRegion, /* 117 */
+ TkSetRegion, /* 118 */
+ TkUnionRectWithRegion, /* 119 */
+ 0, /* 120 */
+#if !(defined(_WIN32) || defined(MAC_OSX_TK)) /* X11 */
+ 0, /* 121 */
+#endif /* X11 */
+#if defined(_WIN32) /* WIN */
+ 0, /* 121 */
+#endif /* WIN */
+#ifdef MAC_OSX_TK /* AQUA */
+ 0, /* 121 */ /* Dummy entry for stubs table backwards compatibility */
+ TkpCreateNativeBitmap, /* 121 */
+#endif /* AQUA */
+#if !(defined(_WIN32) || defined(MAC_OSX_TK)) /* X11 */
+ 0, /* 122 */
+#endif /* X11 */
+#if defined(_WIN32) /* WIN */
+ 0, /* 122 */
+#endif /* WIN */
+#ifdef MAC_OSX_TK /* AQUA */
+ 0, /* 122 */ /* Dummy entry for stubs table backwards compatibility */
+ TkpDefineNativeBitmaps, /* 122 */
+#endif /* AQUA */
+ 0, /* 123 */
+#if !(defined(_WIN32) || defined(MAC_OSX_TK)) /* X11 */
+ 0, /* 124 */
+#endif /* X11 */
+#if defined(_WIN32) /* WIN */
+ 0, /* 124 */
+#endif /* WIN */
+#ifdef MAC_OSX_TK /* AQUA */
+ 0, /* 124 */ /* Dummy entry for stubs table backwards compatibility */
+ TkpGetNativeAppBitmap, /* 124 */
+#endif /* AQUA */
+ 0, /* 125 */
+ 0, /* 126 */
+ 0, /* 127 */
+ 0, /* 128 */
+ 0, /* 129 */
+ 0, /* 130 */
+ 0, /* 131 */
+ 0, /* 132 */
+ 0, /* 133 */
+ 0, /* 134 */
+ TkpDrawHighlightBorder, /* 135 */
+ TkSetFocusWin, /* 136 */
+ TkpSetKeycodeAndState, /* 137 */
+ TkpGetKeySym, /* 138 */
+ TkpInitKeymapInfo, /* 139 */
+ TkPhotoGetValidRegion, /* 140 */
+ TkWmStackorderToplevel, /* 141 */
+ TkFocusFree, /* 142 */
+ TkClipCleanup, /* 143 */
+ TkGCCleanup, /* 144 */
+ TkSubtractRegion, /* 145 */
+ TkStylePkgInit, /* 146 */
+ TkStylePkgFree, /* 147 */
+ TkToplevelWindowForCommand, /* 148 */
+ TkGetOptionSpec, /* 149 */
+ TkMakeRawCurve, /* 150 */
+ TkMakeRawCurvePostscript, /* 151 */
+ TkpDrawFrame, /* 152 */
+ TkCreateThreadExitHandler, /* 153 */
+ TkDeleteThreadExitHandler, /* 154 */
+ 0, /* 155 */
+ TkpTestembedCmd, /* 156 */
+ TkpTesttextCmd, /* 157 */
+ TkSelGetSelection, /* 158 */
+ TkTextGetIndex, /* 159 */
+ TkTextIndexBackBytes, /* 160 */
+ TkTextIndexForwBytes, /* 161 */
+ TkTextMakeByteIndex, /* 162 */
+ TkTextPrintIndex, /* 163 */
+ TkTextSetMark, /* 164 */
+ TkTextXviewCmd, /* 165 */
+ TkTextChanged, /* 166 */
+ TkBTreeNumLines, /* 167 */
+ TkTextInsertDisplayProc, /* 168 */
+ TkStateParseProc, /* 169 */
+ TkStatePrintProc, /* 170 */
+ TkCanvasDashParseProc, /* 171 */
+ TkCanvasDashPrintProc, /* 172 */
+ TkOffsetParseProc, /* 173 */
+ TkOffsetPrintProc, /* 174 */
+ TkPixelParseProc, /* 175 */
+ TkPixelPrintProc, /* 176 */
+ TkOrientParseProc, /* 177 */
+ TkOrientPrintProc, /* 178 */
+ TkSmoothParseProc, /* 179 */
+ TkSmoothPrintProc, /* 180 */
+ TkDrawAngledTextLayout, /* 181 */
+ TkUnderlineAngledTextLayout, /* 182 */
+ TkIntersectAngledTextLayout, /* 183 */
+ TkDrawAngledChars, /* 184 */
+};
+
+static const TkIntPlatStubs tkIntPlatStubs = {
+ TCL_STUB_MAGIC,
+ 0,
+#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
+ TkAlignImageData, /* 0 */
+ 0, /* 1 */
+ TkGenerateActivateEvents, /* 2 */
+ TkpGetMS, /* 3 */
+ TkPointerDeadWindow, /* 4 */
+ TkpPrintWindowId, /* 5 */
+ TkpScanWindowId, /* 6 */
+ TkpSetCapture, /* 7 */
+ TkpSetCursor, /* 8 */
+ TkpWmSetState, /* 9 */
+ TkSetPixmapColormap, /* 10 */
+ TkWinCancelMouseTimer, /* 11 */
+ TkWinClipboardRender, /* 12 */
+ TkWinEmbeddedEventProc, /* 13 */
+ TkWinFillRect, /* 14 */
+ TkWinGetBorderPixels, /* 15 */
+ TkWinGetDrawableDC, /* 16 */
+ TkWinGetModifierState, /* 17 */
+ TkWinGetSystemPalette, /* 18 */
+ TkWinGetWrapperWindow, /* 19 */
+ TkWinHandleMenuEvent, /* 20 */
+ TkWinIndexOfColor, /* 21 */
+ TkWinReleaseDrawableDC, /* 22 */
+ TkWinResendEvent, /* 23 */
+ TkWinSelectPalette, /* 24 */
+ TkWinSetMenu, /* 25 */
+ TkWinSetWindowPos, /* 26 */
+ TkWinWmCleanup, /* 27 */
+ TkWinXCleanup, /* 28 */
+ TkWinXInit, /* 29 */
+ TkWinSetForegroundWindow, /* 30 */
+ TkWinDialogDebug, /* 31 */
+ TkWinGetMenuSystemDefault, /* 32 */
+ TkWinGetPlatformId, /* 33 */
+ TkWinSetHINSTANCE, /* 34 */
+ TkWinGetPlatformTheme, /* 35 */
+ TkWinChildProc, /* 36 */
+ TkCreateXEventSource, /* 37 */
+ TkpCmapStressed, /* 38 */
+ TkpSync, /* 39 */
+ TkUnixContainerId, /* 40 */
+ TkUnixDoOneXEvent, /* 41 */
+ TkUnixSetMenubar, /* 42 */
+ TkWmCleanup, /* 43 */
+ TkSendCleanup, /* 44 */
+ TkpTestsendCmd, /* 45 */
+#endif /* WIN */
+#ifdef MAC_OSX_TK /* AQUA */
+ TkGenerateActivateEvents, /* 0 */
+ 0, /* 1 */
+ 0, /* 2 */
+ TkPointerDeadWindow, /* 3 */
+ TkpSetCapture, /* 4 */
+ TkpSetCursor, /* 5 */
+ TkpWmSetState, /* 6 */
+ TkAboutDlg, /* 7 */
+ TkMacOSXButtonKeyState, /* 8 */
+ TkMacOSXClearMenubarActive, /* 9 */
+ TkMacOSXDispatchMenuEvent, /* 10 */
+ TkMacOSXInstallCursor, /* 11 */
+ TkMacOSXHandleTearoffMenu, /* 12 */
+ 0, /* 13 */
+ TkMacOSXDoHLEvent, /* 14 */
+ 0, /* 15 */
+ TkMacOSXGetXWindow, /* 16 */
+ TkMacOSXGrowToplevel, /* 17 */
+ TkMacOSXHandleMenuSelect, /* 18 */
+ 0, /* 19 */
+ 0, /* 20 */
+ TkMacOSXInvalidateWindow, /* 21 */
+ TkMacOSXIsCharacterMissing, /* 22 */
+ TkMacOSXMakeRealWindowExist, /* 23 */
+ TkMacOSXMakeStippleMap, /* 24 */
+ TkMacOSXMenuClick, /* 25 */
+ TkMacOSXRegisterOffScreenWindow, /* 26 */
+ TkMacOSXResizable, /* 27 */
+ TkMacOSXSetHelpMenuItemCount, /* 28 */
+ TkMacOSXSetScrollbarGrow, /* 29 */
+ TkMacOSXSetUpClippingRgn, /* 30 */
+ TkMacOSXSetUpGraphicsPort, /* 31 */
+ TkMacOSXUpdateClipRgn, /* 32 */
+ TkMacOSXUnregisterMacWindow, /* 33 */
+ TkMacOSXUseMenuID, /* 34 */
+ TkMacOSXVisableClipRgn, /* 35 */
+ TkMacOSXWinBounds, /* 36 */
+ TkMacOSXWindowOffset, /* 37 */
+ TkSetMacColor, /* 38 */
+ TkSetWMName, /* 39 */
+ 0, /* 40 */
+ TkMacOSXZoomToplevel, /* 41 */
+ Tk_TopCoordsToWindow, /* 42 */
+ TkMacOSXContainerId, /* 43 */
+ TkMacOSXGetHostToplevel, /* 44 */
+ TkMacOSXPreprocessMenu, /* 45 */
+ TkpIsWindowFloating, /* 46 */
+ TkMacOSXGetCapture, /* 47 */
+ 0, /* 48 */
+ TkGetTransientMaster, /* 49 */
+ TkGenerateButtonEvent, /* 50 */
+ TkGenWMDestroyEvent, /* 51 */
+ TkMacOSXSetDrawingEnabled, /* 52 */
+ TkpGetMS, /* 53 */
+ TkMacOSXDrawable, /* 54 */
+ TkpScanWindowId, /* 55 */
+#endif /* AQUA */
+#if !(defined(_WIN32) || defined(__CYGWIN__) || defined(MAC_OSX_TK)) /* X11 */
+ TkCreateXEventSource, /* 0 */
+ 0, /* 1 */
+ 0, /* 2 */
+ TkpCmapStressed, /* 3 */
+ TkpSync, /* 4 */
+ TkUnixContainerId, /* 5 */
+ TkUnixDoOneXEvent, /* 6 */
+ TkUnixSetMenubar, /* 7 */
+ TkpScanWindowId, /* 8 */
+ TkWmCleanup, /* 9 */
+ TkSendCleanup, /* 10 */
+ 0, /* 11 */
+ TkpWmSetState, /* 12 */
+ TkpTestsendCmd, /* 13 */
+#endif /* X11 */
+};
+
+static const TkIntXlibStubs tkIntXlibStubs = {
+ TCL_STUB_MAGIC,
+ 0,
+#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
+ XSetDashes, /* 0 */
+ XGetModifierMapping, /* 1 */
+ XCreateImage, /* 2 */
+ XGetImage, /* 3 */
+ XGetAtomName, /* 4 */
+ XKeysymToString, /* 5 */
+ XCreateColormap, /* 6 */
+ XCreatePixmapCursor, /* 7 */
+ XCreateGlyphCursor, /* 8 */
+ XGContextFromGC, /* 9 */
+ XListHosts, /* 10 */
+ XKeycodeToKeysym, /* 11 */
+ XStringToKeysym, /* 12 */
+ XRootWindow, /* 13 */
+ XSetErrorHandler, /* 14 */
+ XIconifyWindow, /* 15 */
+ XWithdrawWindow, /* 16 */
+ XGetWMColormapWindows, /* 17 */
+ XAllocColor, /* 18 */
+ XBell, /* 19 */
+ XChangeProperty, /* 20 */
+ XChangeWindowAttributes, /* 21 */
+ XClearWindow, /* 22 */
+ XConfigureWindow, /* 23 */
+ XCopyArea, /* 24 */
+ XCopyPlane, /* 25 */
+ XCreateBitmapFromData, /* 26 */
+ XDefineCursor, /* 27 */
+ XDeleteProperty, /* 28 */
+ XDestroyWindow, /* 29 */
+ XDrawArc, /* 30 */
+ XDrawLines, /* 31 */
+ XDrawRectangle, /* 32 */
+ XFillArc, /* 33 */
+ XFillPolygon, /* 34 */
+ XFillRectangles, /* 35 */
+ XForceScreenSaver, /* 36 */
+ XFreeColormap, /* 37 */
+ XFreeColors, /* 38 */
+ XFreeCursor, /* 39 */
+ XFreeModifiermap, /* 40 */
+ XGetGeometry, /* 41 */
+ XGetInputFocus, /* 42 */
+ XGetWindowProperty, /* 43 */
+ XGetWindowAttributes, /* 44 */
+ XGrabKeyboard, /* 45 */
+ XGrabPointer, /* 46 */
+ XKeysymToKeycode, /* 47 */
+ XLookupColor, /* 48 */
+ XMapWindow, /* 49 */
+ XMoveResizeWindow, /* 50 */
+ XMoveWindow, /* 51 */
+ XNextEvent, /* 52 */
+ XPutBackEvent, /* 53 */
+ XQueryColors, /* 54 */
+ XQueryPointer, /* 55 */
+ XQueryTree, /* 56 */
+ XRaiseWindow, /* 57 */
+ XRefreshKeyboardMapping, /* 58 */
+ XResizeWindow, /* 59 */
+ XSelectInput, /* 60 */
+ XSendEvent, /* 61 */
+ XSetCommand, /* 62 */
+ XSetIconName, /* 63 */
+ XSetInputFocus, /* 64 */
+ XSetSelectionOwner, /* 65 */
+ XSetWindowBackground, /* 66 */
+ XSetWindowBackgroundPixmap, /* 67 */
+ XSetWindowBorder, /* 68 */
+ XSetWindowBorderPixmap, /* 69 */
+ XSetWindowBorderWidth, /* 70 */
+ XSetWindowColormap, /* 71 */
+ XTranslateCoordinates, /* 72 */
+ XUngrabKeyboard, /* 73 */
+ XUngrabPointer, /* 74 */
+ XUnmapWindow, /* 75 */
+ XWindowEvent, /* 76 */
+ XDestroyIC, /* 77 */
+ XFilterEvent, /* 78 */
+ XmbLookupString, /* 79 */
+ TkPutImage, /* 80 */
+ 0, /* 81 */
+ XParseColor, /* 82 */
+ XCreateGC, /* 83 */
+ XFreeGC, /* 84 */
+ XInternAtom, /* 85 */
+ XSetBackground, /* 86 */
+ XSetForeground, /* 87 */
+ XSetClipMask, /* 88 */
+ XSetClipOrigin, /* 89 */
+ XSetTSOrigin, /* 90 */
+ XChangeGC, /* 91 */
+ XSetFont, /* 92 */
+ XSetArcMode, /* 93 */
+ XSetStipple, /* 94 */
+ XSetFillRule, /* 95 */
+ XSetFillStyle, /* 96 */
+ XSetFunction, /* 97 */
+ XSetLineAttributes, /* 98 */
+ _XInitImageFuncPtrs, /* 99 */
+ XCreateIC, /* 100 */
+ XGetVisualInfo, /* 101 */
+ XSetWMClientMachine, /* 102 */
+ XStringListToTextProperty, /* 103 */
+ XDrawLine, /* 104 */
+ XWarpPointer, /* 105 */
+ XFillRectangle, /* 106 */
+ XFlush, /* 107 */
+ XGrabServer, /* 108 */
+ XUngrabServer, /* 109 */
+ XFree, /* 110 */
+ XNoOp, /* 111 */
+ XSynchronize, /* 112 */
+ XSync, /* 113 */
+ XVisualIDFromVisual, /* 114 */
+ 0, /* 115 */
+ 0, /* 116 */
+ 0, /* 117 */
+ 0, /* 118 */
+ 0, /* 119 */
+ XOffsetRegion, /* 120 */
+ XUnionRegion, /* 121 */
+ XCreateWindow, /* 122 */
+ 0, /* 123 */
+ 0, /* 124 */
+ 0, /* 125 */
+ 0, /* 126 */
+ 0, /* 127 */
+ 0, /* 128 */
+ XLowerWindow, /* 129 */
+ XFillArcs, /* 130 */
+ XDrawArcs, /* 131 */
+ XDrawRectangles, /* 132 */
+ XDrawSegments, /* 133 */
+ XDrawPoint, /* 134 */
+ XDrawPoints, /* 135 */
+ XReparentWindow, /* 136 */
+ XPutImage, /* 137 */
+#endif /* WIN */
+#ifdef MAC_OSX_TK /* AQUA */
+ XSetDashes, /* 0 */
+ XGetModifierMapping, /* 1 */
+ XCreateImage, /* 2 */
+ XGetImage, /* 3 */
+ XGetAtomName, /* 4 */
+ XKeysymToString, /* 5 */
+ XCreateColormap, /* 6 */
+ XGContextFromGC, /* 7 */
+ XKeycodeToKeysym, /* 8 */
+ XStringToKeysym, /* 9 */
+ XRootWindow, /* 10 */
+ XSetErrorHandler, /* 11 */
+ XAllocColor, /* 12 */
+ XBell, /* 13 */
+ XChangeProperty, /* 14 */
+ XChangeWindowAttributes, /* 15 */
+ XConfigureWindow, /* 16 */
+ XCopyArea, /* 17 */
+ XCopyPlane, /* 18 */
+ XCreateBitmapFromData, /* 19 */
+ XDefineCursor, /* 20 */
+ XDestroyWindow, /* 21 */
+ XDrawArc, /* 22 */
+ XDrawLines, /* 23 */
+ XDrawRectangle, /* 24 */
+ XFillArc, /* 25 */
+ XFillPolygon, /* 26 */
+ XFillRectangles, /* 27 */
+ XFreeColormap, /* 28 */
+ XFreeColors, /* 29 */
+ XFreeModifiermap, /* 30 */
+ XGetGeometry, /* 31 */
+ XGetWindowProperty, /* 32 */
+ XGrabKeyboard, /* 33 */
+ XGrabPointer, /* 34 */
+ XKeysymToKeycode, /* 35 */
+ XMapWindow, /* 36 */
+ XMoveResizeWindow, /* 37 */
+ XMoveWindow, /* 38 */
+ XQueryPointer, /* 39 */
+ XRaiseWindow, /* 40 */
+ XRefreshKeyboardMapping, /* 41 */
+ XResizeWindow, /* 42 */
+ XSelectInput, /* 43 */
+ XSendEvent, /* 44 */
+ XSetIconName, /* 45 */
+ XSetInputFocus, /* 46 */
+ XSetSelectionOwner, /* 47 */
+ XSetWindowBackground, /* 48 */
+ XSetWindowBackgroundPixmap, /* 49 */
+ XSetWindowBorder, /* 50 */
+ XSetWindowBorderPixmap, /* 51 */
+ XSetWindowBorderWidth, /* 52 */
+ XSetWindowColormap, /* 53 */
+ XUngrabKeyboard, /* 54 */
+ XUngrabPointer, /* 55 */
+ XUnmapWindow, /* 56 */
+ TkPutImage, /* 57 */
+ XParseColor, /* 58 */
+ XCreateGC, /* 59 */
+ XFreeGC, /* 60 */
+ XInternAtom, /* 61 */
+ XSetBackground, /* 62 */
+ XSetForeground, /* 63 */
+ XSetClipMask, /* 64 */
+ XSetClipOrigin, /* 65 */
+ XSetTSOrigin, /* 66 */
+ XChangeGC, /* 67 */
+ XSetFont, /* 68 */
+ XSetArcMode, /* 69 */
+ XSetStipple, /* 70 */
+ XSetFillRule, /* 71 */
+ XSetFillStyle, /* 72 */
+ XSetFunction, /* 73 */
+ XSetLineAttributes, /* 74 */
+ _XInitImageFuncPtrs, /* 75 */
+ XCreateIC, /* 76 */
+ XGetVisualInfo, /* 77 */
+ XSetWMClientMachine, /* 78 */
+ XStringListToTextProperty, /* 79 */
+ XDrawSegments, /* 80 */
+ XForceScreenSaver, /* 81 */
+ XDrawLine, /* 82 */
+ XFillRectangle, /* 83 */
+ XClearWindow, /* 84 */
+ XDrawPoint, /* 85 */
+ XDrawPoints, /* 86 */
+ XWarpPointer, /* 87 */
+ XQueryColor, /* 88 */
+ XQueryColors, /* 89 */
+ XQueryTree, /* 90 */
+ XSync, /* 91 */
+#endif /* AQUA */
+};
+
+static const TkPlatStubs tkPlatStubs = {
+ TCL_STUB_MAGIC,
+ 0,
+#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
+ Tk_AttachHWND, /* 0 */
+ Tk_GetHINSTANCE, /* 1 */
+ Tk_GetHWND, /* 2 */
+ Tk_HWNDToWindow, /* 3 */
+ Tk_PointerEvent, /* 4 */
+ Tk_TranslateWinEvent, /* 5 */
+#endif /* WIN */
+#ifdef MAC_OSX_TK /* AQUA */
+ Tk_MacOSXSetEmbedHandler, /* 0 */
+ Tk_MacOSXTurnOffMenus, /* 1 */
+ Tk_MacOSXTkOwnsCursor, /* 2 */
+ TkMacOSXInitMenus, /* 3 */
+ TkMacOSXInitAppleEvents, /* 4 */
+ TkGenWMConfigureEvent, /* 5 */
+ TkMacOSXInvalClipRgns, /* 6 */
+ TkMacOSXGetDrawablePort, /* 7 */
+ TkMacOSXGetRootControl, /* 8 */
+ Tk_MacOSXSetupTkNotifier, /* 9 */
+ Tk_MacOSXIsAppInFront, /* 10 */
+#endif /* AQUA */
+};
+
+static const TkStubHooks tkStubHooks = {
+ &tkPlatStubs,
+ &tkIntStubs,
+ &tkIntPlatStubs,
+ &tkIntXlibStubs
+};
+
+const TkStubs tkStubs = {
+ TCL_STUB_MAGIC,
+ &tkStubHooks,
+ Tk_MainLoop, /* 0 */
+ Tk_3DBorderColor, /* 1 */
+ Tk_3DBorderGC, /* 2 */
+ Tk_3DHorizontalBevel, /* 3 */
+ Tk_3DVerticalBevel, /* 4 */
+ Tk_AddOption, /* 5 */
+ Tk_BindEvent, /* 6 */
+ Tk_CanvasDrawableCoords, /* 7 */
+ Tk_CanvasEventuallyRedraw, /* 8 */
+ Tk_CanvasGetCoord, /* 9 */
+ Tk_CanvasGetTextInfo, /* 10 */
+ Tk_CanvasPsBitmap, /* 11 */
+ Tk_CanvasPsColor, /* 12 */
+ Tk_CanvasPsFont, /* 13 */
+ Tk_CanvasPsPath, /* 14 */
+ Tk_CanvasPsStipple, /* 15 */
+ Tk_CanvasPsY, /* 16 */
+ Tk_CanvasSetStippleOrigin, /* 17 */
+ Tk_CanvasTagsParseProc, /* 18 */
+ Tk_CanvasTagsPrintProc, /* 19 */
+ Tk_CanvasTkwin, /* 20 */
+ Tk_CanvasWindowCoords, /* 21 */
+ Tk_ChangeWindowAttributes, /* 22 */
+ Tk_CharBbox, /* 23 */
+ Tk_ClearSelection, /* 24 */
+ Tk_ClipboardAppend, /* 25 */
+ Tk_ClipboardClear, /* 26 */
+ Tk_ConfigureInfo, /* 27 */
+ Tk_ConfigureValue, /* 28 */
+ Tk_ConfigureWidget, /* 29 */
+ Tk_ConfigureWindow, /* 30 */
+ Tk_ComputeTextLayout, /* 31 */
+ Tk_CoordsToWindow, /* 32 */
+ Tk_CreateBinding, /* 33 */
+ Tk_CreateBindingTable, /* 34 */
+ Tk_CreateErrorHandler, /* 35 */
+ Tk_CreateEventHandler, /* 36 */
+ Tk_CreateGenericHandler, /* 37 */
+ Tk_CreateImageType, /* 38 */
+ Tk_CreateItemType, /* 39 */
+ Tk_CreatePhotoImageFormat, /* 40 */
+ Tk_CreateSelHandler, /* 41 */
+ Tk_CreateWindow, /* 42 */
+ Tk_CreateWindowFromPath, /* 43 */
+ Tk_DefineBitmap, /* 44 */
+ Tk_DefineCursor, /* 45 */
+ Tk_DeleteAllBindings, /* 46 */
+ Tk_DeleteBinding, /* 47 */
+ Tk_DeleteBindingTable, /* 48 */
+ Tk_DeleteErrorHandler, /* 49 */
+ Tk_DeleteEventHandler, /* 50 */
+ Tk_DeleteGenericHandler, /* 51 */
+ Tk_DeleteImage, /* 52 */
+ Tk_DeleteSelHandler, /* 53 */
+ Tk_DestroyWindow, /* 54 */
+ Tk_DisplayName, /* 55 */
+ Tk_DistanceToTextLayout, /* 56 */
+ Tk_Draw3DPolygon, /* 57 */
+ Tk_Draw3DRectangle, /* 58 */
+ Tk_DrawChars, /* 59 */
+ Tk_DrawFocusHighlight, /* 60 */
+ Tk_DrawTextLayout, /* 61 */
+ Tk_Fill3DPolygon, /* 62 */
+ Tk_Fill3DRectangle, /* 63 */
+ Tk_FindPhoto, /* 64 */
+ Tk_FontId, /* 65 */
+ Tk_Free3DBorder, /* 66 */
+ Tk_FreeBitmap, /* 67 */
+ Tk_FreeColor, /* 68 */
+ Tk_FreeColormap, /* 69 */
+ Tk_FreeCursor, /* 70 */
+ Tk_FreeFont, /* 71 */
+ Tk_FreeGC, /* 72 */
+ Tk_FreeImage, /* 73 */
+ Tk_FreeOptions, /* 74 */
+ Tk_FreePixmap, /* 75 */
+ Tk_FreeTextLayout, /* 76 */
+ Tk_FreeXId, /* 77 */
+ Tk_GCForColor, /* 78 */
+ Tk_GeometryRequest, /* 79 */
+ Tk_Get3DBorder, /* 80 */
+ Tk_GetAllBindings, /* 81 */
+ Tk_GetAnchor, /* 82 */
+ Tk_GetAtomName, /* 83 */
+ Tk_GetBinding, /* 84 */
+ Tk_GetBitmap, /* 85 */
+ Tk_GetBitmapFromData, /* 86 */
+ Tk_GetCapStyle, /* 87 */
+ Tk_GetColor, /* 88 */
+ Tk_GetColorByValue, /* 89 */
+ Tk_GetColormap, /* 90 */
+ Tk_GetCursor, /* 91 */
+ Tk_GetCursorFromData, /* 92 */
+ Tk_GetFont, /* 93 */
+ Tk_GetFontFromObj, /* 94 */
+ Tk_GetFontMetrics, /* 95 */
+ Tk_GetGC, /* 96 */
+ Tk_GetImage, /* 97 */
+ Tk_GetImageMasterData, /* 98 */
+ Tk_GetItemTypes, /* 99 */
+ Tk_GetJoinStyle, /* 100 */
+ Tk_GetJustify, /* 101 */
+ Tk_GetNumMainWindows, /* 102 */
+ Tk_GetOption, /* 103 */
+ Tk_GetPixels, /* 104 */
+ Tk_GetPixmap, /* 105 */
+ Tk_GetRelief, /* 106 */
+ Tk_GetRootCoords, /* 107 */
+ Tk_GetScrollInfo, /* 108 */
+ Tk_GetScreenMM, /* 109 */
+ Tk_GetSelection, /* 110 */
+ Tk_GetUid, /* 111 */
+ Tk_GetVisual, /* 112 */
+ Tk_GetVRootGeometry, /* 113 */
+ Tk_Grab, /* 114 */
+ Tk_HandleEvent, /* 115 */
+ Tk_IdToWindow, /* 116 */
+ Tk_ImageChanged, /* 117 */
+ Tk_Init, /* 118 */
+ Tk_InternAtom, /* 119 */
+ Tk_IntersectTextLayout, /* 120 */
+ Tk_MaintainGeometry, /* 121 */
+ Tk_MainWindow, /* 122 */
+ Tk_MakeWindowExist, /* 123 */
+ Tk_ManageGeometry, /* 124 */
+ Tk_MapWindow, /* 125 */
+ Tk_MeasureChars, /* 126 */
+ Tk_MoveResizeWindow, /* 127 */
+ Tk_MoveWindow, /* 128 */
+ Tk_MoveToplevelWindow, /* 129 */
+ Tk_NameOf3DBorder, /* 130 */
+ Tk_NameOfAnchor, /* 131 */
+ Tk_NameOfBitmap, /* 132 */
+ Tk_NameOfCapStyle, /* 133 */
+ Tk_NameOfColor, /* 134 */
+ Tk_NameOfCursor, /* 135 */
+ Tk_NameOfFont, /* 136 */
+ Tk_NameOfImage, /* 137 */
+ Tk_NameOfJoinStyle, /* 138 */
+ Tk_NameOfJustify, /* 139 */
+ Tk_NameOfRelief, /* 140 */
+ Tk_NameToWindow, /* 141 */
+ Tk_OwnSelection, /* 142 */
+ Tk_ParseArgv, /* 143 */
+ Tk_PhotoPutBlock_NoComposite, /* 144 */
+ Tk_PhotoPutZoomedBlock_NoComposite, /* 145 */
+ Tk_PhotoGetImage, /* 146 */
+ Tk_PhotoBlank, /* 147 */
+ Tk_PhotoExpand_Panic, /* 148 */
+ Tk_PhotoGetSize, /* 149 */
+ Tk_PhotoSetSize_Panic, /* 150 */
+ Tk_PointToChar, /* 151 */
+ Tk_PostscriptFontName, /* 152 */
+ Tk_PreserveColormap, /* 153 */
+ Tk_QueueWindowEvent, /* 154 */
+ Tk_RedrawImage, /* 155 */
+ Tk_ResizeWindow, /* 156 */
+ Tk_RestackWindow, /* 157 */
+ Tk_RestrictEvents, /* 158 */
+ Tk_SafeInit, /* 159 */
+ Tk_SetAppName, /* 160 */
+ Tk_SetBackgroundFromBorder, /* 161 */
+ Tk_SetClass, /* 162 */
+ Tk_SetGrid, /* 163 */
+ Tk_SetInternalBorder, /* 164 */
+ Tk_SetWindowBackground, /* 165 */
+ Tk_SetWindowBackgroundPixmap, /* 166 */
+ Tk_SetWindowBorder, /* 167 */
+ Tk_SetWindowBorderWidth, /* 168 */
+ Tk_SetWindowBorderPixmap, /* 169 */
+ Tk_SetWindowColormap, /* 170 */
+ Tk_SetWindowVisual, /* 171 */
+ Tk_SizeOfBitmap, /* 172 */
+ Tk_SizeOfImage, /* 173 */
+ Tk_StrictMotif, /* 174 */
+ Tk_TextLayoutToPostscript, /* 175 */
+ Tk_TextWidth, /* 176 */
+ Tk_UndefineCursor, /* 177 */
+ Tk_UnderlineChars, /* 178 */
+ Tk_UnderlineTextLayout, /* 179 */
+ Tk_Ungrab, /* 180 */
+ Tk_UnmaintainGeometry, /* 181 */
+ Tk_UnmapWindow, /* 182 */
+ Tk_UnsetGrid, /* 183 */
+ Tk_UpdatePointer, /* 184 */
+ Tk_AllocBitmapFromObj, /* 185 */
+ Tk_Alloc3DBorderFromObj, /* 186 */
+ Tk_AllocColorFromObj, /* 187 */
+ Tk_AllocCursorFromObj, /* 188 */
+ Tk_AllocFontFromObj, /* 189 */
+ Tk_CreateOptionTable, /* 190 */
+ Tk_DeleteOptionTable, /* 191 */
+ Tk_Free3DBorderFromObj, /* 192 */
+ Tk_FreeBitmapFromObj, /* 193 */
+ Tk_FreeColorFromObj, /* 194 */
+ Tk_FreeConfigOptions, /* 195 */
+ Tk_FreeSavedOptions, /* 196 */
+ Tk_FreeCursorFromObj, /* 197 */
+ Tk_FreeFontFromObj, /* 198 */
+ Tk_Get3DBorderFromObj, /* 199 */
+ Tk_GetAnchorFromObj, /* 200 */
+ Tk_GetBitmapFromObj, /* 201 */
+ Tk_GetColorFromObj, /* 202 */
+ Tk_GetCursorFromObj, /* 203 */
+ Tk_GetOptionInfo, /* 204 */
+ Tk_GetOptionValue, /* 205 */
+ Tk_GetJustifyFromObj, /* 206 */
+ Tk_GetMMFromObj, /* 207 */
+ Tk_GetPixelsFromObj, /* 208 */
+ Tk_GetReliefFromObj, /* 209 */
+ Tk_GetScrollInfoObj, /* 210 */
+ Tk_InitOptions, /* 211 */
+ Tk_MainEx, /* 212 */
+ Tk_RestoreSavedOptions, /* 213 */
+ Tk_SetOptions, /* 214 */
+ Tk_InitConsoleChannels, /* 215 */
+ Tk_CreateConsoleWindow, /* 216 */
+ Tk_CreateSmoothMethod, /* 217 */
+ 0, /* 218 */
+ 0, /* 219 */
+ Tk_GetDash, /* 220 */
+ Tk_CreateOutline, /* 221 */
+ Tk_DeleteOutline, /* 222 */
+ Tk_ConfigOutlineGC, /* 223 */
+ Tk_ChangeOutlineGC, /* 224 */
+ Tk_ResetOutlineGC, /* 225 */
+ Tk_CanvasPsOutline, /* 226 */
+ Tk_SetTSOrigin, /* 227 */
+ Tk_CanvasGetCoordFromObj, /* 228 */
+ Tk_CanvasSetOffset, /* 229 */
+ Tk_DitherPhoto, /* 230 */
+ Tk_PostscriptBitmap, /* 231 */
+ Tk_PostscriptColor, /* 232 */
+ Tk_PostscriptFont, /* 233 */
+ Tk_PostscriptImage, /* 234 */
+ Tk_PostscriptPath, /* 235 */
+ Tk_PostscriptStipple, /* 236 */
+ Tk_PostscriptY, /* 237 */
+ Tk_PostscriptPhoto, /* 238 */
+ Tk_CreateClientMessageHandler, /* 239 */
+ Tk_DeleteClientMessageHandler, /* 240 */
+ Tk_CreateAnonymousWindow, /* 241 */
+ Tk_SetClassProcs, /* 242 */
+ Tk_SetInternalBorderEx, /* 243 */
+ Tk_SetMinimumRequestSize, /* 244 */
+ Tk_SetCaretPos, /* 245 */
+ Tk_PhotoPutBlock_Panic, /* 246 */
+ Tk_PhotoPutZoomedBlock_Panic, /* 247 */
+ Tk_CollapseMotionEvents, /* 248 */
+ Tk_RegisterStyleEngine, /* 249 */
+ Tk_GetStyleEngine, /* 250 */
+ Tk_RegisterStyledElement, /* 251 */
+ Tk_GetElementId, /* 252 */
+ Tk_CreateStyle, /* 253 */
+ Tk_GetStyle, /* 254 */
+ Tk_FreeStyle, /* 255 */
+ Tk_NameOfStyle, /* 256 */
+ Tk_AllocStyleFromObj, /* 257 */
+ Tk_GetStyleFromObj, /* 258 */
+ Tk_FreeStyleFromObj, /* 259 */
+ Tk_GetStyledElement, /* 260 */
+ Tk_GetElementSize, /* 261 */
+ Tk_GetElementBox, /* 262 */
+ Tk_GetElementBorderWidth, /* 263 */
+ Tk_DrawElement, /* 264 */
+ Tk_PhotoExpand, /* 265 */
+ Tk_PhotoPutBlock, /* 266 */
+ Tk_PhotoPutZoomedBlock, /* 267 */
+ Tk_PhotoSetSize, /* 268 */
+ Tk_GetUserInactiveTime, /* 269 */
+ Tk_ResetUserInactiveTime, /* 270 */
+ Tk_Interp, /* 271 */
+ Tk_CreateOldImageType, /* 272 */
+ Tk_CreateOldPhotoImageFormat, /* 273 */
+};
+
+/* !END!: Do not edit above this line. */
diff --git a/tk8.6/generic/tkStubLib.c b/tk8.6/generic/tkStubLib.c
new file mode 100644
index 0000000..ea48894
--- /dev/null
+++ b/tk8.6/generic/tkStubLib.c
@@ -0,0 +1,146 @@
+/*
+ * tkStubLib.c --
+ *
+ * Stub object that will be statically linked into extensions that want
+ * to access Tk.
+ *
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
+ * Copyright (c) 1998 Paul Duffin.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkInt.h"
+
+#ifdef _WIN32
+#include "tkWinInt.h"
+#endif
+
+#ifdef MAC_OSX_TK
+#include "tkMacOSXInt.h"
+#endif
+
+#if !(defined(_WIN32) || defined(MAC_OSX_TK))
+#include "tkUnixInt.h"
+#endif
+
+/* TODO: These ought to come in some other way */
+#include "tkPlatDecls.h"
+#include "tkIntXlibDecls.h"
+
+MODULE_SCOPE const TkStubs *tkStubsPtr;
+MODULE_SCOPE const TkPlatStubs *tkPlatStubsPtr;
+MODULE_SCOPE const TkIntStubs *tkIntStubsPtr;
+MODULE_SCOPE const TkIntPlatStubs *tkIntPlatStubsPtr;
+MODULE_SCOPE const TkIntXlibStubs *tkIntXlibStubsPtr;
+
+const TkStubs *tkStubsPtr = NULL;
+const TkPlatStubs *tkPlatStubsPtr = NULL;
+const TkIntStubs *tkIntStubsPtr = NULL;
+const TkIntPlatStubs *tkIntPlatStubsPtr = NULL;
+const TkIntXlibStubs *tkIntXlibStubsPtr = NULL;
+
+/*
+ * Use our own isdigit to avoid linking to libc on windows
+ */
+
+static int
+isDigit(const int c)
+{
+ return (c >= '0' && c <= '9');
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_InitStubs --
+ *
+ * Checks that the correct version of Tk is loaded and that it supports
+ * stubs. It then initialises the stub table pointers.
+ *
+ * Results:
+ * The actual version of Tk that satisfies the request, or NULL to
+ * indicate that an error occurred.
+ *
+ * Side effects:
+ * Sets the stub table pointers.
+ *
+ *----------------------------------------------------------------------
+ */
+#undef Tk_InitStubs
+MODULE_SCOPE const char *
+Tk_InitStubs(
+ Tcl_Interp *interp,
+ const char *version,
+ int exact)
+{
+ const char *packageName = "Tk";
+ const char *errMsg = NULL;
+ ClientData clientData = NULL;
+ const char *actualVersion = tclStubsPtr->tcl_PkgRequireEx(interp,
+ packageName, version, 0, &clientData);
+ const TkStubs *stubsPtr = clientData;
+
+ if (actualVersion == NULL) {
+ return NULL;
+ }
+
+ if (exact) {
+ const char *p = version;
+ int count = 0;
+
+ while (*p) {
+ count += !isDigit(*p++);
+ }
+ if (count == 1) {
+ const char *q = actualVersion;
+
+ p = version;
+ while (*p && (*p == *q)) {
+ p++; q++;
+ }
+ if (*p || isDigit(*q)) {
+ /* Construct error message */
+ tclStubsPtr->tcl_PkgRequireEx(interp, packageName, version, 1, NULL);
+ return NULL;
+ }
+ } else {
+ actualVersion = tclStubsPtr->tcl_PkgRequireEx(interp, packageName,
+ version, 1, NULL);
+ if (actualVersion == NULL) {
+ return NULL;
+ }
+ }
+ }
+ if (stubsPtr == NULL) {
+ errMsg = "missing stub table pointer";
+ } else {
+ tkStubsPtr = stubsPtr;
+ if (stubsPtr->hooks) {
+ tkPlatStubsPtr = stubsPtr->hooks->tkPlatStubs;
+ tkIntStubsPtr = stubsPtr->hooks->tkIntStubs;
+ tkIntPlatStubsPtr = stubsPtr->hooks->tkIntPlatStubs;
+ tkIntXlibStubsPtr = stubsPtr->hooks->tkIntXlibStubs;
+ } else {
+ tkPlatStubsPtr = NULL;
+ tkIntStubsPtr = NULL;
+ tkIntPlatStubsPtr = NULL;
+ tkIntXlibStubsPtr = NULL;
+ }
+ return actualVersion;
+ }
+ tclStubsPtr->tcl_ResetResult(interp);
+ tclStubsPtr->tcl_AppendResult(interp, "Error loading ", packageName,
+ " (requested version ", version, ", actual version ",
+ actualVersion, "): ", errMsg, NULL);
+ return NULL;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkStyle.c b/tk8.6/generic/tkStyle.c
new file mode 100644
index 0000000..5c0f204
--- /dev/null
+++ b/tk8.6/generic/tkStyle.c
@@ -0,0 +1,1554 @@
+/*
+ * tkStyle.c --
+ *
+ * This file implements the widget styles and themes support.
+ *
+ * Copyright (c) 1990-1993 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "tkInt.h"
+
+/*
+ * The following structure is used to cache widget option specs matching an
+ * element's required options defined by Tk_ElementOptionSpecs. It also holds
+ * information behind Tk_StyledElement opaque tokens.
+ */
+
+typedef struct StyledWidgetSpec {
+ struct StyledElement *elementPtr;
+ /* Pointer to the element holding this
+ * structure. */
+ Tk_OptionTable optionTable; /* Option table for the widget class using the
+ * element. */
+ const Tk_OptionSpec **optionsPtr;
+ /* Table of option spec pointers, matching the
+ * option list provided during element
+ * registration. Malloc'd. */
+} StyledWidgetSpec;
+
+/*
+ * Elements are declared using static templates. But static information must
+ * be completed by dynamic information only accessible at runtime. For each
+ * registered element, an instance of the following structure is stored in
+ * each style engine and used to cache information about the widget types
+ * (identified by their optionTable) that use the given element.
+ */
+
+typedef struct StyledElement {
+ struct Tk_ElementSpec *specPtr;
+ /* Filled with template provided during
+ * registration. NULL means no implementation
+ * is available for the current engine. */
+ int nbWidgetSpecs; /* Size of the array below. Number of distinct
+ * widget classes (actually, distinct option
+ * tables) that used the element so far. */
+ StyledWidgetSpec *widgetSpecs;
+ /* See above for the structure definition.
+ * Table grows dynamically as new widgets use
+ * the element. Malloc'd. */
+} StyledElement;
+
+/*
+ * The following structure holds information behind Tk_StyleEngine opaque
+ * tokens.
+ */
+
+typedef struct StyleEngine {
+ const char *name; /* Name of engine. Points to a hash key. */
+ StyledElement *elements; /* Table of widget element descriptors. Each
+ * element is indexed by a unique system-wide
+ * ID. Table grows dynamically as new elements
+ * are registered. Malloc'd. */
+ struct StyleEngine *parentPtr;
+ /* Parent engine. Engines may be layered to
+ * form a fallback chain, terminated by the
+ * default system engine. */
+} StyleEngine;
+
+/*
+ * Styles are instances of style engines. The following structure holds
+ * information behind Tk_Style opaque tokens.
+ */
+
+typedef struct Style {
+ const char *name; /* Name of style. Points to a hash key. */
+ StyleEngine *enginePtr; /* Style engine of which the style is an
+ * instance. */
+ ClientData clientData; /* Data provided during registration. */
+} Style;
+
+/*
+ * Each registered element uses an instance of the following structure.
+ */
+
+typedef struct Element {
+ const char *name; /* Name of element. Points to a hash key. */
+ int id; /* Id of element. */
+ int genericId; /* Id of generic element. */
+ int created; /* Boolean, whether the element was created
+ * explicitly (was registered) or implicitly
+ * (by a derived element). */
+} Element;
+
+/*
+ * Thread-local data.
+ */
+
+typedef struct {
+ int nbInit; /* Number of calls to the init proc. */
+ Tcl_HashTable engineTable; /* Map a name to a style engine. Keys are
+ * strings, values are Tk_StyleEngine
+ * pointers. */
+ StyleEngine *defaultEnginePtr;
+ /* Default, core-defined style engine. Global
+ * fallback for all engines. */
+ Tcl_HashTable styleTable; /* Map a name to a style. Keys are strings,
+ * values are Tk_Style pointers.*/
+ int nbElements; /* Size of the below tables. */
+ Tcl_HashTable elementTable; /* Map a name to an element Id. Keys are
+ * strings, values are integer element IDs. */
+ Element *elements; /* Array of Elements. */
+} ThreadSpecificData;
+
+static Tcl_ThreadDataKey dataKey;
+
+/*
+ * Forward declarations for functions defined later in this file:
+ */
+
+static int CreateElement(const char *name, int create);
+static void DupStyleObjProc(Tcl_Obj *srcObjPtr,
+ Tcl_Obj *dupObjPtr);
+static void FreeElement(Element *elementPtr);
+static void FreeStyledElement(StyledElement *elementPtr);
+static void FreeStyleEngine(StyleEngine *enginePtr);
+static void FreeStyleObjProc(Tcl_Obj *objPtr);
+static void FreeWidgetSpec(StyledWidgetSpec *widgetSpecPtr);
+static StyledElement * GetStyledElement(StyleEngine *enginePtr,
+ int elementId);
+static StyledWidgetSpec*GetWidgetSpec(StyledElement *elementPtr,
+ Tk_OptionTable optionTable);
+static void InitElement(Element *elementPtr, const char *name,
+ int id, int genericId, int created);
+static void InitStyle(Style *stylePtr, const char *name,
+ StyleEngine *enginePtr, ClientData clientData);
+static void InitStyledElement(StyledElement *elementPtr);
+static void InitStyleEngine(StyleEngine *enginePtr,
+ const char *name, StyleEngine *parentPtr);
+static void InitWidgetSpec(StyledWidgetSpec *widgetSpecPtr,
+ StyledElement *elementPtr,
+ Tk_OptionTable optionTable);
+static int SetStyleFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
+
+/*
+ * The following structure defines the implementation of the "style" Tcl
+ * object, used for drawing. The internalRep.twoPtrValue.ptr1 field of each
+ * style object points to the Style structure for the stylefont, or NULL.
+ */
+
+static const Tcl_ObjType styleObjType = {
+ "style", /* name */
+ FreeStyleObjProc, /* freeIntRepProc */
+ DupStyleObjProc, /* dupIntRepProc */
+ NULL, /* updateStringProc */
+ SetStyleFromAny /* setFromAnyProc */
+};
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkStylePkgInit --
+ *
+ * This function is called when an application is created. It initializes
+ * all the structures that are used by the style package on a per
+ * application basis.
+ *
+ * Results:
+ * Stores data in thread-local storage.
+ *
+ * Side effects:
+ * Memory allocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+TkStylePkgInit(
+ TkMainInfo *mainPtr) /* The application being created. */
+{
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (tsdPtr->nbInit != 0) {
+ return;
+ }
+
+ /*
+ * Initialize tables.
+ */
+
+ Tcl_InitHashTable(&tsdPtr->engineTable, TCL_STRING_KEYS);
+ Tcl_InitHashTable(&tsdPtr->styleTable, TCL_STRING_KEYS);
+ Tcl_InitHashTable(&tsdPtr->elementTable, TCL_STRING_KEYS);
+ tsdPtr->nbElements = 0;
+ tsdPtr->elements = NULL;
+
+ /*
+ * Create the default system engine.
+ */
+
+ tsdPtr->defaultEnginePtr = (StyleEngine *)
+ Tk_RegisterStyleEngine(NULL, NULL);
+
+ /*
+ * Create the default system style.
+ */
+
+ Tk_CreateStyle(NULL, (Tk_StyleEngine) tsdPtr->defaultEnginePtr, NULL);
+
+ tsdPtr->nbInit++;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkStylePkgFree --
+ *
+ * This function is called when an application is deleted. It deletes all
+ * the structures that were used by the style package for this
+ * application.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory freed.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+TkStylePkgFree(
+ TkMainInfo *mainPtr) /* The application being deleted. */
+{
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ Tcl_HashSearch search;
+ Tcl_HashEntry *entryPtr;
+ StyleEngine *enginePtr;
+ int i;
+
+ tsdPtr->nbInit--;
+ if (tsdPtr->nbInit != 0) {
+ return;
+ }
+
+ /*
+ * Free styles.
+ */
+
+ entryPtr = Tcl_FirstHashEntry(&tsdPtr->styleTable, &search);
+ while (entryPtr != NULL) {
+ ckfree(Tcl_GetHashValue(entryPtr));
+ entryPtr = Tcl_NextHashEntry(&search);
+ }
+ Tcl_DeleteHashTable(&tsdPtr->styleTable);
+
+ /*
+ * Free engines.
+ */
+
+ entryPtr = Tcl_FirstHashEntry(&tsdPtr->engineTable, &search);
+ while (entryPtr != NULL) {
+ enginePtr = Tcl_GetHashValue(entryPtr);
+ FreeStyleEngine(enginePtr);
+ ckfree(enginePtr);
+ entryPtr = Tcl_NextHashEntry(&search);
+ }
+ Tcl_DeleteHashTable(&tsdPtr->engineTable);
+
+ /*
+ * Free elements.
+ */
+
+ for (i = 0; i < tsdPtr->nbElements; i++) {
+ FreeElement(tsdPtr->elements+i);
+ }
+ Tcl_DeleteHashTable(&tsdPtr->elementTable);
+ ckfree(tsdPtr->elements);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_RegisterStyleEngine --
+ *
+ * This function is called to register a new style engine. Style engines
+ * are stored in thread-local space.
+ *
+ * Results:
+ * The newly allocated engine, or NULL if an engine with the same name
+ * exists.
+ *
+ * Side effects:
+ * Memory allocated. Data added to thread-local table.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tk_StyleEngine
+Tk_RegisterStyleEngine(
+ const char *name, /* Name of the engine to create. NULL or empty
+ * means the default system engine. */
+ Tk_StyleEngine parent) /* The engine's parent. NULL means the default
+ * system engine. */
+{
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ Tcl_HashEntry *entryPtr;
+ int newEntry;
+ StyleEngine *enginePtr;
+
+ /*
+ * Attempt to create a new entry in the engine table.
+ */
+
+ entryPtr = Tcl_CreateHashEntry(&tsdPtr->engineTable,
+ (name != NULL ? name : ""), &newEntry);
+ if (!newEntry) {
+ /*
+ * An engine was already registered by that name.
+ */
+
+ return NULL;
+ }
+
+ /*
+ * Allocate and intitialize a new engine.
+ */
+
+ enginePtr = ckalloc(sizeof(StyleEngine));
+ InitStyleEngine(enginePtr, Tcl_GetHashKey(&tsdPtr->engineTable, entryPtr),
+ (StyleEngine *) parent);
+ Tcl_SetHashValue(entryPtr, enginePtr);
+
+ return (Tk_StyleEngine) enginePtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * InitStyleEngine --
+ *
+ * Initialize a newly allocated style engine.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory allocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+InitStyleEngine(
+ StyleEngine *enginePtr, /* Points to an uninitialized engine. */
+ const char *name, /* Name of the registered engine. NULL or empty
+ * means the default system engine. Usually
+ * points to the hash key. */
+ StyleEngine *parentPtr) /* The engine's parent. NULL means the default
+ * system engine. */
+{
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ int elementId;
+
+ if (name == NULL || *name == '\0') {
+ /*
+ * This is the default style engine.
+ */
+
+ enginePtr->parentPtr = NULL;
+ } else if (parentPtr == NULL) {
+ /*
+ * The default style engine is the parent.
+ */
+
+ enginePtr->parentPtr = tsdPtr->defaultEnginePtr;
+ } else {
+ enginePtr->parentPtr = parentPtr;
+ }
+
+ /*
+ * Allocate and initialize elements array.
+ */
+
+ if (tsdPtr->nbElements > 0) {
+ enginePtr->elements = ckalloc(
+ sizeof(StyledElement) * tsdPtr->nbElements);
+ for (elementId = 0; elementId < tsdPtr->nbElements; elementId++) {
+ InitStyledElement(enginePtr->elements+elementId);
+ }
+ } else {
+ enginePtr->elements = NULL;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FreeStyleEngine --
+ *
+ * Free an engine and its associated data.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * Memory freed.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+FreeStyleEngine(
+ StyleEngine *enginePtr) /* The style engine to free. */
+{
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ int elementId;
+
+ /*
+ * Free allocated elements.
+ */
+
+ for (elementId = 0; elementId < tsdPtr->nbElements; elementId++) {
+ FreeStyledElement(enginePtr->elements+elementId);
+ }
+ ckfree(enginePtr->elements);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_GetStyleEngine --
+ *
+ * Retrieve a registered style engine by its name.
+ *
+ * Results:
+ * A pointer to the style engine, or NULL if none found.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tk_StyleEngine
+Tk_GetStyleEngine(
+ const char *name) /* Name of the engine to retrieve. NULL or
+ * empty means the default system engine. */
+{
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ Tcl_HashEntry *entryPtr;
+
+ if (name == NULL) {
+ return (Tk_StyleEngine) tsdPtr->defaultEnginePtr;
+ }
+
+ entryPtr = Tcl_FindHashEntry(&tsdPtr->engineTable, (name!=NULL?name:""));
+ if (!entryPtr) {
+ return NULL;
+ }
+
+ return Tcl_GetHashValue(entryPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * InitElement --
+ *
+ * Initialize a newly allocated element.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+InitElement(
+ Element *elementPtr, /* Points to an uninitialized element.*/
+ const char *name, /* Name of the registered element. Usually
+ * points to the hash key. */
+ int id, /* Unique element ID. */
+ int genericId, /* ID of generic element. -1 means none. */
+ int created) /* Boolean, whether the element was created
+ * explicitly (was registered) or implicitly
+ * (by a derived element). */
+{
+ elementPtr->name = name;
+ elementPtr->id = id;
+ elementPtr->genericId = genericId;
+ elementPtr->created = (created?1:0);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FreeElement --
+ *
+ * Free an element and its associated data.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory freed.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+FreeElement(
+ Element *elementPtr) /* The element to free. */
+{
+ /* Nothing to do. */
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * InitStyledElement --
+ *
+ * Initialize a newly allocated styled element.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+InitStyledElement(
+ StyledElement *elementPtr) /* Points to an uninitialized element.*/
+{
+ memset(elementPtr, 0, sizeof(StyledElement));
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FreeStyledElement --
+ *
+ * Free a styled element and its associated data.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory freed.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+FreeStyledElement(
+ StyledElement *elementPtr) /* The styled element to free. */
+{
+ int i;
+
+ /*
+ * Free allocated widget specs.
+ */
+
+ for (i = 0; i < elementPtr->nbWidgetSpecs; i++) {
+ FreeWidgetSpec(elementPtr->widgetSpecs+i);
+ }
+ ckfree(elementPtr->widgetSpecs);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CreateElement --
+ *
+ * Find an existing or create a new element.
+ *
+ * Results:
+ * The unique ID for the created or found element.
+ *
+ * Side effects:
+ * Memory allocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static int
+CreateElement(
+ const char *name, /* Name of the element. */
+ int create) /* Boolean, whether the element is being
+ * created explicitly (being registered) or
+ * implicitly (by a derived element). */
+{
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ Tcl_HashEntry *entryPtr, *engineEntryPtr;
+ Tcl_HashSearch search;
+ int newEntry, elementId, genericId = -1;
+ char *dot;
+ StyleEngine *enginePtr;
+
+ /*
+ * Find or create the element.
+ */
+
+ entryPtr = Tcl_CreateHashEntry(&tsdPtr->elementTable, name, &newEntry);
+ if (!newEntry) {
+ elementId = PTR2INT(Tcl_GetHashValue(entryPtr));
+ if (create) {
+ tsdPtr->elements[elementId].created = 1;
+ }
+ return elementId;
+ }
+
+ /*
+ * The element didn't exist. If it's a derived element, find or create its
+ * generic element ID.
+ */
+
+ dot = strchr(name, '.');
+ if (dot) {
+ genericId = CreateElement(dot+1, 0);
+ }
+
+ elementId = tsdPtr->nbElements++;
+ Tcl_SetHashValue(entryPtr, INT2PTR(elementId));
+
+ /*
+ * Reallocate element table.
+ */
+
+ tsdPtr->elements = ckrealloc(tsdPtr->elements,
+ sizeof(Element) * tsdPtr->nbElements);
+ InitElement(tsdPtr->elements+elementId,
+ Tcl_GetHashKey(&tsdPtr->elementTable, entryPtr), elementId,
+ genericId, create);
+
+ /*
+ * Reallocate style engines' element table.
+ */
+
+ engineEntryPtr = Tcl_FirstHashEntry(&tsdPtr->engineTable, &search);
+ while (engineEntryPtr != NULL) {
+ enginePtr = Tcl_GetHashValue(engineEntryPtr);
+
+ enginePtr->elements = ckrealloc(enginePtr->elements,
+ sizeof(StyledElement) * tsdPtr->nbElements);
+ InitStyledElement(enginePtr->elements+elementId);
+
+ engineEntryPtr = Tcl_NextHashEntry(&search);
+ }
+
+ return elementId;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_GetElementId --
+ *
+ * Find an existing element.
+ *
+ * Results:
+ * The unique ID for the found element, or -1 if not found.
+ *
+ * Side effects:
+ * Generic elements may be created.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+Tk_GetElementId(
+ const char *name) /* Name of the element. */
+{
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ Tcl_HashEntry *entryPtr;
+ int genericId = -1;
+ char *dot;
+
+ /*
+ * Find the element Id.
+ */
+
+ entryPtr = Tcl_FindHashEntry(&tsdPtr->elementTable, name);
+ if (entryPtr) {
+ return PTR2INT(Tcl_GetHashValue(entryPtr));
+ }
+
+ /*
+ * Element not found. If the given name was derived, then first search for
+ * the generic element. If found, create the new derived element.
+ */
+
+ dot = strchr(name, '.');
+ if (!dot) {
+ return -1;
+ }
+ genericId = Tk_GetElementId(dot+1);
+ if (genericId == -1) {
+ return -1;
+ }
+ if (!tsdPtr->elements[genericId].created) {
+ /*
+ * The generic element was created implicitly and thus has no real
+ * existence.
+ */
+
+ return -1;
+ } else {
+ /*
+ * The generic element was created explicitly. Create the derived
+ * element.
+ */
+
+ return CreateElement(name, 1);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_RegisterStyledElement --
+ *
+ * Register an implementation of a new or existing element for the given
+ * style engine.
+ *
+ * Results:
+ * The unique ID for the created or found element.
+ *
+ * Side effects:
+ * Elements may be created. Memory allocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+Tk_RegisterStyledElement(
+ Tk_StyleEngine engine, /* Style engine providing the
+ * implementation. */
+ Tk_ElementSpec *templatePtr)/* Static template information about the
+ * element. */
+{
+ int elementId;
+ StyledElement *elementPtr;
+ Tk_ElementSpec *specPtr;
+ int nbOptions;
+ register Tk_ElementOptionSpec *srcOptions, *dstOptions;
+
+ if (templatePtr->version != TK_STYLE_VERSION_1) {
+ /*
+ * Version mismatch. Do nothing.
+ */
+
+ return -1;
+ }
+
+ if (engine == NULL) {
+ engine = Tk_GetStyleEngine(NULL);
+ }
+
+ /*
+ * Register the element, allocating storage in the various engines if
+ * necessary.
+ */
+
+ elementId = CreateElement(templatePtr->name, 1);
+
+ /*
+ * Initialize the styled element.
+ */
+
+ elementPtr = ((StyleEngine *) engine)->elements+elementId;
+
+ specPtr = ckalloc(sizeof(Tk_ElementSpec));
+ specPtr->version = templatePtr->version;
+ specPtr->name = ckalloc(strlen(templatePtr->name)+1);
+ strcpy(specPtr->name, templatePtr->name);
+ nbOptions = 0;
+ for (nbOptions = 0, srcOptions = templatePtr->options;
+ srcOptions->name != NULL; nbOptions++, srcOptions++) {
+ /* empty body */
+ }
+ specPtr->options =
+ ckalloc(sizeof(Tk_ElementOptionSpec) * (nbOptions+1));
+ for (srcOptions = templatePtr->options, dstOptions = specPtr->options;
+ /* End condition within loop */; srcOptions++, dstOptions++) {
+ if (srcOptions->name == NULL) {
+ dstOptions->name = NULL;
+ break;
+ }
+
+ dstOptions->name = ckalloc(strlen(srcOptions->name)+1);
+ strcpy(dstOptions->name, srcOptions->name);
+ dstOptions->type = srcOptions->type;
+ }
+ specPtr->getSize = templatePtr->getSize;
+ specPtr->getBox = templatePtr->getBox;
+ specPtr->getBorderWidth = templatePtr->getBorderWidth;
+ specPtr->draw = templatePtr->draw;
+
+ elementPtr->specPtr = specPtr;
+ elementPtr->nbWidgetSpecs = 0;
+ elementPtr->widgetSpecs = NULL;
+
+ return elementId;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GetStyledElement --
+ *
+ * Get a registered implementation of an existing element for the given
+ * style engine.
+ *
+ * Results:
+ * The styled element descriptor, or NULL if not found.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static StyledElement *
+GetStyledElement(
+ StyleEngine *enginePtr, /* Style engine providing the implementation.
+ * NULL means the default system engine. */
+ int elementId) /* Unique element ID */
+{
+ StyledElement *elementPtr;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ StyleEngine *enginePtr2;
+
+ if (enginePtr == NULL) {
+ enginePtr = tsdPtr->defaultEnginePtr;
+ }
+
+ while (elementId >= 0 && elementId < tsdPtr->nbElements) {
+ /*
+ * Look for an implemented element through the engine chain.
+ */
+
+ enginePtr2 = enginePtr;
+ do {
+ elementPtr = enginePtr2->elements+elementId;
+ if (elementPtr->specPtr != NULL) {
+ return elementPtr;
+ }
+ enginePtr2 = enginePtr2->parentPtr;
+ } while (enginePtr2 != NULL);
+
+ /*
+ * None found, try with the generic element.
+ */
+
+ elementId = tsdPtr->elements[elementId].genericId;
+ }
+
+ /*
+ * No matching element found.
+ */
+
+ return NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * InitWidgetSpec --
+ *
+ * Initialize a newly allocated widget spec.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory allocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+InitWidgetSpec(
+ StyledWidgetSpec *widgetSpecPtr,
+ /* Points to an uninitialized widget spec. */
+ StyledElement *elementPtr, /* Styled element descriptor. */
+ Tk_OptionTable optionTable) /* The widget's option table. */
+{
+ int i, nbOptions;
+ Tk_ElementOptionSpec *elementOptionPtr;
+ const Tk_OptionSpec *widgetOptionPtr;
+
+ widgetSpecPtr->elementPtr = elementPtr;
+ widgetSpecPtr->optionTable = optionTable;
+
+ /*
+ * Count the number of options.
+ */
+
+ for (nbOptions = 0, elementOptionPtr = elementPtr->specPtr->options;
+ elementOptionPtr->name != NULL; nbOptions++, elementOptionPtr++) {
+ /* empty body */
+ }
+
+ /*
+ * Build the widget option list.
+ */
+
+ widgetSpecPtr->optionsPtr =
+ ckalloc(sizeof(Tk_OptionSpec *) * nbOptions);
+ for (i = 0, elementOptionPtr = elementPtr->specPtr->options;
+ i < nbOptions; i++, elementOptionPtr++) {
+ widgetOptionPtr = TkGetOptionSpec(elementOptionPtr->name, optionTable);
+
+ /*
+ * Check that the widget option type is compatible with one of the
+ * element's required types.
+ */
+
+ if (elementOptionPtr->type == TK_OPTION_END
+ || elementOptionPtr->type == widgetOptionPtr->type) {
+ widgetSpecPtr->optionsPtr[i] = widgetOptionPtr;
+ } else {
+ widgetSpecPtr->optionsPtr[i] = NULL;
+ }
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FreeWidgetSpec --
+ *
+ * Free a widget spec and its associated data.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * Memory freed.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+FreeWidgetSpec(
+ StyledWidgetSpec *widgetSpecPtr)
+ /* The widget spec to free. */
+{
+ ckfree(widgetSpecPtr->optionsPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GetWidgetSpec --
+ *
+ * Return a new or existing widget spec for the given element and widget
+ * type (identified by its option table).
+ *
+ * Results:
+ * A pointer to the matching widget spec.
+ *
+ * Side effects:
+ * Memory may be allocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static StyledWidgetSpec *
+GetWidgetSpec(
+ StyledElement *elementPtr, /* Styled element descriptor. */
+ Tk_OptionTable optionTable) /* The widget's option table. */
+{
+ StyledWidgetSpec *widgetSpecPtr;
+ int i;
+
+ /*
+ * Try to find an existing widget spec.
+ */
+
+ for (i = 0; i < elementPtr->nbWidgetSpecs; i++) {
+ widgetSpecPtr = elementPtr->widgetSpecs+i;
+ if (widgetSpecPtr->optionTable == optionTable) {
+ return widgetSpecPtr;
+ }
+ }
+
+ /*
+ * Create and initialize a new widget spec.
+ */
+
+ i = elementPtr->nbWidgetSpecs++;
+ elementPtr->widgetSpecs = ckrealloc(elementPtr->widgetSpecs,
+ sizeof(StyledWidgetSpec) * elementPtr->nbWidgetSpecs);
+ widgetSpecPtr = elementPtr->widgetSpecs+i;
+ InitWidgetSpec(widgetSpecPtr, elementPtr, optionTable);
+
+ return widgetSpecPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_GetStyledElement --
+ *
+ * This function returns a styled instance of the given element.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Cached data may be allocated or updated.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tk_StyledElement
+Tk_GetStyledElement(
+ Tk_Style style, /* The widget style. */
+ int elementId, /* Unique element ID. */
+ Tk_OptionTable optionTable) /* Option table for the widget. */
+{
+ Style *stylePtr = (Style *) style;
+ StyledElement *elementPtr;
+
+ /*
+ * Get an element implementation and call corresponding hook.
+ */
+
+ elementPtr = GetStyledElement((stylePtr?stylePtr->enginePtr:NULL),
+ elementId);
+ if (!elementPtr) {
+ return NULL;
+ }
+
+ return (Tk_StyledElement) GetWidgetSpec(elementPtr, optionTable);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_GetElementSize --
+ *
+ * This function computes the size of the given widget element according
+ * to its style.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Cached data may be allocated or updated.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+Tk_GetElementSize(
+ Tk_Style style, /* The widget style. */
+ Tk_StyledElement element, /* The styled element, previously returned by
+ * Tk_GetStyledElement. */
+ char *recordPtr, /* The widget record. */
+ Tk_Window tkwin, /* The widget window. */
+ int width, int height, /* Requested size. */
+ int inner, /* If TRUE, compute the outer size according
+ * to the requested minimum inner size. If
+ * FALSE, compute the inner size according to
+ * the requested maximum outer size. */
+ int *widthPtr, int *heightPtr)
+ /* Returned size. */
+{
+ Style *stylePtr = (Style *) style;
+ StyledWidgetSpec *widgetSpecPtr = (StyledWidgetSpec *) element;
+
+ widgetSpecPtr->elementPtr->specPtr->getSize(stylePtr->clientData,
+ recordPtr, widgetSpecPtr->optionsPtr, tkwin, width, height, inner,
+ widthPtr, heightPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_GetElementBox --
+ *
+ * This function computes the bounding or inscribed box coordinates of
+ * the given widget element according to its style and within the given
+ * limits.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Cached data may be allocated or updated.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+Tk_GetElementBox(
+ Tk_Style style, /* The widget style. */
+ Tk_StyledElement element, /* The styled element, previously returned by
+ * Tk_GetStyledElement. */
+ char *recordPtr, /* The widget record. */
+ Tk_Window tkwin, /* The widget window. */
+ int x, int y, /* Top left corner of available area. */
+ int width, int height, /* Size of available area. */
+ int inner, /* Boolean. If TRUE, compute the bounding box
+ * according to the requested inscribed box
+ * size. If FALSE, compute the inscribed box
+ * according to the requested bounding box. */
+ int *xPtr, int *yPtr, /* Returned top left corner. */
+ int *widthPtr, int *heightPtr)
+ /* Returned size. */
+{
+ Style *stylePtr = (Style *) style;
+ StyledWidgetSpec *widgetSpecPtr = (StyledWidgetSpec *) element;
+
+ widgetSpecPtr->elementPtr->specPtr->getBox(stylePtr->clientData,
+ recordPtr, widgetSpecPtr->optionsPtr, tkwin, x, y, width, height,
+ inner, xPtr, yPtr, widthPtr, heightPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_GetElementBorderWidth --
+ *
+ * This function computes the border widthof the given widget element
+ * according to its style and within the given limits.
+ *
+ * Results:
+ * Border width in pixels. This value is uniform for all four sides.
+ *
+ * Side effects:
+ * Cached data may be allocated or updated.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+Tk_GetElementBorderWidth(
+ Tk_Style style, /* The widget style. */
+ Tk_StyledElement element, /* The styled element, previously returned by
+ * Tk_GetStyledElement. */
+ char *recordPtr, /* The widget record. */
+ Tk_Window tkwin) /* The widget window. */
+{
+ Style *stylePtr = (Style *) style;
+ StyledWidgetSpec *widgetSpecPtr = (StyledWidgetSpec *) element;
+
+ return widgetSpecPtr->elementPtr->specPtr->getBorderWidth(
+ stylePtr->clientData, recordPtr, widgetSpecPtr->optionsPtr, tkwin);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_DrawElement --
+ *
+ * This function draw the given widget element in a given drawable area.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * Cached data may be allocated or updated.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+Tk_DrawElement(
+ Tk_Style style, /* The widget style. */
+ Tk_StyledElement element, /* The styled element, previously returned by
+ * Tk_GetStyledElement. */
+ char *recordPtr, /* The widget record. */
+ Tk_Window tkwin, /* The widget window. */
+ Drawable d, /* Where to draw element. */
+ int x, int y, /* Top left corner of element. */
+ int width, int height, /* Size of element. */
+ int state) /* Drawing state flags. */
+{
+ Style *stylePtr = (Style *) style;
+ StyledWidgetSpec *widgetSpecPtr = (StyledWidgetSpec *) element;
+
+ widgetSpecPtr->elementPtr->specPtr->draw(stylePtr->clientData,
+ recordPtr, widgetSpecPtr->optionsPtr, tkwin, d, x, y, width,
+ height, state);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_CreateStyle --
+ *
+ * This function is called to create a new style as an instance of the
+ * given engine. Styles are stored in thread-local space.
+ *
+ * Results:
+ * The newly allocated style, or NULL if the style already exists.
+ *
+ * Side effects:
+ * Memory allocated. Data added to thread-local table.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tk_Style
+Tk_CreateStyle(
+ const char *name, /* Name of the style to create. NULL or empty
+ * means the default system style. */
+ Tk_StyleEngine engine, /* The style engine. */
+ ClientData clientData) /* Private data passed as is to engine code. */
+{
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ Tcl_HashEntry *entryPtr;
+ int newEntry;
+ Style *stylePtr;
+
+ /*
+ * Attempt to create a new entry in the style table.
+ */
+
+ entryPtr = Tcl_CreateHashEntry(&tsdPtr->styleTable, (name?name:""),
+ &newEntry);
+ if (!newEntry) {
+ /*
+ * A style was already registered by that name.
+ */
+
+ return NULL;
+ }
+
+ /*
+ * Allocate and intitialize a new style.
+ */
+
+ stylePtr = ckalloc(sizeof(Style));
+ InitStyle(stylePtr, Tcl_GetHashKey(&tsdPtr->styleTable, entryPtr),
+ (engine!=NULL ? (StyleEngine*) engine : tsdPtr->defaultEnginePtr),
+ clientData);
+ Tcl_SetHashValue(entryPtr, stylePtr);
+
+ return (Tk_Style) stylePtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_NameOfStyle --
+ *
+ * Given a style, return its registered name.
+ *
+ * Results:
+ * The return value is the name that was passed to Tk_CreateStyle() to
+ * create the style. The storage for the returned string is private (it
+ * points to the corresponding hash key) The caller should not modify
+ * this string.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+const char *
+Tk_NameOfStyle(
+ Tk_Style style) /* Style whose name is desired. */
+{
+ Style *stylePtr = (Style *) style;
+
+ return stylePtr->name;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * InitStyle --
+ *
+ * Initialize a newly allocated style.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+InitStyle(
+ Style *stylePtr, /* Points to an uninitialized style. */
+ const char *name, /* Name of the registered style. NULL or empty
+ * means the default system style. Usually
+ * points to the hash key. */
+ StyleEngine *enginePtr, /* The style engine. */
+ ClientData clientData) /* Private data passed as is to engine code. */
+{
+ stylePtr->name = name;
+ stylePtr->enginePtr = enginePtr;
+ stylePtr->clientData = clientData;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_GetStyle --
+ *
+ * Retrieve a registered style by its name.
+ *
+ * Results:
+ * A pointer to the style engine, or NULL if none found. In the latter
+ * case and if the interp is not NULL, an error message is left in the
+ * interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tk_Style
+Tk_GetStyle(
+ Tcl_Interp *interp, /* Interp for error return. */
+ const char *name) /* Name of the style to retrieve. NULL or empty
+ * means the default system style. */
+{
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ Tcl_HashEntry *entryPtr;
+ Style *stylePtr;
+
+ /*
+ * Search for a corresponding entry in the style table.
+ */
+
+ entryPtr = Tcl_FindHashEntry(&tsdPtr->styleTable, (name!=NULL?name:""));
+ if (entryPtr == NULL) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "style \"%s\" doesn't exist", name));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "STYLE", name, NULL);
+ }
+ return NULL;
+ }
+ stylePtr = Tcl_GetHashValue(entryPtr);
+
+ return (Tk_Style) stylePtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_FreeStyle --
+ *
+ * No-op. Present only for stubs compatibility.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+Tk_FreeStyle(
+ Tk_Style style)
+{
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_AllocStyleFromObj --
+ *
+ * Map the string name of a style to a corresponding Tk_Style. The style
+ * must have already been created by Tk_CreateStyle.
+ *
+ * Results:
+ * The return value is a token for the style that matches objPtr, or NULL
+ * if none found. If NULL is returned, an error message will be left in
+ * interp's result object.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tk_Style
+Tk_AllocStyleFromObj(
+ Tcl_Interp *interp, /* Interp for error return. */
+ Tcl_Obj *objPtr) /* Object containing name of the style to
+ * retrieve. */
+{
+ Style *stylePtr;
+
+ if (objPtr->typePtr != &styleObjType) {
+ SetStyleFromAny(interp, objPtr);
+ }
+ stylePtr = objPtr->internalRep.twoPtrValue.ptr1;
+
+ return (Tk_Style) stylePtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetStyleFromObj --
+ *
+ * Find the style that corresponds to a given object. The style must have
+ * already been created by Tk_CreateStyle.
+ *
+ * Results:
+ * The return value is a token for the style that matches objPtr, or NULL
+ * if none found.
+ *
+ * Side effects:
+ * If the object is not already a style ref, the conversion will free any
+ * old internal representation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_Style
+Tk_GetStyleFromObj(
+ Tcl_Obj *objPtr) /* The object from which to get the style. */
+{
+ if (objPtr->typePtr != &styleObjType) {
+ SetStyleFromAny(NULL, objPtr);
+ }
+
+ return objPtr->internalRep.twoPtrValue.ptr1;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_FreeStyleFromObj --
+ *
+ * No-op. Present only for stubs compatibility.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Tk_FreeStyleFromObj(
+ Tcl_Obj *objPtr)
+{
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetStyleFromAny --
+ *
+ * Convert the internal representation of a Tcl object to the style
+ * internal form.
+ *
+ * Results:
+ * Always returns TCL_OK. If an error occurs is returned (e.g. the style
+ * doesn't exist), an error message will be left in interp's result.
+ *
+ * Side effects:
+ * The object is left with its typePtr pointing to styleObjType.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetStyleFromAny(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ Tcl_Obj *objPtr) /* The object to convert. */
+{
+ const Tcl_ObjType *typePtr;
+ const char *name;
+
+ /*
+ * Free the old internalRep before setting the new one.
+ */
+
+ name = Tcl_GetString(objPtr);
+ typePtr = objPtr->typePtr;
+ if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
+ typePtr->freeIntRepProc(objPtr);
+ }
+
+ objPtr->typePtr = &styleObjType;
+ objPtr->internalRep.twoPtrValue.ptr1 = Tk_GetStyle(interp, name);
+
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FreeStyleObjProc --
+ *
+ * This proc is called to release an object reference to a style. Called
+ * when the object's internal rep is released.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+FreeStyleObjProc(
+ Tcl_Obj *objPtr) /* The object we are releasing. */
+{
+ objPtr->internalRep.twoPtrValue.ptr1 = NULL;
+ objPtr->typePtr = NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DupStyleObjProc --
+ *
+ * When a cached style object is duplicated, this is called to update the
+ * internal reps.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+DupStyleObjProc(
+ Tcl_Obj *srcObjPtr, /* The object we are copying from. */
+ Tcl_Obj *dupObjPtr) /* The object we are copying to. */
+{
+ dupObjPtr->typePtr = srcObjPtr->typePtr;
+ dupObjPtr->internalRep.twoPtrValue.ptr1 =
+ srcObjPtr->internalRep.twoPtrValue.ptr1;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkTest.c b/tk8.6/generic/tkTest.c
new file mode 100644
index 0000000..a8929b9
--- /dev/null
+++ b/tk8.6/generic/tkTest.c
@@ -0,0 +1,2086 @@
+/*
+ * tkTest.c --
+ *
+ * This file contains C command functions for a bunch of additional Tcl
+ * commands that are used for testing out Tcl's C interfaces. These
+ * commands are not normally included in Tcl applications; they're only
+ * used for testing.
+ *
+ * Copyright (c) 1993-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#undef STATIC_BUILD
+#ifndef USE_TCL_STUBS
+# define USE_TCL_STUBS
+#endif
+#ifndef USE_TK_STUBS
+# define USE_TK_STUBS
+#endif
+#include "tkInt.h"
+#include "tkText.h"
+
+#ifdef _WIN32
+#include "tkWinInt.h"
+#endif
+
+#if defined(MAC_OSX_TK)
+#include "tkMacOSXInt.h"
+#include "tkScrollbar.h"
+#define LOG_DISPLAY TkTestLogDisplay()
+#else
+#define LOG_DISPLAY 1
+#endif
+
+#ifdef __UNIX__
+#include "tkUnixInt.h"
+#endif
+
+/*
+ * TCL_STORAGE_CLASS is set unconditionally to DLLEXPORT because the
+ * Tcltest_Init declaration is in the source file itself, which is only
+ * accessed when we are building a library.
+ */
+
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLEXPORT
+EXTERN int Tktest_Init(Tcl_Interp *interp);
+/*
+ * The following data structure represents the master for a test image:
+ */
+
+typedef struct TImageMaster {
+ Tk_ImageMaster master; /* Tk's token for image master. */
+ Tcl_Interp *interp; /* Interpreter for application. */
+ int width, height; /* Dimensions of image. */
+ char *imageName; /* Name of image (malloc-ed). */
+ char *varName; /* Name of variable in which to log events for
+ * image (malloc-ed). */
+} TImageMaster;
+
+/*
+ * The following data structure represents a particular use of a particular
+ * test image.
+ */
+
+typedef struct TImageInstance {
+ TImageMaster *masterPtr; /* Pointer to master for image. */
+ XColor *fg; /* Foreground color for drawing in image. */
+ GC gc; /* Graphics context for drawing in image. */
+} TImageInstance;
+
+/*
+ * The type record for test images:
+ */
+
+static int ImageCreate(Tcl_Interp *interp,
+ const char *name, int argc, Tcl_Obj *const objv[],
+ const Tk_ImageType *typePtr, Tk_ImageMaster master,
+ ClientData *clientDataPtr);
+static ClientData ImageGet(Tk_Window tkwin, ClientData clientData);
+static void ImageDisplay(ClientData clientData,
+ Display *display, Drawable drawable,
+ int imageX, int imageY, int width,
+ int height, int drawableX,
+ int drawableY);
+static void ImageFree(ClientData clientData, Display *display);
+static void ImageDelete(ClientData clientData);
+
+static Tk_ImageType imageType = {
+ "test", /* name */
+ ImageCreate, /* createProc */
+ ImageGet, /* getProc */
+ ImageDisplay, /* displayProc */
+ ImageFree, /* freeProc */
+ ImageDelete, /* deleteProc */
+ NULL, /* postscriptPtr */
+ NULL, /* nextPtr */
+ NULL
+};
+
+/*
+ * One of the following structures describes each of the interpreters created
+ * by the "testnewapp" command. This information is used by the
+ * "testdeleteinterps" command to destroy all of those interpreters.
+ */
+
+typedef struct NewApp {
+ Tcl_Interp *interp; /* Token for interpreter. */
+ struct NewApp *nextPtr; /* Next in list of new interpreters. */
+} NewApp;
+
+static NewApp *newAppPtr = NULL;/* First in list of all new interpreters. */
+
+/*
+ * Header for trivial configuration command items.
+ */
+
+#define ODD TK_CONFIG_USER_BIT
+#define EVEN (TK_CONFIG_USER_BIT << 1)
+
+enum {
+ NONE,
+ ODD_TYPE,
+ EVEN_TYPE
+};
+
+typedef struct TrivialCommandHeader {
+ Tcl_Interp *interp; /* The interp that this command lives in. */
+ Tk_OptionTable optionTable; /* The option table that go with this
+ * command. */
+ Tk_Window tkwin; /* For widgets, the window associated with
+ * this widget. */
+ Tcl_Command widgetCmd; /* For widgets, the command associated with
+ * this widget. */
+} TrivialCommandHeader;
+
+/*
+ * Forward declarations for functions defined later in this file:
+ */
+
+static int ImageObjCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj * const objv[]);
+static int TestbitmapObjCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj * const objv[]);
+static int TestborderObjCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj * const objv[]);
+static int TestcolorObjCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj * const objv[]);
+static int TestcursorObjCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj * const objv[]);
+static int TestdeleteappsObjCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj * const objv[]);
+static int TestfontObjCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int TestmakeexistObjCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+#if !(defined(_WIN32) || defined(MAC_OSX_TK) || defined(__CYGWIN__))
+static int TestmenubarObjCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+#endif
+#if defined(_WIN32)
+static int TestmetricsObjCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj * const objv[]);
+#endif
+static int TestobjconfigObjCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj * const objv[]);
+static int CustomOptionSet(ClientData clientData,
+ Tcl_Interp *interp, Tk_Window tkwin,
+ Tcl_Obj **value, char *recordPtr,
+ int internalOffset, char *saveInternalPtr,
+ int flags);
+static Tcl_Obj * CustomOptionGet(ClientData clientData,
+ Tk_Window tkwin, char *recordPtr,
+ int internalOffset);
+static void CustomOptionRestore(ClientData clientData,
+ Tk_Window tkwin, char *internalPtr,
+ char *saveInternalPtr);
+static void CustomOptionFree(ClientData clientData,
+ Tk_Window tkwin, char *internalPtr);
+static int TestpropObjCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj * const objv[]);
+#if !(defined(_WIN32) || defined(MAC_OSX_TK) || defined(__CYGWIN__))
+static int TestwrapperObjCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj * const objv[]);
+#endif
+static void TrivialCmdDeletedProc(ClientData clientData);
+static int TrivialConfigObjCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj * const objv[]);
+static void TrivialEventProc(ClientData clientData,
+ XEvent *eventPtr);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tktest_Init --
+ *
+ * This function performs initialization for the Tk test suite extensions.
+ *
+ * Results:
+ * Returns a standard Tcl completion code, and leaves an error message in
+ * the interp's result if an error occurs.
+ *
+ * Side effects:
+ * Creates several test commands.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tktest_Init(
+ Tcl_Interp *interp) /* Interpreter for application. */
+{
+ static int initialized = 0;
+
+ if (Tcl_InitStubs(interp, "8.1", 0) == NULL) {
+ return TCL_ERROR;
+ }
+ if (Tk_InitStubs(interp, TK_VERSION, 0) == NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Create additional commands for testing Tk.
+ */
+
+ if (Tcl_PkgProvideEx(interp, "Tktest", TK_PATCH_LEVEL, NULL) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ Tcl_CreateObjCommand(interp, "square", SquareObjCmd, NULL, NULL);
+ Tcl_CreateObjCommand(interp, "testbitmap", TestbitmapObjCmd,
+ (ClientData) Tk_MainWindow(interp), NULL);
+ Tcl_CreateObjCommand(interp, "testborder", TestborderObjCmd,
+ (ClientData) Tk_MainWindow(interp), NULL);
+ Tcl_CreateObjCommand(interp, "testcolor", TestcolorObjCmd,
+ (ClientData) Tk_MainWindow(interp), NULL);
+ Tcl_CreateObjCommand(interp, "testcursor", TestcursorObjCmd,
+ (ClientData) Tk_MainWindow(interp), NULL);
+ Tcl_CreateObjCommand(interp, "testdeleteapps", TestdeleteappsObjCmd,
+ (ClientData) Tk_MainWindow(interp), NULL);
+ Tcl_CreateObjCommand(interp, "testembed", TkpTestembedCmd,
+ (ClientData) Tk_MainWindow(interp), NULL);
+ Tcl_CreateObjCommand(interp, "testobjconfig", TestobjconfigObjCmd,
+ (ClientData) Tk_MainWindow(interp), NULL);
+ Tcl_CreateObjCommand(interp, "testfont", TestfontObjCmd,
+ (ClientData) Tk_MainWindow(interp), NULL);
+ Tcl_CreateObjCommand(interp, "testmakeexist", TestmakeexistObjCmd,
+ (ClientData) Tk_MainWindow(interp), NULL);
+ Tcl_CreateObjCommand(interp, "testprop", TestpropObjCmd,
+ (ClientData) Tk_MainWindow(interp), NULL);
+ Tcl_CreateObjCommand(interp, "testtext", TkpTesttextCmd,
+ (ClientData) Tk_MainWindow(interp), NULL);
+
+#if defined(_WIN32)
+ Tcl_CreateObjCommand(interp, "testmetrics", TestmetricsObjCmd,
+ (ClientData) Tk_MainWindow(interp), NULL);
+#elif !defined(__CYGWIN__) && !defined(MAC_OSX_TK)
+ Tcl_CreateObjCommand(interp, "testmenubar", TestmenubarObjCmd,
+ (ClientData) Tk_MainWindow(interp), NULL);
+ Tcl_CreateObjCommand(interp, "testsend", TkpTestsendCmd,
+ (ClientData) Tk_MainWindow(interp), NULL);
+ Tcl_CreateObjCommand(interp, "testwrapper", TestwrapperObjCmd,
+ (ClientData) Tk_MainWindow(interp), NULL);
+#endif /* _WIN32 */
+
+ /*
+ * Create test image type.
+ */
+
+ if (!initialized) {
+ initialized = 1;
+ Tk_CreateImageType(&imageType);
+ }
+
+ /*
+ * Enable testing of legacy interfaces.
+ */
+
+ if (TkOldTestInit(interp) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * And finally add any platform specific test commands.
+ */
+
+ return TkplatformtestInit(interp);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TestbitmapObjCmd --
+ *
+ * This function implements the "testbitmap" command, which is used to
+ * test color resource handling in tkBitmap tmp.c.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+TestbitmapObjCmd(
+ ClientData clientData, /* Main window for application. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "bitmap");
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, TkDebugBitmap(Tk_MainWindow(interp),
+ Tcl_GetString(objv[1])));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TestborderObjCmd --
+ *
+ * This function implements the "testborder" command, which is used to
+ * test color resource handling in tkBorder.c.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+TestborderObjCmd(
+ ClientData clientData, /* Main window for application. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "border");
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, TkDebugBorder(Tk_MainWindow(interp),
+ Tcl_GetString(objv[1])));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TestcolorObjCmd --
+ *
+ * This function implements the "testcolor" command, which is used to
+ * test color resource handling in tkColor.c.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+TestcolorObjCmd(
+ ClientData clientData, /* Main window for application. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "color");
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, TkDebugColor(Tk_MainWindow(interp),
+ Tcl_GetString(objv[1])));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TestcursorObjCmd --
+ *
+ * This function implements the "testcursor" command, which is used to
+ * test color resource handling in tkCursor.c.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+TestcursorObjCmd(
+ ClientData clientData, /* Main window for application. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "cursor");
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, TkDebugCursor(Tk_MainWindow(interp),
+ Tcl_GetString(objv[1])));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TestdeleteappsObjCmd --
+ *
+ * This function implements the "testdeleteapps" command. It cleans up
+ * all the interpreters left behind by the "testnewapp" command.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * All the intepreters created by previous calls to "testnewapp" get
+ * deleted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+TestdeleteappsObjCmd(
+ ClientData clientData, /* Main window for application. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument strings. */
+{
+ NewApp *nextPtr;
+
+ while (newAppPtr != NULL) {
+ nextPtr = newAppPtr->nextPtr;
+ Tcl_DeleteInterp(newAppPtr->interp);
+ ckfree(newAppPtr);
+ newAppPtr = nextPtr;
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TestobjconfigObjCmd --
+ *
+ * This function implements the "testobjconfig" command, which is used to
+ * test the functions in tkConfig.c.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+TestobjconfigObjCmd(
+ ClientData clientData, /* Main window for application. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ static const char *const options[] = {
+ "alltypes", "chain1", "chain2", "chain3", "configerror", "delete", "info",
+ "internal", "new", "notenoughparams", "twowindows", NULL
+ };
+ enum {
+ ALL_TYPES, CHAIN1, CHAIN2, CHAIN3, CONFIG_ERROR,
+ DEL, /* Can't use DELETE: VC++ compiler barfs. */
+ INFO, INTERNAL, NEW, NOT_ENOUGH_PARAMS, TWO_WINDOWS
+ };
+ static Tk_OptionTable tables[11];
+ /* Holds pointers to option tables created by
+ * commands below; indexed with same values as
+ * "options" array. */
+ static const Tk_ObjCustomOption CustomOption = {
+ "custom option",
+ CustomOptionSet,
+ CustomOptionGet,
+ CustomOptionRestore,
+ CustomOptionFree,
+ INT2PTR(1)
+ };
+ Tk_Window mainWin = (Tk_Window) clientData;
+ Tk_Window tkwin;
+ int index, result = TCL_OK;
+
+ /*
+ * Structures used by the "chain1" subcommand and also shared by the
+ * "chain2" subcommand:
+ */
+
+ typedef struct ExtensionWidgetRecord {
+ TrivialCommandHeader header;
+ Tcl_Obj *base1ObjPtr;
+ Tcl_Obj *base2ObjPtr;
+ Tcl_Obj *extension3ObjPtr;
+ Tcl_Obj *extension4ObjPtr;
+ Tcl_Obj *extension5ObjPtr;
+ } ExtensionWidgetRecord;
+ static const Tk_OptionSpec baseSpecs[] = {
+ {TK_OPTION_STRING, "-one", "one", "One", "one",
+ Tk_Offset(ExtensionWidgetRecord, base1ObjPtr), -1, 0, NULL, 0},
+ {TK_OPTION_STRING, "-two", "two", "Two", "two",
+ Tk_Offset(ExtensionWidgetRecord, base2ObjPtr), -1, 0, NULL, 0},
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}
+ };
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "command");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[1], options,
+ sizeof(char *), "command", 0, &index)!= TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch (index) {
+ case ALL_TYPES: {
+ typedef struct TypesRecord {
+ TrivialCommandHeader header;
+ Tcl_Obj *booleanPtr;
+ Tcl_Obj *integerPtr;
+ Tcl_Obj *doublePtr;
+ Tcl_Obj *stringPtr;
+ Tcl_Obj *stringTablePtr;
+ Tcl_Obj *colorPtr;
+ Tcl_Obj *fontPtr;
+ Tcl_Obj *bitmapPtr;
+ Tcl_Obj *borderPtr;
+ Tcl_Obj *reliefPtr;
+ Tcl_Obj *cursorPtr;
+ Tcl_Obj *activeCursorPtr;
+ Tcl_Obj *justifyPtr;
+ Tcl_Obj *anchorPtr;
+ Tcl_Obj *pixelPtr;
+ Tcl_Obj *mmPtr;
+ Tcl_Obj *customPtr;
+ } TypesRecord;
+ TypesRecord *recordPtr;
+ static const char *const stringTable[] = {
+ "one", "two", "three", "four", NULL
+ };
+ static const Tk_OptionSpec typesSpecs[] = {
+ {TK_OPTION_BOOLEAN, "-boolean", "boolean", "Boolean", "1",
+ Tk_Offset(TypesRecord, booleanPtr), -1, 0, 0, 0x1},
+ {TK_OPTION_INT, "-integer", "integer", "Integer", "7",
+ Tk_Offset(TypesRecord, integerPtr), -1, 0, 0, 0x2},
+ {TK_OPTION_DOUBLE, "-double", "double", "Double", "3.14159",
+ Tk_Offset(TypesRecord, doublePtr), -1, 0, 0, 0x4},
+ {TK_OPTION_STRING, "-string", "string", "String",
+ "foo", Tk_Offset(TypesRecord, stringPtr), -1,
+ TK_CONFIG_NULL_OK, 0, 0x8},
+ {TK_OPTION_STRING_TABLE,
+ "-stringtable", "StringTable", "stringTable",
+ "one", Tk_Offset(TypesRecord, stringTablePtr), -1,
+ TK_CONFIG_NULL_OK, stringTable, 0x10},
+ {TK_OPTION_COLOR, "-color", "color", "Color",
+ "red", Tk_Offset(TypesRecord, colorPtr), -1,
+ TK_CONFIG_NULL_OK, "black", 0x20},
+ {TK_OPTION_FONT, "-font", "font", "Font", "Helvetica 12",
+ Tk_Offset(TypesRecord, fontPtr), -1,
+ TK_CONFIG_NULL_OK, 0, 0x40},
+ {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap", "gray50",
+ Tk_Offset(TypesRecord, bitmapPtr), -1,
+ TK_CONFIG_NULL_OK, 0, 0x80},
+ {TK_OPTION_BORDER, "-border", "border", "Border",
+ "blue", Tk_Offset(TypesRecord, borderPtr), -1,
+ TK_CONFIG_NULL_OK, "white", 0x100},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief", "raised",
+ Tk_Offset(TypesRecord, reliefPtr), -1,
+ TK_CONFIG_NULL_OK, 0, 0x200},
+ {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", "xterm",
+ Tk_Offset(TypesRecord, cursorPtr), -1,
+ TK_CONFIG_NULL_OK, 0, 0x400},
+ {TK_OPTION_JUSTIFY, "-justify", NULL, NULL, "left",
+ Tk_Offset(TypesRecord, justifyPtr), -1,
+ TK_CONFIG_NULL_OK, 0, 0x800},
+ {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", NULL,
+ Tk_Offset(TypesRecord, anchorPtr), -1,
+ TK_CONFIG_NULL_OK, 0, 0x1000},
+ {TK_OPTION_PIXELS, "-pixel", "pixel", "Pixel",
+ "1", Tk_Offset(TypesRecord, pixelPtr), -1,
+ TK_CONFIG_NULL_OK, 0, 0x2000},
+ {TK_OPTION_CUSTOM, "-custom", NULL, NULL,
+ "", Tk_Offset(TypesRecord, customPtr), -1,
+ TK_CONFIG_NULL_OK, &CustomOption, 0x4000},
+ {TK_OPTION_SYNONYM, "-synonym", NULL, NULL,
+ NULL, 0, -1, 0, "-color", 0x8000},
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}
+ };
+ Tk_OptionTable optionTable;
+ Tk_Window tkwin;
+
+ optionTable = Tk_CreateOptionTable(interp, typesSpecs);
+ tables[index] = optionTable;
+ tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window) clientData,
+ Tcl_GetString(objv[2]), NULL);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ Tk_SetClass(tkwin, "Test");
+
+ recordPtr = ckalloc(sizeof(TypesRecord));
+ recordPtr->header.interp = interp;
+ recordPtr->header.optionTable = optionTable;
+ recordPtr->header.tkwin = tkwin;
+ recordPtr->booleanPtr = NULL;
+ recordPtr->integerPtr = NULL;
+ recordPtr->doublePtr = NULL;
+ recordPtr->stringPtr = NULL;
+ recordPtr->colorPtr = NULL;
+ recordPtr->fontPtr = NULL;
+ recordPtr->bitmapPtr = NULL;
+ recordPtr->borderPtr = NULL;
+ recordPtr->reliefPtr = NULL;
+ recordPtr->cursorPtr = NULL;
+ recordPtr->justifyPtr = NULL;
+ recordPtr->anchorPtr = NULL;
+ recordPtr->pixelPtr = NULL;
+ recordPtr->mmPtr = NULL;
+ recordPtr->stringTablePtr = NULL;
+ recordPtr->customPtr = NULL;
+ result = Tk_InitOptions(interp, (char *) recordPtr, optionTable,
+ tkwin);
+ if (result == TCL_OK) {
+ recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp,
+ Tcl_GetString(objv[2]), TrivialConfigObjCmd,
+ (ClientData) recordPtr, TrivialCmdDeletedProc);
+ Tk_CreateEventHandler(tkwin, StructureNotifyMask,
+ TrivialEventProc, (ClientData) recordPtr);
+ result = Tk_SetOptions(interp, (char *) recordPtr, optionTable,
+ objc-3, objv+3, tkwin, NULL, NULL);
+ if (result != TCL_OK) {
+ Tk_DestroyWindow(tkwin);
+ }
+ } else {
+ Tk_DestroyWindow(tkwin);
+ ckfree(recordPtr);
+ }
+ if (result == TCL_OK) {
+ Tcl_SetObjResult(interp, objv[2]);
+ }
+ break;
+ }
+
+ case CHAIN1: {
+ ExtensionWidgetRecord *recordPtr;
+ Tk_Window tkwin;
+ Tk_OptionTable optionTable;
+
+ tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window) clientData,
+ Tcl_GetString(objv[2]), NULL);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ Tk_SetClass(tkwin, "Test");
+ optionTable = Tk_CreateOptionTable(interp, baseSpecs);
+ tables[index] = optionTable;
+
+ recordPtr = ckalloc(sizeof(ExtensionWidgetRecord));
+ recordPtr->header.interp = interp;
+ recordPtr->header.optionTable = optionTable;
+ recordPtr->header.tkwin = tkwin;
+ recordPtr->base1ObjPtr = recordPtr->base2ObjPtr = NULL;
+ recordPtr->extension3ObjPtr = recordPtr->extension4ObjPtr = NULL;
+ result = Tk_InitOptions(interp, (char *)recordPtr, optionTable, tkwin);
+ if (result == TCL_OK) {
+ result = Tk_SetOptions(interp, (char *) recordPtr, optionTable,
+ objc-3, objv+3, tkwin, NULL, NULL);
+ if (result != TCL_OK) {
+ Tk_FreeConfigOptions((char *) recordPtr, optionTable, tkwin);
+ }
+ }
+ if (result == TCL_OK) {
+ recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp,
+ Tcl_GetString(objv[2]), TrivialConfigObjCmd,
+ (ClientData) recordPtr, TrivialCmdDeletedProc);
+ Tk_CreateEventHandler(tkwin, StructureNotifyMask,
+ TrivialEventProc, (ClientData) recordPtr);
+ Tcl_SetObjResult(interp, objv[2]);
+ }
+ break;
+ }
+
+ case CHAIN2:
+ case CHAIN3: {
+ ExtensionWidgetRecord *recordPtr;
+ static const Tk_OptionSpec extensionSpecs[] = {
+ {TK_OPTION_STRING, "-three", "three", "Three", "three",
+ Tk_Offset(ExtensionWidgetRecord, extension3ObjPtr), -1, 0, NULL, 0},
+ {TK_OPTION_STRING, "-four", "four", "Four", "four",
+ Tk_Offset(ExtensionWidgetRecord, extension4ObjPtr), -1, 0, NULL, 0},
+ {TK_OPTION_STRING, "-two", "two", "Two", "two and a half",
+ Tk_Offset(ExtensionWidgetRecord, base2ObjPtr), -1, 0, NULL, 0},
+ {TK_OPTION_STRING,
+ "-oneAgain", "oneAgain", "OneAgain", "one again",
+ Tk_Offset(ExtensionWidgetRecord, extension5ObjPtr), -1, 0, NULL, 0},
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0,
+ (ClientData) baseSpecs, 0}
+ };
+ Tk_Window tkwin;
+ Tk_OptionTable optionTable;
+
+ tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window) clientData,
+ Tcl_GetString(objv[2]), NULL);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ Tk_SetClass(tkwin, "Test");
+ optionTable = Tk_CreateOptionTable(interp, extensionSpecs);
+ tables[index] = optionTable;
+
+ recordPtr = ckalloc(sizeof(ExtensionWidgetRecord));
+ recordPtr->header.interp = interp;
+ recordPtr->header.optionTable = optionTable;
+ recordPtr->header.tkwin = tkwin;
+ recordPtr->base1ObjPtr = recordPtr->base2ObjPtr = NULL;
+ recordPtr->extension3ObjPtr = recordPtr->extension4ObjPtr = NULL;
+ recordPtr->extension5ObjPtr = NULL;
+ result = Tk_InitOptions(interp, (char *)recordPtr, optionTable, tkwin);
+ if (result == TCL_OK) {
+ result = Tk_SetOptions(interp, (char *) recordPtr, optionTable,
+ objc-3, objv+3, tkwin, NULL, NULL);
+ if (result != TCL_OK) {
+ Tk_FreeConfigOptions((char *) recordPtr, optionTable, tkwin);
+ }
+ }
+ if (result == TCL_OK) {
+ recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp,
+ Tcl_GetString(objv[2]), TrivialConfigObjCmd,
+ (ClientData) recordPtr, TrivialCmdDeletedProc);
+ Tk_CreateEventHandler(tkwin, StructureNotifyMask,
+ TrivialEventProc, (ClientData) recordPtr);
+ Tcl_SetObjResult(interp, objv[2]);
+ }
+ break;
+ }
+
+ case CONFIG_ERROR: {
+ typedef struct ErrorWidgetRecord {
+ Tcl_Obj *intPtr;
+ } ErrorWidgetRecord;
+ ErrorWidgetRecord widgetRecord;
+ static const Tk_OptionSpec errorSpecs[] = {
+ {TK_OPTION_INT, "-int", "integer", "Integer", "bogus",
+ Tk_Offset(ErrorWidgetRecord, intPtr), 0, 0, NULL, 0},
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}
+ };
+ Tk_OptionTable optionTable;
+
+ widgetRecord.intPtr = NULL;
+ optionTable = Tk_CreateOptionTable(interp, errorSpecs);
+ tables[index] = optionTable;
+ return Tk_InitOptions(interp, (char *) &widgetRecord, optionTable,
+ (Tk_Window) NULL);
+ }
+
+ case DEL:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "tableName");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObjStruct(interp, objv[2], options,
+ sizeof(char *), "table", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (tables[index] != NULL) {
+ Tk_DeleteOptionTable(tables[index]);
+ /* Make sure that Tk_DeleteOptionTable() is never done
+ * twice for the same table. */
+ tables[index] = NULL;
+ }
+ break;
+
+ case INFO:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "tableName");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObjStruct(interp, objv[2], options,
+ sizeof(char *), "table", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, TkDebugConfig(interp, tables[index]));
+ break;
+
+ case INTERNAL: {
+ /*
+ * This command is similar to the "alltypes" command except that it
+ * stores all the configuration options as internal forms instead of
+ * objects.
+ */
+
+ typedef struct InternalRecord {
+ TrivialCommandHeader header;
+ int boolean;
+ int integer;
+ double doubleValue;
+ char *string;
+ int index;
+ XColor *colorPtr;
+ Tk_Font tkfont;
+ Pixmap bitmap;
+ Tk_3DBorder border;
+ int relief;
+ Tk_Cursor cursor;
+ Tk_Justify justify;
+ Tk_Anchor anchor;
+ int pixels;
+ double mm;
+ Tk_Window tkwin;
+ char *custom;
+ } InternalRecord;
+ InternalRecord *recordPtr;
+ static const char *const internalStringTable[] = {
+ "one", "two", "three", "four", NULL
+ };
+ static const Tk_OptionSpec internalSpecs[] = {
+ {TK_OPTION_BOOLEAN, "-boolean", "boolean", "Boolean", "1",
+ -1, Tk_Offset(InternalRecord, boolean), 0, 0, 0x1},
+ {TK_OPTION_INT, "-integer", "integer", "Integer", "148962237",
+ -1, Tk_Offset(InternalRecord, integer), 0, 0, 0x2},
+ {TK_OPTION_DOUBLE, "-double", "double", "Double", "3.14159",
+ -1, Tk_Offset(InternalRecord, doubleValue), 0, 0, 0x4},
+ {TK_OPTION_STRING, "-string", "string", "String", "foo",
+ -1, Tk_Offset(InternalRecord, string),
+ TK_CONFIG_NULL_OK, 0, 0x8},
+ {TK_OPTION_STRING_TABLE,
+ "-stringtable", "StringTable", "stringTable", "one",
+ -1, Tk_Offset(InternalRecord, index),
+ TK_CONFIG_NULL_OK, internalStringTable, 0x10},
+ {TK_OPTION_COLOR, "-color", "color", "Color", "red",
+ -1, Tk_Offset(InternalRecord, colorPtr),
+ TK_CONFIG_NULL_OK, "black", 0x20},
+ {TK_OPTION_FONT, "-font", "font", "Font", "Helvetica 12",
+ -1, Tk_Offset(InternalRecord, tkfont),
+ TK_CONFIG_NULL_OK, 0, 0x40},
+ {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap", "gray50",
+ -1, Tk_Offset(InternalRecord, bitmap),
+ TK_CONFIG_NULL_OK, 0, 0x80},
+ {TK_OPTION_BORDER, "-border", "border", "Border", "blue",
+ -1, Tk_Offset(InternalRecord, border),
+ TK_CONFIG_NULL_OK, "white", 0x100},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief", "raised",
+ -1, Tk_Offset(InternalRecord, relief),
+ TK_CONFIG_NULL_OK, 0, 0x200},
+ {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", "xterm",
+ -1, Tk_Offset(InternalRecord, cursor),
+ TK_CONFIG_NULL_OK, 0, 0x400},
+ {TK_OPTION_JUSTIFY, "-justify", NULL, NULL, "left",
+ -1, Tk_Offset(InternalRecord, justify),
+ TK_CONFIG_NULL_OK, 0, 0x800},
+ {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", NULL,
+ -1, Tk_Offset(InternalRecord, anchor),
+ TK_CONFIG_NULL_OK, 0, 0x1000},
+ {TK_OPTION_PIXELS, "-pixel", "pixel", "Pixel", "1",
+ -1, Tk_Offset(InternalRecord, pixels),
+ TK_CONFIG_NULL_OK, 0, 0x2000},
+ {TK_OPTION_WINDOW, "-window", "window", "Window", NULL,
+ -1, Tk_Offset(InternalRecord, tkwin),
+ TK_CONFIG_NULL_OK, 0, 0},
+ {TK_OPTION_CUSTOM, "-custom", NULL, NULL, "",
+ -1, Tk_Offset(InternalRecord, custom),
+ TK_CONFIG_NULL_OK, &CustomOption, 0x4000},
+ {TK_OPTION_SYNONYM, "-synonym", NULL, NULL,
+ NULL, -1, -1, 0, "-color", 0x8000},
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}
+ };
+ Tk_OptionTable optionTable;
+ Tk_Window tkwin;
+
+ optionTable = Tk_CreateOptionTable(interp, internalSpecs);
+ tables[index] = optionTable;
+ tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window) clientData,
+ Tcl_GetString(objv[2]), NULL);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ Tk_SetClass(tkwin, "Test");
+
+ recordPtr = ckalloc(sizeof(InternalRecord));
+ recordPtr->header.interp = interp;
+ recordPtr->header.optionTable = optionTable;
+ recordPtr->header.tkwin = tkwin;
+ recordPtr->boolean = 0;
+ recordPtr->integer = 0;
+ recordPtr->doubleValue = 0.0;
+ recordPtr->string = NULL;
+ recordPtr->index = 0;
+ recordPtr->colorPtr = NULL;
+ recordPtr->tkfont = NULL;
+ recordPtr->bitmap = None;
+ recordPtr->border = NULL;
+ recordPtr->relief = TK_RELIEF_FLAT;
+ recordPtr->cursor = NULL;
+ recordPtr->justify = TK_JUSTIFY_LEFT;
+ recordPtr->anchor = TK_ANCHOR_N;
+ recordPtr->pixels = 0;
+ recordPtr->mm = 0.0;
+ recordPtr->tkwin = NULL;
+ recordPtr->custom = NULL;
+ result = Tk_InitOptions(interp, (char *) recordPtr, optionTable,
+ tkwin);
+ if (result == TCL_OK) {
+ recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp,
+ Tcl_GetString(objv[2]), TrivialConfigObjCmd,
+ recordPtr, TrivialCmdDeletedProc);
+ Tk_CreateEventHandler(tkwin, StructureNotifyMask,
+ TrivialEventProc, recordPtr);
+ result = Tk_SetOptions(interp, (char *) recordPtr, optionTable,
+ objc - 3, objv + 3, tkwin, NULL, NULL);
+ if (result != TCL_OK) {
+ Tk_DestroyWindow(tkwin);
+ }
+ } else {
+ Tk_DestroyWindow(tkwin);
+ ckfree(recordPtr);
+ }
+ if (result == TCL_OK) {
+ Tcl_SetObjResult(interp, objv[2]);
+ }
+ break;
+ }
+
+ case NEW: {
+ typedef struct FiveRecord {
+ TrivialCommandHeader header;
+ Tcl_Obj *one;
+ Tcl_Obj *two;
+ Tcl_Obj *three;
+ Tcl_Obj *four;
+ Tcl_Obj *five;
+ } FiveRecord;
+ FiveRecord *recordPtr;
+ static const Tk_OptionSpec smallSpecs[] = {
+ {TK_OPTION_INT, "-one", "one", "One", "1",
+ Tk_Offset(FiveRecord, one), -1, 0, NULL, 0},
+ {TK_OPTION_INT, "-two", "two", "Two", "2",
+ Tk_Offset(FiveRecord, two), -1, 0, NULL, 0},
+ {TK_OPTION_INT, "-three", "three", "Three", "3",
+ Tk_Offset(FiveRecord, three), -1, 0, NULL, 0},
+ {TK_OPTION_INT, "-four", "four", "Four", "4",
+ Tk_Offset(FiveRecord, four), -1, 0, NULL, 0},
+ {TK_OPTION_STRING, "-five", NULL, NULL, NULL,
+ Tk_Offset(FiveRecord, five), -1, 0, NULL, 0},
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}
+ };
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "new name ?-option value ...?");
+ return TCL_ERROR;
+ }
+
+ recordPtr = ckalloc(sizeof(FiveRecord));
+ recordPtr->header.interp = interp;
+ recordPtr->header.optionTable = Tk_CreateOptionTable(interp,
+ smallSpecs);
+ tables[index] = recordPtr->header.optionTable;
+ recordPtr->header.tkwin = NULL;
+ recordPtr->one = recordPtr->two = recordPtr->three = NULL;
+ recordPtr->four = recordPtr->five = NULL;
+ Tcl_SetObjResult(interp, objv[2]);
+ result = Tk_InitOptions(interp, (char *) recordPtr,
+ recordPtr->header.optionTable, (Tk_Window) NULL);
+ if (result == TCL_OK) {
+ result = Tk_SetOptions(interp, (char *) recordPtr,
+ recordPtr->header.optionTable, objc - 3, objv + 3,
+ (Tk_Window) NULL, NULL, NULL);
+ if (result == TCL_OK) {
+ recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp,
+ Tcl_GetString(objv[2]), TrivialConfigObjCmd,
+ (ClientData) recordPtr, TrivialCmdDeletedProc);
+ } else {
+ Tk_FreeConfigOptions((char *) recordPtr,
+ recordPtr->header.optionTable, (Tk_Window) NULL);
+ }
+ }
+ if (result != TCL_OK) {
+ ckfree(recordPtr);
+ }
+
+ break;
+ }
+ case NOT_ENOUGH_PARAMS: {
+ typedef struct NotEnoughRecord {
+ Tcl_Obj *fooObjPtr;
+ } NotEnoughRecord;
+ NotEnoughRecord record;
+ static const Tk_OptionSpec errorSpecs[] = {
+ {TK_OPTION_INT, "-foo", "foo", "Foo", "0",
+ Tk_Offset(NotEnoughRecord, fooObjPtr), 0, 0, NULL, 0},
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}
+ };
+ Tcl_Obj *newObjPtr = Tcl_NewStringObj("-foo", -1);
+ Tk_OptionTable optionTable;
+
+ record.fooObjPtr = NULL;
+
+ tkwin = Tk_CreateWindowFromPath(interp, mainWin, ".config", NULL);
+ Tk_SetClass(tkwin, "Config");
+ optionTable = Tk_CreateOptionTable(interp, errorSpecs);
+ tables[index] = optionTable;
+ Tk_InitOptions(interp, (char *) &record, optionTable, tkwin);
+ if (Tk_SetOptions(interp, (char *) &record, optionTable, 1,
+ &newObjPtr, tkwin, NULL, NULL) != TCL_OK) {
+ result = TCL_ERROR;
+ }
+ Tcl_DecrRefCount(newObjPtr);
+ Tk_FreeConfigOptions( (char *) &record, optionTable, tkwin);
+ Tk_DestroyWindow(tkwin);
+ return result;
+ }
+
+ case TWO_WINDOWS: {
+ typedef struct SlaveRecord {
+ TrivialCommandHeader header;
+ Tcl_Obj *windowPtr;
+ } SlaveRecord;
+ SlaveRecord *recordPtr;
+ static const Tk_OptionSpec slaveSpecs[] = {
+ {TK_OPTION_WINDOW, "-window", "window", "Window", ".bar",
+ Tk_Offset(SlaveRecord, windowPtr), -1, TK_CONFIG_NULL_OK, NULL, 0},
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}
+ };
+ Tk_Window tkwin = Tk_CreateWindowFromPath(interp,
+ (Tk_Window) clientData, Tcl_GetString(objv[2]), NULL);
+
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ Tk_SetClass(tkwin, "Test");
+
+ recordPtr = ckalloc(sizeof(SlaveRecord));
+ recordPtr->header.interp = interp;
+ recordPtr->header.optionTable = Tk_CreateOptionTable(interp,
+ slaveSpecs);
+ tables[index] = recordPtr->header.optionTable;
+ recordPtr->header.tkwin = tkwin;
+ recordPtr->windowPtr = NULL;
+
+ result = Tk_InitOptions(interp, (char *) recordPtr,
+ recordPtr->header.optionTable, tkwin);
+ if (result == TCL_OK) {
+ result = Tk_SetOptions(interp, (char *) recordPtr,
+ recordPtr->header.optionTable, objc - 3, objv + 3,
+ tkwin, NULL, NULL);
+ if (result == TCL_OK) {
+ recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp,
+ Tcl_GetString(objv[2]), TrivialConfigObjCmd,
+ recordPtr, TrivialCmdDeletedProc);
+ Tk_CreateEventHandler(tkwin, StructureNotifyMask,
+ TrivialEventProc, recordPtr);
+ Tcl_SetObjResult(interp, objv[2]);
+ } else {
+ Tk_FreeConfigOptions((char *) recordPtr,
+ recordPtr->header.optionTable, tkwin);
+ }
+ }
+ if (result != TCL_OK) {
+ Tk_DestroyWindow(tkwin);
+ ckfree(recordPtr);
+ }
+ }
+ }
+
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TrivialConfigObjCmd --
+ *
+ * This command is used to test the configuration package. It only
+ * handles the "configure" and "cget" subcommands.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+TrivialConfigObjCmd(
+ ClientData clientData, /* Main window for application. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ int result = TCL_OK;
+ static const char *const options[] = {
+ "cget", "configure", "csave", NULL
+ };
+ enum {
+ CGET, CONFIGURE, CSAVE
+ };
+ Tcl_Obj *resultObjPtr;
+ int index, mask;
+ TrivialCommandHeader *headerPtr = (TrivialCommandHeader *) clientData;
+ Tk_Window tkwin = headerPtr->tkwin;
+ Tk_SavedOptions saved;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg...?");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[1], options,
+ sizeof(char *), "command", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ Tcl_Preserve(clientData);
+
+ switch (index) {
+ case CGET:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option");
+ result = TCL_ERROR;
+ goto done;
+ }
+ resultObjPtr = Tk_GetOptionValue(interp, (char *) clientData,
+ headerPtr->optionTable, objv[2], tkwin);
+ if (resultObjPtr != NULL) {
+ Tcl_SetObjResult(interp, resultObjPtr);
+ result = TCL_OK;
+ } else {
+ result = TCL_ERROR;
+ }
+ break;
+ case CONFIGURE:
+ if (objc == 2) {
+ resultObjPtr = Tk_GetOptionInfo(interp, (char *) clientData,
+ headerPtr->optionTable, NULL, tkwin);
+ if (resultObjPtr == NULL) {
+ result = TCL_ERROR;
+ } else {
+ Tcl_SetObjResult(interp, resultObjPtr);
+ }
+ } else if (objc == 3) {
+ resultObjPtr = Tk_GetOptionInfo(interp, (char *) clientData,
+ headerPtr->optionTable, objv[2], tkwin);
+ if (resultObjPtr == NULL) {
+ result = TCL_ERROR;
+ } else {
+ Tcl_SetObjResult(interp, resultObjPtr);
+ }
+ } else {
+ result = Tk_SetOptions(interp, (char *) clientData,
+ headerPtr->optionTable, objc - 2, objv + 2,
+ tkwin, NULL, &mask);
+ if (result == TCL_OK) {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(mask));
+ }
+ }
+ break;
+ case CSAVE:
+ result = Tk_SetOptions(interp, (char *) clientData,
+ headerPtr->optionTable, objc - 2, objv + 2,
+ tkwin, &saved, &mask);
+ Tk_FreeSavedOptions(&saved);
+ if (result == TCL_OK) {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(mask));
+ }
+ break;
+ }
+ done:
+ Tcl_Release(clientData);
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TrivialCmdDeletedProc --
+ *
+ * This function is invoked when a widget command is deleted. If the
+ * widget isn't already in the process of being destroyed, this command
+ * destroys it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The widget is destroyed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+TrivialCmdDeletedProc(
+ ClientData clientData) /* Pointer to widget record for widget. */
+{
+ TrivialCommandHeader *headerPtr = (TrivialCommandHeader *) clientData;
+ Tk_Window tkwin = headerPtr->tkwin;
+
+ if (tkwin != NULL) {
+ Tk_DestroyWindow(tkwin);
+ } else if (headerPtr->optionTable != NULL) {
+ /*
+ * This is a "new" object, which doesn't have a window, so we can't
+ * depend on cleaning up in the event function. Free its resources
+ * here.
+ */
+
+ Tk_FreeConfigOptions((char *) clientData,
+ headerPtr->optionTable, (Tk_Window) NULL);
+ Tcl_EventuallyFree(clientData, TCL_DYNAMIC);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TrivialEventProc --
+ *
+ * A dummy event proc.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * When the window gets deleted, internal structures get cleaned up.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+TrivialEventProc(
+ ClientData clientData, /* Information about window. */
+ XEvent *eventPtr) /* Information about event. */
+{
+ TrivialCommandHeader *headerPtr = (TrivialCommandHeader *) clientData;
+
+ if (eventPtr->type == DestroyNotify) {
+ if (headerPtr->tkwin != NULL) {
+ Tk_FreeConfigOptions((char *) clientData,
+ headerPtr->optionTable, headerPtr->tkwin);
+ headerPtr->optionTable = NULL;
+ headerPtr->tkwin = NULL;
+ Tcl_DeleteCommandFromToken(headerPtr->interp,
+ headerPtr->widgetCmd);
+ }
+ Tcl_EventuallyFree(clientData, TCL_DYNAMIC);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TestfontObjCmd --
+ *
+ * This function implements the "testfont" command, which is used to test
+ * TkFont objects.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+TestfontObjCmd(
+ ClientData clientData, /* Main window for application. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ static const char *const options[] = {"counts", "subfonts", NULL};
+ enum option {COUNTS, SUBFONTS};
+ int index;
+ Tk_Window tkwin;
+ Tk_Font tkfont;
+
+ tkwin = (Tk_Window) clientData;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option fontName");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[1], options,
+ sizeof(char *), "command", 0, &index)!= TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch ((enum option) index) {
+ case COUNTS:
+ Tcl_SetObjResult(interp,
+ TkDebugFont(Tk_MainWindow(interp), Tcl_GetString(objv[2])));
+ break;
+ case SUBFONTS:
+ tkfont = Tk_AllocFontFromObj(interp, tkwin, objv[2]);
+ if (tkfont == NULL) {
+ return TCL_ERROR;
+ }
+ TkpGetSubFonts(interp, tkfont);
+ Tk_FreeFont(tkfont);
+ break;
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImageCreate --
+ *
+ * This function is called by the Tk image code to create "test" images.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * The data structure for a new image is allocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+ImageCreate(
+ Tcl_Interp *interp, /* Interpreter for application containing
+ * image. */
+ const char *name, /* Name to use for image. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[], /* Argument strings for options (doesn't
+ * include image name or type). */
+ const Tk_ImageType *typePtr, /* Pointer to our type record (not used). */
+ Tk_ImageMaster master, /* Token for image, to be used by us in later
+ * callbacks. */
+ ClientData *clientDataPtr) /* Store manager's token for image here; it
+ * will be returned in later callbacks. */
+{
+ TImageMaster *timPtr;
+ const char *varName;
+ int i;
+
+ varName = "log";
+ for (i = 0; i < objc; i += 2) {
+ if (strcmp(Tcl_GetString(objv[i]), "-variable") != 0) {
+ Tcl_AppendResult(interp, "bad option name \"",
+ Tcl_GetString(objv[i]), "\"", NULL);
+ return TCL_ERROR;
+ }
+ if ((i+1) == objc) {
+ Tcl_AppendResult(interp, "no value given for \"",
+ Tcl_GetString(objv[i]), "\" option", NULL);
+ return TCL_ERROR;
+ }
+ varName = Tcl_GetString(objv[i+1]);
+ }
+
+ timPtr = ckalloc(sizeof(TImageMaster));
+ timPtr->master = master;
+ timPtr->interp = interp;
+ timPtr->width = 30;
+ timPtr->height = 15;
+ timPtr->imageName = ckalloc(strlen(name) + 1);
+ strcpy(timPtr->imageName, name);
+ timPtr->varName = ckalloc(strlen(varName) + 1);
+ strcpy(timPtr->varName, varName);
+ Tcl_CreateObjCommand(interp, name, ImageObjCmd, timPtr, NULL);
+ *clientDataPtr = timPtr;
+ Tk_ImageChanged(master, 0, 0, 30, 15, 30, 15);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImageObjCmd --
+ *
+ * This function implements the commands corresponding to individual
+ * images.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * Forces windows to be created.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+ImageObjCmd(
+ ClientData clientData, /* Main window for application. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument strings. */
+{
+ TImageMaster *timPtr = (TImageMaster *) clientData;
+ int x, y, width, height;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ if (strcmp(Tcl_GetString(objv[1]), "changed") == 0) {
+ if (objc != 8) {
+ Tcl_WrongNumArgs(interp, 1, objv, "changed x y width height"
+ " imageWidth imageHeight");
+ return TCL_ERROR;
+ }
+ if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[4], &width) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[5], &height) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[6], &timPtr->width) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[7], &timPtr->height) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ Tk_ImageChanged(timPtr->master, x, y, width, height, timPtr->width,
+ timPtr->height);
+ } else {
+ Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[1]),
+ "\": must be changed", NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImageGet --
+ *
+ * This function is called by Tk to set things up for using a test image
+ * in a particular widget.
+ *
+ * Results:
+ * The return value is a token for the image instance, which is used in
+ * future callbacks to ImageDisplay and ImageFree.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static ClientData
+ImageGet(
+ Tk_Window tkwin, /* Token for window in which image will be
+ * used. */
+ ClientData clientData) /* Pointer to TImageMaster for image. */
+{
+ TImageMaster *timPtr = (TImageMaster *) clientData;
+ TImageInstance *instPtr;
+ char buffer[100];
+ XGCValues gcValues;
+
+ sprintf(buffer, "%s get", timPtr->imageName);
+ Tcl_SetVar2(timPtr->interp, timPtr->varName, NULL, buffer,
+ TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
+
+ instPtr = ckalloc(sizeof(TImageInstance));
+ instPtr->masterPtr = timPtr;
+ instPtr->fg = Tk_GetColor(timPtr->interp, tkwin, "#ff0000");
+ gcValues.foreground = instPtr->fg->pixel;
+ instPtr->gc = Tk_GetGC(tkwin, GCForeground, &gcValues);
+ return instPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImageDisplay --
+ *
+ * This function is invoked to redisplay part or all of an image in a
+ * given drawable.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The image gets partially redrawn, as an "X" that shows the exact
+ * redraw area.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ImageDisplay(
+ ClientData clientData, /* Pointer to TImageInstance for image. */
+ Display *display, /* Display to use for drawing. */
+ Drawable drawable, /* Where to redraw image. */
+ int imageX, int imageY, /* Origin of area to redraw, relative to
+ * origin of image. */
+ int width, int height, /* Dimensions of area to redraw. */
+ int drawableX, int drawableY)
+ /* Coordinates in drawable corresponding to
+ * imageX and imageY. */
+{
+ TImageInstance *instPtr = (TImageInstance *) clientData;
+ char buffer[200 + TCL_INTEGER_SPACE * 6];
+
+ /*
+ * The purpose of the test image type is to track the calls to an image
+ * display proc and record the parameters passed in each call. On macOS
+ * a display proc must be run inside of the drawRect method of an NSView
+ * in order for the graphics operations to have any effect. To deal with
+ * this, whenever a display proc is called outside of any drawRect method
+ * it schedules a redraw of the NSView by calling [view setNeedsDisplay:YES].
+ * This will trigger a later call to the view's drawRect method which will
+ * run the display proc a second time.
+ *
+ * This complicates testing, since it can result in more calls to the display
+ * proc than are expected by the test. It can also result in an inconsistent
+ * number of calls unless the test waits until the call to drawRect actually
+ * occurs before validating its results.
+ *
+ * In an attempt to work around this, this display proc only logs those
+ * calls which occur within a drawRect method. This means that tests must
+ * be written so as to ensure that the drawRect method is run before
+ * results are validated. In practice it usually suffices to run update
+ * idletasks (to run the display proc the first time) followed by update
+ * (to run the display proc in drawRect).
+ *
+ * This also has the consequence that the image changed command will log
+ * different results on Aqua than on other systems, because when the image
+ * is redisplayed in the drawRect method the entire image will be drawn,
+ * not just the changed portion. Tests must account for this.
+ */
+
+ if (LOG_DISPLAY) {
+ sprintf(buffer, "%s display %d %d %d %d",
+ instPtr->masterPtr->imageName, imageX, imageY, width, height);
+ Tcl_SetVar2(instPtr->masterPtr->interp, instPtr->masterPtr->varName,
+ NULL, buffer, TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
+ }
+ if (width > (instPtr->masterPtr->width - imageX)) {
+ width = instPtr->masterPtr->width - imageX;
+ }
+ if (height > (instPtr->masterPtr->height - imageY)) {
+ height = instPtr->masterPtr->height - imageY;
+ }
+
+ XDrawRectangle(display, drawable, instPtr->gc, drawableX, drawableY,
+ (unsigned) (width-1), (unsigned) (height-1));
+ XDrawLine(display, drawable, instPtr->gc, drawableX, drawableY,
+ (int) (drawableX + width - 1), (int) (drawableY + height - 1));
+ XDrawLine(display, drawable, instPtr->gc, drawableX,
+ (int) (drawableY + height - 1),
+ (int) (drawableX + width - 1), drawableY);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImageFree --
+ *
+ * This function is called when an instance of an image is no longer
+ * used.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Information related to the instance is freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ImageFree(
+ ClientData clientData, /* Pointer to TImageInstance for instance. */
+ Display *display) /* Display where image was to be drawn. */
+{
+ TImageInstance *instPtr = (TImageInstance *) clientData;
+ char buffer[200];
+
+ sprintf(buffer, "%s free", instPtr->masterPtr->imageName);
+ Tcl_SetVar2(instPtr->masterPtr->interp, instPtr->masterPtr->varName, NULL,
+ buffer, TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
+ Tk_FreeColor(instPtr->fg);
+ Tk_FreeGC(display, instPtr->gc);
+ ckfree(instPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImageDelete --
+ *
+ * This function is called to clean up a test image when an application
+ * goes away.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Information about the image is deleted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ImageDelete(
+ ClientData clientData) /* Pointer to TImageMaster for image. When
+ * this function is called, no more instances
+ * exist. */
+{
+ TImageMaster *timPtr = (TImageMaster *) clientData;
+ char buffer[100];
+
+ sprintf(buffer, "%s delete", timPtr->imageName);
+ Tcl_SetVar2(timPtr->interp, timPtr->varName, NULL, buffer,
+ TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
+
+ Tcl_DeleteCommand(timPtr->interp, timPtr->imageName);
+ ckfree(timPtr->imageName);
+ ckfree(timPtr->varName);
+ ckfree(timPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TestmakeexistObjCmd --
+ *
+ * This function implements the "testmakeexist" command. It calls
+ * Tk_MakeWindowExist on each of its arguments to force the windows to be
+ * created.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * Forces windows to be created.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+TestmakeexistObjCmd(
+ ClientData clientData, /* Main window for application. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument strings. */
+{
+ Tk_Window mainWin = (Tk_Window) clientData;
+ int i;
+ Tk_Window tkwin;
+
+ for (i = 1; i < objc; i++) {
+ tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[i]), mainWin);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ Tk_MakeWindowExist(tkwin);
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TestmenubarObjCmd --
+ *
+ * This function implements the "testmenubar" command. It is used to test
+ * the Unix facilities for creating space above a toplevel window for a
+ * menubar.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * Changes menubar related stuff.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+#if !(defined(_WIN32) || defined(MAC_OSX_TK) || defined(__CYGWIN__))
+static int
+TestmenubarObjCmd(
+ ClientData clientData, /* Main window for application. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument strings. */
+{
+#ifdef __UNIX__
+ Tk_Window mainWin = (Tk_Window) clientData;
+ Tk_Window tkwin, menubar;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+
+ if (strcmp(Tcl_GetString(objv[1]), "window") == 0) {
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "windows toplevel menubar");
+ return TCL_ERROR;
+ }
+ tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), mainWin);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ if (Tcl_GetString(objv[3])[0] == 0) {
+ TkUnixSetMenubar(tkwin, NULL);
+ } else {
+ menubar = Tk_NameToWindow(interp, Tcl_GetString(objv[3]), mainWin);
+ if (menubar == NULL) {
+ return TCL_ERROR;
+ }
+ TkUnixSetMenubar(tkwin, menubar);
+ }
+ } else {
+ Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[1]),
+ "\": must be window", NULL);
+ return TCL_ERROR;
+ }
+
+ return TCL_OK;
+#else
+ Tcl_AppendResult(interp, "testmenubar is supported only under Unix", NULL);
+ return TCL_ERROR;
+#endif
+}
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TestmetricsObjCmd --
+ *
+ * This function implements the testmetrics command. It provides a way to
+ * determine the size of various widget components.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#if defined(_WIN32)
+static int
+TestmetricsObjCmd(
+ ClientData clientData, /* Main window for application. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument strings. */
+{
+ char buf[TCL_INTEGER_SPACE];
+ int val;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+
+ if (strcmp(Tcl_GetString(objv[1]), "cyvscroll") == 0) {
+ val = GetSystemMetrics(SM_CYVSCROLL);
+ } else if (strcmp(Tcl_GetString(objv[1]), "cxhscroll") == 0) {
+ val = GetSystemMetrics(SM_CXHSCROLL);
+ } else {
+ Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[1]),
+ "\": must be cxhscroll or cyvscroll", NULL);
+ return TCL_ERROR;
+ }
+ sprintf(buf, "%d", val);
+ Tcl_AppendResult(interp, buf, NULL);
+ return TCL_OK;
+}
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TestpropObjCmd --
+ *
+ * This function implements the "testprop" command. It fetches and prints
+ * the value of a property on a window.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+TestpropObjCmd(
+ ClientData clientData, /* Main window for application. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument strings. */
+{
+ Tk_Window mainWin = (Tk_Window) clientData;
+ int result, actualFormat;
+ unsigned long bytesAfter, length, value;
+ Atom actualType, propName;
+ unsigned char *property, *p;
+ char *end;
+ Window w;
+ char buffer[30];
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "window property");
+ return TCL_ERROR;
+ }
+
+ w = strtoul(Tcl_GetString(objv[1]), &end, 0);
+ propName = Tk_InternAtom(mainWin, Tcl_GetString(objv[2]));
+ property = NULL;
+ result = XGetWindowProperty(Tk_Display(mainWin),
+ w, propName, 0, 100000, False, AnyPropertyType,
+ &actualType, &actualFormat, &length,
+ &bytesAfter, &property);
+ if ((result == Success) && (actualType != None)) {
+ if ((actualFormat == 8) && (actualType == XA_STRING)) {
+ for (p = property; ((unsigned long)(p-property)) < length; p++) {
+ if (*p == 0) {
+ *p = '\n';
+ }
+ }
+ Tcl_SetObjResult(interp, Tcl_NewStringObj((/*!unsigned*/char*)property, -1));
+ } else {
+ for (p = property; length > 0; length--) {
+ if (actualFormat == 32) {
+ value = *((long *) p);
+ p += sizeof(long);
+ } else if (actualFormat == 16) {
+ value = 0xffff & (*((short *) p));
+ p += sizeof(short);
+ } else {
+ value = 0xff & *p;
+ p += 1;
+ }
+ sprintf(buffer, "0x%lx", value);
+ Tcl_AppendElement(interp, buffer);
+ }
+ }
+ }
+ if (property != NULL) {
+ XFree(property);
+ }
+ return TCL_OK;
+}
+
+#if !(defined(_WIN32) || defined(MAC_OSX_TK) || defined(__CYGWIN__))
+/*
+ *----------------------------------------------------------------------
+ *
+ * TestwrapperObjCmd --
+ *
+ * This function implements the "testwrapper" command. It provides a way
+ * from Tcl to determine the extra window Tk adds in between the toplevel
+ * window and the window decorations.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+TestwrapperObjCmd(
+ ClientData clientData, /* Main window for application. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument strings. */
+{
+ TkWindow *winPtr, *wrapperPtr;
+ Tk_Window tkwin;
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "window");
+ return TCL_ERROR;
+ }
+
+ tkwin = (Tk_Window) clientData;
+ winPtr = (TkWindow *) Tk_NameToWindow(interp, Tcl_GetString(objv[1]), tkwin);
+ if (winPtr == NULL) {
+ return TCL_ERROR;
+ }
+
+ wrapperPtr = TkpGetWrapperWindow(winPtr);
+ if (wrapperPtr != NULL) {
+ char buf[TCL_INTEGER_SPACE];
+
+ TkpPrintWindowId(buf, Tk_WindowId(wrapperPtr));
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1));
+ }
+ return TCL_OK;
+}
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CustomOptionSet, CustomOptionGet, CustomOptionRestore, CustomOptionFree --
+ *
+ * Handlers for object-based custom configuration options. See
+ * Testobjconfigcommand.
+ *
+ * Results:
+ * See user documentation for expected results from these functions.
+ * CustomOptionSet Standard Tcl Result.
+ * CustomOptionGet Tcl_Obj * containing value.
+ * CustomOptionRestore None.
+ * CustomOptionFree None.
+ *
+ * Side effects:
+ * Depends on the function.
+ * CustomOptionSet Sets option value to new setting.
+ * CustomOptionGet Creates a new Tcl_Obj.
+ * CustomOptionRestore Resets option value to original value.
+ * CustomOptionFree Free storage for internal rep of
+ * option.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CustomOptionSet(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ Tk_Window tkwin,
+ Tcl_Obj **value,
+ char *recordPtr,
+ int internalOffset,
+ char *saveInternalPtr,
+ int flags)
+{
+ int objEmpty;
+ char *newStr, *string, *internalPtr;
+
+ objEmpty = 0;
+
+ if (internalOffset >= 0) {
+ internalPtr = recordPtr + internalOffset;
+ } else {
+ internalPtr = NULL;
+ }
+
+ /*
+ * See if the object is empty.
+ */
+
+ if (value == NULL) {
+ objEmpty = 1;
+ CLANG_ASSERT(value);
+ } else if ((*value)->bytes != NULL) {
+ objEmpty = ((*value)->length == 0);
+ } else {
+ (void)Tcl_GetString(*value);
+ objEmpty = ((*value)->length == 0);
+ }
+
+ if ((flags & TK_OPTION_NULL_OK) && objEmpty) {
+ *value = NULL;
+ } else {
+ string = Tcl_GetString(*value);
+ Tcl_UtfToUpper(string);
+ if (strcmp(string, "BAD") == 0) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("expected good value, got \"BAD\"", -1));
+ return TCL_ERROR;
+ }
+ }
+ if (internalPtr != NULL) {
+ if (*value != NULL) {
+ string = Tcl_GetString(*value);
+ newStr = ckalloc((*value)->length + 1);
+ strcpy(newStr, string);
+ } else {
+ newStr = NULL;
+ }
+ *((char **) saveInternalPtr) = *((char **) internalPtr);
+ *((char **) internalPtr) = newStr;
+ }
+
+ return TCL_OK;
+}
+
+static Tcl_Obj *
+CustomOptionGet(
+ ClientData clientData,
+ Tk_Window tkwin,
+ char *recordPtr,
+ int internalOffset)
+{
+ return (Tcl_NewStringObj(*(char **)(recordPtr + internalOffset), -1));
+}
+
+static void
+CustomOptionRestore(
+ ClientData clientData,
+ Tk_Window tkwin,
+ char *internalPtr,
+ char *saveInternalPtr)
+{
+ *(char **)internalPtr = *(char **)saveInternalPtr;
+ return;
+}
+
+static void
+CustomOptionFree(
+ ClientData clientData,
+ Tk_Window tkwin,
+ char *internalPtr)
+{
+ if (*(char **)internalPtr != NULL) {
+ ckfree(*(char **)internalPtr);
+ }
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkText.c b/tk8.6/generic/tkText.c
new file mode 100644
index 0000000..7c62621
--- /dev/null
+++ b/tk8.6/generic/tkText.c
@@ -0,0 +1,6920 @@
+/*
+ * tkText.c --
+ *
+ * This module provides a big chunk of the implementation of multi-line
+ * editable text widgets for Tk. Among other things, it provides the Tcl
+ * command interfaces to text widgets. The B-tree representation of text
+ * and its actual display are implemented elsewhere.
+ *
+ * Copyright (c) 1992-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1996 Sun Microsystems, Inc.
+ * Copyright (c) 1999 by Scriptics Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "default.h"
+#include "tkInt.h"
+#include "tkUndo.h"
+
+#if defined(MAC_OSX_TK)
+#define Style TkStyle
+#define DInfo TkDInfo
+#endif
+
+/*
+ * For compatibility with Tk 4.0 through 8.4.x, we allow tabs to be
+ * mis-specified with non-increasing values. These are converted into tabs
+ * which are the equivalent of at least a character width apart.
+ */
+
+#if (TK_MAJOR_VERSION < 9)
+#define _TK_ALLOW_DECREASING_TABS
+#endif
+
+#include "tkText.h"
+
+/*
+ * Used to avoid having to allocate and deallocate arrays on the fly for
+ * commonly used functions. Must be > 0.
+ */
+
+#define PIXEL_CLIENTS 5
+
+/*
+ * The 'TkTextState' enum in tkText.h is used to define a type for the -state
+ * option of the Text widget. These values are used as indices into the string
+ * table below.
+ */
+
+static const char *const stateStrings[] = {
+ "disabled", "normal", NULL
+};
+
+/*
+ * The 'TkWrapMode' enum in tkText.h is used to define a type for the -wrap
+ * option of the Text widget. These values are used as indices into the string
+ * table below.
+ */
+
+static const char *const wrapStrings[] = {
+ "char", "none", "word", NULL
+};
+
+/*
+ * The 'TkTextTabStyle' enum in tkText.h is used to define a type for the
+ * -tabstyle option of the Text widget. These values are used as indices into
+ * the string table below.
+ */
+
+static const char *const tabStyleStrings[] = {
+ "tabular", "wordprocessor", NULL
+};
+
+/*
+ * The 'TkTextInsertUnfocussed' enum in tkText.h is used to define a type for
+ * the -insertunfocussed option of the Text widget. These values are used as
+ * indice into the string table below.
+ */
+
+static const char *const insertUnfocussedStrings[] = {
+ "hollow", "none", "solid", NULL
+};
+
+/*
+ * The following functions and custom option type are used to define the
+ * "line" option type, and thereby handle the text widget '-startline',
+ * '-endline' configuration options which are of that type.
+ *
+ * We do not need a 'freeProc' because all changes to these two options are
+ * handled through the TK_TEXT_LINE_RANGE flag in the optionSpecs list, and
+ * the internal storage is just a pointer, which therefore doesn't need
+ * freeing.
+ */
+
+static int SetLineStartEnd(ClientData clientData,
+ Tcl_Interp *interp, Tk_Window tkwin,
+ Tcl_Obj **value, char *recordPtr,
+ int internalOffset, char *oldInternalPtr,
+ int flags);
+static Tcl_Obj * GetLineStartEnd(ClientData clientData,
+ Tk_Window tkwin, char *recordPtr,
+ int internalOffset);
+static void RestoreLineStartEnd(ClientData clientData,
+ Tk_Window tkwin, char *internalPtr,
+ char *oldInternalPtr);
+static int ObjectIsEmpty(Tcl_Obj *objPtr);
+
+static const Tk_ObjCustomOption lineOption = {
+ "line", /* name */
+ SetLineStartEnd, /* setProc */
+ GetLineStartEnd, /* getProc */
+ RestoreLineStartEnd, /* restoreProc */
+ NULL, /* freeProc */
+ 0
+};
+
+/*
+ * Information used to parse text configuration options:
+ */
+
+static const Tk_OptionSpec optionSpecs[] = {
+ {TK_OPTION_BOOLEAN, "-autoseparators", "autoSeparators",
+ "AutoSeparators", DEF_TEXT_AUTO_SEPARATORS, -1,
+ Tk_Offset(TkText, autoSeparators),
+ TK_OPTION_DONT_SET_DEFAULT, 0, 0},
+ {TK_OPTION_BORDER, "-background", "background", "Background",
+ DEF_TEXT_BG_COLOR, -1, Tk_Offset(TkText, border),
+ 0, DEF_TEXT_BG_MONO, 0},
+ {TK_OPTION_SYNONYM, "-bd", NULL, NULL,
+ NULL, 0, -1, 0, "-borderwidth",
+ TK_TEXT_LINE_GEOMETRY},
+ {TK_OPTION_SYNONYM, "-bg", NULL, NULL,
+ NULL, 0, -1, 0, "-background", 0},
+ {TK_OPTION_BOOLEAN, "-blockcursor", "blockCursor",
+ "BlockCursor", DEF_TEXT_BLOCK_CURSOR, -1,
+ Tk_Offset(TkText, insertCursorType), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ DEF_TEXT_BORDER_WIDTH, -1, Tk_Offset(TkText, borderWidth),
+ 0, 0, TK_TEXT_LINE_GEOMETRY},
+ {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
+ DEF_TEXT_CURSOR, -1, Tk_Offset(TkText, cursor),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_CUSTOM, "-endline", NULL, NULL,
+ NULL, -1, Tk_Offset(TkText, end), TK_OPTION_NULL_OK,
+ &lineOption, TK_TEXT_LINE_RANGE},
+ {TK_OPTION_BOOLEAN, "-exportselection", "exportSelection",
+ "ExportSelection", DEF_TEXT_EXPORT_SELECTION, -1,
+ Tk_Offset(TkText, exportSelection), 0, 0, 0},
+ {TK_OPTION_SYNONYM, "-fg", "foreground", NULL,
+ NULL, 0, -1, 0, "-foreground", 0},
+ {TK_OPTION_FONT, "-font", "font", "Font",
+ DEF_TEXT_FONT, -1, Tk_Offset(TkText, tkfont), 0, 0,
+ TK_TEXT_LINE_GEOMETRY},
+ {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
+ DEF_TEXT_FG, -1, Tk_Offset(TkText, fgColor), 0,
+ 0, 0},
+ {TK_OPTION_PIXELS, "-height", "height", "Height",
+ DEF_TEXT_HEIGHT, -1, Tk_Offset(TkText, height), 0, 0, 0},
+ {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground",
+ "HighlightBackground", DEF_TEXT_HIGHLIGHT_BG,
+ -1, Tk_Offset(TkText, highlightBgColorPtr),
+ 0, 0, 0},
+ {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
+ DEF_TEXT_HIGHLIGHT, -1, Tk_Offset(TkText, highlightColorPtr),
+ 0, 0, 0},
+ {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
+ "HighlightThickness", DEF_TEXT_HIGHLIGHT_WIDTH, -1,
+ Tk_Offset(TkText, highlightWidth), 0, 0, TK_TEXT_LINE_GEOMETRY},
+ {TK_OPTION_BORDER, "-inactiveselectbackground","inactiveSelectBackground",
+ "Foreground",
+ DEF_TEXT_INACTIVE_SELECT_COLOR,
+ -1, Tk_Offset(TkText, inactiveSelBorder),
+ TK_OPTION_NULL_OK, DEF_TEXT_SELECT_MONO, 0},
+ {TK_OPTION_BORDER, "-insertbackground", "insertBackground", "Foreground",
+ DEF_TEXT_INSERT_BG,
+ -1, Tk_Offset(TkText, insertBorder),
+ 0, 0, 0},
+ {TK_OPTION_PIXELS, "-insertborderwidth", "insertBorderWidth",
+ "BorderWidth", DEF_TEXT_INSERT_BD_COLOR, -1,
+ Tk_Offset(TkText, insertBorderWidth), 0,
+ (ClientData) DEF_TEXT_INSERT_BD_MONO, 0},
+ {TK_OPTION_INT, "-insertofftime", "insertOffTime", "OffTime",
+ DEF_TEXT_INSERT_OFF_TIME, -1, Tk_Offset(TkText, insertOffTime),
+ 0, 0, 0},
+ {TK_OPTION_INT, "-insertontime", "insertOnTime", "OnTime",
+ DEF_TEXT_INSERT_ON_TIME, -1, Tk_Offset(TkText, insertOnTime),
+ 0, 0, 0},
+ {TK_OPTION_STRING_TABLE,
+ "-insertunfocussed", "insertUnfocussed", "InsertUnfocussed",
+ DEF_TEXT_INSERT_UNFOCUSSED, -1, Tk_Offset(TkText, insertUnfocussed),
+ 0, insertUnfocussedStrings, 0},
+ {TK_OPTION_PIXELS, "-insertwidth", "insertWidth", "InsertWidth",
+ DEF_TEXT_INSERT_WIDTH, -1, Tk_Offset(TkText, insertWidth),
+ 0, 0, 0},
+ {TK_OPTION_INT, "-maxundo", "maxUndo", "MaxUndo",
+ DEF_TEXT_MAX_UNDO, -1, Tk_Offset(TkText, maxUndo),
+ TK_OPTION_DONT_SET_DEFAULT, 0, 0},
+ {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
+ DEF_TEXT_PADX, -1, Tk_Offset(TkText, padX), 0, 0,
+ TK_TEXT_LINE_GEOMETRY},
+ {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
+ DEF_TEXT_PADY, -1, Tk_Offset(TkText, padY), 0, 0, 0},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ DEF_TEXT_RELIEF, -1, Tk_Offset(TkText, relief), 0, 0, 0},
+ {TK_OPTION_BORDER, "-selectbackground", "selectBackground", "Foreground",
+ DEF_TEXT_SELECT_COLOR, -1, Tk_Offset(TkText, selBorder),
+ 0, DEF_TEXT_SELECT_MONO, 0},
+ {TK_OPTION_PIXELS, "-selectborderwidth", "selectBorderWidth",
+ "BorderWidth", DEF_TEXT_SELECT_BD_COLOR,
+ Tk_Offset(TkText, selBorderWidthPtr),
+ Tk_Offset(TkText, selBorderWidth),
+ TK_OPTION_NULL_OK, DEF_TEXT_SELECT_BD_MONO, 0},
+ {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background",
+ DEF_TEXT_SELECT_FG_COLOR, -1, Tk_Offset(TkText, selFgColorPtr),
+ TK_OPTION_NULL_OK, DEF_TEXT_SELECT_FG_MONO, 0},
+ {TK_OPTION_BOOLEAN, "-setgrid", "setGrid", "SetGrid",
+ DEF_TEXT_SET_GRID, -1, Tk_Offset(TkText, setGrid), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-spacing1", "spacing1", "Spacing",
+ DEF_TEXT_SPACING1, -1, Tk_Offset(TkText, spacing1),
+ 0, 0 , TK_TEXT_LINE_GEOMETRY },
+ {TK_OPTION_PIXELS, "-spacing2", "spacing2", "Spacing",
+ DEF_TEXT_SPACING2, -1, Tk_Offset(TkText, spacing2),
+ 0, 0 , TK_TEXT_LINE_GEOMETRY },
+ {TK_OPTION_PIXELS, "-spacing3", "spacing3", "Spacing",
+ DEF_TEXT_SPACING3, -1, Tk_Offset(TkText, spacing3),
+ 0, 0 , TK_TEXT_LINE_GEOMETRY },
+ {TK_OPTION_CUSTOM, "-startline", NULL, NULL,
+ NULL, -1, Tk_Offset(TkText, start), TK_OPTION_NULL_OK,
+ &lineOption, TK_TEXT_LINE_RANGE},
+ {TK_OPTION_STRING_TABLE, "-state", "state", "State",
+ DEF_TEXT_STATE, -1, Tk_Offset(TkText, state),
+ 0, stateStrings, 0},
+ {TK_OPTION_STRING, "-tabs", "tabs", "Tabs",
+ DEF_TEXT_TABS, Tk_Offset(TkText, tabOptionPtr), -1,
+ TK_OPTION_NULL_OK, 0, TK_TEXT_LINE_GEOMETRY},
+ {TK_OPTION_STRING_TABLE, "-tabstyle", "tabStyle", "TabStyle",
+ DEF_TEXT_TABSTYLE, -1, Tk_Offset(TkText, tabStyle),
+ 0, tabStyleStrings, TK_TEXT_LINE_GEOMETRY},
+ {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
+ DEF_TEXT_TAKE_FOCUS, -1, Tk_Offset(TkText, takeFocus),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_BOOLEAN, "-undo", "undo", "Undo",
+ DEF_TEXT_UNDO, -1, Tk_Offset(TkText, undo),
+ TK_OPTION_DONT_SET_DEFAULT, 0 , 0},
+ {TK_OPTION_INT, "-width", "width", "Width",
+ DEF_TEXT_WIDTH, -1, Tk_Offset(TkText, width), 0, 0,
+ TK_TEXT_LINE_GEOMETRY},
+ {TK_OPTION_STRING_TABLE, "-wrap", "wrap", "Wrap",
+ DEF_TEXT_WRAP, -1, Tk_Offset(TkText, wrapMode),
+ 0, wrapStrings, TK_TEXT_LINE_GEOMETRY},
+ {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
+ DEF_TEXT_XSCROLL_COMMAND, -1, Tk_Offset(TkText, xScrollCmd),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand",
+ DEF_TEXT_YSCROLL_COMMAND, -1, Tk_Offset(TkText, yScrollCmd),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_END, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0}
+};
+
+/*
+ * These three typedefs, the structure and the SearchPerform, SearchCore
+ * functions below are used for line-based searches of the text widget, and,
+ * in particular, to handle multi-line matching even though the text widget is
+ * a single-line based data structure. They are completely abstracted away
+ * from the Text widget internals, however, so could easily be re-used with
+ * any line-based entity to provide multi-line matching.
+ *
+ * We have abstracted this code away from the text widget to try to keep Tk as
+ * modular as possible.
+ */
+
+struct SearchSpec; /* Forward declaration. */
+
+typedef ClientData SearchAddLineProc(int lineNum,
+ struct SearchSpec *searchSpecPtr,
+ Tcl_Obj *theLine, int *lenPtr,
+ int *extraLinesPtr);
+typedef int SearchMatchProc(int lineNum,
+ struct SearchSpec *searchSpecPtr,
+ ClientData clientData, Tcl_Obj *theLine,
+ int matchOffset, int matchLength);
+typedef int SearchLineIndexProc(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, struct SearchSpec *searchSpecPtr,
+ int *linePosPtr, int *offsetPosPtr);
+
+typedef struct SearchSpec {
+ int exact; /* Whether search is exact or regexp. */
+ int noCase; /* Case-insenstivive? */
+ int noLineStop; /* If not set, a regexp search will use the
+ * TCL_REG_NLSTOP flag. */
+ int overlap; /* If set, results from multiple searches
+ * (-all) are allowed to overlap each
+ * other. */
+ int strictLimits; /* If set, matches must be completely inside
+ * the from,to range. Otherwise the limits
+ * only apply to the start of each match. */
+ int all; /* Whether all or the first match should be
+ * reported. */
+ int startLine; /* First line to examine. */
+ int startOffset; /* Index in first line to start at. */
+ int stopLine; /* Last line to examine, or -1 when we search
+ * all available text. */
+ int stopOffset; /* Index to stop at, provided stopLine is not
+ * -1. */
+ int numLines; /* Total lines which are available. */
+ int backwards; /* Searching forwards or backwards. */
+ Tcl_Obj *varPtr; /* If non-NULL, store length(s) of match(es)
+ * in this variable. */
+ Tcl_Obj *countPtr; /* Keeps track of currently found lengths. */
+ Tcl_Obj *resPtr; /* Keeps track of currently found locations */
+ int searchElide; /* Search in hidden text as well. */
+ SearchAddLineProc *addLineProc;
+ /* Function to call when we need to add
+ * another line to the search string so far */
+ SearchMatchProc *foundMatchProc;
+ /* Function to call when we have found a
+ * match. */
+ SearchLineIndexProc *lineIndexProc;
+ /* Function to call when we have found a
+ * match. */
+ ClientData clientData; /* Information about structure being searched,
+ * in this case a text widget. */
+} SearchSpec;
+
+/*
+ * The text-widget-independent functions which actually perform the search,
+ * handling both regexp and exact searches.
+ */
+
+static int SearchCore(Tcl_Interp *interp,
+ SearchSpec *searchSpecPtr, Tcl_Obj *patObj);
+static int SearchPerform(Tcl_Interp *interp,
+ SearchSpec *searchSpecPtr, Tcl_Obj *patObj,
+ Tcl_Obj *fromPtr, Tcl_Obj *toPtr);
+
+/*
+ * Boolean variable indicating whether or not special debugging code should be
+ * executed.
+ */
+
+int tkTextDebug = 0;
+
+/*
+ * Forward declarations for functions defined later in this file:
+ */
+
+static int ConfigureText(Tcl_Interp *interp,
+ TkText *textPtr, int objc, Tcl_Obj *const objv[]);
+static int DeleteIndexRange(TkSharedText *sharedPtr,
+ TkText *textPtr, const TkTextIndex *indexPtr1,
+ const TkTextIndex *indexPtr2, int viewUpdate);
+static int CountIndices(const TkText *textPtr,
+ const TkTextIndex *indexPtr1,
+ const TkTextIndex *indexPtr2,
+ TkTextCountType type);
+static void DestroyText(TkText *textPtr);
+static int InsertChars(TkSharedText *sharedTextPtr,
+ TkText *textPtr, TkTextIndex *indexPtr,
+ Tcl_Obj *stringPtr, int viewUpdate);
+static void TextBlinkProc(ClientData clientData);
+static void TextCmdDeletedProc(ClientData clientData);
+static int CreateWidget(TkSharedText *sharedPtr, Tk_Window tkwin,
+ Tcl_Interp *interp, const TkText *parent,
+ int objc, Tcl_Obj *const objv[]);
+static void TextEventProc(ClientData clientData,
+ XEvent *eventPtr);
+static int TextFetchSelection(ClientData clientData, int offset,
+ char *buffer, int maxBytes);
+static int TextIndexSortProc(const void *first,
+ const void *second);
+static int TextInsertCmd(TkSharedText *sharedTextPtr,
+ TkText *textPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[],
+ const TkTextIndex *indexPtr, int viewUpdate);
+static int TextReplaceCmd(TkText *textPtr, Tcl_Interp *interp,
+ const TkTextIndex *indexFromPtr,
+ const TkTextIndex *indexToPtr,
+ int objc, Tcl_Obj *const objv[], int viewUpdate);
+static int TextSearchCmd(TkText *textPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int TextEditCmd(TkText *textPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int TextWidgetObjCmd(ClientData clientData,
+ Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int SharedTextObjCmd(ClientData clientData,
+ Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static void TextWorldChangedCallback(ClientData instanceData);
+static void TextWorldChanged(TkText *textPtr, int mask);
+static int TextDumpCmd(TkText *textPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int DumpLine(Tcl_Interp *interp, TkText *textPtr,
+ int what, TkTextLine *linePtr, int start, int end,
+ int lineno, Tcl_Obj *command);
+static int DumpSegment(TkText *textPtr, Tcl_Interp *interp,
+ const char *key, const char *value,
+ Tcl_Obj *command, const TkTextIndex *index,
+ int what);
+static int TextEditUndo(TkText *textPtr);
+static int TextEditRedo(TkText *textPtr);
+static Tcl_Obj * TextGetText(const TkText *textPtr,
+ const TkTextIndex *index1,
+ const TkTextIndex *index2, int visibleOnly);
+static void GenerateModifiedEvent(TkText *textPtr);
+static void GenerateUndoStackEvent(TkText *textPtr);
+static void UpdateDirtyFlag(TkSharedText *sharedPtr);
+static void TextPushUndoAction(TkText *textPtr,
+ Tcl_Obj *undoString, int insert,
+ const TkTextIndex *index1Ptr,
+ const TkTextIndex *index2Ptr);
+static int TextSearchIndexInLine(const SearchSpec *searchSpecPtr,
+ TkTextLine *linePtr, int byteIndex);
+static int TextPeerCmd(TkText *textPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static TkUndoProc TextUndoRedoCallback;
+
+/*
+ * Declarations of the three search procs required by the multi-line search
+ * routines.
+ */
+
+static SearchMatchProc TextSearchFoundMatch;
+static SearchAddLineProc TextSearchAddNextLine;
+static SearchLineIndexProc TextSearchGetLineIndex;
+
+/*
+ * The structure below defines text class behavior by means of functions that
+ * can be invoked from generic window code.
+ */
+
+static const Tk_ClassProcs textClass = {
+ sizeof(Tk_ClassProcs), /* size */
+ TextWorldChangedCallback, /* worldChangedProc */
+ NULL, /* createProc */
+ NULL /* modalProc */
+};
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_TextObjCmd --
+ *
+ * This function is invoked to process the "text" 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_TextObjCmd(
+ 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 = clientData;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?");
+ return TCL_ERROR;
+ }
+
+ return CreateWidget(NULL, tkwin, interp, NULL, objc, objv);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * CreateWidget --
+ *
+ * This function is invoked to process the "text" Tcl command, (when
+ * called by Tk_TextObjCmd) and the "$text peer create" text widget
+ * sub-command (called from TextPeerCmd).
+ *
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result, places the name of the widget created into the
+ * interp's result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+CreateWidget(
+ TkSharedText *sharedPtr, /* Shared widget info, or NULL. */
+ Tk_Window tkwin, /* Main window associated with interpreter. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ const TkText *parent, /* If non-NULL then take default start, end
+ * from this parent. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ register TkText *textPtr;
+ Tk_OptionTable optionTable;
+ TkTextIndex startIndex;
+ Tk_Window newWin;
+
+ /*
+ * Create the window.
+ */
+
+ newWin = Tk_CreateWindowFromPath(interp, tkwin, Tcl_GetString(objv[1]),
+ NULL);
+ if (newWin == NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Create the text widget and initialize everything to zero, then set the
+ * necessary initial (non-NULL) values. It is important that the 'set' tag
+ * and 'insert', 'current' mark pointers are all NULL to start.
+ */
+
+ textPtr = ckalloc(sizeof(TkText));
+ memset(textPtr, 0, sizeof(TkText));
+
+ textPtr->tkwin = newWin;
+ textPtr->display = Tk_Display(newWin);
+ textPtr->interp = interp;
+ textPtr->widgetCmd = Tcl_CreateObjCommand(interp,
+ Tk_PathName(textPtr->tkwin), TextWidgetObjCmd,
+ textPtr, TextCmdDeletedProc);
+
+ if (sharedPtr == NULL) {
+ sharedPtr = ckalloc(sizeof(TkSharedText));
+ memset(sharedPtr, 0, sizeof(TkSharedText));
+
+ sharedPtr->refCount = 0;
+ sharedPtr->peers = NULL;
+ sharedPtr->tree = TkBTreeCreate(sharedPtr);
+
+ Tcl_InitHashTable(&sharedPtr->tagTable, TCL_STRING_KEYS);
+ Tcl_InitHashTable(&sharedPtr->markTable, TCL_STRING_KEYS);
+ Tcl_InitHashTable(&sharedPtr->windowTable, TCL_STRING_KEYS);
+ Tcl_InitHashTable(&sharedPtr->imageTable, TCL_STRING_KEYS);
+ sharedPtr->undoStack = TkUndoInitStack(interp,0);
+ sharedPtr->undo = 0;
+ sharedPtr->isDirty = 0;
+ sharedPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL;
+ sharedPtr->autoSeparators = 1;
+ sharedPtr->lastEditMode = TK_TEXT_EDIT_OTHER;
+ sharedPtr->stateEpoch = 0;
+ }
+
+ /*
+ * Add the new widget to the shared list.
+ */
+
+ textPtr->sharedTextPtr = sharedPtr;
+ sharedPtr->refCount++;
+ textPtr->next = sharedPtr->peers;
+ sharedPtr->peers = textPtr;
+
+ /*
+ * This refCount will be held until DestroyText is called. Note also that
+ * the later call to 'TkTextCreateDInfo' will add more refCounts.
+ */
+
+ textPtr->refCount = 1;
+
+ /*
+ * Specify start and end lines in the B-tree. The default is the same as
+ * the parent, but this can be adjusted to display more or less if the
+ * start, end where given as configuration options.
+ */
+
+ if (parent != NULL) {
+ textPtr->start = parent->start;
+ textPtr->end = parent->end;
+ } else {
+ textPtr->start = NULL;
+ textPtr->end = NULL;
+ }
+
+ textPtr->state = TK_TEXT_STATE_NORMAL;
+ textPtr->relief = TK_RELIEF_FLAT;
+ textPtr->cursor = NULL;
+ textPtr->charWidth = 1;
+ textPtr->charHeight = 10;
+ textPtr->wrapMode = TEXT_WRAPMODE_CHAR;
+ textPtr->prevWidth = Tk_Width(newWin);
+ textPtr->prevHeight = Tk_Height(newWin);
+
+ /*
+ * Register with the B-tree. In some sense it would be best if we could do
+ * this later (after configuration options), so that any changes to
+ * start,end do not require a total recalculation.
+ */
+
+ TkBTreeAddClient(sharedPtr->tree, textPtr, textPtr->charHeight);
+
+ /*
+ * This will add refCounts to textPtr.
+ */
+
+ TkTextCreateDInfo(textPtr);
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, 0, 0,
+ &startIndex);
+ TkTextSetYView(textPtr, &startIndex, 0);
+ textPtr->exportSelection = 1;
+ textPtr->pickEvent.type = LeaveNotify;
+ textPtr->undo = textPtr->sharedTextPtr->undo;
+ textPtr->maxUndo = textPtr->sharedTextPtr->maxUndo;
+ textPtr->autoSeparators = textPtr->sharedTextPtr->autoSeparators;
+ textPtr->tabOptionPtr = NULL;
+
+ /*
+ * Create the "sel" tag and the "current" and "insert" marks.
+ */
+
+ textPtr->selBorder = NULL;
+ textPtr->inactiveSelBorder = NULL;
+ textPtr->selBorderWidth = 0;
+ textPtr->selBorderWidthPtr = NULL;
+ textPtr->selFgColorPtr = NULL;
+
+ /*
+ * Note: it is important that textPtr->selTagPtr is NULL before this
+ * initial call.
+ */
+
+ textPtr->selTagPtr = TkTextCreateTag(textPtr, "sel", NULL);
+ textPtr->selTagPtr->reliefString =
+ ckalloc(sizeof(DEF_TEXT_SELECT_RELIEF));
+ strcpy(textPtr->selTagPtr->reliefString, DEF_TEXT_SELECT_RELIEF);
+ Tk_GetRelief(interp, DEF_TEXT_SELECT_RELIEF, &textPtr->selTagPtr->relief);
+ textPtr->currentMarkPtr = TkTextSetMark(textPtr, "current", &startIndex);
+ textPtr->insertMarkPtr = TkTextSetMark(textPtr, "insert", &startIndex);
+
+ /*
+ * Create the option table for this widget class. If it has already been
+ * created, the cached pointer will be returned.
+ */
+
+ optionTable = Tk_CreateOptionTable(interp, optionSpecs);
+
+ Tk_SetClass(textPtr->tkwin, "Text");
+ Tk_SetClassProcs(textPtr->tkwin, &textClass, textPtr);
+ textPtr->optionTable = optionTable;
+
+ Tk_CreateEventHandler(textPtr->tkwin,
+ ExposureMask|StructureNotifyMask|FocusChangeMask,
+ TextEventProc, textPtr);
+ Tk_CreateEventHandler(textPtr->tkwin, KeyPressMask|KeyReleaseMask
+ |ButtonPressMask|ButtonReleaseMask|EnterWindowMask
+ |LeaveWindowMask|PointerMotionMask|VirtualEventMask,
+ TkTextBindProc, textPtr);
+ Tk_CreateSelHandler(textPtr->tkwin, XA_PRIMARY, XA_STRING,
+ TextFetchSelection, textPtr, XA_STRING);
+
+ if (Tk_InitOptions(interp, (char *) textPtr, optionTable, textPtr->tkwin)
+ != TCL_OK) {
+ Tk_DestroyWindow(textPtr->tkwin);
+ return TCL_ERROR;
+ }
+ if (ConfigureText(interp, textPtr, objc-2, objv+2) != TCL_OK) {
+ Tk_DestroyWindow(textPtr->tkwin);
+ return TCL_ERROR;
+ }
+
+ Tcl_SetObjResult(interp, TkNewWindowObj(textPtr->tkwin));
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TextWidgetObjCmd --
+ *
+ * This function is invoked to process the Tcl command that corresponds
+ * to a text widget. See the user documentation for details on what it
+ * does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+TextWidgetObjCmd(
+ ClientData clientData, /* Information about text widget. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ register TkText *textPtr = clientData;
+ int result = TCL_OK;
+ int index;
+
+ static const char *const optionStrings[] = {
+ "bbox", "cget", "compare", "configure", "count", "debug", "delete",
+ "dlineinfo", "dump", "edit", "get", "image", "index", "insert",
+ "mark", "peer", "pendingsync", "replace", "scan", "search",
+ "see", "sync", "tag", "window", "xview", "yview", NULL
+ };
+ enum options {
+ TEXT_BBOX, TEXT_CGET, TEXT_COMPARE, TEXT_CONFIGURE, TEXT_COUNT,
+ TEXT_DEBUG, TEXT_DELETE, TEXT_DLINEINFO, TEXT_DUMP, TEXT_EDIT,
+ TEXT_GET, TEXT_IMAGE, TEXT_INDEX, TEXT_INSERT, TEXT_MARK,
+ TEXT_PEER, TEXT_PENDINGSYNC, TEXT_REPLACE, TEXT_SCAN,
+ TEXT_SEARCH, TEXT_SEE, TEXT_SYNC, TEXT_TAG, TEXT_WINDOW,
+ TEXT_XVIEW, TEXT_YVIEW
+ };
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings,
+ sizeof(char *), "option", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ textPtr->refCount++;
+
+ switch ((enum options) index) {
+ case TEXT_BBOX: {
+ int x, y, width, height;
+ const TkTextIndex *indexPtr;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index");
+ result = TCL_ERROR;
+ goto done;
+ }
+ indexPtr = TkTextGetIndexFromObj(interp, textPtr, objv[2]);
+ if (indexPtr == NULL) {
+ result = TCL_ERROR;
+ goto done;
+ }
+ if (TkTextIndexBbox(textPtr, indexPtr, &x, &y, &width, &height,
+ NULL) == 0) {
+ Tcl_Obj *listObj = Tcl_NewListObj(0, NULL);
+
+ Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(x));
+ Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(y));
+ Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(width));
+ Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(height));
+
+ Tcl_SetObjResult(interp, listObj);
+ }
+ break;
+ }
+ case TEXT_CGET:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option");
+ result = TCL_ERROR;
+ goto done;
+ } else {
+ Tcl_Obj *objPtr = Tk_GetOptionValue(interp, (char *) textPtr,
+ textPtr->optionTable, objv[2], textPtr->tkwin);
+
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ goto done;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ result = TCL_OK;
+ }
+ break;
+ case TEXT_COMPARE: {
+ int relation, value;
+ const char *p;
+ const TkTextIndex *index1Ptr, *index2Ptr;
+
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index1 op index2");
+ result = TCL_ERROR;
+ goto done;
+ }
+ index1Ptr = TkTextGetIndexFromObj(interp, textPtr, objv[2]);
+ index2Ptr = TkTextGetIndexFromObj(interp, textPtr, objv[4]);
+ if (index1Ptr == NULL || index2Ptr == NULL) {
+ result = TCL_ERROR;
+ goto done;
+ }
+ relation = TkTextIndexCmp(index1Ptr, index2Ptr);
+ p = Tcl_GetString(objv[3]);
+ if (p[0] == '<') {
+ value = (relation < 0);
+ if ((p[1] == '=') && (p[2] == 0)) {
+ value = (relation <= 0);
+ } else if (p[1] != 0) {
+ goto compareError;
+ }
+ } else if (p[0] == '>') {
+ value = (relation > 0);
+ if ((p[1] == '=') && (p[2] == 0)) {
+ value = (relation >= 0);
+ } else if (p[1] != 0) {
+ goto compareError;
+ }
+ } else if ((p[0] == '=') && (p[1] == '=') && (p[2] == 0)) {
+ value = (relation == 0);
+ } else if ((p[0] == '!') && (p[1] == '=') && (p[2] == 0)) {
+ value = (relation != 0);
+ } else {
+ goto compareError;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(value));
+ break;
+
+ compareError:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad comparison operator \"%s\": must be"
+ " <, <=, ==, >=, >, or !=", Tcl_GetString(objv[3])));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "COMPARISON", NULL);
+ result = TCL_ERROR;
+ goto done;
+ }
+ case TEXT_CONFIGURE:
+ if (objc <= 3) {
+ Tcl_Obj *objPtr = Tk_GetOptionInfo(interp, (char *) textPtr,
+ textPtr->optionTable, ((objc == 3) ? objv[2] : NULL),
+ textPtr->tkwin);
+
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ goto done;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ } else {
+ result = ConfigureText(interp, textPtr, objc-2, objv+2);
+ }
+ break;
+ case TEXT_COUNT: {
+ const TkTextIndex *indexFromPtr, *indexToPtr;
+ int i, found = 0, update = 0;
+ Tcl_Obj *objPtr = NULL;
+
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-option value ...? index1 index2");
+ result = TCL_ERROR;
+ goto done;
+ }
+
+ indexFromPtr = TkTextGetIndexFromObj(interp, textPtr, objv[objc-2]);
+ if (indexFromPtr == NULL) {
+ result = TCL_ERROR;
+ goto done;
+ }
+ indexToPtr = TkTextGetIndexFromObj(interp, textPtr, objv[objc-1]);
+ if (indexToPtr == NULL) {
+ result = TCL_ERROR;
+ goto done;
+ }
+
+ for (i = 2; i < objc-2; i++) {
+ int value;
+ size_t length;
+ const char *option = Tcl_GetString(objv[i]);
+ char c;
+
+ length = objv[i]->length;
+ if (length < 2 || option[0] != '-') {
+ goto badOption;
+ }
+ c = option[1];
+ if (c == 'c' && !strncmp("-chars", option, length)) {
+ value = CountIndices(textPtr, indexFromPtr, indexToPtr,
+ COUNT_CHARS);
+ } else if (c == 'd' && (length > 8)
+ && !strncmp("-displaychars", option, length)) {
+ value = CountIndices(textPtr, indexFromPtr, indexToPtr,
+ COUNT_DISPLAY_CHARS);
+ } else if (c == 'd' && (length > 8)
+ && !strncmp("-displayindices", option,length)) {
+ value = CountIndices(textPtr, indexFromPtr, indexToPtr,
+ COUNT_DISPLAY_INDICES);
+ } else if (c == 'd' && (length > 8)
+ && !strncmp("-displaylines", option, length)) {
+ TkTextLine *fromPtr, *lastPtr;
+ TkTextIndex index, index2;
+
+ int compare = TkTextIndexCmp(indexFromPtr, indexToPtr);
+ value = 0;
+
+ if (compare == 0) {
+ goto countDone;
+ }
+
+ if (compare > 0) {
+ const TkTextIndex *tmpPtr = indexFromPtr;
+
+ indexFromPtr = indexToPtr;
+ indexToPtr = tmpPtr;
+ }
+
+ lastPtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree,
+ textPtr,
+ TkBTreeNumLines(textPtr->sharedTextPtr->tree,textPtr));
+ fromPtr = indexFromPtr->linePtr;
+ if (fromPtr == lastPtr) {
+ goto countDone;
+ }
+
+ /*
+ * Caution: we must NEVER call TkTextUpdateOneLine with the
+ * last artificial line in the widget.
+ */
+
+ index = *indexFromPtr;
+ index.byteIndex = 0;
+
+ /*
+ * We're going to count up all display lines in the logical
+ * line of 'indexFromPtr' up to, but not including the logical
+ * line of 'indexToPtr' (except if this line is elided), and
+ * then subtract off what came in too much from elided lines,
+ * also subtract off what we didn't want from 'from' and add
+ * on what we didn't count from 'to'.
+ */
+
+ while (TkTextIndexCmp(&index,indexToPtr) < 0) {
+ value += TkTextUpdateOneLine(textPtr, index.linePtr,
+ 0, &index, 0);
+ }
+
+ index2 = index;
+
+ /*
+ * Now we need to adjust the count to:
+ * - subtract off the number of display lines between
+ * indexToPtr and index2, since we might have skipped past
+ * indexToPtr, if we have several logical lines in a
+ * single display line
+ * - subtract off the number of display lines overcounted
+ * in the first logical line
+ * - add on the number of display lines in the last logical
+ * line
+ * This logic is still ok if both indexFromPtr and indexToPtr
+ * are in the same logical line.
+ */
+
+ index = *indexToPtr;
+ index.byteIndex = 0;
+ while (TkTextIndexCmp(&index,&index2) < 0) {
+ value -= TkTextUpdateOneLine(textPtr, index.linePtr,
+ 0, &index, 0);
+ }
+ index.linePtr = indexFromPtr->linePtr;
+ index.byteIndex = 0;
+ while (1) {
+ TkTextFindDisplayLineEnd(textPtr, &index, 1, NULL);
+ if (TkTextIndexCmp(&index,indexFromPtr) >= 0) {
+ break;
+ }
+ TkTextIndexForwBytes(textPtr, &index, 1, &index);
+ value--;
+
+ }
+ if (indexToPtr->linePtr != lastPtr) {
+ index.linePtr = indexToPtr->linePtr;
+ index.byteIndex = 0;
+ while (1) {
+ TkTextFindDisplayLineEnd(textPtr, &index, 1, NULL);
+ if (TkTextIndexCmp(&index,indexToPtr) >= 0) {
+ break;
+ }
+ TkTextIndexForwBytes(textPtr, &index, 1, &index);
+ value++;
+ }
+ }
+
+ if (compare > 0) {
+ value = -value;
+ }
+ } else if (c == 'i'
+ && !strncmp("-indices", option, length)) {
+ value = CountIndices(textPtr, indexFromPtr, indexToPtr,
+ COUNT_INDICES);
+ } else if (c == 'l'
+ && !strncmp("-lines", option, length)) {
+ value = TkBTreeLinesTo(textPtr, indexToPtr->linePtr)
+ - TkBTreeLinesTo(textPtr, indexFromPtr->linePtr);
+ } else if (c == 'u'
+ && !strncmp("-update", option, length)) {
+ update = 1;
+ continue;
+ } else if (c == 'x'
+ && !strncmp("-xpixels", option, length)) {
+ int x1, x2;
+ TkTextIndex index;
+
+ index = *indexFromPtr;
+ TkTextFindDisplayLineEnd(textPtr, &index, 0, &x1);
+ index = *indexToPtr;
+ TkTextFindDisplayLineEnd(textPtr, &index, 0, &x2);
+ value = x2 - x1;
+ } else if (c == 'y'
+ && !strncmp("-ypixels", option, length)) {
+ if (update) {
+ TkTextUpdateLineMetrics(textPtr,
+ TkBTreeLinesTo(textPtr, indexFromPtr->linePtr),
+ TkBTreeLinesTo(textPtr, indexToPtr->linePtr), -1);
+ }
+ value = TkTextIndexYPixels(textPtr, indexToPtr)
+ - TkTextIndexYPixels(textPtr, indexFromPtr);
+ } else {
+ goto badOption;
+ }
+
+ countDone:
+ found++;
+ if (found == 1) {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(value));
+ } else {
+ if (found == 2) {
+ /*
+ * Move the first item we put into the result into the
+ * first element of the list object.
+ */
+
+ objPtr = Tcl_NewObj();
+ Tcl_ListObjAppendElement(NULL, objPtr,
+ Tcl_GetObjResult(interp));
+ }
+ Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewIntObj(value));
+ }
+ }
+
+ if (found == 0) {
+ /*
+ * Use the default '-indices'.
+ */
+
+ int value = CountIndices(textPtr, indexFromPtr, indexToPtr,
+ COUNT_INDICES);
+
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(value));
+ } else if (found > 1) {
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ break;
+
+ badOption:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad option \"%s\" must be -chars, -displaychars, "
+ "-displayindices, -displaylines, -indices, -lines, -update, "
+ "-xpixels, or -ypixels", Tcl_GetString(objv[i])));
+ Tcl_SetErrorCode(interp, "TK", "TEXT", "INDEX_OPTION", NULL);
+ result = TCL_ERROR;
+ goto done;
+ }
+ case TEXT_DEBUG:
+ if (objc > 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "boolean");
+ result = TCL_ERROR;
+ goto done;
+ }
+ if (objc == 2) {
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(tkBTreeDebug));
+ } else {
+ if (Tcl_GetBooleanFromObj(interp, objv[2],
+ &tkBTreeDebug) != TCL_OK) {
+ result = TCL_ERROR;
+ goto done;
+ }
+ tkTextDebug = tkBTreeDebug;
+ }
+ break;
+ case TEXT_DELETE:
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index1 ?index2 ...?");
+ result = TCL_ERROR;
+ goto done;
+ }
+ if (textPtr->state == TK_TEXT_STATE_NORMAL) {
+ if (objc < 5) {
+ /*
+ * Simple case requires no predetermination of indices.
+ */
+
+ const TkTextIndex *indexPtr1, *indexPtr2;
+
+ /*
+ * Parse the starting and stopping indices.
+ */
+
+ indexPtr1 = TkTextGetIndexFromObj(textPtr->interp, textPtr,
+ objv[2]);
+ if (indexPtr1 == NULL) {
+ result = TCL_ERROR;
+ goto done;
+ }
+ if (objc == 4) {
+ indexPtr2 = TkTextGetIndexFromObj(textPtr->interp,
+ textPtr, objv[3]);
+ if (indexPtr2 == NULL) {
+ result = TCL_ERROR;
+ goto done;
+ }
+ } else {
+ indexPtr2 = NULL;
+ }
+ DeleteIndexRange(NULL, textPtr, indexPtr1, indexPtr2, 1);
+ } else {
+ /*
+ * Multi-index pair case requires that we prevalidate the
+ * indices and sort from last to first so that deletes occur
+ * in the exact (unshifted) text. It also needs to handle
+ * partial and fully overlapping ranges. We have to do this
+ * with multiple passes.
+ */
+
+ TkTextIndex *indices, *ixStart, *ixEnd, *lastStart;
+ char *useIdx;
+ int i;
+
+ objc -= 2;
+ objv += 2;
+ indices = ckalloc((objc + 1) * sizeof(TkTextIndex));
+
+ /*
+ * First pass verifies that all indices are valid.
+ */
+
+ for (i = 0; i < objc; i++) {
+ const TkTextIndex *indexPtr =
+ TkTextGetIndexFromObj(interp, textPtr, objv[i]);
+
+ if (indexPtr == NULL) {
+ result = TCL_ERROR;
+ ckfree(indices);
+ goto done;
+ }
+ indices[i] = *indexPtr;
+ }
+
+ /*
+ * Pad out the pairs evenly to make later code easier.
+ */
+
+ if (objc & 1) {
+ indices[i] = indices[i-1];
+ TkTextIndexForwChars(NULL, &indices[i], 1, &indices[i],
+ COUNT_INDICES);
+ objc++;
+ }
+ useIdx = ckalloc(objc);
+ memset(useIdx, 0, (size_t) objc);
+
+ /*
+ * Do a decreasing order sort so that we delete the end ranges
+ * first to maintain index consistency.
+ */
+
+ qsort(indices, (size_t) objc / 2,
+ 2 * sizeof(TkTextIndex), TextIndexSortProc);
+ lastStart = NULL;
+
+ /*
+ * Second pass will handle bogus ranges (end < start) and
+ * overlapping ranges.
+ */
+
+ for (i = 0; i < objc; i += 2) {
+ ixStart = &indices[i];
+ ixEnd = &indices[i+1];
+ if (TkTextIndexCmp(ixEnd, ixStart) <= 0) {
+ continue;
+ }
+ if (lastStart) {
+ if (TkTextIndexCmp(ixStart, lastStart) == 0) {
+ /*
+ * Start indices were equal, and the sort placed
+ * the longest range first, so skip this one.
+ */
+
+ continue;
+ } else if (TkTextIndexCmp(lastStart, ixEnd) < 0) {
+ /*
+ * The next pair has a start range before the end
+ * point of the last range. Constrain the delete
+ * range, but use the pointer values.
+ */
+
+ *ixEnd = *lastStart;
+ if (TkTextIndexCmp(ixEnd, ixStart) <= 0) {
+ continue;
+ }
+ }
+ }
+ lastStart = ixStart;
+ useIdx[i] = 1;
+ }
+
+ /*
+ * Final pass take the input from the previous and deletes the
+ * ranges which are flagged to be deleted.
+ */
+
+ for (i = 0; i < objc; i += 2) {
+ if (useIdx[i]) {
+ /*
+ * We don't need to check the return value because all
+ * indices are preparsed above.
+ */
+
+ DeleteIndexRange(NULL, textPtr, &indices[i],
+ &indices[i+1], 1);
+ }
+ }
+ ckfree(indices);
+ }
+ }
+ break;
+ case TEXT_DLINEINFO: {
+ int x, y, width, height, base;
+ const TkTextIndex *indexPtr;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index");
+ result = TCL_ERROR;
+ goto done;
+ }
+ indexPtr = TkTextGetIndexFromObj(interp, textPtr, objv[2]);
+ if (indexPtr == NULL) {
+ result = TCL_ERROR;
+ goto done;
+ }
+ if (TkTextDLineInfo(textPtr, indexPtr, &x, &y, &width, &height,
+ &base) == 0) {
+ Tcl_Obj *listObj = Tcl_NewListObj(0, NULL);
+
+ Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(x));
+ Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(y));
+ Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(width));
+ Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(height));
+ Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(base));
+
+ Tcl_SetObjResult(interp, listObj);
+ }
+ break;
+ }
+ case TEXT_DUMP:
+ result = TextDumpCmd(textPtr, interp, objc, objv);
+ break;
+ case TEXT_EDIT:
+ result = TextEditCmd(textPtr, interp, objc, objv);
+ break;
+ case TEXT_GET: {
+ Tcl_Obj *objPtr = NULL;
+ int i, found = 0, visible = 0;
+ const char *name;
+ size_t length;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-displaychars? ?--? index1 ?index2 ...?");
+ result = TCL_ERROR;
+ goto done;
+ }
+
+ /*
+ * Simple, restrictive argument parsing. The only options are -- and
+ * -displaychars (or any unique prefix).
+ */
+
+ i = 2;
+ if (objc > 3) {
+ name = Tcl_GetString(objv[i]);
+ length = objv[i]->length;
+ if (length > 1 && name[0] == '-') {
+ if (strncmp("-displaychars", name, length) == 0) {
+ i++;
+ visible = 1;
+ name = Tcl_GetString(objv[i]);
+ length = objv[i]->length;
+ }
+ if ((i < objc-1) && (length == 2) && !strcmp("--", name)) {
+ i++;
+ }
+ }
+ }
+
+ for (; i < objc; i += 2) {
+ const TkTextIndex *index1Ptr, *index2Ptr;
+ TkTextIndex index2;
+
+ index1Ptr = TkTextGetIndexFromObj(interp, textPtr, objv[i]);
+ if (index1Ptr == NULL) {
+ if (objPtr) {
+ Tcl_DecrRefCount(objPtr);
+ }
+ result = TCL_ERROR;
+ goto done;
+ }
+
+ if (i+1 == objc) {
+ TkTextIndexForwChars(NULL, index1Ptr, 1, &index2,
+ COUNT_INDICES);
+ index2Ptr = &index2;
+ } else {
+ index2Ptr = TkTextGetIndexFromObj(interp, textPtr, objv[i+1]);
+ if (index2Ptr == NULL) {
+ if (objPtr) {
+ Tcl_DecrRefCount(objPtr);
+ }
+ result = TCL_ERROR;
+ goto done;
+ }
+ }
+
+ if (TkTextIndexCmp(index1Ptr, index2Ptr) < 0) {
+ /*
+ * We want to move the text we get from the window into the
+ * result, but since this could in principle be a megabyte or
+ * more, we want to do it efficiently!
+ */
+
+ Tcl_Obj *get = TextGetText(textPtr, index1Ptr, index2Ptr,
+ visible);
+
+ found++;
+ if (found == 1) {
+ Tcl_SetObjResult(interp, get);
+ } else {
+ if (found == 2) {
+ /*
+ * Move the first item we put into the result into the
+ * first element of the list object.
+ */
+
+ objPtr = Tcl_NewObj();
+ Tcl_ListObjAppendElement(NULL, objPtr,
+ Tcl_GetObjResult(interp));
+ }
+ Tcl_ListObjAppendElement(NULL, objPtr, get);
+ }
+ }
+ }
+ if (found > 1) {
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ break;
+ }
+ case TEXT_IMAGE:
+ result = TkTextImageCmd(textPtr, interp, objc, objv);
+ break;
+ case TEXT_INDEX: {
+ const TkTextIndex *indexPtr;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index");
+ result = TCL_ERROR;
+ goto done;
+ }
+
+ indexPtr = TkTextGetIndexFromObj(interp, textPtr, objv[2]);
+ if (indexPtr == NULL) {
+ result = TCL_ERROR;
+ goto done;
+ }
+ Tcl_SetObjResult(interp, TkTextNewIndexObj(textPtr, indexPtr));
+ break;
+ }
+ case TEXT_INSERT: {
+ const TkTextIndex *indexPtr;
+
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "index chars ?tagList chars tagList ...?");
+ result = TCL_ERROR;
+ goto done;
+ }
+ indexPtr = TkTextGetIndexFromObj(interp, textPtr, objv[2]);
+ if (indexPtr == NULL) {
+ result = TCL_ERROR;
+ goto done;
+ }
+ if (textPtr->state == TK_TEXT_STATE_NORMAL) {
+ result = TextInsertCmd(NULL, textPtr, interp, objc-3, objv+3,
+ indexPtr, 1);
+ }
+ break;
+ }
+ case TEXT_MARK:
+ result = TkTextMarkCmd(textPtr, interp, objc, objv);
+ break;
+ case TEXT_PEER:
+ result = TextPeerCmd(textPtr, interp, objc, objv);
+ break;
+ case TEXT_PENDINGSYNC: {
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ result = TCL_ERROR;
+ goto done;
+ }
+ Tcl_SetObjResult(interp,
+ Tcl_NewBooleanObj(TkTextPendingsync(textPtr)));
+ break;
+ }
+ case TEXT_REPLACE: {
+ const TkTextIndex *indexFromPtr, *indexToPtr;
+
+ if (objc < 5) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "index1 index2 chars ?tagList chars tagList ...?");
+ result = TCL_ERROR;
+ goto done;
+ }
+ indexFromPtr = TkTextGetIndexFromObj(interp, textPtr, objv[2]);
+ if (indexFromPtr == NULL) {
+ result = TCL_ERROR;
+ goto done;
+ }
+ indexToPtr = TkTextGetIndexFromObj(interp, textPtr, objv[3]);
+ if (indexToPtr == NULL) {
+ result = TCL_ERROR;
+ goto done;
+ }
+ if (TkTextIndexCmp(indexFromPtr, indexToPtr) > 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "index \"%s\" before \"%s\" in the text",
+ Tcl_GetString(objv[3]), Tcl_GetString(objv[2])));
+ Tcl_SetErrorCode(interp, "TK", "TEXT", "INDEX_ORDER", NULL);
+ result = TCL_ERROR;
+ goto done;
+ }
+ if (textPtr->state == TK_TEXT_STATE_NORMAL) {
+ int lineNum, byteIndex;
+ TkTextIndex index;
+
+ /*
+ * The 'replace' operation is quite complex to do correctly,
+ * because we want a number of criteria to hold:
+ *
+ * 1. The insertion point shouldn't move, unless it is within the
+ * deleted range. In this case it should end up after the new
+ * text.
+ *
+ * 2. The window should not change the text it shows - should not
+ * scroll vertically - unless the result of the replace is
+ * that the insertion position which used to be on-screen is
+ * now off-screen.
+ */
+
+ byteIndex = textPtr->topIndex.byteIndex;
+ lineNum = TkBTreeLinesTo(textPtr, textPtr->topIndex.linePtr);
+
+ TkTextMarkSegToIndex(textPtr, textPtr->insertMarkPtr, &index);
+ if ((TkTextIndexCmp(indexFromPtr, &index) < 0)
+ && (TkTextIndexCmp(indexToPtr, &index) > 0)) {
+ /*
+ * The insertion point is inside the range to be replaced, so
+ * we have to do some calculations to ensure it doesn't move
+ * unnecessarily.
+ */
+
+ int deleteInsertOffset, insertLength, j, indexFromLine, indexFromByteOffset;
+
+ insertLength = 0;
+ for (j = 4; j < objc; j += 2) {
+ insertLength += Tcl_GetCharLength(objv[j]);
+ }
+
+ /*
+ * Calculate 'deleteInsertOffset' as an offset we will apply
+ * to the insertion point after this operation.
+ */
+
+ deleteInsertOffset = CountIndices(textPtr, indexFromPtr,
+ &index, COUNT_CHARS);
+ if (deleteInsertOffset > insertLength) {
+ deleteInsertOffset = insertLength;
+ }
+
+ indexFromLine = TkBTreeLinesTo(textPtr, indexFromPtr->linePtr);
+ indexFromByteOffset = indexFromPtr->byteIndex;
+
+ result = TextReplaceCmd(textPtr, interp, indexFromPtr,
+ indexToPtr, objc, objv, 0);
+
+ if (result == TCL_OK) {
+ /*
+ * Move the insertion position to the correct place.
+ */
+
+ TkTextIndex indexTmp;
+
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, indexFromLine,
+ indexFromByteOffset, &indexTmp);
+ TkTextIndexForwChars(NULL, &indexTmp,
+ deleteInsertOffset, &index, COUNT_INDICES);
+ TkBTreeUnlinkSegment(textPtr->insertMarkPtr,
+ textPtr->insertMarkPtr->body.mark.linePtr);
+ TkBTreeLinkSegment(textPtr->insertMarkPtr, &index);
+ }
+ } else {
+ result = TextReplaceCmd(textPtr, interp, indexFromPtr,
+ indexToPtr, objc, objv, 1);
+ }
+ if (result == TCL_OK) {
+ /*
+ * Now ensure the top-line is in the right place.
+ */
+
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,
+ lineNum, byteIndex, &index);
+ TkTextSetYView(textPtr, &index, TK_TEXT_NOPIXELADJUST);
+ }
+ }
+ break;
+ }
+ case TEXT_SCAN:
+ result = TkTextScanCmd(textPtr, interp, objc, objv);
+ break;
+ case TEXT_SEARCH:
+ result = TextSearchCmd(textPtr, interp, objc, objv);
+ break;
+ case TEXT_SEE:
+ result = TkTextSeeCmd(textPtr, interp, objc, objv);
+ break;
+ case TEXT_SYNC: {
+ if (objc == 4) {
+ Tcl_Obj *cmd = objv[3];
+ const char *option = Tcl_GetString(objv[2]);
+ if (strncmp(option, "-command", objv[2]->length)) {
+ Tcl_AppendResult(interp, "wrong option \"", option, "\": should be \"-command\"", NULL);
+ result = TCL_ERROR;
+ goto done;
+ }
+ Tcl_IncrRefCount(cmd);
+ if (TkTextPendingsync(textPtr)) {
+ if (textPtr->afterSyncCmd) {
+ Tcl_DecrRefCount(textPtr->afterSyncCmd);
+ }
+ textPtr->afterSyncCmd = cmd;
+ } else {
+ textPtr->afterSyncCmd = cmd;
+ Tcl_DoWhenIdle(TkTextRunAfterSyncCmd, (ClientData) textPtr);
+ }
+ break;
+ } else if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?-command command?");
+ result = TCL_ERROR;
+ goto done;
+ }
+ if (textPtr->afterSyncCmd) {
+ Tcl_DecrRefCount(textPtr->afterSyncCmd);
+ }
+ textPtr->afterSyncCmd = NULL;
+ TkTextUpdateLineMetrics(textPtr, 0,
+ TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr), -1);
+ break;
+ }
+ case TEXT_TAG:
+ result = TkTextTagCmd(textPtr, interp, objc, objv);
+ break;
+ case TEXT_WINDOW:
+ result = TkTextWindowCmd(textPtr, interp, objc, objv);
+ break;
+ case TEXT_XVIEW:
+ result = TkTextXviewCmd(textPtr, interp, objc, objv);
+ break;
+ case TEXT_YVIEW:
+ result = TkTextYviewCmd(textPtr, interp, objc, objv);
+ break;
+ }
+
+ done:
+ if (textPtr->refCount-- <= 1) {
+ ckfree(textPtr);
+ }
+ return result;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * SharedTextObjCmd --
+ *
+ * This function is invoked to process commands on the shared portion of
+ * a text widget. Currently it is not actually exported as a Tcl command,
+ * and is only used internally to process parts of undo/redo scripts.
+ * See the user documentation for 'text' for details on what it does -
+ * the only subcommands it currently supports are 'insert' and 'delete'.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation for "text".
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+SharedTextObjCmd(
+ ClientData clientData, /* Information about shared test B-tree. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ register TkSharedText *sharedPtr = clientData;
+ int result = TCL_OK;
+ int index;
+
+ static const char *const optionStrings[] = {
+ "delete", "insert", NULL
+ };
+ enum options {
+ TEXT_DELETE, TEXT_INSERT
+ };
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings,
+ sizeof(char *), "option", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch ((enum options) index) {
+ case TEXT_DELETE:
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index1 ?index2 ...?");
+ return TCL_ERROR;
+ }
+ if (objc < 5) {
+ /*
+ * Simple case requires no predetermination of indices.
+ */
+
+ TkTextIndex index1;
+
+ /*
+ * Parse the starting and stopping indices.
+ */
+
+ result = TkTextSharedGetObjIndex(interp, sharedPtr, objv[2],
+ &index1);
+ if (result != TCL_OK) {
+ return result;
+ }
+ if (objc == 4) {
+ TkTextIndex index2;
+
+ result = TkTextSharedGetObjIndex(interp, sharedPtr, objv[3],
+ &index2);
+ if (result != TCL_OK) {
+ return result;
+ }
+ DeleteIndexRange(sharedPtr, NULL, &index1, &index2, 1);
+ } else {
+ DeleteIndexRange(sharedPtr, NULL, &index1, NULL, 1);
+ }
+ return TCL_OK;
+ } else {
+ /* Too many arguments */
+ return TCL_ERROR;
+ }
+ break;
+ case TEXT_INSERT: {
+ TkTextIndex index1;
+
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "index chars ?tagList chars tagList ...?");
+ return TCL_ERROR;
+ }
+ result = TkTextSharedGetObjIndex(interp, sharedPtr, objv[2],
+ &index1);
+ if (result != TCL_OK) {
+ return result;
+ }
+ return TextInsertCmd(sharedPtr, NULL, interp, objc-3, objv+3, &index1,
+ 1);
+ }
+ default:
+ return TCL_OK;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TextPeerCmd --
+ *
+ * This function is invoked to process the "text peer" 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
+TextPeerCmd(
+ TkText *textPtr, /* Information about text widget. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Tk_Window tkwin = textPtr->tkwin;
+ int index;
+
+ static const char *const peerOptionStrings[] = {
+ "create", "names", NULL
+ };
+ enum peerOptions {
+ PEER_CREATE, PEER_NAMES
+ };
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[2], peerOptionStrings,
+ sizeof(char *), "peer option", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch ((enum peerOptions) index) {
+ case PEER_CREATE:
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "pathName ?-option value ...?");
+ return TCL_ERROR;
+ }
+ return CreateWidget(textPtr->sharedTextPtr, tkwin, interp, textPtr,
+ objc-2, objv+2);
+ case PEER_NAMES: {
+ TkText *tPtr = textPtr->sharedTextPtr->peers;
+ Tcl_Obj *peersObj;
+
+ if (objc > 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ return TCL_ERROR;
+ }
+ peersObj = Tcl_NewObj();
+ while (tPtr != NULL) {
+ if (tPtr != textPtr) {
+ Tcl_ListObjAppendElement(NULL, peersObj,
+ TkNewWindowObj(tPtr->tkwin));
+ }
+ tPtr = tPtr->next;
+ }
+ Tcl_SetObjResult(interp, peersObj);
+ }
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TextReplaceCmd --
+ *
+ * This function is invoked to process part of the "replace" widget
+ * command for text widgets.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ * If 'viewUpdate' is false, then textPtr->topIndex may no longer be a
+ * valid index after this function returns. The caller is responsible for
+ * ensuring a correct index is in place.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TextReplaceCmd(
+ TkText *textPtr, /* Information about text widget. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ const TkTextIndex *indexFromPtr,
+ /* Index from which to replace. */
+ const TkTextIndex *indexToPtr,
+ /* Index to which to replace. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[], /* Argument objects. */
+ int viewUpdate) /* Update vertical view if set. */
+{
+ /*
+ * Perform the deletion and insertion, but ensure no undo-separator is
+ * placed between the two operations. Since we are using the helper
+ * functions 'DeleteIndexRange' and 'TextInsertCmd' we have to pretend
+ * that the autoSeparators setting is off, so that we don't get an
+ * undo-separator between the delete and insert.
+ */
+
+ int origAutoSep = textPtr->sharedTextPtr->autoSeparators;
+ int result, lineNumber;
+ TkTextIndex indexTmp;
+
+ if (textPtr->sharedTextPtr->undo) {
+ textPtr->sharedTextPtr->autoSeparators = 0;
+ if (origAutoSep &&
+ textPtr->sharedTextPtr->lastEditMode!=TK_TEXT_EDIT_REPLACE) {
+ TkUndoInsertUndoSeparator(textPtr->sharedTextPtr->undoStack);
+ }
+ }
+
+ /*
+ * Must save and restore line in indexFromPtr based on line number; can't
+ * keep the line itself as that might be eliminated/invalidated when
+ * deleting the range. [Bug 1602537]
+ */
+
+ indexTmp = *indexFromPtr;
+ lineNumber = TkBTreeLinesTo(textPtr, indexFromPtr->linePtr);
+ DeleteIndexRange(NULL, textPtr, indexFromPtr, indexToPtr, viewUpdate);
+ indexTmp.linePtr = TkBTreeFindLine(indexTmp.tree, textPtr, lineNumber);
+ result = TextInsertCmd(NULL, textPtr, interp, objc-4, objv+4,
+ &indexTmp, viewUpdate);
+
+ if (textPtr->sharedTextPtr->undo) {
+ textPtr->sharedTextPtr->lastEditMode = TK_TEXT_EDIT_REPLACE;
+ textPtr->sharedTextPtr->autoSeparators = origAutoSep;
+ }
+
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TextIndexSortProc --
+ *
+ * This function is called by qsort when sorting an array of indices in
+ * *decreasing* order (last to first).
+ *
+ * Results:
+ * The return value is -1 if the first argument should be before the
+ * second element, 0 if it's equivalent, and 1 if it should be after the
+ * second element.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TextIndexSortProc(
+ const void *first, /* Elements to be compared. */
+ const void *second)
+{
+ TkTextIndex *pair1 = (TkTextIndex *) first;
+ TkTextIndex *pair2 = (TkTextIndex *) second;
+ int cmp = TkTextIndexCmp(&pair1[1], &pair2[1]);
+
+ if (cmp == 0) {
+ /*
+ * If the first indices were equal, we want the second index of the
+ * pair also to be the greater. Use pointer magic to access the second
+ * index pair.
+ */
+
+ cmp = TkTextIndexCmp(&pair1[0], &pair2[0]);
+ }
+ if (cmp > 0) {
+ return -1;
+ } else if (cmp < 0) {
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyText --
+ *
+ * This function is invoked when we receive a destroy event to clean up
+ * the internal structure of a text widget. We will free up most of the
+ * internal structure and delete the associated Tcl command. If there are
+ * no outstanding references to the widget, we also free up the textPtr
+ * itself.
+ *
+ * The widget has already been flagged as deleted.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Either everything or almost everything associated with the text is
+ * freed up.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DestroyText(
+ TkText *textPtr) /* Info about text widget. */
+{
+ Tcl_HashSearch search;
+ Tcl_HashEntry *hPtr;
+ TkTextTag *tagPtr;
+ TkSharedText *sharedTextPtr = textPtr->sharedTextPtr;
+
+ /*
+ * Free up all the stuff that requires special handling. We have already
+ * called let Tk_FreeConfigOptions to handle all the standard
+ * option-related stuff (and so none of that exists when we are called).
+ * Special note: free up display-related information before deleting the
+ * B-tree, since display-related stuff may refer to stuff in the B-tree.
+ */
+
+ TkTextFreeDInfo(textPtr);
+ textPtr->dInfoPtr = NULL;
+
+ /*
+ * Remove ourselves from the peer list.
+ */
+
+ if (sharedTextPtr->peers == textPtr) {
+ sharedTextPtr->peers = textPtr->next;
+ } else {
+ TkText *nextPtr = sharedTextPtr->peers;
+ while (nextPtr != NULL) {
+ if (nextPtr->next == textPtr) {
+ nextPtr->next = textPtr->next;
+ break;
+ }
+ nextPtr = nextPtr->next;
+ }
+ }
+
+ /*
+ * Always clean up the widget-specific tags first. Common tags (i.e. most)
+ * will only be cleaned up when the shared structure is cleaned up.
+ *
+ * We also need to clean up widget-specific marks ('insert', 'current'),
+ * since otherwise marks will never disappear from the B-tree.
+ */
+
+ TkTextDeleteTag(textPtr, textPtr->selTagPtr);
+ TkBTreeUnlinkSegment(textPtr->insertMarkPtr,
+ textPtr->insertMarkPtr->body.mark.linePtr);
+ ckfree(textPtr->insertMarkPtr);
+ TkBTreeUnlinkSegment(textPtr->currentMarkPtr,
+ textPtr->currentMarkPtr->body.mark.linePtr);
+ ckfree(textPtr->currentMarkPtr);
+
+ /*
+ * Now we've cleaned up everything of relevance to us in the B-tree, so we
+ * disassociate outselves from it.
+ *
+ * When the refCount reaches zero, it's time to clean up the shared
+ * portion of the text widget.
+ */
+
+ if (sharedTextPtr->refCount-- > 1) {
+ TkBTreeRemoveClient(sharedTextPtr->tree, textPtr);
+
+ /*
+ * Free up any embedded windows which belong to this widget.
+ */
+
+ for (hPtr = Tcl_FirstHashEntry(&sharedTextPtr->windowTable, &search);
+ hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
+ TkTextEmbWindowClient *loop;
+ TkTextSegment *ewPtr = Tcl_GetHashValue(hPtr);
+
+ loop = ewPtr->body.ew.clients;
+ if (loop->textPtr == textPtr) {
+ ewPtr->body.ew.clients = loop->next;
+ TkTextWinFreeClient(hPtr, loop);
+ } else {
+ TkTextEmbWindowClient *client = ewPtr->body.ew.clients;
+
+ client = loop->next;
+ while (client != NULL) {
+ if (client->textPtr == textPtr) {
+ loop->next = client->next;
+ TkTextWinFreeClient(hPtr, client);
+ break;
+ } else {
+ loop = loop->next;
+ }
+ client = loop->next;
+ }
+ }
+ }
+ } else {
+ /*
+ * No need to call 'TkBTreeRemoveClient' first, since this will do
+ * everything in one go, more quickly.
+ */
+
+ TkBTreeDestroy(sharedTextPtr->tree);
+
+ for (hPtr = Tcl_FirstHashEntry(&sharedTextPtr->tagTable, &search);
+ hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
+ tagPtr = Tcl_GetHashValue(hPtr);
+
+ /*
+ * No need to use 'TkTextDeleteTag' since we've already removed
+ * the B-tree completely.
+ */
+
+ TkTextFreeTag(textPtr, tagPtr);
+ }
+ Tcl_DeleteHashTable(&sharedTextPtr->tagTable);
+ for (hPtr = Tcl_FirstHashEntry(&sharedTextPtr->markTable, &search);
+ hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
+ ckfree(Tcl_GetHashValue(hPtr));
+ }
+ Tcl_DeleteHashTable(&sharedTextPtr->markTable);
+ TkUndoFreeStack(sharedTextPtr->undoStack);
+
+ Tcl_DeleteHashTable(&sharedTextPtr->windowTable);
+ Tcl_DeleteHashTable(&sharedTextPtr->imageTable);
+
+ if (sharedTextPtr->bindingTable != NULL) {
+ Tk_DeleteBindingTable(sharedTextPtr->bindingTable);
+ }
+ ckfree(sharedTextPtr);
+ }
+
+ if (textPtr->tabArrayPtr != NULL) {
+ ckfree(textPtr->tabArrayPtr);
+ }
+ if (textPtr->insertBlinkHandler != NULL) {
+ Tcl_DeleteTimerHandler(textPtr->insertBlinkHandler);
+ }
+
+ textPtr->tkwin = NULL;
+ Tcl_DeleteCommandFromToken(textPtr->interp, textPtr->widgetCmd);
+ if (textPtr->afterSyncCmd){
+ Tcl_DecrRefCount(textPtr->afterSyncCmd);
+ textPtr->afterSyncCmd = NULL;
+ }
+ if (textPtr->refCount-- <= 1) {
+ ckfree(textPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConfigureText --
+ *
+ * This function is called to process an objv/objc list, plus the Tk
+ * option database, in order to configure (or reconfigure) a text widget.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If TCL_ERROR is returned,
+ * then the interp's result contains an error message.
+ *
+ * Side effects:
+ * Configuration information, such as text string, colors, font, etc. get
+ * set for textPtr; old resources get freed, if there were any.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ConfigureText(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ register TkText *textPtr, /* Information about widget; may or may not
+ * already have values for some fields. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Tk_SavedOptions savedOptions;
+ int oldExport = (textPtr->exportSelection) && (!Tcl_IsSafe(textPtr->interp));
+ int mask = 0;
+
+ if (Tk_SetOptions(interp, (char *) textPtr, textPtr->optionTable,
+ objc, objv, textPtr->tkwin, &savedOptions, &mask) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Copy down shared flags.
+ */
+
+ textPtr->sharedTextPtr->undo = textPtr->undo;
+ textPtr->sharedTextPtr->maxUndo = textPtr->maxUndo;
+ textPtr->sharedTextPtr->autoSeparators = textPtr->autoSeparators;
+
+ TkUndoSetMaxDepth(textPtr->sharedTextPtr->undoStack,
+ textPtr->sharedTextPtr->maxUndo);
+
+ /*
+ * A few other options also need special processing, such as parsing the
+ * geometry and setting the background from a 3-D border.
+ */
+
+ Tk_SetBackgroundFromBorder(textPtr->tkwin, textPtr->border);
+
+ if (mask & TK_TEXT_LINE_RANGE) {
+ int start, end, current;
+ TkTextIndex index1, index2, index3;
+
+ /*
+ * Line start and/or end have been adjusted. We need to validate the
+ * first displayed line and arrange for re-layout.
+ */
+
+ TkBTreeClientRangeChanged(textPtr, textPtr->charHeight);
+
+ if (textPtr->start != NULL) {
+ start = TkBTreeLinesTo(NULL, textPtr->start);
+ } else {
+ start = 0;
+ }
+ if (textPtr->end != NULL) {
+ end = TkBTreeLinesTo(NULL, textPtr->end);
+ } else {
+ end = TkBTreeNumLines(textPtr->sharedTextPtr->tree, NULL);
+ }
+ if (start > end) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "-startline must be less than or equal to -endline", -1));
+ Tcl_SetErrorCode(interp, "TK", "TEXT", "INDEX_ORDER", NULL);
+ Tk_RestoreSavedOptions(&savedOptions);
+ return TCL_ERROR;
+ }
+ current = TkBTreeLinesTo(NULL, textPtr->topIndex.linePtr);
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, NULL, start, 0,
+ &index1);
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, NULL, end, 0,
+ &index2);
+ if (current < start || current > end) {
+ TkTextSearch search;
+ TkTextIndex first, last;
+ int selChanged = 0;
+
+ TkTextSetYView(textPtr, &index1, 0);
+
+ /*
+ * We may need to adjust the selection. So we have to check
+ * whether the "sel" tag was applied to anything outside the
+ * current start,end.
+ */
+
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, NULL, 0, 0,
+ &first);
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, NULL,
+ TkBTreeNumLines(textPtr->sharedTextPtr->tree, NULL),
+ 0, &last);
+ TkBTreeStartSearch(&first, &last, textPtr->selTagPtr, &search);
+ if (!TkBTreeCharTagged(&first, textPtr->selTagPtr)
+ && !TkBTreeNextTag(&search)) {
+ /* Nothing tagged with "sel" */
+ } else {
+ int line = TkBTreeLinesTo(NULL, search.curIndex.linePtr);
+
+ if (line < start) {
+ selChanged = 1;
+ } else {
+ TkTextLine *linePtr = search.curIndex.linePtr;
+
+ while (TkBTreeNextTag(&search)) {
+ linePtr = search.curIndex.linePtr;
+ }
+ line = TkBTreeLinesTo(NULL, linePtr);
+ if (line >= end) {
+ selChanged = 1;
+ }
+ }
+ }
+ if (selChanged) {
+ /*
+ * Send an event that the selection has changed, and abort any
+ * partial-selections in progress.
+ */
+
+ TkTextSelectionEvent(textPtr);
+ textPtr->abortSelections = 1;
+ }
+ }
+
+ /* Indices are potentially obsolete after changing -startline and/or
+ * -endline, therefore increase the epoch.
+ * Also, clamp the insert and current (unshared) marks to the new
+ * -startline/-endline range limits of the widget. All other (shared)
+ * marks are unchanged.
+ * The return value of TkTextMarkNameToIndex does not need to be
+ * checked: "insert" and "current" marks always exist, and the
+ * purpose of the code below precisely is to move them inside the
+ * -startline/-endline range.
+ */
+
+ textPtr->sharedTextPtr->stateEpoch++;
+ TkTextMarkNameToIndex(textPtr, "insert", &index3);
+ if (TkTextIndexCmp(&index3, &index1) < 0) {
+ textPtr->insertMarkPtr = TkTextSetMark(textPtr, "insert", &index1);
+ }
+ if (TkTextIndexCmp(&index3, &index2) > 0) {
+ textPtr->insertMarkPtr = TkTextSetMark(textPtr, "insert", &index2);
+ }
+ TkTextMarkNameToIndex(textPtr, "current", &index3);
+ if (TkTextIndexCmp(&index3, &index1) < 0) {
+ textPtr->currentMarkPtr = TkTextSetMark(textPtr, "current", &index1);
+ }
+ if (TkTextIndexCmp(&index3, &index2) > 0) {
+ textPtr->currentMarkPtr = TkTextSetMark(textPtr, "current", &index2);
+ }
+ }
+
+ /*
+ * Don't allow negative spacings.
+ */
+
+ if (textPtr->spacing1 < 0) {
+ textPtr->spacing1 = 0;
+ }
+ if (textPtr->spacing2 < 0) {
+ textPtr->spacing2 = 0;
+ }
+ if (textPtr->spacing3 < 0) {
+ textPtr->spacing3 = 0;
+ }
+
+ /*
+ * Parse tab stops.
+ */
+
+ if (textPtr->tabArrayPtr != NULL) {
+ ckfree(textPtr->tabArrayPtr);
+ textPtr->tabArrayPtr = NULL;
+ }
+ if (textPtr->tabOptionPtr != NULL) {
+ textPtr->tabArrayPtr = TkTextGetTabs(interp, textPtr,
+ textPtr->tabOptionPtr);
+ if (textPtr->tabArrayPtr == NULL) {
+ Tcl_AddErrorInfo(interp,"\n (while processing -tabs option)");
+ Tk_RestoreSavedOptions(&savedOptions);
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * Make sure that configuration options are properly mirrored between the
+ * widget record and the "sel" tags. NOTE: we don't have to free up
+ * information during the mirroring; old information was freed when it was
+ * replaced in the widget record.
+ */
+
+ if (textPtr->selTagPtr->selBorder == NULL) {
+ textPtr->selTagPtr->border = textPtr->selBorder;
+ } else {
+ textPtr->selTagPtr->selBorder = textPtr->selBorder;
+ }
+ if (textPtr->selTagPtr->borderWidthPtr != textPtr->selBorderWidthPtr) {
+ textPtr->selTagPtr->borderWidthPtr = textPtr->selBorderWidthPtr;
+ textPtr->selTagPtr->borderWidth = textPtr->selBorderWidth;
+ }
+ if (textPtr->selTagPtr->selFgColor == NULL) {
+ textPtr->selTagPtr->fgColor = textPtr->selFgColorPtr;
+ } else {
+ textPtr->selTagPtr->selFgColor = textPtr->selFgColorPtr;
+ }
+ textPtr->selTagPtr->affectsDisplay = 0;
+ textPtr->selTagPtr->affectsDisplayGeometry = 0;
+ if ((textPtr->selTagPtr->elideString != NULL)
+ || (textPtr->selTagPtr->tkfont != NULL)
+ || (textPtr->selTagPtr->justifyString != NULL)
+ || (textPtr->selTagPtr->lMargin1String != NULL)
+ || (textPtr->selTagPtr->lMargin2String != NULL)
+ || (textPtr->selTagPtr->offsetString != NULL)
+ || (textPtr->selTagPtr->rMarginString != NULL)
+ || (textPtr->selTagPtr->spacing1String != NULL)
+ || (textPtr->selTagPtr->spacing2String != NULL)
+ || (textPtr->selTagPtr->spacing3String != NULL)
+ || (textPtr->selTagPtr->tabStringPtr != NULL)
+ || (textPtr->selTagPtr->wrapMode != TEXT_WRAPMODE_NULL)) {
+ textPtr->selTagPtr->affectsDisplay = 1;
+ textPtr->selTagPtr->affectsDisplayGeometry = 1;
+ }
+ if ((textPtr->selTagPtr->border != NULL)
+ || (textPtr->selTagPtr->selBorder != NULL)
+ || (textPtr->selTagPtr->reliefString != NULL)
+ || (textPtr->selTagPtr->bgStipple != None)
+ || (textPtr->selTagPtr->fgColor != NULL)
+ || (textPtr->selTagPtr->selFgColor != NULL)
+ || (textPtr->selTagPtr->fgStipple != None)
+ || (textPtr->selTagPtr->overstrikeString != NULL)
+ || (textPtr->selTagPtr->overstrikeColor != NULL)
+ || (textPtr->selTagPtr->underlineString != NULL)
+ || (textPtr->selTagPtr->underlineColor != NULL)
+ || (textPtr->selTagPtr->lMarginColor != NULL)
+ || (textPtr->selTagPtr->rMarginColor != NULL)) {
+ textPtr->selTagPtr->affectsDisplay = 1;
+ }
+ TkTextRedrawTag(NULL, textPtr, NULL, NULL, textPtr->selTagPtr, 1);
+
+ /*
+ * Claim the selection if we've suddenly started exporting it and there
+ * are tagged characters.
+ */
+
+ if (textPtr->exportSelection && (!oldExport) && (!Tcl_IsSafe(textPtr->interp))) {
+ TkTextSearch search;
+ TkTextIndex first, last;
+
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, 0, 0,
+ &first);
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,
+ TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr),
+ 0, &last);
+ TkBTreeStartSearch(&first, &last, textPtr->selTagPtr, &search);
+ if (TkBTreeCharTagged(&first, textPtr->selTagPtr)
+ || TkBTreeNextTag(&search)) {
+ Tk_OwnSelection(textPtr->tkwin, XA_PRIMARY, TkTextLostSelection,
+ textPtr);
+ textPtr->flags |= GOT_SELECTION;
+ }
+ }
+
+ /*
+ * Account for state changes that would reenable blinking cursor state.
+ */
+
+ if (textPtr->flags & GOT_FOCUS) {
+ Tcl_DeleteTimerHandler(textPtr->insertBlinkHandler);
+ textPtr->insertBlinkHandler = NULL;
+ TextBlinkProc(textPtr);
+ }
+
+ /*
+ * Register the desired geometry for the window, and arrange for the
+ * window to be redisplayed.
+ */
+
+ if (textPtr->width <= 0) {
+ textPtr->width = 1;
+ }
+ if (textPtr->height <= 0) {
+ textPtr->height = 1;
+ }
+ Tk_FreeSavedOptions(&savedOptions);
+ TextWorldChanged(textPtr, mask);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TextWorldChangedCallback --
+ *
+ * This function is called when the world has changed in some way and the
+ * widget needs to recompute all its graphics contexts and determine its
+ * new geometry.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Configures all tags in the Text with a empty objc/objv, for the side
+ * effect of causing all the items to recompute their geometry and to be
+ * redisplayed.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+TextWorldChangedCallback(
+ ClientData instanceData) /* Information about widget. */
+{
+ TkText *textPtr = instanceData;
+
+ TextWorldChanged(textPtr, TK_TEXT_LINE_GEOMETRY);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TextWorldChanged --
+ *
+ * This function is called when the world has changed in some way and the
+ * widget needs to recompute all its graphics contexts and determine its
+ * new geometry.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Configures all tags in the Text with a empty objc/objv, for the side
+ * effect of causing all the items to recompute their geometry and to be
+ * redisplayed.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+TextWorldChanged(
+ TkText *textPtr, /* Information about widget. */
+ int mask) /* OR'd collection of bits showing what has
+ * changed. */
+{
+ Tk_FontMetrics fm;
+ int border;
+ int oldCharHeight = textPtr->charHeight;
+
+ textPtr->charWidth = Tk_TextWidth(textPtr->tkfont, "0", 1);
+ if (textPtr->charWidth <= 0) {
+ textPtr->charWidth = 1;
+ }
+ Tk_GetFontMetrics(textPtr->tkfont, &fm);
+
+ textPtr->charHeight = fm.linespace;
+ if (textPtr->charHeight <= 0) {
+ textPtr->charHeight = 1;
+ }
+ if (textPtr->charHeight != oldCharHeight) {
+ TkBTreeClientRangeChanged(textPtr, textPtr->charHeight);
+ }
+ border = textPtr->borderWidth + textPtr->highlightWidth;
+ Tk_GeometryRequest(textPtr->tkwin,
+ textPtr->width * textPtr->charWidth + 2*textPtr->padX + 2*border,
+ textPtr->height*(fm.linespace+textPtr->spacing1+textPtr->spacing3)
+ + 2*textPtr->padY + 2*border);
+
+ Tk_SetInternalBorderEx(textPtr->tkwin,
+ border + textPtr->padX, border + textPtr->padX,
+ border + textPtr->padY, border + textPtr->padY);
+ if (textPtr->setGrid) {
+ Tk_SetGrid(textPtr->tkwin, textPtr->width, textPtr->height,
+ textPtr->charWidth, textPtr->charHeight);
+ } else {
+ Tk_UnsetGrid(textPtr->tkwin);
+ }
+
+ TkTextRelayoutWindow(textPtr, mask);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TextEventProc --
+ *
+ * This function is invoked by the Tk dispatcher on structure changes to
+ * a text. For texts with 3D borders, this function is also invoked for
+ * exposures.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * When the window gets deleted, internal structures get cleaned up.
+ * When it gets exposed, it is redisplayed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+TextEventProc(
+ ClientData clientData, /* Information about window. */
+ register XEvent *eventPtr) /* Information about event. */
+{
+ register TkText *textPtr = clientData;
+ TkTextIndex index, index2;
+
+ if (eventPtr->type == Expose) {
+ TkTextRedrawRegion(textPtr, eventPtr->xexpose.x,
+ eventPtr->xexpose.y, eventPtr->xexpose.width,
+ eventPtr->xexpose.height);
+ } else if (eventPtr->type == ConfigureNotify) {
+ if ((textPtr->prevWidth != Tk_Width(textPtr->tkwin))
+ || (textPtr->prevHeight != Tk_Height(textPtr->tkwin))) {
+ int mask = 0;
+
+ if (textPtr->prevWidth != Tk_Width(textPtr->tkwin)) {
+ mask = TK_TEXT_LINE_GEOMETRY;
+ }
+ TkTextRelayoutWindow(textPtr, mask);
+ textPtr->prevWidth = Tk_Width(textPtr->tkwin);
+ textPtr->prevHeight = Tk_Height(textPtr->tkwin);
+ }
+ } else if (eventPtr->type == DestroyNotify) {
+ /*
+ * NOTE: we must zero out selBorder, selBorderWidthPtr and
+ * selFgColorPtr: they are duplicates of information in the "sel" tag,
+ * which will be freed up when we delete all tags. Hence we don't want
+ * the automatic config options freeing process to delete them as
+ * well.
+ */
+
+ textPtr->selBorder = NULL;
+ textPtr->selBorderWidthPtr = NULL;
+ textPtr->selBorderWidth = 0;
+ textPtr->selFgColorPtr = NULL;
+ if (textPtr->setGrid) {
+ Tk_UnsetGrid(textPtr->tkwin);
+ textPtr->setGrid = 0;
+ }
+ if (!(textPtr->flags & OPTIONS_FREED)) {
+ Tk_FreeConfigOptions((char *) textPtr, textPtr->optionTable,
+ textPtr->tkwin);
+ textPtr->flags |= OPTIONS_FREED;
+ }
+ textPtr->flags |= DESTROYED;
+
+ /*
+ * Call 'DestroyTest' to handle the deletion for us. The actual
+ * textPtr may still exist after this, if there are some outstanding
+ * references. But we have flagged it as DESTROYED just above, so
+ * nothing will try to make use of it very extensively.
+ */
+
+ DestroyText(textPtr);
+ } else if ((eventPtr->type == FocusIn) || (eventPtr->type == FocusOut)) {
+ if (eventPtr->xfocus.detail == NotifyInferior
+ || eventPtr->xfocus.detail == NotifyAncestor
+ || eventPtr->xfocus.detail == NotifyNonlinear) {
+ Tcl_DeleteTimerHandler(textPtr->insertBlinkHandler);
+ if (eventPtr->type == FocusIn) {
+ textPtr->flags |= GOT_FOCUS | INSERT_ON;
+ if (textPtr->insertOffTime != 0) {
+ textPtr->insertBlinkHandler = Tcl_CreateTimerHandler(
+ textPtr->insertOnTime, TextBlinkProc, textPtr);
+ }
+ } else {
+ textPtr->flags &= ~(GOT_FOCUS | INSERT_ON);
+ textPtr->insertBlinkHandler = NULL;
+ }
+ if (textPtr->inactiveSelBorder != textPtr->selBorder) {
+ TkTextRedrawTag(NULL, textPtr, NULL, NULL, textPtr->selTagPtr,
+ 1);
+ }
+ TkTextMarkSegToIndex(textPtr, textPtr->insertMarkPtr, &index);
+ TkTextIndexForwChars(NULL, &index, 1, &index2, COUNT_INDICES);
+
+ /*
+ * While we wish to redisplay, no heights have changed, so no need
+ * to call TkTextInvalidateLineMetrics.
+ */
+
+ TkTextChanged(NULL, textPtr, &index, &index2);
+ if (textPtr->highlightWidth > 0) {
+ TkTextRedrawRegion(textPtr, 0, 0, textPtr->highlightWidth,
+ textPtr->highlightWidth);
+ }
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TextCmdDeletedProc --
+ *
+ * This function is invoked when a widget command is deleted. If the
+ * widget isn't already in the process of being destroyed, this command
+ * destroys it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The widget is destroyed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+TextCmdDeletedProc(
+ ClientData clientData) /* Pointer to widget record for widget. */
+{
+ TkText *textPtr = clientData;
+ Tk_Window tkwin = textPtr->tkwin;
+
+ /*
+ * This function could be invoked either because the window was destroyed
+ * and the command was then deleted (in which this flag is already set) or
+ * because the command was deleted, and then this function destroys the
+ * widget.
+ */
+
+ if (!(textPtr->flags & DESTROYED)) {
+ if (textPtr->setGrid) {
+ Tk_UnsetGrid(textPtr->tkwin);
+ textPtr->setGrid = 0;
+ }
+ textPtr->flags |= DESTROYED;
+ Tk_DestroyWindow(tkwin);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InsertChars --
+ *
+ * This function implements most of the functionality of the "insert"
+ * widget command.
+ *
+ * Results:
+ * The length of the inserted string.
+ *
+ * Side effects:
+ * The characters in "stringPtr" get added to the text just before the
+ * character indicated by "indexPtr".
+ *
+ * If 'viewUpdate' is true, we may adjust the window contents'
+ * y-position, and scrollbar setting.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+InsertChars(
+ TkSharedText *sharedTextPtr,
+ TkText *textPtr, /* Overall information about text widget. */
+ TkTextIndex *indexPtr, /* Where to insert new characters. May be
+ * modified if the index is not valid for
+ * insertion (e.g. if at "end"). */
+ Tcl_Obj *stringPtr, /* Null-terminated string containing new
+ * information to add to text. */
+ int viewUpdate) /* Update the view if set. */
+{
+ int lineIndex;
+ size_t length;
+ TkText *tPtr;
+ int *lineAndByteIndex;
+ int resetViewCount;
+ int pixels[2*PIXEL_CLIENTS];
+ const char *string = Tcl_GetString(stringPtr);
+
+ length = stringPtr->length;
+ if (sharedTextPtr == NULL) {
+ sharedTextPtr = textPtr->sharedTextPtr;
+ }
+
+ /*
+ * Don't allow insertions on the last (dummy) line of the text. This is
+ * the only place in this function where the indexPtr is modified.
+ */
+
+ lineIndex = TkBTreeLinesTo(textPtr, indexPtr->linePtr);
+ if (lineIndex == TkBTreeNumLines(sharedTextPtr->tree, textPtr)) {
+ lineIndex--;
+ TkTextMakeByteIndex(sharedTextPtr->tree, textPtr, lineIndex, 1000000,
+ indexPtr);
+ }
+
+ /*
+ * Notify the display module that lines are about to change, then do the
+ * insertion. If the insertion occurs on the top line of the widget
+ * (textPtr->topIndex), then we have to recompute topIndex after the
+ * insertion, since the insertion could invalidate it.
+ */
+
+ resetViewCount = 0;
+ if (sharedTextPtr->refCount > PIXEL_CLIENTS) {
+ lineAndByteIndex = ckalloc(sizeof(int) * 2 * sharedTextPtr->refCount);
+ } else {
+ lineAndByteIndex = pixels;
+ }
+ for (tPtr = sharedTextPtr->peers; tPtr != NULL ; tPtr = tPtr->next) {
+ lineAndByteIndex[resetViewCount] = -1;
+ if (indexPtr->linePtr == tPtr->topIndex.linePtr) {
+ lineAndByteIndex[resetViewCount] =
+ TkBTreeLinesTo(tPtr, indexPtr->linePtr);
+ lineAndByteIndex[resetViewCount+1] = tPtr->topIndex.byteIndex;
+ if (lineAndByteIndex[resetViewCount+1] > indexPtr->byteIndex) {
+ lineAndByteIndex[resetViewCount+1] += length;
+ }
+ }
+ resetViewCount += 2;
+ }
+
+ TkTextChanged(sharedTextPtr, NULL, indexPtr, indexPtr);
+
+ sharedTextPtr->stateEpoch++;
+
+ TkBTreeInsertChars(sharedTextPtr->tree, indexPtr, string);
+
+ /*
+ * Push the insertion on the undo stack, and update the modified status of
+ * the widget.
+ */
+
+ if (length > 0) {
+ if (sharedTextPtr->undo) {
+ TkTextIndex toIndex;
+
+ if (sharedTextPtr->autoSeparators &&
+ sharedTextPtr->lastEditMode != TK_TEXT_EDIT_INSERT) {
+ TkUndoInsertUndoSeparator(sharedTextPtr->undoStack);
+ }
+
+ sharedTextPtr->lastEditMode = TK_TEXT_EDIT_INSERT;
+
+ TkTextIndexForwBytes(textPtr, indexPtr, length, &toIndex);
+ TextPushUndoAction(textPtr, stringPtr, 1, indexPtr, &toIndex);
+ }
+
+ UpdateDirtyFlag(sharedTextPtr);
+ }
+
+ resetViewCount = 0;
+ for (tPtr = sharedTextPtr->peers; tPtr != NULL ; tPtr = tPtr->next) {
+ if (lineAndByteIndex[resetViewCount] != -1) {
+ if ((tPtr != textPtr) || viewUpdate) {
+ TkTextIndex newTop;
+
+ TkTextMakeByteIndex(sharedTextPtr->tree, tPtr,
+ lineAndByteIndex[resetViewCount], 0, &newTop);
+ TkTextIndexForwBytes(tPtr, &newTop,
+ lineAndByteIndex[resetViewCount+1], &newTop);
+ TkTextSetYView(tPtr, &newTop, 0);
+ }
+ }
+ resetViewCount += 2;
+ }
+ if (sharedTextPtr->refCount > PIXEL_CLIENTS) {
+ ckfree(lineAndByteIndex);
+ }
+
+ /*
+ * Invalidate any selection retrievals in progress, and send an event
+ * that the selection changed if that is the case.
+ */
+
+ for (tPtr = sharedTextPtr->peers; tPtr != NULL ; tPtr = tPtr->next) {
+ if (TkBTreeCharTagged(indexPtr, tPtr->selTagPtr)) {
+ TkTextSelectionEvent(tPtr);
+ }
+ tPtr->abortSelections = 1;
+ }
+
+ /*
+ * For convenience, return the length of the string.
+ */
+
+ return length;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TextPushUndoAction --
+ *
+ * Shared by insert and delete actions. Stores the appropriate scripts
+ * into our undo stack. We will add a single refCount to the 'undoString'
+ * object, so, if it previously had a refCount of zero, the caller should
+ * not free it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Items pushed onto stack.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+TextPushUndoAction(
+ TkText *textPtr, /* Overall information about text widget. */
+ Tcl_Obj *undoString, /* New text. */
+ int insert, /* 1 if insert, else delete. */
+ const TkTextIndex *index1Ptr,
+ /* Index describing first location. */
+ const TkTextIndex *index2Ptr)
+ /* Index describing second location. */
+{
+ TkUndoSubAtom *iAtom, *dAtom;
+ int canUndo, canRedo;
+
+ /*
+ * Create the helpers.
+ */
+
+ Tcl_Obj *seeInsertObj = Tcl_NewObj();
+ Tcl_Obj *markSet1InsertObj = Tcl_NewObj();
+ Tcl_Obj *markSet2InsertObj = NULL;
+ Tcl_Obj *insertCmdObj = Tcl_NewObj();
+ Tcl_Obj *deleteCmdObj = Tcl_NewObj();
+
+ /*
+ * Get the index positions.
+ */
+
+ Tcl_Obj *index1Obj = TkTextNewIndexObj(NULL, index1Ptr);
+ Tcl_Obj *index2Obj = TkTextNewIndexObj(NULL, index2Ptr);
+
+ /*
+ * These need refCounts, because they are used more than once below.
+ */
+
+ Tcl_IncrRefCount(seeInsertObj);
+ Tcl_IncrRefCount(index1Obj);
+ Tcl_IncrRefCount(index2Obj);
+
+ Tcl_ListObjAppendElement(NULL, seeInsertObj,
+ Tcl_NewStringObj(Tk_PathName(textPtr->tkwin), -1));
+ Tcl_ListObjAppendElement(NULL, seeInsertObj, Tcl_NewStringObj("see", 3));
+ Tcl_ListObjAppendElement(NULL, seeInsertObj,
+ Tcl_NewStringObj("insert", 6));
+
+ Tcl_ListObjAppendElement(NULL, markSet1InsertObj,
+ Tcl_NewStringObj(Tk_PathName(textPtr->tkwin), -1));
+ Tcl_ListObjAppendElement(NULL, markSet1InsertObj,
+ Tcl_NewStringObj("mark", 4));
+ Tcl_ListObjAppendElement(NULL, markSet1InsertObj,
+ Tcl_NewStringObj("set", 3));
+ Tcl_ListObjAppendElement(NULL, markSet1InsertObj,
+ Tcl_NewStringObj("insert", 6));
+ markSet2InsertObj = Tcl_DuplicateObj(markSet1InsertObj);
+ Tcl_ListObjAppendElement(NULL, markSet1InsertObj, index1Obj);
+ Tcl_ListObjAppendElement(NULL, markSet2InsertObj, index2Obj);
+
+ Tcl_ListObjAppendElement(NULL, insertCmdObj,
+ Tcl_NewStringObj("insert", 6));
+ Tcl_ListObjAppendElement(NULL, insertCmdObj, index1Obj);
+
+ /*
+ * Only use of 'undoString' is here.
+ */
+
+ Tcl_ListObjAppendElement(NULL, insertCmdObj, undoString);
+
+ Tcl_ListObjAppendElement(NULL, deleteCmdObj,
+ Tcl_NewStringObj("delete", 6));
+ Tcl_ListObjAppendElement(NULL, deleteCmdObj, index1Obj);
+ Tcl_ListObjAppendElement(NULL, deleteCmdObj, index2Obj);
+
+ /*
+ * Note: we don't wish to use textPtr->widgetCmd in these callbacks
+ * because if we delete the textPtr, but peers still exist, we will then
+ * have references to a non-existent Tcl_Command in the undo stack, which
+ * will lead to crashes later. Also, the behaviour of the widget w.r.t.
+ * bindings (%W substitutions) always uses the widget path name, so there
+ * is no good reason the undo stack should do otherwise.
+ *
+ * For the 'insert' and 'delete' actions, we have to register a functional
+ * callback, because these actions are defined to operate on the
+ * underlying data shared by all peers.
+ */
+
+ iAtom = TkUndoMakeSubAtom(&TextUndoRedoCallback, textPtr->sharedTextPtr,
+ insertCmdObj, NULL);
+ TkUndoMakeCmdSubAtom(NULL, markSet2InsertObj, iAtom);
+ TkUndoMakeCmdSubAtom(NULL, seeInsertObj, iAtom);
+
+ dAtom = TkUndoMakeSubAtom(&TextUndoRedoCallback, textPtr->sharedTextPtr,
+ deleteCmdObj, NULL);
+ TkUndoMakeCmdSubAtom(NULL, markSet1InsertObj, dAtom);
+ TkUndoMakeCmdSubAtom(NULL, seeInsertObj, dAtom);
+
+ Tcl_DecrRefCount(seeInsertObj);
+ Tcl_DecrRefCount(index1Obj);
+ Tcl_DecrRefCount(index2Obj);
+
+ canUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack);
+ canRedo = TkUndoCanRedo(textPtr->sharedTextPtr->undoStack);
+
+ /*
+ * Depending whether the action is to insert or delete, we provide the
+ * appropriate second and third arguments to TkUndoPushAction. (The first
+ * is the 'actionCommand', and the second the 'revertCommand').
+ */
+
+ if (insert) {
+ TkUndoPushAction(textPtr->sharedTextPtr->undoStack, iAtom, dAtom);
+ } else {
+ TkUndoPushAction(textPtr->sharedTextPtr->undoStack, dAtom, iAtom);
+ }
+
+ if (!canUndo || canRedo) {
+ GenerateUndoStackEvent(textPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TextUndoRedoCallback --
+ *
+ * This function is registered with the generic undo/redo code to handle
+ * 'insert' and 'delete' actions on all text widgets. We cannot perform
+ * those actions on any particular text widget, because that text widget
+ * might have been deleted by the time we get here.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * Will insert or delete text, depending on the first word contained in
+ * objPtr.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TextUndoRedoCallback(
+ Tcl_Interp *interp, /* Current interpreter. */
+ ClientData clientData, /* Passed from undo code, but contains our
+ * shared text data structure. */
+ Tcl_Obj *objPtr) /* Arguments of a command to be handled by the
+ * shared text data structure. */
+{
+ TkSharedText *sharedPtr = clientData;
+ int res, objc;
+ Tcl_Obj **objv;
+ TkText *textPtr;
+
+ res = Tcl_ListObjGetElements(interp, objPtr, &objc, &objv);
+ if (res != TCL_OK) {
+ return res;
+ }
+
+ /*
+ * If possible, use a real text widget to perform the undo/redo action
+ * (i.e. insertion or deletion of text). This provides maximum
+ * compatibility with older versions of Tk, in which the user may rename
+ * the text widget to allow capture of undo or redo actions.
+ *
+ * In particular, this sorting of capture is useful in text editors based
+ * on the Tk text widget, which need to know which new text needs
+ * re-coloring.
+ *
+ * It would be better if the text widget provided some other mechanism to
+ * allow capture of this information ("What has just changed in the text
+ * widget?"). What we have here is not entirely satisfactory under all
+ * circumstances.
+ */
+
+ textPtr = sharedPtr->peers;
+ while (textPtr != NULL) {
+ if (textPtr->start == NULL && textPtr->end == NULL) {
+ Tcl_Obj *cmdNameObj, *evalObj;
+
+ evalObj = Tcl_NewObj();
+ Tcl_IncrRefCount(evalObj);
+
+ /*
+ * We might wish to use the real, current command-name for the
+ * widget, but this will break any code that has over-ridden the
+ * widget, and is expecting to observe the insert/delete actions
+ * which are caused by undo/redo operations.
+ *
+ * cmdNameObj = Tcl_NewObj();
+ * Tcl_GetCommandFullName(interp, textPtr->widgetCmd, cmdNameObj);
+ *
+ * While such interception is not explicitly documented as
+ * supported, it does occur, and so until we can provide some
+ * alternative mechanism for such code to do what it needs, we
+ * allow it to take place here.
+ */
+
+ cmdNameObj = Tcl_NewStringObj(Tk_PathName(textPtr->tkwin), -1);
+ Tcl_ListObjAppendElement(NULL, evalObj, cmdNameObj);
+ Tcl_ListObjAppendList(NULL, evalObj, objPtr);
+ res = Tcl_EvalObjEx(interp, evalObj, TCL_EVAL_GLOBAL);
+ Tcl_DecrRefCount(evalObj);
+ return res;
+ }
+ textPtr = textPtr->next;
+ }
+
+ /*
+ * If there's no current text widget which shows everything, then we fall
+ * back on acting directly. This means there is no way to intercept from
+ * the Tcl level.
+ */
+
+ return SharedTextObjCmd(sharedPtr, interp, objc+1, objv-1);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CountIndices --
+ *
+ * This function implements most of the functionality of the "count"
+ * widget command.
+ *
+ * Note that 'textPtr' is only used if we need to check for elided
+ * attributes, i.e. if type is COUNT_DISPLAY_INDICES or
+ * COUNT_DISPLAY_CHARS
+ *
+ * Results:
+ * Returns the number of characters in the range.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CountIndices(
+ const TkText *textPtr, /* Overall information about text widget. */
+ const TkTextIndex *indexPtr1,
+ /* Index describing location of first
+ * character to delete. */
+ const TkTextIndex *indexPtr2,
+ /* Index describing location of last character
+ * to delete. NULL means just delete the one
+ * character given by indexPtr1. */
+ TkTextCountType type) /* The kind of indices to count. */
+{
+ /*
+ * Order the starting and stopping indices.
+ */
+
+ int compare = TkTextIndexCmp(indexPtr1, indexPtr2);
+
+ if (compare == 0) {
+ return 0;
+ } else if (compare > 0) {
+ return -TkTextIndexCount(textPtr, indexPtr2, indexPtr1, type);
+ } else {
+ return TkTextIndexCount(textPtr, indexPtr1, indexPtr2, type);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DeleteIndexRange --
+ *
+ * This function implements most of the functionality of the "delete"
+ * widget command.
+ *
+ * Results:
+ * Returns a standard Tcl result, currently always TCL_OK.
+ *
+ * Side effects:
+ * Characters and other entities (windows, images) get deleted from the
+ * text.
+ *
+ * If 'viewUpdate' is true, we may adjust the window contents'
+ * y-position, and scrollbar setting.
+ *
+ * If 'viewUpdate' is true we can guarantee that textPtr->topIndex
+ * points to a valid TkTextLine after this function returns. However, if
+ * 'viewUpdate' is false, then there is no such guarantee (since
+ * topIndex.linePtr can be garbage). The caller is expected to take
+ * actions to ensure the topIndex is validated before laying out the
+ * window again.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DeleteIndexRange(
+ TkSharedText *sharedTextPtr,/* Shared portion of peer widgets. */
+ TkText *textPtr, /* Overall information about text widget. */
+ const TkTextIndex *indexPtr1,
+ /* Index describing location of first
+ * character (or other entity) to delete. */
+ const TkTextIndex *indexPtr2,
+ /* Index describing location of last
+ * character (or other entity) to delete.
+ * NULL means just delete the one character
+ * given by indexPtr1. */
+ int viewUpdate) /* Update vertical view if set. */
+{
+ int line1, line2;
+ TkTextIndex index1, index2;
+ TkText *tPtr;
+ int *lineAndByteIndex;
+ int resetViewCount;
+ int pixels[2*PIXEL_CLIENTS];
+ Tcl_HashSearch search;
+ Tcl_HashEntry *hPtr;
+ int i;
+
+ if (sharedTextPtr == NULL) {
+ sharedTextPtr = textPtr->sharedTextPtr;
+ }
+
+ /*
+ * Prepare the starting and stopping indices.
+ */
+
+ index1 = *indexPtr1;
+ if (indexPtr2 != NULL) {
+ index2 = *indexPtr2;
+ } else {
+ index2 = index1;
+ TkTextIndexForwChars(NULL, &index2, 1, &index2, COUNT_INDICES);
+ }
+
+ /*
+ * Make sure there's really something to delete.
+ */
+
+ if (TkTextIndexCmp(&index1, &index2) >= 0) {
+ return TCL_OK;
+ }
+
+ /*
+ * The code below is ugly, but it's needed to make sure there is always a
+ * dummy empty line at the end of the text. If the final newline of the
+ * file (just before the dummy line) is being deleted, then back up index
+ * to just before the newline. If there is a newline just before the first
+ * character being deleted, then back up the first index too. The idea is
+ * that a deletion involving a range starting at a line start and
+ * including the final \n (i.e. index2 is "end") is an attempt to delete
+ * complete lines, so the \n before the deleted block shall become the new
+ * final \n. Furthermore, remove any tags that are present on the newline
+ * that isn't going to be deleted after all (this simulates deleting the
+ * newline and then adding a "clean" one back again). Note that index1 and
+ * index2 might now be equal again which means that no text will be
+ * deleted but tags might be removed.
+ */
+
+ line1 = TkBTreeLinesTo(textPtr, index1.linePtr);
+ line2 = TkBTreeLinesTo(textPtr, index2.linePtr);
+ if (line2 == TkBTreeNumLines(sharedTextPtr->tree, textPtr)) {
+ TkTextTag **arrayPtr;
+ int arraySize, i;
+ TkTextIndex oldIndex2;
+
+ oldIndex2 = index2;
+ TkTextIndexBackChars(NULL, &oldIndex2, 1, &index2, COUNT_INDICES);
+ line2--;
+ if ((index1.byteIndex == 0) && (line1 != 0)) {
+ TkTextIndexBackChars(NULL, &index1, 1, &index1, COUNT_INDICES);
+ line1--;
+ }
+ arrayPtr = TkBTreeGetTags(&index2, NULL, &arraySize);
+ if (arrayPtr != NULL) {
+ for (i = 0; i < arraySize; i++) {
+ TkBTreeTag(&index2, &oldIndex2, arrayPtr[i], 0);
+ }
+ ckfree(arrayPtr);
+ }
+ }
+
+ /*
+ * For speed, we remove all tags from the range first. If we don't
+ * do this, the code below can (when there are many tags) grow
+ * non-linearly in execution time.
+ */
+
+ for (i=0, hPtr=Tcl_FirstHashEntry(&sharedTextPtr->tagTable, &search);
+ hPtr != NULL; i++, hPtr = Tcl_NextHashEntry(&search)) {
+ TkTextTag *tagPtr = Tcl_GetHashValue(hPtr);
+
+ TkBTreeTag(&index1, &index2, tagPtr, 0);
+ }
+
+ /*
+ * Special case for the sel tag which is not in the hash table. We
+ * need to do this once for each peer text widget.
+ */
+
+ for (tPtr = sharedTextPtr->peers; tPtr != NULL ;
+ tPtr = tPtr->next) {
+ if (TkBTreeTag(&index1, &index2, tPtr->selTagPtr, 0)) {
+ /*
+ * Send an event that the selection changed. This is
+ * equivalent to:
+ * event generate $textWidget <<Selection>>
+ */
+
+ TkTextSelectionEvent(textPtr);
+ tPtr->abortSelections = 1;
+ }
+ }
+
+ /*
+ * Tell the display what's about to happen so it can discard obsolete
+ * display information, then do the deletion. Also, if the deletion
+ * involves the top line on the screen, then we have to reset the view
+ * (the deletion will invalidate textPtr->topIndex). Compute what the new
+ * first character will be, then do the deletion, then reset the view.
+ */
+
+ TkTextChanged(sharedTextPtr, NULL, &index1, &index2);
+
+ resetViewCount = 0;
+ if (sharedTextPtr->refCount > PIXEL_CLIENTS) {
+ lineAndByteIndex = ckalloc(sizeof(int) * 2 * sharedTextPtr->refCount);
+ } else {
+ lineAndByteIndex = pixels;
+ }
+ for (tPtr = sharedTextPtr->peers; tPtr != NULL ; tPtr = tPtr->next) {
+ int line = 0;
+ int byteIndex = 0;
+ int resetView = 0;
+
+ if (TkTextIndexCmp(&index2, &tPtr->topIndex) >= 0) {
+ if (TkTextIndexCmp(&index1, &tPtr->topIndex) <= 0) {
+ /*
+ * Deletion range straddles topIndex: use the beginning of the
+ * range as the new topIndex.
+ */
+
+ resetView = 1;
+ line = line1;
+ byteIndex = index1.byteIndex;
+ } else if (index1.linePtr == tPtr->topIndex.linePtr) {
+ /*
+ * Deletion range starts on top line but after topIndex. Use
+ * the current topIndex as the new one.
+ */
+
+ resetView = 1;
+ line = line1;
+ byteIndex = tPtr->topIndex.byteIndex;
+ } else {
+ /*
+ * Deletion range starts after the top line. This peers's view
+ * will not need to be reset. Nothing to do.
+ */
+ }
+ } else if (index2.linePtr == tPtr->topIndex.linePtr) {
+ /*
+ * Deletion range ends on top line but before topIndex. Figure out
+ * what will be the new character index for the character
+ * currently pointed to by topIndex.
+ */
+
+ resetView = 1;
+ line = line2;
+ byteIndex = tPtr->topIndex.byteIndex;
+ if (index1.linePtr != index2.linePtr) {
+ byteIndex -= index2.byteIndex;
+ } else {
+ byteIndex -= (index2.byteIndex - index1.byteIndex);
+ }
+ } else {
+ /*
+ * Deletion range ends before the top line. This peers's view
+ * will not need to be reset. Nothing to do.
+ */
+ }
+ if (resetView) {
+ lineAndByteIndex[resetViewCount] = line;
+ lineAndByteIndex[resetViewCount+1] = byteIndex;
+ } else {
+ lineAndByteIndex[resetViewCount] = -1;
+ }
+ resetViewCount += 2;
+ }
+
+ /*
+ * Push the deletion on the undo stack if something was actually deleted.
+ */
+
+ if (TkTextIndexCmp(&index1, &index2) < 0) {
+ if (sharedTextPtr->undo) {
+ Tcl_Obj *get;
+
+ if (sharedTextPtr->autoSeparators
+ && (sharedTextPtr->lastEditMode != TK_TEXT_EDIT_DELETE)) {
+ TkUndoInsertUndoSeparator(sharedTextPtr->undoStack);
+ }
+
+ sharedTextPtr->lastEditMode = TK_TEXT_EDIT_DELETE;
+
+ get = TextGetText(textPtr, &index1, &index2, 0);
+ TextPushUndoAction(textPtr, get, 0, &index1, &index2);
+ }
+ sharedTextPtr->stateEpoch++;
+
+ TkBTreeDeleteIndexRange(sharedTextPtr->tree, &index1, &index2);
+
+ UpdateDirtyFlag(sharedTextPtr);
+ }
+
+ resetViewCount = 0;
+ for (tPtr = sharedTextPtr->peers; tPtr != NULL ; tPtr = tPtr->next) {
+ int line = lineAndByteIndex[resetViewCount];
+
+ if (line != -1) {
+ int byteIndex = lineAndByteIndex[resetViewCount+1];
+ TkTextIndex indexTmp;
+
+ if (tPtr == textPtr) {
+ if (viewUpdate) {
+ /*
+ * line cannot be before -startline of textPtr because
+ * this line corresponds to an index which is necessarily
+ * between "1.0" and "end" relative to textPtr.
+ * Therefore no need to clamp line to the -start/-end
+ * range.
+ */
+
+ TkTextMakeByteIndex(sharedTextPtr->tree, textPtr, line,
+ byteIndex, &indexTmp);
+ TkTextSetYView(tPtr, &indexTmp, 0);
+ }
+ } else {
+ TkTextMakeByteIndex(sharedTextPtr->tree, tPtr, line,
+ byteIndex, &indexTmp);
+ /*
+ * line may be before -startline of tPtr and must be
+ * clamped to -startline before providing it to
+ * TkTextSetYView otherwise lines before -startline
+ * would be displayed.
+ * There is no need to worry about -endline however,
+ * because the view will only be reset if the deletion
+ * involves the TOP line of the screen
+ */
+
+ if (tPtr->start != NULL) {
+ int start;
+ TkTextIndex indexStart;
+
+ start = TkBTreeLinesTo(NULL, tPtr->start);
+ TkTextMakeByteIndex(sharedTextPtr->tree, NULL, start,
+ 0, &indexStart);
+ if (TkTextIndexCmp(&indexTmp, &indexStart) < 0) {
+ indexTmp = indexStart;
+ }
+ }
+ TkTextSetYView(tPtr, &indexTmp, 0);
+ }
+ }
+ resetViewCount += 2;
+ }
+ if (sharedTextPtr->refCount > PIXEL_CLIENTS) {
+ ckfree(lineAndByteIndex);
+ }
+
+ if (line1 >= line2) {
+ /*
+ * Invalidate any selection retrievals in progress, assuming we didn't
+ * check for this case above.
+ */
+
+ for (tPtr = sharedTextPtr->peers; tPtr != NULL ; tPtr = tPtr->next) {
+ tPtr->abortSelections = 1;
+ }
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TextFetchSelection --
+ *
+ * This function is called back by Tk when the selection is requested by
+ * someone. It returns part or all of the selection in a buffer provided
+ * by the caller.
+ *
+ * Results:
+ * The return value is the number of non-NULL bytes stored at buffer.
+ * Buffer is filled (or partially filled) with a NULL-terminated string
+ * containing part or all of the selection, as given by offset and
+ * maxBytes.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TextFetchSelection(
+ ClientData clientData, /* Information about text widget. */
+ int offset, /* Offset within selection of first character
+ * to be returned. */
+ char *buffer, /* Location in which to place selection. */
+ int maxBytes) /* Maximum number of bytes to place at buffer,
+ * not including terminating NULL
+ * character. */
+{
+ register TkText *textPtr = clientData;
+ TkTextIndex eof;
+ int count, chunkSize, offsetInSeg;
+ TkTextSearch search;
+ TkTextSegment *segPtr;
+
+ if ((!textPtr->exportSelection) || Tcl_IsSafe(textPtr->interp)) {
+ return -1;
+ }
+
+ /*
+ * Find the beginning of the next range of selected text. Note: if the
+ * selection is being retrieved in multiple pieces (offset != 0) and some
+ * modification has been made to the text that affects the selection then
+ * reject the selection request (make 'em start over again).
+ */
+
+ if (offset == 0) {
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, 0, 0,
+ &textPtr->selIndex);
+ textPtr->abortSelections = 0;
+ } else if (textPtr->abortSelections) {
+ return 0;
+ }
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,
+ TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr), 0, &eof);
+ TkBTreeStartSearch(&textPtr->selIndex, &eof, textPtr->selTagPtr, &search);
+ if (!TkBTreeCharTagged(&textPtr->selIndex, textPtr->selTagPtr)) {
+ if (!TkBTreeNextTag(&search)) {
+ if (offset == 0) {
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+ textPtr->selIndex = search.curIndex;
+ }
+
+ /*
+ * Each iteration through the outer loop below scans one selected range.
+ * Each iteration through the inner loop scans one segment in the selected
+ * range.
+ */
+
+ count = 0;
+ while (1) {
+ /*
+ * Find the end of the current range of selected text.
+ */
+
+ if (!TkBTreeNextTag(&search)) {
+ Tcl_Panic("TextFetchSelection couldn't find end of range");
+ }
+
+ /*
+ * Copy information from character segments into the buffer until
+ * either we run out of space in the buffer or we get to the end of
+ * this range of text.
+ */
+
+ while (1) {
+ if (maxBytes == 0) {
+ goto fetchDone;
+ }
+ segPtr = TkTextIndexToSeg(&textPtr->selIndex, &offsetInSeg);
+ chunkSize = segPtr->size - offsetInSeg;
+ if (chunkSize > maxBytes) {
+ chunkSize = maxBytes;
+ }
+ if (textPtr->selIndex.linePtr == search.curIndex.linePtr) {
+ int leftInRange;
+
+ leftInRange = search.curIndex.byteIndex
+ - textPtr->selIndex.byteIndex;
+ if (leftInRange < chunkSize) {
+ chunkSize = leftInRange;
+ if (chunkSize <= 0) {
+ break;
+ }
+ }
+ }
+ if ((segPtr->typePtr == &tkTextCharType)
+ && !TkTextIsElided(textPtr, &textPtr->selIndex, NULL)) {
+ memcpy(buffer, segPtr->body.chars + offsetInSeg,
+ (size_t) chunkSize);
+ buffer += chunkSize;
+ maxBytes -= chunkSize;
+ count += chunkSize;
+ }
+ TkTextIndexForwBytes(textPtr, &textPtr->selIndex, chunkSize,
+ &textPtr->selIndex);
+ }
+
+ /*
+ * Find the beginning of the next range of selected text.
+ */
+
+ if (!TkBTreeNextTag(&search)) {
+ break;
+ }
+ textPtr->selIndex = search.curIndex;
+ }
+
+ fetchDone:
+ *buffer = 0;
+ return count;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkTextLostSelection --
+ *
+ * This function is called back by Tk when the selection is grabbed away
+ * from a text widget. On Windows and Mac systems, we want to remember
+ * the selection for the next time the focus enters the window. On Unix,
+ * just remove the "sel" tag from everything in the widget.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The "sel" tag is cleared from the window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkTextLostSelection(
+ ClientData clientData) /* Information about text widget. */
+{
+ register TkText *textPtr = clientData;
+
+ if (TkpAlwaysShowSelection(textPtr->tkwin)) {
+ TkTextIndex start, end;
+
+ if ((!textPtr->exportSelection) || Tcl_IsSafe(textPtr->interp)) {
+ return;
+ }
+
+ /*
+ * On Windows and Mac systems, we want to remember the selection for
+ * the next time the focus enters the window. On Unix, just remove the
+ * "sel" tag from everything in the widget.
+ */
+
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,
+ 0, 0, &start);
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,
+ TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr),
+ 0, &end);
+ TkTextRedrawTag(NULL, textPtr, &start, &end, textPtr->selTagPtr, 1);
+ TkBTreeTag(&start, &end, textPtr->selTagPtr, 0);
+ }
+
+ /*
+ * Send an event that the selection changed. This is equivalent to:
+ * event generate $textWidget <<Selection>>
+ */
+
+ TkTextSelectionEvent(textPtr);
+
+ textPtr->flags &= ~GOT_SELECTION;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkTextSelectionEvent --
+ *
+ * When anything relevant to the "sel" tag has been changed, call this
+ * function to generate a <<Selection>> event.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If <<Selection>> bindings are present, they will trigger.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkTextSelectionEvent(
+ TkText *textPtr)
+{
+ /*
+ * Send an event that the selection changed. This is equivalent to:
+ * event generate $textWidget <<Selection>>
+ */
+
+ TkSendVirtualEvent(textPtr->tkwin, "Selection", NULL);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TextBlinkProc --
+ *
+ * This function is called as a timer handler to blink the insertion
+ * cursor off and on.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The cursor gets turned on or off, redisplay gets invoked, and this
+ * function reschedules itself.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+TextBlinkProc(
+ ClientData clientData) /* Pointer to record describing text. */
+{
+ register TkText *textPtr = clientData;
+ TkTextIndex index;
+ int x, y, w, h, charWidth;
+
+ if ((textPtr->state == TK_TEXT_STATE_DISABLED) ||
+ !(textPtr->flags & GOT_FOCUS) || (textPtr->insertOffTime == 0)) {
+ if (!(textPtr->flags & GOT_FOCUS) &&
+ (textPtr->insertUnfocussed != TK_TEXT_INSERT_NOFOCUS_NONE)) {
+ /*
+ * The widget doesn't have the focus yet it is configured to
+ * display the cursor when it doesn't have the focus. Act now!
+ */
+
+ textPtr->flags |= INSERT_ON;
+ goto redrawInsert;
+ }
+ if ((textPtr->insertOffTime == 0) && !(textPtr->flags & INSERT_ON)) {
+ /*
+ * The widget was configured to have zero offtime while the
+ * insertion point was not displayed. We have to display it once.
+ */
+
+ textPtr->flags |= INSERT_ON;
+ goto redrawInsert;
+ }
+ return;
+ }
+ if (textPtr->flags & INSERT_ON) {
+ textPtr->flags &= ~INSERT_ON;
+ textPtr->insertBlinkHandler = Tcl_CreateTimerHandler(
+ textPtr->insertOffTime, TextBlinkProc, textPtr);
+ } else {
+ textPtr->flags |= INSERT_ON;
+ textPtr->insertBlinkHandler = Tcl_CreateTimerHandler(
+ textPtr->insertOnTime, TextBlinkProc, textPtr);
+ }
+ redrawInsert:
+ TkTextMarkSegToIndex(textPtr, textPtr->insertMarkPtr, &index);
+ if (TkTextIndexBbox(textPtr, &index, &x, &y, &w, &h, &charWidth) == 0) {
+ if (textPtr->insertCursorType) {
+ /* Block cursor */
+ TkTextRedrawRegion(textPtr, x - textPtr->width / 2, y,
+ charWidth + textPtr->insertWidth / 2, h);
+ } else {
+ /* I-beam cursor */
+ TkTextRedrawRegion(textPtr, x - textPtr->insertWidth / 2, y,
+ textPtr->insertWidth, h);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TextInsertCmd --
+ *
+ * This function is invoked to process the "insert" and "replace" widget
+ * commands for text widgets.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ * If 'viewUpdate' is true, we may adjust the window contents'
+ * y-position, and scrollbar setting.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TextInsertCmd(
+ TkSharedText *sharedTextPtr,/* Shared portion of peer widgets. */
+ TkText *textPtr, /* Information about text widget. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[], /* Argument objects. */
+ const TkTextIndex *indexPtr,/* Index at which to insert. */
+ int viewUpdate) /* Update the view if set. */
+{
+ TkTextIndex index1, index2;
+ int j;
+
+ if (sharedTextPtr == NULL) {
+ sharedTextPtr = textPtr->sharedTextPtr;
+ }
+
+ index1 = *indexPtr;
+ for (j = 0; j < objc; j += 2) {
+ /*
+ * Here we rely on this call to modify index1 if it is outside the
+ * acceptable range. In particular, if index1 is "end", it must be set
+ * to the last allowable index for insertion, otherwise subsequent tag
+ * insertions will fail.
+ */
+
+ int length = InsertChars(sharedTextPtr, textPtr, &index1, objv[j],
+ viewUpdate);
+
+ if (objc > (j+1)) {
+ Tcl_Obj **tagNamePtrs;
+ TkTextTag **oldTagArrayPtr;
+ int numTags;
+
+ TkTextIndexForwBytes(textPtr, &index1, length, &index2);
+ oldTagArrayPtr = TkBTreeGetTags(&index1, NULL, &numTags);
+ if (oldTagArrayPtr != NULL) {
+ int i;
+
+ for (i = 0; i < numTags; i++) {
+ TkBTreeTag(&index1, &index2, oldTagArrayPtr[i], 0);
+ }
+ ckfree(oldTagArrayPtr);
+ }
+ if (Tcl_ListObjGetElements(interp, objv[j+1], &numTags,
+ &tagNamePtrs) != TCL_OK) {
+ return TCL_ERROR;
+ } else {
+ int i;
+
+ for (i = 0; i < numTags; i++) {
+ const char *strTag = Tcl_GetString(tagNamePtrs[i]);
+
+ TkBTreeTag(&index1, &index2,
+ TkTextCreateTag(textPtr, strTag, NULL), 1);
+ }
+ index1 = index2;
+ }
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TextSearchCmd --
+ *
+ * This function is invoked to process the "search" widget command for
+ * text widgets. See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TextSearchCmd(
+ TkText *textPtr, /* Information about text widget. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ int i, argsLeft, code;
+ SearchSpec searchSpec;
+
+ static const char *const switchStrings[] = {
+ "-hidden",
+ "--", "-all", "-backwards", "-count", "-elide", "-exact", "-forwards",
+ "-nocase", "-nolinestop", "-overlap", "-regexp", "-strictlimits", NULL
+ };
+ enum SearchSwitches {
+ TK_TEXT_SEARCH_HIDDEN,
+ TK_TEXT_SEARCH_END, TK_TEXT_SEARCH_ALL, TK_TEXT_SEARCH_BACK, TK_TEXT_SEARCH_COUNT, TK_TEXT_SEARCH_ELIDE,
+ TK_TEXT_SEARCH_EXACT, TK_TEXT_SEARCH_FWD, TK_TEXT_SEARCH_NOCASE,
+ TK_TEXT_SEARCH_NOLINESTOP, TK_TEXT_SEARCH_OVERLAP, TK_TEXT_SEARCH_REGEXP, TK_TEXT_SEARCH_STRICTLIMITS
+ };
+
+ /*
+ * Set up the search specification, including the last 4 fields which are
+ * text widget specific.
+ */
+
+ searchSpec.exact = 1;
+ searchSpec.noCase = 0;
+ searchSpec.all = 0;
+ searchSpec.backwards = 0;
+ searchSpec.varPtr = NULL;
+ searchSpec.countPtr = NULL;
+ searchSpec.resPtr = NULL;
+ searchSpec.searchElide = 0;
+ searchSpec.noLineStop = 0;
+ searchSpec.overlap = 0;
+ searchSpec.strictLimits = 0;
+ searchSpec.numLines =
+ TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr);
+ searchSpec.clientData = textPtr;
+ searchSpec.addLineProc = &TextSearchAddNextLine;
+ searchSpec.foundMatchProc = &TextSearchFoundMatch;
+ searchSpec.lineIndexProc = &TextSearchGetLineIndex;
+
+ /*
+ * Parse switches and other arguments.
+ */
+
+ for (i=2 ; i<objc ; i++) {
+ int index;
+
+ if (Tcl_GetString(objv[i])[0] != '-') {
+ break;
+ }
+
+ if (Tcl_GetIndexFromObjStruct(NULL, objv[i], switchStrings,
+ sizeof(char *), "switch", 0, &index) != TCL_OK) {
+ /*
+ * Hide the -hidden option, generating the error description with
+ * the side effects of T_GIFO.
+ */
+
+ (void) Tcl_GetIndexFromObjStruct(interp, objv[i], switchStrings+1,
+ sizeof(char *), "switch", 0, &index);
+ return TCL_ERROR;
+ }
+
+ switch ((enum SearchSwitches) index) {
+ case TK_TEXT_SEARCH_END:
+ i++;
+ goto endOfSwitchProcessing;
+ case TK_TEXT_SEARCH_ALL:
+ searchSpec.all = 1;
+ break;
+ case TK_TEXT_SEARCH_BACK:
+ searchSpec.backwards = 1;
+ break;
+ case TK_TEXT_SEARCH_COUNT:
+ if (i >= objc-1) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "no value given for \"-count\" option", -1));
+ Tcl_SetErrorCode(interp, "TK", "TEXT", "VALUE", NULL);
+ return TCL_ERROR;
+ }
+ i++;
+
+ /*
+ * Assumption objv[i] isn't going to disappear on us during this
+ * function, which is fair.
+ */
+
+ searchSpec.varPtr = objv[i];
+ break;
+ case TK_TEXT_SEARCH_ELIDE:
+ case TK_TEXT_SEARCH_HIDDEN:
+ searchSpec.searchElide = 1;
+ break;
+ case TK_TEXT_SEARCH_EXACT:
+ searchSpec.exact = 1;
+ break;
+ case TK_TEXT_SEARCH_FWD:
+ searchSpec.backwards = 0;
+ break;
+ case TK_TEXT_SEARCH_NOCASE:
+ searchSpec.noCase = 1;
+ break;
+ case TK_TEXT_SEARCH_NOLINESTOP:
+ searchSpec.noLineStop = 1;
+ break;
+ case TK_TEXT_SEARCH_OVERLAP:
+ searchSpec.overlap = 1;
+ break;
+ case TK_TEXT_SEARCH_STRICTLIMITS:
+ searchSpec.strictLimits = 1;
+ break;
+ case TK_TEXT_SEARCH_REGEXP:
+ searchSpec.exact = 0;
+ break;
+ default:
+ Tcl_Panic("unexpected switch fallthrough");
+ }
+ }
+ endOfSwitchProcessing:
+
+ argsLeft = objc - (i+2);
+ if ((argsLeft != 0) && (argsLeft != 1)) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?switches? pattern index ?stopIndex?");
+ return TCL_ERROR;
+ }
+
+ if (searchSpec.noLineStop && searchSpec.exact) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "the \"-nolinestop\" option requires the \"-regexp\" option"
+ " to be present", -1));
+ Tcl_SetErrorCode(interp, "TK", "TEXT", "SEARCH_USAGE", NULL);
+ return TCL_ERROR;
+ }
+
+ if (searchSpec.overlap && !searchSpec.all) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "the \"-overlap\" option requires the \"-all\" option"
+ " to be present", -1));
+ Tcl_SetErrorCode(interp, "TK", "TEXT", "SEARCH_USAGE", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Scan through all of the lines of the text circularly, starting at the
+ * given index. 'objv[i]' is the pattern which may be an exact string or a
+ * regexp pattern depending on the flags set above.
+ */
+
+ code = SearchPerform(interp, &searchSpec, objv[i], objv[i+1],
+ (argsLeft == 1 ? objv[i+2] : NULL));
+ if (code != TCL_OK) {
+ goto cleanup;
+ }
+
+ /*
+ * Set the '-count' variable, if given.
+ */
+
+ if (searchSpec.varPtr != NULL && searchSpec.countPtr != NULL) {
+ Tcl_IncrRefCount(searchSpec.countPtr);
+ if (Tcl_ObjSetVar2(interp, searchSpec.varPtr, NULL,
+ searchSpec.countPtr, TCL_LEAVE_ERR_MSG) == NULL) {
+ code = TCL_ERROR;
+ goto cleanup;
+ }
+ }
+
+ /*
+ * Set the result.
+ */
+
+ if (searchSpec.resPtr != NULL) {
+ Tcl_SetObjResult(interp, searchSpec.resPtr);
+ searchSpec.resPtr = NULL;
+ }
+
+ cleanup:
+ if (searchSpec.countPtr != NULL) {
+ Tcl_DecrRefCount(searchSpec.countPtr);
+ }
+ if (searchSpec.resPtr != NULL) {
+ Tcl_DecrRefCount(searchSpec.resPtr);
+ }
+ return code;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TextSearchGetLineIndex --
+ *
+ * Extract a row, text offset index position from an objPtr
+ *
+ * This means we ignore any embedded windows/images and elidden text
+ * (unless we are searching that).
+ *
+ * Results:
+ * Standard Tcl error code (with a message in the interpreter on error
+ * conditions).
+ *
+ * The offset placed in offsetPosPtr is a utf-8 char* byte index for
+ * exact searches, and a Unicode character index for regexp searches.
+ *
+ * The line number should start at zero (searches which wrap around
+ * assume the first line is numbered 0).
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TextSearchGetLineIndex(
+ Tcl_Interp *interp, /* For error messages. */
+ Tcl_Obj *objPtr, /* Contains a textual index like "1.2" */
+ SearchSpec *searchSpecPtr, /* Contains other search parameters. */
+ int *linePosPtr, /* For returning the line number. */
+ int *offsetPosPtr) /* For returning the text offset in the
+ * line. */
+{
+ const TkTextIndex *indexPtr;
+ int line;
+ TkText *textPtr = searchSpecPtr->clientData;
+
+ indexPtr = TkTextGetIndexFromObj(interp, textPtr, objPtr);
+ if (indexPtr == NULL) {
+ return TCL_ERROR;
+ }
+
+ line = TkBTreeLinesTo(textPtr, indexPtr->linePtr);
+ if (line >= searchSpecPtr->numLines) {
+ TkTextLine *linePtr;
+ int count = 0;
+ TkTextSegment *segPtr;
+
+ line = searchSpecPtr->numLines-1;
+ linePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, textPtr, line);
+
+ /*
+ * Count the number of bytes in this line.
+ */
+
+ for (segPtr=linePtr->segPtr ; segPtr!=NULL ; segPtr=segPtr->nextPtr) {
+ count += segPtr->size;
+ }
+ *offsetPosPtr = TextSearchIndexInLine(searchSpecPtr, linePtr, count);
+ } else {
+ *offsetPosPtr = TextSearchIndexInLine(searchSpecPtr,
+ indexPtr->linePtr, indexPtr->byteIndex);
+ }
+
+ *linePosPtr = line;
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TextSearchIndexInLine --
+ *
+ * Find textual index of 'byteIndex' in the searchable characters of
+ * 'linePtr'.
+ *
+ * This means we ignore any embedded windows/images and elidden text
+ * (unless we are searching that).
+ *
+ * Results:
+ * The returned index is a utf-8 char* byte index for exact searches, and
+ * a Unicode character index for regexp searches.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TextSearchIndexInLine(
+ const SearchSpec *searchSpecPtr,
+ /* Search parameters. */
+ TkTextLine *linePtr, /* The line we're looking at. */
+ int byteIndex) /* Index into the line. */
+{
+ TkTextSegment *segPtr;
+ TkTextIndex curIndex;
+ int index, leftToScan;
+ TkText *textPtr = searchSpecPtr->clientData;
+
+ index = 0;
+ curIndex.tree = textPtr->sharedTextPtr->tree;
+ curIndex.linePtr = linePtr; curIndex.byteIndex = 0;
+ for (segPtr = linePtr->segPtr, leftToScan = byteIndex;
+ leftToScan > 0;
+ curIndex.byteIndex += segPtr->size, segPtr = segPtr->nextPtr) {
+ if ((segPtr->typePtr == &tkTextCharType) &&
+ (searchSpecPtr->searchElide
+ || !TkTextIsElided(textPtr, &curIndex, NULL))) {
+ if (leftToScan < segPtr->size) {
+ if (searchSpecPtr->exact) {
+ index += leftToScan;
+ } else {
+ index += Tcl_NumUtfChars(segPtr->body.chars, leftToScan);
+ }
+ } else if (searchSpecPtr->exact) {
+ index += segPtr->size;
+ } else {
+ index += Tcl_NumUtfChars(segPtr->body.chars, -1);
+ }
+ }
+ leftToScan -= segPtr->size;
+ }
+ return index;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TextSearchAddNextLine --
+ *
+ * Adds a line from the text widget to the object 'theLine'.
+ *
+ * Results:
+ * A pointer to the TkTextLine corresponding to the given line, or NULL
+ * if there was no available line.
+ *
+ * Also 'lenPtr' (if non-NULL) is filled in with the total length of
+ * 'theLine' (not just what we added to it, but the length including what
+ * was already in there). This is in bytes for an exact search and in
+ * chars for a regexp search.
+ *
+ * Also 'extraLinesPtr' (if non-NULL) will have its value incremented by
+ * 1 for each additional logical line we have added because a newline is
+ * elided (this will only ever happen if we have chosen not to search
+ * elided text, of course).
+ *
+ * Side effects:
+ * Memory may be allocated or re-allocated for theLine's string
+ * representation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static ClientData
+TextSearchAddNextLine(
+ int lineNum, /* Line we must add. */
+ SearchSpec *searchSpecPtr, /* Search parameters. */
+ Tcl_Obj *theLine, /* Object to append to. */
+ int *lenPtr, /* For returning the total length. */
+ int *extraLinesPtr) /* If non-NULL, will have its value
+ * incremented by the number of additional
+ * logical lines which are merged into this
+ * one by newlines being elided. */
+{
+ TkTextLine *linePtr, *thisLinePtr;
+ TkTextIndex curIndex;
+ TkTextSegment *segPtr;
+ TkText *textPtr = searchSpecPtr->clientData;
+ int nothingYet = 1;
+
+ /*
+ * Extract the text from the line.
+ */
+
+ linePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, textPtr, lineNum);
+ if (linePtr == NULL) {
+ return NULL;
+ }
+ curIndex.tree = textPtr->sharedTextPtr->tree;
+ thisLinePtr = linePtr;
+
+ while (thisLinePtr != NULL) {
+ int elideWraps = 0;
+
+ curIndex.linePtr = thisLinePtr;
+ curIndex.byteIndex = 0;
+ for (segPtr = thisLinePtr->segPtr; segPtr != NULL;
+ curIndex.byteIndex += segPtr->size, segPtr = segPtr->nextPtr) {
+ if (!searchSpecPtr->searchElide
+ && TkTextIsElided(textPtr, &curIndex, NULL)) {
+ /*
+ * If we reach the end of the logical line, and if we have at
+ * least one character in the string, then we continue
+ * wrapping to the next logical line. If there are no
+ * characters yet, then the entire line of characters is
+ * elided and there's no need to complicate matters by
+ * wrapping - we'll look at the next line in due course.
+ */
+
+ if (segPtr->nextPtr == NULL && !nothingYet) {
+ elideWraps = 1;
+ }
+ continue;
+ }
+ if (segPtr->typePtr != &tkTextCharType) {
+ continue;
+ }
+ Tcl_AppendToObj(theLine, segPtr->body.chars, segPtr->size);
+ nothingYet = 0;
+ }
+ if (!elideWraps) {
+ break;
+ }
+ lineNum++;
+ if (lineNum >= searchSpecPtr->numLines) {
+ break;
+ }
+ thisLinePtr = TkBTreeNextLine(textPtr, thisLinePtr);
+ if (thisLinePtr != NULL && extraLinesPtr != NULL) {
+ /*
+ * Tell our caller we have an extra line merged in.
+ */
+
+ *extraLinesPtr = (*extraLinesPtr) + 1;
+ }
+ }
+
+ /*
+ * If we're ignoring case, convert the line to lower case. There is no
+ * need to do this for regexp searches, since they handle a flag for this
+ * purpose.
+ */
+
+ if (searchSpecPtr->exact && searchSpecPtr->noCase) {
+ Tcl_SetObjLength(theLine, Tcl_UtfToLower(Tcl_GetString(theLine)));
+ }
+
+ if (lenPtr != NULL) {
+ if (searchSpecPtr->exact) {
+ Tcl_GetString(theLine);
+ *lenPtr = theLine->length;
+ } else {
+ *lenPtr = Tcl_GetCharLength(theLine);
+ }
+ }
+ return linePtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TextSearchFoundMatch --
+ *
+ * Stores information from a successful search.
+ *
+ * Results:
+ * 1 if the information was stored, 0 if the position at which the match
+ * was found actually falls outside the allowable search region (and
+ * therefore the search is actually complete).
+ *
+ * Side effects:
+ * Memory may be allocated in the 'countPtr' and 'resPtr' fields of
+ * 'searchSpecPtr'. Each of those objects will have refCount zero and
+ * must eventually be freed or stored elsewhere as appropriate.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TextSearchFoundMatch(
+ int lineNum, /* Line on which match was found. */
+ SearchSpec *searchSpecPtr, /* Search parameters. */
+ ClientData clientData, /* Token returned by the 'addNextLineProc',
+ * TextSearchAddNextLine. May be NULL, in
+ * which we case we must generate it (from
+ * lineNum). */
+ Tcl_Obj *theLine, /* Text from current line, only accessed for
+ * exact searches, and is allowed to be NULL
+ * for regexp searches. */
+ int matchOffset, /* Offset of found item in utf-8 bytes for
+ * exact search, Unicode chars for regexp. */
+ int matchLength) /* Length also in bytes/chars as per search
+ * type. */
+{
+ int numChars;
+ int leftToScan;
+ TkTextIndex curIndex, foundIndex;
+ TkTextSegment *segPtr;
+ TkTextLine *linePtr;
+ TkText *textPtr = searchSpecPtr->clientData;
+
+ if (lineNum == searchSpecPtr->stopLine) {
+ /*
+ * If the current index is on the wrong side of the stopIndex, then
+ * the item we just found is actually outside the acceptable range,
+ * and the search is over.
+ */
+
+ if (searchSpecPtr->backwards ^
+ (matchOffset >= searchSpecPtr->stopOffset)) {
+ return 0;
+ }
+ }
+
+ /*
+ * Calculate the character count, which may need augmenting if there are
+ * embedded windows or elidden text.
+ */
+
+ if (searchSpecPtr->exact) {
+ const char *startOfLine = Tcl_GetString(theLine);
+
+ numChars = Tcl_NumUtfChars(startOfLine + matchOffset, matchLength);
+ } else {
+ numChars = matchLength;
+ }
+
+ /*
+ * If we're using strict limits checking, ensure that the match with its
+ * full length fits inside the given range.
+ */
+
+ if (searchSpecPtr->strictLimits && lineNum == searchSpecPtr->stopLine) {
+ if (searchSpecPtr->backwards ^
+ ((matchOffset + numChars) > searchSpecPtr->stopOffset)) {
+ return 0;
+ }
+ }
+
+ /*
+ * The index information returned by the regular expression parser only
+ * considers textual information: it doesn't account for embedded windows,
+ * elided text (when we are not searching elided text) or any other
+ * non-textual info. Scan through the line's segments again to adjust both
+ * matchChar and matchCount.
+ *
+ * We will walk through the segments of this line until we have either
+ * reached the end of the match or we have reached the end of the line.
+ */
+
+ linePtr = clientData;
+ if (linePtr == NULL) {
+ linePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, textPtr,
+ lineNum);
+ }
+
+ curIndex.tree = textPtr->sharedTextPtr->tree;
+
+ /*
+ * Find the starting point.
+ */
+
+ leftToScan = matchOffset;
+ while (1) {
+ curIndex.linePtr = linePtr;
+ curIndex.byteIndex = 0;
+
+ /*
+ * Note that we allow leftToScan to be zero because we want to skip
+ * over any preceding non-textual items.
+ */
+
+ for (segPtr = linePtr->segPtr; leftToScan >= 0 && segPtr;
+ segPtr = segPtr->nextPtr) {
+ if (segPtr->typePtr != &tkTextCharType) {
+ matchOffset += segPtr->size;
+ } else if (!searchSpecPtr->searchElide
+ && TkTextIsElided(textPtr, &curIndex, NULL)) {
+ if (searchSpecPtr->exact) {
+ matchOffset += segPtr->size;
+ } else {
+ matchOffset += Tcl_NumUtfChars(segPtr->body.chars, -1);
+ }
+ } else {
+ if (searchSpecPtr->exact) {
+ leftToScan -= segPtr->size;
+ } else {
+ leftToScan -= Tcl_NumUtfChars(segPtr->body.chars, -1);
+ }
+ }
+ curIndex.byteIndex += segPtr->size;
+ }
+ if (segPtr == NULL && leftToScan >= 0) {
+ /*
+ * This will only happen if we are eliding newlines.
+ */
+
+ linePtr = TkBTreeNextLine(textPtr, linePtr);
+ if (linePtr == NULL) {
+ /*
+ * If we reach the end of the text, we have a serious problem,
+ * unless there's actually nothing left to look for.
+ */
+
+ if (leftToScan == 0) {
+ break;
+ } else {
+ Tcl_Panic("Reached end of text in a match");
+ }
+ }
+
+ /*
+ * We've wrapped to the beginning of the next logical line, which
+ * has been merged with the previous one whose newline was elided.
+ */
+
+ lineNum++;
+ matchOffset = 0;
+ } else {
+ break;
+ }
+ }
+
+ /*
+ * Calculate and store the found index in the result.
+ */
+
+ if (searchSpecPtr->exact) {
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, lineNum,
+ matchOffset, &foundIndex);
+ } else {
+ TkTextMakeCharIndex(textPtr->sharedTextPtr->tree, textPtr, lineNum,
+ matchOffset, &foundIndex);
+ }
+
+ if (searchSpecPtr->all) {
+ if (searchSpecPtr->resPtr == NULL) {
+ searchSpecPtr->resPtr = Tcl_NewObj();
+ }
+ Tcl_ListObjAppendElement(NULL, searchSpecPtr->resPtr,
+ TkTextNewIndexObj(textPtr, &foundIndex));
+ } else {
+ searchSpecPtr->resPtr = TkTextNewIndexObj(textPtr, &foundIndex);
+ }
+
+ /*
+ * Find the end point. Here 'leftToScan' could be negative already as a
+ * result of the above loop if the segment we reached spanned the start of
+ * the string. When we add matchLength it will become non-negative.
+ */
+
+ for (leftToScan += matchLength; leftToScan > 0;
+ curIndex.byteIndex += segPtr->size, segPtr = segPtr->nextPtr) {
+ if (segPtr == NULL) {
+ /*
+ * We are on the next line - this of course should only ever
+ * happen with searches which have matched across multiple lines.
+ */
+
+ linePtr = TkBTreeNextLine(textPtr, linePtr);
+ segPtr = linePtr->segPtr;
+ curIndex.linePtr = linePtr; curIndex.byteIndex = 0;
+ }
+ if (segPtr->typePtr != &tkTextCharType) {
+ /*
+ * Anything we didn't count in the search needs adding.
+ */
+
+ numChars += segPtr->size;
+ continue;
+ } else if (!searchSpecPtr->searchElide
+ && TkTextIsElided(textPtr, &curIndex, NULL)) {
+ numChars += Tcl_NumUtfChars(segPtr->body.chars, -1);
+ continue;
+ }
+ if (searchSpecPtr->exact) {
+ leftToScan -= segPtr->size;
+ } else {
+ leftToScan -= Tcl_NumUtfChars(segPtr->body.chars, -1);
+ }
+ }
+
+ /*
+ * Now store the count result, if it is wanted.
+ */
+
+ if (searchSpecPtr->varPtr != NULL) {
+ Tcl_Obj *tmpPtr = Tcl_NewIntObj(numChars);
+ if (searchSpecPtr->all) {
+ if (searchSpecPtr->countPtr == NULL) {
+ searchSpecPtr->countPtr = Tcl_NewObj();
+ }
+ Tcl_ListObjAppendElement(NULL, searchSpecPtr->countPtr, tmpPtr);
+ } else {
+ searchSpecPtr->countPtr = tmpPtr;
+ }
+ }
+ return 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkTextGetTabs --
+ *
+ * Parses a string description of a set of tab stops.
+ *
+ * Results:
+ * The return value is a pointer to a malloc'ed structure holding parsed
+ * information about the tab stops. If an error occurred then the return
+ * value is NULL and an error message is left in the interp's result.
+ *
+ * Side effects:
+ * Memory is allocated for the structure that is returned. It is up to
+ * the caller to free this structure when it is no longer needed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkTextTabArray *
+TkTextGetTabs(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ TkText *textPtr, /* Information about the text widget. */
+ Tcl_Obj *stringPtr) /* Description of the tab stops. See the text
+ * manual entry for details. */
+{
+ int objc, i, count;
+ Tcl_Obj **objv;
+ TkTextTabArray *tabArrayPtr;
+ TkTextTab *tabPtr;
+ int ch;
+ double prevStop, lastStop;
+ /*
+ * Map these strings to TkTextTabAlign values.
+ */
+ static const char *const tabOptionStrings[] = {
+ "left", "right", "center", "numeric", NULL
+ };
+
+ if (Tcl_ListObjGetElements(interp, stringPtr, &objc, &objv) != TCL_OK) {
+ return NULL;
+ }
+
+ /*
+ * First find out how many entries we need to allocate in the tab array.
+ */
+
+ count = 0;
+ for (i = 0; i < objc; i++) {
+ char c = Tcl_GetString(objv[i])[0];
+
+ if ((c != 'l') && (c != 'r') && (c != 'c') && (c != 'n')) {
+ count++;
+ }
+ }
+
+ /*
+ * Parse the elements of the list one at a time to fill in the array.
+ */
+
+ tabArrayPtr = ckalloc(sizeof(TkTextTabArray)
+ + (count - 1) * sizeof(TkTextTab));
+ tabArrayPtr->numTabs = 0;
+ prevStop = 0.0;
+ lastStop = 0.0;
+ for (i = 0, tabPtr = &tabArrayPtr->tabs[0]; i < objc; i++, tabPtr++) {
+ int index;
+
+ /*
+ * This will round fractional pixels above 0.5 upwards, and otherwise
+ * downwards, to find the right integer pixel position.
+ */
+
+ if (Tk_GetPixelsFromObj(interp, textPtr->tkwin, objv[i],
+ &tabPtr->location) != TCL_OK) {
+ goto error;
+ }
+
+ if (tabPtr->location <= 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "tab stop \"%s\" is not at a positive distance",
+ Tcl_GetString(objv[i])));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "TAB_STOP", NULL);
+ goto error;
+ }
+
+ prevStop = lastStop;
+ if (Tk_GetDoublePixelsFromObj(interp, textPtr->tkwin, objv[i],
+ &lastStop) != TCL_OK) {
+ goto error;
+ }
+
+ if (i > 0 && (tabPtr->location <= (tabPtr-1)->location)) {
+ /*
+ * This tab is actually to the left of the previous one, which is
+ * illegal.
+ */
+
+#ifdef _TK_ALLOW_DECREASING_TABS
+ /*
+ * Force the tab to be a typical character width to the right of
+ * the previous one, and update the 'lastStop' with the changed
+ * position.
+ */
+
+ if (textPtr->charWidth > 0) {
+ tabPtr->location = (tabPtr-1)->location + textPtr->charWidth;
+ } else {
+ tabPtr->location = (tabPtr-1)->location + 8;
+ }
+ lastStop = tabPtr->location;
+#else
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "tabs must be monotonically increasing, but \"%s\" is "
+ "smaller than or equal to the previous tab",
+ Tcl_GetString(objv[i])));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "TAB_STOP", NULL);
+ goto error;
+#endif /* _TK_ALLOW_DECREASING_TABS */
+ }
+
+ tabArrayPtr->numTabs++;
+
+ /*
+ * See if there is an explicit alignment in the next list element.
+ * Otherwise just use "left".
+ */
+
+ tabPtr->alignment = LEFT;
+ if ((i+1) == objc) {
+ continue;
+ }
+
+ /*
+ * There may be a more efficient way of getting this.
+ */
+
+ TkUtfToUniChar(Tcl_GetString(objv[i+1]), &ch);
+ if (!Tcl_UniCharIsAlpha(ch)) {
+ continue;
+ }
+ i += 1;
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[i], tabOptionStrings,
+ sizeof(char *), "tab alignment", 0, &index) != TCL_OK) {
+ goto error;
+ }
+ tabPtr->alignment = (TkTextTabAlign) index;
+ }
+
+ /*
+ * For when we need to interpolate tab stops, store these two so we know
+ * the tab stop size to very high precision. With the above checks, we can
+ * guarantee that tabIncrement is strictly positive here.
+ */
+
+ tabArrayPtr->lastTab = lastStop;
+ tabArrayPtr->tabIncrement = lastStop - prevStop;
+
+ return tabArrayPtr;
+
+ error:
+ ckfree(tabArrayPtr);
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TextDumpCmd --
+ *
+ * Return information about the text, tags, marks, and embedded windows
+ * and images in a text widget. See the man page for the description of
+ * the text dump operation for all the details.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * Memory is allocated for the result, if needed (standard Tcl result
+ * side effects).
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TextDumpCmd(
+ register TkText *textPtr, /* Information about text widget. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. Someone else has already
+ * parsed this command enough to know that
+ * objv[1] is "dump". */
+{
+ TkTextIndex index1, index2;
+ int arg;
+ int lineno; /* Current line number. */
+ int what = 0; /* bitfield to select segment types. */
+ int atEnd; /* True if dumping up to logical end. */
+ TkTextLine *linePtr;
+ Tcl_Obj *command = NULL; /* Script callback to apply to segments. */
+#define TK_DUMP_TEXT 0x1
+#define TK_DUMP_MARK 0x2
+#define TK_DUMP_TAG 0x4
+#define TK_DUMP_WIN 0x8
+#define TK_DUMP_IMG 0x10
+#define TK_DUMP_ALL (TK_DUMP_TEXT|TK_DUMP_MARK|TK_DUMP_TAG| \
+ TK_DUMP_WIN|TK_DUMP_IMG)
+ static const char *const optStrings[] = {
+ "-all", "-command", "-image", "-mark", "-tag", "-text", "-window",
+ NULL
+ };
+ enum opts {
+ DUMP_ALL, DUMP_CMD, DUMP_IMG, DUMP_MARK, DUMP_TAG, DUMP_TXT, DUMP_WIN
+ };
+
+ for (arg=2 ; arg < objc ; arg++) {
+ int index;
+ if (Tcl_GetString(objv[arg])[0] != '-') {
+ break;
+ }
+ if (Tcl_GetIndexFromObjStruct(interp, objv[arg], optStrings,
+ sizeof(char *), "option", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch ((enum opts) index) {
+ case DUMP_ALL:
+ what = TK_DUMP_ALL;
+ break;
+ case DUMP_TXT:
+ what |= TK_DUMP_TEXT;
+ break;
+ case DUMP_TAG:
+ what |= TK_DUMP_TAG;
+ break;
+ case DUMP_MARK:
+ what |= TK_DUMP_MARK;
+ break;
+ case DUMP_IMG:
+ what |= TK_DUMP_IMG;
+ break;
+ case DUMP_WIN:
+ what |= TK_DUMP_WIN;
+ break;
+ case DUMP_CMD:
+ arg++;
+ if (arg >= objc) {
+ goto wrongArgs;
+ }
+ command = objv[arg];
+ break;
+ default:
+ Tcl_Panic("unexpected switch fallthrough");
+ }
+ }
+ if (arg >= objc || arg+2 < objc) {
+ wrongArgs:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "Usage: %s dump ?-all -image -text -mark -tag -window? "
+ "?-command script? index ?index2?", Tcl_GetString(objv[0])));
+ Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL);
+ return TCL_ERROR;
+ }
+ if (what == 0) {
+ what = TK_DUMP_ALL;
+ }
+ if (TkTextGetObjIndex(interp, textPtr, objv[arg], &index1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ arg++;
+ atEnd = 0;
+ if (objc == arg) {
+ TkTextIndexForwChars(NULL, &index1, 1, &index2, COUNT_INDICES);
+ } else {
+ size_t length;
+ const char *str;
+
+ if (TkTextGetObjIndex(interp, textPtr, objv[arg], &index2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ str = Tcl_GetString(objv[arg]);
+ length = objv[arg]->length;
+ if (strncmp(str, "end", length) == 0) {
+ atEnd = 1;
+ }
+ }
+ if (TkTextIndexCmp(&index1, &index2) >= 0) {
+ return TCL_OK;
+ }
+ lineno = TkBTreeLinesTo(textPtr, index1.linePtr);
+ if (index1.linePtr == index2.linePtr) {
+ DumpLine(interp, textPtr, what, index1.linePtr,
+ index1.byteIndex, index2.byteIndex, lineno, command);
+ } else {
+ int textChanged;
+ int lineend = TkBTreeLinesTo(textPtr, index2.linePtr);
+ int endByteIndex = index2.byteIndex;
+
+ textChanged = DumpLine(interp, textPtr, what, index1.linePtr,
+ index1.byteIndex, 32000000, lineno, command);
+ if (textChanged) {
+ if (textPtr->flags & DESTROYED) {
+ return TCL_OK;
+ }
+ linePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree,
+ textPtr, lineno);
+ textChanged = 0;
+ } else {
+ linePtr = index1.linePtr;
+ }
+ while ((linePtr = TkBTreeNextLine(textPtr, linePtr)) != NULL) {
+ lineno++;
+ if (lineno == lineend) {
+ break;
+ }
+ textChanged = DumpLine(interp, textPtr, what, linePtr, 0,
+ 32000000, lineno, command);
+ if (textChanged) {
+ if (textPtr->flags & DESTROYED) {
+ return TCL_OK;
+ }
+ linePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree,
+ textPtr, lineno);
+ textChanged = 0;
+ }
+ }
+ if (linePtr != NULL) {
+ DumpLine(interp, textPtr, what, linePtr, 0, endByteIndex, lineno,
+ command);
+ if (textPtr->flags & DESTROYED) {
+ return TCL_OK;
+ }
+ }
+ }
+
+ /*
+ * Special case to get the leftovers hiding at the end mark.
+ */
+
+ if (atEnd) {
+ if (textPtr->flags & DESTROYED) {
+ return TCL_OK;
+ }
+
+ /*
+ * Re-get the end index, in case it has changed.
+ */
+
+ if (TkTextGetObjIndex(interp, textPtr, objv[arg], &index2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ DumpLine(interp, textPtr, what & ~TK_DUMP_TEXT, index2.linePtr,
+ 0, 1, lineno, command);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DumpLine
+ *
+ * Return information about a given text line from character position
+ * "start" up to, but not including, "end".
+ *
+ * Results:
+ * Returns 1 if the command callback made any changes to the text widget
+ * which will have invalidated internal structures such as TkTextSegment,
+ * TkTextIndex, pointers. Our caller can then take action to recompute
+ * such entities. Returns 0 otherwise.
+ *
+ * Side effects:
+ * None, but see DumpSegment which can have arbitrary side-effects
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DumpLine(
+ Tcl_Interp *interp,
+ TkText *textPtr,
+ int what, /* Bit flags to select segment types. */
+ TkTextLine *linePtr, /* The current line. */
+ int startByte, int endByte, /* Byte range to dump. */
+ int lineno, /* Line number for indices dump. */
+ Tcl_Obj *command) /* Script to apply to the segment. */
+{
+ TkTextSegment *segPtr;
+ TkTextIndex index;
+ int offset = 0, textChanged = 0;
+
+ /*
+ * Must loop through line looking at its segments.
+ * character
+ * toggleOn, toggleOff
+ * mark
+ * image
+ * window
+ */
+
+ segPtr = linePtr->segPtr;
+ while ((offset < endByte) && (segPtr != NULL)) {
+ int lineChanged = 0;
+ int currentSize = segPtr->size;
+
+ if ((what & TK_DUMP_TEXT) && (segPtr->typePtr == &tkTextCharType) &&
+ (offset + currentSize > startByte)) {
+ int last = currentSize; /* Index of last char in seg. */
+ int first = 0; /* Index of first char in seg. */
+
+ if (offset + currentSize > endByte) {
+ last = endByte - offset;
+ }
+ if (startByte > offset) {
+ first = startByte - offset;
+ }
+ if (last != currentSize) {
+ /*
+ * To avoid modifying the string in place we copy over just
+ * the segment that we want. Since DumpSegment can modify the
+ * text, we could not confidently revert the modification
+ * here.
+ */
+
+ int length = last - first;
+ char *range = ckalloc(length + 1);
+
+ memcpy(range, segPtr->body.chars + first, length);
+ range[length] = '\0';
+
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,
+ lineno, offset + first, &index);
+ lineChanged = DumpSegment(textPtr, interp, "text", range,
+ command, &index, what);
+ ckfree(range);
+ } else {
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,
+ lineno, offset + first, &index);
+ lineChanged = DumpSegment(textPtr, interp, "text",
+ segPtr->body.chars + first, command, &index, what);
+ }
+ } else if ((offset >= startByte)) {
+ if ((what & TK_DUMP_MARK)
+ && (segPtr->typePtr == &tkTextLeftMarkType
+ || segPtr->typePtr == &tkTextRightMarkType)) {
+ const char *name;
+ TkTextMark *markPtr = &segPtr->body.mark;
+
+ if (segPtr == textPtr->insertMarkPtr) {
+ name = "insert";
+ } else if (segPtr == textPtr->currentMarkPtr) {
+ name = "current";
+ } else if (markPtr->hPtr == NULL) {
+ name = NULL;
+ lineChanged = 0;
+ } else {
+ name = Tcl_GetHashKey(&textPtr->sharedTextPtr->markTable,
+ markPtr->hPtr);
+ }
+ if (name != NULL) {
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,
+ lineno, offset, &index);
+ lineChanged = DumpSegment(textPtr, interp, "mark", name,
+ command, &index, what);
+ }
+ } else if ((what & TK_DUMP_TAG) &&
+ (segPtr->typePtr == &tkTextToggleOnType)) {
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,
+ lineno, offset, &index);
+ lineChanged = DumpSegment(textPtr, interp, "tagon",
+ segPtr->body.toggle.tagPtr->name, command, &index,
+ what);
+ } else if ((what & TK_DUMP_TAG) &&
+ (segPtr->typePtr == &tkTextToggleOffType)) {
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,
+ lineno, offset, &index);
+ lineChanged = DumpSegment(textPtr, interp, "tagoff",
+ segPtr->body.toggle.tagPtr->name, command, &index,
+ what);
+ } else if ((what & TK_DUMP_IMG) &&
+ (segPtr->typePtr == &tkTextEmbImageType)) {
+ TkTextEmbImage *eiPtr = &segPtr->body.ei;
+ const char *name = (eiPtr->name == NULL) ? "" : eiPtr->name;
+
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,
+ lineno, offset, &index);
+ lineChanged = DumpSegment(textPtr, interp, "image", name,
+ command, &index, what);
+ } else if ((what & TK_DUMP_WIN) &&
+ (segPtr->typePtr == &tkTextEmbWindowType)) {
+ TkTextEmbWindow *ewPtr = &segPtr->body.ew;
+ const char *pathname;
+
+ if (ewPtr->tkwin == NULL) {
+ pathname = "";
+ } else {
+ pathname = Tk_PathName(ewPtr->tkwin);
+ }
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,
+ lineno, offset, &index);
+ lineChanged = DumpSegment(textPtr, interp, "window", pathname,
+ command, &index, what);
+ }
+ }
+
+ offset += currentSize;
+ if (lineChanged) {
+ TkTextSegment *newSegPtr;
+ int newOffset = 0;
+
+ textChanged = 1;
+
+ /*
+ * Our indices are no longer valid.
+ */
+
+ if (textPtr->flags & DESTROYED) {
+ return textChanged;
+ }
+ linePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree,
+ textPtr, lineno);
+ newSegPtr = linePtr->segPtr;
+ if (segPtr != newSegPtr) {
+ while ((newOffset < endByte) && (newOffset < offset)
+ && (newSegPtr != NULL)) {
+ newOffset += currentSize;
+ newSegPtr = newSegPtr->nextPtr;
+ if (segPtr == newSegPtr) {
+ break;
+ }
+ }
+ if (segPtr != newSegPtr && newOffset == offset
+ && currentSize == 0) {
+ TkTextSegment *searchPtr = newSegPtr;
+
+ while (searchPtr != NULL && searchPtr->size == 0) {
+ if (searchPtr == segPtr) {
+ newSegPtr = searchPtr;
+ break;
+ }
+ searchPtr = searchPtr->nextPtr;
+ }
+ }
+ segPtr = newSegPtr;
+ }
+ }
+ if (segPtr != NULL) {
+ segPtr = segPtr->nextPtr;
+ }
+ }
+ return textChanged;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DumpSegment
+ *
+ * Either append information about the current segment to the result, or
+ * make a script callback with that information as arguments.
+ *
+ * Results:
+ * Returns 1 if the command callback made any changes to the text widget
+ * which will have invalidated internal structures such as TkTextSegment,
+ * TkTextIndex, pointers. Our caller can then take action to recompute
+ * such entities. Returns 0 otherwise.
+ *
+ * Side effects:
+ * Either evals the callback or appends elements to the result string.
+ * The callback can have arbitrary side-effects.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DumpSegment(
+ TkText *textPtr,
+ Tcl_Interp *interp,
+ const char *key, /* Segment type key. */
+ const char *value, /* Segment value. */
+ Tcl_Obj *command, /* Script callback. */
+ const TkTextIndex *index, /* index with line/byte position info. */
+ int what) /* Look for TK_DUMP_INDEX bit. */
+{
+ char buffer[TK_POS_CHARS];
+ Tcl_Obj *values[3], *tuple;
+
+ TkTextPrintIndex(textPtr, index, buffer);
+ values[0] = Tcl_NewStringObj(key, -1);
+ values[1] = Tcl_NewStringObj(value, -1);
+ values[2] = Tcl_NewStringObj(buffer, -1);
+ tuple = Tcl_NewListObj(3, values);
+ if (command == NULL) {
+ Tcl_ListObjAppendList(NULL, Tcl_GetObjResult(interp), tuple);
+ Tcl_DecrRefCount(tuple);
+ return 0;
+ } else {
+ int oldStateEpoch = TkBTreeEpoch(textPtr->sharedTextPtr->tree);
+ Tcl_DString buf;
+ int code;
+
+ Tcl_DStringInit(&buf);
+ Tcl_DStringAppend(&buf, Tcl_GetString(command), -1);
+ Tcl_DStringAppend(&buf, " ", -1);
+ Tcl_DStringAppend(&buf, Tcl_GetString(tuple), -1);
+ code = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0);
+ Tcl_DStringFree(&buf);
+ if (code != TCL_OK) {
+ Tcl_AddErrorInfo(interp,
+ "\n (segment dumping command executed by text)");
+ Tcl_BackgroundException(interp, code);
+ }
+ Tcl_DecrRefCount(tuple);
+ return ((textPtr->flags & DESTROYED) ||
+ TkBTreeEpoch(textPtr->sharedTextPtr->tree) != oldStateEpoch);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TextEditUndo --
+ *
+ * Undo the last change.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Apart from manipulating the undo and redo stacks, the state of the
+ * rest of the widget may also change (due to whatever is being undone).
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TextEditUndo(
+ TkText *textPtr) /* Overall information about text widget. */
+{
+ int status;
+
+ if (!textPtr->sharedTextPtr->undo) {
+ return TCL_OK;
+ }
+
+ /*
+ * Turn off the undo feature while we revert a compound action, setting
+ * the dirty handling mode to undo for the duration (unless it is
+ * 'fixed').
+ */
+
+ textPtr->sharedTextPtr->undo = 0;
+ if (textPtr->sharedTextPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) {
+ textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_UNDO;
+ }
+
+ status = TkUndoRevert(textPtr->sharedTextPtr->undoStack);
+
+ if (textPtr->sharedTextPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) {
+ textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL;
+ }
+ textPtr->sharedTextPtr->undo = 1;
+
+ return status;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TextEditRedo --
+ *
+ * Redo the last undone change.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Apart from manipulating the undo and redo stacks, the state of the
+ * rest of the widget may also change (due to whatever is being redone).
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TextEditRedo(
+ TkText *textPtr) /* Overall information about text widget. */
+{
+ int status;
+
+ if (!textPtr->sharedTextPtr->undo) {
+ return TCL_OK;
+ }
+
+ /*
+ * Turn off the undo feature temporarily while we revert a previously
+ * undone compound action, setting the dirty handling mode to redo for the
+ * duration (unless it is 'fixed').
+ */
+
+ textPtr->sharedTextPtr->undo = 0;
+ if (textPtr->sharedTextPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) {
+ textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_REDO;
+ }
+
+ status = TkUndoApply(textPtr->sharedTextPtr->undoStack);
+
+ if (textPtr->sharedTextPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) {
+ textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL;
+ }
+ textPtr->sharedTextPtr->undo = 1;
+ return status;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TextEditCmd --
+ *
+ * Handle the subcommands to "$text edit ...". See documentation for
+ * details.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TextEditCmd(
+ TkText *textPtr, /* Information about text widget. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ int index, setModified, oldModified;
+ int canRedo = 0;
+ int canUndo = 0;
+
+ static const char *const editOptionStrings[] = {
+ "canundo", "canredo", "modified", "redo", "reset", "separator",
+ "undo", NULL
+ };
+ enum editOptions {
+ EDIT_CANUNDO, EDIT_CANREDO, EDIT_MODIFIED, EDIT_REDO, EDIT_RESET,
+ EDIT_SEPARATOR, EDIT_UNDO
+ };
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[2], editOptionStrings,
+ sizeof(char *), "edit option", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch ((enum editOptions) index) {
+ case EDIT_CANREDO:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ return TCL_ERROR;
+ }
+ if (textPtr->sharedTextPtr->undo) {
+ canRedo = TkUndoCanRedo(textPtr->sharedTextPtr->undoStack);
+ }
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(canRedo));
+ break;
+ case EDIT_CANUNDO:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ return TCL_ERROR;
+ }
+ if (textPtr->sharedTextPtr->undo) {
+ canUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack);
+ }
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(canUndo));
+ break;
+ case EDIT_MODIFIED:
+ if (objc == 3) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewBooleanObj(textPtr->sharedTextPtr->isDirty));
+ return TCL_OK;
+ } else if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "?boolean?");
+ return TCL_ERROR;
+ } else if (Tcl_GetBooleanFromObj(interp, objv[3],
+ &setModified) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Set or reset the dirty info, and trigger a Modified event.
+ */
+
+ setModified = setModified ? 1 : 0;
+
+ oldModified = textPtr->sharedTextPtr->isDirty;
+ textPtr->sharedTextPtr->isDirty = setModified;
+ if (setModified) {
+ textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_FIXED;
+ } else {
+ textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL;
+ }
+
+ /*
+ * Only issue the <<Modified>> event if the flag actually changed.
+ * However, degree of modified-ness doesn't matter. [Bug 1799782]
+ */
+
+ if ((!oldModified) != (!setModified)) {
+ GenerateModifiedEvent(textPtr);
+ }
+ break;
+ case EDIT_REDO:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ return TCL_ERROR;
+ }
+ canUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack);
+ if (TextEditRedo(textPtr)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("nothing to redo", -1));
+ Tcl_SetErrorCode(interp, "TK", "TEXT", "NO_REDO", NULL);
+ return TCL_ERROR;
+ }
+ canRedo = TkUndoCanRedo(textPtr->sharedTextPtr->undoStack);
+ if (!canUndo || !canRedo) {
+ GenerateUndoStackEvent(textPtr);
+ }
+ break;
+ case EDIT_RESET:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ return TCL_ERROR;
+ }
+ canUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack);
+ canRedo = TkUndoCanRedo(textPtr->sharedTextPtr->undoStack);
+ TkUndoClearStacks(textPtr->sharedTextPtr->undoStack);
+ if (canUndo || canRedo) {
+ GenerateUndoStackEvent(textPtr);
+ }
+ break;
+ case EDIT_SEPARATOR:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ return TCL_ERROR;
+ }
+ TkUndoInsertUndoSeparator(textPtr->sharedTextPtr->undoStack);
+ break;
+ case EDIT_UNDO:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ return TCL_ERROR;
+ }
+ canRedo = TkUndoCanRedo(textPtr->sharedTextPtr->undoStack);
+ if (TextEditUndo(textPtr)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("nothing to undo", -1));
+ Tcl_SetErrorCode(interp, "TK", "TEXT", "NO_UNDO", NULL);
+ return TCL_ERROR;
+ }
+ canUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack);
+ if (!canRedo || !canUndo) {
+ GenerateUndoStackEvent(textPtr);
+ }
+ break;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TextGetText --
+ *
+ * Returns the text from indexPtr1 to indexPtr2, placing that text in a
+ * string object which is returned with a refCount of zero.
+ *
+ * Since the amount of text may potentially be several megabytes (e.g.
+ * in text editors built on the text widget), efficiency is very
+ * important. We may want to investigate the efficiency of the
+ * Tcl_AppendToObj more carefully (e.g. if we know we are going to be
+ * appending several thousand lines, we could attempt to pre-allocate a
+ * larger space).
+ *
+ * Also the result is built up as a utf-8 string, but, if we knew we
+ * wanted it as Unicode, we could potentially save a huge conversion by
+ * building it up as Unicode directly. This could be as simple as
+ * replacing Tcl_NewObj by Tcl_NewUnicodeObj.
+ *
+ * Results:
+ * Tcl_Obj of string type containing the specified text. If the
+ * visibleOnly flag is set to 1, then only those characters which are not
+ * elided will be returned. Otherwise (flag is 0) all characters in the
+ * given range are returned.
+ *
+ * Side effects:
+ * Memory will be allocated for the new object. Remember to free it if it
+ * isn't going to be stored appropriately.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj *
+TextGetText(
+ const TkText *textPtr, /* Information about text widget. */
+ const TkTextIndex *indexPtr1,
+ /* Get text from this index... */
+ const TkTextIndex *indexPtr2,
+ /* ...to this index. */
+ int visibleOnly) /* If non-zero, then only return non-elided
+ * characters. */
+{
+ TkTextIndex tmpIndex;
+ Tcl_Obj *resultPtr = Tcl_NewObj();
+
+ TkTextMakeByteIndex(indexPtr1->tree, textPtr,
+ TkBTreeLinesTo(textPtr, indexPtr1->linePtr),
+ indexPtr1->byteIndex, &tmpIndex);
+
+ if (TkTextIndexCmp(indexPtr1, indexPtr2) < 0) {
+ while (1) {
+ int offset;
+ TkTextSegment *segPtr = TkTextIndexToSeg(&tmpIndex, &offset);
+ int last = segPtr->size, last2;
+
+ if (tmpIndex.linePtr == indexPtr2->linePtr) {
+ /*
+ * The last line that was requested must be handled carefully,
+ * because we may need to break out of this loop in the middle
+ * of the line.
+ */
+
+ if (indexPtr2->byteIndex == tmpIndex.byteIndex) {
+ break;
+ }
+ last2 = indexPtr2->byteIndex - tmpIndex.byteIndex + offset;
+ if (last2 < last) {
+ last = last2;
+ }
+ }
+ if (segPtr->typePtr == &tkTextCharType &&
+ !(visibleOnly && TkTextIsElided(textPtr,&tmpIndex,NULL))){
+ Tcl_AppendToObj(resultPtr, segPtr->body.chars + offset,
+ last - offset);
+ }
+ TkTextIndexForwBytes(textPtr, &tmpIndex, last-offset, &tmpIndex);
+ }
+ }
+ return resultPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GenerateModifiedEvent --
+ *
+ * Send an event that the text was modified. This is equivalent to:
+ * event generate $textWidget <<Modified>>
+ * for all peers of $textWidget.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * May force the text window into existence.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GenerateModifiedEvent(
+ TkText *textPtr) /* Information about text widget. */
+{
+ for (textPtr = textPtr->sharedTextPtr->peers; textPtr != NULL;
+ textPtr = textPtr->next) {
+ Tk_MakeWindowExist(textPtr->tkwin);
+ TkSendVirtualEvent(textPtr->tkwin, "Modified", NULL);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GenerateUndoStackEvent --
+ *
+ * Send an event that the undo or redo stack became empty or unempty.
+ * This is equivalent to:
+ * event generate $textWidget <<UndoStack>>
+ * for all peers of $textWidget.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * May force the text window (and all peers) into existence.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GenerateUndoStackEvent(
+ TkText *textPtr) /* Information about text widget. */
+{
+ for (textPtr = textPtr->sharedTextPtr->peers; textPtr != NULL;
+ textPtr = textPtr->next) {
+ Tk_MakeWindowExist(textPtr->tkwin);
+ TkSendVirtualEvent(textPtr->tkwin, "UndoStack", NULL);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UpdateDirtyFlag --
+ *
+ * Updates the dirtyness of the text widget
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UpdateDirtyFlag(
+ TkSharedText *sharedTextPtr)/* Information about text widget. */
+{
+ int oldDirtyFlag;
+
+ /*
+ * If we've been forced to be dirty, we stay dirty (until explicitly
+ * reset, of course).
+ */
+
+ if (sharedTextPtr->dirtyMode == TK_TEXT_DIRTY_FIXED) {
+ return;
+ }
+
+ if (sharedTextPtr->isDirty < 0
+ && sharedTextPtr->dirtyMode == TK_TEXT_DIRTY_NORMAL) {
+ /*
+ * If dirty flag is negative, only redo operations can make it zero
+ * again. If we do a normal operation, it can never become zero any
+ * more (other than by explicit reset).
+ */
+
+ sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_FIXED;
+ return;
+ }
+
+ oldDirtyFlag = sharedTextPtr->isDirty;
+ if (sharedTextPtr->dirtyMode == TK_TEXT_DIRTY_UNDO) {
+ sharedTextPtr->isDirty--;
+ } else {
+ sharedTextPtr->isDirty++;
+ }
+
+ if (sharedTextPtr->isDirty == 0 || oldDirtyFlag == 0) {
+ GenerateModifiedEvent(sharedTextPtr->peers);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkTextRunAfterSyncCmd --
+ *
+ * This function is called by the event loop and executes the command
+ * scheduled by [.text sync -command $cmd].
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Anything may happen, depending on $cmd contents.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkTextRunAfterSyncCmd(
+ ClientData clientData) /* Information about text widget. */
+{
+ register TkText *textPtr = (TkText *) clientData;
+ int code;
+
+ if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) {
+ /*
+ * The widget has been deleted. Don't do anything.
+ */
+
+ if (textPtr->refCount-- <= 1) {
+ ckfree((char *) textPtr);
+ }
+ return;
+ }
+
+ Tcl_Preserve((ClientData) textPtr->interp);
+ code = Tcl_EvalObjEx(textPtr->interp, textPtr->afterSyncCmd, TCL_EVAL_GLOBAL);
+ if (code == TCL_ERROR) {
+ Tcl_AddErrorInfo(textPtr->interp, "\n (text sync)");
+ Tcl_BackgroundError(textPtr->interp);
+ }
+ Tcl_Release((ClientData) textPtr->interp);
+ Tcl_DecrRefCount(textPtr->afterSyncCmd);
+ textPtr->afterSyncCmd = NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SearchPerform --
+ *
+ * Overall control of search process. Is given a pattern, a starting
+ * index and an ending index, and attempts to perform a search. This
+ * function is actually completely independent of Tk, and could in the
+ * future be split off.
+ *
+ * Results:
+ * Standard Tcl result code. In particular, if fromPtr or toPtr are not
+ * considered valid by the 'lineIndexProc', an error will be thrown and
+ * no search performed.
+ *
+ * Side effects:
+ * See 'SearchCore'.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SearchPerform(
+ Tcl_Interp *interp, /* For error messages. */
+ SearchSpec *searchSpecPtr, /* Search parameters. */
+ Tcl_Obj *patObj, /* Contains an exact string or a regexp
+ * pattern. Must have a refCount > 0. */
+ Tcl_Obj *fromPtr, /* Contains information describing the first
+ * index. */
+ Tcl_Obj *toPtr) /* NULL or information describing the last
+ * index. */
+{
+ /*
+ * Find the starting line and starting offset (measured in Unicode chars
+ * for regexp search, utf-8 bytes for exact search).
+ */
+
+ if (searchSpecPtr->lineIndexProc(interp, fromPtr, searchSpecPtr,
+ &searchSpecPtr->startLine,
+ &searchSpecPtr->startOffset) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Find the optional end location, similarly.
+ */
+
+ if (toPtr != NULL) {
+ const TkTextIndex *indexToPtr, *indexFromPtr;
+ TkText *textPtr = searchSpecPtr->clientData;
+
+ indexToPtr = TkTextGetIndexFromObj(interp, textPtr, toPtr);
+ if (indexToPtr == NULL) {
+ return TCL_ERROR;
+ }
+ indexFromPtr = TkTextGetIndexFromObj(interp, textPtr, fromPtr);
+
+ /*
+ * Check for any empty search range here. It might be better in the
+ * future to embed that in SearchCore (whose default behaviour is to
+ * wrap when given a negative search range).
+ */
+
+ if (TkTextIndexCmp(indexFromPtr, indexToPtr) ==
+ (searchSpecPtr->backwards ? -1 : 1)) {
+ return TCL_OK;
+ }
+
+ if (searchSpecPtr->lineIndexProc(interp, toPtr, searchSpecPtr,
+ &searchSpecPtr->stopLine,
+ &searchSpecPtr->stopOffset) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ } else {
+ searchSpecPtr->stopLine = -1;
+ }
+
+ /*
+ * Scan through all of the lines of the text circularly, starting at the
+ * given index. 'patObj' is the pattern which may be an exact string or a
+ * regexp pattern depending on the flags in searchSpecPtr.
+ */
+
+ return SearchCore(interp, searchSpecPtr, patObj);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SearchCore --
+ *
+ * The core of the search function. This function is actually completely
+ * independent of Tk, and could in the future be split off.
+ *
+ * The function assumes regexp-based searches operate on Unicode strings,
+ * and exact searches on utf-8 strings. Therefore the 'foundMatchProc'
+ * and 'addLineProc' need to be aware of this distinction.
+ *
+ * Results:
+ * Standard Tcl result code.
+ *
+ * Side effects:
+ * Only those of the 'searchSpecPtr->foundMatchProc' which is called
+ * whenever a match is found.
+ *
+ * Note that the way matching across multiple lines is implemented, we
+ * start afresh with each line we have available, even though we may
+ * already have examined the contents of that line (and further ones) if
+ * we were attempting a multi-line match using the previous line. This
+ * means there may be ways to speed this up a lot by not throwing away
+ * all the multi-line information one has accumulated. Profiling should
+ * be done to see where the bottlenecks lie before attempting this,
+ * however. We would also need to be very careful such optimisation keep
+ * within the specified search bounds.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SearchCore(
+ Tcl_Interp *interp, /* For error messages. */
+ SearchSpec *searchSpecPtr, /* Search parameters. */
+ Tcl_Obj *patObj) /* Contains an exact string or a regexp
+ * pattern. Must have a refCount > 0. */
+{
+ /*
+ * For exact searches these are utf-8 char* offsets, for regexp searches
+ * they are Unicode char offsets.
+ */
+
+ int firstOffset, lastOffset, matchOffset, matchLength;
+ int passes;
+ int lineNum = searchSpecPtr->startLine;
+ int code = TCL_OK;
+ Tcl_Obj *theLine;
+ int alreadySearchOffset = -1;
+
+ const char *pattern = NULL; /* For exact searches only. */
+ int firstNewLine = -1; /* For exact searches only. */
+ Tcl_RegExp regexp = NULL; /* For regexp searches only. */
+
+ /*
+ * These items are for backward regexp searches only. They are for two
+ * purposes: to allow us to report backwards matches in the correct order,
+ * even though the implementation uses repeated forward searches; and to
+ * provide for overlap checking between backwards matches on different
+ * text lines.
+ */
+
+#define LOTS_OF_MATCHES 20
+ int matchNum = LOTS_OF_MATCHES;
+ int smArray[2 * LOTS_OF_MATCHES];
+ int *storeMatch = smArray;
+ int *storeLength = smArray + LOTS_OF_MATCHES;
+ int lastBackwardsLineMatch = -1;
+ int lastBackwardsMatchOffset = -1;
+
+ if (searchSpecPtr->exact) {
+ /*
+ * Convert the pattern to lower-case if we're supposed to ignore case.
+ */
+
+ if (searchSpecPtr->noCase) {
+ patObj = Tcl_DuplicateObj(patObj);
+
+ /*
+ * This can change the length of the string behind the object's
+ * back, so ensure it is correctly synchronised.
+ */
+
+ Tcl_SetObjLength(patObj, Tcl_UtfToLower(Tcl_GetString(patObj)));
+ }
+ } else {
+ /*
+ * Compile the regular expression. We want '^$' to match after and
+ * before \n respectively, so use the TCL_REG_NLANCH flag.
+ */
+
+ regexp = Tcl_GetRegExpFromObj(interp, patObj,
+ (searchSpecPtr->noCase ? TCL_REG_NOCASE : 0)
+ | (searchSpecPtr->noLineStop ? 0 : TCL_REG_NLSTOP)
+ | TCL_REG_ADVANCED | TCL_REG_CANMATCH | TCL_REG_NLANCH);
+ if (regexp == NULL) {
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * For exact strings, we want to know where the first newline is, and we
+ * will also use this as a flag to test whether it is even possible to
+ * match the pattern on a single line. If not we will have to search
+ * across multiple lines.
+ */
+
+ if (searchSpecPtr->exact) {
+ const char *nl;
+
+ /*
+ * We only need to set the matchLength once for exact searches, and we
+ * do it here. It is also used below as the actual pattern length, so
+ * it has dual purpose.
+ */
+
+ pattern = Tcl_GetString(patObj);
+ matchLength = patObj->length;
+ nl = strchr(pattern, '\n');
+
+ /*
+ * If there is no newline, or it is the very end of the string, then
+ * we don't need any special treatment, since single-line matching
+ * will work fine.
+ */
+
+ if (nl != NULL && nl[1] != '\0') {
+ firstNewLine = (nl - pattern);
+ }
+ } else {
+ matchLength = 0; /* Only needed to prevent compiler warnings. */
+ }
+
+ /*
+ * Keep a reference here, so that we can be sure the object doesn't
+ * disappear behind our backs and invalidate its contents which we are
+ * using.
+ */
+
+ Tcl_IncrRefCount(patObj);
+
+ /*
+ * For building up the current line being checked.
+ */
+
+ theLine = Tcl_NewObj();
+ Tcl_IncrRefCount(theLine);
+
+ for (passes = 0; passes < 2; ) {
+ ClientData lineInfo;
+ int linesSearched = 1;
+ int extraLinesSearched = 0;
+
+ if (lineNum >= searchSpecPtr->numLines) {
+ /*
+ * Don't search the dummy last line of the text.
+ */
+
+ goto nextLine;
+ }
+
+ /*
+ * Extract the text from the line, storing its length in 'lastOffset'
+ * (in bytes if exact, chars if regexp), since obviously the length is
+ * the maximum offset at which it is possible to find something on
+ * this line, which is what 'lastOffset' represents.
+ */
+
+ lineInfo = searchSpecPtr->addLineProc(lineNum, searchSpecPtr, theLine,
+ &lastOffset, &linesSearched);
+
+ if (lineInfo == NULL) {
+ /*
+ * This should not happen, since 'lineNum' should be valid in the
+ * call above. However, let's try to be flexible and not cause a
+ * crash below.
+ */
+
+ goto nextLine;
+ }
+
+ if (lineNum == searchSpecPtr->stopLine && searchSpecPtr->backwards) {
+ firstOffset = searchSpecPtr->stopOffset;
+ } else {
+ firstOffset = 0;
+ }
+
+ if (alreadySearchOffset >= 0) {
+ if (searchSpecPtr->backwards) {
+ if (alreadySearchOffset < lastOffset) {
+ lastOffset = alreadySearchOffset;
+ }
+ } else {
+ if (alreadySearchOffset > firstOffset) {
+ firstOffset = alreadySearchOffset;
+ }
+ }
+ alreadySearchOffset = -1;
+ }
+
+ if (lineNum == searchSpecPtr->startLine) {
+ /*
+ * The starting line is tricky: the first time we see it we check
+ * one part of the line, and the second pass through we check the
+ * other part of the line.
+ */
+
+ passes++;
+ if ((passes == 1) ^ searchSpecPtr->backwards) {
+ /*
+ * Forward search and first pass, or backward search and
+ * second pass.
+ *
+ * Only use the last part of the line.
+ */
+
+ if (searchSpecPtr->startOffset > firstOffset) {
+ firstOffset = searchSpecPtr->startOffset;
+ }
+ if ((firstOffset >= lastOffset)
+ && ((lastOffset != 0) || searchSpecPtr->exact)) {
+ goto nextLine;
+ }
+ } else {
+ /*
+ * Use only the first part of the line.
+ */
+
+ if (searchSpecPtr->startOffset < lastOffset) {
+ lastOffset = searchSpecPtr->startOffset;
+ }
+ }
+ }
+
+ /*
+ * Check for matches within the current line 'lineNum'. If so, and if
+ * we're searching backwards or for all matches, repeat the search
+ * until we find the last match in the line. The 'lastOffset' is one
+ * beyond the last position in the line at which a match is allowed to
+ * begin.
+ */
+
+ matchOffset = -1;
+
+ if (searchSpecPtr->exact) {
+ int maxExtraLines = 0;
+ const char *startOfLine = Tcl_GetString(theLine);
+
+ CLANG_ASSERT(pattern);
+ do {
+ int ch;
+ const char *p;
+ int lastFullLine = lastOffset;
+
+ if (firstNewLine == -1) {
+ if (searchSpecPtr->strictLimits
+ && (firstOffset + matchLength > lastOffset)) {
+ /*
+ * Not enough characters to match.
+ */
+
+ break;
+ }
+
+ /*
+ * Single line matching. We want to scan forwards or
+ * backwards as appropriate.
+ */
+
+ if (searchSpecPtr->backwards) {
+ /*
+ * Search back either from the previous match or from
+ * 'startOfLine + lastOffset - 1' until we find a
+ * match.
+ */
+
+ const char c = matchLength ? pattern[0] : '\0';
+
+ if (alreadySearchOffset >= 0) {
+ p = startOfLine + alreadySearchOffset;
+ alreadySearchOffset = -1;
+ } else {
+ p = startOfLine + lastOffset -1;
+ }
+ while (p >= startOfLine + firstOffset) {
+ if (matchLength == 0 || (p[0] == c && !strncmp(
+ p, pattern, (size_t) matchLength))) {
+ goto backwardsMatch;
+ }
+ p--;
+ }
+ break;
+ } else {
+ p = strstr(startOfLine + firstOffset, pattern);
+ }
+ if (p == NULL) {
+ /*
+ * Single line match failed.
+ */
+
+ break;
+ }
+ } else if (firstNewLine >= (lastOffset - firstOffset)) {
+ /*
+ * Multi-line match, but not enough characters to match.
+ */
+
+ break;
+ } else {
+ /*
+ * Multi-line match has only one possible match position,
+ * because we know where the '\n' is.
+ */
+
+ p = startOfLine + lastOffset - firstNewLine - 1;
+ if (strncmp(p, pattern, (unsigned) firstNewLine + 1)) {
+ /*
+ * No match.
+ */
+
+ break;
+ } else {
+ int extraLines = 1;
+
+ /*
+ * If we find a match that overlaps more than one
+ * line, we will use this value to determine the first
+ * allowed starting offset for the following search
+ * (to avoid overlapping results).
+ */
+
+ int lastTotal = lastOffset;
+ int skipFirst = lastOffset - firstNewLine -1;
+
+ /*
+ * We may be able to match if given more text. The
+ * following 'while' block handles multi-line exact
+ * searches.
+ */
+
+ while (1) {
+ lastFullLine = lastTotal;
+
+ if (lineNum+extraLines>=searchSpecPtr->numLines) {
+ p = NULL;
+ break;
+ }
+
+ /*
+ * Only add the line if we haven't already done so
+ * already.
+ */
+
+ if (extraLines > maxExtraLines) {
+ if (searchSpecPtr->addLineProc(lineNum
+ + extraLines, searchSpecPtr, theLine,
+ &lastTotal, &extraLines) == NULL) {
+ p = NULL;
+ if (!searchSpecPtr->backwards) {
+ extraLinesSearched = extraLines;
+ }
+ break;
+ }
+ maxExtraLines = extraLines;
+ }
+
+ startOfLine = Tcl_GetString(theLine);
+ p = startOfLine + skipFirst;
+
+ /*
+ * Use the fact that 'matchLength = patLength' for
+ * exact searches.
+ */
+
+ if ((lastTotal - skipFirst) >= matchLength) {
+ /*
+ * We now have enough text to match, so we
+ * make a final test and break whatever the
+ * result.
+ */
+
+ if (strncmp(p,pattern,(size_t)matchLength)) {
+ p = NULL;
+ }
+ break;
+ } else {
+ /*
+ * Not enough text yet, but check the prefix.
+ */
+
+ if (strncmp(p, pattern,
+ (unsigned)(lastTotal - skipFirst))) {
+ p = NULL;
+ break;
+ }
+
+ /*
+ * The prefix matches, so keep looking.
+ */
+ }
+ extraLines++;
+ }
+ /*
+ * If we reach here, with p != NULL, we've found a
+ * multi-line match, else we started a multi-match but
+ * didn't finish it off, so we go to the next line.
+ */
+
+ if (p == NULL) {
+ break;
+ }
+
+ /*
+ * We've found a multi-line match.
+ */
+
+ if (extraLines > 0) {
+ extraLinesSearched = extraLines - 1;
+ }
+ }
+ }
+
+ backwardsMatch:
+ if ((p - startOfLine) >= lastOffset) {
+ break;
+ }
+
+ /*
+ * Remember the match.
+ */
+
+ matchOffset = p - startOfLine;
+
+ if (searchSpecPtr->all &&
+ !searchSpecPtr->foundMatchProc(lineNum, searchSpecPtr,
+ lineInfo, theLine, matchOffset, matchLength)) {
+ /*
+ * We reached the end of the search.
+ */
+
+ goto searchDone;
+ }
+
+ if (!searchSpecPtr->overlap) {
+ if (searchSpecPtr->backwards) {
+ alreadySearchOffset = p - startOfLine;
+ if (firstNewLine != -1) {
+ break;
+ } else {
+ alreadySearchOffset -= (matchLength ? matchLength : 1);
+ if (alreadySearchOffset < 0) {
+ break;
+ }
+ }
+ } else {
+ firstOffset = matchLength ? p - startOfLine + matchLength
+ : p - startOfLine + 1;
+ if (firstOffset >= lastOffset) {
+ /*
+ * Now, we have to be careful not to find
+ * overlapping matches either on the same or
+ * following lines. Assume that if we did find
+ * something, it goes until the last extra line we
+ * added.
+ *
+ * We can break out of the loop, since we know no
+ * more will be found.
+ */
+
+ if (!searchSpecPtr->backwards) {
+ alreadySearchOffset =
+ firstOffset - lastFullLine;
+ break;
+ }
+ }
+ }
+ } else {
+ if (searchSpecPtr->backwards) {
+ alreadySearchOffset = p - startOfLine - 1;
+ if (alreadySearchOffset < 0) {
+ break;
+ }
+ } else {
+ firstOffset = p - startOfLine +
+ TkUtfToUniChar(startOfLine+matchOffset,&ch);
+ }
+ }
+ } while (searchSpecPtr->all);
+ } else {
+ int maxExtraLines = 0;
+ int matches = 0;
+ int lastNonOverlap = -1;
+
+ do {
+ Tcl_RegExpInfo info;
+ int match;
+ int lastFullLine = lastOffset;
+
+ match = Tcl_RegExpExecObj(interp, regexp, theLine,
+ firstOffset, 1, (firstOffset>0 ? TCL_REG_NOTBOL : 0));
+ if (match < 0) {
+ code = TCL_ERROR;
+ goto searchDone;
+ }
+ Tcl_RegExpGetInfo(regexp, &info);
+
+ /*
+ * If we don't have a match, or if we do, but it extends to
+ * the end of the line, we must try to add more lines to get a
+ * full greedy match.
+ */
+
+ if (!match ||
+ ((info.extendStart == info.matches[0].start)
+ && (info.matches[0].end == lastOffset-firstOffset))) {
+ int extraLines = 0;
+ int prevFullLine;
+
+ /*
+ * If we find a match that overlaps more than one line, we
+ * will use this value to determine the first allowed
+ * starting offset for the following search (to avoid
+ * overlapping results).
+ */
+
+ int lastTotal = lastOffset;
+
+ if ((lastBackwardsLineMatch != -1)
+ && (lastBackwardsLineMatch == (lineNum + 1))) {
+ lastNonOverlap = lastTotal;
+ }
+
+ if (info.extendStart < 0) {
+ /*
+ * No multi-line match is possible.
+ */
+
+ break;
+ }
+
+ /*
+ * We may be able to match if given more text. The
+ * following 'while' block handles multi-line regexp
+ * searches.
+ */
+
+ while (1) {
+ prevFullLine = lastTotal;
+
+ /*
+ * Move firstOffset to first possible start.
+ */
+
+ if (!match) {
+ firstOffset += info.extendStart;
+ }
+ if (firstOffset >= lastOffset) {
+ /*
+ * We're being told that the only possible new
+ * match is starting after the end of the line.
+ * But, that is the next line which we will handle
+ * when we look at that line.
+ */
+
+ if (!match && !searchSpecPtr->backwards
+ && (firstOffset == 0)) {
+ extraLinesSearched = extraLines;
+ }
+ break;
+ }
+
+ if (lineNum + extraLines >= searchSpecPtr->numLines) {
+ break;
+ }
+
+ /*
+ * Add next line, provided we haven't already done so.
+ */
+
+ if (extraLines > maxExtraLines) {
+ if (searchSpecPtr->addLineProc(lineNum
+ + extraLines, searchSpecPtr, theLine,
+ &lastTotal, &extraLines) == NULL) {
+ /*
+ * There are no more acceptable lines, so we
+ * can say we have searched all of these.
+ */
+
+ if (!match && !searchSpecPtr->backwards) {
+ extraLinesSearched = extraLines;
+ }
+ break;
+ }
+
+ maxExtraLines = extraLines;
+ if ((lastBackwardsLineMatch != -1)
+ && (lastBackwardsLineMatch
+ == (lineNum + extraLines + 1))) {
+ lastNonOverlap = lastTotal;
+ }
+ }
+
+ match = Tcl_RegExpExecObj(interp, regexp, theLine,
+ firstOffset, 1,
+ ((firstOffset > 0) ? TCL_REG_NOTBOL : 0));
+ if (match < 0) {
+ code = TCL_ERROR;
+ goto searchDone;
+ }
+ Tcl_RegExpGetInfo(regexp, &info);
+
+ /*
+ * Unfortunately there are bugs in Tcl's regexp
+ * library, which tells us that info.extendStart is
+ * zero when it should not be (should be -1), which
+ * makes our task a bit more complicated here. We
+ * check if there was a match, and the end of the
+ * match leaves an entire extra line unmatched, then
+ * we stop searching. Clearly it still might sometimes
+ * be possible to add more text and match again, but
+ * Tcl's regexp library doesn't tell us that.
+ *
+ * This means we often add and search one more line
+ * than might be necessary if Tcl were able to give us
+ * a correct value of info.extendStart under all
+ * circumstances.
+ */
+
+ if ((match &&
+ firstOffset+info.matches[0].end != lastTotal &&
+ firstOffset+info.matches[0].end < prevFullLine)
+ || info.extendStart < 0) {
+ break;
+ }
+
+ /*
+ * If there is a match, but that match starts after
+ * the end of the first line, then we'll handle that
+ * next time around, when we're actually looking at
+ * that line.
+ */
+
+ if (match && (info.matches[0].start >= lastOffset)) {
+ break;
+ }
+ if (match && ((firstOffset + info.matches[0].end)
+ >= prevFullLine)) {
+ if (extraLines > 0) {
+ extraLinesSearched = extraLines - 1;
+ }
+ lastFullLine = prevFullLine;
+ }
+
+ /*
+ * The prefix matches, so keep looking.
+ */
+
+ extraLines++;
+ }
+
+ /*
+ * If we reach here with 'match == 1', we've found a
+ * multi-line match, which we will record in the code
+ * which follows directly else we started a multi-line
+ * match but didn't finish it off, so we go to the next
+ * line.
+ */
+
+ if (!match) {
+ /*
+ * Here is where we could perform an optimisation,
+ * since we have already retrieved the contents of the
+ * next line (perhaps many more), so we shouldn't
+ * really throw it all away and start again. This
+ * could be particularly important for complex regexp
+ * searches.
+ *
+ * This 'break' will take us to just before the
+ * 'nextLine:' below.
+ */
+
+ break;
+ }
+
+ if (lastBackwardsLineMatch != -1) {
+ if ((lineNum + linesSearched + extraLinesSearched)
+ == lastBackwardsLineMatch) {
+ /*
+ * Possible overlap or inclusion.
+ */
+
+ int thisOffset = firstOffset + info.matches[0].end
+ - info.matches[0].start;
+
+ if (lastNonOverlap != -1) {
+ /*
+ * Possible overlap or enclosure.
+ */
+
+ if (thisOffset-lastNonOverlap >=
+ lastBackwardsMatchOffset+matchLength){
+ /*
+ * Totally encloses previous match, so
+ * forget the previous match.
+ */
+
+ lastBackwardsLineMatch = -1;
+ } else if ((thisOffset - lastNonOverlap)
+ > lastBackwardsMatchOffset) {
+ /*
+ * Overlap. Previous match is ok, and the
+ * current match is only ok if we are
+ * searching with -overlap.
+ */
+
+ if (searchSpecPtr->overlap) {
+ goto recordBackwardsMatch;
+ } else {
+ match = 0;
+ break;
+ }
+ } else {
+ /*
+ * No overlap, although the same line was
+ * reached.
+ */
+
+ goto recordBackwardsMatch;
+ }
+ } else {
+ /*
+ * No overlap.
+ */
+
+ goto recordBackwardsMatch;
+ }
+ } else if (lineNum+linesSearched+extraLinesSearched
+ < lastBackwardsLineMatch) {
+ /*
+ * No overlap.
+ */
+
+ goto recordBackwardsMatch;
+ } else {
+ /*
+ * Totally enclosed.
+ */
+
+ lastBackwardsLineMatch = -1;
+ }
+ }
+
+ } else {
+ /*
+ * Matched in a single line.
+ */
+
+ if (lastBackwardsLineMatch != -1) {
+ recordBackwardsMatch:
+ searchSpecPtr->foundMatchProc(lastBackwardsLineMatch,
+ searchSpecPtr, NULL, NULL,
+ lastBackwardsMatchOffset, matchLength);
+ lastBackwardsLineMatch = -1;
+ if (!searchSpecPtr->all) {
+ goto searchDone;
+ }
+ }
+ }
+
+ firstOffset += info.matches[0].start;
+ if (firstOffset >= lastOffset) {
+ break;
+ }
+
+ /*
+ * Update our local variables with the match, if we haven't
+ * yet found anything, or if we're doing '-all' or
+ * '-backwards' _and_ this match isn't fully enclosed in the
+ * previous match.
+ */
+
+ if (matchOffset == -1 ||
+ ((searchSpecPtr->all || searchSpecPtr->backwards)
+ && ((firstOffset < matchOffset)
+ || ((firstOffset + info.matches[0].end
+ - info.matches[0].start)
+ > (matchOffset + matchLength))))) {
+
+ matchOffset = firstOffset;
+ matchLength = info.matches[0].end - info.matches[0].start;
+
+ if (searchSpecPtr->backwards) {
+ /*
+ * To get backwards searches in the correct order, we
+ * must store them away here.
+ */
+
+ if (matches == matchNum) {
+ /*
+ * We've run out of space in our normal store, so
+ * we must allocate space for these backwards
+ * matches on the heap.
+ */
+
+ int *newArray =
+ ckalloc(4 * matchNum * sizeof(int));
+ memcpy(newArray, storeMatch, matchNum*sizeof(int));
+ memcpy(newArray + 2*matchNum, storeLength,
+ matchNum * sizeof(int));
+ if (storeMatch != smArray) {
+ ckfree(storeMatch);
+ }
+ matchNum *= 2;
+ storeMatch = newArray;
+ storeLength = newArray + matchNum;
+ }
+ storeMatch[matches] = matchOffset;
+ storeLength[matches] = matchLength;
+ matches++;
+ } else {
+ /*
+ * Now actually record the match, but only if we are
+ * doing an '-all' search.
+ */
+
+ if (searchSpecPtr->all &&
+ !searchSpecPtr->foundMatchProc(lineNum,
+ searchSpecPtr, lineInfo, theLine, matchOffset,
+ matchLength)) {
+ /*
+ * We reached the end of the search.
+ */
+
+ goto searchDone;
+ }
+ }
+
+ /*
+ * For forward matches, unless we allow overlaps, we move
+ * this on by the length of the current match so that we
+ * explicitly disallow overlapping matches.
+ */
+
+ if (matchLength > 0 && !searchSpecPtr->overlap
+ && !searchSpecPtr->backwards) {
+ firstOffset += matchLength;
+ if (firstOffset >= lastOffset) {
+ /*
+ * Now, we have to be careful not to find
+ * overlapping matches either on the same or
+ * following lines. Assume that if we did find
+ * something, it goes until the last extra line we
+ * added.
+ *
+ * We can break out of the loop, since we know no
+ * more will be found.
+ */
+
+ alreadySearchOffset = firstOffset - lastFullLine;
+ break;
+ }
+
+ /*
+ * We'll add this on again just below.
+ */
+
+ firstOffset --;
+ }
+ }
+
+ /*
+ * Move the starting point on, in case we are doing repeated
+ * or backwards searches (for the latter, we actually do
+ * repeated forward searches).
+ */
+
+ firstOffset++;
+ } while (searchSpecPtr->backwards || searchSpecPtr->all);
+
+ if (matches > 0) {
+ /*
+ * Now we have all the matches in our array, but not stored
+ * with 'foundMatchProc' yet.
+ */
+
+ matches--;
+ matchOffset = storeMatch[matches];
+ matchLength = storeLength[matches];
+ while (--matches >= 0) {
+ if (lineNum == searchSpecPtr->stopLine) {
+ /*
+ * It appears as if a condition like:
+ *
+ * if (storeMatch[matches]<searchSpecPtr->stopOffset)
+ * break;
+ *
+ * might be needed here, but no test case has been
+ * found which would exercise such a problem.
+ */
+ }
+ if (storeMatch[matches] + storeLength[matches]
+ >= matchOffset + matchLength) {
+ /*
+ * The new match totally encloses the previous one, so
+ * we overwrite the previous one.
+ */
+
+ matchOffset = storeMatch[matches];
+ matchLength = storeLength[matches];
+ continue;
+ }
+ if (!searchSpecPtr->overlap) {
+ if (storeMatch[matches] + storeLength[matches]
+ > matchOffset) {
+ continue;
+ }
+ }
+ searchSpecPtr->foundMatchProc(lineNum, searchSpecPtr,
+ lineInfo, theLine, matchOffset, matchLength);
+ if (!searchSpecPtr->all) {
+ goto searchDone;
+ }
+ matchOffset = storeMatch[matches];
+ matchLength = storeLength[matches];
+ }
+ if (searchSpecPtr->all && matches > 0) {
+ /*
+ * We only need to do this for the '-all' case, because
+ * just below we will call the foundMatchProc for the
+ * non-all case.
+ */
+
+ searchSpecPtr->foundMatchProc(lineNum, searchSpecPtr,
+ lineInfo, theLine, matchOffset, matchLength);
+ } else {
+ lastBackwardsLineMatch = lineNum;
+ lastBackwardsMatchOffset = matchOffset;
+ }
+ }
+ }
+
+ /*
+ * If the 'all' flag is set, we will already have stored all matches,
+ * so we just proceed to the next line.
+ *
+ * If not, and there is a match we need to store that information and
+ * we are done.
+ */
+
+ if ((lastBackwardsLineMatch == -1) && (matchOffset >= 0)
+ && !searchSpecPtr->all) {
+ searchSpecPtr->foundMatchProc(lineNum, searchSpecPtr, lineInfo,
+ theLine, matchOffset, matchLength);
+ goto searchDone;
+ }
+
+ /*
+ * Go to the next (or previous) line;
+ */
+
+ nextLine:
+ linesSearched += extraLinesSearched;
+
+ while (linesSearched-- > 0) {
+ /*
+ * If we have just completed the 'stopLine', we are done.
+ */
+
+ if (lineNum == searchSpecPtr->stopLine) {
+ goto searchDone;
+ }
+
+ if (searchSpecPtr->backwards) {
+ lineNum--;
+
+ if (lastBackwardsLineMatch != -1
+ && ((lineNum < 0)
+ || (lineNum + 2 < lastBackwardsLineMatch))) {
+ searchSpecPtr->foundMatchProc(lastBackwardsLineMatch,
+ searchSpecPtr, NULL, NULL,
+ lastBackwardsMatchOffset, matchLength);
+ lastBackwardsLineMatch = -1;
+ if (!searchSpecPtr->all) {
+ goto searchDone;
+ }
+ }
+
+ if (lineNum < 0) {
+ lineNum = searchSpecPtr->numLines-1;
+ }
+ if (!searchSpecPtr->exact) {
+ /*
+ * The 'exact' search loops above are designed to give us
+ * an accurate picture of the number of lines which we can
+ * skip here. For 'regexp' searches, on the other hand,
+ * which can match potentially variable lengths, we cannot
+ * skip multiple lines when searching backwards. Therefore
+ * we only allow one line to be skipped here.
+ */
+
+ break;
+ }
+ } else {
+ lineNum++;
+ if (lineNum >= searchSpecPtr->numLines) {
+ lineNum = 0;
+ }
+ }
+ if (lineNum == searchSpecPtr->startLine && linesSearched > 0) {
+ /*
+ * We've just searched all the way round and have gone right
+ * through the start line without finding anything in the last
+ * attempt.
+ */
+
+ break;
+ }
+ }
+
+ Tcl_SetObjLength(theLine, 0);
+ }
+ searchDone:
+
+ if (lastBackwardsLineMatch != -1) {
+ searchSpecPtr->foundMatchProc(lastBackwardsLineMatch, searchSpecPtr,
+ NULL, NULL, lastBackwardsMatchOffset, matchLength);
+ }
+
+ /*
+ * Free up the cached line and pattern.
+ */
+
+ Tcl_DecrRefCount(theLine);
+ Tcl_DecrRefCount(patObj);
+
+ /*
+ * Free up any extra space we allocated.
+ */
+
+ if (storeMatch != smArray) {
+ ckfree(storeMatch);
+ }
+
+ return code;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetLineStartEnd -
+ *
+ * Converts an internal TkTextLine ptr into a Tcl string obj containing
+ * the line number. (Handler for the 'line' configuration option type.)
+ *
+ * Results:
+ * Tcl_Obj containing the string representation of the line value.
+ *
+ * Side effects:
+ * Creates a new Tcl_Obj.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj *
+GetLineStartEnd(
+ ClientData clientData,
+ Tk_Window tkwin,
+ char *recordPtr, /* Pointer to widget record. */
+ int internalOffset) /* Offset within *recordPtr containing the
+ * line value. */
+{
+ TkTextLine *linePtr = *(TkTextLine **)(recordPtr + internalOffset);
+
+ if (linePtr == NULL) {
+ return Tcl_NewObj();
+ }
+ return Tcl_NewIntObj(1 + TkBTreeLinesTo(NULL, linePtr));
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetLineStartEnd --
+ *
+ * Converts a Tcl_Obj representing a widget's (start or end) line into a
+ * TkTextLine* value. (Handler for the 'line' configuration option type.)
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * May store the TkTextLine* value into the internal representation
+ * pointer. May change the pointer to the Tcl_Obj to NULL to indicate
+ * that the specified string was empty and that is acceptable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetLineStartEnd(
+ ClientData clientData,
+ Tcl_Interp *interp, /* Current interp; may be used for errors. */
+ Tk_Window tkwin, /* Window for which option is being set. */
+ Tcl_Obj **value, /* Pointer to the pointer to the value object.
+ * We use a pointer to the pointer because we
+ * may need to return a value (NULL). */
+ char *recordPtr, /* Pointer to storage for the widget record. */
+ int internalOffset, /* Offset within *recordPtr at which the
+ * internal value is to be stored. */
+ char *oldInternalPtr, /* Pointer to storage for the old value. */
+ int flags) /* Flags for the option, set Tk_SetOptions. */
+{
+ TkTextLine *linePtr = NULL;
+ char *internalPtr;
+ TkText *textPtr = (TkText *) recordPtr;
+
+ if (internalOffset >= 0) {
+ internalPtr = recordPtr + internalOffset;
+ } else {
+ internalPtr = NULL;
+ }
+
+ if (flags & TK_OPTION_NULL_OK && ObjectIsEmpty(*value)) {
+ *value = NULL;
+ } else {
+ int line;
+
+ if (Tcl_GetIntFromObj(interp, *value, &line) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ linePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, NULL, line-1);
+ }
+
+ if (internalPtr != NULL) {
+ *((TkTextLine **) oldInternalPtr) = *((TkTextLine **) internalPtr);
+ *((TkTextLine **) internalPtr) = linePtr;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * RestoreLineStartEnd --
+ *
+ * Restore a line option value from a saved value. (Handler for the
+ * 'line' configuration option type.)
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Restores the old value.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+RestoreLineStartEnd(
+ ClientData clientData,
+ Tk_Window tkwin,
+ char *internalPtr, /* Pointer to storage for value. */
+ char *oldInternalPtr) /* Pointer to old value. */
+{
+ *(TkTextLine **)internalPtr = *(TkTextLine **)oldInternalPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ObjectIsEmpty --
+ *
+ * This function tests whether the string value of an object is empty.
+ *
+ * Results:
+ * The return value is 1 if the string value of objPtr has length zero,
+ * and 0 otherwise.
+ *
+ * Side effects:
+ * May cause object shimmering, since this function can force a
+ * conversion to a string object.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ObjectIsEmpty(
+ Tcl_Obj *objPtr) /* Object to test. May be NULL. */
+{
+ if (objPtr == NULL) {
+ return 1;
+ }
+ if (objPtr->bytes == NULL) {
+ Tcl_GetString(objPtr);
+ }
+ return (objPtr->length == 0);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpTesttextCmd --
+ *
+ * This function implements the "testtext" command. It provides a set of
+ * functions for testing text widgets and the associated functions in
+ * tkText*.c.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * Depends on option; see below.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkpTesttextCmd(
+ ClientData clientData, /* Main window for application. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument strings. */
+{
+ TkText *textPtr;
+ size_t len;
+ int lineIndex, byteIndex, byteOffset;
+ TkTextIndex index;
+ char buf[64];
+ Tcl_CmdInfo info;
+
+ if (objc < 3) {
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &info) == 0) {
+ return TCL_ERROR;
+ }
+ textPtr = info.objClientData;
+ len = strlen(Tcl_GetString(objv[2]));
+ if (strncmp(Tcl_GetString(objv[2]), "byteindex", len) == 0) {
+ if (objc != 5) {
+ return TCL_ERROR;
+ }
+ lineIndex = atoi(Tcl_GetString(objv[3])) - 1;
+ byteIndex = atoi(Tcl_GetString(objv[4]));
+
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, lineIndex,
+ byteIndex, &index);
+ } else if (strncmp(Tcl_GetString(objv[2]), "forwbytes", len) == 0) {
+ if (objc != 5) {
+ return TCL_ERROR;
+ }
+ if (TkTextGetIndex(interp, textPtr, Tcl_GetString(objv[3]), &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ byteOffset = atoi(Tcl_GetString(objv[4]));
+ TkTextIndexForwBytes(textPtr, &index, byteOffset, &index);
+ } else if (strncmp(Tcl_GetString(objv[2]), "backbytes", len) == 0) {
+ if (objc != 5) {
+ return TCL_ERROR;
+ }
+ if (TkTextGetIndex(interp, textPtr, Tcl_GetString(objv[3]), &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ byteOffset = atoi(Tcl_GetString(objv[4]));
+ TkTextIndexBackBytes(textPtr, &index, byteOffset, &index);
+ } else {
+ return TCL_ERROR;
+ }
+
+ TkTextSetMark(textPtr, "insert", &index);
+ TkTextPrintIndex(textPtr, &index, buf);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf("%s %d", buf, index.byteIndex));
+ return TCL_OK;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkText.h b/tk8.6/generic/tkText.h
new file mode 100644
index 0000000..a8a17da
--- /dev/null
+++ b/tk8.6/generic/tkText.h
@@ -0,0 +1,1171 @@
+/*
+ * tkText.h --
+ *
+ * Declarations shared among the files that implement text widgets.
+ *
+ * Copyright (c) 1992-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef _TKTEXT
+#define _TKTEXT
+
+#ifndef _TK
+#include "tk.h"
+#endif
+
+#ifndef _TKUNDO
+#include "tkUndo.h"
+#endif
+
+/*
+ * The data structure below defines a single logical line of text (from
+ * newline to newline, not necessarily what appears on one display line of the
+ * screen).
+ */
+
+typedef struct TkTextLine {
+ struct Node *parentPtr; /* Pointer to parent node containing line. */
+ struct TkTextLine *nextPtr; /* Next in linked list of lines with same
+ * parent node in B-tree. NULL means end of
+ * list. */
+ struct TkTextSegment *segPtr;
+ /* First in ordered list of segments that make
+ * up the line. */
+ int *pixels; /* Array containing two integers for each
+ * referring text widget. The first of these
+ * is the number of vertical pixels taken up
+ * by this line, whether currently displayed
+ * or not. This number is only updated
+ * asychronously. The second of these is the
+ * last epoch at which the pixel height was
+ * recalculated. */
+} TkTextLine;
+
+/*
+ * -----------------------------------------------------------------------
+ * Segments: each line is divided into one or more segments, where each
+ * segment is one of several things, such as a group of characters, a tag
+ * toggle, a mark, or an embedded widget. Each segment starts with a standard
+ * header followed by a body that varies from type to type.
+ * -----------------------------------------------------------------------
+ */
+
+/*
+ * The data structure below defines the body of a segment that represents a
+ * tag toggle. There is one of these structures at both the beginning and end
+ * of each tagged range.
+ */
+
+typedef struct TkTextToggle {
+ struct TkTextTag *tagPtr; /* Tag that starts or ends here. */
+ int inNodeCounts; /* 1 means this toggle has been accounted for
+ * in node toggle counts; 0 means it hasn't,
+ * yet. */
+} TkTextToggle;
+
+/*
+ * The data structure below defines line segments that represent marks. There
+ * is one of these for each mark in the text.
+ */
+
+typedef struct TkTextMark {
+ struct TkText *textPtr; /* Overall information about text widget. */
+ TkTextLine *linePtr; /* Line structure that contains the
+ * segment. */
+ Tcl_HashEntry *hPtr; /* Pointer to hash table entry for mark (in
+ * sharedTextPtr->markTable). */
+} TkTextMark;
+
+/*
+ * A structure of the following type holds information for each window
+ * embedded in a text widget. This information is only used by the file
+ * tkTextWind.c
+ */
+
+typedef struct TkTextEmbWindowClient {
+ struct TkText *textPtr; /* Information about the overall text
+ * widget. */
+ Tk_Window tkwin; /* Window for this segment. NULL means that
+ * the window hasn't been created yet. */
+ int chunkCount; /* Number of display chunks that refer to this
+ * window. */
+ int displayed; /* Non-zero means that the window has been
+ * displayed on the screen recently. */
+ struct TkTextSegment *parent;
+ struct TkTextEmbWindowClient *next;
+} TkTextEmbWindowClient;
+
+typedef struct TkTextEmbWindow {
+ struct TkSharedText *sharedTextPtr;
+ /* Information about the shared portion of the
+ * text widget. */
+ Tk_Window tkwin; /* Window for this segment. This is just a
+ * temporary value, copied from 'clients', to
+ * make option table updating easier. NULL
+ * means that the window hasn't been created
+ * yet. */
+ TkTextLine *linePtr; /* Line structure that contains this
+ * window. */
+ char *create; /* Script to create window on-demand. NULL
+ * means no such script. Malloc-ed. */
+ int align; /* How to align window in vertical space. See
+ * definitions in tkTextWind.c. */
+ int padX, padY; /* Padding to leave around each side of
+ * window, in pixels. */
+ int stretch; /* Should window stretch to fill vertical
+ * space of line (except for pady)? 0 or 1. */
+ Tk_OptionTable optionTable; /* Token representing the configuration
+ * specifications. */
+ TkTextEmbWindowClient *clients;
+ /* Linked list of peer-widget specific
+ * information for this embedded window. */
+} TkTextEmbWindow;
+
+/*
+ * A structure of the following type holds information for each image embedded
+ * in a text widget. This information is only used by the file tkTextImage.c
+ */
+
+typedef struct TkTextEmbImage {
+ struct TkSharedText *sharedTextPtr;
+ /* Information about the shared portion of the
+ * text widget. This is used when the image
+ * changes or is deleted. */
+ TkTextLine *linePtr; /* Line structure that contains this image. */
+ char *imageString; /* Name of the image for this segment. */
+ char *imageName; /* Name used by text widget to identify this
+ * image. May be unique-ified. */
+ char *name; /* Name used in the hash table. Used by
+ * "image names" to identify this instance of
+ * the image. */
+ Tk_Image image; /* Image for this segment. NULL means that the
+ * image hasn't been created yet. */
+ int align; /* How to align image in vertical space. See
+ * definitions in tkTextImage.c. */
+ int padX, padY; /* Padding to leave around each side of image,
+ * in pixels. */
+ int chunkCount; /* Number of display chunks that refer to this
+ * image. */
+ Tk_OptionTable optionTable; /* Token representing the configuration
+ * specifications. */
+} TkTextEmbImage;
+
+/*
+ * The data structure below defines line segments.
+ */
+
+typedef struct TkTextSegment {
+ const struct Tk_SegType *typePtr;
+ /* Pointer to record describing segment's
+ * type. */
+ struct TkTextSegment *nextPtr;
+ /* Next in list of segments for this line, or
+ * NULL for end of list. */
+ int size; /* Size of this segment (# of bytes of index
+ * space it occupies). */
+ union {
+ char chars[2]; /* Characters that make up character info.
+ * Actual length varies to hold as many
+ * characters as needed.*/
+ TkTextToggle toggle; /* Information about tag toggle. */
+ TkTextMark mark; /* Information about mark. */
+ TkTextEmbWindow ew; /* Information about embedded window. */
+ TkTextEmbImage ei; /* Information about embedded image. */
+ } body;
+} TkTextSegment;
+
+/*
+ * Data structures of the type defined below are used during the execution of
+ * Tcl commands to keep track of various interesting places in a text. An
+ * index is only valid up until the next modification to the character
+ * structure of the b-tree so they can't be retained across Tcl commands.
+ * However, mods to marks or tags don't invalidate indices.
+ */
+
+typedef struct TkTextIndex {
+ TkTextBTree tree; /* Tree containing desired position. */
+ TkTextLine *linePtr; /* Pointer to line containing position of
+ * interest. */
+ int byteIndex; /* Index within line of desired character (0
+ * means first one). */
+ struct TkText *textPtr; /* May be NULL, but otherwise the text widget
+ * with which this index is associated. If not
+ * NULL, then we have a refCount on the
+ * widget. */
+} TkTextIndex;
+
+/*
+ * Types for procedure pointers stored in TkTextDispChunk strutures:
+ */
+
+typedef struct TkTextDispChunk TkTextDispChunk;
+
+typedef void Tk_ChunkDisplayProc(struct TkText *textPtr,
+ TkTextDispChunk *chunkPtr, int x, int y,
+ int height, int baseline, Display *display,
+ Drawable dst, int screenY);
+typedef void Tk_ChunkUndisplayProc(struct TkText *textPtr,
+ TkTextDispChunk *chunkPtr);
+typedef int Tk_ChunkMeasureProc(TkTextDispChunk *chunkPtr, int x);
+typedef void Tk_ChunkBboxProc(struct TkText *textPtr,
+ TkTextDispChunk *chunkPtr, int index, int y,
+ int lineHeight, int baseline, int *xPtr,
+ int *yPtr, int *widthPtr, int *heightPtr);
+
+/*
+ * The structure below represents a chunk of stuff that is displayed together
+ * on the screen. This structure is allocated and freed by generic display
+ * code but most of its fields are filled in by segment-type-specific code.
+ */
+
+struct TkTextDispChunk {
+ /*
+ * The fields below are set by the type-independent code before calling
+ * the segment-type-specific layoutProc. They should not be modified by
+ * segment-type-specific code.
+ */
+
+ int x; /* X position of chunk, in pixels. This
+ * position is measured from the left edge of
+ * the logical line, not from the left edge of
+ * the window (i.e. it doesn't change under
+ * horizontal scrolling). */
+ struct TkTextDispChunk *nextPtr;
+ /* Next chunk in the display line or NULL for
+ * the end of the list. */
+ struct TextStyle *stylePtr; /* Display information, known only to
+ * tkTextDisp.c. */
+
+ /*
+ * The fields below are set by the layoutProc that creates the chunk.
+ */
+
+ Tk_ChunkDisplayProc *displayProc;
+ /* Procedure to invoke to draw this chunk on
+ * the display or an off-screen pixmap. */
+ Tk_ChunkUndisplayProc *undisplayProc;
+ /* Procedure to invoke when segment ceases to
+ * be displayed on screen anymore. */
+ Tk_ChunkMeasureProc *measureProc;
+ /* Procedure to find character under a given
+ * x-location. */
+ Tk_ChunkBboxProc *bboxProc; /* Procedure to find bounding box of character
+ * in chunk. */
+ int numBytes; /* Number of bytes that will be displayed in
+ * the chunk. */
+ int minAscent; /* Minimum space above the baseline needed by
+ * this chunk. */
+ int minDescent; /* Minimum space below the baseline needed by
+ * this chunk. */
+ int minHeight; /* Minimum total line height needed by this
+ * chunk. */
+ int width; /* Width of this chunk, in pixels. Initially
+ * set by chunk-specific code, but may be
+ * increased to include tab or extra space at
+ * end of line. */
+ int breakIndex; /* Index within chunk of last acceptable
+ * position for a line (break just before this
+ * byte index). <= 0 means don't break during
+ * or immediately after this chunk. */
+ ClientData clientData; /* Additional information for use of
+ * displayProc and undisplayProc. */
+};
+
+/*
+ * One data structure of the following type is used for each tag in a text
+ * widget. These structures are kept in sharedTextPtr->tagTable and referred
+ * to in other structures.
+ */
+
+typedef enum {
+ TEXT_WRAPMODE_CHAR, TEXT_WRAPMODE_NONE, TEXT_WRAPMODE_WORD,
+ TEXT_WRAPMODE_NULL
+} TkWrapMode;
+
+typedef struct TkTextTag {
+ const char *name; /* Name of this tag. This field is actually a
+ * pointer to the key from the entry in
+ * sharedTextPtr->tagTable, so it needn't be
+ * freed explicitly. For 'sel' tags this is
+ * just a static string, so again need not be
+ * freed. */
+ const struct TkText *textPtr;
+ /* If non-NULL, then this tag only applies to
+ * the given text widget (when there are peer
+ * widgets). */
+ int priority; /* Priority of this tag within widget. 0 means
+ * lowest priority. Exactly one tag has each
+ * integer value between 0 and numTags-1. */
+ struct Node *tagRootPtr; /* Pointer into the B-Tree at the lowest node
+ * that completely dominates the ranges of
+ * text occupied by the tag. At this node
+ * there is no information about the tag. One
+ * or more children of the node do contain
+ * information about the tag. */
+ int toggleCount; /* Total number of tag toggles. */
+
+ /*
+ * Information for displaying text with this tag. The information belows
+ * acts as an override on information specified by lower-priority tags.
+ * If no value is specified, then the next-lower-priority tag on the text
+ * determins the value. The text widget itself provides defaults if no tag
+ * specifies an override.
+ */
+
+ Tk_3DBorder border; /* Used for drawing background. NULL means no
+ * value specified here. */
+ int borderWidth; /* Width of 3-D border for background. */
+ Tcl_Obj *borderWidthPtr; /* Width of 3-D border for background. */
+ char *reliefString; /* -relief option string (malloc-ed). NULL
+ * means option not specified. */
+ int relief; /* 3-D relief for background. */
+ Pixmap bgStipple; /* Stipple bitmap for background. None means
+ * no value specified here. */
+ XColor *fgColor; /* Foreground color for text. NULL means no
+ * value specified here. */
+ Tk_Font tkfont; /* Font for displaying text. NULL means no
+ * value specified here. */
+ Pixmap fgStipple; /* Stipple bitmap for text and other
+ * foreground stuff. None means no value
+ * specified here.*/
+ char *justifyString; /* -justify option string (malloc-ed). NULL
+ * means option not specified. */
+ Tk_Justify justify; /* How to justify text: TK_JUSTIFY_LEFT,
+ * TK_JUSTIFY_RIGHT, or TK_JUSTIFY_CENTER.
+ * Only valid if justifyString is non-NULL. */
+ char *lMargin1String; /* -lmargin1 option string (malloc-ed). NULL
+ * means option not specified. */
+ int lMargin1; /* Left margin for first display line of each
+ * text line, in pixels. Only valid if
+ * lMargin1String is non-NULL. */
+ char *lMargin2String; /* -lmargin2 option string (malloc-ed). NULL
+ * means option not specified. */
+ int lMargin2; /* Left margin for second and later display
+ * lines of each text line, in pixels. Only
+ * valid if lMargin2String is non-NULL. */
+ Tk_3DBorder lMarginColor; /* Used for drawing background in left margins.
+ * This is used for both lmargin1 and lmargin2.
+ * NULL means no value specified here. */
+ char *offsetString; /* -offset option string (malloc-ed). NULL
+ * means option not specified. */
+ int offset; /* Vertical offset of text's baseline from
+ * baseline of line. Used for superscripts and
+ * subscripts. Only valid if offsetString is
+ * non-NULL. */
+ char *overstrikeString; /* -overstrike option string (malloc-ed). NULL
+ * means option not specified. */
+ int overstrike; /* Non-zero means draw horizontal line through
+ * middle of text. Only valid if
+ * overstrikeString is non-NULL. */
+ XColor *overstrikeColor; /* Color for the overstrike. NULL means same
+ * color as foreground. */
+ char *rMarginString; /* -rmargin option string (malloc-ed). NULL
+ * means option not specified. */
+ int rMargin; /* Right margin for text, in pixels. Only
+ * valid if rMarginString is non-NULL. */
+ Tk_3DBorder rMarginColor; /* Used for drawing background in right margin.
+ * NULL means no value specified here. */
+ Tk_3DBorder selBorder; /* Used for drawing background for selected text.
+ * NULL means no value specified here. */
+ XColor *selFgColor; /* Foreground color for selected text. NULL means
+ * no value specified here. */
+ char *spacing1String; /* -spacing1 option string (malloc-ed). NULL
+ * means option not specified. */
+ int spacing1; /* Extra spacing above first display line for
+ * text line. Only valid if spacing1String is
+ * non-NULL. */
+ char *spacing2String; /* -spacing2 option string (malloc-ed). NULL
+ * means option not specified. */
+ int spacing2; /* Extra spacing between display lines for the
+ * same text line. Only valid if
+ * spacing2String is non-NULL. */
+ char *spacing3String; /* -spacing2 option string (malloc-ed). NULL
+ * means option not specified. */
+ int spacing3; /* Extra spacing below last display line for
+ * text line. Only valid if spacing3String is
+ * non-NULL. */
+ Tcl_Obj *tabStringPtr; /* -tabs option string. NULL means option not
+ * specified. */
+ struct TkTextTabArray *tabArrayPtr;
+ /* Info about tabs for tag (malloc-ed) or
+ * NULL. Corresponds to tabString. */
+ int tabStyle; /* One of TABULAR or WORDPROCESSOR or NONE (if
+ * not specified). */
+ char *underlineString; /* -underline option string (malloc-ed). NULL
+ * means option not specified. */
+ int underline; /* Non-zero means draw underline underneath
+ * text. Only valid if underlineString is
+ * non-NULL. */
+ XColor *underlineColor; /* Color for the underline. NULL means same
+ * color as foreground. */
+ TkWrapMode wrapMode; /* How to handle wrap-around for this tag.
+ * Must be TEXT_WRAPMODE_CHAR,
+ * TEXT_WRAPMODE_NONE, TEXT_WRAPMODE_WORD, or
+ * TEXT_WRAPMODE_NULL to use wrapmode for
+ * whole widget. */
+ char *elideString; /* -elide option string (malloc-ed). NULL
+ * means option not specified. */
+ int elide; /* Non-zero means that data under this tag
+ * should not be displayed. */
+ int affectsDisplay; /* Non-zero means that this tag affects the
+ * way information is displayed on the screen
+ * (so need to redisplay if tag changes). */
+ Tk_OptionTable optionTable; /* Token representing the configuration
+ * specifications. */
+ int affectsDisplayGeometry; /* Non-zero means that this tag affects the
+ * size with which information is displayed on
+ * the screen (so need to recalculate line
+ * dimensions if tag changes). */
+} TkTextTag;
+
+#define TK_TAG_AFFECTS_DISPLAY 0x1
+#define TK_TAG_UNDERLINE 0x2
+#define TK_TAG_JUSTIFY 0x4
+#define TK_TAG_OFFSET 0x10
+
+/*
+ * The data structure below is used for searching a B-tree for transitions on
+ * a single tag (or for all tag transitions). No code outside of tkTextBTree.c
+ * should ever modify any of the fields in these structures, but it's OK to
+ * use them for read-only information.
+ */
+
+typedef struct TkTextSearch {
+ TkTextIndex curIndex; /* Position of last tag transition returned by
+ * TkBTreeNextTag, or index of start of
+ * segment containing starting position for
+ * search if TkBTreeNextTag hasn't been called
+ * yet, or same as stopIndex if search is
+ * over. */
+ TkTextSegment *segPtr; /* Actual tag segment returned by last call to
+ * TkBTreeNextTag, or NULL if TkBTreeNextTag
+ * hasn't returned anything yet. */
+ TkTextSegment *nextPtr; /* Where to resume search in next call to
+ * TkBTreeNextTag. */
+ TkTextSegment *lastPtr; /* Stop search before just before considering
+ * this segment. */
+ TkTextTag *tagPtr; /* Tag to search for (or tag found, if allTags
+ * is non-zero). */
+ int linesLeft; /* Lines left to search (including curIndex
+ * and stopIndex). When this becomes <= 0 the
+ * search is over. */
+ int allTags; /* Non-zero means ignore tag check: search for
+ * transitions on all tags. */
+} TkTextSearch;
+
+/*
+ * The following data structure describes a single tab stop. It must be kept
+ * in sync with the 'tabOptionStrings' array in the function 'TkTextGetTabs'
+ */
+
+typedef enum {LEFT, RIGHT, CENTER, NUMERIC} TkTextTabAlign;
+
+/*
+ * The following are the supported styles of tabbing, used for the -tabstyle
+ * option of the text widget. The last element is only used for tag options.
+ */
+
+typedef enum {
+ TK_TEXT_TABSTYLE_TABULAR,
+ TK_TEXT_TABSTYLE_WORDPROCESSOR,
+ TK_TEXT_TABSTYLE_NONE
+} TkTextTabStyle;
+
+typedef struct TkTextTab {
+ int location; /* Offset in pixels of this tab stop from the
+ * left margin (lmargin2) of the text. */
+ TkTextTabAlign alignment; /* Where the tab stop appears relative to the
+ * text. */
+} TkTextTab;
+
+typedef struct TkTextTabArray {
+ int numTabs; /* Number of tab stops. */
+ double lastTab; /* The accurate fractional pixel position of
+ * the last tab. */
+ double tabIncrement; /* The accurate fractional pixel increment
+ * between interpolated tabs we have to create
+ * when we exceed numTabs. */
+ TkTextTab tabs[1]; /* Array of tabs. The actual size will be
+ * numTabs. THIS FIELD MUST BE THE LAST IN THE
+ * STRUCTURE. */
+} TkTextTabArray;
+
+/*
+ * Enumeration defining the edit modes of the widget.
+ */
+
+typedef enum {
+ TK_TEXT_EDIT_INSERT, /* insert mode */
+ TK_TEXT_EDIT_DELETE, /* delete mode */
+ TK_TEXT_EDIT_REPLACE, /* replace mode */
+ TK_TEXT_EDIT_OTHER /* none of the above */
+} TkTextEditMode;
+
+/*
+ * Enumeration defining the ways in which a text widget may be modified (for
+ * undo/redo handling).
+ */
+
+typedef enum {
+ TK_TEXT_DIRTY_NORMAL, /* Normal behavior. */
+ TK_TEXT_DIRTY_UNDO, /* Reverting a compound action. */
+ TK_TEXT_DIRTY_REDO, /* Reapplying a compound action. */
+ TK_TEXT_DIRTY_FIXED /* Forced to be dirty; can't be undone/redone
+ * by normal activity. */
+} TkTextDirtyMode;
+
+/*
+ * The following enum is used to define a type for the -state option of the
+ * Text widget.
+ */
+
+typedef enum {
+ TK_TEXT_STATE_DISABLED, TK_TEXT_STATE_NORMAL
+} TkTextState;
+
+/*
+ * A data structure of the following type is shared between each text widget
+ * that are peers.
+ */
+
+typedef struct TkSharedText {
+ int refCount; /* Reference count this shared object. */
+ TkTextBTree tree; /* B-tree representation of text and tags for
+ * widget. */
+ Tcl_HashTable tagTable; /* Hash table that maps from tag names to
+ * pointers to TkTextTag structures. The "sel"
+ * tag does not feature in this table, since
+ * there's one of those for each text peer. */
+ int numTags; /* Number of tags currently defined for
+ * widget; needed to keep track of
+ * priorities. */
+ Tcl_HashTable markTable; /* Hash table that maps from mark names to
+ * pointers to mark segments. The special
+ * "insert" and "current" marks are not stored
+ * in this table, but directly accessed as
+ * fields of textPtr. */
+ Tcl_HashTable windowTable; /* Hash table that maps from window names to
+ * pointers to window segments. If a window
+ * segment doesn't yet have an associated
+ * window, there is no entry for it here. */
+ Tcl_HashTable imageTable; /* Hash table that maps from image names to
+ * pointers to image segments. If an image
+ * segment doesn't yet have an associated
+ * image, there is no entry for it here. */
+ Tk_BindingTable bindingTable;
+ /* Table of all bindings currently defined for
+ * this widget. NULL means that no bindings
+ * exist, so the table hasn't been created.
+ * Each "object" used for this table is the
+ * name of a tag. */
+ int stateEpoch; /* This is incremented each time the B-tree's
+ * contents change structurally, or when the
+ * start/end limits change, and means that any
+ * cached TkTextIndex objects are no longer
+ * valid. */
+
+ /*
+ * Information related to the undo/redo functionality.
+ */
+
+ TkUndoRedoStack *undoStack; /* The undo/redo stack. */
+ int undo; /* Non-zero means the undo/redo behaviour is
+ * enabled. */
+ int maxUndo; /* The maximum depth of the undo stack
+ * expressed as the maximum number of compound
+ * statements. */
+ int autoSeparators; /* Non-zero means the separators will be
+ * inserted automatically. */
+ int isDirty; /* Flag indicating the 'dirtyness' of the
+ * text widget. If the flag is not zero,
+ * unsaved modifications have been applied to
+ * the text widget. */
+ TkTextDirtyMode dirtyMode; /* The nature of the dirtyness characterized
+ * by the isDirty flag. */
+ TkTextEditMode lastEditMode;/* Keeps track of what the last edit mode
+ * was. */
+
+ /*
+ * Keep track of all the peers
+ */
+
+ struct TkText *peers;
+} TkSharedText;
+
+/*
+ * The following enum is used to define a type for the -insertunfocussed
+ * option of the Text widget.
+ */
+
+typedef enum {
+ TK_TEXT_INSERT_NOFOCUS_HOLLOW,
+ TK_TEXT_INSERT_NOFOCUS_NONE,
+ TK_TEXT_INSERT_NOFOCUS_SOLID
+} TkTextInsertUnfocussed;
+
+/*
+ * A data structure of the following type is kept for each text widget that
+ * currently exists for this process:
+ */
+
+typedef struct TkText {
+ /*
+ * Information related to and accessed by widget peers and the
+ * TkSharedText handling routines.
+ */
+
+ TkSharedText *sharedTextPtr;/* Shared section of all peers. */
+ struct TkText *next; /* Next in list of linked peers. */
+ TkTextLine *start; /* First B-tree line to show, or NULL to start
+ * at the beginning. */
+ TkTextLine *end; /* Last B-tree line to show, or NULL for up to
+ * the end. */
+ int pixelReference; /* Counter into the current tree reference
+ * index corresponding to this widget. */
+ int abortSelections; /* Set to 1 whenever the text is modified in a
+ * way that interferes with selection
+ * retrieval: used to abort incremental
+ * selection retrievals. */
+
+ /*
+ * Standard Tk widget information and text-widget specific items
+ */
+
+ Tk_Window tkwin; /* Window that embodies the text. NULL means
+ * that the window has been destroyed but the
+ * data structures haven't yet been cleaned
+ * up.*/
+ Display *display; /* Display for widget. Needed, among other
+ * things, to allow resources to be freed even
+ * after tkwin has gone away. */
+ Tcl_Interp *interp; /* Interpreter associated with widget. Used to
+ * delete widget command. */
+ Tcl_Command widgetCmd; /* Token for text's widget command. */
+ int state; /* Either STATE_NORMAL or STATE_DISABLED. A
+ * text widget is read-only when disabled. */
+
+ /*
+ * Default information for displaying (may be overridden by tags applied
+ * to ranges of characters).
+ */
+
+ Tk_3DBorder border; /* Structure used to draw 3-D border and
+ * default background. */
+ int borderWidth; /* Width of 3-D border to draw around entire
+ * widget. */
+ int padX, padY; /* Padding between text and window border. */
+ int relief; /* 3-d effect for border around entire widget:
+ * TK_RELIEF_RAISED etc. */
+ int highlightWidth; /* Width in pixels of highlight to draw around
+ * widget when it has the focus. <= 0 means
+ * don't draw a highlight. */
+ XColor *highlightBgColorPtr;
+ /* Color for drawing traversal highlight area
+ * when highlight is off. */
+ XColor *highlightColorPtr; /* Color for drawing traversal highlight. */
+ Tk_Cursor cursor; /* Current cursor for window, or NULL. */
+ XColor *fgColor; /* Default foreground color for text. */
+ Tk_Font tkfont; /* Default font for displaying text. */
+ int charWidth; /* Width of average character in default
+ * font. */
+ int charHeight; /* Height of average character in default
+ * font, including line spacing. */
+ int spacing1; /* Default extra spacing above first display
+ * line for each text line. */
+ int spacing2; /* Default extra spacing between display lines
+ * for the same text line. */
+ int spacing3; /* Default extra spacing below last display
+ * line for each text line. */
+ Tcl_Obj *tabOptionPtr; /* Value of -tabs option string. */
+ TkTextTabArray *tabArrayPtr;
+ /* Information about tab stops (malloc'ed).
+ * NULL means perform default tabbing
+ * behavior. */
+ int tabStyle; /* One of TABULAR or WORDPROCESSOR. */
+
+ /*
+ * Additional information used for displaying:
+ */
+
+ TkWrapMode wrapMode; /* How to handle wrap-around. Must be
+ * TEXT_WRAPMODE_CHAR, TEXT_WRAPMODE_NONE, or
+ * TEXT_WRAPMODE_WORD. */
+ int width, height; /* Desired dimensions for window, measured in
+ * characters. */
+ int setGrid; /* Non-zero means pass gridding information to
+ * window manager. */
+ int prevWidth, prevHeight; /* Last known dimensions of window; used to
+ * detect changes in size. */
+ TkTextIndex topIndex; /* Identifies first character in top display
+ * line of window. */
+ struct TextDInfo *dInfoPtr; /* Information maintained by tkTextDisp.c. */
+
+ /*
+ * Information related to selection.
+ */
+
+ TkTextTag *selTagPtr; /* Pointer to "sel" tag. Used to tell when a
+ * new selection has been made. */
+ Tk_3DBorder selBorder; /* Border and background for selected
+ * characters. This is a copy of information
+ * in *selTagPtr, so it shouldn't be
+ * explicitly freed. */
+ Tk_3DBorder inactiveSelBorder;
+ /* Border and background for selected
+ * characters when they don't have the
+ * focus. */
+ int selBorderWidth; /* Width of border around selection. */
+ Tcl_Obj *selBorderWidthPtr; /* Width of border around selection. */
+ XColor *selFgColorPtr; /* Foreground color for selected text. This is
+ * a copy of information in *selTagPtr, so it
+ * shouldn't be explicitly freed. */
+ int exportSelection; /* Non-zero means tie "sel" tag to X
+ * selection. */
+ TkTextIndex selIndex; /* Used during multi-pass selection
+ * retrievals. This index identifies the next
+ * character to be returned from the
+ * selection. */
+
+ /*
+ * Information related to insertion cursor:
+ */
+
+ TkTextSegment *insertMarkPtr;
+ /* Points to segment for "insert" mark. */
+ Tk_3DBorder insertBorder; /* Used to draw vertical bar for insertion
+ * cursor. */
+ int insertWidth; /* Total width of insert cursor. */
+ int insertBorderWidth; /* Width of 3-D border around insert cursor */
+ TkTextInsertUnfocussed insertUnfocussed;
+ /* How to display the insert cursor when the
+ * text widget does not have the focus. */
+ int insertOnTime; /* Number of milliseconds cursor should spend
+ * in "on" state for each blink. */
+ int insertOffTime; /* Number of milliseconds cursor should spend
+ * in "off" state for each blink. */
+ Tcl_TimerToken insertBlinkHandler;
+ /* Timer handler used to blink cursor on and
+ * off. */
+
+ /*
+ * Information used for event bindings associated with tags:
+ */
+
+ TkTextSegment *currentMarkPtr;
+ /* Pointer to segment for "current" mark, or
+ * NULL if none. */
+ XEvent pickEvent; /* The event from which the current character
+ * was chosen. Must be saved so that we can
+ * repick after modifications to the text. */
+ int numCurTags; /* Number of tags associated with character at
+ * current mark. */
+ TkTextTag **curTagArrayPtr; /* Pointer to array of tags for current mark,
+ * or NULL if none. */
+
+ /*
+ * Miscellaneous additional information:
+ */
+
+ char *takeFocus; /* Value of -takeFocus option; not used in the
+ * C code, but used by keyboard traversal
+ * scripts. Malloc'ed, but may be NULL. */
+ char *xScrollCmd; /* Prefix of command to issue to update
+ * horizontal scrollbar when view changes. */
+ char *yScrollCmd; /* Prefix of command to issue to update
+ * vertical scrollbar when view changes. */
+ int flags; /* Miscellaneous flags; see below for
+ * definitions. */
+ Tk_OptionTable optionTable; /* Token representing the configuration
+ * specifications. */
+ int refCount; /* Number of cached TkTextIndex objects
+ * refering to us. */
+ int insertCursorType; /* 0 = standard insertion cursor, 1 = block
+ * cursor. */
+
+ /*
+ * Copies of information from the shared section relating to the undo/redo
+ * functonality
+ */
+
+ int undo; /* Non-zero means the undo/redo behaviour is
+ * enabled. */
+ int maxUndo; /* The maximum depth of the undo stack
+ * expressed as the maximum number of compound
+ * statements. */
+ int autoSeparators; /* Non-zero means the separators will be
+ * inserted automatically. */
+ Tcl_Obj *afterSyncCmd; /* Command to be executed when lines are up to
+ * date */
+} TkText;
+
+/*
+ * Flag values for TkText records:
+ *
+ * GOT_SELECTION: Non-zero means we've already claimed the
+ * selection.
+ * INSERT_ON: Non-zero means insertion cursor should be
+ * displayed on screen.
+ * GOT_FOCUS: Non-zero means this window has the input
+ * focus.
+ * BUTTON_DOWN: 1 means that a mouse button is currently down;
+ * this is used to implement grabs for the
+ * duration of button presses.
+ * UPDATE_SCROLLBARS: Non-zero means scrollbar(s) should be updated
+ * during next redisplay operation.
+ * NEED_REPICK This appears unused and should probably be
+ * ignored.
+ * OPTIONS_FREED The widget's options have been freed.
+ * DESTROYED The widget is going away.
+ */
+
+#define GOT_SELECTION 1
+#define INSERT_ON 2
+#define GOT_FOCUS 4
+#define BUTTON_DOWN 8
+#define UPDATE_SCROLLBARS 0x10
+#define NEED_REPICK 0x20
+#define OPTIONS_FREED 0x40
+#define DESTROYED 0x80
+
+/*
+ * Records of the following type define segment types in terms of a collection
+ * of procedures that may be called to manipulate segments of that type.
+ */
+
+typedef TkTextSegment * Tk_SegSplitProc(struct TkTextSegment *segPtr,
+ int index);
+typedef int Tk_SegDeleteProc(struct TkTextSegment *segPtr,
+ TkTextLine *linePtr, int treeGone);
+typedef TkTextSegment * Tk_SegCleanupProc(struct TkTextSegment *segPtr,
+ TkTextLine *linePtr);
+typedef void Tk_SegLineChangeProc(struct TkTextSegment *segPtr,
+ TkTextLine *linePtr);
+typedef int Tk_SegLayoutProc(struct TkText *textPtr,
+ struct TkTextIndex *indexPtr,
+ TkTextSegment *segPtr, int offset, int maxX,
+ int maxChars, int noCharsYet, TkWrapMode wrapMode,
+ struct TkTextDispChunk *chunkPtr);
+typedef void Tk_SegCheckProc(TkTextSegment *segPtr,
+ TkTextLine *linePtr);
+
+typedef struct Tk_SegType {
+ const char *name; /* Name of this kind of segment. */
+ int leftGravity; /* If a segment has zero size (e.g. a mark or
+ * tag toggle), does it attach to character to
+ * its left or right? 1 means left, 0 means
+ * right. */
+ Tk_SegSplitProc *splitProc; /* Procedure to split large segment into two
+ * smaller ones. */
+ Tk_SegDeleteProc *deleteProc;
+ /* Procedure to call to delete segment. */
+ Tk_SegCleanupProc *cleanupProc;
+ /* After any change to a line, this procedure
+ * is invoked for all segments left in the
+ * line to perform any cleanup they wish
+ * (e.g. joining neighboring segments). */
+ Tk_SegLineChangeProc *lineChangeProc;
+ /* Invoked when a segment is about to be moved
+ * from its current line to an earlier line
+ * because of a deletion. The linePtr is that
+ * for the segment's old line. CleanupProc
+ * will be invoked after the deletion is
+ * finished. */
+ Tk_SegLayoutProc *layoutProc;
+ /* Returns size information when figuring out
+ * what to display in window. */
+ Tk_SegCheckProc *checkProc; /* Called during consistency checks to check
+ * internal consistency of segment. */
+} Tk_SegType;
+
+/*
+ * The following type and items describe different flags for text widget items
+ * to count. They are used in both tkText.c and tkTextIndex.c, in
+ * 'CountIndices', 'TkTextIndexBackChars', 'TkTextIndexForwChars', and
+ * 'TkTextIndexCount'.
+ */
+
+typedef int TkTextCountType;
+
+#define COUNT_CHARS 0
+#define COUNT_INDICES 1
+#define COUNT_DISPLAY 2
+#define COUNT_DISPLAY_CHARS (COUNT_CHARS | COUNT_DISPLAY)
+#define COUNT_DISPLAY_INDICES (COUNT_INDICES | COUNT_DISPLAY)
+
+/*
+ * The following structure is used to keep track of elided text taking account
+ * of different tag priorities, it is need for quick calculations of whether a
+ * single index is elided, and to start at a given index and maintain a
+ * correct elide state as we move or count forwards or backwards.
+ */
+
+#define LOTSA_TAGS 1000
+typedef struct TkTextElideInfo {
+ int numTags; /* Total tags in widget. */
+ int elide; /* Is the state currently elided. */
+ int elidePriority; /* Tag priority controlling elide state. */
+ TkTextSegment *segPtr; /* Segment to look at next. */
+ int segOffset; /* Offset of segment within line. */
+ int deftagCnts[LOTSA_TAGS];
+ TkTextTag *deftagPtrs[LOTSA_TAGS];
+ int *tagCnts; /* 0 or 1 depending if the tag with that
+ * priority is on or off. */
+ TkTextTag **tagPtrs; /* Only filled with a tagPtr if the
+ * corresponding tagCnt is 1. */
+} TkTextElideInfo;
+
+/*
+ * The constant below is used to specify a line when what is really wanted is
+ * the entire text. For now, just use a very big number.
+ */
+
+#define TK_END_OF_TEXT 1000000
+
+/*
+ * The following definition specifies the maximum number of characters needed
+ * in a string to hold a position specifier.
+ */
+
+#define TK_POS_CHARS 30
+
+/*
+ * Mask used for those options which may impact the pixel height calculations
+ * of individual lines displayed in the widget.
+ */
+
+#define TK_TEXT_LINE_GEOMETRY 1
+
+/*
+ * Mask used for those options which may impact the start and end lines used
+ * in the widget.
+ */
+
+#define TK_TEXT_LINE_RANGE 2
+
+/*
+ * Used as 'action' values in calls to TkTextInvalidateLineMetrics
+ */
+
+#define TK_TEXT_INVALIDATE_ONLY 0
+#define TK_TEXT_INVALIDATE_INSERT 1
+#define TK_TEXT_INVALIDATE_DELETE 2
+
+/*
+ * Used as special 'pickPlace' values in calls to TkTextSetYView. Zero or
+ * positive values indicate a number of pixels.
+ */
+
+#define TK_TEXT_PICKPLACE -1
+#define TK_TEXT_NOPIXELADJUST -2
+
+/*
+ * Declarations for variables shared among the text-related files:
+ */
+
+MODULE_SCOPE int tkBTreeDebug;
+MODULE_SCOPE int tkTextDebug;
+MODULE_SCOPE const Tk_SegType tkTextCharType;
+MODULE_SCOPE const Tk_SegType tkTextLeftMarkType;
+MODULE_SCOPE const Tk_SegType tkTextRightMarkType;
+MODULE_SCOPE const Tk_SegType tkTextToggleOnType;
+MODULE_SCOPE const Tk_SegType tkTextToggleOffType;
+MODULE_SCOPE const Tk_SegType tkTextEmbWindowType;
+MODULE_SCOPE const Tk_SegType tkTextEmbImageType;
+
+/*
+ * Convenience macros for use by B-tree clients which want to access pixel
+ * information on each line. Currently only used by TkTextDisp.c
+ */
+
+#define TkBTreeLinePixelCount(text, line) \
+ (line)->pixels[2*(text)->pixelReference]
+#define TkBTreeLinePixelEpoch(text, line) \
+ (line)->pixels[1+2*(text)->pixelReference]
+
+/*
+ * Declarations for procedures that are used by the text-related files but
+ * shouldn't be used anywhere else in Tk (or by Tk clients):
+ */
+
+MODULE_SCOPE int TkBTreeAdjustPixelHeight(const TkText *textPtr,
+ TkTextLine *linePtr, int newPixelHeight,
+ int mergedLogicalLines);
+MODULE_SCOPE int TkBTreeCharTagged(const TkTextIndex *indexPtr,
+ TkTextTag *tagPtr);
+MODULE_SCOPE void TkBTreeCheck(TkTextBTree tree);
+MODULE_SCOPE TkTextBTree TkBTreeCreate(TkSharedText *sharedTextPtr);
+MODULE_SCOPE void TkBTreeAddClient(TkTextBTree tree, TkText *textPtr,
+ int defaultHeight);
+MODULE_SCOPE void TkBTreeClientRangeChanged(TkText *textPtr,
+ int defaultHeight);
+MODULE_SCOPE void TkBTreeRemoveClient(TkTextBTree tree,
+ TkText *textPtr);
+MODULE_SCOPE void TkBTreeDestroy(TkTextBTree tree);
+MODULE_SCOPE void TkBTreeDeleteIndexRange(TkTextBTree tree,
+ TkTextIndex *index1Ptr, TkTextIndex *index2Ptr);
+MODULE_SCOPE int TkBTreeEpoch(TkTextBTree tree);
+MODULE_SCOPE TkTextLine *TkBTreeFindLine(TkTextBTree tree,
+ const TkText *textPtr, int line);
+MODULE_SCOPE TkTextLine *TkBTreeFindPixelLine(TkTextBTree tree,
+ const TkText *textPtr, int pixels,
+ int *pixelOffset);
+MODULE_SCOPE TkTextTag **TkBTreeGetTags(const TkTextIndex *indexPtr,
+ const TkText *textPtr, int *numTagsPtr);
+MODULE_SCOPE void TkBTreeInsertChars(TkTextBTree tree,
+ TkTextIndex *indexPtr, const char *string);
+MODULE_SCOPE int TkBTreeLinesTo(const TkText *textPtr,
+ TkTextLine *linePtr);
+MODULE_SCOPE int TkBTreePixelsTo(const TkText *textPtr,
+ TkTextLine *linePtr);
+MODULE_SCOPE void TkBTreeLinkSegment(TkTextSegment *segPtr,
+ TkTextIndex *indexPtr);
+MODULE_SCOPE TkTextLine *TkBTreeNextLine(const TkText *textPtr,
+ TkTextLine *linePtr);
+MODULE_SCOPE int TkBTreeNextTag(TkTextSearch *searchPtr);
+MODULE_SCOPE int TkBTreeNumPixels(TkTextBTree tree,
+ const TkText *textPtr);
+MODULE_SCOPE TkTextLine *TkBTreePreviousLine(TkText *textPtr,
+ TkTextLine *linePtr);
+MODULE_SCOPE int TkBTreePrevTag(TkTextSearch *searchPtr);
+MODULE_SCOPE void TkBTreeStartSearch(TkTextIndex *index1Ptr,
+ TkTextIndex *index2Ptr, TkTextTag *tagPtr,
+ TkTextSearch *searchPtr);
+MODULE_SCOPE void TkBTreeStartSearchBack(TkTextIndex *index1Ptr,
+ TkTextIndex *index2Ptr, TkTextTag *tagPtr,
+ TkTextSearch *searchPtr);
+MODULE_SCOPE int TkBTreeTag(TkTextIndex *index1Ptr,
+ TkTextIndex *index2Ptr, TkTextTag *tagPtr,
+ int add);
+MODULE_SCOPE void TkBTreeUnlinkSegment(TkTextSegment *segPtr,
+ TkTextLine *linePtr);
+MODULE_SCOPE void TkTextBindProc(ClientData clientData,
+ XEvent *eventPtr);
+MODULE_SCOPE void TkTextSelectionEvent(TkText *textPtr);
+MODULE_SCOPE int TkTextIndexBbox(TkText *textPtr,
+ const TkTextIndex *indexPtr, int *xPtr, int *yPtr,
+ int *widthPtr, int *heightPtr, int *charWidthPtr);
+MODULE_SCOPE int TkTextCharLayoutProc(TkText *textPtr,
+ TkTextIndex *indexPtr, TkTextSegment *segPtr,
+ int offset, int maxX, int maxChars, int noBreakYet,
+ TkWrapMode wrapMode, TkTextDispChunk *chunkPtr);
+MODULE_SCOPE void TkTextCreateDInfo(TkText *textPtr);
+MODULE_SCOPE int TkTextDLineInfo(TkText *textPtr,
+ const TkTextIndex *indexPtr, int *xPtr, int *yPtr,
+ int *widthPtr, int *heightPtr, int *basePtr);
+MODULE_SCOPE void TkTextEmbWinDisplayProc(TkText *textPtr,
+ TkTextDispChunk *chunkPtr, int x, int y,
+ int lineHeight, int baseline, Display *display,
+ Drawable dst, int screenY);
+MODULE_SCOPE TkTextTag *TkTextCreateTag(TkText *textPtr,
+ const char *tagName, int *newTag);
+MODULE_SCOPE void TkTextFreeDInfo(TkText *textPtr);
+MODULE_SCOPE void TkTextDeleteTag(TkText *textPtr, TkTextTag *tagPtr);
+MODULE_SCOPE void TkTextFreeTag(TkText *textPtr, TkTextTag *tagPtr);
+MODULE_SCOPE int TkTextGetObjIndex(Tcl_Interp *interp, TkText *textPtr,
+ Tcl_Obj *idxPtr, TkTextIndex *indexPtr);
+MODULE_SCOPE int TkTextSharedGetObjIndex(Tcl_Interp *interp,
+ TkSharedText *sharedTextPtr, Tcl_Obj *idxPtr,
+ TkTextIndex *indexPtr);
+MODULE_SCOPE const TkTextIndex *TkTextGetIndexFromObj(Tcl_Interp *interp,
+ TkText *textPtr, Tcl_Obj *objPtr);
+MODULE_SCOPE TkTextTabArray *TkTextGetTabs(Tcl_Interp *interp,
+ TkText *textPtr, Tcl_Obj *stringPtr);
+MODULE_SCOPE void TkTextFindDisplayLineEnd(TkText *textPtr,
+ TkTextIndex *indexPtr, int end, int *xOffset);
+MODULE_SCOPE void TkTextIndexBackChars(const TkText *textPtr,
+ const TkTextIndex *srcPtr, int count,
+ TkTextIndex *dstPtr, TkTextCountType type);
+MODULE_SCOPE int TkTextIndexCmp(const TkTextIndex *index1Ptr,
+ const TkTextIndex *index2Ptr);
+MODULE_SCOPE int TkTextIndexCountBytes(const TkText *textPtr,
+ const TkTextIndex *index1Ptr,
+ const TkTextIndex *index2Ptr);
+MODULE_SCOPE int TkTextIndexCount(const TkText *textPtr,
+ const TkTextIndex *index1Ptr,
+ const TkTextIndex *index2Ptr,
+ TkTextCountType type);
+MODULE_SCOPE void TkTextIndexForwChars(const TkText *textPtr,
+ const TkTextIndex *srcPtr, int count,
+ TkTextIndex *dstPtr, TkTextCountType type);
+MODULE_SCOPE void TkTextIndexOfX(TkText *textPtr, int x,
+ TkTextIndex *indexPtr);
+MODULE_SCOPE int TkTextIndexYPixels(TkText *textPtr,
+ const TkTextIndex *indexPtr);
+MODULE_SCOPE TkTextSegment *TkTextIndexToSeg(const TkTextIndex *indexPtr,
+ int *offsetPtr);
+MODULE_SCOPE void TkTextLostSelection(ClientData clientData);
+MODULE_SCOPE TkTextIndex *TkTextMakeCharIndex(TkTextBTree tree, TkText *textPtr,
+ int lineIndex, int charIndex,
+ TkTextIndex *indexPtr);
+MODULE_SCOPE int TkTextMeasureDown(TkText *textPtr,
+ TkTextIndex *srcPtr, int distance);
+MODULE_SCOPE void TkTextFreeElideInfo(TkTextElideInfo *infoPtr);
+MODULE_SCOPE int TkTextIsElided(const TkText *textPtr,
+ const TkTextIndex *indexPtr,
+ TkTextElideInfo *infoPtr);
+MODULE_SCOPE int TkTextMakePixelIndex(TkText *textPtr,
+ int pixelIndex, TkTextIndex *indexPtr);
+MODULE_SCOPE void TkTextInvalidateLineMetrics(
+ TkSharedText *sharedTextPtr, TkText *textPtr,
+ TkTextLine *linePtr, int lineCount, int action);
+MODULE_SCOPE int TkTextUpdateLineMetrics(TkText *textPtr, int lineNum,
+ int endLine, int doThisMuch);
+MODULE_SCOPE int TkTextUpdateOneLine(TkText *textPtr,
+ TkTextLine *linePtr, int pixelHeight,
+ TkTextIndex *indexPtr, int partialCalc);
+MODULE_SCOPE int TkTextMarkCmd(TkText *textPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+MODULE_SCOPE int TkTextMarkNameToIndex(TkText *textPtr,
+ const char *name, TkTextIndex *indexPtr);
+MODULE_SCOPE void TkTextMarkSegToIndex(TkText *textPtr,
+ TkTextSegment *markPtr, TkTextIndex *indexPtr);
+MODULE_SCOPE void TkTextEventuallyRepick(TkText *textPtr);
+MODULE_SCOPE Bool TkTextPendingsync(TkText *textPtr);
+MODULE_SCOPE void TkTextPickCurrent(TkText *textPtr, XEvent *eventPtr);
+MODULE_SCOPE void TkTextPixelIndex(TkText *textPtr, int x, int y,
+ TkTextIndex *indexPtr, int *nearest);
+MODULE_SCOPE Tcl_Obj * TkTextNewIndexObj(TkText *textPtr,
+ const TkTextIndex *indexPtr);
+MODULE_SCOPE void TkTextRedrawRegion(TkText *textPtr, int x, int y,
+ int width, int height);
+MODULE_SCOPE void TkTextRedrawTag(TkSharedText *sharedTextPtr,
+ TkText *textPtr, TkTextIndex *index1Ptr,
+ TkTextIndex *index2Ptr, TkTextTag *tagPtr,
+ int withTag);
+MODULE_SCOPE void TkTextRelayoutWindow(TkText *textPtr, int mask);
+MODULE_SCOPE int TkTextScanCmd(TkText *textPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+MODULE_SCOPE int TkTextSeeCmd(TkText *textPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+MODULE_SCOPE int TkTextSegToOffset(const TkTextSegment *segPtr,
+ const TkTextLine *linePtr);
+MODULE_SCOPE void TkTextSetYView(TkText *textPtr,
+ TkTextIndex *indexPtr, int pickPlace);
+MODULE_SCOPE int TkTextTagCmd(TkText *textPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+MODULE_SCOPE int TkTextImageCmd(TkText *textPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+MODULE_SCOPE int TkTextImageIndex(TkText *textPtr,
+ const char *name, TkTextIndex *indexPtr);
+MODULE_SCOPE int TkTextWindowCmd(TkText *textPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+MODULE_SCOPE int TkTextWindowIndex(TkText *textPtr, const char *name,
+ TkTextIndex *indexPtr);
+MODULE_SCOPE int TkTextYviewCmd(TkText *textPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+MODULE_SCOPE void TkTextWinFreeClient(Tcl_HashEntry *hPtr,
+ TkTextEmbWindowClient *client);
+MODULE_SCOPE void TkTextRunAfterSyncCmd(ClientData clientData);
+#endif /* _TKTEXT */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkTextBTree.c b/tk8.6/generic/tkTextBTree.c
new file mode 100644
index 0000000..81e31dc
--- /dev/null
+++ b/tk8.6/generic/tkTextBTree.c
@@ -0,0 +1,4895 @@
+/*
+ * tkTextBTree.c --
+ *
+ * This file contains code that manages the B-tree representation of text
+ * for Tk's text widget and implements character and toggle segment
+ * types.
+ *
+ * Copyright (c) 1992-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkInt.h"
+#include "tkText.h"
+
+/*
+ * Implementation notes:
+ *
+ * Most of this file is independent of the text widget implementation and
+ * representation now. Without much effort this could be developed further
+ * into a new Tcl object type of which the Tk text widget is one example of a
+ * client.
+ *
+ * The B-tree is set up with a dummy last line of text which must not be
+ * displayed, and must _never_ have a non-zero pixel count. This dummy line is
+ * a historical convenience to avoid other code having to deal with NULL
+ * TkTextLines. Since Tk 8.5, with pixel line height calculations and peer
+ * widgets, this dummy line is becoming somewhat of a liability, and special
+ * case code has been required to deal with it. It is probably a good idea to
+ * investigate removing the dummy line completely. This could result in an
+ * overall simplification (although it would require new special case code to
+ * deal with the fact that '.text index end' would then not really point to a
+ * valid line, rather it would point to the beginning of a non-existent line
+ * one beyond all current lines - we could perhaps define that as a
+ * TkTextIndex with a NULL TkTextLine ptr).
+ */
+
+/*
+ * The data structure below keeps summary information about one tag as part of
+ * the tag information in a node.
+ */
+
+typedef struct Summary {
+ TkTextTag *tagPtr; /* Handle for tag. */
+ int toggleCount; /* Number of transitions into or out of this
+ * tag that occur in the subtree rooted at
+ * this node. */
+ struct Summary *nextPtr; /* Next in list of all tags for same node, or
+ * NULL if at end of list. */
+} Summary;
+
+/*
+ * The data structure below defines a node in the B-tree.
+ */
+
+typedef struct Node {
+ struct Node *parentPtr; /* Pointer to parent node, or NULL if this is
+ * the root. */
+ struct Node *nextPtr; /* Next in list of siblings with the same
+ * parent node, or NULL for end of list. */
+ Summary *summaryPtr; /* First in malloc-ed list of info about tags
+ * in this subtree (NULL if no tag info in the
+ * subtree). */
+ int level; /* Level of this node in the B-tree. 0 refers
+ * to the bottom of the tree (children are
+ * lines, not nodes). */
+ union { /* First in linked list of children. */
+ struct Node *nodePtr; /* Used if level > 0. */
+ TkTextLine *linePtr; /* Used if level == 0. */
+ } children;
+ int numChildren; /* Number of children of this node. */
+ int numLines; /* Total number of lines (leaves) in the
+ * subtree rooted here. */
+ int *numPixels; /* Array containing total number of vertical
+ * display pixels in the subtree rooted here,
+ * one entry for each peer widget. */
+} Node;
+
+/*
+ * Used to avoid having to allocate and deallocate arrays on the fly for
+ * commonly used functions. Must be > 0.
+ */
+
+#define PIXEL_CLIENTS 5
+
+/*
+ * Upper and lower bounds on how many children a node may have: rebalance when
+ * either of these limits is exceeded. MAX_CHILDREN should be twice
+ * MIN_CHILDREN and MIN_CHILDREN must be >= 2.
+ */
+
+#define MAX_CHILDREN 12
+#define MIN_CHILDREN 6
+
+/*
+ * The data structure below defines an entire B-tree. Since text widgets are
+ * the only current B-tree clients, 'clients' and 'pixelReferences' are
+ * identical.
+ */
+
+typedef struct BTree {
+ Node *rootPtr; /* Pointer to root of B-tree. */
+ int clients; /* Number of clients of this B-tree. */
+ int pixelReferences; /* Number of clients of this B-tree which care
+ * about pixel heights. */
+ int stateEpoch; /* Updated each time any aspect of the B-tree
+ * changes. */
+ TkSharedText *sharedTextPtr;/* Used to find tagTable in consistency
+ * checking code, and to access list of all
+ * B-tree clients. */
+ int startEndCount;
+ TkTextLine **startEnd;
+ TkText **startEndRef;
+} BTree;
+
+/*
+ * The structure below is used to pass information between
+ * TkBTreeGetTags and IncCount:
+ */
+
+typedef struct TagInfo {
+ int numTags; /* Number of tags for which there is currently
+ * information in tags and counts. */
+ int arraySize; /* Number of entries allocated for tags and
+ * counts. */
+ TkTextTag **tagPtrs; /* Array of tags seen so far. Malloc-ed. */
+ int *counts; /* Toggle count (so far) for each entry in
+ * tags. Malloc-ed. */
+} TagInfo;
+
+/*
+ * Variable that indicates whether to enable consistency checks for debugging.
+ */
+
+int tkBTreeDebug = 0;
+
+/*
+ * Macros that determine how much space to allocate for new segments:
+ */
+
+#define CSEG_SIZE(chars) ((unsigned) (Tk_Offset(TkTextSegment, body) \
+ + 1 + (chars)))
+#define TSEG_SIZE ((unsigned) (Tk_Offset(TkTextSegment, body) \
+ + sizeof(TkTextToggle)))
+
+/*
+ * Forward declarations for functions defined in this file:
+ */
+
+static int AdjustPixelClient(BTree *treePtr, int defaultHeight,
+ Node *nodePtr, TkTextLine *start, TkTextLine *end,
+ int useReference, int newPixelReferences,
+ int *counting);
+static void ChangeNodeToggleCount(Node *nodePtr,
+ TkTextTag *tagPtr, int delta);
+static void CharCheckProc(TkTextSegment *segPtr,
+ TkTextLine *linePtr);
+static int CharDeleteProc(TkTextSegment *segPtr,
+ TkTextLine *linePtr, int treeGone);
+static TkTextSegment * CharCleanupProc(TkTextSegment *segPtr,
+ TkTextLine *linePtr);
+static TkTextSegment * CharSplitProc(TkTextSegment *segPtr, int index);
+static void CheckNodeConsistency(Node *nodePtr, int references);
+static void CleanupLine(TkTextLine *linePtr);
+static void DeleteSummaries(Summary *tagPtr);
+static void DestroyNode(Node *nodePtr);
+static TkTextSegment * FindTagEnd(TkTextBTree tree, TkTextTag *tagPtr,
+ TkTextIndex *indexPtr);
+static void IncCount(TkTextTag *tagPtr, int inc,
+ TagInfo *tagInfoPtr);
+static void Rebalance(BTree *treePtr, Node *nodePtr);
+static void RecomputeNodeCounts(BTree *treePtr, Node *nodePtr);
+static void RemovePixelClient(BTree *treePtr, Node *nodePtr,
+ int overwriteWithLast);
+static TkTextSegment * SplitSeg(TkTextIndex *indexPtr);
+static void ToggleCheckProc(TkTextSegment *segPtr,
+ TkTextLine *linePtr);
+static TkTextSegment * ToggleCleanupProc(TkTextSegment *segPtr,
+ TkTextLine *linePtr);
+static int ToggleDeleteProc(TkTextSegment *segPtr,
+ TkTextLine *linePtr, int treeGone);
+static void ToggleLineChangeProc(TkTextSegment *segPtr,
+ TkTextLine *linePtr);
+static TkTextSegment * FindTagStart(TkTextBTree tree, TkTextTag *tagPtr,
+ TkTextIndex *indexPtr);
+static void AdjustStartEndRefs(BTree *treePtr, TkText *textPtr,
+ int action);
+
+/*
+ * Actions for use by AdjustStartEndRefs
+ */
+
+#define TEXT_ADD_REFS 1
+#define TEXT_REMOVE_REFS 2
+
+/*
+ * Type record for character segments:
+ */
+
+const Tk_SegType tkTextCharType = {
+ "character", /* name */
+ 0, /* leftGravity */
+ CharSplitProc, /* splitProc */
+ CharDeleteProc, /* deleteProc */
+ CharCleanupProc, /* cleanupProc */
+ NULL, /* lineChangeProc */
+ TkTextCharLayoutProc, /* layoutProc */
+ CharCheckProc /* checkProc */
+};
+
+/*
+ * Type record for segments marking the beginning of a tagged range:
+ */
+
+const Tk_SegType tkTextToggleOnType = {
+ "toggleOn", /* name */
+ 0, /* leftGravity */
+ NULL, /* splitProc */
+ ToggleDeleteProc, /* deleteProc */
+ ToggleCleanupProc, /* cleanupProc */
+ ToggleLineChangeProc, /* lineChangeProc */
+ NULL, /* layoutProc */
+ ToggleCheckProc /* checkProc */
+};
+
+/*
+ * Type record for segments marking the end of a tagged range:
+ */
+
+const Tk_SegType tkTextToggleOffType = {
+ "toggleOff", /* name */
+ 1, /* leftGravity */
+ NULL, /* splitProc */
+ ToggleDeleteProc, /* deleteProc */
+ ToggleCleanupProc, /* cleanupProc */
+ ToggleLineChangeProc, /* lineChangeProc */
+ NULL, /* layoutProc */
+ ToggleCheckProc /* checkProc */
+};
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkBTreeCreate --
+ *
+ * This function is called to create a new text B-tree.
+ *
+ * Results:
+ * The return value is a pointer to a new B-tree containing one line with
+ * nothing but a newline character.
+ *
+ * Side effects:
+ * Memory is allocated and initialized.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkTextBTree
+TkBTreeCreate(
+ TkSharedText *sharedTextPtr)
+{
+ register BTree *treePtr;
+ register Node *rootPtr;
+ register TkTextLine *linePtr, *linePtr2;
+ register TkTextSegment *segPtr;
+
+ /*
+ * The tree will initially have two empty lines. The second line isn't
+ * actually part of the tree's contents, but its presence makes several
+ * operations easier. The tree will have one node, which is also the root
+ * of the tree.
+ */
+
+ rootPtr = ckalloc(sizeof(Node));
+ linePtr = ckalloc(sizeof(TkTextLine));
+ linePtr2 = ckalloc(sizeof(TkTextLine));
+
+ rootPtr->parentPtr = NULL;
+ rootPtr->nextPtr = NULL;
+ rootPtr->summaryPtr = NULL;
+ rootPtr->level = 0;
+ rootPtr->children.linePtr = linePtr;
+ rootPtr->numChildren = 2;
+ rootPtr->numLines = 2;
+
+ /*
+ * The tree currently has no registered clients, so all pixel count
+ * pointers are simply NULL.
+ */
+
+ rootPtr->numPixels = NULL;
+ linePtr->pixels = NULL;
+ linePtr2->pixels = NULL;
+
+ linePtr->parentPtr = rootPtr;
+ linePtr->nextPtr = linePtr2;
+ segPtr = ckalloc(CSEG_SIZE(1));
+ linePtr->segPtr = segPtr;
+ segPtr->typePtr = &tkTextCharType;
+ segPtr->nextPtr = NULL;
+ segPtr->size = 1;
+ segPtr->body.chars[0] = '\n';
+ segPtr->body.chars[1] = 0;
+
+ linePtr2->parentPtr = rootPtr;
+ linePtr2->nextPtr = NULL;
+ segPtr = ckalloc(CSEG_SIZE(1));
+ linePtr2->segPtr = segPtr;
+ segPtr->typePtr = &tkTextCharType;
+ segPtr->nextPtr = NULL;
+ segPtr->size = 1;
+ segPtr->body.chars[0] = '\n';
+ segPtr->body.chars[1] = 0;
+
+ treePtr = ckalloc(sizeof(BTree));
+ treePtr->sharedTextPtr = sharedTextPtr;
+ treePtr->rootPtr = rootPtr;
+ treePtr->clients = 0;
+ treePtr->stateEpoch = 0;
+ treePtr->pixelReferences = 0;
+ treePtr->startEndCount = 0;
+ treePtr->startEnd = NULL;
+ treePtr->startEndRef = NULL;
+
+ return (TkTextBTree) treePtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkBTreeAddClient --
+ *
+ * This function is called to provide a client with access to a given
+ * B-tree. If the client wishes to make use of the B-tree's pixel height
+ * storage, caching and calculation mechanisms, then a non-negative
+ * 'defaultHeight' must be provided. In this case the return value is a
+ * pixel tree reference which must be provided in all of the B-tree API
+ * which refers to or modifies pixel heights:
+ *
+ * TkBTreeAdjustPixelHeight,
+ * TkBTreeFindPixelLine,
+ * TkBTreeNumPixels,
+ * TkBTreePixelsTo,
+ * (and two private functions AdjustPixelClient, RemovePixelClient).
+ *
+ * If this is not provided, then the above functions must never be called
+ * for this client.
+ *
+ * Results:
+ * The return value is the pixelReference used by the B-tree to refer to
+ * pixel counts for the new client. It should be stored by the caller. If
+ * defaultHeight was negative, then the return value will be -1.
+ *
+ * Side effects:
+ * Memory may be allocated and initialized.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkBTreeAddClient(
+ TkTextBTree tree, /* B-tree to add a client to. */
+ TkText *textPtr, /* Client to add. */
+ int defaultHeight) /* Default line height for the new client, or
+ * -1 if no pixel heights are to be kept. */
+{
+ register BTree *treePtr = (BTree *) tree;
+
+ if (treePtr == NULL) {
+ Tcl_Panic("NULL treePtr in TkBTreeAddClient");
+ }
+
+ if (textPtr->start != NULL || textPtr->end != NULL) {
+ AdjustStartEndRefs(treePtr, textPtr, TEXT_ADD_REFS);
+ }
+
+ if (defaultHeight >= 0) {
+ TkTextLine *end;
+ int counting = (textPtr->start == NULL ? 1 : 0);
+ int useReference = treePtr->pixelReferences;
+
+ /*
+ * We must set the 'end' value in AdjustPixelClient so that the last
+ * dummy line in the B-tree doesn't contain a pixel height.
+ */
+
+ end = textPtr->end;
+ if (end == NULL) {
+ end = TkBTreeFindLine(tree, NULL, TkBTreeNumLines(tree, NULL));
+ }
+ AdjustPixelClient(treePtr, defaultHeight, treePtr->rootPtr,
+ textPtr->start, end, useReference, useReference+1, &counting);
+
+ textPtr->pixelReference = useReference;
+ treePtr->pixelReferences++;
+ } else {
+ textPtr->pixelReference = -1;
+ }
+ treePtr->clients++;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkBTreeClientRangeChanged --
+ *
+ * Called when the -startline or -endline options of a text widget client
+ * of the B-tree have changed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Lots of processing of the B-tree is done, with potential for memory to
+ * be allocated and initialized for the pixel heights of the widget.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkBTreeClientRangeChanged(
+ TkText *textPtr, /* Client whose start, end have changed. */
+ int defaultHeight) /* Default line height for the new client, or
+ * -1 if no pixel heights are to be kept. */
+{
+ TkTextLine *end;
+ BTree *treePtr = (BTree *) textPtr->sharedTextPtr->tree;
+
+ int counting = (textPtr->start == NULL ? 1 : 0);
+ int useReference = textPtr->pixelReference;
+
+ AdjustStartEndRefs(treePtr, textPtr, TEXT_ADD_REFS | TEXT_REMOVE_REFS);
+
+ /*
+ * We must set the 'end' value in AdjustPixelClient so that the last dummy
+ * line in the B-tree doesn't contain a pixel height.
+ */
+
+ end = textPtr->end;
+ if (end == NULL) {
+ end = TkBTreeFindLine(textPtr->sharedTextPtr->tree,
+ NULL, TkBTreeNumLines(textPtr->sharedTextPtr->tree, NULL));
+ }
+ AdjustPixelClient(treePtr, defaultHeight, treePtr->rootPtr,
+ textPtr->start, end, useReference, treePtr->pixelReferences,
+ &counting);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkBTreeDestroy --
+ *
+ * Delete a B-tree, recycling all of the storage it contains.
+ *
+ * Results:
+ * The tree is deleted, so 'tree' should never again be used.
+ *
+ * Side effects:
+ * Memory is freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkBTreeDestroy(
+ TkTextBTree tree) /* Tree to clean up. */
+{
+ BTree *treePtr = (BTree *) tree;
+
+ /*
+ * There's no need to loop over each client of the tree, calling
+ * 'TkBTreeRemoveClient', since the 'DestroyNode' will clean everything up
+ * itself.
+ */
+
+ DestroyNode(treePtr->rootPtr);
+ if (treePtr->startEnd != NULL) {
+ ckfree(treePtr->startEnd);
+ ckfree(treePtr->startEndRef);
+ }
+ ckfree(treePtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkBTreeEpoch --
+ *
+ * Return the epoch for the B-tree. This number is incremented any time
+ * anything changes in the tree.
+ *
+ * Results:
+ * The epoch number.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkBTreeEpoch(
+ TkTextBTree tree) /* Tree to get epoch for. */
+{
+ BTree *treePtr = (BTree *) tree;
+ return treePtr->stateEpoch;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkBTreeRemoveClient --
+ *
+ * Remove a client widget from its B-tree, cleaning up the pixel arrays
+ * which it uses if necessary. If this is the last such widget, we also
+ * destroy the whole tree.
+ *
+ * Results:
+ * All tree-specific aspects of the given client are deleted. If no more
+ * references exist, then the given tree is also deleted (in which case
+ * 'tree' must not be used again).
+ *
+ * Side effects:
+ * Memory may be freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkBTreeRemoveClient(
+ TkTextBTree tree, /* Tree to remove client from. */
+ TkText *textPtr) /* Client to remove. */
+{
+ BTree *treePtr = (BTree *) tree;
+ int pixelReference = textPtr->pixelReference;
+
+ if (treePtr->clients == 1) {
+ /*
+ * The last reference to the tree.
+ */
+
+ DestroyNode(treePtr->rootPtr);
+ ckfree(treePtr);
+ return;
+ } else if (pixelReference == -1) {
+ /*
+ * A client which doesn't care about pixels.
+ */
+
+ treePtr->clients--;
+ } else {
+ /*
+ * Clean up pixel data for the given reference.
+ */
+
+ if (pixelReference == (treePtr->pixelReferences-1)) {
+ /*
+ * The widget we're removing has the last index, so deletion is
+ * easier.
+ */
+
+ RemovePixelClient(treePtr, treePtr->rootPtr, -1);
+ } else {
+ TkText *adjustPtr;
+
+ RemovePixelClient(treePtr, treePtr->rootPtr, pixelReference);
+
+ /*
+ * Now we need to adjust the 'pixelReference' of the peer widget
+ * whose storage we've just moved.
+ */
+
+ adjustPtr = treePtr->sharedTextPtr->peers;
+ while (adjustPtr != NULL) {
+ if (adjustPtr->pixelReference == treePtr->pixelReferences-1) {
+ adjustPtr->pixelReference = pixelReference;
+ break;
+ }
+ adjustPtr = adjustPtr->next;
+ }
+ if (adjustPtr == NULL) {
+ Tcl_Panic("Couldn't find text widget with correct reference");
+ }
+ }
+ treePtr->pixelReferences--;
+ treePtr->clients--;
+ }
+
+ if (textPtr->start != NULL || textPtr->end != NULL) {
+ AdjustStartEndRefs(treePtr, textPtr, TEXT_REMOVE_REFS);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AdjustStartEndRefs --
+ *
+ * Modify B-tree's cache of start, end lines for the given text widget.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The number of cached items may change (treePtr->startEndCount).
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+AdjustStartEndRefs(
+ BTree *treePtr, /* The entire B-tree. */
+ TkText *textPtr, /* The text widget for which we want to adjust
+ * it's start and end cache. */
+ int action) /* Action to perform. */
+{
+ if (action & TEXT_REMOVE_REFS) {
+ int i = 0;
+ int count = 0;
+
+ while (i < treePtr->startEndCount) {
+ if (i != count) {
+ treePtr->startEnd[count] = treePtr->startEnd[i];
+ treePtr->startEndRef[count] = treePtr->startEndRef[i];
+ }
+ if (treePtr->startEndRef[i] != textPtr) {
+ count++;
+ }
+ i++;
+ }
+ treePtr->startEndCount = count;
+ treePtr->startEnd = ckrealloc(treePtr->startEnd,
+ sizeof(TkTextLine *) * count);
+ treePtr->startEndRef = ckrealloc(treePtr->startEndRef,
+ sizeof(TkText *) * count);
+ }
+ if ((action & TEXT_ADD_REFS)
+ && (textPtr->start != NULL || textPtr->end != NULL)) {
+ int count;
+
+ if (textPtr->start != NULL) {
+ treePtr->startEndCount++;
+ }
+ if (textPtr->end != NULL) {
+ treePtr->startEndCount++;
+ }
+
+ count = treePtr->startEndCount;
+
+ treePtr->startEnd = ckrealloc(treePtr->startEnd,
+ sizeof(TkTextLine *) * count);
+ treePtr->startEndRef = ckrealloc(treePtr->startEndRef,
+ sizeof(TkText *) * count);
+
+ if (textPtr->start != NULL) {
+ count--;
+ treePtr->startEnd[count] = textPtr->start;
+ treePtr->startEndRef[count] = textPtr;
+ }
+ if (textPtr->end != NULL) {
+ count--;
+ treePtr->startEnd[count] = textPtr->end;
+ treePtr->startEndRef[count] = textPtr;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AdjustPixelClient --
+ *
+ * Utility function used to update all data structures for the existence
+ * of a new peer widget based on this B-tree, or for the modification of
+ * the start, end lines of an existing peer widget.
+ *
+ * Immediately _after_ calling this, treePtr->pixelReferences and
+ * treePtr->clients should be adjusted if needed (i.e. if this is a new
+ * peer).
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * All the storage for Nodes and TkTextLines in the tree may be adjusted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+AdjustPixelClient(
+ BTree *treePtr, /* Pointer to tree. */
+ int defaultHeight, /* Default pixel line height, which can be
+ * zero. */
+ Node *nodePtr, /* Adjust from this node downwards. */
+ TkTextLine *start, /* First line for this pixel client. */
+ TkTextLine *end, /* Last line for this pixel client. */
+ int useReference, /* pixel reference for the client we are
+ * adding or changing. */
+ int newPixelReferences, /* New number of pixel references to this
+ * B-tree. */
+ int *counting) /* References an integer which is zero if
+ * we're outside the relevant range for this
+ * client, and 1 if we're inside. */
+{
+ int pixelCount = 0;
+
+ /*
+ * Traverse entire tree down from nodePtr, reallocating pixel structures
+ * for each Node and TkTextLine, adding room for the new peer's pixel
+ * information (1 extra int per Node, 2 extra ints per TkTextLine). Also
+ * copy the information from the last peer into the new space (so it
+ * contains something sensible).
+ */
+
+ if (nodePtr->level != 0) {
+ Node *loopPtr = nodePtr->children.nodePtr;
+
+ while (loopPtr != NULL) {
+ pixelCount += AdjustPixelClient(treePtr, defaultHeight, loopPtr,
+ start, end, useReference, newPixelReferences, counting);
+ loopPtr = loopPtr->nextPtr;
+ }
+ } else {
+ register TkTextLine *linePtr = nodePtr->children.linePtr;
+
+ while (linePtr != NULL) {
+ if (!*counting && (linePtr == start)) {
+ *counting = 1;
+ }
+ if (*counting && (linePtr == end)) {
+ *counting = 0;
+ }
+ if (newPixelReferences != treePtr->pixelReferences) {
+ linePtr->pixels = ckrealloc(linePtr->pixels,
+ sizeof(int) * 2 * newPixelReferences);
+ }
+
+ /*
+ * Notice that for the very last line, we are never counting and
+ * therefore this always has a height of 0 and an epoch of 1.
+ */
+
+ linePtr->pixels[2*useReference] = (*counting ? defaultHeight : 0);
+ linePtr->pixels[2*useReference+1] = (*counting ? 0 : 1);
+ pixelCount += linePtr->pixels[2*useReference];
+
+ linePtr = linePtr->nextPtr;
+ }
+ }
+ if (newPixelReferences != treePtr->pixelReferences) {
+ nodePtr->numPixels = ckrealloc(nodePtr->numPixels,
+ sizeof(int) * newPixelReferences);
+ }
+ nodePtr->numPixels[useReference] = pixelCount;
+ return pixelCount;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * RemovePixelClient --
+ *
+ * Utility function used to update all data structures for the removal of
+ * a peer widget which used to be based on this B-tree.
+ *
+ * Immediately _after_ calling this, treePtr->clients should be
+ * decremented.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * All the storage for Nodes and TkTextLines in the tree may be adjusted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+RemovePixelClient(
+ BTree *treePtr, /* Pointer to tree. */
+ Node *nodePtr, /* Adjust from this node downwards. */
+ int overwriteWithLast) /* Over-write this peer widget's information
+ * with the last one. */
+{
+ /*
+ * Traverse entire tree down from nodePtr, reallocating pixel structures
+ * for each Node and TkTextLine, removing space allocated for one peer. If
+ * 'overwriteWithLast' is not -1, then copy the information which was in
+ * the last slot on top of one of the others (i.e. it's not the last one
+ * we're deleting).
+ */
+
+ if (overwriteWithLast != -1) {
+ nodePtr->numPixels[overwriteWithLast] =
+ nodePtr->numPixels[treePtr->pixelReferences-1];
+ }
+ if (treePtr->pixelReferences == 1) {
+ ckfree(nodePtr->numPixels);
+ nodePtr->numPixels = NULL;
+ } else {
+ nodePtr->numPixels = ckrealloc(nodePtr->numPixels,
+ sizeof(int) * (treePtr->pixelReferences - 1));
+ }
+ if (nodePtr->level != 0) {
+ nodePtr = nodePtr->children.nodePtr;
+ while (nodePtr != NULL) {
+ RemovePixelClient(treePtr, nodePtr, overwriteWithLast);
+ nodePtr = nodePtr->nextPtr;
+ }
+ } else {
+ register TkTextLine *linePtr = nodePtr->children.linePtr;
+ while (linePtr != NULL) {
+ if (overwriteWithLast != -1) {
+ linePtr->pixels[2*overwriteWithLast] =
+ linePtr->pixels[2*(treePtr->pixelReferences-1)];
+ linePtr->pixels[1+2*overwriteWithLast] =
+ linePtr->pixels[1+2*(treePtr->pixelReferences-1)];
+ }
+ if (treePtr->pixelReferences == 1) {
+ linePtr->pixels = NULL;
+ } else {
+ linePtr->pixels = ckrealloc(linePtr->pixels,
+ sizeof(int) * 2 * (treePtr->pixelReferences-1));
+ }
+ linePtr = linePtr->nextPtr;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyNode --
+ *
+ * This is a recursive utility function used during the deletion of a
+ * B-tree.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * All the storage for nodePtr and its descendants is freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DestroyNode(
+ register Node *nodePtr) /* Destroy from this node downwards. */
+{
+ if (nodePtr->level == 0) {
+ TkTextLine *linePtr;
+ TkTextSegment *segPtr;
+
+ while (nodePtr->children.linePtr != NULL) {
+ linePtr = nodePtr->children.linePtr;
+ nodePtr->children.linePtr = linePtr->nextPtr;
+ while (linePtr->segPtr != NULL) {
+ segPtr = linePtr->segPtr;
+ linePtr->segPtr = segPtr->nextPtr;
+ segPtr->typePtr->deleteProc(segPtr, linePtr, 1);
+ }
+ ckfree(linePtr->pixels);
+ ckfree(linePtr);
+ }
+ } else {
+ register Node *childPtr;
+
+ while (nodePtr->children.nodePtr != NULL) {
+ childPtr = nodePtr->children.nodePtr;
+ nodePtr->children.nodePtr = childPtr->nextPtr;
+ DestroyNode(childPtr);
+ }
+ }
+ DeleteSummaries(nodePtr->summaryPtr);
+ ckfree(nodePtr->numPixels);
+ ckfree(nodePtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DeleteSummaries --
+ *
+ * Free up all of the memory in a list of tag summaries associated with a
+ * node.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Storage is released.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DeleteSummaries(
+ register Summary *summaryPtr)
+ /* First in list of node's tag summaries. */
+{
+ register Summary *nextPtr;
+
+ while (summaryPtr != NULL) {
+ nextPtr = summaryPtr->nextPtr;
+ ckfree(summaryPtr);
+ summaryPtr = nextPtr;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkBTreeAdjustPixelHeight --
+ *
+ * Adjust the pixel height of a given logical line to the specified
+ * value.
+ *
+ * Results:
+ * Total number of valid pixels currently known in the tree.
+ *
+ * Side effects:
+ * Updates overall data structures so pixel height count is consistent.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkBTreeAdjustPixelHeight(
+ const TkText *textPtr, /* Client of the B-tree. */
+ register TkTextLine *linePtr,
+ /* The logical line to update. */
+ int newPixelHeight, /* The line's known height in pixels. */
+ int mergedLogicalLines) /* The number of extra logical lines which
+ * have been merged with this one (due to
+ * elided eols). They will have their pixel
+ * height set to zero, and the total pixel
+ * height associated with the given
+ * linePtr. */
+{
+ register Node *nodePtr;
+ int changeToPixelCount; /* Counts change to total number of pixels in
+ * file. */
+ int pixelReference = textPtr->pixelReference;
+
+ changeToPixelCount = newPixelHeight - linePtr->pixels[2 * pixelReference];
+
+ /*
+ * Increment the pixel counts in all the parent nodes of the current line,
+ * then rebalance the tree if necessary.
+ */
+
+ nodePtr = linePtr->parentPtr;
+ nodePtr->numPixels[pixelReference] += changeToPixelCount;
+
+ while (nodePtr->parentPtr != NULL) {
+ nodePtr = nodePtr->parentPtr;
+ nodePtr->numPixels[pixelReference] += changeToPixelCount;
+ }
+
+ linePtr->pixels[2 * pixelReference] = newPixelHeight;
+
+ /*
+ * Any merged logical lines must have their height set to zero.
+ */
+
+ while (mergedLogicalLines-- > 0) {
+ linePtr = TkBTreeNextLine(textPtr, linePtr);
+ TkBTreeAdjustPixelHeight(textPtr, linePtr, 0, 0);
+ }
+
+ /*
+ * Return total number of pixels in the tree.
+ */
+
+ return nodePtr->numPixels[pixelReference];
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkBTreeInsertChars --
+ *
+ * Insert characters at a given position in a B-tree.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Characters are added to the B-tree at the given position. If the
+ * string contains newlines, new lines will be added, which could cause
+ * the structure of the B-tree to change.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkBTreeInsertChars(
+ TkTextBTree tree, /* Tree to insert into. */
+ register TkTextIndex *indexPtr,
+ /* Indicates where to insert text. When the
+ * function returns, this index is no longer
+ * valid because of changes to the segment
+ * structure. */
+ const char *string) /* Pointer to bytes to insert (may contain
+ * newlines, must be null-terminated). */
+{
+ register Node *nodePtr;
+ register TkTextSegment *prevPtr;
+ /* The segment just before the first new
+ * segment (NULL means new segment is at
+ * beginning of line). */
+ TkTextSegment *curPtr; /* Current segment; new characters are
+ * inserted just after this one. NULL means
+ * insert at beginning of line. */
+ TkTextLine *linePtr; /* Current line (new segments are added to
+ * this line). */
+ register TkTextSegment *segPtr;
+ TkTextLine *newLinePtr;
+ int chunkSize; /* # characters in current chunk. */
+ register const char *eol; /* Pointer to character just after last one in
+ * current chunk. */
+ int changeToLineCount; /* Counts change to total number of lines in
+ * file. */
+ int *changeToPixelCount; /* Counts change to total number of pixels in
+ * file. */
+ int ref;
+ int pixels[PIXEL_CLIENTS];
+
+ BTree *treePtr = (BTree *) tree;
+ treePtr->stateEpoch++;
+ prevPtr = SplitSeg(indexPtr);
+ linePtr = indexPtr->linePtr;
+ curPtr = prevPtr;
+
+ /*
+ * Chop the string up into lines and create a new segment for each line,
+ * plus a new line for the leftovers from the previous line.
+ */
+
+ changeToLineCount = 0;
+ if (treePtr->pixelReferences > PIXEL_CLIENTS) {
+ changeToPixelCount = ckalloc(sizeof(int) * treePtr->pixelReferences);
+ } else {
+ changeToPixelCount = pixels;
+ }
+ for (ref = 0; ref < treePtr->pixelReferences; ref++) {
+ changeToPixelCount[ref] = 0;
+ }
+
+ while (*string != 0) {
+ for (eol = string; *eol != 0; eol++) {
+ if (*eol == '\n') {
+ eol++;
+ break;
+ }
+ }
+ chunkSize = eol-string;
+ segPtr = ckalloc(CSEG_SIZE(chunkSize));
+ segPtr->typePtr = &tkTextCharType;
+ if (curPtr == NULL) {
+ segPtr->nextPtr = linePtr->segPtr;
+ linePtr->segPtr = segPtr;
+ } else {
+ segPtr->nextPtr = curPtr->nextPtr;
+ curPtr->nextPtr = segPtr;
+ }
+ segPtr->size = chunkSize;
+ memcpy(segPtr->body.chars, string, (size_t) chunkSize);
+ segPtr->body.chars[chunkSize] = 0;
+
+ if (eol[-1] != '\n') {
+ break;
+ }
+
+ /*
+ * The chunk ended with a newline, so create a new TkTextLine and move
+ * the remainder of the old line to it.
+ */
+
+ newLinePtr = ckalloc(sizeof(TkTextLine));
+ newLinePtr->pixels =
+ ckalloc(sizeof(int) * 2 * treePtr->pixelReferences);
+
+ newLinePtr->parentPtr = linePtr->parentPtr;
+ newLinePtr->nextPtr = linePtr->nextPtr;
+ linePtr->nextPtr = newLinePtr;
+ newLinePtr->segPtr = segPtr->nextPtr;
+
+ /*
+ * Set up a starting default height, which will be re-adjusted later.
+ * We need to do this for each referenced widget.
+ */
+
+ for (ref = 0; ref < treePtr->pixelReferences; ref++) {
+ newLinePtr->pixels[2 * ref] = linePtr->pixels[2 * ref];
+ newLinePtr->pixels[2 * ref + 1] = 0;
+ changeToPixelCount[ref] += newLinePtr->pixels[2 * ref];
+ }
+
+ segPtr->nextPtr = NULL;
+ linePtr = newLinePtr;
+ curPtr = NULL;
+ changeToLineCount++;
+
+ string = eol;
+ }
+
+ /*
+ * I don't believe it's possible for either of the two lines passed to
+ * this function to be the last line of text, but the function is robust
+ * to that case anyway. (We must never re-calculate the line height of
+ * the last line).
+ */
+
+ TkTextInvalidateLineMetrics(treePtr->sharedTextPtr, NULL,
+ indexPtr->linePtr, changeToLineCount, TK_TEXT_INVALIDATE_INSERT);
+
+ /*
+ * Cleanup the starting line for the insertion, plus the ending line if
+ * it's different.
+ */
+
+ CleanupLine(indexPtr->linePtr);
+ if (linePtr != indexPtr->linePtr) {
+ CleanupLine(linePtr);
+ }
+
+ /*
+ * Increment the line and pixel counts in all the parent nodes of the
+ * insertion point, then rebalance the tree if necessary.
+ */
+
+ for (nodePtr = linePtr->parentPtr ; nodePtr != NULL;
+ nodePtr = nodePtr->parentPtr) {
+ nodePtr->numLines += changeToLineCount;
+ for (ref = 0; ref < treePtr->pixelReferences; ref++) {
+ nodePtr->numPixels[ref] += changeToPixelCount[ref];
+ }
+ }
+ if (treePtr->pixelReferences > PIXEL_CLIENTS) {
+ ckfree(changeToPixelCount);
+ }
+
+ nodePtr = linePtr->parentPtr;
+ nodePtr->numChildren += changeToLineCount;
+ if (nodePtr->numChildren > MAX_CHILDREN) {
+ Rebalance(treePtr, nodePtr);
+ }
+
+ if (tkBTreeDebug) {
+ TkBTreeCheck(indexPtr->tree);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * SplitSeg --
+ *
+ * This function is called before adding or deleting segments. It does
+ * three things: (a) it finds the segment containing indexPtr; (b) if
+ * there are several such segments (because some segments have zero
+ * length) then it picks the first segment that does not have left
+ * gravity; (c) if the index refers to the middle of a segment then it
+ * splits the segment so that the index now refers to the beginning of a
+ * segment.
+ *
+ * Results:
+ * The return value is a pointer to the segment just before the segment
+ * corresponding to indexPtr (as described above). If the segment
+ * corresponding to indexPtr is the first in its line then the return
+ * value is NULL.
+ *
+ * Side effects:
+ * The segment referred to by indexPtr is split unless indexPtr refers to
+ * its first character.
+ *
+ *--------------------------------------------------------------
+ */
+
+static TkTextSegment *
+SplitSeg(
+ TkTextIndex *indexPtr) /* Index identifying position at which to
+ * split a segment. */
+{
+ TkTextSegment *prevPtr, *segPtr;
+ TkTextLine *linePtr;
+ int count = indexPtr->byteIndex;
+
+ linePtr = indexPtr->linePtr;
+ prevPtr = NULL;
+ segPtr = linePtr->segPtr;
+
+ while (segPtr != NULL) {
+ if (segPtr->size > count) {
+ if (count == 0) {
+ return prevPtr;
+ }
+ segPtr = segPtr->typePtr->splitProc(segPtr, count);
+ if (prevPtr == NULL) {
+ indexPtr->linePtr->segPtr = segPtr;
+ } else {
+ prevPtr->nextPtr = segPtr;
+ }
+ return segPtr;
+ } else if ((segPtr->size == 0) && (count == 0)
+ && !segPtr->typePtr->leftGravity) {
+ return prevPtr;
+ }
+
+ count -= segPtr->size;
+ prevPtr = segPtr;
+ segPtr = segPtr->nextPtr;
+ if (segPtr == NULL) {
+ /*
+ * Two logical lines merged into one display line through eliding
+ * of a newline.
+ */
+
+ linePtr = TkBTreeNextLine(NULL, linePtr);
+ if (linePtr == NULL) {
+ /*
+ * Reached end of the text.
+ */
+ } else {
+ segPtr = linePtr->segPtr;
+ }
+ }
+ }
+ Tcl_Panic("SplitSeg reached end of line!");
+ return NULL;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * CleanupLine --
+ *
+ * This function is called after modifications have been made to a line.
+ * It scans over all of the segments in the line, giving each a chance to
+ * clean itself up, e.g. by merging with the following segments, updating
+ * internal information, etc.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Depends on what the segment-specific cleanup functions do.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+CleanupLine(
+ TkTextLine *linePtr) /* Line to be cleaned up. */
+{
+ TkTextSegment *segPtr, **prevPtrPtr;
+ int anyChanges;
+
+ /*
+ * Make a pass over all of the segments in the line, giving each a chance
+ * to clean itself up. This could potentially change the structure of the
+ * line, e.g. by merging two segments together or having two segments
+ * cancel themselves; if so, then repeat the whole process again, since
+ * the first structure change might make other structure changes possible.
+ * Repeat until eventually there are no changes.
+ */
+
+ while (1) {
+ anyChanges = 0;
+ for (prevPtrPtr = &linePtr->segPtr, segPtr = *prevPtrPtr;
+ segPtr != NULL;
+ prevPtrPtr = &(*prevPtrPtr)->nextPtr, segPtr = *prevPtrPtr) {
+ if (segPtr->typePtr->cleanupProc != NULL) {
+ *prevPtrPtr = segPtr->typePtr->cleanupProc(segPtr, linePtr);
+ if (segPtr != *prevPtrPtr) {
+ anyChanges = 1;
+ }
+ }
+ }
+ if (!anyChanges) {
+ break;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkBTreeDeleteIndexRange --
+ *
+ * Delete a range of characters from a B-tree. The caller must make sure
+ * that the final newline of the B-tree is never deleted.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Information is deleted from the B-tree. This can cause the internal
+ * structure of the B-tree to change. Note: because of changes to the
+ * B-tree structure, the indices pointed to by index1Ptr and index2Ptr
+ * should not be used after this function returns.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkBTreeDeleteIndexRange(
+ TkTextBTree tree, /* Tree to delete from. */
+ register TkTextIndex *index1Ptr,
+ /* Indicates first character that is to be
+ * deleted. */
+ register TkTextIndex *index2Ptr)
+ /* Indicates character just after the last one
+ * that is to be deleted. */
+{
+ TkTextSegment *prevPtr; /* The segment just before the start of the
+ * deletion range. */
+ TkTextSegment *lastPtr; /* The segment just after the end of the
+ * deletion range. */
+ TkTextSegment *segPtr, *nextPtr;
+ TkTextLine *curLinePtr;
+ Node *curNodePtr, *nodePtr;
+ int changeToLineCount = 0;
+ int ref;
+ BTree *treePtr = (BTree *) tree;
+
+ treePtr->stateEpoch++;
+
+ /*
+ * Tricky point: split at index2Ptr first; otherwise the split at
+ * index2Ptr may invalidate segPtr and/or prevPtr.
+ */
+
+ lastPtr = SplitSeg(index2Ptr);
+ if (lastPtr != NULL) {
+ lastPtr = lastPtr->nextPtr;
+ } else {
+ lastPtr = index2Ptr->linePtr->segPtr;
+ }
+ prevPtr = SplitSeg(index1Ptr);
+ if (prevPtr != NULL) {
+ segPtr = prevPtr->nextPtr;
+ prevPtr->nextPtr = lastPtr;
+ } else {
+ segPtr = index1Ptr->linePtr->segPtr;
+ index1Ptr->linePtr->segPtr = lastPtr;
+ }
+
+ /*
+ * Delete all of the segments between prevPtr and lastPtr.
+ */
+
+ curLinePtr = index1Ptr->linePtr;
+
+ curNodePtr = curLinePtr->parentPtr;
+ while (segPtr != lastPtr) {
+ if (segPtr == NULL) {
+ TkTextLine *nextLinePtr;
+
+ /*
+ * We just ran off the end of a line. First find the next line,
+ * then go back to the old line and delete it (unless it's the
+ * starting line for the range).
+ */
+
+ nextLinePtr = TkBTreeNextLine(NULL, curLinePtr);
+ if (curLinePtr != index1Ptr->linePtr) {
+ if (curNodePtr == index1Ptr->linePtr->parentPtr) {
+ index1Ptr->linePtr->nextPtr = curLinePtr->nextPtr;
+ } else {
+ curNodePtr->children.linePtr = curLinePtr->nextPtr;
+ }
+ for (nodePtr = curNodePtr; nodePtr != NULL;
+ nodePtr = nodePtr->parentPtr) {
+ nodePtr->numLines--;
+ for (ref = 0; ref < treePtr->pixelReferences; ref++) {
+ nodePtr->numPixels[ref] -= curLinePtr->pixels[2*ref];
+ }
+ }
+ changeToLineCount++;
+ CLANG_ASSERT(curNodePtr);
+ curNodePtr->numChildren--;
+
+ /*
+ * Check if we need to adjust any partial clients.
+ */
+
+ if (treePtr->startEnd != NULL) {
+ int checkCount = 0;
+
+ while (checkCount < treePtr->startEndCount) {
+ if (treePtr->startEnd[checkCount] == curLinePtr) {
+ TkText *peer = treePtr->startEndRef[checkCount];
+
+ /*
+ * We're deleting a line which is the start or end
+ * of a current client. This means we need to
+ * adjust that client.
+ */
+
+ treePtr->startEnd[checkCount] = nextLinePtr;
+ if (peer->start == curLinePtr) {
+ peer->start = nextLinePtr;
+ }
+ if (peer->end == curLinePtr) {
+ peer->end = nextLinePtr;
+ }
+ }
+ checkCount++;
+ }
+ }
+ ckfree(curLinePtr->pixels);
+ ckfree(curLinePtr);
+ }
+ curLinePtr = nextLinePtr;
+ segPtr = curLinePtr->segPtr;
+
+ /*
+ * If the node is empty then delete it and its parents recursively
+ * upwards until a non-empty node is found.
+ */
+
+ while (curNodePtr->numChildren == 0) {
+ Node *parentPtr;
+
+ parentPtr = curNodePtr->parentPtr;
+ if (parentPtr->children.nodePtr == curNodePtr) {
+ parentPtr->children.nodePtr = curNodePtr->nextPtr;
+ } else {
+ Node *prevNodePtr = parentPtr->children.nodePtr;
+ while (prevNodePtr->nextPtr != curNodePtr) {
+ prevNodePtr = prevNodePtr->nextPtr;
+ }
+ prevNodePtr->nextPtr = curNodePtr->nextPtr;
+ }
+ parentPtr->numChildren--;
+ DeleteSummaries(curNodePtr->summaryPtr);
+ ckfree(curNodePtr->numPixels);
+ ckfree(curNodePtr);
+ curNodePtr = parentPtr;
+ }
+ curNodePtr = curLinePtr->parentPtr;
+ continue;
+ }
+
+ nextPtr = segPtr->nextPtr;
+ if (segPtr->typePtr->deleteProc(segPtr, curLinePtr, 0) != 0) {
+ /*
+ * This segment refuses to die. Move it to prevPtr and advance
+ * prevPtr if the segment has left gravity.
+ */
+
+ if (prevPtr == NULL) {
+ segPtr->nextPtr = index1Ptr->linePtr->segPtr;
+ index1Ptr->linePtr->segPtr = segPtr;
+ } else {
+ segPtr->nextPtr = prevPtr->nextPtr;
+ prevPtr->nextPtr = segPtr;
+ }
+ if (segPtr->typePtr->leftGravity) {
+ prevPtr = segPtr;
+ }
+ }
+ segPtr = nextPtr;
+ }
+
+ /*
+ * If the beginning and end of the deletion range are in different lines,
+ * join the two lines together and discard the ending line.
+ */
+
+ if (index1Ptr->linePtr != index2Ptr->linePtr) {
+ TkTextLine *prevLinePtr;
+
+ for (segPtr = lastPtr; segPtr != NULL;
+ segPtr = segPtr->nextPtr) {
+ if (segPtr->typePtr->lineChangeProc != NULL) {
+ segPtr->typePtr->lineChangeProc(segPtr, index2Ptr->linePtr);
+ }
+ }
+ curNodePtr = index2Ptr->linePtr->parentPtr;
+ for (nodePtr = curNodePtr; nodePtr != NULL;
+ nodePtr = nodePtr->parentPtr) {
+ nodePtr->numLines--;
+ for (ref = 0; ref < treePtr->pixelReferences; ref++) {
+ nodePtr->numPixels[ref] -= index2Ptr->linePtr->pixels[2*ref];
+ }
+ }
+ changeToLineCount++;
+ curNodePtr->numChildren--;
+ prevLinePtr = curNodePtr->children.linePtr;
+ if (prevLinePtr == index2Ptr->linePtr) {
+ curNodePtr->children.linePtr = index2Ptr->linePtr->nextPtr;
+ } else {
+ while (prevLinePtr->nextPtr != index2Ptr->linePtr) {
+ prevLinePtr = prevLinePtr->nextPtr;
+ }
+ prevLinePtr->nextPtr = index2Ptr->linePtr->nextPtr;
+ }
+
+ /*
+ * Check if we need to adjust any partial clients. In this case if
+ * we're deleting the line, we actually move back to the previous line
+ * for our (start,end) storage. We do this because we still want the
+ * portion of the second line that still exists to be in the start,end
+ * range.
+ */
+
+ if (treePtr->startEnd != NULL) {
+ int checkCount = 0;
+
+ while (checkCount < treePtr->startEndCount &&
+ treePtr->startEnd[checkCount] != NULL) {
+ if (treePtr->startEnd[checkCount] == index2Ptr->linePtr) {
+ TkText *peer = treePtr->startEndRef[checkCount];
+
+ /*
+ * We're deleting a line which is the start or end of a
+ * current client. This means we need to adjust that
+ * client.
+ */
+
+ treePtr->startEnd[checkCount] = index1Ptr->linePtr;
+ if (peer->start == index2Ptr->linePtr) {
+ peer->start = index1Ptr->linePtr;
+ }
+ if (peer->end == index2Ptr->linePtr) {
+ peer->end = index1Ptr->linePtr;
+ }
+ }
+ checkCount++;
+ }
+ }
+ ckfree(index2Ptr->linePtr->pixels);
+ ckfree(index2Ptr->linePtr);
+
+ Rebalance((BTree *) index2Ptr->tree, curNodePtr);
+ }
+
+ /*
+ * Cleanup the segments in the new line.
+ */
+
+ CleanupLine(index1Ptr->linePtr);
+
+ /*
+ * This line now needs to have its height recalculated. For safety, ensure
+ * we don't call this function with the last artificial line of text. I
+ * _believe_ that it isn't possible to get this far with the last line,
+ * but it is good to be safe.
+ */
+
+ if (TkBTreeNextLine(NULL, index1Ptr->linePtr) != NULL) {
+ TkTextInvalidateLineMetrics(treePtr->sharedTextPtr, NULL,
+ index1Ptr->linePtr, changeToLineCount,
+ TK_TEXT_INVALIDATE_DELETE);
+ }
+
+ /*
+ * Lastly, rebalance the first node of the range.
+ */
+
+ Rebalance((BTree *) index1Ptr->tree, index1Ptr->linePtr->parentPtr);
+ if (tkBTreeDebug) {
+ TkBTreeCheck(index1Ptr->tree);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkBTreeFindLine --
+ *
+ * Find a particular line in a B-tree based on its line number.
+ *
+ * Results:
+ * The return value is a pointer to the line structure for the line whose
+ * index is "line", or NULL if no such line exists.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkTextLine *
+TkBTreeFindLine(
+ TkTextBTree tree, /* B-tree in which to find line. */
+ const TkText *textPtr, /* Relative to this client of the B-tree. */
+ int line) /* Index of desired line. */
+{
+ BTree *treePtr = (BTree *) tree;
+ register Node *nodePtr;
+ register TkTextLine *linePtr;
+
+ if (treePtr == NULL) {
+ treePtr = (BTree *) textPtr->sharedTextPtr->tree;
+ }
+
+ nodePtr = treePtr->rootPtr;
+ if ((line < 0) || (line >= nodePtr->numLines)) {
+ return NULL;
+ }
+
+ /*
+ * Check for any start/end offset for this text widget.
+ */
+
+ if (textPtr != NULL) {
+ if (textPtr->start != NULL) {
+ line += TkBTreeLinesTo(NULL, textPtr->start);
+ if (line >= nodePtr->numLines) {
+ return NULL;
+ }
+ }
+ if (textPtr->end != NULL) {
+ if (line > TkBTreeLinesTo(NULL, textPtr->end)) {
+ return NULL;
+ }
+ }
+ }
+
+ /*
+ * Work down through levels of the tree until a node is found at level 0.
+ */
+
+ while (nodePtr->level != 0) {
+ for (nodePtr = nodePtr->children.nodePtr;
+ nodePtr->numLines <= line;
+ nodePtr = nodePtr->nextPtr) {
+ if (nodePtr == NULL) {
+ Tcl_Panic("TkBTreeFindLine ran out of nodes");
+ }
+ line -= nodePtr->numLines;
+ }
+ }
+
+ /*
+ * Work through the lines attached to the level-0 node.
+ */
+
+ for (linePtr = nodePtr->children.linePtr; line > 0;
+ linePtr = linePtr->nextPtr) {
+ if (linePtr == NULL) {
+ Tcl_Panic("TkBTreeFindLine ran out of lines");
+ }
+ line -= 1;
+ }
+ return linePtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkBTreeFindPixelLine --
+ *
+ * Find a particular line in a B-tree based on its pixel count.
+ *
+ * Results:
+ * The return value is a pointer to the line structure for the line which
+ * contains the pixel "pixels", or NULL if no such line exists. If the
+ * first line is of height 20, then pixels 0-19 will return it, and
+ * pixels = 20 will return the next line.
+ *
+ * If pixelOffset is non-NULL, it is set to the amount by which 'pixels'
+ * exceeds the first pixel located on the returned line. This should
+ * always be non-negative.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkTextLine *
+TkBTreeFindPixelLine(
+ TkTextBTree tree, /* B-tree to use. */
+ const TkText *textPtr, /* Relative to this client of the B-tree. */
+ int pixels, /* Pixel index of desired line. */
+ int *pixelOffset) /* Used to return offset. */
+{
+ BTree *treePtr = (BTree *) tree;
+ register Node *nodePtr;
+ register TkTextLine *linePtr;
+ int pixelReference = textPtr->pixelReference;
+
+ nodePtr = treePtr->rootPtr;
+
+ if ((pixels < 0) || (pixels > nodePtr->numPixels[pixelReference])) {
+ return NULL;
+ }
+
+ if (nodePtr->numPixels[pixelReference] == 0) {
+ Tcl_Panic("TkBTreeFindPixelLine called with empty window");
+ }
+
+ /*
+ * Work down through levels of the tree until a node is found at level 0.
+ */
+
+ while (nodePtr->level != 0) {
+ for (nodePtr = nodePtr->children.nodePtr;
+ nodePtr->numPixels[pixelReference] <= pixels;
+ nodePtr = nodePtr->nextPtr) {
+ if (nodePtr == NULL) {
+ Tcl_Panic("TkBTreeFindPixelLine ran out of nodes");
+ }
+ pixels -= nodePtr->numPixels[pixelReference];
+ }
+ }
+
+ /*
+ * Work through the lines attached to the level-0 node.
+ */
+
+ for (linePtr = nodePtr->children.linePtr;
+ linePtr->pixels[2 * pixelReference] < pixels;
+ linePtr = linePtr->nextPtr) {
+ if (linePtr == NULL) {
+ Tcl_Panic("TkBTreeFindPixelLine ran out of lines");
+ }
+ pixels -= linePtr->pixels[2 * pixelReference];
+ }
+ if (pixelOffset != NULL && linePtr != NULL) {
+ *pixelOffset = pixels;
+ }
+ return linePtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkBTreeNextLine --
+ *
+ * Given an existing line in a B-tree, this function locates the next
+ * line in the B-tree. This function is used for scanning through the
+ * B-tree.
+ *
+ * Results:
+ * The return value is a pointer to the line that immediately follows
+ * linePtr, or NULL if there is no such line.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkTextLine *
+TkBTreeNextLine(
+ const TkText *textPtr, /* Next line in the context of this client. */
+ register TkTextLine *linePtr)
+ /* Pointer to existing line in B-tree. */
+{
+ register Node *nodePtr;
+
+ if (linePtr->nextPtr != NULL) {
+ if (textPtr != NULL && (linePtr == textPtr->end)) {
+ return NULL;
+ } else {
+ return linePtr->nextPtr;
+ }
+ }
+
+ /*
+ * This was the last line associated with the particular parent node.
+ * Search up the tree for the next node, then search down from that node
+ * to find the first line.
+ */
+
+ for (nodePtr = linePtr->parentPtr; ; nodePtr = nodePtr->parentPtr) {
+ if (nodePtr->nextPtr != NULL) {
+ nodePtr = nodePtr->nextPtr;
+ break;
+ }
+ if (nodePtr->parentPtr == NULL) {
+ return NULL;
+ }
+ }
+ while (nodePtr->level > 0) {
+ nodePtr = nodePtr->children.nodePtr;
+ }
+ return nodePtr->children.linePtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkBTreePreviousLine --
+ *
+ * Given an existing line in a B-tree, this function locates the previous
+ * line in the B-tree. This function is used for scanning through the
+ * B-tree in the reverse direction.
+ *
+ * Results:
+ * The return value is a pointer to the line that immediately preceeds
+ * linePtr, or NULL if there is no such line.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkTextLine *
+TkBTreePreviousLine(
+ TkText *textPtr, /* Relative to this client of the B-tree. */
+ register TkTextLine *linePtr)
+ /* Pointer to existing line in B-tree. */
+{
+ register Node *nodePtr;
+ register Node *node2Ptr;
+ register TkTextLine *prevPtr;
+
+ if (textPtr != NULL && textPtr->start == linePtr) {
+ return NULL;
+ }
+
+ /*
+ * Find the line under this node just before the starting line.
+ */
+
+ prevPtr = linePtr->parentPtr->children.linePtr; /* First line at leaf. */
+ while (prevPtr != linePtr) {
+ if (prevPtr->nextPtr == linePtr) {
+ return prevPtr;
+ }
+ prevPtr = prevPtr->nextPtr;
+ if (prevPtr == NULL) {
+ Tcl_Panic("TkBTreePreviousLine ran out of lines");
+ }
+ }
+
+ /*
+ * This was the first line associated with the particular parent node.
+ * Search up the tree for the previous node, then search down from that
+ * node to find its last line.
+ */
+
+ for (nodePtr = linePtr->parentPtr; ; nodePtr = nodePtr->parentPtr) {
+ if (nodePtr == NULL || nodePtr->parentPtr == NULL) {
+ return NULL;
+ }
+ if (nodePtr != nodePtr->parentPtr->children.nodePtr) {
+ break;
+ }
+ }
+ for (node2Ptr = nodePtr->parentPtr->children.nodePtr; ;
+ node2Ptr = node2Ptr->children.nodePtr) {
+ while (node2Ptr->nextPtr != nodePtr) {
+ node2Ptr = node2Ptr->nextPtr;
+ }
+ if (node2Ptr->level == 0) {
+ break;
+ }
+ nodePtr = NULL;
+ }
+ for (prevPtr = node2Ptr->children.linePtr ; ; prevPtr = prevPtr->nextPtr) {
+ if (prevPtr->nextPtr == NULL) {
+ return prevPtr;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkBTreePixelsTo --
+ *
+ * Given a pointer to a line in a B-tree, return the numerical pixel
+ * index of the top of that line (i.e. the result does not include the
+ * height of the given line).
+ *
+ * Since the last line of text (the artificial one) has zero height by
+ * defintion, calling this with the last line will return the total
+ * number of pixels in the widget.
+ *
+ * Results:
+ * The result is the pixel height of the top of the given line.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkBTreePixelsTo(
+ const TkText *textPtr, /* Relative to this client of the B-tree. */
+ TkTextLine *linePtr) /* Pointer to existing line in B-tree. */
+{
+ register TkTextLine *linePtr2;
+ register Node *nodePtr, *parentPtr;
+ int index;
+ int pixelReference = textPtr->pixelReference;
+
+ /*
+ * First count how many pixels precede this line in its level-0 node.
+ */
+
+ nodePtr = linePtr->parentPtr;
+ index = 0;
+ for (linePtr2 = nodePtr->children.linePtr; linePtr2 != linePtr;
+ linePtr2 = linePtr2->nextPtr) {
+ if (linePtr2 == NULL) {
+ Tcl_Panic("TkBTreePixelsTo couldn't find line");
+ }
+ index += linePtr2->pixels[2 * pixelReference];
+ }
+
+ /*
+ * Now work up through the levels of the tree one at a time, counting how
+ * many pixels are in nodes preceding the current node.
+ */
+
+ for (parentPtr = nodePtr->parentPtr ; parentPtr != NULL;
+ nodePtr = parentPtr, parentPtr = parentPtr->parentPtr) {
+ register Node *nodePtr2;
+
+ for (nodePtr2 = parentPtr->children.nodePtr; nodePtr2 != nodePtr;
+ nodePtr2 = nodePtr2->nextPtr) {
+ if (nodePtr2 == NULL) {
+ Tcl_Panic("TkBTreePixelsTo couldn't find node");
+ }
+ index += nodePtr2->numPixels[pixelReference];
+ }
+ }
+ return index;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkBTreeLinesTo --
+ *
+ * Given a pointer to a line in a B-tree, return the numerical index of
+ * that line.
+ *
+ * Results:
+ * The result is the index of linePtr within the tree, where 0
+ * corresponds to the first line in the tree.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkBTreeLinesTo(
+ const TkText *textPtr, /* Relative to this client of the B-tree. */
+ TkTextLine *linePtr) /* Pointer to existing line in B-tree. */
+{
+ register TkTextLine *linePtr2;
+ register Node *nodePtr, *parentPtr, *nodePtr2;
+ int index;
+
+ /*
+ * First count how many lines precede this one in its level-0 node.
+ */
+
+ nodePtr = linePtr->parentPtr;
+ index = 0;
+ for (linePtr2 = nodePtr->children.linePtr; linePtr2 != linePtr;
+ linePtr2 = linePtr2->nextPtr) {
+ if (linePtr2 == NULL) {
+ Tcl_Panic("TkBTreeLinesTo couldn't find line");
+ }
+ index += 1;
+ }
+
+ /*
+ * Now work up through the levels of the tree one at a time, counting how
+ * many lines are in nodes preceding the current node.
+ */
+
+ for (parentPtr = nodePtr->parentPtr ; parentPtr != NULL;
+ nodePtr = parentPtr, parentPtr = parentPtr->parentPtr) {
+ for (nodePtr2 = parentPtr->children.nodePtr; nodePtr2 != nodePtr;
+ nodePtr2 = nodePtr2->nextPtr) {
+ if (nodePtr2 == NULL) {
+ Tcl_Panic("TkBTreeLinesTo couldn't find node");
+ }
+ index += nodePtr2->numLines;
+ }
+ }
+ if (textPtr != NULL) {
+ /*
+ * The index to return must be relative to textPtr, not to the entire
+ * tree. Take care to never return a negative index when linePtr
+ * denotes a line before -startline, or an index larger than the
+ * number of lines in textPtr when linePtr is a line past -endline.
+ */
+
+ int indexStart, indexEnd;
+
+ if (textPtr->start != NULL) {
+ indexStart = TkBTreeLinesTo(NULL, textPtr->start);
+ } else {
+ indexStart = 0;
+ }
+ if (textPtr->end != NULL) {
+ indexEnd = TkBTreeLinesTo(NULL, textPtr->end);
+ } else {
+ indexEnd = TkBTreeNumLines(textPtr->sharedTextPtr->tree, NULL);
+ }
+ if (index < indexStart) {
+ index = 0;
+ } else if (index > indexEnd) {
+ index = TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr);
+ } else {
+ index -= indexStart;
+ }
+ }
+ return index;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkBTreeLinkSegment --
+ *
+ * This function adds a new segment to a B-tree at a given location.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * SegPtr will be linked into its tree.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+void
+TkBTreeLinkSegment(
+ TkTextSegment *segPtr, /* Pointer to new segment to be added to
+ * B-tree. Should be completely initialized by
+ * caller except for nextPtr field. */
+ TkTextIndex *indexPtr) /* Where to add segment: it gets linked in
+ * just before the segment indicated here. */
+{
+ register TkTextSegment *prevPtr;
+
+ prevPtr = SplitSeg(indexPtr);
+ if (prevPtr == NULL) {
+ segPtr->nextPtr = indexPtr->linePtr->segPtr;
+ indexPtr->linePtr->segPtr = segPtr;
+ } else {
+ segPtr->nextPtr = prevPtr->nextPtr;
+ prevPtr->nextPtr = segPtr;
+ }
+ CleanupLine(indexPtr->linePtr);
+ if (tkBTreeDebug) {
+ TkBTreeCheck(indexPtr->tree);
+ }
+ ((BTree *)indexPtr->tree)->stateEpoch++;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkBTreeUnlinkSegment --
+ *
+ * This function unlinks a segment from its line in a B-tree.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * SegPtr will be unlinked from linePtr. The segment itself isn't
+ * modified by this function.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+void
+TkBTreeUnlinkSegment(
+ TkTextSegment *segPtr, /* Segment to be unlinked. */
+ TkTextLine *linePtr) /* Line that currently contains segment. */
+{
+ register TkTextSegment *prevPtr;
+
+ if (linePtr->segPtr == segPtr) {
+ linePtr->segPtr = segPtr->nextPtr;
+ } else {
+ prevPtr = linePtr->segPtr;
+ while (prevPtr->nextPtr != segPtr) {
+ prevPtr = prevPtr->nextPtr;
+
+ if (prevPtr == NULL) {
+ /*
+ * Two logical lines merged into one display line through
+ * eliding of a newline.
+ */
+
+ linePtr = TkBTreeNextLine(NULL, linePtr);
+ prevPtr = linePtr->segPtr;
+ }
+ }
+ prevPtr->nextPtr = segPtr->nextPtr;
+ }
+ CleanupLine(linePtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkBTreeTag --
+ *
+ * Turn a given tag on or off for a given range of characters in a B-tree
+ * of text.
+ *
+ * Results:
+ * 1 if the tags on any characters in the range were changed, and zero
+ * otherwise (i.e. if the tag was already absent (add = 0) or present
+ * (add = 1) on the index range in question).
+ *
+ * Side effects:
+ * The given tag is added to the given range of characters in the tree or
+ * removed from all those characters, depending on the "add" argument.
+ * The structure of the btree is modified enough that index1Ptr and
+ * index2Ptr are no longer valid after this function returns, and the
+ * indexes may be modified by this function.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkBTreeTag(
+ register TkTextIndex *index1Ptr,
+ /* Indicates first character in range. */
+ register TkTextIndex *index2Ptr,
+ /* Indicates character just after the last one
+ * in range. */
+ TkTextTag *tagPtr, /* Tag to add or remove. */
+ int add) /* One means add tag to the given range of
+ * characters; zero means remove the tag from
+ * the range. */
+{
+ TkTextSegment *segPtr, *prevPtr;
+ TkTextSearch search;
+ TkTextLine *cleanupLinePtr;
+ int oldState, changed, anyChanges = 0;
+
+ /*
+ * See whether the tag is present at the start of the range. If the state
+ * doesn't already match what we want then add a toggle there.
+ */
+
+ oldState = TkBTreeCharTagged(index1Ptr, tagPtr);
+ if ((add != 0) ^ oldState) {
+ segPtr = ckalloc(TSEG_SIZE);
+ segPtr->typePtr = (add) ? &tkTextToggleOnType : &tkTextToggleOffType;
+ prevPtr = SplitSeg(index1Ptr);
+ if (prevPtr == NULL) {
+ segPtr->nextPtr = index1Ptr->linePtr->segPtr;
+ index1Ptr->linePtr->segPtr = segPtr;
+ } else {
+ segPtr->nextPtr = prevPtr->nextPtr;
+ prevPtr->nextPtr = segPtr;
+ }
+ segPtr->size = 0;
+ segPtr->body.toggle.tagPtr = tagPtr;
+ segPtr->body.toggle.inNodeCounts = 0;
+ anyChanges = 1;
+ }
+
+ /*
+ * Scan the range of characters and delete any internal tag transitions.
+ * Keep track of what the old state was at the end of the range, and add a
+ * toggle there if it's needed.
+ */
+
+ TkBTreeStartSearch(index1Ptr, index2Ptr, tagPtr, &search);
+ cleanupLinePtr = index1Ptr->linePtr;
+ while (TkBTreeNextTag(&search)) {
+ anyChanges = 1;
+ oldState ^= 1;
+ segPtr = search.segPtr;
+ prevPtr = search.curIndex.linePtr->segPtr;
+ if (prevPtr == segPtr) {
+ search.curIndex.linePtr->segPtr = segPtr->nextPtr;
+ } else {
+ while (prevPtr->nextPtr != segPtr) {
+ prevPtr = prevPtr->nextPtr;
+ }
+ prevPtr->nextPtr = segPtr->nextPtr;
+ }
+ if (segPtr->body.toggle.inNodeCounts) {
+ ChangeNodeToggleCount(search.curIndex.linePtr->parentPtr,
+ segPtr->body.toggle.tagPtr, -1);
+ segPtr->body.toggle.inNodeCounts = 0;
+ changed = 1;
+ } else {
+ changed = 0;
+ }
+ ckfree(segPtr);
+
+ /*
+ * The code below is a bit tricky. After deleting a toggle we
+ * eventually have to call CleanupLine, in order to allow character
+ * segments to be merged together. To do this, we remember in
+ * cleanupLinePtr a line that needs to be cleaned up, but we don't
+ * clean it up until we've moved on to a different line. That way the
+ * cleanup process won't goof up segPtr.
+ */
+
+ if (cleanupLinePtr != search.curIndex.linePtr) {
+ CleanupLine(cleanupLinePtr);
+ cleanupLinePtr = search.curIndex.linePtr;
+ }
+
+ /*
+ * Quick hack. ChangeNodeToggleCount may move the tag's root location
+ * around and leave the search in the void. This resets the search.
+ */
+
+ if (changed) {
+ TkBTreeStartSearch(index1Ptr, index2Ptr, tagPtr, &search);
+ }
+ }
+ if ((add != 0) ^ oldState) {
+ segPtr = ckalloc(TSEG_SIZE);
+ segPtr->typePtr = (add) ? &tkTextToggleOffType : &tkTextToggleOnType;
+ prevPtr = SplitSeg(index2Ptr);
+ if (prevPtr == NULL) {
+ segPtr->nextPtr = index2Ptr->linePtr->segPtr;
+ index2Ptr->linePtr->segPtr = segPtr;
+ } else {
+ segPtr->nextPtr = prevPtr->nextPtr;
+ prevPtr->nextPtr = segPtr;
+ }
+ segPtr->size = 0;
+ segPtr->body.toggle.tagPtr = tagPtr;
+ segPtr->body.toggle.inNodeCounts = 0;
+ anyChanges = 1;
+ }
+
+ /*
+ * Cleanup cleanupLinePtr and the last line of the range, if these are
+ * different.
+ */
+
+ if (anyChanges) {
+ CleanupLine(cleanupLinePtr);
+ if (cleanupLinePtr != index2Ptr->linePtr) {
+ CleanupLine(index2Ptr->linePtr);
+ }
+ ((BTree *)index1Ptr->tree)->stateEpoch++;
+ }
+
+ if (tkBTreeDebug) {
+ TkBTreeCheck(index1Ptr->tree);
+ }
+ return anyChanges;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ChangeNodeToggleCount --
+ *
+ * This function increments or decrements the toggle count for a
+ * particular tag in a particular node and all its ancestors up to the
+ * per-tag root node.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The toggle count for tag is adjusted up or down by "delta" in nodePtr.
+ * This routine maintains the tagRootPtr that identifies the root node
+ * for the tag, moving it up or down the tree as needed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ChangeNodeToggleCount(
+ register Node *nodePtr, /* Node whose toggle count for a tag must be
+ * changed. */
+ TkTextTag *tagPtr, /* Information about tag. */
+ int delta) /* Amount to add to current toggle count for
+ * tag (may be negative). */
+{
+ register Summary *summaryPtr, *prevPtr;
+ register Node *node2Ptr;
+ int rootLevel; /* Level of original tag root. */
+
+ tagPtr->toggleCount += delta;
+ if (tagPtr->tagRootPtr == NULL) {
+ tagPtr->tagRootPtr = nodePtr;
+ return;
+ }
+
+ /*
+ * Note the level of the existing root for the tag so we can detect if it
+ * needs to be moved because of the toggle count change.
+ */
+
+ rootLevel = tagPtr->tagRootPtr->level;
+
+ /*
+ * Iterate over the node and its ancestors up to the tag root, adjusting
+ * summary counts at each node and moving the tag's root upwards if
+ * necessary.
+ */
+
+ for ( ; nodePtr != tagPtr->tagRootPtr; nodePtr = nodePtr->parentPtr) {
+ /*
+ * See if there's already an entry for this tag for this node. If so,
+ * perhaps all we have to do is adjust its count.
+ */
+
+ for (prevPtr = NULL, summaryPtr = nodePtr->summaryPtr;
+ summaryPtr != NULL;
+ prevPtr = summaryPtr, summaryPtr = summaryPtr->nextPtr) {
+ if (summaryPtr->tagPtr == tagPtr) {
+ break;
+ }
+ }
+ if (summaryPtr != NULL) {
+ summaryPtr->toggleCount += delta;
+ if (summaryPtr->toggleCount > 0 &&
+ summaryPtr->toggleCount < tagPtr->toggleCount) {
+ continue;
+ }
+ if (summaryPtr->toggleCount != 0) {
+ /*
+ * Should never find a node with max toggle count at this
+ * point (there shouldn't have been a summary entry in the
+ * first place).
+ */
+
+ Tcl_Panic("ChangeNodeToggleCount: bad toggle count (%d) max (%d)",
+ summaryPtr->toggleCount, tagPtr->toggleCount);
+ }
+
+ /*
+ * Zero toggle count; must remove this tag from the list.
+ */
+
+ if (prevPtr == NULL) {
+ nodePtr->summaryPtr = summaryPtr->nextPtr;
+ } else {
+ prevPtr->nextPtr = summaryPtr->nextPtr;
+ }
+ ckfree(summaryPtr);
+ } else {
+ /*
+ * This tag isn't currently in the summary information list.
+ */
+
+ if (rootLevel == nodePtr->level) {
+ /*
+ * The old tag root is at the same level in the tree as this
+ * node, but it isn't at this node. Move the tag root up a
+ * level, in the hopes that it will now cover this node as
+ * well as the old root (if not, we'll move it up again the
+ * next time through the loop). To push it up one level we
+ * copy the original toggle count into the summary information
+ * at the old root and change the root to its parent node.
+ */
+
+ Node *rootNodePtr = tagPtr->tagRootPtr;
+
+ summaryPtr = ckalloc(sizeof(Summary));
+ summaryPtr->tagPtr = tagPtr;
+ summaryPtr->toggleCount = tagPtr->toggleCount - delta;
+ summaryPtr->nextPtr = rootNodePtr->summaryPtr;
+ rootNodePtr->summaryPtr = summaryPtr;
+ rootNodePtr = rootNodePtr->parentPtr;
+ rootLevel = rootNodePtr->level;
+ tagPtr->tagRootPtr = rootNodePtr;
+ }
+ summaryPtr = ckalloc(sizeof(Summary));
+ summaryPtr->tagPtr = tagPtr;
+ summaryPtr->toggleCount = delta;
+ summaryPtr->nextPtr = nodePtr->summaryPtr;
+ nodePtr->summaryPtr = summaryPtr;
+ }
+ }
+
+ /*
+ * If we've decremented the toggle count, then it may be necessary to push
+ * the tag root down one or more levels.
+ */
+
+ if (delta >= 0) {
+ return;
+ }
+ if (tagPtr->toggleCount == 0) {
+ tagPtr->tagRootPtr = NULL;
+ return;
+ }
+ nodePtr = tagPtr->tagRootPtr;
+ while (nodePtr->level > 0) {
+ /*
+ * See if a single child node accounts for all of the tag's toggles.
+ * If so, push the root down one level.
+ */
+
+ for (node2Ptr = nodePtr->children.nodePtr;
+ node2Ptr != NULL ;
+ node2Ptr = node2Ptr->nextPtr) {
+ for (prevPtr = NULL, summaryPtr = node2Ptr->summaryPtr;
+ summaryPtr != NULL;
+ prevPtr = summaryPtr, summaryPtr = summaryPtr->nextPtr) {
+ if (summaryPtr->tagPtr == tagPtr) {
+ break;
+ }
+ }
+ if (summaryPtr == NULL) {
+ continue;
+ }
+ if (summaryPtr->toggleCount != tagPtr->toggleCount) {
+ /*
+ * No node has all toggles, so the root is still valid.
+ */
+
+ return;
+ }
+
+ /*
+ * This node has all the toggles, so push down the root.
+ */
+
+ if (prevPtr == NULL) {
+ node2Ptr->summaryPtr = summaryPtr->nextPtr;
+ } else {
+ prevPtr->nextPtr = summaryPtr->nextPtr;
+ }
+ ckfree(summaryPtr);
+ tagPtr->tagRootPtr = node2Ptr;
+ break;
+ }
+ nodePtr = tagPtr->tagRootPtr;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FindTagStart --
+ *
+ * Find the start of the first range of a tag.
+ *
+ * Results:
+ * The return value is a pointer to the first tag toggle segment for the
+ * tag. This can be either a tagon or tagoff segments because of the way
+ * TkBTreeAdd removes a tag. Sets *indexPtr to be the index of the tag
+ * toggle.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static TkTextSegment *
+FindTagStart(
+ TkTextBTree tree, /* Tree to search within. */
+ TkTextTag *tagPtr, /* Tag to search for. */
+ TkTextIndex *indexPtr) /* Return - index information. */
+{
+ register Node *nodePtr;
+ register TkTextLine *linePtr;
+ register TkTextSegment *segPtr;
+ register Summary *summaryPtr;
+ int offset;
+
+ nodePtr = tagPtr->tagRootPtr;
+ if (nodePtr == NULL) {
+ return NULL;
+ }
+
+ /*
+ * Search from the root of the subtree that contains the tag down to the
+ * level 0 node.
+ */
+
+ while (nodePtr && nodePtr->level > 0) {
+ for (nodePtr = nodePtr->children.nodePtr ; nodePtr != NULL;
+ nodePtr = nodePtr->nextPtr) {
+ for (summaryPtr = nodePtr->summaryPtr ; summaryPtr != NULL;
+ summaryPtr = summaryPtr->nextPtr) {
+ if (summaryPtr->tagPtr == tagPtr) {
+ goto gotNodeWithTag;
+ }
+ }
+ }
+ gotNodeWithTag:
+ continue;
+ }
+
+ if (nodePtr == NULL) {
+ return NULL;
+ }
+
+ /*
+ * Work through the lines attached to the level-0 node.
+ */
+
+ for (linePtr = nodePtr->children.linePtr; linePtr != NULL;
+ linePtr = linePtr->nextPtr) {
+ for (offset = 0, segPtr = linePtr->segPtr ; segPtr != NULL;
+ offset += segPtr->size, segPtr = segPtr->nextPtr) {
+ if (((segPtr->typePtr == &tkTextToggleOnType)
+ || (segPtr->typePtr == &tkTextToggleOffType))
+ && (segPtr->body.toggle.tagPtr == tagPtr)) {
+ /*
+ * It is possible that this is a tagoff tag, but that gets
+ * cleaned up later.
+ */
+
+ indexPtr->tree = tree;
+ indexPtr->linePtr = linePtr;
+ indexPtr->byteIndex = offset;
+ return segPtr;
+ }
+ }
+ }
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FindTagEnd --
+ *
+ * Find the end of the last range of a tag.
+ *
+ * Results:
+ * The return value is a pointer to the last tag toggle segment for the
+ * tag. This can be either a tagon or tagoff segments because of the way
+ * TkBTreeAdd removes a tag. Sets *indexPtr to be the index of the tag
+ * toggle.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static TkTextSegment *
+FindTagEnd(
+ TkTextBTree tree, /* Tree to search within. */
+ TkTextTag *tagPtr, /* Tag to search for. */
+ TkTextIndex *indexPtr) /* Return - index information. */
+{
+ register Node *nodePtr, *lastNodePtr;
+ register TkTextLine *linePtr ,*lastLinePtr;
+ register TkTextSegment *segPtr, *lastSegPtr, *last2SegPtr;
+ register Summary *summaryPtr;
+ int lastoffset, lastoffset2, offset;
+
+ nodePtr = tagPtr->tagRootPtr;
+ if (nodePtr == NULL) {
+ return NULL;
+ }
+
+ /*
+ * Search from the root of the subtree that contains the tag down to the
+ * level 0 node.
+ */
+
+ while (nodePtr && nodePtr->level > 0) {
+ for (lastNodePtr = NULL, nodePtr = nodePtr->children.nodePtr ;
+ nodePtr != NULL; nodePtr = nodePtr->nextPtr) {
+ for (summaryPtr = nodePtr->summaryPtr ; summaryPtr != NULL;
+ summaryPtr = summaryPtr->nextPtr) {
+ if (summaryPtr->tagPtr == tagPtr) {
+ lastNodePtr = nodePtr;
+ break;
+ }
+ }
+ }
+ nodePtr = lastNodePtr;
+ }
+
+ if (nodePtr == NULL) {
+ return NULL;
+ }
+
+ /*
+ * Work through the lines attached to the level-0 node.
+ */
+
+ last2SegPtr = NULL;
+ lastoffset2 = 0;
+ lastoffset = 0;
+ for (lastLinePtr = NULL, linePtr = nodePtr->children.linePtr;
+ linePtr != NULL; linePtr = linePtr->nextPtr) {
+ for (offset = 0, lastSegPtr = NULL, segPtr = linePtr->segPtr ;
+ segPtr != NULL;
+ offset += segPtr->size, segPtr = segPtr->nextPtr) {
+ if (((segPtr->typePtr == &tkTextToggleOnType)
+ || (segPtr->typePtr == &tkTextToggleOffType))
+ && (segPtr->body.toggle.tagPtr == tagPtr)) {
+ lastSegPtr = segPtr;
+ lastoffset = offset;
+ }
+ }
+ if (lastSegPtr != NULL) {
+ lastLinePtr = linePtr;
+ last2SegPtr = lastSegPtr;
+ lastoffset2 = lastoffset;
+ }
+ }
+ indexPtr->tree = tree;
+ indexPtr->linePtr = lastLinePtr;
+ indexPtr->byteIndex = lastoffset2;
+ return last2SegPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkBTreeStartSearch --
+ *
+ * This function sets up a search for tag transitions involving a given
+ * tag (or all tags) in a given range of the text.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The information at *searchPtr is set up so that subsequent calls to
+ * TkBTreeNextTag or TkBTreePrevTag will return information about the
+ * locations of tag transitions. Note that TkBTreeNextTag or
+ * TkBTreePrevTag must be called to get the first transition. Note:
+ * unlike TkBTreeNextTag and TkBTreePrevTag, this routine does not
+ * guarantee that searchPtr->curIndex is equal to *index1Ptr. It may be
+ * greater than that if *index1Ptr is less than the first tag transition.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkBTreeStartSearch(
+ TkTextIndex *index1Ptr, /* Search starts here. Tag toggles at this
+ * position will not be returned. */
+ TkTextIndex *index2Ptr, /* Search stops here. Tag toggles at this
+ * position *will* be returned. */
+ TkTextTag *tagPtr, /* Tag to search for. NULL means search for
+ * any tag. */
+ register TkTextSearch *searchPtr)
+ /* Where to store information about search's
+ * progress. */
+{
+ int offset;
+ TkTextIndex index0; /* First index of the tag. */
+ TkTextSegment *seg0Ptr; /* First segment of the tag. */
+
+ /*
+ * Find the segment that contains the first toggle for the tag. This may
+ * become the starting point in the search.
+ */
+
+ seg0Ptr = FindTagStart(index1Ptr->tree, tagPtr, &index0);
+ if (seg0Ptr == NULL) {
+ /*
+ * Even though there are no toggles, the display code still uses the
+ * search curIndex, so initialize that anyway.
+ */
+
+ searchPtr->linesLeft = 0;
+ searchPtr->curIndex = *index1Ptr;
+ searchPtr->segPtr = NULL;
+ searchPtr->nextPtr = NULL;
+ return;
+ }
+ if (TkTextIndexCmp(index1Ptr, &index0) < 0) {
+ /*
+ * Adjust start of search up to the first range of the tag.
+ */
+
+ searchPtr->curIndex = index0;
+ searchPtr->segPtr = NULL;
+ searchPtr->nextPtr = seg0Ptr; /* Will be returned by NextTag. */
+ index1Ptr = &index0;
+ } else {
+ searchPtr->curIndex = *index1Ptr;
+ searchPtr->segPtr = NULL;
+ searchPtr->nextPtr = TkTextIndexToSeg(index1Ptr, &offset);
+ searchPtr->curIndex.byteIndex -= offset;
+ }
+ searchPtr->lastPtr = TkTextIndexToSeg(index2Ptr, NULL);
+ searchPtr->tagPtr = tagPtr;
+ searchPtr->linesLeft = TkBTreeLinesTo(NULL, index2Ptr->linePtr) + 1
+ - TkBTreeLinesTo(NULL, index1Ptr->linePtr);
+ searchPtr->allTags = (tagPtr == NULL);
+ if (searchPtr->linesLeft == 1) {
+ /*
+ * Starting and stopping segments are in the same line; mark the
+ * search as over immediately if the second segment is before the
+ * first. A search does not return a toggle at the very start of the
+ * range, unless the range is artificially moved up to index0.
+ */
+
+ if (((index1Ptr == &index0) &&
+ (index1Ptr->byteIndex > index2Ptr->byteIndex)) ||
+ ((index1Ptr != &index0) &&
+ (index1Ptr->byteIndex >= index2Ptr->byteIndex))) {
+ searchPtr->linesLeft = 0;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkBTreeStartSearchBack --
+ *
+ * This function sets up a search backwards for tag transitions involving
+ * a given tag (or all tags) in a given range of the text. In the normal
+ * case the first index (*index1Ptr) is beyond the second index
+ * (*index2Ptr).
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The information at *searchPtr is set up so that subsequent calls to
+ * TkBTreePrevTag will return information about the locations of tag
+ * transitions. Note that TkBTreePrevTag must be called to get the first
+ * transition. Note: unlike TkBTreeNextTag and TkBTreePrevTag, this
+ * routine does not guarantee that searchPtr->curIndex is equal to
+ * *index1Ptr. It may be less than that if *index1Ptr is greater than the
+ * last tag transition.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkBTreeStartSearchBack(
+ TkTextIndex *index1Ptr, /* Search starts here. Tag toggles at this
+ * position will not be returned. */
+ TkTextIndex *index2Ptr, /* Search stops here. Tag toggles at this
+ * position *will* be returned. */
+ TkTextTag *tagPtr, /* Tag to search for. NULL means search for
+ * any tag. */
+ register TkTextSearch *searchPtr)
+ /* Where to store information about search's
+ * progress. */
+{
+ int offset;
+ TkTextIndex index0; /* Last index of the tag. */
+ TkTextIndex backOne; /* One character before starting index. */
+ TkTextSegment *seg0Ptr; /* Last segment of the tag. */
+
+ /*
+ * Find the segment that contains the last toggle for the tag. This may
+ * become the starting point in the search.
+ */
+
+ seg0Ptr = FindTagEnd(index1Ptr->tree, tagPtr, &index0);
+ if (seg0Ptr == NULL) {
+ /*
+ * Even though there are no toggles, the display code still uses the
+ * search curIndex, so initialize that anyway.
+ */
+
+ searchPtr->linesLeft = 0;
+ searchPtr->curIndex = *index1Ptr;
+ searchPtr->segPtr = NULL;
+ searchPtr->nextPtr = NULL;
+ return;
+ }
+
+ /*
+ * Adjust the start of the search so it doesn't find any tag toggles
+ * that are right at the index specified by the user.
+ */
+
+ if (TkTextIndexCmp(index1Ptr, &index0) > 0) {
+ searchPtr->curIndex = index0;
+ index1Ptr = &index0;
+ } else {
+ TkTextIndexBackChars(NULL, index1Ptr, 1, &searchPtr->curIndex,
+ COUNT_INDICES);
+ }
+ searchPtr->segPtr = NULL;
+ searchPtr->nextPtr = TkTextIndexToSeg(&searchPtr->curIndex, &offset);
+ searchPtr->curIndex.byteIndex -= offset;
+
+ /*
+ * Adjust the end of the search so it does find toggles that are right at
+ * the second index specified by the user.
+ */
+
+ if ((TkBTreeLinesTo(NULL, index2Ptr->linePtr) == 0) &&
+ (index2Ptr->byteIndex == 0)) {
+ backOne = *index2Ptr;
+ searchPtr->lastPtr = NULL; /* Signals special case for 1.0. */
+ } else {
+ TkTextIndexBackChars(NULL, index2Ptr, 1, &backOne, COUNT_INDICES);
+ searchPtr->lastPtr = TkTextIndexToSeg(&backOne, NULL);
+ }
+ searchPtr->tagPtr = tagPtr;
+ searchPtr->linesLeft = TkBTreeLinesTo(NULL, index1Ptr->linePtr) + 1
+ - TkBTreeLinesTo(NULL, backOne.linePtr);
+ searchPtr->allTags = (tagPtr == NULL);
+ if (searchPtr->linesLeft == 1) {
+ /*
+ * Starting and stopping segments are in the same line; mark the
+ * search as over immediately if the second segment is after the
+ * first.
+ */
+
+ if (index1Ptr->byteIndex <= backOne.byteIndex) {
+ searchPtr->linesLeft = 0;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkBTreeNextTag --
+ *
+ * Once a tag search has begun, successive calls to this function return
+ * successive tag toggles. Note: it is NOT SAFE to call this function if
+ * characters have been inserted into or deleted from the B-tree since
+ * the call to TkBTreeStartSearch.
+ *
+ * Results:
+ * The return value is 1 if another toggle was found that met the
+ * criteria specified in the call to TkBTreeStartSearch; in this case
+ * searchPtr->curIndex gives the toggle's position and
+ * searchPtr->curTagPtr points to its segment. 0 is returned if no more
+ * matching tag transitions were found; in this case searchPtr->curIndex
+ * is the same as searchPtr->stopIndex.
+ *
+ * Side effects:
+ * Information in *searchPtr is modified to update the state of the
+ * search and indicate where the next tag toggle is located.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkBTreeNextTag(
+ register TkTextSearch *searchPtr)
+ /* Information about search in progress; must
+ * have been set up by call to
+ * TkBTreeStartSearch. */
+{
+ register TkTextSegment *segPtr;
+ register Node *nodePtr;
+ register Summary *summaryPtr;
+
+ if (searchPtr->linesLeft <= 0) {
+ goto searchOver;
+ }
+
+ /*
+ * The outermost loop iterates over lines that may potentially contain a
+ * relevant tag transition, starting from the current segment in the
+ * current line.
+ */
+
+ segPtr = searchPtr->nextPtr;
+ while (1) {
+ /*
+ * Check for more tags on the current line.
+ */
+
+ for ( ; segPtr != NULL; segPtr = segPtr->nextPtr) {
+ if (segPtr == searchPtr->lastPtr) {
+ goto searchOver;
+ }
+ if (((segPtr->typePtr == &tkTextToggleOnType)
+ || (segPtr->typePtr == &tkTextToggleOffType))
+ && (searchPtr->allTags
+ || (segPtr->body.toggle.tagPtr == searchPtr->tagPtr))) {
+ searchPtr->segPtr = segPtr;
+ searchPtr->nextPtr = segPtr->nextPtr;
+ searchPtr->tagPtr = segPtr->body.toggle.tagPtr;
+ return 1;
+ }
+ searchPtr->curIndex.byteIndex += segPtr->size;
+ }
+
+ /*
+ * See if there are more lines associated with the current parent
+ * node. If so, go back to the top of the loop to search the next one.
+ */
+
+ nodePtr = searchPtr->curIndex.linePtr->parentPtr;
+ searchPtr->curIndex.linePtr = searchPtr->curIndex.linePtr->nextPtr;
+ searchPtr->linesLeft--;
+ if (searchPtr->linesLeft <= 0) {
+ goto searchOver;
+ }
+ if (searchPtr->curIndex.linePtr != NULL) {
+ segPtr = searchPtr->curIndex.linePtr->segPtr;
+ searchPtr->curIndex.byteIndex = 0;
+ continue;
+ }
+ if (nodePtr == searchPtr->tagPtr->tagRootPtr) {
+ goto searchOver;
+ }
+
+ /*
+ * Search across and up through the B-tree's node hierarchy looking
+ * for the next node that has a relevant tag transition somewhere in
+ * its subtree. Be sure to update linesLeft as we skip over large
+ * chunks of lines.
+ */
+
+ while (1) {
+ while (nodePtr->nextPtr == NULL) {
+ if (nodePtr->parentPtr == NULL ||
+ nodePtr->parentPtr == searchPtr->tagPtr->tagRootPtr) {
+ goto searchOver;
+ }
+ nodePtr = nodePtr->parentPtr;
+ }
+ nodePtr = nodePtr->nextPtr;
+ for (summaryPtr = nodePtr->summaryPtr; summaryPtr != NULL;
+ summaryPtr = summaryPtr->nextPtr) {
+ if ((searchPtr->allTags) ||
+ (summaryPtr->tagPtr == searchPtr->tagPtr)) {
+ goto gotNodeWithTag;
+ }
+ }
+ searchPtr->linesLeft -= nodePtr->numLines;
+ }
+
+ /*
+ * At this point we've found a subtree that has a relevant tag
+ * transition. Now search down (and across) through that subtree to
+ * find the first level-0 node that has a relevant tag transition.
+ */
+
+ gotNodeWithTag:
+ while (nodePtr->level > 0) {
+ for (nodePtr = nodePtr->children.nodePtr; ;
+ nodePtr = nodePtr->nextPtr) {
+ for (summaryPtr = nodePtr->summaryPtr; summaryPtr != NULL;
+ summaryPtr = summaryPtr->nextPtr) {
+ if ((searchPtr->allTags)
+ || (summaryPtr->tagPtr == searchPtr->tagPtr)) {
+ /*
+ * Would really like a multi-level continue here...
+ */
+
+ goto nextChild;
+ }
+ }
+ searchPtr->linesLeft -= nodePtr->numLines;
+ if (nodePtr->nextPtr == NULL) {
+ Tcl_Panic("TkBTreeNextTag found incorrect tag summary info");
+ }
+ }
+ nextChild:
+ continue;
+ }
+
+ /*
+ * Now we're down to a level-0 node that contains a line that contains
+ * a relevant tag transition. Set up line information and go back to
+ * the beginning of the loop to search through lines.
+ */
+
+ searchPtr->curIndex.linePtr = nodePtr->children.linePtr;
+ searchPtr->curIndex.byteIndex = 0;
+ segPtr = searchPtr->curIndex.linePtr->segPtr;
+ if (searchPtr->linesLeft <= 0) {
+ goto searchOver;
+ }
+ continue;
+ }
+
+ searchOver:
+ searchPtr->linesLeft = 0;
+ searchPtr->segPtr = NULL;
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkBTreePrevTag --
+ *
+ * Once a tag search has begun, successive calls to this function return
+ * successive tag toggles in the reverse direction. Note: it is NOT SAFE
+ * to call this function if characters have been inserted into or deleted
+ * from the B-tree since the call to TkBTreeStartSearch.
+ *
+ * Results:
+ * The return value is 1 if another toggle was found that met the
+ * criteria specified in the call to TkBTreeStartSearch; in this case
+ * searchPtr->curIndex gives the toggle's position and
+ * searchPtr->curTagPtr points to its segment. 0 is returned if no more
+ * matching tag transitions were found; in this case searchPtr->curIndex
+ * is the same as searchPtr->stopIndex.
+ *
+ * Side effects:
+ * Information in *searchPtr is modified to update the state of the
+ * search and indicate where the next tag toggle is located.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkBTreePrevTag(
+ register TkTextSearch *searchPtr)
+ /* Information about search in progress; must
+ * have been set up by call to
+ * TkBTreeStartSearch. */
+{
+ register TkTextSegment *segPtr, *prevPtr;
+ register TkTextLine *linePtr, *prevLinePtr;
+ register Node *nodePtr, *node2Ptr, *prevNodePtr;
+ register Summary *summaryPtr;
+ int byteIndex, linesSkipped;
+ int pastLast; /* Saw last marker during scan. */
+
+ if (searchPtr->linesLeft <= 0) {
+ goto searchOver;
+ }
+
+ /*
+ * The outermost loop iterates over lines that may potentially contain a
+ * relevant tag transition, starting from the current segment in the
+ * current line. "nextPtr" is maintained as the last segment in a line
+ * that we can look at.
+ */
+
+ while (1) {
+ /*
+ * Check for the last toggle before the current segment on this line.
+ */
+
+ byteIndex = 0;
+ if (searchPtr->lastPtr == NULL) {
+ /*
+ * Search back to the very beginning, so pastLast is irrelevent.
+ */
+
+ pastLast = 1;
+ } else {
+ pastLast = 0;
+ }
+
+ for (prevPtr = NULL, segPtr = searchPtr->curIndex.linePtr->segPtr ;
+ segPtr != NULL && segPtr != searchPtr->nextPtr;
+ segPtr = segPtr->nextPtr) {
+ if (((segPtr->typePtr == &tkTextToggleOnType)
+ || (segPtr->typePtr == &tkTextToggleOffType))
+ && (searchPtr->allTags
+ || (segPtr->body.toggle.tagPtr == searchPtr->tagPtr))) {
+ prevPtr = segPtr;
+ searchPtr->curIndex.byteIndex = byteIndex;
+ }
+ if (segPtr == searchPtr->lastPtr) {
+ prevPtr = NULL; /* Segments earlier than last don't
+ * count. */
+ pastLast = 1;
+ }
+ byteIndex += segPtr->size;
+ }
+ if (prevPtr != NULL) {
+ if (searchPtr->linesLeft == 1 && !pastLast) {
+ /*
+ * We found a segment that is before the stopping index. Note
+ * that it is OK if prevPtr == lastPtr.
+ */
+
+ goto searchOver;
+ }
+ searchPtr->segPtr = prevPtr;
+ searchPtr->nextPtr = prevPtr;
+ searchPtr->tagPtr = prevPtr->body.toggle.tagPtr;
+ return 1;
+ }
+
+ searchPtr->linesLeft--;
+ if (searchPtr->linesLeft <= 0) {
+ goto searchOver;
+ }
+
+ /*
+ * See if there are more lines associated with the current parent
+ * node. If so, go back to the top of the loop to search the previous
+ * one.
+ */
+
+ nodePtr = searchPtr->curIndex.linePtr->parentPtr;
+ for (prevLinePtr = NULL, linePtr = nodePtr->children.linePtr;
+ linePtr != NULL && linePtr != searchPtr->curIndex.linePtr;
+ prevLinePtr = linePtr, linePtr = linePtr->nextPtr) {
+ /* empty loop body */ ;
+ }
+ if (prevLinePtr != NULL) {
+ searchPtr->curIndex.linePtr = prevLinePtr;
+ searchPtr->nextPtr = NULL;
+ continue;
+ }
+ if (nodePtr == searchPtr->tagPtr->tagRootPtr) {
+ goto searchOver;
+ }
+
+ /*
+ * Search across and up through the B-tree's node hierarchy looking
+ * for the previous node that has a relevant tag transition somewhere
+ * in its subtree. The search and line counting is trickier with/out
+ * back pointers. We'll scan all the nodes under a parent up to the
+ * current node, searching all of them for tag state. The last one we
+ * find, if any, is recorded in prevNodePtr, and any nodes past
+ * prevNodePtr that don't have tag state increment linesSkipped.
+ */
+
+ while (1) {
+ for (prevNodePtr = NULL, linesSkipped = 0,
+ node2Ptr = nodePtr->parentPtr->children.nodePtr ;
+ node2Ptr != nodePtr; node2Ptr = node2Ptr->nextPtr) {
+ for (summaryPtr = node2Ptr->summaryPtr; summaryPtr != NULL;
+ summaryPtr = summaryPtr->nextPtr) {
+ if ((searchPtr->allTags) ||
+ (summaryPtr->tagPtr == searchPtr->tagPtr)) {
+ prevNodePtr = node2Ptr;
+ linesSkipped = 0;
+ goto keepLooking;
+ }
+ }
+ linesSkipped += node2Ptr->numLines;
+
+ keepLooking:
+ continue;
+ }
+ if (prevNodePtr != NULL) {
+ nodePtr = prevNodePtr;
+ searchPtr->linesLeft -= linesSkipped;
+ goto gotNodeWithTag;
+ }
+ nodePtr = nodePtr->parentPtr;
+ if (nodePtr->parentPtr == NULL ||
+ nodePtr == searchPtr->tagPtr->tagRootPtr) {
+ goto searchOver;
+ }
+ }
+
+ /*
+ * At this point we've found a subtree that has a relevant tag
+ * transition. Now search down (and across) through that subtree to
+ * find the last level-0 node that has a relevant tag transition.
+ */
+
+ gotNodeWithTag:
+ while (nodePtr->level > 0) {
+ for (linesSkipped = 0, prevNodePtr = NULL,
+ nodePtr = nodePtr->children.nodePtr; nodePtr != NULL ;
+ nodePtr = nodePtr->nextPtr) {
+ for (summaryPtr = nodePtr->summaryPtr; summaryPtr != NULL;
+ summaryPtr = summaryPtr->nextPtr) {
+ if ((searchPtr->allTags)
+ || (summaryPtr->tagPtr == searchPtr->tagPtr)) {
+ prevNodePtr = nodePtr;
+ linesSkipped = 0;
+ goto keepLooking2;
+ }
+ }
+ linesSkipped += nodePtr->numLines;
+
+ keepLooking2:
+ continue;
+ }
+ if (prevNodePtr == NULL) {
+ Tcl_Panic("TkBTreePrevTag found incorrect tag summary info");
+ }
+ searchPtr->linesLeft -= linesSkipped;
+ nodePtr = prevNodePtr;
+ }
+
+ /*
+ * Now we're down to a level-0 node that contains a line that contains
+ * a relevant tag transition. Set up line information and go back to
+ * the beginning of the loop to search through lines. We start with
+ * the last line below the node.
+ */
+
+ for (prevLinePtr = NULL, linePtr = nodePtr->children.linePtr;
+ linePtr != NULL ;
+ prevLinePtr = linePtr, linePtr = linePtr->nextPtr) {
+ /* empty loop body */ ;
+ }
+ searchPtr->curIndex.linePtr = prevLinePtr;
+ searchPtr->curIndex.byteIndex = 0;
+ if (searchPtr->linesLeft <= 0) {
+ goto searchOver;
+ }
+ continue;
+ }
+
+ searchOver:
+ searchPtr->linesLeft = 0;
+ searchPtr->segPtr = NULL;
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkBTreeCharTagged --
+ *
+ * Determine whether a particular character has a particular tag.
+ *
+ * Results:
+ * The return value is 1 if the given tag is in effect at the character
+ * given by linePtr and ch, and 0 otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkBTreeCharTagged(
+ const TkTextIndex *indexPtr,/* Indicates a character position at which to
+ * check for a tag. */
+ TkTextTag *tagPtr) /* Tag of interest. */
+{
+ register Node *nodePtr;
+ register TkTextLine *siblingLinePtr;
+ register TkTextSegment *segPtr;
+ TkTextSegment *toggleSegPtr;
+ int toggles, index;
+
+ /*
+ * Check for toggles for the tag in indexPtr's line but before indexPtr.
+ * If there is one, its type indicates whether or not the character is
+ * tagged.
+ */
+
+ toggleSegPtr = NULL;
+ for (index = 0, segPtr = indexPtr->linePtr->segPtr;
+ (index + segPtr->size) <= indexPtr->byteIndex;
+ index += segPtr->size, segPtr = segPtr->nextPtr) {
+ if (((segPtr->typePtr == &tkTextToggleOnType)
+ || (segPtr->typePtr == &tkTextToggleOffType))
+ && (segPtr->body.toggle.tagPtr == tagPtr)) {
+ toggleSegPtr = segPtr;
+ }
+ }
+ if (toggleSegPtr != NULL) {
+ return (toggleSegPtr->typePtr == &tkTextToggleOnType);
+ }
+
+ /*
+ * No toggle in this line. Look for toggles for the tag in lines that are
+ * predecessors of indexPtr->linePtr but under the same level-0 node.
+ */
+
+ for (siblingLinePtr = indexPtr->linePtr->parentPtr->children.linePtr;
+ siblingLinePtr != indexPtr->linePtr;
+ siblingLinePtr = siblingLinePtr->nextPtr) {
+ for (segPtr = siblingLinePtr->segPtr; segPtr != NULL;
+ segPtr = segPtr->nextPtr) {
+ if (((segPtr->typePtr == &tkTextToggleOnType)
+ || (segPtr->typePtr == &tkTextToggleOffType))
+ && (segPtr->body.toggle.tagPtr == tagPtr)) {
+ toggleSegPtr = segPtr;
+ }
+ }
+ }
+ if (toggleSegPtr != NULL) {
+ return (toggleSegPtr->typePtr == &tkTextToggleOnType);
+ }
+
+ /*
+ * No toggle in this node. Scan upwards through the ancestors of this
+ * node, counting the number of toggles of the given tag in siblings that
+ * precede that node.
+ */
+
+ toggles = 0;
+ for (nodePtr = indexPtr->linePtr->parentPtr; nodePtr->parentPtr != NULL;
+ nodePtr = nodePtr->parentPtr) {
+ register Node *siblingPtr;
+ register Summary *summaryPtr;
+
+ for (siblingPtr = nodePtr->parentPtr->children.nodePtr;
+ siblingPtr != nodePtr; siblingPtr = siblingPtr->nextPtr) {
+ for (summaryPtr = siblingPtr->summaryPtr; summaryPtr != NULL;
+ summaryPtr = summaryPtr->nextPtr) {
+ if (summaryPtr->tagPtr == tagPtr) {
+ toggles += summaryPtr->toggleCount;
+ }
+ }
+ }
+ if (nodePtr == tagPtr->tagRootPtr) {
+ break;
+ }
+ }
+
+ /*
+ * An odd number of toggles means that the tag is present at the given
+ * point.
+ */
+
+ return toggles & 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkBTreeGetTags --
+ *
+ * Return information about all of the tags that are associated with a
+ * particular character in a B-tree of text.
+ *
+ * Results:
+ * The return value is a malloc-ed array containing pointers to
+ * information for each of the tags that is associated with the character
+ * at the position given by linePtr and ch. The word at *numTagsPtr is
+ * filled in with the number of pointers in the array. It is up to the
+ * caller to free the array by passing it to free. If there are no tags
+ * at the given character then a NULL pointer is returned and *numTagsPtr
+ * will be set to 0.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+TkTextTag **
+TkBTreeGetTags(
+ const TkTextIndex *indexPtr,/* Indicates a particular position in the
+ * B-tree. */
+ const TkText *textPtr, /* If non-NULL, then only return tags for this
+ * text widget (when there are peer
+ * widgets). */
+ int *numTagsPtr) /* Store number of tags found at this
+ * location. */
+{
+ register Node *nodePtr;
+ register TkTextLine *siblingLinePtr;
+ register TkTextSegment *segPtr;
+ TkTextLine *linePtr;
+ int src, dst, index;
+ TagInfo tagInfo;
+#define NUM_TAG_INFOS 10
+
+ tagInfo.numTags = 0;
+ tagInfo.arraySize = NUM_TAG_INFOS;
+ tagInfo.tagPtrs = ckalloc(NUM_TAG_INFOS * sizeof(TkTextTag *));
+ tagInfo.counts = ckalloc(NUM_TAG_INFOS * sizeof(int));
+
+ /*
+ * Record tag toggles within the line of indexPtr but preceding indexPtr.
+ */
+
+ linePtr = indexPtr->linePtr;
+ index = 0;
+ segPtr = linePtr->segPtr;
+ while ((index + segPtr->size) <= indexPtr->byteIndex) {
+ if ((segPtr->typePtr == &tkTextToggleOnType)
+ || (segPtr->typePtr == &tkTextToggleOffType)) {
+ IncCount(segPtr->body.toggle.tagPtr, 1, &tagInfo);
+ }
+ index += segPtr->size;
+ segPtr = segPtr->nextPtr;
+
+ if (segPtr == NULL) {
+ /*
+ * Two logical lines merged into one display line through eliding
+ * of a newline.
+ */
+
+ linePtr = TkBTreeNextLine(NULL, linePtr);
+ segPtr = linePtr->segPtr;
+ }
+ }
+
+ /*
+ * Record toggles for tags in lines that are predecessors of
+ * indexPtr->linePtr but under the same level-0 node.
+ */
+
+ for (siblingLinePtr = indexPtr->linePtr->parentPtr->children.linePtr;
+ siblingLinePtr != indexPtr->linePtr;
+ siblingLinePtr = siblingLinePtr->nextPtr) {
+ for (segPtr = siblingLinePtr->segPtr; segPtr != NULL;
+ segPtr = segPtr->nextPtr) {
+ if ((segPtr->typePtr == &tkTextToggleOnType)
+ || (segPtr->typePtr == &tkTextToggleOffType)) {
+ IncCount(segPtr->body.toggle.tagPtr, 1, &tagInfo);
+ }
+ }
+ }
+
+ /*
+ * For each node in the ancestry of this line, record tag toggles for all
+ * siblings that precede that node.
+ */
+
+ for (nodePtr = indexPtr->linePtr->parentPtr; nodePtr->parentPtr != NULL;
+ nodePtr = nodePtr->parentPtr) {
+ register Node *siblingPtr;
+ register Summary *summaryPtr;
+
+ for (siblingPtr = nodePtr->parentPtr->children.nodePtr;
+ siblingPtr != nodePtr; siblingPtr = siblingPtr->nextPtr) {
+ for (summaryPtr = siblingPtr->summaryPtr; summaryPtr != NULL;
+ summaryPtr = summaryPtr->nextPtr) {
+ if (summaryPtr->toggleCount & 1) {
+ IncCount(summaryPtr->tagPtr, summaryPtr->toggleCount,
+ &tagInfo);
+ }
+ }
+ }
+ }
+
+ /*
+ * Go through the tag information and squash out all of the tags that have
+ * even toggle counts (these tags exist before the point of interest, but
+ * not at the desired character itself). Also squash out all tags that
+ * don't belong to the requested widget.
+ */
+
+ for (src = 0, dst = 0; src < tagInfo.numTags; src++) {
+ if (tagInfo.counts[src] & 1) {
+ const TkText *tagTextPtr = tagInfo.tagPtrs[src]->textPtr;
+
+ if (tagTextPtr==NULL || textPtr==NULL || tagTextPtr==textPtr) {
+ tagInfo.tagPtrs[dst] = tagInfo.tagPtrs[src];
+ dst++;
+ }
+ }
+ }
+ *numTagsPtr = dst;
+ ckfree(tagInfo.counts);
+ if (dst == 0) {
+ ckfree(tagInfo.tagPtrs);
+ return NULL;
+ }
+ return tagInfo.tagPtrs;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkTextIsElided --
+ *
+ * Special case to just return information about elided attribute.
+ * Specialized from TkBTreeGetTags(indexPtr, textPtr, numTagsPtr) and
+ * GetStyle(textPtr, indexPtr). Just need to keep track of invisibility
+ * settings for each priority, pick highest one active at end.
+ *
+ * Note that this returns all elide information up to and including the
+ * given index (quite obviously). However, this does mean that if
+ * indexPtr is a line-start and one then iterates from the beginning of
+ * that line forwards, one will actually revisit the segPtrs of size zero
+ * (for tag toggling, for example) which have already been seen here.
+ *
+ * For this reason we fill in the fields 'segPtr' and 'segOffset' of
+ * elideInfo, enabling our caller easily to calculate incremental changes
+ * from where we left off.
+ *
+ * Results:
+ * Returns whether this text should be elided or not.
+ *
+ * Optionally returns more detailed information in elideInfo.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+int
+TkTextIsElided(
+ const TkText *textPtr, /* Overall information about text widget. */
+ const TkTextIndex *indexPtr,/* The character in the text for which display
+ * information is wanted. */
+ TkTextElideInfo *elideInfo) /* NULL or a pointer to a structure in which
+ * indexPtr's elide state will be stored and
+ * returned. */
+{
+ register Node *nodePtr;
+ register TkTextLine *siblingLinePtr;
+ register TkTextSegment *segPtr;
+ register TkTextTag *tagPtr = NULL;
+ register int i, index;
+ register TkTextElideInfo *infoPtr;
+ TkTextLine *linePtr;
+ int elide;
+
+ if (elideInfo == NULL) {
+ infoPtr = ckalloc(sizeof(TkTextElideInfo));
+ } else {
+ infoPtr = elideInfo;
+ }
+
+ infoPtr->elide = 0; /* If nobody says otherwise, it's visible. */
+ infoPtr->tagCnts = infoPtr->deftagCnts;
+ infoPtr->tagPtrs = infoPtr->deftagPtrs;
+ infoPtr->numTags = textPtr->sharedTextPtr->numTags;
+
+ /*
+ * Almost always avoid malloc, so stay out of system calls.
+ */
+
+ if (LOTSA_TAGS < infoPtr->numTags) {
+ infoPtr->tagCnts = ckalloc(sizeof(int) * infoPtr->numTags);
+ infoPtr->tagPtrs = ckalloc(sizeof(TkTextTag *) * infoPtr->numTags);
+ }
+
+ for (i=0; i<infoPtr->numTags; i++) {
+ infoPtr->tagCnts[i] = 0;
+ }
+
+ /*
+ * Record tag toggles within the line of indexPtr but preceding indexPtr.
+ */
+
+ index = 0;
+ linePtr = indexPtr->linePtr;
+ segPtr = linePtr->segPtr;
+ while ((index + segPtr->size) <= indexPtr->byteIndex) {
+ if ((segPtr->typePtr == &tkTextToggleOnType)
+ || (segPtr->typePtr == &tkTextToggleOffType)) {
+ tagPtr = segPtr->body.toggle.tagPtr;
+ if (tagPtr->elideString != NULL) {
+ infoPtr->tagPtrs[tagPtr->priority] = tagPtr;
+ infoPtr->tagCnts[tagPtr->priority]++;
+ }
+ }
+
+ index += segPtr->size;
+ segPtr = segPtr->nextPtr;
+ if (segPtr == NULL) {
+ /*
+ * Two logical lines merged into one display line through eliding
+ * of a newline.
+ */
+
+ linePtr = TkBTreeNextLine(NULL, linePtr);
+ segPtr = linePtr->segPtr;
+ }
+ }
+
+ /*
+ * Store the first segPtr we haven't examined completely so that our
+ * caller knows where to start.
+ */
+
+ infoPtr->segPtr = segPtr;
+ infoPtr->segOffset = index;
+
+ /*
+ * Record toggles for tags in lines that are predecessors of
+ * indexPtr->linePtr but under the same level-0 node.
+ */
+
+ for (siblingLinePtr = indexPtr->linePtr->parentPtr->children.linePtr;
+ siblingLinePtr != indexPtr->linePtr;
+ siblingLinePtr = siblingLinePtr->nextPtr) {
+ for (segPtr = siblingLinePtr->segPtr; segPtr != NULL;
+ segPtr = segPtr->nextPtr) {
+ if ((segPtr->typePtr == &tkTextToggleOnType)
+ || (segPtr->typePtr == &tkTextToggleOffType)) {
+ tagPtr = segPtr->body.toggle.tagPtr;
+ if (tagPtr->elideString != NULL) {
+ infoPtr->tagPtrs[tagPtr->priority] = tagPtr;
+ infoPtr->tagCnts[tagPtr->priority]++;
+ }
+ }
+ }
+ }
+
+ /*
+ * For each node in the ancestry of this line, record tag toggles for all
+ * siblings that precede that node.
+ */
+
+ for (nodePtr = indexPtr->linePtr->parentPtr; nodePtr->parentPtr != NULL;
+ nodePtr = nodePtr->parentPtr) {
+ register Node *siblingPtr;
+ register Summary *summaryPtr;
+
+ for (siblingPtr = nodePtr->parentPtr->children.nodePtr;
+ siblingPtr != nodePtr; siblingPtr = siblingPtr->nextPtr) {
+ for (summaryPtr = siblingPtr->summaryPtr; summaryPtr != NULL;
+ summaryPtr = summaryPtr->nextPtr) {
+ if (summaryPtr->toggleCount & 1) {
+ tagPtr = summaryPtr->tagPtr;
+ if (tagPtr->elideString != NULL) {
+ infoPtr->tagPtrs[tagPtr->priority] = tagPtr;
+ infoPtr->tagCnts[tagPtr->priority] +=
+ summaryPtr->toggleCount;
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * Now traverse from highest priority to lowest, take elided value from
+ * first odd count (= on).
+ */
+
+ infoPtr->elidePriority = -1;
+ for (i = infoPtr->numTags-1; i >=0; i--) {
+ if (infoPtr->tagCnts[i] & 1) {
+ infoPtr->elide = infoPtr->tagPtrs[i]->elide;
+
+ /*
+ * Note: i == infoPtr->tagPtrs[i]->priority
+ */
+
+ infoPtr->elidePriority = i;
+ break;
+ }
+ }
+
+ elide = infoPtr->elide;
+
+ if (elideInfo == NULL) {
+ if (LOTSA_TAGS < infoPtr->numTags) {
+ ckfree(infoPtr->tagCnts);
+ ckfree(infoPtr->tagPtrs);
+ }
+
+ ckfree(infoPtr);
+ }
+
+ return elide;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkTextFreeElideInfo --
+ *
+ * This is a utility function used to free up any memory allocated by the
+ * TkTextIsElided function above.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory may be freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkTextFreeElideInfo(
+ TkTextElideInfo *elideInfo) /* Free any allocated memory in this
+ * structure. */
+{
+ if (LOTSA_TAGS < elideInfo->numTags) {
+ ckfree(elideInfo->tagCnts);
+ ckfree(elideInfo->tagPtrs);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * IncCount --
+ *
+ * This is a utility function used by TkBTreeGetTags. It increments the
+ * count for a particular tag, adding a new entry for that tag if there
+ * wasn't one previously.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The information at *tagInfoPtr may be modified, and the arrays may be
+ * reallocated to make them larger.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+IncCount(
+ TkTextTag *tagPtr, /* Handle for tag. */
+ int inc, /* Amount by which to increment tag count. */
+ TagInfo *tagInfoPtr) /* Holds cumulative information about tags;
+ * increment count here. */
+{
+ register TkTextTag **tagPtrPtr;
+ int count;
+
+ for (tagPtrPtr = tagInfoPtr->tagPtrs, count = tagInfoPtr->numTags;
+ count > 0; tagPtrPtr++, count--) {
+ if (*tagPtrPtr == tagPtr) {
+ tagInfoPtr->counts[tagInfoPtr->numTags-count] += inc;
+ return;
+ }
+ }
+
+ /*
+ * There isn't currently an entry for this tag, so we have to make a new
+ * one. If the arrays are full, then enlarge the arrays first.
+ */
+
+ if (tagInfoPtr->numTags == tagInfoPtr->arraySize) {
+ TkTextTag **newTags;
+ int *newCounts, newSize;
+
+ newSize = 2 * tagInfoPtr->arraySize;
+ newTags = ckalloc(newSize * sizeof(TkTextTag *));
+ memcpy(newTags, tagInfoPtr->tagPtrs,
+ tagInfoPtr->arraySize * sizeof(TkTextTag *));
+ ckfree(tagInfoPtr->tagPtrs);
+ tagInfoPtr->tagPtrs = newTags;
+ newCounts = ckalloc(newSize * sizeof(int));
+ memcpy(newCounts, tagInfoPtr->counts,
+ tagInfoPtr->arraySize * sizeof(int));
+ ckfree(tagInfoPtr->counts);
+ tagInfoPtr->counts = newCounts;
+ tagInfoPtr->arraySize = newSize;
+ }
+
+ tagInfoPtr->tagPtrs[tagInfoPtr->numTags] = tagPtr;
+ tagInfoPtr->counts[tagInfoPtr->numTags] = inc;
+ tagInfoPtr->numTags++;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkBTreeCheck --
+ *
+ * This function runs a set of consistency checks over a B-tree and
+ * panics if any inconsistencies are found.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If a structural defect is found, the function panics with an error
+ * message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkBTreeCheck(
+ TkTextBTree tree) /* Tree to check. */
+{
+ BTree *treePtr = (BTree *) tree;
+ register Summary *summaryPtr;
+ register Node *nodePtr;
+ register TkTextLine *linePtr;
+ register TkTextSegment *segPtr;
+ register TkTextTag *tagPtr;
+ Tcl_HashEntry *entryPtr;
+ Tcl_HashSearch search;
+ int count;
+
+ /*
+ * Make sure that the tag toggle counts and the tag root pointers are OK.
+ */
+
+ for (entryPtr=Tcl_FirstHashEntry(&treePtr->sharedTextPtr->tagTable,&search);
+ entryPtr != NULL ; entryPtr = Tcl_NextHashEntry(&search)) {
+ tagPtr = Tcl_GetHashValue(entryPtr);
+ nodePtr = tagPtr->tagRootPtr;
+ if (nodePtr == NULL) {
+ if (tagPtr->toggleCount != 0) {
+ Tcl_Panic("TkBTreeCheck found \"%s\" with toggles (%d) but no root",
+ tagPtr->name, tagPtr->toggleCount);
+ }
+ continue; /* No ranges for the tag. */
+ } else if (tagPtr->toggleCount == 0) {
+ Tcl_Panic("TkBTreeCheck found root for \"%s\" with no toggles",
+ tagPtr->name);
+ } else if (tagPtr->toggleCount & 1) {
+ Tcl_Panic("TkBTreeCheck found odd toggle count for \"%s\" (%d)",
+ tagPtr->name, tagPtr->toggleCount);
+ }
+ for (summaryPtr = nodePtr->summaryPtr; summaryPtr != NULL;
+ summaryPtr = summaryPtr->nextPtr) {
+ if (summaryPtr->tagPtr == tagPtr) {
+ Tcl_Panic("TkBTreeCheck found root node with summary info");
+ }
+ }
+ count = 0;
+ if (nodePtr->level > 0) {
+ for (nodePtr = nodePtr->children.nodePtr ; nodePtr != NULL ;
+ nodePtr = nodePtr->nextPtr) {
+ for (summaryPtr = nodePtr->summaryPtr; summaryPtr != NULL;
+ summaryPtr = summaryPtr->nextPtr) {
+ if (summaryPtr->tagPtr == tagPtr) {
+ count += summaryPtr->toggleCount;
+ }
+ }
+ }
+ } else {
+ for (linePtr = nodePtr->children.linePtr ; linePtr != NULL ;
+ linePtr = linePtr->nextPtr) {
+ for (segPtr = linePtr->segPtr; segPtr != NULL;
+ segPtr = segPtr->nextPtr) {
+ if ((segPtr->typePtr == &tkTextToggleOnType ||
+ segPtr->typePtr == &tkTextToggleOffType) &&
+ segPtr->body.toggle.tagPtr == tagPtr) {
+ count++;
+ }
+ }
+ }
+ }
+ if (count != tagPtr->toggleCount) {
+ Tcl_Panic("TkBTreeCheck toggleCount (%d) wrong for \"%s\" should be (%d)",
+ tagPtr->toggleCount, tagPtr->name, count);
+ }
+ }
+
+ /*
+ * Call a recursive function to do the main body of checks.
+ */
+
+ nodePtr = treePtr->rootPtr;
+ CheckNodeConsistency(treePtr->rootPtr, treePtr->pixelReferences);
+
+ /*
+ * Make sure that there are at least two lines in the text and that the
+ * last line has no characters except a newline.
+ */
+
+ if (nodePtr->numLines < 2) {
+ Tcl_Panic("TkBTreeCheck: less than 2 lines in tree");
+ }
+ while (nodePtr->level > 0) {
+ nodePtr = nodePtr->children.nodePtr;
+ while (nodePtr->nextPtr != NULL) {
+ nodePtr = nodePtr->nextPtr;
+ }
+ }
+ linePtr = nodePtr->children.linePtr;
+ while (linePtr->nextPtr != NULL) {
+ linePtr = linePtr->nextPtr;
+ }
+ segPtr = linePtr->segPtr;
+ while ((segPtr->typePtr == &tkTextToggleOffType)
+ || (segPtr->typePtr == &tkTextRightMarkType)
+ || (segPtr->typePtr == &tkTextLeftMarkType)) {
+ /*
+ * It's OK to toggle a tag off in the last line, but not to start a
+ * new range. It's also OK to have marks in the last line.
+ */
+
+ segPtr = segPtr->nextPtr;
+ }
+ if (segPtr->typePtr != &tkTextCharType) {
+ Tcl_Panic("TkBTreeCheck: last line has bogus segment type");
+ }
+ if (segPtr->nextPtr != NULL) {
+ Tcl_Panic("TkBTreeCheck: last line has too many segments");
+ }
+ if (segPtr->size != 1) {
+ Tcl_Panic("TkBTreeCheck: last line has wrong # characters: %d",
+ segPtr->size);
+ }
+ if ((segPtr->body.chars[0] != '\n') || (segPtr->body.chars[1] != 0)) {
+ Tcl_Panic("TkBTreeCheck: last line had bad value: %s",
+ segPtr->body.chars);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CheckNodeConsistency --
+ *
+ * This function is called as part of consistency checking for B-trees:
+ * it checks several aspects of a node and also runs checks recursively
+ * on the node's children.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If anything suspicious is found in the tree structure, the function
+ * panics.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+CheckNodeConsistency(
+ register Node *nodePtr, /* Node whose subtree should be checked. */
+ int references) /* Number of referring widgets which have
+ * pixel counts. */
+{
+ register Node *childNodePtr;
+ register Summary *summaryPtr, *summaryPtr2;
+ register TkTextLine *linePtr;
+ register TkTextSegment *segPtr;
+ int numChildren, numLines, toggleCount, minChildren, i;
+ int *numPixels;
+ int pixels[PIXEL_CLIENTS];
+
+ if (nodePtr->parentPtr != NULL) {
+ minChildren = MIN_CHILDREN;
+ } else if (nodePtr->level > 0) {
+ minChildren = 2;
+ } else {
+ minChildren = 1;
+ }
+ if ((nodePtr->numChildren < minChildren)
+ || (nodePtr->numChildren > MAX_CHILDREN)) {
+ Tcl_Panic("CheckNodeConsistency: bad child count (%d)",
+ nodePtr->numChildren);
+ }
+
+ numChildren = 0;
+ numLines = 0;
+ if (references > PIXEL_CLIENTS) {
+ numPixels = ckalloc(sizeof(int) * references);
+ } else {
+ numPixels = pixels;
+ }
+ for (i = 0; i<references; i++) {
+ numPixels[i] = 0;
+ }
+
+ if (nodePtr->level == 0) {
+ for (linePtr = nodePtr->children.linePtr; linePtr != NULL;
+ linePtr = linePtr->nextPtr) {
+ if (linePtr->parentPtr != nodePtr) {
+ Tcl_Panic("CheckNodeConsistency: line doesn't point to parent");
+ }
+ if (linePtr->segPtr == NULL) {
+ Tcl_Panic("CheckNodeConsistency: line has no segments");
+ }
+ for (segPtr = linePtr->segPtr; segPtr != NULL;
+ segPtr = segPtr->nextPtr) {
+ if (segPtr->typePtr->checkProc != NULL) {
+ segPtr->typePtr->checkProc(segPtr, linePtr);
+ }
+ if ((segPtr->size == 0) && (!segPtr->typePtr->leftGravity)
+ && (segPtr->nextPtr != NULL)
+ && (segPtr->nextPtr->size == 0)
+ && (segPtr->nextPtr->typePtr->leftGravity)) {
+ Tcl_Panic("CheckNodeConsistency: wrong segment order for gravity");
+ }
+ if ((segPtr->nextPtr == NULL)
+ && (segPtr->typePtr != &tkTextCharType)) {
+ Tcl_Panic("CheckNodeConsistency: line ended with wrong type");
+ }
+ }
+ numChildren++;
+ numLines++;
+ for (i = 0; i<references; i++) {
+ numPixels[i] += linePtr->pixels[2 * i];
+ }
+ }
+ } else {
+ for (childNodePtr = nodePtr->children.nodePtr; childNodePtr != NULL;
+ childNodePtr = childNodePtr->nextPtr) {
+ if (childNodePtr->parentPtr != nodePtr) {
+ Tcl_Panic("CheckNodeConsistency: node doesn't point to parent");
+ }
+ if (childNodePtr->level != (nodePtr->level-1)) {
+ Tcl_Panic("CheckNodeConsistency: level mismatch (%d %d)",
+ nodePtr->level, childNodePtr->level);
+ }
+ CheckNodeConsistency(childNodePtr, references);
+ for (summaryPtr = childNodePtr->summaryPtr; summaryPtr != NULL;
+ summaryPtr = summaryPtr->nextPtr) {
+ for (summaryPtr2 = nodePtr->summaryPtr; ;
+ summaryPtr2 = summaryPtr2->nextPtr) {
+ if (summaryPtr2 == NULL) {
+ if (summaryPtr->tagPtr->tagRootPtr == nodePtr) {
+ break;
+ }
+ Tcl_Panic("CheckNodeConsistency: node tag \"%s\" not %s",
+ summaryPtr->tagPtr->name,
+ "present in parent summaries");
+ }
+ if (summaryPtr->tagPtr == summaryPtr2->tagPtr) {
+ break;
+ }
+ }
+ }
+ numChildren++;
+ numLines += childNodePtr->numLines;
+ for (i = 0; i<references; i++) {
+ numPixels[i] += childNodePtr->numPixels[i];
+ }
+ }
+ }
+ if (numChildren != nodePtr->numChildren) {
+ Tcl_Panic("CheckNodeConsistency: mismatch in numChildren (%d %d)",
+ numChildren, nodePtr->numChildren);
+ }
+ if (numLines != nodePtr->numLines) {
+ Tcl_Panic("CheckNodeConsistency: mismatch in numLines (%d %d)",
+ numLines, nodePtr->numLines);
+ }
+ for (i = 0; i<references; i++) {
+ if (numPixels[i] != nodePtr->numPixels[i]) {
+ Tcl_Panic("CheckNodeConsistency: mismatch in numPixels (%d %d) for widget (%d)",
+ numPixels[i], nodePtr->numPixels[i], i);
+ }
+ }
+ if (references > PIXEL_CLIENTS) {
+ ckfree(numPixels);
+ }
+
+ for (summaryPtr = nodePtr->summaryPtr; summaryPtr != NULL;
+ summaryPtr = summaryPtr->nextPtr) {
+ if (summaryPtr->tagPtr->toggleCount == summaryPtr->toggleCount) {
+ Tcl_Panic("CheckNodeConsistency: found unpruned root for \"%s\"",
+ summaryPtr->tagPtr->name);
+ }
+ toggleCount = 0;
+ if (nodePtr->level == 0) {
+ for (linePtr = nodePtr->children.linePtr; linePtr != NULL;
+ linePtr = linePtr->nextPtr) {
+ for (segPtr = linePtr->segPtr; segPtr != NULL;
+ segPtr = segPtr->nextPtr) {
+ if ((segPtr->typePtr != &tkTextToggleOnType)
+ && (segPtr->typePtr != &tkTextToggleOffType)) {
+ continue;
+ }
+ if (segPtr->body.toggle.tagPtr == summaryPtr->tagPtr) {
+ toggleCount++;
+ }
+ }
+ }
+ } else {
+ for (childNodePtr = nodePtr->children.nodePtr;
+ childNodePtr != NULL;
+ childNodePtr = childNodePtr->nextPtr) {
+ for (summaryPtr2 = childNodePtr->summaryPtr;
+ summaryPtr2 != NULL;
+ summaryPtr2 = summaryPtr2->nextPtr) {
+ if (summaryPtr2->tagPtr == summaryPtr->tagPtr) {
+ toggleCount += summaryPtr2->toggleCount;
+ }
+ }
+ }
+ }
+ if (toggleCount != summaryPtr->toggleCount) {
+ Tcl_Panic("CheckNodeConsistency: mismatch in toggleCount (%d %d)",
+ toggleCount, summaryPtr->toggleCount);
+ }
+ for (summaryPtr2 = summaryPtr->nextPtr; summaryPtr2 != NULL;
+ summaryPtr2 = summaryPtr2->nextPtr) {
+ if (summaryPtr2->tagPtr == summaryPtr->tagPtr) {
+ Tcl_Panic("CheckNodeConsistency: duplicated node tag: %s",
+ summaryPtr->tagPtr->name);
+ }
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Rebalance --
+ *
+ * This function is called when a node of a B-tree appears to be out of
+ * balance (too many children, or too few). It rebalances that node and
+ * all of its ancestors in the tree.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The internal structure of treePtr may change.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+Rebalance(
+ BTree *treePtr, /* Tree that is being rebalanced. */
+ register Node *nodePtr) /* Node that may be out of balance. */
+{
+ /*
+ * Loop over the entire ancestral chain of the node, working up through
+ * the tree one node at a time until the root node has been processed.
+ */
+
+ for ( ; nodePtr != NULL; nodePtr = nodePtr->parentPtr) {
+ register Node *newPtr, *childPtr;
+ register TkTextLine *linePtr;
+ int i;
+
+ /*
+ * Check to see if the node has too many children. If it does, then
+ * split off all but the first MIN_CHILDREN into a separate node
+ * following the original one. Then repeat until the node has a decent
+ * size.
+ */
+
+ if (nodePtr->numChildren > MAX_CHILDREN) {
+ while (1) {
+ /*
+ * If the node being split is the root node, then make a new
+ * root node above it first.
+ */
+
+ if (nodePtr->parentPtr == NULL) {
+ newPtr = ckalloc(sizeof(Node));
+ newPtr->parentPtr = NULL;
+ newPtr->nextPtr = NULL;
+ newPtr->summaryPtr = NULL;
+ newPtr->level = nodePtr->level + 1;
+ newPtr->children.nodePtr = nodePtr;
+ newPtr->numChildren = 1;
+ newPtr->numLines = nodePtr->numLines;
+ newPtr->numPixels =
+ ckalloc(sizeof(int) * treePtr->pixelReferences);
+ for (i=0; i<treePtr->pixelReferences; i++) {
+ newPtr->numPixels[i] = nodePtr->numPixels[i];
+ }
+ RecomputeNodeCounts(treePtr, newPtr);
+ treePtr->rootPtr = newPtr;
+ }
+ newPtr = ckalloc(sizeof(Node));
+ newPtr->numPixels =
+ ckalloc(sizeof(int) * treePtr->pixelReferences);
+ for (i=0; i<treePtr->pixelReferences; i++) {
+ newPtr->numPixels[i] = 0;
+ }
+ newPtr->parentPtr = nodePtr->parentPtr;
+ newPtr->nextPtr = nodePtr->nextPtr;
+ nodePtr->nextPtr = newPtr;
+ newPtr->summaryPtr = NULL;
+ newPtr->level = nodePtr->level;
+ newPtr->numChildren = nodePtr->numChildren - MIN_CHILDREN;
+ if (nodePtr->level == 0) {
+ for (i = MIN_CHILDREN-1,
+ linePtr = nodePtr->children.linePtr;
+ i > 0; i--, linePtr = linePtr->nextPtr) {
+ /* Empty loop body. */
+ }
+ newPtr->children.linePtr = linePtr->nextPtr;
+ linePtr->nextPtr = NULL;
+ } else {
+ for (i = MIN_CHILDREN-1,
+ childPtr = nodePtr->children.nodePtr;
+ i > 0; i--, childPtr = childPtr->nextPtr) {
+ /* Empty loop body. */
+ }
+ newPtr->children.nodePtr = childPtr->nextPtr;
+ childPtr->nextPtr = NULL;
+ }
+ RecomputeNodeCounts(treePtr, nodePtr);
+ nodePtr->parentPtr->numChildren++;
+ nodePtr = newPtr;
+ if (nodePtr->numChildren <= MAX_CHILDREN) {
+ RecomputeNodeCounts(treePtr, nodePtr);
+ break;
+ }
+ }
+ }
+
+ while (nodePtr->numChildren < MIN_CHILDREN) {
+ register Node *otherPtr;
+ Node *halfwayNodePtr = NULL; /* Initialization needed only */
+ TkTextLine *halfwayLinePtr = NULL; /* to prevent cc warnings. */
+ int totalChildren, firstChildren, i;
+
+ /*
+ * Too few children for this node. If this is the root then, it's
+ * OK for it to have less than MIN_CHILDREN children as long as
+ * it's got at least two. If it has only one (and isn't at level
+ * 0), then chop the root node out of the tree and use its child
+ * as the new root.
+ */
+
+ if (nodePtr->parentPtr == NULL) {
+ if ((nodePtr->numChildren == 1) && (nodePtr->level > 0)) {
+ treePtr->rootPtr = nodePtr->children.nodePtr;
+ treePtr->rootPtr->parentPtr = NULL;
+ DeleteSummaries(nodePtr->summaryPtr);
+ ckfree(nodePtr->numPixels);
+ ckfree(nodePtr);
+ }
+ return;
+ }
+
+ /*
+ * Not the root. Make sure that there are siblings to balance
+ * with.
+ */
+
+ if (nodePtr->parentPtr->numChildren < 2) {
+ Rebalance(treePtr, nodePtr->parentPtr);
+ continue;
+ }
+
+ /*
+ * Find a sibling neighbor to borrow from, and arrange for nodePtr
+ * to be the earlier of the pair.
+ */
+
+ if (nodePtr->nextPtr == NULL) {
+ for (otherPtr = nodePtr->parentPtr->children.nodePtr;
+ otherPtr->nextPtr != nodePtr;
+ otherPtr = otherPtr->nextPtr) {
+ /* Empty loop body. */
+ }
+ nodePtr = otherPtr;
+ }
+ otherPtr = nodePtr->nextPtr;
+
+ /*
+ * We're going to either merge the two siblings together into one
+ * node or redivide the children among them to balance their
+ * loads. As preparation, join their two child lists into a single
+ * list and remember the half-way point in the list.
+ */
+
+ totalChildren = nodePtr->numChildren + otherPtr->numChildren;
+ firstChildren = totalChildren/2;
+ if (nodePtr->children.nodePtr == NULL) {
+ nodePtr->children = otherPtr->children;
+ otherPtr->children.nodePtr = NULL;
+ otherPtr->children.linePtr = NULL;
+ }
+ if (nodePtr->level == 0) {
+ register TkTextLine *linePtr;
+
+ for (linePtr = nodePtr->children.linePtr, i = 1;
+ linePtr->nextPtr != NULL;
+ linePtr = linePtr->nextPtr, i++) {
+ if (i == firstChildren) {
+ halfwayLinePtr = linePtr;
+ }
+ }
+ linePtr->nextPtr = otherPtr->children.linePtr;
+ while (i <= firstChildren) {
+ halfwayLinePtr = linePtr;
+ linePtr = linePtr->nextPtr;
+ i++;
+ }
+ } else {
+ register Node *childPtr;
+
+ for (childPtr = nodePtr->children.nodePtr, i = 1;
+ childPtr->nextPtr != NULL;
+ childPtr = childPtr->nextPtr, i++) {
+ if (i <= firstChildren) {
+ if (i == firstChildren) {
+ halfwayNodePtr = childPtr;
+ }
+ }
+ }
+ childPtr->nextPtr = otherPtr->children.nodePtr;
+ while (i <= firstChildren) {
+ halfwayNodePtr = childPtr;
+ childPtr = childPtr->nextPtr;
+ i++;
+ }
+ }
+
+ /*
+ * If the two siblings can simply be merged together, do it.
+ */
+
+ if (totalChildren <= MAX_CHILDREN) {
+ RecomputeNodeCounts(treePtr, nodePtr);
+ nodePtr->nextPtr = otherPtr->nextPtr;
+ nodePtr->parentPtr->numChildren--;
+ DeleteSummaries(otherPtr->summaryPtr);
+ ckfree(otherPtr->numPixels);
+ ckfree(otherPtr);
+ continue;
+ }
+
+ /*
+ * The siblings can't be merged, so just divide their children
+ * evenly between them.
+ */
+
+ if (nodePtr->level == 0) {
+ CLANG_ASSERT(halfwayLinePtr);
+ otherPtr->children.linePtr = halfwayLinePtr->nextPtr;
+ halfwayLinePtr->nextPtr = NULL;
+ } else {
+ CLANG_ASSERT(halfwayNodePtr);
+ otherPtr->children.nodePtr = halfwayNodePtr->nextPtr;
+ halfwayNodePtr->nextPtr = NULL;
+ }
+ RecomputeNodeCounts(treePtr, nodePtr);
+ RecomputeNodeCounts(treePtr, otherPtr);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * RecomputeNodeCounts --
+ *
+ * This function is called to recompute all the counts in a node (tags,
+ * child information, etc.) by scanning the information in its
+ * descendants. This function is called during rebalancing when a node's
+ * child structure has changed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The tag counts for nodePtr are modified to reflect its current child
+ * structure, as are its numChildren and numLines fields. Also, all of
+ * the childrens' parentPtr fields are made to point to nodePtr.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+RecomputeNodeCounts(
+ register BTree *treePtr, /* The whole B-tree. */
+ register Node *nodePtr) /* Node whose tag summary information must be
+ * recomputed. */
+{
+ register Summary *summaryPtr, *summaryPtr2;
+ register Node *childPtr;
+ register TkTextLine *linePtr;
+ register TkTextSegment *segPtr;
+ TkTextTag *tagPtr;
+ int ref;
+
+ /*
+ * Zero out all the existing counts for the node, but don't delete the
+ * existing Summary records (most of them will probably be reused).
+ */
+
+ for (summaryPtr = nodePtr->summaryPtr; summaryPtr != NULL;
+ summaryPtr = summaryPtr->nextPtr) {
+ summaryPtr->toggleCount = 0;
+ }
+ nodePtr->numChildren = 0;
+ nodePtr->numLines = 0;
+ for (ref = 0; ref<treePtr->pixelReferences; ref++) {
+ nodePtr->numPixels[ref] = 0;
+ }
+
+ /*
+ * Scan through the children, adding the childrens' tag counts into the
+ * node's tag counts and adding new Summary structures if necessary.
+ */
+
+ if (nodePtr->level == 0) {
+ for (linePtr = nodePtr->children.linePtr; linePtr != NULL;
+ linePtr = linePtr->nextPtr) {
+ nodePtr->numChildren++;
+ nodePtr->numLines++;
+ for (ref = 0; ref<treePtr->pixelReferences; ref++) {
+ nodePtr->numPixels[ref] += linePtr->pixels[2 * ref];
+ }
+ linePtr->parentPtr = nodePtr;
+ for (segPtr = linePtr->segPtr; segPtr != NULL;
+ segPtr = segPtr->nextPtr) {
+ if (((segPtr->typePtr != &tkTextToggleOnType)
+ && (segPtr->typePtr != &tkTextToggleOffType))
+ || !(segPtr->body.toggle.inNodeCounts)) {
+ continue;
+ }
+ tagPtr = segPtr->body.toggle.tagPtr;
+ for (summaryPtr = nodePtr->summaryPtr; ;
+ summaryPtr = summaryPtr->nextPtr) {
+ if (summaryPtr == NULL) {
+ summaryPtr = ckalloc(sizeof(Summary));
+ summaryPtr->tagPtr = tagPtr;
+ summaryPtr->toggleCount = 1;
+ summaryPtr->nextPtr = nodePtr->summaryPtr;
+ nodePtr->summaryPtr = summaryPtr;
+ break;
+ }
+ if (summaryPtr->tagPtr == tagPtr) {
+ summaryPtr->toggleCount++;
+ break;
+ }
+ }
+ }
+ }
+ } else {
+ for (childPtr = nodePtr->children.nodePtr; childPtr != NULL;
+ childPtr = childPtr->nextPtr) {
+ nodePtr->numChildren++;
+ nodePtr->numLines += childPtr->numLines;
+ for (ref = 0; ref<treePtr->pixelReferences; ref++) {
+ nodePtr->numPixels[ref] += childPtr->numPixels[ref];
+ }
+ childPtr->parentPtr = nodePtr;
+ for (summaryPtr2 = childPtr->summaryPtr; summaryPtr2 != NULL;
+ summaryPtr2 = summaryPtr2->nextPtr) {
+ for (summaryPtr = nodePtr->summaryPtr; ;
+ summaryPtr = summaryPtr->nextPtr) {
+ if (summaryPtr == NULL) {
+ summaryPtr = ckalloc(sizeof(Summary));
+ summaryPtr->tagPtr = summaryPtr2->tagPtr;
+ summaryPtr->toggleCount = summaryPtr2->toggleCount;
+ summaryPtr->nextPtr = nodePtr->summaryPtr;
+ nodePtr->summaryPtr = summaryPtr;
+ break;
+ }
+ if (summaryPtr->tagPtr == summaryPtr2->tagPtr) {
+ summaryPtr->toggleCount += summaryPtr2->toggleCount;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * Scan through the node's tag records again and delete any Summary
+ * records that still have a zero count, or that have all the toggles.
+ * The node with the children that account for all the tags toggles have
+ * no summary information, and they become the tagRootPtr for the tag.
+ */
+
+ summaryPtr2 = NULL;
+ for (summaryPtr = nodePtr->summaryPtr; summaryPtr != NULL; ) {
+ if (summaryPtr->toggleCount > 0 &&
+ summaryPtr->toggleCount < summaryPtr->tagPtr->toggleCount) {
+ if (nodePtr->level == summaryPtr->tagPtr->tagRootPtr->level) {
+ /*
+ * The tag's root node split and some toggles left. The tag
+ * root must move up a level.
+ */
+
+ summaryPtr->tagPtr->tagRootPtr = nodePtr->parentPtr;
+ }
+ summaryPtr2 = summaryPtr;
+ summaryPtr = summaryPtr->nextPtr;
+ continue;
+ }
+ if (summaryPtr->toggleCount == summaryPtr->tagPtr->toggleCount) {
+ /*
+ * A node merge has collected all the toggles under one node. Push
+ * the root down to this level.
+ */
+
+ summaryPtr->tagPtr->tagRootPtr = nodePtr;
+ }
+ if (summaryPtr2 != NULL) {
+ summaryPtr2->nextPtr = summaryPtr->nextPtr;
+ ckfree(summaryPtr);
+ summaryPtr = summaryPtr2->nextPtr;
+ } else {
+ nodePtr->summaryPtr = summaryPtr->nextPtr;
+ ckfree(summaryPtr);
+ summaryPtr = nodePtr->summaryPtr;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkBTreeNumLines --
+ *
+ * This function returns a count of the number of logical lines of text
+ * present in a given B-tree.
+ *
+ * Results:
+ * The return value is a count of the number of usable lines in tree
+ * (i.e. it doesn't include the dummy line that is just used to mark the
+ * end of the tree).
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkBTreeNumLines(
+ TkTextBTree tree, /* Information about tree. */
+ const TkText *textPtr) /* Relative to this client of the B-tree. */
+{
+ BTree *treePtr = (BTree *) tree;
+ int count;
+
+ if (textPtr != NULL && textPtr->end != NULL) {
+ count = TkBTreeLinesTo(NULL, textPtr->end);
+ } else {
+ count = treePtr->rootPtr->numLines - 1;
+ }
+ if (textPtr != NULL && textPtr->start != NULL) {
+ count -= TkBTreeLinesTo(NULL, textPtr->start);
+ }
+
+ return count;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkBTreeNumPixels --
+ *
+ * This function returns a count of the number of pixels of text present
+ * in a given widget's B-tree representation.
+ *
+ * Results:
+ * The return value is a count of the number of usable pixels in tree
+ * (since the dummy line used to mark the end of the B-tree is maintained
+ * with zero height, as are any lines that are before or after the
+ * '-start -end' range of the text widget in question, the number stored
+ * at the root is the number we want).
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkBTreeNumPixels(
+ TkTextBTree tree, /* The B-tree. */
+ const TkText *textPtr) /* Relative to this client of the B-tree. */
+{
+ BTree *treePtr = (BTree *) tree;
+ return treePtr->rootPtr->numPixels[textPtr->pixelReference];
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * CharSplitProc --
+ *
+ * This function implements splitting for character segments.
+ *
+ * Results:
+ * The return value is a pointer to a chain of two segments that have the
+ * same characters as segPtr except split among the two segments.
+ *
+ * Side effects:
+ * Storage for segPtr is freed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static TkTextSegment *
+CharSplitProc(
+ TkTextSegment *segPtr, /* Pointer to segment to split. */
+ int index) /* Position within segment at which to
+ * split. */
+{
+ TkTextSegment *newPtr1, *newPtr2;
+
+ newPtr1 = ckalloc(CSEG_SIZE(index));
+ newPtr2 = ckalloc(CSEG_SIZE(segPtr->size - index));
+ newPtr1->typePtr = &tkTextCharType;
+ newPtr1->nextPtr = newPtr2;
+ newPtr1->size = index;
+ memcpy(newPtr1->body.chars, segPtr->body.chars, (size_t) index);
+ newPtr1->body.chars[index] = 0;
+ newPtr2->typePtr = &tkTextCharType;
+ newPtr2->nextPtr = segPtr->nextPtr;
+ newPtr2->size = segPtr->size - index;
+ memcpy(newPtr2->body.chars, segPtr->body.chars + index, newPtr2->size);
+ newPtr2->body.chars[newPtr2->size] = 0;
+ ckfree(segPtr);
+ return newPtr1;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * CharCleanupProc --
+ *
+ * This function merges adjacent character segments into a single
+ * character segment, if possible.
+ *
+ * Results:
+ * The return value is a pointer to the first segment in the (new) list
+ * of segments that used to start with segPtr.
+ *
+ * Side effects:
+ * Storage for the segments may be allocated and freed.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static TkTextSegment *
+CharCleanupProc(
+ TkTextSegment *segPtr, /* Pointer to first of two adjacent segments
+ * to join. */
+ TkTextLine *linePtr) /* Line containing segments (not used). */
+{
+ TkTextSegment *segPtr2, *newPtr;
+
+ segPtr2 = segPtr->nextPtr;
+ if ((segPtr2 == NULL) || (segPtr2->typePtr != &tkTextCharType)) {
+ return segPtr;
+ }
+ newPtr = ckalloc(CSEG_SIZE(segPtr->size + segPtr2->size));
+ newPtr->typePtr = &tkTextCharType;
+ newPtr->nextPtr = segPtr2->nextPtr;
+ newPtr->size = segPtr->size + segPtr2->size;
+ memcpy(newPtr->body.chars, segPtr->body.chars, segPtr->size);
+ memcpy(newPtr->body.chars + segPtr->size, segPtr2->body.chars, segPtr2->size);
+ newPtr->body.chars[newPtr->size] = 0;
+ ckfree(segPtr);
+ ckfree(segPtr2);
+ return newPtr;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * CharDeleteProc --
+ *
+ * This function is invoked to delete a character segment.
+ *
+ * Results:
+ * Always returns 0 to indicate that the segment was deleted.
+ *
+ * Side effects:
+ * Storage for the segment is freed.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+CharDeleteProc(
+ TkTextSegment *segPtr, /* Segment to delete. */
+ TkTextLine *linePtr, /* Line containing segment. */
+ int treeGone) /* Non-zero means the entire tree is being
+ * deleted, so everything must get cleaned
+ * up. */
+{
+ ckfree(segPtr);
+ return 0;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * CharCheckProc --
+ *
+ * This function is invoked to perform consistency checks on character
+ * segments.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If the segment isn't inconsistent then the function panics.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static void
+CharCheckProc(
+ TkTextSegment *segPtr, /* Segment to check. */
+ TkTextLine *linePtr) /* Line containing segment. */
+{
+ /*
+ * Make sure that the segment contains the number of characters indicated
+ * by its header, and that the last segment in a line ends in a newline.
+ * Also make sure that there aren't ever two character segments adjacent
+ * to each other: they should be merged together.
+ */
+
+ if (segPtr->size <= 0) {
+ Tcl_Panic("CharCheckProc: segment has size <= 0");
+ }
+ if (strlen(segPtr->body.chars) != (size_t) segPtr->size) {
+ Tcl_Panic("CharCheckProc: segment has wrong size");
+ }
+ if (segPtr->nextPtr == NULL) {
+ if (segPtr->body.chars[segPtr->size-1] != '\n') {
+ Tcl_Panic("CharCheckProc: line doesn't end with newline");
+ }
+ } else if (segPtr->nextPtr->typePtr == &tkTextCharType) {
+ Tcl_Panic("CharCheckProc: adjacent character segments weren't merged");
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ToggleDeleteProc --
+ *
+ * This function is invoked to delete toggle segments.
+ *
+ * Results:
+ * Returns 1 to indicate that the segment may not be deleted, unless the
+ * entire B-tree is going away.
+ *
+ * Side effects:
+ * If the tree is going away then the toggle's memory is freed; otherwise
+ * the toggle counts in nodes above the segment get updated.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+ToggleDeleteProc(
+ TkTextSegment *segPtr, /* Segment to check. */
+ TkTextLine *linePtr, /* Line containing segment. */
+ int treeGone) /* Non-zero means the entire tree is being
+ * deleted, so everything must get cleaned
+ * up. */
+{
+ if (treeGone) {
+ ckfree(segPtr);
+ return 0;
+ }
+
+ /*
+ * This toggle is in the middle of a range of characters that's being
+ * deleted. Refuse to die. We'll be moved to the end of the deleted range
+ * and our cleanup function will be called later. Decrement node toggle
+ * counts here, and set a flag so we'll re-increment them in the cleanup
+ * function.
+ */
+
+ if (segPtr->body.toggle.inNodeCounts) {
+ ChangeNodeToggleCount(linePtr->parentPtr,
+ segPtr->body.toggle.tagPtr, -1);
+ segPtr->body.toggle.inNodeCounts = 0;
+ }
+ return 1;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ToggleCleanupProc --
+ *
+ * This function is called when a toggle is part of a line that's been
+ * modified in some way. It's invoked after the modifications are
+ * complete.
+ *
+ * Results:
+ * The return value is the head segment in a new list that is to replace
+ * the tail of the line that used to start at segPtr. This allows the
+ * function to delete or modify segPtr.
+ *
+ * Side effects:
+ * Toggle counts in the nodes above the new line will be updated if
+ * they're not already. Toggles may be collapsed if there are duplicate
+ * toggles at the same position.
+ *
+ *--------------------------------------------------------------
+ */
+
+static TkTextSegment *
+ToggleCleanupProc(
+ TkTextSegment *segPtr, /* Segment to check. */
+ TkTextLine *linePtr) /* Line that now contains segment. */
+{
+ TkTextSegment *segPtr2, *prevPtr;
+ int counts;
+
+ /*
+ * If this is a toggle-off segment, look ahead through the next segments
+ * to see if there's a toggle-on segment for the same tag before any
+ * segments with non-zero size. If so then the two toggles cancel each
+ * other; remove them both.
+ */
+
+ if (segPtr->typePtr == &tkTextToggleOffType) {
+ for (prevPtr = segPtr, segPtr2 = prevPtr->nextPtr;
+ (segPtr2 != NULL) && (segPtr2->size == 0);
+ prevPtr = segPtr2, segPtr2 = prevPtr->nextPtr) {
+ if (segPtr2->typePtr != &tkTextToggleOnType) {
+ continue;
+ }
+ if (segPtr2->body.toggle.tagPtr != segPtr->body.toggle.tagPtr) {
+ continue;
+ }
+ counts = segPtr->body.toggle.inNodeCounts
+ + segPtr2->body.toggle.inNodeCounts;
+ if (counts != 0) {
+ ChangeNodeToggleCount(linePtr->parentPtr,
+ segPtr->body.toggle.tagPtr, -counts);
+ }
+ prevPtr->nextPtr = segPtr2->nextPtr;
+ ckfree(segPtr2);
+ segPtr2 = segPtr->nextPtr;
+ ckfree(segPtr);
+ return segPtr2;
+ }
+ }
+
+ if (!segPtr->body.toggle.inNodeCounts) {
+ ChangeNodeToggleCount(linePtr->parentPtr,
+ segPtr->body.toggle.tagPtr, 1);
+ segPtr->body.toggle.inNodeCounts = 1;
+ }
+ return segPtr;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ToggleLineChangeProc --
+ *
+ * This function is invoked when a toggle segment is about to move from
+ * one line to another.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Toggle counts are decremented in the nodes above the line.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ToggleLineChangeProc(
+ TkTextSegment *segPtr, /* Segment to check. */
+ TkTextLine *linePtr) /* Line that used to contain segment. */
+{
+ if (segPtr->body.toggle.inNodeCounts) {
+ ChangeNodeToggleCount(linePtr->parentPtr,
+ segPtr->body.toggle.tagPtr, -1);
+ segPtr->body.toggle.inNodeCounts = 0;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ToggleCheckProc --
+ *
+ * This function is invoked to perform consistency checks on toggle
+ * segments.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If a consistency problem is found the function panics.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ToggleCheckProc(
+ TkTextSegment *segPtr, /* Segment to check. */
+ TkTextLine *linePtr) /* Line containing segment. */
+{
+ register Summary *summaryPtr;
+ int needSummary;
+
+ if (segPtr->size != 0) {
+ Tcl_Panic("ToggleCheckProc: segment had non-zero size");
+ }
+ if (!segPtr->body.toggle.inNodeCounts) {
+ Tcl_Panic("ToggleCheckProc: toggle counts not updated in nodes");
+ }
+ needSummary = (segPtr->body.toggle.tagPtr->tagRootPtr!=linePtr->parentPtr);
+ for (summaryPtr = linePtr->parentPtr->summaryPtr; ;
+ summaryPtr = summaryPtr->nextPtr) {
+ if (summaryPtr == NULL) {
+ if (needSummary) {
+ Tcl_Panic("ToggleCheckProc: tag not present in node");
+ } else {
+ break;
+ }
+ }
+ if (summaryPtr->tagPtr == segPtr->body.toggle.tagPtr) {
+ if (!needSummary) {
+ Tcl_Panic("ToggleCheckProc: tag present in root node summary");
+ }
+ break;
+ }
+ }
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkTextDisp.c b/tk8.6/generic/tkTextDisp.c
new file mode 100644
index 0000000..c848fd2
--- /dev/null
+++ b/tk8.6/generic/tkTextDisp.c
@@ -0,0 +1,9106 @@
+/*
+ * tkTextDisp.c --
+ *
+ * This module provides facilities to display text widgets. It is the
+ * only place where information is kept about the screen layout of text
+ * widgets. (Well, strictly, each TkTextLine and B-tree node caches its
+ * last observed pixel height, but that information originates here).
+ *
+ * Copyright (c) 1992-1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "tkInt.h"
+#include "tkText.h"
+
+#ifdef _WIN32
+#include "tkWinInt.h"
+#elif defined(__CYGWIN__)
+#include "tkUnixInt.h"
+#endif
+
+#ifdef MAC_OSX_TK
+#include "tkMacOSXInt.h"
+#define OK_TO_LOG (!TkpAppIsDrawing())
+#define FORCE_DISPLAY(winPtr) TkpDisplayWindow(winPtr)
+#else
+#define OK_TO_LOG 1
+#define FORCE_DISPLAY(winPtr)
+#endif
+
+/*
+ * "Calculations of line pixel heights and the size of the vertical
+ * scrollbar."
+ *
+ * Given that tag, font and elide changes can happen to large numbers of
+ * diverse chunks in a text widget containing megabytes of text, it is not
+ * possible to recalculate all affected height information immediately any
+ * such change takes place and maintain a responsive user-experience. Yet, for
+ * an accurate vertical scrollbar to be drawn, we must know the total number
+ * of vertical pixels shown on display versus the number available to be
+ * displayed.
+ *
+ * The way the text widget solves this problem is by maintaining cached line
+ * pixel heights (in the BTree for each logical line), and having asynchronous
+ * timer callbacks (i) to iterate through the logical lines recalculating
+ * their heights, and (ii) to recalculate the vertical scrollbar's position
+ * and size.
+ *
+ * Typically this works well but there are some situations where the overall
+ * functional design of this file causes some problems. These problems can
+ * only arise because the calculations used to display lines on screen are not
+ * connected to those in the iterating-line- recalculation-process.
+ *
+ * The reason for this disconnect is that the display calculations operate in
+ * display lines, and the iteration and cache operates in logical lines.
+ * Given that the display calculations both need not contain complete logical
+ * lines (at top or bottom of display), and that they do not actually keep
+ * track of logical lines (for simplicity of code and historical design), this
+ * means a line may be known and drawn with a different pixel height to that
+ * which is cached in the BTree, and this might cause some temporary
+ * undesirable mismatch between display and the vertical scrollbar.
+ *
+ * All such mismatches should be temporary, however, since the asynchronous
+ * height calculations will always catch up eventually.
+ *
+ * For further details see the comments before and within the following
+ * functions below: LayoutDLine, AsyncUpdateLineMetrics, GetYView,
+ * GetYPixelCount, TkTextUpdateOneLine, TkTextUpdateLineMetrics.
+ *
+ * For details of the way in which the BTree keeps track of pixel heights, see
+ * tkTextBTree.c. Basically the BTree maintains two pieces of information: the
+ * logical line indices and the pixel height cache.
+ */
+
+/*
+ * TK_LAYOUT_WITH_BASE_CHUNKS:
+ *
+ * With this macro set, collect all char chunks that have no holes
+ * between them, that are on the same line and use the same font and font
+ * size. Allocate the chars of all these chunks, the so-called "stretch",
+ * in a DString in the first chunk, the so-called "base chunk". Use the
+ * base chunk string for measuring and drawing, so that these actions are
+ * always performed with maximum context.
+ *
+ * This is necessary for text rendering engines that provide ligatures
+ * and sub-pixel layout, like ATSU on Mac. If we don't do this, the
+ * measuring will change all the time, leading to an ugly "tremble and
+ * shiver" effect. This is because of the continuous splitting and
+ * re-merging of chunks that goes on in a text widget, when the cursor or
+ * the selection move.
+ *
+ * Side effects:
+ *
+ * Memory management changes. Instead of attaching the character data to
+ * the clientData structures of the char chunks, an additional DString is
+ * used. The collection process will even lead to resizing this DString
+ * for large stretches (> TCL_DSTRING_STATIC_SIZE == 200). We could
+ * reduce the overall memory footprint by copying the result to a plain
+ * char array after the line breaking process, but that would complicate
+ * the code and make performance even worse speedwise. See also TODOs.
+ *
+ * TODOs:
+ *
+ * - Move the character collection process from the LayoutProc into
+ * LayoutDLine(), so that the collection can be done before actual
+ * layout. In this way measuring can look at the following text, too,
+ * right from the beginning. Memory handling can also be improved with
+ * this. Problem: We don't easily know which chunks are adjacent until
+ * all the other chunks have calculated their width. Apparently marks
+ * would return width==0. A separate char collection loop would have to
+ * know these things.
+ *
+ * - Use a new context parameter to pass the context from LayoutDLine() to
+ * the LayoutProc instead of using a global variable like now. Not
+ * pressing until the previous point gets implemented.
+ */
+
+/*
+ * The following structure describes how to display a range of characters.
+ * The information is generated by scanning all of the tags associated with
+ * the characters and combining that with default information for the overall
+ * widget. These structures form the hash keys for dInfoPtr->styleTable.
+ */
+
+typedef struct StyleValues {
+ Tk_3DBorder border; /* Used for drawing background under text.
+ * NULL means use widget background. */
+ int borderWidth; /* Width of 3-D border for background. */
+ int relief; /* 3-D relief for background. */
+ Pixmap bgStipple; /* Stipple bitmap for background. None means
+ * draw solid. */
+ XColor *fgColor; /* Foreground color for text. */
+ Tk_Font tkfont; /* Font for displaying text. */
+ Pixmap fgStipple; /* Stipple bitmap for text and other
+ * foreground stuff. None means draw solid.*/
+ int justify; /* Justification style for text. */
+ int lMargin1; /* Left margin, in pixels, for first display
+ * line of each text line. */
+ int lMargin2; /* Left margin, in pixels, for second and
+ * later display lines of each text line. */
+ Tk_3DBorder lMarginColor; /* Color of left margins (1 and 2). */
+ int offset; /* Offset in pixels of baseline, relative to
+ * baseline of line. */
+ int overstrike; /* Non-zero means draw overstrike through
+ * text. */
+ XColor *overstrikeColor; /* Foreground color for overstrike through
+ * text. */
+ int rMargin; /* Right margin, in pixels. */
+ Tk_3DBorder rMarginColor; /* Color of right margin. */
+ int spacing1; /* Spacing above first dline in text line. */
+ int spacing2; /* Spacing between lines of dline. */
+ int spacing3; /* Spacing below last dline in text line. */
+ TkTextTabArray *tabArrayPtr;/* Locations and types of tab stops (may be
+ * NULL). */
+ int tabStyle; /* One of TABULAR or WORDPROCESSOR. */
+ int underline; /* Non-zero means draw underline underneath
+ * text. */
+ XColor *underlineColor; /* Foreground color for underline underneath
+ * text. */
+ int elide; /* Zero means draw text, otherwise not. */
+ TkWrapMode wrapMode; /* How to handle wrap-around for this tag.
+ * One of TEXT_WRAPMODE_CHAR,
+ * TEXT_WRAPMODE_NONE or TEXT_WRAPMODE_WORD.*/
+} StyleValues;
+
+/*
+ * The following structure extends the StyleValues structure above with
+ * graphics contexts used to actually draw the characters. The entries in
+ * dInfoPtr->styleTable point to structures of this type.
+ */
+
+typedef struct TextStyle {
+ int refCount; /* Number of times this structure is
+ * referenced in Chunks. */
+ GC bgGC; /* Graphics context for background. None means
+ * use widget background. */
+ GC fgGC; /* Graphics context for foreground. */
+ GC ulGC; /* Graphics context for underline. */
+ GC ovGC; /* Graphics context for overstrike. */
+ StyleValues *sValuePtr; /* Raw information from which GCs were
+ * derived. */
+ Tcl_HashEntry *hPtr; /* Pointer to entry in styleTable. Used to
+ * delete entry. */
+} TextStyle;
+
+/*
+ * The following macro determines whether two styles have the same background
+ * so that, for example, no beveled border should be drawn between them.
+ */
+
+#define SAME_BACKGROUND(s1, s2) \
+ (((s1)->sValuePtr->border == (s2)->sValuePtr->border) \
+ && ((s1)->sValuePtr->borderWidth == (s2)->sValuePtr->borderWidth) \
+ && ((s1)->sValuePtr->relief == (s2)->sValuePtr->relief) \
+ && ((s1)->sValuePtr->bgStipple == (s2)->sValuePtr->bgStipple))
+
+/*
+ * The following macro is used to compare two floating-point numbers to within
+ * a certain degree of scale. Direct comparison fails on processors where the
+ * processor and memory representations of FP numbers of a particular
+ * precision is different (e.g. Intel)
+ */
+
+#define FP_EQUAL_SCALE(double1, double2, scaleFactor) \
+ (fabs((double1)-(double2))*((scaleFactor)+1.0) < 0.3)
+
+/*
+ * Macros to make debugging/testing logging a little easier.
+ *
+ * On OSX 10.14 Drawing procedures are sometimes run because the system has
+ * decided to redraw the window. This can corrupt the data that a test is
+ * trying to collect. So we don't write to the logging variables when the
+ * drawing procedure is being run that way. Other systems can always log.
+ */
+
+#define LOG(toVar,what) \
+ if (OK_TO_LOG) \
+ Tcl_SetVar2(textPtr->interp, toVar, NULL, (what), \
+ TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT)
+#define CLEAR(var) \
+ if (OK_TO_LOG) \
+ Tcl_SetVar2(interp, var, NULL, "", TCL_GLOBAL_ONLY)
+
+/*
+ * The following structure describes one line of the display, which may be
+ * either part or all of one line of the text.
+ */
+
+typedef struct DLine {
+ TkTextIndex index; /* Identifies first character in text that is
+ * displayed on this line. */
+ int byteCount; /* Number of bytes accounted for by this
+ * display line, including a trailing space or
+ * newline that isn't actually displayed. */
+ int logicalLinesMerged; /* Number of extra logical lines merged into
+ * this one due to elided newlines. */
+ int y; /* Y-position at which line is supposed to be
+ * drawn (topmost pixel of rectangular area
+ * occupied by line). */
+ int oldY; /* Y-position at which line currently appears
+ * on display. This is used to move lines by
+ * scrolling rather than re-drawing. If
+ * 'flags' have the OLD_Y_INVALID bit set,
+ * then we will never examine this field
+ * (which means line isn't currently visible
+ * on display and must be redrawn). */
+ int height; /* Height of line, in pixels. */
+ int baseline; /* Offset of text baseline from y, in
+ * pixels. */
+ int spaceAbove; /* How much extra space was added to the top
+ * of the line because of spacing options.
+ * This is included in height and baseline. */
+ int spaceBelow; /* How much extra space was added to the
+ * bottom of the line because of spacing
+ * options. This is included in height. */
+ Tk_3DBorder lMarginColor; /* Background color of the area corresponding
+ * to the left margin of the display line. */
+ int lMarginWidth; /* Pixel width of the area corresponding to
+ * the left margin. */
+ Tk_3DBorder rMarginColor; /* Background color of the area corresponding
+ * to the right margin of the display line. */
+ int rMarginWidth; /* Pixel width of the area corresponding to
+ * the right margin. */
+ int length; /* Total length of line, in pixels. */
+ TkTextDispChunk *chunkPtr; /* Pointer to first chunk in list of all of
+ * those that are displayed on this line of
+ * the screen. */
+ struct DLine *nextPtr; /* Next in list of all display lines for this
+ * window. The list is sorted in order from
+ * top to bottom. Note: the next DLine doesn't
+ * always correspond to the next line of text:
+ * (a) can have multiple DLines for one text
+ * line (wrapping), (b) can have elided newlines,
+ * and (c) can have gaps where DLine's
+ * have been deleted because they're out of
+ * date. */
+ int flags; /* Various flag bits: see below for values. */
+} DLine;
+
+/*
+ * Flag bits for DLine structures:
+ *
+ * HAS_3D_BORDER - Non-zero means that at least one of the chunks
+ * in this line has a 3D border, so it
+ * potentially interacts with 3D borders in
+ * neighboring lines (see DisplayLineBackground).
+ * NEW_LAYOUT - Non-zero means that the line has been
+ * re-layed out since the last time the display
+ * was updated.
+ * TOP_LINE - Non-zero means that this was the top line in
+ * in the window the last time that the window
+ * was laid out. This is important because a line
+ * may be displayed differently if its at the top
+ * or bottom than if it's in the middle
+ * (e.g. beveled edges aren't displayed for
+ * middle lines if the adjacent line has a
+ * similar background).
+ * BOTTOM_LINE - Non-zero means that this was the bottom line
+ * in the window the last time that the window
+ * was laid out.
+ * OLD_Y_INVALID - The value of oldY in the structure is not
+ * valid or useful and should not be examined.
+ * 'oldY' is only useful when the DLine is
+ * currently displayed at a different position
+ * and we wish to re-display it via scrolling, so
+ * this means the DLine needs redrawing.
+ */
+
+#define HAS_3D_BORDER 1
+#define NEW_LAYOUT 2
+#define TOP_LINE 4
+#define BOTTOM_LINE 8
+#define OLD_Y_INVALID 16
+
+/*
+ * Overall display information for a text widget:
+ */
+
+typedef struct TextDInfo {
+ Tcl_HashTable styleTable; /* Hash table that maps from StyleValues to
+ * TextStyles for this widget. */
+ DLine *dLinePtr; /* First in list of all display lines for this
+ * widget, in order from top to bottom. */
+ int topPixelOffset; /* Identifies first pixel in top display line
+ * to display in window. */
+ int newTopPixelOffset; /* Desired first pixel in top display line to
+ * display in window. */
+ GC copyGC; /* Graphics context for copying from off-
+ * screen pixmaps onto screen. */
+ GC scrollGC; /* Graphics context for copying from one place
+ * in the window to another (scrolling):
+ * differs from copyGC in that we need to get
+ * GraphicsExpose events. */
+ int x; /* First x-coordinate that may be used for
+ * actually displaying line information.
+ * Leaves space for border, etc. */
+ int y; /* First y-coordinate that may be used for
+ * actually displaying line information.
+ * Leaves space for border, etc. */
+ int maxX; /* First x-coordinate to right of available
+ * space for displaying lines. */
+ int maxY; /* First y-coordinate below available space
+ * for displaying lines. */
+ int topOfEof; /* Top-most pixel (lowest y-value) that has
+ * been drawn in the appropriate fashion for
+ * the portion of the window after the last
+ * line of the text. This field is used to
+ * figure out when to redraw part or all of
+ * the eof field. */
+
+ /*
+ * Information used for scrolling:
+ */
+
+ int newXPixelOffset; /* Desired x scroll position, measured as the
+ * number of pixels off-screen to the left for
+ * a line with no left margin. */
+ int curXPixelOffset; /* Actual x scroll position, measured as the
+ * number of pixels off-screen to the left. */
+ int maxLength; /* Length in pixels of longest line that's
+ * visible in window (length may exceed window
+ * size). If there's no wrapping, this will be
+ * zero. */
+ double xScrollFirst, xScrollLast;
+ /* Most recent values reported to horizontal
+ * scrollbar; used to eliminate unnecessary
+ * reports. */
+ double yScrollFirst, yScrollLast;
+ /* Most recent values reported to vertical
+ * scrollbar; used to eliminate unnecessary
+ * reports. */
+
+ /*
+ * The following information is used to implement scanning:
+ */
+
+ int scanMarkXPixel; /* Pixel index of left edge of the window when
+ * the scan started. */
+ int scanMarkX; /* X-position of mouse at time scan started. */
+ int scanTotalYScroll; /* Total scrolling (in screen pixels) that has
+ * occurred since scanMarkY was set. */
+ int scanMarkY; /* Y-position of mouse at time scan started. */
+
+ /*
+ * Miscellaneous information:
+ */
+
+ int dLinesInvalidated; /* This value is set to 1 whenever something
+ * happens that invalidates information in
+ * DLine structures; if a redisplay is in
+ * progress, it will see this and abort the
+ * redisplay. This is needed because, for
+ * example, an embedded window could change
+ * its size when it is first displayed,
+ * invalidating the DLine that is currently
+ * being displayed. If redisplay continues, it
+ * will use freed memory and could dump
+ * core. */
+ int flags; /* Various flag values: see below for
+ * definitions. */
+ /*
+ * Information used to handle the asynchronous updating of the y-scrollbar
+ * and the vertical height calculations:
+ */
+
+ int lineMetricUpdateEpoch; /* Stores a number which is incremented each
+ * time the text widget changes in a
+ * significant way (e.g. resizing or
+ * geometry-influencing tag changes). */
+ int currentMetricUpdateLine;/* Stores a counter which is used to iterate
+ * over the logical lines contained in the
+ * widget and update their geometry
+ * calculations, if they are out of date. */
+ TkTextIndex metricIndex; /* If the current metric update line wraps
+ * into very many display lines, then this is
+ * used to keep track of what index we've got
+ * to so far... */
+ int metricPixelHeight; /* ...and this is for the height calculation
+ * so far...*/
+ int metricEpoch; /* ...and this for the epoch of the partial
+ * calculation so it can be cancelled if
+ * things change once more. This field will be
+ * -1 if there is no long-line calculation in
+ * progress, and take a non-negative value if
+ * there is such a calculation in progress. */
+ int lastMetricUpdateLine; /* When the current update line reaches this
+ * line, we are done and should stop the
+ * asychronous callback mechanism. */
+ Tcl_TimerToken lineUpdateTimer;
+ /* A token pointing to the current line metric
+ * update callback. */
+ Tcl_TimerToken scrollbarTimer;
+ /* A token pointing to the current scrollbar
+ * update callback. */
+} TextDInfo;
+
+/*
+ * In TkTextDispChunk structures for character segments, the clientData field
+ * points to one of the following structures:
+ */
+
+#if !TK_LAYOUT_WITH_BASE_CHUNKS
+
+typedef struct CharInfo {
+ int numBytes; /* Number of bytes to display. */
+ char chars[1]; /* UTF characters to display. Actual size will
+ * be numBytes, not 1. THIS MUST BE THE LAST
+ * FIELD IN THE STRUCTURE. */
+} CharInfo;
+
+#else /* TK_LAYOUT_WITH_BASE_CHUNKS */
+
+typedef struct CharInfo {
+ TkTextDispChunk *baseChunkPtr;
+ int baseOffset; /* Starting offset in base chunk
+ * baseChars. */
+ int numBytes; /* Number of bytes that belong to this
+ * chunk. */
+ const char *chars; /* UTF characters to display. Actually points
+ * into the baseChars of the base chunk. Only
+ * valid after FinalizeBaseChunk(). */
+} CharInfo;
+
+/*
+ * The BaseCharInfo is a CharInfo with some additional data added.
+ */
+
+typedef struct BaseCharInfo {
+ CharInfo ci;
+ Tcl_DString baseChars; /* Actual characters for the stretch of text
+ * represented by this base chunk. */
+ int width; /* Width in pixels of the whole string, if
+ * known, else -1. Valid during
+ * LayoutDLine(). */
+} BaseCharInfo;
+
+/* TODO: Thread safety */
+static TkTextDispChunk *baseCharChunkPtr = NULL;
+
+#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */
+
+/*
+ * Flag values for TextDInfo structures:
+ *
+ * DINFO_OUT_OF_DATE: Non-zero means that the DLine structures for
+ * this window are partially or completely out of
+ * date and need to be recomputed.
+ * REDRAW_PENDING: Means that a when-idle handler has been
+ * scheduled to update the display.
+ * REDRAW_BORDERS: Means window border or pad area has
+ * potentially been damaged and must be redrawn.
+ * REPICK_NEEDED: 1 means that the widget has been modified in a
+ * way that could change the current character (a
+ * different character might be under the mouse
+ * cursor now). Need to recompute the current
+ * character before the next redisplay.
+ * OUT_OF_SYNC 1 means that the last <<WidgetViewSync>> event had
+ * value 0, indicating that the widget is out of sync.
+ */
+
+#define DINFO_OUT_OF_DATE 1
+#define REDRAW_PENDING 2
+#define REDRAW_BORDERS 4
+#define REPICK_NEEDED 8
+#define OUT_OF_SYNC 16
+/*
+ * Action values for FreeDLines:
+ *
+ * DLINE_FREE: Free the lines, but no need to unlink them from the
+ * current list of actual display lines.
+ * DLINE_UNLINK: Free and unlink from current display.
+ * DLINE_FREE_TEMP: Free, but don't unlink, and also don't set
+ * 'dLinesInvalidated'.
+ */
+
+#define DLINE_FREE 0
+#define DLINE_UNLINK 1
+#define DLINE_FREE_TEMP 2
+
+/*
+ * The following counters keep statistics about redisplay that can be checked
+ * to see how clever this code is at reducing redisplays.
+ */
+
+static int numRedisplays; /* Number of calls to DisplayText. */
+static int linesRedrawn; /* Number of calls to DisplayDLine. */
+static int numCopies; /* Number of calls to XCopyArea to copy part
+ * of the screen. */
+static int lineHeightsRecalculated;
+ /* Number of line layouts purely for height
+ * calculation purposes.*/
+/*
+ * Forward declarations for functions defined later in this file:
+ */
+
+static void AdjustForTab(TkText *textPtr,
+ TkTextTabArray *tabArrayPtr, int index,
+ TkTextDispChunk *chunkPtr);
+static void CharBboxProc(TkText *textPtr,
+ TkTextDispChunk *chunkPtr, int index, int y,
+ int lineHeight, int baseline, int *xPtr,
+ int *yPtr, int *widthPtr, int *heightPtr);
+static int CharChunkMeasureChars(TkTextDispChunk *chunkPtr,
+ const char *chars, int charsLen,
+ int start, int end, int startX, int maxX,
+ int flags, int *nextX);
+static void CharDisplayProc(TkText *textPtr,
+ TkTextDispChunk *chunkPtr, int x, int y,
+ int height, int baseline, Display *display,
+ Drawable dst, int screenY);
+static int CharMeasureProc(TkTextDispChunk *chunkPtr, int x);
+static void CharUndisplayProc(TkText *textPtr,
+ TkTextDispChunk *chunkPtr);
+#if TK_LAYOUT_WITH_BASE_CHUNKS
+static void FinalizeBaseChunk(TkTextDispChunk *additionalChunkPtr);
+static void FreeBaseChunk(TkTextDispChunk *baseChunkPtr);
+static int IsSameFGStyle(TextStyle *style1, TextStyle *style2);
+static void RemoveFromBaseChunk(TkTextDispChunk *chunkPtr);
+#endif
+/*
+ * Definitions of elided procs. Compiler can't inline these since we use
+ * pointers to these functions. ElideDisplayProc and ElideUndisplayProc are
+ * special-cased for speed, as potentially many elided DLine chunks if large,
+ * tag toggle-filled elided region.
+ */
+static void ElideBboxProc(TkText *textPtr,
+ TkTextDispChunk *chunkPtr, int index, int y,
+ int lineHeight, int baseline, int *xPtr,
+ int *yPtr, int *widthPtr, int *heightPtr);
+static int ElideMeasureProc(TkTextDispChunk *chunkPtr, int x);
+static void DisplayDLine(TkText *textPtr, DLine *dlPtr,
+ DLine *prevPtr, Pixmap pixmap);
+static void DisplayLineBackground(TkText *textPtr, DLine *dlPtr,
+ DLine *prevPtr, Pixmap pixmap);
+static void DisplayText(ClientData clientData);
+static DLine * FindDLine(TkText *textPtr, DLine *dlPtr,
+ const TkTextIndex *indexPtr);
+static void FreeDLines(TkText *textPtr, DLine *firstPtr,
+ DLine *lastPtr, int action);
+static void FreeStyle(TkText *textPtr, TextStyle *stylePtr);
+static TextStyle * GetStyle(TkText *textPtr, const TkTextIndex *indexPtr);
+static void GetXView(Tcl_Interp *interp, TkText *textPtr,
+ int report);
+static void GetYView(Tcl_Interp *interp, TkText *textPtr,
+ int report);
+static int GetYPixelCount(TkText *textPtr, DLine *dlPtr);
+static DLine * LayoutDLine(TkText *textPtr,
+ const TkTextIndex *indexPtr);
+static int MeasureChars(Tk_Font tkfont, const char *source,
+ int maxBytes, int rangeStart, int rangeLength,
+ int startX, int maxX, int flags, int *nextXPtr);
+static void MeasureUp(TkText *textPtr,
+ const TkTextIndex *srcPtr, int distance,
+ TkTextIndex *dstPtr, int *overlap);
+static int NextTabStop(Tk_Font tkfont, int x, int tabOrigin);
+static void UpdateDisplayInfo(TkText *textPtr);
+static void YScrollByLines(TkText *textPtr, int offset);
+static void YScrollByPixels(TkText *textPtr, int offset);
+static int SizeOfTab(TkText *textPtr, int tabStyle,
+ TkTextTabArray *tabArrayPtr, int *indexPtr, int x,
+ int maxX);
+static void TextChanged(TkText *textPtr,
+ const TkTextIndex *index1Ptr,
+ const TkTextIndex *index2Ptr);
+static void TextInvalidateRegion(TkText *textPtr, TkRegion region);
+static void TextRedrawTag(TkText *textPtr,
+ TkTextIndex *index1Ptr, TkTextIndex *index2Ptr,
+ TkTextTag *tagPtr, int withTag);
+static void TextInvalidateLineMetrics(TkText *textPtr,
+ TkTextLine *linePtr, int lineCount, int action);
+static int CalculateDisplayLineHeight(TkText *textPtr,
+ const TkTextIndex *indexPtr, int *byteCountPtr,
+ int *mergedLinePtr);
+static void DlineIndexOfX(TkText *textPtr,
+ DLine *dlPtr, int x, TkTextIndex *indexPtr);
+static int DlineXOfIndex(TkText *textPtr,
+ DLine *dlPtr, int byteIndex);
+static int TextGetScrollInfoObj(Tcl_Interp *interp,
+ TkText *textPtr, int objc,
+ Tcl_Obj *const objv[], double *dblPtr,
+ int *intPtr);
+static void AsyncUpdateLineMetrics(ClientData clientData);
+static void GenerateWidgetViewSyncEvent(TkText *textPtr, Bool InSync);
+static void AsyncUpdateYScrollbar(ClientData clientData);
+static int IsStartOfNotMergedLine(TkText *textPtr,
+ const TkTextIndex *indexPtr);
+
+/*
+ * Result values returned by TextGetScrollInfoObj:
+ */
+
+#define TKTEXT_SCROLL_MOVETO 1
+#define TKTEXT_SCROLL_PAGES 2
+#define TKTEXT_SCROLL_UNITS 3
+#define TKTEXT_SCROLL_ERROR 4
+#define TKTEXT_SCROLL_PIXELS 5
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkTextCreateDInfo --
+ *
+ * This function is called when a new text widget is created. Its job is
+ * to set up display-related information for the widget.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A TextDInfo data structure is allocated and initialized and attached
+ * to textPtr.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkTextCreateDInfo(
+ TkText *textPtr) /* Overall information for text widget. */
+{
+ register TextDInfo *dInfoPtr;
+ XGCValues gcValues;
+
+ dInfoPtr = ckalloc(sizeof(TextDInfo));
+ Tcl_InitHashTable(&dInfoPtr->styleTable, sizeof(StyleValues)/sizeof(int));
+ dInfoPtr->dLinePtr = NULL;
+ dInfoPtr->copyGC = NULL;
+ gcValues.graphics_exposures = True;
+ dInfoPtr->scrollGC = Tk_GetGC(textPtr->tkwin, GCGraphicsExposures,
+ &gcValues);
+ dInfoPtr->topOfEof = 0;
+ dInfoPtr->newXPixelOffset = 0;
+ dInfoPtr->curXPixelOffset = 0;
+ dInfoPtr->maxLength = 0;
+ dInfoPtr->xScrollFirst = -1;
+ dInfoPtr->xScrollLast = -1;
+ dInfoPtr->yScrollFirst = -1;
+ dInfoPtr->yScrollLast = -1;
+ dInfoPtr->scanMarkXPixel = 0;
+ dInfoPtr->scanMarkX = 0;
+ dInfoPtr->scanTotalYScroll = 0;
+ dInfoPtr->scanMarkY = 0;
+ dInfoPtr->dLinesInvalidated = 0;
+ dInfoPtr->flags = 0;
+ dInfoPtr->topPixelOffset = 0;
+ dInfoPtr->newTopPixelOffset = 0;
+ dInfoPtr->currentMetricUpdateLine = -1;
+ dInfoPtr->lastMetricUpdateLine = -1;
+ dInfoPtr->lineMetricUpdateEpoch = 1;
+ dInfoPtr->metricEpoch = -1;
+ dInfoPtr->metricIndex.textPtr = NULL;
+ dInfoPtr->metricIndex.linePtr = NULL;
+ dInfoPtr->lineUpdateTimer = NULL;
+ dInfoPtr->scrollbarTimer = NULL;
+
+ textPtr->dInfoPtr = dInfoPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkTextFreeDInfo --
+ *
+ * This function is called to free up all of the private display
+ * information kept by this file for a text widget.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Lots of resources get freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkTextFreeDInfo(
+ TkText *textPtr) /* Overall information for text widget. */
+{
+ register TextDInfo *dInfoPtr = textPtr->dInfoPtr;
+
+ /*
+ * Be careful to free up styleTable *after* freeing up all the DLines, so
+ * that the hash table is still intact to free up the style-related
+ * information from the lines. Once the lines are all free then styleTable
+ * will be empty.
+ */
+
+ FreeDLines(textPtr, dInfoPtr->dLinePtr, NULL, DLINE_UNLINK);
+ Tcl_DeleteHashTable(&dInfoPtr->styleTable);
+ if (dInfoPtr->copyGC != NULL) {
+ Tk_FreeGC(textPtr->display, dInfoPtr->copyGC);
+ }
+ Tk_FreeGC(textPtr->display, dInfoPtr->scrollGC);
+ if (dInfoPtr->flags & REDRAW_PENDING) {
+ Tcl_CancelIdleCall(DisplayText, textPtr);
+ }
+ if (dInfoPtr->lineUpdateTimer != NULL) {
+ Tcl_DeleteTimerHandler(dInfoPtr->lineUpdateTimer);
+ textPtr->refCount--;
+ dInfoPtr->lineUpdateTimer = NULL;
+ }
+ if (dInfoPtr->scrollbarTimer != NULL) {
+ Tcl_DeleteTimerHandler(dInfoPtr->scrollbarTimer);
+ textPtr->refCount--;
+ dInfoPtr->scrollbarTimer = NULL;
+ }
+ ckfree(dInfoPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetStyle --
+ *
+ * This function creates all the information needed to display text at a
+ * particular location.
+ *
+ * Results:
+ * The return value is a pointer to a TextStyle structure that
+ * corresponds to *sValuePtr.
+ *
+ * Side effects:
+ * A new entry may be created in the style table for the widget.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static TextStyle *
+GetStyle(
+ TkText *textPtr, /* Overall information about text widget. */
+ const TkTextIndex *indexPtr)/* The character in the text for which display
+ * information is wanted. */
+{
+ TkTextTag **tagPtrs;
+ register TkTextTag *tagPtr;
+ StyleValues styleValues;
+ TextStyle *stylePtr;
+ Tcl_HashEntry *hPtr;
+ int numTags, isNew, i;
+ int isSelected;
+ XGCValues gcValues;
+ unsigned long mask;
+ /*
+ * The variables below keep track of the highest-priority specification
+ * that has occurred for each of the various fields of the StyleValues.
+ */
+ int borderPrio, borderWidthPrio, reliefPrio, bgStipplePrio;
+ int fgPrio, fontPrio, fgStipplePrio;
+ int underlinePrio, elidePrio, justifyPrio, offsetPrio;
+ int lMargin1Prio, lMargin2Prio, rMarginPrio;
+ int lMarginColorPrio, rMarginColorPrio;
+ int spacing1Prio, spacing2Prio, spacing3Prio;
+ int overstrikePrio, tabPrio, tabStylePrio, wrapPrio;
+
+ /*
+ * Find out what tags are present for the character, then compute a
+ * StyleValues structure corresponding to those tags (scan through all of
+ * the tags, saving information for the highest-priority tag).
+ */
+
+ tagPtrs = TkBTreeGetTags(indexPtr, textPtr, &numTags);
+ borderPrio = borderWidthPrio = reliefPrio = bgStipplePrio = -1;
+ fgPrio = fontPrio = fgStipplePrio = -1;
+ underlinePrio = elidePrio = justifyPrio = offsetPrio = -1;
+ lMargin1Prio = lMargin2Prio = rMarginPrio = -1;
+ lMarginColorPrio = rMarginColorPrio = -1;
+ spacing1Prio = spacing2Prio = spacing3Prio = -1;
+ overstrikePrio = tabPrio = tabStylePrio = wrapPrio = -1;
+ memset(&styleValues, 0, sizeof(StyleValues));
+ styleValues.relief = TK_RELIEF_FLAT;
+ styleValues.fgColor = textPtr->fgColor;
+ styleValues.underlineColor = textPtr->fgColor;
+ styleValues.overstrikeColor = textPtr->fgColor;
+ styleValues.tkfont = textPtr->tkfont;
+ styleValues.justify = TK_JUSTIFY_LEFT;
+ styleValues.spacing1 = textPtr->spacing1;
+ styleValues.spacing2 = textPtr->spacing2;
+ styleValues.spacing3 = textPtr->spacing3;
+ styleValues.tabArrayPtr = textPtr->tabArrayPtr;
+ styleValues.tabStyle = textPtr->tabStyle;
+ styleValues.wrapMode = textPtr->wrapMode;
+ styleValues.elide = 0;
+ isSelected = 0;
+
+ for (i = 0 ; i < numTags; i++) {
+ if (textPtr->selTagPtr == tagPtrs[i]) {
+ isSelected = 1;
+ break;
+ }
+ }
+
+ for (i = 0 ; i < numTags; i++) {
+ Tk_3DBorder border;
+ XColor *fgColor;
+
+ tagPtr = tagPtrs[i];
+ border = tagPtr->border;
+ fgColor = tagPtr->fgColor;
+
+ /*
+ * If this is the selection tag, and inactiveSelBorder is NULL (the
+ * default on Windows), then we need to skip it if we don't have the
+ * focus.
+ */
+
+ if ((tagPtr == textPtr->selTagPtr) && !(textPtr->flags & GOT_FOCUS)) {
+ if (textPtr->inactiveSelBorder == NULL
+#ifdef MAC_OSX_TK
+ /* Don't show inactive selection in disabled widgets. */
+ || textPtr->state == TK_TEXT_STATE_DISABLED
+#endif
+ ) {
+ continue;
+ }
+ border = textPtr->inactiveSelBorder;
+ }
+
+ if ((tagPtr->selBorder != NULL) && (isSelected)) {
+ border = tagPtr->selBorder;
+ }
+
+ if ((tagPtr->selFgColor != NULL) && isSelected) {
+ fgColor = tagPtr->selFgColor;
+ }
+
+ if ((border != NULL) && (tagPtr->priority > borderPrio)) {
+ styleValues.border = border;
+ borderPrio = tagPtr->priority;
+ }
+ if ((tagPtr->borderWidthPtr != NULL)
+ && (Tcl_GetString(tagPtr->borderWidthPtr)[0] != '\0')
+ && (tagPtr->priority > borderWidthPrio)) {
+ styleValues.borderWidth = tagPtr->borderWidth;
+ borderWidthPrio = tagPtr->priority;
+ }
+ if ((tagPtr->reliefString != NULL)
+ && (tagPtr->priority > reliefPrio)) {
+ if (styleValues.border == NULL) {
+ styleValues.border = textPtr->border;
+ }
+ styleValues.relief = tagPtr->relief;
+ reliefPrio = tagPtr->priority;
+ }
+ if ((tagPtr->bgStipple != None)
+ && (tagPtr->priority > bgStipplePrio)) {
+ styleValues.bgStipple = tagPtr->bgStipple;
+ bgStipplePrio = tagPtr->priority;
+ }
+ if ((fgColor != NULL) && (tagPtr->priority > fgPrio)) {
+ styleValues.fgColor = fgColor;
+ fgPrio = tagPtr->priority;
+ }
+ if ((tagPtr->tkfont != NULL) && (tagPtr->priority > fontPrio)) {
+ styleValues.tkfont = tagPtr->tkfont;
+ fontPrio = tagPtr->priority;
+ }
+ if ((tagPtr->fgStipple != None)
+ && (tagPtr->priority > fgStipplePrio)) {
+ styleValues.fgStipple = tagPtr->fgStipple;
+ fgStipplePrio = tagPtr->priority;
+ }
+ if ((tagPtr->justifyString != NULL)
+ && (tagPtr->priority > justifyPrio)) {
+ styleValues.justify = tagPtr->justify;
+ justifyPrio = tagPtr->priority;
+ }
+ if ((tagPtr->lMargin1String != NULL)
+ && (tagPtr->priority > lMargin1Prio)) {
+ styleValues.lMargin1 = tagPtr->lMargin1;
+ lMargin1Prio = tagPtr->priority;
+ }
+ if ((tagPtr->lMargin2String != NULL)
+ && (tagPtr->priority > lMargin2Prio)) {
+ styleValues.lMargin2 = tagPtr->lMargin2;
+ lMargin2Prio = tagPtr->priority;
+ }
+ if ((tagPtr->lMarginColor != NULL)
+ && (tagPtr->priority > lMarginColorPrio)) {
+ styleValues.lMarginColor = tagPtr->lMarginColor;
+ lMarginColorPrio = tagPtr->priority;
+ }
+ if ((tagPtr->offsetString != NULL)
+ && (tagPtr->priority > offsetPrio)) {
+ styleValues.offset = tagPtr->offset;
+ offsetPrio = tagPtr->priority;
+ }
+ if ((tagPtr->overstrikeString != NULL)
+ && (tagPtr->priority > overstrikePrio)) {
+ styleValues.overstrike = tagPtr->overstrike;
+ overstrikePrio = tagPtr->priority;
+ if (tagPtr->overstrikeColor != NULL) {
+ styleValues.overstrikeColor = tagPtr->overstrikeColor;
+ } else if (fgColor != NULL) {
+ styleValues.overstrikeColor = fgColor;
+ }
+ }
+ if ((tagPtr->rMarginString != NULL)
+ && (tagPtr->priority > rMarginPrio)) {
+ styleValues.rMargin = tagPtr->rMargin;
+ rMarginPrio = tagPtr->priority;
+ }
+ if ((tagPtr->rMarginColor != NULL)
+ && (tagPtr->priority > rMarginColorPrio)) {
+ styleValues.rMarginColor = tagPtr->rMarginColor;
+ rMarginColorPrio = tagPtr->priority;
+ }
+ if ((tagPtr->spacing1String != NULL)
+ && (tagPtr->priority > spacing1Prio)) {
+ styleValues.spacing1 = tagPtr->spacing1;
+ spacing1Prio = tagPtr->priority;
+ }
+ if ((tagPtr->spacing2String != NULL)
+ && (tagPtr->priority > spacing2Prio)) {
+ styleValues.spacing2 = tagPtr->spacing2;
+ spacing2Prio = tagPtr->priority;
+ }
+ if ((tagPtr->spacing3String != NULL)
+ && (tagPtr->priority > spacing3Prio)) {
+ styleValues.spacing3 = tagPtr->spacing3;
+ spacing3Prio = tagPtr->priority;
+ }
+ if ((tagPtr->tabStringPtr != NULL)
+ && (tagPtr->priority > tabPrio)) {
+ styleValues.tabArrayPtr = tagPtr->tabArrayPtr;
+ tabPrio = tagPtr->priority;
+ }
+ if ((tagPtr->tabStyle != TK_TEXT_TABSTYLE_NONE)
+ && (tagPtr->priority > tabStylePrio)) {
+ styleValues.tabStyle = tagPtr->tabStyle;
+ tabStylePrio = tagPtr->priority;
+ }
+ if ((tagPtr->underlineString != NULL)
+ && (tagPtr->priority > underlinePrio)) {
+ styleValues.underline = tagPtr->underline;
+ underlinePrio = tagPtr->priority;
+ if (tagPtr->underlineColor != NULL) {
+ styleValues.underlineColor = tagPtr->underlineColor;
+ } else if (fgColor != NULL) {
+ styleValues.underlineColor = fgColor;
+ }
+ }
+ if ((tagPtr->elideString != NULL)
+ && (tagPtr->priority > elidePrio)) {
+ styleValues.elide = tagPtr->elide;
+ elidePrio = tagPtr->priority;
+ }
+ if ((tagPtr->wrapMode != TEXT_WRAPMODE_NULL)
+ && (tagPtr->priority > wrapPrio)) {
+ styleValues.wrapMode = tagPtr->wrapMode;
+ wrapPrio = tagPtr->priority;
+ }
+ }
+ if (tagPtrs != NULL) {
+ ckfree(tagPtrs);
+ }
+
+ /*
+ * Use an existing style if there's one around that matches.
+ */
+
+ hPtr = Tcl_CreateHashEntry(&textPtr->dInfoPtr->styleTable,
+ (char *) &styleValues, &isNew);
+ if (!isNew) {
+ stylePtr = Tcl_GetHashValue(hPtr);
+ stylePtr->refCount++;
+ return stylePtr;
+ }
+
+ /*
+ * No existing style matched. Make a new one.
+ */
+
+ stylePtr = ckalloc(sizeof(TextStyle));
+ stylePtr->refCount = 1;
+ if (styleValues.border != NULL) {
+ gcValues.foreground = Tk_3DBorderColor(styleValues.border)->pixel;
+ mask = GCForeground;
+ if (styleValues.bgStipple != None) {
+ gcValues.stipple = styleValues.bgStipple;
+ gcValues.fill_style = FillStippled;
+ mask |= GCStipple|GCFillStyle;
+ }
+ stylePtr->bgGC = Tk_GetGC(textPtr->tkwin, mask, &gcValues);
+ } else {
+ stylePtr->bgGC = NULL;
+ }
+ mask = GCFont;
+ gcValues.font = Tk_FontId(styleValues.tkfont);
+ mask |= GCForeground;
+ gcValues.foreground = styleValues.fgColor->pixel;
+ if (styleValues.fgStipple != None) {
+ gcValues.stipple = styleValues.fgStipple;
+ gcValues.fill_style = FillStippled;
+ mask |= GCStipple|GCFillStyle;
+ }
+ stylePtr->fgGC = Tk_GetGC(textPtr->tkwin, mask, &gcValues);
+ mask = GCForeground;
+ gcValues.foreground = styleValues.underlineColor->pixel;
+ stylePtr->ulGC = Tk_GetGC(textPtr->tkwin, mask, &gcValues);
+ gcValues.foreground = styleValues.overstrikeColor->pixel;
+ stylePtr->ovGC = Tk_GetGC(textPtr->tkwin, mask, &gcValues);
+ stylePtr->sValuePtr = (StyleValues *)
+ Tcl_GetHashKey(&textPtr->dInfoPtr->styleTable, hPtr);
+ stylePtr->hPtr = hPtr;
+ Tcl_SetHashValue(hPtr, stylePtr);
+ return stylePtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeStyle --
+ *
+ * This function is called when a TextStyle structure is no longer
+ * needed. It decrements the reference count and frees up the space for
+ * the style structure if the reference count is 0.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The storage and other resources associated with the style are freed up
+ * if no-one's still using it.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FreeStyle(
+ TkText *textPtr, /* Information about overall widget. */
+ register TextStyle *stylePtr)
+ /* Information about style to free. */
+{
+ stylePtr->refCount--;
+ if (stylePtr->refCount == 0) {
+ if (stylePtr->bgGC != NULL) {
+ Tk_FreeGC(textPtr->display, stylePtr->bgGC);
+ }
+ if (stylePtr->fgGC != NULL) {
+ Tk_FreeGC(textPtr->display, stylePtr->fgGC);
+ }
+ if (stylePtr->ulGC != NULL) {
+ Tk_FreeGC(textPtr->display, stylePtr->ulGC);
+ }
+ if (stylePtr->ovGC != NULL) {
+ Tk_FreeGC(textPtr->display, stylePtr->ovGC);
+ }
+ Tcl_DeleteHashEntry(stylePtr->hPtr);
+ ckfree(stylePtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * LayoutDLine --
+ *
+ * This function generates a single DLine structure for a display line
+ * whose leftmost character is given by indexPtr.
+ *
+ * Results:
+ * The return value is a pointer to a DLine structure describing the
+ * display line. All fields are filled in and correct except for y and
+ * nextPtr.
+ *
+ * Side effects:
+ * Storage is allocated for the new DLine.
+ *
+ * See the comments in 'GetYView' for some thoughts on what the side-
+ * effects of this call (or its callers) should be; the synchronisation
+ * of TkTextLine->pixelHeight with the sum of the results of this
+ * function operating on all display lines within each logical line.
+ * Ideally the code should be refactored to ensure the cached pixel
+ * height is never behind what is known when this function is called
+ * elsewhere.
+ *
+ * Unfortunately, this function is currently called from many different
+ * places, not just to layout a display line for actual display, but also
+ * simply to calculate some metric or other of one or more display lines
+ * (typically the height). It would be a good idea to do some profiling
+ * of typical text widget usage and the way in which this is called and
+ * see if some optimization could or should be done.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static DLine *
+LayoutDLine(
+ TkText *textPtr, /* Overall information about text widget. */
+ const TkTextIndex *indexPtr)/* Beginning of display line. May not
+ * necessarily point to a character
+ * segment. */
+{
+ register DLine *dlPtr; /* New display line. */
+ TkTextSegment *segPtr; /* Current segment in text. */
+ TkTextDispChunk *lastChunkPtr;
+ /* Last chunk allocated so far for line. */
+ TkTextDispChunk *chunkPtr; /* Current chunk. */
+ TkTextIndex curIndex;
+ TkTextDispChunk *breakChunkPtr;
+ /* Chunk containing best word break point, if
+ * any. */
+ TkTextIndex breakIndex; /* Index of first character in
+ * breakChunkPtr. */
+ int breakByteOffset; /* Byte offset of character within
+ * breakChunkPtr just to right of best break
+ * point. */
+ int noCharsYet; /* Non-zero means that no characters have been
+ * placed on the line yet. */
+ int paragraphStart; /* Non-zero means that we are on the first
+ * line of a paragraph (used to choose between
+ * lmargin1, lmargin2). */
+ int justify; /* How to justify line: taken from style for
+ * the first character in line. */
+ int jIndent; /* Additional indentation (beyond margins) due
+ * to justification. */
+ int rMargin; /* Right margin width for line. */
+ TkWrapMode wrapMode; /* Wrap mode to use for this line. */
+ int x = 0, maxX = 0; /* Initializations needed only to stop
+ * compiler warnings. */
+ int wholeLine; /* Non-zero means this display line runs to
+ * the end of the text line. */
+ int tabIndex; /* Index of the current tab stop. */
+ int gotTab; /* Non-zero means the current chunk contains a
+ * tab. */
+ TkTextDispChunk *tabChunkPtr;
+ /* Pointer to the chunk containing the
+ * previous tab stop. */
+ int maxBytes; /* Maximum number of bytes to include in this
+ * chunk. */
+ TkTextTabArray *tabArrayPtr;/* Tab stops for line; taken from style for
+ * the first character on line. */
+ int tabStyle; /* One of TABULAR or WORDPROCESSOR. */
+ int tabSize; /* Number of pixels consumed by current tab
+ * stop. */
+ TkTextDispChunk *lastCharChunkPtr;
+ /* Pointer to last chunk in display lines with
+ * numBytes > 0. Used to drop 0-sized chunks
+ * from the end of the line. */
+ int byteOffset, ascent, descent, code, elide, elidesize;
+ StyleValues *sValuePtr;
+ TkTextElideInfo info; /* Keep track of elide state. */
+
+ /*
+ * Create and initialize a new DLine structure.
+ */
+
+ dlPtr = ckalloc(sizeof(DLine));
+ dlPtr->index = *indexPtr;
+ dlPtr->byteCount = 0;
+ dlPtr->y = 0;
+ dlPtr->oldY = 0; /* Only set to avoid compiler warnings. */
+ dlPtr->height = 0;
+ dlPtr->baseline = 0;
+ dlPtr->chunkPtr = NULL;
+ dlPtr->nextPtr = NULL;
+ dlPtr->flags = NEW_LAYOUT | OLD_Y_INVALID;
+ dlPtr->logicalLinesMerged = 0;
+ dlPtr->lMarginColor = NULL;
+ dlPtr->lMarginWidth = 0;
+ dlPtr->rMarginColor = NULL;
+ dlPtr->rMarginWidth = 0;
+
+ /*
+ * This is not necessarily totally correct, where we have merged logical
+ * lines. Fixing this would require a quite significant overhaul, though,
+ * so currently we make do with this.
+ */
+
+ paragraphStart = (indexPtr->byteIndex == 0);
+
+ /*
+ * Special case entirely elide line as there may be 1000s or more.
+ */
+
+ elide = TkTextIsElided(textPtr, indexPtr, &info);
+ if (elide && indexPtr->byteIndex == 0) {
+ maxBytes = 0;
+ for (segPtr = info.segPtr; segPtr != NULL; segPtr = segPtr->nextPtr) {
+ if (segPtr->size > 0) {
+ if (elide == 0) {
+ /*
+ * We toggled a tag and the elide state changed to
+ * visible, and we have something of non-zero size.
+ * Therefore we must bail out.
+ */
+
+ break;
+ }
+ maxBytes += segPtr->size;
+
+ /*
+ * Reset tag elide priority, since we're on a new character.
+ */
+
+ } else if ((segPtr->typePtr == &tkTextToggleOffType)
+ || (segPtr->typePtr == &tkTextToggleOnType)) {
+ TkTextTag *tagPtr = segPtr->body.toggle.tagPtr;
+
+ /*
+ * The elide state only changes if this tag is either the
+ * current highest priority tag (and is therefore being
+ * toggled off), or it's a new tag with higher priority.
+ */
+
+ if (tagPtr->elideString != NULL) {
+ info.tagCnts[tagPtr->priority]++;
+ if (info.tagCnts[tagPtr->priority] & 1) {
+ info.tagPtrs[tagPtr->priority] = tagPtr;
+ }
+ if (tagPtr->priority >= info.elidePriority) {
+ if (segPtr->typePtr == &tkTextToggleOffType) {
+ /*
+ * If it is being toggled off, and it has an elide
+ * string, it must actually be the current highest
+ * priority tag, so this check is redundant:
+ */
+
+ if (tagPtr->priority != info.elidePriority) {
+ Tcl_Panic("Bad tag priority being toggled off");
+ }
+
+ /*
+ * Find previous elide tag, if any (if not then
+ * elide will be zero, of course).
+ */
+
+ elide = 0;
+ while (--info.elidePriority > 0) {
+ if (info.tagCnts[info.elidePriority] & 1) {
+ elide = info.tagPtrs[info.elidePriority]
+ ->elide;
+ break;
+ }
+ }
+ } else {
+ elide = tagPtr->elide;
+ info.elidePriority = tagPtr->priority;
+ }
+ }
+ }
+ }
+ }
+
+ if (elide) {
+ dlPtr->byteCount = maxBytes;
+ dlPtr->spaceAbove = dlPtr->spaceBelow = dlPtr->length = 0;
+ if (dlPtr->index.byteIndex == 0) {
+ /*
+ * Elided state goes from beginning to end of an entire
+ * logical line. This means we can update the line's pixel
+ * height, and bring its pixel calculation up to date.
+ */
+
+ TkBTreeLinePixelEpoch(textPtr, dlPtr->index.linePtr)
+ = textPtr->dInfoPtr->lineMetricUpdateEpoch;
+
+ if (TkBTreeLinePixelCount(textPtr,dlPtr->index.linePtr) != 0) {
+ TkBTreeAdjustPixelHeight(textPtr,
+ dlPtr->index.linePtr, 0, 0);
+ }
+ }
+ TkTextFreeElideInfo(&info);
+ return dlPtr;
+ }
+ }
+ TkTextFreeElideInfo(&info);
+
+ /*
+ * Each iteration of the loop below creates one TkTextDispChunk for the
+ * new display line. The line will always have at least one chunk (for the
+ * newline character at the end, if there's nothing else available).
+ */
+
+ curIndex = *indexPtr;
+ lastChunkPtr = NULL;
+ chunkPtr = NULL;
+ noCharsYet = 1;
+ elide = 0;
+ breakChunkPtr = NULL;
+ breakByteOffset = 0;
+ justify = TK_JUSTIFY_LEFT;
+ tabIndex = -1;
+ tabChunkPtr = NULL;
+ tabArrayPtr = NULL;
+ tabStyle = TK_TEXT_TABSTYLE_TABULAR;
+ rMargin = 0;
+ wrapMode = TEXT_WRAPMODE_CHAR;
+ tabSize = 0;
+ lastCharChunkPtr = NULL;
+
+ /*
+ * Find the first segment to consider for the line. Can't call
+ * TkTextIndexToSeg for this because it won't return a segment with zero
+ * size (such as the insertion cursor's mark).
+ */
+
+ connectNextLogicalLine:
+ byteOffset = curIndex.byteIndex;
+ segPtr = curIndex.linePtr->segPtr;
+ while ((byteOffset > 0) && (byteOffset >= segPtr->size)) {
+ byteOffset -= segPtr->size;
+ segPtr = segPtr->nextPtr;
+
+ if (segPtr == NULL) {
+ /*
+ * Two logical lines merged into one display line through eliding
+ * of a newline.
+ */
+
+ TkTextLine *linePtr = TkBTreeNextLine(NULL, curIndex.linePtr);
+ if (linePtr == NULL) {
+ break;
+ }
+
+ dlPtr->logicalLinesMerged++;
+ curIndex.byteIndex = 0;
+ curIndex.linePtr = linePtr;
+ segPtr = curIndex.linePtr->segPtr;
+ }
+ }
+
+ while (segPtr != NULL) {
+ /*
+ * Every logical line still gets at least one chunk due to
+ * expectations in the rest of the code, but we are able to skip
+ * elided portions of the line quickly.
+ *
+ * If current chunk is elided and last chunk was too, coalese.
+ *
+ * This also means that each logical line which is entirely elided
+ * still gets laid out into a DLine, but with zero height. This isn't
+ * particularly a problem, but it does seem somewhat unnecessary. We
+ * may wish to redesign the code to remove these zero height DLines in
+ * the future.
+ */
+
+ if (elide && (lastChunkPtr != NULL)
+ && (lastChunkPtr->displayProc == NULL /*ElideDisplayProc*/)) {
+ elidesize = segPtr->size - byteOffset;
+ if (elidesize > 0) {
+ curIndex.byteIndex += elidesize;
+ lastChunkPtr->numBytes += elidesize;
+ breakByteOffset = lastChunkPtr->breakIndex
+ = lastChunkPtr->numBytes;
+
+ /*
+ * If have we have a tag toggle, there is a chance that
+ * invisibility state changed, so bail out.
+ */
+ } else if ((segPtr->typePtr == &tkTextToggleOffType)
+ || (segPtr->typePtr == &tkTextToggleOnType)) {
+ if (segPtr->body.toggle.tagPtr->elideString != NULL) {
+ elide = (segPtr->typePtr == &tkTextToggleOffType)
+ ^ segPtr->body.toggle.tagPtr->elide;
+ }
+ }
+
+ byteOffset = 0;
+ segPtr = segPtr->nextPtr;
+
+ if (segPtr == NULL) {
+ /*
+ * Two logical lines merged into one display line through
+ * eliding of a newline.
+ */
+
+ TkTextLine *linePtr = TkBTreeNextLine(NULL, curIndex.linePtr);
+
+ if (linePtr != NULL) {
+ dlPtr->logicalLinesMerged++;
+ curIndex.byteIndex = 0;
+ curIndex.linePtr = linePtr;
+ goto connectNextLogicalLine;
+ }
+ }
+
+ /*
+ * Code no longer needed, now that we allow logical lines to merge
+ * into a single display line.
+ *
+ if (segPtr == NULL && chunkPtr != NULL) {
+ ckfree(chunkPtr);
+ chunkPtr = NULL;
+ }
+ */
+
+ continue;
+ }
+
+ if (segPtr->typePtr->layoutProc == NULL) {
+ segPtr = segPtr->nextPtr;
+ byteOffset = 0;
+ continue;
+ }
+ if (chunkPtr == NULL) {
+ chunkPtr = ckalloc(sizeof(TkTextDispChunk));
+ chunkPtr->nextPtr = NULL;
+ chunkPtr->clientData = NULL;
+ }
+ chunkPtr->stylePtr = GetStyle(textPtr, &curIndex);
+ elide = chunkPtr->stylePtr->sValuePtr->elide;
+
+ /*
+ * Save style information such as justification and indentation, up
+ * until the first character is encountered, then retain that
+ * information for the rest of the line.
+ */
+
+ if (!elide && noCharsYet) {
+ tabArrayPtr = chunkPtr->stylePtr->sValuePtr->tabArrayPtr;
+ tabStyle = chunkPtr->stylePtr->sValuePtr->tabStyle;
+ justify = chunkPtr->stylePtr->sValuePtr->justify;
+ rMargin = chunkPtr->stylePtr->sValuePtr->rMargin;
+ wrapMode = chunkPtr->stylePtr->sValuePtr->wrapMode;
+
+ /*
+ * See above - this test may not be entirely correct where we have
+ * partially elided lines (and therefore merged logical lines).
+ * In such a case a byteIndex of zero doesn't necessarily mean the
+ * beginning of a logical line.
+ */
+
+ if (paragraphStart) {
+ /*
+ * Beginning of logical line.
+ */
+
+ x = chunkPtr->stylePtr->sValuePtr->lMargin1;
+ } else {
+ /*
+ * Beginning of display line.
+ */
+
+ x = chunkPtr->stylePtr->sValuePtr->lMargin2;
+ }
+ dlPtr->lMarginWidth = x;
+ if (wrapMode == TEXT_WRAPMODE_NONE) {
+ maxX = -1;
+ } else {
+ maxX = textPtr->dInfoPtr->maxX - textPtr->dInfoPtr->x
+ - rMargin;
+ if (maxX < x) {
+ maxX = x;
+ }
+ }
+ }
+
+ gotTab = 0;
+ maxBytes = segPtr->size - byteOffset;
+ if (segPtr->typePtr == &tkTextCharType) {
+
+ /*
+ * See if there is a tab in the current chunk; if so, only layout
+ * characters up to (and including) the tab.
+ */
+
+ if (!elide && justify == TK_JUSTIFY_LEFT) {
+ char *p;
+
+ for (p = segPtr->body.chars + byteOffset; *p != 0; p++) {
+ if (*p == '\t') {
+ maxBytes = (p + 1 - segPtr->body.chars) - byteOffset;
+ gotTab = 1;
+ break;
+ }
+ }
+ }
+
+#if TK_LAYOUT_WITH_BASE_CHUNKS
+ if (baseCharChunkPtr != NULL) {
+ int expectedX =
+ ((BaseCharInfo *) baseCharChunkPtr->clientData)->width
+ + baseCharChunkPtr->x;
+
+ if ((expectedX != x) || !IsSameFGStyle(
+ baseCharChunkPtr->stylePtr, chunkPtr->stylePtr)) {
+ FinalizeBaseChunk(NULL);
+ }
+ }
+#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */
+ }
+ chunkPtr->x = x;
+ if (elide /*&& maxBytes*/) {
+ /*
+ * Don't free style here, as other code expects to be able to do
+ * that.
+ */
+
+ /* breakByteOffset =*/
+ chunkPtr->breakIndex = chunkPtr->numBytes = maxBytes;
+ chunkPtr->width = 0;
+ chunkPtr->minAscent = chunkPtr->minDescent
+ = chunkPtr->minHeight = 0;
+
+ /*
+ * Would just like to point to canonical empty chunk.
+ */
+
+ chunkPtr->displayProc = NULL;
+ chunkPtr->undisplayProc = NULL;
+ chunkPtr->measureProc = ElideMeasureProc;
+ chunkPtr->bboxProc = ElideBboxProc;
+
+ code = 1;
+ } else {
+ code = segPtr->typePtr->layoutProc(textPtr, &curIndex, segPtr,
+ byteOffset, maxX-tabSize, maxBytes, noCharsYet, wrapMode,
+ chunkPtr);
+ }
+ if (code <= 0) {
+ FreeStyle(textPtr, chunkPtr->stylePtr);
+ if (code < 0) {
+ /*
+ * This segment doesn't wish to display itself (e.g. most
+ * marks).
+ */
+
+ segPtr = segPtr->nextPtr;
+ byteOffset = 0;
+ continue;
+ }
+
+ /*
+ * No characters from this segment fit in the window: this means
+ * we're at the end of the display line.
+ */
+
+ if (chunkPtr != NULL) {
+ ckfree(chunkPtr);
+ }
+ break;
+ }
+
+ /*
+ * We currently say we have some characters (and therefore something
+ * from which to examine tag values for the first character of the
+ * line) even if those characters are actually elided. This behaviour
+ * is not well documented, and it might be more consistent to
+ * completely ignore such elided characters and their tags. To do so
+ * change this to:
+ *
+ * if (!elide && chunkPtr->numBytes > 0).
+ */
+
+ if (!elide && chunkPtr->numBytes > 0) {
+ noCharsYet = 0;
+ lastCharChunkPtr = chunkPtr;
+ }
+ if (lastChunkPtr == NULL) {
+ dlPtr->chunkPtr = chunkPtr;
+ } else {
+ lastChunkPtr->nextPtr = chunkPtr;
+ }
+ lastChunkPtr = chunkPtr;
+ x += chunkPtr->width;
+ if (chunkPtr->breakIndex > 0) {
+ breakByteOffset = chunkPtr->breakIndex;
+ breakIndex = curIndex;
+ breakChunkPtr = chunkPtr;
+ }
+ if (chunkPtr->numBytes != maxBytes) {
+ break;
+ }
+
+ /*
+ * If we're at a new tab, adjust the layout for all the chunks
+ * pertaining to the previous tab. Also adjust the amount of space
+ * left in the line to account for space that will be eaten up by the
+ * tab.
+ */
+
+ if (gotTab) {
+ if (tabIndex >= 0) {
+ AdjustForTab(textPtr, tabArrayPtr, tabIndex, tabChunkPtr);
+ x = chunkPtr->x + chunkPtr->width;
+ }
+ tabChunkPtr = chunkPtr;
+ tabSize = SizeOfTab(textPtr, tabStyle, tabArrayPtr, &tabIndex, x,
+ maxX);
+ if ((maxX >= 0) && (tabSize >= maxX - x)) {
+ break;
+ }
+ }
+ curIndex.byteIndex += chunkPtr->numBytes;
+ byteOffset += chunkPtr->numBytes;
+ if (byteOffset >= segPtr->size) {
+ byteOffset = 0;
+ segPtr = segPtr->nextPtr;
+ if (elide && segPtr == NULL) {
+ /*
+ * An elided section started on this line, and carries on
+ * until the newline. Hence the newline is actually elided,
+ * and we want to merge the display of the next logical line
+ * with this one.
+ */
+
+ TkTextLine *linePtr = TkBTreeNextLine(NULL, curIndex.linePtr);
+
+ if (linePtr != NULL) {
+ dlPtr->logicalLinesMerged++;
+ curIndex.byteIndex = 0;
+ curIndex.linePtr = linePtr;
+ chunkPtr = NULL;
+ goto connectNextLogicalLine;
+ }
+ }
+ }
+
+ chunkPtr = NULL;
+ }
+#if TK_LAYOUT_WITH_BASE_CHUNKS
+ FinalizeBaseChunk(NULL);
+#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */
+ if (noCharsYet) {
+ dlPtr->spaceAbove = 0;
+ dlPtr->spaceBelow = 0;
+ dlPtr->length = 0;
+
+ /*
+ * We used to Tcl_Panic here, saying that LayoutDLine couldn't place
+ * any characters on a line, but I believe a more appropriate response
+ * is to return a DLine with zero height. With elided lines, tag
+ * transitions and asynchronous line height calculations, it is hard
+ * to avoid this situation ever arising with the current code design.
+ */
+
+ return dlPtr;
+ }
+ wholeLine = (segPtr == NULL);
+
+ /*
+ * We're at the end of the display line. Throw away everything after the
+ * most recent word break, if there is one; this may potentially require
+ * the last chunk to be layed out again.
+ */
+
+ if (breakChunkPtr == NULL) {
+ /*
+ * This code makes sure that we don't accidentally display chunks with
+ * no characters at the end of the line (such as the insertion
+ * cursor). These chunks belong on the next line. So, throw away
+ * everything after the last chunk that has characters in it.
+ */
+
+ breakChunkPtr = lastCharChunkPtr;
+ breakByteOffset = breakChunkPtr->numBytes;
+ }
+ if ((breakChunkPtr != NULL) && ((lastChunkPtr != breakChunkPtr)
+ || (breakByteOffset != lastChunkPtr->numBytes))) {
+ while (1) {
+ chunkPtr = breakChunkPtr->nextPtr;
+ if (chunkPtr == NULL) {
+ break;
+ }
+ FreeStyle(textPtr, chunkPtr->stylePtr);
+ breakChunkPtr->nextPtr = chunkPtr->nextPtr;
+ if (chunkPtr->undisplayProc != NULL) {
+ chunkPtr->undisplayProc(textPtr, chunkPtr);
+ }
+ ckfree(chunkPtr);
+ }
+ if (breakByteOffset != breakChunkPtr->numBytes) {
+ if (breakChunkPtr->undisplayProc != NULL) {
+ breakChunkPtr->undisplayProc(textPtr, breakChunkPtr);
+ }
+ segPtr = TkTextIndexToSeg(&breakIndex, &byteOffset);
+ segPtr->typePtr->layoutProc(textPtr, &breakIndex, segPtr,
+ byteOffset, maxX, breakByteOffset, 0, wrapMode,
+ breakChunkPtr);
+#if TK_LAYOUT_WITH_BASE_CHUNKS
+ FinalizeBaseChunk(NULL);
+#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */
+ }
+ lastChunkPtr = breakChunkPtr;
+ wholeLine = 0;
+ }
+
+ /*
+ * Make tab adjustments for the last tab stop, if there is one.
+ */
+
+ if ((tabIndex >= 0) && (tabChunkPtr != NULL)) {
+ AdjustForTab(textPtr, tabArrayPtr, tabIndex, tabChunkPtr);
+ }
+
+ /*
+ * Make one more pass over the line to recompute various things like its
+ * height, length, and total number of bytes. Also modify the x-locations
+ * of chunks to reflect justification. If we're not wrapping, I'm not sure
+ * what is the best way to handle right and center justification: should
+ * the total length, for purposes of justification, be (a) the window
+ * width, (b) the length of the longest line in the window, or (c) the
+ * length of the longest line in the text? (c) isn't available, (b) seems
+ * weird, since it can change with vertical scrolling, so (a) is what is
+ * implemented below.
+ */
+
+ if (wrapMode == TEXT_WRAPMODE_NONE) {
+ maxX = textPtr->dInfoPtr->maxX - textPtr->dInfoPtr->x - rMargin;
+ }
+ dlPtr->length = lastChunkPtr->x + lastChunkPtr->width;
+ if (justify == TK_JUSTIFY_LEFT) {
+ jIndent = 0;
+ } else if (justify == TK_JUSTIFY_RIGHT) {
+ jIndent = maxX - dlPtr->length;
+ } else {
+ jIndent = (maxX - dlPtr->length)/2;
+ }
+ ascent = descent = 0;
+ for (chunkPtr = dlPtr->chunkPtr; chunkPtr != NULL;
+ chunkPtr = chunkPtr->nextPtr) {
+ chunkPtr->x += jIndent;
+ dlPtr->byteCount += chunkPtr->numBytes;
+ if (chunkPtr->minAscent > ascent) {
+ ascent = chunkPtr->minAscent;
+ }
+ if (chunkPtr->minDescent > descent) {
+ descent = chunkPtr->minDescent;
+ }
+ if (chunkPtr->minHeight > dlPtr->height) {
+ dlPtr->height = chunkPtr->minHeight;
+ }
+ sValuePtr = chunkPtr->stylePtr->sValuePtr;
+ if ((sValuePtr->borderWidth > 0)
+ && (sValuePtr->relief != TK_RELIEF_FLAT)) {
+ dlPtr->flags |= HAS_3D_BORDER;
+ }
+ }
+ if (dlPtr->height < (ascent + descent)) {
+ dlPtr->height = ascent + descent;
+ dlPtr->baseline = ascent;
+ } else {
+ dlPtr->baseline = ascent + (dlPtr->height - ascent - descent)/2;
+ }
+ sValuePtr = dlPtr->chunkPtr->stylePtr->sValuePtr;
+ if (dlPtr->index.byteIndex == 0) {
+ dlPtr->spaceAbove = sValuePtr->spacing1;
+ } else {
+ dlPtr->spaceAbove = sValuePtr->spacing2 - sValuePtr->spacing2/2;
+ }
+ if (wholeLine) {
+ dlPtr->spaceBelow = sValuePtr->spacing3;
+ } else {
+ dlPtr->spaceBelow = sValuePtr->spacing2/2;
+ }
+ dlPtr->height += dlPtr->spaceAbove + dlPtr->spaceBelow;
+ dlPtr->baseline += dlPtr->spaceAbove;
+ dlPtr->lMarginColor = sValuePtr->lMarginColor;
+ dlPtr->rMarginColor = sValuePtr->rMarginColor;
+ if (wrapMode != TEXT_WRAPMODE_NONE) {
+ dlPtr->rMarginWidth = rMargin;
+ }
+
+ /*
+ * Recompute line length: may have changed because of justification.
+ */
+
+ dlPtr->length = lastChunkPtr->x + lastChunkPtr->width;
+
+ return dlPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UpdateDisplayInfo --
+ *
+ * This function is invoked to recompute some or all of the DLine
+ * structures for a text widget. At the time it is called the DLine
+ * structures still left in the widget are guaranteed to be correct
+ * except that (a) the y-coordinates aren't necessarily correct, (b)
+ * there may be missing structures (the DLine structures get removed as
+ * soon as they are potentially out-of-date), and (c) DLine structures
+ * that don't start at the beginning of a line may be incorrect if
+ * previous information in the same line changed size in a way that moved
+ * a line boundary (DLines for any info that changed will have been
+ * deleted, but not DLines for unchanged info in the same text line).
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Upon return, the DLine information for textPtr correctly reflects the
+ * positions where characters will be displayed. However, this function
+ * doesn't actually bring the display up-to-date.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UpdateDisplayInfo(
+ TkText *textPtr) /* Text widget to update. */
+{
+ register TextDInfo *dInfoPtr = textPtr->dInfoPtr;
+ register DLine *dlPtr, *prevPtr;
+ TkTextIndex index;
+ TkTextLine *lastLinePtr;
+ int y, maxY, xPixelOffset, maxOffset, lineHeight;
+
+ if (!(dInfoPtr->flags & DINFO_OUT_OF_DATE)) {
+ return;
+ }
+ dInfoPtr->flags &= ~DINFO_OUT_OF_DATE;
+
+ /*
+ * Delete any DLines that are now above the top of the window.
+ */
+
+ index = textPtr->topIndex;
+ dlPtr = FindDLine(textPtr, dInfoPtr->dLinePtr, &index);
+ if ((dlPtr != NULL) && (dlPtr != dInfoPtr->dLinePtr)) {
+ FreeDLines(textPtr, dInfoPtr->dLinePtr, dlPtr, DLINE_UNLINK);
+ }
+ if (index.byteIndex == 0) {
+ lineHeight = 0;
+ } else {
+ lineHeight = -1;
+ }
+
+ /*
+ * Scan through the contents of the window from top to bottom, recomputing
+ * information for lines that are missing.
+ */
+
+ lastLinePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, textPtr,
+ TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr));
+ dlPtr = dInfoPtr->dLinePtr;
+ prevPtr = NULL;
+ y = dInfoPtr->y - dInfoPtr->newTopPixelOffset;
+ maxY = dInfoPtr->maxY;
+ while (1) {
+ register DLine *newPtr;
+
+ if (index.linePtr == lastLinePtr) {
+ break;
+ }
+
+ /*
+ * There are three possibilities right now:
+ * (a) the next DLine (dlPtr) corresponds exactly to the next
+ * information we want to display: just use it as-is.
+ * (b) the next DLine corresponds to a different line, or to a segment
+ * that will be coming later in the same line: leave this DLine
+ * alone in the hopes that we'll be able to use it later, then
+ * create a new DLine in front of it.
+ * (c) the next DLine corresponds to a segment in the line we want,
+ * but it's a segment that has already been processed or will
+ * never be processed. Delete the DLine and try again.
+ *
+ * One other twist on all this. It's possible for 3D borders to
+ * interact between lines (see DisplayLineBackground) so if a line is
+ * relayed out and has styles with 3D borders, its neighbors have to
+ * be redrawn if they have 3D borders too, since the interactions
+ * could have changed (the neighbors don't have to be relayed out,
+ * just redrawn).
+ */
+
+ if ((dlPtr == NULL) || (dlPtr->index.linePtr != index.linePtr)) {
+ /*
+ * Case (b) -- must make new DLine.
+ */
+
+ makeNewDLine:
+ if (tkTextDebug) {
+ char string[TK_POS_CHARS];
+
+ /*
+ * Debugging is enabled, so keep a log of all the lines that
+ * were re-layed out. The test suite uses this information.
+ */
+
+ TkTextPrintIndex(textPtr, &index, string);
+ LOG("tk_textRelayout", string);
+ }
+ newPtr = LayoutDLine(textPtr, &index);
+ if (prevPtr == NULL) {
+ dInfoPtr->dLinePtr = newPtr;
+ } else {
+ prevPtr->nextPtr = newPtr;
+ if (prevPtr->flags & HAS_3D_BORDER) {
+ prevPtr->flags |= OLD_Y_INVALID;
+ }
+ }
+ newPtr->nextPtr = dlPtr;
+ dlPtr = newPtr;
+ } else {
+ /*
+ * DlPtr refers to the line we want. Next check the index within
+ * the line.
+ */
+
+ if (index.byteIndex == dlPtr->index.byteIndex) {
+ /*
+ * Case (a) - can use existing display line as-is.
+ */
+
+ if ((dlPtr->flags & HAS_3D_BORDER) && (prevPtr != NULL)
+ && (prevPtr->flags & (NEW_LAYOUT))) {
+ dlPtr->flags |= OLD_Y_INVALID;
+ }
+ goto lineOK;
+ }
+ if (index.byteIndex < dlPtr->index.byteIndex) {
+ goto makeNewDLine;
+ }
+
+ /*
+ * Case (c) - dlPtr is useless. Discard it and start again with
+ * the next display line.
+ */
+
+ newPtr = dlPtr->nextPtr;
+ FreeDLines(textPtr, dlPtr, newPtr, DLINE_FREE);
+ dlPtr = newPtr;
+ if (prevPtr != NULL) {
+ prevPtr->nextPtr = newPtr;
+ } else {
+ dInfoPtr->dLinePtr = newPtr;
+ }
+ continue;
+ }
+
+ /*
+ * Advance to the start of the next line.
+ */
+
+ lineOK:
+ dlPtr->y = y;
+ y += dlPtr->height;
+ if (lineHeight != -1) {
+ lineHeight += dlPtr->height;
+ }
+ TkTextIndexForwBytes(textPtr, &index, dlPtr->byteCount, &index);
+ prevPtr = dlPtr;
+ dlPtr = dlPtr->nextPtr;
+
+ /*
+ * If we switched text lines, delete any DLines left for the old text
+ * line.
+ */
+
+ if (index.linePtr != prevPtr->index.linePtr) {
+ register DLine *nextPtr;
+
+ nextPtr = dlPtr;
+ while ((nextPtr != NULL)
+ && (nextPtr->index.linePtr == prevPtr->index.linePtr)) {
+ nextPtr = nextPtr->nextPtr;
+ }
+ if (nextPtr != dlPtr) {
+ FreeDLines(textPtr, dlPtr, nextPtr, DLINE_FREE);
+ prevPtr->nextPtr = nextPtr;
+ dlPtr = nextPtr;
+ }
+
+ if ((lineHeight != -1) && (TkBTreeLinePixelCount(textPtr,
+ prevPtr->index.linePtr) != lineHeight)) {
+ /*
+ * The logical line height we just calculated is actually
+ * different to the currently cached height of the text line.
+ * That is fine (the text line heights are only calculated
+ * asynchronously), but we must update the cached height so
+ * that any counts made with DLine pointers are the same as
+ * counts made through the BTree. This helps to ensure that
+ * the scrollbar size corresponds accurately to that displayed
+ * contents, even as the window is re-sized.
+ */
+
+ TkBTreeAdjustPixelHeight(textPtr, prevPtr->index.linePtr,
+ lineHeight, 0);
+
+ /*
+ * I believe we can be 100% sure that we started at the
+ * beginning of the logical line, so we can also adjust the
+ * 'pixelCalculationEpoch' to mark it as being up to date.
+ * There is a slight concern that we might not have got this
+ * right for the first line in the re-display.
+ */
+
+ TkBTreeLinePixelEpoch(textPtr, prevPtr->index.linePtr) =
+ dInfoPtr->lineMetricUpdateEpoch;
+ }
+ lineHeight = 0;
+ }
+
+ /*
+ * It's important to have the following check here rather than in the
+ * while statement for the loop, so that there's always at least one
+ * DLine generated, regardless of how small the window is. This keeps
+ * a lot of other code from breaking.
+ */
+
+ if (y >= maxY) {
+ break;
+ }
+ }
+
+ /*
+ * Delete any DLine structures that don't fit on the screen.
+ */
+
+ FreeDLines(textPtr, dlPtr, NULL, DLINE_UNLINK);
+
+ /*
+ * If there is extra space at the bottom of the window (because we've hit
+ * the end of the text), then bring in more lines at the top of the
+ * window, if there are any, to fill in the view.
+ *
+ * Since the top line may only be partially visible, we try first to
+ * simply show more pixels from that line (newTopPixelOffset). If that
+ * isn't enough, we have to layout more lines.
+ */
+
+ if (y < maxY) {
+ /*
+ * This counts how many vertical pixels we have left to fill by
+ * pulling in more display pixels either from the first currently
+ * displayed, or the lines above it.
+ */
+
+ int spaceLeft = maxY - y;
+
+ if (spaceLeft <= dInfoPtr->newTopPixelOffset) {
+ /*
+ * We can fill up all the needed space just by showing more of the
+ * current top line.
+ */
+
+ dInfoPtr->newTopPixelOffset -= spaceLeft;
+ y += spaceLeft;
+ spaceLeft = 0;
+ } else {
+ int lineNum, bytesToCount;
+ DLine *lowestPtr;
+
+ /*
+ * Add in all of the current top line, which won't be enough to
+ * bring y up to maxY (if it was we would be in the 'if' block
+ * above).
+ */
+
+ y += dInfoPtr->newTopPixelOffset;
+ dInfoPtr->newTopPixelOffset = 0;
+
+ /*
+ * Layout an entire text line (potentially > 1 display line), then
+ * link in as many display lines as fit without moving the bottom
+ * line out of the window. Repeat this until all the extra space
+ * has been used up or we've reached the beginning of the text.
+ */
+
+ spaceLeft = maxY - y;
+ if (dInfoPtr->dLinePtr == NULL) {
+ /*
+ * No lines have been laid out. This must be an empty peer
+ * widget.
+ */
+
+ lineNum = TkBTreeNumLines(textPtr->sharedTextPtr->tree,
+ textPtr) - 1;
+ bytesToCount = INT_MAX;
+ } else {
+ lineNum = TkBTreeLinesTo(textPtr,
+ dInfoPtr->dLinePtr->index.linePtr);
+ bytesToCount = dInfoPtr->dLinePtr->index.byteIndex;
+ if (bytesToCount == 0) {
+ bytesToCount = INT_MAX;
+ lineNum--;
+ }
+ }
+ for ( ; (lineNum >= 0) && (spaceLeft > 0); lineNum--) {
+ int pixelHeight = 0;
+
+ index.linePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree,
+ textPtr, lineNum);
+ index.byteIndex = 0;
+ lowestPtr = NULL;
+
+ do {
+ dlPtr = LayoutDLine(textPtr, &index);
+ pixelHeight += dlPtr->height;
+ dlPtr->nextPtr = lowestPtr;
+ lowestPtr = dlPtr;
+ if (dlPtr->length == 0 && dlPtr->height == 0) {
+ bytesToCount--;
+ break;
+ } /* elide */
+ TkTextIndexForwBytes(textPtr, &index, dlPtr->byteCount,
+ &index);
+ bytesToCount -= dlPtr->byteCount;
+ } while ((bytesToCount > 0)
+ && (index.linePtr == lowestPtr->index.linePtr));
+
+ /*
+ * We may not have examined the entire line (depending on the
+ * value of 'bytesToCount', so we only want to set this if it
+ * is genuinely bigger).
+ */
+
+ if (pixelHeight > TkBTreeLinePixelCount(textPtr,
+ lowestPtr->index.linePtr)) {
+ TkBTreeAdjustPixelHeight(textPtr,
+ lowestPtr->index.linePtr, pixelHeight, 0);
+ if (index.linePtr != lowestPtr->index.linePtr) {
+ /*
+ * We examined the entire line, so can update the
+ * epoch.
+ */
+
+ TkBTreeLinePixelEpoch(textPtr,
+ lowestPtr->index.linePtr) =
+ dInfoPtr->lineMetricUpdateEpoch;
+ }
+ }
+
+ /*
+ * Scan through the display lines from the bottom one up to
+ * the top one.
+ */
+
+ while (lowestPtr != NULL) {
+ dlPtr = lowestPtr;
+ spaceLeft -= dlPtr->height;
+ lowestPtr = dlPtr->nextPtr;
+ dlPtr->nextPtr = dInfoPtr->dLinePtr;
+ dInfoPtr->dLinePtr = dlPtr;
+ if (tkTextDebug) {
+ char string[TK_POS_CHARS];
+
+ TkTextPrintIndex(textPtr, &dlPtr->index, string);
+ LOG("tk_textRelayout", string);
+ }
+ if (spaceLeft <= 0) {
+ break;
+ }
+ }
+ FreeDLines(textPtr, lowestPtr, NULL, DLINE_FREE);
+ bytesToCount = INT_MAX;
+ }
+
+ /*
+ * We've either filled in the space we wanted to or we've run out
+ * of display lines at the top of the text. Note that we already
+ * set dInfoPtr->newTopPixelOffset to zero above.
+ */
+
+ if (spaceLeft < 0) {
+ /*
+ * We've laid out a few too many vertical pixels at or above
+ * the first line. Therefore we only want to show part of the
+ * first displayed line, so that the last displayed line just
+ * fits in the window.
+ */
+
+ dInfoPtr->newTopPixelOffset = -spaceLeft;
+ if (dInfoPtr->newTopPixelOffset>=dInfoPtr->dLinePtr->height) {
+ /*
+ * Somehow the entire first line we laid out is shorter
+ * than the new offset. This should not occur and would
+ * indicate a bad problem in the logic above.
+ */
+
+ Tcl_Panic("Error in pixel height consistency while filling in spacesLeft");
+ }
+ }
+ }
+
+ /*
+ * Now we're all done except that the y-coordinates in all the DLines
+ * are wrong and the top index for the text is wrong. Update them.
+ */
+
+ if (dInfoPtr->dLinePtr != NULL) {
+ textPtr->topIndex = dInfoPtr->dLinePtr->index;
+ y = dInfoPtr->y - dInfoPtr->newTopPixelOffset;
+ for (dlPtr = dInfoPtr->dLinePtr; dlPtr != NULL;
+ dlPtr = dlPtr->nextPtr) {
+ if (y > dInfoPtr->maxY) {
+ Tcl_Panic("Added too many new lines in UpdateDisplayInfo");
+ }
+ dlPtr->y = y;
+ y += dlPtr->height;
+ }
+ }
+ }
+
+ /*
+ * If the old top or bottom line has scrolled elsewhere on the screen, we
+ * may not be able to re-use its old contents by copying bits (e.g., a
+ * beveled edge that was drawn when it was at the top or bottom won't be
+ * drawn when the line is in the middle and its neighbor has a matching
+ * background). Similarly, if the new top or bottom line came from
+ * somewhere else on the screen, we may not be able to copy the old bits.
+ */
+
+ dlPtr = dInfoPtr->dLinePtr;
+ if (dlPtr != NULL) {
+ if ((dlPtr->flags & HAS_3D_BORDER) && !(dlPtr->flags & TOP_LINE)) {
+ dlPtr->flags |= OLD_Y_INVALID;
+ }
+ while (1) {
+ if ((dlPtr->flags & TOP_LINE) && (dlPtr != dInfoPtr->dLinePtr)
+ && (dlPtr->flags & HAS_3D_BORDER)) {
+ dlPtr->flags |= OLD_Y_INVALID;
+ }
+
+ /*
+ * If the old top-line was not completely showing (i.e. the
+ * pixelOffset is non-zero) and is no longer the top-line, then we
+ * must re-draw it.
+ */
+
+ if ((dlPtr->flags & TOP_LINE) &&
+ dInfoPtr->topPixelOffset!=0 && dlPtr!=dInfoPtr->dLinePtr) {
+ dlPtr->flags |= OLD_Y_INVALID;
+ }
+ if ((dlPtr->flags & BOTTOM_LINE) && (dlPtr->nextPtr != NULL)
+ && (dlPtr->flags & HAS_3D_BORDER)) {
+ dlPtr->flags |= OLD_Y_INVALID;
+ }
+ if (dlPtr->nextPtr == NULL) {
+ if ((dlPtr->flags & HAS_3D_BORDER)
+ && !(dlPtr->flags & BOTTOM_LINE)) {
+ dlPtr->flags |= OLD_Y_INVALID;
+ }
+ dlPtr->flags &= ~TOP_LINE;
+ dlPtr->flags |= BOTTOM_LINE;
+ break;
+ }
+ dlPtr->flags &= ~(TOP_LINE|BOTTOM_LINE);
+ dlPtr = dlPtr->nextPtr;
+ }
+ dInfoPtr->dLinePtr->flags |= TOP_LINE;
+ dInfoPtr->topPixelOffset = dInfoPtr->newTopPixelOffset;
+ }
+
+ /*
+ * Arrange for scrollbars to be updated.
+ */
+
+ textPtr->flags |= UPDATE_SCROLLBARS;
+
+ /*
+ * Deal with horizontal scrolling:
+ * 1. If there's empty space to the right of the longest line, shift the
+ * screen to the right to fill in the empty space.
+ * 2. If the desired horizontal scroll position has changed, force a full
+ * redisplay of all the lines in the widget.
+ * 3. If the wrap mode isn't "none" then re-scroll to the base position.
+ */
+
+ dInfoPtr->maxLength = 0;
+ for (dlPtr = dInfoPtr->dLinePtr; dlPtr != NULL;
+ dlPtr = dlPtr->nextPtr) {
+ if (dlPtr->length > dInfoPtr->maxLength) {
+ dInfoPtr->maxLength = dlPtr->length;
+ }
+ }
+ maxOffset = dInfoPtr->maxLength - (dInfoPtr->maxX - dInfoPtr->x);
+
+ xPixelOffset = dInfoPtr->newXPixelOffset;
+ if (xPixelOffset > maxOffset) {
+ xPixelOffset = maxOffset;
+ }
+ if (xPixelOffset < 0) {
+ xPixelOffset = 0;
+ }
+
+ /*
+ * Here's a problem: see the tests textDisp-29.2.1-4
+ *
+ * If the widget is being created, but has not yet been configured it will
+ * have a maxY of 1 above, and we won't have examined all the lines
+ * (just the first line, in fact), and so maxOffset will not be a true
+ * reflection of the widget's lines. Therefore we must not overwrite the
+ * original newXPixelOffset in this case.
+ */
+
+ if (!(((Tk_FakeWin *) (textPtr->tkwin))->flags & TK_NEED_CONFIG_NOTIFY)) {
+ dInfoPtr->newXPixelOffset = xPixelOffset;
+ }
+
+ if (xPixelOffset != dInfoPtr->curXPixelOffset) {
+ dInfoPtr->curXPixelOffset = xPixelOffset;
+ for (dlPtr = dInfoPtr->dLinePtr; dlPtr != NULL;
+ dlPtr = dlPtr->nextPtr) {
+ dlPtr->flags |= OLD_Y_INVALID;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeDLines --
+ *
+ * This function is called to free up all of the resources associated
+ * with one or more DLine structures.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory gets freed and various other resources are released.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FreeDLines(
+ TkText *textPtr, /* Information about overall text widget. */
+ register DLine *firstPtr, /* Pointer to first DLine to free up. */
+ DLine *lastPtr, /* Pointer to DLine just after last one to
+ * free (NULL means everything starting with
+ * firstPtr). */
+ int action) /* DLINE_UNLINK means DLines are currently
+ * linked into the list rooted at
+ * textPtr->dInfoPtr->dLinePtr and they have
+ * to be unlinked. DLINE_FREE means just free
+ * without unlinking. DLINE_FREE_TEMP means
+ * the DLine given is just a temporary one and
+ * we shouldn't invalidate anything for the
+ * overall widget. */
+{
+ register TkTextDispChunk *chunkPtr, *nextChunkPtr;
+ register DLine *nextDLinePtr;
+
+ if (action == DLINE_FREE_TEMP) {
+ lineHeightsRecalculated++;
+ if (tkTextDebug) {
+ char string[TK_POS_CHARS];
+
+ /*
+ * Debugging is enabled, so keep a log of all the lines whose
+ * height was recalculated. The test suite uses this information.
+ */
+
+ TkTextPrintIndex(textPtr, &firstPtr->index, string);
+ LOG("tk_textHeightCalc", string);
+ }
+ } else if (action == DLINE_UNLINK) {
+ if (textPtr->dInfoPtr->dLinePtr == firstPtr) {
+ textPtr->dInfoPtr->dLinePtr = lastPtr;
+ } else {
+ register DLine *prevPtr;
+
+ for (prevPtr = textPtr->dInfoPtr->dLinePtr;
+ prevPtr->nextPtr != firstPtr; prevPtr = prevPtr->nextPtr) {
+ /* Empty loop body. */
+ }
+ prevPtr->nextPtr = lastPtr;
+ }
+ }
+ while (firstPtr != lastPtr) {
+ nextDLinePtr = firstPtr->nextPtr;
+ for (chunkPtr = firstPtr->chunkPtr; chunkPtr != NULL;
+ chunkPtr = nextChunkPtr) {
+ if (chunkPtr->undisplayProc != NULL) {
+ chunkPtr->undisplayProc(textPtr, chunkPtr);
+ }
+ FreeStyle(textPtr, chunkPtr->stylePtr);
+ nextChunkPtr = chunkPtr->nextPtr;
+ ckfree(chunkPtr);
+ }
+ ckfree(firstPtr);
+ firstPtr = nextDLinePtr;
+ }
+ if (action != DLINE_FREE_TEMP) {
+ textPtr->dInfoPtr->dLinesInvalidated = 1;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DisplayDLine --
+ *
+ * This function is invoked to draw a single line on the screen.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The line given by dlPtr is drawn at its correct position in textPtr's
+ * window. Note that this is one *display* line, not one *text* line.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DisplayDLine(
+ TkText *textPtr, /* Text widget in which to draw line. */
+ register DLine *dlPtr, /* Information about line to draw. */
+ DLine *prevPtr, /* Line just before one to draw, or NULL if
+ * dlPtr is the top line. */
+ Pixmap pixmap) /* Pixmap to use for double-buffering. Caller
+ * must make sure it's large enough to hold
+ * line. */
+{
+ register TkTextDispChunk *chunkPtr;
+ TextDInfo *dInfoPtr = textPtr->dInfoPtr;
+ Display *display;
+ int height, y_off;
+#ifndef TK_NO_DOUBLE_BUFFERING
+ const int y = 0;
+#else
+ const int y = dlPtr->y;
+#endif /* TK_NO_DOUBLE_BUFFERING */
+
+ if (dlPtr->chunkPtr == NULL) return;
+
+ display = Tk_Display(textPtr->tkwin);
+
+ height = dlPtr->height;
+ if ((height + dlPtr->y) > dInfoPtr->maxY) {
+ height = dInfoPtr->maxY - dlPtr->y;
+ }
+ if (dlPtr->y < dInfoPtr->y) {
+ y_off = dInfoPtr->y - dlPtr->y;
+ height -= y_off;
+ } else {
+ y_off = 0;
+ }
+
+#ifdef TK_NO_DOUBLE_BUFFERING
+ TkpClipDrawableToRect(display, pixmap, dInfoPtr->x, y + y_off,
+ dInfoPtr->maxX - dInfoPtr->x, height);
+#endif /* TK_NO_DOUBLE_BUFFERING */
+
+ /*
+ * First, clear the area of the line to the background color for the text
+ * widget.
+ */
+
+ Tk_Fill3DRectangle(textPtr->tkwin, pixmap, textPtr->border, 0, y,
+ Tk_Width(textPtr->tkwin), dlPtr->height, 0, TK_RELIEF_FLAT);
+
+ /*
+ * Second, draw background information for the whole line.
+ */
+
+ DisplayLineBackground(textPtr, dlPtr, prevPtr, pixmap);
+
+ /*
+ * Third, draw the background color of the left and right margins.
+ */
+ if (dlPtr->lMarginColor != NULL) {
+ Tk_Fill3DRectangle(textPtr->tkwin, pixmap, dlPtr->lMarginColor, 0, y,
+ dlPtr->lMarginWidth + dInfoPtr->x - dInfoPtr->curXPixelOffset,
+ dlPtr->height, 0, TK_RELIEF_FLAT);
+ }
+ if (dlPtr->rMarginColor != NULL) {
+ Tk_Fill3DRectangle(textPtr->tkwin, pixmap, dlPtr->rMarginColor,
+ dInfoPtr->maxX - dlPtr->rMarginWidth + dInfoPtr->curXPixelOffset,
+ y, dlPtr->rMarginWidth, dlPtr->height, 0, TK_RELIEF_FLAT);
+ }
+
+ /*
+ * Make another pass through all of the chunks to redraw the insertion
+ * cursor, if it is visible on this line. Must do it here rather than in
+ * the foreground pass below because otherwise a wide insertion cursor
+ * will obscure the character to its left.
+ */
+
+ if (textPtr->state == TK_TEXT_STATE_NORMAL) {
+ for (chunkPtr = dlPtr->chunkPtr; (chunkPtr != NULL);
+ chunkPtr = chunkPtr->nextPtr) {
+ if (chunkPtr->displayProc == TkTextInsertDisplayProc) {
+ int x = chunkPtr->x + dInfoPtr->x - dInfoPtr->curXPixelOffset;
+
+ chunkPtr->displayProc(textPtr, chunkPtr, x,
+ y + dlPtr->spaceAbove,
+ dlPtr->height - dlPtr->spaceAbove - dlPtr->spaceBelow,
+ dlPtr->baseline - dlPtr->spaceAbove, display, pixmap,
+ dlPtr->y + dlPtr->spaceAbove);
+ }
+ }
+ }
+
+ /*
+ * Make yet another pass through all of the chunks to redraw all of
+ * foreground information. Note: we have to call the displayProc even for
+ * chunks that are off-screen. This is needed, for example, so that
+ * embedded windows can be unmapped in this case.
+ */
+
+ for (chunkPtr = dlPtr->chunkPtr; (chunkPtr != NULL);
+ chunkPtr = chunkPtr->nextPtr) {
+ if (chunkPtr->displayProc == TkTextInsertDisplayProc) {
+ /*
+ * Already displayed the insertion cursor above. Don't do it again
+ * here.
+ */
+
+ continue;
+ }
+
+ /*
+ * Don't call if elide. This tax OK since not very many visible DLines
+ * in an area, but potentially many elide ones.
+ */
+
+ if (chunkPtr->displayProc != NULL) {
+ int x = chunkPtr->x + dInfoPtr->x - dInfoPtr->curXPixelOffset;
+
+ if ((x + chunkPtr->width <= 0) || (x >= dInfoPtr->maxX)) {
+ /*
+ * Note: we have to call the displayProc even for chunks that
+ * are off-screen. This is needed, for example, so that
+ * embedded windows can be unmapped in this case. Display the
+ * chunk at a coordinate that can be clearly identified by the
+ * displayProc as being off-screen to the left (the
+ * displayProc may not be able to tell if something is off to
+ * the right).
+ */
+
+ x = -chunkPtr->width;
+ }
+ chunkPtr->displayProc(textPtr, chunkPtr, x,
+ y + dlPtr->spaceAbove, dlPtr->height - dlPtr->spaceAbove -
+ dlPtr->spaceBelow, dlPtr->baseline - dlPtr->spaceAbove,
+ display, pixmap, dlPtr->y + dlPtr->spaceAbove);
+ }
+
+ if (dInfoPtr->dLinesInvalidated) {
+ return;
+ }
+ }
+
+#ifndef TK_NO_DOUBLE_BUFFERING
+ /*
+ * Copy the pixmap onto the screen. If this is the first or last line on
+ * the screen then copy a piece of the line, so that it doesn't overflow
+ * into the border area. Another special trick: copy the padding area to
+ * the left of the line; this is because the insertion cursor sometimes
+ * overflows onto that area and we want to get as much of the cursor as
+ * possible.
+ */
+
+ XCopyArea(display, pixmap, Tk_WindowId(textPtr->tkwin), dInfoPtr->copyGC,
+ dInfoPtr->x, y + y_off, (unsigned) (dInfoPtr->maxX - dInfoPtr->x),
+ (unsigned) height, dInfoPtr->x, dlPtr->y + y_off);
+#else
+ TkpClipDrawableToRect(display, pixmap, 0, 0, -1, -1);
+#endif /* TK_NO_DOUBLE_BUFFERING */
+ linesRedrawn++;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DisplayLineBackground --
+ *
+ * This function is called to fill in the background for a display line.
+ * It draws 3D borders cleverly so that adjacent chunks with the same
+ * style (whether on the same line or different lines) have a single 3D
+ * border around the whole region.
+ *
+ * Results:
+ * There is no return value. Pixmap is filled in with background
+ * information for dlPtr.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+DisplayLineBackground(
+ TkText *textPtr, /* Text widget containing line. */
+ register DLine *dlPtr, /* Information about line to draw. */
+ DLine *prevPtr, /* Line just above dlPtr, or NULL if dlPtr is
+ * the top-most line in the window. */
+ Pixmap pixmap) /* Pixmap to use for double-buffering. Caller
+ * must make sure it's large enough to hold
+ * line. Caller must also have filled it with
+ * the background color for the widget. */
+{
+ TextDInfo *dInfoPtr = textPtr->dInfoPtr;
+ TkTextDispChunk *chunkPtr; /* Pointer to chunk in the current line. */
+ TkTextDispChunk *chunkPtr2; /* Pointer to chunk in the line above or below
+ * the current one. NULL if we're to the left
+ * of or to the right of the chunks in the
+ * line. */
+ TkTextDispChunk *nextPtr2; /* Next chunk after chunkPtr2 (it's not the
+ * same as chunkPtr2->nextPtr in the case
+ * where chunkPtr2 is NULL because the line is
+ * indented). */
+ int leftX; /* The left edge of the region we're currently
+ * working on. */
+ int leftXIn; /* 1 means beveled edge at leftX slopes right
+ * as it goes down, 0 means it slopes left as
+ * it goes down. */
+ int rightX; /* Right edge of chunkPtr. */
+ int rightX2; /* Right edge of chunkPtr2. */
+ int matchLeft; /* Does the style of this line match that of
+ * its neighbor just to the left of the
+ * current x coordinate? */
+ int matchRight; /* Does line's style match its neighbor just
+ * to the right of the current x-coord? */
+ int minX, maxX, xOffset, bw;
+ StyleValues *sValuePtr;
+ Display *display;
+#ifndef TK_NO_DOUBLE_BUFFERING
+ const int y = 0;
+#else
+ const int y = dlPtr->y;
+#endif /* TK_NO_DOUBLE_BUFFERING */
+
+ /*
+ * Pass 1: scan through dlPtr from left to right. For each range of chunks
+ * with the same style, draw the main background for the style plus the
+ * vertical parts of the 3D borders (the left and right edges).
+ */
+
+ display = Tk_Display(textPtr->tkwin);
+ minX = dInfoPtr->curXPixelOffset;
+ xOffset = dInfoPtr->x - minX;
+ maxX = minX + dInfoPtr->maxX - dInfoPtr->x;
+ chunkPtr = dlPtr->chunkPtr;
+
+ /*
+ * Note A: in the following statement, and a few others later in this file
+ * marked with "See Note A above", the right side of the assignment was
+ * replaced with 0 on 6/18/97. This has the effect of highlighting the
+ * empty space to the left of a line whenever the leftmost character of
+ * the line is highlighted. This way, multi-line highlights always line up
+ * along their left edges. However, this may look funny in the case where
+ * a single word is highlighted. To undo the change, replace "leftX = 0"
+ * with "leftX = chunkPtr->x" and "rightX2 = 0" with "rightX2 =
+ * nextPtr2->x" here and at all the marked points below. This restores the
+ * old behavior where empty space to the left of a line is not
+ * highlighted, leaving a ragged left edge for multi-line highlights.
+ */
+
+ leftX = 0;
+ for (; leftX < maxX; chunkPtr = chunkPtr->nextPtr) {
+ if ((chunkPtr->nextPtr != NULL)
+ && SAME_BACKGROUND(chunkPtr->nextPtr->stylePtr,
+ chunkPtr->stylePtr)) {
+ continue;
+ }
+ sValuePtr = chunkPtr->stylePtr->sValuePtr;
+ rightX = chunkPtr->x + chunkPtr->width;
+ if ((chunkPtr->nextPtr == NULL) && (rightX < maxX)) {
+ rightX = maxX;
+ }
+ if (chunkPtr->stylePtr->bgGC != NULL) {
+ /*
+ * Not visible - bail out now.
+ */
+
+ if (rightX + xOffset <= 0) {
+ leftX = rightX;
+ continue;
+ }
+
+ /*
+ * Trim the start position for drawing to be no further away than
+ * -borderWidth. The reason is that on many X servers drawing from
+ * -32768 (or less) to +something simply does not display
+ * correctly. [Patch #541999]
+ */
+
+ if ((leftX + xOffset) < -(sValuePtr->borderWidth)) {
+ leftX = -sValuePtr->borderWidth - xOffset;
+ }
+ if ((rightX - leftX) > 32767) {
+ rightX = leftX + 32767;
+ }
+
+ /*
+ * Prevent the borders from leaking on adjacent characters,
+ * which would happen for too large border width.
+ */
+
+ bw = sValuePtr->borderWidth;
+ if (leftX + sValuePtr->borderWidth > rightX) {
+ bw = rightX - leftX;
+ }
+
+ XFillRectangle(display, pixmap, chunkPtr->stylePtr->bgGC,
+ leftX + xOffset, y, (unsigned int) (rightX - leftX),
+ (unsigned int) dlPtr->height);
+ if (sValuePtr->relief != TK_RELIEF_FLAT) {
+ Tk_3DVerticalBevel(textPtr->tkwin, pixmap, sValuePtr->border,
+ leftX + xOffset, y, bw, dlPtr->height, 1,
+ sValuePtr->relief);
+ Tk_3DVerticalBevel(textPtr->tkwin, pixmap, sValuePtr->border,
+ rightX - bw + xOffset, y, bw, dlPtr->height, 0,
+ sValuePtr->relief);
+ }
+ }
+ leftX = rightX;
+ }
+
+ /*
+ * Pass 2: draw the horizontal bevels along the top of the line. To do
+ * this, scan through dlPtr from left to right while simultaneously
+ * scanning through the line just above dlPtr. ChunkPtr2 and nextPtr2
+ * refer to two adjacent chunks in the line above.
+ */
+
+ chunkPtr = dlPtr->chunkPtr;
+ leftX = 0; /* See Note A above. */
+ leftXIn = 1;
+ rightX = chunkPtr->x + chunkPtr->width;
+ if ((chunkPtr->nextPtr == NULL) && (rightX < maxX)) {
+ rightX = maxX;
+ }
+ chunkPtr2 = NULL;
+ if (prevPtr != NULL && prevPtr->chunkPtr != NULL) {
+ /*
+ * Find the chunk in the previous line that covers leftX.
+ */
+
+ nextPtr2 = prevPtr->chunkPtr;
+ rightX2 = 0; /* See Note A above. */
+ while (rightX2 <= leftX) {
+ chunkPtr2 = nextPtr2;
+ if (chunkPtr2 == NULL) {
+ break;
+ }
+ nextPtr2 = chunkPtr2->nextPtr;
+ rightX2 = chunkPtr2->x + chunkPtr2->width;
+ if (nextPtr2 == NULL) {
+ rightX2 = INT_MAX;
+ }
+ }
+ } else {
+ nextPtr2 = NULL;
+ rightX2 = INT_MAX;
+ }
+
+ while (leftX < maxX) {
+ matchLeft = (chunkPtr2 != NULL)
+ && SAME_BACKGROUND(chunkPtr2->stylePtr, chunkPtr->stylePtr);
+ sValuePtr = chunkPtr->stylePtr->sValuePtr;
+ if (rightX <= rightX2) {
+ /*
+ * The chunk in our line is about to end. If its style changes
+ * then draw the bevel for the current style.
+ */
+
+ if ((chunkPtr->nextPtr == NULL)
+ || !SAME_BACKGROUND(chunkPtr->stylePtr,
+ chunkPtr->nextPtr->stylePtr)) {
+ if (!matchLeft && (sValuePtr->relief != TK_RELIEF_FLAT)) {
+ Tk_3DHorizontalBevel(textPtr->tkwin, pixmap,
+ sValuePtr->border, leftX + xOffset, y,
+ rightX - leftX, sValuePtr->borderWidth, leftXIn,
+ 1, 1, sValuePtr->relief);
+ }
+ leftX = rightX;
+ leftXIn = 1;
+
+ /*
+ * If the chunk in the line above is also ending at the same
+ * point then advance to the next chunk in that line.
+ */
+
+ if ((rightX == rightX2) && (chunkPtr2 != NULL)) {
+ goto nextChunk2;
+ }
+ }
+ chunkPtr = chunkPtr->nextPtr;
+ if (chunkPtr == NULL) {
+ break;
+ }
+ rightX = chunkPtr->x + chunkPtr->width;
+ if ((chunkPtr->nextPtr == NULL) && (rightX < maxX)) {
+ rightX = maxX;
+ }
+ continue;
+ }
+
+ /*
+ * The chunk in the line above is ending at an x-position where there
+ * is no change in the style of the current line. If the style above
+ * matches the current line on one side of the change but not on the
+ * other, we have to draw an L-shaped piece of bevel.
+ */
+
+ matchRight = (nextPtr2 != NULL)
+ && SAME_BACKGROUND(nextPtr2->stylePtr, chunkPtr->stylePtr);
+ if (matchLeft && !matchRight) {
+ bw = sValuePtr->borderWidth;
+ if (rightX2 - sValuePtr->borderWidth < leftX) {
+ bw = rightX2 - leftX;
+ }
+ if (sValuePtr->relief != TK_RELIEF_FLAT) {
+ Tk_3DVerticalBevel(textPtr->tkwin, pixmap, sValuePtr->border,
+ rightX2 - bw + xOffset, y, bw,
+ sValuePtr->borderWidth, 0, sValuePtr->relief);
+ }
+ leftX = rightX2 - bw;
+ leftXIn = 0;
+ } else if (!matchLeft && matchRight
+ && (sValuePtr->relief != TK_RELIEF_FLAT)) {
+ bw = sValuePtr->borderWidth;
+ if (rightX2 + sValuePtr->borderWidth > rightX) {
+ bw = rightX - rightX2;
+ }
+ Tk_3DVerticalBevel(textPtr->tkwin, pixmap, sValuePtr->border,
+ rightX2 + xOffset, y, bw, sValuePtr->borderWidth,
+ 1, sValuePtr->relief);
+ Tk_3DHorizontalBevel(textPtr->tkwin, pixmap, sValuePtr->border,
+ leftX + xOffset, y, rightX2 + bw - leftX,
+ sValuePtr->borderWidth, leftXIn, 0, 1,
+ sValuePtr->relief);
+ }
+
+ nextChunk2:
+ chunkPtr2 = nextPtr2;
+ if (chunkPtr2 == NULL) {
+ rightX2 = INT_MAX;
+ } else {
+ nextPtr2 = chunkPtr2->nextPtr;
+ rightX2 = chunkPtr2->x + chunkPtr2->width;
+ if (nextPtr2 == NULL) {
+ rightX2 = INT_MAX;
+ }
+ }
+ }
+
+ /*
+ * Pass 3: draw the horizontal bevels along the bottom of the line. This
+ * uses the same approach as pass 2.
+ */
+
+ chunkPtr = dlPtr->chunkPtr;
+ leftX = 0; /* See Note A above. */
+ leftXIn = 0;
+ rightX = chunkPtr->x + chunkPtr->width;
+ if ((chunkPtr->nextPtr == NULL) && (rightX < maxX)) {
+ rightX = maxX;
+ }
+ chunkPtr2 = NULL;
+ if (dlPtr->nextPtr != NULL && dlPtr->nextPtr->chunkPtr != NULL) {
+ /*
+ * Find the chunk in the next line that covers leftX.
+ */
+
+ nextPtr2 = dlPtr->nextPtr->chunkPtr;
+ rightX2 = 0; /* See Note A above. */
+ while (rightX2 <= leftX) {
+ chunkPtr2 = nextPtr2;
+ if (chunkPtr2 == NULL) {
+ break;
+ }
+ nextPtr2 = chunkPtr2->nextPtr;
+ rightX2 = chunkPtr2->x + chunkPtr2->width;
+ if (nextPtr2 == NULL) {
+ rightX2 = INT_MAX;
+ }
+ }
+ } else {
+ nextPtr2 = NULL;
+ rightX2 = INT_MAX;
+ }
+
+ while (leftX < maxX) {
+ matchLeft = (chunkPtr2 != NULL)
+ && SAME_BACKGROUND(chunkPtr2->stylePtr, chunkPtr->stylePtr);
+ sValuePtr = chunkPtr->stylePtr->sValuePtr;
+ if (rightX <= rightX2) {
+ if ((chunkPtr->nextPtr == NULL)
+ || !SAME_BACKGROUND(chunkPtr->stylePtr,
+ chunkPtr->nextPtr->stylePtr)) {
+ if (!matchLeft && (sValuePtr->relief != TK_RELIEF_FLAT)) {
+ Tk_3DHorizontalBevel(textPtr->tkwin, pixmap,
+ sValuePtr->border, leftX + xOffset,
+ y + dlPtr->height - sValuePtr->borderWidth,
+ rightX - leftX, sValuePtr->borderWidth, leftXIn,
+ 0, 0, sValuePtr->relief);
+ }
+ leftX = rightX;
+ leftXIn = 0;
+ if ((rightX == rightX2) && (chunkPtr2 != NULL)) {
+ goto nextChunk2b;
+ }
+ }
+ chunkPtr = chunkPtr->nextPtr;
+ if (chunkPtr == NULL) {
+ break;
+ }
+ rightX = chunkPtr->x + chunkPtr->width;
+ if ((chunkPtr->nextPtr == NULL) && (rightX < maxX)) {
+ rightX = maxX;
+ }
+ continue;
+ }
+
+ matchRight = (nextPtr2 != NULL)
+ && SAME_BACKGROUND(nextPtr2->stylePtr, chunkPtr->stylePtr);
+ if (matchLeft && !matchRight) {
+ bw = sValuePtr->borderWidth;
+ if (rightX2 - sValuePtr->borderWidth < leftX) {
+ bw = rightX2 - leftX;
+ }
+ if (sValuePtr->relief != TK_RELIEF_FLAT) {
+ Tk_3DVerticalBevel(textPtr->tkwin, pixmap, sValuePtr->border,
+ rightX2 - bw + xOffset,
+ y + dlPtr->height - sValuePtr->borderWidth,
+ bw, sValuePtr->borderWidth, 0, sValuePtr->relief);
+ }
+ leftX = rightX2 - bw;
+ leftXIn = 1;
+ } else if (!matchLeft && matchRight
+ && (sValuePtr->relief != TK_RELIEF_FLAT)) {
+ bw = sValuePtr->borderWidth;
+ if (rightX2 + sValuePtr->borderWidth > rightX) {
+ bw = rightX - rightX2;
+ }
+ Tk_3DVerticalBevel(textPtr->tkwin, pixmap, sValuePtr->border,
+ rightX2 + xOffset,
+ y + dlPtr->height - sValuePtr->borderWidth, bw,
+ sValuePtr->borderWidth, 1, sValuePtr->relief);
+ Tk_3DHorizontalBevel(textPtr->tkwin, pixmap, sValuePtr->border,
+ leftX + xOffset,
+ y + dlPtr->height - sValuePtr->borderWidth,
+ rightX2 + bw - leftX, sValuePtr->borderWidth, leftXIn,
+ 1, 0, sValuePtr->relief);
+ }
+
+ nextChunk2b:
+ chunkPtr2 = nextPtr2;
+ if (chunkPtr2 == NULL) {
+ rightX2 = INT_MAX;
+ } else {
+ nextPtr2 = chunkPtr2->nextPtr;
+ rightX2 = chunkPtr2->x + chunkPtr2->width;
+ if (nextPtr2 == NULL) {
+ rightX2 = INT_MAX;
+ }
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AsyncUpdateLineMetrics --
+ *
+ * This function is invoked as a background handler to update the pixel-
+ * height calculations of individual lines in an asychronous manner.
+ *
+ * Currently a timer-handler is used for this purpose, which continuously
+ * reschedules itself. It may well be better to use some other approach
+ * (e.g., a background thread). We can't use an idle-callback because of
+ * a known bug in Tcl/Tk in which idle callbacks are not allowed to
+ * re-schedule themselves. This just causes an effective infinite loop.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Line heights may be recalculated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+AsyncUpdateLineMetrics(
+ ClientData clientData) /* Information about widget. */
+{
+ register TkText *textPtr = clientData;
+ TextDInfo *dInfoPtr = textPtr->dInfoPtr;
+ int lineNum;
+
+ dInfoPtr->lineUpdateTimer = NULL;
+
+ if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)
+ || !Tk_IsMapped(textPtr->tkwin)) {
+ /*
+ * The widget has been deleted, or is not mapped. Don't do anything.
+ */
+
+ if (textPtr->refCount-- <= 1) {
+ ckfree(textPtr);
+ }
+ return;
+ }
+
+ if (dInfoPtr->flags & REDRAW_PENDING) {
+ dInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(1,
+ AsyncUpdateLineMetrics, clientData);
+ return;
+ }
+
+ /*
+ * Reify where we end or all hell breaks loose with the calculations when
+ * we try to update. [Bug 2677890]
+ */
+
+ lineNum = dInfoPtr->currentMetricUpdateLine;
+ if (dInfoPtr->lastMetricUpdateLine == -1) {
+ dInfoPtr->lastMetricUpdateLine =
+ TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr);
+ }
+
+ /*
+ * Update the lines in blocks of about 24 recalculations, or 250+ lines
+ * examined, so we pass in 256 for 'doThisMuch'.
+ */
+
+ lineNum = TkTextUpdateLineMetrics(textPtr, lineNum,
+ dInfoPtr->lastMetricUpdateLine, 256);
+
+ dInfoPtr->currentMetricUpdateLine = lineNum;
+
+ if (tkTextDebug) {
+ char buffer[2 * TCL_INTEGER_SPACE + 1];
+
+ sprintf(buffer, "%d %d", lineNum, dInfoPtr->lastMetricUpdateLine);
+ LOG("tk_textInvalidateLine", buffer);
+ }
+
+ /*
+ * If we're not in the middle of a long-line calculation (metricEpoch==-1)
+ * and we've reached the last line, then we're done.
+ */
+
+ if (dInfoPtr->metricEpoch == -1
+ && lineNum == dInfoPtr->lastMetricUpdateLine) {
+ /*
+ * We have looped over all lines, so we're done. We must release our
+ * refCount on the widget (the timer token was already set to NULL
+ * above). If there is a registered aftersync command, run that first.
+ * Cancel any pending idle task which would try to run the command
+ * after the afterSyncCmd pointer had been set to NULL.
+ */
+
+ if (textPtr->afterSyncCmd) {
+ int code;
+ Tcl_CancelIdleCall(TkTextRunAfterSyncCmd, textPtr);
+ Tcl_Preserve((ClientData) textPtr->interp);
+ code = Tcl_EvalObjEx(textPtr->interp, textPtr->afterSyncCmd,
+ TCL_EVAL_GLOBAL);
+ if (code == TCL_ERROR) {
+ Tcl_AddErrorInfo(textPtr->interp, "\n (text sync)");
+ Tcl_BackgroundError(textPtr->interp);
+ }
+ Tcl_Release((ClientData) textPtr->interp);
+ Tcl_DecrRefCount(textPtr->afterSyncCmd);
+ textPtr->afterSyncCmd = NULL;
+ }
+
+ /*
+ * Fire the <<WidgetViewSync>> event since the widget view is in sync
+ * with its internal data (actually it will be after the next trip
+ * through the event loop, because the widget redraws at idle-time).
+ */
+ GenerateWidgetViewSyncEvent(textPtr, 1);
+
+ if (textPtr->refCount-- <= 1) {
+ ckfree(textPtr);
+ }
+ return;
+ }
+
+ /*
+ * Re-arm the timer. We already have a refCount on the text widget so no
+ * need to adjust that.
+ */
+
+ dInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(1,
+ AsyncUpdateLineMetrics, textPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GenerateWidgetViewSyncEvent --
+ *
+ * Send the <<WidgetViewSync>> event related to the text widget
+ * line metrics asynchronous update. These events should only
+ * be sent when the sync status has changed. So this function
+ * compares the requested state with the state saved in the
+ * TkText structure, and only generates the event if they are
+ * different. This means that it is safe to call this function
+ * at any time when the state is known.
+ *
+ * If an event is sent, the effect is equivalent to:
+ * event generate $textWidget <<WidgetViewSync>> -data $s
+ * where $s is the sync status: true (when the widget view is in
+ * sync with its internal data) or false (when it is not).
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * If corresponding bindings are present, they will trigger.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GenerateWidgetViewSyncEvent(
+ TkText *textPtr, /* Information about text widget. */
+ Bool InSync) /* true if becoming in sync, false otherwise */
+{
+ Bool NewSyncState = (InSync != 0); /* ensure 0 or 1 value */
+ Bool OldSyncState = !(textPtr->dInfoPtr->flags & OUT_OF_SYNC);
+
+ /*
+ * OSX 10.14 needs to be told to display the window when the Text Widget
+ * is in sync. (That is, to run DisplayText inside of the drawRect
+ * method.) Otherwise the screen might not get updated until an event
+ * like a mouse click is received. But that extra drawing corrupts the
+ * data that the test suite is trying to collect.
+ */
+
+ if (!tkTextDebug) {
+ FORCE_DISPLAY(textPtr->tkwin);
+ }
+
+ if (NewSyncState != OldSyncState) {
+ if (NewSyncState) {
+ textPtr->dInfoPtr->flags &= ~OUT_OF_SYNC;
+ } else {
+ textPtr->dInfoPtr->flags |= OUT_OF_SYNC;
+ }
+ TkSendVirtualEvent(textPtr->tkwin, "WidgetViewSync",
+ Tcl_NewBooleanObj(NewSyncState));
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkTextUpdateLineMetrics --
+ *
+ * This function updates the pixel height calculations of a range of
+ * lines in the widget. The range is from lineNum to endLine, but, if
+ * doThisMuch is positive, then the function may return earlier, once a
+ * certain number of lines has been examined. The line counts are from 0.
+ *
+ * If doThisMuch is -1, then all lines in the range will be updated. This
+ * will potentially take quite some time for a large text widget.
+ *
+ * Note: with bad input for lineNum and endLine, this function can loop
+ * indefinitely.
+ *
+ * Results:
+ * The index of the last line examined (or -1 if we are about to wrap
+ * around from end to beginning of the widget, and the next line will be
+ * the first line).
+ *
+ * Side effects:
+ * Line heights may be recalculated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkTextUpdateLineMetrics(
+ TkText *textPtr, /* Information about widget. */
+ int lineNum, /* Start at this line. */
+ int endLine, /* Go no further than this line. */
+ int doThisMuch) /* How many lines to check, or how many 10s of
+ * lines to recalculate. If '-1' then do
+ * everything in the range (which may take a
+ * while). */
+{
+ TkTextLine *linePtr = NULL;
+ int count = 0;
+ int totalLines = TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr);
+ int fullUpdateRequested = (lineNum == 0 &&
+ endLine == totalLines &&
+ doThisMuch == -1);
+
+ if (totalLines == 0) {
+ /*
+ * Empty peer widget.
+ */
+
+ return endLine;
+ }
+
+ while (1) {
+
+ /*
+ * Get a suitable line.
+ */
+
+ if (lineNum == -1 && linePtr == NULL) {
+ lineNum = 0;
+ linePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, textPtr,
+ lineNum);
+ } else {
+ if (lineNum == -1 || linePtr == NULL) {
+ if (lineNum == -1) {
+ lineNum = 0;
+ }
+ linePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree,
+ textPtr, lineNum);
+ } else {
+ lineNum++;
+ linePtr = TkBTreeNextLine(textPtr, linePtr);
+ }
+
+ /*
+ * If we're in the middle of a partial-line height calculation,
+ * then we can't be done.
+ */
+
+ if (textPtr->dInfoPtr->metricEpoch == -1 && lineNum == endLine) {
+
+ /*
+ * We have looped over all lines, so we're done.
+ */
+
+ break;
+ }
+ }
+
+ if (lineNum < totalLines) {
+ if (tkTextDebug) {
+ char buffer[4 * TCL_INTEGER_SPACE + 3];
+
+ sprintf(buffer, "%d %d %d %d",
+ lineNum, endLine, totalLines, count);
+ LOG("tk_textInvalidateLine", buffer);
+ }
+
+ /*
+ * Now update the line's metrics if necessary.
+ */
+
+ if (TkBTreeLinePixelEpoch(textPtr, linePtr)
+ == textPtr->dInfoPtr->lineMetricUpdateEpoch) {
+
+ /*
+ * This line is already up to date. That means there's nothing
+ * to do here.
+ */
+
+ } else if (doThisMuch == -1) {
+ count += 8 * TkTextUpdateOneLine(textPtr, linePtr, 0,NULL,0);
+ } else {
+ TkTextIndex index;
+ TkTextIndex *indexPtr;
+ int pixelHeight;
+
+ /*
+ * If the metric epoch is the same as the widget's epoch, then
+ * we know that indexPtrs are still valid, and if the cached
+ * metricIndex (if any) is for the same line as we wish to
+ * examine, then we are looking at a long line wrapped many
+ * times, which we will examine in pieces.
+ */
+
+ if (textPtr->dInfoPtr->metricEpoch ==
+ textPtr->sharedTextPtr->stateEpoch &&
+ textPtr->dInfoPtr->metricIndex.linePtr==linePtr) {
+ indexPtr = &textPtr->dInfoPtr->metricIndex;
+ pixelHeight = textPtr->dInfoPtr->metricPixelHeight;
+ } else {
+
+ /*
+ * We must reset the partial line height calculation data
+ * here, so we don't use it when it is out of date.
+ */
+
+ textPtr->dInfoPtr->metricEpoch = -1;
+ index.tree = textPtr->sharedTextPtr->tree;
+ index.linePtr = linePtr;
+ index.byteIndex = 0;
+ index.textPtr = NULL;
+ indexPtr = &index;
+ pixelHeight = 0;
+ }
+
+ /*
+ * Update the line and update the counter, counting 8 for each
+ * display line we actually re-layout.
+ */
+
+ count += 8 * TkTextUpdateOneLine(textPtr, linePtr,
+ pixelHeight, indexPtr, 1);
+
+ if (indexPtr->linePtr == linePtr) {
+
+ /*
+ * We didn't complete the logical line, because it
+ * produced very many display lines, which must be because
+ * it must be a long line wrapped many times. So we must
+ * cache as far as we got for next time around.
+ */
+
+ if (pixelHeight == 0) {
+
+ /*
+ * These have already been stored, unless we just
+ * started the new line.
+ */
+
+ textPtr->dInfoPtr->metricIndex = index;
+ textPtr->dInfoPtr->metricEpoch =
+ textPtr->sharedTextPtr->stateEpoch;
+ }
+ textPtr->dInfoPtr->metricPixelHeight =
+ TkBTreeLinePixelCount(textPtr, linePtr);
+ break;
+ }
+
+ /*
+ * We're done with this long line.
+ */
+
+ textPtr->dInfoPtr->metricEpoch = -1;
+ }
+ } else {
+
+ /*
+ * We must never recalculate the height of the last artificial
+ * line. It must stay at zero, and if we recalculate it, it will
+ * change.
+ */
+
+ if (endLine >= totalLines) {
+ lineNum = endLine;
+ break;
+ }
+
+ /*
+ * Set things up for the next loop through.
+ */
+
+ lineNum = -1;
+ }
+ count++;
+
+ if (doThisMuch != -1 && count >= doThisMuch) {
+ break;
+ }
+ }
+ if (doThisMuch == -1) {
+
+ /*
+ * If we were requested to update the entire range, then also update
+ * the scrollbar.
+ */
+
+ GetYView(textPtr->interp, textPtr, 1);
+ }
+ if (fullUpdateRequested) {
+ GenerateWidgetViewSyncEvent(textPtr, 1);
+ }
+ return lineNum;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkTextInvalidateLineMetrics, TextInvalidateLineMetrics --
+ *
+ * Mark a number of text lines as having invalid line metric
+ * calculations. Never call this with linePtr as the last (artificial)
+ * line in the text. Depending on 'action' which indicates whether the
+ * given lines are simply invalid or have been inserted or deleted, the
+ * pre-existing asynchronous line update range may need to be adjusted.
+ *
+ * If linePtr is NULL then 'lineCount' and 'action' are ignored and all
+ * lines are invalidated.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * May schedule an asychronous callback.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkTextInvalidateLineMetrics(
+ TkSharedText *sharedTextPtr,/* Shared widget section for all peers, or
+ * NULL. */
+ TkText *textPtr, /* Widget record for text widget. */
+ TkTextLine *linePtr, /* Invalidation starts from this line. */
+ int lineCount, /* And includes this many following lines. */
+ int action) /* Indicates what type of invalidation
+ * occurred (insert, delete, or simple). */
+{
+ if (sharedTextPtr == NULL) {
+ TextInvalidateLineMetrics(textPtr, linePtr, lineCount, action);
+ } else {
+ textPtr = sharedTextPtr->peers;
+ while (textPtr != NULL) {
+ TextInvalidateLineMetrics(textPtr, linePtr, lineCount, action);
+ textPtr = textPtr->next;
+ }
+ }
+}
+
+static void
+TextInvalidateLineMetrics(
+ TkText *textPtr, /* Widget record for text widget. */
+ TkTextLine *linePtr, /* Invalidation starts from this line. */
+ int lineCount, /* And includes this many following lines. */
+ int action) /* Indicates what type of invalidation
+ * occurred (insert, delete, or simple). */
+{
+ int fromLine;
+ TextDInfo *dInfoPtr = textPtr->dInfoPtr;
+
+ if (linePtr != NULL) {
+ int counter = lineCount;
+
+ fromLine = TkBTreeLinesTo(textPtr, linePtr);
+
+ /*
+ * Invalidate the height calculations of each line in the given range.
+ */
+
+ TkBTreeLinePixelEpoch(textPtr, linePtr) = 0;
+ while (counter > 0 && linePtr != NULL) {
+ linePtr = TkBTreeNextLine(textPtr, linePtr);
+ if (linePtr != NULL) {
+ TkBTreeLinePixelEpoch(textPtr, linePtr) = 0;
+ }
+ counter--;
+ }
+
+ /*
+ * Now schedule an examination of each line in the union of the old
+ * and new update ranges, including the (possibly empty) range in
+ * between. If that between range is not-empty, then we are examining
+ * more lines than is strictly necessary (but the examination of the
+ * extra lines should be quick, since their pixelCalculationEpoch will
+ * be up to date). However, to keep track of that would require more
+ * complex record-keeping than what we have.
+ */
+
+ if (dInfoPtr->lineUpdateTimer == NULL) {
+ dInfoPtr->currentMetricUpdateLine = fromLine;
+ if (action == TK_TEXT_INVALIDATE_DELETE) {
+ lineCount = 0;
+ }
+ dInfoPtr->lastMetricUpdateLine = fromLine + lineCount + 1;
+ } else {
+ int toLine = fromLine + lineCount + 1;
+
+ if (action == TK_TEXT_INVALIDATE_DELETE) {
+ if (toLine <= dInfoPtr->currentMetricUpdateLine) {
+ dInfoPtr->currentMetricUpdateLine = fromLine;
+ if (dInfoPtr->lastMetricUpdateLine != -1) {
+ dInfoPtr->lastMetricUpdateLine -= lineCount;
+ }
+ } else if (fromLine <= dInfoPtr->currentMetricUpdateLine) {
+ dInfoPtr->currentMetricUpdateLine = fromLine;
+ if (toLine <= dInfoPtr->lastMetricUpdateLine) {
+ dInfoPtr->lastMetricUpdateLine -= lineCount;
+ }
+ } else {
+ if (dInfoPtr->lastMetricUpdateLine != -1) {
+ dInfoPtr->lastMetricUpdateLine = toLine;
+ }
+ }
+ } else if (action == TK_TEXT_INVALIDATE_INSERT) {
+ if (toLine <= dInfoPtr->currentMetricUpdateLine) {
+ dInfoPtr->currentMetricUpdateLine = fromLine;
+ if (dInfoPtr->lastMetricUpdateLine != -1) {
+ dInfoPtr->lastMetricUpdateLine += lineCount;
+ }
+ } else if (fromLine <= dInfoPtr->currentMetricUpdateLine) {
+ dInfoPtr->currentMetricUpdateLine = fromLine;
+ if (toLine <= dInfoPtr->lastMetricUpdateLine) {
+ dInfoPtr->lastMetricUpdateLine += lineCount;
+ }
+ if (toLine > dInfoPtr->lastMetricUpdateLine) {
+ dInfoPtr->lastMetricUpdateLine = toLine;
+ }
+ } else {
+ if (dInfoPtr->lastMetricUpdateLine != -1) {
+ dInfoPtr->lastMetricUpdateLine = toLine;
+ }
+ }
+ } else {
+ if (fromLine < dInfoPtr->currentMetricUpdateLine) {
+ dInfoPtr->currentMetricUpdateLine = fromLine;
+ }
+ if (dInfoPtr->lastMetricUpdateLine != -1
+ && toLine > dInfoPtr->lastMetricUpdateLine) {
+ dInfoPtr->lastMetricUpdateLine = toLine;
+ }
+ }
+ }
+ } else {
+ /*
+ * This invalidates the height of all lines in the widget.
+ */
+
+ if ((++dInfoPtr->lineMetricUpdateEpoch) == 0) {
+ dInfoPtr->lineMetricUpdateEpoch++;
+ }
+
+ /*
+ * This has the effect of forcing an entire new loop of update checks
+ * on all lines in the widget.
+ */
+
+ if (dInfoPtr->lineUpdateTimer == NULL) {
+ dInfoPtr->currentMetricUpdateLine = -1;
+ }
+ dInfoPtr->lastMetricUpdateLine = dInfoPtr->currentMetricUpdateLine;
+ }
+
+ /*
+ * Now re-set the current update calculations.
+ */
+
+ if (dInfoPtr->lineUpdateTimer == NULL) {
+ textPtr->refCount++;
+ dInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(1,
+ AsyncUpdateLineMetrics, textPtr);
+ }
+
+ /*
+ * The widget is out of sync: send a <<WidgetViewSync>> event.
+ */
+ GenerateWidgetViewSyncEvent(textPtr, 0);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkTextFindDisplayLineEnd --
+ *
+ * This function is invoked to find the index of the beginning or end of
+ * the particular display line on which the given index sits, whether
+ * that line is displayed or not.
+ *
+ * If 'end' is zero, we look for the start, and if 'end' is one we look
+ * for the end.
+ *
+ * If the beginning of the current display line is elided, and we are
+ * looking for the start of the line, then the returned index will be the
+ * first elided index on the display line.
+ *
+ * Similarly if the end of the current display line is elided and we are
+ * looking for the end, then the returned index will be the last elided
+ * index on the display line.
+ *
+ * Results:
+ * Modifies indexPtr to point to the given end.
+ *
+ * If xOffset is non-NULL, it is set to the x-pixel offset of the given
+ * original index within the given display line.
+ *
+ * Side effects:
+ * The combination of 'LayoutDLine' and 'FreeDLines' seems like a rather
+ * time-consuming way of gathering the information we need, so this would
+ * be a good place to look to speed up the calculations. In particular
+ * these calls will map and unmap embedded windows respectively, which I
+ * would hope isn't exactly necessary!
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkTextFindDisplayLineEnd(
+ TkText *textPtr, /* Widget record for text widget. */
+ TkTextIndex *indexPtr, /* Index we will adjust to the display line
+ * start or end. */
+ int end, /* 0 = start, 1 = end. */
+ int *xOffset) /* NULL, or used to store the x-pixel offset
+ * of the original index within its display
+ * line. */
+{
+ TkTextIndex index;
+
+ if (!end && IsStartOfNotMergedLine(textPtr, indexPtr)) {
+ /*
+ * Nothing to do.
+ */
+
+ if (xOffset != NULL) {
+ *xOffset = 0;
+ }
+ return;
+ }
+
+ index = *indexPtr;
+ index.byteIndex = 0;
+ index.textPtr = NULL;
+
+ while (1) {
+ TkTextIndex endOfLastLine;
+
+ if (TkTextIndexBackBytes(textPtr, &index, 1, &endOfLastLine)) {
+ /*
+ * Reached beginning of text.
+ */
+
+ break;
+ }
+
+ if (!TkTextIsElided(textPtr, &endOfLastLine, NULL)) {
+ /*
+ * The eol is not elided, so 'index' points to the start of a
+ * display line (as well as logical line).
+ */
+
+ break;
+ }
+
+ /*
+ * indexPtr's logical line is actually merged with the previous
+ * logical line whose eol is elided. Continue searching back to get a
+ * real line start.
+ */
+
+ index = endOfLastLine;
+ index.byteIndex = 0;
+ }
+
+ while (1) {
+ DLine *dlPtr;
+ int byteCount;
+ TkTextIndex nextLineStart;
+
+ dlPtr = LayoutDLine(textPtr, &index);
+ byteCount = dlPtr->byteCount;
+
+ TkTextIndexForwBytes(textPtr, &index, byteCount, &nextLineStart);
+
+ /*
+ * 'byteCount' goes up to the beginning of the next display line, so
+ * equality here says we need one more line. We try to perform a quick
+ * comparison which is valid for the case where the logical line is
+ * the same, but otherwise fall back on a full TkTextIndexCmp.
+ */
+
+ if (((index.linePtr == indexPtr->linePtr)
+ && (index.byteIndex + byteCount > indexPtr->byteIndex))
+ || (dlPtr->logicalLinesMerged > 0
+ && TkTextIndexCmp(&nextLineStart, indexPtr) > 0)) {
+ /*
+ * It's on this display line.
+ */
+
+ if (xOffset != NULL) {
+ /*
+ * This call takes a byte index relative to the start of the
+ * current _display_ line, not logical line. We are about to
+ * overwrite indexPtr->byteIndex, so we must do this now.
+ */
+
+ *xOffset = DlineXOfIndex(textPtr, dlPtr,
+ TkTextIndexCountBytes(textPtr, &dlPtr->index,
+ indexPtr));
+ }
+ if (end) {
+ /*
+ * The index we want is one less than the number of bytes in
+ * the display line.
+ */
+
+ TkTextIndexBackBytes(textPtr, &nextLineStart, 1, indexPtr);
+ } else {
+ *indexPtr = index;
+ }
+ FreeDLines(textPtr, dlPtr, NULL, DLINE_FREE_TEMP);
+ return;
+ }
+
+ FreeDLines(textPtr, dlPtr, NULL, DLINE_FREE_TEMP);
+ index = nextLineStart;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CalculateDisplayLineHeight --
+ *
+ * This function is invoked to recalculate the height of the particular
+ * display line which starts with the given index, whether that line is
+ * displayed or not.
+ *
+ * This function does not, in itself, update any cached information about
+ * line heights. That should be done, where necessary, by its callers.
+ *
+ * The behaviour of this function is _undefined_ if indexPtr is not
+ * currently at the beginning of a display line.
+ *
+ * Results:
+ * The number of vertical pixels used by the display line.
+ *
+ * If 'byteCountPtr' is non-NULL, then returns in that pointer the number
+ * of byte indices on the given display line (which can be used to update
+ * indexPtr in a loop).
+ *
+ * If 'mergedLinePtr' is non-NULL, then returns in that pointer the
+ * number of extra logical lines merged into the given display line.
+ *
+ * Side effects:
+ * The combination of 'LayoutDLine' and 'FreeDLines' seems like a rather
+ * time-consuming way of gathering the information we need, so this would
+ * be a good place to look to speed up the calculations. In particular
+ * these calls will map and unmap embedded windows respectively, which I
+ * would hope isn't exactly necessary!
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CalculateDisplayLineHeight(
+ TkText *textPtr, /* Widget record for text widget. */
+ const TkTextIndex *indexPtr,/* The index at the beginning of the display
+ * line of interest. */
+ int *byteCountPtr, /* NULL or used to return the number of byte
+ * indices on the given display line. */
+ int *mergedLinePtr) /* NULL or used to return if the given display
+ * line merges with a following logical line
+ * (because the eol is elided). */
+{
+ DLine *dlPtr;
+ int pixelHeight;
+
+ if (tkTextDebug) {
+ int oldtkTextDebug = tkTextDebug;
+ /*
+ * Check that the indexPtr we are given really is at the start of a
+ * display line. The gymnastics with tkTextDebug is to prevent
+ * failure of a test suite test, that checks that lines are rendered
+ * exactly once. TkTextFindDisplayLineEnd is used here for checking
+ * indexPtr but it calls LayoutDLine/FreeDLine which makes the
+ * counting wrong. The debug mode shall therefore be switched off
+ * when calling TkTextFindDisplayLineEnd.
+ */
+
+ TkTextIndex indexPtr2 = *indexPtr;
+ tkTextDebug = 0;
+ TkTextFindDisplayLineEnd(textPtr, &indexPtr2, 0, NULL);
+ tkTextDebug = oldtkTextDebug;
+ if (TkTextIndexCmp(&indexPtr2,indexPtr) != 0) {
+ Tcl_Panic("CalculateDisplayLineHeight called with bad indexPtr");
+ }
+ }
+
+ /*
+ * Special case for artificial last line. May be better to move this
+ * inside LayoutDLine.
+ */
+
+ if (indexPtr->byteIndex == 0
+ && TkBTreeNextLine(textPtr, indexPtr->linePtr) == NULL) {
+ if (byteCountPtr != NULL) {
+ *byteCountPtr = 0;
+ }
+ if (mergedLinePtr != NULL) {
+ *mergedLinePtr = 0;
+ }
+ return 0;
+ }
+
+ /*
+ * Layout, find the information we need and then free the display-line we
+ * laid-out. We must use 'FreeDLines' because it will actually call the
+ * relevant code to unmap any embedded windows which were mapped in the
+ * LayoutDLine call!
+ */
+
+ dlPtr = LayoutDLine(textPtr, indexPtr);
+ pixelHeight = dlPtr->height;
+ if (byteCountPtr != NULL) {
+ *byteCountPtr = dlPtr->byteCount;
+ }
+ if (mergedLinePtr != NULL) {
+ *mergedLinePtr = dlPtr->logicalLinesMerged;
+ }
+ FreeDLines(textPtr, dlPtr, NULL, DLINE_FREE_TEMP);
+
+ return pixelHeight;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkTextIndexYPixels --
+ *
+ * This function is invoked to calculate the number of vertical pixels
+ * between the first index of the text widget and the given index. The
+ * range from first logical line to given logical line is determined
+ * using the cached values, and the range inside the given logical line
+ * is calculated on the fly.
+ *
+ * Results:
+ * The pixel distance between first pixel in the widget and the
+ * top of the index's current display line (could be zero).
+ *
+ * Side effects:
+ * Just those of 'CalculateDisplayLineHeight'.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkTextIndexYPixels(
+ TkText *textPtr, /* Widget record for text widget. */
+ const TkTextIndex *indexPtr)/* The index of which we want the pixel
+ * distance from top of logical line to top of
+ * index. */
+{
+ int pixelHeight;
+ TkTextIndex index;
+ int alreadyStartOfLine = 1;
+
+ /*
+ * Find the index denoting the closest position being at the same time
+ * the start of a logical line above indexPtr and the start of a display
+ * line.
+ */
+
+ index = *indexPtr;
+ while (1) {
+ TkTextFindDisplayLineEnd(textPtr, &index, 0, NULL);
+ if (index.byteIndex == 0) {
+ break;
+ }
+ TkTextIndexBackBytes(textPtr, &index, 1, &index);
+ alreadyStartOfLine = 0;
+ }
+
+ pixelHeight = TkBTreePixelsTo(textPtr, index.linePtr);
+
+ /*
+ * Shortcut to avoid layout of a superfluous display line. We know there
+ * is nothing more to add up to the height if the index we were given was
+ * already on the first display line of a logical line.
+ */
+
+ if (alreadyStartOfLine) {
+ return pixelHeight;
+ }
+
+ /*
+ * Iterate through display lines, starting at the logical line belonging
+ * to index, adding up the pixel height of each such display line as we
+ * go along, until we go past 'indexPtr'.
+ */
+
+ while (1) {
+ int bytes, height, compare;
+
+ /*
+ * Currently this call doesn't have many side-effects. However, if in
+ * the future we change the code so there are side-effects (such as
+ * adjusting linePtr->pixelHeight), then the code might not quite work
+ * as intended, specifically the 'linePtr->pixelHeight == pixelHeight'
+ * test below this while loop.
+ */
+
+ height = CalculateDisplayLineHeight(textPtr, &index, &bytes, NULL);
+
+ TkTextIndexForwBytes(textPtr, &index, bytes, &index);
+
+ compare = TkTextIndexCmp(&index,indexPtr);
+ if (compare > 0) {
+ return pixelHeight;
+ }
+
+ if (height > 0) {
+ pixelHeight += height;
+ }
+
+ if (compare == 0) {
+ return pixelHeight;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkTextUpdateOneLine --
+ *
+ * This function is invoked to recalculate the height of a particular
+ * logical line, whether that line is displayed or not.
+ *
+ * It must NEVER be called for the artificial last TkTextLine which is
+ * used internally for administrative purposes only. That line must
+ * retain its initial height of 0 otherwise the pixel height calculation
+ * maintained by the B-tree will be wrong.
+ *
+ * Results:
+ * The number of display lines in the logical line. This could be zero if
+ * the line is totally elided.
+ *
+ * Side effects:
+ * Line heights may be recalculated, and a timer to update the scrollbar
+ * may be installed. Also see the called function
+ * CalculateDisplayLineHeight for its side effects.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkTextUpdateOneLine(
+ TkText *textPtr, /* Widget record for text widget. */
+ TkTextLine *linePtr, /* The line of which to calculate the
+ * height. */
+ int pixelHeight, /* If indexPtr is non-NULL, then this is the
+ * number of pixels in the logical line
+ * linePtr, up to the index which has been
+ * given. */
+ TkTextIndex *indexPtr, /* Either NULL or an index at the start of a
+ * display line belonging to linePtr, at which
+ * we wish to start (e.g. up to which we have
+ * already calculated). On return this will be
+ * set to the first index on the next line. */
+ int partialCalc) /* Set to 1 if we are allowed to do partial
+ * height calculations of long-lines. In this
+ * case we'll only return what we know so
+ * far. */
+{
+ TkTextIndex index;
+ int displayLines;
+ int mergedLines;
+
+ if (indexPtr == NULL) {
+ index.tree = textPtr->sharedTextPtr->tree;
+ index.linePtr = linePtr;
+ index.byteIndex = 0;
+ index.textPtr = NULL;
+ indexPtr = &index;
+ pixelHeight = 0;
+ }
+
+ /*
+ * CalculateDisplayLineHeight _must_ be called (below) with an index at
+ * the beginning of a display line. Force this to happen. This is needed
+ * when TkTextUpdateOneLine is called with a line that is merged with its
+ * previous line: the number of merged logical lines in a display line is
+ * calculated correctly only when CalculateDisplayLineHeight receives
+ * an index at the beginning of a display line. In turn this causes the
+ * merged lines to receive their correct zero pixel height in
+ * TkBTreeAdjustPixelHeight.
+ */
+
+ TkTextFindDisplayLineEnd(textPtr, indexPtr, 0, NULL);
+ linePtr = indexPtr->linePtr;
+
+ /*
+ * Iterate through all display-lines corresponding to the single logical
+ * line 'linePtr' (and lines merged into this line due to eol elision),
+ * adding up the pixel height of each such display line as we go along.
+ * The final total is, therefore, the total height of all display lines
+ * made up by the logical line 'linePtr' and subsequent logical lines
+ * merged into this line.
+ */
+
+ displayLines = 0;
+ mergedLines = 0;
+
+ while (1) {
+ int bytes, height, logicalLines;
+
+ /*
+ * Currently this call doesn't have many side-effects. However, if in
+ * the future we change the code so there are side-effects (such as
+ * adjusting linePtr->pixelHeight), then the code might not quite work
+ * as intended, specifically the 'linePtr->pixelHeight == pixelHeight'
+ * test below this while loop.
+ */
+
+ height = CalculateDisplayLineHeight(textPtr, indexPtr, &bytes,
+ &logicalLines);
+
+ if (height > 0) {
+ pixelHeight += height;
+ displayLines++;
+ }
+
+ mergedLines += logicalLines;
+
+ if (TkTextIndexForwBytes(textPtr, indexPtr, bytes, indexPtr)) {
+ break;
+ }
+
+ if (mergedLines == 0) {
+ if (indexPtr->linePtr != linePtr) {
+ /*
+ * If we reached the end of the logical line, then either way
+ * we don't have a partial calculation.
+ */
+
+ partialCalc = 0;
+ break;
+ }
+ } else {
+ if (IsStartOfNotMergedLine(textPtr, indexPtr)) {
+ /*
+ * We've ended a logical line.
+ */
+
+ partialCalc = 0;
+ break;
+ }
+
+ /*
+ * We must still be on the same wrapped line, on a new logical
+ * line merged with the logical line 'linePtr'.
+ */
+ }
+ if (partialCalc && displayLines > 50 && mergedLines == 0) {
+ /*
+ * Only calculate 50 display lines at a time, to avoid huge
+ * delays. In any case it is very rare that a single line wraps 50
+ * times!
+ *
+ * If we have any merged lines, we must complete the full logical
+ * line layout here and now, because the partial-calculation code
+ * isn't designed to handle merged logical lines. Hence the
+ * 'mergedLines == 0' check.
+ */
+
+ break;
+ }
+ }
+
+ if (!partialCalc) {
+ int changed = 0;
+
+ /*
+ * Cancel any partial line height calculation state.
+ */
+
+ textPtr->dInfoPtr->metricEpoch = -1;
+
+ /*
+ * Mark the logical line as being up to date (caution: it isn't yet up
+ * to date, that will happen in TkBTreeAdjustPixelHeight just below).
+ */
+
+ TkBTreeLinePixelEpoch(textPtr, linePtr)
+ = textPtr->dInfoPtr->lineMetricUpdateEpoch;
+ if (TkBTreeLinePixelCount(textPtr, linePtr) != pixelHeight) {
+ changed = 1;
+ }
+
+ if (mergedLines > 0) {
+ int i = mergedLines;
+ TkTextLine *mergedLinePtr;
+
+ /*
+ * Loop over all merged logical lines, marking them up to date
+ * (again, the pixel count setting will actually happen in
+ * TkBTreeAdjustPixelHeight).
+ */
+
+ mergedLinePtr = linePtr;
+ while (i-- > 0) {
+ mergedLinePtr = TkBTreeNextLine(textPtr, mergedLinePtr);
+ TkBTreeLinePixelEpoch(textPtr, mergedLinePtr)
+ = textPtr->dInfoPtr->lineMetricUpdateEpoch;
+ if (TkBTreeLinePixelCount(textPtr, mergedLinePtr) != 0) {
+ changed = 1;
+ }
+ }
+ }
+
+ if (!changed) {
+ /*
+ * If there's nothing to change, then we can already return.
+ */
+
+ return displayLines;
+ }
+ }
+
+ /*
+ * We set the line's height, but the return value is now the height of the
+ * entire widget, which may be used just below for reporting/debugging
+ * purposes.
+ */
+
+ pixelHeight = TkBTreeAdjustPixelHeight(textPtr, linePtr, pixelHeight,
+ mergedLines);
+
+ if (tkTextDebug) {
+ char buffer[2 * TCL_INTEGER_SPACE + 1];
+
+ if (TkBTreeNextLine(textPtr, linePtr) == NULL) {
+ Tcl_Panic("Mustn't ever update line height of last artificial line");
+ }
+
+ sprintf(buffer, "%d %d", TkBTreeLinesTo(textPtr,linePtr), pixelHeight);
+ LOG("tk_textNumPixels", buffer);
+ }
+ if (textPtr->dInfoPtr->scrollbarTimer == NULL) {
+ textPtr->refCount++;
+ textPtr->dInfoPtr->scrollbarTimer = Tcl_CreateTimerHandler(200,
+ AsyncUpdateYScrollbar, textPtr);
+ }
+ return displayLines;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DisplayText --
+ *
+ * This function is invoked as a when-idle handler to update the display.
+ * It only redisplays the parts of the text widget that are out of date.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Information is redrawn on the screen.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DisplayText(
+ ClientData clientData) /* Information about widget. */
+{
+ register TkText *textPtr = clientData;
+ TextDInfo *dInfoPtr = textPtr->dInfoPtr;
+ register DLine *dlPtr;
+ DLine *prevPtr;
+ Pixmap pixmap;
+ int maxHeight, borders;
+ int bottomY = 0; /* Initialization needed only to stop compiler
+ * warnings. */
+ Tcl_Interp *interp;
+
+#ifdef MAC_OSX_TK
+ /*
+ * If drawing is disabled, all we need to do is
+ * clear the REDRAW_PENDING flag.
+ */
+ TkWindow *winPtr = (TkWindow *)(textPtr->tkwin);
+ MacDrawable *macWin = winPtr->privatePtr;
+ if (macWin && (macWin->flags & TK_DO_NOT_DRAW)){
+ dInfoPtr->flags &= ~REDRAW_PENDING;
+ return;
+ }
+#endif
+
+ if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) {
+ /*
+ * The widget has been deleted. Don't do anything.
+ */
+
+ return;
+ }
+
+ interp = textPtr->interp;
+ Tcl_Preserve(interp);
+
+ if (tkTextDebug) {
+ CLEAR("tk_textRelayout");
+ }
+
+ if (!Tk_IsMapped(textPtr->tkwin) || (dInfoPtr->maxX <= dInfoPtr->x)
+ || (dInfoPtr->maxY <= dInfoPtr->y)) {
+ UpdateDisplayInfo(textPtr);
+ dInfoPtr->flags &= ~REDRAW_PENDING;
+ goto doScrollbars;
+ }
+ numRedisplays++;
+ if (tkTextDebug) {
+ CLEAR("tk_textRedraw");
+ }
+
+ /*
+ * Choose a new current item if that is needed (this could cause event
+ * handlers to be invoked, hence the preserve/release calls and the loop,
+ * since the handlers could conceivably necessitate yet another current
+ * item calculation). The tkwin check is because the whole window could go
+ * away in the Tcl_Release call.
+ */
+
+ while (dInfoPtr->flags & REPICK_NEEDED) {
+ textPtr->refCount++;
+ dInfoPtr->flags &= ~REPICK_NEEDED;
+ TkTextPickCurrent(textPtr, &textPtr->pickEvent);
+ if (textPtr->refCount-- <= 1) {
+ ckfree(textPtr);
+ goto end;
+ }
+ if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) {
+ goto end;
+ }
+ }
+
+ /*
+ * First recompute what's supposed to be displayed.
+ */
+
+ UpdateDisplayInfo(textPtr);
+ dInfoPtr->dLinesInvalidated = 0;
+
+ /*
+ * See if it's possible to bring some parts of the screen up-to-date by
+ * scrolling (copying from other parts of the screen). We have to be
+ * particularly careful with the top and bottom lines of the display,
+ * since these may only be partially visible and therefore not helpful for
+ * some scrolling purposes.
+ */
+
+ for (dlPtr = dInfoPtr->dLinePtr; dlPtr != NULL; dlPtr = dlPtr->nextPtr) {
+ register DLine *dlPtr2;
+ int offset, height, y, oldY;
+ TkRegion damageRgn;
+
+ /*
+ * These tests are, in order:
+ *
+ * 1. If the line is already marked as invalid
+ * 2. If the line hasn't moved
+ * 3. If the line overlaps the bottom of the window and we are
+ * scrolling up.
+ * 4. If the line overlaps the top of the window and we are scrolling
+ * down.
+ *
+ * If any of these tests are true, then we can't scroll this line's
+ * part of the display.
+ *
+ * Note that even if tests 3 or 4 aren't true, we may be able to
+ * scroll the line, but we still need to be sure to call embedded
+ * window display procs on top and bottom lines if they have any
+ * portion non-visible (see below).
+ */
+
+ if ((dlPtr->flags & OLD_Y_INVALID)
+ || (dlPtr->y == dlPtr->oldY)
+ || (((dlPtr->oldY + dlPtr->height) > dInfoPtr->maxY)
+ && (dlPtr->y < dlPtr->oldY))
+ || ((dlPtr->oldY < dInfoPtr->y) && (dlPtr->y > dlPtr->oldY))) {
+ continue;
+ }
+
+ /*
+ * This line is already drawn somewhere in the window so it only needs
+ * to be copied to its new location. See if there's a group of lines
+ * that can all be copied together.
+ */
+
+ offset = dlPtr->y - dlPtr->oldY;
+ height = dlPtr->height;
+ y = dlPtr->y;
+ for (dlPtr2 = dlPtr->nextPtr; dlPtr2 != NULL;
+ dlPtr2 = dlPtr2->nextPtr) {
+ if ((dlPtr2->flags & OLD_Y_INVALID)
+ || ((dlPtr2->oldY + offset) != dlPtr2->y)
+ || ((dlPtr2->oldY + dlPtr2->height) > dInfoPtr->maxY)) {
+ break;
+ }
+ height += dlPtr2->height;
+ }
+
+ /*
+ * Reduce the height of the area being copied if necessary to avoid
+ * overwriting the border area.
+ */
+
+ if ((y + height) > dInfoPtr->maxY) {
+ height = dInfoPtr->maxY - y;
+ }
+ oldY = dlPtr->oldY;
+ if (y < dInfoPtr->y) {
+ /*
+ * Adjust if the area being copied is going to overwrite the top
+ * border of the window (so the top line is only half onscreen).
+ */
+
+ int y_off = dInfoPtr->y - dlPtr->y;
+ height -= y_off;
+ oldY += y_off;
+ y = dInfoPtr->y;
+ }
+
+ /*
+ * Update the lines we are going to scroll to show that they have been
+ * copied.
+ */
+
+ while (1) {
+ /*
+ * The DLine already has OLD_Y_INVALID cleared.
+ */
+
+ dlPtr->oldY = dlPtr->y;
+ if (dlPtr->nextPtr == dlPtr2) {
+ break;
+ }
+ dlPtr = dlPtr->nextPtr;
+ }
+ /*
+ * Scan through the lines following the copied ones to see if we are
+ * going to overwrite them with the copy operation. If so, mark them
+ * for redisplay.
+ */
+
+ for ( ; dlPtr2 != NULL; dlPtr2 = dlPtr2->nextPtr) {
+ if ((!(dlPtr2->flags & OLD_Y_INVALID))
+ && ((dlPtr2->oldY + dlPtr2->height) > y)
+ && (dlPtr2->oldY < (y + height))) {
+ dlPtr2->flags |= OLD_Y_INVALID;
+ }
+ }
+
+ /*
+ * Now scroll the lines. This may generate damage which we handle by
+ * calling TextInvalidateRegion to mark the display blocks as stale.
+ */
+
+ damageRgn = TkCreateRegion();
+ if (TkScrollWindow(textPtr->tkwin, dInfoPtr->scrollGC, dInfoPtr->x,
+ oldY, dInfoPtr->maxX-dInfoPtr->x, height, 0, y-oldY,
+ damageRgn)) {
+ TextInvalidateRegion(textPtr, damageRgn);
+ }
+ numCopies++;
+ TkDestroyRegion(damageRgn);
+ }
+
+ /*
+ * Clear the REDRAW_PENDING flag here. This is actually pretty tricky. We
+ * want to wait until *after* doing the scrolling, since that could
+ * generate more areas to redraw and don't want to reschedule a redisplay
+ * for them. On the other hand, we can't wait until after all the
+ * redisplaying, because the act of redisplaying could actually generate
+ * more redisplays (e.g. in the case of a nested window with event
+ * bindings triggered by redisplay).
+ */
+
+ dInfoPtr->flags &= ~REDRAW_PENDING;
+
+ /*
+ * Redraw the borders if that's needed.
+ */
+
+ if (dInfoPtr->flags & REDRAW_BORDERS) {
+ if (tkTextDebug) {
+ LOG("tk_textRedraw", "borders");
+ }
+
+ if (textPtr->tkwin == NULL) {
+ /*
+ * The widget has been deleted. Don't do anything.
+ */
+
+ goto end;
+ }
+
+ Tk_Draw3DRectangle(textPtr->tkwin, Tk_WindowId(textPtr->tkwin),
+ textPtr->border, textPtr->highlightWidth,
+ textPtr->highlightWidth,
+ Tk_Width(textPtr->tkwin) - 2*textPtr->highlightWidth,
+ Tk_Height(textPtr->tkwin) - 2*textPtr->highlightWidth,
+ textPtr->borderWidth, textPtr->relief);
+ if (textPtr->highlightWidth != 0) {
+ GC fgGC, bgGC;
+
+ bgGC = Tk_GCForColor(textPtr->highlightBgColorPtr,
+ Tk_WindowId(textPtr->tkwin));
+ if (textPtr->flags & GOT_FOCUS) {
+ fgGC = Tk_GCForColor(textPtr->highlightColorPtr,
+ Tk_WindowId(textPtr->tkwin));
+ TkpDrawHighlightBorder(textPtr->tkwin, fgGC, bgGC,
+ textPtr->highlightWidth, Tk_WindowId(textPtr->tkwin));
+ } else {
+ TkpDrawHighlightBorder(textPtr->tkwin, bgGC, bgGC,
+ textPtr->highlightWidth, Tk_WindowId(textPtr->tkwin));
+ }
+ }
+ borders = textPtr->borderWidth + textPtr->highlightWidth;
+ if (textPtr->padY > 0) {
+ Tk_Fill3DRectangle(textPtr->tkwin, Tk_WindowId(textPtr->tkwin),
+ textPtr->border, borders, borders,
+ Tk_Width(textPtr->tkwin) - 2*borders, textPtr->padY,
+ 0, TK_RELIEF_FLAT);
+ Tk_Fill3DRectangle(textPtr->tkwin, Tk_WindowId(textPtr->tkwin),
+ textPtr->border, borders,
+ Tk_Height(textPtr->tkwin) - borders - textPtr->padY,
+ Tk_Width(textPtr->tkwin) - 2*borders,
+ textPtr->padY, 0, TK_RELIEF_FLAT);
+ }
+ if (textPtr->padX > 0) {
+ Tk_Fill3DRectangle(textPtr->tkwin, Tk_WindowId(textPtr->tkwin),
+ textPtr->border, borders, borders + textPtr->padY,
+ textPtr->padX,
+ Tk_Height(textPtr->tkwin) - 2*borders -2*textPtr->padY,
+ 0, TK_RELIEF_FLAT);
+ Tk_Fill3DRectangle(textPtr->tkwin, Tk_WindowId(textPtr->tkwin),
+ textPtr->border,
+ Tk_Width(textPtr->tkwin) - borders - textPtr->padX,
+ borders + textPtr->padY, textPtr->padX,
+ Tk_Height(textPtr->tkwin) - 2*borders -2*textPtr->padY,
+ 0, TK_RELIEF_FLAT);
+ }
+ dInfoPtr->flags &= ~REDRAW_BORDERS;
+ }
+
+ /*
+ * Now we have to redraw the lines that couldn't be updated by scrolling.
+ * First, compute the height of the largest line and allocate an off-
+ * screen pixmap to use for double-buffered displays.
+ */
+
+ maxHeight = -1;
+ for (dlPtr = dInfoPtr->dLinePtr; dlPtr != NULL;
+ dlPtr = dlPtr->nextPtr) {
+ if ((dlPtr->height > maxHeight) &&
+ ((dlPtr->flags&OLD_Y_INVALID) || (dlPtr->oldY != dlPtr->y))) {
+ maxHeight = dlPtr->height;
+ }
+ bottomY = dlPtr->y + dlPtr->height;
+ }
+
+ /*
+ * There used to be a line here which restricted 'maxHeight' to be no
+ * larger than 'dInfoPtr->maxY', but this is incorrect for the case where
+ * individual lines may be taller than the widget _and_ we have smooth
+ * scrolling. What we can do is restrict maxHeight to be no larger than
+ * 'dInfoPtr->maxY + dInfoPtr->topPixelOffset'.
+ */
+
+ if (maxHeight > (dInfoPtr->maxY + dInfoPtr->topPixelOffset)) {
+ maxHeight = (dInfoPtr->maxY + dInfoPtr->topPixelOffset);
+ }
+
+ if (maxHeight > 0) {
+#ifndef TK_NO_DOUBLE_BUFFERING
+ pixmap = Tk_GetPixmap(Tk_Display(textPtr->tkwin),
+ Tk_WindowId(textPtr->tkwin), Tk_Width(textPtr->tkwin),
+ maxHeight, Tk_Depth(textPtr->tkwin));
+#else
+ pixmap = Tk_WindowId(textPtr->tkwin);
+#endif /* TK_NO_DOUBLE_BUFFERING */
+ for (prevPtr = NULL, dlPtr = textPtr->dInfoPtr->dLinePtr;
+ (dlPtr != NULL) && (dlPtr->y < dInfoPtr->maxY);
+ prevPtr = dlPtr, dlPtr = dlPtr->nextPtr) {
+ if (dlPtr->chunkPtr == NULL) {
+ continue;
+ }
+ if ((dlPtr->flags & OLD_Y_INVALID) || dlPtr->oldY != dlPtr->y) {
+ if (tkTextDebug) {
+ char string[TK_POS_CHARS];
+
+ TkTextPrintIndex(textPtr, &dlPtr->index, string);
+ LOG("tk_textRedraw", string);
+ }
+ DisplayDLine(textPtr, dlPtr, prevPtr, pixmap);
+ if (dInfoPtr->dLinesInvalidated) {
+#ifndef TK_NO_DOUBLE_BUFFERING
+ Tk_FreePixmap(Tk_Display(textPtr->tkwin), pixmap);
+#endif /* TK_NO_DOUBLE_BUFFERING */
+ return;
+ }
+ dlPtr->oldY = dlPtr->y;
+ dlPtr->flags &= ~(NEW_LAYOUT | OLD_Y_INVALID);
+#ifdef MAC_OSX_TK
+ } else if (dlPtr->chunkPtr != NULL) {
+ /*
+ * On macOS we need to redisplay all embedded windows which
+ * were moved by the call to TkScrollWindows above. This is
+ * not necessary on Unix or Windows because XScrollWindow will
+ * have included the bounding rectangles of all of these
+ * windows in the damage region. The macosx implementation of
+ * TkScrollWindow does not do this. It simply generates a
+ * damage region which is the scroll source rectangle minus
+ * the scroll destination rectangle. This is because there is
+ * no efficient process available for iterating through the
+ * subwindows which meet the scrolled area. (On Unix this is
+ * handled by GraphicsExpose events generated by XCopyArea and
+ * on Windows by ScrollWindowEx. On macOS the low level
+ * scrolling is accomplished by calling [view scrollRect:by:].
+ * This method does not provide any damage information and, in
+ * any case, could not be aware of Tk windows which were not
+ * based on NSView objects.
+ *
+ * On the other hand, this loop is already iterating through
+ * all embedded windows which could possibly have been moved
+ * by the scrolling. So it is as efficient to redisplay them
+ * here as it would have been if they had been redisplayed by
+ * the call to TextInvalidateRegion above.
+ */
+#else
+ } else if (dlPtr->chunkPtr != NULL && ((dlPtr->y < 0)
+ || (dlPtr->y + dlPtr->height > dInfoPtr->maxY))) {
+ /*
+ * On platforms other than the Mac:
+ *
+ * It's the first or last DLine which are also overlapping the
+ * top or bottom of the window, but we decided above it wasn't
+ * necessary to display them (we were able to update them by
+ * scrolling). This is fine, except that if the lines contain
+ * any embedded windows, we must still call the display proc
+ * on them because they might need to be unmapped or they
+ * might need to be moved to reflect their new position.
+ * Otherwise, everything else moves, but the embedded window
+ * doesn't!
+ *
+ * So, we loop through all the chunks, calling the display
+ * proc of embedded windows only.
+ */
+#endif
+ register TkTextDispChunk *chunkPtr;
+
+ for (chunkPtr = dlPtr->chunkPtr; (chunkPtr != NULL);
+ chunkPtr = chunkPtr->nextPtr) {
+ int x;
+ if (chunkPtr->displayProc != TkTextEmbWinDisplayProc) {
+ continue;
+ }
+ x = chunkPtr->x + dInfoPtr->x - dInfoPtr->curXPixelOffset;
+ if ((x + chunkPtr->width <= 0) || (x >= dInfoPtr->maxX)) {
+ /*
+ * Note: we have to call the displayProc even for
+ * chunks that are off-screen. This is needed, for
+ * example, so that embedded windows can be unmapped
+ * in this case. Display the chunk at a coordinate
+ * that can be clearly identified by the displayProc
+ * as being off-screen to the left (the displayProc
+ * may not be able to tell if something is off to the
+ * right).
+ */
+
+ x = -chunkPtr->width;
+ }
+ if (tkTextDebug) {
+ char string[TK_POS_CHARS];
+
+ TkTextPrintIndex(textPtr, &dlPtr->index, string);
+ LOG("tk_textEmbWinDisplay", string);
+ }
+ TkTextEmbWinDisplayProc(textPtr, chunkPtr, x,
+ dlPtr->spaceAbove,
+ dlPtr->height-dlPtr->spaceAbove-dlPtr->spaceBelow,
+ dlPtr->baseline - dlPtr->spaceAbove, NULL,
+ None, dlPtr->y + dlPtr->spaceAbove);
+ }
+ }
+ }
+#ifndef TK_NO_DOUBLE_BUFFERING
+ Tk_FreePixmap(Tk_Display(textPtr->tkwin), pixmap);
+#endif /* TK_NO_DOUBLE_BUFFERING */
+ }
+
+ /*
+ * See if we need to refresh the part of the window below the last line of
+ * text (if there is any such area). Refresh the padding area on the left
+ * too, since the insertion cursor might have been displayed there
+ * previously).
+ */
+
+ if (dInfoPtr->topOfEof > dInfoPtr->maxY) {
+ dInfoPtr->topOfEof = dInfoPtr->maxY;
+ }
+ if (bottomY < dInfoPtr->topOfEof) {
+ if (tkTextDebug) {
+ LOG("tk_textRedraw", "eof");
+ }
+
+ if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) {
+ /*
+ * The widget has been deleted. Don't do anything.
+ */
+
+ goto end;
+ }
+
+ Tk_Fill3DRectangle(textPtr->tkwin, Tk_WindowId(textPtr->tkwin),
+ textPtr->border, dInfoPtr->x - textPtr->padX, bottomY,
+ dInfoPtr->maxX - (dInfoPtr->x - textPtr->padX),
+ dInfoPtr->topOfEof-bottomY, 0, TK_RELIEF_FLAT);
+ }
+ dInfoPtr->topOfEof = bottomY;
+
+ /*
+ * Update the vertical scrollbar, if there is one. Note: it's important to
+ * clear REDRAW_PENDING here, just in case the scroll function does
+ * something that requires redisplay.
+ */
+
+ doScrollbars:
+ if (textPtr->flags & UPDATE_SCROLLBARS) {
+ textPtr->flags &= ~UPDATE_SCROLLBARS;
+ if (textPtr->yScrollCmd != NULL) {
+ GetYView(textPtr->interp, textPtr, 1);
+ }
+
+ if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) {
+ /*
+ * The widget has been deleted. Don't do anything.
+ */
+
+ goto end;
+ }
+
+ /*
+ * Update the horizontal scrollbar, if any.
+ */
+
+ if (textPtr->xScrollCmd != NULL) {
+ GetXView(textPtr->interp, textPtr, 1);
+ }
+ }
+
+ end:
+ Tcl_Release(interp);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkTextEventuallyRepick --
+ *
+ * This function is invoked whenever something happens that could change
+ * the current character or the tags associated with it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A repick is scheduled as an idle handler.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkTextEventuallyRepick(
+ TkText *textPtr) /* Widget record for text widget. */
+{
+ TextDInfo *dInfoPtr = textPtr->dInfoPtr;
+
+ dInfoPtr->flags |= REPICK_NEEDED;
+ if (!(dInfoPtr->flags & REDRAW_PENDING)) {
+ dInfoPtr->flags |= REDRAW_PENDING;
+ Tcl_DoWhenIdle(DisplayText, textPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkTextRedrawRegion --
+ *
+ * This function is invoked to schedule a redisplay for a given region of
+ * a text widget. The redisplay itself may not occur immediately: it's
+ * scheduled as a when-idle handler.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Information will eventually be redrawn on the screen.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkTextRedrawRegion(
+ TkText *textPtr, /* Widget record for text widget. */
+ int x, int y, /* Coordinates of upper-left corner of area to
+ * be redrawn, in pixels relative to textPtr's
+ * window. */
+ int width, int height) /* Width and height of area to be redrawn. */
+{
+ TextDInfo *dInfoPtr = textPtr->dInfoPtr;
+ TkRegion damageRgn = TkCreateRegion();
+ XRectangle rect;
+
+ rect.x = x;
+ rect.y = y;
+ rect.width = width;
+ rect.height = height;
+ TkUnionRectWithRegion(&rect, damageRgn, damageRgn);
+
+ TextInvalidateRegion(textPtr, damageRgn);
+
+ if (!(dInfoPtr->flags & REDRAW_PENDING)) {
+ dInfoPtr->flags |= REDRAW_PENDING;
+ Tcl_DoWhenIdle(DisplayText, textPtr);
+ }
+ TkDestroyRegion(damageRgn);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TextInvalidateRegion --
+ *
+ * Mark a region of text as invalid.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Updates the display information for the text widget.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+TextInvalidateRegion(
+ TkText *textPtr, /* Widget record for text widget. */
+ TkRegion region) /* Region of area to redraw. */
+{
+ register DLine *dlPtr;
+ TextDInfo *dInfoPtr = textPtr->dInfoPtr;
+ int maxY, inset;
+ XRectangle rect;
+
+ /*
+ * Find all lines that overlap the given region and mark them for
+ * redisplay.
+ */
+
+ TkClipBox(region, &rect);
+ maxY = rect.y + rect.height;
+ for (dlPtr = dInfoPtr->dLinePtr; dlPtr != NULL;
+ dlPtr = dlPtr->nextPtr) {
+ if ((!(dlPtr->flags & OLD_Y_INVALID))
+ && (TkRectInRegion(region, rect.x, dlPtr->y,
+ rect.width, (unsigned int) dlPtr->height) != RectangleOut)) {
+ dlPtr->flags |= OLD_Y_INVALID;
+ }
+ }
+ if (dInfoPtr->topOfEof < maxY) {
+ dInfoPtr->topOfEof = maxY;
+ }
+
+ /*
+ * Schedule the redisplay operation if there isn't one already scheduled.
+ */
+
+ inset = textPtr->borderWidth + textPtr->highlightWidth;
+ if ((rect.x < (inset + textPtr->padX))
+ || (rect.y < (inset + textPtr->padY))
+ || ((int) (rect.x + rect.width) > (Tk_Width(textPtr->tkwin)
+ - inset - textPtr->padX))
+ || (maxY > (Tk_Height(textPtr->tkwin) - inset - textPtr->padY))) {
+ dInfoPtr->flags |= REDRAW_BORDERS;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkTextChanged, TextChanged --
+ *
+ * This function is invoked when info in a text widget is about to be
+ * modified in a way that changes how it is displayed (e.g. characters
+ * were inserted or deleted, or tag information was changed). This
+ * function must be called *before* a change is made, so that indexes in
+ * the display information are still valid.
+ *
+ * Note: if the range of indices may change geometry as well as simply
+ * requiring redisplay, then the caller should also call
+ * TkTextInvalidateLineMetrics.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The range of character between index1Ptr (inclusive) and index2Ptr
+ * (exclusive) will be redisplayed at some point in the future (the
+ * actual redisplay is scheduled as a when-idle handler).
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkTextChanged(
+ TkSharedText *sharedTextPtr,/* Shared widget section, or NULL. */
+ TkText *textPtr, /* Widget record for text widget, or NULL. */
+ const TkTextIndex*index1Ptr,/* Index of first character to redisplay. */
+ const TkTextIndex*index2Ptr)/* Index of character just after last one to
+ * redisplay. */
+{
+ if (sharedTextPtr == NULL) {
+ TextChanged(textPtr, index1Ptr, index2Ptr);
+ } else {
+ textPtr = sharedTextPtr->peers;
+ while (textPtr != NULL) {
+ TextChanged(textPtr, index1Ptr, index2Ptr);
+ textPtr = textPtr->next;
+ }
+ }
+}
+
+static void
+TextChanged(
+ TkText *textPtr, /* Widget record for text widget, or NULL. */
+ const TkTextIndex*index1Ptr,/* Index of first character to redisplay. */
+ const TkTextIndex*index2Ptr)/* Index of character just after last one to
+ * redisplay. */
+{
+ TextDInfo *dInfoPtr = textPtr->dInfoPtr;
+ DLine *firstPtr, *lastPtr;
+ TkTextIndex rounded;
+ TkTextLine *linePtr;
+ int notBegin;
+
+ /*
+ * Schedule both a redisplay and a recomputation of display information.
+ * It's done here rather than the end of the function for two reasons:
+ *
+ * 1. If there are no display lines to update we'll want to return
+ * immediately, well before the end of the function.
+ * 2. It's important to arrange for the redisplay BEFORE calling
+ * FreeDLines. The reason for this is subtle and has to do with
+ * embedded windows. The chunk delete function for an embedded window
+ * will schedule an idle handler to unmap the window. However, we want
+ * the idle handler for redisplay to be called first, so that it can
+ * put the embedded window back on the screen again (if appropriate).
+ * This will prevent the window from ever being unmapped, and thereby
+ * avoid flashing.
+ */
+
+ if (!(dInfoPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DisplayText, textPtr);
+ }
+ dInfoPtr->flags |= REDRAW_PENDING|DINFO_OUT_OF_DATE|REPICK_NEEDED;
+
+ /*
+ * Find the DLines corresponding to index1Ptr and index2Ptr. There is one
+ * tricky thing here, which is that we have to relayout in units of whole
+ * text lines: This is necessary because the indices stored in the display
+ * lines will no longer be valid. It's also needed because any edit could
+ * change the way lines wrap.
+ * To relayout in units of whole text (logical) lines, round index1Ptr
+ * back to the beginning of its text line (or, if this line start is
+ * elided, to the beginning of the text line that starts the display line
+ * it is included in), and include all the display lines after index2Ptr,
+ * up to the end of its text line (or, if this line end is elided, up to
+ * the end of the first non elided text line after this line end).
+ */
+
+ rounded = *index1Ptr;
+ rounded.byteIndex = 0;
+ notBegin = 0;
+ while (!IsStartOfNotMergedLine(textPtr, &rounded) && notBegin) {
+ notBegin = !TkTextIndexBackBytes(textPtr, &rounded, 1, &rounded);
+ rounded.byteIndex = 0;
+ }
+
+ /*
+ * 'rounded' now points to the start of a display line as well as the
+ * real (non elided) start of a logical line, and this index is the
+ * closest before index1Ptr.
+ */
+
+ firstPtr = FindDLine(textPtr, dInfoPtr->dLinePtr, &rounded);
+
+ if (firstPtr == NULL) {
+ /*
+ * index1Ptr pertains to no display line, i.e this index is after
+ * the last display line. Since index2Ptr is after index1Ptr, there
+ * is no display line to free/redisplay and we can return early.
+ */
+
+ return;
+ }
+
+ rounded = *index2Ptr;
+ linePtr = index2Ptr->linePtr;
+ do {
+ linePtr = TkBTreeNextLine(textPtr, linePtr);
+ if (linePtr == NULL) {
+ break;
+ }
+ rounded.linePtr = linePtr;
+ rounded.byteIndex = 0;
+ } while (!IsStartOfNotMergedLine(textPtr, &rounded));
+
+ if (linePtr == NULL) {
+ lastPtr = NULL;
+ } else {
+ /*
+ * 'rounded' now points to the start of a display line as well as the
+ * start of a logical line not merged with its previous line, and
+ * this index is the closest after index2Ptr.
+ */
+
+ lastPtr = FindDLine(textPtr, dInfoPtr->dLinePtr, &rounded);
+
+ /*
+ * At least one display line is supposed to change. This makes the
+ * redisplay OK in case the display line we expect to get here was
+ * unlinked by a previous call to TkTextChanged and the text widget
+ * did not update before reaching this point. This happens for
+ * instance when moving the cursor up one line.
+ * Note that lastPtr != NULL here, otherwise we would have returned
+ * earlier when we tested for firstPtr being NULL.
+ */
+
+ if (lastPtr == firstPtr) {
+ lastPtr = lastPtr->nextPtr;
+ }
+ }
+
+ /*
+ * Delete all the DLines from firstPtr up to but not including lastPtr.
+ */
+
+ FreeDLines(textPtr, firstPtr, lastPtr, DLINE_UNLINK);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkTextRedrawTag, TextRedrawTag --
+ *
+ * This function is invoked to request a redraw of all characters in a
+ * given range that have a particular tag on or off. It's called, for
+ * example, when tag options change.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Information on the screen may be redrawn, and the layout of the screen
+ * may change.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkTextRedrawTag(
+ TkSharedText *sharedTextPtr,/* Shared widget section, or NULL. */
+ TkText *textPtr, /* Widget record for text widget. */
+ TkTextIndex *index1Ptr, /* First character in range to consider for
+ * redisplay. NULL means start at beginning of
+ * text. */
+ TkTextIndex *index2Ptr, /* Character just after last one to consider
+ * for redisplay. NULL means process all the
+ * characters in the text. */
+ TkTextTag *tagPtr, /* Information about tag. */
+ int withTag) /* 1 means redraw characters that have the
+ * tag, 0 means redraw those without. */
+{
+ if (sharedTextPtr == NULL) {
+ TextRedrawTag(textPtr, index1Ptr, index2Ptr, tagPtr, withTag);
+ } else {
+ textPtr = sharedTextPtr->peers;
+ while (textPtr != NULL) {
+ TextRedrawTag(textPtr, index1Ptr, index2Ptr, tagPtr, withTag);
+ textPtr = textPtr->next;
+ }
+ }
+}
+
+static void
+TextRedrawTag(
+ TkText *textPtr, /* Widget record for text widget. */
+ TkTextIndex *index1Ptr, /* First character in range to consider for
+ * redisplay. NULL means start at beginning of
+ * text. */
+ TkTextIndex *index2Ptr, /* Character just after last one to consider
+ * for redisplay. NULL means process all the
+ * characters in the text. */
+ TkTextTag *tagPtr, /* Information about tag. */
+ int withTag) /* 1 means redraw characters that have the
+ * tag, 0 means redraw those without. */
+{
+ register DLine *dlPtr;
+ DLine *endPtr;
+ int tagOn;
+ TkTextSearch search;
+ TextDInfo *dInfoPtr = textPtr->dInfoPtr;
+ TkTextIndex *curIndexPtr;
+ TkTextIndex endOfText, *endIndexPtr;
+
+ /*
+ * Invalidate the pixel calculation of all lines in the given range. This
+ * may be a bit over-aggressive, so we could consider more subtle
+ * techniques here in the future. In particular, when we create a tag for
+ * the first time with '.t tag configure foo -font "Arial 20"', say, even
+ * though that obviously can't apply to anything at all (the tag didn't
+ * exist a moment ago), we invalidate every single line in the widget.
+ */
+
+ if (tagPtr->affectsDisplayGeometry) {
+ TkTextLine *startLine, *endLine;
+ int lineCount;
+
+ if (index2Ptr == NULL) {
+ endLine = NULL;
+ lineCount = TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr);
+ } else {
+ endLine = index2Ptr->linePtr;
+ lineCount = TkBTreeLinesTo(textPtr, endLine);
+ }
+ if (index1Ptr == NULL) {
+ startLine = NULL;
+ } else {
+ startLine = index1Ptr->linePtr;
+ lineCount -= TkBTreeLinesTo(textPtr, startLine);
+ }
+ TkTextInvalidateLineMetrics(NULL, textPtr, startLine, lineCount,
+ TK_TEXT_INVALIDATE_ONLY);
+ }
+
+ /*
+ * Round up the starting position if it's before the first line visible on
+ * the screen (we only care about what's on the screen).
+ */
+
+ dlPtr = dInfoPtr->dLinePtr;
+ if (dlPtr == NULL) {
+ return;
+ }
+ if ((index1Ptr == NULL) || (TkTextIndexCmp(&dlPtr->index, index1Ptr)>0)) {
+ index1Ptr = &dlPtr->index;
+ }
+
+ /*
+ * Set the stopping position if it wasn't specified.
+ */
+
+ if (index2Ptr == NULL) {
+ int lastLine = TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr);
+
+ index2Ptr = TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,
+ lastLine, 0, &endOfText);
+ }
+
+ /*
+ * Initialize a search through all transitions on the tag, starting with
+ * the first transition where the tag's current state is different from
+ * what it will eventually be.
+ */
+
+ TkBTreeStartSearch(index1Ptr, index2Ptr, tagPtr, &search);
+
+ /*
+ * Make our own curIndex because at this point search.curIndex may not
+ * equal index1Ptr->curIndex in the case the first tag toggle comes after
+ * index1Ptr (See the use of FindTagStart in TkBTreeStartSearch).
+ */
+
+ curIndexPtr = index1Ptr;
+ tagOn = TkBTreeCharTagged(index1Ptr, tagPtr);
+ if (tagOn != withTag) {
+ if (!TkBTreeNextTag(&search)) {
+ return;
+ }
+ curIndexPtr = &search.curIndex;
+ }
+
+ /*
+ * Schedule a redisplay and layout recalculation if they aren't already
+ * pending. This has to be done before calling FreeDLines, for the reason
+ * given in TkTextChanged.
+ */
+
+ if (!(dInfoPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DisplayText, textPtr);
+ }
+ dInfoPtr->flags |= REDRAW_PENDING|DINFO_OUT_OF_DATE|REPICK_NEEDED;
+
+ /*
+ * Each loop through the loop below is for one range of characters where
+ * the tag's current state is different than its eventual state. At the
+ * top of the loop, search contains information about the first character
+ * in the range.
+ */
+
+ while (1) {
+ /*
+ * Find the first DLine structure in the range. Note: if the desired
+ * character isn't the first in its text line, then look for the
+ * character just before it instead. This is needed to handle the case
+ * where the first character of a wrapped display line just got
+ * smaller, so that it now fits on the line before: need to relayout
+ * the line containing the previous character.
+ */
+
+ if (IsStartOfNotMergedLine(textPtr, curIndexPtr)) {
+ dlPtr = FindDLine(textPtr, dlPtr, curIndexPtr);
+ } else {
+ TkTextIndex tmp = *curIndexPtr;
+
+ TkTextIndexBackBytes(textPtr, &tmp, 1, &tmp);
+ dlPtr = FindDLine(textPtr, dlPtr, &tmp);
+ }
+ if (dlPtr == NULL) {
+ break;
+ }
+
+ /*
+ * Find the first DLine structure that's past the end of the range.
+ */
+
+ if (!TkBTreeNextTag(&search)) {
+ endIndexPtr = index2Ptr;
+ } else {
+ curIndexPtr = &search.curIndex;
+ endIndexPtr = curIndexPtr;
+ }
+ endPtr = FindDLine(textPtr, dlPtr, endIndexPtr);
+ if ((endPtr != NULL)
+ && (TkTextIndexCmp(&endPtr->index,endIndexPtr) < 0)) {
+ endPtr = endPtr->nextPtr;
+ }
+
+ /*
+ * Delete all of the display lines in the range, so that they'll be
+ * re-layed out and redrawn.
+ */
+
+ FreeDLines(textPtr, dlPtr, endPtr, DLINE_UNLINK);
+ dlPtr = endPtr;
+
+ /*
+ * Find the first text line in the next range.
+ */
+
+ if (!TkBTreeNextTag(&search)) {
+ break;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkTextRelayoutWindow --
+ *
+ * This function is called when something has happened that invalidates
+ * the whole layout of characters on the screen, such as a change in a
+ * configuration option for the overall text widget or a change in the
+ * window size. It causes all display information to be recomputed and
+ * the window to be redrawn.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * All the display information will be recomputed for the window and the
+ * window will be redrawn.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkTextRelayoutWindow(
+ TkText *textPtr, /* Widget record for text widget. */
+ int mask) /* OR'd collection of bits showing what has
+ * changed. */
+{
+ TextDInfo *dInfoPtr = textPtr->dInfoPtr;
+ GC newGC;
+ XGCValues gcValues;
+ Bool inSync = 1;
+
+ /*
+ * Schedule the window redisplay. See TkTextChanged for the reason why
+ * this has to be done before any calls to FreeDLines.
+ */
+
+ if (!(dInfoPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DisplayText, textPtr);
+ inSync = 0;
+ }
+ dInfoPtr->flags |= REDRAW_PENDING|REDRAW_BORDERS|DINFO_OUT_OF_DATE
+ |REPICK_NEEDED;
+
+ /*
+ * (Re-)create the graphics context for drawing the traversal highlight.
+ */
+
+ gcValues.graphics_exposures = False;
+ newGC = Tk_GetGC(textPtr->tkwin, GCGraphicsExposures, &gcValues);
+ if (dInfoPtr->copyGC != NULL) {
+ Tk_FreeGC(textPtr->display, dInfoPtr->copyGC);
+ }
+ dInfoPtr->copyGC = newGC;
+
+ /*
+ * Throw away all the current layout information.
+ */
+
+ FreeDLines(textPtr, dInfoPtr->dLinePtr, NULL, DLINE_UNLINK);
+ dInfoPtr->dLinePtr = NULL;
+
+ /*
+ * Recompute some overall things for the layout. Even if the window gets
+ * very small, pretend that there's at least one pixel of drawing space in
+ * it.
+ */
+
+ if (textPtr->highlightWidth < 0) {
+ textPtr->highlightWidth = 0;
+ }
+ dInfoPtr->x = textPtr->highlightWidth + textPtr->borderWidth
+ + textPtr->padX;
+ dInfoPtr->y = textPtr->highlightWidth + textPtr->borderWidth
+ + textPtr->padY;
+ dInfoPtr->maxX = Tk_Width(textPtr->tkwin) - textPtr->highlightWidth
+ - textPtr->borderWidth - textPtr->padX;
+ if (dInfoPtr->maxX <= dInfoPtr->x) {
+ dInfoPtr->maxX = dInfoPtr->x + 1;
+ }
+
+ /*
+ * This is the only place where dInfoPtr->maxY is set.
+ */
+
+ dInfoPtr->maxY = Tk_Height(textPtr->tkwin) - textPtr->highlightWidth
+ - textPtr->borderWidth - textPtr->padY;
+ if (dInfoPtr->maxY <= dInfoPtr->y) {
+ dInfoPtr->maxY = dInfoPtr->y + 1;
+ }
+ dInfoPtr->topOfEof = dInfoPtr->maxY;
+
+ /*
+ * If the upper-left character isn't the first in a line, recompute it.
+ * This is necessary because a change in the window's size or options
+ * could change the way lines wrap.
+ */
+
+ if (!IsStartOfNotMergedLine(textPtr, &textPtr->topIndex)) {
+ TkTextFindDisplayLineEnd(textPtr, &textPtr->topIndex, 0, NULL);
+ }
+
+ /*
+ * Invalidate cached scrollbar positions, so that scrollbars sliders will
+ * be udpated.
+ */
+
+ dInfoPtr->xScrollFirst = dInfoPtr->xScrollLast = -1;
+ dInfoPtr->yScrollFirst = dInfoPtr->yScrollLast = -1;
+
+ if (mask & TK_TEXT_LINE_GEOMETRY) {
+
+ /*
+ * Set up line metric recalculation.
+ *
+ * Avoid the special zero value, since that is used to mark individual
+ * lines as being out of date.
+ */
+
+ if ((++dInfoPtr->lineMetricUpdateEpoch) == 0) {
+ dInfoPtr->lineMetricUpdateEpoch++;
+ }
+
+ dInfoPtr->currentMetricUpdateLine = -1;
+
+ /*
+ * Also cancel any partial line-height calculations (for long-wrapped
+ * lines) in progress.
+ */
+
+ dInfoPtr->metricEpoch = -1;
+
+ if (dInfoPtr->lineUpdateTimer == NULL) {
+ textPtr->refCount++;
+ dInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(1,
+ AsyncUpdateLineMetrics, textPtr);
+ inSync = 0;
+ }
+
+ GenerateWidgetViewSyncEvent(textPtr, inSync);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkTextSetYView --
+ *
+ * This function is called to specify what lines are to be displayed in a
+ * text widget.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The display will (eventually) be updated so that the position given by
+ * "indexPtr" is visible on the screen at the position determined by
+ * "pickPlace".
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkTextSetYView(
+ TkText *textPtr, /* Widget record for text widget. */
+ TkTextIndex *indexPtr, /* Position that is to appear somewhere in the
+ * view. */
+ int pickPlace) /* 0 means the given index must appear exactly
+ * at the top of the screen. TK_TEXT_PICKPLACE
+ * (-1) means we get to pick where it appears:
+ * minimize screen motion or else display line
+ * at center of screen. TK_TEXT_NOPIXELADJUST
+ * (-2) indicates to make the given index the
+ * top line, but if it is already the top
+ * line, don't nudge it up or down by a few
+ * pixels just to make sure it is entirely
+ * displayed. Positive numbers indicate the
+ * number of pixels of the index's line which
+ * are to be off the top of the screen. */
+{
+ TextDInfo *dInfoPtr = textPtr->dInfoPtr;
+ register DLine *dlPtr;
+ int bottomY, close, lineIndex;
+ TkTextIndex tmpIndex, rounded;
+ int lineHeight;
+
+ /*
+ * If the specified position is the extra line at the end of the text,
+ * round it back to the last real line.
+ */
+
+ lineIndex = TkBTreeLinesTo(textPtr, indexPtr->linePtr);
+ if (lineIndex == TkBTreeNumLines(indexPtr->tree, textPtr)) {
+ TkTextIndexBackChars(textPtr, indexPtr, 1, &rounded, COUNT_INDICES);
+ indexPtr = &rounded;
+ }
+
+ if (pickPlace == TK_TEXT_NOPIXELADJUST) {
+ if (textPtr->topIndex.linePtr == indexPtr->linePtr
+ && textPtr->topIndex.byteIndex == indexPtr->byteIndex) {
+ pickPlace = dInfoPtr->topPixelOffset;
+ } else {
+ pickPlace = 0;
+ }
+ }
+
+ if (pickPlace != TK_TEXT_PICKPLACE) {
+ /*
+ * The specified position must go at the top of the screen. Just leave
+ * all the DLine's alone: we may be able to reuse some of the
+ * information that's currently on the screen without redisplaying it
+ * all.
+ */
+
+ textPtr->topIndex = *indexPtr;
+ if (!IsStartOfNotMergedLine(textPtr, indexPtr)) {
+ TkTextFindDisplayLineEnd(textPtr, &textPtr->topIndex, 0, NULL);
+ }
+ dInfoPtr->newTopPixelOffset = pickPlace;
+ goto scheduleUpdate;
+ }
+
+ /*
+ * We have to pick where to display the index. First, bring the display
+ * information up to date and see if the index will be completely visible
+ * in the current screen configuration. If so then there's nothing to do.
+ */
+
+ if (dInfoPtr->flags & DINFO_OUT_OF_DATE) {
+ UpdateDisplayInfo(textPtr);
+ }
+ dlPtr = FindDLine(textPtr, dInfoPtr->dLinePtr, indexPtr);
+ if (dlPtr != NULL) {
+ if ((dlPtr->y + dlPtr->height) > dInfoPtr->maxY) {
+ /*
+ * Part of the line hangs off the bottom of the screen; pretend
+ * the whole line is off-screen.
+ */
+
+ dlPtr = NULL;
+ } else {
+ if (TkTextIndexCmp(&dlPtr->index, indexPtr) <= 0) {
+ if (dInfoPtr->dLinePtr == dlPtr && dInfoPtr->topPixelOffset != 0) {
+ /*
+ * It is on the top line, but that line is hanging off the top
+ * of the screen. Change the top overlap to zero and update.
+ */
+
+ dInfoPtr->newTopPixelOffset = 0;
+ goto scheduleUpdate;
+ }
+ /*
+ * The line is already on screen, with no need to scroll.
+ */
+ return;
+ }
+ }
+ }
+
+ /*
+ * The desired line isn't already on-screen. Figure out what it means to
+ * be "close" to the top or bottom of the screen. Close means within 1/3
+ * of the screen height or within three lines, whichever is greater.
+ *
+ * If the line is not close, place it in the center of the window.
+ */
+
+ tmpIndex = *indexPtr;
+ TkTextFindDisplayLineEnd(textPtr, &tmpIndex, 0, NULL);
+ lineHeight = CalculateDisplayLineHeight(textPtr, &tmpIndex, NULL, NULL);
+
+ /*
+ * It would be better if 'bottomY' were calculated using the actual height
+ * of the given line, not 'textPtr->charHeight'.
+ */
+
+ bottomY = (dInfoPtr->y + dInfoPtr->maxY + lineHeight)/2;
+ close = (dInfoPtr->maxY - dInfoPtr->y)/3;
+ if (close < 3*textPtr->charHeight) {
+ close = 3*textPtr->charHeight;
+ }
+ if (dlPtr != NULL) {
+ int overlap;
+
+ /*
+ * The desired line is above the top of screen. If it is "close" to
+ * the top of the window then make it the top line on the screen.
+ * MeasureUp counts from the bottom of the given index upwards, so we
+ * add an extra half line to be sure we count far enough.
+ */
+
+ MeasureUp(textPtr, &textPtr->topIndex, close + textPtr->charHeight/2,
+ &tmpIndex, &overlap);
+ if (TkTextIndexCmp(&tmpIndex, indexPtr) <= 0) {
+ textPtr->topIndex = *indexPtr;
+ TkTextFindDisplayLineEnd(textPtr, &textPtr->topIndex, 0, NULL);
+ dInfoPtr->newTopPixelOffset = 0;
+ goto scheduleUpdate;
+ }
+ } else {
+ int overlap;
+
+ /*
+ * The desired line is below the bottom of the screen. If it is
+ * "close" to the bottom of the screen then position it at the bottom
+ * of the screen.
+ */
+
+ MeasureUp(textPtr, indexPtr, close + lineHeight
+ - textPtr->charHeight/2, &tmpIndex, &overlap);
+ if (FindDLine(textPtr, dInfoPtr->dLinePtr, &tmpIndex) != NULL) {
+ bottomY = dInfoPtr->maxY - dInfoPtr->y;
+ }
+ }
+
+ /*
+ * If the window height is smaller than the line height, prefer to make
+ * the top of the line visible.
+ */
+
+ if (dInfoPtr->maxY - dInfoPtr->y < lineHeight) {
+ bottomY = lineHeight;
+ }
+
+ /*
+ * Our job now is to arrange the display so that indexPtr appears as low
+ * on the screen as possible but with its bottom no lower than bottomY.
+ * BottomY is the bottom of the window if the desired line is just below
+ * the current screen, otherwise it is a half-line lower than the center
+ * of the window.
+ */
+
+ MeasureUp(textPtr, indexPtr, bottomY, &textPtr->topIndex,
+ &dInfoPtr->newTopPixelOffset);
+
+ scheduleUpdate:
+ if (!(dInfoPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DisplayText, textPtr);
+ }
+ dInfoPtr->flags |= REDRAW_PENDING|DINFO_OUT_OF_DATE|REPICK_NEEDED;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkTextMeasureDown --
+ *
+ * Given one index, find the index of the first character on the highest
+ * display line that would be displayed no more than "distance" pixels
+ * below the top of the given index.
+ *
+ * Results:
+ * The srcPtr is manipulated in place to reflect the new position. We
+ * return the number of pixels by which 'distance' overlaps the srcPtr.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkTextMeasureDown(
+ TkText *textPtr, /* Text widget in which to measure. */
+ TkTextIndex *srcPtr, /* Index of character from which to start
+ * measuring. */
+ int distance) /* Vertical distance in pixels measured from
+ * the top pixel in srcPtr's logical line. */
+{
+ TkTextLine *lastLinePtr;
+ DLine *dlPtr;
+ TkTextIndex loop;
+
+ lastLinePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, textPtr,
+ TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr));
+
+ do {
+ dlPtr = LayoutDLine(textPtr, srcPtr);
+ dlPtr->nextPtr = NULL;
+
+ if (distance < dlPtr->height) {
+ FreeDLines(textPtr, dlPtr, NULL, DLINE_FREE_TEMP);
+ break;
+ }
+ distance -= dlPtr->height;
+ TkTextIndexForwBytes(textPtr, srcPtr, dlPtr->byteCount, &loop);
+ FreeDLines(textPtr, dlPtr, NULL, DLINE_FREE_TEMP);
+ if (loop.linePtr == lastLinePtr) {
+ break;
+ }
+ *srcPtr = loop;
+ } while (distance > 0);
+
+ return distance;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * MeasureUp --
+ *
+ * Given one index, find the index of the first character on the highest
+ * display line that would be displayed no more than "distance" pixels
+ * above the given index.
+ *
+ * If this function is called with distance=0, it simply finds the first
+ * index on the same display line as srcPtr. However, there is a another
+ * function TkTextFindDisplayLineEnd designed just for that task which is
+ * probably better to use.
+ *
+ * Results:
+ * *dstPtr is filled in with the index of the first character on a
+ * display line. The display line is found by measuring up "distance"
+ * pixels above the pixel just below an imaginary display line that
+ * contains srcPtr. If the display line that covers this coordinate
+ * actually extends above the coordinate, then return any excess pixels
+ * in *overlap, if that is non-NULL.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+MeasureUp(
+ TkText *textPtr, /* Text widget in which to measure. */
+ const TkTextIndex *srcPtr, /* Index of character from which to start
+ * measuring. */
+ int distance, /* Vertical distance in pixels measured from
+ * the pixel just below the lowest one in
+ * srcPtr's line. */
+ TkTextIndex *dstPtr, /* Index to fill in with result. */
+ int *overlap) /* Used to store how much of the final index
+ * returned was not covered by 'distance'. */
+{
+ int lineNum; /* Number of current line. */
+ int bytesToCount; /* Maximum number of bytes to measure in
+ * current line. */
+ TkTextIndex index;
+ DLine *dlPtr, *lowestPtr;
+
+ bytesToCount = srcPtr->byteIndex + 1;
+ index.tree = srcPtr->tree;
+ for (lineNum = TkBTreeLinesTo(textPtr, srcPtr->linePtr); lineNum >= 0;
+ lineNum--) {
+ /*
+ * Layout an entire text line (potentially > 1 display line).
+ *
+ * For the first line, which contains srcPtr, only layout the part up
+ * through srcPtr (bytesToCount is non-infinite to accomplish this).
+ * Make a list of all the display lines in backwards order (the lowest
+ * DLine on the screen is first in the list).
+ */
+
+ index.linePtr = TkBTreeFindLine(srcPtr->tree, textPtr, lineNum);
+ index.byteIndex = 0;
+ TkTextFindDisplayLineEnd(textPtr, &index, 0, NULL);
+ lineNum = TkBTreeLinesTo(textPtr, index.linePtr);
+ lowestPtr = NULL;
+ do {
+ dlPtr = LayoutDLine(textPtr, &index);
+ dlPtr->nextPtr = lowestPtr;
+ lowestPtr = dlPtr;
+ TkTextIndexForwBytes(textPtr, &index, dlPtr->byteCount, &index);
+ bytesToCount -= dlPtr->byteCount;
+ } while (bytesToCount>0 && index.linePtr==dlPtr->index.linePtr);
+
+ /*
+ * Scan through the display lines to see if we've covered enough
+ * vertical distance. If so, save the starting index for the line at
+ * the desired location. If distance was zero to start with then we
+ * simply get the first index on the same display line as the original
+ * index.
+ */
+
+ for (dlPtr = lowestPtr; dlPtr != NULL; dlPtr = dlPtr->nextPtr) {
+ distance -= dlPtr->height;
+ if (distance <= 0) {
+ *dstPtr = dlPtr->index;
+
+ /*
+ * dstPtr is the start of a display line that is or is not
+ * the start of a logical line. If it is the start of a
+ * logical line, we must check whether this line is merged
+ * with the previous logical line, and if so we must adjust
+ * dstPtr to the start of the display line since a display
+ * line start needs to be returned.
+ */
+ if (!IsStartOfNotMergedLine(textPtr, dstPtr)) {
+ TkTextFindDisplayLineEnd(textPtr, dstPtr, 0, NULL);
+ }
+
+ if (overlap != NULL) {
+ *overlap = -distance;
+ }
+ break;
+ }
+ }
+
+ /*
+ * Discard the display lines, then either return or prepare for the
+ * next display line to lay out.
+ */
+
+ FreeDLines(textPtr, lowestPtr, NULL, DLINE_FREE);
+ if (distance <= 0) {
+ return;
+ }
+ bytesToCount = INT_MAX; /* Consider all chars. in next line. */
+ }
+
+ /*
+ * Ran off the beginning of the text. Return the first character in the
+ * text.
+ */
+
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, 0, 0, dstPtr);
+ if (overlap != NULL) {
+ *overlap = 0;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkTextSeeCmd --
+ *
+ * This function is invoked to process the "see" option for the widget
+ * command for text widgets. See the user documentation for details on
+ * what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkTextSeeCmd(
+ TkText *textPtr, /* Information about text widget. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. Someone else has already
+ * parsed this command enough to know that
+ * objv[1] is "see". */
+{
+ TextDInfo *dInfoPtr = textPtr->dInfoPtr;
+ TkTextIndex index;
+ int x, y, width, height, lineWidth, byteCount, oneThird, delta;
+ DLine *dlPtr;
+ TkTextDispChunk *chunkPtr;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index");
+ return TCL_ERROR;
+ }
+ if (TkTextGetObjIndex(interp, textPtr, objv[2], &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * If the specified position is the extra line at the end of the text,
+ * round it back to the last real line.
+ */
+
+ if (TkBTreeLinesTo(textPtr, index.linePtr)
+ == TkBTreeNumLines(index.tree, textPtr)) {
+ TkTextIndexBackChars(textPtr, &index, 1, &index, COUNT_INDICES);
+ }
+
+ /*
+ * First get the desired position into the vertical range of the window.
+ */
+
+ TkTextSetYView(textPtr, &index, TK_TEXT_PICKPLACE);
+
+ /*
+ * Now make sure that the character is in view horizontally.
+ */
+
+ if (dInfoPtr->flags & DINFO_OUT_OF_DATE) {
+ UpdateDisplayInfo(textPtr);
+ }
+ lineWidth = dInfoPtr->maxX - dInfoPtr->x;
+ if (dInfoPtr->maxLength < lineWidth) {
+ return TCL_OK;
+ }
+
+ /*
+ * Find the display line containing the desired index. dlPtr may be NULL
+ * if the widget is not mapped. [Bug #641778]
+ */
+
+ dlPtr = FindDLine(textPtr, dInfoPtr->dLinePtr, &index);
+ if (dlPtr == NULL) {
+ return TCL_OK;
+ }
+
+ /*
+ * Find the chunk within the display line that contains the desired
+ * index. The chunks making the display line are skipped up to but not
+ * including the one crossing index. Skipping is done based on a
+ * byteCount offset possibly spanning several logical lines in case
+ * they are elided.
+ */
+
+ byteCount = TkTextIndexCountBytes(textPtr, &dlPtr->index, &index);
+ for (chunkPtr = dlPtr->chunkPtr; chunkPtr != NULL ;
+ chunkPtr = chunkPtr->nextPtr) {
+ if (byteCount < chunkPtr->numBytes) {
+ break;
+ }
+ byteCount -= chunkPtr->numBytes;
+ }
+
+ /*
+ * Call a chunk-specific function to find the horizontal range of the
+ * character within the chunk. chunkPtr is NULL if trying to see in elided
+ * region.
+ */
+
+ if (chunkPtr != NULL) {
+ chunkPtr->bboxProc(textPtr, chunkPtr, byteCount,
+ dlPtr->y + dlPtr->spaceAbove,
+ dlPtr->height - dlPtr->spaceAbove - dlPtr->spaceBelow,
+ dlPtr->baseline - dlPtr->spaceAbove, &x, &y, &width,
+ &height);
+ delta = x - dInfoPtr->curXPixelOffset;
+ oneThird = lineWidth/3;
+ if (delta < 0) {
+ if (delta < -oneThird) {
+ dInfoPtr->newXPixelOffset = x - lineWidth/2;
+ } else {
+ dInfoPtr->newXPixelOffset += delta;
+ }
+ } else {
+ delta -= lineWidth - width;
+ if (delta <= 0) {
+ return TCL_OK;
+ }
+ if (delta > oneThird) {
+ dInfoPtr->newXPixelOffset = x - lineWidth/2;
+ } else {
+ dInfoPtr->newXPixelOffset += delta;
+ }
+ }
+ }
+ dInfoPtr->flags |= DINFO_OUT_OF_DATE;
+ if (!(dInfoPtr->flags & REDRAW_PENDING)) {
+ dInfoPtr->flags |= REDRAW_PENDING;
+ Tcl_DoWhenIdle(DisplayText, textPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkTextXviewCmd --
+ *
+ * This function is invoked to process the "xview" option for the widget
+ * command for text widgets. See the user documentation for details on
+ * what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkTextXviewCmd(
+ TkText *textPtr, /* Information about text widget. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. Someone else has already
+ * parsed this command enough to know that
+ * objv[1] is "xview". */
+{
+ TextDInfo *dInfoPtr = textPtr->dInfoPtr;
+ int type, count;
+ double fraction;
+
+ if (dInfoPtr->flags & DINFO_OUT_OF_DATE) {
+ UpdateDisplayInfo(textPtr);
+ }
+
+ if (objc == 2) {
+ GetXView(interp, textPtr, 0);
+ return TCL_OK;
+ }
+
+ type = TextGetScrollInfoObj(interp, textPtr, objc, objv,
+ &fraction, &count);
+ switch (type) {
+ case TKTEXT_SCROLL_ERROR:
+ return TCL_ERROR;
+ case TKTEXT_SCROLL_MOVETO:
+ if (fraction > 1.0) {
+ fraction = 1.0;
+ }
+ if (fraction < 0) {
+ fraction = 0;
+ }
+ dInfoPtr->newXPixelOffset = (int)
+ (fraction * dInfoPtr->maxLength + 0.5);
+ break;
+ case TKTEXT_SCROLL_PAGES: {
+ int pixelsPerPage;
+
+ pixelsPerPage = (dInfoPtr->maxX-dInfoPtr->x) - 2*textPtr->charWidth;
+ if (pixelsPerPage < 1) {
+ pixelsPerPage = 1;
+ }
+ dInfoPtr->newXPixelOffset += pixelsPerPage * count;
+ break;
+ }
+ case TKTEXT_SCROLL_UNITS:
+ dInfoPtr->newXPixelOffset += count * textPtr->charWidth;
+ break;
+ case TKTEXT_SCROLL_PIXELS:
+ dInfoPtr->newXPixelOffset += count;
+ break;
+ }
+
+ dInfoPtr->flags |= DINFO_OUT_OF_DATE;
+ if (!(dInfoPtr->flags & REDRAW_PENDING)) {
+ dInfoPtr->flags |= REDRAW_PENDING;
+ Tcl_DoWhenIdle(DisplayText, textPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * YScrollByPixels --
+ *
+ * This function is called to scroll a text widget up or down by a given
+ * number of pixels.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The view in textPtr's window changes to reflect the value of "offset".
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+YScrollByPixels(
+ TkText *textPtr, /* Widget to scroll. */
+ int offset) /* Amount by which to scroll, in pixels.
+ * Positive means that information later in
+ * text becomes visible, negative means that
+ * information earlier in the text becomes
+ * visible. */
+{
+ TextDInfo *dInfoPtr = textPtr->dInfoPtr;
+
+ if (offset < 0) {
+ /*
+ * Now we want to measure up this number of pixels from the top of the
+ * screen. But the top line may not be totally visible. Note that
+ * 'count' is negative here.
+ */
+
+ offset -= CalculateDisplayLineHeight(textPtr,
+ &textPtr->topIndex, NULL, NULL) - dInfoPtr->topPixelOffset;
+ MeasureUp(textPtr, &textPtr->topIndex, -offset,
+ &textPtr->topIndex, &dInfoPtr->newTopPixelOffset);
+ } else if (offset > 0) {
+ DLine *dlPtr;
+ TkTextLine *lastLinePtr;
+ TkTextIndex newIdx;
+
+ /*
+ * Scrolling down by pixels. Layout lines starting at the top index
+ * and count through the desired vertical distance.
+ */
+
+ lastLinePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, textPtr,
+ TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr));
+ offset += dInfoPtr->topPixelOffset;
+ dInfoPtr->newTopPixelOffset = 0;
+ while (offset > 0) {
+ dlPtr = LayoutDLine(textPtr, &textPtr->topIndex);
+ dlPtr->nextPtr = NULL;
+ TkTextIndexForwBytes(textPtr, &textPtr->topIndex,
+ dlPtr->byteCount, &newIdx);
+ if (offset <= dlPtr->height) {
+ /*
+ * Adjust the top overlap accordingly.
+ */
+
+ dInfoPtr->newTopPixelOffset = offset;
+ }
+ offset -= dlPtr->height;
+ FreeDLines(textPtr, dlPtr, NULL, DLINE_FREE_TEMP);
+ if (newIdx.linePtr == lastLinePtr || offset <= 0) {
+ break;
+ }
+ textPtr->topIndex = newIdx;
+ }
+ } else {
+ /*
+ * offset = 0, so no scrolling required.
+ */
+
+ return;
+ }
+ if (!(dInfoPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DisplayText, textPtr);
+ }
+ dInfoPtr->flags |= REDRAW_PENDING|DINFO_OUT_OF_DATE|REPICK_NEEDED;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * YScrollByLines --
+ *
+ * This function is called to scroll a text widget up or down by a given
+ * number of lines.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The view in textPtr's window changes to reflect the value of "offset".
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+YScrollByLines(
+ TkText *textPtr, /* Widget to scroll. */
+ int offset) /* Amount by which to scroll, in display
+ * lines. Positive means that information
+ * later in text becomes visible, negative
+ * means that information earlier in the text
+ * becomes visible. */
+{
+ int i, bytesToCount, lineNum;
+ TkTextIndex newIdx, index;
+ TkTextLine *lastLinePtr;
+ TextDInfo *dInfoPtr = textPtr->dInfoPtr;
+ DLine *dlPtr, *lowestPtr;
+
+ if (offset < 0) {
+ /*
+ * Must scroll up (to show earlier information in the text). The code
+ * below is similar to that in MeasureUp, except that it counts lines
+ * instead of pixels.
+ */
+
+ bytesToCount = textPtr->topIndex.byteIndex + 1;
+ index.tree = textPtr->sharedTextPtr->tree;
+ offset--; /* Skip line containing topIndex. */
+ for (lineNum = TkBTreeLinesTo(textPtr, textPtr->topIndex.linePtr);
+ lineNum >= 0; lineNum--) {
+ index.linePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree,
+ textPtr, lineNum);
+ index.byteIndex = 0;
+ lowestPtr = NULL;
+ do {
+ dlPtr = LayoutDLine(textPtr, &index);
+ dlPtr->nextPtr = lowestPtr;
+ lowestPtr = dlPtr;
+ TkTextIndexForwBytes(textPtr, &index, dlPtr->byteCount,&index);
+ bytesToCount -= dlPtr->byteCount;
+ } while ((bytesToCount > 0)
+ && (index.linePtr == dlPtr->index.linePtr));
+
+ for (dlPtr = lowestPtr; dlPtr != NULL; dlPtr = dlPtr->nextPtr) {
+ offset++;
+ if (offset == 0) {
+ textPtr->topIndex = dlPtr->index;
+
+ /*
+ * topIndex is the start of a logical line. However, if
+ * the eol of the previous logical line is elided, then
+ * topIndex may be elsewhere than the first character of
+ * a display line, which is unwanted. Adjust to the start
+ * of the display line, if needed.
+ * topIndex is the start of a display line that is or is
+ * not the start of a logical line. If it is the start of
+ * a logical line, we must check whether this line is
+ * merged with the previous logical line, and if so we
+ * must adjust topIndex to the start of the display line.
+ */
+ if (!IsStartOfNotMergedLine(textPtr, &textPtr->topIndex)) {
+ TkTextFindDisplayLineEnd(textPtr, &textPtr->topIndex,
+ 0, NULL);
+ }
+
+ break;
+ }
+ }
+
+ /*
+ * Discard the display lines, then either return or prepare for
+ * the next display line to lay out.
+ */
+
+ FreeDLines(textPtr, lowestPtr, NULL, DLINE_FREE);
+ if (offset >= 0) {
+ goto scheduleUpdate;
+ }
+ bytesToCount = INT_MAX;
+ }
+
+ /*
+ * Ran off the beginning of the text. Return the first character in
+ * the text, and make sure we haven't left anything overlapping the
+ * top window border.
+ */
+
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, 0, 0,
+ &textPtr->topIndex);
+ dInfoPtr->newTopPixelOffset = 0;
+ } else {
+ /*
+ * Scrolling down, to show later information in the text. Just count
+ * lines from the current top of the window.
+ */
+
+ lastLinePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, textPtr,
+ TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr));
+ for (i = 0; i < offset; i++) {
+ dlPtr = LayoutDLine(textPtr, &textPtr->topIndex);
+ if (dlPtr->length == 0 && dlPtr->height == 0) {
+ offset++;
+ }
+ dlPtr->nextPtr = NULL;
+ TkTextIndexForwBytes(textPtr, &textPtr->topIndex,
+ dlPtr->byteCount, &newIdx);
+ FreeDLines(textPtr, dlPtr, NULL, DLINE_FREE);
+ if (newIdx.linePtr == lastLinePtr) {
+ break;
+ }
+ textPtr->topIndex = newIdx;
+ }
+ }
+
+ scheduleUpdate:
+ if (!(dInfoPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DisplayText, textPtr);
+ }
+ dInfoPtr->flags |= REDRAW_PENDING|DINFO_OUT_OF_DATE|REPICK_NEEDED;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkTextYviewCmd --
+ *
+ * This function is invoked to process the "yview" option for the widget
+ * command for text widgets. See the user documentation for details on
+ * what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkTextYviewCmd(
+ TkText *textPtr, /* Information about text widget. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. Someone else has already
+ * parsed this command enough to know that
+ * objv[1] is "yview". */
+{
+ TextDInfo *dInfoPtr = textPtr->dInfoPtr;
+ int pickPlace, type;
+ int pixels, count;
+ int switchLength;
+ double fraction;
+ TkTextIndex index;
+
+ if (dInfoPtr->flags & DINFO_OUT_OF_DATE) {
+ UpdateDisplayInfo(textPtr);
+ }
+
+ if (objc == 2) {
+ GetYView(interp, textPtr, 0);
+ return TCL_OK;
+ }
+
+ /*
+ * Next, handle the old syntax: "pathName yview ?-pickplace? where"
+ */
+
+ pickPlace = 0;
+ if (Tcl_GetString(objv[2])[0] == '-') {
+ register const char *switchStr =
+ Tcl_GetStringFromObj(objv[2], &switchLength);
+
+ if ((switchLength >= 2) && (strncmp(switchStr, "-pickplace",
+ (unsigned) switchLength) == 0)) {
+ pickPlace = 1;
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "lineNum|index");
+ return TCL_ERROR;
+ }
+ }
+ }
+ if ((objc == 3) || pickPlace) {
+ int lineNum;
+
+ if (Tcl_GetIntFromObj(interp, objv[2+pickPlace], &lineNum) == TCL_OK) {
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,
+ lineNum, 0, &index);
+ TkTextSetYView(textPtr, &index, 0);
+ return TCL_OK;
+ }
+
+ /*
+ * The argument must be a regular text index.
+ */
+
+ Tcl_ResetResult(interp);
+ if (TkTextGetObjIndex(interp, textPtr, objv[2+pickPlace],
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ TkTextSetYView(textPtr, &index, (pickPlace ? TK_TEXT_PICKPLACE : 0));
+ return TCL_OK;
+ }
+
+ /*
+ * New syntax: dispatch based on objv[2].
+ */
+
+ type = TextGetScrollInfoObj(interp, textPtr, objc,objv, &fraction, &count);
+ switch (type) {
+ case TKTEXT_SCROLL_ERROR:
+ return TCL_ERROR;
+ case TKTEXT_SCROLL_MOVETO: {
+ int numPixels = TkBTreeNumPixels(textPtr->sharedTextPtr->tree,
+ textPtr);
+ int topMostPixel;
+
+ if (numPixels == 0) {
+ /*
+ * If the window is totally empty no scrolling is needed, and the
+ * TkTextMakePixelIndex call below will fail.
+ */
+
+ break;
+ }
+ if (fraction > 1.0) {
+ fraction = 1.0;
+ }
+ if (fraction < 0) {
+ fraction = 0;
+ }
+
+ /*
+ * Calculate the pixel count for the new topmost pixel in the topmost
+ * line of the window. Note that the interpretation of 'fraction' is
+ * that it counts from 0 (top pixel in buffer) to 1.0 (one pixel past
+ * the last pixel in buffer).
+ */
+
+ topMostPixel = (int) (0.5 + fraction * numPixels);
+ if (topMostPixel >= numPixels) {
+ topMostPixel = numPixels -1;
+ }
+
+ /*
+ * This function returns the number of pixels by which the given line
+ * should overlap the top of the visible screen.
+ *
+ * This is then used to provide smooth scrolling.
+ */
+
+ pixels = TkTextMakePixelIndex(textPtr, topMostPixel, &index);
+ TkTextSetYView(textPtr, &index, pixels);
+ break;
+ }
+ case TKTEXT_SCROLL_PAGES: {
+ /*
+ * Scroll up or down by screenfuls. Actually, use the window height
+ * minus two lines, so that there's some overlap between adjacent
+ * pages.
+ */
+
+ int height = dInfoPtr->maxY - dInfoPtr->y;
+
+ if (textPtr->charHeight * 4 >= height) {
+ /*
+ * A single line is more than a quarter of the display. We choose
+ * to scroll by 3/4 of the height instead.
+ */
+
+ pixels = 3*height/4;
+ if (pixels < textPtr->charHeight) {
+ /*
+ * But, if 3/4 of the height is actually less than a single
+ * typical character height, then scroll by the minimum of the
+ * linespace or the total height.
+ */
+
+ if (textPtr->charHeight < height) {
+ pixels = textPtr->charHeight;
+ } else {
+ pixels = height;
+ }
+ }
+ pixels *= count;
+ } else {
+ pixels = (height - 2*textPtr->charHeight)*count;
+ }
+ YScrollByPixels(textPtr, pixels);
+ break;
+ }
+ case TKTEXT_SCROLL_PIXELS:
+ YScrollByPixels(textPtr, count);
+ break;
+ case TKTEXT_SCROLL_UNITS:
+ YScrollByLines(textPtr, count);
+ break;
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkTextPendingsync --
+ *
+ * This function checks if any line heights are not up-to-date.
+ *
+ * Results:
+ * Returns a boolean true if it is the case, or false if all line
+ * heights are up-to-date.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+Bool
+TkTextPendingsync(
+ TkText *textPtr) /* Information about text widget. */
+{
+ TextDInfo *dInfoPtr = textPtr->dInfoPtr;
+
+ return ((dInfoPtr->flags & OUT_OF_SYNC) != 0);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkTextScanCmd --
+ *
+ * This function is invoked to process the "scan" option for the widget
+ * command for text widgets. See the user documentation for details on
+ * what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkTextScanCmd(
+ register TkText *textPtr, /* Information about text widget. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. Someone else has already
+ * parsed this command enough to know that
+ * objv[1] is "scan". */
+{
+ TextDInfo *dInfoPtr = textPtr->dInfoPtr;
+ TkTextIndex index;
+ int c, x, y, totalScroll, gain=10;
+ size_t length;
+
+ if ((objc != 5) && (objc != 6)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "mark x y");
+ Tcl_AppendResult(interp, " or \"", Tcl_GetString(objv[0]),
+ " scan dragto x y ?gain?\"", NULL);
+ /*
+ * Ought to be:
+ * Tcl_WrongNumArgs(interp, 2, objc, "dragto x y ?gain?");
+ */
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((objc == 6) && (Tcl_GetIntFromObj(interp, objv[5], &gain) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ c = Tcl_GetString(objv[2])[0];
+ length = strlen(Tcl_GetString(objv[2]));
+ if (c=='d' && strncmp(Tcl_GetString(objv[2]), "dragto", length)==0) {
+ int newX, maxX;
+
+ /*
+ * Amplify the difference between the current position and the mark
+ * position to compute how much the view should shift, then update the
+ * mark position to correspond to the new view. If we run off the edge
+ * of the text, reset the mark point so that the current position
+ * continues to correspond to the edge of the window. This means that
+ * the picture will start dragging as soon as the mouse reverses
+ * direction (without this reset, might have to slide mouse a long
+ * ways back before the picture starts moving again).
+ */
+
+ newX = dInfoPtr->scanMarkXPixel + gain*(dInfoPtr->scanMarkX - x);
+ maxX = 1 + dInfoPtr->maxLength - (dInfoPtr->maxX - dInfoPtr->x);
+ if (newX < 0) {
+ newX = 0;
+ dInfoPtr->scanMarkXPixel = 0;
+ dInfoPtr->scanMarkX = x;
+ } else if (newX > maxX) {
+ newX = maxX;
+ dInfoPtr->scanMarkXPixel = maxX;
+ dInfoPtr->scanMarkX = x;
+ }
+ dInfoPtr->newXPixelOffset = newX;
+
+ totalScroll = gain*(dInfoPtr->scanMarkY - y);
+ if (totalScroll != dInfoPtr->scanTotalYScroll) {
+ index = textPtr->topIndex;
+ YScrollByPixels(textPtr, totalScroll-dInfoPtr->scanTotalYScroll);
+ dInfoPtr->scanTotalYScroll = totalScroll;
+ if ((index.linePtr == textPtr->topIndex.linePtr) &&
+ (index.byteIndex == textPtr->topIndex.byteIndex)) {
+ dInfoPtr->scanTotalYScroll = 0;
+ dInfoPtr->scanMarkY = y;
+ }
+ }
+ dInfoPtr->flags |= DINFO_OUT_OF_DATE;
+ if (!(dInfoPtr->flags & REDRAW_PENDING)) {
+ dInfoPtr->flags |= REDRAW_PENDING;
+ Tcl_DoWhenIdle(DisplayText, textPtr);
+ }
+ } else if (c=='m' && strncmp(Tcl_GetString(objv[2]), "mark", length)==0) {
+ dInfoPtr->scanMarkXPixel = dInfoPtr->newXPixelOffset;
+ dInfoPtr->scanMarkX = x;
+ dInfoPtr->scanTotalYScroll = 0;
+ dInfoPtr->scanMarkY = y;
+ } else {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad scan option \"%s\": must be mark or dragto",
+ Tcl_GetString(objv[2])));
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "scan option",
+ Tcl_GetString(objv[2]), NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetXView --
+ *
+ * This function computes the fractions that indicate what's visible in a
+ * text window and, optionally, evaluates a Tcl script to report them to
+ * the text's associated scrollbar.
+ *
+ * Results:
+ * If report is zero, then the interp's result is filled in with two real
+ * numbers separated by a space, giving the position of the left and
+ * right edges of the window as fractions from 0 to 1, where 0 means the
+ * left edge of the text and 1 means the right edge. If report is
+ * non-zero, then the interp's result isn't modified directly, but
+ * instead a script is evaluated in interp to report the new horizontal
+ * scroll position to the scrollbar (if the scroll position hasn't
+ * changed then no script is invoked).
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GetXView(
+ Tcl_Interp *interp, /* If "report" is FALSE, string describing
+ * visible range gets stored in the interp's
+ * result. */
+ TkText *textPtr, /* Information about text widget. */
+ int report) /* Non-zero means report info to scrollbar if
+ * it has changed. */
+{
+ TextDInfo *dInfoPtr = textPtr->dInfoPtr;
+ double first, last;
+ int code;
+ Tcl_Obj *listObj;
+
+ if (dInfoPtr->maxLength > 0) {
+ first = ((double) dInfoPtr->curXPixelOffset)
+ / dInfoPtr->maxLength;
+ last = ((double) (dInfoPtr->curXPixelOffset + dInfoPtr->maxX
+ - dInfoPtr->x))/dInfoPtr->maxLength;
+ if (last > 1.0) {
+ last = 1.0;
+ }
+ } else {
+ first = 0;
+ last = 1.0;
+ }
+ if (!report) {
+ listObj = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(interp, listObj, Tcl_NewDoubleObj(first));
+ Tcl_ListObjAppendElement(interp, listObj, Tcl_NewDoubleObj(last));
+ Tcl_SetObjResult(interp, listObj);
+ return;
+ }
+ if (FP_EQUAL_SCALE(first, dInfoPtr->xScrollFirst, dInfoPtr->maxLength) &&
+ FP_EQUAL_SCALE(last, dInfoPtr->xScrollLast, dInfoPtr->maxLength)) {
+ return;
+ }
+ dInfoPtr->xScrollFirst = first;
+ dInfoPtr->xScrollLast = last;
+ if (textPtr->xScrollCmd != NULL) {
+ char buf1[TCL_DOUBLE_SPACE+1];
+ char buf2[TCL_DOUBLE_SPACE+1];
+ Tcl_DString buf;
+
+ buf1[0] = ' ';
+ buf2[0] = ' ';
+ Tcl_PrintDouble(NULL, first, buf1+1);
+ Tcl_PrintDouble(NULL, last, buf2+1);
+ Tcl_DStringInit(&buf);
+ Tcl_DStringAppend(&buf, textPtr->xScrollCmd, -1);
+ Tcl_DStringAppend(&buf, buf1, -1);
+ Tcl_DStringAppend(&buf, buf2, -1);
+ code = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0);
+ Tcl_DStringFree(&buf);
+ if (code != TCL_OK) {
+ Tcl_AddErrorInfo(interp,
+ "\n (horizontal scrolling command executed by text)");
+ Tcl_BackgroundException(interp, code);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetYPixelCount --
+ *
+ * How many pixels are there between the absolute top of the widget and
+ * the top of the given DLine.
+ *
+ * While this function will work for any valid DLine, it is only ever
+ * called when dlPtr is the first display line in the widget (by
+ * 'GetYView'). This means that usually this function is a very quick
+ * calculation, since it can use the pre-calculated linked-list of DLines
+ * for height information.
+ *
+ * The only situation where this breaks down is if dlPtr's logical line
+ * wraps enough times to fill the text widget's current view - in this
+ * case we won't have enough dlPtrs in the linked list to be able to
+ * subtract off what we want.
+ *
+ * Results:
+ * The number of pixels.
+ *
+ * This value has a valid range between '0' (the very top of the widget)
+ * and the number of pixels in the total widget minus the pixel-height of
+ * the last line.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GetYPixelCount(
+ TkText *textPtr, /* Information about text widget. */
+ DLine *dlPtr) /* Information about the layout of a given
+ * index. */
+{
+ TkTextLine *linePtr = dlPtr->index.linePtr;
+ int count;
+
+ /*
+ * Get the pixel count to the top of dlPtr's logical line. The rest of the
+ * function is then concerned with updating 'count' for any difference
+ * between the top of the logical line and the display line.
+ */
+
+ count = TkBTreePixelsTo(textPtr, linePtr);
+
+ /*
+ * For the common case where this dlPtr is also the start of the logical
+ * line, we can return right away.
+ */
+
+ if (IsStartOfNotMergedLine(textPtr, &dlPtr->index)) {
+ return count;
+ }
+
+ /*
+ * Add on the logical line's height to reach one pixel beyond the bottom
+ * of the logical line. And then subtract off the heights of all the
+ * display lines from dlPtr to the end of its logical line.
+ *
+ * A different approach would be to lay things out from the start of the
+ * logical line until we reach dlPtr, but since none of those are
+ * pre-calculated, it'll usually take a lot longer. (But there are cases
+ * where it would be more efficient: say if we're on the second of 1000
+ * wrapped lines all from a single logical line - but that sort of
+ * optimization is left for the future).
+ */
+
+ count += TkBTreeLinePixelCount(textPtr, linePtr);
+
+ do {
+ count -= dlPtr->height;
+ if (dlPtr->nextPtr == NULL) {
+ /*
+ * We've run out of pre-calculated display lines, so we have to
+ * lay them out ourselves until the end of the logical line. Here
+ * is where we could be clever and ask: what's faster, to layout
+ * all lines from here to line-end, or all lines from the original
+ * dlPtr to the line-start? We just assume the former.
+ */
+
+ TkTextIndex index;
+ int notFirst = 0;
+
+ while (1) {
+ TkTextIndexForwBytes(textPtr, &dlPtr->index,
+ dlPtr->byteCount, &index);
+ if (notFirst) {
+ FreeDLines(textPtr, dlPtr, NULL, DLINE_FREE_TEMP);
+ }
+ if (index.linePtr != linePtr) {
+ break;
+ }
+ dlPtr = LayoutDLine(textPtr, &index);
+
+ if (tkTextDebug) {
+ char string[TK_POS_CHARS];
+
+ /*
+ * Debugging is enabled, so keep a log of all the lines
+ * whose height was recalculated. The test suite uses this
+ * information.
+ */
+
+ TkTextPrintIndex(textPtr, &index, string);
+ LOG("tk_textHeightCalc", string);
+ }
+ count -= dlPtr->height;
+ notFirst = 1;
+ }
+ break;
+ }
+ dlPtr = dlPtr->nextPtr;
+ } while (dlPtr->index.linePtr == linePtr);
+
+ return count;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetYView --
+ *
+ * This function computes the fractions that indicate what's visible in a
+ * text window and, optionally, evaluates a Tcl script to report them to
+ * the text's associated scrollbar.
+ *
+ * Results:
+ * If report is zero, then the interp's result is filled in with two real
+ * numbers separated by a space, giving the position of the top and
+ * bottom of the window as fractions from 0 to 1, where 0 means the
+ * beginning of the text and 1 means the end. If report is non-zero, then
+ * the interp's result isn't modified directly, but a script is evaluated
+ * in interp to report the new scroll position to the scrollbar (if the
+ * scroll position hasn't changed then no script is invoked).
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GetYView(
+ Tcl_Interp *interp, /* If "report" is FALSE, string describing
+ * visible range gets stored in the interp's
+ * result. */
+ TkText *textPtr, /* Information about text widget. */
+ int report) /* Non-zero means report info to scrollbar if
+ * it has changed. */
+{
+ TextDInfo *dInfoPtr = textPtr->dInfoPtr;
+ double first, last;
+ DLine *dlPtr;
+ int totalPixels, code, count;
+ Tcl_Obj *listObj;
+
+ dlPtr = dInfoPtr->dLinePtr;
+
+ if (dlPtr == NULL) {
+ return;
+ }
+
+ totalPixels = TkBTreeNumPixels(textPtr->sharedTextPtr->tree, textPtr);
+
+ if (totalPixels == 0) {
+ first = 0.0;
+ last = 1.0;
+ } else {
+ /*
+ * Get the pixel count for the first visible pixel of the first
+ * visible line. If the first visible line is only partially visible,
+ * then we use 'topPixelOffset' to get the difference.
+ */
+
+ count = GetYPixelCount(textPtr, dlPtr);
+ first = (count + dInfoPtr->topPixelOffset) / (double) totalPixels;
+
+ /*
+ * Add on the total number of visible pixels to get the count to one
+ * pixel _past_ the last visible pixel. This is how the 'yview'
+ * command is documented, and also explains why we are dividing by
+ * 'totalPixels' and not 'totalPixels-1'.
+ */
+
+ while (1) {
+ int extra;
+
+ count += dlPtr->height;
+ extra = dlPtr->y + dlPtr->height - dInfoPtr->maxY;
+ if (extra > 0) {
+ /*
+ * This much of the last line is not visible, so don't count
+ * these pixels. Since we've reached the bottom of the window,
+ * we break out of the loop.
+ */
+
+ count -= extra;
+ break;
+ }
+ if (dlPtr->nextPtr == NULL) {
+ break;
+ }
+ dlPtr = dlPtr->nextPtr;
+ }
+
+ if (count > totalPixels) {
+ /*
+ * It can be possible, if we do not update each line's pixelHeight
+ * cache when we lay out individual DLines that the count
+ * generated here is more up-to-date than that maintained by the
+ * BTree. In such a case, the best we can do here is to fix up
+ * 'count' and continue, which might result in small, temporary
+ * perturbations to the size of the scrollbar. This is basically
+ * harmless, but in a perfect world we would not have this
+ * problem.
+ *
+ * For debugging purposes, if anyone wishes to improve the text
+ * widget further, the following 'panic' can be activated. In
+ * principle it should be possible to ensure the BTree is always
+ * at least as up to date as the display, so in the future we
+ * might be able to leave the 'panic' in permanently when we
+ * believe we have resolved the cache synchronisation issue.
+ *
+ * However, to achieve that goal would, I think, require a fairly
+ * substantial refactorisation of the code in this file so that
+ * there is much more obvious and explicit coordination between
+ * calls to LayoutDLine and updating of each TkTextLine's
+ * pixelHeight. The complicated bit is that LayoutDLine deals with
+ * individual display lines, but pixelHeight is for a logical
+ * line.
+ */
+
+#if 0
+ Tcl_Panic("Counted more pixels (%d) than expected (%d) total "
+ "pixels in text widget scroll bar calculation.", count,
+ totalPixels);
+#endif
+ count = totalPixels;
+ }
+
+ last = ((double) count)/((double)totalPixels);
+ }
+
+ if (!report) {
+ listObj = Tcl_NewListObj(0,NULL);
+ Tcl_ListObjAppendElement(interp, listObj, Tcl_NewDoubleObj(first));
+ Tcl_ListObjAppendElement(interp, listObj, Tcl_NewDoubleObj(last));
+ Tcl_SetObjResult(interp, listObj);
+ return;
+ }
+
+ if (FP_EQUAL_SCALE(first, dInfoPtr->yScrollFirst, totalPixels) &&
+ FP_EQUAL_SCALE(last, dInfoPtr->yScrollLast, totalPixels)) {
+ return;
+ }
+
+ dInfoPtr->yScrollFirst = first;
+ dInfoPtr->yScrollLast = last;
+ if (textPtr->yScrollCmd != NULL) {
+ char buf1[TCL_DOUBLE_SPACE+1];
+ char buf2[TCL_DOUBLE_SPACE+1];
+ Tcl_DString buf;
+
+ buf1[0] = ' ';
+ buf2[0] = ' ';
+ Tcl_PrintDouble(NULL, first, buf1+1);
+ Tcl_PrintDouble(NULL, last, buf2+1);
+ Tcl_DStringInit(&buf);
+ Tcl_DStringAppend(&buf, textPtr->yScrollCmd, -1);
+ Tcl_DStringAppend(&buf, buf1, -1);
+ Tcl_DStringAppend(&buf, buf2, -1);
+ code = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0);
+ Tcl_DStringFree(&buf);
+ if (code != TCL_OK) {
+ Tcl_AddErrorInfo(interp,
+ "\n (vertical scrolling command executed by text)");
+ Tcl_BackgroundException(interp, code);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AsyncUpdateYScrollbar --
+ *
+ * This function is called to update the vertical scrollbar asychronously
+ * as the pixel height calculations progress for lines in the widget.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * See 'GetYView'. In particular the scrollbar position and size may be
+ * changed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+AsyncUpdateYScrollbar(
+ ClientData clientData) /* Information about widget. */
+{
+ register TkText *textPtr = clientData;
+
+ textPtr->dInfoPtr->scrollbarTimer = NULL;
+
+ if (!(textPtr->flags & DESTROYED)) {
+ GetYView(textPtr->interp, textPtr, 1);
+ }
+
+ if (textPtr->refCount-- <= 1) {
+ ckfree(textPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FindDLine --
+ *
+ * This function is called to find the DLine corresponding to a given
+ * text index.
+ *
+ * Results:
+ * The return value is a pointer to the first DLine found in the list
+ * headed by dlPtr that displays information at or after the specified
+ * position. If there is no such line in the list then NULL is returned.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static DLine *
+FindDLine(
+ TkText *textPtr, /* Widget record for text widget. */
+ register DLine *dlPtr, /* Pointer to first in list of DLines to
+ * search. */
+ const TkTextIndex *indexPtr)/* Index of desired character. */
+{
+ DLine *dlPtrPrev;
+ TkTextIndex indexPtr2;
+
+ if (dlPtr == NULL) {
+ return NULL;
+ }
+ if (TkBTreeLinesTo(NULL, indexPtr->linePtr)
+ < TkBTreeLinesTo(NULL, dlPtr->index.linePtr)) {
+ /*
+ * The first display line is already past the desired line.
+ */
+
+ return dlPtr;
+ }
+
+ /*
+ * The display line containing the desired index is such that the index
+ * of the first character of this display line is at or before the
+ * desired index, and the index of the first character of the next
+ * display line is after the desired index.
+ */
+
+ while (TkTextIndexCmp(&dlPtr->index,indexPtr) < 0) {
+ dlPtrPrev = dlPtr;
+ dlPtr = dlPtr->nextPtr;
+ if (dlPtr == NULL) {
+ /*
+ * We're past the last display line, either because the desired
+ * index lies past the visible text, or because the desired index
+ * is on the last display line.
+ */
+ indexPtr2 = dlPtrPrev->index;
+ TkTextIndexForwBytes(textPtr, &indexPtr2, dlPtrPrev->byteCount,
+ &indexPtr2);
+ if (TkTextIndexCmp(&indexPtr2,indexPtr) > 0) {
+ /*
+ * The desired index is on the last display line.
+ * --> return this display line.
+ */
+ dlPtr = dlPtrPrev;
+ } else {
+ /*
+ * The desired index is past the visible text. There is no
+ * display line displaying something at the desired index.
+ * --> return NULL.
+ */
+ }
+ break;
+ }
+ if (TkTextIndexCmp(&dlPtr->index,indexPtr) > 0) {
+ /*
+ * If we're here then we would normally expect that:
+ * dlPtrPrev->index <= indexPtr < dlPtr->index
+ * i.e. we have found the searched display line being dlPtr.
+ * However it is possible that some DLines were unlinked
+ * previously, leading to a situation where going through
+ * the list of display lines skips display lines that did
+ * exist just a moment ago.
+ */
+ indexPtr2 = dlPtrPrev->index;
+ TkTextIndexForwBytes(textPtr, &indexPtr2, dlPtrPrev->byteCount,
+ &indexPtr2);
+ if (TkTextIndexCmp(&indexPtr2,indexPtr) > 0) {
+ /*
+ * Confirmed:
+ * dlPtrPrev->index <= indexPtr < dlPtr->index
+ * --> return dlPtrPrev.
+ */
+ dlPtr = dlPtrPrev;
+ } else {
+ /*
+ * The last (rightmost) index shown by dlPtrPrev is still
+ * before the desired index. This may be because there was
+ * previously a display line between dlPtrPrev and dlPtr
+ * and this display line has been unlinked.
+ * --> return dlPtr.
+ */
+ }
+ break;
+ }
+ }
+
+ return dlPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * IsStartOfNotMergedLine --
+ *
+ * This function checks whether the given index is the start of a
+ * logical line that is not merged with the previous logical line
+ * (due to elision of the eol of the previous line).
+ *
+ * Results:
+ * Returns whether the given index denotes the first index of a
+* logical line not merged with its previous line.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+IsStartOfNotMergedLine(
+ TkText *textPtr, /* Widget record for text widget. */
+ const TkTextIndex *indexPtr) /* Index to check. */
+{
+ TkTextIndex indexPtr2;
+
+ if (indexPtr->byteIndex != 0) {
+ /*
+ * Not the start of a logical line.
+ */
+ return 0;
+ }
+
+ if (TkTextIndexBackBytes(textPtr, indexPtr, 1, &indexPtr2)) {
+ /*
+ * indexPtr is the first index of the text widget.
+ */
+ return 1;
+ }
+
+ if (!TkTextIsElided(textPtr, &indexPtr2, NULL)) {
+ /*
+ * The eol of the line just before indexPtr is elided.
+ */
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkTextPixelIndex --
+ *
+ * Given an (x,y) coordinate on the screen, find the location of the
+ * character closest to that location.
+ *
+ * Results:
+ * The index at *indexPtr is modified to refer to the character on the
+ * display that is closest to (x,y).
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkTextPixelIndex(
+ TkText *textPtr, /* Widget record for text widget. */
+ int x, int y, /* Pixel coordinates of point in widget's
+ * window. */
+ TkTextIndex *indexPtr, /* This index gets filled in with the index of
+ * the character nearest to (x,y). */
+ int *nearest) /* If non-NULL then gets set to 0 if (x,y) is
+ * actually over the returned index, and 1 if
+ * it is just nearby (e.g. if x,y is on the
+ * border of the widget). */
+{
+ TextDInfo *dInfoPtr = textPtr->dInfoPtr;
+ register DLine *dlPtr, *validDlPtr;
+ int nearby = 0;
+
+ /*
+ * Make sure that all of the layout information about what's displayed
+ * where on the screen is up-to-date.
+ */
+
+ if (dInfoPtr->flags & DINFO_OUT_OF_DATE) {
+ UpdateDisplayInfo(textPtr);
+ }
+
+ /*
+ * If the coordinates are above the top of the window, then adjust them to
+ * refer to the upper-right corner of the window. If they're off to one
+ * side or the other, then adjust to the closest side.
+ */
+
+ if (y < dInfoPtr->y) {
+ y = dInfoPtr->y;
+ x = dInfoPtr->x;
+ nearby = 1;
+ }
+ if (x >= dInfoPtr->maxX) {
+ x = dInfoPtr->maxX - 1;
+ nearby = 1;
+ }
+ if (x < dInfoPtr->x) {
+ x = dInfoPtr->x;
+ nearby = 1;
+ }
+
+ /*
+ * Find the display line containing the desired y-coordinate.
+ */
+
+ if (dInfoPtr->dLinePtr == NULL) {
+ if (nearest != NULL) {
+ *nearest = 1;
+ }
+ *indexPtr = textPtr->topIndex;
+ return;
+ }
+ for (dlPtr = validDlPtr = dInfoPtr->dLinePtr;
+ y >= (dlPtr->y + dlPtr->height);
+ dlPtr = dlPtr->nextPtr) {
+ if (dlPtr->chunkPtr != NULL) {
+ validDlPtr = dlPtr;
+ }
+ if (dlPtr->nextPtr == NULL) {
+ /*
+ * Y-coordinate is off the bottom of the displayed text. Use the
+ * last character on the last line.
+ */
+
+ x = dInfoPtr->maxX - 1;
+ nearby = 1;
+ break;
+ }
+ }
+ if (dlPtr->chunkPtr == NULL) {
+ dlPtr = validDlPtr;
+ }
+
+ if (nearest != NULL) {
+ *nearest = nearby;
+ }
+
+ DlineIndexOfX(textPtr, dlPtr, x, indexPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DlineIndexOfX --
+ *
+ * Given an x coordinate in a display line, find the index of the
+ * character closest to that location.
+ *
+ * This is effectively the opposite of DlineXOfIndex.
+ *
+ * Results:
+ * The index at *indexPtr is modified to refer to the character on the
+ * display line that is closest to x.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DlineIndexOfX(
+ TkText *textPtr, /* Widget record for text widget. */
+ DLine *dlPtr, /* Display information for this display
+ * line. */
+ int x, /* Pixel x coordinate of point in widget's
+ * window. */
+ TkTextIndex *indexPtr) /* This index gets filled in with the index of
+ * the character nearest to x. */
+{
+ TextDInfo *dInfoPtr = textPtr->dInfoPtr;
+ register TkTextDispChunk *chunkPtr;
+
+ /*
+ * Scan through the line's chunks to find the one that contains the
+ * desired x-coordinate. Before doing this, translate the x-coordinate
+ * from the coordinate system of the window to the coordinate system of
+ * the line (to take account of x-scrolling).
+ */
+
+ *indexPtr = dlPtr->index;
+ x = x - dInfoPtr->x + dInfoPtr->curXPixelOffset;
+ chunkPtr = dlPtr->chunkPtr;
+
+ if (chunkPtr == NULL || x == 0) {
+ /*
+ * This may occur if everything is elided, or if we're simply already
+ * at the beginning of the line.
+ */
+
+ return;
+ }
+
+ while (x >= (chunkPtr->x + chunkPtr->width)) {
+ /*
+ * Note that this forward then backward movement of the index can be
+ * problematic at the end of the buffer (we can't move forward, and
+ * then when we move backward, we do, leading to the wrong position).
+ * Hence when x == 0 we take special action above.
+ */
+
+ if (TkTextIndexForwBytes(NULL,indexPtr,chunkPtr->numBytes,indexPtr)) {
+ /*
+ * We've reached the end of the text.
+ */
+
+ TkTextIndexBackChars(NULL, indexPtr, 1, indexPtr, COUNT_INDICES);
+ return;
+ }
+ if (chunkPtr->nextPtr == NULL) {
+ /*
+ * We've reached the end of the display line.
+ */
+
+ TkTextIndexBackChars(NULL, indexPtr, 1, indexPtr, COUNT_INDICES);
+ return;
+ }
+ chunkPtr = chunkPtr->nextPtr;
+ }
+
+ /*
+ * If the chunk has more than one byte in it, ask it which character is at
+ * the desired location. In this case we can manipulate
+ * 'indexPtr->byteIndex' directly, because we know we're staying inside a
+ * single logical line.
+ */
+
+ if (chunkPtr->numBytes > 1) {
+ indexPtr->byteIndex += chunkPtr->measureProc(chunkPtr, x);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkTextIndexOfX --
+ *
+ * Given a logical x coordinate (i.e. distance in pixels from the
+ * beginning of the display line, not taking into account any information
+ * about the window, scrolling etc.) on the display line starting with
+ * the given index, adjust that index to refer to the object under the x
+ * coordinate.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkTextIndexOfX(
+ TkText *textPtr, /* Widget record for text widget. */
+ int x, /* The x coordinate for which we want the
+ * index. */
+ TkTextIndex *indexPtr) /* Index of display line start, which will be
+ * adjusted to the index under the given x
+ * coordinate. */
+{
+ DLine *dlPtr = LayoutDLine(textPtr, indexPtr);
+ DlineIndexOfX(textPtr, dlPtr, x + textPtr->dInfoPtr->x
+ - textPtr->dInfoPtr->curXPixelOffset, indexPtr);
+ FreeDLines(textPtr, dlPtr, NULL, DLINE_FREE_TEMP);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DlineXOfIndex --
+ *
+ * Given a relative byte index on a given display line (i.e. the number
+ * of byte indices from the beginning of the given display line), find
+ * the x coordinate of that index within the abstract display line,
+ * without adjusting for the x-scroll state of the line.
+ *
+ * This is effectively the opposite of DlineIndexOfX.
+ *
+ * NB. The 'byteIndex' is relative to the display line, NOT the logical
+ * line.
+ *
+ * Results:
+ * The x coordinate.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DlineXOfIndex(
+ TkText *textPtr, /* Widget record for text widget. */
+ DLine *dlPtr, /* Display information for this display
+ * line. */
+ int byteIndex) /* The byte index for which we want the
+ * coordinate. */
+{
+ register TkTextDispChunk *chunkPtr = dlPtr->chunkPtr;
+ int x = 0;
+
+ if (byteIndex == 0 || chunkPtr == NULL) {
+ return x;
+ }
+
+ /*
+ * Scan through the line's chunks to find the one that contains the
+ * desired byte index.
+ */
+
+ chunkPtr = dlPtr->chunkPtr;
+ while (byteIndex > 0) {
+ if (byteIndex < chunkPtr->numBytes) {
+ int y, width, height;
+
+ chunkPtr->bboxProc(textPtr, chunkPtr, byteIndex,
+ dlPtr->y + dlPtr->spaceAbove,
+ dlPtr->height - dlPtr->spaceAbove - dlPtr->spaceBelow,
+ dlPtr->baseline - dlPtr->spaceAbove, &x, &y, &width,
+ &height);
+ break;
+ }
+ byteIndex -= chunkPtr->numBytes;
+ if (chunkPtr->nextPtr == NULL || byteIndex == 0) {
+ x = chunkPtr->x + chunkPtr->width;
+ break;
+ }
+ chunkPtr = chunkPtr->nextPtr;
+ }
+
+ return x;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkTextIndexBbox --
+ *
+ * Given an index, find the bounding box of the screen area occupied by
+ * the entity (character, window, image) at that index.
+ *
+ * Results:
+ * Zero is returned if the index is on the screen. -1 means the index is
+ * not on the screen. If the return value is 0, then the bounding box of
+ * the part of the index that's visible on the screen is returned to
+ * *xPtr, *yPtr, *widthPtr, and *heightPtr.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkTextIndexBbox(
+ TkText *textPtr, /* Widget record for text widget. */
+ const TkTextIndex *indexPtr,/* Index whose bounding box is desired. */
+ int *xPtr, int *yPtr, /* Filled with index's upper-left
+ * coordinate. */
+ int *widthPtr, int *heightPtr,
+ /* Filled in with index's dimensions. */
+ int *charWidthPtr) /* If the 'index' is at the end of a display
+ * line and therefore takes up a very large
+ * width, this is used to return the smaller
+ * width actually desired by the index. */
+{
+ TextDInfo *dInfoPtr = textPtr->dInfoPtr;
+ DLine *dlPtr;
+ register TkTextDispChunk *chunkPtr;
+ int byteCount;
+
+ /*
+ * Make sure that all of the screen layout information is up to date.
+ */
+
+ if (dInfoPtr->flags & DINFO_OUT_OF_DATE) {
+ UpdateDisplayInfo(textPtr);
+ }
+
+ /*
+ * Find the display line containing the desired index.
+ */
+
+ dlPtr = FindDLine(textPtr, dInfoPtr->dLinePtr, indexPtr);
+
+ /*
+ * Two cases shall be trapped here because the logic later really
+ * needs dlPtr to be the display line containing indexPtr:
+ * 1. if no display line contains the desired index (NULL dlPtr)
+ * 2. if indexPtr is before the first display line, in which case
+ * dlPtr currently points to the first display line
+ */
+
+ if ((dlPtr == NULL) || (TkTextIndexCmp(&dlPtr->index, indexPtr) > 0)) {
+ return -1;
+ }
+
+ /*
+ * Find the chunk within the display line that contains the desired
+ * index. The chunks making the display line are skipped up to but not
+ * including the one crossing indexPtr. Skipping is done based on
+ * a byteCount offset possibly spanning several logical lines in case
+ * they are elided.
+ */
+
+ byteCount = TkTextIndexCountBytes(textPtr, &dlPtr->index, indexPtr);
+ for (chunkPtr = dlPtr->chunkPtr; ; chunkPtr = chunkPtr->nextPtr) {
+ if (chunkPtr == NULL) {
+ return -1;
+ }
+ if (byteCount < chunkPtr->numBytes) {
+ break;
+ }
+ byteCount -= chunkPtr->numBytes;
+ }
+
+ /*
+ * Call a chunk-specific function to find the horizontal range of the
+ * character within the chunk, then fill in the vertical range. The
+ * x-coordinate returned by bboxProc is a coordinate within a line, not a
+ * coordinate on the screen. Translate it to reflect horizontal scrolling.
+ */
+
+ chunkPtr->bboxProc(textPtr, chunkPtr, byteCount,
+ dlPtr->y + dlPtr->spaceAbove,
+ dlPtr->height - dlPtr->spaceAbove - dlPtr->spaceBelow,
+ dlPtr->baseline - dlPtr->spaceAbove, xPtr, yPtr, widthPtr,
+ heightPtr);
+ *xPtr = *xPtr + dInfoPtr->x - dInfoPtr->curXPixelOffset;
+ if ((byteCount == chunkPtr->numBytes-1) && (chunkPtr->nextPtr == NULL)) {
+ /*
+ * Last character in display line. Give it all the space up to the
+ * line.
+ */
+
+ if (charWidthPtr != NULL) {
+ *charWidthPtr = dInfoPtr->maxX - *xPtr;
+ if (*charWidthPtr > textPtr->charWidth) {
+ *charWidthPtr = textPtr->charWidth;
+ }
+ }
+ if (*xPtr > dInfoPtr->maxX) {
+ *xPtr = dInfoPtr->maxX;
+ }
+ *widthPtr = dInfoPtr->maxX - *xPtr;
+ } else {
+ if (charWidthPtr != NULL) {
+ *charWidthPtr = *widthPtr;
+ }
+ }
+ if (*widthPtr == 0) {
+ /*
+ * With zero width (e.g. elided text) we just need to make sure it is
+ * onscreen, where the '=' case here is ok.
+ */
+
+ if (*xPtr < dInfoPtr->x) {
+ return -1;
+ }
+ } else {
+ if ((*xPtr + *widthPtr) <= dInfoPtr->x) {
+ return -1;
+ }
+ }
+ if ((*xPtr + *widthPtr) > dInfoPtr->maxX) {
+ *widthPtr = dInfoPtr->maxX - *xPtr;
+ if (*widthPtr <= 0) {
+ return -1;
+ }
+ }
+ if ((*yPtr + *heightPtr) > dInfoPtr->maxY) {
+ *heightPtr = dInfoPtr->maxY - *yPtr;
+ if (*heightPtr <= 0) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkTextDLineInfo --
+ *
+ * Given an index, return information about the display line containing
+ * that character.
+ *
+ * Results:
+ * Zero is returned if the character is on the screen. -1 means the
+ * character isn't on the screen. If the return value is 0, then
+ * information is returned in the variables pointed to by xPtr, yPtr,
+ * widthPtr, heightPtr, and basePtr.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkTextDLineInfo(
+ TkText *textPtr, /* Widget record for text widget. */
+ const TkTextIndex *indexPtr,/* Index of character whose bounding box is
+ * desired. */
+ int *xPtr, int *yPtr, /* Filled with line's upper-left
+ * coordinate. */
+ int *widthPtr, int *heightPtr,
+ /* Filled in with line's dimensions. */
+ int *basePtr) /* Filled in with the baseline position,
+ * measured as an offset down from *yPtr. */
+{
+ TextDInfo *dInfoPtr = textPtr->dInfoPtr;
+ DLine *dlPtr;
+ int dlx;
+
+ /*
+ * Make sure that all of the screen layout information is up to date.
+ */
+
+ if (dInfoPtr->flags & DINFO_OUT_OF_DATE) {
+ UpdateDisplayInfo(textPtr);
+ }
+
+ /*
+ * Find the display line containing the desired index.
+ */
+
+ dlPtr = FindDLine(textPtr, dInfoPtr->dLinePtr, indexPtr);
+
+ /*
+ * Two cases shall be trapped here because the logic later really
+ * needs dlPtr to be the display line containing indexPtr:
+ * 1. if no display line contains the desired index (NULL dlPtr)
+ * 2. if indexPtr is before the first display line, in which case
+ * dlPtr currently points to the first display line
+ */
+
+ if ((dlPtr == NULL) || (TkTextIndexCmp(&dlPtr->index, indexPtr) > 0)) {
+ return -1;
+ }
+
+ dlx = (dlPtr->chunkPtr != NULL? dlPtr->chunkPtr->x: 0);
+ *xPtr = dInfoPtr->x - dInfoPtr->curXPixelOffset + dlx;
+ *widthPtr = dlPtr->length - dlx;
+ *yPtr = dlPtr->y;
+ if ((dlPtr->y + dlPtr->height) > dInfoPtr->maxY) {
+ *heightPtr = dInfoPtr->maxY - dlPtr->y;
+ } else {
+ *heightPtr = dlPtr->height;
+ }
+ *basePtr = dlPtr->baseline;
+ return 0;
+}
+
+/*
+ * Get bounding-box information about an elided chunk.
+ */
+
+static void
+ElideBboxProc(
+ TkText *textPtr,
+ TkTextDispChunk *chunkPtr, /* Chunk containing desired char. */
+ int index, /* Index of desired character within the
+ * chunk. */
+ int y, /* Topmost pixel in area allocated for this
+ * line. */
+ int lineHeight, /* Height of line, in pixels. */
+ int baseline, /* Location of line's baseline, in pixels
+ * measured down from y. */
+ int *xPtr, int *yPtr, /* Gets filled in with coords of character's
+ * upper-left pixel. X-coord is in same
+ * coordinate system as chunkPtr->x. */
+ int *widthPtr, /* Gets filled in with width of character, in
+ * pixels. */
+ int *heightPtr) /* Gets filled in with height of character, in
+ * pixels. */
+{
+ *xPtr = chunkPtr->x;
+ *yPtr = y;
+ *widthPtr = *heightPtr = 0;
+}
+
+/*
+ * Measure an elided chunk.
+ */
+
+static int
+ElideMeasureProc(
+ TkTextDispChunk *chunkPtr, /* Chunk containing desired coord. */
+ int x) /* X-coordinate, in same coordinate system as
+ * chunkPtr->x. */
+{
+ return 0 /*chunkPtr->numBytes - 1*/;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkTextCharLayoutProc --
+ *
+ * This function is the "layoutProc" for character segments.
+ *
+ * Results:
+ * If there is something to display for the chunk then a non-zero value
+ * is returned and the fields of chunkPtr will be filled in (see the
+ * declaration of TkTextDispChunk in tkText.h for details). If zero is
+ * returned it means that no characters from this chunk fit in the
+ * window. If -1 is returned it means that this segment just doesn't need
+ * to be displayed (never happens for text).
+ *
+ * Side effects:
+ * Memory is allocated to hold additional information about the chunk.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkTextCharLayoutProc(
+ TkText *textPtr, /* Text widget being layed out. */
+ TkTextIndex *indexPtr, /* Index of first character to lay out
+ * (corresponds to segPtr and offset). */
+ TkTextSegment *segPtr, /* Segment being layed out. */
+ int byteOffset, /* Byte offset within segment of first
+ * character to consider. */
+ int maxX, /* Chunk must not occupy pixels at this
+ * position or higher. */
+ int maxBytes, /* Chunk must not include more than this many
+ * characters. */
+ int noCharsYet, /* Non-zero means no characters have been
+ * assigned to this display line yet. */
+ TkWrapMode wrapMode, /* How to handle line wrapping:
+ * TEXT_WRAPMODE_CHAR, TEXT_WRAPMODE_NONE, or
+ * TEXT_WRAPMODE_WORD. */
+ register TkTextDispChunk *chunkPtr)
+ /* Structure to fill in with information about
+ * this chunk. The x field has already been
+ * set by the caller. */
+{
+ Tk_Font tkfont;
+ int nextX, bytesThatFit, count;
+ CharInfo *ciPtr;
+ char *p;
+ TkTextSegment *nextPtr;
+ Tk_FontMetrics fm;
+#if TK_LAYOUT_WITH_BASE_CHUNKS
+ const char *line;
+ int lineOffset;
+ BaseCharInfo *bciPtr;
+ Tcl_DString *baseString;
+#endif
+
+ /*
+ * Figure out how many characters will fit in the space we've got. Include
+ * the next character, even though it won't fit completely, if any of the
+ * following is true:
+ * (a) the chunk contains no characters and the display line contains no
+ * characters yet (i.e. the line isn't wide enough to hold even a
+ * single character).
+ * (b) at least one pixel of the character is visible, we have not
+ * already exceeded the character limit, and the next character is a
+ * white space character.
+ * In the specific case of 'word' wrapping mode however, include all space
+ * characters following the characters that fit in the space we've got,
+ * even if no pixel of them is visible.
+ */
+
+ p = segPtr->body.chars + byteOffset;
+ tkfont = chunkPtr->stylePtr->sValuePtr->tkfont;
+
+#if TK_LAYOUT_WITH_BASE_CHUNKS
+ if (baseCharChunkPtr == NULL) {
+ baseCharChunkPtr = chunkPtr;
+ bciPtr = ckalloc(sizeof(BaseCharInfo));
+ baseString = &bciPtr->baseChars;
+ Tcl_DStringInit(baseString);
+ bciPtr->width = 0;
+
+ ciPtr = &bciPtr->ci;
+ } else {
+ bciPtr = baseCharChunkPtr->clientData;
+ ciPtr = ckalloc(sizeof(CharInfo));
+ baseString = &bciPtr->baseChars;
+ }
+
+ lineOffset = Tcl_DStringLength(baseString);
+ line = Tcl_DStringAppend(baseString,p,maxBytes);
+
+ chunkPtr->clientData = ciPtr;
+ ciPtr->baseChunkPtr = baseCharChunkPtr;
+ ciPtr->baseOffset = lineOffset;
+ ciPtr->chars = NULL;
+ ciPtr->numBytes = 0;
+
+ bytesThatFit = CharChunkMeasureChars(chunkPtr, line,
+ lineOffset + maxBytes, lineOffset, -1, chunkPtr->x, maxX,
+ TK_ISOLATE_END, &nextX);
+#else /* !TK_LAYOUT_WITH_BASE_CHUNKS */
+ bytesThatFit = CharChunkMeasureChars(chunkPtr, p, maxBytes, 0, -1,
+ chunkPtr->x, maxX, TK_ISOLATE_END, &nextX);
+#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */
+
+ if (bytesThatFit < maxBytes) {
+ if ((bytesThatFit == 0) && noCharsYet) {
+ int ch;
+ int chLen = TkUtfToUniChar(p, &ch);
+
+#if TK_LAYOUT_WITH_BASE_CHUNKS
+ bytesThatFit = CharChunkMeasureChars(chunkPtr, line,
+ lineOffset+chLen, lineOffset, -1, chunkPtr->x, -1, 0,
+ &nextX);
+#else /* !TK_LAYOUT_WITH_BASE_CHUNKS */
+ bytesThatFit = CharChunkMeasureChars(chunkPtr, p, chLen, 0, -1,
+ chunkPtr->x, -1, 0, &nextX);
+#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */
+ }
+ if ((nextX < maxX) && ((p[bytesThatFit] == ' ')
+ || (p[bytesThatFit] == '\t'))) {
+ /*
+ * Space characters are funny, in that they are considered to fit
+ * if there is at least one pixel of space left on the line. Just
+ * give the space character whatever space is left.
+ */
+
+ nextX = maxX;
+ bytesThatFit++;
+ }
+ if (wrapMode == TEXT_WRAPMODE_WORD) {
+ while (p[bytesThatFit] == ' ') {
+ /*
+ * Space characters that would go at the beginning of the
+ * next line are allocated to the current line. This gives
+ * the effect of trimming white spaces that would otherwise
+ * be seen at the beginning of wrapped lines.
+ * Note that testing for '\t' is useless here because the
+ * chunk always includes at most one trailing \t, see
+ * LayoutDLine.
+ */
+
+ bytesThatFit++;
+ }
+ }
+ if (p[bytesThatFit] == '\n') {
+ /*
+ * A newline character takes up no space, so if the previous
+ * character fits then so does the newline.
+ */
+
+ bytesThatFit++;
+ }
+ if (bytesThatFit == 0) {
+#if TK_LAYOUT_WITH_BASE_CHUNKS
+ chunkPtr->clientData = NULL;
+ if (chunkPtr == baseCharChunkPtr) {
+ baseCharChunkPtr = NULL;
+ Tcl_DStringFree(baseString);
+ } else {
+ Tcl_DStringSetLength(baseString,lineOffset);
+ }
+ ckfree(ciPtr);
+#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */
+ return 0;
+ }
+ }
+
+ Tk_GetFontMetrics(tkfont, &fm);
+
+ /*
+ * Fill in the chunk structure and allocate and initialize a CharInfo
+ * structure. If the last character is a newline then don't bother to
+ * display it.
+ */
+
+ chunkPtr->displayProc = CharDisplayProc;
+ chunkPtr->undisplayProc = CharUndisplayProc;
+ chunkPtr->measureProc = CharMeasureProc;
+ chunkPtr->bboxProc = CharBboxProc;
+ chunkPtr->numBytes = bytesThatFit;
+ chunkPtr->minAscent = fm.ascent + chunkPtr->stylePtr->sValuePtr->offset;
+ chunkPtr->minDescent = fm.descent - chunkPtr->stylePtr->sValuePtr->offset;
+ chunkPtr->minHeight = 0;
+ chunkPtr->width = nextX - chunkPtr->x;
+ chunkPtr->breakIndex = -1;
+
+#if !TK_LAYOUT_WITH_BASE_CHUNKS
+ ciPtr = ckalloc((Tk_Offset(CharInfo, chars) + 1) + bytesThatFit);
+ chunkPtr->clientData = ciPtr;
+ memcpy(ciPtr->chars, p, (unsigned) bytesThatFit);
+#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */
+
+ ciPtr->numBytes = bytesThatFit;
+ if (p[bytesThatFit - 1] == '\n') {
+ ciPtr->numBytes--;
+ }
+
+#if TK_LAYOUT_WITH_BASE_CHUNKS
+ /*
+ * Final update for the current base chunk data.
+ */
+
+ Tcl_DStringSetLength(baseString,lineOffset+ciPtr->numBytes);
+ bciPtr->width = nextX - baseCharChunkPtr->x;
+
+ /*
+ * Finalize the base chunk if this chunk ends in a tab, which definitly
+ * breaks the context and needs to be handled on a higher level.
+ */
+
+ if (ciPtr->numBytes > 0 && p[ciPtr->numBytes - 1] == '\t') {
+ FinalizeBaseChunk(chunkPtr);
+ }
+#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */
+
+ /*
+ * Compute a break location. If we're in word wrap mode, a break can occur
+ * after any space character, or at the end of the chunk if the next
+ * segment (ignoring those with zero size) is not a character segment.
+ */
+
+ if (wrapMode != TEXT_WRAPMODE_WORD) {
+ chunkPtr->breakIndex = chunkPtr->numBytes;
+ } else {
+ for (count = bytesThatFit, p += bytesThatFit - 1; count > 0;
+ count--, p--) {
+ /*
+ * Don't use isspace(); effects are unpredictable and can lead to
+ * odd word-wrapping problems on some platforms. Also don't use
+ * Tcl_UniCharIsSpace here either, as it identifies non-breaking
+ * spaces as places to break. What we actually want is only the
+ * ASCII space characters, so use them explicitly...
+ */
+
+ switch (*p) {
+ case '\t': case '\n': case '\v': case '\f': case '\r': case ' ':
+ chunkPtr->breakIndex = count;
+ goto checkForNextChunk;
+ }
+ }
+ checkForNextChunk:
+ if ((bytesThatFit + byteOffset) == segPtr->size) {
+ for (nextPtr = segPtr->nextPtr; nextPtr != NULL;
+ nextPtr = nextPtr->nextPtr) {
+ if (nextPtr->size != 0) {
+ if (nextPtr->typePtr != &tkTextCharType) {
+ chunkPtr->breakIndex = chunkPtr->numBytes;
+ }
+ break;
+ }
+ }
+ }
+ }
+ return 1;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CharChunkMeasureChars --
+ *
+ * Determine the number of characters from a char chunk that will fit in
+ * the given horizontal span.
+ *
+ * This is the same as MeasureChars (which see), but in the context of a
+ * char chunk, i.e. on a higher level of abstraction. Use this function
+ * whereever possible instead of plain MeasureChars, so that the right
+ * context is used automatically.
+ *
+ * Results:
+ * The return value is the number of bytes from the range of start to end
+ * in source that fit in the span given by startX and maxX. *nextXPtr is
+ * filled in with the x-coordinate at which the first character that
+ * didn't fit would be drawn, if it were to be drawn.
+ *
+ * Side effects:
+ * None.
+ *--------------------------------------------------------------
+ */
+
+static int
+CharChunkMeasureChars(
+ TkTextDispChunk *chunkPtr, /* Chunk from which to measure. */
+ const char *chars, /* Chars to use, instead of the chunk's own.
+ * Used by the layoutproc during chunk setup.
+ * All other callers use NULL. Not
+ * NUL-terminated. */
+ int charsLen, /* Length of the "chars" parameter. */
+ int start, int end, /* The range of chars to measure inside the
+ * chunk (or inside the additional chars). */
+ int startX, /* Starting x coordinate where the measured
+ * span will begin. */
+ int maxX, /* Maximum pixel width of the span. May be -1
+ * for unlimited. */
+ int flags, /* Flags to pass to MeasureChars. */
+ int *nextXPtr) /* The function puts the newly calculated
+ * right border x-position of the span
+ * here. */
+{
+ Tk_Font tkfont = chunkPtr->stylePtr->sValuePtr->tkfont;
+ CharInfo *ciPtr = chunkPtr->clientData;
+
+#if !TK_LAYOUT_WITH_BASE_CHUNKS
+ if (chars == NULL) {
+ chars = ciPtr->chars;
+ charsLen = ciPtr->numBytes;
+ }
+ if (end == -1) {
+ end = charsLen;
+ }
+
+ return MeasureChars(tkfont, chars, charsLen, start, end-start,
+ startX, maxX, flags, nextXPtr);
+#else /* TK_LAYOUT_WITH_BASE_CHUNKS */
+ {
+ int xDisplacement;
+ int fit, bstart = start, bend = end;
+
+ if (chars == NULL) {
+ Tcl_DString *baseChars = &((BaseCharInfo *)
+ ciPtr->baseChunkPtr->clientData)->baseChars;
+
+ chars = Tcl_DStringValue(baseChars);
+ charsLen = Tcl_DStringLength(baseChars);
+ bstart += ciPtr->baseOffset;
+ if (bend == -1) {
+ bend = ciPtr->baseOffset + ciPtr->numBytes;
+ } else {
+ bend += ciPtr->baseOffset;
+ }
+ } else if (bend == -1) {
+ bend = charsLen;
+ }
+
+ if (bstart == ciPtr->baseOffset) {
+ xDisplacement = startX - chunkPtr->x;
+ } else {
+ int widthUntilStart = 0;
+
+ MeasureChars(tkfont, chars, charsLen, 0, bstart,
+ 0, -1, 0, &widthUntilStart);
+ xDisplacement = startX - widthUntilStart - ciPtr->baseChunkPtr->x;
+ }
+
+ fit = MeasureChars(tkfont, chars, charsLen, 0, bend,
+ ciPtr->baseChunkPtr->x + xDisplacement, maxX, flags, nextXPtr);
+
+ if (fit < bstart) {
+ return 0;
+ } else {
+ return fit - bstart;
+ }
+ }
+#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * CharDisplayProc --
+ *
+ * This function is called to display a character chunk on the screen or
+ * in an off-screen pixmap.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Graphics are drawn.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+CharDisplayProc(
+ TkText *textPtr,
+ TkTextDispChunk *chunkPtr, /* Chunk that is to be drawn. */
+ int x, /* X-position in dst at which to draw this
+ * chunk (may differ from the x-position in
+ * the chunk because of scrolling). */
+ int y, /* Y-position at which to draw this chunk in
+ * dst. */
+ int height, /* Total height of line. */
+ int baseline, /* Offset of baseline from y. */
+ Display *display, /* Display to use for drawing. */
+ Drawable dst, /* Pixmap or window in which to draw chunk. */
+ int screenY) /* Y-coordinate in text window that
+ * corresponds to y. */
+{
+ CharInfo *ciPtr = chunkPtr->clientData;
+ const char *string;
+ TextStyle *stylePtr;
+ StyleValues *sValuePtr;
+ int numBytes, offsetBytes, offsetX;
+#if TK_DRAW_IN_CONTEXT
+ BaseCharInfo *bciPtr;
+#endif /* TK_DRAW_IN_CONTEXT */
+
+ if ((x + chunkPtr->width) <= 0) {
+ /*
+ * The chunk is off-screen.
+ */
+
+ return;
+ }
+
+#if TK_DRAW_IN_CONTEXT
+ bciPtr = ciPtr->baseChunkPtr->clientData;
+ numBytes = Tcl_DStringLength(&bciPtr->baseChars);
+ string = Tcl_DStringValue(&bciPtr->baseChars);
+
+#elif TK_LAYOUT_WITH_BASE_CHUNKS
+ if (ciPtr->baseChunkPtr != chunkPtr) {
+ /*
+ * Without context drawing only base chunks display their foreground.
+ */
+
+ return;
+ }
+
+ numBytes = Tcl_DStringLength(&((BaseCharInfo *) ciPtr)->baseChars);
+ string = ciPtr->chars;
+
+#else /* !TK_LAYOUT_WITH_BASE_CHUNKS */
+ numBytes = ciPtr->numBytes;
+ string = ciPtr->chars;
+#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */
+
+ stylePtr = chunkPtr->stylePtr;
+ sValuePtr = stylePtr->sValuePtr;
+
+ /*
+ * If the text sticks out way to the left of the window, skip over the
+ * characters that aren't in the visible part of the window. This is
+ * essential if x is very negative (such as less than 32K); otherwise
+ * overflow problems will occur in servers that use 16-bit arithmetic,
+ * like X.
+ */
+
+ offsetX = x;
+ offsetBytes = 0;
+ if (x < 0) {
+ offsetBytes = CharChunkMeasureChars(chunkPtr, NULL, 0, 0, -1,
+ x, 0, 0, &offsetX);
+ }
+
+ /*
+ * Draw the text, underline, and overstrike for this chunk.
+ */
+
+ if (!sValuePtr->elide && (numBytes > offsetBytes)
+ && (stylePtr->fgGC != NULL)) {
+#if TK_DRAW_IN_CONTEXT
+ int start = ciPtr->baseOffset + offsetBytes;
+ int len = ciPtr->numBytes - offsetBytes;
+ int xDisplacement = x - chunkPtr->x;
+
+ if ((len > 0) && (string[start + len - 1] == '\t')) {
+ len--;
+ }
+ if (len <= 0) {
+ return;
+ }
+
+ TkpDrawCharsInContext(display, dst, stylePtr->fgGC, sValuePtr->tkfont,
+ string, numBytes, start, len,
+ ciPtr->baseChunkPtr->x + xDisplacement,
+ y + baseline - sValuePtr->offset);
+
+ if (sValuePtr->underline) {
+ TkUnderlineCharsInContext(display, dst, stylePtr->ulGC,
+ sValuePtr->tkfont, string, numBytes,
+ ciPtr->baseChunkPtr->x + xDisplacement,
+ y + baseline - sValuePtr->offset,
+ start, start+len);
+ }
+ if (sValuePtr->overstrike) {
+ Tk_FontMetrics fm;
+
+ Tk_GetFontMetrics(sValuePtr->tkfont, &fm);
+ TkUnderlineCharsInContext(display, dst, stylePtr->ovGC,
+ sValuePtr->tkfont, string, numBytes,
+ ciPtr->baseChunkPtr->x + xDisplacement,
+ y + baseline - sValuePtr->offset
+ - fm.descent - (fm.ascent * 3) / 10,
+ start, start+len);
+ }
+#else /* !TK_DRAW_IN_CONTEXT */
+ string += offsetBytes;
+ numBytes -= offsetBytes;
+
+ if ((numBytes > 0) && (string[numBytes - 1] == '\t')) {
+ numBytes--;
+ }
+ Tk_DrawChars(display, dst, stylePtr->fgGC, sValuePtr->tkfont, string,
+ numBytes, offsetX, y + baseline - sValuePtr->offset);
+ if (sValuePtr->underline) {
+ Tk_UnderlineChars(display, dst, stylePtr->ulGC, sValuePtr->tkfont,
+ string, offsetX,
+ y + baseline - sValuePtr->offset,
+ 0, numBytes);
+
+ }
+ if (sValuePtr->overstrike) {
+ Tk_FontMetrics fm;
+
+ Tk_GetFontMetrics(sValuePtr->tkfont, &fm);
+ Tk_UnderlineChars(display, dst, stylePtr->ovGC, sValuePtr->tkfont,
+ string, offsetX,
+ y + baseline - sValuePtr->offset
+ - fm.descent - (fm.ascent * 3) / 10,
+ 0, numBytes);
+ }
+#endif /* TK_DRAW_IN_CONTEXT */
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * CharUndisplayProc --
+ *
+ * This function is called when a character chunk is no longer going to
+ * be displayed. It frees up resources that were allocated to display the
+ * chunk.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory and other resources get freed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+CharUndisplayProc(
+ TkText *textPtr, /* Overall information about text widget. */
+ TkTextDispChunk *chunkPtr) /* Chunk that is about to be freed. */
+{
+ CharInfo *ciPtr = chunkPtr->clientData;
+
+ if (ciPtr) {
+#if TK_LAYOUT_WITH_BASE_CHUNKS
+ if (chunkPtr == ciPtr->baseChunkPtr) {
+ /*
+ * Basechunks are undisplayed first, when DLines are freed or
+ * partially freed, so this makes sure we don't access their data
+ * any more.
+ */
+
+ FreeBaseChunk(chunkPtr);
+ } else if (ciPtr->baseChunkPtr != NULL) {
+ /*
+ * When other char chunks are undisplayed, drop their characters
+ * from the base chunk. This usually happens, when they are last
+ * in a line and need to be re-layed out.
+ */
+
+ RemoveFromBaseChunk(chunkPtr);
+ }
+
+ ciPtr->baseChunkPtr = NULL;
+ ciPtr->chars = NULL;
+ ciPtr->numBytes = 0;
+#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */
+
+ ckfree(ciPtr);
+ chunkPtr->clientData = NULL;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * CharMeasureProc --
+ *
+ * This function is called to determine which character in a character
+ * chunk lies over a given x-coordinate.
+ *
+ * Results:
+ * The return value is the index *within the chunk* of the character that
+ * covers the position given by "x".
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+CharMeasureProc(
+ TkTextDispChunk *chunkPtr, /* Chunk containing desired coord. */
+ int x) /* X-coordinate, in same coordinate system as
+ * chunkPtr->x. */
+{
+ int endX;
+
+ return CharChunkMeasureChars(chunkPtr, NULL, 0, 0, chunkPtr->numBytes-1,
+ chunkPtr->x, x, 0, &endX); /* CHAR OFFSET */
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * CharBboxProc --
+ *
+ * This function is called to compute the bounding box of the area
+ * occupied by a single character.
+ *
+ * Results:
+ * There is no return value. *xPtr and *yPtr are filled in with the
+ * coordinates of the upper left corner of the character, and *widthPtr
+ * and *heightPtr are filled in with the dimensions of the character in
+ * pixels. Note: not all of the returned bbox is necessarily visible on
+ * the screen (the rightmost part might be off-screen to the right, and
+ * the bottommost part might be off-screen to the bottom).
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+CharBboxProc(
+ TkText *textPtr,
+ TkTextDispChunk *chunkPtr, /* Chunk containing desired char. */
+ int byteIndex, /* Byte offset of desired character within the
+ * chunk. */
+ int y, /* Topmost pixel in area allocated for this
+ * line. */
+ int lineHeight, /* Height of line, in pixels. */
+ int baseline, /* Location of line's baseline, in pixels
+ * measured down from y. */
+ int *xPtr, int *yPtr, /* Gets filled in with coords of character's
+ * upper-left pixel. X-coord is in same
+ * coordinate system as chunkPtr->x. */
+ int *widthPtr, /* Gets filled in with width of character, in
+ * pixels. */
+ int *heightPtr) /* Gets filled in with height of character, in
+ * pixels. */
+{
+ CharInfo *ciPtr = chunkPtr->clientData;
+ int maxX;
+
+ maxX = chunkPtr->width + chunkPtr->x;
+ CharChunkMeasureChars(chunkPtr, NULL, 0, 0, byteIndex,
+ chunkPtr->x, -1, 0, xPtr);
+
+ if (byteIndex == ciPtr->numBytes) {
+ /*
+ * This situation only happens if the last character in a line is a
+ * space character, in which case it absorbs all of the extra space in
+ * the line (see TkTextCharLayoutProc).
+ */
+
+ *widthPtr = maxX - *xPtr;
+ } else if ((ciPtr->chars[byteIndex] == '\t')
+ && (byteIndex == ciPtr->numBytes - 1)) {
+ /*
+ * The desired character is a tab character that terminates a chunk;
+ * give it all the space left in the chunk.
+ */
+
+ *widthPtr = maxX - *xPtr;
+ } else {
+ CharChunkMeasureChars(chunkPtr, NULL, 0, byteIndex, byteIndex+1,
+ *xPtr, -1, 0, widthPtr);
+ if (*widthPtr > maxX) {
+ *widthPtr = maxX - *xPtr;
+ } else {
+ *widthPtr -= *xPtr;
+ }
+ }
+ *yPtr = y + baseline - chunkPtr->minAscent;
+ *heightPtr = chunkPtr->minAscent + chunkPtr->minDescent;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AdjustForTab --
+ *
+ * This function is called to move a series of chunks right in order to
+ * align them with a tab stop.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The width of chunkPtr gets adjusted so that it absorbs the extra space
+ * due to the tab. The x locations in all the chunks after chunkPtr are
+ * adjusted rightward to align with the tab stop given by tabArrayPtr and
+ * index.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+AdjustForTab(
+ TkText *textPtr, /* Information about the text widget as a
+ * whole. */
+ TkTextTabArray *tabArrayPtr,/* Information about the tab stops that apply
+ * to this line. May be NULL to indicate
+ * default tabbing (every 8 chars). */
+ int index, /* Index of current tab stop. */
+ TkTextDispChunk *chunkPtr) /* Chunk whose last character is the tab; the
+ * following chunks contain information to be
+ * shifted right. */
+{
+ int x, desired, delta, width, decimal, i, gotDigit;
+ TkTextDispChunk *chunkPtr2, *decimalChunkPtr;
+ CharInfo *ciPtr;
+ int tabX, spaceWidth;
+ const char *p;
+ TkTextTabAlign alignment;
+
+ if (chunkPtr->nextPtr == NULL) {
+ /*
+ * Nothing after the actual tab; just return.
+ */
+
+ return;
+ }
+
+ x = chunkPtr->nextPtr->x;
+
+ /*
+ * If no tab information has been given, assuming tab stops are at 8
+ * average-sized characters. Still ensure we respect the tabular versus
+ * wordprocessor tab style.
+ */
+
+ if ((tabArrayPtr == NULL) || (tabArrayPtr->numTabs == 0)) {
+ /*
+ * No tab information has been given, so use the default
+ * interpretation of tabs.
+ */
+
+ if (textPtr->tabStyle == TK_TEXT_TABSTYLE_TABULAR) {
+ int tabWidth = Tk_TextWidth(textPtr->tkfont, "0", 1) * 8;
+ if (tabWidth == 0) {
+ tabWidth = 1;
+ }
+
+ desired = tabWidth * (index + 1);
+ } else {
+ desired = NextTabStop(textPtr->tkfont, x, 0);
+ }
+
+ goto update;
+ }
+
+ if (index < tabArrayPtr->numTabs) {
+ alignment = tabArrayPtr->tabs[index].alignment;
+ tabX = tabArrayPtr->tabs[index].location;
+ } else {
+ /*
+ * Ran out of tab stops; compute a tab position by extrapolating from
+ * the last two tab positions.
+ */
+
+ tabX = (int) (tabArrayPtr->lastTab +
+ (index + 1 - tabArrayPtr->numTabs)*tabArrayPtr->tabIncrement +
+ 0.5);
+ alignment = tabArrayPtr->tabs[tabArrayPtr->numTabs-1].alignment;
+ }
+
+ if (alignment == LEFT) {
+ desired = tabX;
+ goto update;
+ }
+
+ if ((alignment == CENTER) || (alignment == RIGHT)) {
+ /*
+ * Compute the width of all the information in the tab group, then use
+ * it to pick a desired location.
+ */
+
+ width = 0;
+ for (chunkPtr2 = chunkPtr->nextPtr; chunkPtr2 != NULL;
+ chunkPtr2 = chunkPtr2->nextPtr) {
+ width += chunkPtr2->width;
+ }
+ if (alignment == CENTER) {
+ desired = tabX - width/2;
+ } else {
+ desired = tabX - width;
+ }
+ goto update;
+ }
+
+ /*
+ * Must be numeric alignment. Search through the text to be tabbed,
+ * looking for the last , or . before the first character that isn't a
+ * number, comma, period, or sign.
+ */
+
+ decimalChunkPtr = NULL;
+ decimal = gotDigit = 0;
+ for (chunkPtr2 = chunkPtr->nextPtr; chunkPtr2 != NULL;
+ chunkPtr2 = chunkPtr2->nextPtr) {
+ if (chunkPtr2->displayProc != CharDisplayProc) {
+ continue;
+ }
+ ciPtr = chunkPtr2->clientData;
+ for (p = ciPtr->chars, i = 0; i < ciPtr->numBytes; p++, i++) {
+ if (isdigit(UCHAR(*p))) {
+ gotDigit = 1;
+ } else if ((*p == '.') || (*p == ',')) {
+ decimal = p-ciPtr->chars;
+ decimalChunkPtr = chunkPtr2;
+ } else if (gotDigit) {
+ if (decimalChunkPtr == NULL) {
+ decimal = p-ciPtr->chars;
+ decimalChunkPtr = chunkPtr2;
+ }
+ goto endOfNumber;
+ }
+ }
+ }
+
+ endOfNumber:
+ if (decimalChunkPtr != NULL) {
+ int curX;
+
+ ciPtr = decimalChunkPtr->clientData;
+ CharChunkMeasureChars(decimalChunkPtr, NULL, 0, 0, decimal,
+ decimalChunkPtr->x, -1, 0, &curX);
+ desired = tabX - (curX - x);
+ goto update;
+ }
+
+ /*
+ * There wasn't a decimal point. Right justify the text.
+ */
+
+ width = 0;
+ for (chunkPtr2 = chunkPtr->nextPtr; chunkPtr2 != NULL;
+ chunkPtr2 = chunkPtr2->nextPtr) {
+ width += chunkPtr2->width;
+ }
+ desired = tabX - width;
+
+ /*
+ * Shift all of the chunks to the right so that the left edge is at the
+ * desired location, then expand the chunk containing the tab. Be sure
+ * that the tab occupies at least the width of a space character.
+ */
+
+ update:
+ delta = desired - x;
+ MeasureChars(textPtr->tkfont, " ", 1, 0, 1, 0, -1, 0, &spaceWidth);
+ if (delta < spaceWidth) {
+ delta = spaceWidth;
+ }
+ for (chunkPtr2 = chunkPtr->nextPtr; chunkPtr2 != NULL;
+ chunkPtr2 = chunkPtr2->nextPtr) {
+ chunkPtr2->x += delta;
+ }
+ chunkPtr->width += delta;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SizeOfTab --
+ *
+ * This returns an estimate of the amount of white space that will be
+ * consumed by a tab.
+ *
+ * Results:
+ * The return value is the minimum number of pixels that will be occupied
+ * by the next tab of tabArrayPtr, assuming that the current position on
+ * the line is x and the end of the line is maxX. The 'next tab' is
+ * determined by a combination of the current position (x) which it must
+ * be equal to or beyond, and the tab count in indexPtr.
+ *
+ * For numeric tabs, this is a conservative estimate. The return value is
+ * always >= 0.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SizeOfTab(
+ TkText *textPtr, /* Information about the text widget as a
+ * whole. */
+ int tabStyle, /* One of TK_TEXT_TABSTYLE_TABULAR
+ * or TK_TEXT_TABSTYLE_WORDPROCESSOR. */
+ TkTextTabArray *tabArrayPtr,/* Information about the tab stops that apply
+ * to this line. NULL means use default
+ * tabbing (every 8 chars.) */
+ int *indexPtr, /* Contains index of previous tab stop, will
+ * be updated to reflect the number of stops
+ * used. */
+ int x, /* Current x-location in line. */
+ int maxX) /* X-location of pixel just past the right
+ * edge of the line. */
+{
+ int tabX, result, index, spaceWidth, tabWidth;
+ TkTextTabAlign alignment;
+
+ index = *indexPtr;
+
+ if ((tabArrayPtr == NULL) || (tabArrayPtr->numTabs == 0)) {
+ /*
+ * We're using a default tab spacing of 8 characters.
+ */
+
+ tabWidth = Tk_TextWidth(textPtr->tkfont, "0", 1) * 8;
+ if (tabWidth == 0) {
+ tabWidth = 1;
+ }
+ } else {
+ tabWidth = 0; /* Avoid compiler error. */
+ }
+
+ do {
+ /*
+ * We were given the count before this tab, so increment it first.
+ */
+
+ index++;
+
+ if ((tabArrayPtr == NULL) || (tabArrayPtr->numTabs == 0)) {
+ /*
+ * We're using a default tab spacing calculated above.
+ */
+
+ tabX = tabWidth * (index + 1);
+ alignment = LEFT;
+ } else if (index < tabArrayPtr->numTabs) {
+ tabX = tabArrayPtr->tabs[index].location;
+ alignment = tabArrayPtr->tabs[index].alignment;
+ } else {
+ /*
+ * Ran out of tab stops; compute a tab position by extrapolating.
+ */
+
+ tabX = (int) (tabArrayPtr->lastTab
+ + (index + 1 - tabArrayPtr->numTabs)
+ * tabArrayPtr->tabIncrement + 0.5);
+ alignment = tabArrayPtr->tabs[tabArrayPtr->numTabs-1].alignment;
+ }
+
+ /*
+ * If this tab stop is before the current x position, then we have two
+ * cases:
+ *
+ * With 'wordprocessor' style tabs, we must obviously continue until
+ * we reach the text tab stop.
+ *
+ * With 'tabular' style tabs, we always use the index'th tab stop.
+ */
+ } while (tabX <= x && (tabStyle == TK_TEXT_TABSTYLE_WORDPROCESSOR));
+
+ /*
+ * Inform our caller of how many tab stops we've used up.
+ */
+
+ *indexPtr = index;
+
+ if (alignment == CENTER) {
+ /*
+ * Be very careful in the arithmetic below, because maxX may be the
+ * largest positive number: watch out for integer overflow.
+ */
+
+ if ((maxX-tabX) < (tabX - x)) {
+ result = (maxX - x) - 2*(maxX - tabX);
+ } else {
+ result = 0;
+ }
+ goto done;
+ }
+ if (alignment == RIGHT) {
+ result = 0;
+ goto done;
+ }
+
+ /*
+ * Note: this treats NUMERIC alignment the same as LEFT alignment, which
+ * is somewhat conservative. However, it's pretty tricky at this point to
+ * figure out exactly where the damn decimal point will be.
+ */
+
+ if (tabX > x) {
+ result = tabX - x;
+ } else {
+ result = 0;
+ }
+
+ done:
+ MeasureChars(textPtr->tkfont, " ", 1, 0, 1, 0, -1, 0, &spaceWidth);
+ if (result < spaceWidth) {
+ result = spaceWidth;
+ }
+ return result;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * NextTabStop --
+ *
+ * Given the current position, determine where the next default tab stop
+ * would be located. This function is called when the current chunk in
+ * the text has no tabs defined and so the default tab spacing for the
+ * font should be used, provided we are using wordprocessor style tabs.
+ *
+ * Results:
+ * The location in pixels of the next tab stop.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static int
+NextTabStop(
+ Tk_Font tkfont, /* Font in which chunk that contains tab stop
+ * will be drawn. */
+ int x, /* X-position in pixels where last character
+ * was drawn. The next tab stop occurs
+ * somewhere after this location. */
+ int tabOrigin) /* The origin for tab stops. May be non-zero
+ * if text has been scrolled. */
+{
+ int tabWidth, rem;
+
+ tabWidth = Tk_TextWidth(tkfont, "0", 1) * 8;
+ if (tabWidth == 0) {
+ tabWidth = 1;
+ }
+
+ x += tabWidth;
+ rem = (x - tabOrigin) % tabWidth;
+ if (rem < 0) {
+ rem += tabWidth;
+ }
+ x -= rem;
+ return x;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * If tabs are encountered in the string, they will be ignored (they
+ * should only occur as last character of the string anyway).
+ *
+ * If a newline is encountered in the string, the line will be broken at
+ * that point.
+ *
+ * Results:
+ * The return value is the number of bytes from the range of start to end
+ * in source that fit in the span given by startX and maxX. *nextXPtr is
+ * filled in with the x-coordinate at which the first character that
+ * didn't fit would be drawn, if it were to be drawn.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+MeasureChars(
+ Tk_Font tkfont, /* Font in which to draw characters. */
+ const char *source, /* Characters to be displayed. Need not be
+ * NULL-terminated. */
+ int maxBytes, /* Maximum # of bytes to consider from
+ * source. */
+ int rangeStart, int rangeLength,
+ /* Range of bytes to consider in source.*/
+ int startX, /* X-position at which first character will be
+ * drawn. */
+ int maxX, /* Don't consider any character that would
+ * cross this x-position. */
+ int flags, /* Flags to pass to Tk_MeasureChars. */
+ int *nextXPtr) /* Return x-position of terminating character
+ * here. */
+{
+ int curX, width, ch;
+ const char *special, *end, *start;
+
+ ch = 0; /* lint. */
+ curX = startX;
+ start = source + rangeStart;
+ end = start + rangeLength;
+ special = start;
+ while (start < end) {
+ if (start >= special) {
+ /*
+ * Find the next special character in the string.
+ */
+
+ for (special = start; special < end; special++) {
+ ch = *special;
+ if ((ch == '\t') || (ch == '\n')) {
+ break;
+ }
+ }
+ }
+
+ /*
+ * Special points at the next special character (or the end of the
+ * string). Process characters between start and special.
+ */
+
+ if ((maxX >= 0) && (curX >= maxX)) {
+ break;
+ }
+#if TK_DRAW_IN_CONTEXT
+ start += TkpMeasureCharsInContext(tkfont, source, maxBytes,
+ start - source, special - start,
+ maxX >= 0 ? maxX - curX : -1, flags, &width);
+#else
+ (void) maxBytes;
+ start += Tk_MeasureChars(tkfont, start, special - start,
+ maxX >= 0 ? maxX - curX : -1, flags, &width);
+#endif /* TK_DRAW_IN_CONTEXT */
+ curX += width;
+ if (start < special) {
+ /*
+ * No more chars fit in line.
+ */
+
+ break;
+ }
+ if (special < end) {
+ if (ch != '\t') {
+ break;
+ }
+ start++;
+ }
+ }
+
+ *nextXPtr = curX;
+ return start - (source+rangeStart);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TextGetScrollInfoObj --
+ *
+ * This function is invoked to parse "xview" and "yview" scrolling
+ * commands for text widgets using the new scrolling command syntax
+ * ("moveto" or "scroll" options). It extends the public
+ * Tk_GetScrollInfoObj function with the addition of "pixels" as a valid
+ * unit alongside "pages" and "units". It is a shame the core API isn't
+ * more flexible in this regard.
+ *
+ * Results:
+ * The return value is either TKTEXT_SCROLL_MOVETO, TKTEXT_SCROLL_PAGES,
+ * TKTEXT_SCROLL_UNITS, TKTEXT_SCROLL_PIXELS or TKTEXT_SCROLL_ERROR. This
+ * indicates whether the command was successfully parsed and what form
+ * the command took. If TKTEXT_SCROLL_MOVETO, *dblPtr is filled in with
+ * the desired position; if TKTEXT_SCROLL_PAGES, TKTEXT_SCROLL_PIXELS or
+ * TKTEXT_SCROLL_UNITS, *intPtr is filled in with the number of
+ * pages/pixels/lines to move (may be negative); if TKTEXT_SCROLL_ERROR,
+ * the interp's result contains an error message.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TextGetScrollInfoObj(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ TkText *textPtr, /* Information about the text widget. */
+ int objc, /* # arguments for command. */
+ Tcl_Obj *const objv[], /* Arguments for command. */
+ double *dblPtr, /* Filled in with argument "moveto" option, if
+ * any. */
+ int *intPtr) /* Filled in with number of pages or lines or
+ * pixels to scroll, if any. */
+{
+ static const char *const subcommands[] = {
+ "moveto", "scroll", NULL
+ };
+ enum viewSubcmds {
+ VIEW_MOVETO, VIEW_SCROLL
+ };
+ static const char *const units[] = {
+ "units", "pages", "pixels", NULL
+ };
+ enum viewUnits {
+ VIEW_SCROLL_UNITS, VIEW_SCROLL_PAGES, VIEW_SCROLL_PIXELS
+ };
+ int index;
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[2], subcommands,
+ sizeof(char *), "option", 0, &index) != TCL_OK) {
+ return TKTEXT_SCROLL_ERROR;
+ }
+
+ switch ((enum viewSubcmds) index) {
+ case VIEW_MOVETO:
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "fraction");
+ return TKTEXT_SCROLL_ERROR;
+ }
+ if (Tcl_GetDoubleFromObj(interp, objv[3], dblPtr) != TCL_OK) {
+ return TKTEXT_SCROLL_ERROR;
+ }
+ return TKTEXT_SCROLL_MOVETO;
+ case VIEW_SCROLL:
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 3, objv, "number units|pages|pixels");
+ return TKTEXT_SCROLL_ERROR;
+ }
+ if (Tcl_GetIndexFromObjStruct(interp, objv[4], units,
+ sizeof(char *), "argument", 0, &index) != TCL_OK) {
+ return TKTEXT_SCROLL_ERROR;
+ }
+ switch ((enum viewUnits) index) {
+ case VIEW_SCROLL_PAGES:
+ if (Tcl_GetIntFromObj(interp, objv[3], intPtr) != TCL_OK) {
+ return TKTEXT_SCROLL_ERROR;
+ }
+ return TKTEXT_SCROLL_PAGES;
+ case VIEW_SCROLL_PIXELS:
+ if (Tk_GetPixelsFromObj(interp, textPtr->tkwin, objv[3],
+ intPtr) != TCL_OK) {
+ return TKTEXT_SCROLL_ERROR;
+ }
+ return TKTEXT_SCROLL_PIXELS;
+ case VIEW_SCROLL_UNITS:
+ if (Tcl_GetIntFromObj(interp, objv[3], intPtr) != TCL_OK) {
+ return TKTEXT_SCROLL_ERROR;
+ }
+ return TKTEXT_SCROLL_UNITS;
+ }
+ }
+ Tcl_Panic("unexpected switch fallthrough");
+ return TKTEXT_SCROLL_ERROR;
+}
+
+#if TK_LAYOUT_WITH_BASE_CHUNKS
+/*
+ *----------------------------------------------------------------------
+ *
+ * FinalizeBaseChunk --
+ *
+ * This procedure makes sure that all the chunks of the stretch are
+ * up-to-date. It is invoked when the LayoutProc has been called for all
+ * chunks and the base chunk is stable.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The CharInfo.chars of all dependent chunks point into
+ * BaseCharInfo.baseChars for easy access (and compatibility).
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FinalizeBaseChunk(
+ TkTextDispChunk *addChunkPtr)
+ /* An additional chunk to add to the stretch,
+ * even though it may not be in the linked
+ * list yet. Used by the LayoutProc, otherwise
+ * NULL. */
+{
+ const char *baseChars;
+ TkTextDispChunk *chunkPtr;
+ CharInfo *ciPtr;
+#if TK_DRAW_IN_CONTEXT
+ int widthAdjust = 0;
+ int newwidth;
+#endif /* TK_DRAW_IN_CONTEXT */
+
+ if (baseCharChunkPtr == NULL) {
+ return;
+ }
+
+ baseChars = Tcl_DStringValue(
+ &((BaseCharInfo *) baseCharChunkPtr->clientData)->baseChars);
+
+ for (chunkPtr = baseCharChunkPtr; chunkPtr != NULL;
+ chunkPtr = chunkPtr->nextPtr) {
+#if TK_DRAW_IN_CONTEXT
+ chunkPtr->x += widthAdjust;
+#endif /* TK_DRAW_IN_CONTEXT */
+
+ if (chunkPtr->displayProc != CharDisplayProc) {
+ continue;
+ }
+ ciPtr = chunkPtr->clientData;
+ if (ciPtr->baseChunkPtr != baseCharChunkPtr) {
+ break;
+ }
+ ciPtr->chars = baseChars + ciPtr->baseOffset;
+
+#if TK_DRAW_IN_CONTEXT
+ newwidth = 0;
+ CharChunkMeasureChars(chunkPtr, NULL, 0, 0, -1, 0, -1, 0, &newwidth);
+ if (newwidth < chunkPtr->width) {
+ widthAdjust += newwidth - chunkPtr->width;
+ chunkPtr->width = newwidth;
+ }
+#endif /* TK_DRAW_IN_CONTEXT */
+ }
+
+ if (addChunkPtr != NULL) {
+ ciPtr = addChunkPtr->clientData;
+ ciPtr->chars = baseChars + ciPtr->baseOffset;
+
+#if TK_DRAW_IN_CONTEXT
+ addChunkPtr->x += widthAdjust;
+ CharChunkMeasureChars(addChunkPtr, NULL, 0, 0, -1, 0, -1, 0,
+ &addChunkPtr->width);
+#endif /* TK_DRAW_IN_CONTEXT */
+ }
+
+ baseCharChunkPtr = NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeBaseChunk --
+ *
+ * This procedure makes sure that all the chunks of the stretch are
+ * disconnected from the base chunk and the base chunk specific data is
+ * freed. It is invoked from the UndisplayProc. The procedure doesn't
+ * ckfree the base chunk clientData itself, that's up to the main
+ * UndisplayProc.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The CharInfo.chars of all dependent chunks are set to NULL. Memory
+ * that belongs specifically to the base chunk is freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FreeBaseChunk(
+ TkTextDispChunk *baseChunkPtr)
+ /* The base chunk of the stretch and head of
+ * the linked list. */
+{
+ TkTextDispChunk *chunkPtr;
+ CharInfo *ciPtr;
+
+ if (baseCharChunkPtr == baseChunkPtr) {
+ baseCharChunkPtr = NULL;
+ }
+
+ for (chunkPtr=baseChunkPtr; chunkPtr!=NULL; chunkPtr=chunkPtr->nextPtr) {
+ if (chunkPtr->undisplayProc != CharUndisplayProc) {
+ continue;
+ }
+ ciPtr = chunkPtr->clientData;
+ if (ciPtr->baseChunkPtr != baseChunkPtr) {
+ break;
+ }
+
+ ciPtr->baseChunkPtr = NULL;
+ ciPtr->chars = NULL;
+ }
+
+ if (baseChunkPtr) {
+ Tcl_DStringFree(&((BaseCharInfo *) baseChunkPtr->clientData)->baseChars);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * IsSameFGStyle --
+ *
+ * Compare the foreground attributes of two styles. Specifically must
+ * consider: foreground color, font, font style and font decorations,
+ * elide, "offset" and foreground stipple. Do *not* consider: background
+ * color, border, relief or background stipple.
+ *
+ * If we use TkpDrawCharsInContext(), we also don't need to check
+ * foreground color, font decorations, elide, offset and foreground
+ * stipple, so all that is left is font (including font size and font
+ * style) and "offset".
+ *
+ * Results:
+ * 1 if the two styles match, 0 otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+IsSameFGStyle(
+ TextStyle *style1,
+ TextStyle *style2)
+{
+ StyleValues *sv1;
+ StyleValues *sv2;
+
+ if (style1 == style2) {
+ return 1;
+ }
+
+#if !TK_DRAW_IN_CONTEXT
+ if (
+#ifdef MAC_OSX_TK
+ !TkMacOSXCompareColors(style1->fgGC->foreground,
+ style2->fgGC->foreground)
+#else
+ style1->fgGC->foreground != style2->fgGC->foreground
+#endif
+ ) {
+ return 0;
+ }
+#endif /* !TK_DRAW_IN_CONTEXT */
+
+ sv1 = style1->sValuePtr;
+ sv2 = style2->sValuePtr;
+
+#if TK_DRAW_IN_CONTEXT
+ return sv1->tkfont == sv2->tkfont && sv1->offset == sv2->offset;
+#else
+ return sv1->tkfont == sv2->tkfont
+ && sv1->underline == sv2->underline
+ && sv1->overstrike == sv2->overstrike
+ && sv1->elide == sv2->elide
+ && sv1->offset == sv2->offset
+ && sv1->fgStipple == sv1->fgStipple;
+#endif /* TK_DRAW_IN_CONTEXT */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * RemoveFromBaseChunk --
+ *
+ * This procedure removes a chunk from the stretch as a result of
+ * UndisplayProc. The chunk in question should be the last in a stretch.
+ * This happens during re-layouting of the break position.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The characters that belong to this chunk are removed from the base
+ * chunk. It is assumed that LayoutProc and FinalizeBaseChunk are called
+ * next to repair any damage that this causes to the integrity of the
+ * stretch and the other chunks. For that reason the base chunk is also
+ * put into baseCharChunkPtr automatically, so that LayoutProc can resume
+ * correctly.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+RemoveFromBaseChunk(
+ TkTextDispChunk *chunkPtr) /* The chunk to remove from the end of the
+ * stretch. */
+{
+ CharInfo *ciPtr;
+ BaseCharInfo *bciPtr;
+
+ if (chunkPtr->displayProc != CharDisplayProc) {
+#ifdef DEBUG_LAYOUT_WITH_BASE_CHUNKS
+ fprintf(stderr,"RemoveFromBaseChunk called with wrong chunk type\n");
+#endif
+ return;
+ }
+
+ /*
+ * Reinstitute this base chunk for re-layout.
+ */
+
+ ciPtr = chunkPtr->clientData;
+ baseCharChunkPtr = ciPtr->baseChunkPtr;
+
+ /*
+ * Remove the chunk data from the base chunk data.
+ */
+
+ bciPtr = baseCharChunkPtr->clientData;
+
+#ifdef DEBUG_LAYOUT_WITH_BASE_CHUNKS
+ if ((ciPtr->baseOffset + ciPtr->numBytes)
+ != Tcl_DStringLength(&bciPtr->baseChars)) {
+ fprintf(stderr,"RemoveFromBaseChunk called with wrong chunk "
+ "(not last)\n");
+ }
+#endif
+
+ Tcl_DStringSetLength(&bciPtr->baseChars, ciPtr->baseOffset);
+
+ /*
+ * Invalidate the stored pixel width of the base chunk.
+ */
+
+ bciPtr->width = -1;
+}
+#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkTextImage.c b/tk8.6/generic/tkTextImage.c
new file mode 100644
index 0000000..41dd448
--- /dev/null
+++ b/tk8.6/generic/tkTextImage.c
@@ -0,0 +1,855 @@
+/*
+ * tkImage.c --
+ *
+ * This file contains code that allows images to be nested inside text
+ * widgets. It also implements the "image" widget command for texts.
+ *
+ * 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.
+ */
+
+#include "tkPort.h"
+#include "tkText.h"
+
+/*
+ * Macro that determines the size of an embedded image segment:
+ */
+
+#define EI_SEG_SIZE \
+ ((unsigned) (Tk_Offset(TkTextSegment, body) + sizeof(TkTextEmbImage)))
+
+/*
+ * Prototypes for functions defined in this file:
+ */
+
+static TkTextSegment * EmbImageCleanupProc(TkTextSegment *segPtr,
+ TkTextLine *linePtr);
+static void EmbImageCheckProc(TkTextSegment *segPtr,
+ TkTextLine *linePtr);
+static void EmbImageBboxProc(TkText *textPtr,
+ TkTextDispChunk *chunkPtr, int index, int y,
+ int lineHeight, int baseline, int *xPtr, int *yPtr,
+ int *widthPtr, int *heightPtr);
+static int EmbImageConfigure(TkText *textPtr,
+ TkTextSegment *eiPtr, int objc,
+ Tcl_Obj *const objv[]);
+static int EmbImageDeleteProc(TkTextSegment *segPtr,
+ TkTextLine *linePtr, int treeGone);
+static void EmbImageDisplayProc(TkText *textPtr,
+ TkTextDispChunk *chunkPtr, int x, int y,
+ int lineHeight, int baseline, Display *display,
+ Drawable dst, int screenY);
+static int EmbImageLayoutProc(TkText *textPtr,
+ TkTextIndex *indexPtr, TkTextSegment *segPtr,
+ int offset, int maxX, int maxChars,
+ int noCharsYet, TkWrapMode wrapMode,
+ TkTextDispChunk *chunkPtr);
+static void EmbImageProc(ClientData clientData, int x, int y,
+ int width, int height, int imageWidth,
+ int imageHeight);
+
+/*
+ * The following structure declares the "embedded image" segment type.
+ */
+
+const Tk_SegType tkTextEmbImageType = {
+ "image", /* name */
+ 0, /* leftGravity */
+ NULL, /* splitProc */
+ EmbImageDeleteProc, /* deleteProc */
+ EmbImageCleanupProc, /* cleanupProc */
+ NULL, /* lineChangeProc */
+ EmbImageLayoutProc, /* layoutProc */
+ EmbImageCheckProc /* checkProc */
+};
+
+/*
+ * Definitions for alignment values:
+ */
+
+static const char *const alignStrings[] = {
+ "baseline", "bottom", "center", "top", NULL
+};
+
+typedef enum {
+ ALIGN_BASELINE, ALIGN_BOTTOM, ALIGN_CENTER, ALIGN_TOP
+} alignMode;
+
+/*
+ * Information used for parsing image configuration options:
+ */
+
+static const Tk_OptionSpec optionSpecs[] = {
+ {TK_OPTION_STRING_TABLE, "-align", NULL, NULL,
+ "center", -1, Tk_Offset(TkTextEmbImage, align),
+ 0, alignStrings, 0},
+ {TK_OPTION_PIXELS, "-padx", NULL, NULL,
+ "0", -1, Tk_Offset(TkTextEmbImage, padX), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-pady", NULL, NULL,
+ "0", -1, Tk_Offset(TkTextEmbImage, padY), 0, 0, 0},
+ {TK_OPTION_STRING, "-image", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextEmbImage, imageString),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-name", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextEmbImage, imageName),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}
+};
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkTextImageCmd --
+ *
+ * This function implements the "image" widget command for text widgets.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result or error.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkTextImageCmd(
+ register TkText *textPtr, /* Information about text widget. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. Someone else has already
+ * parsed this command enough to know that
+ * objv[1] is "image". */
+{
+ int idx;
+ register TkTextSegment *eiPtr;
+ TkTextIndex index;
+ static const char *const optionStrings[] = {
+ "cget", "configure", "create", "names", NULL
+ };
+ enum opts {
+ CMD_CGET, CMD_CONF, CMD_CREATE, CMD_NAMES
+ };
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObjStruct(interp, objv[2], optionStrings,
+ sizeof(char *), "option", 0, &idx) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch ((enum opts) idx) {
+ case CMD_CGET: {
+ Tcl_Obj *objPtr;
+
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index option");
+ return TCL_ERROR;
+ }
+ if (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ eiPtr = TkTextIndexToSeg(&index, NULL);
+ if (eiPtr->typePtr != &tkTextEmbImageType) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "no embedded image at index \"%s\"",
+ Tcl_GetString(objv[3])));
+ Tcl_SetErrorCode(interp, "TK", "TEXT", "NO_IMAGE", NULL);
+ return TCL_ERROR;
+ }
+ objPtr = Tk_GetOptionValue(interp, (char *) &eiPtr->body.ei,
+ eiPtr->body.ei.optionTable, objv[4], textPtr->tkwin);
+ if (objPtr == NULL) {
+ return TCL_ERROR;
+ } else {
+ Tcl_SetObjResult(interp, objPtr);
+ return TCL_OK;
+ }
+ }
+ case CMD_CONF:
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index ?-option value ...?");
+ return TCL_ERROR;
+ }
+ if (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ eiPtr = TkTextIndexToSeg(&index, NULL);
+ if (eiPtr->typePtr != &tkTextEmbImageType) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "no embedded image at index \"%s\"",
+ Tcl_GetString(objv[3])));
+ Tcl_SetErrorCode(interp, "TK", "TEXT", "NO_IMAGE", NULL);
+ return TCL_ERROR;
+ }
+ if (objc <= 5) {
+ Tcl_Obj *objPtr = Tk_GetOptionInfo(interp,
+ (char *) &eiPtr->body.ei, eiPtr->body.ei.optionTable,
+ (objc == 5) ? objv[4] : NULL, textPtr->tkwin);
+
+ if (objPtr == NULL) {
+ return TCL_ERROR;
+ } else {
+ Tcl_SetObjResult(interp, objPtr);
+ return TCL_OK;
+ }
+ } else {
+ TkTextChanged(textPtr->sharedTextPtr, NULL, &index, &index);
+
+ /*
+ * It's probably not true that all window configuration can change
+ * the line height, so we could be more efficient here and only
+ * call this when necessary.
+ */
+
+ TkTextInvalidateLineMetrics(textPtr->sharedTextPtr, NULL,
+ index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY);
+ return EmbImageConfigure(textPtr, eiPtr, objc-4, objv+4);
+ }
+ case CMD_CREATE: {
+ int lineIndex;
+
+ /*
+ * Add a new image. Find where to put the new image, and mark that
+ * position for redisplay.
+ */
+
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index ?-option value ...?");
+ return TCL_ERROR;
+ }
+ if (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Don't allow insertions on the last (dummy) line of the text.
+ */
+
+ lineIndex = TkBTreeLinesTo(textPtr, index.linePtr);
+ if (lineIndex == TkBTreeNumLines(textPtr->sharedTextPtr->tree,
+ textPtr)) {
+ lineIndex--;
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,
+ lineIndex, 1000000, &index);
+ }
+
+ /*
+ * Create the new image segment and initialize it.
+ */
+
+ eiPtr = ckalloc(EI_SEG_SIZE);
+ eiPtr->typePtr = &tkTextEmbImageType;
+ eiPtr->size = 1;
+ eiPtr->body.ei.sharedTextPtr = textPtr->sharedTextPtr;
+ eiPtr->body.ei.linePtr = NULL;
+ eiPtr->body.ei.imageName = NULL;
+ eiPtr->body.ei.imageString = NULL;
+ eiPtr->body.ei.name = NULL;
+ eiPtr->body.ei.image = NULL;
+ eiPtr->body.ei.align = ALIGN_CENTER;
+ eiPtr->body.ei.padX = eiPtr->body.ei.padY = 0;
+ eiPtr->body.ei.chunkCount = 0;
+ eiPtr->body.ei.optionTable = Tk_CreateOptionTable(interp, optionSpecs);
+
+ /*
+ * Link the segment into the text widget, then configure it (delete it
+ * again if the configuration fails).
+ */
+
+ TkTextChanged(textPtr->sharedTextPtr, NULL, &index, &index);
+ TkBTreeLinkSegment(eiPtr, &index);
+ if (EmbImageConfigure(textPtr, eiPtr, objc-4, objv+4) != TCL_OK) {
+ TkTextIndex index2;
+
+ TkTextIndexForwChars(NULL, &index, 1, &index2, COUNT_INDICES);
+ TkBTreeDeleteIndexRange(textPtr->sharedTextPtr->tree, &index, &index2);
+ return TCL_ERROR;
+ }
+ TkTextInvalidateLineMetrics(textPtr->sharedTextPtr, NULL,
+ index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY);
+ return TCL_OK;
+ }
+ case CMD_NAMES: {
+ Tcl_HashSearch search;
+ Tcl_HashEntry *hPtr;
+ Tcl_Obj *resultObj;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ return TCL_ERROR;
+ }
+ resultObj = Tcl_NewObj();
+ for (hPtr = Tcl_FirstHashEntry(&textPtr->sharedTextPtr->imageTable,
+ &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
+ Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(
+ Tcl_GetHashKey(&textPtr->sharedTextPtr->markTable, hPtr),
+ -1));
+ }
+ Tcl_SetObjResult(interp, resultObj);
+ return TCL_OK;
+ }
+ default:
+ Tcl_Panic("unexpected switch fallthrough");
+ }
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EmbImageConfigure --
+ *
+ * This function is called to handle configuration options for an
+ * embedded image, using an objc/objv list.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If TCL_ERROR is returned,
+ * then the interp's result contains an error message..
+ *
+ * Side effects:
+ * Configuration information for the embedded image changes, such as
+ * alignment, or name of the image.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+EmbImageConfigure(
+ TkText *textPtr, /* Information about text widget that contains
+ * embedded image. */
+ TkTextSegment *eiPtr, /* Embedded image to be configured. */
+ int objc, /* Number of strings in objv. */
+ Tcl_Obj *const objv[]) /* Array of strings describing configuration
+ * options. */
+{
+ Tk_Image image;
+ Tcl_DString newName;
+ Tcl_HashEntry *hPtr;
+ Tcl_HashSearch search;
+ char *name;
+ int dummy;
+ int count = 0; /* The counter for picking a unique name */
+ int conflict = 0; /* True if we have a name conflict */
+ size_t len; /* length of image name */
+
+ if (Tk_SetOptions(textPtr->interp, (char *) &eiPtr->body.ei,
+ eiPtr->body.ei.optionTable,
+ objc, objv, textPtr->tkwin, NULL, NULL) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Create the image. Save the old image around and don't free it until
+ * after the new one is allocated. This keeps the reference count from
+ * going to zero so the image doesn't have to be recreated if it hasn't
+ * changed.
+ */
+
+ if (eiPtr->body.ei.imageString != NULL) {
+ image = Tk_GetImage(textPtr->interp, textPtr->tkwin,
+ eiPtr->body.ei.imageString, EmbImageProc, eiPtr);
+ if (image == NULL) {
+ return TCL_ERROR;
+ }
+ } else {
+ image = NULL;
+ }
+ if (eiPtr->body.ei.image != NULL) {
+ Tk_FreeImage(eiPtr->body.ei.image);
+ }
+ eiPtr->body.ei.image = image;
+
+ if (eiPtr->body.ei.name != NULL) {
+ return TCL_OK;
+ }
+
+ /*
+ * Find a unique name for this image. Use imageName (or imageString) if
+ * available, otherwise tack on a #nn and use it. If a name is already
+ * associated with this image, delete the name.
+ */
+
+ name = eiPtr->body.ei.imageName;
+ if (name == NULL) {
+ name = eiPtr->body.ei.imageString;
+ }
+ if (name == NULL) {
+ Tcl_SetObjResult(textPtr->interp, Tcl_NewStringObj(
+ "Either a \"-name\" or a \"-image\" argument must be"
+ " provided to the \"image create\" subcommand", -1));
+ Tcl_SetErrorCode(textPtr->interp, "TK", "TEXT", "IMAGE_CREATE_USAGE",
+ NULL);
+ return TCL_ERROR;
+ }
+ len = strlen(name);
+ for (hPtr = Tcl_FirstHashEntry(&textPtr->sharedTextPtr->imageTable,
+ &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
+ char *haveName =
+ Tcl_GetHashKey(&textPtr->sharedTextPtr->imageTable, hPtr);
+
+ if (strncmp(name, haveName, len) == 0) {
+ int newVal = 0;
+
+ sscanf(haveName+len, "#%d", &newVal);
+ if (newVal > count) {
+ count = newVal;
+ }
+ if (len == strlen(haveName)) {
+ conflict = 1;
+ }
+ }
+ }
+
+ Tcl_DStringInit(&newName);
+ Tcl_DStringAppend(&newName, name, -1);
+
+ if (conflict) {
+ char buf[4 + TCL_INTEGER_SPACE];
+
+ sprintf(buf, "#%d", count+1);
+ Tcl_DStringAppend(&newName, buf, -1);
+ }
+ name = Tcl_DStringValue(&newName);
+ hPtr = Tcl_CreateHashEntry(&textPtr->sharedTextPtr->imageTable, name,
+ &dummy);
+ Tcl_SetHashValue(hPtr, eiPtr);
+ Tcl_SetObjResult(textPtr->interp, Tcl_NewStringObj(name, -1));
+ eiPtr->body.ei.name = ckalloc(Tcl_DStringLength(&newName) + 1);
+ strcpy(eiPtr->body.ei.name, name);
+ Tcl_DStringFree(&newName);
+
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EmbImageDeleteProc --
+ *
+ * This function is invoked by the text B-tree code whenever an embedded
+ * image lies in a range of characters being deleted.
+ *
+ * Results:
+ * Returns 0 to indicate that the deletion has been accepted.
+ *
+ * Side effects:
+ * The embedded image is deleted, if it exists, and any resources
+ * associated with it are released.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+EmbImageDeleteProc(
+ TkTextSegment *eiPtr, /* Segment being deleted. */
+ TkTextLine *linePtr, /* Line containing segment. */
+ int treeGone) /* Non-zero means the entire tree is being
+ * deleted, so everything must get cleaned
+ * up. */
+{
+ Tcl_HashEntry *hPtr;
+
+ if (eiPtr->body.ei.image != NULL) {
+ hPtr = Tcl_FindHashEntry(&eiPtr->body.ei.sharedTextPtr->imageTable,
+ eiPtr->body.ei.name);
+ if (hPtr != NULL) {
+ /*
+ * (It's possible for there to be no hash table entry for this
+ * image, if an error occurred while creating the image segment
+ * but before the image got added to the table)
+ */
+
+ Tcl_DeleteHashEntry(hPtr);
+ }
+ Tk_FreeImage(eiPtr->body.ei.image);
+ }
+
+ /*
+ * No need to supply a tkwin argument, since we have no window-specific
+ * options.
+ */
+
+ Tk_FreeConfigOptions((char *) &eiPtr->body.ei, eiPtr->body.ei.optionTable,
+ NULL);
+ if (eiPtr->body.ei.name) {
+ ckfree(eiPtr->body.ei.name);
+ }
+ ckfree(eiPtr);
+ return 0;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EmbImageCleanupProc --
+ *
+ * This function is invoked by the B-tree code whenever a segment
+ * containing an embedded image is moved from one line to another.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The linePtr field of the segment gets updated.
+ *
+ *--------------------------------------------------------------
+ */
+
+static TkTextSegment *
+EmbImageCleanupProc(
+ TkTextSegment *eiPtr, /* Mark segment that's being moved. */
+ TkTextLine *linePtr) /* Line that now contains segment. */
+{
+ eiPtr->body.ei.linePtr = linePtr;
+ return eiPtr;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EmbImageLayoutProc --
+ *
+ * This function is the "layoutProc" for embedded image segments.
+ *
+ * Results:
+ * 1 is returned to indicate that the segment should be displayed. The
+ * chunkPtr structure is filled in.
+ *
+ * Side effects:
+ * None, except for filling in chunkPtr.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /*ARGSUSED*/
+static int
+EmbImageLayoutProc(
+ TkText *textPtr, /* Text widget being layed out. */
+ TkTextIndex *indexPtr, /* Identifies first character in chunk. */
+ TkTextSegment *eiPtr, /* Segment corresponding to indexPtr. */
+ int offset, /* Offset within segPtr corresponding to
+ * indexPtr (always 0). */
+ int maxX, /* Chunk must not occupy pixels at this
+ * position or higher. */
+ int maxChars, /* Chunk must not include more than this many
+ * characters. */
+ int noCharsYet, /* Non-zero means no characters have been
+ * assigned to this line yet. */
+ TkWrapMode wrapMode, /* Wrap mode to use for line:
+ * TEXT_WRAPMODE_CHAR, TEXT_WRAPMODE_NONE, or
+ * TEXT_WRAPMODE_WORD. */
+ register TkTextDispChunk *chunkPtr)
+ /* Structure to fill in with information about
+ * this chunk. The x field has already been
+ * set by the caller. */
+{
+ int width, height;
+
+ if (offset != 0) {
+ Tcl_Panic("Non-zero offset in EmbImageLayoutProc");
+ }
+
+ /*
+ * See if there's room for this image on this line.
+ */
+
+ if (eiPtr->body.ei.image == NULL) {
+ width = 0;
+ height = 0;
+ } else {
+ Tk_SizeOfImage(eiPtr->body.ei.image, &width, &height);
+ width += 2*eiPtr->body.ei.padX;
+ height += 2*eiPtr->body.ei.padY;
+ }
+ if ((width > (maxX - chunkPtr->x))
+ && !noCharsYet && (textPtr->wrapMode != TEXT_WRAPMODE_NONE)) {
+ return 0;
+ }
+
+ /*
+ * Fill in the chunk structure.
+ */
+
+ chunkPtr->displayProc = EmbImageDisplayProc;
+ chunkPtr->undisplayProc = NULL;
+ chunkPtr->measureProc = NULL;
+ chunkPtr->bboxProc = EmbImageBboxProc;
+ chunkPtr->numBytes = 1;
+ if (eiPtr->body.ei.align == ALIGN_BASELINE) {
+ chunkPtr->minAscent = height - eiPtr->body.ei.padY;
+ chunkPtr->minDescent = eiPtr->body.ei.padY;
+ chunkPtr->minHeight = 0;
+ } else {
+ chunkPtr->minAscent = 0;
+ chunkPtr->minDescent = 0;
+ chunkPtr->minHeight = height;
+ }
+ chunkPtr->width = width;
+ chunkPtr->breakIndex = -1;
+ chunkPtr->breakIndex = 1;
+ chunkPtr->clientData = eiPtr;
+ eiPtr->body.ei.chunkCount += 1;
+ return 1;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EmbImageCheckProc --
+ *
+ * This function is invoked by the B-tree code to perform consistency
+ * checks on embedded images.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The function panics if it detects anything wrong with the embedded
+ * image.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+EmbImageCheckProc(
+ TkTextSegment *eiPtr, /* Segment to check. */
+ TkTextLine *linePtr) /* Line containing segment. */
+{
+ if (eiPtr->nextPtr == NULL) {
+ Tcl_Panic("EmbImageCheckProc: embedded image is last segment in line");
+ }
+ if (eiPtr->size != 1) {
+ Tcl_Panic("EmbImageCheckProc: embedded image has size %d",
+ eiPtr->size);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EmbImageDisplayProc --
+ *
+ * This function is invoked by the text displaying code when it is time
+ * to actually draw an embedded image chunk on the screen.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The embedded image gets moved to the correct location and drawn onto
+ * the display.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+EmbImageDisplayProc(
+ TkText *textPtr,
+ TkTextDispChunk *chunkPtr, /* Chunk that is to be drawn. */
+ int x, /* X-position in dst at which to draw this
+ * chunk (differs from the x-position in the
+ * chunk because of scrolling). */
+ int y, /* Top of rectangular bounding box for line:
+ * tells where to draw this chunk in dst
+ * (x-position is in the chunk itself). */
+ int lineHeight, /* Total height of line. */
+ int baseline, /* Offset of baseline from y. */
+ Display *display, /* Display to use for drawing. */
+ Drawable dst, /* Pixmap or window in which to draw */
+ int screenY) /* Y-coordinate in text window that
+ * corresponds to y. */
+{
+ TkTextSegment *eiPtr = chunkPtr->clientData;
+ int lineX, imageX, imageY, width, height;
+ Tk_Image image;
+
+ image = eiPtr->body.ei.image;
+ if (image == NULL) {
+ return;
+ }
+ if ((x + chunkPtr->width) <= 0) {
+ return;
+ }
+
+ /*
+ * Compute the image's location and size in the text widget, taking into
+ * account the align value for the image.
+ */
+
+ EmbImageBboxProc(textPtr, chunkPtr, 0, y, lineHeight, baseline, &lineX,
+ &imageY, &width, &height);
+ imageX = lineX - chunkPtr->x + x;
+
+ Tk_RedrawImage(image, 0, 0, width, height, dst, imageX, imageY);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EmbImageBboxProc --
+ *
+ * This function is called to compute the bounding box of the area
+ * occupied by an embedded image.
+ *
+ * Results:
+ * There is no return value. *xPtr and *yPtr are filled in with the
+ * coordinates of the upper left corner of the image, and *widthPtr and
+ * *heightPtr are filled in with the dimensions of the image in pixels.
+ * Note: not all of the returned bbox is necessarily visible on the
+ * screen (the rightmost part might be off-screen to the right, and the
+ * bottommost part might be off-screen to the bottom).
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+EmbImageBboxProc(
+ TkText *textPtr,
+ TkTextDispChunk *chunkPtr, /* Chunk containing desired char. */
+ int index, /* Index of desired character within the
+ * chunk. */
+ int y, /* Topmost pixel in area allocated for this
+ * line. */
+ int lineHeight, /* Total height of line. */
+ int baseline, /* Location of line's baseline, in pixels
+ * measured down from y. */
+ int *xPtr, int *yPtr, /* Gets filled in with coords of character's
+ * upper-left pixel. */
+ int *widthPtr, /* Gets filled in with width of image, in
+ * pixels. */
+ int *heightPtr) /* Gets filled in with height of image, in
+ * pixels. */
+{
+ TkTextSegment *eiPtr = chunkPtr->clientData;
+ Tk_Image image;
+
+ image = eiPtr->body.ei.image;
+ if (image != NULL) {
+ Tk_SizeOfImage(image, widthPtr, heightPtr);
+ } else {
+ *widthPtr = 0;
+ *heightPtr = 0;
+ }
+
+ *xPtr = chunkPtr->x + eiPtr->body.ei.padX;
+
+ switch (eiPtr->body.ei.align) {
+ case ALIGN_BOTTOM:
+ *yPtr = y + (lineHeight - *heightPtr - eiPtr->body.ei.padY);
+ break;
+ case ALIGN_CENTER:
+ *yPtr = y + (lineHeight - *heightPtr)/2;
+ break;
+ case ALIGN_TOP:
+ *yPtr = y + eiPtr->body.ei.padY;
+ break;
+ case ALIGN_BASELINE:
+ *yPtr = y + (baseline - *heightPtr);
+ break;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkTextImageIndex --
+ *
+ * Given the name of an embedded image within a text widget, returns an
+ * index corresponding to the image's position in the text.
+ *
+ * Results:
+ * The return value is 1 if there is an embedded image by the given name
+ * in the text widget, 0 otherwise. If the image exists, *indexPtr is
+ * filled in with its index.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkTextImageIndex(
+ TkText *textPtr, /* Text widget containing image. */
+ const char *name, /* Name of image. */
+ TkTextIndex *indexPtr) /* Index information gets stored here. */
+{
+ Tcl_HashEntry *hPtr;
+ TkTextSegment *eiPtr;
+
+ if (textPtr == NULL) {
+ return 0;
+ }
+
+ hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->imageTable, name);
+ if (hPtr == NULL) {
+ return 0;
+ }
+ eiPtr = Tcl_GetHashValue(hPtr);
+ indexPtr->tree = textPtr->sharedTextPtr->tree;
+ indexPtr->linePtr = eiPtr->body.ei.linePtr;
+ indexPtr->byteIndex = TkTextSegToOffset(eiPtr, indexPtr->linePtr);
+ return 1;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EmbImageProc --
+ *
+ * This function is called by the image code whenever an image or its
+ * contents changes.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The image will be redisplayed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+EmbImageProc(
+ ClientData clientData, /* Pointer to widget record. */
+ int x, int y, /* Upper left pixel (within image) that must
+ * be redisplayed. */
+ int width, int height, /* Dimensions of area to redisplay (may be
+ * <= 0). */
+ int imgWidth, int imgHeight)/* New dimensions of image. */
+
+{
+ TkTextSegment *eiPtr = clientData;
+ TkTextIndex index;
+
+ index.tree = eiPtr->body.ei.sharedTextPtr->tree;
+ index.linePtr = eiPtr->body.ei.linePtr;
+ index.byteIndex = TkTextSegToOffset(eiPtr, eiPtr->body.ei.linePtr);
+ TkTextChanged(eiPtr->body.ei.sharedTextPtr, NULL, &index, &index);
+
+ /*
+ * It's probably not true that all image changes can change the line
+ * height, so we could be more efficient here and only call this when
+ * necessary.
+ */
+
+ TkTextInvalidateLineMetrics(eiPtr->body.ei.sharedTextPtr, NULL,
+ index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY);
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkTextIndex.c b/tk8.6/generic/tkTextIndex.c
new file mode 100644
index 0000000..7430197
--- /dev/null
+++ b/tk8.6/generic/tkTextIndex.c
@@ -0,0 +1,2402 @@
+/*
+ * tkTextIndex.c --
+ *
+ * This module provides functions that manipulate indices for text
+ * widgets.
+ *
+ * Copyright (c) 1992-1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "default.h"
+#include "tkInt.h"
+#include "tkText.h"
+
+/*
+ * Index to use to select last character in line (very large integer):
+ */
+
+#define LAST_CHAR 1000000
+
+/*
+ * Modifiers for index parsing: 'display', 'any' or nothing.
+ */
+
+#define TKINDEX_NONE 0
+#define TKINDEX_DISPLAY 1
+#define TKINDEX_ANY 2
+
+/*
+ * Forward declarations for functions defined later in this file:
+ */
+
+static const char * ForwBack(TkText *textPtr, const char *string,
+ TkTextIndex *indexPtr);
+static const char * StartEnd(TkText *textPtr, const char *string,
+ TkTextIndex *indexPtr);
+static int GetIndex(Tcl_Interp *interp, TkSharedText *sharedPtr,
+ TkText *textPtr, const char *string,
+ TkTextIndex *indexPtr, int *canCachePtr);
+static int IndexCountBytesOrdered(const TkText *textPtr,
+ const TkTextIndex *indexPtr1,
+ const TkTextIndex *indexPtr2);
+
+/*
+ * The "textindex" Tcl_Obj definition:
+ */
+
+static void DupTextIndexInternalRep(Tcl_Obj *srcPtr,
+ Tcl_Obj *copyPtr);
+static void FreeTextIndexInternalRep(Tcl_Obj *listPtr);
+static void UpdateStringOfTextIndex(Tcl_Obj *objPtr);
+
+/*
+ * Accessor macros for the "textindex" type.
+ */
+
+#define GET_TEXTINDEX(objPtr) \
+ ((TkTextIndex *) (objPtr)->internalRep.twoPtrValue.ptr1)
+#define GET_INDEXEPOCH(objPtr) \
+ (PTR2INT((objPtr)->internalRep.twoPtrValue.ptr2))
+#define SET_TEXTINDEX(objPtr, indexPtr) \
+ ((objPtr)->internalRep.twoPtrValue.ptr1 = (void *) (indexPtr))
+#define SET_INDEXEPOCH(objPtr, epoch) \
+ ((objPtr)->internalRep.twoPtrValue.ptr2 = INT2PTR(epoch))
+
+/*
+ * Define the 'textindex' object type, which Tk uses to represent indices in
+ * text widgets internally.
+ */
+
+const Tcl_ObjType tkTextIndexType = {
+ "textindex", /* name */
+ FreeTextIndexInternalRep, /* freeIntRepProc */
+ DupTextIndexInternalRep, /* dupIntRepProc */
+ NULL, /* updateStringProc */
+ NULL /* setFromAnyProc */
+};
+
+static void
+FreeTextIndexInternalRep(
+ Tcl_Obj *indexObjPtr) /* TextIndex object with internal rep to
+ * free. */
+{
+ TkTextIndex *indexPtr = GET_TEXTINDEX(indexObjPtr);
+
+ if (indexPtr->textPtr != NULL) {
+ if (indexPtr->textPtr->refCount-- <= 1) {
+ /*
+ * The text widget has been deleted and we need to free it now.
+ */
+
+ ckfree(indexPtr->textPtr);
+ }
+ }
+ ckfree(indexPtr);
+ indexObjPtr->typePtr = NULL;
+}
+
+static void
+DupTextIndexInternalRep(
+ Tcl_Obj *srcPtr, /* TextIndex obj with internal rep to copy. */
+ Tcl_Obj *copyPtr) /* TextIndex obj with internal rep to set. */
+{
+ int epoch;
+ TkTextIndex *dupIndexPtr, *indexPtr;
+
+ dupIndexPtr = ckalloc(sizeof(TkTextIndex));
+ indexPtr = GET_TEXTINDEX(srcPtr);
+ epoch = GET_INDEXEPOCH(srcPtr);
+
+ dupIndexPtr->tree = indexPtr->tree;
+ dupIndexPtr->linePtr = indexPtr->linePtr;
+ dupIndexPtr->byteIndex = indexPtr->byteIndex;
+ dupIndexPtr->textPtr = indexPtr->textPtr;
+ if (dupIndexPtr->textPtr != NULL) {
+ dupIndexPtr->textPtr->refCount++;
+ }
+ SET_TEXTINDEX(copyPtr, dupIndexPtr);
+ SET_INDEXEPOCH(copyPtr, epoch);
+ copyPtr->typePtr = &tkTextIndexType;
+}
+
+/*
+ * This will not be called except by TkTextNewIndexObj below. This is because
+ * if a TkTextIndex is no longer valid, it is not possible to regenerate the
+ * string representation.
+ */
+
+static void
+UpdateStringOfTextIndex(
+ Tcl_Obj *objPtr)
+{
+ char buffer[TK_POS_CHARS];
+ size_t len;
+ const TkTextIndex *indexPtr = GET_TEXTINDEX(objPtr);
+
+ len = TkTextPrintIndex(indexPtr->textPtr, indexPtr, buffer);
+
+ objPtr->bytes = ckalloc(len + 1);
+ strcpy(objPtr->bytes, buffer);
+ objPtr->length = len;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MakeObjIndex --
+ *
+ * This function generates a Tcl_Obj description of an index, suitable
+ * for reading in again later. If the 'textPtr' is NULL then we still
+ * generate an index object, but it's internal description is deemed
+ * non-cacheable, and therefore effectively useless (apart from as a
+ * temporary memory storage). This is used for indices whose meaning is
+ * very temporary (like @0,0 or the name of a mark or tag). The mapping
+ * from such strings/objects to actual TkTextIndex pointers is not stable
+ * to minor text widget changes which we do not track (we track
+ * insertions and deletions).
+ *
+ * Results:
+ * A pointer to an allocated TkTextIndex which will be freed
+ * automatically when the Tcl_Obj is used for other purposes.
+ *
+ * Side effects:
+ * A small amount of memory is allocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static TkTextIndex *
+MakeObjIndex(
+ TkText *textPtr, /* Information about text widget. */
+ Tcl_Obj *objPtr, /* Object containing description of
+ * position. */
+ const TkTextIndex *origPtr) /* Pointer to index. */
+{
+ TkTextIndex *indexPtr = ckalloc(sizeof(TkTextIndex));
+
+ indexPtr->tree = origPtr->tree;
+ indexPtr->linePtr = origPtr->linePtr;
+ indexPtr->byteIndex = origPtr->byteIndex;
+ SET_TEXTINDEX(objPtr, indexPtr);
+ objPtr->typePtr = &tkTextIndexType;
+ indexPtr->textPtr = textPtr;
+
+ if (textPtr != NULL) {
+ textPtr->refCount++;
+ SET_INDEXEPOCH(objPtr, textPtr->sharedTextPtr->stateEpoch);
+ } else {
+ SET_INDEXEPOCH(objPtr, 0);
+ }
+ return indexPtr;
+}
+
+const TkTextIndex *
+TkTextGetIndexFromObj(
+ Tcl_Interp *interp, /* Use this for error reporting. */
+ TkText *textPtr, /* Information about text widget. */
+ Tcl_Obj *objPtr) /* Object containing description of
+ * position. */
+{
+ TkTextIndex index;
+ TkTextIndex *indexPtr = NULL;
+ int cache;
+
+ if (objPtr->typePtr == &tkTextIndexType) {
+ int epoch;
+
+ indexPtr = GET_TEXTINDEX(objPtr);
+ epoch = GET_INDEXEPOCH(objPtr);
+
+ if (epoch == textPtr->sharedTextPtr->stateEpoch) {
+ if (indexPtr->textPtr == textPtr) {
+ return indexPtr;
+ }
+ }
+ }
+
+ /*
+ * The object is either not an index type or referred to a different text
+ * widget, or referred to the correct widget, but it is out of date (text
+ * has been added/deleted since).
+ */
+
+ if (GetIndex(interp, NULL, textPtr, Tcl_GetString(objPtr), &index,
+ &cache) != TCL_OK) {
+ return NULL;
+ }
+
+ if (objPtr->typePtr != NULL) {
+ if (objPtr->bytes == NULL) {
+ objPtr->typePtr->updateStringProc(objPtr);
+ }
+ if (objPtr->typePtr->freeIntRepProc != NULL) {
+ objPtr->typePtr->freeIntRepProc(objPtr);
+ }
+ }
+
+ return MakeObjIndex((cache ? textPtr : NULL), objPtr, &index);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkTextNewIndexObj --
+ *
+ * This function generates a Tcl_Obj description of an index, suitable
+ * for reading in again later. The index generated is effectively stable
+ * to all except insertion/deletion operations on the widget.
+ *
+ * Results:
+ * A new Tcl_Obj with refCount zero.
+ *
+ * Side effects:
+ * A small amount of memory is allocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TkTextNewIndexObj(
+ TkText *textPtr, /* Text widget for this index */
+ const TkTextIndex *indexPtr)/* Pointer to index. */
+{
+ Tcl_Obj *retVal;
+
+ retVal = Tcl_NewObj();
+ retVal->bytes = NULL;
+
+ /*
+ * Assumption that the above call returns an object with:
+ * retVal->typePtr == NULL
+ */
+
+ MakeObjIndex(textPtr, retVal, indexPtr);
+
+ /*
+ * Unfortunately, it isn't possible for us to regenerate the string
+ * representation so we have to create it here, while we can be sure the
+ * contents of the index are still valid.
+ */
+
+ UpdateStringOfTextIndex(retVal);
+ return retVal;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkTextMakePixelIndex --
+ *
+ * Given a pixel index and a byte index, look things up in the B-tree and
+ * fill in a TkTextIndex structure.
+ *
+ * The valid input range for pixelIndex is from 0 to the number of pixels
+ * in the widget-1. Anything outside that range will be rounded to the
+ * closest acceptable value.
+ *
+ * Results:
+ *
+ * The structure at *indexPtr is filled in with information about the
+ * character at pixelIndex (or the closest existing character, if the
+ * specified one doesn't exist), and the number of excess pixels is
+ * returned as a result. This means if the given pixel index is exactly
+ * correct for the top-edge of the indexPtr, then zero will be returned,
+ * and otherwise we will return the calculation 'desired pixelIndex' -
+ * 'actual pixel index of indexPtr'.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TkTextMakePixelIndex(
+ TkText *textPtr, /* The Text Widget */
+ int pixelIndex, /* Pixel-index of desired line (0 means first
+ * pixel of first line of text). */
+ TkTextIndex *indexPtr) /* Structure to fill in. */
+{
+ int pixelOffset = 0;
+
+ indexPtr->tree = textPtr->sharedTextPtr->tree;
+ indexPtr->textPtr = textPtr;
+
+ if (pixelIndex < 0) {
+ pixelIndex = 0;
+ }
+ indexPtr->linePtr = TkBTreeFindPixelLine(textPtr->sharedTextPtr->tree,
+ textPtr, pixelIndex, &pixelOffset);
+
+ /*
+ * 'pixelIndex' was too large, so we try again, just to find the last
+ * pixel in the window.
+ */
+
+ if (indexPtr->linePtr == NULL) {
+ int lastMinusOne = TkBTreeNumPixels(textPtr->sharedTextPtr->tree,
+ textPtr)-1;
+
+ indexPtr->linePtr = TkBTreeFindPixelLine(textPtr->sharedTextPtr->tree,
+ textPtr, lastMinusOne, &pixelOffset);
+ indexPtr->byteIndex = 0;
+ return pixelOffset;
+ }
+ indexPtr->byteIndex = 0;
+
+ if (pixelOffset <= 0) {
+ return 0;
+ }
+ return TkTextMeasureDown(textPtr, indexPtr, pixelOffset);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkTextMakeByteIndex --
+ *
+ * Given a line index and a byte index, look things up in the B-tree and
+ * fill in a TkTextIndex structure.
+ *
+ * Results:
+ * The structure at *indexPtr is filled in with information about the
+ * character at lineIndex and byteIndex (or the closest existing
+ * character, if the specified one doesn't exist), and indexPtr is
+ * returned as result.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+TkTextIndex *
+TkTextMakeByteIndex(
+ TkTextBTree tree, /* Tree that lineIndex and byteIndex refer
+ * to. */
+ const TkText *textPtr,
+ int lineIndex, /* Index of desired line (0 means first line
+ * of text). */
+ int byteIndex, /* Byte index of desired character. */
+ TkTextIndex *indexPtr) /* Structure to fill in. */
+{
+ TkTextSegment *segPtr;
+ int index;
+ const char *p, *start;
+ int ch;
+
+ indexPtr->tree = tree;
+ if (lineIndex < 0) {
+ lineIndex = 0;
+ byteIndex = 0;
+ }
+ if (byteIndex < 0) {
+ byteIndex = 0;
+ }
+ indexPtr->linePtr = TkBTreeFindLine(tree, textPtr, lineIndex);
+ if (indexPtr->linePtr == NULL) {
+ indexPtr->linePtr = TkBTreeFindLine(tree, textPtr,
+ TkBTreeNumLines(tree, textPtr));
+ byteIndex = 0;
+ }
+ if (byteIndex == 0) {
+ indexPtr->byteIndex = byteIndex;
+ return indexPtr;
+ }
+
+ /*
+ * Verify that the index is within the range of the line and points to a
+ * valid character boundary.
+ */
+
+ index = 0;
+ for (segPtr = indexPtr->linePtr->segPtr; ; segPtr = segPtr->nextPtr) {
+ if (segPtr == NULL) {
+ /*
+ * Use the index of the last character in the line. Since the last
+ * character on the line is guaranteed to be a '\n', we can back
+ * up a constant sizeof(char) bytes.
+ */
+
+ indexPtr->byteIndex = index - sizeof(char);
+ break;
+ }
+ if (index + segPtr->size > byteIndex) {
+ indexPtr->byteIndex = byteIndex;
+ if ((byteIndex > index) && (segPtr->typePtr == &tkTextCharType)) {
+ /*
+ * Prevent UTF-8 character from being split up by ensuring
+ * that byteIndex falls on a character boundary. If the index
+ * falls in the middle of a UTF-8 character, it will be
+ * adjusted to the end of that UTF-8 character.
+ */
+
+ start = segPtr->body.chars + (byteIndex - index);
+ p = Tcl_UtfPrev(start, segPtr->body.chars);
+ p += TkUtfToUniChar(p, &ch);
+ indexPtr->byteIndex += p - start;
+ }
+ break;
+ }
+ index += segPtr->size;
+ }
+ return indexPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkTextMakeCharIndex --
+ *
+ * Given a line index and a character index, look things up in the B-tree
+ * and fill in a TkTextIndex structure.
+ *
+ * Results:
+ * The structure at *indexPtr is filled in with information about the
+ * character at lineIndex and charIndex (or the closest existing
+ * character, if the specified one doesn't exist), and indexPtr is
+ * returned as result.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+TkTextIndex *
+TkTextMakeCharIndex(
+ TkTextBTree tree, /* Tree that lineIndex and charIndex refer
+ * to. */
+ TkText *textPtr,
+ int lineIndex, /* Index of desired line (0 means first line
+ * of text). */
+ int charIndex, /* Index of desired character. */
+ TkTextIndex *indexPtr) /* Structure to fill in. */
+{
+ register TkTextSegment *segPtr;
+ char *p, *start, *end;
+ int index, offset;
+ int ch;
+
+ indexPtr->tree = tree;
+ if (lineIndex < 0) {
+ lineIndex = 0;
+ charIndex = 0;
+ }
+ if (charIndex < 0) {
+ charIndex = 0;
+ }
+ indexPtr->linePtr = TkBTreeFindLine(tree, textPtr, lineIndex);
+ if (indexPtr->linePtr == NULL) {
+ indexPtr->linePtr = TkBTreeFindLine(tree, textPtr,
+ TkBTreeNumLines(tree, textPtr));
+ charIndex = 0;
+ }
+
+ /*
+ * Verify that the index is within the range of the line. If not, just use
+ * the index of the last character in the line.
+ */
+
+ index = 0;
+ for (segPtr = indexPtr->linePtr->segPtr; ; segPtr = segPtr->nextPtr) {
+ if (segPtr == NULL) {
+ /*
+ * Use the index of the last character in the line. Since the last
+ * character on the line is guaranteed to be a '\n', we can back
+ * up a constant sizeof(char) bytes.
+ */
+
+ indexPtr->byteIndex = index - sizeof(char);
+ break;
+ }
+ if (segPtr->typePtr == &tkTextCharType) {
+ /*
+ * Turn character offset into a byte offset.
+ */
+
+ start = segPtr->body.chars;
+ end = start + segPtr->size;
+ for (p = start; p < end; p += offset) {
+ if (charIndex == 0) {
+ indexPtr->byteIndex = index;
+ return indexPtr;
+ }
+ charIndex--;
+ offset = TkUtfToUniChar(p, &ch);
+ index += offset;
+ }
+ } else {
+ if (charIndex < segPtr->size) {
+ indexPtr->byteIndex = index;
+ break;
+ }
+ charIndex -= segPtr->size;
+ index += segPtr->size;
+ }
+ }
+ return indexPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkTextIndexToSeg --
+ *
+ * Given an index, this function returns the segment and offset within
+ * segment for the index.
+ *
+ * Results:
+ * The return value is a pointer to the segment referred to by indexPtr;
+ * this will always be a segment with non-zero size. The variable at
+ * *offsetPtr is set to hold the integer offset within the segment of the
+ * character given by indexPtr.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+TkTextSegment *
+TkTextIndexToSeg(
+ const TkTextIndex *indexPtr,/* Text index. */
+ int *offsetPtr) /* Where to store offset within segment, or
+ * NULL if offset isn't wanted. */
+{
+ TkTextSegment *segPtr;
+ int offset;
+
+ for (offset = indexPtr->byteIndex, segPtr = indexPtr->linePtr->segPtr;
+ offset >= segPtr->size;
+ offset -= segPtr->size, segPtr = segPtr->nextPtr) {
+ /* Empty loop body. */
+ }
+ if (offsetPtr != NULL) {
+ *offsetPtr = offset;
+ }
+ return segPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkTextSegToOffset --
+ *
+ * Given a segment pointer and the line containing it, this function
+ * returns the offset of the segment within its line.
+ *
+ * Results:
+ * The return value is the offset (within its line) of the first
+ * character in segPtr.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TkTextSegToOffset(
+ const TkTextSegment *segPtr,/* Segment whose offset is desired. */
+ const TkTextLine *linePtr) /* Line containing segPtr. */
+{
+ const TkTextSegment *segPtr2;
+ int offset = 0;
+
+ for (segPtr2 = linePtr->segPtr; segPtr2 != segPtr;
+ segPtr2 = segPtr2->nextPtr) {
+ offset += segPtr2->size;
+ }
+ return offset;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkTextGetObjIndex --
+ *
+ * Simpler wrapper around the string based function, but could be
+ * enhanced with a new object type in the future.
+ *
+ * Results:
+ * see TkTextGetIndex
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TkTextGetObjIndex(
+ Tcl_Interp *interp, /* Use this for error reporting. */
+ TkText *textPtr, /* Information about text widget. */
+ Tcl_Obj *idxObj, /* Object containing textual description of
+ * position. */
+ TkTextIndex *indexPtr) /* Index structure to fill in. */
+{
+ return GetIndex(interp, NULL, textPtr, Tcl_GetString(idxObj), indexPtr,
+ NULL);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkTextSharedGetObjIndex --
+ *
+ * Simpler wrapper around the string based function, but could be
+ * enhanced with a new object type in the future.
+ *
+ * Results:
+ * see TkTextGetIndex
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TkTextSharedGetObjIndex(
+ Tcl_Interp *interp, /* Use this for error reporting. */
+ TkSharedText *sharedTextPtr,/* Information about text widget. */
+ Tcl_Obj *idxObj, /* Object containing textual description of
+ * position. */
+ TkTextIndex *indexPtr) /* Index structure to fill in. */
+{
+ return GetIndex(interp, sharedTextPtr, NULL, Tcl_GetString(idxObj),
+ indexPtr, NULL);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkTextGetIndex --
+ *
+ * Given a string, return the index that is described.
+ *
+ * Results:
+ * The return value is a standard Tcl return result. If TCL_OK is
+ * returned, then everything went well and the index at *indexPtr is
+ * filled in; otherwise TCL_ERROR is returned and an error message is
+ * left in the interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TkTextGetIndex(
+ Tcl_Interp *interp, /* Use this for error reporting. */
+ TkText *textPtr, /* Information about text widget. */
+ const char *string, /* Textual description of position. */
+ TkTextIndex *indexPtr) /* Index structure to fill in. */
+{
+ return GetIndex(interp, NULL, textPtr, string, indexPtr, NULL);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GetIndex --
+ *
+ * Given a string, return the index that is described.
+ *
+ * Results:
+ * The return value is a standard Tcl return result. If TCL_OK is
+ * returned, then everything went well and the index at *indexPtr is
+ * filled in; otherwise TCL_ERROR is returned and an error message is
+ * left in the interp's result.
+ *
+ * If *canCachePtr is non-NULL, and everything went well, the integer it
+ * points to is set to 1 if the indexPtr is something which can be
+ * cached, and zero otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static int
+GetIndex(
+ Tcl_Interp *interp, /* Use this for error reporting. */
+ TkSharedText *sharedPtr,
+ TkText *textPtr, /* Information about text widget. */
+ const char *string, /* Textual description of position. */
+ TkTextIndex *indexPtr, /* Index structure to fill in. */
+ int *canCachePtr) /* Pointer to integer to store whether we can
+ * cache the index (or NULL). */
+{
+ char *p, *end, *endOfBase;
+ TkTextIndex first, last;
+ int wantLast, result;
+ char c;
+ const char *cp;
+ Tcl_DString copy;
+ int canCache = 0;
+
+ if (sharedPtr == NULL) {
+ sharedPtr = textPtr->sharedTextPtr;
+ }
+
+ /*
+ *---------------------------------------------------------------------
+ * Stage 1: check to see if the index consists of nothing but a mark
+ * name, an embedded window or an embedded image. We do this check
+ * now even though it's also done later, in order to allow mark names,
+ * embedded window names or image names that include funny characters
+ * such as spaces or "+1c".
+ *---------------------------------------------------------------------
+ */
+
+ if (TkTextMarkNameToIndex(textPtr, string, indexPtr) == TCL_OK) {
+ goto done;
+ }
+
+ if (TkTextWindowIndex(textPtr, string, indexPtr) != 0) {
+ goto done;
+ }
+
+ if (TkTextImageIndex(textPtr, string, indexPtr) != 0) {
+ goto done;
+ }
+
+ /*
+ *------------------------------------------------
+ * Stage 2: start again by parsing the base index.
+ *------------------------------------------------
+ */
+
+ indexPtr->tree = sharedPtr->tree;
+
+ /*
+ * First look for the form "tag.first" or "tag.last" where "tag" is the
+ * name of a valid tag. Try to use up as much as possible of the string in
+ * this check (strrchr instead of strchr below). Doing the check now, and
+ * in this way, allows tag names to include funny characters like "@" or
+ * "+1c".
+ */
+
+ Tcl_DStringInit(&copy);
+ p = strrchr(Tcl_DStringAppend(&copy, string, -1), '.');
+ if (p != NULL) {
+ TkTextSearch search;
+ TkTextTag *tagPtr;
+ Tcl_HashEntry *hPtr = NULL;
+ const char *tagName;
+
+ if ((p[1] == 'f') && (strncmp(p+1, "first", 5) == 0)) {
+ wantLast = 0;
+ endOfBase = p+6;
+ } else if ((p[1] == 'l') && (strncmp(p+1, "last", 4) == 0)) {
+ wantLast = 1;
+ endOfBase = p+5;
+ } else {
+ goto tryxy;
+ }
+
+ tagPtr = NULL;
+ tagName = Tcl_DStringValue(&copy);
+ if (((p - tagName) == 3) && !strncmp(tagName, "sel", 3)) {
+ /*
+ * Special case for sel tag which is not stored in the hash table.
+ */
+
+ tagPtr = textPtr->selTagPtr;
+ } else {
+ *p = 0;
+ hPtr = Tcl_FindHashEntry(&sharedPtr->tagTable, tagName);
+ *p = '.';
+ if (hPtr != NULL) {
+ tagPtr = Tcl_GetHashValue(hPtr);
+ }
+ }
+
+ if (tagPtr == NULL) {
+ goto tryxy;
+ }
+
+ TkTextMakeByteIndex(sharedPtr->tree, textPtr, 0, 0, &first);
+ TkTextMakeByteIndex(sharedPtr->tree, textPtr,
+ TkBTreeNumLines(sharedPtr->tree, textPtr), 0, &last);
+ TkBTreeStartSearch(&first, &last, tagPtr, &search);
+ if (!TkBTreeCharTagged(&first, tagPtr) && !TkBTreeNextTag(&search)) {
+ if (tagPtr == textPtr->selTagPtr) {
+ tagName = "sel";
+ } else if (hPtr != NULL) {
+ tagName = Tcl_GetHashKey(&sharedPtr->tagTable, hPtr);
+ }
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "text doesn't contain any characters tagged with \"%s\"",
+ tagName));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "TEXT_INDEX", tagName,
+ NULL);
+ Tcl_DStringFree(&copy);
+ return TCL_ERROR;
+ }
+ *indexPtr = search.curIndex;
+ if (wantLast) {
+ while (TkBTreeNextTag(&search)) {
+ *indexPtr = search.curIndex;
+ }
+ }
+ goto gotBase;
+ }
+
+ tryxy:
+ if (string[0] == '@') {
+ /*
+ * Find character at a given x,y location in the window.
+ */
+
+ int x, y;
+
+ cp = string+1;
+ x = strtol(cp, &end, 0);
+ if ((end == cp) || (*end != ',')) {
+ goto error;
+ }
+ cp = end+1;
+ y = strtol(cp, &end, 0);
+ if (end == cp) {
+ goto error;
+ }
+ TkTextPixelIndex(textPtr, x, y, indexPtr, NULL);
+ endOfBase = end;
+ goto gotBase;
+ }
+
+ if (isdigit(UCHAR(string[0])) || (string[0] == '-')) {
+ int lineIndex, charIndex;
+
+ /*
+ * Base is identified with line and character indices.
+ */
+
+ lineIndex = strtol(string, &end, 0) - 1;
+ if ((end == string) || (*end != '.')) {
+ goto error;
+ }
+ p = end+1;
+ if ((*p == 'e') && (strncmp(p, "end", 3) == 0)) {
+ charIndex = LAST_CHAR;
+ endOfBase = p+3;
+ } else {
+ charIndex = strtol(p, &end, 0);
+ if (end == p) {
+ goto error;
+ }
+ endOfBase = end;
+ }
+ TkTextMakeCharIndex(sharedPtr->tree, textPtr, lineIndex, charIndex,
+ indexPtr);
+ canCache = 1;
+ goto gotBase;
+ }
+
+ for (p = Tcl_DStringValue(&copy); *p != 0; p++) {
+ if (isspace(UCHAR(*p)) || (*p == '+') || (*p == '-')) {
+ break;
+ }
+ }
+ endOfBase = p;
+ if (string[0] == '.') {
+ /*
+ * See if the base position is the name of an embedded window.
+ */
+
+ c = *endOfBase;
+ *endOfBase = 0;
+ result = TkTextWindowIndex(textPtr, Tcl_DStringValue(&copy), indexPtr);
+ *endOfBase = c;
+ if (result != 0) {
+ goto gotBase;
+ }
+ }
+ if ((string[0] == 'e')
+ && (strncmp(string, "end",
+ (size_t) (endOfBase-Tcl_DStringValue(&copy))) == 0)) {
+ /*
+ * Base position is end of text.
+ */
+
+ TkTextMakeByteIndex(sharedPtr->tree, textPtr,
+ TkBTreeNumLines(sharedPtr->tree, textPtr), 0, indexPtr);
+ canCache = 1;
+ goto gotBase;
+ } else {
+ /*
+ * See if the base position is the name of a mark.
+ */
+
+ c = *endOfBase;
+ *endOfBase = 0;
+ result = TkTextMarkNameToIndex(textPtr, Tcl_DStringValue(&copy),
+ indexPtr);
+ *endOfBase = c;
+ if (result == TCL_OK) {
+ goto gotBase;
+ }
+
+ /*
+ * See if the base position is the name of an embedded image.
+ */
+
+ c = *endOfBase;
+ *endOfBase = 0;
+ result = TkTextImageIndex(textPtr, Tcl_DStringValue(&copy), indexPtr);
+ *endOfBase = c;
+ if (result != 0) {
+ goto gotBase;
+ }
+ }
+ goto error;
+
+ /*
+ *-------------------------------------------------------------------
+ * Stage 3: process zero or more modifiers. Each modifier is either a
+ * keyword like "wordend" or "linestart", or it has the form "op count
+ * units" where op is + or -, count is a number, and units is "chars" or
+ * "lines".
+ *-------------------------------------------------------------------
+ */
+
+ gotBase:
+ cp = endOfBase;
+ while (1) {
+ while (isspace(UCHAR(*cp))) {
+ cp++;
+ }
+ if (*cp == 0) {
+ break;
+ }
+
+ if ((*cp == '+') || (*cp == '-')) {
+ cp = ForwBack(textPtr, cp, indexPtr);
+ } else {
+ cp = StartEnd(textPtr, cp, indexPtr);
+ }
+ if (cp == NULL) {
+ goto error;
+ }
+ }
+ Tcl_DStringFree(&copy);
+
+ done:
+ if (canCachePtr != NULL) {
+ *canCachePtr = canCache;
+ }
+ if (indexPtr->linePtr == NULL) {
+ Tcl_Panic("Bad index created");
+ }
+ return TCL_OK;
+
+ error:
+ Tcl_DStringFree(&copy);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad text index \"%s\"", string));
+ Tcl_SetErrorCode(interp, "TK", "TEXT", "BAD_INDEX", NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkTextPrintIndex --
+ *
+ * This function generates a string description of an index, suitable for
+ * reading in again later.
+ *
+ * Results:
+ * The characters pointed to by string are modified. Returns the number
+ * of characters in the string.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TkTextPrintIndex(
+ const TkText *textPtr,
+ const TkTextIndex *indexPtr,/* Pointer to index. */
+ char *string) /* Place to store the position. Must have at
+ * least TK_POS_CHARS characters. */
+{
+ TkTextSegment *segPtr;
+ TkTextLine *linePtr;
+ int numBytes, charIndex;
+
+ numBytes = indexPtr->byteIndex;
+ charIndex = 0;
+ linePtr = indexPtr->linePtr;
+
+ for (segPtr = linePtr->segPtr; ; segPtr = segPtr->nextPtr) {
+ if (segPtr == NULL) {
+ /*
+ * Two logical lines merged into one display line through eliding
+ * of a newline.
+ */
+
+ linePtr = TkBTreeNextLine(NULL, linePtr);
+ segPtr = linePtr->segPtr;
+ }
+ if (numBytes <= segPtr->size) {
+ break;
+ }
+ if (segPtr->typePtr == &tkTextCharType) {
+ charIndex += Tcl_NumUtfChars(segPtr->body.chars, segPtr->size);
+ } else {
+ charIndex += segPtr->size;
+ }
+ numBytes -= segPtr->size;
+ }
+
+ if (segPtr->typePtr == &tkTextCharType) {
+ charIndex += Tcl_NumUtfChars(segPtr->body.chars, numBytes);
+ } else {
+ charIndex += numBytes;
+ }
+
+ return sprintf(string, "%d.%d",
+ TkBTreeLinesTo(textPtr, indexPtr->linePtr) + 1, charIndex);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkTextIndexCmp --
+ *
+ * Compare two indices to see which one is earlier in the text.
+ *
+ * Results:
+ * The return value is 0 if index1Ptr and index2Ptr refer to the same
+ * position in the file, -1 if index1Ptr refers to an earlier position
+ * than index2Ptr, and 1 otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TkTextIndexCmp(
+ const TkTextIndex*index1Ptr,/* First index. */
+ const TkTextIndex*index2Ptr)/* Second index. */
+{
+ int line1, line2;
+
+ if (index1Ptr->linePtr == index2Ptr->linePtr) {
+ if (index1Ptr->byteIndex < index2Ptr->byteIndex) {
+ return -1;
+ } else if (index1Ptr->byteIndex > index2Ptr->byteIndex) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+
+ /*
+ * Assumption here that it is ok for comparisons to reflect the full
+ * B-tree and not just the portion that is available to any client. This
+ * should be true because the only indexPtr's we should be given are ones
+ * which are valid for the current client.
+ */
+
+ line1 = TkBTreeLinesTo(NULL, index1Ptr->linePtr);
+ line2 = TkBTreeLinesTo(NULL, index2Ptr->linePtr);
+ if (line1 < line2) {
+ return -1;
+ }
+ if (line1 > line2) {
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ForwBack --
+ *
+ * This function handles +/- modifiers for indices to adjust the index
+ * forwards or backwards.
+ *
+ * Results:
+ * If the modifier in string is successfully parsed then the return value
+ * is the address of the first character after the modifier, and
+ * *indexPtr is updated to reflect the modifier. If there is a syntax
+ * error in the modifier then NULL is returned.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static const char *
+ForwBack(
+ TkText *textPtr, /* Information about text widget. */
+ const char *string, /* String to parse for additional info about
+ * modifier (count and units). Points to "+"
+ * or "-" that starts modifier. */
+ TkTextIndex *indexPtr) /* Index to update as specified in string. */
+{
+ register const char *p, *units;
+ char *end;
+ int count, lineIndex, modifier;
+ size_t length;
+
+ /*
+ * Get the count (how many units forward or backward).
+ */
+
+ p = string+1;
+ while (isspace(UCHAR(*p))) {
+ p++;
+ }
+ count = strtol(p, &end, 0);
+ if (end == p) {
+ return NULL;
+ }
+ p = end;
+ while (isspace(UCHAR(*p))) {
+ p++;
+ }
+
+ /*
+ * Find the end of this modifier (next space or + or - character), then
+ * check if there is a textual 'display' or 'any' modifier. These
+ * modifiers can be their own word (in which case they can be abbreviated)
+ * or they can follow on to the actual unit in a single word (in which
+ * case no abbreviation is allowed). So, 'display lines', 'd lines',
+ * 'displaylin' are all ok, but 'dline' is not.
+ */
+
+ units = p;
+ while ((*p != '\0') && !isspace(UCHAR(*p)) && (*p != '+') && (*p != '-')) {
+ p++;
+ }
+ length = p - units;
+ if ((*units == 'd') &&
+ (strncmp(units, "display", (length > 7 ? 7 : length)) == 0)) {
+ modifier = TKINDEX_DISPLAY;
+ if (length > 7) {
+ p -= (length - 7);
+ }
+ } else if ((*units == 'a') &&
+ (strncmp(units, "any", (length > 3 ? 3 : length)) == 0)) {
+ modifier = TKINDEX_ANY;
+ if (length > 3) {
+ p -= (length - 3);
+ }
+ } else {
+ modifier = TKINDEX_NONE;
+ }
+
+ /*
+ * If we had a modifier, which we interpreted ok, so now forward to the
+ * actual units.
+ */
+
+ if (modifier != TKINDEX_NONE) {
+ while (isspace(UCHAR(*p))) {
+ p++;
+ }
+ units = p;
+ while (*p!='\0' && !isspace(UCHAR(*p)) && *p!='+' && *p!='-') {
+ p++;
+ }
+ length = p - units;
+ }
+
+ /*
+ * Finally parse the units.
+ */
+
+ if ((*units == 'c') && (strncmp(units, "chars", length) == 0)) {
+ TkTextCountType type;
+
+ if (modifier == TKINDEX_NONE) {
+ type = COUNT_INDICES;
+ } else if (modifier == TKINDEX_ANY) {
+ type = COUNT_CHARS;
+ } else {
+ type = COUNT_DISPLAY_CHARS;
+ }
+
+ if (*string == '+') {
+ TkTextIndexForwChars(textPtr, indexPtr, count, indexPtr, type);
+ } else {
+ TkTextIndexBackChars(textPtr, indexPtr, count, indexPtr, type);
+ }
+ } else if ((*units == 'i') && (strncmp(units, "indices", length) == 0)) {
+ TkTextCountType type;
+
+ if (modifier == TKINDEX_DISPLAY) {
+ type = COUNT_DISPLAY_INDICES;
+ } else {
+ type = COUNT_INDICES;
+ }
+
+ if (*string == '+') {
+ TkTextIndexForwChars(textPtr, indexPtr, count, indexPtr, type);
+ } else {
+ TkTextIndexBackChars(textPtr, indexPtr, count, indexPtr, type);
+ }
+ } else if ((*units == 'l') && (strncmp(units, "lines", length) == 0)) {
+ if (modifier == TKINDEX_DISPLAY) {
+ /*
+ * Find the appropriate pixel offset of the current position
+ * within its display line. This also has the side-effect of
+ * moving indexPtr, but that doesn't matter since we will do it
+ * again below.
+ *
+ * Then find the right display line, and finally calculated the
+ * index we want in that display line, based on the original pixel
+ * offset.
+ */
+
+ int xOffset, forward;
+
+ if (TkTextIsElided(textPtr, indexPtr, NULL)) {
+ /*
+ * Go forward to the first non-elided index.
+ */
+
+ TkTextIndexForwChars(textPtr, indexPtr, 0, indexPtr,
+ COUNT_DISPLAY_INDICES);
+ }
+
+ /*
+ * Unlike the Forw/BackChars code, the display line code is
+ * sensitive to whether we are genuinely going forwards or
+ * backwards. So, we need to determine that. This is important in
+ * the case where we have "+ -3 displaylines", for example.
+ */
+
+ if ((count < 0) ^ (*string == '-')) {
+ forward = 0;
+ } else {
+ forward = 1;
+ }
+
+ count = abs(count);
+ if (count == 0) {
+ return p;
+ }
+
+ if (forward) {
+ TkTextFindDisplayLineEnd(textPtr, indexPtr, 1, &xOffset);
+ while (count-- > 0) {
+ /*
+ * Go to the end of the line, then forward one char/byte
+ * to get to the beginning of the next line.
+ */
+
+ TkTextFindDisplayLineEnd(textPtr, indexPtr, 1, NULL);
+ TkTextIndexForwChars(textPtr, indexPtr, 1, indexPtr,
+ COUNT_DISPLAY_INDICES);
+ }
+ } else {
+ TkTextFindDisplayLineEnd(textPtr, indexPtr, 0, &xOffset);
+ while (count-- > 0) {
+ /*
+ * Go to the beginning of the line, then backward one
+ * char/byte to get to the end of the previous line.
+ */
+
+ TkTextFindDisplayLineEnd(textPtr, indexPtr, 0, NULL);
+ TkTextIndexBackChars(textPtr, indexPtr, 1, indexPtr,
+ COUNT_DISPLAY_INDICES);
+ }
+ TkTextFindDisplayLineEnd(textPtr, indexPtr, 0, NULL);
+ }
+
+ /*
+ * This call assumes indexPtr is the beginning of a display line
+ * and moves it to the 'xOffset' position of that line, which is
+ * just what we want.
+ */
+
+ TkTextIndexOfX(textPtr, xOffset, indexPtr);
+ } else {
+ lineIndex = TkBTreeLinesTo(textPtr, indexPtr->linePtr);
+ if (*string == '+') {
+ lineIndex += count;
+ } else {
+ lineIndex -= count;
+
+ /*
+ * The check below retains the character position, even if the
+ * line runs off the start of the file. Without it, the
+ * character position will get reset to 0 by TkTextMakeIndex.
+ */
+
+ if (lineIndex < 0) {
+ lineIndex = 0;
+ }
+ }
+
+ /*
+ * This doesn't work quite right if using a proportional font or
+ * UTF-8 characters with varying numbers of bytes, or if there are
+ * embedded windows, images, etc. The cursor will bop around,
+ * keeping a constant number of bytes (not characters) from the
+ * left edge (but making sure not to split any UTF-8 characters),
+ * regardless of the x-position the index corresponds to. The
+ * proper way to do this is to get the x-position of the index and
+ * then pick the character at the same x-position in the new line.
+ */
+
+ TkTextMakeByteIndex(indexPtr->tree, textPtr, lineIndex,
+ indexPtr->byteIndex, indexPtr);
+ }
+ } else {
+ return NULL;
+ }
+ return p;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkTextIndexForwBytes --
+ *
+ * Given an index for a text widget, this function creates a new index
+ * that points "count" bytes ahead of the source index.
+ *
+ * Results:
+ * *dstPtr is modified to refer to the character "count" bytes after
+ * srcPtr, or to the last character in the TkText if there aren't "count"
+ * bytes left.
+ *
+ * In this latter case, the function returns '1' to indicate that not all
+ * of 'byteCount' could be used.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TkTextIndexForwBytes(
+ const TkText *textPtr,
+ const TkTextIndex *srcPtr, /* Source index. */
+ int byteCount, /* How many bytes forward to move. May be
+ * negative. */
+ TkTextIndex *dstPtr) /* Destination index: gets modified. */
+{
+ TkTextLine *linePtr;
+ TkTextSegment *segPtr;
+ int lineLength;
+
+ if (byteCount < 0) {
+ TkTextIndexBackBytes(textPtr, srcPtr, -byteCount, dstPtr);
+ return 0;
+ }
+
+ *dstPtr = *srcPtr;
+ dstPtr->byteIndex += byteCount;
+ while (1) {
+ /*
+ * Compute the length of the current line.
+ */
+
+ lineLength = 0;
+ for (segPtr = dstPtr->linePtr->segPtr; segPtr != NULL;
+ segPtr = segPtr->nextPtr) {
+ lineLength += segPtr->size;
+ }
+
+ /*
+ * If the new index is in the same line then we're done. Otherwise go
+ * on to the next line.
+ */
+
+ if (dstPtr->byteIndex < lineLength) {
+ return 0;
+ }
+ dstPtr->byteIndex -= lineLength;
+ linePtr = TkBTreeNextLine(textPtr, dstPtr->linePtr);
+ if (linePtr == NULL) {
+ dstPtr->byteIndex = lineLength - 1;
+ return 1;
+ }
+ dstPtr->linePtr = linePtr;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkTextIndexForwChars --
+ *
+ * Given an index for a text widget, this function creates a new index
+ * that points "count" items of type given by "type" ahead of the source
+ * index. "count" can be zero, which is useful in the case where one
+ * wishes to move forward by display (non-elided) chars or indices or one
+ * wishes to move forward by chars, skipping any intervening indices. In
+ * this case dstPtr will point to the first acceptable index which is
+ * encountered.
+ *
+ * Results:
+ * *dstPtr is modified to refer to the character "count" items after
+ * srcPtr, or to the last character in the TkText if there aren't
+ * sufficient items left in the widget.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+TkTextIndexForwChars(
+ const TkText *textPtr, /* Overall information about text widget. */
+ const TkTextIndex *srcPtr, /* Source index. */
+ int charCount, /* How many characters forward to move. May
+ * be negative. */
+ TkTextIndex *dstPtr, /* Destination index: gets modified. */
+ TkTextCountType type) /* The type of item to count */
+{
+ TkTextLine *linePtr;
+ TkTextSegment *segPtr;
+ TkTextElideInfo *infoPtr = NULL;
+ int byteOffset;
+ char *start, *end, *p;
+ int ch;
+ int elide = 0;
+ int checkElided = (type & COUNT_DISPLAY);
+
+ if (charCount < 0) {
+ TkTextIndexBackChars(textPtr, srcPtr, -charCount, dstPtr, type);
+ return;
+ }
+ if (checkElided) {
+ infoPtr = ckalloc(sizeof(TkTextElideInfo));
+ elide = TkTextIsElided(textPtr, srcPtr, infoPtr);
+ }
+
+ *dstPtr = *srcPtr;
+
+ /*
+ * Find seg that contains src byteIndex. Move forward specified number of
+ * chars.
+ */
+
+ if (checkElided) {
+ /*
+ * In this case we have already calculated the information we need, so
+ * no need to use TkTextIndexToSeg()
+ */
+
+ segPtr = infoPtr->segPtr;
+ byteOffset = dstPtr->byteIndex - infoPtr->segOffset;
+ } else {
+ segPtr = TkTextIndexToSeg(dstPtr, &byteOffset);
+ }
+
+ while (1) {
+ /*
+ * Go through each segment in line looking for specified character
+ * index.
+ */
+
+ for ( ; segPtr != NULL; segPtr = segPtr->nextPtr) {
+ /*
+ * If we do need to pay attention to the visibility of
+ * characters/indices, check that first. If the current segment
+ * isn't visible, then we simply continue the loop.
+ */
+
+ if (checkElided && ((segPtr->typePtr == &tkTextToggleOffType)
+ || (segPtr->typePtr == &tkTextToggleOnType))) {
+ TkTextTag *tagPtr = segPtr->body.toggle.tagPtr;
+
+ /*
+ * The elide state only changes if this tag is either the
+ * current highest priority tag (and is therefore being
+ * toggled off), or it's a new tag with higher priority.
+ */
+
+ if (tagPtr->elideString != NULL) {
+ infoPtr->tagCnts[tagPtr->priority]++;
+ if (infoPtr->tagCnts[tagPtr->priority] & 1) {
+ infoPtr->tagPtrs[tagPtr->priority] = tagPtr;
+ }
+
+ if (tagPtr->priority >= infoPtr->elidePriority) {
+ if (segPtr->typePtr == &tkTextToggleOffType) {
+ /*
+ * If it is being toggled off, and it has an elide
+ * string, it must actually be the current highest
+ * priority tag, so this check is redundant:
+ */
+
+ if (tagPtr->priority != infoPtr->elidePriority) {
+ Tcl_Panic("Bad tag priority being toggled off");
+ }
+
+ /*
+ * Find previous elide tag, if any (if not then
+ * elide will be zero, of course).
+ */
+
+ elide = 0;
+ while (--infoPtr->elidePriority > 0) {
+ if (infoPtr->tagCnts[infoPtr->elidePriority]
+ & 1) {
+ elide = infoPtr->tagPtrs
+ [infoPtr->elidePriority]->elide;
+ break;
+ }
+ }
+ } else {
+ elide = tagPtr->elide;
+ infoPtr->elidePriority = tagPtr->priority;
+ }
+ }
+ }
+ }
+
+ if (!elide) {
+ if (segPtr->typePtr == &tkTextCharType) {
+ start = segPtr->body.chars + byteOffset;
+ end = segPtr->body.chars + segPtr->size;
+ for (p = start; p < end; p += TkUtfToUniChar(p, &ch)) {
+ if (charCount == 0) {
+ dstPtr->byteIndex += (p - start);
+ goto forwardCharDone;
+ }
+ charCount--;
+ }
+ } else if (type & COUNT_INDICES) {
+ if (charCount < segPtr->size - byteOffset) {
+ dstPtr->byteIndex += charCount;
+ goto forwardCharDone;
+ }
+ charCount -= segPtr->size - byteOffset;
+ }
+ }
+
+ dstPtr->byteIndex += segPtr->size - byteOffset;
+ byteOffset = 0;
+ }
+
+ /*
+ * Go to the next line. If we are at the end of the text item, back up
+ * one byte (for the terminal '\n' character) and return that index.
+ */
+
+ linePtr = TkBTreeNextLine(textPtr, dstPtr->linePtr);
+ if (linePtr == NULL) {
+ dstPtr->byteIndex -= sizeof(char);
+ goto forwardCharDone;
+ }
+ dstPtr->linePtr = linePtr;
+ dstPtr->byteIndex = 0;
+ segPtr = dstPtr->linePtr->segPtr;
+ }
+
+ forwardCharDone:
+ if (infoPtr != NULL) {
+ TkTextFreeElideInfo(infoPtr);
+ ckfree(infoPtr);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkTextIndexCountBytes --
+ *
+ * Given a pair of indices in a text widget, this function counts how
+ * many bytes are between the two indices. The two indices do not need
+ * to be ordered.
+ *
+ * Results:
+ * The number of bytes in the given range.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TkTextIndexCountBytes(
+ const TkText *textPtr,
+ const TkTextIndex *indexPtr1, /* Index describing one location. */
+ const TkTextIndex *indexPtr2) /* Index describing second location. */
+{
+ int compare = TkTextIndexCmp(indexPtr1, indexPtr2);
+
+ if (compare == 0) {
+ return 0;
+ } else if (compare > 0) {
+ return IndexCountBytesOrdered(textPtr, indexPtr2, indexPtr1);
+ } else {
+ return IndexCountBytesOrdered(textPtr, indexPtr1, indexPtr2);
+ }
+}
+
+static int
+IndexCountBytesOrdered(
+ const TkText *textPtr,
+ const TkTextIndex *indexPtr1,
+ /* Index describing location of character from
+ * which to count. */
+ const TkTextIndex *indexPtr2)
+ /* Index describing location of last character
+ * at which to stop the count. */
+{
+ int byteCount, offset;
+ TkTextSegment *segPtr, *segPtr1;
+ TkTextLine *linePtr;
+
+ if (indexPtr1->linePtr == indexPtr2->linePtr) {
+ return indexPtr2->byteIndex - indexPtr1->byteIndex;
+ }
+
+ /*
+ * indexPtr2 is on a line strictly after the line containing indexPtr1.
+ * Add up:
+ * bytes between indexPtr1 and end of its line
+ * bytes in lines strictly between indexPtr1 and indexPtr2
+ * bytes between start of the indexPtr2 line and indexPtr2
+ */
+
+ segPtr1 = TkTextIndexToSeg(indexPtr1, &offset);
+ byteCount = -offset;
+ for (segPtr = segPtr1; segPtr != NULL; segPtr = segPtr->nextPtr) {
+ byteCount += segPtr->size;
+ }
+
+ linePtr = TkBTreeNextLine(textPtr, indexPtr1->linePtr);
+ while (linePtr != indexPtr2->linePtr) {
+ for (segPtr = linePtr->segPtr; segPtr != NULL;
+ segPtr = segPtr->nextPtr) {
+ byteCount += segPtr->size;
+ }
+ linePtr = TkBTreeNextLine(textPtr, linePtr);
+ if (linePtr == NULL) {
+ Tcl_Panic("TextIndexCountBytesOrdered ran out of lines");
+ }
+ }
+
+ byteCount += indexPtr2->byteIndex;
+
+ return byteCount;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkTextIndexCount --
+ *
+ * Given an ordered pair of indices in a text widget, this function
+ * counts how many characters (not bytes) are between the two indices.
+ *
+ * It is illegal to call this function with unordered indices.
+ *
+ * Note that 'textPtr' is only used if we need to check for elided
+ * attributes, i.e. if type is COUNT_DISPLAY_INDICES or
+ * COUNT_DISPLAY_CHARS.
+ *
+ * Results:
+ * The number of characters in the given range, which meet the
+ * appropriate 'type' attributes.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TkTextIndexCount(
+ const TkText *textPtr, /* Overall information about text widget. */
+ const TkTextIndex *indexPtr1,
+ /* Index describing location of character from
+ * which to count. */
+ const TkTextIndex *indexPtr2,
+ /* Index describing location of last character
+ * at which to stop the count. */
+ TkTextCountType type) /* The kind of indices to count. */
+{
+ TkTextLine *linePtr1;
+ TkTextSegment *segPtr, *seg2Ptr = NULL;
+ TkTextElideInfo *infoPtr = NULL;
+ int byteOffset, maxBytes, count = 0, elide = 0;
+ int checkElided = (type & COUNT_DISPLAY);
+
+ /*
+ * Find seg that contains src index, and remember how many bytes not to
+ * count in the given segment.
+ */
+
+ segPtr = TkTextIndexToSeg(indexPtr1, &byteOffset);
+ linePtr1 = indexPtr1->linePtr;
+
+ seg2Ptr = TkTextIndexToSeg(indexPtr2, &maxBytes);
+
+ if (checkElided) {
+ infoPtr = ckalloc(sizeof(TkTextElideInfo));
+ elide = TkTextIsElided(textPtr, indexPtr1, infoPtr);
+ }
+
+ while (1) {
+ /*
+ * Go through each segment in line adding up the number of characters.
+ */
+
+ for ( ; segPtr != NULL; segPtr = segPtr->nextPtr) {
+ /*
+ * If we do need to pay attention to the visibility of
+ * characters/indices, check that first. If the current segment
+ * isn't visible, then we simply continue the loop.
+ */
+
+ if (checkElided) {
+ if ((segPtr->typePtr == &tkTextToggleOffType)
+ || (segPtr->typePtr == &tkTextToggleOnType)) {
+ TkTextTag *tagPtr = segPtr->body.toggle.tagPtr;
+
+ /*
+ * The elide state only changes if this tag is either the
+ * current highest priority tag (and is therefore being
+ * toggled off), or it's a new tag with higher priority.
+ */
+
+ if (tagPtr->elideString != NULL) {
+ infoPtr->tagCnts[tagPtr->priority]++;
+ if (infoPtr->tagCnts[tagPtr->priority] & 1) {
+ infoPtr->tagPtrs[tagPtr->priority] = tagPtr;
+ }
+ if (tagPtr->priority >= infoPtr->elidePriority) {
+ if (segPtr->typePtr == &tkTextToggleOffType) {
+ /*
+ * If it is being toggled off, and it has an
+ * elide string, it must actually be the
+ * current highest priority tag, so this check
+ * is redundant:
+ */
+
+ if (tagPtr->priority!=infoPtr->elidePriority) {
+ Tcl_Panic("Bad tag priority being toggled off");
+ }
+
+ /*
+ * Find previous elide tag, if any (if not
+ * then elide will be zero, of course).
+ */
+
+ elide = 0;
+ while (--infoPtr->elidePriority > 0) {
+ if (infoPtr->tagCnts[
+ infoPtr->elidePriority] & 1) {
+ elide = infoPtr->tagPtrs[
+ infoPtr->elidePriority]->elide;
+ break;
+ }
+ }
+ } else {
+ elide = tagPtr->elide;
+ infoPtr->elidePriority = tagPtr->priority;
+ }
+ }
+ }
+ }
+ if (elide) {
+ if (segPtr == seg2Ptr) {
+ goto countDone;
+ }
+ byteOffset = 0;
+ continue;
+ }
+ }
+
+ if (segPtr->typePtr == &tkTextCharType) {
+ int byteLen = segPtr->size - byteOffset;
+ register unsigned char *str = (unsigned char *)
+ segPtr->body.chars + byteOffset;
+ register int i;
+
+ if (segPtr == seg2Ptr) {
+ if (byteLen > (maxBytes - byteOffset)) {
+ byteLen = maxBytes - byteOffset;
+ }
+ }
+ i = byteLen;
+
+ /*
+ * This is a speed sensitive function, so run specially over
+ * the string to count continuous ascii characters before
+ * resorting to the Tcl_NumUtfChars call. This is a long form
+ * of:
+ *
+ * stringPtr->numChars =
+ * Tcl_NumUtfChars(objPtr->bytes, objPtr->length);
+ */
+
+ while (i && (*str < 0xC0)) {
+ i--;
+ str++;
+ }
+ count += byteLen - i;
+ if (i) {
+ count += Tcl_NumUtfChars(segPtr->body.chars + byteOffset
+ + (byteLen - i), i);
+ }
+ } else {
+ if (type & COUNT_INDICES) {
+ int byteLen = segPtr->size - byteOffset;
+
+ if (segPtr == seg2Ptr) {
+ if (byteLen > (maxBytes - byteOffset)) {
+ byteLen = maxBytes - byteOffset;
+ }
+ }
+ count += byteLen;
+ }
+ }
+ if (segPtr == seg2Ptr) {
+ goto countDone;
+ }
+ byteOffset = 0;
+ }
+
+ /*
+ * Go to the next line. If we are at the end of the text item, back up
+ * one byte (for the terminal '\n' character) and return that index.
+ */
+
+ linePtr1 = TkBTreeNextLine(textPtr, linePtr1);
+ if (linePtr1 == NULL) {
+ Tcl_Panic("Reached end of text widget when counting characters");
+ }
+ segPtr = linePtr1->segPtr;
+ }
+
+ countDone:
+ if (infoPtr != NULL) {
+ TkTextFreeElideInfo(infoPtr);
+ ckfree(infoPtr);
+ }
+ return count;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkTextIndexBackBytes --
+ *
+ * Given an index for a text widget, this function creates a new index
+ * that points "count" bytes earlier than the source index.
+ *
+ * Results:
+ * *dstPtr is modified to refer to the character "count" bytes before
+ * srcPtr, or to the first character in the TkText if there aren't
+ * "count" bytes earlier than srcPtr.
+ *
+ * Returns 1 if we couldn't use all of 'byteCount' because we have run
+ * into the beginning or end of the text, and zero otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TkTextIndexBackBytes(
+ const TkText *textPtr,
+ const TkTextIndex *srcPtr, /* Source index. */
+ int byteCount, /* How many bytes backward to move. May be
+ * negative. */
+ TkTextIndex *dstPtr) /* Destination index: gets modified. */
+{
+ TkTextSegment *segPtr;
+ int lineIndex;
+
+ if (byteCount < 0) {
+ return TkTextIndexForwBytes(textPtr, srcPtr, -byteCount, dstPtr);
+ }
+
+ *dstPtr = *srcPtr;
+ dstPtr->byteIndex -= byteCount;
+ lineIndex = -1;
+ while (dstPtr->byteIndex < 0) {
+ /*
+ * Move back one line in the text. If we run off the beginning of the
+ * file then just return the first character in the text.
+ */
+
+ if (lineIndex < 0) {
+ lineIndex = TkBTreeLinesTo(textPtr, dstPtr->linePtr);
+ }
+ if (lineIndex == 0) {
+ dstPtr->byteIndex = 0;
+ return 1;
+ }
+ lineIndex--;
+ dstPtr->linePtr = TkBTreeFindLine(dstPtr->tree, textPtr, lineIndex);
+
+ /*
+ * Compute the length of the line and add that to dstPtr->charIndex.
+ */
+
+ for (segPtr = dstPtr->linePtr->segPtr; segPtr != NULL;
+ segPtr = segPtr->nextPtr) {
+ dstPtr->byteIndex += segPtr->size;
+ }
+ }
+ return 0;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkTextIndexBackChars --
+ *
+ * Given an index for a text widget, this function creates a new index
+ * that points "count" items of type given by "type" earlier than the
+ * source index. "count" can be zero, which is useful in the case where
+ * one wishes to move backward by display (non-elided) chars or indices
+ * or one wishes to move backward by chars, skipping any intervening
+ * indices. In this case the returned index *dstPtr will point just
+ * _after_ the first acceptable index which is encountered.
+ *
+ * Results:
+ * *dstPtr is modified to refer to the character "count" items before
+ * srcPtr, or to the first index in the window if there aren't sufficient
+ * items earlier than srcPtr.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+TkTextIndexBackChars(
+ const TkText *textPtr, /* Overall information about text widget. */
+ const TkTextIndex *srcPtr, /* Source index. */
+ int charCount, /* How many characters backward to move. May
+ * be negative. */
+ TkTextIndex *dstPtr, /* Destination index: gets modified. */
+ TkTextCountType type) /* The type of item to count */
+{
+ TkTextSegment *segPtr, *oldPtr;
+ TkTextElideInfo *infoPtr = NULL;
+ int lineIndex, segSize;
+ const char *p, *start, *end;
+ int elide = 0;
+ int checkElided = (type & COUNT_DISPLAY);
+
+ if (charCount < 0) {
+ TkTextIndexForwChars(textPtr, srcPtr, -charCount, dstPtr, type);
+ return;
+ }
+ if (checkElided) {
+ infoPtr = ckalloc(sizeof(TkTextElideInfo));
+ elide = TkTextIsElided(textPtr, srcPtr, infoPtr);
+ }
+
+ *dstPtr = *srcPtr;
+
+ /*
+ * Find offset within seg that contains byteIndex. Move backward specified
+ * number of chars.
+ */
+
+ lineIndex = -1;
+
+ segSize = dstPtr->byteIndex;
+
+ if (checkElided) {
+ segPtr = infoPtr->segPtr;
+ segSize -= infoPtr->segOffset;
+ } else {
+ TkTextLine *linePtr = dstPtr->linePtr;
+ for (segPtr = linePtr->segPtr; ; segPtr = segPtr->nextPtr) {
+ if (segPtr == NULL) {
+ /*
+ * Two logical lines merged into one display line through
+ * eliding of a newline.
+ */
+
+ linePtr = TkBTreeNextLine(NULL, linePtr);
+ segPtr = linePtr->segPtr;
+ }
+ if (segSize <= segPtr->size) {
+ break;
+ }
+ segSize -= segPtr->size;
+ }
+ }
+
+ /*
+ * Now segPtr points to the segment containing the starting index.
+ */
+
+ while (1) {
+ /*
+ * If we do need to pay attention to the visibility of
+ * characters/indices, check that first. If the current segment isn't
+ * visible, then we simply continue the loop.
+ */
+
+ if (checkElided && ((segPtr->typePtr == &tkTextToggleOffType)
+ || (segPtr->typePtr == &tkTextToggleOnType))) {
+ TkTextTag *tagPtr = segPtr->body.toggle.tagPtr;
+
+ /*
+ * The elide state only changes if this tag is either the current
+ * highest priority tag (and is therefore being toggled off), or
+ * it's a new tag with higher priority.
+ */
+
+ if (tagPtr->elideString != NULL) {
+ infoPtr->tagCnts[tagPtr->priority]++;
+ if (infoPtr->tagCnts[tagPtr->priority] & 1) {
+ infoPtr->tagPtrs[tagPtr->priority] = tagPtr;
+ }
+ if (tagPtr->priority >= infoPtr->elidePriority) {
+ if (segPtr->typePtr == &tkTextToggleOnType) {
+ /*
+ * If it is being toggled on, and it has an elide
+ * string, it must actually be the current highest
+ * priority tag, so this check is redundant:
+ */
+
+ if (tagPtr->priority != infoPtr->elidePriority) {
+ Tcl_Panic("Bad tag priority being toggled on");
+ }
+
+ /*
+ * Find previous elide tag, if any (if not then elide
+ * will be zero, of course).
+ */
+
+ elide = 0;
+ while (--infoPtr->elidePriority > 0) {
+ if (infoPtr->tagCnts[infoPtr->elidePriority] & 1) {
+ elide = infoPtr->tagPtrs[
+ infoPtr->elidePriority]->elide;
+ break;
+ }
+ }
+ } else {
+ elide = tagPtr->elide;
+ infoPtr->elidePriority = tagPtr->priority;
+ }
+ }
+ }
+ }
+
+ if (!elide) {
+ if (segPtr->typePtr == &tkTextCharType) {
+ start = segPtr->body.chars;
+ end = segPtr->body.chars + segSize;
+ for (p = end; ; p = Tcl_UtfPrev(p, start)) {
+ if (charCount == 0) {
+ dstPtr->byteIndex -= (end - p);
+ goto backwardCharDone;
+ }
+ if (p == start) {
+ break;
+ }
+ charCount--;
+ }
+ } else {
+ if (type & COUNT_INDICES) {
+ if (charCount <= segSize) {
+ dstPtr->byteIndex -= charCount;
+ goto backwardCharDone;
+ }
+ charCount -= segSize;
+ }
+ }
+ }
+ dstPtr->byteIndex -= segSize;
+
+ /*
+ * Move back into previous segment.
+ */
+
+ oldPtr = segPtr;
+ segPtr = dstPtr->linePtr->segPtr;
+ if (segPtr != oldPtr) {
+ for ( ; segPtr->nextPtr != oldPtr; segPtr = segPtr->nextPtr) {
+ /* Empty body. */
+ }
+ segSize = segPtr->size;
+ continue;
+ }
+
+ /*
+ * Move back to previous line.
+ */
+
+ if (lineIndex < 0) {
+ lineIndex = TkBTreeLinesTo(textPtr, dstPtr->linePtr);
+ }
+ if (lineIndex == 0) {
+ dstPtr->byteIndex = 0;
+ goto backwardCharDone;
+ }
+ lineIndex--;
+ dstPtr->linePtr = TkBTreeFindLine(dstPtr->tree, textPtr, lineIndex);
+
+ /*
+ * Compute the length of the line and add that to dstPtr->byteIndex.
+ */
+
+ oldPtr = dstPtr->linePtr->segPtr;
+ for (segPtr = oldPtr; segPtr != NULL; segPtr = segPtr->nextPtr) {
+ dstPtr->byteIndex += segPtr->size;
+ oldPtr = segPtr;
+ }
+ segPtr = oldPtr;
+ segSize = segPtr->size;
+ }
+
+ backwardCharDone:
+ if (infoPtr != NULL) {
+ TkTextFreeElideInfo(infoPtr);
+ ckfree(infoPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * StartEnd --
+ *
+ * This function handles modifiers like "wordstart" and "lineend" to
+ * adjust indices forwards or backwards.
+ *
+ * Results:
+ * If the modifier is successfully parsed then the return value is the
+ * address of the first character after the modifier, and *indexPtr is
+ * updated to reflect the modifier. If there is a syntax error in the
+ * modifier then NULL is returned.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static const char *
+StartEnd(
+ TkText *textPtr, /* Information about text widget. */
+ const char *string, /* String to parse for additional info about
+ * modifier (count and units). Points to first
+ * character of modifier word. */
+ TkTextIndex *indexPtr) /* Index to modify based on string. */
+{
+ const char *p;
+ size_t length;
+ register TkTextSegment *segPtr;
+ int modifier;
+
+ /*
+ * Find the end of the modifier word.
+ */
+
+ for (p = string; isalnum(UCHAR(*p)); p++) {
+ /* Empty loop body. */
+ }
+
+ length = p-string;
+ if ((*string == 'd') &&
+ (strncmp(string, "display", (length > 7 ? 7 : length)) == 0)) {
+ modifier = TKINDEX_DISPLAY;
+ if (length > 7) {
+ p -= (length - 7);
+ }
+ } else if ((*string == 'a') &&
+ (strncmp(string, "any", (length > 3 ? 3 : length)) == 0)) {
+ modifier = TKINDEX_ANY;
+ if (length > 3) {
+ p -= (length - 3);
+ }
+ } else {
+ modifier = TKINDEX_NONE;
+ }
+
+ /*
+ * If we had a modifier, which we interpreted ok, so now forward to the
+ * actual units.
+ */
+
+ if (modifier != TKINDEX_NONE) {
+ while (isspace(UCHAR(*p))) {
+ p++;
+ }
+ string = p;
+ while ((*p!='\0') && !isspace(UCHAR(*p)) && (*p!='+') && (*p!='-')) {
+ p++;
+ }
+ length = p - string;
+ }
+
+ if ((*string == 'l') && (strncmp(string, "lineend", length) == 0)
+ && (length >= 5)) {
+ if (modifier == TKINDEX_DISPLAY) {
+ TkTextFindDisplayLineEnd(textPtr, indexPtr, 1, NULL);
+ } else {
+ indexPtr->byteIndex = 0;
+ for (segPtr = indexPtr->linePtr->segPtr; segPtr != NULL;
+ segPtr = segPtr->nextPtr) {
+ indexPtr->byteIndex += segPtr->size;
+ }
+
+ /*
+ * We know '\n' is encoded with a single byte index.
+ */
+
+ indexPtr->byteIndex -= sizeof(char);
+ }
+ } else if ((*string == 'l') && (strncmp(string, "linestart", length) == 0)
+ && (length >= 5)) {
+ if (modifier == TKINDEX_DISPLAY) {
+ TkTextFindDisplayLineEnd(textPtr, indexPtr, 0, NULL);
+ } else {
+ indexPtr->byteIndex = 0;
+ }
+ } else if ((*string == 'w') && (strncmp(string, "wordend", length) == 0)
+ && (length >= 5)) {
+ int firstChar = 1;
+ int offset;
+
+ /*
+ * If the current character isn't part of a word then just move
+ * forward one character. Otherwise move forward until finding a
+ * character that isn't part of a word and stop there.
+ */
+
+ if (modifier == TKINDEX_DISPLAY) {
+ TkTextIndexForwChars(textPtr, indexPtr, 0, indexPtr,
+ COUNT_DISPLAY_INDICES);
+ }
+ segPtr = TkTextIndexToSeg(indexPtr, &offset);
+ while (1) {
+ int chSize = 1;
+
+ if (segPtr->typePtr == &tkTextCharType) {
+ int ch;
+
+ chSize = TkUtfToUniChar(segPtr->body.chars + offset, &ch);
+ if (!Tcl_UniCharIsWordChar(ch)) {
+ break;
+ }
+ firstChar = 0;
+ }
+ offset += chSize;
+ indexPtr->byteIndex += chSize;
+ if (offset >= segPtr->size) {
+ segPtr = TkTextIndexToSeg(indexPtr, &offset);
+ }
+ }
+ if (firstChar) {
+ if (modifier == TKINDEX_DISPLAY) {
+ TkTextIndexForwChars(textPtr, indexPtr, 1, indexPtr,
+ COUNT_DISPLAY_INDICES);
+ } else {
+ TkTextIndexForwChars(NULL, indexPtr, 1, indexPtr,
+ COUNT_INDICES);
+ }
+ }
+ } else if ((*string == 'w') && (strncmp(string, "wordstart", length) == 0)
+ && (length >= 5)) {
+ int firstChar = 1;
+ int offset;
+
+ if (modifier == TKINDEX_DISPLAY) {
+ TkTextIndexForwChars(textPtr, indexPtr, 0, indexPtr,
+ COUNT_DISPLAY_INDICES);
+ }
+
+ /*
+ * Starting with the current character, look for one that's not part
+ * of a word and keep moving backward until you find one. Then if the
+ * character found wasn't the first one, move forward again one
+ * position.
+ */
+
+ segPtr = TkTextIndexToSeg(indexPtr, &offset);
+ while (1) {
+ int chSize = 1;
+
+ if (segPtr->typePtr == &tkTextCharType) {
+
+ int ch;
+ TkUtfToUniChar(segPtr->body.chars + offset, &ch);
+ if (!Tcl_UniCharIsWordChar(ch)) {
+ break;
+ }
+ if (offset > 0) {
+ chSize = (segPtr->body.chars + offset
+ - Tcl_UtfPrev(segPtr->body.chars + offset,
+ segPtr->body.chars));
+ }
+ firstChar = 0;
+ }
+ if (offset == 0) {
+ if (modifier == TKINDEX_DISPLAY) {
+ TkTextIndexBackChars(textPtr, indexPtr, 1, indexPtr,
+ COUNT_DISPLAY_INDICES);
+ } else {
+ TkTextIndexBackChars(NULL, indexPtr, 1, indexPtr,
+ COUNT_INDICES);
+ }
+ } else {
+ indexPtr->byteIndex -= chSize;
+ }
+ offset -= chSize;
+ if (offset < 0) {
+ if (indexPtr->byteIndex == 0) {
+ goto done;
+ }
+ segPtr = TkTextIndexToSeg(indexPtr, &offset);
+ }
+ }
+
+ if (!firstChar) {
+ if (modifier == TKINDEX_DISPLAY) {
+ TkTextIndexForwChars(textPtr, indexPtr, 1, indexPtr,
+ COUNT_DISPLAY_INDICES);
+ } else {
+ TkTextIndexForwChars(NULL, indexPtr, 1, indexPtr,
+ COUNT_INDICES);
+ }
+ }
+ } else {
+ return NULL;
+ }
+
+ done:
+ return p;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkTextMark.c b/tk8.6/generic/tkTextMark.c
new file mode 100644
index 0000000..6a41c77
--- /dev/null
+++ b/tk8.6/generic/tkTextMark.c
@@ -0,0 +1,1027 @@
+/*
+ * tkTextMark.c --
+ *
+ * This file contains the functions that implement marks for text
+ * widgets.
+ *
+ * Copyright (c) 1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "tkInt.h"
+#include "tkText.h"
+#include "tk3d.h"
+
+/*
+ * Macro that determines the size of a mark segment:
+ */
+
+#define MSEG_SIZE ((unsigned) (Tk_Offset(TkTextSegment, body) \
+ + sizeof(TkTextMark)))
+
+/*
+ * Forward references for functions defined in this file:
+ */
+
+static Tcl_Obj * GetMarkName(TkText *textPtr, TkTextSegment *segPtr);
+static void InsertUndisplayProc(TkText *textPtr,
+ TkTextDispChunk *chunkPtr);
+static int MarkDeleteProc(TkTextSegment *segPtr,
+ TkTextLine *linePtr, int treeGone);
+static TkTextSegment * MarkCleanupProc(TkTextSegment *segPtr,
+ TkTextLine *linePtr);
+static void MarkCheckProc(TkTextSegment *segPtr,
+ TkTextLine *linePtr);
+static int MarkLayoutProc(TkText *textPtr, TkTextIndex *indexPtr,
+ TkTextSegment *segPtr, int offset, int maxX,
+ int maxChars, int noCharsYet, TkWrapMode wrapMode,
+ TkTextDispChunk *chunkPtr);
+static int MarkFindNext(Tcl_Interp *interp,
+ TkText *textPtr, Tcl_Obj *markName);
+static int MarkFindPrev(Tcl_Interp *interp,
+ TkText *textPtr, Tcl_Obj *markName);
+
+
+/*
+ * The following structures declare the "mark" segment types. There are
+ * actually two types for marks, one with left gravity and one with right
+ * gravity. They are identical except for their gravity property.
+ */
+
+const Tk_SegType tkTextRightMarkType = {
+ "mark", /* name */
+ 0, /* leftGravity */
+ NULL, /* splitProc */
+ MarkDeleteProc, /* deleteProc */
+ MarkCleanupProc, /* cleanupProc */
+ NULL, /* lineChangeProc */
+ MarkLayoutProc, /* layoutProc */
+ MarkCheckProc /* checkProc */
+};
+
+const Tk_SegType tkTextLeftMarkType = {
+ "mark", /* name */
+ 1, /* leftGravity */
+ NULL, /* splitProc */
+ MarkDeleteProc, /* deleteProc */
+ MarkCleanupProc, /* cleanupProc */
+ NULL, /* lineChangeProc */
+ MarkLayoutProc, /* layoutProc */
+ MarkCheckProc /* checkProc */
+};
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkTextMarkCmd --
+ *
+ * This function is invoked to process the "mark" options of the widget
+ * command for text widgets. See the user documentation for details on
+ * what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkTextMarkCmd(
+ register TkText *textPtr, /* Information about text widget. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. Someone else has already
+ * parsed this command enough to know that
+ * objv[1] is "mark". */
+{
+ Tcl_HashEntry *hPtr;
+ TkTextSegment *markPtr;
+ Tcl_HashSearch search;
+ TkTextIndex index;
+ const Tk_SegType *newTypePtr;
+ int optionIndex;
+ static const char *const markOptionStrings[] = {
+ "gravity", "names", "next", "previous", "set", "unset", NULL
+ };
+ enum markOptions {
+ MARK_GRAVITY, MARK_NAMES, MARK_NEXT, MARK_PREVIOUS, MARK_SET,
+ MARK_UNSET
+ };
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObjStruct(interp, objv[2], markOptionStrings,
+ sizeof(char *), "mark option", 0, &optionIndex) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch ((enum markOptions) optionIndex) {
+ case MARK_GRAVITY: {
+ char c;
+ int length;
+ const char *str;
+
+ if (objc < 4 || objc > 5) {
+ Tcl_WrongNumArgs(interp, 3, objv, "markName ?gravity?");
+ return TCL_ERROR;
+ }
+ str = Tcl_GetStringFromObj(objv[3], &length);
+ if (length == 6 && !strcmp(str, "insert")) {
+ markPtr = textPtr->insertMarkPtr;
+ } else if (length == 7 && !strcmp(str, "current")) {
+ markPtr = textPtr->currentMarkPtr;
+ } else {
+ hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->markTable, str);
+ if (hPtr == NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "there is no mark named \"%s\"", str));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "TEXT_MARK", str,
+ NULL);
+ return TCL_ERROR;
+ }
+ markPtr = Tcl_GetHashValue(hPtr);
+ }
+ if (objc == 4) {
+ const char *typeStr;
+
+ if (markPtr->typePtr == &tkTextRightMarkType) {
+ typeStr = "right";
+ } else {
+ typeStr = "left";
+ }
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(typeStr, -1));
+ return TCL_OK;
+ }
+ str = Tcl_GetStringFromObj(objv[4],&length);
+ c = str[0];
+ if ((c == 'l') && (strncmp(str, "left", (unsigned) length) == 0)) {
+ newTypePtr = &tkTextLeftMarkType;
+ } else if ((c == 'r') &&
+ (strncmp(str, "right", (unsigned) length) == 0)) {
+ newTypePtr = &tkTextRightMarkType;
+ } else {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad mark gravity \"%s\": must be left or right", str));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "MARK_GRAVITY", NULL);
+ return TCL_ERROR;
+ }
+ TkTextMarkSegToIndex(textPtr, markPtr, &index);
+ TkBTreeUnlinkSegment(markPtr, markPtr->body.mark.linePtr);
+ markPtr->typePtr = newTypePtr;
+ TkBTreeLinkSegment(markPtr, &index);
+ break;
+ }
+ case MARK_NAMES: {
+ Tcl_Obj *resultObj;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ return TCL_ERROR;
+ }
+ resultObj = Tcl_NewObj();
+ Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(
+ "insert", -1));
+ Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(
+ "current", -1));
+ for (hPtr = Tcl_FirstHashEntry(&textPtr->sharedTextPtr->markTable,
+ &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
+ Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(
+ Tcl_GetHashKey(&textPtr->sharedTextPtr->markTable, hPtr),
+ -1));
+ }
+ Tcl_SetObjResult(interp, resultObj);
+ break;
+ }
+ case MARK_NEXT:
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index");
+ return TCL_ERROR;
+ }
+ return MarkFindNext(interp, textPtr, objv[3]);
+ case MARK_PREVIOUS:
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index");
+ return TCL_ERROR;
+ }
+ return MarkFindPrev(interp, textPtr, objv[3]);
+ case MARK_SET:
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 3, objv, "markName index");
+ return TCL_ERROR;
+ }
+ if (TkTextGetObjIndex(interp, textPtr, objv[4], &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ TkTextSetMark(textPtr, Tcl_GetString(objv[3]), &index);
+ return TCL_OK;
+ case MARK_UNSET: {
+ int i;
+
+ for (i = 3; i < objc; i++) {
+ hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->markTable,
+ Tcl_GetString(objv[i]));
+ if (hPtr != NULL) {
+ markPtr = Tcl_GetHashValue(hPtr);
+
+ /*
+ * Special case not needed with peer widgets.
+ */
+
+ if ((markPtr == textPtr->insertMarkPtr)
+ || (markPtr == textPtr->currentMarkPtr)) {
+ continue;
+ }
+ TkBTreeUnlinkSegment(markPtr, markPtr->body.mark.linePtr);
+ Tcl_DeleteHashEntry(hPtr);
+ ckfree(markPtr);
+ }
+ }
+ break;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkTextSetMark --
+ *
+ * Set a mark to a particular position, creating a new mark if one
+ * doesn't already exist.
+ *
+ * Results:
+ * The return value is a pointer to the mark that was just set.
+ *
+ * Side effects:
+ * A new mark is created, or an existing mark is moved.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkTextSegment *
+TkTextSetMark(
+ TkText *textPtr, /* Text widget in which to create mark. */
+ const char *name, /* Name of mark to set. */
+ TkTextIndex *indexPtr) /* Where to set mark. */
+{
+ Tcl_HashEntry *hPtr = NULL;
+ TkTextSegment *markPtr;
+ TkTextIndex insertIndex;
+ int isNew, widgetSpecific;
+
+ if (!strcmp(name, "insert")) {
+ widgetSpecific = 1;
+ markPtr = textPtr->insertMarkPtr;
+ isNew = (markPtr == NULL ? 1 : 0);
+ } else if (!strcmp(name, "current")) {
+ widgetSpecific = 2;
+ markPtr = textPtr->currentMarkPtr;
+ isNew = (markPtr == NULL ? 1 : 0);
+ } else {
+ widgetSpecific = 0;
+ hPtr = Tcl_CreateHashEntry(&textPtr->sharedTextPtr->markTable, name,
+ &isNew);
+ markPtr = Tcl_GetHashValue(hPtr);
+ }
+ if (!isNew) {
+ /*
+ * If this is the insertion point that's being moved, be sure to force
+ * a display update at the old position. Also, don't let the insertion
+ * cursor be after the final newline of the file.
+ */
+
+ if (markPtr == textPtr->insertMarkPtr) {
+ TkTextIndex index, index2;
+ int nblines;
+
+ TkTextMarkSegToIndex(textPtr, textPtr->insertMarkPtr, &index);
+ TkTextIndexForwChars(NULL, &index, 1, &index2, COUNT_INDICES);
+
+ /*
+ * While we wish to redisplay, no heights have changed, so no need
+ * to call TkTextInvalidateLineMetrics.
+ */
+
+ TkTextChanged(NULL, textPtr, &index, &index2);
+
+ /*
+ * The number of lines in the widget is zero if and only if it is
+ * a partial peer with -startline == -endline, i.e. an empty
+ * peer. In this case the mark shall be set exactly at the given
+ * index, and not one character backwards (bug 3487407).
+ */
+
+ nblines = TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr);
+ if ((TkBTreeLinesTo(textPtr, indexPtr->linePtr) == nblines)
+ && (nblines > 0)) {
+ TkTextIndexBackChars(NULL,indexPtr, 1, &insertIndex,
+ COUNT_INDICES);
+ indexPtr = &insertIndex;
+ }
+ }
+ TkBTreeUnlinkSegment(markPtr, markPtr->body.mark.linePtr);
+ } else {
+ markPtr = ckalloc(MSEG_SIZE);
+ markPtr->typePtr = &tkTextRightMarkType;
+ markPtr->size = 0;
+ markPtr->body.mark.textPtr = textPtr;
+ markPtr->body.mark.linePtr = indexPtr->linePtr;
+ markPtr->body.mark.hPtr = hPtr;
+ if (widgetSpecific == 0) {
+ Tcl_SetHashValue(hPtr, markPtr);
+ } else if (widgetSpecific == 1) {
+ textPtr->insertMarkPtr = markPtr;
+ } else {
+ textPtr->currentMarkPtr = markPtr;
+ }
+ }
+ TkBTreeLinkSegment(markPtr, indexPtr);
+
+ /*
+ * If the mark is the insertion cursor, then update the screen at the
+ * mark's new location.
+ */
+
+ if (markPtr == textPtr->insertMarkPtr) {
+ TkTextIndex index2;
+
+ TkTextIndexForwChars(NULL, indexPtr, 1, &index2, COUNT_INDICES);
+
+ /*
+ * While we wish to redisplay, no heights have changed, so no need to
+ * call TkTextInvalidateLineMetrics
+ */
+
+ TkTextChanged(NULL, textPtr, indexPtr, &index2);
+ }
+ return markPtr;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkTextMarkSegToIndex --
+ *
+ * Given a segment that is a mark, create an index that refers to the
+ * next text character (or other text segment with non-zero size) after
+ * the mark.
+ *
+ * Results:
+ * *IndexPtr is filled in with index information.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkTextMarkSegToIndex(
+ TkText *textPtr, /* Text widget containing mark. */
+ TkTextSegment *markPtr, /* Mark segment. */
+ TkTextIndex *indexPtr) /* Index information gets stored here. */
+{
+ TkTextSegment *segPtr;
+
+ indexPtr->tree = textPtr->sharedTextPtr->tree;
+ indexPtr->linePtr = markPtr->body.mark.linePtr;
+ indexPtr->byteIndex = 0;
+ for (segPtr = indexPtr->linePtr->segPtr; segPtr != markPtr;
+ segPtr = segPtr->nextPtr) {
+ indexPtr->byteIndex += segPtr->size;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkTextMarkNameToIndex --
+ *
+ * Given the name of a mark, return an index corresponding to the mark
+ * name.
+ *
+ * Results:
+ * The return value is TCL_OK if "name" exists as a mark in the text
+ * widget and is located within its -starline/-endline range. In this
+ * case *indexPtr is filled in with the next segment who is after the
+ * mark whose size is non-zero. TCL_ERROR is returned if the mark
+ * doesn't exist in the text widget, or if it is out of its -starline/
+ * -endline range. In this latter case *indexPtr still contains valid
+ * information, in particular TkTextMarkNameToIndex called with the
+ * "insert" or "current" mark name may return TCL_ERROR, but *indexPtr
+ * contains the correct index of this mark before -startline or after
+ * -endline.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkTextMarkNameToIndex(
+ TkText *textPtr, /* Text widget containing mark. */
+ const char *name, /* Name of mark. */
+ TkTextIndex *indexPtr) /* Index information gets stored here. */
+{
+ TkTextSegment *segPtr;
+ TkTextIndex index;
+ int start, end;
+
+ if (textPtr == NULL) {
+ return TCL_ERROR;
+ }
+
+ if (!strcmp(name, "insert")) {
+ segPtr = textPtr->insertMarkPtr;
+ } else if (!strcmp(name, "current")) {
+ segPtr = textPtr->currentMarkPtr;
+ } else {
+ Tcl_HashEntry *hPtr =
+ Tcl_FindHashEntry(&textPtr->sharedTextPtr->markTable, name);
+
+ if (hPtr == NULL) {
+ return TCL_ERROR;
+ }
+ segPtr = Tcl_GetHashValue(hPtr);
+ }
+ TkTextMarkSegToIndex(textPtr, segPtr, indexPtr);
+
+ /* If indexPtr refers to somewhere outside the -startline/-endline
+ * range limits of the widget, error out since the mark indeed is not
+ * reachable from this text widget (it may be reachable from a peer)
+ * (bug 1630271).
+ */
+
+ if (textPtr->start != NULL) {
+ start = TkBTreeLinesTo(NULL, textPtr->start);
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, NULL, start, 0,
+ &index);
+ if (TkTextIndexCmp(indexPtr, &index) < 0) {
+ return TCL_ERROR;
+ }
+ }
+ if (textPtr->end != NULL) {
+ end = TkBTreeLinesTo(NULL, textPtr->end);
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, NULL, end, 0,
+ &index);
+ if (TkTextIndexCmp(indexPtr, &index) > 0) {
+ return TCL_ERROR;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * MarkDeleteProc --
+ *
+ * This function is invoked by the text B-tree code whenever a mark lies
+ * in a range of characters being deleted.
+ *
+ * Results:
+ * Returns 1 to indicate that deletion has been rejected.
+ *
+ * Side effects:
+ * None (even if the whole tree is being deleted we don't free up the
+ * mark; it will be done elsewhere).
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+MarkDeleteProc(
+ TkTextSegment *segPtr, /* Segment being deleted. */
+ TkTextLine *linePtr, /* Line containing segment. */
+ int treeGone) /* Non-zero means the entire tree is being
+ * deleted, so everything must get cleaned
+ * up. */
+{
+ return 1;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * MarkCleanupProc --
+ *
+ * This function is invoked by the B-tree code whenever a mark segment is
+ * moved from one line to another.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The linePtr field of the segment gets updated.
+ *
+ *--------------------------------------------------------------
+ */
+
+static TkTextSegment *
+MarkCleanupProc(
+ TkTextSegment *markPtr, /* Mark segment that's being moved. */
+ TkTextLine *linePtr) /* Line that now contains segment. */
+{
+ markPtr->body.mark.linePtr = linePtr;
+ return markPtr;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * MarkLayoutProc --
+ *
+ * This function is the "layoutProc" for mark segments.
+ *
+ * Results:
+ * If the mark isn't the insertion cursor then the return value is -1 to
+ * indicate that this segment shouldn't be displayed. If the mark is the
+ * insertion character then 1 is returned and the chunkPtr structure is
+ * filled in.
+ *
+ * Side effects:
+ * None, except for filling in chunkPtr.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+MarkLayoutProc(
+ TkText *textPtr, /* Text widget being layed out. */
+ TkTextIndex *indexPtr, /* Identifies first character in chunk. */
+ TkTextSegment *segPtr, /* Segment corresponding to indexPtr. */
+ int offset, /* Offset within segPtr corresponding to
+ * indexPtr (always 0). */
+ int maxX, /* Chunk must not occupy pixels at this
+ * position or higher. */
+ int maxChars, /* Chunk must not include more than this many
+ * characters. */
+ int noCharsYet, /* Non-zero means no characters have been
+ * assigned to this line yet. */
+ TkWrapMode wrapMode, /* Not used. */
+ register TkTextDispChunk *chunkPtr)
+ /* Structure to fill in with information about
+ * this chunk. The x field has already been
+ * set by the caller. */
+{
+ if (segPtr != textPtr->insertMarkPtr) {
+ return -1;
+ }
+
+ chunkPtr->displayProc = TkTextInsertDisplayProc;
+ chunkPtr->undisplayProc = InsertUndisplayProc;
+ chunkPtr->measureProc = NULL;
+ chunkPtr->bboxProc = NULL;
+ chunkPtr->numBytes = 0;
+ chunkPtr->minAscent = 0;
+ chunkPtr->minDescent = 0;
+ chunkPtr->minHeight = 0;
+ chunkPtr->width = 0;
+
+ /*
+ * Note: can't break a line after the insertion cursor: this prevents the
+ * insertion cursor from being stranded at the end of a line.
+ */
+
+ chunkPtr->breakIndex = -1;
+ chunkPtr->clientData = textPtr;
+ return 1;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkTextInsertDisplayProc --
+ *
+ * This function is called to display the insertion cursor.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Graphics are drawn.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+void
+TkTextInsertDisplayProc(
+ TkText *textPtr, /* The current text widget. */
+ TkTextDispChunk *chunkPtr, /* Chunk that is to be drawn. */
+ int x, /* X-position in dst at which to draw this
+ * chunk (may differ from the x-position in
+ * the chunk because of scrolling). */
+ int y, /* Y-position at which to draw this chunk in
+ * dst (x-position is in the chunk itself). */
+ int height, /* Total height of line. */
+ int baseline, /* Offset of baseline from y. */
+ Display *display, /* Display to use for drawing. */
+ Drawable dst, /* Pixmap or window in which to draw chunk. */
+ int screenY) /* Y-coordinate in text window that
+ * corresponds to y. */
+{
+ /*
+ * We have no need for the clientData.
+ */
+
+ /* TkText *textPtr = chunkPtr->clientData; */
+ TkTextIndex index;
+ int halfWidth = textPtr->insertWidth/2;
+ int rightSideWidth;
+ int ix = 0, iy = 0, iw = 0, ih = 0, charWidth = 0;
+
+ if (textPtr->insertCursorType) {
+ TkTextMarkSegToIndex(textPtr, textPtr->insertMarkPtr, &index);
+ TkTextIndexBbox(textPtr, &index, &ix, &iy, &iw, &ih, &charWidth);
+ rightSideWidth = charWidth + halfWidth;
+ } else {
+ rightSideWidth = halfWidth;
+ }
+
+ if ((x + rightSideWidth) < 0) {
+ /*
+ * The insertion cursor is off-screen. Indicate caret at 0,0 and
+ * return.
+ */
+
+ Tk_SetCaretPos(textPtr->tkwin, 0, 0, height);
+ return;
+ }
+
+ Tk_SetCaretPos(textPtr->tkwin, x - halfWidth, screenY, height);
+
+ /*
+ * As a special hack to keep the cursor visible on mono displays (or
+ * anywhere else that the selection and insertion cursors have the same
+ * color) write the default background in the cursor area (instead of
+ * nothing) when the cursor isn't on. Otherwise the selection might hide
+ * the cursor.
+ */
+
+ if (textPtr->flags & GOT_FOCUS) {
+ if (textPtr->flags & INSERT_ON) {
+ Tk_Fill3DRectangle(textPtr->tkwin, dst, textPtr->insertBorder,
+ x - halfWidth, y, charWidth + textPtr->insertWidth,
+ height, textPtr->insertBorderWidth, TK_RELIEF_RAISED);
+ } else if (textPtr->selBorder == textPtr->insertBorder) {
+ Tk_Fill3DRectangle(textPtr->tkwin, dst, textPtr->border,
+ x - halfWidth, y, charWidth + textPtr->insertWidth,
+ height, 0, TK_RELIEF_FLAT);
+ }
+ } else if (textPtr->insertUnfocussed == TK_TEXT_INSERT_NOFOCUS_HOLLOW) {
+ if (textPtr->insertBorderWidth < 1) {
+ /*
+ * Hack to work around the fact that a "solid" border always
+ * paints in black.
+ */
+
+ TkBorder *borderPtr = (TkBorder *) textPtr->insertBorder;
+
+ XDrawRectangle(Tk_Display(textPtr->tkwin), dst, borderPtr->bgGC,
+ x - halfWidth, y, charWidth + textPtr->insertWidth - 1,
+ height - 1);
+ } else {
+ Tk_Draw3DRectangle(textPtr->tkwin, dst, textPtr->insertBorder,
+ x - halfWidth, y, charWidth + textPtr->insertWidth,
+ height, textPtr->insertBorderWidth, TK_RELIEF_RAISED);
+ }
+ } else if (textPtr->insertUnfocussed == TK_TEXT_INSERT_NOFOCUS_SOLID) {
+ Tk_Fill3DRectangle(textPtr->tkwin, dst, textPtr->insertBorder,
+ x - halfWidth, y, charWidth + textPtr->insertWidth, height,
+ textPtr->insertBorderWidth, TK_RELIEF_RAISED);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * InsertUndisplayProc --
+ *
+ * This function is called when the insertion cursor is no longer at a
+ * visible point on the display. It does nothing right now.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static void
+InsertUndisplayProc(
+ TkText *textPtr, /* Overall information about text widget. */
+ TkTextDispChunk *chunkPtr) /* Chunk that is about to be freed. */
+{
+ return;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * MarkCheckProc --
+ *
+ * This function is invoked by the B-tree code to perform consistency
+ * checks on mark segments.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The function panics if it detects anything wrong with
+ * the mark.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+MarkCheckProc(
+ TkTextSegment *markPtr, /* Segment to check. */
+ TkTextLine *linePtr) /* Line containing segment. */
+{
+ Tcl_HashSearch search;
+ Tcl_HashEntry *hPtr;
+
+ if (markPtr->body.mark.linePtr != linePtr) {
+ Tcl_Panic("MarkCheckProc: markPtr->body.mark.linePtr bogus");
+ }
+
+ /*
+ * These two marks are not in the hash table
+ */
+
+ if (markPtr->body.mark.textPtr->insertMarkPtr == markPtr) {
+ return;
+ }
+ if (markPtr->body.mark.textPtr->currentMarkPtr == markPtr) {
+ return;
+ }
+
+ /*
+ * Make sure that the mark is still present in the text's mark hash table.
+ */
+
+ for (hPtr = Tcl_FirstHashEntry(
+ &markPtr->body.mark.textPtr->sharedTextPtr->markTable,
+ &search); hPtr != markPtr->body.mark.hPtr;
+ hPtr = Tcl_NextHashEntry(&search)) {
+ if (hPtr == NULL) {
+ Tcl_Panic("MarkCheckProc couldn't find hash table entry for mark");
+ }
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * MarkFindNext --
+ *
+ * This function searches forward for the next mark.
+ *
+ * Results:
+ * A standard Tcl result, which is a mark name or an empty string.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+MarkFindNext(
+ Tcl_Interp *interp, /* For error reporting */
+ TkText *textPtr, /* The widget */
+ Tcl_Obj *obj) /* The starting index or mark name */
+{
+ TkTextIndex index;
+ Tcl_HashEntry *hPtr;
+ register TkTextSegment *segPtr;
+ int offset;
+ const char *string = Tcl_GetString(obj);
+
+ if (!strcmp(string, "insert")) {
+ segPtr = textPtr->insertMarkPtr;
+ TkTextMarkSegToIndex(textPtr, segPtr, &index);
+ segPtr = segPtr->nextPtr;
+ } else if (!strcmp(string, "current")) {
+ segPtr = textPtr->currentMarkPtr;
+ TkTextMarkSegToIndex(textPtr, segPtr, &index);
+ segPtr = segPtr->nextPtr;
+ } else {
+ hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->markTable, string);
+ if (hPtr != NULL) {
+ /*
+ * If given a mark name, return the next mark in the list of
+ * segments, even if it happens to be at the same character
+ * position.
+ */
+
+ segPtr = Tcl_GetHashValue(hPtr);
+ TkTextMarkSegToIndex(textPtr, segPtr, &index);
+ segPtr = segPtr->nextPtr;
+ } else {
+ /*
+ * For non-mark name indices we want to return any marks that are
+ * right at the index.
+ */
+
+ if (TkTextGetObjIndex(interp, textPtr, obj, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ for (offset = 0, segPtr = index.linePtr->segPtr;
+ segPtr != NULL && offset < index.byteIndex;
+ offset += segPtr->size, segPtr = segPtr->nextPtr) {
+ /* Empty loop body */ ;
+ }
+ }
+ }
+
+ while (1) {
+ /*
+ * segPtr points at the first possible candidate, or NULL if we ran
+ * off the end of the line.
+ */
+
+ for ( ; segPtr != NULL ; segPtr = segPtr->nextPtr) {
+ if (segPtr->typePtr == &tkTextRightMarkType ||
+ segPtr->typePtr == &tkTextLeftMarkType) {
+ Tcl_Obj *markName = GetMarkName(textPtr, segPtr);
+
+ if (markName != NULL) {
+ Tcl_SetObjResult(interp, markName);
+ return TCL_OK;
+ }
+ }
+ }
+ index.linePtr = TkBTreeNextLine(textPtr, index.linePtr);
+ if (index.linePtr == NULL) {
+ return TCL_OK;
+ }
+ index.byteIndex = 0;
+ segPtr = index.linePtr->segPtr;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * MarkFindPrev --
+ *
+ * This function searches backwards for the previous mark.
+ *
+ * Results:
+ * A standard Tcl result, which is a mark name or an empty string.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+MarkFindPrev(
+ Tcl_Interp *interp, /* For error reporting */
+ TkText *textPtr, /* The widget */
+ Tcl_Obj *obj) /* The starting index or mark name */
+{
+ TkTextIndex index;
+ Tcl_HashEntry *hPtr;
+ register TkTextSegment *segPtr, *seg2Ptr, *prevPtr;
+ int offset;
+ const char *string = Tcl_GetString(obj);
+
+ if (!strcmp(string, "insert")) {
+ segPtr = textPtr->insertMarkPtr;
+ TkTextMarkSegToIndex(textPtr, segPtr, &index);
+ } else if (!strcmp(string, "current")) {
+ segPtr = textPtr->currentMarkPtr;
+ TkTextMarkSegToIndex(textPtr, segPtr, &index);
+ } else {
+ hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->markTable, string);
+ if (hPtr != NULL) {
+ /*
+ * If given a mark name, return the previous mark in the list of
+ * segments, even if it happens to be at the same character
+ * position.
+ */
+
+ segPtr = Tcl_GetHashValue(hPtr);
+ TkTextMarkSegToIndex(textPtr, segPtr, &index);
+ } else {
+ /*
+ * For non-mark name indices we do not return any marks that are
+ * right at the index.
+ */
+
+ if (TkTextGetObjIndex(interp, textPtr, obj, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ for (offset = 0, segPtr = index.linePtr->segPtr;
+ segPtr != NULL && offset < index.byteIndex;
+ offset += segPtr->size, segPtr = segPtr->nextPtr) {
+ /* Empty loop body */
+ }
+ }
+ }
+
+ while (1) {
+ /*
+ * segPtr points just past the first possible candidate, or at the
+ * beginning of the line.
+ */
+
+ for (prevPtr = NULL, seg2Ptr = index.linePtr->segPtr;
+ seg2Ptr != NULL && seg2Ptr != segPtr;
+ seg2Ptr = seg2Ptr->nextPtr) {
+ if (seg2Ptr->typePtr == &tkTextRightMarkType ||
+ seg2Ptr->typePtr == &tkTextLeftMarkType) {
+ if (seg2Ptr->body.mark.hPtr == NULL) {
+ if (seg2Ptr != textPtr->currentMarkPtr &&
+ seg2Ptr != textPtr->insertMarkPtr) {
+ /*
+ * This is an insert or current mark from a
+ * peer of textPtr.
+ */
+ continue;
+ }
+ }
+ prevPtr = seg2Ptr;
+ }
+ }
+ if (prevPtr != NULL) {
+ Tcl_Obj *markName = GetMarkName(textPtr, prevPtr);
+
+ if (markName != NULL) {
+ Tcl_SetObjResult(interp, markName);
+ return TCL_OK;
+ }
+ }
+ index.linePtr = TkBTreePreviousLine(textPtr, index.linePtr);
+ if (index.linePtr == NULL) {
+ return TCL_OK;
+ }
+ segPtr = NULL;
+ }
+}
+
+/*
+ * ------------------------------------------------------------------------
+ *
+ * GetMarkName --
+ * Returns the name of the mark that is the given text segment, or NULL
+ * if it is unnamed (i.e., a widget-specific mark that isn't "current" or
+ * "insert").
+ *
+ * ------------------------------------------------------------------------
+ */
+
+static Tcl_Obj *
+GetMarkName(
+ TkText *textPtr,
+ TkTextSegment *segPtr)
+{
+ const char *markName;
+
+ if (segPtr == textPtr->currentMarkPtr) {
+ markName = "current";
+ } else if (segPtr == textPtr->insertMarkPtr) {
+ markName = "insert";
+ } else if (segPtr->body.mark.hPtr == NULL) {
+ /*
+ * Ignore widget-specific marks for the other widgets. This is either
+ * an insert or a current mark (markPtr->body.mark.hPtr actually
+ * receives NULL for these marks in TkTextSetMark). The insert and
+ * current marks for textPtr having already been tested above, the
+ * current segment is an insert or current mark from a peer of
+ * textPtr, which we don't want to return.
+ */
+
+ return NULL;
+ } else {
+ markName = Tcl_GetHashKey(&textPtr->sharedTextPtr->markTable,
+ segPtr->body.mark.hPtr);
+ }
+ return Tcl_NewStringObj(markName, -1);
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkTextTag.c b/tk8.6/generic/tkTextTag.c
new file mode 100644
index 0000000..13216ca
--- /dev/null
+++ b/tk8.6/generic/tkTextTag.c
@@ -0,0 +1,1802 @@
+/*
+ * tkTextTag.c --
+ *
+ * This module implements the "tag" subcommand of the widget command for
+ * text widgets, plus most of the other high-level functions related to
+ * tags.
+ *
+ * Copyright (c) 1992-1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "default.h"
+#include "tkInt.h"
+#include "tkText.h"
+
+/*
+ * The 'TkWrapMode' enum in tkText.h is used to define a type for the -wrap
+ * option of tags in a Text widget. These values are used as indices into the
+ * string table below. Tags are allowed an empty wrap value, but the widget as
+ * a whole is not.
+ */
+
+static const char *const wrapStrings[] = {
+ "char", "none", "word", "", NULL
+};
+
+/*
+ * The 'TkTextTabStyle' enum in tkText.h is used to define a type for the
+ * -tabstyle option of the Text widget. These values are used as indices into
+ * the string table below. Tags are allowed an empty tabstyle value, but the
+ * widget as a whole is not.
+ */
+
+static const char *const tabStyleStrings[] = {
+ "tabular", "wordprocessor", "", NULL
+};
+
+static const Tk_OptionSpec tagOptionSpecs[] = {
+ {TK_OPTION_BORDER, "-background", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, border), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_BITMAP, "-bgstipple", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, bgStipple), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-borderwidth", NULL, NULL,
+ NULL, Tk_Offset(TkTextTag, borderWidthPtr), Tk_Offset(TkTextTag, borderWidth),
+ TK_OPTION_NULL_OK|TK_OPTION_DONT_SET_DEFAULT, 0, 0},
+ {TK_OPTION_STRING, "-elide", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, elideString),
+ TK_OPTION_NULL_OK|TK_OPTION_DONT_SET_DEFAULT, 0, 0},
+ {TK_OPTION_BITMAP, "-fgstipple", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, fgStipple), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_FONT, "-font", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, tkfont), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_COLOR, "-foreground", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, fgColor), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-justify", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, justifyString), TK_OPTION_NULL_OK, 0,0},
+ {TK_OPTION_STRING, "-lmargin1", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, lMargin1String), TK_OPTION_NULL_OK,0,0},
+ {TK_OPTION_STRING, "-lmargin2", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, lMargin2String), TK_OPTION_NULL_OK,0,0},
+ {TK_OPTION_BORDER, "-lmargincolor", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, lMarginColor), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-offset", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, offsetString), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-overstrike", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, overstrikeString),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_COLOR, "-overstrikefg", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, overstrikeColor),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-relief", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, reliefString), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-rmargin", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, rMarginString), TK_OPTION_NULL_OK, 0,0},
+ {TK_OPTION_BORDER, "-rmargincolor", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, rMarginColor), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_BORDER, "-selectbackground", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, selBorder), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_COLOR, "-selectforeground", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, selFgColor), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-spacing1", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, spacing1String), TK_OPTION_NULL_OK,0,0},
+ {TK_OPTION_STRING, "-spacing2", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, spacing2String), TK_OPTION_NULL_OK,0,0},
+ {TK_OPTION_STRING, "-spacing3", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, spacing3String), TK_OPTION_NULL_OK,0,0},
+ {TK_OPTION_STRING, "-tabs", NULL, NULL,
+ NULL, Tk_Offset(TkTextTag, tabStringPtr), -1, TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-tabstyle", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, tabStyle),
+ TK_OPTION_NULL_OK, tabStyleStrings, 0},
+ {TK_OPTION_STRING, "-underline", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, underlineString),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_COLOR, "-underlinefg", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, underlineColor),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-wrap", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, wrapMode),
+ TK_OPTION_NULL_OK, wrapStrings, 0},
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}
+};
+
+/*
+ * Forward declarations for functions defined later in this file:
+ */
+
+static void ChangeTagPriority(TkText *textPtr, TkTextTag *tagPtr,
+ int prio);
+static TkTextTag * FindTag(Tcl_Interp *interp, TkText *textPtr,
+ Tcl_Obj *tagName);
+static void SortTags(int numTags, TkTextTag **tagArrayPtr);
+static int TagSortProc(const void *first, const void *second);
+static void TagBindEvent(TkText *textPtr, XEvent *eventPtr,
+ int numTags, TkTextTag **tagArrayPtr);
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkTextTagCmd --
+ *
+ * This function is invoked to process the "tag" options of the widget
+ * command for text widgets. See the user documentation for details on
+ * what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkTextTagCmd(
+ register TkText *textPtr, /* Information about text widget. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. Someone else has already
+ * parsed this command enough to know that
+ * objv[1] is "tag". */
+{
+ static const char *const tagOptionStrings[] = {
+ "add", "bind", "cget", "configure", "delete", "lower", "names",
+ "nextrange", "prevrange", "raise", "ranges", "remove", NULL
+ };
+ enum tagOptions {
+ TAG_ADD, TAG_BIND, TAG_CGET, TAG_CONFIGURE, TAG_DELETE, TAG_LOWER,
+ TAG_NAMES, TAG_NEXTRANGE, TAG_PREVRANGE, TAG_RAISE, TAG_RANGES,
+ TAG_REMOVE
+ };
+ int optionIndex, i;
+ register TkTextTag *tagPtr;
+ TkTextIndex index1, index2;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[2], tagOptionStrings,
+ sizeof(char *), "tag option", 0, &optionIndex) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch ((enum tagOptions)optionIndex) {
+ case TAG_ADD:
+ case TAG_REMOVE: {
+ int addTag;
+
+ if (((enum tagOptions)optionIndex) == TAG_ADD) {
+ addTag = 1;
+ } else {
+ addTag = 0;
+ }
+ if (objc < 5) {
+ Tcl_WrongNumArgs(interp, 3, objv,
+ "tagName index1 ?index2 index1 index2 ...?");
+ return TCL_ERROR;
+ }
+ tagPtr = TkTextCreateTag(textPtr, Tcl_GetString(objv[3]), NULL);
+ if (tagPtr->elide) {
+ /*
+ * Indices are potentially obsolete after adding or removing
+ * elided character ranges, especially indices having "display"
+ * or "any" submodifier, therefore increase the epoch.
+ */
+ textPtr->sharedTextPtr->stateEpoch++;
+ }
+ for (i = 4; i < objc; i += 2) {
+ if (TkTextGetObjIndex(interp, textPtr, objv[i],
+ &index1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (objc > (i+1)) {
+ if (TkTextGetObjIndex(interp, textPtr, objv[i+1],
+ &index2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (TkTextIndexCmp(&index1, &index2) >= 0) {
+ return TCL_OK;
+ }
+ } else {
+ index2 = index1;
+ TkTextIndexForwChars(NULL,&index2, 1, &index2, COUNT_INDICES);
+ }
+
+ if (tagPtr->affectsDisplay) {
+ TkTextRedrawTag(textPtr->sharedTextPtr, NULL, &index1, &index2,
+ tagPtr, !addTag);
+ } else {
+ /*
+ * Still need to trigger enter/leave events on tags that have
+ * changed.
+ */
+
+ TkTextEventuallyRepick(textPtr);
+ }
+ if (TkBTreeTag(&index1, &index2, tagPtr, addTag)) {
+ /*
+ * If the tag is "sel", and we actually adjusted something
+ * then grab the selection if we're supposed to export it and
+ * don't already have it.
+ *
+ * Also, invalidate partially-completed selection retrievals.
+ * We only need to check whether the tag is "sel" for this
+ * textPtr (not for other peer widget's "sel" tags) because we
+ * cannot reach this code path with a different widget's "sel"
+ * tag.
+ */
+
+ if (tagPtr == textPtr->selTagPtr) {
+ /*
+ * Send an event that the selection changed. This is
+ * equivalent to:
+ * event generate $textWidget <<Selection>>
+ */
+
+ TkTextSelectionEvent(textPtr);
+
+ if (addTag && textPtr->exportSelection
+ && (!Tcl_IsSafe(textPtr->interp))
+ && !(textPtr->flags & GOT_SELECTION)) {
+ Tk_OwnSelection(textPtr->tkwin, XA_PRIMARY,
+ TkTextLostSelection, textPtr);
+ textPtr->flags |= GOT_SELECTION;
+ }
+ textPtr->abortSelections = 1;
+ }
+ }
+ }
+ break;
+ }
+ case TAG_BIND:
+ if ((objc < 4) || (objc > 6)) {
+ Tcl_WrongNumArgs(interp, 3, objv, "tagName ?sequence? ?command?");
+ return TCL_ERROR;
+ }
+ tagPtr = TkTextCreateTag(textPtr, Tcl_GetString(objv[3]), NULL);
+
+ /*
+ * Make a binding table if the widget doesn't already have one.
+ */
+
+ if (textPtr->sharedTextPtr->bindingTable == NULL) {
+ textPtr->sharedTextPtr->bindingTable =
+ Tk_CreateBindingTable(interp);
+ }
+
+ if (objc == 6) {
+ int append = 0;
+ unsigned long mask;
+ const char *fifth = Tcl_GetString(objv[5]);
+
+ if (fifth[0] == 0) {
+ return Tk_DeleteBinding(interp,
+ textPtr->sharedTextPtr->bindingTable,
+ (ClientData) tagPtr->name, Tcl_GetString(objv[4]));
+ }
+ if (fifth[0] == '+') {
+ fifth++;
+ append = 1;
+ }
+ mask = Tk_CreateBinding(interp,
+ textPtr->sharedTextPtr->bindingTable,
+ (ClientData) tagPtr->name, Tcl_GetString(objv[4]), fifth,
+ append);
+ if (mask == 0) {
+ return TCL_ERROR;
+ }
+ if (mask & (unsigned) ~(ButtonMotionMask|Button1MotionMask
+ |Button2MotionMask|Button3MotionMask|Button4MotionMask
+ |Button5MotionMask|ButtonPressMask|ButtonReleaseMask
+ |EnterWindowMask|LeaveWindowMask|KeyPressMask
+ |KeyReleaseMask|PointerMotionMask|VirtualEventMask)) {
+ Tk_DeleteBinding(interp, textPtr->sharedTextPtr->bindingTable,
+ (ClientData) tagPtr->name, Tcl_GetString(objv[4]));
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "requested illegal events; only key, button, motion,"
+ " enter, leave, and virtual events may be used", -1));
+ Tcl_SetErrorCode(interp, "TK", "TEXT", "TAG_BIND_EVENT",NULL);
+ return TCL_ERROR;
+ }
+ } else if (objc == 5) {
+ const char *command;
+
+ command = Tk_GetBinding(interp,
+ textPtr->sharedTextPtr->bindingTable,
+ (ClientData) tagPtr->name, Tcl_GetString(objv[4]));
+ if (command == NULL) {
+ const char *string = Tcl_GetString(Tcl_GetObjResult(interp));
+
+ /*
+ * Ignore missing binding errors. This is a special hack that
+ * relies on the error message returned by FindSequence in
+ * tkBind.c.
+ */
+
+ if (string[0] != '\0') {
+ return TCL_ERROR;
+ }
+ Tcl_ResetResult(interp);
+ } else {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(command, -1));
+ }
+ } else {
+ Tk_GetAllBindings(interp, textPtr->sharedTextPtr->bindingTable,
+ (ClientData) tagPtr->name);
+ }
+ break;
+ case TAG_CGET:
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 1, objv, "tag cget tagName option");
+ return TCL_ERROR;
+ } else {
+ Tcl_Obj *objPtr;
+
+ tagPtr = FindTag(interp, textPtr, objv[3]);
+ if (tagPtr == NULL) {
+ return TCL_ERROR;
+ }
+ objPtr = Tk_GetOptionValue(interp, (char *) tagPtr,
+ tagPtr->optionTable, objv[4], textPtr->tkwin);
+ if (objPtr == NULL) {
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ return TCL_OK;
+ }
+ break;
+ case TAG_CONFIGURE: {
+ int newTag;
+
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 3, objv,
+ "tagName ?-option? ?value? ?-option value ...?");
+ return TCL_ERROR;
+ }
+ tagPtr = TkTextCreateTag(textPtr, Tcl_GetString(objv[3]), &newTag);
+ if (objc <= 5) {
+ Tcl_Obj *objPtr = Tk_GetOptionInfo(interp, (char *) tagPtr,
+ tagPtr->optionTable,
+ (objc == 5) ? objv[4] : NULL, textPtr->tkwin);
+
+ if (objPtr == NULL) {
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ return TCL_OK;
+ } else {
+ int result = TCL_OK;
+
+ if (Tk_SetOptions(interp, (char *) tagPtr, tagPtr->optionTable,
+ objc-4, objv+4, textPtr->tkwin, NULL, NULL) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Some of the configuration options, like -underline and
+ * -justify, require additional translation (this is needed
+ * because we need to distinguish a particular value of an option
+ * from "unspecified").
+ */
+
+ if (tagPtr->borderWidth < 0) {
+ tagPtr->borderWidth = 0;
+ }
+ if (tagPtr->reliefString != NULL) {
+ if (Tk_GetRelief(interp, tagPtr->reliefString,
+ &tagPtr->relief) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (tagPtr->justifyString != NULL) {
+ if (Tk_GetJustify(interp, tagPtr->justifyString,
+ &tagPtr->justify) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (tagPtr->lMargin1String != NULL) {
+ if (Tk_GetPixels(interp, textPtr->tkwin,
+ tagPtr->lMargin1String, &tagPtr->lMargin1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (tagPtr->lMargin2String != NULL) {
+ if (Tk_GetPixels(interp, textPtr->tkwin,
+ tagPtr->lMargin2String, &tagPtr->lMargin2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (tagPtr->offsetString != NULL) {
+ if (Tk_GetPixels(interp, textPtr->tkwin, tagPtr->offsetString,
+ &tagPtr->offset) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (tagPtr->overstrikeString != NULL) {
+ if (Tcl_GetBoolean(interp, tagPtr->overstrikeString,
+ &tagPtr->overstrike) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (tagPtr->rMarginString != NULL) {
+ if (Tk_GetPixels(interp, textPtr->tkwin,
+ tagPtr->rMarginString, &tagPtr->rMargin) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (tagPtr->spacing1String != NULL) {
+ if (Tk_GetPixels(interp, textPtr->tkwin,
+ tagPtr->spacing1String, &tagPtr->spacing1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (tagPtr->spacing1 < 0) {
+ tagPtr->spacing1 = 0;
+ }
+ }
+ if (tagPtr->spacing2String != NULL) {
+ if (Tk_GetPixels(interp, textPtr->tkwin,
+ tagPtr->spacing2String, &tagPtr->spacing2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (tagPtr->spacing2 < 0) {
+ tagPtr->spacing2 = 0;
+ }
+ }
+ if (tagPtr->spacing3String != NULL) {
+ if (Tk_GetPixels(interp, textPtr->tkwin,
+ tagPtr->spacing3String, &tagPtr->spacing3) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (tagPtr->spacing3 < 0) {
+ tagPtr->spacing3 = 0;
+ }
+ }
+ if (tagPtr->tabArrayPtr != NULL) {
+ ckfree(tagPtr->tabArrayPtr);
+ tagPtr->tabArrayPtr = NULL;
+ }
+ if (tagPtr->tabStringPtr != NULL) {
+ tagPtr->tabArrayPtr =
+ TkTextGetTabs(interp, textPtr, tagPtr->tabStringPtr);
+ if (tagPtr->tabArrayPtr == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ if (tagPtr->underlineString != NULL) {
+ if (Tcl_GetBoolean(interp, tagPtr->underlineString,
+ &tagPtr->underline) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (tagPtr->elideString != NULL) {
+ if (Tcl_GetBoolean(interp, tagPtr->elideString,
+ &tagPtr->elide) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Indices are potentially obsolete after changing -elide,
+ * especially those computed with "display" or "any"
+ * submodifier, therefore increase the epoch.
+ */
+
+ textPtr->sharedTextPtr->stateEpoch++;
+ }
+
+ /*
+ * If the "sel" tag was changed, be sure to mirror information
+ * from the tag back into the text widget record. NOTE: we don't
+ * have to free up information in the widget record before
+ * overwriting it, because it was mirrored in the tag and hence
+ * freed when the tag field was overwritten.
+ */
+
+ if (tagPtr == textPtr->selTagPtr) {
+ if (tagPtr->selBorder == NULL) {
+ textPtr->selBorder = tagPtr->border;
+ } else {
+ textPtr->selBorder = tagPtr->selBorder;
+ }
+ textPtr->selBorderWidth = tagPtr->borderWidth;
+ textPtr->selBorderWidthPtr = tagPtr->borderWidthPtr;
+ if (tagPtr->selFgColor == NULL) {
+ textPtr->selFgColorPtr = tagPtr->fgColor;
+ } else {
+ textPtr->selFgColorPtr = tagPtr->selFgColor;
+ }
+ }
+
+ tagPtr->affectsDisplay = 0;
+ tagPtr->affectsDisplayGeometry = 0;
+ if ((tagPtr->elideString != NULL)
+ || (tagPtr->tkfont != NULL)
+ || (tagPtr->justifyString != NULL)
+ || (tagPtr->lMargin1String != NULL)
+ || (tagPtr->lMargin2String != NULL)
+ || (tagPtr->offsetString != NULL)
+ || (tagPtr->rMarginString != NULL)
+ || (tagPtr->spacing1String != NULL)
+ || (tagPtr->spacing2String != NULL)
+ || (tagPtr->spacing3String != NULL)
+ || (tagPtr->tabStringPtr != NULL)
+ || (tagPtr->tabStyle != TK_TEXT_TABSTYLE_NONE)
+ || (tagPtr->wrapMode != TEXT_WRAPMODE_NULL)) {
+ tagPtr->affectsDisplay = 1;
+ tagPtr->affectsDisplayGeometry = 1;
+ }
+ if ((tagPtr->border != NULL)
+ || (tagPtr->selBorder != NULL)
+ || (tagPtr->reliefString != NULL)
+ || (tagPtr->bgStipple != None)
+ || (tagPtr->fgColor != NULL)
+ || (tagPtr->selFgColor != NULL)
+ || (tagPtr->fgStipple != None)
+ || (tagPtr->overstrikeString != NULL)
+ || (tagPtr->overstrikeColor != NULL)
+ || (tagPtr->underlineString != NULL)
+ || (tagPtr->underlineColor != NULL)
+ || (tagPtr->lMarginColor != NULL)
+ || (tagPtr->rMarginColor != NULL)) {
+ tagPtr->affectsDisplay = 1;
+ }
+ if (!newTag) {
+ /*
+ * This line is not necessary if this is a new tag, since it
+ * can't possibly have been applied to anything yet.
+ */
+
+ /*
+ * VMD: If this is the 'sel' tag, then we don't need to call
+ * this for all peers, unless we actually want to synchronize
+ * sel-style changes across the peers.
+ */
+
+ TkTextRedrawTag(textPtr->sharedTextPtr, NULL,
+ NULL, NULL, tagPtr, 1);
+ }
+ return result;
+ }
+ break;
+ }
+ case TAG_DELETE: {
+ Tcl_HashEntry *hPtr;
+
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "tagName ?tagName ...?");
+ return TCL_ERROR;
+ }
+ for (i = 3; i < objc; i++) {
+ hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->tagTable,
+ Tcl_GetString(objv[i]));
+ if (hPtr == NULL) {
+ /*
+ * Either this tag doesn't exist or it's the 'sel' tag (which
+ * is not in the hash table). Either way we don't want to
+ * delete it.
+ */
+
+ continue;
+ }
+ tagPtr = Tcl_GetHashValue(hPtr);
+ if (tagPtr == textPtr->selTagPtr) {
+ continue;
+ }
+ if (tagPtr->affectsDisplay) {
+ TkTextRedrawTag(textPtr->sharedTextPtr, NULL,
+ NULL, NULL, tagPtr, 1);
+ }
+ TkTextDeleteTag(textPtr, tagPtr);
+ Tcl_DeleteHashEntry(hPtr);
+ }
+ break;
+ }
+ case TAG_LOWER: {
+ TkTextTag *tagPtr2;
+ int prio;
+
+ if ((objc != 4) && (objc != 5)) {
+ Tcl_WrongNumArgs(interp, 3, objv, "tagName ?belowThis?");
+ return TCL_ERROR;
+ }
+ tagPtr = FindTag(interp, textPtr, objv[3]);
+ if (tagPtr == NULL) {
+ return TCL_ERROR;
+ }
+ if (objc == 5) {
+ tagPtr2 = FindTag(interp, textPtr, objv[4]);
+ if (tagPtr2 == NULL) {
+ return TCL_ERROR;
+ }
+ if (tagPtr->priority < tagPtr2->priority) {
+ prio = tagPtr2->priority - 1;
+ } else {
+ prio = tagPtr2->priority;
+ }
+ } else {
+ prio = 0;
+ }
+ ChangeTagPriority(textPtr, tagPtr, prio);
+
+ /*
+ * If this is the 'sel' tag, then we don't actually need to call this
+ * for all peers.
+ */
+
+ TkTextRedrawTag(textPtr->sharedTextPtr, NULL, NULL, NULL, tagPtr, 1);
+ break;
+ }
+ case TAG_NAMES: {
+ TkTextTag **arrayPtr;
+ int arraySize;
+ Tcl_Obj *listObj;
+
+ if ((objc != 3) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 3, objv, "?index?");
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ Tcl_HashSearch search;
+ Tcl_HashEntry *hPtr;
+
+ arrayPtr = ckalloc(textPtr->sharedTextPtr->numTags
+ * sizeof(TkTextTag *));
+ for (i=0, hPtr = Tcl_FirstHashEntry(
+ &textPtr->sharedTextPtr->tagTable, &search);
+ hPtr != NULL; i++, hPtr = Tcl_NextHashEntry(&search)) {
+ arrayPtr[i] = Tcl_GetHashValue(hPtr);
+ }
+
+ /*
+ * The 'sel' tag is not in the hash table.
+ */
+
+ arrayPtr[i] = textPtr->selTagPtr;
+ arraySize = ++i;
+ } else {
+ if (TkTextGetObjIndex(interp, textPtr, objv[3],
+ &index1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ arrayPtr = TkBTreeGetTags(&index1, textPtr, &arraySize);
+ if (arrayPtr == NULL) {
+ return TCL_OK;
+ }
+ }
+
+ SortTags(arraySize, arrayPtr);
+ listObj = Tcl_NewListObj(0, NULL);
+
+ for (i = 0; i < arraySize; i++) {
+ tagPtr = arrayPtr[i];
+ Tcl_ListObjAppendElement(interp, listObj,
+ Tcl_NewStringObj(tagPtr->name,-1));
+ }
+ Tcl_SetObjResult(interp, listObj);
+ ckfree(arrayPtr);
+ break;
+ }
+ case TAG_NEXTRANGE: {
+ TkTextIndex last;
+ TkTextSearch tSearch;
+ char position[TK_POS_CHARS];
+ Tcl_Obj *resultObj;
+
+ if ((objc != 5) && (objc != 6)) {
+ Tcl_WrongNumArgs(interp, 3, objv, "tagName index1 ?index2?");
+ return TCL_ERROR;
+ }
+ tagPtr = FindTag(NULL, textPtr, objv[3]);
+ if (tagPtr == NULL) {
+ return TCL_OK;
+ }
+ if (TkTextGetObjIndex(interp, textPtr, objv[4], &index1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,
+ TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr),
+ 0, &last);
+ if (objc == 5) {
+ index2 = last;
+ } else if (TkTextGetObjIndex(interp, textPtr, objv[5],
+ &index2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * The search below is a bit tricky. Rather than use the B-tree
+ * facilities to stop the search at index2, let it search up until the
+ * end of the file but check for a position past index2 ourselves.
+ * The reason for doing it this way is that we only care whether the
+ * *start* of the range is before index2; once we find the start, we
+ * don't want TkBTreeNextTag to abort the search because the end of
+ * the range is after index2.
+ */
+
+ TkBTreeStartSearch(&index1, &last, tagPtr, &tSearch);
+ if (TkBTreeCharTagged(&index1, tagPtr)) {
+ TkTextSegment *segPtr;
+ int offset;
+
+ /*
+ * The first character is tagged. See if there is an on-toggle
+ * just before the character. If not, then skip to the end of this
+ * tagged range.
+ */
+
+ for (segPtr = index1.linePtr->segPtr, offset = index1.byteIndex;
+ offset >= 0;
+ offset -= segPtr->size, segPtr = segPtr->nextPtr) {
+ if ((offset == 0) && (segPtr->typePtr == &tkTextToggleOnType)
+ && (segPtr->body.toggle.tagPtr == tagPtr)) {
+ goto gotStart;
+ }
+ }
+ if (!TkBTreeNextTag(&tSearch)) {
+ return TCL_OK;
+ }
+ }
+
+ /*
+ * Find the start of the tagged range.
+ */
+
+ if (!TkBTreeNextTag(&tSearch)) {
+ return TCL_OK;
+ }
+
+ gotStart:
+ if (TkTextIndexCmp(&tSearch.curIndex, &index2) >= 0) {
+ return TCL_OK;
+ }
+ resultObj = Tcl_NewObj();
+ TkTextPrintIndex(textPtr, &tSearch.curIndex, position);
+ Tcl_ListObjAppendElement(NULL, resultObj,
+ Tcl_NewStringObj(position, -1));
+ TkBTreeNextTag(&tSearch);
+ TkTextPrintIndex(textPtr, &tSearch.curIndex, position);
+ Tcl_ListObjAppendElement(NULL, resultObj,
+ Tcl_NewStringObj(position, -1));
+ Tcl_SetObjResult(interp, resultObj);
+ break;
+ }
+ case TAG_PREVRANGE: {
+ TkTextIndex last;
+ TkTextSearch tSearch;
+ char position1[TK_POS_CHARS];
+ char position2[TK_POS_CHARS];
+ Tcl_Obj *resultObj;
+
+ if ((objc != 5) && (objc != 6)) {
+ Tcl_WrongNumArgs(interp, 3, objv, "tagName index1 ?index2?");
+ return TCL_ERROR;
+ }
+ tagPtr = FindTag(NULL, textPtr, objv[3]);
+ if (tagPtr == NULL) {
+ return TCL_OK;
+ }
+ if (TkTextGetObjIndex(interp, textPtr, objv[4], &index1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (objc == 5) {
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, 0, 0,
+ &index2);
+ } else if (TkTextGetObjIndex(interp, textPtr, objv[5],
+ &index2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * The search below is a bit weird. The previous toggle can be either
+ * an on or off toggle. If it is an on toggle, then we need to turn
+ * around and search forward for the end toggle. Otherwise we keep
+ * searching backwards.
+ */
+
+ TkBTreeStartSearchBack(&index1, &index2, tagPtr, &tSearch);
+
+ if (!TkBTreePrevTag(&tSearch)) {
+ /*
+ * Special case, there may be a tag off toggle at index1, and a
+ * tag on toggle before the start of a partial peer widget. In
+ * this case we missed it.
+ */
+
+ if (textPtr->start != NULL && (textPtr->start == index2.linePtr)
+ && (index2.byteIndex == 0)
+ && TkBTreeCharTagged(&index2, tagPtr)
+ && (TkTextIndexCmp(&index2, &index1) < 0)) {
+ /*
+ * The first character is tagged, so just add the range from
+ * the first char to the start of the range.
+ */
+
+ TkTextPrintIndex(textPtr, &index2, position1);
+ TkTextPrintIndex(textPtr, &index1, position2);
+ goto gotPrevIndexPair;
+ }
+ return TCL_OK;
+ }
+
+ if (tSearch.segPtr->typePtr == &tkTextToggleOnType) {
+ TkTextPrintIndex(textPtr, &tSearch.curIndex, position1);
+ if (textPtr->start != NULL) {
+ /*
+ * Make sure the first index is not before the first allowed
+ * text index in this widget.
+ */
+
+ TkTextIndex firstIndex;
+
+ firstIndex.linePtr = textPtr->start;
+ firstIndex.byteIndex = 0;
+ firstIndex.textPtr = NULL;
+ if (TkTextIndexCmp(&tSearch.curIndex, &firstIndex) < 0) {
+ if (TkTextIndexCmp(&firstIndex, &index1) >= 0) {
+ /*
+ * But now the new first index is actually too far
+ * along in the text, so nothing is returned.
+ */
+
+ return TCL_OK;
+ }
+ TkTextPrintIndex(textPtr, &firstIndex, position1);
+ }
+ }
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,
+ TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr),
+ 0, &last);
+ TkBTreeStartSearch(&tSearch.curIndex, &last, tagPtr, &tSearch);
+ TkBTreeNextTag(&tSearch);
+ TkTextPrintIndex(textPtr, &tSearch.curIndex, position2);
+ } else {
+ TkTextPrintIndex(textPtr, &tSearch.curIndex, position2);
+ TkBTreePrevTag(&tSearch);
+ TkTextPrintIndex(textPtr, &tSearch.curIndex, position1);
+ if (TkTextIndexCmp(&tSearch.curIndex, &index2) < 0) {
+ if (textPtr->start != NULL && index2.linePtr == textPtr->start
+ && index2.byteIndex == 0) {
+ /* It's ok */
+ TkTextPrintIndex(textPtr, &index2, position1);
+ } else {
+ return TCL_OK;
+ }
+ }
+ }
+
+ gotPrevIndexPair:
+ resultObj = Tcl_NewObj();
+ Tcl_ListObjAppendElement(NULL, resultObj,
+ Tcl_NewStringObj(position1, -1));
+ Tcl_ListObjAppendElement(NULL, resultObj,
+ Tcl_NewStringObj(position2, -1));
+ Tcl_SetObjResult(interp, resultObj);
+ break;
+ }
+ case TAG_RAISE: {
+ TkTextTag *tagPtr2;
+ int prio;
+
+ if ((objc != 4) && (objc != 5)) {
+ Tcl_WrongNumArgs(interp, 3, objv, "tagName ?aboveThis?");
+ return TCL_ERROR;
+ }
+ tagPtr = FindTag(interp, textPtr, objv[3]);
+ if (tagPtr == NULL) {
+ return TCL_ERROR;
+ }
+ if (objc == 5) {
+ tagPtr2 = FindTag(interp, textPtr, objv[4]);
+ if (tagPtr2 == NULL) {
+ return TCL_ERROR;
+ }
+ if (tagPtr->priority <= tagPtr2->priority) {
+ prio = tagPtr2->priority;
+ } else {
+ prio = tagPtr2->priority + 1;
+ }
+ } else {
+ prio = textPtr->sharedTextPtr->numTags-1;
+ }
+ ChangeTagPriority(textPtr, tagPtr, prio);
+
+ /*
+ * If this is the 'sel' tag, then we don't actually need to call this
+ * for all peers.
+ */
+
+ TkTextRedrawTag(textPtr->sharedTextPtr, NULL, NULL, NULL, tagPtr, 1);
+ break;
+ }
+ case TAG_RANGES: {
+ TkTextIndex first, last;
+ TkTextSearch tSearch;
+ Tcl_Obj *listObj = Tcl_NewListObj(0, NULL);
+ int count = 0;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "tagName");
+ return TCL_ERROR;
+ }
+ tagPtr = FindTag(NULL, textPtr, objv[3]);
+ if (tagPtr == NULL) {
+ return TCL_OK;
+ }
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, 0, 0,
+ &first);
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,
+ TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr),
+ 0, &last);
+ TkBTreeStartSearch(&first, &last, tagPtr, &tSearch);
+ if (TkBTreeCharTagged(&first, tagPtr)) {
+ Tcl_ListObjAppendElement(NULL, listObj,
+ TkTextNewIndexObj(textPtr, &first));
+ count++;
+ }
+ while (TkBTreeNextTag(&tSearch)) {
+ Tcl_ListObjAppendElement(NULL, listObj,
+ TkTextNewIndexObj(textPtr, &tSearch.curIndex));
+ count++;
+ }
+ if (count % 2 == 1) {
+ /*
+ * If a text widget uses '-end', it won't necessarily run to the
+ * end of the B-tree, and therefore the tag range might not be
+ * closed. In this case we add the end of the range.
+ */
+
+ Tcl_ListObjAppendElement(NULL, listObj,
+ TkTextNewIndexObj(textPtr, &last));
+ }
+ Tcl_SetObjResult(interp, listObj);
+ break;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkTextCreateTag --
+ *
+ * Find the record describing a tag within a given text widget, creating
+ * a new record if one doesn't already exist.
+ *
+ * Results:
+ * The return value is a pointer to the TkTextTag record for tagName.
+ *
+ * Side effects:
+ * A new tag record is created if there isn't one already defined for
+ * tagName.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkTextTag *
+TkTextCreateTag(
+ TkText *textPtr, /* Widget in which tag is being used. */
+ const char *tagName, /* Name of desired tag. */
+ int *newTag) /* If non-NULL, then return 1 if new, or 0 if
+ * already exists. */
+{
+ register TkTextTag *tagPtr;
+ Tcl_HashEntry *hPtr = NULL;
+ int isNew;
+ const char *name;
+
+ if (!strcmp(tagName, "sel")) {
+ if (textPtr->selTagPtr != NULL) {
+ if (newTag != NULL) {
+ *newTag = 0;
+ }
+ return textPtr->selTagPtr;
+ }
+ if (newTag != NULL) {
+ *newTag = 1;
+ }
+ name = "sel";
+ } else {
+ hPtr = Tcl_CreateHashEntry(&textPtr->sharedTextPtr->tagTable,
+ tagName, &isNew);
+ if (newTag != NULL) {
+ *newTag = isNew;
+ }
+ if (!isNew) {
+ return Tcl_GetHashValue(hPtr);
+ }
+ name = Tcl_GetHashKey(&textPtr->sharedTextPtr->tagTable, hPtr);
+ }
+
+ /*
+ * No existing entry. Create a new one, initialize it, and add a pointer
+ * to it to the hash table entry.
+ */
+
+ tagPtr = ckalloc(sizeof(TkTextTag));
+ tagPtr->name = name;
+ tagPtr->textPtr = NULL;
+ tagPtr->toggleCount = 0;
+ tagPtr->tagRootPtr = NULL;
+ tagPtr->priority = textPtr->sharedTextPtr->numTags;
+ tagPtr->border = NULL;
+ tagPtr->borderWidth = 0;
+ tagPtr->borderWidthPtr = NULL;
+ tagPtr->reliefString = NULL;
+ tagPtr->relief = TK_RELIEF_FLAT;
+ tagPtr->bgStipple = None;
+ tagPtr->fgColor = NULL;
+ tagPtr->tkfont = NULL;
+ tagPtr->fgStipple = None;
+ tagPtr->justifyString = NULL;
+ tagPtr->justify = TK_JUSTIFY_LEFT;
+ tagPtr->lMargin1String = NULL;
+ tagPtr->lMargin1 = 0;
+ tagPtr->lMargin2String = NULL;
+ tagPtr->lMargin2 = 0;
+ tagPtr->lMarginColor = NULL;
+ tagPtr->offsetString = NULL;
+ tagPtr->offset = 0;
+ tagPtr->overstrikeString = NULL;
+ tagPtr->overstrike = 0;
+ tagPtr->overstrikeColor = NULL;
+ tagPtr->rMarginString = NULL;
+ tagPtr->rMargin = 0;
+ tagPtr->rMarginColor = NULL;
+ tagPtr->selBorder = NULL;
+ tagPtr->selFgColor = NULL;
+ tagPtr->spacing1String = NULL;
+ tagPtr->spacing1 = 0;
+ tagPtr->spacing2String = NULL;
+ tagPtr->spacing2 = 0;
+ tagPtr->spacing3String = NULL;
+ tagPtr->spacing3 = 0;
+ tagPtr->tabStringPtr = NULL;
+ tagPtr->tabArrayPtr = NULL;
+ tagPtr->tabStyle = TK_TEXT_TABSTYLE_NONE;
+ tagPtr->underlineString = NULL;
+ tagPtr->underline = 0;
+ tagPtr->underlineColor = NULL;
+ tagPtr->elideString = NULL;
+ tagPtr->elide = 0;
+ tagPtr->wrapMode = TEXT_WRAPMODE_NULL;
+ tagPtr->affectsDisplay = 0;
+ tagPtr->affectsDisplayGeometry = 0;
+ textPtr->sharedTextPtr->numTags++;
+ if (!strcmp(tagName, "sel")) {
+ tagPtr->textPtr = textPtr;
+ textPtr->refCount++;
+ } else {
+ CLANG_ASSERT(hPtr);
+ Tcl_SetHashValue(hPtr, tagPtr);
+ }
+ tagPtr->optionTable =
+ Tk_CreateOptionTable(textPtr->interp, tagOptionSpecs);
+ return tagPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FindTag --
+ *
+ * See if tag is defined for a given widget.
+ *
+ * Results:
+ * If tagName is defined in textPtr, a pointer to its TkTextTag structure
+ * is returned. Otherwise NULL is returned and an error message is
+ * recorded in the interp's result unless interp is NULL.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static TkTextTag *
+FindTag(
+ Tcl_Interp *interp, /* Interpreter to use for error message; if
+ * NULL, then don't record an error
+ * message. */
+ TkText *textPtr, /* Widget in which tag is being used. */
+ Tcl_Obj *tagName) /* Name of desired tag. */
+{
+ Tcl_HashEntry *hPtr;
+ int len;
+ const char *str;
+
+ str = Tcl_GetStringFromObj(tagName, &len);
+ if (len == 3 && !strcmp(str, "sel")) {
+ return textPtr->selTagPtr;
+ }
+ hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->tagTable,
+ Tcl_GetString(tagName));
+ if (hPtr != NULL) {
+ return Tcl_GetHashValue(hPtr);
+ }
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "tag \"%s\" isn't defined in text widget",
+ Tcl_GetString(tagName)));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "TEXT_TAG",
+ Tcl_GetString(tagName), NULL);
+ }
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkTextDeleteTag --
+ *
+ * This function is called to carry out most actions associated with the
+ * 'tag delete' sub-command. It will remove all evidence of the tag from
+ * the B-tree, and then call TkTextFreeTag to clean up the tag structure
+ * itself.
+ *
+ * The only actions this doesn't carry out it to check if the deletion of
+ * the tag requires something to be re-displayed, and to remove the tag
+ * from the tagTable (hash table) if that is necessary (i.e. if it's not
+ * the 'sel' tag). It is expected that the caller carry out both of these
+ * actions.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory and other resources are freed, the B-tree is manipulated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkTextDeleteTag(
+ TkText *textPtr, /* Info about overall widget. */
+ register TkTextTag *tagPtr) /* Tag being deleted. */
+{
+ TkTextIndex first, last;
+
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, 0, 0, &first);
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,
+ TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr), 0, &last),
+ TkBTreeTag(&first, &last, tagPtr, 0);
+
+ if (tagPtr == textPtr->selTagPtr) {
+ /*
+ * Send an event that the selection changed. This is equivalent to:
+ * event generate $textWidget <<Selection>>
+ */
+
+ TkTextSelectionEvent(textPtr);
+ } else {
+ /*
+ * Since all peer widgets have an independent "sel" tag, we
+ * don't want removal of one sel tag to remove bindings which
+ * are still valid in other peer widgets.
+ */
+
+ if (textPtr->sharedTextPtr->bindingTable != NULL) {
+ Tk_DeleteAllBindings(textPtr->sharedTextPtr->bindingTable,
+ (ClientData) tagPtr->name);
+ }
+ }
+
+ /*
+ * Update the tag priorities to reflect the deletion of this tag.
+ */
+
+ ChangeTagPriority(textPtr, tagPtr, textPtr->sharedTextPtr->numTags-1);
+ textPtr->sharedTextPtr->numTags -= 1;
+ TkTextFreeTag(textPtr, tagPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkTextFreeTag --
+ *
+ * This function is called when a tag is deleted to free up the memory
+ * and other resources associated with the tag.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory and other resources are freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkTextFreeTag(
+ TkText *textPtr, /* Info about overall widget. */
+ register TkTextTag *tagPtr) /* Tag being deleted. */
+{
+ int i;
+
+ /*
+ * Let Tk do most of the hard work for us.
+ */
+
+ Tk_FreeConfigOptions((char *) tagPtr, tagPtr->optionTable,
+ textPtr->tkwin);
+
+ /*
+ * This associated information is managed by us.
+ */
+
+ if (tagPtr->tabArrayPtr != NULL) {
+ ckfree(tagPtr->tabArrayPtr);
+ }
+
+ /*
+ * Make sure this tag isn't referenced from the 'current' tag array.
+ */
+
+ for (i = 0; i < textPtr->numCurTags; i++) {
+ if (textPtr->curTagArrayPtr[i] == tagPtr) {
+ for (; i < textPtr->numCurTags-1; i++) {
+ textPtr->curTagArrayPtr[i] = textPtr->curTagArrayPtr[i+1];
+ }
+ textPtr->curTagArrayPtr[textPtr->numCurTags-1] = NULL;
+ textPtr->numCurTags--;
+ break;
+ }
+ }
+
+ /*
+ * If this tag is widget-specific (peer widgets) then clean up the
+ * refCount it holds.
+ */
+
+ if (tagPtr->textPtr != NULL) {
+ if (textPtr != tagPtr->textPtr) {
+ Tcl_Panic("Tag being deleted from wrong widget");
+ }
+ if (textPtr->refCount-- <= 1) {
+ ckfree(textPtr);
+ }
+ tagPtr->textPtr = NULL;
+ }
+
+ /*
+ * Finally free the tag's memory.
+ */
+
+ ckfree(tagPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SortTags --
+ *
+ * This function sorts an array of tag pointers in increasing order of
+ * priority, optimizing for the common case where the array is small.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+SortTags(
+ int numTags, /* Number of tag pointers at *tagArrayPtr. */
+ TkTextTag **tagArrayPtr) /* Pointer to array of pointers. */
+{
+ int i, j, prio;
+ register TkTextTag **tagPtrPtr;
+ TkTextTag **maxPtrPtr, *tmp;
+
+ if (numTags < 2) {
+ return;
+ }
+ if (numTags < 20) {
+ for (i = numTags-1; i > 0; i--, tagArrayPtr++) {
+ maxPtrPtr = tagPtrPtr = tagArrayPtr;
+ prio = tagPtrPtr[0]->priority;
+ for (j = i, tagPtrPtr++; j > 0; j--, tagPtrPtr++) {
+ if (tagPtrPtr[0]->priority < prio) {
+ prio = tagPtrPtr[0]->priority;
+ maxPtrPtr = tagPtrPtr;
+ }
+ }
+ tmp = *maxPtrPtr;
+ *maxPtrPtr = *tagArrayPtr;
+ *tagArrayPtr = tmp;
+ }
+ } else {
+ qsort(tagArrayPtr,(unsigned)numTags,sizeof(TkTextTag *),TagSortProc);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TagSortProc --
+ *
+ * This function is called by qsort() when sorting an array of tags in
+ * priority order.
+ *
+ * Results:
+ * The return value is -1 if the first argument should be before the
+ * second element (i.e. it has lower priority), 0 if it's equivalent
+ * (this should never happen!), and 1 if it should be after the second
+ * element.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TagSortProc(
+ const void *first,
+ const void *second) /* Elements to be compared. */
+{
+ TkTextTag *tagPtr1, *tagPtr2;
+
+ tagPtr1 = * (TkTextTag **) first;
+ tagPtr2 = * (TkTextTag **) second;
+ return tagPtr1->priority - tagPtr2->priority;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ChangeTagPriority --
+ *
+ * This function changes the priority of a tag by modifying its priority
+ * and the priorities of other tags that are affected by the change.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Priorities may be changed for some or all of the tags in textPtr. The
+ * tags will be arranged so that there is exactly one tag at each
+ * priority level between 0 and textPtr->sharedTextPtr->numTags-1, with
+ * tagPtr at priority "prio".
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ChangeTagPriority(
+ TkText *textPtr, /* Information about text widget. */
+ TkTextTag *tagPtr, /* Tag whose priority is to be changed. */
+ int prio) /* New priority for tag. */
+{
+ int low, high, delta;
+ register TkTextTag *tagPtr2;
+ Tcl_HashEntry *hPtr;
+ Tcl_HashSearch search;
+
+ if (prio < 0) {
+ prio = 0;
+ }
+ if (prio >= textPtr->sharedTextPtr->numTags) {
+ prio = textPtr->sharedTextPtr->numTags-1;
+ }
+ if (prio == tagPtr->priority) {
+ return;
+ }
+ if (prio < tagPtr->priority) {
+ low = prio;
+ high = tagPtr->priority-1;
+ delta = 1;
+ } else {
+ low = tagPtr->priority+1;
+ high = prio;
+ delta = -1;
+ }
+
+ /*
+ * Adjust first the 'sel' tag, then all others from the hash table
+ */
+
+ if ((textPtr->selTagPtr->priority >= low)
+ && (textPtr->selTagPtr->priority <= high)) {
+ textPtr->selTagPtr->priority += delta;
+ }
+ for (hPtr = Tcl_FirstHashEntry(&textPtr->sharedTextPtr->tagTable, &search);
+ hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
+ tagPtr2 = Tcl_GetHashValue(hPtr);
+ if ((tagPtr2->priority >= low) && (tagPtr2->priority <= high)) {
+ tagPtr2->priority += delta;
+ }
+ }
+ tagPtr->priority = prio;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkTextBindProc --
+ *
+ * This function is invoked by the Tk dispatcher to handle events
+ * associated with bindings on items.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Depends on the command invoked as part of the binding (if there was
+ * any).
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkTextBindProc(
+ ClientData clientData, /* Pointer to canvas structure. */
+ XEvent *eventPtr) /* Pointer to X event that just happened. */
+{
+ TkText *textPtr = clientData;
+ int repick = 0;
+
+# define AnyButtonMask \
+ (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask)
+
+ textPtr->refCount++;
+
+ /*
+ * This code simulates grabs for mouse buttons by keeping track of whether
+ * a button is pressed and refusing to pick a new current character while
+ * a button is pressed.
+ */
+
+ if (eventPtr->type == ButtonPress) {
+ textPtr->flags |= BUTTON_DOWN;
+ } else if (eventPtr->type == ButtonRelease) {
+ int mask;
+
+ switch (eventPtr->xbutton.button) {
+ case Button1:
+ mask = Button1Mask;
+ break;
+ case Button2:
+ mask = Button2Mask;
+ break;
+ case Button3:
+ mask = Button3Mask;
+ break;
+ case Button4:
+ mask = Button4Mask;
+ break;
+ case Button5:
+ mask = Button5Mask;
+ break;
+ default:
+ mask = 0;
+ break;
+ }
+ if ((eventPtr->xbutton.state & AnyButtonMask) == (unsigned) mask) {
+ textPtr->flags &= ~BUTTON_DOWN;
+ repick = 1;
+ }
+ } else if ((eventPtr->type == EnterNotify)
+ || (eventPtr->type == LeaveNotify)) {
+ if (eventPtr->xcrossing.state & AnyButtonMask) {
+ textPtr->flags |= BUTTON_DOWN;
+ } else {
+ textPtr->flags &= ~BUTTON_DOWN;
+ }
+ TkTextPickCurrent(textPtr, eventPtr);
+ goto done;
+ } else if (eventPtr->type == MotionNotify) {
+ if (eventPtr->xmotion.state & AnyButtonMask) {
+ textPtr->flags |= BUTTON_DOWN;
+ } else {
+ textPtr->flags &= ~BUTTON_DOWN;
+ }
+ TkTextPickCurrent(textPtr, eventPtr);
+ }
+ if ((textPtr->numCurTags > 0)
+ && (textPtr->sharedTextPtr->bindingTable != NULL)
+ && (textPtr->tkwin != NULL) && !(textPtr->flags & DESTROYED)) {
+ TagBindEvent(textPtr, eventPtr, textPtr->numCurTags,
+ textPtr->curTagArrayPtr);
+ }
+ if (repick) {
+ unsigned int oldState;
+
+ oldState = eventPtr->xbutton.state;
+ eventPtr->xbutton.state &= ~(Button1Mask|Button2Mask
+ |Button3Mask|Button4Mask|Button5Mask);
+ if (!(textPtr->flags & DESTROYED)) {
+ TkTextPickCurrent(textPtr, eventPtr);
+ }
+ eventPtr->xbutton.state = oldState;
+ }
+
+ done:
+ if (textPtr->refCount-- <= 1) {
+ ckfree(textPtr);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkTextPickCurrent --
+ *
+ * Find the character containing the coordinates in an event and place
+ * the "current" mark on that character. If the "current" mark has moved
+ * then generate a fake leave event on the old current character and a
+ * fake enter event on the new current character.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The current mark for textPtr may change. If it does, then the commands
+ * associated with character entry and leave could do just about
+ * anything. For example, the text widget might be deleted. It is up to
+ * the caller to protect itself by incrementing the refCount of the text
+ * widget.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkTextPickCurrent(
+ register TkText *textPtr, /* Text widget in which to select current
+ * character. */
+ XEvent *eventPtr) /* Event describing location of mouse cursor.
+ * Must be EnterWindow, LeaveWindow,
+ * ButtonRelease, or MotionNotify. */
+{
+ TkTextIndex index;
+ TkTextTag **oldArrayPtr, **newArrayPtr;
+ TkTextTag **copyArrayPtr = NULL;
+ /* Initialization needed to prevent compiler
+ * warning. */
+ int numOldTags, numNewTags, i, j, size, nearby;
+ XEvent event;
+
+ /*
+ * If a button is down, then don't do anything at all; we'll be called
+ * again when all buttons are up, and we can repick then. This implements
+ * a form of mouse grabbing.
+ */
+
+ if (textPtr->flags & BUTTON_DOWN) {
+ if (((eventPtr->type == EnterNotify)
+ || (eventPtr->type == LeaveNotify))
+ && ((eventPtr->xcrossing.mode == NotifyGrab)
+ || (eventPtr->xcrossing.mode == NotifyUngrab))) {
+ /*
+ * Special case: the window is being entered or left because of a
+ * grab or ungrab. In this case, repick after all. Furthermore,
+ * clear BUTTON_DOWN to release the simulated grab.
+ */
+
+ textPtr->flags &= ~BUTTON_DOWN;
+ } else {
+ return;
+ }
+ }
+
+ /*
+ * Save information about this event in the widget in case we have to
+ * synthesize more enter and leave events later (e.g. because a character
+ * was deleted, causing a new character to be underneath the mouse
+ * cursor). Also translate MotionNotify events into EnterNotify events,
+ * since that's what gets reported to event handlers when the current
+ * character changes.
+ */
+
+ if (eventPtr != &textPtr->pickEvent) {
+ if ((eventPtr->type == MotionNotify)
+ || (eventPtr->type == ButtonRelease)) {
+ textPtr->pickEvent.xcrossing.type = EnterNotify;
+ textPtr->pickEvent.xcrossing.serial = eventPtr->xmotion.serial;
+ textPtr->pickEvent.xcrossing.send_event
+ = eventPtr->xmotion.send_event;
+ textPtr->pickEvent.xcrossing.display = eventPtr->xmotion.display;
+ textPtr->pickEvent.xcrossing.window = eventPtr->xmotion.window;
+ textPtr->pickEvent.xcrossing.root = eventPtr->xmotion.root;
+ textPtr->pickEvent.xcrossing.subwindow = None;
+ textPtr->pickEvent.xcrossing.time = eventPtr->xmotion.time;
+ textPtr->pickEvent.xcrossing.x = eventPtr->xmotion.x;
+ textPtr->pickEvent.xcrossing.y = eventPtr->xmotion.y;
+ textPtr->pickEvent.xcrossing.x_root = eventPtr->xmotion.x_root;
+ textPtr->pickEvent.xcrossing.y_root = eventPtr->xmotion.y_root;
+ textPtr->pickEvent.xcrossing.mode = NotifyNormal;
+ textPtr->pickEvent.xcrossing.detail = NotifyNonlinear;
+ textPtr->pickEvent.xcrossing.same_screen
+ = eventPtr->xmotion.same_screen;
+ textPtr->pickEvent.xcrossing.focus = False;
+ textPtr->pickEvent.xcrossing.state = eventPtr->xmotion.state;
+ } else {
+ textPtr->pickEvent = *eventPtr;
+ }
+ }
+
+ /*
+ * Find the new current character, then find and sort all of the tags
+ * associated with it.
+ */
+
+ if (textPtr->pickEvent.type != LeaveNotify) {
+ TkTextPixelIndex(textPtr, textPtr->pickEvent.xcrossing.x,
+ textPtr->pickEvent.xcrossing.y, &index, &nearby);
+ if (nearby) {
+ newArrayPtr = NULL;
+ numNewTags = 0;
+ } else {
+ newArrayPtr = TkBTreeGetTags(&index, textPtr, &numNewTags);
+ SortTags(numNewTags, newArrayPtr);
+ }
+ } else {
+ newArrayPtr = NULL;
+ numNewTags = 0;
+ }
+
+ /*
+ * Resort the tags associated with the previous marked character (the
+ * priorities might have changed), then make a copy of the new tags, and
+ * compare the old tags to the copy, nullifying any tags that are present
+ * in both groups (i.e. the tags that haven't changed).
+ */
+
+ SortTags(textPtr->numCurTags, textPtr->curTagArrayPtr);
+ if (numNewTags > 0) {
+ size = numNewTags * sizeof(TkTextTag *);
+ copyArrayPtr = ckalloc(size);
+ memcpy(copyArrayPtr, newArrayPtr, (size_t) size);
+ for (i = 0; i < textPtr->numCurTags; i++) {
+ for (j = 0; j < numNewTags; j++) {
+ if (textPtr->curTagArrayPtr[i] == copyArrayPtr[j]) {
+ textPtr->curTagArrayPtr[i] = NULL;
+ copyArrayPtr[j] = NULL;
+ break;
+ }
+ }
+ }
+ }
+
+ /*
+ * Invoke the binding system with a LeaveNotify event for all of the tags
+ * that have gone away. We have to be careful here, because it's possible
+ * that the binding could do something (like calling tkwait) that
+ * eventually modifies textPtr->curTagArrayPtr. To avoid problems in
+ * situations like this, update curTagArrayPtr to its new value before
+ * invoking any bindings, and don't use it any more here.
+ */
+
+ numOldTags = textPtr->numCurTags;
+ textPtr->numCurTags = numNewTags;
+ oldArrayPtr = textPtr->curTagArrayPtr;
+ textPtr->curTagArrayPtr = newArrayPtr;
+ if (numOldTags != 0) {
+ if ((textPtr->sharedTextPtr->bindingTable != NULL)
+ && (textPtr->tkwin != NULL)
+ && !(textPtr->flags & DESTROYED)) {
+ event = textPtr->pickEvent;
+ event.type = LeaveNotify;
+
+ /*
+ * Always use a detail of NotifyAncestor. Besides being
+ * consistent, this avoids problems where the binding code will
+ * discard NotifyInferior events.
+ */
+
+ event.xcrossing.detail = NotifyAncestor;
+ TagBindEvent(textPtr, &event, numOldTags, oldArrayPtr);
+ }
+ ckfree(oldArrayPtr);
+ }
+
+ /*
+ * Reset the "current" mark (be careful to recompute its location, since
+ * it might have changed during an event binding). Then invoke the binding
+ * system with an EnterNotify event for all of the tags that have just
+ * appeared.
+ */
+
+ TkTextPixelIndex(textPtr, textPtr->pickEvent.xcrossing.x,
+ textPtr->pickEvent.xcrossing.y, &index, &nearby);
+ TkTextSetMark(textPtr, "current", &index);
+ if (numNewTags != 0) {
+ if ((textPtr->sharedTextPtr->bindingTable != NULL)
+ && (textPtr->tkwin != NULL)
+ && !(textPtr->flags & DESTROYED) && !nearby) {
+ event = textPtr->pickEvent;
+ event.type = EnterNotify;
+ event.xcrossing.detail = NotifyAncestor;
+ TagBindEvent(textPtr, &event, numNewTags, copyArrayPtr);
+ }
+ ckfree(copyArrayPtr);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TagBindEvent --
+ *
+ * Trigger given events for all tags that match the relevant bindings.
+ * To handle the "sel" tag correctly in all peer widgets, we must use the
+ * name of the tags as the binding table element.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Almost anything can be triggered by tag bindings, including deletion
+ * of the text widget.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+TagBindEvent(
+ TkText *textPtr, /* Text widget to fire bindings in. */
+ XEvent *eventPtr, /* What actually happened. */
+ int numTags, /* Number of relevant tags. */
+ TkTextTag **tagArrayPtr) /* Array of relevant tags. */
+{
+# define NUM_BIND_TAGS 10
+ const char *nameArray[NUM_BIND_TAGS];
+ const char **nameArrPtr;
+ int i;
+
+ /*
+ * Try to avoid allocation unless there are lots of tags.
+ */
+
+ if (numTags > NUM_BIND_TAGS) {
+ nameArrPtr = ckalloc(numTags * sizeof(const char *));
+ } else {
+ nameArrPtr = nameArray;
+ }
+
+ /*
+ * We use tag names as keys in the hash table. We do this instead of using
+ * the actual tagPtr objects because we want one "sel" tag binding for all
+ * peer widgets, despite the fact that each has its own tagPtr object.
+ */
+
+ for (i = 0; i < numTags; i++) {
+ TkTextTag *tagPtr = tagArrayPtr[i];
+
+ if (tagPtr != NULL) {
+ nameArrPtr[i] = tagPtr->name;
+ } else {
+ /*
+ * Tag has been deleted elsewhere, and therefore nulled out in
+ * this array. Tk_BindEvent is clever enough to cope with NULLs
+ * being thrown at it.
+ */
+
+ nameArrPtr[i] = NULL;
+ }
+ }
+ Tk_BindEvent(textPtr->sharedTextPtr->bindingTable, eventPtr,
+ textPtr->tkwin, numTags, (ClientData *) nameArrPtr);
+
+ if (numTags > NUM_BIND_TAGS) {
+ ckfree(nameArrPtr);
+ }
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkTextWind.c b/tk8.6/generic/tkTextWind.c
new file mode 100644
index 0000000..c9fc20f
--- /dev/null
+++ b/tk8.6/generic/tkTextWind.c
@@ -0,0 +1,1409 @@
+/*
+ * tkTextWind.c --
+ *
+ * This file contains code that allows arbitrary windows to be nested
+ * inside text widgets. It also implements the "window" widget command
+ * for texts.
+ *
+ * Copyright (c) 1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "tkPort.h"
+#include "tkText.h"
+
+/*
+ * The following structure is the official type record for the embedded window
+ * geometry manager:
+ */
+
+static void EmbWinRequestProc(ClientData clientData,
+ Tk_Window tkwin);
+static void EmbWinLostSlaveProc(ClientData clientData,
+ Tk_Window tkwin);
+
+static const Tk_GeomMgr textGeomType = {
+ "text", /* name */
+ EmbWinRequestProc, /* requestProc */
+ EmbWinLostSlaveProc, /* lostSlaveProc */
+};
+
+/*
+ * Macro that determines the size of an embedded window segment:
+ */
+
+#define EW_SEG_SIZE ((unsigned) (Tk_Offset(TkTextSegment, body) \
+ + sizeof(TkTextEmbWindow)))
+
+/*
+ * Prototypes for functions defined in this file:
+ */
+
+static TkTextSegment * EmbWinCleanupProc(TkTextSegment *segPtr,
+ TkTextLine *linePtr);
+static void EmbWinCheckProc(TkTextSegment *segPtr,
+ TkTextLine *linePtr);
+static void EmbWinBboxProc(TkText *textPtr,
+ TkTextDispChunk *chunkPtr, int index, int y,
+ int lineHeight, int baseline, int *xPtr,int *yPtr,
+ int *widthPtr, int *heightPtr);
+static int EmbWinConfigure(TkText *textPtr, TkTextSegment *ewPtr,
+ int objc, Tcl_Obj *const objv[]);
+static void EmbWinDelayedUnmap(ClientData clientData);
+static int EmbWinDeleteProc(TkTextSegment *segPtr,
+ TkTextLine *linePtr, int treeGone);
+static int EmbWinLayoutProc(TkText *textPtr,
+ TkTextIndex *indexPtr, TkTextSegment *segPtr,
+ int offset, int maxX, int maxChars,int noCharsYet,
+ TkWrapMode wrapMode, TkTextDispChunk *chunkPtr);
+static void EmbWinStructureProc(ClientData clientData,
+ XEvent *eventPtr);
+static void EmbWinUndisplayProc(TkText *textPtr,
+ TkTextDispChunk *chunkPtr);
+static TkTextEmbWindowClient *EmbWinGetClient(const TkText *textPtr,
+ TkTextSegment *ewPtr);
+
+/*
+ * The following structure declares the "embedded window" segment type.
+ */
+
+const Tk_SegType tkTextEmbWindowType = {
+ "window", /* name */
+ 0, /* leftGravity */
+ NULL, /* splitProc */
+ EmbWinDeleteProc, /* deleteProc */
+ EmbWinCleanupProc, /* cleanupProc */
+ NULL, /* lineChangeProc */
+ EmbWinLayoutProc, /* layoutProc */
+ EmbWinCheckProc /* checkProc */
+};
+
+/*
+ * Definitions for alignment values:
+ */
+
+static const char *const alignStrings[] = {
+ "baseline", "bottom", "center", "top", NULL
+};
+
+typedef enum {
+ ALIGN_BASELINE, ALIGN_BOTTOM, ALIGN_CENTER, ALIGN_TOP
+} alignMode;
+
+/*
+ * Information used for parsing window configuration options:
+ */
+
+static const Tk_OptionSpec optionSpecs[] = {
+ {TK_OPTION_STRING_TABLE, "-align", NULL, NULL,
+ "center", -1, Tk_Offset(TkTextEmbWindow, align),
+ 0, alignStrings, 0},
+ {TK_OPTION_STRING, "-create", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextEmbWindow, create), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-padx", NULL, NULL,
+ "0", -1, Tk_Offset(TkTextEmbWindow, padX), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-pady", NULL, NULL,
+ "0", -1, Tk_Offset(TkTextEmbWindow, padY), 0, 0, 0},
+ {TK_OPTION_BOOLEAN, "-stretch", NULL, NULL,
+ "0", -1, Tk_Offset(TkTextEmbWindow, stretch), 0, 0, 0},
+ {TK_OPTION_WINDOW, "-window", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextEmbWindow, tkwin), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}
+};
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkTextWindowCmd --
+ *
+ * This function implements the "window" widget command for text widgets.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result or error.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkTextWindowCmd(
+ register TkText *textPtr, /* Information about text widget. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. Someone else has already
+ * parsed this command enough to know that
+ * objv[1] is "window". */
+{
+ int optionIndex;
+ static const char *const windOptionStrings[] = {
+ "cget", "configure", "create", "names", NULL
+ };
+ enum windOptions {
+ WIND_CGET, WIND_CONFIGURE, WIND_CREATE, WIND_NAMES
+ };
+ register TkTextSegment *ewPtr;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObjStruct(interp, objv[2], windOptionStrings,
+ sizeof(char *), "window option", 0, &optionIndex) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch ((enum windOptions) optionIndex) {
+ case WIND_CGET: {
+ TkTextIndex index;
+ TkTextSegment *ewPtr;
+ Tcl_Obj *objPtr;
+ TkTextEmbWindowClient *client;
+
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index option");
+ return TCL_ERROR;
+ }
+ if (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ ewPtr = TkTextIndexToSeg(&index, NULL);
+ if (ewPtr->typePtr != &tkTextEmbWindowType) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "no embedded window at index \"%s\"",
+ Tcl_GetString(objv[3])));
+ Tcl_SetErrorCode(interp, "TK", "TEXT", "NO_WINDOW", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Copy over client specific value before querying.
+ */
+
+ client = EmbWinGetClient(textPtr, ewPtr);
+ if (client != NULL) {
+ ewPtr->body.ew.tkwin = client->tkwin;
+ } else {
+ ewPtr->body.ew.tkwin = NULL;
+ }
+
+ objPtr = Tk_GetOptionValue(interp, (char *) &ewPtr->body.ew,
+ ewPtr->body.ew.optionTable, objv[4], textPtr->tkwin);
+ if (objPtr == NULL) {
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ return TCL_OK;
+ }
+ case WIND_CONFIGURE: {
+ TkTextIndex index;
+ TkTextSegment *ewPtr;
+
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index ?-option value ...?");
+ return TCL_ERROR;
+ }
+ if (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ ewPtr = TkTextIndexToSeg(&index, NULL);
+ if (ewPtr->typePtr != &tkTextEmbWindowType) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "no embedded window at index \"%s\"",
+ Tcl_GetString(objv[3])));
+ Tcl_SetErrorCode(interp, "TK", "TEXT", "NO_WINDOW", NULL);
+ return TCL_ERROR;
+ }
+ if (objc <= 5) {
+ TkTextEmbWindowClient *client;
+ Tcl_Obj *objPtr;
+
+ /*
+ * Copy over client specific value before querying.
+ */
+
+ client = EmbWinGetClient(textPtr, ewPtr);
+ if (client != NULL) {
+ ewPtr->body.ew.tkwin = client->tkwin;
+ } else {
+ ewPtr->body.ew.tkwin = NULL;
+ }
+
+ objPtr = Tk_GetOptionInfo(interp, (char *) &ewPtr->body.ew,
+ ewPtr->body.ew.optionTable, (objc == 5) ? objv[4] : NULL,
+ textPtr->tkwin);
+ if (objPtr == NULL) {
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ return TCL_OK;
+ } else {
+ TkTextChanged(textPtr->sharedTextPtr, NULL, &index, &index);
+
+ /*
+ * It's probably not true that all window configuration can change
+ * the line height, so we could be more efficient here and only
+ * call this when necessary.
+ */
+
+ TkTextInvalidateLineMetrics(textPtr->sharedTextPtr, NULL,
+ index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY);
+ return EmbWinConfigure(textPtr, ewPtr, objc-4, objv+4);
+ }
+ }
+ case WIND_CREATE: {
+ TkTextIndex index;
+ int lineIndex;
+ TkTextEmbWindowClient *client;
+ int res;
+
+ /*
+ * Add a new window. Find where to put the new window, and mark that
+ * position for redisplay.
+ */
+
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index ?-option value ...?");
+ return TCL_ERROR;
+ }
+ if (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Don't allow insertions on the last (dummy) line of the text.
+ */
+
+ lineIndex = TkBTreeLinesTo(textPtr, index.linePtr);
+ if (lineIndex == TkBTreeNumLines(textPtr->sharedTextPtr->tree,
+ textPtr)) {
+ lineIndex--;
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,
+ lineIndex, 1000000, &index);
+ }
+
+ /*
+ * Create the new window segment and initialize it.
+ */
+
+ ewPtr = ckalloc(EW_SEG_SIZE);
+ ewPtr->typePtr = &tkTextEmbWindowType;
+ ewPtr->size = 1;
+ ewPtr->body.ew.sharedTextPtr = textPtr->sharedTextPtr;
+ ewPtr->body.ew.linePtr = NULL;
+ ewPtr->body.ew.tkwin = NULL;
+ ewPtr->body.ew.create = NULL;
+ ewPtr->body.ew.align = ALIGN_CENTER;
+ ewPtr->body.ew.padX = ewPtr->body.ew.padY = 0;
+ ewPtr->body.ew.stretch = 0;
+ ewPtr->body.ew.optionTable = Tk_CreateOptionTable(interp, optionSpecs);
+
+ client = ckalloc(sizeof(TkTextEmbWindowClient));
+ client->next = NULL;
+ client->textPtr = textPtr;
+ client->tkwin = NULL;
+ client->chunkCount = 0;
+ client->displayed = 0;
+ client->parent = ewPtr;
+ ewPtr->body.ew.clients = client;
+
+ /*
+ * Link the segment into the text widget, then configure it (delete it
+ * again if the configuration fails).
+ */
+
+ TkTextChanged(textPtr->sharedTextPtr, NULL, &index, &index);
+ TkBTreeLinkSegment(ewPtr, &index);
+ res = EmbWinConfigure(textPtr, ewPtr, objc-4, objv+4);
+ client->tkwin = ewPtr->body.ew.tkwin;
+ if (res != TCL_OK) {
+ TkTextIndex index2;
+
+ TkTextIndexForwChars(NULL, &index, 1, &index2, COUNT_INDICES);
+ TkBTreeDeleteIndexRange(textPtr->sharedTextPtr->tree, &index,
+ &index2);
+ return TCL_ERROR;
+ }
+ TkTextInvalidateLineMetrics(textPtr->sharedTextPtr, NULL,
+ index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY);
+ break;
+ }
+ case WIND_NAMES: {
+ Tcl_HashSearch search;
+ Tcl_HashEntry *hPtr;
+ Tcl_Obj *resultObj;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ return TCL_ERROR;
+ }
+ resultObj = Tcl_NewObj();
+ for (hPtr = Tcl_FirstHashEntry(&textPtr->sharedTextPtr->windowTable,
+ &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
+ Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(
+ Tcl_GetHashKey(&textPtr->sharedTextPtr->markTable, hPtr),
+ -1));
+ }
+ Tcl_SetObjResult(interp, resultObj);
+ break;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EmbWinConfigure --
+ *
+ * This function is called to handle configuration options for an
+ * embedded window, using an objc/objv list.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If TCL_ERROR is returned,
+ * then the interp's result contains an error message..
+ *
+ * Side effects:
+ * Configuration information for the embedded window changes, such as
+ * alignment, stretching, or name of the embedded window.
+ *
+ * Note that this function may leave widget specific client information
+ * with a NULL tkwin attached to ewPtr. While we could choose to clean up
+ * the client data structure here, there is no need to do so, and it is
+ * likely that the user is going to adjust the tkwin again soon.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+EmbWinConfigure(
+ TkText *textPtr, /* Information about text widget that contains
+ * embedded window. */
+ TkTextSegment *ewPtr, /* Embedded window to be configured. */
+ int objc, /* Number of strings in objv. */
+ Tcl_Obj *const objv[]) /* Array of objects describing configuration
+ * options. */
+{
+ Tk_Window oldWindow;
+ TkTextEmbWindowClient *client;
+
+ /*
+ * Copy over client specific value before querying or setting.
+ */
+
+ client = EmbWinGetClient(textPtr, ewPtr);
+ if (client != NULL) {
+ ewPtr->body.ew.tkwin = client->tkwin;
+ } else {
+ ewPtr->body.ew.tkwin = NULL;
+ }
+
+ oldWindow = ewPtr->body.ew.tkwin;
+ if (Tk_SetOptions(textPtr->interp, (char *) &ewPtr->body.ew,
+ ewPtr->body.ew.optionTable, objc, objv, textPtr->tkwin, NULL,
+ NULL) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (oldWindow != ewPtr->body.ew.tkwin) {
+ if (oldWindow != NULL) {
+ Tcl_DeleteHashEntry(Tcl_FindHashEntry(
+ &textPtr->sharedTextPtr->windowTable,
+ Tk_PathName(oldWindow)));
+ Tk_DeleteEventHandler(oldWindow, StructureNotifyMask,
+ EmbWinStructureProc, client);
+ Tk_ManageGeometry(oldWindow, NULL, NULL);
+ if (textPtr->tkwin != Tk_Parent(oldWindow)) {
+ Tk_UnmaintainGeometry(oldWindow, textPtr->tkwin);
+ } else {
+ Tk_UnmapWindow(oldWindow);
+ }
+ }
+ if (client != NULL) {
+ client->tkwin = NULL;
+ }
+ if (ewPtr->body.ew.tkwin != NULL) {
+ Tk_Window ancestor, parent;
+ Tcl_HashEntry *hPtr;
+ int isNew;
+
+ /*
+ * Make sure that the text is either the parent of the embedded
+ * window or a descendant of that parent. Also, don't allow a
+ * top-level window to be managed inside a text.
+ */
+
+ parent = Tk_Parent(ewPtr->body.ew.tkwin);
+ for (ancestor = textPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) {
+ if (ancestor == parent) {
+ break;
+ }
+ if (Tk_TopWinHierarchy(ancestor)) {
+ badMaster:
+ Tcl_SetObjResult(textPtr->interp, Tcl_ObjPrintf(
+ "can't embed %s in %s",
+ Tk_PathName(ewPtr->body.ew.tkwin),
+ Tk_PathName(textPtr->tkwin)));
+ Tcl_SetErrorCode(textPtr->interp, "TK", "GEOMETRY",
+ "HIERARCHY", NULL);
+ ewPtr->body.ew.tkwin = NULL;
+ if (client != NULL) {
+ client->tkwin = NULL;
+ }
+ return TCL_ERROR;
+ }
+ }
+ if (Tk_TopWinHierarchy(ewPtr->body.ew.tkwin)
+ || (ewPtr->body.ew.tkwin == textPtr->tkwin)) {
+ goto badMaster;
+ }
+
+ if (client == NULL) {
+ /*
+ * Have to make the new client.
+ */
+
+ client = ckalloc(sizeof(TkTextEmbWindowClient));
+ client->next = ewPtr->body.ew.clients;
+ client->textPtr = textPtr;
+ client->tkwin = NULL;
+ client->chunkCount = 0;
+ client->displayed = 0;
+ client->parent = ewPtr;
+ ewPtr->body.ew.clients = client;
+ }
+ client->tkwin = ewPtr->body.ew.tkwin;
+
+ /*
+ * Take over geometry management for the window, plus create an
+ * event handler to find out when it is deleted.
+ */
+
+ Tk_ManageGeometry(ewPtr->body.ew.tkwin, &textGeomType, client);
+ Tk_CreateEventHandler(ewPtr->body.ew.tkwin, StructureNotifyMask,
+ EmbWinStructureProc, client);
+
+ /*
+ * Special trick! Must enter into the hash table *after* calling
+ * Tk_ManageGeometry: if the window was already managed elsewhere
+ * in this text, the Tk_ManageGeometry call will cause the entry
+ * to be removed, which could potentially lose the new entry.
+ */
+
+ hPtr = Tcl_CreateHashEntry(&textPtr->sharedTextPtr->windowTable,
+ Tk_PathName(ewPtr->body.ew.tkwin), &isNew);
+ Tcl_SetHashValue(hPtr, ewPtr);
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EmbWinStructureProc --
+ *
+ * This function is invoked by the Tk event loop whenever StructureNotify
+ * events occur for a window that's embedded in a text widget. This
+ * function's only purpose is to clean up when windows are deleted.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The window is disassociated from the window segment, and the portion
+ * of the text is redisplayed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+EmbWinStructureProc(
+ ClientData clientData, /* Pointer to record describing window item. */
+ XEvent *eventPtr) /* Describes what just happened. */
+{
+ TkTextEmbWindowClient *client = clientData;
+ TkTextSegment *ewPtr = client->parent;
+ TkTextIndex index;
+ Tcl_HashEntry *hPtr;
+
+ if (eventPtr->type != DestroyNotify) {
+ return;
+ }
+
+ hPtr = Tcl_FindHashEntry(&ewPtr->body.ew.sharedTextPtr->windowTable,
+ Tk_PathName(client->tkwin));
+ if (hPtr != NULL) {
+ /*
+ * This may not exist if the entire widget is being deleted.
+ */
+
+ Tcl_DeleteHashEntry(hPtr);
+ }
+
+ ewPtr->body.ew.tkwin = NULL;
+ client->tkwin = NULL;
+ index.tree = ewPtr->body.ew.sharedTextPtr->tree;
+ index.linePtr = ewPtr->body.ew.linePtr;
+ index.byteIndex = TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr);
+ TkTextChanged(ewPtr->body.ew.sharedTextPtr, NULL, &index, &index);
+ TkTextInvalidateLineMetrics(ewPtr->body.ew.sharedTextPtr, NULL,
+ index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EmbWinRequestProc --
+ *
+ * This function is invoked whenever a window that's associated with a
+ * window canvas item changes its requested dimensions.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The size and location on the screen of the window may change,
+ * depending on the options specified for the window item.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static void
+EmbWinRequestProc(
+ ClientData clientData, /* Pointer to record for window item. */
+ Tk_Window tkwin) /* Window that changed its desired size. */
+{
+ TkTextEmbWindowClient *client = clientData;
+ TkTextSegment *ewPtr = client->parent;
+ TkTextIndex index;
+
+ index.tree = ewPtr->body.ew.sharedTextPtr->tree;
+ index.linePtr = ewPtr->body.ew.linePtr;
+ index.byteIndex = TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr);
+ TkTextChanged(ewPtr->body.ew.sharedTextPtr, NULL, &index, &index);
+ TkTextInvalidateLineMetrics(ewPtr->body.ew.sharedTextPtr, NULL,
+ index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EmbWinLostSlaveProc --
+ *
+ * This function is invoked by the Tk geometry manager when a slave
+ * window managed by a text widget is claimed away by another geometry
+ * manager.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The window is disassociated from the window segment, and the portion
+ * of the text is redisplayed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+EmbWinLostSlaveProc(
+ ClientData clientData, /* Pointer to record describing window item. */
+ Tk_Window tkwin) /* Window that was claimed away by another
+ * geometry manager. */
+{
+ TkTextEmbWindowClient *client = clientData;
+ TkTextSegment *ewPtr = client->parent;
+ TkTextIndex index;
+ Tcl_HashEntry *hPtr;
+ TkTextEmbWindowClient *loop;
+
+ Tk_DeleteEventHandler(client->tkwin, StructureNotifyMask,
+ EmbWinStructureProc, client);
+ Tcl_CancelIdleCall(EmbWinDelayedUnmap, client);
+ if (client->textPtr->tkwin != Tk_Parent(tkwin)) {
+ Tk_UnmaintainGeometry(tkwin, client->textPtr->tkwin);
+ } else {
+ Tk_UnmapWindow(tkwin);
+ }
+ hPtr = Tcl_FindHashEntry(&ewPtr->body.ew.sharedTextPtr->windowTable,
+ Tk_PathName(client->tkwin));
+ Tcl_DeleteHashEntry(hPtr);
+ client->tkwin = NULL;
+ ewPtr->body.ew.tkwin = NULL;
+
+ /*
+ * Free up the memory allocation for this client.
+ */
+
+ loop = ewPtr->body.ew.clients;
+ if (loop == client) {
+ ewPtr->body.ew.clients = client->next;
+ } else {
+ while (loop->next != client) {
+ loop = loop->next;
+ }
+ loop->next = client->next;
+ }
+ ckfree(client);
+
+ index.tree = ewPtr->body.ew.sharedTextPtr->tree;
+ index.linePtr = ewPtr->body.ew.linePtr;
+ index.byteIndex = TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr);
+ TkTextChanged(ewPtr->body.ew.sharedTextPtr, NULL, &index, &index);
+ TkTextInvalidateLineMetrics(ewPtr->body.ew.sharedTextPtr, NULL,
+ index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkTextWinFreeClient --
+ *
+ * Free up the hash entry and client information for a given embedded
+ * window.
+ *
+ * It is assumed the caller will manage the linked list of clients
+ * associated with the relevant TkTextSegment.
+ *
+ * Results:
+ * Nothing.
+ *
+ * Side effects:
+ * The embedded window information for a single client is deleted, if it
+ * exists, and any resources associated with it are released.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkTextWinFreeClient(
+ Tcl_HashEntry *hPtr, /* Hash entry corresponding to this client, or
+ * NULL */
+ TkTextEmbWindowClient *client)
+ /* Client data structure, with the 'tkwin'
+ * field to be cleaned up. */
+{
+ if (hPtr != NULL) {
+ /*
+ * (It's possible for there to be no hash table entry for this window,
+ * if an error occurred while creating the window segment but before
+ * the window got added to the table)
+ */
+
+ Tcl_DeleteHashEntry(hPtr);
+ }
+
+ /*
+ * Delete the event handler for the window before destroying the window,
+ * so that EmbWinStructureProc doesn't get called (we'll already do
+ * everything that it would have done, and it will just get confused).
+ */
+
+ if (client->tkwin != NULL) {
+ Tk_DeleteEventHandler(client->tkwin, StructureNotifyMask,
+ EmbWinStructureProc, client);
+ Tk_DestroyWindow(client->tkwin);
+ }
+ Tcl_CancelIdleCall(EmbWinDelayedUnmap, client);
+
+ /*
+ * Free up this client.
+ */
+
+ ckfree(client);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EmbWinDeleteProc --
+ *
+ * This function is invoked by the text B-tree code whenever an embedded
+ * window lies in a range of characters being deleted.
+ *
+ * Results:
+ * Returns 0 to indicate that the deletion has been accepted.
+ *
+ * Side effects:
+ * The embedded window is deleted, if it exists, and any resources
+ * associated with it are released.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+EmbWinDeleteProc(
+ TkTextSegment *ewPtr, /* Segment being deleted. */
+ TkTextLine *linePtr, /* Line containing segment. */
+ int treeGone) /* Non-zero means the entire tree is being
+ * deleted, so everything must get cleaned
+ * up. */
+{
+ TkTextEmbWindowClient *client;
+ client = ewPtr->body.ew.clients;
+
+ while (client != NULL) {
+ TkTextEmbWindowClient *next = client->next;
+ Tcl_HashEntry *hPtr = NULL;
+
+ if (client->tkwin != NULL) {
+ hPtr = Tcl_FindHashEntry(
+ &ewPtr->body.ew.sharedTextPtr->windowTable,
+ Tk_PathName(client->tkwin));
+ }
+ TkTextWinFreeClient(hPtr, client);
+ client = next;
+ }
+ ewPtr->body.ew.clients = NULL;
+
+ Tk_FreeConfigOptions((char *) &ewPtr->body.ew, ewPtr->body.ew.optionTable,
+ NULL);
+
+ /*
+ * Free up all memory allocated.
+ */
+
+ ckfree(ewPtr);
+ return 0;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EmbWinCleanupProc --
+ *
+ * This function is invoked by the B-tree code whenever a segment
+ * containing an embedded window is moved from one line to another.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The linePtr field of the segment gets updated.
+ *
+ *--------------------------------------------------------------
+ */
+
+static TkTextSegment *
+EmbWinCleanupProc(
+ TkTextSegment *ewPtr, /* Mark segment that's being moved. */
+ TkTextLine *linePtr) /* Line that now contains segment. */
+{
+ ewPtr->body.ew.linePtr = linePtr;
+ return ewPtr;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EmbWinLayoutProc --
+ *
+ * This function is the "layoutProc" for embedded window segments.
+ *
+ * Results:
+ * 1 is returned to indicate that the segment should be displayed. The
+ * chunkPtr structure is filled in.
+ *
+ * Side effects:
+ * None, except for filling in chunkPtr.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /*ARGSUSED*/
+static int
+EmbWinLayoutProc(
+ TkText *textPtr, /* Text widget being layed out. */
+ TkTextIndex *indexPtr, /* Identifies first character in chunk. */
+ TkTextSegment *ewPtr, /* Segment corresponding to indexPtr. */
+ int offset, /* Offset within segPtr corresponding to
+ * indexPtr (always 0). */
+ int maxX, /* Chunk must not occupy pixels at this
+ * position or higher. */
+ int maxChars, /* Chunk must not include more than this many
+ * characters. */
+ int noCharsYet, /* Non-zero means no characters have been
+ * assigned to this line yet. */
+ TkWrapMode wrapMode, /* Wrap mode to use for line:
+ * TEXT_WRAPMODE_CHAR, TEXT_WRAPMODE_NONE, or
+ * TEXT_WRAPMODE_WORD. */
+ register TkTextDispChunk *chunkPtr)
+ /* Structure to fill in with information about
+ * this chunk. The x field has already been
+ * set by the caller. */
+{
+ int width, height;
+ TkTextEmbWindowClient *client;
+
+ if (offset != 0) {
+ Tcl_Panic("Non-zero offset in EmbWinLayoutProc");
+ }
+
+ client = EmbWinGetClient(textPtr, ewPtr);
+ if (client == NULL) {
+ ewPtr->body.ew.tkwin = NULL;
+ } else {
+ ewPtr->body.ew.tkwin = client->tkwin;
+ }
+
+ if ((ewPtr->body.ew.tkwin == NULL) && (ewPtr->body.ew.create != NULL)) {
+ int code, isNew;
+ Tk_Window ancestor;
+ Tcl_HashEntry *hPtr;
+ const char *before, *string;
+ Tcl_DString buf, *dsPtr = NULL;
+ Tcl_Obj *nameObj;
+
+ before = ewPtr->body.ew.create;
+
+ /*
+ * Find everything up to the next % character and append it to the
+ * result string.
+ */
+
+ string = before;
+ while (*string != 0) {
+ if ((*string == '%') && (string[1] == '%' || string[1] == 'W')) {
+ if (dsPtr == NULL) {
+ Tcl_DStringInit(&buf);
+ dsPtr = &buf;
+ }
+ if (string != before) {
+ Tcl_DStringAppend(dsPtr, before, (int) (string-before));
+ before = string;
+ }
+ if (string[1] == '%') {
+ Tcl_DStringAppend(dsPtr, "%", 1);
+ } else {
+ /*
+ * Substitute string as proper Tcl list element.
+ */
+
+ int spaceNeeded, cvtFlags, length;
+ const char *str = Tk_PathName(textPtr->tkwin);
+
+ spaceNeeded = Tcl_ScanElement(str, &cvtFlags);
+ length = Tcl_DStringLength(dsPtr);
+ Tcl_DStringSetLength(dsPtr, length + spaceNeeded);
+ spaceNeeded = Tcl_ConvertElement(str,
+ Tcl_DStringValue(dsPtr) + length,
+ cvtFlags | TCL_DONT_USE_BRACES);
+ Tcl_DStringSetLength(dsPtr, length + spaceNeeded);
+ }
+ before += 2;
+ string++;
+ }
+ string++;
+ }
+
+ /*
+ * The window doesn't currently exist. Create it by evaluating the
+ * creation script. The script must return the window's path name:
+ * look up that name to get back to the window token. Then register
+ * ourselves as the geometry manager for the window.
+ */
+
+ if (dsPtr != NULL) {
+ Tcl_DStringAppend(dsPtr, before, (int) (string-before));
+ code = Tcl_EvalEx(textPtr->interp, Tcl_DStringValue(dsPtr), -1, TCL_EVAL_GLOBAL);
+ Tcl_DStringFree(dsPtr);
+ } else {
+ code = Tcl_EvalEx(textPtr->interp, ewPtr->body.ew.create, -1, TCL_EVAL_GLOBAL);
+ }
+ if (code != TCL_OK) {
+ Tcl_BackgroundException(textPtr->interp, code);
+ goto gotWindow;
+ }
+ nameObj = Tcl_GetObjResult(textPtr->interp);
+ Tcl_IncrRefCount(nameObj);
+ Tcl_ResetResult(textPtr->interp);
+ ewPtr->body.ew.tkwin = Tk_NameToWindow(textPtr->interp,
+ Tcl_GetString(nameObj), textPtr->tkwin);
+ Tcl_DecrRefCount(nameObj);
+ if (ewPtr->body.ew.tkwin == NULL) {
+ Tcl_BackgroundException(textPtr->interp, TCL_ERROR);
+ goto gotWindow;
+ }
+
+ for (ancestor = textPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) {
+ if (ancestor == Tk_Parent(ewPtr->body.ew.tkwin)) {
+ break;
+ }
+ if (Tk_TopWinHierarchy(ancestor)) {
+ goto badMaster;
+ }
+ }
+ if (Tk_TopWinHierarchy(ewPtr->body.ew.tkwin)
+ || (textPtr->tkwin == ewPtr->body.ew.tkwin)) {
+ badMaster:
+ Tcl_SetObjResult(textPtr->interp, Tcl_ObjPrintf(
+ "can't embed %s relative to %s",
+ Tk_PathName(ewPtr->body.ew.tkwin),
+ Tk_PathName(textPtr->tkwin)));
+ Tcl_SetErrorCode(textPtr->interp, "TK", "GEOMETRY", "HIERARCHY",
+ NULL);
+ Tcl_BackgroundException(textPtr->interp, TCL_ERROR);
+ ewPtr->body.ew.tkwin = NULL;
+ goto gotWindow;
+ }
+
+ if (client == NULL) {
+ /*
+ * We just used a '-create' script to make a new window, which we
+ * now need to add to our client list.
+ */
+
+ client = ckalloc(sizeof(TkTextEmbWindowClient));
+ client->next = ewPtr->body.ew.clients;
+ client->textPtr = textPtr;
+ client->tkwin = NULL;
+ client->chunkCount = 0;
+ client->displayed = 0;
+ client->parent = ewPtr;
+ ewPtr->body.ew.clients = client;
+ }
+
+ client->tkwin = ewPtr->body.ew.tkwin;
+ Tk_ManageGeometry(client->tkwin, &textGeomType, client);
+ Tk_CreateEventHandler(client->tkwin, StructureNotifyMask,
+ EmbWinStructureProc, client);
+
+ /*
+ * Special trick! Must enter into the hash table *after* calling
+ * Tk_ManageGeometry: if the window was already managed elsewhere in
+ * this text, the Tk_ManageGeometry call will cause the entry to be
+ * removed, which could potentially lose the new entry.
+ */
+
+ hPtr = Tcl_CreateHashEntry(&textPtr->sharedTextPtr->windowTable,
+ Tk_PathName(client->tkwin), &isNew);
+ Tcl_SetHashValue(hPtr, ewPtr);
+ }
+
+ /*
+ * See if there's room for this window on this line.
+ */
+
+ gotWindow:
+ if (ewPtr->body.ew.tkwin == NULL) {
+ width = 0;
+ height = 0;
+ } else {
+ width = Tk_ReqWidth(ewPtr->body.ew.tkwin) + 2*ewPtr->body.ew.padX;
+ height = Tk_ReqHeight(ewPtr->body.ew.tkwin) + 2*ewPtr->body.ew.padY;
+ }
+ if ((width > (maxX - chunkPtr->x))
+ && !noCharsYet && (textPtr->wrapMode != TEXT_WRAPMODE_NONE)) {
+ return 0;
+ }
+
+ /*
+ * Fill in the chunk structure.
+ */
+
+ chunkPtr->displayProc = TkTextEmbWinDisplayProc;
+ chunkPtr->undisplayProc = EmbWinUndisplayProc;
+ chunkPtr->measureProc = NULL;
+ chunkPtr->bboxProc = EmbWinBboxProc;
+ chunkPtr->numBytes = 1;
+ if (ewPtr->body.ew.align == ALIGN_BASELINE) {
+ chunkPtr->minAscent = height - ewPtr->body.ew.padY;
+ chunkPtr->minDescent = ewPtr->body.ew.padY;
+ chunkPtr->minHeight = 0;
+ } else {
+ chunkPtr->minAscent = 0;
+ chunkPtr->minDescent = 0;
+ chunkPtr->minHeight = height;
+ }
+ chunkPtr->width = width;
+ chunkPtr->breakIndex = -1;
+ chunkPtr->breakIndex = 1;
+ chunkPtr->clientData = ewPtr;
+ if (client != NULL) {
+ client->chunkCount += 1;
+ }
+ return 1;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EmbWinCheckProc --
+ *
+ * This function is invoked by the B-tree code to perform consistency
+ * checks on embedded windows.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The function panics if it detects anything wrong with the embedded
+ * window.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+EmbWinCheckProc(
+ TkTextSegment *ewPtr, /* Segment to check. */
+ TkTextLine *linePtr) /* Line containing segment. */
+{
+ if (ewPtr->nextPtr == NULL) {
+ Tcl_Panic("EmbWinCheckProc: embedded window is last segment in line");
+ }
+ if (ewPtr->size != 1) {
+ Tcl_Panic("EmbWinCheckProc: embedded window has size %d", ewPtr->size);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkTextEmbWinDisplayProc --
+ *
+ * This function is invoked by the text displaying code when it is time
+ * to actually draw an embedded window chunk on the screen.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The embedded window gets moved to the correct location and mapped onto
+ * the screen.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkTextEmbWinDisplayProc(
+ TkText *textPtr, /* Information about text widget. */
+ TkTextDispChunk *chunkPtr, /* Chunk that is to be drawn. */
+ int x, /* X-position in dst at which to draw this
+ * chunk (differs from the x-position in the
+ * chunk because of scrolling). */
+ int y, /* Top of rectangular bounding box for line:
+ * tells where to draw this chunk in dst
+ * (x-position is in the chunk itself). */
+ int lineHeight, /* Total height of line. */
+ int baseline, /* Offset of baseline from y. */
+ Display *display, /* Display to use for drawing (unused). */
+ Drawable dst, /* Pixmap or window in which to draw
+ * (unused). */
+ int screenY) /* Y-coordinate in text window that
+ * corresponds to y. */
+{
+ int lineX, windowX, windowY, width, height;
+ Tk_Window tkwin;
+ TkTextSegment *ewPtr = chunkPtr->clientData;
+ TkTextEmbWindowClient *client = EmbWinGetClient(textPtr, ewPtr);
+
+ if (client == NULL) {
+ return;
+ }
+
+ tkwin = client->tkwin;
+ if (tkwin == NULL) {
+ return;
+ }
+
+ if ((x + chunkPtr->width) <= 0) {
+ /*
+ * The window is off-screen; just unmap it.
+ */
+
+ if (textPtr->tkwin != Tk_Parent(tkwin)) {
+ Tk_UnmaintainGeometry(tkwin, textPtr->tkwin);
+ } else {
+ Tk_UnmapWindow(tkwin);
+ }
+ return;
+ }
+
+ /*
+ * Compute the window's location and size in the text widget, taking into
+ * account the align and stretch values for the window.
+ */
+
+ EmbWinBboxProc(textPtr, chunkPtr, 0, screenY, lineHeight, baseline,
+ &lineX, &windowY, &width, &height);
+ windowX = lineX - chunkPtr->x + x;
+
+ /*
+ * Mark the window as displayed so that it won't get unmapped.
+ * This needs to be done before the next instruction block because
+ * Tk_MaintainGeometry/Tk_MapWindow will run event handlers, in
+ * particular for the <Map> event, and if the bound script deletes
+ * the embedded window its clients will get freed.
+ */
+
+ client->displayed = 1;
+
+ if (textPtr->tkwin == Tk_Parent(tkwin)) {
+ if ((windowX != Tk_X(tkwin)) || (windowY != Tk_Y(tkwin))
+ || (Tk_ReqWidth(tkwin) != Tk_Width(tkwin))
+ || (height != Tk_Height(tkwin))) {
+ Tk_MoveResizeWindow(tkwin, windowX, windowY, width, height);
+ }
+ Tk_MapWindow(tkwin);
+ } else {
+ Tk_MaintainGeometry(tkwin, textPtr->tkwin, windowX, windowY,
+ width, height);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EmbWinUndisplayProc --
+ *
+ * This function is called when the chunk for an embedded window is no
+ * longer going to be displayed. It arranges for the window associated
+ * with the chunk to be unmapped.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The window is scheduled for unmapping.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+EmbWinUndisplayProc(
+ TkText *textPtr, /* Overall information about text widget. */
+ TkTextDispChunk *chunkPtr) /* Chunk that is about to be freed. */
+{
+ TkTextSegment *ewPtr = chunkPtr->clientData;
+ TkTextEmbWindowClient *client = EmbWinGetClient(textPtr, ewPtr);
+
+ if (client == NULL) {
+ return;
+ }
+
+ client->chunkCount--;
+ if (client->chunkCount == 0) {
+ /*
+ * Don't unmap the window immediately, since there's a good chance
+ * that it will immediately be redisplayed, perhaps even in the same
+ * place. Instead, schedule the window to be unmapped later; the call
+ * to EmbWinDelayedUnmap will be cancelled in the likely event that
+ * the unmap becomes unnecessary.
+ */
+
+ client->displayed = 0;
+ Tcl_DoWhenIdle(EmbWinDelayedUnmap, client);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EmbWinBboxProc --
+ *
+ * This function is called to compute the bounding box of the area
+ * occupied by an embedded window.
+ *
+ * Results:
+ * There is no return value. *xPtr and *yPtr are filled in with the
+ * coordinates of the upper left corner of the window, and *widthPtr and
+ * *heightPtr are filled in with the dimensions of the window in pixels.
+ * Note: not all of the returned bbox is necessarily visible on the
+ * screen (the rightmost part might be off-screen to the right, and the
+ * bottommost part might be off-screen to the bottom).
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+EmbWinBboxProc(
+ TkText *textPtr, /* Information about text widget. */
+ TkTextDispChunk *chunkPtr, /* Chunk containing desired char. */
+ int index, /* Index of desired character within the
+ * chunk. */
+ int y, /* Topmost pixel in area allocated for this
+ * line. */
+ int lineHeight, /* Total height of line. */
+ int baseline, /* Location of line's baseline, in pixels
+ * measured down from y. */
+ int *xPtr, int *yPtr, /* Gets filled in with coords of character's
+ * upper-left pixel. */
+ int *widthPtr, /* Gets filled in with width of window, in
+ * pixels. */
+ int *heightPtr) /* Gets filled in with height of window, in
+ * pixels. */
+{
+ Tk_Window tkwin;
+ TkTextSegment *ewPtr = chunkPtr->clientData;
+ TkTextEmbWindowClient *client = EmbWinGetClient(textPtr, ewPtr);
+
+ if (client == NULL) {
+ tkwin = NULL;
+ } else {
+ tkwin = client->tkwin;
+ }
+ if (tkwin != NULL) {
+ *widthPtr = Tk_ReqWidth(tkwin);
+ *heightPtr = Tk_ReqHeight(tkwin);
+ } else {
+ *widthPtr = 0;
+ *heightPtr = 0;
+ }
+ *xPtr = chunkPtr->x + ewPtr->body.ew.padX;
+ if (ewPtr->body.ew.stretch) {
+ if (ewPtr->body.ew.align == ALIGN_BASELINE) {
+ *heightPtr = baseline - ewPtr->body.ew.padY;
+ } else {
+ *heightPtr = lineHeight - 2*ewPtr->body.ew.padY;
+ }
+ }
+ switch (ewPtr->body.ew.align) {
+ case ALIGN_BOTTOM:
+ *yPtr = y + (lineHeight - *heightPtr - ewPtr->body.ew.padY);
+ break;
+ case ALIGN_CENTER:
+ *yPtr = y + (lineHeight - *heightPtr)/2;
+ break;
+ case ALIGN_TOP:
+ *yPtr = y + ewPtr->body.ew.padY;
+ break;
+ case ALIGN_BASELINE:
+ *yPtr = y + (baseline - *heightPtr);
+ break;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EmbWinDelayedUnmap --
+ *
+ * This function is an idle handler that does the actual work of
+ * unmapping an embedded window. See the comment in EmbWinUndisplayProc
+ * for details.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The window gets unmapped, unless its chunk reference count has become
+ * non-zero again.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+EmbWinDelayedUnmap(
+ ClientData clientData) /* Token for the window to be unmapped. */
+{
+ TkTextEmbWindowClient *client = clientData;
+
+ if (!client->displayed && (client->tkwin != NULL)) {
+ if (client->textPtr->tkwin != Tk_Parent(client->tkwin)) {
+ Tk_UnmaintainGeometry(client->tkwin, client->textPtr->tkwin);
+ } else {
+ Tk_UnmapWindow(client->tkwin);
+ }
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkTextWindowIndex --
+ *
+ * Given the name of an embedded window within a text widget, returns an
+ * index corresponding to the window's position in the text.
+ *
+ * Results:
+ * The return value is 1 if there is an embedded window by the given name
+ * in the text widget, 0 otherwise. If the window exists, *indexPtr is
+ * filled in with its index.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkTextWindowIndex(
+ TkText *textPtr, /* Text widget containing window. */
+ const char *name, /* Name of window. */
+ TkTextIndex *indexPtr) /* Index information gets stored here. */
+{
+ Tcl_HashEntry *hPtr;
+ TkTextSegment *ewPtr;
+
+ if (textPtr == NULL) {
+ return 0;
+ }
+
+ hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->windowTable, name);
+ if (hPtr == NULL) {
+ return 0;
+ }
+
+ ewPtr = Tcl_GetHashValue(hPtr);
+ indexPtr->tree = textPtr->sharedTextPtr->tree;
+ indexPtr->linePtr = ewPtr->body.ew.linePtr;
+ indexPtr->byteIndex = TkTextSegToOffset(ewPtr, indexPtr->linePtr);
+ return 1;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EmbWinGetClient --
+ *
+ * Given a text widget and a segment which contains an embedded window,
+ * find the text-widget specific information about the embedded window,
+ * if any.
+ *
+ * This function performs a completely linear lookup for a matching data
+ * structure. If we envisage using this code with dozens of peer widgets,
+ * then performance could become an issue and a more sophisticated lookup
+ * mechanism might be desirable.
+ *
+ * Results:
+ * NULL if no widget-specific info exists, otherwise the structure is
+ * returned.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static TkTextEmbWindowClient *
+EmbWinGetClient(
+ const TkText *textPtr, /* Information about text widget. */
+ TkTextSegment *ewPtr) /* Segment containing embedded window. */
+{
+ TkTextEmbWindowClient *client = ewPtr->body.ew.clients;
+
+ while (client != NULL) {
+ if (client->textPtr == textPtr) {
+ return client;
+ }
+ client = client->next;
+ }
+ return NULL;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkTrig.c b/tk8.6/generic/tkTrig.c
new file mode 100644
index 0000000..a2bf456
--- /dev/null
+++ b/tk8.6/generic/tkTrig.c
@@ -0,0 +1,1753 @@
+/*
+ * tkTrig.c --
+ *
+ * This file contains a collection of trigonometry utility routines that
+ * are used by Tk and in particular by the canvas code. It also has
+ * miscellaneous geometry functions used by canvases.
+ *
+ * Copyright (c) 1992-1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "tkInt.h"
+#include "tkCanvas.h"
+
+#undef MIN
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#undef MAX
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkLineToPoint --
+ *
+ * Compute the distance from a point to a finite line segment.
+ *
+ * Results:
+ * The return value is the distance from the line segment whose
+ * end-points are *end1Ptr and *end2Ptr to the point given by *pointPtr.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+double
+TkLineToPoint(
+ double end1Ptr[2], /* Coordinates of first end-point of line. */
+ double end2Ptr[2], /* Coordinates of second end-point of line. */
+ double pointPtr[2]) /* Points to coords for point. */
+{
+ double x, y;
+
+ /*
+ * Compute the point on the line that is closest to the point. This must
+ * be done separately for vertical edges, horizontal edges, and other
+ * edges.
+ */
+
+ if (end1Ptr[0] == end2Ptr[0]) {
+
+ /*
+ * Vertical edge.
+ */
+
+ x = end1Ptr[0];
+ if (end1Ptr[1] >= end2Ptr[1]) {
+ y = MIN(end1Ptr[1], pointPtr[1]);
+ y = MAX(y, end2Ptr[1]);
+ } else {
+ y = MIN(end2Ptr[1], pointPtr[1]);
+ y = MAX(y, end1Ptr[1]);
+ }
+ } else if (end1Ptr[1] == end2Ptr[1]) {
+
+ /*
+ * Horizontal edge.
+ */
+
+ y = end1Ptr[1];
+ if (end1Ptr[0] >= end2Ptr[0]) {
+ x = MIN(end1Ptr[0], pointPtr[0]);
+ x = MAX(x, end2Ptr[0]);
+ } else {
+ x = MIN(end2Ptr[0], pointPtr[0]);
+ x = MAX(x, end1Ptr[0]);
+ }
+ } else {
+ double m1, b1, m2, b2;
+
+ /*
+ * The edge is neither horizontal nor vertical. Convert the edge to a
+ * line equation of the form y = m1*x + b1. Then compute a line
+ * perpendicular to this edge but passing through the point, also in
+ * the form y = m2*x + b2.
+ */
+
+ m1 = (end2Ptr[1] - end1Ptr[1])/(end2Ptr[0] - end1Ptr[0]);
+ b1 = end1Ptr[1] - m1*end1Ptr[0];
+ m2 = -1.0/m1;
+ b2 = pointPtr[1] - m2*pointPtr[0];
+ x = (b2 - b1)/(m1 - m2);
+ y = m1*x + b1;
+ if (end1Ptr[0] > end2Ptr[0]) {
+ if (x > end1Ptr[0]) {
+ x = end1Ptr[0];
+ y = end1Ptr[1];
+ } else if (x < end2Ptr[0]) {
+ x = end2Ptr[0];
+ y = end2Ptr[1];
+ }
+ } else {
+ if (x > end2Ptr[0]) {
+ x = end2Ptr[0];
+ y = end2Ptr[1];
+ } else if (x < end1Ptr[0]) {
+ x = end1Ptr[0];
+ y = end1Ptr[1];
+ }
+ }
+ }
+
+ /*
+ * Compute the distance to the closest point.
+ */
+
+ return hypot(pointPtr[0] - x, pointPtr[1] - y);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkLineToArea --
+ *
+ * Determine whether a line lies entirely inside, entirely outside, or
+ * overlapping a given rectangular area.
+ *
+ * Results:
+ * -1 is returned if the line given by end1Ptr and end2Ptr is entirely
+ * outside the rectangle given by rectPtr. 0 is returned if the polygon
+ * overlaps the rectangle, and 1 is returned if the polygon is entirely
+ * inside the rectangle.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkLineToArea(
+ double end1Ptr[2], /* X and y coordinates for one endpoint of
+ * line. */
+ double end2Ptr[2], /* X and y coordinates for other endpoint of
+ * line. */
+ double rectPtr[4]) /* Points to coords for rectangle, in the
+ * order x1, y1, x2, y2. X1 must be no larger
+ * than x2, and y1 no larger than y2. */
+{
+ int inside1, inside2;
+
+ /*
+ * First check the two points individually to see whether they are inside
+ * the rectangle or not.
+ */
+
+ inside1 = (end1Ptr[0] >= rectPtr[0]) && (end1Ptr[0] <= rectPtr[2])
+ && (end1Ptr[1] >= rectPtr[1]) && (end1Ptr[1] <= rectPtr[3]);
+ inside2 = (end2Ptr[0] >= rectPtr[0]) && (end2Ptr[0] <= rectPtr[2])
+ && (end2Ptr[1] >= rectPtr[1]) && (end2Ptr[1] <= rectPtr[3]);
+ if (inside1 != inside2) {
+ return 0;
+ }
+ if (inside1 & inside2) {
+ return 1;
+ }
+
+ /*
+ * Both points are outside the rectangle, but still need to check for
+ * intersections between the line and the rectangle. Horizontal and
+ * vertical lines are particularly easy, so handle them separately.
+ */
+
+ if (end1Ptr[0] == end2Ptr[0]) {
+ /*
+ * Vertical line.
+ */
+
+ if (((end1Ptr[1] >= rectPtr[1]) ^ (end2Ptr[1] >= rectPtr[1]))
+ && (end1Ptr[0] >= rectPtr[0])
+ && (end1Ptr[0] <= rectPtr[2])) {
+ return 0;
+ }
+ } else if (end1Ptr[1] == end2Ptr[1]) {
+ /*
+ * Horizontal line.
+ */
+
+ if (((end1Ptr[0] >= rectPtr[0]) ^ (end2Ptr[0] >= rectPtr[0]))
+ && (end1Ptr[1] >= rectPtr[1])
+ && (end1Ptr[1] <= rectPtr[3])) {
+ return 0;
+ }
+ } else {
+ double m, x, y, low, high;
+
+ /*
+ * Diagonal line. Compute slope of line and use for intersection
+ * checks against each of the sides of the rectangle: left, right,
+ * bottom, top.
+ */
+
+ m = (end2Ptr[1] - end1Ptr[1])/(end2Ptr[0] - end1Ptr[0]);
+ if (end1Ptr[0] < end2Ptr[0]) {
+ low = end1Ptr[0];
+ high = end2Ptr[0];
+ } else {
+ low = end2Ptr[0];
+ high = end1Ptr[0];
+ }
+
+ /*
+ * Left edge.
+ */
+
+ y = end1Ptr[1] + (rectPtr[0] - end1Ptr[0])*m;
+ if ((rectPtr[0] >= low) && (rectPtr[0] <= high)
+ && (y >= rectPtr[1]) && (y <= rectPtr[3])) {
+ return 0;
+ }
+
+ /*
+ * Right edge.
+ */
+
+ y += (rectPtr[2] - rectPtr[0])*m;
+ if ((y >= rectPtr[1]) && (y <= rectPtr[3])
+ && (rectPtr[2] >= low) && (rectPtr[2] <= high)) {
+ return 0;
+ }
+
+ /*
+ * Bottom edge.
+ */
+
+ if (end1Ptr[1] < end2Ptr[1]) {
+ low = end1Ptr[1];
+ high = end2Ptr[1];
+ } else {
+ low = end2Ptr[1];
+ high = end1Ptr[1];
+ }
+ x = end1Ptr[0] + (rectPtr[1] - end1Ptr[1])/m;
+ if ((x >= rectPtr[0]) && (x <= rectPtr[2])
+ && (rectPtr[1] >= low) && (rectPtr[1] <= high)) {
+ return 0;
+ }
+
+ /*
+ * Top edge.
+ */
+
+ x += (rectPtr[3] - rectPtr[1])/m;
+ if ((x >= rectPtr[0]) && (x <= rectPtr[2])
+ && (rectPtr[3] >= low) && (rectPtr[3] <= high)) {
+ return 0;
+ }
+ }
+ return -1;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkThickPolyLineToArea --
+ *
+ * This function is called to determine whether a connected series of
+ * line segments lies entirely inside, entirely outside, or overlapping a
+ * given rectangular area.
+ *
+ * Results:
+ * -1 is returned if the lines are entirely outside the area, 0 if they
+ * overlap, and 1 if they are entirely inside the given area.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+int
+TkThickPolyLineToArea(
+ double *coordPtr, /* Points to an array of coordinates for the
+ * polyline: x0, y0, x1, y1, ... */
+ int numPoints, /* Total number of points at *coordPtr. */
+ double width, /* Width of each line segment. */
+ int capStyle, /* How are end-points of polyline drawn?
+ * CapRound, CapButt, or CapProjecting. */
+ int joinStyle, /* How are joints in polyline drawn?
+ * JoinMiter, JoinRound, or JoinBevel. */
+ double *rectPtr) /* Rectangular area to check against. */
+{
+ double radius, poly[10];
+ int count;
+ int changedMiterToBevel; /* Non-zero means that a mitered corner had to
+ * be treated as beveled after all because the
+ * angle was < 11 degrees. */
+ int inside; /* Tentative guess about what to return, based
+ * on all points seen so far: one means
+ * everything seen so far was inside the area;
+ * -1 means everything was outside the area.
+ * 0 means overlap has been found. */
+
+ radius = width/2.0;
+ inside = -1;
+
+ if ((coordPtr[0] >= rectPtr[0]) && (coordPtr[0] <= rectPtr[2])
+ && (coordPtr[1] >= rectPtr[1]) && (coordPtr[1] <= rectPtr[3])) {
+ inside = 1;
+ }
+
+ /*
+ * Iterate through all of the edges of the line, computing a polygon for
+ * each edge and testing the area against that polygon. In addition, there
+ * are additional tests to deal with rounded joints and caps.
+ */
+
+ changedMiterToBevel = 0;
+ for (count = numPoints; count >= 2; count--, coordPtr += 2) {
+ /*
+ * If rounding is done around the first point of the edge then test a
+ * circular region around the point with the area.
+ */
+
+ if (((capStyle == CapRound) && (count == numPoints))
+ || ((joinStyle == JoinRound) && (count != numPoints))) {
+ poly[0] = coordPtr[0] - radius;
+ poly[1] = coordPtr[1] - radius;
+ poly[2] = coordPtr[0] + radius;
+ poly[3] = coordPtr[1] + radius;
+ if (TkOvalToArea(poly, rectPtr) != inside) {
+ return 0;
+ }
+ }
+
+ /*
+ * Compute the polygonal shape corresponding to this edge, consisting
+ * of two points for the first point of the edge and two points for
+ * the last point of the edge.
+ */
+
+ if (count == numPoints) {
+ TkGetButtPoints(coordPtr+2, coordPtr, width,
+ capStyle == CapProjecting, poly, poly+2);
+ } else if ((joinStyle == JoinMiter) && !changedMiterToBevel) {
+ poly[0] = poly[6];
+ poly[1] = poly[7];
+ poly[2] = poly[4];
+ poly[3] = poly[5];
+ } else {
+ TkGetButtPoints(coordPtr+2, coordPtr, width, 0, poly, poly+2);
+
+ /*
+ * If the last joint was beveled, then also check a polygon
+ * comprising the last two points of the previous polygon and the
+ * first two from this polygon; this checks the wedges that fill
+ * the beveled joint.
+ */
+
+ if ((joinStyle == JoinBevel) || changedMiterToBevel) {
+ poly[8] = poly[0];
+ poly[9] = poly[1];
+ if (TkPolygonToArea(poly, 5, rectPtr) != inside) {
+ return 0;
+ }
+ changedMiterToBevel = 0;
+ }
+ }
+ if (count == 2) {
+ TkGetButtPoints(coordPtr, coordPtr+2, width,
+ capStyle == CapProjecting, poly+4, poly+6);
+ } else if (joinStyle == JoinMiter) {
+ if (TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4,
+ (double) width, poly+4, poly+6) == 0) {
+ changedMiterToBevel = 1;
+ TkGetButtPoints(coordPtr, coordPtr+2, width, 0, poly+4,
+ poly+6);
+ }
+ } else {
+ TkGetButtPoints(coordPtr, coordPtr+2, width, 0, poly+4, poly+6);
+ }
+ poly[8] = poly[0];
+ poly[9] = poly[1];
+ if (TkPolygonToArea(poly, 5, rectPtr) != inside) {
+ return 0;
+ }
+ }
+
+ /*
+ * If caps are rounded, check the cap around the final point of the line.
+ */
+
+ if (capStyle == CapRound) {
+ poly[0] = coordPtr[0] - radius;
+ poly[1] = coordPtr[1] - radius;
+ poly[2] = coordPtr[0] + radius;
+ poly[3] = coordPtr[1] + radius;
+ if (TkOvalToArea(poly, rectPtr) != inside) {
+ return 0;
+ }
+ }
+
+ return inside;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkPolygonToPoint --
+ *
+ * Compute the distance from a point to a polygon.
+ *
+ * Results:
+ * The return value is 0.0 if the point referred to by pointPtr is within
+ * the polygon referred to by polyPtr and numPoints. Otherwise the return
+ * value is the distance of the point from the polygon.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+double
+TkPolygonToPoint(
+ double *polyPtr, /* Points to an array coordinates for closed
+ * polygon: x0, y0, x1, y1, ... The polygon
+ * may be self-intersecting. */
+ int numPoints, /* Total number of points at *polyPtr. */
+ double *pointPtr) /* Points to coords for point. */
+{
+ double bestDist; /* Closest distance between point and any edge
+ * in polygon. */
+ int intersections; /* Number of edges in the polygon that
+ * intersect a ray extending vertically
+ * upwards from the point to infinity. */
+ int count;
+ register double *pPtr;
+
+ /*
+ * Iterate through all of the edges in the polygon, updating bestDist and
+ * intersections.
+ *
+ * TRICKY POINT: when computing intersections, include left x-coordinate
+ * of line within its range, but not y-coordinate. Otherwise if the point
+ * lies exactly below a vertex we'll count it as two intersections.
+ */
+
+ bestDist = 1.0e36;
+ intersections = 0;
+
+ for (count = numPoints, pPtr = polyPtr; count > 1; count--, pPtr += 2) {
+ double x, y, dist;
+
+ /*
+ * Compute the point on the current edge closest to the point and
+ * update the intersection count. This must be done separately for
+ * vertical edges, horizontal edges, and other edges.
+ */
+
+ if (pPtr[2] == pPtr[0]) {
+
+ /*
+ * Vertical edge.
+ */
+
+ x = pPtr[0];
+ if (pPtr[1] >= pPtr[3]) {
+ y = MIN(pPtr[1], pointPtr[1]);
+ y = MAX(y, pPtr[3]);
+ } else {
+ y = MIN(pPtr[3], pointPtr[1]);
+ y = MAX(y, pPtr[1]);
+ }
+ } else if (pPtr[3] == pPtr[1]) {
+
+ /*
+ * Horizontal edge.
+ */
+
+ y = pPtr[1];
+ if (pPtr[0] >= pPtr[2]) {
+ x = MIN(pPtr[0], pointPtr[0]);
+ x = MAX(x, pPtr[2]);
+ if ((pointPtr[1] < y) && (pointPtr[0] < pPtr[0])
+ && (pointPtr[0] >= pPtr[2])) {
+ intersections++;
+ }
+ } else {
+ x = MIN(pPtr[2], pointPtr[0]);
+ x = MAX(x, pPtr[0]);
+ if ((pointPtr[1] < y) && (pointPtr[0] < pPtr[2])
+ && (pointPtr[0] >= pPtr[0])) {
+ intersections++;
+ }
+ }
+ } else {
+ double m1, b1, m2, b2;
+ int lower; /* Non-zero means point below line. */
+
+ /*
+ * The edge is neither horizontal nor vertical. Convert the edge
+ * to a line equation of the form y = m1*x + b1. Then compute a
+ * line perpendicular to this edge but passing through the point,
+ * also in the form y = m2*x + b2.
+ */
+
+ m1 = (pPtr[3] - pPtr[1])/(pPtr[2] - pPtr[0]);
+ b1 = pPtr[1] - m1*pPtr[0];
+ m2 = -1.0/m1;
+ b2 = pointPtr[1] - m2*pointPtr[0];
+ x = (b2 - b1)/(m1 - m2);
+ y = m1*x + b1;
+ if (pPtr[0] > pPtr[2]) {
+ if (x > pPtr[0]) {
+ x = pPtr[0];
+ y = pPtr[1];
+ } else if (x < pPtr[2]) {
+ x = pPtr[2];
+ y = pPtr[3];
+ }
+ } else {
+ if (x > pPtr[2]) {
+ x = pPtr[2];
+ y = pPtr[3];
+ } else if (x < pPtr[0]) {
+ x = pPtr[0];
+ y = pPtr[1];
+ }
+ }
+ lower = (m1*pointPtr[0] + b1) > pointPtr[1];
+ if (lower && (pointPtr[0] >= MIN(pPtr[0], pPtr[2]))
+ && (pointPtr[0] < MAX(pPtr[0], pPtr[2]))) {
+ intersections++;
+ }
+ }
+
+ /*
+ * Compute the distance to the closest point, and see if that is the
+ * best distance seen so far.
+ */
+
+ dist = hypot(pointPtr[0] - x, pointPtr[1] - y);
+ if (dist < bestDist) {
+ bestDist = dist;
+ }
+ }
+
+ /*
+ * We've processed all of the points. If the number of intersections is
+ * odd, the point is inside the polygon.
+ */
+
+ if (intersections & 0x1) {
+ return 0.0;
+ }
+ return bestDist;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkPolygonToArea --
+ *
+ * Determine whether a polygon lies entirely inside, entirely outside, or
+ * overlapping a given rectangular area.
+ *
+ * Results:
+ * -1 is returned if the polygon given by polyPtr and numPoints is
+ * entirely outside the rectangle given by rectPtr. 0 is returned if the
+ * polygon overlaps the rectangle, and 1 is returned if the polygon is
+ * entirely inside the rectangle.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkPolygonToArea(
+ double *polyPtr, /* Points to an array coordinates for closed
+ * polygon: x0, y0, x1, y1, ... The polygon
+ * may be self-intersecting. */
+ int numPoints, /* Total number of points at *polyPtr. */
+ register double *rectPtr) /* Points to coords for rectangle, in the
+ * order x1, y1, x2, y2. X1 and y1 must be
+ * lower-left corner. */
+{
+ int state; /* State of all edges seen so far (-1 means
+ * outside, 1 means inside, won't ever be
+ * 0). */
+ int count;
+ register double *pPtr;
+
+ /*
+ * Iterate over all of the edges of the polygon and test them against the
+ * rectangle. Can quit as soon as the state becomes "intersecting".
+ */
+
+ state = TkLineToArea(polyPtr, polyPtr+2, rectPtr);
+ if (state == 0) {
+ return 0;
+ }
+ for (pPtr = polyPtr+2, count = numPoints-1; count >= 2;
+ pPtr += 2, count--) {
+ if (TkLineToArea(pPtr, pPtr+2, rectPtr) != state) {
+ return 0;
+ }
+ }
+
+ /*
+ * If all of the edges were inside the rectangle we're done. If all of the
+ * edges were outside, then the rectangle could still intersect the
+ * polygon (if it's entirely enclosed). Call TkPolygonToPoint to figure
+ * this out.
+ */
+
+ if (state == 1) {
+ return 1;
+ }
+ if (TkPolygonToPoint(polyPtr, numPoints, rectPtr) == 0.0) {
+ return 0;
+ }
+ return -1;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkOvalToPoint --
+ *
+ * Computes the distance from a given point to a given oval, in canvas
+ * units.
+ *
+ * Results:
+ * The return value is 0 if the point given by *pointPtr is inside the
+ * oval. If the point isn't inside the oval then the return value is
+ * approximately the distance from the point to the oval. If the oval is
+ * filled, then anywhere in the interior is considered "inside"; if the
+ * oval isn't filled, then "inside" means only the area occupied by the
+ * outline.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+double
+TkOvalToPoint(
+ double ovalPtr[4], /* Pointer to array of four coordinates (x1,
+ * y1, x2, y2) defining oval's bounding
+ * box. */
+ double width, /* Width of outline for oval. */
+ int filled, /* Non-zero means oval should be treated as
+ * filled; zero means only consider
+ * outline. */
+ double pointPtr[2]) /* Coordinates of point. */
+{
+ double xDelta, yDelta, scaledDistance, distToOutline, distToCenter;
+ double xDiam, yDiam;
+
+ /*
+ * Compute the distance between the center of the oval and the point in
+ * question, using a coordinate system where the oval has been transformed
+ * to a circle with unit radius.
+ */
+
+ xDelta = (pointPtr[0] - (ovalPtr[0] + ovalPtr[2])/2.0);
+ yDelta = (pointPtr[1] - (ovalPtr[1] + ovalPtr[3])/2.0);
+ distToCenter = hypot(xDelta, yDelta);
+ scaledDistance = hypot(xDelta / ((ovalPtr[2] + width - ovalPtr[0])/2.0),
+ yDelta / ((ovalPtr[3] + width - ovalPtr[1])/2.0));
+
+ /*
+ * If the scaled distance is greater than 1 then it means no hit. Compute
+ * the distance from the point to the edge of the circle, then scale this
+ * distance back to the original coordinate system.
+ *
+ * Note: this distance isn't completely accurate. It's only an
+ * approximation, and it can overestimate the correct distance when the
+ * oval is eccentric.
+ */
+
+ if (scaledDistance > 1.0) {
+ return (distToCenter/scaledDistance) * (scaledDistance - 1.0);
+ }
+
+ /*
+ * Scaled distance less than 1 means the point is inside the outer edge of
+ * the oval. If this is a filled oval, then we have a hit. Otherwise, do
+ * the same computation as above (scale back to original coordinate
+ * system), but also check to see if the point is within the width of the
+ * outline.
+ */
+
+ if (filled) {
+ return 0.0;
+ }
+ if (scaledDistance > 1E-10) {
+ distToOutline = (distToCenter/scaledDistance) * (1.0 - scaledDistance)
+ - width;
+ } else {
+ /*
+ * Avoid dividing by a very small number (it could cause an arithmetic
+ * overflow). This problem occurs if the point is very close to the
+ * center of the oval.
+ */
+
+ xDiam = ovalPtr[2] - ovalPtr[0];
+ yDiam = ovalPtr[3] - ovalPtr[1];
+ if (xDiam < yDiam) {
+ distToOutline = (xDiam - width)/2;
+ } else {
+ distToOutline = (yDiam - width)/2;
+ }
+ }
+
+ if (distToOutline < 0.0) {
+ return 0.0;
+ }
+ return distToOutline;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkOvalToArea --
+ *
+ * Determine whether an oval lies entirely inside, entirely outside, or
+ * overlapping a given rectangular area.
+ *
+ * Results:
+ * -1 is returned if the oval described by ovalPtr is entirely outside
+ * the rectangle given by rectPtr. 0 is returned if the oval overlaps the
+ * rectangle, and 1 is returned if the oval is entirely inside the
+ * rectangle.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkOvalToArea(
+ register double *ovalPtr, /* Points to coordinates defining the
+ * bounding rectangle for the oval: x1, y1,
+ * x2, y2. X1 must be less than x2 and y1 less
+ * than y2. */
+ register double *rectPtr) /* Points to coords for rectangle, in the
+ * order x1, y1, x2, y2. X1 and y1 must be
+ * lower-left corner. */
+{
+ double centerX, centerY, radX, radY, deltaX, deltaY;
+
+ /*
+ * First, see if oval is entirely inside rectangle or entirely outside
+ * rectangle.
+ */
+
+ if ((rectPtr[0] <= ovalPtr[0]) && (rectPtr[2] >= ovalPtr[2])
+ && (rectPtr[1] <= ovalPtr[1]) && (rectPtr[3] >= ovalPtr[3])) {
+ return 1;
+ }
+ if ((rectPtr[2] < ovalPtr[0]) || (rectPtr[0] > ovalPtr[2])
+ || (rectPtr[3] < ovalPtr[1]) || (rectPtr[1] > ovalPtr[3])) {
+ return -1;
+ }
+
+ /*
+ * Next, go through the rectangle side by side. For each side of the
+ * rectangle, find the point on the side that is closest to the oval's
+ * center, and see if that point is inside the oval. If at least one such
+ * point is inside the oval, then the rectangle intersects the oval.
+ */
+
+ centerX = (ovalPtr[0] + ovalPtr[2])/2;
+ centerY = (ovalPtr[1] + ovalPtr[3])/2;
+ radX = (ovalPtr[2] - ovalPtr[0])/2;
+ radY = (ovalPtr[3] - ovalPtr[1])/2;
+
+ deltaY = rectPtr[1] - centerY;
+ if (deltaY < 0.0) {
+ deltaY = centerY - rectPtr[3];
+ if (deltaY < 0.0) {
+ deltaY = 0;
+ }
+ }
+ deltaY /= radY;
+ deltaY *= deltaY;
+
+ /*
+ * Left side:
+ */
+
+ deltaX = (rectPtr[0] - centerX)/radX;
+ deltaX *= deltaX;
+ if ((deltaX + deltaY) <= 1.0) {
+ return 0;
+ }
+
+ /*
+ * Right side:
+ */
+
+ deltaX = (rectPtr[2] - centerX)/radX;
+ deltaX *= deltaX;
+ if ((deltaX + deltaY) <= 1.0) {
+ return 0;
+ }
+
+ deltaX = rectPtr[0] - centerX;
+ if (deltaX < 0.0) {
+ deltaX = centerX - rectPtr[2];
+ if (deltaX < 0.0) {
+ deltaX = 0;
+ }
+ }
+ deltaX /= radX;
+ deltaX *= deltaX;
+
+ /*
+ * Bottom side:
+ */
+
+ deltaY = (rectPtr[1] - centerY)/radY;
+ deltaY *= deltaY;
+ if ((deltaX + deltaY) < 1.0) {
+ return 0;
+ }
+
+ /*
+ * Top side:
+ */
+
+ deltaY = (rectPtr[3] - centerY)/radY;
+ deltaY *= deltaY;
+ if ((deltaX + deltaY) < 1.0) {
+ return 0;
+ }
+
+ return -1;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkIncludePoint --
+ *
+ * Given a point and a generic canvas item header, expand the item's
+ * bounding box if needed to include the point.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The boudn.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+void
+TkIncludePoint(
+ register Tk_Item *itemPtr, /* Item whose bounding box is being
+ * calculated. */
+ double *pointPtr) /* Address of two doubles giving x and y
+ * coordinates of point. */
+{
+ int tmp;
+
+ tmp = (int) (pointPtr[0] + 0.5);
+ if (tmp < itemPtr->x1) {
+ itemPtr->x1 = tmp;
+ }
+ if (tmp > itemPtr->x2) {
+ itemPtr->x2 = tmp;
+ }
+ tmp = (int) (pointPtr[1] + 0.5);
+ if (tmp < itemPtr->y1) {
+ itemPtr->y1 = tmp;
+ }
+ if (tmp > itemPtr->y2) {
+ itemPtr->y2 = tmp;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkBezierScreenPoints --
+ *
+ * Given four control points, create a larger set of XPoints for a Bezier
+ * curve based on the points.
+ *
+ * Results:
+ * The array at *xPointPtr gets filled in with numSteps XPoints
+ * corresponding to the Bezier spline defined by the four control points.
+ * Note: no output point is generated for the first input point, but an
+ * output point *is* generated for the last input point.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkBezierScreenPoints(
+ Tk_Canvas canvas, /* Canvas in which curve is to be drawn. */
+ double control[], /* Array of coordinates for four control
+ * points: x0, y0, x1, y1, ... x3 y3. */
+ int numSteps, /* Number of curve points to generate. */
+ register XPoint *xPointPtr) /* Where to put new points. */
+{
+ int i;
+ double u, u2, u3, t, t2, t3;
+
+ for (i = 1; i <= numSteps; i++, xPointPtr++) {
+ t = ((double) i)/((double) numSteps);
+ t2 = t*t;
+ t3 = t2*t;
+ u = 1.0 - t;
+ u2 = u*u;
+ u3 = u2*u;
+ Tk_CanvasDrawableCoords(canvas,
+ (control[0]*u3 + 3.0 * (control[2]*t*u2 + control[4]*t2*u)
+ + control[6]*t3),
+ (control[1]*u3 + 3.0 * (control[3]*t*u2 + control[5]*t2*u)
+ + control[7]*t3),
+ &xPointPtr->x, &xPointPtr->y);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkBezierPoints --
+ *
+ * Given four control points, create a larger set of points for a Bezier
+ * curve based on the points.
+ *
+ * Results:
+ * The array at *coordPtr gets filled in with 2*numSteps coordinates,
+ * which correspond to the Bezier spline defined by the four control
+ * points. Note: no output point is generated for the first input point,
+ * but an output point *is* generated for the last input point.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkBezierPoints(
+ double control[], /* Array of coordinates for four control
+ * points: x0, y0, x1, y1, ... x3 y3. */
+ int numSteps, /* Number of curve points to generate. */
+ register double *coordPtr) /* Where to put new points. */
+{
+ int i;
+ double u, u2, u3, t, t2, t3;
+
+ for (i = 1; i <= numSteps; i++, coordPtr += 2) {
+ t = ((double) i)/((double) numSteps);
+ t2 = t*t;
+ t3 = t2*t;
+ u = 1.0 - t;
+ u2 = u*u;
+ u3 = u2*u;
+ coordPtr[0] = control[0]*u3
+ + 3.0 * (control[2]*t*u2 + control[4]*t2*u) + control[6]*t3;
+ coordPtr[1] = control[1]*u3
+ + 3.0 * (control[3]*t*u2 + control[5]*t2*u) + control[7]*t3;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkMakeBezierCurve --
+ *
+ * Given a set of points, create a new set of points that fit parabolic
+ * splines to the line segments connecting the original points. Produces
+ * output points in either of two forms.
+ *
+ * Note: the name of this function should *not* be taken to mean that it
+ * interprets the input points as directly defining Bezier curves.
+ * Rather, it internally computes a Bezier curve representation of each
+ * parabolic spline segment. (These Bezier curves are then flattened to
+ * produce the points filled into the output arrays.)
+ *
+ * Results:
+ * Either or both of the xPoints or dblPoints arrays are filled in. The
+ * return value is the number of points placed in the arrays. Note: if
+ * the first and last points are the same, then a closed curve is
+ * generated.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkMakeBezierCurve(
+ Tk_Canvas canvas, /* Canvas in which curve is to be drawn. */
+ double *pointPtr, /* Array of input coordinates: x0, y0, x1, y1,
+ * etc.. */
+ int numPoints, /* Number of points at pointPtr. */
+ int numSteps, /* Number of steps to use for each spline
+ * segments (determines smoothness of
+ * curve). */
+ XPoint xPoints[], /* Array of XPoints to fill in (e.g. for
+ * display). NULL means don't fill in any
+ * XPoints. */
+ double dblPoints[]) /* Array of points to fill in as doubles, in
+ * the form x0, y0, x1, y1, .... NULL means
+ * don't fill in anything in this form. Caller
+ * must make sure that this array has enough
+ * space. */
+{
+ int closed, outputPoints, i;
+ int numCoords = numPoints*2;
+ double control[8];
+
+ /*
+ * If the curve is a closed one then generate a special spline that spans
+ * the last points and the first ones. Otherwise just put the first point
+ * into the output.
+ */
+
+ if (!pointPtr) {
+ /*
+ * Of pointPtr == NULL, this function returns an upper limit of the
+ * array size to store the coordinates. This can be used to allocate
+ * storage, before the actual coordinates are calculated.
+ */
+
+ return 1 + numPoints * numSteps;
+ }
+
+ outputPoints = 0;
+ if ((pointPtr[0] == pointPtr[numCoords-2])
+ && (pointPtr[1] == pointPtr[numCoords-1])) {
+ closed = 1;
+ control[0] = 0.5*pointPtr[numCoords-4] + 0.5*pointPtr[0];
+ control[1] = 0.5*pointPtr[numCoords-3] + 0.5*pointPtr[1];
+ control[2] = 0.167*pointPtr[numCoords-4] + 0.833*pointPtr[0];
+ control[3] = 0.167*pointPtr[numCoords-3] + 0.833*pointPtr[1];
+ control[4] = 0.833*pointPtr[0] + 0.167*pointPtr[2];
+ control[5] = 0.833*pointPtr[1] + 0.167*pointPtr[3];
+ control[6] = 0.5*pointPtr[0] + 0.5*pointPtr[2];
+ control[7] = 0.5*pointPtr[1] + 0.5*pointPtr[3];
+ if (xPoints != NULL) {
+ Tk_CanvasDrawableCoords(canvas, control[0], control[1],
+ &xPoints->x, &xPoints->y);
+ TkBezierScreenPoints(canvas, control, numSteps, xPoints+1);
+ xPoints += numSteps+1;
+ }
+ if (dblPoints != NULL) {
+ dblPoints[0] = control[0];
+ dblPoints[1] = control[1];
+ TkBezierPoints(control, numSteps, dblPoints+2);
+ dblPoints += 2*(numSteps+1);
+ }
+ outputPoints += numSteps+1;
+ } else {
+ closed = 0;
+ if (xPoints != NULL) {
+ Tk_CanvasDrawableCoords(canvas, pointPtr[0], pointPtr[1],
+ &xPoints->x, &xPoints->y);
+ xPoints += 1;
+ }
+ if (dblPoints != NULL) {
+ dblPoints[0] = pointPtr[0];
+ dblPoints[1] = pointPtr[1];
+ dblPoints += 2;
+ }
+ outputPoints += 1;
+ }
+
+ for (i = 2; i < numPoints; i++, pointPtr += 2) {
+ /*
+ * Set up the first two control points. This is done differently for
+ * the first spline of an open curve than for other cases.
+ */
+
+ if ((i == 2) && !closed) {
+ control[0] = pointPtr[0];
+ control[1] = pointPtr[1];
+ control[2] = 0.333*pointPtr[0] + 0.667*pointPtr[2];
+ control[3] = 0.333*pointPtr[1] + 0.667*pointPtr[3];
+ } else {
+ control[0] = 0.5*pointPtr[0] + 0.5*pointPtr[2];
+ control[1] = 0.5*pointPtr[1] + 0.5*pointPtr[3];
+ control[2] = 0.167*pointPtr[0] + 0.833*pointPtr[2];
+ control[3] = 0.167*pointPtr[1] + 0.833*pointPtr[3];
+ }
+
+ /*
+ * Set up the last two control points. This is done differently for
+ * the last spline of an open curve than for other cases.
+ */
+
+ if ((i == (numPoints-1)) && !closed) {
+ control[4] = .667*pointPtr[2] + .333*pointPtr[4];
+ control[5] = .667*pointPtr[3] + .333*pointPtr[5];
+ control[6] = pointPtr[4];
+ control[7] = pointPtr[5];
+ } else {
+ control[4] = .833*pointPtr[2] + .167*pointPtr[4];
+ control[5] = .833*pointPtr[3] + .167*pointPtr[5];
+ control[6] = 0.5*pointPtr[2] + 0.5*pointPtr[4];
+ control[7] = 0.5*pointPtr[3] + 0.5*pointPtr[5];
+ }
+
+ /*
+ * If the first two points coincide, or if the last two points
+ * coincide, then generate a single straight-line segment by
+ * outputting the last control point.
+ */
+
+ if (((pointPtr[0] == pointPtr[2]) && (pointPtr[1] == pointPtr[3]))
+ || ((pointPtr[2] == pointPtr[4])
+ && (pointPtr[3] == pointPtr[5]))) {
+ if (xPoints != NULL) {
+ Tk_CanvasDrawableCoords(canvas, control[6], control[7],
+ &xPoints[0].x, &xPoints[0].y);
+ xPoints++;
+ }
+ if (dblPoints != NULL) {
+ dblPoints[0] = control[6];
+ dblPoints[1] = control[7];
+ dblPoints += 2;
+ }
+ outputPoints += 1;
+ continue;
+ }
+
+ /*
+ * Generate a Bezier spline using the control points.
+ */
+
+
+ if (xPoints != NULL) {
+ TkBezierScreenPoints(canvas, control, numSteps, xPoints);
+ xPoints += numSteps;
+ }
+ if (dblPoints != NULL) {
+ TkBezierPoints(control, numSteps, dblPoints);
+ dblPoints += 2*numSteps;
+ }
+ outputPoints += numSteps;
+ }
+ return outputPoints;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkMakeRawCurve --
+ *
+ * Interpret the given set of points as the raw knots and control points
+ * defining a sequence of cubic Bezier curves. Create a new set of points
+ * that fit these Bezier curves. Output points are produced in either of
+ * two forms.
+ *
+ * Results:
+ * Either or both of the xPoints or dblPoints arrays are filled in. The
+ * return value is the number of points placed in the arrays.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkMakeRawCurve(
+ Tk_Canvas canvas, /* Canvas in which curve is to be drawn. */
+ double *pointPtr, /* Array of input coordinates: x0, y0, x1, y1,
+ * etc.. */
+ int numPoints, /* Number of points at pointPtr. */
+ int numSteps, /* Number of steps to use for each curve
+ * segment (determines smoothness of
+ * curve). */
+ XPoint xPoints[], /* Array of XPoints to fill in (e.g. for
+ * display). NULL means don't fill in any
+ * XPoints. */
+ double dblPoints[]) /* Array of points to fill in as doubles, in
+ * the form x0, y0, x1, y1, .... NULL means
+ * don't fill in anything in this form.
+ * Caller must make sure that this array has
+ * enough space. */
+{
+ int outputPoints, i;
+ int numSegments = (numPoints+1)/3;
+ double *segPtr;
+
+ /*
+ * The input describes a curve with s Bezier curve segments if there are
+ * 3s+1, 3s, or 3s-1 input points. In the last two cases, 1 or 2 initial
+ * points from the first curve segment are reused as defining points also
+ * for the last curve segment. In the case of 3s input points, this will
+ * automatically close the curve.
+ */
+
+ if (!pointPtr) {
+ /*
+ * If pointPtr == NULL, this function returns an upper limit of the
+ * array size to store the coordinates. This can be used to allocate
+ * storage, before the actual coordinates are calculated.
+ */
+
+ return 1 + numSegments * numSteps;
+ }
+
+ outputPoints = 0;
+ if (xPoints != NULL) {
+ Tk_CanvasDrawableCoords(canvas, pointPtr[0], pointPtr[1],
+ &xPoints->x, &xPoints->y);
+ xPoints += 1;
+ }
+ if (dblPoints != NULL) {
+ dblPoints[0] = pointPtr[0];
+ dblPoints[1] = pointPtr[1];
+ dblPoints += 2;
+ }
+ outputPoints += 1;
+
+ /*
+ * The next loop handles all curve segments except one that overlaps the
+ * end of the list of coordinates.
+ */
+
+ for (i=numPoints,segPtr=pointPtr ; i>=4 ; i-=3,segPtr+=6) {
+ if (segPtr[0]==segPtr[2] && segPtr[1]==segPtr[3] &&
+ segPtr[4]==segPtr[6] && segPtr[5]==segPtr[7]) {
+ /*
+ * The control points on this segment are equal to their
+ * neighbouring knots, so this segment is just a straight line. A
+ * single point is sufficient.
+ */
+
+ if (xPoints != NULL) {
+ Tk_CanvasDrawableCoords(canvas, segPtr[6], segPtr[7],
+ &xPoints->x, &xPoints->y);
+ xPoints += 1;
+ }
+ if (dblPoints != NULL) {
+ dblPoints[0] = segPtr[6];
+ dblPoints[1] = segPtr[7];
+ dblPoints += 2;
+ }
+ outputPoints += 1;
+ } else {
+ /*
+ * This is a generic Bezier curve segment.
+ */
+
+ if (xPoints != NULL) {
+ TkBezierScreenPoints(canvas, segPtr, numSteps, xPoints);
+ xPoints += numSteps;
+ }
+ if (dblPoints != NULL) {
+ TkBezierPoints(segPtr, numSteps, dblPoints);
+ dblPoints += 2*numSteps;
+ }
+ outputPoints += numSteps;
+ }
+ }
+
+ /*
+ * If at this point i>1, then there is some point which has not yet been
+ * used. Make another curve segment.
+ */
+
+ if (i > 1) {
+ int j;
+ double control[8];
+
+ /*
+ * Copy the relevant coordinates to control[], so that it can be
+ * passed as a unit to e.g. TkBezierPoints.
+ */
+
+ for (j=0; j<2*i; j++) {
+ control[j] = segPtr[j];
+ }
+ for (; j<8; j++) {
+ control[j] = pointPtr[j-2*i];
+ }
+
+ /*
+ * Then we just do the same things as above.
+ */
+
+ if (control[0]==control[2] && control[1]==control[3] &&
+ control[4]==control[6] && control[5]==control[7]) {
+ /*
+ * The control points on this segment are equal to their
+ * neighbouring knots, so this segment is just a straight line. A
+ * single point is sufficient.
+ */
+
+ if (xPoints != NULL) {
+ Tk_CanvasDrawableCoords(canvas, control[6], control[7],
+ &xPoints->x, &xPoints->y);
+ xPoints += 1;
+ }
+ if (dblPoints != NULL) {
+ dblPoints[0] = control[6];
+ dblPoints[1] = control[7];
+ dblPoints += 2;
+ }
+ outputPoints += 1;
+ } else {
+ /*
+ * This is a generic Bezier curve segment.
+ */
+
+ if (xPoints != NULL) {
+ TkBezierScreenPoints(canvas, control, numSteps, xPoints);
+ xPoints += numSteps;
+ }
+ if (dblPoints != NULL) {
+ TkBezierPoints(control, numSteps, dblPoints);
+ dblPoints += 2*numSteps;
+ }
+ outputPoints += numSteps;
+ }
+ }
+
+ return outputPoints;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkMakeBezierPostscript --
+ *
+ * This function generates Postscript commands that create a path
+ * corresponding to a given Bezier curve.
+ *
+ * Results:
+ * None. Postscript commands to generate the path are appended to the
+ * interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkMakeBezierPostscript(
+ Tcl_Interp *interp, /* Interpreter in whose result the Postscript
+ * is to be stored. */
+ Tk_Canvas canvas, /* Canvas widget for which the Postscript is
+ * being generated. */
+ double *pointPtr, /* Array of input coordinates: x0, y0, x1, y1,
+ * etc.. */
+ int numPoints) /* Number of points at pointPtr. */
+{
+ int closed, i;
+ int numCoords = numPoints*2;
+ double control[8];
+ Tcl_Obj *psObj;
+
+ /*
+ * If the curve is a closed one then generate a special spline that spans
+ * the last points and the first ones. Otherwise just put the first point
+ * into the path.
+ */
+
+ if ((pointPtr[0] == pointPtr[numCoords-2])
+ && (pointPtr[1] == pointPtr[numCoords-1])) {
+ closed = 1;
+ control[0] = 0.5*pointPtr[numCoords-4] + 0.5*pointPtr[0];
+ control[1] = 0.5*pointPtr[numCoords-3] + 0.5*pointPtr[1];
+ control[2] = 0.167*pointPtr[numCoords-4] + 0.833*pointPtr[0];
+ control[3] = 0.167*pointPtr[numCoords-3] + 0.833*pointPtr[1];
+ control[4] = 0.833*pointPtr[0] + 0.167*pointPtr[2];
+ control[5] = 0.833*pointPtr[1] + 0.167*pointPtr[3];
+ control[6] = 0.5*pointPtr[0] + 0.5*pointPtr[2];
+ control[7] = 0.5*pointPtr[1] + 0.5*pointPtr[3];
+ psObj = Tcl_ObjPrintf(
+ "%.15g %.15g moveto\n"
+ "%.15g %.15g %.15g %.15g %.15g %.15g curveto\n",
+ control[0], Tk_CanvasPsY(canvas, control[1]),
+ control[2], Tk_CanvasPsY(canvas, control[3]),
+ control[4], Tk_CanvasPsY(canvas, control[5]),
+ control[6], Tk_CanvasPsY(canvas, control[7]));
+ } else {
+ closed = 0;
+ control[6] = pointPtr[0];
+ control[7] = pointPtr[1];
+ psObj = Tcl_ObjPrintf("%.15g %.15g moveto\n",
+ control[6], Tk_CanvasPsY(canvas, control[7]));
+ }
+
+ /*
+ * Cycle through all the remaining points in the curve, generating a curve
+ * section for each vertex in the linear path.
+ */
+
+ for (i = numPoints-2, pointPtr += 2; i > 0; i--, pointPtr += 2) {
+ control[2] = 0.333*control[6] + 0.667*pointPtr[0];
+ control[3] = 0.333*control[7] + 0.667*pointPtr[1];
+
+ /*
+ * Set up the last two control points. This is done differently for
+ * the last spline of an open curve than for other cases.
+ */
+
+ if ((i == 1) && !closed) {
+ control[6] = pointPtr[2];
+ control[7] = pointPtr[3];
+ } else {
+ control[6] = 0.5*pointPtr[0] + 0.5*pointPtr[2];
+ control[7] = 0.5*pointPtr[1] + 0.5*pointPtr[3];
+ }
+ control[4] = 0.333*control[6] + 0.667*pointPtr[0];
+ control[5] = 0.333*control[7] + 0.667*pointPtr[1];
+
+ Tcl_AppendPrintfToObj(psObj,
+ "%.15g %.15g %.15g %.15g %.15g %.15g curveto\n",
+ control[2], Tk_CanvasPsY(canvas, control[3]),
+ control[4], Tk_CanvasPsY(canvas, control[5]),
+ control[6], Tk_CanvasPsY(canvas, control[7]));
+ }
+
+ Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj);
+ Tcl_DecrRefCount(psObj);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkMakeRawCurvePostscript --
+ *
+ * This function interprets the input points as the raw knot and control
+ * points for a curve composed of Bezier curve segments, just like
+ * TkMakeRawCurve. It generates Postscript commands that create a path
+ * corresponding to this given curve.
+ *
+ * Results:
+ * None. Postscript commands to generate the path are appended to the
+ * interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkMakeRawCurvePostscript(
+ Tcl_Interp *interp, /* Interpreter in whose result the Postscript
+ * is to be stored. */
+ Tk_Canvas canvas, /* Canvas widget for which the Postscript is
+ * being generated. */
+ double *pointPtr, /* Array of input coordinates: x0, y0, x1, y1,
+ * etc.. */
+ int numPoints) /* Number of points at pointPtr. */
+{
+ int i;
+ double *segPtr;
+ Tcl_Obj *psObj;
+
+ /*
+ * Put the first point into the path.
+ */
+
+ psObj = Tcl_ObjPrintf("%.15g %.15g moveto\n",
+ pointPtr[0], Tk_CanvasPsY(canvas, pointPtr[1]));
+
+ /*
+ * Loop through all the remaining points in the curve, generating a
+ * straight line or curve section for every three of them.
+ */
+
+ for (i=numPoints-1,segPtr=pointPtr ; i>=3 ; i-=3,segPtr+=6) {
+ if (segPtr[0]==segPtr[2] && segPtr[1]==segPtr[3] &&
+ segPtr[4]==segPtr[6] && segPtr[5]==segPtr[7]) {
+ /*
+ * The control points on this segment are equal to their
+ * neighbouring knots, so this segment is just a straight line.
+ */
+
+ Tcl_AppendPrintfToObj(psObj, "%.15g %.15g lineto\n",
+ segPtr[6], Tk_CanvasPsY(canvas, segPtr[7]));
+ } else {
+ /*
+ * This is a generic Bezier curve segment.
+ */
+
+ Tcl_AppendPrintfToObj(psObj,
+ "%.15g %.15g %.15g %.15g %.15g %.15g curveto\n",
+ segPtr[2], Tk_CanvasPsY(canvas, segPtr[3]),
+ segPtr[4], Tk_CanvasPsY(canvas, segPtr[5]),
+ segPtr[6], Tk_CanvasPsY(canvas, segPtr[7]));
+ }
+ }
+
+ /*
+ * If there are any points left that haven't been used, then build the
+ * last segment and generate Postscript in the same way for that.
+ */
+
+ if (i > 0) {
+ int j;
+ double control[8];
+
+ for (j=0; j<2*i+2; j++) {
+ control[j] = segPtr[j];
+ }
+ for (; j<8; j++) {
+ control[j] = pointPtr[j-2*i-2];
+ }
+
+ if (control[0]==control[2] && control[1]==control[3] &&
+ control[4]==control[6] && control[5]==control[7]) {
+ /*
+ * Straight line.
+ */
+
+ Tcl_AppendPrintfToObj(psObj, "%.15g %.15g lineto\n",
+ control[6], Tk_CanvasPsY(canvas, control[7]));
+ } else {
+ /*
+ * Bezier curve segment.
+ */
+
+ Tcl_AppendPrintfToObj(psObj,
+ "%.15g %.15g %.15g %.15g %.15g %.15g curveto\n",
+ control[2], Tk_CanvasPsY(canvas, control[3]),
+ control[4], Tk_CanvasPsY(canvas, control[5]),
+ control[6], Tk_CanvasPsY(canvas, control[7]));
+ }
+ }
+
+ Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj);
+ Tcl_DecrRefCount(psObj);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkGetMiterPoints --
+ *
+ * Given three points forming an angle, compute the coordinates of the
+ * inside and outside points of the mitered corner formed by a line of a
+ * given width at that angle.
+ *
+ * Results:
+ * If the angle formed by the three points is less than 11 degrees then 0
+ * is returned and m1 and m2 aren't modified. Otherwise 1 is returned and
+ * the points at m1 and m2 are filled in with the positions of the points
+ * of the mitered corner.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkGetMiterPoints(
+ double p1[], /* Points to x- and y-coordinates of point
+ * before vertex. */
+ double p2[], /* Points to x- and y-coordinates of vertex
+ * for mitered joint. */
+ double p3[], /* Points to x- and y-coordinates of point
+ * after vertex. */
+ double width, /* Width of line. */
+ double m1[], /* Points to place to put "left" vertex point
+ * (see as you face from p1 to p2). */
+ double m2[]) /* Points to place to put "right" vertex
+ * point. */
+{
+ double theta1; /* Angle of segment p2-p1. */
+ double theta2; /* Angle of segment p2-p3. */
+ double theta; /* Angle between line segments (angle of
+ * joint). */
+ double theta3; /* Angle that bisects theta1 and theta2 and
+ * points to m1. */
+ double dist; /* Distance of miter points from p2. */
+ double deltaX, deltaY; /* X and y offsets cooresponding to dist
+ * (fudge factors for bounding box). */
+ double p1x, p1y, p2x, p2y, p3x, p3y;
+#ifndef _MSC_VER
+ static const double elevenDegrees = (11.0*2.0*PI)/360.0;
+#else /* msvc8 with -fp:strict requires it this way */
+ static const double elevenDegrees = 0.19198621771937624;
+#endif
+
+ /*
+ * Round the coordinates to integers to mimic what happens when the line
+ * segments are displayed; without this code, the bounding box of a
+ * mitered line can be miscomputed greatly.
+ */
+
+ p1x = floor(p1[0]+0.5);
+ p1y = floor(p1[1]+0.5);
+ p2x = floor(p2[0]+0.5);
+ p2y = floor(p2[1]+0.5);
+ p3x = floor(p3[0]+0.5);
+ p3y = floor(p3[1]+0.5);
+
+ if (p2y == p1y) {
+ theta1 = (p2x < p1x) ? 0 : PI;
+ } else if (p2x == p1x) {
+ theta1 = (p2y < p1y) ? PI/2.0 : -PI/2.0;
+ } else {
+ theta1 = atan2(p1y - p2y, p1x - p2x);
+ }
+
+ if (p3y == p2y) {
+ theta2 = (p3x > p2x) ? 0 : PI;
+ } else if (p3x == p2x) {
+ theta2 = (p3y > p2y) ? PI/2.0 : -PI/2.0;
+ } else {
+ theta2 = atan2(p3y - p2y, p3x - p2x);
+ }
+
+ theta = theta1 - theta2;
+ if (theta > PI) {
+ theta -= 2*PI;
+ } else if (theta < -PI) {
+ theta += 2*PI;
+ }
+
+ if ((theta < elevenDegrees) && (theta > -elevenDegrees)) {
+ return 0;
+ }
+
+ dist = 0.5*width/sin(0.5*theta);
+ if (dist < 0.0) {
+ dist = -dist;
+ }
+
+ /*
+ * Compute theta3 (make sure that it points to the left when looking from
+ * p1 to p2).
+ */
+
+ theta3 = (theta1 + theta2)/2.0;
+ if (sin(theta3 - (theta1 + PI)) < 0.0) {
+ theta3 += PI;
+ }
+ deltaX = dist*cos(theta3);
+ m1[0] = p2x + deltaX;
+ m2[0] = p2x - deltaX;
+ deltaY = dist*sin(theta3);
+ m1[1] = p2y + deltaY;
+ m2[1] = p2y - deltaY;
+
+ return 1;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkGetButtPoints --
+ *
+ * Given two points forming a line segment, compute the coordinates of
+ * two endpoints of a rectangle formed by bloating the line segment until
+ * it is width units wide.
+ *
+ * Results:
+ * There is no return value. M1 and m2 are filled in to correspond to m1
+ * and m2 in the diagram below:
+ *
+ * ----------------* m1
+ * |
+ * p1 *---------------* p2
+ * |
+ * ----------------* m2
+ *
+ * M1 and m2 will be W units apart, with p2 centered between them and
+ * m1-m2 perpendicular to p1-p2. However, if "project" is true then m1
+ * and m2 will be as follows:
+ *
+ * -------------------* m1
+ * p2 |
+ * p1 *---------------* |
+ * |
+ * -------------------* m2
+ *
+ * In this case p2 will be width/2 units from the segment m1-m2.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkGetButtPoints(
+ double p1[], /* Points to x- and y-coordinates of point
+ * before vertex. */
+ double p2[], /* Points to x- and y-coordinates of vertex
+ * for mitered joint. */
+ double width, /* Width of line. */
+ int project, /* Non-zero means project p2 by an additional
+ * width/2 before computing m1 and m2. */
+ double m1[], /* Points to place to put "left" result point,
+ * as you face from p1 to p2. */
+ double m2[]) /* Points to place to put "right" result
+ * point. */
+{
+ double length; /* Length of p1-p2 segment. */
+ double deltaX, deltaY; /* Increments in coords. */
+
+ width *= 0.5;
+ length = hypot(p2[0] - p1[0], p2[1] - p1[1]);
+ if (length == 0.0) {
+ m1[0] = m2[0] = p2[0];
+ m1[1] = m2[1] = p2[1];
+ } else {
+ deltaX = -width * (p2[1] - p1[1]) / length;
+ deltaY = width * (p2[0] - p1[0]) / length;
+ m1[0] = p2[0] + deltaX;
+ m2[0] = p2[0] - deltaX;
+ m1[1] = p2[1] + deltaY;
+ m2[1] = p2[1] - deltaY;
+ if (project) {
+ m1[0] += deltaY;
+ m2[0] += deltaY;
+ m1[1] -= deltaX;
+ m2[1] -= deltaX;
+ }
+ }
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkUndo.c b/tk8.6/generic/tkUndo.c
new file mode 100644
index 0000000..c66905d
--- /dev/null
+++ b/tk8.6/generic/tkUndo.c
@@ -0,0 +1,736 @@
+/*
+ * tkUndo.c --
+ *
+ * This module provides the implementation of an undo stack.
+ *
+ * Copyright (c) 2002 by Ludwig Callewaert.
+ * Copyright (c) 2003-2004 by Vincent Darley.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkInt.h"
+#include "tkUndo.h"
+
+static int EvaluateActionList(Tcl_Interp *interp,
+ TkUndoSubAtom *action);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkUndoPushStack --
+ *
+ * Push elem on the stack identified by stack.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkUndoPushStack(
+ TkUndoAtom **stack,
+ TkUndoAtom *elem)
+{
+ elem->next = *stack;
+ *stack = elem;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkUndoPopStack --
+ *
+ * Remove and return the top element from the stack identified by stack.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkUndoAtom *
+TkUndoPopStack(
+ TkUndoAtom **stack)
+{
+ TkUndoAtom *elem = NULL;
+
+ if (*stack != NULL) {
+ elem = *stack;
+ *stack = elem->next;
+ }
+ return elem;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkUndoInsertSeparator --
+ *
+ * Insert a separator on the stack, indicating a border for an undo/redo
+ * chunk.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkUndoInsertSeparator(
+ TkUndoAtom **stack)
+{
+ TkUndoAtom *separator;
+
+ if (*stack!=NULL && (*stack)->type!=TK_UNDO_SEPARATOR) {
+ separator = ckalloc(sizeof(TkUndoAtom));
+ separator->type = TK_UNDO_SEPARATOR;
+ TkUndoPushStack(stack,separator);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkUndoClearStack --
+ *
+ * Clear an entire undo or redo stack and destroy all elements in it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkUndoClearStack(
+ TkUndoAtom **stack) /* An Undo or Redo stack */
+{
+ TkUndoAtom *elem;
+
+ while ((elem = TkUndoPopStack(stack)) != NULL) {
+ if (elem->type != TK_UNDO_SEPARATOR) {
+ TkUndoSubAtom *sub;
+
+ sub = elem->apply;
+ while (sub != NULL) {
+ TkUndoSubAtom *next = sub->next;
+
+ if (sub->action != NULL) {
+ Tcl_DecrRefCount(sub->action);
+ }
+ ckfree(sub);
+ sub = next;
+ }
+
+ sub = elem->revert;
+ while (sub != NULL) {
+ TkUndoSubAtom *next = sub->next;
+
+ if (sub->action != NULL) {
+ Tcl_DecrRefCount(sub->action);
+ }
+ ckfree(sub);
+ sub = next;
+ }
+ }
+ ckfree(elem);
+ }
+ *stack = NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkUndoPushAction --
+ *
+ * Push a new elem on the stack identified by stack. Action and revert
+ * are given through Tcl_Obj's to which we will retain a reference. (So
+ * they can be passed in with a zero refCount if desired).
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkUndoPushAction(
+ TkUndoRedoStack *stack, /* An Undo or Redo stack */
+ TkUndoSubAtom *apply,
+ TkUndoSubAtom *revert)
+{
+ TkUndoAtom *atom;
+
+ atom = ckalloc(sizeof(TkUndoAtom));
+ atom->type = TK_UNDO_ACTION;
+ atom->apply = apply;
+ atom->revert = revert;
+
+ TkUndoPushStack(&stack->undoStack, atom);
+ TkUndoClearStack(&stack->redoStack);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkUndoMakeCmdSubAtom --
+ *
+ * Create a new undo/redo step which must later be place into an undo
+ * stack with TkUndoPushAction. This sub-atom, if evaluated, will take
+ * the given command (if non-NULL), find its full Tcl command string, and
+ * then evaluate that command with the list elements of 'actionScript'
+ * appended.
+ *
+ * If 'subAtomList' is non-NULL, the newly created sub-atom is added onto
+ * the end of the linked list of which 'subAtomList' is a part. This
+ * makes it easy to build up a sequence of actions which will be pushed
+ * in one step.
+ *
+ * Note: if the undo stack can persist for longer than the Tcl_Command
+ * provided, the stack will cause crashes when actions are evaluated. In
+ * this case the 'command' argument should not be used. This is the case
+ * with peer text widgets, for example.
+ *
+ * Results:
+ * The newly created subAtom is returned. It must be passed to
+ * TkUndoPushAction otherwise a memory leak will result.
+ *
+ * Side effects:
+ * A refCount is retained on 'actionScript'.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkUndoSubAtom *
+TkUndoMakeCmdSubAtom(
+ Tcl_Command command, /* Tcl command token for actions, may be NULL
+ * if not needed. */
+ Tcl_Obj *actionScript, /* The script to append to the command to
+ * perform the action (may be NULL if the
+ * command is not-null). */
+ TkUndoSubAtom *subAtomList) /* Add to the end of this list of actions if
+ * non-NULL */
+{
+ TkUndoSubAtom *atom;
+
+ if (command == NULL && actionScript == NULL) {
+ Tcl_Panic("NULL command and actionScript in TkUndoMakeCmdSubAtom");
+ }
+
+ atom = ckalloc(sizeof(TkUndoSubAtom));
+ atom->command = command;
+ atom->funcPtr = NULL;
+ atom->clientData = NULL;
+ atom->next = NULL;
+ atom->action = actionScript;
+ if (atom->action != NULL) {
+ Tcl_IncrRefCount(atom->action);
+ }
+
+ if (subAtomList != NULL) {
+ while (subAtomList->next != NULL) {
+ subAtomList = subAtomList->next;
+ }
+ subAtomList->next = atom;
+ }
+ return atom;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkUndoMakeSubAtom --
+ *
+ * Create a new undo/redo step which must later be place into an undo
+ * stack with TkUndoPushAction. This sub-atom, if evaluated, will take
+ * the given C-funcPtr (which must be non-NULL), and call it with three
+ * arguments: the undo stack's 'interp', the 'clientData' given and the
+ * 'actionScript'. The callback should return a standard Tcl return code
+ * (TCL_OK on success).
+ *
+ * If 'subAtomList' is non-NULL, the newly created sub-atom is added onto
+ * the end of the linked list of which 'subAtomList' is a part. This
+ * makes it easy to build up a sequence of actions which will be pushed
+ * in one step.
+ *
+ * Results:
+ * The newly created subAtom is returned. It must be passed to
+ * TkUndoPushAction otherwise a memory leak will result.
+ *
+ * Side effects:
+ * A refCount is retained on 'actionScript'.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkUndoSubAtom *
+TkUndoMakeSubAtom(
+ TkUndoProc *funcPtr, /* Callback function to perform the
+ * undo/redo. */
+ ClientData clientData, /* Data to pass to the callback function. */
+ Tcl_Obj *actionScript, /* Additional Tcl data to pass to the callback
+ * function (may be NULL). */
+ TkUndoSubAtom *subAtomList) /* Add to the end of this list of actions if
+ * non-NULL */
+{
+ TkUndoSubAtom *atom;
+
+ if (funcPtr == NULL) {
+ Tcl_Panic("NULL funcPtr in TkUndoMakeSubAtom");
+ }
+
+ atom = ckalloc(sizeof(TkUndoSubAtom));
+ atom->command = NULL;
+ atom->funcPtr = funcPtr;
+ atom->clientData = clientData;
+ atom->next = NULL;
+ atom->action = actionScript;
+ if (atom->action != NULL) {
+ Tcl_IncrRefCount(atom->action);
+ }
+
+ if (subAtomList != NULL) {
+ while (subAtomList->next != NULL) {
+ subAtomList = subAtomList->next;
+ }
+ subAtomList->next = atom;
+ }
+ return atom;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkUndoInitStack --
+ *
+ * Initialize a new undo/redo stack.
+ *
+ * Results:
+ * An Undo/Redo stack pointer.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkUndoRedoStack *
+TkUndoInitStack(
+ Tcl_Interp *interp, /* The interpreter */
+ int maxdepth) /* The maximum stack depth */
+{
+ TkUndoRedoStack *stack; /* An Undo/Redo stack */
+
+ stack = ckalloc(sizeof(TkUndoRedoStack));
+ stack->undoStack = NULL;
+ stack->redoStack = NULL;
+ stack->interp = interp;
+ stack->maxdepth = maxdepth;
+ stack->depth = 0;
+ return stack;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkUndoSetMaxDepth --
+ *
+ * Set the maximum depth of stack.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * May delete elements from the stack if the new maximum depth is smaller
+ * than the number of elements previously in the stack.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkUndoSetMaxDepth(
+ TkUndoRedoStack *stack, /* An Undo/Redo stack */
+ int maxdepth) /* The maximum stack depth */
+{
+ stack->maxdepth = maxdepth;
+
+ if (stack->maxdepth>0 && stack->depth>stack->maxdepth) {
+ TkUndoAtom *elem, *prevelem;
+ int sepNumber = 0;
+
+ /*
+ * Maximum stack depth exceeded. We have to remove the last compound
+ * elements on the stack.
+ */
+
+ elem = stack->undoStack;
+ prevelem = NULL;
+ while ((elem != NULL) && (sepNumber <= stack->maxdepth)) {
+ if (elem->type == TK_UNDO_SEPARATOR) {
+ sepNumber++;
+ }
+ prevelem = elem;
+ elem = elem->next;
+ }
+ CLANG_ASSERT(prevelem);
+ prevelem->next = NULL;
+ while (elem != NULL) {
+ prevelem = elem;
+ if (elem->type != TK_UNDO_SEPARATOR) {
+ TkUndoSubAtom *sub = elem->apply;
+ while (sub != NULL) {
+ TkUndoSubAtom *next = sub->next;
+
+ if (sub->action != NULL) {
+ Tcl_DecrRefCount(sub->action);
+ }
+ ckfree(sub);
+ sub = next;
+ }
+ sub = elem->revert;
+ while (sub != NULL) {
+ TkUndoSubAtom *next = sub->next;
+
+ if (sub->action != NULL) {
+ Tcl_DecrRefCount(sub->action);
+ }
+ ckfree(sub);
+ sub = next;
+ }
+ }
+ elem = elem->next;
+ ckfree(prevelem);
+ }
+ stack->depth = stack->maxdepth;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkUndoClearStacks --
+ *
+ * Clear both the undo and redo stack.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkUndoClearStacks(
+ TkUndoRedoStack *stack) /* An Undo/Redo stack */
+{
+ TkUndoClearStack(&stack->undoStack);
+ TkUndoClearStack(&stack->redoStack);
+ stack->depth = 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkUndoFreeStack
+ *
+ * Clear both the undo and redo stack and free the memory allocated to
+ * the u/r stack pointer.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkUndoFreeStack(
+ TkUndoRedoStack *stack) /* An Undo/Redo stack */
+{
+ TkUndoClearStacks(stack);
+ ckfree(stack);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkUndoCanRedo --
+ *
+ * Returns true if redo is possible, i.e. if the redo stack is not empty.
+ *
+ * Results:
+ * A boolean.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkUndoCanRedo(
+ TkUndoRedoStack *stack) /* An Undo/Redo stack */
+{
+ return stack->redoStack != NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkUndoCanUndo --
+ *
+ * Returns true if undo is possible, i.e. if the undo stack is not empty.
+ *
+ * Results:
+ * A boolean.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkUndoCanUndo(
+ TkUndoRedoStack *stack) /* An Undo/Redo stack */
+{
+ return stack->undoStack != NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkUndoInsertUndoSeparator --
+ *
+ * Insert a separator on the undo stack, indicating a border for an
+ * undo/redo chunk.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkUndoInsertUndoSeparator(
+ TkUndoRedoStack *stack)
+{
+ if (TkUndoInsertSeparator(&stack->undoStack)) {
+ stack->depth++;
+ TkUndoSetMaxDepth(stack, stack->maxdepth);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkUndoRevert --
+ *
+ * Undo a compound action on the stack.
+ *
+ * Results:
+ * A Tcl status code
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkUndoRevert(
+ TkUndoRedoStack *stack)
+{
+ TkUndoAtom *elem;
+
+ /*
+ * Insert a separator on the undo and the redo stack.
+ */
+
+ TkUndoInsertUndoSeparator(stack);
+ TkUndoInsertSeparator(&stack->redoStack);
+
+ /*
+ * Pop and skip the first separator if there is one.
+ */
+
+ elem = TkUndoPopStack(&stack->undoStack);
+ if (elem == NULL) {
+ return TCL_ERROR;
+ }
+
+ if (elem->type == TK_UNDO_SEPARATOR) {
+ ckfree(elem);
+ elem = TkUndoPopStack(&stack->undoStack);
+ }
+
+ while (elem != NULL && elem->type != TK_UNDO_SEPARATOR) {
+ /*
+ * Note that we currently ignore errors thrown here.
+ */
+
+ EvaluateActionList(stack->interp, elem->revert);
+
+ TkUndoPushStack(&stack->redoStack, elem);
+ elem = TkUndoPopStack(&stack->undoStack);
+ }
+
+ /*
+ * Insert a separator on the redo stack.
+ */
+
+ TkUndoInsertSeparator(&stack->redoStack);
+ stack->depth--;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkUndoApply --
+ *
+ * Redo a compound action on the stack.
+ *
+ * Results:
+ * A Tcl status code
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkUndoApply(
+ TkUndoRedoStack *stack)
+{
+ TkUndoAtom *elem;
+
+ /*
+ * Insert a separator on the undo stack.
+ */
+
+ TkUndoInsertSeparator(&stack->undoStack);
+
+ /*
+ * Pop and skip the first separator if there is one.
+ */
+
+ elem = TkUndoPopStack(&stack->redoStack);
+ if (elem == NULL) {
+ return TCL_ERROR;
+ }
+
+ if (elem->type == TK_UNDO_SEPARATOR) {
+ ckfree(elem);
+ elem = TkUndoPopStack(&stack->redoStack);
+ }
+
+ while (elem != NULL && elem->type != TK_UNDO_SEPARATOR) {
+ /*
+ * Note that we currently ignore errors thrown here.
+ */
+
+ EvaluateActionList(stack->interp, elem->apply);
+
+ TkUndoPushStack(&stack->undoStack, elem);
+ elem = TkUndoPopStack(&stack->redoStack);
+ }
+
+ /*
+ * Insert a separator on the undo stack.
+ */
+
+ TkUndoInsertSeparator(&stack->undoStack);
+ stack->depth++;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EvaluateActionList --
+ *
+ * Execute a linked list of undo/redo sub-atoms. If any sub-atom returns
+ * a non TCL_OK value, execution of subsequent sub-atoms is cancelled and
+ * the error returned immediately.
+ *
+ * Results:
+ * A Tcl status code
+ *
+ * Side effects:
+ * The undo/redo subAtoms can perform arbitrary actions.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+EvaluateActionList(
+ Tcl_Interp *interp, /* Interpreter to evaluate the action in. */
+ TkUndoSubAtom *action) /* Head of linked list of action steps to
+ * perform. */
+{
+ int result = TCL_OK;
+
+ while (action != NULL) {
+ if (action->funcPtr != NULL) {
+ result = action->funcPtr(interp, action->clientData,
+ action->action);
+ } else if (action->command != NULL) {
+ Tcl_Obj *cmdNameObj, *evalObj;
+
+ cmdNameObj = Tcl_NewObj();
+ evalObj = Tcl_NewObj();
+ Tcl_IncrRefCount(evalObj);
+ Tcl_GetCommandFullName(interp, action->command, cmdNameObj);
+ Tcl_ListObjAppendElement(NULL, evalObj, cmdNameObj);
+ if (action->action != NULL) {
+ Tcl_ListObjAppendList(NULL, evalObj, action->action);
+ }
+ result = Tcl_EvalObjEx(interp, evalObj, TCL_EVAL_GLOBAL);
+ Tcl_DecrRefCount(evalObj);
+ } else {
+ result = Tcl_EvalObjEx(interp, action->action, TCL_EVAL_GLOBAL);
+ }
+ if (result != TCL_OK) {
+ return result;
+ }
+ action = action->next;
+ }
+ return result;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkUndo.h b/tk8.6/generic/tkUndo.h
new file mode 100644
index 0000000..490ede9
--- /dev/null
+++ b/tk8.6/generic/tkUndo.h
@@ -0,0 +1,115 @@
+/*
+ * tkUndo.h --
+ *
+ * Declarations shared among the files that implement an undo stack.
+ *
+ * Copyright (c) 2002 Ludwig Callewaert.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef _TKUNDO
+#define _TKUNDO
+
+#ifndef _TKINT
+#include "tkInt.h"
+#endif
+
+/*
+ * Enum defining the types used in an undo stack.
+ */
+
+typedef enum {
+ TK_UNDO_SEPARATOR, /* Marker */
+ TK_UNDO_ACTION /* Command */
+} TkUndoAtomType;
+
+/*
+ * Callback proc type to carry out an undo or redo action via C code. (Actions
+ * can also be defined by Tcl scripts).
+ */
+
+typedef int (TkUndoProc)(Tcl_Interp *interp, ClientData clientData,
+ Tcl_Obj *objPtr);
+
+/*
+ * Struct defining a single action, one or more of which may be defined (and
+ * stored in a linked list) separately for each undo and redo action of an
+ * undo atom.
+ */
+
+typedef struct TkUndoSubAtom {
+ Tcl_Command command; /* Tcl token used to get the current Tcl
+ * command name which will be used to execute
+ * apply/revert scripts. If NULL then it is
+ * assumed the apply/revert scripts already
+ * contain everything. */
+ TkUndoProc *funcPtr; /* Function pointer for callback to perform
+ * undo/redo actions. */
+ ClientData clientData; /* Data for 'funcPtr'. */
+ Tcl_Obj *action; /* Command to apply the action that was
+ * taken. */
+ struct TkUndoSubAtom *next; /* Pointer to the next element in the linked
+ * list. */
+} TkUndoSubAtom;
+
+/*
+ * Struct representing a single undo+redo atom to be placed in the stack.
+ */
+
+typedef struct TkUndoAtom {
+ TkUndoAtomType type; /* The type that will trigger the required
+ * action. */
+ TkUndoSubAtom *apply; /* Linked list of 'apply' actions to perform
+ * for this operation. */
+ TkUndoSubAtom *revert; /* Linked list of 'revert' actions to perform
+ * for this operation. */
+ struct TkUndoAtom *next; /* Pointer to the next element in the
+ * stack. */
+} TkUndoAtom;
+
+/*
+ * Struct defining a single undo+redo stack.
+ */
+
+typedef struct TkUndoRedoStack {
+ TkUndoAtom *undoStack; /* The undo stack. */
+ TkUndoAtom *redoStack; /* The redo stack. */
+ Tcl_Interp *interp; /* The interpreter in which to execute the
+ * revert and apply scripts. */
+ int maxdepth;
+ int depth;
+} TkUndoRedoStack;
+
+/*
+ * Basic functions.
+ */
+
+MODULE_SCOPE void TkUndoPushStack(TkUndoAtom **stack, TkUndoAtom *elem);
+MODULE_SCOPE TkUndoAtom *TkUndoPopStack(TkUndoAtom **stack);
+MODULE_SCOPE int TkUndoInsertSeparator(TkUndoAtom **stack);
+MODULE_SCOPE void TkUndoClearStack(TkUndoAtom **stack);
+
+/*
+ * Functions for working on an undo/redo stack.
+ */
+
+MODULE_SCOPE TkUndoRedoStack *TkUndoInitStack(Tcl_Interp *interp, int maxdepth);
+MODULE_SCOPE void TkUndoSetMaxDepth(TkUndoRedoStack *stack, int maxdepth);
+MODULE_SCOPE void TkUndoClearStacks(TkUndoRedoStack *stack);
+MODULE_SCOPE void TkUndoFreeStack(TkUndoRedoStack *stack);
+MODULE_SCOPE int TkUndoCanRedo(TkUndoRedoStack *stack);
+MODULE_SCOPE int TkUndoCanUndo(TkUndoRedoStack *stack);
+MODULE_SCOPE void TkUndoInsertUndoSeparator(TkUndoRedoStack *stack);
+MODULE_SCOPE TkUndoSubAtom *TkUndoMakeCmdSubAtom(Tcl_Command command,
+ Tcl_Obj *actionScript, TkUndoSubAtom *subAtomList);
+MODULE_SCOPE TkUndoSubAtom *TkUndoMakeSubAtom(TkUndoProc *funcPtr,
+ ClientData clientData, Tcl_Obj *actionScript,
+ TkUndoSubAtom *subAtomList);
+MODULE_SCOPE void TkUndoPushAction(TkUndoRedoStack *stack,
+ TkUndoSubAtom *apply, TkUndoSubAtom *revert);
+MODULE_SCOPE int TkUndoRevert(TkUndoRedoStack *stack);
+MODULE_SCOPE int TkUndoApply(TkUndoRedoStack *stack);
+
+#endif /* _TKUNDO */
diff --git a/tk8.6/generic/tkUtil.c b/tk8.6/generic/tkUtil.c
new file mode 100644
index 0000000..1942975
--- /dev/null
+++ b/tk8.6/generic/tkUtil.c
@@ -0,0 +1,1281 @@
+/*
+ * tkUtil.c --
+ *
+ * This file contains miscellaneous utility functions that are used by
+ * the rest of Tk, such as a function for drawing a focus highlight.
+ *
+ * Copyright (c) 1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "tkInt.h"
+
+/*
+ * The structure below defines the implementation of the "statekey" Tcl
+ * object, used for quickly finding a mapping in a TkStateMap.
+ */
+
+const Tcl_ObjType tkStateKeyObjType = {
+ "statekey", /* name */
+ NULL, /* freeIntRepProc */
+ NULL, /* dupIntRepProc */
+ NULL, /* updateStringProc */
+ NULL /* setFromAnyProc */
+};
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkStateParseProc --
+ *
+ * This function is invoked during option processing to handle the
+ * "-state" and "-default" options.
+ *
+ * Results:
+ * A standard Tcl return value.
+ *
+ * Side effects:
+ * The state for a given item gets replaced by the state indicated in the
+ * value argument.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkStateParseProc(
+ ClientData clientData, /* some flags.*/
+ Tcl_Interp *interp, /* Used for reporting errors. */
+ Tk_Window tkwin, /* Window containing canvas widget. */
+ const char *value, /* Value of option. */
+ char *widgRec, /* Pointer to record for item. */
+ int offset) /* Offset into item. */
+{
+ int c;
+ int flags = PTR2INT(clientData);
+ size_t length;
+ Tcl_Obj *msgObj;
+
+ register Tk_State *statePtr = (Tk_State *) (widgRec + offset);
+
+ if (value == NULL || *value == 0) {
+ *statePtr = TK_STATE_NULL;
+ return TCL_OK;
+ }
+
+ c = value[0];
+ length = strlen(value);
+
+ if ((c == 'n') && (strncmp(value, "normal", length) == 0)) {
+ *statePtr = TK_STATE_NORMAL;
+ return TCL_OK;
+ }
+ if ((c == 'd') && (strncmp(value, "disabled", length) == 0)) {
+ *statePtr = TK_STATE_DISABLED;
+ return TCL_OK;
+ }
+ if ((c == 'a') && (flags&1) && (strncmp(value, "active", length) == 0)) {
+ *statePtr = TK_STATE_ACTIVE;
+ return TCL_OK;
+ }
+ if ((c == 'h') && (flags&2) && (strncmp(value, "hidden", length) == 0)) {
+ *statePtr = TK_STATE_HIDDEN;
+ return TCL_OK;
+ }
+
+ msgObj = Tcl_ObjPrintf("bad %s value \"%s\": must be normal",
+ ((flags & 4) ? "-default" : "state"), value);
+ if (flags & 1) {
+ Tcl_AppendToObj(msgObj, ", active", -1);
+ }
+ if (flags & 2) {
+ Tcl_AppendToObj(msgObj, ", hidden", -1);
+ }
+ if (flags & 3) {
+ Tcl_AppendToObj(msgObj, ",", -1);
+ }
+ Tcl_AppendToObj(msgObj, " or disabled", -1);
+ Tcl_SetObjResult(interp, msgObj);
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "STATE", NULL);
+ *statePtr = TK_STATE_NORMAL;
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkStatePrintProc --
+ *
+ * This function is invoked by the Tk configuration code to produce a
+ * printable string for the "-state" configuration option.
+ *
+ * Results:
+ * The return value is a string describing the state for the item
+ * referred to by "widgRec". In addition, *freeProcPtr is filled in with
+ * the address of a function to call to free the result string when it's
+ * no longer needed (or NULL to indicate that the string doesn't need to
+ * be freed).
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+const char *
+TkStatePrintProc(
+ ClientData clientData, /* Ignored. */
+ Tk_Window tkwin, /* Window containing canvas widget. */
+ char *widgRec, /* Pointer to record for item. */
+ int offset, /* Offset into item. */
+ Tcl_FreeProc **freeProcPtr) /* Pointer to variable to fill in with
+ * information about how to reclaim storage
+ * for return string. */
+{
+ register Tk_State *statePtr = (Tk_State *) (widgRec + offset);
+
+ switch (*statePtr) {
+ case TK_STATE_NORMAL:
+ return "normal";
+ case TK_STATE_DISABLED:
+ return "disabled";
+ case TK_STATE_HIDDEN:
+ return "hidden";
+ case TK_STATE_ACTIVE:
+ return "active";
+ default:
+ return "";
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkOrientParseProc --
+ *
+ * This function is invoked during option processing to handle the
+ * "-orient" option.
+ *
+ * Results:
+ * A standard Tcl return value.
+ *
+ * Side effects:
+ * The orientation for a given item gets replaced by the orientation
+ * indicated in the value argument.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkOrientParseProc(
+ ClientData clientData, /* some flags.*/
+ Tcl_Interp *interp, /* Used for reporting errors. */
+ Tk_Window tkwin, /* Window containing canvas widget. */
+ const char *value, /* Value of option. */
+ char *widgRec, /* Pointer to record for item. */
+ int offset) /* Offset into item. */
+{
+ int c;
+ size_t length;
+
+ register int *orientPtr = (int *) (widgRec + offset);
+
+ if (value == NULL || *value == 0) {
+ *orientPtr = 0;
+ return TCL_OK;
+ }
+
+ c = value[0];
+ length = strlen(value);
+
+ if ((c == 'h') && (strncmp(value, "horizontal", length) == 0)) {
+ *orientPtr = 0;
+ return TCL_OK;
+ }
+ if ((c == 'v') && (strncmp(value, "vertical", length) == 0)) {
+ *orientPtr = 1;
+ return TCL_OK;
+ }
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad orientation \"%s\": must be vertical or horizontal",
+ value));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "ORIENTATION", NULL);
+ *orientPtr = 0;
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkOrientPrintProc --
+ *
+ * This function is invoked by the Tk configuration code to produce a
+ * printable string for the "-orient" configuration option.
+ *
+ * Results:
+ * The return value is a string describing the orientation for the item
+ * referred to by "widgRec". In addition, *freeProcPtr is filled in with
+ * the address of a function to call to free the result string when it's
+ * no longer needed (or NULL to indicate that the string doesn't need to
+ * be freed).
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+const char *
+TkOrientPrintProc(
+ ClientData clientData, /* Ignored. */
+ Tk_Window tkwin, /* Window containing canvas widget. */
+ char *widgRec, /* Pointer to record for item. */
+ int offset, /* Offset into item. */
+ Tcl_FreeProc **freeProcPtr) /* Pointer to variable to fill in with
+ * information about how to reclaim storage
+ * for return string. */
+{
+ register int *statePtr = (int *) (widgRec + offset);
+
+ if (*statePtr) {
+ return "vertical";
+ } else {
+ return "horizontal";
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkOffsetParseProc --
+ *
+ * Converts the offset of a stipple or tile into the Tk_TSOffset
+ * structure.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkOffsetParseProc(
+ ClientData clientData, /* not used */
+ Tcl_Interp *interp, /* Interpreter to send results back to */
+ Tk_Window tkwin, /* Window on same display as tile */
+ const char *value, /* Name of image */
+ char *widgRec, /* Widget structure record */
+ int offset) /* Offset of tile in record */
+{
+ Tk_TSOffset *offsetPtr = (Tk_TSOffset *) (widgRec + offset);
+ Tk_TSOffset tsoffset;
+ const char *q, *p;
+ int result;
+ Tcl_Obj *msgObj;
+
+ if ((value == NULL) || (*value == 0)) {
+ tsoffset.flags = TK_OFFSET_CENTER|TK_OFFSET_MIDDLE;
+ goto goodTSOffset;
+ }
+ tsoffset.flags = 0;
+ p = value;
+
+ switch (value[0]) {
+ case '#':
+ if (PTR2INT(clientData) & TK_OFFSET_RELATIVE) {
+ tsoffset.flags = TK_OFFSET_RELATIVE;
+ p++;
+ break;
+ }
+ goto badTSOffset;
+ case 'e':
+ switch(value[1]) {
+ case '\0':
+ tsoffset.flags = TK_OFFSET_RIGHT|TK_OFFSET_MIDDLE;
+ goto goodTSOffset;
+ case 'n':
+ if (value[2]!='d' || value[3]!='\0') {
+ goto badTSOffset;
+ }
+ tsoffset.flags = INT_MAX;
+ goto goodTSOffset;
+ }
+ case 'w':
+ if (value[1] != '\0') {goto badTSOffset;}
+ tsoffset.flags = TK_OFFSET_LEFT|TK_OFFSET_MIDDLE;
+ goto goodTSOffset;
+ case 'n':
+ if ((value[1] != '\0') && (value[2] != '\0')) {
+ goto badTSOffset;
+ }
+ switch(value[1]) {
+ case '\0':
+ tsoffset.flags = TK_OFFSET_CENTER|TK_OFFSET_TOP;
+ goto goodTSOffset;
+ case 'w':
+ tsoffset.flags = TK_OFFSET_LEFT|TK_OFFSET_TOP;
+ goto goodTSOffset;
+ case 'e':
+ tsoffset.flags = TK_OFFSET_RIGHT|TK_OFFSET_TOP;
+ goto goodTSOffset;
+ }
+ goto badTSOffset;
+ case 's':
+ if ((value[1] != '\0') && (value[2] != '\0')) {
+ goto badTSOffset;
+ }
+ switch(value[1]) {
+ case '\0':
+ tsoffset.flags = TK_OFFSET_CENTER|TK_OFFSET_BOTTOM;
+ goto goodTSOffset;
+ case 'w':
+ tsoffset.flags = TK_OFFSET_LEFT|TK_OFFSET_BOTTOM;
+ goto goodTSOffset;
+ case 'e':
+ tsoffset.flags = TK_OFFSET_RIGHT|TK_OFFSET_BOTTOM;
+ goto goodTSOffset;
+ }
+ goto badTSOffset;
+ case 'c':
+ if (strncmp(value, "center", strlen(value)) != 0) {
+ goto badTSOffset;
+ }
+ tsoffset.flags = TK_OFFSET_CENTER|TK_OFFSET_MIDDLE;
+ goto goodTSOffset;
+ }
+
+ /*
+ * Check for an extra offset.
+ */
+
+ q = strchr(p, ',');
+ if (q == NULL) {
+ if (PTR2INT(clientData) & TK_OFFSET_INDEX) {
+ if (Tcl_GetInt(interp, (char *) p, &tsoffset.flags) != TCL_OK) {
+ Tcl_ResetResult(interp);
+ goto badTSOffset;
+ }
+ tsoffset.flags |= TK_OFFSET_INDEX;
+ goto goodTSOffset;
+ }
+ goto badTSOffset;
+ }
+
+ *((char *) q) = 0;
+ result = Tk_GetPixels(interp, tkwin, (char *) p, &tsoffset.xoffset);
+ *((char *) q) = ',';
+ if (result != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tk_GetPixels(interp, tkwin, (char*)q+1, &tsoffset.yoffset) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Below is a hack to allow the stipple/tile offset to be stored in the
+ * internal tile structure. Most of the times, offsetPtr is a pointer to
+ * an already existing tile structure. However if this structure is not
+ * already created, we must do it with Tk_GetTile()!!!!
+ */
+
+ goodTSOffset:
+ memcpy(offsetPtr, &tsoffset, sizeof(Tk_TSOffset));
+ return TCL_OK;
+
+ badTSOffset:
+ msgObj = Tcl_ObjPrintf("bad offset \"%s\": expected \"x,y\"", value);
+ if (PTR2INT(clientData) & TK_OFFSET_RELATIVE) {
+ Tcl_AppendToObj(msgObj, ", \"#x,y\"", -1);
+ }
+ if (PTR2INT(clientData) & TK_OFFSET_INDEX) {
+ Tcl_AppendToObj(msgObj, ", <index>", -1);
+ }
+ Tcl_AppendToObj(msgObj, ", n, ne, e, se, s, sw, w, nw, or center", -1);
+ Tcl_SetObjResult(interp, msgObj);
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "OFFSET", NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkOffsetPrintProc --
+ *
+ * Returns the offset of the tile.
+ *
+ * Results:
+ * The offset of the tile is returned.
+ *
+ *----------------------------------------------------------------------
+ */
+
+const char *
+TkOffsetPrintProc(
+ ClientData clientData, /* not used */
+ Tk_Window tkwin, /* not used */
+ char *widgRec, /* Widget structure record */
+ int offset, /* Offset of tile in record */
+ Tcl_FreeProc **freeProcPtr) /* not used */
+{
+ Tk_TSOffset *offsetPtr = (Tk_TSOffset *) (widgRec + offset);
+ char *p, *q;
+
+ if (offsetPtr->flags & TK_OFFSET_INDEX) {
+ if (offsetPtr->flags >= INT_MAX) {
+ return "end";
+ }
+ p = ckalloc(32);
+ sprintf(p, "%d", offsetPtr->flags & ~TK_OFFSET_INDEX);
+ *freeProcPtr = TCL_DYNAMIC;
+ return p;
+ }
+ if (offsetPtr->flags & TK_OFFSET_TOP) {
+ if (offsetPtr->flags & TK_OFFSET_LEFT) {
+ return "nw";
+ } else if (offsetPtr->flags & TK_OFFSET_CENTER) {
+ return "n";
+ } else if (offsetPtr->flags & TK_OFFSET_RIGHT) {
+ return "ne";
+ }
+ } else if (offsetPtr->flags & TK_OFFSET_MIDDLE) {
+ if (offsetPtr->flags & TK_OFFSET_LEFT) {
+ return "w";
+ } else if (offsetPtr->flags & TK_OFFSET_CENTER) {
+ return "center";
+ } else if (offsetPtr->flags & TK_OFFSET_RIGHT) {
+ return "e";
+ }
+ } else if (offsetPtr->flags & TK_OFFSET_BOTTOM) {
+ if (offsetPtr->flags & TK_OFFSET_LEFT) {
+ return "sw";
+ } else if (offsetPtr->flags & TK_OFFSET_CENTER) {
+ return "s";
+ } else if (offsetPtr->flags & TK_OFFSET_RIGHT) {
+ return "se";
+ }
+ }
+ q = p = ckalloc(32);
+ if (offsetPtr->flags & TK_OFFSET_RELATIVE) {
+ *q++ = '#';
+ }
+ sprintf(q, "%d,%d", offsetPtr->xoffset, offsetPtr->yoffset);
+ *freeProcPtr = TCL_DYNAMIC;
+ return p;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkPixelParseProc --
+ *
+ * Converts the name of an image into a tile.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkPixelParseProc(
+ ClientData clientData, /* If non-NULL, negative values are allowed as
+ * well. */
+ Tcl_Interp *interp, /* Interpreter to send results back to */
+ Tk_Window tkwin, /* Window on same display as tile */
+ const char *value, /* Name of image */
+ char *widgRec, /* Widget structure record */
+ int offset) /* Offset of tile in record */
+{
+ double *doublePtr = (double *) (widgRec + offset);
+ int result;
+
+ result = TkGetDoublePixels(interp, tkwin, value, doublePtr);
+
+ if ((result == TCL_OK) && (clientData == NULL) && (*doublePtr < 0.0)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad screen distance \"%s\"", value));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "PIXELS", NULL);
+ return TCL_ERROR;
+ }
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkPixelPrintProc --
+ *
+ * Returns the name of the tile.
+ *
+ * Results:
+ * The name of the tile is returned.
+ *
+ *----------------------------------------------------------------------
+ */
+
+const char *
+TkPixelPrintProc(
+ ClientData clientData, /* not used */
+ Tk_Window tkwin, /* not used */
+ char *widgRec, /* Widget structure record */
+ int offset, /* Offset of tile in record */
+ Tcl_FreeProc **freeProcPtr) /* not used */
+{
+ double *doublePtr = (double *) (widgRec + offset);
+ char *p = ckalloc(24);
+
+ Tcl_PrintDouble(NULL, *doublePtr, p);
+ *freeProcPtr = TCL_DYNAMIC;
+ return p;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkDrawInsetFocusHighlight --
+ *
+ * This function draws a rectangular ring around the outside of a widget
+ * to indicate that it has received the input focus. It takes an
+ * additional padding argument that specifies how much padding is present
+ * outside the widget.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A rectangle "width" pixels wide is drawn in "drawable", corresponding
+ * to the outer area of "tkwin".
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkDrawInsetFocusHighlight(
+ Tk_Window tkwin, /* Window whose focus highlight ring is to be
+ * drawn. */
+ GC gc, /* Graphics context to use for drawing the
+ * highlight ring. */
+ int width, /* Width of the highlight ring, in pixels. */
+ Drawable drawable, /* Where to draw the ring (typically a pixmap
+ * for double buffering). */
+ int padding) /* Width of padding outside of widget. */
+{
+ XRectangle rects[4];
+
+ rects[0].x = padding;
+ rects[0].y = padding;
+ rects[0].width = Tk_Width(tkwin) - (2 * padding);
+ rects[0].height = width;
+ rects[1].x = padding;
+ rects[1].y = Tk_Height(tkwin) - width - padding;
+ rects[1].width = Tk_Width(tkwin) - (2 * padding);
+ rects[1].height = width;
+ rects[2].x = padding;
+ rects[2].y = width + padding;
+ rects[2].width = width;
+ rects[2].height = Tk_Height(tkwin) - 2*width - 2*padding;
+ rects[3].x = Tk_Width(tkwin) - width - padding;
+ rects[3].y = rects[2].y;
+ rects[3].width = width;
+ rects[3].height = rects[2].height;
+ XFillRectangles(Tk_Display(tkwin), drawable, gc, rects, 4);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_DrawFocusHighlight --
+ *
+ * This function draws a rectangular ring around the outside of a widget
+ * to indicate that it has received the input focus.
+ *
+ * This function is now deprecated. Use TkpDrawHighlightBorder instead,
+ * since this function does not handle drawing the Focus ring properly on
+ * the Macintosh - you need to know the background GC as well as the
+ * foreground since the Mac focus ring separated from the widget by a 1
+ * pixel border.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A rectangle "width" pixels wide is drawn in "drawable", corresponding
+ * to the outer area of "tkwin".
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_DrawFocusHighlight(
+ Tk_Window tkwin, /* Window whose focus highlight ring is to be
+ * drawn. */
+ GC gc, /* Graphics context to use for drawing the
+ * highlight ring. */
+ int width, /* Width of the highlight ring, in pixels. */
+ Drawable drawable) /* Where to draw the ring (typically a pixmap
+ * for double buffering). */
+{
+ TkDrawInsetFocusHighlight(tkwin, gc, width, drawable, 0);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetScrollInfo --
+ *
+ * This function is invoked to parse "xview" and "yview" scrolling
+ * commands for widgets using the new scrolling command syntax ("moveto"
+ * or "scroll" options).
+ *
+ * Results:
+ * The return value is either TK_SCROLL_MOVETO, TK_SCROLL_PAGES,
+ * TK_SCROLL_UNITS, or TK_SCROLL_ERROR. This indicates whether the
+ * command was successfully parsed and what form the command took. If
+ * TK_SCROLL_MOVETO, *dblPtr is filled in with the desired position; if
+ * TK_SCROLL_PAGES or TK_SCROLL_UNITS, *intPtr is filled in with the
+ * number of lines to move (may be negative); if TK_SCROLL_ERROR, the
+ * interp's result contains an error message.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_GetScrollInfo(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ int argc, /* # arguments for command. */
+ const char **argv, /* Arguments for command. */
+ double *dblPtr, /* Filled in with argument "moveto" option, if
+ * any. */
+ int *intPtr) /* Filled in with number of pages or lines to
+ * scroll, if any. */
+{
+ int c = argv[2][0];
+ size_t length = strlen(argv[2]);
+
+ if ((c == 'm') && (strncmp(argv[2], "moveto", length) == 0)) {
+ if (argc != 4) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "wrong # args: should be \"%s %s %s\"",
+ argv[0], argv[1], "moveto fraction"));
+ Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL);
+ return TK_SCROLL_ERROR;
+ }
+ if (Tcl_GetDouble(interp, argv[3], dblPtr) != TCL_OK) {
+ return TK_SCROLL_ERROR;
+ }
+ return TK_SCROLL_MOVETO;
+ } else if ((c == 's')
+ && (strncmp(argv[2], "scroll", length) == 0)) {
+ if (argc != 5) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "wrong # args: should be \"%s %s %s\"",
+ argv[0], argv[1], "scroll number units|pages"));
+ Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL);
+ return TK_SCROLL_ERROR;
+ }
+ if (Tcl_GetInt(interp, argv[3], intPtr) != TCL_OK) {
+ return TK_SCROLL_ERROR;
+ }
+ length = strlen(argv[4]);
+ c = argv[4][0];
+ if ((c == 'p') && (strncmp(argv[4], "pages", length) == 0)) {
+ return TK_SCROLL_PAGES;
+ } else if ((c == 'u') && (strncmp(argv[4], "units", length) == 0)) {
+ return TK_SCROLL_UNITS;
+ }
+
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad argument \"%s\": must be units or pages", argv[4]));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "SCROLL_UNITS", NULL);
+ return TK_SCROLL_ERROR;
+ }
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "unknown option \"%s\": must be moveto or scroll", argv[2]));
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "option", argv[2],
+ NULL);
+ return TK_SCROLL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetScrollInfoObj --
+ *
+ * This function is invoked to parse "xview" and "yview" scrolling
+ * commands for widgets using the new scrolling command syntax ("moveto"
+ * or "scroll" options).
+ *
+ * Results:
+ * The return value is either TK_SCROLL_MOVETO, TK_SCROLL_PAGES,
+ * TK_SCROLL_UNITS, or TK_SCROLL_ERROR. This indicates whether the
+ * command was successfully parsed and what form the command took. If
+ * TK_SCROLL_MOVETO, *dblPtr is filled in with the desired position; if
+ * TK_SCROLL_PAGES or TK_SCROLL_UNITS, *intPtr is filled in with the
+ * number of lines to move (may be negative); if TK_SCROLL_ERROR, the
+ * interp's result contains an error message.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_GetScrollInfoObj(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ int objc, /* # arguments for command. */
+ Tcl_Obj *const objv[], /* Arguments for command. */
+ double *dblPtr, /* Filled in with argument "moveto" option, if
+ * any. */
+ int *intPtr) /* Filled in with number of pages or lines to
+ * scroll, if any. */
+{
+ const char *arg = Tcl_GetString(objv[2]);
+ size_t length = objv[2]->length;
+
+#define ArgPfxEq(str) \
+ ((arg[0] == str[0]) && !strncmp(arg, str, length))
+
+ if (ArgPfxEq("moveto")) {
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "moveto fraction");
+ return TK_SCROLL_ERROR;
+ }
+ if (Tcl_GetDoubleFromObj(interp, objv[3], dblPtr) != TCL_OK) {
+ return TK_SCROLL_ERROR;
+ }
+ return TK_SCROLL_MOVETO;
+ } else if (ArgPfxEq("scroll")) {
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 2, objv, "scroll number units|pages");
+ return TK_SCROLL_ERROR;
+ }
+ if (Tcl_GetIntFromObj(interp, objv[3], intPtr) != TCL_OK) {
+ return TK_SCROLL_ERROR;
+ }
+
+ arg = Tcl_GetString(objv[4]);
+ length = objv[4]->length;
+ if (ArgPfxEq("pages")) {
+ return TK_SCROLL_PAGES;
+ } else if (ArgPfxEq("units")) {
+ return TK_SCROLL_UNITS;
+ }
+
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad argument \"%s\": must be units or pages", arg));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "SCROLL_UNITS", NULL);
+ return TK_SCROLL_ERROR;
+ }
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "unknown option \"%s\": must be moveto or scroll", arg));
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "option", arg, NULL);
+ return TK_SCROLL_ERROR;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkComputeAnchor --
+ *
+ * Determine where to place a rectangle so that it will be properly
+ * anchored with respect to the given window. Used by widgets to align a
+ * box of text inside a window. When anchoring with respect to one of the
+ * sides, the rectangle be placed inside of the internal border of the
+ * window.
+ *
+ * Results:
+ * *xPtr and *yPtr set to the upper-left corner of the rectangle anchored
+ * in the window.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+TkComputeAnchor(
+ Tk_Anchor anchor, /* Desired anchor. */
+ Tk_Window tkwin, /* Anchored with respect to this window. */
+ int padX, int padY, /* Use this extra padding inside window, in
+ * addition to the internal border. */
+ int innerWidth, int innerHeight,
+ /* Size of rectangle to anchor in window. */
+ int *xPtr, int *yPtr) /* Returns upper-left corner of anchored
+ * rectangle. */
+{
+ /*
+ * Handle the horizontal parts.
+ */
+
+ switch (anchor) {
+ case TK_ANCHOR_NW:
+ case TK_ANCHOR_W:
+ case TK_ANCHOR_SW:
+ *xPtr = Tk_InternalBorderLeft(tkwin) + padX;
+ break;
+
+ case TK_ANCHOR_N:
+ case TK_ANCHOR_CENTER:
+ case TK_ANCHOR_S:
+ *xPtr = (Tk_Width(tkwin) - innerWidth - Tk_InternalBorderLeft(tkwin) -
+ Tk_InternalBorderRight(tkwin)) / 2 +
+ Tk_InternalBorderLeft(tkwin);
+ break;
+
+ default:
+ *xPtr = Tk_Width(tkwin) - Tk_InternalBorderRight(tkwin) - padX
+ - innerWidth;
+ break;
+ }
+
+ /*
+ * Handle the vertical parts.
+ */
+
+ switch (anchor) {
+ case TK_ANCHOR_NW:
+ case TK_ANCHOR_N:
+ case TK_ANCHOR_NE:
+ *yPtr = Tk_InternalBorderTop(tkwin) + padY;
+ break;
+
+ case TK_ANCHOR_W:
+ case TK_ANCHOR_CENTER:
+ case TK_ANCHOR_E:
+ *yPtr = (Tk_Height(tkwin) - innerHeight- Tk_InternalBorderTop(tkwin) -
+ Tk_InternalBorderBottom(tkwin)) / 2 +
+ Tk_InternalBorderTop(tkwin);
+ break;
+
+ default:
+ *yPtr = Tk_Height(tkwin) - Tk_InternalBorderBottom(tkwin) - padY
+ - innerHeight;
+ break;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkFindStateString --
+ *
+ * Given a lookup table, map a number to a string in the table.
+ *
+ * Results:
+ * If numKey was equal to the numeric key of one of the elements in the
+ * table, returns the string key of that element. Returns NULL if numKey
+ * was not equal to any of the numeric keys in the table.
+ *
+ * Side effects.
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+const char *
+TkFindStateString(
+ const TkStateMap *mapPtr, /* The state table. */
+ int numKey) /* The key to try to find in the table. */
+{
+ for (; mapPtr->strKey!=NULL ; mapPtr++) {
+ if (numKey == mapPtr->numKey) {
+ return mapPtr->strKey;
+ }
+ }
+ return NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkFindStateNum, TkFindStateNumObj --
+ *
+ * Given a lookup table, map a string to a number in the table.
+ *
+ * Results:
+ * If strKey was equal to the string keys of one of the elements in the
+ * table, returns the numeric key of that element. Returns the numKey
+ * associated with the last element (the NULL string one) in the table if
+ * strKey was not equal to any of the string keys in the table. In that
+ * case, an error message is also left in the interp's result (if interp
+ * is not NULL).
+ *
+ * Side effects.
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TkFindStateNum(
+ Tcl_Interp *interp, /* Interp for error reporting. */
+ const char *option, /* String to use when constructing error. */
+ const TkStateMap *mapPtr, /* Lookup table. */
+ const char *strKey) /* String to try to find in lookup table. */
+{
+ const TkStateMap *mPtr;
+
+ /*
+ * See if the value is in the state map.
+ */
+
+ for (mPtr = mapPtr; mPtr->strKey != NULL; mPtr++) {
+ if (strcmp(strKey, mPtr->strKey) == 0) {
+ return mPtr->numKey;
+ }
+ }
+
+ /*
+ * Not there. Generate an error message (if we can) and return the
+ * default.
+ */
+
+ if (interp != NULL) {
+ Tcl_Obj *msgObj;
+
+ mPtr = mapPtr;
+ msgObj = Tcl_ObjPrintf("bad %s value \"%s\": must be %s",
+ option, strKey, mPtr->strKey);
+ for (mPtr++; mPtr->strKey != NULL; mPtr++) {
+ Tcl_AppendPrintfToObj(msgObj, ",%s %s",
+ ((mPtr[1].strKey != NULL) ? "" : "or "), mPtr->strKey);
+ }
+ Tcl_SetObjResult(interp, msgObj);
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", option, strKey, NULL);
+ }
+ return mPtr->numKey;
+}
+
+int
+TkFindStateNumObj(
+ Tcl_Interp *interp, /* Interp for error reporting. */
+ Tcl_Obj *optionPtr, /* String to use when constructing error. */
+ const TkStateMap *mapPtr, /* Lookup table. */
+ Tcl_Obj *keyPtr) /* String key to find in lookup table. */
+{
+ const TkStateMap *mPtr;
+ const char *key;
+ const Tcl_ObjType *typePtr;
+
+ /*
+ * See if the value is in the object cache.
+ */
+
+ if ((keyPtr->typePtr == &tkStateKeyObjType)
+ && (keyPtr->internalRep.twoPtrValue.ptr1 == mapPtr)) {
+ return PTR2INT(keyPtr->internalRep.twoPtrValue.ptr2);
+ }
+
+ /*
+ * Not there. Look in the state map.
+ */
+
+ key = Tcl_GetString(keyPtr);
+ for (mPtr = mapPtr; mPtr->strKey != NULL; mPtr++) {
+ if (strcmp(key, mPtr->strKey) == 0) {
+ typePtr = keyPtr->typePtr;
+ if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
+ typePtr->freeIntRepProc(keyPtr);
+ }
+ keyPtr->internalRep.twoPtrValue.ptr1 = (void *) mapPtr;
+ keyPtr->internalRep.twoPtrValue.ptr2 = INT2PTR(mPtr->numKey);
+ keyPtr->typePtr = &tkStateKeyObjType;
+ return mPtr->numKey;
+ }
+ }
+
+ /*
+ * Not there either. Generate an error message (if we can) and return the
+ * default.
+ */
+
+ if (interp != NULL) {
+ Tcl_Obj *msgObj;
+
+ mPtr = mapPtr;
+ msgObj = Tcl_ObjPrintf(
+ "bad %s value \"%s\": must be %s",
+ Tcl_GetString(optionPtr), key, mPtr->strKey);
+ for (mPtr++; mPtr->strKey != NULL; mPtr++) {
+ Tcl_AppendPrintfToObj(msgObj, ",%s %s",
+ ((mPtr[1].strKey != NULL) ? "" : " or"), mPtr->strKey);
+ }
+ Tcl_SetObjResult(interp, msgObj);
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", Tcl_GetString(optionPtr),
+ key, NULL);
+ }
+ return mPtr->numKey;
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * TkBackgroundEvalObjv --
+ *
+ * Evaluate a command while ensuring that we do not affect the
+ * interpreters state. This is important when evaluating script
+ * during background tasks.
+ *
+ * Results:
+ * A standard Tcl result code.
+ *
+ * Side Effects:
+ * The interpreters variables and code may be modified by the script
+ * but the result will not be modified.
+ *
+ * ----------------------------------------------------------------------
+ */
+
+int
+TkBackgroundEvalObjv(
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv,
+ int flags)
+{
+ Tcl_InterpState state;
+ int n, r = TCL_OK;
+
+ /*
+ * Record the state of the interpreter.
+ */
+
+ Tcl_Preserve(interp);
+ state = Tcl_SaveInterpState(interp, TCL_OK);
+
+ /*
+ * Evaluate the command and handle any error.
+ */
+
+ for (n = 0; n < objc; ++n) {
+ Tcl_IncrRefCount(objv[n]);
+ }
+ r = Tcl_EvalObjv(interp, objc, objv, flags);
+ for (n = 0; n < objc; ++n) {
+ Tcl_DecrRefCount(objv[n]);
+ }
+ if (r == TCL_ERROR) {
+ Tcl_AddErrorInfo(interp, "\n (background event handler)");
+ Tcl_BackgroundException(interp, r);
+ }
+
+ /*
+ * Restore the state of the interpreter.
+ */
+
+ (void) Tcl_RestoreInterpState(interp, state);
+ Tcl_Release(interp);
+
+ return r;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMakeEnsemble --
+ *
+ * Create an ensemble from a table of implementation commands. This may
+ * be called recursively to create sub-ensembles.
+ *
+ * Results:
+ * Handle for the ensemble, or NULL if creation of it fails.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Command
+TkMakeEnsemble(
+ Tcl_Interp *interp,
+ const char *namespace,
+ const char *name,
+ ClientData clientData,
+ const TkEnsemble map[])
+{
+ Tcl_Namespace *namespacePtr = NULL;
+ Tcl_Command ensemble = NULL;
+ Tcl_Obj *dictObj = NULL, *nameObj;
+ Tcl_DString ds;
+ int i;
+
+ if (map == NULL) {
+ return NULL;
+ }
+
+ Tcl_DStringInit(&ds);
+
+ namespacePtr = Tcl_FindNamespace(interp, namespace, NULL, 0);
+ if (namespacePtr == NULL) {
+ namespacePtr = Tcl_CreateNamespace(interp, namespace, NULL, NULL);
+ if (namespacePtr == NULL) {
+ Tcl_Panic("failed to create namespace \"%s\"", namespace);
+ }
+ }
+
+ nameObj = Tcl_NewStringObj(name, -1);
+ ensemble = Tcl_FindEnsemble(interp, nameObj, 0);
+ Tcl_DecrRefCount(nameObj);
+ if (ensemble == NULL) {
+ ensemble = Tcl_CreateEnsemble(interp, name, namespacePtr,
+ TCL_ENSEMBLE_PREFIX);
+ if (ensemble == NULL) {
+ Tcl_Panic("failed to create ensemble \"%s\"", name);
+ }
+ }
+
+ Tcl_DStringSetLength(&ds, 0);
+ Tcl_DStringAppend(&ds, namespace, -1);
+ if (!(strlen(namespace) == 2 && namespace[1] == ':')) {
+ Tcl_DStringAppend(&ds, "::", -1);
+ }
+ Tcl_DStringAppend(&ds, name, -1);
+
+ dictObj = Tcl_NewObj();
+ for (i = 0; map[i].name != NULL ; ++i) {
+ Tcl_Obj *nameObj, *fqdnObj;
+
+ nameObj = Tcl_NewStringObj(map[i].name, -1);
+ fqdnObj = Tcl_NewStringObj(Tcl_DStringValue(&ds),
+ Tcl_DStringLength(&ds));
+ Tcl_AppendStringsToObj(fqdnObj, "::", map[i].name, NULL);
+ Tcl_DictObjPut(NULL, dictObj, nameObj, fqdnObj);
+ if (map[i].proc) {
+ Tcl_CreateObjCommand(interp, Tcl_GetString(fqdnObj),
+ map[i].proc, clientData, NULL);
+ } else if (map[i].subensemble) {
+ TkMakeEnsemble(interp, Tcl_DStringValue(&ds),
+ map[i].name, clientData, map[i].subensemble);
+ }
+ }
+
+ if (ensemble) {
+ Tcl_SetEnsembleMappingDict(interp, ensemble, dictObj);
+ }
+
+ Tcl_DStringFree(&ds);
+ return ensemble;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkSendVirtualEvent --
+ *
+ * Send a virtual event notification to the specified target window.
+ * Equivalent to:
+ * "event generate $target <<$eventName>> -data $detail"
+ *
+ * Note that we use Tk_QueueWindowEvent, not Tk_HandleEvent, so this
+ * routine does not reenter the interpreter.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkSendVirtualEvent(
+ Tk_Window target,
+ const char *eventName,
+ Tcl_Obj *detail)
+{
+ union {XEvent general; XVirtualEvent virtual;} event;
+
+ memset(&event, 0, sizeof(event));
+ event.general.xany.type = VirtualEvent;
+ event.general.xany.serial = NextRequest(Tk_Display(target));
+ event.general.xany.send_event = False;
+ event.general.xany.window = Tk_WindowId(target);
+ event.general.xany.display = Tk_Display(target);
+ event.virtual.name = Tk_GetUid(eventName);
+ if (detail != NULL) {
+ event.virtual.user_data = detail;
+ }
+
+ Tk_QueueWindowEvent(&event.general, TCL_QUEUE_TAIL);
+}
+
+#if TCL_UTF_MAX <= 4
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkUtfToUniChar --
+ *
+ * Almost the same as Tcl_UtfToUniChar but using int instead of Tcl_UniChar.
+ * This function is capable of collapsing a upper/lower surrogate pair to a
+ * single unicode character. So, up to 6 bytes might be consumed.
+ *
+ * Results:
+ * *chPtr is filled with the Tcl_UniChar, and the return value is the
+ * number of bytes from the UTF-8 string that were consumed.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TkUtfToUniChar(
+ const char *src, /* The UTF-8 string. */
+ int *chPtr) /* Filled with the Tcl_UniChar represented by
+ * the UTF-8 string. */
+{
+ Tcl_UniChar uniChar = 0;
+
+ int len = Tcl_UtfToUniChar(src, &uniChar);
+ if ((uniChar & 0xfc00) == 0xd800) {
+ Tcl_UniChar high = uniChar;
+ /* This can only happen if Tcl is compiled with TCL_UTF_MAX=4,
+ * or when a high surrogate character is detected in UTF-8 form */
+ int len2 = Tcl_UtfToUniChar(src+len, &uniChar);
+ if ((uniChar & 0xfc00) == 0xdc00) {
+ *chPtr = (((high & 0x3ff) << 10) | (uniChar & 0x3ff)) + 0x10000;
+ len += len2;
+ } else {
+ *chPtr = high;
+ }
+ } else {
+ *chPtr = uniChar;
+ }
+ return len;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkUniCharToUtf --
+ *
+ * Almost the same as Tcl_UniCharToUtf but producing surrogates if
+ * TCL_UTF_MAX==3. So, up to 6 bytes might be produced.
+ *
+ * Results:
+ * *buf is filled with the UTF-8 string, and the return value is the
+ * number of bytes produced.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int TkUniCharToUtf(int ch, char *buf)
+{
+ int size = Tcl_UniCharToUtf(ch, buf);
+ if ((((unsigned)(ch - 0x10000) <= 0xFFFFF)) && (size < 4)) {
+ /* Hey, this is wrong, we must be running TCL_UTF_MAX==3
+ * The best thing we can do is spit out 2 surrogates */
+ ch -= 0x10000;
+ size = Tcl_UniCharToUtf(((ch >> 10) | 0xd800), buf);
+ size += Tcl_UniCharToUtf(((ch & 0x3ff) | 0xdc00), buf+size);
+ }
+ return size;
+}
+
+
+#endif
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkVisual.c b/tk8.6/generic/tkVisual.c
new file mode 100644
index 0000000..8b0c155
--- /dev/null
+++ b/tk8.6/generic/tkVisual.c
@@ -0,0 +1,549 @@
+/*
+ * tkVisual.c --
+ *
+ * This file contains library procedures for allocating and freeing
+ * visuals and colormaps. This code is based on a prototype
+ * implementation by Paul Mackerras.
+ *
+ * Copyright (c) 1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "tkInt.h"
+
+/*
+ * The table below maps from symbolic names for visual classes to the
+ * associated X class symbols.
+ */
+
+typedef struct VisualDictionary {
+ const char *name; /* Textual name of class. */
+ int minLength; /* Minimum # characters that must be specified
+ * for an unambiguous match. */
+ int class; /* X symbol for class. */
+} VisualDictionary;
+static const VisualDictionary visualNames[] = {
+ {"best", 1, 0},
+ {"directcolor", 2, DirectColor},
+ {"grayscale", 1, GrayScale},
+ {"greyscale", 1, GrayScale},
+ {"pseudocolor", 1, PseudoColor},
+ {"staticcolor", 7, StaticColor},
+ {"staticgray", 7, StaticGray},
+ {"staticgrey", 7, StaticGray},
+ {"truecolor", 1, TrueColor},
+ {NULL, 0, 0},
+};
+
+/*
+ * One of the following structures exists for each distinct non-default
+ * colormap allocated for a display by Tk_GetColormap.
+ */
+
+struct TkColormap {
+ Colormap colormap; /* X's identifier for the colormap. */
+ Visual *visual; /* Visual for which colormap was allocated. */
+ int refCount; /* How many uses of the colormap are still
+ * outstanding (calls to Tk_GetColormap minus
+ * calls to Tk_FreeColormap). */
+ int shareable; /* 0 means this colormap was allocated by a
+ * call to Tk_GetColormap with "new", implying
+ * that the window wants it all for itself. 1
+ * means that the colormap was allocated as a
+ * default for a particular visual, so it can
+ * be shared. */
+ struct TkColormap *nextPtr; /* Next in list of colormaps for this display,
+ * or NULL for end of list. */
+};
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetVisual --
+ *
+ * Given a string identifying a particular kind of visual, this procedure
+ * returns a visual and depth that matches the specification.
+ *
+ * Results:
+ * The return value is normally a pointer to a visual. If an error
+ * occurred in looking up the visual, NULL is returned and an error
+ * message is left in the interp's result. The depth of the visual is
+ * returned to *depthPtr under normal returns. If colormapPtr is
+ * non-NULL, then this procedure also finds a suitable colormap for use
+ * with the visual in tkwin, and it returns that colormap in *colormapPtr
+ * unless an error occurs.
+ *
+ * Side effects:
+ * A new colormap may be allocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Visual *
+Tk_GetVisual(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting. */
+ Tk_Window tkwin, /* Window in which visual will be used. */
+ const char *string, /* String describing visual. See manual entry
+ * for details. */
+ int *depthPtr, /* The depth of the returned visual is stored
+ * here. */
+ Colormap *colormapPtr) /* If non-NULL, then a suitable colormap for
+ * visual is placed here. This colormap must
+ * eventually be freed by calling
+ * Tk_FreeColormap. */
+{
+ Tk_Window tkwin2;
+ XVisualInfo template, *visInfoList, *bestPtr;
+ long mask;
+ Visual *visual;
+ ptrdiff_t length;
+ int c, numVisuals, prio, bestPrio, i;
+ const char *p;
+ const VisualDictionary *dictPtr;
+ TkColormap *cmapPtr;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+
+ /*
+ * Parse string and set up a template for use in searching for an
+ * appropriate visual.
+ */
+
+ c = string[0];
+ if (c == '.') {
+ /*
+ * The string must be a window name. If the window is on the same
+ * screen as tkwin, then just use its visual. Otherwise use the
+ * information about the visual as a template for the search.
+ */
+
+ tkwin2 = Tk_NameToWindow(interp, string, tkwin);
+ if (tkwin2 == NULL) {
+ return NULL;
+ }
+ visual = Tk_Visual(tkwin2);
+ if (Tk_Screen(tkwin) == Tk_Screen(tkwin2)) {
+ *depthPtr = Tk_Depth(tkwin2);
+ if (colormapPtr != NULL) {
+ /*
+ * Use the colormap from the other window too (but be sure to
+ * increment its reference count if it's one of the ones
+ * allocated here).
+ */
+
+ *colormapPtr = Tk_Colormap(tkwin2);
+ for (cmapPtr = dispPtr->cmapPtr; cmapPtr != NULL;
+ cmapPtr = cmapPtr->nextPtr) {
+ if (cmapPtr->colormap == *colormapPtr) {
+ cmapPtr->refCount += 1;
+ break;
+ }
+ }
+ }
+ return visual;
+ }
+ template.depth = Tk_Depth(tkwin2);
+ template.class = visual->class;
+ template.red_mask = visual->red_mask;
+ template.green_mask = visual->green_mask;
+ template.blue_mask = visual->blue_mask;
+ template.colormap_size = visual->map_entries;
+ template.bits_per_rgb = visual->bits_per_rgb;
+ mask = VisualDepthMask|VisualClassMask|VisualRedMaskMask
+ |VisualGreenMaskMask|VisualBlueMaskMask|VisualColormapSizeMask
+ |VisualBitsPerRGBMask;
+ } else if ((c == 0) || ((c == 'd') && (string[1] != 0)
+ && (strncmp(string, "default", strlen(string)) == 0))) {
+ /*
+ * Use the default visual for the window's screen.
+ */
+
+ if (colormapPtr != NULL) {
+ *colormapPtr = DefaultColormapOfScreen(Tk_Screen(tkwin));
+ }
+ *depthPtr = DefaultDepthOfScreen(Tk_Screen(tkwin));
+ return DefaultVisualOfScreen(Tk_Screen(tkwin));
+ } else if (isdigit(UCHAR(c))) {
+ int visualId;
+
+ /*
+ * This is a visual ID.
+ */
+
+ if (Tcl_GetInt(interp, string, &visualId) == TCL_ERROR) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad X identifier for visual: \"%s\"", string));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "VISUALID", NULL);
+ return NULL;
+ }
+ template.visualid = visualId;
+ mask = VisualIDMask;
+ } else {
+ /*
+ * Parse the string into a class name (or "best") optionally followed
+ * by whitespace and a depth.
+ */
+
+ for (p = string; *p != 0; p++) {
+ if (isspace(UCHAR(*p)) || isdigit(UCHAR(*p))) {
+ break;
+ }
+ }
+ length = p - string;
+ template.class = -1;
+ for (dictPtr = visualNames; dictPtr->name != NULL; dictPtr++) {
+ if ((dictPtr->name[0] == c) && (length >= dictPtr->minLength)
+ && (strncmp(string, dictPtr->name,
+ (size_t) length) == 0)) {
+ template.class = dictPtr->class;
+ break;
+ }
+ }
+ if (template.class == -1) {
+ Tcl_Obj *msgObj = Tcl_ObjPrintf(
+ "unknown or ambiguous visual name \"%s\": class must be ",
+ string);
+
+ for (dictPtr = visualNames; dictPtr->name != NULL; dictPtr++) {
+ Tcl_AppendPrintfToObj(msgObj, "%s, ", dictPtr->name);
+ }
+ Tcl_AppendToObj(msgObj, "or default", -1);
+ Tcl_SetObjResult(interp, msgObj);
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "VISUAL", string, NULL);
+ return NULL;
+ }
+ while (isspace(UCHAR(*p))) {
+ p++;
+ }
+ if (*p == 0) {
+ template.depth = 10000;
+ } else if (Tcl_GetInt(interp, p, &template.depth) != TCL_OK) {
+ return NULL;
+ }
+ if (c == 'b') {
+ mask = 0;
+ } else {
+ mask = VisualClassMask;
+ }
+ }
+
+ /*
+ * Find all visuals that match the template we've just created, and return
+ * an error if there are none that match.
+ */
+
+ template.screen = Tk_ScreenNumber(tkwin);
+ mask |= VisualScreenMask;
+ visInfoList = XGetVisualInfo(Tk_Display(tkwin), mask, &template,
+ &numVisuals);
+ if (visInfoList == NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "couldn't find an appropriate visual", -1));
+ Tcl_SetErrorCode(interp, "TK", "VISUAL", "INAPPROPRIATE", NULL);
+ return NULL;
+ }
+
+ /*
+ * Search through the visuals that were returned to find the best one.
+ * The choice is based on the following criteria, in decreasing order of
+ * importance:
+ *
+ * 1. Depth: choose a visual with exactly the desired depth, else one with
+ * more bits than requested but as few bits as possible, else one with
+ * fewer bits but as many as possible.
+ * 2. Class: some visual classes are more desirable than others; pick the
+ * visual with the most desirable class.
+ * 3. Default: the default visual for the screen gets preference over
+ * other visuals, all else being equal.
+ */
+
+ bestPrio = 0;
+ bestPtr = NULL;
+ for (i = 0; i < numVisuals; i++) {
+ switch (visInfoList[i].class) {
+ case DirectColor:
+ prio = 5; break;
+ case GrayScale:
+ prio = 1; break;
+ case PseudoColor:
+ prio = 7; break;
+ case StaticColor:
+ prio = 3; break;
+ case StaticGray:
+ prio = 1; break;
+ case TrueColor:
+ prio = 5; break;
+ default:
+ prio = 0; break;
+ }
+ if (visInfoList[i].visual
+ == DefaultVisualOfScreen(Tk_Screen(tkwin))) {
+ prio++;
+ }
+ if (bestPtr == NULL) {
+ goto newBest;
+ }
+ if (visInfoList[i].depth < bestPtr->depth) {
+ if (visInfoList[i].depth >= template.depth) {
+ goto newBest;
+ }
+ } else if (visInfoList[i].depth > bestPtr->depth) {
+ if (bestPtr->depth < template.depth) {
+ goto newBest;
+ }
+ } else {
+ if (prio > bestPrio) {
+ goto newBest;
+ }
+ }
+ continue;
+
+ newBest:
+ bestPtr = &visInfoList[i];
+ bestPrio = prio;
+ }
+ CLANG_ASSERT(bestPtr);
+ *depthPtr = bestPtr->depth;
+ visual = bestPtr->visual;
+ XFree((char *) visInfoList);
+
+ /*
+ * If we need to find a colormap for this visual, do it now. If the visual
+ * is the default visual for the screen, then use the default colormap.
+ * Otherwise search for an existing colormap that's shareable. If all else
+ * fails, create a new colormap.
+ */
+
+ if (colormapPtr != NULL) {
+ if (visual == DefaultVisualOfScreen(Tk_Screen(tkwin))) {
+ *colormapPtr = DefaultColormapOfScreen(Tk_Screen(tkwin));
+ } else {
+ for (cmapPtr = dispPtr->cmapPtr; cmapPtr != NULL;
+ cmapPtr = cmapPtr->nextPtr) {
+ if (cmapPtr->shareable && (cmapPtr->visual == visual)) {
+ *colormapPtr = cmapPtr->colormap;
+ cmapPtr->refCount += 1;
+ goto done;
+ }
+ }
+ cmapPtr = ckalloc(sizeof(TkColormap));
+ cmapPtr->colormap = XCreateColormap(Tk_Display(tkwin),
+ RootWindowOfScreen(Tk_Screen(tkwin)), visual,
+ AllocNone);
+ cmapPtr->visual = visual;
+ cmapPtr->refCount = 1;
+ cmapPtr->shareable = 1;
+ cmapPtr->nextPtr = dispPtr->cmapPtr;
+ dispPtr->cmapPtr = cmapPtr;
+ *colormapPtr = cmapPtr->colormap;
+ }
+ }
+
+ done:
+ return visual;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetColormap --
+ *
+ * Given a string identifying a colormap, this procedure finds an
+ * appropriate colormap.
+ *
+ * Results:
+ * The return value is normally the X resource identifier for the
+ * colormap. If an error occurs, None is returned and an error message is
+ * placed in the interp's result.
+ *
+ * Side effects:
+ * A reference count is incremented for the colormap, so Tk_FreeColormap
+ * must eventually be called exactly once for each call to
+ * Tk_GetColormap.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Colormap
+Tk_GetColormap(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting. */
+ Tk_Window tkwin, /* Window where colormap will be used. */
+ const char *string) /* String that identifies colormap: either
+ * "new" or the name of another window. */
+{
+ Colormap colormap;
+ TkColormap *cmapPtr;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+ Tk_Window other;
+
+ /*
+ * Allocate a new colormap, if that's what is wanted.
+ */
+
+ if (strcmp(string, "new") == 0) {
+ cmapPtr = ckalloc(sizeof(TkColormap));
+ cmapPtr->colormap = XCreateColormap(Tk_Display(tkwin),
+ RootWindowOfScreen(Tk_Screen(tkwin)), Tk_Visual(tkwin),
+ AllocNone);
+ cmapPtr->visual = Tk_Visual(tkwin);
+ cmapPtr->refCount = 1;
+ cmapPtr->shareable = 0;
+ cmapPtr->nextPtr = dispPtr->cmapPtr;
+ dispPtr->cmapPtr = cmapPtr;
+ return cmapPtr->colormap;
+ }
+
+ /*
+ * Use a colormap from an existing window. It must have the same visual as
+ * tkwin (which means, among other things, that the other window must be
+ * on the same screen).
+ */
+
+ other = Tk_NameToWindow(interp, string, tkwin);
+ if (other == NULL) {
+ return None;
+ }
+ if (Tk_Screen(other) != Tk_Screen(tkwin)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't use colormap for %s: not on same screen", string));
+ Tcl_SetErrorCode(interp, "TK", "COLORMAP", "SCREEN", NULL);
+ return None;
+ }
+ if (Tk_Visual(other) != Tk_Visual(tkwin)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't use colormap for %s: incompatible visuals", string));
+ Tcl_SetErrorCode(interp, "TK", "COLORMAP", "INCOMPATIBLE", NULL);
+ return None;
+ }
+ colormap = Tk_Colormap(other);
+
+ /*
+ * If the colormap was a special one allocated by code in this file,
+ * increment its reference count.
+ */
+
+ for (cmapPtr = dispPtr->cmapPtr; cmapPtr != NULL;
+ cmapPtr = cmapPtr->nextPtr) {
+ if (cmapPtr->colormap == colormap) {
+ cmapPtr->refCount += 1;
+ }
+ }
+ return colormap;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_FreeColormap --
+ *
+ * This procedure is called to release a colormap that was previously
+ * allocated by Tk_GetColormap.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The colormap's reference count is decremented. If this was the last
+ * reference to the colormap, then the colormap is freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_FreeColormap(
+ Display *display, /* Display for which colormap was
+ * allocated. */
+ Colormap colormap) /* Colormap that is no longer needed. Must
+ * have been returned by previous call to
+ * Tk_GetColormap, or preserved by a previous
+ * call to Tk_PreserveColormap. */
+{
+ TkDisplay *dispPtr;
+ TkColormap *cmapPtr, *prevPtr;
+
+ /*
+ * Find Tk's information about the display, then see if this colormap is a
+ * non-default one (if it's a default one, there won't be an entry for it
+ * in the display's list).
+ */
+
+ dispPtr = TkGetDisplay(display);
+ if (dispPtr == NULL) {
+ Tcl_Panic("unknown display passed to Tk_FreeColormap");
+ }
+ for (prevPtr = NULL, cmapPtr = dispPtr->cmapPtr; cmapPtr != NULL;
+ prevPtr = cmapPtr, cmapPtr = cmapPtr->nextPtr) {
+ if (cmapPtr->colormap == colormap) {
+ cmapPtr->refCount -= 1;
+ if (cmapPtr->refCount == 0) {
+ XFreeColormap(display, colormap);
+ if (prevPtr == NULL) {
+ dispPtr->cmapPtr = cmapPtr->nextPtr;
+ } else {
+ prevPtr->nextPtr = cmapPtr->nextPtr;
+ }
+ ckfree(cmapPtr);
+ }
+ return;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_PreserveColormap --
+ *
+ * This procedure is called to indicate to Tk that the specified colormap
+ * is being referenced from another location and should not be freed
+ * until all extra references are eliminated. The colormap must have been
+ * returned by Tk_GetColormap.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The colormap's reference count is incremented, so Tk_FreeColormap must
+ * eventually be called exactly once for each call to
+ * Tk_PreserveColormap.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_PreserveColormap(
+ Display *display, /* Display for which colormap was
+ * allocated. */
+ Colormap colormap) /* Colormap that should be preserved. */
+{
+ TkDisplay *dispPtr;
+ TkColormap *cmapPtr;
+
+ /*
+ * Find Tk's information about the display, then see if this colormap is a
+ * non-default one (if it's a default one, there won't be an entry for it
+ * in the display's list).
+ */
+
+ dispPtr = TkGetDisplay(display);
+ if (dispPtr == NULL) {
+ Tcl_Panic("unknown display passed to Tk_PreserveColormap");
+ }
+ for (cmapPtr = dispPtr->cmapPtr; cmapPtr != NULL;
+ cmapPtr = cmapPtr->nextPtr) {
+ if (cmapPtr->colormap == colormap) {
+ cmapPtr->refCount += 1;
+ return;
+ }
+ }
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/tkWindow.c b/tk8.6/generic/tkWindow.c
new file mode 100644
index 0000000..51cbaf3
--- /dev/null
+++ b/tk8.6/generic/tkWindow.c
@@ -0,0 +1,3414 @@
+/*
+ * tkWindow.c --
+ *
+ * This file provides basic window-manipulation functions, which are
+ * equivalent to functions in Xlib (and even invoke them) but also
+ * maintain the local Tk_Window structure.
+ *
+ * Copyright (c) 1989-1994 The Regents of the University of California.
+ * Copyright (c) 1994-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.
+ */
+
+#include "tkInt.h"
+
+#ifdef _WIN32
+#include "tkWinInt.h"
+#elif !defined(MAC_OSX_TK)
+#include "tkUnixInt.h"
+#endif
+
+/*
+ * Type used to keep track of Window objects that were only partially
+ * deallocated by Tk_DestroyWindow.
+ */
+
+#define HD_CLEANUP 1
+#define HD_FOCUS 2
+#define HD_MAIN_WIN 4
+#define HD_DESTROY_COUNT 8
+#define HD_DESTROY_EVENT 0x10
+
+typedef struct TkHalfdeadWindow {
+ int flags;
+ struct TkWindow *winPtr;
+ struct TkHalfdeadWindow *nextPtr;
+} TkHalfdeadWindow;
+
+typedef struct {
+ int numMainWindows; /* Count of numver of main windows currently
+ * open in this thread. */
+ TkMainInfo *mainWindowList;
+ /* First in list of all main windows managed
+ * by this thread. */
+ TkHalfdeadWindow *halfdeadWindowList;
+ /* First in list of partially deallocated
+ * windows. */
+ TkDisplay *displayList; /* List of all displays currently in use by
+ * the current thread. */
+ int initialized; /* 0 means the structures above need
+ * initializing. */
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+
+/*
+ * Default values for "changes" and "atts" fields of TkWindows. Note that Tk
+ * always requests all events for all windows, except StructureNotify events
+ * on internal windows: these events are generated internally.
+ */
+
+static const XWindowChanges defChanges = {
+ 0, 0, 1, 1, 0, 0, Above
+};
+#define ALL_EVENTS_MASK \
+ KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask| \
+ EnterWindowMask|LeaveWindowMask|PointerMotionMask|ExposureMask| \
+ VisibilityChangeMask|PropertyChangeMask|ColormapChangeMask
+static const XSetWindowAttributes defAtts= {
+ None, /* background_pixmap */
+ 0, /* background_pixel */
+ CopyFromParent, /* border_pixmap */
+ 0, /* border_pixel */
+ NorthWestGravity, /* bit_gravity */
+ NorthWestGravity, /* win_gravity */
+ NotUseful, /* backing_store */
+ (unsigned) ~0, /* backing_planes */
+ 0, /* backing_pixel */
+ False, /* save_under */
+ ALL_EVENTS_MASK, /* event_mask */
+ 0, /* do_not_propagate_mask */
+ False, /* override_redirect */
+ CopyFromParent, /* colormap */
+ None /* cursor */
+};
+
+/*
+ * The following structure defines all of the commands supported by Tk, and
+ * the C functions that execute them.
+ */
+
+#define ISSAFE 1
+#define PASSMAINWINDOW 2
+#define WINMACONLY 4
+#define USEINITPROC 8
+
+typedef int (TkInitProc)(Tcl_Interp *interp, ClientData clientData);
+typedef struct {
+ const char *name; /* Name of command. */
+ Tcl_ObjCmdProc *objProc; /* Command's object- (or string-) based
+ * function, or initProc. */
+ int flags;
+} TkCmd;
+
+static const TkCmd commands[] = {
+ /*
+ * Commands that are part of the intrinsics:
+ */
+
+ {"bell", Tk_BellObjCmd, PASSMAINWINDOW},
+ {"bind", Tk_BindObjCmd, PASSMAINWINDOW|ISSAFE},
+ {"bindtags", Tk_BindtagsObjCmd, PASSMAINWINDOW|ISSAFE},
+ {"clipboard", Tk_ClipboardObjCmd, PASSMAINWINDOW},
+ {"destroy", Tk_DestroyObjCmd, PASSMAINWINDOW|ISSAFE},
+ {"event", Tk_EventObjCmd, PASSMAINWINDOW|ISSAFE},
+ {"focus", Tk_FocusObjCmd, PASSMAINWINDOW|ISSAFE},
+ {"font", Tk_FontObjCmd, PASSMAINWINDOW|ISSAFE},
+ {"grab", Tk_GrabObjCmd, PASSMAINWINDOW},
+ {"grid", Tk_GridObjCmd, PASSMAINWINDOW|ISSAFE},
+ {"image", Tk_ImageObjCmd, PASSMAINWINDOW|ISSAFE},
+ {"lower", Tk_LowerObjCmd, PASSMAINWINDOW|ISSAFE},
+ {"option", Tk_OptionObjCmd, PASSMAINWINDOW|ISSAFE},
+ {"pack", Tk_PackObjCmd, PASSMAINWINDOW|ISSAFE},
+ {"place", Tk_PlaceObjCmd, PASSMAINWINDOW|ISSAFE},
+ {"raise", Tk_RaiseObjCmd, PASSMAINWINDOW|ISSAFE},
+ {"selection", Tk_SelectionObjCmd, PASSMAINWINDOW},
+ {"tk", (Tcl_ObjCmdProc *) TkInitTkCmd, USEINITPROC|PASSMAINWINDOW|ISSAFE},
+ {"tkwait", Tk_TkwaitObjCmd, PASSMAINWINDOW|ISSAFE},
+ {"update", Tk_UpdateObjCmd, PASSMAINWINDOW|ISSAFE},
+ {"winfo", Tk_WinfoObjCmd, PASSMAINWINDOW|ISSAFE},
+ {"wm", Tk_WmObjCmd, PASSMAINWINDOW},
+
+ /*
+ * Default widget class commands.
+ */
+
+ {"button", Tk_ButtonObjCmd, ISSAFE},
+ {"canvas", Tk_CanvasObjCmd, PASSMAINWINDOW|ISSAFE},
+ {"checkbutton", Tk_CheckbuttonObjCmd, ISSAFE},
+ {"entry", Tk_EntryObjCmd, ISSAFE},
+ {"frame", Tk_FrameObjCmd, ISSAFE},
+ {"label", Tk_LabelObjCmd, ISSAFE},
+ {"labelframe", Tk_LabelframeObjCmd, ISSAFE},
+ {"listbox", Tk_ListboxObjCmd, ISSAFE},
+ {"menu", Tk_MenuObjCmd, PASSMAINWINDOW},
+ {"menubutton", Tk_MenubuttonObjCmd, ISSAFE},
+ {"message", Tk_MessageObjCmd, ISSAFE},
+ {"panedwindow", Tk_PanedWindowObjCmd, ISSAFE},
+ {"radiobutton", Tk_RadiobuttonObjCmd, ISSAFE},
+ {"scale", Tk_ScaleObjCmd, ISSAFE},
+ {"scrollbar", Tk_ScrollbarObjCmd, PASSMAINWINDOW|ISSAFE},
+ {"spinbox", Tk_SpinboxObjCmd, ISSAFE},
+ {"text", Tk_TextObjCmd, PASSMAINWINDOW|ISSAFE},
+ {"toplevel", Tk_ToplevelObjCmd, 0},
+
+ /*
+ * Classic widget class commands.
+ */
+
+ {"::tk::button", Tk_ButtonObjCmd, ISSAFE},
+ {"::tk::canvas", Tk_CanvasObjCmd, PASSMAINWINDOW|ISSAFE},
+ {"::tk::checkbutton",Tk_CheckbuttonObjCmd, ISSAFE},
+ {"::tk::entry", Tk_EntryObjCmd, ISSAFE},
+ {"::tk::frame", Tk_FrameObjCmd, ISSAFE},
+ {"::tk::label", Tk_LabelObjCmd, ISSAFE},
+ {"::tk::labelframe",Tk_LabelframeObjCmd, ISSAFE},
+ {"::tk::listbox", Tk_ListboxObjCmd, ISSAFE},
+ {"::tk::menubutton",Tk_MenubuttonObjCmd, ISSAFE},
+ {"::tk::message", Tk_MessageObjCmd, ISSAFE},
+ {"::tk::panedwindow",Tk_PanedWindowObjCmd, ISSAFE},
+ {"::tk::radiobutton",Tk_RadiobuttonObjCmd, ISSAFE},
+ {"::tk::scale", Tk_ScaleObjCmd, ISSAFE},
+ {"::tk::scrollbar", Tk_ScrollbarObjCmd, PASSMAINWINDOW|ISSAFE},
+ {"::tk::spinbox", Tk_SpinboxObjCmd, ISSAFE},
+ {"::tk::text", Tk_TextObjCmd, PASSMAINWINDOW|ISSAFE},
+ {"::tk::toplevel", Tk_ToplevelObjCmd, 0},
+
+ /*
+ * Standard dialog support. Note that the Unix/X11 platform implements
+ * these commands differently (via the script library).
+ */
+
+#if defined(_WIN32) || defined(MAC_OSX_TK)
+ {"tk_chooseColor", Tk_ChooseColorObjCmd, PASSMAINWINDOW},
+ {"tk_chooseDirectory", Tk_ChooseDirectoryObjCmd,WINMACONLY|PASSMAINWINDOW},
+ {"tk_getOpenFile", Tk_GetOpenFileObjCmd, WINMACONLY|PASSMAINWINDOW},
+ {"tk_getSaveFile", Tk_GetSaveFileObjCmd, WINMACONLY|PASSMAINWINDOW},
+ {"tk_messageBox", Tk_MessageBoxObjCmd, PASSMAINWINDOW},
+#endif
+
+ /*
+ * Misc.
+ */
+
+#ifdef MAC_OSX_TK
+ {"::tk::unsupported::MacWindowStyle",
+ TkUnsupported1ObjCmd, PASSMAINWINDOW|ISSAFE},
+#endif
+ {NULL, NULL, 0}
+};
+
+/*
+ * Forward declarations to functions defined later in this file:
+ */
+
+static Tk_Window CreateTopLevelWindow(Tcl_Interp *interp,
+ Tk_Window parent, const char *name,
+ const char *screenName, unsigned int flags);
+static void DeleteWindowsExitProc(ClientData clientData);
+static TkDisplay * GetScreen(Tcl_Interp *interp, const char *screenName,
+ int *screenPtr);
+static int Initialize(Tcl_Interp *interp);
+static int NameWindow(Tcl_Interp *interp, TkWindow *winPtr,
+ TkWindow *parentPtr, const char *name);
+static void UnlinkWindow(TkWindow *winPtr);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkCloseDisplay --
+ *
+ * Closing the display can lead to order of deletion problems. We defer
+ * it until exit handling for Mac/Win, but since Unix can use many
+ * displays, try and clean it up as best as possible.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Resources associated with the display will be free. The display may
+ * not be referenced at all after this.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+TkCloseDisplay(
+ TkDisplay *dispPtr)
+{
+ TkClipCleanup(dispPtr);
+
+ TkpCancelWarp(dispPtr);
+
+ if (dispPtr->name != NULL) {
+ ckfree(dispPtr->name);
+ }
+
+ if (dispPtr->atomInit) {
+ Tcl_DeleteHashTable(&dispPtr->nameTable);
+ Tcl_DeleteHashTable(&dispPtr->atomTable);
+ dispPtr->atomInit = 0;
+ }
+
+ if (dispPtr->errorPtr != NULL) {
+ TkErrorHandler *errorPtr;
+
+ for (errorPtr = dispPtr->errorPtr;
+ errorPtr != NULL;
+ errorPtr = dispPtr->errorPtr) {
+ dispPtr->errorPtr = errorPtr->nextPtr;
+ ckfree(errorPtr);
+ }
+ }
+
+ TkGCCleanup(dispPtr);
+
+ TkpCloseDisplay(dispPtr);
+
+ /*
+ * Delete winTable after TkpCloseDisplay since special windows may need
+ * call Tk_DestroyWindow and it checks the winTable.
+ */
+
+ Tcl_DeleteHashTable(&dispPtr->winTable);
+
+ ckfree(dispPtr);
+
+ /*
+ * There is more to clean up, we leave it at this for the time being.
+ */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CreateTopLevelWindow --
+ *
+ * Make a new window that will be at top-level (its parent will be the
+ * root window of a screen).
+ *
+ * Results:
+ * The return value is a token for the new window, or NULL if an error
+ * prevented the new window from being created. If NULL is returned, an
+ * error message will be left in the interp's result.
+ *
+ * Side effects:
+ * A new window structure is allocated locally. An X window is NOT
+ * initially created, but will be created the first time the window is
+ * mapped.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tk_Window
+CreateTopLevelWindow(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting. */
+ Tk_Window parent, /* Token for logical parent of new window
+ * (used for naming, options, etc.). May be
+ * NULL. */
+ const char *name, /* Name for new window; if parent is non-NULL,
+ * must be unique among parent's children. */
+ const char *screenName, /* Name of screen on which to create window.
+ * NULL means use DISPLAY environment variable
+ * to determine. Empty string means use
+ * parent's screen, or DISPLAY if no
+ * parent. */
+ unsigned int flags) /* Additional flags to set on the window. */
+{
+ register TkWindow *winPtr;
+ register TkDisplay *dispPtr;
+ int screenId;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (!tsdPtr->initialized) {
+ tsdPtr->initialized = 1;
+
+ /*
+ * Create built-in image types.
+ */
+
+ Tk_CreateImageType(&tkBitmapImageType);
+ Tk_CreateImageType(&tkPhotoImageType);
+
+ /*
+ * Create built-in photo image formats.
+ */
+
+ Tk_CreatePhotoImageFormat(&tkImgFmtGIF);
+ Tk_CreatePhotoImageFormat(&tkImgFmtPNG);
+ Tk_CreatePhotoImageFormat(&tkImgFmtPPM);
+ }
+
+ if ((parent != NULL) && (screenName != NULL) && (screenName[0] == '\0')) {
+ dispPtr = ((TkWindow *) parent)->dispPtr;
+ screenId = Tk_ScreenNumber(parent);
+ } else {
+ dispPtr = GetScreen(interp, screenName, &screenId);
+ if (dispPtr == NULL) {
+ return NULL;
+ }
+ }
+
+ winPtr = TkAllocWindow(dispPtr, screenId, (TkWindow *) parent);
+
+ /*
+ * Set the flags specified in the call.
+ */
+
+#ifdef TK_USE_INPUT_METHODS
+ winPtr->ximGeneration = 0;
+#endif /*TK_USE_INPUT_METHODS*/
+ winPtr->flags |= flags;
+
+ /*
+ * Force the window to use a border pixel instead of border pixmap. This
+ * is needed for the case where the window doesn't use the default visual.
+ * In this case, the default border is a pixmap inherited from the root
+ * window, which won't work because it will have the wrong visual.
+ */
+
+ winPtr->dirtyAtts |= CWBorderPixel;
+
+ /*
+ * (Need to set the TK_TOP_HIERARCHY flag immediately here; otherwise
+ * Tk_DestroyWindow will core dump if it is called before the flag has
+ * been set.)
+ */
+
+ winPtr->flags |=
+ TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED;
+
+ if (parent != NULL) {
+ if (NameWindow(interp, winPtr, (TkWindow *) parent, name) != TCL_OK) {
+ Tk_DestroyWindow((Tk_Window) winPtr);
+ return NULL;
+ }
+ }
+ TkWmNewWindow(winPtr);
+
+ return (Tk_Window) winPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetScreen --
+ *
+ * Given a string name for a display-plus-screen, find the TkDisplay
+ * structure for the display and return the screen number too.
+ *
+ * Results:
+ * The return value is a pointer to information about the display, or
+ * NULL if the display couldn't be opened. In this case, an error message
+ * is left in the interp's result. The location at *screenPtr is
+ * overwritten with the screen number parsed from screenName.
+ *
+ * Side effects:
+ * A new connection is opened to the display if there is no connection
+ * already. A new TkDisplay data structure is also setup, if necessary.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static TkDisplay *
+GetScreen(
+ Tcl_Interp *interp, /* Place to leave error message. */
+ const char *screenName, /* Name for screen. NULL or empty means use
+ * DISPLAY envariable. */
+ int *screenPtr) /* Where to store screen number. */
+{
+ register TkDisplay *dispPtr;
+ const char *p;
+ int screenId;
+ size_t length;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ /*
+ * Separate the screen number from the rest of the display name.
+ * ScreenName is assumed to have the syntax <display>.<screen> with the
+ * dot and the screen being optional.
+ */
+
+ screenName = TkGetDefaultScreenName(interp, screenName);
+ if (screenName == NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "no display name and no $DISPLAY environment variable", -1));
+ Tcl_SetErrorCode(interp, "TK", "NO_DISPLAY", NULL);
+ return NULL;
+ }
+ length = strlen(screenName);
+ screenId = 0;
+ p = screenName+length-1;
+ while (isdigit(UCHAR(*p)) && (p != screenName)) {
+ p--;
+ }
+ if ((*p == '.') && (p[1] != '\0')) {
+ length = p - screenName;
+ screenId = strtoul(p+1, NULL, 10);
+ }
+
+ /*
+ * See if we already have a connection to this display. If not, then open
+ * a new connection.
+ */
+
+ for (dispPtr = tsdPtr->displayList; ; dispPtr = dispPtr->nextPtr) {
+ if (dispPtr == NULL) {
+ /*
+ * The private function zeros out dispPtr when it is created, so
+ * we only need to initialize the non-zero items.
+ */
+
+ dispPtr = TkpOpenDisplay(screenName);
+ if (dispPtr == NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "couldn't connect to display \"%s\"", screenName));
+ Tcl_SetErrorCode(interp, "TK", "DISPLAY", "CONNECT", NULL);
+ return NULL;
+ }
+ dispPtr->nextPtr = tsdPtr->displayList; /* TkGetDisplayList(); */
+ tsdPtr->displayList = dispPtr;
+
+ dispPtr->lastEventTime = CurrentTime;
+ dispPtr->bindInfoStale = 1;
+ dispPtr->cursorFont = None;
+ dispPtr->warpWindow = NULL;
+ dispPtr->multipleAtom = None;
+
+ /*
+ * By default we do want to collapse motion events in
+ * Tk_QueueWindowEvent.
+ */
+
+ dispPtr->flags |= TK_DISPLAY_COLLAPSE_MOTION_EVENTS;
+
+ Tcl_InitHashTable(&dispPtr->winTable, TCL_ONE_WORD_KEYS);
+
+ dispPtr->name = ckalloc(length + 1);
+ strncpy(dispPtr->name, screenName, length);
+ dispPtr->name[length] = '\0';
+ break;
+ }
+ if ((strncmp(dispPtr->name, screenName, length) == 0)
+ && (dispPtr->name[length] == '\0')) {
+ break;
+ }
+ }
+ if (screenId >= ScreenCount(dispPtr->display)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad screen number \"%d\"", screenId));
+ Tcl_SetErrorCode(interp, "TK", "DISPLAY", "SCREEN_NUMBER", NULL);
+ return NULL;
+ }
+ *screenPtr = screenId;
+ return dispPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkGetDisplay --
+ *
+ * Given an X display, TkGetDisplay returns the TkDisplay structure for
+ * the display.
+ *
+ * Results:
+ * The return value is a pointer to information about the display, or
+ * NULL if the display did not have a TkDisplay structure.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkDisplay *
+TkGetDisplay(
+ Display *display) /* X's display pointer */
+{
+ TkDisplay *dispPtr;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ for (dispPtr = tsdPtr->displayList; dispPtr != NULL;
+ dispPtr = dispPtr->nextPtr) {
+ if (dispPtr->display == display) {
+ break;
+ }
+ }
+ return dispPtr;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkGetDisplayList --
+ *
+ * This function returns a pointer to the thread-local list of TkDisplays
+ * corresponding to the open displays.
+ *
+ * Results:
+ * The return value is a pointer to the first TkDisplay structure in
+ * thread-local-storage.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+TkDisplay *
+TkGetDisplayList(void)
+{
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ return tsdPtr->displayList;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkGetMainInfoList --
+ *
+ * This function returns a pointer to the list of structures containing
+ * information about all main windows for the current thread.
+ *
+ * Results:
+ * The return value is a pointer to the first TkMainInfo structure in
+ * thread local storage.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+TkMainInfo *
+TkGetMainInfoList(void)
+{
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ return tsdPtr->mainWindowList;
+}
+/*
+ *--------------------------------------------------------------
+ *
+ * TkAllocWindow --
+ *
+ * This function creates and initializes a TkWindow structure.
+ *
+ * Results:
+ * The return value is a pointer to the new window.
+ *
+ * Side effects:
+ * A new window structure is allocated and all its fields are
+ * initialized.
+ *
+ *--------------------------------------------------------------
+ */
+
+TkWindow *
+TkAllocWindow(
+ TkDisplay *dispPtr, /* Display associated with new window. */
+ int screenNum, /* Index of screen for new window. */
+ TkWindow *parentPtr) /* Parent from which this window should
+ * inherit visual information. NULL means use
+ * screen defaults instead of inheriting. */
+{
+ register TkWindow *winPtr = ckalloc(sizeof(TkWindow));
+
+ winPtr->display = dispPtr->display;
+ winPtr->dispPtr = dispPtr;
+ winPtr->screenNum = screenNum;
+ if ((parentPtr != NULL) && (parentPtr->display == winPtr->display)
+ && (parentPtr->screenNum == winPtr->screenNum)) {
+ winPtr->visual = parentPtr->visual;
+ winPtr->depth = parentPtr->depth;
+ } else {
+ winPtr->visual = DefaultVisual(dispPtr->display, screenNum);
+ winPtr->depth = DefaultDepth(dispPtr->display, screenNum);
+ }
+ winPtr->window = None;
+ winPtr->childList = NULL;
+ winPtr->lastChildPtr = NULL;
+ winPtr->parentPtr = NULL;
+ winPtr->nextPtr = NULL;
+ winPtr->mainPtr = NULL;
+ winPtr->pathName = NULL;
+ winPtr->nameUid = NULL;
+ winPtr->classUid = NULL;
+ winPtr->changes = defChanges;
+ winPtr->dirtyChanges = CWX|CWY|CWWidth|CWHeight|CWBorderWidth;
+ winPtr->atts = defAtts;
+ if ((parentPtr != NULL) && (parentPtr->display == winPtr->display)
+ && (parentPtr->screenNum == winPtr->screenNum)) {
+ winPtr->atts.colormap = parentPtr->atts.colormap;
+ } else {
+ winPtr->atts.colormap = DefaultColormap(dispPtr->display, screenNum);
+ }
+ winPtr->dirtyAtts = CWEventMask|CWColormap|CWBitGravity;
+ winPtr->flags = 0;
+ winPtr->handlerList = NULL;
+#ifdef TK_USE_INPUT_METHODS
+ winPtr->ximGeneration = 0;
+ winPtr->inputContext = NULL;
+#endif /* TK_USE_INPUT_METHODS */
+ winPtr->tagPtr = NULL;
+ winPtr->numTags = 0;
+ winPtr->optionLevel = -1;
+ winPtr->selHandlerList = NULL;
+ winPtr->geomMgrPtr = NULL;
+ winPtr->geomData = NULL;
+ winPtr->geomMgrName = NULL;
+ winPtr->maintainerPtr = NULL;
+ winPtr->reqWidth = winPtr->reqHeight = 1;
+ winPtr->internalBorderLeft = 0;
+ winPtr->wmInfoPtr = NULL;
+ winPtr->classProcsPtr = NULL;
+ winPtr->instanceData = NULL;
+ winPtr->privatePtr = NULL;
+ winPtr->internalBorderRight = 0;
+ winPtr->internalBorderTop = 0;
+ winPtr->internalBorderBottom = 0;
+ winPtr->minReqWidth = 0;
+ winPtr->minReqHeight = 0;
+
+ return winPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NameWindow --
+ *
+ * This function is invoked to give a window a name and insert the window
+ * into the hierarchy associated with a particular application.
+ *
+ * Results:
+ * A standard Tcl return value.
+ *
+ * Side effects:
+ * See above.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+NameWindow(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting. */
+ register TkWindow *winPtr, /* Window that is to be named and inserted. */
+ TkWindow *parentPtr, /* Pointer to logical parent for winPtr (used
+ * for naming, options, etc.). */
+ const char *name) /* Name for winPtr; must be unique among
+ * parentPtr's children. */
+{
+#define FIXED_SIZE 200
+ char staticSpace[FIXED_SIZE];
+ char *pathName;
+ int isNew;
+ Tcl_HashEntry *hPtr;
+ size_t length1, length2;
+
+ /*
+ * Setup all the stuff except name right away, then do the name stuff
+ * last. This is so that if the name stuff fails, everything else will be
+ * properly initialized (needed to destroy the window cleanly after the
+ * naming failure).
+ */
+
+ winPtr->parentPtr = parentPtr;
+ winPtr->nextPtr = NULL;
+ if (parentPtr->childList == NULL) {
+ parentPtr->childList = winPtr;
+ } else {
+ parentPtr->lastChildPtr->nextPtr = winPtr;
+ }
+ parentPtr->lastChildPtr = winPtr;
+ winPtr->mainPtr = parentPtr->mainPtr;
+ winPtr->mainPtr->refCount++;
+
+ /*
+ * If this is an anonymous window (ie, it has no name), just return OK
+ * now.
+ */
+
+ if (winPtr->flags & TK_ANONYMOUS_WINDOW) {
+ return TCL_OK;
+ }
+
+ /*
+ * Don't permit names that start with an upper-case letter: this will just
+ * cause confusion with class names in the option database.
+ */
+
+ if (isupper(UCHAR(name[0]))) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "window name starts with an upper-case letter: \"%s\"",
+ name));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "WINDOW", "NOTCLASS", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * For non-anonymous windows, set up the window name.
+ */
+
+ winPtr->nameUid = Tk_GetUid(name);
+
+ /*
+ * To permit names of arbitrary length, must be prepared to malloc a
+ * buffer to hold the new path name. To run fast in the common case where
+ * names are short, use a fixed-size buffer on the stack.
+ */
+
+ length1 = strlen(parentPtr->pathName);
+ length2 = strlen(name);
+ if ((length1 + length2 + 2) <= FIXED_SIZE) {
+ pathName = staticSpace;
+ } else {
+ pathName = ckalloc(length1 + length2 + 2);
+ }
+ if (length1 == 1) {
+ pathName[0] = '.';
+ strcpy(pathName+1, name);
+ } else {
+ strcpy(pathName, parentPtr->pathName);
+ pathName[length1] = '.';
+ strcpy(pathName+length1+1, name);
+ }
+ hPtr = Tcl_CreateHashEntry(&parentPtr->mainPtr->nameTable, pathName,
+ &isNew);
+ if (pathName != staticSpace) {
+ ckfree(pathName);
+ }
+ if (!isNew) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "window name \"%s\" already exists in parent", name));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "WINDOW", "EXISTS", NULL);
+ return TCL_ERROR;
+ }
+ Tcl_SetHashValue(hPtr, winPtr);
+ winPtr->pathName = Tcl_GetHashKey(&parentPtr->mainPtr->nameTable, hPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkCreateMainWindow --
+ *
+ * Make a new main window. A main window is a special kind of top-level
+ * window used as the outermost window in an application.
+ *
+ * Results:
+ * The return value is a token for the new window, or NULL if an error
+ * prevented the new window from being created. If NULL is returned, an
+ * error message will be left in the interp's result.
+ *
+ * Side effects:
+ * A new window structure is allocated locally; "interp" is associated
+ * with the window and registered for "send" commands under "baseName".
+ * BaseName may be extended with an instance number in the form "#2" if
+ * necessary to make it globally unique. Tk-related commands are bound
+ * into interp.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_Window
+TkCreateMainWindow(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting. */
+ const char *screenName, /* Name of screen on which to create window.
+ * Empty or NULL string means use DISPLAY
+ * environment variable. */
+ const char *baseName) /* Base name for application; usually of the
+ * form "prog instance". */
+{
+ Tk_Window tkwin;
+ int dummy, isSafe;
+ Tcl_HashEntry *hPtr;
+ register TkMainInfo *mainPtr;
+ register TkWindow *winPtr;
+ register const TkCmd *cmdPtr;
+ ClientData clientData;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ /*
+ * Panic if someone updated the TkWindow structure without also updating
+ * the Tk_FakeWin structure (or vice versa).
+ */
+
+ if (sizeof(TkWindow) != sizeof(Tk_FakeWin)) {
+ Tcl_Panic("TkWindow and Tk_FakeWin are not the same size");
+ }
+
+ /*
+ * Create the basic TkWindow structure.
+ */
+
+ tkwin = CreateTopLevelWindow(interp, NULL, baseName,
+ screenName, /* flags */ 0);
+ if (tkwin == NULL) {
+ return NULL;
+ }
+
+ /*
+ * Create the TkMainInfo structure for this application, and set up
+ * name-related information for the new window.
+ */
+
+ winPtr = (TkWindow *) tkwin;
+ mainPtr = ckalloc(sizeof(TkMainInfo));
+ mainPtr->winPtr = winPtr;
+ mainPtr->refCount = 1;
+ mainPtr->interp = interp;
+ Tcl_InitHashTable(&mainPtr->nameTable, TCL_STRING_KEYS);
+ mainPtr->deletionEpoch = 0l;
+ TkEventInit();
+ TkBindInit(mainPtr);
+ TkFontPkgInit(mainPtr);
+ TkStylePkgInit(mainPtr);
+ mainPtr->tlFocusPtr = NULL;
+ mainPtr->displayFocusPtr = NULL;
+ mainPtr->optionRootPtr = NULL;
+ Tcl_InitHashTable(&mainPtr->imageTable, TCL_STRING_KEYS);
+ mainPtr->strictMotif = 0;
+ mainPtr->alwaysShowSelection = 0;
+ if (Tcl_LinkVar(interp, "tk_strictMotif", (char *) &mainPtr->strictMotif,
+ TCL_LINK_BOOLEAN) != TCL_OK) {
+ Tcl_ResetResult(interp);
+ }
+ if (Tcl_CreateNamespace(interp, "::tk", NULL, NULL) == NULL) {
+ Tcl_ResetResult(interp);
+ }
+ if (Tcl_LinkVar(interp, "::tk::AlwaysShowSelection",
+ (char *) &mainPtr->alwaysShowSelection,
+ TCL_LINK_BOOLEAN) != TCL_OK) {
+ Tcl_ResetResult(interp);
+ }
+ mainPtr->nextPtr = tsdPtr->mainWindowList;
+ tsdPtr->mainWindowList = mainPtr;
+ winPtr->mainPtr = mainPtr;
+ hPtr = Tcl_CreateHashEntry(&mainPtr->nameTable, ".", &dummy);
+ Tcl_SetHashValue(hPtr, winPtr);
+ winPtr->pathName = Tcl_GetHashKey(&mainPtr->nameTable, hPtr);
+ Tcl_InitHashTable(&mainPtr->busyTable, TCL_ONE_WORD_KEYS);
+
+ /*
+ * We have just created another Tk application; increment the refcount on
+ * the display pointer.
+ */
+
+ winPtr->dispPtr->refCount++;
+
+ /*
+ * Register the interpreter for "send" purposes.
+ */
+
+ winPtr->nameUid = Tk_GetUid(Tk_SetAppName(tkwin, baseName));
+
+ /*
+ * Bind in Tk's commands.
+ */
+
+ isSafe = Tcl_IsSafe(interp);
+ for (cmdPtr = commands; cmdPtr->name != NULL; cmdPtr++) {
+ if (cmdPtr->objProc == NULL) {
+ Tcl_Panic("TkCreateMainWindow: builtin command with NULL string and object procs");
+ }
+
+#if defined(_WIN32) && !defined(STATIC_BUILD)
+ if ((cmdPtr->flags & WINMACONLY) && tclStubsPtr->reserved9) {
+ /*
+ * We are running on Cygwin, so don't use the win32 dialogs.
+ */
+
+ continue;
+ }
+#endif /* _WIN32 && !STATIC_BUILD */
+
+ if (cmdPtr->flags & PASSMAINWINDOW) {
+ clientData = tkwin;
+ } else {
+ clientData = NULL;
+ }
+ if (cmdPtr->flags & USEINITPROC) {
+ ((TkInitProc *) cmdPtr->objProc)(interp, clientData);
+ } else {
+ Tcl_CreateObjCommand(interp, cmdPtr->name, cmdPtr->objProc,
+ clientData, NULL);
+ }
+ if (isSafe && !(cmdPtr->flags & ISSAFE)) {
+ Tcl_HideCommand(interp, cmdPtr->name, cmdPtr->name);
+ }
+ }
+
+ /*
+ * Set variables for the intepreter.
+ */
+
+ Tcl_SetVar2(interp, "tk_patchLevel", NULL, TK_PATCH_LEVEL, TCL_GLOBAL_ONLY);
+ Tcl_SetVar2(interp, "tk_version", NULL, TK_VERSION, TCL_GLOBAL_ONLY);
+
+ tsdPtr->numMainWindows++;
+ return tkwin;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CreateWindow --
+ *
+ * Create a new internal or top-level window as a child of an existing
+ * window.
+ *
+ * Results:
+ * The return value is a token for the new window. This is not the same
+ * as X's token for the window. If an error occurred in creating the
+ * window (e.g. no such display or screen), then an error message is left
+ * in the interp's result and NULL is returned.
+ *
+ * Side effects:
+ * A new window structure is allocated locally. An X window is not
+ * initially created, but will be created the first time the window is
+ * mapped.
+ *
+ *--------------------------------------------------------------
+ */
+
+Tk_Window
+Tk_CreateWindow(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting.
+ * the interp's result is assumed to be
+ * initialized by the caller. */
+ Tk_Window parent, /* Token for parent of new window. */
+ const char *name, /* Name for new window. Must be unique among
+ * parent's children. */
+ const char *screenName) /* If NULL, new window will be internal on
+ * same screen as its parent. If non-NULL,
+ * gives name of screen on which to create new
+ * window; window will be a top-level
+ * window. */
+{
+ TkWindow *parentPtr = (TkWindow *) parent;
+
+ if (parentPtr) {
+ if (parentPtr->flags & TK_ALREADY_DEAD) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "can't create window: parent has been destroyed", -1));
+ Tcl_SetErrorCode(interp, "TK", "CREATE", "DEAD_PARENT", NULL);
+ return NULL;
+ } else if (parentPtr->flags & TK_CONTAINER) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "can't create window: its parent has -container = yes",
+ -1));
+ Tcl_SetErrorCode(interp, "TK", "CREATE", "CONTAINER", NULL);
+ return NULL;
+ } else if (screenName == NULL) {
+ TkWindow *winPtr = TkAllocWindow(parentPtr->dispPtr,
+ parentPtr->screenNum, parentPtr);
+
+ if (NameWindow(interp, winPtr, parentPtr, name) != TCL_OK) {
+ Tk_DestroyWindow((Tk_Window) winPtr);
+ return NULL;
+ }
+ return (Tk_Window) winPtr;
+ }
+ }
+ return CreateTopLevelWindow(interp, parent, name, screenName,
+ /* flags */ 0);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CreateAnonymousWindow --
+ *
+ * Create a new internal or top-level window as a child of an existing
+ * window; this window will be anonymous (unnamed), so it will not be
+ * visible at the Tcl level.
+ *
+ * Results:
+ * The return value is a token for the new window. This is not the same
+ * as X's token for the window. If an error occurred in creating the
+ * window (e.g. no such display or screen), then an error message is left
+ * in the interp's result and NULL is returned.
+ *
+ * Side effects:
+ * A new window structure is allocated locally. An X window is not
+ * initially created, but will be created the first time the window is
+ * mapped.
+ *
+ *--------------------------------------------------------------
+ */
+
+Tk_Window
+Tk_CreateAnonymousWindow(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting.
+ * the interp's result is assumed to be
+ * initialized by the caller. */
+ Tk_Window parent, /* Token for parent of new window. */
+ const char *screenName) /* If NULL, new window will be internal on
+ * same screen as its parent. If non-NULL,
+ * gives name of screen on which to create new
+ * window; window will be a top-level
+ * window. */
+{
+ TkWindow *parentPtr = (TkWindow *) parent;
+
+ if (parentPtr) {
+ if (parentPtr->flags & TK_ALREADY_DEAD) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "can't create window: parent has been destroyed", -1));
+ Tcl_SetErrorCode(interp, "TK", "CREATE", "DEAD_PARENT", NULL);
+ return NULL;
+ } else if (parentPtr->flags & TK_CONTAINER) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "can't create window: its parent has -container = yes",
+ -1));
+ Tcl_SetErrorCode(interp, "TK", "CREATE", "CONTAINER", NULL);
+ return NULL;
+ } else if (screenName == NULL) {
+ TkWindow *winPtr = TkAllocWindow(parentPtr->dispPtr,
+ parentPtr->screenNum, parentPtr);
+ /*
+ * Add the anonymous window flag now, so that NameWindow will
+ * behave correctly.
+ */
+
+ winPtr->flags |= TK_ANONYMOUS_WINDOW;
+ if (NameWindow(interp, winPtr, parentPtr, NULL) != TCL_OK) {
+ Tk_DestroyWindow((Tk_Window) winPtr);
+ return NULL;
+ }
+ return (Tk_Window) winPtr;
+ }
+ }
+ return CreateTopLevelWindow(interp, parent, NULL, screenName,
+ TK_ANONYMOUS_WINDOW);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_CreateWindowFromPath --
+ *
+ * This function is similar to Tk_CreateWindow except that it uses a path
+ * name to create the window, rather than a parent and a child name.
+ *
+ * Results:
+ * The return value is a token for the new window. This is not the same
+ * as X's token for the window. If an error occurred in creating the
+ * window (e.g. no such display or screen), then an error message is left
+ * in the interp's result and NULL is returned.
+ *
+ * Side effects:
+ * A new window structure is allocated locally. An X window is not
+ * initially created, but will be created the first time the window is
+ * mapped.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_Window
+Tk_CreateWindowFromPath(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting.
+ * the interp's result is assumed to be
+ * initialized by the caller. */
+ Tk_Window tkwin, /* Token for any window in application that is
+ * to contain new window. */
+ const char *pathName, /* Path name for new window within the
+ * application of tkwin. The parent of this
+ * window must already exist, but the window
+ * itself must not exist. */
+ const char *screenName) /* If NULL, new window will be on same screen
+ * as its parent. If non-NULL, gives name of
+ * screen on which to create new window;
+ * window will be a top-level window. */
+{
+#define FIXED_SPACE 5
+ char fixedSpace[FIXED_SPACE+1];
+ char *p;
+ Tk_Window parent;
+ int numChars;
+
+ /*
+ * Strip the parent's name out of pathName (it's everything up to the last
+ * dot). There are two tricky parts: (a) must copy the parent's name
+ * somewhere else to avoid modifying the pathName string (for large names,
+ * space for the copy will have to be malloc'ed); (b) must special-case
+ * the situation where the parent is ".".
+ */
+
+ p = strrchr(pathName, '.');
+ if (p == NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad window path name \"%s\"", pathName));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "WINDOW_PATH", NULL);
+ return NULL;
+ }
+ numChars = (int) (p-pathName);
+ if (numChars > FIXED_SPACE) {
+ p = ckalloc(numChars + 1);
+ } else {
+ p = fixedSpace;
+ }
+ if (numChars == 0) {
+ *p = '.';
+ p[1] = '\0';
+ } else {
+ strncpy(p, pathName, (size_t) numChars);
+ p[numChars] = '\0';
+ }
+
+ /*
+ * Find the parent window.
+ */
+
+ parent = Tk_NameToWindow(interp, p, tkwin);
+ if (p != fixedSpace) {
+ ckfree(p);
+ }
+ if (parent == NULL) {
+ return NULL;
+ }
+ if (((TkWindow *) parent)->flags & TK_ALREADY_DEAD) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "can't create window: parent has been destroyed", -1));
+ Tcl_SetErrorCode(interp, "TK", "CREATE", "DEAD_PARENT", NULL);
+ return NULL;
+ } else if (((TkWindow *) parent)->flags & TK_CONTAINER) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "can't create window: its parent has -container = yes", -1));
+ Tcl_SetErrorCode(interp, "TK", "CREATE", "CONTAINER", NULL);
+ return NULL;
+ }
+
+ /*
+ * Create the window.
+ */
+
+ if (screenName == NULL) {
+ TkWindow *parentPtr = (TkWindow *) parent;
+ TkWindow *winPtr;
+
+ winPtr = TkAllocWindow(parentPtr->dispPtr, parentPtr->screenNum,
+ parentPtr);
+ if (NameWindow(interp, winPtr, parentPtr, pathName+numChars+1)
+ != TCL_OK) {
+ Tk_DestroyWindow((Tk_Window) winPtr);
+ return NULL;
+ }
+ return (Tk_Window) winPtr;
+ }
+
+ return CreateTopLevelWindow(interp, parent, pathName+numChars+1,
+ screenName, /* flags */ 0);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_DestroyWindow --
+ *
+ * Destroy an existing window. After this call, the caller should never
+ * again use the token. Note that this function can be reentered to
+ * destroy a window that was only partially destroyed before a call to
+ * exit.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The window is deleted, along with all of its children. Relevant
+ * callback functions are invoked.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_DestroyWindow(
+ Tk_Window tkwin) /* Window to destroy. */
+{
+ TkWindow *winPtr = (TkWindow *) tkwin;
+ TkDisplay *dispPtr = winPtr->dispPtr;
+ XEvent event;
+ TkHalfdeadWindow *halfdeadPtr, *prev_halfdeadPtr;
+ ThreadSpecificData *tsdPtr =
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (winPtr->flags & TK_ALREADY_DEAD) {
+ /*
+ * A destroy event binding caused the window to be destroyed again.
+ * Ignore the request.
+ */
+
+ return;
+ }
+ winPtr->flags |= TK_ALREADY_DEAD;
+
+ /*
+ * Unless we are cleaning up a half dead window from
+ * DeleteWindowsExitProc, add this window to the half dead list.
+ */
+
+ if (tsdPtr->halfdeadWindowList &&
+ (tsdPtr->halfdeadWindowList->flags & HD_CLEANUP) &&
+ (tsdPtr->halfdeadWindowList->winPtr == winPtr)) {
+ halfdeadPtr = tsdPtr->halfdeadWindowList;
+ } else {
+ halfdeadPtr = ckalloc(sizeof(TkHalfdeadWindow));
+ halfdeadPtr->flags = 0;
+ halfdeadPtr->winPtr = winPtr;
+ halfdeadPtr->nextPtr = tsdPtr->halfdeadWindowList;
+ tsdPtr->halfdeadWindowList = halfdeadPtr;
+ }
+
+ /*
+ * Some cleanup needs to be done immediately, rather than later, because
+ * it needs information that will be destoyed before we get to the main
+ * cleanup point. For example, TkFocusDeadWindow needs to access the
+ * parentPtr field from a window, but if a Destroy event handler deletes
+ * the window's parent this field will be NULL before the main cleanup
+ * point is reached.
+ */
+
+ if (!(halfdeadPtr->flags & HD_FOCUS)) {
+ halfdeadPtr->flags |= HD_FOCUS;
+ TkFocusDeadWindow(winPtr);
+ }
+
+ /*
+ * If this is a main window, remove it from the list of main windows.
+ * This needs to be done now (rather than later with all the other main
+ * window cleanup) to handle situations where a destroy binding for a
+ * window calls "exit". In this case the child window cleanup isn't
+ * complete when exit is called. This situation is dealt with using the
+ * half dead window list. Windows that are half dead gets cleaned up
+ * during exit.
+ *
+ * Also decrement the display refcount so that if this is the last Tk
+ * application in this process on this display, the display can be closed
+ * and its data structures deleted.
+ */
+
+ if (!(halfdeadPtr->flags & HD_MAIN_WIN) &&
+ winPtr->mainPtr != NULL && winPtr->mainPtr->winPtr == winPtr) {
+ halfdeadPtr->flags |= HD_MAIN_WIN;
+ dispPtr->refCount--;
+ if (tsdPtr->mainWindowList == winPtr->mainPtr) {
+ tsdPtr->mainWindowList = winPtr->mainPtr->nextPtr;
+ } else {
+ TkMainInfo *prevPtr;
+
+ for (prevPtr = tsdPtr->mainWindowList;
+ prevPtr->nextPtr != winPtr->mainPtr;
+ prevPtr = prevPtr->nextPtr) {
+ /* Empty loop body. */
+ }
+ prevPtr->nextPtr = winPtr->mainPtr->nextPtr;
+ }
+ tsdPtr->numMainWindows--;
+ }
+
+ /*
+ * Recursively destroy children. Note that this child window block may
+ * need to be run multiple times in the case where a child window has a
+ * Destroy binding that calls exit.
+ */
+
+ if (!(halfdeadPtr->flags & HD_DESTROY_COUNT)) {
+ halfdeadPtr->flags |= HD_DESTROY_COUNT;
+ }
+
+ while (winPtr->childList != NULL) {
+ TkWindow *childPtr = winPtr->childList;
+
+ childPtr->flags |= TK_DONT_DESTROY_WINDOW;
+ Tk_DestroyWindow((Tk_Window) childPtr);
+ if (winPtr->childList == childPtr) {
+ /*
+ * The child didn't remove itself from the child list, so let's
+ * remove it here. This can happen in some strange conditions,
+ * such as when a Destroy event handler for a window destroys the
+ * window's parent.
+ */
+
+ winPtr->childList = childPtr->nextPtr;
+ childPtr->parentPtr = NULL;
+ }
+ }
+ if ((winPtr->flags & (TK_CONTAINER|TK_BOTH_HALVES))
+ == (TK_CONTAINER|TK_BOTH_HALVES)) {
+ /*
+ * This is the container for an embedded application, and the embedded
+ * application is also in this process. Delete the embedded window
+ * in-line here, for the same reasons we delete children in-line
+ * (otherwise, for example, the Tk window may appear to exist even
+ * though its X window is gone; this could cause errors). Special
+ * note: it's possible that the embedded window has already been
+ * deleted, in which case TkpGetOtherWindow will return NULL.
+ */
+
+ TkWindow *childPtr = TkpGetOtherWindow(winPtr);
+
+ if (childPtr != NULL) {
+ childPtr->flags |= TK_DONT_DESTROY_WINDOW;
+ Tk_DestroyWindow((Tk_Window) childPtr);
+ }
+ }
+
+ /*
+ * Generate a DestroyNotify event. In order for the DestroyNotify event to
+ * be processed correctly, need to make sure the window exists. This is a
+ * bit of a kludge, and may be unnecessarily expensive, but without it no
+ * event handlers will get called for windows that don't exist yet.
+ *
+ * Note: if the window's pathName is NULL and the window is not an
+ * anonymous window, it means that the window was not successfully
+ * initialized in the first place, so we should not make the window exist
+ * or generate the event.
+ */
+
+ if (!(halfdeadPtr->flags & HD_DESTROY_EVENT) &&
+ winPtr->pathName != NULL &&
+ !(winPtr->flags & TK_ANONYMOUS_WINDOW)) {
+ halfdeadPtr->flags |= HD_DESTROY_EVENT;
+ if (winPtr->window == None) {
+ Tk_MakeWindowExist(tkwin);
+ }
+ event.type = DestroyNotify;
+ event.xdestroywindow.serial =
+ LastKnownRequestProcessed(winPtr->display);
+ event.xdestroywindow.send_event = False;
+ event.xdestroywindow.display = winPtr->display;
+ event.xdestroywindow.event = winPtr->window;
+ event.xdestroywindow.window = winPtr->window;
+ Tk_HandleEvent(&event);
+ }
+
+ /*
+ * No additional bindings that could call exit should be invoked from this
+ * point on, so it is safe to remove this window from the half dead list.
+ */
+
+ for (prev_halfdeadPtr = NULL,
+ halfdeadPtr = tsdPtr->halfdeadWindowList;
+ halfdeadPtr != NULL; ) {
+ if (halfdeadPtr->winPtr == winPtr) {
+ if (prev_halfdeadPtr == NULL) {
+ tsdPtr->halfdeadWindowList = halfdeadPtr->nextPtr;
+ } else {
+ prev_halfdeadPtr->nextPtr = halfdeadPtr->nextPtr;
+ }
+ ckfree(halfdeadPtr);
+ break;
+ }
+ prev_halfdeadPtr = halfdeadPtr;
+ halfdeadPtr = halfdeadPtr->nextPtr;
+ }
+ if (halfdeadPtr == NULL) {
+ Tcl_Panic("window not found on half dead list");
+ }
+
+ /*
+ * Cleanup the data structures associated with this window.
+ */
+
+ if (winPtr->flags & TK_WIN_MANAGED) {
+ TkWmDeadWindow(winPtr);
+ } else if (winPtr->flags & TK_WM_COLORMAP_WINDOW) {
+ TkWmRemoveFromColormapWindows(winPtr);
+ }
+ if (winPtr->window != None) {
+#if defined(MAC_OSX_TK) || defined(_WIN32)
+ XDestroyWindow(winPtr->display, winPtr->window);
+#else
+ if ((winPtr->flags & TK_TOP_HIERARCHY)
+ || !(winPtr->flags & TK_DONT_DESTROY_WINDOW)) {
+ /*
+ * The parent has already been destroyed and this isn't a
+ * top-level window, so this window will be destroyed implicitly
+ * when the parent's X window is destroyed; it's much faster not
+ * to do an explicit destroy of this X window.
+ */
+
+ XDestroyWindow(winPtr->display, winPtr->window);
+ }
+#endif
+ Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->winTable,
+ (char *) winPtr->window));
+ winPtr->window = None;
+ }
+ UnlinkWindow(winPtr);
+ TkEventDeadWindow(winPtr);
+#ifdef TK_USE_INPUT_METHODS
+ if (winPtr->inputContext != NULL &&
+ winPtr->ximGeneration == winPtr->dispPtr->ximGeneration) {
+ XDestroyIC(winPtr->inputContext);
+ }
+ winPtr->inputContext = NULL;
+#endif /* TK_USE_INPUT_METHODS */
+ if (winPtr->tagPtr != NULL) {
+ TkFreeBindingTags(winPtr);
+ }
+ TkOptionDeadWindow(winPtr);
+ TkSelDeadWindow(winPtr);
+ TkGrabDeadWindow(winPtr);
+ if (winPtr->geomMgrName != NULL) {
+ ckfree(winPtr->geomMgrName);
+ winPtr->geomMgrName = NULL;
+ }
+ if (winPtr->mainPtr != NULL) {
+ if (winPtr->pathName != NULL) {
+ Tk_DeleteAllBindings(winPtr->mainPtr->bindingTable,
+ winPtr->pathName);
+ Tcl_DeleteHashEntry(Tcl_FindHashEntry(&winPtr->mainPtr->nameTable,
+ winPtr->pathName));
+
+ /*
+ * The memory pointed to by pathName has been deallocated. Keep
+ * users from accessing it after the window has been destroyed by
+ * setting it to NULL.
+ */
+
+ winPtr->pathName = NULL;
+
+ /*
+ * Invalidate all objects referring to windows with the same main
+ * window.
+ */
+
+ winPtr->mainPtr->deletionEpoch++;
+ }
+ if (winPtr->mainPtr->refCount-- <= 1) {
+ register const TkCmd *cmdPtr;
+
+ /*
+ * We just deleted the last window in the application. Delete the
+ * TkMainInfo structure too and replace all of Tk's commands with
+ * dummy commands that return errors. Also delete the "send"
+ * command to unregister the interpreter.
+ *
+ * NOTE: Only replace the commands it if the interpreter is not
+ * being deleted. If it *is*, the interpreter cleanup will do all
+ * the needed work.
+ */
+
+ if ((winPtr->mainPtr->interp != NULL) &&
+ !Tcl_InterpDeleted(winPtr->mainPtr->interp)) {
+ for (cmdPtr = commands; cmdPtr->name != NULL; cmdPtr++) {
+ Tcl_CreateObjCommand(winPtr->mainPtr->interp, cmdPtr->name,
+ TkDeadAppObjCmd, NULL, NULL);
+ }
+ Tcl_CreateObjCommand(winPtr->mainPtr->interp, "send",
+ TkDeadAppObjCmd, NULL, NULL);
+ Tcl_UnlinkVar(winPtr->mainPtr->interp, "tk_strictMotif");
+ Tcl_UnlinkVar(winPtr->mainPtr->interp,
+ "::tk::AlwaysShowSelection");
+ }
+
+ Tcl_DeleteHashTable(&winPtr->mainPtr->busyTable);
+ Tcl_DeleteHashTable(&winPtr->mainPtr->nameTable);
+ TkBindFree(winPtr->mainPtr);
+ TkDeleteAllImages(winPtr->mainPtr);
+ TkFontPkgFree(winPtr->mainPtr);
+ TkFocusFree(winPtr->mainPtr);
+ TkStylePkgFree(winPtr->mainPtr);
+
+ /*
+ * When embedding Tk into other applications, make sure that all
+ * destroy events reach the server. Otherwise the embedding
+ * application may also attempt to destroy the windows, resulting
+ * in an X error
+ */
+
+ if (winPtr->flags & TK_EMBEDDED) {
+ XSync(winPtr->display, False);
+ }
+ ckfree(winPtr->mainPtr);
+
+ /*
+ * If no other applications are using the display, close the
+ * display now and relinquish its data structures.
+ */
+
+#if !defined(_WIN32) && defined(NOT_YET)
+ if (dispPtr->refCount <= 0) {
+ /*
+ * I have disabled this code because on Windows there are
+ * still order dependencies in close-down. All displays and
+ * resources will get closed down properly anyway at exit,
+ * through the exit handler. -- jyl
+ *
+ * Ideally this should be enabled, as unix Tk can use multiple
+ * displays. However, there are order issues still, as well as
+ * the handling of queued events and such that must be
+ * addressed before this can be enabled. The current cleanup
+ * works except for send event issues. -- hobbs 04/2002
+ */
+
+ TkDisplay *theDispPtr, *backDispPtr;
+
+ /*
+ * Splice this display out of the list of displays.
+ */
+
+ for (theDispPtr = tsdPtr->displayList, backDispPtr = NULL;
+ (theDispPtr!=winPtr->dispPtr) && (theDispPtr!=NULL);
+ theDispPtr = theDispPtr->nextPtr) {
+ backDispPtr = theDispPtr;
+ }
+ if (theDispPtr == NULL) {
+ Tcl_Panic("could not find display to close!");
+ }
+ if (backDispPtr == NULL) {
+ tsdPtr->displayList = theDispPtr->nextPtr;
+ } else {
+ backDispPtr->nextPtr = theDispPtr->nextPtr;
+ }
+
+ /*
+ * Calling XSync creates X server traffic, but addresses a
+ * focus issue on close (but not the send issue). -- hobbs
+ *
+ * XSync(dispPtr->display, True);
+ */
+
+ /*
+ * Found and spliced it out, now actually do the cleanup.
+ */
+
+ TkCloseDisplay(dispPtr);
+ }
+#endif /* !_WIN32 && NOT_YET */
+ }
+ }
+ Tcl_EventuallyFree(winPtr, TCL_DYNAMIC);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_MapWindow --
+ *
+ * Map a window within its parent. This may require the window and/or its
+ * parents to actually be created.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The given window will be mapped. Windows may also be created.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_MapWindow(
+ Tk_Window tkwin) /* Token for window to map. */
+{
+ TkWindow *winPtr = (TkWindow *) tkwin;
+ XEvent event;
+
+ if (winPtr->flags & TK_MAPPED) {
+ return;
+ }
+ if (winPtr->window == None) {
+ Tk_MakeWindowExist(tkwin);
+ }
+ /*
+ * [Bug 2645457]: the previous call permits events to be processed and can
+ * lead to the destruction of the window under some conditions.
+ */
+ if (winPtr->flags & TK_ALREADY_DEAD) {
+ return;
+ }
+ if (winPtr->flags & TK_WIN_MANAGED) {
+ /*
+ * Lots of special processing has to be done for top-level windows.
+ * Let tkWm.c handle everything itself.
+ */
+
+ TkWmMapWindow(winPtr);
+ return;
+ }
+ winPtr->flags |= TK_MAPPED;
+ XMapWindow(winPtr->display, winPtr->window);
+ event.type = MapNotify;
+ event.xmap.serial = LastKnownRequestProcessed(winPtr->display);
+ event.xmap.send_event = False;
+ event.xmap.display = winPtr->display;
+ event.xmap.event = winPtr->window;
+ event.xmap.window = winPtr->window;
+ event.xmap.override_redirect = winPtr->atts.override_redirect;
+ Tk_HandleEvent(&event);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_MakeWindowExist --
+ *
+ * Ensure that a particular window actually exists. This function should
+ * not normally need to be invoked from outside the Tk package, but may
+ * be needed if someone wants to manipulate a window before mapping it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * When the function returns, the X window associated with tkwin is
+ * guaranteed to exist. This may require the window's ancestors to be
+ * created also.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_MakeWindowExist(
+ Tk_Window tkwin) /* Token for window. */
+{
+ register TkWindow *winPtr = (TkWindow *) tkwin;
+ TkWindow *winPtr2;
+ Window parent;
+ Tcl_HashEntry *hPtr;
+ Tk_ClassCreateProc *createProc;
+ int isNew;
+
+ if (winPtr->window != None) {
+ return;
+ }
+
+ if ((winPtr->parentPtr == NULL) || (winPtr->flags & TK_TOP_HIERARCHY)) {
+ parent = XRootWindow(winPtr->display, winPtr->screenNum);
+ } else {
+ if (winPtr->parentPtr->window == None) {
+ Tk_MakeWindowExist((Tk_Window) winPtr->parentPtr);
+ }
+ parent = winPtr->parentPtr->window;
+ }
+
+ createProc = Tk_GetClassProc(winPtr->classProcsPtr, createProc);
+ if (createProc != NULL && parent != None) {
+ winPtr->window = createProc(tkwin, parent, winPtr->instanceData);
+ } else {
+ winPtr->window = TkpMakeWindow(winPtr, parent);
+ }
+
+ hPtr = Tcl_CreateHashEntry(&winPtr->dispPtr->winTable,
+ (char *) winPtr->window, &isNew);
+ Tcl_SetHashValue(hPtr, winPtr);
+ winPtr->dirtyAtts = 0;
+ winPtr->dirtyChanges = 0;
+
+ if (!(winPtr->flags & TK_TOP_HIERARCHY)) {
+ /*
+ * If any siblings higher up in the stacking order have already been
+ * created then move this window to its rightful position in the
+ * stacking order.
+ *
+ * NOTE: this code ignores any changes anyone might have made to the
+ * sibling and stack_mode field of the window's attributes, so it
+ * really isn't safe for these to be manipulated except by calling
+ * Tk_RestackWindow.
+ */
+
+ for (winPtr2 = winPtr->nextPtr; winPtr2 != NULL;
+ winPtr2 = winPtr2->nextPtr) {
+ if ((winPtr2->window != None)
+ && !(winPtr2->flags & (TK_TOP_HIERARCHY|TK_REPARENTED))) {
+ XWindowChanges changes;
+
+ changes.sibling = winPtr2->window;
+ changes.stack_mode = Below;
+ XConfigureWindow(winPtr->display, winPtr->window,
+ CWSibling|CWStackMode, &changes);
+ break;
+ }
+ }
+
+ /*
+ * If this window has a different colormap than its parent, add the
+ * window to the WM_COLORMAP_WINDOWS property for its top-level.
+ */
+
+ if ((winPtr->parentPtr != NULL) &&
+ (winPtr->atts.colormap != winPtr->parentPtr->atts.colormap)) {
+ TkWmAddToColormapWindows(winPtr);
+ winPtr->flags |= TK_WM_COLORMAP_WINDOW;
+ }
+ }
+
+ /*
+ * Issue a ConfigureNotify event if there were deferred configuration
+ * changes (but skip it if the window is being deleted; the
+ * ConfigureNotify event could cause problems if we're being called from
+ * Tk_DestroyWindow under some conditions).
+ */
+
+ if ((winPtr->flags & TK_NEED_CONFIG_NOTIFY)
+ && !(winPtr->flags & TK_ALREADY_DEAD)) {
+ winPtr->flags &= ~TK_NEED_CONFIG_NOTIFY;
+ TkDoConfigureNotify(winPtr);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_UnmapWindow, etc. --
+ *
+ * There are several functions under here, each of which mirrors an
+ * existing X function. In addition to performing the functions of the
+ * corresponding function, each function also updates the local window
+ * structure and synthesizes an X event (if the window's structure is
+ * being managed internally).
+ *
+ * Results:
+ * See the manual entries.
+ *
+ * Side effects:
+ * See the manual entries.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_UnmapWindow(
+ Tk_Window tkwin) /* Token for window to unmap. */
+{
+ register TkWindow *winPtr = (TkWindow *) tkwin;
+
+ if (!(winPtr->flags & TK_MAPPED) || (winPtr->flags & TK_ALREADY_DEAD)) {
+ return;
+ }
+ if (winPtr->flags & TK_WIN_MANAGED) {
+ /*
+ * Special processing has to be done for top-level windows. Let tkWm.c
+ * handle everything itself.
+ */
+
+ TkWmUnmapWindow(winPtr);
+ return;
+ }
+ winPtr->flags &= ~TK_MAPPED;
+ XUnmapWindow(winPtr->display, winPtr->window);
+ if (!(winPtr->flags & TK_TOP_HIERARCHY)) {
+ XEvent event;
+
+ event.type = UnmapNotify;
+ event.xunmap.serial = LastKnownRequestProcessed(winPtr->display);
+ event.xunmap.send_event = False;
+ event.xunmap.display = winPtr->display;
+ event.xunmap.event = winPtr->window;
+ event.xunmap.window = winPtr->window;
+ event.xunmap.from_configure = False;
+ Tk_HandleEvent(&event);
+ }
+}
+
+void
+Tk_ConfigureWindow(
+ Tk_Window tkwin, /* Window to re-configure. */
+ unsigned int valueMask, /* Mask indicating which parts of *valuePtr
+ * are to be used. */
+ XWindowChanges *valuePtr) /* New values. */
+{
+ register TkWindow *winPtr = (TkWindow *) tkwin;
+
+ if (valueMask & CWX) {
+ winPtr->changes.x = valuePtr->x;
+ }
+ if (valueMask & CWY) {
+ winPtr->changes.y = valuePtr->y;
+ }
+ if (valueMask & CWWidth) {
+ winPtr->changes.width = valuePtr->width;
+ }
+ if (valueMask & CWHeight) {
+ winPtr->changes.height = valuePtr->height;
+ }
+ if (valueMask & CWBorderWidth) {
+ winPtr->changes.border_width = valuePtr->border_width;
+ }
+ if (valueMask & (CWSibling|CWStackMode)) {
+ Tcl_Panic("Can't set sibling or stack mode from Tk_ConfigureWindow");
+ }
+
+ if (winPtr->window != None) {
+ XConfigureWindow(winPtr->display, winPtr->window,
+ valueMask, valuePtr);
+ TkDoConfigureNotify(winPtr);
+ } else {
+ winPtr->dirtyChanges |= valueMask;
+ winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
+ }
+}
+
+void
+Tk_MoveWindow(
+ Tk_Window tkwin, /* Window to move. */
+ int x, int y) /* New location for window (within parent). */
+{
+ register TkWindow *winPtr = (TkWindow *) tkwin;
+
+ winPtr->changes.x = x;
+ winPtr->changes.y = y;
+ if (winPtr->window != None) {
+ XMoveWindow(winPtr->display, winPtr->window, x, y);
+ TkDoConfigureNotify(winPtr);
+ } else {
+ winPtr->dirtyChanges |= CWX|CWY;
+ winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
+ }
+}
+
+void
+Tk_ResizeWindow(
+ Tk_Window tkwin, /* Window to resize. */
+ int width, int height) /* New dimensions for window. */
+{
+ register TkWindow *winPtr = (TkWindow *) tkwin;
+
+ winPtr->changes.width = (unsigned) width;
+ winPtr->changes.height = (unsigned) height;
+ if (winPtr->window != None) {
+ XResizeWindow(winPtr->display, winPtr->window, (unsigned) width,
+ (unsigned) height);
+ TkDoConfigureNotify(winPtr);
+ } else {
+ winPtr->dirtyChanges |= CWWidth|CWHeight;
+ winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
+ }
+}
+
+void
+Tk_MoveResizeWindow(
+ Tk_Window tkwin, /* Window to move and resize. */
+ int x, int y, /* New location for window (within parent). */
+ int width, int height) /* New dimensions for window. */
+{
+ register TkWindow *winPtr = (TkWindow *) tkwin;
+
+ winPtr->changes.x = x;
+ winPtr->changes.y = y;
+ winPtr->changes.width = (unsigned) width;
+ winPtr->changes.height = (unsigned) height;
+ if (winPtr->window != None) {
+ XMoveResizeWindow(winPtr->display, winPtr->window, x, y,
+ (unsigned) width, (unsigned) height);
+ TkDoConfigureNotify(winPtr);
+ } else {
+ winPtr->dirtyChanges |= CWX|CWY|CWWidth|CWHeight;
+ winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
+ }
+}
+
+void
+Tk_SetWindowBorderWidth(
+ Tk_Window tkwin, /* Window to modify. */
+ int width) /* New border width for window. */
+{
+ register TkWindow *winPtr = (TkWindow *) tkwin;
+
+ winPtr->changes.border_width = width;
+ if (winPtr->window != None) {
+ XSetWindowBorderWidth(winPtr->display, winPtr->window,
+ (unsigned) width);
+ TkDoConfigureNotify(winPtr);
+ } else {
+ winPtr->dirtyChanges |= CWBorderWidth;
+ winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
+ }
+}
+
+void
+Tk_ChangeWindowAttributes(
+ Tk_Window tkwin, /* Window to manipulate. */
+ unsigned long valueMask, /* OR'ed combination of bits, indicating which
+ * fields of *attsPtr are to be used. */
+ register XSetWindowAttributes *attsPtr)
+ /* New values for some attributes. */
+{
+ register TkWindow *winPtr = (TkWindow *) tkwin;
+
+ if (valueMask & CWBackPixmap) {
+ winPtr->atts.background_pixmap = attsPtr->background_pixmap;
+ }
+ if (valueMask & CWBackPixel) {
+ winPtr->atts.background_pixel = attsPtr->background_pixel;
+ }
+ if (valueMask & CWBorderPixmap) {
+ winPtr->atts.border_pixmap = attsPtr->border_pixmap;
+ }
+ if (valueMask & CWBorderPixel) {
+ winPtr->atts.border_pixel = attsPtr->border_pixel;
+ }
+ if (valueMask & CWBitGravity) {
+ winPtr->atts.bit_gravity = attsPtr->bit_gravity;
+ }
+ if (valueMask & CWWinGravity) {
+ winPtr->atts.win_gravity = attsPtr->win_gravity;
+ }
+ if (valueMask & CWBackingStore) {
+ winPtr->atts.backing_store = attsPtr->backing_store;
+ }
+ if (valueMask & CWBackingPlanes) {
+ winPtr->atts.backing_planes = attsPtr->backing_planes;
+ }
+ if (valueMask & CWBackingPixel) {
+ winPtr->atts.backing_pixel = attsPtr->backing_pixel;
+ }
+ if (valueMask & CWOverrideRedirect) {
+ winPtr->atts.override_redirect = attsPtr->override_redirect;
+ }
+ if (valueMask & CWSaveUnder) {
+ winPtr->atts.save_under = attsPtr->save_under;
+ }
+ if (valueMask & CWEventMask) {
+ winPtr->atts.event_mask = attsPtr->event_mask;
+ }
+ if (valueMask & CWDontPropagate) {
+ winPtr->atts.do_not_propagate_mask
+ = attsPtr->do_not_propagate_mask;
+ }
+ if (valueMask & CWColormap) {
+ winPtr->atts.colormap = attsPtr->colormap;
+ }
+ if (valueMask & CWCursor) {
+ winPtr->atts.cursor = attsPtr->cursor;
+ }
+
+ if (winPtr->window != None) {
+ XChangeWindowAttributes(winPtr->display, winPtr->window,
+ valueMask, attsPtr);
+ } else {
+ winPtr->dirtyAtts |= valueMask;
+ }
+}
+
+void
+Tk_SetWindowBackground(
+ Tk_Window tkwin, /* Window to manipulate. */
+ unsigned long pixel) /* Pixel value to use for window's
+ * background. */
+{
+ register TkWindow *winPtr = (TkWindow *) tkwin;
+
+ winPtr->atts.background_pixel = pixel;
+
+ if (winPtr->window != None) {
+ XSetWindowBackground(winPtr->display, winPtr->window, pixel);
+ } else {
+ winPtr->dirtyAtts = (winPtr->dirtyAtts & (unsigned) ~CWBackPixmap)
+ | CWBackPixel;
+ }
+}
+
+void
+Tk_SetWindowBackgroundPixmap(
+ Tk_Window tkwin, /* Window to manipulate. */
+ Pixmap pixmap) /* Pixmap to use for window's background. */
+{
+ register TkWindow *winPtr = (TkWindow *) tkwin;
+
+ winPtr->atts.background_pixmap = pixmap;
+
+ if (winPtr->window != None) {
+ XSetWindowBackgroundPixmap(winPtr->display,
+ winPtr->window, pixmap);
+ } else {
+ winPtr->dirtyAtts = (winPtr->dirtyAtts & (unsigned) ~CWBackPixel)
+ | CWBackPixmap;
+ }
+}
+
+void
+Tk_SetWindowBorder(
+ Tk_Window tkwin, /* Window to manipulate. */
+ unsigned long pixel) /* Pixel value to use for window's border. */
+{
+ register TkWindow *winPtr = (TkWindow *) tkwin;
+
+ winPtr->atts.border_pixel = pixel;
+
+ if (winPtr->window != None) {
+ XSetWindowBorder(winPtr->display, winPtr->window, pixel);
+ } else {
+ winPtr->dirtyAtts = (winPtr->dirtyAtts & (unsigned) ~CWBorderPixmap)
+ | CWBorderPixel;
+ }
+}
+
+void
+Tk_SetWindowBorderPixmap(
+ Tk_Window tkwin, /* Window to manipulate. */
+ Pixmap pixmap) /* Pixmap to use for window's border. */
+{
+ register TkWindow *winPtr = (TkWindow *) tkwin;
+
+ winPtr->atts.border_pixmap = pixmap;
+
+ if (winPtr->window != None) {
+ XSetWindowBorderPixmap(winPtr->display,
+ winPtr->window, pixmap);
+ } else {
+ winPtr->dirtyAtts = (winPtr->dirtyAtts & (unsigned) ~CWBorderPixel)
+ | CWBorderPixmap;
+ }
+}
+
+void
+Tk_DefineCursor(
+ Tk_Window tkwin, /* Window to manipulate. */
+ Tk_Cursor cursor) /* Cursor to use for window (may be None). */
+{
+ register TkWindow *winPtr = (TkWindow *) tkwin;
+
+#if defined(MAC_OSX_TK)
+ winPtr->atts.cursor = (XCursor) cursor;
+#else
+ winPtr->atts.cursor = (Cursor) cursor;
+#endif
+
+ if (winPtr->window != None) {
+ XDefineCursor(winPtr->display, winPtr->window, winPtr->atts.cursor);
+ } else {
+ winPtr->dirtyAtts = winPtr->dirtyAtts | CWCursor;
+ }
+}
+
+void
+Tk_UndefineCursor(
+ Tk_Window tkwin) /* Window to manipulate. */
+{
+ Tk_DefineCursor(tkwin, NULL);
+}
+
+void
+Tk_SetWindowColormap(
+ Tk_Window tkwin, /* Window to manipulate. */
+ Colormap colormap) /* Colormap to use for window. */
+{
+ register TkWindow *winPtr = (TkWindow *) tkwin;
+
+ winPtr->atts.colormap = colormap;
+
+ if (winPtr->window != None) {
+ XSetWindowColormap(winPtr->display, winPtr->window, colormap);
+ if (!(winPtr->flags & TK_WIN_MANAGED)) {
+ TkWmAddToColormapWindows(winPtr);
+ winPtr->flags |= TK_WM_COLORMAP_WINDOW;
+ }
+ } else {
+ winPtr->dirtyAtts |= CWColormap;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_SetWindowVisual --
+ *
+ * This function is called to specify a visual to be used for a Tk window
+ * when it is created. This function, if called at all, must be called
+ * before the X window is created (i.e. before Tk_MakeWindowExist is
+ * called).
+ *
+ * Results:
+ * The return value is 1 if successful, or 0 if the X window has been
+ * already created.
+ *
+ * Side effects:
+ * The information given is stored for when the window is created.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_SetWindowVisual(
+ Tk_Window tkwin, /* Window to manipulate. */
+ Visual *visual, /* New visual for window. */
+ int depth, /* New depth for window. */
+ Colormap colormap) /* An appropriate colormap for the visual. */
+{
+ register TkWindow *winPtr = (TkWindow *) tkwin;
+
+ if (winPtr->window != None) {
+ /* Too late! */
+ return 0;
+ }
+
+ winPtr->visual = visual;
+ winPtr->depth = depth;
+ winPtr->atts.colormap = colormap;
+ winPtr->dirtyAtts |= CWColormap;
+
+ /*
+ * The following code is needed to make sure that the window doesn't
+ * inherit the parent's border pixmap, which would result in a BadMatch
+ * error.
+ */
+
+ if (!(winPtr->dirtyAtts & CWBorderPixmap)) {
+ winPtr->dirtyAtts |= CWBorderPixel;
+ }
+ return 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkDoConfigureNotify --
+ *
+ * Generate a ConfigureNotify event describing the current configuration
+ * of a window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * An event is generated and processed by Tk_HandleEvent.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkDoConfigureNotify(
+ register TkWindow *winPtr) /* Window whose configuration was just
+ * changed. */
+{
+ XEvent event;
+
+ event.type = ConfigureNotify;
+ event.xconfigure.serial = LastKnownRequestProcessed(winPtr->display);
+ event.xconfigure.send_event = False;
+ event.xconfigure.display = winPtr->display;
+ event.xconfigure.event = winPtr->window;
+ event.xconfigure.window = winPtr->window;
+ event.xconfigure.x = winPtr->changes.x;
+ event.xconfigure.y = winPtr->changes.y;
+ event.xconfigure.width = winPtr->changes.width;
+ event.xconfigure.height = winPtr->changes.height;
+ event.xconfigure.border_width = winPtr->changes.border_width;
+ if (winPtr->changes.stack_mode == Above) {
+ event.xconfigure.above = winPtr->changes.sibling;
+ } else {
+ event.xconfigure.above = None;
+ }
+ event.xconfigure.override_redirect = winPtr->atts.override_redirect;
+ Tk_HandleEvent(&event);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_SetClass --
+ *
+ * This function is used to give a window a class.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A new class is stored for tkwin, replacing any existing class for it.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_SetClass(
+ Tk_Window tkwin, /* Token for window to assign class. */
+ const char *className) /* New class for tkwin. */
+{
+ register TkWindow *winPtr = (TkWindow *) tkwin;
+
+ winPtr->classUid = Tk_GetUid(className);
+ if (winPtr->flags & TK_WIN_MANAGED) {
+ TkWmSetClass(winPtr);
+ }
+ TkOptionClassChanged(winPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_SetClassProcs --
+ *
+ * This function is used to set the class functions and instance data for
+ * a window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A new set of class functions and instance data is stored for tkwin,
+ * replacing any existing values.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_SetClassProcs(
+ Tk_Window tkwin, /* Token for window to modify. */
+ const Tk_ClassProcs *procs, /* Class procs structure. */
+ ClientData instanceData) /* Data to be passed to class functions. */
+{
+ register TkWindow *winPtr = (TkWindow *) tkwin;
+
+ winPtr->classProcsPtr = procs;
+ winPtr->instanceData = instanceData;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_NameToWindow --
+ *
+ * Given a string name for a window, this function returns the token for
+ * the window, if there exists a window corresponding to the given name.
+ *
+ * Results:
+ * The return result is either a token for the window corresponding to
+ * "name", or else NULL to indicate that there is no such window. In this
+ * case, an error message is left in the interp's result, unless interp
+ * is NULL.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_Window
+Tk_NameToWindow(
+ Tcl_Interp *interp, /* Where to report errors. */
+ const char *pathName, /* Path name of window. */
+ Tk_Window tkwin) /* Token for window: name is assumed to belong
+ * to the same main window as tkwin. */
+{
+ Tcl_HashEntry *hPtr;
+
+ if (tkwin == NULL) {
+ /*
+ * Either we're not really in Tk, or the main window was destroyed and
+ * we're on our way out of the application.
+ */
+
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("NULL main window",-1));
+ Tcl_SetErrorCode(interp, "TK", "NO_MAIN_WINDOW", NULL);
+ }
+ return NULL;
+ }
+
+ hPtr = Tcl_FindHashEntry(&((TkWindow *) tkwin)->mainPtr->nameTable,
+ pathName);
+ if (hPtr == NULL) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad window path name \"%s\"", pathName));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "WINDOW", pathName,
+ NULL);
+ }
+ return NULL;
+ }
+ return Tcl_GetHashValue(hPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_IdToWindow --
+ *
+ * Given an X display and window ID, this function returns the Tk token
+ * for the window, if there exists a Tk window corresponding to the given
+ * ID.
+ *
+ * Results:
+ * The return result is either a token for the window corresponding to
+ * the given X id, or else NULL to indicate that there is no such window.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_Window
+Tk_IdToWindow(
+ Display *display, /* X display containing the window. */
+ Window window) /* X window window id. */
+{
+ TkDisplay *dispPtr;
+ Tcl_HashEntry *hPtr;
+
+ for (dispPtr = TkGetDisplayList(); ; dispPtr = dispPtr->nextPtr) {
+ if (dispPtr == NULL) {
+ return NULL;
+ }
+ if (dispPtr->display == display) {
+ break;
+ }
+ }
+ if (window == None) {
+ return NULL;
+ }
+
+ hPtr = Tcl_FindHashEntry(&dispPtr->winTable, (char *) window);
+ if (hPtr == NULL) {
+ return NULL;
+ }
+ return Tcl_GetHashValue(hPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_DisplayName --
+ *
+ * Return the textual name of a window's display.
+ *
+ * Results:
+ * The return value is the string name of the display associated with
+ * tkwin.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+const char *
+Tk_DisplayName(
+ Tk_Window tkwin) /* Window whose display name is desired. */
+{
+ return ((TkWindow *) tkwin)->dispPtr->name;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_Interp --
+ *
+ * Get the Tcl interpreter from a Tk window.
+ *
+ * Results:
+ * A pointer to the interpreter or NULL.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Interp *
+Tk_Interp(
+ Tk_Window tkwin)
+{
+ if (tkwin != NULL && ((TkWindow *) tkwin)->mainPtr != NULL) {
+ return ((TkWindow *) tkwin)->mainPtr->interp;
+ }
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UnlinkWindow --
+ *
+ * This function removes a window from the childList of its parent.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The window is unlinked from its childList.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UnlinkWindow(
+ TkWindow *winPtr) /* Child window to be unlinked. */
+{
+ TkWindow *prevPtr;
+
+ if (winPtr->parentPtr == NULL) {
+ return;
+ }
+ prevPtr = winPtr->parentPtr->childList;
+ if (prevPtr == winPtr) {
+ winPtr->parentPtr->childList = winPtr->nextPtr;
+ if (winPtr->nextPtr == NULL) {
+ winPtr->parentPtr->lastChildPtr = NULL;
+ }
+ } else {
+ while (prevPtr->nextPtr != winPtr) {
+ prevPtr = prevPtr->nextPtr;
+ if (prevPtr == NULL) {
+ Tcl_Panic("UnlinkWindow couldn't find child in parent");
+ }
+ }
+ prevPtr->nextPtr = winPtr->nextPtr;
+ if (winPtr->nextPtr == NULL) {
+ winPtr->parentPtr->lastChildPtr = prevPtr;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_RestackWindow --
+ *
+ * Change a window's position in the stacking order.
+ *
+ * Results:
+ * TCL_OK is normally returned. If other is not a descendant of tkwin's
+ * parent then TCL_ERROR is returned and tkwin is not repositioned.
+ *
+ * Side effects:
+ * Tkwin is repositioned in the stacking order.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_RestackWindow(
+ Tk_Window tkwin, /* Token for window whose position in the
+ * stacking order is to change. */
+ int aboveBelow, /* Indicates new position of tkwin relative to
+ * other; must be Above or Below. */
+ Tk_Window other) /* Tkwin will be moved to a position that puts
+ * it just above or below this window. If NULL
+ * then tkwin goes above or below all windows
+ * in the same parent. */
+{
+ TkWindow *winPtr = (TkWindow *) tkwin;
+ TkWindow *otherPtr = (TkWindow *) other;
+
+ /*
+ * Special case: if winPtr is a top-level window then just find the
+ * top-level ancestor of otherPtr and restack winPtr above otherPtr
+ * without changing any of Tk's childLists.
+ */
+
+ if (winPtr->flags & TK_WIN_MANAGED) {
+ while ((otherPtr != NULL) && !(otherPtr->flags & TK_TOP_HIERARCHY)) {
+ otherPtr = otherPtr->parentPtr;
+ }
+ TkWmRestackToplevel(winPtr, aboveBelow, otherPtr);
+ return TCL_OK;
+ }
+
+ /*
+ * Find an ancestor of otherPtr that is a sibling of winPtr.
+ */
+
+ if (winPtr->parentPtr == NULL) {
+ /*
+ * Window is going to be deleted shortly; don't do anything.
+ */
+
+ return TCL_OK;
+ }
+ if (otherPtr == NULL) {
+ if (aboveBelow == Above) {
+ otherPtr = winPtr->parentPtr->lastChildPtr;
+ } else {
+ otherPtr = winPtr->parentPtr->childList;
+ }
+ } else {
+ while (winPtr->parentPtr != otherPtr->parentPtr) {
+ if ((otherPtr == NULL) || (otherPtr->flags & TK_TOP_HIERARCHY)) {
+ return TCL_ERROR;
+ }
+ otherPtr = otherPtr->parentPtr;
+ }
+ }
+ if (otherPtr == winPtr) {
+ return TCL_OK;
+ }
+
+ /*
+ * Reposition winPtr in the stacking order.
+ */
+
+ UnlinkWindow(winPtr);
+ if (aboveBelow == Above) {
+ winPtr->nextPtr = otherPtr->nextPtr;
+ if (winPtr->nextPtr == NULL) {
+ winPtr->parentPtr->lastChildPtr = winPtr;
+ }
+ otherPtr->nextPtr = winPtr;
+ } else {
+ TkWindow *prevPtr;
+
+ prevPtr = winPtr->parentPtr->childList;
+ if (prevPtr == otherPtr) {
+ winPtr->parentPtr->childList = winPtr;
+ } else {
+ while (prevPtr->nextPtr != otherPtr) {
+ prevPtr = prevPtr->nextPtr;
+ }
+ prevPtr->nextPtr = winPtr;
+ }
+ winPtr->nextPtr = otherPtr;
+ }
+
+ /*
+ * Notify the X server of the change. If winPtr hasn't yet been created
+ * then there's no need to tell the X server now, since the stacking order
+ * will be handled properly when the window is finally created.
+ */
+
+ if (winPtr->window != None) {
+ XWindowChanges changes;
+ unsigned int mask = CWStackMode;
+
+ changes.stack_mode = Above;
+ for (otherPtr = winPtr->nextPtr; otherPtr != NULL;
+ otherPtr = otherPtr->nextPtr) {
+ if ((otherPtr->window != None)
+ && !(otherPtr->flags & (TK_TOP_HIERARCHY|TK_REPARENTED))){
+ changes.sibling = otherPtr->window;
+ changes.stack_mode = Below;
+ mask = CWStackMode|CWSibling;
+ break;
+ }
+ }
+ XConfigureWindow(winPtr->display, winPtr->window, mask, &changes);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_MainWindow --
+ *
+ * Returns the main window for an application.
+ *
+ * Results:
+ * If interp has a Tk application associated with it, the main window for
+ * the application is returned. Otherwise NULL is returned and an error
+ * message is left in the interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_Window
+Tk_MainWindow(
+ Tcl_Interp *interp) /* Interpreter that embodies the application.
+ * Used for error reporting also. */
+{
+ TkMainInfo *mainPtr;
+ ThreadSpecificData *tsdPtr;
+
+ if (interp == NULL) {
+ return NULL;
+ }
+#ifdef USE_TCL_STUBS
+ if (tclStubsPtr == NULL) {
+ return NULL;
+ }
+#endif
+ tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ for (mainPtr = tsdPtr->mainWindowList; mainPtr != NULL;
+ mainPtr = mainPtr->nextPtr) {
+ if (mainPtr->interp == interp) {
+ return (Tk_Window) mainPtr->winPtr;
+ }
+ }
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "this isn't a Tk application", -1));
+ Tcl_SetErrorCode(interp, "TK", "NO_MAIN_WINDOW", NULL);
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_StrictMotif --
+ *
+ * Indicates whether strict Motif compliance has been specified for the
+ * given window.
+ *
+ * Results:
+ * The return value is 1 if strict Motif compliance has been requested
+ * for tkwin's application by setting the tk_strictMotif variable in its
+ * interpreter to a true value. 0 is returned if tk_strictMotif has a
+ * false value.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_StrictMotif(
+ Tk_Window tkwin) /* Window whose application is to be
+ * checked. */
+{
+ return ((TkWindow *) tkwin)->mainPtr->strictMotif;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetNumMainWindows --
+ *
+ * This function returns the number of main windows currently open in
+ * this process.
+ *
+ * Results:
+ * The number of main windows open in this process.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_GetNumMainWindows(void)
+{
+ ThreadSpecificData *tsdPtr;
+
+#ifdef USE_TCL_STUBS
+ if (tclStubsPtr == NULL) {
+ return 0;
+ }
+#endif
+
+ tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ return tsdPtr->numMainWindows;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpAlwaysShowSelection --
+ *
+ * Indicates whether text/entry widgets should always display
+ * their selection, regardless of window focus.
+ *
+ * Results:
+ * The return value is 1 if always showing the selection has been
+ * requested for tkwin's application by setting the
+ * ::tk::AlwaysShowSelection variable in its interpreter to a true value.
+ * 0 is returned if it has a false value.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkpAlwaysShowSelection(
+ Tk_Window tkwin) /* Window whose application is to be
+ * checked. */
+{
+ return ((TkWindow *) tkwin)->mainPtr->alwaysShowSelection;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DeleteWindowsExitProc --
+ *
+ * This function is invoked as an exit handler. It deletes all of the
+ * main windows in the current thread. We really should be using a thread
+ * local exit handler to delete windows and a process exit handler to
+ * close the display but Tcl does not provide support for this usage.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DeleteWindowsExitProc(
+ ClientData clientData) /* tsdPtr when handler was created. */
+{
+ TkDisplay *dispPtr, *nextPtr;
+ Tcl_Interp *interp;
+ ThreadSpecificData *tsdPtr = clientData;
+
+ if (tsdPtr == NULL) {
+ return;
+ }
+
+ /*
+ * Finish destroying any windows that are in a half-dead state. We must
+ * protect the interpreter while destroying the window, because of
+ * <Destroy> bindings which could destroy the interpreter while the window
+ * is being deleted. This would leave frames on the call stack pointing at
+ * deleted memory, causing core dumps.
+ */
+
+ while (tsdPtr->halfdeadWindowList != NULL) {
+ interp = tsdPtr->halfdeadWindowList->winPtr->mainPtr->interp;
+ Tcl_Preserve(interp);
+ tsdPtr->halfdeadWindowList->flags |= HD_CLEANUP;
+ tsdPtr->halfdeadWindowList->winPtr->flags &= ~TK_ALREADY_DEAD;
+ Tk_DestroyWindow((Tk_Window) tsdPtr->halfdeadWindowList->winPtr);
+ Tcl_Release(interp);
+ }
+
+ /*
+ * Destroy any remaining main windows.
+ */
+
+ while (tsdPtr->mainWindowList != NULL) {
+ interp = tsdPtr->mainWindowList->interp;
+ Tcl_Preserve(interp);
+ Tk_DestroyWindow((Tk_Window) tsdPtr->mainWindowList->winPtr);
+ Tcl_Release(interp);
+ }
+
+ /*
+ * Let error handlers catch up before actual close of displays.
+ * Must be done before tsdPtr->displayList is cleared, otherwise
+ * ErrorProc() in tkError.c cannot associate the pending X errors
+ * to the remaining error handlers.
+ */
+
+ for (dispPtr = tsdPtr->displayList; dispPtr != NULL;
+ dispPtr = dispPtr->nextPtr) {
+ XSync(dispPtr->display, False);
+ }
+
+ /*
+ * Iterate destroying the displays until no more displays remain. It is
+ * possible for displays to get recreated during exit by any code that
+ * calls GetScreen, so we must destroy these new displays as well as the
+ * old ones.
+ */
+
+ for (dispPtr = tsdPtr->displayList; dispPtr != NULL;
+ dispPtr = tsdPtr->displayList) {
+ /*
+ * Now iterate over the current list of open displays, and first set
+ * the global pointer to NULL so we will be able to notice if any new
+ * displays got created during deletion of the current set. We must
+ * also do this to ensure that Tk_IdToWindow does not find the old
+ * display as it is being destroyed, when it wants to see if it needs
+ * to dispatch a message.
+ */
+
+ for (tsdPtr->displayList = NULL; dispPtr != NULL; dispPtr = nextPtr) {
+ nextPtr = dispPtr->nextPtr;
+ TkCloseDisplay(dispPtr);
+ }
+ }
+
+ tsdPtr->numMainWindows = 0;
+ tsdPtr->mainWindowList = NULL;
+ tsdPtr->initialized = 0;
+}
+
+#if defined(_WIN32)
+
+static HMODULE tkcygwindll = NULL;
+
+/*
+ * Run Tk_MainEx from libtk8.?.dll
+ *
+ * This function is only ever called from wish8.4.exe, the cygwin port of Tcl.
+ * This means that the system encoding is utf-8, so we don't have to do any
+ * encoding conversions.
+ */
+
+int
+TkCygwinMainEx(
+ int argc, /* Number of arguments. */
+ char **argv, /* Array of argument strings. */
+ Tcl_AppInitProc *appInitProc,
+ /* Application-specific initialization
+ * procedure to call after most initialization
+ * but before starting to execute commands. */
+ Tcl_Interp *interp)
+{
+ TCHAR name[MAX_PATH];
+ int len;
+ void (*tkmainex)(int, char **, Tcl_AppInitProc *, Tcl_Interp *);
+
+ /* construct "<path>/libtk8.?.dll", from "<path>/tk8?.dll" */
+ len = GetModuleFileNameW(Tk_GetHINSTANCE(), name, MAX_PATH);
+ name[len-2] = TEXT('.');
+ name[len-1] = name[len-5];
+ _tcscpy(name+len, TEXT(".dll"));
+ memcpy(name+len-8, TEXT("libtk8"), 6 * sizeof(TCHAR));
+
+ tkcygwindll = LoadLibrary(name);
+ if (!tkcygwindll) {
+ /* dll is not present */
+ return 0;
+ }
+ tkmainex = (void (*)(int, char **, Tcl_AppInitProc *, Tcl_Interp *))
+ GetProcAddress(tkcygwindll, "Tk_MainEx");
+ if (!tkmainex) {
+ return 0;
+ }
+ tkmainex(argc, argv, appInitProc, interp);
+ return 1;
+}
+#endif /* _WIN32 */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_Init --
+ *
+ * This function is invoked to add Tk to an interpreter. It incorporates
+ * all of Tk's commands into the interpreter and creates the main window
+ * for a new Tk application. If the interpreter contains a variable
+ * "argv", this function extracts several arguments from that variable,
+ * uses them to configure the main window, and modifies argv to exclude
+ * the arguments (see the "wish" documentation for a list of the
+ * arguments that are extracted).
+ *
+ * Results:
+ * Returns a standard Tcl completion code and sets the interp's result if
+ * there is an error.
+ *
+ * Side effects:
+ * Depends on various initialization scripts that get invoked.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_Init(
+ Tcl_Interp *interp) /* Interpreter to initialize. */
+{
+#if defined(_WIN32)
+ if (tkcygwindll) {
+ int (*tkinit)(Tcl_Interp *);
+
+ tkinit = (int(*)(Tcl_Interp *)) GetProcAddress(tkcygwindll,"Tk_Init");
+ if (tkinit) {
+ return tkinit(interp);
+ }
+ }
+#endif /* _WIN32 */
+ return Initialize(interp);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_SafeInit --
+ *
+ * This function is invoked to add Tk to a safe interpreter. It invokes
+ * the internal function that does the real work.
+ *
+ * Results:
+ * Returns a standard Tcl completion code and sets the interp's result if
+ * there is an error.
+ *
+ * Side effects:
+ * Depends on various initialization scripts that are invoked.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_SafeInit(
+ Tcl_Interp *interp) /* Interpreter to initialize. */
+{
+ /*
+ * Initialize the interpreter with Tk, safely. This removes all the Tk
+ * commands that are unsafe.
+ *
+ * Rationale:
+ *
+ * - Toplevel and menu are unsafe because they can be used to cover the
+ * entire screen and to steal input from the user.
+ * - Continuous ringing of the bell is a nuisance.
+ * - Cannot allow access to the clipboard because a malicious script can
+ * replace the contents with the string "rm -r *" and lead to surprises
+ * when the contents of the clipboard are pasted. Similarly, the
+ * selection command is blocked.
+ * - Cannot allow send because it can be used to cause unsafe interpreters
+ * to execute commands. The tk command recreates the send command, so
+ * that too must be hidden.
+ * - Focus can be used to grab the focus away from another window, in
+ * effect stealing user input. Cannot allow that.
+ * NOTE: We currently do *not* hide focus as it would make it impossible
+ * to provide keyboard input to Tk in a safe interpreter.
+ * - Grab can be used to block the user from using any other apps on the
+ * screen.
+ * - Tkwait can block the containing process forever. Use bindings,
+ * fileevents and split the protocol into before-the-wait and
+ * after-the-wait parts. More work but necessary.
+ * - Wm is unsafe because (if toplevels are allowed, in the future) it can
+ * be used to remove decorations, move windows around, cover the entire
+ * screen etc etc.
+ *
+ * Current risks:
+ *
+ * - No CPU time limit, no memory allocation limits, no color limits.
+ * CPU time limits can be imposed by an unsafe master interpreter.
+ *
+ * The actual code called is the same as Tk_Init but Tcl_IsSafe() is
+ * checked at several places to differentiate the two initialisations.
+ */
+
+#if defined(_WIN32)
+ if (tkcygwindll) {
+ int (*tksafeinit)(Tcl_Interp *);
+
+ tksafeinit = (int (*)(Tcl_Interp *))
+ GetProcAddress(tkcygwindll, "Tk_SafeInit");
+ if (tksafeinit) {
+ return tksafeinit(interp);
+ }
+ }
+#endif /* _WIN32 */
+ return Initialize(interp);
+}
+
+MODULE_SCOPE const TkStubs tkStubs;
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Initialize --
+ *
+ * The core of the initialization code for Tk, called from Tk_Init and
+ * Tk_SafeInit.
+ *
+ * Results:
+ * A standard Tcl result. Also leaves an error message in the interp's
+ * result if there was an error.
+ *
+ * Side effects:
+ * Depends on the initialization scripts that are invoked.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CopyValue(
+ ClientData dummy,
+ Tcl_Obj *objPtr,
+ void *dstPtr)
+{
+ *(Tcl_Obj **)dstPtr = objPtr;
+ return 1;
+}
+
+static int
+Initialize(
+ Tcl_Interp *interp) /* Interpreter to initialize. */
+{
+ int code = TCL_OK;
+ ThreadSpecificData *tsdPtr;
+ Tcl_Obj *value = NULL;
+ Tcl_Obj *cmd;
+
+ Tcl_Obj *nameObj = NULL;
+ Tcl_Obj *classObj = NULL;
+ Tcl_Obj *displayObj = NULL;
+ Tcl_Obj *colorMapObj = NULL;
+ Tcl_Obj *useObj = NULL;
+ Tcl_Obj *visualObj = NULL;
+ Tcl_Obj *geometryObj = NULL;
+
+ int sync = 0;
+
+ const Tcl_ArgvInfo table[] = {
+ {TCL_ARGV_CONSTANT, "-sync", INT2PTR(1), &sync,
+ "Use synchronous mode for display server", NULL},
+ {TCL_ARGV_FUNC, "-colormap", CopyValue, &colorMapObj,
+ "Colormap for main window", NULL},
+ {TCL_ARGV_FUNC, "-display", CopyValue, &displayObj,
+ "Display to use", NULL},
+ {TCL_ARGV_FUNC, "-geometry", CopyValue, &geometryObj,
+ "Initial geometry for window", NULL},
+ {TCL_ARGV_FUNC, "-name", CopyValue, &nameObj,
+ "Name to use for application", NULL},
+ {TCL_ARGV_FUNC, "-visual", CopyValue, &visualObj,
+ "Visual for main window", NULL},
+ {TCL_ARGV_FUNC, "-use", CopyValue, &useObj,
+ "Id of window in which to embed application", NULL},
+ TCL_ARGV_AUTO_REST, TCL_ARGV_AUTO_HELP, TCL_ARGV_TABLE_END
+ };
+
+ /*
+ * Ensure that we are getting a compatible version of Tcl.
+ */
+
+ if (Tcl_InitStubs(interp, "8.6", 0) == NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Ensure that our obj-types are registered with the Tcl runtime.
+ */
+
+ TkRegisterObjTypes();
+
+ tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ /*
+ * We start by resetting the result because it might not be clean.
+ */
+
+ Tcl_ResetResult(interp);
+
+ if (Tcl_IsSafe(interp)) {
+ /*
+ * Get the clearance to start Tk and the "argv" parameters from the
+ * master.
+ */
+
+ /*
+ * Step 1 : find the master and construct the interp name (could be a
+ * function if new APIs were ok). We could also construct the path
+ * while walking, but there is no API to get the name of an interp
+ * either.
+ */
+
+ Tcl_Interp *master = interp;
+
+ while (Tcl_IsSafe(master)) {
+ master = Tcl_GetMaster(master);
+ if (master == NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "no controlling master interpreter", -1));
+ Tcl_SetErrorCode(interp, "TK", "SAFE", "NO_MASTER", NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * Construct the name (rewalk...)
+ */
+
+ code = Tcl_GetInterpPath(master, interp);
+ if (code != TCL_OK) {
+ Tcl_Panic("Tcl_GetInterpPath broken!");
+ }
+
+ /*
+ * Build the command to eval in trusted master.
+ */
+
+ cmd = Tcl_NewListObj(2, NULL);
+ Tcl_ListObjAppendElement(NULL, cmd,
+ Tcl_NewStringObj("::safe::TkInit", -1));
+ Tcl_ListObjAppendElement(NULL, cmd, Tcl_GetObjResult(master));
+
+ /*
+ * Step 2 : Eval in the master. The argument is the *reversed* interp
+ * path of the slave.
+ */
+
+ Tcl_IncrRefCount(cmd);
+ code = Tcl_EvalObjEx(master, cmd, 0);
+ Tcl_DecrRefCount(cmd);
+ Tcl_TransferResult(master, code, interp);
+ if (code != TCL_OK) {
+ return code;
+ }
+
+ /*
+ * Use the master's result as argv. Note: We don't use the Obj
+ * interfaces to avoid dealing with cross interp refcounting and
+ * changing the code below.
+ */
+
+ value = Tcl_GetObjResult(interp);
+ } else {
+ /*
+ * If there is an "argv" variable, get its value, extract out relevant
+ * arguments from it, and rewrite the variable without the arguments
+ * that we used.
+ */
+
+ value = Tcl_GetVar2Ex(interp, "argv", NULL, TCL_GLOBAL_ONLY);
+ }
+
+ if (value) {
+ int objc;
+ Tcl_Obj **objv, **rest;
+ Tcl_Obj *parseList = Tcl_NewListObj(1, NULL);
+
+ Tcl_ListObjAppendElement(NULL, parseList, Tcl_NewObj());
+
+ Tcl_IncrRefCount(value);
+ if (TCL_OK != Tcl_ListObjAppendList(interp, parseList, value) ||
+ TCL_OK != Tcl_ListObjGetElements(NULL, parseList, &objc, &objv) ||
+ TCL_OK != Tcl_ParseArgsObjv(interp, table, &objc, objv, &rest)) {
+ Tcl_AddErrorInfo(interp,
+ "\n (processing arguments in argv variable)");
+ code = TCL_ERROR;
+ }
+ if (code == TCL_OK) {
+ Tcl_SetVar2Ex(interp, "argv", NULL,
+ Tcl_NewListObj(objc-1, rest+1), TCL_GLOBAL_ONLY);
+ Tcl_SetVar2Ex(interp, "argc", NULL,
+ Tcl_NewIntObj(objc-1), TCL_GLOBAL_ONLY);
+ ckfree(rest);
+ }
+ Tcl_DecrRefCount(parseList);
+ if (code != TCL_OK) {
+ goto done;
+ }
+ }
+
+ /*
+ * Figure out the application's name and class.
+ */
+
+ /*
+ * If we got no -name argument, fetch from TkpGetAppName().
+ */
+
+ if (nameObj == NULL) {
+ Tcl_DString nameDS;
+
+ Tcl_DStringInit(&nameDS);
+ TkpGetAppName(interp, &nameDS);
+ nameObj = Tcl_NewStringObj(Tcl_DStringValue(&nameDS),
+ Tcl_DStringLength(&nameDS));
+ Tcl_DStringFree(&nameDS);
+ }
+
+ /*
+ * The -class argument is always the ToTitle of the -name
+ */
+
+ {
+ int numBytes;
+ const char *bytes = Tcl_GetStringFromObj(nameObj, &numBytes);
+
+ classObj = Tcl_NewStringObj(bytes, numBytes);
+
+ numBytes = Tcl_UtfToTitle(Tcl_GetString(classObj));
+ Tcl_SetObjLength(classObj, numBytes);
+ }
+
+ /*
+ * Create an argument list for creating the top-level window, using the
+ * information parsed from argv, if any.
+ */
+
+ cmd = Tcl_NewStringObj("toplevel . -class", -1);
+
+ Tcl_ListObjAppendElement(NULL, cmd, classObj);
+ classObj = NULL;
+
+ if (displayObj) {
+ Tcl_ListObjAppendElement(NULL, cmd, Tcl_NewStringObj("-screen", -1));
+ Tcl_ListObjAppendElement(NULL, cmd, displayObj);
+
+ /*
+ * If this is the first application for this process, save the display
+ * name in the DISPLAY environment variable so that it will be
+ * available to subprocesses created by us.
+ */
+
+ if (tsdPtr->numMainWindows == 0) {
+ Tcl_SetVar2Ex(interp, "env", "DISPLAY", displayObj, TCL_GLOBAL_ONLY);
+ }
+ displayObj = NULL;
+ }
+ if (colorMapObj) {
+ Tcl_ListObjAppendElement(NULL, cmd, Tcl_NewStringObj("-colormap", -1));
+ Tcl_ListObjAppendElement(NULL, cmd, colorMapObj);
+ colorMapObj = NULL;
+ }
+ if (useObj) {
+ Tcl_ListObjAppendElement(NULL, cmd, Tcl_NewStringObj("-use", -1));
+ Tcl_ListObjAppendElement(NULL, cmd, useObj);
+ useObj = NULL;
+ }
+ if (visualObj) {
+ Tcl_ListObjAppendElement(NULL, cmd, Tcl_NewStringObj("-visual", -1));
+ Tcl_ListObjAppendElement(NULL, cmd, visualObj);
+ visualObj = NULL;
+ }
+
+ code = TkListCreateFrame(NULL, interp, cmd, 1, nameObj);
+
+ Tcl_DecrRefCount(cmd);
+
+ if (code != TCL_OK) {
+ goto done;
+ }
+ Tcl_ResetResult(interp);
+ if (sync) {
+ XSynchronize(Tk_Display(Tk_MainWindow(interp)), True);
+ }
+
+ /*
+ * Set the geometry of the main window, if requested. Put the requested
+ * geometry into the "geometry" variable.
+ */
+
+ if (geometryObj) {
+
+ Tcl_SetVar2Ex(interp, "geometry", NULL, geometryObj, TCL_GLOBAL_ONLY);
+
+ cmd = Tcl_NewStringObj("wm geometry .", -1);
+ Tcl_ListObjAppendElement(NULL, cmd, geometryObj);
+ Tcl_IncrRefCount(cmd);
+ code = Tcl_EvalObjEx(interp, cmd, 0);
+ Tcl_DecrRefCount(cmd);
+ geometryObj = NULL;
+ if (code != TCL_OK) {
+ goto done;
+ }
+ }
+
+ /*
+ * Provide Tk and its stub table.
+ */
+
+ code = Tcl_PkgProvideEx(interp, "Tk", TK_PATCH_LEVEL,
+ (ClientData) &tkStubs);
+ if (code != TCL_OK) {
+ goto done;
+ }
+
+ /*
+ * If we were able to provide ourselves as a package, then set the main
+ * loop function in Tcl to our main loop proc. This will cause tclsh to be
+ * event-aware when Tk is dynamically loaded. This will have no effect in
+ * wish, which already is prepared to run the event loop.
+ */
+
+ Tcl_SetMainLoop(Tk_MainLoop);
+
+ /*
+ * Initialized the themed widget set
+ */
+
+ code = Ttk_Init(interp);
+ if (code != TCL_OK) {
+ goto done;
+ }
+
+ /*
+ * Invoke platform-specific initialization. Unlock mutex before entering
+ * TkpInit, as that may run through the Tk_Init routine again for the
+ * console window interpreter.
+ */
+
+ code = TkpInit(interp);
+ if (code == TCL_OK) {
+
+ /*
+ * In order to find tk.tcl during initialization, we evaluate the
+ * following script. It calls on the Tcl command [tcl_findLibrary]
+ * to perform the search. See the docs for that command for details
+ * on where it looks.
+ *
+ * Note that this entire search mechanism can be bypassed by defining
+ * an alternate [tkInit] command before calling Tk_Init().
+ */
+
+ code = Tcl_EvalEx(interp,
+"if {[namespace which -command tkInit] eq \"\"} {\n\
+ proc tkInit {} {\n\
+ global tk_library tk_version tk_patchLevel\n\
+ rename tkInit {}\n\
+ tcl_findLibrary tk $tk_version $tk_patchLevel tk.tcl TK_LIBRARY tk_library\n\
+ }\n\
+}\n\
+tkInit", -1, 0);
+ }
+ if (code == TCL_OK) {
+ /*
+ * Create exit handlers to delete all windows when the application or
+ * thread exits. The handler need to be invoked before other platform
+ * specific cleanups take place to avoid panics in finalization.
+ */
+
+ TkCreateThreadExitHandler(DeleteWindowsExitProc, tsdPtr);
+ }
+ done:
+ if (value) {
+ Tcl_DecrRefCount(value);
+ value = NULL;
+ }
+ return code;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_PkgInitStubsCheck --
+ *
+ * This is a replacement routine for Tk_InitStubs() that is called
+ * from code where -DUSE_TK_STUBS has not been enabled.
+ *
+ * Results:
+ * Returns the version of a conforming Tk stubs table, or NULL, if
+ * the table version doesn't satisfy the requested requirements,
+ * according to historical practice.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+const char *
+Tk_PkgInitStubsCheck(
+ Tcl_Interp *interp,
+ const char * version,
+ int exact)
+{
+ const char *actualVersion = Tcl_PkgRequireEx(interp, "Tk", version, 0, NULL);
+
+ if (exact && actualVersion) {
+ const char *p = version;
+ int count = 0;
+
+ while (*p) {
+ count += !isdigit(UCHAR(*p++));
+ }
+ if (count == 1) {
+ if (0 != strncmp(version, actualVersion, strlen(version))) {
+ /* Construct error message */
+ Tcl_PkgPresentEx(interp, "Tk", version, 1, NULL);
+ return NULL;
+ }
+ } else {
+ return Tcl_PkgPresentEx(interp, "Tk", version, 1, NULL);
+ }
+ }
+ return actualVersion;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tk8.6/generic/ttk/ttk.decls b/tk8.6/generic/ttk/ttk.decls
new file mode 100644
index 0000000..e668a2a
--- /dev/null
+++ b/tk8.6/generic/ttk/ttk.decls
@@ -0,0 +1,150 @@
+library ttk
+interface ttk
+epoch 0
+scspec TTKAPI
+
+declare 0 {
+ Ttk_Theme Ttk_GetTheme(Tcl_Interp *interp, const char *name)
+}
+declare 1 {
+ Ttk_Theme Ttk_GetDefaultTheme(Tcl_Interp *interp)
+}
+declare 2 {
+ Ttk_Theme Ttk_GetCurrentTheme(Tcl_Interp *interp)
+}
+declare 3 {
+ Ttk_Theme Ttk_CreateTheme(
+ Tcl_Interp *interp, const char *name, Ttk_Theme parent)
+}
+declare 4 {
+ void Ttk_RegisterCleanup(
+ Tcl_Interp *interp, void *deleteData, Ttk_CleanupProc *cleanupProc)
+}
+
+declare 5 {
+ int Ttk_RegisterElementSpec(
+ Ttk_Theme theme,
+ const char *elementName,
+ Ttk_ElementSpec *elementSpec,
+ void *clientData)
+}
+
+declare 6 {
+ Ttk_ElementClass *Ttk_RegisterElement(
+ Tcl_Interp *interp,
+ Ttk_Theme theme,
+ const char *elementName,
+ Ttk_ElementSpec *elementSpec,
+ void *clientData)
+}
+
+declare 7 {
+ int Ttk_RegisterElementFactory(
+ Tcl_Interp *interp,
+ const char *name,
+ Ttk_ElementFactory factoryProc,
+ void *clientData)
+}
+
+declare 8 {
+ void Ttk_RegisterLayout(
+ Ttk_Theme theme, const char *className, Ttk_LayoutSpec layoutSpec)
+}
+
+#
+# State maps.
+#
+declare 10 {
+ int Ttk_GetStateSpecFromObj(
+ Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_StateSpec *spec_rtn)
+}
+declare 11 {
+ Tcl_Obj *Ttk_NewStateSpecObj(
+ unsigned int onbits, unsigned int offbits)
+}
+declare 12 {
+ Ttk_StateMap Ttk_GetStateMapFromObj(
+ Tcl_Interp *interp, Tcl_Obj *objPtr)
+}
+declare 13 {
+ Tcl_Obj *Ttk_StateMapLookup(
+ Tcl_Interp *interp, Ttk_StateMap map, Ttk_State state)
+}
+declare 14 {
+ int Ttk_StateTableLookup(
+ Ttk_StateTable map[], Ttk_State state)
+}
+
+
+#
+# Low-level geometry utilities.
+#
+declare 20 {
+ int Ttk_GetPaddingFromObj(
+ Tcl_Interp *interp,
+ Tk_Window tkwin,
+ Tcl_Obj *objPtr,
+ Ttk_Padding *pad_rtn)
+}
+declare 21 {
+ int Ttk_GetBorderFromObj(
+ Tcl_Interp *interp,
+ Tcl_Obj *objPtr,
+ Ttk_Padding *pad_rtn)
+}
+declare 22 {
+ int Ttk_GetStickyFromObj(
+ Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_Sticky *sticky_rtn)
+}
+declare 23 {
+ Ttk_Padding Ttk_MakePadding(
+ short l, short t, short r, short b)
+}
+declare 24 {
+ Ttk_Padding Ttk_UniformPadding(
+ short borderWidth)
+}
+declare 25 {
+ Ttk_Padding Ttk_AddPadding(Ttk_Padding pad1, Ttk_Padding pad2)
+}
+declare 26 {
+ Ttk_Padding Ttk_RelievePadding(
+ Ttk_Padding padding, int relief, int n)
+}
+declare 27 {
+ Ttk_Box Ttk_MakeBox(int x, int y, int width, int height)
+}
+declare 28 {
+ int Ttk_BoxContains(Ttk_Box box, int x, int y)
+}
+declare 29 {
+ Ttk_Box Ttk_PackBox(Ttk_Box *cavity, int w, int h, Ttk_Side side)
+}
+declare 30 {
+ Ttk_Box Ttk_StickBox(Ttk_Box parcel, int w, int h, Ttk_Sticky sticky)
+}
+declare 31 {
+ Ttk_Box Ttk_AnchorBox(Ttk_Box parcel, int w, int h, Tk_Anchor anchor)
+}
+declare 32 {
+ Ttk_Box Ttk_PadBox(Ttk_Box b, Ttk_Padding p)
+}
+declare 33 {
+ Ttk_Box Ttk_ExpandBox(Ttk_Box b, Ttk_Padding p)
+}
+declare 34 {
+ Ttk_Box Ttk_PlaceBox(
+ Ttk_Box *cavity, int w, int h, Ttk_Side side, Ttk_Sticky sticky)
+}
+declare 35 {
+ Tcl_Obj *Ttk_NewBoxObj(Ttk_Box box)
+}
+
+#
+# Utilities.
+#
+declare 40 {
+ int Ttk_GetOrientFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int *orient)
+}
+
+
diff --git a/tk8.6/generic/ttk/ttkBlink.c b/tk8.6/generic/ttk/ttkBlink.c
new file mode 100644
index 0000000..706a871
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkBlink.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2004, Joe English.
+ *
+ * Usage:
+ * TtkBlinkCursor(corePtr), usually called in a widget's Init hook,
+ * arranges to periodically toggle the corePtr->flags CURSOR_ON bit
+ * on and off (and schedule a redisplay) whenever the widget has focus.
+ *
+ * Note: Widgets may have additional logic to decide whether
+ * to display the cursor or not (e.g., readonly or disabled states);
+ * TtkBlinkCursor() does not account for this.
+ *
+ * TODO:
+ * Add script-level access to configure application-wide blink rate.
+ */
+
+#include <tk.h>
+#include "ttkTheme.h"
+#include "ttkWidget.h"
+
+#define DEF_CURSOR_ON_TIME 600 /* milliseconds */
+#define DEF_CURSOR_OFF_TIME 300 /* milliseconds */
+
+/* Interp-specific data for tracking cursors:
+ */
+typedef struct
+{
+ WidgetCore *owner; /* Widget that currently has cursor */
+ Tcl_TimerToken timer; /* Blink timer */
+ int onTime; /* #milliseconds to blink cursor on */
+ int offTime; /* #milliseconds to blink cursor off */
+} CursorManager;
+
+/* CursorManagerDeleteProc --
+ * InterpDeleteProc for cursor manager.
+ */
+static void CursorManagerDeleteProc(ClientData clientData, Tcl_Interp *interp)
+{
+ CursorManager *cm = (CursorManager*)clientData;
+ if (cm->timer) {
+ Tcl_DeleteTimerHandler(cm->timer);
+ }
+ ckfree(clientData);
+}
+
+/* GetCursorManager --
+ * Look up and create if necessary the interp's cursor manager.
+ */
+static CursorManager *GetCursorManager(Tcl_Interp *interp)
+{
+ static const char *cm_key = "ttk::CursorManager";
+ CursorManager *cm = Tcl_GetAssocData(interp, cm_key,0);
+
+ if (!cm) {
+ cm = ckalloc(sizeof(*cm));
+ cm->timer = 0;
+ cm->owner = 0;
+ cm->onTime = DEF_CURSOR_ON_TIME;
+ cm->offTime = DEF_CURSOR_OFF_TIME;
+ Tcl_SetAssocData(interp,cm_key,CursorManagerDeleteProc,(ClientData)cm);
+ }
+ return cm;
+}
+
+/* CursorBlinkProc --
+ * Timer handler to blink the insert cursor on and off.
+ */
+static void
+CursorBlinkProc(ClientData clientData)
+{
+ CursorManager *cm = (CursorManager*)clientData;
+ int blinkTime;
+
+ if (cm->owner->flags & CURSOR_ON) {
+ cm->owner->flags &= ~CURSOR_ON;
+ blinkTime = cm->offTime;
+ } else {
+ cm->owner->flags |= CURSOR_ON;
+ blinkTime = cm->onTime;
+ }
+ cm->timer = Tcl_CreateTimerHandler(blinkTime, CursorBlinkProc, clientData);
+ TtkRedisplayWidget(cm->owner);
+}
+
+/* LoseCursor --
+ * Turn cursor off, disable blink timer.
+ */
+static void LoseCursor(CursorManager *cm, WidgetCore *corePtr)
+{
+ if (corePtr->flags & CURSOR_ON) {
+ corePtr->flags &= ~CURSOR_ON;
+ TtkRedisplayWidget(corePtr);
+ }
+ if (cm->owner == corePtr) {
+ cm->owner = NULL;
+ }
+ if (cm->timer) {
+ Tcl_DeleteTimerHandler(cm->timer);
+ cm->timer = 0;
+ }
+}
+
+/* ClaimCursor --
+ * Claim ownership of the insert cursor and blink on.
+ */
+static void ClaimCursor(CursorManager *cm, WidgetCore *corePtr)
+{
+ if (cm->owner == corePtr)
+ return;
+ if (cm->owner)
+ LoseCursor(cm, cm->owner);
+
+ corePtr->flags |= CURSOR_ON;
+ TtkRedisplayWidget(corePtr);
+
+ cm->owner = corePtr;
+ cm->timer = Tcl_CreateTimerHandler(cm->onTime, CursorBlinkProc, cm);
+}
+
+/*
+ * CursorEventProc --
+ * Event handler for FocusIn and FocusOut events;
+ * claim/lose ownership of the insert cursor when the widget
+ * acquires/loses keyboard focus.
+ */
+
+#define CursorEventMask (FocusChangeMask|StructureNotifyMask)
+#define RealFocusEvent(d) \
+ (d == NotifyInferior || d == NotifyAncestor || d == NotifyNonlinear)
+
+static void
+CursorEventProc(ClientData clientData, XEvent *eventPtr)
+{
+ WidgetCore *corePtr = (WidgetCore *)clientData;
+ CursorManager *cm = GetCursorManager(corePtr->interp);
+
+ switch (eventPtr->type) {
+ case DestroyNotify:
+ if (cm->owner == corePtr)
+ LoseCursor(cm, corePtr);
+ Tk_DeleteEventHandler(
+ corePtr->tkwin, CursorEventMask, CursorEventProc, clientData);
+ break;
+ case FocusIn:
+ if (RealFocusEvent(eventPtr->xfocus.detail))
+ ClaimCursor(cm, corePtr);
+ break;
+ case FocusOut:
+ if (RealFocusEvent(eventPtr->xfocus.detail))
+ LoseCursor(cm, corePtr);
+ break;
+ }
+}
+
+/*
+ * TtkBlinkCursor (main routine) --
+ * Arrange to blink the cursor on and off whenever the
+ * widget has focus.
+ */
+void TtkBlinkCursor(WidgetCore *corePtr)
+{
+ Tk_CreateEventHandler(
+ corePtr->tkwin, CursorEventMask, CursorEventProc, corePtr);
+}
+
+/*EOF*/
diff --git a/tk8.6/generic/ttk/ttkButton.c b/tk8.6/generic/ttk/ttkButton.c
new file mode 100644
index 0000000..68a6293
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkButton.c
@@ -0,0 +1,870 @@
+/*
+ * Copyright (c) 2003, Joe English
+ *
+ * label, button, checkbutton, radiobutton, and menubutton widgets.
+ */
+
+#include <string.h>
+#include <tk.h>
+#include "ttkTheme.h"
+#include "ttkWidget.h"
+
+/* Bit fields for OptionSpec mask field:
+ */
+#define STATE_CHANGED (0x100) /* -state option changed */
+#define DEFAULTSTATE_CHANGED (0x200) /* -default option changed */
+
+/*------------------------------------------------------------------------
+ * +++ Base resources for labels, buttons, checkbuttons, etc:
+ */
+typedef struct
+{
+ /*
+ * Text element resources:
+ */
+ Tcl_Obj *textObj;
+ Tcl_Obj *textVariableObj;
+ Tcl_Obj *underlineObj;
+ Tcl_Obj *widthObj;
+
+ Ttk_TraceHandle *textVariableTrace;
+ Ttk_ImageSpec *imageSpec;
+
+ /*
+ * Image element resources:
+ */
+ Tcl_Obj *imageObj;
+
+ /*
+ * Compound label/image resources:
+ */
+ Tcl_Obj *compoundObj;
+ Tcl_Obj *paddingObj;
+
+ /*
+ * Compatibility/legacy options:
+ */
+ Tcl_Obj *stateObj;
+
+} BasePart;
+
+typedef struct
+{
+ WidgetCore core;
+ BasePart base;
+} Base;
+
+static Tk_OptionSpec BaseOptionSpecs[] =
+{
+ {TK_OPTION_STRING, "-text", "text", "Text", "",
+ Tk_Offset(Base,base.textObj), -1,
+ 0,0,GEOMETRY_CHANGED },
+ {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable", "",
+ Tk_Offset(Base,base.textVariableObj), -1,
+ TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
+ {TK_OPTION_INT, "-underline", "underline", "Underline",
+ "-1", Tk_Offset(Base,base.underlineObj), -1,
+ 0,0,0 },
+ /* SB: OPTION_INT, see <<NOTE-NULLOPTIONS>> */
+ {TK_OPTION_STRING, "-width", "width", "Width",
+ NULL, Tk_Offset(Base,base.widthObj), -1,
+ TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
+
+ /*
+ * Image options
+ */
+ {TK_OPTION_STRING, "-image", "image", "Image", NULL/*default*/,
+ Tk_Offset(Base,base.imageObj), -1,
+ TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
+
+ /*
+ * Compound base/image options
+ */
+ {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound",
+ "none", Tk_Offset(Base,base.compoundObj), -1,
+ 0,(ClientData)ttkCompoundStrings,GEOMETRY_CHANGED },
+ {TK_OPTION_STRING, "-padding", "padding", "Pad",
+ NULL, Tk_Offset(Base,base.paddingObj), -1,
+ TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED},
+
+ /*
+ * Compatibility/legacy options
+ */
+ {TK_OPTION_STRING, "-state", "state", "State",
+ "normal", Tk_Offset(Base,base.stateObj), -1,
+ 0,0,STATE_CHANGED },
+
+ WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)
+};
+
+/*
+ * Variable trace procedure for -textvariable option:
+ */
+static void TextVariableChanged(void *clientData, const char *value)
+{
+ Base *basePtr = clientData;
+ Tcl_Obj *newText;
+
+ if (WidgetDestroyed(&basePtr->core)) {
+ return;
+ }
+
+ newText = value ? Tcl_NewStringObj(value, -1) : Tcl_NewStringObj("", 0);
+
+ Tcl_IncrRefCount(newText);
+ Tcl_DecrRefCount(basePtr->base.textObj);
+ basePtr->base.textObj = newText;
+
+ TtkResizeWidget(&basePtr->core);
+}
+
+static void
+BaseInitialize(Tcl_Interp *interp, void *recordPtr)
+{
+ Base *basePtr = recordPtr;
+ basePtr->base.textVariableTrace = 0;
+ basePtr->base.imageSpec = NULL;
+}
+
+static void
+BaseCleanup(void *recordPtr)
+{
+ Base *basePtr = recordPtr;
+ if (basePtr->base.textVariableTrace)
+ Ttk_UntraceVariable(basePtr->base.textVariableTrace);
+ if (basePtr->base.imageSpec)
+ TtkFreeImageSpec(basePtr->base.imageSpec);
+}
+
+static void
+BaseImageChanged(
+ ClientData clientData, int x, int y, int width, int height,
+ int imageWidth, int imageHeight)
+{
+ Base *basePtr = (Base *)clientData;
+ TtkResizeWidget(&basePtr->core);
+}
+
+static int BaseConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
+{
+ Base *basePtr = recordPtr;
+ Tcl_Obj *textVarName = basePtr->base.textVariableObj;
+ Ttk_TraceHandle *vt = 0;
+ Ttk_ImageSpec *imageSpec = NULL;
+
+ if (textVarName != NULL && *Tcl_GetString(textVarName) != '\0') {
+ vt = Ttk_TraceVariable(interp,textVarName,TextVariableChanged,basePtr);
+ if (!vt) return TCL_ERROR;
+ }
+
+ if (basePtr->base.imageObj) {
+ imageSpec = TtkGetImageSpecEx(
+ interp, basePtr->core.tkwin, basePtr->base.imageObj, BaseImageChanged, basePtr);
+ if (!imageSpec) {
+ goto error;
+ }
+ }
+
+ if (TtkCoreConfigure(interp, recordPtr, mask) != TCL_OK) {
+error:
+ if (imageSpec) TtkFreeImageSpec(imageSpec);
+ if (vt) Ttk_UntraceVariable(vt);
+ return TCL_ERROR;
+ }
+
+ if (basePtr->base.textVariableTrace) {
+ Ttk_UntraceVariable(basePtr->base.textVariableTrace);
+ }
+ basePtr->base.textVariableTrace = vt;
+
+ if (basePtr->base.imageSpec) {
+ TtkFreeImageSpec(basePtr->base.imageSpec);
+ }
+ basePtr->base.imageSpec = imageSpec;
+
+ if (mask & STATE_CHANGED) {
+ TtkCheckStateOption(&basePtr->core, basePtr->base.stateObj);
+ }
+
+ return TCL_OK;
+}
+
+static int
+BasePostConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
+{
+ Base *basePtr = recordPtr;
+ int status = TCL_OK;
+
+ if (basePtr->base.textVariableTrace) {
+ status = Ttk_FireTrace(basePtr->base.textVariableTrace);
+ }
+
+ return status;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Label widget.
+ * Just a base widget that adds a few appearance-related options
+ */
+
+typedef struct
+{
+ Tcl_Obj *backgroundObj;
+ Tcl_Obj *foregroundObj;
+ Tcl_Obj *fontObj;
+ Tcl_Obj *borderWidthObj;
+ Tcl_Obj *reliefObj;
+ Tcl_Obj *anchorObj;
+ Tcl_Obj *justifyObj;
+ Tcl_Obj *wrapLengthObj;
+} LabelPart;
+
+typedef struct
+{
+ WidgetCore core;
+ BasePart base;
+ LabelPart label;
+} Label;
+
+static Tk_OptionSpec LabelOptionSpecs[] =
+{
+ {TK_OPTION_BORDER, "-background", "frameColor", "FrameColor",
+ NULL, Tk_Offset(Label,label.backgroundObj), -1,
+ TK_OPTION_NULL_OK,0,0 },
+ {TK_OPTION_COLOR, "-foreground", "textColor", "TextColor",
+ NULL, Tk_Offset(Label,label.foregroundObj), -1,
+ TK_OPTION_NULL_OK,0,0 },
+ {TK_OPTION_FONT, "-font", "font", "Font",
+ NULL, Tk_Offset(Label,label.fontObj), -1,
+ TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ NULL, Tk_Offset(Label,label.borderWidthObj), -1,
+ TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ NULL, Tk_Offset(Label,label.reliefObj), -1,
+ TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
+ {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
+ NULL, Tk_Offset(Label,label.anchorObj), -1,
+ TK_OPTION_NULL_OK, 0, GEOMETRY_CHANGED},
+ {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
+ NULL, Tk_Offset(Label, label.justifyObj), -1,
+ TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
+ {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",
+ NULL, Tk_Offset(Label, label.wrapLengthObj), -1,
+ TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED /*SB: SIZE_CHANGED*/ },
+
+ WIDGET_TAKEFOCUS_FALSE,
+ WIDGET_INHERIT_OPTIONS(BaseOptionSpecs)
+};
+
+static const Ttk_Ensemble LabelCommands[] = {
+ { "configure", TtkWidgetConfigureCommand,0 },
+ { "cget", TtkWidgetCgetCommand,0 },
+ { "instate", TtkWidgetInstateCommand,0 },
+ { "state", TtkWidgetStateCommand,0 },
+ { "identify", TtkWidgetIdentifyCommand,0 },
+ { 0,0,0 }
+};
+
+static WidgetSpec LabelWidgetSpec =
+{
+ "TLabel", /* className */
+ sizeof(Label), /* recordSize */
+ LabelOptionSpecs, /* optionSpecs */
+ LabelCommands, /* subcommands */
+ BaseInitialize, /* initializeProc */
+ BaseCleanup, /* cleanupProc */
+ BaseConfigure, /* configureProc */
+ BasePostConfigure, /* postConfigureProc */
+ TtkWidgetGetLayout, /* getLayoutProc */
+ TtkWidgetSize, /* sizeProc */
+ TtkWidgetDoLayout, /* layoutProc */
+ TtkWidgetDisplay /* displayProc */
+};
+
+TTK_BEGIN_LAYOUT(LabelLayout)
+ TTK_GROUP("Label.border", TTK_FILL_BOTH|TTK_BORDER,
+ TTK_GROUP("Label.padding", TTK_FILL_BOTH|TTK_BORDER,
+ TTK_NODE("Label.label", TTK_FILL_BOTH)))
+TTK_END_LAYOUT
+
+/*------------------------------------------------------------------------
+ * +++ Button widget.
+ * Adds a new subcommand "invoke", and options "-command" and "-default"
+ */
+
+typedef struct
+{
+ Tcl_Obj *commandObj;
+ Tcl_Obj *defaultStateObj;
+} ButtonPart;
+
+typedef struct
+{
+ WidgetCore core;
+ BasePart base;
+ ButtonPart button;
+} Button;
+
+/*
+ * Option specifications:
+ */
+static Tk_OptionSpec ButtonOptionSpecs[] =
+{
+ {TK_OPTION_STRING, "-command", "command", "Command",
+ "", Tk_Offset(Button, button.commandObj), -1, 0,0,0},
+ {TK_OPTION_STRING_TABLE, "-default", "default", "Default",
+ "normal", Tk_Offset(Button, button.defaultStateObj), -1,
+ 0, (ClientData) ttkDefaultStrings, DEFAULTSTATE_CHANGED},
+
+ WIDGET_TAKEFOCUS_TRUE,
+ WIDGET_INHERIT_OPTIONS(BaseOptionSpecs)
+};
+
+static int ButtonConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
+{
+ Button *buttonPtr = recordPtr;
+
+ if (BaseConfigure(interp, recordPtr, mask) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /* Handle "-default" option:
+ */
+ if (mask & DEFAULTSTATE_CHANGED) {
+ int defaultState = TTK_BUTTON_DEFAULT_DISABLED;
+ Ttk_GetButtonDefaultStateFromObj(
+ NULL, buttonPtr->button.defaultStateObj, &defaultState);
+ if (defaultState == TTK_BUTTON_DEFAULT_ACTIVE) {
+ TtkWidgetChangeState(&buttonPtr->core, TTK_STATE_ALTERNATE, 0);
+ } else {
+ TtkWidgetChangeState(&buttonPtr->core, 0, TTK_STATE_ALTERNATE);
+ }
+ }
+ return TCL_OK;
+}
+
+/* $button invoke --
+ * Evaluate the button's -command.
+ */
+static int
+ButtonInvokeCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Button *buttonPtr = recordPtr;
+ if (objc > 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "invoke");
+ return TCL_ERROR;
+ }
+ if (buttonPtr->core.state & TTK_STATE_DISABLED) {
+ return TCL_OK;
+ }
+ return Tcl_EvalObjEx(interp, buttonPtr->button.commandObj, TCL_EVAL_GLOBAL);
+}
+
+static const Ttk_Ensemble ButtonCommands[] = {
+ { "configure", TtkWidgetConfigureCommand,0 },
+ { "cget", TtkWidgetCgetCommand,0 },
+ { "invoke", ButtonInvokeCommand,0 },
+ { "instate", TtkWidgetInstateCommand,0 },
+ { "state", TtkWidgetStateCommand,0 },
+ { "identify", TtkWidgetIdentifyCommand,0 },
+ { 0,0,0 }
+};
+
+static WidgetSpec ButtonWidgetSpec =
+{
+ "TButton", /* className */
+ sizeof(Button), /* recordSize */
+ ButtonOptionSpecs, /* optionSpecs */
+ ButtonCommands, /* subcommands */
+ BaseInitialize, /* initializeProc */
+ BaseCleanup, /* cleanupProc */
+ ButtonConfigure, /* configureProc */
+ BasePostConfigure, /* postConfigureProc */
+ TtkWidgetGetLayout, /* getLayoutProc */
+ TtkWidgetSize, /* sizeProc */
+ TtkWidgetDoLayout, /* layoutProc */
+ TtkWidgetDisplay /* displayProc */
+};
+
+TTK_BEGIN_LAYOUT(ButtonLayout)
+ TTK_GROUP("Button.border", TTK_FILL_BOTH|TTK_BORDER,
+ TTK_GROUP("Button.focus", TTK_FILL_BOTH,
+ TTK_GROUP("Button.padding", TTK_FILL_BOTH,
+ TTK_NODE("Button.label", TTK_FILL_BOTH))))
+TTK_END_LAYOUT
+
+/*------------------------------------------------------------------------
+ * +++ Checkbutton widget.
+ */
+typedef struct
+{
+ Tcl_Obj *variableObj;
+ Tcl_Obj *onValueObj;
+ Tcl_Obj *offValueObj;
+ Tcl_Obj *commandObj;
+
+ Ttk_TraceHandle *variableTrace;
+
+} CheckbuttonPart;
+
+typedef struct
+{
+ WidgetCore core;
+ BasePart base;
+ CheckbuttonPart checkbutton;
+} Checkbutton;
+
+/*
+ * Option specifications:
+ */
+static Tk_OptionSpec CheckbuttonOptionSpecs[] =
+{
+ {TK_OPTION_STRING, "-variable", "variable", "Variable",
+ NULL, Tk_Offset(Checkbutton, checkbutton.variableObj), -1,
+ TK_OPTION_NULL_OK,0,0},
+ {TK_OPTION_STRING, "-onvalue", "onValue", "OnValue",
+ "1", Tk_Offset(Checkbutton, checkbutton.onValueObj), -1,
+ 0,0,0},
+ {TK_OPTION_STRING, "-offvalue", "offValue", "OffValue",
+ "0", Tk_Offset(Checkbutton, checkbutton.offValueObj), -1,
+ 0,0,0},
+ {TK_OPTION_STRING, "-command", "command", "Command",
+ "", Tk_Offset(Checkbutton, checkbutton.commandObj), -1,
+ 0,0,0},
+
+ WIDGET_TAKEFOCUS_TRUE,
+ WIDGET_INHERIT_OPTIONS(BaseOptionSpecs)
+};
+
+/*
+ * Variable trace procedure for checkbutton -variable option
+ */
+static void CheckbuttonVariableChanged(void *clientData, const char *value)
+{
+ Checkbutton *checkPtr = clientData;
+
+ if (WidgetDestroyed(&checkPtr->core)) {
+ return;
+ }
+
+ if (!value) {
+ TtkWidgetChangeState(&checkPtr->core, TTK_STATE_ALTERNATE, 0);
+ return;
+ }
+ /* else */
+ TtkWidgetChangeState(&checkPtr->core, 0, TTK_STATE_ALTERNATE);
+ if (!strcmp(value, Tcl_GetString(checkPtr->checkbutton.onValueObj))) {
+ TtkWidgetChangeState(&checkPtr->core, TTK_STATE_SELECTED, 0);
+ } else {
+ TtkWidgetChangeState(&checkPtr->core, 0, TTK_STATE_SELECTED);
+ }
+}
+
+static void
+CheckbuttonInitialize(Tcl_Interp *interp, void *recordPtr)
+{
+ Checkbutton *checkPtr = recordPtr;
+ Tcl_Obj *variableObj;
+
+ /* default -variable is the widget name:
+ */
+ variableObj = Tcl_NewStringObj(Tk_PathName(checkPtr->core.tkwin), -1);
+ Tcl_IncrRefCount(variableObj);
+ checkPtr->checkbutton.variableObj = variableObj;
+ BaseInitialize(interp, recordPtr);
+}
+
+static void
+CheckbuttonCleanup(void *recordPtr)
+{
+ Checkbutton *checkPtr = recordPtr;
+ Ttk_UntraceVariable(checkPtr->checkbutton.variableTrace);
+ checkPtr->checkbutton.variableTrace = 0;
+ BaseCleanup(recordPtr);
+}
+
+static int
+CheckbuttonConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
+{
+ Checkbutton *checkPtr = recordPtr;
+ Tcl_Obj *varName = checkPtr->checkbutton.variableObj;
+ Ttk_TraceHandle *vt = NULL;
+
+ if (varName != NULL && *Tcl_GetString(varName) != '\0') {
+ vt = Ttk_TraceVariable(interp, varName,
+ CheckbuttonVariableChanged, checkPtr);
+ if (!vt) {
+ return TCL_ERROR;
+ }
+ }
+
+ if (BaseConfigure(interp, recordPtr, mask) != TCL_OK){
+ Ttk_UntraceVariable(vt);
+ return TCL_ERROR;
+ }
+
+ if (checkPtr->checkbutton.variableTrace) {
+ Ttk_UntraceVariable(checkPtr->checkbutton.variableTrace);
+ }
+ checkPtr->checkbutton.variableTrace = vt;
+
+ return TCL_OK;
+}
+
+static int
+CheckbuttonPostConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
+{
+ Checkbutton *checkPtr = recordPtr;
+ int status = TCL_OK;
+
+ if (checkPtr->checkbutton.variableTrace)
+ status = Ttk_FireTrace(checkPtr->checkbutton.variableTrace);
+ if (status == TCL_OK && !WidgetDestroyed(&checkPtr->core))
+ status = BasePostConfigure(interp, recordPtr, mask);
+ return status;
+}
+
+/*
+ * Checkbutton 'invoke' subcommand:
+ * Toggles the checkbutton state.
+ */
+static int
+CheckbuttonInvokeCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Checkbutton *checkPtr = recordPtr;
+ WidgetCore *corePtr = &checkPtr->core;
+ Tcl_Obj *newValue;
+
+ if (objc > 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "invoke");
+ return TCL_ERROR;
+ }
+ if (corePtr->state & TTK_STATE_DISABLED)
+ return TCL_OK;
+
+ /*
+ * Toggle the selected state.
+ */
+ if (corePtr->state & TTK_STATE_SELECTED)
+ newValue = checkPtr->checkbutton.offValueObj;
+ else
+ newValue = checkPtr->checkbutton.onValueObj;
+
+ if (checkPtr->checkbutton.variableObj == NULL ||
+ *Tcl_GetString(checkPtr->checkbutton.variableObj) == '\0')
+ CheckbuttonVariableChanged(checkPtr, Tcl_GetString(newValue));
+ else if (Tcl_ObjSetVar2(interp,
+ checkPtr->checkbutton.variableObj, NULL, newValue,
+ TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
+ == NULL)
+ return TCL_ERROR;
+
+ if (WidgetDestroyed(corePtr))
+ return TCL_ERROR;
+
+ return Tcl_EvalObjEx(interp,
+ checkPtr->checkbutton.commandObj, TCL_EVAL_GLOBAL);
+}
+
+static const Ttk_Ensemble CheckbuttonCommands[] = {
+ { "configure", TtkWidgetConfigureCommand,0 },
+ { "cget", TtkWidgetCgetCommand,0 },
+ { "invoke", CheckbuttonInvokeCommand,0 },
+ { "instate", TtkWidgetInstateCommand,0 },
+ { "state", TtkWidgetStateCommand,0 },
+ { "identify", TtkWidgetIdentifyCommand,0 },
+ /* MISSING: select, deselect, toggle */
+ { 0,0,0 }
+};
+
+static WidgetSpec CheckbuttonWidgetSpec =
+{
+ "TCheckbutton", /* className */
+ sizeof(Checkbutton), /* recordSize */
+ CheckbuttonOptionSpecs, /* optionSpecs */
+ CheckbuttonCommands, /* subcommands */
+ CheckbuttonInitialize, /* initializeProc */
+ CheckbuttonCleanup, /* cleanupProc */
+ CheckbuttonConfigure, /* configureProc */
+ CheckbuttonPostConfigure, /* postConfigureProc */
+ TtkWidgetGetLayout, /* getLayoutProc */
+ TtkWidgetSize, /* sizeProc */
+ TtkWidgetDoLayout, /* layoutProc */
+ TtkWidgetDisplay /* displayProc */
+};
+
+TTK_BEGIN_LAYOUT(CheckbuttonLayout)
+ TTK_GROUP("Checkbutton.padding", TTK_FILL_BOTH,
+ TTK_NODE("Checkbutton.indicator", TTK_PACK_LEFT)
+ TTK_GROUP("Checkbutton.focus", TTK_PACK_LEFT | TTK_STICK_W,
+ TTK_NODE("Checkbutton.label", TTK_FILL_BOTH)))
+TTK_END_LAYOUT
+
+/*------------------------------------------------------------------------
+ * +++ Radiobutton widget.
+ */
+
+typedef struct
+{
+ Tcl_Obj *variableObj;
+ Tcl_Obj *valueObj;
+ Tcl_Obj *commandObj;
+
+ Ttk_TraceHandle *variableTrace;
+
+} RadiobuttonPart;
+
+typedef struct
+{
+ WidgetCore core;
+ BasePart base;
+ RadiobuttonPart radiobutton;
+} Radiobutton;
+
+/*
+ * Option specifications:
+ */
+static Tk_OptionSpec RadiobuttonOptionSpecs[] =
+{
+ {TK_OPTION_STRING, "-variable", "variable", "Variable",
+ "::selectedButton", Tk_Offset(Radiobutton, radiobutton.variableObj),-1,
+ 0,0,0},
+ {TK_OPTION_STRING, "-value", "Value", "Value",
+ "1", Tk_Offset(Radiobutton, radiobutton.valueObj), -1,
+ 0,0,0},
+ {TK_OPTION_STRING, "-command", "command", "Command",
+ "", Tk_Offset(Radiobutton, radiobutton.commandObj), -1,
+ 0,0,0},
+
+ WIDGET_TAKEFOCUS_TRUE,
+ WIDGET_INHERIT_OPTIONS(BaseOptionSpecs)
+};
+
+/*
+ * Variable trace procedure for radiobuttons.
+ */
+static void
+RadiobuttonVariableChanged(void *clientData, const char *value)
+{
+ Radiobutton *radioPtr = clientData;
+
+ if (WidgetDestroyed(&radioPtr->core)) {
+ return;
+ }
+
+ if (!value) {
+ TtkWidgetChangeState(&radioPtr->core, TTK_STATE_ALTERNATE, 0);
+ return;
+ }
+ /* else */
+ TtkWidgetChangeState(&radioPtr->core, 0, TTK_STATE_ALTERNATE);
+ if (!strcmp(value, Tcl_GetString(radioPtr->radiobutton.valueObj))) {
+ TtkWidgetChangeState(&radioPtr->core, TTK_STATE_SELECTED, 0);
+ } else {
+ TtkWidgetChangeState(&radioPtr->core, 0, TTK_STATE_SELECTED);
+ }
+}
+
+static void
+RadiobuttonCleanup(void *recordPtr)
+{
+ Radiobutton *radioPtr = recordPtr;
+ Ttk_UntraceVariable(radioPtr->radiobutton.variableTrace);
+ radioPtr->radiobutton.variableTrace = 0;
+ BaseCleanup(recordPtr);
+}
+
+static int
+RadiobuttonConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
+{
+ Radiobutton *radioPtr = recordPtr;
+ Ttk_TraceHandle *vt = Ttk_TraceVariable(
+ interp, radioPtr->radiobutton.variableObj,
+ RadiobuttonVariableChanged, radioPtr);
+
+ if (!vt) {
+ return TCL_ERROR;
+ }
+
+ if (BaseConfigure(interp, recordPtr, mask) != TCL_OK) {
+ Ttk_UntraceVariable(vt);
+ return TCL_ERROR;
+ }
+
+ Ttk_UntraceVariable(radioPtr->radiobutton.variableTrace);
+ radioPtr->radiobutton.variableTrace = vt;
+
+ return TCL_OK;
+}
+
+static int
+RadiobuttonPostConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
+{
+ Radiobutton *radioPtr = recordPtr;
+ int status = TCL_OK;
+
+ if (radioPtr->radiobutton.variableTrace)
+ status = Ttk_FireTrace(radioPtr->radiobutton.variableTrace);
+ if (status == TCL_OK && !WidgetDestroyed(&radioPtr->core))
+ status = BasePostConfigure(interp, recordPtr, mask);
+ return status;
+}
+
+/*
+ * Radiobutton 'invoke' subcommand:
+ * Sets the radiobutton -variable to the -value, evaluates the -command.
+ */
+static int
+RadiobuttonInvokeCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Radiobutton *radioPtr = recordPtr;
+ WidgetCore *corePtr = &radioPtr->core;
+
+ if (objc > 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "invoke");
+ return TCL_ERROR;
+ }
+ if (corePtr->state & TTK_STATE_DISABLED)
+ return TCL_OK;
+
+ if (Tcl_ObjSetVar2(interp,
+ radioPtr->radiobutton.variableObj, NULL,
+ radioPtr->radiobutton.valueObj,
+ TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
+ == NULL)
+ return TCL_ERROR;
+
+ if (WidgetDestroyed(corePtr))
+ return TCL_ERROR;
+
+ return Tcl_EvalObjEx(interp,
+ radioPtr->radiobutton.commandObj, TCL_EVAL_GLOBAL);
+}
+
+static const Ttk_Ensemble RadiobuttonCommands[] = {
+ { "configure", TtkWidgetConfigureCommand,0 },
+ { "cget", TtkWidgetCgetCommand,0 },
+ { "invoke", RadiobuttonInvokeCommand,0 },
+ { "instate", TtkWidgetInstateCommand,0 },
+ { "state", TtkWidgetStateCommand,0 },
+ { "identify", TtkWidgetIdentifyCommand,0 },
+ /* MISSING: select, deselect */
+ { 0,0,0 }
+};
+
+static WidgetSpec RadiobuttonWidgetSpec =
+{
+ "TRadiobutton", /* className */
+ sizeof(Radiobutton), /* recordSize */
+ RadiobuttonOptionSpecs, /* optionSpecs */
+ RadiobuttonCommands, /* subcommands */
+ BaseInitialize, /* initializeProc */
+ RadiobuttonCleanup, /* cleanupProc */
+ RadiobuttonConfigure, /* configureProc */
+ RadiobuttonPostConfigure, /* postConfigureProc */
+ TtkWidgetGetLayout, /* getLayoutProc */
+ TtkWidgetSize, /* sizeProc */
+ TtkWidgetDoLayout, /* layoutProc */
+ TtkWidgetDisplay /* displayProc */
+};
+
+TTK_BEGIN_LAYOUT(RadiobuttonLayout)
+ TTK_GROUP("Radiobutton.padding", TTK_FILL_BOTH,
+ TTK_NODE("Radiobutton.indicator", TTK_PACK_LEFT)
+ TTK_GROUP("Radiobutton.focus", TTK_PACK_LEFT,
+ TTK_NODE("Radiobutton.label", TTK_FILL_BOTH)))
+TTK_END_LAYOUT
+
+/*------------------------------------------------------------------------
+ * +++ Menubutton widget.
+ */
+
+typedef struct
+{
+ Tcl_Obj *menuObj;
+ Tcl_Obj *directionObj;
+} MenubuttonPart;
+
+typedef struct
+{
+ WidgetCore core;
+ BasePart base;
+ MenubuttonPart menubutton;
+} Menubutton;
+
+/*
+ * Option specifications:
+ */
+static const char *const directionStrings[] = {
+ "above", "below", "left", "right", "flush", NULL
+};
+static Tk_OptionSpec MenubuttonOptionSpecs[] =
+{
+ {TK_OPTION_STRING, "-menu", "menu", "Menu",
+ "", Tk_Offset(Menubutton, menubutton.menuObj), -1, 0,0,0},
+ {TK_OPTION_STRING_TABLE, "-direction", "direction", "Direction",
+ "below", Tk_Offset(Menubutton, menubutton.directionObj), -1,
+ 0,(ClientData)directionStrings,GEOMETRY_CHANGED},
+
+ WIDGET_TAKEFOCUS_TRUE,
+ WIDGET_INHERIT_OPTIONS(BaseOptionSpecs)
+};
+
+static const Ttk_Ensemble MenubuttonCommands[] = {
+ { "configure", TtkWidgetConfigureCommand,0 },
+ { "cget", TtkWidgetCgetCommand,0 },
+ { "instate", TtkWidgetInstateCommand,0 },
+ { "state", TtkWidgetStateCommand,0 },
+ { "identify", TtkWidgetIdentifyCommand,0 },
+ { 0,0,0 }
+};
+
+static WidgetSpec MenubuttonWidgetSpec =
+{
+ "TMenubutton", /* className */
+ sizeof(Menubutton), /* recordSize */
+ MenubuttonOptionSpecs, /* optionSpecs */
+ MenubuttonCommands, /* subcommands */
+ BaseInitialize, /* initializeProc */
+ BaseCleanup, /* cleanupProc */
+ BaseConfigure, /* configureProc */
+ BasePostConfigure, /* postConfigureProc */
+ TtkWidgetGetLayout, /* getLayoutProc */
+ TtkWidgetSize, /* sizeProc */
+ TtkWidgetDoLayout, /* layoutProc */
+ TtkWidgetDisplay /* displayProc */
+};
+
+TTK_BEGIN_LAYOUT(MenubuttonLayout)
+ TTK_GROUP("Menubutton.border", TTK_FILL_BOTH,
+ TTK_GROUP("Menubutton.focus", TTK_FILL_BOTH,
+ TTK_NODE("Menubutton.indicator", TTK_PACK_RIGHT)
+ TTK_GROUP("Menubutton.padding", TTK_PACK_LEFT|TTK_EXPAND|TTK_FILL_X,
+ TTK_NODE("Menubutton.label", TTK_PACK_LEFT))))
+TTK_END_LAYOUT
+
+/*------------------------------------------------------------------------
+ * +++ Initialization.
+ */
+
+MODULE_SCOPE
+void TtkButton_Init(Tcl_Interp *interp)
+{
+ Ttk_Theme theme = Ttk_GetDefaultTheme(interp);
+
+ Ttk_RegisterLayout(theme, "TLabel", LabelLayout);
+ Ttk_RegisterLayout(theme, "TButton", ButtonLayout);
+ Ttk_RegisterLayout(theme, "TCheckbutton", CheckbuttonLayout);
+ Ttk_RegisterLayout(theme, "TRadiobutton", RadiobuttonLayout);
+ Ttk_RegisterLayout(theme, "TMenubutton", MenubuttonLayout);
+
+ RegisterWidget(interp, "ttk::label", &LabelWidgetSpec);
+ RegisterWidget(interp, "ttk::button", &ButtonWidgetSpec);
+ RegisterWidget(interp, "ttk::checkbutton", &CheckbuttonWidgetSpec);
+ RegisterWidget(interp, "ttk::radiobutton", &RadiobuttonWidgetSpec);
+ RegisterWidget(interp, "ttk::menubutton", &MenubuttonWidgetSpec);
+}
diff --git a/tk8.6/generic/ttk/ttkCache.c b/tk8.6/generic/ttk/ttkCache.c
new file mode 100644
index 0000000..0ae2372
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkCache.c
@@ -0,0 +1,350 @@
+/*
+ * Theme engine resource cache.
+ *
+ * Copyright (c) 2004, Joe English
+ *
+ * The problem:
+ *
+ * Tk maintains reference counts for fonts, colors, and images,
+ * and deallocates them when the reference count goes to zero.
+ * With the theme engine, resources are allocated right before
+ * drawing an element and released immediately after.
+ * This causes a severe performance penalty, and on PseudoColor
+ * visuals it causes colormap cycling as colormap entries are
+ * released and reused.
+ *
+ * Solution: Acquire fonts, colors, and objects from a
+ * resource cache instead of directly from Tk; the cache
+ * holds a semipermanent reference to the resource to keep
+ * it from being deallocated.
+ *
+ * The plumbing and control flow here is quite contorted;
+ * it would be better to address this problem in the core instead.
+ *
+ * @@@ BUGS/TODO: Need distinct caches for each combination
+ * of display, visual, and colormap.
+ *
+ * @@@ Colormap flashing on PseudoColor visuals is still possible,
+ * but this will be a transient effect.
+ */
+
+#include <stdio.h> /* for sprintf */
+#include <tk.h>
+#include "ttkTheme.h"
+
+struct Ttk_ResourceCache_ {
+ Tcl_Interp *interp; /* Interpreter for error reporting */
+ Tk_Window tkwin; /* Cache window. */
+ Tcl_HashTable fontTable; /* Entries: Tcl_Obj* holding FontObjs */
+ Tcl_HashTable colorTable; /* Entries: Tcl_Obj* holding ColorObjs */
+ Tcl_HashTable borderTable; /* Entries: Tcl_Obj* holding BorderObjs */
+ Tcl_HashTable imageTable; /* Entries: Tk_Images */
+
+ Tcl_HashTable namedColors; /* Entries: RGB values as Tcl_StringObjs */
+};
+
+/*
+ * Ttk_CreateResourceCache --
+ * Initialize a new resource cache.
+ */
+Ttk_ResourceCache Ttk_CreateResourceCache(Tcl_Interp *interp)
+{
+ Ttk_ResourceCache cache = ckalloc(sizeof(*cache));
+
+ cache->tkwin = NULL; /* initialized later */
+ cache->interp = interp;
+ Tcl_InitHashTable(&cache->fontTable, TCL_STRING_KEYS);
+ Tcl_InitHashTable(&cache->colorTable, TCL_STRING_KEYS);
+ Tcl_InitHashTable(&cache->borderTable, TCL_STRING_KEYS);
+ Tcl_InitHashTable(&cache->imageTable, TCL_STRING_KEYS);
+ Tcl_InitHashTable(&cache->namedColors, TCL_STRING_KEYS);
+
+ return cache;
+}
+
+/*
+ * Ttk_ClearCache --
+ * Release references to all cached resources.
+ */
+static void Ttk_ClearCache(Ttk_ResourceCache cache)
+{
+ Tcl_HashSearch search;
+ Tcl_HashEntry *entryPtr;
+
+ /*
+ * Free fonts:
+ */
+ entryPtr = Tcl_FirstHashEntry(&cache->fontTable, &search);
+ while (entryPtr != NULL) {
+ Tcl_Obj *fontObj = Tcl_GetHashValue(entryPtr);
+ if (fontObj) {
+ Tk_FreeFontFromObj(cache->tkwin, fontObj);
+ Tcl_DecrRefCount(fontObj);
+ }
+ entryPtr = Tcl_NextHashEntry(&search);
+ }
+ Tcl_DeleteHashTable(&cache->fontTable);
+ Tcl_InitHashTable(&cache->fontTable, TCL_STRING_KEYS);
+
+ /*
+ * Free colors:
+ */
+ entryPtr = Tcl_FirstHashEntry(&cache->colorTable, &search);
+ while (entryPtr != NULL) {
+ Tcl_Obj *colorObj = Tcl_GetHashValue(entryPtr);
+ if (colorObj) {
+ Tk_FreeColorFromObj(cache->tkwin, colorObj);
+ Tcl_DecrRefCount(colorObj);
+ }
+ entryPtr = Tcl_NextHashEntry(&search);
+ }
+ Tcl_DeleteHashTable(&cache->colorTable);
+ Tcl_InitHashTable(&cache->colorTable, TCL_STRING_KEYS);
+
+ /*
+ * Free borders:
+ */
+ entryPtr = Tcl_FirstHashEntry(&cache->borderTable, &search);
+ while (entryPtr != NULL) {
+ Tcl_Obj *borderObj = Tcl_GetHashValue(entryPtr);
+ if (borderObj) {
+ Tk_Free3DBorderFromObj(cache->tkwin, borderObj);
+ Tcl_DecrRefCount(borderObj);
+ }
+ entryPtr = Tcl_NextHashEntry(&search);
+ }
+ Tcl_DeleteHashTable(&cache->borderTable);
+ Tcl_InitHashTable(&cache->borderTable, TCL_STRING_KEYS);
+
+ /*
+ * Free images:
+ */
+ entryPtr = Tcl_FirstHashEntry(&cache->imageTable, &search);
+ while (entryPtr != NULL) {
+ Tk_Image image = Tcl_GetHashValue(entryPtr);
+ if (image) {
+ Tk_FreeImage(image);
+ }
+ entryPtr = Tcl_NextHashEntry(&search);
+ }
+ Tcl_DeleteHashTable(&cache->imageTable);
+ Tcl_InitHashTable(&cache->imageTable, TCL_STRING_KEYS);
+
+ return;
+}
+
+/*
+ * Ttk_FreeResourceCache --
+ * Release references to all cached resources, delete the cache.
+ */
+
+void Ttk_FreeResourceCache(Ttk_ResourceCache cache)
+{
+ Tcl_HashEntry *entryPtr;
+ Tcl_HashSearch search;
+
+ Ttk_ClearCache(cache);
+
+ Tcl_DeleteHashTable(&cache->colorTable);
+ Tcl_DeleteHashTable(&cache->fontTable);
+ Tcl_DeleteHashTable(&cache->imageTable);
+
+ /*
+ * Free named colors:
+ */
+ entryPtr = Tcl_FirstHashEntry(&cache->namedColors, &search);
+ while (entryPtr != NULL) {
+ Tcl_Obj *colorNameObj = Tcl_GetHashValue(entryPtr);
+ Tcl_DecrRefCount(colorNameObj);
+ entryPtr = Tcl_NextHashEntry(&search);
+ }
+ Tcl_DeleteHashTable(&cache->namedColors);
+
+ ckfree(cache);
+}
+
+/*
+ * CacheWinEventHandler --
+ * Detect when the cache window is destroyed, clear cache.
+ */
+static void CacheWinEventHandler(ClientData clientData, XEvent *eventPtr)
+{
+ Ttk_ResourceCache cache = clientData;
+
+ if (eventPtr->type != DestroyNotify) {
+ return;
+ }
+ Tk_DeleteEventHandler(cache->tkwin, StructureNotifyMask,
+ CacheWinEventHandler, clientData);
+ Ttk_ClearCache(cache);
+ cache->tkwin = NULL;
+}
+
+/*
+ * InitCacheWindow --
+ * Specify the cache window if not already set.
+ * @@@ SHOULD: use separate caches for each combination
+ * @@@ of display, visual, and colormap.
+ */
+static void InitCacheWindow(Ttk_ResourceCache cache, Tk_Window tkwin)
+{
+ if (cache->tkwin == NULL) {
+ cache->tkwin = tkwin;
+ Tk_CreateEventHandler(tkwin, StructureNotifyMask,
+ CacheWinEventHandler, cache);
+ }
+}
+
+/*
+ * Ttk_RegisterNamedColor --
+ * Specify an RGB triplet as a named color.
+ * Overrides any previous named color specification.
+ */
+void Ttk_RegisterNamedColor(
+ Ttk_ResourceCache cache,
+ const char *colorName,
+ XColor *colorPtr)
+{
+ int newEntry;
+ Tcl_HashEntry *entryPtr;
+ char nameBuf[14];
+ Tcl_Obj *colorNameObj;
+
+ sprintf(nameBuf, "#%04X%04X%04X",
+ colorPtr->red, colorPtr->green, colorPtr->blue);
+ colorNameObj = Tcl_NewStringObj(nameBuf, -1);
+ Tcl_IncrRefCount(colorNameObj);
+
+ entryPtr = Tcl_CreateHashEntry(&cache->namedColors, colorName, &newEntry);
+ if (!newEntry) {
+ Tcl_Obj *oldColor = Tcl_GetHashValue(entryPtr);
+ Tcl_DecrRefCount(oldColor);
+ }
+
+ Tcl_SetHashValue(entryPtr, colorNameObj);
+}
+
+/*
+ * CheckNamedColor(objPtr) --
+ * If objPtr is a registered color name, return a Tcl_Obj *
+ * containing the registered color value specification.
+ * Otherwise, return the input argument.
+ */
+static Tcl_Obj *CheckNamedColor(Ttk_ResourceCache cache, Tcl_Obj *objPtr)
+{
+ Tcl_HashEntry *entryPtr =
+ Tcl_FindHashEntry(&cache->namedColors, Tcl_GetString(objPtr));
+ if (entryPtr) { /* Use named color instead */
+ objPtr = Tcl_GetHashValue(entryPtr);
+ }
+ return objPtr;
+}
+
+/*
+ * Template for allocation routines:
+ */
+typedef void *(*Allocator)(Tcl_Interp *, Tk_Window, Tcl_Obj *);
+
+static Tcl_Obj *Ttk_Use(
+ Tcl_Interp *interp,
+ Tcl_HashTable *table,
+ Allocator allocate,
+ Tk_Window tkwin,
+ Tcl_Obj *objPtr)
+{
+ int newEntry;
+ Tcl_HashEntry *entryPtr =
+ Tcl_CreateHashEntry(table,Tcl_GetString(objPtr),&newEntry);
+ Tcl_Obj *cacheObj;
+
+ if (!newEntry) {
+ return Tcl_GetHashValue(entryPtr);
+ }
+
+ cacheObj = Tcl_DuplicateObj(objPtr);
+ Tcl_IncrRefCount(cacheObj);
+
+ if (allocate(interp, tkwin, cacheObj)) {
+ Tcl_SetHashValue(entryPtr, cacheObj);
+ return cacheObj;
+ } else {
+ Tcl_DecrRefCount(cacheObj);
+ Tcl_SetHashValue(entryPtr, NULL);
+ Tcl_BackgroundException(interp, TCL_ERROR);
+ return NULL;
+ }
+}
+
+/*
+ * Ttk_UseFont --
+ * Acquire a font from the cache.
+ */
+Tcl_Obj *Ttk_UseFont(Ttk_ResourceCache cache, Tk_Window tkwin, Tcl_Obj *objPtr)
+{
+ InitCacheWindow(cache, tkwin);
+ return Ttk_Use(cache->interp,
+ &cache->fontTable,(Allocator)Tk_AllocFontFromObj, tkwin, objPtr);
+}
+
+/*
+ * Ttk_UseColor --
+ * Acquire a color from the cache.
+ */
+Tcl_Obj *Ttk_UseColor(Ttk_ResourceCache cache, Tk_Window tkwin, Tcl_Obj *objPtr)
+{
+ objPtr = CheckNamedColor(cache, objPtr);
+ InitCacheWindow(cache, tkwin);
+ return Ttk_Use(cache->interp,
+ &cache->colorTable,(Allocator)Tk_AllocColorFromObj, tkwin, objPtr);
+}
+
+/*
+ * Ttk_UseBorder --
+ * Acquire a Tk_3DBorder from the cache.
+ */
+Tcl_Obj *Ttk_UseBorder(
+ Ttk_ResourceCache cache, Tk_Window tkwin, Tcl_Obj *objPtr)
+{
+ objPtr = CheckNamedColor(cache, objPtr);
+ InitCacheWindow(cache, tkwin);
+ return Ttk_Use(cache->interp,
+ &cache->borderTable,(Allocator)Tk_Alloc3DBorderFromObj, tkwin, objPtr);
+}
+
+/* NullImageChanged --
+ * Tk_ImageChangedProc for Ttk_UseImage
+ */
+
+static void NullImageChanged(ClientData clientData,
+ int x, int y, int width, int height, int imageWidth, int imageHeight)
+{ /* No-op */ }
+
+/*
+ * Ttk_UseImage --
+ * Acquire a Tk_Image from the cache.
+ */
+Tk_Image Ttk_UseImage(Ttk_ResourceCache cache, Tk_Window tkwin, Tcl_Obj *objPtr)
+{
+ const char *imageName = Tcl_GetString(objPtr);
+ int newEntry;
+ Tcl_HashEntry *entryPtr =
+ Tcl_CreateHashEntry(&cache->imageTable,imageName,&newEntry);
+ Tk_Image image;
+
+ InitCacheWindow(cache, tkwin);
+
+ if (!newEntry) {
+ return Tcl_GetHashValue(entryPtr);
+ }
+
+ image = Tk_GetImage(cache->interp, tkwin, imageName, NullImageChanged,0);
+ Tcl_SetHashValue(entryPtr, image);
+
+ if (!image) {
+ Tcl_BackgroundException(cache->interp, TCL_ERROR);
+ }
+
+ return image;
+}
+
+/*EOF*/
diff --git a/tk8.6/generic/ttk/ttkClamTheme.c b/tk8.6/generic/ttk/ttkClamTheme.c
new file mode 100644
index 0000000..15ebcb7
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkClamTheme.c
@@ -0,0 +1,971 @@
+/*
+ * Copyright (C) 2004 Joe English
+ *
+ * "clam" theme; inspired by the XFCE family of Gnome themes.
+ */
+
+#include <tk.h>
+#include "ttkTheme.h"
+
+/*
+ * Under windows, the Tk-provided XDrawLine and XDrawArc have an
+ * off-by-one error in the end point. This is especially apparent with this
+ * theme. Defining this macro as true handles this case.
+ */
+#if defined(_WIN32) && !defined(WIN32_XDRAWLINE_HACK)
+# define WIN32_XDRAWLINE_HACK 1
+#else
+# define WIN32_XDRAWLINE_HACK 0
+#endif
+
+#define STR(x) StR(x)
+#define StR(x) #x
+
+#define SCROLLBAR_THICKNESS 14
+
+#define FRAME_COLOR "#dcdad5"
+#define LIGHT_COLOR "#ffffff"
+#define DARK_COLOR "#cfcdc8"
+#define DARKER_COLOR "#bab5ab"
+#define DARKEST_COLOR "#9e9a91"
+
+/*------------------------------------------------------------------------
+ * +++ Utilities.
+ */
+
+static GC Ttk_GCForColor(Tk_Window tkwin, Tcl_Obj* colorObj, Drawable d)
+{
+ GC gc = Tk_GCForColor(Tk_GetColorFromObj(tkwin, colorObj), d);
+
+#ifdef MAC_OSX_TK
+ /*
+ * Workaround for Tk bug under Aqua where the default line width is 0.
+ */
+ Display *display = Tk_Display(tkwin);
+ unsigned long mask = 0ul;
+ XGCValues gcValues;
+
+ gcValues.line_width = 1;
+ mask = GCLineWidth;
+
+ XChangeGC(display, gc, mask, &gcValues);
+#endif
+
+ return gc;
+}
+
+static void DrawSmoothBorder(
+ Tk_Window tkwin, Drawable d, Ttk_Box b,
+ Tcl_Obj *outerColorObj, Tcl_Obj *upperColorObj, Tcl_Obj *lowerColorObj)
+{
+ Display *display = Tk_Display(tkwin);
+ int x1 = b.x, x2 = b.x + b.width - 1;
+ int y1 = b.y, y2 = b.y + b.height - 1;
+ const int w = WIN32_XDRAWLINE_HACK;
+ GC gc;
+
+ if ( outerColorObj
+ && (gc=Ttk_GCForColor(tkwin,outerColorObj,d)))
+ {
+ XDrawLine(display,d,gc, x1+1,y1, x2-1+w,y1); /* N */
+ XDrawLine(display,d,gc, x1+1,y2, x2-1+w,y2); /* S */
+ XDrawLine(display,d,gc, x1,y1+1, x1,y2-1+w); /* E */
+ XDrawLine(display,d,gc, x2,y1+1, x2,y2-1+w); /* W */
+ }
+
+ if ( upperColorObj
+ && (gc=Ttk_GCForColor(tkwin,upperColorObj,d)))
+ {
+ XDrawLine(display,d,gc, x1+1,y1+1, x2-1+w,y1+1); /* N */
+ XDrawLine(display,d,gc, x1+1,y1+1, x1+1,y2-1); /* E */
+ }
+
+ if ( lowerColorObj
+ && (gc=Ttk_GCForColor(tkwin,lowerColorObj,d)))
+ {
+ XDrawLine(display,d,gc, x2-1,y2-1, x1+1-w,y2-1); /* S */
+ XDrawLine(display,d,gc, x2-1,y2-1, x2-1,y1+1-w); /* W */
+ }
+}
+
+static GC BackgroundGC(Tk_Window tkwin, Tcl_Obj *backgroundObj)
+{
+ Tk_3DBorder bd = Tk_Get3DBorderFromObj(tkwin, backgroundObj);
+ return Tk_3DBorderGC(tkwin, bd, TK_3D_FLAT_GC);
+}
+
+/*------------------------------------------------------------------------
+ * +++ Border element.
+ */
+
+typedef struct {
+ Tcl_Obj *borderColorObj;
+ Tcl_Obj *lightColorObj;
+ Tcl_Obj *darkColorObj;
+ Tcl_Obj *reliefObj;
+ Tcl_Obj *borderWidthObj; /* See <<NOTE-BORDERWIDTH>> */
+} BorderElement;
+
+static Ttk_ElementOptionSpec BorderElementOptions[] = {
+ { "-bordercolor", TK_OPTION_COLOR,
+ Tk_Offset(BorderElement,borderColorObj), DARKEST_COLOR },
+ { "-lightcolor", TK_OPTION_COLOR,
+ Tk_Offset(BorderElement,lightColorObj), LIGHT_COLOR },
+ { "-darkcolor", TK_OPTION_COLOR,
+ Tk_Offset(BorderElement,darkColorObj), DARK_COLOR },
+ { "-relief", TK_OPTION_RELIEF,
+ Tk_Offset(BorderElement,reliefObj), "flat" },
+ { "-borderwidth", TK_OPTION_PIXELS,
+ Tk_Offset(BorderElement,borderWidthObj), "2" },
+ { NULL, 0, 0, NULL }
+};
+
+/*
+ * <<NOTE-BORDERWIDTH>>: -borderwidth is only partially supported:
+ * in this theme, borders are always exactly 2 pixels thick.
+ * With -borderwidth 0, border is not drawn at all;
+ * otherwise a 2-pixel border is used. For -borderwidth > 2,
+ * the excess is used as padding.
+ */
+
+static void BorderElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ BorderElement *border = (BorderElement*)elementRecord;
+ int borderWidth = 2;
+ Tk_GetPixelsFromObj(NULL, tkwin, border->borderWidthObj, &borderWidth);
+ if (borderWidth == 1) ++borderWidth;
+ *paddingPtr = Ttk_UniformPadding((short)borderWidth);
+}
+
+static void BorderElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned state)
+{
+ BorderElement *border = elementRecord;
+ int relief = TK_RELIEF_FLAT;
+ int borderWidth = 2;
+ Tcl_Obj *outer = 0, *upper = 0, *lower = 0;
+
+ Tk_GetReliefFromObj(NULL, border->reliefObj, &relief);
+ Tk_GetPixelsFromObj(NULL, tkwin, border->borderWidthObj, &borderWidth);
+
+ if (borderWidth == 0) return;
+
+ switch (relief) {
+ case TK_RELIEF_GROOVE :
+ case TK_RELIEF_RIDGE :
+ case TK_RELIEF_RAISED :
+ outer = border->borderColorObj;
+ upper = border->lightColorObj;
+ lower = border->darkColorObj;
+ break;
+ case TK_RELIEF_SUNKEN :
+ outer = border->borderColorObj;
+ upper = border->darkColorObj;
+ lower = border->lightColorObj;
+ break;
+ case TK_RELIEF_FLAT :
+ outer = upper = lower = 0;
+ break;
+ case TK_RELIEF_SOLID :
+ outer = upper = lower = border->borderColorObj;
+ break;
+ }
+
+ DrawSmoothBorder(tkwin, d, b, outer, upper, lower);
+}
+
+static Ttk_ElementSpec BorderElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(BorderElement),
+ BorderElementOptions,
+ BorderElementSize,
+ BorderElementDraw
+};
+
+/*------------------------------------------------------------------------
+ * +++ Field element.
+ */
+
+typedef struct {
+ Tcl_Obj *borderColorObj;
+ Tcl_Obj *lightColorObj;
+ Tcl_Obj *darkColorObj;
+ Tcl_Obj *backgroundObj;
+} FieldElement;
+
+static Ttk_ElementOptionSpec FieldElementOptions[] = {
+ { "-bordercolor", TK_OPTION_COLOR,
+ Tk_Offset(FieldElement,borderColorObj), DARKEST_COLOR },
+ { "-lightcolor", TK_OPTION_COLOR,
+ Tk_Offset(FieldElement,lightColorObj), LIGHT_COLOR },
+ { "-darkcolor", TK_OPTION_COLOR,
+ Tk_Offset(FieldElement,darkColorObj), DARK_COLOR },
+ { "-fieldbackground", TK_OPTION_BORDER,
+ Tk_Offset(FieldElement,backgroundObj), "white" },
+ { NULL, 0, 0, NULL }
+};
+
+static void FieldElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ *paddingPtr = Ttk_UniformPadding(2);
+}
+
+static void FieldElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned state)
+{
+ FieldElement *field = elementRecord;
+ Tk_3DBorder bg = Tk_Get3DBorderFromObj(tkwin, field->backgroundObj);
+ Ttk_Box f = Ttk_PadBox(b, Ttk_UniformPadding(2));
+ Tcl_Obj *outer = field->borderColorObj,
+ *inner = field->lightColorObj;
+
+ DrawSmoothBorder(tkwin, d, b, outer, inner, inner);
+ Tk_Fill3DRectangle(
+ tkwin, d, bg, f.x, f.y, f.width, f.height, 0, TK_RELIEF_SUNKEN);
+}
+
+static Ttk_ElementSpec FieldElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(FieldElement),
+ FieldElementOptions,
+ FieldElementSize,
+ FieldElementDraw
+};
+
+/*
+ * Modified field element for comboboxes:
+ * Right edge is expanded to overlap the dropdown button.
+ */
+static void ComboboxFieldElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned state)
+{
+ FieldElement *field = elementRecord;
+ GC gc = Ttk_GCForColor(tkwin,field->borderColorObj,d);
+
+ ++b.width;
+ FieldElementDraw(clientData, elementRecord, tkwin, d, b, state);
+
+ XDrawLine(Tk_Display(tkwin), d, gc,
+ b.x + b.width - 1, b.y,
+ b.x + b.width - 1, b.y + b.height - 1 + WIN32_XDRAWLINE_HACK);
+}
+
+static Ttk_ElementSpec ComboboxFieldElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(FieldElement),
+ FieldElementOptions,
+ FieldElementSize,
+ ComboboxFieldElementDraw
+};
+
+/*------------------------------------------------------------------------
+ * +++ Indicator elements for check and radio buttons.
+ */
+
+typedef struct {
+ Tcl_Obj *sizeObj;
+ Tcl_Obj *marginObj;
+ Tcl_Obj *backgroundObj;
+ Tcl_Obj *foregroundObj;
+ Tcl_Obj *upperColorObj;
+ Tcl_Obj *lowerColorObj;
+} IndicatorElement;
+
+static Ttk_ElementOptionSpec IndicatorElementOptions[] = {
+ { "-indicatorsize", TK_OPTION_PIXELS,
+ Tk_Offset(IndicatorElement,sizeObj), "10" },
+ { "-indicatormargin", TK_OPTION_STRING,
+ Tk_Offset(IndicatorElement,marginObj), "1" },
+ { "-indicatorbackground", TK_OPTION_COLOR,
+ Tk_Offset(IndicatorElement,backgroundObj), "white" },
+ { "-indicatorforeground", TK_OPTION_COLOR,
+ Tk_Offset(IndicatorElement,foregroundObj), "black" },
+ { "-upperbordercolor", TK_OPTION_COLOR,
+ Tk_Offset(IndicatorElement,upperColorObj), DARKEST_COLOR },
+ { "-lowerbordercolor", TK_OPTION_COLOR,
+ Tk_Offset(IndicatorElement,lowerColorObj), DARK_COLOR },
+ { NULL, 0, 0, NULL }
+};
+
+static void IndicatorElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ IndicatorElement *indicator = elementRecord;
+ Ttk_Padding margins;
+ int size = 10;
+ Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &margins);
+ Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &size);
+ *widthPtr = size + Ttk_PaddingWidth(margins);
+ *heightPtr = size + Ttk_PaddingHeight(margins);
+}
+
+static void RadioIndicatorElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned state)
+{
+ IndicatorElement *indicator = elementRecord;
+ GC gcb=Ttk_GCForColor(tkwin,indicator->backgroundObj,d);
+ GC gcf=Ttk_GCForColor(tkwin,indicator->foregroundObj,d);
+ GC gcu=Ttk_GCForColor(tkwin,indicator->upperColorObj,d);
+ GC gcl=Ttk_GCForColor(tkwin,indicator->lowerColorObj,d);
+ Ttk_Padding padding;
+
+ Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &padding);
+ b = Ttk_PadBox(b, padding);
+
+ XFillArc(Tk_Display(tkwin),d,gcb, b.x,b.y,b.width,b.height, 0,360*64);
+ XDrawArc(Tk_Display(tkwin),d,gcl, b.x,b.y,b.width,b.height, 225*64,180*64);
+ XDrawArc(Tk_Display(tkwin),d,gcu, b.x,b.y,b.width,b.height, 45*64,180*64);
+
+ if (state & TTK_STATE_SELECTED) {
+ b = Ttk_PadBox(b,Ttk_UniformPadding(3));
+ XFillArc(Tk_Display(tkwin),d,gcf, b.x,b.y,b.width,b.height, 0,360*64);
+ XDrawArc(Tk_Display(tkwin),d,gcf, b.x,b.y,b.width,b.height, 0,360*64);
+#if WIN32_XDRAWLINE_HACK
+ XDrawArc(Tk_Display(tkwin),d,gcf, b.x,b.y,b.width,b.height, 300*64,360*64);
+#endif
+ }
+}
+
+static void CheckIndicatorElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned state)
+{
+ Display *display = Tk_Display(tkwin);
+ IndicatorElement *indicator = elementRecord;
+ GC gcb=Ttk_GCForColor(tkwin,indicator->backgroundObj,d);
+ GC gcf=Ttk_GCForColor(tkwin,indicator->foregroundObj,d);
+ GC gcu=Ttk_GCForColor(tkwin,indicator->upperColorObj,d);
+ GC gcl=Ttk_GCForColor(tkwin,indicator->lowerColorObj,d);
+ Ttk_Padding padding;
+ const int w = WIN32_XDRAWLINE_HACK;
+
+ Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &padding);
+ b = Ttk_PadBox(b, padding);
+
+ XFillRectangle(display,d,gcb, b.x,b.y,b.width,b.height);
+ XDrawLine(display,d,gcl,b.x,b.y+b.height,b.x+b.width+w,b.y+b.height);/*S*/
+ XDrawLine(display,d,gcl,b.x+b.width,b.y,b.x+b.width,b.y+b.height+w); /*E*/
+ XDrawLine(display,d,gcu,b.x,b.y, b.x,b.y+b.height+w); /*W*/
+ XDrawLine(display,d,gcu,b.x,b.y, b.x+b.width+w,b.y); /*N*/
+
+ if (state & TTK_STATE_SELECTED) {
+ int p,q,r,s;
+
+ b = Ttk_PadBox(b,Ttk_UniformPadding(2));
+ p = b.x, q = b.y, r = b.x+b.width, s = b.y+b.height;
+
+ r+=w, s+=w;
+ XDrawLine(display, d, gcf, p, q, r, s);
+ XDrawLine(display, d, gcf, p+1, q, r, s-1);
+ XDrawLine(display, d, gcf, p, q+1, r-1, s);
+
+ s-=w, q-=w;
+ XDrawLine(display, d, gcf, p, s, r, q);
+ XDrawLine(display, d, gcf, p+1, s, r, q+1);
+ XDrawLine(display, d, gcf, p, s-1, r-1, q);
+ }
+}
+
+static Ttk_ElementSpec RadioIndicatorElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(IndicatorElement),
+ IndicatorElementOptions,
+ IndicatorElementSize,
+ RadioIndicatorElementDraw
+};
+
+static Ttk_ElementSpec CheckIndicatorElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(IndicatorElement),
+ IndicatorElementOptions,
+ IndicatorElementSize,
+ CheckIndicatorElementDraw
+};
+
+#define MENUBUTTON_ARROW_SIZE 5
+
+typedef struct {
+ Tcl_Obj *sizeObj;
+ Tcl_Obj *colorObj;
+ Tcl_Obj *paddingObj;
+} MenuIndicatorElement;
+
+static Ttk_ElementOptionSpec MenuIndicatorElementOptions[] =
+{
+ { "-arrowsize", TK_OPTION_PIXELS,
+ Tk_Offset(MenuIndicatorElement,sizeObj),
+ STR(MENUBUTTON_ARROW_SIZE)},
+ { "-arrowcolor",TK_OPTION_COLOR,
+ Tk_Offset(MenuIndicatorElement,colorObj),
+ "black" },
+ { "-arrowpadding",TK_OPTION_STRING,
+ Tk_Offset(MenuIndicatorElement,paddingObj),
+ "3" },
+ { NULL, 0, 0, NULL }
+};
+
+static void MenuIndicatorElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ MenuIndicatorElement *indicator = elementRecord;
+ Ttk_Padding margins;
+ int size = MENUBUTTON_ARROW_SIZE;
+ Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &size);
+ Ttk_GetPaddingFromObj(NULL, tkwin, indicator->paddingObj, &margins);
+ TtkArrowSize(size, ARROW_DOWN, widthPtr, heightPtr);
+ *widthPtr += Ttk_PaddingWidth(margins);
+ *heightPtr += Ttk_PaddingHeight(margins);
+}
+
+static void MenuIndicatorElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ MenuIndicatorElement *indicator = elementRecord;
+ XColor *arrowColor = Tk_GetColorFromObj(tkwin, indicator->colorObj);
+ GC gc = Tk_GCForColor(arrowColor, d);
+ int size = MENUBUTTON_ARROW_SIZE;
+ int width, height;
+
+ Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &size);
+
+ TtkArrowSize(size, ARROW_DOWN, &width, &height);
+ b = Ttk_StickBox(b, width, height, 0);
+ TtkFillArrow(Tk_Display(tkwin), d, gc, b, ARROW_DOWN);
+}
+
+static Ttk_ElementSpec MenuIndicatorElementSpec =
+{
+ TK_STYLE_VERSION_2,
+ sizeof(MenuIndicatorElement),
+ MenuIndicatorElementOptions,
+ MenuIndicatorElementSize,
+ MenuIndicatorElementDraw
+};
+
+/*------------------------------------------------------------------------
+ * +++ Grips.
+ *
+ * TODO: factor this with ThumbElementDraw
+ */
+
+static Ttk_Orient GripClientData[] = {
+ TTK_ORIENT_HORIZONTAL, TTK_ORIENT_VERTICAL
+};
+
+typedef struct {
+ Tcl_Obj *lightColorObj;
+ Tcl_Obj *borderColorObj;
+ Tcl_Obj *gripCountObj;
+} GripElement;
+
+static Ttk_ElementOptionSpec GripElementOptions[] = {
+ { "-lightcolor", TK_OPTION_COLOR,
+ Tk_Offset(GripElement,lightColorObj), LIGHT_COLOR },
+ { "-bordercolor", TK_OPTION_COLOR,
+ Tk_Offset(GripElement,borderColorObj), DARKEST_COLOR },
+ { "-gripcount", TK_OPTION_INT,
+ Tk_Offset(GripElement,gripCountObj), "5" },
+ { NULL, 0, 0, NULL }
+};
+
+static void GripElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ int horizontal = *((Ttk_Orient*)clientData) == TTK_ORIENT_HORIZONTAL;
+ GripElement *grip = elementRecord;
+ int gripCount = 0;
+
+ Tcl_GetIntFromObj(NULL, grip->gripCountObj, &gripCount);
+ if (horizontal) {
+ *widthPtr = 2*gripCount;
+ } else {
+ *heightPtr = 2*gripCount;
+ }
+}
+
+static void GripElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned state)
+{
+ const int w = WIN32_XDRAWLINE_HACK;
+ int horizontal = *((Ttk_Orient*)clientData) == TTK_ORIENT_HORIZONTAL;
+ GripElement *grip = elementRecord;
+ GC lightGC = Ttk_GCForColor(tkwin,grip->lightColorObj,d);
+ GC darkGC = Ttk_GCForColor(tkwin,grip->borderColorObj,d);
+ int gripPad = 1, gripCount = 0;
+ int i;
+
+ Tcl_GetIntFromObj(NULL, grip->gripCountObj, &gripCount);
+
+ if (horizontal) {
+ int x = b.x + b.width / 2 - gripCount;
+ int y1 = b.y + gripPad, y2 = b.y + b.height - gripPad - 1 + w;
+ for (i=0; i<gripCount; ++i) {
+ XDrawLine(Tk_Display(tkwin), d, darkGC, x,y1, x,y2); ++x;
+ XDrawLine(Tk_Display(tkwin), d, lightGC, x,y1, x,y2); ++x;
+ }
+ } else {
+ int y = b.y + b.height / 2 - gripCount;
+ int x1 = b.x + gripPad, x2 = b.x + b.width - gripPad - 1 + w;
+ for (i=0; i<gripCount; ++i) {
+ XDrawLine(Tk_Display(tkwin), d, darkGC, x1,y, x2,y); ++y;
+ XDrawLine(Tk_Display(tkwin), d, lightGC, x1,y, x2,y); ++y;
+ }
+ }
+}
+
+static Ttk_ElementSpec GripElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(GripElement),
+ GripElementOptions,
+ GripElementSize,
+ GripElementDraw
+};
+
+/*------------------------------------------------------------------------
+ * +++ Scrollbar elements: trough, arrows, thumb.
+ *
+ * Notice that the trough element has 0 internal padding;
+ * that way the thumb and arrow borders overlap the trough.
+ */
+
+typedef struct { /* Common element record for scrollbar elements */
+ Tcl_Obj *orientObj;
+ Tcl_Obj *backgroundObj;
+ Tcl_Obj *borderColorObj;
+ Tcl_Obj *troughColorObj;
+ Tcl_Obj *lightColorObj;
+ Tcl_Obj *darkColorObj;
+ Tcl_Obj *arrowColorObj;
+ Tcl_Obj *arrowSizeObj;
+ Tcl_Obj *gripCountObj;
+ Tcl_Obj *sliderlengthObj;
+} ScrollbarElement;
+
+static Ttk_ElementOptionSpec ScrollbarElementOptions[] = {
+ { "-orient", TK_OPTION_ANY,
+ Tk_Offset(ScrollbarElement, orientObj), "horizontal" },
+ { "-background", TK_OPTION_BORDER,
+ Tk_Offset(ScrollbarElement,backgroundObj), FRAME_COLOR },
+ { "-bordercolor", TK_OPTION_COLOR,
+ Tk_Offset(ScrollbarElement,borderColorObj), DARKEST_COLOR },
+ { "-troughcolor", TK_OPTION_COLOR,
+ Tk_Offset(ScrollbarElement,troughColorObj), DARKER_COLOR },
+ { "-lightcolor", TK_OPTION_COLOR,
+ Tk_Offset(ScrollbarElement,lightColorObj), LIGHT_COLOR },
+ { "-darkcolor", TK_OPTION_COLOR,
+ Tk_Offset(ScrollbarElement,darkColorObj), DARK_COLOR },
+ { "-arrowcolor", TK_OPTION_COLOR,
+ Tk_Offset(ScrollbarElement,arrowColorObj), "#000000" },
+ { "-arrowsize", TK_OPTION_PIXELS,
+ Tk_Offset(ScrollbarElement,arrowSizeObj), STR(SCROLLBAR_THICKNESS) },
+ { "-gripcount", TK_OPTION_INT,
+ Tk_Offset(ScrollbarElement,gripCountObj), "5" },
+ { "-sliderlength", TK_OPTION_INT,
+ Tk_Offset(ScrollbarElement,sliderlengthObj), "30" },
+ { NULL, 0, 0, NULL }
+};
+
+static void TroughElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned state)
+{
+ ScrollbarElement *sb = elementRecord;
+ GC gcb = Ttk_GCForColor(tkwin,sb->borderColorObj,d);
+ GC gct = Ttk_GCForColor(tkwin,sb->troughColorObj,d);
+ XFillRectangle(Tk_Display(tkwin), d, gct, b.x, b.y, b.width-1, b.height-1);
+ XDrawRectangle(Tk_Display(tkwin), d, gcb, b.x, b.y, b.width-1, b.height-1);
+}
+
+static Ttk_ElementSpec TroughElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(ScrollbarElement),
+ ScrollbarElementOptions,
+ TtkNullElementSize,
+ TroughElementDraw
+};
+
+static void ThumbElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ ScrollbarElement *sb = elementRecord;
+ int size = SCROLLBAR_THICKNESS;
+ Tcl_GetIntFromObj(NULL, sb->arrowSizeObj, &size);
+ *widthPtr = *heightPtr = size;
+}
+
+static void ThumbElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned state)
+{
+ ScrollbarElement *sb = elementRecord;
+ int gripCount = 0, orient = TTK_ORIENT_HORIZONTAL;
+ GC lightGC, darkGC;
+ int x1, y1, x2, y2, dx, dy, i;
+ const int w = WIN32_XDRAWLINE_HACK;
+
+ DrawSmoothBorder(tkwin, d, b,
+ sb->borderColorObj, sb->lightColorObj, sb->darkColorObj);
+ XFillRectangle(
+ Tk_Display(tkwin), d, BackgroundGC(tkwin, sb->backgroundObj),
+ b.x+2, b.y+2, b.width-4, b.height-4);
+
+ /*
+ * Draw grip:
+ */
+ Ttk_GetOrientFromObj(NULL, sb->orientObj, &orient);
+ Tcl_GetIntFromObj(NULL, sb->gripCountObj, &gripCount);
+ lightGC = Ttk_GCForColor(tkwin,sb->lightColorObj,d);
+ darkGC = Ttk_GCForColor(tkwin,sb->borderColorObj,d);
+
+ if (orient == TTK_ORIENT_HORIZONTAL) {
+ dx = 1; dy = 0;
+ x1 = x2 = b.x + b.width / 2 - gripCount;
+ y1 = b.y + 2;
+ y2 = b.y + b.height - 3 + w;
+ } else {
+ dx = 0; dy = 1;
+ y1 = y2 = b.y + b.height / 2 - gripCount;
+ x1 = b.x + 2;
+ x2 = b.x + b.width - 3 + w;
+ }
+
+ for (i=0; i<gripCount; ++i) {
+ XDrawLine(Tk_Display(tkwin), d, darkGC, x1,y1, x2,y2);
+ x1 += dx; x2 += dx; y1 += dy; y2 += dy;
+ XDrawLine(Tk_Display(tkwin), d, lightGC, x1,y1, x2,y2);
+ x1 += dx; x2 += dx; y1 += dy; y2 += dy;
+ }
+}
+
+static Ttk_ElementSpec ThumbElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(ScrollbarElement),
+ ScrollbarElementOptions,
+ ThumbElementSize,
+ ThumbElementDraw
+};
+
+/*------------------------------------------------------------------------
+ * +++ Slider element.
+ */
+static void SliderElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ ScrollbarElement *sb = elementRecord;
+ int length, thickness, orient;
+
+ length = thickness = SCROLLBAR_THICKNESS;
+ Ttk_GetOrientFromObj(NULL, sb->orientObj, &orient);
+ Tcl_GetIntFromObj(NULL, sb->arrowSizeObj, &thickness);
+ Tk_GetPixelsFromObj(NULL, tkwin, sb->sliderlengthObj, &length);
+ if (orient == TTK_ORIENT_VERTICAL) {
+ *heightPtr = length;
+ *widthPtr = thickness;
+ } else {
+ *heightPtr = thickness;
+ *widthPtr = length;
+ }
+
+}
+
+static Ttk_ElementSpec SliderElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(ScrollbarElement),
+ ScrollbarElementOptions,
+ SliderElementSize,
+ ThumbElementDraw
+};
+
+/*------------------------------------------------------------------------
+ * +++ Progress bar element
+ */
+static void PbarElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ SliderElementSize(clientData, elementRecord, tkwin,
+ widthPtr, heightPtr, paddingPtr);
+ *paddingPtr = Ttk_UniformPadding(2);
+ *widthPtr += 4;
+ *heightPtr += 4;
+}
+
+static void PbarElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned state)
+{
+ ScrollbarElement *sb = elementRecord;
+
+ b = Ttk_PadBox(b, Ttk_UniformPadding(2));
+ if (b.width > 4 && b.height > 4) {
+ DrawSmoothBorder(tkwin, d, b,
+ sb->borderColorObj, sb->lightColorObj, sb->darkColorObj);
+ XFillRectangle(Tk_Display(tkwin), d,
+ BackgroundGC(tkwin, sb->backgroundObj),
+ b.x+2, b.y+2, b.width-4, b.height-4);
+ }
+}
+
+static Ttk_ElementSpec PbarElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(ScrollbarElement),
+ ScrollbarElementOptions,
+ PbarElementSize,
+ PbarElementDraw
+};
+
+
+/*------------------------------------------------------------------------
+ * +++ Scrollbar arrows.
+ */
+static int ArrowElements[] = { ARROW_UP, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT };
+
+static void ArrowElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ ScrollbarElement *sb = elementRecord;
+ int size = SCROLLBAR_THICKNESS;
+ Tcl_GetIntFromObj(NULL, sb->arrowSizeObj, &size);
+ *widthPtr = *heightPtr = size;
+}
+
+static void ArrowElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned state)
+{
+ ArrowDirection dir = *(ArrowDirection*)clientData;
+ ScrollbarElement *sb = elementRecord;
+ GC gc = Ttk_GCForColor(tkwin,sb->arrowColorObj, d);
+ int h, cx, cy;
+
+ DrawSmoothBorder(tkwin, d, b,
+ sb->borderColorObj, sb->lightColorObj, sb->darkColorObj);
+
+ XFillRectangle(
+ Tk_Display(tkwin), d, BackgroundGC(tkwin, sb->backgroundObj),
+ b.x+2, b.y+2, b.width-4, b.height-4);
+
+ b = Ttk_PadBox(b, Ttk_UniformPadding(3));
+ h = b.width < b.height ? b.width : b.height;
+ TtkArrowSize(h/2, dir, &cx, &cy);
+ b = Ttk_AnchorBox(b, cx, cy, TK_ANCHOR_CENTER);
+
+ TtkFillArrow(Tk_Display(tkwin), d, gc, b, dir);
+}
+
+static Ttk_ElementSpec ArrowElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(ScrollbarElement),
+ ScrollbarElementOptions,
+ ArrowElementSize,
+ ArrowElementDraw
+};
+
+
+/*------------------------------------------------------------------------
+ * +++ Notebook elements.
+ *
+ * Note: Tabs, except for the rightmost, overlap the neighbor to
+ * their right by one pixel.
+ */
+
+typedef struct {
+ Tcl_Obj *backgroundObj;
+ Tcl_Obj *borderColorObj;
+ Tcl_Obj *lightColorObj;
+ Tcl_Obj *darkColorObj;
+} NotebookElement;
+
+static Ttk_ElementOptionSpec NotebookElementOptions[] = {
+ { "-background", TK_OPTION_BORDER,
+ Tk_Offset(NotebookElement,backgroundObj), FRAME_COLOR },
+ { "-bordercolor", TK_OPTION_COLOR,
+ Tk_Offset(NotebookElement,borderColorObj), DARKEST_COLOR },
+ { "-lightcolor", TK_OPTION_COLOR,
+ Tk_Offset(NotebookElement,lightColorObj), LIGHT_COLOR },
+ { "-darkcolor", TK_OPTION_COLOR,
+ Tk_Offset(NotebookElement,darkColorObj), DARK_COLOR },
+ { NULL, 0, 0, NULL }
+};
+
+static void TabElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ int borderWidth = 2;
+ paddingPtr->top = paddingPtr->left = paddingPtr->right = borderWidth;
+ paddingPtr->bottom = 0;
+}
+
+static void TabElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ NotebookElement *tab = elementRecord;
+ Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, tab->backgroundObj);
+ Display *display = Tk_Display(tkwin);
+ int borderWidth = 2, dh = 0;
+ int x1,y1,x2,y2;
+ GC gc;
+ const int w = WIN32_XDRAWLINE_HACK;
+
+ if (state & TTK_STATE_SELECTED) {
+ dh = borderWidth;
+ }
+
+ if (state & TTK_STATE_USER2) { /* Rightmost tab */
+ --b.width;
+ }
+
+ Tk_Fill3DRectangle(tkwin, d, border,
+ b.x+2, b.y+2, b.width-1, b.height-2+dh, borderWidth, TK_RELIEF_FLAT);
+
+ x1 = b.x, x2 = b.x + b.width;
+ y1 = b.y, y2 = b.y + b.height;
+
+
+ gc=Ttk_GCForColor(tkwin,tab->borderColorObj,d);
+ XDrawLine(display,d,gc, x1,y1+1, x1,y2+w);
+ XDrawLine(display,d,gc, x2,y1+1, x2,y2+w);
+ XDrawLine(display,d,gc, x1+1,y1, x2-1+w,y1);
+
+ gc=Ttk_GCForColor(tkwin,tab->lightColorObj,d);
+ XDrawLine(display,d,gc, x1+1,y1+1, x1+1,y2-1+dh+w);
+ XDrawLine(display,d,gc, x1+1,y1+1, x2-1+w,y1+1);
+}
+
+static Ttk_ElementSpec TabElementSpec =
+{
+ TK_STYLE_VERSION_2,
+ sizeof(NotebookElement),
+ NotebookElementOptions,
+ TabElementSize,
+ TabElementDraw
+};
+
+static void ClientElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ int borderWidth = 2;
+ *paddingPtr = Ttk_UniformPadding((short)borderWidth);
+}
+
+static void ClientElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ NotebookElement *ce = elementRecord;
+ Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, ce->backgroundObj);
+ int borderWidth = 2;
+
+ Tk_Fill3DRectangle(tkwin, d, border,
+ b.x, b.y, b.width, b.height, borderWidth,TK_RELIEF_FLAT);
+ DrawSmoothBorder(tkwin, d, b,
+ ce->borderColorObj, ce->lightColorObj, ce->darkColorObj);
+}
+
+static Ttk_ElementSpec ClientElementSpec =
+{
+ TK_STYLE_VERSION_2,
+ sizeof(NotebookElement),
+ NotebookElementOptions,
+ ClientElementSize,
+ ClientElementDraw
+};
+
+/*------------------------------------------------------------------------
+ * +++ Modified widget layouts.
+ */
+
+TTK_BEGIN_LAYOUT_TABLE(LayoutTable)
+
+TTK_LAYOUT("TCombobox",
+ TTK_NODE("Combobox.downarrow", TTK_PACK_RIGHT|TTK_FILL_Y)
+ TTK_GROUP("Combobox.field", TTK_PACK_LEFT|TTK_FILL_BOTH|TTK_EXPAND,
+ TTK_GROUP("Combobox.padding", TTK_FILL_BOTH,
+ TTK_NODE("Combobox.textarea", TTK_FILL_BOTH))))
+
+TTK_LAYOUT("Horizontal.Sash",
+ TTK_GROUP("Sash.hsash", TTK_FILL_BOTH,
+ TTK_NODE("Sash.hgrip", TTK_FILL_BOTH)))
+
+TTK_LAYOUT("Vertical.Sash",
+ TTK_GROUP("Sash.vsash", TTK_FILL_BOTH,
+ TTK_NODE("Sash.vgrip", TTK_FILL_BOTH)))
+
+TTK_END_LAYOUT_TABLE
+
+/*------------------------------------------------------------------------
+ * +++ Initialization.
+ */
+
+MODULE_SCOPE int
+TtkClamTheme_Init(Tcl_Interp *interp)
+{
+ Ttk_Theme theme = Ttk_CreateTheme(interp, "clam", 0);
+
+ if (!theme) {
+ return TCL_ERROR;
+ }
+
+ Ttk_RegisterElement(interp,
+ theme, "border", &BorderElementSpec, NULL);
+ Ttk_RegisterElement(interp,
+ theme, "field", &FieldElementSpec, NULL);
+ Ttk_RegisterElement(interp,
+ theme, "Combobox.field", &ComboboxFieldElementSpec, NULL);
+ Ttk_RegisterElement(interp,
+ theme, "trough", &TroughElementSpec, NULL);
+ Ttk_RegisterElement(interp,
+ theme, "thumb", &ThumbElementSpec, NULL);
+ Ttk_RegisterElement(interp,
+ theme, "uparrow", &ArrowElementSpec, &ArrowElements[0]);
+ Ttk_RegisterElement(interp,
+ theme, "downarrow", &ArrowElementSpec, &ArrowElements[1]);
+ Ttk_RegisterElement(interp,
+ theme, "leftarrow", &ArrowElementSpec, &ArrowElements[2]);
+ Ttk_RegisterElement(interp,
+ theme, "rightarrow", &ArrowElementSpec, &ArrowElements[3]);
+
+ Ttk_RegisterElement(interp,
+ theme, "Radiobutton.indicator", &RadioIndicatorElementSpec, NULL);
+ Ttk_RegisterElement(interp,
+ theme, "Checkbutton.indicator", &CheckIndicatorElementSpec, NULL);
+ Ttk_RegisterElement(interp,
+ theme, "Menubutton.indicator", &MenuIndicatorElementSpec, NULL);
+
+ Ttk_RegisterElement(interp, theme, "tab", &TabElementSpec, NULL);
+ Ttk_RegisterElement(interp, theme, "client", &ClientElementSpec, NULL);
+
+ Ttk_RegisterElement(interp, theme, "slider", &SliderElementSpec, NULL);
+ Ttk_RegisterElement(interp, theme, "bar", &PbarElementSpec, NULL);
+ Ttk_RegisterElement(interp, theme, "pbar", &PbarElementSpec, NULL);
+
+ Ttk_RegisterElement(interp, theme, "hgrip",
+ &GripElementSpec, &GripClientData[0]);
+ Ttk_RegisterElement(interp, theme, "vgrip",
+ &GripElementSpec, &GripClientData[1]);
+
+ Ttk_RegisterLayouts(theme, LayoutTable);
+
+ Tcl_PkgProvide(interp, "ttk::theme::clam", TTK_VERSION);
+
+ return TCL_OK;
+}
diff --git a/tk8.6/generic/ttk/ttkClassicTheme.c b/tk8.6/generic/ttk/ttkClassicTheme.c
new file mode 100644
index 0000000..e0886f2
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkClassicTheme.c
@@ -0,0 +1,511 @@
+/*
+ * Copyright (c) 2004, Joe English
+ *
+ * "classic" theme; implements the classic Motif-like Tk look.
+ *
+ */
+
+#include "tkInt.h"
+#include "ttkTheme.h"
+
+#define DEFAULT_BORDERWIDTH "2"
+#define DEFAULT_ARROW_SIZE "15"
+
+/*----------------------------------------------------------------------
+ * +++ Highlight element implementation.
+ * Draw a solid highlight border to indicate focus.
+ */
+
+typedef struct {
+ Tcl_Obj *highlightColorObj;
+ Tcl_Obj *highlightThicknessObj;
+} HighlightElement;
+
+static Ttk_ElementOptionSpec HighlightElementOptions[] = {
+ { "-highlightcolor",TK_OPTION_COLOR,
+ Tk_Offset(HighlightElement,highlightColorObj), DEFAULT_BACKGROUND },
+ { "-highlightthickness",TK_OPTION_PIXELS,
+ Tk_Offset(HighlightElement,highlightThicknessObj), "0" },
+ { NULL, 0, 0, NULL }
+};
+
+static void HighlightElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ HighlightElement *hl = elementRecord;
+ int highlightThickness = 0;
+
+ Tcl_GetIntFromObj(NULL,hl->highlightThicknessObj,&highlightThickness);
+ *paddingPtr = Ttk_UniformPadding((short)highlightThickness);
+}
+
+static void HighlightElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ HighlightElement *hl = elementRecord;
+ int highlightThickness = 0;
+ XColor *highlightColor = Tk_GetColorFromObj(tkwin, hl->highlightColorObj);
+
+ Tcl_GetIntFromObj(NULL,hl->highlightThicknessObj,&highlightThickness);
+ if (highlightColor && highlightThickness > 0) {
+ GC gc = Tk_GCForColor(highlightColor, d);
+ Tk_DrawFocusHighlight(tkwin, gc, highlightThickness, d);
+ }
+}
+
+static Ttk_ElementSpec HighlightElementSpec =
+{
+ TK_STYLE_VERSION_2,
+ sizeof(HighlightElement),
+ HighlightElementOptions,
+ HighlightElementSize,
+ HighlightElementDraw
+};
+
+/*------------------------------------------------------------------------
+ * +++ Button Border element:
+ *
+ * The Motif-style button border on X11 consists of (from outside-in):
+ *
+ * + focus indicator (controlled by -highlightcolor and -highlightthickness),
+ * + default ring (if -default active; blank if -default normal)
+ * + shaded border (controlled by -background, -borderwidth, and -relief)
+ */
+
+typedef struct {
+ Tcl_Obj *borderObj;
+ Tcl_Obj *borderWidthObj;
+ Tcl_Obj *reliefObj;
+ Tcl_Obj *defaultStateObj;
+} ButtonBorderElement;
+
+static Ttk_ElementOptionSpec ButtonBorderElementOptions[] =
+{
+ { "-background", TK_OPTION_BORDER,
+ Tk_Offset(ButtonBorderElement,borderObj), DEFAULT_BACKGROUND },
+ { "-borderwidth", TK_OPTION_PIXELS,
+ Tk_Offset(ButtonBorderElement,borderWidthObj), DEFAULT_BORDERWIDTH },
+ { "-relief", TK_OPTION_RELIEF,
+ Tk_Offset(ButtonBorderElement,reliefObj), "flat" },
+ { "-default", TK_OPTION_ANY,
+ Tk_Offset(ButtonBorderElement,defaultStateObj), "disabled" },
+ { NULL, 0, 0, NULL }
+};
+
+static void ButtonBorderElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ ButtonBorderElement *bd = elementRecord;
+ int defaultState = TTK_BUTTON_DEFAULT_DISABLED;
+ int borderWidth = 0;
+
+ Tcl_GetIntFromObj(NULL, bd->borderWidthObj, &borderWidth);
+ Ttk_GetButtonDefaultStateFromObj(NULL, bd->defaultStateObj, &defaultState);
+
+ if (defaultState != TTK_BUTTON_DEFAULT_DISABLED) {
+ borderWidth += 5;
+ }
+ *paddingPtr = Ttk_UniformPadding((short)borderWidth);
+}
+
+/*
+ * (@@@ Note: ButtonBorderElement still still still buggy:
+ * padding for default ring is drawn in the wrong color
+ * when the button is active.)
+ */
+static void ButtonBorderElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ ButtonBorderElement *bd = elementRecord;
+ Tk_3DBorder border = NULL;
+ int borderWidth = 1, relief = TK_RELIEF_FLAT;
+ int defaultState = TTK_BUTTON_DEFAULT_DISABLED;
+ int inset = 0;
+
+ /*
+ * Get option values.
+ */
+ border = Tk_Get3DBorderFromObj(tkwin, bd->borderObj);
+ Tcl_GetIntFromObj(NULL, bd->borderWidthObj, &borderWidth);
+ Tk_GetReliefFromObj(NULL, bd->reliefObj, &relief);
+ Ttk_GetButtonDefaultStateFromObj(NULL, bd->defaultStateObj, &defaultState);
+
+ /*
+ * Default ring:
+ */
+ switch (defaultState)
+ {
+ case TTK_BUTTON_DEFAULT_DISABLED :
+ break;
+ case TTK_BUTTON_DEFAULT_NORMAL :
+ inset += 5;
+ break;
+ case TTK_BUTTON_DEFAULT_ACTIVE :
+ Tk_Draw3DRectangle(tkwin, d, border,
+ b.x+inset, b.y+inset, b.width - 2*inset, b.height - 2*inset,
+ 2, TK_RELIEF_FLAT);
+ inset += 2;
+ Tk_Draw3DRectangle(tkwin, d, border,
+ b.x+inset, b.y+inset, b.width - 2*inset, b.height - 2*inset,
+ 1, TK_RELIEF_SUNKEN);
+ ++inset;
+ Tk_Draw3DRectangle(tkwin, d, border,
+ b.x+inset, b.y+inset, b.width - 2*inset, b.height - 2*inset,
+ 2, TK_RELIEF_FLAT);
+ inset += 2;
+ break;
+ }
+
+ /*
+ * 3-D border:
+ */
+ if (border && borderWidth > 0) {
+ Tk_Draw3DRectangle(tkwin, d, border,
+ b.x+inset, b.y+inset, b.width - 2*inset, b.height - 2*inset,
+ borderWidth,relief);
+ }
+}
+
+static Ttk_ElementSpec ButtonBorderElementSpec =
+{
+ TK_STYLE_VERSION_2,
+ sizeof(ButtonBorderElement),
+ ButtonBorderElementOptions,
+ ButtonBorderElementSize,
+ ButtonBorderElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ Arrow element(s).
+ *
+ * Draws a 3-D shaded triangle.
+ * clientData is an enum ArrowDirection pointer.
+ */
+
+static int ArrowElements[] = { ARROW_UP, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT };
+typedef struct
+{
+ Tcl_Obj *sizeObj;
+ Tcl_Obj *borderObj;
+ Tcl_Obj *borderWidthObj;
+ Tcl_Obj *reliefObj;
+} ArrowElement;
+
+static Ttk_ElementOptionSpec ArrowElementOptions[] =
+{
+ { "-arrowsize", TK_OPTION_PIXELS, Tk_Offset(ArrowElement,sizeObj),
+ DEFAULT_ARROW_SIZE },
+ { "-background", TK_OPTION_BORDER, Tk_Offset(ArrowElement,borderObj),
+ DEFAULT_BACKGROUND },
+ { "-borderwidth", TK_OPTION_PIXELS, Tk_Offset(ArrowElement,borderWidthObj),
+ DEFAULT_BORDERWIDTH },
+ { "-relief", TK_OPTION_RELIEF, Tk_Offset(ArrowElement,reliefObj),"raised" },
+ { NULL, 0, 0, NULL }
+};
+
+static void ArrowElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ ArrowElement *arrow = elementRecord;
+ int size = 12;
+
+ Tk_GetPixelsFromObj(NULL, tkwin, arrow->sizeObj, &size);
+ *widthPtr = *heightPtr = size;
+}
+
+static void ArrowElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ int direction = *(int *)clientData;
+ ArrowElement *arrow = elementRecord;
+ Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, arrow->borderObj);
+ int borderWidth = 2;
+ int relief = TK_RELIEF_RAISED;
+ int size = b.width < b.height ? b.width : b.height;
+ XPoint points[3];
+
+ Tk_GetPixelsFromObj(NULL, tkwin, arrow->borderWidthObj, &borderWidth);
+ Tk_GetReliefFromObj(NULL, arrow->reliefObj, &relief);
+
+
+ /*
+ * @@@ There are off-by-one pixel errors in the way these are drawn;
+ * @@@ need to take a look at Tk_Fill3DPolygon and X11 to find the
+ * @@@ exact rules.
+ */
+ switch (direction)
+ {
+ case ARROW_UP:
+ points[2].x = b.x; points[2].y = b.y + size;
+ points[1].x = b.x + size/2; points[1].y = b.y;
+ points[0].x = b.x + size; points[0].y = b.y + size;
+ break;
+ case ARROW_DOWN:
+ points[0].x = b.x; points[0].y = b.y;
+ points[1].x = b.x + size/2; points[1].y = b.y + size;
+ points[2].x = b.x + size; points[2].y = b.y;
+ break;
+ case ARROW_LEFT:
+ points[0].x = b.x; points[0].y = b.y + size / 2;
+ points[1].x = b.x + size; points[1].y = b.y + size;
+ points[2].x = b.x + size; points[2].y = b.y;
+ break;
+ case ARROW_RIGHT:
+ points[0].x = b.x + size; points[0].y = b.y + size / 2;
+ points[1].x = b.x; points[1].y = b.y;
+ points[2].x = b.x; points[2].y = b.y + size;
+ break;
+ }
+
+ Tk_Fill3DPolygon(tkwin, d, border, points, 3, borderWidth, relief);
+}
+
+static Ttk_ElementSpec ArrowElementSpec =
+{
+ TK_STYLE_VERSION_2,
+ sizeof(ArrowElement),
+ ArrowElementOptions,
+ ArrowElementSize,
+ ArrowElementDraw
+};
+
+
+/*------------------------------------------------------------------------
+ * +++ Sash element (for ttk::panedwindow)
+ *
+ * NOTES:
+ *
+ * panedwindows with -orient horizontal use vertical sashes, and vice versa.
+ *
+ * Interpretation of -sashrelief 'groove' and 'ridge' are
+ * swapped wrt. the core panedwindow, which (I think) has them backwards.
+ *
+ * Default -sashrelief is sunken; the core panedwindow has default
+ * -sashrelief raised, but that looks wrong to me.
+ */
+
+static Ttk_Orient SashClientData[] = {
+ TTK_ORIENT_HORIZONTAL, TTK_ORIENT_VERTICAL
+};
+
+typedef struct {
+ Tcl_Obj *borderObj; /* background color */
+ Tcl_Obj *sashReliefObj; /* sash relief */
+ Tcl_Obj *sashThicknessObj; /* overall thickness of sash */
+ Tcl_Obj *sashPadObj; /* padding on either side of handle */
+ Tcl_Obj *handleSizeObj; /* handle width and height */
+ Tcl_Obj *handlePadObj; /* handle's distance from edge */
+} SashElement;
+
+static Ttk_ElementOptionSpec SashOptions[] = {
+ { "-background", TK_OPTION_BORDER,
+ Tk_Offset(SashElement,borderObj), DEFAULT_BACKGROUND },
+ { "-sashrelief", TK_OPTION_RELIEF,
+ Tk_Offset(SashElement,sashReliefObj), "sunken" },
+ { "-sashthickness", TK_OPTION_PIXELS,
+ Tk_Offset(SashElement,sashThicknessObj), "6" },
+ { "-sashpad", TK_OPTION_PIXELS,
+ Tk_Offset(SashElement,sashPadObj), "2" },
+ { "-handlesize", TK_OPTION_PIXELS,
+ Tk_Offset(SashElement,handleSizeObj), "8" },
+ { "-handlepad", TK_OPTION_PIXELS,
+ Tk_Offset(SashElement,handlePadObj), "8" },
+ { NULL, 0, 0, NULL }
+};
+
+static void SashElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ SashElement *sash = elementRecord;
+ int sashPad = 2, sashThickness = 6, handleSize = 8;
+ int horizontal = *((Ttk_Orient*)clientData) == TTK_ORIENT_HORIZONTAL;
+
+ Tk_GetPixelsFromObj(NULL, tkwin, sash->sashThicknessObj, &sashThickness);
+ Tk_GetPixelsFromObj(NULL, tkwin, sash->handleSizeObj, &handleSize);
+ Tk_GetPixelsFromObj(NULL, tkwin, sash->sashPadObj, &sashPad);
+
+ if (sashThickness < handleSize + 2*sashPad)
+ sashThickness = handleSize + 2*sashPad;
+
+ if (horizontal)
+ *heightPtr = sashThickness;
+ else
+ *widthPtr = sashThickness;
+}
+
+static void SashElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, Ttk_State state)
+{
+ SashElement *sash = elementRecord;
+ Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, sash->borderObj);
+ GC gc1,gc2;
+ int relief = TK_RELIEF_RAISED;
+ int handleSize = 8, handlePad = 8;
+ int horizontal = *((Ttk_Orient*)clientData) == TTK_ORIENT_HORIZONTAL;
+ Ttk_Box hb;
+
+ Tk_GetPixelsFromObj(NULL, tkwin, sash->handleSizeObj, &handleSize);
+ Tk_GetPixelsFromObj(NULL, tkwin, sash->handlePadObj, &handlePad);
+ Tk_GetReliefFromObj(NULL, sash->sashReliefObj, &relief);
+
+ switch (relief) {
+ case TK_RELIEF_RAISED: case TK_RELIEF_RIDGE:
+ gc1 = Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC);
+ gc2 = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC);
+ break;
+ case TK_RELIEF_SUNKEN: case TK_RELIEF_GROOVE:
+ gc1 = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC);
+ gc2 = Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC);
+ break;
+ case TK_RELIEF_SOLID:
+ gc1 = gc2 = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC);
+ break;
+ case TK_RELIEF_FLAT:
+ default:
+ gc1 = gc2 = Tk_3DBorderGC(tkwin, border, TK_3D_FLAT_GC);
+ break;
+ }
+
+ /* Draw sash line:
+ */
+ if (horizontal) {
+ int y = b.y + b.height/2 - 1;
+ XDrawLine(Tk_Display(tkwin), d, gc1, b.x, y, b.x+b.width, y); ++y;
+ XDrawLine(Tk_Display(tkwin), d, gc2, b.x, y, b.x+b.width, y);
+ } else {
+ int x = b.x + b.width/2 - 1;
+ XDrawLine(Tk_Display(tkwin), d, gc1, x, b.y, x, b.y+b.height); ++x;
+ XDrawLine(Tk_Display(tkwin), d, gc2, x, b.y, x, b.y+b.height);
+ }
+
+ /* Draw handle:
+ */
+ if (handleSize >= 0) {
+ if (horizontal) {
+ hb = Ttk_StickBox(b, handleSize, handleSize, TTK_STICK_W);
+ hb.x += handlePad;
+ } else {
+ hb = Ttk_StickBox(b, handleSize, handleSize, TTK_STICK_N);
+ hb.y += handlePad;
+ }
+ Tk_Fill3DRectangle(tkwin, d, border,
+ hb.x, hb.y, hb.width, hb.height, 1, TK_RELIEF_RAISED);
+ }
+}
+
+static Ttk_ElementSpec SashElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(SashElement),
+ SashOptions,
+ SashElementSize,
+ SashElementDraw
+};
+
+/*------------------------------------------------------------------------
+ * +++ Widget layouts.
+ */
+
+TTK_BEGIN_LAYOUT_TABLE(LayoutTable)
+
+TTK_LAYOUT("TButton",
+ TTK_GROUP("Button.highlight", TTK_FILL_BOTH,
+ TTK_GROUP("Button.border", TTK_FILL_BOTH|TTK_BORDER,
+ TTK_GROUP("Button.padding", TTK_FILL_BOTH,
+ TTK_NODE("Button.label", TTK_FILL_BOTH)))))
+
+TTK_LAYOUT("TCheckbutton",
+ TTK_GROUP("Checkbutton.highlight", TTK_FILL_BOTH,
+ TTK_GROUP("Checkbutton.border", TTK_FILL_BOTH,
+ TTK_GROUP("Checkbutton.padding", TTK_FILL_BOTH,
+ TTK_NODE("Checkbutton.indicator", TTK_PACK_LEFT)
+ TTK_NODE("Checkbutton.label", TTK_PACK_LEFT|TTK_FILL_BOTH)))))
+
+TTK_LAYOUT("TRadiobutton",
+ TTK_GROUP("Radiobutton.highlight", TTK_FILL_BOTH,
+ TTK_GROUP("Radiobutton.border", TTK_FILL_BOTH,
+ TTK_GROUP("Radiobutton.padding", TTK_FILL_BOTH,
+ TTK_NODE("Radiobutton.indicator", TTK_PACK_LEFT)
+ TTK_NODE("Radiobutton.label", TTK_PACK_LEFT|TTK_FILL_BOTH)))))
+
+TTK_LAYOUT("TMenubutton",
+ TTK_GROUP("Menubutton.highlight", TTK_FILL_BOTH,
+ TTK_GROUP("Menubutton.border", TTK_FILL_BOTH,
+ TTK_NODE("Menubutton.indicator", TTK_PACK_RIGHT)
+ TTK_GROUP("Menubutton.padding", TTK_PACK_LEFT|TTK_EXPAND|TTK_FILL_X,
+ TTK_NODE("Menubutton.label", 0)))))
+
+/* "classic" entry, includes highlight border */
+TTK_LAYOUT("TEntry",
+ TTK_GROUP("Entry.highlight", TTK_FILL_BOTH,
+ TTK_GROUP("Entry.field", TTK_FILL_BOTH|TTK_BORDER,
+ TTK_GROUP("Entry.padding", TTK_FILL_BOTH,
+ TTK_NODE("Entry.textarea", TTK_FILL_BOTH)))))
+
+/* Notebook tabs -- omit focus ring */
+TTK_LAYOUT("Tab",
+ TTK_GROUP("Notebook.tab", TTK_FILL_BOTH,
+ TTK_GROUP("Notebook.padding", TTK_FILL_BOTH,
+ TTK_NODE("Notebook.label", TTK_FILL_BOTH))))
+
+TTK_END_LAYOUT_TABLE
+
+/* POSSIBLY: include Scale layouts w/focus border
+ */
+
+/*------------------------------------------------------------------------
+ * TtkClassicTheme_Init --
+ * Install classic theme.
+ */
+
+MODULE_SCOPE int TtkClassicTheme_Init(Tcl_Interp *interp)
+{
+ Ttk_Theme theme = Ttk_CreateTheme(interp, "classic", NULL);
+
+ if (!theme) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Register elements:
+ */
+ Ttk_RegisterElement(interp, theme, "highlight",
+ &HighlightElementSpec, NULL);
+
+ Ttk_RegisterElement(interp, theme, "Button.border",
+ &ButtonBorderElementSpec, NULL);
+
+ Ttk_RegisterElement(interp, theme, "uparrow",
+ &ArrowElementSpec, &ArrowElements[0]);
+ Ttk_RegisterElement(interp, theme, "downarrow",
+ &ArrowElementSpec, &ArrowElements[1]);
+ Ttk_RegisterElement(interp, theme, "leftarrow",
+ &ArrowElementSpec, &ArrowElements[2]);
+ Ttk_RegisterElement(interp, theme, "rightarrow",
+ &ArrowElementSpec, &ArrowElements[3]);
+ Ttk_RegisterElement(interp, theme, "arrow",
+ &ArrowElementSpec, &ArrowElements[0]);
+
+ Ttk_RegisterElement(interp, theme, "hsash",
+ &SashElementSpec, &SashClientData[0]);
+ Ttk_RegisterElement(interp, theme, "vsash",
+ &SashElementSpec, &SashClientData[1]);
+
+ /*
+ * Register layouts:
+ */
+ Ttk_RegisterLayouts(theme, LayoutTable);
+
+ Tcl_PkgProvide(interp, "ttk::theme::classic", TTK_VERSION);
+
+ return TCL_OK;
+}
+
+/*EOF*/
diff --git a/tk8.6/generic/ttk/ttkDecls.h b/tk8.6/generic/ttk/ttkDecls.h
new file mode 100644
index 0000000..6701724
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkDecls.h
@@ -0,0 +1,274 @@
+/*
+ * This file is (mostly) automatically generated from ttk.decls.
+ */
+
+#ifndef _TTKDECLS
+#define _TTKDECLS
+
+#if defined(USE_TTK_STUBS)
+
+extern const char *TtkInitializeStubs(
+ Tcl_Interp *, const char *version, int epoch, int revision);
+#define Ttk_InitStubs(interp) TtkInitializeStubs( \
+ interp, TTK_VERSION, TTK_STUBS_EPOCH, TTK_STUBS_REVISION)
+#else
+
+#define Ttk_InitStubs(interp) Tcl_PkgRequireEx(interp, "Ttk", TTK_VERSION, 0, NULL)
+
+#endif
+
+
+/* !BEGIN!: Do not edit below this line. */
+
+#define TTK_STUBS_EPOCH 0
+#define TTK_STUBS_REVISION 31
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Exported function declarations:
+ */
+
+/* 0 */
+TTKAPI Ttk_Theme Ttk_GetTheme(Tcl_Interp *interp, const char *name);
+/* 1 */
+TTKAPI Ttk_Theme Ttk_GetDefaultTheme(Tcl_Interp *interp);
+/* 2 */
+TTKAPI Ttk_Theme Ttk_GetCurrentTheme(Tcl_Interp *interp);
+/* 3 */
+TTKAPI Ttk_Theme Ttk_CreateTheme(Tcl_Interp *interp, const char *name,
+ Ttk_Theme parent);
+/* 4 */
+TTKAPI void Ttk_RegisterCleanup(Tcl_Interp *interp,
+ void *deleteData,
+ Ttk_CleanupProc *cleanupProc);
+/* 5 */
+TTKAPI int Ttk_RegisterElementSpec(Ttk_Theme theme,
+ const char *elementName,
+ Ttk_ElementSpec *elementSpec,
+ void *clientData);
+/* 6 */
+TTKAPI Ttk_ElementClass * Ttk_RegisterElement(Tcl_Interp *interp,
+ Ttk_Theme theme, const char *elementName,
+ Ttk_ElementSpec *elementSpec,
+ void *clientData);
+/* 7 */
+TTKAPI int Ttk_RegisterElementFactory(Tcl_Interp *interp,
+ const char *name,
+ Ttk_ElementFactory factoryProc,
+ void *clientData);
+/* 8 */
+TTKAPI void Ttk_RegisterLayout(Ttk_Theme theme,
+ const char *className,
+ Ttk_LayoutSpec layoutSpec);
+/* Slot 9 is reserved */
+/* 10 */
+TTKAPI int Ttk_GetStateSpecFromObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, Ttk_StateSpec *spec_rtn);
+/* 11 */
+TTKAPI Tcl_Obj * Ttk_NewStateSpecObj(unsigned int onbits,
+ unsigned int offbits);
+/* 12 */
+TTKAPI Ttk_StateMap Ttk_GetStateMapFromObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr);
+/* 13 */
+TTKAPI Tcl_Obj * Ttk_StateMapLookup(Tcl_Interp *interp,
+ Ttk_StateMap map, Ttk_State state);
+/* 14 */
+TTKAPI int Ttk_StateTableLookup(Ttk_StateTable map[],
+ Ttk_State state);
+/* Slot 15 is reserved */
+/* Slot 16 is reserved */
+/* Slot 17 is reserved */
+/* Slot 18 is reserved */
+/* Slot 19 is reserved */
+/* 20 */
+TTKAPI int Ttk_GetPaddingFromObj(Tcl_Interp *interp,
+ Tk_Window tkwin, Tcl_Obj *objPtr,
+ Ttk_Padding *pad_rtn);
+/* 21 */
+TTKAPI int Ttk_GetBorderFromObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, Ttk_Padding *pad_rtn);
+/* 22 */
+TTKAPI int Ttk_GetStickyFromObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, Ttk_Sticky *sticky_rtn);
+/* 23 */
+TTKAPI Ttk_Padding Ttk_MakePadding(short l, short t, short r, short b);
+/* 24 */
+TTKAPI Ttk_Padding Ttk_UniformPadding(short borderWidth);
+/* 25 */
+TTKAPI Ttk_Padding Ttk_AddPadding(Ttk_Padding pad1, Ttk_Padding pad2);
+/* 26 */
+TTKAPI Ttk_Padding Ttk_RelievePadding(Ttk_Padding padding, int relief,
+ int n);
+/* 27 */
+TTKAPI Ttk_Box Ttk_MakeBox(int x, int y, int width, int height);
+/* 28 */
+TTKAPI int Ttk_BoxContains(Ttk_Box box, int x, int y);
+/* 29 */
+TTKAPI Ttk_Box Ttk_PackBox(Ttk_Box *cavity, int w, int h,
+ Ttk_Side side);
+/* 30 */
+TTKAPI Ttk_Box Ttk_StickBox(Ttk_Box parcel, int w, int h,
+ Ttk_Sticky sticky);
+/* 31 */
+TTKAPI Ttk_Box Ttk_AnchorBox(Ttk_Box parcel, int w, int h,
+ Tk_Anchor anchor);
+/* 32 */
+TTKAPI Ttk_Box Ttk_PadBox(Ttk_Box b, Ttk_Padding p);
+/* 33 */
+TTKAPI Ttk_Box Ttk_ExpandBox(Ttk_Box b, Ttk_Padding p);
+/* 34 */
+TTKAPI Ttk_Box Ttk_PlaceBox(Ttk_Box *cavity, int w, int h,
+ Ttk_Side side, Ttk_Sticky sticky);
+/* 35 */
+TTKAPI Tcl_Obj * Ttk_NewBoxObj(Ttk_Box box);
+/* Slot 36 is reserved */
+/* Slot 37 is reserved */
+/* Slot 38 is reserved */
+/* Slot 39 is reserved */
+/* 40 */
+TTKAPI int Ttk_GetOrientFromObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, int *orient);
+
+typedef struct TtkStubs {
+ int magic;
+ int epoch;
+ int revision;
+ void *hooks;
+
+ Ttk_Theme (*ttk_GetTheme) (Tcl_Interp *interp, const char *name); /* 0 */
+ Ttk_Theme (*ttk_GetDefaultTheme) (Tcl_Interp *interp); /* 1 */
+ Ttk_Theme (*ttk_GetCurrentTheme) (Tcl_Interp *interp); /* 2 */
+ Ttk_Theme (*ttk_CreateTheme) (Tcl_Interp *interp, const char *name, Ttk_Theme parent); /* 3 */
+ void (*ttk_RegisterCleanup) (Tcl_Interp *interp, void *deleteData, Ttk_CleanupProc *cleanupProc); /* 4 */
+ int (*ttk_RegisterElementSpec) (Ttk_Theme theme, const char *elementName, Ttk_ElementSpec *elementSpec, void *clientData); /* 5 */
+ Ttk_ElementClass * (*ttk_RegisterElement) (Tcl_Interp *interp, Ttk_Theme theme, const char *elementName, Ttk_ElementSpec *elementSpec, void *clientData); /* 6 */
+ int (*ttk_RegisterElementFactory) (Tcl_Interp *interp, const char *name, Ttk_ElementFactory factoryProc, void *clientData); /* 7 */
+ void (*ttk_RegisterLayout) (Ttk_Theme theme, const char *className, Ttk_LayoutSpec layoutSpec); /* 8 */
+ void (*reserved9)(void);
+ int (*ttk_GetStateSpecFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_StateSpec *spec_rtn); /* 10 */
+ Tcl_Obj * (*ttk_NewStateSpecObj) (unsigned int onbits, unsigned int offbits); /* 11 */
+ Ttk_StateMap (*ttk_GetStateMapFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr); /* 12 */
+ Tcl_Obj * (*ttk_StateMapLookup) (Tcl_Interp *interp, Ttk_StateMap map, Ttk_State state); /* 13 */
+ int (*ttk_StateTableLookup) (Ttk_StateTable map[], Ttk_State state); /* 14 */
+ void (*reserved15)(void);
+ void (*reserved16)(void);
+ void (*reserved17)(void);
+ void (*reserved18)(void);
+ void (*reserved19)(void);
+ int (*ttk_GetPaddingFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, Ttk_Padding *pad_rtn); /* 20 */
+ int (*ttk_GetBorderFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_Padding *pad_rtn); /* 21 */
+ int (*ttk_GetStickyFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_Sticky *sticky_rtn); /* 22 */
+ Ttk_Padding (*ttk_MakePadding) (short l, short t, short r, short b); /* 23 */
+ Ttk_Padding (*ttk_UniformPadding) (short borderWidth); /* 24 */
+ Ttk_Padding (*ttk_AddPadding) (Ttk_Padding pad1, Ttk_Padding pad2); /* 25 */
+ Ttk_Padding (*ttk_RelievePadding) (Ttk_Padding padding, int relief, int n); /* 26 */
+ Ttk_Box (*ttk_MakeBox) (int x, int y, int width, int height); /* 27 */
+ int (*ttk_BoxContains) (Ttk_Box box, int x, int y); /* 28 */
+ Ttk_Box (*ttk_PackBox) (Ttk_Box *cavity, int w, int h, Ttk_Side side); /* 29 */
+ Ttk_Box (*ttk_StickBox) (Ttk_Box parcel, int w, int h, Ttk_Sticky sticky); /* 30 */
+ Ttk_Box (*ttk_AnchorBox) (Ttk_Box parcel, int w, int h, Tk_Anchor anchor); /* 31 */
+ Ttk_Box (*ttk_PadBox) (Ttk_Box b, Ttk_Padding p); /* 32 */
+ Ttk_Box (*ttk_ExpandBox) (Ttk_Box b, Ttk_Padding p); /* 33 */
+ Ttk_Box (*ttk_PlaceBox) (Ttk_Box *cavity, int w, int h, Ttk_Side side, Ttk_Sticky sticky); /* 34 */
+ Tcl_Obj * (*ttk_NewBoxObj) (Ttk_Box box); /* 35 */
+ void (*reserved36)(void);
+ void (*reserved37)(void);
+ void (*reserved38)(void);
+ void (*reserved39)(void);
+ int (*ttk_GetOrientFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *orient); /* 40 */
+} TtkStubs;
+
+extern const TtkStubs *ttkStubsPtr;
+
+#ifdef __cplusplus
+}
+#endif
+
+#if defined(USE_TTK_STUBS)
+
+/*
+ * Inline function declarations:
+ */
+
+#define Ttk_GetTheme \
+ (ttkStubsPtr->ttk_GetTheme) /* 0 */
+#define Ttk_GetDefaultTheme \
+ (ttkStubsPtr->ttk_GetDefaultTheme) /* 1 */
+#define Ttk_GetCurrentTheme \
+ (ttkStubsPtr->ttk_GetCurrentTheme) /* 2 */
+#define Ttk_CreateTheme \
+ (ttkStubsPtr->ttk_CreateTheme) /* 3 */
+#define Ttk_RegisterCleanup \
+ (ttkStubsPtr->ttk_RegisterCleanup) /* 4 */
+#define Ttk_RegisterElementSpec \
+ (ttkStubsPtr->ttk_RegisterElementSpec) /* 5 */
+#define Ttk_RegisterElement \
+ (ttkStubsPtr->ttk_RegisterElement) /* 6 */
+#define Ttk_RegisterElementFactory \
+ (ttkStubsPtr->ttk_RegisterElementFactory) /* 7 */
+#define Ttk_RegisterLayout \
+ (ttkStubsPtr->ttk_RegisterLayout) /* 8 */
+/* Slot 9 is reserved */
+#define Ttk_GetStateSpecFromObj \
+ (ttkStubsPtr->ttk_GetStateSpecFromObj) /* 10 */
+#define Ttk_NewStateSpecObj \
+ (ttkStubsPtr->ttk_NewStateSpecObj) /* 11 */
+#define Ttk_GetStateMapFromObj \
+ (ttkStubsPtr->ttk_GetStateMapFromObj) /* 12 */
+#define Ttk_StateMapLookup \
+ (ttkStubsPtr->ttk_StateMapLookup) /* 13 */
+#define Ttk_StateTableLookup \
+ (ttkStubsPtr->ttk_StateTableLookup) /* 14 */
+/* Slot 15 is reserved */
+/* Slot 16 is reserved */
+/* Slot 17 is reserved */
+/* Slot 18 is reserved */
+/* Slot 19 is reserved */
+#define Ttk_GetPaddingFromObj \
+ (ttkStubsPtr->ttk_GetPaddingFromObj) /* 20 */
+#define Ttk_GetBorderFromObj \
+ (ttkStubsPtr->ttk_GetBorderFromObj) /* 21 */
+#define Ttk_GetStickyFromObj \
+ (ttkStubsPtr->ttk_GetStickyFromObj) /* 22 */
+#define Ttk_MakePadding \
+ (ttkStubsPtr->ttk_MakePadding) /* 23 */
+#define Ttk_UniformPadding \
+ (ttkStubsPtr->ttk_UniformPadding) /* 24 */
+#define Ttk_AddPadding \
+ (ttkStubsPtr->ttk_AddPadding) /* 25 */
+#define Ttk_RelievePadding \
+ (ttkStubsPtr->ttk_RelievePadding) /* 26 */
+#define Ttk_MakeBox \
+ (ttkStubsPtr->ttk_MakeBox) /* 27 */
+#define Ttk_BoxContains \
+ (ttkStubsPtr->ttk_BoxContains) /* 28 */
+#define Ttk_PackBox \
+ (ttkStubsPtr->ttk_PackBox) /* 29 */
+#define Ttk_StickBox \
+ (ttkStubsPtr->ttk_StickBox) /* 30 */
+#define Ttk_AnchorBox \
+ (ttkStubsPtr->ttk_AnchorBox) /* 31 */
+#define Ttk_PadBox \
+ (ttkStubsPtr->ttk_PadBox) /* 32 */
+#define Ttk_ExpandBox \
+ (ttkStubsPtr->ttk_ExpandBox) /* 33 */
+#define Ttk_PlaceBox \
+ (ttkStubsPtr->ttk_PlaceBox) /* 34 */
+#define Ttk_NewBoxObj \
+ (ttkStubsPtr->ttk_NewBoxObj) /* 35 */
+/* Slot 36 is reserved */
+/* Slot 37 is reserved */
+/* Slot 38 is reserved */
+/* Slot 39 is reserved */
+#define Ttk_GetOrientFromObj \
+ (ttkStubsPtr->ttk_GetOrientFromObj) /* 40 */
+
+#endif /* defined(USE_TTK_STUBS) */
+
+/* !END!: Do not edit above this line. */
+
+#endif /* _TTKDECLS */
diff --git a/tk8.6/generic/ttk/ttkDefaultTheme.c b/tk8.6/generic/ttk/ttkDefaultTheme.c
new file mode 100644
index 0000000..89bf028
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkDefaultTheme.c
@@ -0,0 +1,1181 @@
+/*
+ * Copyright (c) 2003, Joe English
+ *
+ * Tk alternate theme, intended to match the MSUE and Gtk's (old) default theme
+ */
+
+#include "tkInt.h"
+#include "ttkTheme.h"
+
+#if defined(_WIN32)
+static const int WIN32_XDRAWLINE_HACK = 1;
+#else
+static const int WIN32_XDRAWLINE_HACK = 0;
+#endif
+
+#if defined(MAC_OSX_TK)
+ #define IGNORES_VISUAL
+#endif
+
+#define BORDERWIDTH 2
+#define SCROLLBAR_WIDTH 14
+#define MIN_THUMB_SIZE 8
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Helper routines for border drawing:
+ *
+ * NOTE: MSUE specifies a slightly different arrangement
+ * for button borders than for other elements; "shadowColors"
+ * is for button borders.
+ *
+ * Please excuse the gross misspelling "LITE" for "LIGHT",
+ * but it makes things line up nicer.
+ */
+
+enum BorderColor { FLAT = 1, LITE = 2, DARK = 3, BRDR = 4 };
+
+/* top-left outer, top-left inner, bottom-right inner, bottom-right outer */
+static int const shadowColors[6][4] = {
+ { FLAT, FLAT, FLAT, FLAT }, /* TK_RELIEF_FLAT = 0*/
+ { DARK, LITE, DARK, LITE }, /* TK_RELIEF_GROOVE = 1*/
+ { LITE, FLAT, DARK, BRDR }, /* TK_RELIEF_RAISED = 2*/
+ { LITE, DARK, LITE, DARK }, /* TK_RELIEF_RIDGE = 3*/
+ { BRDR, BRDR, BRDR, BRDR }, /* TK_RELIEF_SOLID = 4*/
+ { BRDR, DARK, FLAT, LITE } /* TK_RELIEF_SUNKEN = 5*/
+};
+
+/* top-left, bottom-right */
+static int const thinShadowColors[6][4] = {
+ { FLAT, FLAT }, /* TK_RELIEF_FLAT = 0*/
+ { DARK, LITE }, /* TK_RELIEF_GROOVE = 1*/
+ { LITE, DARK }, /* TK_RELIEF_RAISED = 2*/
+ { LITE, DARK }, /* TK_RELIEF_RIDGE = 3*/
+ { BRDR, BRDR }, /* TK_RELIEF_SOLID = 4*/
+ { DARK, LITE } /* TK_RELIEF_SUNKEN = 5*/
+};
+
+static void DrawCorner(
+ Tk_Window tkwin,
+ Drawable d,
+ Tk_3DBorder border, /* get most GCs from here... */
+ GC borderGC, /* "window border" color GC */
+ int x,int y, int width,int height, /* where to draw */
+ int corner, /* 0 => top left; 1 => bottom right */
+ enum BorderColor color)
+{
+ XPoint points[3];
+ GC gc;
+
+ --width; --height;
+ points[0].x = x; points[0].y = y+height;
+ points[1].x = x+width*corner; points[1].y = y+height*corner;
+ points[2].x = x+width; points[2].y = y;
+
+ if (color == BRDR)
+ gc = borderGC;
+ else
+ gc = Tk_3DBorderGC(tkwin, border, (int)color);
+
+ XDrawLines(Tk_Display(tkwin), d, gc, points, 3, CoordModeOrigin);
+}
+
+static void DrawBorder(
+ Tk_Window tkwin, Drawable d, Tk_3DBorder border, XColor *borderColor,
+ Ttk_Box b, int borderWidth, int relief)
+{
+ GC borderGC = Tk_GCForColor(borderColor, d);
+
+ switch (borderWidth) {
+ case 2: /* "thick" border */
+ DrawCorner(tkwin, d, border, borderGC,
+ b.x, b.y, b.width, b.height, 0,shadowColors[relief][0]);
+ DrawCorner(tkwin, d, border, borderGC,
+ b.x+1, b.y+1, b.width-2, b.height-2, 0,shadowColors[relief][1]);
+ DrawCorner(tkwin, d, border, borderGC,
+ b.x+1, b.y+1, b.width-2, b.height-2, 1,shadowColors[relief][2]);
+ DrawCorner(tkwin, d, border, borderGC,
+ b.x, b.y, b.width, b.height, 1,shadowColors[relief][3]);
+ break;
+ case 1: /* "thin" border */
+ DrawCorner(tkwin, d, border, borderGC,
+ b.x, b.y, b.width, b.height, 0, thinShadowColors[relief][0]);
+ DrawCorner(tkwin, d, border, borderGC,
+ b.x, b.y, b.width, b.height, 1, thinShadowColors[relief][1]);
+ break;
+ case 0: /* no border -- do nothing */
+ break;
+ default: /* Fall back to Motif-style borders: */
+ Tk_Draw3DRectangle(tkwin, d, border,
+ b.x, b.y, b.width, b.height, borderWidth,relief);
+ break;
+ }
+}
+
+/* Alternate shadow colors for entry fields:
+ * NOTE: FLAT color is normally white, and the LITE color is a darker shade.
+ */
+static int fieldShadowColors[4] = { DARK, BRDR, LITE, FLAT };
+
+static void DrawFieldBorder(
+ Tk_Window tkwin, Drawable d, Tk_3DBorder border, XColor *borderColor,
+ Ttk_Box b)
+{
+ GC borderGC = Tk_GCForColor(borderColor, d);
+ DrawCorner(tkwin, d, border, borderGC,
+ b.x, b.y, b.width, b.height, 0,fieldShadowColors[0]);
+ DrawCorner(tkwin, d, border, borderGC,
+ b.x+1, b.y+1, b.width-2, b.height-2, 0,fieldShadowColors[1]);
+ DrawCorner(tkwin, d, border, borderGC,
+ b.x+1, b.y+1, b.width-2, b.height-2, 1,fieldShadowColors[2]);
+ DrawCorner(tkwin, d, border, borderGC,
+ b.x, b.y, b.width, b.height, 1,fieldShadowColors[3]);
+ return;
+}
+
+/*
+ * ArrowPoints --
+ * Compute points of arrow polygon.
+ */
+static void ArrowPoints(Ttk_Box b, ArrowDirection dir, XPoint points[4])
+{
+ int cx, cy, h;
+
+ switch (dir) {
+ case ARROW_UP:
+ h = (b.width - 1)/2;
+ cx = b.x + h;
+ cy = b.y;
+ if (b.height <= h) h = b.height - 1;
+ points[0].x = cx; points[0].y = cy;
+ points[1].x = cx - h; points[1].y = cy + h;
+ points[2].x = cx + h; points[2].y = cy + h;
+ break;
+ case ARROW_DOWN:
+ h = (b.width - 1)/2;
+ cx = b.x + h;
+ cy = b.y + b.height - 1;
+ if (b.height <= h) h = b.height - 1;
+ points[0].x = cx; points[0].y = cy;
+ points[1].x = cx - h; points[1].y = cy - h;
+ points[2].x = cx + h; points[2].y = cy - h;
+ break;
+ case ARROW_LEFT:
+ h = (b.height - 1)/2;
+ cx = b.x;
+ cy = b.y + h;
+ if (b.width <= h) h = b.width - 1;
+ points[0].x = cx; points[0].y = cy;
+ points[1].x = cx + h; points[1].y = cy - h;
+ points[2].x = cx + h; points[2].y = cy + h;
+ break;
+ case ARROW_RIGHT:
+ h = (b.height - 1)/2;
+ cx = b.x + b.width - 1;
+ cy = b.y + h;
+ if (b.width <= h) h = b.width - 1;
+ points[0].x = cx; points[0].y = cy;
+ points[1].x = cx - h; points[1].y = cy - h;
+ points[2].x = cx - h; points[2].y = cy + h;
+ break;
+ }
+
+ points[3].x = points[0].x;
+ points[3].y = points[0].y;
+}
+
+/*public*/
+void TtkArrowSize(int h, ArrowDirection dir, int *widthPtr, int *heightPtr)
+{
+ switch (dir) {
+ case ARROW_UP:
+ case ARROW_DOWN: *widthPtr = 2*h+1; *heightPtr = h+1; break;
+ case ARROW_LEFT:
+ case ARROW_RIGHT: *widthPtr = h+1; *heightPtr = 2*h+1;
+ }
+}
+
+/*
+ * TtkDrawArrow, TtkFillArrow --
+ * Draw an arrow in the indicated direction inside the specified box.
+ */
+/*public*/
+void TtkFillArrow(
+ Display *display, Drawable d, GC gc, Ttk_Box b, ArrowDirection dir)
+{
+ XPoint points[4];
+ ArrowPoints(b, dir, points);
+ XFillPolygon(display, d, gc, points, 3, Convex, CoordModeOrigin);
+ XDrawLines(display, d, gc, points, 4, CoordModeOrigin);
+
+ /* Work around bug [77527326e5] - ttk artifacts on Ubuntu */
+ XDrawPoint(display, d, gc, points[2].x, points[2].y);
+}
+
+/*public*/
+void TtkDrawArrow(
+ Display *display, Drawable d, GC gc, Ttk_Box b, ArrowDirection dir)
+{
+ XPoint points[4];
+ ArrowPoints(b, dir, points);
+ XDrawLines(display, d, gc, points, 4, CoordModeOrigin);
+
+ /* Work around bug [77527326e5] - ttk artifacts on Ubuntu */
+ XDrawPoint(display, d, gc, points[2].x, points[2].y);
+}
+
+/*
+ *----------------------------------------------------------------------
+ * +++ Border element implementation.
+ *
+ * This border consists of (from outside-in):
+ *
+ * + a 1-pixel thick default indicator (defaultable widgets only)
+ * + 1- or 2- pixel shaded border (controlled by -background and -relief)
+ * + 1 pixel padding (???)
+ */
+
+typedef struct {
+ Tcl_Obj *borderObj;
+ Tcl_Obj *borderColorObj; /* Extra border color */
+ Tcl_Obj *borderWidthObj;
+ Tcl_Obj *reliefObj;
+ Tcl_Obj *defaultStateObj; /* for buttons */
+} BorderElement;
+
+static Ttk_ElementOptionSpec BorderElementOptions[] = {
+ { "-background", TK_OPTION_BORDER, Tk_Offset(BorderElement,borderObj),
+ DEFAULT_BACKGROUND },
+ { "-bordercolor",TK_OPTION_COLOR,
+ Tk_Offset(BorderElement,borderColorObj), "black" },
+ { "-default", TK_OPTION_ANY, Tk_Offset(BorderElement,defaultStateObj),
+ "disabled" },
+ { "-borderwidth",TK_OPTION_PIXELS,Tk_Offset(BorderElement,borderWidthObj),
+ STRINGIFY(BORDERWIDTH) },
+ { "-relief", TK_OPTION_RELIEF, Tk_Offset(BorderElement,reliefObj),
+ "flat" },
+ { NULL, 0, 0, NULL }
+};
+
+static void BorderElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ BorderElement *bd = elementRecord;
+ int borderWidth = 0;
+ int defaultState = TTK_BUTTON_DEFAULT_DISABLED;
+
+ Tcl_GetIntFromObj(NULL, bd->borderWidthObj, &borderWidth);
+ Ttk_GetButtonDefaultStateFromObj(NULL, bd->defaultStateObj, &defaultState);
+
+ if (defaultState != TTK_BUTTON_DEFAULT_DISABLED) {
+ ++borderWidth;
+ }
+
+ *paddingPtr = Ttk_UniformPadding((short)borderWidth);
+}
+
+static void BorderElementDraw(
+ void *clientData, void *elementRecord,
+ Tk_Window tkwin, Drawable d, Ttk_Box b, unsigned int state)
+{
+ BorderElement *bd = elementRecord;
+ Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, bd->borderObj);
+ XColor *borderColor = Tk_GetColorFromObj(tkwin, bd->borderColorObj);
+ int borderWidth = 2;
+ int relief = TK_RELIEF_FLAT;
+ int defaultState = TTK_BUTTON_DEFAULT_DISABLED;
+
+ /*
+ * Get option values.
+ */
+ Tcl_GetIntFromObj(NULL, bd->borderWidthObj, &borderWidth);
+ Tk_GetReliefFromObj(NULL, bd->reliefObj, &relief);
+ Ttk_GetButtonDefaultStateFromObj(NULL, bd->defaultStateObj, &defaultState);
+
+ if (defaultState == TTK_BUTTON_DEFAULT_ACTIVE) {
+ GC gc = Tk_GCForColor(borderColor, d);
+ XDrawRectangle(Tk_Display(tkwin), d, gc,
+ b.x, b.y, b.width-1, b.height-1);
+ }
+ if (defaultState != TTK_BUTTON_DEFAULT_DISABLED) {
+ /* Space for default ring: */
+ b = Ttk_PadBox(b, Ttk_UniformPadding(1));
+ }
+
+ DrawBorder(tkwin, d, border, borderColor, b, borderWidth, relief);
+}
+
+static Ttk_ElementSpec BorderElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(BorderElement),
+ BorderElementOptions,
+ BorderElementSize,
+ BorderElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ Field element:
+ * Used for editable fields.
+ */
+typedef struct {
+ Tcl_Obj *borderObj;
+ Tcl_Obj *borderColorObj; /* Extra border color */
+} FieldElement;
+
+static Ttk_ElementOptionSpec FieldElementOptions[] = {
+ { "-fieldbackground", TK_OPTION_BORDER, Tk_Offset(FieldElement,borderObj),
+ "white" },
+ { "-bordercolor",TK_OPTION_COLOR, Tk_Offset(FieldElement,borderColorObj),
+ "black" },
+ { NULL, 0, 0, NULL }
+};
+
+static void FieldElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ *paddingPtr = Ttk_UniformPadding(2);
+}
+
+static void FieldElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ FieldElement *field = elementRecord;
+ Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, field->borderObj);
+ XColor *borderColor = Tk_GetColorFromObj(tkwin, field->borderColorObj);
+
+ Tk_Fill3DRectangle(
+ tkwin, d, border, b.x, b.y, b.width, b.height, 0, TK_RELIEF_SUNKEN);
+ DrawFieldBorder(tkwin, d, border, borderColor, b);
+}
+
+static Ttk_ElementSpec FieldElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(FieldElement),
+ FieldElementOptions,
+ FieldElementSize,
+ FieldElementDraw
+};
+
+/*------------------------------------------------------------------------
+ * Indicators --
+ *
+ * Code derived (probably incorrectly) from TIP 109 implementation,
+ * unix/tkUnixButton.c r 1.15.
+ */
+
+/*
+ * Indicator bitmap descriptor:
+ */
+typedef struct {
+ int width; /* Width of each image */
+ int height; /* Height of each image */
+ int nimages; /* #images / row */
+ const char *const *pixels; /* array[height] of char[width*nimage] */
+ Ttk_StateTable *map;/* used to look up image index by state */
+} IndicatorSpec;
+
+#if 0
+/*XPM*/
+static const char *const button_images[] = {
+ /* width height ncolors chars_per_pixel */
+ "52 13 8 1",
+ /* colors */
+ "A c #808000000000 s shadow",
+ "B c #000080800000 s highlight",
+ "C c #808080800000 s 3dlight",
+ "D c #000000008080 s window",
+ "E c #808000008080 s 3ddark",
+ "F c #000080808080 s frame",
+ "G c #000000000000 s foreground",
+ "H c #000080800000 s disabledfg",
+};
+#endif
+
+static Ttk_StateTable checkbutton_states[] = {
+ { 0, 0, TTK_STATE_SELECTED|TTK_STATE_DISABLED },
+ { 1, TTK_STATE_SELECTED, TTK_STATE_DISABLED },
+ { 2, TTK_STATE_DISABLED, TTK_STATE_SELECTED },
+ { 3, TTK_STATE_SELECTED|TTK_STATE_DISABLED, 0 },
+ { 0, 0, 0 }
+};
+
+static const char *const checkbutton_pixels[] = {
+ "AAAAAAAAAAAABAAAAAAAAAAAABAAAAAAAAAAAABAAAAAAAAAAAAB",
+ "AEEEEEEEEEECBAEEEEEEEEEECBAEEEEEEEEEECBAEEEEEEEEEECB",
+ "AEDDDDDDDDDCBAEDDDDDDDDDCBAEFFFFFFFFFCBAEFFFFFFFFFCB",
+ "AEDDDDDDDDDCBAEDDDDDDDGDCBAEFFFFFFFFFCBAEFFFFFFFHFCB",
+ "AEDDDDDDDDDCBAEDDDDDDGGDCBAEFFFFFFFFFCBAEFFFFFFHHFCB",
+ "AEDDDDDDDDDCBAEDGDDDGGGDCBAEFFFFFFFFFCBAEFHFFFHHHFCB",
+ "AEDDDDDDDDDCBAEDGGDGGGDDCBAEFFFFFFFFFCBAEFHHFHHHFFCB",
+ "AEDDDDDDDDDCBAEDGGGGGDDDCBAEFFFFFFFFFCBAEFHHHHHFFFCB",
+ "AEDDDDDDDDDCBAEDDGGGDDDDCBAEFFFFFFFFFCBAEFFHHHFFFFCB",
+ "AEDDDDDDDDDCBAEDDDGDDDDDCBAEFFFFFFFFFCBAEFFFHFFFFFCB",
+ "AEDDDDDDDDDCBAEDDDDDDDDDCBAEFFFFFFFFFCBAEFFFFFFFFFCB",
+ "ACCCCCCCCCCCBACCCCCCCCCCCBACCCCCCCCCCCBACCCCCCCCCCCB",
+ "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
+};
+
+static IndicatorSpec checkbutton_spec = {
+ 13, 13, 4, /* width, height, nimages */
+ checkbutton_pixels,
+ checkbutton_states
+};
+
+static Ttk_StateTable radiobutton_states[] = {
+ { 0, 0, TTK_STATE_SELECTED|TTK_STATE_DISABLED },
+ { 1, TTK_STATE_SELECTED, TTK_STATE_DISABLED },
+ { 2, TTK_STATE_DISABLED, TTK_STATE_SELECTED },
+ { 3, TTK_STATE_SELECTED|TTK_STATE_DISABLED, 0 },
+ { 0, 0, 0 }
+};
+
+static const char *const radiobutton_pixels[] = {
+ "FFFFAAAAFFFFFFFFFAAAAFFFFFFFFFAAAAFFFFFFFFFAAAAFFFFF",
+ "FFAAEEEEAAFFFFFAAEEEEAAFFFFFAAEEEEAAFFFFFAAEEEEAAFFF",
+ "FAEEDDDDEEBFFFAEEDDDDEEBFFFAEEFFFFEEBFFFAEEFFFFEEBFF",
+ "FAEDDDDDDCBFFFAEDDDDDDCBFFFAEFFFFFFCBFFFAEFFFFFFCBFF",
+ "AEDDDDDDDDCBFAEDDDGGDDDCBFAEFFFFFFFFCBFAEFFFHHFFFCBF",
+ "AEDDDDDDDDCBFAEDDGGGGDDCBFAEFFFFFFFFCBFAEFFHHHHFFCBF",
+ "AEDDDDDDDDCBFAEDDGGGGDDCBFAEFFFFFFFFCBFAEFFHHHHFFCBF",
+ "AEDDDDDDDDCBFAEDDDGGDDDCBFAEFFFFFFFFCBFAEFFFHHFFFCBF",
+ "FAEDDDDDDCBFFFAEDDDDDDCBFFFAEFFFFFFCBFFFAEFFFFFFCBFF",
+ "FACCDDDDCCBFFFACCDDDDCCBFFFACCFFFFCCBFFFACCFFFFCCBFF",
+ "FFBBCCCCBBFFFFFBBCCCCBBFFFFFBBCCCCBBFFFFFBBCCCCBBFFF",
+ "FFFFBBBBFFFFFFFFFBBBBFFFFFFFFFBBBBFFFFFFFFFBBBBFFFFF",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
+};
+
+static IndicatorSpec radiobutton_spec = {
+ 13, 13, 4, /* width, height, nimages */
+ radiobutton_pixels,
+ radiobutton_states
+};
+
+typedef struct {
+ Tcl_Obj *backgroundObj;
+ Tcl_Obj *foregroundObj;
+ Tcl_Obj *colorObj;
+ Tcl_Obj *lightColorObj;
+ Tcl_Obj *shadeColorObj;
+ Tcl_Obj *borderColorObj;
+ Tcl_Obj *marginObj;
+} IndicatorElement;
+
+static Ttk_ElementOptionSpec IndicatorElementOptions[] = {
+ { "-background", TK_OPTION_COLOR,
+ Tk_Offset(IndicatorElement,backgroundObj), DEFAULT_BACKGROUND },
+ { "-foreground", TK_OPTION_COLOR,
+ Tk_Offset(IndicatorElement,foregroundObj), DEFAULT_FOREGROUND },
+ { "-indicatorcolor", TK_OPTION_COLOR,
+ Tk_Offset(IndicatorElement,colorObj), "#FFFFFF" },
+ { "-lightcolor", TK_OPTION_COLOR,
+ Tk_Offset(IndicatorElement,lightColorObj), "#DDDDDD" },
+ { "-shadecolor", TK_OPTION_COLOR,
+ Tk_Offset(IndicatorElement,shadeColorObj), "#888888" },
+ { "-bordercolor", TK_OPTION_COLOR,
+ Tk_Offset(IndicatorElement,borderColorObj), "black" },
+ { "-indicatormargin", TK_OPTION_STRING,
+ Tk_Offset(IndicatorElement,marginObj), "0 2 4 2" },
+ { NULL, 0, 0, NULL }
+};
+
+static void IndicatorElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ IndicatorSpec *spec = clientData;
+ IndicatorElement *indicator = elementRecord;
+ Ttk_Padding margins;
+ Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &margins);
+ *widthPtr = spec->width + Ttk_PaddingWidth(margins);
+ *heightPtr = spec->height + Ttk_PaddingHeight(margins);
+}
+
+static void IndicatorElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ IndicatorSpec *spec = clientData;
+ IndicatorElement *indicator = elementRecord;
+ Display *display = Tk_Display(tkwin);
+ Ttk_Padding padding;
+ XColor *fgColor, *frameColor, *shadeColor, *indicatorColor, *borderColor;
+
+ int index, ix, iy;
+ XGCValues gcValues;
+ GC copyGC;
+ unsigned long imgColors[8];
+ XImage *img = NULL;
+
+ Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &padding);
+ b = Ttk_PadBox(b, padding);
+
+ if ( b.x < 0
+ || b.y < 0
+ || Tk_Width(tkwin) < b.x + spec->width
+ || Tk_Height(tkwin) < b.y + spec->height)
+ {
+ /* Oops! not enough room to display the image.
+ * Don't draw anything.
+ */
+ return;
+ }
+
+ /*
+ * Fill in imgColors palette:
+ *
+ * (SHOULD: take light and shade colors from the border object,
+ * but Tk doesn't provide easy access to these in the public API.)
+ */
+ fgColor = Tk_GetColorFromObj(tkwin, indicator->foregroundObj);
+ frameColor = Tk_GetColorFromObj(tkwin, indicator->backgroundObj);
+ shadeColor = Tk_GetColorFromObj(tkwin, indicator->shadeColorObj);
+ indicatorColor = Tk_GetColorFromObj(tkwin, indicator->colorObj);
+ borderColor = Tk_GetColorFromObj(tkwin, indicator->borderColorObj);
+
+ imgColors[0 /*A*/] = shadeColor->pixel;
+ imgColors[1 /*B*/] = indicatorColor->pixel;
+ imgColors[2 /*C*/] = frameColor->pixel;
+ imgColors[3 /*D*/] = indicatorColor->pixel;
+ imgColors[4 /*E*/] = borderColor->pixel;
+ imgColors[5 /*F*/] = frameColor->pixel;
+ imgColors[6 /*G*/] = fgColor->pixel;
+ imgColors[7 /*H*/] = fgColor->pixel;
+
+ /*
+ * Create a scratch buffer to store the image:
+ */
+
+#if defined(IGNORES_VISUAL)
+
+ /*
+ * Platforms which ignore the VisualInfo can use XCreateImage to get the
+ * scratch image. This is essential on macOS, where it is not safe to call
+ * XGetImage in a display procedure.
+ */
+
+ img = XCreateImage(display, NULL, 32, ZPixmap, 0, NULL,
+ (unsigned int)spec->width, (unsigned int)spec->height,
+ 0, 0);
+#else
+
+ /*
+ * This trick allows creating the scratch XImage without having to
+ * construct a VisualInfo.
+ */
+
+ img = XGetImage(display, d, 0, 0,
+ (unsigned int)spec->width, (unsigned int)spec->height,
+ AllPlanes, ZPixmap);
+#endif
+
+ if (img == NULL) {
+ return;
+ }
+
+#if defined(IGNORES_VISUAL)
+
+ img->data = ckalloc(img->bytes_per_line * img->height);
+ if (img->data == NULL) {
+ XDestroyImage(img);
+ return;
+ }
+
+#endif
+
+ /*
+ * Create the image, painting it into the XImage one pixel at a time.
+ */
+
+ index = Ttk_StateTableLookup(spec->map, state);
+ for (iy=0 ; iy<spec->height ; iy++) {
+ for (ix=0 ; ix<spec->width ; ix++) {
+ XPutPixel(img, ix, iy,
+ imgColors[spec->pixels[iy][index*spec->width+ix] - 'A'] );
+ }
+ }
+
+ /*
+ * Copy the image onto our target drawable surface.
+ */
+
+ memset(&gcValues, 0, sizeof(gcValues));
+ copyGC = Tk_GetGC(tkwin, 0, &gcValues);
+ TkPutImage(NULL, 0, display, d, copyGC, img, 0, 0, b.x, b.y,
+ spec->width, spec->height);
+
+ /*
+ * Tidy up.
+ */
+
+ Tk_FreeGC(display, copyGC);
+
+ /*
+ * Protect against the possibility that some future platform might
+ * not use the Tk memory manager in its implementation of XDestroyImage,
+ * even though that would be an extremely strange thing to do.
+ */
+
+#if defined(IGNORES_VISUAL)
+ ckfree(img->data);
+ img->data = NULL;
+#endif
+
+ XDestroyImage(img);
+}
+
+static Ttk_ElementSpec IndicatorElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(IndicatorElement),
+ IndicatorElementOptions,
+ IndicatorElementSize,
+ IndicatorElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ Arrow element(s).
+ *
+ * Draws a solid triangle, inside a box.
+ * clientData is an enum ArrowDirection pointer.
+ */
+
+static int ArrowElements[] = { ARROW_UP, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT };
+typedef struct {
+ Tcl_Obj *sizeObj;
+ Tcl_Obj *borderObj;
+ Tcl_Obj *borderColorObj; /* Extra color for borders */
+ Tcl_Obj *reliefObj;
+ Tcl_Obj *colorObj; /* Arrow color */
+} ArrowElement;
+
+static Ttk_ElementOptionSpec ArrowElementOptions[] = {
+ { "-arrowsize", TK_OPTION_PIXELS,
+ Tk_Offset(ArrowElement,sizeObj), STRINGIFY(SCROLLBAR_WIDTH) },
+ { "-background", TK_OPTION_BORDER,
+ Tk_Offset(ArrowElement,borderObj), DEFAULT_BACKGROUND },
+ { "-bordercolor", TK_OPTION_COLOR,
+ Tk_Offset(ArrowElement,borderColorObj), "black" },
+ { "-relief", TK_OPTION_RELIEF,
+ Tk_Offset(ArrowElement,reliefObj),"raised"},
+ { "-arrowcolor", TK_OPTION_COLOR,
+ Tk_Offset(ArrowElement,colorObj),"black"},
+ { NULL, 0, 0, NULL }
+};
+
+/*
+ * Note asymmetric padding:
+ * top/left padding is 1 less than bottom/right,
+ * since in this theme 2-pixel borders are asymmetric.
+ */
+static Ttk_Padding ArrowPadding = { 3,3,4,4 };
+
+static void ArrowElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ ArrowElement *arrow = elementRecord;
+ int direction = *(int *)clientData;
+ int width = SCROLLBAR_WIDTH;
+
+ Tk_GetPixelsFromObj(NULL, tkwin, arrow->sizeObj, &width);
+ width -= Ttk_PaddingWidth(ArrowPadding);
+ TtkArrowSize(width/2, direction, widthPtr, heightPtr);
+ *widthPtr += Ttk_PaddingWidth(ArrowPadding);
+ *heightPtr += Ttk_PaddingHeight(ArrowPadding);
+}
+
+static void ArrowElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ int direction = *(int *)clientData;
+ ArrowElement *arrow = elementRecord;
+ Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, arrow->borderObj);
+ XColor *borderColor = Tk_GetColorFromObj(tkwin, arrow->borderColorObj);
+ XColor *arrowColor = Tk_GetColorFromObj(tkwin, arrow->colorObj);
+ int relief = TK_RELIEF_RAISED;
+ int borderWidth = 2;
+
+ Tk_GetReliefFromObj(NULL, arrow->reliefObj, &relief);
+
+ Tk_Fill3DRectangle(
+ tkwin, d, border, b.x, b.y, b.width, b.height, 0, TK_RELIEF_FLAT);
+ DrawBorder(tkwin,d,border,borderColor,b,borderWidth,relief);
+
+ TtkFillArrow(Tk_Display(tkwin), d, Tk_GCForColor(arrowColor, d),
+ Ttk_PadBox(b, ArrowPadding), direction);
+}
+
+static Ttk_ElementSpec ArrowElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(ArrowElement),
+ ArrowElementOptions,
+ ArrowElementSize,
+ ArrowElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ Menubutton indicator:
+ * Draw an arrow in the direction where the menu will be posted.
+ */
+
+#define MENUBUTTON_ARROW_SIZE 5
+
+typedef struct {
+ Tcl_Obj *directionObj;
+ Tcl_Obj *sizeObj;
+ Tcl_Obj *colorObj;
+} MenubuttonArrowElement;
+
+static const char *directionStrings[] = { /* See also: button.c */
+ "above", "below", "left", "right", "flush", NULL
+};
+enum { POST_ABOVE, POST_BELOW, POST_LEFT, POST_RIGHT, POST_FLUSH };
+
+static Ttk_ElementOptionSpec MenubuttonArrowElementOptions[] = {
+ { "-direction", TK_OPTION_STRING,
+ Tk_Offset(MenubuttonArrowElement,directionObj), "below" },
+ { "-arrowsize", TK_OPTION_PIXELS,
+ Tk_Offset(MenubuttonArrowElement,sizeObj), STRINGIFY(MENUBUTTON_ARROW_SIZE)},
+ { "-arrowcolor",TK_OPTION_COLOR,
+ Tk_Offset(MenubuttonArrowElement,colorObj), "black"},
+ { NULL, 0, 0, NULL }
+};
+
+static Ttk_Padding MenubuttonArrowPadding = { 3, 0, 3, 0 };
+
+static void MenubuttonArrowElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ MenubuttonArrowElement *arrow = elementRecord;
+ int size = MENUBUTTON_ARROW_SIZE;
+ Tk_GetPixelsFromObj(NULL, tkwin, arrow->sizeObj, &size);
+ *widthPtr = *heightPtr = 2 * size + 1;
+ *widthPtr += Ttk_PaddingWidth(MenubuttonArrowPadding);
+ *heightPtr += Ttk_PaddingHeight(MenubuttonArrowPadding);
+}
+
+static void MenubuttonArrowElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ MenubuttonArrowElement *arrow = elementRecord;
+ XColor *arrowColor = Tk_GetColorFromObj(tkwin, arrow->colorObj);
+ GC gc = Tk_GCForColor(arrowColor, d);
+ int size = MENUBUTTON_ARROW_SIZE;
+ int postDirection = POST_BELOW;
+ ArrowDirection arrowDirection = ARROW_DOWN;
+ int width = 0, height = 0;
+
+ Tk_GetPixelsFromObj(NULL, tkwin, arrow->sizeObj, &size);
+ Tcl_GetIndexFromObjStruct(NULL, arrow->directionObj, directionStrings,
+ sizeof(char *), ""/*message*/, 0/*flags*/, &postDirection);
+
+ /* ... this might not be such a great idea ... */
+ switch (postDirection) {
+ case POST_ABOVE: arrowDirection = ARROW_UP; break;
+ case POST_BELOW: arrowDirection = ARROW_DOWN; break;
+ case POST_LEFT: arrowDirection = ARROW_LEFT; break;
+ case POST_RIGHT: arrowDirection = ARROW_RIGHT; break;
+ case POST_FLUSH: arrowDirection = ARROW_DOWN; break;
+ }
+
+ TtkArrowSize(size, arrowDirection, &width, &height);
+ b = Ttk_PadBox(b, MenubuttonArrowPadding);
+ b = Ttk_AnchorBox(b, width, height, TK_ANCHOR_CENTER);
+ TtkFillArrow(Tk_Display(tkwin), d, gc, b, arrowDirection);
+}
+
+static Ttk_ElementSpec MenubuttonArrowElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(MenubuttonArrowElement),
+ MenubuttonArrowElementOptions,
+ MenubuttonArrowElementSize,
+ MenubuttonArrowElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ Trough element
+ *
+ * Used in scrollbars and the scale.
+ *
+ * The -groovewidth option can be used to set the size of the short axis
+ * for the drawn area. This will not affect the geometry, but can be used
+ * to draw a thin centered trough inside the packet alloted. This is used
+ * to show a win32-style scale widget. Use -1 or a large number to use the
+ * full area (default).
+ *
+ */
+
+typedef struct {
+ Tcl_Obj *colorObj;
+ Tcl_Obj *borderWidthObj;
+ Tcl_Obj *reliefObj;
+ Tcl_Obj *grooveWidthObj;
+ Tcl_Obj *orientObj;
+} TroughElement;
+
+static Ttk_ElementOptionSpec TroughElementOptions[] = {
+ { "-orient", TK_OPTION_ANY,
+ Tk_Offset(TroughElement, orientObj), "horizontal" },
+ { "-troughborderwidth", TK_OPTION_PIXELS,
+ Tk_Offset(TroughElement,borderWidthObj), "1" },
+ { "-troughcolor", TK_OPTION_BORDER,
+ Tk_Offset(TroughElement,colorObj), DEFAULT_BACKGROUND },
+ { "-troughrelief",TK_OPTION_RELIEF,
+ Tk_Offset(TroughElement,reliefObj), "sunken" },
+ { "-groovewidth", TK_OPTION_PIXELS,
+ Tk_Offset(TroughElement,grooveWidthObj), "-1" },
+ { NULL, 0, 0, NULL }
+};
+
+static void TroughElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ TroughElement *troughPtr = elementRecord;
+ int borderWidth = 2, grooveWidth = 0;
+
+ Tk_GetPixelsFromObj(NULL, tkwin, troughPtr->borderWidthObj, &borderWidth);
+ Tk_GetPixelsFromObj(NULL, tkwin, troughPtr->grooveWidthObj, &grooveWidth);
+
+ if (grooveWidth <= 0) {
+ *paddingPtr = Ttk_UniformPadding((short)borderWidth);
+ }
+}
+
+static void TroughElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ TroughElement *troughPtr = elementRecord;
+ Tk_3DBorder border = NULL;
+ int borderWidth = 2, relief = TK_RELIEF_SUNKEN, groove = -1, orient;
+
+ border = Tk_Get3DBorderFromObj(tkwin, troughPtr->colorObj);
+ Ttk_GetOrientFromObj(NULL, troughPtr->orientObj, &orient);
+ Tk_GetReliefFromObj(NULL, troughPtr->reliefObj, &relief);
+ Tk_GetPixelsFromObj(NULL, tkwin, troughPtr->borderWidthObj, &borderWidth);
+ Tk_GetPixelsFromObj(NULL, tkwin, troughPtr->grooveWidthObj, &groove);
+
+ if (groove != -1 && groove < b.height && groove < b.width) {
+ if (orient == TTK_ORIENT_HORIZONTAL) {
+ b.y = b.y + b.height/2 - groove/2;
+ b.height = groove;
+ } else {
+ b.x = b.x + b.width/2 - groove/2;
+ b.width = groove;
+ }
+ }
+
+ Tk_Fill3DRectangle(tkwin, d, border, b.x, b.y, b.width, b.height,
+ borderWidth, relief);
+}
+
+static Ttk_ElementSpec TroughElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(TroughElement),
+ TroughElementOptions,
+ TroughElementSize,
+ TroughElementDraw
+};
+
+/*
+ *----------------------------------------------------------------------
+ * +++ Thumb element.
+ */
+
+typedef struct {
+ Tcl_Obj *sizeObj;
+ Tcl_Obj *firstObj;
+ Tcl_Obj *lastObj;
+ Tcl_Obj *borderObj;
+ Tcl_Obj *borderColorObj;
+ Tcl_Obj *reliefObj;
+ Tcl_Obj *orientObj;
+} ThumbElement;
+
+static Ttk_ElementOptionSpec ThumbElementOptions[] = {
+ { "-width", TK_OPTION_PIXELS, Tk_Offset(ThumbElement,sizeObj),
+ STRINGIFY(SCROLLBAR_WIDTH) },
+ { "-background", TK_OPTION_BORDER, Tk_Offset(ThumbElement,borderObj),
+ DEFAULT_BACKGROUND },
+ { "-bordercolor", TK_OPTION_COLOR, Tk_Offset(ThumbElement,borderColorObj),
+ "black" },
+ { "-relief", TK_OPTION_RELIEF,Tk_Offset(ThumbElement,reliefObj),"raised" },
+ { "-orient", TK_OPTION_ANY,Tk_Offset(ThumbElement,orientObj),"horizontal"},
+ { NULL, 0, 0, NULL }
+};
+
+static void ThumbElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ ThumbElement *thumb = elementRecord;
+ int orient, size;
+ Tk_GetPixelsFromObj(NULL, tkwin, thumb->sizeObj, &size);
+ Ttk_GetOrientFromObj(NULL, thumb->orientObj, &orient);
+
+ if (orient == TTK_ORIENT_VERTICAL) {
+ *widthPtr = size;
+ *heightPtr = MIN_THUMB_SIZE;
+ } else {
+ *widthPtr = MIN_THUMB_SIZE;
+ *heightPtr = size;
+ }
+}
+
+static void ThumbElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ ThumbElement *thumb = elementRecord;
+ Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, thumb->borderObj);
+ XColor *borderColor = Tk_GetColorFromObj(tkwin, thumb->borderColorObj);
+ int relief = TK_RELIEF_RAISED;
+ int borderWidth = 2;
+
+ /*
+ * Don't draw the thumb if we are disabled.
+ * This makes it behave like Windows ... if that's what we want.
+ if (state & TTK_STATE_DISABLED)
+ return;
+ */
+
+ Tk_GetReliefFromObj(NULL, thumb->reliefObj, &relief);
+
+ Tk_Fill3DRectangle(
+ tkwin, d, border, b.x,b.y,b.width,b.height, 0, TK_RELIEF_FLAT);
+ DrawBorder(tkwin, d, border, borderColor, b, borderWidth, relief);
+}
+
+static Ttk_ElementSpec ThumbElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(ThumbElement),
+ ThumbElementOptions,
+ ThumbElementSize,
+ ThumbElementDraw
+};
+
+/*
+ *----------------------------------------------------------------------
+ * +++ Slider element.
+ *
+ * This is the moving part of the scale widget.
+ *
+ * The slider element is the thumb in the scale widget. This is drawn
+ * as an arrow-type element that can point up, down, left or right.
+ *
+ */
+
+typedef struct {
+ Tcl_Obj *lengthObj; /* Long axis dimension */
+ Tcl_Obj *thicknessObj; /* Short axis dimension */
+ Tcl_Obj *reliefObj; /* Relief for this object */
+ Tcl_Obj *borderObj; /* Border / background color */
+ Tcl_Obj *borderColorObj; /* Additional border color */
+ Tcl_Obj *borderWidthObj;
+ Tcl_Obj *orientObj; /* Orientation of overall slider */
+} SliderElement;
+
+static Ttk_ElementOptionSpec SliderElementOptions[] = {
+ { "-sliderlength", TK_OPTION_PIXELS, Tk_Offset(SliderElement,lengthObj),
+ "15" },
+ { "-sliderthickness",TK_OPTION_PIXELS,Tk_Offset(SliderElement,thicknessObj),
+ "15" },
+ { "-sliderrelief", TK_OPTION_RELIEF, Tk_Offset(SliderElement,reliefObj),
+ "raised" },
+ { "-borderwidth", TK_OPTION_PIXELS, Tk_Offset(SliderElement,borderWidthObj),
+ STRINGIFY(BORDERWIDTH) },
+ { "-background", TK_OPTION_BORDER, Tk_Offset(SliderElement,borderObj),
+ DEFAULT_BACKGROUND },
+ { "-bordercolor", TK_OPTION_COLOR, Tk_Offset(ThumbElement,borderColorObj),
+ "black" },
+ { "-orient", TK_OPTION_ANY, Tk_Offset(SliderElement,orientObj),
+ "horizontal" },
+ { NULL, 0, 0, NULL }
+};
+
+static void SliderElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ SliderElement *slider = elementRecord;
+ int orient, length, thickness, borderWidth;
+
+ Ttk_GetOrientFromObj(NULL, slider->orientObj, &orient);
+ Tk_GetPixelsFromObj(NULL, tkwin, slider->borderWidthObj, &borderWidth);
+ Tk_GetPixelsFromObj(NULL, tkwin, slider->lengthObj, &length);
+ Tk_GetPixelsFromObj(NULL, tkwin, slider->thicknessObj, &thickness);
+
+ switch (orient) {
+ case TTK_ORIENT_VERTICAL:
+ *widthPtr = thickness + (borderWidth *2);
+ *heightPtr = *widthPtr/2;
+ break;
+
+ case TTK_ORIENT_HORIZONTAL:
+ *heightPtr = thickness + (borderWidth *2);
+ *widthPtr = *heightPtr/2;
+ break;
+ }
+}
+
+static void SliderElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ SliderElement *slider = elementRecord;
+ Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, slider->borderObj);
+ XColor *borderColor = Tk_GetColorFromObj(tkwin, slider->borderColorObj);
+ int relief = TK_RELIEF_RAISED, borderWidth = 2;
+
+ Tk_GetPixelsFromObj(NULL, tkwin, slider->borderWidthObj, &borderWidth);
+ Tk_GetReliefFromObj(NULL, slider->reliefObj, &relief);
+
+ Tk_Fill3DRectangle(tkwin, d, border,
+ b.x, b.y, b.width, b.height,
+ borderWidth, TK_RELIEF_FLAT);
+ DrawBorder(tkwin, d, border, borderColor, b, borderWidth, relief);
+}
+
+static Ttk_ElementSpec SliderElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(SliderElement),
+ SliderElementOptions,
+ SliderElementSize,
+ SliderElementDraw
+};
+
+/*------------------------------------------------------------------------
+ * +++ Tree indicator element.
+ */
+
+#define TTK_STATE_OPEN TTK_STATE_USER1 /* XREF: treeview.c */
+#define TTK_STATE_LEAF TTK_STATE_USER2
+
+typedef struct {
+ Tcl_Obj *colorObj;
+ Tcl_Obj *marginObj;
+ Tcl_Obj *diameterObj;
+} TreeitemIndicator;
+
+static Ttk_ElementOptionSpec TreeitemIndicatorOptions[] = {
+ { "-foreground", TK_OPTION_COLOR,
+ Tk_Offset(TreeitemIndicator,colorObj), DEFAULT_FOREGROUND },
+ { "-diameter", TK_OPTION_PIXELS,
+ Tk_Offset(TreeitemIndicator,diameterObj), "9" },
+ { "-indicatormargins", TK_OPTION_STRING,
+ Tk_Offset(TreeitemIndicator,marginObj), "2 2 4 2" },
+ { NULL, 0, 0, NULL }
+};
+
+static void TreeitemIndicatorSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ TreeitemIndicator *indicator = elementRecord;
+ int diameter = 0;
+ Ttk_Padding margins;
+
+ Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &margins);
+ Tk_GetPixelsFromObj(NULL, tkwin, indicator->diameterObj, &diameter);
+ *widthPtr = diameter + Ttk_PaddingWidth(margins);
+ *heightPtr = diameter + Ttk_PaddingHeight(margins);
+}
+
+static void TreeitemIndicatorDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, Ttk_State state)
+{
+ TreeitemIndicator *indicator = elementRecord;
+ XColor *color = Tk_GetColorFromObj(tkwin, indicator->colorObj);
+ GC gc = Tk_GCForColor(color, d);
+ Ttk_Padding padding = Ttk_UniformPadding(0);
+ int w = WIN32_XDRAWLINE_HACK;
+ int cx, cy;
+
+ if (state & TTK_STATE_LEAF) {
+ /* don't draw anything ... */
+ return;
+ }
+
+ Ttk_GetPaddingFromObj(NULL,tkwin,indicator->marginObj,&padding);
+ b = Ttk_PadBox(b, padding);
+
+ XDrawRectangle(Tk_Display(tkwin), d, gc,
+ b.x, b.y, b.width - 1, b.height - 1);
+
+ cx = b.x + (b.width - 1) / 2;
+ cy = b.y + (b.height - 1) / 2;
+ XDrawLine(Tk_Display(tkwin), d, gc, b.x+2, cy, b.x+b.width-3+w, cy);
+
+ if (!(state & TTK_STATE_OPEN)) {
+ /* turn '-' into a '+' */
+ XDrawLine(Tk_Display(tkwin), d, gc, cx, b.y+2, cx, b.y+b.height-3+w);
+ }
+}
+
+static Ttk_ElementSpec TreeitemIndicatorElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(TreeitemIndicator),
+ TreeitemIndicatorOptions,
+ TreeitemIndicatorSize,
+ TreeitemIndicatorDraw
+};
+
+/*------------------------------------------------------------------------
+ * TtkAltTheme_Init --
+ * Install alternate theme.
+ */
+MODULE_SCOPE int TtkAltTheme_Init(Tcl_Interp *interp)
+{
+ Ttk_Theme theme = Ttk_CreateTheme(interp, "alt", NULL);
+
+ if (!theme) {
+ return TCL_ERROR;
+ }
+
+ Ttk_RegisterElement(interp, theme, "border", &BorderElementSpec, NULL);
+
+ Ttk_RegisterElement(interp, theme, "Checkbutton.indicator",
+ &IndicatorElementSpec, &checkbutton_spec);
+ Ttk_RegisterElement(interp, theme, "Radiobutton.indicator",
+ &IndicatorElementSpec, &radiobutton_spec);
+ Ttk_RegisterElement(interp, theme, "Menubutton.indicator",
+ &MenubuttonArrowElementSpec, NULL);
+
+ Ttk_RegisterElement(interp, theme, "field", &FieldElementSpec, NULL);
+
+ Ttk_RegisterElement(interp, theme, "trough", &TroughElementSpec, NULL);
+ Ttk_RegisterElement(interp, theme, "thumb", &ThumbElementSpec, NULL);
+ Ttk_RegisterElement(interp, theme, "slider", &SliderElementSpec, NULL);
+
+ Ttk_RegisterElement(interp, theme, "uparrow",
+ &ArrowElementSpec, &ArrowElements[0]);
+ Ttk_RegisterElement(interp, theme, "downarrow",
+ &ArrowElementSpec, &ArrowElements[1]);
+ Ttk_RegisterElement(interp, theme, "leftarrow",
+ &ArrowElementSpec, &ArrowElements[2]);
+ Ttk_RegisterElement(interp, theme, "rightarrow",
+ &ArrowElementSpec, &ArrowElements[3]);
+ Ttk_RegisterElement(interp, theme, "arrow",
+ &ArrowElementSpec, &ArrowElements[0]);
+
+ Ttk_RegisterElement(interp, theme, "arrow",
+ &ArrowElementSpec, &ArrowElements[0]);
+
+ Ttk_RegisterElement(interp, theme, "Treeitem.indicator",
+ &TreeitemIndicatorElementSpec, 0);
+
+ Tcl_PkgProvide(interp, "ttk::theme::alt", TTK_VERSION);
+
+ return TCL_OK;
+}
+
+/*EOF*/
diff --git a/tk8.6/generic/ttk/ttkElements.c b/tk8.6/generic/ttk/ttkElements.c
new file mode 100644
index 0000000..5c95dba
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkElements.c
@@ -0,0 +1,1281 @@
+/*
+ * Copyright (c) 2003, Joe English
+ *
+ * Default implementation for themed elements.
+ *
+ */
+
+#include <tcl.h>
+#include <tk.h>
+#include <string.h>
+#include "ttkTheme.h"
+#include "ttkWidget.h"
+
+#define DEFAULT_BORDERWIDTH "2"
+#define DEFAULT_ARROW_SIZE "15"
+#define MIN_THUMB_SIZE 10
+
+/*----------------------------------------------------------------------
+ * +++ Null element. Does nothing; used as a stub.
+ * Null element methods, option table and element spec are public,
+ * and may be used in other engines.
+ */
+
+/* public */ Ttk_ElementOptionSpec TtkNullElementOptions[] = { { NULL, 0, 0, NULL } };
+
+/* public */ void
+TtkNullElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+}
+
+/* public */ void
+TtkNullElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+}
+
+/* public */ Ttk_ElementSpec ttkNullElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(NullElement),
+ TtkNullElementOptions,
+ TtkNullElementSize,
+ TtkNullElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ Background and fill elements.
+ *
+ * The fill element fills its parcel with the background color.
+ * The background element ignores the parcel, and fills the entire window.
+ *
+ * Ttk_GetLayout() automatically includes a background element.
+ */
+
+typedef struct {
+ Tcl_Obj *backgroundObj;
+} BackgroundElement;
+
+static Ttk_ElementOptionSpec BackgroundElementOptions[] = {
+ { "-background", TK_OPTION_BORDER,
+ Tk_Offset(BackgroundElement,backgroundObj), DEFAULT_BACKGROUND },
+ { NULL, 0, 0, NULL }
+};
+
+static void FillElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ BackgroundElement *bg = elementRecord;
+ Tk_3DBorder backgroundPtr = Tk_Get3DBorderFromObj(tkwin,bg->backgroundObj);
+
+ XFillRectangle(Tk_Display(tkwin), d,
+ Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC),
+ b.x, b.y, b.width, b.height);
+}
+
+static void BackgroundElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ FillElementDraw(
+ clientData, elementRecord, tkwin,
+ d, Ttk_WinBox(tkwin), state);
+}
+
+static Ttk_ElementSpec FillElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(BackgroundElement),
+ BackgroundElementOptions,
+ TtkNullElementSize,
+ FillElementDraw
+};
+
+static Ttk_ElementSpec BackgroundElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(BackgroundElement),
+ BackgroundElementOptions,
+ TtkNullElementSize,
+ BackgroundElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ Border element.
+ */
+
+typedef struct {
+ Tcl_Obj *borderObj;
+ Tcl_Obj *borderWidthObj;
+ Tcl_Obj *reliefObj;
+} BorderElement;
+
+static Ttk_ElementOptionSpec BorderElementOptions[] = {
+ { "-background", TK_OPTION_BORDER,
+ Tk_Offset(BorderElement,borderObj), DEFAULT_BACKGROUND },
+ { "-borderwidth", TK_OPTION_PIXELS,
+ Tk_Offset(BorderElement,borderWidthObj), DEFAULT_BORDERWIDTH },
+ { "-relief", TK_OPTION_RELIEF,
+ Tk_Offset(BorderElement,reliefObj), "flat" },
+ { NULL, 0, 0, NULL }
+};
+
+static void BorderElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ BorderElement *bd = elementRecord;
+ int borderWidth = 0;
+ Tcl_GetIntFromObj(NULL, bd->borderWidthObj, &borderWidth);
+ *paddingPtr = Ttk_UniformPadding((short)borderWidth);
+}
+
+static void BorderElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ BorderElement *bd = elementRecord;
+ Tk_3DBorder border = NULL;
+ int borderWidth = 1, relief = TK_RELIEF_FLAT;
+
+ border = Tk_Get3DBorderFromObj(tkwin, bd->borderObj);
+ Tcl_GetIntFromObj(NULL, bd->borderWidthObj, &borderWidth);
+ Tk_GetReliefFromObj(NULL, bd->reliefObj, &relief);
+
+ if (border && borderWidth > 0 && relief != TK_RELIEF_FLAT) {
+ Tk_Draw3DRectangle(tkwin, d, border,
+ b.x, b.y, b.width, b.height, borderWidth,relief);
+ }
+}
+
+static Ttk_ElementSpec BorderElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(BorderElement),
+ BorderElementOptions,
+ BorderElementSize,
+ BorderElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ Field element.
+ * Used for editable fields.
+ */
+typedef struct {
+ Tcl_Obj *borderObj;
+ Tcl_Obj *borderWidthObj;
+} FieldElement;
+
+static Ttk_ElementOptionSpec FieldElementOptions[] = {
+ { "-fieldbackground", TK_OPTION_BORDER,
+ Tk_Offset(FieldElement,borderObj), "white" },
+ { "-borderwidth", TK_OPTION_PIXELS,
+ Tk_Offset(FieldElement,borderWidthObj), "2" },
+ { NULL, 0, 0, NULL }
+};
+
+static void FieldElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ FieldElement *field = elementRecord;
+ int borderWidth = 2;
+ Tk_GetPixelsFromObj(NULL, tkwin, field->borderWidthObj, &borderWidth);
+ *paddingPtr = Ttk_UniformPadding((short)borderWidth);
+}
+
+static void FieldElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ FieldElement *field = elementRecord;
+ Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, field->borderObj);
+ int borderWidth = 2;
+
+ Tk_GetPixelsFromObj(NULL, tkwin, field->borderWidthObj, &borderWidth);
+ Tk_Fill3DRectangle(tkwin, d, border,
+ b.x, b.y, b.width, b.height, borderWidth, TK_RELIEF_SUNKEN);
+}
+
+static Ttk_ElementSpec FieldElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(FieldElement),
+ FieldElementOptions,
+ FieldElementSize,
+ FieldElementDraw
+};
+
+/*
+ *----------------------------------------------------------------------
+ * +++ Padding element.
+ *
+ * This element has no visual representation, only geometry.
+ * It adds a (possibly non-uniform) internal border.
+ * In addition, if "-shiftrelief" is specified,
+ * adds additional pixels to shift child elements "in" or "out"
+ * depending on the -relief.
+ */
+
+typedef struct {
+ Tcl_Obj *paddingObj;
+ Tcl_Obj *reliefObj;
+ Tcl_Obj *shiftreliefObj;
+} PaddingElement;
+
+static Ttk_ElementOptionSpec PaddingElementOptions[] = {
+ { "-padding", TK_OPTION_STRING,
+ Tk_Offset(PaddingElement,paddingObj), "0" },
+ { "-relief", TK_OPTION_RELIEF,
+ Tk_Offset(PaddingElement,reliefObj), "flat" },
+ { "-shiftrelief", TK_OPTION_INT,
+ Tk_Offset(PaddingElement,shiftreliefObj), "0" },
+ { NULL, 0, 0, NULL }
+};
+
+static void PaddingElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ PaddingElement *padding = elementRecord;
+ int shiftRelief = 0;
+ int relief = TK_RELIEF_FLAT;
+ Ttk_Padding pad;
+
+ Tk_GetReliefFromObj(NULL, padding->reliefObj, &relief);
+ Tcl_GetIntFromObj(NULL, padding->shiftreliefObj, &shiftRelief);
+ Ttk_GetPaddingFromObj(NULL,tkwin,padding->paddingObj,&pad);
+ *paddingPtr = Ttk_RelievePadding(pad, relief, shiftRelief);
+}
+
+static Ttk_ElementSpec PaddingElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(PaddingElement),
+ PaddingElementOptions,
+ PaddingElementSize,
+ TtkNullElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ Focus ring element.
+ * Draws a dashed focus ring, if the widget has keyboard focus.
+ */
+typedef struct {
+ Tcl_Obj *focusColorObj;
+ Tcl_Obj *focusThicknessObj;
+} FocusElement;
+
+/*
+ * DrawFocusRing --
+ * Draw a dotted rectangle to indicate focus.
+ */
+static void DrawFocusRing(
+ Tk_Window tkwin, Drawable d, Tcl_Obj *colorObj, Ttk_Box b)
+{
+ XColor *color = Tk_GetColorFromObj(tkwin, colorObj);
+ unsigned long mask = 0UL;
+ XGCValues gcvalues;
+ GC gc;
+
+ gcvalues.foreground = color->pixel;
+ gcvalues.line_style = LineOnOffDash;
+ gcvalues.line_width = 1;
+ gcvalues.dashes = 1;
+ gcvalues.dash_offset = 1;
+ mask = GCForeground | GCLineStyle | GCDashList | GCDashOffset | GCLineWidth;
+
+ gc = Tk_GetGC(tkwin, mask, &gcvalues);
+ XDrawRectangle(Tk_Display(tkwin), d, gc, b.x, b.y, b.width-1, b.height-1);
+ Tk_FreeGC(Tk_Display(tkwin), gc);
+}
+
+static Ttk_ElementOptionSpec FocusElementOptions[] = {
+ { "-focuscolor",TK_OPTION_COLOR,
+ Tk_Offset(FocusElement,focusColorObj), "black" },
+ { "-focusthickness",TK_OPTION_PIXELS,
+ Tk_Offset(FocusElement,focusThicknessObj), "1" },
+ { NULL, 0, 0, NULL }
+};
+
+static void FocusElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ FocusElement *focus = elementRecord;
+ int focusThickness = 0;
+
+ Tcl_GetIntFromObj(NULL, focus->focusThicknessObj, &focusThickness);
+ *paddingPtr = Ttk_UniformPadding((short)focusThickness);
+}
+
+static void FocusElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ FocusElement *focus = elementRecord;
+ int focusThickness = 0;
+
+ if (state & TTK_STATE_FOCUS) {
+ Tcl_GetIntFromObj(NULL,focus->focusThicknessObj,&focusThickness);
+ DrawFocusRing(tkwin, d, focus->focusColorObj, b);
+ }
+}
+
+static Ttk_ElementSpec FocusElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(FocusElement),
+ FocusElementOptions,
+ FocusElementSize,
+ FocusElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ Separator element.
+ * Just draws a horizontal or vertical bar.
+ * Three elements are defined: horizontal, vertical, and general;
+ * the general separator checks the "-orient" option.
+ */
+
+typedef struct {
+ Tcl_Obj *orientObj;
+ Tcl_Obj *borderObj;
+} SeparatorElement;
+
+static Ttk_ElementOptionSpec SeparatorElementOptions[] = {
+ { "-orient", TK_OPTION_ANY,
+ Tk_Offset(SeparatorElement, orientObj), "horizontal" },
+ { "-background", TK_OPTION_BORDER,
+ Tk_Offset(SeparatorElement,borderObj), DEFAULT_BACKGROUND },
+ { NULL, 0, 0, NULL }
+};
+
+static void SeparatorElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ *widthPtr = *heightPtr = 2;
+}
+
+static void HorizontalSeparatorElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ SeparatorElement *separator = elementRecord;
+ Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, separator->borderObj);
+ GC lightGC = Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC);
+ GC darkGC = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC);
+
+ XDrawLine(Tk_Display(tkwin), d, darkGC, b.x, b.y, b.x + b.width, b.y);
+ XDrawLine(Tk_Display(tkwin), d, lightGC, b.x, b.y+1, b.x + b.width, b.y+1);
+}
+
+static void VerticalSeparatorElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ SeparatorElement *separator = elementRecord;
+ Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, separator->borderObj);
+ GC lightGC = Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC);
+ GC darkGC = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC);
+
+ XDrawLine(Tk_Display(tkwin), d, darkGC, b.x, b.y, b.x, b.y + b.height);
+ XDrawLine(Tk_Display(tkwin), d, lightGC, b.x+1, b.y, b.x+1, b.y+b.height);
+}
+
+static void GeneralSeparatorElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ SeparatorElement *separator = elementRecord;
+ int orient;
+ Ttk_GetOrientFromObj(NULL, separator->orientObj, &orient);
+ switch (orient) {
+ case TTK_ORIENT_HORIZONTAL:
+ HorizontalSeparatorElementDraw(
+ clientData, elementRecord, tkwin, d, b, state);
+ break;
+ case TTK_ORIENT_VERTICAL:
+ VerticalSeparatorElementDraw(
+ clientData, elementRecord, tkwin, d, b, state);
+ break;
+ }
+}
+
+static Ttk_ElementSpec HorizontalSeparatorElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(SeparatorElement),
+ SeparatorElementOptions,
+ SeparatorElementSize,
+ HorizontalSeparatorElementDraw
+};
+
+static Ttk_ElementSpec VerticalSeparatorElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(SeparatorElement),
+ SeparatorElementOptions,
+ SeparatorElementSize,
+ HorizontalSeparatorElementDraw
+};
+
+static Ttk_ElementSpec SeparatorElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(SeparatorElement),
+ SeparatorElementOptions,
+ SeparatorElementSize,
+ GeneralSeparatorElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ Sizegrip: lower-right corner grip handle for resizing window.
+ */
+
+typedef struct {
+ Tcl_Obj *backgroundObj;
+} SizegripElement;
+
+static Ttk_ElementOptionSpec SizegripOptions[] = {
+ { "-background", TK_OPTION_BORDER,
+ Tk_Offset(SizegripElement,backgroundObj), DEFAULT_BACKGROUND },
+ {0,0,0,0}
+};
+
+static void SizegripSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ int gripCount = 3, gripSpace = 2, gripThickness = 3;
+ *widthPtr = *heightPtr = gripCount * (gripSpace + gripThickness);
+}
+
+static void SizegripDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, Ttk_State state)
+{
+ SizegripElement *grip = elementRecord;
+ int gripCount = 3, gripSpace = 2;
+ Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, grip->backgroundObj);
+ GC lightGC = Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC);
+ GC darkGC = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC);
+ int x1 = b.x + b.width-1, y1 = b.y + b.height-1, x2 = x1, y2 = y1;
+
+ while (gripCount--) {
+ x1 -= gripSpace; y2 -= gripSpace;
+ XDrawLine(Tk_Display(tkwin), d, darkGC, x1,y1, x2,y2); --x1; --y2;
+ XDrawLine(Tk_Display(tkwin), d, darkGC, x1,y1, x2,y2); --x1; --y2;
+ XDrawLine(Tk_Display(tkwin), d, lightGC, x1,y1, x2,y2); --x1; --y2;
+ }
+}
+
+static Ttk_ElementSpec SizegripElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(SizegripElement),
+ SizegripOptions,
+ SizegripSize,
+ SizegripDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ Indicator element.
+ *
+ * Draws the on/off indicator for checkbuttons and radiobuttons.
+ *
+ * Draws a 3-D square (or diamond), raised if off, sunken if on.
+ *
+ * This is actually a regression from Tk 8.5 back to the ugly old Motif
+ * style; use "altTheme" for the newer, nicer version.
+ */
+
+typedef struct {
+ Tcl_Obj *backgroundObj;
+ Tcl_Obj *reliefObj;
+ Tcl_Obj *colorObj;
+ Tcl_Obj *diameterObj;
+ Tcl_Obj *marginObj;
+ Tcl_Obj *borderWidthObj;
+} IndicatorElement;
+
+static Ttk_ElementOptionSpec IndicatorElementOptions[] = {
+ { "-background", TK_OPTION_BORDER,
+ Tk_Offset(IndicatorElement,backgroundObj), DEFAULT_BACKGROUND },
+ { "-indicatorcolor", TK_OPTION_BORDER,
+ Tk_Offset(IndicatorElement,colorObj), DEFAULT_BACKGROUND },
+ { "-indicatorrelief", TK_OPTION_RELIEF,
+ Tk_Offset(IndicatorElement,reliefObj), "raised" },
+ { "-indicatordiameter", TK_OPTION_PIXELS,
+ Tk_Offset(IndicatorElement,diameterObj), "12" },
+ { "-indicatormargin", TK_OPTION_STRING,
+ Tk_Offset(IndicatorElement,marginObj), "0 2 4 2" },
+ { "-borderwidth", TK_OPTION_PIXELS,
+ Tk_Offset(IndicatorElement,borderWidthObj), DEFAULT_BORDERWIDTH },
+ { NULL, 0, 0, NULL }
+};
+
+/*
+ * Checkbutton indicators (default): 3-D square.
+ */
+static void SquareIndicatorElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ IndicatorElement *indicator = elementRecord;
+ Ttk_Padding margins;
+ int diameter = 0;
+ Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &margins);
+ Tk_GetPixelsFromObj(NULL, tkwin, indicator->diameterObj, &diameter);
+ *widthPtr = diameter + Ttk_PaddingWidth(margins);
+ *heightPtr = diameter + Ttk_PaddingHeight(margins);
+}
+
+static void SquareIndicatorElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ IndicatorElement *indicator = elementRecord;
+ Tk_3DBorder border = 0, interior = 0;
+ int relief = TK_RELIEF_RAISED;
+ Ttk_Padding padding;
+ int borderWidth = 2;
+ int diameter;
+
+ interior = Tk_Get3DBorderFromObj(tkwin, indicator->colorObj);
+ border = Tk_Get3DBorderFromObj(tkwin, indicator->backgroundObj);
+ Tcl_GetIntFromObj(NULL,indicator->borderWidthObj,&borderWidth);
+ Tk_GetReliefFromObj(NULL,indicator->reliefObj,&relief);
+ Ttk_GetPaddingFromObj(NULL,tkwin,indicator->marginObj,&padding);
+
+ b = Ttk_PadBox(b, padding);
+
+ diameter = b.width < b.height ? b.width : b.height;
+ Tk_Fill3DRectangle(tkwin, d, interior, b.x, b.y,
+ diameter, diameter,borderWidth, TK_RELIEF_FLAT);
+ Tk_Draw3DRectangle(tkwin, d, border, b.x, b.y,
+ diameter, diameter, borderWidth, relief);
+}
+
+/*
+ * Radiobutton indicators: 3-D diamond.
+ */
+static void DiamondIndicatorElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ IndicatorElement *indicator = elementRecord;
+ Ttk_Padding margins;
+ int diameter = 0;
+ Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &margins);
+ Tk_GetPixelsFromObj(NULL, tkwin, indicator->diameterObj, &diameter);
+ *widthPtr = diameter + 3 + Ttk_PaddingWidth(margins);
+ *heightPtr = diameter + 3 + Ttk_PaddingHeight(margins);
+}
+
+static void DiamondIndicatorElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ IndicatorElement *indicator = elementRecord;
+ Tk_3DBorder border = 0, interior = 0;
+ int borderWidth = 2;
+ int relief = TK_RELIEF_RAISED;
+ int diameter, radius;
+ XPoint points[4];
+ Ttk_Padding padding;
+
+ interior = Tk_Get3DBorderFromObj(tkwin, indicator->colorObj);
+ border = Tk_Get3DBorderFromObj(tkwin, indicator->backgroundObj);
+ Tcl_GetIntFromObj(NULL,indicator->borderWidthObj,&borderWidth);
+ Tk_GetReliefFromObj(NULL,indicator->reliefObj,&relief);
+ Ttk_GetPaddingFromObj(NULL,tkwin,indicator->marginObj,&padding);
+
+ b = Ttk_PadBox(b, padding);
+
+ diameter = b.width < b.height ? b.width : b.height;
+ radius = diameter / 2;
+
+ points[0].x = b.x;
+ points[0].y = b.y + radius;
+ points[1].x = b.x + radius;
+ points[1].y = b.y + 2*radius;
+ points[2].x = b.x + 2*radius;
+ points[2].y = b.y + radius;
+ points[3].x = b.x + radius;
+ points[3].y = b.y;
+
+ Tk_Fill3DPolygon(tkwin,d,interior,points,4,borderWidth,TK_RELIEF_FLAT);
+ Tk_Draw3DPolygon(tkwin,d,border,points,4,borderWidth,relief);
+}
+
+static Ttk_ElementSpec CheckbuttonIndicatorElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(IndicatorElement),
+ IndicatorElementOptions,
+ SquareIndicatorElementSize,
+ SquareIndicatorElementDraw
+};
+
+static Ttk_ElementSpec RadiobuttonIndicatorElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(IndicatorElement),
+ IndicatorElementOptions,
+ DiamondIndicatorElementSize,
+ DiamondIndicatorElementDraw
+};
+
+/*
+ *----------------------------------------------------------------------
+ * +++ Menubutton indicators.
+ *
+ * These aren't functional like radio/check indicators,
+ * they're just affordability indicators.
+ *
+ * Standard Tk sets the indicator size to 4.0 mm by 1.7 mm.
+ * I have no idea where these numbers came from.
+ */
+
+typedef struct {
+ Tcl_Obj *backgroundObj;
+ Tcl_Obj *widthObj;
+ Tcl_Obj *heightObj;
+ Tcl_Obj *borderWidthObj;
+ Tcl_Obj *reliefObj;
+ Tcl_Obj *marginObj;
+} MenuIndicatorElement;
+
+static Ttk_ElementOptionSpec MenuIndicatorElementOptions[] = {
+ { "-background", TK_OPTION_BORDER,
+ Tk_Offset(MenuIndicatorElement,backgroundObj), DEFAULT_BACKGROUND },
+ { "-indicatorwidth", TK_OPTION_PIXELS,
+ Tk_Offset(MenuIndicatorElement,widthObj), "4.0m" },
+ { "-indicatorheight", TK_OPTION_PIXELS,
+ Tk_Offset(MenuIndicatorElement,heightObj), "1.7m" },
+ { "-borderwidth", TK_OPTION_PIXELS,
+ Tk_Offset(MenuIndicatorElement,borderWidthObj), DEFAULT_BORDERWIDTH },
+ { "-indicatorrelief", TK_OPTION_RELIEF,
+ Tk_Offset(MenuIndicatorElement,reliefObj),"raised" },
+ { "-indicatormargin", TK_OPTION_STRING,
+ Tk_Offset(MenuIndicatorElement,marginObj), "5 0" },
+ { NULL, 0, 0, NULL }
+};
+
+static void MenuIndicatorElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ MenuIndicatorElement *mi = elementRecord;
+ Ttk_Padding margins;
+ Tk_GetPixelsFromObj(NULL, tkwin, mi->widthObj, widthPtr);
+ Tk_GetPixelsFromObj(NULL, tkwin, mi->heightObj, heightPtr);
+ Ttk_GetPaddingFromObj(NULL,tkwin,mi->marginObj, &margins);
+ *widthPtr += Ttk_PaddingWidth(margins);
+ *heightPtr += Ttk_PaddingHeight(margins);
+}
+
+static void MenuIndicatorElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ MenuIndicatorElement *mi = elementRecord;
+ Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, mi->backgroundObj);
+ Ttk_Padding margins;
+ int borderWidth = 2;
+
+ Ttk_GetPaddingFromObj(NULL,tkwin,mi->marginObj,&margins);
+ b = Ttk_PadBox(b, margins);
+ Tk_GetPixelsFromObj(NULL, tkwin, mi->borderWidthObj, &borderWidth);
+ Tk_Fill3DRectangle(tkwin, d, border, b.x, b.y, b.width, b.height,
+ borderWidth, TK_RELIEF_RAISED);
+}
+
+static Ttk_ElementSpec MenuIndicatorElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(MenuIndicatorElement),
+ MenuIndicatorElementOptions,
+ MenuIndicatorElementSize,
+ MenuIndicatorElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ Arrow elements.
+ *
+ * Draws a solid triangle inside a box.
+ * clientData is an enum ArrowDirection pointer.
+ */
+
+static int ArrowElements[] = { ARROW_UP, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT };
+typedef struct {
+ Tcl_Obj *borderObj;
+ Tcl_Obj *borderWidthObj;
+ Tcl_Obj *reliefObj;
+ Tcl_Obj *sizeObj;
+ Tcl_Obj *colorObj;
+} ArrowElement;
+
+static Ttk_ElementOptionSpec ArrowElementOptions[] = {
+ { "-background", TK_OPTION_BORDER,
+ Tk_Offset(ArrowElement,borderObj), DEFAULT_BACKGROUND },
+ { "-relief",TK_OPTION_RELIEF,
+ Tk_Offset(ArrowElement,reliefObj),"raised"},
+ { "-borderwidth", TK_OPTION_PIXELS,
+ Tk_Offset(ArrowElement,borderWidthObj), "1" },
+ { "-arrowcolor",TK_OPTION_COLOR,
+ Tk_Offset(ArrowElement,colorObj),"black"},
+ { "-arrowsize", TK_OPTION_PIXELS,
+ Tk_Offset(ArrowElement,sizeObj), "14" },
+ { NULL, 0, 0, NULL }
+};
+
+static Ttk_Padding ArrowMargins = { 3,3,3,3 };
+
+static void ArrowElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ ArrowElement *arrow = elementRecord;
+ int direction = *(int *)clientData;
+ int width = 14;
+
+ Tk_GetPixelsFromObj(NULL, tkwin, arrow->sizeObj, &width);
+ width -= Ttk_PaddingWidth(ArrowMargins);
+ TtkArrowSize(width/2, direction, widthPtr, heightPtr);
+ *widthPtr += Ttk_PaddingWidth(ArrowMargins);
+ *heightPtr += Ttk_PaddingWidth(ArrowMargins);
+}
+
+static void ArrowElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ int direction = *(int *)clientData;
+ ArrowElement *arrow = elementRecord;
+ Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, arrow->borderObj);
+ XColor *arrowColor = Tk_GetColorFromObj(tkwin, arrow->colorObj);
+ int relief = TK_RELIEF_RAISED;
+ int borderWidth = 1;
+
+ Tk_GetReliefFromObj(NULL, arrow->reliefObj, &relief);
+
+ Tk_Fill3DRectangle(
+ tkwin, d, border, b.x, b.y, b.width, b.height, borderWidth, relief);
+
+ TtkFillArrow(Tk_Display(tkwin), d, Tk_GCForColor(arrowColor, d),
+ Ttk_PadBox(b, ArrowMargins), direction);
+}
+
+static Ttk_ElementSpec ArrowElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(ArrowElement),
+ ArrowElementOptions,
+ ArrowElementSize,
+ ArrowElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ Trough element.
+ *
+ * Used in scrollbars and scales in place of "border".
+ */
+
+typedef struct {
+ Tcl_Obj *colorObj;
+ Tcl_Obj *borderWidthObj;
+ Tcl_Obj *reliefObj;
+} TroughElement;
+
+static Ttk_ElementOptionSpec TroughElementOptions[] = {
+ { "-borderwidth", TK_OPTION_PIXELS,
+ Tk_Offset(TroughElement,borderWidthObj), DEFAULT_BORDERWIDTH },
+ { "-troughcolor", TK_OPTION_BORDER,
+ Tk_Offset(TroughElement,colorObj), DEFAULT_BACKGROUND },
+ { "-troughrelief",TK_OPTION_RELIEF,
+ Tk_Offset(TroughElement,reliefObj), "sunken" },
+ { NULL, 0, 0, NULL }
+};
+
+static void TroughElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ TroughElement *troughPtr = elementRecord;
+ int borderWidth = 2;
+
+ Tk_GetPixelsFromObj(NULL, tkwin, troughPtr->borderWidthObj, &borderWidth);
+ *paddingPtr = Ttk_UniformPadding((short)borderWidth);
+}
+
+static void TroughElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ TroughElement *troughPtr = elementRecord;
+ Tk_3DBorder border = NULL;
+ int borderWidth = 2, relief = TK_RELIEF_SUNKEN;
+
+ border = Tk_Get3DBorderFromObj(tkwin, troughPtr->colorObj);
+ Tk_GetReliefFromObj(NULL, troughPtr->reliefObj, &relief);
+ Tk_GetPixelsFromObj(NULL, tkwin, troughPtr->borderWidthObj, &borderWidth);
+
+ Tk_Fill3DRectangle(tkwin, d, border, b.x, b.y, b.width, b.height,
+ borderWidth, relief);
+}
+
+static Ttk_ElementSpec TroughElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(TroughElement),
+ TroughElementOptions,
+ TroughElementSize,
+ TroughElementDraw
+};
+
+/*
+ *----------------------------------------------------------------------
+ * +++ Thumb element.
+ *
+ * Used in scrollbars.
+ */
+
+typedef struct {
+ Tcl_Obj *orientObj;
+ Tcl_Obj *thicknessObj;
+ Tcl_Obj *reliefObj;
+ Tcl_Obj *borderObj;
+ Tcl_Obj *borderWidthObj;
+} ThumbElement;
+
+static Ttk_ElementOptionSpec ThumbElementOptions[] = {
+ { "-orient", TK_OPTION_ANY,
+ Tk_Offset(ThumbElement, orientObj), "horizontal" },
+ { "-width", TK_OPTION_PIXELS,
+ Tk_Offset(ThumbElement,thicknessObj), DEFAULT_ARROW_SIZE },
+ { "-relief", TK_OPTION_RELIEF,
+ Tk_Offset(ThumbElement,reliefObj), "raised" },
+ { "-background", TK_OPTION_BORDER,
+ Tk_Offset(ThumbElement,borderObj), DEFAULT_BACKGROUND },
+ { "-borderwidth", TK_OPTION_PIXELS,
+ Tk_Offset(ThumbElement,borderWidthObj), DEFAULT_BORDERWIDTH },
+ { NULL, 0, 0, NULL }
+};
+
+static void ThumbElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ ThumbElement *thumb = elementRecord;
+ int orient, thickness;
+
+ Tk_GetPixelsFromObj(NULL, tkwin, thumb->thicknessObj, &thickness);
+ Ttk_GetOrientFromObj(NULL, thumb->orientObj, &orient);
+
+ if (orient == TTK_ORIENT_VERTICAL) {
+ *widthPtr = thickness;
+ *heightPtr = MIN_THUMB_SIZE;
+ } else {
+ *widthPtr = MIN_THUMB_SIZE;
+ *heightPtr = thickness;
+ }
+}
+
+static void ThumbElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ ThumbElement *thumb = elementRecord;
+ Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, thumb->borderObj);
+ int borderWidth = 2, relief = TK_RELIEF_RAISED;
+
+ Tk_GetPixelsFromObj(NULL, tkwin, thumb->borderWidthObj, &borderWidth);
+ Tk_GetReliefFromObj(NULL, thumb->reliefObj, &relief);
+ Tk_Fill3DRectangle(tkwin, d, border, b.x, b.y, b.width, b.height,
+ borderWidth, relief);
+}
+
+static Ttk_ElementSpec ThumbElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(ThumbElement),
+ ThumbElementOptions,
+ ThumbElementSize,
+ ThumbElementDraw
+};
+
+/*
+ *----------------------------------------------------------------------
+ * +++ Slider element.
+ *
+ * This is the moving part of the scale widget. Drawn as a raised box.
+ */
+
+typedef struct {
+ Tcl_Obj *orientObj; /* orientation of overall slider */
+ Tcl_Obj *lengthObj; /* slider length */
+ Tcl_Obj *thicknessObj; /* slider thickness */
+ Tcl_Obj *reliefObj; /* the relief for this object */
+ Tcl_Obj *borderObj; /* the background color */
+ Tcl_Obj *borderWidthObj; /* the size of the border */
+} SliderElement;
+
+static Ttk_ElementOptionSpec SliderElementOptions[] = {
+ { "-sliderlength", TK_OPTION_PIXELS, Tk_Offset(SliderElement,lengthObj),
+ "30" },
+ { "-sliderthickness",TK_OPTION_PIXELS,Tk_Offset(SliderElement,thicknessObj),
+ "15" },
+ { "-sliderrelief", TK_OPTION_RELIEF, Tk_Offset(SliderElement,reliefObj),
+ "raised" },
+ { "-borderwidth", TK_OPTION_PIXELS, Tk_Offset(SliderElement,borderWidthObj),
+ DEFAULT_BORDERWIDTH },
+ { "-background", TK_OPTION_BORDER, Tk_Offset(SliderElement,borderObj),
+ DEFAULT_BACKGROUND },
+ { "-orient", TK_OPTION_ANY, Tk_Offset(SliderElement,orientObj),
+ "horizontal" },
+ { NULL, 0, 0, NULL }
+};
+
+static void SliderElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ SliderElement *slider = elementRecord;
+ int orient, length, thickness;
+
+ Ttk_GetOrientFromObj(NULL, slider->orientObj, &orient);
+ Tk_GetPixelsFromObj(NULL, tkwin, slider->lengthObj, &length);
+ Tk_GetPixelsFromObj(NULL, tkwin, slider->thicknessObj, &thickness);
+
+ switch (orient) {
+ case TTK_ORIENT_VERTICAL:
+ *widthPtr = thickness;
+ *heightPtr = length;
+ break;
+
+ case TTK_ORIENT_HORIZONTAL:
+ *widthPtr = length;
+ *heightPtr = thickness;
+ break;
+ }
+}
+
+static void SliderElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ SliderElement *slider = elementRecord;
+ Tk_3DBorder border = NULL;
+ int relief = TK_RELIEF_RAISED, borderWidth = 2, orient;
+
+ border = Tk_Get3DBorderFromObj(tkwin, slider->borderObj);
+ Ttk_GetOrientFromObj(NULL, slider->orientObj, &orient);
+ Tk_GetPixelsFromObj(NULL, tkwin, slider->borderWidthObj, &borderWidth);
+ Tk_GetReliefFromObj(NULL, slider->reliefObj, &relief);
+
+ Tk_Fill3DRectangle(tkwin, d, border,
+ b.x, b.y, b.width, b.height,
+ borderWidth, relief);
+
+ if (relief != TK_RELIEF_FLAT) {
+ if (orient == TTK_ORIENT_HORIZONTAL) {
+ if (b.width > 4) {
+ b.x += b.width/2;
+ XDrawLine(Tk_Display(tkwin), d,
+ Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC),
+ b.x-1, b.y+borderWidth, b.x-1, b.y+b.height-borderWidth);
+ XDrawLine(Tk_Display(tkwin), d,
+ Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC),
+ b.x, b.y+borderWidth, b.x, b.y+b.height-borderWidth);
+ }
+ } else {
+ if (b.height > 4) {
+ b.y += b.height/2;
+ XDrawLine(Tk_Display(tkwin), d,
+ Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC),
+ b.x+borderWidth, b.y-1, b.x+b.width-borderWidth, b.y-1);
+ XDrawLine(Tk_Display(tkwin), d,
+ Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC),
+ b.x+borderWidth, b.y, b.x+b.width-borderWidth, b.y);
+ }
+ }
+ }
+}
+
+static Ttk_ElementSpec SliderElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(SliderElement),
+ SliderElementOptions,
+ SliderElementSize,
+ SliderElementDraw
+};
+
+/*------------------------------------------------------------------------
+ * +++ Progress bar element:
+ * Draws the moving part of the progress bar.
+ *
+ * -thickness specifies the size along the short axis of the bar.
+ * -length specifies the default size along the long axis;
+ * the bar will be this long in indeterminate mode.
+ */
+
+#define DEFAULT_PBAR_THICKNESS "15"
+#define DEFAULT_PBAR_LENGTH "30"
+
+typedef struct {
+ Tcl_Obj *orientObj; /* widget orientation */
+ Tcl_Obj *thicknessObj; /* the height/width of the bar */
+ Tcl_Obj *lengthObj; /* default width/height of the bar */
+ Tcl_Obj *reliefObj; /* border relief for this object */
+ Tcl_Obj *borderObj; /* background color */
+ Tcl_Obj *borderWidthObj; /* thickness of the border */
+} PbarElement;
+
+static Ttk_ElementOptionSpec PbarElementOptions[] = {
+ { "-orient", TK_OPTION_ANY, Tk_Offset(PbarElement,orientObj),
+ "horizontal" },
+ { "-thickness", TK_OPTION_PIXELS, Tk_Offset(PbarElement,thicknessObj),
+ DEFAULT_PBAR_THICKNESS },
+ { "-barsize", TK_OPTION_PIXELS, Tk_Offset(PbarElement,lengthObj),
+ DEFAULT_PBAR_LENGTH },
+ { "-pbarrelief", TK_OPTION_RELIEF, Tk_Offset(PbarElement,reliefObj),
+ "raised" },
+ { "-borderwidth", TK_OPTION_PIXELS, Tk_Offset(PbarElement,borderWidthObj),
+ DEFAULT_BORDERWIDTH },
+ { "-background", TK_OPTION_BORDER, Tk_Offset(PbarElement,borderObj),
+ DEFAULT_BACKGROUND },
+ { NULL, 0, 0, NULL }
+};
+
+static void PbarElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ PbarElement *pbar = elementRecord;
+ int orient, thickness = 15, length = 30, borderWidth = 2;
+
+ Ttk_GetOrientFromObj(NULL, pbar->orientObj, &orient);
+ Tk_GetPixelsFromObj(NULL, tkwin, pbar->thicknessObj, &thickness);
+ Tk_GetPixelsFromObj(NULL, tkwin, pbar->lengthObj, &length);
+ Tk_GetPixelsFromObj(NULL, tkwin, pbar->borderWidthObj, &borderWidth);
+
+ switch (orient) {
+ case TTK_ORIENT_HORIZONTAL:
+ *widthPtr = length + 2 * borderWidth;
+ *heightPtr = thickness + 2 * borderWidth;
+ break;
+ case TTK_ORIENT_VERTICAL:
+ *widthPtr = thickness + 2 * borderWidth;
+ *heightPtr = length + 2 * borderWidth;
+ break;
+ }
+}
+
+static void PbarElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, Ttk_State state)
+{
+ PbarElement *pbar = elementRecord;
+ Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, pbar->borderObj);
+ int relief = TK_RELIEF_RAISED, borderWidth = 2;
+
+ Tk_GetPixelsFromObj(NULL, tkwin, pbar->borderWidthObj, &borderWidth);
+ Tk_GetReliefFromObj(NULL, pbar->reliefObj, &relief);
+
+ Tk_Fill3DRectangle(tkwin, d, border,
+ b.x, b.y, b.width, b.height,
+ borderWidth, relief);
+}
+
+static Ttk_ElementSpec PbarElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(PbarElement),
+ PbarElementOptions,
+ PbarElementSize,
+ PbarElementDraw
+};
+
+/*------------------------------------------------------------------------
+ * +++ Notebook tabs and client area.
+ */
+
+typedef struct {
+ Tcl_Obj *borderWidthObj;
+ Tcl_Obj *backgroundObj;
+} TabElement;
+
+static Ttk_ElementOptionSpec TabElementOptions[] = {
+ { "-borderwidth", TK_OPTION_PIXELS,
+ Tk_Offset(TabElement,borderWidthObj),"1" },
+ { "-background", TK_OPTION_BORDER,
+ Tk_Offset(TabElement,backgroundObj), DEFAULT_BACKGROUND },
+ {0,0,0,0}
+};
+
+static void TabElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ TabElement *tab = elementRecord;
+ int borderWidth = 1;
+ Tk_GetPixelsFromObj(0, tkwin, tab->borderWidthObj, &borderWidth);
+ paddingPtr->top = paddingPtr->left = paddingPtr->right = borderWidth;
+ paddingPtr->bottom = 0;
+}
+
+static void TabElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ TabElement *tab = elementRecord;
+ Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, tab->backgroundObj);
+ int borderWidth = 1;
+ int cut = 2;
+ XPoint pts[6];
+ int n = 0;
+
+ Tcl_GetIntFromObj(NULL, tab->borderWidthObj, &borderWidth);
+
+ if (state & TTK_STATE_SELECTED) {
+ /*
+ * Draw slightly outside of the allocated parcel,
+ * to overwrite the client area border.
+ */
+ b.height += borderWidth;
+ }
+
+ pts[n].x = b.x; pts[n].y = b.y + b.height - 1; ++n;
+ pts[n].x = b.x; pts[n].y = b.y + cut; ++n;
+ pts[n].x = b.x + cut; pts[n].y = b.y; ++n;
+ pts[n].x = b.x + b.width-1-cut; pts[n].y = b.y; ++n;
+ pts[n].x = b.x + b.width-1; pts[n].y = b.y + cut; ++n;
+ pts[n].x = b.x + b.width-1; pts[n].y = b.y + b.height; ++n;
+
+ XFillPolygon(Tk_Display(tkwin), d,
+ Tk_3DBorderGC(tkwin, border, TK_3D_FLAT_GC),
+ pts, 6, Convex, CoordModeOrigin);
+
+#ifndef _WIN32
+ /*
+ * Account for whether XDrawLines draws endpoints by platform
+ */
+ --pts[5].y;
+#endif
+
+ while (borderWidth--) {
+ XDrawLines(Tk_Display(tkwin), d,
+ Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC),
+ pts, 4, CoordModeOrigin);
+ XDrawLines(Tk_Display(tkwin), d,
+ Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC),
+ pts+3, 3, CoordModeOrigin);
+ ++pts[0].x; ++pts[1].x; ++pts[2].x; --pts[4].x; --pts[5].x;
+ ++pts[2].y; ++pts[3].y;
+ }
+
+}
+
+static Ttk_ElementSpec TabElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(TabElement),
+ TabElementOptions,
+ TabElementSize,
+ TabElementDraw
+};
+
+/*
+ * Client area element:
+ * Uses same resources as tab element.
+ */
+typedef TabElement ClientElement;
+#define ClientElementOptions TabElementOptions
+
+static void ClientElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ ClientElement *ce = elementRecord;
+ Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, ce->backgroundObj);
+ int borderWidth = 1;
+
+ Tcl_GetIntFromObj(NULL, ce->borderWidthObj, &borderWidth);
+
+ Tk_Fill3DRectangle(tkwin, d, border,
+ b.x, b.y, b.width, b.height, borderWidth,TK_RELIEF_RAISED);
+}
+
+static void ClientElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ ClientElement *ce = elementRecord;
+ int borderWidth = 1;
+ Tk_GetPixelsFromObj(0, tkwin, ce->borderWidthObj, &borderWidth);
+ *paddingPtr = Ttk_UniformPadding((short)borderWidth);
+}
+
+static Ttk_ElementSpec ClientElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(ClientElement),
+ ClientElementOptions,
+ ClientElementSize,
+ ClientElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * TtkElements_Init --
+ * Register default element implementations.
+ */
+
+MODULE_SCOPE
+void TtkElements_Init(Tcl_Interp *interp)
+{
+ Ttk_Theme theme = Ttk_GetDefaultTheme(interp);
+
+ /*
+ * Elements:
+ */
+ Ttk_RegisterElement(interp, theme, "background",
+ &BackgroundElementSpec,NULL);
+
+ Ttk_RegisterElement(interp, theme, "fill", &FillElementSpec, NULL);
+ Ttk_RegisterElement(interp, theme, "border", &BorderElementSpec, NULL);
+ Ttk_RegisterElement(interp, theme, "field", &FieldElementSpec, NULL);
+ Ttk_RegisterElement(interp, theme, "focus", &FocusElementSpec, NULL);
+
+ Ttk_RegisterElement(interp, theme, "padding", &PaddingElementSpec, NULL);
+
+ Ttk_RegisterElement(interp, theme, "Checkbutton.indicator",
+ &CheckbuttonIndicatorElementSpec, NULL);
+ Ttk_RegisterElement(interp, theme, "Radiobutton.indicator",
+ &RadiobuttonIndicatorElementSpec, NULL);
+ Ttk_RegisterElement(interp, theme, "Menubutton.indicator",
+ &MenuIndicatorElementSpec, NULL);
+
+ Ttk_RegisterElement(interp, theme, "indicator", &ttkNullElementSpec,NULL);
+
+ Ttk_RegisterElement(interp, theme, "uparrow",
+ &ArrowElementSpec, &ArrowElements[0]);
+ Ttk_RegisterElement(interp, theme, "downarrow",
+ &ArrowElementSpec, &ArrowElements[1]);
+ Ttk_RegisterElement(interp, theme, "leftarrow",
+ &ArrowElementSpec, &ArrowElements[2]);
+ Ttk_RegisterElement(interp, theme, "rightarrow",
+ &ArrowElementSpec, &ArrowElements[3]);
+ Ttk_RegisterElement(interp, theme, "arrow",
+ &ArrowElementSpec, &ArrowElements[0]);
+
+ Ttk_RegisterElement(interp, theme, "trough", &TroughElementSpec, NULL);
+ Ttk_RegisterElement(interp, theme, "thumb", &ThumbElementSpec, NULL);
+ Ttk_RegisterElement(interp, theme, "slider", &SliderElementSpec, NULL);
+ Ttk_RegisterElement(interp, theme, "pbar", &PbarElementSpec, NULL);
+
+ Ttk_RegisterElement(interp, theme, "separator",
+ &SeparatorElementSpec, NULL);
+ Ttk_RegisterElement(interp, theme, "hseparator",
+ &HorizontalSeparatorElementSpec, NULL);
+ Ttk_RegisterElement(interp, theme, "vseparator",
+ &VerticalSeparatorElementSpec, NULL);
+
+ Ttk_RegisterElement(interp, theme, "sizegrip", &SizegripElementSpec, NULL);
+
+ Ttk_RegisterElement(interp, theme, "tab", &TabElementSpec, NULL);
+ Ttk_RegisterElement(interp, theme, "client", &ClientElementSpec, NULL);
+
+ /*
+ * Register "default" as a user-loadable theme (for now):
+ */
+ Tcl_PkgProvideEx(interp, "ttk::theme::default", TTK_VERSION, NULL);
+}
+
+/*EOF*/
diff --git a/tk8.6/generic/ttk/ttkEntry.c b/tk8.6/generic/ttk/ttkEntry.c
new file mode 100644
index 0000000..1579a32
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkEntry.c
@@ -0,0 +1,2103 @@
+/*
+ * DERIVED FROM: tk/generic/tkEntry.c r1.35.
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 2000 Ajuba Solutions.
+ * Copyright (c) 2002 ActiveState Corporation.
+ * Copyright (c) 2004 Joe English
+ */
+
+#include "tkInt.h"
+#include "ttkTheme.h"
+#include "ttkWidget.h"
+
+/*
+ * Extra bits for core.flags:
+ */
+#define GOT_SELECTION (WIDGET_USER_FLAG<<1)
+#define SYNCING_VARIABLE (WIDGET_USER_FLAG<<2)
+#define VALIDATING (WIDGET_USER_FLAG<<3)
+#define VALIDATION_SET_VALUE (WIDGET_USER_FLAG<<4)
+
+/*
+ * Definitions for -validate option values:
+ */
+typedef enum validateMode {
+ VMODE_ALL, VMODE_KEY, VMODE_FOCUS, VMODE_FOCUSIN, VMODE_FOCUSOUT, VMODE_NONE
+} VMODE;
+
+static const char *const validateStrings[] = {
+ "all", "key", "focus", "focusin", "focusout", "none", NULL
+};
+
+/*
+ * Validation reasons:
+ */
+typedef enum validateReason {
+ VALIDATE_INSERT, VALIDATE_DELETE,
+ VALIDATE_FOCUSIN, VALIDATE_FOCUSOUT,
+ VALIDATE_FORCED
+} VREASON;
+
+static const char *const validateReasonStrings[] = {
+ "key", "key", "focusin", "focusout", "forced", NULL
+};
+
+/*------------------------------------------------------------------------
+ * +++ Entry widget record.
+ *
+ * Dependencies:
+ *
+ * textVariableTrace : textVariableObj
+ *
+ * numBytes,numChars : string
+ * displayString : numChars, showChar
+ * layoutHeight,
+ * layoutWidth,
+ * textLayout : fontObj, displayString
+ * layoutX, layoutY : textLayout, justify, xscroll.first
+ *
+ * Invariants:
+ *
+ * 0 <= insertPos <= numChars
+ * 0 <= selectFirst < selectLast <= numChars || selectFirst == selectLast == -1
+ * displayString points to string if showChar == NULL,
+ * or to malloc'ed storage if showChar != NULL.
+ */
+
+/* Style parameters:
+ */
+typedef struct {
+ Tcl_Obj *foregroundObj; /* Foreground color for normal text */
+ Tcl_Obj *backgroundObj; /* Entry widget background color */
+ Tcl_Obj *selBorderObj; /* Border and background for selection */
+ Tcl_Obj *selBorderWidthObj; /* Width of selection border */
+ Tcl_Obj *selForegroundObj; /* Foreground color for selected text */
+ Tcl_Obj *insertColorObj; /* Color of insertion cursor */
+ Tcl_Obj *insertWidthObj; /* Insert cursor width */
+} EntryStyleData;
+
+typedef struct {
+ /*
+ * Internal state:
+ */
+ char *string; /* Storage for string (malloced) */
+ int numBytes; /* Length of string in bytes. */
+ int numChars; /* Length of string in characters. */
+
+ int insertPos; /* Insert index */
+ int selectFirst; /* Index of start of selection, or -1 */
+ int selectLast; /* Index of end of selection, or -1 */
+
+ Scrollable xscroll; /* Current scroll position */
+ ScrollHandle xscrollHandle;
+
+ /*
+ * Options managed by Tk_SetOptions:
+ */
+ Tcl_Obj *textVariableObj; /* Name of linked variable */
+ int exportSelection; /* Tie internal selection to X selection? */
+
+ VMODE validate; /* Validation mode */
+ char *validateCmd; /* Validation script template */
+ char *invalidCmd; /* Invalid callback script template */
+
+ char *showChar; /* Used to derive displayString */
+
+ Tcl_Obj *fontObj; /* Text font to use */
+ Tcl_Obj *widthObj; /* Desired width of window (in avgchars) */
+ Tk_Justify justify; /* Text justification */
+
+ EntryStyleData styleData; /* Display style data (widget options) */
+ EntryStyleData styleDefaults;/* Style defaults (fallback values) */
+
+ Tcl_Obj *stateObj; /* Compatibility option -- see CheckStateObj */
+
+ /*
+ * Derived resources:
+ */
+ Ttk_TraceHandle *textVariableTrace;
+
+ char *displayString; /* String to use when displaying */
+ Tk_TextLayout textLayout; /* Cached text layout information. */
+ int layoutWidth; /* textLayout width */
+ int layoutHeight; /* textLayout height */
+
+ int layoutX, layoutY; /* Origin for text layout. */
+
+} EntryPart;
+
+typedef struct {
+ WidgetCore core;
+ EntryPart entry;
+} Entry;
+
+/*
+ * Extra mask bits for Tk_SetOptions()
+ */
+#define STATE_CHANGED (0x100) /* -state option changed */
+#define TEXTVAR_CHANGED (0x200) /* -textvariable option changed */
+#define SCROLLCMD_CHANGED (0x400) /* -xscrollcommand option changed */
+
+/*
+ * Default option values:
+ */
+#define DEF_SELECT_BG "#000000"
+#define DEF_SELECT_FG "#ffffff"
+#define DEF_INSERT_BG "black"
+#define DEF_ENTRY_WIDTH "20"
+#define DEF_ENTRY_FONT "TkTextFont"
+#define DEF_LIST_HEIGHT "10"
+
+static Tk_OptionSpec EntryOptionSpecs[] = {
+ {TK_OPTION_BOOLEAN, "-exportselection", "exportSelection",
+ "ExportSelection", "1", -1, Tk_Offset(Entry, entry.exportSelection),
+ 0,0,0 },
+ {TK_OPTION_FONT, "-font", "font", "Font",
+ DEF_ENTRY_FONT, Tk_Offset(Entry, entry.fontObj),-1,
+ 0,0,GEOMETRY_CHANGED},
+ {TK_OPTION_STRING, "-invalidcommand", "invalidCommand", "InvalidCommand",
+ NULL, -1, Tk_Offset(Entry, entry.invalidCmd),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
+ "left", -1, Tk_Offset(Entry, entry.justify),
+ 0, 0, GEOMETRY_CHANGED},
+ {TK_OPTION_STRING, "-show", "show", "Show",
+ NULL, -1, Tk_Offset(Entry, entry.showChar),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-state", "state", "State",
+ "normal", Tk_Offset(Entry, entry.stateObj), -1,
+ 0,0,STATE_CHANGED},
+ {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
+ NULL, Tk_Offset(Entry, entry.textVariableObj), -1,
+ TK_OPTION_NULL_OK,0,TEXTVAR_CHANGED},
+ {TK_OPTION_STRING_TABLE, "-validate", "validate", "Validate",
+ "none", -1, Tk_Offset(Entry, entry.validate),
+ 0, (ClientData) validateStrings, 0},
+ {TK_OPTION_STRING, "-validatecommand", "validateCommand", "ValidateCommand",
+ NULL, -1, Tk_Offset(Entry, entry.validateCmd),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_INT, "-width", "width", "Width",
+ DEF_ENTRY_WIDTH, Tk_Offset(Entry, entry.widthObj), -1,
+ 0,0,GEOMETRY_CHANGED},
+ {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
+ NULL, -1, Tk_Offset(Entry, entry.xscroll.scrollCmd),
+ TK_OPTION_NULL_OK, 0, SCROLLCMD_CHANGED},
+
+ /* EntryStyleData options:
+ */
+ {TK_OPTION_COLOR, "-foreground", "textColor", "TextColor",
+ NULL, Tk_Offset(Entry, entry.styleData.foregroundObj), -1,
+ TK_OPTION_NULL_OK,0,0},
+ {TK_OPTION_COLOR, "-background", "windowColor", "WindowColor",
+ NULL, Tk_Offset(Entry, entry.styleData.backgroundObj), -1,
+ TK_OPTION_NULL_OK,0,0},
+
+ WIDGET_TAKEFOCUS_TRUE,
+ WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)
+};
+
+/*------------------------------------------------------------------------
+ * +++ EntryStyleData management.
+ * This is still more awkward than it should be;
+ * it should be able to use the Element API instead.
+ */
+
+/* EntryInitStyleDefaults --
+ * Initialize EntryStyleData record to fallback values.
+ */
+static void EntryInitStyleDefaults(EntryStyleData *es)
+{
+#define INIT(member, value) \
+ es->member = Tcl_NewStringObj(value, -1); \
+ Tcl_IncrRefCount(es->member);
+ INIT(foregroundObj, DEFAULT_FOREGROUND)
+ INIT(selBorderObj, DEF_SELECT_BG)
+ INIT(selForegroundObj, DEF_SELECT_FG)
+ INIT(insertColorObj, DEFAULT_FOREGROUND)
+ INIT(selBorderWidthObj, "0")
+ INIT(insertWidthObj, "1")
+#undef INIT
+}
+
+static void EntryFreeStyleDefaults(EntryStyleData *es)
+{
+ Tcl_DecrRefCount(es->foregroundObj);
+ Tcl_DecrRefCount(es->selBorderObj);
+ Tcl_DecrRefCount(es->selForegroundObj);
+ Tcl_DecrRefCount(es->insertColorObj);
+ Tcl_DecrRefCount(es->selBorderWidthObj);
+ Tcl_DecrRefCount(es->insertWidthObj);
+}
+
+/*
+ * EntryInitStyleData --
+ * Look up style-specific data for an entry widget.
+ */
+static void EntryInitStyleData(Entry *entryPtr, EntryStyleData *es)
+{
+ Ttk_State state = entryPtr->core.state;
+ Ttk_ResourceCache cache = Ttk_GetResourceCache(entryPtr->core.interp);
+ Tk_Window tkwin = entryPtr->core.tkwin;
+ Tcl_Obj *tmp;
+
+ /* Initialize to fallback values:
+ */
+ *es = entryPtr->entry.styleDefaults;
+
+# define INIT(member, name) \
+ if ((tmp=Ttk_QueryOption(entryPtr->core.layout,name,state))) \
+ es->member=tmp;
+ INIT(foregroundObj, "-foreground");
+ INIT(selBorderObj, "-selectbackground")
+ INIT(selBorderWidthObj, "-selectborderwidth")
+ INIT(selForegroundObj, "-selectforeground")
+ INIT(insertColorObj, "-insertcolor")
+ INIT(insertWidthObj, "-insertwidth")
+#undef INIT
+
+ /* Reacquire color & border resources from resource cache.
+ */
+ es->foregroundObj = Ttk_UseColor(cache, tkwin, es->foregroundObj);
+ es->selForegroundObj = Ttk_UseColor(cache, tkwin, es->selForegroundObj);
+ es->insertColorObj = Ttk_UseColor(cache, tkwin, es->insertColorObj);
+ es->selBorderObj = Ttk_UseBorder(cache, tkwin, es->selBorderObj);
+}
+
+/*------------------------------------------------------------------------
+ * +++ Resource management.
+ */
+
+/* EntryDisplayString --
+ * Return a malloc'ed string consisting of 'numChars' copies
+ * of (the first character in the string) 'showChar'.
+ * Used to compute the displayString if -show is non-NULL.
+ */
+static char *EntryDisplayString(const char *showChar, int numChars)
+{
+ char *displayString, *p;
+ int size;
+ int ch;
+ char buf[6];
+
+ TkUtfToUniChar(showChar, &ch);
+ size = TkUniCharToUtf(ch, buf);
+ p = displayString = ckalloc(numChars * size + 1);
+
+ while (numChars--) {
+ memcpy(p, buf, size);
+ p += size;
+ }
+ *p = '\0';
+
+ return displayString;
+}
+
+/* EntryUpdateTextLayout --
+ * Recompute textLayout, layoutWidth, and layoutHeight
+ * from displayString and fontObj.
+ */
+static void EntryUpdateTextLayout(Entry *entryPtr)
+{
+ Tk_FreeTextLayout(entryPtr->entry.textLayout);
+ entryPtr->entry.textLayout = Tk_ComputeTextLayout(
+ Tk_GetFontFromObj(entryPtr->core.tkwin, entryPtr->entry.fontObj),
+ entryPtr->entry.displayString, entryPtr->entry.numChars,
+ 0/*wraplength*/, entryPtr->entry.justify, TK_IGNORE_NEWLINES,
+ &entryPtr->entry.layoutWidth, &entryPtr->entry.layoutHeight);
+}
+
+/* EntryEditable --
+ * Returns 1 if the entry widget accepts user changes, 0 otherwise
+ */
+static int
+EntryEditable(Entry *entryPtr)
+{
+ return !(entryPtr->core.state & (TTK_STATE_DISABLED|TTK_STATE_READONLY));
+}
+
+/*------------------------------------------------------------------------
+ * +++ Selection management.
+ */
+
+/* EntryFetchSelection --
+ * Selection handler for entry widgets.
+ */
+static int
+EntryFetchSelection(
+ ClientData clientData, int offset, char *buffer, int maxBytes)
+{
+ Entry *entryPtr = (Entry *) clientData;
+ int byteCount;
+ const char *string;
+ const char *selStart, *selEnd;
+
+ if (entryPtr->entry.selectFirst < 0 || (!entryPtr->entry.exportSelection)
+ || Tcl_IsSafe(entryPtr->core.interp)) {
+ return -1;
+ }
+ string = entryPtr->entry.displayString;
+
+ selStart = Tcl_UtfAtIndex(string, entryPtr->entry.selectFirst);
+ selEnd = Tcl_UtfAtIndex(selStart,
+ entryPtr->entry.selectLast - entryPtr->entry.selectFirst);
+ byteCount = selEnd - selStart - offset;
+ if (byteCount > maxBytes) {
+ /* @@@POSSIBLE BUG: Can transfer partial UTF-8 sequences. Is this OK? */
+ byteCount = maxBytes;
+ }
+ if (byteCount <= 0) {
+ return 0;
+ }
+ memcpy(buffer, selStart + offset, byteCount);
+ buffer[byteCount] = '\0';
+ return byteCount;
+}
+
+/* EntryLostSelection --
+ * Tk_LostSelProc for Entry widgets; called when an entry
+ * loses ownership of the selection.
+ */
+static void EntryLostSelection(ClientData clientData)
+{
+ Entry *entryPtr = (Entry *) clientData;
+ entryPtr->core.flags &= ~GOT_SELECTION;
+ entryPtr->entry.selectFirst = entryPtr->entry.selectLast = -1;
+ TtkRedisplayWidget(&entryPtr->core);
+}
+
+/* EntryOwnSelection --
+ * Assert ownership of the PRIMARY selection,
+ * if -exportselection set and selection is present and interp is unsafe.
+ */
+static void EntryOwnSelection(Entry *entryPtr)
+{
+ if (entryPtr->entry.exportSelection
+ && (!Tcl_IsSafe(entryPtr->core.interp))
+ && !(entryPtr->core.flags & GOT_SELECTION)) {
+ Tk_OwnSelection(entryPtr->core.tkwin, XA_PRIMARY, EntryLostSelection,
+ (ClientData) entryPtr);
+ entryPtr->core.flags |= GOT_SELECTION;
+ }
+}
+
+/*------------------------------------------------------------------------
+ * +++ Validation.
+ */
+
+/* ExpandPercents --
+ * Expand an entry validation script template (-validatecommand
+ * or -invalidcommand).
+ */
+static void
+ExpandPercents(
+ Entry *entryPtr, /* Entry that needs validation. */
+ const char *template, /* Script template */
+ const char *new, /* Potential new value of entry string */
+ int index, /* index of insert/delete */
+ int count, /* #changed characters */
+ VREASON reason, /* Reason for change */
+ Tcl_DString *dsPtr) /* Result of %-substitutions */
+{
+ int spaceNeeded, cvtFlags;
+ int number, length;
+ const char *string;
+ int stringLength;
+ int ch;
+ char numStorage[2*TCL_INTEGER_SPACE];
+
+ while (*template) {
+ /* Find everything up to the next % character and append it
+ * to the result string.
+ */
+ string = Tcl_UtfFindFirst(template, '%');
+ if (string == NULL) {
+ /* No more %-sequences to expand.
+ * Copy the rest of the template.
+ */
+ Tcl_DStringAppend(dsPtr, template, -1);
+ return;
+ }
+ if (string != template) {
+ Tcl_DStringAppend(dsPtr, template, string - template);
+ template = string;
+ }
+
+ /* There's a percent sequence here. Process it.
+ */
+ ++template; /* skip over % */
+ if (*template != '\0') {
+ template += TkUtfToUniChar(template, &ch);
+ } else {
+ ch = '%';
+ }
+
+ stringLength = -1;
+ switch (ch) {
+ case 'd': /* Type of call that caused validation */
+ if (reason == VALIDATE_INSERT) {
+ number = 1;
+ } else if (reason == VALIDATE_DELETE) {
+ number = 0;
+ } else {
+ number = -1;
+ }
+ sprintf(numStorage, "%d", number);
+ string = numStorage;
+ break;
+ case 'i': /* index of insert/delete */
+ sprintf(numStorage, "%d", index);
+ string = numStorage;
+ break;
+ case 'P': /* 'Peeked' new value of the string */
+ string = new;
+ break;
+ case 's': /* Current string value */
+ string = entryPtr->entry.string;
+ break;
+ case 'S': /* string to be inserted/deleted, if any */
+ if (reason == VALIDATE_INSERT) {
+ string = Tcl_UtfAtIndex(new, index);
+ stringLength = Tcl_UtfAtIndex(string, count) - string;
+ } else if (reason == VALIDATE_DELETE) {
+ string = Tcl_UtfAtIndex(entryPtr->entry.string, index);
+ stringLength = Tcl_UtfAtIndex(string, count) - string;
+ } else {
+ string = "";
+ stringLength = 0;
+ }
+ break;
+ case 'v': /* type of validation currently set */
+ string = validateStrings[entryPtr->entry.validate];
+ break;
+ case 'V': /* type of validation in effect */
+ string = validateReasonStrings[reason];
+ break;
+ case 'W': /* widget name */
+ string = Tk_PathName(entryPtr->core.tkwin);
+ break;
+ default:
+ length = TkUniCharToUtf(ch, numStorage);
+ numStorage[length] = '\0';
+ string = numStorage;
+ break;
+ }
+
+ spaceNeeded = Tcl_ScanCountedElement(string, stringLength, &cvtFlags);
+ length = Tcl_DStringLength(dsPtr);
+ Tcl_DStringSetLength(dsPtr, length + spaceNeeded);
+ spaceNeeded = Tcl_ConvertCountedElement(string, stringLength,
+ Tcl_DStringValue(dsPtr) + length,
+ cvtFlags | TCL_DONT_USE_BRACES);
+ Tcl_DStringSetLength(dsPtr, length + spaceNeeded);
+ }
+}
+
+/* RunValidationScript --
+ * Build and evaluate an entry validation script.
+ * If the script raises an error, disable validation
+ * by setting '-validate none'
+ */
+static int RunValidationScript(
+ Tcl_Interp *interp, /* Interpreter to use */
+ Entry *entryPtr, /* Entry being validated */
+ const char *template, /* Script template */
+ const char *optionName, /* "-validatecommand", "-invalidcommand" */
+ const char *new, /* Potential new value of entry string */
+ int index, /* index of insert/delete */
+ int count, /* #changed characters */
+ VREASON reason) /* Reason for change */
+{
+ Tcl_DString script;
+ int code;
+
+ Tcl_DStringInit(&script);
+ ExpandPercents(entryPtr, template, new, index, count, reason, &script);
+ code = Tcl_EvalEx(interp,
+ Tcl_DStringValue(&script), Tcl_DStringLength(&script),
+ TCL_EVAL_GLOBAL);
+ Tcl_DStringFree(&script);
+ if (WidgetDestroyed(&entryPtr->core))
+ return TCL_ERROR;
+
+ if (code != TCL_OK && code != TCL_RETURN) {
+ Tcl_AddErrorInfo(interp, "\n\t(in ");
+ Tcl_AddErrorInfo(interp, optionName);
+ Tcl_AddErrorInfo(interp, " validation command executed by ");
+ Tcl_AddErrorInfo(interp, Tk_PathName(entryPtr->core.tkwin));
+ Tcl_AddErrorInfo(interp, ")");
+ entryPtr->entry.validate = VMODE_NONE;
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/* EntryNeedsValidation --
+ * Determine whether the specified VREASON should trigger validation
+ * in the current VMODE.
+ */
+static int EntryNeedsValidation(VMODE vmode, VREASON reason)
+{
+ return (reason == VALIDATE_FORCED)
+ || (vmode == VMODE_ALL)
+ || (reason == VALIDATE_FOCUSIN
+ && (vmode == VMODE_FOCUSIN || vmode == VMODE_FOCUS))
+ || (reason == VALIDATE_FOCUSOUT
+ && (vmode == VMODE_FOCUSOUT || vmode == VMODE_FOCUS))
+ || (reason == VALIDATE_INSERT && vmode == VMODE_KEY)
+ || (reason == VALIDATE_DELETE && vmode == VMODE_KEY)
+ ;
+}
+
+/* EntryValidateChange --
+ * Validate a proposed change to the entry widget's value if required.
+ * Call the -invalidcommand if validation fails.
+ *
+ * Returns:
+ * TCL_OK if the change is accepted
+ * TCL_BREAK if the change is rejected
+ * TCL_ERROR if any errors occured
+ *
+ * The change will be rejected if -validatecommand returns 0,
+ * or if -validatecommand or -invalidcommand modifies the value.
+ */
+static int
+EntryValidateChange(
+ Entry *entryPtr, /* Entry that needs validation. */
+ const char *newValue, /* Potential new value of entry string */
+ int index, /* index of insert/delete, -1 otherwise */
+ int count, /* #changed characters */
+ VREASON reason) /* Reason for change */
+{
+ Tcl_Interp *interp = entryPtr->core.interp;
+ VMODE vmode = entryPtr->entry.validate;
+ int code, change_ok;
+
+ if ( (entryPtr->entry.validateCmd == NULL)
+ || (entryPtr->core.flags & VALIDATING)
+ || !EntryNeedsValidation(vmode, reason) )
+ {
+ return TCL_OK;
+ }
+
+ entryPtr->core.flags |= VALIDATING;
+
+ /* Run -validatecommand and check return value:
+ */
+ code = RunValidationScript(interp, entryPtr,
+ entryPtr->entry.validateCmd, "-validatecommand",
+ newValue, index, count, reason);
+ if (code != TCL_OK) {
+ goto done;
+ }
+
+ code = Tcl_GetBooleanFromObj(interp,Tcl_GetObjResult(interp), &change_ok);
+ if (code != TCL_OK) {
+ entryPtr->entry.validate = VMODE_NONE; /* Disable validation */
+ Tcl_AddErrorInfo(interp,
+ "\n(validation command did not return valid boolean)");
+ goto done;
+ }
+
+ /* Run the -invalidcommand if validation failed:
+ */
+ if (!change_ok && entryPtr->entry.invalidCmd != NULL) {
+ code = RunValidationScript(interp, entryPtr,
+ entryPtr->entry.invalidCmd, "-invalidcommand",
+ newValue, index, count, reason);
+ if (code != TCL_OK) {
+ goto done;
+ }
+ }
+
+ /* Reject the pending change if validation failed
+ * or if a validation script changed the value.
+ */
+ if (!change_ok || (entryPtr->core.flags & VALIDATION_SET_VALUE)) {
+ code = TCL_BREAK;
+ }
+
+done:
+ entryPtr->core.flags &= ~(VALIDATING|VALIDATION_SET_VALUE);
+ return code;
+}
+
+/* EntryRevalidate --
+ * Revalidate the current value of an entry widget,
+ * update the TTK_STATE_INVALID bit.
+ *
+ * Returns:
+ * TCL_OK if valid, TCL_BREAK if invalid, TCL_ERROR on error.
+ */
+static int EntryRevalidate(Tcl_Interp *interp, Entry *entryPtr, VREASON reason)
+{
+ int code = EntryValidateChange(
+ entryPtr, entryPtr->entry.string, -1,0, reason);
+
+ if (code == TCL_BREAK) {
+ TtkWidgetChangeState(&entryPtr->core, TTK_STATE_INVALID, 0);
+ } else if (code == TCL_OK) {
+ TtkWidgetChangeState(&entryPtr->core, 0, TTK_STATE_INVALID);
+ }
+
+ return code;
+}
+
+/* EntryRevalidateBG --
+ * Revalidate in the background (called from event handler).
+ */
+static void EntryRevalidateBG(Entry *entryPtr, VREASON reason)
+{
+ Tcl_Interp *interp = entryPtr->core.interp;
+ if (EntryRevalidate(interp, entryPtr, reason) == TCL_ERROR) {
+ Tcl_BackgroundException(interp, TCL_ERROR);
+ }
+}
+
+/*------------------------------------------------------------------------
+ * +++ Entry widget modification.
+ */
+
+/* AdjustIndex --
+ * Adjust index to account for insertion (nChars > 0)
+ * or deletion (nChars < 0) at specified index.
+ */
+static int AdjustIndex(int i0, int index, int nChars)
+{
+ if (i0 >= index) {
+ i0 += nChars;
+ if (i0 < index) { /* index was inside deleted range */
+ i0 = index;
+ }
+ }
+ return i0;
+}
+
+/* AdjustIndices --
+ * Adjust all internal entry indexes to account for change.
+ * Note that insertPos, and selectFirst have "right gravity",
+ * while leftIndex (=xscroll.first) and selectLast have "left gravity".
+ */
+static void AdjustIndices(Entry *entryPtr, int index, int nChars)
+{
+ EntryPart *e = &entryPtr->entry;
+ int g = nChars > 0; /* left gravity adjustment */
+
+ e->insertPos = AdjustIndex(e->insertPos, index, nChars);
+ e->selectFirst = AdjustIndex(e->selectFirst, index, nChars);
+ e->selectLast = AdjustIndex(e->selectLast, index+g, nChars);
+ e->xscroll.first= AdjustIndex(e->xscroll.first, index+g, nChars);
+
+ if (e->selectLast <= e->selectFirst)
+ e->selectFirst = e->selectLast = -1;
+}
+
+/* EntryStoreValue --
+ * Replace the contents of a text entry with a given value,
+ * recompute dependent resources, and schedule a redisplay.
+ *
+ * See also: EntrySetValue().
+ */
+static void
+EntryStoreValue(Entry *entryPtr, const char *value)
+{
+ size_t numBytes = strlen(value);
+ int numChars = Tcl_NumUtfChars(value, numBytes);
+
+ if (entryPtr->core.flags & VALIDATING)
+ entryPtr->core.flags |= VALIDATION_SET_VALUE;
+
+ /* Make sure all indices remain in bounds:
+ */
+ if (numChars < entryPtr->entry.numChars)
+ AdjustIndices(entryPtr, numChars, numChars - entryPtr->entry.numChars);
+
+ /* Free old value:
+ */
+ if (entryPtr->entry.displayString != entryPtr->entry.string)
+ ckfree(entryPtr->entry.displayString);
+ ckfree(entryPtr->entry.string);
+
+ /* Store new value:
+ */
+ entryPtr->entry.string = ckalloc(numBytes + 1);
+ strcpy(entryPtr->entry.string, value);
+ entryPtr->entry.numBytes = numBytes;
+ entryPtr->entry.numChars = numChars;
+
+ entryPtr->entry.displayString
+ = entryPtr->entry.showChar
+ ? EntryDisplayString(entryPtr->entry.showChar, numChars)
+ : entryPtr->entry.string
+ ;
+
+ /* Update layout, schedule redisplay:
+ */
+ EntryUpdateTextLayout(entryPtr);
+ TtkRedisplayWidget(&entryPtr->core);
+}
+
+/* EntrySetValue --
+ * Stores a new value in the entry widget and updates the
+ * linked -textvariable, if any. The write trace on the
+ * text variable is temporarily disabled; however, other
+ * write traces may change the value of the variable.
+ * If so, the widget is updated again with the new value.
+ *
+ * Returns:
+ * TCL_OK if successful, TCL_ERROR otherwise.
+ */
+static int EntrySetValue(Entry *entryPtr, const char *value)
+{
+ EntryStoreValue(entryPtr, value);
+
+ if (entryPtr->entry.textVariableObj) {
+ const char *textVarName =
+ Tcl_GetString(entryPtr->entry.textVariableObj);
+ if (textVarName && *textVarName) {
+ entryPtr->core.flags |= SYNCING_VARIABLE;
+ value = Tcl_SetVar2(entryPtr->core.interp, textVarName,
+ NULL, value, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG);
+ entryPtr->core.flags &= ~SYNCING_VARIABLE;
+ if (!value || WidgetDestroyed(&entryPtr->core)) {
+ return TCL_ERROR;
+ } else if (strcmp(value, entryPtr->entry.string) != 0) {
+ /* Some write trace has changed the variable value.
+ */
+ EntryStoreValue(entryPtr, value);
+ }
+ }
+ }
+
+ return TCL_OK;
+}
+
+/* EntryTextVariableTrace --
+ * Variable trace procedure for entry -textvariable
+ */
+static void EntryTextVariableTrace(void *recordPtr, const char *value)
+{
+ Entry *entryPtr = recordPtr;
+
+ if (WidgetDestroyed(&entryPtr->core)) {
+ return;
+ }
+
+ if (entryPtr->core.flags & SYNCING_VARIABLE) {
+ /* Trace was fired due to Tcl_SetVar2 call in EntrySetValue.
+ * Don't do anything.
+ */
+ return;
+ }
+
+ EntryStoreValue(entryPtr, value ? value : "");
+}
+
+/*------------------------------------------------------------------------
+ * +++ Insertion and deletion.
+ */
+
+/* InsertChars --
+ * Add new characters to an entry widget.
+ */
+static int
+InsertChars(
+ Entry *entryPtr, /* Entry that is to get the new elements. */
+ int index, /* Insert before this index */
+ const char *value) /* New characters to add */
+{
+ char *string = entryPtr->entry.string;
+ size_t byteIndex = Tcl_UtfAtIndex(string, index) - string;
+ size_t byteCount = strlen(value);
+ int charsAdded = Tcl_NumUtfChars(value, byteCount);
+ size_t newByteCount = entryPtr->entry.numBytes + byteCount + 1;
+ char *new;
+ int code;
+
+ if (byteCount == 0) {
+ return TCL_OK;
+ }
+
+ new = ckalloc(newByteCount);
+ memcpy(new, string, byteIndex);
+ strcpy(new + byteIndex, value);
+ strcpy(new + byteIndex + byteCount, string + byteIndex);
+
+ code = EntryValidateChange(
+ entryPtr, new, index, charsAdded, VALIDATE_INSERT);
+
+ if (code == TCL_OK) {
+ AdjustIndices(entryPtr, index, charsAdded);
+ code = EntrySetValue(entryPtr, new);
+ } else if (code == TCL_BREAK) {
+ code = TCL_OK;
+ }
+
+ ckfree(new);
+ return code;
+}
+
+/* DeleteChars --
+ * Remove one or more characters from an entry widget.
+ */
+static int
+DeleteChars(
+ Entry *entryPtr, /* Entry widget to modify. */
+ int index, /* Index of first character to delete. */
+ int count) /* How many characters to delete. */
+{
+ char *string = entryPtr->entry.string;
+ size_t byteIndex, byteCount, newByteCount;
+ char *new;
+ int code;
+
+ if (index < 0) {
+ index = 0;
+ }
+ if (count > entryPtr->entry.numChars - index) {
+ count = entryPtr->entry.numChars - index;
+ }
+ if (count <= 0) {
+ return TCL_OK;
+ }
+
+ byteIndex = Tcl_UtfAtIndex(string, index) - string;
+ byteCount = Tcl_UtfAtIndex(string+byteIndex, count) - (string+byteIndex);
+
+ newByteCount = entryPtr->entry.numBytes + 1 - byteCount;
+ new = ckalloc(newByteCount);
+ memcpy(new, string, byteIndex);
+ strcpy(new + byteIndex, string + byteIndex + byteCount);
+
+ code = EntryValidateChange(
+ entryPtr, new, index, count, VALIDATE_DELETE);
+
+ if (code == TCL_OK) {
+ AdjustIndices(entryPtr, index, -count);
+ code = EntrySetValue(entryPtr, new);
+ } else if (code == TCL_BREAK) {
+ code = TCL_OK;
+ }
+ ckfree(new);
+
+ return code;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Event handler.
+ */
+
+/* EntryEventProc --
+ * Extra event handling for entry widgets:
+ * Triggers validation on FocusIn and FocusOut events.
+ */
+#define EntryEventMask (FocusChangeMask)
+static void
+EntryEventProc(ClientData clientData, XEvent *eventPtr)
+{
+ Entry *entryPtr = (Entry *) clientData;
+
+ Tcl_Preserve(clientData);
+ switch (eventPtr->type) {
+ case DestroyNotify:
+ Tk_DeleteEventHandler(entryPtr->core.tkwin,
+ EntryEventMask, EntryEventProc, clientData);
+ break;
+ case FocusIn:
+ EntryRevalidateBG(entryPtr, VALIDATE_FOCUSIN);
+ break;
+ case FocusOut:
+ EntryRevalidateBG(entryPtr, VALIDATE_FOCUSOUT);
+ break;
+ }
+ Tcl_Release(clientData);
+}
+
+/*------------------------------------------------------------------------
+ * +++ Initialization and cleanup.
+ */
+
+static void
+EntryInitialize(Tcl_Interp *interp, void *recordPtr)
+{
+ Entry *entryPtr = recordPtr;
+
+ Tk_CreateEventHandler(
+ entryPtr->core.tkwin, EntryEventMask, EntryEventProc, entryPtr);
+ Tk_CreateSelHandler(entryPtr->core.tkwin, XA_PRIMARY, XA_STRING,
+ EntryFetchSelection, (ClientData) entryPtr, XA_STRING);
+ TtkBlinkCursor(&entryPtr->core);
+
+ entryPtr->entry.string = ckalloc(1);
+ *entryPtr->entry.string = '\0';
+ entryPtr->entry.displayString = entryPtr->entry.string;
+ entryPtr->entry.textVariableTrace = 0;
+ entryPtr->entry.numBytes = entryPtr->entry.numChars = 0;
+
+ EntryInitStyleDefaults(&entryPtr->entry.styleDefaults);
+
+ entryPtr->entry.xscrollHandle =
+ TtkCreateScrollHandle(&entryPtr->core, &entryPtr->entry.xscroll);
+
+ entryPtr->entry.insertPos = 0;
+ entryPtr->entry.selectFirst = -1;
+ entryPtr->entry.selectLast = -1;
+}
+
+static void
+EntryCleanup(void *recordPtr)
+{
+ Entry *entryPtr = recordPtr;
+
+ if (entryPtr->entry.textVariableTrace)
+ Ttk_UntraceVariable(entryPtr->entry.textVariableTrace);
+
+ TtkFreeScrollHandle(entryPtr->entry.xscrollHandle);
+
+ EntryFreeStyleDefaults(&entryPtr->entry.styleDefaults);
+
+ Tk_DeleteSelHandler(entryPtr->core.tkwin, XA_PRIMARY, XA_STRING);
+
+ Tk_FreeTextLayout(entryPtr->entry.textLayout);
+ if (entryPtr->entry.displayString != entryPtr->entry.string)
+ ckfree(entryPtr->entry.displayString);
+ ckfree(entryPtr->entry.string);
+}
+
+/* EntryConfigure --
+ * Configure hook for Entry widgets.
+ */
+static int EntryConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
+{
+ Entry *entryPtr = recordPtr;
+ Tcl_Obj *textVarName = entryPtr->entry.textVariableObj;
+ Ttk_TraceHandle *vt = 0;
+
+ if (mask & TEXTVAR_CHANGED) {
+ if (textVarName && *Tcl_GetString(textVarName) != '\0') {
+ vt = Ttk_TraceVariable(interp,
+ textVarName,EntryTextVariableTrace,entryPtr);
+ if (!vt) return TCL_ERROR;
+ }
+ }
+
+ if (TtkCoreConfigure(interp, recordPtr, mask) != TCL_OK) {
+ if (vt) Ttk_UntraceVariable(vt);
+ return TCL_ERROR;
+ }
+
+ /* Update derived resources:
+ */
+ if (mask & TEXTVAR_CHANGED) {
+ if (entryPtr->entry.textVariableTrace)
+ Ttk_UntraceVariable(entryPtr->entry.textVariableTrace);
+ entryPtr->entry.textVariableTrace = vt;
+ }
+
+ /* Claim the selection, in case we've suddenly started exporting it.
+ */
+ if (entryPtr->entry.exportSelection && (entryPtr->entry.selectFirst != -1)
+ && (!Tcl_IsSafe(entryPtr->core.interp))) {
+ EntryOwnSelection(entryPtr);
+ }
+
+ /* Handle -state compatibility option:
+ */
+ if (mask & STATE_CHANGED) {
+ TtkCheckStateOption(&entryPtr->core, entryPtr->entry.stateObj);
+ }
+
+ /* Force scrollbar update if needed:
+ */
+ if (mask & SCROLLCMD_CHANGED) {
+ TtkScrollbarUpdateRequired(entryPtr->entry.xscrollHandle);
+ }
+
+ /* Recompute the displayString, in case showChar changed:
+ */
+ if (entryPtr->entry.displayString != entryPtr->entry.string)
+ ckfree(entryPtr->entry.displayString);
+
+ entryPtr->entry.displayString
+ = entryPtr->entry.showChar
+ ? EntryDisplayString(entryPtr->entry.showChar, entryPtr->entry.numChars)
+ : entryPtr->entry.string
+ ;
+
+ /* Update textLayout:
+ */
+ EntryUpdateTextLayout(entryPtr);
+ return TCL_OK;
+}
+
+/* EntryPostConfigure --
+ * Post-configuration hook for entry widgets.
+ */
+static int EntryPostConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
+{
+ Entry *entryPtr = recordPtr;
+ int status = TCL_OK;
+
+ if ((mask & TEXTVAR_CHANGED) && entryPtr->entry.textVariableTrace != NULL) {
+ status = Ttk_FireTrace(entryPtr->entry.textVariableTrace);
+ }
+
+ return status;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Layout and display.
+ */
+
+/* EntryCharPosition --
+ * Return the X coordinate of the specified character index.
+ * Precondition: textLayout and layoutX up-to-date.
+ */
+static int
+EntryCharPosition(Entry *entryPtr, int index)
+{
+ int xPos;
+ Tk_CharBbox(entryPtr->entry.textLayout, index, &xPos, NULL, NULL, NULL);
+ return xPos + entryPtr->entry.layoutX;
+}
+
+/* EntryDoLayout --
+ * Layout hook for entry widgets.
+ *
+ * Determine position of textLayout based on xscroll.first, justify,
+ * and display area.
+ *
+ * Recalculates layoutX, layoutY, and rightIndex,
+ * and updates xscroll accordingly.
+ * May adjust xscroll.first to ensure the maximum #characters are onscreen.
+ */
+static void
+EntryDoLayout(void *recordPtr)
+{
+ Entry *entryPtr = recordPtr;
+ WidgetCore *corePtr = &entryPtr->core;
+ Tk_TextLayout textLayout = entryPtr->entry.textLayout;
+ int leftIndex = entryPtr->entry.xscroll.first;
+ int rightIndex;
+ Ttk_Box textarea;
+
+ Ttk_PlaceLayout(corePtr->layout,corePtr->state,Ttk_WinBox(corePtr->tkwin));
+ textarea = Ttk_ClientRegion(corePtr->layout, "textarea");
+
+ /* Center the text vertically within the available parcel:
+ */
+ entryPtr->entry.layoutY = textarea.y +
+ (textarea.height - entryPtr->entry.layoutHeight)/2;
+
+ /* Recompute where the leftmost character on the display will
+ * be drawn (layoutX) and adjust leftIndex if necessary.
+ */
+ if (entryPtr->entry.layoutWidth <= textarea.width) {
+ /* Everything fits. Set leftIndex to zero (no need to scroll),
+ * and compute layoutX based on -justify.
+ */
+ int extraSpace = textarea.width - entryPtr->entry.layoutWidth;
+ leftIndex = 0;
+ rightIndex = entryPtr->entry.numChars;
+ entryPtr->entry.layoutX = textarea.x;
+ if (entryPtr->entry.justify == TK_JUSTIFY_RIGHT) {
+ entryPtr->entry.layoutX += extraSpace;
+ } else if (entryPtr->entry.justify == TK_JUSTIFY_CENTER) {
+ entryPtr->entry.layoutX += extraSpace / 2;
+ }
+ } else {
+ /* The whole string doesn't fit in the window.
+ * Limit leftIndex to leave at most one character's worth
+ * of empty space on the right.
+ */
+ int overflow = entryPtr->entry.layoutWidth - textarea.width;
+ int maxLeftIndex = 1 + Tk_PointToChar(textLayout, overflow, 0);
+ int leftX;
+
+ if (leftIndex > maxLeftIndex) {
+ leftIndex = maxLeftIndex;
+ }
+
+ /* Compute layoutX and rightIndex.
+ * rightIndex is set to one past the last fully-visible character.
+ */
+ Tk_CharBbox(textLayout, leftIndex, &leftX, NULL, NULL, NULL);
+ rightIndex = Tk_PointToChar(textLayout, leftX + textarea.width, 0);
+ entryPtr->entry.layoutX = textarea.x - leftX;
+ }
+
+ TtkScrolled(entryPtr->entry.xscrollHandle,
+ leftIndex, rightIndex, entryPtr->entry.numChars);
+}
+
+/* EntryGetGC -- Helper routine.
+ * Get a GC using the specified foreground color and the entry's font.
+ * Result must be freed with Tk_FreeGC().
+ */
+static GC EntryGetGC(Entry *entryPtr, Tcl_Obj *colorObj, TkRegion clip)
+{
+ Tk_Window tkwin = entryPtr->core.tkwin;
+ Tk_Font font = Tk_GetFontFromObj(tkwin, entryPtr->entry.fontObj);
+ XColor *colorPtr;
+ unsigned long mask = 0ul;
+ XGCValues gcValues;
+ GC gc;
+
+ gcValues.line_width = 1; mask |= GCLineWidth;
+ gcValues.font = Tk_FontId(font); mask |= GCFont;
+ if (colorObj != 0 && (colorPtr=Tk_GetColorFromObj(tkwin,colorObj)) != 0) {
+ gcValues.foreground = colorPtr->pixel;
+ mask |= GCForeground;
+ }
+ gc = Tk_GetGC(entryPtr->core.tkwin, mask, &gcValues);
+ if (clip != NULL) {
+ TkSetRegion(Tk_Display(entryPtr->core.tkwin), gc, clip);
+ }
+ return gc;
+}
+
+/* EntryDisplay --
+ * Redraws the contents of an entry window.
+ */
+static void EntryDisplay(void *clientData, Drawable d)
+{
+ Entry *entryPtr = clientData;
+ Tk_Window tkwin = entryPtr->core.tkwin;
+ int leftIndex = entryPtr->entry.xscroll.first,
+ rightIndex = entryPtr->entry.xscroll.last + 1,
+ selFirst = entryPtr->entry.selectFirst,
+ selLast = entryPtr->entry.selectLast;
+ EntryStyleData es;
+ GC gc;
+ int showSelection, showCursor;
+ Ttk_Box textarea;
+ TkRegion clipRegion;
+ XRectangle rect;
+
+ EntryInitStyleData(entryPtr, &es);
+
+ textarea = Ttk_ClientRegion(entryPtr->core.layout, "textarea");
+ showCursor =
+ (entryPtr->core.flags & CURSOR_ON)
+ && EntryEditable(entryPtr)
+ && entryPtr->entry.insertPos >= leftIndex
+ && entryPtr->entry.insertPos <= rightIndex
+ ;
+ showSelection =
+ !(entryPtr->core.state & TTK_STATE_DISABLED)
+ && selFirst > -1
+ && selLast > leftIndex
+ && selFirst <= rightIndex
+ ;
+
+ /* Adjust selection range to keep in display bounds.
+ */
+ if (showSelection) {
+ if (selFirst < leftIndex)
+ selFirst = leftIndex;
+ if (selLast > rightIndex)
+ selLast = rightIndex;
+ }
+
+ /* Draw widget background & border
+ */
+ Ttk_DrawLayout(entryPtr->core.layout, entryPtr->core.state, d);
+
+ /* Draw selection background
+ */
+ if (showSelection && es.selBorderObj) {
+ Tk_3DBorder selBorder = Tk_Get3DBorderFromObj(tkwin, es.selBorderObj);
+ int selStartX = EntryCharPosition(entryPtr, selFirst);
+ int selEndX = EntryCharPosition(entryPtr, selLast);
+ int borderWidth = 1;
+
+ Tcl_GetIntFromObj(NULL, es.selBorderWidthObj, &borderWidth);
+
+ if (selBorder) {
+ Tk_Fill3DRectangle(tkwin, d, selBorder,
+ selStartX - borderWidth, entryPtr->entry.layoutY - borderWidth,
+ selEndX - selStartX + 2*borderWidth,
+ entryPtr->entry.layoutHeight + 2*borderWidth,
+ borderWidth, TK_RELIEF_RAISED);
+ }
+ }
+
+ /* Initialize the clip region. Note that Xft does _not_ derive its
+ * clipping area from the GC, so we have to supply that by other means.
+ */
+
+ rect.x = textarea.x;
+ rect.y = textarea.y;
+ rect.width = textarea.width;
+ rect.height = textarea.height;
+ clipRegion = TkCreateRegion();
+ TkUnionRectWithRegion(&rect, clipRegion, clipRegion);
+#ifdef HAVE_XFT
+ TkUnixSetXftClipRegion(clipRegion);
+#endif
+
+ /* Draw cursor:
+ */
+ if (showCursor) {
+ Ttk_Box field = Ttk_ClientRegion(entryPtr->core.layout, "field");
+ int cursorX = EntryCharPosition(entryPtr, entryPtr->entry.insertPos),
+ cursorY = entryPtr->entry.layoutY,
+ cursorHeight = entryPtr->entry.layoutHeight,
+ cursorWidth = 1;
+
+ Tcl_GetIntFromObj(NULL,es.insertWidthObj,&cursorWidth);
+ if (cursorWidth <= 0) {
+ cursorWidth = 1;
+ }
+
+ /* @@@ should: maybe: SetCaretPos even when blinked off */
+ Tk_SetCaretPos(tkwin, cursorX, cursorY, cursorHeight);
+
+ cursorX -= cursorWidth/2;
+ if (cursorX < field.x) {
+ cursorX = field.x;
+ } else if (cursorX + cursorWidth > field.x + field.width) {
+ cursorX = field.x + field.width - cursorWidth;
+ }
+
+ gc = EntryGetGC(entryPtr, es.insertColorObj, NULL);
+ XFillRectangle(Tk_Display(tkwin), d, gc,
+ cursorX, cursorY, cursorWidth, cursorHeight);
+ Tk_FreeGC(Tk_Display(tkwin), gc);
+ }
+
+ /* Draw the text:
+ */
+ gc = EntryGetGC(entryPtr, es.foregroundObj, clipRegion);
+ Tk_DrawTextLayout(
+ Tk_Display(tkwin), d, gc, entryPtr->entry.textLayout,
+ entryPtr->entry.layoutX, entryPtr->entry.layoutY,
+ leftIndex, rightIndex);
+ XSetClipMask(Tk_Display(tkwin), gc, None);
+ Tk_FreeGC(Tk_Display(tkwin), gc);
+
+ /* Overwrite the selected portion (if any) in the -selectforeground color:
+ */
+ if (showSelection) {
+ gc = EntryGetGC(entryPtr, es.selForegroundObj, clipRegion);
+ Tk_DrawTextLayout(
+ Tk_Display(tkwin), d, gc, entryPtr->entry.textLayout,
+ entryPtr->entry.layoutX, entryPtr->entry.layoutY,
+ selFirst, selLast);
+ XSetClipMask(Tk_Display(tkwin), gc, None);
+ Tk_FreeGC(Tk_Display(tkwin), gc);
+ }
+
+ /* Drop the region. Note that we have to manually remove the reference to
+ * it from the Xft guts (if they're being used).
+ */
+#ifdef HAVE_XFT
+ TkUnixSetXftClipRegion(NULL);
+#endif
+ TkDestroyRegion(clipRegion);
+}
+
+/*------------------------------------------------------------------------
+ * +++ Widget commands.
+ */
+
+/* EntryIndex --
+ * Parse an index into an entry and return either its value
+ * or an error.
+ *
+ * Results:
+ * A standard Tcl result. If all went well, then *indexPtr is
+ * filled in with the character index (into entryPtr) corresponding to
+ * string. The index value is guaranteed to lie between 0 and
+ * the number of characters in the string, inclusive. If an
+ * error occurs then an error message is left in the interp's result.
+ */
+static int
+EntryIndex(
+ Tcl_Interp *interp, /* For error messages. */
+ Entry *entryPtr, /* Entry widget to query */
+ Tcl_Obj *indexObj, /* Symbolic index name */
+ int *indexPtr) /* Return value */
+{
+# define EntryWidth(e) (Tk_Width(entryPtr->core.tkwin)) /* Not Right */
+ const char *string = Tcl_GetString(indexObj);
+ size_t length = indexObj->length;
+
+ if (strncmp(string, "end", length) == 0) {
+ *indexPtr = entryPtr->entry.numChars;
+ } else if (strncmp(string, "insert", length) == 0) {
+ *indexPtr = entryPtr->entry.insertPos;
+ } else if (strncmp(string, "left", length) == 0) { /* for debugging */
+ *indexPtr = entryPtr->entry.xscroll.first;
+ } else if (strncmp(string, "right", length) == 0) { /* for debugging */
+ *indexPtr = entryPtr->entry.xscroll.last;
+ } else if (strncmp(string, "sel.", 4) == 0) {
+ if (entryPtr->entry.selectFirst < 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "selection isn't in widget %s",
+ Tk_PathName(entryPtr->core.tkwin)));
+ Tcl_SetErrorCode(interp, "TTK", "ENTRY", "NO_SELECTION", NULL);
+ return TCL_ERROR;
+ }
+ if (strncmp(string, "sel.first", length) == 0) {
+ *indexPtr = entryPtr->entry.selectFirst;
+ } else if (strncmp(string, "sel.last", length) == 0) {
+ *indexPtr = entryPtr->entry.selectLast;
+ } else {
+ goto badIndex;
+ }
+ } else if (string[0] == '@') {
+ int roundUp = 0;
+ int maxWidth = EntryWidth(entryPtr);
+ int x;
+
+ if (Tcl_GetInt(interp, string + 1, &x) != TCL_OK) {
+ goto badIndex;
+ }
+ if (x > maxWidth) {
+ x = maxWidth;
+ roundUp = 1;
+ }
+ *indexPtr = Tk_PointToChar(entryPtr->entry.textLayout,
+ x - entryPtr->entry.layoutX, 0);
+
+ TtkUpdateScrollInfo(entryPtr->entry.xscrollHandle);
+ if (*indexPtr < entryPtr->entry.xscroll.first) {
+ *indexPtr = entryPtr->entry.xscroll.first;
+ }
+
+ /*
+ * Special trick: if the x-position was off-screen to the right,
+ * round the index up to refer to the character just after the
+ * last visible one on the screen. This is needed to enable the
+ * last character to be selected, for example.
+ */
+
+ if (roundUp && (*indexPtr < entryPtr->entry.numChars)) {
+ *indexPtr += 1;
+ }
+ } else {
+ if (Tcl_GetInt(interp, string, indexPtr) != TCL_OK) {
+ goto badIndex;
+ }
+ if (*indexPtr < 0) {
+ *indexPtr = 0;
+ } else if (*indexPtr > entryPtr->entry.numChars) {
+ *indexPtr = entryPtr->entry.numChars;
+ }
+ }
+ return TCL_OK;
+
+badIndex:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad entry index \"%s\"", string));
+ Tcl_SetErrorCode(interp, "TTK", "ENTRY", "INDEX", NULL);
+ return TCL_ERROR;
+}
+
+/* $entry bbox $index --
+ * Return the bounding box of the character at the specified index.
+ */
+static int
+EntryBBoxCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Entry *entryPtr = recordPtr;
+ Ttk_Box b;
+ int index;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index");
+ return TCL_ERROR;
+ }
+ if (EntryIndex(interp, entryPtr, objv[2], &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((index == entryPtr->entry.numChars) && (index > 0)) {
+ index--;
+ }
+ Tk_CharBbox(entryPtr->entry.textLayout, index,
+ &b.x, &b.y, &b.width, &b.height);
+ b.x += entryPtr->entry.layoutX;
+ b.y += entryPtr->entry.layoutY;
+ Tcl_SetObjResult(interp, Ttk_NewBoxObj(b));
+ return TCL_OK;
+}
+
+/* $entry delete $from ?$to? --
+ * Delete the characters in the range [$from,$to).
+ * $to defaults to $from+1 if not specified.
+ */
+static int
+EntryDeleteCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Entry *entryPtr = recordPtr;
+ int first, last;
+
+ if ((objc < 3) || (objc > 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "firstIndex ?lastIndex?");
+ return TCL_ERROR;
+ }
+ if (EntryIndex(interp, entryPtr, objv[2], &first) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ last = first + 1;
+ } else if (EntryIndex(interp, entryPtr, objv[3], &last) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (last >= first && EntryEditable(entryPtr)) {
+ return DeleteChars(entryPtr, first, last - first);
+ }
+ return TCL_OK;
+}
+
+/* $entry get --
+ * Return the current value of the entry widget.
+ */
+static int
+EntryGetCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Entry *entryPtr = recordPtr;
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(entryPtr->entry.string, -1));
+ return TCL_OK;
+}
+
+/* $entry icursor $index --
+ * Set the insert cursor position.
+ */
+static int
+EntryICursorCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Entry *entryPtr = recordPtr;
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "pos");
+ return TCL_ERROR;
+ }
+ if (EntryIndex(interp, entryPtr, objv[2],
+ &entryPtr->entry.insertPos) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ TtkRedisplayWidget(&entryPtr->core);
+ return TCL_OK;
+}
+
+/* $entry index $index --
+ * Return numeric value (0..numChars) of the specified index.
+ */
+static int
+EntryIndexCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Entry *entryPtr = recordPtr;
+ int index;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "string");
+ return TCL_ERROR;
+ }
+ if (EntryIndex(interp, entryPtr, objv[2], &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(index));
+ return TCL_OK;
+}
+
+/* $entry insert $index $text --
+ * Insert $text after position $index.
+ * Silent no-op if the entry is disabled or read-only.
+ */
+static int
+EntryInsertCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Entry *entryPtr = recordPtr;
+ int index;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index text");
+ return TCL_ERROR;
+ }
+ if (EntryIndex(interp, entryPtr, objv[2], &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (EntryEditable(entryPtr)) {
+ return InsertChars(entryPtr, index, Tcl_GetString(objv[3]));
+ }
+ return TCL_OK;
+}
+
+/* $entry selection clear --
+ * Clear selection.
+ */
+static int EntrySelectionClearCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Entry *entryPtr = recordPtr;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ return TCL_ERROR;
+ }
+ entryPtr->entry.selectFirst = entryPtr->entry.selectLast = -1;
+ TtkRedisplayWidget(&entryPtr->core);
+ return TCL_OK;
+}
+
+/* $entry selection present --
+ * Returns 1 if any characters are selected, 0 otherwise.
+ */
+static int EntrySelectionPresentCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Entry *entryPtr = recordPtr;
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp,
+ Tcl_NewBooleanObj(entryPtr->entry.selectFirst >= 0));
+ return TCL_OK;
+}
+
+/* $entry selection range $start $end --
+ * Explicitly set the selection range.
+ */
+static int EntrySelectionRangeCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Entry *entryPtr = recordPtr;
+ int start, end;
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 3, objv, "start end");
+ return TCL_ERROR;
+ }
+ if ( EntryIndex(interp, entryPtr, objv[3], &start) != TCL_OK
+ || EntryIndex(interp, entryPtr, objv[4], &end) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (entryPtr->core.state & TTK_STATE_DISABLED) {
+ return TCL_OK;
+ }
+
+ if (start >= end) {
+ entryPtr->entry.selectFirst = entryPtr->entry.selectLast = -1;
+ } else {
+ entryPtr->entry.selectFirst = start;
+ entryPtr->entry.selectLast = end;
+ EntryOwnSelection(entryPtr);
+ }
+ TtkRedisplayWidget(&entryPtr->core);
+ return TCL_OK;
+}
+
+static const Ttk_Ensemble EntrySelectionCommands[] = {
+ { "clear", EntrySelectionClearCommand,0 },
+ { "present", EntrySelectionPresentCommand,0 },
+ { "range", EntrySelectionRangeCommand,0 },
+ { 0,0,0 }
+};
+
+/* $entry set $value
+ * Sets the value of an entry widget.
+ */
+static int EntrySetCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Entry *entryPtr = recordPtr;
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "value");
+ return TCL_ERROR;
+ }
+ EntrySetValue(entryPtr, Tcl_GetString(objv[2]));
+ return TCL_OK;
+}
+
+/* $entry validate --
+ * Trigger forced validation. Returns 1/0 if validation succeeds/fails
+ * or error status from -validatecommand / -invalidcommand.
+ */
+static int EntryValidateCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Entry *entryPtr = recordPtr;
+ int code;
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ return TCL_ERROR;
+ }
+
+ code = EntryRevalidate(interp, entryPtr, VALIDATE_FORCED);
+
+ if (code == TCL_ERROR)
+ return code;
+
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(code == TCL_OK));
+ return TCL_OK;
+}
+
+/* $entry xview -- horizontal scrolling interface
+ */
+static int EntryXViewCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Entry *entryPtr = recordPtr;
+ if (objc == 3) {
+ int newFirst;
+ if (EntryIndex(interp, entryPtr, objv[2], &newFirst) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ TtkScrollTo(entryPtr->entry.xscrollHandle, newFirst, 1);
+ return TCL_OK;
+ }
+ return TtkScrollviewCommand(interp, objc, objv, entryPtr->entry.xscrollHandle);
+}
+
+static const Ttk_Ensemble EntryCommands[] = {
+ { "bbox", EntryBBoxCommand,0 },
+ { "cget", TtkWidgetCgetCommand,0 },
+ { "configure", TtkWidgetConfigureCommand,0 },
+ { "delete", EntryDeleteCommand,0 },
+ { "get", EntryGetCommand,0 },
+ { "icursor", EntryICursorCommand,0 },
+ { "identify", TtkWidgetIdentifyCommand,0 },
+ { "index", EntryIndexCommand,0 },
+ { "insert", EntryInsertCommand,0 },
+ { "instate", TtkWidgetInstateCommand,0 },
+ { "selection", 0,EntrySelectionCommands },
+ { "state", TtkWidgetStateCommand,0 },
+ { "validate", EntryValidateCommand,0 },
+ { "xview", EntryXViewCommand,0 },
+ { 0,0,0 }
+};
+
+/*------------------------------------------------------------------------
+ * +++ Entry widget definition.
+ */
+
+static WidgetSpec EntryWidgetSpec = {
+ "TEntry", /* className */
+ sizeof(Entry), /* recordSize */
+ EntryOptionSpecs, /* optionSpecs */
+ EntryCommands, /* subcommands */
+ EntryInitialize, /* initializeProc */
+ EntryCleanup, /* cleanupProc */
+ EntryConfigure, /* configureProc */
+ EntryPostConfigure, /* postConfigureProc */
+ TtkWidgetGetLayout, /* getLayoutProc */
+ TtkWidgetSize, /* sizeProc */
+ EntryDoLayout, /* layoutProc */
+ EntryDisplay /* displayProc */
+};
+
+/*------------------------------------------------------------------------
+ * Named indices for the combobox "current" command
+ */
+static const char *const comboboxCurrentIndexNames[] = {
+ "end", NULL
+};
+enum comboboxCurrentIndices {
+ INDEX_END
+};
+
+/*------------------------------------------------------------------------
+ * +++ Combobox widget record.
+ */
+
+typedef struct {
+ Tcl_Obj *postCommandObj;
+ Tcl_Obj *valuesObj;
+ Tcl_Obj *heightObj;
+ int currentIndex;
+} ComboboxPart;
+
+typedef struct {
+ WidgetCore core;
+ EntryPart entry;
+ ComboboxPart combobox;
+} Combobox;
+
+static Tk_OptionSpec ComboboxOptionSpecs[] = {
+ {TK_OPTION_STRING, "-height", "height", "Height",
+ DEF_LIST_HEIGHT, Tk_Offset(Combobox, combobox.heightObj), -1,
+ 0,0,0 },
+ {TK_OPTION_STRING, "-postcommand", "postCommand", "PostCommand",
+ "", Tk_Offset(Combobox, combobox.postCommandObj), -1,
+ 0,0,0 },
+ {TK_OPTION_STRING, "-values", "values", "Values",
+ "", Tk_Offset(Combobox, combobox.valuesObj), -1,
+ 0,0,0 },
+ WIDGET_INHERIT_OPTIONS(EntryOptionSpecs)
+};
+
+/* ComboboxInitialize --
+ * Initialization hook for combobox widgets.
+ */
+static void
+ComboboxInitialize(Tcl_Interp *interp, void *recordPtr)
+{
+ Combobox *cb = recordPtr;
+
+ cb->combobox.currentIndex = -1;
+ TtkTrackElementState(&cb->core);
+ EntryInitialize(interp, recordPtr);
+}
+
+/* ComboboxConfigure --
+ * Configuration hook for combobox widgets.
+ */
+static int
+ComboboxConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
+{
+ Combobox *cbPtr = recordPtr;
+ int unused;
+
+ /* Make sure -values is a valid list:
+ */
+ if (Tcl_ListObjLength(interp,cbPtr->combobox.valuesObj,&unused) != TCL_OK)
+ return TCL_ERROR;
+
+ return EntryConfigure(interp, recordPtr, mask);
+}
+
+/* $cb current ?newIndex? -- get or set current index.
+ * Setting the current index updates the combobox value,
+ * but the value and -values may be changed independently
+ * of the index. Instead of trying to keep currentIndex
+ * in sync at all times, [$cb current] double-checks
+ */
+static int ComboboxCurrentCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Combobox *cbPtr = recordPtr;
+ int currentIndex = cbPtr->combobox.currentIndex;
+ const char *currentValue = cbPtr->entry.string;
+ int nValues;
+ Tcl_Obj **values;
+
+ Tcl_ListObjGetElements(interp,cbPtr->combobox.valuesObj,&nValues,&values);
+
+ if (objc == 2) {
+ /* Check if currentIndex still valid:
+ */
+ if ( currentIndex < 0
+ || currentIndex >= nValues
+ || strcmp(currentValue,Tcl_GetString(values[currentIndex]))
+ )
+ {
+ /* Not valid. Check current value against each element in -values:
+ */
+ for (currentIndex = 0; currentIndex < nValues; ++currentIndex) {
+ if (!strcmp(currentValue,Tcl_GetString(values[currentIndex]))) {
+ break;
+ }
+ }
+ if (currentIndex >= nValues) {
+ /* Not found */
+ currentIndex = -1;
+ }
+ }
+ cbPtr->combobox.currentIndex = currentIndex;
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(currentIndex));
+ return TCL_OK;
+ } else if (objc == 3) {
+ int result, index;
+
+ result = Tcl_GetIndexFromObj(NULL, objv[2], comboboxCurrentIndexNames,
+ "", 0, &index);
+ if (result == TCL_OK) {
+
+ /*
+ * The index is one of the named indices.
+ */
+
+ switch (index) {
+ case INDEX_END:
+ /* "end" index */
+ currentIndex = nValues - 1;
+ break;
+ }
+ } else {
+
+ /*
+ * The index should be just an integer.
+ */
+
+ if (Tcl_GetIntFromObj(NULL, objv[2], &currentIndex) != TCL_OK) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "Incorrect index %s", Tcl_GetString(objv[2])));
+ Tcl_SetErrorCode(interp, "TTK", "COMBOBOX", "IDX_VALUE", NULL);
+ return TCL_ERROR;
+ }
+
+ if (currentIndex < 0 || currentIndex >= nValues) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "Index %s out of range", Tcl_GetString(objv[2])));
+ Tcl_SetErrorCode(interp, "TTK", "COMBOBOX", "IDX_RANGE", NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ cbPtr->combobox.currentIndex = currentIndex;
+
+ return EntrySetValue(recordPtr, Tcl_GetString(values[currentIndex]));
+ } else {
+ Tcl_WrongNumArgs(interp, 2, objv, "?newIndex?");
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Combobox widget definition.
+ */
+static const Ttk_Ensemble ComboboxCommands[] = {
+ { "bbox", EntryBBoxCommand,0 },
+ { "cget", TtkWidgetCgetCommand,0 },
+ { "configure", TtkWidgetConfigureCommand,0 },
+ { "current", ComboboxCurrentCommand,0 },
+ { "delete", EntryDeleteCommand,0 },
+ { "get", EntryGetCommand,0 },
+ { "icursor", EntryICursorCommand,0 },
+ { "identify", TtkWidgetIdentifyCommand,0 },
+ { "index", EntryIndexCommand,0 },
+ { "insert", EntryInsertCommand,0 },
+ { "instate", TtkWidgetInstateCommand,0 },
+ { "selection", 0,EntrySelectionCommands },
+ { "state", TtkWidgetStateCommand,0 },
+ { "set", EntrySetCommand,0 },
+ { "validate", EntryValidateCommand,0 },
+ { "xview", EntryXViewCommand,0 },
+ { 0,0,0 }
+};
+
+static WidgetSpec ComboboxWidgetSpec = {
+ "TCombobox", /* className */
+ sizeof(Combobox), /* recordSize */
+ ComboboxOptionSpecs, /* optionSpecs */
+ ComboboxCommands, /* subcommands */
+ ComboboxInitialize, /* initializeProc */
+ EntryCleanup, /* cleanupProc */
+ ComboboxConfigure, /* configureProc */
+ EntryPostConfigure, /* postConfigureProc */
+ TtkWidgetGetLayout, /* getLayoutProc */
+ TtkWidgetSize, /* sizeProc */
+ EntryDoLayout, /* layoutProc */
+ EntryDisplay /* displayProc */
+};
+
+/*------------------------------------------------------------------------
+ * +++ Spinbox widget.
+ */
+
+typedef struct {
+ Tcl_Obj *valuesObj;
+
+ Tcl_Obj *fromObj;
+ Tcl_Obj *toObj;
+ Tcl_Obj *incrementObj;
+ Tcl_Obj *formatObj;
+
+ Tcl_Obj *wrapObj;
+ Tcl_Obj *commandObj;
+} SpinboxPart;
+
+typedef struct {
+ WidgetCore core;
+ EntryPart entry;
+ SpinboxPart spinbox;
+} Spinbox;
+
+static Tk_OptionSpec SpinboxOptionSpecs[] = {
+ {TK_OPTION_STRING, "-values", "values", "Values",
+ "", Tk_Offset(Spinbox, spinbox.valuesObj), -1,
+ 0,0,0 },
+
+ {TK_OPTION_DOUBLE, "-from", "from", "From",
+ "0", Tk_Offset(Spinbox,spinbox.fromObj), -1,
+ 0,0,0 },
+ {TK_OPTION_DOUBLE, "-to", "to", "To",
+ "0", Tk_Offset(Spinbox,spinbox.toObj), -1,
+ 0,0,0 },
+ {TK_OPTION_DOUBLE, "-increment", "increment", "Increment",
+ "1", Tk_Offset(Spinbox,spinbox.incrementObj), -1,
+ 0,0,0 },
+ {TK_OPTION_STRING, "-format", "format", "Format",
+ "", Tk_Offset(Spinbox, spinbox.formatObj), -1,
+ 0,0,0 },
+
+ {TK_OPTION_STRING, "-command", "command", "Command",
+ "", Tk_Offset(Spinbox, spinbox.commandObj), -1,
+ 0,0,0 },
+ {TK_OPTION_BOOLEAN, "-wrap", "wrap", "Wrap",
+ "0", Tk_Offset(Spinbox,spinbox.wrapObj), -1,
+ 0,0,0 },
+
+ WIDGET_INHERIT_OPTIONS(EntryOptionSpecs)
+};
+
+/* SpinboxInitialize --
+ * Initialization hook for spinbox widgets.
+ */
+static void
+SpinboxInitialize(Tcl_Interp *interp, void *recordPtr)
+{
+ Spinbox *sb = recordPtr;
+ TtkTrackElementState(&sb->core);
+ EntryInitialize(interp, recordPtr);
+}
+
+/* SpinboxConfigure --
+ * Configuration hook for spinbox widgets.
+ */
+static int
+SpinboxConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
+{
+ Spinbox *sb = recordPtr;
+ int unused;
+
+ /* Make sure -values is a valid list:
+ */
+ if (Tcl_ListObjLength(interp,sb->spinbox.valuesObj,&unused) != TCL_OK)
+ return TCL_ERROR;
+
+ return EntryConfigure(interp, recordPtr, mask);
+}
+
+static const Ttk_Ensemble SpinboxCommands[] = {
+ { "bbox", EntryBBoxCommand,0 },
+ { "cget", TtkWidgetCgetCommand,0 },
+ { "configure", TtkWidgetConfigureCommand,0 },
+ { "delete", EntryDeleteCommand,0 },
+ { "get", EntryGetCommand,0 },
+ { "icursor", EntryICursorCommand,0 },
+ { "identify", TtkWidgetIdentifyCommand,0 },
+ { "index", EntryIndexCommand,0 },
+ { "insert", EntryInsertCommand,0 },
+ { "instate", TtkWidgetInstateCommand,0 },
+ { "selection", 0,EntrySelectionCommands },
+ { "state", TtkWidgetStateCommand,0 },
+ { "set", EntrySetCommand,0 },
+ { "validate", EntryValidateCommand,0 },
+ { "xview", EntryXViewCommand,0 },
+ { 0,0,0 }
+};
+
+static WidgetSpec SpinboxWidgetSpec = {
+ "TSpinbox", /* className */
+ sizeof(Spinbox), /* recordSize */
+ SpinboxOptionSpecs, /* optionSpecs */
+ SpinboxCommands, /* subcommands */
+ SpinboxInitialize, /* initializeProc */
+ EntryCleanup, /* cleanupProc */
+ SpinboxConfigure, /* configureProc */
+ EntryPostConfigure, /* postConfigureProc */
+ TtkWidgetGetLayout, /* getLayoutProc */
+ TtkWidgetSize, /* sizeProc */
+ EntryDoLayout, /* layoutProc */
+ EntryDisplay /* displayProc */
+};
+
+/*------------------------------------------------------------------------
+ * +++ Textarea element.
+ *
+ * Text display area for Entry widgets.
+ * Just computes requested size; display is handled by the widget itself.
+ */
+
+typedef struct {
+ Tcl_Obj *fontObj;
+ Tcl_Obj *widthObj;
+} TextareaElement;
+
+static Ttk_ElementOptionSpec TextareaElementOptions[] = {
+ { "-font", TK_OPTION_FONT,
+ Tk_Offset(TextareaElement,fontObj), DEF_ENTRY_FONT },
+ { "-width", TK_OPTION_INT,
+ Tk_Offset(TextareaElement,widthObj), "20" },
+ { NULL, 0, 0, NULL }
+};
+
+static void TextareaElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ TextareaElement *textarea = elementRecord;
+ Tk_Font font = Tk_GetFontFromObj(tkwin, textarea->fontObj);
+ int avgWidth = Tk_TextWidth(font, "0", 1);
+ Tk_FontMetrics fm;
+ int prefWidth = 1;
+
+ Tk_GetFontMetrics(font, &fm);
+ Tcl_GetIntFromObj(NULL, textarea->widthObj, &prefWidth);
+ if (prefWidth <= 0)
+ prefWidth = 1;
+
+ *heightPtr = fm.linespace;
+ *widthPtr = prefWidth * avgWidth;
+}
+
+static Ttk_ElementSpec TextareaElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(TextareaElement),
+ TextareaElementOptions,
+ TextareaElementSize,
+ TtkNullElementDraw
+};
+
+/*------------------------------------------------------------------------
+ * +++ Widget layouts.
+ */
+
+TTK_BEGIN_LAYOUT(EntryLayout)
+ TTK_GROUP("Entry.field", TTK_FILL_BOTH|TTK_BORDER,
+ TTK_GROUP("Entry.padding", TTK_FILL_BOTH,
+ TTK_NODE("Entry.textarea", TTK_FILL_BOTH)))
+TTK_END_LAYOUT
+
+TTK_BEGIN_LAYOUT(ComboboxLayout)
+ TTK_GROUP("Combobox.field", TTK_FILL_BOTH,
+ TTK_NODE("Combobox.downarrow", TTK_PACK_RIGHT|TTK_FILL_Y)
+ TTK_GROUP("Combobox.padding", TTK_FILL_BOTH|TTK_PACK_LEFT|TTK_EXPAND,
+ TTK_NODE("Combobox.textarea", TTK_FILL_BOTH)))
+TTK_END_LAYOUT
+
+TTK_BEGIN_LAYOUT(SpinboxLayout)
+ TTK_GROUP("Spinbox.field", TTK_PACK_TOP|TTK_FILL_X,
+ TTK_GROUP("null", TTK_PACK_RIGHT,
+ TTK_NODE("Spinbox.uparrow", TTK_PACK_TOP|TTK_STICK_E)
+ TTK_NODE("Spinbox.downarrow", TTK_PACK_BOTTOM|TTK_STICK_E))
+ TTK_GROUP("Spinbox.padding", TTK_FILL_BOTH,
+ TTK_NODE("Spinbox.textarea", TTK_FILL_BOTH)))
+TTK_END_LAYOUT
+
+/*------------------------------------------------------------------------
+ * +++ Initialization.
+ */
+MODULE_SCOPE
+void TtkEntry_Init(Tcl_Interp *interp)
+{
+ Ttk_Theme themePtr = Ttk_GetDefaultTheme(interp);
+
+ Ttk_RegisterElement(interp, themePtr, "textarea", &TextareaElementSpec, 0);
+
+ Ttk_RegisterLayout(themePtr, "TEntry", EntryLayout);
+ Ttk_RegisterLayout(themePtr, "TCombobox", ComboboxLayout);
+ Ttk_RegisterLayout(themePtr, "TSpinbox", SpinboxLayout);
+
+ RegisterWidget(interp, "ttk::entry", &EntryWidgetSpec);
+ RegisterWidget(interp, "ttk::combobox", &ComboboxWidgetSpec);
+ RegisterWidget(interp, "ttk::spinbox", &SpinboxWidgetSpec);
+}
+
+/*EOF*/
diff --git a/tk8.6/generic/ttk/ttkFrame.c b/tk8.6/generic/ttk/ttkFrame.c
new file mode 100644
index 0000000..3e50a7f
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkFrame.c
@@ -0,0 +1,653 @@
+/*
+ * Copyright (c) 2004, Joe English
+ *
+ * ttk::frame and ttk::labelframe widgets.
+ */
+
+#include <tk.h>
+
+#include "ttkTheme.h"
+#include "ttkWidget.h"
+#include "ttkManager.h"
+
+/* ======================================================================
+ * +++ Frame widget:
+ */
+
+typedef struct {
+ Tcl_Obj *borderWidthObj;
+ Tcl_Obj *paddingObj;
+ Tcl_Obj *reliefObj;
+ Tcl_Obj *widthObj;
+ Tcl_Obj *heightObj;
+} FramePart;
+
+typedef struct {
+ WidgetCore core;
+ FramePart frame;
+} Frame;
+
+static Tk_OptionSpec FrameOptionSpecs[] = {
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", NULL,
+ Tk_Offset(Frame,frame.borderWidthObj), -1,
+ TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
+ {TK_OPTION_STRING, "-padding", "padding", "Pad", NULL,
+ Tk_Offset(Frame,frame.paddingObj), -1,
+ TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief", NULL,
+ Tk_Offset(Frame,frame.reliefObj), -1,
+ TK_OPTION_NULL_OK,0,0 },
+ {TK_OPTION_PIXELS, "-width", "width", "Width", "0",
+ Tk_Offset(Frame,frame.widthObj), -1,
+ 0,0,GEOMETRY_CHANGED },
+ {TK_OPTION_PIXELS, "-height", "height", "Height", "0",
+ Tk_Offset(Frame,frame.heightObj), -1,
+ 0,0,GEOMETRY_CHANGED },
+
+ WIDGET_TAKEFOCUS_FALSE,
+ WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)
+};
+
+static const Ttk_Ensemble FrameCommands[] = {
+ { "configure", TtkWidgetConfigureCommand,0 },
+ { "cget", TtkWidgetCgetCommand,0 },
+ { "instate", TtkWidgetInstateCommand,0 },
+ { "state", TtkWidgetStateCommand,0 },
+ { "identify", TtkWidgetIdentifyCommand,0 },
+ { 0,0,0 }
+};
+
+/*
+ * FrameMargins --
+ * Compute internal margins for a frame widget.
+ * This includes the -borderWidth, plus any additional -padding.
+ */
+static Ttk_Padding FrameMargins(Frame *framePtr)
+{
+ Ttk_Padding margins = Ttk_UniformPadding(0);
+
+ /* Check -padding:
+ */
+ if (framePtr->frame.paddingObj) {
+ Ttk_GetPaddingFromObj(NULL,
+ framePtr->core.tkwin, framePtr->frame.paddingObj, &margins);
+ }
+
+ /* Add padding for border:
+ */
+ if (framePtr->frame.borderWidthObj) {
+ int border = 0;
+ Tk_GetPixelsFromObj(NULL,
+ framePtr->core.tkwin, framePtr->frame.borderWidthObj, &border);
+ margins = Ttk_AddPadding(margins, Ttk_UniformPadding((short)border));
+ }
+
+ return margins;
+}
+
+/* FrameSize procedure --
+ * The frame doesn't request a size of its own by default,
+ * but it does have an internal border. See also <<NOTE-SIZE>>
+ */
+static int FrameSize(void *recordPtr, int *widthPtr, int *heightPtr)
+{
+ Frame *framePtr = recordPtr;
+ Ttk_SetMargins(framePtr->core.tkwin, FrameMargins(framePtr));
+ return 0;
+}
+
+/*
+ * FrameConfigure -- configure hook.
+ * <<NOTE-SIZE>> Usually the size of a frame is controlled by
+ * a geometry manager (pack, grid); the -width and -height
+ * options are only effective if geometry propagation is turned
+ * off or if the [place] GM is used for child widgets.
+ *
+ * To avoid geometry blinking, we issue a geometry request
+ * in the Configure hook instead of the Size hook, and only
+ * if -width and/or -height is nonzero and one of them
+ * or the other size-related options (-borderwidth, -padding)
+ * has been changed.
+ */
+
+static int FrameConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
+{
+ Frame *framePtr = recordPtr;
+ int width, height;
+
+ /*
+ * Make sure -padding resource, if present, is correct:
+ */
+ if (framePtr->frame.paddingObj) {
+ Ttk_Padding unused;
+ if (Ttk_GetPaddingFromObj(interp,
+ framePtr->core.tkwin,
+ framePtr->frame.paddingObj,
+ &unused) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+
+ /* See <<NOTE-SIZE>>
+ */
+ if ( TCL_OK != Tk_GetPixelsFromObj(
+ interp,framePtr->core.tkwin,framePtr->frame.widthObj,&width)
+ || TCL_OK != Tk_GetPixelsFromObj(
+ interp,framePtr->core.tkwin,framePtr->frame.heightObj,&height)
+ )
+ {
+ return TCL_ERROR;
+ }
+
+ if ((width > 0 || height > 0) && (mask & GEOMETRY_CHANGED)) {
+ Tk_GeometryRequest(framePtr->core.tkwin, width, height);
+ }
+
+ return TtkCoreConfigure(interp, recordPtr, mask);
+}
+
+static WidgetSpec FrameWidgetSpec = {
+ "TFrame", /* className */
+ sizeof(Frame), /* recordSize */
+ FrameOptionSpecs, /* optionSpecs */
+ FrameCommands, /* subcommands */
+ TtkNullInitialize, /* initializeProc */
+ TtkNullCleanup, /* cleanupProc */
+ FrameConfigure, /* configureProc */
+ TtkNullPostConfigure, /* postConfigureProc */
+ TtkWidgetGetLayout, /* getLayoutProc */
+ FrameSize, /* sizeProc */
+ TtkWidgetDoLayout, /* layoutProc */
+ TtkWidgetDisplay /* displayProc */
+};
+
+TTK_BEGIN_LAYOUT(FrameLayout)
+ TTK_NODE("Frame.border", TTK_FILL_BOTH)
+TTK_END_LAYOUT
+
+/* ======================================================================
+ * +++ Labelframe widget:
+ */
+
+#define DEFAULT_LABELINSET 8
+#define DEFAULT_BORDERWIDTH 2
+
+int TtkGetLabelAnchorFromObj(
+ Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_PositionSpec *anchorPtr)
+{
+ const char *string = Tcl_GetString(objPtr);
+ char c = *string++;
+ Ttk_PositionSpec flags = 0;
+
+ /* First character determines side:
+ */
+ switch (c) {
+ case 'w' : flags = TTK_PACK_LEFT; break;
+ case 'e' : flags = TTK_PACK_RIGHT; break;
+ case 'n' : flags = TTK_PACK_TOP; break;
+ case 's' : flags = TTK_PACK_BOTTOM; break;
+ default : goto error;
+ }
+
+ /* Remaining characters are as per -sticky:
+ */
+ while ((c = *string++) != '\0') {
+ switch (c) {
+ case 'w' : flags |= TTK_STICK_W; break;
+ case 'e' : flags |= TTK_STICK_E; break;
+ case 'n' : flags |= TTK_STICK_N; break;
+ case 's' : flags |= TTK_STICK_S; break;
+ default : goto error;
+ }
+ }
+
+ *anchorPtr = flags;
+ return TCL_OK;
+
+error:
+ if (interp) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "Bad label anchor specification %s", Tcl_GetString(objPtr)));
+ Tcl_SetErrorCode(interp, "TTK", "LABEL", "ANCHOR", NULL);
+ }
+ return TCL_ERROR;
+}
+
+/* LabelAnchorSide --
+ * Returns the side corresponding to a LabelAnchor value.
+ */
+static Ttk_Side LabelAnchorSide(Ttk_PositionSpec flags)
+{
+ if (flags & TTK_PACK_LEFT) return TTK_SIDE_LEFT;
+ else if (flags & TTK_PACK_RIGHT) return TTK_SIDE_RIGHT;
+ else if (flags & TTK_PACK_TOP) return TTK_SIDE_TOP;
+ else if (flags & TTK_PACK_BOTTOM) return TTK_SIDE_BOTTOM;
+ /*NOTREACHED*/
+ return TTK_SIDE_TOP;
+}
+
+/*
+ * Labelframe widget record:
+ */
+typedef struct {
+ Tcl_Obj *labelAnchorObj;
+ Tcl_Obj *textObj;
+ Tcl_Obj *underlineObj;
+ Tk_Window labelWidget;
+
+ Ttk_Manager *mgr;
+ Ttk_Layout labelLayout; /* Sublayout for label */
+ Ttk_Box labelParcel; /* Set in layoutProc */
+} LabelframePart;
+
+typedef struct {
+ WidgetCore core;
+ FramePart frame;
+ LabelframePart label;
+} Labelframe;
+
+#define LABELWIDGET_CHANGED 0x100
+
+static Tk_OptionSpec LabelframeOptionSpecs[] = {
+ {TK_OPTION_STRING, "-labelanchor", "labelAnchor", "LabelAnchor",
+ "nw", Tk_Offset(Labelframe, label.labelAnchorObj),-1,
+ 0,0,GEOMETRY_CHANGED},
+ {TK_OPTION_STRING, "-text", "text", "Text", "",
+ Tk_Offset(Labelframe,label.textObj), -1,
+ 0,0,GEOMETRY_CHANGED },
+ {TK_OPTION_INT, "-underline", "underline", "Underline",
+ "-1", Tk_Offset(Labelframe,label.underlineObj), -1,
+ 0,0,0 },
+ {TK_OPTION_WINDOW, "-labelwidget", "labelWidget", "LabelWidget", NULL,
+ -1, Tk_Offset(Labelframe,label.labelWidget),
+ TK_OPTION_NULL_OK,0,LABELWIDGET_CHANGED|GEOMETRY_CHANGED },
+
+ WIDGET_INHERIT_OPTIONS(FrameOptionSpecs)
+};
+
+/*
+ * Labelframe style parameters:
+ */
+typedef struct {
+ int borderWidth; /* border width */
+ Ttk_Padding padding; /* internal padding */
+ Ttk_PositionSpec labelAnchor; /* corner/side to place label */
+ Ttk_Padding labelMargins; /* extra space around label */
+ int labelOutside; /* true=>place label outside border */
+} LabelframeStyle;
+
+static void LabelframeStyleOptions(Labelframe *lf, LabelframeStyle *style)
+{
+ Ttk_Layout layout = lf->core.layout;
+ Tcl_Obj *objPtr;
+
+ style->borderWidth = DEFAULT_BORDERWIDTH;
+ style->padding = Ttk_UniformPadding(0);
+ style->labelAnchor = TTK_PACK_TOP | TTK_STICK_W;
+ style->labelOutside = 0;
+
+ if ((objPtr = Ttk_QueryOption(layout, "-borderwidth", 0)) != NULL) {
+ Tk_GetPixelsFromObj(NULL, lf->core.tkwin, objPtr, &style->borderWidth);
+ }
+ if ((objPtr = Ttk_QueryOption(layout, "-padding", 0)) != NULL) {
+ Ttk_GetPaddingFromObj(NULL, lf->core.tkwin, objPtr, &style->padding);
+ }
+ if ((objPtr = Ttk_QueryOption(layout,"-labelanchor", 0)) != NULL) {
+ TtkGetLabelAnchorFromObj(NULL, objPtr, &style->labelAnchor);
+ }
+ if ((objPtr = Ttk_QueryOption(layout,"-labelmargins", 0)) != NULL) {
+ Ttk_GetBorderFromObj(NULL, objPtr, &style->labelMargins);
+ } else {
+ if (style->labelAnchor & (TTK_PACK_TOP|TTK_PACK_BOTTOM)) {
+ style->labelMargins =
+ Ttk_MakePadding(DEFAULT_LABELINSET,0,DEFAULT_LABELINSET,0);
+ } else {
+ style->labelMargins =
+ Ttk_MakePadding(0,DEFAULT_LABELINSET,0,DEFAULT_LABELINSET);
+ }
+ }
+ if ((objPtr = Ttk_QueryOption(layout,"-labeloutside", 0)) != NULL) {
+ Tcl_GetBooleanFromObj(NULL, objPtr, &style->labelOutside);
+ }
+
+ return;
+}
+
+/* LabelframeLabelSize --
+ * Extract the requested width and height of the labelframe's label:
+ * taken from the label widget if specified, otherwise the text label.
+ */
+static void
+LabelframeLabelSize(Labelframe *lframePtr, int *widthPtr, int *heightPtr)
+{
+ Tk_Window labelWidget = lframePtr->label.labelWidget;
+ Ttk_Layout labelLayout = lframePtr->label.labelLayout;
+
+ if (labelWidget) {
+ *widthPtr = Tk_ReqWidth(labelWidget);
+ *heightPtr = Tk_ReqHeight(labelWidget);
+ } else if (labelLayout) {
+ Ttk_LayoutSize(labelLayout, 0, widthPtr, heightPtr);
+ } else {
+ *widthPtr = *heightPtr = 0;
+ }
+}
+
+/*
+ * LabelframeSize --
+ * Like the frame, this doesn't request a size of its own
+ * but it does have internal padding and a minimum size.
+ */
+static int LabelframeSize(void *recordPtr, int *widthPtr, int *heightPtr)
+{
+ Labelframe *lframePtr = recordPtr;
+ WidgetCore *corePtr = &lframePtr->core;
+ Ttk_Padding margins;
+ LabelframeStyle style;
+ int labelWidth, labelHeight;
+
+ LabelframeStyleOptions(lframePtr, &style);
+
+ /* Compute base margins (See also: FrameMargins)
+ */
+ margins = Ttk_AddPadding(
+ style.padding, Ttk_UniformPadding((short)style.borderWidth));
+
+ /* Adjust margins based on label size and position:
+ */
+ LabelframeLabelSize(lframePtr, &labelWidth, &labelHeight);
+ labelWidth += Ttk_PaddingWidth(style.labelMargins);
+ labelHeight += Ttk_PaddingHeight(style.labelMargins);
+
+ switch (LabelAnchorSide(style.labelAnchor)) {
+ case TTK_SIDE_LEFT: margins.left += labelWidth; break;
+ case TTK_SIDE_RIGHT: margins.right += labelWidth; break;
+ case TTK_SIDE_TOP: margins.top += labelHeight; break;
+ case TTK_SIDE_BOTTOM: margins.bottom += labelHeight; break;
+ }
+
+ Ttk_SetMargins(corePtr->tkwin,margins);
+
+ /* Request minimum size based on border width and label size:
+ */
+ Tk_SetMinimumRequestSize(corePtr->tkwin,
+ labelWidth + 2*style.borderWidth,
+ labelHeight + 2*style.borderWidth);
+
+ return 0;
+}
+
+/*
+ * LabelframeGetLayout --
+ * Getlayout widget hook.
+ */
+
+static Ttk_Layout LabelframeGetLayout(
+ Tcl_Interp *interp, Ttk_Theme theme, void *recordPtr)
+{
+ Labelframe *lf = recordPtr;
+ Ttk_Layout frameLayout = TtkWidgetGetLayout(interp, theme, recordPtr);
+ Ttk_Layout labelLayout;
+
+ if (!frameLayout) {
+ return NULL;
+ }
+
+ labelLayout = Ttk_CreateSublayout(
+ interp, theme, frameLayout, ".Label", lf->core.optionTable);
+
+ if (labelLayout) {
+ if (lf->label.labelLayout) {
+ Ttk_FreeLayout(lf->label.labelLayout);
+ }
+ Ttk_RebindSublayout(labelLayout, recordPtr);
+ lf->label.labelLayout = labelLayout;
+ }
+
+ return frameLayout;
+}
+
+/*
+ * LabelframeDoLayout --
+ * Labelframe layout hook.
+ *
+ * Side effects: Computes labelParcel.
+ */
+
+static void LabelframeDoLayout(void *recordPtr)
+{
+ Labelframe *lframePtr = recordPtr;
+ WidgetCore *corePtr = &lframePtr->core;
+ int lw, lh; /* Label width and height */
+ LabelframeStyle style;
+ Ttk_Box borderParcel = Ttk_WinBox(lframePtr->core.tkwin);
+ Ttk_Box labelParcel;
+
+ /*
+ * Compute label parcel:
+ */
+ LabelframeStyleOptions(lframePtr, &style);
+ LabelframeLabelSize(lframePtr, &lw, &lh);
+ lw += Ttk_PaddingWidth(style.labelMargins);
+ lh += Ttk_PaddingHeight(style.labelMargins);
+
+ labelParcel = Ttk_PadBox(
+ Ttk_PositionBox(&borderParcel, lw, lh, style.labelAnchor),
+ style.labelMargins);
+
+ if (!style.labelOutside) {
+ /* Move border edge so it's over label:
+ */
+ switch (LabelAnchorSide(style.labelAnchor)) {
+ case TTK_SIDE_LEFT: borderParcel.x -= lw / 2;
+ case TTK_SIDE_RIGHT: borderParcel.width += lw/2; break;
+ case TTK_SIDE_TOP: borderParcel.y -= lh / 2;
+ case TTK_SIDE_BOTTOM: borderParcel.height += lh / 2; break;
+ }
+ }
+
+ /*
+ * Place border and label:
+ */
+ Ttk_PlaceLayout(corePtr->layout, corePtr->state, borderParcel);
+ if (lframePtr->label.labelLayout) {
+ Ttk_PlaceLayout(
+ lframePtr->label.labelLayout, corePtr->state, labelParcel);
+ }
+ /* labelWidget placed in LabelframePlaceSlaves GM hook */
+ lframePtr->label.labelParcel = labelParcel;
+}
+
+static void LabelframeDisplay(void *recordPtr, Drawable d)
+{
+ Labelframe *lframePtr = recordPtr;
+ Ttk_DrawLayout(lframePtr->core.layout, lframePtr->core.state, d);
+ if (lframePtr->label.labelLayout) {
+ Ttk_DrawLayout(lframePtr->label.labelLayout, lframePtr->core.state, d);
+ }
+}
+
+/* +++ Labelframe geometry manager hooks.
+ */
+
+/* LabelframePlaceSlaves --
+ * Sets the position and size of the labelwidget.
+ */
+static void LabelframePlaceSlaves(void *recordPtr)
+{
+ Labelframe *lframe = recordPtr;
+
+ if (Ttk_NumberSlaves(lframe->label.mgr) == 1) {
+ Ttk_Box b;
+ LabelframeDoLayout(recordPtr);
+ b = lframe->label.labelParcel;
+ /* ASSERT: slave #0 is lframe->label.labelWidget */
+ Ttk_PlaceSlave(lframe->label.mgr, 0, b.x,b.y,b.width,b.height);
+ }
+}
+
+static int LabelRequest(void *managerData, int index, int width, int height)
+{
+ return 1;
+}
+
+/* LabelRemoved --
+ * Unset the -labelwidget option.
+ *
+ * <<NOTE-LABELREMOVED>>:
+ * This routine is also called when the widget voluntarily forgets
+ * the slave in LabelframeConfigure.
+ */
+static void LabelRemoved(void *managerData, int slaveIndex)
+{
+ Labelframe *lframe = managerData;
+ lframe->label.labelWidget = 0;
+}
+
+static Ttk_ManagerSpec LabelframeManagerSpec = {
+ { "labelframe", Ttk_GeometryRequestProc, Ttk_LostSlaveProc },
+ LabelframeSize,
+ LabelframePlaceSlaves,
+ LabelRequest,
+ LabelRemoved
+};
+
+/* LabelframeInitialize --
+ * Initialization hook.
+ */
+static void LabelframeInitialize(Tcl_Interp *interp, void *recordPtr)
+{
+ Labelframe *lframe = recordPtr;
+
+ lframe->label.mgr = Ttk_CreateManager(
+ &LabelframeManagerSpec, lframe, lframe->core.tkwin);
+ lframe->label.labelWidget = 0;
+ lframe->label.labelLayout = 0;
+ lframe->label.labelParcel = Ttk_MakeBox(-1,-1,-1,-1);
+}
+
+/* LabelframeCleanup --
+ * Cleanup hook.
+ */
+static void LabelframeCleanup(void *recordPtr)
+{
+ Labelframe *lframe = recordPtr;
+ Ttk_DeleteManager(lframe->label.mgr);
+ if (lframe->label.labelLayout) {
+ Ttk_FreeLayout(lframe->label.labelLayout);
+ }
+}
+
+/* RaiseLabelWidget --
+ * Raise the -labelwidget to ensure that the labelframe doesn't
+ * obscure it (if it's not a direct child), or bring it to
+ * the top of the stacking order (if it is).
+ */
+static void RaiseLabelWidget(Labelframe *lframe)
+{
+ Tk_Window parent = Tk_Parent(lframe->label.labelWidget);
+ Tk_Window sibling = NULL;
+ Tk_Window w = lframe->core.tkwin;
+
+ while (w && w != parent) {
+ sibling = w;
+ w = Tk_Parent(w);
+ }
+
+ Tk_RestackWindow(lframe->label.labelWidget, Above, sibling);
+}
+
+/* LabelframeConfigure --
+ * Configuration hook.
+ */
+static int LabelframeConfigure(Tcl_Interp *interp,void *recordPtr,int mask)
+{
+ Labelframe *lframePtr = recordPtr;
+ Tk_Window labelWidget = lframePtr->label.labelWidget;
+ Ttk_PositionSpec unused;
+
+ /* Validate options:
+ */
+ if (mask & LABELWIDGET_CHANGED && labelWidget != NULL) {
+ if (!Ttk_Maintainable(interp, labelWidget, lframePtr->core.tkwin)) {
+ return TCL_ERROR;
+ }
+ }
+
+ if (TtkGetLabelAnchorFromObj(
+ interp, lframePtr->label.labelAnchorObj, &unused) != TCL_OK)
+ {
+ return TCL_ERROR;
+ }
+
+ /* Base class configuration:
+ */
+ if (FrameConfigure(interp, recordPtr, mask) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /* Update -labelwidget changes, if any:
+ */
+ if (mask & LABELWIDGET_CHANGED) {
+ if (Ttk_NumberSlaves(lframePtr->label.mgr) == 1) {
+ Ttk_ForgetSlave(lframePtr->label.mgr, 0);
+ /* Restore labelWidget field (see <<NOTE-LABELREMOVED>>)
+ */
+ lframePtr->label.labelWidget = labelWidget;
+ }
+
+ if (labelWidget) {
+ Ttk_InsertSlave(lframePtr->label.mgr, 0, labelWidget, NULL);
+ RaiseLabelWidget(lframePtr);
+ }
+ }
+
+ if (mask & GEOMETRY_CHANGED) {
+ Ttk_ManagerSizeChanged(lframePtr->label.mgr);
+ Ttk_ManagerLayoutChanged(lframePtr->label.mgr);
+ }
+
+ return TCL_OK;
+}
+
+static WidgetSpec LabelframeWidgetSpec = {
+ "TLabelframe", /* className */
+ sizeof(Labelframe), /* recordSize */
+ LabelframeOptionSpecs, /* optionSpecs */
+ FrameCommands, /* subcommands */
+ LabelframeInitialize, /* initializeProc */
+ LabelframeCleanup, /* cleanupProc */
+ LabelframeConfigure, /* configureProc */
+ TtkNullPostConfigure, /* postConfigureProc */
+ LabelframeGetLayout, /* getLayoutProc */
+ LabelframeSize, /* sizeProc */
+ LabelframeDoLayout, /* layoutProc */
+ LabelframeDisplay /* displayProc */
+};
+
+TTK_BEGIN_LAYOUT(LabelframeLayout)
+ TTK_NODE("Labelframe.border", TTK_FILL_BOTH)
+TTK_END_LAYOUT
+
+TTK_BEGIN_LAYOUT(LabelSublayout)
+ TTK_GROUP("Label.fill", TTK_FILL_BOTH,
+ TTK_NODE("Label.text", TTK_FILL_BOTH))
+TTK_END_LAYOUT
+
+/* ======================================================================
+ * +++ Initialization.
+ */
+
+MODULE_SCOPE
+void TtkFrame_Init(Tcl_Interp *interp)
+{
+ Ttk_Theme theme = Ttk_GetDefaultTheme(interp);
+
+ Ttk_RegisterLayout(theme, "TFrame", FrameLayout);
+ Ttk_RegisterLayout(theme, "TLabelframe", LabelframeLayout);
+ Ttk_RegisterLayout(theme, "Label", LabelSublayout);
+
+ RegisterWidget(interp, "ttk::frame", &FrameWidgetSpec);
+ RegisterWidget(interp, "ttk::labelframe", &LabelframeWidgetSpec);
+}
+
diff --git a/tk8.6/generic/ttk/ttkGenStubs.tcl b/tk8.6/generic/ttk/ttkGenStubs.tcl
new file mode 100644
index 0000000..8047e3f
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkGenStubs.tcl
@@ -0,0 +1,963 @@
+# ttkGenStubs.tcl --
+#
+# This script generates a set of stub files for a given
+# interface.
+#
+#
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# SOURCE: tcl/tools/genStubs.tcl, revision 1.44
+#
+# CHANGES:
+# + Second argument to "declare" is used as a status guard
+# instead of a platform guard.
+# + Allow trailing semicolon in function declarations
+#
+
+namespace eval genStubs {
+ # libraryName --
+ #
+ # The name of the entire library. This value is used to compute
+ # the USE_*_STUBS macro and the name of the init file.
+
+ variable libraryName "UNKNOWN"
+
+ # interfaces --
+ #
+ # An array indexed by interface name that is used to maintain
+ # the set of valid interfaces. The value is empty.
+
+ array set interfaces {}
+
+ # curName --
+ #
+ # The name of the interface currently being defined.
+
+ variable curName "UNKNOWN"
+
+ # scspec --
+ #
+ # Storage class specifier for external function declarations.
+ # Normally "EXTERN", may be set to something like XYZAPI
+ #
+ variable scspec "EXTERN"
+
+ # epoch, revision --
+ #
+ # The epoch and revision numbers of the interface currently being defined.
+ # (@@@TODO: should be an array mapping interface names -> numbers)
+ #
+
+ variable epoch {}
+ variable revision 0
+
+ # hooks --
+ #
+ # An array indexed by interface name that contains the set of
+ # subinterfaces that should be defined for a given interface.
+
+ array set hooks {}
+
+ # stubs --
+ #
+ # This three dimensional array is indexed first by interface name,
+ # second by field name, and third by a numeric offset or the
+ # constant "lastNum". The lastNum entry contains the largest
+ # numeric offset used for a given interface.
+ #
+ # Field "decl,$i" contains the C function specification that
+ # should be used for the given entry in the stub table. The spec
+ # consists of a list in the form returned by parseDecl.
+ # Other fields TBD later.
+
+ array set stubs {}
+
+ # outDir --
+ #
+ # The directory where the generated files should be placed.
+
+ variable outDir .
+}
+
+# genStubs::library --
+#
+# This function is used in the declarations file to set the name
+# of the library that the interfaces are associated with (e.g. "tcl").
+# This value will be used to define the inline conditional macro.
+#
+# Arguments:
+# name The library name.
+#
+# Results:
+# None.
+
+proc genStubs::library {name} {
+ variable libraryName $name
+}
+
+# genStubs::interface --
+#
+# This function is used in the declarations file to set the name
+# of the interface currently being defined.
+#
+# Arguments:
+# name The name of the interface.
+#
+# Results:
+# None.
+
+proc genStubs::interface {name} {
+ variable curName $name
+ variable interfaces
+ variable stubs
+
+ set interfaces($name) {}
+ set stubs($name,lastNum) 0
+ return
+}
+
+# genStubs::scspec --
+#
+# Define the storage class macro used for external function declarations.
+# Typically, this will be a macro like XYZAPI or EXTERN that
+# expands to either DLLIMPORT or DLLEXPORT, depending on whether
+# -DBUILD_XYZ has been set.
+#
+proc genStubs::scspec {value} {
+ variable scspec $value
+}
+
+# genStubs::epoch --
+#
+# Define the epoch number for this library. The epoch
+# should be incrememented when a release is made that
+# contains incompatible changes to the public API.
+#
+proc genStubs::epoch {value} {
+ variable epoch $value
+}
+
+# genStubs::hooks --
+#
+# This function defines the subinterface hooks for the current
+# interface.
+#
+# Arguments:
+# names The ordered list of interfaces that are reachable through the
+# hook vector.
+#
+# Results:
+# None.
+
+proc genStubs::hooks {names} {
+ variable curName
+ variable hooks
+
+ set hooks($curName) $names
+ return
+}
+
+# genStubs::declare --
+#
+# This function is used in the declarations file to declare a new
+# interface entry.
+#
+# Arguments:
+# index The index number of the interface.
+# status Status of the interface: one of "current",
+# "deprecated", or "obsolete".
+# decl The C function declaration, or {} for an undefined
+# entry.
+#
+# Results:
+# None.
+
+proc genStubs::declare {args} {
+ variable stubs
+ variable curName
+ variable revision
+
+ incr revision
+ if {[llength $args] == 2} {
+ lassign $args index decl
+ set status current
+ } elseif {[llength $args] == 3} {
+ lassign $args index status decl
+ } else {
+ puts stderr "wrong # args: declare $args"
+ return
+ }
+
+ # Check for duplicate declarations, then add the declaration and
+ # bump the lastNum counter if necessary.
+
+ if {[info exists stubs($curName,decl,$index)]} {
+ puts stderr "Duplicate entry: $index"
+ }
+ regsub -all "\[ \t\n\]+" [string trim $decl] " " decl
+ set decl [parseDecl $decl]
+
+ set stubs($curName,status,$index) $status
+ set stubs($curName,decl,$index) $decl
+
+ if {$index > $stubs($curName,lastNum)} {
+ set stubs($curName,lastNum) $index
+ }
+ return
+}
+
+# genStubs::export --
+#
+# This function is used in the declarations file to declare a symbol
+# that is exported from the library but is not in the stubs table.
+#
+# Arguments:
+# decl The C function declaration, or {} for an undefined
+# entry.
+#
+# Results:
+# None.
+
+proc genStubs::export {args} {
+ if {[llength $args] != 1} {
+ puts stderr "wrong # args: export $args"
+ }
+ return
+}
+
+# genStubs::rewriteFile --
+#
+# This function replaces the machine generated portion of the
+# specified file with new contents. It looks for the !BEGIN! and
+# !END! comments to determine where to place the new text.
+#
+# Arguments:
+# file The name of the file to modify.
+# text The new text to place in the file.
+#
+# Results:
+# None.
+
+proc genStubs::rewriteFile {file text} {
+ if {![file exists $file]} {
+ puts stderr "Cannot find file: $file"
+ return
+ }
+ set in [open ${file} r]
+ set out [open ${file}.new w]
+ fconfigure $out -translation lf
+
+ while {![eof $in]} {
+ set line [gets $in]
+ if {[string match "*!BEGIN!*" $line]} {
+ break
+ }
+ puts $out $line
+ }
+ puts $out "/* !BEGIN!: Do not edit below this line. */"
+ puts $out $text
+ while {![eof $in]} {
+ set line [gets $in]
+ if {[string match "*!END!*" $line]} {
+ break
+ }
+ }
+ puts $out "/* !END!: Do not edit above this line. */"
+ puts -nonewline $out [read $in]
+ close $in
+ close $out
+ file rename -force ${file}.new ${file}
+ return
+}
+
+# genStubs::addPlatformGuard --
+#
+# Wrap a string inside a platform #ifdef.
+#
+# Arguments:
+# plat Platform to test.
+#
+# Results:
+# Returns the original text inside an appropriate #ifdef.
+
+proc genStubs::addPlatformGuard {plat iftxt {eltxt {}}} {
+ set text ""
+ switch $plat {
+ win {
+ append text "#ifdef _WIN32 /* WIN */\n${iftxt}"
+ if {$eltxt ne ""} {
+ append text "#else /* WIN */\n${eltxt}"
+ }
+ append text "#endif /* WIN */\n"
+ }
+ unix {
+ append text "#if !defined(_WIN32) && !defined(MAC_OSX_TCL)\
+ /* UNIX */\n${iftxt}"
+ if {$eltxt ne ""} {
+ append text "#else /* UNIX */\n${eltxt}"
+ }
+ append text "#endif /* UNIX */\n"
+ }
+ macosx {
+ append text "#ifdef MAC_OSX_TCL /* MACOSX */\n${iftxt}"
+ if {$eltxt ne ""} {
+ append text "#else /* MACOSX */\n${eltxt}"
+ }
+ append text "#endif /* MACOSX */\n"
+ }
+ aqua {
+ append text "#ifdef MAC_OSX_TK /* AQUA */\n${iftxt}"
+ if {$eltxt ne ""} {
+ append text "#else /* AQUA */\n${eltxt}"
+ }
+ append text "#endif /* AQUA */\n"
+ }
+ x11 {
+ append text "#if !(defined(_WIN32) || defined(MAC_OSX_TK))\
+ /* X11 */\n${iftxt}"
+ if {$eltxt ne ""} {
+ append text "#else /* X11 */\n${eltxt}"
+ }
+ append text "#endif /* X11 */\n"
+ }
+ default {
+ append text "${iftxt}${eltxt}"
+ }
+ }
+ return $text
+}
+
+# genStubs::emitSlots --
+#
+# Generate the stub table slots for the given interface. If there
+# are no generic slots, then one table is generated for each
+# platform, otherwise one table is generated for all platforms.
+#
+# Arguments:
+# name The name of the interface being emitted.
+# textVar The variable to use for output.
+#
+# Results:
+# None.
+
+proc genStubs::emitSlots {name textVar} {
+ upvar $textVar text
+
+ forAllStubs $name makeSlot noGuard text {" void (*reserved$i)(void);\n"}
+ return
+}
+
+# genStubs::parseDecl --
+#
+# Parse a C function declaration into its component parts.
+#
+# Arguments:
+# decl The function declaration.
+#
+# Results:
+# Returns a list of the form {returnType name args}. The args
+# element consists of a list of type/name pairs, or a single
+# element "void". If the function declaration is malformed
+# then an error is displayed and the return value is {}.
+
+proc genStubs::parseDecl {decl} {
+ if {![regexp {^(.*)\((.*)\);?$} $decl all prefix args]} {
+ set prefix $decl
+ set args {}
+ }
+ set prefix [string trim $prefix]
+ if {![regexp {^(.+[ ][*]*)([^ *]+)$} $prefix all rtype fname]} {
+ puts stderr "Bad return type: $decl"
+ return
+ }
+ set rtype [string trim $rtype]
+ if {$args eq ""} {
+ return [list $rtype $fname {}]
+ }
+ foreach arg [split $args ,] {
+ lappend argList [string trim $arg]
+ }
+ if {![string compare [lindex $argList end] "..."]} {
+ set args TCL_VARARGS
+ foreach arg [lrange $argList 0 end-1] {
+ set argInfo [parseArg $arg]
+ if {[llength $argInfo] == 2 || [llength $argInfo] == 3} {
+ lappend args $argInfo
+ } else {
+ puts stderr "Bad argument: '$arg' in '$decl'"
+ return
+ }
+ }
+ } else {
+ set args {}
+ foreach arg $argList {
+ set argInfo [parseArg $arg]
+ if {![string compare $argInfo "void"]} {
+ lappend args "void"
+ break
+ } elseif {[llength $argInfo] == 2 || [llength $argInfo] == 3} {
+ lappend args $argInfo
+ } else {
+ puts stderr "Bad argument: '$arg' in '$decl'"
+ return
+ }
+ }
+ }
+ return [list $rtype $fname $args]
+}
+
+# genStubs::parseArg --
+#
+# This function parses a function argument into a type and name.
+#
+# Arguments:
+# arg The argument to parse.
+#
+# Results:
+# Returns a list of type and name with an optional third array
+# indicator. If the argument is malformed, returns "".
+
+proc genStubs::parseArg {arg} {
+ if {![regexp {^(.+[ ][*]*)([^][ *]+)(\[\])?$} $arg all type name array]} {
+ if {$arg eq "void"} {
+ return $arg
+ } else {
+ return
+ }
+ }
+ set result [list [string trim $type] $name]
+ if {$array ne ""} {
+ lappend result $array
+ }
+ return $result
+}
+
+# genStubs::makeDecl --
+#
+# Generate the prototype for a function.
+#
+# Arguments:
+# name The interface name.
+# decl The function declaration.
+# index The slot index for this function.
+#
+# Results:
+# Returns the formatted declaration string.
+
+proc genStubs::makeDecl {name decl index} {
+ variable scspec
+ lassign $decl rtype fname args
+
+ append text "/* $index */\n"
+ set line "$scspec $rtype"
+ set count [expr {2 - ([string length $line] / 8)}]
+ append line [string range "\t\t\t" 0 $count]
+ set pad [expr {24 - [string length $line]}]
+ if {$pad <= 0} {
+ append line " "
+ set pad 0
+ }
+ if {$args eq ""} {
+ append line $fname
+ append text $line
+ append text ";\n"
+ return $text
+ }
+ append line $fname
+
+ set arg1 [lindex $args 0]
+ switch -exact $arg1 {
+ void {
+ append line "(void)"
+ }
+ TCL_VARARGS {
+ set sep "("
+ foreach arg [lrange $args 1 end] {
+ append line $sep
+ set next {}
+ append next [lindex $arg 0]
+ if {[string index $next end] ne "*"} {
+ append next " "
+ }
+ append next [lindex $arg 1] [lindex $arg 2]
+ if {[string length $line] + [string length $next] \
+ + $pad > 76} {
+ append text [string trimright $line] \n
+ set line "\t\t\t\t"
+ set pad 28
+ }
+ append line $next
+ set sep ", "
+ }
+ append line ", ...)"
+ }
+ default {
+ set sep "("
+ foreach arg $args {
+ append line $sep
+ set next {}
+ append next [lindex $arg 0]
+ if {[string index $next end] ne "*"} {
+ append next " "
+ }
+ append next [lindex $arg 1] [lindex $arg 2]
+ if {[string length $line] + [string length $next] \
+ + $pad > 76} {
+ append text [string trimright $line] \n
+ set line "\t\t\t\t"
+ set pad 28
+ }
+ append line $next
+ set sep ", "
+ }
+ append line ")"
+ }
+ }
+ return "$text$line;\n"
+}
+
+# genStubs::makeMacro --
+#
+# Generate the inline macro for a function.
+#
+# Arguments:
+# name The interface name.
+# decl The function declaration.
+# index The slot index for this function.
+#
+# Results:
+# Returns the formatted macro definition.
+
+proc genStubs::makeMacro {name decl index} {
+ lassign $decl rtype fname args
+
+ set lfname [string tolower [string index $fname 0]]
+ append lfname [string range $fname 1 end]
+
+ set text "#define $fname \\\n\t("
+ if {$args eq ""} {
+ append text "*"
+ }
+ append text "${name}StubsPtr->$lfname)"
+ append text " /* $index */\n"
+ return $text
+}
+
+# genStubs::makeSlot --
+#
+# Generate the stub table entry for a function.
+#
+# Arguments:
+# name The interface name.
+# decl The function declaration.
+# index The slot index for this function.
+#
+# Results:
+# Returns the formatted table entry.
+
+proc genStubs::makeSlot {name decl index} {
+ lassign $decl rtype fname args
+
+ set lfname [string tolower [string index $fname 0]]
+ append lfname [string range $fname 1 end]
+
+ set text " "
+ if {$args eq ""} {
+ append text $rtype " *" $lfname "; /* $index */\n"
+ return $text
+ }
+ if {[string range $rtype end-8 end] eq "__stdcall"} {
+ append text [string trim [string range $rtype 0 end-9]] " (__stdcall *" $lfname ") "
+ } else {
+ append text $rtype " (*" $lfname ") "
+ }
+ set arg1 [lindex $args 0]
+ switch -exact $arg1 {
+ void {
+ append text "(void)"
+ }
+ TCL_VARARGS {
+ set sep "("
+ foreach arg [lrange $args 1 end] {
+ append text $sep [lindex $arg 0]
+ if {[string index $text end] ne "*"} {
+ append text " "
+ }
+ append text [lindex $arg 1] [lindex $arg 2]
+ set sep ", "
+ }
+ append text ", ...)"
+ }
+ default {
+ set sep "("
+ foreach arg $args {
+ append text $sep [lindex $arg 0]
+ if {[string index $text end] ne "*"} {
+ append text " "
+ }
+ append text [lindex $arg 1] [lindex $arg 2]
+ set sep ", "
+ }
+ append text ")"
+ }
+ }
+
+ append text "; /* $index */\n"
+ return $text
+}
+
+# genStubs::makeInit --
+#
+# Generate the prototype for a function.
+#
+# Arguments:
+# name The interface name.
+# decl The function declaration.
+# index The slot index for this function.
+#
+# Results:
+# Returns the formatted declaration string.
+
+proc genStubs::makeInit {name decl index} {
+ if {[lindex $decl 2] eq ""} {
+ append text " &" [lindex $decl 1] ", /* " $index " */\n"
+ } else {
+ append text " " [lindex $decl 1] ", /* " $index " */\n"
+ }
+ return $text
+}
+
+# genStubs::forAllStubs --
+#
+# This function iterates over all of the slots and invokes
+# a callback for each slot. The result of the callback is then
+# placed inside appropriate guards.
+#
+# Arguments:
+# name The interface name.
+# slotProc The proc to invoke to handle the slot. It will
+# have the interface name, the declaration, and
+# the index appended.
+# guardProc The proc to invoke to add guards. It will have
+# the slot status and text appended.
+# textVar The variable to use for output.
+# skipString The string to emit if a slot is skipped. This
+# string will be subst'ed in the loop so "$i" can
+# be used to substitute the index value.
+#
+# Results:
+# None.
+
+proc genStubs::forAllStubs {name slotProc guardProc textVar
+ {skipString {"/* Slot $i is reserved */\n"}}} {
+ variable stubs
+ upvar $textVar text
+
+ set lastNum $stubs($name,lastNum)
+
+ for {set i 0} {$i <= $lastNum} {incr i} {
+ if {[info exists stubs($name,decl,$i)]} {
+ append text [$guardProc $stubs($name,status,$i) \
+ [$slotProc $name $stubs($name,decl,$i) $i]]
+ } else {
+ eval {append text} $skipString
+ }
+ }
+}
+
+proc genStubs::noGuard {status text} { return $text }
+
+proc genStubs::addGuard {status text} {
+ variable libraryName
+ set upName [string toupper $libraryName]
+
+ switch -- $status {
+ current {
+ # No change
+ }
+ deprecated {
+ set text [ifdeffed "${upName}_DEPRECATED" $text]
+ }
+ obsolete {
+ set text ""
+ }
+ default {
+ puts stderr "Unrecognized status code $status"
+ }
+ }
+ return $text
+}
+
+proc genStubs::ifdeffed {macro text} {
+ join [list "#ifdef $macro" $text "#endif" ""] \n
+}
+
+# genStubs::emitDeclarations --
+#
+# This function emits the function declarations for this interface.
+#
+# Arguments:
+# name The interface name.
+# textVar The variable to use for output.
+#
+# Results:
+# None.
+
+proc genStubs::emitDeclarations {name textVar} {
+ upvar $textVar text
+
+ append text "\n/*\n * Exported function declarations:\n */\n\n"
+ forAllStubs $name makeDecl noGuard text
+ return
+}
+
+# genStubs::emitMacros --
+#
+# This function emits the inline macros for an interface.
+#
+# Arguments:
+# name The name of the interface being emitted.
+# textVar The variable to use for output.
+#
+# Results:
+# None.
+
+proc genStubs::emitMacros {name textVar} {
+ variable libraryName
+ upvar $textVar text
+
+ set upName [string toupper $libraryName]
+ append text "\n#if defined(USE_${upName}_STUBS)\n"
+ append text "\n/*\n * Inline function declarations:\n */\n\n"
+
+ forAllStubs $name makeMacro addGuard text
+
+ append text "\n#endif /* defined(USE_${upName}_STUBS) */\n"
+ return
+}
+
+# genStubs::emitHeader --
+#
+# This function emits the body of the <name>Decls.h file for
+# the specified interface.
+#
+# Arguments:
+# name The name of the interface being emitted.
+#
+# Results:
+# None.
+
+proc genStubs::emitHeader {name} {
+ variable outDir
+ variable hooks
+ variable epoch
+ variable revision
+
+ set capName [string toupper [string index $name 0]]
+ append capName [string range $name 1 end]
+
+ if {$epoch ne ""} {
+ set CAPName [string toupper $name]
+ append text "\n"
+ append text "#define ${CAPName}_STUBS_EPOCH $epoch\n"
+ append text "#define ${CAPName}_STUBS_REVISION $revision\n"
+ }
+
+ append text "\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n"
+
+ emitDeclarations $name text
+
+ if {[info exists hooks($name)]} {
+ append text "\ntypedef struct {\n"
+ foreach hook $hooks($name) {
+ set capHook [string toupper [string index $hook 0]]
+ append capHook [string range $hook 1 end]
+ append text " const struct ${capHook}Stubs *${hook}Stubs;\n"
+ }
+ append text "} ${capName}StubHooks;\n"
+ }
+ append text "\ntypedef struct ${capName}Stubs {\n"
+ append text " int magic;\n"
+ if {$epoch ne ""} {
+ append text " int epoch;\n"
+ append text " int revision;\n"
+ }
+ if {[info exists hooks($name)]} {
+ append text " const ${capName}StubHooks *hooks;\n\n"
+ } else {
+ append text " void *hooks;\n\n"
+ }
+
+ emitSlots $name text
+
+ append text "} ${capName}Stubs;\n\n"
+
+ append text "extern const ${capName}Stubs *${name}StubsPtr;\n\n"
+ append text "#ifdef __cplusplus\n}\n#endif\n"
+
+ emitMacros $name text
+
+ rewriteFile [file join $outDir ${name}Decls.h] $text
+ return
+}
+
+# genStubs::emitInit --
+#
+# Generate the table initializers for an interface.
+#
+# Arguments:
+# name The name of the interface to initialize.
+# textVar The variable to use for output.
+#
+# Results:
+# Returns the formatted output.
+
+proc genStubs::emitInit {name textVar} {
+ variable hooks
+ variable interfaces
+ variable epoch
+ upvar $textVar text
+ set root 1
+
+ set capName [string toupper [string index $name 0]]
+ append capName [string range $name 1 end]
+
+ if {[info exists hooks($name)]} {
+ append text "\nstatic const ${capName}StubHooks ${name}StubHooks = \{\n"
+ set sep " "
+ foreach sub $hooks($name) {
+ append text $sep "&${sub}Stubs"
+ set sep ",\n "
+ }
+ append text "\n\};\n"
+ }
+ foreach intf [array names interfaces] {
+ if {[info exists hooks($intf)]} {
+ if {[lsearch -exact $hooks($intf) $name] >= 0} {
+ set root 0
+ break
+ }
+ }
+ }
+
+ append text "\n"
+ if {!$root} {
+ append text "static "
+ }
+ append text "const ${capName}Stubs ${name}Stubs = \{\n TCL_STUB_MAGIC,\n"
+ if {$epoch ne ""} {
+ set CAPName [string toupper $name]
+ append text " ${CAPName}_STUBS_EPOCH,\n"
+ append text " ${CAPName}_STUBS_REVISION,\n"
+ }
+ if {[info exists hooks($name)]} {
+ append text " &${name}StubHooks,\n"
+ } else {
+ append text " 0,\n"
+ }
+
+ forAllStubs $name makeInit noGuard text {" 0, /* $i */\n"}
+
+ append text "\};\n"
+ return
+}
+
+# genStubs::emitInits --
+#
+# This function emits the body of the <name>StubInit.c file for
+# the specified interface.
+#
+# Arguments:
+# name The name of the interface being emitted.
+#
+# Results:
+# None.
+
+proc genStubs::emitInits {} {
+ variable hooks
+ variable outDir
+ variable libraryName
+ variable interfaces
+
+ # Assuming that dependencies only go one level deep, we need to emit
+ # all of the leaves first to avoid needing forward declarations.
+
+ set leaves {}
+ set roots {}
+ foreach name [lsort [array names interfaces]] {
+ if {[info exists hooks($name)]} {
+ lappend roots $name
+ } else {
+ lappend leaves $name
+ }
+ }
+ foreach name $leaves {
+ emitInit $name text
+ }
+ foreach name $roots {
+ emitInit $name text
+ }
+
+ rewriteFile [file join $outDir ${libraryName}StubInit.c] $text
+}
+
+# genStubs::init --
+#
+# This is the main entry point.
+#
+# Arguments:
+# None.
+#
+# Results:
+# None.
+
+proc genStubs::init {} {
+ global argv argv0
+ variable outDir
+ variable interfaces
+
+ if {[llength $argv] < 2} {
+ puts stderr "usage: $argv0 outDir declFile ?declFile...?"
+ exit 1
+ }
+
+ set outDir [lindex $argv 0]
+
+ foreach file [lrange $argv 1 end] {
+ source $file
+ }
+
+ foreach name [lsort [array names interfaces]] {
+ puts "Emitting $name"
+ emitHeader $name
+ }
+
+ emitInits
+}
+
+# lassign --
+#
+# This function emulates the TclX lassign command.
+#
+# Arguments:
+# valueList A list containing the values to be assigned.
+# args The list of variables to be assigned.
+#
+# Results:
+# Returns any values that were not assigned to variables.
+
+if {[string length [namespace which lassign]] == 0} {
+ proc lassign {valueList args} {
+ if {[llength $args] == 0} {
+ error "wrong # args: should be \"lassign list varName ?varName ...?\""
+ }
+ uplevel [list foreach $args $valueList {break}]
+ return [lrange $valueList [llength $args] end]
+ }
+}
+
+genStubs::init
diff --git a/tk8.6/generic/ttk/ttkImage.c b/tk8.6/generic/ttk/ttkImage.c
new file mode 100644
index 0000000..e403e2d
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkImage.c
@@ -0,0 +1,452 @@
+/*
+ * Image specifications and image element factory.
+ *
+ * Copyright (C) 2004 Pat Thoyts <patthoyts@users.sf.net>
+ * Copyright (C) 2004 Joe English
+ *
+ * An imageSpec is a multi-element list; the first element
+ * is the name of the default image to use, the remainder of the
+ * list is a sequence of statespec/imagename options as per
+ * [style map].
+ */
+
+#include <string.h>
+#include <tk.h>
+#include "ttkTheme.h"
+
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+/*------------------------------------------------------------------------
+ * +++ ImageSpec management.
+ */
+
+struct TtkImageSpec {
+ Tk_Image baseImage; /* Base image to use */
+ int mapCount; /* #state-specific overrides */
+ Ttk_StateSpec *states; /* array[mapCount] of states ... */
+ Tk_Image *images; /* ... per-state images to use */
+ Tk_ImageChangedProc *imageChanged;
+ ClientData imageChangedClientData;
+};
+
+/* NullImageChanged --
+ * Do-nothing Tk_ImageChangedProc.
+ */
+static void NullImageChanged(ClientData clientData,
+ int x, int y, int width, int height, int imageWidth, int imageHeight)
+{ /* No-op */ }
+
+/* ImageSpecImageChanged --
+ * Image changes should trigger a repaint.
+ */
+static void ImageSpecImageChanged(ClientData clientData,
+ int x, int y, int width, int height, int imageWidth, int imageHeight)
+{
+ Ttk_ImageSpec *imageSpec = (Ttk_ImageSpec *)clientData;
+ if (imageSpec->imageChanged != NULL) {
+ imageSpec->imageChanged(imageSpec->imageChangedClientData,
+ x, y, width, height,
+ imageWidth, imageHeight);
+ }
+}
+
+/* TtkGetImageSpec --
+ * Constructs a Ttk_ImageSpec * from a Tcl_Obj *.
+ * Result must be released using TtkFreeImageSpec.
+ *
+ */
+Ttk_ImageSpec *
+TtkGetImageSpec(Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr)
+{
+ return TtkGetImageSpecEx(interp, tkwin, objPtr, NULL, NULL);
+}
+
+/* TtkGetImageSpecEx --
+ * Constructs a Ttk_ImageSpec * from a Tcl_Obj *.
+ * Result must be released using TtkFreeImageSpec.
+ * imageChangedProc will be called when not NULL when
+ * the image changes to allow widgets to repaint.
+ */
+Ttk_ImageSpec *
+TtkGetImageSpecEx(Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr,
+ Tk_ImageChangedProc *imageChangedProc, ClientData imageChangedClientData)
+{
+ Ttk_ImageSpec *imageSpec = 0;
+ int i = 0, n = 0, objc;
+ Tcl_Obj **objv;
+
+ imageSpec = ckalloc(sizeof(*imageSpec));
+ imageSpec->baseImage = 0;
+ imageSpec->mapCount = 0;
+ imageSpec->states = 0;
+ imageSpec->images = 0;
+ imageSpec->imageChanged = imageChangedProc;
+ imageSpec->imageChangedClientData = imageChangedClientData;
+
+ if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
+ goto error;
+ }
+
+ if ((objc % 2) != 1) {
+ if (interp) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "image specification must contain an odd number of elements",
+ -1));
+ Tcl_SetErrorCode(interp, "TTK", "IMAGE", "SPEC", NULL);
+ }
+ goto error;
+ }
+
+ n = (objc - 1) / 2;
+ imageSpec->states = ckalloc(n * sizeof(Ttk_StateSpec));
+ imageSpec->images = ckalloc(n * sizeof(Tk_Image *));
+
+ /* Get base image:
+ */
+ imageSpec->baseImage = Tk_GetImage(
+ interp, tkwin, Tcl_GetString(objv[0]), ImageSpecImageChanged, imageSpec);
+ if (!imageSpec->baseImage) {
+ goto error;
+ }
+
+ /* Extract state and image specifications:
+ */
+ for (i = 0; i < n; ++i) {
+ Tcl_Obj *stateSpec = objv[2*i + 1];
+ const char *imageName = Tcl_GetString(objv[2*i + 2]);
+ Ttk_StateSpec state;
+
+ if (Ttk_GetStateSpecFromObj(interp, stateSpec, &state) != TCL_OK) {
+ goto error;
+ }
+ imageSpec->states[i] = state;
+
+ imageSpec->images[i] = Tk_GetImage(
+ interp, tkwin, imageName, NullImageChanged, NULL);
+ if (imageSpec->images[i] == NULL) {
+ goto error;
+ }
+ imageSpec->mapCount = i+1;
+ }
+
+ return imageSpec;
+
+error:
+ TtkFreeImageSpec(imageSpec);
+ return NULL;
+}
+
+/* TtkFreeImageSpec --
+ * Dispose of an image specification.
+ */
+void TtkFreeImageSpec(Ttk_ImageSpec *imageSpec)
+{
+ int i;
+
+ for (i=0; i < imageSpec->mapCount; ++i) {
+ Tk_FreeImage(imageSpec->images[i]);
+ }
+
+ if (imageSpec->baseImage) { Tk_FreeImage(imageSpec->baseImage); }
+ if (imageSpec->states) { ckfree(imageSpec->states); }
+ if (imageSpec->images) { ckfree(imageSpec->images); }
+
+ ckfree(imageSpec);
+}
+
+/* TtkSelectImage --
+ * Return a state-specific image from an ImageSpec
+ */
+Tk_Image TtkSelectImage(Ttk_ImageSpec *imageSpec, Ttk_State state)
+{
+ int i;
+ for (i = 0; i < imageSpec->mapCount; ++i) {
+ if (Ttk_StateMatches(state, imageSpec->states+i)) {
+ return imageSpec->images[i];
+ }
+ }
+ return imageSpec->baseImage;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Drawing utilities.
+ */
+
+/* LPadding, CPadding, RPadding --
+ * Split a box+padding pair into left, center, and right boxes.
+ */
+static Ttk_Box LPadding(Ttk_Box b, Ttk_Padding p)
+ { return Ttk_MakeBox(b.x, b.y, p.left, b.height); }
+
+static Ttk_Box CPadding(Ttk_Box b, Ttk_Padding p)
+ { return Ttk_MakeBox(b.x+p.left, b.y, b.width-p.left-p.right, b.height); }
+
+static Ttk_Box RPadding(Ttk_Box b, Ttk_Padding p)
+ { return Ttk_MakeBox(b.x+b.width-p.right, b.y, p.right, b.height); }
+
+/* TPadding, MPadding, BPadding --
+ * Split a box+padding pair into top, middle, and bottom parts.
+ */
+static Ttk_Box TPadding(Ttk_Box b, Ttk_Padding p)
+ { return Ttk_MakeBox(b.x, b.y, b.width, p.top); }
+
+static Ttk_Box MPadding(Ttk_Box b, Ttk_Padding p)
+ { return Ttk_MakeBox(b.x, b.y+p.top, b.width, b.height-p.top-p.bottom); }
+
+static Ttk_Box BPadding(Ttk_Box b, Ttk_Padding p)
+ { return Ttk_MakeBox(b.x, b.y+b.height-p.bottom, b.width, p.bottom); }
+
+/* Ttk_Fill --
+ * Fill the destination area of the drawable by replicating
+ * the source area of the image.
+ */
+static void Ttk_Fill(
+ Tk_Window tkwin, Drawable d, Tk_Image image, Ttk_Box src, Ttk_Box dst)
+{
+ int dr = dst.x + dst.width;
+ int db = dst.y + dst.height;
+ int x,y;
+
+ if (!(src.width && src.height && dst.width && dst.height))
+ return;
+
+ for (x = dst.x; x < dr; x += src.width) {
+ int cw = MIN(src.width, dr - x);
+ for (y = dst.y; y <= db; y += src.height) {
+ int ch = MIN(src.height, db - y);
+ Tk_RedrawImage(image, src.x, src.y, cw, ch, d, x, y);
+ }
+ }
+}
+
+/* Ttk_Stripe --
+ * Fill a horizontal stripe of the destination drawable.
+ */
+static void Ttk_Stripe(
+ Tk_Window tkwin, Drawable d, Tk_Image image,
+ Ttk_Box src, Ttk_Box dst, Ttk_Padding p)
+{
+ Ttk_Fill(tkwin, d, image, LPadding(src,p), LPadding(dst,p));
+ Ttk_Fill(tkwin, d, image, CPadding(src,p), CPadding(dst,p));
+ Ttk_Fill(tkwin, d, image, RPadding(src,p), RPadding(dst,p));
+}
+
+/* Ttk_Tile --
+ * Fill successive horizontal stripes of the destination drawable.
+ */
+static void Ttk_Tile(
+ Tk_Window tkwin, Drawable d, Tk_Image image,
+ Ttk_Box src, Ttk_Box dst, Ttk_Padding p)
+{
+ Ttk_Stripe(tkwin, d, image, TPadding(src,p), TPadding(dst,p), p);
+ Ttk_Stripe(tkwin, d, image, MPadding(src,p), MPadding(dst,p), p);
+ Ttk_Stripe(tkwin, d, image, BPadding(src,p), BPadding(dst,p), p);
+}
+
+/*------------------------------------------------------------------------
+ * +++ Image element definition.
+ */
+
+typedef struct { /* ClientData for image elements */
+ Ttk_ImageSpec *imageSpec; /* Image(s) to use */
+ int minWidth; /* Minimum width; overrides image width */
+ int minHeight; /* Minimum width; overrides image width */
+ Ttk_Sticky sticky; /* -stickiness specification */
+ Ttk_Padding border; /* Fixed border region */
+ Ttk_Padding padding; /* Internal padding */
+
+#if TILE_07_COMPAT
+ Ttk_ResourceCache cache; /* Resource cache for images */
+ Ttk_StateMap imageMap; /* State-based lookup table for images */
+#endif
+} ImageData;
+
+static void FreeImageData(void *clientData)
+{
+ ImageData *imageData = clientData;
+ if (imageData->imageSpec) { TtkFreeImageSpec(imageData->imageSpec); }
+#if TILE_07_COMPAT
+ if (imageData->imageMap) { Tcl_DecrRefCount(imageData->imageMap); }
+#endif
+ ckfree(clientData);
+}
+
+static void ImageElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ ImageData *imageData = clientData;
+ Tk_Image image = imageData->imageSpec->baseImage;
+
+ if (image) {
+ Tk_SizeOfImage(image, widthPtr, heightPtr);
+ }
+ if (imageData->minWidth >= 0) {
+ *widthPtr = imageData->minWidth;
+ }
+ if (imageData->minHeight >= 0) {
+ *heightPtr = imageData->minHeight;
+ }
+
+ *paddingPtr = imageData->padding;
+}
+
+static void ImageElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ ImageData *imageData = clientData;
+ Tk_Image image = 0;
+ int imgWidth, imgHeight;
+ Ttk_Box src, dst;
+
+#if TILE_07_COMPAT
+ if (imageData->imageMap) {
+ Tcl_Obj *imageObj = Ttk_StateMapLookup(NULL,imageData->imageMap,state);
+ if (imageObj) {
+ image = Ttk_UseImage(imageData->cache, tkwin, imageObj);
+ }
+ }
+ if (!image) {
+ image = TtkSelectImage(imageData->imageSpec, state);
+ }
+#else
+ image = TtkSelectImage(imageData->imageSpec, state);
+#endif
+
+ if (!image) {
+ return;
+ }
+
+ Tk_SizeOfImage(image, &imgWidth, &imgHeight);
+ src = Ttk_MakeBox(0, 0, imgWidth, imgHeight);
+ dst = Ttk_StickBox(b, imgWidth, imgHeight, imageData->sticky);
+
+ Ttk_Tile(tkwin, d, image, src, dst, imageData->border);
+}
+
+static Ttk_ElementSpec ImageElementSpec =
+{
+ TK_STYLE_VERSION_2,
+ sizeof(NullElement),
+ TtkNullElementOptions,
+ ImageElementSize,
+ ImageElementDraw
+};
+
+/*------------------------------------------------------------------------
+ * +++ Image element factory.
+ */
+static int
+Ttk_CreateImageElement(
+ Tcl_Interp *interp,
+ void *clientData,
+ Ttk_Theme theme,
+ const char *elementName,
+ int objc, Tcl_Obj *const objv[])
+{
+ static const char *optionStrings[] =
+ { "-border","-height","-padding","-sticky","-width",NULL };
+ enum { O_BORDER, O_HEIGHT, O_PADDING, O_STICKY, O_WIDTH };
+
+ Ttk_ImageSpec *imageSpec = 0;
+ ImageData *imageData = 0;
+ int padding_specified = 0;
+ int i;
+
+ if (objc <= 0) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "Must supply a base image", -1));
+ Tcl_SetErrorCode(interp, "TTK", "IMAGE", "BASE", NULL);
+ return TCL_ERROR;
+ }
+
+ imageSpec = TtkGetImageSpec(interp, Tk_MainWindow(interp), objv[0]);
+ if (!imageSpec) {
+ return TCL_ERROR;
+ }
+
+ imageData = ckalloc(sizeof(*imageData));
+ imageData->imageSpec = imageSpec;
+ imageData->minWidth = imageData->minHeight = -1;
+ imageData->sticky = TTK_FILL_BOTH;
+ imageData->border = imageData->padding = Ttk_UniformPadding(0);
+#if TILE_07_COMPAT
+ imageData->cache = Ttk_GetResourceCache(interp);
+ imageData->imageMap = 0;
+#endif
+
+ for (i = 1; i < objc; i += 2) {
+ int option;
+
+ if (i == objc - 1) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "Value for %s missing", Tcl_GetString(objv[i])));
+ Tcl_SetErrorCode(interp, "TTK", "IMAGE", "VALUE", NULL);
+ goto error;
+ }
+
+#if TILE_07_COMPAT
+ if (!strcmp("-map", Tcl_GetString(objv[i]))) {
+ imageData->imageMap = objv[i+1];
+ Tcl_IncrRefCount(imageData->imageMap);
+ continue;
+ }
+#endif
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[i], optionStrings,
+ sizeof(char *), "option", 0, &option) != TCL_OK) {
+ goto error;
+ }
+
+ switch (option) {
+ case O_BORDER:
+ if (Ttk_GetBorderFromObj(interp, objv[i+1], &imageData->border)
+ != TCL_OK) {
+ goto error;
+ }
+ if (!padding_specified) {
+ imageData->padding = imageData->border;
+ }
+ break;
+ case O_PADDING:
+ if (Ttk_GetBorderFromObj(interp, objv[i+1], &imageData->padding)
+ != TCL_OK) { goto error; }
+ padding_specified = 1;
+ break;
+ case O_WIDTH:
+ if (Tcl_GetIntFromObj(interp, objv[i+1], &imageData->minWidth)
+ != TCL_OK) { goto error; }
+ break;
+ case O_HEIGHT:
+ if (Tcl_GetIntFromObj(interp, objv[i+1], &imageData->minHeight)
+ != TCL_OK) { goto error; }
+ break;
+ case O_STICKY:
+ if (Ttk_GetStickyFromObj(interp, objv[i+1], &imageData->sticky)
+ != TCL_OK) { goto error; }
+ }
+ }
+
+ if (!Ttk_RegisterElement(interp, theme, elementName, &ImageElementSpec,
+ imageData))
+ {
+ goto error;
+ }
+
+ Ttk_RegisterCleanup(interp, imageData, FreeImageData);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(elementName, -1));
+ return TCL_OK;
+
+error:
+ FreeImageData(imageData);
+ return TCL_ERROR;
+}
+
+MODULE_SCOPE
+void TtkImage_Init(Tcl_Interp *interp)
+{
+ Ttk_RegisterElementFactory(interp, "image", Ttk_CreateImageElement, NULL);
+}
+
+/*EOF*/
diff --git a/tk8.6/generic/ttk/ttkInit.c b/tk8.6/generic/ttk/ttkInit.c
new file mode 100644
index 0000000..dc6e994
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkInit.c
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2003, Joe English
+ *
+ * Ttk package: initialization routine and miscellaneous utilities.
+ */
+
+#include <string.h>
+#include <tk.h>
+#include "ttkTheme.h"
+#include "ttkWidget.h"
+
+/*
+ * Legal values for the button -default option.
+ * See also: enum Ttk_ButtonDefaultState.
+ */
+const char *ttkDefaultStrings[] = {
+ "normal", "active", "disabled", NULL
+};
+
+int Ttk_GetButtonDefaultStateFromObj(
+ Tcl_Interp *interp, Tcl_Obj *objPtr, int *statePtr)
+{
+ *statePtr = TTK_BUTTON_DEFAULT_DISABLED;
+ return Tcl_GetIndexFromObjStruct(interp, objPtr, ttkDefaultStrings,
+ sizeof(char *), "default state", 0, statePtr);
+}
+
+/*
+ * Legal values for the -compound option.
+ * See also: enum Ttk_Compound.
+ */
+const char *ttkCompoundStrings[] = {
+ "none", "text", "image", "center",
+ "top", "bottom", "left", "right", NULL
+};
+
+int Ttk_GetCompoundFromObj(
+ Tcl_Interp *interp, Tcl_Obj *objPtr, int *statePtr)
+{
+ *statePtr = TTK_COMPOUND_NONE;
+ return Tcl_GetIndexFromObjStruct(interp, objPtr, ttkCompoundStrings,
+ sizeof(char *), "compound layout", 0, statePtr);
+}
+
+/*
+ * Legal values for the -orient option.
+ * See also: enum Ttk_Orient.
+ */
+const char *ttkOrientStrings[] = {
+ "horizontal", "vertical", NULL
+};
+
+int Ttk_GetOrientFromObj(
+ Tcl_Interp *interp, Tcl_Obj *objPtr, int *resultPtr)
+{
+ *resultPtr = TTK_ORIENT_HORIZONTAL;
+ return Tcl_GetIndexFromObjStruct(interp, objPtr, ttkOrientStrings,
+ sizeof(char *), "orientation", 0, resultPtr);
+}
+
+/*
+ * Recognized values for the -state compatibility option.
+ * Other options are accepted and interpreted as synonyms for "normal".
+ */
+static const char *ttkStateStrings[] = {
+ "normal", "readonly", "disabled", "active", NULL
+};
+enum {
+ TTK_COMPAT_STATE_NORMAL,
+ TTK_COMPAT_STATE_READONLY,
+ TTK_COMPAT_STATE_DISABLED,
+ TTK_COMPAT_STATE_ACTIVE
+};
+
+/* TtkCheckStateOption --
+ * Handle -state compatibility option.
+ *
+ * NOTE: setting -state disabled / -state enabled affects the
+ * widget state, but the internal widget state does *not* affect
+ * the value of the -state option.
+ * This option is present for compatibility only.
+ */
+void TtkCheckStateOption(WidgetCore *corePtr, Tcl_Obj *objPtr)
+{
+ int stateOption = TTK_COMPAT_STATE_NORMAL;
+ unsigned all = TTK_STATE_DISABLED|TTK_STATE_READONLY|TTK_STATE_ACTIVE;
+# define SETFLAGS(f) TtkWidgetChangeState(corePtr, f, all^f)
+
+ (void)Tcl_GetIndexFromObjStruct(NULL, objPtr, ttkStateStrings,
+ sizeof(char *), "", 0, &stateOption);
+ switch (stateOption) {
+ case TTK_COMPAT_STATE_NORMAL:
+ default:
+ SETFLAGS(0);
+ break;
+ case TTK_COMPAT_STATE_READONLY:
+ SETFLAGS(TTK_STATE_READONLY);
+ break;
+ case TTK_COMPAT_STATE_DISABLED:
+ SETFLAGS(TTK_STATE_DISABLED);
+ break;
+ case TTK_COMPAT_STATE_ACTIVE:
+ SETFLAGS(TTK_STATE_ACTIVE);
+ break;
+ }
+# undef SETFLAGS
+}
+
+/* TtkSendVirtualEvent --
+ * Send a virtual event notification to the specified target window.
+ * Equivalent to "event generate $tgtWindow <<$eventName>>"
+ *
+ * Note that we use Tk_QueueWindowEvent, not Tk_HandleEvent,
+ * so this routine does not reenter the interpreter.
+ */
+void TtkSendVirtualEvent(Tk_Window tgtWin, const char *eventName)
+{
+ union {XEvent general; XVirtualEvent virtual;} event;
+
+ memset(&event, 0, sizeof(event));
+ event.general.xany.type = VirtualEvent;
+ event.general.xany.serial = NextRequest(Tk_Display(tgtWin));
+ event.general.xany.send_event = False;
+ event.general.xany.window = Tk_WindowId(tgtWin);
+ event.general.xany.display = Tk_Display(tgtWin);
+ event.virtual.name = Tk_GetUid(eventName);
+
+ Tk_QueueWindowEvent(&event.general, TCL_QUEUE_TAIL);
+}
+
+/* TtkEnumerateOptions, TtkGetOptionValue --
+ * Common factors for data accessor commands.
+ */
+int TtkEnumerateOptions(
+ Tcl_Interp *interp, void *recordPtr, const Tk_OptionSpec *specPtr,
+ Tk_OptionTable optionTable, Tk_Window tkwin)
+{
+ Tcl_Obj *result = Tcl_NewListObj(0,0);
+ while (specPtr->type != TK_OPTION_END)
+ {
+ Tcl_Obj *optionName = Tcl_NewStringObj(specPtr->optionName, -1);
+ Tcl_Obj *optionValue =
+ Tk_GetOptionValue(interp,recordPtr,optionTable,optionName,tkwin);
+ if (optionValue) {
+ Tcl_ListObjAppendElement(interp, result, optionName);
+ Tcl_ListObjAppendElement(interp, result, optionValue);
+ }
+ ++specPtr;
+
+ if (specPtr->type == TK_OPTION_END && specPtr->clientData != NULL) {
+ /* Chain to next option spec array: */
+ specPtr = specPtr->clientData;
+ }
+ }
+ Tcl_SetObjResult(interp, result);
+ return TCL_OK;
+}
+
+int TtkGetOptionValue(
+ Tcl_Interp *interp, void *recordPtr, Tcl_Obj *optionName,
+ Tk_OptionTable optionTable, Tk_Window tkwin)
+{
+ Tcl_Obj *result =
+ Tk_GetOptionValue(interp,recordPtr,optionTable,optionName,tkwin);
+ if (result) {
+ Tcl_SetObjResult(interp, result);
+ return TCL_OK;
+ }
+ return TCL_ERROR;
+}
+
+
+/*------------------------------------------------------------------------
+ * Core Option specifications:
+ * type name dbName dbClass default objOffset intOffset flags clientData mask
+ */
+
+/* public */
+Tk_OptionSpec ttkCoreOptionSpecs[] =
+{
+ {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", NULL,
+ Tk_Offset(WidgetCore, cursorObj), -1, TK_OPTION_NULL_OK,0,0 },
+ {TK_OPTION_STRING, "-style", "style", "Style", "",
+ Tk_Offset(WidgetCore,styleObj), -1, 0,0,STYLE_CHANGED},
+ {TK_OPTION_STRING, "-class", "", "", NULL,
+ Tk_Offset(WidgetCore,classObj), -1, 0,0,READONLY_OPTION},
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}
+};
+
+/*------------------------------------------------------------------------
+ * +++ Initialization: elements and element factories.
+ */
+
+extern void TtkElements_Init(Tcl_Interp *);
+extern void TtkLabel_Init(Tcl_Interp *);
+extern void TtkImage_Init(Tcl_Interp *);
+
+static void RegisterElements(Tcl_Interp *interp)
+{
+ TtkElements_Init(interp);
+ TtkLabel_Init(interp);
+ TtkImage_Init(interp);
+}
+
+/*------------------------------------------------------------------------
+ * +++ Initialization: Widget definitions.
+ */
+
+extern void TtkButton_Init(Tcl_Interp *);
+extern void TtkEntry_Init(Tcl_Interp *);
+extern void TtkFrame_Init(Tcl_Interp *);
+extern void TtkNotebook_Init(Tcl_Interp *);
+extern void TtkPanedwindow_Init(Tcl_Interp *);
+extern void TtkProgressbar_Init(Tcl_Interp *);
+extern void TtkScale_Init(Tcl_Interp *);
+extern void TtkScrollbar_Init(Tcl_Interp *);
+extern void TtkSeparator_Init(Tcl_Interp *);
+extern void TtkTreeview_Init(Tcl_Interp *);
+
+#ifdef TTK_SQUARE_WIDGET
+extern int TtkSquareWidget_Init(Tcl_Interp *);
+#endif
+
+static void RegisterWidgets(Tcl_Interp *interp)
+{
+ TtkButton_Init(interp);
+ TtkEntry_Init(interp);
+ TtkFrame_Init(interp);
+ TtkNotebook_Init(interp);
+ TtkPanedwindow_Init(interp);
+ TtkProgressbar_Init(interp);
+ TtkScale_Init(interp);
+ TtkScrollbar_Init(interp);
+ TtkSeparator_Init(interp);
+ TtkTreeview_Init(interp);
+#ifdef TTK_SQUARE_WIDGET
+ TtkSquareWidget_Init(interp);
+#endif
+}
+
+/*------------------------------------------------------------------------
+ * +++ Initialization: Built-in themes.
+ */
+
+extern int TtkAltTheme_Init(Tcl_Interp *);
+extern int TtkClassicTheme_Init(Tcl_Interp *);
+extern int TtkClamTheme_Init(Tcl_Interp *);
+
+static void RegisterThemes(Tcl_Interp *interp)
+{
+
+ TtkAltTheme_Init(interp);
+ TtkClassicTheme_Init(interp);
+ TtkClamTheme_Init(interp);
+}
+
+/*
+ * Ttk initialization.
+ */
+
+extern const TtkStubs ttkStubs;
+
+MODULE_SCOPE int
+Ttk_Init(Tcl_Interp *interp)
+{
+ /*
+ * This will be run for both safe and regular interp init.
+ * Use Tcl_IsSafe if necessary to not initialize unsafe bits.
+ */
+ Ttk_StylePkgInit(interp);
+
+ RegisterElements(interp);
+ RegisterWidgets(interp);
+ RegisterThemes(interp);
+
+ Ttk_PlatformInit(interp);
+
+ Tcl_PkgProvideEx(interp, "Ttk", TTK_PATCH_LEVEL, (ClientData)&ttkStubs);
+
+ return TCL_OK;
+}
+
+/*EOF*/
diff --git a/tk8.6/generic/ttk/ttkLabel.c b/tk8.6/generic/ttk/ttkLabel.c
new file mode 100644
index 0000000..3cebc14
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkLabel.c
@@ -0,0 +1,697 @@
+/*
+ * text, image, and label elements.
+ *
+ * The label element combines text and image elements,
+ * with layout determined by the "-compound" option.
+ *
+ */
+
+#include "tkInt.h"
+#include "ttkTheme.h"
+
+/*----------------------------------------------------------------------
+ * +++ Text element.
+ *
+ * This element displays a textual label in the foreground color.
+ *
+ * Optionally underlines the mnemonic character if the -underline resource
+ * is present and >= 0.
+ */
+
+typedef struct {
+ /*
+ * Element options:
+ */
+ Tcl_Obj *textObj;
+ Tcl_Obj *fontObj;
+ Tcl_Obj *foregroundObj;
+ Tcl_Obj *underlineObj;
+ Tcl_Obj *widthObj;
+ Tcl_Obj *anchorObj;
+ Tcl_Obj *justifyObj;
+ Tcl_Obj *wrapLengthObj;
+ Tcl_Obj *embossedObj;
+
+ /*
+ * Computed resources:
+ */
+ Tk_Font tkfont;
+ Tk_TextLayout textLayout;
+ int width;
+ int height;
+ int embossed;
+
+} TextElement;
+
+/* Text element options table.
+ * NB: Keep in sync with label element option table.
+ */
+static Ttk_ElementOptionSpec TextElementOptions[] = {
+ { "-text", TK_OPTION_STRING,
+ Tk_Offset(TextElement,textObj), "" },
+ { "-font", TK_OPTION_FONT,
+ Tk_Offset(TextElement,fontObj), DEFAULT_FONT },
+ { "-foreground", TK_OPTION_COLOR,
+ Tk_Offset(TextElement,foregroundObj), "black" },
+ { "-underline", TK_OPTION_INT,
+ Tk_Offset(TextElement,underlineObj), "-1"},
+ { "-width", TK_OPTION_INT,
+ Tk_Offset(TextElement,widthObj), "-1"},
+ { "-anchor", TK_OPTION_ANCHOR,
+ Tk_Offset(TextElement,anchorObj), "w"},
+ { "-justify", TK_OPTION_JUSTIFY,
+ Tk_Offset(TextElement,justifyObj), "left" },
+ { "-wraplength", TK_OPTION_PIXELS,
+ Tk_Offset(TextElement,wrapLengthObj), "0" },
+ { "-embossed", TK_OPTION_INT,
+ Tk_Offset(TextElement,embossedObj), "0"},
+ { NULL, 0, 0, NULL }
+};
+
+static int TextSetup(TextElement *text, Tk_Window tkwin)
+{
+ const char *string = Tcl_GetString(text->textObj);
+ Tk_Justify justify = TK_JUSTIFY_LEFT;
+ int wrapLength = 0;
+
+ text->tkfont = Tk_GetFontFromObj(tkwin, text->fontObj);
+ Tk_GetJustifyFromObj(NULL, text->justifyObj, &justify);
+ Tk_GetPixelsFromObj(NULL, tkwin, text->wrapLengthObj, &wrapLength);
+ Tcl_GetBooleanFromObj(NULL, text->embossedObj, &text->embossed);
+
+ text->textLayout = Tk_ComputeTextLayout(
+ text->tkfont, string, -1/*numChars*/, wrapLength, justify,
+ 0/*flags*/, &text->width, &text->height);
+
+ return 1;
+}
+
+/*
+ * TextReqWidth -- compute the requested width of a text element.
+ *
+ * If -width is positive, use that as the width
+ * If -width is negative, use that as the minimum width
+ * If not specified or empty, use the natural size of the text
+ */
+
+static int TextReqWidth(TextElement *text)
+{
+ int reqWidth;
+
+ if ( text->widthObj
+ && Tcl_GetIntFromObj(NULL, text->widthObj, &reqWidth) == TCL_OK)
+ {
+ int avgWidth = Tk_TextWidth(text->tkfont, "0", 1);
+ if (reqWidth <= 0) {
+ int specWidth = avgWidth * -reqWidth;
+ if (specWidth > text->width)
+ return specWidth;
+ } else {
+ return avgWidth * reqWidth;
+ }
+ }
+ return text->width;
+}
+
+static void TextCleanup(TextElement *text)
+{
+ Tk_FreeTextLayout(text->textLayout);
+}
+
+/*
+ * TextDraw --
+ * Draw a text element.
+ * Called by TextElementDraw() and LabelElementDraw().
+ */
+static void TextDraw(TextElement *text, Tk_Window tkwin, Drawable d, Ttk_Box b)
+{
+ XColor *color = Tk_GetColorFromObj(tkwin, text->foregroundObj);
+ int underline = -1;
+ XGCValues gcValues;
+ GC gc1, gc2;
+ Tk_Anchor anchor = TK_ANCHOR_CENTER;
+ TkRegion clipRegion = NULL;
+
+ gcValues.font = Tk_FontId(text->tkfont);
+ gcValues.foreground = color->pixel;
+ gc1 = Tk_GetGC(tkwin, GCFont | GCForeground, &gcValues);
+ gcValues.foreground = WhitePixelOfScreen(Tk_Screen(tkwin));
+ gc2 = Tk_GetGC(tkwin, GCFont | GCForeground, &gcValues);
+
+ /*
+ * Place text according to -anchor:
+ */
+ Tk_GetAnchorFromObj(NULL, text->anchorObj, &anchor);
+ b = Ttk_AnchorBox(b, text->width, text->height, anchor);
+
+ /*
+ * Clip text if it's too wide:
+ */
+ if (b.width < text->width) {
+ XRectangle rect;
+
+ clipRegion = TkCreateRegion();
+ rect.x = b.x;
+ rect.y = b.y;
+ rect.width = b.width + (text->embossed ? 1 : 0);
+ rect.height = b.height + (text->embossed ? 1 : 0);
+ TkUnionRectWithRegion(&rect, clipRegion, clipRegion);
+ TkSetRegion(Tk_Display(tkwin), gc1, clipRegion);
+ TkSetRegion(Tk_Display(tkwin), gc2, clipRegion);
+#ifdef HAVE_XFT
+ TkUnixSetXftClipRegion(clipRegion);
+#endif
+ }
+
+ if (text->embossed) {
+ Tk_DrawTextLayout(Tk_Display(tkwin), d, gc2,
+ text->textLayout, b.x+1, b.y+1, 0/*firstChar*/, -1/*lastChar*/);
+ }
+ Tk_DrawTextLayout(Tk_Display(tkwin), d, gc1,
+ text->textLayout, b.x, b.y, 0/*firstChar*/, -1/*lastChar*/);
+
+ Tcl_GetIntFromObj(NULL, text->underlineObj, &underline);
+ if (underline >= 0) {
+ if (text->embossed) {
+ Tk_UnderlineTextLayout(Tk_Display(tkwin), d, gc2,
+ text->textLayout, b.x+1, b.y+1, underline);
+ }
+ Tk_UnderlineTextLayout(Tk_Display(tkwin), d, gc1,
+ text->textLayout, b.x, b.y, underline);
+ }
+
+ if (clipRegion != NULL) {
+#ifdef HAVE_XFT
+ TkUnixSetXftClipRegion(NULL);
+#endif
+ XSetClipMask(Tk_Display(tkwin), gc1, None);
+ XSetClipMask(Tk_Display(tkwin), gc2, None);
+ TkDestroyRegion(clipRegion);
+ }
+ Tk_FreeGC(Tk_Display(tkwin), gc1);
+ Tk_FreeGC(Tk_Display(tkwin), gc2);
+}
+
+static void TextElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ TextElement *text = elementRecord;
+
+ if (!TextSetup(text, tkwin))
+ return;
+
+ *heightPtr = text->height;
+ *widthPtr = TextReqWidth(text);
+
+ TextCleanup(text);
+
+ return;
+}
+
+static void TextElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, Ttk_State state)
+{
+ TextElement *text = elementRecord;
+ if (TextSetup(text, tkwin)) {
+ TextDraw(text, tkwin, d, b);
+ TextCleanup(text);
+ }
+}
+
+static Ttk_ElementSpec TextElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(TextElement),
+ TextElementOptions,
+ TextElementSize,
+ TextElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ Image element.
+ * Draws an image.
+ */
+
+typedef struct {
+ Tcl_Obj *imageObj;
+ Tcl_Obj *stippleObj; /* For TTK_STATE_DISABLED */
+ Tcl_Obj *backgroundObj; /* " " */
+
+ Ttk_ImageSpec *imageSpec;
+ Tk_Image tkimg;
+ int width;
+ int height;
+} ImageElement;
+
+/* ===> NB: Keep in sync with label element option table. <===
+ */
+static Ttk_ElementOptionSpec ImageElementOptions[] = {
+ { "-image", TK_OPTION_STRING,
+ Tk_Offset(ImageElement,imageObj), "" },
+ { "-stipple", TK_OPTION_STRING, /* Really: TK_OPTION_BITMAP */
+ Tk_Offset(ImageElement,stippleObj), "gray50" },
+ { "-background", TK_OPTION_COLOR,
+ Tk_Offset(ImageElement,backgroundObj), DEFAULT_BACKGROUND },
+ { NULL, 0, 0, NULL }
+};
+
+/*
+ * ImageSetup() --
+ * Look up the Tk_Image from the image element's imageObj resource.
+ * Caller must release the image with ImageCleanup().
+ *
+ * Returns:
+ * 1 if successful, 0 if there was an error (unreported)
+ * or the image resource was not specified.
+ */
+
+static int ImageSetup(
+ ImageElement *image, Tk_Window tkwin, Ttk_State state)
+{
+
+ if (!image->imageObj) {
+ return 0;
+ }
+ image->imageSpec = TtkGetImageSpec(NULL, tkwin, image->imageObj);
+ if (!image->imageSpec) {
+ return 0;
+ }
+ image->tkimg = TtkSelectImage(image->imageSpec, state);
+ if (!image->tkimg) {
+ TtkFreeImageSpec(image->imageSpec);
+ return 0;
+ }
+ Tk_SizeOfImage(image->tkimg, &image->width, &image->height);
+
+ return 1;
+}
+
+static void ImageCleanup(ImageElement *image)
+{
+ TtkFreeImageSpec(image->imageSpec);
+}
+
+#ifndef MAC_OSX_TK
+/*
+ * StippleOver --
+ * Draw a stipple over the image area, to make it look "grayed-out"
+ * when TTK_STATE_DISABLED is set.
+ */
+static void StippleOver(
+ ImageElement *image, Tk_Window tkwin, Drawable d, int x, int y)
+{
+ Pixmap stipple = Tk_AllocBitmapFromObj(NULL, tkwin, image->stippleObj);
+ XColor *color = Tk_GetColorFromObj(tkwin, image->backgroundObj);
+
+ if (stipple != None) {
+ unsigned long mask = GCFillStyle | GCStipple | GCForeground;
+ XGCValues gcvalues;
+ GC gc;
+ gcvalues.foreground = color->pixel;
+ gcvalues.fill_style = FillStippled;
+ gcvalues.stipple = stipple;
+ gc = Tk_GetGC(tkwin, mask, &gcvalues);
+ XFillRectangle(Tk_Display(tkwin),d,gc,x,y,image->width,image->height);
+ Tk_FreeGC(Tk_Display(tkwin), gc);
+ Tk_FreeBitmapFromObj(tkwin, image->stippleObj);
+ }
+}
+#endif
+
+static void ImageDraw(
+ ImageElement *image, Tk_Window tkwin,Drawable d,Ttk_Box b,Ttk_State state)
+{
+ int width = image->width, height = image->height;
+
+ /* Clip width and height to remain within window bounds:
+ */
+ if (b.x + width > Tk_Width(tkwin)) {
+ width = Tk_Width(tkwin) - b.x;
+ }
+ if (b.y + height > Tk_Height(tkwin)) {
+ height = Tk_Height(tkwin) - b.y;
+ }
+
+ if (height <= 0 || width <= 0) {
+ /* Completely clipped - bail out.
+ */
+ return;
+ }
+
+ Tk_RedrawImage(image->tkimg, 0,0, width, height, d, b.x, b.y);
+
+ /* If we're disabled there's no state-specific 'disabled' image,
+ * stipple the image.
+ * @@@ Possibly: Don't do disabled-stippling at all;
+ * @@@ it's ugly and out of fashion.
+ * Do not stipple at all under Aqua, just draw the image: it shows up
+ * as a white rectangle otherwise.
+ */
+
+
+ if (state & TTK_STATE_DISABLED) {
+ if (TtkSelectImage(image->imageSpec, 0ul) == image->tkimg) {
+#ifndef MAC_OSX_TK
+ StippleOver(image, tkwin, d, b.x,b.y);
+#endif
+ }
+ }
+}
+
+static void ImageElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ ImageElement *image = elementRecord;
+
+ if (ImageSetup(image, tkwin, 0)) {
+ *widthPtr = image->width;
+ *heightPtr = image->height;
+ ImageCleanup(image);
+ }
+}
+
+static void ImageElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, Ttk_State state)
+{
+ ImageElement *image = elementRecord;
+
+ if (ImageSetup(image, tkwin, state)) {
+ ImageDraw(image, tkwin, d, b, state);
+ ImageCleanup(image);
+ }
+}
+
+static Ttk_ElementSpec ImageElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(ImageElement),
+ ImageElementOptions,
+ ImageElementSize,
+ ImageElementDraw
+};
+
+/*------------------------------------------------------------------------
+ * +++ Label element.
+ *
+ * Displays an image and/or text, as determined by the -compound option.
+ *
+ * Differences from Tk 8.4 compound elements:
+ *
+ * This adds two new values for the -compound option, "text"
+ * and "image". (This is useful for configuring toolbars to
+ * display icons, text and icons, or text only, as found in
+ * many browsers.)
+ *
+ * "-compound none" is supported, but I'd like to get rid of it;
+ * it makes the logic more complex, and the only benefit is
+ * backwards compatibility with Tk < 8.3.0 scripts.
+ *
+ * This adds a new resource, -space, for determining how much
+ * space to leave between the text and image; Tk 8.4 reuses the
+ * -padx or -pady option for this purpose.
+ *
+ * -width always specifies the length in characters of the text part;
+ * in Tk 8.4 it's either characters or pixels, depending on the
+ * value of -compound.
+ *
+ * Negative values of -width are interpreted as a minimum width
+ * on all platforms, not just on Windows.
+ *
+ * Tk 8.4 ignores -padx and -pady if -compound is set to "none".
+ * Here, padding is handled by a different element.
+ */
+
+typedef struct {
+ /*
+ * Element options:
+ */
+ Tcl_Obj *compoundObj;
+ Tcl_Obj *spaceObj;
+ TextElement text;
+ ImageElement image;
+
+ /*
+ * Computed values (see LabelSetup)
+ */
+ Ttk_Compound compound;
+ int space;
+ int totalWidth, totalHeight;
+} LabelElement;
+
+static Ttk_ElementOptionSpec LabelElementOptions[] = {
+ { "-compound", TK_OPTION_ANY,
+ Tk_Offset(LabelElement,compoundObj), "none" },
+ { "-space", TK_OPTION_PIXELS,
+ Tk_Offset(LabelElement,spaceObj), "4" },
+
+ /* Text element part:
+ * NB: Keep in sync with TextElementOptions.
+ */
+ { "-text", TK_OPTION_STRING,
+ Tk_Offset(LabelElement,text.textObj), "" },
+ { "-font", TK_OPTION_FONT,
+ Tk_Offset(LabelElement,text.fontObj), DEFAULT_FONT },
+ { "-foreground", TK_OPTION_COLOR,
+ Tk_Offset(LabelElement,text.foregroundObj), "black" },
+ { "-underline", TK_OPTION_INT,
+ Tk_Offset(LabelElement,text.underlineObj), "-1"},
+ { "-width", TK_OPTION_INT,
+ Tk_Offset(LabelElement,text.widthObj), ""},
+ { "-anchor", TK_OPTION_ANCHOR,
+ Tk_Offset(LabelElement,text.anchorObj), "w"},
+ { "-justify", TK_OPTION_JUSTIFY,
+ Tk_Offset(LabelElement,text.justifyObj), "left" },
+ { "-wraplength", TK_OPTION_PIXELS,
+ Tk_Offset(LabelElement,text.wrapLengthObj), "0" },
+ { "-embossed", TK_OPTION_INT,
+ Tk_Offset(LabelElement,text.embossedObj), "0"},
+
+ /* Image element part:
+ * NB: Keep in sync with ImageElementOptions.
+ */
+ { "-image", TK_OPTION_STRING,
+ Tk_Offset(LabelElement,image.imageObj), "" },
+ { "-stipple", TK_OPTION_STRING, /* Really: TK_OPTION_BITMAP */
+ Tk_Offset(LabelElement,image.stippleObj), "gray50" },
+ { "-background", TK_OPTION_COLOR,
+ Tk_Offset(LabelElement,image.backgroundObj), DEFAULT_BACKGROUND },
+ { NULL, 0, 0, NULL }
+};
+
+/*
+ * LabelSetup --
+ * Fills in computed fields of the label element.
+ *
+ * Calculate the text, image, and total width and height.
+ */
+
+#undef MAX
+#define MAX(a,b) ((a) > (b) ? a : b);
+static void LabelSetup(
+ LabelElement *c, Tk_Window tkwin, Ttk_State state)
+{
+ Ttk_Compound *compoundPtr = &c->compound;
+
+ Tk_GetPixelsFromObj(NULL,tkwin,c->spaceObj,&c->space);
+ Ttk_GetCompoundFromObj(NULL,c->compoundObj,(int*)compoundPtr);
+
+ /*
+ * Deal with TTK_COMPOUND_NONE.
+ */
+ if (c->compound == TTK_COMPOUND_NONE) {
+ if (ImageSetup(&c->image, tkwin, state)) {
+ c->compound = TTK_COMPOUND_IMAGE;
+ } else {
+ c->compound = TTK_COMPOUND_TEXT;
+ }
+ } else if (c->compound != TTK_COMPOUND_TEXT) {
+ if (!ImageSetup(&c->image, tkwin, state)) {
+ c->compound = TTK_COMPOUND_TEXT;
+ }
+ }
+ if (c->compound != TTK_COMPOUND_IMAGE)
+ TextSetup(&c->text, tkwin);
+
+ /*
+ * ASSERT:
+ * if c->compound != IMAGE, then TextSetup() has been called
+ * if c->compound != TEXT, then ImageSetup() has returned successfully
+ * c->compound != COMPOUND_NONE.
+ */
+
+ switch (c->compound)
+ {
+ case TTK_COMPOUND_NONE:
+ /* Can't happen */
+ break;
+ case TTK_COMPOUND_TEXT:
+ c->totalWidth = c->text.width;
+ c->totalHeight = c->text.height;
+ break;
+ case TTK_COMPOUND_IMAGE:
+ c->totalWidth = c->image.width;
+ c->totalHeight = c->image.height;
+ break;
+ case TTK_COMPOUND_CENTER:
+ c->totalWidth = MAX(c->image.width, c->text.width);
+ c->totalHeight = MAX(c->image.height, c->text.height);
+ break;
+ case TTK_COMPOUND_TOP:
+ case TTK_COMPOUND_BOTTOM:
+ c->totalWidth = MAX(c->image.width, c->text.width);
+ c->totalHeight = c->image.height + c->text.height + c->space;
+ break;
+
+ case TTK_COMPOUND_LEFT:
+ case TTK_COMPOUND_RIGHT:
+ c->totalWidth = c->image.width + c->text.width + c->space;
+ c->totalHeight = MAX(c->image.height, c->text.height);
+ break;
+ }
+}
+
+static void LabelCleanup(LabelElement *c)
+{
+ if (c->compound != TTK_COMPOUND_TEXT)
+ ImageCleanup(&c->image);
+ if (c->compound != TTK_COMPOUND_IMAGE)
+ TextCleanup(&c->text);
+}
+
+static void LabelElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ LabelElement *label = elementRecord;
+ int textReqWidth = 0;
+
+ LabelSetup(label, tkwin, 0);
+
+ *heightPtr = label->totalHeight;
+
+ /* Requested width based on -width option, not actual text width:
+ */
+ if (label->compound != TTK_COMPOUND_IMAGE)
+ textReqWidth = TextReqWidth(&label->text);
+
+ switch (label->compound)
+ {
+ case TTK_COMPOUND_TEXT:
+ *widthPtr = textReqWidth;
+ break;
+ case TTK_COMPOUND_IMAGE:
+ *widthPtr = label->image.width;
+ break;
+ case TTK_COMPOUND_TOP:
+ case TTK_COMPOUND_BOTTOM:
+ case TTK_COMPOUND_CENTER:
+ *widthPtr = MAX(label->image.width, textReqWidth);
+ break;
+ case TTK_COMPOUND_LEFT:
+ case TTK_COMPOUND_RIGHT:
+ *widthPtr = label->image.width + textReqWidth + label->space;
+ break;
+ case TTK_COMPOUND_NONE:
+ break; /* Can't happen */
+ }
+
+ LabelCleanup(label);
+}
+
+/*
+ * DrawCompound --
+ * Helper routine for LabelElementDraw;
+ * Handles layout for -compound {left,right,top,bottom}
+ */
+static void DrawCompound(
+ LabelElement *l, Ttk_Box b, Tk_Window tkwin, Drawable d, Ttk_State state,
+ int imageSide, int textSide)
+{
+ Ttk_Box imageBox =
+ Ttk_PlaceBox(&b, l->image.width, l->image.height, imageSide, 0);
+ Ttk_Box textBox =
+ Ttk_PlaceBox(&b, l->text.width, l->text.height, textSide, 0);
+ ImageDraw(&l->image,tkwin,d,imageBox,state);
+ TextDraw(&l->text,tkwin,d,textBox);
+}
+
+static void LabelElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, Ttk_State state)
+{
+ LabelElement *l = elementRecord;
+ Tk_Anchor anchor = TK_ANCHOR_CENTER;
+
+ LabelSetup(l, tkwin, state);
+
+ /*
+ * Adjust overall parcel based on -anchor:
+ */
+ Tk_GetAnchorFromObj(NULL, l->text.anchorObj, &anchor);
+ b = Ttk_AnchorBox(b, l->totalWidth, l->totalHeight, anchor);
+
+ /*
+ * Draw text and/or image parts based on -compound:
+ */
+ switch (l->compound)
+ {
+ case TTK_COMPOUND_NONE:
+ /* Can't happen */
+ break;
+ case TTK_COMPOUND_TEXT:
+ TextDraw(&l->text,tkwin,d,b);
+ break;
+ case TTK_COMPOUND_IMAGE:
+ ImageDraw(&l->image,tkwin,d,b,state);
+ break;
+ case TTK_COMPOUND_CENTER:
+ {
+ Ttk_Box pb = Ttk_AnchorBox(
+ b, l->image.width, l->image.height, TK_ANCHOR_CENTER);
+ ImageDraw(&l->image, tkwin, d, pb, state);
+ pb = Ttk_AnchorBox(
+ b, l->text.width, l->text.height, TK_ANCHOR_CENTER);
+ TextDraw(&l->text, tkwin, d, pb);
+ break;
+ }
+ case TTK_COMPOUND_TOP:
+ DrawCompound(l, b, tkwin, d, state, TTK_SIDE_TOP, TTK_SIDE_BOTTOM);
+ break;
+ case TTK_COMPOUND_BOTTOM:
+ DrawCompound(l, b, tkwin, d, state, TTK_SIDE_BOTTOM, TTK_SIDE_TOP);
+ break;
+ case TTK_COMPOUND_LEFT:
+ DrawCompound(l, b, tkwin, d, state, TTK_SIDE_LEFT, TTK_SIDE_RIGHT);
+ break;
+ case TTK_COMPOUND_RIGHT:
+ DrawCompound(l, b, tkwin, d, state, TTK_SIDE_RIGHT, TTK_SIDE_LEFT);
+ break;
+ }
+
+ LabelCleanup(l);
+}
+
+static Ttk_ElementSpec LabelElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(LabelElement),
+ LabelElementOptions,
+ LabelElementSize,
+ LabelElementDraw
+};
+
+/*------------------------------------------------------------------------
+ * +++ Initialization.
+ */
+
+MODULE_SCOPE
+void TtkLabel_Init(Tcl_Interp *interp)
+{
+ Ttk_Theme theme = Ttk_GetDefaultTheme(interp);
+
+ Ttk_RegisterElement(interp, theme, "text", &TextElementSpec, NULL);
+ Ttk_RegisterElement(interp, theme, "image", &ImageElementSpec, NULL);
+ Ttk_RegisterElement(interp, theme, "label", &LabelElementSpec, NULL);
+}
+
diff --git a/tk8.6/generic/ttk/ttkLayout.c b/tk8.6/generic/ttk/ttkLayout.c
new file mode 100644
index 0000000..2512c4b
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkLayout.c
@@ -0,0 +1,1259 @@
+/*
+ * ttkLayout.c --
+ *
+ * Generic layout processing.
+ *
+ * Copyright (c) 2003 Joe English. Freely redistributable.
+ */
+
+#include <string.h>
+#include "tkInt.h"
+#include "ttkThemeInt.h"
+
+#define MAX(a,b) (a > b ? a : b)
+#define MIN(a,b) (a < b ? a : b)
+
+/*------------------------------------------------------------------------
+ * +++ Ttk_Box and Ttk_Padding utilities:
+ */
+
+Ttk_Box
+Ttk_MakeBox(int x, int y, int width, int height)
+{
+ Ttk_Box b;
+ b.x = x; b.y = y; b.width = width; b.height = height;
+ return b;
+}
+
+int
+Ttk_BoxContains(Ttk_Box box, int x, int y)
+{
+ return box.x <= x && x < box.x + box.width
+ && box.y <= y && y < box.y + box.height;
+}
+
+Tcl_Obj *
+Ttk_NewBoxObj(Ttk_Box box)
+{
+ Tcl_Obj *result[4];
+
+ result[0] = Tcl_NewIntObj(box.x);
+ result[1] = Tcl_NewIntObj(box.y);
+ result[2] = Tcl_NewIntObj(box.width);
+ result[3] = Tcl_NewIntObj(box.height);
+
+ return Tcl_NewListObj(4, result);
+}
+
+/*
+ * packTop, packBottom, packLeft, packRight --
+ * Carve out a parcel of the specified height (resp width)
+ * from the specified cavity.
+ *
+ * Returns:
+ * The new parcel.
+ *
+ * Side effects:
+ * Adjust the cavity.
+ */
+
+static Ttk_Box packTop(Ttk_Box *cavity, int height)
+{
+ Ttk_Box parcel;
+ height = MIN(height, cavity->height);
+ parcel = Ttk_MakeBox(cavity->x, cavity->y, cavity->width, height);
+ cavity->y += height;
+ cavity->height -= height;
+ return parcel;
+}
+
+static Ttk_Box packBottom(Ttk_Box *cavity, int height)
+{
+ height = MIN(height, cavity->height);
+ cavity->height -= height;
+ return Ttk_MakeBox(
+ cavity->x, cavity->y + cavity->height,
+ cavity->width, height);
+}
+
+static Ttk_Box packLeft(Ttk_Box *cavity, int width)
+{
+ Ttk_Box parcel;
+ width = MIN(width, cavity->width);
+ parcel = Ttk_MakeBox(cavity->x, cavity->y, width,cavity->height);
+ cavity->x += width;
+ cavity->width -= width;
+ return parcel;
+}
+
+static Ttk_Box packRight(Ttk_Box *cavity, int width)
+{
+ width = MIN(width, cavity->width);
+ cavity->width -= width;
+ return Ttk_MakeBox(cavity->x + cavity->width,
+ cavity->y, width, cavity->height);
+}
+
+/*
+ * Ttk_PackBox --
+ * Carve out a parcel of the specified size on the specified side
+ * in the specified cavity.
+ *
+ * Returns:
+ * The new parcel.
+ *
+ * Side effects:
+ * Adjust the cavity.
+ */
+
+Ttk_Box Ttk_PackBox(Ttk_Box *cavity, int width, int height, Ttk_Side side)
+{
+ switch (side) {
+ default:
+ case TTK_SIDE_TOP: return packTop(cavity, height);
+ case TTK_SIDE_BOTTOM: return packBottom(cavity, height);
+ case TTK_SIDE_LEFT: return packLeft(cavity, width);
+ case TTK_SIDE_RIGHT: return packRight(cavity, width);
+ }
+}
+
+/*
+ * Ttk_PadBox --
+ * Shrink a box by the specified padding amount.
+ */
+Ttk_Box Ttk_PadBox(Ttk_Box b, Ttk_Padding p)
+{
+ b.x += p.left;
+ b.y += p.top;
+ b.width -= (p.left + p.right);
+ b.height -= (p.top + p.bottom);
+ if (b.width <= 0) b.width = 1;
+ if (b.height <= 0) b.height = 1;
+ return b;
+}
+
+/*
+ * Ttk_ExpandBox --
+ * Grow a box by the specified padding amount.
+ */
+Ttk_Box Ttk_ExpandBox(Ttk_Box b, Ttk_Padding p)
+{
+ b.x -= p.left;
+ b.y -= p.top;
+ b.width += (p.left + p.right);
+ b.height += (p.top + p.bottom);
+ return b;
+}
+
+/*
+ * Ttk_StickBox --
+ * Place a box of size w * h in the specified parcel,
+ * according to the specified sticky bits.
+ */
+Ttk_Box Ttk_StickBox(Ttk_Box parcel, int width, int height, unsigned sticky)
+{
+ int dx, dy;
+
+ if (width > parcel.width) width = parcel.width;
+ if (height > parcel.height) height = parcel.height;
+
+ dx = parcel.width - width;
+ dy = parcel.height - height;
+
+ /*
+ * X coordinate adjustment:
+ */
+ switch (sticky & (TTK_STICK_W | TTK_STICK_E))
+ {
+ case TTK_STICK_W | TTK_STICK_E:
+ /* no-op -- use entire parcel width */
+ break;
+ case TTK_STICK_W:
+ parcel.width = width;
+ break;
+ case TTK_STICK_E:
+ parcel.x += dx;
+ parcel.width = width;
+ break;
+ default :
+ parcel.x += dx / 2;
+ parcel.width = width;
+ break;
+ }
+
+ /*
+ * Y coordinate adjustment:
+ */
+ switch (sticky & (TTK_STICK_N | TTK_STICK_S))
+ {
+ case TTK_STICK_N | TTK_STICK_S:
+ /* use entire parcel height */
+ break;
+ case TTK_STICK_N:
+ parcel.height = height;
+ break;
+ case TTK_STICK_S:
+ parcel.y += dy;
+ parcel.height = height;
+ break;
+ default :
+ parcel.y += dy / 2;
+ parcel.height = height;
+ break;
+ }
+
+ return parcel;
+}
+
+/*
+ * AnchorToSticky --
+ * Convert a Tk_Anchor enum to a TTK_STICKY bitmask.
+ */
+static Ttk_Sticky AnchorToSticky(Tk_Anchor anchor)
+{
+ switch (anchor)
+ {
+ case TK_ANCHOR_N: return TTK_STICK_N;
+ case TK_ANCHOR_NE: return TTK_STICK_N | TTK_STICK_E;
+ case TK_ANCHOR_E: return TTK_STICK_E;
+ case TK_ANCHOR_SE: return TTK_STICK_S | TTK_STICK_E;
+ case TK_ANCHOR_S: return TTK_STICK_S;
+ case TK_ANCHOR_SW: return TTK_STICK_S | TTK_STICK_W;
+ case TK_ANCHOR_W: return TTK_STICK_W;
+ case TK_ANCHOR_NW: return TTK_STICK_N | TTK_STICK_W;
+ default:
+ case TK_ANCHOR_CENTER: return 0;
+ }
+}
+
+/*
+ * Ttk_AnchorBox --
+ * Place a box of size w * h in the specified parcel,
+ * according to the specified anchor.
+ */
+Ttk_Box Ttk_AnchorBox(Ttk_Box parcel, int width, int height, Tk_Anchor anchor)
+{
+ return Ttk_StickBox(parcel, width, height, AnchorToSticky(anchor));
+}
+
+/*
+ * Ttk_PlaceBox --
+ * Combine Ttk_PackBox() and Ttk_StickBox().
+ */
+Ttk_Box Ttk_PlaceBox(
+ Ttk_Box *cavity, int width, int height, Ttk_Side side, unsigned sticky)
+{
+ return Ttk_StickBox(
+ Ttk_PackBox(cavity, width, height, side), width, height, sticky);
+}
+
+/*
+ * Ttk_PositionBox --
+ * Pack and stick a box according to PositionSpec flags.
+ */
+MODULE_SCOPE Ttk_Box
+Ttk_PositionBox(Ttk_Box *cavity, int width, int height, Ttk_PositionSpec flags)
+{
+ Ttk_Box parcel;
+
+ if (flags & TTK_EXPAND) parcel = *cavity;
+ else if (flags & TTK_PACK_TOP) parcel = packTop(cavity, height);
+ else if (flags & TTK_PACK_LEFT) parcel = packLeft(cavity, width);
+ else if (flags & TTK_PACK_BOTTOM) parcel = packBottom(cavity, height);
+ else if (flags & TTK_PACK_RIGHT) parcel = packRight(cavity, width);
+ else parcel = *cavity;
+
+ return Ttk_StickBox(parcel, width, height, flags);
+}
+
+/*
+ * TTKInitPadding --
+ * Common factor of Ttk_GetPaddingFromObj and Ttk_GetBorderFromObj.
+ * Initializes Ttk_Padding record, supplying default values
+ * for missing entries.
+ */
+static void TTKInitPadding(int padc, int pixels[4], Ttk_Padding *pad)
+{
+ switch (padc)
+ {
+ case 0: pixels[0] = 0; /*FALLTHRU*/
+ case 1: pixels[1] = pixels[0]; /*FALLTHRU*/
+ case 2: pixels[2] = pixels[0]; /*FALLTHRU*/
+ case 3: pixels[3] = pixels[1]; /*FALLTHRU*/
+ }
+
+ pad->left = (short)pixels[0];
+ pad->top = (short)pixels[1];
+ pad->right = (short)pixels[2];
+ pad->bottom = (short)pixels[3];
+}
+
+/*
+ * Ttk_GetPaddingFromObj --
+ *
+ * Extract a padding specification from a Tcl_Obj * scaled
+ * to work with a particular Tk_Window.
+ *
+ * The string representation of a Ttk_Padding is a list
+ * of one to four Tk_Pixel specifications, corresponding
+ * to the left, top, right, and bottom padding.
+ *
+ * If the 'bottom' (fourth) element is missing, it defaults to 'top'.
+ * If the 'right' (third) element is missing, it defaults to 'left'.
+ * If the 'top' (second) element is missing, it defaults to 'left'.
+ *
+ * The internal representation is a Tcl_ListObj containing
+ * one to four Tk_PixelObj objects.
+ *
+ * Returns:
+ * TCL_OK or TCL_ERROR. In the latter case an error message is
+ * left in 'interp' and '*paddingPtr' is set to all-zeros.
+ * Otherwise, *paddingPtr is filled in with the padding specification.
+ *
+ */
+int Ttk_GetPaddingFromObj(
+ Tcl_Interp *interp,
+ Tk_Window tkwin,
+ Tcl_Obj *objPtr,
+ Ttk_Padding *pad)
+{
+ Tcl_Obj **padv;
+ int i, padc, pixels[4];
+
+ if (TCL_OK != Tcl_ListObjGetElements(interp, objPtr, &padc, &padv)) {
+ goto error;
+ }
+
+ if (padc > 4) {
+ if (interp) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "Wrong #elements in padding spec", -1));
+ Tcl_SetErrorCode(interp, "TTK", "VALUE", "PADDING", NULL);
+ }
+ goto error;
+ }
+
+ for (i=0; i < padc; ++i) {
+ if (Tk_GetPixelsFromObj(interp, tkwin, padv[i], &pixels[i]) != TCL_OK) {
+ goto error;
+ }
+ }
+
+ TTKInitPadding(padc, pixels, pad);
+ return TCL_OK;
+
+error:
+ pad->left = pad->top = pad->right = pad->bottom = 0;
+ return TCL_ERROR;
+}
+
+/* Ttk_GetBorderFromObj --
+ * Same as Ttk_GetPaddingFromObj, except padding is a list of integers
+ * instead of Tk_Pixel specifications. Does not require a Tk_Window
+ * parameter.
+ *
+ */
+int Ttk_GetBorderFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_Padding *pad)
+{
+ Tcl_Obj **padv;
+ int i, padc, pixels[4];
+
+ if (TCL_OK != Tcl_ListObjGetElements(interp, objPtr, &padc, &padv)) {
+ goto error;
+ }
+
+ if (padc > 4) {
+ if (interp) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "Wrong #elements in padding spec", -1));
+ Tcl_SetErrorCode(interp, "TTK", "VALUE", "BORDER", NULL);
+ }
+ goto error;
+ }
+
+ for (i=0; i < padc; ++i) {
+ if (Tcl_GetIntFromObj(interp, padv[i], &pixels[i]) != TCL_OK) {
+ goto error;
+ }
+ }
+
+ TTKInitPadding(padc, pixels, pad);
+ return TCL_OK;
+
+error:
+ pad->left = pad->top = pad->right = pad->bottom = 0;
+ return TCL_ERROR;
+}
+
+/*
+ * Ttk_MakePadding --
+ * Return an initialized Ttk_Padding structure.
+ */
+Ttk_Padding Ttk_MakePadding(short left, short top, short right, short bottom)
+{
+ Ttk_Padding pad;
+ pad.left = left;
+ pad.top = top;
+ pad.right = right;
+ pad.bottom = bottom;
+ return pad;
+}
+
+/*
+ * Ttk_UniformPadding --
+ * Returns a uniform Ttk_Padding structure, with the same
+ * border width on all sides.
+ */
+Ttk_Padding Ttk_UniformPadding(short borderWidth)
+{
+ Ttk_Padding pad;
+ pad.left = pad.top = pad.right = pad.bottom = borderWidth;
+ return pad;
+}
+
+/*
+ * Ttk_AddPadding --
+ * Combine two padding records.
+ */
+Ttk_Padding Ttk_AddPadding(Ttk_Padding p1, Ttk_Padding p2)
+{
+ p1.left += p2.left;
+ p1.top += p2.top;
+ p1.right += p2.right;
+ p1.bottom += p2.bottom;
+ return p1;
+}
+
+/* Ttk_RelievePadding --
+ * Add an extra n pixels of padding according to specified relief.
+ * This may be used in element geometry procedures to simulate
+ * a "pressed-in" look for pushbuttons.
+ */
+Ttk_Padding Ttk_RelievePadding(Ttk_Padding padding, int relief, int n)
+{
+ switch (relief)
+ {
+ case TK_RELIEF_RAISED:
+ padding.right += n;
+ padding.bottom += n;
+ break;
+ case TK_RELIEF_SUNKEN: /* shift */
+ padding.left += n;
+ padding.top += n;
+ break;
+ default:
+ {
+ int h1 = n/2, h2 = h1 + n % 2;
+ padding.left += h1;
+ padding.top += h1;
+ padding.right += h2;
+ padding.bottom += h2;
+ break;
+ }
+ }
+ return padding;
+}
+
+/*
+ * Ttk_GetStickyFromObj --
+ * Returns a stickiness specification from the specified Tcl_Obj*,
+ * consisting of any combination of n, s, e, and w.
+ *
+ * Returns: TCL_OK if objPtr holds a valid stickiness specification,
+ * otherwise TCL_ERROR. interp is used for error reporting if non-NULL.
+ *
+ */
+int Ttk_GetStickyFromObj(
+ Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_Sticky *result)
+{
+ const char *string = Tcl_GetString(objPtr);
+ Ttk_Sticky sticky = 0;
+ char c;
+
+ while ((c = *string++) != '\0') {
+ switch (c) {
+ case 'w': case 'W': sticky |= TTK_STICK_W; break;
+ case 'e': case 'E': sticky |= TTK_STICK_E; break;
+ case 'n': case 'N': sticky |= TTK_STICK_N; break;
+ case 's': case 'S': sticky |= TTK_STICK_S; break;
+ default:
+ if (interp) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "Bad -sticky specification %s",
+ Tcl_GetString(objPtr)));
+ Tcl_SetErrorCode(interp, "TTK", "VALUE", "STICKY", NULL);
+ }
+ return TCL_ERROR;
+ }
+ }
+
+ *result = sticky;
+ return TCL_OK;
+}
+
+/* Ttk_NewStickyObj --
+ * Construct a new Tcl_Obj * containing a stickiness specification.
+ */
+Tcl_Obj *Ttk_NewStickyObj(Ttk_Sticky sticky)
+{
+ char buf[5];
+ char *p = buf;
+
+ if (sticky & TTK_STICK_N) *p++ = 'n';
+ if (sticky & TTK_STICK_S) *p++ = 's';
+ if (sticky & TTK_STICK_W) *p++ = 'w';
+ if (sticky & TTK_STICK_E) *p++ = 'e';
+
+ *p = '\0';
+ return Tcl_NewStringObj(buf, p - buf);
+}
+
+/*------------------------------------------------------------------------
+ * +++ Layout nodes.
+ */
+
+typedef struct Ttk_LayoutNode_ Ttk_LayoutNode;
+struct Ttk_LayoutNode_
+{
+ unsigned flags; /* Packing and sticky flags */
+ Ttk_ElementClass *eclass; /* Class record */
+ Ttk_State state; /* Current state */
+ Ttk_Box parcel; /* allocated parcel */
+ Ttk_LayoutNode *next, *child;
+};
+
+static Ttk_LayoutNode *Ttk_NewLayoutNode(
+ unsigned flags, Ttk_ElementClass *elementClass)
+{
+ Ttk_LayoutNode *node = ckalloc(sizeof(*node));
+
+ node->flags = flags;
+ node->eclass = elementClass;
+ node->state = 0u;
+ node->next = node->child = 0;
+ node->parcel = Ttk_MakeBox(0,0,0,0);
+
+ return node;
+}
+
+static void Ttk_FreeLayoutNode(Ttk_LayoutNode *node)
+{
+ while (node) {
+ Ttk_LayoutNode *next = node->next;
+ Ttk_FreeLayoutNode(node->child);
+ ckfree(node);
+ node = next;
+ }
+}
+
+/*------------------------------------------------------------------------
+ * +++ Layout templates.
+ */
+
+struct Ttk_TemplateNode_ {
+ char *name;
+ unsigned flags;
+ struct Ttk_TemplateNode_ *next, *child;
+};
+
+static Ttk_TemplateNode *Ttk_NewTemplateNode(const char *name, unsigned flags)
+{
+ Ttk_TemplateNode *op = ckalloc(sizeof(*op));
+ op->name = ckalloc(strlen(name) + 1); strcpy(op->name, name);
+ op->flags = flags;
+ op->next = op->child = 0;
+ return op;
+}
+
+void Ttk_FreeLayoutTemplate(Ttk_LayoutTemplate op)
+{
+ while (op) {
+ Ttk_LayoutTemplate next = op->next;
+ Ttk_FreeLayoutTemplate(op->child);
+ ckfree(op->name);
+ ckfree(op);
+ op = next;
+ }
+}
+
+/* InstantiateLayout --
+ * Create a layout tree from a template.
+ */
+static Ttk_LayoutNode *
+Ttk_InstantiateLayout(Ttk_Theme theme, Ttk_TemplateNode *op)
+{
+ Ttk_ElementClass *elementClass = Ttk_GetElement(theme, op->name);
+ Ttk_LayoutNode *node = Ttk_NewLayoutNode(op->flags, elementClass);
+
+ if (op->next) {
+ node->next = Ttk_InstantiateLayout(theme,op->next);
+ }
+ if (op->child) {
+ node->child = Ttk_InstantiateLayout(theme,op->child);
+ }
+
+ return node;
+}
+
+/*
+ * Ttk_ParseLayoutTemplate --
+ * Convert a Tcl list into a layout template.
+ *
+ * Syntax:
+ * layoutSpec ::= { elementName ?-option value ...? }+
+ */
+
+/* NB: This must match bit definitions TTK_PACK_LEFT etc. */
+static const char *packSideStrings[] =
+ { "left", "right", "top", "bottom", NULL };
+
+Ttk_LayoutTemplate Ttk_ParseLayoutTemplate(Tcl_Interp *interp, Tcl_Obj *objPtr)
+{
+ enum { OP_SIDE, OP_STICKY, OP_EXPAND, OP_BORDER, OP_UNIT, OP_CHILDREN };
+ static const char *optStrings[] = {
+ "-side", "-sticky", "-expand", "-border", "-unit", "-children", 0 };
+
+ int i = 0, objc;
+ Tcl_Obj **objv;
+ Ttk_TemplateNode *head = 0, *tail = 0;
+
+ if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK)
+ return 0;
+
+ while (i < objc) {
+ const char *elementName = Tcl_GetString(objv[i]);
+ unsigned flags = 0x0, sticky = TTK_FILL_BOTH;
+ Tcl_Obj *childSpec = 0;
+
+ /*
+ * Parse options:
+ */
+ ++i;
+ while (i < objc) {
+ const char *optName = Tcl_GetString(objv[i]);
+ int option, value;
+
+ if (optName[0] != '-')
+ break;
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[i], optStrings,
+ sizeof(char *), "option", 0, &option)
+ != TCL_OK)
+ {
+ goto error;
+ }
+
+ if (++i >= objc) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "Missing value for option %s",
+ Tcl_GetString(objv[i-1])));
+ Tcl_SetErrorCode(interp, "TTK", "VALUE", "LAYOUT", NULL);
+ goto error;
+ }
+
+ switch (option) {
+ case OP_SIDE: /* <<NOTE-PACKSIDE>> */
+ if (Tcl_GetIndexFromObjStruct(interp, objv[i], packSideStrings,
+ sizeof(char *), "side", 0, &value) != TCL_OK)
+ {
+ goto error;
+ }
+ flags |= (TTK_PACK_LEFT << value);
+
+ break;
+ case OP_STICKY:
+ if (Ttk_GetStickyFromObj(interp,objv[i],&sticky) != TCL_OK)
+ goto error;
+ break;
+ case OP_EXPAND:
+ if (Tcl_GetBooleanFromObj(interp,objv[i],&value) != TCL_OK)
+ goto error;
+ if (value)
+ flags |= TTK_EXPAND;
+ break;
+ case OP_BORDER:
+ if (Tcl_GetBooleanFromObj(interp,objv[i],&value) != TCL_OK)
+ goto error;
+ if (value)
+ flags |= TTK_BORDER;
+ break;
+ case OP_UNIT:
+ if (Tcl_GetBooleanFromObj(interp,objv[i],&value) != TCL_OK)
+ goto error;
+ if (value)
+ flags |= TTK_UNIT;
+ break;
+ case OP_CHILDREN:
+ childSpec = objv[i];
+ break;
+ }
+ ++i;
+ }
+
+ /*
+ * Build new node:
+ */
+ if (tail) {
+ tail->next = Ttk_NewTemplateNode(elementName, flags | sticky);
+ tail = tail->next;
+ } else {
+ head = tail = Ttk_NewTemplateNode(elementName, flags | sticky);
+ }
+ if (childSpec) {
+ tail->child = Ttk_ParseLayoutTemplate(interp, childSpec);
+ if (!tail->child) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf("Invalid -children value"));
+ Tcl_SetErrorCode(interp, "TTK", "VALUE", "CHILDREN", NULL);
+ goto error;
+ }
+ }
+ }
+
+ return head;
+
+error:
+ Ttk_FreeLayoutTemplate(head);
+ return 0;
+}
+
+/* Ttk_BuildLayoutTemplate --
+ * Build a layout template tree from a statically defined
+ * Ttk_LayoutSpec array.
+ */
+Ttk_LayoutTemplate Ttk_BuildLayoutTemplate(Ttk_LayoutSpec spec)
+{
+ Ttk_TemplateNode *first = 0, *last = 0;
+
+ for ( ; !(spec->opcode & _TTK_LAYOUT_END) ; ++spec) {
+ if (spec->elementName) {
+ Ttk_TemplateNode *node =
+ Ttk_NewTemplateNode(spec->elementName, spec->opcode);
+
+ if (last) {
+ last->next = node;
+ } else {
+ first = node;
+ }
+ last = node;
+ }
+
+ if (spec->opcode & _TTK_CHILDREN && last) {
+ int depth = 1;
+ last->child = Ttk_BuildLayoutTemplate(spec+1);
+
+ /* Skip to end of group:
+ */
+ while (depth) {
+ ++spec;
+ if (spec->opcode & _TTK_CHILDREN) {
+ ++depth;
+ }
+ if (spec->opcode & _TTK_LAYOUT_END) {
+ --depth;
+ }
+ }
+ }
+
+ } /* for */
+
+ return first;
+}
+
+void Ttk_RegisterLayouts(Ttk_Theme theme, Ttk_LayoutSpec spec)
+{
+ while (!(spec->opcode & _TTK_LAYOUT_END)) {
+ Ttk_LayoutTemplate layoutTemplate = Ttk_BuildLayoutTemplate(spec+1);
+ Ttk_RegisterLayoutTemplate(theme, spec->elementName, layoutTemplate);
+ do {
+ ++spec;
+ } while (!(spec->opcode & _TTK_LAYOUT));
+ }
+}
+
+Tcl_Obj *Ttk_UnparseLayoutTemplate(Ttk_TemplateNode *node)
+{
+ Tcl_Obj *result = Tcl_NewListObj(0,0);
+
+# define APPENDOBJ(obj) Tcl_ListObjAppendElement(NULL, result, obj)
+# define APPENDSTR(str) APPENDOBJ(Tcl_NewStringObj(str,-1))
+
+ while (node) {
+ unsigned flags = node->flags;
+
+ APPENDSTR(node->name);
+
+ /* Back-compute -side. <<NOTE-PACKSIDE>>
+ * @@@ NOTES: Ick.
+ */
+ if (flags & TTK_EXPAND) {
+ APPENDSTR("-expand");
+ APPENDSTR("1");
+ } else {
+ if (flags & _TTK_MASK_PACK) {
+ int side = 0;
+ unsigned sideFlags = flags & _TTK_MASK_PACK;
+
+ while (!(sideFlags & TTK_PACK_LEFT)) {
+ ++side;
+ sideFlags >>= 1;
+ }
+ APPENDSTR("-side");
+ APPENDSTR(packSideStrings[side]);
+ }
+ }
+
+ /*
+ * In Ttk_ParseLayoutTemplate, default -sticky is "nsew", so always
+ * include this even if no sticky bits are set.
+ */
+
+ APPENDSTR("-sticky");
+ APPENDOBJ(Ttk_NewStickyObj(flags & _TTK_MASK_STICK));
+
+ /* @@@ Check again: are these necessary? */
+ if (flags & TTK_BORDER) { APPENDSTR("-border"); APPENDSTR("1"); }
+ if (flags & TTK_UNIT) { APPENDSTR("-unit"); APPENDSTR("1"); }
+
+ if (node->child) {
+ APPENDSTR("-children");
+ APPENDOBJ(Ttk_UnparseLayoutTemplate(node->child));
+ }
+ node = node->next;
+ }
+
+# undef APPENDOBJ
+# undef APPENDSTR
+
+ return result;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Layouts.
+ */
+struct Ttk_Layout_
+{
+ Ttk_Style style;
+ void *recordPtr;
+ Tk_OptionTable optionTable;
+ Tk_Window tkwin;
+ Ttk_LayoutNode *root;
+};
+
+static Ttk_Layout TTKNewLayout(
+ Ttk_Style style,
+ void *recordPtr,Tk_OptionTable optionTable, Tk_Window tkwin,
+ Ttk_LayoutNode *root)
+{
+ Ttk_Layout layout = ckalloc(sizeof(*layout));
+ layout->style = style;
+ layout->recordPtr = recordPtr;
+ layout->optionTable = optionTable;
+ layout->tkwin = tkwin;
+ layout->root = root;
+ return layout;
+}
+
+void Ttk_FreeLayout(Ttk_Layout layout)
+{
+ Ttk_FreeLayoutNode(layout->root);
+ ckfree(layout);
+}
+
+/*
+ * Ttk_CreateLayout --
+ * Create a layout from the specified theme and style name.
+ * Returns: New layout, 0 on error.
+ * Leaves an error message in interp's result if there is an error.
+ */
+Ttk_Layout Ttk_CreateLayout(
+ Tcl_Interp *interp, /* where to leave error messages */
+ Ttk_Theme themePtr,
+ const char *styleName,
+ void *recordPtr,
+ Tk_OptionTable optionTable,
+ Tk_Window tkwin)
+{
+ Ttk_Style style = Ttk_GetStyle(themePtr, styleName);
+ Ttk_LayoutTemplate layoutTemplate =
+ Ttk_FindLayoutTemplate(themePtr,styleName);
+ Ttk_ElementClass *bgelement = Ttk_GetElement(themePtr, "background");
+ Ttk_LayoutNode *bgnode;
+
+ if (!layoutTemplate) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "Layout %s not found", styleName));
+ Tcl_SetErrorCode(interp, "TTK", "LOOKUP", "LAYOUT", styleName, NULL);
+ return 0;
+ }
+
+ bgnode = Ttk_NewLayoutNode(TTK_FILL_BOTH, bgelement);
+ bgnode->next = Ttk_InstantiateLayout(themePtr, layoutTemplate);
+
+ return TTKNewLayout(style, recordPtr, optionTable, tkwin, bgnode);
+}
+
+/* Ttk_CreateSublayout --
+ * Creates a new sublayout.
+ *
+ * Sublayouts are used to draw subparts of a compound widget.
+ * They use the same Tk_Window, but a different option table
+ * and data record.
+ */
+Ttk_Layout
+Ttk_CreateSublayout(
+ Tcl_Interp *interp,
+ Ttk_Theme themePtr,
+ Ttk_Layout parentLayout,
+ const char *baseName,
+ Tk_OptionTable optionTable)
+{
+ Tcl_DString buf;
+ const char *styleName;
+ Ttk_Style style;
+ Ttk_LayoutTemplate layoutTemplate;
+
+ Tcl_DStringInit(&buf);
+ Tcl_DStringAppend(&buf, Ttk_StyleName(parentLayout->style), -1);
+ Tcl_DStringAppend(&buf, baseName, -1);
+ styleName = Tcl_DStringValue(&buf);
+
+ style = Ttk_GetStyle(themePtr, styleName);
+ layoutTemplate = Ttk_FindLayoutTemplate(themePtr, styleName);
+
+ if (!layoutTemplate) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "Layout %s not found", styleName));
+ Tcl_SetErrorCode(interp, "TTK", "LOOKUP", "LAYOUT", styleName, NULL);
+ return 0;
+ }
+
+ Tcl_DStringFree(&buf);
+
+ return TTKNewLayout(
+ style, 0, optionTable, parentLayout->tkwin,
+ Ttk_InstantiateLayout(themePtr, layoutTemplate));
+}
+
+/* Ttk_RebindSublayout --
+ * Bind sublayout to new data source.
+ */
+void Ttk_RebindSublayout(Ttk_Layout layout, void *recordPtr)
+{
+ layout->recordPtr = recordPtr;
+}
+
+/*
+ * Ttk_QueryOption --
+ * Look up an option from a layout's associated option.
+ */
+Tcl_Obj *Ttk_QueryOption(
+ Ttk_Layout layout, const char *optionName, Ttk_State state)
+{
+ return Ttk_QueryStyle(
+ layout->style,layout->recordPtr,layout->optionTable,optionName,state);
+}
+
+/*
+ * Ttk_LayoutStyle --
+ * Extract Ttk_Style from Ttk_Layout.
+ */
+Ttk_Style Ttk_LayoutStyle(Ttk_Layout layout)
+{
+ return layout->style;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Size computation.
+ */
+static void Ttk_NodeListSize(
+ Ttk_Layout layout, Ttk_LayoutNode *node,
+ Ttk_State state, int *widthPtr, int *heightPtr); /* Forward */
+
+static void Ttk_NodeSize(
+ Ttk_Layout layout, Ttk_LayoutNode *node, Ttk_State state,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ int elementWidth, elementHeight, subWidth, subHeight;
+ Ttk_Padding elementPadding;
+
+ Ttk_ElementSize(node->eclass,
+ layout->style, layout->recordPtr,layout->optionTable, layout->tkwin,
+ state|node->state,
+ &elementWidth, &elementHeight, &elementPadding);
+
+ Ttk_NodeListSize(layout,node->child,state,&subWidth,&subHeight);
+ subWidth += Ttk_PaddingWidth(elementPadding);
+ subHeight += Ttk_PaddingHeight(elementPadding);
+
+ *widthPtr = MAX(elementWidth, subWidth);
+ *heightPtr = MAX(elementHeight, subHeight);
+ *paddingPtr = elementPadding;
+}
+
+static void Ttk_NodeListSize(
+ Ttk_Layout layout, Ttk_LayoutNode *node,
+ Ttk_State state, int *widthPtr, int *heightPtr)
+{
+ if (!node) {
+ *widthPtr = *heightPtr = 0;
+ } else {
+ int width, height, restWidth, restHeight;
+ Ttk_Padding unused;
+
+ Ttk_NodeSize(layout, node, state, &width, &height, &unused);
+ Ttk_NodeListSize(layout, node->next, state, &restWidth, &restHeight);
+
+ if (node->flags & (TTK_PACK_LEFT|TTK_PACK_RIGHT)) {
+ *widthPtr = width + restWidth;
+ } else {
+ *widthPtr = MAX(width, restWidth);
+ }
+
+ if (node->flags & (TTK_PACK_TOP|TTK_PACK_BOTTOM)) {
+ *heightPtr = height + restHeight;
+ } else {
+ *heightPtr = MAX(height, restHeight);
+ }
+ }
+}
+
+/*
+ * Ttk_LayoutNodeInternalPadding --
+ * Returns the internal padding of a layout node.
+ */
+Ttk_Padding Ttk_LayoutNodeInternalPadding(
+ Ttk_Layout layout, Ttk_LayoutNode *node)
+{
+ int unused;
+ Ttk_Padding padding;
+ Ttk_ElementSize(node->eclass,
+ layout->style, layout->recordPtr, layout->optionTable, layout->tkwin,
+ 0/*state*/, &unused, &unused, &padding);
+ return padding;
+}
+
+/*
+ * Ttk_LayoutNodeInternalParcel --
+ * Returns the inner area of a specified layout node,
+ * based on current parcel and element's internal padding.
+ */
+Ttk_Box Ttk_LayoutNodeInternalParcel(Ttk_Layout layout, Ttk_LayoutNode *node)
+{
+ Ttk_Padding padding = Ttk_LayoutNodeInternalPadding(layout, node);
+ return Ttk_PadBox(node->parcel, padding);
+}
+
+/* Ttk_LayoutSize --
+ * Compute requested size of a layout.
+ */
+void Ttk_LayoutSize(
+ Ttk_Layout layout, Ttk_State state, int *widthPtr, int *heightPtr)
+{
+ Ttk_NodeListSize(layout, layout->root, state, widthPtr, heightPtr);
+}
+
+void Ttk_LayoutNodeReqSize( /* @@@ Rename this */
+ Ttk_Layout layout, Ttk_LayoutNode *node, int *widthPtr, int *heightPtr)
+{
+ Ttk_Padding unused;
+ Ttk_NodeSize(layout, node, 0/*state*/, widthPtr, heightPtr, &unused);
+}
+
+/*------------------------------------------------------------------------
+ * +++ Layout placement.
+ */
+
+/* Ttk_PlaceNodeList --
+ * Compute parcel for each node in a layout tree
+ * according to position specification and overall size.
+ */
+static void Ttk_PlaceNodeList(
+ Ttk_Layout layout, Ttk_LayoutNode *node, Ttk_State state, Ttk_Box cavity)
+{
+ for (; node; node = node->next)
+ {
+ int width, height;
+ Ttk_Padding padding;
+
+ /* Compute node size: (@@@ cache this instead?)
+ */
+ Ttk_NodeSize(layout, node, state, &width, &height, &padding);
+
+ /* Compute parcel:
+ */
+ node->parcel = Ttk_PositionBox(&cavity, width, height, node->flags);
+
+ /* Place child nodes:
+ */
+ if (node->child) {
+ Ttk_Box childBox = Ttk_PadBox(node->parcel, padding);
+ Ttk_PlaceNodeList(layout,node->child, state, childBox);
+ }
+ }
+}
+
+void Ttk_PlaceLayout(Ttk_Layout layout, Ttk_State state, Ttk_Box b)
+{
+ Ttk_PlaceNodeList(layout, layout->root, state, b);
+}
+
+/*------------------------------------------------------------------------
+ * +++ Layout drawing.
+ */
+
+/*
+ * Ttk_DrawLayout --
+ * Draw a layout tree.
+ */
+static void Ttk_DrawNodeList(
+ Ttk_Layout layout, Ttk_State state, Ttk_LayoutNode *node, Drawable d)
+{
+ for (; node; node = node->next)
+ {
+ int border = node->flags & TTK_BORDER;
+ int substate = state;
+
+ if (node->flags & TTK_UNIT)
+ substate |= node->state;
+
+ if (node->child && border)
+ Ttk_DrawNodeList(layout, substate, node->child, d);
+
+ Ttk_DrawElement(
+ node->eclass,
+ layout->style,layout->recordPtr,layout->optionTable,layout->tkwin,
+ d, node->parcel, state | node->state);
+
+ if (node->child && !border)
+ Ttk_DrawNodeList(layout, substate, node->child, d);
+ }
+}
+
+void Ttk_DrawLayout(Ttk_Layout layout, Ttk_State state, Drawable d)
+{
+ Ttk_DrawNodeList(layout, state, layout->root, d);
+}
+
+/*------------------------------------------------------------------------
+ * +++ Inquiry and modification.
+ */
+
+/*
+ * Ttk_IdentifyElement --
+ * Find the element at the specified x,y coordinate.
+ */
+static Ttk_Element IdentifyNode(Ttk_Element node, int x, int y)
+{
+ Ttk_Element closest = NULL;
+
+ for (; node; node = node->next) {
+ if (Ttk_BoxContains(node->parcel, x, y)) {
+ closest = node;
+ if (node->child && !(node->flags & TTK_UNIT)) {
+ Ttk_Element childNode = IdentifyNode(node->child, x,y);
+ if (childNode) {
+ closest = childNode;
+ }
+ }
+ }
+ }
+ return closest;
+}
+
+Ttk_Element Ttk_IdentifyElement(Ttk_Layout layout, int x, int y)
+{
+ return IdentifyNode(layout->root, x, y);
+}
+
+/*
+ * tail --
+ * Return the last component of an element name, e.g.,
+ * "Scrollbar.thumb" => "thumb"
+ */
+static const char *tail(const char *elementName)
+{
+ const char *dot;
+ while ((dot=strchr(elementName,'.')) != NULL)
+ elementName = dot + 1;
+ return elementName;
+}
+
+/*
+ * Ttk_FindElement --
+ * Look up an element by name
+ */
+static Ttk_Element
+FindNode(Ttk_Element node, const char *nodeName)
+{
+ for (; node ; node = node->next) {
+ if (!strcmp(tail(Ttk_ElementName(node)), nodeName))
+ return node;
+
+ if (node->child) {
+ Ttk_Element childNode = FindNode(node->child, nodeName);
+ if (childNode)
+ return childNode;
+ }
+ }
+ return 0;
+}
+
+Ttk_Element Ttk_FindElement(Ttk_Layout layout, const char *nodeName)
+{
+ return FindNode(layout->root, nodeName);
+}
+
+/*
+ * Ttk_ClientRegion --
+ * Find the internal parcel of a named element within a given layout.
+ * If the element is not present, use the entire window.
+ */
+Ttk_Box Ttk_ClientRegion(Ttk_Layout layout, const char *elementName)
+{
+ Ttk_Element element = Ttk_FindElement(layout, elementName);
+ return element
+ ? Ttk_LayoutNodeInternalParcel(layout, element)
+ : Ttk_WinBox(layout->tkwin)
+ ;
+}
+
+/*
+ * Ttk_ElementName --
+ * Return the name (class name) of the element.
+ */
+const char *Ttk_ElementName(Ttk_Element node)
+{
+ return Ttk_ElementClassName(node->eclass);
+}
+
+/*
+ * Ttk_ElementParcel --
+ * Return the element's current parcel.
+ */
+Ttk_Box Ttk_ElementParcel(Ttk_Element node)
+{
+ return node->parcel;
+}
+
+/*
+ * Ttk_PlaceElement --
+ * Explicitly specify an element's parcel.
+ */
+void Ttk_PlaceElement(Ttk_Layout layout, Ttk_Element node, Ttk_Box b)
+{
+ node->parcel = b;
+ if (node->child) {
+ Ttk_PlaceNodeList(layout, node->child, 0,
+ Ttk_PadBox(b, Ttk_LayoutNodeInternalPadding(layout, node)));
+ }
+}
+
+/*
+ * Ttk_ChangeElementState --
+ */
+void Ttk_ChangeElementState(Ttk_LayoutNode *node,unsigned set,unsigned clr)
+{
+ node->state = (node->state | set) & ~clr;
+}
+
+/*EOF*/
diff --git a/tk8.6/generic/ttk/ttkManager.c b/tk8.6/generic/ttk/ttkManager.c
new file mode 100644
index 0000000..24a0fb1
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkManager.c
@@ -0,0 +1,549 @@
+/*
+ * Copyright 2005, Joe English. Freely redistributable.
+ *
+ * Support routines for geometry managers.
+ */
+
+#include <string.h>
+#include <tk.h>
+#include "ttkManager.h"
+
+/*------------------------------------------------------------------------
+ * +++ The Geometry Propagation Dance.
+ *
+ * When a slave window requests a new size or some other parameter changes,
+ * the manager recomputes the required size for the master window and calls
+ * Tk_GeometryRequest(). This is scheduled as an idle handler so multiple
+ * updates can be processed as a single batch.
+ *
+ * If all goes well, the master's manager will process the request
+ * (and so on up the chain to the toplevel window), and the master
+ * window will eventually receive a <Configure> event. At this point
+ * it recomputes the size and position of all slaves and places them.
+ *
+ * If all does not go well, however, the master's request may be ignored
+ * (typically because the top-level window has a fixed, user-specified size).
+ * Tk doesn't provide any notification when this happens; to account for this,
+ * we also schedule an idle handler to call the layout procedure
+ * after making a geometry request.
+ *
+ * +++ Slave removal <<NOTE-LOSTSLAVE>>.
+ *
+ * There are three conditions under which a slave is removed:
+ *
+ * (1) Another GM claims control
+ * (2) Manager voluntarily relinquishes control
+ * (3) Slave is destroyed
+ *
+ * In case (1), Tk calls the manager's lostSlaveProc.
+ * Case (2) is performed by calling Tk_ManageGeometry(slave,NULL,0);
+ * in this case Tk does _not_ call the LostSlaveProc (documented behavior).
+ * Tk doesn't handle case (3) either; to account for that we
+ * register an event handler on the slave widget to track <Destroy> events.
+ */
+
+/* ++ Data structures.
+ */
+typedef struct
+{
+ Tk_Window slaveWindow;
+ Ttk_Manager *manager;
+ void *slaveData;
+ unsigned flags;
+} Ttk_Slave;
+
+/* slave->flags bits:
+ */
+#define SLAVE_MAPPED 0x1 /* slave to be mapped when master is */
+
+struct TtkManager_
+{
+ Ttk_ManagerSpec *managerSpec;
+ void *managerData;
+ Tk_Window masterWindow;
+ unsigned flags;
+ int nSlaves;
+ Ttk_Slave **slaves;
+};
+
+/* manager->flags bits:
+ */
+#define MGR_UPDATE_PENDING 0x1
+#define MGR_RESIZE_REQUIRED 0x2
+#define MGR_RELAYOUT_REQUIRED 0x4
+
+static void ManagerIdleProc(void *); /* forward */
+
+/* ++ ScheduleUpdate --
+ * Schedule a call to recompute the size and/or layout,
+ * depending on flags.
+ */
+static void ScheduleUpdate(Ttk_Manager *mgr, unsigned flags)
+{
+ if (!(mgr->flags & MGR_UPDATE_PENDING)) {
+ Tcl_DoWhenIdle(ManagerIdleProc, mgr);
+ mgr->flags |= MGR_UPDATE_PENDING;
+ }
+ mgr->flags |= flags;
+}
+
+/* ++ RecomputeSize --
+ * Recomputes the required size of the master window,
+ * makes geometry request.
+ */
+static void RecomputeSize(Ttk_Manager *mgr)
+{
+ int width = 1, height = 1;
+
+ if (mgr->managerSpec->RequestedSize(mgr->managerData, &width, &height)) {
+ Tk_GeometryRequest(mgr->masterWindow, width, height);
+ ScheduleUpdate(mgr, MGR_RELAYOUT_REQUIRED);
+ }
+ mgr->flags &= ~MGR_RESIZE_REQUIRED;
+}
+
+/* ++ RecomputeLayout --
+ * Recompute geometry of all slaves.
+ */
+static void RecomputeLayout(Ttk_Manager *mgr)
+{
+ mgr->managerSpec->PlaceSlaves(mgr->managerData);
+ mgr->flags &= ~MGR_RELAYOUT_REQUIRED;
+}
+
+/* ++ ManagerIdleProc --
+ * DoWhenIdle procedure for deferred updates.
+ */
+static void ManagerIdleProc(ClientData clientData)
+{
+ Ttk_Manager *mgr = clientData;
+ mgr->flags &= ~MGR_UPDATE_PENDING;
+
+ if (mgr->flags & MGR_RESIZE_REQUIRED) {
+ RecomputeSize(mgr);
+ }
+ if (mgr->flags & MGR_RELAYOUT_REQUIRED) {
+ if (mgr->flags & MGR_UPDATE_PENDING) {
+ /* RecomputeSize has scheduled another update; relayout later */
+ return;
+ }
+ RecomputeLayout(mgr);
+ }
+}
+
+/*------------------------------------------------------------------------
+ * +++ Event handlers.
+ */
+
+/* ++ ManagerEventHandler --
+ * Recompute slave layout when master widget is resized.
+ * Keep the slave's map state in sync with the master's.
+ */
+static const int ManagerEventMask = StructureNotifyMask;
+static void ManagerEventHandler(ClientData clientData, XEvent *eventPtr)
+{
+ Ttk_Manager *mgr = clientData;
+ int i;
+
+ switch (eventPtr->type)
+ {
+ case ConfigureNotify:
+ RecomputeLayout(mgr);
+ break;
+ case MapNotify:
+ for (i = 0; i < mgr->nSlaves; ++i) {
+ Ttk_Slave *slave = mgr->slaves[i];
+ if (slave->flags & SLAVE_MAPPED) {
+ Tk_MapWindow(slave->slaveWindow);
+ }
+ }
+ break;
+ case UnmapNotify:
+ for (i = 0; i < mgr->nSlaves; ++i) {
+ Ttk_Slave *slave = mgr->slaves[i];
+ Tk_UnmapWindow(slave->slaveWindow);
+ }
+ break;
+ }
+}
+
+/* ++ SlaveEventHandler --
+ * Notifies manager when a slave is destroyed
+ * (see <<NOTE-LOSTSLAVE>>).
+ */
+static const unsigned SlaveEventMask = StructureNotifyMask;
+static void SlaveEventHandler(ClientData clientData, XEvent *eventPtr)
+{
+ Ttk_Slave *slave = clientData;
+ if (eventPtr->type == DestroyNotify) {
+ slave->manager->managerSpec->tkGeomMgr.lostSlaveProc(
+ slave->manager, slave->slaveWindow);
+ }
+}
+
+/*------------------------------------------------------------------------
+ * +++ Slave initialization and cleanup.
+ */
+
+static Ttk_Slave *NewSlave(
+ Ttk_Manager *mgr, Tk_Window slaveWindow, void *slaveData)
+{
+ Ttk_Slave *slave = ckalloc(sizeof(*slave));
+
+ slave->slaveWindow = slaveWindow;
+ slave->manager = mgr;
+ slave->flags = 0;
+ slave->slaveData = slaveData;
+
+ return slave;
+}
+
+static void DeleteSlave(Ttk_Slave *slave)
+{
+ ckfree(slave);
+}
+
+/*------------------------------------------------------------------------
+ * +++ Manager initialization and cleanup.
+ */
+
+Ttk_Manager *Ttk_CreateManager(
+ Ttk_ManagerSpec *managerSpec, void *managerData, Tk_Window masterWindow)
+{
+ Ttk_Manager *mgr = ckalloc(sizeof(*mgr));
+
+ mgr->managerSpec = managerSpec;
+ mgr->managerData = managerData;
+ mgr->masterWindow = masterWindow;
+ mgr->nSlaves = 0;
+ mgr->slaves = NULL;
+ mgr->flags = 0;
+
+ Tk_CreateEventHandler(
+ mgr->masterWindow, ManagerEventMask, ManagerEventHandler, mgr);
+
+ return mgr;
+}
+
+void Ttk_DeleteManager(Ttk_Manager *mgr)
+{
+ Tk_DeleteEventHandler(
+ mgr->masterWindow, ManagerEventMask, ManagerEventHandler, mgr);
+
+ while (mgr->nSlaves > 0) {
+ Ttk_ForgetSlave(mgr, mgr->nSlaves - 1);
+ }
+ if (mgr->slaves) {
+ ckfree(mgr->slaves);
+ }
+
+ Tcl_CancelIdleCall(ManagerIdleProc, mgr);
+
+ ckfree(mgr);
+}
+
+/*------------------------------------------------------------------------
+ * +++ Slave management.
+ */
+
+/* ++ InsertSlave --
+ * Adds slave to the list of managed windows.
+ */
+static void InsertSlave(Ttk_Manager *mgr, Ttk_Slave *slave, int index)
+{
+ int endIndex = mgr->nSlaves++;
+ mgr->slaves = ckrealloc(mgr->slaves, mgr->nSlaves * sizeof(Ttk_Slave *));
+
+ while (endIndex > index) {
+ mgr->slaves[endIndex] = mgr->slaves[endIndex - 1];
+ --endIndex;
+ }
+
+ mgr->slaves[index] = slave;
+
+ Tk_ManageGeometry(slave->slaveWindow,
+ &mgr->managerSpec->tkGeomMgr, (ClientData)mgr);
+
+ Tk_CreateEventHandler(slave->slaveWindow,
+ SlaveEventMask, SlaveEventHandler, (ClientData)slave);
+
+ ScheduleUpdate(mgr, MGR_RESIZE_REQUIRED);
+}
+
+/* RemoveSlave --
+ * Unmanage and delete the slave.
+ *
+ * NOTES/ASSUMPTIONS:
+ *
+ * [1] It's safe to call Tk_UnmapWindow / Tk_UnmaintainGeometry even if this
+ * routine is called from the slave's DestroyNotify event handler.
+ */
+static void RemoveSlave(Ttk_Manager *mgr, int index)
+{
+ Ttk_Slave *slave = mgr->slaves[index];
+ int i;
+
+ /* Notify manager:
+ */
+ mgr->managerSpec->SlaveRemoved(mgr->managerData, index);
+
+ /* Remove from array:
+ */
+ --mgr->nSlaves;
+ for (i = index ; i < mgr->nSlaves; ++i) {
+ mgr->slaves[i] = mgr->slaves[i+1];
+ }
+
+ /* Clean up:
+ */
+ Tk_DeleteEventHandler(
+ slave->slaveWindow, SlaveEventMask, SlaveEventHandler, slave);
+
+ /* Note [1] */
+ Tk_UnmaintainGeometry(slave->slaveWindow, mgr->masterWindow);
+ Tk_UnmapWindow(slave->slaveWindow);
+
+ DeleteSlave(slave);
+
+ ScheduleUpdate(mgr, MGR_RESIZE_REQUIRED);
+}
+
+/*------------------------------------------------------------------------
+ * +++ Tk_GeomMgr hooks.
+ */
+
+void Ttk_GeometryRequestProc(ClientData clientData, Tk_Window slaveWindow)
+{
+ Ttk_Manager *mgr = clientData;
+ int slaveIndex = Ttk_SlaveIndex(mgr, slaveWindow);
+ int reqWidth = Tk_ReqWidth(slaveWindow);
+ int reqHeight= Tk_ReqHeight(slaveWindow);
+
+ if (mgr->managerSpec->SlaveRequest(
+ mgr->managerData, slaveIndex, reqWidth, reqHeight))
+ {
+ ScheduleUpdate(mgr, MGR_RESIZE_REQUIRED);
+ }
+}
+
+void Ttk_LostSlaveProc(ClientData clientData, Tk_Window slaveWindow)
+{
+ Ttk_Manager *mgr = clientData;
+ int index = Ttk_SlaveIndex(mgr, slaveWindow);
+
+ /* ASSERT: index >= 0 */
+ RemoveSlave(mgr, index);
+}
+
+/*------------------------------------------------------------------------
+ * +++ Public API.
+ */
+
+/* ++ Ttk_InsertSlave --
+ * Add a new slave window at the specified index.
+ */
+void Ttk_InsertSlave(
+ Ttk_Manager *mgr, int index, Tk_Window tkwin, void *slaveData)
+{
+ Ttk_Slave *slave = NewSlave(mgr, tkwin, slaveData);
+ InsertSlave(mgr, slave, index);
+}
+
+/* ++ Ttk_ForgetSlave --
+ * Unmanage the specified slave.
+ */
+void Ttk_ForgetSlave(Ttk_Manager *mgr, int slaveIndex)
+{
+ Tk_Window slaveWindow = mgr->slaves[slaveIndex]->slaveWindow;
+ RemoveSlave(mgr, slaveIndex);
+ Tk_ManageGeometry(slaveWindow, NULL, 0);
+}
+
+/* ++ Ttk_PlaceSlave --
+ * Set the position and size of the specified slave window.
+ *
+ * NOTES:
+ * Contrary to documentation, Tk_MaintainGeometry doesn't always
+ * map the slave.
+ */
+void Ttk_PlaceSlave(
+ Ttk_Manager *mgr, int slaveIndex, int x, int y, int width, int height)
+{
+ Ttk_Slave *slave = mgr->slaves[slaveIndex];
+ Tk_MaintainGeometry(slave->slaveWindow,mgr->masterWindow,x,y,width,height);
+ slave->flags |= SLAVE_MAPPED;
+ if (Tk_IsMapped(mgr->masterWindow)) {
+ Tk_MapWindow(slave->slaveWindow);
+ }
+}
+
+/* ++ Ttk_UnmapSlave --
+ * Unmap the specified slave, but leave it managed.
+ */
+void Ttk_UnmapSlave(Ttk_Manager *mgr, int slaveIndex)
+{
+ Ttk_Slave *slave = mgr->slaves[slaveIndex];
+ Tk_UnmaintainGeometry(slave->slaveWindow, mgr->masterWindow);
+ slave->flags &= ~SLAVE_MAPPED;
+ /* Contrary to documentation, Tk_UnmaintainGeometry doesn't always
+ * unmap the slave:
+ */
+ Tk_UnmapWindow(slave->slaveWindow);
+}
+
+/* LayoutChanged, SizeChanged --
+ * Schedule a relayout, resp. resize request.
+ */
+void Ttk_ManagerLayoutChanged(Ttk_Manager *mgr)
+{
+ ScheduleUpdate(mgr, MGR_RELAYOUT_REQUIRED);
+}
+
+void Ttk_ManagerSizeChanged(Ttk_Manager *mgr)
+{
+ ScheduleUpdate(mgr, MGR_RESIZE_REQUIRED);
+}
+
+/* +++ Accessors.
+ */
+int Ttk_NumberSlaves(Ttk_Manager *mgr)
+{
+ return mgr->nSlaves;
+}
+void *Ttk_SlaveData(Ttk_Manager *mgr, int slaveIndex)
+{
+ return mgr->slaves[slaveIndex]->slaveData;
+}
+Tk_Window Ttk_SlaveWindow(Ttk_Manager *mgr, int slaveIndex)
+{
+ return mgr->slaves[slaveIndex]->slaveWindow;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Utility routines.
+ */
+
+/* ++ Ttk_SlaveIndex --
+ * Returns the index of specified slave window, -1 if not found.
+ */
+int Ttk_SlaveIndex(Ttk_Manager *mgr, Tk_Window slaveWindow)
+{
+ int index;
+ for (index = 0; index < mgr->nSlaves; ++index)
+ if (mgr->slaves[index]->slaveWindow == slaveWindow)
+ return index;
+ return -1;
+}
+
+/* ++ Ttk_GetSlaveIndexFromObj(interp, mgr, objPtr, indexPtr) --
+ * Return the index of the slave specified by objPtr.
+ * Slaves may be specified as an integer index or
+ * as the name of the managed window.
+ *
+ * Returns:
+ * Standard Tcl completion code. Leaves an error message in case of error.
+ */
+
+int Ttk_GetSlaveIndexFromObj(
+ Tcl_Interp *interp, Ttk_Manager *mgr, Tcl_Obj *objPtr, int *indexPtr)
+{
+ const char *string = Tcl_GetString(objPtr);
+ int slaveIndex = 0;
+ Tk_Window tkwin;
+
+ /* Try interpreting as an integer first:
+ */
+ if (Tcl_GetIntFromObj(NULL, objPtr, &slaveIndex) == TCL_OK) {
+ if (slaveIndex < 0 || slaveIndex >= mgr->nSlaves) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "Slave index %d out of bounds", slaveIndex));
+ Tcl_SetErrorCode(interp, "TTK", "SLAVE", "INDEX", NULL);
+ return TCL_ERROR;
+ }
+ *indexPtr = slaveIndex;
+ return TCL_OK;
+ }
+
+ /* Try interpreting as a slave window name;
+ */
+ if ((*string == '.') &&
+ (tkwin = Tk_NameToWindow(interp, string, mgr->masterWindow))) {
+ slaveIndex = Ttk_SlaveIndex(mgr, tkwin);
+ if (slaveIndex < 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "%s is not managed by %s", string,
+ Tk_PathName(mgr->masterWindow)));
+ Tcl_SetErrorCode(interp, "TTK", "SLAVE", "MANAGER", NULL);
+ return TCL_ERROR;
+ }
+ *indexPtr = slaveIndex;
+ return TCL_OK;
+ }
+
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "Invalid slave specification %s", string));
+ Tcl_SetErrorCode(interp, "TTK", "SLAVE", "SPEC", NULL);
+ return TCL_ERROR;
+}
+
+/* ++ Ttk_ReorderSlave(mgr, fromIndex, toIndex) --
+ * Change slave order.
+ */
+void Ttk_ReorderSlave(Ttk_Manager *mgr, int fromIndex, int toIndex)
+{
+ Ttk_Slave *moved = mgr->slaves[fromIndex];
+
+ /* Shuffle down: */
+ while (fromIndex > toIndex) {
+ mgr->slaves[fromIndex] = mgr->slaves[fromIndex - 1];
+ --fromIndex;
+ }
+ /* Or, shuffle up: */
+ while (fromIndex < toIndex) {
+ mgr->slaves[fromIndex] = mgr->slaves[fromIndex + 1];
+ ++fromIndex;
+ }
+ /* ASSERT: fromIndex == toIndex */
+ mgr->slaves[fromIndex] = moved;
+
+ /* Schedule a relayout. In general, rearranging slaves
+ * may also change the size:
+ */
+ ScheduleUpdate(mgr, MGR_RESIZE_REQUIRED);
+}
+
+/* ++ Ttk_Maintainable(interp, slave, master) --
+ * Utility routine. Verifies that 'master' may be used to maintain
+ * the geometry of 'slave' via Tk_MaintainGeometry:
+ *
+ * + 'master' is either 'slave's parent -OR-
+ * + 'master is a descendant of 'slave's parent.
+ * + 'slave' is not a toplevel window
+ * + 'slave' belongs to the same toplevel as 'master'
+ *
+ * Returns: 1 if OK; otherwise 0, leaving an error message in 'interp'.
+ */
+int Ttk_Maintainable(Tcl_Interp *interp, Tk_Window slave, Tk_Window master)
+{
+ Tk_Window ancestor = master, parent = Tk_Parent(slave);
+
+ if (Tk_IsTopLevel(slave) || slave == master) {
+ goto badWindow;
+ }
+
+ while (ancestor != parent) {
+ if (Tk_IsTopLevel(ancestor)) {
+ goto badWindow;
+ }
+ ancestor = Tk_Parent(ancestor);
+ }
+
+ return 1;
+
+badWindow:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf("can't add %s as slave of %s",
+ Tk_PathName(slave), Tk_PathName(master)));
+ Tcl_SetErrorCode(interp, "TTK", "GEOMETRY", "MAINTAINABLE", NULL);
+ return 0;
+}
+
diff --git a/tk8.6/generic/ttk/ttkManager.h b/tk8.6/generic/ttk/ttkManager.h
new file mode 100644
index 0000000..d22ff98
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkManager.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2005, Joe English. Freely redistributable.
+ *
+ * Geometry manager utilities.
+ */
+
+#ifndef _TTKMANAGER
+#define _TTKMANAGER
+
+#include "ttkTheme.h"
+
+typedef struct TtkManager_ Ttk_Manager;
+
+/*
+ * Geometry manager specification record:
+ *
+ * RequestedSize computes the requested size of the master window.
+ *
+ * PlaceSlaves sets the position and size of all managed slaves
+ * by calling Ttk_PlaceSlave().
+ *
+ * SlaveRemoved() is called immediately before a slave is removed.
+ * NB: the associated slave window may have been destroyed when this
+ * routine is called.
+ *
+ * SlaveRequest() is called when a slave requests a size change.
+ * It should return 1 if the request should propagate, 0 otherwise.
+ */
+typedef struct { /* Manager hooks */
+ Tk_GeomMgr tkGeomMgr; /* "real" Tk Geometry Manager */
+
+ int (*RequestedSize)(void *managerData, int *widthPtr, int *heightPtr);
+ void (*PlaceSlaves)(void *managerData);
+ int (*SlaveRequest)(void *managerData, int slaveIndex, int w, int h);
+ void (*SlaveRemoved)(void *managerData, int slaveIndex);
+} Ttk_ManagerSpec;
+
+/*
+ * Default implementations for Tk_GeomMgr hooks:
+ */
+MODULE_SCOPE void Ttk_GeometryRequestProc(ClientData, Tk_Window slave);
+MODULE_SCOPE void Ttk_LostSlaveProc(ClientData, Tk_Window slave);
+
+/*
+ * Public API:
+ */
+MODULE_SCOPE Ttk_Manager *Ttk_CreateManager(
+ Ttk_ManagerSpec *, void *managerData, Tk_Window masterWindow);
+MODULE_SCOPE void Ttk_DeleteManager(Ttk_Manager *);
+
+MODULE_SCOPE void Ttk_InsertSlave(
+ Ttk_Manager *, int position, Tk_Window, void *slaveData);
+
+MODULE_SCOPE void Ttk_ForgetSlave(Ttk_Manager *, int slaveIndex);
+
+MODULE_SCOPE void Ttk_ReorderSlave(Ttk_Manager *, int fromIndex, int toIndex);
+ /* Rearrange slave positions */
+
+MODULE_SCOPE void Ttk_PlaceSlave(
+ Ttk_Manager *, int slaveIndex, int x, int y, int width, int height);
+ /* Position and map the slave */
+
+MODULE_SCOPE void Ttk_UnmapSlave(Ttk_Manager *, int slaveIndex);
+ /* Unmap the slave */
+
+MODULE_SCOPE void Ttk_ManagerSizeChanged(Ttk_Manager *);
+MODULE_SCOPE void Ttk_ManagerLayoutChanged(Ttk_Manager *);
+ /* Notify manager that size (resp. layout) needs to be recomputed */
+
+/* Utilities:
+ */
+MODULE_SCOPE int Ttk_SlaveIndex(Ttk_Manager *, Tk_Window);
+ /* Returns: index in slave array of specified window, -1 if not found */
+
+MODULE_SCOPE int Ttk_GetSlaveIndexFromObj(
+ Tcl_Interp *, Ttk_Manager *, Tcl_Obj *, int *indexPtr);
+
+/* Accessor functions:
+ */
+MODULE_SCOPE int Ttk_NumberSlaves(Ttk_Manager *);
+ /* Returns: number of managed slaves */
+
+MODULE_SCOPE void *Ttk_SlaveData(Ttk_Manager *, int slaveIndex);
+ /* Returns: client data associated with slave */
+
+MODULE_SCOPE Tk_Window Ttk_SlaveWindow(Ttk_Manager *, int slaveIndex);
+ /* Returns: slave window */
+
+MODULE_SCOPE int Ttk_Maintainable(Tcl_Interp *, Tk_Window slave, Tk_Window master);
+ /* Returns: 1 if master can manage slave; 0 otherwise leaving error msg */
+
+#endif /* _TTKMANAGER */
diff --git a/tk8.6/generic/ttk/ttkNotebook.c b/tk8.6/generic/ttk/ttkNotebook.c
new file mode 100644
index 0000000..56439a6
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkNotebook.c
@@ -0,0 +1,1421 @@
+/*
+ * Copyright (c) 2004, Joe English
+ */
+
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <tk.h>
+
+#include "ttkTheme.h"
+#include "ttkWidget.h"
+#include "ttkManager.h"
+
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+
+/*------------------------------------------------------------------------
+ * +++ Tab resources.
+ */
+
+#define DEFAULT_MIN_TAB_WIDTH 24
+
+static const char *const TabStateStrings[] = { "normal", "disabled", "hidden", 0 };
+typedef enum {
+ TAB_STATE_NORMAL, TAB_STATE_DISABLED, TAB_STATE_HIDDEN
+} TAB_STATE;
+
+typedef struct
+{
+ /* Internal data:
+ */
+ int width, height; /* Requested size of tab */
+ Ttk_Box parcel; /* Tab position */
+
+ /* Tab options:
+ */
+ TAB_STATE state;
+
+ /* Child window options:
+ */
+ Tcl_Obj *paddingObj; /* Padding inside pane */
+ Ttk_Padding padding;
+ Tcl_Obj *stickyObj;
+ Ttk_Sticky sticky;
+
+ /* Label options:
+ */
+ Tcl_Obj *textObj;
+ Tcl_Obj *imageObj;
+ Tcl_Obj *compoundObj;
+ Tcl_Obj *underlineObj;
+
+} Tab;
+
+/* Two different option tables are used for tabs:
+ * TabOptionSpecs is used to draw the tab, and only includes resources
+ * relevant to the tab.
+ *
+ * PaneOptionSpecs includes additional options for child window placement
+ * and is used to configure the slave.
+ */
+static Tk_OptionSpec TabOptionSpecs[] =
+{
+ {TK_OPTION_STRING_TABLE, "-state", "", "",
+ "normal", -1,Tk_Offset(Tab,state),
+ 0,(ClientData)TabStateStrings,0 },
+ {TK_OPTION_STRING, "-text", "text", "Text", "",
+ Tk_Offset(Tab,textObj), -1, 0,0,GEOMETRY_CHANGED },
+ {TK_OPTION_STRING, "-image", "image", "Image", NULL/*default*/,
+ Tk_Offset(Tab,imageObj), -1, TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
+ {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound",
+ "none", Tk_Offset(Tab,compoundObj), -1,
+ 0,(ClientData)ttkCompoundStrings,GEOMETRY_CHANGED },
+ {TK_OPTION_INT, "-underline", "underline", "Underline", "-1",
+ Tk_Offset(Tab,underlineObj), -1, 0,0,GEOMETRY_CHANGED },
+ {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0 }
+};
+
+static Tk_OptionSpec PaneOptionSpecs[] =
+{
+ {TK_OPTION_STRING, "-padding", "padding", "Padding", "0",
+ Tk_Offset(Tab,paddingObj), -1, 0,0,GEOMETRY_CHANGED },
+ {TK_OPTION_STRING, "-sticky", "sticky", "Sticky", "nsew",
+ Tk_Offset(Tab,stickyObj), -1, 0,0,GEOMETRY_CHANGED },
+
+ WIDGET_INHERIT_OPTIONS(TabOptionSpecs)
+};
+
+/*------------------------------------------------------------------------
+ * +++ Notebook resources.
+ */
+typedef struct
+{
+ Tcl_Obj *widthObj; /* Default width */
+ Tcl_Obj *heightObj; /* Default height */
+ Tcl_Obj *paddingObj; /* Padding around notebook */
+
+ Ttk_Manager *mgr; /* Geometry manager */
+ Tk_OptionTable tabOptionTable; /* Tab options */
+ Tk_OptionTable paneOptionTable; /* Tab+pane options */
+ int currentIndex; /* index of currently selected tab */
+ int activeIndex; /* index of currently active tab */
+ Ttk_Layout tabLayout; /* Sublayout for tabs */
+
+ Ttk_Box clientArea; /* Where to pack slave widgets */
+} NotebookPart;
+
+typedef struct
+{
+ WidgetCore core;
+ NotebookPart notebook;
+} Notebook;
+
+static Tk_OptionSpec NotebookOptionSpecs[] =
+{
+ {TK_OPTION_INT, "-width", "width", "Width", "0",
+ Tk_Offset(Notebook,notebook.widthObj),-1,
+ 0,0,GEOMETRY_CHANGED },
+ {TK_OPTION_INT, "-height", "height", "Height", "0",
+ Tk_Offset(Notebook,notebook.heightObj),-1,
+ 0,0,GEOMETRY_CHANGED },
+ {TK_OPTION_STRING, "-padding", "padding", "Padding", NULL,
+ Tk_Offset(Notebook,notebook.paddingObj),-1,
+ TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
+
+ WIDGET_TAKEFOCUS_TRUE,
+ WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)
+};
+
+/* Notebook style options:
+ */
+typedef struct
+{
+ Ttk_PositionSpec tabPosition; /* Where to place tabs */
+ Ttk_Padding tabMargins; /* Margins around tab row */
+ Ttk_PositionSpec tabPlacement; /* How to pack tabs within tab row */
+ Ttk_Orient tabOrient; /* ... */
+ int minTabWidth; /* Minimum tab width */
+ Ttk_Padding padding; /* External padding */
+} NotebookStyle;
+
+static void NotebookStyleOptions(Notebook *nb, NotebookStyle *nbstyle)
+{
+ Tcl_Obj *objPtr;
+
+ nbstyle->tabPosition = TTK_PACK_TOP | TTK_STICK_W;
+ if ((objPtr = Ttk_QueryOption(nb->core.layout, "-tabposition", 0)) != 0) {
+ TtkGetLabelAnchorFromObj(NULL, objPtr, &nbstyle->tabPosition);
+ }
+
+ /* Guess default tabPlacement as function of tabPosition:
+ */
+ if (nbstyle->tabPosition & TTK_PACK_LEFT) {
+ nbstyle->tabPlacement = TTK_PACK_TOP | TTK_STICK_E;
+ } else if (nbstyle->tabPosition & TTK_PACK_RIGHT) {
+ nbstyle->tabPlacement = TTK_PACK_TOP | TTK_STICK_W;
+ } else if (nbstyle->tabPosition & TTK_PACK_BOTTOM) {
+ nbstyle->tabPlacement = TTK_PACK_LEFT | TTK_STICK_N;
+ } else { /* Assume TTK_PACK_TOP */
+ nbstyle->tabPlacement = TTK_PACK_LEFT | TTK_STICK_S;
+ }
+ if ((objPtr = Ttk_QueryOption(nb->core.layout, "-tabplacement", 0)) != 0) {
+ TtkGetLabelAnchorFromObj(NULL, objPtr, &nbstyle->tabPlacement);
+ }
+
+ /* Compute tabOrient as function of tabPlacement:
+ */
+ if (nbstyle->tabPlacement & (TTK_PACK_LEFT|TTK_PACK_RIGHT)) {
+ nbstyle->tabOrient = TTK_ORIENT_HORIZONTAL;
+ } else {
+ nbstyle->tabOrient = TTK_ORIENT_VERTICAL;
+ }
+
+ nbstyle->tabMargins = Ttk_UniformPadding(0);
+ if ((objPtr = Ttk_QueryOption(nb->core.layout, "-tabmargins", 0)) != 0) {
+ Ttk_GetBorderFromObj(NULL, objPtr, &nbstyle->tabMargins);
+ }
+
+ nbstyle->padding = Ttk_UniformPadding(0);
+ if ((objPtr = Ttk_QueryOption(nb->core.layout, "-padding", 0)) != 0) {
+ Ttk_GetPaddingFromObj(NULL,nb->core.tkwin,objPtr,&nbstyle->padding);
+ }
+
+ nbstyle->minTabWidth = DEFAULT_MIN_TAB_WIDTH;
+ if ((objPtr = Ttk_QueryOption(nb->core.layout, "-mintabwidth", 0)) != 0) {
+ Tcl_GetIntFromObj(NULL, objPtr, &nbstyle->minTabWidth);
+ }
+}
+
+/*------------------------------------------------------------------------
+ * +++ Tab management.
+ */
+
+static Tab *CreateTab(Tcl_Interp *interp, Notebook *nb, Tk_Window slaveWindow)
+{
+ Tk_OptionTable optionTable = nb->notebook.paneOptionTable;
+ void *record = ckalloc(sizeof(Tab));
+ memset(record, 0, sizeof(Tab));
+
+ if (Tk_InitOptions(interp, record, optionTable, slaveWindow) != TCL_OK) {
+ ckfree(record);
+ return NULL;
+ }
+
+ return record;
+}
+
+static void DestroyTab(Notebook *nb, Tab *tab)
+{
+ void *record = tab;
+ Tk_FreeConfigOptions(record, nb->notebook.paneOptionTable, nb->core.tkwin);
+ ckfree(record);
+}
+
+static int ConfigureTab(
+ Tcl_Interp *interp, Notebook *nb, Tab *tab, Tk_Window slaveWindow,
+ int objc, Tcl_Obj *const objv[])
+{
+ Ttk_Sticky sticky = tab->sticky;
+ Ttk_Padding padding = tab->padding;
+ Tk_SavedOptions savedOptions;
+ int mask = 0;
+
+ if (Tk_SetOptions(interp, (ClientData)tab, nb->notebook.paneOptionTable,
+ objc, objv, slaveWindow, &savedOptions, &mask) != TCL_OK)
+ {
+ return TCL_ERROR;
+ }
+
+ /* Check options:
+ * @@@ TODO: validate -image option.
+ */
+ if (Ttk_GetStickyFromObj(interp, tab->stickyObj, &sticky) != TCL_OK)
+ {
+ goto error;
+ }
+ if (Ttk_GetPaddingFromObj(interp, slaveWindow, tab->paddingObj, &padding)
+ != TCL_OK)
+ {
+ goto error;
+ }
+
+ tab->sticky = sticky;
+ tab->padding = padding;
+
+ Tk_FreeSavedOptions(&savedOptions);
+ Ttk_ManagerSizeChanged(nb->notebook.mgr);
+ TtkRedisplayWidget(&nb->core);
+
+ return TCL_OK;
+error:
+ Tk_RestoreSavedOptions(&savedOptions);
+ return TCL_ERROR;
+}
+
+/*
+ * IdentifyTab --
+ * Return the index of the tab at point x,y,
+ * or -1 if no tab at that point.
+ */
+static int IdentifyTab(Notebook *nb, int x, int y)
+{
+ int index;
+ for (index = 0; index < Ttk_NumberSlaves(nb->notebook.mgr); ++index) {
+ Tab *tab = Ttk_SlaveData(nb->notebook.mgr,index);
+ if ( tab->state != TAB_STATE_HIDDEN
+ && Ttk_BoxContains(tab->parcel, x,y))
+ {
+ return index;
+ }
+ }
+ return -1;
+}
+
+/*
+ * ActivateTab --
+ * Set the active tab index, redisplay if necessary.
+ */
+static void ActivateTab(Notebook *nb, int index)
+{
+ if (index != nb->notebook.activeIndex) {
+ nb->notebook.activeIndex = index;
+ TtkRedisplayWidget(&nb->core);
+ }
+}
+
+/*
+ * TabState --
+ * Return the state of the specified tab, based on
+ * notebook state, currentIndex, activeIndex, and user-specified tab state.
+ * The USER1 bit is set for the leftmost visible tab, and USER2
+ * is set for the rightmost visible tab.
+ */
+static Ttk_State TabState(Notebook *nb, int index)
+{
+ Ttk_State state = nb->core.state;
+ Tab *tab = Ttk_SlaveData(nb->notebook.mgr, index);
+ int i = 0;
+
+ if (index == nb->notebook.currentIndex) {
+ state |= TTK_STATE_SELECTED;
+ } else {
+ state &= ~TTK_STATE_FOCUS;
+ }
+
+ if (index == nb->notebook.activeIndex) {
+ state |= TTK_STATE_ACTIVE;
+ }
+ for (i = 0; i < Ttk_NumberSlaves(nb->notebook.mgr); ++i) {
+ Tab *tab = Ttk_SlaveData(nb->notebook.mgr, i);
+ if (tab->state == TAB_STATE_HIDDEN) {
+ continue;
+ }
+ if (index == i) {
+ state |= TTK_STATE_USER1;
+ }
+ break;
+ }
+ for (i = Ttk_NumberSlaves(nb->notebook.mgr) - 1; i >= 0; --i) {
+ Tab *tab = Ttk_SlaveData(nb->notebook.mgr, i);
+ if (tab->state == TAB_STATE_HIDDEN) {
+ continue;
+ }
+ if (index == i) {
+ state |= TTK_STATE_USER2;
+ }
+ break;
+ }
+ if (tab->state == TAB_STATE_DISABLED) {
+ state |= TTK_STATE_DISABLED;
+ }
+
+ return state;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Geometry management - size computation.
+ */
+
+/* TabrowSize --
+ * Compute max height and total width of all tabs (horizontal layouts)
+ * or total height and max width (vertical layouts).
+ * The -mintabwidth style option is taken into account (for the width
+ * only).
+ *
+ * Side effects:
+ * Sets width and height fields for all tabs.
+ *
+ * Notes:
+ * Hidden tabs are included in the perpendicular computation
+ * (max height/width) but not parallel (total width/height).
+ */
+static void TabrowSize(
+ Notebook *nb, Ttk_Orient orient, int minTabWidth, int *widthPtr, int *heightPtr)
+{
+ Ttk_Layout tabLayout = nb->notebook.tabLayout;
+ int tabrowWidth = 0, tabrowHeight = 0;
+ int i;
+
+ for (i = 0; i < Ttk_NumberSlaves(nb->notebook.mgr); ++i) {
+ Tab *tab = Ttk_SlaveData(nb->notebook.mgr, i);
+ Ttk_State tabState = TabState(nb,i);
+
+ Ttk_RebindSublayout(tabLayout, tab);
+ Ttk_LayoutSize(tabLayout,tabState,&tab->width,&tab->height);
+ tab->width = MAX(tab->width, minTabWidth);
+
+ if (orient == TTK_ORIENT_HORIZONTAL) {
+ tabrowHeight = MAX(tabrowHeight, tab->height);
+ if (tab->state != TAB_STATE_HIDDEN) { tabrowWidth += tab->width; }
+ } else {
+ tabrowWidth = MAX(tabrowWidth, tab->width);
+ if (tab->state != TAB_STATE_HIDDEN) { tabrowHeight += tab->height; }
+ }
+ }
+
+ *widthPtr = tabrowWidth;
+ *heightPtr = tabrowHeight;
+}
+
+/* NotebookSize -- GM and widget size hook.
+ *
+ * Total height is tab height + client area height + pane internal padding
+ * Total width is max(client width, tab width) + pane internal padding
+ * Client area size determined by max size of slaves,
+ * overridden by -width and/or -height if nonzero.
+ */
+
+static int NotebookSize(void *clientData, int *widthPtr, int *heightPtr)
+{
+ Notebook *nb = clientData;
+ NotebookStyle nbstyle;
+ Ttk_Padding padding;
+ Ttk_Element clientNode = Ttk_FindElement(nb->core.layout, "client");
+ int clientWidth = 0, clientHeight = 0,
+ reqWidth = 0, reqHeight = 0,
+ tabrowWidth = 0, tabrowHeight = 0;
+ int i;
+
+ NotebookStyleOptions(nb, &nbstyle);
+
+ /* Compute max requested size of all slaves:
+ */
+ for (i = 0; i < Ttk_NumberSlaves(nb->notebook.mgr); ++i) {
+ Tk_Window slaveWindow = Ttk_SlaveWindow(nb->notebook.mgr, i);
+ Tab *tab = Ttk_SlaveData(nb->notebook.mgr, i);
+ int slaveWidth
+ = Tk_ReqWidth(slaveWindow) + Ttk_PaddingWidth(tab->padding);
+ int slaveHeight
+ = Tk_ReqHeight(slaveWindow) + Ttk_PaddingHeight(tab->padding);
+
+ clientWidth = MAX(clientWidth, slaveWidth);
+ clientHeight = MAX(clientHeight, slaveHeight);
+ }
+
+ /* Client width/height overridable by widget options:
+ */
+ Tcl_GetIntFromObj(NULL, nb->notebook.widthObj,&reqWidth);
+ Tcl_GetIntFromObj(NULL, nb->notebook.heightObj,&reqHeight);
+ if (reqWidth > 0)
+ clientWidth = reqWidth;
+ if (reqHeight > 0)
+ clientHeight = reqHeight;
+
+ /* Tab row:
+ */
+ TabrowSize(nb, nbstyle.tabOrient, nbstyle.minTabWidth, &tabrowWidth, &tabrowHeight);
+ tabrowHeight += Ttk_PaddingHeight(nbstyle.tabMargins);
+ tabrowWidth += Ttk_PaddingWidth(nbstyle.tabMargins);
+
+ /* Account for exterior and interior padding:
+ */
+ padding = nbstyle.padding;
+ if (clientNode) {
+ Ttk_Padding ipad =
+ Ttk_LayoutNodeInternalPadding(nb->core.layout, clientNode);
+ padding = Ttk_AddPadding(padding, ipad);
+ }
+
+ if (nbstyle.tabPosition & (TTK_PACK_TOP|TTK_PACK_BOTTOM)) {
+ *widthPtr = MAX(tabrowWidth, clientWidth) + Ttk_PaddingWidth(padding);
+ *heightPtr = tabrowHeight + clientHeight + Ttk_PaddingHeight(padding);
+ } else {
+ *widthPtr = tabrowWidth + clientWidth + Ttk_PaddingWidth(padding);
+ *heightPtr = MAX(tabrowHeight,clientHeight) + Ttk_PaddingHeight(padding);
+ }
+
+ return 1;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Geometry management - layout.
+ */
+
+/* SqueezeTabs --
+ * Squeeze or stretch tabs to fit within the tab area parcel.
+ * This happens independently of the -mintabwidth style option.
+ *
+ * All tabs are adjusted by an equal amount.
+ *
+ * @@@ <<NOTE-TABPOSITION>> bug: only works for horizontal orientations
+ * @@@ <<NOTE-SQUEEZE-HIDDEN>> does not account for hidden tabs.
+ */
+
+static void SqueezeTabs(
+ Notebook *nb, int needed, int available)
+{
+ int nTabs = Ttk_NumberSlaves(nb->notebook.mgr);
+
+ if (nTabs > 0) {
+ int difference = available - needed;
+ double delta = (double)difference / needed;
+ double slack = 0;
+ int i;
+
+ for (i = 0; i < nTabs; ++i) {
+ Tab *tab = Ttk_SlaveData(nb->notebook.mgr,i);
+ double ad = slack + tab->width * delta;
+ tab->width += (int)ad;
+ slack = ad - (int)ad;
+ }
+ }
+}
+
+/* PlaceTabs --
+ * Compute all tab parcels.
+ */
+static void PlaceTabs(
+ Notebook *nb, Ttk_Box tabrowBox, Ttk_PositionSpec tabPlacement)
+{
+ Ttk_Layout tabLayout = nb->notebook.tabLayout;
+ int nTabs = Ttk_NumberSlaves(nb->notebook.mgr);
+ int i;
+
+ for (i = 0; i < nTabs; ++i) {
+ Tab *tab = Ttk_SlaveData(nb->notebook.mgr, i);
+ Ttk_State tabState = TabState(nb, i);
+
+ if (tab->state != TAB_STATE_HIDDEN) {
+ Ttk_Padding expand = Ttk_UniformPadding(0);
+ Tcl_Obj *expandObj = Ttk_QueryOption(tabLayout,"-expand",tabState);
+
+ if (expandObj) {
+ Ttk_GetBorderFromObj(NULL, expandObj, &expand);
+ }
+
+ tab->parcel =
+ Ttk_ExpandBox(
+ Ttk_PositionBox(&tabrowBox,
+ tab->width, tab->height, tabPlacement),
+ expand);
+ }
+ }
+}
+
+/* NotebookDoLayout --
+ * Computes notebook layout and places tabs.
+ *
+ * Side effects:
+ * Sets clientArea, used to place slave panes.
+ */
+static void NotebookDoLayout(void *recordPtr)
+{
+ Notebook *nb = recordPtr;
+ Tk_Window nbwin = nb->core.tkwin;
+ Ttk_Box cavity = Ttk_WinBox(nbwin);
+ int tabrowWidth = 0, tabrowHeight = 0;
+ Ttk_Element clientNode = Ttk_FindElement(nb->core.layout, "client");
+ Ttk_Box tabrowBox;
+ NotebookStyle nbstyle;
+
+ NotebookStyleOptions(nb, &nbstyle);
+
+ /* Notebook internal padding:
+ */
+ cavity = Ttk_PadBox(cavity, nbstyle.padding);
+
+ /* Layout for notebook background (base layout):
+ */
+ Ttk_PlaceLayout(nb->core.layout, nb->core.state, Ttk_WinBox(nbwin));
+
+ /* Place tabs:
+ * Note: TabrowSize() takes into account -mintabwidth, but the tabs will
+ * actually have this minimum size when displayed only if there is enough
+ * space to draw the tabs with this width. Otherwise some of the tabs can
+ * be squeezed to a size smaller than -mintabwidth because we prefer
+ * displaying all tabs than than honoring -mintabwidth for all of them.
+ */
+ TabrowSize(nb, nbstyle.tabOrient, nbstyle.minTabWidth, &tabrowWidth, &tabrowHeight);
+ tabrowBox = Ttk_PadBox(
+ Ttk_PositionBox(&cavity,
+ tabrowWidth + Ttk_PaddingWidth(nbstyle.tabMargins),
+ tabrowHeight + Ttk_PaddingHeight(nbstyle.tabMargins),
+ nbstyle.tabPosition),
+ nbstyle.tabMargins);
+
+ SqueezeTabs(nb, tabrowWidth, tabrowBox.width);
+ PlaceTabs(nb, tabrowBox, nbstyle.tabPlacement);
+
+ /* Layout for client area frame:
+ */
+ if (clientNode) {
+ Ttk_PlaceElement(nb->core.layout, clientNode, cavity);
+ cavity = Ttk_LayoutNodeInternalParcel(nb->core.layout, clientNode);
+ }
+
+ if (cavity.height <= 0) cavity.height = 1;
+ if (cavity.width <= 0) cavity.width = 1;
+
+ nb->notebook.clientArea = cavity;
+}
+
+/*
+ * NotebookPlaceSlave --
+ * Set the position and size of a child widget
+ * based on the current client area and slave options:
+ */
+static void NotebookPlaceSlave(Notebook *nb, int slaveIndex)
+{
+ Tab *tab = Ttk_SlaveData(nb->notebook.mgr, slaveIndex);
+ Tk_Window slaveWindow = Ttk_SlaveWindow(nb->notebook.mgr, slaveIndex);
+ Ttk_Box slaveBox =
+ Ttk_StickBox(Ttk_PadBox(nb->notebook.clientArea, tab->padding),
+ Tk_ReqWidth(slaveWindow), Tk_ReqHeight(slaveWindow),tab->sticky);
+
+ Ttk_PlaceSlave(nb->notebook.mgr, slaveIndex,
+ slaveBox.x, slaveBox.y, slaveBox.width, slaveBox.height);
+}
+
+/* NotebookPlaceSlaves --
+ * Geometry manager hook.
+ */
+static void NotebookPlaceSlaves(void *recordPtr)
+{
+ Notebook *nb = recordPtr;
+ int currentIndex = nb->notebook.currentIndex;
+ if (currentIndex >= 0) {
+ NotebookDoLayout(nb);
+ NotebookPlaceSlave(nb, currentIndex);
+ }
+}
+
+/*
+ * SelectTab(nb, index) --
+ * Change the currently-selected tab.
+ */
+static void SelectTab(Notebook *nb, int index)
+{
+ Tab *tab = Ttk_SlaveData(nb->notebook.mgr,index);
+ int currentIndex = nb->notebook.currentIndex;
+
+ if (index == currentIndex) {
+ return;
+ }
+
+ if (TabState(nb, index) & TTK_STATE_DISABLED) {
+ return;
+ }
+
+ /* Unhide the tab if it is currently hidden and being selected.
+ */
+ if (tab->state == TAB_STATE_HIDDEN) {
+ tab->state = TAB_STATE_NORMAL;
+ }
+
+ if (currentIndex >= 0) {
+ Ttk_UnmapSlave(nb->notebook.mgr, currentIndex);
+ }
+
+ /* Must be set before calling NotebookPlaceSlave(), otherwise it may
+ * happen that NotebookPlaceSlaves(), triggered by an interveaning
+ * geometry request, will swap to old index. */
+ nb->notebook.currentIndex = index;
+
+ NotebookPlaceSlave(nb, index);
+ TtkRedisplayWidget(&nb->core);
+
+ TtkSendVirtualEvent(nb->core.tkwin, "NotebookTabChanged");
+}
+
+/* NextTab --
+ * Returns the index of the next tab after the specified tab
+ * in the normal state (e.g., not hidden or disabled),
+ * or -1 if all tabs are disabled or hidden.
+ */
+static int NextTab(Notebook *nb, int index)
+{
+ int nTabs = Ttk_NumberSlaves(nb->notebook.mgr);
+ int nextIndex;
+
+ /* Scan forward for following usable tab:
+ */
+ for (nextIndex = index + 1; nextIndex < nTabs; ++nextIndex) {
+ Tab *tab = Ttk_SlaveData(nb->notebook.mgr, nextIndex);
+ if (tab->state == TAB_STATE_NORMAL) {
+ return nextIndex;
+ }
+ }
+
+ /* Not found -- scan backwards.
+ */
+ for (nextIndex = index - 1; nextIndex >= 0; --nextIndex) {
+ Tab *tab = Ttk_SlaveData(nb->notebook.mgr, nextIndex);
+ if (tab->state == TAB_STATE_NORMAL) {
+ return nextIndex;
+ }
+ }
+
+ /* Still nothing. Give up.
+ */
+ return -1;
+}
+
+/* SelectNearestTab --
+ * Handles the case where the current tab is forgotten, hidden,
+ * or destroyed.
+ *
+ * Unmap the current tab and schedule the next available one
+ * to be mapped at the next GM update.
+ */
+static void SelectNearestTab(Notebook *nb)
+{
+ int currentIndex = nb->notebook.currentIndex;
+ int nextIndex = NextTab(nb, currentIndex);
+
+ if (currentIndex >= 0) {
+ Ttk_UnmapSlave(nb->notebook.mgr, currentIndex);
+ }
+ if (currentIndex != nextIndex) {
+ TtkSendVirtualEvent(nb->core.tkwin, "NotebookTabChanged");
+ }
+
+ nb->notebook.currentIndex = nextIndex;
+ Ttk_ManagerLayoutChanged(nb->notebook.mgr);
+ TtkRedisplayWidget(&nb->core);
+}
+
+/* TabRemoved -- GM SlaveRemoved hook.
+ * Select the next tab if the current one is being removed.
+ * Adjust currentIndex to account for removed slave.
+ */
+static void TabRemoved(void *managerData, int index)
+{
+ Notebook *nb = managerData;
+ Tab *tab = Ttk_SlaveData(nb->notebook.mgr, index);
+
+ if (index == nb->notebook.currentIndex) {
+ SelectNearestTab(nb);
+ }
+
+ if (index < nb->notebook.currentIndex) {
+ --nb->notebook.currentIndex;
+ }
+
+ DestroyTab(nb, tab);
+
+ TtkRedisplayWidget(&nb->core);
+}
+
+static int TabRequest(void *managerData, int index, int width, int height)
+{
+ return 1;
+}
+
+/* AddTab --
+ * Add new tab at specified index.
+ */
+static int AddTab(
+ Tcl_Interp *interp, Notebook *nb,
+ int destIndex, Tk_Window slaveWindow,
+ int objc, Tcl_Obj *const objv[])
+{
+ Tab *tab;
+ if (!Ttk_Maintainable(interp, slaveWindow, nb->core.tkwin)) {
+ return TCL_ERROR;
+ }
+#if 0 /* can't happen */
+ if (Ttk_SlaveIndex(nb->notebook.mgr, slaveWindow) >= 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf("%s already added",
+ Tk_PathName(slaveWindow)));
+ Tcl_SetErrorCode(interp, "TTK", "NOTEBOOK", "PRESENT", NULL);
+ return TCL_ERROR;
+ }
+#endif
+
+ /* Create and insert tab.
+ */
+ tab = CreateTab(interp, nb, slaveWindow);
+ if (!tab) {
+ return TCL_ERROR;
+ }
+ if (ConfigureTab(interp, nb, tab, slaveWindow, objc, objv) != TCL_OK) {
+ DestroyTab(nb, tab);
+ return TCL_ERROR;
+ }
+
+ Ttk_InsertSlave(nb->notebook.mgr, destIndex, slaveWindow, tab);
+
+ /* Adjust indices and/or autoselect first tab:
+ */
+ if (nb->notebook.currentIndex < 0) {
+ SelectTab(nb, destIndex);
+ } else if (nb->notebook.currentIndex >= destIndex) {
+ ++nb->notebook.currentIndex;
+ }
+
+ return TCL_OK;
+}
+
+static Ttk_ManagerSpec NotebookManagerSpec = {
+ { "notebook", Ttk_GeometryRequestProc, Ttk_LostSlaveProc },
+ NotebookSize,
+ NotebookPlaceSlaves,
+ TabRequest,
+ TabRemoved
+};
+
+/*------------------------------------------------------------------------
+ * +++ Event handlers.
+ */
+
+/* NotebookEventHandler --
+ * Tracks the active tab.
+ */
+static const int NotebookEventMask
+ = StructureNotifyMask
+ | PointerMotionMask
+ | LeaveWindowMask
+ ;
+static void NotebookEventHandler(ClientData clientData, XEvent *eventPtr)
+{
+ Notebook *nb = clientData;
+
+ if (eventPtr->type == DestroyNotify) { /* Remove self */
+ Tk_DeleteEventHandler(nb->core.tkwin,
+ NotebookEventMask, NotebookEventHandler, clientData);
+ } else if (eventPtr->type == MotionNotify) {
+ int index = IdentifyTab(nb, eventPtr->xmotion.x, eventPtr->xmotion.y);
+ ActivateTab(nb, index);
+ } else if (eventPtr->type == LeaveNotify) {
+ ActivateTab(nb, -1);
+ }
+}
+
+/*------------------------------------------------------------------------
+ * +++ Utilities.
+ */
+
+/* FindTabIndex --
+ * Find the index of the specified tab.
+ * Tab identifiers are one of:
+ *
+ * + positional specifications @x,y,
+ * + "current",
+ * + numeric indices [0..nTabs],
+ * + slave window names
+ *
+ * Stores index of specified tab in *index_rtn, -1 if not found.
+ *
+ * Returns TCL_ERROR and leaves an error message in interp->result
+ * if the tab identifier was incorrect.
+ *
+ * See also: GetTabIndex.
+ */
+static int FindTabIndex(
+ Tcl_Interp *interp, Notebook *nb, Tcl_Obj *objPtr, int *index_rtn)
+{
+ const char *string = Tcl_GetString(objPtr);
+ int x, y;
+
+ *index_rtn = -1;
+
+ /* Check for @x,y ...
+ */
+ if (string[0] == '@' && sscanf(string, "@%d,%d",&x,&y) == 2) {
+ *index_rtn = IdentifyTab(nb, x, y);
+ return TCL_OK;
+ }
+
+ /* ... or "current" ...
+ */
+ if (!strcmp(string, "current")) {
+ *index_rtn = nb->notebook.currentIndex;
+ return TCL_OK;
+ }
+
+ /* ... or integer index or slave window name:
+ */
+ if (Ttk_GetSlaveIndexFromObj(
+ interp, nb->notebook.mgr, objPtr, index_rtn) == TCL_OK)
+ {
+ return TCL_OK;
+ }
+
+ /* Nothing matched; Ttk_GetSlaveIndexFromObj will have left error message.
+ */
+ return TCL_ERROR;
+}
+
+/* GetTabIndex --
+ * Get the index of an existing tab.
+ * Tab identifiers are as per FindTabIndex.
+ * Returns TCL_ERROR if the tab does not exist.
+ */
+static int GetTabIndex(
+ Tcl_Interp *interp, Notebook *nb, Tcl_Obj *objPtr, int *index_rtn)
+{
+ int status = FindTabIndex(interp, nb, objPtr, index_rtn);
+
+ if (status == TCL_OK && *index_rtn < 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "tab '%s' not found", Tcl_GetString(objPtr)));
+ Tcl_SetErrorCode(interp, "TTK", "NOTEBOOK", "TAB", NULL);
+ status = TCL_ERROR;
+ }
+ return status;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Widget command routines.
+ */
+
+/* $nb add window ?options ... ?
+ */
+static int NotebookAddCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Notebook *nb = recordPtr;
+ int index = Ttk_NumberSlaves(nb->notebook.mgr);
+ Tk_Window slaveWindow;
+ int slaveIndex;
+ Tab *tab;
+
+ if (objc <= 2 || objc % 2 != 1) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?-option value ...?");
+ return TCL_ERROR;
+ }
+
+ slaveWindow = Tk_NameToWindow(interp,Tcl_GetString(objv[2]),nb->core.tkwin);
+ if (!slaveWindow) {
+ return TCL_ERROR;
+ }
+ slaveIndex = Ttk_SlaveIndex(nb->notebook.mgr, slaveWindow);
+
+ if (slaveIndex < 0) { /* New tab */
+ return AddTab(interp, nb, index, slaveWindow, objc-3,objv+3);
+ }
+
+ tab = Ttk_SlaveData(nb->notebook.mgr, slaveIndex);
+ if (tab->state == TAB_STATE_HIDDEN) {
+ tab->state = TAB_STATE_NORMAL;
+ }
+ if (ConfigureTab(interp, nb, tab, slaveWindow, objc-3,objv+3) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ TtkRedisplayWidget(&nb->core);
+
+ return TCL_OK;
+}
+
+/* $nb insert $index $tab ?-option value ...?
+ * Insert new tab, or move existing one.
+ */
+static int NotebookInsertCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Notebook *nb = recordPtr;
+ int current = nb->notebook.currentIndex;
+ int nSlaves = Ttk_NumberSlaves(nb->notebook.mgr);
+ int srcIndex, destIndex;
+
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 2,objv, "index slave ?-option value ...?");
+ return TCL_ERROR;
+ }
+
+ if (!strcmp(Tcl_GetString(objv[2]), "end")) {
+ destIndex = Ttk_NumberSlaves(nb->notebook.mgr);
+ } else if (TCL_OK != Ttk_GetSlaveIndexFromObj(
+ interp, nb->notebook.mgr, objv[2], &destIndex)) {
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetString(objv[3])[0] == '.') {
+ /* Window name -- could be new or existing slave.
+ */
+ Tk_Window slaveWindow =
+ Tk_NameToWindow(interp,Tcl_GetString(objv[3]),nb->core.tkwin);
+
+ if (!slaveWindow) {
+ return TCL_ERROR;
+ }
+
+ srcIndex = Ttk_SlaveIndex(nb->notebook.mgr, slaveWindow);
+ if (srcIndex < 0) { /* New slave */
+ return AddTab(interp, nb, destIndex, slaveWindow, objc-4,objv+4);
+ }
+ } else if (Ttk_GetSlaveIndexFromObj(
+ interp, nb->notebook.mgr, objv[3], &srcIndex) != TCL_OK)
+ {
+ return TCL_ERROR;
+ }
+
+ /* Move existing slave:
+ */
+ if (ConfigureTab(interp, nb,
+ Ttk_SlaveData(nb->notebook.mgr,srcIndex),
+ Ttk_SlaveWindow(nb->notebook.mgr,srcIndex),
+ objc-4,objv+4) != TCL_OK)
+ {
+ return TCL_ERROR;
+ }
+
+ if (destIndex >= nSlaves) {
+ destIndex = nSlaves - 1;
+ }
+ Ttk_ReorderSlave(nb->notebook.mgr, srcIndex, destIndex);
+
+ /* Adjust internal indexes:
+ */
+ nb->notebook.activeIndex = -1;
+ if (current == srcIndex) {
+ nb->notebook.currentIndex = destIndex;
+ } else if (destIndex <= current && current < srcIndex) {
+ ++nb->notebook.currentIndex;
+ } else if (srcIndex < current && current <= destIndex) {
+ --nb->notebook.currentIndex;
+ }
+
+ TtkRedisplayWidget(&nb->core);
+
+ return TCL_OK;
+}
+
+/* $nb forget $tab --
+ * Removes the specified tab.
+ */
+static int NotebookForgetCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Notebook *nb = recordPtr;
+ int index;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "tab");
+ return TCL_ERROR;
+ }
+
+ if (GetTabIndex(interp, nb, objv[2], &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ Ttk_ForgetSlave(nb->notebook.mgr, index);
+ TtkRedisplayWidget(&nb->core);
+
+ return TCL_OK;
+}
+
+/* $nb hide $tab --
+ * Hides the specified tab.
+ */
+static int NotebookHideCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Notebook *nb = recordPtr;
+ int index;
+ Tab *tab;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "tab");
+ return TCL_ERROR;
+ }
+
+ if (GetTabIndex(interp, nb, objv[2], &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ tab = Ttk_SlaveData(nb->notebook.mgr, index);
+ tab->state = TAB_STATE_HIDDEN;
+ if (index == nb->notebook.currentIndex) {
+ SelectNearestTab(nb);
+ }
+
+ TtkRedisplayWidget(&nb->core);
+
+ return TCL_OK;
+}
+
+/* $nb identify $x $y --
+ * Returns name of tab element at $x,$y; empty string if none.
+ */
+static int NotebookIdentifyCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ static const char *whatTable[] = { "element", "tab", NULL };
+ enum { IDENTIFY_ELEMENT, IDENTIFY_TAB };
+ int what = IDENTIFY_ELEMENT;
+ Notebook *nb = recordPtr;
+ Ttk_Element element = NULL;
+ int x, y, tabIndex;
+
+ if (objc < 4 || objc > 5) {
+ Tcl_WrongNumArgs(interp, 2,objv, "?what? x y");
+ return TCL_ERROR;
+ }
+
+ if ( Tcl_GetIntFromObj(interp, objv[objc-2], &x) != TCL_OK
+ || Tcl_GetIntFromObj(interp, objv[objc-1], &y) != TCL_OK
+ || (objc == 5 && Tcl_GetIndexFromObjStruct(interp, objv[2], whatTable,
+ sizeof(char *), "option", 0, &what) != TCL_OK)
+ ) {
+ return TCL_ERROR;
+ }
+
+ tabIndex = IdentifyTab(nb, x, y);
+ if (tabIndex >= 0) {
+ Tab *tab = Ttk_SlaveData(nb->notebook.mgr, tabIndex);
+ Ttk_State state = TabState(nb, tabIndex);
+ Ttk_Layout tabLayout = nb->notebook.tabLayout;
+
+ Ttk_RebindSublayout(tabLayout, tab);
+ Ttk_PlaceLayout(tabLayout, state, tab->parcel);
+
+ element = Ttk_IdentifyElement(tabLayout, x, y);
+ }
+
+ switch (what) {
+ case IDENTIFY_ELEMENT:
+ if (element) {
+ const char *elementName = Ttk_ElementName(element);
+
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(elementName, -1));
+ }
+ break;
+ case IDENTIFY_TAB:
+ if (tabIndex >= 0) {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(tabIndex));
+ }
+ break;
+ }
+ return TCL_OK;
+}
+
+/* $nb index $item --
+ * Returns the integer index of the tab specified by $item,
+ * the empty string if $item does not identify a tab.
+ * See above for valid item formats.
+ */
+static int NotebookIndexCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Notebook *nb = recordPtr;
+ int index, status;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "tab");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Special-case for "end":
+ */
+ if (!strcmp("end", Tcl_GetString(objv[2]))) {
+ int nSlaves = Ttk_NumberSlaves(nb->notebook.mgr);
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(nSlaves));
+ return TCL_OK;
+ }
+
+ status = FindTabIndex(interp, nb, objv[2], &index);
+ if (status == TCL_OK && index >= 0) {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(index));
+ }
+
+ return status;
+}
+
+/* $nb select ?$item? --
+ * Select the specified tab, or return the widget path of
+ * the currently-selected pane.
+ */
+static int NotebookSelectCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Notebook *nb = recordPtr;
+
+ if (objc == 2) {
+ if (nb->notebook.currentIndex >= 0) {
+ Tk_Window pane = Ttk_SlaveWindow(
+ nb->notebook.mgr, nb->notebook.currentIndex);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(Tk_PathName(pane), -1));
+ }
+ return TCL_OK;
+ } else if (objc == 3) {
+ int index, status = GetTabIndex(interp, nb, objv[2], &index);
+ if (status == TCL_OK) {
+ SelectTab(nb, index);
+ }
+ return status;
+ } /*else*/
+ Tcl_WrongNumArgs(interp, 2, objv, "?tab?");
+ return TCL_ERROR;
+}
+
+/* $nb tabs --
+ * Return list of tabs.
+ */
+static int NotebookTabsCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Notebook *nb = recordPtr;
+ Ttk_Manager *mgr = nb->notebook.mgr;
+ Tcl_Obj *result;
+ int i;
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, "");
+ return TCL_ERROR;
+ }
+
+ result = Tcl_NewListObj(0, NULL);
+ for (i = 0; i < Ttk_NumberSlaves(mgr); ++i) {
+ const char *pathName = Tk_PathName(Ttk_SlaveWindow(mgr,i));
+
+ Tcl_ListObjAppendElement(NULL, result, Tcl_NewStringObj(pathName,-1));
+ }
+ Tcl_SetObjResult(interp, result);
+ return TCL_OK;
+}
+
+/* $nb tab $tab ?-option ?value -option value...??
+ */
+static int NotebookTabCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Notebook *nb = recordPtr;
+ Ttk_Manager *mgr = nb->notebook.mgr;
+ int index;
+ Tk_Window slaveWindow;
+ Tab *tab;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "tab ?-option ?value??...");
+ return TCL_ERROR;
+ }
+
+ if (GetTabIndex(interp, nb, objv[2], &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ tab = Ttk_SlaveData(mgr, index);
+ slaveWindow = Ttk_SlaveWindow(mgr, index);
+
+ if (objc == 3) {
+ return TtkEnumerateOptions(interp, tab,
+ PaneOptionSpecs, nb->notebook.paneOptionTable, slaveWindow);
+ } else if (objc == 4) {
+ return TtkGetOptionValue(interp, tab, objv[3],
+ nb->notebook.paneOptionTable, slaveWindow);
+ } /* else */
+
+ if (ConfigureTab(interp, nb, tab, slaveWindow, objc-3,objv+3) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /* If the current tab has become disabled or hidden,
+ * select the next nondisabled, unhidden one:
+ */
+ if (index == nb->notebook.currentIndex && tab->state != TAB_STATE_NORMAL) {
+ SelectNearestTab(nb);
+ }
+
+ return TCL_OK;
+}
+
+/* Subcommand table:
+ */
+static const Ttk_Ensemble NotebookCommands[] = {
+ { "add", NotebookAddCommand,0 },
+ { "configure", TtkWidgetConfigureCommand,0 },
+ { "cget", TtkWidgetCgetCommand,0 },
+ { "forget", NotebookForgetCommand,0 },
+ { "hide", NotebookHideCommand,0 },
+ { "identify", NotebookIdentifyCommand,0 },
+ { "index", NotebookIndexCommand,0 },
+ { "insert", NotebookInsertCommand,0 },
+ { "instate", TtkWidgetInstateCommand,0 },
+ { "select", NotebookSelectCommand,0 },
+ { "state", TtkWidgetStateCommand,0 },
+ { "tab", NotebookTabCommand,0 },
+ { "tabs", NotebookTabsCommand,0 },
+ { 0,0,0 }
+};
+
+/*------------------------------------------------------------------------
+ * +++ Widget class hooks.
+ */
+
+static void NotebookInitialize(Tcl_Interp *interp, void *recordPtr)
+{
+ Notebook *nb = recordPtr;
+
+ nb->notebook.mgr = Ttk_CreateManager(
+ &NotebookManagerSpec, recordPtr, nb->core.tkwin);
+
+ nb->notebook.tabOptionTable = Tk_CreateOptionTable(interp,TabOptionSpecs);
+ nb->notebook.paneOptionTable = Tk_CreateOptionTable(interp,PaneOptionSpecs);
+
+ nb->notebook.currentIndex = -1;
+ nb->notebook.activeIndex = -1;
+ nb->notebook.tabLayout = 0;
+
+ nb->notebook.clientArea = Ttk_MakeBox(0,0,1,1);
+
+ Tk_CreateEventHandler(
+ nb->core.tkwin, NotebookEventMask, NotebookEventHandler, recordPtr);
+}
+
+static void NotebookCleanup(void *recordPtr)
+{
+ Notebook *nb = recordPtr;
+
+ Ttk_DeleteManager(nb->notebook.mgr);
+ if (nb->notebook.tabLayout)
+ Ttk_FreeLayout(nb->notebook.tabLayout);
+}
+
+static int NotebookConfigure(Tcl_Interp *interp, void *clientData, int mask)
+{
+ Notebook *nb = clientData;
+
+ /*
+ * Error-checks:
+ */
+ if (nb->notebook.paddingObj) {
+ /* Check for valid -padding: */
+ Ttk_Padding unused;
+ if (Ttk_GetPaddingFromObj(
+ interp, nb->core.tkwin, nb->notebook.paddingObj, &unused)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+
+ return TtkCoreConfigure(interp, clientData, mask);
+}
+
+/* NotebookGetLayout --
+ * GetLayout widget hook.
+ */
+static Ttk_Layout NotebookGetLayout(
+ Tcl_Interp *interp, Ttk_Theme theme, void *recordPtr)
+{
+ Notebook *nb = recordPtr;
+ Ttk_Layout notebookLayout = TtkWidgetGetLayout(interp, theme, recordPtr);
+ Ttk_Layout tabLayout;
+
+ if (!notebookLayout) {
+ return NULL;
+ }
+
+ tabLayout = Ttk_CreateSublayout(
+ interp, theme, notebookLayout, ".Tab", nb->notebook.tabOptionTable);
+
+ if (tabLayout) {
+ if (nb->notebook.tabLayout) {
+ Ttk_FreeLayout(nb->notebook.tabLayout);
+ }
+ nb->notebook.tabLayout = tabLayout;
+ }
+
+ return notebookLayout;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Display routines.
+ */
+
+static void DisplayTab(Notebook *nb, int index, Drawable d)
+{
+ Ttk_Layout tabLayout = nb->notebook.tabLayout;
+ Tab *tab = Ttk_SlaveData(nb->notebook.mgr, index);
+ Ttk_State state = TabState(nb, index);
+
+ if (tab->state != TAB_STATE_HIDDEN) {
+ Ttk_RebindSublayout(tabLayout, tab);
+ Ttk_PlaceLayout(tabLayout, state, tab->parcel);
+ Ttk_DrawLayout(tabLayout, state, d);
+ }
+}
+
+static void NotebookDisplay(void *clientData, Drawable d)
+{
+ Notebook *nb = clientData;
+ int nSlaves = Ttk_NumberSlaves(nb->notebook.mgr);
+ int index;
+
+ /* Draw notebook background (base layout):
+ */
+ Ttk_DrawLayout(nb->core.layout, nb->core.state, d);
+
+ /* Draw tabs from left to right, but draw the current tab last
+ * so it will overwrite its neighbors.
+ */
+ for (index = 0; index < nSlaves; ++index) {
+ if (index != nb->notebook.currentIndex) {
+ DisplayTab(nb, index, d);
+ }
+ }
+ if (nb->notebook.currentIndex >= 0) {
+ DisplayTab(nb, nb->notebook.currentIndex, d);
+ }
+}
+
+/*------------------------------------------------------------------------
+ * +++ Widget specification and layout definitions.
+ */
+
+static WidgetSpec NotebookWidgetSpec =
+{
+ "TNotebook", /* className */
+ sizeof(Notebook), /* recordSize */
+ NotebookOptionSpecs, /* optionSpecs */
+ NotebookCommands, /* subcommands */
+ NotebookInitialize, /* initializeProc */
+ NotebookCleanup, /* cleanupProc */
+ NotebookConfigure, /* configureProc */
+ TtkNullPostConfigure, /* postConfigureProc */
+ NotebookGetLayout, /* getLayoutProc */
+ NotebookSize, /* geometryProc */
+ NotebookDoLayout, /* layoutProc */
+ NotebookDisplay /* displayProc */
+};
+
+TTK_BEGIN_LAYOUT(NotebookLayout)
+ TTK_NODE("Notebook.client", TTK_FILL_BOTH)
+TTK_END_LAYOUT
+
+TTK_BEGIN_LAYOUT(TabLayout)
+ TTK_GROUP("Notebook.tab", TTK_FILL_BOTH,
+ TTK_GROUP("Notebook.padding", TTK_PACK_TOP|TTK_FILL_BOTH,
+ TTK_GROUP("Notebook.focus", TTK_PACK_TOP|TTK_FILL_BOTH,
+ TTK_NODE("Notebook.label", TTK_PACK_TOP))))
+TTK_END_LAYOUT
+
+/*------------------------------------------------------------------------
+ * +++ Initialization.
+ */
+
+MODULE_SCOPE
+void TtkNotebook_Init(Tcl_Interp *interp)
+{
+ Ttk_Theme themePtr = Ttk_GetDefaultTheme(interp);
+
+ Ttk_RegisterLayout(themePtr, "Tab", TabLayout);
+ Ttk_RegisterLayout(themePtr, "TNotebook", NotebookLayout);
+
+ RegisterWidget(interp, "ttk::notebook", &NotebookWidgetSpec);
+}
+
+/*EOF*/
diff --git a/tk8.6/generic/ttk/ttkPanedwindow.c b/tk8.6/generic/ttk/ttkPanedwindow.c
new file mode 100644
index 0000000..adc2aef
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkPanedwindow.c
@@ -0,0 +1,976 @@
+/*
+ * Copyright (c) 2005, Joe English. Freely redistributable.
+ *
+ * ttk::panedwindow widget implementation.
+ *
+ * TODO: track active/pressed sash.
+ */
+
+#include <string.h>
+#include <tk.h>
+#include "ttkManager.h"
+#include "ttkTheme.h"
+#include "ttkWidget.h"
+
+/*------------------------------------------------------------------------
+ * +++ Layout algorithm.
+ *
+ * (pos=x/y, size=width/height, depending on -orient=horizontal/vertical)
+ *
+ * Each pane carries two pieces of state: the request size and the
+ * position of the following sash. (The final pane has no sash,
+ * its sash position is used as a sentinel value).
+ *
+ * Pane geometry is determined by the sash positions.
+ * When resizing, sash positions are computed from the request sizes,
+ * the available space, and pane weights (see PlaceSashes()).
+ * This ensures continuous resize behavior (that is: changing
+ * the size by X pixels then changing the size by Y pixels
+ * gives the same result as changing the size by X+Y pixels
+ * in one step).
+ *
+ * The request size is initially set to the slave window's requested size.
+ * When the user drags a sash, each pane's request size is set to its
+ * actual size. This ensures that panes "stay put" on the next resize.
+ *
+ * If reqSize == 0, use 0 for the weight as well. This ensures that
+ * "collapsed" panes stay collapsed during a resize, regardless of
+ * their nominal -weight.
+ *
+ * +++ Invariants.
+ *
+ * #sash = #pane - 1
+ * pos(pane[0]) = 0
+ * pos(sash[i]) = pos(pane[i]) + size(pane[i]), 0 <= i <= #sash
+ * pos(pane[i+1]) = pos(sash[i]) + size(sash[i]), 0 <= i < #sash
+ * pos(sash[#sash]) = size(pw) // sentinel value, constraint
+ *
+ * size(pw) = sum(size(pane(0..#pane))) + sum(size(sash(0..#sash)))
+ * size(pane[i]) >= 0, for 0 <= i < #pane
+ * size(sash[i]) >= 0, for 0 <= i < #sash
+ * ==> pos(pane[i]) <= pos(sash[i]) <= pos(pane[i+1]), for 0 <= i < #sash
+ *
+ * Assumption: all sashes are the same size.
+ */
+
+/*------------------------------------------------------------------------
+ * +++ Widget record.
+ */
+
+typedef struct {
+ Tcl_Obj *orientObj;
+ int orient;
+ int width;
+ int height;
+ Ttk_Manager *mgr;
+ Tk_OptionTable paneOptionTable;
+ Ttk_Layout sashLayout;
+ int sashThickness;
+} PanedPart;
+
+typedef struct {
+ WidgetCore core;
+ PanedPart paned;
+} Paned;
+
+/* @@@ NOTE: -orient is readonly 'cause dynamic oriention changes NYI
+ */
+static Tk_OptionSpec PanedOptionSpecs[] = {
+ {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient", "vertical",
+ Tk_Offset(Paned,paned.orientObj), Tk_Offset(Paned,paned.orient),
+ 0,(ClientData)ttkOrientStrings,READONLY_OPTION|STYLE_CHANGED },
+ {TK_OPTION_INT, "-width", "width", "Width", "0",
+ -1,Tk_Offset(Paned,paned.width),
+ 0,0,GEOMETRY_CHANGED },
+ {TK_OPTION_INT, "-height", "height", "Height", "0",
+ -1,Tk_Offset(Paned,paned.height),
+ 0,0,GEOMETRY_CHANGED },
+
+ WIDGET_TAKEFOCUS_FALSE,
+ WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)
+};
+
+/*------------------------------------------------------------------------
+ * +++ Slave pane record.
+ */
+typedef struct {
+ int reqSize; /* Pane request size */
+ int sashPos; /* Folowing sash position */
+ int weight; /* Pane -weight, for resizing */
+} Pane;
+
+static Tk_OptionSpec PaneOptionSpecs[] = {
+ {TK_OPTION_INT, "-weight", "weight", "Weight", "0",
+ -1,Tk_Offset(Pane,weight), 0,0,GEOMETRY_CHANGED },
+ {TK_OPTION_END, 0,0,0, NULL, -1,-1, 0,0,0}
+};
+
+/* CreatePane --
+ * Create a new pane record.
+ */
+static Pane *CreatePane(Tcl_Interp *interp, Paned *pw, Tk_Window slaveWindow)
+{
+ Tk_OptionTable optionTable = pw->paned.paneOptionTable;
+ void *record = ckalloc(sizeof(Pane));
+ Pane *pane = record;
+
+ memset(record, 0, sizeof(Pane));
+ if (Tk_InitOptions(interp, record, optionTable, slaveWindow) != TCL_OK) {
+ ckfree(record);
+ return NULL;
+ }
+
+ pane->reqSize
+ = pw->paned.orient == TTK_ORIENT_HORIZONTAL
+ ? Tk_ReqWidth(slaveWindow) : Tk_ReqHeight(slaveWindow);
+
+ return pane;
+}
+
+/* DestroyPane --
+ * Free pane record.
+ */
+static void DestroyPane(Paned *pw, Pane *pane)
+{
+ void *record = pane;
+ Tk_FreeConfigOptions(record, pw->paned.paneOptionTable, pw->core.tkwin);
+ ckfree(record);
+}
+
+/* ConfigurePane --
+ * Set pane options.
+ */
+static int ConfigurePane(
+ Tcl_Interp *interp, Paned *pw, Pane *pane, Tk_Window slaveWindow,
+ int objc, Tcl_Obj *const objv[])
+{
+ Ttk_Manager *mgr = pw->paned.mgr;
+ Tk_SavedOptions savedOptions;
+ int mask = 0;
+
+ if (Tk_SetOptions(interp, (void*)pane, pw->paned.paneOptionTable,
+ objc, objv, slaveWindow, &savedOptions, &mask) != TCL_OK)
+ {
+ return TCL_ERROR;
+ }
+
+ /* Sanity-check:
+ */
+ if (pane->weight < 0) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "-weight must be nonnegative", -1));
+ Tcl_SetErrorCode(interp, "TTK", "PANE", "WEIGHT", NULL);
+ goto error;
+ }
+
+ /* Done.
+ */
+ Tk_FreeSavedOptions(&savedOptions);
+ Ttk_ManagerSizeChanged(mgr);
+ return TCL_OK;
+
+error:
+ Tk_RestoreSavedOptions(&savedOptions);
+ return TCL_ERROR;
+}
+
+
+/*------------------------------------------------------------------------
+ * +++ Sash adjustment.
+ */
+
+/* ShoveUp --
+ * Place sash i at specified position, recursively shoving
+ * previous sashes upwards as needed, until hitting the top
+ * of the window. If that happens, shove back down.
+ *
+ * Returns: final position of sash i.
+ */
+
+static int ShoveUp(Paned *pw, int i, int pos)
+{
+ Pane *pane = Ttk_SlaveData(pw->paned.mgr, i);
+ int sashThickness = pw->paned.sashThickness;
+
+ if (i == 0) {
+ if (pos < 0)
+ pos = 0;
+ } else {
+ Pane *prevPane = Ttk_SlaveData(pw->paned.mgr, i-1);
+ if (pos < prevPane->sashPos + sashThickness)
+ pos = ShoveUp(pw, i-1, pos - sashThickness) + sashThickness;
+ }
+ return pane->sashPos = pos;
+}
+
+/* ShoveDown --
+ * Same as ShoveUp, but going in the opposite direction
+ * and stopping at the sentinel sash.
+ */
+static int ShoveDown(Paned *pw, int i, int pos)
+{
+ Pane *pane = Ttk_SlaveData(pw->paned.mgr,i);
+ int sashThickness = pw->paned.sashThickness;
+
+ if (i == Ttk_NumberSlaves(pw->paned.mgr) - 1) {
+ pos = pane->sashPos; /* Sentinel value == master window size */
+ } else {
+ Pane *nextPane = Ttk_SlaveData(pw->paned.mgr,i+1);
+ if (pos + sashThickness > nextPane->sashPos)
+ pos = ShoveDown(pw, i+1, pos + sashThickness) - sashThickness;
+ }
+ return pane->sashPos = pos;
+}
+
+/* PanedSize --
+ * Compute the requested size of the paned widget
+ * from the individual pane request sizes.
+ *
+ * Used as the WidgetSpec sizeProc and the ManagerSpec sizeProc.
+ */
+static int PanedSize(void *recordPtr, int *widthPtr, int *heightPtr)
+{
+ Paned *pw = recordPtr;
+ int nPanes = Ttk_NumberSlaves(pw->paned.mgr);
+ int nSashes = nPanes - 1;
+ int sashThickness = pw->paned.sashThickness;
+ int width = 0, height = 0;
+ int index;
+
+ if (pw->paned.orient == TTK_ORIENT_HORIZONTAL) {
+ for (index = 0; index < nPanes; ++index) {
+ Pane *pane = Ttk_SlaveData(pw->paned.mgr, index);
+ Tk_Window slaveWindow = Ttk_SlaveWindow(pw->paned.mgr, index);
+
+ if (height < Tk_ReqHeight(slaveWindow))
+ height = Tk_ReqHeight(slaveWindow);
+ width += pane->reqSize;
+ }
+ width += nSashes * sashThickness;
+ } else {
+ for (index = 0; index < nPanes; ++index) {
+ Pane *pane = Ttk_SlaveData(pw->paned.mgr, index);
+ Tk_Window slaveWindow = Ttk_SlaveWindow(pw->paned.mgr, index);
+
+ if (width < Tk_ReqWidth(slaveWindow))
+ width = Tk_ReqWidth(slaveWindow);
+ height += pane->reqSize;
+ }
+ height += nSashes * sashThickness;
+ }
+
+ *widthPtr = pw->paned.width > 0 ? pw->paned.width : width;
+ *heightPtr = pw->paned.height > 0 ? pw->paned.height : height;
+ return 1;
+}
+
+/* AdjustPanes --
+ * Set pane request sizes from sash positions.
+ *
+ * NOTE:
+ * AdjustPanes followed by PlaceSashes (called during relayout)
+ * will leave the sashes in the same place, as long as available size
+ * remains contant.
+ */
+static void AdjustPanes(Paned *pw)
+{
+ int sashThickness = pw->paned.sashThickness;
+ int pos = 0;
+ int index;
+
+ for (index = 0; index < Ttk_NumberSlaves(pw->paned.mgr); ++index) {
+ Pane *pane = Ttk_SlaveData(pw->paned.mgr, index);
+ int size = pane->sashPos - pos;
+ pane->reqSize = size >= 0 ? size : 0;
+ pos = pane->sashPos + sashThickness;
+ }
+}
+
+/* PlaceSashes --
+ * Set sash positions from pane request sizes and available space.
+ * The sentinel sash position is set to the available space.
+ *
+ * Allocate pane->reqSize pixels to each pane, and distribute
+ * the difference = available size - requested size according
+ * to pane->weight.
+ *
+ * If there's still some left over, squeeze panes from the bottom up
+ * (This can happen if all weights are zero, or if one or more panes
+ * are too small to absorb the required shrinkage).
+ *
+ * Notes:
+ * This doesn't distribute the remainder pixels as evenly as it could
+ * when more than one pane has weight > 1.
+ */
+static void PlaceSashes(Paned *pw, int width, int height)
+{
+ Ttk_Manager *mgr = pw->paned.mgr;
+ int nPanes = Ttk_NumberSlaves(mgr);
+ int sashThickness = pw->paned.sashThickness;
+ int available = pw->paned.orient == TTK_ORIENT_HORIZONTAL ? width : height;
+ int reqSize = 0, totalWeight = 0;
+ int difference, delta, remainder, pos, i;
+
+ if (nPanes == 0)
+ return;
+
+ /* Compute total required size and total available weight:
+ */
+ for (i = 0; i < nPanes; ++i) {
+ Pane *pane = Ttk_SlaveData(mgr, i);
+ reqSize += pane->reqSize;
+ totalWeight += pane->weight * (pane->reqSize != 0);
+ }
+
+ /* Compute difference to be redistributed:
+ */
+ difference = available - reqSize - sashThickness*(nPanes-1);
+ if (totalWeight != 0) {
+ delta = difference / totalWeight;
+ remainder = difference % totalWeight;
+ if (remainder < 0) {
+ --delta;
+ remainder += totalWeight;
+ }
+ } else {
+ delta = remainder = 0;
+ }
+ /* ASSERT: 0 <= remainder < totalWeight */
+
+ /* Place sashes:
+ */
+ pos = 0;
+ for (i = 0; i < nPanes; ++i) {
+ Pane *pane = Ttk_SlaveData(mgr, i);
+ int weight = pane->weight * (pane->reqSize != 0);
+ int size = pane->reqSize + delta * weight;
+
+ if (weight > remainder)
+ weight = remainder;
+ remainder -= weight;
+ size += weight;
+
+ if (size < 0)
+ size = 0;
+
+ pane->sashPos = (pos += size);
+ pos += sashThickness;
+ }
+
+ /* Handle emergency shrink/emergency stretch:
+ * Set sentinel sash position to end of widget,
+ * shove preceding sashes up.
+ */
+ ShoveUp(pw, nPanes - 1, available);
+}
+
+/* PlacePanes --
+ * Places slave panes based on sash positions.
+ */
+static void PlacePanes(Paned *pw)
+{
+ int horizontal = pw->paned.orient == TTK_ORIENT_HORIZONTAL;
+ int width = Tk_Width(pw->core.tkwin), height = Tk_Height(pw->core.tkwin);
+ int sashThickness = pw->paned.sashThickness;
+ int pos = 0;
+ int index;
+
+ for (index = 0; index < Ttk_NumberSlaves(pw->paned.mgr); ++index) {
+ Pane *pane = Ttk_SlaveData(pw->paned.mgr, index);
+ int size = pane->sashPos - pos;
+
+ if (size > 0) {
+ if (horizontal) {
+ Ttk_PlaceSlave(pw->paned.mgr, index, pos, 0, size, height);
+ } else {
+ Ttk_PlaceSlave(pw->paned.mgr, index, 0, pos, width, size);
+ }
+ } else {
+ Ttk_UnmapSlave(pw->paned.mgr, index);
+ }
+
+ pos = pane->sashPos + sashThickness;
+ }
+}
+
+/*------------------------------------------------------------------------
+ * +++ Manager specification.
+ */
+
+static void PanedPlaceSlaves(void *managerData)
+{
+ Paned *pw = managerData;
+ PlaceSashes(pw, Tk_Width(pw->core.tkwin), Tk_Height(pw->core.tkwin));
+ PlacePanes(pw);
+}
+
+static void PaneRemoved(void *managerData, int index)
+{
+ Paned *pw = managerData;
+ Pane *pane = Ttk_SlaveData(pw->paned.mgr, index);
+ DestroyPane(pw, pane);
+}
+
+static int AddPane(
+ Tcl_Interp *interp, Paned *pw,
+ int destIndex, Tk_Window slaveWindow,
+ int objc, Tcl_Obj *const objv[])
+{
+ Pane *pane;
+ if (!Ttk_Maintainable(interp, slaveWindow, pw->core.tkwin)) {
+ return TCL_ERROR;
+ }
+ if (Ttk_SlaveIndex(pw->paned.mgr, slaveWindow) >= 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "%s already added", Tk_PathName(slaveWindow)));
+ Tcl_SetErrorCode(interp, "TTK", "PANE", "PRESENT", NULL);
+ return TCL_ERROR;
+ }
+
+ pane = CreatePane(interp, pw, slaveWindow);
+ if (!pane) {
+ return TCL_ERROR;
+ }
+ if (ConfigurePane(interp, pw, pane, slaveWindow, objc, objv) != TCL_OK) {
+ DestroyPane(pw, pane);
+ return TCL_ERROR;
+ }
+
+ Ttk_InsertSlave(pw->paned.mgr, destIndex, slaveWindow, pane);
+ return TCL_OK;
+}
+
+/* PaneRequest --
+ * Only update pane request size if slave is currently unmapped.
+ * Geometry requests from mapped slaves are not directly honored
+ * in order to avoid unexpected pane resizes (esp. while the
+ * user is dragging a sash [#1325286]).
+ */
+static int PaneRequest(void *managerData, int index, int width, int height)
+{
+ Paned *pw = managerData;
+ Pane *pane = Ttk_SlaveData(pw->paned.mgr, index);
+ Tk_Window slaveWindow = Ttk_SlaveWindow(pw->paned.mgr, index);
+ int horizontal = pw->paned.orient == TTK_ORIENT_HORIZONTAL;
+
+ if (!Tk_IsMapped(slaveWindow)) {
+ pane->reqSize = horizontal ? width : height;
+ }
+ return 1;
+}
+
+static Ttk_ManagerSpec PanedManagerSpec = {
+ { "panedwindow", Ttk_GeometryRequestProc, Ttk_LostSlaveProc },
+ PanedSize,
+ PanedPlaceSlaves,
+ PaneRequest,
+ PaneRemoved
+};
+
+/*------------------------------------------------------------------------
+ * +++ Event handler.
+ *
+ * <<NOTE-PW-LEAVE-NOTIFYINFERIOR>>
+ * Tk does not execute binding scripts for <Leave> events when
+ * the pointer crosses from a parent to a child. This widget
+ * needs to know when that happens, though, so it can reset
+ * the cursor.
+ *
+ * This event handler generates an <<EnteredChild>> virtual event
+ * on LeaveNotify/NotifyInferior.
+ */
+
+static const unsigned PanedEventMask = LeaveWindowMask;
+static void PanedEventProc(ClientData clientData, XEvent *eventPtr)
+{
+ WidgetCore *corePtr = clientData;
+ if ( eventPtr->type == LeaveNotify
+ && eventPtr->xcrossing.detail == NotifyInferior)
+ {
+ TtkSendVirtualEvent(corePtr->tkwin, "EnteredChild");
+ }
+}
+
+/*------------------------------------------------------------------------
+ * +++ Initialization and cleanup hooks.
+ */
+
+static void PanedInitialize(Tcl_Interp *interp, void *recordPtr)
+{
+ Paned *pw = recordPtr;
+
+ Tk_CreateEventHandler(pw->core.tkwin,
+ PanedEventMask, PanedEventProc, recordPtr);
+ pw->paned.mgr = Ttk_CreateManager(&PanedManagerSpec, pw, pw->core.tkwin);
+ pw->paned.paneOptionTable = Tk_CreateOptionTable(interp,PaneOptionSpecs);
+ pw->paned.sashLayout = 0;
+ pw->paned.sashThickness = 1;
+}
+
+static void PanedCleanup(void *recordPtr)
+{
+ Paned *pw = recordPtr;
+
+ if (pw->paned.sashLayout)
+ Ttk_FreeLayout(pw->paned.sashLayout);
+ Tk_DeleteEventHandler(pw->core.tkwin,
+ PanedEventMask, PanedEventProc, recordPtr);
+ Ttk_DeleteManager(pw->paned.mgr);
+}
+
+/* Post-configuration hook.
+ */
+static int PanedPostConfigure(Tcl_Interp *interp, void *clientData, int mask)
+{
+ Paned *pw = clientData;
+
+ if (mask & GEOMETRY_CHANGED) {
+ /* User has changed -width or -height.
+ * Recalculate sash positions based on requested size.
+ */
+ Tk_Window tkwin = pw->core.tkwin;
+ PlaceSashes(pw,
+ pw->paned.width > 0 ? pw->paned.width : Tk_Width(tkwin),
+ pw->paned.height > 0 ? pw->paned.height : Tk_Height(tkwin));
+ }
+
+ return TCL_OK;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Layout management hooks.
+ */
+static Ttk_Layout PanedGetLayout(
+ Tcl_Interp *interp, Ttk_Theme themePtr, void *recordPtr)
+{
+ Paned *pw = recordPtr;
+ Ttk_Layout panedLayout = TtkWidgetGetLayout(interp, themePtr, recordPtr);
+
+ if (panedLayout) {
+ int horizontal = pw->paned.orient == TTK_ORIENT_HORIZONTAL;
+ const char *layoutName =
+ horizontal ? ".Vertical.Sash" : ".Horizontal.Sash";
+ Ttk_Layout sashLayout = Ttk_CreateSublayout(
+ interp, themePtr, panedLayout, layoutName, pw->core.optionTable);
+
+ if (sashLayout) {
+ int sashWidth, sashHeight;
+
+ Ttk_LayoutSize(sashLayout, 0, &sashWidth, &sashHeight);
+ pw->paned.sashThickness = horizontal ? sashWidth : sashHeight;
+
+ if (pw->paned.sashLayout)
+ Ttk_FreeLayout(pw->paned.sashLayout);
+ pw->paned.sashLayout = sashLayout;
+ } else {
+ Ttk_FreeLayout(panedLayout);
+ return 0;
+ }
+ }
+
+ return panedLayout;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Drawing routines.
+ */
+
+/* SashLayout --
+ * Place the sash sublayout after the specified pane,
+ * in preparation for drawing.
+ */
+static Ttk_Layout SashLayout(Paned *pw, int index)
+{
+ Pane *pane = Ttk_SlaveData(pw->paned.mgr, index);
+ int thickness = pw->paned.sashThickness,
+ height = Tk_Height(pw->core.tkwin),
+ width = Tk_Width(pw->core.tkwin),
+ sashPos = pane->sashPos;
+
+ Ttk_PlaceLayout(
+ pw->paned.sashLayout, pw->core.state,
+ pw->paned.orient == TTK_ORIENT_HORIZONTAL
+ ? Ttk_MakeBox(sashPos, 0, thickness, height)
+ : Ttk_MakeBox(0, sashPos, width, thickness));
+
+ return pw->paned.sashLayout;
+}
+
+static void DrawSash(Paned *pw, int index, Drawable d)
+{
+ Ttk_DrawLayout(SashLayout(pw, index), pw->core.state, d);
+}
+
+static void PanedDisplay(void *recordPtr, Drawable d)
+{
+ Paned *pw = recordPtr;
+ int i, nSashes = Ttk_NumberSlaves(pw->paned.mgr) - 1;
+
+ TtkWidgetDisplay(recordPtr, d);
+ for (i = 0; i < nSashes; ++i) {
+ DrawSash(pw, i, d);
+ }
+}
+
+/*------------------------------------------------------------------------
+ * +++ Widget commands.
+ */
+
+/* $pw add window [ options ... ]
+ */
+static int PanedAddCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Paned *pw = recordPtr;
+ Tk_Window slaveWindow;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window");
+ return TCL_ERROR;
+ }
+
+ slaveWindow = Tk_NameToWindow(
+ interp, Tcl_GetString(objv[2]), pw->core.tkwin);
+
+ if (!slaveWindow) {
+ return TCL_ERROR;
+ }
+
+ return AddPane(interp, pw, Ttk_NumberSlaves(pw->paned.mgr), slaveWindow,
+ objc - 3, objv + 3);
+}
+
+/* $pw insert $index $slave ?-option value ...?
+ * Insert new slave, or move existing one.
+ */
+static int PanedInsertCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Paned *pw = recordPtr;
+ int nSlaves = Ttk_NumberSlaves(pw->paned.mgr);
+ int srcIndex, destIndex;
+ Tk_Window slaveWindow;
+
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 2,objv, "index slave ?-option value ...?");
+ return TCL_ERROR;
+ }
+
+ slaveWindow = Tk_NameToWindow(
+ interp, Tcl_GetString(objv[3]), pw->core.tkwin);
+ if (!slaveWindow) {
+ return TCL_ERROR;
+ }
+
+ if (!strcmp(Tcl_GetString(objv[2]), "end")) {
+ destIndex = Ttk_NumberSlaves(pw->paned.mgr);
+ } else if (TCL_OK != Ttk_GetSlaveIndexFromObj(
+ interp,pw->paned.mgr,objv[2],&destIndex))
+ {
+ return TCL_ERROR;
+ }
+
+ srcIndex = Ttk_SlaveIndex(pw->paned.mgr, slaveWindow);
+ if (srcIndex < 0) { /* New slave: */
+ return AddPane(interp, pw, destIndex, slaveWindow, objc-4, objv+4);
+ } /* else -- move existing slave: */
+
+ if (destIndex >= nSlaves)
+ destIndex = nSlaves - 1;
+ Ttk_ReorderSlave(pw->paned.mgr, srcIndex, destIndex);
+
+ return objc == 4 ? TCL_OK :
+ ConfigurePane(interp, pw,
+ Ttk_SlaveData(pw->paned.mgr, destIndex),
+ Ttk_SlaveWindow(pw->paned.mgr, destIndex),
+ objc-4,objv+4);
+}
+
+/* $pw forget $pane
+ */
+static int PanedForgetCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Paned *pw = recordPtr;
+ int paneIndex;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2,objv, "pane");
+ return TCL_ERROR;
+ }
+
+ if (TCL_OK != Ttk_GetSlaveIndexFromObj(
+ interp, pw->paned.mgr, objv[2], &paneIndex))
+ {
+ return TCL_ERROR;
+ }
+ Ttk_ForgetSlave(pw->paned.mgr, paneIndex);
+
+ return TCL_OK;
+}
+
+/* $pw identify ?what? $x $y --
+ * Return index of sash at $x,$y
+ */
+static int PanedIdentifyCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ static const char *whatTable[] = { "element", "sash", NULL };
+ enum { IDENTIFY_ELEMENT, IDENTIFY_SASH };
+ int what = IDENTIFY_SASH;
+ Paned *pw = recordPtr;
+ int sashThickness = pw->paned.sashThickness;
+ int nSashes = Ttk_NumberSlaves(pw->paned.mgr) - 1;
+ int x, y, pos;
+ int index;
+
+ if (objc < 4 || objc > 5) {
+ Tcl_WrongNumArgs(interp, 2,objv, "?what? x y");
+ return TCL_ERROR;
+ }
+
+ if ( Tcl_GetIntFromObj(interp, objv[objc-2], &x) != TCL_OK
+ || Tcl_GetIntFromObj(interp, objv[objc-1], &y) != TCL_OK
+ || (objc == 5 && Tcl_GetIndexFromObjStruct(interp, objv[2], whatTable,
+ sizeof(char *), "option", 0, &what) != TCL_OK)
+ ) {
+ return TCL_ERROR;
+ }
+
+ pos = pw->paned.orient == TTK_ORIENT_HORIZONTAL ? x : y;
+ for (index = 0; index < nSashes; ++index) {
+ Pane *pane = Ttk_SlaveData(pw->paned.mgr, index);
+ if (pane->sashPos <= pos && pos <= pane->sashPos + sashThickness) {
+ /* Found it. */
+ switch (what) {
+ case IDENTIFY_SASH:
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(index));
+ return TCL_OK;
+ case IDENTIFY_ELEMENT:
+ {
+ Ttk_Element element =
+ Ttk_IdentifyElement(SashLayout(pw, index), x, y);
+ if (element) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj(Ttk_ElementName(element), -1));
+ }
+ return TCL_OK;
+ }
+ }
+ }
+ }
+
+ return TCL_OK; /* nothing found - return empty string */
+}
+
+/* $pw pane $pane ?-option ?value -option value ...??
+ * Query/modify pane options.
+ */
+static int PanedPaneCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Paned *pw = recordPtr;
+ int paneIndex;
+ Tk_Window slaveWindow;
+ Pane *pane;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2,objv, "pane ?-option value ...?");
+ return TCL_ERROR;
+ }
+
+ if (TCL_OK != Ttk_GetSlaveIndexFromObj(
+ interp,pw->paned.mgr,objv[2],&paneIndex))
+ {
+ return TCL_ERROR;
+ }
+
+ pane = Ttk_SlaveData(pw->paned.mgr, paneIndex);
+ slaveWindow = Ttk_SlaveWindow(pw->paned.mgr, paneIndex);
+
+ switch (objc) {
+ case 3:
+ return TtkEnumerateOptions(interp, pane, PaneOptionSpecs,
+ pw->paned.paneOptionTable, slaveWindow);
+ case 4:
+ return TtkGetOptionValue(interp, pane, objv[3],
+ pw->paned.paneOptionTable, slaveWindow);
+ default:
+ return ConfigurePane(interp, pw, pane, slaveWindow, objc-3,objv+3);
+ }
+}
+
+/* $pw panes --
+ * Return list of managed panes.
+ */
+static int PanedPanesCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Paned *pw = recordPtr;
+ Ttk_Manager *mgr = pw->paned.mgr;
+ Tcl_Obj *panes;
+ int i;
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, "");
+ return TCL_ERROR;
+ }
+
+ panes = Tcl_NewListObj(0, NULL);
+ for (i = 0; i < Ttk_NumberSlaves(mgr); ++i) {
+ const char *pathName = Tk_PathName(Ttk_SlaveWindow(mgr,i));
+ Tcl_ListObjAppendElement(interp, panes, Tcl_NewStringObj(pathName,-1));
+ }
+ Tcl_SetObjResult(interp, panes);
+
+ return TCL_OK;
+}
+
+
+/* $pw sashpos $index ?$newpos?
+ * Query or modify sash position.
+ */
+static int PanedSashposCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Paned *pw = recordPtr;
+ int sashIndex, position = -1;
+ Pane *pane;
+
+ if (objc < 3 || objc > 4) {
+ Tcl_WrongNumArgs(interp, 2,objv, "index ?newpos?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIntFromObj(interp, objv[2], &sashIndex) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (sashIndex < 0 || sashIndex >= Ttk_NumberSlaves(pw->paned.mgr) - 1) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "sash index %d out of range", sashIndex));
+ Tcl_SetErrorCode(interp, "TTK", "PANE", "SASH_INDEX", NULL);
+ return TCL_ERROR;
+ }
+
+ pane = Ttk_SlaveData(pw->paned.mgr, sashIndex);
+
+ if (objc == 3) {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(pane->sashPos));
+ return TCL_OK;
+ }
+ /* else -- set new sash position */
+
+ if (Tcl_GetIntFromObj(interp, objv[3], &position) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (position < pane->sashPos) {
+ ShoveUp(pw, sashIndex, position);
+ } else {
+ ShoveDown(pw, sashIndex, position);
+ }
+
+ AdjustPanes(pw);
+ Ttk_ManagerLayoutChanged(pw->paned.mgr);
+
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(pane->sashPos));
+ return TCL_OK;
+}
+
+static const Ttk_Ensemble PanedCommands[] = {
+ { "add", PanedAddCommand,0 },
+ { "configure", TtkWidgetConfigureCommand,0 },
+ { "cget", TtkWidgetCgetCommand,0 },
+ { "forget", PanedForgetCommand,0 },
+ { "identify", PanedIdentifyCommand,0 },
+ { "insert", PanedInsertCommand,0 },
+ { "instate", TtkWidgetInstateCommand,0 },
+ { "pane", PanedPaneCommand,0 },
+ { "panes", PanedPanesCommand,0 },
+ { "sashpos", PanedSashposCommand,0 },
+ { "state", TtkWidgetStateCommand,0 },
+ { 0,0,0 }
+};
+
+/*------------------------------------------------------------------------
+ * +++ Widget specification.
+ */
+
+static WidgetSpec PanedWidgetSpec =
+{
+ "TPanedwindow", /* className */
+ sizeof(Paned), /* recordSize */
+ PanedOptionSpecs, /* optionSpecs */
+ PanedCommands, /* subcommands */
+ PanedInitialize, /* initializeProc */
+ PanedCleanup, /* cleanupProc */
+ TtkCoreConfigure, /* configureProc */
+ PanedPostConfigure, /* postConfigureProc */
+ PanedGetLayout, /* getLayoutProc */
+ PanedSize, /* sizeProc */
+ TtkWidgetDoLayout, /* layoutProc */
+ PanedDisplay /* displayProc */
+};
+
+/*------------------------------------------------------------------------
+ * +++ Elements and layouts.
+ */
+
+static const int DEFAULT_SASH_THICKNESS = 5;
+
+typedef struct {
+ Tcl_Obj *thicknessObj;
+} SashElement;
+
+static Ttk_ElementOptionSpec SashElementOptions[] = {
+ { "-sashthickness", TK_OPTION_INT,
+ Tk_Offset(SashElement,thicknessObj), "5" },
+ { NULL, 0, 0, NULL }
+};
+
+static void SashElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ SashElement *sash = elementRecord;
+ int thickness = DEFAULT_SASH_THICKNESS;
+ Tcl_GetIntFromObj(NULL, sash->thicknessObj, &thickness);
+ *widthPtr = *heightPtr = thickness;
+}
+
+static Ttk_ElementSpec SashElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(SashElement),
+ SashElementOptions,
+ SashElementSize,
+ TtkNullElementDraw
+};
+
+TTK_BEGIN_LAYOUT(PanedLayout)
+ TTK_NODE("Panedwindow.background", 0)/* @@@ BUG: empty layouts don't work */
+TTK_END_LAYOUT
+
+TTK_BEGIN_LAYOUT(HorizontalSashLayout)
+ TTK_NODE("Sash.hsash", TTK_FILL_X)
+TTK_END_LAYOUT
+
+TTK_BEGIN_LAYOUT(VerticalSashLayout)
+ TTK_NODE("Sash.vsash", TTK_FILL_Y)
+TTK_END_LAYOUT
+
+/*------------------------------------------------------------------------
+ * +++ Registration routine.
+ */
+MODULE_SCOPE
+void TtkPanedwindow_Init(Tcl_Interp *interp)
+{
+ Ttk_Theme themePtr = Ttk_GetDefaultTheme(interp);
+ RegisterWidget(interp, "ttk::panedwindow", &PanedWidgetSpec);
+
+ Ttk_RegisterElement(interp, themePtr, "hsash", &SashElementSpec, 0);
+ Ttk_RegisterElement(interp, themePtr, "vsash", &SashElementSpec, 0);
+
+ Ttk_RegisterLayout(themePtr, "TPanedwindow", PanedLayout);
+ Ttk_RegisterLayout(themePtr, "Horizontal.Sash", HorizontalSashLayout);
+ Ttk_RegisterLayout(themePtr, "Vertical.Sash", VerticalSashLayout);
+}
+
diff --git a/tk8.6/generic/ttk/ttkProgress.c b/tk8.6/generic/ttk/ttkProgress.c
new file mode 100644
index 0000000..6c13992
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkProgress.c
@@ -0,0 +1,547 @@
+/*
+ * Copyright (c) Joe English, Pat Thoyts, Michael Kirkham
+ *
+ * ttk::progressbar widget.
+ */
+
+#include <math.h>
+#include <tk.h>
+
+#include "ttkTheme.h"
+#include "ttkWidget.h"
+
+/*------------------------------------------------------------------------
+ * +++ Widget record:
+ */
+
+#define DEF_PROGRESSBAR_LENGTH "100"
+enum {
+ TTK_PROGRESSBAR_DETERMINATE, TTK_PROGRESSBAR_INDETERMINATE
+};
+static const char *const ProgressbarModeStrings[] = {
+ "determinate", "indeterminate", NULL
+};
+
+typedef struct {
+ Tcl_Obj *orientObj;
+ Tcl_Obj *lengthObj;
+ Tcl_Obj *modeObj;
+ Tcl_Obj *variableObj;
+ Tcl_Obj *maximumObj;
+ Tcl_Obj *valueObj;
+ Tcl_Obj *phaseObj;
+
+ int mode;
+ Ttk_TraceHandle *variableTrace; /* Trace handle for -variable option */
+ int period; /* Animation period */
+ int maxPhase; /* Max animation phase */
+ Tcl_TimerToken timer; /* Animation timer */
+
+} ProgressbarPart;
+
+typedef struct {
+ WidgetCore core;
+ ProgressbarPart progress;
+} Progressbar;
+
+static Tk_OptionSpec ProgressbarOptionSpecs[] =
+{
+ {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient",
+ "horizontal", Tk_Offset(Progressbar,progress.orientObj), -1,
+ 0, (ClientData)ttkOrientStrings, STYLE_CHANGED },
+ {TK_OPTION_PIXELS, "-length", "length", "Length",
+ DEF_PROGRESSBAR_LENGTH, Tk_Offset(Progressbar,progress.lengthObj), -1,
+ 0, 0, GEOMETRY_CHANGED },
+ {TK_OPTION_STRING_TABLE, "-mode", "mode", "ProgressMode", "determinate",
+ Tk_Offset(Progressbar,progress.modeObj),
+ Tk_Offset(Progressbar,progress.mode),
+ 0, (ClientData)ProgressbarModeStrings, 0 },
+ {TK_OPTION_DOUBLE, "-maximum", "maximum", "Maximum",
+ "100", Tk_Offset(Progressbar,progress.maximumObj), -1,
+ 0, 0, 0 },
+ {TK_OPTION_STRING, "-variable", "variable", "Variable",
+ NULL, Tk_Offset(Progressbar,progress.variableObj), -1,
+ TK_OPTION_NULL_OK, 0, 0 },
+ {TK_OPTION_DOUBLE, "-value", "value", "Value",
+ "0.0", Tk_Offset(Progressbar,progress.valueObj), -1,
+ 0, 0, 0 },
+ {TK_OPTION_INT, "-phase", "phase", "Phase",
+ "0", Tk_Offset(Progressbar,progress.phaseObj), -1,
+ 0, 0, 0 },
+
+ WIDGET_TAKEFOCUS_FALSE,
+ WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)
+};
+
+/*------------------------------------------------------------------------
+ * +++ Animation procedures:
+ */
+
+/* AnimationEnabled --
+ * Returns 1 if animation should be active, 0 otherwise.
+ */
+static int AnimationEnabled(Progressbar *pb)
+{
+ double maximum = 100, value = 0;
+
+ Tcl_GetDoubleFromObj(NULL, pb->progress.maximumObj, &maximum);
+ Tcl_GetDoubleFromObj(NULL, pb->progress.valueObj, &value);
+
+ return pb->progress.period > 0
+ && value > 0.0
+ && ( value < maximum
+ || pb->progress.mode == TTK_PROGRESSBAR_INDETERMINATE);
+}
+
+/* AnimateProgressProc --
+ * Timer callback for progress bar animation.
+ * Increments the -phase option, redisplays the widget,
+ * and reschedules itself if animation still enabled.
+ */
+static void AnimateProgressProc(ClientData clientData)
+{
+ Progressbar *pb = clientData;
+
+ pb->progress.timer = 0;
+
+ if (AnimationEnabled(pb)) {
+ int phase = 0;
+ Tcl_GetIntFromObj(NULL, pb->progress.phaseObj, &phase);
+
+ /*
+ * Update -phase:
+ */
+ ++phase;
+ if (pb->progress.maxPhase)
+ phase %= pb->progress.maxPhase;
+ Tcl_DecrRefCount(pb->progress.phaseObj);
+ pb->progress.phaseObj = Tcl_NewIntObj(phase);
+ Tcl_IncrRefCount(pb->progress.phaseObj);
+
+ /*
+ * Reschedule:
+ */
+ pb->progress.timer = Tcl_CreateTimerHandler(
+ pb->progress.period, AnimateProgressProc, clientData);
+
+ TtkRedisplayWidget(&pb->core);
+ }
+}
+
+/* CheckAnimation --
+ * If animation is enabled and not scheduled, schedule it.
+ * If animation is disabled but scheduled, cancel it.
+ */
+static void CheckAnimation(Progressbar *pb)
+{
+ if (AnimationEnabled(pb)) {
+ if (pb->progress.timer == 0) {
+ pb->progress.timer = Tcl_CreateTimerHandler(
+ pb->progress.period, AnimateProgressProc, (ClientData)pb);
+ }
+ } else {
+ if (pb->progress.timer != 0) {
+ Tcl_DeleteTimerHandler(pb->progress.timer);
+ pb->progress.timer = 0;
+ }
+ }
+}
+
+/*------------------------------------------------------------------------
+ * +++ Trace hook for progressbar -variable option:
+ */
+
+static void VariableChanged(void *recordPtr, const char *value)
+{
+ Progressbar *pb = recordPtr;
+ Tcl_Obj *newValue;
+ double scratch;
+
+ if (WidgetDestroyed(&pb->core)) {
+ return;
+ }
+
+ if (!value) {
+ /* Linked variable is unset -- disable widget */
+ TtkWidgetChangeState(&pb->core, TTK_STATE_DISABLED, 0);
+ return;
+ }
+ TtkWidgetChangeState(&pb->core, 0, TTK_STATE_DISABLED);
+
+ newValue = Tcl_NewStringObj(value, -1);
+ Tcl_IncrRefCount(newValue);
+ if (Tcl_GetDoubleFromObj(NULL, newValue, &scratch) != TCL_OK) {
+ TtkWidgetChangeState(&pb->core, TTK_STATE_INVALID, 0);
+ return;
+ }
+ TtkWidgetChangeState(&pb->core, 0, TTK_STATE_INVALID);
+ Tcl_DecrRefCount(pb->progress.valueObj);
+ pb->progress.valueObj = newValue;
+
+ CheckAnimation(pb);
+ TtkRedisplayWidget(&pb->core);
+}
+
+/*------------------------------------------------------------------------
+ * +++ Widget class methods:
+ */
+
+static void ProgressbarInitialize(Tcl_Interp *interp, void *recordPtr)
+{
+ Progressbar *pb = recordPtr;
+ pb->progress.variableTrace = 0;
+ pb->progress.timer = 0;
+}
+
+static void ProgressbarCleanup(void *recordPtr)
+{
+ Progressbar *pb = recordPtr;
+ if (pb->progress.variableTrace)
+ Ttk_UntraceVariable(pb->progress.variableTrace);
+ if (pb->progress.timer)
+ Tcl_DeleteTimerHandler(pb->progress.timer);
+}
+
+/*
+ * Configure hook:
+ *
+ * @@@ TODO: deal with [$pb configure -value ... -variable ...]
+ */
+static int ProgressbarConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
+{
+ Progressbar *pb = recordPtr;
+ Tcl_Obj *varName = pb->progress.variableObj;
+ Ttk_TraceHandle *vt = 0;
+
+ if (varName != NULL && *Tcl_GetString(varName) != '\0') {
+ vt = Ttk_TraceVariable(interp, varName, VariableChanged, recordPtr);
+ if (!vt) return TCL_ERROR;
+ }
+
+ if (TtkCoreConfigure(interp, recordPtr, mask) != TCL_OK) {
+ if (vt) Ttk_UntraceVariable(vt);
+ return TCL_ERROR;
+ }
+
+ if (pb->progress.variableTrace) {
+ Ttk_UntraceVariable(pb->progress.variableTrace);
+ }
+ pb->progress.variableTrace = vt;
+
+ return TCL_OK;
+}
+
+/*
+ * Post-configuration hook:
+ */
+static int ProgressbarPostConfigure(
+ Tcl_Interp *interp, void *recordPtr, int mask)
+{
+ Progressbar *pb = recordPtr;
+ int status = TCL_OK;
+
+ if (pb->progress.variableTrace) {
+ status = Ttk_FireTrace(pb->progress.variableTrace);
+ if (WidgetDestroyed(&pb->core)) {
+ return TCL_ERROR;
+ }
+ if (status != TCL_OK) {
+ /* Unset -variable: */
+ Ttk_UntraceVariable(pb->progress.variableTrace);
+ Tcl_DecrRefCount(pb->progress.variableObj);
+ pb->progress.variableTrace = 0;
+ pb->progress.variableObj = NULL;
+ return TCL_ERROR;
+ }
+ }
+
+ CheckAnimation(pb);
+
+ return status;
+}
+
+/*
+ * Size hook:
+ * Compute base layout size, overrid
+ */
+static int ProgressbarSize(void *recordPtr, int *widthPtr, int *heightPtr)
+{
+ Progressbar *pb = recordPtr;
+ int length = 100, orient = TTK_ORIENT_HORIZONTAL;
+
+ TtkWidgetSize(recordPtr, widthPtr, heightPtr);
+
+ /* Override requested width (height) based on -length and -orient
+ */
+ Tk_GetPixelsFromObj(NULL, pb->core.tkwin, pb->progress.lengthObj, &length);
+ Ttk_GetOrientFromObj(NULL, pb->progress.orientObj, &orient);
+
+ if (orient == TTK_ORIENT_HORIZONTAL) {
+ *widthPtr = length;
+ } else {
+ *heightPtr = length;
+ }
+
+ return 1;
+}
+
+/*
+ * Layout hook:
+ * Adjust size and position of pbar element, if present.
+ */
+
+static void ProgressbarDeterminateLayout(
+ Progressbar *pb,
+ Ttk_Element pbar,
+ Ttk_Box parcel,
+ double fraction,
+ Ttk_Orient orient)
+{
+ if (fraction < 0.0) fraction = 0.0;
+ if (fraction > 1.0) fraction = 1.0;
+
+ if (orient == TTK_ORIENT_HORIZONTAL) {
+ parcel.width = (int)(parcel.width * fraction);
+ } else {
+ int newHeight = (int)(parcel.height * fraction);
+ parcel.y += (parcel.height - newHeight);
+ parcel.height = newHeight;
+ }
+ Ttk_PlaceElement(pb->core.layout, pbar, parcel);
+}
+
+static void ProgressbarIndeterminateLayout(
+ Progressbar *pb,
+ Ttk_Element pbar,
+ Ttk_Box parcel,
+ double fraction,
+ Ttk_Orient orient)
+{
+ Ttk_Box pbarBox = Ttk_ElementParcel(pbar);
+
+ fraction = fmod(fabs(fraction), 2.0);
+ if (fraction > 1.0) {
+ fraction = 2.0 - fraction;
+ }
+
+ if (orient == TTK_ORIENT_HORIZONTAL) {
+ pbarBox.x = parcel.x + (int)(fraction * (parcel.width-pbarBox.width));
+ } else {
+ pbarBox.y = parcel.y + (int)(fraction * (parcel.height-pbarBox.height));
+ }
+ Ttk_PlaceElement(pb->core.layout, pbar, pbarBox);
+}
+
+static void ProgressbarDoLayout(void *recordPtr)
+{
+ Progressbar *pb = recordPtr;
+ WidgetCore *corePtr = &pb->core;
+ Ttk_Element pbar = Ttk_FindElement(corePtr->layout, "pbar");
+ double value = 0.0, maximum = 100.0;
+ int orient = TTK_ORIENT_HORIZONTAL;
+
+ Ttk_PlaceLayout(corePtr->layout,corePtr->state,Ttk_WinBox(corePtr->tkwin));
+
+ /* Adjust the bar size:
+ */
+
+ Tcl_GetDoubleFromObj(NULL, pb->progress.valueObj, &value);
+ Tcl_GetDoubleFromObj(NULL, pb->progress.maximumObj, &maximum);
+ Ttk_GetOrientFromObj(NULL, pb->progress.orientObj, &orient);
+
+ if (pbar) {
+ double fraction = value / maximum;
+ Ttk_Box parcel = Ttk_ClientRegion(corePtr->layout, "trough");
+
+ if (pb->progress.mode == TTK_PROGRESSBAR_DETERMINATE) {
+ ProgressbarDeterminateLayout(
+ pb, pbar, parcel, fraction, orient);
+ } else {
+ ProgressbarIndeterminateLayout(
+ pb, pbar, parcel, fraction, orient);
+ }
+ }
+}
+
+static Ttk_Layout ProgressbarGetLayout(
+ Tcl_Interp *interp, Ttk_Theme theme, void *recordPtr)
+{
+ Progressbar *pb = recordPtr;
+ Ttk_Layout layout = TtkWidgetGetOrientedLayout(
+ interp, theme, recordPtr, pb->progress.orientObj);
+
+ /*
+ * Check if the style supports animation:
+ */
+ pb->progress.period = 0;
+ pb->progress.maxPhase = 0;
+ if (layout) {
+ Tcl_Obj *periodObj = Ttk_QueryOption(layout,"-period", 0);
+ Tcl_Obj *maxPhaseObj = Ttk_QueryOption(layout,"-maxphase", 0);
+ if (periodObj)
+ Tcl_GetIntFromObj(NULL, periodObj, &pb->progress.period);
+ if (maxPhaseObj)
+ Tcl_GetIntFromObj(NULL, maxPhaseObj, &pb->progress.maxPhase);
+ }
+
+ return layout;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Widget commands:
+ */
+
+/* $sb step ?amount?
+ */
+static int ProgressbarStepCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Progressbar *pb = recordPtr;
+ double value = 0.0, stepAmount = 1.0;
+ Tcl_Obj *newValueObj;
+
+ if (objc == 3) {
+ if (Tcl_GetDoubleFromObj(interp, objv[2], &stepAmount) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ } else if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2,objv, "?stepAmount?");
+ return TCL_ERROR;
+ }
+
+ (void)Tcl_GetDoubleFromObj(NULL, pb->progress.valueObj, &value);
+ value += stepAmount;
+
+ /* In determinate mode, wrap around if value exceeds maximum:
+ */
+ if (pb->progress.mode == TTK_PROGRESSBAR_DETERMINATE) {
+ double maximum = 100.0;
+ (void)Tcl_GetDoubleFromObj(NULL, pb->progress.maximumObj, &maximum);
+ value = fmod(value, maximum);
+ }
+
+ newValueObj = Tcl_NewDoubleObj(value);
+ Tcl_IncrRefCount(newValueObj);
+
+ TtkRedisplayWidget(&pb->core);
+
+ /* Update value by setting the linked -variable, if there is one:
+ */
+ if (pb->progress.variableTrace) {
+ int result = Tcl_ObjSetVar2(
+ interp, pb->progress.variableObj, 0, newValueObj,
+ TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG)
+ ? TCL_OK : TCL_ERROR;
+ Tcl_DecrRefCount(newValueObj);
+ return result;
+ }
+
+ /* Otherwise, change the -value directly:
+ */
+ Tcl_DecrRefCount(pb->progress.valueObj);
+ pb->progress.valueObj = newValueObj;
+ CheckAnimation(pb);
+
+ return TCL_OK;
+}
+
+/* $sb start|stop ?args? --
+ * Change [$sb $cmd ...] to [ttk::progressbar::$cmd ...]
+ * and pass to interpreter.
+ */
+static int ProgressbarStartStopCommand(
+ Tcl_Interp *interp, const char *cmdName, int objc, Tcl_Obj *const objv[])
+{
+ Tcl_Obj *cmd = Tcl_NewListObj(objc, objv);
+ Tcl_Obj *prefix[2];
+ int status;
+
+ /* ASSERT: objc >= 2 */
+
+ prefix[0] = Tcl_NewStringObj(cmdName, -1);
+ prefix[1] = objv[0];
+ Tcl_ListObjReplace(interp, cmd, 0,2, 2,prefix);
+
+ Tcl_IncrRefCount(cmd);
+ status = Tcl_EvalObjEx(interp, cmd, 0);
+ Tcl_DecrRefCount(cmd);
+
+ return status;
+}
+
+static int ProgressbarStartCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ return ProgressbarStartStopCommand(
+ interp, "::ttk::progressbar::start", objc, objv);
+}
+
+static int ProgressbarStopCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ return ProgressbarStartStopCommand(
+ interp, "::ttk::progressbar::stop", objc, objv);
+}
+
+static const Ttk_Ensemble ProgressbarCommands[] = {
+ { "configure", TtkWidgetConfigureCommand,0 },
+ { "cget", TtkWidgetCgetCommand,0 },
+ { "identify", TtkWidgetIdentifyCommand,0 },
+ { "instate", TtkWidgetInstateCommand,0 },
+ { "start", ProgressbarStartCommand,0 },
+ { "state", TtkWidgetStateCommand,0 },
+ { "step", ProgressbarStepCommand,0 },
+ { "stop", ProgressbarStopCommand,0 },
+ { 0,0,0 }
+};
+
+/*
+ * Widget specification:
+ */
+static WidgetSpec ProgressbarWidgetSpec =
+{
+ "TProgressbar", /* className */
+ sizeof(Progressbar), /* recordSize */
+ ProgressbarOptionSpecs, /* optionSpecs */
+ ProgressbarCommands, /* subcommands */
+ ProgressbarInitialize, /* initializeProc */
+ ProgressbarCleanup, /* cleanupProc */
+ ProgressbarConfigure, /* configureProc */
+ ProgressbarPostConfigure, /* postConfigureProc */
+ ProgressbarGetLayout, /* getLayoutProc */
+ ProgressbarSize, /* sizeProc */
+ ProgressbarDoLayout, /* layoutProc */
+ TtkWidgetDisplay /* displayProc */
+};
+
+/*
+ * Layouts:
+ */
+TTK_BEGIN_LAYOUT(VerticalProgressbarLayout)
+ TTK_GROUP("Vertical.Progressbar.trough", TTK_FILL_BOTH,
+ TTK_NODE("Vertical.Progressbar.pbar", TTK_PACK_BOTTOM|TTK_FILL_X))
+TTK_END_LAYOUT
+
+TTK_BEGIN_LAYOUT(HorizontalProgressbarLayout)
+ TTK_GROUP("Horizontal.Progressbar.trough", TTK_FILL_BOTH,
+ TTK_NODE("Horizontal.Progressbar.pbar", TTK_PACK_LEFT|TTK_FILL_Y))
+TTK_END_LAYOUT
+
+/*
+ * Initialization:
+ */
+
+MODULE_SCOPE
+void TtkProgressbar_Init(Tcl_Interp *interp)
+{
+ Ttk_Theme themePtr = Ttk_GetDefaultTheme(interp);
+
+ Ttk_RegisterLayout(themePtr,
+ "Vertical.TProgressbar", VerticalProgressbarLayout);
+ Ttk_RegisterLayout(themePtr,
+ "Horizontal.TProgressbar", HorizontalProgressbarLayout);
+
+ RegisterWidget(interp, "ttk::progressbar", &ProgressbarWidgetSpec);
+}
+
+/*EOF*/
diff --git a/tk8.6/generic/ttk/ttkScale.c b/tk8.6/generic/ttk/ttkScale.c
new file mode 100644
index 0000000..279fc7a
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkScale.c
@@ -0,0 +1,532 @@
+/*
+ * Copyright (C) 2004 Pat Thoyts <patthoyts@users.sourceforge.net>
+ *
+ * ttk::scale widget.
+ */
+
+#include <tk.h>
+#include <string.h>
+#include <stdio.h>
+#include "ttkTheme.h"
+#include "ttkWidget.h"
+
+#define DEF_SCALE_LENGTH "100"
+
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+/* Bit fields for OptionSpec mask field:
+ */
+#define STATE_CHANGED (0x100) /* -state option changed */
+
+/*
+ * Scale widget record
+ */
+typedef struct
+{
+ /* slider element options */
+ Tcl_Obj *fromObj; /* minimum value */
+ Tcl_Obj *toObj; /* maximum value */
+ Tcl_Obj *valueObj; /* current value */
+ Tcl_Obj *lengthObj; /* length of the long axis of the scale */
+ Tcl_Obj *orientObj; /* widget orientation */
+ int orient;
+
+ /* widget options */
+ Tcl_Obj *commandObj;
+ Tcl_Obj *variableObj;
+
+ /* internal state */
+ Ttk_TraceHandle *variableTrace;
+
+ /*
+ * Compatibility/legacy options:
+ */
+ Tcl_Obj *stateObj;
+
+} ScalePart;
+
+typedef struct
+{
+ WidgetCore core;
+ ScalePart scale;
+} Scale;
+
+static Tk_OptionSpec ScaleOptionSpecs[] =
+{
+ {TK_OPTION_STRING, "-command", "command", "Command", "",
+ Tk_Offset(Scale,scale.commandObj), -1,
+ TK_OPTION_NULL_OK,0,0},
+ {TK_OPTION_STRING, "-variable", "variable", "Variable", "",
+ Tk_Offset(Scale,scale.variableObj), -1,
+ 0,0,0},
+ {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient", "horizontal",
+ Tk_Offset(Scale,scale.orientObj),
+ Tk_Offset(Scale,scale.orient), 0,
+ (ClientData)ttkOrientStrings, STYLE_CHANGED },
+
+ {TK_OPTION_DOUBLE, "-from", "from", "From", "0",
+ Tk_Offset(Scale,scale.fromObj), -1, 0, 0, 0},
+ {TK_OPTION_DOUBLE, "-to", "to", "To", "1.0",
+ Tk_Offset(Scale,scale.toObj), -1, 0, 0, 0},
+ {TK_OPTION_DOUBLE, "-value", "value", "Value", "0",
+ Tk_Offset(Scale,scale.valueObj), -1, 0, 0, 0},
+ {TK_OPTION_PIXELS, "-length", "length", "Length",
+ DEF_SCALE_LENGTH, Tk_Offset(Scale,scale.lengthObj), -1, 0, 0,
+ GEOMETRY_CHANGED},
+
+ {TK_OPTION_STRING, "-state", "state", "State",
+ "normal", Tk_Offset(Scale,scale.stateObj), -1,
+ 0,0,STATE_CHANGED},
+
+ WIDGET_TAKEFOCUS_TRUE,
+ WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)
+};
+
+static XPoint ValueToPoint(Scale *scalePtr, double value);
+static double PointToValue(Scale *scalePtr, int x, int y);
+
+/* ScaleVariableChanged --
+ * Variable trace procedure for scale -variable;
+ * Updates the scale's value.
+ * If the linked variable is not a valid double,
+ * sets the 'invalid' state.
+ */
+static void ScaleVariableChanged(void *recordPtr, const char *value)
+{
+ Scale *scale = recordPtr;
+ double v;
+
+ if (value == NULL || Tcl_GetDouble(0, value, &v) != TCL_OK) {
+ TtkWidgetChangeState(&scale->core, TTK_STATE_INVALID, 0);
+ } else {
+ Tcl_Obj *valueObj = Tcl_NewDoubleObj(v);
+ Tcl_IncrRefCount(valueObj);
+ Tcl_DecrRefCount(scale->scale.valueObj);
+ scale->scale.valueObj = valueObj;
+ TtkWidgetChangeState(&scale->core, 0, TTK_STATE_INVALID);
+ }
+ TtkRedisplayWidget(&scale->core);
+}
+
+/* ScaleInitialize --
+ * Scale widget initialization hook.
+ */
+static void ScaleInitialize(Tcl_Interp *interp, void *recordPtr)
+{
+ Scale *scalePtr = recordPtr;
+ TtkTrackElementState(&scalePtr->core);
+}
+
+static void ScaleCleanup(void *recordPtr)
+{
+ Scale *scale = recordPtr;
+
+ if (scale->scale.variableTrace) {
+ Ttk_UntraceVariable(scale->scale.variableTrace);
+ scale->scale.variableTrace = 0;
+ }
+}
+
+/* ScaleConfigure --
+ * Configuration hook.
+ */
+static int ScaleConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
+{
+ Scale *scale = recordPtr;
+ Tcl_Obj *varName = scale->scale.variableObj;
+ Ttk_TraceHandle *vt = 0;
+
+ if (varName != NULL && *Tcl_GetString(varName) != '\0') {
+ vt = Ttk_TraceVariable(interp,varName, ScaleVariableChanged,recordPtr);
+ if (!vt) return TCL_ERROR;
+ }
+
+ if (TtkCoreConfigure(interp, recordPtr, mask) != TCL_OK) {
+ if (vt) Ttk_UntraceVariable(vt);
+ return TCL_ERROR;
+ }
+
+ if (scale->scale.variableTrace) {
+ Ttk_UntraceVariable(scale->scale.variableTrace);
+ }
+ scale->scale.variableTrace = vt;
+
+ if (mask & STATE_CHANGED) {
+ TtkCheckStateOption(&scale->core, scale->scale.stateObj);
+ }
+
+ return TCL_OK;
+}
+
+/* ScalePostConfigure --
+ * Post-configuration hook.
+ */
+static int ScalePostConfigure(
+ Tcl_Interp *interp, void *recordPtr, int mask)
+{
+ Scale *scale = recordPtr;
+ int status = TCL_OK;
+
+ if (scale->scale.variableTrace) {
+ status = Ttk_FireTrace(scale->scale.variableTrace);
+ if (WidgetDestroyed(&scale->core)) {
+ return TCL_ERROR;
+ }
+ if (status != TCL_OK) {
+ /* Unset -variable: */
+ Ttk_UntraceVariable(scale->scale.variableTrace);
+ Tcl_DecrRefCount(scale->scale.variableObj);
+ scale->scale.variableTrace = 0;
+ scale->scale.variableObj = NULL;
+ status = TCL_ERROR;
+ }
+ }
+
+ return status;
+}
+
+/* ScaleGetLayout --
+ * getLayout hook.
+ */
+static Ttk_Layout
+ScaleGetLayout(Tcl_Interp *interp, Ttk_Theme theme, void *recordPtr)
+{
+ Scale *scalePtr = recordPtr;
+ return TtkWidgetGetOrientedLayout(
+ interp, theme, recordPtr, scalePtr->scale.orientObj);
+}
+
+/*
+ * TroughBox --
+ * Returns the inner area of the trough element.
+ */
+static Ttk_Box TroughBox(Scale *scalePtr)
+{
+ return Ttk_ClientRegion(scalePtr->core.layout, "trough");
+}
+
+/*
+ * TroughRange --
+ * Return the value area of the trough element, adjusted
+ * for slider size.
+ */
+static Ttk_Box TroughRange(Scale *scalePtr)
+{
+ Ttk_Box troughBox = TroughBox(scalePtr);
+ Ttk_Element slider = Ttk_FindElement(scalePtr->core.layout,"slider");
+
+ /*
+ * If this is a scale widget, adjust range for slider:
+ */
+ if (slider) {
+ Ttk_Box sliderBox = Ttk_ElementParcel(slider);
+ if (scalePtr->scale.orient == TTK_ORIENT_HORIZONTAL) {
+ troughBox.x += sliderBox.width / 2;
+ troughBox.width -= sliderBox.width;
+ } else {
+ troughBox.y += sliderBox.height / 2;
+ troughBox.height -= sliderBox.height;
+ }
+ }
+
+ return troughBox;
+}
+
+/*
+ * ScaleFraction --
+ */
+static double ScaleFraction(Scale *scalePtr, double value)
+{
+ double from = 0, to = 1, fraction;
+
+ Tcl_GetDoubleFromObj(NULL, scalePtr->scale.fromObj, &from);
+ Tcl_GetDoubleFromObj(NULL, scalePtr->scale.toObj, &to);
+
+ if (from == to) {
+ return 1.0;
+ }
+
+ fraction = (value - from) / (to - from);
+
+ return fraction < 0 ? 0 : fraction > 1 ? 1 : fraction;
+}
+
+/* $scale get ?x y? --
+ * Returns the current value of the scale widget, or if $x and
+ * $y are specified, the value represented by point @x,y.
+ */
+static int
+ScaleGetCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Scale *scalePtr = recordPtr;
+ int x, y, r = TCL_OK;
+ double value = 0;
+
+ if ((objc != 2) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "get ?x y?");
+ return TCL_ERROR;
+ }
+ if (objc == 2) {
+ Tcl_SetObjResult(interp, scalePtr->scale.valueObj);
+ } else {
+ r = Tcl_GetIntFromObj(interp, objv[2], &x);
+ if (r == TCL_OK)
+ r = Tcl_GetIntFromObj(interp, objv[3], &y);
+ if (r == TCL_OK) {
+ value = PointToValue(scalePtr, x, y);
+ Tcl_SetObjResult(interp, Tcl_NewDoubleObj(value));
+ }
+ }
+ return r;
+}
+
+/* $scale set $newValue
+ */
+static int
+ScaleSetCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Scale *scalePtr = recordPtr;
+ double from = 0.0, to = 1.0, value;
+ int result = TCL_OK;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "set value");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetDoubleFromObj(interp, objv[2], &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (scalePtr->core.state & TTK_STATE_DISABLED) {
+ return TCL_OK;
+ }
+
+ /* ASSERT: fromObj and toObj are valid doubles.
+ */
+ Tcl_GetDoubleFromObj(interp, scalePtr->scale.fromObj, &from);
+ Tcl_GetDoubleFromObj(interp, scalePtr->scale.toObj, &to);
+
+ /* Limit new value to between 'from' and 'to':
+ */
+ if (from < to) {
+ value = value < from ? from : value > to ? to : value;
+ } else {
+ value = value < to ? to : value > from ? from : value;
+ }
+
+ /*
+ * Set value:
+ */
+ Tcl_DecrRefCount(scalePtr->scale.valueObj);
+ scalePtr->scale.valueObj = Tcl_NewDoubleObj(value);
+ Tcl_IncrRefCount(scalePtr->scale.valueObj);
+ TtkRedisplayWidget(&scalePtr->core);
+
+ /*
+ * Set attached variable, if any:
+ */
+ if (scalePtr->scale.variableObj != NULL) {
+ Tcl_ObjSetVar2(interp, scalePtr->scale.variableObj, NULL,
+ scalePtr->scale.valueObj, TCL_GLOBAL_ONLY);
+ }
+ if (WidgetDestroyed(&scalePtr->core)) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Invoke -command, if any:
+ */
+ if (scalePtr->scale.commandObj != NULL) {
+ Tcl_Obj *cmdObj = Tcl_DuplicateObj(scalePtr->scale.commandObj);
+ Tcl_IncrRefCount(cmdObj);
+ Tcl_AppendToObj(cmdObj, " ", 1);
+ Tcl_AppendObjToObj(cmdObj, scalePtr->scale.valueObj);
+ result = Tcl_EvalObjEx(interp, cmdObj, TCL_EVAL_GLOBAL);
+ Tcl_DecrRefCount(cmdObj);
+ }
+
+ return result;
+}
+
+static int
+ScaleCoordsCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Scale *scalePtr = recordPtr;
+ double value;
+ int r = TCL_OK;
+
+ if (objc < 2 || objc > 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "coords ?value?");
+ return TCL_ERROR;
+ }
+
+ if (objc == 3) {
+ r = Tcl_GetDoubleFromObj(interp, objv[2], &value);
+ } else {
+ r = Tcl_GetDoubleFromObj(interp, scalePtr->scale.valueObj, &value);
+ }
+
+ if (r == TCL_OK) {
+ Tcl_Obj *point[2];
+ XPoint pt = ValueToPoint(scalePtr, value);
+ point[0] = Tcl_NewIntObj(pt.x);
+ point[1] = Tcl_NewIntObj(pt.y);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(2, point));
+ }
+ return r;
+}
+
+static void ScaleDoLayout(void *clientData)
+{
+ WidgetCore *corePtr = clientData;
+ Ttk_Element slider = Ttk_FindElement(corePtr->layout, "slider");
+
+ Ttk_PlaceLayout(corePtr->layout,corePtr->state,Ttk_WinBox(corePtr->tkwin));
+
+ /* Adjust the slider position:
+ */
+ if (slider) {
+ Scale *scalePtr = clientData;
+ Ttk_Box troughBox = TroughBox(scalePtr);
+ Ttk_Box sliderBox = Ttk_ElementParcel(slider);
+ double value = 0.0;
+ double fraction;
+ int range;
+
+ Tcl_GetDoubleFromObj(NULL, scalePtr->scale.valueObj, &value);
+ fraction = ScaleFraction(scalePtr, value);
+
+ if (scalePtr->scale.orient == TTK_ORIENT_HORIZONTAL) {
+ range = troughBox.width - sliderBox.width;
+ sliderBox.x += (int)(fraction * range);
+ } else {
+ range = troughBox.height - sliderBox.height;
+ sliderBox.y += (int)(fraction * range);
+ }
+ Ttk_PlaceElement(corePtr->layout, slider, sliderBox);
+ }
+}
+
+/*
+ * ScaleSize --
+ * Compute requested size of scale.
+ */
+static int ScaleSize(void *clientData, int *widthPtr, int *heightPtr)
+{
+ WidgetCore *corePtr = clientData;
+ Scale *scalePtr = clientData;
+ int length;
+
+ Ttk_LayoutSize(corePtr->layout, corePtr->state, widthPtr, heightPtr);
+
+ /* Assert the -length configuration option */
+ Tk_GetPixelsFromObj(NULL, corePtr->tkwin,
+ scalePtr->scale.lengthObj, &length);
+ if (scalePtr->scale.orient == TTK_ORIENT_VERTICAL) {
+ *heightPtr = MAX(*heightPtr, length);
+ } else {
+ *widthPtr = MAX(*widthPtr, length);
+ }
+
+ return 1;
+}
+
+static double
+PointToValue(Scale *scalePtr, int x, int y)
+{
+ Ttk_Box troughBox = TroughRange(scalePtr);
+ double from = 0, to = 1, fraction;
+
+ Tcl_GetDoubleFromObj(NULL, scalePtr->scale.fromObj, &from);
+ Tcl_GetDoubleFromObj(NULL, scalePtr->scale.toObj, &to);
+
+ if (scalePtr->scale.orient == TTK_ORIENT_HORIZONTAL) {
+ fraction = (double)(x - troughBox.x) / (double)troughBox.width;
+ } else {
+ fraction = (double)(y - troughBox.y) / (double)troughBox.height;
+ }
+
+ fraction = fraction < 0 ? 0 : fraction > 1 ? 1 : fraction;
+
+ return from + fraction * (to-from);
+}
+
+/*
+ * Return the center point in the widget corresponding to the given
+ * value. This point can be used to center the slider.
+ */
+
+static XPoint
+ValueToPoint(Scale *scalePtr, double value)
+{
+ Ttk_Box troughBox = TroughRange(scalePtr);
+ double fraction = ScaleFraction(scalePtr, value);
+ XPoint pt = {0, 0};
+
+ if (scalePtr->scale.orient == TTK_ORIENT_HORIZONTAL) {
+ pt.x = troughBox.x + (int)(fraction * troughBox.width);
+ pt.y = troughBox.y + troughBox.height / 2;
+ } else {
+ pt.x = troughBox.x + troughBox.width / 2;
+ pt.y = troughBox.y + (int)(fraction * troughBox.height);
+ }
+ return pt;
+}
+
+static const Ttk_Ensemble ScaleCommands[] = {
+ { "configure", TtkWidgetConfigureCommand,0 },
+ { "cget", TtkWidgetCgetCommand,0 },
+ { "state", TtkWidgetStateCommand,0 },
+ { "instate", TtkWidgetInstateCommand,0 },
+ { "identify", TtkWidgetIdentifyCommand,0 },
+ { "set", ScaleSetCommand,0 },
+ { "get", ScaleGetCommand,0 },
+ { "coords", ScaleCoordsCommand,0 },
+ { 0,0,0 }
+};
+
+static WidgetSpec ScaleWidgetSpec =
+{
+ "TScale", /* Class name */
+ sizeof(Scale), /* record size */
+ ScaleOptionSpecs, /* option specs */
+ ScaleCommands, /* widget commands */
+ ScaleInitialize, /* initialization proc */
+ ScaleCleanup, /* cleanup proc */
+ ScaleConfigure, /* configure proc */
+ ScalePostConfigure, /* postConfigure */
+ ScaleGetLayout, /* getLayoutProc */
+ ScaleSize, /* sizeProc */
+ ScaleDoLayout, /* layoutProc */
+ TtkWidgetDisplay /* displayProc */
+};
+
+TTK_BEGIN_LAYOUT(VerticalScaleLayout)
+ TTK_GROUP("Vertical.Scale.trough", TTK_FILL_BOTH,
+ TTK_NODE("Vertical.Scale.slider", TTK_PACK_TOP) )
+TTK_END_LAYOUT
+
+TTK_BEGIN_LAYOUT(HorizontalScaleLayout)
+ TTK_GROUP("Horizontal.Scale.trough", TTK_FILL_BOTH,
+ TTK_NODE("Horizontal.Scale.slider", TTK_PACK_LEFT) )
+TTK_END_LAYOUT
+
+/*
+ * Initialization.
+ */
+MODULE_SCOPE
+void TtkScale_Init(Tcl_Interp *interp)
+{
+ Ttk_Theme theme = Ttk_GetDefaultTheme(interp);
+
+ Ttk_RegisterLayout(theme, "Vertical.TScale", VerticalScaleLayout);
+ Ttk_RegisterLayout(theme, "Horizontal.TScale", HorizontalScaleLayout);
+
+ RegisterWidget(interp, "ttk::scale", &ScaleWidgetSpec);
+}
+
diff --git a/tk8.6/generic/ttk/ttkScroll.c b/tk8.6/generic/ttk/ttkScroll.c
new file mode 100644
index 0000000..47db6ac
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkScroll.c
@@ -0,0 +1,278 @@
+/*
+ * Copyright 2004, Joe English
+ *
+ * Support routines for scrollable widgets.
+ *
+ * (This is sort of half-baked; needs some work)
+ *
+ * Scrollable interface:
+ *
+ * + 'first' is controlled by [xy]view widget command
+ * and other scrolling commands like 'see';
+ * + 'total' depends on widget contents;
+ * + 'last' depends on first, total, and widget size.
+ *
+ * Choreography (typical usage):
+ *
+ * 1. User adjusts scrollbar, scrollbar widget calls its -command
+ * 2. Scrollbar -command invokes the scrollee [xy]view widget method
+ * 3. TtkScrollviewCommand calls TtkScrollTo(), which updates
+ * 'first' and schedules a redisplay.
+ * 4. Once the scrollee knows 'total' and 'last' (typically in
+ * the LayoutProc), call TtkScrolled(h,first,last,total) to
+ * synchronize the scrollbar.
+ * 5. The scrollee -[xy]scrollcommand is called (in an idle callback)
+ * 6. Which calls the scrollbar 'set' method and redisplays the scrollbar.
+ *
+ * If the scrollee has internal scrolling (e.g., a 'see' method),
+ * it should TtkScrollTo() directly (step 2).
+ *
+ * If the widget value changes, it should call TtkScrolled() (step 4).
+ * (This usually happens automatically when the widget is redisplayed).
+ *
+ * If the scrollee's -[xy]scrollcommand changes, it should call
+ * TtkScrollbarUpdateRequired, which will invoke step (5) (@@@ Fix this)
+ */
+
+#include "tkInt.h"
+#include "ttkTheme.h"
+#include "ttkWidget.h"
+
+/* Private data:
+ */
+#define SCROLL_UPDATE_PENDING (0x1)
+#define SCROLL_UPDATE_REQUIRED (0x2)
+
+struct ScrollHandleRec
+{
+ unsigned flags;
+ WidgetCore *corePtr;
+ Scrollable *scrollPtr;
+};
+
+/* TtkCreateScrollHandle --
+ * Initialize scroll handle.
+ */
+ScrollHandle TtkCreateScrollHandle(WidgetCore *corePtr, Scrollable *scrollPtr)
+{
+ ScrollHandle h = ckalloc(sizeof(*h));
+
+ h->flags = 0;
+ h->corePtr = corePtr;
+ h->scrollPtr = scrollPtr;
+
+ scrollPtr->first = 0;
+ scrollPtr->last = 1;
+ scrollPtr->total = 1;
+ return h;
+}
+
+/* UpdateScrollbar --
+ * Call the -scrollcommand callback to sync the scrollbar.
+ * Returns: Whatever the -scrollcommand does.
+ */
+static int UpdateScrollbar(Tcl_Interp *interp, ScrollHandle h)
+{
+ Scrollable *s = h->scrollPtr;
+ WidgetCore *corePtr = h->corePtr;
+ char arg1[TCL_DOUBLE_SPACE + 2];
+ char arg2[TCL_DOUBLE_SPACE + 2];
+ int code;
+ Tcl_DString buf;
+
+ h->flags &= ~SCROLL_UPDATE_REQUIRED;
+
+ if (s->scrollCmd == NULL) {
+ return TCL_OK;
+ }
+
+ arg1[0] = arg2[0] = ' ';
+ Tcl_PrintDouble(interp, (double)s->first / s->total, arg1+1);
+ Tcl_PrintDouble(interp, (double)s->last / s->total, arg2+1);
+ Tcl_DStringInit(&buf);
+ Tcl_DStringAppend(&buf, s->scrollCmd, -1);
+ Tcl_DStringAppend(&buf, arg1, -1);
+ Tcl_DStringAppend(&buf, arg2, -1);
+
+ Tcl_Preserve(corePtr);
+ code = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, TCL_EVAL_GLOBAL);
+ Tcl_DStringFree(&buf);
+ if (WidgetDestroyed(corePtr)) {
+ Tcl_Release(corePtr);
+ return TCL_ERROR;
+ }
+ Tcl_Release(corePtr);
+
+ if (code != TCL_OK && !Tcl_InterpDeleted(interp)) {
+ /* Disable the -scrollcommand, add to stack trace:
+ */
+ ckfree(s->scrollCmd);
+ s->scrollCmd = 0;
+
+ Tcl_AddErrorInfo(interp, /* @@@ "horizontal" / "vertical" */
+ "\n (scrolling command executed by ");
+ Tcl_AddErrorInfo(interp, Tk_PathName(h->corePtr->tkwin));
+ Tcl_AddErrorInfo(interp, ")");
+ }
+ return code;
+}
+
+/* UpdateScrollbarBG --
+ * Idle handler to update the scrollbar.
+ */
+static void UpdateScrollbarBG(ClientData clientData)
+{
+ ScrollHandle h = (ScrollHandle)clientData;
+ Tcl_Interp *interp = h->corePtr->interp;
+ int code;
+
+ h->flags &= ~SCROLL_UPDATE_PENDING;
+ Tcl_Preserve((ClientData) interp);
+ code = UpdateScrollbar(interp, h);
+ if (code == TCL_ERROR && !Tcl_InterpDeleted(interp)) {
+ Tcl_BackgroundException(interp, code);
+ }
+ Tcl_Release((ClientData) interp);
+}
+
+/* TtkScrolled --
+ * Update scroll info, schedule scrollbar update.
+ */
+void TtkScrolled(ScrollHandle h, int first, int last, int total)
+{
+ Scrollable *s = h->scrollPtr;
+
+ /* Sanity-check inputs:
+ */
+ if (total <= 0) {
+ first = 0;
+ last = 1;
+ total = 1;
+ }
+
+ if (last > total) {
+ first -= (last - total);
+ if (first < 0) first = 0;
+ last = total;
+ }
+
+ if (s->first != first || s->last != last || s->total != total
+ || (h->flags & SCROLL_UPDATE_REQUIRED))
+ {
+ s->first = first;
+ s->last = last;
+ s->total = total;
+
+ if (!(h->flags & SCROLL_UPDATE_PENDING)) {
+ Tcl_DoWhenIdle(UpdateScrollbarBG, (ClientData)h);
+ h->flags |= SCROLL_UPDATE_PENDING;
+ }
+ }
+}
+
+/* TtkScrollbarUpdateRequired --
+ * Force a scrollbar update at the next call to TtkScrolled(),
+ * even if scroll parameters haven't changed (e.g., if
+ * -yscrollcommand has changed).
+ */
+
+void TtkScrollbarUpdateRequired(ScrollHandle h)
+{
+ h->flags |= SCROLL_UPDATE_REQUIRED;
+}
+
+/* TtkUpdateScrollInfo --
+ * Call the layoutProc to update the scroll info first, last, and total.
+ * Do it only if needed, that is when a redisplay is pending (which
+ * indicates scroll info are possibly out of date).
+ */
+
+void TtkUpdateScrollInfo(ScrollHandle h)
+{
+ if (h->corePtr->flags & REDISPLAY_PENDING) {
+ h->corePtr->widgetSpec->layoutProc(h->corePtr);
+ }
+}
+
+/* TtkScrollviewCommand --
+ * Widget [xy]view command implementation.
+ *
+ * $w [xy]view -- return current view region
+ * $w [xy]view $index -- set topmost item
+ * $w [xy]view moveto $fraction
+ * $w [xy]view scroll $number $what -- scrollbar interface
+ */
+int TtkScrollviewCommand(
+ Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], ScrollHandle h)
+{
+ Scrollable *s = h->scrollPtr;
+ int newFirst;
+
+ TtkUpdateScrollInfo(h);
+ newFirst = s->first;
+
+ if (objc == 2) {
+ Tcl_Obj *result[2];
+ result[0] = Tcl_NewDoubleObj((double)s->first / s->total);
+ result[1] = Tcl_NewDoubleObj((double)s->last / s->total);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(2, result));
+ return TCL_OK;
+ } else if (objc == 3) {
+ if (Tcl_GetIntFromObj(interp, objv[2], &newFirst) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ } else {
+ double fraction;
+ int count;
+
+ switch (Tk_GetScrollInfoObj(interp, objc, objv, &fraction, &count)) {
+ case TK_SCROLL_ERROR:
+ return TCL_ERROR;
+ case TK_SCROLL_MOVETO:
+ newFirst = (int) ((fraction * s->total) + 0.5);
+ break;
+ case TK_SCROLL_UNITS:
+ newFirst = s->first + count;
+ break;
+ case TK_SCROLL_PAGES: {
+ int perPage = s->last - s->first; /* @@@ */
+ newFirst = s->first + count * perPage;
+ break;
+ }
+ }
+ }
+
+ TtkScrollTo(h, newFirst, 0);
+
+ return TCL_OK;
+}
+
+void TtkScrollTo(ScrollHandle h, int newFirst, int updateScrollInfo)
+{
+ Scrollable *s = h->scrollPtr;
+
+ if (updateScrollInfo) {
+ TtkUpdateScrollInfo(h);
+ }
+
+ if (newFirst >= s->total)
+ newFirst = s->total - 1;
+ if (newFirst > s->first && s->last >= s->total) /* don't scroll past end */
+ newFirst = s->first;
+ if (newFirst < 0)
+ newFirst = 0;
+
+ if (newFirst != s->first) {
+ s->first = newFirst;
+ TtkRedisplayWidget(h->corePtr);
+ }
+}
+
+void TtkFreeScrollHandle(ScrollHandle h)
+{
+ if (h->flags & SCROLL_UPDATE_PENDING) {
+ Tcl_CancelIdleCall(UpdateScrollbarBG, (ClientData)h);
+ }
+ ckfree(h);
+}
+
diff --git a/tk8.6/generic/ttk/ttkScrollbar.c b/tk8.6/generic/ttk/ttkScrollbar.c
new file mode 100644
index 0000000..5b0c212
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkScrollbar.c
@@ -0,0 +1,345 @@
+/*
+ * Copyright (c) 2003, Joe English
+ *
+ * ttk::scrollbar widget.
+ */
+
+#include <tk.h>
+
+#include "ttkTheme.h"
+#include "ttkWidget.h"
+
+/*------------------------------------------------------------------------
+ * +++ Scrollbar widget record.
+ */
+typedef struct
+{
+ Tcl_Obj *commandObj;
+
+ int orient;
+ Tcl_Obj *orientObj;
+
+ double first; /* top fraction */
+ double last; /* bottom fraction */
+
+ Ttk_Box troughBox; /* trough parcel */
+ int minSize; /* minimum size of thumb */
+} ScrollbarPart;
+
+typedef struct
+{
+ WidgetCore core;
+ ScrollbarPart scrollbar;
+} Scrollbar;
+
+static Tk_OptionSpec ScrollbarOptionSpecs[] =
+{
+ {TK_OPTION_STRING, "-command", "command", "Command", "",
+ Tk_Offset(Scrollbar,scrollbar.commandObj), -1, 0,0,0},
+
+ {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient", "vertical",
+ Tk_Offset(Scrollbar,scrollbar.orientObj),
+ Tk_Offset(Scrollbar,scrollbar.orient),
+ 0,(ClientData)ttkOrientStrings,STYLE_CHANGED },
+
+ WIDGET_TAKEFOCUS_FALSE,
+ WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)
+};
+
+/*------------------------------------------------------------------------
+ * +++ Widget hooks.
+ */
+
+static void
+ScrollbarInitialize(Tcl_Interp *interp, void *recordPtr)
+{
+ Scrollbar *sb = recordPtr;
+ sb->scrollbar.first = 0.0;
+ sb->scrollbar.last = 1.0;
+
+ TtkTrackElementState(&sb->core);
+}
+
+static Ttk_Layout ScrollbarGetLayout(
+ Tcl_Interp *interp, Ttk_Theme theme, void *recordPtr)
+{
+ Scrollbar *sb = recordPtr;
+ return TtkWidgetGetOrientedLayout(
+ interp, theme, recordPtr, sb->scrollbar.orientObj);
+}
+
+/*
+ * ScrollbarDoLayout --
+ * Layout hook. Adjusts the position of the scrollbar thumb.
+ *
+ * Side effects:
+ * Sets sb->troughBox and sb->minSize.
+ */
+static void ScrollbarDoLayout(void *recordPtr)
+{
+ Scrollbar *sb = recordPtr;
+ WidgetCore *corePtr = &sb->core;
+ Ttk_Element thumb;
+ Ttk_Box thumbBox;
+ int thumbWidth, thumbHeight;
+ double first, last, size;
+ int minSize;
+
+ /*
+ * Use generic layout manager to compute initial layout:
+ */
+ Ttk_PlaceLayout(corePtr->layout,corePtr->state,Ttk_WinBox(corePtr->tkwin));
+
+ /*
+ * Locate thumb element, extract parcel and requested minimum size:
+ */
+ thumb = Ttk_FindElement(corePtr->layout, "thumb");
+ if (!thumb) /* Something has gone wrong -- bail */
+ return;
+
+ sb->scrollbar.troughBox = thumbBox = Ttk_ElementParcel(thumb);
+ Ttk_LayoutNodeReqSize(
+ corePtr->layout, thumb, &thumbWidth,&thumbHeight);
+
+ /*
+ * Adjust thumb element parcel:
+ */
+ first = sb->scrollbar.first;
+ last = sb->scrollbar.last;
+
+ if (sb->scrollbar.orient == TTK_ORIENT_VERTICAL) {
+ minSize = thumbHeight;
+ size = thumbBox.height - minSize;
+ thumbBox.y += (int)(size * first);
+ thumbBox.height = (int)(size * last) + minSize - (int)(size * first);
+ } else {
+ minSize = thumbWidth;
+ size = thumbBox.width - minSize;
+ thumbBox.x += (int)(size * first);
+ thumbBox.width = (int)(size * last) + minSize - (int)(size * first);
+ }
+ sb->scrollbar.minSize = minSize;
+ Ttk_PlaceElement(corePtr->layout, thumb, thumbBox);
+}
+
+/*------------------------------------------------------------------------
+ * +++ Widget commands.
+ */
+
+/* $sb set $first $last --
+ * Set the position of the scrollbar.
+ */
+static int
+ScrollbarSetCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Scrollbar *scrollbar = recordPtr;
+ Tcl_Obj *firstObj, *lastObj;
+ double first, last;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "first last");
+ return TCL_ERROR;
+ }
+
+ firstObj = objv[2];
+ lastObj = objv[3];
+ if (Tcl_GetDoubleFromObj(interp, firstObj, &first) != TCL_OK
+ || Tcl_GetDoubleFromObj(interp, lastObj, &last) != TCL_OK)
+ return TCL_ERROR;
+
+ /* Range-checks:
+ */
+ if (first < 0.0) {
+ first = 0.0;
+ } else if (first > 1.0) {
+ first = 1.0;
+ }
+
+ if (last < first) {
+ last = first;
+ } else if (last > 1.0) {
+ last = 1.0;
+ }
+
+ /* ASSERT: 0.0 <= first <= last <= 1.0 */
+
+ scrollbar->scrollbar.first = first;
+ scrollbar->scrollbar.last = last;
+ if (first <= 0.0 && last >= 1.0) {
+ scrollbar->core.state |= TTK_STATE_DISABLED;
+ } else {
+ scrollbar->core.state &= ~TTK_STATE_DISABLED;
+ }
+
+ TtkRedisplayWidget(&scrollbar->core);
+
+ return TCL_OK;
+}
+
+/* $sb get --
+ * Returns the last thing passed to 'set'.
+ */
+static int
+ScrollbarGetCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Scrollbar *scrollbar = recordPtr;
+ Tcl_Obj *result[2];
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, "");
+ return TCL_ERROR;
+ }
+
+ result[0] = Tcl_NewDoubleObj(scrollbar->scrollbar.first);
+ result[1] = Tcl_NewDoubleObj(scrollbar->scrollbar.last);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(2, result));
+
+ return TCL_OK;
+}
+
+/* $sb delta $dx $dy --
+ * Returns the percentage change corresponding to a mouse movement
+ * of $dx, $dy.
+ */
+static int
+ScrollbarDeltaCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Scrollbar *sb = recordPtr;
+ double dx, dy;
+ double delta = 0.0;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "dx dy");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetDoubleFromObj(interp, objv[2], &dx) != TCL_OK
+ || Tcl_GetDoubleFromObj(interp, objv[3], &dy) != TCL_OK)
+ {
+ return TCL_ERROR;
+ }
+
+ delta = 0.0;
+ if (sb->scrollbar.orient == TTK_ORIENT_VERTICAL) {
+ int size = sb->scrollbar.troughBox.height - sb->scrollbar.minSize;
+ if (size > 0) {
+ delta = (double)dy / (double)size;
+ }
+ } else {
+ int size = sb->scrollbar.troughBox.width - sb->scrollbar.minSize;
+ if (size > 0) {
+ delta = (double)dx / (double)size;
+ }
+ }
+
+ Tcl_SetObjResult(interp, Tcl_NewDoubleObj(delta));
+ return TCL_OK;
+}
+
+/* $sb fraction $x $y --
+ * Returns a real number between 0 and 1 indicating where the
+ * point given by x and y lies in the trough area of the scrollbar.
+ */
+static int
+ScrollbarFractionCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Scrollbar *sb = recordPtr;
+ Ttk_Box b = sb->scrollbar.troughBox;
+ int minSize = sb->scrollbar.minSize;
+ double x, y;
+ double fraction = 0.0;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "x y");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetDoubleFromObj(interp, objv[2], &x) != TCL_OK
+ || Tcl_GetDoubleFromObj(interp, objv[3], &y) != TCL_OK)
+ {
+ return TCL_ERROR;
+ }
+
+ fraction = 0.0;
+ if (sb->scrollbar.orient == TTK_ORIENT_VERTICAL) {
+ if (b.height > minSize) {
+ fraction = (double)(y - b.y) / (double)(b.height - minSize);
+ }
+ } else {
+ if (b.width > minSize) {
+ fraction = (double)(x - b.x) / (double)(b.width - minSize);
+ }
+ }
+
+ Tcl_SetObjResult(interp, Tcl_NewDoubleObj(fraction));
+ return TCL_OK;
+}
+
+static const Ttk_Ensemble ScrollbarCommands[] = {
+ { "configure", TtkWidgetConfigureCommand,0 },
+ { "cget", TtkWidgetCgetCommand,0 },
+ { "delta", ScrollbarDeltaCommand,0 },
+ { "fraction", ScrollbarFractionCommand,0 },
+ { "get", ScrollbarGetCommand,0 },
+ { "identify", TtkWidgetIdentifyCommand,0 },
+ { "instate", TtkWidgetInstateCommand,0 },
+ { "set", ScrollbarSetCommand,0 },
+ { "state", TtkWidgetStateCommand,0 },
+ { 0,0,0 }
+};
+
+/*------------------------------------------------------------------------
+ * +++ Widget specification.
+ */
+static WidgetSpec ScrollbarWidgetSpec =
+{
+ "TScrollbar", /* className */
+ sizeof(Scrollbar), /* recordSize */
+ ScrollbarOptionSpecs, /* optionSpecs */
+ ScrollbarCommands, /* subcommands */
+ ScrollbarInitialize, /* initializeProc */
+ TtkNullCleanup, /* cleanupProc */
+ TtkCoreConfigure, /* configureProc */
+ TtkNullPostConfigure, /* postConfigureProc */
+ ScrollbarGetLayout, /* getLayoutProc */
+ TtkWidgetSize, /* sizeProc */
+ ScrollbarDoLayout, /* layoutProc */
+ TtkWidgetDisplay /* displayProc */
+};
+
+TTK_BEGIN_LAYOUT(VerticalScrollbarLayout)
+ TTK_GROUP("Vertical.Scrollbar.trough", TTK_FILL_Y,
+ TTK_NODE("Vertical.Scrollbar.uparrow", TTK_PACK_TOP)
+ TTK_NODE("Vertical.Scrollbar.downarrow", TTK_PACK_BOTTOM)
+ TTK_NODE(
+ "Vertical.Scrollbar.thumb", TTK_PACK_TOP|TTK_EXPAND|TTK_FILL_BOTH))
+TTK_END_LAYOUT
+
+TTK_BEGIN_LAYOUT(HorizontalScrollbarLayout)
+ TTK_GROUP("Horizontal.Scrollbar.trough", TTK_FILL_X,
+ TTK_NODE("Horizontal.Scrollbar.leftarrow", TTK_PACK_LEFT)
+ TTK_NODE("Horizontal.Scrollbar.rightarrow", TTK_PACK_RIGHT)
+ TTK_NODE(
+ "Horizontal.Scrollbar.thumb", TTK_PACK_LEFT|TTK_EXPAND|TTK_FILL_BOTH))
+TTK_END_LAYOUT
+
+/*------------------------------------------------------------------------
+ * +++ Initialization.
+ */
+
+MODULE_SCOPE
+void TtkScrollbar_Init(Tcl_Interp *interp)
+{
+ Ttk_Theme theme = Ttk_GetDefaultTheme(interp);
+
+ Ttk_RegisterLayout(theme,"Vertical.TScrollbar",VerticalScrollbarLayout);
+ Ttk_RegisterLayout(theme,"Horizontal.TScrollbar",HorizontalScrollbarLayout);
+
+ RegisterWidget(interp, "ttk::scrollbar", &ScrollbarWidgetSpec);
+}
+
+/*EOF*/
diff --git a/tk8.6/generic/ttk/ttkSeparator.c b/tk8.6/generic/ttk/ttkSeparator.c
new file mode 100644
index 0000000..b52e6f4
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkSeparator.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2004, Joe English
+ *
+ * ttk::separator and ttk::sizegrip widgets.
+ */
+
+#include <tk.h>
+
+#include "ttkTheme.h"
+#include "ttkWidget.h"
+
+/* +++ Separator widget record:
+ */
+typedef struct
+{
+ Tcl_Obj *orientObj;
+ int orient;
+} SeparatorPart;
+
+typedef struct
+{
+ WidgetCore core;
+ SeparatorPart separator;
+} Separator;
+
+static Tk_OptionSpec SeparatorOptionSpecs[] = {
+ {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient", "horizontal",
+ Tk_Offset(Separator,separator.orientObj),
+ Tk_Offset(Separator,separator.orient),
+ 0,(ClientData)ttkOrientStrings,STYLE_CHANGED },
+
+ WIDGET_TAKEFOCUS_FALSE,
+ WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)
+};
+
+/*
+ * GetLayout hook --
+ * Choose layout based on -orient option.
+ */
+static Ttk_Layout SeparatorGetLayout(
+ Tcl_Interp *interp, Ttk_Theme theme, void *recordPtr)
+{
+ Separator *sep = recordPtr;
+ return TtkWidgetGetOrientedLayout(
+ interp, theme, recordPtr, sep->separator.orientObj);
+}
+
+/*
+ * Widget commands:
+ */
+static const Ttk_Ensemble SeparatorCommands[] = {
+ { "configure", TtkWidgetConfigureCommand,0 },
+ { "cget", TtkWidgetCgetCommand,0 },
+ { "identify", TtkWidgetIdentifyCommand,0 },
+ { "instate", TtkWidgetInstateCommand,0 },
+ { "state", TtkWidgetStateCommand,0 },
+ { 0,0,0 }
+};
+
+/*
+ * Widget specification:
+ */
+static WidgetSpec SeparatorWidgetSpec =
+{
+ "TSeparator", /* className */
+ sizeof(Separator), /* recordSize */
+ SeparatorOptionSpecs, /* optionSpecs */
+ SeparatorCommands, /* subcommands */
+ TtkNullInitialize, /* initializeProc */
+ TtkNullCleanup, /* cleanupProc */
+ TtkCoreConfigure, /* configureProc */
+ TtkNullPostConfigure, /* postConfigureProc */
+ SeparatorGetLayout, /* getLayoutProc */
+ TtkWidgetSize, /* sizeProc */
+ TtkWidgetDoLayout, /* layoutProc */
+ TtkWidgetDisplay /* displayProc */
+};
+
+TTK_BEGIN_LAYOUT(SeparatorLayout)
+ TTK_NODE("Separator.separator", TTK_FILL_BOTH)
+TTK_END_LAYOUT
+
+/* +++ Sizegrip widget:
+ * Has no options or methods other than the standard ones.
+ */
+
+static Tk_OptionSpec SizegripOptionSpecs[] = {
+ WIDGET_TAKEFOCUS_FALSE,
+ WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)
+};
+
+static const Ttk_Ensemble SizegripCommands[] = {
+ { "configure", TtkWidgetConfigureCommand,0 },
+ { "cget", TtkWidgetCgetCommand,0 },
+ { "identify", TtkWidgetIdentifyCommand,0 },
+ { "instate", TtkWidgetInstateCommand,0 },
+ { "state", TtkWidgetStateCommand,0 },
+ { 0,0,0 }
+};
+
+static WidgetSpec SizegripWidgetSpec =
+{
+ "TSizegrip", /* className */
+ sizeof(WidgetCore), /* recordSize */
+ SizegripOptionSpecs, /* optionSpecs */
+ SizegripCommands, /* subcommands */
+ TtkNullInitialize, /* initializeProc */
+ TtkNullCleanup, /* cleanupProc */
+ TtkCoreConfigure, /* configureProc */
+ TtkNullPostConfigure, /* postConfigureProc */
+ TtkWidgetGetLayout, /* getLayoutProc */
+ TtkWidgetSize, /* sizeProc */
+ TtkWidgetDoLayout, /* layoutProc */
+ TtkWidgetDisplay /* displayProc */
+};
+
+TTK_BEGIN_LAYOUT(SizegripLayout)
+ TTK_NODE("Sizegrip.sizegrip", TTK_PACK_BOTTOM|TTK_STICK_S|TTK_STICK_E)
+TTK_END_LAYOUT
+
+/* +++ Initialization:
+ */
+
+MODULE_SCOPE
+void TtkSeparator_Init(Tcl_Interp *interp)
+{
+ Ttk_Theme theme = Ttk_GetDefaultTheme(interp);
+
+ Ttk_RegisterLayout(theme, "TSeparator", SeparatorLayout);
+ Ttk_RegisterLayout(theme, "TSizegrip", SizegripLayout);
+
+ RegisterWidget(interp, "ttk::separator", &SeparatorWidgetSpec);
+ RegisterWidget(interp, "ttk::sizegrip", &SizegripWidgetSpec);
+}
+
+/*EOF*/
diff --git a/tk8.6/generic/ttk/ttkSquare.c b/tk8.6/generic/ttk/ttkSquare.c
new file mode 100644
index 0000000..d002f2f
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkSquare.c
@@ -0,0 +1,301 @@
+/* square.c - Copyright (C) 2004 Pat Thoyts <patthoyts@users.sourceforge.net>
+ *
+ * Minimal sample ttk widget.
+ */
+
+#include <tk.h>
+#include "ttkTheme.h"
+#include "ttkWidget.h"
+
+#if defined(TTK_SQUARE_WIDGET) || 1
+
+#ifndef DEFAULT_BORDERWIDTH
+#define DEFAULT_BORDERWIDTH "2"
+#endif
+
+/*
+ * First, we setup the widget record. The Ttk package provides a structure
+ * that contains standard widget data so it is only necessary to define
+ * a structure that holds the data required for our widget. We do this by
+ * defining a widget part and then specifying the widget record as the
+ * concatenation of the two structures.
+ */
+
+typedef struct
+{
+ Tcl_Obj *widthObj;
+ Tcl_Obj *heightObj;
+ Tcl_Obj *reliefObj;
+ Tcl_Obj *borderWidthObj;
+ Tcl_Obj *foregroundObj;
+ Tcl_Obj *paddingObj;
+ Tcl_Obj *anchorObj;
+} SquarePart;
+
+typedef struct
+{
+ WidgetCore core;
+ SquarePart square;
+} Square;
+
+/*
+ * Widget options.
+ *
+ * This structure is the same as the option specification structure used
+ * for Tk widgets. For each option we provide the type, name and options
+ * database name and class name and the position in the structure and
+ * default values. At the bottom we bring in the standard widget option
+ * defined for all widgets.
+ */
+
+static Tk_OptionSpec SquareOptionSpecs[] =
+{
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ DEFAULT_BORDERWIDTH, Tk_Offset(Square,square.borderWidthObj), -1,
+ 0,0,GEOMETRY_CHANGED },
+ {TK_OPTION_BORDER, "-foreground", "foreground", "Foreground",
+ DEFAULT_BACKGROUND, Tk_Offset(Square,square.foregroundObj),
+ -1, 0, 0, 0},
+
+ {TK_OPTION_PIXELS, "-width", "width", "Width",
+ "50", Tk_Offset(Square,square.widthObj), -1, 0, 0,
+ GEOMETRY_CHANGED},
+ {TK_OPTION_PIXELS, "-height", "height", "Height",
+ "50", Tk_Offset(Square,square.heightObj), -1, 0, 0,
+ GEOMETRY_CHANGED},
+
+ {TK_OPTION_STRING, "-padding", "padding", "Pad", NULL,
+ Tk_Offset(Square,square.paddingObj), -1,
+ TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
+
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ NULL, Tk_Offset(Square,square.reliefObj), -1, TK_OPTION_NULL_OK, 0, 0},
+
+ {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
+ NULL, Tk_Offset(Square,square.anchorObj), -1, TK_OPTION_NULL_OK, 0, 0},
+
+ WIDGET_TAKEFOCUS_TRUE,
+ WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)
+};
+
+/*
+ * Almost all of the widget functionality is handled by the default Ttk
+ * widget code and the contained element. The one thing that we must handle
+ * is the -anchor option which positions the square element within the parcel
+ * of space available for the widget.
+ * To do this we must find out the layout preferences for the square
+ * element and adjust its position within our region.
+ *
+ * Note that if we do not have a "square" elememt then just the default
+ * layout will be done. So if someone places a label element into the
+ * widget layout it will still be handled but the -anchor option will be
+ * passed onto the label element instead of handled here.
+ */
+
+static void
+SquareDoLayout(void *clientData)
+{
+ WidgetCore *corePtr = (WidgetCore *)clientData;
+ Ttk_Box winBox;
+ Ttk_Element squareNode;
+
+ squareNode = Ttk_FindElement(corePtr->layout, "square");
+ winBox = Ttk_WinBox(corePtr->tkwin);
+ Ttk_PlaceLayout(corePtr->layout, corePtr->state, winBox);
+
+ /*
+ * Adjust the position of the square element within the widget according
+ * to the -anchor option.
+ */
+
+ if (squareNode) {
+ Square *squarePtr = clientData;
+ Tk_Anchor anchor = TK_ANCHOR_CENTER;
+ Ttk_Box b;
+
+ b = Ttk_ElementParcel(squareNode);
+ if (squarePtr->square.anchorObj != NULL)
+ Tk_GetAnchorFromObj(NULL, squarePtr->square.anchorObj, &anchor);
+ b = Ttk_AnchorBox(winBox, b.width, b.height, anchor);
+
+ Ttk_PlaceElement(corePtr->layout, squareNode, b);
+ }
+}
+
+/*
+ * Widget commands. A widget is impelemented as an ensemble and the
+ * subcommands are listed here. Ttk provides default implementations
+ * that are sufficient for our needs.
+ */
+
+static const Ttk_Ensemble SquareCommands[] = {
+ { "configure", TtkWidgetConfigureCommand,0 },
+ { "cget", TtkWidgetCgetCommand,0 },
+ { "identify", TtkWidgetIdentifyCommand,0 },
+ { "instate", TtkWidgetInstateCommand,0 },
+ { "state", TtkWidgetStateCommand,0 },
+ { 0,0,0 }
+};
+
+/*
+ * The Widget specification structure holds all the implementation
+ * information about this widget and this is what must be registered
+ * with Tk in the package initialization code (see bottom).
+ */
+
+static WidgetSpec SquareWidgetSpec =
+{
+ "TSquare", /* className */
+ sizeof(Square), /* recordSize */
+ SquareOptionSpecs, /* optionSpecs */
+ SquareCommands, /* subcommands */
+ TtkNullInitialize, /* initializeProc */
+ TtkNullCleanup, /* cleanupProc */
+ TtkCoreConfigure, /* configureProc */
+ TtkNullPostConfigure, /* postConfigureProc */
+ TtkWidgetGetLayout, /* getLayoutProc */
+ TtkWidgetSize, /* sizeProc */
+ SquareDoLayout, /* layoutProc */
+ TtkWidgetDisplay /* displayProc */
+};
+
+/* ----------------------------------------------------------------------
+ * Square element
+ *
+ * In this section we demonstrate what is required to create a new themed
+ * element.
+ */
+
+typedef struct
+{
+ Tcl_Obj *borderObj;
+ Tcl_Obj *foregroundObj;
+ Tcl_Obj *borderWidthObj;
+ Tcl_Obj *reliefObj;
+ Tcl_Obj *widthObj;
+ Tcl_Obj *heightObj;
+} SquareElement;
+
+static Ttk_ElementOptionSpec SquareElementOptions[] =
+{
+ { "-background", TK_OPTION_BORDER, Tk_Offset(SquareElement,borderObj),
+ DEFAULT_BACKGROUND },
+ { "-foreground", TK_OPTION_BORDER, Tk_Offset(SquareElement,foregroundObj),
+ DEFAULT_BACKGROUND },
+ { "-borderwidth", TK_OPTION_PIXELS, Tk_Offset(SquareElement,borderWidthObj),
+ DEFAULT_BORDERWIDTH },
+ { "-relief", TK_OPTION_RELIEF, Tk_Offset(SquareElement,reliefObj),
+ "raised" },
+ { "-width", TK_OPTION_PIXELS, Tk_Offset(SquareElement,widthObj), "20"},
+ { "-height", TK_OPTION_PIXELS, Tk_Offset(SquareElement,heightObj), "20"},
+ { NULL, 0, 0, NULL }
+};
+
+/*
+ * The element geometry function is called when the layout code wishes to
+ * find out how big this element wants to be. We must return our preferred
+ * size and padding information
+ */
+
+static void SquareElementSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ SquareElement *square = elementRecord;
+ int borderWidth = 0;
+
+ Tcl_GetIntFromObj(NULL, square->borderWidthObj, &borderWidth);
+ *paddingPtr = Ttk_UniformPadding((short)borderWidth);
+ Tk_GetPixelsFromObj(NULL, tkwin, square->widthObj, widthPtr);
+ Tk_GetPixelsFromObj(NULL, tkwin, square->heightObj, heightPtr);
+}
+
+/*
+ * Draw the element in the box provided.
+ */
+
+static void SquareElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, unsigned int state)
+{
+ SquareElement *square = elementRecord;
+ Tk_3DBorder foreground = NULL;
+ int borderWidth = 1, relief = TK_RELIEF_FLAT;
+
+ foreground = Tk_Get3DBorderFromObj(tkwin, square->foregroundObj);
+ Tcl_GetIntFromObj(NULL, square->borderWidthObj, &borderWidth);
+ Tk_GetReliefFromObj(NULL, square->reliefObj, &relief);
+
+ Tk_Fill3DRectangle(tkwin, d, foreground,
+ b.x, b.y, b.width, b.height, borderWidth, relief);
+}
+
+static Ttk_ElementSpec SquareElementSpec =
+{
+ TK_STYLE_VERSION_2,
+ sizeof(SquareElement),
+ SquareElementOptions,
+ SquareElementSize,
+ SquareElementDraw
+};
+
+/* ----------------------------------------------------------------------
+ *
+ * Layout section.
+ *
+ * Every widget class needs a layout style that specifies which elements
+ * are part of the widget and how they should be placed. The element layout
+ * engine is similar to the Tk pack geometry manager. Read the documentation
+ * for the details. In this example we just need to have the square element
+ * that has been defined for this widget placed on a background. We will
+ * also need some padding to keep it away from the edges.
+ */
+
+TTK_BEGIN_LAYOUT(SquareLayout)
+ TTK_NODE("Square.background", TTK_FILL_BOTH)
+ TTK_GROUP("Square.padding", TTK_FILL_BOTH,
+ TTK_NODE("Square.square", 0))
+TTK_END_LAYOUT
+
+/* ----------------------------------------------------------------------
+ *
+ * Widget initialization.
+ *
+ * This file defines a new element and a new widget. We need to register
+ * the element with the themes that will need it. In this case we will
+ * register with the default theme that is the root of the theme inheritance
+ * tree. This means all themes will find this element.
+ * We then need to register the widget class style. This is the layout
+ * specification. If a different theme requires an alternative layout, we
+ * could register that here. For instance, in some themes the scrollbars have
+ * one uparrow, in other themes there are two uparrow elements.
+ * Finally we register the widget itself. This step creates a tcl command so
+ * that we can actually create an instance of this class. The widget is
+ * linked to a particular style by the widget class name. This is important
+ * to realise as the programmer may change the classname when creating a
+ * new instance. If this is done, a new layout will need to be created (which
+ * can be done at script level). Some widgets may require particular elements
+ * to be present but we try to avoid this where possible. In this widget's C
+ * code, no reference is made to any particular elements. The programmer is
+ * free to specify a new style using completely different elements.
+ */
+
+/* public */ MODULE_SCOPE int
+TtkSquareWidget_Init(Tcl_Interp *interp)
+{
+ Ttk_Theme theme = Ttk_GetDefaultTheme(interp);
+
+ /* register the new elements for this theme engine */
+ Ttk_RegisterElement(interp, theme, "square", &SquareElementSpec, NULL);
+
+ /* register the layout for this theme */
+ Ttk_RegisterLayout(theme, "TSquare", SquareLayout);
+
+ /* register the widget */
+ RegisterWidget(interp, "ttk::square", &SquareWidgetSpec);
+
+ return TCL_OK;
+}
+
+#endif /* TTK_SQUARE_WIDGET */
+
diff --git a/tk8.6/generic/ttk/ttkState.c b/tk8.6/generic/ttk/ttkState.c
new file mode 100644
index 0000000..5b62f3c
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkState.c
@@ -0,0 +1,276 @@
+/*
+ * Tk widget state utilities.
+ *
+ * Copyright (c) 2003 Joe English. Freely redistributable.
+ *
+ */
+
+#include <string.h>
+
+#include <tk.h>
+#include "ttkTheme.h"
+
+/*
+ * Table of state names. Must be kept in sync with TTK_STATE_*
+ * #defines in ttkTheme.h.
+ */
+static const char *const stateNames[] =
+{
+ "active", /* Mouse cursor is over widget or element */
+ "disabled", /* Widget is disabled */
+ "focus", /* Widget has keyboard focus */
+ "pressed", /* Pressed or "armed" */
+ "selected", /* "on", "true", "current", etc. */
+ "background", /* Top-level window lost focus (Mac,Win "inactive") */
+ "alternate", /* Widget-specific alternate display style */
+ "invalid", /* Bad value */
+ "readonly", /* Editing/modification disabled */
+ "hover", /* Mouse cursor is over widget */
+ "reserved1", /* Reserved for future extension */
+ "reserved2", /* Reserved for future extension */
+ "reserved3", /* Reserved for future extension */
+ "user3", /* User-definable state */
+ "user2", /* User-definable state */
+ "user1", /* User-definable state */
+ NULL
+};
+
+/*------------------------------------------------------------------------
+ * +++ StateSpec object type:
+ *
+ * The string representation consists of a list of state names,
+ * each optionally prefixed by an exclamation point (!).
+ *
+ * The internal representation uses the upper half of the longValue
+ * to store the on bits and the lower half to store the off bits.
+ * If we ever get more than 16 states, this will need to be reconsidered...
+ */
+
+static int StateSpecSetFromAny(Tcl_Interp *interp, Tcl_Obj *obj);
+/* static void StateSpecFreeIntRep(Tcl_Obj *); */
+#define StateSpecFreeIntRep 0 /* not needed */
+static void StateSpecDupIntRep(Tcl_Obj *, Tcl_Obj *);
+static void StateSpecUpdateString(Tcl_Obj *);
+
+static
+struct Tcl_ObjType StateSpecObjType =
+{
+ "StateSpec",
+ StateSpecFreeIntRep,
+ StateSpecDupIntRep,
+ StateSpecUpdateString,
+ StateSpecSetFromAny
+};
+
+static void StateSpecDupIntRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr)
+{
+ copyPtr->internalRep.longValue = srcPtr->internalRep.longValue;
+ copyPtr->typePtr = &StateSpecObjType;
+}
+
+static int StateSpecSetFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr)
+{
+ int status;
+ int objc;
+ Tcl_Obj **objv;
+ int i;
+ unsigned int onbits = 0, offbits = 0;
+
+ status = Tcl_ListObjGetElements(interp, objPtr, &objc, &objv);
+ if (status != TCL_OK)
+ return status;
+
+ for (i = 0; i < objc; ++i) {
+ const char *stateName = Tcl_GetString(objv[i]);
+ int on, j;
+
+ if (*stateName == '!') {
+ ++stateName;
+ on = 0;
+ } else {
+ on = 1;
+ }
+
+ for (j = 0; stateNames[j] != 0; ++j) {
+ if (strcmp(stateName, stateNames[j]) == 0)
+ break;
+ }
+
+ if (stateNames[j] == 0) {
+ if (interp) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "Invalid state name %s", stateName));
+ Tcl_SetErrorCode(interp, "TTK", "VALUE", "STATE", NULL);
+ }
+ return TCL_ERROR;
+ }
+
+ if (on) {
+ onbits |= (1<<j);
+ } else {
+ offbits |= (1<<j);
+ }
+ }
+
+ /* Invalidate old intrep:
+ */
+ if (objPtr->typePtr && objPtr->typePtr->freeIntRepProc) {
+ objPtr->typePtr->freeIntRepProc(objPtr);
+ }
+
+ objPtr->typePtr = &StateSpecObjType;
+ objPtr->internalRep.longValue = (onbits << 16) | offbits;
+
+ return TCL_OK;
+}
+
+static void StateSpecUpdateString(Tcl_Obj *objPtr)
+{
+ unsigned int onbits = (objPtr->internalRep.longValue & 0xFFFF0000) >> 16;
+ unsigned int offbits = objPtr->internalRep.longValue & 0x0000FFFF;
+ unsigned int mask = onbits | offbits;
+ Tcl_DString result;
+ int i;
+ int len;
+
+ Tcl_DStringInit(&result);
+
+ for (i=0; stateNames[i] != NULL; ++i) {
+ if (mask & (1<<i)) {
+ if (offbits & (1<<i))
+ Tcl_DStringAppend(&result, "!", 1);
+ Tcl_DStringAppend(&result, stateNames[i], -1);
+ Tcl_DStringAppend(&result, " ", 1);
+ }
+ }
+
+ len = Tcl_DStringLength(&result);
+ if (len) {
+ /* 'len' includes extra trailing ' ' */
+ objPtr->bytes = ckalloc(len);
+ objPtr->length = len-1;
+ strncpy(objPtr->bytes, Tcl_DStringValue(&result), len-1);
+ objPtr->bytes[len-1] = '\0';
+ } else {
+ /* empty string */
+ objPtr->length = 0;
+ objPtr->bytes = ckalloc(1);
+ *objPtr->bytes = '\0';
+ }
+
+ Tcl_DStringFree(&result);
+}
+
+Tcl_Obj *Ttk_NewStateSpecObj(unsigned int onbits, unsigned int offbits)
+{
+ Tcl_Obj *objPtr = Tcl_NewObj();
+
+ Tcl_InvalidateStringRep(objPtr);
+ objPtr->typePtr = &StateSpecObjType;
+ objPtr->internalRep.longValue = (onbits << 16) | offbits;
+
+ return objPtr;
+}
+
+int Ttk_GetStateSpecFromObj(
+ Tcl_Interp *interp,
+ Tcl_Obj *objPtr,
+ Ttk_StateSpec *spec)
+{
+ if (objPtr->typePtr != &StateSpecObjType) {
+ int status = StateSpecSetFromAny(interp, objPtr);
+ if (status != TCL_OK)
+ return status;
+ }
+
+ spec->onbits = (objPtr->internalRep.longValue & 0xFFFF0000) >> 16;
+ spec->offbits = objPtr->internalRep.longValue & 0x0000FFFF;
+ return TCL_OK;
+}
+
+
+/*
+ * Tk_StateMapLookup --
+ *
+ * A state map is a paired list of StateSpec / value pairs.
+ * Returns the value corresponding to the first matching state
+ * specification, or NULL if not found or an error occurs.
+ */
+Tcl_Obj *Ttk_StateMapLookup(
+ Tcl_Interp *interp, /* Where to leave error messages; may be NULL */
+ Ttk_StateMap map, /* State map */
+ Ttk_State state) /* State to look up */
+{
+ Tcl_Obj **specs;
+ int nSpecs;
+ int j, status;
+
+ status = Tcl_ListObjGetElements(interp, map, &nSpecs, &specs);
+ if (status != TCL_OK)
+ return NULL;
+
+ for (j = 0; j < nSpecs; j += 2) {
+ Ttk_StateSpec spec;
+ status = Ttk_GetStateSpecFromObj(interp, specs[j], &spec);
+ if (status != TCL_OK)
+ return NULL;
+ if (Ttk_StateMatches(state, &spec))
+ return specs[j+1];
+ }
+ if (interp) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("No match in state map", -1));
+ Tcl_SetErrorCode(interp, "TTK", "STATE", "UNMATCHED", NULL);
+ }
+ return NULL;
+}
+
+/* Ttk_GetStateMapFromObj --
+ * Returns a Ttk_StateMap from a Tcl_Obj*.
+ * Since a Ttk_StateMap is just a specially-formatted Tcl_Obj,
+ * this basically just checks for errors.
+ */
+Ttk_StateMap Ttk_GetStateMapFromObj(
+ Tcl_Interp *interp, /* Where to leave error messages; may be NULL */
+ Tcl_Obj *mapObj) /* State map */
+{
+ Tcl_Obj **specs;
+ int nSpecs;
+ int j, status;
+
+ status = Tcl_ListObjGetElements(interp, mapObj, &nSpecs, &specs);
+ if (status != TCL_OK)
+ return NULL;
+
+ if (nSpecs % 2 != 0) {
+ if (interp) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "State map must have an even number of elements", -1));
+ Tcl_SetErrorCode(interp, "TTK", "VALUE", "STATEMAP", NULL);
+ }
+ return 0;
+ }
+
+ for (j = 0; j < nSpecs; j += 2) {
+ Ttk_StateSpec spec;
+ if (Ttk_GetStateSpecFromObj(interp, specs[j], &spec) != TCL_OK)
+ return NULL;
+ }
+
+ return mapObj;
+}
+
+/*
+ * Ttk_StateTableLooup --
+ * Look up an index from a statically allocated state table.
+ */
+int Ttk_StateTableLookup(Ttk_StateTable *map, unsigned int state)
+{
+ while ((state & map->onBits) != map->onBits
+ || (~state & map->offBits) != map->offBits)
+ {
+ ++map;
+ }
+ return map->index;
+}
+
+/*EOF*/
diff --git a/tk8.6/generic/ttk/ttkStubInit.c b/tk8.6/generic/ttk/ttkStubInit.c
new file mode 100644
index 0000000..87b33dc
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkStubInit.c
@@ -0,0 +1,61 @@
+/*
+ * This file is (mostly) automatically generated from ttk.decls.
+ * It is compiled and linked in with the ttk package proper.
+ */
+
+#include "tk.h"
+#include "ttkTheme.h"
+
+MODULE_SCOPE const TtkStubs ttkStubs;
+
+/* !BEGIN!: Do not edit below this line. */
+
+const TtkStubs ttkStubs = {
+ TCL_STUB_MAGIC,
+ TTK_STUBS_EPOCH,
+ TTK_STUBS_REVISION,
+ 0,
+ Ttk_GetTheme, /* 0 */
+ Ttk_GetDefaultTheme, /* 1 */
+ Ttk_GetCurrentTheme, /* 2 */
+ Ttk_CreateTheme, /* 3 */
+ Ttk_RegisterCleanup, /* 4 */
+ Ttk_RegisterElementSpec, /* 5 */
+ Ttk_RegisterElement, /* 6 */
+ Ttk_RegisterElementFactory, /* 7 */
+ Ttk_RegisterLayout, /* 8 */
+ 0, /* 9 */
+ Ttk_GetStateSpecFromObj, /* 10 */
+ Ttk_NewStateSpecObj, /* 11 */
+ Ttk_GetStateMapFromObj, /* 12 */
+ Ttk_StateMapLookup, /* 13 */
+ Ttk_StateTableLookup, /* 14 */
+ 0, /* 15 */
+ 0, /* 16 */
+ 0, /* 17 */
+ 0, /* 18 */
+ 0, /* 19 */
+ Ttk_GetPaddingFromObj, /* 20 */
+ Ttk_GetBorderFromObj, /* 21 */
+ Ttk_GetStickyFromObj, /* 22 */
+ Ttk_MakePadding, /* 23 */
+ Ttk_UniformPadding, /* 24 */
+ Ttk_AddPadding, /* 25 */
+ Ttk_RelievePadding, /* 26 */
+ Ttk_MakeBox, /* 27 */
+ Ttk_BoxContains, /* 28 */
+ Ttk_PackBox, /* 29 */
+ Ttk_StickBox, /* 30 */
+ Ttk_AnchorBox, /* 31 */
+ Ttk_PadBox, /* 32 */
+ Ttk_ExpandBox, /* 33 */
+ Ttk_PlaceBox, /* 34 */
+ Ttk_NewBoxObj, /* 35 */
+ 0, /* 36 */
+ 0, /* 37 */
+ 0, /* 38 */
+ 0, /* 39 */
+ Ttk_GetOrientFromObj, /* 40 */
+};
+
+/* !END!: Do not edit above this line. */
diff --git a/tk8.6/generic/ttk/ttkStubLib.c b/tk8.6/generic/ttk/ttkStubLib.c
new file mode 100644
index 0000000..2c07b9d
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkStubLib.c
@@ -0,0 +1,74 @@
+/*
+ * We need to ensure that we use the tcl stub macros so that this file
+ * contains no references to any of the tcl stub functions.
+ */
+
+#undef USE_TCL_STUBS
+#define USE_TCL_STUBS
+
+#include "tk.h"
+
+#define USE_TTK_STUBS 1
+#include "ttkTheme.h"
+
+MODULE_SCOPE const TtkStubs *ttkStubsPtr;
+const TtkStubs *ttkStubsPtr = NULL;
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TtkInitializeStubs --
+ * Load the Ttk package, initialize stub table pointer.
+ * Do not call this function directly, use Ttk_InitStubs() macro instead.
+ *
+ * Results:
+ * The actual version of the package that satisfies the request, or
+ * NULL to indicate that an error occurred.
+ *
+ * Side effects:
+ * Sets the stub table pointer.
+ *
+ */
+MODULE_SCOPE const char *
+TtkInitializeStubs(
+ Tcl_Interp *interp, const char *version, int epoch, int revision)
+{
+ int exact = 0;
+ const char *packageName = "Ttk";
+ const char *errMsg = NULL;
+ ClientData pkgClientData = NULL;
+ const char *actualVersion = Tcl_PkgRequireEx(
+ interp, packageName, version, exact, &pkgClientData);
+ const TtkStubs *stubsPtr = pkgClientData;
+
+ if (!actualVersion) {
+ return NULL;
+ }
+
+ if (!stubsPtr) {
+ errMsg = "missing stub table pointer";
+ goto error;
+ }
+ if (stubsPtr->epoch != epoch) {
+ errMsg = "epoch number mismatch";
+ goto error;
+ }
+ if (stubsPtr->revision < revision) {
+ errMsg = "require later revision";
+ goto error;
+ }
+
+ ttkStubsPtr = stubsPtr;
+ return actualVersion;
+
+error:
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp,
+ "Error loading ", packageName, " package",
+ " (requested version '", version,
+ "', loaded version '", actualVersion, "'): ",
+ errMsg,
+ NULL);
+ return NULL;
+}
+
diff --git a/tk8.6/generic/ttk/ttkTagSet.c b/tk8.6/generic/ttk/ttkTagSet.c
new file mode 100644
index 0000000..f2108b9
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkTagSet.c
@@ -0,0 +1,306 @@
+/*
+ * Tag tables. 3/4-baked, work in progress.
+ *
+ * Copyright (C) 2005, Joe English. Freely redistributable.
+ */
+
+#include <string.h> /* for memset() */
+#include <tcl.h>
+#include <tk.h>
+
+#include "ttkTheme.h"
+#include "ttkWidget.h"
+
+/*------------------------------------------------------------------------
+ * +++ Internal data structures.
+ */
+struct TtkTag {
+ int priority; /* 1=>highest */
+ const char *tagName; /* Back-pointer to hash table entry */
+ void *tagRecord; /* User data */
+};
+
+struct TtkTagTable {
+ Tk_Window tkwin; /* owner window */
+ Tk_OptionSpec *optionSpecs; /* ... */
+ Tk_OptionTable optionTable; /* ... */
+ int recordSize; /* size of tag record */
+ int nTags; /* #tags defined so far */
+ Tcl_HashTable tags; /* defined tags */
+};
+
+/*------------------------------------------------------------------------
+ * +++ Tags.
+ */
+static Ttk_Tag NewTag(Ttk_TagTable tagTable, const char *tagName)
+{
+ Ttk_Tag tag = ckalloc(sizeof(*tag));
+ tag->tagRecord = ckalloc(tagTable->recordSize);
+ memset(tag->tagRecord, 0, tagTable->recordSize);
+ /* Don't need Tk_InitOptions() here, all defaults should be NULL. */
+ tag->priority = ++tagTable->nTags;
+ tag->tagName = tagName;
+ return tag;
+}
+
+static void DeleteTag(Ttk_TagTable tagTable, Ttk_Tag tag)
+{
+ Tk_FreeConfigOptions(tag->tagRecord,tagTable->optionTable,tagTable->tkwin);
+ ckfree(tag->tagRecord);
+ ckfree(tag);
+}
+
+/*------------------------------------------------------------------------
+ * +++ Tag tables.
+ */
+
+Ttk_TagTable Ttk_CreateTagTable(
+ Tcl_Interp *interp, Tk_Window tkwin,
+ Tk_OptionSpec optionSpecs[], int recordSize)
+{
+ Ttk_TagTable tagTable = ckalloc(sizeof(*tagTable));
+ tagTable->tkwin = tkwin;
+ tagTable->optionSpecs = optionSpecs;
+ tagTable->optionTable = Tk_CreateOptionTable(interp, optionSpecs);
+ tagTable->recordSize = recordSize;
+ tagTable->nTags = 0;
+ Tcl_InitHashTable(&tagTable->tags, TCL_STRING_KEYS);
+ return tagTable;
+}
+
+void Ttk_DeleteTagTable(Ttk_TagTable tagTable)
+{
+ Tcl_HashSearch search;
+ Tcl_HashEntry *entryPtr;
+
+ entryPtr = Tcl_FirstHashEntry(&tagTable->tags, &search);
+ while (entryPtr != NULL) {
+ DeleteTag(tagTable, Tcl_GetHashValue(entryPtr));
+ entryPtr = Tcl_NextHashEntry(&search);
+ }
+
+ Tcl_DeleteHashTable(&tagTable->tags);
+ ckfree(tagTable);
+}
+
+Ttk_Tag Ttk_GetTag(Ttk_TagTable tagTable, const char *tagName)
+{
+ int isNew = 0;
+ Tcl_HashEntry *entryPtr = Tcl_CreateHashEntry(
+ &tagTable->tags, tagName, &isNew);
+
+ if (isNew) {
+ tagName = Tcl_GetHashKey(&tagTable->tags, entryPtr);
+ Tcl_SetHashValue(entryPtr, NewTag(tagTable,tagName));
+ }
+ return Tcl_GetHashValue(entryPtr);
+}
+
+Ttk_Tag Ttk_GetTagFromObj(Ttk_TagTable tagTable, Tcl_Obj *objPtr)
+{
+ return Ttk_GetTag(tagTable, Tcl_GetString(objPtr));
+}
+
+/*------------------------------------------------------------------------
+ * +++ Tag sets.
+ */
+
+/* Ttk_GetTagSetFromObj --
+ * Extract an array of pointers to Ttk_Tags from a Tcl_Obj.
+ * objPtr may be NULL, in which case a new empty tag set is returned.
+ *
+ * Returns NULL and leaves an error message in interp->result on error.
+ *
+ * Non-NULL results must be passed to Ttk_FreeTagSet().
+ */
+Ttk_TagSet Ttk_GetTagSetFromObj(
+ Tcl_Interp *interp, Ttk_TagTable tagTable, Tcl_Obj *objPtr)
+{
+ Ttk_TagSet tagset = ckalloc(sizeof(*tagset));
+ Tcl_Obj **objv;
+ int i, objc;
+
+ if (objPtr == NULL) {
+ tagset->tags = NULL;
+ tagset->nTags = 0;
+ return tagset;
+ }
+
+ if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
+ ckfree(tagset);
+ return NULL;
+ }
+
+ tagset->tags = ckalloc((objc+1) * sizeof(Ttk_Tag));
+ for (i=0; i<objc; ++i) {
+ tagset->tags[i] = Ttk_GetTagFromObj(tagTable, objv[i]);
+ }
+ tagset->tags[i] = NULL;
+ tagset->nTags = objc;
+
+ return tagset;
+}
+
+/* Ttk_NewTagSetObj --
+ * Construct a fresh Tcl_Obj * from a tag set.
+ */
+Tcl_Obj *Ttk_NewTagSetObj(Ttk_TagSet tagset)
+{
+ Tcl_Obj *result = Tcl_NewListObj(0,0);
+ int i;
+
+ for (i = 0; i < tagset->nTags; ++i) {
+ Tcl_ListObjAppendElement(
+ NULL, result, Tcl_NewStringObj(tagset->tags[i]->tagName, -1));
+ }
+ return result;
+}
+
+void Ttk_FreeTagSet(Ttk_TagSet tagset)
+{
+ ckfree(tagset->tags);
+ ckfree(tagset);
+}
+
+/* Ttk_TagSetContains -- test if tag set contains a tag.
+ */
+int Ttk_TagSetContains(Ttk_TagSet tagset, Ttk_Tag tag)
+{
+ int i;
+ for (i = 0; i < tagset->nTags; ++i) {
+ if (tagset->tags[i] == tag) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* Ttk_TagSetAdd -- add a tag to a tag set.
+ *
+ * Returns: 0 if tagset already contained tag,
+ * 1 if tagset was modified.
+ */
+int Ttk_TagSetAdd(Ttk_TagSet tagset, Ttk_Tag tag)
+{
+ int i;
+ for (i = 0; i < tagset->nTags; ++i) {
+ if (tagset->tags[i] == tag) {
+ return 0;
+ }
+ }
+ tagset->tags = ckrealloc(tagset->tags,
+ (tagset->nTags+1)*sizeof(tagset->tags[0]));
+ tagset->tags[tagset->nTags++] = tag;
+ return 1;
+}
+
+/* Ttk_TagSetRemove -- remove a tag from a tag set.
+ *
+ * Returns: 0 if tagset did not contain tag,
+ * 1 if tagset was modified.
+ */
+int Ttk_TagSetRemove(Ttk_TagSet tagset, Ttk_Tag tag)
+{
+ int i = 0, j = 0;
+ while (i < tagset->nTags) {
+ if ((tagset->tags[j] = tagset->tags[i]) != tag) {
+ ++j;
+ }
+ ++i;
+ }
+ tagset->nTags = j;
+ return j != i;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Utilities for widget commands.
+ */
+
+/* Ttk_EnumerateTags -- implements [$w tag names]
+ */
+int Ttk_EnumerateTags(
+ Tcl_Interp *interp, Ttk_TagTable tagTable)
+{
+ return TtkEnumerateHashTable(interp, &tagTable->tags);
+}
+
+/* Ttk_EnumerateTagOptions -- implements [$w tag configure $tag]
+ */
+int Ttk_EnumerateTagOptions(
+ Tcl_Interp *interp, Ttk_TagTable tagTable, Ttk_Tag tag)
+{
+ return TtkEnumerateOptions(interp, tag->tagRecord,
+ tagTable->optionSpecs, tagTable->optionTable, tagTable->tkwin);
+}
+
+/* Ttk_TagOptionValue -- implements [$w tag configure $tag -option]
+ */
+Tcl_Obj *Ttk_TagOptionValue(
+ Tcl_Interp *interp,
+ Ttk_TagTable tagTable,
+ Ttk_Tag tag,
+ Tcl_Obj *optionName)
+{
+ return Tk_GetOptionValue(interp,
+ tag->tagRecord, tagTable->optionTable, optionName, tagTable->tkwin);
+}
+
+/* Ttk_ConfigureTag -- implements [$w tag configure $tag -option value...]
+ */
+int Ttk_ConfigureTag(
+ Tcl_Interp *interp,
+ Ttk_TagTable tagTable,
+ Ttk_Tag tag,
+ int objc, Tcl_Obj *const objv[])
+{
+ return Tk_SetOptions(
+ interp, tag->tagRecord, tagTable->optionTable,
+ objc, objv, tagTable->tkwin, NULL/*savedOptions*/, NULL/*mask*/);
+}
+
+/*------------------------------------------------------------------------
+ * +++ Tag values.
+ */
+
+#define OBJ_AT(record, offset) (*(Tcl_Obj**)(((char*)record)+offset))
+
+void Ttk_TagSetValues(Ttk_TagTable tagTable, Ttk_TagSet tagSet, void *record)
+{
+ const int LOWEST_PRIORITY = 0x7FFFFFFF;
+ int i, j;
+
+ memset(record, 0, tagTable->recordSize);
+
+ for (i = 0; tagTable->optionSpecs[i].type != TK_OPTION_END; ++i) {
+ Tk_OptionSpec *optionSpec = tagTable->optionSpecs + i;
+ int offset = optionSpec->objOffset;
+ int prio = LOWEST_PRIORITY;
+
+ for (j = 0; j < tagSet->nTags; ++j) {
+ Ttk_Tag tag = tagSet->tags[j];
+ if (OBJ_AT(tag->tagRecord, offset) != 0 && tag->priority < prio) {
+ OBJ_AT(record, offset) = OBJ_AT(tag->tagRecord, offset);
+ prio = tag->priority;
+ }
+ }
+ }
+}
+
+void Ttk_TagSetApplyStyle(
+ Ttk_TagTable tagTable, Ttk_Style style, Ttk_State state, void *record)
+{
+ Tk_OptionSpec *optionSpec = tagTable->optionSpecs;
+
+ while (optionSpec->type != TK_OPTION_END) {
+ int offset = optionSpec->objOffset;
+ const char *optionName = optionSpec->optionName;
+ Tcl_Obj *val = Ttk_StyleMap(style, optionName, state);
+ if (val) {
+ OBJ_AT(record, offset) = val;
+ } else if (OBJ_AT(record, offset) == 0) {
+ OBJ_AT(record, offset) = Ttk_StyleDefault(style, optionName);
+ }
+ ++optionSpec;
+ }
+}
+
diff --git a/tk8.6/generic/ttk/ttkTheme.c b/tk8.6/generic/ttk/ttkTheme.c
new file mode 100644
index 0000000..cc75238
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkTheme.c
@@ -0,0 +1,1755 @@
+/*
+ * ttkTheme.c --
+ *
+ * This file implements the widget styles and themes support.
+ *
+ * Copyright (c) 2002 Frederic Bonnet
+ * Copyright (c) 2003 Joe English
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkInt.h"
+#include "ttkThemeInt.h"
+
+#define PKG_ASSOC_KEY "Ttk"
+
+#ifdef MAC_OSX_TK
+ extern void TkMacOSXFlushWindows(void);
+ #define UPDATE_WINDOWS() TkMacOSXFlushWindows()
+#else
+ #define UPDATE_WINDOWS()
+#endif
+
+/*------------------------------------------------------------------------
+ * +++ Styles.
+ *
+ * Invariants:
+ * If styleName contains a dot, parentStyle->styleName is everything
+ * after the first dot; otherwise, parentStyle is the theme's root
+ * style ".". The root style's parentStyle is NULL.
+ *
+ */
+
+typedef struct Ttk_Style_
+{
+ const char *styleName; /* points to hash table key */
+ Tcl_HashTable settingsTable; /* KEY: string; VALUE: StateMap */
+ Tcl_HashTable defaultsTable; /* KEY: string; VALUE: resource */
+ Ttk_LayoutTemplate layoutTemplate; /* Layout template for style, or NULL */
+ Ttk_Style parentStyle; /* Previous style in chain */
+ Ttk_ResourceCache cache; /* Back-pointer to resource cache */
+} Style;
+
+static Style *NewStyle()
+{
+ Style *stylePtr = ckalloc(sizeof(Style));
+
+ stylePtr->styleName = NULL;
+ stylePtr->parentStyle = NULL;
+ stylePtr->layoutTemplate = NULL;
+ stylePtr->cache = NULL;
+ Tcl_InitHashTable(&stylePtr->settingsTable, TCL_STRING_KEYS);
+ Tcl_InitHashTable(&stylePtr->defaultsTable, TCL_STRING_KEYS);
+
+ return stylePtr;
+}
+
+static void FreeStyle(Style *stylePtr)
+{
+ Tcl_HashSearch search;
+ Tcl_HashEntry *entryPtr;
+
+ entryPtr = Tcl_FirstHashEntry(&stylePtr->settingsTable, &search);
+ while (entryPtr != NULL) {
+ Ttk_StateMap stateMap = Tcl_GetHashValue(entryPtr);
+ Tcl_DecrRefCount(stateMap);
+ entryPtr = Tcl_NextHashEntry(&search);
+ }
+ Tcl_DeleteHashTable(&stylePtr->settingsTable);
+
+ entryPtr = Tcl_FirstHashEntry(&stylePtr->defaultsTable, &search);
+ while (entryPtr != NULL) {
+ Tcl_Obj *defaultValue = Tcl_GetHashValue(entryPtr);
+ Tcl_DecrRefCount(defaultValue);
+ entryPtr = Tcl_NextHashEntry(&search);
+ }
+ Tcl_DeleteHashTable(&stylePtr->defaultsTable);
+
+ Ttk_FreeLayoutTemplate(stylePtr->layoutTemplate);
+
+ ckfree(stylePtr);
+}
+
+/*
+ * Ttk_StyleMap --
+ * Look up state-specific option value from specified style.
+ */
+Tcl_Obj *Ttk_StyleMap(Ttk_Style style, const char *optionName, Ttk_State state)
+{
+ while (style) {
+ Tcl_HashEntry *entryPtr =
+ Tcl_FindHashEntry(&style->settingsTable, optionName);
+ if (entryPtr) {
+ Ttk_StateMap stateMap = Tcl_GetHashValue(entryPtr);
+ return Ttk_StateMapLookup(NULL, stateMap, state);
+ }
+ style = style->parentStyle;
+ }
+ return 0;
+}
+
+/*
+ * Ttk_StyleDefault --
+ * Look up default resource setting the in the specified style.
+ */
+Tcl_Obj *Ttk_StyleDefault(Ttk_Style style, const char *optionName)
+{
+ while (style) {
+ Tcl_HashEntry *entryPtr =
+ Tcl_FindHashEntry(&style->defaultsTable, optionName);
+ if (entryPtr)
+ return Tcl_GetHashValue(entryPtr);
+ style= style->parentStyle;
+ }
+ return 0;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Elements.
+ */
+typedef const Tk_OptionSpec **OptionMap;
+ /* array of Tk_OptionSpecs mapping widget options to element options */
+
+struct Ttk_ElementClass_ {
+ const char *name; /* Points to hash table key */
+ Ttk_ElementSpec *specPtr; /* Template provided during registration. */
+ void *clientData; /* Client data passed in at registration time */
+ void *elementRecord; /* Scratch buffer for element record storage */
+ int nResources; /* #Element options */
+ Tcl_Obj **defaultValues; /* Array of option default values */
+ Tcl_HashTable optMapCache; /* Map: Tk_OptionTable * -> OptionMap */
+};
+
+/* TTKGetOptionSpec --
+ * Look up a Tk_OptionSpec by name from a Tk_OptionTable,
+ * and verify that it's compatible with the specified Tk_OptionType,
+ * along with other constraints (see below).
+ */
+static const Tk_OptionSpec *TTKGetOptionSpec(
+ const char *optionName,
+ Tk_OptionTable optionTable,
+ Tk_OptionType optionType)
+{
+ const Tk_OptionSpec *optionSpec = TkGetOptionSpec(optionName, optionTable);
+
+ if (!optionSpec)
+ return 0;
+
+ /* Make sure widget option has a Tcl_Obj* entry:
+ */
+ if (optionSpec->objOffset < 0) {
+ return 0;
+ }
+
+ /* Grrr. Ignore accidental mismatches caused by prefix-matching:
+ */
+ if (strcmp(optionSpec->optionName, optionName)) {
+ return 0;
+ }
+
+ /* Ensure that the widget option type is compatible with
+ * the element option type.
+ *
+ * TK_OPTION_STRING element options are compatible with anything.
+ * As a workaround for the workaround for Bug #967209,
+ * TK_OPTION_STRING widget options are also compatible with anything
+ * (see <<NOTE-NULLOPTIONS>>).
+ */
+ if ( optionType != TK_OPTION_STRING
+ && optionSpec->type != TK_OPTION_STRING
+ && optionType != optionSpec->type)
+ {
+ return 0;
+ }
+
+ return optionSpec;
+}
+
+/* BuildOptionMap --
+ * Construct the mapping from element options to widget options.
+ */
+static OptionMap
+BuildOptionMap(Ttk_ElementClass *elementClass, Tk_OptionTable optionTable)
+{
+ OptionMap optionMap = ckalloc(
+ sizeof(const Tk_OptionSpec) * elementClass->nResources + 1);
+ int i;
+
+ for (i = 0; i < elementClass->nResources; ++i) {
+ Ttk_ElementOptionSpec *e = elementClass->specPtr->options+i;
+ optionMap[i] = TTKGetOptionSpec(e->optionName, optionTable, e->type);
+ }
+
+ return optionMap;
+}
+
+/* GetOptionMap --
+ * Return a cached OptionMap matching the specified optionTable
+ * for the specified element, creating it if necessary.
+ */
+static OptionMap
+GetOptionMap(Ttk_ElementClass *elementClass, Tk_OptionTable optionTable)
+{
+ OptionMap optionMap;
+ int isNew;
+ Tcl_HashEntry *entryPtr = Tcl_CreateHashEntry(
+ &elementClass->optMapCache, (void*)optionTable, &isNew);
+
+ if (isNew) {
+ optionMap = BuildOptionMap(elementClass, optionTable);
+ Tcl_SetHashValue(entryPtr, optionMap);
+ } else {
+ optionMap = Tcl_GetHashValue(entryPtr);
+ }
+
+ return optionMap;
+}
+
+/*
+ * NewElementClass --
+ * Allocate and initialize an element class record
+ * from the specified element specification.
+ */
+static Ttk_ElementClass *
+NewElementClass(const char *name, Ttk_ElementSpec *specPtr,void *clientData)
+{
+ Ttk_ElementClass *elementClass = ckalloc(sizeof(Ttk_ElementClass));
+ int i;
+
+ elementClass->name = name;
+ elementClass->specPtr = specPtr;
+ elementClass->clientData = clientData;
+ elementClass->elementRecord = ckalloc(specPtr->elementSize);
+
+ /* Count #element resources:
+ */
+ for (i = 0; specPtr->options[i].optionName != 0; ++i)
+ continue;
+ elementClass->nResources = i;
+
+ /* Initialize default values:
+ */
+ elementClass->defaultValues =
+ ckalloc(elementClass->nResources * sizeof(Tcl_Obj *) + 1);
+ for (i=0; i < elementClass->nResources; ++i) {
+ const char *defaultValue = specPtr->options[i].defaultValue;
+ if (defaultValue) {
+ elementClass->defaultValues[i] = Tcl_NewStringObj(defaultValue,-1);
+ Tcl_IncrRefCount(elementClass->defaultValues[i]);
+ } else {
+ elementClass->defaultValues[i] = 0;
+ }
+ }
+
+ /* Initialize option map cache:
+ */
+ Tcl_InitHashTable(&elementClass->optMapCache, TCL_ONE_WORD_KEYS);
+
+ return elementClass;
+}
+
+/*
+ * FreeElementClass --
+ * Release resources associated with an element class record.
+ */
+static void FreeElementClass(Ttk_ElementClass *elementClass)
+{
+ Tcl_HashSearch search;
+ Tcl_HashEntry *entryPtr;
+ int i;
+
+ /*
+ * Free default values:
+ */
+ for (i = 0; i < elementClass->nResources; ++i) {
+ if (elementClass->defaultValues[i]) {
+ Tcl_DecrRefCount(elementClass->defaultValues[i]);
+ }
+ }
+ ckfree(elementClass->defaultValues);
+
+ /*
+ * Free option map cache:
+ */
+ entryPtr = Tcl_FirstHashEntry(&elementClass->optMapCache, &search);
+ while (entryPtr != NULL) {
+ ckfree(Tcl_GetHashValue(entryPtr));
+ entryPtr = Tcl_NextHashEntry(&search);
+ }
+ Tcl_DeleteHashTable(&elementClass->optMapCache);
+
+ ckfree(elementClass->elementRecord);
+ ckfree(elementClass);
+}
+
+/*------------------------------------------------------------------------
+ * +++ Themes.
+ */
+
+static int ThemeEnabled(Ttk_Theme theme, void *clientData) { return 1; }
+ /* Default ThemeEnabledProc -- always return true */
+
+typedef struct Ttk_Theme_
+{
+ Ttk_Theme parentPtr; /* Parent theme. */
+ Tcl_HashTable elementTable; /* Map element names to class records */
+ Tcl_HashTable styleTable; /* Map style names to Styles */
+ Ttk_Style rootStyle; /* "." style, root of chain */
+ Ttk_ThemeEnabledProc *enabledProc; /* Function called by SetTheme */
+ void *enabledData; /* ClientData for enabledProc */
+ Ttk_ResourceCache cache; /* Back-pointer to resource cache */
+} Theme;
+
+static Theme *NewTheme(Ttk_ResourceCache cache, Ttk_Theme parent)
+{
+ Theme *themePtr = ckalloc(sizeof(Theme));
+ Tcl_HashEntry *entryPtr;
+ int unused;
+
+ themePtr->parentPtr = parent;
+ themePtr->enabledProc = ThemeEnabled;
+ themePtr->enabledData = NULL;
+ themePtr->cache = cache;
+ Tcl_InitHashTable(&themePtr->elementTable, TCL_STRING_KEYS);
+ Tcl_InitHashTable(&themePtr->styleTable, TCL_STRING_KEYS);
+
+ /*
+ * Create root style "."
+ */
+ entryPtr = Tcl_CreateHashEntry(&themePtr->styleTable, ".", &unused);
+ themePtr->rootStyle = NewStyle();
+ themePtr->rootStyle->styleName =
+ Tcl_GetHashKey(&themePtr->styleTable, entryPtr);
+ themePtr->rootStyle->cache = themePtr->cache;
+ Tcl_SetHashValue(entryPtr, themePtr->rootStyle);
+
+ return themePtr;
+}
+
+static void FreeTheme(Theme *themePtr)
+{
+ Tcl_HashSearch search;
+ Tcl_HashEntry *entryPtr;
+
+ /*
+ * Free element table:
+ */
+ entryPtr = Tcl_FirstHashEntry(&themePtr->elementTable, &search);
+ while (entryPtr != NULL) {
+ Ttk_ElementClass *elementClass = Tcl_GetHashValue(entryPtr);
+ FreeElementClass(elementClass);
+ entryPtr = Tcl_NextHashEntry(&search);
+ }
+ Tcl_DeleteHashTable(&themePtr->elementTable);
+
+ /*
+ * Free style table:
+ */
+ entryPtr = Tcl_FirstHashEntry(&themePtr->styleTable, &search);
+ while (entryPtr != NULL) {
+ Style *stylePtr = Tcl_GetHashValue(entryPtr);
+ FreeStyle(stylePtr);
+ entryPtr = Tcl_NextHashEntry(&search);
+ }
+ Tcl_DeleteHashTable(&themePtr->styleTable);
+
+ /*
+ * Free theme record:
+ */
+ ckfree(themePtr);
+
+ return;
+}
+
+/*
+ * Element constructors.
+ */
+typedef struct {
+ Ttk_ElementFactory factory;
+ void *clientData;
+} FactoryRec;
+
+/*
+ * Cleanup records:
+ */
+typedef struct CleanupStruct {
+ void *clientData;
+ Ttk_CleanupProc *cleanupProc;
+ struct CleanupStruct *next;
+} Cleanup;
+
+/*------------------------------------------------------------------------
+ * +++ Master style package data structure.
+ */
+typedef struct
+{
+ Tcl_Interp *interp; /* Owner interp */
+ Tcl_HashTable themeTable; /* KEY: name; VALUE: Theme pointer */
+ Tcl_HashTable factoryTable; /* KEY: name; VALUE: FactoryRec ptr */
+ Theme *defaultTheme; /* Default theme; global fallback*/
+ Theme *currentTheme; /* Currently-selected theme */
+ Cleanup *cleanupList; /* Cleanup records */
+ Ttk_ResourceCache cache; /* Resource cache */
+ int themeChangePending; /* scheduled ThemeChangedProc call? */
+} StylePackageData;
+
+static void ThemeChangedProc(ClientData); /* Forward */
+
+/* Ttk_StylePkgFree --
+ * Cleanup procedure for StylePackageData.
+ */
+static void Ttk_StylePkgFree(ClientData clientData, Tcl_Interp *interp)
+{
+ StylePackageData *pkgPtr = clientData;
+ Tcl_HashSearch search;
+ Tcl_HashEntry *entryPtr;
+ Cleanup *cleanup;
+
+ /*
+ * Cancel any pending ThemeChanged calls:
+ */
+ if (pkgPtr->themeChangePending) {
+ Tcl_CancelIdleCall(ThemeChangedProc, pkgPtr);
+ }
+
+ /*
+ * Free themes.
+ */
+ entryPtr = Tcl_FirstHashEntry(&pkgPtr->themeTable, &search);
+ while (entryPtr != NULL) {
+ Theme *themePtr = Tcl_GetHashValue(entryPtr);
+ FreeTheme(themePtr);
+ entryPtr = Tcl_NextHashEntry(&search);
+ }
+ Tcl_DeleteHashTable(&pkgPtr->themeTable);
+
+ /*
+ * Free element constructor table:
+ */
+ entryPtr = Tcl_FirstHashEntry(&pkgPtr->factoryTable, &search);
+ while (entryPtr != NULL) {
+ ckfree(Tcl_GetHashValue(entryPtr));
+ entryPtr = Tcl_NextHashEntry(&search);
+ }
+ Tcl_DeleteHashTable(&pkgPtr->factoryTable);
+
+ /*
+ * Release cache:
+ */
+ Ttk_FreeResourceCache(pkgPtr->cache);
+
+ /*
+ * Call all registered cleanup procedures:
+ */
+ cleanup = pkgPtr->cleanupList;
+ while (cleanup) {
+ Cleanup *next = cleanup->next;
+ cleanup->cleanupProc(cleanup->clientData);
+ ckfree(cleanup);
+ cleanup = next;
+ }
+
+ ckfree(pkgPtr);
+}
+
+/*
+ * GetStylePackageData --
+ * Look up the package data registered with the interp.
+ */
+
+static StylePackageData *GetStylePackageData(Tcl_Interp *interp)
+{
+ return Tcl_GetAssocData(interp, PKG_ASSOC_KEY, NULL);
+}
+
+/*
+ * Ttk_RegisterCleanup --
+ *
+ * Register a function to be called when a theme engine is deleted.
+ * (This only happens when the main interp is destroyed). The cleanup
+ * function is called with the current Tcl interpreter and the client
+ * data provided here.
+ *
+ */
+void Ttk_RegisterCleanup(
+ Tcl_Interp *interp, ClientData clientData, Ttk_CleanupProc *cleanupProc)
+{
+ StylePackageData *pkgPtr = GetStylePackageData(interp);
+ Cleanup *cleanup = ckalloc(sizeof(*cleanup));
+
+ cleanup->clientData = clientData;
+ cleanup->cleanupProc = cleanupProc;
+ cleanup->next = pkgPtr->cleanupList;
+ pkgPtr->cleanupList = cleanup;
+}
+
+/* ThemeChangedProc --
+ * Notify all widgets that the theme has been changed.
+ * Scheduled as an idle callback; clientData is a StylePackageData *.
+ *
+ * Sends a <<ThemeChanged>> event to every widget in the hierarchy.
+ * Widgets respond to this by calling the WorldChanged class proc,
+ * which in turn recreates the layout.
+ *
+ * The Tk C API doesn't doesn't provide an easy way to traverse
+ * the widget hierarchy, so this is done by evaluating a Tcl script.
+ */
+
+static void ThemeChangedProc(ClientData clientData)
+{
+ static char ThemeChangedScript[] = "ttk::ThemeChanged";
+ StylePackageData *pkgPtr = clientData;
+
+ int code = Tcl_EvalEx(pkgPtr->interp, ThemeChangedScript, -1, TCL_EVAL_GLOBAL);
+ if (code != TCL_OK) {
+ Tcl_BackgroundException(pkgPtr->interp, code);
+ }
+ pkgPtr->themeChangePending = 0;
+ UPDATE_WINDOWS();
+}
+
+/*
+ * ThemeChanged --
+ * Schedule a call to ThemeChanged if one is not already pending.
+ */
+static void ThemeChanged(StylePackageData *pkgPtr)
+{
+ if (!pkgPtr->themeChangePending) {
+ Tcl_DoWhenIdle(ThemeChangedProc, pkgPtr);
+ pkgPtr->themeChangePending = 1;
+ }
+}
+
+/*
+ * Ttk_CreateTheme --
+ * Create a new theme and register it in the global theme table.
+ *
+ * Returns:
+ * Pointer to new Theme structure; NULL if named theme already exists.
+ * Leaves an error message in interp's result on error.
+ */
+
+Ttk_Theme
+Ttk_CreateTheme(
+ Tcl_Interp *interp, /* Interpreter in which to create theme */
+ const char *name, /* Name of the theme to create. */
+ Ttk_Theme parent) /* Parent/fallback theme, NULL for default */
+{
+ StylePackageData *pkgPtr = GetStylePackageData(interp);
+ Tcl_HashEntry *entryPtr;
+ int newEntry;
+ Theme *themePtr;
+
+ entryPtr = Tcl_CreateHashEntry(&pkgPtr->themeTable, name, &newEntry);
+ if (!newEntry) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "Theme %s already exists", name));
+ Tcl_SetErrorCode(interp, "TTK", "THEME", "EXISTS", NULL);
+ return NULL;
+ }
+
+ /*
+ * Initialize new theme:
+ */
+ if (!parent) parent = pkgPtr->defaultTheme;
+
+ themePtr = NewTheme(pkgPtr->cache, parent);
+ Tcl_SetHashValue(entryPtr, themePtr);
+
+ return themePtr;
+}
+
+/*
+ * Ttk_SetThemeEnabledProc --
+ * Sets a procedure that is used to check that this theme is available.
+ */
+
+void Ttk_SetThemeEnabledProc(
+ Ttk_Theme theme, Ttk_ThemeEnabledProc enabledProc, void *enabledData)
+{
+ theme->enabledProc = enabledProc;
+ theme->enabledData = enabledData;
+}
+
+/*
+ * LookupTheme --
+ * Retrieve a registered theme by name. If not found,
+ * returns NULL and leaves an error message in interp's result.
+ */
+
+static Ttk_Theme LookupTheme(
+ Tcl_Interp *interp, /* where to leave error messages */
+ StylePackageData *pkgPtr, /* style package master record */
+ const char *name) /* theme name */
+{
+ Tcl_HashEntry *entryPtr;
+
+ entryPtr = Tcl_FindHashEntry(&pkgPtr->themeTable, name);
+ if (!entryPtr) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "theme \"%s\" doesn't exist", name));
+ Tcl_SetErrorCode(interp, "TTK", "LOOKUP", "THEME", name, NULL);
+ return NULL;
+ }
+
+ return Tcl_GetHashValue(entryPtr);
+}
+
+/*
+ * Ttk_GetTheme --
+ * Public interface to LookupTheme.
+ */
+Ttk_Theme Ttk_GetTheme(Tcl_Interp *interp, const char *themeName)
+{
+ StylePackageData *pkgPtr = GetStylePackageData(interp);
+
+ return LookupTheme(interp, pkgPtr, themeName);
+}
+
+Ttk_Theme Ttk_GetCurrentTheme(Tcl_Interp *interp)
+{
+ StylePackageData *pkgPtr = GetStylePackageData(interp);
+ return pkgPtr->currentTheme;
+}
+
+Ttk_Theme Ttk_GetDefaultTheme(Tcl_Interp *interp)
+{
+ StylePackageData *pkgPtr = GetStylePackageData(interp);
+ return pkgPtr->defaultTheme;
+}
+
+/*
+ * Ttk_UseTheme --
+ * Set the current theme, notify all widgets that the theme has changed.
+ */
+int Ttk_UseTheme(Tcl_Interp *interp, Ttk_Theme theme)
+{
+ StylePackageData *pkgPtr = GetStylePackageData(interp);
+
+ /*
+ * Check if selected theme is enabled:
+ */
+ while (theme && !theme->enabledProc(theme, theme->enabledData)) {
+ theme = theme->parentPtr;
+ }
+ if (!theme) {
+ /* This shouldn't happen -- default theme should always work */
+ Tcl_Panic("No themes available?");
+ return TCL_ERROR;
+ }
+
+ pkgPtr->currentTheme = theme;
+ ThemeChanged(pkgPtr);
+ return TCL_OK;
+}
+
+/*
+ * Ttk_GetResourceCache --
+ * Return the resource cache associated with 'interp'
+ */
+Ttk_ResourceCache
+Ttk_GetResourceCache(Tcl_Interp *interp)
+{
+ StylePackageData *pkgPtr = GetStylePackageData(interp);
+ return pkgPtr->cache;
+}
+
+/*
+ * Register a new layout specification with a style.
+ * @@@ TODO: Make sure layoutName is not ".", root style must not have a layout
+ */
+MODULE_SCOPE
+void Ttk_RegisterLayoutTemplate(
+ Ttk_Theme theme, /* Target theme */
+ const char *layoutName, /* Name of new layout */
+ Ttk_LayoutTemplate layoutTemplate) /* Template */
+{
+ Ttk_Style style = Ttk_GetStyle(theme, layoutName);
+ if (style->layoutTemplate) {
+ Ttk_FreeLayoutTemplate(style->layoutTemplate);
+ }
+ style->layoutTemplate = layoutTemplate;
+}
+
+void Ttk_RegisterLayout(
+ Ttk_Theme themePtr, /* Target theme */
+ const char *layoutName, /* Name of new layout */
+ Ttk_LayoutSpec specPtr) /* Static layout information */
+{
+ Ttk_LayoutTemplate layoutTemplate = Ttk_BuildLayoutTemplate(specPtr);
+ Ttk_RegisterLayoutTemplate(themePtr, layoutName, layoutTemplate);
+}
+
+/*
+ * Ttk_GetStyle --
+ * Look up a Style from a Theme, create new style if not found.
+ */
+Ttk_Style Ttk_GetStyle(Ttk_Theme themePtr, const char *styleName)
+{
+ Tcl_HashEntry *entryPtr;
+ int newStyle;
+
+ entryPtr = Tcl_CreateHashEntry(&themePtr->styleTable, styleName, &newStyle);
+ if (newStyle) {
+ Ttk_Style stylePtr = NewStyle();
+ const char *dot = strchr(styleName, '.');
+
+ if (dot) {
+ stylePtr->parentStyle = Ttk_GetStyle(themePtr, dot + 1);
+ } else {
+ stylePtr->parentStyle = themePtr->rootStyle;
+ }
+
+ stylePtr->styleName = Tcl_GetHashKey(&themePtr->styleTable, entryPtr);
+ stylePtr->cache = stylePtr->parentStyle->cache;
+ Tcl_SetHashValue(entryPtr, stylePtr);
+ return stylePtr;
+ }
+ return Tcl_GetHashValue(entryPtr);
+}
+
+/* FindLayoutTemplate --
+ * Locate a layout template in the layout table, checking
+ * generic names to specific names first, then looking for
+ * the full name in the parent theme.
+ */
+Ttk_LayoutTemplate
+Ttk_FindLayoutTemplate(Ttk_Theme themePtr, const char *layoutName)
+{
+ while (themePtr) {
+ Ttk_Style stylePtr = Ttk_GetStyle(themePtr, layoutName);
+ while (stylePtr) {
+ if (stylePtr->layoutTemplate) {
+ return stylePtr->layoutTemplate;
+ }
+ stylePtr = stylePtr->parentStyle;
+ }
+ themePtr = themePtr->parentPtr;
+ }
+ return NULL;
+}
+
+const char *Ttk_StyleName(Ttk_Style stylePtr)
+{
+ return stylePtr->styleName;
+}
+
+/*
+ * Ttk_GetElement --
+ * Look up an element class by name in a given theme.
+ * If not found, try generic element names in this theme, then
+ * repeat the lookups in the parent theme.
+ * If not found, return the null element.
+ */
+Ttk_ElementClass *Ttk_GetElement(Ttk_Theme themePtr, const char *elementName)
+{
+ Tcl_HashEntry *entryPtr;
+ const char *dot = elementName;
+
+ /*
+ * Check if element has already been registered:
+ */
+ entryPtr = Tcl_FindHashEntry(&themePtr->elementTable, elementName);
+ if (entryPtr) {
+ return Tcl_GetHashValue(entryPtr);
+ }
+
+ /*
+ * Check generic names:
+ */
+ while (!entryPtr && ((dot = strchr(dot, '.')) != NULL)) {
+ dot++;
+ entryPtr = Tcl_FindHashEntry(&themePtr->elementTable, dot);
+ }
+ if (entryPtr) {
+ return Tcl_GetHashValue(entryPtr);
+ }
+
+ /*
+ * Check parent theme:
+ */
+ if (themePtr->parentPtr) {
+ return Ttk_GetElement(themePtr->parentPtr, elementName);
+ }
+
+ /*
+ * Not found, and this is the root theme; return null element, "".
+ * (@@@ SHOULD: signal a background error)
+ */
+ entryPtr = Tcl_FindHashEntry(&themePtr->elementTable, "");
+ /* ASSERT: entryPtr != 0 */
+ return Tcl_GetHashValue(entryPtr);
+}
+
+const char *Ttk_ElementClassName(Ttk_ElementClass *elementClass)
+{
+ return elementClass->name;
+}
+
+/*
+ * Ttk_RegisterElementFactory --
+ * Register a new element factory.
+ */
+int Ttk_RegisterElementFactory(
+ Tcl_Interp *interp, const char *name,
+ Ttk_ElementFactory factory, void *clientData)
+{
+ StylePackageData *pkgPtr = GetStylePackageData(interp);
+ FactoryRec *recPtr = ckalloc(sizeof(*recPtr));
+ Tcl_HashEntry *entryPtr;
+ int newEntry;
+
+ recPtr->factory = factory;
+ recPtr->clientData = clientData;
+
+ entryPtr = Tcl_CreateHashEntry(&pkgPtr->factoryTable, name, &newEntry);
+ if (!newEntry) {
+ /* Free old factory: */
+ ckfree(Tcl_GetHashValue(entryPtr));
+ }
+ Tcl_SetHashValue(entryPtr, recPtr);
+
+ return TCL_OK;
+}
+
+/* Ttk_CloneElement -- element factory procedure.
+ * (style element create $name) "from" $theme ?$element?
+ */
+static int Ttk_CloneElement(
+ Tcl_Interp *interp, void *clientData,
+ Ttk_Theme theme, const char *elementName,
+ int objc, Tcl_Obj *const objv[])
+{
+ Ttk_Theme fromTheme;
+ Ttk_ElementClass *fromElement;
+
+ if (objc <= 0 || objc > 2) {
+ Tcl_WrongNumArgs(interp, 0, objv, "theme ?element?");
+ return TCL_ERROR;
+ }
+
+ fromTheme = Ttk_GetTheme(interp, Tcl_GetString(objv[0]));
+ if (!fromTheme) {
+ return TCL_ERROR;
+ }
+
+ if (objc == 2) {
+ fromElement = Ttk_GetElement(fromTheme, Tcl_GetString(objv[1]));
+ } else {
+ fromElement = Ttk_GetElement(fromTheme, elementName);
+ }
+ if (!fromElement) {
+ return TCL_ERROR;
+ }
+
+ if (Ttk_RegisterElement(interp, theme, elementName,
+ fromElement->specPtr, fromElement->clientData) == NULL)
+ {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/* Ttk_RegisterElement--
+ * Register an element in the given theme.
+ * Returns: Element handle if successful, NULL otherwise.
+ * On failure, leaves an error message in interp's result
+ * if interp is non-NULL.
+ */
+
+Ttk_ElementClass *Ttk_RegisterElement(
+ Tcl_Interp *interp, /* Where to leave error messages */
+ Ttk_Theme theme, /* Style engine providing the implementation. */
+ const char *name, /* Name of new element */
+ Ttk_ElementSpec *specPtr, /* Static template information */
+ void *clientData) /* application-specific data */
+{
+ Ttk_ElementClass *elementClass;
+ Tcl_HashEntry *entryPtr;
+ int newEntry;
+
+ if (specPtr->version != TK_STYLE_VERSION_2) {
+ /* Version mismatch */
+ if (interp) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "Internal error: Ttk_RegisterElement (%s): invalid version",
+ name));
+ Tcl_SetErrorCode(interp, "TTK", "REGISTER_ELEMENT", "VERSION",
+ NULL);
+ }
+ return 0;
+ }
+
+ entryPtr = Tcl_CreateHashEntry(&theme->elementTable, name, &newEntry);
+ if (!newEntry) {
+ if (interp) {
+ Tcl_ResetResult(interp);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "Duplicate element %s", name));
+ Tcl_SetErrorCode(interp, "TTK", "REGISTER_ELEMENT", "DUPE", NULL);
+ }
+ return 0;
+ }
+
+ name = Tcl_GetHashKey(&theme->elementTable, entryPtr);
+ elementClass = NewElementClass(name, specPtr, clientData);
+ Tcl_SetHashValue(entryPtr, elementClass);
+
+ return elementClass;
+}
+
+/* Ttk_RegisterElementSpec (deprecated) --
+ * Register a new element.
+ */
+int Ttk_RegisterElementSpec(Ttk_Theme theme,
+ const char *name, Ttk_ElementSpec *specPtr, void *clientData)
+{
+ return Ttk_RegisterElement(NULL, theme, name, specPtr, clientData)
+ ? TCL_OK : TCL_ERROR;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Element record initialization.
+ */
+
+/*
+ * AllocateResource --
+ * Extra initialization for element options like TK_OPTION_COLOR, etc.
+ *
+ * Returns: 1 if OK, 0 on failure.
+ *
+ * Note: if resource allocation fails at this point (just prior
+ * to drawing an element), there's really no good place to
+ * report the error. Instead we just silently fail.
+ */
+
+static int AllocateResource(
+ Ttk_ResourceCache cache,
+ Tk_Window tkwin,
+ Tcl_Obj **destPtr,
+ int optionType)
+{
+ Tcl_Obj *resource = *destPtr;
+
+ switch (optionType)
+ {
+ case TK_OPTION_FONT:
+ return (*destPtr = Ttk_UseFont(cache, tkwin, resource)) != NULL;
+ case TK_OPTION_COLOR:
+ return (*destPtr = Ttk_UseColor(cache, tkwin, resource)) != NULL;
+ case TK_OPTION_BORDER:
+ return (*destPtr = Ttk_UseBorder(cache, tkwin, resource)) != NULL;
+ default:
+ /* no-op; always succeeds */
+ return 1;
+ }
+}
+
+/*
+ * InitializeElementRecord --
+ *
+ * Fill in the element record based on the element's option table.
+ * Resources are initialized from:
+ * the corresponding widget option if present and non-NULL,
+ * otherwise the dynamic state map if specified,
+ * otherwise from the corresponding widget resource if present,
+ * otherwise the default value specified at registration time.
+ *
+ * Returns:
+ * 1 if OK, 0 if an error is detected.
+ *
+ * NOTES:
+ * Tcl_Obj * reference counts are _NOT_ adjusted.
+ */
+
+static
+int InitializeElementRecord(
+ Ttk_ElementClass *eclass, /* Element instance to initialize */
+ Ttk_Style style, /* Style table */
+ char *widgetRecord, /* Source of widget option values */
+ Tk_OptionTable optionTable, /* Option table describing widget record */
+ Tk_Window tkwin, /* Corresponding window */
+ Ttk_State state) /* Widget or element state */
+{
+ char *elementRecord = eclass->elementRecord;
+ OptionMap optionMap = GetOptionMap(eclass,optionTable);
+ int nResources = eclass->nResources;
+ Ttk_ResourceCache cache = style->cache;
+ Ttk_ElementOptionSpec *elementOption = eclass->specPtr->options;
+
+ int i;
+ for (i=0; i<nResources; ++i, ++elementOption) {
+ Tcl_Obj **dest = (Tcl_Obj **)
+ (elementRecord + elementOption->offset);
+ const char *optionName = elementOption->optionName;
+ Tcl_Obj *dynamicSetting = Ttk_StyleMap(style, optionName, state);
+ Tcl_Obj *widgetValue = 0;
+ Tcl_Obj *elementDefault = eclass->defaultValues[i];
+
+ if (optionMap[i]) {
+ widgetValue = *(Tcl_Obj **)
+ (widgetRecord + optionMap[i]->objOffset);
+ }
+
+ if (widgetValue) {
+ *dest = widgetValue;
+ } else if (dynamicSetting) {
+ *dest = dynamicSetting;
+ } else {
+ Tcl_Obj *styleDefault = Ttk_StyleDefault(style, optionName);
+ *dest = styleDefault ? styleDefault : elementDefault;
+ }
+
+ if (!AllocateResource(cache, tkwin, dest, elementOption->type)) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Public API.
+ */
+
+/*
+ * Ttk_QueryStyle --
+ * Look up a style option based on the current state.
+ */
+Tcl_Obj *Ttk_QueryStyle(
+ Ttk_Style style, /* Style to query */
+ void *recordPtr, /* Widget record */
+ Tk_OptionTable optionTable, /* Option table describing widget record */
+ const char *optionName, /* Option name */
+ Ttk_State state) /* Current state */
+{
+ const Tk_OptionSpec *optionSpec;
+ Tcl_Obj *result;
+
+ /*
+ * Check widget record:
+ */
+ optionSpec = TTKGetOptionSpec(optionName, optionTable, TK_OPTION_ANY);
+ if (optionSpec) {
+ result = *(Tcl_Obj**)(((char*)recordPtr) + optionSpec->objOffset);
+ if (result) {
+ return result;
+ }
+ }
+
+ /*
+ * Check dynamic settings:
+ */
+ result = Ttk_StyleMap(style, optionName, state);
+ if (result) {
+ return result;
+ }
+
+ /*
+ * Use style default:
+ */
+ return Ttk_StyleDefault(style, optionName);
+}
+
+/*
+ * Ttk_ElementSize --
+ * Compute the requested size of the given element.
+ */
+
+void
+Ttk_ElementSize(
+ Ttk_ElementClass *eclass, /* Element to query */
+ Ttk_Style style, /* Style settings */
+ char *recordPtr, /* The widget record. */
+ Tk_OptionTable optionTable, /* Description of widget record */
+ Tk_Window tkwin, /* The widget window. */
+ Ttk_State state, /* Current widget state */
+ int *widthPtr, /* Requested width */
+ int *heightPtr, /* Reqested height */
+ Ttk_Padding *paddingPtr) /* Requested inner border */
+{
+ paddingPtr->left = paddingPtr->right = paddingPtr->top = paddingPtr->bottom
+ = *widthPtr = *heightPtr = 0;
+
+ if (!InitializeElementRecord(
+ eclass, style, recordPtr, optionTable, tkwin, state))
+ {
+ return;
+ }
+ eclass->specPtr->size(
+ eclass->clientData, eclass->elementRecord,
+ tkwin, widthPtr, heightPtr, paddingPtr);
+}
+
+/*
+ * Ttk_DrawElement --
+ * Draw the given widget element in a given drawable area.
+ */
+
+void
+Ttk_DrawElement(
+ Ttk_ElementClass *eclass, /* Element instance */
+ Ttk_Style style, /* Style settings */
+ char *recordPtr, /* The widget record. */
+ Tk_OptionTable optionTable, /* Description of option table */
+ Tk_Window tkwin, /* The widget window. */
+ Drawable d, /* Where to draw element. */
+ Ttk_Box b, /* Element area */
+ Ttk_State state) /* Widget or element state flags. */
+{
+ if (b.width <= 0 || b.height <= 0)
+ return;
+ if (!InitializeElementRecord(
+ eclass, style, recordPtr, optionTable, tkwin, state))
+ {
+ return;
+ }
+ eclass->specPtr->draw(
+ eclass->clientData, eclass->elementRecord,
+ tkwin, d, b, state);
+}
+
+/*------------------------------------------------------------------------
+ * +++ 'style' command ensemble procedures.
+ */
+
+/*
+ * TtkEnumerateHashTable --
+ * Helper routine. Sets interp's result to the list of all keys
+ * in the hash table.
+ *
+ * Returns: TCL_OK.
+ * Side effects: Sets interp's result.
+ */
+
+MODULE_SCOPE
+int TtkEnumerateHashTable(Tcl_Interp *interp, Tcl_HashTable *ht)
+{
+ Tcl_HashSearch search;
+ Tcl_Obj *result = Tcl_NewListObj(0, NULL);
+ Tcl_HashEntry *entryPtr = Tcl_FirstHashEntry(ht, &search);
+
+ while (entryPtr != NULL) {
+ Tcl_Obj *nameObj = Tcl_NewStringObj(Tcl_GetHashKey(ht, entryPtr),-1);
+ Tcl_ListObjAppendElement(interp, result, nameObj);
+ entryPtr = Tcl_NextHashEntry(&search);
+ }
+
+ Tcl_SetObjResult(interp, result);
+ return TCL_OK;
+}
+
+/* HashTableToDict --
+ * Helper routine. Converts a TCL_STRING_KEYS Tcl_HashTable
+ * with Tcl_Obj * entries into a dictionary.
+ */
+static Tcl_Obj* HashTableToDict(Tcl_HashTable *ht)
+{
+ Tcl_HashSearch search;
+ Tcl_Obj *result = Tcl_NewListObj(0, NULL);
+ Tcl_HashEntry *entryPtr = Tcl_FirstHashEntry(ht, &search);
+
+ while (entryPtr != NULL) {
+ Tcl_Obj *nameObj = Tcl_NewStringObj(Tcl_GetHashKey(ht, entryPtr),-1);
+ Tcl_Obj *valueObj = Tcl_GetHashValue(entryPtr);
+ Tcl_ListObjAppendElement(NULL, result, nameObj);
+ Tcl_ListObjAppendElement(NULL, result, valueObj);
+ entryPtr = Tcl_NextHashEntry(&search);
+ }
+
+ return result;
+}
+
+/* + style map $style ? -resource statemap ... ?
+ *
+ * Note that resource names are unconstrained; the Style
+ * doesn't know what resources individual elements may use.
+ */
+static int
+StyleMapCmd(
+ ClientData clientData, /* Master StylePackageData pointer */
+ Tcl_Interp *interp, /* Current interpreter */
+ int objc, /* Number of arguments */
+ Tcl_Obj *const objv[]) /* Argument objects */
+{
+ StylePackageData *pkgPtr = clientData;
+ Ttk_Theme theme = pkgPtr->currentTheme;
+ const char *styleName;
+ Style *stylePtr;
+ int i;
+
+ if (objc < 3) {
+usage:
+ Tcl_WrongNumArgs(interp,2,objv,"style ?-option ?value...??");
+ return TCL_ERROR;
+ }
+
+ styleName = Tcl_GetString(objv[2]);
+ stylePtr = Ttk_GetStyle(theme, styleName);
+
+ /* NOTE: StateMaps are actually Tcl_Obj *s, so HashTableToDict works
+ * for settingsTable.
+ */
+ if (objc == 3) { /* style map $styleName */
+ Tcl_SetObjResult(interp, HashTableToDict(&stylePtr->settingsTable));
+ return TCL_OK;
+ } else if (objc == 4) { /* style map $styleName -option */
+ const char *optionName = Tcl_GetString(objv[3]);
+ Tcl_HashEntry *entryPtr =
+ Tcl_FindHashEntry(&stylePtr->settingsTable, optionName);
+ if (entryPtr) {
+ Tcl_SetObjResult(interp, (Tcl_Obj*)Tcl_GetHashValue(entryPtr));
+ }
+ return TCL_OK;
+ } else if (objc % 2 != 1) {
+ goto usage;
+ }
+
+ for (i = 3; i < objc; i += 2) {
+ const char *optionName = Tcl_GetString(objv[i]);
+ Tcl_Obj *stateMap = objv[i+1];
+ Tcl_HashEntry *entryPtr;
+ int newEntry;
+
+ /* Make sure 'stateMap' is legal:
+ * (@@@ SHOULD: check for valid resource values as well,
+ * but we don't know what types they should be at this level.)
+ */
+ if (!Ttk_GetStateMapFromObj(interp, stateMap))
+ return TCL_ERROR;
+
+ entryPtr = Tcl_CreateHashEntry(
+ &stylePtr->settingsTable,optionName,&newEntry);
+
+ Tcl_IncrRefCount(stateMap);
+ if (!newEntry) {
+ Tcl_DecrRefCount((Tcl_Obj*)Tcl_GetHashValue(entryPtr));
+ }
+ Tcl_SetHashValue(entryPtr, stateMap);
+ }
+ ThemeChanged(pkgPtr);
+ return TCL_OK;
+}
+
+/* + style configure $style -option ?value...
+ */
+static int StyleConfigureCmd(
+ ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ StylePackageData *pkgPtr = clientData;
+ Ttk_Theme theme = pkgPtr->currentTheme;
+ const char *styleName;
+ Style *stylePtr;
+ int i;
+
+ if (objc < 3) {
+usage:
+ Tcl_WrongNumArgs(interp,2,objv,"style ?-option ?value...??");
+ return TCL_ERROR;
+ }
+
+ styleName = Tcl_GetString(objv[2]);
+ stylePtr = Ttk_GetStyle(theme, styleName);
+
+ if (objc == 3) { /* style default $styleName */
+ Tcl_SetObjResult(interp, HashTableToDict(&stylePtr->defaultsTable));
+ return TCL_OK;
+ } else if (objc == 4) { /* style default $styleName -option */
+ const char *optionName = Tcl_GetString(objv[3]);
+ Tcl_HashEntry *entryPtr =
+ Tcl_FindHashEntry(&stylePtr->defaultsTable, optionName);
+ if (entryPtr) {
+ Tcl_SetObjResult(interp, (Tcl_Obj*)Tcl_GetHashValue(entryPtr));
+ }
+ return TCL_OK;
+ } else if (objc % 2 != 1) {
+ goto usage;
+ }
+
+ for (i = 3; i < objc; i += 2) {
+ const char *optionName = Tcl_GetString(objv[i]);
+ Tcl_Obj *value = objv[i+1];
+ Tcl_HashEntry *entryPtr;
+ int newEntry;
+
+ entryPtr = Tcl_CreateHashEntry(
+ &stylePtr->defaultsTable,optionName,&newEntry);
+
+ Tcl_IncrRefCount(value);
+ if (!newEntry) {
+ Tcl_DecrRefCount((Tcl_Obj*)Tcl_GetHashValue(entryPtr));
+ }
+ Tcl_SetHashValue(entryPtr, value);
+ }
+
+ ThemeChanged(pkgPtr);
+ return TCL_OK;
+}
+
+/* + style lookup $style -option ?statespec? ?defaultValue?
+ */
+static int StyleLookupCmd(
+ ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ StylePackageData *pkgPtr = clientData;
+ Ttk_Theme theme = pkgPtr->currentTheme;
+ Ttk_Style style = NULL;
+ const char *optionName;
+ Ttk_State state = 0ul;
+ Tcl_Obj *result;
+
+ if (objc < 4 || objc > 6) {
+ Tcl_WrongNumArgs(interp, 2, objv, "style -option ?state? ?default?");
+ return TCL_ERROR;
+ }
+
+ style = Ttk_GetStyle(theme, Tcl_GetString(objv[2]));
+ if (!style) {
+ return TCL_ERROR;
+ }
+ optionName = Tcl_GetString(objv[3]);
+
+ if (objc >= 5) {
+ Ttk_StateSpec stateSpec;
+ /* @@@ SB: Ttk_GetStateFromObj(); 'offbits' spec is ignored */
+ if (Ttk_GetStateSpecFromObj(interp, objv[4], &stateSpec) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ state = stateSpec.onbits;
+ }
+
+ result = Ttk_QueryStyle(style, NULL,NULL, optionName, state);
+ if (result == NULL && objc >= 6) { /* Use caller-supplied fallback */
+ result = objv[5];
+ }
+
+ if (result) {
+ Tcl_SetObjResult(interp, result);
+ }
+
+ return TCL_OK;
+}
+
+static int StyleThemeCurrentCmd(
+ ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[])
+{
+ StylePackageData *pkgPtr = clientData;
+ Tcl_HashSearch search;
+ Tcl_HashEntry *entryPtr = NULL;
+ const char *name = NULL;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, "");
+ return TCL_ERROR;
+ }
+
+ entryPtr = Tcl_FirstHashEntry(&pkgPtr->themeTable, &search);
+ while (entryPtr != NULL) {
+ Theme *ptr = Tcl_GetHashValue(entryPtr);
+ if (ptr == pkgPtr->currentTheme) {
+ name = Tcl_GetHashKey(&pkgPtr->themeTable, entryPtr);
+ break;
+ }
+ entryPtr = Tcl_NextHashEntry(&search);
+ }
+
+ if (name == NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "error: failed to get theme name", -1));
+ Tcl_SetErrorCode(interp, "TTK", "THEME", "NAMELESS", NULL);
+ return TCL_ERROR;
+ }
+
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(name, -1));
+ return TCL_OK;
+}
+
+/* + style theme create name ?-parent $theme? ?-settings { script }?
+ */
+static int StyleThemeCreateCmd(
+ ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ StylePackageData *pkgPtr = clientData;
+ static const char *optStrings[] =
+ { "-parent", "-settings", NULL };
+ enum { OP_PARENT, OP_SETTINGS };
+ Ttk_Theme parentTheme = pkgPtr->defaultTheme, newTheme;
+ Tcl_Obj *settingsScript = NULL;
+ const char *themeName;
+ int i;
+
+ if (objc < 4 || objc % 2 != 0) {
+ Tcl_WrongNumArgs(interp, 3, objv, "name ?-option value ...?");
+ return TCL_ERROR;
+ }
+
+ themeName = Tcl_GetString(objv[3]);
+
+ for (i=4; i < objc; i +=2) {
+ int option;
+ if (Tcl_GetIndexFromObjStruct(interp, objv[i], optStrings,
+ sizeof(char *), "option", 0, &option) != TCL_OK)
+ {
+ return TCL_ERROR;
+ }
+
+ switch (option) {
+ case OP_PARENT:
+ parentTheme = LookupTheme(
+ interp, pkgPtr, Tcl_GetString(objv[i+1]));
+ if (!parentTheme)
+ return TCL_ERROR;
+ break;
+ case OP_SETTINGS:
+ settingsScript = objv[i+1];
+ break;
+ }
+ }
+
+ newTheme = Ttk_CreateTheme(interp, themeName, parentTheme);
+ if (!newTheme) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Evaluate the -settings script, if supplied:
+ */
+ if (settingsScript) {
+ Ttk_Theme oldTheme = pkgPtr->currentTheme;
+ int status;
+
+ pkgPtr->currentTheme = newTheme;
+ status = Tcl_EvalObjEx(interp, settingsScript, 0);
+ pkgPtr->currentTheme = oldTheme;
+ return status;
+ } else {
+ return TCL_OK;
+ }
+}
+
+/* + style theme names --
+ * Return list of registered themes.
+ */
+static int StyleThemeNamesCmd(
+ ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ StylePackageData *pkgPtr = clientData;
+ return TtkEnumerateHashTable(interp, &pkgPtr->themeTable);
+}
+
+/* + style theme settings $theme $script
+ *
+ * Temporarily sets the current theme to $themeName,
+ * evaluates $script, then restores the old theme.
+ */
+static int
+StyleThemeSettingsCmd(
+ ClientData clientData, /* Master StylePackageData pointer */
+ Tcl_Interp *interp, /* Current interpreter */
+ int objc, /* Number of arguments */
+ Tcl_Obj *const objv[]) /* Argument objects */
+{
+ StylePackageData *pkgPtr = clientData;
+ Ttk_Theme oldTheme = pkgPtr->currentTheme;
+ Ttk_Theme newTheme;
+ int status;
+
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 3, objv, "theme script");
+ return TCL_ERROR;
+ }
+
+ newTheme = LookupTheme(interp, pkgPtr, Tcl_GetString(objv[3]));
+ if (!newTheme)
+ return TCL_ERROR;
+
+ pkgPtr->currentTheme = newTheme;
+ status = Tcl_EvalObjEx(interp, objv[4], 0);
+ pkgPtr->currentTheme = oldTheme;
+
+ return status;
+}
+
+/* + style element create name type ? ...args ?
+ */
+static int StyleElementCreateCmd(
+ ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ StylePackageData *pkgPtr = clientData;
+ Ttk_Theme theme = pkgPtr->currentTheme;
+ const char *elementName, *factoryName;
+ Tcl_HashEntry *entryPtr;
+ FactoryRec *recPtr;
+
+ if (objc < 5) {
+ Tcl_WrongNumArgs(interp, 3, objv, "name type ?-option value ...?");
+ return TCL_ERROR;
+ }
+
+ elementName = Tcl_GetString(objv[3]);
+ factoryName = Tcl_GetString(objv[4]);
+
+ entryPtr = Tcl_FindHashEntry(&pkgPtr->factoryTable, factoryName);
+ if (!entryPtr) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "No such element type %s", factoryName));
+ Tcl_SetErrorCode(interp, "TTK", "LOOKUP", "ELEMENT_TYPE", factoryName,
+ NULL);
+ return TCL_ERROR;
+ }
+
+ recPtr = Tcl_GetHashValue(entryPtr);
+
+ return recPtr->factory(interp, recPtr->clientData,
+ theme, elementName, objc - 5, objv + 5);
+}
+
+/* + style element names --
+ * Return a list of elements defined in the current theme.
+ */
+static int StyleElementNamesCmd(
+ ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ StylePackageData *pkgPtr = clientData;
+ Ttk_Theme theme = pkgPtr->currentTheme;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ return TCL_ERROR;
+ }
+ return TtkEnumerateHashTable(interp, &theme->elementTable);
+}
+
+/* + style element options $element --
+ * Return list of element options for specified element
+ */
+static int StyleElementOptionsCmd(
+ ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ StylePackageData *pkgPtr = clientData;
+ Ttk_Theme theme = pkgPtr->currentTheme;
+ const char *elementName;
+ Ttk_ElementClass *elementClass;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "element");
+ return TCL_ERROR;
+ }
+
+ elementName = Tcl_GetString(objv[3]);
+ elementClass = Ttk_GetElement(theme, elementName);
+ if (elementClass) {
+ Ttk_ElementSpec *specPtr = elementClass->specPtr;
+ Ttk_ElementOptionSpec *option = specPtr->options;
+ Tcl_Obj *result = Tcl_NewListObj(0,0);
+
+ while (option->optionName) {
+ Tcl_ListObjAppendElement(
+ interp, result, Tcl_NewStringObj(option->optionName,-1));
+ ++option;
+ }
+
+ Tcl_SetObjResult(interp, result);
+ return TCL_OK;
+ }
+
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "element %s not found", elementName));
+ Tcl_SetErrorCode(interp, "TTK", "LOOKUP", "ELEMENT", elementName, NULL);
+ return TCL_ERROR;
+}
+
+/* + style layout name ?spec?
+ */
+static int StyleLayoutCmd(
+ ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ StylePackageData *pkgPtr = clientData;
+ Ttk_Theme theme = pkgPtr->currentTheme;
+ const char *layoutName;
+ Ttk_LayoutTemplate layoutTemplate;
+
+ if (objc < 3 || objc > 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "name ?spec?");
+ return TCL_ERROR;
+ }
+
+ layoutName = Tcl_GetString(objv[2]);
+
+ if (objc == 3) {
+ layoutTemplate = Ttk_FindLayoutTemplate(theme, layoutName);
+ if (!layoutTemplate) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "Layout %s not found", layoutName));
+ Tcl_SetErrorCode(interp, "TTK", "LOOKUP", "LAYOUT", layoutName,
+ NULL);
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, Ttk_UnparseLayoutTemplate(layoutTemplate));
+ } else {
+ layoutTemplate = Ttk_ParseLayoutTemplate(interp, objv[3]);
+ if (!layoutTemplate) {
+ return TCL_ERROR;
+ }
+ Ttk_RegisterLayoutTemplate(theme, layoutName, layoutTemplate);
+ ThemeChanged(pkgPtr);
+ }
+ return TCL_OK;
+}
+
+/* + style theme use $theme --
+ * Sets the current theme to $theme
+ */
+static int
+StyleThemeUseCmd(
+ ClientData clientData, /* Master StylePackageData pointer */
+ Tcl_Interp *interp, /* Current interpreter */
+ int objc, /* Number of arguments */
+ Tcl_Obj *const objv[]) /* Argument objects */
+{
+ StylePackageData *pkgPtr = clientData;
+ Ttk_Theme theme;
+
+ if (objc < 3 || objc > 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "?theme?");
+ return TCL_ERROR;
+ }
+
+ if (objc == 3) {
+ return StyleThemeCurrentCmd(clientData, interp, objc, objv);
+ }
+
+ theme = LookupTheme(interp, pkgPtr, Tcl_GetString(objv[3]));
+ if (!theme) {
+ return TCL_ERROR;
+ }
+
+ return Ttk_UseTheme(interp, theme);
+}
+
+/*
+ * StyleObjCmd --
+ * Implementation of the [style] command.
+ */
+
+static const Ttk_Ensemble StyleThemeEnsemble[] = {
+ { "create", StyleThemeCreateCmd, 0 },
+ { "names", StyleThemeNamesCmd, 0 },
+ { "settings", StyleThemeSettingsCmd, 0 },
+ { "use", StyleThemeUseCmd, 0 },
+ { NULL, 0, 0 }
+};
+
+static const Ttk_Ensemble StyleElementEnsemble[] = {
+ { "create", StyleElementCreateCmd, 0 },
+ { "names", StyleElementNamesCmd, 0 },
+ { "options", StyleElementOptionsCmd, 0 },
+ { NULL, 0, 0 }
+};
+
+static const Ttk_Ensemble StyleEnsemble[] = {
+ { "configure", StyleConfigureCmd, 0 },
+ { "map", StyleMapCmd, 0 },
+ { "lookup", StyleLookupCmd, 0 },
+ { "layout", StyleLayoutCmd, 0 },
+ { "theme", 0, StyleThemeEnsemble },
+ { "element", 0, StyleElementEnsemble },
+ { NULL, 0, 0 }
+};
+
+static int
+StyleObjCmd(
+ ClientData clientData, /* Master StylePackageData pointer */
+ Tcl_Interp *interp, /* Current interpreter */
+ int objc, /* Number of arguments */
+ Tcl_Obj *const objv[]) /* Argument objects */
+{
+ return Ttk_InvokeEnsemble(StyleEnsemble, 1, clientData,interp,objc,objv);
+}
+
+MODULE_SCOPE
+int Ttk_InvokeEnsemble( /* Run an ensemble command */
+ const Ttk_Ensemble *ensemble, int cmdIndex,
+ void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ while (cmdIndex < objc) {
+ int index;
+ if (Tcl_GetIndexFromObjStruct(interp,
+ objv[cmdIndex], ensemble, sizeof(ensemble[0]),
+ "command", 0, &index)
+ != TCL_OK)
+ {
+ return TCL_ERROR;
+ }
+
+ if (ensemble[index].command) {
+ return ensemble[index].command(clientData, interp, objc, objv);
+ }
+ ensemble = ensemble[index].ensemble;
+ ++cmdIndex;
+ }
+ Tcl_WrongNumArgs(interp, cmdIndex, objv, "option ?arg ...?");
+ return TCL_ERROR;
+}
+
+/*
+ * Ttk_StylePkgInit --
+ * Initializes all the structures that are used by the style
+ * package on a per-interp basis.
+ */
+
+void Ttk_StylePkgInit(Tcl_Interp *interp)
+{
+ Tcl_Namespace *nsPtr;
+
+ StylePackageData *pkgPtr = ckalloc(sizeof(StylePackageData));
+
+ pkgPtr->interp = interp;
+ Tcl_InitHashTable(&pkgPtr->themeTable, TCL_STRING_KEYS);
+ Tcl_InitHashTable(&pkgPtr->factoryTable, TCL_STRING_KEYS);
+ pkgPtr->cleanupList = NULL;
+ pkgPtr->cache = Ttk_CreateResourceCache(interp);
+ pkgPtr->themeChangePending = 0;
+
+ Tcl_SetAssocData(interp, PKG_ASSOC_KEY, Ttk_StylePkgFree, pkgPtr);
+
+ /*
+ * Create the default system theme:
+ *
+ * pkgPtr->defaultTheme must be initialized to 0 before
+ * calling Ttk_CreateTheme for the first time, since it's used
+ * as the parent theme.
+ */
+ pkgPtr->defaultTheme = 0;
+ pkgPtr->defaultTheme = pkgPtr->currentTheme =
+ Ttk_CreateTheme(interp, "default", NULL);
+
+ /*
+ * Register null element, used as a last-resort fallback:
+ */
+ Ttk_RegisterElement(interp, pkgPtr->defaultTheme, "", &ttkNullElementSpec, 0);
+
+ /*
+ * Register commands:
+ */
+ Tcl_CreateObjCommand(interp, "::ttk::style", StyleObjCmd, pkgPtr, 0);
+
+ nsPtr = Tcl_FindNamespace(interp, "::ttk", NULL, TCL_LEAVE_ERR_MSG);
+ Tcl_Export(interp, nsPtr, "style", 0 /* dontResetList */);
+
+ Ttk_RegisterElementFactory(interp, "from", Ttk_CloneElement, 0);
+}
+
+/*EOF*/
diff --git a/tk8.6/generic/ttk/ttkTheme.h b/tk8.6/generic/ttk/ttkTheme.h
new file mode 100644
index 0000000..cf0a07c
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkTheme.h
@@ -0,0 +1,450 @@
+/*
+ * Copyright (c) 2003 Joe English. Freely redistributable.
+ *
+ * Declarations for Tk theme engine.
+ */
+
+#ifndef _TTKTHEME
+#define _TTKTHEME
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef MODULE_SCOPE
+# ifdef __cplusplus
+# define MODULE_SCOPE extern "C"
+# else
+# define MODULE_SCOPE extern
+# endif
+#endif
+
+#define TTKAPI MODULE_SCOPE
+
+/* Ttk syncs to the Tk version & patchlevel */
+#define TTK_VERSION TK_VERSION
+#define TTK_PATCH_LEVEL TK_PATCH_LEVEL
+
+/*------------------------------------------------------------------------
+ * +++ Defaults for element option specifications.
+ */
+#define DEFAULT_FONT "TkDefaultFont"
+#ifdef MAC_OSX_TK
+#define DEFAULT_BACKGROUND "systemTextBackgroundColor"
+#define DEFAULT_FOREGROUND "systemTextColor"
+#else
+#define DEFAULT_BACKGROUND "#d9d9d9"
+#define DEFAULT_FOREGROUND "black"
+#endif
+/*------------------------------------------------------------------------
+ * +++ Widget states.
+ * Keep in sync with stateNames[] in tkstate.c.
+ */
+
+typedef unsigned int Ttk_State;
+
+#define TTK_STATE_ACTIVE (1<<0)
+#define TTK_STATE_DISABLED (1<<1)
+#define TTK_STATE_FOCUS (1<<2)
+#define TTK_STATE_PRESSED (1<<3)
+#define TTK_STATE_SELECTED (1<<4)
+#define TTK_STATE_BACKGROUND (1<<5)
+#define TTK_STATE_ALTERNATE (1<<6)
+#define TTK_STATE_INVALID (1<<7)
+#define TTK_STATE_READONLY (1<<8)
+#define TTK_STATE_HOVER (1<<9)
+#define TTK_STATE_USER6 (1<<10)
+#define TTK_STATE_USER5 (1<<11)
+#define TTK_STATE_USER4 (1<<12)
+#define TTK_STATE_USER3 (1<<13)
+#define TTK_STATE_USER2 (1<<14)
+#define TTK_STATE_USER1 (1<<15)
+
+/* Maintenance note: if you get all the way to "USER1",
+ * see tkstate.c
+ */
+typedef struct
+{
+ unsigned int onbits; /* bits to turn on */
+ unsigned int offbits; /* bits to turn off */
+} Ttk_StateSpec;
+
+#define Ttk_StateMatches(state, spec) \
+ (((state) & ((spec)->onbits|(spec)->offbits)) == (spec)->onbits)
+
+#define Ttk_ModifyState(state, spec) \
+ (((state) & ~(spec)->offbits) | (spec)->onbits)
+
+TTKAPI int Ttk_GetStateSpecFromObj(Tcl_Interp *, Tcl_Obj *, Ttk_StateSpec *);
+TTKAPI Tcl_Obj *Ttk_NewStateSpecObj(unsigned int onbits,unsigned int offbits);
+
+/*------------------------------------------------------------------------
+ * +++ State maps and state tables.
+ */
+typedef Tcl_Obj *Ttk_StateMap;
+
+TTKAPI Ttk_StateMap Ttk_GetStateMapFromObj(Tcl_Interp *, Tcl_Obj *);
+TTKAPI Tcl_Obj *Ttk_StateMapLookup(Tcl_Interp*, Ttk_StateMap, Ttk_State);
+
+/*
+ * Table for looking up an integer index based on widget state:
+ */
+typedef struct
+{
+ int index; /* Value to return if this entry matches */
+ unsigned int onBits; /* Bits which must be set */
+ unsigned int offBits; /* Bits which must be cleared */
+} Ttk_StateTable;
+
+TTKAPI int Ttk_StateTableLookup(Ttk_StateTable map[], Ttk_State);
+
+/*------------------------------------------------------------------------
+ * +++ Padding.
+ * Used to represent internal padding and borders.
+ */
+typedef struct
+{
+ short left;
+ short top;
+ short right;
+ short bottom;
+} Ttk_Padding;
+
+TTKAPI int Ttk_GetPaddingFromObj(Tcl_Interp*,Tk_Window,Tcl_Obj*,Ttk_Padding*);
+TTKAPI int Ttk_GetBorderFromObj(Tcl_Interp*,Tcl_Obj*,Ttk_Padding*);
+
+TTKAPI Ttk_Padding Ttk_MakePadding(short l, short t, short r, short b);
+TTKAPI Ttk_Padding Ttk_UniformPadding(short borderWidth);
+TTKAPI Ttk_Padding Ttk_AddPadding(Ttk_Padding, Ttk_Padding);
+TTKAPI Ttk_Padding Ttk_RelievePadding(Ttk_Padding, int relief, int n);
+
+#define Ttk_PaddingWidth(p) ((p).left + (p).right)
+#define Ttk_PaddingHeight(p) ((p).top + (p).bottom)
+
+#define Ttk_SetMargins(tkwin, pad) \
+ Tk_SetInternalBorderEx(tkwin, pad.left, pad.right, pad.top, pad.bottom)
+
+/*------------------------------------------------------------------------
+ * +++ Boxes.
+ * Used to represent rectangular regions
+ */
+typedef struct /* Hey, this is an XRectangle! */
+{
+ int x;
+ int y;
+ int width;
+ int height;
+} Ttk_Box;
+
+TTKAPI Ttk_Box Ttk_MakeBox(int x, int y, int width, int height);
+TTKAPI int Ttk_BoxContains(Ttk_Box, int x, int y);
+
+#define Ttk_WinBox(tkwin) Ttk_MakeBox(0,0,Tk_Width(tkwin),Tk_Height(tkwin))
+
+/*------------------------------------------------------------------------
+ * +++ Layout utilities.
+ */
+typedef enum {
+ TTK_SIDE_LEFT, TTK_SIDE_TOP, TTK_SIDE_RIGHT, TTK_SIDE_BOTTOM
+} Ttk_Side;
+
+typedef unsigned int Ttk_Sticky;
+
+/*
+ * -sticky bits for Ttk_StickBox:
+ */
+#define TTK_STICK_W (0x1)
+#define TTK_STICK_E (0x2)
+#define TTK_STICK_N (0x4)
+#define TTK_STICK_S (0x8)
+
+/*
+ * Aliases and useful combinations:
+ */
+#define TTK_FILL_X (0x3) /* -sticky ew */
+#define TTK_FILL_Y (0xC) /* -sticky ns */
+#define TTK_FILL_BOTH (0xF) /* -sticky nswe */
+
+TTKAPI int Ttk_GetStickyFromObj(Tcl_Interp *, Tcl_Obj *, Ttk_Sticky *);
+TTKAPI Tcl_Obj *Ttk_NewStickyObj(Ttk_Sticky);
+
+/*
+ * Extra bits for position specifications (combine -side and -sticky)
+ */
+
+typedef unsigned int Ttk_PositionSpec; /* See below */
+
+#define TTK_PACK_LEFT (0x10) /* pack at left of current parcel */
+#define TTK_PACK_RIGHT (0x20) /* pack at right of current parcel */
+#define TTK_PACK_TOP (0x40) /* pack at top of current parcel */
+#define TTK_PACK_BOTTOM (0x80) /* pack at bottom of current parcel */
+#define TTK_EXPAND (0x100) /* use entire parcel */
+#define TTK_BORDER (0x200) /* draw this element after children */
+#define TTK_UNIT (0x400) /* treat descendants as a part of element */
+
+/*
+ * Extra bits for layout specifications
+ */
+#define _TTK_CHILDREN (0x1000)/* for LayoutSpecs -- children follow */
+#define _TTK_LAYOUT_END (0x2000)/* for LayoutSpecs -- end of child list */
+#define _TTK_LAYOUT (0x4000)/* for LayoutSpec tables -- define layout */
+
+#define _TTK_MASK_STICK (0x0F) /* See Ttk_UnparseLayout() */
+#define _TTK_MASK_PACK (0xF0) /* See Ttk_UnparseLayout(), packStrings */
+
+TTKAPI Ttk_Box Ttk_PackBox(Ttk_Box *cavity, int w, int h, Ttk_Side side);
+TTKAPI Ttk_Box Ttk_StickBox(Ttk_Box parcel, int w, int h, Ttk_Sticky sticky);
+TTKAPI Ttk_Box Ttk_AnchorBox(Ttk_Box parcel, int w, int h, Tk_Anchor anchor);
+TTKAPI Ttk_Box Ttk_PadBox(Ttk_Box b, Ttk_Padding p);
+TTKAPI Ttk_Box Ttk_ExpandBox(Ttk_Box b, Ttk_Padding p);
+TTKAPI Ttk_Box Ttk_PlaceBox(Ttk_Box *cavity, int w,int h, Ttk_Side,Ttk_Sticky);
+TTKAPI Ttk_Box Ttk_PositionBox(Ttk_Box *cavity, int w, int h, Ttk_PositionSpec);
+
+/*------------------------------------------------------------------------
+ * +++ Themes.
+ */
+MODULE_SCOPE void Ttk_StylePkgInit(Tcl_Interp *);
+
+typedef struct Ttk_Theme_ *Ttk_Theme;
+typedef struct Ttk_ElementClass_ Ttk_ElementClass;
+typedef struct Ttk_Layout_ *Ttk_Layout;
+typedef struct Ttk_LayoutNode_ *Ttk_Element;
+typedef struct Ttk_Style_ *Ttk_Style;
+
+TTKAPI Ttk_Theme Ttk_GetTheme(Tcl_Interp *interp, const char *name);
+TTKAPI Ttk_Theme Ttk_GetDefaultTheme(Tcl_Interp *interp);
+TTKAPI Ttk_Theme Ttk_GetCurrentTheme(Tcl_Interp *interp);
+
+TTKAPI Ttk_Theme Ttk_CreateTheme(
+ Tcl_Interp *interp, const char *name, Ttk_Theme parent);
+
+typedef int (Ttk_ThemeEnabledProc)(Ttk_Theme theme, void *clientData);
+MODULE_SCOPE void Ttk_SetThemeEnabledProc(Ttk_Theme, Ttk_ThemeEnabledProc, void *);
+
+MODULE_SCOPE int Ttk_UseTheme(Tcl_Interp *, Ttk_Theme);
+
+typedef void (Ttk_CleanupProc)(void *clientData);
+TTKAPI void Ttk_RegisterCleanup(
+ Tcl_Interp *interp, void *deleteData, Ttk_CleanupProc *cleanupProc);
+
+/*------------------------------------------------------------------------
+ * +++ Elements.
+ */
+
+enum TTKStyleVersion2 { TK_STYLE_VERSION_2 = 2 };
+
+typedef void (Ttk_ElementSizeProc)(void *clientData, void *elementRecord,
+ Tk_Window tkwin, int *widthPtr, int *heightPtr, Ttk_Padding*);
+typedef void (Ttk_ElementDrawProc)(void *clientData, void *elementRecord,
+ Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state);
+
+typedef struct Ttk_ElementOptionSpec
+{
+ const char *optionName; /* Command-line name of the widget option */
+ Tk_OptionType type; /* Accepted option types */
+ int offset; /* Offset of Tcl_Obj* field in element record */
+ const char *defaultValue; /* Default value to used if resource missing */
+} Ttk_ElementOptionSpec;
+
+#define TK_OPTION_ANY TK_OPTION_STRING
+
+typedef struct Ttk_ElementSpec {
+ enum TTKStyleVersion2 version; /* Version of the style support. */
+ size_t elementSize; /* Size of element record */
+ Ttk_ElementOptionSpec *options; /* List of options, NULL-terminated */
+ Ttk_ElementSizeProc *size; /* Compute min size and padding */
+ Ttk_ElementDrawProc *draw; /* Draw the element */
+} Ttk_ElementSpec;
+
+TTKAPI Ttk_ElementClass *Ttk_RegisterElement(
+ Tcl_Interp *interp, Ttk_Theme theme, const char *elementName,
+ Ttk_ElementSpec *, void *clientData);
+
+typedef int (*Ttk_ElementFactory)
+ (Tcl_Interp *, void *clientData,
+ Ttk_Theme, const char *elementName, int objc, Tcl_Obj *const objv[]);
+
+TTKAPI int Ttk_RegisterElementFactory(
+ Tcl_Interp *, const char *name, Ttk_ElementFactory, void *clientData);
+
+/*
+ * Null element implementation:
+ * has no geometry or layout; may be used as a stub or placeholder.
+ */
+
+typedef struct {
+ Tcl_Obj *unused;
+} NullElement;
+
+MODULE_SCOPE void TtkNullElementSize
+ (void *, void *, Tk_Window, int *, int *, Ttk_Padding *);
+MODULE_SCOPE void TtkNullElementDraw
+ (void *, void *, Tk_Window, Drawable, Ttk_Box, Ttk_State);
+MODULE_SCOPE Ttk_ElementOptionSpec TtkNullElementOptions[];
+MODULE_SCOPE Ttk_ElementSpec ttkNullElementSpec;
+
+/*------------------------------------------------------------------------
+ * +++ Layout templates.
+ */
+typedef struct {
+ const char * elementName;
+ unsigned opcode;
+} TTKLayoutInstruction, *Ttk_LayoutSpec;
+
+#define TTK_BEGIN_LAYOUT_TABLE(name) \
+ static TTKLayoutInstruction name[] = {
+#define TTK_LAYOUT(name, content) \
+ { name, _TTK_CHILDREN|_TTK_LAYOUT }, \
+ content \
+ { 0, _TTK_LAYOUT_END },
+#define TTK_GROUP(name, flags, children) \
+ { name, flags | _TTK_CHILDREN }, \
+ children \
+ { 0, _TTK_LAYOUT_END },
+#define TTK_NODE(name, flags) { name, flags },
+#define TTK_END_LAYOUT_TABLE { 0, _TTK_LAYOUT | _TTK_LAYOUT_END } };
+
+#define TTK_BEGIN_LAYOUT(name) static TTKLayoutInstruction name[] = {
+#define TTK_END_LAYOUT { 0, _TTK_LAYOUT_END } };
+
+TTKAPI void Ttk_RegisterLayout(
+ Ttk_Theme theme, const char *className, Ttk_LayoutSpec layoutSpec);
+
+TTKAPI void Ttk_RegisterLayouts(
+ Ttk_Theme theme, Ttk_LayoutSpec layoutTable);
+
+/*------------------------------------------------------------------------
+ * +++ Layout instances.
+ */
+
+MODULE_SCOPE Ttk_Layout Ttk_CreateLayout(
+ Tcl_Interp *, Ttk_Theme, const char *name,
+ void *recordPtr, Tk_OptionTable, Tk_Window tkwin);
+
+MODULE_SCOPE Ttk_Layout Ttk_CreateSublayout(
+ Tcl_Interp *, Ttk_Theme, Ttk_Layout, const char *name, Tk_OptionTable);
+
+MODULE_SCOPE void Ttk_FreeLayout(Ttk_Layout);
+
+MODULE_SCOPE void Ttk_LayoutSize(Ttk_Layout,Ttk_State,int *widthPtr,int *heightPtr);
+MODULE_SCOPE void Ttk_PlaceLayout(Ttk_Layout, Ttk_State, Ttk_Box);
+MODULE_SCOPE void Ttk_DrawLayout(Ttk_Layout, Ttk_State, Drawable);
+
+MODULE_SCOPE void Ttk_RebindSublayout(Ttk_Layout, void *recordPtr);
+
+MODULE_SCOPE Ttk_Element Ttk_IdentifyElement(Ttk_Layout, int x, int y);
+MODULE_SCOPE Ttk_Element Ttk_FindElement(Ttk_Layout, const char *nodeName);
+
+MODULE_SCOPE const char *Ttk_ElementName(Ttk_Element);
+MODULE_SCOPE Ttk_Box Ttk_ElementParcel(Ttk_Element);
+
+MODULE_SCOPE Ttk_Box Ttk_ClientRegion(Ttk_Layout, const char *elementName);
+
+MODULE_SCOPE Ttk_Box Ttk_LayoutNodeInternalParcel(Ttk_Layout,Ttk_Element);
+MODULE_SCOPE Ttk_Padding Ttk_LayoutNodeInternalPadding(Ttk_Layout,Ttk_Element);
+MODULE_SCOPE void Ttk_LayoutNodeReqSize(Ttk_Layout, Ttk_Element, int *w, int *h);
+
+MODULE_SCOPE void Ttk_PlaceElement(Ttk_Layout, Ttk_Element, Ttk_Box);
+MODULE_SCOPE void Ttk_ChangeElementState(Ttk_Element,unsigned set,unsigned clr);
+
+MODULE_SCOPE Tcl_Obj *Ttk_QueryOption(Ttk_Layout, const char *, Ttk_State);
+
+TTKAPI Ttk_Style Ttk_LayoutStyle(Ttk_Layout);
+TTKAPI Tcl_Obj *Ttk_StyleDefault(Ttk_Style, const char *optionName);
+TTKAPI Tcl_Obj *Ttk_StyleMap(Ttk_Style, const char *optionName, Ttk_State);
+
+/*------------------------------------------------------------------------
+ * +++ Resource cache.
+ * See resource.c for explanation.
+ */
+
+typedef struct Ttk_ResourceCache_ *Ttk_ResourceCache;
+MODULE_SCOPE Ttk_ResourceCache Ttk_CreateResourceCache(Tcl_Interp *);
+MODULE_SCOPE void Ttk_FreeResourceCache(Ttk_ResourceCache);
+
+MODULE_SCOPE Ttk_ResourceCache Ttk_GetResourceCache(Tcl_Interp*);
+MODULE_SCOPE Tcl_Obj *Ttk_UseFont(Ttk_ResourceCache, Tk_Window, Tcl_Obj *);
+MODULE_SCOPE Tcl_Obj *Ttk_UseColor(Ttk_ResourceCache, Tk_Window, Tcl_Obj *);
+MODULE_SCOPE Tcl_Obj *Ttk_UseBorder(Ttk_ResourceCache, Tk_Window, Tcl_Obj *);
+MODULE_SCOPE Tk_Image Ttk_UseImage(Ttk_ResourceCache, Tk_Window, Tcl_Obj *);
+
+MODULE_SCOPE void Ttk_RegisterNamedColor(Ttk_ResourceCache, const char *, XColor *);
+
+/*------------------------------------------------------------------------
+ * +++ Image specifications.
+ */
+
+typedef struct TtkImageSpec Ttk_ImageSpec;
+TTKAPI Ttk_ImageSpec *TtkGetImageSpec(Tcl_Interp *, Tk_Window, Tcl_Obj *);
+TTKAPI Ttk_ImageSpec *TtkGetImageSpecEx(Tcl_Interp *, Tk_Window, Tcl_Obj *,
+ Tk_ImageChangedProc *, ClientData);
+TTKAPI void TtkFreeImageSpec(Ttk_ImageSpec *);
+TTKAPI Tk_Image TtkSelectImage(Ttk_ImageSpec *, Ttk_State);
+
+/*------------------------------------------------------------------------
+ * +++ Miscellaneous enumerations.
+ * Other stuff that element implementations need to know about.
+ */
+typedef enum /* -default option values */
+{
+ TTK_BUTTON_DEFAULT_NORMAL, /* widget defaultable */
+ TTK_BUTTON_DEFAULT_ACTIVE, /* currently the default widget */
+ TTK_BUTTON_DEFAULT_DISABLED /* not defaultable */
+} Ttk_ButtonDefaultState;
+
+TTKAPI int Ttk_GetButtonDefaultStateFromObj(Tcl_Interp *, Tcl_Obj *, int *);
+
+typedef enum /* -compound option values */
+{
+ TTK_COMPOUND_NONE, /* image if specified, otherwise text */
+ TTK_COMPOUND_TEXT, /* text only */
+ TTK_COMPOUND_IMAGE, /* image only */
+ TTK_COMPOUND_CENTER, /* text overlays image */
+ TTK_COMPOUND_TOP, /* image above text */
+ TTK_COMPOUND_BOTTOM, /* image below text */
+ TTK_COMPOUND_LEFT, /* image to left of text */
+ TTK_COMPOUND_RIGHT /* image to right of text */
+} Ttk_Compound;
+
+TTKAPI int Ttk_GetCompoundFromObj(Tcl_Interp *, Tcl_Obj *, int *);
+
+typedef enum { /* -orient option values */
+ TTK_ORIENT_HORIZONTAL,
+ TTK_ORIENT_VERTICAL
+} Ttk_Orient;
+
+/*------------------------------------------------------------------------
+ * +++ Utilities.
+ */
+
+typedef struct TtkEnsemble {
+ const char *name; /* subcommand name */
+ Tcl_ObjCmdProc *command; /* subcommand implementation, OR: */
+ const struct TtkEnsemble *ensemble; /* subcommand ensemble */
+} Ttk_Ensemble;
+
+MODULE_SCOPE int Ttk_InvokeEnsemble( /* Run an ensemble command */
+ const Ttk_Ensemble *commands, int cmdIndex,
+ void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
+
+MODULE_SCOPE int TtkEnumerateHashTable(Tcl_Interp *, Tcl_HashTable *);
+
+/*------------------------------------------------------------------------
+ * +++ Stub table declarations.
+ */
+
+#include "ttkDecls.h"
+
+/*
+ * Drawing utilities for theme code:
+ * (@@@ find a better home for this)
+ */
+typedef enum { ARROW_UP, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT } ArrowDirection;
+MODULE_SCOPE void TtkArrowSize(int h, ArrowDirection, int *widthPtr, int *heightPtr);
+MODULE_SCOPE void TtkDrawArrow(Display *, Drawable, GC, Ttk_Box, ArrowDirection);
+MODULE_SCOPE void TtkFillArrow(Display *, Drawable, GC, Ttk_Box, ArrowDirection);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _TTKTHEME */
diff --git a/tk8.6/generic/ttk/ttkThemeInt.h b/tk8.6/generic/ttk/ttkThemeInt.h
new file mode 100644
index 0000000..3aaada8
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkThemeInt.h
@@ -0,0 +1,42 @@
+/*
+ * Theme engine: private definitions.
+ *
+ * Copyright (c) 2004 Joe English. Freely redistributable.
+ */
+
+#ifndef _TTKTHEMEINT
+#define _TTKTHEMEINT
+
+#include "ttkTheme.h"
+
+typedef struct Ttk_TemplateNode_ Ttk_TemplateNode, *Ttk_LayoutTemplate;
+
+MODULE_SCOPE Ttk_ElementClass *Ttk_GetElement(Ttk_Theme, const char *name);
+MODULE_SCOPE const char *Ttk_ElementClassName(Ttk_ElementClass *);
+
+MODULE_SCOPE void Ttk_ElementSize(
+ Ttk_ElementClass *, Ttk_Style, char *recordPtr, Tk_OptionTable,
+ Tk_Window tkwin, Ttk_State state,
+ int *widthPtr, int *heightPtr, Ttk_Padding*);
+MODULE_SCOPE void Ttk_DrawElement(
+ Ttk_ElementClass *, Ttk_Style, char *recordPtr, Tk_OptionTable,
+ Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state);
+
+MODULE_SCOPE Tcl_Obj *Ttk_QueryStyle(
+ Ttk_Style, void *, Tk_OptionTable, const char *, Ttk_State state);
+
+MODULE_SCOPE Ttk_LayoutTemplate Ttk_ParseLayoutTemplate(
+ Tcl_Interp *, Tcl_Obj *);
+MODULE_SCOPE Tcl_Obj *Ttk_UnparseLayoutTemplate(Ttk_LayoutTemplate);
+MODULE_SCOPE Ttk_LayoutTemplate Ttk_BuildLayoutTemplate(Ttk_LayoutSpec);
+MODULE_SCOPE void Ttk_FreeLayoutTemplate(Ttk_LayoutTemplate);
+MODULE_SCOPE void Ttk_RegisterLayoutTemplate(
+ Ttk_Theme theme, const char *layoutName, Ttk_LayoutTemplate);
+
+MODULE_SCOPE Ttk_Style Ttk_GetStyle(Ttk_Theme themePtr, const char *styleName);
+MODULE_SCOPE Ttk_LayoutTemplate Ttk_FindLayoutTemplate(
+ Ttk_Theme themePtr, const char *layoutName);
+
+MODULE_SCOPE const char *Ttk_StyleName(Ttk_Style);
+
+#endif /* _TTKTHEMEINT */
diff --git a/tk8.6/generic/ttk/ttkTrace.c b/tk8.6/generic/ttk/ttkTrace.c
new file mode 100644
index 0000000..7c4345d
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkTrace.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2003, Joe English
+ *
+ * Simplified interface to Tcl_TraceVariable.
+ *
+ * PROBLEM: Can't distinguish "variable does not exist" (which is OK)
+ * from other errors (which are not).
+ */
+
+#include <tk.h>
+#include "ttkTheme.h"
+#include "ttkWidget.h"
+
+struct TtkTraceHandle_
+{
+ Tcl_Interp *interp; /* Containing interpreter */
+ Tcl_Obj *varnameObj; /* Name of variable being traced */
+ Ttk_TraceProc callback; /* Callback procedure */
+ void *clientData; /* Data to pass to callback */
+};
+
+/*
+ * Tcl_VarTraceProc for trace handles.
+ */
+static char *
+VarTraceProc(
+ ClientData clientData, /* Widget record pointer */
+ Tcl_Interp *interp, /* Interpreter containing variable. */
+ const char *name1, /* (unused) */
+ const char *name2, /* (unused) */
+ int flags) /* Information about what happened. */
+{
+ Ttk_TraceHandle *tracePtr = clientData;
+ const char *name, *value;
+ Tcl_Obj *valuePtr;
+
+ if (Tcl_InterpDeleted(interp)) {
+ return NULL;
+ }
+
+ name = Tcl_GetString(tracePtr->varnameObj);
+
+ /*
+ * If the variable is being unset, then re-establish the trace:
+ */
+ if (flags & TCL_TRACE_DESTROYED) {
+ /*
+ * If a prior call to Ttk_UntraceVariable() left behind an
+ * indicator that we wanted this handler to be deleted (see below),
+ * cleanup the ClientData bits and exit.
+ */
+ if (tracePtr->interp == NULL) {
+ Tcl_DecrRefCount(tracePtr->varnameObj);
+ ckfree((ClientData)tracePtr);
+ return NULL;
+ }
+ Tcl_TraceVar2(interp, name, NULL,
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ VarTraceProc, clientData);
+ tracePtr->callback(tracePtr->clientData, NULL);
+ return NULL;
+ }
+
+ /*
+ * Call the callback:
+ */
+ valuePtr = Tcl_GetVar2Ex(interp, name, NULL, TCL_GLOBAL_ONLY);
+ value = valuePtr ? Tcl_GetString(valuePtr) : NULL;
+ tracePtr->callback(tracePtr->clientData, value);
+
+ return NULL;
+}
+
+/* Ttk_TraceVariable(interp, varNameObj, callback, clientdata) --
+ * Attach a write trace to the specified variable,
+ * which will pass the variable's value to 'callback'
+ * whenever the variable is set.
+ *
+ * When the variable is unset, passes NULL to the callback
+ * and reattaches the trace.
+ */
+Ttk_TraceHandle *Ttk_TraceVariable(
+ Tcl_Interp *interp,
+ Tcl_Obj *varnameObj,
+ Ttk_TraceProc callback,
+ void *clientData)
+{
+ Ttk_TraceHandle *h = ckalloc(sizeof(*h));
+ int status;
+
+ h->interp = interp;
+ h->varnameObj = Tcl_DuplicateObj(varnameObj);
+ Tcl_IncrRefCount(h->varnameObj);
+ h->clientData = clientData;
+ h->callback = callback;
+
+ status = Tcl_TraceVar2(interp, Tcl_GetString(varnameObj),
+ NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ VarTraceProc, (ClientData)h);
+
+ if (status != TCL_OK) {
+ Tcl_DecrRefCount(h->varnameObj);
+ ckfree(h);
+ return NULL;
+ }
+
+ return h;
+}
+
+/*
+ * Ttk_UntraceVariable --
+ * Remove previously-registered trace and free the handle.
+ */
+void Ttk_UntraceVariable(Ttk_TraceHandle *h)
+{
+ if (h) {
+ ClientData cd = NULL;
+
+ /*
+ * Workaround for Tcl Bug 3062331. The trace design problem is
+ * that when variable unset traces fire, Tcl documents that the
+ * traced variable has already been unset. It's already gone.
+ * So from within an unset trace, if you try to call
+ * Tcl_UntraceVar() on that variable, it will do nothing, because
+ * the variable by that name can no longer be found. It's gone.
+ * This means callers of Tcl_UntraceVar() that might be running
+ * in response to an unset trace have to handle the possibility
+ * that their Tcl_UntraceVar() call will do nothing. In this case,
+ * we have to support the possibility that Tcl_UntraceVar() will
+ * leave the trace in place, so we need to leave the ClientData
+ * untouched so when that trace does fire it will not crash.
+ */
+
+ /*
+ * Search the traces on the variable to see if the one we are tasked
+ * with removing is present.
+ */
+ while ((cd = Tcl_VarTraceInfo(h->interp, Tcl_GetString(h->varnameObj),
+ TCL_GLOBAL_ONLY, VarTraceProc, cd)) != NULL) {
+ if (cd == (ClientData) h) {
+ break;
+ }
+ }
+ /*
+ * If the trace we wish to delete is not visible, Tcl_UntraceVar
+ * will do nothing, so don't try to call it. Instead set an
+ * indicator in the Ttk_TraceHandle that we need to cleanup later.
+ */
+ if (cd == NULL) {
+ h->interp = NULL;
+ return;
+ }
+ Tcl_UntraceVar2(h->interp, Tcl_GetString(h->varnameObj),
+ NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ VarTraceProc, (ClientData)h);
+ Tcl_DecrRefCount(h->varnameObj);
+ ckfree(h);
+ }
+}
+
+/*
+ * Ttk_FireTrace --
+ * Executes a trace handle as if the variable has been written.
+ *
+ * Note: may reenter the interpreter.
+ */
+int Ttk_FireTrace(Ttk_TraceHandle *tracePtr)
+{
+ Tcl_Interp *interp = tracePtr->interp;
+ void *clientData = tracePtr->clientData;
+ const char *name = Tcl_GetString(tracePtr->varnameObj);
+ Ttk_TraceProc callback = tracePtr->callback;
+ Tcl_Obj *valuePtr;
+ const char *value;
+
+ /* Read the variable.
+ * Note that this can reenter the interpreter, and anything can happen --
+ * including the current trace handle being freed!
+ */
+ valuePtr = Tcl_GetVar2Ex(interp, name, NULL, TCL_GLOBAL_ONLY);
+ value = valuePtr ? Tcl_GetString(valuePtr) : NULL;
+
+ /* Call callback.
+ */
+ callback(clientData, value);
+
+ return TCL_OK;
+}
+
+/*EOF*/
diff --git a/tk8.6/generic/ttk/ttkTrack.c b/tk8.6/generic/ttk/ttkTrack.c
new file mode 100644
index 0000000..396b073
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkTrack.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2004, Joe English
+ *
+ * TtkTrackElementState() -- helper routine for widgets
+ * like scrollbars in which individual elements may
+ * be active or pressed instead of the widget as a whole.
+ *
+ * Usage:
+ * TtkTrackElementState(&recordPtr->core);
+ *
+ * Registers an event handler on the widget that tracks pointer
+ * events and updates the state of the element under the
+ * mouse cursor.
+ *
+ * The "active" element is the one under the mouse cursor,
+ * and is normally set to the ACTIVE state unless another element
+ * is currently being pressed.
+ *
+ * The active element becomes "pressed" on <ButtonPress> events,
+ * and remains "active" and "pressed" until the corresponding
+ * <ButtonRelease> event.
+ *
+ * TODO: Handle "chords" properly (e.g., <B1-ButtonPress-2>)
+ */
+
+#include <tk.h>
+#include "ttkTheme.h"
+#include "ttkWidget.h"
+
+typedef struct {
+ WidgetCore *corePtr; /* widget to track */
+ Ttk_Layout tracking; /* current layout being tracked */
+ Ttk_Element activeElement; /* element under the mouse cursor */
+ Ttk_Element pressedElement; /* currently pressed element */
+} ElementStateTracker;
+
+/*
+ * ActivateElement(es, node) --
+ * Make 'node' the active element if non-NULL.
+ * Deactivates the currently active element if different.
+ *
+ * The active element has TTK_STATE_ACTIVE set _unless_
+ * another element is 'pressed'
+ */
+static void ActivateElement(ElementStateTracker *es, Ttk_Element element)
+{
+ if (es->activeElement == element) {
+ /* No change */
+ return;
+ }
+
+ if (!es->pressedElement) {
+ if (es->activeElement) {
+ /* Deactivate old element */
+ Ttk_ChangeElementState(es->activeElement, 0,TTK_STATE_ACTIVE);
+ }
+ if (element) {
+ /* Activate new element */
+ Ttk_ChangeElementState(element, TTK_STATE_ACTIVE,0);
+ }
+ TtkRedisplayWidget(es->corePtr);
+ }
+
+ es->activeElement = element;
+}
+
+/* ReleaseElement --
+ * Releases the currently pressed element, if any.
+ */
+static void ReleaseElement(ElementStateTracker *es)
+{
+ if (!es->pressedElement)
+ return;
+
+ Ttk_ChangeElementState(
+ es->pressedElement, 0,TTK_STATE_PRESSED|TTK_STATE_ACTIVE);
+ es->pressedElement = 0;
+
+ /* Reactivate element under the mouse cursor:
+ */
+ if (es->activeElement)
+ Ttk_ChangeElementState(es->activeElement, TTK_STATE_ACTIVE,0);
+
+ TtkRedisplayWidget(es->corePtr);
+}
+
+/* PressElement --
+ * Presses the specified element.
+ */
+static void PressElement(ElementStateTracker *es, Ttk_Element element)
+{
+ if (es->pressedElement) {
+ ReleaseElement(es);
+ }
+
+ if (element) {
+ Ttk_ChangeElementState(
+ element, TTK_STATE_PRESSED|TTK_STATE_ACTIVE, 0);
+ }
+
+ es->pressedElement = element;
+ TtkRedisplayWidget(es->corePtr);
+}
+
+/* ElementStateEventProc --
+ * Event handler for tracking element states.
+ */
+
+static const unsigned ElementStateMask =
+ ButtonPressMask
+ | ButtonReleaseMask
+ | PointerMotionMask
+ | LeaveWindowMask
+ | EnterWindowMask
+ | StructureNotifyMask
+ ;
+
+static void
+ElementStateEventProc(ClientData clientData, XEvent *ev)
+{
+ ElementStateTracker *es = clientData;
+ Ttk_Layout layout = es->corePtr->layout;
+ Ttk_Element element;
+
+ /* Guard against dangling pointers [#2431428]
+ */
+ if (es->tracking != layout) {
+ es->pressedElement = es->activeElement = 0;
+ es->tracking = layout;
+ }
+
+ switch (ev->type)
+ {
+ case MotionNotify :
+ element = Ttk_IdentifyElement(
+ layout, ev->xmotion.x, ev->xmotion.y);
+ ActivateElement(es, element);
+ break;
+ case LeaveNotify:
+ ActivateElement(es, 0);
+ if (ev->xcrossing.mode == NotifyGrab)
+ PressElement(es, 0);
+ break;
+ case EnterNotify:
+ element = Ttk_IdentifyElement(
+ layout, ev->xcrossing.x, ev->xcrossing.y);
+ ActivateElement(es, element);
+ break;
+ case ButtonPress:
+ element = Ttk_IdentifyElement(
+ layout, ev->xbutton.x, ev->xbutton.y);
+ if (element)
+ PressElement(es, element);
+ break;
+ case ButtonRelease:
+ ReleaseElement(es);
+ break;
+ case DestroyNotify:
+ /* Unregister this event handler and free client data.
+ */
+ Tk_DeleteEventHandler(es->corePtr->tkwin,
+ ElementStateMask, ElementStateEventProc, es);
+ ckfree(clientData);
+ break;
+ }
+}
+
+/*
+ * TtkTrackElementState --
+ * Register an event handler to manage the 'pressed'
+ * and 'active' states of individual widget elements.
+ */
+
+void TtkTrackElementState(WidgetCore *corePtr)
+{
+ ElementStateTracker *es = ckalloc(sizeof(*es));
+ es->corePtr = corePtr;
+ es->tracking = 0;
+ es->activeElement = es->pressedElement = 0;
+ Tk_CreateEventHandler(corePtr->tkwin,
+ ElementStateMask,ElementStateEventProc,es);
+}
+
diff --git a/tk8.6/generic/ttk/ttkTreeview.c b/tk8.6/generic/ttk/ttkTreeview.c
new file mode 100644
index 0000000..b1739b6
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkTreeview.c
@@ -0,0 +1,3488 @@
+/*
+ * Copyright (c) 2004, Joe English
+ *
+ * ttk::treeview widget implementation.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include "tkInt.h"
+#include "ttkTheme.h"
+#include "ttkWidget.h"
+
+#define DEF_TREE_ROWS "10"
+#define DEF_COLWIDTH "200"
+#define DEF_MINWIDTH "20"
+
+static const int DEFAULT_ROWHEIGHT = 20;
+static const int DEFAULT_INDENT = 20;
+static const int HALO = 4; /* separator */
+
+#define TTK_STATE_OPEN TTK_STATE_USER1
+#define TTK_STATE_LEAF TTK_STATE_USER2
+
+#define STATE_CHANGED (0x100) /* item state option changed */
+
+/*------------------------------------------------------------------------
+ * +++ Tree items.
+ *
+ * INVARIANTS:
+ * item->children ==> item->children->parent == item
+ * item->next ==> item->next->parent == item->parent
+ * item->next ==> item->next->prev == item
+ * item->prev ==> item->prev->next == item
+ */
+
+typedef struct TreeItemRec TreeItem;
+struct TreeItemRec {
+ Tcl_HashEntry *entryPtr; /* Back-pointer to hash table entry */
+ TreeItem *parent; /* Parent item */
+ TreeItem *children; /* Linked list of child items */
+ TreeItem *next; /* Next sibling */
+ TreeItem *prev; /* Previous sibling */
+
+ /*
+ * Options and instance data:
+ */
+ Ttk_State state;
+ Tcl_Obj *textObj;
+ Tcl_Obj *imageObj;
+ Tcl_Obj *valuesObj;
+ Tcl_Obj *openObj;
+ Tcl_Obj *tagsObj;
+
+ /*
+ * Derived resources:
+ */
+ Ttk_TagSet tagset;
+ Ttk_ImageSpec *imagespec;
+};
+
+#define ITEM_OPTION_TAGS_CHANGED 0x100
+#define ITEM_OPTION_IMAGE_CHANGED 0x200
+
+static Tk_OptionSpec ItemOptionSpecs[] = {
+ {TK_OPTION_STRING, "-text", "text", "Text",
+ "", Tk_Offset(TreeItem,textObj), -1,
+ 0,0,0 },
+ {TK_OPTION_STRING, "-image", "image", "Image",
+ NULL, Tk_Offset(TreeItem,imageObj), -1,
+ TK_OPTION_NULL_OK,0,ITEM_OPTION_IMAGE_CHANGED },
+ {TK_OPTION_STRING, "-values", "values", "Values",
+ NULL, Tk_Offset(TreeItem,valuesObj), -1,
+ TK_OPTION_NULL_OK,0,0 },
+ {TK_OPTION_BOOLEAN, "-open", "open", "Open",
+ "0", Tk_Offset(TreeItem,openObj), -1,
+ 0,0,0 },
+ {TK_OPTION_STRING, "-tags", "tags", "Tags",
+ NULL, Tk_Offset(TreeItem,tagsObj), -1,
+ TK_OPTION_NULL_OK,0,ITEM_OPTION_TAGS_CHANGED },
+
+ {TK_OPTION_END, 0,0,0, NULL, -1,-1, 0,0,0}
+};
+
+/* + NewItem --
+ * Allocate a new, uninitialized, unlinked item
+ */
+static TreeItem *NewItem(void)
+{
+ TreeItem *item = ckalloc(sizeof(*item));
+
+ item->entryPtr = 0;
+ item->parent = item->children = item->next = item->prev = NULL;
+
+ item->state = 0ul;
+ item->textObj = NULL;
+ item->imageObj = NULL;
+ item->valuesObj = NULL;
+ item->openObj = NULL;
+ item->tagsObj = NULL;
+
+ item->tagset = NULL;
+ item->imagespec = NULL;
+
+ return item;
+}
+
+/* + FreeItem --
+ * Destroy an item
+ */
+static void FreeItem(TreeItem *item)
+{
+ if (item->textObj) { Tcl_DecrRefCount(item->textObj); }
+ if (item->imageObj) { Tcl_DecrRefCount(item->imageObj); }
+ if (item->valuesObj) { Tcl_DecrRefCount(item->valuesObj); }
+ if (item->openObj) { Tcl_DecrRefCount(item->openObj); }
+ if (item->tagsObj) { Tcl_DecrRefCount(item->tagsObj); }
+
+ if (item->tagset) { Ttk_FreeTagSet(item->tagset); }
+ if (item->imagespec) { TtkFreeImageSpec(item->imagespec); }
+
+ ckfree(item);
+}
+
+static void FreeItemCB(void *clientData) { FreeItem(clientData); }
+
+/* + DetachItem --
+ * Unlink an item from the tree.
+ */
+static void DetachItem(TreeItem *item)
+{
+ if (item->parent && item->parent->children == item)
+ item->parent->children = item->next;
+ if (item->prev)
+ item->prev->next = item->next;
+ if (item->next)
+ item->next->prev = item->prev;
+ item->next = item->prev = item->parent = NULL;
+}
+
+/* + InsertItem --
+ * Insert an item into the tree after the specified item.
+ *
+ * Preconditions:
+ * + item is currently detached
+ * + prev != NULL ==> prev->parent == parent.
+ */
+static void InsertItem(TreeItem *parent, TreeItem *prev, TreeItem *item)
+{
+ item->parent = parent;
+ item->prev = prev;
+ if (prev) {
+ item->next = prev->next;
+ prev->next = item;
+ } else {
+ item->next = parent->children;
+ parent->children = item;
+ }
+ if (item->next) {
+ item->next->prev = item;
+ }
+}
+
+/* + NextPreorder --
+ * Return the next item in preorder traversal order.
+ */
+
+static TreeItem *NextPreorder(TreeItem *item)
+{
+ if (item->children)
+ return item->children;
+ while (!item->next) {
+ item = item->parent;
+ if (!item)
+ return 0;
+ }
+ return item->next;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Display items and tag options.
+ */
+
+typedef struct {
+ Tcl_Obj *textObj; /* taken from item / data cell */
+ Tcl_Obj *imageObj; /* taken from item */
+ Tcl_Obj *anchorObj; /* from column <<NOTE-ANCHOR>> */
+ Tcl_Obj *backgroundObj; /* remainder from tag */
+ Tcl_Obj *foregroundObj;
+ Tcl_Obj *fontObj;
+} DisplayItem;
+
+static Tk_OptionSpec TagOptionSpecs[] = {
+ {TK_OPTION_STRING, "-text", "text", "Text",
+ NULL, Tk_Offset(DisplayItem,textObj), -1,
+ TK_OPTION_NULL_OK,0,0 },
+ {TK_OPTION_STRING, "-image", "image", "Image",
+ NULL, Tk_Offset(DisplayItem,imageObj), -1,
+ TK_OPTION_NULL_OK,0,0 },
+ {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
+ NULL, Tk_Offset(DisplayItem,anchorObj), -1,
+ TK_OPTION_NULL_OK, 0, GEOMETRY_CHANGED}, /* <<NOTE-ANCHOR>> */
+ {TK_OPTION_COLOR, "-background", "windowColor", "WindowColor",
+ NULL, Tk_Offset(DisplayItem,backgroundObj), -1,
+ TK_OPTION_NULL_OK,0,0 },
+ {TK_OPTION_COLOR, "-foreground", "textColor", "TextColor",
+ NULL, Tk_Offset(DisplayItem,foregroundObj), -1,
+ TK_OPTION_NULL_OK,0,0 },
+ {TK_OPTION_FONT, "-font", "font", "Font",
+ NULL, Tk_Offset(DisplayItem,fontObj), -1,
+ TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
+
+ {TK_OPTION_END, 0,0,0, NULL, -1,-1, 0,0,0}
+};
+
+/*------------------------------------------------------------------------
+ * +++ Columns.
+ *
+ * There are separate option tables associated with the column record:
+ * ColumnOptionSpecs is for configuring the column,
+ * and HeadingOptionSpecs is for drawing headings.
+ */
+typedef struct {
+ int width; /* Column width, in pixels */
+ int minWidth; /* Minimum column width, in pixels */
+ int stretch; /* Should column stretch while resizing? */
+ Tcl_Obj *idObj; /* Column identifier, from -columns option */
+
+ Tcl_Obj *anchorObj; /* -anchor for cell data <<NOTE-ANCHOR>> */
+
+ /* Column heading data:
+ */
+ Tcl_Obj *headingObj; /* Heading label */
+ Tcl_Obj *headingImageObj; /* Heading image */
+ Tcl_Obj *headingAnchorObj; /* -anchor for heading label */
+ Tcl_Obj *headingCommandObj; /* Command to execute */
+ Tcl_Obj *headingStateObj; /* @@@ testing ... */
+ Ttk_State headingState; /* ... */
+
+ /* Temporary storage for cell data
+ */
+ Tcl_Obj *data;
+} TreeColumn;
+
+static void InitColumn(TreeColumn *column)
+{
+ column->width = 200;
+ column->minWidth = 20;
+ column->stretch = 1;
+ column->idObj = 0;
+ column->anchorObj = 0;
+
+ column->headingState = 0;
+ column->headingObj = 0;
+ column->headingImageObj = 0;
+ column->headingAnchorObj = 0;
+ column->headingStateObj = 0;
+ column->headingCommandObj = 0;
+
+ column->data = 0;
+}
+
+static void FreeColumn(TreeColumn *column)
+{
+ if (column->idObj) { Tcl_DecrRefCount(column->idObj); }
+ if (column->anchorObj) { Tcl_DecrRefCount(column->anchorObj); }
+
+ if (column->headingObj) { Tcl_DecrRefCount(column->headingObj); }
+ if (column->headingImageObj) { Tcl_DecrRefCount(column->headingImageObj); }
+ if (column->headingAnchorObj) { Tcl_DecrRefCount(column->headingAnchorObj); }
+ if (column->headingStateObj) { Tcl_DecrRefCount(column->headingStateObj); }
+ if (column->headingCommandObj) { Tcl_DecrRefCount(column->headingCommandObj); }
+
+ /* Don't touch column->data, it's scratch storage */
+}
+
+static Tk_OptionSpec ColumnOptionSpecs[] = {
+ {TK_OPTION_INT, "-width", "width", "Width",
+ DEF_COLWIDTH, -1, Tk_Offset(TreeColumn,width),
+ 0,0,GEOMETRY_CHANGED },
+ {TK_OPTION_INT, "-minwidth", "minWidth", "MinWidth",
+ DEF_MINWIDTH, -1, Tk_Offset(TreeColumn,minWidth),
+ 0,0,0 },
+ {TK_OPTION_BOOLEAN, "-stretch", "stretch", "Stretch",
+ "1", -1, Tk_Offset(TreeColumn,stretch),
+ 0,0,GEOMETRY_CHANGED },
+ {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
+ "w", Tk_Offset(TreeColumn,anchorObj), -1, /* <<NOTE-ANCHOR>> */
+ 0,0,0 },
+ {TK_OPTION_STRING, "-id", "id", "ID",
+ NULL, Tk_Offset(TreeColumn,idObj), -1,
+ TK_OPTION_NULL_OK,0,READONLY_OPTION },
+ {TK_OPTION_END, 0,0,0, NULL, -1,-1, 0,0,0}
+};
+
+static Tk_OptionSpec HeadingOptionSpecs[] = {
+ {TK_OPTION_STRING, "-text", "text", "Text",
+ "", Tk_Offset(TreeColumn,headingObj), -1,
+ 0,0,0 },
+ {TK_OPTION_STRING, "-image", "image", "Image",
+ "", Tk_Offset(TreeColumn,headingImageObj), -1,
+ 0,0,0 },
+ {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
+ "center", Tk_Offset(TreeColumn,headingAnchorObj), -1,
+ 0,0,0 },
+ {TK_OPTION_STRING, "-command", "", "",
+ "", Tk_Offset(TreeColumn,headingCommandObj), -1,
+ TK_OPTION_NULL_OK,0,0 },
+ {TK_OPTION_STRING, "state", "", "",
+ "", Tk_Offset(TreeColumn,headingStateObj), -1,
+ 0,0,STATE_CHANGED },
+ {TK_OPTION_END, 0,0,0, NULL, -1,-1, 0,0,0}
+};
+
+/*------------------------------------------------------------------------
+ * +++ -show option:
+ * TODO: Implement SHOW_BRANCHES.
+ */
+
+#define SHOW_TREE (0x1) /* Show tree column? */
+#define SHOW_HEADINGS (0x2) /* Show heading row? */
+
+#define DEFAULT_SHOW "tree headings"
+
+static const char *showStrings[] = {
+ "tree", "headings", NULL
+};
+
+static int GetEnumSetFromObj(
+ Tcl_Interp *interp,
+ Tcl_Obj *objPtr,
+ const char *table[],
+ unsigned *resultPtr)
+{
+ unsigned result = 0;
+ int i, objc;
+ Tcl_Obj **objv;
+
+ if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK)
+ return TCL_ERROR;
+
+ for (i = 0; i < objc; ++i) {
+ int index;
+ if (TCL_OK != Tcl_GetIndexFromObjStruct(interp, objv[i], table,
+ sizeof(char *), "value", TCL_EXACT, &index))
+ {
+ return TCL_ERROR;
+ }
+ result |= (1 << index);
+ }
+
+ *resultPtr = result;
+ return TCL_OK;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Treeview widget record.
+ *
+ * Dependencies:
+ * columns, columnNames: -columns
+ * displayColumns: -columns, -displaycolumns
+ * headingHeight: [layout]
+ * rowHeight, indent: style
+ */
+typedef struct {
+ /* Resources acquired at initialization-time:
+ */
+ Tk_OptionTable itemOptionTable;
+ Tk_OptionTable columnOptionTable;
+ Tk_OptionTable headingOptionTable;
+ Tk_OptionTable tagOptionTable;
+ Tk_BindingTable bindingTable;
+ Ttk_TagTable tagTable;
+
+ /* Acquired in GetLayout hook:
+ */
+ Ttk_Layout itemLayout;
+ Ttk_Layout cellLayout;
+ Ttk_Layout headingLayout;
+ Ttk_Layout rowLayout;
+
+ int headingHeight; /* Space for headings */
+ int rowHeight; /* Height of each item */
+ int indent; /* #pixels horizontal offset for child items */
+
+ /* Tree data:
+ */
+ Tcl_HashTable items; /* Map: item name -> item */
+ int serial; /* Next item # for autogenerated names */
+ TreeItem *root; /* Root item */
+
+ TreeColumn column0; /* Column options for display column #0 */
+ TreeColumn *columns; /* Array of column options for data columns */
+
+ TreeItem *focus; /* Current focus item */
+ TreeItem *endPtr; /* See EndPosition() */
+
+ /* Widget options:
+ */
+ Tcl_Obj *columnsObj; /* List of symbolic column names */
+ Tcl_Obj *displayColumnsObj; /* List of columns to display */
+
+ Tcl_Obj *heightObj; /* height (rows) */
+ Tcl_Obj *paddingObj; /* internal padding */
+
+ Tcl_Obj *showObj; /* -show list */
+ Tcl_Obj *selectModeObj; /* -selectmode option */
+
+ Scrollable xscroll;
+ ScrollHandle xscrollHandle;
+ Scrollable yscroll;
+ ScrollHandle yscrollHandle;
+
+ /* Derived resources:
+ */
+ Tcl_HashTable columnNames; /* Map: column name -> column table entry */
+ int nColumns; /* #columns */
+ unsigned showFlags; /* bitmask of subparts to display */
+
+ TreeColumn **displayColumns; /* List of columns for display (incl tree) */
+ int nDisplayColumns; /* #display columns */
+ Ttk_Box headingArea; /* Display area for column headings */
+ Ttk_Box treeArea; /* Display area for tree */
+ int slack; /* Slack space (see Resizing section) */
+
+} TreePart;
+
+typedef struct {
+ WidgetCore core;
+ TreePart tree;
+} Treeview;
+
+#define USER_MASK 0x0100
+#define COLUMNS_CHANGED (USER_MASK)
+#define DCOLUMNS_CHANGED (USER_MASK<<1)
+#define SCROLLCMD_CHANGED (USER_MASK<<2)
+#define SHOW_CHANGED (USER_MASK<<3)
+
+static const char *SelectModeStrings[] = { "none", "browse", "extended", NULL };
+
+static Tk_OptionSpec TreeviewOptionSpecs[] = {
+ {TK_OPTION_STRING, "-columns", "columns", "Columns",
+ "", Tk_Offset(Treeview,tree.columnsObj), -1,
+ 0,0,COLUMNS_CHANGED | GEOMETRY_CHANGED /*| READONLY_OPTION*/ },
+ {TK_OPTION_STRING, "-displaycolumns","displayColumns","DisplayColumns",
+ "#all", Tk_Offset(Treeview,tree.displayColumnsObj), -1,
+ 0,0,DCOLUMNS_CHANGED | GEOMETRY_CHANGED },
+ {TK_OPTION_STRING, "-show", "show", "Show",
+ DEFAULT_SHOW, Tk_Offset(Treeview,tree.showObj), -1,
+ 0,0,SHOW_CHANGED | GEOMETRY_CHANGED },
+
+ {TK_OPTION_STRING_TABLE, "-selectmode", "selectMode", "SelectMode",
+ "extended", Tk_Offset(Treeview,tree.selectModeObj), -1,
+ 0,(ClientData)SelectModeStrings,0 },
+
+ {TK_OPTION_PIXELS, "-height", "height", "Height",
+ DEF_TREE_ROWS, Tk_Offset(Treeview,tree.heightObj), -1,
+ 0,0,GEOMETRY_CHANGED},
+ {TK_OPTION_STRING, "-padding", "padding", "Pad",
+ NULL, Tk_Offset(Treeview,tree.paddingObj), -1,
+ TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
+
+ {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
+ NULL, -1, Tk_Offset(Treeview, tree.xscroll.scrollCmd),
+ TK_OPTION_NULL_OK, 0, SCROLLCMD_CHANGED},
+ {TK_OPTION_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand",
+ NULL, -1, Tk_Offset(Treeview, tree.yscroll.scrollCmd),
+ TK_OPTION_NULL_OK, 0, SCROLLCMD_CHANGED},
+
+ WIDGET_TAKEFOCUS_TRUE,
+ WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)
+};
+
+/*------------------------------------------------------------------------
+ * +++ Utilities.
+ */
+typedef void (*HashEntryIterator)(void *hashValue);
+
+static void foreachHashEntry(Tcl_HashTable *ht, HashEntryIterator func)
+{
+ Tcl_HashSearch search;
+ Tcl_HashEntry *entryPtr = Tcl_FirstHashEntry(ht, &search);
+ while (entryPtr != NULL) {
+ func(Tcl_GetHashValue(entryPtr));
+ entryPtr = Tcl_NextHashEntry(&search);
+ }
+}
+
+/* + unshareObj(objPtr) --
+ * Ensure that a Tcl_Obj * has refcount 1 -- either return objPtr
+ * itself, or a duplicated copy.
+ */
+static Tcl_Obj *unshareObj(Tcl_Obj *objPtr)
+{
+ if (Tcl_IsShared(objPtr)) {
+ Tcl_Obj *newObj = Tcl_DuplicateObj(objPtr);
+ Tcl_DecrRefCount(objPtr);
+ Tcl_IncrRefCount(newObj);
+ return newObj;
+ }
+ return objPtr;
+}
+
+/* DisplayLayout --
+ * Rebind, place, and draw a layout + object combination.
+ */
+static void DisplayLayout(
+ Ttk_Layout layout, void *recordPtr, Ttk_State state, Ttk_Box b, Drawable d)
+{
+ Ttk_RebindSublayout(layout, recordPtr);
+ Ttk_PlaceLayout(layout, state, b);
+ Ttk_DrawLayout(layout, state, d);
+}
+
+/* + GetColumn --
+ * Look up column by name or number.
+ * Returns: pointer to column table entry, NULL if not found.
+ * Leaves an error message in interp->result on error.
+ */
+static TreeColumn *GetColumn(
+ Tcl_Interp *interp, Treeview *tv, Tcl_Obj *columnIDObj)
+{
+ Tcl_HashEntry *entryPtr;
+ int columnIndex;
+
+ /* Check for named column:
+ */
+ entryPtr = Tcl_FindHashEntry(
+ &tv->tree.columnNames, Tcl_GetString(columnIDObj));
+ if (entryPtr) {
+ return Tcl_GetHashValue(entryPtr);
+ }
+
+ /* Check for number:
+ */
+ if (Tcl_GetIntFromObj(NULL, columnIDObj, &columnIndex) == TCL_OK) {
+ if (columnIndex < 0 || columnIndex >= tv->tree.nColumns) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "Column index %s out of bounds",
+ Tcl_GetString(columnIDObj)));
+ Tcl_SetErrorCode(interp, "TTK", "TREE", "COLBOUND", NULL);
+ return NULL;
+ }
+
+ return tv->tree.columns + columnIndex;
+ }
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "Invalid column index %s", Tcl_GetString(columnIDObj)));
+ Tcl_SetErrorCode(interp, "TTK", "TREE", "COLUMN", NULL);
+ return NULL;
+}
+
+/* + FindColumn --
+ * Look up column by name, number, or display index.
+ */
+static TreeColumn *FindColumn(
+ Tcl_Interp *interp, Treeview *tv, Tcl_Obj *columnIDObj)
+{
+ int colno;
+
+ if (sscanf(Tcl_GetString(columnIDObj), "#%d", &colno) == 1)
+ { /* Display column specification, #n */
+ if (colno >= 0 && colno < tv->tree.nDisplayColumns) {
+ return tv->tree.displayColumns[colno];
+ }
+ /* else */
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "Column %s out of range", Tcl_GetString(columnIDObj)));
+ Tcl_SetErrorCode(interp, "TTK", "TREE", "COLUMN", NULL);
+ return NULL;
+ }
+
+ return GetColumn(interp, tv, columnIDObj);
+}
+
+/* + FindItem --
+ * Locates the item with the specified identifier in the tree.
+ * If there is no such item, leaves an error message in interp.
+ */
+static TreeItem *FindItem(
+ Tcl_Interp *interp, Treeview *tv, Tcl_Obj *itemNameObj)
+{
+ const char *itemName = Tcl_GetString(itemNameObj);
+ Tcl_HashEntry *entryPtr = Tcl_FindHashEntry(&tv->tree.items, itemName);
+
+ if (!entryPtr) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "Item %s not found", itemName));
+ Tcl_SetErrorCode(interp, "TTK", "TREE", "ITEM", NULL);
+ return 0;
+ }
+ return Tcl_GetHashValue(entryPtr);
+}
+
+/* + GetItemListFromObj --
+ * Parse a Tcl_Obj * as a list of items.
+ * Returns a NULL-terminated array of items; result must
+ * be ckfree()d. On error, returns NULL and leaves an error
+ * message in interp.
+ */
+
+static TreeItem **GetItemListFromObj(
+ Tcl_Interp *interp, Treeview *tv, Tcl_Obj *objPtr)
+{
+ TreeItem **items;
+ Tcl_Obj **elements;
+ int i, nElements;
+
+ if (Tcl_ListObjGetElements(interp,objPtr,&nElements,&elements) != TCL_OK) {
+ return NULL;
+ }
+
+ items = ckalloc((nElements + 1)*sizeof(TreeItem*));
+ for (i = 0; i < nElements; ++i) {
+ items[i] = FindItem(interp, tv, elements[i]);
+ if (!items[i]) {
+ ckfree(items);
+ return NULL;
+ }
+ }
+ items[i] = NULL;
+ return items;
+}
+
+/* + ItemName --
+ * Returns the item's ID.
+ */
+static const char *ItemName(Treeview *tv, TreeItem *item)
+{
+ return Tcl_GetHashKey(&tv->tree.items, item->entryPtr);
+}
+
+/* + ItemID --
+ * Returns a fresh Tcl_Obj * (refcount 0) holding the
+ * item identifier of the specified item.
+ */
+static Tcl_Obj *ItemID(Treeview *tv, TreeItem *item)
+{
+ return Tcl_NewStringObj(ItemName(tv, item), -1);
+}
+
+/*------------------------------------------------------------------------
+ * +++ Column configuration.
+ */
+
+/* + TreeviewFreeColumns --
+ * Free column data.
+ */
+static void TreeviewFreeColumns(Treeview *tv)
+{
+ int i;
+
+ Tcl_DeleteHashTable(&tv->tree.columnNames);
+ Tcl_InitHashTable(&tv->tree.columnNames, TCL_STRING_KEYS);
+
+ if (tv->tree.columns) {
+ for (i = 0; i < tv->tree.nColumns; ++i)
+ FreeColumn(tv->tree.columns + i);
+ ckfree(tv->tree.columns);
+ tv->tree.columns = 0;
+ }
+}
+
+/* + TreeviewInitColumns --
+ * Initialize column data when -columns changes.
+ * Returns: TCL_OK or TCL_ERROR;
+ */
+static int TreeviewInitColumns(Tcl_Interp *interp, Treeview *tv)
+{
+ Tcl_Obj **columns;
+ int i, ncols;
+
+ if (Tcl_ListObjGetElements(
+ interp, tv->tree.columnsObj, &ncols, &columns) != TCL_OK)
+ {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Free old values:
+ */
+ TreeviewFreeColumns(tv);
+
+ /*
+ * Initialize columns array and columnNames hash table:
+ */
+ tv->tree.nColumns = ncols;
+ tv->tree.columns = ckalloc(tv->tree.nColumns * sizeof(TreeColumn));
+
+ for (i = 0; i < ncols; ++i) {
+ int isNew;
+ Tcl_Obj *columnName = Tcl_DuplicateObj(columns[i]);
+
+ Tcl_HashEntry *entryPtr = Tcl_CreateHashEntry(
+ &tv->tree.columnNames, Tcl_GetString(columnName), &isNew);
+ Tcl_SetHashValue(entryPtr, tv->tree.columns + i);
+
+ InitColumn(tv->tree.columns + i);
+ Tk_InitOptions(
+ interp, (ClientData)(tv->tree.columns + i),
+ tv->tree.columnOptionTable, tv->core.tkwin);
+ Tk_InitOptions(
+ interp, (ClientData)(tv->tree.columns + i),
+ tv->tree.headingOptionTable, tv->core.tkwin);
+ Tcl_IncrRefCount(columnName);
+ tv->tree.columns[i].idObj = columnName;
+ }
+
+ return TCL_OK;
+}
+
+/* + TreeviewInitDisplayColumns --
+ * Initializes the 'displayColumns' array.
+ *
+ * Note that displayColumns[0] is always the tree column,
+ * even when SHOW_TREE is not set.
+ *
+ * @@@ TODO: disallow duplicated columns
+ */
+static int TreeviewInitDisplayColumns(Tcl_Interp *interp, Treeview *tv)
+{
+ Tcl_Obj **dcolumns;
+ int index, ndcols;
+ TreeColumn **displayColumns = 0;
+
+ if (Tcl_ListObjGetElements(interp,
+ tv->tree.displayColumnsObj, &ndcols, &dcolumns) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (!strcmp(Tcl_GetString(tv->tree.displayColumnsObj), "#all")) {
+ ndcols = tv->tree.nColumns;
+ displayColumns = ckalloc((ndcols+1) * sizeof(TreeColumn*));
+ for (index = 0; index < ndcols; ++index) {
+ displayColumns[index+1] = tv->tree.columns + index;
+ }
+ } else {
+ displayColumns = ckalloc((ndcols+1) * sizeof(TreeColumn*));
+ for (index = 0; index < ndcols; ++index) {
+ displayColumns[index+1] = GetColumn(interp, tv, dcolumns[index]);
+ if (!displayColumns[index+1]) {
+ ckfree(displayColumns);
+ return TCL_ERROR;
+ }
+ }
+ }
+ displayColumns[0] = &tv->tree.column0;
+
+ if (tv->tree.displayColumns)
+ ckfree(tv->tree.displayColumns);
+ tv->tree.displayColumns = displayColumns;
+ tv->tree.nDisplayColumns = ndcols + 1;
+
+ return TCL_OK;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Resizing.
+ * slack invariant: TreeWidth(tree) + slack = treeArea.width
+ */
+
+#define FirstColumn(tv) ((tv->tree.showFlags&SHOW_TREE) ? 0 : 1)
+
+/* + TreeWidth --
+ * Compute the requested tree width from the sum of visible column widths.
+ */
+static int TreeWidth(Treeview *tv)
+{
+ int i = FirstColumn(tv);
+ int width = 0;
+
+ while (i < tv->tree.nDisplayColumns) {
+ width += tv->tree.displayColumns[i++]->width;
+ }
+ return width;
+}
+
+/* + RecomputeSlack --
+ */
+static void RecomputeSlack(Treeview *tv)
+{
+ tv->tree.slack = tv->tree.treeArea.width - TreeWidth(tv);
+}
+
+/* + PickupSlack/DepositSlack --
+ * When resizing columns, distribute extra space to 'slack' first,
+ * and only adjust column widths if 'slack' goes to zero.
+ * That is, don't bother changing column widths if the tree
+ * is already scrolled or short.
+ */
+static int PickupSlack(Treeview *tv, int extra)
+{
+ int newSlack = tv->tree.slack + extra;
+
+ if ( (newSlack < 0 && 0 <= tv->tree.slack)
+ || (newSlack > 0 && 0 >= tv->tree.slack))
+ {
+ tv->tree.slack = 0;
+ return newSlack;
+ } else {
+ tv->tree.slack = newSlack;
+ return 0;
+ }
+}
+
+static void DepositSlack(Treeview *tv, int extra)
+{
+ tv->tree.slack += extra;
+}
+
+/* + Stretch --
+ * Adjust width of column by N pixels, down to minimum width.
+ * Returns: #pixels actually moved.
+ */
+static int Stretch(TreeColumn *c, int n)
+{
+ int newWidth = n + c->width;
+ if (newWidth < c->minWidth) {
+ n = c->minWidth - c->width;
+ c->width = c->minWidth;
+ } else {
+ c->width = newWidth;
+ }
+ return n;
+}
+
+/* + ShoveLeft --
+ * Adjust width of (stretchable) columns to the left by N pixels.
+ * Returns: leftover slack.
+ */
+static int ShoveLeft(Treeview *tv, int i, int n)
+{
+ int first = FirstColumn(tv);
+ while (n != 0 && i >= first) {
+ TreeColumn *c = tv->tree.displayColumns[i];
+ if (c->stretch) {
+ n -= Stretch(c, n);
+ }
+ --i;
+ }
+ return n;
+}
+
+/* + ShoveRight --
+ * Adjust width of (stretchable) columns to the right by N pixels.
+ * Returns: leftover slack.
+ */
+static int ShoveRight(Treeview *tv, int i, int n)
+{
+ while (n != 0 && i < tv->tree.nDisplayColumns) {
+ TreeColumn *c = tv->tree.displayColumns[i];
+ if (c->stretch) {
+ n -= Stretch(c, n);
+ }
+ ++i;
+ }
+ return n;
+}
+
+/* + DistributeWidth --
+ * Distribute n pixels evenly across all stretchable display columns.
+ * Returns: leftover slack.
+ * Notes:
+ * The "((++w % m) < r)" term is there so that the remainder r = n % m
+ * is distributed round-robin.
+ */
+static int DistributeWidth(Treeview *tv, int n)
+{
+ int w = TreeWidth(tv);
+ int m = 0;
+ int i, d, r;
+
+ for (i = FirstColumn(tv); i < tv->tree.nDisplayColumns; ++i) {
+ if (tv->tree.displayColumns[i]->stretch) {
+ ++m;
+ }
+ }
+ if (m == 0) {
+ return n;
+ }
+
+ d = n / m;
+ r = n % m;
+ if (r < 0) { r += m; --d; }
+
+ for (i = FirstColumn(tv); i < tv->tree.nDisplayColumns; ++i) {
+ TreeColumn *c = tv->tree.displayColumns[i];
+ if (c->stretch) {
+ n -= Stretch(c, d + ((++w % m) < r));
+ }
+ }
+ return n;
+}
+
+/* + ResizeColumns --
+ * Recompute column widths based on available width.
+ * Pick up slack first;
+ * Distribute the remainder evenly across stretchable columns;
+ * If any is still left over due to minwidth constraints, shove left.
+ */
+static void ResizeColumns(Treeview *tv, int newWidth)
+{
+ int delta = newWidth - (TreeWidth(tv) + tv->tree.slack);
+ DepositSlack(tv,
+ ShoveLeft(tv, tv->tree.nDisplayColumns - 1,
+ DistributeWidth(tv, PickupSlack(tv, delta))));
+}
+
+/* + DragColumn --
+ * Move the separator to the right of specified column,
+ * adjusting other column widths as necessary.
+ */
+static void DragColumn(Treeview *tv, int i, int delta)
+{
+ TreeColumn *c = tv->tree.displayColumns[i];
+ int dl = delta - ShoveLeft(tv, i-1, delta - Stretch(c, delta));
+ int dr = ShoveRight(tv, i+1, PickupSlack(tv, -dl));
+ DepositSlack(tv, dr);
+}
+
+/*------------------------------------------------------------------------
+ * +++ Event handlers.
+ */
+
+static TreeItem *IdentifyItem(Treeview *tv, int y); /*forward*/
+
+static const unsigned int TreeviewBindEventMask =
+ KeyPressMask|KeyReleaseMask
+ | ButtonPressMask|ButtonReleaseMask
+ | PointerMotionMask|ButtonMotionMask
+ | VirtualEventMask
+ ;
+
+static void TreeviewBindEventProc(void *clientData, XEvent *event)
+{
+ Treeview *tv = clientData;
+ TreeItem *item = NULL;
+ Ttk_TagSet tagset;
+
+ /*
+ * Figure out where to deliver the event.
+ */
+ switch (event->type)
+ {
+ case KeyPress:
+ case KeyRelease:
+ case VirtualEvent:
+ item = tv->tree.focus;
+ break;
+ case ButtonPress:
+ case ButtonRelease:
+ item = IdentifyItem(tv, event->xbutton.y);
+ break;
+ case MotionNotify:
+ item = IdentifyItem(tv, event->xmotion.y);
+ break;
+ default:
+ break;
+ }
+
+ if (!item) {
+ return;
+ }
+
+ /* ASSERT: Ttk_GetTagSetFromObj succeeds.
+ * NB: must use a local copy of the tagset,
+ * in case a binding script stomps on -tags.
+ */
+ tagset = Ttk_GetTagSetFromObj(NULL, tv->tree.tagTable, item->tagsObj);
+
+ /*
+ * Fire binding:
+ */
+ Tcl_Preserve(clientData);
+ Tk_BindEvent(tv->tree.bindingTable, event, tv->core.tkwin,
+ tagset->nTags, (void **)tagset->tags);
+ Tcl_Release(clientData);
+
+ Ttk_FreeTagSet(tagset);
+}
+
+/*------------------------------------------------------------------------
+ * +++ Initialization and cleanup.
+ */
+
+static void TreeviewInitialize(Tcl_Interp *interp, void *recordPtr)
+{
+ Treeview *tv = recordPtr;
+ int unused;
+
+ tv->tree.itemOptionTable =
+ Tk_CreateOptionTable(interp, ItemOptionSpecs);
+ tv->tree.columnOptionTable =
+ Tk_CreateOptionTable(interp, ColumnOptionSpecs);
+ tv->tree.headingOptionTable =
+ Tk_CreateOptionTable(interp, HeadingOptionSpecs);
+ tv->tree.tagOptionTable =
+ Tk_CreateOptionTable(interp, TagOptionSpecs);
+
+ tv->tree.tagTable = Ttk_CreateTagTable(
+ interp, tv->core.tkwin, TagOptionSpecs, sizeof(DisplayItem));
+ tv->tree.bindingTable = Tk_CreateBindingTable(interp);
+ Tk_CreateEventHandler(tv->core.tkwin,
+ TreeviewBindEventMask, TreeviewBindEventProc, tv);
+
+ tv->tree.itemLayout
+ = tv->tree.cellLayout
+ = tv->tree.headingLayout
+ = tv->tree.rowLayout
+ = 0;
+ tv->tree.headingHeight = tv->tree.rowHeight = DEFAULT_ROWHEIGHT;
+ tv->tree.indent = DEFAULT_INDENT;
+
+ Tcl_InitHashTable(&tv->tree.columnNames, TCL_STRING_KEYS);
+ tv->tree.nColumns = tv->tree.nDisplayColumns = 0;
+ tv->tree.columns = NULL;
+ tv->tree.displayColumns = NULL;
+ tv->tree.showFlags = ~0;
+
+ InitColumn(&tv->tree.column0);
+ Tk_InitOptions(
+ interp, (ClientData)(&tv->tree.column0),
+ tv->tree.columnOptionTable, tv->core.tkwin);
+ Tk_InitOptions(
+ interp, (ClientData)(&tv->tree.column0),
+ tv->tree.headingOptionTable, tv->core.tkwin);
+
+ Tcl_InitHashTable(&tv->tree.items, TCL_STRING_KEYS);
+ tv->tree.serial = 0;
+
+ tv->tree.focus = tv->tree.endPtr = 0;
+
+ /* Create root item "":
+ */
+ tv->tree.root = NewItem();
+ Tk_InitOptions(interp, (ClientData)tv->tree.root,
+ tv->tree.itemOptionTable, tv->core.tkwin);
+ tv->tree.root->tagset = Ttk_GetTagSetFromObj(NULL, tv->tree.tagTable, NULL);
+ tv->tree.root->entryPtr = Tcl_CreateHashEntry(&tv->tree.items, "", &unused);
+ Tcl_SetHashValue(tv->tree.root->entryPtr, tv->tree.root);
+
+ /* Scroll handles:
+ */
+ tv->tree.xscrollHandle = TtkCreateScrollHandle(&tv->core,&tv->tree.xscroll);
+ tv->tree.yscrollHandle = TtkCreateScrollHandle(&tv->core,&tv->tree.yscroll);
+
+ /* Size parameters:
+ */
+ tv->tree.treeArea = tv->tree.headingArea = Ttk_MakeBox(0,0,0,0);
+ tv->tree.slack = 0;
+}
+
+static void TreeviewCleanup(void *recordPtr)
+{
+ Treeview *tv = recordPtr;
+
+ Tk_DeleteEventHandler(tv->core.tkwin,
+ TreeviewBindEventMask, TreeviewBindEventProc, tv);
+ Tk_DeleteBindingTable(tv->tree.bindingTable);
+ Ttk_DeleteTagTable(tv->tree.tagTable);
+
+ if (tv->tree.itemLayout) Ttk_FreeLayout(tv->tree.itemLayout);
+ if (tv->tree.cellLayout) Ttk_FreeLayout(tv->tree.cellLayout);
+ if (tv->tree.headingLayout) Ttk_FreeLayout(tv->tree.headingLayout);
+ if (tv->tree.rowLayout) Ttk_FreeLayout(tv->tree.rowLayout);
+
+ TreeviewFreeColumns(tv);
+
+ if (tv->tree.displayColumns)
+ Tcl_Free((ClientData)tv->tree.displayColumns);
+
+ foreachHashEntry(&tv->tree.items, FreeItemCB);
+ Tcl_DeleteHashTable(&tv->tree.items);
+
+ TtkFreeScrollHandle(tv->tree.xscrollHandle);
+ TtkFreeScrollHandle(tv->tree.yscrollHandle);
+}
+
+/* + TreeviewConfigure --
+ * Configuration widget hook.
+ *
+ * BUG: If user sets -columns and -displaycolumns, but -displaycolumns
+ * has an error, the widget is left in an inconsistent state.
+ */
+static int
+TreeviewConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
+{
+ Treeview *tv = recordPtr;
+ unsigned showFlags = tv->tree.showFlags;
+
+ if (mask & COLUMNS_CHANGED) {
+ if (TreeviewInitColumns(interp, tv) != TCL_OK)
+ return TCL_ERROR;
+ mask |= DCOLUMNS_CHANGED;
+ }
+ if (mask & DCOLUMNS_CHANGED) {
+ if (TreeviewInitDisplayColumns(interp, tv) != TCL_OK)
+ return TCL_ERROR;
+ }
+ if (mask & SCROLLCMD_CHANGED) {
+ TtkScrollbarUpdateRequired(tv->tree.xscrollHandle);
+ TtkScrollbarUpdateRequired(tv->tree.yscrollHandle);
+ }
+ if ( (mask & SHOW_CHANGED)
+ && GetEnumSetFromObj(
+ interp,tv->tree.showObj,showStrings,&showFlags) != TCL_OK)
+ {
+ return TCL_ERROR;
+ }
+
+ if (TtkCoreConfigure(interp, recordPtr, mask) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ tv->tree.showFlags = showFlags;
+
+ if (mask & (SHOW_CHANGED | DCOLUMNS_CHANGED)) {
+ RecomputeSlack(tv);
+ }
+ return TCL_OK;
+}
+
+/* + ConfigureItem --
+ * Set item options.
+ */
+static int ConfigureItem(
+ Tcl_Interp *interp, Treeview *tv, TreeItem *item,
+ int objc, Tcl_Obj *const objv[])
+{
+ Tk_SavedOptions savedOptions;
+ int mask;
+ Ttk_ImageSpec *newImageSpec = NULL;
+ Ttk_TagSet newTagSet = NULL;
+
+ if (Tk_SetOptions(interp, (ClientData)item, tv->tree.itemOptionTable,
+ objc, objv, tv->core.tkwin, &savedOptions, &mask)
+ != TCL_OK)
+ {
+ return TCL_ERROR;
+ }
+
+ /* Make sure that -values is a valid list:
+ */
+ if (item->valuesObj) {
+ int unused;
+ if (Tcl_ListObjLength(interp, item->valuesObj, &unused) != TCL_OK)
+ goto error;
+ }
+
+ /* Check -image.
+ */
+ if ((mask & ITEM_OPTION_IMAGE_CHANGED) && item->imageObj) {
+ newImageSpec = TtkGetImageSpec(interp, tv->core.tkwin, item->imageObj);
+ if (!newImageSpec) {
+ goto error;
+ }
+ }
+
+ /* Check -tags.
+ * Side effect: may create new tags.
+ */
+ if (mask & ITEM_OPTION_TAGS_CHANGED) {
+ newTagSet = Ttk_GetTagSetFromObj(
+ interp, tv->tree.tagTable, item->tagsObj);
+ if (!newTagSet) {
+ goto error;
+ }
+ }
+
+ /* Keep TTK_STATE_OPEN flag in sync with item->openObj.
+ * We use both a state flag and a Tcl_Obj* resource so elements
+ * can access the value in either way.
+ */
+ if (item->openObj) {
+ int isOpen;
+ if (Tcl_GetBooleanFromObj(interp, item->openObj, &isOpen) != TCL_OK)
+ goto error;
+ if (isOpen)
+ item->state |= TTK_STATE_OPEN;
+ else
+ item->state &= ~TTK_STATE_OPEN;
+ }
+
+ /* All OK.
+ */
+ Tk_FreeSavedOptions(&savedOptions);
+ if (mask & ITEM_OPTION_TAGS_CHANGED) {
+ if (item->tagset) { Ttk_FreeTagSet(item->tagset); }
+ item->tagset = newTagSet;
+ }
+ if (mask & ITEM_OPTION_IMAGE_CHANGED) {
+ if (item->imagespec) { TtkFreeImageSpec(item->imagespec); }
+ item->imagespec = newImageSpec;
+ }
+ TtkRedisplayWidget(&tv->core);
+ return TCL_OK;
+
+error:
+ Tk_RestoreSavedOptions(&savedOptions);
+ if (newTagSet) { Ttk_FreeTagSet(newTagSet); }
+ if (newImageSpec) { TtkFreeImageSpec(newImageSpec); }
+ return TCL_ERROR;
+}
+
+/* + ConfigureColumn --
+ * Set column options.
+ */
+static int ConfigureColumn(
+ Tcl_Interp *interp, Treeview *tv, TreeColumn *column,
+ int objc, Tcl_Obj *const objv[])
+{
+ Tk_SavedOptions savedOptions;
+ int mask;
+
+ if (Tk_SetOptions(interp, (ClientData)column,
+ tv->tree.columnOptionTable, objc, objv, tv->core.tkwin,
+ &savedOptions,&mask) != TCL_OK)
+ {
+ return TCL_ERROR;
+ }
+
+ if (mask & READONLY_OPTION) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "Attempt to change read-only option", -1));
+ Tcl_SetErrorCode(interp, "TTK", "TREE", "READONLY", NULL);
+ goto error;
+ }
+
+ /* Propagate column width changes to overall widget request width,
+ * but only if the widget is currently unmapped, in order to prevent
+ * geometry jumping during interactive column resize.
+ */
+ if (mask & GEOMETRY_CHANGED) {
+ if (!Tk_IsMapped(tv->core.tkwin)) {
+ TtkResizeWidget(&tv->core);
+ }
+ RecomputeSlack(tv);
+ ResizeColumns(tv, TreeWidth(tv));
+ }
+ TtkRedisplayWidget(&tv->core);
+
+ Tk_FreeSavedOptions(&savedOptions);
+ return TCL_OK;
+
+error:
+ Tk_RestoreSavedOptions(&savedOptions);
+ return TCL_ERROR;
+}
+
+/* + ConfigureHeading --
+ * Set heading options.
+ */
+static int ConfigureHeading(
+ Tcl_Interp *interp, Treeview *tv, TreeColumn *column,
+ int objc, Tcl_Obj *const objv[])
+{
+ Tk_SavedOptions savedOptions;
+ int mask;
+
+ if (Tk_SetOptions(interp, (ClientData)column,
+ tv->tree.headingOptionTable, objc, objv, tv->core.tkwin,
+ &savedOptions,&mask) != TCL_OK)
+ {
+ return TCL_ERROR;
+ }
+
+ /* @@@ testing ... */
+ if ((mask & STATE_CHANGED) && column->headingStateObj) {
+ Ttk_StateSpec stateSpec;
+ if (Ttk_GetStateSpecFromObj(
+ interp, column->headingStateObj, &stateSpec) != TCL_OK)
+ {
+ goto error;
+ }
+ column->headingState = Ttk_ModifyState(column->headingState,&stateSpec);
+ Tcl_DecrRefCount(column->headingStateObj);
+ column->headingStateObj = Ttk_NewStateSpecObj(column->headingState,0);
+ Tcl_IncrRefCount(column->headingStateObj);
+ }
+
+ TtkRedisplayWidget(&tv->core);
+ Tk_FreeSavedOptions(&savedOptions);
+ return TCL_OK;
+
+error:
+ Tk_RestoreSavedOptions(&savedOptions);
+ return TCL_ERROR;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Geometry routines.
+ */
+
+/* + CountRows --
+ * Returns the number of viewable rows rooted at item
+ */
+static int CountRows(TreeItem *item)
+{
+ int rows = 1;
+
+ if (item->state & TTK_STATE_OPEN) {
+ TreeItem *child = item->children;
+ while (child) {
+ rows += CountRows(child);
+ child = child->next;
+ }
+ }
+ return rows;
+}
+
+/* + IdentifyRow --
+ * Recursive search for item at specified y position.
+ * Main work routine for IdentifyItem()
+ */
+static TreeItem *IdentifyRow(
+ Treeview *tv, /* Widget record */
+ TreeItem *item, /* Where to start search */
+ int *ypos, /* Scan position */
+ int y) /* Target y coordinate */
+{
+ while (item) {
+ int next_ypos = *ypos + tv->tree.rowHeight;
+ if (*ypos <= y && y <= next_ypos) {
+ return item;
+ }
+ *ypos = next_ypos;
+ if (item->state & TTK_STATE_OPEN) {
+ TreeItem *subitem = IdentifyRow(tv, item->children, ypos, y);
+ if (subitem) {
+ return subitem;
+ }
+ }
+ item = item->next;
+ }
+ return 0;
+}
+
+/* + IdentifyItem --
+ * Locate the item at the specified y position, if any.
+ */
+static TreeItem *IdentifyItem(Treeview *tv, int y)
+{
+ int rowHeight = tv->tree.rowHeight;
+ int ypos = tv->tree.treeArea.y - rowHeight * tv->tree.yscroll.first;
+ return IdentifyRow(tv, tv->tree.root->children, &ypos, y);
+}
+
+/* + IdentifyDisplayColumn --
+ * Returns the display column number at the specified x position,
+ * or -1 if x is outside any columns.
+ */
+static int IdentifyDisplayColumn(Treeview *tv, int x, int *x1)
+{
+ int colno = FirstColumn(tv);
+ int xpos = tv->tree.treeArea.x - tv->tree.xscroll.first;
+
+ while (colno < tv->tree.nDisplayColumns) {
+ TreeColumn *column = tv->tree.displayColumns[colno];
+ int next_xpos = xpos + column->width;
+ if (xpos <= x && x <= next_xpos + HALO) {
+ *x1 = next_xpos;
+ return colno;
+ }
+ ++colno;
+ xpos = next_xpos;
+ }
+
+ return -1;
+}
+
+/* + RowNumber --
+ * Calculate which row the specified item appears on;
+ * returns -1 if the item is not viewable.
+ * Xref: DrawForest, IdentifyItem.
+ */
+static int RowNumber(Treeview *tv, TreeItem *item)
+{
+ TreeItem *p = tv->tree.root->children;
+ int n = 0;
+
+ while (p) {
+ if (p == item)
+ return n;
+
+ ++n;
+
+ /* Find next viewable item in preorder traversal order
+ */
+ if (p->children && (p->state & TTK_STATE_OPEN)) {
+ p = p->children;
+ } else {
+ while (!p->next && p && p->parent)
+ p = p->parent;
+ if (p)
+ p = p->next;
+ }
+ }
+
+ return -1;
+}
+
+/* + ItemDepth -- return the depth of a tree item.
+ * The depth of an item is equal to the number of proper ancestors,
+ * not counting the root node.
+ */
+static int ItemDepth(TreeItem *item)
+{
+ int depth = 0;
+ while (item->parent) {
+ ++depth;
+ item = item->parent;
+ }
+ return depth-1;
+}
+
+/* + ItemRow --
+ * Returns row number of specified item relative to root,
+ * -1 if item is not viewable.
+ */
+static int ItemRow(Treeview *tv, TreeItem *p)
+{
+ TreeItem *root = tv->tree.root;
+ int rowNumber = 0;
+
+ for (;;) {
+ if (p->prev) {
+ p = p->prev;
+ rowNumber += CountRows(p);
+ } else {
+ p = p->parent;
+ if (!(p && (p->state & TTK_STATE_OPEN))) {
+ /* detached or closed ancestor */
+ return -1;
+ }
+ if (p == root) {
+ return rowNumber;
+ }
+ ++rowNumber;
+ }
+ }
+}
+
+/* + BoundingBox --
+ * Compute the parcel of the specified column of the specified item,
+ * (or the entire item if column is NULL)
+ * Returns: 0 if item or column is not viewable, 1 otherwise.
+ */
+static int BoundingBox(
+ Treeview *tv, /* treeview widget */
+ TreeItem *item, /* desired item */
+ TreeColumn *column, /* desired column */
+ Ttk_Box *bbox_rtn) /* bounding box of item */
+{
+ int row = ItemRow(tv, item);
+ Ttk_Box bbox = tv->tree.treeArea;
+
+ if (row < tv->tree.yscroll.first || row > tv->tree.yscroll.last) {
+ /* not viewable, or off-screen */
+ return 0;
+ }
+
+ bbox.y += (row - tv->tree.yscroll.first) * tv->tree.rowHeight;
+ bbox.height = tv->tree.rowHeight;
+
+ bbox.x -= tv->tree.xscroll.first;
+ bbox.width = TreeWidth(tv);
+
+ if (column) {
+ int xpos = 0, i = FirstColumn(tv);
+ while (i < tv->tree.nDisplayColumns) {
+ if (tv->tree.displayColumns[i] == column) {
+ break;
+ }
+ xpos += tv->tree.displayColumns[i]->width;
+ ++i;
+ }
+ if (i == tv->tree.nDisplayColumns) { /* specified column unviewable */
+ return 0;
+ }
+ bbox.x += xpos;
+ bbox.width = column->width;
+
+ /* Account for indentation in tree column:
+ */
+ if (column == &tv->tree.column0) {
+ int indent = tv->tree.indent * ItemDepth(item);
+ bbox.x += indent;
+ bbox.width -= indent;
+ }
+ }
+ *bbox_rtn = bbox;
+ return 1;
+}
+
+/* + IdentifyRegion --
+ */
+
+typedef enum {
+ REGION_NOTHING = 0,
+ REGION_HEADING,
+ REGION_SEPARATOR,
+ REGION_TREE,
+ REGION_CELL
+} TreeRegion;
+
+static const char *regionStrings[] = {
+ "nothing", "heading", "separator", "tree", "cell", 0
+};
+
+static TreeRegion IdentifyRegion(Treeview *tv, int x, int y)
+{
+ int x1 = 0, colno;
+
+ colno = IdentifyDisplayColumn(tv, x, &x1);
+ if (Ttk_BoxContains(tv->tree.headingArea, x, y)) {
+ if (colno < 0) {
+ return REGION_NOTHING;
+ } else if (-HALO <= x1 - x && x1 - x <= HALO) {
+ return REGION_SEPARATOR;
+ } else {
+ return REGION_HEADING;
+ }
+ } else if (Ttk_BoxContains(tv->tree.treeArea, x, y)) {
+ TreeItem *item = IdentifyItem(tv, y);
+ if (item && colno > 0) {
+ return REGION_CELL;
+ } else if (item) {
+ return REGION_TREE;
+ }
+ }
+ return REGION_NOTHING;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Display routines.
+ */
+
+/* + GetSublayout --
+ * Utility routine; acquires a sublayout for items, cells, etc.
+ */
+static Ttk_Layout GetSublayout(
+ Tcl_Interp *interp,
+ Ttk_Theme themePtr,
+ Ttk_Layout parentLayout,
+ const char *layoutName,
+ Tk_OptionTable optionTable,
+ Ttk_Layout *layoutPtr)
+{
+ Ttk_Layout newLayout = Ttk_CreateSublayout(
+ interp, themePtr, parentLayout, layoutName, optionTable);
+
+ if (newLayout) {
+ if (*layoutPtr)
+ Ttk_FreeLayout(*layoutPtr);
+ *layoutPtr = newLayout;
+ }
+ return newLayout;
+}
+
+/* + TreeviewGetLayout --
+ * GetLayout() widget hook.
+ */
+static Ttk_Layout TreeviewGetLayout(
+ Tcl_Interp *interp, Ttk_Theme themePtr, void *recordPtr)
+{
+ Treeview *tv = recordPtr;
+ Ttk_Layout treeLayout = TtkWidgetGetLayout(interp, themePtr, recordPtr);
+ Tcl_Obj *objPtr;
+ int unused;
+
+ if (!(
+ treeLayout
+ && GetSublayout(interp, themePtr, treeLayout, ".Item",
+ tv->tree.tagOptionTable, &tv->tree.itemLayout)
+ && GetSublayout(interp, themePtr, treeLayout, ".Cell",
+ tv->tree.tagOptionTable, &tv->tree.cellLayout)
+ && GetSublayout(interp, themePtr, treeLayout, ".Heading",
+ tv->tree.headingOptionTable, &tv->tree.headingLayout)
+ && GetSublayout(interp, themePtr, treeLayout, ".Row",
+ tv->tree.tagOptionTable, &tv->tree.rowLayout)
+ )) {
+ return 0;
+ }
+
+ /* Compute heading height.
+ */
+ Ttk_RebindSublayout(tv->tree.headingLayout, &tv->tree.column0);
+ Ttk_LayoutSize(tv->tree.headingLayout, 0, &unused, &tv->tree.headingHeight);
+
+ /* Get item height, indent from style:
+ * @@@ TODO: sanity-check.
+ */
+ tv->tree.rowHeight = DEFAULT_ROWHEIGHT;
+ tv->tree.indent = DEFAULT_INDENT;
+ if ((objPtr = Ttk_QueryOption(treeLayout, "-rowheight", 0))) {
+ (void)Tcl_GetIntFromObj(NULL, objPtr, &tv->tree.rowHeight);
+ }
+ if ((objPtr = Ttk_QueryOption(treeLayout, "-indent", 0))) {
+ (void)Tcl_GetIntFromObj(NULL, objPtr, &tv->tree.indent);
+ }
+
+ return treeLayout;
+}
+
+/* + TreeviewDoLayout --
+ * DoLayout() widget hook. Computes widget layout.
+ *
+ * Side effects:
+ * Computes headingArea and treeArea.
+ * Computes subtree height.
+ * Invokes scroll callbacks.
+ */
+static void TreeviewDoLayout(void *clientData)
+{
+ Treeview *tv = clientData;
+ int visibleRows;
+
+ Ttk_PlaceLayout(tv->core.layout,tv->core.state,Ttk_WinBox(tv->core.tkwin));
+ tv->tree.treeArea = Ttk_ClientRegion(tv->core.layout, "treearea");
+
+ ResizeColumns(tv, tv->tree.treeArea.width);
+
+ TtkScrolled(tv->tree.xscrollHandle,
+ tv->tree.xscroll.first,
+ tv->tree.xscroll.first + tv->tree.treeArea.width,
+ TreeWidth(tv));
+
+ if (tv->tree.showFlags & SHOW_HEADINGS) {
+ tv->tree.headingArea = Ttk_PackBox(
+ &tv->tree.treeArea, 1, tv->tree.headingHeight, TTK_SIDE_TOP);
+ } else {
+ tv->tree.headingArea = Ttk_MakeBox(0,0,0,0);
+ }
+
+ visibleRows = tv->tree.treeArea.height / tv->tree.rowHeight;
+ tv->tree.root->state |= TTK_STATE_OPEN;
+ TtkScrolled(tv->tree.yscrollHandle,
+ tv->tree.yscroll.first,
+ tv->tree.yscroll.first + visibleRows,
+ CountRows(tv->tree.root) - 1);
+}
+
+/* + TreeviewSize --
+ * SizeProc() widget hook. Size is determined by
+ * -height option and column widths.
+ */
+static int TreeviewSize(void *clientData, int *widthPtr, int *heightPtr)
+{
+ Treeview *tv = clientData;
+ int nRows, padHeight, padWidth;
+
+ Ttk_LayoutSize(tv->core.layout, tv->core.state, &padWidth, &padHeight);
+ Tcl_GetIntFromObj(NULL, tv->tree.heightObj, &nRows);
+
+ *widthPtr = padWidth + TreeWidth(tv);
+ *heightPtr = padHeight + tv->tree.rowHeight * nRows;
+
+ if (tv->tree.showFlags & SHOW_HEADINGS) {
+ *heightPtr += tv->tree.headingHeight;
+ }
+
+ return 1;
+}
+
+/* + ItemState --
+ * Returns the state of the specified item, based
+ * on widget state, item state, and other information.
+ */
+static Ttk_State ItemState(Treeview *tv, TreeItem *item)
+{
+ Ttk_State state = tv->core.state | item->state;
+ if (!item->children)
+ state |= TTK_STATE_LEAF;
+ if (item != tv->tree.focus)
+ state &= ~TTK_STATE_FOCUS;
+ return state;
+}
+
+/* + DrawHeadings --
+ * Draw tree headings.
+ */
+static void DrawHeadings(Treeview *tv, Drawable d)
+{
+ const int x0 = tv->tree.headingArea.x - tv->tree.xscroll.first;
+ const int y0 = tv->tree.headingArea.y;
+ const int h0 = tv->tree.headingArea.height;
+ int i = FirstColumn(tv);
+ int x = 0;
+
+ while (i < tv->tree.nDisplayColumns) {
+ TreeColumn *column = tv->tree.displayColumns[i];
+ Ttk_Box parcel = Ttk_MakeBox(x0+x, y0, column->width, h0);
+ DisplayLayout(tv->tree.headingLayout,
+ column, column->headingState, parcel, d);
+ x += column->width;
+ ++i;
+ }
+}
+
+/* + PrepareItem --
+ * Fill in a displayItem record.
+ */
+static void PrepareItem(
+ Treeview *tv, TreeItem *item, DisplayItem *displayItem)
+{
+ Ttk_Style style = Ttk_LayoutStyle(tv->core.layout);
+ Ttk_State state = ItemState(tv, item);
+
+ Ttk_TagSetValues(tv->tree.tagTable, item->tagset, displayItem);
+ Ttk_TagSetApplyStyle(tv->tree.tagTable, style, state, displayItem);
+}
+
+/* + DrawCells --
+ * Draw data cells for specified item.
+ */
+static void DrawCells(
+ Treeview *tv, TreeItem *item, DisplayItem *displayItem,
+ Drawable d, int x, int y)
+{
+ Ttk_Layout layout = tv->tree.cellLayout;
+ Ttk_State state = ItemState(tv, item);
+ Ttk_Padding cellPadding = {4, 0, 4, 0};
+ int rowHeight = tv->tree.rowHeight;
+ int nValues = 0;
+ Tcl_Obj **values = 0;
+ int i;
+
+ if (!item->valuesObj) {
+ return;
+ }
+
+ Tcl_ListObjGetElements(NULL, item->valuesObj, &nValues, &values);
+ for (i = 0; i < tv->tree.nColumns; ++i) {
+ tv->tree.columns[i].data = (i < nValues) ? values[i] : 0;
+ }
+
+ for (i = 1; i < tv->tree.nDisplayColumns; ++i) {
+ TreeColumn *column = tv->tree.displayColumns[i];
+ Ttk_Box parcel = Ttk_PadBox(
+ Ttk_MakeBox(x, y, column->width, rowHeight), cellPadding);
+
+ displayItem->textObj = column->data;
+ displayItem->anchorObj = column->anchorObj; /* <<NOTE-ANCHOR>> */
+
+ DisplayLayout(layout, displayItem, state, parcel, d);
+ x += column->width;
+ }
+}
+
+/* + DrawItem --
+ * Draw an item (row background, tree label, and cells).
+ */
+static void DrawItem(
+ Treeview *tv, TreeItem *item, Drawable d, int depth, int row)
+{
+ Ttk_State state = ItemState(tv, item);
+ DisplayItem displayItem;
+ int rowHeight = tv->tree.rowHeight;
+ int x = tv->tree.treeArea.x - tv->tree.xscroll.first;
+ int y = tv->tree.treeArea.y + rowHeight * (row - tv->tree.yscroll.first);
+
+ if (row % 2) state |= TTK_STATE_ALTERNATE;
+
+ PrepareItem(tv, item, &displayItem);
+
+ /* Draw row background:
+ */
+ {
+ Ttk_Box rowBox = Ttk_MakeBox(x, y, TreeWidth(tv), rowHeight);
+ DisplayLayout(tv->tree.rowLayout, &displayItem, state, rowBox, d);
+ }
+
+ /* Draw tree label:
+ */
+ if (tv->tree.showFlags & SHOW_TREE) {
+ int indent = depth * tv->tree.indent;
+ int colwidth = tv->tree.column0.width;
+ Ttk_Box parcel = Ttk_MakeBox(
+ x+indent, y, colwidth-indent, rowHeight);
+ if (item->textObj) { displayItem.textObj = item->textObj; }
+ if (item->imageObj) { displayItem.imageObj = item->imageObj; }
+ /* ??? displayItem.anchorObj = 0; <<NOTE-ANCHOR>> */
+ DisplayLayout(tv->tree.itemLayout, &displayItem, state, parcel, d);
+ x += colwidth;
+ }
+
+ /* Draw data cells:
+ */
+ DrawCells(tv, item, &displayItem, d, x, y);
+}
+
+/* + DrawSubtree --
+ * Draw an item and all of its (viewable) descendants.
+ *
+ * Returns:
+ * Row number of the last item drawn.
+ */
+
+static int DrawForest( /* forward */
+ Treeview *tv, TreeItem *item, Drawable d, int depth, int row);
+
+static int DrawSubtree(
+ Treeview *tv, TreeItem *item, Drawable d, int depth, int row)
+{
+ if (row >= tv->tree.yscroll.first) {
+ DrawItem(tv, item, d, depth, row);
+ }
+
+ if (item->state & TTK_STATE_OPEN) {
+ return DrawForest(tv, item->children, d, depth + 1, row + 1);
+ } else {
+ return row + 1;
+ }
+}
+
+/* + DrawForest --
+ * Draw a sequence of items and their visible descendants.
+ *
+ * Returns:
+ * Row number of the last item drawn.
+ */
+static int DrawForest(
+ Treeview *tv, TreeItem *item, Drawable d, int depth, int row)
+{
+ while (item && row < tv->tree.yscroll.last) {
+ row = DrawSubtree(tv, item, d, depth, row);
+ item = item->next;
+ }
+ return row;
+}
+
+/* + TreeviewDisplay --
+ * Display() widget hook. Draw the widget contents.
+ */
+static void TreeviewDisplay(void *clientData, Drawable d)
+{
+ Treeview *tv = clientData;
+
+ Ttk_DrawLayout(tv->core.layout, tv->core.state, d);
+ if (tv->tree.showFlags & SHOW_HEADINGS) {
+ DrawHeadings(tv, d);
+ }
+ DrawForest(tv, tv->tree.root->children, d, 0,0);
+}
+
+/*------------------------------------------------------------------------
+ * +++ Utilities for widget commands
+ */
+
+/* + InsertPosition --
+ * Locate the previous sibling for [$tree insert].
+ *
+ * Returns a pointer to the item just before the specified index,
+ * or 0 if the item is to be inserted at the beginning.
+ */
+static TreeItem *InsertPosition(TreeItem *parent, int index)
+{
+ TreeItem *prev = 0, *next = parent->children;
+
+ while (next != 0 && index > 0) {
+ --index;
+ prev = next;
+ next = prev->next;
+ }
+
+ return prev;
+}
+
+/* + EndPosition --
+ * Locate the last child of the specified node.
+ *
+ * To avoid quadratic-time behavior in the common cases
+ * where the treeview is populated in breadth-first or
+ * depth-first order using [$tv insert $parent end ...],
+ * we cache the result from the last call to EndPosition()
+ * and start the search from there on a cache hit.
+ *
+ */
+static TreeItem *EndPosition(Treeview *tv, TreeItem *parent)
+{
+ TreeItem *endPtr = tv->tree.endPtr;
+
+ while (endPtr && endPtr->parent != parent) {
+ endPtr = endPtr->parent;
+ }
+ if (!endPtr) {
+ endPtr = parent->children;
+ }
+
+ if (endPtr) {
+ while (endPtr->next) {
+ endPtr = endPtr->next;
+ }
+ tv->tree.endPtr = endPtr;
+ }
+
+ return endPtr;
+}
+
+/* + AncestryCheck --
+ * Verify that specified item is not an ancestor of the specified parent;
+ * returns 1 if OK, 0 and leaves an error message in interp otherwise.
+ */
+static int AncestryCheck(
+ Tcl_Interp *interp, Treeview *tv, TreeItem *item, TreeItem *parent)
+{
+ TreeItem *p = parent;
+ while (p) {
+ if (p == item) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "Cannot insert %s as descendant of %s",
+ ItemName(tv, item), ItemName(tv, parent)));
+ Tcl_SetErrorCode(interp, "TTK", "TREE", "ANCESTRY", NULL);
+ return 0;
+ }
+ p = p->parent;
+ }
+ return 1;
+}
+
+/* + DeleteItems --
+ * Remove an item and all of its descendants from the hash table
+ * and detach them from the tree; returns a linked list (chained
+ * along the ->next pointer) of deleted items.
+ */
+static TreeItem *DeleteItems(TreeItem *item, TreeItem *delq)
+{
+ if (item->entryPtr) {
+ DetachItem(item);
+ while (item->children) {
+ delq = DeleteItems(item->children, delq);
+ }
+ Tcl_DeleteHashEntry(item->entryPtr);
+ item->entryPtr = 0;
+ item->next = delq;
+ delq = item;
+ } /* else -- item has already been unlinked */
+ return delq;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Widget commands -- item inquiry.
+ */
+
+/* + $tv children $item ?newchildren? --
+ * Return the list of children associated with $item
+ */
+static int TreeviewChildrenCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Treeview *tv = recordPtr;
+ TreeItem *item;
+ Tcl_Obj *result;
+
+ if (objc < 3 || objc > 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "item ?newchildren?");
+ return TCL_ERROR;
+ }
+ item = FindItem(interp, tv, objv[2]);
+ if (!item) {
+ return TCL_ERROR;
+ }
+
+ if (objc == 3) {
+ result = Tcl_NewListObj(0,0);
+ for (item = item->children; item; item = item->next) {
+ Tcl_ListObjAppendElement(interp, result, ItemID(tv, item));
+ }
+ Tcl_SetObjResult(interp, result);
+ } else {
+ TreeItem **newChildren = GetItemListFromObj(interp, tv, objv[3]);
+ TreeItem *child;
+ int i;
+
+ if (!newChildren)
+ return TCL_ERROR;
+
+ /* Sanity-check:
+ */
+ for (i=0; newChildren[i]; ++i) {
+ if (!AncestryCheck(interp, tv, newChildren[i], item)) {
+ ckfree(newChildren);
+ return TCL_ERROR;
+ }
+ }
+
+ /* Detach old children:
+ */
+ child = item->children;
+ while (child) {
+ TreeItem *next = child->next;
+ DetachItem(child);
+ child = next;
+ }
+
+ /* Detach new children from their current locations:
+ */
+ for (i=0; newChildren[i]; ++i) {
+ DetachItem(newChildren[i]);
+ }
+
+ /* Reinsert new children:
+ * Note: it is not an error for an item to be listed more than once,
+ * though it probably should be...
+ */
+ child = 0;
+ for (i=0; newChildren[i]; ++i) {
+ if (newChildren[i]->parent) {
+ /* This is a duplicate element which has already been
+ * inserted. Ignore it.
+ */
+ continue;
+ }
+ InsertItem(item, child, newChildren[i]);
+ child = newChildren[i];
+ }
+
+ ckfree(newChildren);
+ TtkRedisplayWidget(&tv->core);
+ }
+
+ return TCL_OK;
+}
+
+/* + $tv parent $item --
+ * Return the item ID of $item's parent.
+ */
+static int TreeviewParentCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Treeview *tv = recordPtr;
+ TreeItem *item;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "item");
+ return TCL_ERROR;
+ }
+ item = FindItem(interp, tv, objv[2]);
+ if (!item) {
+ return TCL_ERROR;
+ }
+
+ if (item->parent) {
+ Tcl_SetObjResult(interp, ItemID(tv, item->parent));
+ } else {
+ /* This is the root item. @@@ Return an error? */
+ Tcl_ResetResult(interp);
+ }
+
+ return TCL_OK;
+}
+
+/* + $tv next $item
+ * Return the ID of $item's next sibling.
+ */
+static int TreeviewNextCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Treeview *tv = recordPtr;
+ TreeItem *item;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "item");
+ return TCL_ERROR;
+ }
+ item = FindItem(interp, tv, objv[2]);
+ if (!item) {
+ return TCL_ERROR;
+ }
+
+ if (item->next) {
+ Tcl_SetObjResult(interp, ItemID(tv, item->next));
+ } /* else -- leave interp-result empty */
+
+ return TCL_OK;
+}
+
+/* + $tv prev $item
+ * Return the ID of $item's previous sibling.
+ */
+static int TreeviewPrevCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Treeview *tv = recordPtr;
+ TreeItem *item;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "item");
+ return TCL_ERROR;
+ }
+ item = FindItem(interp, tv, objv[2]);
+ if (!item) {
+ return TCL_ERROR;
+ }
+
+ if (item->prev) {
+ Tcl_SetObjResult(interp, ItemID(tv, item->prev));
+ } /* else -- leave interp-result empty */
+
+ return TCL_OK;
+}
+
+/* + $tv index $item --
+ * Return the index of $item within its parent.
+ */
+static int TreeviewIndexCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Treeview *tv = recordPtr;
+ TreeItem *item;
+ int index = 0;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "item");
+ return TCL_ERROR;
+ }
+ item = FindItem(interp, tv, objv[2]);
+ if (!item) {
+ return TCL_ERROR;
+ }
+
+ while (item->prev) {
+ ++index;
+ item = item->prev;
+ }
+
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(index));
+ return TCL_OK;
+}
+
+/* + $tv exists $itemid --
+ * Test if the specified item id is present in the tree.
+ */
+static int TreeviewExistsCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Treeview *tv = recordPtr;
+ Tcl_HashEntry *entryPtr;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "itemid");
+ return TCL_ERROR;
+ }
+
+ entryPtr = Tcl_FindHashEntry(&tv->tree.items, Tcl_GetString(objv[2]));
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(entryPtr != 0));
+ return TCL_OK;
+}
+
+/* + $tv bbox $itemid ?$column? --
+ * Return bounding box [x y width height] of specified item.
+ */
+static int TreeviewBBoxCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Treeview *tv = recordPtr;
+ TreeItem *item = 0;
+ TreeColumn *column = 0;
+ Ttk_Box bbox;
+
+ if (objc < 3 || objc > 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "itemid ?column");
+ return TCL_ERROR;
+ }
+
+ item = FindItem(interp, tv, objv[2]);
+ if (!item) {
+ return TCL_ERROR;
+ }
+ if (objc >=4 && (column = FindColumn(interp,tv,objv[3])) == NULL) {
+ return TCL_ERROR;
+ }
+
+ if (BoundingBox(tv, item, column, &bbox)) {
+ Tcl_SetObjResult(interp, Ttk_NewBoxObj(bbox));
+ }
+
+ return TCL_OK;
+}
+
+/* + $tv identify $x $y -- (obsolescent)
+ * Implements the old, horrible, 2-argument form of [$tv identify].
+ *
+ * Returns: one of
+ * heading #n
+ * cell itemid #n
+ * item itemid element
+ * row itemid
+ */
+static int TreeviewHorribleIdentify(
+ Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], Treeview *tv)
+{
+ const char *what = "nothing", *detail = NULL;
+ TreeItem *item = 0;
+ Tcl_Obj *result;
+ int dColumnNumber;
+ char dcolbuf[16];
+ int x, y, x1;
+
+ /* ASSERT: objc == 4 */
+
+ if ( Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK
+ || Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK
+ ) {
+ return TCL_ERROR;
+ }
+
+ dColumnNumber = IdentifyDisplayColumn(tv, x, &x1);
+ if (dColumnNumber < 0) {
+ goto done;
+ }
+ sprintf(dcolbuf, "#%d", dColumnNumber);
+
+ if (Ttk_BoxContains(tv->tree.headingArea,x,y)) {
+ if (-HALO <= x1 - x && x1 - x <= HALO) {
+ what = "separator";
+ } else {
+ what = "heading";
+ }
+ detail = dcolbuf;
+ } else if (Ttk_BoxContains(tv->tree.treeArea,x,y)) {
+ item = IdentifyItem(tv, y);
+ if (item && dColumnNumber > 0) {
+ what = "cell";
+ detail = dcolbuf;
+ } else if (item) {
+ Ttk_Layout layout = tv->tree.itemLayout;
+ Ttk_Box itemBox;
+ DisplayItem displayItem;
+ Ttk_Element element;
+
+ BoundingBox(tv, item, NULL, &itemBox);
+ PrepareItem(tv, item, &displayItem);
+ if (item->textObj) { displayItem.textObj = item->textObj; }
+ if (item->imageObj) { displayItem.imageObj = item->imageObj; }
+ Ttk_RebindSublayout(layout, &displayItem);
+ Ttk_PlaceLayout(layout, ItemState(tv,item), itemBox);
+ element = Ttk_IdentifyElement(layout, x, y);
+
+ if (element) {
+ what = "item";
+ detail = Ttk_ElementName(element);
+ } else {
+ what = "row";
+ }
+ }
+ }
+
+done:
+ result = Tcl_NewListObj(0,0);
+ Tcl_ListObjAppendElement(NULL, result, Tcl_NewStringObj(what, -1));
+ if (item)
+ Tcl_ListObjAppendElement(NULL, result, ItemID(tv, item));
+ if (detail)
+ Tcl_ListObjAppendElement(NULL, result, Tcl_NewStringObj(detail, -1));
+
+ Tcl_SetObjResult(interp, result);
+ return TCL_OK;
+}
+
+/* + $tv identify $component $x $y --
+ * Identify the component at position x,y.
+ */
+
+static int TreeviewIdentifyCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ static const char *submethodStrings[] =
+ { "region", "item", "column", "row", "element", NULL };
+ enum { I_REGION, I_ITEM, I_COLUMN, I_ROW, I_ELEMENT };
+
+ Treeview *tv = recordPtr;
+ int submethod;
+ int x, y;
+
+ TreeRegion region;
+ Ttk_Box bbox;
+ TreeItem *item;
+ TreeColumn *column = 0;
+ int colno, x1;
+
+ if (objc == 4) { /* Old form */
+ return TreeviewHorribleIdentify(interp, objc, objv, tv);
+ } else if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 2, objv, "command x y");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[2], submethodStrings,
+ sizeof(char *), "command", TCL_EXACT, &submethod) != TCL_OK
+ || Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK
+ || Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK
+ ) {
+ return TCL_ERROR;
+ }
+
+ region = IdentifyRegion(tv, x, y);
+ item = IdentifyItem(tv, y);
+ colno = IdentifyDisplayColumn(tv, x, &x1);
+ column = (colno >= 0) ? tv->tree.displayColumns[colno] : NULL;
+
+ switch (submethod)
+ {
+ case I_REGION :
+ Tcl_SetObjResult(interp,Tcl_NewStringObj(regionStrings[region],-1));
+ break;
+
+ case I_ITEM :
+ case I_ROW :
+ if (item) {
+ Tcl_SetObjResult(interp, ItemID(tv, item));
+ }
+ break;
+
+ case I_COLUMN :
+ if (colno >= 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf("#%d", colno));
+ }
+ break;
+
+ case I_ELEMENT :
+ {
+ Ttk_Layout layout = 0;
+ DisplayItem displayItem;
+ Ttk_Element element;
+
+ switch (region) {
+ case REGION_NOTHING:
+ layout = tv->core.layout;
+ return TCL_OK; /* @@@ NYI */
+ case REGION_HEADING:
+ case REGION_SEPARATOR:
+ layout = tv->tree.headingLayout;
+ return TCL_OK; /* @@@ NYI */
+ case REGION_TREE:
+ layout = tv->tree.itemLayout;
+ break;
+ case REGION_CELL:
+ layout = tv->tree.cellLayout;
+ break;
+ }
+
+ if (!BoundingBox(tv, item, column, &bbox)) {
+ return TCL_OK;
+ }
+
+ PrepareItem(tv, item, &displayItem);
+ if (item->textObj) { displayItem.textObj = item->textObj; }
+ if (item->imageObj) { displayItem.imageObj = item->imageObj; }
+ Ttk_RebindSublayout(layout, &displayItem);
+ Ttk_PlaceLayout(layout, ItemState(tv,item), bbox);
+ element = Ttk_IdentifyElement(layout, x, y);
+
+ if (element) {
+ const char *elementName = Ttk_ElementName(element);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(elementName, -1));
+ }
+ break;
+ }
+ }
+ return TCL_OK;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Widget commands -- item and column configuration.
+ */
+
+/* + $tv item $item ?options ....?
+ * Query or configure item options.
+ */
+static int TreeviewItemCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Treeview *tv = recordPtr;
+ TreeItem *item;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "item ?option ?value??...");
+ return TCL_ERROR;
+ }
+ if (!(item = FindItem(interp, tv, objv[2]))) {
+ return TCL_ERROR;
+ }
+
+ if (objc == 3) {
+ return TtkEnumerateOptions(interp, item, ItemOptionSpecs,
+ tv->tree.itemOptionTable, tv->core.tkwin);
+ } else if (objc == 4) {
+ return TtkGetOptionValue(interp, item, objv[3],
+ tv->tree.itemOptionTable, tv->core.tkwin);
+ } else {
+ return ConfigureItem(interp, tv, item, objc-3, objv+3);
+ }
+}
+
+/* + $tv column column ?options ....?
+ * Column data accessor
+ */
+static int TreeviewColumnCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Treeview *tv = recordPtr;
+ TreeColumn *column;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "column -option value...");
+ return TCL_ERROR;
+ }
+ if (!(column = FindColumn(interp, tv, objv[2]))) {
+ return TCL_ERROR;
+ }
+
+ if (objc == 3) {
+ return TtkEnumerateOptions(interp, column, ColumnOptionSpecs,
+ tv->tree.columnOptionTable, tv->core.tkwin);
+ } else if (objc == 4) {
+ return TtkGetOptionValue(interp, column, objv[3],
+ tv->tree.columnOptionTable, tv->core.tkwin);
+ } else {
+ return ConfigureColumn(interp, tv, column, objc-3, objv+3);
+ }
+}
+
+/* + $tv heading column ?options ....?
+ * Heading data accessor
+ */
+static int TreeviewHeadingCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Treeview *tv = recordPtr;
+ Tk_OptionTable optionTable = tv->tree.headingOptionTable;
+ Tk_Window tkwin = tv->core.tkwin;
+ TreeColumn *column;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "column -option value...");
+ return TCL_ERROR;
+ }
+ if (!(column = FindColumn(interp, tv, objv[2]))) {
+ return TCL_ERROR;
+ }
+
+ if (objc == 3) {
+ return TtkEnumerateOptions(
+ interp, column, HeadingOptionSpecs, optionTable, tkwin);
+ } else if (objc == 4) {
+ return TtkGetOptionValue(
+ interp, column, objv[3], optionTable, tkwin);
+ } else {
+ return ConfigureHeading(interp, tv, column, objc-3,objv+3);
+ }
+}
+
+/* + $tv set $item ?$column ?value??
+ * Query or configure cell values
+ */
+static int TreeviewSetCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Treeview *tv = recordPtr;
+ TreeItem *item;
+ TreeColumn *column;
+ int columnNumber;
+
+ if (objc < 3 || objc > 5) {
+ Tcl_WrongNumArgs(interp, 2, objv, "item ?column ?value??");
+ return TCL_ERROR;
+ }
+ if (!(item = FindItem(interp, tv, objv[2])))
+ return TCL_ERROR;
+
+ /* Make sure -values exists:
+ */
+ if (!item->valuesObj) {
+ item->valuesObj = Tcl_NewListObj(0,0);
+ Tcl_IncrRefCount(item->valuesObj);
+ }
+
+ if (objc == 3) {
+ /* Return dictionary:
+ */
+ Tcl_Obj *result = Tcl_NewListObj(0,0);
+ Tcl_Obj *value;
+ for (columnNumber=0; columnNumber<tv->tree.nColumns; ++columnNumber) {
+ Tcl_ListObjIndex(interp, item->valuesObj, columnNumber, &value);
+ if (value) {
+ Tcl_ListObjAppendElement(NULL, result,
+ tv->tree.columns[columnNumber].idObj);
+ Tcl_ListObjAppendElement(NULL, result, value);
+ }
+ }
+ Tcl_SetObjResult(interp, result);
+ return TCL_OK;
+ }
+
+ /* else -- get or set column
+ */
+ if (!(column = FindColumn(interp, tv, objv[3])))
+ return TCL_ERROR;
+
+ if (column == &tv->tree.column0) {
+ /* @@@ Maybe set -text here instead? */
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "Display column #0 cannot be set", -1));
+ Tcl_SetErrorCode(interp, "TTK", "TREE", "COLUMN_0", NULL);
+ return TCL_ERROR;
+ }
+
+ /* Note: we don't do any error checking in the list operations,
+ * since item->valuesObj is guaranteed to be a list.
+ */
+ columnNumber = column - tv->tree.columns;
+
+ if (objc == 4) { /* get column */
+ Tcl_Obj *result = 0;
+ Tcl_ListObjIndex(interp, item->valuesObj, columnNumber, &result);
+ if (!result) {
+ result = Tcl_NewStringObj("",0);
+ }
+ Tcl_SetObjResult(interp, result);
+ return TCL_OK;
+ } else { /* set column */
+ int length;
+
+ item->valuesObj = unshareObj(item->valuesObj);
+
+ /* Make sure -values is fully populated:
+ */
+ Tcl_ListObjLength(interp, item->valuesObj, &length);
+ while (length < tv->tree.nColumns) {
+ Tcl_Obj *empty = Tcl_NewStringObj("",0);
+ Tcl_ListObjAppendElement(interp, item->valuesObj, empty);
+ ++length;
+ }
+
+ /* Set value:
+ */
+ Tcl_ListObjReplace(interp,item->valuesObj,columnNumber,1,1,objv+4);
+ TtkRedisplayWidget(&tv->core);
+ return TCL_OK;
+ }
+}
+
+/*------------------------------------------------------------------------
+ * +++ Widget commands -- tree modification.
+ */
+
+/* + $tv insert $parent $index ?-id id? ?-option value ...?
+ * Insert a new item.
+ */
+static int TreeviewInsertCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Treeview *tv = recordPtr;
+ TreeItem *parent, *sibling, *newItem;
+ Tcl_HashEntry *entryPtr;
+ int isNew;
+
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "parent index ?-id id? -options...");
+ return TCL_ERROR;
+ }
+
+ /* Get parent node:
+ */
+ if ((parent = FindItem(interp, tv, objv[2])) == NULL) {
+ return TCL_ERROR;
+ }
+
+ /* Locate previous sibling based on $index:
+ */
+ if (!strcmp(Tcl_GetString(objv[3]), "end")) {
+ sibling = EndPosition(tv, parent);
+ } else {
+ int index;
+ if (Tcl_GetIntFromObj(interp, objv[3], &index) != TCL_OK)
+ return TCL_ERROR;
+ sibling = InsertPosition(parent, index);
+ }
+
+ /* Get node name:
+ * If -id supplied and does not already exist, use that;
+ * Otherwise autogenerate new one.
+ */
+ objc -= 4; objv += 4;
+ if (objc >= 2 && !strcmp("-id", Tcl_GetString(objv[0]))) {
+ const char *itemName = Tcl_GetString(objv[1]);
+
+ entryPtr = Tcl_CreateHashEntry(&tv->tree.items, itemName, &isNew);
+ if (!isNew) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "Item %s already exists", itemName));
+ Tcl_SetErrorCode(interp, "TTK", "TREE", "ITEM_EXISTS", NULL);
+ return TCL_ERROR;
+ }
+ objc -= 2; objv += 2;
+ } else {
+ char idbuf[16];
+ do {
+ ++tv->tree.serial;
+ sprintf(idbuf, "I%03X", tv->tree.serial);
+ entryPtr = Tcl_CreateHashEntry(&tv->tree.items, idbuf, &isNew);
+ } while (!isNew);
+ }
+
+ /* Create and configure new item:
+ */
+ newItem = NewItem();
+ Tk_InitOptions(
+ interp, (ClientData)newItem, tv->tree.itemOptionTable, tv->core.tkwin);
+ newItem->tagset = Ttk_GetTagSetFromObj(NULL, tv->tree.tagTable, NULL);
+ if (ConfigureItem(interp, tv, newItem, objc, objv) != TCL_OK) {
+ Tcl_DeleteHashEntry(entryPtr);
+ FreeItem(newItem);
+ return TCL_ERROR;
+ }
+
+ /* Store in hash table, link into tree:
+ */
+ Tcl_SetHashValue(entryPtr, newItem);
+ newItem->entryPtr = entryPtr;
+ InsertItem(parent, sibling, newItem);
+ TtkRedisplayWidget(&tv->core);
+
+ Tcl_SetObjResult(interp, ItemID(tv, newItem));
+ return TCL_OK;
+}
+
+/* + $tv detach $item --
+ * Unlink $item from the tree.
+ */
+static int TreeviewDetachCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Treeview *tv = recordPtr;
+ TreeItem **items;
+ int i;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "item");
+ return TCL_ERROR;
+ }
+ if (!(items = GetItemListFromObj(interp, tv, objv[2]))) {
+ return TCL_ERROR;
+ }
+
+ /* Sanity-check */
+ for (i = 0; items[i]; ++i) {
+ if (items[i] == tv->tree.root) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "Cannot detach root item", -1));
+ Tcl_SetErrorCode(interp, "TTK", "TREE", "ROOT", NULL);
+ ckfree(items);
+ return TCL_ERROR;
+ }
+ }
+
+ for (i = 0; items[i]; ++i) {
+ DetachItem(items[i]);
+ }
+
+ TtkRedisplayWidget(&tv->core);
+ ckfree(items);
+ return TCL_OK;
+}
+
+/* + $tv delete $items --
+ * Delete each item in $items.
+ *
+ * Do this in two passes:
+ * First detach the item and all its descendants and remove them
+ * from the hash table. Free the items themselves in a second pass.
+ *
+ * It's done this way because an item may appear more than once
+ * in the list of items to delete (either directly or as a descendant
+ * of a previously deleted item.)
+ */
+
+static int TreeviewDeleteCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Treeview *tv = recordPtr;
+ TreeItem **items, *delq;
+ int i, selItemDeleted = 0;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "items");
+ return TCL_ERROR;
+ }
+
+ if (!(items = GetItemListFromObj(interp, tv, objv[2]))) {
+ return TCL_ERROR;
+ }
+
+ /* Sanity-check:
+ */
+ for (i=0; items[i]; ++i) {
+ if (items[i] == tv->tree.root) {
+ ckfree(items);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "Cannot delete root item", -1));
+ Tcl_SetErrorCode(interp, "TTK", "TREE", "ROOT", NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ /* Remove items from hash table.
+ */
+ delq = 0;
+ for (i=0; items[i]; ++i) {
+ if (items[i]->state & TTK_STATE_SELECTED) {
+ selItemDeleted = 1;
+ }
+ delq = DeleteItems(items[i], delq);
+ }
+
+ /* Free items:
+ */
+ while (delq) {
+ TreeItem *next = delq->next;
+ if (tv->tree.focus == delq)
+ tv->tree.focus = 0;
+ if (tv->tree.endPtr == delq)
+ tv->tree.endPtr = 0;
+ FreeItem(delq);
+ delq = next;
+ }
+
+ ckfree(items);
+ if (selItemDeleted) {
+ TtkSendVirtualEvent(tv->core.tkwin, "TreeviewSelect");
+ }
+ TtkRedisplayWidget(&tv->core);
+ return TCL_OK;
+}
+
+/* + $tv move $item $parent $index
+ * Move $item to the specified $index in $parent's child list.
+ */
+static int TreeviewMoveCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Treeview *tv = recordPtr;
+ TreeItem *item, *parent;
+ TreeItem *sibling;
+
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 2, objv, "item parent index");
+ return TCL_ERROR;
+ }
+ if ( (item = FindItem(interp, tv, objv[2])) == 0
+ || (parent = FindItem(interp, tv, objv[3])) == 0)
+ {
+ return TCL_ERROR;
+ }
+
+ /* Locate previous sibling based on $index:
+ */
+ if (!strcmp(Tcl_GetString(objv[4]), "end")) {
+ sibling = EndPosition(tv, parent);
+ } else {
+ TreeItem *p;
+ int index;
+
+ if (Tcl_GetIntFromObj(interp, objv[4], &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ sibling = 0;
+ for (p = parent->children; p != NULL && index > 0; p = p->next) {
+ if (p != item) {
+ --index;
+ } /* else -- moving node forward, count index+1 nodes */
+ sibling = p;
+ }
+ }
+
+ /* Check ancestry:
+ */
+ if (!AncestryCheck(interp, tv, item, parent)) {
+ return TCL_ERROR;
+ }
+
+ /* Moving an item after itself is a no-op:
+ */
+ if (item == sibling) {
+ return TCL_OK;
+ }
+
+ /* Move item:
+ */
+ DetachItem(item);
+ InsertItem(parent, sibling, item);
+
+ TtkRedisplayWidget(&tv->core);
+ return TCL_OK;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Widget commands -- scrolling
+ */
+
+static int TreeviewXViewCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Treeview *tv = recordPtr;
+ return TtkScrollviewCommand(interp, objc, objv, tv->tree.xscrollHandle);
+}
+
+static int TreeviewYViewCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Treeview *tv = recordPtr;
+ return TtkScrollviewCommand(interp, objc, objv, tv->tree.yscrollHandle);
+}
+
+/* $tree see $item --
+ * Ensure that $item is visible.
+ */
+static int TreeviewSeeCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Treeview *tv = recordPtr;
+ TreeItem *item, *parent;
+ int rowNumber;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "item");
+ return TCL_ERROR;
+ }
+ if (!(item = FindItem(interp, tv, objv[2]))) {
+ return TCL_ERROR;
+ }
+
+ /* Make sure all ancestors are open:
+ */
+ for (parent = item->parent; parent; parent = parent->parent) {
+ if (!(parent->state & TTK_STATE_OPEN)) {
+ parent->openObj = unshareObj(parent->openObj);
+ Tcl_SetBooleanObj(parent->openObj, 1);
+ parent->state |= TTK_STATE_OPEN;
+ TtkRedisplayWidget(&tv->core);
+ }
+ }
+ tv->tree.yscroll.total = CountRows(tv->tree.root) - 1;
+
+ /* Make sure item is visible:
+ */
+ rowNumber = RowNumber(tv, item);
+ if (rowNumber < tv->tree.yscroll.first) {
+ TtkScrollTo(tv->tree.yscrollHandle, rowNumber, 1);
+ } else if (rowNumber >= tv->tree.yscroll.last) {
+ TtkScrollTo(tv->tree.yscrollHandle,
+ tv->tree.yscroll.first + (1+rowNumber - tv->tree.yscroll.last), 1);
+ }
+
+ return TCL_OK;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Widget commands -- interactive column resize
+ */
+
+/* + $tree drag $column $newX --
+ * Set right edge of display column $column to x position $X
+ */
+static int TreeviewDragCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Treeview *tv = recordPtr;
+ int left = tv->tree.treeArea.x - tv->tree.xscroll.first;
+ int i = FirstColumn(tv);
+ TreeColumn *column;
+ int newx;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "column xposition");
+ return TCL_ERROR;
+ }
+
+ if ( (column = FindColumn(interp, tv, objv[2])) == 0
+ || Tcl_GetIntFromObj(interp, objv[3], &newx) != TCL_OK)
+ {
+ return TCL_ERROR;
+ }
+
+ for (;i < tv->tree.nDisplayColumns; ++i) {
+ TreeColumn *c = tv->tree.displayColumns[i];
+ int right = left + c->width;
+ if (c == column) {
+ /* The limit not to exceed at the right is given by the tree width
+ minus the sum of the min widths of the columns at the right of
+ the one being resized (and don't forget possible x scrolling!).
+ For stretchable columns, this min width really is the minWidth,
+ for non-stretchable columns, this is the column width.
+ */
+ int newxRightLimit = tv->tree.treeArea.x - tv->tree.xscroll.first
+ + tv->tree.treeArea.width;
+ int j = i + 1;
+ while (j < tv->tree.nDisplayColumns) {
+ TreeColumn *cr = tv->tree.displayColumns[j];
+ if (cr->stretch) {
+ newxRightLimit -= cr->minWidth;
+ } else {
+ newxRightLimit -= cr->width;
+ }
+ ++j;
+ }
+ if (newx <= newxRightLimit) {
+ DragColumn(tv, i, newx - right);
+ TtkRedisplayWidget(&tv->core);
+ }
+ return TCL_OK;
+ }
+ left = right;
+ }
+
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "column %s is not displayed", Tcl_GetString(objv[2])));
+ Tcl_SetErrorCode(interp, "TTK", "TREE", "COLUMN_INVISIBLE", NULL);
+ return TCL_ERROR;
+}
+
+static int TreeviewDropCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Treeview *tv = recordPtr;
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "drop");
+ return TCL_ERROR;
+ }
+ ResizeColumns(tv, TreeWidth(tv));
+ TtkRedisplayWidget(&tv->core);
+ return TCL_OK;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Widget commands -- focus and selection
+ */
+
+/* + $tree focus ?item?
+ */
+static int TreeviewFocusCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Treeview *tv = recordPtr;
+
+ if (objc == 2) {
+ if (tv->tree.focus) {
+ Tcl_SetObjResult(interp, ItemID(tv, tv->tree.focus));
+ }
+ return TCL_OK;
+ } else if (objc == 3) {
+ TreeItem *newFocus = FindItem(interp, tv, objv[2]);
+ if (!newFocus)
+ return TCL_ERROR;
+ tv->tree.focus = newFocus;
+ TtkRedisplayWidget(&tv->core);
+ return TCL_OK;
+ } else {
+ Tcl_WrongNumArgs(interp, 2, objv, "?newFocus?");
+ return TCL_ERROR;
+ }
+}
+
+/* + $tree selection ?add|remove|set|toggle $items?
+ */
+static int TreeviewSelectionCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ enum {
+ SELECTION_SET, SELECTION_ADD, SELECTION_REMOVE, SELECTION_TOGGLE
+ };
+ static const char *selopStrings[] = {
+ "set", "add", "remove", "toggle", NULL
+ };
+
+ Treeview *tv = recordPtr;
+ int selop, i;
+ TreeItem *item, **items;
+
+ if (objc == 2) {
+ Tcl_Obj *result = Tcl_NewListObj(0,0);
+ for (item = tv->tree.root->children; item; item=NextPreorder(item)) {
+ if (item->state & TTK_STATE_SELECTED)
+ Tcl_ListObjAppendElement(NULL, result, ItemID(tv, item));
+ }
+ Tcl_SetObjResult(interp, result);
+ return TCL_OK;
+ }
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?add|remove|set|toggle items?");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[2], selopStrings,
+ sizeof(char *), "selection operation", 0, &selop) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ items = GetItemListFromObj(interp, tv, objv[3]);
+ if (!items) {
+ return TCL_ERROR;
+ }
+
+ switch (selop)
+ {
+ case SELECTION_SET:
+ for (item=tv->tree.root; item; item=NextPreorder(item)) {
+ item->state &= ~TTK_STATE_SELECTED;
+ }
+ /*FALLTHRU*/
+ case SELECTION_ADD:
+ for (i=0; items[i]; ++i) {
+ items[i]->state |= TTK_STATE_SELECTED;
+ }
+ break;
+ case SELECTION_REMOVE:
+ for (i=0; items[i]; ++i) {
+ items[i]->state &= ~TTK_STATE_SELECTED;
+ }
+ break;
+ case SELECTION_TOGGLE:
+ for (i=0; items[i]; ++i) {
+ items[i]->state ^= TTK_STATE_SELECTED;
+ }
+ break;
+ }
+
+ ckfree(items);
+ TtkSendVirtualEvent(tv->core.tkwin, "TreeviewSelect");
+ TtkRedisplayWidget(&tv->core);
+
+ return TCL_OK;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Widget commands -- tags and bindings.
+ */
+
+/* + $tv tag bind $tag ?$sequence ?$script??
+ */
+static int TreeviewTagBindCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Treeview *tv = recordPtr;
+ Ttk_TagTable tagTable = tv->tree.tagTable;
+ Tk_BindingTable bindingTable = tv->tree.bindingTable;
+ Ttk_Tag tag;
+
+ if (objc < 4 || objc > 6) {
+ Tcl_WrongNumArgs(interp, 3, objv, "tagName ?sequence? ?script?");
+ return TCL_ERROR;
+ }
+
+ tag = Ttk_GetTagFromObj(tagTable, objv[3]);
+ if (!tag) { return TCL_ERROR; }
+
+ if (objc == 4) { /* $tv tag bind $tag */
+ Tk_GetAllBindings(interp, bindingTable, tag);
+ } else if (objc == 5) { /* $tv tag bind $tag $sequence */
+ /* TODO: distinguish "no such binding" (OK) from "bad pattern" (ERROR)
+ */
+ const char *script = Tk_GetBinding(interp,
+ bindingTable, tag, Tcl_GetString(objv[4]));
+ if (script != NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(script,-1));
+ }
+ } else if (objc == 6) { /* $tv tag bind $tag $sequence $script */
+ const char *sequence = Tcl_GetString(objv[4]);
+ const char *script = Tcl_GetString(objv[5]);
+
+ if (!*script) { /* Delete existing binding */
+ Tk_DeleteBinding(interp, bindingTable, tag, sequence);
+ } else {
+ unsigned long mask = Tk_CreateBinding(interp,
+ bindingTable, tag, sequence, script, 0);
+
+ /* Test mask to make sure event is supported:
+ */
+ if (mask & (~TreeviewBindEventMask)) {
+ Tk_DeleteBinding(interp, bindingTable, tag, sequence);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "unsupported event %s\nonly key, button, motion, and"
+ " virtual events supported", sequence));
+ Tcl_SetErrorCode(interp, "TTK", "TREE", "BIND_EVENTS", NULL);
+ return TCL_ERROR;
+ }
+ }
+ }
+ return TCL_OK;
+}
+
+/* + $tv tag configure $tag ?-option ?value -option value...??
+ */
+static int TreeviewTagConfigureCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Treeview *tv = recordPtr;
+ Ttk_TagTable tagTable = tv->tree.tagTable;
+ Ttk_Tag tag;
+
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "tagName ?-option ?value ...??");
+ return TCL_ERROR;
+ }
+
+ tag = Ttk_GetTagFromObj(tagTable, objv[3]);
+
+ if (objc == 4) {
+ return Ttk_EnumerateTagOptions(interp, tagTable, tag);
+ } else if (objc == 5) {
+ Tcl_Obj *result = Ttk_TagOptionValue(interp, tagTable, tag, objv[4]);
+ if (result) {
+ Tcl_SetObjResult(interp, result);
+ return TCL_OK;
+ } /* else */
+ return TCL_ERROR;
+ }
+ /* else */
+ TtkRedisplayWidget(&tv->core);
+ return Ttk_ConfigureTag(interp, tagTable, tag, objc - 4, objv + 4);
+}
+
+/* + $tv tag has $tag ?$item?
+ */
+static int TreeviewTagHasCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Treeview *tv = recordPtr;
+
+ if (objc == 4) { /* Return list of all items with tag */
+ Ttk_Tag tag = Ttk_GetTagFromObj(tv->tree.tagTable, objv[3]);
+ TreeItem *item = tv->tree.root;
+ Tcl_Obj *result = Tcl_NewListObj(0,0);
+
+ while (item) {
+ if (Ttk_TagSetContains(item->tagset, tag)) {
+ Tcl_ListObjAppendElement(NULL, result, ItemID(tv, item));
+ }
+ item = NextPreorder(item);
+ }
+
+ Tcl_SetObjResult(interp, result);
+ return TCL_OK;
+ } else if (objc == 5) { /* Test if item has specified tag */
+ Ttk_Tag tag = Ttk_GetTagFromObj(tv->tree.tagTable, objv[3]);
+ TreeItem *item = FindItem(interp, tv, objv[4]);
+ if (!item) {
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp,
+ Tcl_NewBooleanObj(Ttk_TagSetContains(item->tagset, tag)));
+ return TCL_OK;
+ } else {
+ Tcl_WrongNumArgs(interp, 3, objv, "tagName ?item?");
+ return TCL_ERROR;
+ }
+}
+
+/* + $tv tag names $tag
+ */
+static int TreeviewTagNamesCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Treeview *tv = recordPtr;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, "");
+ return TCL_ERROR;
+ }
+
+ return Ttk_EnumerateTags(interp, tv->tree.tagTable);
+}
+
+/* + $tv tag add $tag $items
+ */
+static void AddTag(TreeItem *item, Ttk_Tag tag)
+{
+ if (Ttk_TagSetAdd(item->tagset, tag)) {
+ if (item->tagsObj) Tcl_DecrRefCount(item->tagsObj);
+ item->tagsObj = Ttk_NewTagSetObj(item->tagset);
+ Tcl_IncrRefCount(item->tagsObj);
+ }
+}
+
+static int TreeviewTagAddCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Treeview *tv = recordPtr;
+ Ttk_Tag tag;
+ TreeItem **items;
+ int i;
+
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 3, objv, "tagName items");
+ return TCL_ERROR;
+ }
+
+ tag = Ttk_GetTagFromObj(tv->tree.tagTable, objv[3]);
+ items = GetItemListFromObj(interp, tv, objv[4]);
+
+ if (!items) {
+ return TCL_ERROR;
+ }
+
+ for (i=0; items[i]; ++i) {
+ AddTag(items[i], tag);
+ }
+
+ TtkRedisplayWidget(&tv->core);
+
+ return TCL_OK;
+}
+
+/* + $tv tag remove $tag ?$items?
+ */
+static void RemoveTag(TreeItem *item, Ttk_Tag tag)
+{
+ if (Ttk_TagSetRemove(item->tagset, tag)) {
+ if (item->tagsObj) Tcl_DecrRefCount(item->tagsObj);
+ item->tagsObj = Ttk_NewTagSetObj(item->tagset);
+ Tcl_IncrRefCount(item->tagsObj);
+ }
+}
+
+static int TreeviewTagRemoveCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Treeview *tv = recordPtr;
+ Ttk_Tag tag;
+
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "tagName items");
+ return TCL_ERROR;
+ }
+
+ tag = Ttk_GetTagFromObj(tv->tree.tagTable, objv[3]);
+
+ if (objc == 5) {
+ TreeItem **items = GetItemListFromObj(interp, tv, objv[4]);
+ int i;
+
+ if (!items) {
+ return TCL_ERROR;
+ }
+ for (i=0; items[i]; ++i) {
+ RemoveTag(items[i], tag);
+ }
+ } else if (objc == 4) {
+ TreeItem *item = tv->tree.root;
+ while (item) {
+ RemoveTag(item, tag);
+ item=NextPreorder(item);
+ }
+ }
+
+ TtkRedisplayWidget(&tv->core);
+
+ return TCL_OK;
+}
+
+static const Ttk_Ensemble TreeviewTagCommands[] = {
+ { "add", TreeviewTagAddCommand,0 },
+ { "bind", TreeviewTagBindCommand,0 },
+ { "configure", TreeviewTagConfigureCommand,0 },
+ { "has", TreeviewTagHasCommand,0 },
+ { "names", TreeviewTagNamesCommand,0 },
+ { "remove", TreeviewTagRemoveCommand,0 },
+ { 0,0,0 }
+};
+
+/*------------------------------------------------------------------------
+ * +++ Widget commands record.
+ */
+static const Ttk_Ensemble TreeviewCommands[] = {
+ { "bbox", TreeviewBBoxCommand,0 },
+ { "children", TreeviewChildrenCommand,0 },
+ { "cget", TtkWidgetCgetCommand,0 },
+ { "column", TreeviewColumnCommand,0 },
+ { "configure", TtkWidgetConfigureCommand,0 },
+ { "delete", TreeviewDeleteCommand,0 },
+ { "detach", TreeviewDetachCommand,0 },
+ { "drag", TreeviewDragCommand,0 },
+ { "drop", TreeviewDropCommand,0 },
+ { "exists", TreeviewExistsCommand,0 },
+ { "focus", TreeviewFocusCommand,0 },
+ { "heading", TreeviewHeadingCommand,0 },
+ { "identify", TreeviewIdentifyCommand,0 },
+ { "index", TreeviewIndexCommand,0 },
+ { "instate", TtkWidgetInstateCommand,0 },
+ { "insert", TreeviewInsertCommand,0 },
+ { "item", TreeviewItemCommand,0 },
+ { "move", TreeviewMoveCommand,0 },
+ { "next", TreeviewNextCommand,0 },
+ { "parent", TreeviewParentCommand,0 },
+ { "prev", TreeviewPrevCommand,0 },
+ { "see", TreeviewSeeCommand,0 },
+ { "selection" , TreeviewSelectionCommand,0 },
+ { "set", TreeviewSetCommand,0 },
+ { "state", TtkWidgetStateCommand,0 },
+ { "tag", 0,TreeviewTagCommands },
+ { "xview", TreeviewXViewCommand,0 },
+ { "yview", TreeviewYViewCommand,0 },
+ { 0,0,0 }
+};
+
+/*------------------------------------------------------------------------
+ * +++ Widget definition.
+ */
+
+static WidgetSpec TreeviewWidgetSpec = {
+ "Treeview", /* className */
+ sizeof(Treeview), /* recordSize */
+ TreeviewOptionSpecs, /* optionSpecs */
+ TreeviewCommands, /* subcommands */
+ TreeviewInitialize, /* initializeProc */
+ TreeviewCleanup, /* cleanupProc */
+ TreeviewConfigure, /* configureProc */
+ TtkNullPostConfigure, /* postConfigureProc */
+ TreeviewGetLayout, /* getLayoutProc */
+ TreeviewSize, /* sizeProc */
+ TreeviewDoLayout, /* layoutProc */
+ TreeviewDisplay /* displayProc */
+};
+
+/*------------------------------------------------------------------------
+ * +++ Layout specifications.
+ */
+
+TTK_BEGIN_LAYOUT_TABLE(LayoutTable)
+
+TTK_LAYOUT("Treeview",
+ TTK_GROUP("Treeview.field", TTK_FILL_BOTH|TTK_BORDER,
+ TTK_GROUP("Treeview.padding", TTK_FILL_BOTH,
+ TTK_NODE("Treeview.treearea", TTK_FILL_BOTH))))
+
+TTK_LAYOUT("Item",
+ TTK_GROUP("Treeitem.padding", TTK_FILL_BOTH,
+ TTK_NODE("Treeitem.indicator", TTK_PACK_LEFT)
+ TTK_NODE("Treeitem.image", TTK_PACK_LEFT)
+ TTK_GROUP("Treeitem.focus", TTK_PACK_LEFT,
+ TTK_NODE("Treeitem.text", TTK_PACK_LEFT))))
+
+TTK_LAYOUT("Cell",
+ TTK_GROUP("Treedata.padding", TTK_FILL_BOTH,
+ TTK_NODE("Treeitem.text", TTK_FILL_BOTH)))
+
+TTK_LAYOUT("Heading",
+ TTK_NODE("Treeheading.cell", TTK_FILL_BOTH)
+ TTK_GROUP("Treeheading.border", TTK_FILL_BOTH,
+ TTK_GROUP("Treeheading.padding", TTK_FILL_BOTH,
+ TTK_NODE("Treeheading.image", TTK_PACK_RIGHT)
+ TTK_NODE("Treeheading.text", TTK_FILL_X))))
+
+TTK_LAYOUT("Row",
+ TTK_NODE("Treeitem.row", TTK_FILL_BOTH))
+
+TTK_END_LAYOUT_TABLE
+
+/*------------------------------------------------------------------------
+ * +++ Tree indicator element.
+ */
+
+typedef struct {
+ Tcl_Obj *colorObj;
+ Tcl_Obj *sizeObj;
+ Tcl_Obj *marginsObj;
+} TreeitemIndicator;
+
+static Ttk_ElementOptionSpec TreeitemIndicatorOptions[] = {
+ { "-foreground", TK_OPTION_COLOR,
+ Tk_Offset(TreeitemIndicator,colorObj), DEFAULT_FOREGROUND },
+ { "-indicatorsize", TK_OPTION_PIXELS,
+ Tk_Offset(TreeitemIndicator,sizeObj), "12" },
+ { "-indicatormargins", TK_OPTION_STRING,
+ Tk_Offset(TreeitemIndicator,marginsObj), "2 2 4 2" },
+ { NULL, 0, 0, NULL }
+};
+
+static void TreeitemIndicatorSize(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+ TreeitemIndicator *indicator = elementRecord;
+ Ttk_Padding margins;
+ int size = 0;
+
+ Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginsObj, &margins);
+ Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &size);
+
+ *widthPtr = size + Ttk_PaddingWidth(margins);
+ *heightPtr = size + Ttk_PaddingHeight(margins);
+}
+
+static void TreeitemIndicatorDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, Ttk_State state)
+{
+ TreeitemIndicator *indicator = elementRecord;
+ ArrowDirection direction =
+ (state & TTK_STATE_OPEN) ? ARROW_DOWN : ARROW_RIGHT;
+ Ttk_Padding margins;
+ XColor *borderColor = Tk_GetColorFromObj(tkwin, indicator->colorObj);
+ XGCValues gcvalues; GC gc; unsigned mask;
+
+ if (state & TTK_STATE_LEAF) /* don't draw anything */
+ return;
+
+ Ttk_GetPaddingFromObj(NULL,tkwin,indicator->marginsObj,&margins);
+ b = Ttk_PadBox(b, margins);
+
+ gcvalues.foreground = borderColor->pixel;
+ gcvalues.line_width = 1;
+ mask = GCForeground | GCLineWidth;
+ gc = Tk_GetGC(tkwin, mask, &gcvalues);
+
+ TtkDrawArrow(Tk_Display(tkwin), d, gc, b, direction);
+
+ Tk_FreeGC(Tk_Display(tkwin), gc);
+}
+
+static Ttk_ElementSpec TreeitemIndicatorElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(TreeitemIndicator),
+ TreeitemIndicatorOptions,
+ TreeitemIndicatorSize,
+ TreeitemIndicatorDraw
+};
+
+/*------------------------------------------------------------------------
+ * +++ Row element.
+ */
+
+typedef struct {
+ Tcl_Obj *backgroundObj;
+ Tcl_Obj *rowNumberObj;
+} RowElement;
+
+static Ttk_ElementOptionSpec RowElementOptions[] = {
+ { "-background", TK_OPTION_COLOR,
+ Tk_Offset(RowElement,backgroundObj), DEFAULT_BACKGROUND },
+ { "-rownumber", TK_OPTION_INT,
+ Tk_Offset(RowElement,rowNumberObj), "0" },
+ { NULL, 0, 0, NULL }
+};
+
+static void RowElementDraw(
+ void *clientData, void *elementRecord, Tk_Window tkwin,
+ Drawable d, Ttk_Box b, Ttk_State state)
+{
+ RowElement *row = elementRecord;
+ XColor *color = Tk_GetColorFromObj(tkwin, row->backgroundObj);
+ GC gc = Tk_GCForColor(color, d);
+ XFillRectangle(Tk_Display(tkwin), d, gc,
+ b.x, b.y, b.width, b.height);
+}
+
+static Ttk_ElementSpec RowElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(RowElement),
+ RowElementOptions,
+ TtkNullElementSize,
+ RowElementDraw
+};
+
+/*------------------------------------------------------------------------
+ * +++ Initialisation.
+ */
+
+MODULE_SCOPE
+void TtkTreeview_Init(Tcl_Interp *interp)
+{
+ Ttk_Theme theme = Ttk_GetDefaultTheme(interp);
+
+ RegisterWidget(interp, "ttk::treeview", &TreeviewWidgetSpec);
+
+ Ttk_RegisterElement(interp, theme, "Treeitem.indicator",
+ &TreeitemIndicatorElementSpec, 0);
+ Ttk_RegisterElement(interp, theme, "Treeitem.row", &RowElementSpec, 0);
+ Ttk_RegisterElement(interp, theme, "Treeheading.cell", &RowElementSpec, 0);
+ Ttk_RegisterElement(interp, theme, "treearea", &ttkNullElementSpec, 0);
+
+ Ttk_RegisterLayouts(theme, LayoutTable);
+}
+
+/*EOF*/
diff --git a/tk8.6/generic/ttk/ttkWidget.c b/tk8.6/generic/ttk/ttkWidget.c
new file mode 100644
index 0000000..d7f4b25
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkWidget.c
@@ -0,0 +1,791 @@
+/*
+ * Copyright (c) 2003, Joe English
+ *
+ * Core widget utilities.
+ */
+
+#include <string.h>
+#include "tkInt.h"
+#include "ttkTheme.h"
+#include "ttkWidget.h"
+
+#ifdef MAC_OSX_TK
+#define TK_NO_DOUBLE_BUFFERING 1
+#endif
+
+/*------------------------------------------------------------------------
+ * +++ Internal helper routines.
+ */
+
+/* UpdateLayout --
+ * Call the widget's get-layout hook to recompute corePtr->layout.
+ * Returns TCL_OK if successful, returns TCL_ERROR and leaves
+ * the layout unchanged otherwise.
+ */
+static int UpdateLayout(Tcl_Interp *interp, WidgetCore *corePtr)
+{
+ Ttk_Theme themePtr = Ttk_GetCurrentTheme(interp);
+ Ttk_Layout newLayout =
+ corePtr->widgetSpec->getLayoutProc(interp, themePtr,corePtr);
+
+ if (newLayout) {
+ if (corePtr->layout) {
+ Ttk_FreeLayout(corePtr->layout);
+ }
+ corePtr->layout = newLayout;
+ return TCL_OK;
+ }
+ return TCL_ERROR;
+}
+
+/* SizeChanged --
+ * Call the widget's sizeProc to compute new requested size
+ * and pass it to the geometry manager.
+ */
+static void SizeChanged(WidgetCore *corePtr)
+{
+ int reqWidth = 1, reqHeight = 1;
+
+ if (corePtr->widgetSpec->sizeProc(corePtr,&reqWidth,&reqHeight)) {
+ Tk_GeometryRequest(corePtr->tkwin, reqWidth, reqHeight);
+ }
+}
+
+#ifndef TK_NO_DOUBLE_BUFFERING
+
+/* BeginDrawing --
+ * Returns a Drawable for drawing the widget contents.
+ * This is normally an off-screen Pixmap, copied to
+ * the window by EndDrawing().
+ */
+static Drawable BeginDrawing(Tk_Window tkwin)
+{
+ return Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin),
+ Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));
+}
+
+/* EndDrawing --
+ * Copy the drawable contents to the screen and release resources.
+ */
+static void EndDrawing(Tk_Window tkwin, Drawable d)
+{
+ XGCValues gcValues;
+ GC gc;
+
+ gcValues.function = GXcopy;
+ gcValues.graphics_exposures = False;
+ gc = Tk_GetGC(tkwin, GCFunction|GCGraphicsExposures, &gcValues);
+
+ XCopyArea(Tk_Display(tkwin), d, Tk_WindowId(tkwin), gc,
+ 0, 0, (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin),
+ 0, 0);
+
+ Tk_FreePixmap(Tk_Display(tkwin), d);
+ Tk_FreeGC(Tk_Display(tkwin), gc);
+}
+#else
+/* No double-buffering: draw directly into the window. */
+static Drawable BeginDrawing(Tk_Window tkwin) { return Tk_WindowId(tkwin); }
+static void EndDrawing(Tk_Window tkwin, Drawable d) { }
+#endif
+
+/* DrawWidget --
+ * Redraw a widget. Called as an idle handler.
+ */
+static void DrawWidget(ClientData recordPtr)
+{
+ WidgetCore *corePtr = recordPtr;
+
+ corePtr->flags &= ~REDISPLAY_PENDING;
+ if (Tk_IsMapped(corePtr->tkwin)) {
+ Drawable d = BeginDrawing(corePtr->tkwin);
+ corePtr->widgetSpec->layoutProc(recordPtr);
+ corePtr->widgetSpec->displayProc(recordPtr, d);
+ EndDrawing(corePtr->tkwin, d);
+ }
+}
+
+/* TtkRedisplayWidget --
+ * Schedule redisplay as an idle handler.
+ */
+void TtkRedisplayWidget(WidgetCore *corePtr)
+{
+ if (corePtr->flags & WIDGET_DESTROYED) {
+ return;
+ }
+
+ if (!(corePtr->flags & REDISPLAY_PENDING)) {
+ Tcl_DoWhenIdle(DrawWidget, corePtr);
+ corePtr->flags |= REDISPLAY_PENDING;
+ }
+}
+
+/* TtkResizeWidget --
+ * Recompute widget size, schedule geometry propagation and redisplay.
+ */
+void TtkResizeWidget(WidgetCore *corePtr)
+{
+ if (corePtr->flags & WIDGET_DESTROYED) {
+ return;
+ }
+
+ SizeChanged(corePtr);
+ TtkRedisplayWidget(corePtr);
+}
+
+/* TtkWidgetChangeState --
+ * Set / clear the specified bits in the 'state' flag,
+ */
+void TtkWidgetChangeState(WidgetCore *corePtr,
+ unsigned int setBits, unsigned int clearBits)
+{
+ Ttk_State oldState = corePtr->state;
+ corePtr->state = (oldState & ~clearBits) | setBits;
+ if (corePtr->state ^ oldState) {
+ TtkRedisplayWidget(corePtr);
+ }
+}
+
+/* WidgetInstanceObjCmd --
+ * Widget instance command implementation.
+ */
+static int
+WidgetInstanceObjCmd(
+ ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ WidgetCore *corePtr = clientData;
+ const Ttk_Ensemble *commands = corePtr->widgetSpec->commands;
+ int status;
+
+ Tcl_Preserve(clientData);
+ status = Ttk_InvokeEnsemble(commands,1, clientData,interp,objc,objv);
+ Tcl_Release(clientData);
+
+ return status;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Widget destruction.
+ *
+ * A widget can be destroyed when the application explicitly
+ * destroys the window or one of its ancestors via [destroy]
+ * or Tk_DestroyWindow(); when the application deletes the widget
+ * instance command; when there is an error in the widget constructor;
+ * or when another application calls XDestroyWindow on the window ID.
+ *
+ * The window receives a <DestroyNotify> event in all cases,
+ * so we do the bulk of the cleanup there. See [#2207435] for
+ * further notes (esp. re: Tk_FreeConfigOptions).
+ *
+ * Widget code that reenters the interp should only do so
+ * when the widtget is Tcl_Preserve()d, and should check
+ * the WIDGET_DESTROYED flag bit upon return.
+ */
+
+/* WidgetInstanceObjCmdDeleted --
+ * Widget instance command deletion callback.
+ */
+static void
+WidgetInstanceObjCmdDeleted(ClientData clientData)
+{
+ WidgetCore *corePtr = clientData;
+ corePtr->widgetCmd = NULL;
+ if (corePtr->tkwin != NULL)
+ Tk_DestroyWindow(corePtr->tkwin);
+}
+
+/* FreeWidget --
+ * Final cleanup for widget; called via Tcl_EventuallyFree().
+ */
+static void
+FreeWidget(void *memPtr)
+{
+ ckfree(memPtr);
+}
+
+/* DestroyWidget --
+ * Main widget destructor; called from <DestroyNotify> event handler.
+ */
+static void
+DestroyWidget(WidgetCore *corePtr)
+{
+ corePtr->flags |= WIDGET_DESTROYED;
+
+ corePtr->widgetSpec->cleanupProc(corePtr);
+
+ Tk_FreeConfigOptions(
+ (ClientData)corePtr, corePtr->optionTable, corePtr->tkwin);
+
+ if (corePtr->layout) {
+ Ttk_FreeLayout(corePtr->layout);
+ }
+
+ if (corePtr->flags & REDISPLAY_PENDING) {
+ Tcl_CancelIdleCall(DrawWidget, corePtr);
+ }
+
+ corePtr->tkwin = NULL;
+ if (corePtr->widgetCmd) {
+ Tcl_Command cmd = corePtr->widgetCmd;
+ corePtr->widgetCmd = 0;
+ /* NB: this can reenter the interpreter via a command traces */
+ Tcl_DeleteCommandFromToken(corePtr->interp, cmd);
+ }
+ Tcl_EventuallyFree(corePtr, (Tcl_FreeProc *) FreeWidget);
+}
+
+/*
+ * CoreEventProc --
+ * Event handler for basic events.
+ * Processes Expose, Configure, FocusIn/Out, and Destroy events.
+ * Also handles <<ThemeChanged>> virtual events.
+ *
+ * For Expose and Configure, simply schedule the widget for redisplay.
+ * For Destroy events, handle the cleanup process.
+ *
+ * For Focus events, set/clear the focus bit in the state field.
+ * It turns out this is impossible to do correctly in a binding script,
+ * because Tk filters out focus events with detail == NotifyInferior.
+ *
+ * For Deactivate/Activate pseudo-events, set/clear the background state
+ * flag.
+ */
+
+static const unsigned CoreEventMask
+ = ExposureMask
+ | StructureNotifyMask
+ | FocusChangeMask
+ | VirtualEventMask
+ | ActivateMask
+ | EnterWindowMask
+ | LeaveWindowMask
+ ;
+
+static void CoreEventProc(ClientData clientData, XEvent *eventPtr)
+{
+ WidgetCore *corePtr = clientData;
+
+ switch (eventPtr->type)
+ {
+ case ConfigureNotify :
+ TtkRedisplayWidget(corePtr);
+ break;
+ case Expose :
+ if (eventPtr->xexpose.count == 0) {
+ TtkRedisplayWidget(corePtr);
+ }
+ break;
+ case DestroyNotify :
+ Tk_DeleteEventHandler(
+ corePtr->tkwin, CoreEventMask,CoreEventProc,clientData);
+ DestroyWidget(corePtr);
+ break;
+ case FocusIn:
+ case FocusOut:
+ /* Don't process "virtual crossing" events */
+ if ( eventPtr->xfocus.detail == NotifyInferior
+ || eventPtr->xfocus.detail == NotifyAncestor
+ || eventPtr->xfocus.detail == NotifyNonlinear)
+ {
+ if (eventPtr->type == FocusIn)
+ corePtr->state |= TTK_STATE_FOCUS;
+ else
+ corePtr->state &= ~TTK_STATE_FOCUS;
+ TtkRedisplayWidget(corePtr);
+ }
+ break;
+ case ActivateNotify:
+ corePtr->state &= ~TTK_STATE_BACKGROUND;
+ TtkRedisplayWidget(corePtr);
+ break;
+ case DeactivateNotify:
+ corePtr->state |= TTK_STATE_BACKGROUND;
+ TtkRedisplayWidget(corePtr);
+ break;
+ case LeaveNotify:
+ corePtr->state &= ~TTK_STATE_HOVER;
+ TtkRedisplayWidget(corePtr);
+ break;
+ case EnterNotify:
+ corePtr->state |= TTK_STATE_HOVER;
+ TtkRedisplayWidget(corePtr);
+ break;
+ case VirtualEvent:
+ if (!strcmp("ThemeChanged", ((XVirtualEvent *)(eventPtr))->name)) {
+ (void)UpdateLayout(corePtr->interp, corePtr);
+ SizeChanged(corePtr);
+ TtkRedisplayWidget(corePtr);
+ }
+ default:
+ /* can't happen... */
+ break;
+ }
+}
+
+/*
+ * WidgetWorldChanged --
+ * Default Tk_ClassWorldChangedProc() for widgets.
+ * Invoked whenever fonts or other system resources are changed;
+ * recomputes geometry.
+ */
+static void WidgetWorldChanged(ClientData clientData)
+{
+ WidgetCore *corePtr = clientData;
+ SizeChanged(corePtr);
+ TtkRedisplayWidget(corePtr);
+}
+
+static Tk_ClassProcs widgetClassProcs = {
+ sizeof(Tk_ClassProcs), /* size */
+ WidgetWorldChanged, /* worldChangedProc */
+ NULL, /* createProc */
+ NULL /* modalProc */
+};
+
+/*
+ * TtkWidgetConstructorObjCmd --
+ * General-purpose widget constructor command implementation.
+ * ClientData is a WidgetSpec *.
+ */
+int TtkWidgetConstructorObjCmd(
+ ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ WidgetSpec *widgetSpec = clientData;
+ const char *className = widgetSpec->className;
+ Tk_OptionTable optionTable =
+ Tk_CreateOptionTable(interp, widgetSpec->optionSpecs);
+ Tk_Window tkwin;
+ void *recordPtr;
+ WidgetCore *corePtr;
+ Tk_SavedOptions savedOptions;
+ int i;
+
+ if (objc < 2 || objc % 2 == 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?");
+ return TCL_ERROR;
+ }
+
+ /* Check if a -class option has been specified.
+ * We have to do this before the InitOptions() call,
+ * since InitOptions() is affected by the widget class.
+ */
+ for (i = 2; i < objc; i += 2) {
+ if (!strcmp(Tcl_GetString(objv[i]), "-class")) {
+ className = Tcl_GetString(objv[i+1]);
+ break;
+ }
+ }
+
+ tkwin = Tk_CreateWindowFromPath(
+ interp, Tk_MainWindow(interp), Tcl_GetString(objv[1]), NULL);
+ if (tkwin == NULL)
+ return TCL_ERROR;
+
+ /*
+ * Allocate and initialize the widget record.
+ */
+ recordPtr = ckalloc(widgetSpec->recordSize);
+ memset(recordPtr, 0, widgetSpec->recordSize);
+ corePtr = recordPtr;
+
+ corePtr->tkwin = tkwin;
+ corePtr->interp = interp;
+ corePtr->widgetSpec = widgetSpec;
+ corePtr->widgetCmd = Tcl_CreateObjCommand(interp, Tk_PathName(tkwin),
+ WidgetInstanceObjCmd, recordPtr, WidgetInstanceObjCmdDeleted);
+ corePtr->optionTable = optionTable;
+ corePtr->layout = NULL;
+ corePtr->flags = 0;
+ corePtr->state = 0;
+
+ Tk_SetClass(tkwin, className);
+ Tk_SetClassProcs(tkwin, &widgetClassProcs, recordPtr);
+ Tk_SetWindowBackgroundPixmap(tkwin, ParentRelative);
+
+ widgetSpec->initializeProc(interp, recordPtr);
+
+ Tk_CreateEventHandler(tkwin, CoreEventMask, CoreEventProc, recordPtr);
+
+ /*
+ * Initial configuration.
+ */
+
+ Tcl_Preserve(corePtr);
+ if (Tk_InitOptions(interp, recordPtr, optionTable, tkwin) != TCL_OK) {
+ goto error;
+ }
+
+ if (Tk_SetOptions(interp, recordPtr, optionTable,
+ objc - 2, objv + 2, tkwin, &savedOptions, NULL) != TCL_OK) {
+ Tk_RestoreSavedOptions(&savedOptions);
+ goto error;
+ } else {
+ Tk_FreeSavedOptions(&savedOptions);
+ }
+ if (widgetSpec->configureProc(interp, recordPtr, ~0) != TCL_OK)
+ goto error;
+ if (widgetSpec->postConfigureProc(interp, recordPtr, ~0) != TCL_OK)
+ goto error;
+
+ if (WidgetDestroyed(corePtr))
+ goto error;
+
+ Tcl_Release(corePtr);
+
+ SizeChanged(corePtr);
+ Tk_MakeWindowExist(tkwin);
+
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(Tk_PathName(tkwin), -1));
+ return TCL_OK;
+
+error:
+ if (WidgetDestroyed(corePtr)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "widget has been destroyed", -1));
+ } else {
+ Tk_DestroyWindow(tkwin);
+ }
+ Tcl_Release(corePtr);
+ return TCL_ERROR;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Default implementations for widget hook procedures.
+ */
+
+/* TtkWidgetGetLayout --
+ * Default getLayoutProc.
+ * Looks up the layout based on the -style resource (if specified),
+ * otherwise use the widget class.
+ */
+Ttk_Layout TtkWidgetGetLayout(
+ Tcl_Interp *interp, Ttk_Theme themePtr, void *recordPtr)
+{
+ WidgetCore *corePtr = recordPtr;
+ const char *styleName = 0;
+
+ if (corePtr->styleObj)
+ styleName = Tcl_GetString(corePtr->styleObj);
+
+ if (!styleName || *styleName == '\0')
+ styleName = corePtr->widgetSpec->className;
+
+ return Ttk_CreateLayout(interp, themePtr, styleName,
+ recordPtr, corePtr->optionTable, corePtr->tkwin);
+}
+
+/*
+ * TtkWidgetGetOrientedLayout --
+ * Helper routine. Same as TtkWidgetGetLayout, but prefixes
+ * "Horizontal." or "Vertical." to the style name, depending
+ * on the value of the 'orient' option.
+ */
+Ttk_Layout TtkWidgetGetOrientedLayout(
+ Tcl_Interp *interp, Ttk_Theme themePtr, void *recordPtr, Tcl_Obj *orientObj)
+{
+ WidgetCore *corePtr = recordPtr;
+ const char *baseStyleName = 0;
+ Tcl_DString styleName;
+ int orient = TTK_ORIENT_HORIZONTAL;
+ Ttk_Layout layout;
+
+ Tcl_DStringInit(&styleName);
+
+ /* Prefix:
+ */
+ Ttk_GetOrientFromObj(NULL, orientObj, &orient);
+ if (orient == TTK_ORIENT_HORIZONTAL)
+ Tcl_DStringAppend(&styleName, "Horizontal.", -1);
+ else
+ Tcl_DStringAppend(&styleName, "Vertical.", -1);
+
+ /* Add base style name:
+ */
+ if (corePtr->styleObj)
+ baseStyleName = Tcl_GetString(corePtr->styleObj);
+ if (!baseStyleName || *baseStyleName == '\0')
+ baseStyleName = corePtr->widgetSpec->className;
+
+ Tcl_DStringAppend(&styleName, baseStyleName, -1);
+
+ /* Create layout:
+ */
+ layout= Ttk_CreateLayout(interp, themePtr, Tcl_DStringValue(&styleName),
+ recordPtr, corePtr->optionTable, corePtr->tkwin);
+
+ Tcl_DStringFree(&styleName);
+
+ return layout;
+}
+
+/* TtkNullInitialize --
+ * Default widget initializeProc (no-op)
+ */
+void TtkNullInitialize(Tcl_Interp *interp, void *recordPtr)
+{
+}
+
+/* TtkNullPostConfigure --
+ * Default widget postConfigureProc (no-op)
+ */
+int TtkNullPostConfigure(Tcl_Interp *interp, void *clientData, int mask)
+{
+ return TCL_OK;
+}
+
+/* TtkCoreConfigure --
+ * Default widget configureProc.
+ * Handles -style option.
+ */
+int TtkCoreConfigure(Tcl_Interp *interp, void *clientData, int mask)
+{
+ WidgetCore *corePtr = clientData;
+ int status = TCL_OK;
+
+ if (mask & STYLE_CHANGED) {
+ status = UpdateLayout(interp, corePtr);
+ }
+
+ return status;
+}
+
+/* TtkNullCleanup --
+ * Default widget cleanupProc (no-op)
+ */
+void TtkNullCleanup(void *recordPtr)
+{
+ return;
+}
+
+/* TtkWidgetDoLayout --
+ * Default widget layoutProc.
+ */
+void TtkWidgetDoLayout(void *clientData)
+{
+ WidgetCore *corePtr = clientData;
+ Ttk_PlaceLayout(corePtr->layout,corePtr->state,Ttk_WinBox(corePtr->tkwin));
+}
+
+/* TtkWidgetDisplay --
+ * Default widget displayProc.
+ */
+void TtkWidgetDisplay(void *recordPtr, Drawable d)
+{
+ WidgetCore *corePtr = recordPtr;
+ Ttk_DrawLayout(corePtr->layout, corePtr->state, d);
+}
+
+/* TtkWidgetSize --
+ * Default widget sizeProc()
+ */
+int TtkWidgetSize(void *recordPtr, int *widthPtr, int *heightPtr)
+{
+ WidgetCore *corePtr = recordPtr;
+ Ttk_LayoutSize(corePtr->layout, corePtr->state, widthPtr, heightPtr);
+ return 1;
+}
+
+/*------------------------------------------------------------------------
+ * +++ Default implementations for widget subcommands.
+ */
+
+/* $w cget -option
+ */
+int TtkWidgetCgetCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ WidgetCore *corePtr = recordPtr;
+ Tcl_Obj *result;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option");
+ return TCL_ERROR;
+ }
+ result = Tk_GetOptionValue(interp, recordPtr,
+ corePtr->optionTable, objv[2], corePtr->tkwin);
+ if (result == NULL)
+ return TCL_ERROR;
+ Tcl_SetObjResult(interp, result);
+ return TCL_OK;
+}
+
+/* $w configure ?-option ?value ....??
+ */
+int TtkWidgetConfigureCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ WidgetCore *corePtr = recordPtr;
+ Tcl_Obj *result;
+
+ if (objc == 2) {
+ result = Tk_GetOptionInfo(interp, recordPtr,
+ corePtr->optionTable, NULL, corePtr->tkwin);
+ } else if (objc == 3) {
+ result = Tk_GetOptionInfo(interp, recordPtr,
+ corePtr->optionTable, objv[2], corePtr->tkwin);
+ } else {
+ Tk_SavedOptions savedOptions;
+ int status;
+ int mask = 0;
+
+ status = Tk_SetOptions(interp, recordPtr,
+ corePtr->optionTable, objc - 2, objv + 2,
+ corePtr->tkwin, &savedOptions, &mask);
+ if (status != TCL_OK)
+ return status;
+
+ if (mask & READONLY_OPTION) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "attempt to change read-only option", -1));
+ Tk_RestoreSavedOptions(&savedOptions);
+ return TCL_ERROR;
+ }
+
+ status = corePtr->widgetSpec->configureProc(interp, recordPtr, mask);
+ if (status != TCL_OK) {
+ Tk_RestoreSavedOptions(&savedOptions);
+ return status;
+ }
+ Tk_FreeSavedOptions(&savedOptions);
+
+ status = corePtr->widgetSpec->postConfigureProc(interp,recordPtr,mask);
+ if (WidgetDestroyed(corePtr)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "widget has been destroyed", -1));
+ status = TCL_ERROR;
+ }
+ if (status != TCL_OK) {
+ return status;
+ }
+
+ if (mask & (STYLE_CHANGED | GEOMETRY_CHANGED)) {
+ SizeChanged(corePtr);
+ }
+
+ TtkRedisplayWidget(corePtr);
+ result = Tcl_NewObj();
+ }
+
+ if (result == 0) {
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, result);
+ return TCL_OK;
+}
+
+/* $w state ? $stateSpec ?
+ *
+ * If $stateSpec is specified, modify the widget state accordingly,
+ * return a new stateSpec representing the changed bits.
+ *
+ * Otherwise, return a statespec matching all the currently-set bits.
+ */
+
+int TtkWidgetStateCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ WidgetCore *corePtr = recordPtr;
+ Ttk_StateSpec spec;
+ int status;
+ Ttk_State oldState, changed;
+
+ if (objc == 2) {
+ Tcl_SetObjResult(interp,
+ Ttk_NewStateSpecObj(corePtr->state, 0ul));
+ return TCL_OK;
+ }
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "state-spec");
+ return TCL_ERROR;
+ }
+ status = Ttk_GetStateSpecFromObj(interp, objv[2], &spec);
+ if (status != TCL_OK)
+ return status;
+
+ oldState = corePtr->state;
+ corePtr->state = Ttk_ModifyState(corePtr->state, &spec);
+ changed = corePtr->state ^ oldState;
+
+ TtkRedisplayWidget(corePtr);
+
+ Tcl_SetObjResult(interp,
+ Ttk_NewStateSpecObj(oldState & changed, ~oldState & changed));
+ return status;
+}
+
+/* $w instate $stateSpec ?$script?
+ *
+ * Tests if widget state matches $stateSpec.
+ * If $script is specified, execute script if state matches.
+ * Otherwise, return true/false
+ */
+
+int TtkWidgetInstateCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ WidgetCore *corePtr = recordPtr;
+ Ttk_State state = corePtr->state;
+ Ttk_StateSpec spec;
+ int status = TCL_OK;
+
+ if (objc < 3 || objc > 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "state-spec ?script?");
+ return TCL_ERROR;
+ }
+ status = Ttk_GetStateSpecFromObj(interp, objv[2], &spec);
+ if (status != TCL_OK)
+ return status;
+
+ if (objc == 3) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewBooleanObj(Ttk_StateMatches(state,&spec)));
+ } else if (objc == 4) {
+ if (Ttk_StateMatches(state,&spec)) {
+ status = Tcl_EvalObjEx(interp, objv[3], 0);
+ }
+ }
+ return status;
+}
+
+/* $w identify $x $y
+ * $w identify element $x $y
+ * Returns: name of element at $x, $y
+ */
+int TtkWidgetIdentifyCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ WidgetCore *corePtr = recordPtr;
+ Ttk_Element element;
+ static const char *whatTable[] = { "element", NULL };
+ int x, y, what;
+
+ if (objc < 4 || objc > 5) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?what? x y");
+ return TCL_ERROR;
+ }
+ if (objc == 5) {
+ /* $w identify element $x $y */
+ if (Tcl_GetIndexFromObjStruct(interp, objv[2], whatTable,
+ sizeof(char *), "option", 0, &what) != TCL_OK)
+ {
+ return TCL_ERROR;
+ }
+ }
+
+ if ( Tcl_GetIntFromObj(interp, objv[objc-2], &x) != TCL_OK
+ || Tcl_GetIntFromObj(interp, objv[objc-1], &y) != TCL_OK
+ ) {
+ return TCL_ERROR;
+ }
+
+ element = Ttk_IdentifyElement(corePtr->layout, x, y);
+ if (element) {
+ const char *elementName = Ttk_ElementName(element);
+ Tcl_SetObjResult(interp,Tcl_NewStringObj(elementName,-1));
+ }
+
+ return TCL_OK;
+}
+
+/*EOF*/
diff --git a/tk8.6/generic/ttk/ttkWidget.h b/tk8.6/generic/ttk/ttkWidget.h
new file mode 100644
index 0000000..8a94bb7
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkWidget.h
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2003, Joe English
+ * Helper routines for widget implementations.
+ */
+
+#ifndef _TTKWIDGET
+#define _TTKWIDGET
+
+/*
+ * State flags for 'flags' field.
+ */
+#define WIDGET_DESTROYED 0x0001
+#define REDISPLAY_PENDING 0x0002 /* scheduled call to RedisplayWidget */
+#define CURSOR_ON 0x0020 /* See TtkBlinkCursor() */
+#define WIDGET_USER_FLAG 0x0100 /* 0x0100 - 0x8000 for user flags */
+
+/*
+ * Bit fields for OptionSpec 'mask' field:
+ */
+#define READONLY_OPTION 0x1
+#define STYLE_CHANGED 0x2
+#define GEOMETRY_CHANGED 0x4
+
+/*
+ * Core widget elements
+ */
+typedef struct WidgetSpec_ WidgetSpec; /* Forward */
+
+typedef struct
+{
+ Tk_Window tkwin; /* Window associated with widget */
+ Tcl_Interp *interp; /* Interpreter associated with widget. */
+ WidgetSpec *widgetSpec; /* Widget class hooks */
+ Tcl_Command widgetCmd; /* Token for widget command. */
+ Tk_OptionTable optionTable; /* Option table */
+ Ttk_Layout layout; /* Widget layout */
+
+ /*
+ * Storage for resources:
+ */
+ Tcl_Obj *takeFocusPtr; /* Storage for -takefocus option */
+ Tcl_Obj *cursorObj; /* Storage for -cursor option */
+ Tcl_Obj *styleObj; /* Name of currently-applied style */
+ Tcl_Obj *classObj; /* Class name (readonly option) */
+
+ Ttk_State state; /* Current widget state */
+ unsigned int flags; /* internal flags, see above */
+
+} WidgetCore;
+
+/*
+ * Widget specifications:
+ */
+struct WidgetSpec_
+{
+ const char *className; /* Widget class name */
+ size_t recordSize; /* #bytes in widget record */
+ const Tk_OptionSpec *optionSpecs; /* Option specifications */
+ const Ttk_Ensemble *commands; /* Widget instance subcommands */
+
+ /*
+ * Hooks:
+ */
+ void (*initializeProc)(Tcl_Interp *, void *recordPtr);
+ void (*cleanupProc)(void *recordPtr);
+ int (*configureProc)(Tcl_Interp *, void *recordPtr, int flags);
+ int (*postConfigureProc)(Tcl_Interp *, void *recordPtr, int flags);
+ Ttk_Layout (*getLayoutProc)(Tcl_Interp *,Ttk_Theme, void *recordPtr);
+ int (*sizeProc)(void *recordPtr, int *widthPtr, int *heightPtr);
+ void (*layoutProc)(void *recordPtr);
+ void (*displayProc)(void *recordPtr, Drawable d);
+};
+
+/*
+ * Common factors for widget implementations:
+ */
+MODULE_SCOPE void TtkNullInitialize(Tcl_Interp *, void *);
+MODULE_SCOPE int TtkNullPostConfigure(Tcl_Interp *, void *, int);
+MODULE_SCOPE void TtkNullCleanup(void *recordPtr);
+MODULE_SCOPE Ttk_Layout TtkWidgetGetLayout(
+ Tcl_Interp *, Ttk_Theme, void *recordPtr);
+MODULE_SCOPE Ttk_Layout TtkWidgetGetOrientedLayout(
+ Tcl_Interp *, Ttk_Theme, void *recordPtr, Tcl_Obj *orientObj);
+MODULE_SCOPE int TtkWidgetSize(void *recordPtr, int *w, int *h);
+MODULE_SCOPE void TtkWidgetDoLayout(void *recordPtr);
+MODULE_SCOPE void TtkWidgetDisplay(void *recordPtr, Drawable);
+
+MODULE_SCOPE int TtkCoreConfigure(Tcl_Interp*, void *, int mask);
+
+/* Common widget commands:
+ */
+MODULE_SCOPE int TtkWidgetConfigureCommand(
+ void *,Tcl_Interp *, int, Tcl_Obj*const[]);
+MODULE_SCOPE int TtkWidgetCgetCommand(
+ void *,Tcl_Interp *, int, Tcl_Obj*const[]);
+MODULE_SCOPE int TtkWidgetInstateCommand(
+ void *,Tcl_Interp *, int, Tcl_Obj*const[]);
+MODULE_SCOPE int TtkWidgetStateCommand(
+ void *,Tcl_Interp *, int, Tcl_Obj*const[]);
+MODULE_SCOPE int TtkWidgetIdentifyCommand(
+ void *,Tcl_Interp *, int, Tcl_Obj*const[]);
+
+/* Widget constructor:
+ */
+MODULE_SCOPE int TtkWidgetConstructorObjCmd(
+ ClientData, Tcl_Interp*, int, Tcl_Obj*const[]);
+
+#define RegisterWidget(interp, name, specPtr) \
+ Tcl_CreateObjCommand(interp, name, \
+ TtkWidgetConstructorObjCmd, (ClientData)specPtr,NULL)
+
+/* WIDGET_TAKEFOCUS_TRUE --
+ * WIDGET_TAKEFOCUS_FALSE --
+ * Add one or the other of these to each OptionSpecs table
+ * to indicate whether the widget should take focus
+ * during keyboard traversal.
+ */
+#define WIDGET_TAKEFOCUS_TRUE \
+ {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", \
+ "ttk::takefocus", Tk_Offset(WidgetCore, takeFocusPtr), -1, 0,0,0 }
+#define WIDGET_TAKEFOCUS_FALSE \
+ {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", \
+ "", Tk_Offset(WidgetCore, takeFocusPtr), -1, 0,0,0 }
+
+/* WIDGET_INHERIT_OPTIONS(baseOptionSpecs) --
+ * Add this at the end of an OptionSpecs table to inherit
+ * the options from 'baseOptionSpecs'.
+ */
+#define WIDGET_INHERIT_OPTIONS(baseOptionSpecs) \
+ {TK_OPTION_END, 0,0,0, NULL, -1,-1, 0, (ClientData)baseOptionSpecs, 0}
+
+/* All widgets should inherit from ttkCoreOptionSpecs[].
+ */
+MODULE_SCOPE Tk_OptionSpec ttkCoreOptionSpecs[];
+
+/*
+ * Useful routines for use inside widget implementations:
+ */
+/* extern int WidgetDestroyed(WidgetCore *); */
+#define WidgetDestroyed(corePtr) ((corePtr)->flags & WIDGET_DESTROYED)
+
+MODULE_SCOPE void TtkWidgetChangeState(WidgetCore *,
+ unsigned int setBits, unsigned int clearBits);
+
+MODULE_SCOPE void TtkRedisplayWidget(WidgetCore *);
+MODULE_SCOPE void TtkResizeWidget(WidgetCore *);
+
+MODULE_SCOPE void TtkTrackElementState(WidgetCore *);
+MODULE_SCOPE void TtkBlinkCursor(WidgetCore *);
+
+/*
+ * -state option values (compatibility)
+ */
+MODULE_SCOPE void TtkCheckStateOption(WidgetCore *, Tcl_Obj *);
+
+/*
+ * Variable traces:
+ */
+typedef void (*Ttk_TraceProc)(void *recordPtr, const char *value);
+typedef struct TtkTraceHandle_ Ttk_TraceHandle;
+
+MODULE_SCOPE Ttk_TraceHandle *Ttk_TraceVariable(
+ Tcl_Interp*, Tcl_Obj *varnameObj, Ttk_TraceProc callback, void *clientData);
+MODULE_SCOPE void Ttk_UntraceVariable(Ttk_TraceHandle *);
+MODULE_SCOPE int Ttk_FireTrace(Ttk_TraceHandle *);
+
+/*
+ * Virtual events:
+ */
+MODULE_SCOPE void TtkSendVirtualEvent(Tk_Window tgtWin, const char *eventName);
+
+/*
+ * Helper routines for data accessor commands:
+ */
+MODULE_SCOPE int TtkEnumerateOptions(
+ Tcl_Interp *, void *, const Tk_OptionSpec *, Tk_OptionTable, Tk_Window);
+MODULE_SCOPE int TtkGetOptionValue(
+ Tcl_Interp *, void *, Tcl_Obj *optName, Tk_OptionTable, Tk_Window);
+
+/*
+ * Helper routines for scrolling widgets (see scroll.c).
+ */
+typedef struct {
+ int first; /* First visible item */
+ int last; /* Last visible item */
+ int total; /* Total #items */
+ char *scrollCmd; /* Widget option */
+} Scrollable;
+
+typedef struct ScrollHandleRec *ScrollHandle;
+
+MODULE_SCOPE ScrollHandle TtkCreateScrollHandle(WidgetCore *, Scrollable *);
+MODULE_SCOPE void TtkFreeScrollHandle(ScrollHandle);
+
+MODULE_SCOPE int TtkScrollviewCommand(
+ Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], ScrollHandle);
+
+MODULE_SCOPE void TtkUpdateScrollInfo(ScrollHandle h);
+MODULE_SCOPE void TtkScrollTo(ScrollHandle, int newFirst, int updateScrollInfo);
+MODULE_SCOPE void TtkScrolled(ScrollHandle, int first, int last, int total);
+MODULE_SCOPE void TtkScrollbarUpdateRequired(ScrollHandle);
+
+/*
+ * Tag sets (work in progress, half-baked)
+ */
+
+typedef struct TtkTag *Ttk_Tag;
+typedef struct TtkTagTable *Ttk_TagTable;
+typedef struct TtkTagSet { /* TODO: make opaque */
+ Ttk_Tag *tags;
+ int nTags;
+} *Ttk_TagSet;
+
+MODULE_SCOPE Ttk_TagTable Ttk_CreateTagTable(
+ Tcl_Interp *, Tk_Window tkwin, Tk_OptionSpec[], int recordSize);
+MODULE_SCOPE void Ttk_DeleteTagTable(Ttk_TagTable);
+
+MODULE_SCOPE Ttk_Tag Ttk_GetTag(Ttk_TagTable, const char *tagName);
+MODULE_SCOPE Ttk_Tag Ttk_GetTagFromObj(Ttk_TagTable, Tcl_Obj *);
+
+MODULE_SCOPE Tcl_Obj *Ttk_TagOptionValue(
+ Tcl_Interp *, Ttk_TagTable, Ttk_Tag, Tcl_Obj *optionName);
+
+MODULE_SCOPE int Ttk_EnumerateTagOptions(
+ Tcl_Interp *, Ttk_TagTable, Ttk_Tag);
+
+MODULE_SCOPE int Ttk_EnumerateTags(Tcl_Interp *, Ttk_TagTable);
+
+MODULE_SCOPE int Ttk_ConfigureTag(
+ Tcl_Interp *interp, Ttk_TagTable tagTable, Ttk_Tag tag,
+ int objc, Tcl_Obj *const objv[]);
+
+MODULE_SCOPE Ttk_TagSet Ttk_GetTagSetFromObj(
+ Tcl_Interp *interp, Ttk_TagTable, Tcl_Obj *objPtr);
+MODULE_SCOPE Tcl_Obj *Ttk_NewTagSetObj(Ttk_TagSet);
+
+MODULE_SCOPE void Ttk_FreeTagSet(Ttk_TagSet);
+
+MODULE_SCOPE int Ttk_TagSetContains(Ttk_TagSet, Ttk_Tag tag);
+MODULE_SCOPE int Ttk_TagSetAdd(Ttk_TagSet, Ttk_Tag tag);
+MODULE_SCOPE int Ttk_TagSetRemove(Ttk_TagSet, Ttk_Tag tag);
+
+MODULE_SCOPE void Ttk_TagSetValues(Ttk_TagTable, Ttk_TagSet, void *record);
+MODULE_SCOPE void Ttk_TagSetApplyStyle(Ttk_TagTable,Ttk_Style,Ttk_State,void*);
+
+/*
+ * String tables for widget resource specifications:
+ */
+
+MODULE_SCOPE const char *ttkOrientStrings[];
+MODULE_SCOPE const char *ttkCompoundStrings[];
+MODULE_SCOPE const char *ttkDefaultStrings[];
+
+/*
+ * ... other option types...
+ */
+MODULE_SCOPE int TtkGetLabelAnchorFromObj(
+ Tcl_Interp*, Tcl_Obj*, Ttk_PositionSpec *);
+
+/*
+ * Platform-specific initialization.
+ */
+
+#ifdef _WIN32
+#define Ttk_PlatformInit Ttk_WinPlatformInit
+MODULE_SCOPE int Ttk_PlatformInit(Tcl_Interp *);
+#elif defined(MAC_OSX_TK)
+#define Ttk_PlatformInit Ttk_MacOSXPlatformInit
+MODULE_SCOPE int Ttk_PlatformInit(Tcl_Interp *);
+#else
+#define Ttk_PlatformInit(interp) /* TTK_X11PlatformInit() */
+#endif
+
+#endif /* _TTKWIDGET */
diff --git a/tk8.6/library/bgerror.tcl b/tk8.6/library/bgerror.tcl
new file mode 100644
index 0000000..574ad8b
--- /dev/null
+++ b/tk8.6/library/bgerror.tcl
@@ -0,0 +1,270 @@
+# bgerror.tcl --
+#
+# Implementation of the bgerror procedure. It posts a dialog box with
+# the error message and gives the user a chance to see a more detailed
+# stack trace, and possible do something more interesting with that
+# trace (like save it to a log). This is adapted from work done by
+# Donal K. Fellows.
+#
+# Copyright (c) 1998-2000 by Ajuba Solutions.
+# Copyright (c) 2007 by ActiveState Software Inc.
+# Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
+# Copyright (c) 2009 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+namespace eval ::tk::dialog::error {
+ namespace import -force ::tk::msgcat::*
+ namespace export bgerror
+ option add *ErrorDialog.function.text [mc "Save To Log"] \
+ widgetDefault
+ option add *ErrorDialog.function.command [namespace code SaveToLog]
+ option add *ErrorDialog*Label.font TkCaptionFont widgetDefault
+ if {[tk windowingsystem] eq "aqua"} {
+ option add *ErrorDialog*background systemAlertBackgroundActive \
+ widgetDefault
+ option add *ErrorDialog*info.text.background white widgetDefault
+ option add *ErrorDialog*Button.highlightBackground \
+ systemAlertBackgroundActive widgetDefault
+ }
+}
+
+proc ::tk::dialog::error::Return {which code} {
+ variable button
+
+ .bgerrorDialog.$which state {active selected focus}
+ update idletasks
+ after 100
+ set button $code
+}
+
+proc ::tk::dialog::error::Details {} {
+ set w .bgerrorDialog
+ set caption [option get $w.function text {}]
+ set command [option get $w.function command {}]
+ if { ($caption eq "") || ($command eq "") } {
+ grid forget $w.function
+ }
+ lappend command [$w.top.info.text get 1.0 end-1c]
+ $w.function configure -text $caption -command $command
+ grid $w.top.info - -sticky nsew -padx 3m -pady 3m
+}
+
+proc ::tk::dialog::error::SaveToLog {text} {
+ if { $::tcl_platform(platform) eq "windows" } {
+ set allFiles *.*
+ } else {
+ set allFiles *
+ }
+ set types [list \
+ [list [mc "Log Files"] .log] \
+ [list [mc "Text Files"] .txt] \
+ [list [mc "All Files"] $allFiles] \
+ ]
+ set filename [tk_getSaveFile -title [mc "Select Log File"] \
+ -filetypes $types -defaultextension .log -parent .bgerrorDialog]
+ if {$filename ne {}} {
+ set f [open $filename w]
+ puts -nonewline $f $text
+ close $f
+ }
+ return
+}
+
+proc ::tk::dialog::error::Destroy {w} {
+ if {$w eq ".bgerrorDialog"} {
+ variable button
+ set button -1
+ }
+}
+
+proc ::tk::dialog::error::DeleteByProtocol {} {
+ variable button
+ set button 1
+}
+
+proc ::tk::dialog::error::ReturnInDetails w {
+ bind $w <Return> {}; # Remove this binding
+ $w invoke
+ return -code break
+}
+
+# ::tk::dialog::error::bgerror --
+#
+# This is the default version of bgerror.
+# It tries to execute tkerror, if that fails it posts a dialog box
+# containing the error message and gives the user a chance to ask
+# to see a stack trace.
+#
+# Arguments:
+# err - The error message.
+#
+proc ::tk::dialog::error::bgerror {err {flag 1}} {
+ global errorInfo
+ variable button
+
+ set info $errorInfo
+
+ set ret [catch {::tkerror $err} msg];
+ if {$ret != 1} {return -code $ret $msg}
+
+ # The application's tkerror either failed or was not found
+ # so we use the default dialog. But on Aqua we cannot display
+ # the dialog if the background error occurs in an idle task
+ # being processed inside of [NSView drawRect]. In that case
+ # we post the dialog as an after task instead.
+ set windowingsystem [tk windowingsystem]
+ if {$windowingsystem eq "aqua"} {
+ if $flag {
+ after 500 [list bgerror "$err" 0]
+ return
+ }
+ }
+
+ set ok [mc OK]
+ # Truncate the message if it is too wide (>maxLine characters) or
+ # too tall (>4 lines). Truncation occurs at the first point at
+ # which one of those conditions is met.
+ set displayedErr ""
+ set lines 0
+ set maxLine 45
+ foreach line [split $err \n] {
+ if { [string length $line] > $maxLine } {
+ append displayedErr "[string range $line 0 [expr {$maxLine-3}]]..."
+ break
+ }
+ if { $lines > 4 } {
+ append displayedErr "..."
+ break
+ } else {
+ append displayedErr "${line}\n"
+ }
+ incr lines
+ }
+
+ set title [mc "Application Error"]
+ set text [mc "Error: %1\$s" $displayedErr]
+ set buttons [list ok $ok dismiss [mc "Skip Messages"] \
+ function [mc "Details >>"]]
+
+ # 1. Create the top-level window and divide it into top
+ # and bottom parts.
+
+ set dlg .bgerrorDialog
+ set bg [ttk::style lookup . -background]
+ destroy $dlg
+ toplevel $dlg -class ErrorDialog -background $bg
+ wm withdraw $dlg
+ wm title $dlg $title
+ wm iconname $dlg ErrorDialog
+ wm protocol $dlg WM_DELETE_WINDOW [namespace code DeleteByProtocol]
+
+ if {$windowingsystem eq "aqua"} {
+ ::tk::unsupported::MacWindowStyle style $dlg moveableAlert {}
+ } elseif {$windowingsystem eq "x11"} {
+ wm attributes $dlg -type dialog
+ }
+
+ ttk::frame $dlg.bot
+ ttk::frame $dlg.top
+ pack $dlg.bot -side bottom -fill both
+ pack $dlg.top -side top -fill both -expand 1
+
+ set W [ttk::frame $dlg.top.info]
+ text $W.text -setgrid true -height 10 -wrap char \
+ -yscrollcommand [list $W.scroll set]
+ if {$windowingsystem ne "aqua"} {
+ $W.text configure -width 40
+ }
+
+ ttk::scrollbar $W.scroll -command [list $W.text yview]
+ pack $W.scroll -side right -fill y
+ pack $W.text -side left -expand yes -fill both
+ $W.text insert 0.0 "$err\n$info"
+ $W.text mark set insert 0.0
+ bind $W.text <ButtonPress-1> { focus %W }
+ $W.text configure -state disabled
+
+ # 2. Fill the top part with bitmap and message
+
+ # Max-width of message is the width of the screen...
+ set wrapwidth [winfo screenwidth $dlg]
+ # ...minus the width of the icon, padding and a fudge factor for
+ # the window manager decorations and aesthetics.
+ set wrapwidth [expr {$wrapwidth-60-[winfo pixels $dlg 9m]}]
+ ttk::label $dlg.msg -justify left -text $text -wraplength $wrapwidth
+ ttk::label $dlg.bitmap -image ::tk::icons::error
+
+ grid $dlg.bitmap $dlg.msg -in $dlg.top -row 0 -padx 3m -pady 3m
+ grid configure $dlg.bitmap -sticky ne
+ grid configure $dlg.msg -sticky nsw -padx {0 3m}
+ grid rowconfigure $dlg.top 1 -weight 1
+ grid columnconfigure $dlg.top 1 -weight 1
+
+ # 3. Create a row of buttons at the bottom of the dialog.
+
+ set i 0
+ foreach {name caption} $buttons {
+ ttk::button $dlg.$name -text $caption -default normal \
+ -command [namespace code [list set button $i]]
+ grid $dlg.$name -in $dlg.bot -column $i -row 0 -sticky ew -padx 10
+ grid columnconfigure $dlg.bot $i -weight 1
+ # We boost the size of some Mac buttons for l&f
+ if {$windowingsystem eq "aqua"} {
+ if {($name eq "ok") || ($name eq "dismiss")} {
+ grid columnconfigure $dlg.bot $i -minsize 90
+ }
+ grid configure $dlg.$name -pady 7
+ }
+ incr i
+ }
+ # The "OK" button is the default for this dialog.
+ $dlg.ok configure -default active
+
+ bind $dlg <Return> [namespace code {Return ok 0}]
+ bind $dlg <Escape> [namespace code {Return dismiss 1}]
+ bind $dlg <Destroy> [namespace code {Destroy %W}]
+ bind $dlg.function <Return> [namespace code {ReturnInDetails %W}]
+ $dlg.function configure -command [namespace code Details]
+
+ # 6. Withdraw the window, then update all the geometry information
+ # so we know how big it wants to be, then center the window in the
+ # display (Motif style) and de-iconify it.
+
+ ::tk::PlaceWindow $dlg
+
+ # 7. Set a grab and claim the focus too.
+
+ ::tk::SetFocusGrab $dlg $dlg.ok
+
+ # 8. Ensure that we are topmost.
+
+ raise $dlg
+ if {[tk windowingsystem] eq "win32"} {
+ # Place it topmost if we aren't at the top of the stacking
+ # order to ensure that it's seen
+ if {[lindex [wm stackorder .] end] ne "$dlg"} {
+ wm attributes $dlg -topmost 1
+ }
+ }
+
+ # 9. Wait for the user to respond, then restore the focus and
+ # return the index of the selected button. Restore the focus
+ # before deleting the window, since otherwise the window manager
+ # may take the focus away so we can't redirect it. Finally,
+ # restore any grab that was in effect.
+
+ vwait [namespace which -variable button]
+ set copy $button; # Save a copy...
+
+ ::tk::RestoreFocusGrab $dlg $dlg.ok destroy
+
+ if {$copy == 1} {
+ return -code break
+ }
+}
+
+namespace eval :: {
+ # Fool the indexer
+ proc bgerror err {}
+ rename bgerror {}
+ namespace import ::tk::dialog::error::bgerror
+}
diff --git a/tk8.6/library/button.tcl b/tk8.6/library/button.tcl
new file mode 100644
index 0000000..9b13607
--- /dev/null
+++ b/tk8.6/library/button.tcl
@@ -0,0 +1,782 @@
+# button.tcl --
+#
+# This file defines the default bindings for Tk label, button,
+# checkbutton, and radiobutton widgets and provides procedures
+# that help in implementing those bindings.
+#
+# Copyright (c) 1992-1994 The Regents of the University of California.
+# Copyright (c) 1994-1996 Sun Microsystems, Inc.
+# Copyright (c) 2002 ActiveState Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+
+#-------------------------------------------------------------------------
+# The code below creates the default class bindings for buttons.
+#-------------------------------------------------------------------------
+
+if {[tk windowingsystem] eq "aqua"} {
+
+ bind Radiobutton <Enter> {
+ tk::ButtonEnter %W
+ }
+ bind Radiobutton <1> {
+ tk::ButtonDown %W
+ }
+ bind Radiobutton <ButtonRelease-1> {
+ tk::ButtonUp %W
+ }
+ bind Checkbutton <Enter> {
+ tk::ButtonEnter %W
+ }
+ bind Checkbutton <1> {
+ tk::ButtonDown %W
+ }
+ bind Checkbutton <ButtonRelease-1> {
+ tk::ButtonUp %W
+ }
+ bind Checkbutton <Leave> {
+ tk::ButtonLeave %W
+ }
+}
+if {"win32" eq [tk windowingsystem]} {
+ bind Checkbutton <equal> {
+ tk::CheckRadioInvoke %W select
+ }
+ bind Checkbutton <plus> {
+ tk::CheckRadioInvoke %W select
+ }
+ bind Checkbutton <minus> {
+ tk::CheckRadioInvoke %W deselect
+ }
+ bind Checkbutton <1> {
+ tk::CheckRadioDown %W
+ }
+ bind Checkbutton <ButtonRelease-1> {
+ tk::ButtonUp %W
+ }
+ bind Checkbutton <Enter> {
+ tk::CheckRadioEnter %W
+ }
+ bind Checkbutton <Leave> {
+ tk::ButtonLeave %W
+ }
+
+ bind Radiobutton <1> {
+ tk::CheckRadioDown %W
+ }
+ bind Radiobutton <ButtonRelease-1> {
+ tk::ButtonUp %W
+ }
+ bind Radiobutton <Enter> {
+ tk::CheckRadioEnter %W
+ }
+}
+if {"x11" eq [tk windowingsystem]} {
+ bind Checkbutton <Return> {
+ if {!$tk_strictMotif} {
+ tk::CheckInvoke %W
+ }
+ }
+ bind Radiobutton <Return> {
+ if {!$tk_strictMotif} {
+ tk::CheckRadioInvoke %W
+ }
+ }
+ bind Checkbutton <1> {
+ tk::CheckInvoke %W
+ }
+ bind Radiobutton <1> {
+ tk::CheckRadioInvoke %W
+ }
+ bind Checkbutton <Enter> {
+ tk::CheckEnter %W
+ }
+ bind Radiobutton <Enter> {
+ tk::ButtonEnter %W
+ }
+ bind Checkbutton <Leave> {
+ tk::CheckLeave %W
+ }
+}
+
+bind Button <space> {
+ tk::ButtonInvoke %W
+}
+bind Checkbutton <space> {
+ tk::CheckRadioInvoke %W
+}
+bind Radiobutton <space> {
+ tk::CheckRadioInvoke %W
+}
+bind Button <<Invoke>> {
+ tk::ButtonInvoke %W
+}
+bind Checkbutton <<Invoke>> {
+ tk::CheckRadioInvoke %W
+}
+bind Radiobutton <<Invoke>> {
+ tk::CheckRadioInvoke %W
+}
+
+bind Button <FocusIn> {}
+bind Button <Enter> {
+ tk::ButtonEnter %W
+}
+bind Button <Leave> {
+ tk::ButtonLeave %W
+}
+bind Button <1> {
+ tk::ButtonDown %W
+}
+bind Button <ButtonRelease-1> {
+ tk::ButtonUp %W
+}
+
+bind Checkbutton <FocusIn> {}
+
+bind Radiobutton <FocusIn> {}
+bind Radiobutton <Leave> {
+ tk::ButtonLeave %W
+}
+
+if {"win32" eq [tk windowingsystem]} {
+
+#########################
+# Windows implementation
+#########################
+
+# ::tk::ButtonEnter --
+# The procedure below is invoked when the mouse pointer enters a
+# button widget. It records the button we're in and changes the
+# state of the button to active unless the button is disabled.
+#
+# Arguments:
+# w - The name of the widget.
+
+proc ::tk::ButtonEnter w {
+ variable ::tk::Priv
+ if {[$w cget -state] ne "disabled"} {
+
+ # If the mouse button is down, set the relief to sunken on entry.
+ # Overwise, if there's an -overrelief value, set the relief to that.
+
+ set Priv($w,relief) [$w cget -relief]
+ if {$Priv(buttonWindow) eq $w} {
+ $w configure -relief sunken -state active
+ set Priv($w,prelief) sunken
+ } elseif {[set over [$w cget -overrelief]] ne ""} {
+ $w configure -relief $over
+ set Priv($w,prelief) $over
+ }
+ }
+ set Priv(window) $w
+}
+
+# ::tk::ButtonLeave --
+# The procedure below is invoked when the mouse pointer leaves a
+# button widget. It changes the state of the button back to inactive.
+# Restore any modified relief too.
+#
+# Arguments:
+# w - The name of the widget.
+
+proc ::tk::ButtonLeave w {
+ variable ::tk::Priv
+ if {[$w cget -state] ne "disabled"} {
+ $w configure -state normal
+ }
+
+ # Restore the original button relief if it was changed by Tk.
+ # That is signaled by the existence of Priv($w,prelief).
+
+ if {[info exists Priv($w,relief)]} {
+ if {[info exists Priv($w,prelief)] && \
+ $Priv($w,prelief) eq [$w cget -relief]} {
+ $w configure -relief $Priv($w,relief)
+ }
+ unset -nocomplain Priv($w,relief) Priv($w,prelief)
+ }
+
+ set Priv(window) ""
+}
+
+# ::tk::ButtonDown --
+# The procedure below is invoked when the mouse button is pressed in
+# a button widget. It records the fact that the mouse is in the button,
+# saves the button's relief so it can be restored later, and changes
+# the relief to sunken.
+#
+# Arguments:
+# w - The name of the widget.
+
+proc ::tk::ButtonDown w {
+ variable ::tk::Priv
+
+ # Only save the button's relief if it does not yet exist. If there
+ # is an overrelief setting, Priv($w,relief) will already have been set,
+ # and the current value of the -relief option will be incorrect.
+
+ if {![info exists Priv($w,relief)]} {
+ set Priv($w,relief) [$w cget -relief]
+ }
+
+ if {[$w cget -state] ne "disabled"} {
+ set Priv(buttonWindow) $w
+ $w configure -relief sunken -state active
+ set Priv($w,prelief) sunken
+
+ # If this button has a repeatdelay set up, get it going with an after
+ after cancel $Priv(afterId)
+ set delay [$w cget -repeatdelay]
+ set Priv(repeated) 0
+ if {$delay > 0} {
+ set Priv(afterId) [after $delay [list tk::ButtonAutoInvoke $w]]
+ }
+ }
+}
+
+# ::tk::ButtonUp --
+# The procedure below is invoked when the mouse button is released
+# in a button widget. It restores the button's relief and invokes
+# the command as long as the mouse hasn't left the button.
+#
+# Arguments:
+# w - The name of the widget.
+
+proc ::tk::ButtonUp w {
+ variable ::tk::Priv
+ if {$Priv(buttonWindow) eq $w} {
+ set Priv(buttonWindow) ""
+
+ # Restore the button's relief if it was cached.
+
+ if {[info exists Priv($w,relief)]} {
+ if {[info exists Priv($w,prelief)] && \
+ $Priv($w,prelief) eq [$w cget -relief]} {
+ $w configure -relief $Priv($w,relief)
+ }
+ unset -nocomplain Priv($w,relief) Priv($w,prelief)
+ }
+
+ # Clean up the after event from the auto-repeater
+ after cancel $Priv(afterId)
+
+ if {$Priv(window) eq $w && [$w cget -state] ne "disabled"} {
+ $w configure -state normal
+
+ # Only invoke the command if it wasn't already invoked by the
+ # auto-repeater functionality
+ if { $Priv(repeated) == 0 } {
+ uplevel #0 [list $w invoke]
+ }
+ }
+ }
+}
+
+# ::tk::CheckRadioEnter --
+# The procedure below is invoked when the mouse pointer enters a
+# checkbutton or radiobutton widget. It records the button we're in
+# and changes the state of the button to active unless the button is
+# disabled.
+#
+# Arguments:
+# w - The name of the widget.
+
+proc ::tk::CheckRadioEnter w {
+ variable ::tk::Priv
+ if {[$w cget -state] ne "disabled"} {
+ if {$Priv(buttonWindow) eq $w} {
+ $w configure -state active
+ }
+ if {[set over [$w cget -overrelief]] ne ""} {
+ set Priv($w,relief) [$w cget -relief]
+ set Priv($w,prelief) $over
+ $w configure -relief $over
+ }
+ }
+ set Priv(window) $w
+}
+
+# ::tk::CheckRadioDown --
+# The procedure below is invoked when the mouse button is pressed in
+# a button widget. It records the fact that the mouse is in the button,
+# saves the button's relief so it can be restored later, and changes
+# the relief to sunken.
+#
+# Arguments:
+# w - The name of the widget.
+
+proc ::tk::CheckRadioDown w {
+ variable ::tk::Priv
+ if {![info exists Priv($w,relief)]} {
+ set Priv($w,relief) [$w cget -relief]
+ }
+ if {[$w cget -state] ne "disabled"} {
+ set Priv(buttonWindow) $w
+ set Priv(repeated) 0
+ $w configure -state active
+ }
+}
+
+}
+
+if {"x11" eq [tk windowingsystem]} {
+
+#####################
+# Unix implementation
+#####################
+
+# ::tk::ButtonEnter --
+# The procedure below is invoked when the mouse pointer enters a
+# button widget. It records the button we're in and changes the
+# state of the button to active unless the button is disabled.
+#
+# Arguments:
+# w - The name of the widget.
+
+proc ::tk::ButtonEnter {w} {
+ variable ::tk::Priv
+ if {[$w cget -state] ne "disabled"} {
+ # On unix the state is active just with mouse-over
+ $w configure -state active
+
+ # If the mouse button is down, set the relief to sunken on entry.
+ # Overwise, if there's an -overrelief value, set the relief to that.
+
+ set Priv($w,relief) [$w cget -relief]
+ if {$Priv(buttonWindow) eq $w} {
+ $w configure -relief sunken
+ set Priv($w,prelief) sunken
+ } elseif {[set over [$w cget -overrelief]] ne ""} {
+ $w configure -relief $over
+ set Priv($w,prelief) $over
+ }
+ }
+ set Priv(window) $w
+}
+
+# ::tk::ButtonLeave --
+# The procedure below is invoked when the mouse pointer leaves a
+# button widget. It changes the state of the button back to inactive.
+# Restore any modified relief too.
+#
+# Arguments:
+# w - The name of the widget.
+
+proc ::tk::ButtonLeave w {
+ variable ::tk::Priv
+ if {[$w cget -state] ne "disabled"} {
+ $w configure -state normal
+ }
+
+ # Restore the original button relief if it was changed by Tk.
+ # That is signaled by the existence of Priv($w,prelief).
+
+ if {[info exists Priv($w,relief)]} {
+ if {[info exists Priv($w,prelief)] && \
+ $Priv($w,prelief) eq [$w cget -relief]} {
+ $w configure -relief $Priv($w,relief)
+ }
+ unset -nocomplain Priv($w,relief) Priv($w,prelief)
+ }
+
+ set Priv(window) ""
+}
+
+# ::tk::ButtonDown --
+# The procedure below is invoked when the mouse button is pressed in
+# a button widget. It records the fact that the mouse is in the button,
+# saves the button's relief so it can be restored later, and changes
+# the relief to sunken.
+#
+# Arguments:
+# w - The name of the widget.
+
+proc ::tk::ButtonDown w {
+ variable ::tk::Priv
+
+ # Only save the button's relief if it does not yet exist. If there
+ # is an overrelief setting, Priv($w,relief) will already have been set,
+ # and the current value of the -relief option will be incorrect.
+
+ if {![info exists Priv($w,relief)]} {
+ set Priv($w,relief) [$w cget -relief]
+ }
+
+ if {[$w cget -state] ne "disabled"} {
+ set Priv(buttonWindow) $w
+ $w configure -relief sunken
+ set Priv($w,prelief) sunken
+
+ # If this button has a repeatdelay set up, get it going with an after
+ after cancel $Priv(afterId)
+ set delay [$w cget -repeatdelay]
+ set Priv(repeated) 0
+ if {$delay > 0} {
+ set Priv(afterId) [after $delay [list tk::ButtonAutoInvoke $w]]
+ }
+ }
+}
+
+# ::tk::ButtonUp --
+# The procedure below is invoked when the mouse button is released
+# in a button widget. It restores the button's relief and invokes
+# the command as long as the mouse hasn't left the button.
+#
+# Arguments:
+# w - The name of the widget.
+
+proc ::tk::ButtonUp w {
+ variable ::tk::Priv
+ if {$w eq $Priv(buttonWindow)} {
+ set Priv(buttonWindow) ""
+
+ # Restore the button's relief if it was cached.
+
+ if {[info exists Priv($w,relief)]} {
+ if {[info exists Priv($w,prelief)] && \
+ $Priv($w,prelief) eq [$w cget -relief]} {
+ $w configure -relief $Priv($w,relief)
+ }
+ unset -nocomplain Priv($w,relief) Priv($w,prelief)
+ }
+
+ # Clean up the after event from the auto-repeater
+ after cancel $Priv(afterId)
+
+ if {$Priv(window) eq $w && [$w cget -state] ne "disabled"} {
+ # Only invoke the command if it wasn't already invoked by the
+ # auto-repeater functionality
+ if { $Priv(repeated) == 0 } {
+ uplevel #0 [list $w invoke]
+ }
+ }
+ }
+}
+
+}
+
+if {[tk windowingsystem] eq "aqua"} {
+
+####################
+# Mac implementation
+####################
+
+# ::tk::ButtonEnter --
+# The procedure below is invoked when the mouse pointer enters a
+# button widget. It records the button we're in and changes the
+# state of the button to active unless the button is disabled.
+#
+# Arguments:
+# w - The name of the widget.
+
+proc ::tk::ButtonEnter {w} {
+ variable ::tk::Priv
+ if {[$w cget -state] ne "disabled"} {
+
+ # If there's an -overrelief value, set the relief to that.
+
+ if {$Priv(buttonWindow) eq $w} {
+ $w configure -state active
+ } elseif {[set over [$w cget -overrelief]] ne ""} {
+ set Priv($w,relief) [$w cget -relief]
+ set Priv($w,prelief) $over
+ $w configure -relief $over
+ }
+ }
+ set Priv(window) $w
+}
+
+# ::tk::ButtonLeave --
+# The procedure below is invoked when the mouse pointer leaves a
+# button widget. It changes the state of the button back to
+# inactive. If we're leaving the button window with a mouse button
+# pressed (Priv(buttonWindow) == $w), restore the relief of the
+# button too.
+#
+# Arguments:
+# w - The name of the widget.
+
+proc ::tk::ButtonLeave w {
+ variable ::tk::Priv
+ if {$w eq $Priv(buttonWindow)} {
+ $w configure -state normal
+ }
+
+ # Restore the original button relief if it was changed by Tk.
+ # That is signaled by the existence of Priv($w,prelief).
+
+ if {[info exists Priv($w,relief)]} {
+ if {[info exists Priv($w,prelief)] && \
+ $Priv($w,prelief) eq [$w cget -relief]} {
+ $w configure -relief $Priv($w,relief)
+ }
+ unset -nocomplain Priv($w,relief) Priv($w,prelief)
+ }
+
+ set Priv(window) ""
+}
+
+# ::tk::ButtonDown --
+# The procedure below is invoked when the mouse button is pressed in
+# a button widget. It records the fact that the mouse is in the button,
+# saves the button's relief so it can be restored later, and changes
+# the relief to sunken.
+#
+# Arguments:
+# w - The name of the widget.
+
+proc ::tk::ButtonDown w {
+ variable ::tk::Priv
+
+ if {[$w cget -state] ne "disabled"} {
+ set Priv(buttonWindow) $w
+ $w configure -state active
+
+ # If this button has a repeatdelay set up, get it going with an after
+ after cancel $Priv(afterId)
+ set Priv(repeated) 0
+ if { ![catch {$w cget -repeatdelay} delay] } {
+ if {$delay > 0} {
+ set Priv(afterId) [after $delay [list tk::ButtonAutoInvoke $w]]
+ }
+ }
+ }
+}
+
+# ::tk::ButtonUp --
+# The procedure below is invoked when the mouse button is released
+# in a button widget. It restores the button's relief and invokes
+# the command as long as the mouse hasn't left the button.
+#
+# Arguments:
+# w - The name of the widget.
+
+proc ::tk::ButtonUp w {
+ variable ::tk::Priv
+ if {$Priv(buttonWindow) eq $w} {
+ set Priv(buttonWindow) ""
+ $w configure -state normal
+
+ # Restore the button's relief if it was cached.
+
+ if {[info exists Priv($w,relief)]} {
+ if {[info exists Priv($w,prelief)] && \
+ $Priv($w,prelief) eq [$w cget -relief]} {
+ $w configure -relief $Priv($w,relief)
+ }
+ unset -nocomplain Priv($w,relief) Priv($w,prelief)
+ }
+
+ # Clean up the after event from the auto-repeater
+ after cancel $Priv(afterId)
+
+ if {$Priv(window) eq $w && [$w cget -state] ne "disabled"} {
+ # Only invoke the command if it wasn't already invoked by the
+ # auto-repeater functionality
+ if { $Priv(repeated) == 0 } {
+ uplevel #0 [list $w invoke]
+ }
+ }
+ }
+}
+
+}
+
+##################
+# Shared routines
+##################
+
+# ::tk::ButtonInvoke --
+# The procedure below is called when a button is invoked through
+# the keyboard. It simulate a press of the button via the mouse.
+#
+# Arguments:
+# w - The name of the widget.
+
+proc ::tk::ButtonInvoke w {
+ if {[winfo exists $w] && [$w cget -state] ne "disabled"} {
+ set oldRelief [$w cget -relief]
+ set oldState [$w cget -state]
+ $w configure -state active -relief sunken
+ after 100 [list ::tk::ButtonInvokeEnd $w $oldState $oldRelief]
+ }
+}
+
+# ::tk::ButtonInvokeEnd --
+# The procedure below is called after a button is invoked through
+# the keyboard. It simulate a release of the button via the mouse.
+#
+# Arguments:
+# w - The name of the widget.
+# oldState - Old state to be set back.
+# oldRelief - Old relief to be set back.
+
+proc ::tk::ButtonInvokeEnd {w oldState oldRelief} {
+ if {[winfo exists $w]} {
+ $w configure -state $oldState -relief $oldRelief
+ uplevel #0 [list $w invoke]
+ }
+}
+
+# ::tk::ButtonAutoInvoke --
+#
+# Invoke an auto-repeating button, and set it up to continue to repeat.
+#
+# Arguments:
+# w button to invoke.
+#
+# Results:
+# None.
+#
+# Side effects:
+# May create an after event to call ::tk::ButtonAutoInvoke.
+
+proc ::tk::ButtonAutoInvoke {w} {
+ variable ::tk::Priv
+ after cancel $Priv(afterId)
+ set delay [$w cget -repeatinterval]
+ if {$Priv(window) eq $w} {
+ incr Priv(repeated)
+ uplevel #0 [list $w invoke]
+ }
+ if {$delay > 0} {
+ set Priv(afterId) [after $delay [list tk::ButtonAutoInvoke $w]]
+ }
+}
+
+# ::tk::CheckRadioInvoke --
+# The procedure below is invoked when the mouse button is pressed in
+# a checkbutton or radiobutton widget, or when the widget is invoked
+# through the keyboard. It invokes the widget if it
+# isn't disabled.
+#
+# Arguments:
+# w - The name of the widget.
+# cmd - The subcommand to invoke (one of invoke, select, or deselect).
+
+proc ::tk::CheckRadioInvoke {w {cmd invoke}} {
+ if {[$w cget -state] ne "disabled"} {
+ uplevel #0 [list $w $cmd]
+ }
+}
+
+# Special versions of the handlers for checkbuttons on Unix that do the magic
+# to make things work right when the checkbutton indicator is hidden;
+# radiobuttons don't need this complexity.
+
+# ::tk::CheckInvoke --
+# The procedure below invokes the checkbutton, like ButtonInvoke, but handles
+# what to do when the checkbutton indicator is missing. Only used on Unix.
+#
+# Arguments:
+# w - The name of the widget.
+
+proc ::tk::CheckInvoke {w} {
+ variable ::tk::Priv
+ if {[$w cget -state] ne "disabled"} {
+ # Additional logic to switch the "selected" colors around if necessary
+ # (when we're indicator-less).
+
+ if {![$w cget -indicatoron] && [info exist Priv($w,selectcolor)]} {
+ if {[$w cget -selectcolor] eq $Priv($w,aselectcolor)} {
+ $w configure -selectcolor $Priv($w,selectcolor)
+ } else {
+ $w configure -selectcolor $Priv($w,aselectcolor)
+ }
+ }
+ uplevel #0 [list $w invoke]
+ }
+}
+
+# ::tk::CheckEnter --
+# The procedure below enters the checkbutton, like ButtonEnter, but handles
+# what to do when the checkbutton indicator is missing. Only used on Unix.
+#
+# Arguments:
+# w - The name of the widget.
+
+proc ::tk::CheckEnter {w} {
+ variable ::tk::Priv
+ if {[$w cget -state] ne "disabled"} {
+ # On unix the state is active just with mouse-over
+ $w configure -state active
+
+ # If the mouse button is down, set the relief to sunken on entry.
+ # Overwise, if there's an -overrelief value, set the relief to that.
+
+ set Priv($w,relief) [$w cget -relief]
+ if {$Priv(buttonWindow) eq $w} {
+ $w configure -relief sunken
+ set Priv($w,prelief) sunken
+ } elseif {[set over [$w cget -overrelief]] ne ""} {
+ $w configure -relief $over
+ set Priv($w,prelief) $over
+ }
+
+ # Compute what the "selected and active" color should be.
+
+ if {![$w cget -indicatoron] && [$w cget -selectcolor] ne ""} {
+ set Priv($w,selectcolor) [$w cget -selectcolor]
+ lassign [winfo rgb $w [$w cget -selectcolor]] r1 g1 b1
+ lassign [winfo rgb $w [$w cget -activebackground]] r2 g2 b2
+ set Priv($w,aselectcolor) \
+ [format "#%04x%04x%04x" [expr {($r1+$r2)/2}] \
+ [expr {($g1+$g2)/2}] [expr {($b1+$b2)/2}]]
+ # use uplevel to work with other var resolvers
+ if {[uplevel #0 [list set [$w cget -variable]]]
+ eq [$w cget -onvalue]} {
+ $w configure -selectcolor $Priv($w,aselectcolor)
+ }
+ }
+ }
+ set Priv(window) $w
+}
+
+# ::tk::CheckLeave --
+# The procedure below leaves the checkbutton, like ButtonLeave, but handles
+# what to do when the checkbutton indicator is missing. Only used on Unix.
+#
+# Arguments:
+# w - The name of the widget.
+
+proc ::tk::CheckLeave {w} {
+ variable ::tk::Priv
+ if {[$w cget -state] ne "disabled"} {
+ $w configure -state normal
+ }
+
+ # Restore the original button "selected" color; but only if the user
+ # has not changed it in the meantime.
+
+ if {![$w cget -indicatoron] && [info exist Priv($w,selectcolor)]} {
+ if {[$w cget -selectcolor] eq $Priv($w,selectcolor)
+ || ([info exist Priv($w,aselectcolor)] &&
+ [$w cget -selectcolor] eq $Priv($w,aselectcolor))} {
+ $w configure -selectcolor $Priv($w,selectcolor)
+ }
+ }
+ unset -nocomplain Priv($w,selectcolor) Priv($w,aselectcolor)
+
+ # Restore the original button relief if it was changed by Tk. That is
+ # signaled by the existence of Priv($w,prelief).
+
+ if {[info exists Priv($w,relief)]} {
+ if {[info exists Priv($w,prelief)] && \
+ $Priv($w,prelief) eq [$w cget -relief]} {
+ $w configure -relief $Priv($w,relief)
+ }
+ unset -nocomplain Priv($w,relief) Priv($w,prelief)
+ }
+
+ set Priv(window) ""
+}
+
+return
+
+# Local Variables:
+# mode: tcl
+# fill-column: 78
+# End:
diff --git a/tk8.6/library/choosedir.tcl b/tk8.6/library/choosedir.tcl
new file mode 100644
index 0000000..68dd9b0
--- /dev/null
+++ b/tk8.6/library/choosedir.tcl
@@ -0,0 +1,308 @@
+# choosedir.tcl --
+#
+# Choose directory dialog implementation for Unix/Mac.
+#
+# Copyright (c) 1998-2000 by Scriptics Corporation.
+# All rights reserved.
+
+# Make sure the tk::dialog namespace, in which all dialogs should live, exists
+namespace eval ::tk::dialog {}
+namespace eval ::tk::dialog::file {}
+
+# Make the chooseDir namespace inside the dialog namespace
+namespace eval ::tk::dialog::file::chooseDir {
+ namespace import -force ::tk::msgcat::*
+}
+
+# ::tk::dialog::file::chooseDir:: --
+#
+# Implements the TK directory selection dialog.
+#
+# Arguments:
+# args Options parsed by the procedure.
+#
+proc ::tk::dialog::file::chooseDir:: {args} {
+ variable ::tk::Priv
+ set dataName __tk_choosedir
+ upvar ::tk::dialog::file::$dataName data
+ Config $dataName $args
+
+ if {$data(-parent) eq "."} {
+ set w .$dataName
+ } else {
+ set w $data(-parent).$dataName
+ }
+
+ # (re)create the dialog box if necessary
+ #
+ if {![winfo exists $w]} {
+ ::tk::dialog::file::Create $w TkChooseDir
+ } elseif {[winfo class $w] ne "TkChooseDir"} {
+ destroy $w
+ ::tk::dialog::file::Create $w TkChooseDir
+ } else {
+ set data(dirMenuBtn) $w.contents.f1.menu
+ set data(dirMenu) $w.contents.f1.menu.menu
+ set data(upBtn) $w.contents.f1.up
+ set data(icons) $w.contents.icons
+ set data(ent) $w.contents.f2.ent
+ set data(okBtn) $w.contents.f2.ok
+ set data(cancelBtn) $w.contents.f2.cancel
+ set data(hiddenBtn) $w.contents.f2.hidden
+ }
+ if {$::tk::dialog::file::showHiddenBtn} {
+ $data(hiddenBtn) configure -state normal
+ grid $data(hiddenBtn)
+ } else {
+ $data(hiddenBtn) configure -state disabled
+ grid remove $data(hiddenBtn)
+ }
+
+ # When using -mustexist, manage the OK button state for validity
+ $data(okBtn) configure -state normal
+ if {$data(-mustexist)} {
+ $data(ent) configure -validate key \
+ -validatecommand [list ::tk::dialog::file::chooseDir::IsOK? $w %P]
+ } else {
+ $data(ent) configure -validate none
+ }
+
+ # Dialog boxes should be transient with respect to their parent,
+ # so that they will always stay on top of their parent window. However,
+ # some window managers will create the window as withdrawn if the parent
+ # window is withdrawn or iconified. Combined with the grab we put on the
+ # window, this can hang the entire application. Therefore we only make
+ # the dialog transient if the parent is viewable.
+
+ if {[winfo viewable [winfo toplevel $data(-parent)]] } {
+ wm transient $w $data(-parent)
+ }
+
+ trace add variable data(selectPath) write \
+ [list ::tk::dialog::file::SetPath $w]
+ $data(dirMenuBtn) configure \
+ -textvariable ::tk::dialog::file::${dataName}(selectPath)
+
+ set data(filter) "*"
+ set data(previousEntryText) ""
+ ::tk::dialog::file::UpdateWhenIdle $w
+
+ # Withdraw the window, then update all the geometry information
+ # so we know how big it wants to be, then center the window in the
+ # display (Motif style) and de-iconify it.
+
+ ::tk::PlaceWindow $w widget $data(-parent)
+ wm title $w $data(-title)
+
+ # Set a grab and claim the focus too.
+
+ ::tk::SetFocusGrab $w $data(ent)
+ $data(ent) delete 0 end
+ $data(ent) insert 0 $data(selectPath)
+ $data(ent) selection range 0 end
+ $data(ent) icursor end
+
+ # Wait for the user to respond, then restore the focus and
+ # return the index of the selected button. Restore the focus
+ # before deleting the window, since otherwise the window manager
+ # may take the focus away so we can't redirect it. Finally,
+ # restore any grab that was in effect.
+
+ vwait ::tk::Priv(selectFilePath)
+
+ ::tk::RestoreFocusGrab $w $data(ent) withdraw
+
+ # Cleanup traces on selectPath variable
+ #
+
+ foreach trace [trace info variable data(selectPath)] {
+ trace remove variable data(selectPath) [lindex $trace 0] [lindex $trace 1]
+ }
+ $data(dirMenuBtn) configure -textvariable {}
+
+ # Return value to user
+ #
+
+ return $Priv(selectFilePath)
+}
+
+# ::tk::dialog::file::chooseDir::Config --
+#
+# Configures the Tk choosedir dialog according to the argument list
+#
+proc ::tk::dialog::file::chooseDir::Config {dataName argList} {
+ upvar ::tk::dialog::file::$dataName data
+
+ # 0: Delete all variable that were set on data(selectPath) the
+ # last time the file dialog is used. The traces may cause troubles
+ # if the dialog is now used with a different -parent option.
+ #
+ foreach trace [trace info variable data(selectPath)] {
+ trace remove variable data(selectPath) [lindex $trace 0] [lindex $trace 1]
+ }
+
+ # 1: the configuration specs
+ #
+ set specs {
+ {-mustexist "" "" 0}
+ {-initialdir "" "" ""}
+ {-parent "" "" "."}
+ {-title "" "" ""}
+ }
+
+ # 2: default values depending on the type of the dialog
+ #
+ if {![info exists data(selectPath)]} {
+ # first time the dialog has been popped up
+ set data(selectPath) [pwd]
+ }
+
+ # 3: parse the arguments
+ #
+ tclParseConfigSpec ::tk::dialog::file::$dataName $specs "" $argList
+
+ if {$data(-title) eq ""} {
+ set data(-title) "[mc "Choose Directory"]"
+ }
+
+ # Stub out the -multiple value for the dialog; it doesn't make sense for
+ # choose directory dialogs, but we have to have something there because we
+ # share so much code with the file dialogs.
+ set data(-multiple) 0
+
+ # 4: set the default directory and selection according to the -initial
+ # settings
+ #
+ if {$data(-initialdir) ne ""} {
+ # Ensure that initialdir is an absolute path name.
+ if {[file isdirectory $data(-initialdir)]} {
+ set old [pwd]
+ cd $data(-initialdir)
+ set data(selectPath) [pwd]
+ cd $old
+ } else {
+ set data(selectPath) [pwd]
+ }
+ }
+
+ if {![winfo exists $data(-parent)]} {
+ return -code error -errorcode [list TK LOOKUP WINDOW $data(-parent)] \
+ "bad window path name \"$data(-parent)\""
+ }
+}
+
+# Gets called when user presses Return in the "Selection" entry or presses OK.
+#
+proc ::tk::dialog::file::chooseDir::OkCmd {w} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+
+ # This is the brains behind selecting non-existant directories. Here's
+ # the flowchart:
+ # 1. If the icon list has a selection, join it with the current dir,
+ # and return that value.
+ # 1a. If the icon list does not have a selection ...
+ # 2. If the entry is empty, do nothing.
+ # 3. If the entry contains an invalid directory, then...
+ # 3a. If the value is the same as last time through here, end dialog.
+ # 3b. If the value is different than last time, save it and return.
+ # 4. If entry contains a valid directory, then...
+ # 4a. If the value is the same as the current directory, end dialog.
+ # 4b. If the value is different from the current directory, change to
+ # that directory.
+
+ set selection [$data(icons) selection get]
+ if {[llength $selection] != 0} {
+ set iconText [$data(icons) get [lindex $selection 0]]
+ set iconText [file join $data(selectPath) $iconText]
+ Done $w $iconText
+ } else {
+ set text [$data(ent) get]
+ if {$text eq ""} {
+ return
+ }
+ set text [file join {*}[file split [string trim $text]]]
+ if {![file exists $text] || ![file isdirectory $text]} {
+ # Entry contains an invalid directory. If it's the same as the
+ # last time they came through here, reset the saved value and end
+ # the dialog. Otherwise, save the value (so we can do this test
+ # next time).
+ if {$text eq $data(previousEntryText)} {
+ set data(previousEntryText) ""
+ Done $w $text
+ } else {
+ set data(previousEntryText) $text
+ }
+ } else {
+ # Entry contains a valid directory. If it is the same as the
+ # current directory, end the dialog. Otherwise, change to that
+ # directory.
+ if {$text eq $data(selectPath)} {
+ Done $w $text
+ } else {
+ set data(selectPath) $text
+ }
+ }
+ }
+ return
+}
+
+# Change state of OK button to match -mustexist correctness of entry
+#
+proc ::tk::dialog::file::chooseDir::IsOK? {w text} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+
+ set ok [file isdirectory $text]
+ $data(okBtn) configure -state [expr {$ok ? "normal" : "disabled"}]
+
+ # always return 1
+ return 1
+}
+
+proc ::tk::dialog::file::chooseDir::DblClick {w} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+ set selection [$data(icons) selection get]
+ if {[llength $selection] != 0} {
+ set filenameFragment [$data(icons) get [lindex $selection 0]]
+ set file $data(selectPath)
+ if {[file isdirectory $file]} {
+ ::tk::dialog::file::ListInvoke $w [list $filenameFragment]
+ return
+ }
+ }
+}
+
+# Gets called when user browses the IconList widget (dragging mouse, arrow
+# keys, etc)
+#
+proc ::tk::dialog::file::chooseDir::ListBrowse {w text} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+
+ if {$text eq ""} {
+ return
+ }
+
+ set file [::tk::dialog::file::JoinFile $data(selectPath) $text]
+ $data(ent) delete 0 end
+ $data(ent) insert 0 $file
+}
+
+# ::tk::dialog::file::chooseDir::Done --
+#
+# Gets called when user has input a valid filename. Pops up a
+# dialog box to confirm selection when necessary. Sets the
+# Priv(selectFilePath) variable, which will break the "vwait"
+# loop in tk_chooseDirectory and return the selected filename to the
+# script that calls tk_getOpenFile or tk_getSaveFile
+#
+proc ::tk::dialog::file::chooseDir::Done {w {selectFilePath ""}} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+ variable ::tk::Priv
+
+ if {$selectFilePath eq ""} {
+ set selectFilePath $data(selectPath)
+ }
+ if {$data(-mustexist) && ![file isdirectory $selectFilePath]} {
+ return
+ }
+ set Priv(selectFilePath) $selectFilePath
+}
diff --git a/tk8.6/library/clrpick.tcl b/tk8.6/library/clrpick.tcl
new file mode 100644
index 0000000..600be16
--- /dev/null
+++ b/tk8.6/library/clrpick.tcl
@@ -0,0 +1,695 @@
+# clrpick.tcl --
+#
+# Color selection dialog for platforms that do not support a
+# standard color selection dialog.
+#
+# 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.
+#
+# ToDo:
+#
+# (1): Find out how many free colors are left in the colormap and
+# don't allocate too many colors.
+# (2): Implement HSV color selection.
+#
+
+# Make sure namespaces exist
+namespace eval ::tk {}
+namespace eval ::tk::dialog {}
+namespace eval ::tk::dialog::color {
+ namespace import ::tk::msgcat::*
+}
+
+# ::tk::dialog::color:: --
+#
+# Create a color dialog and let the user choose a color. This function
+# should not be called directly. It is called by the tk_chooseColor
+# function when a native color selector widget does not exist
+#
+proc ::tk::dialog::color:: {args} {
+ variable ::tk::Priv
+ set dataName __tk__color
+ upvar ::tk::dialog::color::$dataName data
+ set w .$dataName
+
+ # The lines variables track the start and end indices of the line
+ # elements in the colorbar canvases.
+ set data(lines,red,start) 0
+ set data(lines,red,last) -1
+ set data(lines,green,start) 0
+ set data(lines,green,last) -1
+ set data(lines,blue,start) 0
+ set data(lines,blue,last) -1
+
+ # This is the actual number of lines that are drawn in each color strip.
+ # Note that the bars may be of any width.
+ # However, NUM_COLORBARS must be a number that evenly divides 256.
+ # Such as 256, 128, 64, etc.
+ set data(NUM_COLORBARS) 16
+
+ # BARS_WIDTH is the number of pixels wide the color bar portion of the
+ # canvas is. This number must be a multiple of NUM_COLORBARS
+ set data(BARS_WIDTH) 160
+
+ # PLGN_WIDTH is the number of pixels wide of the triangular selection
+ # polygon. This also results in the definition of the padding on the
+ # left and right sides which is half of PLGN_WIDTH. Make this number even.
+ set data(PLGN_HEIGHT) 10
+
+ # PLGN_HEIGHT is the height of the selection polygon and the height of the
+ # selection rectangle at the bottom of the color bar. No restrictions.
+ set data(PLGN_WIDTH) 10
+
+ Config $dataName $args
+ InitValues $dataName
+
+ set sc [winfo screen $data(-parent)]
+ set winExists [winfo exists $w]
+ if {!$winExists || $sc ne [winfo screen $w]} {
+ if {$winExists} {
+ destroy $w
+ }
+ toplevel $w -class TkColorDialog -screen $sc
+ if {[tk windowingsystem] eq "x11"} {wm attributes $w -type dialog}
+ BuildDialog $w
+ }
+
+ # Dialog boxes should be transient with respect to their parent,
+ # so that they will always stay on top of their parent window. However,
+ # some window managers will create the window as withdrawn if the parent
+ # window is withdrawn or iconified. Combined with the grab we put on the
+ # window, this can hang the entire application. Therefore we only make
+ # the dialog transient if the parent is viewable.
+
+ if {[winfo viewable [winfo toplevel $data(-parent)]] } {
+ wm transient $w $data(-parent)
+ }
+
+ # 5. Withdraw the window, then update all the geometry information
+ # so we know how big it wants to be, then center the window in the
+ # display (Motif style) and de-iconify it.
+
+ ::tk::PlaceWindow $w widget $data(-parent)
+ wm title $w $data(-title)
+
+ # 6. Set a grab and claim the focus too.
+
+ ::tk::SetFocusGrab $w $data(okBtn)
+
+ # 7. Wait for the user to respond, then restore the focus and
+ # return the index of the selected button. Restore the focus
+ # before deleting the window, since otherwise the window manager
+ # may take the focus away so we can't redirect it. Finally,
+ # restore any grab that was in effect.
+
+ vwait ::tk::Priv(selectColor)
+ set result $Priv(selectColor)
+ ::tk::RestoreFocusGrab $w $data(okBtn)
+ unset data
+
+ return $result
+}
+
+# ::tk::dialog::color::InitValues --
+#
+# Get called during initialization or when user resets NUM_COLORBARS
+#
+proc ::tk::dialog::color::InitValues {dataName} {
+ upvar ::tk::dialog::color::$dataName data
+
+ # IntensityIncr is the difference in color intensity between a colorbar
+ # and its neighbors.
+ set data(intensityIncr) [expr {256 / $data(NUM_COLORBARS)}]
+
+ # ColorbarWidth is the width of each colorbar
+ set data(colorbarWidth) [expr {$data(BARS_WIDTH) / $data(NUM_COLORBARS)}]
+
+ # Indent is the width of the space at the left and right side of the
+ # colorbar. It is always half the selector polygon width, because the
+ # polygon extends into the space.
+ set data(indent) [expr {$data(PLGN_WIDTH) / 2}]
+
+ set data(colorPad) 2
+ set data(selPad) [expr {$data(PLGN_WIDTH) / 2}]
+
+ #
+ # minX is the x coordinate of the first colorbar
+ #
+ set data(minX) $data(indent)
+
+ #
+ # maxX is the x coordinate of the last colorbar
+ #
+ set data(maxX) [expr {$data(BARS_WIDTH) + $data(indent)-1}]
+
+ #
+ # canvasWidth is the width of the entire canvas, including the indents
+ #
+ set data(canvasWidth) [expr {$data(BARS_WIDTH) + $data(PLGN_WIDTH)}]
+
+ # Set the initial color, specified by -initialcolor, or the
+ # color chosen by the user the last time.
+ set data(selection) $data(-initialcolor)
+ set data(finalColor) $data(-initialcolor)
+ set rgb [winfo rgb . $data(selection)]
+
+ set data(red,intensity) [expr {[lindex $rgb 0]/0x100}]
+ set data(green,intensity) [expr {[lindex $rgb 1]/0x100}]
+ set data(blue,intensity) [expr {[lindex $rgb 2]/0x100}]
+}
+
+# ::tk::dialog::color::Config --
+#
+# Parses the command line arguments to tk_chooseColor
+#
+proc ::tk::dialog::color::Config {dataName argList} {
+ variable ::tk::Priv
+ upvar ::tk::dialog::color::$dataName data
+
+ # 1: the configuration specs
+ #
+ if {[info exists Priv(selectColor)] && $Priv(selectColor) ne ""} {
+ set defaultColor $Priv(selectColor)
+ } else {
+ set defaultColor [. cget -background]
+ }
+
+ set specs [list \
+ [list -initialcolor "" "" $defaultColor] \
+ [list -parent "" "" "."] \
+ [list -title "" "" [mc "Color"]] \
+ ]
+
+ # 2: parse the arguments
+ #
+ tclParseConfigSpec ::tk::dialog::color::$dataName $specs "" $argList
+
+ if {$data(-title) eq ""} {
+ set data(-title) " "
+ }
+ if {[catch {winfo rgb . $data(-initialcolor)} err]} {
+ return -code error -errorcode [list TK LOOKUP COLOR $data(-initialcolor)] \
+ $err
+ }
+
+ if {![winfo exists $data(-parent)]} {
+ return -code error -errorcode [list TK LOOKUP WINDOW $data(-parent)] \
+ "bad window path name \"$data(-parent)\""
+ }
+}
+
+# ::tk::dialog::color::BuildDialog --
+#
+# Build the dialog.
+#
+proc ::tk::dialog::color::BuildDialog {w} {
+ upvar ::tk::dialog::color::[winfo name $w] data
+
+ # TopFrame contains the color strips and the color selection
+ #
+ set topFrame [frame $w.top -relief raised -bd 1]
+
+ # StripsFrame contains the colorstrips and the individual RGB entries
+ set stripsFrame [frame $topFrame.colorStrip]
+
+ set maxWidth [::tk::mcmaxamp &Red &Green &Blue]
+ set maxWidth [expr {$maxWidth<6 ? 6 : $maxWidth}]
+ set colorList {
+ red "&Red"
+ green "&Green"
+ blue "&Blue"
+ }
+ foreach {color l} $colorList {
+ # each f frame contains an [R|G|B] entry and the equiv. color strip.
+ set f [frame $stripsFrame.$color]
+
+ # The box frame contains the label and entry widget for an [R|G|B]
+ set box [frame $f.box]
+
+ ::tk::AmpWidget label $box.label -text "[mc $l]:" \
+ -width $maxWidth -anchor ne
+ bind $box.label <<AltUnderlined>> [list focus $box.entry]
+
+ entry $box.entry -textvariable \
+ ::tk::dialog::color::[winfo name $w]($color,intensity) \
+ -width 4
+ pack $box.label -side left -fill y -padx 2 -pady 3
+ pack $box.entry -side left -anchor n -pady 0
+ pack $box -side left -fill both
+
+ set height [expr {
+ [winfo reqheight $box.entry] -
+ 2*([$box.entry cget -highlightthickness] + [$box.entry cget -bd])
+ }]
+
+ canvas $f.color -height $height \
+ -width $data(BARS_WIDTH) -relief sunken -bd 2
+ canvas $f.sel -height $data(PLGN_HEIGHT) \
+ -width $data(canvasWidth) -highlightthickness 0
+ pack $f.color -expand yes -fill both
+ pack $f.sel -expand yes -fill both
+
+ pack $f -side top -fill x -padx 0 -pady 2
+
+ set data($color,entry) $box.entry
+ set data($color,col) $f.color
+ set data($color,sel) $f.sel
+
+ bind $data($color,col) <Configure> \
+ [list tk::dialog::color::DrawColorScale $w $color 1]
+ bind $data($color,col) <Enter> \
+ [list tk::dialog::color::EnterColorBar $w $color]
+ bind $data($color,col) <Leave> \
+ [list tk::dialog::color::LeaveColorBar $w $color]
+
+ bind $data($color,sel) <Enter> \
+ [list tk::dialog::color::EnterColorBar $w $color]
+ bind $data($color,sel) <Leave> \
+ [list tk::dialog::color::LeaveColorBar $w $color]
+
+ bind $box.entry <Return> [list tk::dialog::color::HandleRGBEntry $w]
+ }
+
+ pack $stripsFrame -side left -fill both -padx 4 -pady 10
+
+ # The selFrame contains a frame that demonstrates the currently
+ # selected color
+ #
+ set selFrame [frame $topFrame.sel]
+ set lab [::tk::AmpWidget label $selFrame.lab \
+ -text [mc "&Selection:"] -anchor sw]
+ set ent [entry $selFrame.ent \
+ -textvariable ::tk::dialog::color::[winfo name $w](selection) \
+ -width 16]
+ set f1 [frame $selFrame.f1 -relief sunken -bd 2]
+ set data(finalCanvas) [frame $f1.demo -bd 0 -width 100 -height 70]
+
+ pack $lab $ent -side top -fill x -padx 4 -pady 2
+ pack $f1 -expand yes -anchor nw -fill both -padx 6 -pady 10
+ pack $data(finalCanvas) -expand yes -fill both
+
+ bind $ent <Return> [list tk::dialog::color::HandleSelEntry $w]
+
+ pack $selFrame -side left -fill none -anchor nw
+ pack $topFrame -side top -expand yes -fill both -anchor nw
+
+ # the botFrame frame contains the buttons
+ #
+ set botFrame [frame $w.bot -relief raised -bd 1]
+
+ ::tk::AmpWidget button $botFrame.ok -text [mc "&OK"] \
+ -command [list tk::dialog::color::OkCmd $w]
+ ::tk::AmpWidget button $botFrame.cancel -text [mc "&Cancel"] \
+ -command [list tk::dialog::color::CancelCmd $w]
+
+ set data(okBtn) $botFrame.ok
+ set data(cancelBtn) $botFrame.cancel
+
+ grid x $botFrame.ok x $botFrame.cancel x -sticky ew
+ grid configure $botFrame.ok $botFrame.cancel -padx 10 -pady 10
+ grid columnconfigure $botFrame {0 4} -weight 1 -uniform space
+ grid columnconfigure $botFrame {1 3} -weight 1 -uniform button
+ grid columnconfigure $botFrame 2 -weight 2 -uniform space
+ pack $botFrame -side bottom -fill x
+
+ # Accelerator bindings
+ bind $lab <<AltUnderlined>> [list focus $ent]
+ bind $w <KeyPress-Escape> [list tk::ButtonInvoke $data(cancelBtn)]
+ bind $w <Alt-Key> [list tk::AltKeyInDialog $w %A]
+
+ wm protocol $w WM_DELETE_WINDOW [list tk::dialog::color::CancelCmd $w]
+ bind $lab <Destroy> [list tk::dialog::color::CancelCmd $w]
+}
+
+# ::tk::dialog::color::SetRGBValue --
+#
+# Sets the current selection of the dialog box
+#
+proc ::tk::dialog::color::SetRGBValue {w color} {
+ upvar ::tk::dialog::color::[winfo name $w] data
+
+ set data(red,intensity) [lindex $color 0]
+ set data(green,intensity) [lindex $color 1]
+ set data(blue,intensity) [lindex $color 2]
+
+ RedrawColorBars $w all
+
+ # Now compute the new x value of each colorbars pointer polygon
+ foreach color {red green blue} {
+ set x [RgbToX $w $data($color,intensity)]
+ MoveSelector $w $data($color,sel) $color $x 0
+ }
+}
+
+# ::tk::dialog::color::XToRgb --
+#
+# Converts a screen coordinate to intensity
+#
+proc ::tk::dialog::color::XToRgb {w x} {
+ upvar ::tk::dialog::color::[winfo name $w] data
+
+ set x [expr {($x * $data(intensityIncr))/ $data(colorbarWidth)}]
+ if {$x > 255} {
+ set x 255
+ }
+ return $x
+}
+
+# ::tk::dialog::color::RgbToX
+#
+# Converts an intensity to screen coordinate.
+#
+proc ::tk::dialog::color::RgbToX {w color} {
+ upvar ::tk::dialog::color::[winfo name $w] data
+
+ return [expr {($color * $data(colorbarWidth)/ $data(intensityIncr))}]
+}
+
+# ::tk::dialog::color::DrawColorScale --
+#
+# Draw color scale is called whenever the size of one of the color
+# scale canvases is changed.
+#
+proc ::tk::dialog::color::DrawColorScale {w c {create 0}} {
+ upvar ::tk::dialog::color::[winfo name $w] data
+
+ # col: color bar canvas
+ # sel: selector canvas
+ set col $data($c,col)
+ set sel $data($c,sel)
+
+ # First handle the case that we are creating everything for the first time.
+ if {$create} {
+ # First remove all the lines that already exist.
+ if { $data(lines,$c,last) > $data(lines,$c,start)} {
+ for {set i $data(lines,$c,start)} \
+ {$i <= $data(lines,$c,last)} {incr i} {
+ $sel delete $i
+ }
+ }
+ # Delete the selector if it exists
+ if {[info exists data($c,index)]} {
+ $sel delete $data($c,index)
+ }
+
+ # Draw the selection polygons
+ CreateSelector $w $sel $c
+ $sel bind $data($c,index) <ButtonPress-1> \
+ [list tk::dialog::color::StartMove $w $sel $c %x $data(selPad) 1]
+ $sel bind $data($c,index) <B1-Motion> \
+ [list tk::dialog::color::MoveSelector $w $sel $c %x $data(selPad)]
+ $sel bind $data($c,index) <ButtonRelease-1> \
+ [list tk::dialog::color::ReleaseMouse $w $sel $c %x $data(selPad)]
+
+ set height [winfo height $col]
+ # Create an invisible region under the colorstrip to catch mouse clicks
+ # that aren't on the selector.
+ set data($c,clickRegion) [$sel create rectangle 0 0 \
+ $data(canvasWidth) $height -fill {} -outline {}]
+
+ bind $col <ButtonPress-1> \
+ [list tk::dialog::color::StartMove $w $sel $c %x $data(colorPad)]
+ bind $col <B1-Motion> \
+ [list tk::dialog::color::MoveSelector $w $sel $c %x $data(colorPad)]
+ bind $col <ButtonRelease-1> \
+ [list tk::dialog::color::ReleaseMouse $w $sel $c %x $data(colorPad)]
+
+ $sel bind $data($c,clickRegion) <ButtonPress-1> \
+ [list tk::dialog::color::StartMove $w $sel $c %x $data(selPad)]
+ $sel bind $data($c,clickRegion) <B1-Motion> \
+ [list tk::dialog::color::MoveSelector $w $sel $c %x $data(selPad)]
+ $sel bind $data($c,clickRegion) <ButtonRelease-1> \
+ [list tk::dialog::color::ReleaseMouse $w $sel $c %x $data(selPad)]
+ } else {
+ # l is the canvas index of the first colorbar.
+ set l $data(lines,$c,start)
+ }
+
+ # Draw the color bars.
+ set highlightW [expr {[$col cget -highlightthickness] + [$col cget -bd]}]
+ for {set i 0} { $i < $data(NUM_COLORBARS)} { incr i} {
+ set intensity [expr {$i * $data(intensityIncr)}]
+ set startx [expr {$i * $data(colorbarWidth) + $highlightW}]
+ if {$c eq "red"} {
+ set color [format "#%02x%02x%02x" \
+ $intensity $data(green,intensity) $data(blue,intensity)]
+ } elseif {$c eq "green"} {
+ set color [format "#%02x%02x%02x" \
+ $data(red,intensity) $intensity $data(blue,intensity)]
+ } else {
+ set color [format "#%02x%02x%02x" \
+ $data(red,intensity) $data(green,intensity) $intensity]
+ }
+
+ if {$create} {
+ set index [$col create rect $startx $highlightW \
+ [expr {$startx +$data(colorbarWidth)}] \
+ [expr {[winfo height $col] + $highlightW}] \
+ -fill $color -outline $color]
+ } else {
+ $col itemconfigure $l -fill $color -outline $color
+ incr l
+ }
+ }
+ $sel raise $data($c,index)
+
+ if {$create} {
+ set data(lines,$c,last) $index
+ set data(lines,$c,start) [expr {$index - $data(NUM_COLORBARS) + 1}]
+ }
+
+ RedrawFinalColor $w
+}
+
+# ::tk::dialog::color::CreateSelector --
+#
+# Creates and draws the selector polygon at the position
+# $data($c,intensity).
+#
+proc ::tk::dialog::color::CreateSelector {w sel c } {
+ upvar ::tk::dialog::color::[winfo name $w] data
+ set data($c,index) [$sel create polygon \
+ 0 $data(PLGN_HEIGHT) \
+ $data(PLGN_WIDTH) $data(PLGN_HEIGHT) \
+ $data(indent) 0]
+ set data($c,x) [RgbToX $w $data($c,intensity)]
+ $sel move $data($c,index) $data($c,x) 0
+}
+
+# ::tk::dialog::color::RedrawFinalColor
+#
+# Combines the intensities of the three colors into the final color
+#
+proc ::tk::dialog::color::RedrawFinalColor {w} {
+ upvar ::tk::dialog::color::[winfo name $w] data
+
+ set color [format "#%02x%02x%02x" $data(red,intensity) \
+ $data(green,intensity) $data(blue,intensity)]
+
+ $data(finalCanvas) configure -bg $color
+ set data(finalColor) $color
+ set data(selection) $color
+ set data(finalRGB) [list \
+ $data(red,intensity) \
+ $data(green,intensity) \
+ $data(blue,intensity)]
+}
+
+# ::tk::dialog::color::RedrawColorBars --
+#
+# Only redraws the colors on the color strips that were not manipulated.
+# Params: color of colorstrip that changed. If color is not [red|green|blue]
+# Then all colorstrips will be updated
+#
+proc ::tk::dialog::color::RedrawColorBars {w colorChanged} {
+ upvar ::tk::dialog::color::[winfo name $w] data
+
+ switch $colorChanged {
+ red {
+ DrawColorScale $w green
+ DrawColorScale $w blue
+ }
+ green {
+ DrawColorScale $w red
+ DrawColorScale $w blue
+ }
+ blue {
+ DrawColorScale $w red
+ DrawColorScale $w green
+ }
+ default {
+ DrawColorScale $w red
+ DrawColorScale $w green
+ DrawColorScale $w blue
+ }
+ }
+ RedrawFinalColor $w
+}
+
+#----------------------------------------------------------------------
+# Event handlers
+#----------------------------------------------------------------------
+
+# ::tk::dialog::color::StartMove --
+#
+# Handles a mousedown button event over the selector polygon.
+# Adds the bindings for moving the mouse while the button is
+# pressed. Sets the binding for the button-release event.
+#
+# Params: sel is the selector canvas window, color is the color of the strip.
+#
+proc ::tk::dialog::color::StartMove {w sel color x delta {dontMove 0}} {
+ upvar ::tk::dialog::color::[winfo name $w] data
+
+ if {!$dontMove} {
+ MoveSelector $w $sel $color $x $delta
+ }
+}
+
+# ::tk::dialog::color::MoveSelector --
+#
+# Moves the polygon selector so that its middle point has the same
+# x value as the specified x. If x is outside the bounds [0,255],
+# the selector is set to the closest endpoint.
+#
+# Params: sel is the selector canvas, c is [red|green|blue]
+# x is a x-coordinate.
+#
+proc ::tk::dialog::color::MoveSelector {w sel color x delta} {
+ upvar ::tk::dialog::color::[winfo name $w] data
+
+ incr x -$delta
+
+ if { $x < 0 } {
+ set x 0
+ } elseif { $x > $data(BARS_WIDTH)} {
+ set x $data(BARS_WIDTH)
+ }
+ set diff [expr {$x - $data($color,x)}]
+ $sel move $data($color,index) $diff 0
+ set data($color,x) [expr {$data($color,x) + $diff}]
+
+ # Return the x value that it was actually set at
+ return $x
+}
+
+# ::tk::dialog::color::ReleaseMouse
+#
+# Removes mouse tracking bindings, updates the colorbars.
+#
+# Params: sel is the selector canvas, color is the color of the strip,
+# x is the x-coord of the mouse.
+#
+proc ::tk::dialog::color::ReleaseMouse {w sel color x delta} {
+ upvar ::tk::dialog::color::[winfo name $w] data
+
+ set x [MoveSelector $w $sel $color $x $delta]
+
+ # Determine exactly what color we are looking at.
+ set data($color,intensity) [XToRgb $w $x]
+
+ RedrawColorBars $w $color
+}
+
+# ::tk::dialog::color::ResizeColorbars --
+#
+# Completely redraws the colorbars, including resizing the
+# colorstrips
+#
+proc ::tk::dialog::color::ResizeColorBars {w} {
+ upvar ::tk::dialog::color::[winfo name $w] data
+
+ if {
+ ($data(BARS_WIDTH) < $data(NUM_COLORBARS)) ||
+ (($data(BARS_WIDTH) % $data(NUM_COLORBARS)) != 0)
+ } then {
+ set data(BARS_WIDTH) $data(NUM_COLORBARS)
+ }
+ InitValues [winfo name $w]
+ foreach color {red green blue} {
+ $data($color,col) configure -width $data(canvasWidth)
+ DrawColorScale $w $color 1
+ }
+}
+
+# ::tk::dialog::color::HandleSelEntry --
+#
+# Handles the return keypress event in the "Selection:" entry
+#
+proc ::tk::dialog::color::HandleSelEntry {w} {
+ upvar ::tk::dialog::color::[winfo name $w] data
+
+ set text [string trim $data(selection)]
+ # Check to make sure that the color is valid
+ if {[catch {set color [winfo rgb . $text]} ]} {
+ set data(selection) $data(finalColor)
+ return
+ }
+
+ set R [expr {[lindex $color 0]/0x100}]
+ set G [expr {[lindex $color 1]/0x100}]
+ set B [expr {[lindex $color 2]/0x100}]
+
+ SetRGBValue $w "$R $G $B"
+ set data(selection) $text
+}
+
+# ::tk::dialog::color::HandleRGBEntry --
+#
+# Handles the return keypress event in the R, G or B entry
+#
+proc ::tk::dialog::color::HandleRGBEntry {w} {
+ upvar ::tk::dialog::color::[winfo name $w] data
+
+ foreach c {red green blue} {
+ if {[catch {
+ set data($c,intensity) [expr {int($data($c,intensity))}]
+ }]} {
+ set data($c,intensity) 0
+ }
+
+ if {$data($c,intensity) < 0} {
+ set data($c,intensity) 0
+ }
+ if {$data($c,intensity) > 255} {
+ set data($c,intensity) 255
+ }
+ }
+
+ SetRGBValue $w "$data(red,intensity) \
+ $data(green,intensity) $data(blue,intensity)"
+}
+
+# mouse cursor enters a color bar
+#
+proc ::tk::dialog::color::EnterColorBar {w color} {
+ upvar ::tk::dialog::color::[winfo name $w] data
+
+ $data($color,sel) itemconfigure $data($color,index) -fill red
+}
+
+# mouse leaves enters a color bar
+#
+proc ::tk::dialog::color::LeaveColorBar {w color} {
+ upvar ::tk::dialog::color::[winfo name $w] data
+
+ $data($color,sel) itemconfigure $data($color,index) -fill black
+}
+
+# user hits OK button
+#
+proc ::tk::dialog::color::OkCmd {w} {
+ variable ::tk::Priv
+ upvar ::tk::dialog::color::[winfo name $w] data
+
+ set Priv(selectColor) $data(finalColor)
+}
+
+# user hits Cancel button or destroys window
+#
+proc ::tk::dialog::color::CancelCmd {w} {
+ variable ::tk::Priv
+ set Priv(selectColor) ""
+}
diff --git a/tk8.6/library/comdlg.tcl b/tk8.6/library/comdlg.tcl
new file mode 100644
index 0000000..18df8a6
--- /dev/null
+++ b/tk8.6/library/comdlg.tcl
@@ -0,0 +1,319 @@
+# comdlg.tcl --
+#
+# Some functions needed for the common dialog boxes. Probably need to go
+# in a different file.
+#
+# 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.
+#
+
+# tclParseConfigSpec --
+#
+# Parses a list of "-option value" pairs. If all options and
+# values are legal, the values are stored in
+# $data($option). Otherwise an error message is returned. When
+# an error happens, the data() array may have been partially
+# modified, but all the modified members of the data(0 array are
+# guaranteed to have valid values. This is different than
+# Tk_ConfigureWidget() which does not modify the value of a
+# widget record if any error occurs.
+#
+# Arguments:
+#
+# w = widget record to modify. Must be the pathname of a widget.
+#
+# specs = {
+# {-commandlineswitch resourceName ResourceClass defaultValue verifier}
+# {....}
+# }
+#
+# flags = currently unused.
+#
+# argList = The list of "-option value" pairs.
+#
+proc tclParseConfigSpec {w specs flags argList} {
+ upvar #0 $w data
+
+ # 1: Put the specs in associative arrays for faster access
+ #
+ foreach spec $specs {
+ if {[llength $spec] < 4} {
+ return -code error -errorcode {TK VALUE CONFIG_SPEC} \
+ "\"spec\" should contain 5 or 4 elements"
+ }
+ set cmdsw [lindex $spec 0]
+ set cmd($cmdsw) ""
+ set rname($cmdsw) [lindex $spec 1]
+ set rclass($cmdsw) [lindex $spec 2]
+ set def($cmdsw) [lindex $spec 3]
+ set verproc($cmdsw) [lindex $spec 4]
+ }
+
+ if {[llength $argList] & 1} {
+ set cmdsw [lindex $argList end]
+ if {![info exists cmd($cmdsw)]} {
+ return -code error -errorcode [list TK LOOKUP OPTION $cmdsw] \
+ "bad option \"$cmdsw\": must be [tclListValidFlags cmd]"
+ }
+ return -code error -errorcode {TK VALUE_MISSING} \
+ "value for \"$cmdsw\" missing"
+ }
+
+ # 2: set the default values
+ #
+ foreach cmdsw [array names cmd] {
+ set data($cmdsw) $def($cmdsw)
+ }
+
+ # 3: parse the argument list
+ #
+ foreach {cmdsw value} $argList {
+ if {![info exists cmd($cmdsw)]} {
+ return -code error -errorcode [list TK LOOKUP OPTION $cmdsw] \
+ "bad option \"$cmdsw\": must be [tclListValidFlags cmd]"
+ }
+ set data($cmdsw) $value
+ }
+
+ # Done!
+}
+
+proc tclListValidFlags {v} {
+ upvar $v cmd
+
+ set len [llength [array names cmd]]
+ set i 1
+ set separator ""
+ set errormsg ""
+ foreach cmdsw [lsort [array names cmd]] {
+ append errormsg "$separator$cmdsw"
+ incr i
+ if {$i == $len} {
+ set separator ", or "
+ } else {
+ set separator ", "
+ }
+ }
+ return $errormsg
+}
+
+#----------------------------------------------------------------------
+#
+# Focus Group
+#
+# Focus groups are used to handle the user's focusing actions inside a
+# toplevel.
+#
+# One example of using focus groups is: when the user focuses on an
+# entry, the text in the entry is highlighted and the cursor is put to
+# the end of the text. When the user changes focus to another widget,
+# the text in the previously focused entry is validated.
+#
+#----------------------------------------------------------------------
+
+
+# ::tk::FocusGroup_Create --
+#
+# Create a focus group. All the widgets in a focus group must be
+# within the same focus toplevel. Each toplevel can have only
+# one focus group, which is identified by the name of the
+# toplevel widget.
+#
+proc ::tk::FocusGroup_Create {t} {
+ variable ::tk::Priv
+ if {[winfo toplevel $t] ne $t} {
+ return -code error -errorcode [list TK LOOKUP TOPLEVEL $t] \
+ "$t is not a toplevel window"
+ }
+ if {![info exists Priv(fg,$t)]} {
+ set Priv(fg,$t) 1
+ set Priv(focus,$t) ""
+ bind $t <FocusIn> [list tk::FocusGroup_In $t %W %d]
+ bind $t <FocusOut> [list tk::FocusGroup_Out $t %W %d]
+ bind $t <Destroy> [list tk::FocusGroup_Destroy $t %W]
+ }
+}
+
+# ::tk::FocusGroup_BindIn --
+#
+# Add a widget into the "FocusIn" list of the focus group. The $cmd will be
+# called when the widget is focused on by the user.
+#
+proc ::tk::FocusGroup_BindIn {t w cmd} {
+ variable FocusIn
+ variable ::tk::Priv
+ if {![info exists Priv(fg,$t)]} {
+ return -code error -errorcode [list TK LOOKUP FOCUS_GROUP $t] \
+ "focus group \"$t\" doesn't exist"
+ }
+ set FocusIn($t,$w) $cmd
+}
+
+
+# ::tk::FocusGroup_BindOut --
+#
+# Add a widget into the "FocusOut" list of the focus group. The
+# $cmd will be called when the widget loses the focus (User
+# types Tab or click on another widget).
+#
+proc ::tk::FocusGroup_BindOut {t w cmd} {
+ variable FocusOut
+ variable ::tk::Priv
+ if {![info exists Priv(fg,$t)]} {
+ return -code error -errorcode [list TK LOOKUP FOCUS_GROUP $t] \
+ "focus group \"$t\" doesn't exist"
+ }
+ set FocusOut($t,$w) $cmd
+}
+
+# ::tk::FocusGroup_Destroy --
+#
+# Cleans up when members of the focus group is deleted, or when the
+# toplevel itself gets deleted.
+#
+proc ::tk::FocusGroup_Destroy {t w} {
+ variable FocusIn
+ variable FocusOut
+ variable ::tk::Priv
+
+ if {$t eq $w} {
+ unset Priv(fg,$t)
+ unset Priv(focus,$t)
+
+ foreach name [array names FocusIn $t,*] {
+ unset FocusIn($name)
+ }
+ foreach name [array names FocusOut $t,*] {
+ unset FocusOut($name)
+ }
+ } else {
+ if {[info exists Priv(focus,$t)] && ($Priv(focus,$t) eq $w)} {
+ set Priv(focus,$t) ""
+ }
+ unset -nocomplain FocusIn($t,$w) FocusOut($t,$w)
+ }
+}
+
+# ::tk::FocusGroup_In --
+#
+# Handles the <FocusIn> event. Calls the FocusIn command for the newly
+# focused widget in the focus group.
+#
+proc ::tk::FocusGroup_In {t w detail} {
+ variable FocusIn
+ variable ::tk::Priv
+
+ if {$detail ne "NotifyNonlinear" && $detail ne "NotifyNonlinearVirtual"} {
+ # This is caused by mouse moving out&in of the window *or*
+ # ordinary keypresses some window managers (ie: CDE [Bug: 2960]).
+ return
+ }
+ if {![info exists FocusIn($t,$w)]} {
+ set FocusIn($t,$w) ""
+ return
+ }
+ if {![info exists Priv(focus,$t)]} {
+ return
+ }
+ if {$Priv(focus,$t) eq $w} {
+ # This is already in focus
+ #
+ return
+ } else {
+ set Priv(focus,$t) $w
+ eval $FocusIn($t,$w)
+ }
+}
+
+# ::tk::FocusGroup_Out --
+#
+# Handles the <FocusOut> event. Checks if this is really a lose
+# focus event, not one generated by the mouse moving out of the
+# toplevel window. Calls the FocusOut command for the widget
+# who loses its focus.
+#
+proc ::tk::FocusGroup_Out {t w detail} {
+ variable FocusOut
+ variable ::tk::Priv
+
+ if {$detail ne "NotifyNonlinear" && $detail ne "NotifyNonlinearVirtual"} {
+ # This is caused by mouse moving out of the window
+ return
+ }
+ if {![info exists Priv(focus,$t)]} {
+ return
+ }
+ if {![info exists FocusOut($t,$w)]} {
+ return
+ } else {
+ eval $FocusOut($t,$w)
+ set Priv(focus,$t) ""
+ }
+}
+
+# ::tk::FDGetFileTypes --
+#
+# Process the string given by the -filetypes option of the file
+# dialogs. Similar to the C function TkGetFileFilters() on the Mac
+# and Windows platform.
+#
+proc ::tk::FDGetFileTypes {string} {
+ foreach t $string {
+ if {[llength $t] < 2 || [llength $t] > 3} {
+ return -code error -errorcode {TK VALUE FILE_TYPE} \
+ "bad file type \"$t\", should be \"typeName {extension ?extensions ...?} ?{macType ?macTypes ...?}?\""
+ }
+ lappend fileTypes([lindex $t 0]) {*}[lindex $t 1]
+ }
+
+ set types {}
+ foreach t $string {
+ set label [lindex $t 0]
+ set exts {}
+
+ if {[info exists hasDoneType($label)]} {
+ continue
+ }
+
+ # Validate each macType. This is to agree with the
+ # behaviour of TkGetFileFilters(). This list may be
+ # empty.
+ foreach macType [lindex $t 2] {
+ if {[string length $macType] != 4} {
+ return -code error -errorcode {TK VALUE MAC_TYPE} \
+ "bad Macintosh file type \"$macType\""
+ }
+ }
+
+ set name "$label \("
+ set sep ""
+ set doAppend 1
+ foreach ext $fileTypes($label) {
+ if {$ext eq ""} {
+ continue
+ }
+ regsub {^[.]} $ext "*." ext
+ if {![info exists hasGotExt($label,$ext)]} {
+ if {$doAppend} {
+ if {[string length $sep] && [string length $name]>40} {
+ set doAppend 0
+ append name $sep...
+ } else {
+ append name $sep$ext
+ }
+ }
+ lappend exts $ext
+ set hasGotExt($label,$ext) 1
+ }
+ set sep ","
+ }
+ append name "\)"
+ lappend types [list $name $exts]
+
+ set hasDoneType($label) 1
+ }
+
+ return $types
+}
diff --git a/tk8.6/library/console.tcl b/tk8.6/library/console.tcl
new file mode 100644
index 0000000..355a43b
--- /dev/null
+++ b/tk8.6/library/console.tcl
@@ -0,0 +1,1150 @@
+# console.tcl --
+#
+# This code constructs the console window for an application. It
+# can be used by non-unix systems that do not have built-in support
+# for shells.
+#
+# Copyright (c) 1995-1997 Sun Microsystems, Inc.
+# Copyright (c) 1998-2000 Ajuba Solutions.
+# Copyright (c) 2007-2008 Daniel A. Steffen <das@users.sourceforge.net>
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+
+# TODO: history - remember partially written command
+
+namespace eval ::tk::console {
+ variable blinkTime 500 ; # msecs to blink braced range for
+ variable blinkRange 1 ; # enable blinking of the entire braced range
+ variable magicKeys 1 ; # enable brace matching and proc/var recognition
+ variable maxLines 600 ; # maximum # of lines buffered in console
+ variable showMatches 1 ; # show multiple expand matches
+ variable useFontchooser [llength [info command ::tk::fontchooser]]
+ variable inPlugin [info exists embed_args]
+ variable defaultPrompt ; # default prompt if tcl_prompt1 isn't used
+
+ if {$inPlugin} {
+ set defaultPrompt {subst {[history nextid] % }}
+ } else {
+ set defaultPrompt {subst {([file tail [pwd]]) [history nextid] % }}
+ }
+}
+
+# simple compat function for tkcon code added for this console
+interp alias {} EvalAttached {} consoleinterp eval
+
+# ::tk::ConsoleInit --
+# This procedure constructs and configures the console windows.
+#
+# Arguments:
+# None.
+
+proc ::tk::ConsoleInit {} {
+ if {![consoleinterp eval {set tcl_interactive}]} {
+ wm withdraw .
+ }
+
+ if {[tk windowingsystem] eq "aqua"} {
+ set mod "Cmd"
+ } else {
+ set mod "Ctrl"
+ }
+
+ if {[catch {menu .menubar} err]} {
+ bgerror "INIT: $err"
+ }
+ AmpMenuArgs .menubar add cascade -label [mc &File] -menu .menubar.file
+ AmpMenuArgs .menubar add cascade -label [mc &Edit] -menu .menubar.edit
+
+ menu .menubar.file -tearoff 0
+ AmpMenuArgs .menubar.file add command -label [mc "&Source..."] \
+ -command {tk::ConsoleSource}
+ AmpMenuArgs .menubar.file add command -label [mc "&Hide Console"] \
+ -command {wm withdraw .}
+ AmpMenuArgs .menubar.file add command -label [mc "&Clear Console"] \
+ -command {.console delete 1.0 "promptEnd linestart"}
+ if {[tk windowingsystem] ne "aqua"} {
+ AmpMenuArgs .menubar.file add command -label [mc E&xit] -command {exit}
+ }
+
+ menu .menubar.edit -tearoff 0
+ AmpMenuArgs .menubar.edit add command -label [mc Cu&t] -accel "$mod+X"\
+ -command {event generate .console <<Cut>>}
+ AmpMenuArgs .menubar.edit add command -label [mc &Copy] -accel "$mod+C"\
+ -command {event generate .console <<Copy>>}
+ AmpMenuArgs .menubar.edit add command -label [mc P&aste] -accel "$mod+V"\
+ -command {event generate .console <<Paste>>}
+
+ if {[tk windowingsystem] ne "win32"} {
+ AmpMenuArgs .menubar.edit add command -label [mc Cl&ear] \
+ -command {event generate .console <<Clear>>}
+ } else {
+ AmpMenuArgs .menubar.edit add command -label [mc &Delete] \
+ -command {event generate .console <<Clear>>} -accel "Del"
+
+ AmpMenuArgs .menubar add cascade -label [mc &Help] -menu .menubar.help
+ menu .menubar.help -tearoff 0
+ AmpMenuArgs .menubar.help add command -label [mc &About...] \
+ -command tk::ConsoleAbout
+ }
+
+ AmpMenuArgs .menubar.edit add separator
+ if {$::tk::console::useFontchooser} {
+ if {[tk windowingsystem] eq "aqua"} {
+ .menubar.edit add command -label tk_choose_font_marker
+ set index [.menubar.edit index tk_choose_font_marker]
+ .menubar.edit entryconfigure $index \
+ -label [mc "Show Fonts"]\
+ -accelerator "$mod-T"\
+ -command [list ::tk::console::FontchooserToggle]
+ bind Console <<TkFontchooserVisibility>> \
+ [list ::tk::console::FontchooserVisibility $index]
+ ::tk::console::FontchooserVisibility $index
+ } else {
+ AmpMenuArgs .menubar.edit add command -label [mc "&Font..."] \
+ -command [list ::tk::console::FontchooserToggle]
+ }
+ bind Console <FocusIn> [list ::tk::console::FontchooserFocus %W 1]
+ bind Console <FocusOut> [list ::tk::console::FontchooserFocus %W 0]
+ }
+ AmpMenuArgs .menubar.edit add command -label [mc "&Increase Font Size"] \
+ -accel "$mod++" -command {event generate .console <<Console_FontSizeIncr>>}
+ AmpMenuArgs .menubar.edit add command -label [mc "&Decrease Font Size"] \
+ -accel "$mod+-" -command {event generate .console <<Console_FontSizeDecr>>}
+ AmpMenuArgs .menubar.edit add command -label [mc "Fit To Screen Width"] \
+ -command {event generate .console <<Console_FitScreenWidth>>}
+
+ if {[tk windowingsystem] eq "aqua"} {
+ .menubar add cascade -label [mc Window] -menu [menu .menubar.window]
+ .menubar add cascade -label [mc Help] -menu [menu .menubar.help]
+ }
+
+ . configure -menu .menubar
+
+ # See if we can find a better font than the TkFixedFont
+ catch {font create TkConsoleFont {*}[font configure TkFixedFont]}
+ set families [font families]
+ switch -exact -- [tk windowingsystem] {
+ aqua { set preferred {Monaco 10} }
+ win32 { set preferred {ProFontWindows 8 Consolas 8} }
+ default { set preferred {} }
+ }
+ foreach {family size} $preferred {
+ if {[lsearch -exact $families $family] != -1} {
+ font configure TkConsoleFont -family $family -size $size
+ break
+ }
+ }
+
+ # Provide the right border for the text widget (platform dependent).
+ ::ttk::style layout ConsoleFrame {
+ Entry.field -sticky news -border 1 -children {
+ ConsoleFrame.padding -sticky news
+ }
+ }
+ ::ttk::frame .consoleframe -style ConsoleFrame
+
+ set con [text .console -yscrollcommand [list .sb set] -setgrid true \
+ -borderwidth 0 -highlightthickness 0 -font TkConsoleFont]
+ if {[tk windowingsystem] eq "aqua"} {
+ scrollbar .sb -command [list $con yview]
+ } else {
+ ::ttk::scrollbar .sb -command [list $con yview]
+ }
+ pack .sb -in .consoleframe -fill both -side right -padx 1 -pady 1
+ pack $con -in .consoleframe -fill both -expand 1 -side left -padx 1 -pady 1
+ pack .consoleframe -fill both -expand 1 -side left
+
+ ConsoleBind $con
+
+ $con tag configure stderr -foreground red
+ $con tag configure stdin -foreground blue
+ $con tag configure prompt -foreground \#8F4433
+ $con tag configure proc -foreground \#008800
+ $con tag configure var -background \#FFC0D0
+ $con tag raise sel
+ $con tag configure blink -background \#FFFF00
+ $con tag configure find -background \#FFFF00
+
+ focus $con
+
+ # Avoid listing this console in [winfo interps]
+ if {[info command ::send] eq "::send"} {rename ::send {}}
+
+ wm protocol . WM_DELETE_WINDOW { wm withdraw . }
+ wm title . [mc "Console"]
+ flush stdout
+ $con mark set output [$con index "end - 1 char"]
+ tk::TextSetCursor $con end
+ $con mark set promptEnd insert
+ $con mark gravity promptEnd left
+
+ # A variant of ConsolePrompt to avoid a 'puts' call
+ set w $con
+ set temp [$w index "end - 1 char"]
+ $w mark set output end
+ if {![consoleinterp eval "info exists tcl_prompt1"]} {
+ set string [EvalAttached $::tk::console::defaultPrompt]
+ $w insert output $string stdout
+ }
+ $w mark set output $temp
+ ::tk::TextSetCursor $w end
+ $w mark set promptEnd insert
+ $w mark gravity promptEnd left
+
+ if {[tk windowingsystem] ne "aqua"} {
+ # Subtle work-around to erase the '% ' that tclMain.c prints out
+ after idle [subst -nocommand {
+ if {[$con get 1.0 output] eq "% "} { $con delete 1.0 output }
+ }]
+ }
+}
+
+# ::tk::ConsoleSource --
+#
+# Prompts the user for a file to source in the main interpreter.
+#
+# Arguments:
+# None.
+
+proc ::tk::ConsoleSource {} {
+ set filename [tk_getOpenFile -defaultextension .tcl -parent . \
+ -title [mc "Select a file to source"] \
+ -filetypes [list \
+ [list [mc "Tcl Scripts"] .tcl] \
+ [list [mc "All Files"] *]]]
+ if {$filename ne ""} {
+ set cmd [list source $filename]
+ if {[catch {consoleinterp eval $cmd} result]} {
+ ConsoleOutput stderr "$result\n"
+ }
+ }
+}
+
+# ::tk::ConsoleInvoke --
+# Processes the command line input. If the command is complete it
+# is evaled in the main interpreter. Otherwise, the continuation
+# prompt is added and more input may be added.
+#
+# Arguments:
+# None.
+
+proc ::tk::ConsoleInvoke {args} {
+ set ranges [.console tag ranges input]
+ set cmd ""
+ if {[llength $ranges]} {
+ set pos 0
+ while {[lindex $ranges $pos] ne ""} {
+ set start [lindex $ranges $pos]
+ set end [lindex $ranges [incr pos]]
+ append cmd [.console get $start $end]
+ incr pos
+ }
+ }
+ if {$cmd eq ""} {
+ ConsolePrompt
+ } elseif {[info complete $cmd]} {
+ .console mark set output end
+ .console tag delete input
+ set result [consoleinterp record $cmd]
+ if {$result ne ""} {
+ puts $result
+ }
+ ConsoleHistory reset
+ ConsolePrompt
+ } else {
+ ConsolePrompt partial
+ }
+ .console yview -pickplace insert
+}
+
+# ::tk::ConsoleHistory --
+# This procedure implements command line history for the
+# console. In general is evals the history command in the
+# main interpreter to obtain the history. The variable
+# ::tk::HistNum is used to store the current location in the history.
+#
+# Arguments:
+# cmd - Which action to take: prev, next, reset.
+
+set ::tk::HistNum 1
+proc ::tk::ConsoleHistory {cmd} {
+ variable HistNum
+
+ switch $cmd {
+ prev {
+ incr HistNum -1
+ if {$HistNum == 0} {
+ set cmd {history event [expr {[history nextid] -1}]}
+ } else {
+ set cmd "history event $HistNum"
+ }
+ if {[catch {consoleinterp eval $cmd} cmd]} {
+ incr HistNum
+ return
+ }
+ .console delete promptEnd end
+ .console insert promptEnd $cmd {input stdin}
+ .console see end
+ }
+ next {
+ incr HistNum
+ if {$HistNum == 0} {
+ set cmd {history event [expr {[history nextid] -1}]}
+ } elseif {$HistNum > 0} {
+ set cmd ""
+ set HistNum 1
+ } else {
+ set cmd "history event $HistNum"
+ }
+ if {$cmd ne ""} {
+ catch {consoleinterp eval $cmd} cmd
+ }
+ .console delete promptEnd end
+ .console insert promptEnd $cmd {input stdin}
+ .console see end
+ }
+ reset {
+ set HistNum 1
+ }
+ }
+}
+
+# ::tk::ConsolePrompt --
+# This procedure draws the prompt. If tcl_prompt1 or tcl_prompt2
+# exists in the main interpreter it will be called to generate the
+# prompt. Otherwise, a hard coded default prompt is printed.
+#
+# Arguments:
+# partial - Flag to specify which prompt to print.
+
+proc ::tk::ConsolePrompt {{partial normal}} {
+ set w .console
+ if {$partial eq "normal"} {
+ set temp [$w index "end - 1 char"]
+ $w mark set output end
+ if {[consoleinterp eval "info exists tcl_prompt1"]} {
+ consoleinterp eval "eval \[set tcl_prompt1\]"
+ } else {
+ puts -nonewline [EvalAttached $::tk::console::defaultPrompt]
+ }
+ } else {
+ set temp [$w index output]
+ $w mark set output end
+ if {[consoleinterp eval "info exists tcl_prompt2"]} {
+ consoleinterp eval "eval \[set tcl_prompt2\]"
+ } else {
+ puts -nonewline "> "
+ }
+ }
+ flush stdout
+ $w mark set output $temp
+ ::tk::TextSetCursor $w end
+ $w mark set promptEnd insert
+ $w mark gravity promptEnd left
+ ::tk::console::ConstrainBuffer $w $::tk::console::maxLines
+ $w see end
+}
+
+# Copy selected text from the console
+proc ::tk::console::Copy {w} {
+ if {![catch {set data [$w get sel.first sel.last]}]} {
+ clipboard clear -displayof $w
+ clipboard append -displayof $w $data
+ }
+}
+# Copies selected text. If the selection is within the current active edit
+# region then it will be cut, if not it is only copied.
+proc ::tk::console::Cut {w} {
+ if {![catch {set data [$w get sel.first sel.last]}]} {
+ clipboard clear -displayof $w
+ clipboard append -displayof $w $data
+ if {[$w compare sel.first >= output]} {
+ $w delete sel.first sel.last
+ }
+ }
+}
+# Paste text from the clipboard
+proc ::tk::console::Paste {w} {
+ catch {
+ set clip [::tk::GetSelection $w CLIPBOARD]
+ set list [split $clip \n\r]
+ tk::ConsoleInsert $w [lindex $list 0]
+ foreach x [lrange $list 1 end] {
+ $w mark set insert {end - 1c}
+ tk::ConsoleInsert $w "\n"
+ tk::ConsoleInvoke
+ tk::ConsoleInsert $w $x
+ }
+ }
+}
+
+# Fit TkConsoleFont to window width
+proc ::tk::console::FitScreenWidth {w} {
+ set width [winfo screenwidth $w]
+ set cwidth [$w cget -width]
+ set s -50
+ set fit 0
+ array set fi [font configure TkConsoleFont]
+ while {$s < 0} {
+ set fi(-size) $s
+ set f [font create {*}[array get fi]]
+ set c [font measure $f "eM"]
+ font delete $f
+ if {$c * $cwidth < 1.667 * $width} {
+ font configure TkConsoleFont -size $s
+ break
+ }
+ incr s 2
+ }
+}
+
+# ::tk::ConsoleBind --
+# This procedure first ensures that the default bindings for the Text
+# class have been defined. Then certain bindings are overridden for
+# the class.
+#
+# Arguments:
+# None.
+
+proc ::tk::ConsoleBind {w} {
+ bindtags $w [list $w Console PostConsole [winfo toplevel $w] all]
+
+ ## Get all Text bindings into Console
+ foreach ev [bind Text] {
+ bind Console $ev [bind Text $ev]
+ }
+ ## We really didn't want the newline insertion...
+ bind Console <Control-Key-o> {}
+ ## ...or any Control-v binding (would block <<Paste>>)
+ bind Console <Control-Key-v> {}
+
+ # For the moment, transpose isn't enabled until the console
+ # gets and overhaul of how it handles input -- hobbs
+ bind Console <Control-Key-t> {}
+
+ # Ignore all Alt, Meta, and Control keypresses unless explicitly bound.
+ # Otherwise, if a widget binding for one of these is defined, the
+ # <Keypress> class binding will also fire and insert the character
+ # which is wrong.
+
+ bind Console <Alt-KeyPress> {# nothing }
+ bind Console <Meta-KeyPress> {# nothing}
+ bind Console <Control-KeyPress> {# nothing}
+
+ foreach {ev key} {
+ <<Console_NextImmediate>> <Control-Key-n>
+ <<Console_PrevImmediate>> <Control-Key-p>
+ <<Console_PrevSearch>> <Control-Key-r>
+ <<Console_NextSearch>> <Control-Key-s>
+
+ <<Console_Expand>> <Key-Tab>
+ <<Console_Expand>> <Key-Escape>
+ <<Console_ExpandFile>> <Control-Shift-Key-F>
+ <<Console_ExpandProc>> <Control-Shift-Key-P>
+ <<Console_ExpandVar>> <Control-Shift-Key-V>
+ <<Console_Tab>> <Control-Key-i>
+ <<Console_Tab>> <Meta-Key-i>
+ <<Console_Eval>> <Key-Return>
+ <<Console_Eval>> <Key-KP_Enter>
+
+ <<Console_Clear>> <Control-Key-l>
+ <<Console_KillLine>> <Control-Key-k>
+ <<Console_Transpose>> <Control-Key-t>
+ <<Console_ClearLine>> <Control-Key-u>
+ <<Console_SaveCommand>> <Control-Key-z>
+ <<Console_FontSizeIncr>> <Control-Key-plus>
+ <<Console_FontSizeDecr>> <Control-Key-minus>
+ } {
+ event add $ev $key
+ bind Console $key {}
+ }
+ if {[tk windowingsystem] eq "aqua"} {
+ foreach {ev key} {
+ <<Console_FontSizeIncr>> <Command-Key-plus>
+ <<Console_FontSizeDecr>> <Command-Key-minus>
+ } {
+ event add $ev $key
+ bind Console $key {}
+ }
+ if {$::tk::console::useFontchooser} {
+ bind Console <Command-Key-t> [list ::tk::console::FontchooserToggle]
+ }
+ }
+ bind Console <<Console_Expand>> {
+ if {[%W compare insert > promptEnd]} {
+ ::tk::console::Expand %W
+ }
+ }
+ bind Console <<Console_ExpandFile>> {
+ if {[%W compare insert > promptEnd]} {
+ ::tk::console::Expand %W path
+ }
+ }
+ bind Console <<Console_ExpandProc>> {
+ if {[%W compare insert > promptEnd]} {
+ ::tk::console::Expand %W proc
+ }
+ }
+ bind Console <<Console_ExpandVar>> {
+ if {[%W compare insert > promptEnd]} {
+ ::tk::console::Expand %W var
+ }
+ }
+ bind Console <<Console_Eval>> {
+ %W mark set insert {end - 1c}
+ tk::ConsoleInsert %W "\n"
+ tk::ConsoleInvoke
+ break
+ }
+ bind Console <Delete> {
+ if {{} ne [%W tag nextrange sel 1.0 end] \
+ && [%W compare sel.first >= promptEnd]} {
+ %W delete sel.first sel.last
+ } elseif {[%W compare insert >= promptEnd]} {
+ %W delete insert
+ %W see insert
+ }
+ }
+ bind Console <BackSpace> {
+ if {{} ne [%W tag nextrange sel 1.0 end] \
+ && [%W compare sel.first >= promptEnd]} {
+ %W delete sel.first sel.last
+ } elseif {[%W compare insert != 1.0] && \
+ [%W compare insert > promptEnd]} {
+ %W delete insert-1c
+ %W see insert
+ }
+ }
+ bind Console <Control-h> [bind Console <BackSpace>]
+
+ bind Console <<LineStart>> {
+ if {[%W compare insert < promptEnd]} {
+ tk::TextSetCursor %W {insert linestart}
+ } else {
+ tk::TextSetCursor %W promptEnd
+ }
+ }
+ bind Console <<LineEnd>> {
+ tk::TextSetCursor %W {insert lineend}
+ }
+ bind Console <Control-d> {
+ if {[%W compare insert < promptEnd]} {
+ break
+ }
+ %W delete insert
+ }
+ bind Console <<Console_KillLine>> {
+ if {[%W compare insert < promptEnd]} {
+ break
+ }
+ if {[%W compare insert == {insert lineend}]} {
+ %W delete insert
+ } else {
+ %W delete insert {insert lineend}
+ }
+ }
+ bind Console <<Console_Clear>> {
+ ## Clear console display
+ %W delete 1.0 "promptEnd linestart"
+ }
+ bind Console <<Console_ClearLine>> {
+ ## Clear command line (Unix shell staple)
+ %W delete promptEnd end
+ }
+ bind Console <Meta-d> {
+ if {[%W compare insert >= promptEnd]} {
+ %W delete insert {insert wordend}
+ }
+ }
+ bind Console <Meta-BackSpace> {
+ if {[%W compare {insert -1c wordstart} >= promptEnd]} {
+ %W delete {insert -1c wordstart} insert
+ }
+ }
+ bind Console <Meta-d> {
+ if {[%W compare insert >= promptEnd]} {
+ %W delete insert {insert wordend}
+ }
+ }
+ bind Console <Meta-BackSpace> {
+ if {[%W compare {insert -1c wordstart} >= promptEnd]} {
+ %W delete {insert -1c wordstart} insert
+ }
+ }
+ bind Console <Meta-Delete> {
+ if {[%W compare insert >= promptEnd]} {
+ %W delete insert {insert wordend}
+ }
+ }
+ bind Console <<PrevLine>> {
+ tk::ConsoleHistory prev
+ }
+ bind Console <<NextLine>> {
+ tk::ConsoleHistory next
+ }
+ bind Console <Insert> {
+ catch {tk::ConsoleInsert %W [::tk::GetSelection %W PRIMARY]}
+ }
+ bind Console <KeyPress> {
+ tk::ConsoleInsert %W %A
+ }
+ bind Console <F9> {
+ eval destroy [winfo child .]
+ source [file join $tk_library console.tcl]
+ }
+ if {[tk windowingsystem] eq "aqua"} {
+ bind Console <Command-q> {
+ exit
+ }
+ }
+ bind Console <<Cut>> { ::tk::console::Cut %W }
+ bind Console <<Copy>> { ::tk::console::Copy %W }
+ bind Console <<Paste>> { ::tk::console::Paste %W }
+
+ bind Console <<Console_FontSizeIncr>> {
+ set size [font configure TkConsoleFont -size]
+ if {$size < 0} {set sign -1} else {set sign 1}
+ set size [expr {(abs($size) + 1) * $sign}]
+ font configure TkConsoleFont -size $size
+ if {$::tk::console::useFontchooser} {
+ tk fontchooser configure -font TkConsoleFont
+ }
+ }
+ bind Console <<Console_FontSizeDecr>> {
+ set size [font configure TkConsoleFont -size]
+ if {abs($size) < 2} { return }
+ if {$size < 0} {set sign -1} else {set sign 1}
+ set size [expr {(abs($size) - 1) * $sign}]
+ font configure TkConsoleFont -size $size
+ if {$::tk::console::useFontchooser} {
+ tk fontchooser configure -font TkConsoleFont
+ }
+ }
+ bind Console <<Console_FitScreenWidth>> {
+ ::tk::console::FitScreenWidth %W
+ }
+
+ ##
+ ## Bindings for doing special things based on certain keys
+ ##
+ bind PostConsole <Key-parenright> {
+ if {"\\" ne [%W get insert-2c]} {
+ ::tk::console::MatchPair %W \( \) promptEnd
+ }
+ }
+ bind PostConsole <Key-bracketright> {
+ if {"\\" ne [%W get insert-2c]} {
+ ::tk::console::MatchPair %W \[ \] promptEnd
+ }
+ }
+ bind PostConsole <Key-braceright> {
+ if {"\\" ne [%W get insert-2c]} {
+ ::tk::console::MatchPair %W \{ \} promptEnd
+ }
+ }
+ bind PostConsole <Key-quotedbl> {
+ if {"\\" ne [%W get insert-2c]} {
+ ::tk::console::MatchQuote %W promptEnd
+ }
+ }
+
+ bind PostConsole <KeyPress> {
+ if {"%A" ne ""} {
+ ::tk::console::TagProc %W
+ }
+ }
+}
+
+# ::tk::ConsoleInsert --
+# Insert a string into a text at the point of the insertion cursor.
+# If there is a selection in the text, and it covers the point of the
+# insertion cursor, then delete the selection before inserting. Insertion
+# is restricted to the prompt area.
+#
+# Arguments:
+# w - The text window in which to insert the string
+# s - The string to insert (usually just a single character)
+
+proc ::tk::ConsoleInsert {w s} {
+ if {$s eq ""} {
+ return
+ }
+ catch {
+ if {[$w compare sel.first <= insert] \
+ && [$w compare sel.last >= insert]} {
+ $w tag remove sel sel.first promptEnd
+ $w delete sel.first sel.last
+ }
+ }
+ if {[$w compare insert < promptEnd]} {
+ $w mark set insert end
+ }
+ $w insert insert $s {input stdin}
+ $w see insert
+}
+
+# ::tk::ConsoleOutput --
+#
+# This routine is called directly by ConsolePutsCmd to cause a string
+# to be displayed in the console.
+#
+# Arguments:
+# dest - The output tag to be used: either "stderr" or "stdout".
+# string - The string to be displayed.
+
+proc ::tk::ConsoleOutput {dest string} {
+ set w .console
+ $w insert output $string $dest
+ ::tk::console::ConstrainBuffer $w $::tk::console::maxLines
+ $w see insert
+}
+
+# ::tk::ConsoleExit --
+#
+# This routine is called by ConsoleEventProc when the main window of
+# the application is destroyed. Don't call exit - that probably already
+# happened. Just delete our window.
+#
+# Arguments:
+# None.
+
+proc ::tk::ConsoleExit {} {
+ destroy .
+}
+
+# ::tk::ConsoleAbout --
+#
+# This routine displays an About box to show Tcl/Tk version info.
+#
+# Arguments:
+# None.
+
+proc ::tk::ConsoleAbout {} {
+ tk_messageBox -type ok -message "[mc {Tcl for Windows}]
+
+Tcl $::tcl_patchLevel
+Tk $::tk_patchLevel"
+}
+
+# ::tk::console::Fontchooser* --
+# Let the user select the console font (TIP 324).
+
+proc ::tk::console::FontchooserToggle {} {
+ if {[tk fontchooser configure -visible]} {
+ tk fontchooser hide
+ } else {
+ tk fontchooser show
+ }
+}
+proc ::tk::console::FontchooserVisibility {index} {
+ if {[tk fontchooser configure -visible]} {
+ .menubar.edit entryconfigure $index -label [msgcat::mc "Hide Fonts"]
+ } else {
+ .menubar.edit entryconfigure $index -label [msgcat::mc "Show Fonts"]
+ }
+}
+proc ::tk::console::FontchooserFocus {w isFocusIn} {
+ if {$isFocusIn} {
+ tk fontchooser configure -parent $w -font TkConsoleFont \
+ -command [namespace code [list FontchooserApply]]
+ } else {
+ tk fontchooser configure -parent $w -font {} -command {}
+ }
+}
+proc ::tk::console::FontchooserApply {font args} {
+ catch {font configure TkConsoleFont {*}[font actual $font]}
+}
+
+# ::tk::console::TagProc --
+#
+# Tags a procedure in the console if it's recognized
+# This procedure is not perfect. However, making it perfect wastes
+# too much CPU time...
+#
+# Arguments:
+# w - console text widget
+
+proc ::tk::console::TagProc w {
+ if {!$::tk::console::magicKeys} {
+ return
+ }
+ set exp "\[^\\\\\]\[\[ \t\n\r\;{}\"\$\]"
+ set i [$w search -backwards -regexp $exp insert-1c promptEnd-1c]
+ if {$i eq ""} {
+ set i promptEnd
+ } else {
+ append i +2c
+ }
+ regsub -all "\[\[\\\\\\?\\*\]" [$w get $i "insert-1c wordend"] {\\\0} c
+ if {[llength [EvalAttached [list info commands $c]]]} {
+ $w tag add proc $i "insert-1c wordend"
+ } else {
+ $w tag remove proc $i "insert-1c wordend"
+ }
+ if {[llength [EvalAttached [list info vars $c]]]} {
+ $w tag add var $i "insert-1c wordend"
+ } else {
+ $w tag remove var $i "insert-1c wordend"
+ }
+}
+
+# ::tk::console::MatchPair --
+#
+# Blinks a matching pair of characters
+# c2 is assumed to be at the text index 'insert'.
+# This proc is really loopy and took me an hour to figure out given
+# all possible combinations with escaping except for escaped \'s.
+# It doesn't take into account possible commenting... Oh well. If
+# anyone has something better, I'd like to see/use it. This is really
+# only efficient for small contexts.
+#
+# Arguments:
+# w - console text widget
+# c1 - first char of pair
+# c2 - second char of pair
+#
+# Calls: ::tk::console::Blink
+
+proc ::tk::console::MatchPair {w c1 c2 {lim 1.0}} {
+ if {!$::tk::console::magicKeys} {
+ return
+ }
+ if {{} ne [set ix [$w search -back $c1 insert $lim]]} {
+ while {
+ [string match {\\} [$w get $ix-1c]] &&
+ [set ix [$w search -back $c1 $ix-1c $lim]] ne {}
+ } {}
+ set i1 insert-1c
+ while {$ix ne {}} {
+ set i0 $ix
+ set j 0
+ while {[set i0 [$w search $c2 $i0 $i1]] ne {}} {
+ append i0 +1c
+ if {[string match {\\} [$w get $i0-2c]]} {
+ continue
+ }
+ incr j
+ }
+ if {!$j} {
+ break
+ }
+ set i1 $ix
+ while {$j && [set ix [$w search -back $c1 $ix $lim]] ne {}} {
+ if {[string match {\\} [$w get $ix-1c]]} {
+ continue
+ }
+ incr j -1
+ }
+ }
+ if {[string match {} $ix]} {
+ set ix [$w index $lim]
+ }
+ } else {
+ set ix [$w index $lim]
+ }
+ if {$::tk::console::blinkRange} {
+ Blink $w $ix [$w index insert]
+ } else {
+ Blink $w $ix $ix+1c [$w index insert-1c] [$w index insert]
+ }
+}
+
+# ::tk::console::MatchQuote --
+#
+# Blinks between matching quotes.
+# Blinks just the quote if it's unmatched, otherwise blinks quoted string
+# The quote to match is assumed to be at the text index 'insert'.
+#
+# Arguments:
+# w - console text widget
+#
+# Calls: ::tk::console::Blink
+
+proc ::tk::console::MatchQuote {w {lim 1.0}} {
+ if {!$::tk::console::magicKeys} {
+ return
+ }
+ set i insert-1c
+ set j 0
+ while {[set i [$w search -back \" $i $lim]] ne {}} {
+ if {[string match {\\} [$w get $i-1c]]} {
+ continue
+ }
+ if {!$j} {
+ set i0 $i
+ }
+ incr j
+ }
+ if {$j&1} {
+ if {$::tk::console::blinkRange} {
+ Blink $w $i0 [$w index insert]
+ } else {
+ Blink $w $i0 $i0+1c [$w index insert-1c] [$w index insert]
+ }
+ } else {
+ Blink $w [$w index insert-1c] [$w index insert]
+ }
+}
+
+# ::tk::console::Blink --
+#
+# Blinks between n index pairs for a specified duration.
+#
+# Arguments:
+# w - console text widget
+# i1 - start index to blink region
+# i2 - end index of blink region
+# dur - duration in usecs to blink for
+#
+# Outputs:
+# blinks selected characters in $w
+
+proc ::tk::console::Blink {w args} {
+ eval [list $w tag add blink] $args
+ after $::tk::console::blinkTime [list $w] tag remove blink $args
+}
+
+# ::tk::console::ConstrainBuffer --
+#
+# This limits the amount of data in the text widget
+# Called by Prompt and ConsoleOutput
+#
+# Arguments:
+# w - console text widget
+# size - # of lines to constrain to
+#
+# Outputs:
+# may delete data in console widget
+
+proc ::tk::console::ConstrainBuffer {w size} {
+ if {[$w index end] > $size} {
+ $w delete 1.0 [expr {int([$w index end])-$size}].0
+ }
+}
+
+# ::tk::console::Expand --
+#
+# Arguments:
+# ARGS: w - text widget in which to expand str
+# type - type of expansion (path / proc / variable)
+#
+# Calls: ::tk::console::Expand(Pathname|Procname|Variable)
+#
+# Outputs: The string to match is expanded to the longest possible match.
+# If ::tk::console::showMatches is non-zero and the longest match
+# equaled the string to expand, then all possible matches are
+# output to stdout. Triggers bell if no matches are found.
+#
+# Returns: number of matches found
+
+proc ::tk::console::Expand {w {type ""}} {
+ set exp "\[^\\\\\]\[\[ \t\n\r\\\{\"\\\\\$\]"
+ set tmp [$w search -backwards -regexp $exp insert-1c promptEnd-1c]
+ if {$tmp eq ""} {
+ set tmp promptEnd
+ } else {
+ append tmp +2c
+ }
+ if {[$w compare $tmp >= insert]} {
+ return
+ }
+ set str [$w get $tmp insert]
+ switch -glob $type {
+ path* {
+ set res [ExpandPathname $str]
+ }
+ proc* {
+ set res [ExpandProcname $str]
+ }
+ var* {
+ set res [ExpandVariable $str]
+ }
+ default {
+ set res {}
+ foreach t {Pathname Procname Variable} {
+ if {![catch {Expand$t $str} res] && ($res ne "")} {
+ break
+ }
+ }
+ }
+ }
+ set len [llength $res]
+ if {$len} {
+ set repl [lindex $res 0]
+ $w delete $tmp insert
+ $w insert $tmp $repl {input stdin}
+ if {($len > 1) && ($::tk::console::showMatches) && ($repl eq $str)} {
+ puts stdout [lsort [lreplace $res 0 0]]
+ }
+ } else {
+ bell
+ }
+ return [incr len -1]
+}
+
+# ::tk::console::ExpandPathname --
+#
+# Expand a file pathname based on $str
+# This is based on UNIX file name conventions
+#
+# Arguments:
+# str - partial file pathname to expand
+#
+# Calls: ::tk::console::ExpandBestMatch
+#
+# Returns: list containing longest unique match followed by all the
+# possible further matches
+
+proc ::tk::console::ExpandPathname str {
+ set pwd [EvalAttached pwd]
+ if {[catch {EvalAttached [list cd [file dirname $str]]} err opt]} {
+ return -options $opt $err
+ }
+ set dir [file tail $str]
+ ## Check to see if it was known to be a directory and keep the trailing
+ ## slash if so (file tail cuts it off)
+ if {[string match */ $str]} {
+ append dir /
+ }
+ if {[catch {lsort [EvalAttached [list glob $dir*]]} m]} {
+ set match {}
+ } else {
+ if {[llength $m] > 1} {
+ if { $::tcl_platform(platform) eq "windows" } {
+ ## Windows is screwy because it's case insensitive
+ set tmp [ExpandBestMatch [string tolower $m] \
+ [string tolower $dir]]
+ ## Don't change case if we haven't changed the word
+ if {[string length $dir]==[string length $tmp]} {
+ set tmp $dir
+ }
+ } else {
+ set tmp [ExpandBestMatch $m $dir]
+ }
+ if {[string match ?*/* $str]} {
+ set tmp [file dirname $str]/$tmp
+ } elseif {[string match /* $str]} {
+ set tmp /$tmp
+ }
+ regsub -all { } $tmp {\\ } tmp
+ set match [linsert $m 0 $tmp]
+ } else {
+ ## This may look goofy, but it handles spaces in path names
+ eval append match $m
+ if {[file isdir $match]} {
+ append match /
+ }
+ if {[string match ?*/* $str]} {
+ set match [file dirname $str]/$match
+ } elseif {[string match /* $str]} {
+ set match /$match
+ }
+ regsub -all { } $match {\\ } match
+ ## Why is this one needed and the ones below aren't!!
+ set match [list $match]
+ }
+ }
+ EvalAttached [list cd $pwd]
+ return $match
+}
+
+# ::tk::console::ExpandProcname --
+#
+# Expand a tcl proc name based on $str
+#
+# Arguments:
+# str - partial proc name to expand
+#
+# Calls: ::tk::console::ExpandBestMatch
+#
+# Returns: list containing longest unique match followed by all the
+# possible further matches
+
+proc ::tk::console::ExpandProcname str {
+ set match [EvalAttached [list info commands $str*]]
+ if {[llength $match] == 0} {
+ set ns [EvalAttached \
+ "namespace children \[namespace current\] [list $str*]"]
+ if {[llength $ns]==1} {
+ set match [EvalAttached [list info commands ${ns}::*]]
+ } else {
+ set match $ns
+ }
+ }
+ if {[llength $match] > 1} {
+ regsub -all { } [ExpandBestMatch $match $str] {\\ } str
+ set match [linsert $match 0 $str]
+ } else {
+ regsub -all { } $match {\\ } match
+ }
+ return $match
+}
+
+# ::tk::console::ExpandVariable --
+#
+# Expand a tcl variable name based on $str
+#
+# Arguments:
+# str - partial tcl var name to expand
+#
+# Calls: ::tk::console::ExpandBestMatch
+#
+# Returns: list containing longest unique match followed by all the
+# possible further matches
+
+proc ::tk::console::ExpandVariable str {
+ if {[regexp {([^\(]*)\((.*)} $str -> ary str]} {
+ ## Looks like they're trying to expand an array.
+ set match [EvalAttached [list array names $ary $str*]]
+ if {[llength $match] > 1} {
+ set vars $ary\([ExpandBestMatch $match $str]
+ foreach var $match {
+ lappend vars $ary\($var\)
+ }
+ return $vars
+ } elseif {[llength $match] == 1} {
+ set match $ary\($match\)
+ }
+ ## Space transformation avoided for array names.
+ } else {
+ set match [EvalAttached [list info vars $str*]]
+ if {[llength $match] > 1} {
+ regsub -all { } [ExpandBestMatch $match $str] {\\ } str
+ set match [linsert $match 0 $str]
+ } else {
+ regsub -all { } $match {\\ } match
+ }
+ }
+ return $match
+}
+
+# ::tk::console::ExpandBestMatch --
+#
+# Finds the best unique match in a list of names.
+# The extra $e in this argument allows us to limit the innermost loop a little
+# further. This improves speed as $l becomes large or $e becomes long.
+#
+# Arguments:
+# l - list to find best unique match in
+# e - currently best known unique match
+#
+# Returns: longest unique match in the list
+
+proc ::tk::console::ExpandBestMatch {l {e {}}} {
+ set ec [lindex $l 0]
+ if {[llength $l]>1} {
+ set e [expr {[string length $e] - 1}]
+ set ei [expr {[string length $ec] - 1}]
+ foreach l $l {
+ while {$ei>=$e && [string first $ec $l]} {
+ set ec [string range $ec 0 [incr ei -1]]
+ }
+ }
+ }
+ return $ec
+}
+
+# now initialize the console
+::tk::ConsoleInit
diff --git a/tk8.6/library/demos/README b/tk8.6/library/demos/README
new file mode 100644
index 0000000..7285a93
--- /dev/null
+++ b/tk8.6/library/demos/README
@@ -0,0 +1,44 @@
+This directory contains a collection of programs to demonstrate
+the features of the Tk toolkit. The programs are all scripts for
+"wish", a windowing shell. If wish has been installed on your path
+then you can invoke any of the programs in this directory just
+by typing its file name to your command shell under Unix. Otherwise
+invoke wish with the file as its first argument, e.g., "wish hello".
+The rest of this file contains a brief description of each program.
+Files with names ending in ".tcl" are procedure packages used by one
+or more of the demo programs; they can't be used as programs by
+themselves so they aren't described below.
+
+hello - Creates a single button; if you click on it, a message
+ is typed and the application terminates.
+
+widget - Contains a collection of demonstrations of the widgets
+ currently available in the Tk library. Most of the .tcl
+ files are scripts for individual demos available through
+ the "widget" program.
+
+ixset - A simple Tk-based wrapper for the "xset" program, which
+ allows you to interactively query and set various X options
+ such as mouse acceleration and bell volume. Thanks to
+ Pierre David for contributing this example.
+
+rolodex - A mock-up of a simple rolodex application. It has much of
+ the user interface for such an application but no back-end
+ database. This program was written in response to Tom
+ LaStrange's toolkit benchmark challenge.
+
+tcolor - A color editor. Allows you to edit colors in several
+ different ways, and will also perform automatic updates
+ using "send".
+
+rmt - Allows you to "hook-up" remotely to any Tk application
+ on the display. Select an application with the menu,
+ then just type commands: they'll go to that application.
+
+timer - Displays a seconds timer with start and stop buttons.
+ Control-c and control-q cause it to exit.
+
+browse - A simple directory browser. Invoke it with and argument
+ giving the name of the directory you'd like to browse.
+ Double-click on files or subdirectories to browse them.
+ Control-c and control-q cause the program to exit.
diff --git a/tk8.6/library/demos/anilabel.tcl b/tk8.6/library/demos/anilabel.tcl
new file mode 100644
index 0000000..61e6315
--- /dev/null
+++ b/tk8.6/library/demos/anilabel.tcl
@@ -0,0 +1,160 @@
+# anilabel.tcl --
+#
+# This demonstration script creates a toplevel window containing
+# several animated label widgets.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .anilabel
+catch {destroy $w}
+toplevel $w
+wm title $w "Animated Label Demonstration"
+wm iconname $w "anilabel"
+positionWindow $w
+
+label $w.msg -font $font -wraplength 4i -justify left -text "Four animated labels are displayed below; each of the labels on the left is animated by making the text message inside it appear to scroll, and the label on the right is animated by animating the image that it displays."
+pack $w.msg -side top
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+# Ensure that this this is an array
+array set animationCallbacks {}
+
+## This callback is the core of how to do animation in Tcl/Tk; all
+## animations work in basically the same way, with a procedure that
+## uses the [after] command to reschedule itself at some point in the
+## future. Of course, the details of how to update the state will vary
+## according to what is being animated.
+proc RotateLabelText {w interval} {
+ global animationCallbacks
+
+ # Schedule the calling of this procedure again in the future
+ set animationCallbacks($w) [after $interval RotateLabelText $w $interval]
+
+ # We do marquee-like scrolling text by chopping characters off the
+ # front of the text and sticking them on the end.
+ set text [$w cget -text]
+ set newText [string range $text 1 end][string index $text 0]
+ $w configure -text $newText
+}
+
+## A helper procedure to start the animation happening.
+proc animateLabelText {w text interval} {
+ global animationCallbacks
+
+ # Install the text into the widget
+ $w configure -text $text
+
+ # Schedule the start of the animation loop
+ set animationCallbacks($w) [after $interval RotateLabelText $w $interval]
+
+ # Make sure that the animation stops and is cleaned up after itself
+ # when the animated label is destroyed. Note that at this point we
+ # cannot manipulate the widget itself, as that has already died.
+ bind $w <Destroy> {
+ after cancel $animationCallbacks(%W)
+ unset animationCallbacks(%W)
+ }
+}
+
+## Next, a similar pair of procedures to animate a GIF loaded into a
+## photo image.
+proc SelectNextImageFrame {w interval} {
+ global animationCallbacks
+ set animationCallbacks($w) \
+ [after $interval SelectNextImageFrame $w $interval]
+ set image [$w cget -image]
+
+ # The easy way to animate a GIF!
+ set idx -1
+ scan [$image cget -format] "GIF -index %d" idx
+ if {[catch {
+ # Note that we get an error if the index is out of range
+ $image configure -format "GIF -index [incr idx]"
+ }]} then {
+ $image configure -format "GIF -index 0"
+ }
+}
+proc animateLabelImage {w imageData interval} {
+ global animationCallbacks
+
+ # Create a multi-frame GIF from base-64-encoded data
+ set image [image create photo -format GIF -data $imageData]
+
+ # Install the image into the widget
+ $w configure -image $image
+
+ # Schedule the start of the animation loop
+ set animationCallbacks($w) \
+ [after $interval SelectNextImageFrame $w $interval]
+
+ # Make sure that the animation stops and is cleaned up after itself
+ # when the animated label is destroyed. Note that at this point we
+ # cannot manipulate the widget itself, as that has already died.
+ # Also note that this script is in double-quotes; this is always OK
+ # because image names are chosen automatically to be simple words.
+ bind $w <Destroy> "
+ after cancel \$animationCallbacks(%W)
+ unset animationCallbacks(%W)
+ rename $image {}
+ "
+}
+
+# Make some widgets to contain the animations
+labelframe $w.left -text "Scrolling Texts"
+labelframe $w.right -text "GIF Image"
+pack $w.left $w.right -side left -padx 10 -pady 10 -expand yes
+
+# This method of scrolling text looks far better with a fixed-width font
+label $w.left.l1 -bd 4 -relief ridge -font fixedFont
+label $w.left.l2 -bd 4 -relief groove -font fixedFont
+label $w.left.l3 -bd 4 -relief flat -font fixedFont -width 18
+pack $w.left.l1 $w.left.l2 $w.left.l3 -side top -expand yes -padx 10 -pady 10 -anchor w
+# Don't need to do very much with this label except turn off the border
+label $w.right.l -bd 0
+pack $w.right.l -side top -expand yes -padx 10 -pady 10
+
+# This is a base-64-encoded animated GIF file.
+set tclPoweredData {
+ R0lGODlhKgBAAPQAAP//////zP//AP/MzP/Mmf/MAP+Zmf+ZZv+ZAMz//8zM
+ zMyZmcyZZsxmZsxmAMwzAJnMzJmZzJmZmZlmmZlmZplmM5kzM2aZzGZmzGZm
+ mWZmZmYzZmYzMzNmzDMzZgAzmSH+IE1hZGUgd2l0aCBHSU1QIGJ5IExARGVt
+ YWlsbHkuY29tACH5BAVkAAEALAAAAAAqAEAAAAX+YCCOZEkyTKM2jOm66yPP
+ dF03bx7YcuHIDkGBR7SZeIyhTID4FZ+4Es8nQyCe2EeUNJ0peY2s9mi7PhAM
+ ngEAMGRbUpvzSxskLh1J+Hkg134OdDIDEB+GHxtYMEQMTjMGEYeGFoomezaC
+ DZGSHFmLXTQKkh8eNQVpZ2afmDQGHaOYSoEyhhcklzVmMpuHnaZmDqiGJbg0
+ qFqvh6UNAwB7VA+OwydEjgujkgrPNhbTI8dFvNgEYcHcHx0lB1kX2IYeA2G6
+ NN0YfkXJ2BsAMuAzHB9cZMk3qoEbRzUACsRCUBK5JxsC3iMiKd8GN088SIyT
+ 0RAFSROyeEg38caDiB/+JEgqxsODrZJ1BkT0oHKSmI0ceQxo94HDpg0qsuDk
+ UmRAMgu8OgwQ+uIJgUMVeGXA+IQkzEeHGvD8cIGlDXsLiRjQ+EHroQhea7xY
+ 8IQBSgYYDi1IS+OFBCgaDMGVS3fGi5BPJpBaENdQ0EomKGD56IHwO39EXiSC
+ Ysgxor5+Xfgq0qByYUpiXmwuoredB2aYH4gWWda0B7SeNENpEJHC1ghi+pS4
+ AJpIAwWvKPBi+8YEht5EriEqpFfMlhEdkBNpx0HUhwypx5T4IB1MBg/Ws2sn
+ wV3MSQOkzI8fUd48Aw3dOZto71x85hHtHijYv18Gf/3GqCdDCXHNoICBobSo
+ IqBqJLyCoH8JPrLgdh88CKCFD0CGmAiGYPgffwceZh6FC2ohIIklnkhehTNY
+ 4CIHHGzgwYw01ujBBhvAqKOLLq5AAk9kuSPkkKO40NB+h1gnypJIIvkBf09a
+ N5QIRz5p5ZJXJpmlIVhOGQA2TmIJZZhKKmmll2BqyWSXWUrZpQtpatlmk1c2
+ KaWRHeTZEJF8SqLDn/hhsOeQgBbqAh6DGqronxeARUIIACH5BAUeAAAALAUA
+ LgAFAAUAAAUM4CeKz/OV5YmqaRkCACH5BAUeAAEALAUALgAKAAUAAAUUICCK
+ z/OdJVCaa7p+7aOWcDvTZwgAIfkEBR4AAQAsCwAuAAkABQAABRPgA4zP95zA
+ eZqoWqqpyqLkZ38hACH5BAUKAAEALAcALgANAA4AAAU7ICA+jwiUJEqeKau+
+ r+vGaTmac63v/GP9HM7GQyx+jsgkkoRUHJ3Qx0cK/VQVTKtWwbVKn9suNunc
+ WkMAIfkEBQoAAAAsBwA3AAcABQAABRGgIHzk842j+Yjlt5KuO8JmCAAh+QQF
+ CgAAACwLADcABwAFAAAFEeAnfN9TjqP5oOWziq05lmUIACH5BAUKAAAALA8A
+ NwAHAAUAAAUPoPCJTymS3yiQj4qOcPmEACH5BAUKAAAALBMANwAHAAUAAAUR
+ oCB+z/MJX2o+I2miKimiawgAIfkEBQoAAAAsFwA3AAcABQAABRGgIHzfY47j
+ Q4qk+aHl+pZmCAAh+QQFCgAAACwbADcABwAFAAAFEaAgfs/zCV9qPiNJouo7
+ ll8IACH5BAUKAAAALB8ANwADAAUAAAUIoCB8o0iWZggAOw==
+}
+
+# Finally, set up the text scrolling animation
+animateLabelText $w.left.l1 "* Slow Animation *" 300
+animateLabelText $w.left.l2 "* Fast Animation *" 80
+animateLabelText $w.left.l3 "This is a longer scrolling text in a widget that will not show the whole message at once. " 150
+animateLabelImage $w.right.l $tclPoweredData 100
diff --git a/tk8.6/library/demos/aniwave.tcl b/tk8.6/library/demos/aniwave.tcl
new file mode 100644
index 0000000..a7539fb
--- /dev/null
+++ b/tk8.6/library/demos/aniwave.tcl
@@ -0,0 +1,104 @@
+# aniwave.tcl --
+#
+# This demonstration script illustrates how to adjust canvas item
+# coordinates in a way that does something fairly similar to waveform
+# display.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .aniwave
+catch {destroy $w}
+toplevel $w
+wm title $w "Animated Wave Demonstration"
+wm iconname $w "aniwave"
+positionWindow $w
+
+label $w.msg -font $font -wraplength 4i -justify left -text "This demonstration contains a canvas widget with a line item inside it. The animation routines work by adjusting the coordinates list of the line; a trace on a variable is used so updates to the variable result in a change of position of the line."
+pack $w.msg -side top
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+# Create a canvas large enough to hold the wave. In fact, the wave
+# sticks off both sides of the canvas to prevent visual glitches.
+pack [canvas $w.c -width 300 -height 200 -background black] -padx 10 -pady 10 -expand yes
+
+# Ensure that this this is an array
+array set animationCallbacks {}
+
+# Creates a coordinates list of a wave. This code does a very sketchy
+# job and relies on Tk's line smoothing to make things look better.
+set waveCoords {}
+for {set x -10} {$x<=300} {incr x 5} {
+ lappend waveCoords $x 100
+}
+lappend waveCoords $x 0 [incr x 5] 200
+
+# Create a smoothed line and arrange for its coordinates to be the
+# contents of the variable waveCoords.
+$w.c create line $waveCoords -tags wave -width 1 -fill green -smooth 1
+proc waveCoordsTracer {w args} {
+ global waveCoords
+ # Actual visual update will wait until we have finished
+ # processing; Tk does that for us automatically.
+ $w.c coords wave $waveCoords
+}
+trace add variable waveCoords write [list waveCoordsTracer $w]
+
+# Basic motion handler. Given what direction the wave is travelling
+# in, it advances the y coordinates in the coordinate-list one step in
+# that direction.
+proc basicMotion {} {
+ global waveCoords direction
+ set oc $waveCoords
+ for {set i 1} {$i<[llength $oc]} {incr i 2} {
+ if {$direction eq "left"} {
+ lset waveCoords $i [lindex $oc \
+ [expr {$i+2>[llength $oc] ? 1 : $i+2}]]
+ } else {
+ lset waveCoords $i \
+ [lindex $oc [expr {$i-2<0 ? "end" : $i-2}]]
+ }
+ }
+}
+
+# Oscillation handler. This detects whether to reverse the direction
+# of the wave by checking to see if the peak of the wave has moved off
+# the screen (whose size we know already.)
+proc reverser {} {
+ global waveCoords direction
+ if {[lindex $waveCoords 1] < 10} {
+ set direction "right"
+ } elseif {[lindex $waveCoords end] < 10} {
+ set direction "left"
+ }
+}
+
+# Main animation "loop". This calls the two procedures that handle the
+# movement repeatedly by scheduling asynchronous calls back to itself
+# using the [after] command. This procedure is the fundamental basis
+# for all animated effect handling in Tk.
+proc move {} {
+ basicMotion
+ reverser
+
+ # Theoretically 100 frames-per-second (==10ms between frames)
+ global animationCallbacks
+ set animationCallbacks(simpleWave) [after 10 move]
+}
+
+# Initialise our remaining animation variables
+set direction "left"
+set animateAfterCallback {}
+# Arrange for the animation loop to stop when the canvas is deleted
+bind $w.c <Destroy> {
+ after cancel $animationCallbacks(simpleWave)
+ unset animationCallbacks(simpleWave)
+}
+# Start the animation processing
+move
diff --git a/tk8.6/library/demos/arrow.tcl b/tk8.6/library/demos/arrow.tcl
new file mode 100644
index 0000000..5011f6f
--- /dev/null
+++ b/tk8.6/library/demos/arrow.tcl
@@ -0,0 +1,237 @@
+# arrow.tcl --
+#
+# This demonstration script creates a canvas widget that displays a
+# large line with an arrowhead whose shape can be edited interactively.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+# arrowSetup --
+# This procedure regenerates all the text and graphics in the canvas
+# window. It's called when the canvas is initially created, and also
+# whenever any of the parameters of the arrow head are changed
+# interactively.
+#
+# Arguments:
+# c - Name of the canvas widget.
+
+proc arrowSetup c {
+ upvar #0 demo_arrowInfo v
+
+ # Remember the current box, if there is one.
+
+ set tags [$c gettags current]
+ if {$tags != ""} {
+ set cur [lindex $tags [lsearch -glob $tags box?]]
+ } else {
+ set cur ""
+ }
+
+ # Create the arrow and outline.
+
+ $c delete all
+ eval {$c create line $v(x1) $v(y) $v(x2) $v(y) -arrow last \
+ -width [expr {10*$v(width)}] -arrowshape [list \
+ [expr {10*$v(a)}] [expr {10*$v(b)}] [expr {10*$v(c)}]]} \
+ $v(bigLineStyle)
+ set xtip [expr {$v(x2)-10*$v(b)}]
+ set deltaY [expr {10*$v(c)+5*$v(width)}]
+ $c create line $v(x2) $v(y) $xtip [expr {$v(y)+$deltaY}] \
+ [expr {$v(x2)-10*$v(a)}] $v(y) $xtip [expr {$v(y)-$deltaY}] \
+ $v(x2) $v(y) -width 2 -capstyle round -joinstyle round
+
+ # Create the boxes for reshaping the line and arrowhead.
+
+ eval {$c create rect [expr {$v(x2)-10*$v(a)-5}] [expr {$v(y)-5}] \
+ [expr {$v(x2)-10*$v(a)+5}] [expr {$v(y)+5}] \
+ -tags {box1 box}} $v(boxStyle)
+ eval {$c create rect [expr {$xtip-5}] [expr {$v(y)-$deltaY-5}] \
+ [expr {$xtip+5}] [expr {$v(y)-$deltaY+5}] \
+ -tags {box2 box}} $v(boxStyle)
+ eval {$c create rect [expr {$v(x1)-5}] [expr {$v(y)-5*$v(width)-5}] \
+ [expr {$v(x1)+5}] [expr {$v(y)-5*$v(width)+5}] \
+ -tags {box3 box}} $v(boxStyle)
+ if {$cur != ""} {
+ eval $c itemconfigure $cur $v(activeStyle)
+ }
+
+ # Create three arrows in actual size with the same parameters
+
+ $c create line [expr {$v(x2)+50}] 0 [expr {$v(x2)+50}] 1000 \
+ -width 2
+ set tmp [expr {$v(x2)+100}]
+ $c create line $tmp [expr {$v(y)-125}] $tmp [expr {$v(y)-75}] \
+ -width $v(width) \
+ -arrow both -arrowshape "$v(a) $v(b) $v(c)"
+ $c create line [expr {$tmp-25}] $v(y) [expr {$tmp+25}] $v(y) \
+ -width $v(width) \
+ -arrow both -arrowshape "$v(a) $v(b) $v(c)"
+ $c create line [expr {$tmp-25}] [expr {$v(y)+75}] [expr {$tmp+25}] \
+ [expr {$v(y)+125}] -width $v(width) \
+ -arrow both -arrowshape "$v(a) $v(b) $v(c)"
+
+ # Create a bunch of other arrows and text items showing the
+ # current dimensions.
+
+ set tmp [expr {$v(x2)+10}]
+ $c create line $tmp [expr {$v(y)-5*$v(width)}] \
+ $tmp [expr {$v(y)-$deltaY}] \
+ -arrow both -arrowshape $v(smallTips)
+ $c create text [expr {$v(x2)+15}] [expr {$v(y)-$deltaY+5*$v(c)}] \
+ -text $v(c) -anchor w
+ set tmp [expr {$v(x1)-10}]
+ $c create line $tmp [expr {$v(y)-5*$v(width)}] \
+ $tmp [expr {$v(y)+5*$v(width)}] \
+ -arrow both -arrowshape $v(smallTips)
+ $c create text [expr {$v(x1)-15}] $v(y) -text $v(width) -anchor e
+ set tmp [expr {$v(y)+5*$v(width)+10*$v(c)+10}]
+ $c create line [expr {$v(x2)-10*$v(a)}] $tmp $v(x2) $tmp \
+ -arrow both -arrowshape $v(smallTips)
+ $c create text [expr {$v(x2)-5*$v(a)}] [expr {$tmp+5}] \
+ -text $v(a) -anchor n
+ set tmp [expr {$tmp+25}]
+ $c create line [expr {$v(x2)-10*$v(b)}] $tmp $v(x2) $tmp \
+ -arrow both -arrowshape $v(smallTips)
+ $c create text [expr {$v(x2)-5*$v(b)}] [expr {$tmp+5}] \
+ -text $v(b) -anchor n
+
+ $c create text $v(x1) 310 -text "-width $v(width)" \
+ -anchor w -font {Helvetica 18}
+ $c create text $v(x1) 330 -text "-arrowshape {$v(a) $v(b) $v(c)}" \
+ -anchor w -font {Helvetica 18}
+
+ incr v(count)
+}
+
+set w .arrow
+catch {destroy $w}
+toplevel $w
+wm title $w "Arrowhead Editor Demonstration"
+wm iconname $w "arrow"
+positionWindow $w
+set c $w.c
+
+label $w.msg -font $font -wraplength 5i -justify left -text "This widget allows you to experiment with different widths and arrowhead shapes for lines in canvases. To change the line width or the shape of the arrowhead, drag any of the three boxes attached to the oversized arrow. The arrows on the right give examples at normal scale. The text at the bottom shows the configuration options as you'd enter them for a canvas line item."
+pack $w.msg -side top
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+canvas $c -width 500 -height 350 -relief sunken -borderwidth 2
+pack $c -expand yes -fill both
+
+set demo_arrowInfo(a) 8
+set demo_arrowInfo(b) 10
+set demo_arrowInfo(c) 3
+set demo_arrowInfo(width) 2
+set demo_arrowInfo(motionProc) arrowMoveNull
+set demo_arrowInfo(x1) 40
+set demo_arrowInfo(x2) 350
+set demo_arrowInfo(y) 150
+set demo_arrowInfo(smallTips) {5 5 2}
+set demo_arrowInfo(count) 0
+if {[winfo depth $c] > 1} {
+ set demo_arrowInfo(bigLineStyle) "-fill SkyBlue1"
+ set demo_arrowInfo(boxStyle) "-fill {} -outline black -width 1"
+ set demo_arrowInfo(activeStyle) "-fill red -outline black -width 1"
+} else {
+ # Main widget program sets variable tk_demoDirectory
+ set demo_arrowInfo(bigLineStyle) "-fill black \
+ -stipple @[file join $tk_demoDirectory images grey.25]"
+ set demo_arrowInfo(boxStyle) "-fill {} -outline black -width 1"
+ set demo_arrowInfo(activeStyle) "-fill black -outline black -width 1"
+}
+arrowSetup $c
+$c bind box <Enter> "$c itemconfigure current $demo_arrowInfo(activeStyle)"
+$c bind box <Leave> "$c itemconfigure current $demo_arrowInfo(boxStyle)"
+$c bind box <B1-Enter> " "
+$c bind box <B1-Leave> " "
+$c bind box1 <1> {set demo_arrowInfo(motionProc) arrowMove1}
+$c bind box2 <1> {set demo_arrowInfo(motionProc) arrowMove2}
+$c bind box3 <1> {set demo_arrowInfo(motionProc) arrowMove3}
+$c bind box <B1-Motion> "\$demo_arrowInfo(motionProc) $c %x %y"
+bind $c <Any-ButtonRelease-1> "arrowSetup $c"
+
+# arrowMove1 --
+# This procedure is called for each mouse motion event on box1 (the
+# one at the vertex of the arrow). It updates the controlling parameters
+# for the line and arrowhead.
+#
+# Arguments:
+# c - The name of the canvas window.
+# x, y - The coordinates of the mouse.
+
+proc arrowMove1 {c x y} {
+ upvar #0 demo_arrowInfo v
+ set newA [expr {($v(x2)+5-round([$c canvasx $x]))/10}]
+ if {$newA < 0} {
+ set newA 0
+ }
+ if {$newA > 25} {
+ set newA 25
+ }
+ if {$newA != $v(a)} {
+ $c move box1 [expr {10*($v(a)-$newA)}] 0
+ set v(a) $newA
+ }
+}
+
+# arrowMove2 --
+# This procedure is called for each mouse motion event on box2 (the
+# one at the trailing tip of the arrowhead). It updates the controlling
+# parameters for the line and arrowhead.
+#
+# Arguments:
+# c - The name of the canvas window.
+# x, y - The coordinates of the mouse.
+
+proc arrowMove2 {c x y} {
+ upvar #0 demo_arrowInfo v
+ set newB [expr {($v(x2)+5-round([$c canvasx $x]))/10}]
+ if {$newB < 0} {
+ set newB 0
+ }
+ if {$newB > 25} {
+ set newB 25
+ }
+ set newC [expr {($v(y)+5-round([$c canvasy $y])-5*$v(width))/10}]
+ if {$newC < 0} {
+ set newC 0
+ }
+ if {$newC > 20} {
+ set newC 20
+ }
+ if {($newB != $v(b)) || ($newC != $v(c))} {
+ $c move box2 [expr {10*($v(b)-$newB)}] [expr {10*($v(c)-$newC)}]
+ set v(b) $newB
+ set v(c) $newC
+ }
+}
+
+# arrowMove3 --
+# This procedure is called for each mouse motion event on box3 (the
+# one that controls the thickness of the line). It updates the
+# controlling parameters for the line and arrowhead.
+#
+# Arguments:
+# c - The name of the canvas window.
+# x, y - The coordinates of the mouse.
+
+proc arrowMove3 {c x y} {
+ upvar #0 demo_arrowInfo v
+ set newWidth [expr {($v(y)+2-round([$c canvasy $y]))/5}]
+ if {$newWidth < 0} {
+ set newWidth 0
+ }
+ if {$newWidth > 20} {
+ set newWidth 20
+ }
+ if {$newWidth != $v(width)} {
+ $c move box3 0 [expr {5*($v(width)-$newWidth)}]
+ set v(width) $newWidth
+ }
+}
diff --git a/tk8.6/library/demos/bind.tcl b/tk8.6/library/demos/bind.tcl
new file mode 100644
index 0000000..03f6d3b
--- /dev/null
+++ b/tk8.6/library/demos/bind.tcl
@@ -0,0 +1,78 @@
+# bind.tcl --
+#
+# This demonstration script creates a text widget with bindings set
+# up for hypertext-like effects.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .bind
+catch {destroy $w}
+toplevel $w
+wm title $w "Text Demonstration - Tag Bindings"
+wm iconname $w "bind"
+positionWindow $w
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+text $w.text -yscrollcommand "$w.scroll set" -setgrid true \
+ -width 60 -height 24 -font $font -wrap word
+ttk::scrollbar $w.scroll -command "$w.text yview"
+pack $w.scroll -side right -fill y
+pack $w.text -expand yes -fill both
+
+# Set up display styles.
+
+if {[winfo depth $w] > 1} {
+ set bold "-background #43ce80 -relief raised -borderwidth 1"
+ set normal "-background {} -relief flat"
+} else {
+ set bold "-foreground white -background black"
+ set normal "-foreground {} -background {}"
+}
+
+# Add text to widget.
+
+$w.text insert 0.0 {\
+The same tag mechanism that controls display styles in text widgets can also be used to associate Tcl commands with regions of text, so that mouse or keyboard actions on the text cause particular Tcl commands to be invoked. For example, in the text below the descriptions of the canvas demonstrations have been tagged. When you move the mouse over a demo description the description lights up, and when you press button 1 over a description then that particular demonstration is invoked.
+
+}
+$w.text insert end \
+{1. Samples of all the different types of items that can be created in canvas widgets.} d1
+$w.text insert end \n\n
+$w.text insert end \
+{2. A simple two-dimensional plot that allows you to adjust the positions of the data points.} d2
+$w.text insert end \n\n
+$w.text insert end \
+{3. Anchoring and justification modes for text items.} d3
+$w.text insert end \n\n
+$w.text insert end \
+{4. An editor for arrow-head shapes for line items.} d4
+$w.text insert end \n\n
+$w.text insert end \
+{5. A ruler with facilities for editing tab stops.} d5
+$w.text insert end \n\n
+$w.text insert end \
+{6. A grid that demonstrates how canvases can be scrolled.} d6
+
+# Create bindings for tags.
+
+foreach tag {d1 d2 d3 d4 d5 d6} {
+ $w.text tag bind $tag <Any-Enter> "$w.text tag configure $tag $bold"
+ $w.text tag bind $tag <Any-Leave> "$w.text tag configure $tag $normal"
+}
+# Main widget program sets variable tk_demoDirectory
+$w.text tag bind d1 <1> {source [file join $tk_demoDirectory items.tcl]}
+$w.text tag bind d2 <1> {source [file join $tk_demoDirectory plot.tcl]}
+$w.text tag bind d3 <1> {source [file join $tk_demoDirectory ctext.tcl]}
+$w.text tag bind d4 <1> {source [file join $tk_demoDirectory arrow.tcl]}
+$w.text tag bind d5 <1> {source [file join $tk_demoDirectory ruler.tcl]}
+$w.text tag bind d6 <1> {source [file join $tk_demoDirectory cscroll.tcl]}
+
+$w.text mark set insert 0.0
+$w.text configure -state disabled
diff --git a/tk8.6/library/demos/bitmap.tcl b/tk8.6/library/demos/bitmap.tcl
new file mode 100644
index 0000000..453987d
--- /dev/null
+++ b/tk8.6/library/demos/bitmap.tcl
@@ -0,0 +1,52 @@
+# bitmap.tcl --
+#
+# This demonstration script creates a toplevel window that displays
+# all of Tk's built-in bitmaps.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+# bitmapRow --
+# Create a row of bitmap items in a window.
+#
+# Arguments:
+# w - The window that is to contain the row.
+# args - The names of one or more bitmaps, which will be displayed
+# in a new row across the bottom of w along with their
+# names.
+
+proc bitmapRow {w args} {
+ frame $w
+ pack $w -side top -fill both
+ set i 0
+ foreach bitmap $args {
+ frame $w.$i
+ pack $w.$i -side left -fill both -pady .25c -padx .25c
+ label $w.$i.bitmap -bitmap $bitmap
+ label $w.$i.label -text $bitmap -width 9
+ pack $w.$i.label $w.$i.bitmap -side bottom
+ incr i
+ }
+}
+
+set w .bitmap
+catch {destroy $w}
+toplevel $w
+wm title $w "Bitmap Demonstration"
+wm iconname $w "bitmap"
+positionWindow $w
+
+label $w.msg -font $font -wraplength 4i -justify left -text "This window displays all of Tk's built-in bitmaps, along with the names you can use for them in Tcl scripts."
+pack $w.msg -side top
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+frame $w.frame
+bitmapRow $w.frame.0 error gray12 gray25 gray50 gray75
+bitmapRow $w.frame.1 hourglass info question questhead warning
+pack $w.frame -side top -expand yes -fill both
diff --git a/tk8.6/library/demos/browse b/tk8.6/library/demos/browse
new file mode 100644
index 0000000..d107f28
--- /dev/null
+++ b/tk8.6/library/demos/browse
@@ -0,0 +1,66 @@
+#!/bin/sh
+# the next line restarts using wish \
+exec wish "$0" ${1+"$@"}
+
+# browse --
+# This script generates a directory browser, which lists the working
+# directory and allows you to open files or subdirectories by
+# double-clicking.
+
+package require Tk
+
+# Create a scrollbar on the right side of the main window and a listbox
+# on the left side.
+
+scrollbar .scroll -command ".list yview"
+pack .scroll -side right -fill y
+listbox .list -yscroll ".scroll set" -relief sunken -width 20 -height 20 \
+ -setgrid yes
+pack .list -side left -fill both -expand yes
+wm minsize . 1 1
+
+# The procedure below is invoked to open a browser on a given file; if the
+# file is a directory then another instance of this program is invoked; if
+# the file is a regular file then the Mx editor is invoked to display
+# the file.
+
+set browseScript [file join [pwd] $argv0]
+proc browse {dir file} {
+ global env browseScript
+ if {[string compare $dir "."] != 0} {set file $dir/$file}
+ switch [file type $file] {
+ directory {
+ exec [info nameofexecutable] $browseScript $file &
+ }
+ file {
+ if {[info exists env(EDITOR)]} {
+ eval exec $env(EDITOR) $file &
+ } else {
+ exec xedit $file &
+ }
+ }
+ default {
+ puts stdout "\"$file\" isn't a directory or regular file"
+ }
+ }
+}
+
+# Fill the listbox with a list of all the files in the directory.
+
+if {$argc>0} {set dir [lindex $argv 0]} else {set dir "."}
+foreach i [lsort [glob * .* *.*]] {
+ if {[file type $i] eq "directory"} {
+ # Safe to do since it is still a directory.
+ append i /
+ }
+ .list insert end $i
+}
+
+# Set up bindings for the browser.
+
+bind all <Control-c> {destroy .}
+bind .list <Double-Button-1> {foreach i [selection get] {browse $dir $i}}
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tk8.6/library/demos/button.tcl b/tk8.6/library/demos/button.tcl
new file mode 100644
index 0000000..bb943e6
--- /dev/null
+++ b/tk8.6/library/demos/button.tcl
@@ -0,0 +1,47 @@
+# button.tcl --
+#
+# This demonstration script creates a toplevel window containing
+# several button widgets.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .button
+catch {destroy $w}
+toplevel $w
+wm title $w "Button Demonstration"
+wm iconname $w "button"
+positionWindow $w
+
+label $w.msg -font $font -wraplength 4i -justify left -text "If you click on any of the four buttons below, the background of the button area will change to the color indicated in the button. You can press Tab to move among the buttons, then press Space to invoke the current button."
+pack $w.msg -side top
+
+## See Code / Dismiss buttons
+pack [addSeeDismiss $w.buttons $w] -side bottom -fill x
+
+proc colorrefresh {w col} {
+ $w configure -bg $col
+ if {[tk windowingsystem] eq "aqua"} {
+ # set highlightbackground of all buttons in $w
+ set l [list $w]
+ while {[llength $l]} {
+ set l [concat [lassign $l b] [winfo children $b]]
+ if {[winfo class $b] eq "Button"} {
+ $b configure -highlightbackground $col
+ }
+ }
+ }
+}
+
+button $w.b1 -text "Peach Puff" -width 10 \
+ -command [list colorrefresh $w PeachPuff1]
+button $w.b2 -text "Light Blue" -width 10 \
+ -command [list colorrefresh $w LightBlue1]
+button $w.b3 -text "Sea Green" -width 10 \
+ -command [list colorrefresh $w SeaGreen2]
+button $w.b4 -text "Yellow" -width 10 \
+ -command [list colorrefresh $w Yellow1]
+pack $w.b1 $w.b2 $w.b3 $w.b4 -side top -expand yes -pady 2
diff --git a/tk8.6/library/demos/check.tcl b/tk8.6/library/demos/check.tcl
new file mode 100644
index 0000000..c072096
--- /dev/null
+++ b/tk8.6/library/demos/check.tcl
@@ -0,0 +1,71 @@
+# check.tcl --
+#
+# This demonstration script creates a toplevel window containing
+# several checkbuttons.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .check
+catch {destroy $w}
+toplevel $w
+wm title $w "Checkbutton Demonstration"
+wm iconname $w "check"
+positionWindow $w
+
+label $w.msg -font $font -wraplength 4i -justify left -text "Four checkbuttons are displayed below. If you click on a button, it will toggle the button's selection state and set a Tcl variable to a value indicating the state of the checkbutton. The first button also follows the state of the other three. If only some of the three are checked, the first button will display the tri-state mode. Click the \"See Variables\" button to see the current values of the variables."
+pack $w.msg -side top
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w [list safety wipers brakes sober]]
+pack $btns -side bottom -fill x
+
+checkbutton $w.b0 -text "Safety Check" -variable safety -relief flat \
+ -onvalue "all" \
+ -offvalue "none" \
+ -tristatevalue "partial"
+checkbutton $w.b1 -text "Wipers OK" -variable wipers -relief flat
+checkbutton $w.b2 -text "Brakes OK" -variable brakes -relief flat
+checkbutton $w.b3 -text "Driver Sober" -variable sober -relief flat
+pack $w.b0 -side top -pady 2 -anchor w
+pack $w.b1 $w.b2 $w.b3 -side top -pady 2 -anchor w -padx 15
+
+## This code makes $w.b0 function as a tri-state button; it's not
+## needed at all for just straight yes/no buttons.
+
+set in_check 0
+proc tristate_check {n1 n2 op} {
+ global safety wipers brakes sober in_check
+ if {$in_check} {
+ return
+ }
+ set in_check 1
+ if {$n1 eq "safety"} {
+ if {$safety eq "none"} {
+ set wipers 0
+ set brakes 0
+ set sober 0
+ } elseif {$safety eq "all"} {
+ set wipers 1
+ set brakes 1
+ set sober 1
+ }
+ } else {
+ if {$wipers == 1 && $brakes == 1 && $sober == 1} {
+ set safety all
+ } elseif {$wipers == 1 || $brakes == 1 || $sober == 1} {
+ set safety partial
+ } else {
+ set safety none
+ }
+ }
+ set in_check 0
+}
+
+trace variable wipers w tristate_check
+trace variable brakes w tristate_check
+trace variable sober w tristate_check
+trace variable safety w tristate_check
diff --git a/tk8.6/library/demos/clrpick.tcl b/tk8.6/library/demos/clrpick.tcl
new file mode 100644
index 0000000..ba50b75
--- /dev/null
+++ b/tk8.6/library/demos/clrpick.tcl
@@ -0,0 +1,54 @@
+# clrpick.tcl --
+#
+# This demonstration script prompts the user to select a color.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .clrpick
+catch {destroy $w}
+toplevel $w
+wm title $w "Color Selection Dialog"
+wm iconname $w "colors"
+positionWindow $w
+
+label $w.msg -font $font -wraplength 4i -justify left -text "Press the buttons below to choose the foreground and background colors for the widgets in this window."
+pack $w.msg -side top
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+button $w.back -text "Set background color ..." \
+ -command \
+ "setColor $w $w.back background {-background -highlightbackground}"
+button $w.fore -text "Set foreground color ..." \
+ -command \
+ "setColor $w $w.back foreground -foreground"
+
+pack $w.back $w.fore -side top -anchor c -pady 2m
+
+proc setColor {w button name options} {
+ grab $w
+ set initialColor [$button cget -$name]
+ set color [tk_chooseColor -title "Choose a $name color" -parent $w \
+ -initialcolor $initialColor]
+ if {[string compare $color ""]} {
+ setColor_helper $w $options $color
+ }
+ grab release $w
+}
+
+proc setColor_helper {w options color} {
+ foreach option $options {
+ catch {
+ $w config $option $color
+ }
+ }
+ foreach child [winfo children $w] {
+ setColor_helper $child $options $color
+ }
+}
diff --git a/tk8.6/library/demos/colors.tcl b/tk8.6/library/demos/colors.tcl
new file mode 100644
index 0000000..99dec92
--- /dev/null
+++ b/tk8.6/library/demos/colors.tcl
@@ -0,0 +1,99 @@
+# colors.tcl --
+#
+# This demonstration script creates a listbox widget that displays
+# many of the colors from the X color database. You can click on
+# a color to change the application's palette.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .colors
+catch {destroy $w}
+toplevel $w
+wm title $w "Listbox Demonstration (colors)"
+wm iconname $w "Listbox"
+positionWindow $w
+
+label $w.msg -font $font -wraplength 4i -justify left -text "A listbox containing several color names is displayed below, along with a scrollbar. You can scan the list either using the scrollbar or by dragging in the listbox window with button 2 pressed. If you double-click button 1 on a color, then the application's color palette will be set to match that color"
+pack $w.msg -side top
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+frame $w.frame -borderwidth 10
+pack $w.frame -side top -expand yes -fill y
+
+scrollbar $w.frame.scroll -command "$w.frame.list yview"
+listbox $w.frame.list -yscroll "$w.frame.scroll set" \
+ -width 20 -height 16 -setgrid 1
+pack $w.frame.list $w.frame.scroll -side left -fill y -expand 1
+
+bind $w.frame.list <Double-1> {
+ tk_setPalette [selection get]
+}
+$w.frame.list insert 0 gray60 gray70 gray80 gray85 gray90 gray95 \
+ snow1 snow2 snow3 snow4 seashell1 seashell2 \
+ seashell3 seashell4 AntiqueWhite1 AntiqueWhite2 AntiqueWhite3 \
+ AntiqueWhite4 bisque1 bisque2 bisque3 bisque4 PeachPuff1 \
+ PeachPuff2 PeachPuff3 PeachPuff4 NavajoWhite1 NavajoWhite2 \
+ NavajoWhite3 NavajoWhite4 LemonChiffon1 LemonChiffon2 \
+ LemonChiffon3 LemonChiffon4 cornsilk1 cornsilk2 cornsilk3 \
+ cornsilk4 ivory1 ivory2 ivory3 ivory4 honeydew1 honeydew2 \
+ honeydew3 honeydew4 LavenderBlush1 LavenderBlush2 \
+ LavenderBlush3 LavenderBlush4 MistyRose1 MistyRose2 \
+ MistyRose3 MistyRose4 azure1 azure2 azure3 azure4 \
+ SlateBlue1 SlateBlue2 SlateBlue3 SlateBlue4 RoyalBlue1 \
+ RoyalBlue2 RoyalBlue3 RoyalBlue4 blue1 blue2 blue3 blue4 \
+ DodgerBlue1 DodgerBlue2 DodgerBlue3 DodgerBlue4 SteelBlue1 \
+ SteelBlue2 SteelBlue3 SteelBlue4 DeepSkyBlue1 DeepSkyBlue2 \
+ DeepSkyBlue3 DeepSkyBlue4 SkyBlue1 SkyBlue2 SkyBlue3 \
+ SkyBlue4 LightSkyBlue1 LightSkyBlue2 LightSkyBlue3 \
+ LightSkyBlue4 SlateGray1 SlateGray2 SlateGray3 SlateGray4 \
+ LightSteelBlue1 LightSteelBlue2 LightSteelBlue3 \
+ LightSteelBlue4 LightBlue1 LightBlue2 LightBlue3 \
+ LightBlue4 LightCyan1 LightCyan2 LightCyan3 LightCyan4 \
+ PaleTurquoise1 PaleTurquoise2 PaleTurquoise3 PaleTurquoise4 \
+ CadetBlue1 CadetBlue2 CadetBlue3 CadetBlue4 turquoise1 \
+ turquoise2 turquoise3 turquoise4 cyan1 cyan2 cyan3 cyan4 \
+ DarkSlateGray1 DarkSlateGray2 DarkSlateGray3 \
+ DarkSlateGray4 aquamarine1 aquamarine2 aquamarine3 \
+ aquamarine4 DarkSeaGreen1 DarkSeaGreen2 DarkSeaGreen3 \
+ DarkSeaGreen4 SeaGreen1 SeaGreen2 SeaGreen3 SeaGreen4 \
+ PaleGreen1 PaleGreen2 PaleGreen3 PaleGreen4 SpringGreen1 \
+ SpringGreen2 SpringGreen3 SpringGreen4 green1 green2 \
+ green3 green4 chartreuse1 chartreuse2 chartreuse3 \
+ chartreuse4 OliveDrab1 OliveDrab2 OliveDrab3 OliveDrab4 \
+ DarkOliveGreen1 DarkOliveGreen2 DarkOliveGreen3 \
+ DarkOliveGreen4 khaki1 khaki2 khaki3 khaki4 \
+ LightGoldenrod1 LightGoldenrod2 LightGoldenrod3 \
+ LightGoldenrod4 LightYellow1 LightYellow2 LightYellow3 \
+ LightYellow4 yellow1 yellow2 yellow3 yellow4 gold1 gold2 \
+ gold3 gold4 goldenrod1 goldenrod2 goldenrod3 goldenrod4 \
+ DarkGoldenrod1 DarkGoldenrod2 DarkGoldenrod3 DarkGoldenrod4 \
+ RosyBrown1 RosyBrown2 RosyBrown3 RosyBrown4 IndianRed1 \
+ IndianRed2 IndianRed3 IndianRed4 sienna1 sienna2 sienna3 \
+ sienna4 burlywood1 burlywood2 burlywood3 burlywood4 wheat1 \
+ wheat2 wheat3 wheat4 tan1 tan2 tan3 tan4 chocolate1 \
+ chocolate2 chocolate3 chocolate4 firebrick1 firebrick2 \
+ firebrick3 firebrick4 brown1 brown2 brown3 brown4 salmon1 \
+ salmon2 salmon3 salmon4 LightSalmon1 LightSalmon2 \
+ LightSalmon3 LightSalmon4 orange1 orange2 orange3 orange4 \
+ DarkOrange1 DarkOrange2 DarkOrange3 DarkOrange4 coral1 \
+ coral2 coral3 coral4 tomato1 tomato2 tomato3 tomato4 \
+ OrangeRed1 OrangeRed2 OrangeRed3 OrangeRed4 red1 red2 red3 \
+ red4 DeepPink1 DeepPink2 DeepPink3 DeepPink4 HotPink1 \
+ HotPink2 HotPink3 HotPink4 pink1 pink2 pink3 pink4 \
+ LightPink1 LightPink2 LightPink3 LightPink4 PaleVioletRed1 \
+ PaleVioletRed2 PaleVioletRed3 PaleVioletRed4 maroon1 \
+ maroon2 maroon3 maroon4 VioletRed1 VioletRed2 VioletRed3 \
+ VioletRed4 magenta1 magenta2 magenta3 magenta4 orchid1 \
+ orchid2 orchid3 orchid4 plum1 plum2 plum3 plum4 \
+ MediumOrchid1 MediumOrchid2 MediumOrchid3 MediumOrchid4 \
+ DarkOrchid1 DarkOrchid2 DarkOrchid3 DarkOrchid4 purple1 \
+ purple2 purple3 purple4 MediumPurple1 MediumPurple2 \
+ MediumPurple3 MediumPurple4 thistle1 thistle2 thistle3 \
+ thistle4
diff --git a/tk8.6/library/demos/combo.tcl b/tk8.6/library/demos/combo.tcl
new file mode 100644
index 0000000..8631904
--- /dev/null
+++ b/tk8.6/library/demos/combo.tcl
@@ -0,0 +1,61 @@
+# combo.tcl --
+#
+# This demonstration script creates several combobox widgets.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .combo
+catch {destroy $w}
+toplevel $w
+wm title $w "Combobox Demonstration"
+wm iconname $w "combo"
+positionWindow $w
+
+ttk::label $w.msg -font $font -wraplength 5i -justify left -text "Three different\
+ combo-boxes are displayed below. You can add characters to the first\
+ one by pointing, clicking and typing, just as with an entry; pressing\
+ Return will cause the current value to be added to the list that is\
+ selectable from the drop-down list, and you can choose other values\
+ by pressing the Down key, using the arrow keys to pick another one,\
+ and pressing Return again. The second combo-box is fixed to a\
+ particular value, and cannot be modified at all. The third one only\
+ allows you to select values from its drop-down list of Australian\
+ cities."
+pack $w.msg -side top -fill x
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w {firstValue secondValue ozCity}]
+pack $btns -side bottom -fill x
+
+ttk::frame $w.f
+pack $w.f -fill both -expand 1
+set w $w.f
+
+set australianCities {
+ Canberra Sydney Melbourne Perth Adelaide Brisbane
+ Hobart Darwin "Alice Springs"
+}
+set secondValue unchangable
+set ozCity Sydney
+
+ttk::labelframe $w.c1 -text "Fully Editable"
+ttk::combobox $w.c1.c -textvariable firstValue
+ttk::labelframe $w.c2 -text Disabled
+ttk::combobox $w.c2.c -textvariable secondValue -state disabled
+ttk::labelframe $w.c3 -text "Defined List Only"
+ttk::combobox $w.c3.c -textvariable ozCity -state readonly \
+ -values $australianCities
+bind $w.c1.c <Return> {
+ if {[%W get] ni [%W cget -values]} {
+ %W configure -values [concat [%W cget -values] [list [%W get]]]
+ }
+}
+
+pack $w.c1 $w.c2 $w.c3 -side top -pady 5 -padx 10
+pack $w.c1.c -pady 5 -padx 10
+pack $w.c2.c -pady 5 -padx 10
+pack $w.c3.c -pady 5 -padx 10
diff --git a/tk8.6/library/demos/cscroll.tcl b/tk8.6/library/demos/cscroll.tcl
new file mode 100644
index 0000000..f6e88f4
--- /dev/null
+++ b/tk8.6/library/demos/cscroll.tcl
@@ -0,0 +1,108 @@
+# cscroll.tcl --
+#
+# This demonstration script creates a simple canvas that can be
+# scrolled in two dimensions.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .cscroll
+catch {destroy $w}
+toplevel $w
+wm title $w "Scrollable Canvas Demonstration"
+wm iconname $w "cscroll"
+positionWindow $w
+set c $w.c
+
+label $w.msg -font $font -wraplength 4i -justify left -text "This window displays a canvas widget that can be scrolled either using the scrollbars or by dragging with button 2 in the canvas. If you click button 1 on one of the rectangles, its indices will be printed on stdout."
+pack $w.msg -side top
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+frame $w.grid
+scrollbar $w.hscroll -orient horiz -command "$c xview"
+scrollbar $w.vscroll -command "$c yview"
+canvas $c -relief sunken -borderwidth 2 -scrollregion {-11c -11c 50c 20c} \
+ -xscrollcommand "$w.hscroll set" \
+ -yscrollcommand "$w.vscroll set"
+pack $w.grid -expand yes -fill both -padx 1 -pady 1
+grid rowconfig $w.grid 0 -weight 1 -minsize 0
+grid columnconfig $w.grid 0 -weight 1 -minsize 0
+
+grid $c -padx 1 -in $w.grid -pady 1 \
+ -row 0 -column 0 -rowspan 1 -columnspan 1 -sticky news
+grid $w.vscroll -in $w.grid -padx 1 -pady 1 \
+ -row 0 -column 1 -rowspan 1 -columnspan 1 -sticky news
+grid $w.hscroll -in $w.grid -padx 1 -pady 1 \
+ -row 1 -column 0 -rowspan 1 -columnspan 1 -sticky news
+
+
+set bg [lindex [$c config -bg] 4]
+for {set i 0} {$i < 20} {incr i} {
+ set x [expr {-10 + 3*$i}]
+ for {set j 0; set y -10} {$j < 10} {incr j; incr y 3} {
+ $c create rect ${x}c ${y}c [expr {$x+2}]c [expr {$y+2}]c \
+ -outline black -fill $bg -tags rect
+ $c create text [expr {$x+1}]c [expr {$y+1}]c -text "$i,$j" \
+ -anchor center -tags text
+ }
+}
+
+$c bind all <Any-Enter> "scrollEnter $c"
+$c bind all <Any-Leave> "scrollLeave $c"
+$c bind all <1> "scrollButton $c"
+bind $c <2> "$c scan mark %x %y"
+bind $c <B2-Motion> "$c scan dragto %x %y"
+if {[tk windowingsystem] eq "aqua"} {
+ bind $c <MouseWheel> {
+ %W yview scroll [expr {- (%D)}] units
+ }
+ bind $c <Option-MouseWheel> {
+ %W yview scroll [expr {-10 * (%D)}] units
+ }
+ bind $c <Shift-MouseWheel> {
+ %W xview scroll [expr {- (%D)}] units
+ }
+ bind $c <Shift-Option-MouseWheel> {
+ %W xview scroll [expr {-10 * (%D)}] units
+ }
+}
+
+proc scrollEnter canvas {
+ global oldFill
+ set id [$canvas find withtag current]
+ if {[lsearch [$canvas gettags current] text] >= 0} {
+ set id [expr {$id-1}]
+ }
+ set oldFill [lindex [$canvas itemconfig $id -fill] 4]
+ if {[winfo depth $canvas] > 1} {
+ $canvas itemconfigure $id -fill SeaGreen1
+ } else {
+ $canvas itemconfigure $id -fill black
+ $canvas itemconfigure [expr {$id+1}] -fill white
+ }
+}
+
+proc scrollLeave canvas {
+ global oldFill
+ set id [$canvas find withtag current]
+ if {[lsearch [$canvas gettags current] text] >= 0} {
+ set id [expr {$id-1}]
+ }
+ $canvas itemconfigure $id -fill $oldFill
+ $canvas itemconfigure [expr {$id+1}] -fill black
+}
+
+proc scrollButton canvas {
+ global oldFill
+ set id [$canvas find withtag current]
+ if {[lsearch [$canvas gettags current] text] < 0} {
+ set id [expr {$id+1}]
+ }
+ puts stdout "You buttoned at [lindex [$canvas itemconf $id -text] 4]"
+}
diff --git a/tk8.6/library/demos/ctext.tcl b/tk8.6/library/demos/ctext.tcl
new file mode 100644
index 0000000..a3b4e8a
--- /dev/null
+++ b/tk8.6/library/demos/ctext.tcl
@@ -0,0 +1,172 @@
+# ctext.tcl --
+#
+# This demonstration script creates a canvas widget with a text
+# item that can be edited and reconfigured in various ways.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .ctext
+catch {destroy $w}
+toplevel $w
+wm title $w "Canvas Text Demonstration"
+wm iconname $w "Text"
+positionWindow $w
+set c $w.c
+
+label $w.msg -font $font -wraplength 5i -justify left -text "This window displays a string of text to demonstrate the text facilities of canvas widgets. You can click in the boxes to adjust the position of the text relative to its positioning point or change its justification, and on a pie slice to change its angle. The text also supports the following simple bindings for editing:
+ 1. You can point, click, and type.
+ 2. You can also select with button 1.
+ 3. You can copy the selection to the mouse position with button 2.
+ 4. Backspace and Control+h delete the selection if there is one;
+ otherwise they delete the character just before the insertion cursor.
+ 5. Delete deletes the selection if there is one; otherwise it deletes
+ the character just after the insertion cursor."
+pack $w.msg -side top
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+canvas $c -relief flat -borderwidth 0 -width 500 -height 350
+pack $w.c -side top -expand yes -fill both
+
+set textFont {Helvetica 24}
+
+$c create rectangle 245 195 255 205 -outline black -fill red
+
+# First, create the text item and give it bindings so it can be edited.
+
+$c addtag text withtag [$c create text 250 200 -text "This is just a string of text to demonstrate the text facilities of canvas widgets. Bindings have been defined to support editing (see above)." -width 440 -anchor n -font $textFont -justify left]
+$c bind text <1> "textB1Press $c %x %y"
+$c bind text <B1-Motion> "textB1Move $c %x %y"
+$c bind text <Shift-1> "$c select adjust current @%x,%y"
+$c bind text <Shift-B1-Motion> "textB1Move $c %x %y"
+$c bind text <KeyPress> "textInsert $c %A"
+$c bind text <Return> "textInsert $c \\n"
+$c bind text <Control-h> "textBs $c"
+$c bind text <BackSpace> "textBs $c"
+$c bind text <Delete> "textDel $c"
+$c bind text <2> "textPaste $c @%x,%y"
+
+# Next, create some items that allow the text's anchor position
+# to be edited.
+
+proc mkTextConfigBox {w x y option value color} {
+ set item [$w create rect $x $y [expr {$x+30}] [expr {$y+30}] \
+ -outline black -fill $color -width 1]
+ $w bind $item <1> "$w itemconf text $option $value"
+ $w addtag config withtag $item
+}
+proc mkTextConfigPie {w x y a option value color} {
+ set item [$w create arc $x $y [expr {$x+90}] [expr {$y+90}] \
+ -start [expr {$a-15}] -extent 30 -outline black -fill $color \
+ -width 1]
+ $w bind $item <1> "$w itemconf text $option $value"
+ $w addtag config withtag $item
+}
+
+set x 50
+set y 50
+set color LightSkyBlue1
+mkTextConfigBox $c $x $y -anchor se $color
+mkTextConfigBox $c [expr {$x+30}] [expr {$y }] -anchor s $color
+mkTextConfigBox $c [expr {$x+60}] [expr {$y }] -anchor sw $color
+mkTextConfigBox $c [expr {$x }] [expr {$y+30}] -anchor e $color
+mkTextConfigBox $c [expr {$x+30}] [expr {$y+30}] -anchor center $color
+mkTextConfigBox $c [expr {$x+60}] [expr {$y+30}] -anchor w $color
+mkTextConfigBox $c [expr {$x }] [expr {$y+60}] -anchor ne $color
+mkTextConfigBox $c [expr {$x+30}] [expr {$y+60}] -anchor n $color
+mkTextConfigBox $c [expr {$x+60}] [expr {$y+60}] -anchor nw $color
+set item [$c create rect \
+ [expr {$x+40}] [expr {$y+40}] [expr {$x+50}] [expr {$y+50}] \
+ -outline black -fill red]
+$c bind $item <1> "$c itemconf text -anchor center"
+$c create text [expr {$x+45}] [expr {$y-5}] \
+ -text {Text Position} -anchor s -font {Times 20} -fill brown
+
+# Now create some items that allow the text's angle to be changed.
+
+set x 205
+set y 50
+set color Yellow
+mkTextConfigPie $c $x $y 0 -angle 90 $color
+mkTextConfigPie $c $x $y 30 -angle 120 $color
+mkTextConfigPie $c $x $y 60 -angle 150 $color
+mkTextConfigPie $c $x $y 90 -angle 180 $color
+mkTextConfigPie $c $x $y 120 -angle 210 $color
+mkTextConfigPie $c $x $y 150 -angle 240 $color
+mkTextConfigPie $c $x $y 180 -angle 270 $color
+mkTextConfigPie $c $x $y 210 -angle 300 $color
+mkTextConfigPie $c $x $y 240 -angle 330 $color
+mkTextConfigPie $c $x $y 270 -angle 0 $color
+mkTextConfigPie $c $x $y 300 -angle 30 $color
+mkTextConfigPie $c $x $y 330 -angle 60 $color
+$c create text [expr {$x+45}] [expr {$y-5}] \
+ -text {Text Angle} -anchor s -font {Times 20} -fill brown
+
+# Lastly, create some items that allow the text's justification to be
+# changed.
+
+set x 350
+set y 50
+set color SeaGreen2
+mkTextConfigBox $c $x $y -justify left $color
+mkTextConfigBox $c [expr {$x+30}] $y -justify center $color
+mkTextConfigBox $c [expr {$x+60}] $y -justify right $color
+$c create text [expr {$x+45}] [expr {$y-5}] \
+ -text {Justification} -anchor s -font {Times 20} -fill brown
+
+$c bind config <Enter> "textEnter $c"
+$c bind config <Leave> "$c itemconf current -fill \$textConfigFill"
+
+set textConfigFill {}
+
+proc textEnter {w} {
+ global textConfigFill
+ set textConfigFill [lindex [$w itemconfig current -fill] 4]
+ $w itemconfig current -fill black
+}
+
+proc textInsert {w string} {
+ if {$string == ""} {
+ return
+ }
+ catch {$w dchars text sel.first sel.last}
+ $w insert text insert $string
+}
+
+proc textPaste {w pos} {
+ catch {
+ $w insert text $pos [selection get]
+ }
+}
+
+proc textB1Press {w x y} {
+ $w icursor current @$x,$y
+ $w focus current
+ focus $w
+ $w select from current @$x,$y
+}
+
+proc textB1Move {w x y} {
+ $w select to current @$x,$y
+}
+
+proc textBs {w} {
+ if {![catch {$w dchars text sel.first sel.last}]} {
+ return
+ }
+ set char [expr {[$w index text insert] - 1}]
+ if {$char >= 0} {$w dchar text $char}
+}
+
+proc textDel {w} {
+ if {![catch {$w dchars text sel.first sel.last}]} {
+ return
+ }
+ $w dchars text insert
+}
diff --git a/tk8.6/library/demos/dialog1.tcl b/tk8.6/library/demos/dialog1.tcl
new file mode 100644
index 0000000..976e955
--- /dev/null
+++ b/tk8.6/library/demos/dialog1.tcl
@@ -0,0 +1,25 @@
+# dialog1.tcl --
+#
+# This demonstration script creates a dialog box with a local grab.
+
+interp create slave
+load {} Tk slave
+slave eval {
+ wm title . slave
+ wm geometry . +700+30
+ pack [text .t -width 30 -height 10]
+}
+
+after idle {.dialog1.msg configure -wraplength 4i}
+set i [tk_dialog .dialog1 "Dialog with local grab" {This is a modal dialog box. It uses Tk's "grab" command to create a "local grab" on the dialog box. The grab prevents any mouse or keyboard events from getting to any other windows in the application until you have answered the dialog by invoking one of the buttons below. However, you can still interact with other applications. For example, you should be able to edit text in the window named "slave" which was created by a slave interpreter.} \
+info 0 OK Cancel {Show Code}]
+
+switch $i {
+ 0 {puts "You pressed OK"}
+ 1 {puts "You pressed Cancel"}
+ 2 {showCode .dialog1}
+}
+
+if {[interp exists slave]} {
+ interp delete slave
+}
diff --git a/tk8.6/library/demos/dialog2.tcl b/tk8.6/library/demos/dialog2.tcl
new file mode 100644
index 0000000..6ae27a8
--- /dev/null
+++ b/tk8.6/library/demos/dialog2.tcl
@@ -0,0 +1,18 @@
+# dialog2.tcl --
+#
+# This demonstration script creates a dialog box with a global grab.
+
+after idle {
+ .dialog2.msg configure -wraplength 4i
+}
+after 100 {
+ grab -global .dialog2
+}
+set i [tk_dialog .dialog2 "Dialog with global grab" {This dialog box uses a global grab. If you are using an X11 window manager you will be prevented from interacting with anything on your display until you invoke one of the buttons below. This is almost always a bad idea; don't use global grabs with X11 unless you're truly desperate. On macOS systems you will not be able to interact with any window belonging to this process, but interaction with other macOS Applications will still be possible.}\
+warning 0 OK Cancel {Show Code}]
+
+switch $i {
+ 0 {puts "You pressed OK"}
+ 1 {puts "You pressed Cancel"}
+ 2 {showCode .dialog2}
+}
diff --git a/tk8.6/library/demos/en.msg b/tk8.6/library/demos/en.msg
new file mode 100644
index 0000000..05d4a64
--- /dev/null
+++ b/tk8.6/library/demos/en.msg
@@ -0,0 +1,97 @@
+::msgcat::mcset en "Widget Demonstration"
+::msgcat::mcset en "tkWidgetDemo"
+::msgcat::mcset en "&File"
+::msgcat::mcset en "About..."
+::msgcat::mcset en "&About..."
+::msgcat::mcset en "<F1>"
+::msgcat::mcset en "&Quit"
+::msgcat::mcset en "Meta+Q" ;# Displayed hotkey
+::msgcat::mcset en "Meta-q" ;# Actual binding sequence
+::msgcat::mcset en "Ctrl+Q" ;# Displayed hotkey
+::msgcat::mcset en "Control-q" ;# Actual binding sequence
+::msgcat::mcset en "Variable values"
+::msgcat::mcset en "Variable values:"
+::msgcat::mcset en "OK"
+::msgcat::mcset en "Run the \"%s\" sample program"
+::msgcat::mcset en "Dismiss"
+::msgcat::mcset en "Rerun Demo"
+::msgcat::mcset en "Demo code: %s"
+::msgcat::mcset en "About Widget Demo"
+::msgcat::mcset en "Tk widget demonstration application"
+::msgcat::mcset en "Copyright © %s"
+::msgcat::mcset en "
+ @@title
+ Tk Widget Demonstrations
+ @@newline
+ @@normal
+ @@newline
+
+ This application provides a front end for several short scripts
+ that demonstrate what you can do with Tk widgets. Each of the
+ numbered lines below describes a demonstration; you can click on
+ it to invoke the demonstration. Once the demonstration window
+ appears, you can click the
+ @@bold
+ See Code
+ @@normal
+ button to see the Tcl/Tk code that created the demonstration. If
+ you wish, you can edit the code and click the
+ @@bold
+ Rerun Demo
+ @@normal
+ button in the code window to reinvoke the demonstration with the
+ modified code.
+ @@newline
+"
+::msgcat::mcset en "Labels, buttons, checkbuttons, and radiobuttons"
+::msgcat::mcset en "Labels (text and bitmaps)"
+::msgcat::mcset en "Labels and UNICODE text"
+::msgcat::mcset en "Buttons"
+::msgcat::mcset en "Check-buttons (select any of a group)"
+::msgcat::mcset en "Radio-buttons (select one of a group)"
+::msgcat::mcset en "A 15-puzzle game made out of buttons"
+::msgcat::mcset en "Iconic buttons that use bitmaps"
+::msgcat::mcset en "Two labels displaying images"
+::msgcat::mcset en "A simple user interface for viewing images"
+::msgcat::mcset en "Labelled frames"
+::msgcat::mcset en "Listboxes"
+::msgcat::mcset en "The 50 states"
+::msgcat::mcset en "Colors: change the color scheme for the application"
+::msgcat::mcset en "A collection of famous and infamous sayings"
+::msgcat::mcset en "Entries and Spin-boxes"
+::msgcat::mcset en "Entries without scrollbars"
+::msgcat::mcset en "Entries with scrollbars"
+::msgcat::mcset en "Validated entries and password fields"
+::msgcat::mcset en "Spin-boxes"
+::msgcat::mcset en "Simple Rolodex-like form"
+::msgcat::mcset en "Text"
+::msgcat::mcset en "Basic editable text"
+::msgcat::mcset en "Text display styles"
+::msgcat::mcset en "Hypertext (tag bindings)"
+::msgcat::mcset en "A text widget with embedded windows"
+::msgcat::mcset en "A search tool built with a text widget"
+::msgcat::mcset en "Canvases"
+::msgcat::mcset en "The canvas item types"
+::msgcat::mcset en "A simple 2-D plot"
+::msgcat::mcset en "Text items in canvases"
+::msgcat::mcset en "An editor for arrowheads on canvas lines"
+::msgcat::mcset en "A ruler with adjustable tab stops"
+::msgcat::mcset en "A building floor plan"
+::msgcat::mcset en "A simple scrollable canvas"
+::msgcat::mcset en "Scales"
+::msgcat::mcset en "Horizontal scale"
+::msgcat::mcset en "Vertical scale"
+::msgcat::mcset en "Paned Windows"
+::msgcat::mcset en "Horizontal paned window"
+::msgcat::mcset en "Vertical paned window"
+::msgcat::mcset en "Menus"
+::msgcat::mcset en "Menus and cascades (sub-menus)"
+::msgcat::mcset en "Menu-buttons"
+::msgcat::mcset en "Common Dialogs"
+::msgcat::mcset en "Message boxes"
+::msgcat::mcset en "File selection dialog"
+::msgcat::mcset en "Color picker"
+::msgcat::mcset en "Miscellaneous"
+::msgcat::mcset en "The built-in bitmaps"
+::msgcat::mcset en "A dialog box with a local grab"
+::msgcat::mcset en "A dialog box with a global grab"
diff --git a/tk8.6/library/demos/entry1.tcl b/tk8.6/library/demos/entry1.tcl
new file mode 100644
index 0000000..eef8964
--- /dev/null
+++ b/tk8.6/library/demos/entry1.tcl
@@ -0,0 +1,34 @@
+# entry1.tcl --
+#
+# This demonstration script creates several entry widgets without
+# scrollbars.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .entry1
+catch {destroy $w}
+toplevel $w
+wm title $w "Entry Demonstration (no scrollbars)"
+wm iconname $w "entry1"
+positionWindow $w
+
+label $w.msg -font $font -wraplength 5i -justify left -text "Three different entries are displayed below. You can add characters by pointing, clicking and typing. The normal Motif editing characters are supported, along with many Emacs bindings. For example, Backspace and Control-h delete the character to the left of the insertion cursor and Delete and Control-d delete the chararacter to the right of the insertion cursor. For entries that are too large to fit in the window all at once, you can scan through the entries by dragging with mouse button2 pressed."
+pack $w.msg -side top
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+entry $w.e1
+entry $w.e2
+entry $w.e3
+pack $w.e1 $w.e2 $w.e3 -side top -pady 5 -padx 10 -fill x
+
+$w.e1 insert 0 "Initial value"
+$w.e2 insert end "This entry contains a long value, much too long "
+$w.e2 insert end "to fit in the window at one time, so long in fact "
+$w.e2 insert end "that you'll have to scan or scroll to see the end."
diff --git a/tk8.6/library/demos/entry2.tcl b/tk8.6/library/demos/entry2.tcl
new file mode 100644
index 0000000..9e3f4ef
--- /dev/null
+++ b/tk8.6/library/demos/entry2.tcl
@@ -0,0 +1,46 @@
+# entry2.tcl --
+#
+# This demonstration script is the same as the entry1.tcl script
+# except that it creates scrollbars for the entries.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .entry2
+catch {destroy $w}
+toplevel $w
+wm title $w "Entry Demonstration (with scrollbars)"
+wm iconname $w "entry2"
+positionWindow $w
+
+label $w.msg -font $font -wraplength 5i -justify left -text "Three different entries are displayed below, with a scrollbar for each entry. You can add characters by pointing, clicking and typing. The normal Motif editing characters are supported, along with many Emacs bindings. For example, Backspace and Control-h delete the character to the left of the insertion cursor and Delete and Control-d delete the chararacter to the right of the insertion cursor. For entries that are too large to fit in the window all at once, you can scan through the entries with the scrollbars, or by dragging with mouse button2 pressed."
+pack $w.msg -side top
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+frame $w.frame -borderwidth 10
+pack $w.frame -side top -fill x -expand 1
+
+entry $w.frame.e1 -xscrollcommand "$w.frame.s1 set"
+ttk::scrollbar $w.frame.s1 -orient horiz -command \
+ "$w.frame.e1 xview"
+frame $w.frame.spacer1 -width 20 -height 10
+entry $w.frame.e2 -xscrollcommand "$w.frame.s2 set"
+ttk::scrollbar $w.frame.s2 -orient horiz -command \
+ "$w.frame.e2 xview"
+frame $w.frame.spacer2 -width 20 -height 10
+entry $w.frame.e3 -xscrollcommand "$w.frame.s3 set"
+ttk::scrollbar $w.frame.s3 -orient horiz -command \
+ "$w.frame.e3 xview"
+pack $w.frame.e1 $w.frame.s1 $w.frame.spacer1 $w.frame.e2 $w.frame.s2 \
+ $w.frame.spacer2 $w.frame.e3 $w.frame.s3 -side top -fill x
+
+$w.frame.e1 insert 0 "Initial value"
+$w.frame.e2 insert end "This entry contains a long value, much too long "
+$w.frame.e2 insert end "to fit in the window at one time, so long in fact "
+$w.frame.e2 insert end "that you'll have to scan or scroll to see the end."
diff --git a/tk8.6/library/demos/entry3.tcl b/tk8.6/library/demos/entry3.tcl
new file mode 100644
index 0000000..d4435c6
--- /dev/null
+++ b/tk8.6/library/demos/entry3.tcl
@@ -0,0 +1,185 @@
+# entry3.tcl --
+#
+# This demonstration script creates several entry widgets whose
+# permitted input is constrained in some way. It also shows off a
+# password entry.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .entry3
+catch {destroy $w}
+toplevel $w
+wm title $w "Constrained Entry Demonstration"
+wm iconname $w "entry3"
+positionWindow $w
+
+label $w.msg -font $font -wraplength 5i -justify left -text "Four different\
+ entries are displayed below. You can add characters by pointing,\
+ clicking and typing, though each is constrained in what it will\
+ accept. The first only accepts 32-bit integers or the empty string\
+ (checking when focus leaves it) and will flash to indicate any\
+ problem. The second only accepts strings with fewer than ten\
+ characters and sounds the bell when an attempt to go over the limit\
+ is made. The third accepts US phone numbers, mapping letters to\
+ their digit equivalent and sounding the bell on encountering an\
+ illegal character or if trying to type over a character that is not\
+ a digit. The fourth is a password field that accepts up to eight\
+ characters (silently ignoring further ones), and displaying them as\
+ asterisk characters."
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+# focusAndFlash --
+# Error handler for entry widgets that forces the focus onto the
+# widget and makes the widget flash by exchanging the foreground and
+# background colours at intervals of 200ms (i.e. at approximately
+# 2.5Hz).
+#
+# Arguments:
+# W - Name of entry widget to flash
+# fg - Initial foreground colour
+# bg - Initial background colour
+# count - Counter to control the number of times flashed
+
+proc focusAndFlash {W fg bg {count 9}} {
+ focus -force $W
+ if {$count<1} {
+ $W configure -foreground $fg -background $bg
+ } else {
+ if {$count%2} {
+ $W configure -foreground $bg -background $fg
+ } else {
+ $W configure -foreground $fg -background $bg
+ }
+ after 200 [list focusAndFlash $W $fg $bg [expr {$count-1}]]
+ }
+}
+
+labelframe $w.l1 -text "Integer Entry"
+# Alternatively try using {string is digit} for arbitrary length numbers,
+# and not just 32-bit ones.
+entry $w.l1.e -validate focus -vcmd {string is integer %P}
+$w.l1.e configure -invalidcommand \
+ "focusAndFlash %W [$w.l1.e cget -fg] [$w.l1.e cget -bg]"
+pack $w.l1.e -fill x -expand 1 -padx 1m -pady 1m
+
+labelframe $w.l2 -text "Length-Constrained Entry"
+entry $w.l2.e -validate key -invcmd bell -vcmd {expr {[string length %P]<10}}
+pack $w.l2.e -fill x -expand 1 -padx 1m -pady 1m
+
+### PHONE NUMBER ENTRY ###
+# Note that the source to this is quite a bit longer as the behaviour
+# demonstrated is a lot more ambitious than with the others.
+
+# Initial content for the third entry widget
+set entry3content "1-(000)-000-0000"
+# Mapping from alphabetic characters to numbers. This is probably
+# wrong, but it is the only mapping I have; the UK doesn't really go
+# for associating letters with digits for some reason.
+set phoneNumberMap {}
+foreach {chars digit} {abc 2 def 3 ghi 4 jkl 5 mno 6 pqrs 7 tuv 8 wxyz 9} {
+ foreach char [split $chars ""] {
+ lappend phoneNumberMap $char $digit [string toupper $char] $digit
+ }
+}
+
+# validatePhoneChange --
+# Checks that the replacement (mapped to a digit) of the given
+# character in an entry widget at the given position will leave a
+# valid phone number in the widget.
+#
+# W - The entry widget to validate
+# vmode - The widget's validation mode
+# idx - The index where replacement is to occur
+# char - The character (or string, though that will always be
+# refused) to be overwritten at that point.
+
+proc validatePhoneChange {W vmode idx char} {
+ global phoneNumberMap entry3content
+ if {$idx == -1} {return 1}
+ after idle [list $W configure -validate $vmode -invcmd bell]
+ if {
+ !($idx<3 || $idx==6 || $idx==7 || $idx==11 || $idx>15) &&
+ [string match {[0-9A-Za-z]} $char]
+ } then {
+ $W delete $idx
+ $W insert $idx [string map $phoneNumberMap $char]
+ after idle [list phoneSkipRight $W -1]
+ return 1
+ }
+ return 0
+}
+
+# phoneSkipLeft --
+# Skip over fixed characters in a phone-number string when moving left.
+#
+# Arguments:
+# W - The entry widget containing the phone-number.
+
+proc phoneSkipLeft {W} {
+ set idx [$W index insert]
+ if {$idx == 8} {
+ # Skip back two extra characters
+ $W icursor [incr idx -2]
+ } elseif {$idx == 7 || $idx == 12} {
+ # Skip back one extra character
+ $W icursor [incr idx -1]
+ } elseif {$idx <= 3} {
+ # Can't move any further
+ bell
+ return -code break
+ }
+}
+
+# phoneSkipRight --
+# Skip over fixed characters in a phone-number string when moving right.
+#
+# Arguments:
+# W - The entry widget containing the phone-number.
+# add - Offset to add to index before calculation (used by validation.)
+
+proc phoneSkipRight {W {add 0}} {
+ set idx [$W index insert]
+ if {$idx+$add == 5} {
+ # Skip forward two extra characters
+ $W icursor [incr idx 2]
+ } elseif {$idx+$add == 6 || $idx+$add == 10} {
+ # Skip forward one extra character
+ $W icursor [incr idx]
+ } elseif {$idx+$add == 15 && !$add} {
+ # Can't move any further
+ bell
+ return -code break
+ }
+}
+
+labelframe $w.l3 -text "US Phone-Number Entry"
+entry $w.l3.e -validate key -invcmd bell -textvariable entry3content \
+ -vcmd {validatePhoneChange %W %v %i %S}
+# Click to focus goes to the first editable character...
+bind $w.l3.e <FocusIn> {
+ if {"%d" ne "NotifyAncestor"} {
+ %W icursor 3
+ after idle {%W selection clear}
+ }
+}
+bind $w.l3.e <<PrevChar>> {phoneSkipLeft %W}
+bind $w.l3.e <<NextChar>> {phoneSkipRight %W}
+pack $w.l3.e -fill x -expand 1 -padx 1m -pady 1m
+
+labelframe $w.l4 -text "Password Entry"
+entry $w.l4.e -validate key -show "*" -vcmd {expr {[string length %P]<=8}}
+pack $w.l4.e -fill x -expand 1 -padx 1m -pady 1m
+
+lower [frame $w.mid]
+grid $w.l1 $w.l2 -in $w.mid -padx 3m -pady 1m -sticky ew
+grid $w.l3 $w.l4 -in $w.mid -padx 3m -pady 1m -sticky ew
+grid columnconfigure $w.mid {0 1} -uniform 1
+pack $w.msg -side top
+pack $w.mid -fill both -expand 1
diff --git a/tk8.6/library/demos/filebox.tcl b/tk8.6/library/demos/filebox.tcl
new file mode 100644
index 0000000..e06ebba
--- /dev/null
+++ b/tk8.6/library/demos/filebox.tcl
@@ -0,0 +1,81 @@
+# filebox.tcl --
+#
+# This demonstration script prompts the user to select a file.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .filebox
+catch {destroy $w}
+toplevel $w
+wm title $w "File Selection Dialogs"
+wm iconname $w "filebox"
+positionWindow $w
+
+ttk::frame $w._bg
+place $w._bg -x 0 -y 0 -relwidth 1 -relheight 1
+
+ttk::label $w.msg -font $font -wraplength 4i -justify left -text "Enter a file name in the entry box or click on the \"Browse\" buttons to select a file name using the file selection dialog."
+pack $w.msg -side top
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+foreach i {open save} {
+ set f [ttk::frame $w.$i]
+ ttk::label $f.lab -text "Select a file to $i: " -anchor e
+ ttk::entry $f.ent -width 20
+ ttk::button $f.but -text "Browse ..." -command "fileDialog $w $f.ent $i"
+ pack $f.lab -side left
+ pack $f.ent -side left -expand yes -fill x
+ pack $f.but -side left
+ pack $f -fill x -padx 1c -pady 3
+}
+
+if {[tk windowingsystem] eq "x11"} {
+ ttk::checkbutton $w.strict -text "Use Motif Style Dialog" \
+ -variable tk_strictMotif -onvalue 1 -offvalue 0
+ pack $w.strict -anchor c
+
+ # This binding ensures that we don't run the rest of the demos
+ # with motif style interactions
+ bind $w.strict <Destroy> {set tk_strictMotif 0}
+}
+
+proc fileDialog {w ent operation} {
+ # Type names Extension(s) Mac File Type(s)
+ #
+ #---------------------------------------------------------
+ set types {
+ {"Text files" {.txt .doc} }
+ {"Text files" {} TEXT}
+ {"Tcl Scripts" {.tcl} TEXT}
+ {"C Source Files" {.c .h} }
+ {"All Source Files" {.tcl .c .h} }
+ {"Image Files" {.gif} }
+ {"Image Files" {.jpeg .jpg} }
+ {"Image Files" "" {GIFF JPEG}}
+ {"All files" *}
+ }
+ if {$operation == "open"} {
+ global selected_type
+ if {![info exists selected_type]} {
+ set selected_type "Tcl Scripts"
+ }
+ set file [tk_getOpenFile -filetypes $types -parent $w \
+ -typevariable selected_type]
+ puts "You selected filetype \"$selected_type\""
+ } else {
+ set file [tk_getSaveFile -filetypes $types -parent $w \
+ -initialfile Untitled -defaultextension .txt]
+ }
+ if {[string compare $file ""]} {
+ $ent delete 0 end
+ $ent insert 0 $file
+ $ent xview end
+ }
+}
diff --git a/tk8.6/library/demos/floor.tcl b/tk8.6/library/demos/floor.tcl
new file mode 100644
index 0000000..c36979b
--- /dev/null
+++ b/tk8.6/library/demos/floor.tcl
@@ -0,0 +1,1366 @@
+# floor.tcl --
+#
+# This demonstration script creates a canvas widet that displays the
+# floorplan for DEC's Western Research Laboratory.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+# floorDisplay --
+# Recreate the floorplan display in the canvas given by "w". The
+# floor given by "active" is displayed on top with its office structure
+# visible.
+#
+# Arguments:
+# w - Name of the canvas window.
+# active - Number of active floor (1, 2, or 3).
+
+proc floorDisplay {w active} {
+ global floorLabels floorItems colors activeFloor
+
+ if {$activeFloor == $active} {
+ return
+ }
+
+ $w delete all
+ set activeFloor $active
+
+ # First go through the three floors, displaying the backgrounds for
+ # each floor.
+
+ bg1 $w $colors(bg1) $colors(outline1)
+ bg2 $w $colors(bg2) $colors(outline2)
+ bg3 $w $colors(bg3) $colors(outline3)
+
+ # Raise the background for the active floor so that it's on top.
+
+ $w raise floor$active
+
+ # Create a dummy item just to mark this point in the display list,
+ # so we can insert highlights here.
+
+ $w create rect 0 100 1 101 -fill {} -outline {} -tags marker
+
+ # Add the walls and labels for the active floor, along with
+ # transparent polygons that define the rooms on the floor.
+ # Make sure that the room polygons are on top.
+
+ catch {unset floorLabels}
+ catch {unset floorItems}
+ fg$active $w $colors(offices)
+ $w raise room
+
+ # Offset the floors diagonally from each other.
+
+ $w move floor1 2c 2c
+ $w move floor2 1c 1c
+
+ # Create items for the room entry and its label.
+
+ $w create window 600 100 -anchor w -window $w.entry
+ $w create text 600 100 -anchor e -text "Room: "
+ $w config -scrollregion [$w bbox all]
+}
+
+# newRoom --
+# This procedure is invoked whenever the mouse enters a room
+# in the floorplan. It changes tags so that the current room is
+# highlighted.
+#
+# Arguments:
+# w - The name of the canvas window.
+
+proc newRoom w {
+ global currentRoom floorLabels
+
+ set id [$w find withtag current]
+ if {$id != ""} {
+ set currentRoom $floorLabels($id)
+ }
+ update idletasks
+}
+
+# roomChanged --
+# This procedure is invoked whenever the currentRoom variable changes.
+# It highlights the current room and unhighlights any previous room.
+#
+# Arguments:
+# w - The canvas window displaying the floorplan.
+# args - Not used.
+
+proc roomChanged {w args} {
+ global currentRoom floorItems colors
+ $w delete highlight
+ if {[catch {set item $floorItems($currentRoom)}]} {
+ return
+ }
+ set new [eval \
+ "$w create polygon [$w coords $item] -fill $colors(active) \
+ -tags highlight"]
+ $w raise $new marker
+}
+
+# bg1 --
+# This procedure represents part of the floorplan database. When
+# invoked, it instantiates the background information for the first
+# floor.
+#
+# Arguments:
+# w - The canvas window.
+# fill - Fill color to use for the floor's background.
+# outline - Color to use for the floor's outline.
+
+proc bg1 {w fill outline} {
+ $w create poly 347 80 349 82 351 84 353 85 363 92 375 99 386 104 \
+ 386 129 398 129 398 162 484 162 484 129 559 129 559 133 725 \
+ 133 725 129 802 129 802 389 644 389 644 391 559 391 559 327 \
+ 508 327 508 311 484 311 484 278 395 278 395 288 400 288 404 \
+ 288 409 290 413 292 418 297 421 302 422 309 421 318 417 325 \
+ 411 330 405 332 397 333 344 333 340 334 336 336 335 338 332 \
+ 342 331 347 332 351 334 354 336 357 341 359 340 360 335 363 \
+ 331 365 326 366 304 366 304 355 258 355 258 387 60 387 60 391 \
+ 0 391 0 337 3 337 3 114 8 114 8 25 30 25 30 5 93 5 98 5 104 7 \
+ 110 10 116 16 119 20 122 28 123 32 123 68 220 68 220 34 221 \
+ 22 223 17 227 13 231 8 236 4 242 2 246 0 260 0 283 1 300 5 \
+ 321 14 335 22 348 25 365 29 363 39 358 48 352 56 337 70 \
+ 344 76 347 80 \
+ -tags {floor1 bg} -fill $fill
+ $w create line 386 129 398 129 -fill $outline -tags {floor1 bg}
+ $w create line 258 355 258 387 -fill $outline -tags {floor1 bg}
+ $w create line 60 387 60 391 -fill $outline -tags {floor1 bg}
+ $w create line 0 337 0 391 -fill $outline -tags {floor1 bg}
+ $w create line 60 391 0 391 -fill $outline -tags {floor1 bg}
+ $w create line 3 114 3 337 -fill $outline -tags {floor1 bg}
+ $w create line 258 387 60 387 -fill $outline -tags {floor1 bg}
+ $w create line 484 162 398 162 -fill $outline -tags {floor1 bg}
+ $w create line 398 162 398 129 -fill $outline -tags {floor1 bg}
+ $w create line 484 278 484 311 -fill $outline -tags {floor1 bg}
+ $w create line 484 311 508 311 -fill $outline -tags {floor1 bg}
+ $w create line 508 327 508 311 -fill $outline -tags {floor1 bg}
+ $w create line 559 327 508 327 -fill $outline -tags {floor1 bg}
+ $w create line 644 391 559 391 -fill $outline -tags {floor1 bg}
+ $w create line 644 389 644 391 -fill $outline -tags {floor1 bg}
+ $w create line 559 129 484 129 -fill $outline -tags {floor1 bg}
+ $w create line 484 162 484 129 -fill $outline -tags {floor1 bg}
+ $w create line 725 133 559 133 -fill $outline -tags {floor1 bg}
+ $w create line 559 129 559 133 -fill $outline -tags {floor1 bg}
+ $w create line 725 129 802 129 -fill $outline -tags {floor1 bg}
+ $w create line 802 389 802 129 -fill $outline -tags {floor1 bg}
+ $w create line 3 337 0 337 -fill $outline -tags {floor1 bg}
+ $w create line 559 391 559 327 -fill $outline -tags {floor1 bg}
+ $w create line 802 389 644 389 -fill $outline -tags {floor1 bg}
+ $w create line 725 133 725 129 -fill $outline -tags {floor1 bg}
+ $w create line 8 25 8 114 -fill $outline -tags {floor1 bg}
+ $w create line 8 114 3 114 -fill $outline -tags {floor1 bg}
+ $w create line 30 25 8 25 -fill $outline -tags {floor1 bg}
+ $w create line 484 278 395 278 -fill $outline -tags {floor1 bg}
+ $w create line 30 25 30 5 -fill $outline -tags {floor1 bg}
+ $w create line 93 5 30 5 -fill $outline -tags {floor1 bg}
+ $w create line 98 5 93 5 -fill $outline -tags {floor1 bg}
+ $w create line 104 7 98 5 -fill $outline -tags {floor1 bg}
+ $w create line 110 10 104 7 -fill $outline -tags {floor1 bg}
+ $w create line 116 16 110 10 -fill $outline -tags {floor1 bg}
+ $w create line 119 20 116 16 -fill $outline -tags {floor1 bg}
+ $w create line 122 28 119 20 -fill $outline -tags {floor1 bg}
+ $w create line 123 32 122 28 -fill $outline -tags {floor1 bg}
+ $w create line 123 68 123 32 -fill $outline -tags {floor1 bg}
+ $w create line 220 68 123 68 -fill $outline -tags {floor1 bg}
+ $w create line 386 129 386 104 -fill $outline -tags {floor1 bg}
+ $w create line 386 104 375 99 -fill $outline -tags {floor1 bg}
+ $w create line 375 99 363 92 -fill $outline -tags {floor1 bg}
+ $w create line 353 85 363 92 -fill $outline -tags {floor1 bg}
+ $w create line 220 68 220 34 -fill $outline -tags {floor1 bg}
+ $w create line 337 70 352 56 -fill $outline -tags {floor1 bg}
+ $w create line 352 56 358 48 -fill $outline -tags {floor1 bg}
+ $w create line 358 48 363 39 -fill $outline -tags {floor1 bg}
+ $w create line 363 39 365 29 -fill $outline -tags {floor1 bg}
+ $w create line 365 29 348 25 -fill $outline -tags {floor1 bg}
+ $w create line 348 25 335 22 -fill $outline -tags {floor1 bg}
+ $w create line 335 22 321 14 -fill $outline -tags {floor1 bg}
+ $w create line 321 14 300 5 -fill $outline -tags {floor1 bg}
+ $w create line 300 5 283 1 -fill $outline -tags {floor1 bg}
+ $w create line 283 1 260 0 -fill $outline -tags {floor1 bg}
+ $w create line 260 0 246 0 -fill $outline -tags {floor1 bg}
+ $w create line 246 0 242 2 -fill $outline -tags {floor1 bg}
+ $w create line 242 2 236 4 -fill $outline -tags {floor1 bg}
+ $w create line 236 4 231 8 -fill $outline -tags {floor1 bg}
+ $w create line 231 8 227 13 -fill $outline -tags {floor1 bg}
+ $w create line 223 17 227 13 -fill $outline -tags {floor1 bg}
+ $w create line 221 22 223 17 -fill $outline -tags {floor1 bg}
+ $w create line 220 34 221 22 -fill $outline -tags {floor1 bg}
+ $w create line 340 360 335 363 -fill $outline -tags {floor1 bg}
+ $w create line 335 363 331 365 -fill $outline -tags {floor1 bg}
+ $w create line 331 365 326 366 -fill $outline -tags {floor1 bg}
+ $w create line 326 366 304 366 -fill $outline -tags {floor1 bg}
+ $w create line 304 355 304 366 -fill $outline -tags {floor1 bg}
+ $w create line 395 288 400 288 -fill $outline -tags {floor1 bg}
+ $w create line 404 288 400 288 -fill $outline -tags {floor1 bg}
+ $w create line 409 290 404 288 -fill $outline -tags {floor1 bg}
+ $w create line 413 292 409 290 -fill $outline -tags {floor1 bg}
+ $w create line 418 297 413 292 -fill $outline -tags {floor1 bg}
+ $w create line 421 302 418 297 -fill $outline -tags {floor1 bg}
+ $w create line 422 309 421 302 -fill $outline -tags {floor1 bg}
+ $w create line 421 318 422 309 -fill $outline -tags {floor1 bg}
+ $w create line 421 318 417 325 -fill $outline -tags {floor1 bg}
+ $w create line 417 325 411 330 -fill $outline -tags {floor1 bg}
+ $w create line 411 330 405 332 -fill $outline -tags {floor1 bg}
+ $w create line 405 332 397 333 -fill $outline -tags {floor1 bg}
+ $w create line 397 333 344 333 -fill $outline -tags {floor1 bg}
+ $w create line 344 333 340 334 -fill $outline -tags {floor1 bg}
+ $w create line 340 334 336 336 -fill $outline -tags {floor1 bg}
+ $w create line 336 336 335 338 -fill $outline -tags {floor1 bg}
+ $w create line 335 338 332 342 -fill $outline -tags {floor1 bg}
+ $w create line 331 347 332 342 -fill $outline -tags {floor1 bg}
+ $w create line 332 351 331 347 -fill $outline -tags {floor1 bg}
+ $w create line 334 354 332 351 -fill $outline -tags {floor1 bg}
+ $w create line 336 357 334 354 -fill $outline -tags {floor1 bg}
+ $w create line 341 359 336 357 -fill $outline -tags {floor1 bg}
+ $w create line 341 359 340 360 -fill $outline -tags {floor1 bg}
+ $w create line 395 288 395 278 -fill $outline -tags {floor1 bg}
+ $w create line 304 355 258 355 -fill $outline -tags {floor1 bg}
+ $w create line 347 80 344 76 -fill $outline -tags {floor1 bg}
+ $w create line 344 76 337 70 -fill $outline -tags {floor1 bg}
+ $w create line 349 82 347 80 -fill $outline -tags {floor1 bg}
+ $w create line 351 84 349 82 -fill $outline -tags {floor1 bg}
+ $w create line 353 85 351 84 -fill $outline -tags {floor1 bg}
+}
+
+# bg2 --
+# This procedure represents part of the floorplan database. When
+# invoked, it instantiates the background information for the second
+# floor.
+#
+# Arguments:
+# w - The canvas window.
+# fill - Fill color to use for the floor's background.
+# outline - Color to use for the floor's outline.
+
+proc bg2 {w fill outline} {
+ $w create poly 559 129 484 129 484 162 398 162 398 129 315 129 \
+ 315 133 176 133 176 129 96 129 96 133 3 133 3 339 0 339 0 391 \
+ 60 391 60 387 258 387 258 329 350 329 350 311 395 311 395 280 \
+ 484 280 484 311 508 311 508 327 558 327 558 391 644 391 644 \
+ 367 802 367 802 129 725 129 725 133 559 133 559 129 \
+ -tags {floor2 bg} -fill $fill
+ $w create line 350 311 350 329 -fill $outline -tags {floor2 bg}
+ $w create line 398 129 398 162 -fill $outline -tags {floor2 bg}
+ $w create line 802 367 802 129 -fill $outline -tags {floor2 bg}
+ $w create line 802 129 725 129 -fill $outline -tags {floor2 bg}
+ $w create line 725 133 725 129 -fill $outline -tags {floor2 bg}
+ $w create line 559 129 559 133 -fill $outline -tags {floor2 bg}
+ $w create line 559 133 725 133 -fill $outline -tags {floor2 bg}
+ $w create line 484 162 484 129 -fill $outline -tags {floor2 bg}
+ $w create line 559 129 484 129 -fill $outline -tags {floor2 bg}
+ $w create line 802 367 644 367 -fill $outline -tags {floor2 bg}
+ $w create line 644 367 644 391 -fill $outline -tags {floor2 bg}
+ $w create line 644 391 558 391 -fill $outline -tags {floor2 bg}
+ $w create line 558 327 558 391 -fill $outline -tags {floor2 bg}
+ $w create line 558 327 508 327 -fill $outline -tags {floor2 bg}
+ $w create line 508 327 508 311 -fill $outline -tags {floor2 bg}
+ $w create line 484 311 508 311 -fill $outline -tags {floor2 bg}
+ $w create line 484 280 484 311 -fill $outline -tags {floor2 bg}
+ $w create line 398 162 484 162 -fill $outline -tags {floor2 bg}
+ $w create line 484 280 395 280 -fill $outline -tags {floor2 bg}
+ $w create line 395 280 395 311 -fill $outline -tags {floor2 bg}
+ $w create line 258 387 60 387 -fill $outline -tags {floor2 bg}
+ $w create line 3 133 3 339 -fill $outline -tags {floor2 bg}
+ $w create line 3 339 0 339 -fill $outline -tags {floor2 bg}
+ $w create line 60 391 0 391 -fill $outline -tags {floor2 bg}
+ $w create line 0 339 0 391 -fill $outline -tags {floor2 bg}
+ $w create line 60 387 60 391 -fill $outline -tags {floor2 bg}
+ $w create line 258 329 258 387 -fill $outline -tags {floor2 bg}
+ $w create line 350 329 258 329 -fill $outline -tags {floor2 bg}
+ $w create line 395 311 350 311 -fill $outline -tags {floor2 bg}
+ $w create line 398 129 315 129 -fill $outline -tags {floor2 bg}
+ $w create line 176 133 315 133 -fill $outline -tags {floor2 bg}
+ $w create line 176 129 96 129 -fill $outline -tags {floor2 bg}
+ $w create line 3 133 96 133 -fill $outline -tags {floor2 bg}
+ $w create line 315 133 315 129 -fill $outline -tags {floor2 bg}
+ $w create line 176 133 176 129 -fill $outline -tags {floor2 bg}
+ $w create line 96 133 96 129 -fill $outline -tags {floor2 bg}
+}
+
+# bg3 --
+# This procedure represents part of the floorplan database. When
+# invoked, it instantiates the background information for the third
+# floor.
+#
+# Arguments:
+# w - The canvas window.
+# fill - Fill color to use for the floor's background.
+# outline - Color to use for the floor's outline.
+
+proc bg3 {w fill outline} {
+ $w create poly 159 300 107 300 107 248 159 248 159 129 96 129 96 \
+ 133 21 133 21 331 0 331 0 391 60 391 60 370 159 370 159 300 \
+ -tags {floor3 bg} -fill $fill
+ $w create poly 258 370 258 329 350 329 350 311 399 311 399 129 \
+ 315 129 315 133 176 133 176 129 159 129 159 370 258 370 \
+ -tags {floor3 bg} -fill $fill
+ $w create line 96 133 96 129 -fill $outline -tags {floor3 bg}
+ $w create line 176 129 96 129 -fill $outline -tags {floor3 bg}
+ $w create line 176 129 176 133 -fill $outline -tags {floor3 bg}
+ $w create line 315 133 176 133 -fill $outline -tags {floor3 bg}
+ $w create line 315 133 315 129 -fill $outline -tags {floor3 bg}
+ $w create line 399 129 315 129 -fill $outline -tags {floor3 bg}
+ $w create line 399 311 399 129 -fill $outline -tags {floor3 bg}
+ $w create line 399 311 350 311 -fill $outline -tags {floor3 bg}
+ $w create line 350 329 350 311 -fill $outline -tags {floor3 bg}
+ $w create line 350 329 258 329 -fill $outline -tags {floor3 bg}
+ $w create line 258 370 258 329 -fill $outline -tags {floor3 bg}
+ $w create line 60 370 258 370 -fill $outline -tags {floor3 bg}
+ $w create line 60 370 60 391 -fill $outline -tags {floor3 bg}
+ $w create line 60 391 0 391 -fill $outline -tags {floor3 bg}
+ $w create line 0 391 0 331 -fill $outline -tags {floor3 bg}
+ $w create line 21 331 0 331 -fill $outline -tags {floor3 bg}
+ $w create line 21 331 21 133 -fill $outline -tags {floor3 bg}
+ $w create line 96 133 21 133 -fill $outline -tags {floor3 bg}
+ $w create line 107 300 159 300 159 248 107 248 107 300 \
+ -fill $outline -tags {floor3 bg}
+}
+
+# fg1 --
+# This procedure represents part of the floorplan database. When
+# invoked, it instantiates the foreground information for the first
+# floor (office outlines and numbers).
+#
+# Arguments:
+# w - The canvas window.
+# color - Color to use for drawing foreground information.
+
+proc fg1 {w color} {
+ global floorLabels floorItems
+ set i [$w create polygon 375 246 375 172 341 172 341 246 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 101
+ set {floorItems(101)} $i
+ $w create text 358 209 -text 101 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 307 240 339 240 339 206 307 206 -fill {} -tags {floor1 room}]
+ set floorLabels($i) {Pub Lift1}
+ set {floorItems(Pub Lift1)} $i
+ $w create text 323 223 -text {Pub Lift1} -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 339 205 307 205 307 171 339 171 -fill {} -tags {floor1 room}]
+ set floorLabels($i) {Priv Lift1}
+ set {floorItems(Priv Lift1)} $i
+ $w create text 323 188 -text {Priv Lift1} -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 42 389 42 337 1 337 1 389 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 110
+ set {floorItems(110)} $i
+ $w create text 21.5 363 -text 110 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 59 389 59 385 90 385 90 337 44 337 44 389 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 109
+ set {floorItems(109)} $i
+ $w create text 67 363 -text 109 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 51 300 51 253 6 253 6 300 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 111
+ set {floorItems(111)} $i
+ $w create text 28.5 276.5 -text 111 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 98 248 98 309 79 309 79 248 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 117B
+ set {floorItems(117B)} $i
+ $w create text 88.5 278.5 -text 117B -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 51 251 51 204 6 204 6 251 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 112
+ set {floorItems(112)} $i
+ $w create text 28.5 227.5 -text 112 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 6 156 51 156 51 203 6 203 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 113
+ set {floorItems(113)} $i
+ $w create text 28.5 179.5 -text 113 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 85 169 79 169 79 192 85 192 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 117A
+ set {floorItems(117A)} $i
+ $w create text 82 180.5 -text 117A -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 77 302 77 168 53 168 53 302 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 117
+ set {floorItems(117)} $i
+ $w create text 65 235 -text 117 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 51 155 51 115 6 115 6 155 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 114
+ set {floorItems(114)} $i
+ $w create text 28.5 135 -text 114 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 95 115 53 115 53 168 95 168 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 115
+ set {floorItems(115)} $i
+ $w create text 74 141.5 -text 115 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 87 113 87 27 10 27 10 113 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 116
+ set {floorItems(116)} $i
+ $w create text 48.5 70 -text 116 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 89 91 128 91 128 113 89 113 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 118
+ set {floorItems(118)} $i
+ $w create text 108.5 102 -text 118 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 178 128 178 132 216 132 216 91 163 91 163 112 149 112 149 128 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 120
+ set {floorItems(120)} $i
+ $w create text 189.5 111.5 -text 120 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 79 193 87 193 87 169 136 169 136 192 156 192 156 169 175 169 175 246 79 246 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 122
+ set {floorItems(122)} $i
+ $w create text 131 207.5 -text 122 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 138 169 154 169 154 191 138 191 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 121
+ set {floorItems(121)} $i
+ $w create text 146 180 -text 121 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 99 300 126 300 126 309 99 309 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 106A
+ set {floorItems(106A)} $i
+ $w create text 112.5 304.5 -text 106A -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 128 299 128 309 150 309 150 248 99 248 99 299 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 105
+ set {floorItems(105)} $i
+ $w create text 124.5 278.5 -text 105 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 174 309 174 300 152 300 152 309 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 106B
+ set {floorItems(106B)} $i
+ $w create text 163 304.5 -text 106B -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 176 299 176 309 216 309 216 248 152 248 152 299 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 104
+ set {floorItems(104)} $i
+ $w create text 184 278.5 -text 104 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 138 385 138 337 91 337 91 385 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 108
+ set {floorItems(108)} $i
+ $w create text 114.5 361 -text 108 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 256 337 140 337 140 385 256 385 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 107
+ set {floorItems(107)} $i
+ $w create text 198 361 -text 107 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 300 353 300 329 260 329 260 353 -fill {} -tags {floor1 room}]
+ set floorLabels($i) Smoking
+ set {floorItems(Smoking)} $i
+ $w create text 280 341 -text Smoking -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 314 135 314 170 306 170 306 246 177 246 177 135 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 123
+ set {floorItems(123)} $i
+ $w create text 245.5 190.5 -text 123 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 217 248 301 248 301 326 257 326 257 310 217 310 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 103
+ set {floorItems(103)} $i
+ $w create text 259 287 -text 103 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 396 188 377 188 377 169 316 169 316 131 396 131 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 124
+ set {floorItems(124)} $i
+ $w create text 356 150 -text 124 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 397 226 407 226 407 189 377 189 377 246 397 246 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 125
+ set {floorItems(125)} $i
+ $w create text 392 217.5 -text 125 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 399 187 409 187 409 207 474 207 474 164 399 164 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 126
+ set {floorItems(126)} $i
+ $w create text 436.5 185.5 -text 126 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 409 209 409 229 399 229 399 253 486 253 486 239 474 239 474 209 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 127
+ set {floorItems(127)} $i
+ $w create text 436.5 231 -text 127 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 501 164 501 174 495 174 495 188 490 188 490 204 476 204 476 164 -fill {} -tags {floor1 room}]
+ set floorLabels($i) MShower
+ set {floorItems(MShower)} $i
+ $w create text 488.5 184 -text MShower -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 497 176 513 176 513 204 492 204 492 190 497 190 -fill {} -tags {floor1 room}]
+ set floorLabels($i) Closet
+ set {floorItems(Closet)} $i
+ $w create text 502.5 190 -text Closet -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 476 237 476 206 513 206 513 254 488 254 488 237 -fill {} -tags {floor1 room}]
+ set floorLabels($i) WShower
+ set {floorItems(WShower)} $i
+ $w create text 494.5 230 -text WShower -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 486 131 558 131 558 135 724 135 724 166 697 166 697 275 553 275 531 254 515 254 515 174 503 174 503 161 486 161 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 130
+ set {floorItems(130)} $i
+ $w create text 638.5 205 -text 130 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 308 242 339 242 339 248 342 248 342 246 397 246 397 276 393 276 393 309 300 309 300 248 308 248 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 102
+ set {floorItems(102)} $i
+ $w create text 367.5 278.5 -text 102 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 397 255 486 255 486 276 397 276 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 128
+ set {floorItems(128)} $i
+ $w create text 441.5 265.5 -text 128 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 510 309 486 309 486 255 530 255 552 277 561 277 561 325 510 325 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 129
+ set {floorItems(129)} $i
+ $w create text 535.5 293 -text 129 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 696 281 740 281 740 387 642 387 642 389 561 389 561 277 696 277 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 133
+ set {floorItems(133)} $i
+ $w create text 628.5 335 -text 133 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 742 387 742 281 800 281 800 387 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 132
+ set {floorItems(132)} $i
+ $w create text 771 334 -text 132 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 800 168 800 280 699 280 699 168 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 134
+ set {floorItems(134)} $i
+ $w create text 749.5 224 -text 134 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 726 131 726 166 800 166 800 131 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 135
+ set {floorItems(135)} $i
+ $w create text 763 148.5 -text 135 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 340 360 335 363 331 365 326 366 304 366 304 312 396 312 396 288 400 288 404 288 409 290 413 292 418 297 421 302 422 309 421 318 417 325 411 330 405 332 397 333 344 333 340 334 336 336 335 338 332 342 331 347 332 351 334 354 336 357 341 359 -fill {} -tags {floor1 room}]
+ set floorLabels($i) {Ramona Stair}
+ set {floorItems(Ramona Stair)} $i
+ $w create text 368 323 -text {Ramona Stair} -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 30 23 30 5 93 5 98 5 104 7 110 10 116 16 119 20 122 28 123 32 123 68 220 68 220 87 90 87 90 23 -fill {} -tags {floor1 room}]
+ set floorLabels($i) {University Stair}
+ set {floorItems(University Stair)} $i
+ $w create text 155 77.5 -text {University Stair} -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 282 37 295 40 312 49 323 56 337 70 352 56 358 48 363 39 365 29 348 25 335 22 321 14 300 5 283 1 260 0 246 0 242 2 236 4 231 8 227 13 223 17 221 22 220 34 260 34 -fill {} -tags {floor1 room}]
+ set floorLabels($i) {Plaza Stair}
+ set {floorItems(Plaza Stair)} $i
+ $w create text 317.5 28.5 -text {Plaza Stair} -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 220 34 260 34 282 37 295 40 312 49 323 56 337 70 350 83 365 94 377 100 386 104 386 128 220 128 -fill {} -tags {floor1 room}]
+ set floorLabels($i) {Plaza Deck}
+ set {floorItems(Plaza Deck)} $i
+ $w create text 303 81 -text {Plaza Deck} -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 257 336 77 336 6 336 6 301 77 301 77 310 257 310 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 106
+ set {floorItems(106)} $i
+ $w create text 131.5 318.5 -text 106 -fill $color -anchor c -tags {floor1 label}
+ set i [$w create polygon 146 110 162 110 162 91 130 91 130 115 95 115 95 128 114 128 114 151 157 151 157 153 112 153 112 130 97 130 97 168 175 168 175 131 146 131 -fill {} -tags {floor1 room}]
+ set floorLabels($i) 119
+ set {floorItems(119)} $i
+ $w create text 143.5 133 -text 119 -fill $color -anchor c -tags {floor1 label}
+ $w create line 155 191 155 189 -fill $color -tags {floor1 wall}
+ $w create line 155 177 155 169 -fill $color -tags {floor1 wall}
+ $w create line 96 129 96 169 -fill $color -tags {floor1 wall}
+ $w create line 78 169 176 169 -fill $color -tags {floor1 wall}
+ $w create line 176 247 176 129 -fill $color -tags {floor1 wall}
+ $w create line 340 206 307 206 -fill $color -tags {floor1 wall}
+ $w create line 340 187 340 170 -fill $color -tags {floor1 wall}
+ $w create line 340 210 340 201 -fill $color -tags {floor1 wall}
+ $w create line 340 247 340 224 -fill $color -tags {floor1 wall}
+ $w create line 340 241 307 241 -fill $color -tags {floor1 wall}
+ $w create line 376 246 376 170 -fill $color -tags {floor1 wall}
+ $w create line 307 247 307 170 -fill $color -tags {floor1 wall}
+ $w create line 376 170 307 170 -fill $color -tags {floor1 wall}
+ $w create line 315 129 315 170 -fill $color -tags {floor1 wall}
+ $w create line 147 129 176 129 -fill $color -tags {floor1 wall}
+ $w create line 202 133 176 133 -fill $color -tags {floor1 wall}
+ $w create line 398 129 315 129 -fill $color -tags {floor1 wall}
+ $w create line 258 352 258 387 -fill $color -tags {floor1 wall}
+ $w create line 60 387 60 391 -fill $color -tags {floor1 wall}
+ $w create line 0 337 0 391 -fill $color -tags {floor1 wall}
+ $w create line 60 391 0 391 -fill $color -tags {floor1 wall}
+ $w create line 3 114 3 337 -fill $color -tags {floor1 wall}
+ $w create line 258 387 60 387 -fill $color -tags {floor1 wall}
+ $w create line 52 237 52 273 -fill $color -tags {floor1 wall}
+ $w create line 52 189 52 225 -fill $color -tags {floor1 wall}
+ $w create line 52 140 52 177 -fill $color -tags {floor1 wall}
+ $w create line 395 306 395 311 -fill $color -tags {floor1 wall}
+ $w create line 531 254 398 254 -fill $color -tags {floor1 wall}
+ $w create line 475 178 475 238 -fill $color -tags {floor1 wall}
+ $w create line 502 162 398 162 -fill $color -tags {floor1 wall}
+ $w create line 398 129 398 188 -fill $color -tags {floor1 wall}
+ $w create line 383 188 376 188 -fill $color -tags {floor1 wall}
+ $w create line 408 188 408 194 -fill $color -tags {floor1 wall}
+ $w create line 398 227 398 254 -fill $color -tags {floor1 wall}
+ $w create line 408 227 398 227 -fill $color -tags {floor1 wall}
+ $w create line 408 222 408 227 -fill $color -tags {floor1 wall}
+ $w create line 408 206 408 210 -fill $color -tags {floor1 wall}
+ $w create line 408 208 475 208 -fill $color -tags {floor1 wall}
+ $w create line 484 278 484 311 -fill $color -tags {floor1 wall}
+ $w create line 484 311 508 311 -fill $color -tags {floor1 wall}
+ $w create line 508 327 508 311 -fill $color -tags {floor1 wall}
+ $w create line 559 327 508 327 -fill $color -tags {floor1 wall}
+ $w create line 644 391 559 391 -fill $color -tags {floor1 wall}
+ $w create line 644 389 644 391 -fill $color -tags {floor1 wall}
+ $w create line 514 205 475 205 -fill $color -tags {floor1 wall}
+ $w create line 496 189 496 187 -fill $color -tags {floor1 wall}
+ $w create line 559 129 484 129 -fill $color -tags {floor1 wall}
+ $w create line 484 162 484 129 -fill $color -tags {floor1 wall}
+ $w create line 725 133 559 133 -fill $color -tags {floor1 wall}
+ $w create line 559 129 559 133 -fill $color -tags {floor1 wall}
+ $w create line 725 149 725 167 -fill $color -tags {floor1 wall}
+ $w create line 725 129 802 129 -fill $color -tags {floor1 wall}
+ $w create line 802 389 802 129 -fill $color -tags {floor1 wall}
+ $w create line 739 167 802 167 -fill $color -tags {floor1 wall}
+ $w create line 396 188 408 188 -fill $color -tags {floor1 wall}
+ $w create line 0 337 9 337 -fill $color -tags {floor1 wall}
+ $w create line 58 337 21 337 -fill $color -tags {floor1 wall}
+ $w create line 43 391 43 337 -fill $color -tags {floor1 wall}
+ $w create line 105 337 75 337 -fill $color -tags {floor1 wall}
+ $w create line 91 387 91 337 -fill $color -tags {floor1 wall}
+ $w create line 154 337 117 337 -fill $color -tags {floor1 wall}
+ $w create line 139 387 139 337 -fill $color -tags {floor1 wall}
+ $w create line 227 337 166 337 -fill $color -tags {floor1 wall}
+ $w create line 258 337 251 337 -fill $color -tags {floor1 wall}
+ $w create line 258 328 302 328 -fill $color -tags {floor1 wall}
+ $w create line 302 355 302 311 -fill $color -tags {floor1 wall}
+ $w create line 395 311 302 311 -fill $color -tags {floor1 wall}
+ $w create line 484 278 395 278 -fill $color -tags {floor1 wall}
+ $w create line 395 294 395 278 -fill $color -tags {floor1 wall}
+ $w create line 473 278 473 275 -fill $color -tags {floor1 wall}
+ $w create line 473 256 473 254 -fill $color -tags {floor1 wall}
+ $w create line 533 257 531 254 -fill $color -tags {floor1 wall}
+ $w create line 553 276 551 274 -fill $color -tags {floor1 wall}
+ $w create line 698 276 553 276 -fill $color -tags {floor1 wall}
+ $w create line 559 391 559 327 -fill $color -tags {floor1 wall}
+ $w create line 802 389 644 389 -fill $color -tags {floor1 wall}
+ $w create line 741 314 741 389 -fill $color -tags {floor1 wall}
+ $w create line 698 280 698 167 -fill $color -tags {floor1 wall}
+ $w create line 707 280 698 280 -fill $color -tags {floor1 wall}
+ $w create line 802 280 731 280 -fill $color -tags {floor1 wall}
+ $w create line 741 280 741 302 -fill $color -tags {floor1 wall}
+ $w create line 698 167 727 167 -fill $color -tags {floor1 wall}
+ $w create line 725 137 725 129 -fill $color -tags {floor1 wall}
+ $w create line 514 254 514 175 -fill $color -tags {floor1 wall}
+ $w create line 496 175 514 175 -fill $color -tags {floor1 wall}
+ $w create line 502 175 502 162 -fill $color -tags {floor1 wall}
+ $w create line 475 166 475 162 -fill $color -tags {floor1 wall}
+ $w create line 496 176 496 175 -fill $color -tags {floor1 wall}
+ $w create line 491 189 496 189 -fill $color -tags {floor1 wall}
+ $w create line 491 205 491 189 -fill $color -tags {floor1 wall}
+ $w create line 487 238 475 238 -fill $color -tags {floor1 wall}
+ $w create line 487 240 487 238 -fill $color -tags {floor1 wall}
+ $w create line 487 252 487 254 -fill $color -tags {floor1 wall}
+ $w create line 315 133 304 133 -fill $color -tags {floor1 wall}
+ $w create line 256 133 280 133 -fill $color -tags {floor1 wall}
+ $w create line 78 247 270 247 -fill $color -tags {floor1 wall}
+ $w create line 307 247 294 247 -fill $color -tags {floor1 wall}
+ $w create line 214 133 232 133 -fill $color -tags {floor1 wall}
+ $w create line 217 247 217 266 -fill $color -tags {floor1 wall}
+ $w create line 217 309 217 291 -fill $color -tags {floor1 wall}
+ $w create line 217 309 172 309 -fill $color -tags {floor1 wall}
+ $w create line 154 309 148 309 -fill $color -tags {floor1 wall}
+ $w create line 175 300 175 309 -fill $color -tags {floor1 wall}
+ $w create line 151 300 175 300 -fill $color -tags {floor1 wall}
+ $w create line 151 247 151 309 -fill $color -tags {floor1 wall}
+ $w create line 78 237 78 265 -fill $color -tags {floor1 wall}
+ $w create line 78 286 78 309 -fill $color -tags {floor1 wall}
+ $w create line 106 309 78 309 -fill $color -tags {floor1 wall}
+ $w create line 130 309 125 309 -fill $color -tags {floor1 wall}
+ $w create line 99 309 99 247 -fill $color -tags {floor1 wall}
+ $w create line 127 299 99 299 -fill $color -tags {floor1 wall}
+ $w create line 127 309 127 299 -fill $color -tags {floor1 wall}
+ $w create line 155 191 137 191 -fill $color -tags {floor1 wall}
+ $w create line 137 169 137 191 -fill $color -tags {floor1 wall}
+ $w create line 78 171 78 169 -fill $color -tags {floor1 wall}
+ $w create line 78 190 78 218 -fill $color -tags {floor1 wall}
+ $w create line 86 192 86 169 -fill $color -tags {floor1 wall}
+ $w create line 86 192 78 192 -fill $color -tags {floor1 wall}
+ $w create line 52 301 3 301 -fill $color -tags {floor1 wall}
+ $w create line 52 286 52 301 -fill $color -tags {floor1 wall}
+ $w create line 52 252 3 252 -fill $color -tags {floor1 wall}
+ $w create line 52 203 3 203 -fill $color -tags {floor1 wall}
+ $w create line 3 156 52 156 -fill $color -tags {floor1 wall}
+ $w create line 8 25 8 114 -fill $color -tags {floor1 wall}
+ $w create line 63 114 3 114 -fill $color -tags {floor1 wall}
+ $w create line 75 114 97 114 -fill $color -tags {floor1 wall}
+ $w create line 108 114 129 114 -fill $color -tags {floor1 wall}
+ $w create line 129 114 129 89 -fill $color -tags {floor1 wall}
+ $w create line 52 114 52 128 -fill $color -tags {floor1 wall}
+ $w create line 132 89 88 89 -fill $color -tags {floor1 wall}
+ $w create line 88 25 88 89 -fill $color -tags {floor1 wall}
+ $w create line 88 114 88 89 -fill $color -tags {floor1 wall}
+ $w create line 218 89 144 89 -fill $color -tags {floor1 wall}
+ $w create line 147 111 147 129 -fill $color -tags {floor1 wall}
+ $w create line 162 111 147 111 -fill $color -tags {floor1 wall}
+ $w create line 162 109 162 111 -fill $color -tags {floor1 wall}
+ $w create line 162 96 162 89 -fill $color -tags {floor1 wall}
+ $w create line 218 89 218 94 -fill $color -tags {floor1 wall}
+ $w create line 218 89 218 119 -fill $color -tags {floor1 wall}
+ $w create line 8 25 88 25 -fill $color -tags {floor1 wall}
+ $w create line 258 337 258 328 -fill $color -tags {floor1 wall}
+ $w create line 113 129 96 129 -fill $color -tags {floor1 wall}
+ $w create line 302 355 258 355 -fill $color -tags {floor1 wall}
+ $w create line 386 104 386 129 -fill $color -tags {floor1 wall}
+ $w create line 377 100 386 104 -fill $color -tags {floor1 wall}
+ $w create line 365 94 377 100 -fill $color -tags {floor1 wall}
+ $w create line 350 83 365 94 -fill $color -tags {floor1 wall}
+ $w create line 337 70 350 83 -fill $color -tags {floor1 wall}
+ $w create line 337 70 323 56 -fill $color -tags {floor1 wall}
+ $w create line 312 49 323 56 -fill $color -tags {floor1 wall}
+ $w create line 295 40 312 49 -fill $color -tags {floor1 wall}
+ $w create line 282 37 295 40 -fill $color -tags {floor1 wall}
+ $w create line 260 34 282 37 -fill $color -tags {floor1 wall}
+ $w create line 253 34 260 34 -fill $color -tags {floor1 wall}
+ $w create line 386 128 386 104 -fill $color -tags {floor1 wall}
+ $w create line 113 152 156 152 -fill $color -tags {floor1 wall}
+ $w create line 113 152 156 152 -fill $color -tags {floor1 wall}
+ $w create line 113 152 113 129 -fill $color -tags {floor1 wall}
+}
+
+# fg2 --
+# This procedure represents part of the floorplan database. When
+# invoked, it instantiates the foreground information for the second
+# floor (office outlines and numbers).
+#
+# Arguments:
+# w - The canvas window.
+# color - Color to use for drawing foreground information.
+
+proc fg2 {w color} {
+ global floorLabels floorItems
+ set i [$w create polygon 748 188 755 188 755 205 758 205 758 222 800 222 800 168 748 168 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 238
+ set {floorItems(238)} $i
+ $w create text 774 195 -text 238 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 726 188 746 188 746 166 800 166 800 131 726 131 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 237
+ set {floorItems(237)} $i
+ $w create text 763 148.5 -text 237 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 497 187 497 204 559 204 559 324 641 324 643 324 643 291 641 291 641 205 696 205 696 291 694 291 694 314 715 314 715 291 715 205 755 205 755 190 724 190 724 187 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 246
+ set {floorItems(246)} $i
+ $w create text 600 264 -text 246 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 694 279 643 279 643 314 694 314 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 247
+ set {floorItems(247)} $i
+ $w create text 668.5 296.5 -text 247 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 232 250 308 250 308 242 339 242 339 246 397 246 397 255 476 255 476 250 482 250 559 250 559 274 482 274 482 278 396 278 396 274 232 274 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 202
+ set {floorItems(202)} $i
+ $w create text 285.5 260 -text 202 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 53 228 53 338 176 338 233 338 233 196 306 196 306 180 175 180 175 169 156 169 156 196 176 196 176 228 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 206
+ set {floorItems(206)} $i
+ $w create text 143 267 -text 206 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 51 277 6 277 6 338 51 338 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 212
+ set {floorItems(212)} $i
+ $w create text 28.5 307.5 -text 212 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 557 276 486 276 486 309 510 309 510 325 557 325 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 245
+ set {floorItems(245)} $i
+ $w create text 521.5 300.5 -text 245 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 560 389 599 389 599 326 560 326 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 244
+ set {floorItems(244)} $i
+ $w create text 579.5 357.5 -text 244 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 601 389 601 326 643 326 643 389 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 243
+ set {floorItems(243)} $i
+ $w create text 622 357.5 -text 243 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 688 316 645 316 645 365 688 365 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 242
+ set {floorItems(242)} $i
+ $w create text 666.5 340.5 -text 242 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 802 367 759 367 759 226 802 226 -fill {} -tags {floor2 room}]
+ set floorLabels($i) {Barbecue Deck}
+ set {floorItems(Barbecue Deck)} $i
+ $w create text 780.5 296.5 -text {Barbecue Deck} -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 755 262 755 314 717 314 717 262 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 240
+ set {floorItems(240)} $i
+ $w create text 736 288 -text 240 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 755 316 689 316 689 365 755 365 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 241
+ set {floorItems(241)} $i
+ $w create text 722 340.5 -text 241 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 755 206 717 206 717 261 755 261 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 239
+ set {floorItems(239)} $i
+ $w create text 736 233.5 -text 239 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 695 277 643 277 643 206 695 206 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 248
+ set {floorItems(248)} $i
+ $w create text 669 241.5 -text 248 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 676 135 676 185 724 185 724 135 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 236
+ set {floorItems(236)} $i
+ $w create text 700 160 -text 236 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 675 135 635 135 635 145 628 145 628 185 675 185 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 235
+ set {floorItems(235)} $i
+ $w create text 651.5 160 -text 235 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 626 143 633 143 633 135 572 135 572 143 579 143 579 185 626 185 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 234
+ set {floorItems(234)} $i
+ $w create text 606 160 -text 234 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 557 135 571 135 571 145 578 145 578 185 527 185 527 131 557 131 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 233
+ set {floorItems(233)} $i
+ $w create text 552.5 158 -text 233 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 476 249 557 249 557 205 476 205 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 230
+ set {floorItems(230)} $i
+ $w create text 516.5 227 -text 230 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 476 164 486 164 486 131 525 131 525 185 476 185 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 232
+ set {floorItems(232)} $i
+ $w create text 500.5 158 -text 232 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 476 186 495 186 495 204 476 204 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 229
+ set {floorItems(229)} $i
+ $w create text 485.5 195 -text 229 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 474 207 409 207 409 187 399 187 399 164 474 164 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 227
+ set {floorItems(227)} $i
+ $w create text 436.5 185.5 -text 227 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 399 228 399 253 474 253 474 209 409 209 409 228 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 228
+ set {floorItems(228)} $i
+ $w create text 436.5 231 -text 228 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 397 246 397 226 407 226 407 189 377 189 377 246 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 226
+ set {floorItems(226)} $i
+ $w create text 392 217.5 -text 226 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 377 169 316 169 316 131 397 131 397 188 377 188 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 225
+ set {floorItems(225)} $i
+ $w create text 356.5 150 -text 225 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 234 198 306 198 306 249 234 249 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 224
+ set {floorItems(224)} $i
+ $w create text 270 223.5 -text 224 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 270 179 306 179 306 170 314 170 314 135 270 135 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 223
+ set {floorItems(223)} $i
+ $w create text 292 157 -text 223 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 268 179 221 179 221 135 268 135 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 222
+ set {floorItems(222)} $i
+ $w create text 244.5 157 -text 222 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 177 179 219 179 219 135 177 135 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 221
+ set {floorItems(221)} $i
+ $w create text 198 157 -text 221 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 299 327 349 327 349 284 341 284 341 276 299 276 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 204
+ set {floorItems(204)} $i
+ $w create text 324 301.5 -text 204 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 234 276 297 276 297 327 257 327 257 338 234 338 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 205
+ set {floorItems(205)} $i
+ $w create text 265.5 307 -text 205 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 256 385 256 340 212 340 212 385 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 207
+ set {floorItems(207)} $i
+ $w create text 234 362.5 -text 207 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 210 340 164 340 164 385 210 385 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 208
+ set {floorItems(208)} $i
+ $w create text 187 362.5 -text 208 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 115 340 162 340 162 385 115 385 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 209
+ set {floorItems(209)} $i
+ $w create text 138.5 362.5 -text 209 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 89 228 89 156 53 156 53 228 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 217
+ set {floorItems(217)} $i
+ $w create text 71 192 -text 217 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 89 169 97 169 97 190 89 190 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 217A
+ set {floorItems(217A)} $i
+ $w create text 93 179.5 -text 217A -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 89 156 89 168 95 168 95 135 53 135 53 156 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 216
+ set {floorItems(216)} $i
+ $w create text 71 145.5 -text 216 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 51 179 51 135 6 135 6 179 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 215
+ set {floorItems(215)} $i
+ $w create text 28.5 157 -text 215 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 51 227 6 227 6 180 51 180 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 214
+ set {floorItems(214)} $i
+ $w create text 28.5 203.5 -text 214 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 51 275 6 275 6 229 51 229 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 213
+ set {floorItems(213)} $i
+ $w create text 28.5 252 -text 213 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 114 340 67 340 67 385 114 385 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 210
+ set {floorItems(210)} $i
+ $w create text 90.5 362.5 -text 210 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 59 389 59 385 65 385 65 340 1 340 1 389 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 211
+ set {floorItems(211)} $i
+ $w create text 33 364.5 -text 211 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 393 309 350 309 350 282 342 282 342 276 393 276 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 203
+ set {floorItems(203)} $i
+ $w create text 367.5 292.5 -text 203 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 99 191 91 191 91 226 174 226 174 198 154 198 154 192 109 192 109 169 99 169 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 220
+ set {floorItems(220)} $i
+ $w create text 132.5 208.5 -text 220 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 339 205 307 205 307 171 339 171 -fill {} -tags {floor2 room}]
+ set floorLabels($i) {Priv Lift2}
+ set {floorItems(Priv Lift2)} $i
+ $w create text 323 188 -text {Priv Lift2} -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 307 240 339 240 339 206 307 206 -fill {} -tags {floor2 room}]
+ set floorLabels($i) {Pub Lift 2}
+ set {floorItems(Pub Lift 2)} $i
+ $w create text 323 223 -text {Pub Lift 2} -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 175 168 97 168 97 131 175 131 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 218
+ set {floorItems(218)} $i
+ $w create text 136 149.5 -text 218 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 154 191 111 191 111 169 154 169 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 219
+ set {floorItems(219)} $i
+ $w create text 132.5 180 -text 219 -fill $color -anchor c -tags {floor2 label}
+ set i [$w create polygon 375 246 375 172 341 172 341 246 -fill {} -tags {floor2 room}]
+ set floorLabels($i) 201
+ set {floorItems(201)} $i
+ $w create text 358 209 -text 201 -fill $color -anchor c -tags {floor2 label}
+ $w create line 641 186 678 186 -fill $color -tags {floor2 wall}
+ $w create line 757 350 757 367 -fill $color -tags {floor2 wall}
+ $w create line 634 133 634 144 -fill $color -tags {floor2 wall}
+ $w create line 634 144 627 144 -fill $color -tags {floor2 wall}
+ $w create line 572 133 572 144 -fill $color -tags {floor2 wall}
+ $w create line 572 144 579 144 -fill $color -tags {floor2 wall}
+ $w create line 398 129 398 162 -fill $color -tags {floor2 wall}
+ $w create line 174 197 175 197 -fill $color -tags {floor2 wall}
+ $w create line 175 197 175 227 -fill $color -tags {floor2 wall}
+ $w create line 757 206 757 221 -fill $color -tags {floor2 wall}
+ $w create line 396 188 408 188 -fill $color -tags {floor2 wall}
+ $w create line 727 189 725 189 -fill $color -tags {floor2 wall}
+ $w create line 747 167 802 167 -fill $color -tags {floor2 wall}
+ $w create line 747 167 747 189 -fill $color -tags {floor2 wall}
+ $w create line 755 189 739 189 -fill $color -tags {floor2 wall}
+ $w create line 769 224 757 224 -fill $color -tags {floor2 wall}
+ $w create line 802 224 802 129 -fill $color -tags {floor2 wall}
+ $w create line 802 129 725 129 -fill $color -tags {floor2 wall}
+ $w create line 725 189 725 129 -fill $color -tags {floor2 wall}
+ $w create line 725 186 690 186 -fill $color -tags {floor2 wall}
+ $w create line 676 133 676 186 -fill $color -tags {floor2 wall}
+ $w create line 627 144 627 186 -fill $color -tags {floor2 wall}
+ $w create line 629 186 593 186 -fill $color -tags {floor2 wall}
+ $w create line 579 144 579 186 -fill $color -tags {floor2 wall}
+ $w create line 559 129 559 133 -fill $color -tags {floor2 wall}
+ $w create line 725 133 559 133 -fill $color -tags {floor2 wall}
+ $w create line 484 162 484 129 -fill $color -tags {floor2 wall}
+ $w create line 559 129 484 129 -fill $color -tags {floor2 wall}
+ $w create line 526 129 526 186 -fill $color -tags {floor2 wall}
+ $w create line 540 186 581 186 -fill $color -tags {floor2 wall}
+ $w create line 528 186 523 186 -fill $color -tags {floor2 wall}
+ $w create line 511 186 475 186 -fill $color -tags {floor2 wall}
+ $w create line 496 190 496 186 -fill $color -tags {floor2 wall}
+ $w create line 496 205 496 202 -fill $color -tags {floor2 wall}
+ $w create line 475 205 527 205 -fill $color -tags {floor2 wall}
+ $w create line 558 205 539 205 -fill $color -tags {floor2 wall}
+ $w create line 558 205 558 249 -fill $color -tags {floor2 wall}
+ $w create line 558 249 475 249 -fill $color -tags {floor2 wall}
+ $w create line 662 206 642 206 -fill $color -tags {floor2 wall}
+ $w create line 695 206 675 206 -fill $color -tags {floor2 wall}
+ $w create line 695 278 642 278 -fill $color -tags {floor2 wall}
+ $w create line 642 291 642 206 -fill $color -tags {floor2 wall}
+ $w create line 695 291 695 206 -fill $color -tags {floor2 wall}
+ $w create line 716 208 716 206 -fill $color -tags {floor2 wall}
+ $w create line 757 206 716 206 -fill $color -tags {floor2 wall}
+ $w create line 757 221 757 224 -fill $color -tags {floor2 wall}
+ $w create line 793 224 802 224 -fill $color -tags {floor2 wall}
+ $w create line 757 262 716 262 -fill $color -tags {floor2 wall}
+ $w create line 716 220 716 264 -fill $color -tags {floor2 wall}
+ $w create line 716 315 716 276 -fill $color -tags {floor2 wall}
+ $w create line 757 315 703 315 -fill $color -tags {floor2 wall}
+ $w create line 757 325 757 224 -fill $color -tags {floor2 wall}
+ $w create line 757 367 644 367 -fill $color -tags {floor2 wall}
+ $w create line 689 367 689 315 -fill $color -tags {floor2 wall}
+ $w create line 647 315 644 315 -fill $color -tags {floor2 wall}
+ $w create line 659 315 691 315 -fill $color -tags {floor2 wall}
+ $w create line 600 325 600 391 -fill $color -tags {floor2 wall}
+ $w create line 627 325 644 325 -fill $color -tags {floor2 wall}
+ $w create line 644 391 644 315 -fill $color -tags {floor2 wall}
+ $w create line 615 325 575 325 -fill $color -tags {floor2 wall}
+ $w create line 644 391 558 391 -fill $color -tags {floor2 wall}
+ $w create line 563 325 558 325 -fill $color -tags {floor2 wall}
+ $w create line 558 391 558 314 -fill $color -tags {floor2 wall}
+ $w create line 558 327 508 327 -fill $color -tags {floor2 wall}
+ $w create line 558 275 484 275 -fill $color -tags {floor2 wall}
+ $w create line 558 302 558 275 -fill $color -tags {floor2 wall}
+ $w create line 508 327 508 311 -fill $color -tags {floor2 wall}
+ $w create line 484 311 508 311 -fill $color -tags {floor2 wall}
+ $w create line 484 275 484 311 -fill $color -tags {floor2 wall}
+ $w create line 475 208 408 208 -fill $color -tags {floor2 wall}
+ $w create line 408 206 408 210 -fill $color -tags {floor2 wall}
+ $w create line 408 222 408 227 -fill $color -tags {floor2 wall}
+ $w create line 408 227 398 227 -fill $color -tags {floor2 wall}
+ $w create line 398 227 398 254 -fill $color -tags {floor2 wall}
+ $w create line 408 188 408 194 -fill $color -tags {floor2 wall}
+ $w create line 383 188 376 188 -fill $color -tags {floor2 wall}
+ $w create line 398 188 398 162 -fill $color -tags {floor2 wall}
+ $w create line 398 162 484 162 -fill $color -tags {floor2 wall}
+ $w create line 475 162 475 254 -fill $color -tags {floor2 wall}
+ $w create line 398 254 475 254 -fill $color -tags {floor2 wall}
+ $w create line 484 280 395 280 -fill $color -tags {floor2 wall}
+ $w create line 395 311 395 275 -fill $color -tags {floor2 wall}
+ $w create line 307 197 293 197 -fill $color -tags {floor2 wall}
+ $w create line 278 197 233 197 -fill $color -tags {floor2 wall}
+ $w create line 233 197 233 249 -fill $color -tags {floor2 wall}
+ $w create line 307 179 284 179 -fill $color -tags {floor2 wall}
+ $w create line 233 249 278 249 -fill $color -tags {floor2 wall}
+ $w create line 269 179 269 133 -fill $color -tags {floor2 wall}
+ $w create line 220 179 220 133 -fill $color -tags {floor2 wall}
+ $w create line 155 191 110 191 -fill $color -tags {floor2 wall}
+ $w create line 90 190 98 190 -fill $color -tags {floor2 wall}
+ $w create line 98 169 98 190 -fill $color -tags {floor2 wall}
+ $w create line 52 133 52 165 -fill $color -tags {floor2 wall}
+ $w create line 52 214 52 177 -fill $color -tags {floor2 wall}
+ $w create line 52 226 52 262 -fill $color -tags {floor2 wall}
+ $w create line 52 274 52 276 -fill $color -tags {floor2 wall}
+ $w create line 234 275 234 339 -fill $color -tags {floor2 wall}
+ $w create line 226 339 258 339 -fill $color -tags {floor2 wall}
+ $w create line 211 387 211 339 -fill $color -tags {floor2 wall}
+ $w create line 214 339 177 339 -fill $color -tags {floor2 wall}
+ $w create line 258 387 60 387 -fill $color -tags {floor2 wall}
+ $w create line 3 133 3 339 -fill $color -tags {floor2 wall}
+ $w create line 165 339 129 339 -fill $color -tags {floor2 wall}
+ $w create line 117 339 80 339 -fill $color -tags {floor2 wall}
+ $w create line 68 339 59 339 -fill $color -tags {floor2 wall}
+ $w create line 0 339 46 339 -fill $color -tags {floor2 wall}
+ $w create line 60 391 0 391 -fill $color -tags {floor2 wall}
+ $w create line 0 339 0 391 -fill $color -tags {floor2 wall}
+ $w create line 60 387 60 391 -fill $color -tags {floor2 wall}
+ $w create line 258 329 258 387 -fill $color -tags {floor2 wall}
+ $w create line 350 329 258 329 -fill $color -tags {floor2 wall}
+ $w create line 395 311 350 311 -fill $color -tags {floor2 wall}
+ $w create line 398 129 315 129 -fill $color -tags {floor2 wall}
+ $w create line 176 133 315 133 -fill $color -tags {floor2 wall}
+ $w create line 176 129 96 129 -fill $color -tags {floor2 wall}
+ $w create line 3 133 96 133 -fill $color -tags {floor2 wall}
+ $w create line 66 387 66 339 -fill $color -tags {floor2 wall}
+ $w create line 115 387 115 339 -fill $color -tags {floor2 wall}
+ $w create line 163 387 163 339 -fill $color -tags {floor2 wall}
+ $w create line 234 275 276 275 -fill $color -tags {floor2 wall}
+ $w create line 288 275 309 275 -fill $color -tags {floor2 wall}
+ $w create line 298 275 298 329 -fill $color -tags {floor2 wall}
+ $w create line 341 283 350 283 -fill $color -tags {floor2 wall}
+ $w create line 321 275 341 275 -fill $color -tags {floor2 wall}
+ $w create line 375 275 395 275 -fill $color -tags {floor2 wall}
+ $w create line 315 129 315 170 -fill $color -tags {floor2 wall}
+ $w create line 376 170 307 170 -fill $color -tags {floor2 wall}
+ $w create line 307 250 307 170 -fill $color -tags {floor2 wall}
+ $w create line 376 245 376 170 -fill $color -tags {floor2 wall}
+ $w create line 340 241 307 241 -fill $color -tags {floor2 wall}
+ $w create line 340 245 340 224 -fill $color -tags {floor2 wall}
+ $w create line 340 210 340 201 -fill $color -tags {floor2 wall}
+ $w create line 340 187 340 170 -fill $color -tags {floor2 wall}
+ $w create line 340 206 307 206 -fill $color -tags {floor2 wall}
+ $w create line 293 250 307 250 -fill $color -tags {floor2 wall}
+ $w create line 271 179 238 179 -fill $color -tags {floor2 wall}
+ $w create line 226 179 195 179 -fill $color -tags {floor2 wall}
+ $w create line 176 129 176 179 -fill $color -tags {floor2 wall}
+ $w create line 182 179 176 179 -fill $color -tags {floor2 wall}
+ $w create line 174 169 176 169 -fill $color -tags {floor2 wall}
+ $w create line 162 169 90 169 -fill $color -tags {floor2 wall}
+ $w create line 96 169 96 129 -fill $color -tags {floor2 wall}
+ $w create line 175 227 90 227 -fill $color -tags {floor2 wall}
+ $w create line 90 190 90 227 -fill $color -tags {floor2 wall}
+ $w create line 52 179 3 179 -fill $color -tags {floor2 wall}
+ $w create line 52 228 3 228 -fill $color -tags {floor2 wall}
+ $w create line 52 276 3 276 -fill $color -tags {floor2 wall}
+ $w create line 155 177 155 169 -fill $color -tags {floor2 wall}
+ $w create line 110 191 110 169 -fill $color -tags {floor2 wall}
+ $w create line 155 189 155 197 -fill $color -tags {floor2 wall}
+ $w create line 350 283 350 329 -fill $color -tags {floor2 wall}
+ $w create line 162 197 155 197 -fill $color -tags {floor2 wall}
+ $w create line 341 275 341 283 -fill $color -tags {floor2 wall}
+}
+
+# fg3 --
+# This procedure represents part of the floorplan database. When
+# invoked, it instantiates the foreground information for the third
+# floor (office outlines and numbers).
+#
+# Arguments:
+# w - The canvas window.
+# color - Color to use for drawing foreground information.
+
+proc fg3 {w color} {
+ global floorLabels floorItems
+ set i [$w create polygon 89 228 89 180 70 180 70 228 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 316
+ set {floorItems(316)} $i
+ $w create text 79.5 204 -text 316 -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 115 368 162 368 162 323 115 323 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 309
+ set {floorItems(309)} $i
+ $w create text 138.5 345.5 -text 309 -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 164 323 164 368 211 368 211 323 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 308
+ set {floorItems(308)} $i
+ $w create text 187.5 345.5 -text 308 -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 256 368 212 368 212 323 256 323 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 307
+ set {floorItems(307)} $i
+ $w create text 234 345.5 -text 307 -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 244 276 297 276 297 327 260 327 260 321 244 321 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 305
+ set {floorItems(305)} $i
+ $w create text 270.5 301.5 -text 305 -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 251 219 251 203 244 203 244 219 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 324B
+ set {floorItems(324B)} $i
+ $w create text 247.5 211 -text 324B -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 251 249 244 249 244 232 251 232 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 324A
+ set {floorItems(324A)} $i
+ $w create text 247.5 240.5 -text 324A -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 223 135 223 179 177 179 177 135 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 320
+ set {floorItems(320)} $i
+ $w create text 200 157 -text 320 -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 114 368 114 323 67 323 67 368 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 310
+ set {floorItems(310)} $i
+ $w create text 90.5 345.5 -text 310 -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 23 277 23 321 68 321 68 277 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 312
+ set {floorItems(312)} $i
+ $w create text 45.5 299 -text 312 -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 23 229 68 229 68 275 23 275 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 313
+ set {floorItems(313)} $i
+ $w create text 45.5 252 -text 313 -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 68 227 23 227 23 180 68 180 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 314
+ set {floorItems(314)} $i
+ $w create text 45.5 203.5 -text 314 -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 95 179 95 135 23 135 23 179 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 315
+ set {floorItems(315)} $i
+ $w create text 59 157 -text 315 -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 99 226 99 204 91 204 91 226 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 316B
+ set {floorItems(316B)} $i
+ $w create text 95 215 -text 316B -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 91 202 99 202 99 180 91 180 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 316A
+ set {floorItems(316A)} $i
+ $w create text 95 191 -text 316A -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 97 169 109 169 109 192 154 192 154 198 174 198 174 226 101 226 101 179 97 179 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 319
+ set {floorItems(319)} $i
+ $w create text 141.5 209 -text 319 -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 65 368 58 368 58 389 1 389 1 333 23 333 23 323 65 323 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 311
+ set {floorItems(311)} $i
+ $w create text 29.5 361 -text 311 -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 154 191 111 191 111 169 154 169 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 318
+ set {floorItems(318)} $i
+ $w create text 132.5 180 -text 318 -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 175 168 97 168 97 131 175 131 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 317
+ set {floorItems(317)} $i
+ $w create text 136 149.5 -text 317 -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 274 194 274 221 306 221 306 194 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 323
+ set {floorItems(323)} $i
+ $w create text 290 207.5 -text 323 -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 306 222 274 222 274 249 306 249 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 325
+ set {floorItems(325)} $i
+ $w create text 290 235.5 -text 325 -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 263 179 224 179 224 135 263 135 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 321
+ set {floorItems(321)} $i
+ $w create text 243.5 157 -text 321 -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 314 169 306 169 306 192 273 192 264 181 264 135 314 135 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 322
+ set {floorItems(322)} $i
+ $w create text 293.5 163.5 -text 322 -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 307 240 339 240 339 206 307 206 -fill {} -tags {floor3 room}]
+ set floorLabels($i) {Pub Lift3}
+ set {floorItems(Pub Lift3)} $i
+ $w create text 323 223 -text {Pub Lift3} -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 339 205 307 205 307 171 339 171 -fill {} -tags {floor3 room}]
+ set floorLabels($i) {Priv Lift3}
+ set {floorItems(Priv Lift3)} $i
+ $w create text 323 188 -text {Priv Lift3} -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 350 284 376 284 376 276 397 276 397 309 350 309 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 303
+ set {floorItems(303)} $i
+ $w create text 373.5 292.5 -text 303 -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 272 203 272 249 252 249 252 230 244 230 244 221 252 221 252 203 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 324
+ set {floorItems(324)} $i
+ $w create text 262 226 -text 324 -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 299 276 299 327 349 327 349 284 341 284 341 276 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 304
+ set {floorItems(304)} $i
+ $w create text 324 301.5 -text 304 -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 375 246 375 172 341 172 341 246 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 301
+ set {floorItems(301)} $i
+ $w create text 358 209 -text 301 -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 397 246 377 246 377 185 397 185 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 327
+ set {floorItems(327)} $i
+ $w create text 387 215.5 -text 327 -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 316 131 316 169 377 169 377 185 397 185 397 131 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 326
+ set {floorItems(326)} $i
+ $w create text 356.5 150 -text 326 -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 308 251 242 251 242 274 342 274 342 282 375 282 375 274 397 274 397 248 339 248 339 242 308 242 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 302
+ set {floorItems(302)} $i
+ $w create text 319.5 261 -text 302 -fill $color -anchor c -tags {floor3 label}
+ set i [$w create polygon 70 321 242 321 242 200 259 200 259 203 272 203 272 193 263 180 242 180 175 180 175 169 156 169 156 196 177 196 177 228 107 228 70 228 70 275 107 275 107 248 160 248 160 301 107 301 107 275 70 275 -fill {} -tags {floor3 room}]
+ set floorLabels($i) 306
+ set {floorItems(306)} $i
+ $w create text 200.5 284.5 -text 306 -fill $color -anchor c -tags {floor3 label}
+ $w create line 341 275 341 283 -fill $color -tags {floor3 wall}
+ $w create line 162 197 155 197 -fill $color -tags {floor3 wall}
+ $w create line 396 247 399 247 -fill $color -tags {floor3 wall}
+ $w create line 399 129 399 311 -fill $color -tags {floor3 wall}
+ $w create line 258 202 243 202 -fill $color -tags {floor3 wall}
+ $w create line 350 283 350 329 -fill $color -tags {floor3 wall}
+ $w create line 251 231 243 231 -fill $color -tags {floor3 wall}
+ $w create line 243 220 251 220 -fill $color -tags {floor3 wall}
+ $w create line 243 250 243 202 -fill $color -tags {floor3 wall}
+ $w create line 155 197 155 190 -fill $color -tags {floor3 wall}
+ $w create line 110 192 110 169 -fill $color -tags {floor3 wall}
+ $w create line 155 192 110 192 -fill $color -tags {floor3 wall}
+ $w create line 155 177 155 169 -fill $color -tags {floor3 wall}
+ $w create line 176 197 176 227 -fill $color -tags {floor3 wall}
+ $w create line 69 280 69 274 -fill $color -tags {floor3 wall}
+ $w create line 21 276 69 276 -fill $color -tags {floor3 wall}
+ $w create line 69 262 69 226 -fill $color -tags {floor3 wall}
+ $w create line 21 228 69 228 -fill $color -tags {floor3 wall}
+ $w create line 21 179 75 179 -fill $color -tags {floor3 wall}
+ $w create line 69 179 69 214 -fill $color -tags {floor3 wall}
+ $w create line 90 220 90 227 -fill $color -tags {floor3 wall}
+ $w create line 90 204 90 202 -fill $color -tags {floor3 wall}
+ $w create line 90 203 100 203 -fill $color -tags {floor3 wall}
+ $w create line 90 187 90 179 -fill $color -tags {floor3 wall}
+ $w create line 90 227 176 227 -fill $color -tags {floor3 wall}
+ $w create line 100 179 100 227 -fill $color -tags {floor3 wall}
+ $w create line 100 179 87 179 -fill $color -tags {floor3 wall}
+ $w create line 96 179 96 129 -fill $color -tags {floor3 wall}
+ $w create line 162 169 96 169 -fill $color -tags {floor3 wall}
+ $w create line 173 169 176 169 -fill $color -tags {floor3 wall}
+ $w create line 182 179 176 179 -fill $color -tags {floor3 wall}
+ $w create line 176 129 176 179 -fill $color -tags {floor3 wall}
+ $w create line 195 179 226 179 -fill $color -tags {floor3 wall}
+ $w create line 224 133 224 179 -fill $color -tags {floor3 wall}
+ $w create line 264 179 264 133 -fill $color -tags {floor3 wall}
+ $w create line 238 179 264 179 -fill $color -tags {floor3 wall}
+ $w create line 273 207 273 193 -fill $color -tags {floor3 wall}
+ $w create line 273 235 273 250 -fill $color -tags {floor3 wall}
+ $w create line 273 224 273 219 -fill $color -tags {floor3 wall}
+ $w create line 273 193 307 193 -fill $color -tags {floor3 wall}
+ $w create line 273 222 307 222 -fill $color -tags {floor3 wall}
+ $w create line 273 250 307 250 -fill $color -tags {floor3 wall}
+ $w create line 384 247 376 247 -fill $color -tags {floor3 wall}
+ $w create line 340 206 307 206 -fill $color -tags {floor3 wall}
+ $w create line 340 187 340 170 -fill $color -tags {floor3 wall}
+ $w create line 340 210 340 201 -fill $color -tags {floor3 wall}
+ $w create line 340 247 340 224 -fill $color -tags {floor3 wall}
+ $w create line 340 241 307 241 -fill $color -tags {floor3 wall}
+ $w create line 376 247 376 170 -fill $color -tags {floor3 wall}
+ $w create line 307 250 307 170 -fill $color -tags {floor3 wall}
+ $w create line 376 170 307 170 -fill $color -tags {floor3 wall}
+ $w create line 315 129 315 170 -fill $color -tags {floor3 wall}
+ $w create line 376 283 366 283 -fill $color -tags {floor3 wall}
+ $w create line 376 283 376 275 -fill $color -tags {floor3 wall}
+ $w create line 399 275 376 275 -fill $color -tags {floor3 wall}
+ $w create line 341 275 320 275 -fill $color -tags {floor3 wall}
+ $w create line 341 283 350 283 -fill $color -tags {floor3 wall}
+ $w create line 298 275 298 329 -fill $color -tags {floor3 wall}
+ $w create line 308 275 298 275 -fill $color -tags {floor3 wall}
+ $w create line 243 322 243 275 -fill $color -tags {floor3 wall}
+ $w create line 243 275 284 275 -fill $color -tags {floor3 wall}
+ $w create line 258 322 226 322 -fill $color -tags {floor3 wall}
+ $w create line 212 370 212 322 -fill $color -tags {floor3 wall}
+ $w create line 214 322 177 322 -fill $color -tags {floor3 wall}
+ $w create line 163 370 163 322 -fill $color -tags {floor3 wall}
+ $w create line 165 322 129 322 -fill $color -tags {floor3 wall}
+ $w create line 84 322 117 322 -fill $color -tags {floor3 wall}
+ $w create line 71 322 64 322 -fill $color -tags {floor3 wall}
+ $w create line 115 322 115 370 -fill $color -tags {floor3 wall}
+ $w create line 66 322 66 370 -fill $color -tags {floor3 wall}
+ $w create line 52 322 21 322 -fill $color -tags {floor3 wall}
+ $w create line 21 331 0 331 -fill $color -tags {floor3 wall}
+ $w create line 21 331 21 133 -fill $color -tags {floor3 wall}
+ $w create line 96 133 21 133 -fill $color -tags {floor3 wall}
+ $w create line 176 129 96 129 -fill $color -tags {floor3 wall}
+ $w create line 315 133 176 133 -fill $color -tags {floor3 wall}
+ $w create line 315 129 399 129 -fill $color -tags {floor3 wall}
+ $w create line 399 311 350 311 -fill $color -tags {floor3 wall}
+ $w create line 350 329 258 329 -fill $color -tags {floor3 wall}
+ $w create line 258 322 258 370 -fill $color -tags {floor3 wall}
+ $w create line 60 370 258 370 -fill $color -tags {floor3 wall}
+ $w create line 60 370 60 391 -fill $color -tags {floor3 wall}
+ $w create line 0 391 0 331 -fill $color -tags {floor3 wall}
+ $w create line 60 391 0 391 -fill $color -tags {floor3 wall}
+ $w create line 307 250 307 242 -fill $color -tags {floor3 wall}
+ $w create line 273 250 307 250 -fill $color -tags {floor3 wall}
+ $w create line 258 250 243 250 -fill $color -tags {floor3 wall}
+}
+
+# Below is the "main program" that creates the floorplan demonstration.
+
+set w .floor
+global c currentRoom colors activeFloor
+catch {destroy $w}
+toplevel $w
+wm title $w "Floorplan Canvas Demonstration"
+wm iconname $w "Floorplan"
+wm geometry $w +20+20
+wm minsize $w 100 100
+
+label $w.msg -font $font -wraplength 8i -justify left -text "This window contains a canvas widget showing the floorplan of Digital Equipment Corporation's Western Research Laboratory. It has three levels. At any given time one of the levels is active, meaning that you can see its room structure. To activate a level, click the left mouse button anywhere on it. As the mouse moves over the active level, the room under the mouse lights up and its room number appears in the \"Room:\" entry. You can also type a room number in the entry and the room will light up."
+pack $w.msg -side top
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+set f [frame $w.frame]
+pack $f -side top -fill both -expand yes
+set h [ttk::scrollbar $f.hscroll -orient horizontal]
+set v [ttk::scrollbar $f.vscroll -orient vertical]
+set f1 [frame $f.f1 -borderwidth 2 -relief sunken]
+set c [canvas $f1.c -width 900 -height 500 -highlightthickness 0 \
+ -xscrollcommand [list $h set] \
+ -yscrollcommand [list $v set]]
+pack $c -expand yes -fill both
+grid $f1 -padx 1 -pady 1 -row 0 -column 0 -rowspan 1 -columnspan 1 -sticky news
+grid $v -padx 1 -pady 1 -row 0 -column 1 -rowspan 1 -columnspan 1 -sticky news
+grid $h -padx 1 -pady 1 -row 1 -column 0 -rowspan 1 -columnspan 1 -sticky news
+grid rowconfig $f 0 -weight 1 -minsize 0
+grid columnconfig $f 0 -weight 1 -minsize 0
+pack $f -expand yes -fill both -padx 1 -pady 1
+
+$v configure -command [list $c yview]
+$h configure -command [list $c xview]
+
+# Create an entry for displaying and typing in current room.
+
+entry $c.entry -width 10 -textvariable currentRoom
+
+# Choose colors, then fill in the floorplan.
+
+if {[winfo depth $c] > 1} {
+ set colors(bg1) #a9c1da
+ set colors(outline1) #77889a
+ set colors(bg2) #9ab0c6
+ set colors(outline2) #687786
+ set colors(bg3) #8ba0b3
+ set colors(outline3) #596673
+ set colors(offices) Black
+ set colors(active) #c4d1df
+} else {
+ set colors(bg1) white
+ set colors(outline1) black
+ set colors(bg2) white
+ set colors(outline2) black
+ set colors(bg3) white
+ set colors(outline3) black
+ set colors(offices) Black
+ set colors(active) black
+}
+set activeFloor ""
+floorDisplay $c 3
+
+# Set up event bindings for canvas:
+
+$c bind floor1 <1> "floorDisplay $c 1"
+$c bind floor2 <1> "floorDisplay $c 2"
+$c bind floor3 <1> "floorDisplay $c 3"
+$c bind room <Enter> "newRoom $c"
+$c bind room <Leave> {set currentRoom ""}
+bind $c <2> "$c scan mark %x %y"
+bind $c <B2-Motion> "$c scan dragto %x %y"
+bind $c <Destroy> "unset currentRoom"
+set currentRoom ""
+trace variable currentRoom w "roomChanged $c"
diff --git a/tk8.6/library/demos/fontchoose.tcl b/tk8.6/library/demos/fontchoose.tcl
new file mode 100644
index 0000000..8b34377
--- /dev/null
+++ b/tk8.6/library/demos/fontchoose.tcl
@@ -0,0 +1,69 @@
+# fontchoose.tcl --
+#
+# Show off the stock font selector dialog
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .fontchoose
+catch {destroy $w}
+toplevel $w
+wm title $w "Font Selection Dialog"
+wm iconname $w "fontchooser"
+positionWindow $w
+
+catch {font create FontchooseDemoFont {*}[font actual TkDefaultFont]}
+
+# The font chooser needs to be configured and then shown.
+proc SelectFont {parent} {
+ tk fontchooser configure -font FontchooseDemoFont \
+ -command ApplyFont -parent $parent
+ tk fontchooser show
+}
+
+proc ApplyFont {font} {
+ font configure FontchooseDemoFont {*}[font actual $font]
+}
+
+# When the visibility of the fontchooser changes, the following event is fired
+# to the parent widget.
+#
+bind $w <<TkFontchooserVisibility>> {
+ if {[tk fontchooser configure -visible]} {
+ %W.f.font state disabled
+ } else {
+ %W.f.font state !disabled
+ }
+}
+
+
+set f [ttk::frame $w.f -relief sunken -padding 2]
+
+text $f.msg -font FontchooseDemoFont -width 40 -height 6 -borderwidth 0 \
+ -yscrollcommand [list $f.vs set]
+ttk::scrollbar $f.vs -command [list $f.msg yview]
+
+$f.msg insert end "Press the buttons below to choose a new font for the\
+ text shown in this window.\n" {}
+
+ttk::button $f.font -text "Set font ..." -command [list SelectFont $w]
+
+grid $f.msg $f.vs -sticky news
+grid $f.font - -sticky e
+grid columnconfigure $f 0 -weight 1
+grid rowconfigure $f 0 -weight 1
+bind $w <Visibility> {
+ bind %W <Visibility> {}
+ grid propagate %W.f 0
+}
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+
+grid $f -sticky news
+grid $btns -sticky ew
+grid columnconfigure $w 0 -weight 1
+grid rowconfigure $w 0 -weight 1
diff --git a/tk8.6/library/demos/form.tcl b/tk8.6/library/demos/form.tcl
new file mode 100644
index 0000000..4d80437
--- /dev/null
+++ b/tk8.6/library/demos/form.tcl
@@ -0,0 +1,38 @@
+# form.tcl --
+#
+# This demonstration script creates a simple form with a bunch
+# of entry widgets.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .form
+catch {destroy $w}
+toplevel $w
+wm title $w "Form Demonstration"
+wm iconname $w "form"
+positionWindow $w
+
+label $w.msg -font $font -wraplength 4i -justify left -text "This window contains a simple form where you can type in the various entries and use tabs to move circularly between the entries."
+pack $w.msg -side top
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+foreach i {f1 f2 f3 f4 f5} {
+ frame $w.$i -bd 2
+ entry $w.$i.entry -relief sunken -width 40
+ label $w.$i.label
+ pack $w.$i.entry -side right
+ pack $w.$i.label -side left
+}
+$w.f1.label config -text Name:
+$w.f2.label config -text Address:
+$w.f5.label config -text Phone:
+pack $w.msg $w.f1 $w.f2 $w.f3 $w.f4 $w.f5 -side top -fill x
+bind $w <Return> "destroy $w"
+focus $w.f1.entry
diff --git a/tk8.6/library/demos/goldberg.tcl b/tk8.6/library/demos/goldberg.tcl
new file mode 100644
index 0000000..284b5c2
--- /dev/null
+++ b/tk8.6/library/demos/goldberg.tcl
@@ -0,0 +1,1833 @@
+##+#################################################################
+#
+# TkGoldberg.tcl
+# by Keith Vetter, March 13, 2003
+#
+# "Man will always find a difficult means to perform a simple task"
+# Rube Goldberg
+#
+# Reproduced here with permission.
+#
+##+#################################################################
+#
+# Keith Vetter 2003-03-21: this started out as a simple little program
+# but was so much fun that it grew and grew. So I apologize about the
+# size but I just couldn't resist sharing it.
+#
+# This is a whizzlet that does a Rube Goldberg type animation, the
+# design of which comes from an New Years e-card from IncrediMail.
+# That version had nice sound effects which I eschewed. On the other
+# hand, that version was in black and white (actually dark blue and
+# light blue) and this one is fully colorized.
+#
+# One thing I learned from this project is that drawing filled complex
+# objects on a canvas is really hard. More often than not I had to
+# draw each item twice--once with the desired fill color but no
+# outline, and once with no fill but with the outline. Another trick
+# is erasing by drawing with the background color. Having a flood fill
+# command would have been extremely helpful.
+#
+# Two wiki pages were extremely helpful: Drawing rounded rectangles
+# which I generalized into Drawing rounded polygons, and regular
+# polygons which allowed me to convert ovals and arcs into polygons
+# which could then be rotated (see Canvas Rotation). I also wrote
+# Named Colors to aid in the color selection.
+#
+# I could comment on the code, but it's just 26 state machines with
+# lots of canvas create and move calls.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .goldberg
+catch {destroy $w}
+toplevel $w
+wm title $w "Tk Goldberg (demonstration)"
+wm iconname $w "goldberg"
+wm resizable $w 0 0
+#positionWindow $w
+
+label $w.msg -font {Arial 10} -wraplength 4i -justify left -text "This is a\
+ demonstration of just how complex you can make your animations\
+ become. Click the ball to start things moving!\n\n\"Man will always\
+ find a difficult means to perform a simple task\"\n - Rube Goldberg"
+pack $w.msg -side top
+
+###--- End of Boilerplate ---###
+
+# Ensure that this this is an array
+array set animationCallbacks {}
+bind $w <Destroy> {
+ if {"%W" eq [winfo toplevel %W]} {
+ unset S C speed
+ }
+}
+
+set S(title) "Tk Goldberg"
+set S(speed) 5
+set S(cnt) 0
+set S(message) "\\nWelcome\\nto\\nTcl/Tk"
+array set speed {1 10 2 20 3 50 4 80 5 100 6 150 7 200 8 300 9 400 10 500}
+
+set MSTART 0; set MGO 1; set MPAUSE 2; set MSSTEP 3; set MBSTEP 4; set MDONE 5
+set S(mode) $::MSTART
+
+# Colors for everything
+set C(fg) black
+set C(bg) gray75
+set C(bg) cornflowerblue
+
+set C(0) white; set C(1a) darkgreen; set C(1b) yellow
+set C(2) red; set C(3a) green; set C(3b) darkblue
+set C(4) $C(fg); set C(5a) brown; set C(5b) white
+set C(6) magenta; set C(7) green; set C(8) $C(fg)
+set C(9) blue4; set C(10a) white; set C(10b) cyan
+set C(11a) yellow; set C(11b) mediumblue; set C(12) tan2
+set C(13a) yellow; set C(13b) red; set C(14) white
+set C(15a) green; set C(15b) yellow; set C(16) gray65
+set C(17) \#A65353; set C(18) $C(fg); set C(19) gray50
+set C(20) cyan; set C(21) gray65; set C(22) $C(20)
+set C(23a) blue; set C(23b) red; set C(23c) yellow
+set C(24a) red; set C(24b) white;
+
+proc DoDisplay {w} {
+ global S C
+
+ ttk::frame $w.ctrl -relief ridge -borderwidth 2 -padding 5
+ pack [frame $w.screen -bd 2 -relief raised] \
+ -side left -fill both -expand 1
+
+ canvas $w.c -width 860 -height 730 -bg $C(bg) -highlightthickness 0
+ $w.c config -scrollregion {0 0 1000 1000} ;# Kludge: move everything up
+ $w.c yview moveto .05
+ pack $w.c -in $w.screen -side top -fill both -expand 1
+
+ bind $w.c <3> [list $w.pause invoke]
+ bind $w.c <Destroy> {
+ after cancel $animationCallbacks(goldberg)
+ unset animationCallbacks(goldberg)
+ }
+ DoCtrlFrame $w
+ DoDetailFrame $w
+ if {[tk windowingsystem] ne "aqua"} {
+ ttk::button $w.show -text "\u00bb" -command [list ShowCtrl $w] -width 2
+ } else {
+ button $w.show -text "\u00bb" -command [list ShowCtrl $w] -width 2 -highlightbackground $C(bg)
+ }
+ place $w.show -in $w.c -relx 1 -rely 0 -anchor ne
+ update
+}
+
+proc DoCtrlFrame {w} {
+ global S
+ ttk::button $w.start -text "Start" -command [list DoButton $w 0]
+ ttk::checkbutton $w.pause -text "Pause" -command [list DoButton $w 1] \
+ -variable S(pause)
+ ttk::button $w.step -text "Single Step" -command [list DoButton $w 2]
+ ttk::button $w.bstep -text "Big Step" -command [list DoButton $w 4]
+ ttk::button $w.reset -text "Reset" -command [list DoButton $w 3]
+ ttk::labelframe $w.details
+ raise $w.details
+ set S(details) 0
+ ttk::checkbutton $w.details.cb -text "Details" -variable S(details)
+ ttk::labelframe $w.message -text "Message"
+ ttk::entry $w.message.e -textvariable S(message) -justify center
+ ttk::labelframe $w.speed -text "Speed: 0"
+ ttk::scale $w.speed.scale -orient h -from 1 -to 10 -variable S(speed)
+ ttk::button $w.about -text About -command [list About $w]
+
+ grid $w.start -in $w.ctrl -row 0 -sticky ew
+ grid rowconfigure $w.ctrl 1 -minsize 10
+ grid $w.pause -in $w.ctrl -row 2 -sticky ew
+ grid $w.step -in $w.ctrl -sticky ew -pady 2
+ grid $w.bstep -in $w.ctrl -sticky ew
+ grid $w.reset -in $w.ctrl -sticky ew -pady 2
+ grid rowconfigure $w.ctrl 10 -minsize 18
+ grid $w.details -in $w.ctrl -row 11 -sticky ew
+ grid rowconfigure $w.ctrl 11 -minsize 20
+ $w.details configure -labelwidget $w.details.cb
+ grid [ttk::frame $w.details.b -height 1] ;# Work around minor bug
+ raise $w.details
+ raise $w.details.cb
+ grid rowconfigure $w.ctrl 50 -weight 1
+ trace variable ::S(mode) w [list ActiveGUI $w]
+ trace variable ::S(details) w [list ActiveGUI $w]
+ trace variable ::S(speed) w [list ActiveGUI $w]
+
+ grid $w.message -in $w.ctrl -row 98 -sticky ew -pady 5
+ grid $w.message.e -sticky nsew
+ grid $w.speed -in $w.ctrl -row 99 -sticky ew -pady {0 5}
+ pack $w.speed.scale -fill both -expand 1
+ grid $w.about -in $w.ctrl -row 100 -sticky ew
+ bind $w.reset <3> {set S(mode) -1} ;# Debugging
+
+ ## See Code / Dismiss buttons hack!
+ set btns [addSeeDismiss $w.ctrl.buttons $w]
+ grid [ttk::separator $w.ctrl.sep] -sticky ew -pady 4
+ set i 0
+ foreach b [winfo children $btns] {
+ if {[winfo class $b] eq "TButton"} {
+ grid [set b2 [ttk::button $w.ctrl.b[incr i]]] -sticky ew
+ foreach b3 [$b configure] {
+ set b3 [lindex $b3 0]
+ # Some options are read-only; ignore those errors
+ catch {$b2 configure $b3 [$b cget $b3]}
+ }
+ }
+ }
+ destroy $btns
+}
+
+proc DoDetailFrame {w} {
+ set w2 $w.details.f
+ ttk::frame $w2
+
+ set bd 2
+ ttk::label $w2.l -textvariable S(cnt) -background white
+ grid $w2.l - - - -sticky ew -row 0
+ for {set i 1} {1} {incr i} {
+ if {[info procs "Move$i"] eq ""} break
+ ttk::label $w2.l$i -text $i -anchor e -width 2 -background white
+ ttk::label $w2.ll$i -textvariable STEP($i) -width 5 -background white
+ set row [expr {($i + 1) / 2}]
+ set col [expr {(($i + 1) & 1) * 2}]
+ grid $w2.l$i -sticky ew -row $row -column $col
+ grid $w2.ll$i -sticky ew -row $row -column [incr col]
+ }
+ grid columnconfigure $w2 1 -weight 1
+}
+
+# Map or unmap the ctrl window
+proc ShowCtrl {w} {
+ if {[winfo ismapped $w.ctrl]} {
+ pack forget $w.ctrl
+ $w.show config -text "\u00bb"
+ } else {
+ pack $w.ctrl -side right -fill both -ipady 5
+ $w.show config -text "\u00ab"
+ }
+}
+
+proc DrawAll {w} {
+ ResetStep
+ $w.c delete all
+ for {set i 0} {1} {incr i} {
+ set p "Draw$i"
+ if {[info procs $p] eq ""} break
+ $p $w
+ }
+}
+
+proc ActiveGUI {w var1 var2 op} {
+ global S MGO MSTART MDONE
+ array set z {0 disabled 1 normal}
+
+ set m $S(mode)
+ set S(pause) [expr {$m == 2}]
+ $w.start config -state $z([expr {$m != $MGO}])
+ $w.pause config -state $z([expr {$m != $MSTART && $m != $MDONE}])
+ $w.step config -state $z([expr {$m != $MGO && $m != $MDONE}])
+ $w.bstep config -state $z([expr {$m != $MGO && $m != $MDONE}])
+ $w.reset config -state $z([expr {$m != $MSTART}])
+
+ if {$S(details)} {
+ grid $w.details.f -sticky ew
+ } else {
+ grid forget $w.details.f
+ }
+ set S(speed) [expr {round($S(speed))}]
+ $w.speed config -text "Speed: $S(speed)"
+}
+
+proc Start {} {
+ global S MGO
+ set S(mode) $MGO
+}
+
+proc DoButton {w what} {
+ global S MDONE MGO MSSTEP MBSTEP MPAUSE
+
+ if {$what == 0} { ;# Start
+ if {$S(mode) == $MDONE} {
+ Reset $w
+ }
+ set S(mode) $MGO
+ } elseif {$what == 1} { ;# Pause
+ set S(mode) [expr {$S(pause) ? $MPAUSE : $MGO}]
+ } elseif {$what == 2} { ;# Step
+ set S(mode) $MSSTEP
+ } elseif {$what == 3} { ;# Reset
+ Reset $w
+ } elseif {$what == 4} { ;# Big step
+ set S(mode) $MBSTEP
+ }
+}
+
+proc Go {w {who {}}} {
+ global S speed animationCallbacks MGO MPAUSE MSSTEP MBSTEP
+
+ set now [clock clicks -milliseconds]
+ catch {after cancel $animationCallbacks(goldberg)}
+ if {$who ne ""} { ;# Start here for debugging
+ set S(active) $who;
+ set S(mode) $MGO
+ }
+ if {$S(mode) == -1} return ;# Debugging
+ set n 0
+ if {$S(mode) != $MPAUSE} { ;# Not paused
+ set n [NextStep $w] ;# Do the next move
+ }
+ if {$S(mode) == $MSSTEP} { ;# Single step
+ set S(mode) $MPAUSE
+ }
+ if {$S(mode) == $MBSTEP && $n} { ;# Big step
+ set S(mode) $MSSTEP
+ }
+
+ set elapsed [expr {[clock click -milliseconds] - $now}]
+ set delay [expr {$speed($S(speed)) - $elapsed}]
+ if {$delay <= 0} {
+ set delay 1
+ }
+ set animationCallbacks(goldberg) [after $delay [list Go $w]]
+}
+
+# NextStep: drives the next step of the animation
+proc NextStep {w} {
+ global S MSTART MDONE
+ set rval 0 ;# Return value
+
+ if {$S(mode) != $MSTART && $S(mode) != $MDONE} {
+ incr S(cnt)
+ }
+ set alive {}
+ foreach {who} $S(active) {
+ set n ["Move$who" $w]
+ if {$n & 1} { ;# This guy still alive
+ lappend alive $who
+ }
+ if {$n & 2} { ;# Next guy is active
+ lappend alive [expr {$who + 1}]
+ set rval 1
+ }
+ if {$n & 4} { ;# End of puzzle flag
+ set S(mode) $MDONE ;# Done mode
+ set S(active) {} ;# No more animation
+ return 1
+ }
+ }
+ set S(active) $alive
+ return $rval
+}
+proc About {w} {
+ set msg "$::S(title)\nby Keith Vetter, March 2003\n(Reproduced by kind\
+ permission of the author)\n\n\"Man will always find a difficult\
+ means to perform a simple task.\"\nRube Goldberg"
+ tk_messageBox -parent $w -message $msg -title About
+}
+################################################################
+#
+# All the drawing and moving routines
+#
+
+# START HERE! banner
+proc Draw0 {w} {
+ set color $::C(0)
+ set xy {579 119}
+ $w.c create text $xy -text "START HERE!" -fill $color -anchor w \
+ -tag I0 -font {{Times Roman} 12 italic bold}
+ set xy {719 119 763 119}
+ $w.c create line $xy -tag I0 -fill $color -width 5 -arrow last \
+ -arrowshape {18 18 5}
+ $w.c bind I0 <1> Start
+}
+proc Move0 {w {step {}}} {
+ set step [GetStep 0 $step]
+
+ if {$::S(mode) > $::MSTART} { ;# Start the ball rolling
+ MoveAbs $w I0 {-100 -100} ;# Hide the banner
+ return 2
+ }
+
+ set pos {
+ {673 119} {678 119} {683 119} {688 119}
+ {693 119} {688 119} {683 119} {678 119}
+ }
+ set step [expr {$step % [llength $pos]}]
+ MoveAbs $w I0 [lindex $pos $step]
+ return 1
+}
+
+# Dropping ball
+proc Draw1 {w} {
+ set color $::C(1a)
+ set color2 $::C(1b)
+ set xy {844 133 800 133 800 346 820 346 820 168 844 168 844 133}
+ $w.c create poly $xy -width 3 -fill $color -outline {}
+ set xy {771 133 685 133 685 168 751 168 751 346 771 346 771 133}
+ $w.c create poly $xy -width 3 -fill $color -outline {}
+
+ set xy [box 812 122 9]
+ $w.c create oval $xy -tag I1 -fill $color2 -outline {}
+ $w.c bind I1 <1> Start
+}
+proc Move1 {w {step {}}} {
+ set step [GetStep 1 $step]
+ set pos {
+ {807 122} {802 122} {797 123} {793 124} {789 129} {785 153}
+ {785 203} {785 278 x} {785 367} {810 392} {816 438} {821 503}
+ {824 585 y} {838 587} {848 593} {857 601} {-100 -100}
+ }
+ if {$step >= [llength $pos]} {
+ return 0
+ }
+ set where [lindex $pos $step]
+ MoveAbs $w I1 $where
+
+ if {[lindex $where 2] eq "y"} {
+ Move15a $w
+ }
+ if {[lindex $where 2] eq "x"} {
+ return 3
+ }
+ return 1
+}
+
+# Lighting the match
+proc Draw2 {w} {
+ set color red
+ set color $::C(2)
+ set xy {750 369 740 392 760 392} ;# Fulcrum
+ $w.c create poly $xy -fill $::C(fg) -outline $::C(fg)
+ set xy {628 335 660 383} ;# Strike box
+ $w.c create rect $xy -fill {} -outline $::C(fg)
+ for {set y 0} {$y < 3} {incr y} {
+ set yy [expr {335+$y*16}]
+ $w.c create bitmap 628 $yy -bitmap gray25 -anchor nw \
+ -foreground $::C(fg)
+ $w.c create bitmap 644 $yy -bitmap gray25 -anchor nw \
+ -foreground $::C(fg)
+ }
+
+ set xy {702 366 798 366} ;# Lever
+ $w.c create line $xy -fill $::C(fg) -width 6 -tag I2_0
+ set xy {712 363 712 355} ;# R strap
+ $w.c create line $xy -fill $::C(fg) -width 3 -tag I2_1
+ set xy {705 363 705 355} ;# L strap
+ $w.c create line $xy -fill $::C(fg) -width 3 -tag I2_2
+ set xy {679 356 679 360 717 360 717 356 679 356} ;# Match stick
+ $w.c create line $xy -fill $::C(fg) -tag I2_3
+
+ #set xy {662 352 680 365} ;# Match head
+ set xy {
+ 671 352 677.4 353.9 680 358.5 677.4 363.1 671 365 664.6 363.1
+ 662 358.5 664.6 353.9
+ }
+ $w.c create poly $xy -fill $color -outline $color -tag I2_4
+}
+proc Move2 {w {step {}}} {
+ set step [GetStep 2 $step]
+
+ set stages {0 0 1 2 0 2 1 0 1 2 0 2 1}
+ set xy(0) {
+ 686 333 692 323 682 316 674 309 671 295 668 307 662 318 662 328
+ 671 336
+ }
+ set xy(1) {687 331 698 322 703 295 680 320 668 297 663 311 661 327 671 335}
+ set xy(2) {
+ 686 331 704 322 688 300 678 283 678 283 674 298 666 309 660 324
+ 672 336
+ }
+
+ if {$step >= [llength $stages]} {
+ $w.c delete I2
+ return 0
+ }
+
+ if {$step == 0} { ;# Rotate the match
+ set beta 20
+ lassign [Anchor $w I2_0 s] Ox Oy ;# Where to pivot
+ for {set i 0} {[$w.c find withtag I2_$i] ne ""} {incr i} {
+ RotateItem $w I2_$i $Ox $Oy $beta
+ }
+ $w.c create poly -tag I2 -smooth 1 -fill $::C(2) ;# For the flame
+ return 1
+ }
+ $w.c coords I2 $xy([lindex $stages $step])
+ return [expr {$step == 7 ? 3 : 1}]
+}
+
+# Weight and pulleys
+proc Draw3 {w} {
+ set color $::C(3a)
+ set color2 $::C(3b)
+
+ set xy {602 296 577 174 518 174}
+ foreach {x y} $xy { ;# 3 Pulleys
+ $w.c create oval [box $x $y 13] -fill $color -outline $::C(fg) \
+ -width 3
+ $w.c create oval [box $x $y 2] -fill $::C(fg) -outline $::C(fg)
+ }
+
+ set xy {750 309 670 309} ;# Wall to flame
+ $w.c create line $xy -tag I3_s -width 3 -fill $::C(fg) -smooth 1
+ set xy {670 309 650 309} ;# Flame to pulley 1
+ $w.c create line $xy -tag I3_0 -width 3 -fill $::C(fg)
+ set xy {650 309 600 309} ;# Flame to pulley 1
+ $w.c create line $xy -tag I3_1 -width 3 -fill $::C(fg)
+ set xy {589 296 589 235} ;# Pulley 1 half way to 2
+ $w.c create line $xy -tag I3_2 -width 3 -fill $::C(fg)
+ set xy {589 235 589 174} ;# Pulley 1 other half to 2
+ $w.c create line $xy -width 3 -fill $::C(fg)
+ set xy {577 161 518 161} ;# Across the top
+ $w.c create line $xy -width 3 -fill $::C(fg)
+ set xy {505 174 505 205} ;# Down to weight
+ $w.c create line $xy -tag I3_w -width 3 -fill $::C(fg)
+
+ # Draw the weight as 2 circles, two rectangles and 1 rounded rectangle
+ set xy {515 207 495 207}
+ foreach {x1 y1 x2 y2} $xy {
+ $w.c create oval [box $x1 $y1 6] -tag I3_ -fill $color2 \
+ -outline $color2
+ $w.c create oval [box $x2 $y2 6] -tag I3_ -fill $color2 \
+ -outline $color2
+ incr y1 -6; incr y2 6
+ $w.c create rect $x1 $y1 $x2 $y2 -tag I3_ -fill $color2 \
+ -outline $color2
+ }
+ set xy {492 220 518 263}
+ set xy [RoundRect $w $xy 15]
+ $w.c create poly $xy -smooth 1 -tag I3_ -fill $color2 -outline $color2
+ set xy {500 217 511 217}
+ $w.c create line $xy -tag I3_ -fill $color2 -width 10
+
+ set xy {502 393 522 393 522 465} ;# Bottom weight target
+ $w.c create line $xy -tag I3__ -fill $::C(fg) -join miter -width 10
+}
+proc Move3 {w {step {}}} {
+ set step [GetStep 3 $step]
+
+ set pos {{505 247} {505 297} {505 386.5} {505 386.5}}
+ set rope(0) {750 309 729 301 711 324 690 300}
+ set rope(1) {750 309 737 292 736 335 717 315 712 320}
+ set rope(2) {750 309 737 309 740 343 736 351 725 340}
+ set rope(3) {750 309 738 321 746 345 742 356}
+
+ if {$step >= [llength $pos]} {
+ return 0
+ }
+
+ $w.c delete "I3_$step" ;# Delete part of the rope
+ MoveAbs $w I3_ [lindex $pos $step] ;# Move weight down
+ $w.c coords I3_s $rope($step) ;# Flapping rope end
+ $w.c coords I3_w [concat 505 174 [lindex $pos $step]]
+ if {$step == 2} {
+ $w.c move I3__ 0 30
+ return 2
+ }
+ return 1
+}
+
+# Cage and door
+proc Draw4 {w} {
+ set color $::C(4)
+ lassign {527 356 611 464} x0 y0 x1 y1
+
+ for {set y $y0} {$y <= $y1} {incr y 12} { ;# Horizontal bars
+ $w.c create line $x0 $y $x1 $y -fill $color -width 1
+ }
+ for {set x $x0} {$x <= $x1} {incr x 12} { ;# Vertical bars
+ $w.c create line $x $y0 $x $y1 -fill $color -width 1
+ }
+
+ set xy {518 464 518 428} ;# Swing gate
+ $w.c create line $xy -tag I4 -fill $color -width 3
+}
+proc Move4 {w {step {}}} {
+ set step [GetStep 4 $step]
+
+ set angles {-10 -20 -30 -30}
+ if {$step >= [llength $angles]} {
+ return 0
+ }
+ RotateItem $w I4 518 464 [lindex $angles $step]
+ $w.c raise I4
+ return [expr {$step == 3 ? 3 : 1}]
+}
+
+# Mouse
+proc Draw5 {w} {
+ set color $::C(5a)
+ set color2 $::C(5b)
+ set xy {377 248 410 248 410 465 518 465} ;# Mouse course
+ lappend xy 518 428 451 428 451 212 377 212
+ $w.c create poly $xy -fill $color2 -outline $::C(fg) -width 3
+
+ set xy {
+ 534.5 445.5 541 440 552 436 560 436 569 440 574 446 575 452 574 454
+ 566 456 554 456 545 456 537 454 530 452
+ }
+ $w.c create poly $xy -tag {I5 I5_0} -fill $color
+ set xy {573 452 592 458 601 460 613 456} ;# Tail
+ $w.c create line $xy -tag {I5 I5_1} -fill $color -smooth 1 -width 3
+ set xy [box 540 446 2] ;# Eye
+ set xy {540 444 541 445 541 447 540 448 538 447 538 445}
+ #.c create oval $xy -tag {I5 I5_2} -fill $::C(bg) -outline {}
+ $w.c create poly $xy -tag {I5 I5_2} -fill $::C(bg) -outline {} -smooth 1
+ set xy {538 454 535 461} ;# Front leg
+ $w.c create line $xy -tag {I5 I5_3} -fill $color -width 2
+ set xy {566 455 569 462} ;# Back leg
+ $w.c create line $xy -tag {I5 I5_4} -fill $color -width 2
+ set xy {544 455 545 460} ;# 2nd front leg
+ $w.c create line $xy -tag {I5 I5_5} -fill $color -width 2
+ set xy {560 455 558 460} ;# 2nd back leg
+ $w.c create line $xy -tag {I5 I5_6} -fill $color -width 2
+}
+proc Move5 {w {step {}}} {
+ set step [GetStep 5 $step]
+
+ set pos {
+ {553 452} {533 452} {513 452} {493 452} {473 452}
+ {463 442 30} {445.5 441.5 30} {425.5 434.5 30} {422 414} {422 394}
+ {422 374} {422 354} {422 334} {422 314} {422 294}
+ {422 274 -30} {422 260.5 -30 x} {422.5 248.5 -28} {425 237}
+ }
+ if {$step >= [llength $pos]} {
+ return 0
+ }
+
+ lassign [lindex $pos $step] x y beta next
+ MoveAbs $w I5 [list $x $y]
+ if {$beta ne ""} {
+ lassign [Centroid $w I5_0] Ox Oy
+ foreach id {0 1 2 3 4 5 6} {
+ RotateItem $w I5_$id $Ox $Oy $beta
+ }
+ }
+ if {$next eq "x"} {
+ return 3
+ }
+ return 1
+}
+
+# Dropping gumballs
+array set XY6 {
+ -1 {366 207} -2 {349 204} -3 {359 193} -4 {375 192} -5 {340 190}
+ -6 {349 177} -7 {366 177} -8 {380 176} -9 {332 172} -10 {342 161}
+ -11 {357 164} -12 {372 163} -13 {381 149} -14 {364 151} -15 {349 146}
+ -16 {333 148} 0 {357 219}
+ 1 {359 261} 2 {359 291} 3 {359 318} 4 {361 324} 5 {365 329} 6 {367 334}
+ 7 {367 340} 8 {366 346} 9 {364 350} 10 {361 355} 11 {359 370} 12 {359 391}
+ 13,0 {360 456} 13,1 {376 456} 13,2 {346 456} 13,3 {330 456}
+ 13,4 {353 444} 13,5 {368 443} 13,6 {339 442} 13,7 {359 431}
+ 13,8 {380 437} 13,9 {345 428} 13,10 {328 434} 13,11 {373 424}
+ 13,12 {331 420} 13,13 {360 417} 13,14 {345 412} 13,15 {376 410}
+ 13,16 {360 403}
+}
+proc Draw6 {w} {
+ set color $::C(6)
+ set xy {324 130 391 204} ;# Ball holder
+ set xy [RoundRect $w $xy 10]
+ $w.c create poly $xy -smooth 1 -outline $::C(fg) -width 3 -fill $color
+ set xy {339 204 376 253} ;# Below the ball holder
+ $w.c create rect $xy -fill {} -outline $::C(fg) -width 3 -fill $color \
+ -tag I6c
+ set xy [box 346 339 28]
+ $w.c create oval $xy -fill $color -outline {} ;# Rotor
+ $w.c create arc $xy -outline $::C(fg) -width 2 -style arc \
+ -start 80 -extent 205
+ $w.c create arc $xy -outline $::C(fg) -width 2 -style arc \
+ -start -41 -extent 85
+
+ set xy [box 346 339 15] ;# Center of rotor
+ $w.c create oval $xy -outline $::C(fg) -fill $::C(fg) -tag I6m
+ set xy {352 312 352 254 368 254 368 322} ;# Top drop to rotor
+ $w.c create poly $xy -fill $color -outline {}
+ $w.c create line $xy -fill $::C(fg) -width 2
+
+ set xy {353 240 367 300} ;# Poke bottom hole
+ $w.c create rect $xy -fill $color -outline {}
+ set xy {341 190 375 210} ;# Poke another hole
+ $w.c create rect $xy -fill $color -outline {}
+
+ set xy {368 356 368 403 389 403 389 464 320 464 320 403 352 403 352 366}
+ $w.c create poly $xy -fill $color -outline {} -width 2 ;# Below rotor
+ $w.c create line $xy -fill $::C(fg) -width 2
+ set xy [box 275 342 7] ;# On/off rotor
+ $w.c create oval $xy -outline $::C(fg) -fill $::C(fg)
+ set xy {276 334 342 325} ;# Fan belt top
+ $w.c create line $xy -fill $::C(fg) -width 3
+ set xy {276 349 342 353} ;# Fan belt bottom
+ $w.c create line $xy -fill $::C(fg) -width 3
+
+ set xy {337 212 337 247} ;# What the mouse pushes
+ $w.c create line $xy -fill $::C(fg) -width 3 -tag I6_
+ set xy {392 212 392 247}
+ $w.c create line $xy -fill $::C(fg) -width 3 -tag I6_
+ set xy {337 230 392 230}
+ $w.c create line $xy -fill $::C(fg) -width 7 -tag I6_
+
+ set who -1 ;# All the balls
+ set colors {red cyan orange green blue darkblue}
+ lappend colors {*}$colors {*}$colors
+
+ for {set i 0} {$i < 17} {incr i} {
+ set loc [expr {-1 * $i}]
+ set color [lindex $colors $i]
+ $w.c create oval [box {*}$::XY6($loc) 5] -fill $color \
+ -outline $color -tag I6_b$i
+ }
+ Draw6a $w 12 ;# The wheel
+}
+proc Draw6a {w beta} {
+ $w.c delete I6_0
+ lassign {346 339} Ox Oy
+ for {set i 0} {$i < 4} {incr i} {
+ set b [expr {$beta + $i * 45}]
+ lassign [RotateC 28 0 0 0 $b] x y
+ set xy [list [expr {$Ox+$x}] [expr {$Oy+$y}] \
+ [expr {$Ox-$x}] [expr {$Oy-$y}]]
+ $w.c create line $xy -tag I6_0 -fill $::C(fg) -width 2
+ }
+}
+proc Move6 {w {step {}}} {
+ set step [GetStep 6 $step]
+ if {$step > 62} {
+ return 0
+ }
+
+ if {$step < 2} { ;# Open gate for balls to drop
+ $w.c move I6_ -7 0
+ if {$step == 1} { ;# Poke a hole
+ set xy {348 226 365 240}
+ $w.c create rect $xy -fill [$w.c itemcget I6c -fill] -outline {}
+ }
+ return 1
+ }
+
+ set s [expr {$step - 1}] ;# Do the gumball drop dance
+ for {set i 0} {$i <= int(($s-1) / 3)} {incr i} {
+ set tag "I6_b$i"
+ if {[$w.c find withtag $tag] eq ""} break
+ set loc [expr {$s - 3 * $i}]
+
+ if {[info exists ::XY6($loc,$i)]} {
+ MoveAbs $w $tag $::XY6($loc,$i)
+ } elseif {[info exists ::XY6($loc)]} {
+ MoveAbs $w $tag $::XY6($loc)
+ }
+ }
+ if {($s % 3) == 1} {
+ set first [expr {($s + 2) / 3}]
+ for {set i $first} {1} {incr i} {
+ set tag "I6_b$i"
+ if {[$w.c find withtag $tag] eq ""} break
+ set loc [expr {$first - $i}]
+ MoveAbs $w $tag $::XY6($loc)
+ }
+ }
+ if {$s >= 3} { ;# Rotate the motor
+ set idx [expr {$s % 3}]
+ #Draw6a $w [lindex {12 35 64} $idx]
+ Draw6a $w [expr {12 + $s * 15}]
+ }
+ return [expr {$s == 3 ? 3 : 1}]
+}
+
+# On/off switch
+proc Draw7 {w} {
+ set color $::C(7)
+ set xy {198 306 277 374} ;# Box
+ $w.c create rect $xy -outline $::C(fg) -width 2 -fill $color -tag I7z
+ $w.c lower I7z
+ set xy {275 343 230 349}
+ $w.c create line $xy -tag I7 -fill $::C(fg) -arrow last \
+ -arrowshape {23 23 8} -width 6
+ set xy {225 324} ;# On button
+ $w.c create oval [box {*}$xy 3] -fill $::C(fg) -outline $::C(fg)
+ set xy {218 323} ;# On text
+ set font {{Times Roman} 8}
+ $w.c create text $xy -text "on" -anchor e -fill $::C(fg) -font $font
+ set xy {225 350} ;# Off button
+ $w.c create oval [box {*}$xy 3] -fill $::C(fg) -outline $::C(fg)
+ set xy {218 349} ;# Off button
+ $w.c create text $xy -text "off" -anchor e -fill $::C(fg) -font $font
+}
+proc Move7 {w {step {}}} {
+ set step [GetStep 7 $step]
+ set numsteps 30
+ if {$step > $numsteps} {
+ return 0
+ }
+ set beta [expr {30.0 / $numsteps}]
+ RotateItem $w I7 275 343 $beta
+
+ return [expr {$step == $numsteps ? 3 : 1}]
+}
+
+# Electricity to the fan
+proc Draw8 {w} {
+ Sine $w 271 248 271 306 5 8 -tag I8_s -fill $::C(8) -width 3
+}
+proc Move8 {w {step {}}} {
+ set step [GetStep 8 $step]
+
+ if {$step > 3} {
+ return 0
+ }
+ if {$step == 0} {
+ Sparkle $w [Anchor $w I8_s s] I8
+ return 1
+
+ } elseif {$step == 1} {
+ MoveAbs $w I8 [Anchor $w I8_s c]
+ } elseif {$step == 2} {
+ MoveAbs $w I8 [Anchor $w I8_s n]
+ } else {
+ $w.c delete I8
+ }
+ return [expr {$step == 2 ? 3 : 1}]
+}
+
+# Fan
+proc Draw9 {w} {
+ set color $::C(9)
+ set xy {266 194 310 220}
+ $w.c create oval $xy -outline $color -fill $color
+ set xy {280 209 296 248}
+ $w.c create oval $xy -outline $color -fill $color
+ set xy {288 249 252 249 260 240 280 234 296 234 316 240 324 249 288 249}
+ $w.c create poly $xy -fill $color -smooth 1
+
+ set xy {248 205 265 214 264 205 265 196} ;# Spinner
+ $w.c create poly $xy -fill $color
+
+ set xy {255 206 265 234} ;# Fan blades
+ $w.c create oval $xy -fill {} -outline $::C(fg) -width 3 -tag I9_0
+ set xy {255 176 265 204}
+ $w.c create oval $xy -fill {} -outline $::C(fg) -width 3 -tag I9_0
+ set xy {255 206 265 220}
+ $w.c create oval $xy -fill {} -outline $::C(fg) -width 1 -tag I9_1
+ set xy {255 190 265 204}
+ $w.c create oval $xy -fill {} -outline $::C(fg) -width 1 -tag I9_1
+}
+proc Move9 {w {step {}}} {
+ set step [GetStep 9 $step]
+
+ if {$step & 1} {
+ $w.c itemconfig I9_0 -width 4
+ $w.c itemconfig I9_1 -width 1
+ $w.c lower I9_1 I9_0
+ } else {
+ $w.c itemconfig I9_0 -width 1
+ $w.c itemconfig I9_1 -width 4
+ $w.c lower I9_0 I9_1
+ }
+ if {$step == 0} {
+ return 3
+ }
+ return 1
+}
+
+# Boat
+proc Draw10 {w} {
+ set color $::C(10a)
+ set color2 $::C(10b)
+ set xy {191 230 233 230 233 178 191 178} ;# Sail
+ $w.c create poly $xy -fill $color -width 3 -outline $::C(fg) -tag I10
+ set xy [box 209 204 31] ;# Front
+ $w.c create arc $xy -outline {} -fill $color -style pie \
+ -start 120 -extent 120 -tag I10
+ $w.c create arc $xy -outline $::C(fg) -width 3 -style arc \
+ -start 120 -extent 120 -tag I10
+ set xy [box 249 204 31] ;# Back
+ $w.c create arc $xy -outline {} -fill $::C(bg) -width 3 -style pie \
+ -start 120 -extent 120 -tag I10
+ $w.c create arc $xy -outline $::C(fg) -width 3 -style arc \
+ -start 120 -extent 120 -tag I10
+
+ set xy {200 171 200 249} ;# Mast
+ $w.c create line $xy -fill $::C(fg) -width 3 -tag I10
+ set xy {159 234 182 234} ;# Bow sprit
+ $w.c create line $xy -fill $::C(fg) -width 3 -tag I10
+ set xy {180 234 180 251 220 251} ;# Hull
+ $w.c create line $xy -fill $::C(fg) -width 6 -tag I10
+
+ set xy {92 255 221 255} ;# Waves
+ Sine $w {*}$xy 2 25 -fill $color2 -width 1 -tag I10w
+
+ set xy [lrange [$w.c coords I10w] 4 end-4] ;# Water
+ set xy [concat $xy 222 266 222 277 99 277]
+ $w.c create poly $xy -fill $color2 -outline $color2
+ set xy {222 266 222 277 97 277 97 266} ;# Water bottom
+ $w.c create line $xy -fill $::C(fg) -width 3
+
+ set xy [box 239 262 17]
+ $w.c create arc $xy -outline $::C(fg) -width 3 -style arc \
+ -start 95 -extent 103
+ set xy [box 76 266 21]
+ $w.c create arc $xy -outline $::C(fg) -width 3 -style arc -extent 190
+}
+proc Move10 {w {step {}}} {
+ set step [GetStep 10 $step]
+ set pos {
+ {195 212} {193 212} {190 212} {186 212} {181 212} {176 212}
+ {171 212} {166 212} {161 212} {156 212} {151 212} {147 212} {142 212}
+ {137 212} {132 212 x} {127 212} {121 212} {116 212} {111 212}
+ }
+
+ if {$step >= [llength $pos]} {
+ return 0
+ }
+ set where [lindex $pos $step]
+ MoveAbs $w I10 $where
+
+ if {[lindex $where 2] eq "x"} {
+ return 3
+ }
+ return 1
+}
+
+# 2nd ball drop
+proc Draw11 {w} {
+ set color $::C(11a)
+ set color2 $::C(11b)
+ set xy {23 264 55 591} ;# Color the down tube
+ $w.c create rect $xy -fill $color -outline {}
+ set xy [box 71 460 48] ;# Color the outer loop
+ $w.c create oval $xy -fill $color -outline {}
+
+ set xy {55 264 55 458} ;# Top right side
+ $w.c create line $xy -fill $::C(fg) -width 3
+ set xy {55 504 55 591} ;# Bottom right side
+ $w.c create line $xy -fill $::C(fg) -width 3
+ set xy [box 71 460 48] ;# Outer loop
+ $w.c create arc $xy -outline $::C(fg) -width 3 -style arc \
+ -start 110 -extent -290 -tag I11i
+ set xy [box 71 460 16] ;# Inner loop
+ $w.c create oval $xy -outline $::C(fg) -fill {} -width 3 -tag I11i
+ $w.c create oval $xy -outline $::C(fg) -fill $::C(bg) -width 3
+
+ set xy {23 264 23 591} ;# Left side
+ $w.c create line $xy -fill $::C(fg) -width 3
+ set xy [box 1 266 23] ;# Top left curve
+ $w.c create arc $xy -outline $::C(fg) -width 3 -style arc -extent 90
+
+ set xy [box 75 235 9] ;# The ball
+ $w.c create oval $xy -fill $color2 -outline {} -width 3 -tag I11
+}
+proc Move11 {w {step {}}} {
+ set step [GetStep 11 $step]
+ set pos {
+ {75 235} {70 235} {65 237} {56 240} {46 247} {38 266} {38 296}
+ {38 333} {38 399} {38 475} {74 496} {105 472} {100 437} {65 423}
+ {-100 -100} {38 505} {38 527 x} {38 591}
+ }
+
+ if {$step >= [llength $pos]} {
+ return 0
+ }
+ set where [lindex $pos $step]
+ MoveAbs $w I11 $where
+ if {[lindex $where 2] eq "x"} {
+ return 3
+ }
+ return 1
+}
+
+# Hand
+proc Draw12 {w} {
+ set xy {20 637 20 617 20 610 20 590 40 590 40 590 60 590 60 610 60 610}
+ lappend xy 60 610 65 620 60 631 ;# Thumb
+ lappend xy 60 631 60 637 60 662 60 669 52 669 56 669 50 669 50 662 50 637
+
+ set y0 637 ;# Bumps for fingers
+ set y1 645
+ for {set x 50} {$x > 20} {incr x -10} {
+ set x1 [expr {$x - 5}]
+ set x2 [expr {$x - 10}]
+ lappend xy $x $y0 $x1 $y1 $x2 $y0
+ }
+ $w.c create poly $xy -fill $::C(12) -outline $::C(fg) -smooth 1 -tag I12 \
+ -width 3
+}
+proc Move12 {w {step {}}} {
+ set step [GetStep 12 $step]
+ set pos {{42.5 641 x}}
+ if {$step >= [llength $pos]} {
+ return 0
+ }
+
+ set where [lindex $pos $step]
+ MoveAbs $w I12 $where
+ if {[lindex $where 2] eq "x"} {
+ return 3
+ }
+ return 1
+}
+
+# Fax
+proc Draw13 {w} {
+ set color $::C(13a)
+ set xy {86 663 149 663 149 704 50 704 50 681 64 681 86 671}
+ set xy2 {784 663 721 663 721 704 820 704 820 681 806 681 784 671}
+ set radii {2 9 9 8 5 5 2}
+
+ RoundPoly $w.c $xy $radii -width 3 -outline $::C(fg) -fill $color
+ RoundPoly $w.c $xy2 $radii -width 3 -outline $::C(fg) -fill $color
+
+ set xy {56 677}
+ $w.c create rect [box {*}$xy 4] -fill {} -outline $::C(fg) -width 3 \
+ -tag I13
+ set xy {809 677}
+ $w.c create rect [box {*}$xy 4] -fill {} -outline $::C(fg) -width 3 \
+ -tag I13R
+
+ set xy {112 687} ;# Label
+ $w.c create text $xy -text "FAX" -fill $::C(fg) \
+ -font {{Times Roman} 12 bold}
+ set xy {762 687}
+ $w.c create text $xy -text "FAX" -fill $::C(fg) \
+ -font {{Times Roman} 12 bold}
+
+ set xy {138 663 148 636 178 636} ;# Paper guide
+ $w.c create line $xy -smooth 1 -fill $::C(fg) -width 3
+ set xy {732 663 722 636 692 636}
+ $w.c create line $xy -smooth 1 -fill $::C(fg) -width 3
+
+ Sine $w 149 688 720 688 5 15 -tag I13_s -fill $::C(fg) -width 3
+}
+proc Move13 {w {step {}}} {
+ set step [GetStep 13 $step]
+ set numsteps 7
+
+ if {$step == $numsteps+2} {
+ MoveAbs $w I13_star {-100 -100}
+ $w.c itemconfig I13R -fill $::C(13b) -width 2
+ return 2
+ }
+ if {$step == 0} { ;# Button down
+ $w.c delete I13
+ Sparkle $w {-100 -100} I13_star ;# Create off screen
+ return 1
+ }
+ lassign [Anchor $w I13_s w] x0 y0
+ lassign [Anchor $w I13_s e] x1 y1
+ set x [expr {$x0 + ($x1-$x0) * ($step - 1) / double($numsteps)}]
+ MoveAbs $w I13_star [list $x $y0]
+ return 1
+}
+
+# Paper in fax
+proc Draw14 {w} {
+ set color $::C(14)
+ set xy {102 661 113 632 130 618} ;# Left paper edge
+ $w.c create line $xy -smooth 1 -fill $color -width 3 -tag I14L_0
+ set xy {148 629 125 640 124 662} ;# Right paper edge
+ $w.c create line $xy -smooth 1 -fill $color -width 3 -tag I14L_1
+ Draw14a $w L
+
+ set xy {
+ 768.0 662.5 767.991316225 662.433786215 767.926187912 662.396880171
+ }
+ $w.c create line $xy -smooth 1 -fill $color -width 3 -tag I14R_0
+ $w.c lower I14R_0
+ # NB. these numbers are VERY sensitive, you must start with final size
+ # and shrink down to get the values
+ set xy {
+ 745.947897349 662.428358855 745.997829056 662.452239237 746.0 662.5
+ }
+ $w.c create line $xy -smooth 1 -fill $color -width 3 -tag I14R_1
+ $w.c lower I14R_1
+}
+proc Draw14a {w side} {
+ set color $::C(14)
+ set xy [$w.c coords I14${side}_0]
+ set xy2 [$w.c coords I14${side}_1]
+ lassign $xy x0 y0 x1 y1 x2 y2
+ lassign $xy2 x3 y3 x4 y4 x5 y5
+ set zz [concat \
+ $x0 $y0 $x0 $y0 $xy $x2 $y2 $x2 $y2 \
+ $x3 $y3 $x3 $y3 $xy2 $x5 $y5 $x5 $y5]
+ $w.c delete I14$side
+ $w.c create poly $zz -tag I14$side -smooth 1 -fill $color -outline $color \
+ -width 3
+ $w.c lower I14$side
+}
+proc Move14 {w {step {}}} {
+ set step [GetStep 14 $step]
+
+ # Paper going down
+ set sc [expr {.9 - .05*$step}]
+ if {$sc < .3} {
+ $w.c delete I14L
+ return 0
+ }
+
+ lassign [$w.c coords I14L_0] Ox Oy
+ $w.c scale I14L_0 $Ox $Oy $sc $sc
+ lassign [lrange [$w.c coords I14L_1] end-1 end] Ox Oy
+ $w.c scale I14L_1 $Ox $Oy $sc $sc
+ Draw14a $w L
+
+ # Paper going up
+ set sc [expr {.35 + .05*$step}]
+ set sc [expr {1 / $sc}]
+
+ lassign [$w.c coords I14R_0] Ox Oy
+ $w.c scale I14R_0 $Ox $Oy $sc $sc
+ lassign [lrange [$w.c coords I14R_1] end-1 end] Ox Oy
+ $w.c scale I14R_1 $Ox $Oy $sc $sc
+ Draw14a $w R
+
+ return [expr {$step == 10 ? 3 : 1}]
+}
+
+# Light beam
+proc Draw15 {w} {
+ set color $::C(15a)
+ set xy {824 599 824 585 820 585 829 585}
+ $w.c create line $xy -fill $::C(fg) -width 3 -tag I15a
+ set xy {789 599 836 643}
+ $w.c create rect $xy -fill $color -outline $::C(fg) -width 3
+ set xy {778 610 788 632}
+ $w.c create rect $xy -fill $color -outline $::C(fg) -width 3
+ set xy {766 617 776 625}
+ $w.c create rect $xy -fill $color -outline $::C(fg) -width 3
+
+ set xy {633 600 681 640}
+ $w.c create rect $xy -fill $color -outline $::C(fg) -width 3
+ set xy {635 567 657 599}
+ $w.c create rect $xy -fill $color -outline $::C(fg) -width 2
+ set xy {765 557 784 583}
+ $w.c create rect $xy -fill $color -outline $::C(fg) -width 2
+
+ Sine $w 658 580 765 580 3 15 -tag I15_s -fill $::C(fg) -width 3
+}
+proc Move15a {w} {
+ set color $::C(15b)
+ $w.c scale I15a 824 599 1 .3 ;# Button down
+ set xy {765 621 681 621}
+ $w.c create line $xy -dash "-" -width 3 -fill $color -tag I15
+}
+proc Move15 {w {step {}}} {
+ set step [GetStep 15 $step]
+ set numsteps 6
+
+ if {$step == $numsteps+2} {
+ MoveAbs $w I15_star {-100 -100}
+ return 2
+ }
+ if {$step == 0} { ;# Break the light beam
+ Sparkle $w {-100 -100} I15_star
+ set xy {765 621 745 621}
+ $w.c coords I15 $xy
+ return 1
+ }
+ lassign [Anchor $w I15_s w] x0 y0
+ lassign [Anchor $w I15_s e] x1 y1
+ set x [expr {$x0 + ($x1-$x0) * ($step - 1) / double($numsteps)}]
+ MoveAbs $w I15_star [list $x $y0]
+ return 1
+}
+
+# Bell
+proc Draw16 {w} {
+ set color $::C(16)
+ set xy {722 485 791 556}
+ $w.c create rect $xy -fill {} -outline $::C(fg) -width 3
+ set xy [box 752 515 25] ;# Bell
+ $w.c create oval $xy -fill $color -outline black -tag I16b -width 2
+ set xy [box 752 515 5] ;# Bell button
+ $w.c create oval $xy -fill black -outline black -tag I16b
+
+ set xy {784 523 764 549} ;# Clapper
+ $w.c create line $xy -width 3 -tag I16c -fill $::C(fg)
+ set xy [box 784 523 4]
+ $w.c create oval $xy -fill $::C(fg) -outline $::C(fg) -tag I16d
+}
+proc Move16 {w {step {}}} {
+ set step [GetStep 16 $step]
+
+ # Note: we never stop
+ lassign {760 553} Ox Oy
+ if {$step & 1} {
+ set beta 12
+ $w.c move I16b 3 0
+ } else {
+ set beta -12
+ $w.c move I16b -3 0
+ }
+ RotateItem $w I16c $Ox $Oy $beta
+ RotateItem $w I16d $Ox $Oy $beta
+
+ return [expr {$step == 1 ? 3 : 1}]
+}
+
+# Cat
+proc Draw17 {w} {
+ set color $::C(17)
+
+ set xy {584 556 722 556}
+ $w.c create line $xy -fill $::C(fg) -width 3
+ set xy {584 485 722 485}
+ $w.c create line $xy -fill $::C(fg) -width 3
+
+ set xy {664 523 717 549} ;# Body
+ $w.c create arc $xy -outline $::C(fg) -fill $color -width 3 \
+ -style chord -start 128 -extent -260 -tag I17
+
+ set xy {709 554 690 543} ;# Paw
+ $w.c create oval $xy -outline $::C(fg) -fill $color -width 3 -tag I17
+ set xy {657 544 676 555}
+ $w.c create oval $xy -outline $::C(fg) -fill $color -width 3 -tag I17
+
+ set xy [box 660 535 15] ;# Lower face
+ $w.c create arc $xy -outline $::C(fg) -width 3 -style arc \
+ -start 150 -extent 240 -tag I17_
+ $w.c create arc $xy -outline {} -fill $color -width 1 -style chord \
+ -start 150 -extent 240 -tag I17_
+ set xy {674 529 670 513 662 521 658 521 650 513 647 529} ;# Ears
+ $w.c create line $xy -fill $::C(fg) -width 3 -tag I17_
+ $w.c create poly $xy -fill $color -outline {} -width 1 -tag {I17_ I17_c}
+ set xy {652 542 628 539} ;# Whiskers
+ $w.c create line $xy -fill $::C(fg) -width 3 -tag I17_
+ set xy {652 543 632 545}
+ $w.c create line $xy -fill $::C(fg) -width 3 -tag I17_
+ set xy {652 546 632 552}
+ $w.c create line $xy -fill $::C(fg) -width 3 -tag I17_
+
+ set xy {668 543 687 538}
+ $w.c create line $xy -fill $::C(fg) -width 3 -tag {I17_ I17w}
+ set xy {668 544 688 546}
+ $w.c create line $xy -fill $::C(fg) -width 3 -tag {I17_ I17w}
+ set xy {668 547 688 553}
+ $w.c create line $xy -fill $::C(fg) -width 3 -tag {I17_ I17w}
+
+ set xy {649 530 654 538 659 530} ;# Left eye
+ $w.c create line $xy -fill $::C(fg) -width 2 -smooth 1 -tag I17
+ set xy {671 530 666 538 661 530} ;# Right eye
+ $w.c create line $xy -fill $::C(fg) -width 2 -smooth 1 -tag I17
+ set xy {655 543 660 551 665 543} ;# Mouth
+ $w.c create line $xy -fill $::C(fg) -width 2 -smooth 1 -tag I17
+}
+proc Move17 {w {step {}}} {
+ set step [GetStep 17 $step]
+
+ if {$step == 0} {
+ $w.c delete I17 ;# Delete most of the cat
+ set xy {655 543 660 535 665 543} ;# Mouth
+ $w.c create line $xy -fill $::C(fg) -width 3 -smooth 1 -tag I17_
+ set xy [box 654 530 4] ;# Left eye
+ $w.c create oval $xy -outline $::C(fg) -width 3 -fill {} -tag I17_
+ set xy [box 666 530 4] ;# Right eye
+ $w.c create oval $xy -outline $::C(fg) -width 3 -fill {} -tag I17_
+
+ $w.c move I17_ 0 -20 ;# Move face up
+ set xy {652 528 652 554} ;# Front leg
+ $w.c create line $xy -fill $::C(fg) -width 3 -tag I17_
+ set xy {670 528 670 554} ;# 2nd front leg
+ $w.c create line $xy -fill $::C(fg) -width 3 -tag I17_
+
+ set xy {
+ 675 506 694 489 715 513 715 513 715 513 716 525 716 525 716 525
+ 706 530 695 530 679 535 668 527 668 527 668 527 675 522 676 517
+ 677 512
+ } ;# Body
+ $w.c create poly $xy -fill [$w.c itemcget I17_c -fill] \
+ -outline $::C(fg) -width 3 -smooth 1 -tag I17_
+ set xy {716 514 716 554} ;# Back leg
+ $w.c create line $xy -fill $::C(fg) -width 3 -tag I17_
+ set xy {694 532 694 554} ;# 2nd back leg
+ $w.c create line $xy -fill $::C(fg) -width 3 -tag I17_
+ set xy {715 514 718 506 719 495 716 488};# Tail
+ $w.c create line $xy -fill $::C(fg) -width 3 -smooth 1 -tag I17_
+
+ $w.c raise I17w ;# Make whiskers visible
+ $w.c move I17_ -5 0 ;# Move away from wall a bit
+ return 2
+ }
+ return 0
+}
+
+# Sling shot
+proc Draw18 {w} {
+ set color $::C(18)
+ set xy {721 506 627 506} ;# Sling hold
+ $w.c create line $xy -width 4 -fill $::C(fg) -tag I18
+
+ set xy {607 500 628 513} ;# Sling rock
+ $w.c create oval $xy -fill $color -outline {} -tag I18a
+
+ set xy {526 513 606 507 494 502} ;# Sling band
+ $w.c create line $xy -fill $::C(fg) -width 4 -tag I18b
+ set xy { 485 490 510 540 510 575 510 540 535 491 } ;# Sling
+ $w.c create line $xy -fill $::C(fg) -width 6
+}
+proc Move18 {w {step {}}} {
+ set step [GetStep 18 $step]
+
+ set pos {
+ {587 506} {537 506} {466 506} {376 506} {266 506 x} {136 506}
+ {16 506} {-100 -100}
+ }
+
+ set b(0) {490 502 719 507 524 512} ;# Band collapsing
+ set b(1) {
+ 491 503 524 557 563 505 559 496 546 506 551 525 553 536 538 534
+ 532 519 529 499
+ }
+ set b(2) {491 503 508 563 542 533 551 526 561 539 549 550 530 500}
+ set b(3) {491 503 508 563 530 554 541 562 525 568 519 544 530 501}
+
+ if {$step >= [llength $pos]} {
+ return 0
+ }
+
+ if {$step == 0} {
+ $w.c delete I18
+ $w.c itemconfig I18b -smooth 1
+ }
+ if {[info exists b($step)]} {
+ $w.c coords I18b $b($step)
+ }
+
+ set where [lindex $pos $step]
+ MoveAbs $w I18a $where
+ if {[lindex $where 2] eq "x"} {
+ return 3
+ }
+ return 1
+}
+
+# Water pipe
+proc Draw19 {w} {
+ set color $::C(19)
+ set xx {249 181 155 118 86 55 22 0}
+ foreach {x1 x2} $xx {
+ $w.c create rect $x1 453 $x2 467 -fill $color -outline {} -tag I19
+ $w.c create line $x1 453 $x2 453 -fill $::C(fg) -width 1;# Pipe top
+ $w.c create line $x1 467 $x2 467 -fill $::C(fg) -width 1;# Pipe bottom
+ }
+ $w.c raise I11i
+
+ set xy [box 168 460 16] ;# Bulge by the joint
+ $w.c create oval $xy -fill $color -outline {}
+ $w.c create arc $xy -outline $::C(fg) -width 1 -style arc \
+ -start 21 -extent 136
+ $w.c create arc $xy -outline $::C(fg) -width 1 -style arc \
+ -start -21 -extent -130
+
+ set xy {249 447 255 473} ;# First joint 26x6
+ $w.c create rect $xy -fill $color -outline $::C(fg) -width 1
+
+ set xy [box 257 433 34] ;# Bend up
+ $w.c create arc $xy -outline {} -fill $color -width 1 \
+ -style pie -start 0 -extent -91
+ $w.c create arc $xy -outline $::C(fg) -width 1 \
+ -style arc -start 0 -extent -90
+ set xy [box 257 433 20]
+ $w.c create arc $xy -outline {} -fill $::C(bg) -width 1 \
+ -style pie -start 0 -extent -92
+ $w.c create arc $xy -outline $::C(fg) -width 1 \
+ -style arc -start 0 -extent -90
+ set xy [box 257 421 34] ;# Bend left
+ $w.c create arc $xy -outline {} -fill $color -width 1 \
+ -style pie -start 1 -extent 91
+ $w.c create arc $xy -outline $::C(fg) -width 1 \
+ -style arc -start 0 -extent 90
+ set xy [box 257 421 20]
+ $w.c create arc $xy -outline {} -fill $::C(bg) -width 1 \
+ -style pie -start 0 -extent 90
+ $w.c create arc $xy -outline $::C(fg) -width 1 \
+ -style arc -start 0 -extent 90
+ set xy [box 243 421 34] ;# Bend down
+ $w.c create arc $xy -outline {} -fill $color -width 1 \
+ -style pie -start 90 -extent 90
+ $w.c create arc $xy -outline $::C(fg) -width 1 \
+ -style arc -start 90 -extent 90
+ set xy [box 243 421 20]
+ $w.c create arc $xy -outline {} -fill $::C(bg) -width 1 \
+ -style pie -start 90 -extent 90
+ $w.c create arc $xy -outline $::C(fg) -width 1 \
+ -style arc -start 90 -extent 90
+
+ set xy {270 427 296 433} ;# 2nd joint bottom
+ $w.c create rect $xy -fill $color -outline $::C(fg) -width 1
+ set xy {270 421 296 427} ;# 2nd joint top
+ $w.c create rect $xy -fill $color -outline $::C(fg) -width 1
+ set xy {249 382 255 408} ;# Third joint right
+ $w.c create rect $xy -fill $color -outline $::C(fg) -width 1
+ set xy {243 382 249 408} ;# Third joint left
+ $w.c create rect $xy -fill $color -outline $::C(fg) -width 1
+ set xy {203 420 229 426} ;# Last joint
+ $w.c create rect $xy -fill $color -outline $::C(fg) -width 1
+
+ set xy [box 168 460 6] ;# Handle joint
+ $w.c create oval $xy -fill $::C(fg) -outline {} -tag I19a
+ set xy {168 460 168 512} ;# Handle bar
+ $w.c create line $xy -fill $::C(fg) -width 5 -tag I19b
+}
+proc Move19 {w {step {}}} {
+ set step [GetStep 19 $step]
+
+ set angles {30 30 30}
+ if {$step == [llength $angles]} {
+ return 2
+ }
+
+ RotateItem $w I19b {*}[Centroid $w I19a] [lindex $angles $step]
+ return 1
+}
+
+# Water pouring
+proc Draw20 {w} {
+}
+proc Move20 {w {step {}}} {
+ set step [GetStep 20 $step]
+
+ set pos {451 462 473 484 496 504 513 523 532}
+ set freq {20 40 40 40 40 40 40 40 40}
+ set pos {
+ {451 20} {462 40} {473 40} {484 40} {496 40} {504 40} {513 40}
+ {523 40} {532 40 x}
+ }
+ if {$step >= [llength $pos]} {
+ return 0
+ }
+
+ $w.c delete I20
+ set where [lindex $pos $step]
+ lassign $where y f
+ H2O $w $y $f
+ if {[lindex $where 2] eq "x"} {
+ return 3
+ }
+ return 1
+}
+proc H2O {w y f} {
+ set color $::C(20)
+ $w.c delete I20
+
+ Sine $w 208 428 208 $y 4 $f -tag {I20 I20s} -width 3 -fill $color \
+ -smooth 1
+ $w.c create line [$w.c coords I20s] -width 3 -fill $color -smooth 1 \
+ -tag {I20 I20a}
+ $w.c create line [$w.c coords I20s] -width 3 -fill $color -smooth 1 \
+ -tag {I20 I20b}
+ $w.c move I20a 8 0
+ $w.c move I20b 16 0
+}
+
+# Bucket
+proc Draw21 {w} {
+ set color $::C(21)
+ set xy {217 451 244 490} ;# Right handle
+ $w.c create line $xy -fill $::C(fg) -width 2 -tag I21_a
+ set xy {201 467 182 490} ;# Left handle
+ $w.c create line $xy -fill $::C(fg) -width 2 -tag I21_a
+
+ set xy {245 490 237 535} ;# Right side
+ set xy2 {189 535 181 490} ;# Left side
+ $w.c create poly [concat $xy $xy2] -fill $color -outline {} \
+ -tag {I21 I21f}
+ $w.c create line $xy -fill $::C(fg) -width 2 -tag I21
+ $w.c create line $xy2 -fill $::C(fg) -width 2 -tag I21
+
+ set xy {182 486 244 498} ;# Top
+ $w.c create oval $xy -fill $color -outline {} -width 2 -tag {I21 I21f}
+ $w.c create oval $xy -fill {} -outline $::C(fg) -width 2 -tag {I21 I21t}
+ set xy {189 532 237 540} ;# Bottom
+ $w.c create oval $xy -fill $color -outline $::C(fg) -width 2 \
+ -tag {I21 I21b}
+}
+proc Move21 {w {step {}}} {
+ set step [GetStep 21 $step]
+
+ set numsteps 30
+ if {$step >= $numsteps} {
+ return 0
+ }
+
+ lassign [$w.c coords I21b] x1 y1 x2 y2
+ #lassign [$w.c coords I21t] X1 Y1 X2 Y2
+ lassign {183 492 243 504} X1 Y1 X2 Y2
+
+ set f [expr {$step / double($numsteps)}]
+ set y2 [expr {$y2 - 3}]
+ set xx1 [expr {$x1 + ($X1 - $x1) * $f}]
+ set yy1 [expr {$y1 + ($Y1 - $y1) * $f}]
+ set xx2 [expr {$x2 + ($X2 - $x2) * $f}]
+ set yy2 [expr {$y2 + ($Y2 - $y2) * $f}]
+ #H2O $w $yy1 40
+
+ $w.c itemconfig I21b -fill $::C(20)
+ $w.c delete I21w
+ $w.c create poly $x2 $y2 $x1 $y1 $xx1 $yy1 $xx2 $yy1 -tag {I21 I21w} \
+ -outline {} -fill $::C(20)
+ $w.c lower I21w I21
+ $w.c raise I21b
+ $w.c lower I21f
+
+ return [expr {$step == $numsteps-1 ? 3 : 1}]
+}
+
+# Bucket drop
+proc Draw22 {w} {
+}
+proc Move22 {w {step {}}} {
+ set step [GetStep 22 $step]
+ set pos {{213 513} {213 523} {213 543 x} {213 583} {213 593}}
+
+ if {$step == 0} {$w.c itemconfig I21f -fill $::C(22)}
+ if {$step >= [llength $pos]} {
+ return 0
+ }
+ set where [lindex $pos $step]
+ MoveAbs $w I21 $where
+ H2O $w [lindex $where 1] 40
+ $w.c delete I21_a ;# Delete handles
+
+ if {[lindex $where 2] eq "x"} {
+ return 3
+ }
+ return 1
+}
+
+# Blow dart
+proc Draw23 {w} {
+ set color $::C(23a)
+ set color2 $::C(23b)
+ set color3 $::C(23c)
+
+ set xy {185 623 253 650} ;# Block
+ $w.c create rect $xy -fill black -outline $::C(fg) -width 2 -tag I23a
+ set xy {187 592 241 623} ;# Balloon
+ $w.c create oval $xy -outline {} -fill $color -tag I23b
+ $w.c create arc $xy -outline $::C(fg) -width 3 -tag I23b \
+ -style arc -start 12 -extent 336
+ set xy {239 604 258 589 258 625 239 610} ;# Balloon nozzle
+ $w.c create poly $xy -outline {} -fill $color -tag I23b
+ $w.c create line $xy -fill $::C(fg) -width 3 -tag I23b
+
+ set xy {285 611 250 603} ;# Dart body
+ $w.c create oval $xy -fill $color2 -outline $::C(fg) -width 3 -tag I23d
+ set xy {249 596 249 618 264 607 249 596} ;# Dart tail
+ $w.c create poly $xy -fill $color3 -outline $::C(fg) -width 3 -tag I23d
+ set xy {249 607 268 607} ;# Dart detail
+ $w.c create line $xy -fill $::C(fg) -width 3 -tag I23d
+ set xy {285 607 305 607} ;# Dart needle
+ $w.c create line $xy -fill $::C(fg) -width 3 -tag I23d
+}
+proc Move23 {w {step {}}} {
+ set step [GetStep 23 $step]
+
+ set pos {
+ {277 607} {287 607} {307 607 x} {347 607} {407 607} {487 607}
+ {587 607} {687 607} {787 607} {-100 -100}
+ }
+
+ if {$step >= [llength $pos]} {
+ return 0
+ }
+ if {$step <= 1} {
+ $w.c scale I23b {*}[Anchor $w I23a n] .9 .5
+ }
+ set where [lindex $pos $step]
+ MoveAbs $w I23d $where
+
+ if {[lindex $where 2] eq "x"} {
+ return 3
+ }
+ return 1
+}
+
+# Balloon
+proc Draw24 {w} {
+ set color $::C(24a)
+ set xy {366 518 462 665} ;# Balloon
+ $w.c create oval $xy -fill $color -outline $::C(fg) -width 3 -tag I24
+ set xy {414 666 414 729} ;# String
+ $w.c create line $xy -fill $::C(fg) -width 3 -tag I24
+ set xy {410 666 404 673 422 673 418 666} ;# Nozzle
+ $w.c create poly $xy -fill $color -outline $::C(fg) -width 3 -tag I24
+
+ set xy {387 567 390 549 404 542} ;# Reflections
+ $w.c create line $xy -fill $::C(fg) -smooth 1 -width 2 -tag I24
+ set xy {395 568 399 554 413 547}
+ $w.c create line $xy -fill $::C(fg) -smooth 1 -width 2 -tag I24
+ set xy {403 570 396 555 381 553}
+ $w.c create line $xy -fill $::C(fg) -smooth 1 -width 2 -tag I24
+ set xy {408 564 402 547 386 545}
+ $w.c create line $xy -fill $::C(fg) -smooth 1 -width 2 -tag I24
+}
+proc Move24 {w {step {}}} {
+ global S
+ set step [GetStep 24 $step]
+
+ if {$step > 4} {
+ return 0
+ } elseif {$step == 4} {
+ return 2
+ }
+
+ if {$step == 0} {
+ $w.c delete I24 ;# Exploding balloon
+ set xy {
+ 347 465 361 557 271 503 272 503 342 574 259 594 259 593 362 626
+ 320 737 320 740 398 691 436 738 436 739 476 679 528 701 527 702
+ 494 627 548 613 548 613 480 574 577 473 577 473 474 538 445 508
+ 431 441 431 440 400 502 347 465 347 465
+ }
+ $w.c create poly $xy -tag I24 -fill $::C(24b) -outline $::C(24a) \
+ -width 10 -smooth 1
+ set msg [subst $S(message)]
+ $w.c create text [Centroid $w I24] -text $msg -tag {I24 I24t} \
+ -justify center -font {{Times Roman} 18 bold}
+ return 1
+ }
+
+ $w.c itemconfig I24t -font [list {Times Roman} [expr {18 + 6*$step}] bold]
+ $w.c move I24 0 -60
+ $w.c scale I24 {*}[Centroid $w I24] 1.25 1.25
+ return 1
+}
+
+# Displaying the message
+proc Move25 {w {step {}}} {
+ global S
+ set step [GetStep 25 $step]
+ if {$step == 0} {
+ set ::XY(25) [clock clicks -milliseconds]
+ return 1
+ }
+ set elapsed [expr {[clock clicks -milliseconds] - $::XY(25)}]
+ if {$elapsed < 5000} {
+ return 1
+ }
+ return 2
+}
+
+# Collapsing balloon
+proc Move26 {w {step {}}} {
+ global S
+ set step [GetStep 26 $step]
+
+ if {$step >= 3} {
+ $w.c delete I24 I26
+ $w.c create text 430 755 -anchor s -tag I26 \
+ -text "click to continue" -font {{Times Roman} 24 bold}
+ bind $w.c <1> [list Reset $w]
+ return 4
+ }
+
+ $w.c scale I24 {*}[Centroid $w I24] .8 .8
+ $w.c move I24 0 60
+ $w.c itemconfig I24t -font [list {Times Roman} [expr {30 - 6*$step}] bold]
+ return 1
+}
+
+################################################################
+#
+# Helper functions
+#
+
+proc box {x y r} {
+ return [list [expr {$x-$r}] [expr {$y-$r}] [expr {$x+$r}] [expr {$y+$r}]]
+}
+
+proc MoveAbs {w item xy} {
+ lassign $xy x y
+ lassign [Centroid $w $item] Ox Oy
+ set dx [expr {$x - $Ox}]
+ set dy [expr {$y - $Oy}]
+ $w.c move $item $dx $dy
+}
+
+proc RotateItem {w item Ox Oy beta} {
+ set xy [$w.c coords $item]
+ set xy2 {}
+ foreach {x y} $xy {
+ lappend xy2 {*}[RotateC $x $y $Ox $Oy $beta]
+ }
+ $w.c coords $item $xy2
+}
+
+proc RotateC {x y Ox Oy beta} {
+ # rotates vector (Ox,Oy)->(x,y) by beta degrees clockwise
+
+ set x [expr {$x - $Ox}] ;# Shift to origin
+ set y [expr {$y - $Oy}]
+
+ set beta [expr {$beta * atan(1) * 4 / 180.0}] ;# Radians
+ set xx [expr {$x * cos($beta) - $y * sin($beta)}] ;# Rotate
+ set yy [expr {$x * sin($beta) + $y * cos($beta)}]
+
+ set xx [expr {$xx + $Ox}] ;# Shift back
+ set yy [expr {$yy + $Oy}]
+
+ return [list $xx $yy]
+}
+
+proc Reset {w} {
+ global S
+ DrawAll $w
+ bind $w.c <1> {}
+ set S(mode) $::MSTART
+ set S(active) 0
+}
+
+# Each Move## keeps its state info in STEP, this retrieves and increments it
+proc GetStep {who step} {
+ global STEP
+ if {$step ne ""} {
+ set STEP($who) $step
+ } elseif {![info exists STEP($who)] || $STEP($who) eq ""} {
+ set STEP($who) 0
+ } else {
+ incr STEP($who)
+ }
+ return $STEP($who)
+}
+
+proc ResetStep {} {
+ global STEP
+ set ::S(cnt) 0
+ foreach a [array names STEP] {
+ set STEP($a) ""
+ }
+}
+
+proc Sine {w x0 y0 x1 y1 amp freq args} {
+ set PI [expr {4 * atan(1)}]
+ set step 2
+ set xy {}
+ if {$y0 == $y1} { ;# Horizontal
+ for {set x $x0} {$x <= $x1} {incr x $step} {
+ set beta [expr {($x - $x0) * 2 * $PI / $freq}]
+ set y [expr {$y0 + $amp * sin($beta)}]
+ lappend xy $x $y
+ }
+ } else {
+ for {set y $y0} {$y <= $y1} {incr y $step} {
+ set beta [expr {($y - $y0) * 2 * $PI / $freq}]
+ set x [expr {$x0 + $amp * sin($beta)}]
+ lappend xy $x $y
+ }
+ }
+ return [$w.c create line $xy {*}$args]
+}
+
+proc RoundRect {w xy radius args} {
+ lassign $xy x0 y0 x3 y3
+ set r [winfo pixels $w.c $radius]
+ set d [expr {2 * $r}]
+
+ # Make sure that the radius of the curve is less than 3/8 size of the box!
+ set maxr 0.75
+ if {$d > $maxr * ($x3 - $x0)} {
+ set d [expr {$maxr * ($x3 - $x0)}]
+ }
+ if {$d > $maxr * ($y3 - $y0)} {
+ set d [expr {$maxr * ($y3 - $y0)}]
+ }
+
+ set x1 [expr { $x0 + $d }]
+ set x2 [expr { $x3 - $d }]
+ set y1 [expr { $y0 + $d }]
+ set y2 [expr { $y3 - $d }]
+
+ set xy [list $x0 $y0 $x1 $y0 $x2 $y0 $x3 $y0 $x3 $y1 $x3 $y2]
+ lappend xy $x3 $y3 $x2 $y3 $x1 $y3 $x0 $y3 $x0 $y2 $x0 $y1
+ return $xy
+}
+
+proc RoundPoly {canv xy radii args} {
+ set lenXY [llength $xy]
+ set lenR [llength $radii]
+ if {$lenXY != 2*$lenR} {
+ error "wrong number of vertices and radii"
+ }
+
+ set knots {}
+ lassign [lrange $xy end-1 end] x0 y0
+ lassign $xy x1 y1
+ lappend xy {*}[lrange $xy 0 1]
+
+ for {set i 0} {$i < $lenXY} {incr i 2} {
+ set radius [lindex $radii [expr {$i/2}]]
+ set r [winfo pixels $canv $radius]
+
+ lassign [lrange $xy [expr {$i + 2}] [expr {$i + 3}]] x2 y2
+ set z [_RoundPoly2 $x0 $y0 $x1 $y1 $x2 $y2 $r]
+ lappend knots {*}$z
+
+ lassign [list $x1 $y1] x0 y0
+ lassign [list $x2 $y2] x1 y1
+ }
+ set n [$canv create polygon $knots -smooth 1 {*}$args]
+ return $n
+}
+
+proc _RoundPoly2 {x0 y0 x1 y1 x2 y2 radius} {
+ set d [expr {2 * $radius}]
+ set maxr 0.75
+
+ set v1x [expr {$x0 - $x1}]
+ set v1y [expr {$y0 - $y1}]
+ set v2x [expr {$x2 - $x1}]
+ set v2y [expr {$y2 - $y1}]
+
+ set vlen1 [expr {sqrt($v1x*$v1x + $v1y*$v1y)}]
+ set vlen2 [expr {sqrt($v2x*$v2x + $v2y*$v2y)}]
+ if {$d > $maxr * $vlen1} {
+ set d [expr {$maxr * $vlen1}]
+ }
+ if {$d > $maxr * $vlen2} {
+ set d [expr {$maxr * $vlen2}]
+ }
+
+ lappend xy [expr {$x1 + $d * $v1x/$vlen1}] [expr {$y1 + $d * $v1y/$vlen1}]
+ lappend xy $x1 $y1
+ lappend xy [expr {$x1 + $d * $v2x/$vlen2}] [expr {$y1 + $d * $v2y/$vlen2}]
+
+ return $xy
+}
+
+proc Sparkle {w Oxy tag} {
+ set xy {299 283 298 302 295 314 271 331 239 310 242 292 256 274 281 273}
+ foreach {x y} $xy {
+ $w.c create line 271 304 $x $y -fill white -width 3 -tag $tag
+ }
+ MoveAbs $w $tag $Oxy
+}
+
+proc Centroid {w item} {
+ return [Anchor $w $item c]
+}
+
+proc Anchor {w item where} {
+ lassign [$w.c bbox $item] x1 y1 x2 y2
+ if {[string match *n* $where]} {
+ set y $y1
+ } elseif {[string match *s* $where]} {
+ set y $y2
+ } else {
+ set y [expr {($y1 + $y2) / 2.0}]
+ }
+ if {[string match *w* $where]} {
+ set x $x1
+ } elseif {[string match *e* $where]} {
+ set x $x2
+ } else {
+ set x [expr {($x1 + $x2) / 2.0}]
+ }
+ return [list $x $y]
+}
+
+DoDisplay $w
+Reset $w
+Go $w ;# Start everything going
diff --git a/tk8.6/library/demos/hello b/tk8.6/library/demos/hello
new file mode 100644
index 0000000..d10b8d5
--- /dev/null
+++ b/tk8.6/library/demos/hello
@@ -0,0 +1,22 @@
+#!/bin/sh
+# the next line restarts using wish \
+exec wish "$0" ${1+"$@"}
+
+# hello --
+# Simple Tk script to create a button that prints "Hello, world".
+# Click on the button to terminate the program.
+
+package require Tk
+
+# The first line below creates the button, and the second line
+# asks the packer to shrink-wrap the application's main window
+# around the button.
+
+button .hello -text "Hello, world" -command {
+ puts stdout "Hello, world"; destroy .
+}
+pack .hello
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tk8.6/library/demos/hscale.tcl b/tk8.6/library/demos/hscale.tcl
new file mode 100644
index 0000000..1df144d
--- /dev/null
+++ b/tk8.6/library/demos/hscale.tcl
@@ -0,0 +1,45 @@
+# hscale.tcl --
+#
+# This demonstration script shows an example with a horizontal scale.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .hscale
+catch {destroy $w}
+toplevel $w
+wm title $w "Horizontal Scale Demonstration"
+wm iconname $w "hscale"
+positionWindow $w
+
+label $w.msg -font $font -wraplength 3.5i -justify left -text "An arrow and a horizontal scale are displayed below. If you click or drag mouse button 1 in the scale, you can change the length of the arrow."
+pack $w.msg -side top -padx .5c
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+frame $w.frame -borderwidth 10
+pack $w.frame -side top -fill x
+
+canvas $w.frame.canvas -width 50 -height 50 -bd 0 -highlightthickness 0
+$w.frame.canvas create polygon 0 0 1 1 2 2 -fill DeepSkyBlue3 -tags poly
+$w.frame.canvas create line 0 0 1 1 2 2 0 0 -fill black -tags line
+scale $w.frame.scale -orient horizontal -length 284 -from 0 -to 250 \
+ -command "setWidth $w.frame.canvas" -tickinterval 50
+pack $w.frame.canvas -side top -expand yes -anchor s -fill x -padx 15
+pack $w.frame.scale -side bottom -expand yes -anchor n
+$w.frame.scale set 75
+
+proc setWidth {w width} {
+ incr width 21
+ set x2 [expr {$width - 30}]
+ if {$x2 < 21} {
+ set x2 21
+ }
+ $w coords poly 20 15 20 35 $x2 35 $x2 45 $width 25 $x2 5 $x2 15 20 15
+ $w coords line 20 15 20 35 $x2 35 $x2 45 $width 25 $x2 5 $x2 15 20 15
+}
diff --git a/tk8.6/library/demos/icon.tcl b/tk8.6/library/demos/icon.tcl
new file mode 100644
index 0000000..224d8f9
--- /dev/null
+++ b/tk8.6/library/demos/icon.tcl
@@ -0,0 +1,51 @@
+# icon.tcl --
+#
+# This demonstration script creates a toplevel window containing
+# buttons that display bitmaps instead of text.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .icon
+catch {destroy $w}
+toplevel $w
+wm title $w "Iconic Button Demonstration"
+wm iconname $w "icon"
+positionWindow $w
+
+label $w.msg -font $font -wraplength 5i -justify left -text "This window shows three ways of using bitmaps or images in radiobuttons and checkbuttons. On the left are two radiobuttons, each of which displays a bitmap and an indicator. In the middle is a checkbutton that displays a different image depending on whether it is selected or not. On the right is a checkbutton that displays a single bitmap but changes its background color to indicate whether or not it is selected."
+pack $w.msg -side top
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+# Main widget program sets variable tk_demoDirectory
+image create bitmap flagup \
+ -file [file join $tk_demoDirectory images flagup.xbm] \
+ -maskfile [file join $tk_demoDirectory images flagup.xbm]
+image create bitmap flagdown \
+ -file [file join $tk_demoDirectory images flagdown.xbm] \
+ -maskfile [file join $tk_demoDirectory images flagdown.xbm]
+frame $w.frame -borderwidth 10
+pack $w.frame -side top
+
+checkbutton $w.frame.b1 -image flagdown -selectimage flagup \
+ -indicatoron 0
+$w.frame.b1 configure -selectcolor [$w.frame.b1 cget -background]
+checkbutton $w.frame.b2 \
+ -bitmap @[file join $tk_demoDirectory images letters.xbm] \
+ -indicatoron 0 -selectcolor SeaGreen1
+frame $w.frame.left
+pack $w.frame.left $w.frame.b1 $w.frame.b2 -side left -expand yes -padx 5m
+
+radiobutton $w.frame.left.b3 \
+ -bitmap @[file join $tk_demoDirectory images letters.xbm] \
+ -variable letters -value full
+radiobutton $w.frame.left.b4 \
+ -bitmap @[file join $tk_demoDirectory images noletter.xbm] \
+ -variable letters -value empty
+pack $w.frame.left.b3 $w.frame.left.b4 -side top -expand yes
diff --git a/tk8.6/library/demos/image1.tcl b/tk8.6/library/demos/image1.tcl
new file mode 100644
index 0000000..0bd2f49
--- /dev/null
+++ b/tk8.6/library/demos/image1.tcl
@@ -0,0 +1,35 @@
+# image1.tcl --
+#
+# This demonstration script displays two image widgets.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .image1
+catch {destroy $w}
+toplevel $w
+wm title $w "Image Demonstration #1"
+wm iconname $w "Image1"
+positionWindow $w
+
+label $w.msg -font $font -wraplength 4i -justify left -text "This demonstration displays two images, each in a separate label widget."
+pack $w.msg -side top
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+# Main widget program sets variable tk_demoDirectory
+catch {image delete image1a}
+image create photo image1a -file [file join $tk_demoDirectory images earth.gif]
+label $w.l1 -image image1a -bd 1 -relief sunken
+
+catch {image delete image1b}
+image create photo image1b \
+ -file [file join $tk_demoDirectory images earthris.gif]
+label $w.l2 -image image1b -bd 1 -relief sunken
+
+pack $w.l1 $w.l2 -side top -padx .5m -pady .5m
diff --git a/tk8.6/library/demos/image2.tcl b/tk8.6/library/demos/image2.tcl
new file mode 100644
index 0000000..2d7ba03
--- /dev/null
+++ b/tk8.6/library/demos/image2.tcl
@@ -0,0 +1,108 @@
+# image2.tcl --
+#
+# This demonstration script creates a simple collection of widgets
+# that allow you to select and view images in a Tk label.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+# loadDir --
+# This procedure reloads the directory listbox from the directory
+# named in the demo's entry.
+#
+# Arguments:
+# w - Name of the toplevel window of the demo.
+
+proc loadDir w {
+ global dirName
+
+ $w.f.list delete 0 end
+ foreach i [lsort [glob -type f -directory $dirName *]] {
+ $w.f.list insert end [file tail $i]
+ }
+}
+
+# selectAndLoadDir --
+# This procedure pops up a dialog to ask for a directory to load into
+# the listobx and (if the user presses OK) reloads the directory
+# listbox from the directory named in the demo's entry.
+#
+# Arguments:
+# w - Name of the toplevel window of the demo.
+
+proc selectAndLoadDir w {
+ global dirName
+ set dir [tk_chooseDirectory -initialdir $dirName -parent $w -mustexist 1]
+ if {$dir ne ""} {
+ set dirName $dir
+ loadDir $w
+ }
+}
+
+# loadImage --
+# Given the name of the toplevel window of the demo and the mouse
+# position, extracts the directory entry under the mouse and loads
+# that file into a photo image for display.
+#
+# Arguments:
+# w - Name of the toplevel window of the demo.
+# x, y- Mouse position within the listbox.
+
+proc loadImage {w x y} {
+ global dirName
+
+ set file [file join $dirName [$w.f.list get @$x,$y]]
+ if {[catch {
+ image2a configure -file $file
+ }]} then {
+ # Mark the file as not loadable
+ $w.f.list itemconfigure @$x,$y -bg \#c00000 -selectbackground \#ff0000
+ }
+}
+
+set w .image2
+catch {destroy $w}
+toplevel $w
+wm title $w "Image Demonstration #2"
+wm iconname $w "Image2"
+positionWindow $w
+
+label $w.msg -font $font -wraplength 4i -justify left -text "This demonstration allows you to view images using a Tk \"photo\" image. First type a directory name in the listbox, then type Return to load the directory into the listbox. Then double-click on a file name in the listbox to see that image."
+pack $w.msg -side top
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+frame $w.mid
+pack $w.mid -fill both -expand 1
+
+labelframe $w.dir -text "Directory:"
+# Main widget program sets variable tk_demoDirectory
+set dirName [file join $tk_demoDirectory images]
+entry $w.dir.e -width 30 -textvariable dirName
+button $w.dir.b -pady 0 -padx 2m -text "Select Dir." \
+ -command "selectAndLoadDir $w"
+bind $w.dir.e <Return> "loadDir $w"
+pack $w.dir.e -side left -fill both -padx 2m -pady 2m -expand true
+pack $w.dir.b -side left -fill y -padx {0 2m} -pady 2m
+labelframe $w.f -text "File:" -padx 2m -pady 2m
+
+listbox $w.f.list -width 20 -height 10 -yscrollcommand "$w.f.scroll set"
+ttk::scrollbar $w.f.scroll -command "$w.f.list yview"
+pack $w.f.list $w.f.scroll -side left -fill y -expand 1
+$w.f.list insert 0 earth.gif earthris.gif teapot.ppm
+bind $w.f.list <Double-1> "loadImage $w %x %y"
+
+catch {image delete image2a}
+image create photo image2a
+labelframe $w.image -text "Image:"
+label $w.image.image -image image2a
+pack $w.image.image -padx 2m -pady 2m
+
+grid $w.dir - -sticky ew -padx 1m -pady 1m -in $w.mid
+grid $w.f $w.image -sticky nw -padx 1m -pady 1m -in $w.mid
+grid columnconfigure $w.mid 1 -weight 1
diff --git a/tk8.6/library/demos/images/earth.gif b/tk8.6/library/demos/images/earth.gif
new file mode 100644
index 0000000..2c229eb
--- /dev/null
+++ b/tk8.6/library/demos/images/earth.gif
Binary files differ
diff --git a/tk8.6/library/demos/images/earthmenu.png b/tk8.6/library/demos/images/earthmenu.png
new file mode 100644
index 0000000..c25b667
--- /dev/null
+++ b/tk8.6/library/demos/images/earthmenu.png
Binary files differ
diff --git a/tk8.6/library/demos/images/earthris.gif b/tk8.6/library/demos/images/earthris.gif
new file mode 100644
index 0000000..c4ee473
--- /dev/null
+++ b/tk8.6/library/demos/images/earthris.gif
Binary files differ
diff --git a/tk8.6/library/demos/images/flagdown.xbm b/tk8.6/library/demos/images/flagdown.xbm
new file mode 100644
index 0000000..55abc51
--- /dev/null
+++ b/tk8.6/library/demos/images/flagdown.xbm
@@ -0,0 +1,27 @@
+#define flagdown_width 48
+#define flagdown_height 48
+static char flagdown_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xe1, 0x00, 0x00,
+ 0x00, 0x00, 0x70, 0x80, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x03, 0x00,
+ 0x00, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x04,
+ 0x00, 0x00, 0x03, 0x00, 0x06, 0x06, 0x00, 0x80, 0x01, 0x00, 0x06, 0x07,
+ 0x00, 0xc0, 0x1f, 0x00, 0x87, 0x07, 0x00, 0xe0, 0x7f, 0x80, 0xc7, 0x07,
+ 0x00, 0x70, 0xe0, 0xc0, 0xe5, 0x07, 0x00, 0x38, 0x80, 0xe1, 0x74, 0x07,
+ 0x00, 0x18, 0x80, 0x71, 0x3c, 0x07, 0x00, 0x0c, 0x00, 0x3b, 0x1e, 0x03,
+ 0x00, 0x0c, 0x00, 0x1f, 0x0f, 0x00, 0x00, 0x86, 0x1f, 0x8e, 0x07, 0x00,
+ 0x00, 0x06, 0x06, 0xc6, 0x05, 0x00, 0x00, 0x06, 0x00, 0xc6, 0x05, 0x00,
+ 0x00, 0x06, 0x00, 0xc6, 0x04, 0x00, 0x00, 0x06, 0x00, 0x06, 0x04, 0x00,
+ 0x7f, 0x06, 0x00, 0x06, 0xe4, 0xff, 0x00, 0x06, 0x00, 0x06, 0x04, 0x00,
+ 0x00, 0x06, 0x00, 0x06, 0x04, 0x00, 0x00, 0x06, 0x00, 0x06, 0x06, 0x00,
+ 0x00, 0x06, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x00, 0x86, 0x01, 0x00,
+ 0x00, 0x06, 0x00, 0xc6, 0x00, 0x00, 0x00, 0x06, 0x00, 0x66, 0x00, 0x00,
+ 0x00, 0x06, 0x00, 0x36, 0x00, 0x00, 0x00, 0x06, 0x00, 0x3e, 0x00, 0x00,
+ 0x00, 0xfe, 0xff, 0x2f, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x27, 0x00, 0x00,
+ 0x00, 0x00, 0x88, 0x20, 0x00, 0x00, 0x00, 0x00, 0x88, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x88, 0x20, 0x00, 0x00, 0x00, 0x00, 0x88, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x88, 0x20, 0x00, 0x00, 0x00, 0x00, 0x88, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x88, 0x20, 0x00, 0x00, 0x00, 0x00, 0x88, 0x20, 0x00, 0x00,
+ 0xf7, 0xbf, 0x8e, 0xfc, 0xdf, 0xf8, 0x9d, 0xeb, 0x9b, 0x76, 0xd2, 0x7a,
+ 0x46, 0x30, 0xe2, 0x0f, 0xe1, 0x47, 0x55, 0x84, 0x48, 0x11, 0x84, 0x19};
diff --git a/tk8.6/library/demos/images/flagup.xbm b/tk8.6/library/demos/images/flagup.xbm
new file mode 100644
index 0000000..6eb0d84
--- /dev/null
+++ b/tk8.6/library/demos/images/flagup.xbm
@@ -0,0 +1,27 @@
+#define flagup_width 48
+#define flagup_height 48
+static char flagup_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00,
+ 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xef, 0x6a, 0x00,
+ 0x00, 0x00, 0xc0, 0x7b, 0x75, 0x00, 0x00, 0x00, 0xe0, 0xe0, 0x6a, 0x00,
+ 0x00, 0x00, 0x30, 0x60, 0x75, 0x00, 0x00, 0x00, 0x18, 0xe0, 0x7f, 0x00,
+ 0x00, 0x00, 0x0c, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x06, 0xe0, 0x04, 0x00,
+ 0x00, 0x00, 0x03, 0xe0, 0x04, 0x00, 0x00, 0x80, 0x01, 0xe0, 0x06, 0x00,
+ 0x00, 0xc0, 0x1f, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x7f, 0xe0, 0x07, 0x00,
+ 0x00, 0x70, 0xe0, 0xe0, 0x05, 0x00, 0x00, 0x38, 0x80, 0xe1, 0x04, 0x00,
+ 0x00, 0x18, 0x80, 0xf1, 0x04, 0x00, 0x00, 0x0c, 0x00, 0xfb, 0x04, 0x00,
+ 0x00, 0x0c, 0x00, 0xff, 0x04, 0x00, 0x00, 0x86, 0x1f, 0xee, 0x04, 0x00,
+ 0x00, 0x06, 0x06, 0xe6, 0x04, 0x00, 0x00, 0x06, 0x00, 0xe6, 0x04, 0x00,
+ 0x00, 0x06, 0x00, 0xe6, 0x04, 0x00, 0x00, 0x06, 0x00, 0x66, 0x04, 0x00,
+ 0x7f, 0x56, 0x52, 0x06, 0xe4, 0xff, 0x00, 0x76, 0x55, 0x06, 0x04, 0x00,
+ 0x00, 0x56, 0x57, 0x06, 0x04, 0x00, 0x00, 0x56, 0x55, 0x06, 0x06, 0x00,
+ 0x00, 0x56, 0xd5, 0x06, 0x03, 0x00, 0x00, 0x06, 0x00, 0x86, 0x01, 0x00,
+ 0x54, 0x06, 0x00, 0xc6, 0x54, 0x55, 0xaa, 0x06, 0x00, 0x66, 0xaa, 0x2a,
+ 0x54, 0x06, 0x00, 0x36, 0x55, 0x55, 0xaa, 0x06, 0x00, 0xbe, 0xaa, 0x2a,
+ 0x54, 0xfe, 0xff, 0x6f, 0x55, 0x55, 0xaa, 0xfc, 0xff, 0xa7, 0xaa, 0x2a,
+ 0x54, 0x01, 0x88, 0x60, 0x55, 0x55, 0xaa, 0xaa, 0x8a, 0xa0, 0xaa, 0x2a,
+ 0x54, 0x55, 0x8d, 0x60, 0x55, 0x55, 0xaa, 0xaa, 0x8a, 0xa0, 0xaa, 0x2a,
+ 0x54, 0x55, 0x8d, 0x60, 0x55, 0x55, 0xaa, 0xaa, 0x8a, 0xa0, 0xaa, 0x2a,
+ 0x54, 0x55, 0x8d, 0x50, 0x55, 0x55, 0xaa, 0xaa, 0x8a, 0xa8, 0xaa, 0x2a,
+ 0x54, 0x55, 0x95, 0x54, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a,
+ 0x54, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/tk8.6/library/demos/images/gray25.xbm b/tk8.6/library/demos/images/gray25.xbm
new file mode 100644
index 0000000..b234b3c
--- /dev/null
+++ b/tk8.6/library/demos/images/gray25.xbm
@@ -0,0 +1,6 @@
+#define grey_width 16
+#define grey_height 16
+static char grey_bits[] = {
+ 0x11, 0x11, 0x44, 0x44, 0x11, 0x11, 0x44, 0x44, 0x11, 0x11, 0x44, 0x44,
+ 0x11, 0x11, 0x44, 0x44, 0x11, 0x11, 0x44, 0x44, 0x11, 0x11, 0x44, 0x44,
+ 0x11, 0x11, 0x44, 0x44, 0x11, 0x11, 0x44, 0x44};
diff --git a/tk8.6/library/demos/images/letters.xbm b/tk8.6/library/demos/images/letters.xbm
new file mode 100644
index 0000000..0f12568
--- /dev/null
+++ b/tk8.6/library/demos/images/letters.xbm
@@ -0,0 +1,27 @@
+#define letters_width 48
+#define letters_height 48
+static char letters_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xfe, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0xfa, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2a,
+ 0x00, 0x3a, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2e,
+ 0xe0, 0xff, 0xff, 0xff, 0xff, 0x21, 0x20, 0x00, 0x00, 0x00, 0x00, 0x21,
+ 0xa0, 0x03, 0x00, 0x00, 0x70, 0x21, 0x20, 0x00, 0x00, 0x00, 0x50, 0x21,
+ 0xa0, 0x1f, 0x00, 0x00, 0x50, 0x21, 0x20, 0x00, 0x00, 0x00, 0x70, 0x21,
+ 0xfe, 0xff, 0xff, 0xff, 0x0f, 0x21, 0x02, 0x00, 0x00, 0x00, 0x08, 0x21,
+ 0xfa, 0x01, 0x00, 0x80, 0x0b, 0x21, 0x02, 0x00, 0x00, 0x80, 0x0a, 0x21,
+ 0xba, 0x01, 0x00, 0x80, 0x0a, 0x21, 0x02, 0x00, 0x00, 0x80, 0x0b, 0x21,
+ 0x3a, 0x00, 0x00, 0x00, 0x08, 0x21, 0x02, 0x00, 0x00, 0x00, 0x08, 0x21,
+ 0x02, 0xc0, 0xfb, 0x03, 0x08, 0x21, 0x02, 0x00, 0x00, 0x00, 0x08, 0x3f,
+ 0x02, 0xc0, 0xbd, 0x0f, 0x08, 0x01, 0x02, 0x00, 0x00, 0x00, 0x08, 0x01,
+ 0x02, 0xc0, 0x7f, 0x7b, 0x08, 0x01, 0x02, 0x00, 0x00, 0x00, 0x08, 0x01,
+ 0x02, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00,
+ 0xfe, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/tk8.6/library/demos/images/noletter.xbm b/tk8.6/library/demos/images/noletter.xbm
new file mode 100644
index 0000000..5774124
--- /dev/null
+++ b/tk8.6/library/demos/images/noletter.xbm
@@ -0,0 +1,27 @@
+#define noletters_width 48
+#define noletters_height 48
+static char noletters_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00,
+ 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x07, 0x00,
+ 0x00, 0xf0, 0x0f, 0xe0, 0x1f, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x7f, 0x00,
+ 0x00, 0x3e, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x1f, 0x00, 0x00, 0xf0, 0x01,
+ 0x80, 0x07, 0x00, 0x00, 0xc0, 0x03, 0xc0, 0x03, 0x00, 0x00, 0xe0, 0x07,
+ 0xe0, 0x01, 0x00, 0x00, 0xf0, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x78, 0x0e,
+ 0xf0, 0x00, 0x00, 0x00, 0x3c, 0x1e, 0x70, 0x00, 0x00, 0x00, 0x1e, 0x1c,
+ 0x38, 0x00, 0x00, 0x00, 0x0f, 0x38, 0x38, 0x00, 0x00, 0x80, 0x07, 0x38,
+ 0x3c, 0xfc, 0xff, 0xff, 0x7f, 0x78, 0x1c, 0x04, 0x00, 0xe0, 0x41, 0x70,
+ 0x1c, 0x04, 0x00, 0xf0, 0x40, 0x70, 0x1c, 0x74, 0x00, 0x78, 0x4e, 0x70,
+ 0x0e, 0x04, 0x00, 0x3c, 0x4a, 0xe0, 0x0e, 0x74, 0x03, 0x1e, 0x4a, 0xe0,
+ 0x0e, 0x04, 0x00, 0x0f, 0x4e, 0xe0, 0x0e, 0x04, 0x80, 0x07, 0x40, 0xe0,
+ 0x0e, 0x04, 0xf8, 0x0f, 0x40, 0xe0, 0x0e, 0x04, 0xe0, 0x01, 0x40, 0xe0,
+ 0x0e, 0x04, 0xf8, 0x00, 0x40, 0xe0, 0x0e, 0x04, 0x78, 0x00, 0x40, 0xe0,
+ 0x0e, 0x04, 0xfc, 0xf3, 0x40, 0xe0, 0x1c, 0x04, 0x1e, 0x00, 0x40, 0x70,
+ 0x1c, 0x04, 0x0f, 0x00, 0x40, 0x70, 0x1c, 0x84, 0x07, 0x00, 0x40, 0x70,
+ 0x3c, 0xfc, 0xff, 0xff, 0x7f, 0x78, 0x38, 0xe0, 0x01, 0x00, 0x00, 0x38,
+ 0x38, 0xf0, 0x00, 0x00, 0x00, 0x38, 0x70, 0x78, 0x00, 0x00, 0x00, 0x1c,
+ 0xf0, 0x3c, 0x00, 0x00, 0x00, 0x1e, 0xe0, 0x1e, 0x00, 0x00, 0x00, 0x0e,
+ 0xe0, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x07, 0x00, 0x00, 0x80, 0x07,
+ 0x80, 0x07, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x1f, 0x00, 0x00, 0xf0, 0x01,
+ 0x00, 0x3e, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x7f, 0x00,
+ 0x00, 0xf0, 0x0f, 0xe0, 0x1f, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x07, 0x00,
+ 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00};
diff --git a/tk8.6/library/demos/images/ouster.png b/tk8.6/library/demos/images/ouster.png
new file mode 100644
index 0000000..259b8f9
--- /dev/null
+++ b/tk8.6/library/demos/images/ouster.png
Binary files differ
diff --git a/tk8.6/library/demos/images/pattern.xbm b/tk8.6/library/demos/images/pattern.xbm
new file mode 100644
index 0000000..df31baf
--- /dev/null
+++ b/tk8.6/library/demos/images/pattern.xbm
@@ -0,0 +1,6 @@
+#define foo_width 16
+#define foo_height 16
+static char foo_bits[] = {
+ 0x60, 0x06, 0x90, 0x09, 0x90, 0x09, 0xb0, 0x0d, 0x4e, 0x72, 0x49, 0x92,
+ 0x71, 0x8e, 0x8e, 0x71, 0x8e, 0x71, 0x71, 0x8e, 0x49, 0x92, 0x4e, 0x72,
+ 0xb0, 0x0d, 0x90, 0x09, 0x90, 0x09, 0x60, 0x06};
diff --git a/tk8.6/library/demos/images/tcllogo.gif b/tk8.6/library/demos/images/tcllogo.gif
new file mode 100644
index 0000000..4603d4f
--- /dev/null
+++ b/tk8.6/library/demos/images/tcllogo.gif
Binary files differ
diff --git a/tk8.6/library/demos/images/teapot.ppm b/tk8.6/library/demos/images/teapot.ppm
new file mode 100644
index 0000000..b8ab85f
--- /dev/null
+++ b/tk8.6/library/demos/images/teapot.ppm
@@ -0,0 +1,31 @@
+P6
+256 256
+255
+\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À[7 eOLjQLmSMoTMnSMlRMhPL_9 \À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀnSMtVMzYN~[N~[N\N\O€\O€]O€]O€]O€]O€\O€\O}[NyYNtVM\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀG-wXN}[N€]O„^O†_O†`O‡`Oˆ`Oˆ`OˆaO‰aO‰aO‰aO‰aO‰aO‰aOˆaOˆ`O†_Oƒ^O\N \À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀaMLyYN…_O‰aP‹bPcPŽcPŽdPŽdPdPdPdPdPdPdPdPeP‘eP’eP’eP‘ePdPcP…_OpUM\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀwXN…_OdP“fP•gQ–hQ˜hQ˜iQ™iQ™iQšiQšiQšjQ›jQ›jQœjQœjQœjQœjQœjQ›jQœjQ™iQ“fP‡`O\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀNCJiQL‹bP—hQkQ¡mR¤nR¥oR¥oR¥oR¥oR¥oR¥oR¦oR¦oR¦pR¨pS©qSªqS«rS¬rS«rS©qS¤oRœjQ€]O\KK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀfOLrUMcPŸlR©qS¯tS²uTµwT·xT¸xT¹yTºyT»zT»zU¼zU¼zU¼zU»zUºyT¸xT¶wT¯tS¡mR‰aOhPL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\Àa0 cNLqUM€\O”fQ¦pS²wVºzV¿|VÂ}VÄVÆVÇ€VÉ‚WÌ…[Õeæ w÷³‹êª…Ĉg§qT“fQ{ZNYIK9\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀO1{G#‘JkRMqUMtVN–iS¨v\·€d¹bµzZ±vU°uT®sSªqS¤nRœjQ’eP„^OrUMHh>!T4\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀG-V5wE"~I#†M%U+¥e7²l:°g2®b*­a(­`(©^(¥])¡^-›]1ŠS,qC$`9 R3G-\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À@)J/i>!pA"tD"wF$yH&xH&tE$wE#yG%}M+ƒT4S5mE*Z7!K/B*;'\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À‰aO¦oR½{UÇ€VÏ…X<(F-a: e<!h>!j@#k@$h>"d<!c=$hD-fF2[<)K0@);'5$Ë‚VÇ€V¿|U_LKYIK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À…_O·xTÉ‚Wó«€ûµ‹Ö’k¼|X×>µf-¨^(¡Z'šW&–T&œN>)F-J/b; g>#nD(jB&c<!b=%jH2_A/I0!<(8&5$”J¥Y’S%8&;'?)E,<:HA=HE?IJAISFJYIKXIK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À£nRÁ}UܘqÊŠe±vU²e,™V&¥V†C €@ |> y< u: r9 o7 l6
+j5
+h4
+g3
+5$D,K/b; h>"wM1tK.e="a<#cA,U8&E-<(9&.!a0 b1 c1    
+
++3#@)46G<:HMCIXHK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀU*´vT¿~X¸{YÃk+›W&‰N$|> u: p8 k5
+f3
+a0 _/ ]. [- I¡\*ª_(‘LkRMmSMmSMnSMnSMD,R3W5mA"|O0|P1j?"c<!a=%Y7"N1F,;'NCJNCJNDJODJODJODJh>!a: X/K%
+g3
+a0 Z- \/ T*Q(ŠHµm8kRMmSMnTMoTMpTMpUM15G15G05G04G04GpUMpTM5^9 d<!yF#O+€N,rC#qB"pB#k?"a: Z7 6ODJPDJPEJQEJQEJREJREJREJRFJSFJSFJSFJSFJe<!X/
+^/ V+Q(L&I$r9  TlRMnSM46G47G47G46G46G46G46G46G36G36G25G25G15G04G/4F.3F
+
+X&pUMuWMwXNxXN<:H<:H<:H<:H<;H<;H<;H<;H=;H=;H=;H=;H>;H>;H?<H@<HA=HC>HG@ILBIREJ[JKcNLjQL§pR±uTºzUÃ~VÈWË‚XÖŽcäsÒŽe¼{V²vT¨pSžkR•gQŒbP†_O‚^O]O€\O€\O€\O€\O€]O]O]O]O]O]O]O]O]O]O]O€\O€\O~\N}[N|ZNxXN•T%H$
+›W&rVMvWNyYNzYN|ZN}[N}[N><H?<H?<H?<H?<H?<H@<H@<H@<HA=HA=HB=HC>HE?IG@IIAIKBIODJSFJWHK—hQŸlR§pR°b(¾i*Én+Ù|7Û|6Ïr,Íq+Êp-Ãl+»g)±b(®sS§pS lRšiQ•gQePcPŠaPˆaO‡`O‡`O†_O†_O…_O…_O…_O…_O…_O…_O…_O„_O„^O„^Oƒ^Oƒ^O‚]O]O€\O~[N{ZN•T%
+
+ 
+@%<-$G?@…pfdNLuWM\NdNL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀTFJvWN‰aP./01„E}[N]O…_Oˆ`O‰aP‹bPŒbPcPcPŽcPdPdPdPeP‘eP’eP’eP“fP“fQ”fQ•gQ•gQ–gQ–hQ—hQ˜hQ™iQšiQ›jQœjQkQkRžlRŸlRžY&¤\'¨^'µ^½bÀcÃeÇi ÄgÀc½b¼a¹`µ^´]¯X¢[' Z'žY&¢mR¡mR¡mR lRŸlRŸlRžkRkQœkQœjQ›jQšjQšiQ™iQ™iQ˜iQ˜hQ—hQ—hQ—hQ–gQ–gQ•gQ•gQ•gQ”fQ”fQ“fQ“fP’eP‘ePdPcP‰aP—O
+ B\À\À\À\À\À\À\À\À\À\À%7!!C*F#P) {dYœze»p€\OgPL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀSFJ`LKvWNŠaPm6
+ 
+$5 ¬`(¶e)£nRœjQƒ^OJAI\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀXIK^KKdNLhPLuWM‚]OŒbP”fQeP m6
+†`OŽcP“fQ—hQ˜hQ™iQšiQšjQ›jQ›jQ›jQœjQœjQœjQœkQkQkQkRžkRžkRžkRžlRŸlRŸlRŸlR lR lR lR¡mR¡mR¡mR¡mRºg)³c(²c(±b(­V¿cÂeÅi!Åi!Àd¼bº`¹`·_·_¶^¢Q§]'ª_(­`(¹f)£nR£nR£nR£nR£nR£nR£nR¢nR¢nR¢nR¢nR¢nR¢nR¢mR¢mR¢mR¢mR¢mR¢mR¢mR¢mR¢mR¢nR¢mR¢mR£nR¢mR¢mR¡mR mRkR—hQˆGa0 ŠbP mRœjQ“fQ‰aP}[NrUMmSM…L$\À\À\À\À\À\À\À\À B B #C, 8&H.Z7 §pR›jQ{ZN\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀQEJ[JK`LKdNLhQLqUM{ZN…_OŽcP–gQ—hQ
+‹bP‘eP–hQšiQ›jQœjQkQkQkRžkRžkRžlRžlRŸlRŸlRŸlRŸlRŸlR lR lR lR mR¡mR¡mR¡mR¡mR¡mR¢mR¢mR¢mR¢nR£nRÀj*ºg)·e)¶d)Âd°XÅgÅhÂe¿c½b½b¾bªU­`(®a(¯a(³c(¾i*¤oR¤oR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤oR¤oR¥oR¥oR¥oR¥oR¥oR¥oR¦oR¦oR¥oR¥oR¤nR¡mR›jQŽQ%Z- œjQ£nRŸlR—hQŽdP…_OuWMpTMnSMkRLa: \À\À\À\À\À\À\À B B&D2 @*S6#G@IPDJ˜hQmSM\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀVGJ]KKbMLeOLiQLlRMvWN\OˆaO‘eP—hQœjQ•gQ
+!C+E'0F.4F7%8%U/lG.SFJZIK]KKZIKB=H\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀREJZJK`LKdNLgPLjQLlRMnSMpTMqUMtWMxXN{ZN~[N]O„^O†`O‰aO‹bPdP•gQ™iQœkQ lR¤nR§pSªrS­sS¯tT²uT´vT¶wT·xT¹yT¹yTºyTºyT¹yT¶xT´vT¬rS¢nR—hQ¿|U¿|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ}UÀ}UÁ}UÁ}UÁ}UÁ}UÂ}UÂ~UÃ~UÃ~VÃ~VÄVÅ€WÆX®a(ŸlRªrS´vT¸yT¼zU¾|UÁ~VÃXÆ‚[Ɇ_΋dÓ‘jÔ“mÔ“nБlÊŒhĆd½_¶{[°vWªsU¦pS¢nRžkRšiQ˜hQ•gQ“fQ‘ePdPŒbP‰aO†_Oƒ^O€\O|ZNxXNsVMpTMnTMmSMjQL€C B)D&/F-3F47G6%>" Y7 kA$YIK]KK^KKSFJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀVGJ\KKbMLeOLhPLkRLmSMnTMpTMrUMuWNyYN|ZN\N‚]O„_O‡`OŠaPŒbPŽcPeP“fP—hQ›jQžlR¢nR¥oS©qT¬sT¯uU²vU´wV¶xV¸yV¹yUºzU»zU¼{U½{U¾{U¾|U¿|U¿|U¿|U¿|U¾{U½{U¼{U¼zU»zTºyT¹yT¸xTµwT³vT´vT´vT´vT´wT´wTµwT·xT¹yTºzT¼zU½{U¾{U¿|UÀ|UÂ}UÄVÅ€WÇ‚YÉ„\͈_ÑŒdÙ”láuç£|쩂ſt명æ¦ÞŸ{Õ—sËŽl†d¹^³yZ­uW¨qU¤oSŸlRžkRœjQšiQ˜hQ–gQ”fQ‘ePdPcPŠaP‡`O„^O]O}[NyYNuWMpTMoTMmSMkRLgPL&D#.E,3F46G;'<(D"iB(VGJ]KK`LK[JKB>H\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀNCJYIK^LKcNLfOLiQLkRMmSMoTMqUMsVMvXNzYN}[N€\O‚^O…_Oˆ`OŠaPŒcPdP‘eP“fQ•gQ—hQ™iQkR mS¤oT¨rU¬tW°wY´zZ¸}\»]¾€^À^Á‚^‚^Â\Á€ZÁYÁXÁ~WÁ~WÂ~VÂ~VÂ~VÃ~VÃ~UÃ~UÄ~UÄ~UÄUÄUÅVÅVÅVÅVÆVÆ€VÆ€VÇ€WÇWÈ‚XɃZË…[͇^ЊaÓdØ’iÜ—nâtè£zî©ó¯‡ø´û¸‘üº“û¹“÷¶ñ±Œé©…à¡~Ö˜vËmÇf»€`´z[®vX©rU¥pT£oS¢nS lRžkRœkRšjQ˜iQ–hQ”fQ’ePdPcP‹bPˆ`O…_O‚]O~[NzYNvWNpTMoTMnSMkRMhQLo7 ,2F36G99HC+@ ]8 nA"\JK`ML_LKSFJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀSFJ[JK`LKdNLgPLjQLlRMnSMpTMqUMtVMwXNzZN}[N€]Oƒ^O†_OˆaO‹bPcPdP‘eP“fQ•gQ—hQ™iQ›jRžlR mS£oU§rW¬vZ²{]¹€a¿…fÅŠjËnГqÓ•sÕ–sÕ–rÕ–qÕ”oÓ’mÑjÏgÍŠcˈaɆ^È„\Ç‚[ÆYÅ€XÅ€WÅWÅWÅVÅVÅWÅ€WÆ€WÇXÈ‚YɃ[Ê…\͇_ÏŠaÒeÕ‘hÙ•mÝ™qávä¡zç¤}꧀멃몄騃奀ߠ|Ù›wÓ•rÌmƉh¿„c¸~^²yZ®vX¬tWªsV¨qU¦pT¤oS¢nS mRžlRœkR›jQ™iQ—hQ•gQ“fPePŽcP‹bPˆaO…_O‚^O\N{ZNwXNsVMoTMnSMlRMiQL~I#26G99G?<HA*E$ i@$ZIKaMLbML[JK;:H\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀWHJ]KKbMLeOLhPLjRLlSMnTMpTMrUMuWMxXN{ZN~\N]O„^O†`O‰aO‹bPŽcPdP’eP”fQ–gQ˜hQšiQœkRžlS mT£oU¦rWªuZ¯y]´~aºƒfŠlË’sÔšzÜ¡€ã§†è«‰ë®‹í¯Œí®‹ë¬ˆè¨„ã£~ßžyÚ™tÖ•oÒjÎŒfˈbÈ…_ƃ\ÅZÄ€YÃXÂWÂ~WÂ~WÂ~WÃXÀXÄ€YÅZƃ\Ç…^Ɇ`ˈbÌŠdÍ‹fÎgÎŽiÎŽjÎŽjÍŽjËŒiljgÆd¿ƒaº^¸}]¶|\´{[²yZ°xY®vX¬tWªsV¨qU¦pT¤oS¢nS mRžlRkR›jQ™iQ—hQ•gQ“fP‘ePŽdPŒbP‰aO†_Oƒ^O€\O|ZNxXNtVMpTMnSMmSMjQLgPL99G?<HG-E&b;!YIK`MLdOM`LKNCJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀŸlRºyTÄ~UÊ‚XʃYÄXº{W­tUšW'¢[(—hQ lRcP€\OhQL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀNCJYIK^LKcNLfOLiQLkRLmSMoTMqUMrVMvWNyYN|ZN\N‚]O„_O‡`O‰aPŒbPŽcPdP’fP”gQ–hQ˜iQšjRœkRžlS¡nT¤pU§sW«vZ°z]µb»„gŠlÉ‘sИyØžÞ¤…ã©Šè­ì±ï³‘ﳑ뭊穅⣀ݞzؘtÒ“nÎiɉdÆ…`Â]Á€[¿~Y¾}X½|W½|V¼{V¼{V¼{V¼{V¼{V¼|W¼|W½}X½}Y½~Z½~Z¼~Z»}[º}[º}[º~\º~\º~]º~]¹~]¸~]·}]¶|\´z[²yZ°wY®vX¬tWªsV¨rU¦pT¤oS¢nS mRŸlRkR›jQšiQ˜hQ–gQ“fQ‘ePdPŒcPŠaP‡`O„^O]O}[NyYNuWNpTMnTMmSMkRLhPL|H$D>IQ2P+XHK_LLfQOcNLXIK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À©qSºyTÃ~VΈ`遲ޜv¾€]ªqS–LŽG|> g3
+S)?*%.—hQ—hQ‘eP‡`OuWM\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀSFJ[JK`LKdNLgPLjQLlRMnSMoTMqUMsVMwXNzYN}[N€\O‚^O…_O‡`OŠaPŒbPŽdP‘eP“fP•gQ—hQ˜iQšjRœkRŸlS¡nT¤pV§sX«vZ°z^¶b¼…gËmÊ’sјzØŸ€Þ¤…ã©Šè­ê¯ë°ê¯Žè¬‹å¨‡à¤‚Ûž|Ö™wÑ“qÌŽlljgÃ…bÀ‚_½\»}Zº{X¹zW¸yV·yU·xU·xU·xT·xT·xU·xU·xU·yV·yV·yW¸zW¸{X¹{Y¹|Zº}[º}[º}\º~\¹~]¹~]¸}]·|\µ{\´z[²yZ°wY®vX¬tWªsV¨rU¦pT¤oS¢nS¡mRŸlRkRœjQšiQ˜hQ–gQ”fQ’ePdPcPŠbP‡`O…_O‚]O~[NzZNvWNrUMoTMmSMlRMiQLeOLJAIJ(h>!]KKfQOgQN_LKD>I\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À™iQ°tS¸yT¼{UÂYÎŒeï­ˆô´Õ—u¶|\ Z'™LˆD |>
+
+ &3#.$-% .% .& /&!,#,#@70A71XNHXNHWNHWNHZRLYQLYQLXQLWQLWPLUOLSNLQMKOLJMJJ0//.-.,,-&(+"(!'
+ %' %$#" ! !$ 
diff --git a/tk8.6/library/demos/items.tcl b/tk8.6/library/demos/items.tcl
new file mode 100644
index 0000000..000e4cb
--- /dev/null
+++ b/tk8.6/library/demos/items.tcl
@@ -0,0 +1,291 @@
+# items.tcl --
+#
+# This demonstration script creates a canvas that displays the
+# canvas item types.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .items
+catch {destroy $w}
+toplevel $w
+wm title $w "Canvas Item Demonstration"
+wm iconname $w "Items"
+positionWindow $w
+set c $w.frame.c
+
+label $w.msg -font $font -wraplength 5i -justify left -text "This window contains a canvas widget with examples of the various kinds of items supported by canvases. The following operations are supported:\n Button-1 drag:\tmoves item under pointer.\n Button-2 drag:\trepositions view.\n Button-3 drag:\tstrokes out area.\n Ctrl+f:\t\tprints items under area."
+pack $w.msg -side top
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+frame $w.frame
+pack $w.frame -side top -fill both -expand yes
+
+canvas $c -scrollregion {0c 0c 30c 24c} -width 15c -height 10c \
+ -relief sunken -borderwidth 2 \
+ -xscrollcommand "$w.frame.hscroll set" \
+ -yscrollcommand "$w.frame.vscroll set"
+ttk::scrollbar $w.frame.vscroll -command "$c yview"
+ttk::scrollbar $w.frame.hscroll -orient horiz -command "$c xview"
+
+grid $c -in $w.frame \
+ -row 0 -column 0 -rowspan 1 -columnspan 1 -sticky news
+grid $w.frame.vscroll \
+ -row 0 -column 1 -rowspan 1 -columnspan 1 -sticky news
+grid $w.frame.hscroll \
+ -row 1 -column 0 -rowspan 1 -columnspan 1 -sticky news
+grid rowconfig $w.frame 0 -weight 1 -minsize 0
+grid columnconfig $w.frame 0 -weight 1 -minsize 0
+
+# Display a 3x3 rectangular grid.
+
+$c create rect 0c 0c 30c 24c -width 2
+$c create line 0c 8c 30c 8c -width 2
+$c create line 0c 16c 30c 16c -width 2
+$c create line 10c 0c 10c 24c -width 2
+$c create line 20c 0c 20c 24c -width 2
+
+set font1 {Helvetica 12}
+set font2 {Helvetica 24 bold}
+if {[winfo depth $c] > 1} {
+ set blue DeepSkyBlue3
+ set red red
+ set bisque bisque3
+ set green SeaGreen3
+} else {
+ set blue black
+ set red black
+ set bisque black
+ set green black
+}
+
+# Set up demos within each of the areas of the grid.
+
+$c create text 5c .2c -text Lines -anchor n
+$c create line 1c 1c 3c 1c 1c 4c 3c 4c -width 2m -fill $blue \
+ -cap butt -join miter -tags item
+$c create line 4.67c 1c 4.67c 4c -arrow last -tags item
+$c create line 6.33c 1c 6.33c 4c -arrow both -tags item
+$c create line 5c 6c 9c 6c 9c 1c 8c 1c 8c 4.8c 8.8c 4.8c 8.8c 1.2c \
+ 8.2c 1.2c 8.2c 4.6c 8.6c 4.6c 8.6c 1.4c 8.4c 1.4c 8.4c 4.4c \
+ -width 3 -fill $red -tags item
+# Main widget program sets variable tk_demoDirectory
+$c create line 1c 5c 7c 5c 7c 7c 9c 7c -width .5c \
+ -stipple @[file join $tk_demoDirectory images gray25.xbm] \
+ -arrow both -arrowshape {15 15 7} -tags item
+$c create line 1c 7c 1.75c 5.8c 2.5c 7c 3.25c 5.8c 4c 7c -width .5c \
+ -cap round -join round -tags item
+
+$c create text 15c .2c -text "Curves (smoothed lines)" -anchor n
+$c create line 11c 4c 11.5c 1c 13.5c 1c 14c 4c -smooth on \
+ -fill $blue -tags item
+$c create line 15.5c 1c 19.5c 1.5c 15.5c 4.5c 19.5c 4c -smooth on \
+ -arrow both -width 3 -tags item
+$c create line 12c 6c 13.5c 4.5c 16.5c 7.5c 18c 6c \
+ 16.5c 4.5c 13.5c 7.5c 12c 6c -smooth on -width 3m -cap round \
+ -stipple @[file join $tk_demoDirectory images gray25.xbm] \
+ -fill $red -tags item
+
+$c create text 25c .2c -text Polygons -anchor n
+$c create polygon 21c 1.0c 22.5c 1.75c 24c 1.0c 23.25c 2.5c \
+ 24c 4.0c 22.5c 3.25c 21c 4.0c 21.75c 2.5c -fill $green \
+ -outline black -width 4 -tags item
+$c create polygon 25c 4c 25c 4c 25c 1c 26c 1c 27c 4c 28c 1c \
+ 29c 1c 29c 4c 29c 4c -fill $red -smooth on -tags item
+$c create polygon 22c 4.5c 25c 4.5c 25c 6.75c 28c 6.75c \
+ 28c 5.25c 24c 5.25c 24c 6.0c 26c 6c 26c 7.5c 22c 7.5c \
+ -stipple @[file join $tk_demoDirectory images gray25.xbm] \
+ -outline black -tags item
+
+$c create text 5c 8.2c -text Rectangles -anchor n
+$c create rectangle 1c 9.5c 4c 12.5c -outline $red -width 3m -tags item
+$c create rectangle 0.5c 13.5c 4.5c 15.5c -fill $green -tags item
+$c create rectangle 6c 10c 9c 15c -outline {} \
+ -stipple @[file join $tk_demoDirectory images gray25.xbm] \
+ -fill $blue -tags item
+
+$c create text 15c 8.2c -text Ovals -anchor n
+$c create oval 11c 9.5c 14c 12.5c -outline $red -width 3m -tags item
+$c create oval 10.5c 13.5c 14.5c 15.5c -fill $green -tags item
+$c create oval 16c 10c 19c 15c -outline {} \
+ -stipple @[file join $tk_demoDirectory images gray25.xbm] \
+ -fill $blue -tags item
+
+$c create text 25c 8.2c -text Text -anchor n
+$c create rectangle 22.4c 8.9c 22.6c 9.1c
+$c create text 22.5c 9c -anchor n -font $font1 -width 4c \
+ -text "A short string of text, word-wrapped, justified left, and anchored north (at the top). The rectangles show the anchor points for each piece of text." -tags item
+$c create rectangle 25.4c 10.9c 25.6c 11.1c
+$c create text 25.5c 11c -anchor w -font $font1 -fill $blue \
+ -text "Several lines,\n each centered\nindividually,\nand all anchored\nat the left edge." \
+ -justify center -tags item
+$c create rectangle 24.9c 13.9c 25.1c 14.1c
+$c create text 25c 14c -font $font2 -anchor c -fill $red -angle 15 \
+ -text "Angled characters" -tags item
+
+$c create text 5c 16.2c -text Arcs -anchor n
+$c create arc 0.5c 17c 7c 20c -fill $green -outline black \
+ -start 45 -extent 270 -style pieslice -tags item
+$c create arc 6.5c 17c 9.5c 20c -width 4m -style arc \
+ -outline $blue -start -135 -extent 270 -tags item \
+ -outlinestipple @[file join $tk_demoDirectory images gray25.xbm]
+$c create arc 0.5c 20c 9.5c 24c -width 4m -style pieslice \
+ -fill {} -outline $red -start 225 -extent -90 -tags item
+$c create arc 5.5c 20.5c 9.5c 23.5c -width 4m -style chord \
+ -fill $blue -outline {} -start 45 -extent 270 -tags item
+
+image create photo items.ousterhout \
+ -file [file join $tk_demoDirectory images ouster.png]
+image create photo items.ousterhout.active -format "png -alpha 0.5" \
+ -file [file join $tk_demoDirectory images ouster.png]
+$c create text 15c 16.2c -text "Bitmaps and Images" -anchor n
+$c create image 13c 20c -tags item -image items.ousterhout \
+ -activeimage items.ousterhout.active
+$c create bitmap 17c 18.5c -tags item \
+ -bitmap @[file join $tk_demoDirectory images noletter.xbm]
+$c create bitmap 17c 21.5c -tags item \
+ -bitmap @[file join $tk_demoDirectory images letters.xbm]
+
+$c create text 25c 16.2c -text Windows -anchor n
+button $c.button -text "Press Me" -command "butPress $c $red"
+$c create window 21c 18c -window $c.button -anchor nw -tags item
+entry $c.entry -width 20 -relief sunken
+$c.entry insert end "Edit this text"
+$c create window 21c 21c -window $c.entry -anchor nw -tags item
+scale $c.scale -from 0 -to 100 -length 6c -sliderlength .4c \
+ -width .5c -tickinterval 0
+$c create window 28.5c 17.5c -window $c.scale -anchor n -tags item
+$c create text 21c 17.9c -text Button: -anchor sw
+$c create text 21c 20.9c -text Entry: -anchor sw
+$c create text 28.5c 17.4c -text Scale: -anchor s
+
+# Set up event bindings for canvas:
+
+$c bind item <Any-Enter> "itemEnter $c"
+$c bind item <Any-Leave> "itemLeave $c"
+bind $c <2> "$c scan mark %x %y"
+bind $c <B2-Motion> "$c scan dragto %x %y"
+bind $c <3> "itemMark $c %x %y"
+bind $c <B3-Motion> "itemStroke $c %x %y"
+bind $c <<NextChar>> "itemsUnderArea $c"
+bind $c <1> "itemStartDrag $c %x %y"
+bind $c <B1-Motion> "itemDrag $c %x %y"
+
+# Utility procedures for highlighting the item under the pointer:
+
+proc itemEnter {c} {
+ global restoreCmd
+
+ if {[winfo depth $c] == 1} {
+ set restoreCmd {}
+ return
+ }
+ set type [$c type current]
+ if {$type == "window" || $type == "image"} {
+ set restoreCmd {}
+ return
+ } elseif {$type == "bitmap"} {
+ set bg [lindex [$c itemconf current -background] 4]
+ set restoreCmd [list $c itemconfig current -background $bg]
+ $c itemconfig current -background SteelBlue2
+ return
+ } elseif {$type == "image"} {
+ set restoreCmd [list $c itemconfig current -state normal]
+ $c itemconfig current -state active
+ return
+ }
+ set fill [lindex [$c itemconfig current -fill] 4]
+ if {(($type == "rectangle") || ($type == "oval") || ($type == "arc"))
+ && ($fill == "")} {
+ set outline [lindex [$c itemconfig current -outline] 4]
+ set restoreCmd "$c itemconfig current -outline $outline"
+ $c itemconfig current -outline SteelBlue2
+ } else {
+ set restoreCmd "$c itemconfig current -fill $fill"
+ $c itemconfig current -fill SteelBlue2
+ }
+}
+
+proc itemLeave {c} {
+ global restoreCmd
+
+ eval $restoreCmd
+}
+
+# Utility procedures for stroking out a rectangle and printing what's
+# underneath the rectangle's area.
+
+proc itemMark {c x y} {
+ global areaX1 areaY1
+ set areaX1 [$c canvasx $x]
+ set areaY1 [$c canvasy $y]
+ $c delete area
+}
+
+proc itemStroke {c x y} {
+ global areaX1 areaY1 areaX2 areaY2
+ set x [$c canvasx $x]
+ set y [$c canvasy $y]
+ if {($areaX1 != $x) && ($areaY1 != $y)} {
+ $c delete area
+ $c addtag area withtag [$c create rect $areaX1 $areaY1 $x $y \
+ -outline black]
+ set areaX2 $x
+ set areaY2 $y
+ }
+}
+
+proc itemsUnderArea {c} {
+ global areaX1 areaY1 areaX2 areaY2
+ set area [$c find withtag area]
+ set items ""
+ foreach i [$c find enclosed $areaX1 $areaY1 $areaX2 $areaY2] {
+ if {[lsearch [$c gettags $i] item] != -1} {
+ lappend items $i
+ }
+ }
+ puts stdout "Items enclosed by area: $items"
+ set items ""
+ foreach i [$c find overlapping $areaX1 $areaY1 $areaX2 $areaY2] {
+ if {[lsearch [$c gettags $i] item] != -1} {
+ lappend items $i
+ }
+ }
+ puts stdout "Items overlapping area: $items"
+}
+
+set areaX1 0
+set areaY1 0
+set areaX2 0
+set areaY2 0
+
+# Utility procedures to support dragging of items.
+
+proc itemStartDrag {c x y} {
+ global lastX lastY
+ set lastX [$c canvasx $x]
+ set lastY [$c canvasy $y]
+}
+
+proc itemDrag {c x y} {
+ global lastX lastY
+ set x [$c canvasx $x]
+ set y [$c canvasy $y]
+ $c move current [expr {$x-$lastX}] [expr {$y-$lastY}]
+ set lastX $x
+ set lastY $y
+}
+
+# Procedure that's invoked when the button embedded in the canvas
+# is invoked.
+
+proc butPress {w color} {
+ set i [$w create text 25c 18.1c -text "Oooohhh!!" -fill $color -anchor n]
+ after 500 "$w delete $i"
+}
diff --git a/tk8.6/library/demos/ixset b/tk8.6/library/demos/ixset
new file mode 100644
index 0000000..13235de
--- /dev/null
+++ b/tk8.6/library/demos/ixset
@@ -0,0 +1,328 @@
+#!/bin/sh
+# the next line restarts using wish \
+exec wish "$0" ${1+"$@"}
+
+# ixset --
+# A nice interface to "xset" to change X server settings
+#
+# History :
+# 91/11/23 : pda@masi.ibp.fr, jt@ratp.fr : design
+# 92/08/01 : pda@masi.ibp.fr : cleaning
+
+package require Tk
+
+#
+# Button actions
+#
+
+proc quit {} {
+ destroy .
+}
+
+proc ok {} {
+ writesettings
+ quit
+}
+
+proc cancel {} {
+ readsettings
+ dispsettings
+ .buttons.apply configure -state disabled
+ .buttons.cancel configure -state disabled
+}
+
+proc apply {} {
+ writesettings
+ .buttons.apply configure -state disabled
+ .buttons.cancel configure -state disabled
+}
+
+#
+# Read current settings
+#
+
+proc readsettings {} {
+ global kbdrep ; set kbdrep "on"
+ global kbdcli ; set kbdcli 0
+ global bellvol ; set bellvol 100
+ global bellpit ; set bellpit 440
+ global belldur ; set belldur 100
+ global mouseacc ; set mouseacc "3/1"
+ global mousethr ; set mousethr 4
+ global screenbla ; set screenbla "blank"
+ global screentim ; set screentim 600
+ global screencyc ; set screencyc 600
+
+ set xfd [open "|xset q" r]
+ while {[gets $xfd line] > -1} {
+ switch -- [lindex $line 0] {
+ auto {
+ set rpt [lindex $line 1]
+ if {$rpt eq "repeat:"} {
+ set kbdrep [lindex $line 2]
+ set kbdcli [lindex $line 6]
+ }
+ }
+ bell {
+ set bellvol [lindex $line 2]
+ set bellpit [lindex $line 5]
+ set belldur [lindex $line 8]
+ }
+ acceleration: {
+ set mouseacc [lindex $line 1]
+ set mousethr [lindex $line 3]
+ }
+ prefer {
+ set bla [lindex $line 2]
+ set screenbla [expr {$bla eq "yes" ? "blank" : "noblank"}]
+ }
+ timeout: {
+ set screentim [lindex $line 1]
+ set screencyc [lindex $line 3]
+ }
+ }
+ }
+ close $xfd
+
+ # puts stdout [format "Key REPEAT = %s\n" $kbdrep]
+ # puts stdout [format "Key CLICK = %s\n" $kbdcli]
+ # puts stdout [format "Bell VOLUME = %s\n" $bellvol]
+ # puts stdout [format "Bell PITCH = %s\n" $bellpit]
+ # puts stdout [format "Bell DURATION = %s\n" $belldur]
+ # puts stdout [format "Mouse ACCELERATION = %s\n" $mouseacc]
+ # puts stdout [format "Mouse THRESHOLD = %s\n" $mousethr]
+ # puts stdout [format "Screen BLANCK = %s\n" $screenbla]
+ # puts stdout [format "Screen TIMEOUT = %s\n" $screentim]
+ # puts stdout [format "Screen CYCLE = %s\n" $screencyc]
+}
+
+
+#
+# Write settings into the X server
+#
+
+proc writesettings {} {
+ global kbdrep kbdcli bellvol bellpit belldur
+ global mouseacc mousethr screenbla screentim screencyc
+
+ set bellvol [.bell.vol get]
+ set bellpit [.bell.val.pit.entry get]
+ set belldur [.bell.val.dur.entry get]
+
+ if {$kbdrep eq "on"} {
+ set kbdcli [.kbd.val.cli get]
+ } else {
+ set kbdcli "off"
+ }
+
+ set mouseacc [.mouse.hor.acc.entry get]
+ set mousethr [.mouse.hor.thr.entry get]
+
+ set screentim [.screen.tim.entry get]
+ set screencyc [.screen.cyc.entry get]
+
+ exec xset \
+ b $bellvol $bellpit $belldur \
+ c $kbdcli \
+ r $kbdrep \
+ m $mouseacc $mousethr \
+ s $screentim $screencyc \
+ s $screenbla
+}
+
+
+#
+# Sends all settings to the window
+#
+
+proc dispsettings {} {
+ global kbdrep kbdcli bellvol bellpit belldur
+ global mouseacc mousethr screenbla screentim screencyc
+
+ .bell.vol set $bellvol
+ .bell.val.pit.entry delete 0 end
+ .bell.val.pit.entry insert 0 $bellpit
+ .bell.val.dur.entry delete 0 end
+ .bell.val.dur.entry insert 0 $belldur
+
+ .kbd.val.onoff [expr {$kbdrep eq "on" ? "select" : "deselect"}]
+ .kbd.val.cli set $kbdcli
+
+ .mouse.hor.acc.entry delete 0 end
+ .mouse.hor.acc.entry insert 0 $mouseacc
+ .mouse.hor.thr.entry delete 0 end
+ .mouse.hor.thr.entry insert 0 $mousethr
+
+ .screen.blank [expr {$screenbla eq "blank" ? "select" : "deselect"}]
+ .screen.pat [expr {$screenbla ne "blank" ? "select" : "deselect"}]
+ .screen.tim.entry delete 0 end
+ .screen.tim.entry insert 0 $screentim
+ .screen.cyc.entry delete 0 end
+ .screen.cyc.entry insert 0 $screencyc
+}
+
+
+#
+# Create all windows, and pack them
+#
+
+proc labelentry {path text length {range {}}} {
+ frame $path
+ label $path.label -text $text
+ if {[llength $range]} {
+ spinbox $path.entry -width $length -relief sunken \
+ -from [lindex $range 0] -to [lindex $range 1]
+ } else {
+ entry $path.entry -width $length -relief sunken
+ }
+ pack $path.label -side left
+ pack $path.entry -side right -expand y -fill x
+}
+
+proc createwindows {} {
+ #
+ # Buttons
+ #
+
+ frame .buttons
+ button .buttons.ok -default active -command ok -text "Ok"
+ button .buttons.apply -default normal -command apply -text "Apply" \
+ -state disabled
+ button .buttons.cancel -default normal -command cancel -text "Cancel" \
+ -state disabled
+ button .buttons.quit -default normal -command quit -text "Quit"
+
+ pack .buttons.ok .buttons.apply .buttons.cancel .buttons.quit \
+ -side left -expand yes -pady 5
+
+ bind . <Return> {.buttons.ok flash; .buttons.ok invoke}
+ bind . <Escape> {.buttons.quit flash; .buttons.quit invoke}
+ bind . <1> {
+ if {![string match .buttons* %W]} {
+ .buttons.apply configure -state normal
+ .buttons.cancel configure -state normal
+ }
+ }
+ bind . <Key> {
+ if {![string match .buttons* %W]} {
+ switch -glob %K {
+ Return - Escape - Tab - *Shift* {}
+ default {
+ .buttons.apply configure -state normal
+ .buttons.cancel configure -state normal
+ }
+ }
+ }
+ }
+
+ #
+ # Bell settings
+ #
+
+ labelframe .bell -text "Bell Settings" -padx 1.5m -pady 1.5m
+ scale .bell.vol \
+ -from 0 -to 100 -length 200 -tickinterval 20 \
+ -label "Volume (%)" -orient horizontal
+
+ frame .bell.val
+ labelentry .bell.val.pit "Pitch (Hz)" 6 {25 20000}
+ labelentry .bell.val.dur "Duration (ms)" 6 {1 10000}
+ pack .bell.val.pit -side left -padx 5
+ pack .bell.val.dur -side right -padx 5
+ pack .bell.vol .bell.val -side top -expand yes
+
+ #
+ # Keyboard settings
+ #
+
+ labelframe .kbd -text "Keyboard Repeat Settings" -padx 1.5m -pady 1.5m
+
+ frame .kbd.val
+ checkbutton .kbd.val.onoff \
+ -text "On" \
+ -onvalue "on" -offvalue "off" -variable kbdrep \
+ -relief flat
+ scale .kbd.val.cli \
+ -from 0 -to 100 -length 200 -tickinterval 20 \
+ -label "Click Volume (%)" -orient horizontal
+ pack .kbd.val.onoff -side left -fill x -expand yes -padx {0 1m}
+ pack .kbd.val.cli -side left -expand yes -fill x -padx {1m 0}
+
+ pack .kbd.val -side top -expand yes -pady 2 -fill x
+
+ #
+ # Mouse settings
+ #
+
+ labelframe .mouse -text "Mouse Settings" -padx 1.5m -pady 1.5m
+
+ frame .mouse.hor
+ labelentry .mouse.hor.acc "Acceleration" 5
+ labelentry .mouse.hor.thr "Threshold (pixels)" 3 {1 2000}
+
+ pack .mouse.hor.acc -side left -padx {0 1m}
+ pack .mouse.hor.thr -side right -padx {1m 0}
+
+ pack .mouse.hor -side top -expand yes
+
+ #
+ # Screen Saver settings
+ #
+
+ labelframe .screen -text "Screen-saver Settings" -padx 1.5m -pady 1.5m
+
+ radiobutton .screen.blank \
+ -variable screenblank -text "Blank" -relief flat \
+ -value "blank" -variable screenbla -anchor w
+ radiobutton .screen.pat \
+ -variable screenblank -text "Pattern" -relief flat \
+ -value "noblank" -variable screenbla -anchor w
+ labelentry .screen.tim "Timeout (s)" 5 {1 100000}
+ labelentry .screen.cyc "Cycle (s)" 5 {1 100000}
+
+ grid .screen.blank .screen.tim -sticky e
+ grid .screen.pat .screen.cyc -sticky e
+ grid configure .screen.blank .screen.pat -sticky ew
+
+ #
+ # Main window
+ #
+
+ pack .buttons -side top -fill both
+ pack .bell .kbd .mouse .screen -side top -fill both -expand yes \
+ -padx 1m -pady 1m
+
+ #
+ # Let the user resize our window
+ #
+ wm minsize . 10 10
+}
+
+##############################################################################
+# Main program
+
+#
+# Listen what "xset" tells us...
+#
+
+readsettings
+
+#
+# Create all windows
+#
+
+createwindows
+
+#
+# Write xset parameters
+#
+
+dispsettings
+
+#
+# Now, wait for user actions...
+#
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tk8.6/library/demos/knightstour.tcl b/tk8.6/library/demos/knightstour.tcl
new file mode 100644
index 0000000..6113db2
--- /dev/null
+++ b/tk8.6/library/demos/knightstour.tcl
@@ -0,0 +1,268 @@
+# Copyright (C) 2008 Pat Thoyts <patthoyts@users.sourceforge.net>
+#
+# Calculate a Knight's tour of a chessboard.
+#
+# This uses Warnsdorff's rule to calculate the next square each
+# time. This specifies that the next square should be the one that
+# has the least number of available moves.
+#
+# Using this rule it is possible to get to a position where
+# there are no squares available to move into. In this implementation
+# this occurs when the starting square is d6.
+#
+# To solve this fault an enhancement to the rule is that if we
+# have a choice of squares with an equal score, we should choose
+# the one nearest the edge of the board.
+#
+# If the call to the Edgemost function is commented out you can see
+# this occur.
+#
+# You can drag the knight to a specific square to start if you wish.
+# If you let it repeat then it will choose random start positions
+# for each new tour.
+
+package require Tk 8.5
+
+# Return a list of accessible squares from a given square
+proc ValidMoves {square} {
+ set moves {}
+ foreach pair {{-1 -2} {-2 -1} {-2 1} {-1 2} {1 2} {2 1} {2 -1} {1 -2}} {
+ set col [expr {($square % 8) + [lindex $pair 0]}]
+ set row [expr {($square / 8) + [lindex $pair 1]}]
+ if {$row > -1 && $row < 8 && $col > -1 && $col < 8} {
+ lappend moves [expr {$row * 8 + $col}]
+ }
+ }
+ return $moves
+}
+
+# Return the number of available moves for this square
+proc CheckSquare {square} {
+ variable visited
+ set moves 0
+ foreach test [ValidMoves $square] {
+ if {[lsearch -exact -integer $visited $test] == -1} {
+ incr moves
+ }
+ }
+ return $moves
+}
+
+# Select the next square to move to. Returns -1 if there are no available
+# squares remaining that we can move to.
+proc Next {square} {
+ variable visited
+ set minimum 9
+ set nextSquare -1
+ foreach testSquare [ValidMoves $square] {
+ if {[lsearch -exact -integer $visited $testSquare] == -1} {
+ set count [CheckSquare $testSquare]
+ if {$count < $minimum} {
+ set minimum $count
+ set nextSquare $testSquare
+ } elseif {$count == $minimum} {
+ # to remove the enhancement to Warnsdorff's rule
+ # remove the next line:
+ set nextSquare [Edgemost $nextSquare $testSquare]
+ }
+ }
+ }
+ return $nextSquare
+}
+
+# Select the square nearest the edge of the board
+proc Edgemost {a b} {
+ set colA [expr {3-int(abs(3.5-($a%8)))}]
+ set colB [expr {3-int(abs(3.5-($b%8)))}]
+ set rowA [expr {3-int(abs(3.5-($a/8)))}]
+ set rowB [expr {3-int(abs(3.5-($b/8)))}]
+ return [expr {($colA * $rowA) < ($colB * $rowB) ? $a : $b}]
+}
+
+# Display a square number as a standard chess square notation.
+proc N {square} {
+ return [format %c%d [expr {97 + $square % 8}] \
+ [expr {$square / 8 + 1}]]
+}
+
+# Perform a Knight's move and schedule the next move.
+proc MovePiece {dlg last square} {
+ variable visited
+ variable delay
+ variable continuous
+ $dlg.f.txt insert end "[llength $visited]. [N $last] .. [N $square]\n" {}
+ $dlg.f.txt see end
+ $dlg.f.c itemconfigure [expr {1+$last}] -state normal -outline black
+ $dlg.f.c itemconfigure [expr {1+$square}] -state normal -outline red
+ $dlg.f.c moveto knight {*}[lrange [$dlg.f.c coords [expr {1+$square}]] 0 1]
+ lappend visited $square
+ set next [Next $square]
+ if {$next ne -1} {
+ variable aid [after $delay [list MovePiece $dlg $square $next]]
+ } else {
+ $dlg.tf.b1 configure -state normal
+ if {[llength $visited] == 64} {
+ variable initial
+ if {$initial == $square} {
+ $dlg.f.txt insert end "Closed tour!"
+ } else {
+ $dlg.f.txt insert end "Success\n" {}
+ if {$continuous} {
+ after [expr {$delay * 2}] [namespace code \
+ [list Tour $dlg [expr {int(rand() * 64)}]]]
+ }
+ }
+ } else {
+ $dlg.f.txt insert end "FAILED!\n" {}
+ }
+ }
+}
+
+# Begin a new tour of the board given a random start position
+proc Tour {dlg {square {}}} {
+ variable visited {}
+ $dlg.f.txt delete 1.0 end
+ $dlg.tf.b1 configure -state disabled
+ for {set n 0} {$n < 64} {incr n} {
+ $dlg.f.c itemconfigure $n -state disabled -outline black
+ }
+ if {$square eq {}} {
+ set coords [lrange [$dlg.f.c coords knight] 0 1]
+ set square [expr {[$dlg.f.c find closest {*}$coords 0 65]-1}]
+ }
+ variable initial $square
+ after idle [list MovePiece $dlg $initial $initial]
+}
+
+proc Stop {} {
+ variable aid
+ catch {after cancel $aid}
+}
+
+proc Exit {dlg} {
+ Stop
+ destroy $dlg
+}
+
+proc SetDelay {new} {
+ variable delay [expr {int($new)}]
+}
+
+proc DragStart {w x y} {
+ $w dtag selected
+ $w addtag selected withtag current
+ variable dragging [list $x $y]
+}
+proc DragMotion {w x y} {
+ variable dragging
+ if {[info exists dragging]} {
+ $w move selected [expr {$x - [lindex $dragging 0]}] \
+ [expr {$y - [lindex $dragging 1]}]
+ variable dragging [list $x $y]
+ }
+}
+proc DragEnd {w x y} {
+ set square [$w find closest $x $y 0 65]
+ $w moveto selected {*}[lrange [$w coords $square] 0 1]
+ $w dtag selected
+ variable dragging ; unset dragging
+}
+
+proc CreateGUI {} {
+ catch {destroy .knightstour}
+ set dlg [toplevel .knightstour]
+ wm title $dlg "Knights tour"
+ wm withdraw $dlg
+ set f [ttk::frame $dlg.f]
+ set c [canvas $f.c -width 240 -height 240]
+ text $f.txt -width 10 -height 1 -background white \
+ -yscrollcommand [list $f.vs set] -font {Arial 8}
+ ttk::scrollbar $f.vs -command [list $f.txt yview]
+
+ variable delay 600
+ variable continuous 0
+ ttk::frame $dlg.tf
+ ttk::label $dlg.tf.ls -text Speed
+ ttk::scale $dlg.tf.sc -from 8 -to 2000 -command [list SetDelay] \
+ -variable [namespace which -variable delay]
+ ttk::checkbutton $dlg.tf.cc -text Repeat \
+ -variable [namespace which -variable continuous]
+ ttk::button $dlg.tf.b1 -text Start -command [list Tour $dlg]
+ ttk::button $dlg.tf.b2 -text Exit -command [list Exit $dlg]
+ set square 0
+ for {set row 7} {$row != -1} {incr row -1} {
+ for {set col 0} {$col < 8} {incr col} {
+ if {(($col & 1) ^ ($row & 1))} {
+ set fill tan3 ; set dfill tan4
+ } else {
+ set fill bisque ; set dfill bisque3
+ }
+ set coords [list [expr {$col * 30 + 4}] [expr {$row * 30 + 4}] \
+ [expr {$col * 30 + 30}] [expr {$row * 30 + 30}]]
+ $c create rectangle $coords -fill $fill -disabledfill $dfill \
+ -width 2 -state disabled
+ }
+ }
+ if {[tk windowingsystem] ne "x11"} {
+ catch {eval font create KnightFont -size -24}
+ $c create text 0 0 -font KnightFont -text "\u265e" \
+ -anchor nw -tags knight -fill black -activefill "#600000"
+ } else {
+ # On X11 we cannot reliably tell if the \u265e glyph is available
+ # so just use a polygon
+ set pts {
+ 2 25 24 25 21 19 20 8 14 0 10 0 0 13 0 16
+ 2 17 4 14 5 15 3 17 5 17 9 14 10 15 5 21
+ }
+ $c create polygon $pts -tag knight -offset 8 \
+ -fill black -activefill "#600000"
+ }
+ $c moveto knight {*}[lrange [$c coords [expr {1 + int(rand() * 64)}]] 0 1]
+ $c bind knight <ButtonPress-1> [namespace code [list DragStart %W %x %y]]
+ $c bind knight <Motion> [namespace code [list DragMotion %W %x %y]]
+ $c bind knight <ButtonRelease-1> [namespace code [list DragEnd %W %x %y]]
+
+ grid $c $f.txt $f.vs -sticky news
+ grid rowconfigure $f 0 -weight 1
+ grid columnconfigure $f 1 -weight 1
+
+ grid $f - - - - - -sticky news
+ set things [list $dlg.tf.ls $dlg.tf.sc $dlg.tf.cc $dlg.tf.b1]
+ if {![info exists ::widgetDemo]} {
+ lappend things $dlg.tf.b2
+ if {[tk windowingsystem] ne "aqua"} {
+ set things [linsert $things 0 [ttk::sizegrip $dlg.tf.sg]]
+ }
+ }
+ pack {*}$things -side right
+ if {[tk windowingsystem] eq "aqua"} {
+ pack configure {*}$things -padx {4 4} -pady {12 12}
+ pack configure [lindex $things 0] -padx {4 24}
+ pack configure [lindex $things end] -padx {16 4}
+ }
+ grid $dlg.tf - - - - - -sticky ew
+ if {[info exists ::widgetDemo]} {
+ grid [addSeeDismiss $dlg.buttons $dlg] - - - - - -sticky ew
+ }
+
+ grid rowconfigure $dlg 0 -weight 1
+ grid columnconfigure $dlg 0 -weight 1
+
+ bind $dlg <Control-F2> {console show}
+ bind $dlg <Return> [list $dlg.tf.b1 invoke]
+ bind $dlg <Escape> [list $dlg.tf.b2 invoke]
+ bind $dlg <Destroy> [namespace code [list Stop]]
+ wm protocol $dlg WM_DELETE_WINDOW [namespace code [list Exit $dlg]]
+
+ wm deiconify $dlg
+ tkwait window $dlg
+}
+
+if {![winfo exists .knightstour]} {
+ if {![info exists widgetDemo]} { wm withdraw . }
+ set r [catch [linsert $argv 0 CreateGUI] err]
+ if {$r} {
+ tk_messageBox -icon error -title "Error" -message $err
+ }
+ if {![info exists widgetDemo]} { exit $r }
+}
diff --git a/tk8.6/library/demos/label.tcl b/tk8.6/library/demos/label.tcl
new file mode 100644
index 0000000..13463f7
--- /dev/null
+++ b/tk8.6/library/demos/label.tcl
@@ -0,0 +1,40 @@
+# label.tcl --
+#
+# This demonstration script creates a toplevel window containing
+# several label widgets.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .label
+catch {destroy $w}
+toplevel $w
+wm title $w "Label Demonstration"
+wm iconname $w "label"
+positionWindow $w
+
+label $w.msg -font $font -wraplength 4i -justify left -text "Five labels are displayed below: three textual ones on the left, and an image label and a text label on the right. Labels are pretty boring because you can't do anything with them."
+pack $w.msg -side top
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+frame $w.left
+frame $w.right
+pack $w.left $w.right -side left -expand yes -padx 10 -pady 10 -fill both
+
+label $w.left.l1 -text "First label"
+label $w.left.l2 -text "Second label, raised" -relief raised
+label $w.left.l3 -text "Third label, sunken" -relief sunken
+pack $w.left.l1 $w.left.l2 $w.left.l3 -side top -expand yes -pady 2 -anchor w
+
+# Main widget program sets variable tk_demoDirectory
+image create photo label.ousterhout \
+ -file [file join $tk_demoDirectory images ouster.png]
+label $w.right.picture -borderwidth 2 -relief sunken -image label.ousterhout
+label $w.right.caption -text "Tcl/Tk Creator"
+pack $w.right.picture $w.right.caption -side top
diff --git a/tk8.6/library/demos/labelframe.tcl b/tk8.6/library/demos/labelframe.tcl
new file mode 100644
index 0000000..21d079f
--- /dev/null
+++ b/tk8.6/library/demos/labelframe.tcl
@@ -0,0 +1,76 @@
+# labelframe.tcl --
+#
+# This demonstration script creates a toplevel window containing
+# several labelframe widgets.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .labelframe
+catch {destroy $w}
+toplevel $w
+wm title $w "Labelframe Demonstration"
+wm iconname $w "labelframe"
+positionWindow $w
+
+# Some information
+
+label $w.msg -font $font -wraplength 4i -justify left -text "Labelframes are\
+ used to group related widgets together. The label may be either \
+ plain text or another widget."
+pack $w.msg -side top
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+# Demo area
+
+frame $w.f
+pack $w.f -side bottom -fill both -expand 1
+set w $w.f
+
+# A group of radiobuttons in a labelframe
+
+labelframe $w.f -text "Value" -padx 2 -pady 2
+grid $w.f -row 0 -column 0 -pady 2m -padx 2m
+
+foreach value {1 2 3 4} {
+ radiobutton $w.f.b$value -text "This is value $value" \
+ -variable lfdummy -value $value
+ pack $w.f.b$value -side top -fill x -pady 2
+}
+
+
+# Using a label window to control a group of options.
+
+proc lfEnableButtons {w} {
+ foreach child [winfo children $w] {
+ if {$child == "$w.cb"} continue
+ if {$::lfdummy2} {
+ $child configure -state normal
+ } else {
+ $child configure -state disabled
+ }
+ }
+}
+
+labelframe $w.f2 -pady 2 -padx 2
+checkbutton $w.f2.cb -text "Use this option." -variable lfdummy2 \
+ -command "lfEnableButtons $w.f2" -padx 0
+$w.f2 configure -labelwidget $w.f2.cb
+grid $w.f2 -row 0 -column 1 -pady 2m -padx 2m
+
+set t 0
+foreach str {Option1 Option2 Option3} {
+ checkbutton $w.f2.b$t -text $str
+ pack $w.f2.b$t -side top -fill x -pady 2
+ incr t
+}
+lfEnableButtons $w.f2
+
+
+grid columnconfigure $w {0 1} -weight 1
diff --git a/tk8.6/library/demos/mclist.tcl b/tk8.6/library/demos/mclist.tcl
new file mode 100644
index 0000000..7a4dd4c
--- /dev/null
+++ b/tk8.6/library/demos/mclist.tcl
@@ -0,0 +1,119 @@
+# mclist.tcl --
+#
+# This demonstration script creates a toplevel window containing a Ttk
+# tree widget configured as a multi-column listbox.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .mclist
+catch {destroy $w}
+toplevel $w
+wm title $w "Multi-Column List"
+wm iconname $w "mclist"
+positionWindow $w
+
+## Explanatory text
+ttk::label $w.msg -font $font -wraplength 4i -justify left -anchor n -padding {10 2 10 6} -text "Ttk is the new Tk themed widget set. One of the widgets it includes is a tree widget, which can be configured to display multiple columns of informational data without displaying the tree itself. This is a simple way to build a listbox that has multiple columns. Clicking on the heading for a column will sort the data by that column. You can also change the width of the columns by dragging the boundary between them."
+pack $w.msg -fill x
+
+## See Code / Dismiss
+pack [addSeeDismiss $w.seeDismiss $w] -side bottom -fill x
+
+ttk::frame $w.container
+ttk::treeview $w.tree -columns {country capital currency} -show headings \
+ -yscroll "$w.vsb set" -xscroll "$w.hsb set"
+ttk::scrollbar $w.vsb -orient vertical -command "$w.tree yview"
+ttk::scrollbar $w.hsb -orient horizontal -command "$w.tree xview"
+pack $w.container -fill both -expand 1
+grid $w.tree $w.vsb -in $w.container -sticky nsew
+grid $w.hsb -in $w.container -sticky nsew
+grid column $w.container 0 -weight 1
+grid row $w.container 0 -weight 1
+
+image create photo upArrow -data {
+ R0lGODlhDgAOAJEAANnZ2YCAgPz8/P///yH5BAEAAAAALAAAAAAOAA4AAAImhI+
+ py+1LIsJHiBAh+BgmiEAJQITgW6DgUQIAECH4JN8IPqYuNxUAOw==}
+image create photo downArrow -data {
+ R0lGODlhDgAOAJEAANnZ2YCAgPz8/P///yH5BAEAAAAALAAAAAAOAA4AAAInhI+
+ py+1I4ocQ/IgDEYIPgYJICUCE4F+YIBolEoKPEJKZmVJK6ZACADs=}
+image create photo noArrow -height 14 -width 14
+
+## The data we're going to insert
+set data {
+ Argentina {Buenos Aires} ARS
+ Australia Canberra AUD
+ Brazil Brazilia BRL
+ Canada Ottawa CAD
+ China Beijing CNY
+ France Paris EUR
+ Germany Berlin EUR
+ India {New Delhi} INR
+ Italy Rome EUR
+ Japan Tokyo JPY
+ Mexico {Mexico City} MXN
+ Russia Moscow RUB
+ {South Africa} Pretoria ZAR
+ {United Kingdom} London GBP
+ {United States} {Washington, D.C.} USD
+}
+
+## Code to insert the data nicely
+set font [ttk::style lookup Heading -font]
+foreach col {country capital currency} name {Country Capital Currency} {
+ $w.tree heading $col -text $name -image noArrow -anchor w \
+ -command [list SortBy $w.tree $col 0]
+ $w.tree column $col -width [expr {
+ [font measure $font $name] + [image width noArrow] + 5
+ }]
+}
+set font [ttk::style lookup Treeview -font]
+foreach {country capital currency} $data {
+ $w.tree insert {} end -values [list $country $capital $currency]
+ foreach col {country capital currency} {
+ set len [font measure $font "[set $col] "]
+ if {[$w.tree column $col -width] < $len} {
+ $w.tree column $col -width $len
+ }
+ }
+}
+
+## Code to do the sorting of the tree contents when clicked on
+proc SortBy {tree col direction} {
+ # Determine currently sorted column and its sort direction
+ foreach c {country capital currency} {
+ set s [$tree heading $c state]
+ if {("selected" in $s || "alternate" in $s) && $col ne $c} {
+ # Sorted column has changed
+ $tree heading $c -image noArrow state {!selected !alternate !user1}
+ set direction [expr {"alternate" in $s}]
+ }
+ }
+
+ # Build something we can sort
+ set data {}
+ foreach row [$tree children {}] {
+ lappend data [list [$tree set $row $col] $row]
+ }
+
+ set dir [expr {$direction ? "-decreasing" : "-increasing"}]
+ set r -1
+
+ # Now reshuffle the rows into the sorted order
+ foreach info [lsort -dictionary -index 0 $dir $data] {
+ $tree move [lindex $info 1] {} [incr r]
+ }
+
+ # Switch the heading so that it will sort in the opposite direction
+ $tree heading $col -command [list SortBy $tree $col [expr {!$direction}]] \
+ state [expr {$direction?"!selected alternate":"selected !alternate"}]
+ if {[ttk::style theme use] eq "aqua"} {
+ # Aqua theme displays native sort arrows when user1 state is set
+ $tree heading $col state "user1"
+ } else {
+ $tree heading $col -image [expr {$direction?"upArrow":"downArrow"}]
+ }
+}
diff --git a/tk8.6/library/demos/menu.tcl b/tk8.6/library/demos/menu.tcl
new file mode 100644
index 0000000..a788a65
--- /dev/null
+++ b/tk8.6/library/demos/menu.tcl
@@ -0,0 +1,163 @@
+# menu.tcl --
+#
+# This demonstration script creates a window with a bunch of menus
+# and cascaded menus using menubars.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .menu
+catch {destroy $w}
+toplevel $w
+wm title $w "Menu Demonstration"
+wm iconname $w "menu"
+positionWindow $w
+
+label $w.msg -font $font -wraplength 4i -justify left
+if {[tk windowingsystem] eq "aqua"} {
+ catch {set origUseCustomMDEF $::tk::mac::useCustomMDEF; set ::tk::mac::useCustomMDEF 1}
+ $w.msg configure -text "This window has a menubar with cascaded menus. You can invoke entries with an accelerator by typing Command+x, where \"x\" is the character next to the command key symbol. The rightmost menu can be torn off into a palette by selecting the first item in the menu."
+} else {
+ $w.msg configure -text "This window contains a menubar with cascaded menus. You can post a menu from the keyboard by typing Alt+x, where \"x\" is the character underlined on the menu. You can then traverse among the menus using the arrow keys. When a menu is posted, you can invoke the current entry by typing space, or you can invoke any entry by typing its underlined character. If a menu entry has an accelerator, you can invoke the entry without posting the menu just by typing the accelerator. The rightmost menu can be torn off into a palette by selecting the first item in the menu."
+}
+pack $w.msg -side top
+
+set menustatus " "
+frame $w.statusBar
+label $w.statusBar.label -textvariable menustatus -relief sunken -bd 1 -font "Helvetica 10" -anchor w
+pack $w.statusBar.label -side left -padx 2 -expand yes -fill both
+pack $w.statusBar -side bottom -fill x -pady 2
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+menu $w.menu -tearoff 0
+
+set m $w.menu.file
+menu $m -tearoff 0
+$w.menu add cascade -label "File" -menu $m -underline 0
+$m add command -label "Open..." -command {error "this is just a demo: no action has been defined for the \"Open...\" entry"}
+$m add command -label "New" -command {error "this is just a demo: no action has been defined for the \"New\" entry"}
+$m add command -label "Save" -command {error "this is just a demo: no action has been defined for the \"Save\" entry"}
+$m add command -label "Save As..." -command {error "this is just a demo: no action has been defined for the \"Save As...\" entry"}
+$m add separator
+$m add command -label "Print Setup..." -command {error "this is just a demo: no action has been defined for the \"Print Setup...\" entry"}
+$m add command -label "Print..." -command {error "this is just a demo: no action has been defined for the \"Print...\" entry"}
+$m add separator
+$m add command -label "Dismiss Menus Demo" -command "destroy $w"
+
+set m $w.menu.basic
+$w.menu add cascade -label "Basic" -menu $m -underline 0
+menu $m -tearoff 0
+$m add command -label "Long entry that does nothing"
+if {[tk windowingsystem] eq "aqua"} {
+ set modifier Command
+} elseif {[tk windowingsystem] == "win32"} {
+ set modifier Control
+} else {
+ set modifier Meta
+}
+foreach i {A B C D E F} {
+ $m add command -label "Print letter \"$i\"" -underline 14 \
+ -accelerator Meta+$i -command "puts $i" -accelerator $modifier+$i
+ bind $w <$modifier-[string tolower $i]> "puts $i"
+}
+
+set m $w.menu.cascade
+$w.menu add cascade -label "Cascades" -menu $m -underline 0
+menu $m -tearoff 0
+$m add command -label "Print hello" \
+ -command {puts stdout "Hello"} -accelerator $modifier+H -underline 6
+bind $w <$modifier-h> {puts stdout "Hello"}
+$m add command -label "Print goodbye" -command {\
+ puts stdout "Goodbye"} -accelerator $modifier+G -underline 6
+bind $w <$modifier-g> {puts stdout "Goodbye"}
+$m add cascade -label "Check buttons" \
+ -menu $w.menu.cascade.check -underline 0
+$m add cascade -label "Radio buttons" \
+ -menu $w.menu.cascade.radio -underline 0
+
+set m $w.menu.cascade.check
+menu $m -tearoff 0
+$m add check -label "Oil checked" -variable oil
+$m add check -label "Transmission checked" -variable trans
+$m add check -label "Brakes checked" -variable brakes
+$m add check -label "Lights checked" -variable lights
+$m add separator
+$m add command -label "Show current values" \
+ -command "showVars $w.menu.cascade.dialog oil trans brakes lights"
+$m invoke 1
+$m invoke 3
+
+set m $w.menu.cascade.radio
+menu $m -tearoff 0
+$m add radio -label "10 point" -variable pointSize -value 10
+$m add radio -label "14 point" -variable pointSize -value 14
+$m add radio -label "18 point" -variable pointSize -value 18
+$m add radio -label "24 point" -variable pointSize -value 24
+$m add radio -label "32 point" -variable pointSize -value 32
+$m add sep
+$m add radio -label "Roman" -variable style -value roman
+$m add radio -label "Bold" -variable style -value bold
+$m add radio -label "Italic" -variable style -value italic
+$m add sep
+$m add command -label "Show current values" \
+ -command "showVars $w.menu.cascade.dialog pointSize style"
+$m invoke 1
+$m invoke 7
+
+set m $w.menu.icon
+$w.menu add cascade -label "Icons" -menu $m -underline 0
+menu $m -tearoff 0
+# Main widget program sets variable tk_demoDirectory
+image create photo lilearth -file [file join $tk_demoDirectory \
+images earthmenu.png]
+$m add command -image lilearth \
+ -hidemargin 1 -command [list \
+ tk_dialog $w.pattern {Bitmap Menu Entry} \
+ "The menu entry you invoked displays a photoimage rather than\
+ a text string. Other than this, it is just like any other\
+ menu entry." {} 0 OK ]
+foreach i {info questhead error} {
+ $m add command -bitmap $i -hidemargin 1 -command [list \
+ puts "You invoked the $i bitmap" ]
+}
+$m entryconfigure 2 -columnbreak 1
+
+set m $w.menu.more
+$w.menu add cascade -label "More" -menu $m -underline 0
+menu $m -tearoff 0
+foreach i {{An entry} {Another entry} {Does nothing} {Does almost nothing} {Make life meaningful}} {
+ $m add command -label $i -command [list puts "You invoked \"$i\""]
+}
+$m entryconfigure "Does almost nothing" -bitmap questhead -compound left \
+ -command [list \
+ tk_dialog $w.compound {Compound Menu Entry} \
+ "The menu entry you invoked displays both a bitmap and a\
+ text string. Other than this, it is just like any other\
+ menu entry." {} 0 OK ]
+
+set m $w.menu.colors
+$w.menu add cascade -label "Colors" -menu $m -underline 1
+menu $m -tearoff 1
+foreach i {red orange yellow green blue} {
+ $m add command -label $i -background $i -command [list \
+ puts "You invoked \"$i\"" ]
+}
+
+$w configure -menu $w.menu
+
+bind Menu <<MenuSelect>> {
+ global $menustatus
+ if {[catch {%W entrycget active -label} label]} {
+ set label " "
+ }
+ set menustatus $label
+ update idletasks
+}
+
+if {[tk windowingsystem] eq "aqua"} {catch {set ::tk::mac::useCustomMDEF $origUseCustomMDEF}}
diff --git a/tk8.6/library/demos/menubu.tcl b/tk8.6/library/demos/menubu.tcl
new file mode 100644
index 0000000..96e3b15
--- /dev/null
+++ b/tk8.6/library/demos/menubu.tcl
@@ -0,0 +1,90 @@
+# menubu.tcl --
+#
+# This demonstration script creates a window with a bunch of menus
+# and cascaded menus using menubuttons.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .menubu
+catch {destroy $w}
+toplevel $w
+wm title $w "Menu Button Demonstration"
+wm iconname $w "menubutton"
+positionWindow $w
+
+frame $w.body
+pack $w.body -expand 1 -fill both
+if {[tk windowingsystem] eq "aqua"} {catch {set origUseCustomMDEF $::tk::mac::useCustomMDEF; set ::tk::mac::useCustomMDEF 1}}
+
+menubutton $w.body.below -text "Below" -underline 0 -direction below -menu $w.body.below.m -relief raised
+menu $w.body.below.m -tearoff 0
+$w.body.below.m add command -label "Below menu: first item" -command "puts \"You have selected the first item from the Below menu.\""
+$w.body.below.m add command -label "Below menu: second item" -command "puts \"You have selected the second item from the Below menu.\""
+grid $w.body.below -row 0 -column 1 -sticky n
+menubutton $w.body.right -text "Right" -underline 0 -direction right -menu $w.body.right.m -relief raised
+menu $w.body.right.m -tearoff 0
+$w.body.right.m add command -label "Right menu: first item" -command "puts \"You have selected the first item from the Right menu.\""
+$w.body.right.m add command -label "Right menu: second item" -command "puts \"You have selected the second item from the Right menu.\""
+frame $w.body.center
+menubutton $w.body.left -text "Left" -underline 0 -direction left -menu $w.body.left.m -relief raised
+menu $w.body.left.m -tearoff 0
+$w.body.left.m add command -label "Left menu: first item" -command "puts \"You have selected the first item from the Left menu.\""
+$w.body.left.m add command -label "Left menu: second item" -command "puts \"You have selected the second item from the Left menu.\""
+grid $w.body.right -row 1 -column 0 -sticky w
+grid $w.body.center -row 1 -column 1 -sticky news
+grid $w.body.left -row 1 -column 2 -sticky e
+menubutton $w.body.above -text "Above" -underline 0 -direction above -menu $w.body.above.m -relief raised
+menu $w.body.above.m -tearoff 0
+$w.body.above.m add command -label "Above menu: first item" -command "puts \"You have selected the first item from the Above menu.\""
+$w.body.above.m add command -label "Above menu: second item" -command "puts \"You have selected the second item from the Above menu.\""
+grid $w.body.above -row 2 -column 1 -sticky s
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+set body $w.body.center
+label $body.label -wraplength 300 -font "Helvetica 14" -justify left -text "This is a demonstration of menubuttons. The \"Below\" menubutton pops its menu below the button; the \"Right\" button pops to the right, etc. There are two option menus directly below this text; one is just a standard menu and the other is a 16-color palette."
+pack $body.label -side top -padx 25 -pady 25
+frame $body.buttons
+pack $body.buttons -padx 25 -pady 25
+tk_optionMenu $body.buttons.options menubuttonoptions one two three
+pack $body.buttons.options -side left -padx 25 -pady 25
+set m [tk_optionMenu $body.buttons.colors paletteColor Black red4 DarkGreen NavyBlue gray75 Red Green Blue gray50 Yellow Cyan Magenta White Brown DarkSeaGreen DarkViolet]
+if {[tk windowingsystem] eq "aqua"} {
+ set topBorderColor Black
+ set bottomBorderColor Black
+} else {
+ set topBorderColor gray50
+ set bottomBorderColor gray75
+}
+for {set i 0} {$i <= [$m index last]} {incr i} {
+ set name [$m entrycget $i -label]
+ image create photo image_$name -height 16 -width 16
+ image_$name put $topBorderColor -to 0 0 16 1
+ image_$name put $topBorderColor -to 0 1 1 16
+ image_$name put $bottomBorderColor -to 0 15 16 16
+ image_$name put $bottomBorderColor -to 15 1 16 16
+ image_$name put $name -to 1 1 15 15
+
+ image create photo image_${name}_s -height 16 -width 16
+ image_${name}_s put Black -to 0 0 16 2
+ image_${name}_s put Black -to 0 2 2 16
+ image_${name}_s put Black -to 2 14 16 16
+ image_${name}_s put Black -to 14 2 16 14
+ image_${name}_s put $name -to 2 2 14 14
+
+ $m entryconfigure $i -image image_$name -selectimage image_${name}_s -hidemargin 1
+}
+$m configure -tearoff 1
+foreach i {Black gray75 gray50 White} {
+ $m entryconfigure $i -columnbreak 1
+}
+
+pack $body.buttons.colors -side left -padx 25 -pady 25
+
+if {[tk windowingsystem] eq "aqua"} {catch {set ::tk::mac::useCustomMDEF $origUseCustomMDEF}}
diff --git a/tk8.6/library/demos/msgbox.tcl b/tk8.6/library/demos/msgbox.tcl
new file mode 100644
index 0000000..2c2cc2d
--- /dev/null
+++ b/tk8.6/library/demos/msgbox.tcl
@@ -0,0 +1,62 @@
+# msgbox.tcl --
+#
+# This demonstration script creates message boxes of various type
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .msgbox
+catch {destroy $w}
+toplevel $w
+wm title $w "Message Box Demonstration"
+wm iconname $w "messagebox"
+positionWindow $w
+
+label $w.msg -font $font -wraplength 4i -justify left -text "Choose the icon and type option of the message box. Then press the \"Message Box\" button to see the message box."
+pack $w.msg -side top
+
+pack [addSeeDismiss $w.buttons $w {} {
+ ttk::button $w.buttons.vars -text "Message Box" -command "showMessageBox $w"
+}] -side bottom -fill x
+#pack $w.buttons.dismiss $w.buttons.code $w.buttons.vars -side left -expand 1
+
+frame $w.left
+frame $w.right
+pack $w.left $w.right -side left -expand yes -fill y -pady .5c -padx .5c
+
+label $w.left.label -text "Icon"
+frame $w.left.sep -relief ridge -bd 1 -height 2
+pack $w.left.label -side top
+pack $w.left.sep -side top -fill x -expand no
+
+set msgboxIcon info
+foreach i {error info question warning} {
+ radiobutton $w.left.b$i -text $i -variable msgboxIcon \
+ -relief flat -value $i -width 16 -anchor w
+ pack $w.left.b$i -side top -pady 2 -anchor w -fill x
+}
+
+label $w.right.label -text "Type"
+frame $w.right.sep -relief ridge -bd 1 -height 2
+pack $w.right.label -side top
+pack $w.right.sep -side top -fill x -expand no
+
+set msgboxType ok
+foreach t {abortretryignore ok okcancel retrycancel yesno yesnocancel} {
+ radiobutton $w.right.$t -text $t -variable msgboxType \
+ -relief flat -value $t -width 16 -anchor w
+ pack $w.right.$t -side top -pady 2 -anchor w -fill x
+}
+
+proc showMessageBox {w} {
+ global msgboxIcon msgboxType
+ set button [tk_messageBox -icon $msgboxIcon -type $msgboxType \
+ -title Message -parent $w\
+ -message "This is a \"$msgboxType\" type messagebox with the \"$msgboxIcon\" icon"]
+
+ tk_messageBox -icon info -message "You have selected \"$button\"" -type ok\
+ -parent $w
+}
diff --git a/tk8.6/library/demos/nl.msg b/tk8.6/library/demos/nl.msg
new file mode 100644
index 0000000..cd52630
--- /dev/null
+++ b/tk8.6/library/demos/nl.msg
@@ -0,0 +1,125 @@
+::msgcat::mcset nl "Widget Demonstration" "Demonstratie van widgets"
+::msgcat::mcset nl "tkWidgetDemo" "tkWidgetDemo"
+::msgcat::mcset nl "&File" "&Bestand"
+::msgcat::mcset nl "About..." "Info..."
+::msgcat::mcset nl "&About..." "&Info..."
+::msgcat::mcset nl "<F1>" "<F1>"
+::msgcat::mcset nl "&Quit" "&Einde"
+::msgcat::mcset nl "Meta+Q" "Meta+E" ;# Displayed hotkey
+::msgcat::mcset nl "Meta-q" "Meta-e" ;# Actual binding sequence
+::msgcat::mcset nl "Ctrl+Q" "Ctrl+E" ;# Displayed hotkey
+::msgcat::mcset nl "Control-q" "Control-e" ;# Actual binding sequence
+::msgcat::mcset nl "Dismiss" "Sluiten"
+::msgcat::mcset nl "See Variables" "Bekijk Variabelen"
+::msgcat::mcset nl "Variable Values" "Waarden Variabelen"
+::msgcat::mcset nl "OK" "OK"
+::msgcat::mcset nl "Run the \"%s\" sample program" "Start voorbeeld \"%s\""
+::msgcat::mcset nl "Print Code" "Code Afdrukken"
+::msgcat::mcset nl "Demo code: %s" "Code van Demo %s"
+::msgcat::mcset nl "About Widget Demo" "Over deze demonstratie"
+::msgcat::mcset nl "Tk widget demonstration" "Demonstratie van Tk widgets"
+::msgcat::mcset nl "Copyright © %s"
+
+::msgcat::mcset nl "Tk Widget Demonstrations" "Demonstratie van Tk widgets"
+::msgcat::mcset nl "This application provides a front end for several short scripts" \
+ "Dit programma is een schil rond enkele korte scripts waarmee"
+::msgcat::mcset nl "that demonstrate what you can do with Tk widgets. Each of the" \
+ "gedemonstreerd wordt wat je kunt doen met Tk widgets. Elk van de"
+::msgcat::mcset nl "numbered lines below describes a demonstration; you can click on" \
+ "genummerde regels hieronder omschrijft een demonstratie; je kunt de"
+::msgcat::mcset nl "it to invoke the demonstration. Once the demonstration window" \
+ "demonstratie starten door op de regel te klikken."
+::msgcat::mcset nl "appears, you can click the" \
+ "Zodra het nieuwe venster verschijnt, kun je op de knop"
+::msgcat::mcset nl "See Code" "Bekijk Code" ;# This is also button text!
+::msgcat::mcset nl "button to see the Tcl/Tk code that created the demonstration. If" \
+ "drukken om de achterliggende Tcl/Tk code te zien. Als je dat wilt,"
+::msgcat::mcset nl "you wish, you can edit the code and click the" \
+ "kun je de code wijzigen en op de knop"
+::msgcat::mcset nl "Rerun Demo" "Herstart Demo" ;# This is also button text!
+::msgcat::mcset nl "button in the code window to reinvoke the demonstration with the" \
+ "drukken in het codevenster om de demonstratie uit te voeren met de"
+::msgcat::mcset nl "modified code." \
+ "nieuwe code."
+
+::msgcat::mcset nl "Labels, buttons, checkbuttons, and radiobuttons" \
+ "Labels, knoppen, vinkjes/aankruishokjes en radioknoppen"
+
+::msgcat::mcset nl "Labels (text and bitmaps)" "Labels (tekst en plaatjes)"
+::msgcat::mcset nl "Labels and UNICODE text" "Labels en tekst in UNICODE"
+::msgcat::mcset nl "Buttons" "Buttons (drukknoppen)"
+::msgcat::mcset nl "Check-buttons (select any of a group)" \
+ "Check-buttons (een of meer uit een groep)"
+::msgcat::mcset nl "Radio-buttons (select one of a group)" \
+ "Radio-buttons (een van een groep)"
+::msgcat::mcset nl "A 15-puzzle game made out of buttons" \
+ "Een schuifpuzzel van buttons"
+::msgcat::mcset nl "Iconic buttons that use bitmaps" \
+ "Buttons met pictogrammen"
+::msgcat::mcset nl "Two labels displaying images" \
+ "Twee labels met plaatjes in plaats van tekst"
+::msgcat::mcset nl "A simple user interface for viewing images" \
+ "Een eenvoudige user-interface voor het bekijken van plaatjes"
+::msgcat::mcset nl "Labelled frames" \
+ "Kaders met bijschrift"
+
+::msgcat::mcset nl "Listboxes" "Keuzelijsten"
+::msgcat::mcset nl "The 50 states" "De 50 staten van de VS"
+::msgcat::mcset nl "Colors: change the color scheme for the application" \
+ "Kleuren: verander het kleurenschema voor het programma"
+::msgcat::mcset nl "A collection of famous and infamous sayings" \
+ "Beroemde en beruchte citaten en gezegden"
+
+::msgcat::mcset nl "Entries and Spin-boxes" "Invulvelden en Spinboxen"
+::msgcat::mcset nl "Entries without scrollbars" "Invulvelden zonder schuifbalk"
+::msgcat::mcset nl "Entries with scrollbars" "Invulvelden met schuifbalk"
+::msgcat::mcset nl "Validated entries and password fields" \
+ "Invulvelden met controle of wachtwoorden"
+::msgcat::mcset nl "Spin-boxes" "Spinboxen"
+::msgcat::mcset nl "Simple Rolodex-like form" "Simpel kaartsysteem"
+
+::msgcat::mcset nl "Text" "Tekst"
+::msgcat::mcset nl "Basic editable text" "Voorbeeld met te wijzigen tekst"
+::msgcat::mcset nl "Text display styles" "Tekst met verschillende stijlen"
+::msgcat::mcset nl "Hypertext (tag bindings)" \
+ "Hypertext (verwijzingen via \"tags\")"
+::msgcat::mcset nl "A text widget with embedded windows" \
+ "Tekstwidget met windows erin"
+::msgcat::mcset nl "A search tool built with a text widget" \
+ "Zoeken in tekst met behulp van een tekstwidget"
+
+::msgcat::mcset nl "Canvases" "Canvaswidgets"
+::msgcat::mcset nl "The canvas item types" "Objecten in een canvas"
+::msgcat::mcset nl "A simple 2-D plot" "Eenvoudige 2D-grafiek"
+::msgcat::mcset nl "Text items in canvases" "Tekstobjecten in een canvas"
+::msgcat::mcset nl "An editor for arrowheads on canvas lines" \
+ "Editor voor de vorm van de pijl (begin/eind van een lijn)"
+::msgcat::mcset nl "A ruler with adjustable tab stops" \
+ "Een meetlat met aanpasbare ruiters"
+::msgcat::mcset nl "A building floor plan" "Plattegrond van een gebouw"
+::msgcat::mcset nl "A simple scrollable canvas" "Een schuifbaar canvas"
+
+::msgcat::mcset nl "Scales" "Schaalverdelingen"
+::msgcat::mcset nl "Horizontal scale" "Horizontale schaal"
+::msgcat::mcset nl "Vertical scale" "Verticale schaal"
+
+::msgcat::mcset nl "Paned Windows" "Vensters opgedeeld in stukken"
+::msgcat::mcset nl "Horizontal paned window" "Horizontaal gedeeld venster"
+::msgcat::mcset nl "Vertical paned window" "Verticaal gedeeld venster"
+
+::msgcat::mcset nl "Menus" "Menu's"
+::msgcat::mcset nl "Menus and cascades (sub-menus)" \
+ "Menu's en cascades (submenu's)"
+::msgcat::mcset nl "Menu-buttons" "Menu-buttons"
+
+::msgcat::mcset nl "Common Dialogs" "Veel voorkomende dialoogvensters"
+::msgcat::mcset nl "Message boxes" "Mededeling (message box)"
+::msgcat::mcset nl "File selection dialog" "Selectie van bestanden"
+::msgcat::mcset nl "Color picker" "Kleurenpalet"
+
+::msgcat::mcset nl "Miscellaneous" "Diversen"
+::msgcat::mcset nl "The built-in bitmaps" "Ingebouwde plaatjes"
+::msgcat::mcset nl "A dialog box with a local grab" \
+ "Een dialoogvenster met een locale \"grab\""
+::msgcat::mcset nl "A dialog box with a global grab" \
+ "Een dialoogvenster met een globale \"grab\""
diff --git a/tk8.6/library/demos/paned1.tcl b/tk8.6/library/demos/paned1.tcl
new file mode 100644
index 0000000..783b7f3
--- /dev/null
+++ b/tk8.6/library/demos/paned1.tcl
@@ -0,0 +1,32 @@
+# paned1.tcl --
+#
+# This demonstration script creates a toplevel window containing
+# a paned window that separates two windows horizontally.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .paned1
+catch {destroy $w}
+toplevel $w
+wm title $w "Horizontal Paned Window Demonstration"
+wm iconname $w "paned1"
+positionWindow $w
+
+label $w.msg -font $font -wraplength 4i -justify left -text "The sash between the two coloured windows below can be used to divide the area between them. Use the left mouse button to resize without redrawing by just moving the sash, and use the middle mouse button to resize opaquely (always redrawing the windows in each position.)"
+pack $w.msg -side top
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+panedwindow $w.pane
+pack $w.pane -side top -expand yes -fill both -pady 2 -padx 2m
+
+label $w.pane.left -text "This is the\nleft side" -bg yellow
+label $w.pane.right -text "This is the\nright side" -bg cyan
+
+$w.pane add $w.pane.left $w.pane.right
diff --git a/tk8.6/library/demos/paned2.tcl b/tk8.6/library/demos/paned2.tcl
new file mode 100644
index 0000000..c549249
--- /dev/null
+++ b/tk8.6/library/demos/paned2.tcl
@@ -0,0 +1,74 @@
+# paned2.tcl --
+#
+# This demonstration script creates a toplevel window containing
+# a paned window that separates two windows vertically.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .paned2
+catch {destroy $w}
+toplevel $w
+wm title $w "Vertical Paned Window Demonstration"
+wm iconname $w "paned2"
+positionWindow $w
+
+label $w.msg -font $font -wraplength 4i -justify left -text "The sash between the two scrolled windows below can be used to divide the area between them. Use the left mouse button to resize without redrawing by just moving the sash, and use the middle mouse button to resize opaquely (always redrawing the windows in each position.)"
+pack $w.msg -side top
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+# Create the pane itself
+panedwindow $w.pane -orient vertical
+pack $w.pane -side top -expand yes -fill both -pady 2 -padx 2m
+
+# The top window is a listbox with scrollbar
+set paneList {
+ {List of Tk Widgets}
+ button
+ canvas
+ checkbutton
+ entry
+ frame
+ label
+ labelframe
+ listbox
+ menu
+ menubutton
+ message
+ panedwindow
+ radiobutton
+ scale
+ scrollbar
+ spinbox
+ text
+ toplevel
+}
+set f [frame $w.pane.top]
+listbox $f.list -listvariable paneList -yscrollcommand "$f.scr set"
+# Invert the first item to highlight it
+$f.list itemconfigure 0 \
+ -background [$f.list cget -fg] -foreground [$f.list cget -bg]
+ttk::scrollbar $f.scr -orient vertical -command "$f.list yview"
+pack $f.scr -side right -fill y
+pack $f.list -fill both -expand 1
+
+# The bottom window is a text widget with scrollbar
+set f [frame $w.pane.bottom]
+text $f.text -xscrollcommand "$f.xscr set" -yscrollcommand "$f.yscr set" \
+ -width 30 -height 8 -wrap none
+ttk::scrollbar $f.xscr -orient horizontal -command "$f.text xview"
+ttk::scrollbar $f.yscr -orient vertical -command "$f.text yview"
+grid $f.text $f.yscr -sticky nsew
+grid $f.xscr -sticky nsew
+grid columnconfigure $f 0 -weight 1
+grid rowconfigure $f 0 -weight 1
+$f.text insert 1.0 "This is just a normal text widget"
+
+# Now add our contents to the paned window
+$w.pane add $w.pane.top $w.pane.bottom
diff --git a/tk8.6/library/demos/pendulum.tcl b/tk8.6/library/demos/pendulum.tcl
new file mode 100644
index 0000000..6422c67
--- /dev/null
+++ b/tk8.6/library/demos/pendulum.tcl
@@ -0,0 +1,197 @@
+# pendulum.tcl --
+#
+# This demonstration illustrates how Tcl/Tk can be used to construct
+# simulations of physical systems.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .pendulum
+catch {destroy $w}
+toplevel $w
+wm title $w "Pendulum Animation Demonstration"
+wm iconname $w "pendulum"
+positionWindow $w
+
+label $w.msg -font $font -wraplength 4i -justify left -text "This demonstration shows how Tcl/Tk can be used to carry out animations that are linked to simulations of physical systems. In the left canvas is a graphical representation of the physical system itself, a simple pendulum, and in the right canvas is a graph of the phase space of the system, which is a plot of the angle (relative to the vertical) against the angular velocity. The pendulum bob may be repositioned by clicking and dragging anywhere on the left canvas."
+pack $w.msg
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+# Create some structural widgets
+pack [panedwindow $w.p] -fill both -expand 1
+$w.p add [labelframe $w.p.l1 -text "Pendulum Simulation"]
+$w.p add [labelframe $w.p.l2 -text "Phase Space"]
+
+# Create the canvas containing the graphical representation of the
+# simulated system.
+canvas $w.c -width 320 -height 200 -background white -bd 2 -relief sunken
+$w.c create text 5 5 -anchor nw -text "Click to Adjust Bob Start Position"
+# Coordinates of these items don't matter; they will be set properly below
+$w.c create line 0 25 320 25 -tags plate -fill grey50 -width 2
+$w.c create oval 155 20 165 30 -tags pivot -fill grey50 -outline {}
+$w.c create line 1 1 1 1 -tags rod -fill black -width 3
+$w.c create oval 1 1 2 2 -tags bob -fill yellow -outline black
+pack $w.c -in $w.p.l1 -fill both -expand true
+
+# Create the canvas containing the phase space graph; this consists of
+# a line that gets gradually paler as it ages, which is an extremely
+# effective visual trick.
+canvas $w.k -width 320 -height 200 -background white -bd 2 -relief sunken
+$w.k create line 160 200 160 0 -fill grey75 -arrow last -tags y_axis
+$w.k create line 0 100 320 100 -fill grey75 -arrow last -tags x_axis
+for {set i 90} {$i>=0} {incr i -10} {
+ # Coordinates of these items don't matter; they will be set properly below
+ $w.k create line 0 0 1 1 -smooth true -tags graph$i -fill grey$i
+}
+
+$w.k create text 0 0 -anchor ne -text "\u03b8" -tags label_theta
+$w.k create text 0 0 -anchor ne -text "\u03b4\u03b8" -tags label_dtheta
+pack $w.k -in $w.p.l2 -fill both -expand true
+
+# Initialize some variables
+set points {}
+set Theta 45.0
+set dTheta 0.0
+set pi 3.1415926535897933
+set length 150
+set home 160
+
+# This procedure makes the pendulum appear at the correct place on the
+# canvas. If the additional arguments "at $x $y" are passed (the 'at'
+# is really just syntactic sugar) instead of computing the position of
+# the pendulum from the length of the pendulum rod and its angle, the
+# length and angle are computed in reverse from the given location
+# (which is taken to be the centre of the pendulum bob.)
+proc showPendulum {canvas {at {}} {x {}} {y {}}} {
+ global Theta dTheta pi length home
+ if {$at eq "at" && ($x!=$home || $y!=25)} {
+ set dTheta 0.0
+ set x2 [expr {$x - $home}]
+ set y2 [expr {$y - 25}]
+ set length [expr {hypot($x2, $y2)}]
+ set Theta [expr {atan2($x2, $y2) * 180/$pi}]
+ } else {
+ set angle [expr {$Theta * $pi/180}]
+ set x [expr {$home + $length*sin($angle)}]
+ set y [expr {25 + $length*cos($angle)}]
+ }
+ $canvas coords rod $home 25 $x $y
+ $canvas coords bob \
+ [expr {$x-15}] [expr {$y-15}] [expr {$x+15}] [expr {$y+15}]
+}
+showPendulum $w.c
+
+# Update the phase-space graph according to the current angle and the
+# rate at which the angle is changing (the first derivative with
+# respect to time.)
+proc showPhase {canvas} {
+ global Theta dTheta points psw psh
+ lappend points [expr {$Theta+$psw}] [expr {-20*$dTheta+$psh}]
+ if {[llength $points] > 100} {
+ set points [lrange $points end-99 end]
+ }
+ for {set i 0} {$i<100} {incr i 10} {
+ set list [lrange $points end-[expr {$i-1}] end-[expr {$i-12}]]
+ if {[llength $list] >= 4} {
+ $canvas coords graph$i $list
+ }
+ }
+}
+
+# Set up some bindings on the canvases. Note that when the user
+# clicks we stop the animation until they release the mouse
+# button. Also note that both canvases are sensitive to <Configure>
+# events, which allows them to find out when they have been resized by
+# the user.
+bind $w.c <Destroy> {
+ after cancel $animationCallbacks(pendulum)
+ unset animationCallbacks(pendulum)
+}
+bind $w.c <1> {
+ after cancel $animationCallbacks(pendulum)
+ showPendulum %W at %x %y
+}
+bind $w.c <B1-Motion> {
+ showPendulum %W at %x %y
+}
+bind $w.c <ButtonRelease-1> {
+ showPendulum %W at %x %y
+ set animationCallbacks(pendulum) [after 15 repeat [winfo toplevel %W]]
+}
+bind $w.c <Configure> {
+ %W coords plate 0 25 %w 25
+ set home [expr {%w/2}]
+ %W coords pivot [expr {$home-5}] 20 [expr {$home+5}] 30
+}
+bind $w.k <Configure> {
+ set psh [expr {%h/2}]
+ set psw [expr {%w/2}]
+ %W coords x_axis 2 $psh [expr {%w-2}] $psh
+ %W coords y_axis $psw [expr {%h-2}] $psw 2
+ %W coords label_dtheta [expr {$psw-4}] 6
+ %W coords label_theta [expr {%w-6}] [expr {$psh+4}]
+}
+
+# This procedure is the "business" part of the simulation that does
+# simple numerical integration of the formula for a simple rotational
+# pendulum.
+proc recomputeAngle {} {
+ global Theta dTheta pi length
+ set scaling [expr {3000.0/$length/$length}]
+
+ # To estimate the integration accurately, we really need to
+ # compute the end-point of our time-step. But to do *that*, we
+ # need to estimate the integration accurately! So we try this
+ # technique, which is inaccurate, but better than doing it in a
+ # single step. What we really want is bound up in the
+ # differential equation:
+ # .. - sin theta
+ # theta + theta = -----------
+ # length
+ # But my math skills are not good enough to solve this!
+
+ # first estimate
+ set firstDDTheta [expr {-sin($Theta * $pi/180)*$scaling}]
+ set midDTheta [expr {$dTheta + $firstDDTheta}]
+ set midTheta [expr {$Theta + ($dTheta + $midDTheta)/2}]
+ # second estimate
+ set midDDTheta [expr {-sin($midTheta * $pi/180)*$scaling}]
+ set midDTheta [expr {$dTheta + ($firstDDTheta + $midDDTheta)/2}]
+ set midTheta [expr {$Theta + ($dTheta + $midDTheta)/2}]
+ # Now we do a double-estimate approach for getting the final value
+ # first estimate
+ set midDDTheta [expr {-sin($midTheta * $pi/180)*$scaling}]
+ set lastDTheta [expr {$midDTheta + $midDDTheta}]
+ set lastTheta [expr {$midTheta + ($midDTheta + $lastDTheta)/2}]
+ # second estimate
+ set lastDDTheta [expr {-sin($lastTheta * $pi/180)*$scaling}]
+ set lastDTheta [expr {$midDTheta + ($midDDTheta + $lastDDTheta)/2}]
+ set lastTheta [expr {$midTheta + ($midDTheta + $lastDTheta)/2}]
+ # Now put the values back in our globals
+ set dTheta $lastDTheta
+ set Theta $lastTheta
+}
+
+# This method ties together the simulation engine and the graphical
+# display code that visualizes it.
+proc repeat w {
+ global animationCallbacks
+
+ # Simulate
+ recomputeAngle
+
+ # Update the display
+ showPendulum $w.c
+ showPhase $w.k
+
+ # Reschedule ourselves
+ set animationCallbacks(pendulum) [after 15 [list repeat $w]]
+}
+# Start the simulation after a short pause
+set animationCallbacks(pendulum) [after 500 [list repeat $w]]
diff --git a/tk8.6/library/demos/plot.tcl b/tk8.6/library/demos/plot.tcl
new file mode 100644
index 0000000..e7f0361
--- /dev/null
+++ b/tk8.6/library/demos/plot.tcl
@@ -0,0 +1,97 @@
+# plot.tcl --
+#
+# This demonstration script creates a canvas widget showing a 2-D
+# plot with data points that can be dragged with the mouse.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .plot
+catch {destroy $w}
+toplevel $w
+wm title $w "Plot Demonstration"
+wm iconname $w "Plot"
+positionWindow $w
+set c $w.c
+
+label $w.msg -font $font -wraplength 4i -justify left -text "This window displays a canvas widget containing a simple 2-dimensional plot. You can doctor the data by dragging any of the points with mouse button 1."
+pack $w.msg -side top
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+canvas $c -relief raised -width 450 -height 300
+pack $w.c -side top -fill x
+
+set plotFont {Helvetica 18}
+
+$c create line 100 250 400 250 -width 2
+$c create line 100 250 100 50 -width 2
+$c create text 225 20 -text "A Simple Plot" -font $plotFont -fill brown
+
+for {set i 0} {$i <= 10} {incr i} {
+ set x [expr {100 + ($i*30)}]
+ $c create line $x 250 $x 245 -width 2
+ $c create text $x 254 -text [expr {10*$i}] -anchor n -font $plotFont
+}
+for {set i 0} {$i <= 5} {incr i} {
+ set y [expr {250 - ($i*40)}]
+ $c create line 100 $y 105 $y -width 2
+ $c create text 96 $y -text [expr {$i*50}].0 -anchor e -font $plotFont
+}
+
+foreach point {
+ {12 56} {20 94} {33 98} {32 120} {61 180} {75 160} {98 223}
+} {
+ set x [expr {100 + (3*[lindex $point 0])}]
+ set y [expr {250 - (4*[lindex $point 1])/5}]
+ set item [$c create oval [expr {$x-6}] [expr {$y-6}] \
+ [expr {$x+6}] [expr {$y+6}] -width 1 -outline black \
+ -fill SkyBlue2]
+ $c addtag point withtag $item
+}
+
+$c bind point <Any-Enter> "$c itemconfig current -fill red"
+$c bind point <Any-Leave> "$c itemconfig current -fill SkyBlue2"
+$c bind point <1> "plotDown $c %x %y"
+$c bind point <ButtonRelease-1> "$c dtag selected"
+bind $c <B1-Motion> "plotMove $c %x %y"
+
+set plot(lastX) 0
+set plot(lastY) 0
+
+# plotDown --
+# This procedure is invoked when the mouse is pressed over one of the
+# data points. It sets up state to allow the point to be dragged.
+#
+# Arguments:
+# w - The canvas window.
+# x, y - The coordinates of the mouse press.
+
+proc plotDown {w x y} {
+ global plot
+ $w dtag selected
+ $w addtag selected withtag current
+ $w raise current
+ set plot(lastX) $x
+ set plot(lastY) $y
+}
+
+# plotMove --
+# This procedure is invoked during mouse motion events. It drags the
+# current item.
+#
+# Arguments:
+# w - The canvas window.
+# x, y - The coordinates of the mouse.
+
+proc plotMove {w x y} {
+ global plot
+ $w move selected [expr {$x-$plot(lastX)}] [expr {$y-$plot(lastY)}]
+ set plot(lastX) $x
+ set plot(lastY) $y
+}
diff --git a/tk8.6/library/demos/puzzle.tcl b/tk8.6/library/demos/puzzle.tcl
new file mode 100644
index 0000000..eebe87a
--- /dev/null
+++ b/tk8.6/library/demos/puzzle.tcl
@@ -0,0 +1,82 @@
+# puzzle.tcl --
+#
+# This demonstration script creates a 15-puzzle game using a collection
+# of buttons.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+# puzzleSwitch --
+# This procedure is invoked when the user clicks on a particular button;
+# if the button is next to the empty space, it moves the button into th
+# empty space.
+
+proc puzzleSwitch {w num} {
+ global xpos ypos
+ if {(($ypos($num) >= ($ypos(space) - .01))
+ && ($ypos($num) <= ($ypos(space) + .01))
+ && ($xpos($num) >= ($xpos(space) - .26))
+ && ($xpos($num) <= ($xpos(space) + .26)))
+ || (($xpos($num) >= ($xpos(space) - .01))
+ && ($xpos($num) <= ($xpos(space) + .01))
+ && ($ypos($num) >= ($ypos(space) - .26))
+ && ($ypos($num) <= ($ypos(space) + .26)))} {
+ set tmp $xpos(space)
+ set xpos(space) $xpos($num)
+ set xpos($num) $tmp
+ set tmp $ypos(space)
+ set ypos(space) $ypos($num)
+ set ypos($num) $tmp
+ place $w.frame.$num -relx $xpos($num) -rely $ypos($num)
+ }
+}
+
+set w .puzzle
+catch {destroy $w}
+toplevel $w
+wm title $w "15-Puzzle Demonstration"
+wm iconname $w "15-Puzzle"
+positionWindow $w
+
+label $w.msg -font $font -wraplength 4i -justify left -text "A 15-puzzle appears below as a collection of buttons. Click on any of the pieces next to the space, and that piece will slide over the space. Continue this until the pieces are arranged in numerical order from upper-left to lower-right."
+pack $w.msg -side top
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+# Special trick: select a darker color for the space by creating a
+# scrollbar widget and using its trough color.
+
+scrollbar $w.s
+
+# The button metrics are a bit bigger in Aqua, and since we are
+# using place which doesn't autosize, then we need to have a
+# slightly larger frame here...
+
+if {[tk windowingsystem] eq "aqua"} {
+ set frameSize 168
+} else {
+ set frameSize 120
+}
+
+frame $w.frame -width $frameSize -height $frameSize -borderwidth 2\
+ -relief sunken -bg [$w.s cget -troughcolor]
+pack $w.frame -side top -pady 1c -padx 1c
+destroy $w.s
+
+set order {3 1 6 2 5 7 15 13 4 11 8 9 14 10 12}
+for {set i 0} {$i < 15} {set i [expr {$i+1}]} {
+ set num [lindex $order $i]
+ set xpos($num) [expr {($i%4)*.25}]
+ set ypos($num) [expr {($i/4)*.25}]
+ button $w.frame.$num -relief raised -text $num -bd 0 -highlightthickness 0 \
+ -command "puzzleSwitch $w $num"
+ place $w.frame.$num -relx $xpos($num) -rely $ypos($num) \
+ -relwidth .25 -relheight .25
+}
+set xpos(space) .75
+set ypos(space) .75
diff --git a/tk8.6/library/demos/radio.tcl b/tk8.6/library/demos/radio.tcl
new file mode 100644
index 0000000..5c73703
--- /dev/null
+++ b/tk8.6/library/demos/radio.tcl
@@ -0,0 +1,66 @@
+# radio.tcl --
+#
+# This demonstration script creates a toplevel window containing
+# several radiobutton widgets.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .radio
+catch {destroy $w}
+toplevel $w
+wm title $w "Radiobutton Demonstration"
+wm iconname $w "radio"
+positionWindow $w
+label $w.msg -font $font -wraplength 5i -justify left -text "Three groups of radiobuttons are displayed below. If you click on a button then the button will become selected exclusively among all the buttons in its group. A Tcl variable is associated with each group to indicate which of the group's buttons is selected. When the 'Tristate' button is pressed, the radio buttons will display the tri-state mode. Selecting any radio button will return the buttons to their respective on/off state. Click the \"See Variables\" button to see the current values of the variables."
+grid $w.msg -row 0 -column 0 -columnspan 3 -sticky nsew
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w [list size color align]]
+grid $btns -row 3 -column 0 -columnspan 3 -sticky ew
+
+labelframe $w.left -pady 2 -text "Point Size" -padx 2
+labelframe $w.mid -pady 2 -text "Color" -padx 2
+labelframe $w.right -pady 2 -text "Alignment" -padx 2
+button $w.tristate -text Tristate -command "set size multi; set color multi" \
+ -pady 2 -padx 2
+if {[tk windowingsystem] eq "aqua"} {
+ $w.tristate configure -padx 10
+}
+grid $w.left -column 0 -row 1 -pady .5c -padx .5c -rowspan 2
+grid $w.mid -column 1 -row 1 -pady .5c -padx .5c -rowspan 2
+grid $w.right -column 2 -row 1 -pady .5c -padx .5c
+grid $w.tristate -column 2 -row 2 -pady .5c -padx .5c
+
+foreach i {10 12 14 18 24} {
+ radiobutton $w.left.b$i -text "Point Size $i" -variable size \
+ -relief flat -value $i -tristatevalue "multi"
+ pack $w.left.b$i -side top -pady 2 -anchor w -fill x
+}
+
+foreach c {Red Green Blue Yellow Orange Purple} {
+ set lower [string tolower $c]
+ radiobutton $w.mid.$lower -text $c -variable color \
+ -relief flat -value $lower -anchor w \
+ -command "$w.mid configure -fg \$color" \
+ -tristatevalue "multi"
+ pack $w.mid.$lower -side top -pady 2 -fill x
+}
+
+
+label $w.right.l -text "Label" -bitmap questhead -compound left
+$w.right.l configure -width [winfo reqwidth $w.right.l] -compound top
+$w.right.l configure -height [winfo reqheight $w.right.l]
+foreach a {Top Left Right Bottom} {
+ set lower [string tolower $a]
+ radiobutton $w.right.$lower -text $a -variable align \
+ -relief flat -value $lower -indicatoron 0 -width 7 \
+ -command "$w.right.l configure -compound \$align"
+}
+
+grid x $w.right.top
+grid $w.right.left $w.right.l $w.right.right
+grid x $w.right.bottom
diff --git a/tk8.6/library/demos/rmt b/tk8.6/library/demos/rmt
new file mode 100644
index 0000000..00bdc9d
--- /dev/null
+++ b/tk8.6/library/demos/rmt
@@ -0,0 +1,210 @@
+#!/bin/sh
+# the next line restarts using wish \
+exec wish "$0" ${1+"$@"}
+
+# rmt --
+# This script implements a simple remote-control mechanism for
+# Tk applications. It allows you to select an application and
+# then type commands to that application.
+
+package require Tk
+
+wm title . "Tk Remote Controller"
+wm iconname . "Tk Remote"
+wm minsize . 1 1
+
+# The global variable below keeps track of the remote application
+# that we're sending to. If it's an empty string then we execute
+# the commands locally.
+
+set app "local"
+
+# The global variable below keeps track of whether we're in the
+# middle of executing a command entered via the text.
+
+set executing 0
+
+# The global variable below keeps track of the last command executed,
+# so it can be re-executed in response to !! commands.
+
+set lastCommand ""
+
+# Create menu bar. Arrange to recreate all the information in the
+# applications sub-menu whenever it is cascaded to.
+
+. configure -menu [menu .menu]
+menu .menu.file
+menu .menu.file.apps -postcommand fillAppsMenu
+.menu add cascade -label "File" -underline 0 -menu .menu.file
+.menu.file add cascade -label "Select Application" -underline 0 \
+ -menu .menu.file.apps
+.menu.file add command -label "Quit" -command "destroy ." -underline 0
+
+# Create text window and scrollbar.
+
+text .t -yscrollcommand ".s set" -setgrid true
+scrollbar .s -command ".t yview"
+grid .t .s -sticky nsew
+grid rowconfigure . 0 -weight 1
+grid columnconfigure . 0 -weight 1
+
+# Create a binding to forward commands to the target application,
+# plus modify many of the built-in bindings so that only information
+# in the current command can be deleted (can still set the cursor
+# earlier in the text and select and insert; just can't delete).
+
+bindtags .t {.t Text . all}
+bind .t <Return> {
+ .t mark set insert {end - 1c}
+ .t insert insert \n
+ invoke
+ break
+}
+bind .t <Delete> {
+ catch {.t tag remove sel sel.first promptEnd}
+ if {[.t tag nextrange sel 1.0 end] eq ""} {
+ if {[.t compare insert < promptEnd]} {
+ break
+ }
+ }
+}
+bind .t <BackSpace> {
+ catch {.t tag remove sel sel.first promptEnd}
+ if {[.t tag nextrange sel 1.0 end] eq ""} {
+ if {[.t compare insert <= promptEnd]} {
+ break
+ }
+ }
+}
+bind .t <Control-d> {
+ if {[.t compare insert < promptEnd]} {
+ break
+ }
+}
+bind .t <Control-k> {
+ if {[.t compare insert < promptEnd]} {
+ .t mark set insert promptEnd
+ }
+}
+bind .t <Control-t> {
+ if {[.t compare insert < promptEnd]} {
+ break
+ }
+}
+bind .t <Meta-d> {
+ if {[.t compare insert < promptEnd]} {
+ break
+ }
+}
+bind .t <Meta-BackSpace> {
+ if {[.t compare insert <= promptEnd]} {
+ break
+ }
+}
+bind .t <Control-h> {
+ if {[.t compare insert <= promptEnd]} {
+ break
+ }
+}
+### This next bit *isn't* nice - DKF ###
+auto_load tk::TextInsert
+proc tk::TextInsert {w s} {
+ if {$s eq ""} {
+ return
+ }
+ catch {
+ if {
+ [$w compare sel.first <= insert] && [$w compare sel.last >= insert]
+ } then {
+ $w tag remove sel sel.first promptEnd
+ $w delete sel.first sel.last
+ }
+ }
+ $w insert insert $s
+ $w see insert
+}
+
+.t configure -font {Courier 12}
+.t tag configure bold -font {Courier 12 bold}
+
+# The procedure below is used to print out a prompt at the
+# insertion point (which should be at the beginning of a line
+# right now).
+
+proc prompt {} {
+ global app
+ .t insert insert "$app: "
+ .t mark set promptEnd {insert}
+ .t mark gravity promptEnd left
+ .t tag add bold {promptEnd linestart} promptEnd
+}
+
+# The procedure below executes a command (it takes everything on the
+# current line after the prompt and either sends it to the remote
+# application or executes it locally, depending on "app".
+
+proc invoke {} {
+ global app executing lastCommand
+ set cmd [.t get promptEnd insert]
+ incr executing 1
+ if {[info complete $cmd]} {
+ if {$cmd eq "!!\n"} {
+ set cmd $lastCommand
+ } else {
+ set lastCommand $cmd
+ }
+ if {$app eq "local"} {
+ set result [catch [list uplevel #0 $cmd] msg]
+ } else {
+ set result [catch [list send $app $cmd] msg]
+ }
+ if {$result != 0} {
+ .t insert insert "Error: $msg\n"
+ } elseif {$msg ne ""} {
+ .t insert insert $msg\n
+ }
+ prompt
+ .t mark set promptEnd insert
+ }
+ incr executing -1
+ .t yview -pickplace insert
+}
+
+# The following procedure is invoked to change the application that
+# we're talking to. It also updates the prompt for the current
+# command, unless we're in the middle of executing a command from
+# the text item (in which case a new prompt is about to be output
+# so there's no need to change the old one).
+
+proc newApp appName {
+ global app executing
+ set app $appName
+ if {!$executing} {
+ .t mark gravity promptEnd right
+ .t delete "promptEnd linestart" promptEnd
+ .t insert promptEnd "$appName: "
+ .t tag add bold "promptEnd linestart" promptEnd
+ .t mark gravity promptEnd left
+ }
+ return
+}
+
+# The procedure below will fill in the applications sub-menu with a list
+# of all the applications that currently exist.
+
+proc fillAppsMenu {} {
+ set m .menu.file.apps
+ catch {$m delete 0 last}
+ foreach i [lsort [winfo interps]] {
+ $m add command -label $i -command [list newApp $i]
+ }
+ $m add command -label local -command {newApp local}
+}
+
+set app [winfo name .]
+prompt
+focus .t
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tk8.6/library/demos/rolodex b/tk8.6/library/demos/rolodex
new file mode 100644
index 0000000..8941570
--- /dev/null
+++ b/tk8.6/library/demos/rolodex
@@ -0,0 +1,204 @@
+#!/bin/sh
+# the next line restarts using wish \
+exec wish "$0" ${1+"$@"}
+
+# rolodex --
+# This script was written as an entry in Tom LaStrange's rolodex
+# benchmark. It creates something that has some of the look and
+# feel of a rolodex program, although it's lifeless and doesn't
+# actually do the rolodex application.
+
+package require Tk
+
+foreach i [winfo child .] {
+ catch {destroy $i}
+}
+
+set version 1.2
+
+#------------------------------------------
+# Phase 0: create the front end.
+#------------------------------------------
+
+frame .frame -relief flat
+pack .frame -side top -fill y -anchor center
+
+set names {{} Name: Address: {} {} {Home Phone:} {Work Phone:} Fax:}
+foreach i {1 2 3 4 5 6 7} {
+ label .frame.label$i -text [lindex $names $i] -anchor e
+ entry .frame.entry$i -width 35
+ grid .frame.label$i .frame.entry$i -sticky ew -pady 2 -padx 1
+}
+
+frame .buttons
+pack .buttons -side bottom -pady 2 -anchor center
+button .buttons.clear -text Clear
+button .buttons.add -text Add
+button .buttons.search -text Search
+button .buttons.delete -text "Delete ..."
+pack .buttons.clear .buttons.add .buttons.search .buttons.delete \
+ -side left -padx 2
+
+#------------------------------------------
+# Phase 1: Add menus, dialog boxes
+#------------------------------------------
+
+# DKF - note that this is an old-style menu bar; I just have not yet
+# got around to converting the context help code to work with the new
+# menu system and its <<MenuSelect>> virtual event.
+
+frame .menu -relief raised -borderwidth 1
+pack .menu -before .frame -side top -fill x
+
+menubutton .menu.file -text "File" -menu .menu.file.m -underline 0
+menu .menu.file.m
+.menu.file.m add command -label "Load ..." -command fileAction -underline 0
+.menu.file.m add command -label "Exit" -command {destroy .} -underline 0
+pack .menu.file -side left
+
+menubutton .menu.help -text "Help" -menu .menu.help.m -underline 0
+menu .menu.help.m
+pack .menu.help -side right
+
+proc deleteAction {} {
+ if {[tk_dialog .delete {Confirm Action} {Are you sure?} {} 0 Cancel]
+ == 0} {
+ clearAction
+ }
+}
+.buttons.delete config -command deleteAction
+
+proc fileAction {} {
+ tk_dialog .fileSelection {File Selection} {This is a dummy file selection dialog box, which is used because there isn't a good file selection dialog built into Tk yet.} {} 0 OK
+ puts stderr {dummy file name}
+}
+
+#------------------------------------------
+# Phase 3: Print contents of card
+#------------------------------------------
+
+proc addAction {} {
+ global names
+ foreach i {1 2 3 4 5 6 7} {
+ puts stderr [format "%-12s %s" [lindex $names $i] [.frame.entry$i get]]
+ }
+}
+.buttons.add config -command addAction
+
+#------------------------------------------
+# Phase 4: Miscellaneous other actions
+#------------------------------------------
+
+proc clearAction {} {
+ foreach i {1 2 3 4 5 6 7} {
+ .frame.entry$i delete 0 end
+ }
+}
+.buttons.clear config -command clearAction
+
+proc fillCard {} {
+ clearAction
+ .frame.entry1 insert 0 "John Ousterhout"
+ .frame.entry2 insert 0 "CS Division, Department of EECS"
+ .frame.entry3 insert 0 "University of California"
+ .frame.entry4 insert 0 "Berkeley, CA 94720"
+ .frame.entry5 insert 0 "private"
+ .frame.entry6 insert 0 "510-642-0865"
+ .frame.entry7 insert 0 "510-642-5775"
+}
+.buttons.search config -command "addAction; fillCard"
+
+#----------------------------------------------------
+# Phase 5: Accelerators, mnemonics, command-line info
+#----------------------------------------------------
+
+.buttons.clear config -text "Clear Ctrl+C"
+bind . <Control-c> clearAction
+.buttons.add config -text "Add Ctrl+A"
+bind . <Control-a> addAction
+.buttons.search config -text "Search Ctrl+S"
+bind . <Control-s> "addAction; fillCard"
+.buttons.delete config -text "Delete... Ctrl+D"
+bind . <Control-d> deleteAction
+
+.menu.file.m entryconfig 1 -accel Ctrl+F
+bind . <Control-f> fileAction
+.menu.file.m entryconfig 2 -accel Ctrl+Q
+bind . <Control-q> {destroy .}
+
+focus .frame.entry1
+
+#----------------------------------------------------
+# Phase 6: help
+#----------------------------------------------------
+
+proc Help {topic {x 0} {y 0}} {
+ global helpTopics helpCmds
+ if {$topic == ""} return
+ while {[info exists helpCmds($topic)]} {
+ set topic [eval $helpCmds($topic)]
+ }
+ if [info exists helpTopics($topic)] {
+ set msg $helpTopics($topic)
+ } else {
+ set msg "Sorry, but no help is available for this topic"
+ }
+ tk_dialog .help {Rolodex Help} "Information on $topic:\n\n$msg" \
+ {} 0 OK
+}
+
+proc getMenuTopic {w x y} {
+ return $w.[$w index @[expr {$y-[winfo rooty $w]}]]
+}
+
+event add <<Help>> <F1> <Help>
+bind . <<Help>> {Help [winfo containing %X %Y] %X %Y}
+bind Menu <<Help>> {Help [winfo containing %X %Y] %X %Y}
+
+# Help text and commands follow:
+
+set helpTopics(.menu.file) {This is the "file" menu. It can be used to invoke some overall operations on the rolodex applications, such as loading a file or exiting.}
+
+set helpCmds(.menu.file.m) {getMenuTopic $topic $x $y}
+set helpTopics(.menu.file.m.1) {The "Load" entry in the "File" menu posts a dialog box that you can use to select a rolodex file}
+set helpTopics(.menu.file.m.2) {The "Exit" entry in the "File" menu causes the rolodex application to terminate}
+set helpCmds(.menu.file.m.none) {set topic ".menu.file"}
+
+set helpTopics(.frame.entry1) {In this field of the rolodex entry you should type the person's name}
+set helpTopics(.frame.entry2) {In this field of the rolodex entry you should type the first line of the person's address}
+set helpTopics(.frame.entry3) {In this field of the rolodex entry you should type the second line of the person's address}
+set helpTopics(.frame.entry4) {In this field of the rolodex entry you should type the third line of the person's address}
+set helpTopics(.frame.entry5) {In this field of the rolodex entry you should type the person's home phone number, or "private" if the person doesn't want his or her number publicized}
+set helpTopics(.frame.entry6) {In this field of the rolodex entry you should type the person's work phone number}
+set helpTopics(.frame.entry7) {In this field of the rolodex entry you should type the phone number for the person's FAX machine}
+
+set helpCmds(.frame.label1) {set topic .frame.entry1}
+set helpCmds(.frame.label2) {set topic .frame.entry2}
+set helpCmds(.frame.label3) {set topic .frame.entry3}
+set helpCmds(.frame.label4) {set topic .frame.entry4}
+set helpCmds(.frame.label5) {set topic .frame.entry5}
+set helpCmds(.frame.label6) {set topic .frame.entry6}
+set helpCmds(.frame.label7) {set topic .frame.entry7}
+
+set helpTopics(context) {Unfortunately, this application doesn't support context-sensitive help in the usual way, because when this demo was written Tk didn't have a grab mechanism and this is needed for context-sensitive help. Instead, you can achieve much the same effect by simply moving the mouse over the window you're curious about and pressing the Help or F1 keys. You can do this anytime.}
+set helpTopics(help) {This application provides only very crude help. Besides the entries in this menu, you can get help on individual windows by moving the mouse cursor over the window and pressing the Help or F1 keys.}
+set helpTopics(window) {This window is a dummy rolodex application created as part of Tom LaStrange's toolkit benchmark. It doesn't really do anything useful except to demonstrate a few features of the Tk toolkit.}
+set helpTopics(keys) "The following accelerator keys are defined for this application (in addition to those already available for the entry windows):\n\nCtrl+A:\t\tAdd\nCtrl+C:\t\tClear\nCtrl+D:\t\tDelete\nCtrl+F:\t\tEnter file name\nCtrl+Q:\t\tExit application (quit)\nCtrl+S:\t\tSearch (dummy operation)"
+set helpTopics(version) "This is version $version."
+
+# Entries in "Help" menu
+
+.menu.help.m add command -label "On Context..." -command {Help context} \
+ -underline 3
+.menu.help.m add command -label "On Help..." -command {Help help} \
+ -underline 3
+.menu.help.m add command -label "On Window..." -command {Help window} \
+ -underline 3
+.menu.help.m add command -label "On Keys..." -command {Help keys} \
+ -underline 3
+.menu.help.m add command -label "On Version..." -command {Help version} \
+ -underline 3
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tk8.6/library/demos/ruler.tcl b/tk8.6/library/demos/ruler.tcl
new file mode 100644
index 0000000..557b680
--- /dev/null
+++ b/tk8.6/library/demos/ruler.tcl
@@ -0,0 +1,171 @@
+# ruler.tcl --
+#
+# This demonstration script creates a canvas widget that displays a ruler
+# with tab stops that can be set, moved, and deleted.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+# rulerMkTab --
+# This procedure creates a new triangular polygon in a canvas to
+# represent a tab stop.
+#
+# Arguments:
+# c - The canvas window.
+# x, y - Coordinates at which to create the tab stop.
+
+proc rulerMkTab {c x y} {
+ upvar #0 demo_rulerInfo v
+ $c create polygon $x $y [expr {$x+$v(size)}] [expr {$y+$v(size)}] \
+ [expr {$x-$v(size)}] [expr {$y+$v(size)}]
+}
+
+set w .ruler
+catch {destroy $w}
+toplevel $w
+wm title $w "Ruler Demonstration"
+wm iconname $w "ruler"
+positionWindow $w
+set c $w.c
+
+label $w.msg -font $font -wraplength 5i -justify left -text "This canvas widget shows a mock-up of a ruler. You can create tab stops by dragging them out of the well to the right of the ruler. You can also drag existing tab stops. If you drag a tab stop far enough up or down so that it turns dim, it will be deleted when you release the mouse button."
+pack $w.msg -side top
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+canvas $c -width 14.8c -height 2.5c
+pack $w.c -side top -fill x
+
+set demo_rulerInfo(grid) .25c
+set demo_rulerInfo(left) [winfo fpixels $c 1c]
+set demo_rulerInfo(right) [winfo fpixels $c 13c]
+set demo_rulerInfo(top) [winfo fpixels $c 1c]
+set demo_rulerInfo(bottom) [winfo fpixels $c 1.5c]
+set demo_rulerInfo(size) [winfo fpixels $c .2c]
+set demo_rulerInfo(normalStyle) "-fill black"
+# Main widget program sets variable tk_demoDirectory
+if {[winfo depth $c] > 1} {
+ set demo_rulerInfo(activeStyle) "-fill red -stipple {}"
+ set demo_rulerInfo(deleteStyle) [list -fill red \
+ -stipple @[file join $tk_demoDirectory images gray25.xbm]]
+} else {
+ set demo_rulerInfo(activeStyle) "-fill black -stipple {}"
+ set demo_rulerInfo(deleteStyle) [list -fill black \
+ -stipple @[file join $tk_demoDirectory images gray25.xbm]]
+}
+
+$c create line 1c 0.5c 1c 1c 13c 1c 13c 0.5c -width 1
+for {set i 0} {$i < 12} {incr i} {
+ set x [expr {$i+1}]
+ $c create line ${x}c 1c ${x}c 0.6c -width 1
+ $c create line $x.25c 1c $x.25c 0.8c -width 1
+ $c create line $x.5c 1c $x.5c 0.7c -width 1
+ $c create line $x.75c 1c $x.75c 0.8c -width 1
+ $c create text $x.15c .75c -text $i -anchor sw
+}
+$c addtag well withtag [$c create rect 13.2c 1c 13.8c 0.5c \
+ -outline black -fill [lindex [$c config -bg] 4]]
+$c addtag well withtag [rulerMkTab $c [winfo pixels $c 13.5c] \
+ [winfo pixels $c .65c]]
+
+$c bind well <1> "rulerNewTab $c %x %y"
+$c bind tab <1> "rulerSelectTab $c %x %y"
+bind $c <B1-Motion> "rulerMoveTab $c %x %y"
+bind $c <Any-ButtonRelease-1> "rulerReleaseTab $c"
+
+# rulerNewTab --
+# Does all the work of creating a tab stop, including creating the
+# triangle object and adding tags to it to give it tab behavior.
+#
+# Arguments:
+# c - The canvas window.
+# x, y - The coordinates of the tab stop.
+
+proc rulerNewTab {c x y} {
+ upvar #0 demo_rulerInfo v
+ $c addtag active withtag [rulerMkTab $c $x $y]
+ $c addtag tab withtag active
+ set v(x) $x
+ set v(y) $y
+ rulerMoveTab $c $x $y
+}
+
+# rulerSelectTab --
+# This procedure is invoked when mouse button 1 is pressed over
+# a tab. It remembers information about the tab so that it can
+# be dragged interactively.
+#
+# Arguments:
+# c - The canvas widget.
+# x, y - The coordinates of the mouse (identifies the point by
+# which the tab was picked up for dragging).
+
+proc rulerSelectTab {c x y} {
+ upvar #0 demo_rulerInfo v
+ set v(x) [$c canvasx $x $v(grid)]
+ set v(y) [expr {$v(top)+2}]
+ $c addtag active withtag current
+ eval "$c itemconf active $v(activeStyle)"
+ $c raise active
+}
+
+# rulerMoveTab --
+# This procedure is invoked during mouse motion events to drag a tab.
+# It adjusts the position of the tab, and changes its appearance if
+# it is about to be dragged out of the ruler.
+#
+# Arguments:
+# c - The canvas widget.
+# x, y - The coordinates of the mouse.
+
+proc rulerMoveTab {c x y} {
+ upvar #0 demo_rulerInfo v
+ if {[$c find withtag active] == ""} {
+ return
+ }
+ set cx [$c canvasx $x $v(grid)]
+ set cy [$c canvasy $y]
+ if {$cx < $v(left)} {
+ set cx $v(left)
+ }
+ if {$cx > $v(right)} {
+ set cx $v(right)
+ }
+ if {($cy >= $v(top)) && ($cy <= $v(bottom))} {
+ set cy [expr {$v(top)+2}]
+ eval "$c itemconf active $v(activeStyle)"
+ } else {
+ set cy [expr {$cy-$v(size)-2}]
+ eval "$c itemconf active $v(deleteStyle)"
+ }
+ $c move active [expr {$cx-$v(x)}] [expr {$cy-$v(y)}]
+ set v(x) $cx
+ set v(y) $cy
+}
+
+# rulerReleaseTab --
+# This procedure is invoked during button release events that end
+# a tab drag operation. It deselects the tab and deletes the tab if
+# it was dragged out of the ruler.
+#
+# Arguments:
+# c - The canvas widget.
+# x, y - The coordinates of the mouse.
+
+proc rulerReleaseTab c {
+ upvar #0 demo_rulerInfo v
+ if {[$c find withtag active] == {}} {
+ return
+ }
+ if {$v(y) != $v(top)+2} {
+ $c delete active
+ } else {
+ eval "$c itemconf active $v(normalStyle)"
+ $c dtag active
+ }
+}
diff --git a/tk8.6/library/demos/sayings.tcl b/tk8.6/library/demos/sayings.tcl
new file mode 100644
index 0000000..aa3479c
--- /dev/null
+++ b/tk8.6/library/demos/sayings.tcl
@@ -0,0 +1,44 @@
+# sayings.tcl --
+#
+# This demonstration script creates a listbox that can be scrolled
+# both horizontally and vertically. It displays a collection of
+# well-known sayings.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .sayings
+catch {destroy $w}
+toplevel $w
+wm title $w "Listbox Demonstration (well-known sayings)"
+wm iconname $w "sayings"
+positionWindow $w
+
+label $w.msg -font $font -wraplength 4i -justify left -text "The listbox below contains a collection of well-known sayings. You can scan the list using either of the scrollbars or by dragging in the listbox window with button 2 pressed."
+pack $w.msg -side top
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+frame $w.frame -borderwidth 10
+pack $w.frame -side top -expand yes -fill both -padx 1c
+
+
+ttk::scrollbar $w.frame.yscroll -command "$w.frame.list yview"
+ttk::scrollbar $w.frame.xscroll -orient horizontal \
+ -command "$w.frame.list xview"
+listbox $w.frame.list -width 20 -height 10 -setgrid 1 \
+ -yscroll "$w.frame.yscroll set" -xscroll "$w.frame.xscroll set"
+
+grid $w.frame.list -row 0 -column 0 -rowspan 1 -columnspan 1 -sticky news
+grid $w.frame.yscroll -row 0 -column 1 -rowspan 1 -columnspan 1 -sticky news
+grid $w.frame.xscroll -row 1 -column 0 -rowspan 1 -columnspan 1 -sticky news
+grid rowconfig $w.frame 0 -weight 1 -minsize 0
+grid columnconfig $w.frame 0 -weight 1 -minsize 0
+
+
+$w.frame.list insert 0 "Don't speculate, measure" "Waste not, want not" "Early to bed and early to rise makes a man healthy, wealthy, and wise" "Ask not what your country can do for you, ask what you can do for your country" "I shall return" "NOT" "A picture is worth a thousand words" "User interfaces are hard to build" "Thou shalt not steal" "A penny for your thoughts" "Fool me once, shame on you; fool me twice, shame on me" "Every cloud has a silver lining" "Where there's smoke there's fire" "It takes one to know one" "Curiosity killed the cat" "Take this job and shove it" "Up a creek without a paddle" "I'm mad as hell and I'm not going to take it any more" "An apple a day keeps the doctor away" "Don't look a gift horse in the mouth" "Measure twice, cut once"
diff --git a/tk8.6/library/demos/search.tcl b/tk8.6/library/demos/search.tcl
new file mode 100644
index 0000000..a1a3d7f
--- /dev/null
+++ b/tk8.6/library/demos/search.tcl
@@ -0,0 +1,139 @@
+# search.tcl --
+#
+# This demonstration script creates a collection of widgets that
+# allow you to load a file into a text widget, then perform searches
+# on that file.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+# textLoadFile --
+# This procedure below loads a file into a text widget, discarding
+# the previous contents of the widget. Tags for the old widget are
+# not affected, however.
+#
+# Arguments:
+# w - The window into which to load the file. Must be a
+# text widget.
+# file - The name of the file to load. Must be readable.
+
+proc textLoadFile {w file} {
+ set f [open $file]
+ $w delete 1.0 end
+ while {![eof $f]} {
+ $w insert end [read $f 10000]
+ }
+ close $f
+}
+
+# textSearch --
+# Search for all instances of a given string in a text widget and
+# apply a given tag to each instance found.
+#
+# Arguments:
+# w - The window in which to search. Must be a text widget.
+# string - The string to search for. The search is done using
+# exact matching only; no special characters.
+# tag - Tag to apply to each instance of a matching string.
+
+proc textSearch {w string tag} {
+ $w tag remove search 0.0 end
+ if {$string == ""} {
+ return
+ }
+ set cur 1.0
+ while 1 {
+ set cur [$w search -count length $string $cur end]
+ if {$cur == ""} {
+ break
+ }
+ $w tag add $tag $cur "$cur + $length char"
+ set cur [$w index "$cur + $length char"]
+ }
+}
+
+# textToggle --
+# This procedure is invoked repeatedly to invoke two commands at
+# periodic intervals. It normally reschedules itself after each
+# execution but if an error occurs (e.g. because the window was
+# deleted) then it doesn't reschedule itself.
+#
+# Arguments:
+# cmd1 - Command to execute when procedure is called.
+# sleep1 - Ms to sleep after executing cmd1 before executing cmd2.
+# cmd2 - Command to execute in the *next* invocation of this
+# procedure.
+# sleep2 - Ms to sleep after executing cmd2 before executing cmd1 again.
+
+proc textToggle {cmd1 sleep1 cmd2 sleep2} {
+ catch {
+ eval $cmd1
+ after $sleep1 [list textToggle $cmd2 $sleep2 $cmd1 $sleep1]
+ }
+}
+
+set w .search
+catch {destroy $w}
+toplevel $w
+wm title $w "Text Demonstration - Search and Highlight"
+wm iconname $w "search"
+positionWindow $w
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+frame $w.file
+label $w.file.label -text "File name:" -width 13 -anchor w
+entry $w.file.entry -width 40 -textvariable fileName
+button $w.file.button -text "Load File" \
+ -command "textLoadFile $w.text \$fileName"
+pack $w.file.label $w.file.entry -side left
+pack $w.file.button -side left -pady 5 -padx 10
+bind $w.file.entry <Return> "
+ textLoadFile $w.text \$fileName
+ focus $w.string.entry
+"
+focus $w.file.entry
+
+frame $w.string
+label $w.string.label -text "Search string:" -width 13 -anchor w
+entry $w.string.entry -width 40 -textvariable searchString
+button $w.string.button -text "Highlight" \
+ -command "textSearch $w.text \$searchString search"
+pack $w.string.label $w.string.entry -side left
+pack $w.string.button -side left -pady 5 -padx 10
+bind $w.string.entry <Return> "textSearch $w.text \$searchString search"
+
+text $w.text -yscrollcommand "$w.scroll set" -setgrid true
+ttk::scrollbar $w.scroll -command "$w.text yview"
+pack $w.file $w.string -side top -fill x
+pack $w.scroll -side right -fill y
+pack $w.text -expand yes -fill both
+
+# Set up display styles for text highlighting.
+
+if {[winfo depth $w] > 1} {
+ textToggle "$w.text tag configure search -background \
+ #ce5555 -foreground white" 800 "$w.text tag configure \
+ search -background {} -foreground {}" 200
+} else {
+ textToggle "$w.text tag configure search -background \
+ black -foreground white" 800 "$w.text tag configure \
+ search -background {} -foreground {}" 200
+}
+$w.text insert 1.0 \
+{This window demonstrates how to use the tagging facilities in text
+widgets to implement a searching mechanism. First, type a file name
+in the top entry, then type <Return> or click on "Load File". Then
+type a string in the lower entry and type <Return> or click on
+"Load File". This will cause all of the instances of the string to
+be tagged with the tag "search", and it will arrange for the tag's
+display attributes to change to make all of the strings blink.}
+$w.text mark set insert 0.0
+
+set fileName ""
+set searchString ""
diff --git a/tk8.6/library/demos/spin.tcl b/tk8.6/library/demos/spin.tcl
new file mode 100644
index 0000000..d897e6d
--- /dev/null
+++ b/tk8.6/library/demos/spin.tcl
@@ -0,0 +1,53 @@
+# spin.tcl --
+#
+# This demonstration script creates several spinbox widgets.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .spin
+catch {destroy $w}
+toplevel $w
+wm title $w "Spinbox Demonstration"
+wm iconname $w "spin"
+positionWindow $w
+
+label $w.msg -font $font -wraplength 5i -justify left -text "Three different\
+ spin-boxes are displayed below. You can add characters by pointing,\
+ clicking and typing. The normal Motif editing characters are\
+ supported, along with many Emacs bindings. For example, Backspace\
+ and Control-h delete the character to the left of the insertion\
+ cursor and Delete and Control-d delete the chararacter to the right\
+ of the insertion cursor. For values that are too large to fit in the\
+ window all at once, you can scan through the value by dragging with\
+ mouse button2 pressed. Note that the first spin-box will only permit\
+ you to type in integers, and the third selects from a list of\
+ Australian cities."
+pack $w.msg -side top
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+set australianCities {
+ Canberra Sydney Melbourne Perth Adelaide Brisbane
+ Hobart Darwin "Alice Springs"
+}
+
+spinbox $w.s1 -from 1 -to 10 -width 10 -validate key \
+ -vcmd {string is integer %P}
+spinbox $w.s2 -from 0 -to 3 -increment .5 -format %05.2f -width 10
+spinbox $w.s3 -values $australianCities -width 10
+
+#entry $w.e1
+#entry $w.e2
+#entry $w.e3
+pack $w.s1 $w.s2 $w.s3 -side top -pady 5 -padx 10 ;#-fill x
+
+#$w.e1 insert 0 "Initial value"
+#$w.e2 insert end "This entry contains a long value, much too long "
+#$w.e2 insert end "to fit in the window at one time, so long in fact "
+#$w.e2 insert end "that you'll have to scan or scroll to see the end."
diff --git a/tk8.6/library/demos/square b/tk8.6/library/demos/square
new file mode 100644
index 0000000..6ce91b8
--- /dev/null
+++ b/tk8.6/library/demos/square
@@ -0,0 +1,60 @@
+#!/bin/sh
+# the next line restarts using wish \
+exec wish "$0" ${1+"$@"}
+
+# square --
+# This script generates a demo application containing only a "square"
+# widget. It's only usable in the "tktest" application or if Tk has
+# been compiled with tkSquare.c. This demo arranges the following
+# bindings for the widget:
+#
+# Button-1 press/drag: moves square to mouse
+# "a": toggle size animation on/off
+
+package require Tk ;# We use Tk generally, and...
+package require Tktest ;# ... we use the square widget too.
+
+square .s
+pack .s -expand yes -fill both
+wm minsize . 1 1
+
+bind .s <1> {center %x %y}
+bind .s <B1-Motion> {center %x %y}
+bind .s a animate
+focus .s
+
+# The procedure below centers the square on a given position.
+
+proc center {x y} {
+ set a [.s size]
+ .s position [expr {$x-($a/2)}] [expr {$y-($a/2)}]
+}
+
+# The procedures below provide a simple form of animation where
+# the box changes size in a pulsing pattern: larger, smaller, larger,
+# and so on.
+
+set inc 0
+proc animate {} {
+ global inc
+ if {$inc == 0} {
+ set inc 3
+ timer
+ } else {
+ set inc 0
+ }
+}
+
+proc timer {} {
+ global inc
+ set s [.s size]
+ if {$inc == 0} return
+ if {$s >= 40} {set inc -3}
+ if {$s <= 10} {set inc 3}
+ .s size [expr {$s+$inc}]
+ after 30 timer
+}
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tk8.6/library/demos/states.tcl b/tk8.6/library/demos/states.tcl
new file mode 100644
index 0000000..aeb3d5b
--- /dev/null
+++ b/tk8.6/library/demos/states.tcl
@@ -0,0 +1,54 @@
+# states.tcl --
+#
+# This demonstration script creates a listbox widget that displays
+# the names of the 50 states in the United States of America.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .states
+catch {destroy $w}
+toplevel $w
+wm title $w "Listbox Demonstration (50 states)"
+wm iconname $w "states"
+positionWindow $w
+
+label $w.msg -font $font -wraplength 4i -justify left -text "A listbox containing the 50 states is displayed below, along with a scrollbar. You can scan the list either using the scrollbar or by scanning. To scan, press button 2 in the widget and drag up or down."
+pack $w.msg -side top
+
+labelframe $w.justif -text Justification
+foreach c {Left Center Right} {
+ set lower [string tolower $c]
+ radiobutton $w.justif.$lower -text $c -variable just \
+ -relief flat -value $lower -anchor w \
+ -command "$w.frame.list configure -justify \$just" \
+ -tristatevalue "multi"
+ pack $w.justif.$lower -side left -pady 2 -fill x
+}
+pack $w.justif
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+frame $w.frame -borderwidth .5c
+pack $w.frame -side top -expand yes -fill y
+
+ttk::scrollbar $w.frame.scroll -command "$w.frame.list yview"
+listbox $w.frame.list -yscroll "$w.frame.scroll set" -setgrid 1 -height 12
+pack $w.frame.scroll -side right -fill y
+pack $w.frame.list -side left -expand 1 -fill both
+
+$w.frame.list insert 0 Alabama Alaska Arizona Arkansas California \
+ Colorado Connecticut Delaware Florida Georgia Hawaii Idaho Illinois \
+ Indiana Iowa Kansas Kentucky Louisiana Maine Maryland \
+ Massachusetts Michigan Minnesota Mississippi Missouri \
+ Montana Nebraska Nevada "New Hampshire" "New Jersey" "New Mexico" \
+ "New York" "North Carolina" "North Dakota" \
+ Ohio Oklahoma Oregon Pennsylvania "Rhode Island" \
+ "South Carolina" "South Dakota" \
+ Tennessee Texas Utah Vermont Virginia Washington \
+ "West Virginia" Wisconsin Wyoming
diff --git a/tk8.6/library/demos/style.tcl b/tk8.6/library/demos/style.tcl
new file mode 100644
index 0000000..a529a03
--- /dev/null
+++ b/tk8.6/library/demos/style.tcl
@@ -0,0 +1,155 @@
+# style.tcl --
+#
+# This demonstration script creates a text widget that illustrates the
+# various display styles that may be set for tags.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .style
+catch {destroy $w}
+toplevel $w
+wm title $w "Text Demonstration - Display Styles"
+wm iconname $w "style"
+positionWindow $w
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+# Only set the font family in one place for simplicity and consistency
+
+set family Courier
+
+text $w.text -yscrollcommand "$w.scroll set" -setgrid true \
+ -width 70 -height 32 -wrap word -font "$family 12"
+ttk::scrollbar $w.scroll -command "$w.text yview"
+pack $w.scroll -side right -fill y
+pack $w.text -expand yes -fill both
+
+# Set up display styles
+
+$w.text tag configure bold -font "$family 12 bold italic"
+$w.text tag configure big -font "$family 14 bold"
+$w.text tag configure verybig -font "Helvetica 24 bold"
+$w.text tag configure tiny -font "Times 8 bold"
+if {[winfo depth $w] > 1} {
+ $w.text tag configure color1 -background #a0b7ce
+ $w.text tag configure color2 -foreground red
+ $w.text tag configure raised -relief raised -borderwidth 1
+ $w.text tag configure sunken -relief sunken -borderwidth 1
+} else {
+ $w.text tag configure color1 -background black -foreground white
+ $w.text tag configure color2 -background black -foreground white
+ $w.text tag configure raised -background white -relief raised \
+ -borderwidth 1
+ $w.text tag configure sunken -background white -relief sunken \
+ -borderwidth 1
+}
+$w.text tag configure bgstipple -background black -borderwidth 0 \
+ -bgstipple gray12
+$w.text tag configure fgstipple -fgstipple gray50
+$w.text tag configure underline -underline on
+$w.text tag configure overstrike -overstrike on
+$w.text tag configure right -justify right
+$w.text tag configure center -justify center
+$w.text tag configure super -offset 4p -font "$family 10"
+$w.text tag configure sub -offset -2p -font "$family 10"
+$w.text tag configure margins -lmargin1 12m -lmargin2 6m -rmargin 10m
+$w.text tag configure spacing -spacing1 10p -spacing2 2p \
+ -lmargin1 12m -lmargin2 6m -rmargin 10m
+
+$w.text insert end {Text widgets like this one allow you to display information in a
+variety of styles. Display styles are controlled using a mechanism
+called }
+$w.text insert end tags bold
+$w.text insert end {. Tags are just textual names that you can apply to one
+or more ranges of characters within a text widget. You can configure
+tags with various display styles. If you do this, then the tagged
+characters will be displayed with the styles you chose. The
+available display styles are:
+}
+$w.text insert end "\n1. Font." big
+$w.text insert end " You can choose any system font, "
+$w.text insert end large verybig
+$w.text insert end " or "
+$w.text insert end "small" tiny ".\n"
+$w.text insert end "\n2. Color." big
+$w.text insert end " You can change either the "
+$w.text insert end background color1
+$w.text insert end " or "
+$w.text insert end foreground color2
+$w.text insert end "\ncolor, or "
+$w.text insert end both {color1 color2}
+$w.text insert end ".\n"
+$w.text insert end "\n3. Stippling." big
+$w.text insert end " You can cause either the "
+$w.text insert end background bgstipple
+$w.text insert end " or "
+$w.text insert end foreground fgstipple
+$w.text insert end {
+information to be drawn with a stipple fill instead of a solid fill.
+}
+$w.text insert end "\n4. Underlining." big
+$w.text insert end " You can "
+$w.text insert end underline underline
+$w.text insert end " ranges of text.\n"
+$w.text insert end "\n5. Overstrikes." big
+$w.text insert end " You can "
+$w.text insert end "draw lines through" overstrike
+$w.text insert end " ranges of text.\n"
+$w.text insert end "\n6. 3-D effects." big
+$w.text insert end { You can arrange for the background to be drawn
+with a border that makes characters appear either }
+$w.text insert end raised raised
+$w.text insert end " or "
+$w.text insert end sunken sunken
+$w.text insert end ".\n"
+$w.text insert end "\n7. Justification." big
+$w.text insert end " You can arrange for lines to be displayed\n"
+$w.text insert end "left-justified,\n"
+$w.text insert end "right-justified, or\n" right
+$w.text insert end "centered.\n" center
+$w.text insert end "\n8. Superscripts and subscripts." big
+$w.text insert end " You can control the vertical\n"
+$w.text insert end "position of text to generate superscript effects like 10"
+$w.text insert end "n" super
+$w.text insert end " or\nsubscript effects like X"
+$w.text insert end "i" sub
+$w.text insert end ".\n"
+$w.text insert end "\n9. Margins." big
+$w.text insert end " You can control the amount of extra space left"
+$w.text insert end " on\neach side of the text:\n"
+$w.text insert end "This paragraph is an example of the use of " margins
+$w.text insert end "margins. It consists of a single line of text " margins
+$w.text insert end "that wraps around on the screen. There are two " margins
+$w.text insert end "separate left margin values, one for the first " margins
+$w.text insert end "display line associated with the text line, " margins
+$w.text insert end "and one for the subsequent display lines, which " margins
+$w.text insert end "occur because of wrapping. There is also a " margins
+$w.text insert end "separate specification for the right margin, " margins
+$w.text insert end "which is used to choose wrap points for lines.\n" margins
+$w.text insert end "\n10. Spacing." big
+$w.text insert end " You can control the spacing of lines with three\n"
+$w.text insert end "separate parameters. \"Spacing1\" tells how much "
+$w.text insert end "extra space to leave\nabove a line, \"spacing3\" "
+$w.text insert end "tells how much space to leave below a line,\nand "
+$w.text insert end "if a text line wraps, \"spacing2\" tells how much "
+$w.text insert end "space to leave\nbetween the display lines that "
+$w.text insert end "make up the text line.\n"
+$w.text insert end "These indented paragraphs illustrate how spacing " spacing
+$w.text insert end "can be used. Each paragraph is actually a " spacing
+$w.text insert end "single line in the text widget, which is " spacing
+$w.text insert end "word-wrapped by the widget.\n" spacing
+$w.text insert end "Spacing1 is set to 10 points for this text, " spacing
+$w.text insert end "which results in relatively large gaps between " spacing
+$w.text insert end "the paragraphs. Spacing2 is set to 2 points, " spacing
+$w.text insert end "which results in just a bit of extra space " spacing
+$w.text insert end "within a pararaph. Spacing3 isn't used " spacing
+$w.text insert end "in this example.\n" spacing
+$w.text insert end "To see where the space is, select ranges of " spacing
+$w.text insert end "text within these paragraphs. The selection " spacing
+$w.text insert end "highlight will cover the extra space." spacing
diff --git a/tk8.6/library/demos/tclIndex b/tk8.6/library/demos/tclIndex
new file mode 100644
index 0000000..86a72e2
--- /dev/null
+++ b/tk8.6/library/demos/tclIndex
@@ -0,0 +1,67 @@
+# Tcl autoload index file, version 2.0
+# This file is generated by the "auto_mkindex" command
+# and sourced to set up indexing information for one or
+# more commands. Typically each line is a command that
+# sets an element in the auto_index array, where the
+# element name is the name of a command and the value is
+# a script that loads the command.
+
+set auto_index(arrowSetup) [list source [file join $dir arrow.tcl]]
+set auto_index(arrowMove1) [list source [file join $dir arrow.tcl]]
+set auto_index(arrowMove2) [list source [file join $dir arrow.tcl]]
+set auto_index(arrowMove3) [list source [file join $dir arrow.tcl]]
+set auto_index(textLoadFile) [list source [file join $dir search.tcl]]
+set auto_index(textSearch) [list source [file join $dir search.tcl]]
+set auto_index(textToggle) [list source [file join $dir search.tcl]]
+set auto_index(itemEnter) [list source [file join $dir items.tcl]]
+set auto_index(itemLeave) [list source [file join $dir items.tcl]]
+set auto_index(itemMark) [list source [file join $dir items.tcl]]
+set auto_index(itemStroke) [list source [file join $dir items.tcl]]
+set auto_index(itemsUnderArea) [list source [file join $dir items.tcl]]
+set auto_index(itemStartDrag) [list source [file join $dir items.tcl]]
+set auto_index(itemDrag) [list source [file join $dir items.tcl]]
+set auto_index(butPress) [list source [file join $dir items.tcl]]
+set auto_index(loadDir) [list source [file join $dir image2.tcl]]
+set auto_index(loadImage) [list source [file join $dir image2.tcl]]
+set auto_index(rulerMkTab) [list source [file join $dir ruler.tcl]]
+set auto_index(rulerNewTab) [list source [file join $dir ruler.tcl]]
+set auto_index(rulerSelectTab) [list source [file join $dir ruler.tcl]]
+set auto_index(rulerMoveTab) [list source [file join $dir ruler.tcl]]
+set auto_index(rulerReleaseTab) [list source [file join $dir ruler.tcl]]
+set auto_index(mkTextConfig) [list source [file join $dir ctext.tcl]]
+set auto_index(textEnter) [list source [file join $dir ctext.tcl]]
+set auto_index(textInsert) [list source [file join $dir ctext.tcl]]
+set auto_index(textPaste) [list source [file join $dir ctext.tcl]]
+set auto_index(textB1Press) [list source [file join $dir ctext.tcl]]
+set auto_index(textB1Move) [list source [file join $dir ctext.tcl]]
+set auto_index(textBs) [list source [file join $dir ctext.tcl]]
+set auto_index(textDel) [list source [file join $dir ctext.tcl]]
+set auto_index(bitmapRow) [list source [file join $dir bitmap.tcl]]
+set auto_index(scrollEnter) [list source [file join $dir cscroll.tcl]]
+set auto_index(scrollLeave) [list source [file join $dir cscroll.tcl]]
+set auto_index(scrollButton) [list source [file join $dir cscroll.tcl]]
+set auto_index(textWindOn) [list source [file join $dir twind.tcl]]
+set auto_index(textWindOff) [list source [file join $dir twind.tcl]]
+set auto_index(textWindPlot) [list source [file join $dir twind.tcl]]
+set auto_index(embPlotDown) [list source [file join $dir twind.tcl]]
+set auto_index(embPlotMove) [list source [file join $dir twind.tcl]]
+set auto_index(textWindDel) [list source [file join $dir twind.tcl]]
+set auto_index(embDefBg) [list source [file join $dir twind.tcl]]
+set auto_index(floorDisplay) [list source [file join $dir floor.tcl]]
+set auto_index(newRoom) [list source [file join $dir floor.tcl]]
+set auto_index(roomChanged) [list source [file join $dir floor.tcl]]
+set auto_index(bg1) [list source [file join $dir floor.tcl]]
+set auto_index(bg2) [list source [file join $dir floor.tcl]]
+set auto_index(bg3) [list source [file join $dir floor.tcl]]
+set auto_index(fg1) [list source [file join $dir floor.tcl]]
+set auto_index(fg2) [list source [file join $dir floor.tcl]]
+set auto_index(fg3) [list source [file join $dir floor.tcl]]
+set auto_index(setWidth) [list source [file join $dir hscale.tcl]]
+set auto_index(plotDown) [list source [file join $dir plot.tcl]]
+set auto_index(plotMove) [list source [file join $dir plot.tcl]]
+set auto_index(puzzleSwitch) [list source [file join $dir puzzle.tcl]]
+set auto_index(setHeight) [list source [file join $dir vscale.tcl]]
+set auto_index(showMessageBox) [list source [file join $dir msgbox.tcl]]
+set auto_index(setColor) [list source [file join $dir clrpick.tcl]]
+set auto_index(setColor_helper) [list source [file join $dir clrpick.tcl]]
+set auto_index(fileDialog) [list source [file join $dir filebox.tcl]]
diff --git a/tk8.6/library/demos/tcolor b/tk8.6/library/demos/tcolor
new file mode 100644
index 0000000..6e50c61
--- /dev/null
+++ b/tk8.6/library/demos/tcolor
@@ -0,0 +1,358 @@
+#!/bin/sh
+# the next line restarts using wish \
+exec wish "$0" ${1+"$@"}
+
+# tcolor --
+# This script implements a simple color editor, where you can
+# create colors using either the RGB, HSB, or CYM color spaces
+# and apply the color to existing applications.
+
+package require Tk 8.4
+wm title . "Color Editor"
+
+# Global variables that control the program:
+#
+# colorSpace - Color space currently being used for
+# editing. Must be "rgb", "cmy", or "hsb".
+# label1, label2, label3 - Labels for the scales.
+# red, green, blue - Current color intensities in decimal
+# on a scale of 0-65535.
+# color - A string giving the current color value
+# in the proper form for x:
+# #RRRRGGGGBBBB
+# updating - Non-zero means that we're in the middle of
+# updating the scales to load a new color,so
+# information shouldn't be propagating back
+# from the scales to other elements of the
+# program: this would make an infinite loop.
+# command - Holds the command that has been typed
+# into the "Command" entry.
+# autoUpdate - 1 means execute the update command
+# automatically whenever the color changes.
+# name - Name for new color, typed into entry.
+
+set colorSpace hsb
+set red 65535
+set green 0
+set blue 0
+set color #ffff00000000
+set updating 0
+set autoUpdate 1
+set name ""
+
+# Create the menu bar at the top of the window.
+
+. configure -menu [menu .menu]
+menu .menu.file
+.menu add cascade -menu .menu.file -label File -underline 0
+.menu.file add radio -label "RGB color space" -variable colorSpace \
+ -value rgb -underline 0 -command {changeColorSpace rgb}
+.menu.file add radio -label "CMY color space" -variable colorSpace \
+ -value cmy -underline 0 -command {changeColorSpace cmy}
+.menu.file add radio -label "HSB color space" -variable colorSpace \
+ -value hsb -underline 0 -command {changeColorSpace hsb}
+.menu.file add separator
+.menu.file add radio -label "Automatic updates" -variable autoUpdate \
+ -value 1 -underline 0
+.menu.file add radio -label "Manual updates" -variable autoUpdate \
+ -value 0 -underline 0
+.menu.file add separator
+.menu.file add command -label "Exit program" -underline 0 -command {exit}
+
+# Create the command entry window at the bottom of the window, along
+# with the update button.
+
+labelframe .command -text "Command:" -padx {1m 0}
+entry .command.e -textvariable command
+button .command.update -text Update -command doUpdate
+pack .command.update -side right -pady .1c -padx {.25c 0}
+pack .command.e -expand yes -fill x -ipadx 0.25c
+
+
+# Create the listbox that holds all of the color names in rgb.txt,
+# if an rgb.txt file can be found.
+
+grid .command -sticky nsew -row 2 -columnspan 3 -padx 1m -pady {0 1m}
+
+grid columnconfigure . {1 2} -weight 1
+grid rowconfigure . 0 -weight 1
+foreach i {
+ /usr/local/lib/X11/rgb.txt /usr/lib/X11/rgb.txt
+ /X11/R5/lib/X11/rgb.txt /X11/R4/lib/rgb/rgb.txt
+ /usr/openwin/lib/X11/rgb.txt
+} {
+ if {![file readable $i]} {
+ continue;
+ }
+ set f [open $i]
+ labelframe .names -text "Select:" -padx .1c -pady .1c
+ grid .names -row 0 -column 0 -sticky nsew -padx .15c -pady .15c -rowspan 2
+ grid columnconfigure . 0 -weight 1
+ listbox .names.lb -width 20 -height 12 -yscrollcommand ".names.s set" \
+ -exportselection false
+ bind .names.lb <Double-1> {
+ tc_loadNamedColor [.names.lb get [.names.lb curselection]]
+ }
+ scrollbar .names.s -orient vertical -command ".names.lb yview"
+ pack .names.lb .names.s -side left -fill y -expand 1
+ while {[gets $f line] >= 0} {
+ if {[regexp {^\s*\d+\s+\d+\s+\d+\s+(\S+)$} $line -> col]} {
+ .names.lb insert end $col
+ }
+ }
+ close $f
+ break
+}
+
+# Create the three scales for editing the color, and the entry for
+# typing in a color value.
+
+frame .adjust
+foreach i {1 2 3} {
+ label .adjust.l$i -textvariable label$i -pady 0
+ labelframe .adjust.$i -labelwidget .adjust.l$i -padx 1m -pady 1m
+ scale .scale$i -from 0 -to 1000 -length 6c -orient horizontal \
+ -command tc_scaleChanged
+ pack .scale$i -in .adjust.$i
+ pack .adjust.$i
+}
+grid .adjust -row 0 -column 1 -sticky nsew -padx .15c -pady .15c
+
+labelframe .name -text "Name:" -padx 1m -pady 1m
+entry .name.e -textvariable name -width 10
+pack .name.e -side right -expand 1 -fill x
+bind .name.e <Return> {tc_loadNamedColor $name}
+grid .name -column 1 -row 1 -sticky nsew -padx .15c -pady .15c
+
+# Create the color display swatch on the right side of the window.
+
+labelframe .sample -text "Color:" -padx 1m -pady 1m
+frame .sample.swatch -width 2c -height 5c -background $color
+label .sample.value -textvariable color -width 13 -font {Courier 12}
+pack .sample.swatch -side top -expand yes -fill both
+pack .sample.value -side bottom -pady .25c
+grid .sample -row 0 -column 2 -sticky nsew -padx .15c -pady .15c -rowspan 2
+
+
+# The procedure below is invoked when one of the scales is adjusted.
+# It propagates color information from the current scale readings
+# to everywhere else that it is used.
+
+proc tc_scaleChanged args {
+ global red green blue colorSpace color updating autoUpdate
+ if {$updating} {
+ return
+ }
+ switch $colorSpace {
+ rgb {
+ set red [format %.0f [expr {[.scale1 get]*65.535}]]
+ set green [format %.0f [expr {[.scale2 get]*65.535}]]
+ set blue [format %.0f [expr {[.scale3 get]*65.535}]]
+ }
+ cmy {
+ set red [format %.0f [expr {65535 - [.scale1 get]*65.535}]]
+ set green [format %.0f [expr {65535 - [.scale2 get]*65.535}]]
+ set blue [format %.0f [expr {65535 - [.scale3 get]*65.535}]]
+ }
+ hsb {
+ set list [hsbToRgb [expr {[.scale1 get]/1000.0}] \
+ [expr {[.scale2 get]/1000.0}] \
+ [expr {[.scale3 get]/1000.0}]]
+ set red [lindex $list 0]
+ set green [lindex $list 1]
+ set blue [lindex $list 2]
+ }
+ }
+ set color [format "#%04x%04x%04x" $red $green $blue]
+ .sample.swatch config -bg $color
+ if {$autoUpdate} doUpdate
+ update idletasks
+}
+
+# The procedure below is invoked to update the scales from the
+# current red, green, and blue intensities. It's invoked after
+# a change in the color space and after a named color value has
+# been loaded.
+
+proc tc_setScales {} {
+ global red green blue colorSpace updating
+ set updating 1
+ switch $colorSpace {
+ rgb {
+ .scale1 set [format %.0f [expr {$red/65.535}]]
+ .scale2 set [format %.0f [expr {$green/65.535}]]
+ .scale3 set [format %.0f [expr {$blue/65.535}]]
+ }
+ cmy {
+ .scale1 set [format %.0f [expr {(65535-$red)/65.535}]]
+ .scale2 set [format %.0f [expr {(65535-$green)/65.535}]]
+ .scale3 set [format %.0f [expr {(65535-$blue)/65.535}]]
+ }
+ hsb {
+ set list [rgbToHsv $red $green $blue]
+ .scale1 set [format %.0f [expr {[lindex $list 0] * 1000.0}]]
+ .scale2 set [format %.0f [expr {[lindex $list 1] * 1000.0}]]
+ .scale3 set [format %.0f [expr {[lindex $list 2] * 1000.0}]]
+ }
+ }
+ set updating 0
+}
+
+# The procedure below is invoked when a named color has been
+# selected from the listbox or typed into the entry. It loads
+# the color into the editor.
+
+proc tc_loadNamedColor name {
+ global red green blue color autoUpdate
+
+ if {[string index $name 0] != "#"} {
+ set list [winfo rgb .sample.swatch $name]
+ set red [lindex $list 0]
+ set green [lindex $list 1]
+ set blue [lindex $list 2]
+ } else {
+ switch [string length $name] {
+ 4 {set format "#%1x%1x%1x"; set shift 12}
+ 7 {set format "#%2x%2x%2x"; set shift 8}
+ 10 {set format "#%3x%3x%3x"; set shift 4}
+ 13 {set format "#%4x%4x%4x"; set shift 0}
+ default {error "syntax error in color name \"$name\""}
+ }
+ if {[scan $name $format red green blue] != 3} {
+ error "syntax error in color name \"$name\""
+ }
+ set red [expr {$red<<$shift}]
+ set green [expr {$green<<$shift}]
+ set blue [expr {$blue<<$shift}]
+ }
+ tc_setScales
+ set color [format "#%04x%04x%04x" $red $green $blue]
+ .sample.swatch config -bg $color
+ if {$autoUpdate} doUpdate
+}
+
+# The procedure below is invoked when a new color space is selected.
+# It changes the labels on the scales and re-loads the scales with
+# the appropriate values for the current color in the new color space
+
+proc changeColorSpace space {
+ global label1 label2 label3
+ switch $space {
+ rgb {
+ set label1 "Adjust Red:"
+ set label2 "Adjust Green:"
+ set label3 "Adjust Blue:"
+ tc_setScales
+ return
+ }
+ cmy {
+ set label1 "Adjust Cyan:"
+ set label2 "Adjust Magenta:"
+ set label3 "Adjust Yellow:"
+ tc_setScales
+ return
+ }
+ hsb {
+ set label1 "Adjust Hue:"
+ set label2 "Adjust Saturation:"
+ set label3 "Adjust Brightness:"
+ tc_setScales
+ return
+ }
+ }
+}
+
+# The procedure below converts an RGB value to HSB. It takes red, green,
+# and blue components (0-65535) as arguments, and returns a list containing
+# HSB components (floating-point, 0-1) as result. The code here is a copy
+# of the code on page 615 of "Fundamentals of Interactive Computer Graphics"
+# by Foley and Van Dam.
+
+proc rgbToHsv {red green blue} {
+ if {$red > $green} {
+ set max [expr {double($red)}]
+ set min [expr {double($green)}]
+ } else {
+ set max [expr {double($green)}]
+ set min [expr {double($red)}]
+ }
+ if {$blue > $max} {
+ set max [expr {double($blue)}]
+ } elseif {$blue < $min} {
+ set min [expr {double($blue)}]
+ }
+ set range [expr {$max-$min}]
+ if {$max == 0} {
+ set sat 0
+ } else {
+ set sat [expr {($max-$min)/$max}]
+ }
+ if {$sat == 0} {
+ set hue 0
+ } else {
+ set rc [expr {($max - $red)/$range}]
+ set gc [expr {($max - $green)/$range}]
+ set bc [expr {($max - $blue)/$range}]
+ if {$red == $max} {
+ set hue [expr {($bc - $gc)/6.0}]
+ } elseif {$green == $max} {
+ set hue [expr {(2 + $rc - $bc)/6.0}]
+ } else {
+ set hue [expr {(4 + $gc - $rc)/6.0}]
+ }
+ if {$hue < 0.0} {
+ set hue [expr {$hue + 1.0}]
+ }
+ }
+ return [list $hue $sat [expr {$max/65535}]]
+}
+
+# The procedure below converts an HSB value to RGB. It takes hue, saturation,
+# and value components (floating-point, 0-1.0) as arguments, and returns a
+# list containing RGB components (integers, 0-65535) as result. The code
+# here is a copy of the code on page 616 of "Fundamentals of Interactive
+# Computer Graphics" by Foley and Van Dam.
+
+proc hsbToRgb {hue sat value} {
+ set v [format %.0f [expr {65535.0*$value}]]
+ if {$sat == 0} {
+ return "$v $v $v"
+ } else {
+ set hue [expr {$hue*6.0}]
+ if {$hue >= 6.0} {
+ set hue 0.0
+ }
+ scan $hue. %d i
+ set f [expr {$hue-$i}]
+ set p [format %.0f [expr {65535.0*$value*(1 - $sat)}]]
+ set q [format %.0f [expr {65535.0*$value*(1 - ($sat*$f))}]]
+ set t [format %.0f [expr {65535.0*$value*(1 - ($sat*(1 - $f)))}]]
+ switch $i {
+ 0 {return "$v $t $p"}
+ 1 {return "$q $v $p"}
+ 2 {return "$p $v $t"}
+ 3 {return "$p $q $v"}
+ 4 {return "$t $p $v"}
+ 5 {return "$v $p $q"}
+ default {error "i value $i is out of range"}
+ }
+ }
+}
+
+# The procedure below is invoked when the "Update" button is pressed,
+# and whenever the color changes if update mode is enabled. It
+# propagates color information as determined by the command in the
+# Command entry.
+
+proc doUpdate {} {
+ global color command
+ set newCmd $command
+ regsub -all %% $command $color newCmd
+ eval $newCmd
+}
+
+changeColorSpace hsb
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tk8.6/library/demos/text.tcl b/tk8.6/library/demos/text.tcl
new file mode 100644
index 0000000..d1801d1
--- /dev/null
+++ b/tk8.6/library/demos/text.tcl
@@ -0,0 +1,111 @@
+# text.tcl --
+#
+# This demonstration script creates a text widget that describes
+# the basic editing functions.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .text
+catch {destroy $w}
+toplevel $w
+wm title $w "Text Demonstration - Basic Facilities"
+wm iconname $w "text"
+positionWindow $w
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w {} \
+ {ttk::button $w.buttons.fontchooser -command fontchooserToggle}]
+pack $btns -side bottom -fill x
+
+text $w.text -yscrollcommand [list $w.scroll set] -setgrid 1 \
+ -height 30 -undo 1 -autosep 1
+ttk::scrollbar $w.scroll -command [list $w.text yview]
+pack $w.scroll -side right -fill y
+pack $w.text -expand yes -fill both
+
+# TIP 324 Demo: [tk fontchooser]
+proc fontchooserToggle {} {
+ tk fontchooser [expr {[tk fontchooser configure -visible] ?
+ "hide" : "show"}]
+}
+proc fontchooserVisibility {w} {
+ $w configure -text [expr {[tk fontchooser configure -visible] ?
+ "Hide Font Dialog" : "Show Font Dialog"}]
+}
+proc fontchooserFocus {w} {
+ tk fontchooser configure -font [$w cget -font] \
+ -command [list fontchooserFontSel $w]
+}
+proc fontchooserFontSel {w font args} {
+ $w configure -font [font actual $font]
+}
+tk fontchooser configure -parent $w
+bind $w.text <FocusIn> [list fontchooserFocus $w.text]
+fontchooserVisibility $w.buttons.fontchooser
+bind $w <<TkFontchooserVisibility>> [list \
+ fontchooserVisibility $w.buttons.fontchooser]
+focus $w.text
+
+$w.text insert 0.0 \
+{This window is a text widget. It displays one or more lines of text
+and allows you to edit the text. Here is a summary of the things you
+can do to a text widget:
+
+1. Scrolling. Use the scrollbar to adjust the view in the text window.
+
+2. Scanning. Press mouse button 2 in the text window and drag up or down.
+This will drag the text at high speed to allow you to scan its contents.
+
+3. Insert text. Press mouse button 1 to set the insertion cursor, then
+type text. What you type will be added to the widget.
+
+4. Select. Press mouse button 1 and drag to select a range of characters.
+Once you've released the button, you can adjust the selection by pressing
+button 1 with the shift key down. This will reset the end of the
+selection nearest the mouse cursor and you can drag that end of the
+selection by dragging the mouse before releasing the mouse button.
+You can double-click to select whole words or triple-click to select
+whole lines.
+
+5. Delete and replace. To delete text, select the characters you'd like
+to delete and type Backspace or Delete. Alternatively, you can type new
+text, in which case it will replace the selected text.
+
+6. Copy the selection. To copy the selection into this window, select
+what you want to copy (either here or in another application), then
+click button 2 to copy the selection to the point of the mouse cursor.
+
+7. Edit. Text widgets support the standard Motif editing characters
+plus many Emacs editing characters. Backspace and Control-h erase the
+character to the left of the insertion cursor. Delete and Control-d
+erase the character to the right of the insertion cursor. Meta-backspace
+deletes the word to the left of the insertion cursor, and Meta-d deletes
+the word to the right of the insertion cursor. Control-k deletes from
+the insertion cursor to the end of the line, or it deletes the newline
+character if that is the only thing left on the line. Control-o opens
+a new line by inserting a newline character to the right of the insertion
+cursor. Control-t transposes the two characters on either side of the
+insertion cursor. Control-z undoes the last editing action performed,
+and }
+
+switch [tk windowingsystem] {
+ "aqua" - "x11" {
+ $w.text insert end "Control-Shift-z"
+ }
+ "win32" {
+ $w.text insert end "Control-y"
+ }
+}
+
+$w.text insert end { redoes undone edits.
+
+7. Resize the window. This widget has been configured with the "setGrid"
+option on, so that if you resize the window it will always resize to an
+even number of characters high and wide. Also, if you make the window
+narrow you can see that long lines automatically wrap around onto
+additional lines so that all the information is always visible.}
+$w.text mark set insert 0.0
diff --git a/tk8.6/library/demos/textpeer.tcl b/tk8.6/library/demos/textpeer.tcl
new file mode 100644
index 0000000..83e8e14
--- /dev/null
+++ b/tk8.6/library/demos/textpeer.tcl
@@ -0,0 +1,62 @@
+# textpeer.tcl --
+#
+# This demonstration script creates a pair of text widgets that can edit a
+# single logical buffer. This is particularly useful when editing related text
+# in two (or more) parts of the same file.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .textpeer
+catch {destroy $w}
+toplevel $w
+wm title $w "Text Widget Peering Demonstration"
+wm iconname $w "textpeer"
+positionWindow $w
+
+set count 0
+
+## Define a widget that we peer from; it won't ever actually be shown though
+set first [text $w.text[incr count]]
+$first insert end "This is a coupled pair of text widgets; they are peers to "
+$first insert end "each other. They have the same underlying data model, but "
+$first insert end "can show different locations, have different current edit "
+$first insert end "locations, and have different selections. You can also "
+$first insert end "create additional peers of any of these text widgets using "
+$first insert end "the Make Peer button beside the text widget to clone, and "
+$first insert end "delete a particular peer widget using the Delete Peer "
+$first insert end "button."
+
+## Procedures to make and kill clones; most of this is just so that the demo
+## looks nice...
+proc makeClone {w parent} {
+ global count
+ set t [$parent peer create $w.text[incr count] -yscroll "$w.sb$count set"\
+ -height 10 -wrap word]
+ set sb [ttk::scrollbar $w.sb$count -command "$t yview" -orient vertical]
+ set b1 [button $w.clone$count -command "makeClone $w $t" \
+ -text "Make Peer"]
+ set b2 [button $w.kill$count -command "killClone $w $count" \
+ -text "Delete Peer"]
+ set row [expr {$count * 2}]
+ grid $t $sb $b1 -sticky nsew -row $row
+ grid ^ ^ $b2 -row [incr row]
+ grid configure $b1 $b2 -sticky new
+ grid rowconfigure $w $b2 -weight 1
+}
+proc killClone {w count} {
+ destroy $w.text$count $w.sb$count
+ destroy $w.clone$count $w.kill$count
+}
+
+## Now set up the GUI
+makeClone $w $first
+makeClone $w $first
+destroy $first
+
+## See Code / Dismiss buttons
+grid [addSeeDismiss $w.buttons $w] - - -sticky ew -row 5000
+grid columnconfigure $w 0 -weight 1
diff --git a/tk8.6/library/demos/timer b/tk8.6/library/demos/timer
new file mode 100644
index 0000000..6b61ca4
--- /dev/null
+++ b/tk8.6/library/demos/timer
@@ -0,0 +1,47 @@
+#!/bin/sh
+# the next line restarts using wish \
+exec wish "$0" ${1+"$@"}
+
+# timer --
+# This script generates a counter with start and stop buttons.
+
+package require Tk
+
+label .counter -text 0.00 -relief raised -width 10 -padx 2m -pady 1m
+button .start -text Start -command {
+ if {$stopped} {
+ set stopped 0
+ set startMoment [clock clicks -milliseconds]
+ tick
+ .stop configure -state normal
+ .start configure -state disabled
+ }
+}
+button .stop -text Stop -state disabled -command {
+ set stopped 1
+ .stop configure -state disabled
+ .start configure -state normal
+}
+pack .counter -side bottom -fill both
+pack .start -side left -fill both -expand yes
+pack .stop -side right -fill both -expand yes
+
+set startMoment {}
+
+set stopped 1
+
+proc tick {} {
+ global startMoment stopped
+ if {$stopped} {return}
+ after 50 tick
+ set elapsedMS [expr {[clock clicks -milliseconds] - $startMoment}]
+ .counter config -text [format "%.2f" [expr {double($elapsedMS)/1000}]]
+}
+
+bind . <Control-c> {destroy .}
+bind . <Control-q> {destroy .}
+focus .
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tk8.6/library/demos/toolbar.tcl b/tk8.6/library/demos/toolbar.tcl
new file mode 100644
index 0000000..cb2a495
--- /dev/null
+++ b/tk8.6/library/demos/toolbar.tcl
@@ -0,0 +1,92 @@
+# toolbar.tcl --
+#
+# This demonstration script creates a toolbar that can be torn off.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .toolbar
+destroy $w
+toplevel $w
+wm title $w "Toolbar Demonstration"
+wm iconname $w "toolbar"
+positionWindow $w
+
+ttk::label $w.msg -wraplength 4i -text "This is a demonstration of how to do\
+ a toolbar that is styled correctly and which can be torn off. The\
+ buttons are configured to be \u201Ctoolbar style\u201D buttons by\
+ telling them that they are to use the Toolbutton style. At the left\
+ end of the toolbar is a simple marker that the cursor changes to a\
+ movement icon over; drag that away from the toolbar to tear off the\
+ whole toolbar into a separate toplevel widget. When the dragged-off\
+ toolbar is no longer needed, just close it like any normal toplevel\
+ and it will reattach to the window it was torn off from."
+
+## Set up the toolbar hull
+set t [frame $w.toolbar] ;# Must be a frame!
+ttk::separator $w.sep
+ttk::frame $t.tearoff -cursor fleur
+ttk::separator $t.tearoff.to -orient vertical
+ttk::separator $t.tearoff.to2 -orient vertical
+pack $t.tearoff.to -fill y -expand 1 -padx 4 -side left
+pack $t.tearoff.to2 -fill y -expand 1 -side left
+ttk::frame $t.contents
+grid $t.tearoff $t.contents -sticky nsew
+grid columnconfigure $t $t.contents -weight 1
+grid columnconfigure $t.contents 1000 -weight 1
+
+## Bindings so that the toolbar can be torn off and reattached
+bind $t.tearoff <B1-Motion> [list tearoff $t %X %Y]
+bind $t.tearoff.to <B1-Motion> [list tearoff $t %X %Y]
+bind $t.tearoff.to2 <B1-Motion> [list tearoff $t %X %Y]
+proc tearoff {w x y} {
+ if {[string match $w* [winfo containing $x $y]]} {
+ return
+ }
+ grid remove $w
+ grid remove $w.tearoff
+ wm manage $w
+ wm protocol $w WM_DELETE_WINDOW [list untearoff $w]
+}
+proc untearoff {w} {
+ wm forget $w
+ grid $w.tearoff
+ grid $w
+}
+
+## Toolbar contents
+ttk::button $t.button -text "Button" -style Toolbutton -command [list \
+ $w.txt insert end "Button Pressed\n"]
+ttk::checkbutton $t.check -text "Check" -variable check -style Toolbutton \
+ -command [concat [list $w.txt insert end] {"check is $check\n"}]
+ttk::menubutton $t.menu -text "Menu" -menu $t.menu.m
+ttk::combobox $t.combo -value [lsort [font families]] -state readonly
+menu $t.menu.m
+$t.menu.m add command -label "Just" -command [list $w.txt insert end Just\n]
+$t.menu.m add command -label "An" -command [list $w.txt insert end An\n]
+$t.menu.m add command -label "Example" \
+ -command [list $w.txt insert end Example\n]
+bind $t.combo <<ComboboxSelected>> [list changeFont $w.txt $t.combo]
+proc changeFont {txt combo} {
+ $txt configure -font [list [$combo get] 10]
+}
+
+## Some content for the rest of the toplevel
+text $w.txt -width 40 -height 10
+interp alias {} doInsert {} $w.txt insert end ;# Make bindings easy to write
+
+## Arrange contents
+grid $t.button $t.check $t.menu $t.combo -in $t.contents -padx 2 -pady 4 -sticky ns
+grid $t -sticky ew
+grid $w.sep -sticky ew
+grid $w.msg -sticky ew
+grid $w.txt -sticky nsew
+grid rowconfigure $w $w.txt -weight 1
+grid columnconfigure $w $w.txt -weight 1
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+grid $btns -sticky ew
diff --git a/tk8.6/library/demos/tree.tcl b/tk8.6/library/demos/tree.tcl
new file mode 100644
index 0000000..8decdf2
--- /dev/null
+++ b/tk8.6/library/demos/tree.tcl
@@ -0,0 +1,88 @@
+# tree.tcl --
+#
+# This demonstration script creates a toplevel window containing a Ttk
+# tree widget.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .tree
+catch {destroy $w}
+toplevel $w
+wm title $w "Directory Browser"
+wm iconname $w "tree"
+positionWindow $w
+
+## Explanatory text
+ttk::label $w.msg -font $font -wraplength 4i -justify left -anchor n -padding {10 2 10 6} -text "Ttk is the new Tk themed widget set. One of the widgets it includes is a tree widget, which allows the user to browse a hierarchical data-set such as a filesystem. The tree widget not only allows for the tree part itself, but it also supports an arbitrary number of additional columns which can show additional data (in this case, the size of the files found in your filesystem). You can also change the width of the columns by dragging the boundary between them."
+pack $w.msg -fill x
+
+## See Code / Dismiss
+pack [addSeeDismiss $w.seeDismiss $w] -side bottom -fill x
+
+## Code to populate the roots of the tree (can be more than one on Windows)
+proc populateRoots {tree} {
+ foreach dir [lsort -dictionary [file volumes]] {
+ populateTree $tree [$tree insert {} end -text $dir \
+ -values [list $dir directory]]
+ }
+}
+
+## Code to populate a node of the tree
+proc populateTree {tree node} {
+ if {[$tree set $node type] ne "directory"} {
+ return
+ }
+ set path [$tree set $node fullpath]
+ $tree delete [$tree children $node]
+ foreach f [lsort -dictionary [glob -nocomplain -dir $path *]] {
+ set type [file type $f]
+ set id [$tree insert $node end -text [file tail $f] \
+ -values [list $f $type]]
+
+ if {$type eq "directory"} {
+ ## Make it so that this node is openable
+ $tree insert $id 0 -text dummy ;# a dummy
+ $tree item $id -text [file tail $f]/
+
+ } elseif {$type eq "file"} {
+ set size [file size $f]
+ ## Format the file size nicely
+ if {$size >= 1024*1024*1024} {
+ set size [format %.1f\ GB [expr {$size/1024/1024/1024.}]]
+ } elseif {$size >= 1024*1024} {
+ set size [format %.1f\ MB [expr {$size/1024/1024.}]]
+ } elseif {$size >= 1024} {
+ set size [format %.1f\ kB [expr {$size/1024.}]]
+ } else {
+ append size " bytes"
+ }
+ $tree set $id size $size
+ }
+ }
+
+ # Stop this code from rerunning on the current node
+ $tree set $node type processedDirectory
+}
+
+## Create the tree and set it up
+ttk::treeview $w.tree -columns {fullpath type size} -displaycolumns {size} \
+ -yscroll "$w.vsb set" -xscroll "$w.hsb set"
+ttk::scrollbar $w.vsb -orient vertical -command "$w.tree yview"
+ttk::scrollbar $w.hsb -orient horizontal -command "$w.tree xview"
+$w.tree heading \#0 -text "Directory Structure"
+$w.tree heading size -text "File Size"
+$w.tree column size -width 70
+populateRoots $w.tree
+bind $w.tree <<TreeviewOpen>> {populateTree %W [%W focus]}
+
+## Arrange the tree and its scrollbars in the toplevel
+lower [ttk::frame $w.dummy]
+pack $w.dummy -fill both -expand 1
+grid $w.tree $w.vsb -sticky nsew -in $w.dummy
+grid $w.hsb -sticky nsew -in $w.dummy
+grid columnconfigure $w.dummy 0 -weight 1
+grid rowconfigure $w.dummy 0 -weight 1
diff --git a/tk8.6/library/demos/ttkbut.tcl b/tk8.6/library/demos/ttkbut.tcl
new file mode 100644
index 0000000..ab49cf4
--- /dev/null
+++ b/tk8.6/library/demos/ttkbut.tcl
@@ -0,0 +1,84 @@
+# ttkbut.tcl --
+#
+# This demonstration script creates a toplevel window containing several
+# simple Ttk widgets, such as labels, labelframes, buttons, checkbuttons and
+# radiobuttons.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .ttkbut
+catch {destroy $w}
+toplevel $w
+wm title $w "Simple Ttk Widgets"
+wm iconname $w "ttkbut"
+positionWindow $w
+
+ttk::label $w.msg -font $font -wraplength 4i -justify left -text "Ttk is the new Tk themed widget set. This is a Ttk themed label, and below are three groups of Ttk widgets in Ttk labelframes. The first group are all buttons that set the current application theme when pressed. The second group contains three sets of checkbuttons, with a separator widget between the sets. Note that the \u201cEnabled\u201d button controls whether all the other themed widgets in this toplevel are in the disabled state. The third group has a collection of linked radiobuttons."
+pack $w.msg -side top -fill x
+
+## See Code / Dismiss
+pack [addSeeDismiss $w.seeDismiss $w {enabled cheese tomato basil oregano happiness}]\
+ -side bottom -fill x
+
+## Add buttons for setting the theme
+ttk::labelframe $w.buttons -text "Buttons"
+foreach theme [ttk::themes] {
+ ttk::button $w.buttons.$theme -text $theme \
+ -command [list ttk::setTheme $theme]
+ pack $w.buttons.$theme -pady 2
+}
+
+## Helper procedure for the top checkbutton
+proc setState {rootWidget exceptThese value} {
+ if {$rootWidget in $exceptThese} {
+ return
+ }
+ ## Non-Ttk widgets (e.g. the toplevel) will fail, so make it silent
+ catch {
+ $rootWidget state $value
+ }
+ ## Recursively invoke on all children of this root that are in the same
+ ## toplevel widget
+ foreach w [winfo children $rootWidget] {
+ if {[winfo toplevel $w] eq [winfo toplevel $rootWidget]} {
+ setState $w $exceptThese $value
+ }
+ }
+}
+
+## Set up the checkbutton group
+ttk::labelframe $w.checks -text "Checkbuttons"
+ttk::checkbutton $w.checks.e -text Enabled -variable enabled -command {
+ setState .ttkbut .ttkbut.checks.e \
+ [expr {$enabled ? "!disabled" : "disabled"}]
+}
+set enabled 1
+## See ttk_widget(n) for other possible state flags
+ttk::separator $w.checks.sep1
+ttk::checkbutton $w.checks.c1 -text Cheese -variable cheese
+ttk::checkbutton $w.checks.c2 -text Tomato -variable tomato
+ttk::separator $w.checks.sep2
+ttk::checkbutton $w.checks.c3 -text Basil -variable basil
+ttk::checkbutton $w.checks.c4 -text Oregano -variable oregano
+pack $w.checks.e $w.checks.sep1 $w.checks.c1 $w.checks.c2 $w.checks.sep2 \
+ $w.checks.c3 $w.checks.c4 -fill x -pady 2
+
+## Set up the radiobutton group
+ttk::labelframe $w.radios -text "Radiobuttons"
+ttk::radiobutton $w.radios.r1 -text "Great" -variable happiness -value great
+ttk::radiobutton $w.radios.r2 -text "Good" -variable happiness -value good
+ttk::radiobutton $w.radios.r3 -text "OK" -variable happiness -value ok
+ttk::radiobutton $w.radios.r4 -text "Poor" -variable happiness -value poor
+ttk::radiobutton $w.radios.r5 -text "Awful" -variable happiness -value awful
+pack $w.radios.r1 $w.radios.r2 $w.radios.r3 $w.radios.r4 $w.radios.r5 \
+ -fill x -padx 3 -pady 2
+
+## Arrange things neatly
+pack [ttk::frame $w.f] -fill both -expand 1
+lower $w.f
+grid $w.buttons $w.checks $w.radios -in $w.f -sticky nwe -pady 2 -padx 3
+grid columnconfigure $w.f {0 1 2} -weight 1 -uniform yes
diff --git a/tk8.6/library/demos/ttkmenu.tcl b/tk8.6/library/demos/ttkmenu.tcl
new file mode 100644
index 0000000..0084dd6
--- /dev/null
+++ b/tk8.6/library/demos/ttkmenu.tcl
@@ -0,0 +1,53 @@
+# ttkmenu.tcl --
+#
+# This demonstration script creates a toplevel window containing several Ttk
+# menubutton widgets.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .ttkmenu
+catch {destroy $w}
+toplevel $w
+wm title $w "Ttk Menu Buttons"
+wm iconname $w "ttkmenu"
+positionWindow $w
+
+ttk::label $w.msg -font $font -wraplength 4i -justify left -text "Ttk is the new Tk themed widget set, and one widget that is available in themed form is the menubutton. Below are some themed menu buttons that allow you to pick the current theme in use. Notice how picking a theme changes the way that the menu buttons themselves look, and that the central menu button is styled differently (in a way that is normally suitable for toolbars). However, there are no themed menus; the standard Tk menus were judged to have a sufficiently good look-and-feel on all platforms, especially as they are implemented as native controls in many places."
+pack $w.msg [ttk::separator $w.msgSep] -side top -fill x
+
+## See Code / Dismiss
+pack [addSeeDismiss $w.seeDismiss $w] -side bottom -fill x
+
+ttk::menubutton $w.m1 -menu $w.m1.menu -text "Select a theme" -direction above
+ttk::menubutton $w.m2 -menu $w.m1.menu -text "Select a theme" -direction left
+ttk::menubutton $w.m3 -menu $w.m1.menu -text "Select a theme" -direction right
+ttk::menubutton $w.m4 -menu $w.m1.menu -text "Select a theme" \
+ -direction flush -style TMenubutton.Toolbutton
+ttk::menubutton $w.m5 -menu $w.m1.menu -text "Select a theme" -direction below
+
+menu $w.m1.menu -tearoff 0
+menu $w.m2.menu -tearoff 0
+menu $w.m3.menu -tearoff 0
+menu $w.m4.menu -tearoff 0
+menu $w.m5.menu -tearoff 0
+
+foreach theme [ttk::themes] {
+ $w.m1.menu add command -label $theme -command [list ttk::setTheme $theme]
+ $w.m2.menu add command -label $theme -command [list ttk::setTheme $theme]
+ $w.m3.menu add command -label $theme -command [list ttk::setTheme $theme]
+ $w.m4.menu add command -label $theme -command [list ttk::setTheme $theme]
+ $w.m5.menu add command -label $theme -command [list ttk::setTheme $theme]
+}
+
+pack [ttk::frame $w.f] -fill x
+pack [ttk::frame $w.f1] -fill both -expand yes
+lower $w.f
+
+grid anchor $w.f center
+grid x $w.m1 x -in $w.f -padx 3 -pady 2
+grid $w.m2 $w.m4 $w.m3 -in $w.f -padx 3 -pady 2
+grid x $w.m5 x -in $w.f -padx 3 -pady 2
diff --git a/tk8.6/library/demos/ttknote.tcl b/tk8.6/library/demos/ttknote.tcl
new file mode 100644
index 0000000..50a9258
--- /dev/null
+++ b/tk8.6/library/demos/ttknote.tcl
@@ -0,0 +1,57 @@
+# ttknote.tcl --
+#
+# This demonstration script creates a toplevel window containing a Ttk
+# notebook widget.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .ttknote
+catch {destroy $w}
+toplevel $w
+wm title $w "Ttk Notebook Widget"
+wm iconname $w "ttknote"
+positionWindow $w
+
+## See Code / Dismiss
+pack [addSeeDismiss $w.seeDismiss $w] -side bottom -fill x
+
+ttk::frame $w.f
+pack $w.f -fill both -expand 1
+set w $w.f
+
+## Make the notebook and set up Ctrl+Tab traversal
+ttk::notebook $w.note
+pack $w.note -fill both -expand 1 -padx 2 -pady 3
+ttk::notebook::enableTraversal $w.note
+
+## Popuplate the first pane
+ttk::frame $w.note.msg
+ttk::label $w.note.msg.m -font $font -wraplength 4i -justify left -anchor n -text "Ttk is the new Tk themed widget set. One of the widgets it includes is the notebook widget, which provides a set of tabs that allow the selection of a group of panels, each with distinct content. They are a feature of many modern user interfaces. Not only can the tabs be selected with the mouse, but they can also be switched between using Ctrl+Tab when the notebook page heading itself is selected. Note that the second tab is disabled, and cannot be selected."
+ttk::button $w.note.msg.b -text "Neat!" -underline 0 -command {
+ set neat "Yeah, I know..."
+ after 500 {set neat {}}
+}
+bind $w <Alt-n> "focus $w.note.msg.b; $w.note.msg.b invoke"
+ttk::label $w.note.msg.l -textvariable neat
+$w.note add $w.note.msg -text "Description" -underline 0 -padding 2
+grid $w.note.msg.m - -sticky new -pady 2
+grid $w.note.msg.b $w.note.msg.l -pady {2 4}
+grid rowconfigure $w.note.msg 1 -weight 1
+grid columnconfigure $w.note.msg {0 1} -weight 1 -uniform 1
+
+## Populate the second pane. Note that the content doesn't really matter
+ttk::frame $w.note.disabled
+$w.note add $w.note.disabled -text "Disabled" -state disabled
+
+## Popuplate the third pane
+ttk::frame $w.note.editor
+$w.note add $w.note.editor -text "Text Editor" -underline 0
+text $w.note.editor.t -width 40 -height 10 -wrap char \
+ -yscroll "$w.note.editor.s set"
+ttk::scrollbar $w.note.editor.s -orient vertical -command "$w.note.editor.t yview"
+pack $w.note.editor.s -side right -fill y -padx {0 2} -pady 2
+pack $w.note.editor.t -fill both -expand 1 -pady 2 -padx {2 0}
diff --git a/tk8.6/library/demos/ttkpane.tcl b/tk8.6/library/demos/ttkpane.tcl
new file mode 100644
index 0000000..3f88987
--- /dev/null
+++ b/tk8.6/library/demos/ttkpane.tcl
@@ -0,0 +1,112 @@
+# ttkpane.tcl --
+#
+# This demonstration script creates a Ttk pane with some content.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .ttkpane
+catch {destroy $w}
+toplevel $w
+wm title $w "Themed Nested Panes"
+wm iconname $w "ttkpane"
+positionWindow $w
+
+ttk::label $w.msg -font $font -wraplength 4i -justify left -text "This demonstration shows off a nested set of themed paned windows. Their sizes can be changed by grabbing the area between each contained pane and dragging the divider."
+pack $w.msg [ttk::separator $w.msgSep] -side top -fill x
+
+## See Code / Dismiss
+pack [addSeeDismiss $w.seeDismiss $w] -side bottom -fill x
+
+ttk::frame $w.f
+pack $w.f -fill both -expand 1
+set w $w.f
+ttk::panedwindow $w.outer -orient horizontal
+$w.outer add [ttk::panedwindow $w.outer.inLeft -orient vertical]
+$w.outer add [ttk::panedwindow $w.outer.inRight -orient vertical]
+$w.outer.inLeft add [ttk::labelframe $w.outer.inLeft.top -text Button]
+$w.outer.inLeft add [ttk::labelframe $w.outer.inLeft.bot -text Clocks]
+$w.outer.inRight add [ttk::labelframe $w.outer.inRight.top -text Progress]
+$w.outer.inRight add [ttk::labelframe $w.outer.inRight.bot -text Text]
+if {[tk windowingsystem] eq "aqua"} {
+ foreach i [list inLeft.top inLeft.bot inRight.top inRight.bot] {
+ $w.outer.$i configure -padding 3
+ }
+}
+
+# Fill the button pane
+ttk::button $w.outer.inLeft.top.b -text "Press Me" -command {
+ tk_messageBox -type ok -icon info -message "Ouch!" -detail "That hurt..." \
+ -parent .ttkpane -title "Button Pressed"
+}
+pack $w.outer.inLeft.top.b -padx 2 -pady 5
+
+# Fill the clocks pane
+set i 0
+proc every {delay script} {
+ uplevel #0 $script
+ after $delay [list every $delay $script]
+}
+set testzones {
+ :Europe/Berlin
+ :America/Argentina/Buenos_Aires
+ :Africa/Johannesburg
+ :Europe/London
+ :America/Los_Angeles
+ :Europe/Moscow
+ :America/New_York
+ :Asia/Singapore
+ :Australia/Sydney
+ :Asia/Tokyo
+}
+# Force a pre-load of all the timezones needed; otherwise can end up
+# poor-looking synch problems!
+set zones {}
+foreach zone $testzones {
+ if {![catch {clock format 0 -timezone $zone}]} {
+ lappend zones $zone
+ }
+}
+if {[llength $zones] < 2} { lappend zones -0200 :GMT :UTC +0200 }
+foreach zone $zones {
+ set city [string map {_ " "} [regexp -inline {[^/]+$} $zone]]
+ if {$i} {
+ pack [ttk::separator $w.outer.inLeft.bot.s$i] -fill x
+ }
+ ttk::label $w.outer.inLeft.bot.l$i -text $city -anchor w
+ ttk::label $w.outer.inLeft.bot.t$i -textvariable time($zone) -anchor w
+ pack $w.outer.inLeft.bot.l$i $w.outer.inLeft.bot.t$i -fill x
+ every 1000 "set time($zone) \[clock format \[clock seconds\] -timezone $zone -format %T\]"
+ incr i
+}
+
+# Fill the progress pane
+ttk::progressbar $w.outer.inRight.top.progress -mode indeterminate
+pack $w.outer.inRight.top.progress -fill both -expand 1
+$w.outer.inRight.top.progress start
+
+# Fill the text pane
+if {[tk windowingsystem] ne "aqua"} {
+ # The trick with the ttk::frame makes the text widget look like it fits with
+ # the current Ttk theme despite not being a themed widget itself. It is done
+ # by styling the frame like an entry, turning off the border in the text
+ # widget, and putting the text widget in the frame with enough space to allow
+ # the surrounding border to show through (2 pixels seems to be enough).
+ ttk::frame $w.outer.inRight.bot.f -style TEntry
+ text $w.txt -wrap word -yscroll "$w.sb set" -width 30 -borderwidth 0
+ pack $w.txt -fill both -expand 1 -in $w.outer.inRight.bot.f -pady 2 -padx 2
+ ttk::scrollbar $w.sb -orient vertical -command "$w.txt yview"
+ pack $w.sb -side right -fill y -in $w.outer.inRight.bot
+ pack $w.outer.inRight.bot.f -fill both -expand 1
+ pack $w.outer -fill both -expand 1
+} else {
+ text $w.txt -wrap word -yscroll "$w.sb set" -width 30 -borderwidth 0
+ ttk::scrollbar $w.sb -orient vertical -command "$w.txt yview"
+ pack $w.sb -side right -fill y -in $w.outer.inRight.bot
+ pack $w.txt -fill both -expand 1 -in $w.outer.inRight.bot
+ pack $w.outer -fill both -expand 1 -padx 10 -pady {6 10}
+}
+
diff --git a/tk8.6/library/demos/ttkprogress.tcl b/tk8.6/library/demos/ttkprogress.tcl
new file mode 100644
index 0000000..8a72cf9
--- /dev/null
+++ b/tk8.6/library/demos/ttkprogress.tcl
@@ -0,0 +1,46 @@
+# ttkprogress.tcl --
+#
+# This demonstration script creates several progress bar widgets.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .ttkprogress
+catch {destroy $w}
+toplevel $w
+wm title $w "Progress Bar Demonstration"
+wm iconname $w "ttkprogress"
+positionWindow $w
+
+ttk::label $w.msg -font $font -wraplength 4i -justify left -text "Below are two progress bars. The top one is a \u201Cdeterminate\u201D progress bar, which is used for showing how far through a defined task the program has got. The bottom one is an \u201Cindeterminate\u201D progress bar, which is used to show that the program is busy but does not know how long for. Both are run here in self-animated mode, which can be turned on and off using the buttons underneath."
+pack $w.msg -side top -fill x
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+ttk::frame $w.f
+pack $w.f -fill both -expand 1
+set w $w.f
+
+proc doBars {op args} {
+ foreach w $args {
+ $w $op
+ }
+}
+ttk::progressbar $w.p1 -mode determinate
+ttk::progressbar $w.p2 -mode indeterminate
+ttk::button $w.start -text "Start Progress" -command [list \
+ doBars start $w.p1 $w.p2]
+ttk::button $w.stop -text "Stop Progress" -command [list \
+ doBars stop $w.p1 $w.p2]
+
+grid $w.p1 - -pady 5 -padx 10
+grid $w.p2 - -pady 5 -padx 10
+grid $w.start $w.stop -padx 10 -pady 5
+grid configure $w.start -sticky e
+grid configure $w.stop -sticky w
+grid columnconfigure $w all -weight 1
diff --git a/tk8.6/library/demos/ttkscale.tcl b/tk8.6/library/demos/ttkscale.tcl
new file mode 100644
index 0000000..1a95416
--- /dev/null
+++ b/tk8.6/library/demos/ttkscale.tcl
@@ -0,0 +1,39 @@
+# ttkscale.tcl --
+#
+# This demonstration script shows an example with a horizontal scale.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .ttkscale
+catch {destroy $w}
+toplevel $w -bg [ttk::style lookup TLabel -background]
+wm title $w "Themed Scale Demonstration"
+wm iconname $w "ttkscale"
+positionWindow $w
+
+pack [ttk::frame [set w $w.contents]] -fill both -expand 1
+
+ttk::label $w.msg -font $font -wraplength 3.5i -justify left -text "A label tied to a horizontal scale is displayed below. If you click or drag mouse button 1 in the scale, you can change the contents of the label; a callback command is used to couple the slider to both the text and the coloring of the label."
+pack $w.msg -side top -padx .5c
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons [winfo toplevel $w]]
+pack $btns -side bottom -fill x
+
+ttk::frame $w.frame -borderwidth 10
+pack $w.frame -side top -fill x
+
+# List of colors from rainbox; "Indigo" is not a standard color
+set colorList {Red Orange Yellow Green Blue Violet}
+ttk::label $w.frame.label
+ttk::scale $w.frame.scale -from 0 -to 5 -command [list apply {{w idx} {
+ set c [lindex $::colorList [tcl::mathfunc::int $idx]]
+ $w.frame.label configure -foreground $c -text "Color: $c"
+}} $w]
+# Trigger the setting of the label's text
+$w.frame.scale set 0
+pack $w.frame.label $w.frame.scale
diff --git a/tk8.6/library/demos/twind.tcl b/tk8.6/library/demos/twind.tcl
new file mode 100644
index 0000000..df879e3
--- /dev/null
+++ b/tk8.6/library/demos/twind.tcl
@@ -0,0 +1,351 @@
+# twind.tcl --
+#
+# This demonstration script creates a text widget with a bunch of
+# embedded windows.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+# Make an Aqua button's fill color match its parent's background
+proc blend {bt} {
+ if {[tk windowingsystem] eq "aqua"} {
+ $bt configure -highlightbackground [[winfo parent $bt] cget -background]
+ }
+ return $bt
+}
+
+set w .twind
+catch {destroy $w}
+toplevel $w
+wm title $w "Text Demonstration - Embedded Windows and Other Features"
+wm iconname $w "Embedded Windows"
+positionWindow $w
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+frame $w.f -highlightthickness 1 -borderwidth 1 -relief sunken
+set t $w.f.text
+text $t -yscrollcommand "$w.scroll set" -setgrid true -font $font -width 70 \
+ -height 35 -wrap word -highlightthickness 0 -borderwidth 0
+pack $t -expand yes -fill both
+ttk::scrollbar $w.scroll -command "$t yview"
+pack $w.scroll -side right -fill y
+panedwindow $w.pane
+pack $w.pane -expand yes -fill both
+$w.pane add $w.f
+# Import to raise given creation order above
+raise $w.f
+
+$t tag configure center -justify center -spacing1 5m -spacing3 5m
+$t tag configure buttons -lmargin1 1c -lmargin2 1c -rmargin 1c \
+ -spacing1 3m -spacing2 0 -spacing3 0
+
+button $t.on -text "Turn On" -command "textWindOn $w" \
+ -cursor top_left_arrow
+button $t.off -text "Turn Off" -command "textWindOff $w" \
+ -cursor top_left_arrow
+
+$t insert end "A text widget can contain many different kinds of items, "
+$t insert end "both active and passive. It can lay these out in various "
+$t insert end "ways, with wrapping, tabs, centering, etc. In addition, "
+$t insert end "when the contents are too big for the window, smooth "
+$t insert end "scrolling in all directions is provided.\n\n"
+
+$t insert end "A text widget can contain other widgets embedded "
+$t insert end "it. These are called \"embedded windows\", "
+$t insert end "and they can consist of arbitrary widgets. "
+$t insert end "For example, here are two embedded button "
+$t insert end "widgets. You can click on the first button to "
+$t window create end -window [blend $t.on]
+$t insert end " horizontal scrolling, which also turns off "
+$t insert end "word wrapping. Or, you can click on the second "
+$t insert end "button to\n"
+$t window create end -window [blend $t.off]
+$t insert end " horizontal scrolling and turn back on word wrapping.\n\n"
+
+$t insert end "Or, here is another example. If you "
+$t window create end -create {
+ button %W.click -text "Click Here" -command "textWindPlot %W" \
+ -cursor top_left_arrow
+ blend %W.click
+}
+
+$t insert end " a canvas displaying an x-y plot will appear right here."
+$t mark set plot insert
+$t mark gravity plot left
+$t insert end " You can drag the data points around with the mouse, "
+$t insert end "or you can click here to "
+$t window create end -create {
+ button %W.delete -text "Delete" -command "textWindDel %W" \
+ -cursor top_left_arrow
+ blend %W.delete
+}
+$t insert end " the plot again.\n\n"
+
+$t insert end "You can also create multiple text widgets each of which "
+$t insert end "display the same underlying text. Click this button to "
+$t window create end \
+ -create {button %W.peer -text "Make A Peer" -command "textMakePeer %W" \
+ -cursor top_left_arrow
+ blend %W.peer} -padx 3
+$t insert end " widget. Notice how peer widgets can have different "
+$t insert end "font settings, and by default contain all the images "
+$t insert end "of the 'parent', but that the embedded windows, "
+$t insert end "such as buttons may not appear in the peer. To ensure "
+$t insert end "that embedded windows appear in all peers you can set the "
+$t insert end "'-create' option to a script or a string containing %W. "
+$t insert end "(The plot above and the 'Make A Peer' button are "
+$t insert end "designed to show up in all peers.) A good use of "
+$t insert end "peers is for "
+$t window create end \
+ -create {button %W.split -text "Split Windows" -command "textSplitWindow %W" \
+ -cursor top_left_arrow
+ blend %W.split} -padx 3
+$t insert end " \n\n"
+
+$t insert end "Users of previous versions of Tk will also be interested "
+$t insert end "to note that now cursor movement is now by visual line by "
+$t insert end "default, and that all scrolling of this widget is by pixel.\n\n"
+
+$t insert end "You may also find it useful to put embedded windows in "
+$t insert end "a text without any actual text. In this case the "
+$t insert end "text widget acts like a geometry manager. For "
+$t insert end "example, here is a collection of buttons laid out "
+$t insert end "neatly into rows by the text widget. These buttons "
+$t insert end "can be used to change the background color of the "
+$t insert end "text widget (\"Default\" restores the color to "
+$t insert end "its default). If you click on the button labeled "
+$t insert end "\"Short\", it changes to a longer string so that "
+$t insert end "you can see how the text widget automatically "
+$t insert end "changes the layout. Click on the button again "
+$t insert end "to restore the short string.\n"
+
+$t insert end "\nNOTE: these buttons will not appear in peers!\n" "peer_warning"
+button $t.default -text Default -command "embDefBg $t" \
+ -cursor top_left_arrow
+$t window create end -window $t.default -padx 3
+global embToggle
+set embToggle Short
+checkbutton $t.toggle -textvariable embToggle -indicatoron 0 \
+ -variable embToggle -onvalue "A much longer string" \
+ -offvalue "Short" -cursor top_left_arrow -pady 5 -padx 2
+$t window create end -window $t.toggle -padx 3 -pady 2
+set i 1
+foreach color {AntiqueWhite3 Bisque1 Bisque2 Bisque3 Bisque4
+ SlateBlue3 RoyalBlue1 SteelBlue2 DeepSkyBlue3 LightBlue1
+ DarkSlateGray1 Aquamarine2 DarkSeaGreen2 SeaGreen1
+ Yellow1 IndianRed1 IndianRed2 Tan1 Tan4} {
+ button $t.color$i -text $color -cursor top_left_arrow -command \
+ "changeBg $t $color"
+ $t window create end -window [blend $t.color$i] -padx 3 -pady 2
+ incr i
+}
+$t tag add buttons [blend $t.default] end
+
+button $t.bigB -text "Big borders" -command "textWindBigB $t" \
+ -cursor top_left_arrow
+button $t.smallB -text "Small borders" -command "textWindSmallB $t" \
+ -cursor top_left_arrow
+button $t.bigH -text "Big highlight" -command "textWindBigH $t" \
+ -cursor top_left_arrow
+button $t.smallH -text "Small highlight" -command "textWindSmallH $t" \
+ -cursor top_left_arrow
+button $t.bigP -text "Big pad" -command "textWindBigP $t" \
+ -cursor top_left_arrow
+button $t.smallP -text "Small pad" -command "textWindSmallP $t" \
+ -cursor top_left_arrow
+
+set text_normal(border) [$t cget -borderwidth]
+set text_normal(highlight) [$t cget -highlightthickness]
+set text_normal(pad) [$t cget -padx]
+
+$t insert end "\nYou can also change the usual border width and "
+$t insert end "highlightthickness and padding.\n"
+$t window create end -window [blend $t.bigB]
+$t window create end -window [blend $t.smallB]
+$t window create end -window [blend $t.bigH]
+$t window create end -window [blend $t.smallH]
+$t window create end -window [blend $t.bigP]
+$t window create end -window [blend $t.smallP]
+
+$t insert end "\n\nFinally, images fit comfortably in text widgets too:"
+
+$t image create end -image \
+ [image create photo -file [file join $tk_demoDirectory images ouster.png]]
+
+proc textWindBigB w {
+ $w configure -borderwidth 15
+}
+
+proc textWindBigH w {
+ $w configure -highlightthickness 15
+}
+
+proc textWindBigP w {
+ $w configure -padx 15 -pady 15
+}
+
+proc textWindSmallB w {
+ $w configure -borderwidth $::text_normal(border)
+}
+
+proc textWindSmallH w {
+ $w configure -highlightthickness $::text_normal(highlight)
+}
+
+proc textWindSmallP w {
+ $w configure -padx $::text_normal(pad) -pady $::text_normal(pad)
+}
+
+proc textWindOn w {
+ catch {destroy $w.scroll2}
+ set t $w.f.text
+ ttk::scrollbar $w.scroll2 -orient horizontal -command "$t xview"
+ pack $w.scroll2 -after $w.buttons -side bottom -fill x
+ $t configure -xscrollcommand "$w.scroll2 set" -wrap none
+}
+
+proc textWindOff w {
+ catch {destroy $w.scroll2}
+ set t $w.f.text
+ $t configure -xscrollcommand {} -wrap word
+}
+
+proc textWindPlot t {
+ set c $t.c
+ if {[winfo exists $c]} {
+ return
+ }
+
+ while {[string first [$t get plot] " \t\n"] >= 0} {
+ $t delete plot
+ }
+ $t insert plot "\n"
+
+ $t window create plot -create {createPlot %W}
+ $t tag add center plot
+ $t insert plot "\n"
+}
+
+proc createPlot {t} {
+ set c $t.c
+
+ canvas $c -relief sunken -width 450 -height 300 -cursor top_left_arrow
+
+ set font {Helvetica 18}
+
+ $c create line 100 250 400 250 -width 2
+ $c create line 100 250 100 50 -width 2
+ $c create text 225 20 -text "A Simple Plot" -font $font -fill brown
+
+ for {set i 0} {$i <= 10} {incr i} {
+ set x [expr {100 + ($i*30)}]
+ $c create line $x 250 $x 245 -width 2
+ $c create text $x 254 -text [expr {10*$i}] -anchor n -font $font
+ }
+ for {set i 0} {$i <= 5} {incr i} {
+ set y [expr {250 - ($i*40)}]
+ $c create line 100 $y 105 $y -width 2
+ $c create text 96 $y -text [expr {$i*50}].0 -anchor e -font $font
+ }
+
+ foreach point {
+ {12 56} {20 94} {33 98} {32 120} {61 180} {75 160} {98 223}
+ } {
+ set x [expr {100 + (3*[lindex $point 0])}]
+ set y [expr {250 - (4*[lindex $point 1])/5}]
+ set item [$c create oval [expr {$x-6}] [expr {$y-6}] \
+ [expr {$x+6}] [expr {$y+6}] -width 1 -outline black \
+ -fill SkyBlue2]
+ $c addtag point withtag $item
+ }
+
+ $c bind point <Any-Enter> "$c itemconfig current -fill red"
+ $c bind point <Any-Leave> "$c itemconfig current -fill SkyBlue2"
+ $c bind point <1> "embPlotDown $c %x %y"
+ $c bind point <ButtonRelease-1> "$c dtag selected"
+ bind $c <B1-Motion> "embPlotMove $c %x %y"
+ return $c
+}
+
+set embPlot(lastX) 0
+set embPlot(lastY) 0
+
+proc embPlotDown {w x y} {
+ global embPlot
+ $w dtag selected
+ $w addtag selected withtag current
+ $w raise current
+ set embPlot(lastX) $x
+ set embPlot(lastY) $y
+}
+
+proc embPlotMove {w x y} {
+ global embPlot
+ $w move selected [expr {$x-$embPlot(lastX)}] [expr {$y-$embPlot(lastY)}]
+ set embPlot(lastX) $x
+ set embPlot(lastY) $y
+}
+
+proc textWindDel t {
+ if {[winfo exists $t.c]} {
+ $t delete $t.c
+ while {[string first [$t get plot] " \t\n"] >= 0} {
+ $t delete plot
+ }
+ $t insert plot " "
+ }
+}
+
+proc changeBg {t c} {
+ $t configure -background $c
+ if {[tk windowingsystem] eq "aqua"} {
+ foreach b [$t window names] {
+ if {[winfo class $b] eq "Button"} {
+ $b configure -highlightbackground $c
+ }
+ }
+ }
+}
+
+proc embDefBg t {
+ set bg [lindex [$t configure -background] 3]
+ changeBg $t $bg
+}
+
+proc textMakePeer {parent} {
+ set n 1
+ while {[winfo exists .peer$n]} { incr n }
+ set w [toplevel .peer$n]
+ wm title $w "Text Peer #$n"
+ frame $w.f -highlightthickness 1 -borderwidth 1 -relief sunken
+ set t [$parent peer create $w.f.text -yscrollcommand "$w.scroll set" \
+ -borderwidth 0 -highlightthickness 0]
+ $t tag configure peer_warning -font boldFont
+ pack $t -expand yes -fill both
+ ttk::scrollbar $w.scroll -command "$t yview"
+ pack $w.scroll -side right -fill y
+ pack $w.f -expand yes -fill both
+}
+
+proc textSplitWindow {textW} {
+ if {$textW eq ".twind.f.text"} {
+ if {[winfo exists .twind.peer]} {
+ destroy .twind.peer
+ } else {
+ set parent [winfo parent $textW]
+ set w [winfo parent $parent]
+ set t [$textW peer create $w.peer \
+ -yscrollcommand "$w.scroll set"]
+ $t tag configure peer_warning -font boldFont
+ $w.pane add $t
+ }
+ } else {
+ return
+ }
+}
diff --git a/tk8.6/library/demos/unicodeout.tcl b/tk8.6/library/demos/unicodeout.tcl
new file mode 100644
index 0000000..faa9f90
--- /dev/null
+++ b/tk8.6/library/demos/unicodeout.tcl
@@ -0,0 +1,137 @@
+# unicodeout.tcl --
+#
+# This demonstration script shows how you can produce output (in label
+# widgets) using many different alphabets.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .unicodeout
+catch {destroy $w}
+toplevel $w
+wm title $w "Unicode Label Demonstration"
+wm iconname $w "unicodeout"
+positionWindow $w
+
+label $w.msg -font $font -wraplength 4i -anchor w -justify left \
+ -text "This is a sample of Tk's support for languages that use\
+ non-Western character sets. However, what you will actually see\
+ below depends largely on what character sets you have installed,\
+ and what you see for characters that are not present varies greatly\
+ between platforms as well. The strings are written in Tcl using\
+ UNICODE characters using the \\uXXXX escape so as to do so in a\
+ portable fashion."
+pack $w.msg -side top
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+## The frame that will contain the sample texts.
+pack [frame $w.f] -side bottom -expand 1 -fill both -padx 2m -pady 1m
+grid columnconfigure $w.f 1 -weight 1
+set i 0
+proc addSample {w language args} {
+ global font i
+ set sample [join $args ""]
+ set j [incr i]
+ label $w.f.l$j -font $font -text "${language}:" -anchor nw -pady 0
+ label $w.f.s$j -font $font -text $sample -anchor nw -width 30 -pady 0
+ grid $w.f.l$j $w.f.s$j -sticky ew -pady 0
+ grid configure $w.f.l$j -padx 1m
+}
+
+## A helper procedure that determines what form to use to express languages
+## that have complex rendering rules...
+proc usePresentationFormsFor {language} {
+ switch [tk windowingsystem] {
+ aqua {
+ # OSX wants natural character order; the renderer knows how to
+ # compose things for display for all languages.
+ return false
+ }
+ x11 {
+ # The X11 font renderers that Tk supports all know nothing about
+ # composing characters, so we need to use presentation forms.
+ return true
+ }
+ win32 {
+ # On Windows, we need to determine whether the font system will
+ # render right-to-left text. This varies by language!
+ try {
+ package require registry
+ set rkey [join {
+ HKEY_LOCAL_MACHINE
+ SOFTWARE
+ Microsoft
+ {Windows NT}
+ CurrentVersion
+ LanguagePack
+ } \\]
+ return [expr {
+ [string toupper $language] ni [registry values $rkey]
+ }]
+ } trap error {} {
+ # Cannot work it out, so use presentation forms.
+ return true
+ }
+ }
+ default {
+ # Default to using presentation forms.
+ return true
+ }
+ }
+}
+
+## Processing when some characters are not currently cached by the display
+## engine might take a while, so make sure we're displaying something in the
+## meantime...
+pack [label $w.wait -text "Please wait while loading fonts..." \
+ -font {Helvetica 12 italic}]
+set oldCursor [$w cget -cursor]
+$w conf -cursor watch
+update
+
+## Add the samples...
+if {[usePresentationFormsFor Arabic]} {
+ # Using presentation forms (pre-layouted)
+ addSample $w Arabic \
+ "\uFE94\uFEF4\uFE91\uFEAE\uFECC\uFEDF\uFE8D " \
+ "\uFE94\uFEE4\uFEE0\uFEDC\uFEDF\uFE8D"
+} else {
+ # Using standard text characters
+ addSample $w Arabic \
+ "\u0627\u0644\u0643\u0644\u0645\u0629 " \
+ "\u0627\u0644\u0639\u0631\u0628\u064A\u0629"
+}
+addSample $w "Trad. Chinese" "\u4E2D\u570B\u7684\u6F22\u5B57"
+addSample $w "Simpl. Chinese" "\u6C49\u8BED"
+addSample $w French "Langue fran\u00E7aise"
+addSample $w Greek \
+ "\u0395\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AE " \
+ "\u03B3\u03BB\u03CE\u03C3\u03C3\u03B1"
+if {[usePresentationFormsFor Hebrew]} {
+ # Visual order (pre-layouted)
+ addSample $w Hebrew \
+ "\u05EA\u05D9\u05E8\u05D1\u05E2 \u05D1\u05EA\u05DB"
+} else {
+ # Standard logical order
+ addSample $w Hebrew \
+ "\u05DB\u05EA\u05D1 \u05E2\u05D1\u05E8\u05D9\u05EA"
+}
+addSample $w Hindi \
+ "\u0939\u093f\u0928\u094d\u0926\u0940 \u092d\u093e\u0937\u093e"
+addSample $w Icelandic "\u00CDslenska"
+addSample $w Japanese \
+ "\u65E5\u672C\u8A9E\u306E\u3072\u3089\u304C\u306A, " \
+ "\u6F22\u5B57\u3068\u30AB\u30BF\u30AB\u30CA"
+addSample $w Korean "\uB300\uD55C\uBBFC\uAD6D\uC758 \uD55C\uAE00"
+addSample $w Russian \
+ "\u0420\u0443\u0441\u0441\u043A\u0438\u0439 \u044F\u0437\u044B\u043A"
+
+## We're done processing, so change things back to normal running...
+destroy $w.wait
+$w conf -cursor $oldCursor
diff --git a/tk8.6/library/demos/vscale.tcl b/tk8.6/library/demos/vscale.tcl
new file mode 100644
index 0000000..2c7ea76
--- /dev/null
+++ b/tk8.6/library/demos/vscale.tcl
@@ -0,0 +1,46 @@
+# vscale.tcl --
+#
+# This demonstration script shows an example with a vertical scale.
+
+if {![info exists widgetDemo]} {
+ error "This script should be run from the \"widget\" demo."
+}
+
+package require Tk
+
+set w .vscale
+catch {destroy $w}
+toplevel $w
+wm title $w "Vertical Scale Demonstration"
+wm iconname $w "vscale"
+positionWindow $w
+
+label $w.msg -font $font -wraplength 3.5i -justify left -text "An arrow and a vertical scale are displayed below. If you click or drag mouse button 1 in the scale, you can change the size of the arrow."
+pack $w.msg -side top -padx .5c
+
+## See Code / Dismiss buttons
+set btns [addSeeDismiss $w.buttons $w]
+pack $btns -side bottom -fill x
+
+frame $w.frame -borderwidth 10
+pack $w.frame
+
+scale $w.frame.scale -orient vertical -length 284 -from 0 -to 250 \
+ -command "setHeight $w.frame.canvas" -tickinterval 50
+canvas $w.frame.canvas -width 50 -height 50 -bd 0 -highlightthickness 0
+$w.frame.canvas create polygon 0 0 1 1 2 2 -fill SeaGreen3 -tags poly
+$w.frame.canvas create line 0 0 1 1 2 2 0 0 -fill black -tags line
+frame $w.frame.right -borderwidth 15
+pack $w.frame.scale -side left -anchor ne
+pack $w.frame.canvas -side left -anchor nw -fill y
+$w.frame.scale set 75
+
+proc setHeight {w height} {
+ incr height 21
+ set y2 [expr {$height - 30}]
+ if {$y2 < 21} {
+ set y2 21
+ }
+ $w coords poly 15 20 35 20 35 $y2 45 $y2 25 $height 5 $y2 15 $y2 15 20
+ $w coords line 15 20 35 20 35 $y2 45 $y2 25 $height 5 $y2 15 $y2 15 20
+}
diff --git a/tk8.6/library/demos/widget b/tk8.6/library/demos/widget
new file mode 100644
index 0000000..6d0b045
--- /dev/null
+++ b/tk8.6/library/demos/widget
@@ -0,0 +1,721 @@
+#!/bin/sh
+# the next line restarts using wish \
+exec wish "$0" ${1+"$@"}
+
+# widget --
+# This script demonstrates the various widgets provided by Tk, along with many
+# of the features of the Tk toolkit. This file only contains code to generate
+# the main window for the application, which invokes individual
+# demonstrations. The code for the actual demonstrations is contained in
+# separate ".tcl" files is this directory, which are sourced by this script as
+# needed.
+
+package require Tk 8.5
+package require msgcat
+
+eval destroy [winfo child .]
+set tk_demoDirectory [file join [pwd] [file dirname [info script]]]
+::msgcat::mcload $tk_demoDirectory
+namespace import ::msgcat::mc
+wm title . [mc "Widget Demonstration"]
+if {[tk windowingsystem] eq "x11"} {
+ # This won't work everywhere, but there's no other way in core Tk at the
+ # moment to display a coloured icon.
+ image create photo TclPowered \
+ -file [file join $tk_library images logo64.gif]
+ wm iconwindow . [toplevel ._iconWindow]
+ pack [label ._iconWindow.i -image TclPowered]
+ wm iconname . [mc "tkWidgetDemo"]
+}
+
+if {"defaultFont" ni [font names]} {
+ # TIP #145 defines some standard named fonts
+ if {"TkDefaultFont" in [font names] && "TkFixedFont" in [font names]} {
+ # FIX ME: the following technique of cloning the font to copy it works
+ # fine but means that if the system font is changed by Tk
+ # cannot update the copied font. font alias might be useful
+ # here -- or fix the app to use TkDefaultFont etc.
+ font create mainFont {*}[font configure TkDefaultFont]
+ font create fixedFont {*}[font configure TkFixedFont]
+ font create boldFont {*}[font configure TkDefaultFont] -weight bold
+ font create titleFont {*}[font configure TkDefaultFont] -weight bold
+ font create statusFont {*}[font configure TkDefaultFont]
+ font create varsFont {*}[font configure TkDefaultFont]
+ if {[tk windowingsystem] eq "aqua"} {
+ font configure titleFont -size 17
+ }
+ } else {
+ font create mainFont -family Helvetica -size 12
+ font create fixedFont -family Courier -size 10
+ font create boldFont -family Helvetica -size 12 -weight bold
+ font create titleFont -family Helvetica -size 18 -weight bold
+ font create statusFont -family Helvetica -size 10
+ font create varsFont -family Helvetica -size 14
+ }
+}
+
+set widgetDemo 1
+set font mainFont
+
+image create photo ::img::refresh -format GIF -data {
+ R0lGODlhEAAQAJEDAP///wAAACpnKv///yH5BAEAAAMALAAAAAAQABAAAAI63IKp
+ xgcPH2ouwgBCw1HIxHCQ4F3hSJKmwZXqWrmWxj7lKJ2dndcon9EBUq+gz3brVXAR
+ 2tICU0gXBQA7
+}
+
+image create photo ::img::view -format GIF -data {
+ R0lGODlhEAAQAKIHAP///wwMDAAAAMDAwNnZ2SYmJmZmZv///yH5BAEAAAcALAAA
+ AAAQABAAAANMKLos90+ASamDRxJCgw9YVnlDOXiQBgRDBRgHKE6sW8QR3doPKK27
+ yg33q/GIOhdg6OsEJzeZykiBSUcs06e56Xx6np8ScIkFGuhQAgA7
+}
+
+image create photo ::img::delete -format GIF -data {
+ R0lGODlhEAAQAIABAIQAAP///yH5BAEAAAEALAAAAAAQABAAAAIjjI+pmwAc3HGy
+ PUSvqYpuvWQg40FfSVacBa5nN6JYDI3mzRQAOw==
+}
+
+image create photo ::img::print -format GIF -data {
+ R0lGODlhEAAQALMKAAAAAP///52VunNkl8C82Yl+qldBgq+pyrOzs1fYAP///wAA
+ AAAAAAAAAAAAAAAAACH5BAEAAAoALAAAAAAQABAAAARGUMlJKwU4AztB+ODGeUiJ
+ fGLlgeEYmGWQXmx7aXgmAUTv/74N4EAsGhOJg1DAbDqbwoJ0Sp0KB9isNis0eL/g
+ ryhH5pgnEQA7
+}
+
+# Note that this is run through the message catalog! This is because this is
+# actually an image of a word.
+image create photo ::img::new -format GIF -data [mc {
+ R0lGODlhHgAOALMPALMAANyIiOu7u8dEROaqqvru7sxVVeGZmbgREfXd3b0iItZ3
+ d8IzM9FmZvDMzP///yH5BAEAAA8ALAAAAAAeAA4AAASa8MlJq7046827WVOCHEkw
+ nANhUgJlEBIABJIwL3K+4IcUALCHjfbItYZDSgJgkBiYPmBMAUAkkLPKs/BAyLgM
+ wAQwOAAY2ByCaw4QAFQSoDEePJ6DmU1xInYZTw5nOEFFdgVUelkVDTIMd3AKFGQ1
+ MgI2AwEmQW8APZ0gdRONAks5nhIFVVxdAAkUAS2pAVwFl7ITB4UqHb0XEQA7
+}]
+
+#----------------------------------------------------------------
+# The code below creates the main window, consisting of a menu bar and a text
+# widget that explains how to use the program, plus lists all of the demos as
+# hypertext items.
+#----------------------------------------------------------------
+
+menu .menuBar -tearoff 0
+
+# On Aqua, just use the default menu.
+if {[tk windowingsystem] ne "aqua"} {
+ # This is a tk-internal procedure to make i18n easier
+ ::tk::AmpMenuArgs .menuBar add cascade -label [mc "&File"] \
+ -menu .menuBar.file
+ menu .menuBar.file -tearoff 0
+ ::tk::AmpMenuArgs .menuBar.file add command -label [mc "&About..."] \
+ -command {tkAboutDialog} -accelerator [mc "<F1>"]
+ bind . <F1> {tkAboutDialog}
+ .menuBar.file add sep
+ if {[string match win* [tk windowingsystem]]} {
+ # Windows doesn't usually have a Meta key
+ ::tk::AmpMenuArgs .menuBar.file add command -label [mc "&Quit"] \
+ -command {exit} -accelerator [mc "Ctrl+Q"]
+ bind . <[mc "Control-q"]> {exit}
+ } else {
+ ::tk::AmpMenuArgs .menuBar.file add command -label [mc "&Quit"] \
+ -command {exit} -accelerator [mc "Meta-Q"]
+ bind . <[mc "Meta-q"]> {exit}
+ }
+ . configure -menu .menuBar
+}
+
+ttk::frame .statusBar
+ttk::label .statusBar.lab -text " " -anchor w
+if {[tk windowingsystem] eq "aqua"} {
+ ttk::separator .statusBar.sep
+ pack .statusBar.sep -side top -expand yes -fill x -pady 0
+}
+pack .statusBar.lab -side left -padx 2 -expand yes -fill both
+if {[tk windowingsystem] ne "aqua"} {
+ ttk::sizegrip .statusBar.foo
+ pack .statusBar.foo -side left -padx 2
+}
+pack .statusBar -side bottom -fill x -pady 2
+
+set textheight 30
+catch {
+ set textheight [expr {
+ ([winfo screenheight .] * 0.7) /
+ [font metrics mainFont -displayof . -linespace]
+ }]
+}
+
+ttk::frame .textFrame
+ttk::scrollbar .s -orient vertical -command {.t yview} -takefocus 1
+pack .s -in .textFrame -side right -fill y
+text .t -yscrollcommand {.s set} -wrap word -width 70 -height $textheight \
+ -font mainFont -setgrid 1 -highlightthickness 0 \
+ -padx 4 -pady 2 -takefocus 0
+pack .t -in .textFrame -expand y -fill both -padx 1
+pack .textFrame -expand yes -fill both
+if {[tk windowingsystem] eq "aqua"} {
+ pack configure .statusBar.lab -padx {10 18} -pady {4 6}
+ pack configure .statusBar -pady 0
+ .t configure -padx 10 -pady 0
+}
+
+# Create a bunch of tags to use in the text widget, such as those for section
+# titles and demo descriptions. Also define the bindings for tags.
+
+.t tag configure title -font titleFont
+.t tag configure subtitle -font titleFont
+.t tag configure bold -font boldFont
+if {[tk windowingsystem] eq "aqua"} {
+ .t tag configure title -spacing1 8
+ .t tag configure subtitle -spacing3 3
+}
+
+# We put some "space" characters to the left and right of each demo
+# description so that the descriptions are highlighted only when the mouse
+# cursor is right over them (but not when the cursor is to their left or
+# right).
+#
+.t tag configure demospace -lmargin1 1c -lmargin2 1c
+
+if {[winfo depth .] == 1} {
+ .t tag configure demo -lmargin1 1c -lmargin2 1c \
+ -underline 1
+ .t tag configure visited -lmargin1 1c -lmargin2 1c \
+ -underline 1
+ .t tag configure hot -background black -foreground white
+} else {
+ .t tag configure demo -lmargin1 1c -lmargin2 1c \
+ -foreground blue -underline 1
+ .t tag configure visited -lmargin1 1c -lmargin2 1c \
+ -foreground #303080 -underline 1
+ .t tag configure hot -foreground red -underline 1
+}
+.t tag bind demo <ButtonRelease-1> {
+ invoke [.t index {@%x,%y}]
+}
+set lastLine ""
+.t tag bind demo <Enter> {
+ set lastLine [.t index {@%x,%y linestart}]
+ .t tag add hot "$lastLine +1 chars" "$lastLine lineend -1 chars"
+ .t config -cursor [::ttk::cursor link]
+ showStatus [.t index {@%x,%y}]
+}
+.t tag bind demo <Leave> {
+ .t tag remove hot 1.0 end
+ .t config -cursor [::ttk::cursor text]
+ .statusBar.lab config -text ""
+}
+.t tag bind demo <Motion> {
+ set newLine [.t index {@%x,%y linestart}]
+ if {$newLine ne $lastLine} {
+ .t tag remove hot 1.0 end
+ set lastLine $newLine
+
+ set tags [.t tag names {@%x,%y}]
+ set i [lsearch -glob $tags demo-*]
+ if {$i >= 0} {
+ .t tag add hot "$lastLine +1 chars" "$lastLine lineend -1 chars"
+ }
+ }
+ showStatus [.t index {@%x,%y}]
+}
+
+##############################################################################
+# Create the text for the text widget.
+
+# addFormattedText --
+#
+# Add formatted text (but not hypertext) to the text widget after first
+# passing it through the message catalog to allow for localization.
+# Lines starting with @@ are formatting directives (insert title, insert
+# demo hyperlink, begin newline, or change style) and all other lines
+# are literal strings to be inserted. Substitutions are performed,
+# allowing processing pieces through the message catalog. Blank lines
+# are ignored.
+#
+proc addFormattedText {formattedText} {
+ set style normal
+ set isNL 1
+ set demoCount 0
+ set new 0
+ foreach line [split $formattedText \n] {
+ set line [string trim $line]
+ if {$line eq ""} {
+ continue
+ }
+ if {[string match @@* $line]} {
+ set data [string range $line 2 end]
+ set key [lindex $data 0]
+ set values [lrange $data 1 end]
+ switch -exact -- $key {
+ title {
+ .t insert end [mc $values]\n title \n normal
+ }
+ newline {
+ .t insert end \n $style
+ set isNL 1
+ }
+ subtitle {
+ .t insert end "\n" {} [mc $values] subtitle \
+ " \n " demospace
+ set demoCount 0
+ }
+ demo {
+ set description [lassign $values name]
+ .t insert end "[incr demoCount]. [mc $description]" \
+ [list demo demo-$name]
+ if {$new} {
+ .t image create end -image ::img::new -padx 5
+ set new 0
+ }
+ .t insert end " \n " demospace
+ }
+ new {
+ set new 1
+ }
+ default {
+ set style $key
+ }
+ }
+ continue
+ }
+ if {!$isNL} {
+ .t insert end " " $style
+ }
+ set isNL 0
+ .t insert end [mc $line] $style
+ }
+}
+
+addFormattedText {
+ @@title Tk Widget Demonstrations
+
+ This application provides a front end for several short scripts
+ that demonstrate what you can do with Tk widgets. Each of the
+ numbered lines below describes a demonstration; you can click on
+ it to invoke the demonstration. Once the demonstration window
+ appears, you can click the
+ @@bold
+ See Code
+ @@normal
+ button to see the Tcl/Tk code that created the demonstration. If
+ you wish, you can edit the code and click the
+ @@bold
+ Rerun Demo
+ @@normal
+ button in the code window to reinvoke the demonstration with the
+ modified code.
+ @@newline
+
+ @@subtitle Labels, buttons, checkbuttons, and radiobuttons
+ @@demo label Labels (text and bitmaps)
+ @@demo unicodeout Labels and UNICODE text
+ @@demo button Buttons
+ @@demo check Check-buttons (select any of a group)
+ @@demo radio Radio-buttons (select one of a group)
+ @@demo puzzle A 15-puzzle game made out of buttons
+ @@demo icon Iconic buttons that use bitmaps
+ @@demo image1 Two labels displaying images
+ @@demo image2 A simple user interface for viewing images
+ @@demo labelframe Labelled frames
+ @@demo ttkbut The simple Themed Tk widgets
+
+ @@subtitle Listboxes and Trees
+ @@demo states The 50 states
+ @@demo colors Colors: change the color scheme for the application
+ @@demo sayings A collection of famous and infamous sayings
+ @@demo mclist A multi-column list of countries
+ @@demo tree A directory browser tree
+
+ @@subtitle Entries, Spin-boxes and Combo-boxes
+ @@demo entry1 Entries without scrollbars
+ @@demo entry2 Entries with scrollbars
+ @@demo entry3 Validated entries and password fields
+ @@demo spin Spin-boxes
+ @@demo combo Combo-boxes
+ @@demo form Simple Rolodex-like form
+
+ @@subtitle Text
+ @@demo text Basic editable text
+ @@demo style Text display styles
+ @@demo bind Hypertext (tag bindings)
+ @@demo twind A text widget with embedded windows and other features
+ @@demo search A search tool built with a text widget
+ @@demo textpeer Peering text widgets
+
+ @@subtitle Canvases
+ @@demo items The canvas item types
+ @@demo plot A simple 2-D plot
+ @@demo ctext Text items in canvases
+ @@demo arrow An editor for arrowheads on canvas lines
+ @@demo ruler A ruler with adjustable tab stops
+ @@demo floor A building floor plan
+ @@demo cscroll A simple scrollable canvas
+ @@demo knightstour A Knight's tour of the chess board
+
+ @@subtitle Scales and Progress Bars
+ @@demo hscale Horizontal scale
+ @@demo vscale Vertical scale
+ @@new
+ @@demo ttkscale Themed scale linked to a label with traces
+ @@demo ttkprogress Progress bar
+
+ @@subtitle Paned Windows and Notebooks
+ @@demo paned1 Horizontal paned window
+ @@demo paned2 Vertical paned window
+ @@demo ttkpane Themed nested panes
+ @@demo ttknote Notebook widget
+
+ @@subtitle Menus and Toolbars
+ @@demo menu Menus and cascades (sub-menus)
+ @@demo menubu Menu-buttons
+ @@demo ttkmenu Themed menu buttons
+ @@demo toolbar Themed toolbar
+
+ @@subtitle Common Dialogs
+ @@demo msgbox Message boxes
+ @@demo filebox File selection dialog
+ @@demo clrpick Color picker
+ @@demo fontchoose Font selection dialog
+
+ @@subtitle Animation
+ @@demo anilabel Animated labels
+ @@demo aniwave Animated wave
+ @@demo pendulum Pendulum simulation
+ @@demo goldberg A celebration of Rube Goldberg
+
+ @@subtitle Miscellaneous
+ @@demo bitmap The built-in bitmaps
+ @@demo dialog1 A dialog box with a local grab
+ @@demo dialog2 A dialog box with a global grab
+}
+
+##############################################################################
+
+.t configure -state disabled
+focus .s
+
+# addSeeDismiss --
+# Add "See Code" and "Dismiss" button frame, with optional "See Vars"
+#
+# Arguments:
+# w - The name of the frame to use.
+
+proc addSeeDismiss {w show {vars {}} {extra {}}} {
+ ## See Code / Dismiss buttons
+ ttk::frame $w
+ ttk::separator $w.sep
+ #ttk::frame $w.sep -height 2 -relief sunken
+ grid $w.sep -columnspan 4 -row 0 -sticky ew -pady 2
+ ttk::button $w.dismiss -text [mc "Dismiss"] \
+ -image ::img::delete -compound left \
+ -command [list destroy [winfo toplevel $w]]
+ ttk::button $w.code -text [mc "See Code"] \
+ -image ::img::view -compound left \
+ -command [list showCode $show]
+ set buttons [list x $w.code $w.dismiss]
+ if {[llength $vars]} {
+ ttk::button $w.vars -text [mc "See Variables"] \
+ -image ::img::view -compound left \
+ -command [concat [list showVars $w.dialog] $vars]
+ set buttons [linsert $buttons 1 $w.vars]
+ }
+ if {$extra ne ""} {
+ set buttons [linsert $buttons 1 [uplevel 1 $extra]]
+ }
+ grid {*}$buttons -padx 4 -pady 4
+ grid columnconfigure $w 0 -weight 1
+ if {[tk windowingsystem] eq "aqua"} {
+ foreach b [lrange $buttons 1 end] {$b configure -takefocus 0}
+ grid configure $w.sep -pady 0
+ grid configure {*}$buttons -pady {10 12}
+ grid configure [lindex $buttons 1] -padx {16 4}
+ grid configure [lindex $buttons end] -padx {4 18}
+ }
+ return $w
+}
+
+# positionWindow --
+# This procedure is invoked by most of the demos to position a new demo
+# window.
+#
+# Arguments:
+# w - The name of the window to position.
+
+proc positionWindow w {
+ wm geometry $w +300+300
+}
+
+# showVars --
+# Displays the values of one or more variables in a window, and updates the
+# display whenever any of the variables changes.
+#
+# Arguments:
+# w - Name of new window to create for display.
+# args - Any number of names of variables.
+
+proc showVars {w args} {
+ catch {destroy $w}
+ toplevel $w
+ if {[tk windowingsystem] eq "x11"} {wm attributes $w -type dialog}
+ wm title $w [mc "Variable values"]
+
+ set b [ttk::frame $w.frame]
+ grid $b -sticky news
+ set f [ttk::labelframe $b.title -text [mc "Variable values:"]]
+ foreach var $args {
+ ttk::label $f.n$var -text "$var:" -anchor w
+ ttk::label $f.v$var -textvariable $var -anchor w
+ grid $f.n$var $f.v$var -padx 2 -pady 2 -sticky w
+ }
+ ttk::button $b.ok -text [mc "OK"] \
+ -command [list destroy $w] -default active
+ bind $w <Return> [list $b.ok invoke]
+ bind $w <Escape> [list $b.ok invoke]
+
+ grid $f -sticky news -padx 4
+ grid $b.ok -sticky e -padx 4 -pady {6 4}
+ if {[tk windowingsystem] eq "aqua"} {
+ $b.ok configure -takefocus 0
+ grid configure $b.ok -pady {10 12} -padx {16 18}
+ grid configure $f -padx 10 -pady {10 0}
+ }
+ grid columnconfig $f 1 -weight 1
+ grid rowconfigure $f 100 -weight 1
+ grid columnconfig $b 0 -weight 1
+ grid rowconfigure $b 0 -weight 1
+ grid columnconfig $w 0 -weight 1
+ grid rowconfigure $w 0 -weight 1
+}
+
+# invoke --
+# This procedure is called when the user clicks on a demo description. It is
+# responsible for invoking the demonstration.
+#
+# Arguments:
+# index - The index of the character that the user clicked on.
+
+proc invoke index {
+ global tk_demoDirectory
+ set tags [.t tag names $index]
+ set i [lsearch -glob $tags demo-*]
+ if {$i < 0} {
+ return
+ }
+ set cursor [.t cget -cursor]
+ .t configure -cursor [::ttk::cursor busy]
+ update
+ set demo [string range [lindex $tags $i] 5 end]
+ uplevel 1 [list source [file join $tk_demoDirectory $demo.tcl]]
+ update
+ .t configure -cursor $cursor
+
+ .t tag add visited "$index linestart +1 chars" "$index lineend -1 chars"
+}
+
+# showStatus --
+#
+# Show the name of the demo program in the status bar. This procedure is
+# called when the user moves the cursor over a demo description.
+#
+proc showStatus index {
+ set tags [.t tag names $index]
+ set i [lsearch -glob $tags demo-*]
+ set cursor [.t cget -cursor]
+ if {$i < 0} {
+ .statusBar.lab config -text " "
+ set newcursor [::ttk::cursor text]
+ } else {
+ set demo [string range [lindex $tags $i] 5 end]
+ .statusBar.lab config -text [mc "Run the \"%s\" sample program" $demo]
+ set newcursor [::ttk::cursor link]
+ }
+ if {$cursor ne $newcursor} {
+ .t config -cursor $newcursor
+ }
+}
+
+# evalShowCode --
+#
+# Arguments:
+# w - Name of text widget containing code to eval
+
+proc evalShowCode {w} {
+ set code [$w get 1.0 end-1c]
+ uplevel #0 $code
+}
+
+# showCode --
+# This procedure creates a toplevel window that displays the code for a
+# demonstration and allows it to be edited and reinvoked.
+#
+# Arguments:
+# w - The name of the demonstration's window, which can be used to
+# derive the name of the file containing its code.
+
+proc showCode w {
+ global tk_demoDirectory
+ set file [string range $w 1 end].tcl
+ set top .code
+ if {![winfo exists $top]} {
+ toplevel $top
+ if {[tk windowingsystem] eq "x11"} {wm attributes $top -type dialog}
+
+ set t [frame $top.f]
+ set text [text $t.text -font fixedFont -height 24 -wrap word \
+ -xscrollcommand [list $t.xscroll set] \
+ -yscrollcommand [list $t.yscroll set] \
+ -setgrid 1 -highlightthickness 0 -pady 2 -padx 3]
+ ttk::scrollbar $t.xscroll -command [list $t.text xview] \
+ -orient horizontal
+ ttk::scrollbar $t.yscroll -command [list $t.text yview] \
+ -orient vertical
+
+ grid $t.text $t.yscroll -sticky news
+ #grid $t.xscroll
+ grid rowconfigure $t 0 -weight 1
+ grid columnconfig $t 0 -weight 1
+
+ set btns [ttk::frame $top.btns]
+ ttk::separator $btns.sep
+ grid $btns.sep -columnspan 4 -row 0 -sticky ew -pady 2
+ ttk::button $btns.dismiss -text [mc "Dismiss"] \
+ -default active -command [list destroy $top] \
+ -image ::img::delete -compound left
+ ttk::button $btns.print -text [mc "Print Code"] \
+ -command [list printCode $text $file] \
+ -image ::img::print -compound left
+ ttk::button $btns.rerun -text [mc "Rerun Demo"] \
+ -command [list evalShowCode $text] \
+ -image ::img::refresh -compound left
+ set buttons [list x $btns.rerun $btns.print $btns.dismiss]
+ grid {*}$buttons -padx 4 -pady 4
+ grid columnconfigure $btns 0 -weight 1
+ if {[tk windowingsystem] eq "aqua"} {
+ foreach b [lrange $buttons 1 end] {$b configure -takefocus 0}
+ grid configure $btns.sep -pady 0
+ grid configure {*}$buttons -pady {10 12}
+ grid configure [lindex $buttons 1] -padx {16 4}
+ grid configure [lindex $buttons end] -padx {4 18}
+ }
+ grid $t -sticky news
+ grid $btns -sticky ew
+ grid rowconfigure $top 0 -weight 1
+ grid columnconfig $top 0 -weight 1
+
+ bind $top <Return> {
+ if {[winfo class %W] ne "Text"} { .code.btns.dismiss invoke }
+ }
+ bind $top <Escape> [bind $top <Return>]
+ } else {
+ wm deiconify $top
+ raise $top
+ }
+ wm title $top [mc "Demo code: %s" [file join $tk_demoDirectory $file]]
+ wm iconname $top $file
+ set id [open [file join $tk_demoDirectory $file]]
+ $top.f.text delete 1.0 end
+ $top.f.text insert 1.0 [read $id]
+ $top.f.text mark set insert 1.0
+ close $id
+}
+
+# printCode --
+# Prints the source code currently displayed in the See Code dialog. Much
+# thanks to Arjen Markus for this.
+#
+# Arguments:
+# w - Name of text widget containing code to print
+# file - Name of the original file (implicitly for title)
+
+proc printCode {w file} {
+ set code [$w get 1.0 end-1c]
+
+ set dir "."
+ if {[info exists ::env(HOME)]} {
+ set dir "$::env(HOME)"
+ }
+ if {[info exists ::env(TMP)]} {
+ set dir $::env(TMP)
+ }
+ if {[info exists ::env(TEMP)]} {
+ set dir $::env(TEMP)
+ }
+
+ set filename [file join $dir "tkdemo-$file"]
+ set outfile [open $filename "w"]
+ puts $outfile $code
+ close $outfile
+
+ switch -- $::tcl_platform(platform) {
+ unix {
+ if {[catch {exec lp -c $filename} msg]} {
+ tk_messageBox -title "Print spooling failure" \
+ -message "Print spooling probably failed: $msg"
+ }
+ }
+ windows {
+ if {[catch {PrintTextWin32 $filename} msg]} {
+ tk_messageBox -title "Print spooling failure" \
+ -message "Print spooling probably failed: $msg"
+ }
+ }
+ default {
+ tk_messageBox -title "Operation not Implemented" \
+ -message "Wow! Unknown platform: $::tcl_platform(platform)"
+ }
+ }
+
+ #
+ # Be careful to throw away the temporary file in a gentle manner ...
+ #
+ if {[file exists $filename]} {
+ catch {file delete $filename}
+ }
+}
+
+# PrintTextWin32 --
+# Print a file under Windows using all the "intelligence" necessary
+#
+# Arguments:
+# filename - Name of the file
+#
+# Note:
+# Taken from the Wiki page by Keith Vetter, "Printing text files under
+# Windows".
+# Note:
+# Do not execute the command in the background: that way we can dispose of the
+# file smoothly.
+#
+proc PrintTextWin32 {filename} {
+ package require registry
+ set app [auto_execok notepad.exe]
+ set pcmd "$app /p %1"
+ catch {
+ set app [registry get {HKEY_CLASSES_ROOT\.txt} {}]
+ set pcmd [registry get \
+ {HKEY_CLASSES_ROOT\\$app\\shell\\print\\command} {}]
+ }
+
+ regsub -all {%1} $pcmd $filename pcmd
+ puts $pcmd
+
+ regsub -all {\\} $pcmd {\\\\} pcmd
+ set command "[auto_execok start] /min $pcmd"
+ eval exec $command
+}
+
+# tkAboutDialog --
+#
+# Pops up a message box with an "about" message
+#
+proc tkAboutDialog {} {
+ tk_messageBox -icon info -type ok -title [mc "About Widget Demo"] \
+ -message [mc "Tk widget demonstration application"] -detail \
+"[mc "Copyright \u00a9 %s" {1996-1997 Sun Microsystems, Inc.}]
+[mc "Copyright \u00a9 %s" {1997-2000 Ajuba Solutions, Inc.}]
+[mc "Copyright \u00a9 %s" {2001-2009 Donal K. Fellows}]
+[mc "Copyright \u00a9 %s" {2002-2007 Daniel A. Steffen}]"
+}
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tk8.6/library/dialog.tcl b/tk8.6/library/dialog.tcl
new file mode 100644
index 0000000..c751621
--- /dev/null
+++ b/tk8.6/library/dialog.tcl
@@ -0,0 +1,180 @@
+# dialog.tcl --
+#
+# This file defines the procedure tk_dialog, which creates a dialog
+# box containing a bitmap, a message, and one or more buttons.
+#
+# Copyright (c) 1992-1993 The Regents of the University of California.
+# Copyright (c) 1994-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.
+#
+
+#
+# ::tk_dialog:
+#
+# This procedure displays a dialog box, waits for a button in the dialog
+# to be invoked, then returns the index of the selected button. If the
+# dialog somehow gets destroyed, -1 is returned.
+#
+# Arguments:
+# w - Window to use for dialog top-level.
+# title - Title to display in dialog's decorative frame.
+# text - Message to display in dialog.
+# bitmap - Bitmap to display in dialog (empty string means none).
+# default - Index of button that is to display the default ring
+# (-1 means none).
+# args - One or more strings to display in buttons across the
+# bottom of the dialog box.
+
+proc ::tk_dialog {w title text bitmap default args} {
+ variable ::tk::Priv
+
+ # Check that $default was properly given
+ if {[string is integer -strict $default]} {
+ if {$default >= [llength $args]} {
+ return -code error -errorcode {TK DIALOG BAD_DEFAULT} \
+ "default button index greater than number of buttons\
+ specified for tk_dialog"
+ }
+ } elseif {"" eq $default} {
+ set default -1
+ } else {
+ set default [lsearch -exact $args $default]
+ }
+
+ set windowingsystem [tk windowingsystem]
+ if {$windowingsystem eq "aqua"} {
+ option add *Dialog*background systemDialogBackgroundActive widgetDefault
+ option add *Dialog*Button.highlightBackground \
+ systemDialogBackgroundActive widgetDefault
+ }
+
+ # 1. Create the top-level window and divide it into top
+ # and bottom parts.
+
+ destroy $w
+ toplevel $w -class Dialog
+ wm title $w $title
+ wm iconname $w Dialog
+ wm protocol $w WM_DELETE_WINDOW { }
+
+ # Dialog boxes should be transient with respect to their parent,
+ # so that they will always stay on top of their parent window. However,
+ # some window managers will create the window as withdrawn if the parent
+ # window is withdrawn or iconified. Combined with the grab we put on the
+ # window, this can hang the entire application. Therefore we only make
+ # the dialog transient if the parent is viewable.
+ #
+ if {[winfo viewable [winfo toplevel [winfo parent $w]]] } {
+ wm transient $w [winfo toplevel [winfo parent $w]]
+ }
+
+ if {$windowingsystem eq "aqua"} {
+ ::tk::unsupported::MacWindowStyle style $w moveableModal {}
+ } elseif {$windowingsystem eq "x11"} {
+ wm attributes $w -type dialog
+ }
+
+ frame $w.bot
+ frame $w.top
+ if {$windowingsystem eq "x11"} {
+ $w.bot configure -relief raised -bd 1
+ $w.top configure -relief raised -bd 1
+ }
+ pack $w.bot -side bottom -fill both
+ pack $w.top -side top -fill both -expand 1
+ grid anchor $w.bot center
+
+ # 2. Fill the top part with bitmap and message (use the option
+ # database for -wraplength and -font so that they can be
+ # overridden by the caller).
+
+ option add *Dialog.msg.wrapLength 3i widgetDefault
+ option add *Dialog.msg.font TkCaptionFont widgetDefault
+
+ label $w.msg -justify left -text $text
+ pack $w.msg -in $w.top -side right -expand 1 -fill both -padx 3m -pady 3m
+ if {$bitmap ne ""} {
+ if {$windowingsystem eq "aqua" && $bitmap eq "error"} {
+ set bitmap "stop"
+ }
+ label $w.bitmap -bitmap $bitmap
+ pack $w.bitmap -in $w.top -side left -padx 3m -pady 3m
+ }
+
+ # 3. Create a row of buttons at the bottom of the dialog.
+
+ set i 0
+ foreach but $args {
+ button $w.button$i -text $but -command [list set ::tk::Priv(button) $i]
+ if {$i == $default} {
+ $w.button$i configure -default active
+ } else {
+ $w.button$i configure -default normal
+ }
+ grid $w.button$i -in $w.bot -column $i -row 0 -sticky ew \
+ -padx 10 -pady 4
+ grid columnconfigure $w.bot $i
+ # We boost the size of some Mac buttons for l&f
+ if {$windowingsystem eq "aqua"} {
+ set tmp [string tolower $but]
+ if {$tmp eq "ok" || $tmp eq "cancel"} {
+ grid columnconfigure $w.bot $i -minsize 90
+ }
+ grid configure $w.button$i -pady 7
+ }
+ incr i
+ }
+
+ # 4. Create a binding for <Return> on the dialog if there is a
+ # default button.
+ # Convention also dictates that if the keyboard focus moves among the
+ # the buttons that the <Return> binding affects the button with the focus.
+
+ if {$default >= 0} {
+ bind $w <Return> [list $w.button$default invoke]
+ }
+ bind $w <<PrevWindow>> [list bind $w <Return> {[tk_focusPrev %W] invoke}]
+ bind $w <<NextWindow>> [list bind $w <Return> {[tk_focusNext %W] invoke}]
+
+ # 5. Create a <Destroy> binding for the window that sets the
+ # button variable to -1; this is needed in case something happens
+ # that destroys the window, such as its parent window being destroyed.
+
+ bind $w <Destroy> {set ::tk::Priv(button) -1}
+
+ # 6. Withdraw the window, then update all the geometry information
+ # so we know how big it wants to be, then center the window in the
+ # display (Motif style) and de-iconify it.
+
+ ::tk::PlaceWindow $w
+ tkwait visibility $w
+
+ # 7. Set a grab and claim the focus too.
+
+ if {$default >= 0} {
+ set focus $w.button$default
+ } else {
+ set focus $w
+ }
+ tk::SetFocusGrab $w $focus
+
+ # 8. Wait for the user to respond, then restore the focus and
+ # return the index of the selected button. Restore the focus
+ # before deleting the window, since otherwise the window manager
+ # may take the focus away so we can't redirect it. Finally,
+ # restore any grab that was in effect.
+
+ vwait ::tk::Priv(button)
+
+ catch {
+ # It's possible that the window has already been destroyed,
+ # hence this "catch". Delete the Destroy handler so that
+ # Priv(button) doesn't get reset by it.
+
+ bind $w <Destroy> {}
+ }
+ tk::RestoreFocusGrab $w $focus
+ return $Priv(button)
+}
diff --git a/tk8.6/library/entry.tcl b/tk8.6/library/entry.tcl
new file mode 100644
index 0000000..0cc9ffb
--- /dev/null
+++ b/tk8.6/library/entry.tcl
@@ -0,0 +1,668 @@
+# entry.tcl --
+#
+# This file defines the default bindings for Tk entry widgets and provides
+# procedures that help in implementing those bindings.
+#
+# Copyright (c) 1992-1994 The Regents of the University of California.
+# Copyright (c) 1994-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.
+#
+
+#-------------------------------------------------------------------------
+# Elements of tk::Priv that are used in this file:
+#
+# afterId - If non-null, it means that auto-scanning is underway
+# and it gives the "after" id for the next auto-scan
+# command to be executed.
+# mouseMoved - Non-zero means the mouse has moved a significant
+# amount since the button went down (so, for example,
+# start dragging out a selection).
+# pressX - X-coordinate at which the mouse button was pressed.
+# selectMode - The style of selection currently underway:
+# char, word, or line.
+# x, y - Last known mouse coordinates for scanning
+# and auto-scanning.
+# data - Used for Cut and Copy
+#-------------------------------------------------------------------------
+
+#-------------------------------------------------------------------------
+# The code below creates the default class bindings for entries.
+#-------------------------------------------------------------------------
+bind Entry <<Cut>> {
+ if {![catch {tk::EntryGetSelection %W} tk::Priv(data)]} {
+ clipboard clear -displayof %W
+ clipboard append -displayof %W $tk::Priv(data)
+ %W delete sel.first sel.last
+ unset tk::Priv(data)
+ }
+}
+bind Entry <<Copy>> {
+ if {![catch {tk::EntryGetSelection %W} tk::Priv(data)]} {
+ clipboard clear -displayof %W
+ clipboard append -displayof %W $tk::Priv(data)
+ unset tk::Priv(data)
+ }
+}
+bind Entry <<Paste>> {
+ catch {
+ if {[tk windowingsystem] ne "x11"} {
+ catch {
+ %W delete sel.first sel.last
+ }
+ }
+ %W insert insert [::tk::GetSelection %W CLIPBOARD]
+ tk::EntrySeeInsert %W
+ }
+}
+bind Entry <<Clear>> {
+ # ignore if there is no selection
+ catch { %W delete sel.first sel.last }
+}
+bind Entry <<PasteSelection>> {
+ if {$tk_strictMotif || ![info exists tk::Priv(mouseMoved)]
+ || !$tk::Priv(mouseMoved)} {
+ tk::EntryPaste %W %x
+ }
+}
+
+bind Entry <<TraverseIn>> {
+ %W selection range 0 end
+ %W icursor end
+}
+
+# Standard Motif bindings:
+
+bind Entry <Map> {
+ if {[tk windowingsystem] eq "aqua"} {
+ ::tk::RegisterServiceWidget %W
+ }
+}
+bind Entry <1> {
+ tk::EntryButton1 %W %x
+ %W selection clear
+}
+bind Entry <B1-Motion> {
+ set tk::Priv(x) %x
+ tk::EntryMouseSelect %W %x
+}
+bind Entry <Double-1> {
+ set tk::Priv(selectMode) word
+ tk::EntryMouseSelect %W %x
+ catch {%W icursor sel.last}
+}
+bind Entry <Triple-1> {
+ set tk::Priv(selectMode) line
+ tk::EntryMouseSelect %W %x
+ catch {%W icursor sel.last}
+}
+bind Entry <Shift-1> {
+ set tk::Priv(selectMode) char
+ %W selection adjust @%x
+}
+bind Entry <Double-Shift-1> {
+ set tk::Priv(selectMode) word
+ tk::EntryMouseSelect %W %x
+}
+bind Entry <Triple-Shift-1> {
+ set tk::Priv(selectMode) line
+ tk::EntryMouseSelect %W %x
+}
+bind Entry <B1-Leave> {
+ set tk::Priv(x) %x
+ tk::EntryAutoScan %W
+}
+bind Entry <B1-Enter> {
+ tk::CancelRepeat
+}
+bind Entry <ButtonRelease-1> {
+ tk::CancelRepeat
+}
+bind Entry <Control-1> {
+ %W icursor @%x
+}
+
+bind Entry <<PrevChar>> {
+ tk::EntrySetCursor %W [expr {[%W index insert] - 1}]
+}
+bind Entry <<NextChar>> {
+ tk::EntrySetCursor %W [expr {[%W index insert] + 1}]
+}
+bind Entry <<SelectPrevChar>> {
+ tk::EntryKeySelect %W [expr {[%W index insert] - 1}]
+ tk::EntrySeeInsert %W
+}
+bind Entry <<SelectNextChar>> {
+ tk::EntryKeySelect %W [expr {[%W index insert] + 1}]
+ tk::EntrySeeInsert %W
+}
+bind Entry <<PrevWord>> {
+ tk::EntrySetCursor %W [tk::EntryPreviousWord %W insert]
+}
+bind Entry <<NextWord>> {
+ tk::EntrySetCursor %W [tk::EntryNextWord %W insert]
+}
+bind Entry <<SelectPrevWord>> {
+ tk::EntryKeySelect %W [tk::EntryPreviousWord %W insert]
+ tk::EntrySeeInsert %W
+}
+bind Entry <<SelectNextWord>> {
+ tk::EntryKeySelect %W [tk::EntryNextWord %W insert]
+ tk::EntrySeeInsert %W
+}
+bind Entry <<LineStart>> {
+ tk::EntrySetCursor %W 0
+}
+bind Entry <<SelectLineStart>> {
+ tk::EntryKeySelect %W 0
+ tk::EntrySeeInsert %W
+}
+bind Entry <<LineEnd>> {
+ tk::EntrySetCursor %W end
+}
+bind Entry <<SelectLineEnd>> {
+ tk::EntryKeySelect %W end
+ tk::EntrySeeInsert %W
+}
+
+bind Entry <Delete> {
+ if {[%W selection present]} {
+ %W delete sel.first sel.last
+ } else {
+ %W delete insert
+ }
+}
+bind Entry <BackSpace> {
+ tk::EntryBackspace %W
+}
+
+bind Entry <Control-space> {
+ %W selection from insert
+}
+bind Entry <Select> {
+ %W selection from insert
+}
+bind Entry <Control-Shift-space> {
+ %W selection adjust insert
+}
+bind Entry <Shift-Select> {
+ %W selection adjust insert
+}
+bind Entry <<SelectAll>> {
+ %W selection range 0 end
+}
+bind Entry <<SelectNone>> {
+ %W selection clear
+}
+bind Entry <KeyPress> {
+ tk::CancelRepeat
+ tk::EntryInsert %W %A
+}
+
+# Ignore all Alt, Meta, and Control keypresses unless explicitly bound.
+# Otherwise, if a widget binding for one of these is defined, the
+# <KeyPress> class binding will also fire and insert the character,
+# which is wrong. Ditto for Escape, Return, and Tab.
+
+bind Entry <Alt-KeyPress> {# nothing}
+bind Entry <Meta-KeyPress> {# nothing}
+bind Entry <Control-KeyPress> {# nothing}
+bind Entry <Escape> {# nothing}
+bind Entry <Return> {# nothing}
+bind Entry <KP_Enter> {# nothing}
+bind Entry <Tab> {# nothing}
+bind Entry <Prior> {# nothing}
+bind Entry <Next> {# nothing}
+if {[tk windowingsystem] eq "aqua"} {
+ bind Entry <Command-KeyPress> {# nothing}
+}
+# Tk-on-Cocoa generates characters for these two keys. [Bug 2971663]
+bind Entry <<NextLine>> {# nothing}
+bind Entry <<PrevLine>> {# nothing}
+
+# On Windows, paste is done using Shift-Insert. Shift-Insert already
+# generates the <<Paste>> event, so we don't need to do anything here.
+if {[tk windowingsystem] ne "win32"} {
+ bind Entry <Insert> {
+ catch {tk::EntryInsert %W [::tk::GetSelection %W PRIMARY]}
+ }
+}
+
+# Additional emacs-like bindings:
+
+bind Entry <Control-d> {
+ if {!$tk_strictMotif} {
+ %W delete insert
+ }
+}
+bind Entry <Control-h> {
+ if {!$tk_strictMotif} {
+ tk::EntryBackspace %W
+ }
+}
+bind Entry <Control-k> {
+ if {!$tk_strictMotif} {
+ %W delete insert end
+ }
+}
+bind Entry <Control-t> {
+ if {!$tk_strictMotif} {
+ tk::EntryTranspose %W
+ }
+}
+bind Entry <Meta-b> {
+ if {!$tk_strictMotif} {
+ tk::EntrySetCursor %W [tk::EntryPreviousWord %W insert]
+ }
+}
+bind Entry <Meta-d> {
+ if {!$tk_strictMotif} {
+ %W delete insert [tk::EntryNextWord %W insert]
+ }
+}
+bind Entry <Meta-f> {
+ if {!$tk_strictMotif} {
+ tk::EntrySetCursor %W [tk::EntryNextWord %W insert]
+ }
+}
+bind Entry <Meta-BackSpace> {
+ if {!$tk_strictMotif} {
+ %W delete [tk::EntryPreviousWord %W insert] insert
+ }
+}
+bind Entry <Meta-Delete> {
+ if {!$tk_strictMotif} {
+ %W delete [tk::EntryPreviousWord %W insert] insert
+ }
+}
+
+# A few additional bindings of my own.
+
+bind Entry <2> {
+ if {!$tk_strictMotif} {
+ ::tk::EntryScanMark %W %x
+ }
+}
+bind Entry <B2-Motion> {
+ if {!$tk_strictMotif} {
+ ::tk::EntryScanDrag %W %x
+ }
+}
+
+# ::tk::EntryClosestGap --
+# Given x and y coordinates, this procedure finds the closest boundary
+# between characters to the given coordinates and returns the index
+# of the character just after the boundary.
+#
+# Arguments:
+# w - The entry window.
+# x - X-coordinate within the window.
+
+proc ::tk::EntryClosestGap {w x} {
+ set pos [$w index @$x]
+ set bbox [$w bbox $pos]
+ if {($x - [lindex $bbox 0]) < ([lindex $bbox 2]/2)} {
+ return $pos
+ }
+ incr pos
+}
+
+# ::tk::EntryButton1 --
+# This procedure is invoked to handle button-1 presses in entry
+# widgets. It moves the insertion cursor, sets the selection anchor,
+# and claims the input focus.
+#
+# Arguments:
+# w - The entry window in which the button was pressed.
+# x - The x-coordinate of the button press.
+
+proc ::tk::EntryButton1 {w x} {
+ variable ::tk::Priv
+
+ set Priv(selectMode) char
+ set Priv(mouseMoved) 0
+ set Priv(pressX) $x
+ $w icursor [EntryClosestGap $w $x]
+ $w selection from insert
+ if {"disabled" ne [$w cget -state]} {
+ focus $w
+ }
+}
+
+# ::tk::EntryMouseSelect --
+# This procedure is invoked when dragging out a selection with
+# the mouse. Depending on the selection mode (character, word,
+# line) it selects in different-sized units. This procedure
+# ignores mouse motions initially until the mouse has moved from
+# one character to another or until there have been multiple clicks.
+#
+# Arguments:
+# w - The entry window in which the button was pressed.
+# x - The x-coordinate of the mouse.
+
+proc ::tk::EntryMouseSelect {w x} {
+ variable ::tk::Priv
+
+ set cur [EntryClosestGap $w $x]
+ set anchor [$w index anchor]
+ if {($cur != $anchor) || (abs($Priv(pressX) - $x) >= 3)} {
+ set Priv(mouseMoved) 1
+ }
+ switch $Priv(selectMode) {
+ char {
+ if {$Priv(mouseMoved)} {
+ if {$cur < $anchor} {
+ $w selection range $cur $anchor
+ } elseif {$cur > $anchor} {
+ $w selection range $anchor $cur
+ } else {
+ $w selection clear
+ }
+ }
+ }
+ word {
+ if {$cur < $anchor} {
+ set before [tcl_wordBreakBefore [$w get] $cur]
+ set after [tcl_wordBreakAfter [$w get] [expr {$anchor-1}]]
+ } elseif {$cur > $anchor} {
+ set before [tcl_wordBreakBefore [$w get] $anchor]
+ set after [tcl_wordBreakAfter [$w get] [expr {$cur - 1}]]
+ } else {
+ if {[$w index @$Priv(pressX)] < $anchor} {
+ incr anchor -1
+ }
+ set before [tcl_wordBreakBefore [$w get] $anchor]
+ set after [tcl_wordBreakAfter [$w get] $anchor]
+ }
+ if {$before < 0} {
+ set before 0
+ }
+ if {$after < 0} {
+ set after end
+ }
+ $w selection range $before $after
+ }
+ line {
+ $w selection range 0 end
+ }
+ }
+ if {$Priv(mouseMoved)} {
+ $w icursor $cur
+ }
+ update idletasks
+}
+
+# ::tk::EntryPaste --
+# This procedure sets the insertion cursor to the current mouse position,
+# pastes the selection there, and sets the focus to the window.
+#
+# Arguments:
+# w - The entry window.
+# x - X position of the mouse.
+
+proc ::tk::EntryPaste {w x} {
+ $w icursor [EntryClosestGap $w $x]
+ catch {$w insert insert [::tk::GetSelection $w PRIMARY]}
+ if {"disabled" ne [$w cget -state]} {
+ focus $w
+ }
+}
+
+# ::tk::EntryAutoScan --
+# This procedure is invoked when the mouse leaves an entry window
+# with button 1 down. It scrolls the window left or right,
+# depending on where the mouse is, and reschedules itself as an
+# "after" command so that the window continues to scroll until the
+# mouse moves back into the window or the mouse button is released.
+#
+# Arguments:
+# w - The entry window.
+
+proc ::tk::EntryAutoScan {w} {
+ variable ::tk::Priv
+ set x $Priv(x)
+ if {![winfo exists $w]} {
+ return
+ }
+ if {$x >= [winfo width $w]} {
+ $w xview scroll 2 units
+ EntryMouseSelect $w $x
+ } elseif {$x < 0} {
+ $w xview scroll -2 units
+ EntryMouseSelect $w $x
+ }
+ set Priv(afterId) [after 50 [list tk::EntryAutoScan $w]]
+}
+
+# ::tk::EntryKeySelect --
+# This procedure is invoked when stroking out selections using the
+# keyboard. It moves the cursor to a new position, then extends
+# the selection to that position.
+#
+# Arguments:
+# w - The entry window.
+# new - A new position for the insertion cursor (the cursor hasn't
+# actually been moved to this position yet).
+
+proc ::tk::EntryKeySelect {w new} {
+ if {![$w selection present]} {
+ $w selection from insert
+ $w selection to $new
+ } else {
+ $w selection adjust $new
+ }
+ $w icursor $new
+}
+
+# ::tk::EntryInsert --
+# Insert a string into an entry at the point of the insertion cursor.
+# If there is a selection in the entry, and it covers the point of the
+# insertion cursor, then delete the selection before inserting.
+#
+# Arguments:
+# w - The entry window in which to insert the string
+# s - The string to insert (usually just a single character)
+
+proc ::tk::EntryInsert {w s} {
+ if {$s eq ""} {
+ return
+ }
+ catch {
+ set insert [$w index insert]
+ if {([$w index sel.first] <= $insert)
+ && ([$w index sel.last] >= $insert)} {
+ $w delete sel.first sel.last
+ }
+ }
+ $w insert insert $s
+ EntrySeeInsert $w
+}
+
+# ::tk::EntryBackspace --
+# Backspace over the character just before the insertion cursor.
+# If backspacing would move the cursor off the left edge of the
+# window, reposition the cursor at about the middle of the window.
+#
+# Arguments:
+# w - The entry window in which to backspace.
+
+proc ::tk::EntryBackspace w {
+ if {[$w selection present]} {
+ $w delete sel.first sel.last
+ } else {
+ set x [expr {[$w index insert] - 1}]
+ if {$x >= 0} {
+ $w delete $x
+ }
+ if {[$w index @0] >= [$w index insert]} {
+ set range [$w xview]
+ set left [lindex $range 0]
+ set right [lindex $range 1]
+ $w xview moveto [expr {$left - ($right - $left)/2.0}]
+ }
+ }
+}
+
+# ::tk::EntrySeeInsert --
+# Make sure that the insertion cursor is visible in the entry window.
+# If not, adjust the view so that it is.
+#
+# Arguments:
+# w - The entry window.
+
+proc ::tk::EntrySeeInsert w {
+ set c [$w index insert]
+ if {($c < [$w index @0]) || ($c > [$w index @[winfo width $w]])} {
+ $w xview $c
+ }
+}
+
+# ::tk::EntrySetCursor -
+# Move the insertion cursor to a given position in an entry. Also
+# clears the selection, if there is one in the entry, and makes sure
+# that the insertion cursor is visible.
+#
+# Arguments:
+# w - The entry window.
+# pos - The desired new position for the cursor in the window.
+
+proc ::tk::EntrySetCursor {w pos} {
+ $w icursor $pos
+ $w selection clear
+ EntrySeeInsert $w
+}
+
+# ::tk::EntryTranspose -
+# This procedure implements the "transpose" function for entry widgets.
+# It tranposes the characters on either side of the insertion cursor,
+# unless the cursor is at the end of the line. In this case it
+# transposes the two characters to the left of the cursor. In either
+# case, the cursor ends up to the right of the transposed characters.
+#
+# Arguments:
+# w - The entry window.
+
+proc ::tk::EntryTranspose w {
+ set i [$w index insert]
+ if {$i < [$w index end]} {
+ incr i
+ }
+ set first [expr {$i-2}]
+ if {$first < 0} {
+ return
+ }
+ set data [$w get]
+ set new [string index $data [expr {$i-1}]][string index $data $first]
+ $w delete $first $i
+ $w insert insert $new
+ EntrySeeInsert $w
+}
+
+# ::tk::EntryNextWord --
+# Returns the index of the next word position after a given position in the
+# entry. The next word is platform dependent and may be either the next
+# end-of-word position or the next start-of-word position after the next
+# end-of-word position.
+#
+# Arguments:
+# w - The entry window in which the cursor is to move.
+# start - Position at which to start search.
+
+if {[tk windowingsystem] eq "win32"} {
+ proc ::tk::EntryNextWord {w start} {
+ set pos [tcl_endOfWord [$w get] [$w index $start]]
+ if {$pos >= 0} {
+ set pos [tcl_startOfNextWord [$w get] $pos]
+ }
+ if {$pos < 0} {
+ return end
+ }
+ return $pos
+ }
+} else {
+ proc ::tk::EntryNextWord {w start} {
+ set pos [tcl_endOfWord [$w get] [$w index $start]]
+ if {$pos < 0} {
+ return end
+ }
+ return $pos
+ }
+}
+
+# ::tk::EntryPreviousWord --
+#
+# Returns the index of the previous word position before a given
+# position in the entry.
+#
+# Arguments:
+# w - The entry window in which the cursor is to move.
+# start - Position at which to start search.
+
+proc ::tk::EntryPreviousWord {w start} {
+ set pos [tcl_startOfPreviousWord [$w get] [$w index $start]]
+ if {$pos < 0} {
+ return 0
+ }
+ return $pos
+}
+
+# ::tk::EntryScanMark --
+#
+# Marks the start of a possible scan drag operation
+#
+# Arguments:
+# w - The entry window from which the text to get
+# x - x location on screen
+
+proc ::tk::EntryScanMark {w x} {
+ $w scan mark $x
+ set ::tk::Priv(x) $x
+ set ::tk::Priv(y) 0 ; # not used
+ set ::tk::Priv(mouseMoved) 0
+}
+
+# ::tk::EntryScanDrag --
+#
+# Marks the start of a possible scan drag operation
+#
+# Arguments:
+# w - The entry window from which the text to get
+# x - x location on screen
+
+proc ::tk::EntryScanDrag {w x} {
+ # Make sure these exist, as some weird situations can trigger the
+ # motion binding without the initial press. [Bug #220269]
+ if {![info exists ::tk::Priv(x)]} { set ::tk::Priv(x) $x }
+ # allow for a delta
+ if {abs($x-$::tk::Priv(x)) > 2} {
+ set ::tk::Priv(mouseMoved) 1
+ }
+ $w scan dragto $x
+}
+
+# ::tk::EntryGetSelection --
+#
+# Returns the selected text of the entry with respect to the -show option.
+#
+# Arguments:
+# w - The entry window from which the text to get
+
+proc ::tk::EntryGetSelection {w} {
+ set entryString [string range [$w get] [$w index sel.first] \
+ [expr {[$w index sel.last] - 1}]]
+ if {[$w cget -show] ne ""} {
+ return [string repeat [string index [$w cget -show] 0] \
+ [string length $entryString]]
+ }
+ return $entryString
+}
+
+
+
+
+
+
+
+
+
diff --git a/tk8.6/library/focus.tcl b/tk8.6/library/focus.tcl
new file mode 100644
index 0000000..640406e
--- /dev/null
+++ b/tk8.6/library/focus.tcl
@@ -0,0 +1,178 @@
+# focus.tcl --
+#
+# This file defines several procedures for managing the input
+# focus.
+#
+# Copyright (c) 1994-1995 Sun Microsystems, Inc.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+
+# ::tk_focusNext --
+# This procedure returns the name of the next window after "w" in
+# "focus order" (the window that should receive the focus next if
+# Tab is typed in w). "Next" is defined by a pre-order search
+# of a top-level and its non-top-level descendants, with the stacking
+# order determining the order of siblings. The "-takefocus" options
+# on windows determine whether or not they should be skipped.
+#
+# Arguments:
+# w - Name of a window.
+
+proc ::tk_focusNext w {
+ set cur $w
+ while {1} {
+
+ # Descend to just before the first child of the current widget.
+
+ set parent $cur
+ set children [winfo children $cur]
+ set i -1
+
+ # Look for the next sibling that isn't a top-level.
+
+ while {1} {
+ incr i
+ if {$i < [llength $children]} {
+ set cur [lindex $children $i]
+ if {[winfo toplevel $cur] eq $cur} {
+ continue
+ } else {
+ break
+ }
+ }
+
+ # No more siblings, so go to the current widget's parent.
+ # If it's a top-level, break out of the loop, otherwise
+ # look for its next sibling.
+
+ set cur $parent
+ if {[winfo toplevel $cur] eq $cur} {
+ break
+ }
+ set parent [winfo parent $parent]
+ set children [winfo children $parent]
+ set i [lsearch -exact $children $cur]
+ }
+ if {$w eq $cur || [tk::FocusOK $cur]} {
+ return $cur
+ }
+ }
+}
+
+# ::tk_focusPrev --
+# This procedure returns the name of the previous window before "w" in
+# "focus order" (the window that should receive the focus next if
+# Shift-Tab is typed in w). "Next" is defined by a pre-order search
+# of a top-level and its non-top-level descendants, with the stacking
+# order determining the order of siblings. The "-takefocus" options
+# on windows determine whether or not they should be skipped.
+#
+# Arguments:
+# w - Name of a window.
+
+proc ::tk_focusPrev w {
+ set cur $w
+ while {1} {
+
+ # Collect information about the current window's position
+ # among its siblings. Also, if the window is a top-level,
+ # then reposition to just after the last child of the window.
+
+ if {[winfo toplevel $cur] eq $cur} {
+ set parent $cur
+ set children [winfo children $cur]
+ set i [llength $children]
+ } else {
+ set parent [winfo parent $cur]
+ set children [winfo children $parent]
+ set i [lsearch -exact $children $cur]
+ }
+
+ # Go to the previous sibling, then descend to its last descendant
+ # (highest in stacking order. While doing this, ignore top-levels
+ # and their descendants. When we run out of descendants, go up
+ # one level to the parent.
+
+ while {$i > 0} {
+ incr i -1
+ set cur [lindex $children $i]
+ if {[winfo toplevel $cur] eq $cur} {
+ continue
+ }
+ set parent $cur
+ set children [winfo children $parent]
+ set i [llength $children]
+ }
+ set cur $parent
+ if {$w eq $cur || [tk::FocusOK $cur]} {
+ return $cur
+ }
+ }
+}
+
+# ::tk::FocusOK --
+#
+# This procedure is invoked to decide whether or not to focus on
+# a given window. It returns 1 if it's OK to focus on the window,
+# 0 if it's not OK. The code first checks whether the window is
+# viewable. If not, then it never focuses on the window. Then it
+# checks the -takefocus option for the window and uses it if it's
+# set. If there's no -takefocus option, the procedure checks to
+# see if (a) the widget isn't disabled, and (b) it has some key
+# bindings. If all of these are true, then 1 is returned.
+#
+# Arguments:
+# w - Name of a window.
+
+proc ::tk::FocusOK w {
+ set code [catch {$w cget -takefocus} value]
+ if {($code == 0) && ($value ne "")} {
+ if {$value == 0} {
+ return 0
+ } elseif {$value == 1} {
+ return [winfo viewable $w]
+ } else {
+ set value [uplevel #0 $value [list $w]]
+ if {$value ne ""} {
+ return $value
+ }
+ }
+ }
+ if {![winfo viewable $w]} {
+ return 0
+ }
+ set code [catch {$w cget -state} value]
+ if {($code == 0) && $value eq "disabled"} {
+ return 0
+ }
+ regexp Key|Focus "[bind $w] [bind [winfo class $w]]"
+}
+
+# ::tk_focusFollowsMouse --
+#
+# If this procedure is invoked, Tk will enter "focus-follows-mouse"
+# mode, where the focus is always on whatever window contains the
+# mouse. If this procedure isn't invoked, then the user typically
+# has to click on a window to give it the focus.
+#
+# Arguments:
+# None.
+
+proc ::tk_focusFollowsMouse {} {
+ set old [bind all <Enter>]
+ set script {
+ if {"%d" eq "NotifyAncestor" || "%d" eq "NotifyNonlinear" \
+ || "%d" eq "NotifyInferior"} {
+ if {[tk::FocusOK %W]} {
+ focus %W
+ }
+ }
+ }
+ if {$old ne ""} {
+ bind all <Enter> "$old; $script"
+ } else {
+ bind all <Enter> $script
+ }
+}
diff --git a/tk8.6/library/fontchooser.tcl b/tk8.6/library/fontchooser.tcl
new file mode 100644
index 0000000..5395acb
--- /dev/null
+++ b/tk8.6/library/fontchooser.tcl
@@ -0,0 +1,452 @@
+# fontchooser.tcl -
+#
+# A themeable Tk font selection dialog. See TIP #324.
+#
+# Copyright (C) 2008 Keith Vetter
+# Copyright (C) 2008 Pat Thoyts <patthoyts@users.sourceforge.net>
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+namespace eval ::tk::fontchooser {
+ variable S
+
+ set S(W) .__tk__fontchooser
+ set S(fonts) [lsort -dictionary [font families]]
+ set S(styles) [list \
+ [::msgcat::mc "Regular"] \
+ [::msgcat::mc "Italic"] \
+ [::msgcat::mc "Bold"] \
+ [::msgcat::mc "Bold Italic"] \
+ ]
+
+ set S(sizes) {8 9 10 11 12 14 16 18 20 22 24 26 28 36 48 72}
+ set S(strike) 0
+ set S(under) 0
+ set S(first) 1
+ set S(sampletext) [::msgcat::mc "AaBbYyZz01"]
+ set S(-parent) .
+ set S(-title) [::msgcat::mc "Font"]
+ set S(-command) ""
+ set S(-font) TkDefaultFont
+}
+
+proc ::tk::fontchooser::Setup {} {
+ variable S
+
+ # Canonical versions of font families, styles, etc. for easier searching
+ set S(fonts,lcase) {}
+ foreach font $S(fonts) { lappend S(fonts,lcase) [string tolower $font]}
+ set S(styles,lcase) {}
+ foreach style $S(styles) { lappend S(styles,lcase) [string tolower $style]}
+ set S(sizes,lcase) $S(sizes)
+
+ ::ttk::style layout FontchooserFrame {
+ Entry.field -sticky news -border true -children {
+ FontchooserFrame.padding -sticky news
+ }
+ }
+ bind [winfo class .] <<ThemeChanged>> \
+ [list +ttk::style layout FontchooserFrame \
+ [ttk::style layout FontchooserFrame]]
+
+ namespace ensemble create -map {
+ show ::tk::fontchooser::Show
+ hide ::tk::fontchooser::Hide
+ configure ::tk::fontchooser::Configure
+ }
+}
+::tk::fontchooser::Setup
+
+proc ::tk::fontchooser::Show {} {
+ variable S
+ if {![winfo exists $S(W)]} {
+ Create
+ wm transient $S(W) [winfo toplevel $S(-parent)]
+ tk::PlaceWindow $S(W) widget $S(-parent)
+ }
+ set S(fonts) [lsort -dictionary [font families]]
+ set S(fonts,lcase) {}
+ foreach font $S(fonts) { lappend S(fonts,lcase) [string tolower $font]}
+ wm deiconify $S(W)
+}
+
+proc ::tk::fontchooser::Hide {} {
+ variable S
+ wm withdraw $S(W)
+}
+
+proc ::tk::fontchooser::Configure {args} {
+ variable S
+
+ set specs {
+ {-parent "" "" . }
+ {-title "" "" ""}
+ {-font "" "" ""}
+ {-command "" "" ""}
+ }
+
+ if {[llength $args] == 0} {
+ set result {}
+ foreach spec $specs {
+ foreach {name xx yy default} $spec break
+ lappend result $name \
+ [expr {[info exists S($name)] ? $S($name) : $default}]
+ }
+ lappend result -visible \
+ [expr {[winfo exists $S(W)] && [winfo ismapped $S(W)]}]
+ return $result
+ }
+ if {[llength $args] == 1} {
+ set option [lindex $args 0]
+ if {[string equal $option "-visible"]} {
+ return [expr {[winfo exists $S(W)] && [winfo ismapped $S(W)]}]
+ } elseif {[info exists S($option)]} {
+ return $S($option)
+ }
+ return -code error -errorcode [list TK LOOKUP OPTION $option] \
+ "bad option \"$option\": must be\
+ -command, -font, -parent, -title or -visible"
+ }
+
+ set cache [dict create -parent $S(-parent) -title $S(-title) \
+ -font $S(-font) -command $S(-command)]
+ set r [tclParseConfigSpec [namespace which -variable S] $specs "" $args]
+ if {![winfo exists $S(-parent)]} {
+ set code [list TK LOOKUP WINDOW $S(-parent)]
+ set err "bad window path name \"$S(-parent)\""
+ array set S $cache
+ return -code error -errorcode $code $err
+ }
+ if {[string trim $S(-title)] eq ""} {
+ set S(-title) [::msgcat::mc "Font"]
+ }
+ if {[winfo exists $S(W)] && [lsearch $args -font] != -1} {
+ Init $S(-font)
+ event generate $S(-parent) <<TkFontchooserFontChanged>>
+ }
+ return $r
+}
+
+proc ::tk::fontchooser::Create {} {
+ variable S
+ set windowName __tk__fontchooser
+ if {$S(-parent) eq "."} {
+ set S(W) .$windowName
+ } else {
+ set S(W) $S(-parent).$windowName
+ }
+
+ # Now build the dialog
+ if {![winfo exists $S(W)]} {
+ toplevel $S(W) -class TkFontDialog
+ if {[package provide tcltest] ne {}} {set ::tk_dialog $S(W)}
+ wm withdraw $S(W)
+ wm title $S(W) $S(-title)
+ wm transient $S(W) [winfo toplevel $S(-parent)]
+
+ set outer [::ttk::frame $S(W).outer -padding {10 10}]
+ ::tk::AmpWidget ::ttk::label $S(W).font -text [::msgcat::mc "&Font:"]
+ ::tk::AmpWidget ::ttk::label $S(W).style -text [::msgcat::mc "Font st&yle:"]
+ ::tk::AmpWidget ::ttk::label $S(W).size -text [::msgcat::mc "&Size:"]
+ ttk::entry $S(W).efont -width 18 \
+ -textvariable [namespace which -variable S](font)
+ ttk::entry $S(W).estyle -width 10 \
+ -textvariable [namespace which -variable S](style)
+ ttk::entry $S(W).esize -textvariable [namespace which -variable S](size) \
+ -width 3 -validate key -validatecommand {string is double %P}
+
+ ttk_slistbox $S(W).lfonts -height 7 -exportselection 0 \
+ -selectmode browse -activestyle none \
+ -listvariable [namespace which -variable S](fonts)
+ ttk_slistbox $S(W).lstyles -width 5 -height 7 -exportselection 0 \
+ -selectmode browse -activestyle none \
+ -listvariable [namespace which -variable S](styles)
+ ttk_slistbox $S(W).lsizes -width 4 -height 7 -exportselection 0 \
+ -selectmode browse -activestyle none \
+ -listvariable [namespace which -variable S](sizes)
+
+ set WE $S(W).effects
+ ::ttk::labelframe $WE -text [::msgcat::mc "Effects"]
+ ::tk::AmpWidget ::ttk::checkbutton $WE.strike \
+ -variable [namespace which -variable S](strike) \
+ -text [::msgcat::mc "Stri&keout"] \
+ -command [namespace code [list Click strike]]
+ ::tk::AmpWidget ::ttk::checkbutton $WE.under \
+ -variable [namespace which -variable S](under) \
+ -text [::msgcat::mc "&Underline"] \
+ -command [namespace code [list Click under]]
+
+ set bbox [::ttk::frame $S(W).bbox]
+ ::ttk::button $S(W).ok -text [::msgcat::mc OK] -default active\
+ -command [namespace code [list Done 1]]
+ ::ttk::button $S(W).cancel -text [::msgcat::mc Cancel] \
+ -command [namespace code [list Done 0]]
+ ::tk::AmpWidget ::ttk::button $S(W).apply -text [::msgcat::mc "&Apply"] \
+ -command [namespace code [list Apply]]
+ wm protocol $S(W) WM_DELETE_WINDOW [namespace code [list Done 0]]
+
+ # Calculate minimum sizes
+ ttk::scrollbar $S(W).tmpvs
+ set scroll_width [winfo reqwidth $S(W).tmpvs]
+ destroy $S(W).tmpvs
+ set minsize(gap) 10
+ set minsize(bbox) [winfo reqwidth $S(W).ok]
+ set minsize(fonts) \
+ [expr {[font measure TkDefaultFont "Helvetica"] + $scroll_width}]
+ set minsize(styles) \
+ [expr {[font measure TkDefaultFont "Bold Italic"] + $scroll_width}]
+ set minsize(sizes) \
+ [expr {[font measure TkDefaultFont "-99"] + $scroll_width}]
+ set min [expr {$minsize(gap) * 4}]
+ foreach {what width} [array get minsize] { incr min $width }
+ wm minsize $S(W) $min 260
+
+ bind $S(W) <Return> [namespace code [list Done 1]]
+ bind $S(W) <Escape> [namespace code [list Done 0]]
+ bind $S(W) <Map> [namespace code [list Visibility %W 1]]
+ bind $S(W) <Unmap> [namespace code [list Visibility %W 0]]
+ bind $S(W) <Destroy> [namespace code [list Visibility %W 0]]
+ bind $S(W).lfonts.list <<ListboxSelect>> [namespace code [list Click font]]
+ bind $S(W).lstyles.list <<ListboxSelect>> [namespace code [list Click style]]
+ bind $S(W).lsizes.list <<ListboxSelect>> [namespace code [list Click size]]
+ bind $S(W) <Alt-Key> [list ::tk::AltKeyInDialog $S(W) %A]
+ bind $S(W).font <<AltUnderlined>> [list ::focus $S(W).efont]
+ bind $S(W).style <<AltUnderlined>> [list ::focus $S(W).estyle]
+ bind $S(W).size <<AltUnderlined>> [list ::focus $S(W).esize]
+ bind $S(W).apply <<AltUnderlined>> [namespace code [list Apply]]
+ bind $WE.strike <<AltUnderlined>> [list $WE.strike invoke]
+ bind $WE.under <<AltUnderlined>> [list $WE.under invoke]
+
+ set WS $S(W).sample
+ ::ttk::labelframe $WS -text [::msgcat::mc "Sample"]
+ ::ttk::label $WS.sample -relief sunken -anchor center \
+ -textvariable [namespace which -variable S](sampletext)
+ set S(sample) $WS.sample
+ grid $WS.sample -sticky news -padx 6 -pady 4
+ grid rowconfigure $WS 0 -weight 1
+ grid columnconfigure $WS 0 -weight 1
+ grid propagate $WS 0
+
+ grid $S(W).ok -in $bbox -sticky new -pady {0 2}
+ grid $S(W).cancel -in $bbox -sticky new -pady 2
+ if {$S(-command) ne ""} {
+ grid $S(W).apply -in $bbox -sticky new -pady 2
+ }
+ grid columnconfigure $bbox 0 -weight 1
+
+ grid $WE.strike -sticky w -padx 10
+ grid $WE.under -sticky w -padx 10 -pady {0 30}
+ grid columnconfigure $WE 1 -weight 1
+
+ grid $S(W).font x $S(W).style x $S(W).size x -in $outer -sticky w
+ grid $S(W).efont x $S(W).estyle x $S(W).esize x $bbox -in $outer -sticky ew
+ grid $S(W).lfonts x $S(W).lstyles x $S(W).lsizes x ^ -in $outer -sticky news
+ grid $WE x $WS - - x ^ -in $outer -sticky news -pady {15 30}
+ grid configure $bbox -sticky n
+ grid columnconfigure $outer {1 3 5} -minsize $minsize(gap)
+ grid columnconfigure $outer {0 2 4} -weight 1
+ grid columnconfigure $outer 0 -minsize $minsize(fonts)
+ grid columnconfigure $outer 2 -minsize $minsize(styles)
+ grid columnconfigure $outer 4 -minsize $minsize(sizes)
+ grid columnconfigure $outer 6 -minsize $minsize(bbox)
+
+ grid $outer -sticky news
+ grid rowconfigure $S(W) 0 -weight 1
+ grid columnconfigure $S(W) 0 -weight 1
+
+ Init $S(-font)
+
+ trace add variable [namespace which -variable S](size) \
+ write [namespace code [list Tracer]]
+ trace add variable [namespace which -variable S](style) \
+ write [namespace code [list Tracer]]
+ trace add variable [namespace which -variable S](font) \
+ write [namespace code [list Tracer]]
+ } else {
+ Init $S(-font)
+ }
+
+ return
+}
+
+# ::tk::fontchooser::Done --
+#
+# Handles teardown of the dialog, calling -command if needed
+#
+# Arguments:
+# ok true if user pressed OK
+#
+proc ::tk::::fontchooser::Done {ok} {
+ variable S
+
+ if {! $ok} {
+ set S(result) ""
+ }
+ trace vdelete S(size) w [namespace code [list Tracer]]
+ trace vdelete S(style) w [namespace code [list Tracer]]
+ trace vdelete S(font) w [namespace code [list Tracer]]
+ destroy $S(W)
+ if {$ok && $S(-command) ne ""} {
+ uplevel #0 $S(-command) [list $S(result)]
+ }
+}
+
+# ::tk::fontchooser::Apply --
+#
+# Call the -command procedure appending the current font
+# Errors are reported via the background error mechanism
+#
+proc ::tk::fontchooser::Apply {} {
+ variable S
+ if {$S(-command) ne ""} {
+ if {[catch {uplevel #0 $S(-command) [list $S(result)]} err]} {
+ ::bgerror $err
+ }
+ }
+ event generate $S(-parent) <<TkFontchooserFontChanged>>
+}
+
+# ::tk::fontchooser::Init --
+#
+# Initializes dialog to a default font
+#
+# Arguments:
+# defaultFont font to use as the default
+#
+proc ::tk::fontchooser::Init {{defaultFont ""}} {
+ variable S
+
+ if {$S(first) || $defaultFont ne ""} {
+ if {$defaultFont eq ""} {
+ set defaultFont [[entry .___e] cget -font]
+ destroy .___e
+ }
+ array set F [font actual $defaultFont]
+ set S(font) $F(-family)
+ set S(size) $F(-size)
+ set S(strike) $F(-overstrike)
+ set S(under) $F(-underline)
+ set S(style) "Regular"
+ if {$F(-weight) eq "bold" && $F(-slant) eq "italic"} {
+ set S(style) "Bold Italic"
+ } elseif {$F(-weight) eq "bold"} {
+ set S(style) "Bold"
+ } elseif {$F(-slant) eq "italic"} {
+ set S(style) "Italic"
+ }
+
+ set S(first) 0
+ }
+
+ Tracer a b c
+ Update
+}
+
+# ::tk::fontchooser::Click --
+#
+# Handles all button clicks, updating the appropriate widgets
+#
+# Arguments:
+# who which widget got pressed
+#
+proc ::tk::fontchooser::Click {who} {
+ variable S
+
+ if {$who eq "font"} {
+ set S(font) [$S(W).lfonts get [$S(W).lfonts curselection]]
+ } elseif {$who eq "style"} {
+ set S(style) [$S(W).lstyles get [$S(W).lstyles curselection]]
+ } elseif {$who eq "size"} {
+ set S(size) [$S(W).lsizes get [$S(W).lsizes curselection]]
+ }
+ Update
+}
+
+# ::tk::fontchooser::Tracer --
+#
+# Handles traces on key variables, updating the appropriate widgets
+#
+# Arguments:
+# standard trace arguments (not used)
+#
+proc ::tk::fontchooser::Tracer {var1 var2 op} {
+ variable S
+
+ set bad 0
+ set nstate normal
+ # Make selection in each listbox
+ foreach var {font style size} {
+ set value [string tolower $S($var)]
+ $S(W).l${var}s selection clear 0 end
+ set n [lsearch -exact $S(${var}s,lcase) $value]
+ $S(W).l${var}s selection set $n
+ if {$n != -1} {
+ set S($var) [lindex $S(${var}s) $n]
+ $S(W).e$var icursor end
+ $S(W).e$var selection clear
+ } else { ;# No match, try prefix
+ # Size is weird: valid numbers are legal but don't display
+ # unless in the font size list
+ set n [lsearch -glob $S(${var}s,lcase) "$value*"]
+ set bad 1
+ if {$var ne "size" || ! [string is double -strict $value]} {
+ set nstate disabled
+ }
+ }
+ $S(W).l${var}s see $n
+ }
+ if {!$bad} { Update }
+ $S(W).ok configure -state $nstate
+}
+
+# ::tk::fontchooser::Update --
+#
+# Shows a sample of the currently selected font
+#
+proc ::tk::fontchooser::Update {} {
+ variable S
+
+ set S(result) [list $S(font) $S(size)]
+ if {$S(style) eq "Bold"} { lappend S(result) bold }
+ if {$S(style) eq "Italic"} { lappend S(result) italic }
+ if {$S(style) eq "Bold Italic"} { lappend S(result) bold italic}
+ if {$S(strike)} { lappend S(result) overstrike}
+ if {$S(under)} { lappend S(result) underline}
+
+ $S(sample) configure -font $S(result)
+}
+
+# ::tk::fontchooser::Visibility --
+#
+# Notify the parent when the dialog visibility changes
+#
+proc ::tk::fontchooser::Visibility {w visible} {
+ variable S
+ if {$w eq $S(W)} {
+ event generate $S(-parent) <<TkFontchooserVisibility>>
+ }
+}
+
+# ::tk::fontchooser::ttk_listbox --
+#
+# Create a properly themed scrolled listbox.
+# This is exactly right on XP but may need adjusting on other platforms.
+#
+proc ::tk::fontchooser::ttk_slistbox {w args} {
+ set f [ttk::frame $w -style FontchooserFrame -padding 2]
+ if {[catch {
+ listbox $f.list -relief flat -highlightthickness 0 -borderwidth 0 {*}$args
+ ttk::scrollbar $f.vs -command [list $f.list yview]
+ $f.list configure -yscrollcommand [list $f.vs set]
+ grid $f.list $f.vs -sticky news
+ grid rowconfigure $f 0 -weight 1
+ grid columnconfigure $f 0 -weight 1
+ interp hide {} $w
+ interp alias {} $w {} $f.list
+ } err opt]} {
+ destroy $f
+ return -options $opt $err
+ }
+ return $w
+}
diff --git a/tk8.6/library/iconlist.tcl b/tk8.6/library/iconlist.tcl
new file mode 100644
index 0000000..62b0b2d
--- /dev/null
+++ b/tk8.6/library/iconlist.tcl
@@ -0,0 +1,696 @@
+# iconlist.tcl
+#
+# Implements the icon-list megawidget used in the "Tk" standard file
+# selection dialog boxes.
+#
+# Copyright (c) 1994-1998 Sun Microsystems, Inc.
+# Copyright (c) 2009 Donal K. Fellows
+#
+# See the file "license.terms" for information on usage and redistribution of
+# this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# API Summary:
+# tk::IconList <path> ?<option> <value>? ...
+# <path> add <imageName> <itemList>
+# <path> cget <option>
+# <path> configure ?<option>? ?<value>? ...
+# <path> deleteall
+# <path> destroy
+# <path> get <itemIndex>
+# <path> index <index>
+# <path> invoke
+# <path> see <index>
+# <path> selection anchor ?<int>?
+# <path> selection clear <first> ?<last>?
+# <path> selection get
+# <path> selection includes <item>
+# <path> selection set <first> ?<last>?
+
+package require Tk 8.6
+
+::tk::Megawidget create ::tk::IconList ::tk::FocusableWidget {
+ variable w canvas sbar accel accelCB fill font index \
+ itemList itemsPerColumn list maxIH maxIW maxTH maxTW noScroll \
+ numItems oldX oldY options rect selected selection textList
+ constructor args {
+ next {*}$args
+ set accelCB {}
+ }
+ destructor {
+ my Reset
+ next
+ }
+
+ method GetSpecs {} {
+ concat [next] {
+ {-command "" "" ""}
+ {-font "" "" "TkIconFont"}
+ {-multiple "" "" "0"}
+ }
+ }
+
+ # ----------------------------------------------------------------------
+
+ method index i {
+ if {![info exist list]} {
+ set list {}
+ }
+ switch -regexp -- $i {
+ "^-?[0-9]+$" {
+ if {$i < 0} {
+ set i 0
+ }
+ if {$i >= [llength $list]} {
+ set i [expr {[llength $list] - 1}]
+ }
+ return $i
+ }
+ "^anchor$" {
+ return $index(anchor)
+ }
+ "^end$" {
+ return [llength $list]
+ }
+ "@-?[0-9]+,-?[0-9]+" {
+ scan $i "@%d,%d" x y
+ set item [$canvas find closest \
+ [$canvas canvasx $x] [$canvas canvasy $y]]
+ return [lindex [$canvas itemcget $item -tags] 1]
+ }
+ }
+ }
+
+ method selection {op args} {
+ switch -exact -- $op {
+ anchor {
+ if {[llength $args] == 1} {
+ set index(anchor) [$w index [lindex $args 0]]
+ } else {
+ return $index(anchor)
+ }
+ }
+ clear {
+ switch [llength $args] {
+ 2 {
+ lassign $args first last
+ }
+ 1 {
+ set first [set last [lindex $args 0]]
+ }
+ default {
+ return -code error -errorcode {TCL WRONGARGS} \
+ "wrong # args: should be\
+ \"[lrange [info level 0] 0 1] first ?last?\""
+ }
+ }
+
+ set first [$w index $first]
+ set last [$w index $last]
+ if {$first > $last} {
+ set tmp $first
+ set first $last
+ set last $tmp
+ }
+ set ind 0
+ foreach item $selection {
+ if {$item >= $first} {
+ set first $ind
+ break
+ }
+ incr ind
+ }
+ set ind [expr {[llength $selection] - 1}]
+ for {} {$ind >= 0} {incr ind -1} {
+ set item [lindex $selection $ind]
+ if {$item <= $last} {
+ set last $ind
+ break
+ }
+ }
+
+ if {$first > $last} {
+ return
+ }
+ set selection [lreplace $selection $first $last]
+ event generate $w <<ListboxSelect>>
+ my DrawSelection
+ }
+ get {
+ return $selection
+ }
+ includes {
+ return [expr {[lindex $args 0] in $selection}]
+ }
+ set {
+ switch [llength $args] {
+ 2 {
+ lassign $args first last
+ }
+ 1 {
+ set first [set last [lindex $args 0]]
+ }
+ default {
+ return -code error -errorcode {TCL WRONGARGS} \
+ "wrong # args: should be\
+ \"[lrange [info level 0] 0 1] first ?last?\""
+ }
+ }
+
+ set first [$w index $first]
+ set last [$w index $last]
+ if {$first > $last} {
+ set tmp $first
+ set first $last
+ set last $tmp
+ }
+
+ for {set i $first} {$i <= $last} {incr i} {
+ lappend selection $i
+ }
+ set selection [lsort -integer -unique $selection]
+ event generate $w <<ListboxSelect>>
+ my DrawSelection
+ }
+ }
+ }
+
+ method get item {
+ set rTag [lindex $list $item 2]
+ lassign $itemList($rTag) iTag tTag text serial
+ return $text
+ }
+
+ # Deletes all the items inside the canvas subwidget and reset the
+ # iconList's state.
+ #
+ method deleteall {} {
+ $canvas delete all
+ unset -nocomplain selected rect list itemList
+ set maxIW 1
+ set maxIH 1
+ set maxTW 1
+ set maxTH 1
+ set numItems 0
+ set noScroll 1
+ set selection {}
+ set index(anchor) ""
+ $sbar set 0.0 1.0
+ $canvas xview moveto 0
+ }
+
+ # Adds an icon into the IconList with the designated image and text
+ #
+ method add {image items} {
+ foreach text $items {
+ set iID item$numItems
+ set iTag [$canvas create image 0 0 -image $image -anchor nw \
+ -tags [list icon $numItems $iID]]
+ set tTag [$canvas create text 0 0 -text $text -anchor nw \
+ -font $options(-font) -fill $fill \
+ -tags [list text $numItems $iID]]
+ set rTag [$canvas create rect 0 0 0 0 -fill "" -outline "" \
+ -tags [list rect $numItems $iID]]
+
+ lassign [$canvas bbox $iTag] x1 y1 x2 y2
+ set iW [expr {$x2 - $x1}]
+ set iH [expr {$y2 - $y1}]
+ if {$maxIW < $iW} {
+ set maxIW $iW
+ }
+ if {$maxIH < $iH} {
+ set maxIH $iH
+ }
+
+ lassign [$canvas bbox $tTag] x1 y1 x2 y2
+ set tW [expr {$x2 - $x1}]
+ set tH [expr {$y2 - $y1}]
+ if {$maxTW < $tW} {
+ set maxTW $tW
+ }
+ if {$maxTH < $tH} {
+ set maxTH $tH
+ }
+
+ lappend list [list $iTag $tTag $rTag $iW $iH $tW $tH $numItems]
+ set itemList($rTag) [list $iTag $tTag $text $numItems]
+ set textList($numItems) [string tolower $text]
+ incr numItems
+ }
+ my WhenIdle Arrange
+ return
+ }
+
+ # Gets called when the user invokes the IconList (usually by
+ # double-clicking or pressing the Return key).
+ #
+ method invoke {} {
+ if {$options(-command) ne "" && [llength $selection]} {
+ uplevel #0 $options(-command)
+ }
+ }
+
+ # If the item is not (completely) visible, scroll the canvas so that it
+ # becomes visible.
+ #
+ method see rTag {
+ if {$noScroll} {
+ return
+ }
+ set sRegion [$canvas cget -scrollregion]
+ if {$sRegion eq ""} {
+ return
+ }
+
+ if {$rTag < 0 || $rTag >= [llength $list]} {
+ return
+ }
+
+ set bbox [$canvas bbox item$rTag]
+ set pad [expr {[$canvas cget -highlightthickness]+[$canvas cget -bd]}]
+
+ set x1 [lindex $bbox 0]
+ set x2 [lindex $bbox 2]
+ incr x1 [expr {$pad * -2}]
+ incr x2 [expr {$pad * -1}]
+
+ set cW [expr {[winfo width $canvas] - $pad*2}]
+
+ set scrollW [expr {[lindex $sRegion 2]-[lindex $sRegion 0]+1}]
+ set dispX [expr {int([lindex [$canvas xview] 0]*$scrollW)}]
+ set oldDispX $dispX
+
+ # check if out of the right edge
+ #
+ if {($x2 - $dispX) >= $cW} {
+ set dispX [expr {$x2 - $cW}]
+ }
+ # check if out of the left edge
+ #
+ if {($x1 - $dispX) < 0} {
+ set dispX $x1
+ }
+
+ if {$oldDispX ne $dispX} {
+ set fraction [expr {double($dispX) / double($scrollW)}]
+ $canvas xview moveto $fraction
+ }
+ }
+
+ # ----------------------------------------------------------------------
+
+ # Places the icons in a column-major arrangement.
+ #
+ method Arrange {} {
+ if {![info exists list]} {
+ if {[info exists canvas] && [winfo exists $canvas]} {
+ set noScroll 1
+ $sbar configure -command ""
+ }
+ return
+ }
+
+ set W [winfo width $canvas]
+ set H [winfo height $canvas]
+ set pad [expr {[$canvas cget -highlightthickness]+[$canvas cget -bd]}]
+ if {$pad < 2} {
+ set pad 2
+ }
+
+ incr W [expr {$pad*-2}]
+ incr H [expr {$pad*-2}]
+
+ set dx [expr {$maxIW + $maxTW + 8}]
+ if {$maxTH > $maxIH} {
+ set dy $maxTH
+ } else {
+ set dy $maxIH
+ }
+ incr dy 2
+ set shift [expr {$maxIW + 4}]
+
+ set x [expr {$pad * 2}]
+ set y [expr {$pad * 1}] ; # Why * 1 ?
+ set usedColumn 0
+ foreach sublist $list {
+ set usedColumn 1
+ lassign $sublist iTag tTag rTag iW iH tW tH
+
+ set i_dy [expr {($dy - $iH)/2}]
+ set t_dy [expr {($dy - $tH)/2}]
+
+ $canvas coords $iTag $x [expr {$y + $i_dy}]
+ $canvas coords $tTag [expr {$x + $shift}] [expr {$y + $t_dy}]
+ $canvas coords $rTag $x $y [expr {$x+$dx}] [expr {$y+$dy}]
+
+ incr y $dy
+ if {($y + $dy) > $H} {
+ set y [expr {$pad * 1}] ; # *1 ?
+ incr x $dx
+ set usedColumn 0
+ }
+ }
+
+ if {$usedColumn} {
+ set sW [expr {$x + $dx}]
+ } else {
+ set sW $x
+ }
+
+ if {$sW < $W} {
+ $canvas configure -scrollregion [list $pad $pad $sW $H]
+ $sbar configure -command ""
+ $canvas xview moveto 0
+ set noScroll 1
+ } else {
+ $canvas configure -scrollregion [list $pad $pad $sW $H]
+ $sbar configure -command [list $canvas xview]
+ set noScroll 0
+ }
+
+ set itemsPerColumn [expr {($H-$pad) / $dy}]
+ if {$itemsPerColumn < 1} {
+ set itemsPerColumn 1
+ }
+
+ my DrawSelection
+ }
+
+ method DrawSelection {} {
+ $canvas delete selection
+ $canvas itemconfigure selectionText -fill black
+ $canvas dtag selectionText
+ set cbg [ttk::style lookup TEntry -selectbackground focus]
+ set cfg [ttk::style lookup TEntry -selectforeground focus]
+ foreach item $selection {
+ set rTag [lindex $list $item 2]
+ foreach {iTag tTag text serial} $itemList($rTag) {
+ break
+ }
+
+ set bbox [$canvas bbox $tTag]
+ $canvas create rect $bbox -fill $cbg -outline $cbg \
+ -tags selection
+ $canvas itemconfigure $tTag -fill $cfg -tags selectionText
+ }
+ $canvas lower selection
+ return
+ }
+
+ # Creates an IconList widget by assembling a canvas widget and a
+ # scrollbar widget. Sets all the bindings necessary for the IconList's
+ # operations.
+ #
+ method Create {} {
+ variable hull
+ set sbar [ttk::scrollbar $hull.sbar -orient horizontal -takefocus 0]
+ catch {$sbar configure -highlightthickness 0}
+ set canvas [canvas $hull.canvas -highlightthick 0 -takefocus 1 \
+ -width 400 -height 120 -background white]
+ pack $sbar -side bottom -fill x -padx 2 -pady {0 2}
+ pack $canvas -expand yes -fill both -padx 2 -pady {2 0}
+
+ $sbar configure -command [list $canvas xview]
+ $canvas configure -xscrollcommand [list $sbar set]
+
+ # Initializes the max icon/text width and height and other variables
+ #
+ set maxIW 1
+ set maxIH 1
+ set maxTW 1
+ set maxTH 1
+ set numItems 0
+ set noScroll 1
+ set selection {}
+ set index(anchor) ""
+ set fg [option get $canvas foreground Foreground]
+ if {$fg eq ""} {
+ set fill black
+ } else {
+ set fill $fg
+ }
+
+ # Creates the event bindings.
+ #
+ bind $canvas <Configure> [namespace code {my WhenIdle Arrange}]
+
+ bind $canvas <1> [namespace code {my Btn1 %x %y}]
+ bind $canvas <B1-Motion> [namespace code {my Motion1 %x %y}]
+ bind $canvas <B1-Leave> [namespace code {my Leave1 %x %y}]
+ bind $canvas <Control-1> [namespace code {my CtrlBtn1 %x %y}]
+ bind $canvas <Shift-1> [namespace code {my ShiftBtn1 %x %y}]
+ bind $canvas <B1-Enter> [list tk::CancelRepeat]
+ bind $canvas <ButtonRelease-1> [list tk::CancelRepeat]
+ bind $canvas <Double-ButtonRelease-1> \
+ [namespace code {my Double1 %x %y}]
+
+ bind $canvas <Control-B1-Motion> {;}
+ bind $canvas <Shift-B1-Motion> [namespace code {my ShiftMotion1 %x %y}]
+
+ bind $canvas <<PrevLine>> [namespace code {my UpDown -1}]
+ bind $canvas <<NextLine>> [namespace code {my UpDown 1}]
+ bind $canvas <<PrevChar>> [namespace code {my LeftRight -1}]
+ bind $canvas <<NextChar>> [namespace code {my LeftRight 1}]
+ bind $canvas <Return> [namespace code {my ReturnKey}]
+ bind $canvas <KeyPress> [namespace code {my KeyPress %A}]
+ bind $canvas <Control-KeyPress> ";"
+ bind $canvas <Alt-KeyPress> ";"
+
+ bind $canvas <FocusIn> [namespace code {my FocusIn}]
+ bind $canvas <FocusOut> [namespace code {my FocusOut}]
+
+ return $w
+ }
+
+ # This procedure is invoked when the mouse leaves an entry window with
+ # button 1 down. It scrolls the window up, down, left, or right,
+ # depending on where the mouse left the window, and reschedules itself
+ # as an "after" command so that the window continues to scroll until the
+ # mouse moves back into the window or the mouse button is released.
+ #
+ method AutoScan {} {
+ if {![winfo exists $w]} return
+ set x $oldX
+ set y $oldY
+ if {$noScroll} {
+ return
+ }
+ if {$x >= [winfo width $canvas]} {
+ $canvas xview scroll 1 units
+ } elseif {$x < 0} {
+ $canvas xview scroll -1 units
+ } elseif {$y >= [winfo height $canvas]} {
+ # do nothing
+ } elseif {$y < 0} {
+ # do nothing
+ } else {
+ return
+ }
+ my Motion1 $x $y
+ set ::tk::Priv(afterId) [after 50 [namespace code {my AutoScan}]]
+ }
+
+ # ----------------------------------------------------------------------
+
+ # Event handlers
+ method Btn1 {x y} {
+ focus $canvas
+ set i [$w index @$x,$y]
+ if {$i eq ""} {
+ return
+ }
+ $w selection clear 0 end
+ $w selection set $i
+ $w selection anchor $i
+ }
+ method CtrlBtn1 {x y} {
+ if {$options(-multiple)} {
+ focus $canvas
+ set i [$w index @$x,$y]
+ if {$i eq ""} {
+ return
+ }
+ if {[$w selection includes $i]} {
+ $w selection clear $i
+ } else {
+ $w selection set $i
+ $w selection anchor $i
+ }
+ }
+ }
+ method ShiftBtn1 {x y} {
+ if {$options(-multiple)} {
+ focus $canvas
+ set i [$w index @$x,$y]
+ if {$i eq ""} {
+ return
+ }
+ if {[$w index anchor] eq ""} {
+ $w selection anchor $i
+ }
+ $w selection clear 0 end
+ $w selection set anchor $i
+ }
+ }
+
+ # Gets called on button-1 motions
+ #
+ method Motion1 {x y} {
+ set oldX $x
+ set oldY $y
+ set i [$w index @$x,$y]
+ if {$i eq ""} {
+ return
+ }
+ $w selection clear 0 end
+ $w selection set $i
+ }
+ method ShiftMotion1 {x y} {
+ set oldX $x
+ set oldY $y
+ set i [$w index @$x,$y]
+ if {$i eq ""} {
+ return
+ }
+ $w selection clear 0 end
+ $w selection set anchor $i
+ }
+ method Double1 {x y} {
+ if {[llength $selection]} {
+ $w invoke
+ }
+ }
+ method ReturnKey {} {
+ $w invoke
+ }
+ method Leave1 {x y} {
+ set oldX $x
+ set oldY $y
+ my AutoScan
+ }
+ method FocusIn {} {
+ $w state focus
+ if {![info exists list]} {
+ return
+ }
+ if {[llength $selection]} {
+ my DrawSelection
+ }
+ }
+ method FocusOut {} {
+ $w state !focus
+ $w selection clear 0 end
+ }
+
+ # Moves the active element up or down by one element
+ #
+ # Arguments:
+ # amount - +1 to move down one item, -1 to move back one item.
+ #
+ method UpDown amount {
+ if {![info exists list]} {
+ return
+ }
+ set curr [$w selection get]
+ if {[llength $curr] == 0} {
+ set i 0
+ } else {
+ set i [$w index anchor]
+ if {$i eq ""} {
+ return
+ }
+ incr i $amount
+ }
+ $w selection clear 0 end
+ $w selection set $i
+ $w selection anchor $i
+ $w see $i
+ }
+
+ # Moves the active element left or right by one column
+ #
+ # Arguments:
+ # amount - +1 to move right one column, -1 to move left one
+ # column
+ #
+ method LeftRight amount {
+ if {![info exists list]} {
+ return
+ }
+ set curr [$w selection get]
+ if {[llength $curr] == 0} {
+ set i 0
+ } else {
+ set i [$w index anchor]
+ if {$i eq ""} {
+ return
+ }
+ incr i [expr {$amount * $itemsPerColumn}]
+ }
+ $w selection clear 0 end
+ $w selection set $i
+ $w selection anchor $i
+ $w see $i
+ }
+
+ # Gets called when user enters an arbitrary key in the listbox.
+ #
+ method KeyPress key {
+ append accel $key
+ my Goto $accel
+ after cancel $accelCB
+ set accelCB [after 500 [namespace code {my Reset}]]
+ }
+
+ method Goto text {
+ if {![info exists list]} {
+ return
+ }
+ if {$text eq "" || $numItems == 0} {
+ return
+ }
+
+ if {[llength [$w selection get]]} {
+ set start [$w index anchor]
+ } else {
+ set start 0
+ }
+ set theIndex -1
+ set less 0
+ set len [string length $text]
+ set len0 [expr {$len - 1}]
+ set i $start
+
+ # Search forward until we find a filename whose prefix is a
+ # case-insensitive match with $text
+ while {1} {
+ if {[string equal -nocase -length $len0 $textList($i) $text]} {
+ set theIndex $i
+ break
+ }
+ incr i
+ if {$i == $numItems} {
+ set i 0
+ }
+ if {$i == $start} {
+ break
+ }
+ }
+
+ if {$theIndex > -1} {
+ $w selection clear 0 end
+ $w selection set $theIndex
+ $w selection anchor $theIndex
+ $w see $theIndex
+ }
+ }
+ method Reset {} {
+ unset -nocomplain accel
+ }
+}
+
+return
+
+# Local Variables:
+# mode: tcl
+# fill-column: 78
+# End:
diff --git a/tk8.6/library/icons.tcl b/tk8.6/library/icons.tcl
new file mode 100644
index 0000000..e53a1bd
--- /dev/null
+++ b/tk8.6/library/icons.tcl
@@ -0,0 +1,153 @@
+# icons.tcl --
+#
+# A set of stock icons for use in Tk dialogs. The icons used here
+# were provided by the Tango Desktop project which provides a
+# unified set of high quality icons licensed under the
+# Creative Commons Attribution Share-Alike license
+# (http://creativecommons.org/licenses/by-sa/3.0/)
+#
+# See http://tango.freedesktop.org/Tango_Desktop_Project
+#
+# Copyright (c) 2009 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+namespace eval ::tk::icons {}
+
+image create photo ::tk::icons::warning -data {
+ iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAABSZJREFU
+ WIXll1toVEcYgL+Zc87u2Yu7MYmrWRuTJuvdiMuqiJd4yYKXgMQKVkSjFR80kFIVJfWCWlvpg4h9
+ 8sXGWGof8iKNICYSo6JgkCBEJRG8ImYThNrNxmaTeM7pQ5IlJkabi0/9YZhhZv7///4z/8zPgf+7
+ KCNRLgdlJijXwRyuDTlcxV9hbzv8nQmxMjg+XDtiOEplkG9PSfkztGmTgmFQd+FCVzwa3fYN/PHZ
+ AcpBaReicW5xcbb64IEQqko8Lc26d/58cxS+/BY6hmJvyEfQBoUpwWCmW1FErKaGWHU13uRk4QkE
+ UtxQNFR7QwIoB4eiKD9PWbVKbb10CZmaCqmpxCormRYO26QQx85B0mcD+AeK0xYvHqu1tNDx+DH6
+ gQM4jh0j3tCA3tGBLyfHLuD7zwJwAcYqun44sHy51nr5MsqsWWj5+djCYdS5c4ldvUr24sU2qarf
+ lUL6qAN0wqH0vDy7+fAhXZEI+v79CNmt7igpofPVK5SmJvyhkJBwYlQBSiHd7vUWZ86bp8WqqtCW
+ LkVbuBAhBEIItGAQ2+rVxG7cICMY1KTDsekc5IwagIQTmStXis47dzBiMfR9+xCi+wb39s79+zFi
+ MczGRjLmzTMlnBoVgLMwyzF+/Cb/lClq2/Xr2AoKUKdPxzAMWltbiUajmKaJkpGBY8sW3tbW4g8E
+ VNXrXVEKK0YMoMKp7Px8K15Tg2VZOHbvBiASiRAMBgkGg0QiEYQQOIuLsRSFrnv3yJo/HxVOW594
+ 7D4KUAa57qysvNSUFOVtbS32rVuRfj9CCFwuV2Kfy+VCCIFMScFVVET7/fukJidLm883rQy+HhaA
+ BUII8cvUNWt4W1WFcLvRd+5MnHl/AOjOB+eOHchx44jX1ZEdCqkSTpaDbcgA5+GrpNmzc9ymKdvr
+ 67Hv2oVMSko4cjgcKIqCoijoup64EdLpxLV3Lx1PnuCVUrgmTfK9hV1DAjgKqlSUk1PCYdl25QrS
+ 70cvLEw4SWS+04nT6XxvXgiBc8MGtKlTaa+rIysnR1Ok/OF38PxngAzY4VuwYKL99WvR8fQpjj17
+ kLqeiL6393g8eDyeAWBSVfEcOkRXczOOaBRvVpZuDPJEDwD4DVyKrv+UlZurxSorUWfMQC8oGOBc
+ CDHgC/Rdc4TD2BctIl5fT+bkyTahaXvOw8RPApiwd2Ju7hjZ2EhXSwvOkhKQcoADgIqKCioqKgYc
+ QW9LOnIEIxZDbWpiXCCABT9+FKAUxtm83pKMUEiLVVejLVqEtmTJB50LIdi2bRuFPbnRd7232efM
+ wbVuHR2PHjHR77dJXS8sg5mDAihweFJenmrevYvR1oazpGTQ6IQQaJqG7ClI/dd655IOHsSyLMSL
+ F6QFAib9nugEQClk2Xy+orTsbK3t1i3sa9ei5eQMGr0QgvLyci5evDiocyEEtsxMPNu30/nsGRO8
+ XlVzu8NlkNvrV+0T/fHMZcusrtu3MeNx9PXrobUVq8cYQrw3TrRub1h9+v573Bs3Ej1zBvP5c/zp
+ 6dbLhoaTwPy+ANKCfF92thq7dg2A6JYt/fNlxGK8eUNSerryHEJHQT8K8V4A5ztojty8OeaLzZul
+ 1DSwLCzDANPEMozusWFgmWZ33288YK3/nGlixuM0v3xpWfDX0Z4i1VupXEWwIgRnJfhGPfQ+YsLr
+ +7DzNFwCuvqWyiRg7DSYoIBu9smPkYqEd4AwIN4ITUAL0A4Da7UC6ICdEfy2fUBMoAvo7GnWKNoe
+ mfwLcAuinuFNL7QAAAAASUVORK5CYII=
+}
+
+image create photo ::tk::icons::error -data {
+ iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAABiRJREFU
+ WIXFl11sHFcVgL97Z/bX693sbtd2ipOqCU7sQKukFYUigQgv/a+hoZGoqipvfQKpAsEDD0hIvCHE
+ j/pQ3sIDUdOiIqUyqXioEFSUhqit7cRJFJpEruxs1mt77Z3d2Z259/KwM5vZXTtOERJXOrozZ+6e
+ 852fuXcW/s9D3O3Cs1Bow1Nx234BKQ9qpYpK6yFLSseScsVoveApdUrAzNOw9j8DOAMTtmX9RsM3
+ SqOjevcXDqUzu8dI5AvEc8O0axu4q6s4yzdZvnCxUSmXLWHMXzxjXpmGq/81wGmIZ6T8NXDi8w8d
+ id//+GPS8j1YWQXHgVYbfA/sGCRiMDQExTzKtvn3zDv6k9m5FsacXNT6+y+D95kAZqCEEO/cMzIy
+ 9eBLLybjyodrN6DpDqw1/dfpFNw3TtuSfPz7P7irlZUL2pjHn4GVuwJ4G/JCiLl9U1OjB58/ZnP5
+ Mqxv3NGpMWZAz64cHNzHlTf/5N9YuHzTMeaLx6HW78+K3pwGKynEu/snJycOHPuWzdw81BuDUQZO
+ dfQ+MmvAuC1MdY3i178izUo15VZXj07DyTf6OGX0Jivlz0vFwgMTz3/bNnMXO0ZCo8b0iIk4C0WF
+ zsP1TRc1e4l9x56N5YuFwxkpf9afgW4J/gi7M1IuHH3lezm5uAQbmwOpjc79ujArA2uMgWwGMz7K
+ P377u/WW1pPTUB7IQFrKXx44NJWRbQ9d2+hGqbeRMEoTZEQFJdERfVgmvVFH+D57Jw9k4lL+YqAE
+ pyGnjZm+95knLHVjcVvHA6WIPgtLE+hVH4i6vsS9T3zTVsY8NwPZHoAUPFUs5JVQCt1q9zqORKm3
+ iLKrF6IjkfSHOiUlqu0hhCSXHdYePNYDEBPiu6MT+zOquo6JGNGhESkxUnYNmkCnLQtjWRgpMRG9
+ CtZ3JdD7axsU9+3N2EK8EALYQcNMpvfuQTcaXUMIAa+/Hi0Xgs9weASjefx4p5mFQDdbpD63G/HR
+ hakeAA2l+EgJU652iIMMyO2sRoYxBq1191oIgZQSITqooT0A7fnEirswUAp/LwG0MZlYIY9WqpPa
+ IHU7Da01Sqluo4UQSil830dr3emVsBeMIZbLoI0Z7gGQQtTbjoOOxW/XewcApVQ38jsBNs6fx6tW
+ O70Si+GWKwghNsM1NoCAW81KJTeUjKNbrR2N7uS4B7TRwJ+fR6TTxO4fxzUeAio9AMCl+tVrE0NH
+ DmM2nU4DAu6JE53UGoNfLuNdv45xnO4OF/ZKz+4X2T179I6D5To0NupouNgD4Btzqjx/8WjpS0cy
+ PU1Tr6MqFfylpc4bss1W26/rBwyfybECtcvXNrUxp3oAXJjZ2Kxb7cVP8P61gDGgWy2M624Z5d1E
+ 3wNkDDKdwMQkjtuygbMhgAQ4DjUhxFvL/5z15X1jeLUaynW7p1u484WiuL3V9m/NoV6F50Ogjx3Y
+ Q/mDBV8a3piGzR4AAFfrHy4vlesmm0bks7edRQ6aAafcPoZVH2AUXOYzkI5TvbVa9+FHREYX4Bgs
+ I8RrV9/9oJF4eBKTjO8YvdoCJgqujcGkEqQemmDxb7OOFOLV6FHcAwBQ1/onTtOd/fTvH3rJRx/A
+ pBIDqd0q+p5sRaInnWDoywdZem+u7bbaH9W1/il9Y2Brfwt22TBfKOVHxr92JOacv4S/UuttuC06
+ PKoHsEs5hg7vZ/m9eW+zWltuwoNbfRNuebacgXsEnE2lkof2Hn04ZRouzQvXUU5z29cwFGs4TWpy
+ HJGK8+lfP256bnuuDU8+B9WtfG17uL0GsTF4VQrxYn60kBh55JDEbdG6uYq/7qDdFtpTELOQyQRW
+ Lk1sLI+MW9w6d8Wv3Vrz2nDyJPzgDDS287MVgAAywBCQ+Q5MTsOPs/BIMpVQ2bFCKlnMYg+nsYeS
+ eE6TVq1Be3WD9ZtrTc9tWetw7k341dtwBagDTmTeESAdAAxH5z0w9iQ8ehi+moWxBGRsiPvguVBf
+ h8qH8P6f4dxSp9PrdN73cN6k859R3U0J0nS+28JMpIM5FUgCiNP5X2ECox7gAk06KQ8ldLzZ7/xO
+ ANHnscBhCkgGjuOB3gb8CEAbaAWO3UA34DQ6/gPnmhBFs5mqXAAAAABJRU5ErkJggg==
+}
+
+image create photo ::tk::icons::information -data {
+ iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBI
+ WXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1gUdFDM4pWaDogAABwNJREFUWMPFlltsVNcVhv+199ln
+ bh7PjAdfMGNDcA04EKMkJlIsBVJVbRqlEVUrqyW0QAtFTVWpjVpFfamUF6K+tCTKQyXn0jaiShOr
+ bRqRoHJpEEoIEBucENuk2OViPB5f5j5zrvuc3YcMFQ8FPBFVj7S0paN91v+tf1/OAv7PD9UzeeCp
+ p0KRCrYyHtymoPrgySYAANdyBBr2Peu1agP+NrR/v3nHAb6/52d7wfivWlet11NdvZG21laEwzo0
+ RvA9F4uLi7h08bxxaWLUVp78xSsv/XrwjgAMDDyjRxPWUGOy5Uu9/VsjEA3I5KvIVQ240gHIh9CA
+ 5YkwelIJRATw94NvGpnpK0fL+eDA0NAzzq3ya7cDjCbsoWWr1j+y4f4vB/41Z8JTeaxqE7hndSNi
+ EeELzn3LkapQdfzJTE5JV/GBb28LHz327lcnzp4ZAvB1AOpmAvyWtv/g6R9GW1c+uf6Bx0Kfzpjo
+ TmnYtDaKtkTAj4aEFBqTnJPUOfciIeG3N4XVQtmyzl/JuY8/fH9wOjO/smvVmuy5s+8P1w2wa9dP
+ 46SLN3sf2ha7uiixaU0Qna06NA6PMXIZQRJBMiIXRBKABygv3hBQV+bK1dmcoR7d3Bc5c/pk/8YN
+ fYOjo6es/6bDbgbAdLa9uXNj2PYF2pOEloQGAiRIuUTkME42J7IZweYES+NkckZWWNfseEPAKJtO
+ oWxLu69/c5jpbPtNdW7qPwvsbO1cF8pVLKxs0+HD94gpl0AOQTlEsDkjizFmMk4WESyNM4NzMgOC
+ VYI6q17OlIp9992ngek769+EvtfVEI3jWqaKgAgAIAlFLuOwGZHDiTnElGQgF4DvM1LKV7Bdz2NE
+ xaCuhQpVm1Y0p5qhvNV1AyjlRTWhwVM2TMdzgkJzieAQyGGMbMZgfwZBEiBPA3xX+VSouAvBAFeM
+ yDddD7rgpHw/WjcAMa0EZScZk5heqFrxiO4BzCGCzYgsBrI4I5sYcxlBKl/5WdOdd6S0gxoLEZEi
+ Iq4AnzGq1r0HiPhYuZRFU1R3FgqWkS1aZQA2gWzOyGQcJudkaAwVR3qz8yXzvCXlzJoViaagrlWC
+ jJnLm8Jarli2GNMm6wbwPPO31y6Ollc2N3pcI+fyYjW/8a5EKqQTz5WtdLHsTi1W7Im5vDlcMdxx
+ wVk2Ys9/pTI3+WhAaIauM+MLbYnlH46MVKVyX6v7Hhg9e2ps3doN32ld0Rlrb1nmmK4stCdCSCUj
+ Le1NwW6uXJ08m/t2OarBXh0ie0syHu0plKtTFGw8n4o33q1z1XngD7+X3C/uHBkZces7hoAi1946
+ fPSvtpDlYFdLPDI8mR03HC87frXwFpgqLYuFuzrbkg8m49EeDsqDa+cizXcNpppia5ui+sYXnn+O
+ 29LbOTg4aHzun9GOPT/pDemhf3xzx25DicjkiqaAIs4zhumMRUJaPhzgJZ0LQ5C7gXjQL1kS0YD+
+ o337nhWlYvHJV178zZ9vlZ/dDuDVl57/2HWt755894hINoYSmZx11TYKCUZKCs4cnQuDmGtfvDiR
+ dD3n04aA6J4YHzeLhfLg7cSXBAAA5NPpufS1WFjwkFSelZ6ZLWfn0kliTDJdue8dO9qenp2d1DVR
+ 4cTarlyZJgV5dim5lwTw8sv7c1L6H89cm6FlDcHVhlOJffThsa9d+ud72y5+cnTn2PjJJ1avjOoE
+ SnBiPadOfRDTGT5YSm5tqR2R7Zp7//L6gRPf27NjVaolqS9MCzh28W6mgDXdKxCNRb/oOlV18O3D
+ 1xzXGXpx8LnZO94Tbt/x+MFYouexh7dsQU/PWjRGI+BcAyMgm1vAO28fxvj4xOX5jL7u0KEX7Dvq
+ AAC0Nucf2rLZhq8Y3njjT8gulOBKDw0NAQjNQT435eQWL3iHDk3YS81ZF0B6psI/GbuAXbu+gQf7
+ H4ArPeQWC5jLZKCUhQvjWb2QD3bVk5PVM9nz5LML8waOH38fekBHIhFDqqMFXd0pnDhxGmMTU3Bd
+ 9/X/GQDntO/eezswMPBjaFwAABxH4sKFq+jt7cX6ni6EQuJbdeWsZ3J3d/PTmqaEYUyhXDZBTEOh
+ WIIQwOi5jzA1eRnZXPFSPO7/bmbGlLfqhus5BVotRH9/x7rGxtBeIQJPACrMOYNSPpRiUIpnlTIO
+ nzmT+eX8fLH8WZMKF4Csje7ncUAHEKhFcHq6ZE5OZoc7O3tlc3N33+7dP9c2bXoE09NlO52uHDhy
+ ZOTVatUWte+otsTXg2pQSwagG6r/jwsAQul0erqjo+OesbGx1tHRUT+fz48dP378j57neQD8mtB1
+ B1TtnV9zo64loJqoXhtFDUQHEGhvb2/2fZ9nMpliTcAFYNdC1sIBYN1sCeq5Ca9bqtWcu9Fe3FDl
+ 9Uqvu3HLjfhvTUo85WzjhogAAAAASUVORK5CYII=
+}
+
+image create photo ::tk::icons::question -data {
+ iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAACG5JREFU
+ WIXFl3twVdUVxn97n3Nubm7euZcghEdeBBICEQUFIgVECqIo1uJMp3WodqyjMzpjZ7TTh20cK31N
+ /2jL2FYdKXaqRcbnDKGpoBFaAY1BHgHMgyRKQkJy87yv3Nyzd/84594k1RlppzPumTXn3Dl3r/Wd
+ b31rrbPhS17iSv+4bl2t2ZFhrRGI7QKxRkMAyHEfjwgYEOgjNnpfcXjiSENDbeL/AqBoW22uGE/7
+ MYL7yubN4MYVpVkrquaKqwJZ+LPTARgcjdIbHKOx+aI+9EH7WGvnZdA8q9PGf9b5eu3w/wygaPPO
+ h6Uhntxcsyj9/q+vtMrnBa6Is7ZPgzzzyvGJ/YfPRpWWj3fWff93/xWAonW1Xu3z/nVx6cxNTz74
+ 1YzK4gIQjuN/nfyEEx9fIjgaYXAkhhAQyE3Hn5PBsvJZrF46l5I5+QB83NnP40+/FT7d1ltPOPrN
+ zoba2BcCWLy91hMOp72/bX1VxU/u3+BJ91i0fhrkuTcaaTzbjTQkhpQIIZBSIBApL1prtNYsryhk
+ xy1XUzonn1g8wVPPvh1/5dDpcz5f7LrmfbXxqfGM6eG1yCw+9uq2G6tW7nxoU5plGrzecJYnnnub
+ SwMhTNPAmmKmYWCaBoYpMQyJaRhIQ3IpGOKt4+1k+dKoLJ7BjStKjb6hcN7JloFrhlsO7oUnPh9A
+ 8Rbvo6uuLrr3N4/ckm4Ykt/vPcqe/R9hGAamaWJZbnDL+W2axqRJA8NlxzAkAI3newhF4lxbMZs1
+ y4rNM+19c0PZ++NDLQff+0wKCu/Y6c/UVsubv/12/ryZubxUf5Ln3vgQ0zKnvK1kadkMlpQUUFEU
+ oCDPR25WOuPxBH2DYZpa+qg/3kEoGsdWCttWJGzF3ZuXcuf6Ci5eHmXrw7sHR4mXd7/2w+A0Bvyl
+ N+265/bl19+8eqE8c6GPn+85jGkYWC4Ay3Luf/3AV1g038+MXB8+rwfDkKR5TPKyvCyan8+qqtmc
+ au8nFrcdnQCn2vuoLptJSWEeE7bynDjdXTDUcvBNAAmweF1tpmXKu+65bYWh0Ty97zhSyGkUO0BM
+ hBAI4RAXTyjiCYWUEukKMz/Ly/b1C7EsE49lYlkmhjTYvf8jNHD3lmsM0zTuWryuNhPABIj4vFvW
+ Xl0s87PTOdXWS8snQTwec4ro3DSYBglbcfx8P+8199I7FMEQgg3L53N7TWkKXOV8Px7LJCFtXKx0
+ dA9zrnOAyqIAa68tkQePtm4BXpaO9vWOm65b4EPAkY+6HDEZTt4NN/dJML946QSv/fMCA6PjpHks
+ LI/F2a5BtNYpMUtJirGpLL7f3A3AxpXlPiHFjhQDaJZVlc0EoPWT4DQ1m8ZkKizTJDRuY1mmC04i
+ pWDNksJUD9Bac7E/jGUZrmuN1qCU5sKlIQAqSwrQWi+bBCDwF+RnAk5fl27wqeYAkZM9wLWaxVex
+ qnJmKritFO+e7sMyDdBOc1JKYxiSkdA4CMGM3Aw02j+VAfLcwTIWibuiEpNApJMSw208ydJcu3QW
+ axZPCW7bHGjspmcwimkYTmAlMWzHTyTmDMiczLRU/ctkNxgajboPvUghppuUGFJMY6O6OJ/ViwIo
+ pVBKYds2dR9e4uPuMbc7Tm9MUgqyM70AjITHUy1IAghNsH8oDEAgz4cQOIqWjkkpEC4rSYfXL/Sn
+ giulONYyRFd/1GXKAZxkUrgvkp/tAAgORxAQnAQg5InmC5cBWDgv4NS5EAhAINzyIlVmUgiy040U
+ 9Uop2voiKYakEAiRvDp7EYKS2XkAnOvsR0h5IqUBrfWeQ8fb1t2xvtJXs3QuB462TfZokbxMGZxC
+ 8If6DtI8Fh6PhcdjojSpBuXin7Kc3csXzQLgrWOtEWWrPSkAvkis7kjTBTU8FqOypIAF8/x09Y6Q
+ FGjyTdHJstLsWDsnNZIBXj7Wj1LKYSS5B412nRTNymHBnHxGQ+O8836r8kVidakUNDfUhhIJtfcv
+ dU22AO69dRlCCNeZU8fJe6U0ylZYBlgGmNKx+ESCiYRNwlYoWzn/UxqtHOB3ra8AAX/7x0nbttXe
+ 5oba0GQVAPGE9dju1z4Y7u4fY9F8P9/YWOUEV06O7eTVnXBTBaiUIj4xwcSETSJhk7BtbNtOPdta
+ U0ZpYS59wRB/2ndsOBa3HkvGTU3D0fb6aE7ZBt3RM1yzuabcqiwKEI5N0N495ChaSKcihJPRa0pz
+ sbUmYTugPmgbJmErB4DLxETC5oYlhWxdXUrCVvxgV32krav/qa4Djx76D4kllxalt/7q9e2bqjf9
+ 9Lsb0oQQHGrsYO+hc0gp3emW/Bhxm5NbZlqD0g79CTcFt60u4YYlhWhg5/MN4y/WNdW3vfnoNhD6
+ Mww46wlmV9/w6snzA1sHRqKBVUvnGQvm+qkuKyA4GqVvKOJAdrcn8zz14yNh2ywozOVbGyuoKg4w
+ PmHzyxcOx1+sazqTlhbZ3H92vT29Pj5nzVn1SLqVH3ipunzOxqceutlX6n7lXrw8yqn2flq7hxgL
+ TzAWiyOFICfTS44vjbLCXKqK/cwOOHOl49IwP9r192hT84V3e4+9cF90sC0IRL8QAOADsgvXfu9B
+ b3bgkTs3LPN+52srzPlX5V7RUerTy6M8/0Zj4uUDH45Hg13PdB/9425gzLUhQH0RgDQgC8hKLyid
+ 7a/c9oCV4d9WVTpLbF5TmX5tRaGYkecjJ8MLAkZD4wyMRGg636PrDjfHzrT26NhYT33w1Kt/Hh/u
+ 6XUDh4BBIHwlDIBTohlANpBhWb6s7PKNK30FCzZa6dnVYORoIX2OExVF26Px8NCZSN/5d0bb3mlK
+ JGIhHLpDwLAL4jPnxSs9nBqABXhddrw4XdRygSrABuKuxYBx9/6KDqlf2vo3PYe56vmkuwMAAAAA
+ SUVORK5CYII=
+}
diff --git a/tk8.6/library/images/README b/tk8.6/library/images/README
new file mode 100644
index 0000000..7b61d5a
--- /dev/null
+++ b/tk8.6/library/images/README
@@ -0,0 +1,7 @@
+README - images directory
+
+This directory includes images for the Tcl Logo and the Tcl Powered
+Logo. Please feel free to use the Tcl Powered Logo on any of your
+products that employ the use of Tcl or Tk. The Tcl logo may also be
+used to promote Tcl in your product documentation, web site or other
+places you so desire.
diff --git a/tk8.6/library/images/logo.eps b/tk8.6/library/images/logo.eps
new file mode 100644
index 0000000..0d05d34
--- /dev/null
+++ b/tk8.6/library/images/logo.eps
@@ -0,0 +1,2091 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Creator: Adobe Illustrator(TM) 5.5
+%%For: (Bud Northern) (Mark Anderson Design)
+%%Title: (TCL/TK LOGO.ILLUS)
+%%CreationDate: (8/1/96) (4:58 PM)
+%%BoundingBox: 251 331 371 512
+%%HiResBoundingBox: 251.3386 331.5616 370.5213 511.775
+%%DocumentProcessColors: Cyan Magenta Yellow
+%%DocumentSuppliedResources: procset Adobe_level2_AI5 1.0 0
+%%+ procset Adobe_IllustratorA_AI5 1.0 0
+%AI5_FileFormat 1.2
+%AI3_ColorUsage: Color
+%%DocumentCustomColors: (TCL RED)
+%%CMYKCustomColor: 0 0.45 1 0 (Orange)
+%%+ 0 0.25 1 0 (Orange Yellow)
+%%+ 0 0.79 0.91 0 (TCL RED)
+%AI3_TemplateBox: 306 396 306 396
+%AI3_TileBox: 12 12 600 780
+%AI3_DocumentPreview: Macintosh_ColorPic
+%AI5_ArtSize: 612 792
+%AI5_RulerUnits: 0
+%AI5_ArtFlags: 1 0 0 1 0 0 1 1 0
+%AI5_TargetResolution: 800
+%AI5_NumLayers: 1
+%AI5_OpenToView: 90 576 2 938 673 18 1 1 2 40
+%AI5_OpenViewLayers: 7
+%%EndComments
+%%BeginProlog
+%%BeginResource: procset Adobe_level2_AI5 1.0 0
+%%Title: (Adobe Illustrator (R) Version 5.0 Level 2 Emulation)
+%%Version: 1.0
+%%CreationDate: (04/10/93) ()
+%%Copyright: ((C) 1987-1993 Adobe Systems Incorporated All Rights Reserved)
+userdict /Adobe_level2_AI5 21 dict dup begin
+ put
+ /packedarray where not
+ {
+ userdict begin
+ /packedarray
+ {
+ array astore readonly
+ } bind def
+ /setpacking /pop load def
+ /currentpacking false def
+ end
+ 0
+ } if
+ pop
+ userdict /defaultpacking currentpacking put true setpacking
+ /initialize
+ {
+ Adobe_level2_AI5 begin
+ } bind def
+ /terminate
+ {
+ currentdict Adobe_level2_AI5 eq
+ {
+ end
+ } if
+ } bind def
+ mark
+ /setcustomcolor where not
+ {
+ /findcmykcustomcolor
+ {
+ 5 packedarray
+ } bind def
+ /setcustomcolor
+ {
+ exch aload pop pop
+ 4
+ {
+ 4 index mul 4 1 roll
+ } repeat
+ 5 -1 roll pop
+ setcmykcolor
+ }
+ def
+ } if
+
+ /gt38? mark {version cvx exec} stopped {cleartomark true} {38 gt exch pop} ifelse def
+ userdict /deviceDPI 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt put
+ userdict /level2?
+ systemdict /languagelevel known dup
+ {
+ pop systemdict /languagelevel get 2 ge
+ } if
+ put
+ level2? not
+ {
+ /setcmykcolor where not
+ {
+ /setcmykcolor
+ {
+ exch .11 mul add exch .59 mul add exch .3 mul add
+ 1 exch sub setgray
+ } def
+ } if
+ /currentcmykcolor where not
+ {
+ /currentcmykcolor
+ {
+ 0 0 0 1 currentgray sub
+ } def
+ } if
+ /setoverprint where not
+ {
+ /setoverprint /pop load def
+ } if
+ /selectfont where not
+ {
+ /selectfont
+ {
+ exch findfont exch
+ dup type /arraytype eq
+ {
+ makefont
+ }
+ {
+ scalefont
+ } ifelse
+ setfont
+ } bind def
+ } if
+ /cshow where not
+ {
+ /cshow
+ {
+ [
+ 0 0 5 -1 roll aload pop
+ ] cvx bind forall
+ } bind def
+ } if
+ } if
+ cleartomark
+ /anyColor?
+ {
+ add add add 0 ne
+ } bind def
+ /testColor
+ {
+ gsave
+ setcmykcolor currentcmykcolor
+ grestore
+ } bind def
+ /testCMYKColorThrough
+ {
+ testColor anyColor?
+ } bind def
+ userdict /composite?
+ level2?
+ {
+ gsave 1 1 1 1 setcmykcolor currentcmykcolor grestore
+ add add add 4 eq
+ }
+ {
+ 1 0 0 0 testCMYKColorThrough
+ 0 1 0 0 testCMYKColorThrough
+ 0 0 1 0 testCMYKColorThrough
+ 0 0 0 1 testCMYKColorThrough
+ and and and
+ } ifelse
+ put
+ composite? not
+ {
+ userdict begin
+ gsave
+ /cyan? 1 0 0 0 testCMYKColorThrough def
+ /magenta? 0 1 0 0 testCMYKColorThrough def
+ /yellow? 0 0 1 0 testCMYKColorThrough def
+ /black? 0 0 0 1 testCMYKColorThrough def
+ grestore
+ /isCMYKSep? cyan? magenta? yellow? black? or or or def
+ /customColor? isCMYKSep? not def
+ end
+ } if
+ end defaultpacking setpacking
+%%EndResource
+%%BeginResource: procset Adobe_IllustratorA_AI5 1.1 0
+%%Title: (Adobe Illustrator (R) Version 5.0 Abbreviated Prolog)
+%%Version: 1.1
+%%CreationDate: (3/7/1994) ()
+%%Copyright: ((C) 1987-1994 Adobe Systems Incorporated All Rights Reserved)
+currentpacking true setpacking
+userdict /Adobe_IllustratorA_AI5_vars 70 dict dup begin
+put
+/_lp /none def
+/_pf
+{
+} def
+/_ps
+{
+} def
+/_psf
+{
+} def
+/_pss
+{
+} def
+/_pjsf
+{
+} def
+/_pjss
+{
+} def
+/_pola 0 def
+/_doClip 0 def
+/cf currentflat def
+/_tm matrix def
+/_renderStart
+[
+/e0 /r0 /a0 /o0 /e1 /r1 /a1 /i0
+] def
+/_renderEnd
+[
+null null null null /i1 /i1 /i1 /i1
+] def
+/_render -1 def
+/_rise 0 def
+/_ax 0 def
+/_ay 0 def
+/_cx 0 def
+/_cy 0 def
+/_leading
+[
+0 0
+] def
+/_ctm matrix def
+/_mtx matrix def
+/_sp 16#020 def
+/_hyphen (-) def
+/_fScl 0 def
+/_cnt 0 def
+/_hs 1 def
+/_nativeEncoding 0 def
+/_useNativeEncoding 0 def
+/_tempEncode 0 def
+/_pntr 0 def
+/_tDict 2 dict def
+/_wv 0 def
+/Tx
+{
+} def
+/Tj
+{
+} def
+/CRender
+{
+} def
+/_AI3_savepage
+{
+} def
+/_gf null def
+/_cf 4 array def
+/_if null def
+/_of false def
+/_fc
+{
+} def
+/_gs null def
+/_cs 4 array def
+/_is null def
+/_os false def
+/_sc
+{
+} def
+/discardSave null def
+/buffer 256 string def
+/beginString null def
+/endString null def
+/endStringLength null def
+/layerCnt 1 def
+/layerCount 1 def
+/perCent (%) 0 get def
+/perCentSeen? false def
+/newBuff null def
+/newBuffButFirst null def
+/newBuffLast null def
+/clipForward? false def
+end
+userdict /Adobe_IllustratorA_AI5 74 dict dup begin
+put
+/initialize
+{
+ Adobe_IllustratorA_AI5 dup begin
+ Adobe_IllustratorA_AI5_vars begin
+ discardDict
+ {
+ bind pop pop
+ } forall
+ dup /nc get begin
+ {
+ dup xcheck 1 index type /operatortype ne and
+ {
+ bind
+ } if
+ pop pop
+ } forall
+ end
+ newpath
+} def
+/terminate
+{
+ end
+ end
+} def
+/_
+null def
+/ddef
+{
+ Adobe_IllustratorA_AI5_vars 3 1 roll put
+} def
+/xput
+{
+ dup load dup length exch maxlength eq
+ {
+ dup dup load dup
+ length 2 mul dict copy def
+ } if
+ load begin
+ def
+ end
+} def
+/npop
+{
+ {
+ pop
+ } repeat
+} def
+/sw
+{
+ dup length exch stringwidth
+ exch 5 -1 roll 3 index mul add
+ 4 1 roll 3 1 roll mul add
+} def
+/swj
+{
+ dup 4 1 roll
+ dup length exch stringwidth
+ exch 5 -1 roll 3 index mul add
+ 4 1 roll 3 1 roll mul add
+ 6 2 roll /_cnt 0 ddef
+ {
+ 1 index eq
+ {
+ /_cnt _cnt 1 add ddef
+ } if
+ } forall
+ pop
+ exch _cnt mul exch _cnt mul 2 index add 4 1 roll 2 index add 4 1 roll pop pop
+} def
+/ss
+{
+ 4 1 roll
+ {
+ 2 npop
+ (0) exch 2 copy 0 exch put pop
+ gsave
+ false charpath currentpoint
+ 4 index setmatrix
+ stroke
+ grestore
+ moveto
+ 2 copy rmoveto
+ } exch cshow
+ 3 npop
+} def
+/jss
+{
+ 4 1 roll
+ {
+ 2 npop
+ (0) exch 2 copy 0 exch put
+ gsave
+ _sp eq
+ {
+ exch 6 index 6 index 6 index 5 -1 roll widthshow
+ currentpoint
+ }
+ {
+ false charpath currentpoint
+ 4 index setmatrix stroke
+ } ifelse
+ grestore
+ moveto
+ 2 copy rmoveto
+ } exch cshow
+ 6 npop
+} def
+/sp
+{
+ {
+ 2 npop (0) exch
+ 2 copy 0 exch put pop
+ false charpath
+ 2 copy rmoveto
+ } exch cshow
+ 2 npop
+} def
+/jsp
+{
+ {
+ 2 npop
+ (0) exch 2 copy 0 exch put
+ _sp eq
+ {
+ exch 5 index 5 index 5 index 5 -1 roll widthshow
+ }
+ {
+ false charpath
+ } ifelse
+ 2 copy rmoveto
+ } exch cshow
+ 5 npop
+} def
+/pl
+{
+ transform
+ 0.25 sub round 0.25 add exch
+ 0.25 sub round 0.25 add exch
+ itransform
+} def
+/setstrokeadjust where
+{
+ pop true setstrokeadjust
+ /c
+ {
+ curveto
+ } def
+ /C
+ /c load def
+ /v
+ {
+ currentpoint 6 2 roll curveto
+ } def
+ /V
+ /v load def
+ /y
+ {
+ 2 copy curveto
+ } def
+ /Y
+ /y load def
+ /l
+ {
+ lineto
+ } def
+ /L
+ /l load def
+ /m
+ {
+ moveto
+ } def
+}
+{
+ /c
+ {
+ pl curveto
+ } def
+ /C
+ /c load def
+ /v
+ {
+ currentpoint 6 2 roll pl curveto
+ } def
+ /V
+ /v load def
+ /y
+ {
+ pl 2 copy curveto
+ } def
+ /Y
+ /y load def
+ /l
+ {
+ pl lineto
+ } def
+ /L
+ /l load def
+ /m
+ {
+ pl moveto
+ } def
+} ifelse
+/d
+{
+ setdash
+} def
+/cf
+{
+} def
+/i
+{
+ dup 0 eq
+ {
+ pop cf
+ } if
+ setflat
+} def
+/j
+{
+ setlinejoin
+} def
+/J
+{
+ setlinecap
+} def
+/M
+{
+ setmiterlimit
+} def
+/w
+{
+ setlinewidth
+} def
+/H
+{
+} def
+/h
+{
+ closepath
+} def
+/N
+{
+ _pola 0 eq
+ {
+ _doClip 1 eq
+ {
+ clip /_doClip 0 ddef
+ } if
+ newpath
+ }
+ {
+ /CRender
+ {
+ N
+ } ddef
+ } ifelse
+} def
+/n
+{
+ N
+} def
+/F
+{
+ _pola 0 eq
+ {
+ _doClip 1 eq
+ {
+ gsave _pf grestore clip newpath /_lp /none ddef _fc
+ /_doClip 0 ddef
+ }
+ {
+ _pf
+ } ifelse
+ }
+ {
+ /CRender
+ {
+ F
+ } ddef
+ } ifelse
+} def
+/f
+{
+ closepath
+ F
+} def
+/S
+{
+ _pola 0 eq
+ {
+ _doClip 1 eq
+ {
+ gsave _ps grestore clip newpath /_lp /none ddef _sc
+ /_doClip 0 ddef
+ }
+ {
+ _ps
+ } ifelse
+ }
+ {
+ /CRender
+ {
+ S
+ } ddef
+ } ifelse
+} def
+/s
+{
+ closepath
+ S
+} def
+/B
+{
+ _pola 0 eq
+ {
+ _doClip 1 eq
+ gsave F grestore
+ {
+ gsave S grestore clip newpath /_lp /none ddef _sc
+ /_doClip 0 ddef
+ }
+ {
+ S
+ } ifelse
+ }
+ {
+ /CRender
+ {
+ B
+ } ddef
+ } ifelse
+} def
+/b
+{
+ closepath
+ B
+} def
+/W
+{
+ /_doClip 1 ddef
+} def
+/*
+{
+ count 0 ne
+ {
+ dup type /stringtype eq
+ {
+ pop
+ } if
+ } if
+ newpath
+} def
+/u
+{
+} def
+/U
+{
+} def
+/q
+{
+ _pola 0 eq
+ {
+ gsave
+ } if
+} def
+/Q
+{
+ _pola 0 eq
+ {
+ grestore
+ } if
+} def
+/*u
+{
+ _pola 1 add /_pola exch ddef
+} def
+/*U
+{
+ _pola 1 sub /_pola exch ddef
+ _pola 0 eq
+ {
+ CRender
+ } if
+} def
+/D
+{
+ pop
+} def
+/*w
+{
+} def
+/*W
+{
+} def
+/`
+{
+ /_i save ddef
+ clipForward?
+ {
+ nulldevice
+ } if
+ 6 1 roll 4 npop
+ concat pop
+ userdict begin
+ /showpage
+ {
+ } def
+ 0 setgray
+ 0 setlinecap
+ 1 setlinewidth
+ 0 setlinejoin
+ 10 setmiterlimit
+ [] 0 setdash
+ /setstrokeadjust where {pop false setstrokeadjust} if
+ newpath
+ 0 setgray
+ false setoverprint
+} def
+/~
+{
+ end
+ _i restore
+} def
+/O
+{
+ 0 ne
+ /_of exch ddef
+ /_lp /none ddef
+} def
+/R
+{
+ 0 ne
+ /_os exch ddef
+ /_lp /none ddef
+} def
+/g
+{
+ /_gf exch ddef
+ /_fc
+ {
+ _lp /fill ne
+ {
+ _of setoverprint
+ _gf setgray
+ /_lp /fill ddef
+ } if
+ } ddef
+ /_pf
+ {
+ _fc
+ fill
+ } ddef
+ /_psf
+ {
+ _fc
+ ashow
+ } ddef
+ /_pjsf
+ {
+ _fc
+ awidthshow
+ } ddef
+ /_lp /none ddef
+} def
+/G
+{
+ /_gs exch ddef
+ /_sc
+ {
+ _lp /stroke ne
+ {
+ _os setoverprint
+ _gs setgray
+ /_lp /stroke ddef
+ } if
+ } ddef
+ /_ps
+ {
+ _sc
+ stroke
+ } ddef
+ /_pss
+ {
+ _sc
+ ss
+ } ddef
+ /_pjss
+ {
+ _sc
+ jss
+ } ddef
+ /_lp /none ddef
+} def
+/k
+{
+ _cf astore pop
+ /_fc
+ {
+ _lp /fill ne
+ {
+ _of setoverprint
+ _cf aload pop setcmykcolor
+ /_lp /fill ddef
+ } if
+ } ddef
+ /_pf
+ {
+ _fc
+ fill
+ } ddef
+ /_psf
+ {
+ _fc
+ ashow
+ } ddef
+ /_pjsf
+ {
+ _fc
+ awidthshow
+ } ddef
+ /_lp /none ddef
+} def
+/K
+{
+ _cs astore pop
+ /_sc
+ {
+ _lp /stroke ne
+ {
+ _os setoverprint
+ _cs aload pop setcmykcolor
+ /_lp /stroke ddef
+ } if
+ } ddef
+ /_ps
+ {
+ _sc
+ stroke
+ } ddef
+ /_pss
+ {
+ _sc
+ ss
+ } ddef
+ /_pjss
+ {
+ _sc
+ jss
+ } ddef
+ /_lp /none ddef
+} def
+/x
+{
+ /_gf exch ddef
+ findcmykcustomcolor
+ /_if exch ddef
+ /_fc
+ {
+ _lp /fill ne
+ {
+ _of setoverprint
+ _if _gf 1 exch sub setcustomcolor
+ /_lp /fill ddef
+ } if
+ } ddef
+ /_pf
+ {
+ _fc
+ fill
+ } ddef
+ /_psf
+ {
+ _fc
+ ashow
+ } ddef
+ /_pjsf
+ {
+ _fc
+ awidthshow
+ } ddef
+ /_lp /none ddef
+} def
+/X
+{
+ /_gs exch ddef
+ findcmykcustomcolor
+ /_is exch ddef
+ /_sc
+ {
+ _lp /stroke ne
+ {
+ _os setoverprint
+ _is _gs 1 exch sub setcustomcolor
+ /_lp /stroke ddef
+ } if
+ } ddef
+ /_ps
+ {
+ _sc
+ stroke
+ } ddef
+ /_pss
+ {
+ _sc
+ ss
+ } ddef
+ /_pjss
+ {
+ _sc
+ jss
+ } ddef
+ /_lp /none ddef
+} def
+/A
+{
+ pop
+} def
+/annotatepage
+{
+userdict /annotatepage 2 copy known {get exec} {pop pop} ifelse
+} def
+/discard
+{
+ save /discardSave exch store
+ discardDict begin
+ /endString exch store
+ gt38?
+ {
+ 2 add
+ } if
+ load
+ stopped
+ pop
+ end
+ discardSave restore
+} bind def
+userdict /discardDict 7 dict dup begin
+put
+/pre38Initialize
+{
+ /endStringLength endString length store
+ /newBuff buffer 0 endStringLength getinterval store
+ /newBuffButFirst newBuff 1 endStringLength 1 sub getinterval store
+ /newBuffLast newBuff endStringLength 1 sub 1 getinterval store
+} def
+/shiftBuffer
+{
+ newBuff 0 newBuffButFirst putinterval
+ newBuffLast 0
+ currentfile read not
+ {
+ stop
+ } if
+ put
+} def
+0
+{
+ pre38Initialize
+ mark
+ currentfile newBuff readstring exch pop
+ {
+ {
+ newBuff endString eq
+ {
+ cleartomark stop
+ } if
+ shiftBuffer
+ } loop
+ }
+ {
+ stop
+ } ifelse
+} def
+1
+{
+ pre38Initialize
+ /beginString exch store
+ mark
+ currentfile newBuff readstring exch pop
+ {
+ {
+ newBuff beginString eq
+ {
+ /layerCount dup load 1 add store
+ }
+ {
+ newBuff endString eq
+ {
+ /layerCount dup load 1 sub store
+ layerCount 0 eq
+ {
+ cleartomark stop
+ } if
+ } if
+ } ifelse
+ shiftBuffer
+ } loop
+ }
+ {
+ stop
+ } ifelse
+} def
+2
+{
+ mark
+ {
+ currentfile buffer readline not
+ {
+ stop
+ } if
+ endString eq
+ {
+ cleartomark stop
+ } if
+ } loop
+} def
+3
+{
+ /beginString exch store
+ /layerCnt 1 store
+ mark
+ {
+ currentfile buffer readline not
+ {
+ stop
+ } if
+ dup beginString eq
+ {
+ pop /layerCnt dup load 1 add store
+ }
+ {
+ endString eq
+ {
+ layerCnt 1 eq
+ {
+ cleartomark stop
+ }
+ {
+ /layerCnt dup load 1 sub store
+ } ifelse
+ } if
+ } ifelse
+ } loop
+} def
+end
+userdict /clipRenderOff 15 dict dup begin
+put
+{
+ /n /N /s /S /f /F /b /B
+}
+{
+ {
+ _doClip 1 eq
+ {
+ /_doClip 0 ddef clip
+ } if
+ newpath
+ } def
+} forall
+/Tr /pop load def
+/Bb {} def
+/BB /pop load def
+/Bg {12 npop} def
+/Bm {6 npop} def
+/Bc /Bm load def
+/Bh {4 npop} def
+end
+/Lb
+{
+ 4 npop
+ 6 1 roll
+ pop
+ 4 1 roll
+ pop pop pop
+ 0 eq
+ {
+ 0 eq
+ {
+ (%AI5_BeginLayer) 1 (%AI5_EndLayer--) discard
+ }
+ {
+ /clipForward? true def
+
+ /Tx /pop load def
+ /Tj /pop load def
+ currentdict end clipRenderOff begin begin
+ } ifelse
+ }
+ {
+ 0 eq
+ {
+ save /discardSave exch store
+ } if
+ } ifelse
+} bind def
+/LB
+{
+ discardSave dup null ne
+ {
+ restore
+ }
+ {
+ pop
+ clipForward?
+ {
+ currentdict
+ end
+ end
+ begin
+
+ /clipForward? false ddef
+ } if
+ } ifelse
+} bind def
+/Pb
+{
+ pop pop
+ 0 (%AI5_EndPalette) discard
+} bind def
+/Np
+{
+ 0 (%AI5_End_NonPrinting--) discard
+} bind def
+/Ln /pop load def
+/Ap
+/pop load def
+/Ar
+{
+ 72 exch div
+ 0 dtransform dup mul exch dup mul add sqrt
+ dup 1 lt
+ {
+ pop 1
+ } if
+ setflat
+} def
+/Mb
+{
+ q
+} def
+/Md
+{
+} def
+/MB
+{
+ Q
+} def
+/nc 3 dict def
+nc begin
+/setgray
+{
+ pop
+} bind def
+/setcmykcolor
+{
+ 4 npop
+} bind def
+/setcustomcolor
+{
+ 2 npop
+} bind def
+currentdict readonly pop
+end
+currentdict readonly pop
+end
+setpacking
+%%EndResource
+%%EndProlog
+%%BeginSetup
+Adobe_level2_AI5 /initialize get exec
+Adobe_IllustratorA_AI5 /initialize get exec
+%AI5_Begin_NonPrinting
+Np
+%AI3_BeginPattern: (Yellow Stripe)
+(Yellow Stripe) 8.4499 4.6 80.4499 76.6 [
+%AI3_Tile
+(0 O 0 R 0 0.4 1 0 k 0 0.4 1 0 K) @
+(
+800 Ar
+0 J 0 j 3.6 w 4 M []0 d
+%AI3_Note:
+0 D
+8.1999 8.1999 m
+80.6999 8.1999 L
+S
+8.1999 22.6 m
+80.6999 22.6 L
+S
+8.1999 37.0001 m
+80.6999 37.0001 L
+S
+8.1999 51.3999 m
+80.6999 51.3999 L
+S
+8.1999 65.8 m
+80.6999 65.8 L
+S
+8.1999 15.3999 m
+80.6999 15.3999 L
+S
+8.1999 29.8 m
+80.6999 29.8 L
+S
+8.1999 44.1999 m
+80.6999 44.1999 L
+S
+8.1999 58.6 m
+80.6999 58.6 L
+S
+8.1999 73.0001 m
+80.6999 73.0001 L
+S
+) &
+] E
+%AI3_EndPattern
+%AI5_End_NonPrinting--
+%AI5_Begin_NonPrinting
+Np
+3 Bn
+%AI5_BeginGradient: (Black & White)
+(Black & White) 0 2 Bd
+[
+<
+FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8
+D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5C4C3C2C1C0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0
+AFAEADACABAAA9A8A7A6A5A4A3A2A1A09F9E9D9C9B9A999897969594939291908F8E8D8C8B8A8988
+87868584838281807F7E7D7C7B7A797877767574737271706F6E6D6C6B6A69686766656463626160
+5F5E5D5C5B5A595857565554535251504F4E4D4C4B4A494847464544434241403F3E3D3C3B3A3938
+37363534333231302F2E2D2C2B2A292827262524232221201F1E1D1C1B1A19181716151413121110
+0F0E0D0C0B0A09080706050403020100
+>
+0 %_Br
+[
+0 0 50 100 %_Bs
+1 0 50 0 %_Bs
+BD
+%AI5_EndGradient
+%AI5_BeginGradient: (Red & Yellow)
+(Red & Yellow) 0 2 Bd
+[
+0
+<
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627
+28292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F
+505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F7071727374757677
+78797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7
+C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF
+F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF
+>
+<
+FFFFFEFEFDFDFDFCFCFBFBFBFAFAF9F9F9F8F8F7F7F7F6F6F5F5F5F4F4F3F3F3F2F2F1F1F1F0F0EF
+EFEFEEEEEDEDEDECECEBEBEBEAEAE9E9E9E8E8E7E7E7E6E6E5E5E5E4E4E3E3E3E2E2E1E1E1E0E0DF
+DFDFDEDEDDDDDDDCDCDBDBDBDADAD9D9D9D8D8D7D7D7D6D6D5D5D5D4D4D3D3D3D2D2D1D1D1D0D0CF
+CFCFCECECDCDCDCCCCCBCBCBCACAC9C9C9C8C8C7C7C7C6C6C5C5C5C4C4C3C3C3C2C2C1C1C1C0C0BF
+BFBFBEBEBDBDBDBCBCBBBBBBBABAB9B9B9B8B8B7B7B7B6B6B5B5B5B4B4B3B3B3B2B2B1B1B1B0B0AF
+AFAFAEAEADADADACACABABABAAAAA9A9A9A8A8A7A7A7A6A6A5A5A5A4A4A3A3A3A2A2A1A1A1A0A09F
+9F9F9E9E9D9D9D9C9C9B9B9B9A9A9999
+>
+0
+1 %_Br
+[
+0 1 0.6 0 1 50 100 %_Bs
+0 0 1 0 1 50 0 %_Bs
+BD
+%AI5_EndGradient
+%AI5_BeginGradient: (Yellow & Blue Radial)
+(Yellow & Blue Radial) 1 2 Bd
+[
+<
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627
+28292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F
+505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F7071727374757677
+78797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7
+C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF
+F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF
+>
+<
+1415161718191A1B1C1D1E1F1F202122232425262728292A2A2B2C2D2E2F30313233343536363738
+393A3B3C3D3E3F40414142434445464748494A4B4C4D4D4E4F50515253545556575858595A5B5C5D
+5E5F60616263646465666768696A6B6C6D6E6F6F707172737475767778797A7B7B7C7D7E7F808182
+83848586868788898A8B8C8D8E8F90919292939495969798999A9B9C9D9D9E9FA0A1A2A3A4A5A6A7
+A8A9A9AAABACADAEAFB0B1B2B3B4B4B5B6B7B8B9BABBBCBDBEBFC0C0C1C2C3C4C5C6C7C8C9CACBCB
+CCCDCECFD0D1D2D3D4D5D6D7D7D8D9DADBDCDDDEDFE0E1E2E2E3E4E5E6E7E8E9EAEBECEDEEEEEFF0
+F1F2F3F4F5F6F7F8F9F9FAFBFCFDFEFF
+>
+<
+ABAAAAA9A8A7A7A6A5A5A4A3A3A2A1A1A09F9F9E9D9D9C9B9B9A9999989797969595949393929191
+908F8F8E8D8D8C8B8B8A8989888787868585848383828181807F7F7E7D7D7C7B7B7A797978777776
+7575747373727171706F6F6E6D6D6C6B6B6A6969686767666565646362626160605F5E5E5D5C5C5B
+5A5A5958585756565554545352525150504F4E4E4D4C4C4B4A4A4948484746464544444342424140
+403F3E3E3D3C3C3B3A3A3938383736363534343332323130302F2E2E2D2C2C2B2A2A292828272626
+25242423222121201F1F1E1D1D1C1B1B1A1919181717161515141313121111100F0F0E0D0D0C0B0B
+0A090908070706050504030302010100
+>
+0
+1 %_Br
+[
+0 0.08 0.67 0 1 50 14 %_Bs
+1 1 0 0 1 50 100 %_Bs
+BD
+%AI5_EndGradient
+%AI5_End_NonPrinting--
+%AI5_BeginPalette
+144 170 Pb
+Pn
+Pc
+1 g
+Pc
+0 g
+Pc
+0 0 0 0 k
+Pc
+0.75 g
+Pc
+0.5 g
+Pc
+0.25 g
+Pc
+0 g
+Pc
+Bb
+2 (Black & White) -4014 4716 0 0 1 0 0 1 0 0 Bg
+0 BB
+Pc
+0.25 0 0 0 k
+Pc
+0.5 0 0 0 k
+Pc
+0.75 0 0 0 k
+Pc
+1 0 0 0 k
+Pc
+0.25 0.25 0 0 k
+Pc
+0.5 0.5 0 0 k
+Pc
+0.75 0.75 0 0 k
+Pc
+1 1 0 0 k
+Pc
+Bb
+2 (Red & Yellow) -4014 4716 0 0 1 0 0 1 0 0 Bg
+0 BB
+Pc
+0 0.25 0 0 k
+Pc
+0 0.5 0 0 k
+Pc
+0 0.75 0 0 k
+Pc
+0 1 0 0 k
+Pc
+0 0.25 0.25 0 k
+Pc
+0 0.5 0.5 0 k
+Pc
+0 0.75 0.75 0 k
+Pc
+0 1 1 0 k
+Pc
+Bb
+0 0 0 0 Bh
+2 (Yellow & Blue Radial) -4014 4716 0 0 1 0 0 1 0 0 Bg
+0 BB
+Pc
+0 0 0.25 0 k
+Pc
+0 0 0.5 0 k
+Pc
+0 0 0.75 0 k
+Pc
+0 0 1 0 k
+Pc
+0.25 0 0.25 0 k
+Pc
+0.5 0 0.5 0 k
+Pc
+0.75 0 0.75 0 k
+Pc
+1 0 1 0 k
+Pc
+(Yellow Stripe) 0 0 1 1 0 0 0 0 0 [1 0 0 1 0 0] p
+Pc
+0.25 0.125 0 0 k
+Pc
+0.5 0.25 0 0 k
+Pc
+0.75 0.375 0 0 k
+Pc
+1 0.5 0 0 k
+Pc
+0.125 0.25 0 0 k
+Pc
+0.25 0.5 0 0 k
+Pc
+0.375 0.75 0 0 k
+Pc
+0.5 1 0 0 k
+Pc
+0.375 0.375 0.75 0 k
+Pc
+0 0.25 0.125 0 k
+Pc
+0 0.5 0.25 0 k
+Pc
+0 0.75 0.375 0 k
+Pc
+0 1 0.5 0 k
+Pc
+0 0.125 0.25 0 k
+Pc
+0 0.25 0.5 0 k
+Pc
+0 0.375 0.75 0 k
+Pc
+0 0.5 1 0 k
+Pc
+0 0.79 0.91 0 (TCL RED) 0 x
+Pc
+0.125 0 0.25 0 k
+Pc
+0.25 0 0.5 0 k
+Pc
+0.375 0 0.75 0 k
+Pc
+0.5 0 1 0 k
+Pc
+0.25 0 0.125 0 k
+Pc
+0.5 0 0.25 0 k
+Pc
+0.75 0 0.375 0 k
+Pc
+1 0 0.5 0 k
+Pc
+0.5 1 0 0 k
+Pc
+0.25 0.125 0.125 0 k
+Pc
+0.5 0.25 0.25 0 k
+Pc
+0.75 0.375 0.375 0 k
+Pc
+1 0.5 0.5 0 k
+Pc
+0.25 0.25 0.125 0 k
+Pc
+0.5 0.5 0.25 0 k
+Pc
+0.75 0.75 0.375 0 k
+Pc
+1 1 0.5 0 k
+Pc
+0 1 0.5 0 k
+Pc
+0.125 0.25 0.125 0 k
+Pc
+0.25 0.5 0.25 0 k
+Pc
+0.375 0.75 0.375 0 k
+Pc
+0.5 1 0.5 0 k
+Pc
+0.125 0.25 0.25 0 k
+Pc
+0.25 0.5 0.5 0 k
+Pc
+0.375 0.75 0.75 0 k
+Pc
+0.5 1 1 0 k
+Pc
+0.75 0.75 0.375 0 k
+Pc
+0.125 0.125 0.25 0 k
+Pc
+0.25 0.25 0.5 0 k
+Pc
+0.375 0.375 0.75 0 k
+Pc
+0.5 0.5 1 0 k
+Pc
+0.25 0.125 0.25 0 k
+Pc
+0.5 0.25 0.5 0 k
+Pc
+0.75 0.375 0.75 0 k
+Pc
+1 0.5 1 0 k
+Pc
+0 0.79 0.91 0 (TCL RED) 0 x
+Pc
+0 0 0 0 k
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+1 0.5 0.5 0 k
+Pc
+0 0 0 0 k
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+0 0.25 1 0 (Orange Yellow) 0 x
+Pc
+0 0 0 0 k
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+0 1 0.5 0 k
+Pc
+0 0 0 0 k
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+1 0 0.5 0 k
+Pc
+0 0 0 0 k
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+0 0.45 1 0 (Orange) 0 x
+Pc
+0 0 0 0 k
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+0.375 0.375 0.75 0 k
+Pc
+0 0 0 0 k
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+0 0.79 0.91 0 (TCL RED) 0 x
+Pc
+0 0 0 0 k
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+1 0.65 0 0 k
+Pc
+0 0 0 0 k
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+0 0 1 0 k
+Pc
+PB
+%AI5_EndPalette
+%%EndSetup
+%AI5_BeginLayer
+1 1 1 1 0 0 0 79 128 255 Lb
+(Layer 1) Ln
+0 A
+u
+1 Ap
+0 O
+0 0.79 0.91 0 (TCL RED) 0 x
+800 Ar
+0 J 0 j 1.25 w 4 M []0 d
+%AI3_Note:
+0 D
+294.5207 335.3041 m
+368.2181 333.001 L
+363.6121 423.9713 L
+370.5213 507.1689 L
+336.5513 505.4417 L
+320.7179 511.775 L
+251.3386 508.0325 L
+254.7931 425.9866 L
+251.3386 331.5616 L
+294.5207 335.3041 L
+f
+u
+0 Ap
+1 0.65 0 0 k
+1 w
+318.1366 400.9627 m
+311.8663 399.2526 l
+315.2864 407.5177 l
+318.7064 430.6032 l
+314.4314 431.4581 l
+319.5616 438.5832 l
+325.9526 462.6014 l
+314.7164 460.2436 l
+320.6412 471.0911 326.9284 478.1557 v
+318.7064 484.469 l
+292.2183 472.8011 299.3434 434.8954 v
+293.8679 435.8542 l
+299.1189 396.1175 l
+294.6797 394.9775 l
+299.2277 385.6974 305.5963 381.2973 v
+306.1744 380.8979 297.6162 412.3629 306.7363 443.7133 c
+307.5914 441.7183 l
+300.3238 408.3015 307.5914 381.2973 v
+307.9261 380.656 311.5598 381.0836 v
+318.1366 393.4813 318.1366 400.9627 v
+f
+u
+*u
+1 g
+271.4311 372.5074 m
+272.7184 372.5074 L
+272.7184 375.1913 L
+273.2858 375.1913 273.8313 375.1913 274.3768 375.2786 c
+274.3768 372.5074 L
+276.2969 372.5074 L
+276.2969 372.0056 L
+274.3768 372.0056 L
+274.3768 365.3286 L
+274.3768 364.9359 274.3768 364.3467 275.2059 364.3467 c
+275.7733 364.3467 276.0787 364.7395 276.4279 365.1541 c
+276.777 364.9141 L
+276.3624 364.0849 275.2932 363.583 274.4204 363.583 c
+272.8494 363.583 272.6748 364.434 272.6748 365.4814 c
+272.6748 372.0056 L
+271.4311 372.0056 L
+271.4311 372.5074 l
+f
+*U
+*u
+290.5617 366.5724 m
+290.0598 365.0232 289.187 363.6703 286.9178 363.583 c
+283.5356 363.583 282.5101 366.3978 282.5101 367.9034 c
+282.5101 371.7874 285.6304 372.7256 286.8741 372.7256 c
+288.2924 372.7256 290.2999 372.071 290.2999 370.3909 c
+290.2999 369.8018 289.9289 369.2344 289.318 369.2344 c
+288.7288 369.2344 288.2924 369.6272 288.2924 370.26 c
+288.2924 371.111 288.9907 371.2201 288.9907 371.4601 c
+288.9907 372.0492 287.616 372.2892 287.136 372.2892 c
+285.0412 372.2892 284.4957 370.7618 284.4957 367.9034 c
+284.4957 366.5942 284.823 365.5905 284.9539 365.285 c
+285.2812 364.5649 285.9577 364.1067 287.0923 364.0413 c
+288.3579 363.9758 289.5798 365.0013 290.1035 366.5724 C
+290.5617 366.5724 l
+f
+*U
+*u
+296.6 363.8667 m
+296.6 364.3686 L
+298.2802 364.3686 L
+298.2802 378.3989 L
+296.6 378.3989 L
+296.6 378.9007 L
+297.5383 378.9007 L
+298.3457 378.9007 299.1966 378.9444 299.9822 379.0971 c
+299.9822 364.3686 L
+301.6623 364.3686 L
+301.6623 363.8667 L
+296.6 363.8667 l
+f
+*U
+*u
+317.4527 372.5074 m
+318.7401 372.5074 L
+318.7401 375.1913 L
+319.3074 375.1913 319.8529 375.1913 320.3984 375.2786 c
+320.3984 372.5074 L
+322.3186 372.5074 L
+322.3186 372.0056 L
+320.3984 372.0056 L
+320.3984 365.3286 L
+320.3984 364.9359 320.3984 364.3467 321.2276 364.3467 c
+321.7949 364.3467 322.1004 364.7395 322.4495 365.1541 c
+322.7986 364.9141 L
+322.384 364.0849 321.3148 363.583 320.442 363.583 c
+318.871 363.583 318.6964 364.434 318.6964 365.4814 c
+318.6964 372.0056 L
+317.4527 372.0056 L
+317.4527 372.5074 l
+f
+*U
+*u
+333.7467 372.0056 m
+333.7467 372.5074 L
+337.3252 372.5074 L
+337.3252 372.0056 L
+335.9942 372.0056 L
+332.983 369.3872 L
+337.1288 364.3686 L
+338.0453 364.3686 L
+338.0453 363.8667 L
+333.8995 363.8667 L
+333.8995 364.3686 L
+334.9905 364.3686 L
+331.3465 368.798 L
+335.0341 371.9401 L
+335.0341 372.0056 L
+333.7467 372.0056 l
+f
+328.4881 363.8667 m
+328.4881 364.3686 L
+329.6227 364.3686 L
+329.6227 378.3989 L
+328.4881 378.3989 L
+328.4881 378.9007 L
+328.8809 378.9007 L
+329.6882 378.9007 330.5392 378.9444 331.3247 379.0971 c
+331.3247 364.3686 L
+332.6339 364.3686 L
+332.6339 363.8667 L
+328.4881 363.8667 l
+f
+*U
+u
+309.5341 446.5364 m
+305.6878 429.3874 306.7947 401.5837 v
+307.1266 393.2441 308.0387 385.5779 309.1527 378.9301 C
+309.1587 378.9297 L
+309.8832 373.0923 310.3679 370.9791 312.2568 363.9454 C
+312.1466 359.4091 L
+297.0216 407.7015 309.5341 446.5364 V
+f
+318.8187 461.4058 m
+322.2203 463.1 327.0966 463.7165 v
+332.427 453.9463 319.3087 437.2655 v
+327.1346 454.735 325.2889 460.2079 v
+323.225 461.4903 318.8187 461.4058 v
+f
+317.2065 432.0795 m
+320.2613 431.3723 321.7279 432.5601 v
+318.8383 421.2839 319.5958 415.0813 v
+320.3533 408.8787 314.8881 404.9079 y
+319.5435 410.7982 318.0802 415.5959 v
+317.0657 418.9214 318.2006 427.4326 319.4809 430.1349 c
+318.2853 430.3025 317.2065 432.0795 v
+f
+314.1861 402.3703 m
+319.2343 402.9744 319.7646 405.5244 v
+320.3824 390.2725 313.3689 383.9873 v
+318.7204 392.3347 317.8807 400.9697 v
+314.1861 402.3703 l
+f
+299.9864 396.0219 m
+298.3586 394.1986 293.4739 398.2203 v
+295.0301 387.9694 304.6978 383.2767 v
+298.0444 388.2897 296.2519 393.7045 v
+298.6029 394.3966 299.9864 396.0219 v
+f
+298.4281 399.9096 m
+291.8229 416.6749 293.2382 439.3286 v
+294.7808 435.2261 299.738 433.7875 v
+297.4026 433.3101 296.0372 433.517 v
+292.5816 423.9535 298.4281 399.9096 v
+f
+326.1736 477.812 m
+323.6983 496.0028 308.2122 477.6066 v
+295.8813 462.9582 297.3508 450.5217 298.1072 443.5831 c
+298.3007 441.8079 295.8131 462.1138 309.3231 475.4768 c
+322.8328 488.8398 325.8846 478.5879 326.1736 477.812 c
+f
+U
+0 0 1 0 k
+303.3623 493.3274 m
+291.211 496.7978 287.3437 456.5222 v
+284.3599 468.9535 292.0777 486.5353 v
+299.7955 504.1172 303.3623 493.3274 y
+f
+288.2873 496.2718 m
+282.0897 486.9502 283.4958 477.0213 v
+278.7953 495.712 288.2873 496.2718 v
+f
+333.8987 470.1328 m
+341.2276 472.8361 330.7334 445.5571 v
+336.1654 453.5292 339.5844 466.0531 v
+341.7789 474.0903 333.8987 470.1328 y
+f
+345.752 472.2583 m
+350.9334 467.5681 347.2615 461.3636 v
+356.4779 471.0481 345.752 472.2583 v
+f
+U
+*u
+273.1765 354.3318 m
+273.1765 353.7507 273.1305 353.2908 272.5159 353.2908 c
+271.8846 353.2908 271.8554 353.7674 271.8554 354.3318 c
+271.8554 356.485 L
+272.148 356.485 L
+272.148 354.3486 L
+272.148 353.8259 272.1773 353.5751 272.5159 353.5751 c
+272.8504 353.5751 272.8839 353.8259 272.8839 354.3486 c
+272.8839 356.485 L
+273.1765 356.485 L
+273.1765 354.3318 l
+f
+*U
+*u
+277.1612 356.485 m
+276.9062 356.485 L
+276.9062 354.3862 l
+276.9062 354.2482 276.9271 354.1061 276.9355 353.9681 C
+276.9229 353.9681 l
+276.8937 354.0768 276.8644 354.1855 276.8268 354.2942 C
+276.1035 356.485 L
+275.8484 356.485 L
+275.8484 353.3326 L
+276.1035 353.3326 L
+276.1035 355.2474 l
+276.1035 355.4523 276.0826 355.653 276.07 355.8579 C
+276.0867 355.8579 l
+276.1244 355.7241 276.1495 355.5819 276.1954 355.4523 C
+276.9062 353.3326 L
+277.1612 353.3326 l
+277.1612 356.485 L
+f
+*U
+*u
+280.1421 353.3326 m
+279.8494 353.3326 L
+279.8494 356.485 L
+280.1421 356.485 L
+280.1421 353.3326 l
+f
+*U
+*u
+283.5141 353.3326 m
+283.2549 353.3326 L
+282.6194 356.485 L
+282.9205 356.485 L
+283.3344 354.1897 L
+283.3511 354.1102 283.3678 353.9054 283.3845 353.7632 c
+283.4013 353.7632 L
+283.4138 353.9054 283.4305 354.1144 283.4431 354.1897 c
+283.8528 356.485 L
+284.1496 356.485 L
+283.5141 353.3326 l
+f
+*U
+*u
+287.6238 356.2174 m
+286.9256 356.2174 L
+286.9256 355.1053 L
+287.6029 355.1053 L
+287.6029 354.8377 L
+286.9256 354.8377 L
+286.9256 353.6002 L
+287.6238 353.6002 L
+287.6238 353.3326 L
+286.6329 353.3326 L
+286.6329 356.485 L
+287.6238 356.485 L
+287.6238 356.2174 l
+f
+*U
+*u
+290.2278 353.3326 m
+290.2278 356.485 L
+290.5414 356.485 L
+290.9804 356.485 291.4026 356.4515 291.4026 355.6823 c
+291.4026 355.2809 291.3148 354.8879 290.8089 354.8712 c
+291.5072 353.3326 L
+291.1978 353.3326 L
+290.5288 354.8753 L
+290.5205 354.8753 L
+290.5205 353.3326 L
+290.2278 353.3326 l
+f
+290.5205 355.1137 m
+290.625 355.1137 L
+291.0347 355.1137 291.1016 355.2558 291.1016 355.6697 c
+291.1016 356.1672 290.9511 356.2174 290.579 356.2174 c
+290.5205 356.2174 L
+290.5205 355.1137 l
+f
+*U
+*u
+295.0981 355.9875 m
+294.9727 356.1296 294.8347 356.2425 294.634 356.2425 c
+294.3414 356.2425 294.1783 356 294.1783 355.7324 c
+294.1783 355.3645 294.4459 355.1931 294.7176 355.0091 c
+294.9852 354.821 295.2528 354.6203 295.2528 354.1855 c
+295.2528 353.7256 294.9559 353.2908 294.4626 353.2908 c
+294.287 353.2908 294.1072 353.341 293.9651 353.4497 c
+293.9651 353.8301 L
+294.0989 353.688 294.2745 353.5751 294.4751 353.5751 c
+294.7845 353.5751 294.9559 353.8468 294.9518 354.1311 c
+294.9559 354.4991 294.6842 354.6621 294.4166 354.8503 c
+294.149 355.0342 293.8773 355.2391 293.8773 355.6906 c
+293.8773 356.1129 294.1365 356.5268 294.6006 356.5268 c
+294.7887 356.5268 294.9476 356.4641 295.0981 356.3596 C
+295.0981 355.9875 l
+f
+*U
+*u
+299.0865 353.3326 m
+298.773 353.3326 L
+298.6559 353.9806 L
+297.9869 353.9806 L
+297.8741 353.3326 L
+297.5605 353.3326 L
+298.1793 356.485 L
+298.4552 356.485 L
+299.0865 353.3326 l
+f
+298.6099 354.2357 m
+298.4009 355.444 L
+298.3632 355.6572 298.3465 355.8746 298.3214 356.0878 c
+298.3047 356.0878 L
+298.2754 355.8746 298.2545 355.6572 298.2211 355.444 c
+298.0371 354.2357 L
+298.6099 354.2357 l
+f
+*U
+*u
+301.8124 353.6002 m
+302.4981 353.6002 L
+302.4981 353.3326 L
+301.5198 353.3326 L
+301.5198 356.485 L
+301.8124 356.485 L
+301.8124 353.6002 l
+f
+*U
+*u
+309.0754 355.9875 m
+308.95 356.1296 308.812 356.2425 308.6114 356.2425 c
+308.3187 356.2425 308.1556 356 308.1556 355.7324 c
+308.1556 355.3645 308.4232 355.1931 308.695 355.0091 c
+308.9626 354.821 309.2301 354.6203 309.2301 354.1855 c
+309.2301 353.7256 308.9333 353.2908 308.4399 353.2908 c
+308.2643 353.2908 308.0846 353.341 307.9424 353.4497 c
+307.9424 353.8301 L
+308.0762 353.688 308.2518 353.5751 308.4525 353.5751 c
+308.7619 353.5751 308.9333 353.8468 308.9291 354.1311 c
+308.9333 354.4991 308.6615 354.6621 308.3939 354.8503 c
+308.1264 355.0342 307.8546 355.2391 307.8546 355.6906 c
+307.8546 356.1129 308.1138 356.5268 308.5779 356.5268 c
+308.766 356.5268 308.9249 356.4641 309.0754 356.3596 C
+309.0754 355.9875 l
+f
+*U
+*u
+312.9468 353.7172 m
+312.8339 353.6378 312.7001 353.5751 312.558 353.5751 c
+311.9977 353.5751 311.9977 354.5492 311.9977 354.9172 c
+311.9977 355.5025 312.0688 356.2425 312.5789 356.2425 c
+312.7252 356.2425 312.8297 356.184 312.9468 356.1045 C
+312.9468 356.4265 l
+312.8506 356.4975 312.6918 356.5268 312.5747 356.5268 c
+311.7134 356.5268 311.6967 355.306 311.6967 354.7959 c
+311.6967 354.2566 311.8054 353.2908 312.5454 353.2908 c
+312.6834 353.2908 312.8381 353.3451 312.9468 353.4204 c
+312.9468 353.7172 L
+f
+*U
+*u
+315.5053 353.3326 m
+315.5053 356.485 L
+315.8188 356.485 L
+316.2578 356.485 316.6801 356.4515 316.6801 355.6823 c
+316.6801 355.2809 316.5923 354.8879 316.0864 354.8712 c
+316.7846 353.3326 L
+316.4752 353.3326 L
+315.8063 354.8753 L
+315.7979 354.8753 L
+315.7979 353.3326 L
+315.5053 353.3326 l
+f
+315.7979 355.1137 m
+315.9025 355.1137 L
+316.3122 355.1137 316.3791 355.2558 316.3791 355.6697 c
+316.3791 356.1672 316.2286 356.2174 315.8565 356.2174 c
+315.7979 356.2174 L
+315.7979 355.1137 l
+f
+*U
+*u
+319.5728 353.3326 m
+319.2802 353.3326 L
+319.2802 356.485 L
+319.5728 356.485 L
+319.5728 353.3326 l
+f
+*U
+*u
+322.2551 353.3326 m
+322.2551 356.485 L
+322.5812 356.485 L
+323.0327 356.485 323.4341 356.4432 323.4341 355.6655 c
+323.4341 355.0551 323.2209 354.8419 322.623 354.8419 c
+322.5477 354.8419 L
+322.5477 353.3326 L
+322.2551 353.3326 l
+f
+322.5477 355.1095 m
+322.6606 355.1095 L
+323.0703 355.1095 323.1205 355.26 323.1331 355.6655 c
+323.1331 356.1004 323.016 356.2174 322.6063 356.2174 c
+322.5477 356.2174 L
+322.5477 355.1095 l
+f
+*U
+*u
+326.9539 356.485 m
+325.7164 356.485 L
+325.7164 356.2174 L
+326.1888 356.2174 L
+326.1888 353.3326 L
+326.4815 353.3326 L
+326.4815 356.2174 L
+326.9539 356.2174 l
+326.9539 356.485 L
+f
+*U
+*u
+329.7077 353.3326 m
+329.4151 353.3326 L
+329.4151 356.485 L
+329.7077 356.485 L
+329.7077 353.3326 l
+f
+*U
+*u
+333.7028 353.3326 m
+333.4477 353.3326 L
+332.737 355.4523 L
+332.691 355.5819 332.6659 355.7241 332.6283 355.8579 c
+332.6116 355.8579 L
+332.6241 355.653 332.645 355.4523 332.645 355.2474 c
+332.645 353.3326 L
+332.39 353.3326 L
+332.39 356.485 L
+332.645 356.485 L
+333.3683 354.2942 L
+333.4059 354.1855 333.4352 354.0768 333.4645 353.9681 c
+333.477 353.9681 L
+333.4686 354.1061 333.4477 354.2482 333.4477 354.3862 c
+333.4477 356.485 L
+333.7028 356.485 L
+333.7028 353.3326 l
+f
+*U
+*u
+336.9846 354.9966 m
+337.7037 354.9966 L
+337.7037 354.4154 L
+337.7037 353.9179 337.6787 353.2908 337.0264 353.2908 c
+336.3617 353.2908 336.299 353.989 336.299 354.9841 c
+336.299 355.7283 336.3868 356.5268 337.0557 356.5268 c
+337.432 356.5268 337.6201 356.276 337.6996 355.9331 c
+337.4111 355.8202 L
+337.3776 356.0084 337.2982 356.2425 337.0682 356.2425 c
+336.6334 356.2383 336.6 355.5652 336.6 355.0091 c
+336.6 353.8427 336.7463 353.5751 337.0515 353.5751 c
+337.3818 353.5751 337.4111 353.8176 337.4111 354.4907 c
+337.4111 354.729 L
+336.9846 354.729 L
+336.9846 354.9966 l
+f
+*U
+U
+U
+337.6667 -3924 m
+(N) *
+337.6667 4716 m
+(N) *
+LB
+%AI5_EndLayer--
+%%PageTrailer
+gsave annotatepage grestore showpage
+%%Trailer
+Adobe_IllustratorA_AI5 /terminate get exec
+Adobe_level2_AI5 /terminate get exec
+%%EOF
diff --git a/tk8.6/library/images/logo100.gif b/tk8.6/library/images/logo100.gif
new file mode 100644
index 0000000..4603d4f
--- /dev/null
+++ b/tk8.6/library/images/logo100.gif
Binary files differ
diff --git a/tk8.6/library/images/logo64.gif b/tk8.6/library/images/logo64.gif
new file mode 100644
index 0000000..749d55b
--- /dev/null
+++ b/tk8.6/library/images/logo64.gif
Binary files differ
diff --git a/tk8.6/library/images/logoLarge.gif b/tk8.6/library/images/logoLarge.gif
new file mode 100644
index 0000000..bd7530a
--- /dev/null
+++ b/tk8.6/library/images/logoLarge.gif
Binary files differ
diff --git a/tk8.6/library/images/logoMed.gif b/tk8.6/library/images/logoMed.gif
new file mode 100644
index 0000000..d41801a
--- /dev/null
+++ b/tk8.6/library/images/logoMed.gif
Binary files differ
diff --git a/tk8.6/library/images/pwrdLogo.eps b/tk8.6/library/images/pwrdLogo.eps
new file mode 100644
index 0000000..e11d9e9
--- /dev/null
+++ b/tk8.6/library/images/pwrdLogo.eps
@@ -0,0 +1,1897 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Creator: Adobe Illustrator(TM) 5.5
+%%For: (Bud Northern) (Mark Anderson Design)
+%%Title: (TCL PWRD LOGO.ILLUS)
+%%CreationDate: (8/1/96) (4:59 PM)
+%%BoundingBox: 242 302 377 513
+%%HiResBoundingBox: 242.0523 302.5199 376.3322 512.5323
+%%DocumentProcessColors: Cyan Magenta Yellow
+%%DocumentSuppliedResources: procset Adobe_level2_AI5 1.0 0
+%%+ procset Adobe_IllustratorA_AI5 1.0 0
+%AI5_FileFormat 1.2
+%AI3_ColorUsage: Color
+%%CMYKCustomColor: 0 0.45 1 0 (Orange)
+%%+ 0 0.25 1 0 (Orange Yellow)
+%%+ 0 0.79 0.91 0 (PANTONE Warm Red CV)
+%%+ 0 0.79 0.91 0 (TCL RED)
+%AI3_TemplateBox: 306 396 306 396
+%AI3_TileBox: 12 12 600 780
+%AI3_DocumentPreview: Macintosh_ColorPic
+%AI5_ArtSize: 612 792
+%AI5_RulerUnits: 0
+%AI5_ArtFlags: 1 0 0 1 0 0 1 1 0
+%AI5_TargetResolution: 800
+%AI5_NumLayers: 1
+%AI5_OpenToView: 102 564 2 938 673 18 1 1 2 40
+%AI5_OpenViewLayers: 7
+%%EndComments
+%%BeginProlog
+%%BeginResource: procset Adobe_level2_AI5 1.0 0
+%%Title: (Adobe Illustrator (R) Version 5.0 Level 2 Emulation)
+%%Version: 1.0
+%%CreationDate: (04/10/93) ()
+%%Copyright: ((C) 1987-1993 Adobe Systems Incorporated All Rights Reserved)
+userdict /Adobe_level2_AI5 21 dict dup begin
+ put
+ /packedarray where not
+ {
+ userdict begin
+ /packedarray
+ {
+ array astore readonly
+ } bind def
+ /setpacking /pop load def
+ /currentpacking false def
+ end
+ 0
+ } if
+ pop
+ userdict /defaultpacking currentpacking put true setpacking
+ /initialize
+ {
+ Adobe_level2_AI5 begin
+ } bind def
+ /terminate
+ {
+ currentdict Adobe_level2_AI5 eq
+ {
+ end
+ } if
+ } bind def
+ mark
+ /setcustomcolor where not
+ {
+ /findcmykcustomcolor
+ {
+ 5 packedarray
+ } bind def
+ /setcustomcolor
+ {
+ exch aload pop pop
+ 4
+ {
+ 4 index mul 4 1 roll
+ } repeat
+ 5 -1 roll pop
+ setcmykcolor
+ }
+ def
+ } if
+
+ /gt38? mark {version cvx exec} stopped {cleartomark true} {38 gt exch pop} ifelse def
+ userdict /deviceDPI 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt put
+ userdict /level2?
+ systemdict /languagelevel known dup
+ {
+ pop systemdict /languagelevel get 2 ge
+ } if
+ put
+ level2? not
+ {
+ /setcmykcolor where not
+ {
+ /setcmykcolor
+ {
+ exch .11 mul add exch .59 mul add exch .3 mul add
+ 1 exch sub setgray
+ } def
+ } if
+ /currentcmykcolor where not
+ {
+ /currentcmykcolor
+ {
+ 0 0 0 1 currentgray sub
+ } def
+ } if
+ /setoverprint where not
+ {
+ /setoverprint /pop load def
+ } if
+ /selectfont where not
+ {
+ /selectfont
+ {
+ exch findfont exch
+ dup type /arraytype eq
+ {
+ makefont
+ }
+ {
+ scalefont
+ } ifelse
+ setfont
+ } bind def
+ } if
+ /cshow where not
+ {
+ /cshow
+ {
+ [
+ 0 0 5 -1 roll aload pop
+ ] cvx bind forall
+ } bind def
+ } if
+ } if
+ cleartomark
+ /anyColor?
+ {
+ add add add 0 ne
+ } bind def
+ /testColor
+ {
+ gsave
+ setcmykcolor currentcmykcolor
+ grestore
+ } bind def
+ /testCMYKColorThrough
+ {
+ testColor anyColor?
+ } bind def
+ userdict /composite?
+ level2?
+ {
+ gsave 1 1 1 1 setcmykcolor currentcmykcolor grestore
+ add add add 4 eq
+ }
+ {
+ 1 0 0 0 testCMYKColorThrough
+ 0 1 0 0 testCMYKColorThrough
+ 0 0 1 0 testCMYKColorThrough
+ 0 0 0 1 testCMYKColorThrough
+ and and and
+ } ifelse
+ put
+ composite? not
+ {
+ userdict begin
+ gsave
+ /cyan? 1 0 0 0 testCMYKColorThrough def
+ /magenta? 0 1 0 0 testCMYKColorThrough def
+ /yellow? 0 0 1 0 testCMYKColorThrough def
+ /black? 0 0 0 1 testCMYKColorThrough def
+ grestore
+ /isCMYKSep? cyan? magenta? yellow? black? or or or def
+ /customColor? isCMYKSep? not def
+ end
+ } if
+ end defaultpacking setpacking
+%%EndResource
+%%BeginResource: procset Adobe_IllustratorA_AI5 1.1 0
+%%Title: (Adobe Illustrator (R) Version 5.0 Abbreviated Prolog)
+%%Version: 1.1
+%%CreationDate: (3/7/1994) ()
+%%Copyright: ((C) 1987-1994 Adobe Systems Incorporated All Rights Reserved)
+currentpacking true setpacking
+userdict /Adobe_IllustratorA_AI5_vars 70 dict dup begin
+put
+/_lp /none def
+/_pf
+{
+} def
+/_ps
+{
+} def
+/_psf
+{
+} def
+/_pss
+{
+} def
+/_pjsf
+{
+} def
+/_pjss
+{
+} def
+/_pola 0 def
+/_doClip 0 def
+/cf currentflat def
+/_tm matrix def
+/_renderStart
+[
+/e0 /r0 /a0 /o0 /e1 /r1 /a1 /i0
+] def
+/_renderEnd
+[
+null null null null /i1 /i1 /i1 /i1
+] def
+/_render -1 def
+/_rise 0 def
+/_ax 0 def
+/_ay 0 def
+/_cx 0 def
+/_cy 0 def
+/_leading
+[
+0 0
+] def
+/_ctm matrix def
+/_mtx matrix def
+/_sp 16#020 def
+/_hyphen (-) def
+/_fScl 0 def
+/_cnt 0 def
+/_hs 1 def
+/_nativeEncoding 0 def
+/_useNativeEncoding 0 def
+/_tempEncode 0 def
+/_pntr 0 def
+/_tDict 2 dict def
+/_wv 0 def
+/Tx
+{
+} def
+/Tj
+{
+} def
+/CRender
+{
+} def
+/_AI3_savepage
+{
+} def
+/_gf null def
+/_cf 4 array def
+/_if null def
+/_of false def
+/_fc
+{
+} def
+/_gs null def
+/_cs 4 array def
+/_is null def
+/_os false def
+/_sc
+{
+} def
+/discardSave null def
+/buffer 256 string def
+/beginString null def
+/endString null def
+/endStringLength null def
+/layerCnt 1 def
+/layerCount 1 def
+/perCent (%) 0 get def
+/perCentSeen? false def
+/newBuff null def
+/newBuffButFirst null def
+/newBuffLast null def
+/clipForward? false def
+end
+userdict /Adobe_IllustratorA_AI5 74 dict dup begin
+put
+/initialize
+{
+ Adobe_IllustratorA_AI5 dup begin
+ Adobe_IllustratorA_AI5_vars begin
+ discardDict
+ {
+ bind pop pop
+ } forall
+ dup /nc get begin
+ {
+ dup xcheck 1 index type /operatortype ne and
+ {
+ bind
+ } if
+ pop pop
+ } forall
+ end
+ newpath
+} def
+/terminate
+{
+ end
+ end
+} def
+/_
+null def
+/ddef
+{
+ Adobe_IllustratorA_AI5_vars 3 1 roll put
+} def
+/xput
+{
+ dup load dup length exch maxlength eq
+ {
+ dup dup load dup
+ length 2 mul dict copy def
+ } if
+ load begin
+ def
+ end
+} def
+/npop
+{
+ {
+ pop
+ } repeat
+} def
+/sw
+{
+ dup length exch stringwidth
+ exch 5 -1 roll 3 index mul add
+ 4 1 roll 3 1 roll mul add
+} def
+/swj
+{
+ dup 4 1 roll
+ dup length exch stringwidth
+ exch 5 -1 roll 3 index mul add
+ 4 1 roll 3 1 roll mul add
+ 6 2 roll /_cnt 0 ddef
+ {
+ 1 index eq
+ {
+ /_cnt _cnt 1 add ddef
+ } if
+ } forall
+ pop
+ exch _cnt mul exch _cnt mul 2 index add 4 1 roll 2 index add 4 1 roll pop pop
+} def
+/ss
+{
+ 4 1 roll
+ {
+ 2 npop
+ (0) exch 2 copy 0 exch put pop
+ gsave
+ false charpath currentpoint
+ 4 index setmatrix
+ stroke
+ grestore
+ moveto
+ 2 copy rmoveto
+ } exch cshow
+ 3 npop
+} def
+/jss
+{
+ 4 1 roll
+ {
+ 2 npop
+ (0) exch 2 copy 0 exch put
+ gsave
+ _sp eq
+ {
+ exch 6 index 6 index 6 index 5 -1 roll widthshow
+ currentpoint
+ }
+ {
+ false charpath currentpoint
+ 4 index setmatrix stroke
+ } ifelse
+ grestore
+ moveto
+ 2 copy rmoveto
+ } exch cshow
+ 6 npop
+} def
+/sp
+{
+ {
+ 2 npop (0) exch
+ 2 copy 0 exch put pop
+ false charpath
+ 2 copy rmoveto
+ } exch cshow
+ 2 npop
+} def
+/jsp
+{
+ {
+ 2 npop
+ (0) exch 2 copy 0 exch put
+ _sp eq
+ {
+ exch 5 index 5 index 5 index 5 -1 roll widthshow
+ }
+ {
+ false charpath
+ } ifelse
+ 2 copy rmoveto
+ } exch cshow
+ 5 npop
+} def
+/pl
+{
+ transform
+ 0.25 sub round 0.25 add exch
+ 0.25 sub round 0.25 add exch
+ itransform
+} def
+/setstrokeadjust where
+{
+ pop true setstrokeadjust
+ /c
+ {
+ curveto
+ } def
+ /C
+ /c load def
+ /v
+ {
+ currentpoint 6 2 roll curveto
+ } def
+ /V
+ /v load def
+ /y
+ {
+ 2 copy curveto
+ } def
+ /Y
+ /y load def
+ /l
+ {
+ lineto
+ } def
+ /L
+ /l load def
+ /m
+ {
+ moveto
+ } def
+}
+{
+ /c
+ {
+ pl curveto
+ } def
+ /C
+ /c load def
+ /v
+ {
+ currentpoint 6 2 roll pl curveto
+ } def
+ /V
+ /v load def
+ /y
+ {
+ pl 2 copy curveto
+ } def
+ /Y
+ /y load def
+ /l
+ {
+ pl lineto
+ } def
+ /L
+ /l load def
+ /m
+ {
+ pl moveto
+ } def
+} ifelse
+/d
+{
+ setdash
+} def
+/cf
+{
+} def
+/i
+{
+ dup 0 eq
+ {
+ pop cf
+ } if
+ setflat
+} def
+/j
+{
+ setlinejoin
+} def
+/J
+{
+ setlinecap
+} def
+/M
+{
+ setmiterlimit
+} def
+/w
+{
+ setlinewidth
+} def
+/H
+{
+} def
+/h
+{
+ closepath
+} def
+/N
+{
+ _pola 0 eq
+ {
+ _doClip 1 eq
+ {
+ clip /_doClip 0 ddef
+ } if
+ newpath
+ }
+ {
+ /CRender
+ {
+ N
+ } ddef
+ } ifelse
+} def
+/n
+{
+ N
+} def
+/F
+{
+ _pola 0 eq
+ {
+ _doClip 1 eq
+ {
+ gsave _pf grestore clip newpath /_lp /none ddef _fc
+ /_doClip 0 ddef
+ }
+ {
+ _pf
+ } ifelse
+ }
+ {
+ /CRender
+ {
+ F
+ } ddef
+ } ifelse
+} def
+/f
+{
+ closepath
+ F
+} def
+/S
+{
+ _pola 0 eq
+ {
+ _doClip 1 eq
+ {
+ gsave _ps grestore clip newpath /_lp /none ddef _sc
+ /_doClip 0 ddef
+ }
+ {
+ _ps
+ } ifelse
+ }
+ {
+ /CRender
+ {
+ S
+ } ddef
+ } ifelse
+} def
+/s
+{
+ closepath
+ S
+} def
+/B
+{
+ _pola 0 eq
+ {
+ _doClip 1 eq
+ gsave F grestore
+ {
+ gsave S grestore clip newpath /_lp /none ddef _sc
+ /_doClip 0 ddef
+ }
+ {
+ S
+ } ifelse
+ }
+ {
+ /CRender
+ {
+ B
+ } ddef
+ } ifelse
+} def
+/b
+{
+ closepath
+ B
+} def
+/W
+{
+ /_doClip 1 ddef
+} def
+/*
+{
+ count 0 ne
+ {
+ dup type /stringtype eq
+ {
+ pop
+ } if
+ } if
+ newpath
+} def
+/u
+{
+} def
+/U
+{
+} def
+/q
+{
+ _pola 0 eq
+ {
+ gsave
+ } if
+} def
+/Q
+{
+ _pola 0 eq
+ {
+ grestore
+ } if
+} def
+/*u
+{
+ _pola 1 add /_pola exch ddef
+} def
+/*U
+{
+ _pola 1 sub /_pola exch ddef
+ _pola 0 eq
+ {
+ CRender
+ } if
+} def
+/D
+{
+ pop
+} def
+/*w
+{
+} def
+/*W
+{
+} def
+/`
+{
+ /_i save ddef
+ clipForward?
+ {
+ nulldevice
+ } if
+ 6 1 roll 4 npop
+ concat pop
+ userdict begin
+ /showpage
+ {
+ } def
+ 0 setgray
+ 0 setlinecap
+ 1 setlinewidth
+ 0 setlinejoin
+ 10 setmiterlimit
+ [] 0 setdash
+ /setstrokeadjust where {pop false setstrokeadjust} if
+ newpath
+ 0 setgray
+ false setoverprint
+} def
+/~
+{
+ end
+ _i restore
+} def
+/O
+{
+ 0 ne
+ /_of exch ddef
+ /_lp /none ddef
+} def
+/R
+{
+ 0 ne
+ /_os exch ddef
+ /_lp /none ddef
+} def
+/g
+{
+ /_gf exch ddef
+ /_fc
+ {
+ _lp /fill ne
+ {
+ _of setoverprint
+ _gf setgray
+ /_lp /fill ddef
+ } if
+ } ddef
+ /_pf
+ {
+ _fc
+ fill
+ } ddef
+ /_psf
+ {
+ _fc
+ ashow
+ } ddef
+ /_pjsf
+ {
+ _fc
+ awidthshow
+ } ddef
+ /_lp /none ddef
+} def
+/G
+{
+ /_gs exch ddef
+ /_sc
+ {
+ _lp /stroke ne
+ {
+ _os setoverprint
+ _gs setgray
+ /_lp /stroke ddef
+ } if
+ } ddef
+ /_ps
+ {
+ _sc
+ stroke
+ } ddef
+ /_pss
+ {
+ _sc
+ ss
+ } ddef
+ /_pjss
+ {
+ _sc
+ jss
+ } ddef
+ /_lp /none ddef
+} def
+/k
+{
+ _cf astore pop
+ /_fc
+ {
+ _lp /fill ne
+ {
+ _of setoverprint
+ _cf aload pop setcmykcolor
+ /_lp /fill ddef
+ } if
+ } ddef
+ /_pf
+ {
+ _fc
+ fill
+ } ddef
+ /_psf
+ {
+ _fc
+ ashow
+ } ddef
+ /_pjsf
+ {
+ _fc
+ awidthshow
+ } ddef
+ /_lp /none ddef
+} def
+/K
+{
+ _cs astore pop
+ /_sc
+ {
+ _lp /stroke ne
+ {
+ _os setoverprint
+ _cs aload pop setcmykcolor
+ /_lp /stroke ddef
+ } if
+ } ddef
+ /_ps
+ {
+ _sc
+ stroke
+ } ddef
+ /_pss
+ {
+ _sc
+ ss
+ } ddef
+ /_pjss
+ {
+ _sc
+ jss
+ } ddef
+ /_lp /none ddef
+} def
+/x
+{
+ /_gf exch ddef
+ findcmykcustomcolor
+ /_if exch ddef
+ /_fc
+ {
+ _lp /fill ne
+ {
+ _of setoverprint
+ _if _gf 1 exch sub setcustomcolor
+ /_lp /fill ddef
+ } if
+ } ddef
+ /_pf
+ {
+ _fc
+ fill
+ } ddef
+ /_psf
+ {
+ _fc
+ ashow
+ } ddef
+ /_pjsf
+ {
+ _fc
+ awidthshow
+ } ddef
+ /_lp /none ddef
+} def
+/X
+{
+ /_gs exch ddef
+ findcmykcustomcolor
+ /_is exch ddef
+ /_sc
+ {
+ _lp /stroke ne
+ {
+ _os setoverprint
+ _is _gs 1 exch sub setcustomcolor
+ /_lp /stroke ddef
+ } if
+ } ddef
+ /_ps
+ {
+ _sc
+ stroke
+ } ddef
+ /_pss
+ {
+ _sc
+ ss
+ } ddef
+ /_pjss
+ {
+ _sc
+ jss
+ } ddef
+ /_lp /none ddef
+} def
+/A
+{
+ pop
+} def
+/annotatepage
+{
+userdict /annotatepage 2 copy known {get exec} {pop pop} ifelse
+} def
+/discard
+{
+ save /discardSave exch store
+ discardDict begin
+ /endString exch store
+ gt38?
+ {
+ 2 add
+ } if
+ load
+ stopped
+ pop
+ end
+ discardSave restore
+} bind def
+userdict /discardDict 7 dict dup begin
+put
+/pre38Initialize
+{
+ /endStringLength endString length store
+ /newBuff buffer 0 endStringLength getinterval store
+ /newBuffButFirst newBuff 1 endStringLength 1 sub getinterval store
+ /newBuffLast newBuff endStringLength 1 sub 1 getinterval store
+} def
+/shiftBuffer
+{
+ newBuff 0 newBuffButFirst putinterval
+ newBuffLast 0
+ currentfile read not
+ {
+ stop
+ } if
+ put
+} def
+0
+{
+ pre38Initialize
+ mark
+ currentfile newBuff readstring exch pop
+ {
+ {
+ newBuff endString eq
+ {
+ cleartomark stop
+ } if
+ shiftBuffer
+ } loop
+ }
+ {
+ stop
+ } ifelse
+} def
+1
+{
+ pre38Initialize
+ /beginString exch store
+ mark
+ currentfile newBuff readstring exch pop
+ {
+ {
+ newBuff beginString eq
+ {
+ /layerCount dup load 1 add store
+ }
+ {
+ newBuff endString eq
+ {
+ /layerCount dup load 1 sub store
+ layerCount 0 eq
+ {
+ cleartomark stop
+ } if
+ } if
+ } ifelse
+ shiftBuffer
+ } loop
+ }
+ {
+ stop
+ } ifelse
+} def
+2
+{
+ mark
+ {
+ currentfile buffer readline not
+ {
+ stop
+ } if
+ endString eq
+ {
+ cleartomark stop
+ } if
+ } loop
+} def
+3
+{
+ /beginString exch store
+ /layerCnt 1 store
+ mark
+ {
+ currentfile buffer readline not
+ {
+ stop
+ } if
+ dup beginString eq
+ {
+ pop /layerCnt dup load 1 add store
+ }
+ {
+ endString eq
+ {
+ layerCnt 1 eq
+ {
+ cleartomark stop
+ }
+ {
+ /layerCnt dup load 1 sub store
+ } ifelse
+ } if
+ } ifelse
+ } loop
+} def
+end
+userdict /clipRenderOff 15 dict dup begin
+put
+{
+ /n /N /s /S /f /F /b /B
+}
+{
+ {
+ _doClip 1 eq
+ {
+ /_doClip 0 ddef clip
+ } if
+ newpath
+ } def
+} forall
+/Tr /pop load def
+/Bb {} def
+/BB /pop load def
+/Bg {12 npop} def
+/Bm {6 npop} def
+/Bc /Bm load def
+/Bh {4 npop} def
+end
+/Lb
+{
+ 4 npop
+ 6 1 roll
+ pop
+ 4 1 roll
+ pop pop pop
+ 0 eq
+ {
+ 0 eq
+ {
+ (%AI5_BeginLayer) 1 (%AI5_EndLayer--) discard
+ }
+ {
+ /clipForward? true def
+
+ /Tx /pop load def
+ /Tj /pop load def
+ currentdict end clipRenderOff begin begin
+ } ifelse
+ }
+ {
+ 0 eq
+ {
+ save /discardSave exch store
+ } if
+ } ifelse
+} bind def
+/LB
+{
+ discardSave dup null ne
+ {
+ restore
+ }
+ {
+ pop
+ clipForward?
+ {
+ currentdict
+ end
+ end
+ begin
+
+ /clipForward? false ddef
+ } if
+ } ifelse
+} bind def
+/Pb
+{
+ pop pop
+ 0 (%AI5_EndPalette) discard
+} bind def
+/Np
+{
+ 0 (%AI5_End_NonPrinting--) discard
+} bind def
+/Ln /pop load def
+/Ap
+/pop load def
+/Ar
+{
+ 72 exch div
+ 0 dtransform dup mul exch dup mul add sqrt
+ dup 1 lt
+ {
+ pop 1
+ } if
+ setflat
+} def
+/Mb
+{
+ q
+} def
+/Md
+{
+} def
+/MB
+{
+ Q
+} def
+/nc 3 dict def
+nc begin
+/setgray
+{
+ pop
+} bind def
+/setcmykcolor
+{
+ 4 npop
+} bind def
+/setcustomcolor
+{
+ 2 npop
+} bind def
+currentdict readonly pop
+end
+currentdict readonly pop
+end
+setpacking
+%%EndResource
+%%EndProlog
+%%BeginSetup
+Adobe_level2_AI5 /initialize get exec
+Adobe_IllustratorA_AI5 /initialize get exec
+%AI5_Begin_NonPrinting
+Np
+%AI3_BeginPattern: (Yellow Stripe)
+(Yellow Stripe) 8.4499 4.6 80.4499 76.6 [
+%AI3_Tile
+(0 O 0 R 0 0.4 1 0 k 0 0.4 1 0 K) @
+(
+800 Ar
+0 J 0 j 3.6 w 4 M []0 d
+%AI3_Note:
+0 D
+8.1999 8.1999 m
+80.6999 8.1999 L
+S
+8.1999 22.6 m
+80.6999 22.6 L
+S
+8.1999 37.0001 m
+80.6999 37.0001 L
+S
+8.1999 51.3999 m
+80.6999 51.3999 L
+S
+8.1999 65.8 m
+80.6999 65.8 L
+S
+8.1999 15.3999 m
+80.6999 15.3999 L
+S
+8.1999 29.8 m
+80.6999 29.8 L
+S
+8.1999 44.1999 m
+80.6999 44.1999 L
+S
+8.1999 58.6 m
+80.6999 58.6 L
+S
+8.1999 73.0001 m
+80.6999 73.0001 L
+S
+) &
+] E
+%AI3_EndPattern
+%AI5_End_NonPrinting--
+%AI5_Begin_NonPrinting
+Np
+3 Bn
+%AI5_BeginGradient: (Black & White)
+(Black & White) 0 2 Bd
+[
+<
+FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8
+D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5C4C3C2C1C0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0
+AFAEADACABAAA9A8A7A6A5A4A3A2A1A09F9E9D9C9B9A999897969594939291908F8E8D8C8B8A8988
+87868584838281807F7E7D7C7B7A797877767574737271706F6E6D6C6B6A69686766656463626160
+5F5E5D5C5B5A595857565554535251504F4E4D4C4B4A494847464544434241403F3E3D3C3B3A3938
+37363534333231302F2E2D2C2B2A292827262524232221201F1E1D1C1B1A19181716151413121110
+0F0E0D0C0B0A09080706050403020100
+>
+0 %_Br
+[
+0 0 50 100 %_Bs
+1 0 50 0 %_Bs
+BD
+%AI5_EndGradient
+%AI5_BeginGradient: (Red & Yellow)
+(Red & Yellow) 0 2 Bd
+[
+0
+<
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627
+28292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F
+505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F7071727374757677
+78797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7
+C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF
+F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF
+>
+<
+FFFFFEFEFDFDFDFCFCFBFBFBFAFAF9F9F9F8F8F7F7F7F6F6F5F5F5F4F4F3F3F3F2F2F1F1F1F0F0EF
+EFEFEEEEEDEDEDECECEBEBEBEAEAE9E9E9E8E8E7E7E7E6E6E5E5E5E4E4E3E3E3E2E2E1E1E1E0E0DF
+DFDFDEDEDDDDDDDCDCDBDBDBDADAD9D9D9D8D8D7D7D7D6D6D5D5D5D4D4D3D3D3D2D2D1D1D1D0D0CF
+CFCFCECECDCDCDCCCCCBCBCBCACAC9C9C9C8C8C7C7C7C6C6C5C5C5C4C4C3C3C3C2C2C1C1C1C0C0BF
+BFBFBEBEBDBDBDBCBCBBBBBBBABAB9B9B9B8B8B7B7B7B6B6B5B5B5B4B4B3B3B3B2B2B1B1B1B0B0AF
+AFAFAEAEADADADACACABABABAAAAA9A9A9A8A8A7A7A7A6A6A5A5A5A4A4A3A3A3A2A2A1A1A1A0A09F
+9F9F9E9E9D9D9D9C9C9B9B9B9A9A9999
+>
+0
+1 %_Br
+[
+0 1 0.6 0 1 50 100 %_Bs
+0 0 1 0 1 50 0 %_Bs
+BD
+%AI5_EndGradient
+%AI5_BeginGradient: (Yellow & Blue Radial)
+(Yellow & Blue Radial) 1 2 Bd
+[
+<
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627
+28292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F
+505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F7071727374757677
+78797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7
+C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF
+F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF
+>
+<
+1415161718191A1B1C1D1E1F1F202122232425262728292A2A2B2C2D2E2F30313233343536363738
+393A3B3C3D3E3F40414142434445464748494A4B4C4D4D4E4F50515253545556575858595A5B5C5D
+5E5F60616263646465666768696A6B6C6D6E6F6F707172737475767778797A7B7B7C7D7E7F808182
+83848586868788898A8B8C8D8E8F90919292939495969798999A9B9C9D9D9E9FA0A1A2A3A4A5A6A7
+A8A9A9AAABACADAEAFB0B1B2B3B4B4B5B6B7B8B9BABBBCBDBEBFC0C0C1C2C3C4C5C6C7C8C9CACBCB
+CCCDCECFD0D1D2D3D4D5D6D7D7D8D9DADBDCDDDEDFE0E1E2E2E3E4E5E6E7E8E9EAEBECEDEEEEEFF0
+F1F2F3F4F5F6F7F8F9F9FAFBFCFDFEFF
+>
+<
+ABAAAAA9A8A7A7A6A5A5A4A3A3A2A1A1A09F9F9E9D9D9C9B9B9A9999989797969595949393929191
+908F8F8E8D8D8C8B8B8A8989888787868585848383828181807F7F7E7D7D7C7B7B7A797978777776
+7575747373727171706F6F6E6D6D6C6B6B6A6969686767666565646362626160605F5E5E5D5C5C5B
+5A5A5958585756565554545352525150504F4E4E4D4C4C4B4A4A4948484746464544444342424140
+403F3E3E3D3C3C3B3A3A3938383736363534343332323130302F2E2E2D2C2C2B2A2A292828272626
+25242423222121201F1F1E1D1D1C1B1B1A1919181717161515141313121111100F0F0E0D0D0C0B0B
+0A090908070706050504030302010100
+>
+0
+1 %_Br
+[
+0 0.08 0.67 0 1 50 14 %_Bs
+1 1 0 0 1 50 100 %_Bs
+BD
+%AI5_EndGradient
+%AI5_End_NonPrinting--
+%AI5_BeginPalette
+144 161 Pb
+Pn
+Pc
+1 g
+Pc
+0 g
+Pc
+0 0 0 0 k
+Pc
+0.75 g
+Pc
+0.5 g
+Pc
+0.25 g
+Pc
+0 g
+Pc
+Bb
+2 (Black & White) -4014 4716 0 0 1 0 0 1 0 0 Bg
+0 BB
+Pc
+0.25 0 0 0 k
+Pc
+0.5 0 0 0 k
+Pc
+0.75 0 0 0 k
+Pc
+1 0 0 0 k
+Pc
+0.25 0.25 0 0 k
+Pc
+0.5 0.5 0 0 k
+Pc
+0.75 0.75 0 0 k
+Pc
+1 1 0 0 k
+Pc
+Bb
+2 (Red & Yellow) -4014 4716 0 0 1 0 0 1 0 0 Bg
+0 BB
+Pc
+0 0.25 0 0 k
+Pc
+0 0.5 0 0 k
+Pc
+0 0.75 0 0 k
+Pc
+0 1 0 0 k
+Pc
+0 0.25 0.25 0 k
+Pc
+0 0.5 0.5 0 k
+Pc
+0 0.75 0.75 0 k
+Pc
+0 1 1 0 k
+Pc
+Bb
+0 0 0 0 Bh
+2 (Yellow & Blue Radial) -4014 4716 0 0 1 0 0 1 0 0 Bg
+0 BB
+Pc
+0 0 0.25 0 k
+Pc
+0 0 0.5 0 k
+Pc
+0 0 0.75 0 k
+Pc
+0 0 1 0 k
+Pc
+0.25 0 0.25 0 k
+Pc
+0.5 0 0.5 0 k
+Pc
+0.75 0 0.75 0 k
+Pc
+1 0 1 0 k
+Pc
+(Yellow Stripe) 0 0 1 1 0 0 0 0 0 [1 0 0 1 0 0] p
+Pc
+0.25 0.125 0 0 k
+Pc
+0.5 0.25 0 0 k
+Pc
+0.75 0.375 0 0 k
+Pc
+1 0.5 0 0 k
+Pc
+0.125 0.25 0 0 k
+Pc
+0.25 0.5 0 0 k
+Pc
+0.375 0.75 0 0 k
+Pc
+0.5 1 0 0 k
+Pc
+0.375 0.375 0.75 0 k
+Pc
+0 0.25 0.125 0 k
+Pc
+0 0.5 0.25 0 k
+Pc
+0 0.75 0.375 0 k
+Pc
+0 1 0.5 0 k
+Pc
+0 0.125 0.25 0 k
+Pc
+0 0.25 0.5 0 k
+Pc
+0 0.375 0.75 0 k
+Pc
+0 0.5 1 0 k
+Pc
+0 0.79 0.91 0 (PANTONE Warm Red CV) 0 x
+Pc
+0.125 0 0.25 0 k
+Pc
+0.25 0 0.5 0 k
+Pc
+0.375 0 0.75 0 k
+Pc
+0.5 0 1 0 k
+Pc
+0.25 0 0.125 0 k
+Pc
+0.5 0 0.25 0 k
+Pc
+0.75 0 0.375 0 k
+Pc
+1 0 0.5 0 k
+Pc
+0.5 1 0 0 k
+Pc
+0.25 0.125 0.125 0 k
+Pc
+0.5 0.25 0.25 0 k
+Pc
+0.75 0.375 0.375 0 k
+Pc
+1 0.5 0.5 0 k
+Pc
+0.25 0.25 0.125 0 k
+Pc
+0.5 0.5 0.25 0 k
+Pc
+0.75 0.75 0.375 0 k
+Pc
+1 1 0.5 0 k
+Pc
+0 1 0.5 0 k
+Pc
+0.125 0.25 0.125 0 k
+Pc
+0.25 0.5 0.25 0 k
+Pc
+0.375 0.75 0.375 0 k
+Pc
+0.5 1 0.5 0 k
+Pc
+0.125 0.25 0.25 0 k
+Pc
+0.25 0.5 0.5 0 k
+Pc
+0.375 0.75 0.75 0 k
+Pc
+0.5 1 1 0 k
+Pc
+0.75 0.75 0.375 0 k
+Pc
+0.125 0.125 0.25 0 k
+Pc
+0.25 0.25 0.5 0 k
+Pc
+0.375 0.375 0.75 0 k
+Pc
+0.5 0.5 1 0 k
+Pc
+0.25 0.125 0.25 0 k
+Pc
+0.5 0.25 0.5 0 k
+Pc
+0.75 0.375 0.75 0 k
+Pc
+1 0.5 1 0 k
+Pc
+0 0.79 0.91 0 (PANTONE Warm Red CV) 0 x
+Pc
+0 0 0 0 k
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+1 0.5 0.5 0 k
+Pc
+0 0 0 0 k
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+0 0.25 1 0 (Orange Yellow) 0 x
+Pc
+0 0 0 0 k
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+0 1 0.5 0 k
+Pc
+0 0 0 0 k
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+1 0 0.5 0 k
+Pc
+0 0 0 0 k
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+0 0.45 1 0 (Orange) 0 x
+Pc
+0 0 0 0 k
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+0.375 0.375 0.75 0 k
+Pc
+0 0 0 0 k
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+0 0.79 0.91 0 (PANTONE Warm Red CV) 0 x
+Pc
+0 0 0 0 k
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+1 0.65 0 0 k
+Pc
+0 0 0 0 k
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+Pc
+0 0 1 0 k
+Pc
+PB
+%AI5_EndPalette
+%%EndSetup
+%AI5_BeginLayer
+1 1 1 1 0 0 0 79 128 255 Lb
+(Layer 1) Ln
+0 A
+1 Ap
+0 O
+1 0.65 0 0 k
+800 Ar
+0 J 0 j 1 w 4 M []0 d
+%AI3_Note:
+0 D
+285.0121 311.7976 m
+357.5043 302.5199 L
+361.6071 392.7105 L
+376.3322 474.1377 L
+342.6527 475.6628 L
+327.6333 483.4165 L
+258.8269 486.3189 L
+254.4361 405.0427 L
+242.0523 312.2099 L
+285.0121 311.7976 L
+f
+0 0.79 0.91 0 k
+1.25 w
+295.4466 337.6172 m
+368.4943 335.3343 L
+363.9288 425.5026 L
+370.7771 507.9667 L
+337.1066 506.2547 L
+321.4128 512.5323 L
+252.6452 508.8228 L
+256.0692 427.5002 L
+252.6452 333.9077 L
+295.4466 337.6172 L
+f
+u
+0 Ap
+1 0.65 0 0 k
+1 w
+320.532 390.6149 m
+312.9017 388.534 l
+317.0637 398.5921 l
+321.2256 426.6854 l
+316.0232 427.7258 l
+322.2662 436.3965 l
+330.0436 465.6249 l
+316.3701 462.7557 l
+323.5798 475.9563 331.2311 484.5534 v
+321.2256 492.2363 l
+288.9913 478.0373 297.6622 431.9088 v
+290.9988 433.0755 l
+297.3888 384.7188 l
+291.9867 383.3315 l
+297.5214 372.0383 305.2714 366.6837 v
+305.9749 366.1976 295.5601 404.4882 306.6587 442.6395 c
+307.6992 440.2117 l
+298.855 399.5459 307.6992 366.6837 v
+308.1064 365.9033 312.5286 366.4235 v
+320.532 381.5106 320.532 390.6149 v
+f
+u
+*u
+1 g
+263.6948 355.9856 m
+265.2612 355.9856 L
+265.2612 359.2513 L
+265.9515 359.2513 266.6153 359.2513 267.2791 359.3575 c
+267.2791 355.9856 L
+269.6155 355.9856 L
+269.6155 355.3749 L
+267.2791 355.3749 L
+267.2791 347.2505 L
+267.2791 346.7726 267.2791 346.0558 268.288 346.0558 c
+268.9783 346.0558 269.35 346.5337 269.7748 347.0381 c
+270.1996 346.7461 L
+269.6951 345.7372 268.3942 345.1265 267.3322 345.1265 c
+265.4205 345.1265 265.2081 346.162 265.2081 347.4364 c
+265.2081 355.3749 L
+263.6948 355.3749 L
+263.6948 355.9856 l
+f
+*U
+*u
+285.7796 348.7639 m
+285.1689 346.8788 284.1069 345.2327 281.3457 345.1265 c
+277.2304 345.1265 275.9825 348.5515 275.9825 350.3835 c
+275.9825 355.1094 279.7792 356.2511 281.2926 356.2511 c
+283.0184 356.2511 285.461 355.4546 285.461 353.4102 c
+285.461 352.6934 285.0096 352.003 284.2662 352.003 c
+283.5494 352.003 283.0184 352.481 283.0184 353.2509 c
+283.0184 354.2864 283.868 354.4191 283.868 354.7112 c
+283.868 355.428 282.1953 355.7201 281.6112 355.7201 c
+279.0624 355.7201 278.3986 353.8616 278.3986 350.3835 c
+278.3986 348.7905 278.7969 347.5691 278.9562 347.1974 c
+279.3544 346.3213 280.1775 345.7637 281.5581 345.6841 c
+283.098 345.6044 284.5848 346.8523 285.222 348.7639 C
+285.7796 348.7639 l
+f
+*U
+*u
+291.9344 345.4717 m
+291.9344 346.0823 L
+293.9788 346.0823 L
+293.9788 363.1542 L
+291.9344 363.1542 L
+291.9344 363.7648 L
+293.0761 363.7648 L
+294.0585 363.7648 295.0939 363.8179 296.0497 364.0038 c
+296.0497 346.0823 L
+298.0941 346.0823 L
+298.0941 345.4717 L
+291.9344 345.4717 l
+f
+*U
+u
+310.0634 446.075 m
+305.3828 425.2059 306.7298 391.3708 v
+307.1338 381.222 308.2436 371.8929 309.5993 363.8029 C
+309.6066 363.8025 L
+310.4883 356.6987 311.0781 354.1272 313.3768 345.5676 C
+313.2426 340.0473 L
+294.8367 398.8155 310.0634 446.075 V
+f
+321.3622 464.1699 m
+325.5016 466.2317 331.4359 466.9819 v
+337.9224 455.0924 321.9584 434.793 v
+331.4821 456.0522 329.2358 462.7122 v
+326.7243 464.2727 321.3622 464.1699 v
+f
+319.4002 428.4819 m
+323.1177 427.6214 324.9024 429.0668 v
+321.386 415.3445 322.3077 407.7964 v
+323.2297 400.2483 316.5788 395.4159 y
+322.2441 402.584 320.4635 408.4226 v
+319.2289 412.4694 320.6101 422.8271 322.1681 426.1155 c
+320.7131 426.3196 319.4002 428.4819 v
+f
+315.7246 392.3281 m
+321.8677 393.0631 322.5131 396.1662 v
+323.265 377.6058 314.7299 369.9571 v
+321.2425 380.1152 320.2206 390.6235 v
+315.7246 392.3281 l
+f
+298.4445 384.6023 m
+296.4635 382.3836 290.5192 387.2778 v
+292.4131 374.803 304.1781 369.0924 v
+296.0814 375.1928 293.9 381.7824 v
+296.7611 382.6245 298.4445 384.6023 v
+f
+296.5483 389.3335 m
+288.5102 409.7356 290.2325 437.3036 v
+292.1098 432.3112 298.1424 430.5604 v
+295.3003 429.9794 293.6387 430.2313 v
+289.4335 418.5932 296.5483 389.3335 v
+f
+330.3126 484.1353 m
+327.3003 506.2722 308.4549 483.8853 v
+293.4491 466.0592 295.2373 450.9247 296.1578 442.4811 c
+296.3932 440.3206 293.366 465.0316 309.8067 481.2933 c
+326.2471 497.5553 329.9609 485.0794 330.3126 484.1353 c
+f
+U
+0 0 1 0 k
+302.5528 503.0164 m
+287.7656 507.2395 283.0593 458.227 v
+279.4282 473.3549 288.8204 494.7509 v
+298.2122 516.1468 302.5528 503.0164 y
+f
+284.2076 506.5994 m
+276.6655 495.2557 278.3767 483.1729 v
+272.6565 505.9183 284.2076 506.5994 v
+f
+339.7135 474.7902 m
+348.6321 478.0799 335.8615 444.8834 v
+342.4718 454.5848 346.6326 469.8253 v
+349.303 479.6062 339.7135 474.7902 y
+f
+354.1382 477.3767 m
+360.4435 471.669 355.9752 464.1187 v
+367.1908 475.904 354.1382 477.3767 v
+f
+U
+U
+*u
+1 g
+258.2029 317.4593 m
+256.6821 317.4593 L
+256.6821 325.2598 L
+258.7512 325.2598 L
+260.3858 325.2598 261.4514 324.608 261.4514 322.839 c
+261.4514 321.1837 260.5513 320.3767 258.9581 320.3767 c
+258.2029 320.3767 L
+258.2029 317.4593 l
+f
+1 D
+258.2029 321.6389 m
+258.5132 321.6389 L
+259.4133 321.6389 259.8995 321.8354 259.8995 322.8493 c
+259.8995 323.8528 259.3202 323.9976 258.4719 323.9976 c
+258.2029 323.9976 L
+258.2029 321.6389 l
+f
+*U
+*u
+0 D
+269.0694 321.3699 m
+269.0694 323.5528 270.6523 325.4667 272.9283 325.4667 c
+275.2043 325.4667 276.7871 323.5528 276.7871 321.3699 c
+276.7871 319.1353 275.2043 317.2524 272.9283 317.2524 c
+270.6523 317.2524 269.0694 319.1353 269.0694 321.3699 c
+f
+1 D
+270.6419 321.432 m
+270.6419 320.2526 271.6351 318.7525 272.9283 318.7525 c
+274.2215 318.7525 275.2146 320.2526 275.2146 321.432 c
+275.2146 322.6941 274.2628 323.9666 272.9283 323.9666 c
+271.5937 323.9666 270.6419 322.6941 270.6419 321.432 c
+f
+*U
+*u
+0 D
+287.2943 319.9422 m
+287.315 319.9422 L
+288.8668 325.3632 L
+289.7668 325.3632 L
+291.3807 319.9422 L
+291.4014 319.9422 L
+292.9326 325.2598 L
+294.5258 325.2598 L
+291.8877 317.3041 L
+290.7704 317.3041 L
+289.2185 322.4044 L
+289.1978 322.4044 L
+287.7288 317.3041 L
+286.6115 317.3041 L
+284.1286 325.2598 L
+285.7218 325.2598 L
+287.2943 319.9422 l
+f
+*U
+*u
+303.7595 323.9356 m
+303.7595 322.2182 L
+306.1803 322.2182 L
+306.1803 320.894 L
+303.7595 320.894 L
+303.7595 318.7835 L
+306.2734 318.7835 L
+306.2734 317.4593 L
+302.2387 317.4593 L
+302.2387 325.2598 L
+306.2734 325.2598 L
+306.2734 323.9356 L
+303.7595 323.9356 l
+f
+*U
+*u
+319.8602 317.4593 m
+318.0187 317.4593 L
+316.1255 320.6043 L
+316.1048 320.6043 L
+316.1048 317.4593 L
+314.5841 317.4593 L
+314.5841 325.2598 L
+316.6428 325.2598 L
+318.1843 325.2598 319.2499 324.577 319.2499 322.9114 c
+319.2499 321.9182 318.7015 320.925 317.6567 320.7492 C
+319.8602 317.4593 l
+f
+1 D
+316.1048 321.6699 m
+316.3014 321.6699 L
+317.1394 321.6699 317.7291 321.9182 317.7291 322.87 c
+317.7291 323.8321 317.1187 324.0183 316.3117 324.0183 c
+316.1048 324.0183 L
+316.1048 321.6699 l
+f
+*U
+*u
+0 D
+329.1754 323.9356 m
+329.1754 322.2182 L
+331.5962 322.2182 L
+331.5962 320.894 L
+329.1754 320.894 L
+329.1754 318.7835 L
+331.6894 318.7835 L
+331.6894 317.4593 L
+327.6546 317.4593 L
+327.6546 325.2598 L
+331.6894 325.2598 L
+331.6894 323.9356 L
+329.1754 323.9356 l
+f
+*U
+*u
+340 325.2598 m
+342.1725 325.2598 L
+344.4279 325.2598 345.9383 323.5735 345.9383 321.3492 c
+345.9383 319.156 344.3865 317.4593 342.1622 317.4593 c
+340 317.4593 L
+340 325.2598 l
+f
+1 D
+341.5208 318.7835 m
+341.7691 318.7835 L
+343.6416 318.7835 344.3658 319.8181 344.3658 321.3596 c
+344.3658 323.0562 343.4968 323.9356 341.7691 323.9356 c
+341.5208 323.9356 L
+341.5208 318.7835 l
+f
+*U
+LB
+%AI5_EndLayer--
+%%PageTrailer
+gsave annotatepage grestore showpage
+%%Trailer
+Adobe_IllustratorA_AI5 /terminate get exec
+Adobe_level2_AI5 /terminate get exec
+%%EOF
diff --git a/tk8.6/library/images/pwrdLogo100.gif b/tk8.6/library/images/pwrdLogo100.gif
new file mode 100644
index 0000000..d2f8cbb
--- /dev/null
+++ b/tk8.6/library/images/pwrdLogo100.gif
Binary files differ
diff --git a/tk8.6/library/images/pwrdLogo150.gif b/tk8.6/library/images/pwrdLogo150.gif
new file mode 100644
index 0000000..89eec7c
--- /dev/null
+++ b/tk8.6/library/images/pwrdLogo150.gif
Binary files differ
diff --git a/tk8.6/library/images/pwrdLogo175.gif b/tk8.6/library/images/pwrdLogo175.gif
new file mode 100644
index 0000000..02dcd92
--- /dev/null
+++ b/tk8.6/library/images/pwrdLogo175.gif
Binary files differ
diff --git a/tk8.6/library/images/pwrdLogo200.gif b/tk8.6/library/images/pwrdLogo200.gif
new file mode 100644
index 0000000..66426bf
--- /dev/null
+++ b/tk8.6/library/images/pwrdLogo200.gif
Binary files differ
diff --git a/tk8.6/library/images/pwrdLogo75.gif b/tk8.6/library/images/pwrdLogo75.gif
new file mode 100644
index 0000000..e75925c
--- /dev/null
+++ b/tk8.6/library/images/pwrdLogo75.gif
Binary files differ
diff --git a/tk8.6/library/images/tai-ku.gif b/tk8.6/library/images/tai-ku.gif
new file mode 100644
index 0000000..a5aea47
--- /dev/null
+++ b/tk8.6/library/images/tai-ku.gif
Binary files differ
diff --git a/tk8.6/library/listbox.tcl b/tk8.6/library/listbox.tcl
new file mode 100644
index 0000000..16e51bd
--- /dev/null
+++ b/tk8.6/library/listbox.tcl
@@ -0,0 +1,552 @@
+# listbox.tcl --
+#
+# This file defines the default bindings for Tk listbox widgets
+# and provides procedures that help in implementing those bindings.
+#
+# Copyright (c) 1994 The Regents of the University of California.
+# Copyright (c) 1994-1995 Sun Microsystems, Inc.
+# Copyright (c) 1998 by Scriptics Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+#--------------------------------------------------------------------------
+# tk::Priv elements used in this file:
+#
+# afterId - Token returned by "after" for autoscanning.
+# listboxPrev - The last element to be selected or deselected
+# during a selection operation.
+# listboxSelection - All of the items that were selected before the
+# current selection operation (such as a mouse
+# drag) started; used to cancel an operation.
+#--------------------------------------------------------------------------
+
+#-------------------------------------------------------------------------
+# The code below creates the default class bindings for listboxes.
+#-------------------------------------------------------------------------
+
+# Note: the check for existence of %W below is because this binding
+# is sometimes invoked after a window has been deleted (e.g. because
+# there is a double-click binding on the widget that deletes it). Users
+# can put "break"s in their bindings to avoid the error, but this check
+# makes that unnecessary.
+
+bind Listbox <1> {
+ if {[winfo exists %W]} {
+ tk::ListboxBeginSelect %W [%W index @%x,%y] 1
+ }
+}
+
+# Ignore double clicks so that users can define their own behaviors.
+# Among other things, this prevents errors if the user deletes the
+# listbox on a double click.
+
+bind Listbox <Double-1> {
+ # Empty script
+}
+
+bind Listbox <B1-Motion> {
+ set tk::Priv(x) %x
+ set tk::Priv(y) %y
+ tk::ListboxMotion %W [%W index @%x,%y]
+}
+bind Listbox <ButtonRelease-1> {
+ tk::CancelRepeat
+ %W activate @%x,%y
+}
+bind Listbox <Shift-1> {
+ tk::ListboxBeginExtend %W [%W index @%x,%y]
+}
+bind Listbox <Control-1> {
+ tk::ListboxBeginToggle %W [%W index @%x,%y]
+}
+bind Listbox <B1-Leave> {
+ set tk::Priv(x) %x
+ set tk::Priv(y) %y
+ tk::ListboxAutoScan %W
+}
+bind Listbox <B1-Enter> {
+ tk::CancelRepeat
+}
+
+bind Listbox <<PrevLine>> {
+ tk::ListboxUpDown %W -1
+}
+bind Listbox <<SelectPrevLine>> {
+ tk::ListboxExtendUpDown %W -1
+}
+bind Listbox <<NextLine>> {
+ tk::ListboxUpDown %W 1
+}
+bind Listbox <<SelectNextLine>> {
+ tk::ListboxExtendUpDown %W 1
+}
+bind Listbox <<PrevChar>> {
+ %W xview scroll -1 units
+}
+bind Listbox <<PrevWord>> {
+ %W xview scroll -1 pages
+}
+bind Listbox <<NextChar>> {
+ %W xview scroll 1 units
+}
+bind Listbox <<NextWord>> {
+ %W xview scroll 1 pages
+}
+bind Listbox <Prior> {
+ %W yview scroll -1 pages
+ %W activate @0,0
+}
+bind Listbox <Next> {
+ %W yview scroll 1 pages
+ %W activate @0,0
+}
+bind Listbox <Control-Prior> {
+ %W xview scroll -1 pages
+}
+bind Listbox <Control-Next> {
+ %W xview scroll 1 pages
+}
+bind Listbox <<LineStart>> {
+ %W xview moveto 0
+}
+bind Listbox <<LineEnd>> {
+ %W xview moveto 1
+}
+bind Listbox <Control-Home> {
+ %W activate 0
+ %W see 0
+ %W selection clear 0 end
+ %W selection set 0
+ tk::FireListboxSelectEvent %W
+}
+bind Listbox <Control-Shift-Home> {
+ tk::ListboxDataExtend %W 0
+}
+bind Listbox <Control-End> {
+ %W activate end
+ %W see end
+ %W selection clear 0 end
+ %W selection set end
+ tk::FireListboxSelectEvent %W
+}
+bind Listbox <Control-Shift-End> {
+ tk::ListboxDataExtend %W [%W index end]
+}
+bind Listbox <<Copy>> {
+ if {[selection own -displayof %W] eq "%W"} {
+ clipboard clear -displayof %W
+ clipboard append -displayof %W [selection get -displayof %W]
+ }
+}
+bind Listbox <space> {
+ tk::ListboxBeginSelect %W [%W index active]
+}
+bind Listbox <<Invoke>> {
+ tk::ListboxBeginSelect %W [%W index active]
+}
+bind Listbox <Select> {
+ tk::ListboxBeginSelect %W [%W index active]
+}
+bind Listbox <Control-Shift-space> {
+ tk::ListboxBeginExtend %W [%W index active]
+}
+bind Listbox <Shift-Select> {
+ tk::ListboxBeginExtend %W [%W index active]
+}
+bind Listbox <Escape> {
+ tk::ListboxCancel %W
+}
+bind Listbox <<SelectAll>> {
+ tk::ListboxSelectAll %W
+}
+bind Listbox <<SelectNone>> {
+ if {[%W cget -selectmode] ne "browse"} {
+ %W selection clear 0 end
+ tk::FireListboxSelectEvent %W
+ }
+}
+
+# Additional Tk bindings that aren't part of the Motif look and feel:
+
+bind Listbox <2> {
+ %W scan mark %x %y
+}
+bind Listbox <B2-Motion> {
+ %W scan dragto %x %y
+}
+
+# The MouseWheel will typically only fire on Windows and Mac OS X.
+# However, someone could use the "event generate" command to produce
+# one on other platforms.
+
+if {[tk windowingsystem] eq "aqua"} {
+ bind Listbox <MouseWheel> {
+ %W yview scroll [expr {- (%D)}] units
+ }
+ bind Listbox <Option-MouseWheel> {
+ %W yview scroll [expr {-10 * (%D)}] units
+ }
+ bind Listbox <Shift-MouseWheel> {
+ %W xview scroll [expr {- (%D)}] units
+ }
+ bind Listbox <Shift-Option-MouseWheel> {
+ %W xview scroll [expr {-10 * (%D)}] units
+ }
+} else {
+ bind Listbox <MouseWheel> {
+ %W yview scroll [expr {- (%D / 120) * 4}] units
+ }
+ bind Listbox <Shift-MouseWheel> {
+ %W xview scroll [expr {- (%D / 120) * 4}] units
+ }
+}
+
+if {"x11" eq [tk windowingsystem]} {
+ # Support for mousewheels on Linux/Unix commonly comes through mapping
+ # the wheel to the extended buttons. If you have a mousewheel, find
+ # Linux configuration info at:
+ # http://linuxreviews.org/howtos/xfree/mouse/
+ bind Listbox <4> {
+ if {!$tk_strictMotif} {
+ %W yview scroll -5 units
+ }
+ }
+ bind Listbox <Shift-4> {
+ if {!$tk_strictMotif} {
+ %W xview scroll -5 units
+ }
+ }
+ bind Listbox <5> {
+ if {!$tk_strictMotif} {
+ %W yview scroll 5 units
+ }
+ }
+ bind Listbox <Shift-5> {
+ if {!$tk_strictMotif} {
+ %W xview scroll 5 units
+ }
+ }
+}
+
+# ::tk::ListboxBeginSelect --
+#
+# This procedure is typically invoked on button-1 presses. It begins
+# the process of making a selection in the listbox. Its exact behavior
+# depends on the selection mode currently in effect for the listbox;
+# see the Motif documentation for details.
+#
+# Arguments:
+# w - The listbox widget.
+# el - The element for the selection operation (typically the
+# one under the pointer). Must be in numerical form.
+
+proc ::tk::ListboxBeginSelect {w el {focus 1}} {
+ variable ::tk::Priv
+ if {[$w cget -selectmode] eq "multiple"} {
+ if {[$w selection includes $el]} {
+ $w selection clear $el
+ } else {
+ $w selection set $el
+ }
+ } else {
+ $w selection clear 0 end
+ $w selection set $el
+ $w selection anchor $el
+ set Priv(listboxSelection) {}
+ set Priv(listboxPrev) $el
+ }
+ tk::FireListboxSelectEvent $w
+ # check existence as ListboxSelect may destroy us
+ if {$focus && [winfo exists $w] && [$w cget -state] eq "normal"} {
+ focus $w
+ }
+}
+
+# ::tk::ListboxMotion --
+#
+# This procedure is called to process mouse motion events while
+# button 1 is down. It may move or extend the selection, depending
+# on the listbox's selection mode.
+#
+# Arguments:
+# w - The listbox widget.
+# el - The element under the pointer (must be a number).
+
+proc ::tk::ListboxMotion {w el} {
+ variable ::tk::Priv
+ if {$el == $Priv(listboxPrev)} {
+ return
+ }
+ set anchor [$w index anchor]
+ switch [$w cget -selectmode] {
+ browse {
+ $w selection clear 0 end
+ $w selection set $el
+ set Priv(listboxPrev) $el
+ tk::FireListboxSelectEvent $w
+ }
+ extended {
+ set i $Priv(listboxPrev)
+ if {$i eq ""} {
+ set i $el
+ $w selection set $el
+ }
+ if {[$w selection includes anchor]} {
+ $w selection clear $i $el
+ $w selection set anchor $el
+ } else {
+ $w selection clear $i $el
+ $w selection clear anchor $el
+ }
+ if {![info exists Priv(listboxSelection)]} {
+ set Priv(listboxSelection) [$w curselection]
+ }
+ while {($i < $el) && ($i < $anchor)} {
+ if {[lsearch $Priv(listboxSelection) $i] >= 0} {
+ $w selection set $i
+ }
+ incr i
+ }
+ while {($i > $el) && ($i > $anchor)} {
+ if {[lsearch $Priv(listboxSelection) $i] >= 0} {
+ $w selection set $i
+ }
+ incr i -1
+ }
+ set Priv(listboxPrev) $el
+ tk::FireListboxSelectEvent $w
+ }
+ }
+}
+
+# ::tk::ListboxBeginExtend --
+#
+# This procedure is typically invoked on shift-button-1 presses. It
+# begins the process of extending a selection in the listbox. Its
+# exact behavior depends on the selection mode currently in effect
+# for the listbox; see the Motif documentation for details.
+#
+# Arguments:
+# w - The listbox widget.
+# el - The element for the selection operation (typically the
+# one under the pointer). Must be in numerical form.
+
+proc ::tk::ListboxBeginExtend {w el} {
+ if {[$w cget -selectmode] eq "extended"} {
+ if {[$w selection includes anchor]} {
+ ListboxMotion $w $el
+ } else {
+ # No selection yet; simulate the begin-select operation.
+ ListboxBeginSelect $w $el
+ }
+ }
+}
+
+# ::tk::ListboxBeginToggle --
+#
+# This procedure is typically invoked on control-button-1 presses. It
+# begins the process of toggling a selection in the listbox. Its
+# exact behavior depends on the selection mode currently in effect
+# for the listbox; see the Motif documentation for details.
+#
+# Arguments:
+# w - The listbox widget.
+# el - The element for the selection operation (typically the
+# one under the pointer). Must be in numerical form.
+
+proc ::tk::ListboxBeginToggle {w el} {
+ variable ::tk::Priv
+ if {[$w cget -selectmode] eq "extended"} {
+ set Priv(listboxSelection) [$w curselection]
+ set Priv(listboxPrev) $el
+ $w selection anchor $el
+ if {[$w selection includes $el]} {
+ $w selection clear $el
+ } else {
+ $w selection set $el
+ }
+ tk::FireListboxSelectEvent $w
+ }
+}
+
+# ::tk::ListboxAutoScan --
+# This procedure is invoked when the mouse leaves an entry window
+# with button 1 down. It scrolls the window up, down, left, or
+# right, depending on where the mouse left the window, and reschedules
+# itself as an "after" command so that the window continues to scroll until
+# the mouse moves back into the window or the mouse button is released.
+#
+# Arguments:
+# w - The entry window.
+
+proc ::tk::ListboxAutoScan {w} {
+ variable ::tk::Priv
+ if {![winfo exists $w]} return
+ set x $Priv(x)
+ set y $Priv(y)
+ if {$y >= [winfo height $w]} {
+ $w yview scroll 1 units
+ } elseif {$y < 0} {
+ $w yview scroll -1 units
+ } elseif {$x >= [winfo width $w]} {
+ $w xview scroll 2 units
+ } elseif {$x < 0} {
+ $w xview scroll -2 units
+ } else {
+ return
+ }
+ ListboxMotion $w [$w index @$x,$y]
+ set Priv(afterId) [after 50 [list tk::ListboxAutoScan $w]]
+}
+
+# ::tk::ListboxUpDown --
+#
+# Moves the location cursor (active element) up or down by one element,
+# and changes the selection if we're in browse or extended selection
+# mode.
+#
+# Arguments:
+# w - The listbox widget.
+# amount - +1 to move down one item, -1 to move back one item.
+
+proc ::tk::ListboxUpDown {w amount} {
+ variable ::tk::Priv
+ $w activate [expr {[$w index active] + $amount}]
+ $w see active
+ switch [$w cget -selectmode] {
+ browse {
+ $w selection clear 0 end
+ $w selection set active
+ tk::FireListboxSelectEvent $w
+ }
+ extended {
+ $w selection clear 0 end
+ $w selection set active
+ $w selection anchor active
+ set Priv(listboxPrev) [$w index active]
+ set Priv(listboxSelection) {}
+ tk::FireListboxSelectEvent $w
+ }
+ }
+}
+
+# ::tk::ListboxExtendUpDown --
+#
+# Does nothing unless we're in extended selection mode; in this
+# case it moves the location cursor (active element) up or down by
+# one element, and extends the selection to that point.
+#
+# Arguments:
+# w - The listbox widget.
+# amount - +1 to move down one item, -1 to move back one item.
+
+proc ::tk::ListboxExtendUpDown {w amount} {
+ variable ::tk::Priv
+ if {[$w cget -selectmode] ne "extended"} {
+ return
+ }
+ set active [$w index active]
+ if {![info exists Priv(listboxSelection)]} {
+ $w selection set $active
+ set Priv(listboxSelection) [$w curselection]
+ }
+ $w activate [expr {$active + $amount}]
+ $w see active
+ ListboxMotion $w [$w index active]
+}
+
+# ::tk::ListboxDataExtend
+#
+# This procedure is called for key-presses such as Shift-KEndData.
+# If the selection mode isn't multiple or extend then it does nothing.
+# Otherwise it moves the active element to el and, if we're in
+# extended mode, extends the selection to that point.
+#
+# Arguments:
+# w - The listbox widget.
+# el - An integer element number.
+
+proc ::tk::ListboxDataExtend {w el} {
+ set mode [$w cget -selectmode]
+ if {$mode eq "extended"} {
+ $w activate $el
+ $w see $el
+ if {[$w selection includes anchor]} {
+ ListboxMotion $w $el
+ }
+ } elseif {$mode eq "multiple"} {
+ $w activate $el
+ $w see $el
+ }
+}
+
+# ::tk::ListboxCancel
+#
+# This procedure is invoked to cancel an extended selection in
+# progress. If there is an extended selection in progress, it
+# restores all of the items between the active one and the anchor
+# to their previous selection state.
+#
+# Arguments:
+# w - The listbox widget.
+
+proc ::tk::ListboxCancel w {
+ variable ::tk::Priv
+ if {[$w cget -selectmode] ne "extended"} {
+ return
+ }
+ set first [$w index anchor]
+ set last $Priv(listboxPrev)
+ if {$last eq ""} {
+ # Not actually doing any selection right now
+ return
+ }
+ if {$first > $last} {
+ set tmp $first
+ set first $last
+ set last $tmp
+ }
+ $w selection clear $first $last
+ while {$first <= $last} {
+ if {[lsearch $Priv(listboxSelection) $first] >= 0} {
+ $w selection set $first
+ }
+ incr first
+ }
+ tk::FireListboxSelectEvent $w
+}
+
+# ::tk::ListboxSelectAll
+#
+# This procedure is invoked to handle the "select all" operation.
+# For single and browse mode, it just selects the active element.
+# Otherwise it selects everything in the widget.
+#
+# Arguments:
+# w - The listbox widget.
+
+proc ::tk::ListboxSelectAll w {
+ set mode [$w cget -selectmode]
+ if {$mode eq "single" || $mode eq "browse"} {
+ $w selection clear 0 end
+ $w selection set active
+ } else {
+ $w selection set 0 end
+ }
+ tk::FireListboxSelectEvent $w
+}
+
+# ::tk::FireListboxSelectEvent
+#
+# Fire the <<ListboxSelect>> event if the listbox is not in disabled
+# state.
+#
+# Arguments:
+# w - The listbox widget.
+
+proc ::tk::FireListboxSelectEvent w {
+ if {[$w cget -state] eq "normal"} {
+ event generate $w <<ListboxSelect>>
+ }
+}
diff --git a/tk8.6/library/megawidget.tcl b/tk8.6/library/megawidget.tcl
new file mode 100644
index 0000000..aeb1263
--- /dev/null
+++ b/tk8.6/library/megawidget.tcl
@@ -0,0 +1,297 @@
+# megawidget.tcl
+#
+# Basic megawidget support classes. Experimental for any use other than
+# the ::tk::IconList megawdget, which is itself only designed for use in
+# the Unix file dialogs.
+#
+# Copyright (c) 2009-2010 Donal K. Fellows
+#
+# See the file "license.terms" for information on usage and redistribution of
+# this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+
+package require Tk 8.6
+
+::oo::class create ::tk::Megawidget {
+ superclass ::oo::class
+ method unknown {w args} {
+ if {[string match .* $w]} {
+ [self] create $w {*}$args
+ return $w
+ }
+ next $w {*}$args
+ }
+ unexport new unknown
+ self method create {name superclasses body} {
+ next $name [list \
+ superclass ::tk::MegawidgetClass {*}$superclasses]\;$body
+ }
+}
+
+::oo::class create ::tk::MegawidgetClass {
+ variable w hull options IdleCallbacks
+ constructor args {
+ # Extract the "widget name" from the object name
+ set w [namespace tail [self]]
+
+ # Configure things
+ tclParseConfigSpec [my varname options] [my GetSpecs] "" $args
+
+ # Move the object out of the way of the hull widget
+ rename [self] _tmp
+
+ # Make the hull widget(s)
+ my CreateHull
+ bind $hull <Destroy> [list [namespace which my] destroy]
+
+ # Rename things into their final places
+ rename ::$w theWidget
+ rename [self] ::$w
+
+ # Make the contents
+ my Create
+ }
+ destructor {
+ foreach {name cb} [array get IdleCallbacks] {
+ after cancel $cb
+ unset IdleCallbacks($name)
+ }
+ if {[winfo exists $w]} {
+ bind $hull <Destroy> {}
+ destroy $w
+ }
+ }
+
+ ####################################################################
+ #
+ # MegawidgetClass::configure --
+ #
+ # Implementation of 'configure' for megawidgets. Emulates the operation
+ # of the standard Tk configure method fairly closely, which makes things
+ # substantially more complex than they otherwise would be.
+ #
+ # This method assumes that the 'GetSpecs' method returns a description
+ # of all the specifications of the options (i.e., as Tk returns except
+ # with the actual values removed). It also assumes that the 'options'
+ # array in the class holds all options; it is up to subclasses to set
+ # traces on that array if they want to respond to configuration changes.
+ #
+ # TODO: allow unambiguous abbreviations.
+ #
+ method configure args {
+ # Configure behaves differently depending on the number of arguments
+ set argc [llength $args]
+ if {$argc == 0} {
+ return [lmap spec [my GetSpecs] {
+ lappend spec $options([lindex $spec 0])
+ }]
+ } elseif {$argc == 1} {
+ set opt [lindex $args 0]
+ if {[info exists options($opt)]} {
+ set spec [lsearch -inline -index 0 -exact [my GetSpecs] $opt]
+ return [linsert $spec end $options($opt)]
+ }
+ } elseif {$argc == 2} {
+ # Special case for where we're setting a single option. This
+ # avoids some of the costly operations. We still do the [array
+ # get] as this gives a sufficiently-consistent trace.
+ set opt [lindex $args 0]
+ if {[dict exists [array get options] $opt]} {
+ # Actually set the new value of the option. Use a catch to
+ # allow a megawidget user to throw an error from a write trace
+ # on the options array to reject invalid values.
+ try {
+ array set options $args
+ } on error {ret info} {
+ # Rethrow the error to get a clean stack trace
+ return -code error -errorcode [dict get $info -errorcode] $ret
+ }
+ return
+ }
+ } elseif {$argc % 2 == 0} {
+ # Check that all specified options exist. Any unknown option will
+ # cause the merged dictionary to be bigger than the options array
+ set merge [dict merge [array get options] $args]
+ if {[dict size $merge] == [array size options]} {
+ # Actually set the new values of the options. Use a catch to
+ # allow a megawidget user to throw an error from a write trace
+ # on the options array to reject invalid values
+ try {
+ array set options $args
+ } on error {ret info} {
+ # Rethrow the error to get a clean stack trace
+ return -code error -errorcode [dict get $info -errorcode] $ret
+ }
+ return
+ }
+ # Due to the order of the merge, the unknown options will be at
+ # the end of the dict. This makes the first unknown option easy to
+ # find.
+ set opt [lindex [dict keys $merge] [array size options]]
+ } else {
+ set opt [lindex $args end]
+ return -code error -errorcode [list TK VALUE_MISSING] \
+ "value for \"$opt\" missing"
+ }
+ return -code error -errorcode [list TK LOOKUP OPTION $opt] \
+ "bad option \"$opt\": must be [tclListValidFlags options]"
+ }
+
+ ####################################################################
+ #
+ # MegawidgetClass::cget --
+ #
+ # Implementation of 'cget' for megawidgets. Emulates the operation of
+ # the standard Tk cget method fairly closely.
+ #
+ # This method assumes that the 'options' array in the class holds all
+ # options; it is up to subclasses to set traces on that array if they
+ # want to respond to configuration reads.
+ #
+ # TODO: allow unambiguous abbreviations.
+ #
+ method cget option {
+ return $options($option)
+ }
+
+ ####################################################################
+ #
+ # MegawidgetClass::TraceOption --
+ #
+ # Sets up the tracing of an element of the options variable.
+ #
+ method TraceOption {option method args} {
+ set callback [list my $method {*}$args]
+ trace add variable options($option) write [namespace code $callback]
+ }
+
+ ####################################################################
+ #
+ # MegawidgetClass::GetSpecs --
+ #
+ # Return a list of descriptions of options supported by this
+ # megawidget. Each option is described by the 4-tuple list, consisting
+ # of the name of the option, the "option database" name, the "option
+ # database" class-name, and the default value of the option. These are
+ # the same values returned by calling the configure method of a widget,
+ # except without the current values of the options.
+ #
+ method GetSpecs {} {
+ return {
+ {-takefocus takeFocus TakeFocus {}}
+ }
+ }
+
+ ####################################################################
+ #
+ # MegawidgetClass::CreateHull --
+ #
+ # Creates the real main widget of the megawidget. This is often a frame
+ # or toplevel widget, but isn't always (lightweight megawidgets might
+ # use a content widget directly).
+ #
+ # The name of the hull widget is given by the 'w' instance variable. The
+ # name should be written into the 'hull' instance variable. The command
+ # created by this method will be renamed.
+ #
+ method CreateHull {} {
+ return -code error -errorcode {TCL OO ABSTRACT_METHOD} \
+ "method must be overridden"
+ }
+
+ ####################################################################
+ #
+ # MegawidgetClass::Create --
+ #
+ # Creates the content of the megawidget. The name of the widget to
+ # create the content in will be in the 'hull' instance variable.
+ #
+ method Create {} {
+ return -code error -errorcode {TCL OO ABSTRACT_METHOD} \
+ "method must be overridden"
+ }
+
+ ####################################################################
+ #
+ # MegawidgetClass::WhenIdle --
+ #
+ # Arrange for a method to be called on the current instance when Tk is
+ # idle. Only one such method call per method will be queued; subsequent
+ # queuing actions before the callback fires will be silently ignored.
+ # The additional args will be passed to the callback, and the callbacks
+ # will be properly cancelled if the widget is destroyed.
+ #
+ method WhenIdle {method args} {
+ if {![info exists IdleCallbacks($method)]} {
+ set IdleCallbacks($method) [after idle [list \
+ [namespace which my] DoWhenIdle $method $args]]
+ }
+ }
+ method DoWhenIdle {method arguments} {
+ unset IdleCallbacks($method)
+ tailcall my $method {*}$arguments
+ }
+}
+
+####################################################################
+#
+# tk::SimpleWidget --
+#
+# Simple megawidget class that makes it easy create widgets that behave
+# like a ttk widget. It creates the hull as a ttk::frame and maps the
+# state manipulation methods of the overall megawidget to the equivalent
+# operations on the ttk::frame.
+#
+::tk::Megawidget create ::tk::SimpleWidget {} {
+ variable w hull options
+ method GetSpecs {} {
+ return {
+ {-cursor cursor Cursor {}}
+ {-takefocus takeFocus TakeFocus {}}
+ }
+ }
+ method CreateHull {} {
+ set hull [::ttk::frame $w -cursor $options(-cursor)]
+ my TraceOption -cursor UpdateCursorOption
+ }
+ method UpdateCursorOption args {
+ $hull configure -cursor $options(-cursor)
+ }
+ # Not fixed names, so can't forward
+ method state args {
+ tailcall $hull state {*}$args
+ }
+ method instate args {
+ tailcall $hull instate {*}$args
+ }
+}
+
+####################################################################
+#
+# tk::FocusableWidget --
+#
+# Simple megawidget class that makes a ttk-like widget that has a focus
+# ring.
+#
+::tk::Megawidget create ::tk::FocusableWidget ::tk::SimpleWidget {
+ variable w hull options
+ method GetSpecs {} {
+ return {
+ {-cursor cursor Cursor {}}
+ {-takefocus takeFocus TakeFocus ::ttk::takefocus}
+ }
+ }
+ method CreateHull {} {
+ ttk::frame $w
+ set hull [ttk::entry $w.cHull -takefocus 0 -cursor $options(-cursor)]
+ pack $hull -expand yes -fill both -ipadx 2 -ipady 2
+ my TraceOption -cursor UpdateCursorOption
+ }
+}
+
+return
+
+# Local Variables:
+# mode: tcl
+# fill-column: 78
+# End:
diff --git a/tk8.6/library/menu.tcl b/tk8.6/library/menu.tcl
new file mode 100644
index 0000000..9d6370a
--- /dev/null
+++ b/tk8.6/library/menu.tcl
@@ -0,0 +1,1379 @@
+# menu.tcl --
+#
+# This file defines the default bindings for Tk menus and menubuttons.
+# It also implements keyboard traversal of menus and implements a few
+# other utility procedures related to menus.
+#
+# Copyright (c) 1992-1994 The Regents of the University of California.
+# Copyright (c) 1994-1997 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+
+#-------------------------------------------------------------------------
+# Elements of tk::Priv that are used in this file:
+#
+# cursor - Saves the -cursor option for the posted menubutton.
+# focus - Saves the focus during a menu selection operation.
+# Focus gets restored here when the menu is unposted.
+# grabGlobal - Used in conjunction with tk::Priv(oldGrab): if
+# tk::Priv(oldGrab) is non-empty, then tk::Priv(grabGlobal)
+# contains either an empty string or "-global" to
+# indicate whether the old grab was a local one or
+# a global one.
+# inMenubutton - The name of the menubutton widget containing
+# the mouse, or an empty string if the mouse is
+# not over any menubutton.
+# menuBar - The name of the menubar that is the root
+# of the cascade hierarchy which is currently
+# posted. This is null when there is no menu currently
+# being pulled down from a menu bar.
+# oldGrab - Window that had the grab before a menu was posted.
+# Used to restore the grab state after the menu
+# is unposted. Empty string means there was no
+# grab previously set.
+# popup - If a menu has been popped up via tk_popup, this
+# gives the name of the menu. Otherwise this
+# value is empty.
+# postedMb - Name of the menubutton whose menu is currently
+# posted, or an empty string if nothing is posted
+# A grab is set on this widget.
+# relief - Used to save the original relief of the current
+# menubutton.
+# window - When the mouse is over a menu, this holds the
+# name of the menu; it's cleared when the mouse
+# leaves the menu.
+# tearoff - Whether the last menu posted was a tearoff or not.
+# This is true always for unix, for tearoffs for Mac
+# and Windows.
+# activeMenu - This is the last active menu for use
+# with the <<MenuSelect>> virtual event.
+# activeItem - This is the last active menu item for
+# use with the <<MenuSelect>> virtual event.
+#-------------------------------------------------------------------------
+
+#-------------------------------------------------------------------------
+# Overall note:
+# This file is tricky because there are five different ways that menus
+# can be used:
+#
+# 1. As a pulldown from a menubutton. In this style, the variable
+# tk::Priv(postedMb) identifies the posted menubutton.
+# 2. As a torn-off menu copied from some other menu. In this style
+# tk::Priv(postedMb) is empty, and menu's type is "tearoff".
+# 3. As an option menu, triggered from an option menubutton. In this
+# style tk::Priv(postedMb) identifies the posted menubutton.
+# 4. As a popup menu. In this style tk::Priv(postedMb) is empty and
+# the top-level menu's type is "normal".
+# 5. As a pulldown from a menubar. The variable tk::Priv(menubar) has
+# the owning menubar, and the menu itself is of type "normal".
+#
+# The various binding procedures use the state described above to
+# distinguish the various cases and take different actions in each
+# case.
+#-------------------------------------------------------------------------
+
+#-------------------------------------------------------------------------
+# The code below creates the default class bindings for menus
+# and menubuttons.
+#-------------------------------------------------------------------------
+
+bind Menubutton <FocusIn> {}
+bind Menubutton <Enter> {
+ tk::MbEnter %W
+}
+bind Menubutton <Leave> {
+ tk::MbLeave %W
+}
+bind Menubutton <1> {
+ if {$tk::Priv(inMenubutton) ne ""} {
+ tk::MbPost $tk::Priv(inMenubutton) %X %Y
+ }
+}
+bind Menubutton <Motion> {
+ tk::MbMotion %W up %X %Y
+}
+bind Menubutton <B1-Motion> {
+ tk::MbMotion %W down %X %Y
+}
+bind Menubutton <ButtonRelease-1> {
+ tk::MbButtonUp %W
+}
+bind Menubutton <space> {
+ tk::MbPost %W
+ tk::MenuFirstEntry [%W cget -menu]
+}
+bind Menubutton <<Invoke>> {
+ tk::MbPost %W
+ tk::MenuFirstEntry [%W cget -menu]
+}
+
+# Must set focus when mouse enters a menu, in order to allow
+# mixed-mode processing using both the mouse and the keyboard.
+# Don't set the focus if the event comes from a grab release,
+# though: such an event can happen after as part of unposting
+# a cascaded chain of menus, after the focus has already been
+# restored to wherever it was before menu selection started.
+
+bind Menu <FocusIn> {}
+
+bind Menu <Enter> {
+ set tk::Priv(window) %W
+ if {[%W cget -type] eq "tearoff"} {
+ if {"%m" ne "NotifyUngrab"} {
+ if {[tk windowingsystem] eq "x11"} {
+ tk_menuSetFocus %W
+ }
+ }
+ }
+ tk::MenuMotion %W %x %y %s
+}
+
+bind Menu <Leave> {
+ tk::MenuLeave %W %X %Y %s
+}
+bind Menu <Motion> {
+ tk::MenuMotion %W %x %y %s
+}
+bind Menu <ButtonPress> {
+ tk::MenuButtonDown %W
+}
+bind Menu <ButtonRelease> {
+ tk::MenuInvoke %W 1
+}
+bind Menu <space> {
+ tk::MenuInvoke %W 0
+}
+bind Menu <<Invoke>> {
+ tk::MenuInvoke %W 0
+}
+bind Menu <Return> {
+ tk::MenuInvoke %W 0
+}
+bind Menu <Escape> {
+ tk::MenuEscape %W
+}
+bind Menu <<PrevChar>> {
+ tk::MenuLeftArrow %W
+}
+bind Menu <<NextChar>> {
+ tk::MenuRightArrow %W
+}
+bind Menu <<PrevLine>> {
+ tk::MenuUpArrow %W
+}
+bind Menu <<NextLine>> {
+ tk::MenuDownArrow %W
+}
+bind Menu <KeyPress> {
+ tk::TraverseWithinMenu %W %A
+ break
+}
+
+# The following bindings apply to all windows, and are used to
+# implement keyboard menu traversal.
+
+if {[tk windowingsystem] eq "x11"} {
+ bind all <Alt-KeyPress> {
+ tk::TraverseToMenu %W %A
+ }
+
+ bind all <F10> {
+ tk::FirstMenu %W
+ }
+} else {
+ bind Menubutton <Alt-KeyPress> {
+ tk::TraverseToMenu %W %A
+ }
+
+ bind Menubutton <F10> {
+ tk::FirstMenu %W
+ }
+}
+
+# ::tk::MbEnter --
+# This procedure is invoked when the mouse enters a menubutton
+# widget. It activates the widget unless it is disabled. Note:
+# this procedure is only invoked when mouse button 1 is *not* down.
+# The procedure ::tk::MbB1Enter is invoked if the button is down.
+#
+# Arguments:
+# w - The name of the widget.
+
+proc ::tk::MbEnter w {
+ variable ::tk::Priv
+
+ if {$Priv(inMenubutton) ne ""} {
+ MbLeave $Priv(inMenubutton)
+ }
+ set Priv(inMenubutton) $w
+ if {[$w cget -state] ne "disabled" && [tk windowingsystem] ne "aqua"} {
+ $w configure -state active
+ }
+}
+
+# ::tk::MbLeave --
+# This procedure is invoked when the mouse leaves a menubutton widget.
+# It de-activates the widget, if the widget still exists.
+#
+# Arguments:
+# w - The name of the widget.
+
+proc ::tk::MbLeave w {
+ variable ::tk::Priv
+
+ set Priv(inMenubutton) {}
+ if {![winfo exists $w]} {
+ return
+ }
+ if {[$w cget -state] eq "active" && [tk windowingsystem] ne "aqua"} {
+ $w configure -state normal
+ }
+}
+
+
+# ::tk::MbPost --
+# Given a menubutton, this procedure does all the work of posting
+# its associated menu and unposting any other menu that is currently
+# posted.
+#
+# Arguments:
+# w - The name of the menubutton widget whose menu
+# is to be posted.
+# x, y - Root coordinates of cursor, used for positioning
+# option menus. If not specified, then the center
+# of the menubutton is used for an option menu.
+
+proc ::tk::MbPost {w {x {}} {y {}}} {
+ global errorInfo
+ variable ::tk::Priv
+
+ if {[$w cget -state] eq "disabled" || $w eq $Priv(postedMb)} {
+ return
+ }
+ set menu [$w cget -menu]
+ if {$menu eq ""} {
+ return
+ }
+ set tearoff [expr {[tk windowingsystem] eq "x11" \
+ || [$menu cget -type] eq "tearoff"}]
+ if {[string first $w $menu] != 0} {
+ return -code error -errorcode {TK MENUBUTTON POST_NONCHILD} \
+ "can't post $menu: it isn't a descendant of $w"
+ }
+ set cur $Priv(postedMb)
+ if {$cur ne ""} {
+ MenuUnpost {}
+ }
+ if {$::tk_strictMotif} {
+ set Priv(cursor) [$w cget -cursor]
+ $w configure -cursor arrow
+ }
+ if {[tk windowingsystem] ne "aqua"} {
+ set Priv(relief) [$w cget -relief]
+ $w configure -relief raised
+ } else {
+ $w configure -state active
+ }
+
+ set Priv(postedMb) $w
+ set Priv(focus) [focus]
+ $menu activate none
+ GenerateMenuSelect $menu
+ update idletasks
+
+ if {[catch {PostMenubuttonMenu $w $menu} msg opt]} {
+ # Error posting menu (e.g. bogus -postcommand). Unpost it and
+ # reflect the error.
+ MenuUnpost {}
+ return -options $opt $msg
+ }
+
+ set Priv(tearoff) $tearoff
+ if {$tearoff != 0 && [tk windowingsystem] ne "aqua"} {
+ focus $menu
+ if {[winfo viewable $w]} {
+ SaveGrabInfo $w
+ grab -global $w
+ }
+ }
+}
+
+# ::tk::MenuUnpost --
+# This procedure unposts a given menu, plus all of its ancestors up
+# to (and including) a menubutton, if any. It also restores various
+# values to what they were before the menu was posted, and releases
+# a grab if there's a menubutton involved. Special notes:
+# 1. It's important to unpost all menus before releasing the grab, so
+# that any Enter-Leave events (e.g. from menu back to main
+# application) have mode NotifyGrab.
+# 2. Be sure to enclose various groups of commands in "catch" so that
+# the procedure will complete even if the menubutton or the menu
+# or the grab window has been deleted.
+#
+# Arguments:
+# menu - Name of a menu to unpost. Ignored if there
+# is a posted menubutton.
+
+proc ::tk::MenuUnpost menu {
+ variable ::tk::Priv
+ set mb $Priv(postedMb)
+
+ # Restore focus right away (otherwise X will take focus away when
+ # the menu is unmapped and under some window managers (e.g. olvwm)
+ # we'll lose the focus completely).
+
+ catch {focus $Priv(focus)}
+ set Priv(focus) ""
+
+ # Unpost menu(s) and restore some stuff that's dependent on
+ # what was posted.
+
+ after cancel [array get Priv menuActivatedTimer]
+ unset -nocomplain Priv(menuActivated)
+ after cancel [array get Priv menuDeactivatedTimer]
+ unset -nocomplain Priv(menuDeactivated)
+
+ catch {
+ if {$mb ne ""} {
+ set menu [$mb cget -menu]
+ $menu unpost
+ set Priv(postedMb) {}
+ if {$::tk_strictMotif} {
+ $mb configure -cursor $Priv(cursor)
+ }
+ if {[tk windowingsystem] ne "aqua"} {
+ $mb configure -relief $Priv(relief)
+ } else {
+ $mb configure -state normal
+ }
+ } elseif {$Priv(popup) ne ""} {
+ $Priv(popup) unpost
+ set Priv(popup) {}
+ } elseif {[$menu cget -type] ne "menubar" && [$menu cget -type] ne "tearoff"} {
+ # We're in a cascaded sub-menu from a torn-off menu or popup.
+ # Unpost all the menus up to the toplevel one (but not
+ # including the top-level torn-off one) and deactivate the
+ # top-level torn off menu if there is one.
+
+ while {1} {
+ set parent [winfo parent $menu]
+ if {[winfo class $parent] ne "Menu" || ![winfo ismapped $parent]} {
+ break
+ }
+ $parent activate none
+ $parent postcascade none
+ GenerateMenuSelect $parent
+ set type [$parent cget -type]
+ if {$type eq "menubar" || $type eq "tearoff"} {
+ break
+ }
+ set menu $parent
+ }
+ if {[$menu cget -type] ne "menubar"} {
+ $menu unpost
+ }
+ }
+ }
+
+ if {($Priv(tearoff) != 0) || $Priv(menuBar) ne ""} {
+ # Release grab, if any, and restore the previous grab, if there
+ # was one.
+ if {$menu ne ""} {
+ set grab [grab current $menu]
+ if {$grab ne ""} {
+ grab release $grab
+ }
+ }
+ RestoreOldGrab
+ if {$Priv(menuBar) ne ""} {
+ if {$::tk_strictMotif} {
+ $Priv(menuBar) configure -cursor $Priv(cursor)
+ }
+ set Priv(menuBar) {}
+ }
+ if {[tk windowingsystem] ne "x11"} {
+ set Priv(tearoff) 0
+ }
+ }
+}
+
+# ::tk::MbMotion --
+# This procedure handles mouse motion events inside menubuttons, and
+# also outside menubuttons when a menubutton has a grab (e.g. when a
+# menu selection operation is in progress).
+#
+# Arguments:
+# w - The name of the menubutton widget.
+# upDown - "down" means button 1 is pressed, "up" means
+# it isn't.
+# rootx, rooty - Coordinates of mouse, in (virtual?) root window.
+
+proc ::tk::MbMotion {w upDown rootx rooty} {
+ variable ::tk::Priv
+
+ if {$Priv(inMenubutton) eq $w} {
+ return
+ }
+ set new [winfo containing $rootx $rooty]
+ if {$new ne $Priv(inMenubutton) \
+ && ($new eq "" || [winfo toplevel $new] eq [winfo toplevel $w])} {
+ if {$Priv(inMenubutton) ne ""} {
+ MbLeave $Priv(inMenubutton)
+ }
+ if {$new ne "" \
+ && [winfo class $new] eq "Menubutton" \
+ && ([$new cget -indicatoron] == 0) \
+ && ([$w cget -indicatoron] == 0)} {
+ if {$upDown eq "down"} {
+ MbPost $new $rootx $rooty
+ } else {
+ MbEnter $new
+ }
+ }
+ }
+}
+
+# ::tk::MbButtonUp --
+# This procedure is invoked to handle button 1 releases for menubuttons.
+# If the release happens inside the menubutton then leave its menu
+# posted with element 0 activated. Otherwise, unpost the menu.
+#
+# Arguments:
+# w - The name of the menubutton widget.
+
+proc ::tk::MbButtonUp w {
+ variable ::tk::Priv
+
+ set menu [$w cget -menu]
+ set tearoff [expr {[tk windowingsystem] eq "x11" || \
+ ($menu ne "" && [$menu cget -type] eq "tearoff")}]
+ if {($tearoff != 0) && $Priv(postedMb) eq $w \
+ && $Priv(inMenubutton) eq $w} {
+ MenuFirstEntry [$Priv(postedMb) cget -menu]
+ } else {
+ MenuUnpost {}
+ }
+}
+
+# ::tk::MenuMotion --
+# This procedure is called to handle mouse motion events for menus.
+# It does two things. First, it resets the active element in the
+# menu, if the mouse is over the menu. Second, if a mouse button
+# is down, it posts and unposts cascade entries to match the mouse
+# position.
+#
+# Arguments:
+# menu - The menu window.
+# x - The x position of the mouse.
+# y - The y position of the mouse.
+# state - Modifier state (tells whether buttons are down).
+
+proc ::tk::MenuMotion {menu x y state} {
+ variable ::tk::Priv
+ if {$menu eq $Priv(window)} {
+ set activeindex [$menu index active]
+ if {[$menu cget -type] eq "menubar"} {
+ if {[info exists Priv(focus)] && $menu ne $Priv(focus)} {
+ $menu activate @$x,$y
+ GenerateMenuSelect $menu
+ }
+ } else {
+ $menu activate @$x,$y
+ GenerateMenuSelect $menu
+ }
+ set index [$menu index @$x,$y]
+ if {[info exists Priv(menuActivated)] \
+ && $index ne "none" \
+ && $index ne $activeindex} {
+ set mode [option get $menu clickToFocus ClickToFocus]
+ if {[string is false $mode]} {
+ set delay [expr {[$menu cget -type] eq "menubar" ? 0 : 50}]
+ if {[$menu type $index] eq "cascade"} {
+ # Catch these postcascade commands since the menu could be
+ # destroyed before they run.
+ set Priv(menuActivatedTimer) \
+ [after $delay "catch {$menu postcascade active}"]
+ } else {
+ set Priv(menuDeactivatedTimer) \
+ [after $delay "catch {$menu postcascade none}"]
+ }
+ }
+ }
+ }
+}
+
+# ::tk::MenuButtonDown --
+# Handles button presses in menus. There are a couple of tricky things
+# here:
+# 1. Change the posted cascade entry (if any) to match the mouse position.
+# 2. If there is a posted menubutton, must grab to the menubutton; this
+# overrrides the implicit grab on button press, so that the menu
+# button can track mouse motions over other menubuttons and change
+# the posted menu.
+# 3. If there's no posted menubutton (e.g. because we're a torn-off menu
+# or one of its descendants) must grab to the top-level menu so that
+# we can track mouse motions across the entire menu hierarchy.
+#
+# Arguments:
+# menu - The menu window.
+
+proc ::tk::MenuButtonDown menu {
+ variable ::tk::Priv
+
+ if {![winfo viewable $menu]} {
+ return
+ }
+ if {[$menu index active] eq "none"} {
+ if {[$menu cget -type] ne "menubar" } {
+ set Priv(window) {}
+ }
+ return
+ }
+ $menu postcascade active
+ if {$Priv(postedMb) ne "" && [winfo viewable $Priv(postedMb)]} {
+ grab -global $Priv(postedMb)
+ } else {
+ while {[$menu cget -type] eq "normal" \
+ && [winfo class [winfo parent $menu]] eq "Menu" \
+ && [winfo ismapped [winfo parent $menu]]} {
+ set menu [winfo parent $menu]
+ }
+
+ if {$Priv(menuBar) eq {}} {
+ set Priv(menuBar) $menu
+ if {$::tk_strictMotif} {
+ set Priv(cursor) [$menu cget -cursor]
+ $menu configure -cursor arrow
+ }
+ if {[$menu type active] eq "cascade"} {
+ set Priv(menuActivated) 1
+ }
+ }
+
+ # Don't update grab information if the grab window isn't changing.
+ # Otherwise, we'll get an error when we unpost the menus and
+ # restore the grab, since the old grab window will not be viewable
+ # anymore.
+
+ if {$menu ne [grab current $menu]} {
+ SaveGrabInfo $menu
+ }
+
+ # Must re-grab even if the grab window hasn't changed, in order
+ # to release the implicit grab from the button press.
+
+ if {[tk windowingsystem] eq "x11"} {
+ grab -global $menu
+ }
+ }
+}
+
+# ::tk::MenuLeave --
+# This procedure is invoked to handle Leave events for a menu. It
+# deactivates everything unless the active element is a cascade element
+# and the mouse is now over the submenu.
+#
+# Arguments:
+# menu - The menu window.
+# rootx, rooty - Root coordinates of mouse.
+# state - Modifier state.
+
+proc ::tk::MenuLeave {menu rootx rooty state} {
+ variable ::tk::Priv
+ set Priv(window) {}
+ if {[$menu index active] eq "none"} {
+ return
+ }
+ if {[$menu type active] eq "cascade" \
+ && [winfo containing $rootx $rooty] eq \
+ [$menu entrycget active -menu]} {
+ return
+ }
+ $menu activate none
+ GenerateMenuSelect $menu
+}
+
+# ::tk::MenuInvoke --
+# This procedure is invoked when button 1 is released over a menu.
+# It invokes the appropriate menu action and unposts the menu if
+# it came from a menubutton.
+#
+# Arguments:
+# w - Name of the menu widget.
+# buttonRelease - 1 means this procedure is called because of
+# a button release; 0 means because of keystroke.
+
+proc ::tk::MenuInvoke {w buttonRelease} {
+ variable ::tk::Priv
+
+ if {$buttonRelease && $Priv(window) eq ""} {
+ # Mouse was pressed over a menu without a menu button, then
+ # dragged off the menu (possibly with a cascade posted) and
+ # released. Unpost everything and quit.
+
+ $w postcascade none
+ $w activate none
+ event generate $w <<MenuSelect>>
+ MenuUnpost $w
+ return
+ }
+ if {[$w type active] eq "cascade"} {
+ $w postcascade active
+ set menu [$w entrycget active -menu]
+ MenuFirstEntry $menu
+ } elseif {[$w type active] eq "tearoff"} {
+ ::tk::TearOffMenu $w
+ MenuUnpost $w
+ } elseif {[$w cget -type] eq "menubar"} {
+ $w postcascade none
+ set active [$w index active]
+ set isCascade [string equal [$w type $active] "cascade"]
+
+ # Only de-activate the active item if it's a cascade; this prevents
+ # the annoying "activation flicker" you otherwise get with
+ # checkbuttons/commands/etc. on menubars
+
+ if { $isCascade } {
+ $w activate none
+ event generate $w <<MenuSelect>>
+ }
+
+ MenuUnpost $w
+
+ # If the active item is not a cascade, invoke it. This enables
+ # the use of checkbuttons/commands/etc. on menubars (which is legal,
+ # but not recommended)
+
+ if { !$isCascade } {
+ uplevel #0 [list $w invoke $active]
+ }
+ } else {
+ set active [$w index active]
+ if {$Priv(popup) eq "" || $active ne "none"} {
+ MenuUnpost $w
+ }
+ uplevel #0 [list $w invoke active]
+ }
+}
+
+# ::tk::MenuEscape --
+# This procedure is invoked for the Cancel (or Escape) key. It unposts
+# the given menu and, if it is the top-level menu for a menu button,
+# unposts the menu button as well.
+#
+# Arguments:
+# menu - Name of the menu window.
+
+proc ::tk::MenuEscape menu {
+ set parent [winfo parent $menu]
+ if {[winfo class $parent] ne "Menu"} {
+ MenuUnpost $menu
+ } elseif {[$parent cget -type] eq "menubar"} {
+ MenuUnpost $menu
+ RestoreOldGrab
+ } else {
+ MenuNextMenu $menu left
+ }
+}
+
+# The following routines handle arrow keys. Arrow keys behave
+# differently depending on whether the menu is a menu bar or not.
+
+proc ::tk::MenuUpArrow {menu} {
+ if {[$menu cget -type] eq "menubar"} {
+ MenuNextMenu $menu left
+ } else {
+ MenuNextEntry $menu -1
+ }
+}
+
+proc ::tk::MenuDownArrow {menu} {
+ if {[$menu cget -type] eq "menubar"} {
+ MenuNextMenu $menu right
+ } else {
+ MenuNextEntry $menu 1
+ }
+}
+
+proc ::tk::MenuLeftArrow {menu} {
+ if {[$menu cget -type] eq "menubar"} {
+ MenuNextEntry $menu -1
+ } else {
+ MenuNextMenu $menu left
+ }
+}
+
+proc ::tk::MenuRightArrow {menu} {
+ if {[$menu cget -type] eq "menubar"} {
+ MenuNextEntry $menu 1
+ } else {
+ MenuNextMenu $menu right
+ }
+}
+
+# ::tk::MenuNextMenu --
+# This procedure is invoked to handle "left" and "right" traversal
+# motions in menus. It traverses to the next menu in a menu bar,
+# or into or out of a cascaded menu.
+#
+# Arguments:
+# menu - The menu that received the keyboard
+# event.
+# direction - Direction in which to move: "left" or "right"
+
+proc ::tk::MenuNextMenu {menu direction} {
+ variable ::tk::Priv
+
+ # First handle traversals into and out of cascaded menus.
+
+ if {$direction eq "right"} {
+ set count 1
+ set parent [winfo parent $menu]
+ set class [winfo class $parent]
+ if {[$menu type active] eq "cascade"} {
+ $menu postcascade active
+ set m2 [$menu entrycget active -menu]
+ if {$m2 ne ""} {
+ MenuFirstEntry $m2
+ }
+ return
+ } else {
+ set parent [winfo parent $menu]
+ while {$parent ne "."} {
+ if {[winfo class $parent] eq "Menu" \
+ && [$parent cget -type] eq "menubar"} {
+ tk_menuSetFocus $parent
+ MenuNextEntry $parent 1
+ return
+ }
+ set parent [winfo parent $parent]
+ }
+ }
+ } else {
+ set count -1
+ set m2 [winfo parent $menu]
+ if {[winfo class $m2] eq "Menu"} {
+ $menu activate none
+ GenerateMenuSelect $menu
+ tk_menuSetFocus $m2
+
+ $m2 postcascade none
+
+ if {[$m2 cget -type] ne "menubar"} {
+ return
+ }
+ }
+ }
+
+ # Can't traverse into or out of a cascaded menu. Go to the next
+ # or previous menubutton, if that makes sense.
+
+ set m2 [winfo parent $menu]
+ if {[winfo class $m2] eq "Menu" && [$m2 cget -type] eq "menubar"} {
+ tk_menuSetFocus $m2
+ MenuNextEntry $m2 -1
+ return
+ }
+
+ set w $Priv(postedMb)
+ if {$w eq ""} {
+ return
+ }
+ set buttons [winfo children [winfo parent $w]]
+ set length [llength $buttons]
+ set i [expr {[lsearch -exact $buttons $w] + $count}]
+ while {1} {
+ while {$i < 0} {
+ incr i $length
+ }
+ while {$i >= $length} {
+ incr i -$length
+ }
+ set mb [lindex $buttons $i]
+ if {[winfo class $mb] eq "Menubutton" \
+ && [$mb cget -state] ne "disabled" \
+ && [$mb cget -menu] ne "" \
+ && [[$mb cget -menu] index last] ne "none"} {
+ break
+ }
+ if {$mb eq $w} {
+ return
+ }
+ incr i $count
+ }
+ MbPost $mb
+ MenuFirstEntry [$mb cget -menu]
+}
+
+# ::tk::MenuNextEntry --
+# Activate the next higher or lower entry in the posted menu,
+# wrapping around at the ends. Disabled entries are skipped.
+#
+# Arguments:
+# menu - Menu window that received the keystroke.
+# count - 1 means go to the next lower entry,
+# -1 means go to the next higher entry.
+
+proc ::tk::MenuNextEntry {menu count} {
+ if {[$menu index last] eq "none"} {
+ return
+ }
+ set length [expr {[$menu index last]+1}]
+ set quitAfter $length
+ set active [$menu index active]
+ if {$active eq "none"} {
+ set i 0
+ } else {
+ set i [expr {$active + $count}]
+ }
+ while {1} {
+ if {$quitAfter <= 0} {
+ # We've tried every entry in the menu. Either there are
+ # none, or they're all disabled. Just give up.
+
+ return
+ }
+ while {$i < 0} {
+ incr i $length
+ }
+ while {$i >= $length} {
+ incr i -$length
+ }
+ if {[catch {$menu entrycget $i -state} state] == 0} {
+ if {$state ne "disabled" && \
+ ($i!=0 || [$menu cget -type] ne "tearoff" \
+ || [$menu type 0] ne "tearoff")} {
+ break
+ }
+ }
+ if {$i == $active} {
+ return
+ }
+ incr i $count
+ incr quitAfter -1
+ }
+ $menu activate $i
+ GenerateMenuSelect $menu
+
+ if {[$menu type $i] eq "cascade" && [$menu cget -type] eq "menubar"} {
+ set cascade [$menu entrycget $i -menu]
+ if {$cascade ne ""} {
+ # Here we auto-post a cascade. This is necessary when
+ # we traverse left/right in the menubar, but undesirable when
+ # we traverse up/down in a menu.
+ $menu postcascade $i
+ MenuFirstEntry $cascade
+ }
+ }
+}
+
+# ::tk::MenuFind --
+# This procedure searches the entire window hierarchy under w for
+# a menubutton that isn't disabled and whose underlined character
+# is "char" or an entry in a menubar that isn't disabled and whose
+# underlined character is "char".
+# It returns the name of that window, if found, or an
+# empty string if no matching window was found. If "char" is an
+# empty string then the procedure returns the name of the first
+# menubutton found that isn't disabled.
+#
+# Arguments:
+# w - Name of window where key was typed.
+# char - Underlined character to search for;
+# may be either upper or lower case, and
+# will match either upper or lower case.
+
+proc ::tk::MenuFind {w char} {
+ set char [string tolower $char]
+ set windowlist [winfo child $w]
+
+ foreach child $windowlist {
+ # Don't descend into other toplevels.
+ if {[winfo toplevel $w] ne [winfo toplevel $child]} {
+ continue
+ }
+ if {[winfo class $child] eq "Menu" && \
+ [$child cget -type] eq "menubar"} {
+ if {$char eq ""} {
+ return $child
+ }
+ set last [$child index last]
+ for {set i [$child cget -tearoff]} {$i <= $last} {incr i} {
+ if {[$child type $i] eq "separator"} {
+ continue
+ }
+ set char2 [string index [$child entrycget $i -label] \
+ [$child entrycget $i -underline]]
+ if {$char eq [string tolower $char2] || $char eq ""} {
+ if {[$child entrycget $i -state] ne "disabled"} {
+ return $child
+ }
+ }
+ }
+ }
+ }
+
+ foreach child $windowlist {
+ # Don't descend into other toplevels.
+ if {[winfo toplevel $w] ne [winfo toplevel $child]} {
+ continue
+ }
+ switch -- [winfo class $child] {
+ Menubutton {
+ set char2 [string index [$child cget -text] \
+ [$child cget -underline]]
+ if {$char eq [string tolower $char2] || $char eq ""} {
+ if {[$child cget -state] ne "disabled"} {
+ return $child
+ }
+ }
+ }
+
+ default {
+ set match [MenuFind $child $char]
+ if {$match ne ""} {
+ return $match
+ }
+ }
+ }
+ }
+ return {}
+}
+
+# ::tk::TraverseToMenu --
+# This procedure implements keyboard traversal of menus. Given an
+# ASCII character "char", it looks for a menubutton with that character
+# underlined. If one is found, it posts the menubutton's menu
+#
+# Arguments:
+# w - Window in which the key was typed (selects
+# a toplevel window).
+# char - Character that selects a menu. The case
+# is ignored. If an empty string, nothing
+# happens.
+
+proc ::tk::TraverseToMenu {w char} {
+ variable ::tk::Priv
+ if {![winfo exists $w] || $char eq ""} {
+ return
+ }
+ while {[winfo class $w] eq "Menu"} {
+ if {[$w cget -type] eq "menubar"} {
+ break
+ } elseif {$Priv(postedMb) eq ""} {
+ return
+ }
+ set w [winfo parent $w]
+ }
+ set w [MenuFind [winfo toplevel $w] $char]
+ if {$w ne ""} {
+ if {[winfo class $w] eq "Menu"} {
+ tk_menuSetFocus $w
+ set Priv(window) $w
+ SaveGrabInfo $w
+ grab -global $w
+ TraverseWithinMenu $w $char
+ } else {
+ MbPost $w
+ MenuFirstEntry [$w cget -menu]
+ }
+ }
+}
+
+# ::tk::FirstMenu --
+# This procedure traverses to the first menubutton in the toplevel
+# for a given window, and posts that menubutton's menu.
+#
+# Arguments:
+# w - Name of a window. Selects which toplevel
+# to search for menubuttons.
+
+proc ::tk::FirstMenu w {
+ variable ::tk::Priv
+ set w [MenuFind [winfo toplevel $w] ""]
+ if {$w ne ""} {
+ if {[winfo class $w] eq "Menu"} {
+ tk_menuSetFocus $w
+ set Priv(window) $w
+ SaveGrabInfo $w
+ grab -global $w
+ MenuFirstEntry $w
+ } else {
+ MbPost $w
+ MenuFirstEntry [$w cget -menu]
+ }
+ }
+}
+
+# ::tk::TraverseWithinMenu
+# This procedure implements keyboard traversal within a menu. It
+# searches for an entry in the menu that has "char" underlined. If
+# such an entry is found, it is invoked and the menu is unposted.
+#
+# Arguments:
+# w - The name of the menu widget.
+# char - The character to look for; case is
+# ignored. If the string is empty then
+# nothing happens.
+
+proc ::tk::TraverseWithinMenu {w char} {
+ if {$char eq ""} {
+ return
+ }
+ set char [string tolower $char]
+ set last [$w index last]
+ if {$last eq "none"} {
+ return
+ }
+ for {set i 0} {$i <= $last} {incr i} {
+ if {[catch {set char2 [string index \
+ [$w entrycget $i -label] [$w entrycget $i -underline]]}]} {
+ continue
+ }
+ if {$char eq [string tolower $char2]} {
+ if {[$w type $i] eq "cascade"} {
+ $w activate $i
+ $w postcascade active
+ event generate $w <<MenuSelect>>
+ set m2 [$w entrycget $i -menu]
+ if {$m2 ne ""} {
+ MenuFirstEntry $m2
+ }
+ } else {
+ MenuUnpost $w
+ uplevel #0 [list $w invoke $i]
+ }
+ return
+ }
+ }
+}
+
+# ::tk::MenuFirstEntry --
+# Given a menu, this procedure finds the first entry that isn't
+# disabled or a tear-off or separator, and activates that entry.
+# However, if there is already an active entry in the menu (e.g.,
+# because of a previous call to tk::PostOverPoint) then the active
+# entry isn't changed. This procedure also sets the input focus
+# to the menu.
+#
+# Arguments:
+# menu - Name of the menu window (possibly empty).
+
+proc ::tk::MenuFirstEntry menu {
+ if {$menu eq ""} {
+ return
+ }
+ tk_menuSetFocus $menu
+ if {[$menu index active] ne "none"} {
+ return
+ }
+ set last [$menu index last]
+ if {$last eq "none"} {
+ return
+ }
+ for {set i 0} {$i <= $last} {incr i} {
+ if {([catch {set state [$menu entrycget $i -state]}] == 0) \
+ && $state ne "disabled" && [$menu type $i] ne "tearoff"} {
+ $menu activate $i
+ GenerateMenuSelect $menu
+ # Only post the cascade if the current menu is a menubar;
+ # otherwise, if the first entry of the cascade is a cascade,
+ # we can get an annoying cascading effect resulting in a bunch of
+ # menus getting posted (bug 676)
+ if {[$menu type $i] eq "cascade" && [$menu cget -type] eq "menubar"} {
+ set cascade [$menu entrycget $i -menu]
+ if {$cascade ne ""} {
+ $menu postcascade $i
+ MenuFirstEntry $cascade
+ }
+ }
+ return
+ }
+ }
+}
+
+# ::tk::MenuFindName --
+# Given a menu and a text string, return the index of the menu entry
+# that displays the string as its label. If there is no such entry,
+# return an empty string. This procedure is tricky because some names
+# like "active" have a special meaning in menu commands, so we can't
+# always use the "index" widget command.
+#
+# Arguments:
+# menu - Name of the menu widget.
+# s - String to look for.
+
+proc ::tk::MenuFindName {menu s} {
+ set i ""
+ if {![regexp {^active$|^last$|^none$|^[0-9]|^@} $s]} {
+ catch {set i [$menu index $s]}
+ return $i
+ }
+ set last [$menu index last]
+ if {$last eq "none"} {
+ return
+ }
+ for {set i 0} {$i <= $last} {incr i} {
+ if {![catch {$menu entrycget $i -label} label]} {
+ if {$label eq $s} {
+ return $i
+ }
+ }
+ }
+ return ""
+}
+
+# ::tk::PostMenubuttonMenu --
+#
+# Given a menubutton and a menu, this procedure posts the menu at the
+# appropriate location. If the menubutton looks like an option
+# menubutton, meaning that the indicator is on and the direction is
+# neither above nor below, then the menu is posted so that the current
+# entry is vertically aligned with the menubutton. On the Mac this
+# will expose a small amount of the blue indicator on the right hand
+# side. On other platforms the entry is centered over the button.
+
+if {[tk windowingsystem] eq "aqua"} {
+ proc ::tk::PostMenubuttonMenu {button menu} {
+ set entry ""
+ if {[$button cget -indicatoron]} {
+ set entry [MenuFindName $menu [$button cget -text]]
+ if {$entry eq ""} {
+ set entry 0
+ }
+ }
+ set x [winfo rootx $button]
+ set y [expr {2 + [winfo rooty $button]}]
+ switch [$button cget -direction] {
+ above {
+ set entry ""
+ incr y [expr {4 - [winfo reqheight $menu]}]
+ }
+ below {
+ set entry ""
+ incr y [expr {2 + [winfo height $button]}]
+ }
+ left {
+ incr x [expr {-[winfo reqwidth $menu]}]
+ }
+ right {
+ incr x [winfo width $button]
+ }
+ default {
+ incr x [expr {[winfo width $button] - [winfo reqwidth $menu] - 5}]
+ }
+ }
+ PostOverPoint $menu $x $y $entry
+ }
+} else {
+ proc ::tk::PostMenubuttonMenu {button menu} {
+ set entry ""
+ if {[$button cget -indicatoron]} {
+ set entry [MenuFindName $menu [$button cget -text]]
+ if {$entry eq ""} {
+ set entry 0
+ }
+ }
+ set x [winfo rootx $button]
+ set y [winfo rooty $button]
+ switch [$button cget -direction] {
+ above {
+ incr y [expr {-[winfo reqheight $menu]}]
+ # if we go offscreen to the top, show as 'below'
+ if {$y < [winfo vrooty $button]} {
+ set y [expr {[winfo vrooty $button] + [winfo rooty $button]\
+ + [winfo reqheight $button]}]
+ }
+ set entry {}
+ }
+ below {
+ incr y [winfo height $button]
+ # if we go offscreen to the bottom, show as 'above'
+ set mh [winfo reqheight $menu]
+ if {($y + $mh) > ([winfo vrooty $button] + [winfo vrootheight $button])} {
+ set y [expr {[winfo vrooty $button] + [winfo vrootheight $button] \
+ + [winfo rooty $button] - $mh}]
+ }
+ set entry {}
+ }
+ left {
+ # It is not clear why this is needed.
+ if {[tk windowingsystem] eq "win32"} {
+ incr x [expr {-4 - [winfo reqwidth $button] / 2}]
+ }
+ incr x [expr {- [winfo reqwidth $menu]}]
+ }
+ right {
+ incr x [expr {[winfo width $button]}]
+ }
+ default {
+ if {[$button cget -indicatoron]} {
+ incr x [expr {([winfo width $button] - \
+ [winfo reqwidth $menu])/ 2}]
+ } else {
+ incr y [winfo height $button]
+ }
+ }
+ }
+ PostOverPoint $menu $x $y $entry
+ }
+}
+
+# ::tk::PostOverPoint --
+#
+# This procedure posts a menu on the screen so that a given entry in
+# the menu is positioned with its upper left corner at a given point
+# in the root window. The procedure also activates that entry. If no
+# entry is specified the upper left corner of the entire menu is
+# placed at the point.
+#
+# Arguments:
+# menu - Menu to post.
+# x, y - Root coordinates of point.
+# entry - Index of entry within menu to center over (x,y).
+# If omitted or specified as {}, then the menu's
+# upper-left corner goes at (x,y).
+
+if {[tk windowingsystem] ne "win32"} {
+ proc ::tk::PostOverPoint {menu x y {entry {}}} {
+ if {$entry ne ""} {
+ $menu post $x $y $entry
+ if {[$menu entrycget $entry -state] ne "disabled"} {
+ $menu activate $entry
+ GenerateMenuSelect $menu
+ }
+ } else {
+ $menu post $x $y
+ }
+ return
+ }
+} else {
+ proc ::tk::PostOverPoint {menu x y {entry {}}} {
+ if {$entry ne ""} {
+ incr y [expr {-[$menu yposition $entry]}]
+ }
+ # osVersion is not available in safe interps
+ set ver 5
+ if {[info exists ::tcl_platform(osVersion)]} {
+ scan $::tcl_platform(osVersion) %d ver
+ }
+
+ # We need to fix some problems with menu posting on Windows,
+ # where, if the menu would overlap top or bottom of screen,
+ # Windows puts it in the wrong place for us. We must also
+ # subtract an extra amount for half the height of the current
+ # entry. To be safe we subtract an extra 10.
+ # NOTE: this issue appears to have been resolved in the Window
+ # manager provided with Vista and Windows 7.
+ if {$ver < 6} {
+ set yoffset [expr {[winfo screenheight $menu] \
+ - $y - [winfo reqheight $menu] - 10}]
+ if {$yoffset < [winfo vrooty $menu]} {
+ # The bottom of the menu is offscreen, so adjust upwards
+ incr y [expr {$yoffset - [winfo vrooty $menu]}]
+ }
+ # If we're off the top of the screen (either because we were
+ # originally or because we just adjusted too far upwards),
+ # then make the menu popup on the top edge.
+ if {$y < [winfo vrooty $menu]} {
+ set y [winfo vrooty $menu]
+ }
+ }
+ $menu post $x $y
+ if {$entry ne "" && [$menu entrycget $entry -state] ne "disabled"} {
+ $menu activate $entry
+ GenerateMenuSelect $menu
+ }
+ }
+}
+
+# ::tk::SaveGrabInfo --
+# Sets the variables tk::Priv(oldGrab) and tk::Priv(grabStatus) to record
+# the state of any existing grab on the w's display.
+#
+# Arguments:
+# w - Name of a window; used to select the display
+# whose grab information is to be recorded.
+
+proc tk::SaveGrabInfo w {
+ variable ::tk::Priv
+ set Priv(oldGrab) [grab current $w]
+ if {$Priv(oldGrab) ne ""} {
+ set Priv(grabStatus) [grab status $Priv(oldGrab)]
+ }
+}
+
+# ::tk::RestoreOldGrab --
+# Restores the grab to what it was before TkSaveGrabInfo was called.
+#
+
+proc ::tk::RestoreOldGrab {} {
+ variable ::tk::Priv
+
+ if {$Priv(oldGrab) ne ""} {
+ # Be careful restoring the old grab, since it's window may not
+ # be visible anymore.
+
+ catch {
+ if {$Priv(grabStatus) eq "global"} {
+ grab set -global $Priv(oldGrab)
+ } else {
+ grab set $Priv(oldGrab)
+ }
+ }
+ set Priv(oldGrab) ""
+ }
+}
+
+proc ::tk_menuSetFocus {menu} {
+ variable ::tk::Priv
+ if {![info exists Priv(focus)] || $Priv(focus) eq ""} {
+ set Priv(focus) [focus]
+ }
+ focus $menu
+}
+
+proc ::tk::GenerateMenuSelect {menu} {
+ variable ::tk::Priv
+
+ if {$Priv(activeMenu) eq $menu \
+ && $Priv(activeItem) eq [$menu index active]} {
+ return
+ }
+
+ set Priv(activeMenu) $menu
+ set Priv(activeItem) [$menu index active]
+ event generate $menu <<MenuSelect>>
+}
+
+# ::tk_popup --
+# This procedure pops up a menu and sets things up for traversing
+# the menu and its submenus.
+#
+# Arguments:
+# menu - Name of the menu to be popped up.
+# x, y - Root coordinates at which to pop up the
+# menu.
+# entry - Index of a menu entry to center over (x,y).
+# If omitted or specified as {}, then menu's
+# upper-left corner goes at (x,y).
+
+proc ::tk_popup {menu x y {entry {}}} {
+ variable ::tk::Priv
+ if {$Priv(popup) ne "" || $Priv(postedMb) ne ""} {
+ tk::MenuUnpost {}
+ }
+ tk::PostOverPoint $menu $x $y $entry
+ if {[tk windowingsystem] eq "x11" && [winfo viewable $menu]} {
+ tk::SaveGrabInfo $menu
+ grab -global $menu
+ set Priv(popup) $menu
+ set Priv(window) $menu
+ set Priv(menuActivated) 1
+ tk_menuSetFocus $menu
+ }
+}
diff --git a/tk8.6/library/mkpsenc.tcl b/tk8.6/library/mkpsenc.tcl
new file mode 100644
index 0000000..b3fd13d
--- /dev/null
+++ b/tk8.6/library/mkpsenc.tcl
@@ -0,0 +1,1488 @@
+# mkpsenc.tcl --
+#
+# This file generates the postscript prolog used by Tk.
+
+namespace eval ::tk {
+ # Creates Postscript encoding vector for ISO-8859-1 (could theoretically
+ # handle any 8-bit encoding, but Tk never generates characters outside
+ # ASCII).
+ #
+ proc CreatePostscriptEncoding {} {
+ variable psglyphs
+ # Now check for known. Even if it is known, it can be other than we
+ # need. GhostScript seems to be happy with such approach
+ set result "\[\n"
+ for {set i 0} {$i<256} {incr i 8} {
+ for {set j 0} {$j<8} {incr j} {
+ set enc [encoding convertfrom "iso8859-1" \
+ [format %c [expr {$i+$j}]]]
+ catch {
+ set hexcode {}
+ set hexcode [format %04X [scan $enc %c]]
+ }
+ if {[info exists psglyphs($hexcode)]} {
+ append result "/$psglyphs($hexcode)"
+ } else {
+ append result "/space"
+ }
+ }
+ append result "\n"
+ }
+ append result "\]"
+ return $result
+ }
+
+ # List of adobe glyph names. Converted from glyphlist.txt, downloaded from
+ # Adobe.
+
+ variable psglyphs
+ array set psglyphs {
+ 0020 space
+ 0021 exclam
+ 0022 quotedbl
+ 0023 numbersign
+ 0024 dollar
+ 0025 percent
+ 0026 ampersand
+ 0027 quotesingle
+ 0028 parenleft
+ 0029 parenright
+ 002A asterisk
+ 002B plus
+ 002C comma
+ 002D hyphen
+ 002E period
+ 002F slash
+ 0030 zero
+ 0031 one
+ 0032 two
+ 0033 three
+ 0034 four
+ 0035 five
+ 0036 six
+ 0037 seven
+ 0038 eight
+ 0039 nine
+ 003A colon
+ 003B semicolon
+ 003C less
+ 003D equal
+ 003E greater
+ 003F question
+ 0040 at
+ 0041 A
+ 0042 B
+ 0043 C
+ 0044 D
+ 0045 E
+ 0046 F
+ 0047 G
+ 0048 H
+ 0049 I
+ 004A J
+ 004B K
+ 004C L
+ 004D M
+ 004E N
+ 004F O
+ 0050 P
+ 0051 Q
+ 0052 R
+ 0053 S
+ 0054 T
+ 0055 U
+ 0056 V
+ 0057 W
+ 0058 X
+ 0059 Y
+ 005A Z
+ 005B bracketleft
+ 005C backslash
+ 005D bracketright
+ 005E asciicircum
+ 005F underscore
+ 0060 grave
+ 0061 a
+ 0062 b
+ 0063 c
+ 0064 d
+ 0065 e
+ 0066 f
+ 0067 g
+ 0068 h
+ 0069 i
+ 006A j
+ 006B k
+ 006C l
+ 006D m
+ 006E n
+ 006F o
+ 0070 p
+ 0071 q
+ 0072 r
+ 0073 s
+ 0074 t
+ 0075 u
+ 0076 v
+ 0077 w
+ 0078 x
+ 0079 y
+ 007A z
+ 007B braceleft
+ 007C bar
+ 007D braceright
+ 007E asciitilde
+ 00A0 space
+ 00A1 exclamdown
+ 00A2 cent
+ 00A3 sterling
+ 00A4 currency
+ 00A5 yen
+ 00A6 brokenbar
+ 00A7 section
+ 00A8 dieresis
+ 00A9 copyright
+ 00AA ordfeminine
+ 00AB guillemotleft
+ 00AC logicalnot
+ 00AD hyphen
+ 00AE registered
+ 00AF macron
+ 00B0 degree
+ 00B1 plusminus
+ 00B2 twosuperior
+ 00B3 threesuperior
+ 00B4 acute
+ 00B5 mu
+ 00B6 paragraph
+ 00B7 periodcentered
+ 00B8 cedilla
+ 00B9 onesuperior
+ 00BA ordmasculine
+ 00BB guillemotright
+ 00BC onequarter
+ 00BD onehalf
+ 00BE threequarters
+ 00BF questiondown
+ 00C0 Agrave
+ 00C1 Aacute
+ 00C2 Acircumflex
+ 00C3 Atilde
+ 00C4 Adieresis
+ 00C5 Aring
+ 00C6 AE
+ 00C7 Ccedilla
+ 00C8 Egrave
+ 00C9 Eacute
+ 00CA Ecircumflex
+ 00CB Edieresis
+ 00CC Igrave
+ 00CD Iacute
+ 00CE Icircumflex
+ 00CF Idieresis
+ 00D0 Eth
+ 00D1 Ntilde
+ 00D2 Ograve
+ 00D3 Oacute
+ 00D4 Ocircumflex
+ 00D5 Otilde
+ 00D6 Odieresis
+ 00D7 multiply
+ 00D8 Oslash
+ 00D9 Ugrave
+ 00DA Uacute
+ 00DB Ucircumflex
+ 00DC Udieresis
+ 00DD Yacute
+ 00DE Thorn
+ 00DF germandbls
+ 00E0 agrave
+ 00E1 aacute
+ 00E2 acircumflex
+ 00E3 atilde
+ 00E4 adieresis
+ 00E5 aring
+ 00E6 ae
+ 00E7 ccedilla
+ 00E8 egrave
+ 00E9 eacute
+ 00EA ecircumflex
+ 00EB edieresis
+ 00EC igrave
+ 00ED iacute
+ 00EE icircumflex
+ 00EF idieresis
+ 00F0 eth
+ 00F1 ntilde
+ 00F2 ograve
+ 00F3 oacute
+ 00F4 ocircumflex
+ 00F5 otilde
+ 00F6 odieresis
+ 00F7 divide
+ 00F8 oslash
+ 00F9 ugrave
+ 00FA uacute
+ 00FB ucircumflex
+ 00FC udieresis
+ 00FD yacute
+ 00FE thorn
+ 00FF ydieresis
+ 0100 Amacron
+ 0101 amacron
+ 0102 Abreve
+ 0103 abreve
+ 0104 Aogonek
+ 0105 aogonek
+ 0106 Cacute
+ 0107 cacute
+ 0108 Ccircumflex
+ 0109 ccircumflex
+ 010A Cdotaccent
+ 010B cdotaccent
+ 010C Ccaron
+ 010D ccaron
+ 010E Dcaron
+ 010F dcaron
+ 0110 Dcroat
+ 0111 dcroat
+ 0112 Emacron
+ 0113 emacron
+ 0114 Ebreve
+ 0115 ebreve
+ 0116 Edotaccent
+ 0117 edotaccent
+ 0118 Eogonek
+ 0119 eogonek
+ 011A Ecaron
+ 011B ecaron
+ 011C Gcircumflex
+ 011D gcircumflex
+ 011E Gbreve
+ 011F gbreve
+ 0120 Gdotaccent
+ 0121 gdotaccent
+ 0122 Gcommaaccent
+ 0123 gcommaaccent
+ 0124 Hcircumflex
+ 0125 hcircumflex
+ 0126 Hbar
+ 0127 hbar
+ 0128 Itilde
+ 0129 itilde
+ 012A Imacron
+ 012B imacron
+ 012C Ibreve
+ 012D ibreve
+ 012E Iogonek
+ 012F iogonek
+ 0130 Idotaccent
+ 0131 dotlessi
+ 0132 IJ
+ 0133 ij
+ 0134 Jcircumflex
+ 0135 jcircumflex
+ 0136 Kcommaaccent
+ 0137 kcommaaccent
+ 0138 kgreenlandic
+ 0139 Lacute
+ 013A lacute
+ 013B Lcommaaccent
+ 013C lcommaaccent
+ 013D Lcaron
+ 013E lcaron
+ 013F Ldot
+ 0140 ldot
+ 0141 Lslash
+ 0142 lslash
+ 0143 Nacute
+ 0144 nacute
+ 0145 Ncommaaccent
+ 0146 ncommaaccent
+ 0147 Ncaron
+ 0148 ncaron
+ 0149 napostrophe
+ 014A Eng
+ 014B eng
+ 014C Omacron
+ 014D omacron
+ 014E Obreve
+ 014F obreve
+ 0150 Ohungarumlaut
+ 0151 ohungarumlaut
+ 0152 OE
+ 0153 oe
+ 0154 Racute
+ 0155 racute
+ 0156 Rcommaaccent
+ 0157 rcommaaccent
+ 0158 Rcaron
+ 0159 rcaron
+ 015A Sacute
+ 015B sacute
+ 015C Scircumflex
+ 015D scircumflex
+ 015E Scedilla
+ 015F scedilla
+ 0160 Scaron
+ 0161 scaron
+ 0162 Tcommaaccent
+ 0163 tcommaaccent
+ 0164 Tcaron
+ 0165 tcaron
+ 0166 Tbar
+ 0167 tbar
+ 0168 Utilde
+ 0169 utilde
+ 016A Umacron
+ 016B umacron
+ 016C Ubreve
+ 016D ubreve
+ 016E Uring
+ 016F uring
+ 0170 Uhungarumlaut
+ 0171 uhungarumlaut
+ 0172 Uogonek
+ 0173 uogonek
+ 0174 Wcircumflex
+ 0175 wcircumflex
+ 0176 Ycircumflex
+ 0177 ycircumflex
+ 0178 Ydieresis
+ 0179 Zacute
+ 017A zacute
+ 017B Zdotaccent
+ 017C zdotaccent
+ 017D Zcaron
+ 017E zcaron
+ 017F longs
+ 0192 florin
+ 01A0 Ohorn
+ 01A1 ohorn
+ 01AF Uhorn
+ 01B0 uhorn
+ 01E6 Gcaron
+ 01E7 gcaron
+ 01FA Aringacute
+ 01FB aringacute
+ 01FC AEacute
+ 01FD aeacute
+ 01FE Oslashacute
+ 01FF oslashacute
+ 0218 Scommaaccent
+ 0219 scommaaccent
+ 021A Tcommaaccent
+ 021B tcommaaccent
+ 02BC afii57929
+ 02BD afii64937
+ 02C6 circumflex
+ 02C7 caron
+ 02C9 macron
+ 02D8 breve
+ 02D9 dotaccent
+ 02DA ring
+ 02DB ogonek
+ 02DC tilde
+ 02DD hungarumlaut
+ 0300 gravecomb
+ 0301 acutecomb
+ 0303 tildecomb
+ 0309 hookabovecomb
+ 0323 dotbelowcomb
+ 0384 tonos
+ 0385 dieresistonos
+ 0386 Alphatonos
+ 0387 anoteleia
+ 0388 Epsilontonos
+ 0389 Etatonos
+ 038A Iotatonos
+ 038C Omicrontonos
+ 038E Upsilontonos
+ 038F Omegatonos
+ 0390 iotadieresistonos
+ 0391 Alpha
+ 0392 Beta
+ 0393 Gamma
+ 0394 Delta
+ 0395 Epsilon
+ 0396 Zeta
+ 0397 Eta
+ 0398 Theta
+ 0399 Iota
+ 039A Kappa
+ 039B Lambda
+ 039C Mu
+ 039D Nu
+ 039E Xi
+ 039F Omicron
+ 03A0 Pi
+ 03A1 Rho
+ 03A3 Sigma
+ 03A4 Tau
+ 03A5 Upsilon
+ 03A6 Phi
+ 03A7 Chi
+ 03A8 Psi
+ 03A9 Omega
+ 03AA Iotadieresis
+ 03AB Upsilondieresis
+ 03AC alphatonos
+ 03AD epsilontonos
+ 03AE etatonos
+ 03AF iotatonos
+ 03B0 upsilondieresistonos
+ 03B1 alpha
+ 03B2 beta
+ 03B3 gamma
+ 03B4 delta
+ 03B5 epsilon
+ 03B6 zeta
+ 03B7 eta
+ 03B8 theta
+ 03B9 iota
+ 03BA kappa
+ 03BB lambda
+ 03BC mu
+ 03BD nu
+ 03BE xi
+ 03BF omicron
+ 03C0 pi
+ 03C1 rho
+ 03C2 sigma1
+ 03C3 sigma
+ 03C4 tau
+ 03C5 upsilon
+ 03C6 phi
+ 03C7 chi
+ 03C8 psi
+ 03C9 omega
+ 03CA iotadieresis
+ 03CB upsilondieresis
+ 03CC omicrontonos
+ 03CD upsilontonos
+ 03CE omegatonos
+ 03D1 theta1
+ 03D2 Upsilon1
+ 03D5 phi1
+ 03D6 omega1
+ 0401 afii10023
+ 0402 afii10051
+ 0403 afii10052
+ 0404 afii10053
+ 0405 afii10054
+ 0406 afii10055
+ 0407 afii10056
+ 0408 afii10057
+ 0409 afii10058
+ 040A afii10059
+ 040B afii10060
+ 040C afii10061
+ 040E afii10062
+ 040F afii10145
+ 0410 afii10017
+ 0411 afii10018
+ 0412 afii10019
+ 0413 afii10020
+ 0414 afii10021
+ 0415 afii10022
+ 0416 afii10024
+ 0417 afii10025
+ 0418 afii10026
+ 0419 afii10027
+ 041A afii10028
+ 041B afii10029
+ 041C afii10030
+ 041D afii10031
+ 041E afii10032
+ 041F afii10033
+ 0420 afii10034
+ 0421 afii10035
+ 0422 afii10036
+ 0423 afii10037
+ 0424 afii10038
+ 0425 afii10039
+ 0426 afii10040
+ 0427 afii10041
+ 0428 afii10042
+ 0429 afii10043
+ 042A afii10044
+ 042B afii10045
+ 042C afii10046
+ 042D afii10047
+ 042E afii10048
+ 042F afii10049
+ 0430 afii10065
+ 0431 afii10066
+ 0432 afii10067
+ 0433 afii10068
+ 0434 afii10069
+ 0435 afii10070
+ 0436 afii10072
+ 0437 afii10073
+ 0438 afii10074
+ 0439 afii10075
+ 043A afii10076
+ 043B afii10077
+ 043C afii10078
+ 043D afii10079
+ 043E afii10080
+ 043F afii10081
+ 0440 afii10082
+ 0441 afii10083
+ 0442 afii10084
+ 0443 afii10085
+ 0444 afii10086
+ 0445 afii10087
+ 0446 afii10088
+ 0447 afii10089
+ 0448 afii10090
+ 0449 afii10091
+ 044A afii10092
+ 044B afii10093
+ 044C afii10094
+ 044D afii10095
+ 044E afii10096
+ 044F afii10097
+ 0451 afii10071
+ 0452 afii10099
+ 0453 afii10100
+ 0454 afii10101
+ 0455 afii10102
+ 0456 afii10103
+ 0457 afii10104
+ 0458 afii10105
+ 0459 afii10106
+ 045A afii10107
+ 045B afii10108
+ 045C afii10109
+ 045E afii10110
+ 045F afii10193
+ 0462 afii10146
+ 0463 afii10194
+ 0472 afii10147
+ 0473 afii10195
+ 0474 afii10148
+ 0475 afii10196
+ 0490 afii10050
+ 0491 afii10098
+ 04D9 afii10846
+ 05B0 afii57799
+ 05B1 afii57801
+ 05B2 afii57800
+ 05B3 afii57802
+ 05B4 afii57793
+ 05B5 afii57794
+ 05B6 afii57795
+ 05B7 afii57798
+ 05B8 afii57797
+ 05B9 afii57806
+ 05BB afii57796
+ 05BC afii57807
+ 05BD afii57839
+ 05BE afii57645
+ 05BF afii57841
+ 05C0 afii57842
+ 05C1 afii57804
+ 05C2 afii57803
+ 05C3 afii57658
+ 05D0 afii57664
+ 05D1 afii57665
+ 05D2 afii57666
+ 05D3 afii57667
+ 05D4 afii57668
+ 05D5 afii57669
+ 05D6 afii57670
+ 05D7 afii57671
+ 05D8 afii57672
+ 05D9 afii57673
+ 05DA afii57674
+ 05DB afii57675
+ 05DC afii57676
+ 05DD afii57677
+ 05DE afii57678
+ 05DF afii57679
+ 05E0 afii57680
+ 05E1 afii57681
+ 05E2 afii57682
+ 05E3 afii57683
+ 05E4 afii57684
+ 05E5 afii57685
+ 05E6 afii57686
+ 05E7 afii57687
+ 05E8 afii57688
+ 05E9 afii57689
+ 05EA afii57690
+ 05F0 afii57716
+ 05F1 afii57717
+ 05F2 afii57718
+ 060C afii57388
+ 061B afii57403
+ 061F afii57407
+ 0621 afii57409
+ 0622 afii57410
+ 0623 afii57411
+ 0624 afii57412
+ 0625 afii57413
+ 0626 afii57414
+ 0627 afii57415
+ 0628 afii57416
+ 0629 afii57417
+ 062A afii57418
+ 062B afii57419
+ 062C afii57420
+ 062D afii57421
+ 062E afii57422
+ 062F afii57423
+ 0630 afii57424
+ 0631 afii57425
+ 0632 afii57426
+ 0633 afii57427
+ 0634 afii57428
+ 0635 afii57429
+ 0636 afii57430
+ 0637 afii57431
+ 0638 afii57432
+ 0639 afii57433
+ 063A afii57434
+ 0640 afii57440
+ 0641 afii57441
+ 0642 afii57442
+ 0643 afii57443
+ 0644 afii57444
+ 0645 afii57445
+ 0646 afii57446
+ 0647 afii57470
+ 0648 afii57448
+ 0649 afii57449
+ 064A afii57450
+ 064B afii57451
+ 064C afii57452
+ 064D afii57453
+ 064E afii57454
+ 064F afii57455
+ 0650 afii57456
+ 0651 afii57457
+ 0652 afii57458
+ 0660 afii57392
+ 0661 afii57393
+ 0662 afii57394
+ 0663 afii57395
+ 0664 afii57396
+ 0665 afii57397
+ 0666 afii57398
+ 0667 afii57399
+ 0668 afii57400
+ 0669 afii57401
+ 066A afii57381
+ 066D afii63167
+ 0679 afii57511
+ 067E afii57506
+ 0686 afii57507
+ 0688 afii57512
+ 0691 afii57513
+ 0698 afii57508
+ 06A4 afii57505
+ 06AF afii57509
+ 06BA afii57514
+ 06D2 afii57519
+ 06D5 afii57534
+ 1E80 Wgrave
+ 1E81 wgrave
+ 1E82 Wacute
+ 1E83 wacute
+ 1E84 Wdieresis
+ 1E85 wdieresis
+ 1EF2 Ygrave
+ 1EF3 ygrave
+ 200C afii61664
+ 200D afii301
+ 200E afii299
+ 200F afii300
+ 2012 figuredash
+ 2013 endash
+ 2014 emdash
+ 2015 afii00208
+ 2017 underscoredbl
+ 2018 quoteleft
+ 2019 quoteright
+ 201A quotesinglbase
+ 201B quotereversed
+ 201C quotedblleft
+ 201D quotedblright
+ 201E quotedblbase
+ 2020 dagger
+ 2021 daggerdbl
+ 2022 bullet
+ 2024 onedotenleader
+ 2025 twodotenleader
+ 2026 ellipsis
+ 202C afii61573
+ 202D afii61574
+ 202E afii61575
+ 2030 perthousand
+ 2032 minute
+ 2033 second
+ 2039 guilsinglleft
+ 203A guilsinglright
+ 203C exclamdbl
+ 2044 fraction
+ 2070 zerosuperior
+ 2074 foursuperior
+ 2075 fivesuperior
+ 2076 sixsuperior
+ 2077 sevensuperior
+ 2078 eightsuperior
+ 2079 ninesuperior
+ 207D parenleftsuperior
+ 207E parenrightsuperior
+ 207F nsuperior
+ 2080 zeroinferior
+ 2081 oneinferior
+ 2082 twoinferior
+ 2083 threeinferior
+ 2084 fourinferior
+ 2085 fiveinferior
+ 2086 sixinferior
+ 2087 seveninferior
+ 2088 eightinferior
+ 2089 nineinferior
+ 208D parenleftinferior
+ 208E parenrightinferior
+ 20A1 colonmonetary
+ 20A3 franc
+ 20A4 lira
+ 20A7 peseta
+ 20AA afii57636
+ 20AB dong
+ 20AC Euro
+ 2105 afii61248
+ 2111 Ifraktur
+ 2113 afii61289
+ 2116 afii61352
+ 2118 weierstrass
+ 211C Rfraktur
+ 211E prescription
+ 2122 trademark
+ 2126 Omega
+ 212E estimated
+ 2135 aleph
+ 2153 onethird
+ 2154 twothirds
+ 215B oneeighth
+ 215C threeeighths
+ 215D fiveeighths
+ 215E seveneighths
+ 2190 arrowleft
+ 2191 arrowup
+ 2192 arrowright
+ 2193 arrowdown
+ 2194 arrowboth
+ 2195 arrowupdn
+ 21A8 arrowupdnbse
+ 21B5 carriagereturn
+ 21D0 arrowdblleft
+ 21D1 arrowdblup
+ 21D2 arrowdblright
+ 21D3 arrowdbldown
+ 21D4 arrowdblboth
+ 2200 universal
+ 2202 partialdiff
+ 2203 existential
+ 2205 emptyset
+ 2206 Delta
+ 2207 gradient
+ 2208 element
+ 2209 notelement
+ 220B suchthat
+ 220F product
+ 2211 summation
+ 2212 minus
+ 2215 fraction
+ 2217 asteriskmath
+ 2219 periodcentered
+ 221A radical
+ 221D proportional
+ 221E infinity
+ 221F orthogonal
+ 2220 angle
+ 2227 logicaland
+ 2228 logicalor
+ 2229 intersection
+ 222A union
+ 222B integral
+ 2234 therefore
+ 223C similar
+ 2245 congruent
+ 2248 approxequal
+ 2260 notequal
+ 2261 equivalence
+ 2264 lessequal
+ 2265 greaterequal
+ 2282 propersubset
+ 2283 propersuperset
+ 2284 notsubset
+ 2286 reflexsubset
+ 2287 reflexsuperset
+ 2295 circleplus
+ 2297 circlemultiply
+ 22A5 perpendicular
+ 22C5 dotmath
+ 2302 house
+ 2310 revlogicalnot
+ 2320 integraltp
+ 2321 integralbt
+ 2329 angleleft
+ 232A angleright
+ 2500 SF100000
+ 2502 SF110000
+ 250C SF010000
+ 2510 SF030000
+ 2514 SF020000
+ 2518 SF040000
+ 251C SF080000
+ 2524 SF090000
+ 252C SF060000
+ 2534 SF070000
+ 253C SF050000
+ 2550 SF430000
+ 2551 SF240000
+ 2552 SF510000
+ 2553 SF520000
+ 2554 SF390000
+ 2555 SF220000
+ 2556 SF210000
+ 2557 SF250000
+ 2558 SF500000
+ 2559 SF490000
+ 255A SF380000
+ 255B SF280000
+ 255C SF270000
+ 255D SF260000
+ 255E SF360000
+ 255F SF370000
+ 2560 SF420000
+ 2561 SF190000
+ 2562 SF200000
+ 2563 SF230000
+ 2564 SF470000
+ 2565 SF480000
+ 2566 SF410000
+ 2567 SF450000
+ 2568 SF460000
+ 2569 SF400000
+ 256A SF540000
+ 256B SF530000
+ 256C SF440000
+ 2580 upblock
+ 2584 dnblock
+ 2588 block
+ 258C lfblock
+ 2590 rtblock
+ 2591 ltshade
+ 2592 shade
+ 2593 dkshade
+ 25A0 filledbox
+ 25A1 H22073
+ 25AA H18543
+ 25AB H18551
+ 25AC filledrect
+ 25B2 triagup
+ 25BA triagrt
+ 25BC triagdn
+ 25C4 triaglf
+ 25CA lozenge
+ 25CB circle
+ 25CF H18533
+ 25D8 invbullet
+ 25D9 invcircle
+ 25E6 openbullet
+ 263A smileface
+ 263B invsmileface
+ 263C sun
+ 2640 female
+ 2642 male
+ 2660 spade
+ 2663 club
+ 2665 heart
+ 2666 diamond
+ 266A musicalnote
+ 266B musicalnotedbl
+ F6BE dotlessj
+ F6BF LL
+ F6C0 ll
+ F6C1 Scedilla
+ F6C2 scedilla
+ F6C3 commaaccent
+ F6C4 afii10063
+ F6C5 afii10064
+ F6C6 afii10192
+ F6C7 afii10831
+ F6C8 afii10832
+ F6C9 Acute
+ F6CA Caron
+ F6CB Dieresis
+ F6CC DieresisAcute
+ F6CD DieresisGrave
+ F6CE Grave
+ F6CF Hungarumlaut
+ F6D0 Macron
+ F6D1 cyrBreve
+ F6D2 cyrFlex
+ F6D3 dblGrave
+ F6D4 cyrbreve
+ F6D5 cyrflex
+ F6D6 dblgrave
+ F6D7 dieresisacute
+ F6D8 dieresisgrave
+ F6D9 copyrightserif
+ F6DA registerserif
+ F6DB trademarkserif
+ F6DC onefitted
+ F6DD rupiah
+ F6DE threequartersemdash
+ F6DF centinferior
+ F6E0 centsuperior
+ F6E1 commainferior
+ F6E2 commasuperior
+ F6E3 dollarinferior
+ F6E4 dollarsuperior
+ F6E5 hypheninferior
+ F6E6 hyphensuperior
+ F6E7 periodinferior
+ F6E8 periodsuperior
+ F6E9 asuperior
+ F6EA bsuperior
+ F6EB dsuperior
+ F6EC esuperior
+ F6ED isuperior
+ F6EE lsuperior
+ F6EF msuperior
+ F6F0 osuperior
+ F6F1 rsuperior
+ F6F2 ssuperior
+ F6F3 tsuperior
+ F6F4 Brevesmall
+ F6F5 Caronsmall
+ F6F6 Circumflexsmall
+ F6F7 Dotaccentsmall
+ F6F8 Hungarumlautsmall
+ F6F9 Lslashsmall
+ F6FA OEsmall
+ F6FB Ogoneksmall
+ F6FC Ringsmall
+ F6FD Scaronsmall
+ F6FE Tildesmall
+ F6FF Zcaronsmall
+ F721 exclamsmall
+ F724 dollaroldstyle
+ F726 ampersandsmall
+ F730 zerooldstyle
+ F731 oneoldstyle
+ F732 twooldstyle
+ F733 threeoldstyle
+ F734 fouroldstyle
+ F735 fiveoldstyle
+ F736 sixoldstyle
+ F737 sevenoldstyle
+ F738 eightoldstyle
+ F739 nineoldstyle
+ F73F questionsmall
+ F760 Gravesmall
+ F761 Asmall
+ F762 Bsmall
+ F763 Csmall
+ F764 Dsmall
+ F765 Esmall
+ F766 Fsmall
+ F767 Gsmall
+ F768 Hsmall
+ F769 Ismall
+ F76A Jsmall
+ F76B Ksmall
+ F76C Lsmall
+ F76D Msmall
+ F76E Nsmall
+ F76F Osmall
+ F770 Psmall
+ F771 Qsmall
+ F772 Rsmall
+ F773 Ssmall
+ F774 Tsmall
+ F775 Usmall
+ F776 Vsmall
+ F777 Wsmall
+ F778 Xsmall
+ F779 Ysmall
+ F77A Zsmall
+ F7A1 exclamdownsmall
+ F7A2 centoldstyle
+ F7A8 Dieresissmall
+ F7AF Macronsmall
+ F7B4 Acutesmall
+ F7B8 Cedillasmall
+ F7BF questiondownsmall
+ F7E0 Agravesmall
+ F7E1 Aacutesmall
+ F7E2 Acircumflexsmall
+ F7E3 Atildesmall
+ F7E4 Adieresissmall
+ F7E5 Aringsmall
+ F7E6 AEsmall
+ F7E7 Ccedillasmall
+ F7E8 Egravesmall
+ F7E9 Eacutesmall
+ F7EA Ecircumflexsmall
+ F7EB Edieresissmall
+ F7EC Igravesmall
+ F7ED Iacutesmall
+ F7EE Icircumflexsmall
+ F7EF Idieresissmall
+ F7F0 Ethsmall
+ F7F1 Ntildesmall
+ F7F2 Ogravesmall
+ F7F3 Oacutesmall
+ F7F4 Ocircumflexsmall
+ F7F5 Otildesmall
+ F7F6 Odieresissmall
+ F7F8 Oslashsmall
+ F7F9 Ugravesmall
+ F7FA Uacutesmall
+ F7FB Ucircumflexsmall
+ F7FC Udieresissmall
+ F7FD Yacutesmall
+ F7FE Thornsmall
+ F7FF Ydieresissmall
+ F8E5 radicalex
+ F8E6 arrowvertex
+ F8E7 arrowhorizex
+ F8E8 registersans
+ F8E9 copyrightsans
+ F8EA trademarksans
+ F8EB parenlefttp
+ F8EC parenleftex
+ F8ED parenleftbt
+ F8EE bracketlefttp
+ F8EF bracketleftex
+ F8F0 bracketleftbt
+ F8F1 bracelefttp
+ F8F2 braceleftmid
+ F8F3 braceleftbt
+ F8F4 braceex
+ F8F5 integralex
+ F8F6 parenrighttp
+ F8F7 parenrightex
+ F8F8 parenrightbt
+ F8F9 bracketrighttp
+ F8FA bracketrightex
+ F8FB bracketrightbt
+ F8FC bracerighttp
+ F8FD bracerightmid
+ F8FE bracerightbt
+ FB00 ff
+ FB01 fi
+ FB02 fl
+ FB03 ffi
+ FB04 ffl
+ FB1F afii57705
+ FB2A afii57694
+ FB2B afii57695
+ FB35 afii57723
+ FB4B afii57700
+ }
+
+ variable ps_preamble {}
+
+ namespace eval ps {
+ namespace ensemble create
+ namespace export {[a-z]*}
+ proc literal {string} {
+ upvar 0 ::tk::ps_preamble preamble
+ foreach line [split $string \n] {
+ set line [string trim $line]
+ if {$line eq ""} continue
+ append preamble $line \n
+ }
+ return
+ }
+ proc variable {name value} {
+ upvar 0 ::tk::ps_preamble preamble
+ append preamble "/$name $value def\n"
+ return
+ }
+ proc function {name body} {
+ upvar 0 ::tk::ps_preamble preamble
+ append preamble "/$name \{"
+ foreach line [split $body \n] {
+ set line [string trim $line]
+ # Strip blank lines and comments from the bodies of functions
+ if {$line eq "" } continue
+ if {[string match {[%#]*} $line]} continue
+ append preamble $line " "
+ }
+ append preamble "\} bind def\n"
+ return
+ }
+ }
+
+ ps literal {
+ %%BeginProlog
+ % This is a standard prolog for Postscript generated by Tk's canvas
+ % widget.
+ }
+ ps variable CurrentEncoding [CreatePostscriptEncoding]
+ ps literal {50 dict begin}
+
+ # The definitions below just define all of the variables used in any of
+ # the procedures here. This is needed for obscure reasons explained on
+ # p. 716 of the Postscript manual (Section H.2.7, "Initializing
+ # Variables," in the section on Encapsulated Postscript).
+ ps variable baseline 0
+ ps variable stipimage 0
+ ps variable height 0
+ ps variable justify 0
+ ps variable lineLength 0
+ ps variable spacing 0
+ ps variable stipple 0
+ ps variable strings 0
+ ps variable xoffset 0
+ ps variable yoffset 0
+ ps variable tmpstip null
+ ps variable baselineSampler "( TXygqPZ)"
+ # Put an extra-tall character in; done this way to avoid encoding trouble
+ ps literal {baselineSampler 0 196 put}
+
+ ps function cstringshow {
+ {
+ dup type /stringtype eq
+ { show } { glyphshow }
+ ifelse
+ } forall
+ }
+
+ ps function cstringwidth {
+ 0 exch 0 exch
+ {
+ dup type /stringtype eq
+ { stringwidth } {
+ currentfont /Encoding get exch 1 exch put (\001)
+ stringwidth
+ }
+ ifelse
+ exch 3 1 roll add 3 1 roll add exch
+ } forall
+ }
+
+ # font ISOEncode font
+ #
+ # This procedure changes the encoding of a font from the default
+ # Postscript encoding to current system encoding. It's typically invoked
+ # just before invoking "setfont". The body of this procedure comes from
+ # Section 5.6.1 of the Postscript book.
+ ps function ISOEncode {
+ dup length dict begin
+ {1 index /FID ne {def} {pop pop} ifelse} forall
+ /Encoding CurrentEncoding def
+ currentdict
+ end
+ % I'm not sure why it's necessary to use "definefont" on this new
+ % font, but it seems to be important; just use the name "Temporary"
+ % for the font.
+ /Temporary exch definefont
+ }
+
+ # StrokeClip
+ #
+ # This procedure converts the current path into a clip area under the
+ # assumption of stroking. It's a bit tricky because some Postscript
+ # interpreters get errors during strokepath for dashed lines. If this
+ # happens then turn off dashes and try again.
+ ps function StrokeClip {
+ {strokepath} stopped {
+ (This Postscript printer gets limitcheck overflows when) =
+ (stippling dashed lines; lines will be printed solid instead.) =
+ [] 0 setdash strokepath} if
+ clip
+ }
+
+ # desiredSize EvenPixels closestSize
+ #
+ # The procedure below is used for stippling. Given the optimal size of a
+ # dot in a stipple pattern in the current user coordinate system, compute
+ # the closest size that is an exact multiple of the device's pixel
+ # size. This allows stipple patterns to be displayed without aliasing
+ # effects.
+ ps function EvenPixels {
+ % Compute exact number of device pixels per stipple dot.
+ dup 0 matrix currentmatrix dtransform
+ dup mul exch dup mul add sqrt
+ % Round to an integer, make sure the number is at least 1, and
+ % compute user coord distance corresponding to this.
+ dup round dup 1 lt {pop 1} if
+ exch div mul
+ }
+
+ # width height string StippleFill --
+ #
+ # Given a path already set up and a clipping region generated from it,
+ # this procedure will fill the clipping region with a stipple pattern.
+ # "String" contains a proper image description of the stipple pattern and
+ # "width" and "height" give its dimensions. Each stipple dot is assumed to
+ # be about one unit across in the current user coordinate system. This
+ # procedure trashes the graphics state.
+ ps function StippleFill {
+ % The following code is needed to work around a NeWSprint bug.
+ /tmpstip 1 index def
+ % Change the scaling so that one user unit in user coordinates
+ % corresponds to the size of one stipple dot.
+ 1 EvenPixels dup scale
+ % Compute the bounding box occupied by the path (which is now the
+ % clipping region), and round the lower coordinates down to the
+ % nearest starting point for the stipple pattern. Be careful about
+ % negative numbers, since the rounding works differently on them.
+ pathbbox
+ 4 2 roll
+ 5 index div dup 0 lt {1 sub} if cvi 5 index mul 4 1 roll
+ 6 index div dup 0 lt {1 sub} if cvi 6 index mul 3 2 roll
+ % Stack now: width height string y1 y2 x1 x2
+ % Below is a doubly-nested for loop to iterate across this area
+ % in units of the stipple pattern size, going up columns then
+ % across rows, blasting out a stipple-pattern-sized rectangle at
+ % each position
+ 6 index exch {
+ 2 index 5 index 3 index {
+ % Stack now: width height string y1 y2 x y
+ gsave
+ 1 index exch translate
+ 5 index 5 index true matrix tmpstip imagemask
+ grestore
+ } for
+ pop
+ } for
+ pop pop pop pop pop
+ }
+
+ # -- AdjustColor --
+ #
+ # Given a color value already set for output by the caller, adjusts that
+ # value to a grayscale or mono value if requested by the CL variable.
+ ps function AdjustColor {
+ CL 2 lt {
+ currentgray
+ CL 0 eq {
+ .5 lt {0} {1} ifelse
+ } if
+ setgray
+ } if
+ }
+
+ # x y strings spacing xoffset yoffset justify stipple DrawText --
+ #
+ # This procedure does all of the real work of drawing text. The color and
+ # font must already have been set by the caller, and the following
+ # arguments must be on the stack:
+ #
+ # x, y - Coordinates at which to draw text.
+ # strings - An array of strings, one for each line of the text item, in
+ # order from top to bottom.
+ # spacing - Spacing between lines.
+ # xoffset - Horizontal offset for text bbox relative to x and y: 0 for
+ # nw/w/sw anchor, -0.5 for n/center/s, and -1.0 for ne/e/se.
+ # yoffset - Vertical offset for text bbox relative to x and y: 0 for
+ # nw/n/ne anchor, +0.5 for w/center/e, and +1.0 for sw/s/se.
+ # justify - 0 for left justification, 0.5 for center, 1 for right justify.
+ # stipple - Boolean value indicating whether or not text is to be drawn in
+ # stippled fashion. If text is stippled, function StippleText
+ # must have been defined to call StippleFill in the right way.
+ #
+ # Also, when this procedure is invoked, the color and font must already
+ # have been set for the text.
+ ps function DrawText {
+ /stipple exch def
+ /justify exch def
+ /yoffset exch def
+ /xoffset exch def
+ /spacing exch def
+ /strings exch def
+ % First scan through all of the text to find the widest line.
+ /lineLength 0 def
+ strings {
+ cstringwidth pop
+ dup lineLength gt {/lineLength exch def} {pop} ifelse
+ newpath
+ } forall
+ % Compute the baseline offset and the actual font height.
+ 0 0 moveto baselineSampler false charpath
+ pathbbox dup /baseline exch def
+ exch pop exch sub /height exch def pop
+ newpath
+ % Translate and rotate coordinates first so that the origin is at
+ % the upper-left corner of the text's bounding box. Remember that
+ % angle for rotating, and x and y for positioning are still on the
+ % stack.
+ translate
+ rotate
+ lineLength xoffset mul
+ strings length 1 sub spacing mul height add yoffset mul translate
+ % Now use the baseline and justification information to translate
+ % so that the origin is at the baseline and positioning point for
+ % the first line of text.
+ justify lineLength mul baseline neg translate
+ % Iterate over each of the lines to output it. For each line,
+ % compute its width again so it can be properly justified, then
+ % display it.
+ strings {
+ dup cstringwidth pop
+ justify neg mul 0 moveto
+ stipple {
+ % The text is stippled, so turn it into a path and print
+ % by calling StippledText, which in turn calls
+ % StippleFill. Unfortunately, many Postscript interpreters
+ % will get overflow errors if we try to do the whole
+ % string at once, so do it a character at a time.
+ gsave
+ /char (X) def
+ {
+ dup type /stringtype eq {
+ % This segment is a string.
+ {
+ char 0 3 -1 roll put
+ currentpoint
+ gsave
+ char true charpath clip StippleText
+ grestore
+ char stringwidth translate
+ moveto
+ } forall
+ } {
+ % This segment is glyph name
+ % Temporary override
+ currentfont /Encoding get exch 1 exch put
+ currentpoint
+ gsave (\001) true charpath clip StippleText
+ grestore
+ (\001) stringwidth translate
+ moveto
+ } ifelse
+ } forall
+ grestore
+ } {cstringshow} ifelse
+ 0 spacing neg translate
+ } forall
+ }
+
+ # Define the "TkPhoto" function variants, which are modified versions
+ # of the original "transparentimage" function posted by ian@five-d.com
+ # (Ian Kemmish) to comp.lang.postscript. For a monochrome colorLevel
+ # this is a slightly different version that uses the imagemask command
+ # instead of image.
+
+ ps function TkPhotoColor {
+ gsave
+ 32 dict begin
+ /tinteger exch def
+ /transparent 1 string def
+ transparent 0 tinteger put
+ /olddict exch def
+ olddict /DataSource get dup type /filetype ne {
+ olddict /DataSource 3 -1 roll
+ 0 () /SubFileDecode filter put
+ } {
+ pop
+ } ifelse
+ /newdict olddict maxlength dict def
+ olddict newdict copy pop
+ /w newdict /Width get def
+ /crpp newdict /Decode get length 2 idiv def
+ /str w string def
+ /pix w crpp mul string def
+ /substrlen 2 w log 2 log div floor exp cvi def
+ /substrs [ {
+ substrlen string
+ 0 1 substrlen 1 sub {
+ 1 index exch tinteger put
+ } for
+ /substrlen substrlen 2 idiv def
+ substrlen 0 eq {exit} if
+ } loop ] def
+ /h newdict /Height get def
+ 1 w div 1 h div matrix scale
+ olddict /ImageMatrix get exch matrix concatmatrix
+ matrix invertmatrix concat
+ newdict /Height 1 put
+ newdict /DataSource pix put
+ /mat [w 0 0 h 0 0] def
+ newdict /ImageMatrix mat put
+ 0 1 h 1 sub {
+ mat 5 3 -1 roll neg put
+ olddict /DataSource get str readstring pop pop
+ /tail str def
+ /x 0 def
+ olddict /DataSource get pix readstring pop pop
+ {
+ tail transparent search dup /done exch not def
+ {exch pop exch pop} if
+ /w1 exch length def
+ w1 0 ne {
+ newdict /DataSource
+ pix x crpp mul w1 crpp mul getinterval put
+ newdict /Width w1 put
+ mat 4 x neg put
+ /x x w1 add def
+ newdict image
+ /tail tail w1 tail length w1 sub getinterval def
+ } if
+ done {exit} if
+ tail substrs {
+ anchorsearch {pop} if
+ } forall
+ /tail exch def
+ tail length 0 eq {exit} if
+ /x w tail length sub def
+ } loop
+ } for
+ end
+ grestore
+ }
+ ps function TkPhotoMono {
+ gsave
+ 32 dict begin
+ /dummyInteger exch def
+ /olddict exch def
+ olddict /DataSource get dup type /filetype ne {
+ olddict /DataSource 3 -1 roll
+ 0 () /SubFileDecode filter put
+ } {
+ pop
+ } ifelse
+ /newdict olddict maxlength dict def
+ olddict newdict copy pop
+ /w newdict /Width get def
+ /pix w 7 add 8 idiv string def
+ /h newdict /Height get def
+ 1 w div 1 h div matrix scale
+ olddict /ImageMatrix get exch matrix concatmatrix
+ matrix invertmatrix concat
+ newdict /Height 1 put
+ newdict /DataSource pix put
+ /mat [w 0 0 h 0 0] def
+ newdict /ImageMatrix mat put
+ 0 1 h 1 sub {
+ mat 5 3 -1 roll neg put
+ 0.000 0.000 0.000 setrgbcolor
+ olddict /DataSource get pix readstring pop pop
+ newdict /DataSource pix put
+ newdict imagemask
+ 1.000 1.000 1.000 setrgbcolor
+ olddict /DataSource get pix readstring pop pop
+ newdict /DataSource pix put
+ newdict imagemask
+ } for
+ end
+ grestore
+ }
+
+ ps literal %%EndProlog
+}
+
+proc tk::ensure_psenc_is_loaded {} {
+}
diff --git a/tk8.6/library/msgbox.tcl b/tk8.6/library/msgbox.tcl
new file mode 100644
index 0000000..98603af
--- /dev/null
+++ b/tk8.6/library/msgbox.tcl
@@ -0,0 +1,430 @@
+# msgbox.tcl --
+#
+# Implements messageboxes for platforms that do not have native
+# messagebox support.
+#
+# Copyright (c) 1994-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.
+#
+
+# Ensure existence of ::tk::dialog namespace
+#
+namespace eval ::tk::dialog {}
+
+image create bitmap ::tk::dialog::b1 -foreground black \
+-data "#define b1_width 32\n#define b1_height 32
+static unsigned char q1_bits[] = {
+ 0x00, 0xf8, 0x1f, 0x00, 0x00, 0x07, 0xe0, 0x00, 0xc0, 0x00, 0x00, 0x03,
+ 0x20, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x10,
+ 0x04, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40,
+ 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80,
+ 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80,
+ 0x01, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40,
+ 0x04, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x08,
+ 0x60, 0x00, 0x00, 0x04, 0x80, 0x03, 0x80, 0x03, 0x00, 0x0c, 0x78, 0x00,
+ 0x00, 0x30, 0x04, 0x00, 0x00, 0x40, 0x04, 0x00, 0x00, 0x40, 0x04, 0x00,
+ 0x00, 0x80, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};"
+image create bitmap ::tk::dialog::b2 -foreground white \
+-data "#define b2_width 32\n#define b2_height 32
+static unsigned char b2_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0xff, 0xff, 0x00,
+ 0xc0, 0xff, 0xff, 0x03, 0xe0, 0xff, 0xff, 0x07, 0xf0, 0xff, 0xff, 0x0f,
+ 0xf8, 0xff, 0xff, 0x1f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f,
+ 0xfe, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x7f,
+ 0xfe, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x7f,
+ 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f,
+ 0xf8, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0xff, 0x0f, 0xe0, 0xff, 0xff, 0x07,
+ 0x80, 0xff, 0xff, 0x03, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0xf0, 0x07, 0x00,
+ 0x00, 0xc0, 0x03, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x80, 0x03, 0x00,
+ 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};"
+image create bitmap ::tk::dialog::q -foreground blue \
+-data "#define q_width 32\n#define q_height 32
+static unsigned char q_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00,
+ 0x00, 0x10, 0x0f, 0x00, 0x00, 0x18, 0x1e, 0x00, 0x00, 0x38, 0x1e, 0x00,
+ 0x00, 0x38, 0x1e, 0x00, 0x00, 0x10, 0x0f, 0x00, 0x00, 0x80, 0x07, 0x00,
+ 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00,
+ 0x00, 0xe0, 0x01, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};"
+image create bitmap ::tk::dialog::i -foreground blue \
+-data "#define i_width 32\n#define i_height 32
+static unsigned char i_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xe0, 0x01, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0xf0, 0x03, 0x00,
+ 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xf8, 0x03, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0xe0, 0x03, 0x00,
+ 0x00, 0xe0, 0x03, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xe0, 0x03, 0x00,
+ 0x00, 0xe0, 0x03, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xf0, 0x07, 0x00,
+ 0x00, 0xf8, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};"
+image create bitmap ::tk::dialog::w1 -foreground black \
+-data "#define w1_width 32\n#define w1_height 32
+static unsigned char w1_bits[] = {
+ 0x00, 0x80, 0x01, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x20, 0x04, 0x00,
+ 0x00, 0x10, 0x04, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00,
+ 0x00, 0x08, 0x10, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x04, 0x20, 0x00,
+ 0x00, 0x02, 0x20, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x01, 0x40, 0x00,
+ 0x00, 0x01, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x01,
+ 0x40, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x02,
+ 0x20, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x08,
+ 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x10,
+ 0x04, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x40,
+ 0x01, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x20,
+ 0xfc, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00};"
+image create bitmap ::tk::dialog::w2 -foreground yellow \
+-data "#define w2_width 32\n#define w2_height 32
+static unsigned char w2_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0xc0, 0x03, 0x00,
+ 0x00, 0xe0, 0x03, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xf0, 0x07, 0x00,
+ 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xf8, 0x1f, 0x00,
+ 0x00, 0xfc, 0x1f, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0xfe, 0x3f, 0x00,
+ 0x00, 0xfe, 0x7f, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, 0xff, 0xff, 0x00,
+ 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x01, 0xc0, 0xff, 0xff, 0x01,
+ 0xc0, 0xff, 0xff, 0x03, 0xe0, 0xff, 0xff, 0x03, 0xe0, 0xff, 0xff, 0x07,
+ 0xf0, 0xff, 0xff, 0x07, 0xf0, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f,
+ 0xf8, 0xff, 0xff, 0x1f, 0xfc, 0xff, 0xff, 0x1f, 0xfe, 0xff, 0xff, 0x3f,
+ 0xfe, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x1f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};"
+image create bitmap ::tk::dialog::w3 -foreground black \
+-data "#define w3_width 32\n#define w3_height 32
+static unsigned char w3_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xc0, 0x03, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,
+ 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,
+ 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00,
+ 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0xc0, 0x03, 0x00,
+ 0x00, 0xc0, 0x03, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};"
+
+# ::tk::MessageBox --
+#
+# Pops up a messagebox with an application-supplied message with
+# an icon and a list of buttons. This procedure will be called
+# by tk_messageBox if the platform does not have native
+# messagebox support, or if the particular type of messagebox is
+# not supported natively.
+#
+# Color icons are used on Unix displays that have a color
+# depth of 4 or more and $tk_strictMotif is not on.
+#
+# This procedure is a private procedure shouldn't be called
+# directly. Call tk_messageBox instead.
+#
+# See the user documentation for details on what tk_messageBox does.
+#
+proc ::tk::MessageBox {args} {
+ global tk_strictMotif
+ variable ::tk::Priv
+
+ set w ::tk::PrivMsgBox
+ upvar $w data
+
+ #
+ # The default value of the title is space (" ") not the empty string
+ # because for some window managers, a
+ # wm title .foo ""
+ # causes the window title to be "foo" instead of the empty string.
+ #
+ set specs {
+ {-default "" "" ""}
+ {-detail "" "" ""}
+ {-icon "" "" "info"}
+ {-message "" "" ""}
+ {-parent "" "" .}
+ {-title "" "" " "}
+ {-type "" "" "ok"}
+ }
+
+ tclParseConfigSpec $w $specs "" $args
+
+ if {$data(-icon) ni {info warning error question}} {
+ return -code error -errorcode [list TK LOOKUP ICON $data(-icon)] \
+ "bad -icon value \"$data(-icon)\": must be error, info, question, or warning"
+ }
+ set windowingsystem [tk windowingsystem]
+ if {$windowingsystem eq "aqua"} {
+ switch -- $data(-icon) {
+ "error" {set data(-icon) "stop"}
+ "warning" {set data(-icon) "caution"}
+ "info" {set data(-icon) "note"}
+ }
+ option add *Dialog*background systemDialogBackgroundActive widgetDefault
+ option add *Dialog*Button.highlightBackground \
+ systemDialogBackgroundActive widgetDefault
+ }
+
+ if {![winfo exists $data(-parent)]} {
+ return -code error -errorcode [list TK LOOKUP WINDOW $data(-parent)] \
+ "bad window path name \"$data(-parent)\""
+ }
+
+ switch -- $data(-type) {
+ abortretryignore {
+ set names [list abort retry ignore]
+ set labels [list &Abort &Retry &Ignore]
+ set cancel abort
+ }
+ ok {
+ set names [list ok]
+ set labels {&OK}
+ set cancel ok
+ }
+ okcancel {
+ set names [list ok cancel]
+ set labels [list &OK &Cancel]
+ set cancel cancel
+ }
+ retrycancel {
+ set names [list retry cancel]
+ set labels [list &Retry &Cancel]
+ set cancel cancel
+ }
+ yesno {
+ set names [list yes no]
+ set labels [list &Yes &No]
+ set cancel no
+ }
+ yesnocancel {
+ set names [list yes no cancel]
+ set labels [list &Yes &No &Cancel]
+ set cancel cancel
+ }
+ default {
+ return -code error -errorcode [list TK LOOKUP DLG_TYPE $data(-type)] \
+ "bad -type value \"$data(-type)\": must be\
+ abortretryignore, ok, okcancel, retrycancel,\
+ yesno, or yesnocancel"
+ }
+ }
+
+ set buttons {}
+ foreach name $names lab $labels {
+ lappend buttons [list $name -text [mc $lab]]
+ }
+
+ # If no default button was specified, the default default is the
+ # first button (Bug: 2218).
+
+ if {$data(-default) eq ""} {
+ set data(-default) [lindex [lindex $buttons 0] 0]
+ }
+
+ set valid 0
+ foreach btn $buttons {
+ if {[lindex $btn 0] eq $data(-default)} {
+ set valid 1
+ break
+ }
+ }
+ if {!$valid} {
+ return -code error -errorcode {TK MSGBOX DEFAULT} \
+ "bad -default value \"$data(-default)\": must be\
+ abort, retry, ignore, ok, cancel, no, or yes"
+ }
+
+ # 2. Set the dialog to be a child window of $parent
+ #
+ #
+ if {$data(-parent) ne "."} {
+ set w $data(-parent).__tk__messagebox
+ } else {
+ set w .__tk__messagebox
+ }
+
+ # There is only one background colour for the whole dialog
+ set bg [ttk::style lookup . -background]
+
+ # 3. Create the top-level window and divide it into top
+ # and bottom parts.
+
+ catch {destroy $w}
+ toplevel $w -class Dialog -bg $bg
+ wm title $w $data(-title)
+ wm iconname $w Dialog
+ wm protocol $w WM_DELETE_WINDOW [list $w.$cancel invoke]
+
+ # Message boxes should be transient with respect to their parent so that
+ # they always stay on top of the parent window. But some window managers
+ # will simply create the child window as withdrawn if the parent is not
+ # viewable (because it is withdrawn or iconified). This is not good for
+ # "grab"bed windows. So only make the message box transient if the parent
+ # is viewable.
+ #
+ if {[winfo viewable [winfo toplevel $data(-parent)]] } {
+ wm transient $w $data(-parent)
+ }
+
+ if {$windowingsystem eq "aqua"} {
+ ::tk::unsupported::MacWindowStyle style $w moveableModal {}
+ } elseif {$windowingsystem eq "x11"} {
+ wm attributes $w -type dialog
+ }
+
+ ttk::frame $w.bot
+ grid anchor $w.bot center
+ pack $w.bot -side bottom -fill both
+ ttk::frame $w.top
+ pack $w.top -side top -fill both -expand 1
+
+ # 4. Fill the top part with bitmap, message and detail (use the
+ # option database for -wraplength and -font so that they can be
+ # overridden by the caller).
+
+ option add *Dialog.msg.wrapLength 3i widgetDefault
+ option add *Dialog.dtl.wrapLength 3i widgetDefault
+ option add *Dialog.msg.font TkCaptionFont widgetDefault
+ option add *Dialog.dtl.font TkDefaultFont widgetDefault
+
+ ttk::label $w.msg -anchor nw -justify left -text $data(-message)
+ if {$data(-detail) ne ""} {
+ ttk::label $w.dtl -anchor nw -justify left -text $data(-detail)
+ }
+ if {$data(-icon) ne ""} {
+ if {([winfo depth $w] < 4) || $tk_strictMotif} {
+ # ttk::label has no -bitmap option
+ label $w.bitmap -bitmap $data(-icon) -background $bg
+ } else {
+ switch $data(-icon) {
+ error {
+ ttk::label $w.bitmap -image ::tk::icons::error
+ }
+ info {
+ ttk::label $w.bitmap -image ::tk::icons::information
+ }
+ question {
+ ttk::label $w.bitmap -image ::tk::icons::question
+ }
+ default {
+ ttk::label $w.bitmap -image ::tk::icons::warning
+ }
+ }
+ }
+ }
+ grid $w.bitmap $w.msg -in $w.top -sticky news -padx 2m -pady 2m
+ grid configure $w.bitmap -sticky nw
+ grid columnconfigure $w.top 1 -weight 1
+ if {$data(-detail) ne ""} {
+ grid ^ $w.dtl -in $w.top -sticky news -padx 2m -pady {0 2m}
+ grid rowconfigure $w.top 1 -weight 1
+ } else {
+ grid rowconfigure $w.top 0 -weight 1
+ }
+
+ # 5. Create a row of buttons at the bottom of the dialog.
+
+ set i 0
+ foreach but $buttons {
+ set name [lindex $but 0]
+ set opts [lrange $but 1 end]
+ if {![llength $opts]} {
+ # Capitalize the first letter of $name
+ set capName [string toupper $name 0]
+ set opts [list -text $capName]
+ }
+
+ eval [list tk::AmpWidget ttk::button $w.$name] $opts \
+ [list -command [list set tk::Priv(button) $name]]
+
+ if {$name eq $data(-default)} {
+ $w.$name configure -default active
+ } else {
+ $w.$name configure -default normal
+ }
+ grid $w.$name -in $w.bot -row 0 -column $i -padx 3m -pady 2m -sticky ew
+ grid columnconfigure $w.bot $i -uniform buttons
+ # We boost the size of some Mac buttons for l&f
+ if {$windowingsystem eq "aqua"} {
+ set tmp [string tolower $name]
+ if {$tmp eq "ok" || $tmp eq "cancel" || $tmp eq "yes" ||
+ $tmp eq "no" || $tmp eq "abort" || $tmp eq "retry" ||
+ $tmp eq "ignore"} {
+ grid columnconfigure $w.bot $i -minsize 90
+ }
+ grid configure $w.$name -pady 7
+ }
+ incr i
+
+ # create the binding for the key accelerator, based on the underline
+ #
+ # set underIdx [$w.$name cget -under]
+ # if {$underIdx >= 0} {
+ # set key [string index [$w.$name cget -text] $underIdx]
+ # bind $w <Alt-[string tolower $key]> [list $w.$name invoke]
+ # bind $w <Alt-[string toupper $key]> [list $w.$name invoke]
+ # }
+ }
+ bind $w <Alt-Key> [list ::tk::AltKeyInDialog $w %A]
+
+ if {$data(-default) ne ""} {
+ bind $w <FocusIn> {
+ if {[winfo class %W] in "Button TButton"} {
+ %W configure -default active
+ }
+ }
+ bind $w <FocusOut> {
+ if {[winfo class %W] in "Button TButton"} {
+ %W configure -default normal
+ }
+ }
+ }
+
+ # 6. Create bindings for <Return>, <Escape> and <Destroy> on the dialog
+
+ bind $w <Return> {
+ if {[winfo class %W] in "Button TButton"} {
+ %W invoke
+ }
+ }
+
+ # Invoke the designated cancelling operation
+ bind $w <Escape> [list $w.$cancel invoke]
+
+ # At <Destroy> the buttons have vanished, so must do this directly.
+ bind $w.msg <Destroy> [list set tk::Priv(button) $cancel]
+
+ # 7. Withdraw the window, then update all the geometry information
+ # so we know how big it wants to be, then center the window in the
+ # display (Motif style) and de-iconify it.
+
+ ::tk::PlaceWindow $w widget $data(-parent)
+
+ # 8. Set a grab and claim the focus too.
+
+ if {$data(-default) ne ""} {
+ set focus $w.$data(-default)
+ } else {
+ set focus $w
+ }
+ ::tk::SetFocusGrab $w $focus
+
+ # 9. Wait for the user to respond, then restore the focus and
+ # return the index of the selected button. Restore the focus
+ # before deleting the window, since otherwise the window manager
+ # may take the focus away so we can't redirect it. Finally,
+ # restore any grab that was in effect.
+
+ vwait ::tk::Priv(button)
+ # Copy the result now so any <Destroy> that happens won't cause
+ # trouble
+ set result $Priv(button)
+
+ ::tk::RestoreFocusGrab $w $focus
+
+ return $result
+}
diff --git a/tk8.6/library/msgs/cs.msg b/tk8.6/library/msgs/cs.msg
new file mode 100644
index 0000000..d6be730
--- /dev/null
+++ b/tk8.6/library/msgs/cs.msg
@@ -0,0 +1,77 @@
+namespace eval ::tk {
+ ::msgcat::mcset cs "&Abort" "&P\u0159eru\u0161it"
+ ::msgcat::mcset cs "&About..." "&O programu..."
+ ::msgcat::mcset cs "All Files" "V\u0161echny soubory"
+ ::msgcat::mcset cs "Application Error" "Chyba programu"
+ ::msgcat::mcset cs "Bold Italic"
+ ::msgcat::mcset cs "&Blue" "&Modr\341"
+ ::msgcat::mcset cs "Cancel" "Zru\u0161it"
+ ::msgcat::mcset cs "&Cancel" "&Zru\u0161it"
+ ::msgcat::mcset cs "Cannot change to the directory \"%1\$s\".\nPermission denied." "Nemohu zm\u011bnit atku\341ln\355 adres\341\u0159 na \"%1\$s\".\nP\u0159\355stup odm\355tnut."
+ ::msgcat::mcset cs "Choose Directory" "V\375b\u011br adres\341\u0159e"
+ ::msgcat::mcset cs "Cl&ear" "Sma&zat"
+ ::msgcat::mcset cs "&Clear Console" "&Smazat konzolu"
+ ::msgcat::mcset cs "Color" "Barva"
+ ::msgcat::mcset cs "Console" "Konzole"
+ ::msgcat::mcset cs "&Copy" "&Kop\355rovat"
+ ::msgcat::mcset cs "Cu&t" "V&y\u0159\355znout"
+ ::msgcat::mcset cs "&Delete" "&Smazat"
+ ::msgcat::mcset cs "Details >>" "Detaily >>"
+ ::msgcat::mcset cs "Directory \"%1\$s\" does not exist." "Adres\341\u0159 \"%1\$s\" neexistuje."
+ ::msgcat::mcset cs "&Directory:" "&Adres\341\u0159:"
+ ::msgcat::mcset cs "&Edit" "&\332pravy"
+ ::msgcat::mcset cs "Error: %1\$s" "Chyba: %1\$s"
+ ::msgcat::mcset cs "E&xit" "&Konec"
+ ::msgcat::mcset cs "&File" "&Soubor"
+ ::msgcat::mcset cs "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Soubor \"%1\$s\" ji\u017e existuje.\nChcete jej p\u0159epsat?"
+ ::msgcat::mcset cs "File \"%1\$s\" already exists.\n\n" "Soubor \"%1\$s\" ji\u017e existuje.\n\n"
+ ::msgcat::mcset cs "File \"%1\$s\" does not exist." "Soubor \"%1\$s\" neexistuje."
+ ::msgcat::mcset cs "File &name:" "&Jm\351no souboru:"
+ ::msgcat::mcset cs "File &names:" "&Jm\351na soubor\u016f:"
+ ::msgcat::mcset cs "Files of &type:" "&Typy soubor\u016f:"
+ ::msgcat::mcset cs "Fi&les:" "Sou&bory:"
+ ::msgcat::mcset cs "&Filter" "&Filtr"
+ ::msgcat::mcset cs "Fil&ter:" "Fil&tr:"
+ ::msgcat::mcset cs "Font st&yle:"
+ ::msgcat::mcset cs "&Green" "Ze&len\341"
+ ::msgcat::mcset cs "&Help" "&N\341pov\u011bda"
+ ::msgcat::mcset cs "Hi" "Ahoj"
+ ::msgcat::mcset cs "&Hide Console" "&Schovat Konzolu"
+ ::msgcat::mcset cs "&Ignore" "&Ignorovat"
+ ::msgcat::mcset cs "Invalid file name \"%1\$s\"." "\u0160patn\351 jm\351no souboru \"%1\$s\"."
+ ::msgcat::mcset cs "Log Files" "Log soubory"
+ ::msgcat::mcset cs "&No" "&Ne"
+ ::msgcat::mcset cs "&OK"
+ ::msgcat::mcset cs "OK"
+ ::msgcat::mcset cs "Ok"
+ ::msgcat::mcset cs "Open" "Otev\u0159\355t"
+ ::msgcat::mcset cs "&Open" "&Otev\u0159\355t"
+ ::msgcat::mcset cs "Open Multiple Files" "Otev\u0159\355t v\355ce soubor\u016f"
+ ::msgcat::mcset cs "P&aste" "&Vlo\u017eit"
+ ::msgcat::mcset cs "&Quit" "&Ukon\u010dit"
+ ::msgcat::mcset cs "&Red" "\u010ce&rven\341"
+ ::msgcat::mcset cs "Replace existing file?" "Nahradit st\341vaj\355c\355 soubor?"
+ ::msgcat::mcset cs "&Retry" "Z&novu"
+ ::msgcat::mcset cs "&Save" "&Ulo\u017eit"
+ ::msgcat::mcset cs "Save As" "Ulo\u017eit jako"
+ ::msgcat::mcset cs "Save To Log" "Ulo\u017eit do logu"
+ ::msgcat::mcset cs "Select Log File" "Vybrat log soubor"
+ ::msgcat::mcset cs "Select a file to source" "Vybrat soubor k nahr\341n\355"
+ ::msgcat::mcset cs "&Selection:" "&V\375b\u011br:"
+ ::msgcat::mcset cs "Skip Messages" "P\u0159esko\u010dit zpr\341vy"
+ ::msgcat::mcset cs "&Source..." "&Zdroj..."
+ ::msgcat::mcset cs "Tcl Scripts" "Tcl skripty"
+ ::msgcat::mcset cs "Tcl for Windows" "Tcl pro Windows"
+ ::msgcat::mcset cs "Text Files" "Textov\351 soubory"
+ ::msgcat::mcset cs "abort" "p\u0159eru\u0161it"
+ ::msgcat::mcset cs "blue" "modr\341"
+ ::msgcat::mcset cs "cancel" "zru\u0161it"
+ ::msgcat::mcset cs "extension" "p\u0159\355pona"
+ ::msgcat::mcset cs "extensions" "p\u0159\355pony"
+ ::msgcat::mcset cs "green" "zelen\341"
+ ::msgcat::mcset cs "ignore" "ignorovat"
+ ::msgcat::mcset cs "ok"
+ ::msgcat::mcset cs "red" "\u010derven\341"
+ ::msgcat::mcset cs "retry" "znovu"
+ ::msgcat::mcset cs "yes" "ano"
+}
diff --git a/tk8.6/library/msgs/da.msg b/tk8.6/library/msgs/da.msg
new file mode 100644
index 0000000..c302c79
--- /dev/null
+++ b/tk8.6/library/msgs/da.msg
@@ -0,0 +1,78 @@
+namespace eval ::tk {
+ ::msgcat::mcset da "&Abort" "&Afbryd"
+ ::msgcat::mcset da "&About..." "&Om..."
+ ::msgcat::mcset da "All Files" "Alle filer"
+ ::msgcat::mcset da "Application Error" "Programfejl"
+ ::msgcat::mcset da "&Blue" "&Bl\u00E5"
+ ::msgcat::mcset da "Cancel" "Annuller"
+ ::msgcat::mcset da "&Cancel" "&Annuller"
+ ::msgcat::mcset da "Cannot change to the directory \"%1\$s\".\nPermission denied." "Kan ikke skifte til katalog \"%1\$s\".\nIngen rettigheder."
+ ::msgcat::mcset da "Choose Directory" "V\u00E6lg katalog"
+ ::msgcat::mcset da "Cl&ear" "&Ryd"
+ ::msgcat::mcset da "&Clear Console" "&Ryd konsolen"
+ ::msgcat::mcset da "Color" "Farve"
+ ::msgcat::mcset da "Console" "Konsol"
+ ::msgcat::mcset da "&Copy" "&Kopier"
+ ::msgcat::mcset da "Cu&t" "Kli&p"
+ ::msgcat::mcset da "&Delete" "&Slet"
+ ::msgcat::mcset da "Details >>" "Detailer"
+ ::msgcat::mcset da "Directory \"%1\$s\" does not exist." "Katalog \"%1\$s\" findes ikke."
+ ::msgcat::mcset da "&Directory:" "&Katalog:"
+ ::msgcat::mcset da "&Edit" "&Rediger"
+ ::msgcat::mcset da "Error: %1\$s" "Fejl: %1\$s"
+ ::msgcat::mcset da "E&xit" "&Afslut"
+ ::msgcat::mcset da "&File" "&Fil"
+ ::msgcat::mcset da "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Filen \"%1\$s\" findes allerede.\nSkal den overskrives?"
+ ::msgcat::mcset da "File \"%1\$s\" already exists.\n\n" "Filen \"%1\$s\" findes allerede.\n\n"
+ ::msgcat::mcset da "File \"%1\$s\" does not exist." "Filen \"%1\$s\" findes ikke."
+ ::msgcat::mcset da "File &name:" "Fil&navn:"
+ ::msgcat::mcset da "File &names:" "Fil&navne:"
+ ::msgcat::mcset da "Files of &type:" "Fil&typer:"
+ ::msgcat::mcset da "Fi&les:" "Fi&ler:"
+ ::msgcat::mcset da "&Filter"
+ ::msgcat::mcset da "Fil&ter:"
+ ::msgcat::mcset da "&Green" "&Gr\u00F8n"
+ ::msgcat::mcset da "&Help" "&Hj\u00E6lp"
+ ::msgcat::mcset da "Hi" "Hej"
+ ::msgcat::mcset da "&Hide Console" "Skjul &konsol"
+ ::msgcat::mcset da "&Ignore" "&Ignorer"
+ ::msgcat::mcset da "Invalid file name \"%1\$s\"." "Ugyldig fil navn \"%1\$s\"."
+ ::msgcat::mcset da "Log Files" "Logfiler"
+ ::msgcat::mcset da "&No" "&Nej"
+ ::msgcat::mcset da "&OK" "&O.K."
+ ::msgcat::mcset da "OK" "O.K."
+ ::msgcat::mcset da "Ok"
+ ::msgcat::mcset da "Open" "\u00C5bn"
+ ::msgcat::mcset da "&Open" "&\u00C5bn"
+ ::msgcat::mcset da "Open Multiple Files" "\u00C5bn flere filer"
+ ::msgcat::mcset da "P&aste" "&Inds\u00E6t"
+ ::msgcat::mcset da "&Quit" "&Afslut"
+ ::msgcat::mcset da "&Red" "&R\u00F8d"
+ ::msgcat::mcset da "Replace existing file?" "Erstat eksisterende fil?"
+ ::msgcat::mcset da "&Retry" "&Gentag"
+ ::msgcat::mcset da "&Save" "&Gem"
+ ::msgcat::mcset da "Save As" "Gem som"
+ ::msgcat::mcset da "Save To Log" "Gem i log"
+ ::msgcat::mcset da "Select Log File" "V\u00E6lg logfil"
+ ::msgcat::mcset da "Select a file to source" "V\u00E6lg k\u00F8rbar fil"
+ ::msgcat::mcset da "&Selection:" "&Udvalg:"
+ ::msgcat::mcset da "Show &Hidden Directories" "Vis &skjulte kataloger"
+ ::msgcat::mcset da "Show &Hidden Files and Directories" "Vis &skjulte filer og kataloger"
+ ::msgcat::mcset da "Skip Messages" "Overspring beskeder"
+ ::msgcat::mcset da "&Source..." "&K\u00F8r..."
+ ::msgcat::mcset da "Tcl Scripts" "Tcl-Skripter"
+ ::msgcat::mcset da "Tcl for Windows" "Tcl for Windows"
+ ::msgcat::mcset da "Text Files" "Tekstfiler"
+ ::msgcat::mcset da "&Yes" "&Ja"
+ ::msgcat::mcset da "abort" "afbryd"
+ ::msgcat::mcset da "blue" "bl\u00E5"
+ ::msgcat::mcset da "cancel" "afbryd"
+ ::msgcat::mcset da "extension"
+ ::msgcat::mcset da "extensions"
+ ::msgcat::mcset da "green" "gr\u00F8n"
+ ::msgcat::mcset da "ignore" "ignorer"
+ ::msgcat::mcset da "ok"
+ ::msgcat::mcset da "red" "r\u00F8d"
+ ::msgcat::mcset da "retry" "gentag"
+ ::msgcat::mcset da "yes" "ja"
+}
diff --git a/tk8.6/library/msgs/de.msg b/tk8.6/library/msgs/de.msg
new file mode 100644
index 0000000..e420f8a
--- /dev/null
+++ b/tk8.6/library/msgs/de.msg
@@ -0,0 +1,91 @@
+namespace eval ::tk {
+ ::msgcat::mcset de "&Abort" "&Abbruch"
+ ::msgcat::mcset de "&About..." "&\u00dcber..."
+ ::msgcat::mcset de "All Files" "Alle Dateien"
+ ::msgcat::mcset de "Application Error" "Applikationsfehler"
+ ::msgcat::mcset de "&Apply" "&Anwenden"
+ ::msgcat::mcset de "Bold" "Fett"
+ ::msgcat::mcset de "Bold Italic" "Fett kursiv"
+ ::msgcat::mcset de "&Blue" "&Blau"
+ ::msgcat::mcset de "Cancel" "Abbruch"
+ ::msgcat::mcset de "&Cancel" "&Abbruch"
+ ::msgcat::mcset de "Cannot change to the directory \"%1\$s\".\nPermission denied." "Kann nicht in das Verzeichnis \"%1\$s\" wechseln.\nKeine Rechte vorhanden."
+ ::msgcat::mcset de "Choose Directory" "W\u00e4hle Verzeichnis"
+ ::msgcat::mcset de "Cl&ear" "&R\u00fccksetzen"
+ ::msgcat::mcset de "&Clear Console" "&Konsole l\u00f6schen"
+ ::msgcat::mcset de "Color" "Farbe"
+ ::msgcat::mcset de "Console" "Konsole"
+ ::msgcat::mcset de "&Copy" "&Kopieren"
+ ::msgcat::mcset de "Cu&t" "Aus&schneiden"
+ ::msgcat::mcset de "&Delete" "&L\u00f6schen"
+ ::msgcat::mcset de "Details >>"
+ ::msgcat::mcset de "Directory \"%1\$s\" does not exist." "Das Verzeichnis \"%1\$s\" existiert nicht."
+ ::msgcat::mcset de "&Directory:" "&Verzeichnis:"
+ ::msgcat::mcset de "&Edit" "&Bearbeiten"
+ ::msgcat::mcset de "Effects" "Effekte"
+ ::msgcat::mcset de "Error: %1\$s" "Fehler: %1\$s"
+ ::msgcat::mcset de "E&xit" "&Ende"
+ ::msgcat::mcset de "&File" "&Datei"
+ ::msgcat::mcset de "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Die Datei \"%1\$s\" ist bereits vorhanden.\nWollen sie diese Datei \u00fcberschreiben ?"
+ ::msgcat::mcset de "File \"%1\$s\" already exists.\n\n" "Die Datei \"%1\$s\" ist bereits vorhanden.\n\n"
+ ::msgcat::mcset de "File \"%1\$s\" does not exist." "Die Datei \"%1\$s\" existiert nicht."
+ ::msgcat::mcset de "File &name:" "Datei&name:"
+ ::msgcat::mcset de "File &names:" "Datei&namen:"
+ ::msgcat::mcset de "Files of &type:" "Dateien des &Typs:"
+ ::msgcat::mcset de "Fi&les:" "Dat&eien:"
+ ::msgcat::mcset de "&Filter"
+ ::msgcat::mcset de "Fil&ter:"
+ ::msgcat::mcset de "Font" "Schriftart"
+ ::msgcat::mcset de "&Font:" "Schriftart:"
+ ::msgcat::mcset de "Font st&yle:" "Schriftschnitt:"
+ ::msgcat::mcset de "&Green" "&Gr\u00fcn"
+ ::msgcat::mcset de "&Help" "&Hilfe"
+ ::msgcat::mcset de "Hi" "Hallo"
+ ::msgcat::mcset de "&Hide Console" "&Konsole unsichtbar machen"
+ ::msgcat::mcset de "&Ignore" "&Ignorieren"
+ ::msgcat::mcset de "Invalid file name \"%1\$s\"." "Ung\u00fcltiger Dateiname \"%1\$s\"."
+ ::msgcat::mcset de "Italic" "Kursiv"
+ ::msgcat::mcset de "Log Files" "Protokolldatei"
+ ::msgcat::mcset de "&No" "&Nein"
+ ::msgcat::mcset de "&OK"
+ ::msgcat::mcset de "OK"
+ ::msgcat::mcset de "Ok"
+ ::msgcat::mcset de "Open" "\u00d6ffnen"
+ ::msgcat::mcset de "&Open" "\u00d6&ffnen"
+ ::msgcat::mcset de "Open Multiple Files" "Mehrere Dateien \u00F6ffnen"
+ ::msgcat::mcset de "P&aste" "E&inf\u00fcgen"
+ ::msgcat::mcset de "&Quit" "&Beenden"
+ ::msgcat::mcset de "&Red" "&Rot"
+ ::msgcat::mcset de "Regular" "Standard"
+ ::msgcat::mcset de "Replace existing file?" "Existierende Datei ersetzen?"
+ ::msgcat::mcset de "&Retry" "&Wiederholen"
+ ::msgcat::mcset de "Sample" "Beispiel"
+ ::msgcat::mcset de "&Save" "&Speichern"
+ ::msgcat::mcset de "Save As" "Speichern unter"
+ ::msgcat::mcset de "Save To Log" "In Protokoll speichern"
+ ::msgcat::mcset de "Select Log File" "Protokolldatei ausw\u00e4hlen"
+ ::msgcat::mcset de "Select a file to source" "Auszuf\u00fchrende Datei ausw\u00e4hlen"
+ ::msgcat::mcset de "&Selection:" "Auswah&l:"
+ ::msgcat::mcset de "&Size:" "Schriftgrad:"
+ ::msgcat::mcset de "Show &Hidden Directories" "Zeige versteckte Dateien"
+ ::msgcat::mcset de "Show &Hidden Files and Directories" "Zeige versteckte Dateien und Verzeichnisse"
+ ::msgcat::mcset de "Skip Messages" "Weitere Nachrichten \u00fcberspringen"
+ ::msgcat::mcset de "&Source..." "&Ausf\u00fchren..."
+ ::msgcat::mcset de "Stri&keout" "&Durchgestrichen"
+ ::msgcat::mcset de "Tcl Scripts" "Tcl-Skripte"
+ ::msgcat::mcset de "Tcl for Windows" "Tcl f\u00fcr Windows"
+ ::msgcat::mcset de "Text Files" "Textdateien"
+ ::msgcat::mcset de "&Underline" "&Unterstrichen"
+ ::msgcat::mcset de "&Yes" "&Ja"
+ ::msgcat::mcset de "abort" "abbrechen"
+ ::msgcat::mcset de "blue" "blau"
+ ::msgcat::mcset de "cancel" "abbrechen"
+ ::msgcat::mcset de "extension" "Erweiterung"
+ ::msgcat::mcset de "extensions" "Erweiterungen"
+ ::msgcat::mcset de "green" "gr\u00fcn"
+ ::msgcat::mcset de "ignore" "ignorieren"
+ ::msgcat::mcset de "ok"
+ ::msgcat::mcset de "red" "rot"
+ ::msgcat::mcset de "retry" "wiederholen"
+ ::msgcat::mcset de "yes" "ja"
+}
diff --git a/tk8.6/library/msgs/el.msg b/tk8.6/library/msgs/el.msg
new file mode 100644
index 0000000..2e3f236
--- /dev/null
+++ b/tk8.6/library/msgs/el.msg
@@ -0,0 +1,86 @@
+## Messages for the Greek (Hellenic - "el") language.
+## Please report any changes/suggestions to:
+## petasis@iit.demokritos.gr
+
+namespace eval ::tk {
+ ::msgcat::mcset el "&Abort" "\u03a4\u03b5\u03c1\u03bc\u03b1\u03c4\u03b9\u03c3\u03bc\u03cc\u03c2"
+ ::msgcat::mcset el "About..." "\u03a3\u03c7\u03b5\u03c4\u03b9\u03ba\u03ac..."
+ ::msgcat::mcset el "All Files" "\u038c\u03bb\u03b1 \u03c4\u03b1 \u0391\u03c1\u03c7\u03b5\u03af\u03b1"
+ ::msgcat::mcset el "Application Error" "\u039b\u03ac\u03b8\u03bf\u03c2 \u0395\u03c6\u03b1\u03c1\u03bc\u03bf\u03b3\u03ae\u03c2"
+ ::msgcat::mcset el "&Blue" "\u039c\u03c0\u03bb\u03b5"
+ ::msgcat::mcset el "&Cancel" "\u0391\u03ba\u03cd\u03c1\u03c9\u03c3\u03b7"
+ ::msgcat::mcset el \
+"Cannot change to the directory \"%1\$s\".\nPermission denied." \
+"\u0394\u03b5\u03bd \u03b5\u03af\u03bd\u03b1\u03b9 \u03b4\u03c5\u03bd\u03b1\u03c4\u03ae \u03b7 \u03b1\u03bb\u03bb\u03b1\u03b3\u03ae \u03ba\u03b1\u03c4\u03b1\u03bb\u03cc\u03b3\u03bf\u03c5 \u03c3\u03b5 \"%1\$s\".\n\u0397 \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7 \u03b4\u03b5\u03bd \u03b5\u03c0\u03b9\u03c4\u03c1\u03ad\u03c0\u03b5\u03c4\u03b1\u03b9."
+ ::msgcat::mcset el "Choose Directory" "\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae \u039a\u03b1\u03c4\u03b1\u03bb\u03cc\u03b3\u03bf\u03c5"
+ ::msgcat::mcset el "Clear" "\u039a\u03b1\u03b8\u03b1\u03c1\u03b9\u03c3\u03bc\u03cc\u03c2"
+ ::msgcat::mcset el "Color" "\u03a7\u03c1\u03ce\u03bc\u03b1"
+ ::msgcat::mcset el "Console" "\u039a\u03bf\u03bd\u03c3\u03cc\u03bb\u03b1"
+ ::msgcat::mcset el "Copy" "\u0391\u03bd\u03c4\u03b9\u03b3\u03c1\u03b1\u03c6\u03ae"
+ ::msgcat::mcset el "Cut" "\u0391\u03c0\u03bf\u03ba\u03bf\u03c0\u03ae"
+ ::msgcat::mcset el "Delete" "\u0394\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae"
+ ::msgcat::mcset el "Details >>" "\u039b\u03b5\u03c0\u03c4\u03bf\u03bc\u03ad\u03c1\u03b5\u03b9\u03b5\u03c2 >>"
+ ::msgcat::mcset el "Directory \"%1\$s\" does not exist." \
+ "\u039f \u03ba\u03b1\u03c4\u03ac\u03bb\u03bf\u03b3\u03bf\u03c2 \"%1\$s\" \u03b4\u03b5\u03bd \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9."
+ ::msgcat::mcset el "&Directory:" "&\u039a\u03b1\u03c4\u03ac\u03bb\u03bf\u03b3\u03bf\u03c2:"
+ ::msgcat::mcset el "Error: %1\$s" "\u039b\u03ac\u03b8\u03bf\u03c2: %1\$s"
+ ::msgcat::mcset el "Exit" "\u0388\u03be\u03bf\u03b4\u03bf\u03c2"
+ ::msgcat::mcset el \
+ "File \"%1\$s\" already exists.\nDo you want to overwrite it?" \
+ "\u03a4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \"%1\$s\" \u03ae\u03b4\u03b7 \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9.\n\u0398\u03ad\u03bb\u03b5\u03c4\u03b5 \u03bd\u03b1 \u03b5\u03c0\u03b9\u03ba\u03b1\u03bb\u03c5\u03c6\u03b8\u03b5\u03af;"
+ ::msgcat::mcset el "File \"%1\$s\" already exists.\n\n" \
+ "\u03a4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \"%1\$s\" \u03ae\u03b4\u03b7 \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9.\n\n"
+ ::msgcat::mcset el "File \"%1\$s\" does not exist." \
+ "\u03a4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \"%1\$s\" \u03b4\u03b5\u03bd \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9."
+ ::msgcat::mcset el "File &name:" "\u038c&\u03bd\u03bf\u03bc\u03b1 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5:"
+ ::msgcat::mcset el "File &names:" "\u038c&\u03bd\u03bf\u03bc\u03b1 \u03b1\u03c1\u03c7\u03b5\u03af\u03c9\u03bd:"
+ ::msgcat::mcset el "Files of &type:" "\u0391\u03c1\u03c7\u03b5\u03af\u03b1 \u03c4\u03bf\u03c5 &\u03c4\u03cd\u03c0\u03bf\u03c5:"
+ ::msgcat::mcset el "Fi&les:" "\u0391\u03c1\u03c7\u03b5\u03af\u03b1:"
+ ::msgcat::mcset el "&Filter" "\u03a6\u03af\u03bb\u03c4\u03c1\u03bf"
+ ::msgcat::mcset el "Fil&ter:" "\u03a6\u03af\u03bb\u03c4\u03c1\u03bf:"
+ ::msgcat::mcset el "&Green" "\u03a0\u03c1\u03ac\u03c3\u03b9\u03bd\u03bf"
+ ::msgcat::mcset el "Hi" "\u0393\u03b5\u03b9\u03b1"
+ ::msgcat::mcset el "Hide Console" "\u0391\u03c0\u03cc\u03ba\u03c1\u03c5\u03c8\u03b7 \u03ba\u03bf\u03bd\u03c3\u03cc\u03bb\u03b1\u03c2"
+ ::msgcat::mcset el "&Ignore" "\u0391\u03b3\u03bd\u03cc\u03b7\u03c3\u03b7"
+ ::msgcat::mcset el "Invalid file name \"%1\$s\"." \
+ "\u0386\u03ba\u03c5\u03c1\u03bf \u03cc\u03bd\u03bf\u03bc\u03b1 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5 \"%1\$s\"."
+ ::msgcat::mcset el "Log Files" "\u0391\u03c1\u03c7\u03b5\u03af\u03b1 \u039a\u03b1\u03c4\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae\u03c2"
+ ::msgcat::mcset el "&No" "\u038c\u03c7\u03b9"
+ ::msgcat::mcset el "&OK" "\u0395\u03bd\u03c4\u03ac\u03be\u03b5\u03b9"
+ ::msgcat::mcset el "OK" "\u0395\u03bd\u03c4\u03ac\u03be\u03b5\u03b9"
+ ::msgcat::mcset el "Ok" "\u0395\u03bd\u03c4\u03ac\u03be\u03b5\u03b9"
+ ::msgcat::mcset el "Open" "\u0386\u03bd\u03bf\u03b9\u03b3\u03bc\u03b1"
+ ::msgcat::mcset el "&Open" "\u0386\u03bd\u03bf\u03b9\u03b3\u03bc\u03b1"
+ ::msgcat::mcset el "Open Multiple Files" \
+ "\u0386\u03bd\u03bf\u03b9\u03b3\u03bc\u03b1 \u03c0\u03bf\u03bb\u03bb\u03b1\u03c0\u03bb\u03ce\u03bd \u03b1\u03c1\u03c7\u03b5\u03af\u03c9\u03bd"
+ ::msgcat::mcset el "P&aste" "\u0395\u03c0\u03b9\u03ba\u03cc\u03bb\u03bb\u03b7\u03c3\u03b7"
+ ::msgcat::mcset el "Quit" "\u0388\u03be\u03bf\u03b4\u03bf\u03c2"
+ ::msgcat::mcset el "&Red" "\u039a\u03cc\u03ba\u03ba\u03b9\u03bd\u03bf"
+ ::msgcat::mcset el "Replace existing file?" \
+ "\u0395\u03c0\u03b9\u03ba\u03ac\u03bb\u03c5\u03c8\u03b7 \u03c5\u03c0\u03ac\u03c1\u03c7\u03bf\u03bd\u03c4\u03bf\u03c2 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5;"
+ ::msgcat::mcset el "&Retry" "\u03a0\u03c1\u03bf\u03c3\u03c0\u03ac\u03b8\u03b7\u03c3\u03b5 \u03be\u03b1\u03bd\u03ac"
+ ::msgcat::mcset el "&Save" "\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7"
+ ::msgcat::mcset el "Save As" "\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7 \u03c3\u03b1\u03bd"
+ ::msgcat::mcset el "Save To Log" "\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7 \u03c3\u03c4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03ba\u03b1\u03c4\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae\u03c2"
+ ::msgcat::mcset el "Select Log File" "\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5 \u03ba\u03b1\u03c4\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae\u03c2"
+ ::msgcat::mcset el "Select a file to source" \
+ "\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03b3\u03b9\u03b1 \u03b5\u03ba\u03c4\u03ad\u03bb\u03b5\u03c3\u03b7"
+ ::msgcat::mcset el "&Selection:" "\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae:"
+ ::msgcat::mcset el "Skip Messages" "\u0391\u03c0\u03bf\u03c6\u03c5\u03b3\u03ae\u03bc\u03b7\u03bd\u03c5\u03bc\u03ac\u03c4\u03c9\u03bd"
+ ::msgcat::mcset el "&Source..." "\u0395\u03ba\u03c4\u03ad\u03bb\u03b5\u03c3\u03b7..."
+ ::msgcat::mcset el "Tcl Scripts" "Tcl Scripts"
+ ::msgcat::mcset el "Tcl for Windows" "Tcl \u03b3\u03b9\u03b1 Windows"
+ ::msgcat::mcset el "Text Files" "\u0391\u03c1\u03c7\u03b5\u03af\u03b1 \u039a\u03b5\u03b9\u03bc\u03ad\u03bd\u03bf\u03c5"
+ ::msgcat::mcset el "&Yes" "\u039d\u03b1\u03b9"
+ ::msgcat::mcset el "abort" "\u03c4\u03b5\u03c1\u03bc\u03b1\u03c4\u03b9\u03c3\u03bc\u03cc\u03c2"
+ ::msgcat::mcset el "blue" "\u03bc\u03c0\u03bb\u03b5"
+ ::msgcat::mcset el "cancel" "\u03b1\u03ba\u03cd\u03c1\u03c9\u03c3\u03b7"
+ ::msgcat::mcset el "extension" "\u03b5\u03c0\u03ad\u03ba\u03c4\u03b1\u03c3\u03b7"
+ ::msgcat::mcset el "extensions" "\u03b5\u03c0\u03b5\u03ba\u03c4\u03ac\u03c3\u03b5\u03b9\u03c2"
+ ::msgcat::mcset el "green" "\u03c0\u03c1\u03ac\u03c3\u03b9\u03bd\u03bf"
+ ::msgcat::mcset el "ignore" "\u03b1\u03b3\u03bd\u03cc\u03b7\u03c3\u03b7"
+ ::msgcat::mcset el "ok" "\u03b5\u03bd\u03c4\u03ac\u03be\u03b5\u03b9"
+ ::msgcat::mcset el "red" "\u03ba\u03cc\u03ba\u03ba\u03b9\u03bd\u03bf"
+ ::msgcat::mcset el "retry" "\u03c0\u03c1\u03bf\u03c3\u03c0\u03ac\u03b8\u03b7\u03c3\u03b5 \u03be\u03b1\u03bd\u03ac"
+ ::msgcat::mcset el "yes" "\u03bd\u03b1\u03b9"
+}
diff --git a/tk8.6/library/msgs/en.msg b/tk8.6/library/msgs/en.msg
new file mode 100644
index 0000000..5ad1094
--- /dev/null
+++ b/tk8.6/library/msgs/en.msg
@@ -0,0 +1,91 @@
+namespace eval ::tk {
+ ::msgcat::mcset en "&Abort"
+ ::msgcat::mcset en "&About..."
+ ::msgcat::mcset en "All Files"
+ ::msgcat::mcset en "Application Error"
+ ::msgcat::mcset en "&Apply"
+ ::msgcat::mcset en "Bold"
+ ::msgcat::mcset en "Bold Italic"
+ ::msgcat::mcset en "&Blue"
+ ::msgcat::mcset en "Cancel"
+ ::msgcat::mcset en "&Cancel"
+ ::msgcat::mcset en "Cannot change to the directory \"%1\$s\".\nPermission denied."
+ ::msgcat::mcset en "Choose Directory"
+ ::msgcat::mcset en "Cl&ear"
+ ::msgcat::mcset en "&Clear Console"
+ ::msgcat::mcset en "Color"
+ ::msgcat::mcset en "Console"
+ ::msgcat::mcset en "&Copy"
+ ::msgcat::mcset en "Cu&t"
+ ::msgcat::mcset en "&Delete"
+ ::msgcat::mcset en "Details >>"
+ ::msgcat::mcset en "Directory \"%1\$s\" does not exist."
+ ::msgcat::mcset en "&Directory:"
+ ::msgcat::mcset en "&Edit"
+ ::msgcat::mcset en "Effects"
+ ::msgcat::mcset en "Error: %1\$s"
+ ::msgcat::mcset en "E&xit"
+ ::msgcat::mcset en "&File"
+ ::msgcat::mcset en "File \"%1\$s\" already exists.\nDo you want to overwrite it?"
+ ::msgcat::mcset en "File \"%1\$s\" already exists.\n\n"
+ ::msgcat::mcset en "File \"%1\$s\" does not exist."
+ ::msgcat::mcset en "File &name:"
+ ::msgcat::mcset en "File &names:"
+ ::msgcat::mcset en "Files of &type:"
+ ::msgcat::mcset en "Fi&les:"
+ ::msgcat::mcset en "&Filter"
+ ::msgcat::mcset en "Fil&ter:"
+ ::msgcat::mcset en "Font"
+ ::msgcat::mcset en "&Font:"
+ ::msgcat::mcset en "Font st&yle:"
+ ::msgcat::mcset en "&Green"
+ ::msgcat::mcset en "&Help"
+ ::msgcat::mcset en "Hi"
+ ::msgcat::mcset en "&Hide Console"
+ ::msgcat::mcset en "&Ignore"
+ ::msgcat::mcset en "Invalid file name \"%1\$s\"."
+ ::msgcat::mcset en "Italic"
+ ::msgcat::mcset en "Log Files"
+ ::msgcat::mcset en "&No"
+ ::msgcat::mcset en "&OK"
+ ::msgcat::mcset en "OK"
+ ::msgcat::mcset en "Ok"
+ ::msgcat::mcset en "Open"
+ ::msgcat::mcset en "&Open"
+ ::msgcat::mcset en "Open Multiple Files"
+ ::msgcat::mcset en "P&aste"
+ ::msgcat::mcset en "&Quit"
+ ::msgcat::mcset en "&Red"
+ ::msgcat::mcset en "Regular"
+ ::msgcat::mcset en "Replace existing file?"
+ ::msgcat::mcset en "&Retry"
+ ::msgcat::mcset en "Sample"
+ ::msgcat::mcset en "&Save"
+ ::msgcat::mcset en "Save As"
+ ::msgcat::mcset en "Save To Log"
+ ::msgcat::mcset en "Select Log File"
+ ::msgcat::mcset en "Select a file to source"
+ ::msgcat::mcset en "&Selection:"
+ ::msgcat::mcset en "&Size:"
+ ::msgcat::mcset en "Show &Hidden Directories"
+ ::msgcat::mcset en "Show &Hidden Files and Directories"
+ ::msgcat::mcset en "Skip Messages"
+ ::msgcat::mcset en "&Source..."
+ ::msgcat::mcset en "Stri&keout"
+ ::msgcat::mcset en "Tcl Scripts"
+ ::msgcat::mcset en "Tcl for Windows"
+ ::msgcat::mcset en "Text Files"
+ ::msgcat::mcset en "&Underline"
+ ::msgcat::mcset en "&Yes"
+ ::msgcat::mcset en "abort"
+ ::msgcat::mcset en "blue"
+ ::msgcat::mcset en "cancel"
+ ::msgcat::mcset en "extension"
+ ::msgcat::mcset en "extensions"
+ ::msgcat::mcset en "green"
+ ::msgcat::mcset en "ignore"
+ ::msgcat::mcset en "ok"
+ ::msgcat::mcset en "red"
+ ::msgcat::mcset en "retry"
+ ::msgcat::mcset en "yes"
+}
diff --git a/tk8.6/library/msgs/en_gb.msg b/tk8.6/library/msgs/en_gb.msg
new file mode 100644
index 0000000..efafa38
--- /dev/null
+++ b/tk8.6/library/msgs/en_gb.msg
@@ -0,0 +1,3 @@
+namespace eval ::tk {
+ ::msgcat::mcset en_gb Color Colour
+}
diff --git a/tk8.6/library/msgs/eo.msg b/tk8.6/library/msgs/eo.msg
new file mode 100644
index 0000000..3645630
--- /dev/null
+++ b/tk8.6/library/msgs/eo.msg
@@ -0,0 +1,75 @@
+namespace eval ::tk {
+ ::msgcat::mcset eo "&Abort" "&\u0108esigo"
+ ::msgcat::mcset eo "&About..." "Pri..."
+ ::msgcat::mcset eo "All Files" "\u0108ioj dosieroj"
+ ::msgcat::mcset eo "Application Error" "Aplikoerraro"
+ ::msgcat::mcset eo "&Blue" "&Blua"
+ ::msgcat::mcset eo "Cancel" "Rezignu"
+ ::msgcat::mcset eo "&Cancel" "&Rezignu"
+ ::msgcat::mcset eo "Cannot change to the directory \"%1\$s\".\nPermission denied." "Neeble \u0109angi al dosierulon \"%1\$s\".\nVi ne rajtas tion."
+ ::msgcat::mcset eo "Choose Directory" "Elektu Dosierujo"
+ ::msgcat::mcset eo "Cl&ear" "&Klaru"
+ ::msgcat::mcset eo "&Clear Console" "&Klaru konzolon"
+ ::msgcat::mcset eo "Color" "Farbo"
+ ::msgcat::mcset eo "Console" "Konzolo"
+ ::msgcat::mcset eo "&Copy" "&Kopiu"
+ ::msgcat::mcset eo "Cu&t" "&Enpo\u015digu"
+ ::msgcat::mcset eo "&Delete" "&Forprenu"
+ ::msgcat::mcset eo "Details >>" "Detaloj >>"
+ ::msgcat::mcset eo "Directory \"%1\$s\" does not exist." "La dosierujo \"%1\$s\" ne ekzistas."
+ ::msgcat::mcset eo "&Directory:" "&Dosierujo:"
+ ::msgcat::mcset eo "&Edit" "&Redaktu"
+ ::msgcat::mcset eo "Error: %1\$s" "Eraro: %1\$s"
+ ::msgcat::mcset eo "E&xit" "&Eliru"
+ ::msgcat::mcset eo "&File" "&Dosiero"
+ ::msgcat::mcset eo "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "La dosiero \"%1\$s\" jam ekzistas.\n\u0108u vi volas anstata\u00fbigi la dosieron?"
+ ::msgcat::mcset eo "File \"%1\$s\" already exists.\n\n" "La dosiero \"%1\$s\" jam egzistas. \n\n"
+ ::msgcat::mcset eo "File \"%1\$s\" does not exist." "La dosierp \"%1\$s\" ne estas."
+ ::msgcat::mcset eo "File &name:" "Dosiero&nomo:"
+ ::msgcat::mcset eo "File &names:" "Dosiero&nomoj:"
+ ::msgcat::mcset eo "Files of &type:" "Dosieroj de &Typo:"
+ ::msgcat::mcset eo "Fi&les:" "Do&sieroj:"
+ ::msgcat::mcset eo "&Filter" "&Filtrilo"
+ ::msgcat::mcset eo "Fil&ter:" "&Filtrilo:"
+ ::msgcat::mcset eo "&Green" "&Verda"
+ ::msgcat::mcset eo "&Help" "&Helpu"
+ ::msgcat::mcset eo "Hi" "Saluton"
+ ::msgcat::mcset eo "&Hide Console" "&Ka\u015du konzolon"
+ ::msgcat::mcset eo "&Ignore" "&Ignoru"
+ ::msgcat::mcset eo "Invalid file name \"%1\$s\"." "Malvalida dosieronomo \"%1\$s\"."
+ ::msgcat::mcset eo "Log Files" "Protokolo"
+ ::msgcat::mcset eo "&No" "&Ne"
+ ::msgcat::mcset eo "&OK"
+ ::msgcat::mcset eo "OK"
+ ::msgcat::mcset eo "Ok"
+ ::msgcat::mcset eo "Open" "Malfermu"
+ ::msgcat::mcset eo "&Open" "&Malfermu"
+ ::msgcat::mcset eo "Open Multiple Files" "Melfermu multan dosierojn"
+ ::msgcat::mcset eo "P&aste" "&Elpo\u015digi"
+ ::msgcat::mcset eo "&Quit" "&Finigu"
+ ::msgcat::mcset eo "&Red" "&Rosa"
+ ::msgcat::mcset eo "Replace existing file?" "\u0108u anstata\u00fbu ekzistantan dosieron?"
+ ::msgcat::mcset eo "&Retry" "&Ripetu"
+ ::msgcat::mcset eo "&Save" "&Savu"
+ ::msgcat::mcset eo "Save As" "Savu kiel"
+ ::msgcat::mcset eo "Save To Log" "Savu en protokolon"
+ ::msgcat::mcset eo "Select Log File" "Elektu prokolodosieron"
+ ::msgcat::mcset eo "Select a file to source" "Elektu dosieron por interpreti"
+ ::msgcat::mcset eo "&Selection:" "&Elekto:"
+ ::msgcat::mcset eo "Skip Messages" "transsaltu pluajn mesa\u011dojn"
+ ::msgcat::mcset eo "&Source..." "&Fontoprogramo..."
+ ::msgcat::mcset eo "Tcl Scripts" "Tcl-skriptoj"
+ ::msgcat::mcset eo "Tcl for Windows" "Tcl por vindoso"
+ ::msgcat::mcset eo "Text Files" "Tekstodosierojn"
+ ::msgcat::mcset eo "&Yes" "&Jes"
+ ::msgcat::mcset eo "abort" "\u0109esigo"
+ ::msgcat::mcset eo "blue" "blua"
+ ::msgcat::mcset eo "cancel" "rezignu"
+ ::msgcat::mcset eo "extension" "ekspansio"
+ ::msgcat::mcset eo "extensions" "ekspansioj"
+ ::msgcat::mcset eo "green" "verda"
+ ::msgcat::mcset eo "ignore" "ignorieren"
+ ::msgcat::mcset eo "red" "ru\u011da"
+ ::msgcat::mcset eo "retry" "ripetu"
+ ::msgcat::mcset eo "yes" "jes"
+}
diff --git a/tk8.6/library/msgs/es.msg b/tk8.6/library/msgs/es.msg
new file mode 100644
index 0000000..578c52c
--- /dev/null
+++ b/tk8.6/library/msgs/es.msg
@@ -0,0 +1,76 @@
+namespace eval ::tk {
+ ::msgcat::mcset es "&Abort" "&Abortar"
+ ::msgcat::mcset es "&About..." "&Acerca de ..."
+ ::msgcat::mcset es "All Files" "Todos los archivos"
+ ::msgcat::mcset es "Application Error" "Error de la aplicaci\u00f3n"
+ ::msgcat::mcset es "&Blue" "&Azul"
+ ::msgcat::mcset es "Cancel" "Cancelar"
+ ::msgcat::mcset es "&Cancel" "&Cancelar"
+ ::msgcat::mcset es "Cannot change to the directory \"%1\$s\".\nPermission denied." "No es posible acceder al directorio \"%1\$s\".\nPermiso denegado."
+ ::msgcat::mcset es "Choose Directory" "Elegir directorio"
+ ::msgcat::mcset es "Cl&ear" "&Borrar"
+ ::msgcat::mcset es "&Clear Console" "&Borrar consola"
+ ::msgcat::mcset es "Color"
+ ::msgcat::mcset es "Console" "Consola"
+ ::msgcat::mcset es "&Copy" "&Copiar"
+ ::msgcat::mcset es "Cu&t" "Cor&tar"
+ ::msgcat::mcset es "&Delete" "&Borrar"
+ ::msgcat::mcset es "Details >>" "Detalles >>"
+ ::msgcat::mcset es "Directory \"%1\$s\" does not exist." "El directorio \"%1\$s\" no existe."
+ ::msgcat::mcset es "&Directory:" "&Directorio:"
+ ::msgcat::mcset es "&Edit" "&Editar"
+ ::msgcat::mcset es "Error: %1\$s"
+ ::msgcat::mcset es "E&xit" "Salir"
+ ::msgcat::mcset es "&File" "&Archivo"
+ ::msgcat::mcset es "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "El archivo \"%1\$s\" ya existe.\n\u00bfDesea sobreescribirlo?"
+ ::msgcat::mcset es "File \"%1\$s\" already exists.\n\n" "El archivo \"%1\$s\" ya existe.\n\n"
+ ::msgcat::mcset es "File \"%1\$s\" does not exist." "El archivo \"%1\$s\" no existe."
+ ::msgcat::mcset es "File &name:" "&Nombre de archivo:"
+ ::msgcat::mcset es "File &names:" "&Nombres de archivo:"
+ ::msgcat::mcset es "Files of &type:" "Archivos de &tipo:"
+ ::msgcat::mcset es "Fi&les:" "&Archivos:"
+ ::msgcat::mcset es "&Filter" "&Filtro"
+ ::msgcat::mcset es "Fil&ter:" "Fil&tro:"
+ ::msgcat::mcset es "&Green" "&Verde"
+ ::msgcat::mcset es "&Help" "&Ayuda"
+ ::msgcat::mcset es "Hi" "Hola"
+ ::msgcat::mcset es "&Hide Console" "&Esconder la consola"
+ ::msgcat::mcset es "&Ignore" "&Ignorar"
+ ::msgcat::mcset es "Invalid file name \"%1\$s\"." "Nombre de archivo inv\u00e1lido \"%1\$s\"."
+ ::msgcat::mcset es "Log Files" "Ficheros de traza"
+ ::msgcat::mcset es "&No"
+ ::msgcat::mcset es "&OK"
+ ::msgcat::mcset es "OK"
+ ::msgcat::mcset es "Ok"
+ ::msgcat::mcset es "Open" "Abrir"
+ ::msgcat::mcset es "&Open" "&Abrir"
+ ::msgcat::mcset es "Open Multiple Files" "Abrir m\u00faltiples archivos"
+ ::msgcat::mcset es "P&aste" "Peg&ar"
+ ::msgcat::mcset es "&Quit" "&Abandonar"
+ ::msgcat::mcset es "&Red" "&Rojo"
+ ::msgcat::mcset es "Replace existing file?" "\u00bfReemplazar el archivo existente?"
+ ::msgcat::mcset es "&Retry" "&Reintentar"
+ ::msgcat::mcset es "&Save" "&Guardar"
+ ::msgcat::mcset es "Save As" "Guardar como"
+ ::msgcat::mcset es "Save To Log" "Guardar al archivo de traza"
+ ::msgcat::mcset es "Select Log File" "Elegir un archivo de traza"
+ ::msgcat::mcset es "Select a file to source" "Seleccionar un archivo a evaluar"
+ ::msgcat::mcset es "&Selection:" "&Selecci\u00f3n:"
+ ::msgcat::mcset es "Skip Messages" "Omitir los mensajes"
+ ::msgcat::mcset es "&Source..." "E&valuar..."
+ ::msgcat::mcset es "Tcl Scripts" "Scripts Tcl"
+ ::msgcat::mcset es "Tcl for Windows" "Tcl para Windows"
+ ::msgcat::mcset es "Text Files" "Archivos de texto"
+ ::msgcat::mcset es "&Yes" "&S\u00ed"
+ ::msgcat::mcset es "abort" "abortar"
+ ::msgcat::mcset es "blue" "azul"
+ ::msgcat::mcset es "cancel" "cancelar"
+ ::msgcat::mcset es "extension" "extensi\u00f3n"
+ ::msgcat::mcset es "extensions" "extensiones"
+ ::msgcat::mcset es "green" "verde"
+ ::msgcat::mcset es "ignore" "ignorar"
+ ::msgcat::mcset es "ok"
+ ::msgcat::mcset es "red" "rojo"
+ ::msgcat::mcset es "retry" "reintentar"
+ ::msgcat::mcset es "yes" "s\u00ed"
+}
diff --git a/tk8.6/library/msgs/fr.msg b/tk8.6/library/msgs/fr.msg
new file mode 100644
index 0000000..7f42aca
--- /dev/null
+++ b/tk8.6/library/msgs/fr.msg
@@ -0,0 +1,72 @@
+namespace eval ::tk {
+ ::msgcat::mcset fr "&Abort" "&Annuler"
+ ::msgcat::mcset fr "About..." "\u00c0 propos..."
+ ::msgcat::mcset fr "All Files" "Tous les fichiers"
+ ::msgcat::mcset fr "Application Error" "Erreur d'application"
+ ::msgcat::mcset fr "&Blue" "&Bleu"
+ ::msgcat::mcset fr "Cancel" "Annuler"
+ ::msgcat::mcset fr "&Cancel" "&Annuler"
+ ::msgcat::mcset fr "Cannot change to the directory \"%1\$s\".\nPermission denied." "Impossible d'acc\u00e9der au r\u00e9pertoire \"%1\$s\".\nPermission refus\u00e9e."
+ ::msgcat::mcset fr "Choose Directory" "Choisir r\u00e9pertoire"
+ ::msgcat::mcset fr "Cl&ear" "Effacer"
+ ::msgcat::mcset fr "Color" "Couleur"
+ ::msgcat::mcset fr "Console"
+ ::msgcat::mcset fr "Copy" "Copier"
+ ::msgcat::mcset fr "Cu&t" "Couper"
+ ::msgcat::mcset fr "Delete" "Effacer"
+ ::msgcat::mcset fr "Details >>" "D\u00e9tails >>"
+ ::msgcat::mcset fr "Directory \"%1\$s\" does not exist." "Le r\u00e9pertoire \"%1\$s\" n'existe pas."
+ ::msgcat::mcset fr "&Directory:" "&R\u00e9pertoire:"
+ ::msgcat::mcset fr "Error: %1\$s" "Erreur: %1\$s"
+ ::msgcat::mcset fr "E&xit" "Quitter"
+ ::msgcat::mcset fr "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Le fichier \"%1\$s\" existe d\u00e9j\u00e0.\nVoulez-vous l'\u00e9craser?"
+ ::msgcat::mcset fr "File \"%1\$s\" already exists.\n\n" "Le fichier \"%1\$s\" existe d\u00e9j\u00e0.\n\n"
+ ::msgcat::mcset fr "File \"%1\$s\" does not exist." "Le fichier \"%1\$s\" n'existe pas."
+ ::msgcat::mcset fr "File &name:" "&Nom de fichier:"
+ ::msgcat::mcset fr "File &names:" "&Noms de fichiers:"
+ ::msgcat::mcset fr "Files of &type:" "&Type de fichiers:"
+ ::msgcat::mcset fr "Fi&les:" "Fich&iers:"
+ ::msgcat::mcset fr "&Filter" "&Filtre"
+ ::msgcat::mcset fr "Fil&ter:" "Fil&tre:"
+ ::msgcat::mcset fr "&Green" "&Vert"
+ ::msgcat::mcset fr "Hi" "Salut"
+ ::msgcat::mcset fr "&Hide Console" "Cacher la Console"
+ ::msgcat::mcset fr "&Ignore" "&Ignorer"
+ ::msgcat::mcset fr "Invalid file name \"%1\$s\"." "Nom de fichier invalide \"%1\$s\"."
+ ::msgcat::mcset fr "Log Files" "Fichiers de trace"
+ ::msgcat::mcset fr "&No" "&Non"
+ ::msgcat::mcset fr "&OK"
+ ::msgcat::mcset fr "OK"
+ ::msgcat::mcset fr "Ok"
+ ::msgcat::mcset fr "Open" "Ouvrir"
+ ::msgcat::mcset fr "&Open" "&Ouvrir"
+ ::msgcat::mcset fr "Open Multiple Files" "Ouvrir plusieurs fichiers"
+ ::msgcat::mcset fr "P&aste" "Coller"
+ ::msgcat::mcset fr "&Quit" "&Quitter"
+ ::msgcat::mcset fr "&Red" "&Rouge"
+ ::msgcat::mcset fr "Replace existing file?" "Remplacer le fichier existant?"
+ ::msgcat::mcset fr "&Retry" "&R\u00e9-essayer"
+ ::msgcat::mcset fr "&Save" "&Sauvegarder"
+ ::msgcat::mcset fr "Save As" "Sauvegarder sous"
+ ::msgcat::mcset fr "Save To Log" "Sauvegarde au fichier de trace"
+ ::msgcat::mcset fr "Select Log File" "Choisir un fichier de trace"
+ ::msgcat::mcset fr "Select a file to source" "Choisir un fichier \u00e0 \u00e9valuer"
+ ::msgcat::mcset fr "&Selection:" "&S\u00e9lection:"
+ ::msgcat::mcset fr "Skip Messages" "Omettre les messages"
+ ::msgcat::mcset fr "&Source..." "\u00c9valuer..."
+ ::msgcat::mcset fr "Tcl Scripts" "Scripts Tcl"
+ ::msgcat::mcset fr "Tcl for Windows" "Tcl pour Windows"
+ ::msgcat::mcset fr "Text Files" "Fichiers texte"
+ ::msgcat::mcset fr "&Yes" "&Oui"
+ ::msgcat::mcset fr "abort" "abandonner"
+ ::msgcat::mcset fr "blue" "bleu"
+ ::msgcat::mcset fr "cancel" "annuler"
+ ::msgcat::mcset fr "extension"
+ ::msgcat::mcset fr "extensions"
+ ::msgcat::mcset fr "green" "vert"
+ ::msgcat::mcset fr "ignore" "ignorer"
+ ::msgcat::mcset fr "ok"
+ ::msgcat::mcset fr "red" "rouge"
+ ::msgcat::mcset fr "retry" "r\u00e9essayer"
+ ::msgcat::mcset fr "yes" "oui"
+}
diff --git a/tk8.6/library/msgs/hu.msg b/tk8.6/library/msgs/hu.msg
new file mode 100644
index 0000000..38ef0b8
--- /dev/null
+++ b/tk8.6/library/msgs/hu.msg
@@ -0,0 +1,78 @@
+namespace eval ::tk {
+ ::msgcat::mcset hu "&Abort" "&Megszak\u00edt\u00e1s"
+ ::msgcat::mcset hu "&About..." "N\u00e9vjegy..."
+ ::msgcat::mcset hu "All Files" "Minden f\u00e1jl"
+ ::msgcat::mcset hu "Application Error" "Alkalmaz\u00e1s hiba"
+ ::msgcat::mcset hu "&Blue" "&K\u00e9k"
+ ::msgcat::mcset hu "Cancel" "M\u00e9gsem"
+ ::msgcat::mcset hu "&Cancel" "M\u00e9g&sem"
+ ::msgcat::mcset hu "Cannot change to the directory \"%1\$s\".\nPermission denied." "A k\u00f6nyvt\u00e1rv\u00e1lt\u00e1s nem siker\u00fclt: \"%1\$s\".\nHozz\u00e1f\u00e9r\u00e9s megtagadva."
+ ::msgcat::mcset hu "Choose Directory" "K\u00f6nyvt\u00e1r kiv\u00e1laszt\u00e1sa"
+ ::msgcat::mcset hu "Cl&ear" "T\u00f6rl\u00e9s"
+ ::msgcat::mcset hu "&Clear Console" "&T\u00f6rl\u00e9s Konzol"
+ ::msgcat::mcset hu "Color" "Sz\u00edn"
+ ::msgcat::mcset hu "Console" "Konzol"
+ ::msgcat::mcset hu "&Copy" "&M\u00e1sol\u00e1s"
+ ::msgcat::mcset hu "Cu&t" "&Kiv\u00e1g\u00e1s"
+ ::msgcat::mcset hu "&Delete" "&T\u00f6rl\u00e9s"
+ ::msgcat::mcset hu "Details >>" "R\u00e9szletek >>"
+ ::msgcat::mcset hu "Directory \"%1\$s\" does not exist." "\"%1\$s\" k\u00f6nyvt\u00e1r nem l\u00e9tezik."
+ ::msgcat::mcset hu "&Directory:" "&K\u00f6nyvt\u00e1r:"
+ #::msgcat::mcset hu "&Edit"
+ ::msgcat::mcset hu "Error: %1\$s" "Hiba: %1\$s"
+ ::msgcat::mcset hu "E&xit" "Kil\u00e9p\u00e9s"
+ ::msgcat::mcset hu "&File" "&F\u00e1jl"
+ ::msgcat::mcset hu "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "\"%1\$s\" f\u00e1jl m\u00e1r l\u00e9tezik.\nFel\u00fcl\u00edrjam?"
+ ::msgcat::mcset hu "File \"%1\$s\" already exists.\n\n" "\"%1\$s\" f\u00e1jl m\u00e1r l\u00e9tezik.\n\n"
+ ::msgcat::mcset hu "File \"%1\$s\" does not exist." "\"%1\$s\" f\u00e1jl nem l\u00e9tezik."
+ ::msgcat::mcset hu "File &name:" "F\u00e1jl &neve:"
+ ::msgcat::mcset hu "File &names:" "F\u00e1jlok &nevei:"
+ ::msgcat::mcset hu "Files of &type:" "F\u00e1jlok &t\u00edpusa:"
+ ::msgcat::mcset hu "Fi&les:" "F\u00e1j&lok:"
+ ::msgcat::mcset hu "&Filter" "&Sz\u0171r\u0151"
+ ::msgcat::mcset hu "Fil&ter:" "S&z\u0171r\u0151:"
+ ::msgcat::mcset hu "&Green" "&Z\u00f6ld"
+ #::msgcat::mcset hu "&Help"
+ ::msgcat::mcset hu "Hi" "\u00dcdv"
+ ::msgcat::mcset hu "&Hide Console" "Konzol &elrejt\u00e9se"
+ ::msgcat::mcset hu "&Ignore" "K&ihagy\u00e1s"
+ ::msgcat::mcset hu "Invalid file name \"%1\$s\"." "\u00c9rv\u00e9nytelen f\u00e1jln\u00e9v: \"%1\$s\"."
+ ::msgcat::mcset hu "Log Files" "Log f\u00e1jlok"
+ ::msgcat::mcset hu "&No" "&Nem"
+ ::msgcat::mcset hu "&OK"
+ ::msgcat::mcset hu "OK"
+ ::msgcat::mcset hu "Ok"
+ ::msgcat::mcset hu "Open" "Megnyit\u00e1s"
+ ::msgcat::mcset hu "&Open" "&Megnyit\u00e1s"
+ ::msgcat::mcset hu "Open Multiple Files" "T\u00f6bb f\u00e1jl megnyit\u00e1sa"
+ ::msgcat::mcset hu "P&aste" "&Beilleszt\u00e9s"
+ ::msgcat::mcset hu "&Quit" "&Kil\u00e9p\u00e9s"
+ ::msgcat::mcset hu "&Red" "&V\u00f6r\u00f6s"
+ ::msgcat::mcset hu "Replace existing file?" "Megl\u00e9v\u0151 f\u00e1jl cser\u00e9je?"
+ ::msgcat::mcset hu "&Retry" "\u00daj&ra"
+ ::msgcat::mcset hu "&Save" "&Ment\u00e9s"
+ ::msgcat::mcset hu "Save As" "Ment\u00e9s m\u00e1sk\u00e9nt"
+ ::msgcat::mcset hu "Save To Log" "Ment\u00e9s log f\u00e1jlba"
+ ::msgcat::mcset hu "Select Log File" "Log f\u00e1jl kiv\u00e1laszt\u00e1sa"
+ ::msgcat::mcset hu "Select a file to source" "Forr\u00e1sf\u00e1jl kiv\u00e1laszt\u00e1sa"
+ ::msgcat::mcset hu "&Selection:" "&Kijel\u00f6l\u00e9s:"
+ ::msgcat::mcset hu "Show &Hidden Directories" "&Rejtett k\u00f6nyvt\u00e1rak megjelen\u00edt\u00e9se"
+ ::msgcat::mcset hu "Show &Hidden Files and Directories" "&Rejtett f\u00e1jlok \u00e9s k\u00f6nyvt\u00e1rak megjelen\u00edt\u00e9se"
+ ::msgcat::mcset hu "Skip Messages" "\u00dczenetek kihagy\u00e1sa"
+ ::msgcat::mcset hu "&Source..." "&Forr\u00e1s..."
+ ::msgcat::mcset hu "Tcl Scripts" "Tcl scriptek"
+ ::msgcat::mcset hu "Tcl for Windows" "Tcl Windows-hoz"
+ ::msgcat::mcset hu "Text Files" "Sz\u00f6vegf\u00e1jlok"
+ ::msgcat::mcset hu "&Yes" "&Igen"
+ ::msgcat::mcset hu "abort" "megszak\u00edt\u00e1s"
+ ::msgcat::mcset hu "blue" "k\u00e9k"
+ ::msgcat::mcset hu "cancel" "m\u00e9gsem"
+ ::msgcat::mcset hu "extension" "kiterjeszt\u00e9s"
+ ::msgcat::mcset hu "extensions" "kiterjeszt\u00e9sek"
+ ::msgcat::mcset hu "green" "z\u00f6ld"
+ ::msgcat::mcset hu "ignore" "ignorer"
+ ::msgcat::mcset hu "ok"
+ ::msgcat::mcset hu "red" "v\u00f6r\u00f6s"
+ ::msgcat::mcset hu "retry" "\u00fajra"
+ ::msgcat::mcset hu "yes" "igen"
+}
diff --git a/tk8.6/library/msgs/it.msg b/tk8.6/library/msgs/it.msg
new file mode 100644
index 0000000..2e1b4bd
--- /dev/null
+++ b/tk8.6/library/msgs/it.msg
@@ -0,0 +1,73 @@
+namespace eval ::tk {
+ ::msgcat::mcset it "&Abort" "&Interrompi"
+ ::msgcat::mcset it "&About..." "Informazioni..."
+ ::msgcat::mcset it "All Files" "Tutti i file"
+ ::msgcat::mcset it "Application Error" "Errore dell' applicazione"
+ ::msgcat::mcset it "&Blue" "&Blu"
+ ::msgcat::mcset it "Cancel" "Annulla"
+ ::msgcat::mcset it "&Cancel" "&Annulla"
+ ::msgcat::mcset it "Cannot change to the directory \"%1\$s\".\nPermission denied." "Impossibile accedere alla directory \"%1\$s\".\nPermesso negato."
+ ::msgcat::mcset it "Choose Directory" "Scegli una directory"
+ ::msgcat::mcset it "Cl&ear" "Azzera"
+ ::msgcat::mcset it "&Clear Console" "Azzera Console"
+ ::msgcat::mcset it "Color" "Colore"
+ ::msgcat::mcset it "Console"
+ ::msgcat::mcset it "&Copy" "Copia"
+ ::msgcat::mcset it "Cu&t" "Taglia"
+ ::msgcat::mcset it "Delete" "Cancella"
+ ::msgcat::mcset it "Details >>" "Dettagli >>"
+ ::msgcat::mcset it "Directory \"%1\$s\" does not exist." "La directory \"%1\$s\" non esiste."
+ ::msgcat::mcset it "&Directory:"
+ ::msgcat::mcset it "Error: %1\$s" "Errore: %1\$s"
+ ::msgcat::mcset it "E&xit" "Esci"
+ ::msgcat::mcset it "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Il file \"%1\$s\" esiste gi\u00e0.\nVuoi sovrascriverlo?"
+ ::msgcat::mcset it "File \"%1\$s\" already exists.\n\n" "Il file \"%1\$s\" esiste gi\u00e0.\n\n"
+ ::msgcat::mcset it "File \"%1\$s\" does not exist." "Il file \"%1\$s\" non esiste."
+ ::msgcat::mcset it "File &name:" "&Nome del file:"
+ ::msgcat::mcset it "File &names:" "&Nomi dei file:"
+ ::msgcat::mcset it "Files of &type:" "File di &tipo:"
+ ::msgcat::mcset it "Fi&les:" "Fi&le:"
+ ::msgcat::mcset it "&Filter" "&Filtro"
+ ::msgcat::mcset it "Fil&ter:" "Fil&tro:"
+ ::msgcat::mcset it "&Green" "&Verde"
+ ::msgcat::mcset it "Hi" "Salve"
+ ::msgcat::mcset it "&Hide Console" "Nascondi la console"
+ ::msgcat::mcset it "&Ignore" "&Ignora"
+ ::msgcat::mcset it "Invalid file name \"%1\$s\"." "Nome di file non valido \"%1\$s\"."
+ ::msgcat::mcset it "Log Files" "File di log"
+ ::msgcat::mcset it "&No"
+ ::msgcat::mcset it "&OK"
+ ::msgcat::mcset it "OK"
+ ::msgcat::mcset it "Ok"
+ ::msgcat::mcset it "Open" "Apri"
+ ::msgcat::mcset it "&Open" "A&pri"
+ ::msgcat::mcset it "Open Multiple Files" "Apri file multipli"
+ ::msgcat::mcset it "P&aste" "Incolla"
+ ::msgcat::mcset it "&Quit" "Esci"
+ ::msgcat::mcset it "&Red" "&Rosso"
+ ::msgcat::mcset it "Replace existing file?" "Sostituisci il file esistente?"
+ ::msgcat::mcset it "&Retry" "&Riprova"
+ ::msgcat::mcset it "&Save" "&Salva"
+ ::msgcat::mcset it "Save As" "Salva come"
+ ::msgcat::mcset it "Save To Log" "Salva il log"
+ ::msgcat::mcset it "Select Log File" "Scegli un file di log"
+ ::msgcat::mcset it "Select a file to source" "Scegli un file da eseguire"
+ ::msgcat::mcset it "&Selection:" "&Selezione:"
+ ::msgcat::mcset it "Skip Messages" "Salta i messaggi"
+ ::msgcat::mcset it "Source..." "Esegui..."
+ ::msgcat::mcset it "Tcl Scripts" "Script Tcl"
+ ::msgcat::mcset it "Tcl for Windows" "Tcl per Windows"
+ ::msgcat::mcset it "Text Files" "File di testo"
+ ::msgcat::mcset it "&Yes" "&S\u00ec"
+ ::msgcat::mcset it "abort" "interrompi"
+ ::msgcat::mcset it "blue" "blu"
+ ::msgcat::mcset it "cancel" "annulla"
+ ::msgcat::mcset it "extension" "estensione"
+ ::msgcat::mcset it "extensions" "estensioni"
+ ::msgcat::mcset it "green" "verde"
+ ::msgcat::mcset it "ignore" "ignora"
+ ::msgcat::mcset it "ok"
+ ::msgcat::mcset it "red" "rosso"
+ ::msgcat::mcset it "retry" "riprova"
+ ::msgcat::mcset it "yes" "s\u00ec"
+}
diff --git a/tk8.6/library/msgs/nl.msg b/tk8.6/library/msgs/nl.msg
new file mode 100644
index 0000000..148a9e6
--- /dev/null
+++ b/tk8.6/library/msgs/nl.msg
@@ -0,0 +1,91 @@
+namespace eval ::tk {
+ ::msgcat::mcset nl "&Abort" "&Afbreken"
+ ::msgcat::mcset nl "&About..." "Over..."
+ ::msgcat::mcset nl "All Files" "Alle Bestanden"
+ ::msgcat::mcset nl "Application Error" "Toepassingsfout"
+ ::msgcat::mcset nl "&Apply" "Toepassen"
+ ::msgcat::mcset nl "Bold" "Vet"
+ ::msgcat::mcset nl "Bold Italic" "Vet Cursief"
+ ::msgcat::mcset nl "&Blue" "&Blauw"
+ ::msgcat::mcset nl "Cancel" "Annuleren"
+ ::msgcat::mcset nl "&Cancel" "&Annuleren"
+ ::msgcat::mcset nl "Cannot change to the directory \"%1\$s\".\nPermission denied." "Kan niet naar map \"%1\$s\" gaan.\nU heeft hiervoor geen toestemming."
+ ::msgcat::mcset nl "Choose Directory" "Kies map"
+ ::msgcat::mcset nl "Cl&ear" "Wissen"
+ ::msgcat::mcset nl "&Clear Console" "&Wis Console"
+ ::msgcat::mcset nl "Color" "Kleur"
+ ::msgcat::mcset nl "Console"
+ ::msgcat::mcset nl "&Copy" "Kopi\u00ebren"
+ ::msgcat::mcset nl "Cu&t" "Knippen"
+ ::msgcat::mcset nl "&Delete" "Wissen"
+ ::msgcat::mcset nl "Details >>"
+ ::msgcat::mcset nl "Directory \"%1\$s\" does not exist." "Map \"%1\$s\" bestaat niet."
+ ::msgcat::mcset nl "&Directory:" "&Map:"
+ ::msgcat::mcset nl "&Edit" "Bewerken"
+ ::msgcat::mcset nl "Effects" "Effecten"
+ ::msgcat::mcset nl "Error: %1\$s" "Fout: %1\$s"
+ ::msgcat::mcset nl "E&xit" "Be\u00ebindigen"
+ ::msgcat::mcset nl "&File" "Bestand"
+ ::msgcat::mcset nl "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Bestand \"%1\$s\" bestaat al.\nWilt u het overschrijven?"
+ ::msgcat::mcset nl "File \"%1\$s\" already exists.\n\n" "Bestand \"%1\$s\" bestaat al.\n\n"
+ ::msgcat::mcset nl "File \"%1\$s\" does not exist." "Bestand \"%1\$s\" bestaat niet."
+ ::msgcat::mcset nl "File &name:" "Bestands&naam:"
+ ::msgcat::mcset nl "File &names:" "Bestands&namen:"
+ ::msgcat::mcset nl "Files of &type:" "Bestanden van het &type:"
+ ::msgcat::mcset nl "Fi&les:" "&Bestanden:"
+ ::msgcat::mcset nl "&Filter"
+ ::msgcat::mcset nl "Fil&ter:"
+ ::msgcat::mcset nl "Font"
+ ::msgcat::mcset nl "&Font:"
+ ::msgcat::mcset nl "Font st&yle:" "Font stijl:"
+ ::msgcat::mcset nl "&Green" "&Groen"
+ ::msgcat::mcset nl "&Help"
+ ::msgcat::mcset nl "Hi" "H\u00e9"
+ ::msgcat::mcset nl "&Hide Console" "Verberg Console"
+ ::msgcat::mcset nl "&Ignore" "&Negeren"
+ ::msgcat::mcset nl "Invalid file name \"%1\$s\"." "Ongeldige bestandsnaam \"%1\$s\"."
+ ::msgcat::mcset nl "Italic" "Cursief"
+ ::msgcat::mcset nl "Log Files" "Log Bestanden"
+ ::msgcat::mcset nl "&No" "&Nee"
+ ::msgcat::mcset nl "&OK"
+ ::msgcat::mcset nl "OK"
+ ::msgcat::mcset nl "Ok"
+ ::msgcat::mcset nl "Open" "Openen"
+ ::msgcat::mcset nl "&Open" "&Openen"
+ ::msgcat::mcset nl "Open Multiple Files" "Open meerdere bestanden"
+ ::msgcat::mcset nl "P&aste" "Pl&akken"
+ ::msgcat::mcset nl "&Quit" "Stoppen"
+ ::msgcat::mcset nl "&Red" "&Rood"
+ ::msgcat::mcset nl "Regular" "Standaard"
+ ::msgcat::mcset nl "Replace existing file?" "Vervang bestaand bestand?"
+ ::msgcat::mcset nl "&Retry" "&Herhalen"
+ ::msgcat::mcset nl "Sample"
+ ::msgcat::mcset nl "&Save" "Op&slaan"
+ ::msgcat::mcset nl "Save As" "Opslaan als"
+ ::msgcat::mcset nl "Save To Log" "Opslaan naar Log"
+ ::msgcat::mcset nl "Select Log File" "Selecteer Log bestand"
+ ::msgcat::mcset nl "Select a file to source" "Selecteer bronbestand"
+ ::msgcat::mcset nl "&Selection:" "&Selectie:"
+ ::msgcat::mcset nl "&Size:" "Grootte"
+ ::msgcat::mcset nl "Show &Hidden Directories" "Laat verborgen mappen zien"
+ ::msgcat::mcset nl "Show &Hidden Files and Directories" "Laat verborgen bestanden mappen zien"
+ ::msgcat::mcset nl "Skip Messages" "Berichten overslaan"
+ ::msgcat::mcset nl "&Source..." "Bron..."
+ ::msgcat::mcset nl "Stri&keout"
+ ::msgcat::mcset nl "Tcl Scripts"
+ ::msgcat::mcset nl "Tcl for Windows" "Tcl voor Windows"
+ ::msgcat::mcset nl "Text Files" "Tekstbestanden"
+ ::msgcat::mcset nl "&Underline" "Onderstreept"
+ ::msgcat::mcset nl "&Yes" "&Ja"
+ ::msgcat::mcset nl "abort" "afbreken"
+ ::msgcat::mcset nl "blue" "blauw"
+ ::msgcat::mcset nl "cancel" "annuleren"
+ ::msgcat::mcset nl "extension"
+ ::msgcat::mcset nl "extensions"
+ ::msgcat::mcset nl "green" "groen"
+ ::msgcat::mcset nl "ignore" "negeren"
+ ::msgcat::mcset nl "ok"
+ ::msgcat::mcset nl "red" "rood"
+ ::msgcat::mcset nl "retry" "opnieuw"
+ ::msgcat::mcset nl "yes" "ja"
+}
diff --git a/tk8.6/library/msgs/pl.msg b/tk8.6/library/msgs/pl.msg
new file mode 100644
index 0000000..c20f41e
--- /dev/null
+++ b/tk8.6/library/msgs/pl.msg
@@ -0,0 +1,91 @@
+namespace eval ::tk {
+ ::msgcat::mcset pl "&Abort" "&Przerwij"
+ ::msgcat::mcset pl "&About..." "O programie..."
+ ::msgcat::mcset pl "All Files" "Wszystkie pliki"
+ ::msgcat::mcset pl "Application Error" "B\u0142\u0105d w programie"
+ ::msgcat::mcset pl "&Apply" "Zastosuj"
+ ::msgcat::mcset pl "Bold" "Pogrubienie"
+ ::msgcat::mcset pl "Bold Italic" "Pogrubiona kursywa"
+ ::msgcat::mcset pl "&Blue" "&Niebieski"
+ ::msgcat::mcset pl "Cancel" "Anuluj"
+ ::msgcat::mcset pl "&Cancel" "&Anuluj"
+ ::msgcat::mcset pl "Cannot change to the directory \"%1\$s\".\nPermission denied." "Nie mo\u017cna otworzy\u0107 katalogu \"%1\$s\".\nOdmowa dost\u0119pu."
+ ::msgcat::mcset pl "Choose Directory" "Wybierz katalog"
+ ::msgcat::mcset pl "Cl&ear" "&Wyczy\u015b\u0107"
+ ::msgcat::mcset pl "&Clear Console" "&Wyczy\u015b\u0107 konsol\u0119"
+ ::msgcat::mcset pl "Color" "Kolor"
+ ::msgcat::mcset pl "Console" "Konsola"
+ ::msgcat::mcset pl "&Copy" "&Kopiuj"
+ ::msgcat::mcset pl "Cu&t" "&Wytnij"
+ ::msgcat::mcset pl "&Delete" "&Usu\u0144"
+ ::msgcat::mcset pl "Details >>" "Szczeg\u00f3\u0142y >>"
+ ::msgcat::mcset pl "Directory \"%1\$s\" does not exist." "Katalog \"%1\$s\" nie istnieje."
+ ::msgcat::mcset pl "&Directory:" "&Katalog:"
+ ::msgcat::mcset pl "&Edit" "&Edytuj"
+ ::msgcat::mcset pl "Effects" "Efekty"
+ ::msgcat::mcset pl "Error: %1\$s" "B\u0142\u0105d: %1\$s"
+ ::msgcat::mcset pl "E&xit" "&Wyjd\u017a"
+ ::msgcat::mcset pl "&File" "&Plik"
+ ::msgcat::mcset pl "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Plik \"%1\$s\" ju\u017c istnieje.\nCzy chcesz go nadpisa\u0107?"
+ ::msgcat::mcset pl "File \"%1\$s\" already exists.\n\n" "Plik \"%1\$s\" ju\u017c istnieje.\n\n"
+ ::msgcat::mcset pl "File \"%1\$s\" does not exist." "Plik \"%1\$s\" nie istnieje."
+ ::msgcat::mcset pl "File &name:" "Nazwa &pliku:"
+ ::msgcat::mcset pl "File &names:" "Nazwy &plik\u00f3w:"
+ ::msgcat::mcset pl "Files of &type:" "Pliki &typu:"
+ ::msgcat::mcset pl "Fi&les:" "Pli&ki:"
+ ::msgcat::mcset pl "&Filter" "&Filtr"
+ ::msgcat::mcset pl "Fil&ter:" "&Filtr:"
+ ::msgcat::mcset pl "Font" "Czcionka"
+ ::msgcat::mcset pl "&Font:" "Czcio&nka:"
+ ::msgcat::mcset pl "Font st&yle:" "&Styl czcionki:"
+ ::msgcat::mcset pl "&Green" "&Zielony"
+ ::msgcat::mcset pl "&Help" "&Pomoc"
+ ::msgcat::mcset pl "Hi" "Witaj"
+ ::msgcat::mcset pl "&Hide Console" "&Ukryj konsol\u0119"
+ ::msgcat::mcset pl "&Ignore" "&Ignoruj"
+ ::msgcat::mcset pl "Invalid file name \"%1\$s\"." "Niew\u0142a\u015bciwa nazwa pliku \"%1\$s\"."
+ ::msgcat::mcset pl "Italic" "Kursywa"
+ ::msgcat::mcset pl "Log Files" "Pliki dziennika"
+ ::msgcat::mcset pl "&No" "&Nie"
+ ::msgcat::mcset pl "&OK"
+ ::msgcat::mcset pl "OK"
+ ::msgcat::mcset pl "Ok"
+ ::msgcat::mcset pl "Open" "Otw\u00f3rz"
+ ::msgcat::mcset pl "&Open" "&Otw\u00f3rz"
+ ::msgcat::mcset pl "Open Multiple Files" "Otw\u00f3rz wiele plik\u00f3w"
+ ::msgcat::mcset pl "P&aste" "&Wklej"
+ ::msgcat::mcset pl "&Quit" "&Zako\u0144cz"
+ ::msgcat::mcset pl "&Red" "&Czerwony"
+ ::msgcat::mcset pl "Regular" "Regularne"
+ ::msgcat::mcset pl "Replace existing file?" "Czy zast\u0105pi\u0107 istniej\u0105cy plik?"
+ ::msgcat::mcset pl "&Retry" "&Pon\u00f3w"
+ ::msgcat::mcset pl "Sample" "Przyk\u0142ad"
+ ::msgcat::mcset pl "&Save" "&Zapisz"
+ ::msgcat::mcset pl "Save As" "Zapisz jako"
+ ::msgcat::mcset pl "Save To Log" "Wpisz do dziennika"
+ ::msgcat::mcset pl "Select Log File" "Wybierz plik dziennika"
+ ::msgcat::mcset pl "Select a file to source" "Wybierz plik do wykonania"
+ ::msgcat::mcset pl "&Selection:" "&Wyb\u00f3r:"
+ ::msgcat::mcset pl "&Size:" "&Rozmiar:"
+ ::msgcat::mcset pl "Show &Hidden Directories" "Poka\u017c &ukryte katalogi"
+ ::msgcat::mcset pl "Show &Hidden Files and Directories" "Poka\u017c &ukryte pliki i katalogi"
+ ::msgcat::mcset pl "Skip Messages" "Pomi\u0144 pozosta\u0142e komunikaty"
+ ::msgcat::mcset pl "&Source..." "&Kod \u017ar\u00f3d\u0142owy..."
+ ::msgcat::mcset pl "Stri&keout" "&Przekre\u015blenie"
+ ::msgcat::mcset pl "Tcl Scripts" "Skrypty Tcl"
+ ::msgcat::mcset pl "Tcl for Windows" "Tcl dla Windows"
+ ::msgcat::mcset pl "Text Files" "Pliki tekstowe"
+ ::msgcat::mcset pl "&Underline" "Po&dkre\u015blenie"
+ ::msgcat::mcset pl "&Yes" "&Tak"
+ ::msgcat::mcset pl "abort" "przerwij"
+ ::msgcat::mcset pl "blue" "niebieski"
+ ::msgcat::mcset pl "cancel" "anuluj"
+ ::msgcat::mcset pl "extension" "rozszerzenie"
+ ::msgcat::mcset pl "extensions" "rozszerzenia"
+ ::msgcat::mcset pl "green" "zielony"
+ ::msgcat::mcset pl "ignore" "ignoruj"
+ ::msgcat::mcset pl "ok"
+ ::msgcat::mcset pl "red" "czerwony"
+ ::msgcat::mcset pl "retry" "pon\u00f3w"
+ ::msgcat::mcset pl "yes" "tak"
+}
diff --git a/tk8.6/library/msgs/pt.msg b/tk8.6/library/msgs/pt.msg
new file mode 100644
index 0000000..c29e293
--- /dev/null
+++ b/tk8.6/library/msgs/pt.msg
@@ -0,0 +1,74 @@
+namespace eval ::tk {
+ ::msgcat::mcset pt "&Abort" "&Abortar"
+ ::msgcat::mcset pt "About..." "Sobre ..."
+ ::msgcat::mcset pt "All Files" "Todos os arquivos"
+ ::msgcat::mcset pt "Application Error" "Erro de aplica\u00e7\u00e3o"
+ ::msgcat::mcset pt "&Blue" "&Azul"
+ ::msgcat::mcset pt "Cancel" "Cancelar"
+ ::msgcat::mcset pt "&Cancel" "&Cancelar"
+ ::msgcat::mcset pt "Cannot change to the directory \"%1\$s\".\nPermission denied." "N\u00e3o foi poss\u00edvel mudar para o diret\u00f3rio \"%1\$s\".\nPermiss\u00e3o negada."
+ ::msgcat::mcset pt "Choose Directory" "Escolha um diret\u00f3rio"
+ ::msgcat::mcset pt "Cl&ear" "Apagar"
+ ::msgcat::mcset pt "&Clear Console" "Apagar Console"
+ ::msgcat::mcset pt "Color" "Cor"
+ ::msgcat::mcset pt "Console"
+ ::msgcat::mcset pt "&Copy" "Copiar"
+ ::msgcat::mcset pt "Cu&t" "Recortar"
+ ::msgcat::mcset pt "&Delete" "Excluir"
+ ::msgcat::mcset pt "Details >>" "Detalhes >>"
+ ::msgcat::mcset pt "Directory \"%1\$s\" does not exist." "O diret\u00f3rio \"%1\$s\" n\u00e3o existe."
+ ::msgcat::mcset pt "&Directory:" "&Diret\u00f3rio:"
+ ::msgcat::mcset pt "Error: %1\$s" "Erro: %1\$s"
+ ::msgcat::mcset pt "E&xit" "Sair"
+ ::msgcat::mcset pt "&File" "Arquivo"
+ ::msgcat::mcset pt "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "O arquivo \"%1\$s\" j\u00e1 existe.\nDeseja sobrescreve-lo?"
+ ::msgcat::mcset pt "File \"%1\$s\" already exists.\n\n" "O arquivo \"%1\$s\" j\u00e1 existe.\n\n"
+ ::msgcat::mcset pt "File \"%1\$s\" does not exist." "Arquivo \"%1\$s\" n\u00e3o existe."
+ ::msgcat::mcset pt "File &name:" "&Nome do arquivo:"
+ ::msgcat::mcset pt "File &names:" "&Nomes dos arquivos:"
+ ::msgcat::mcset pt "Files of &type:" "Arquivos do &tipo:"
+ ::msgcat::mcset pt "Fi&les:" "&Arquivos:"
+ ::msgcat::mcset pt "&Filter" "&Filtro"
+ ::msgcat::mcset pt "Fil&ter:" "Fil&tro:"
+ ::msgcat::mcset pt "&Green" "&Verde"
+ ::msgcat::mcset pt "Hi" "Oi"
+ ::msgcat::mcset pt "&Hide Console" "Ocultar console"
+ ::msgcat::mcset pt "&Ignore" "&Ignorar"
+ ::msgcat::mcset pt "Invalid file name \"%1\$s\"." "O nome do arquivo \u00e9 inv\u00e1lido \"%1\$s\"."
+ ::msgcat::mcset pt "Log Files" "Arquivos de log"
+ ::msgcat::mcset pt "&No" "&N\u00e3o"
+ ::msgcat::mcset pt "&OK"
+ ::msgcat::mcset pt "OK"
+ ::msgcat::mcset pt "Ok"
+ ::msgcat::mcset pt "Open" "Abrir"
+ ::msgcat::mcset pt "&Open" "&Abrir"
+ ::msgcat::mcset pt "Open Multiple Files" "Abrir m\u00faltiplos arquivos"
+ ::msgcat::mcset pt "P&aste" "Col&ar"
+ ::msgcat::mcset pt "Quit" "Encerrar"
+ ::msgcat::mcset pt "&Red" "&Vermelho"
+ ::msgcat::mcset pt "Replace existing file?" "Substituir arquivo existente?"
+ ::msgcat::mcset pt "&Retry" "Tenta&r novamente"
+ ::msgcat::mcset pt "&Save" "&Salvar"
+ ::msgcat::mcset pt "Save As" "Salvar como"
+ ::msgcat::mcset pt "Save To Log" "Salvar arquivo de log"
+ ::msgcat::mcset pt "Select Log File" "Selecionar arquivo de log"
+ ::msgcat::mcset pt "Select a file to source" "Selecione um arquivo como fonte"
+ ::msgcat::mcset pt "&Selection:" "&Sele\u00e7\u00e3o:"
+ ::msgcat::mcset pt "Skip Messages" "Omitir as mensagens"
+ ::msgcat::mcset pt "&Source..." "&Fonte..."
+ ::msgcat::mcset pt "Tcl Scripts" "Scripts Tcl"
+ ::msgcat::mcset pt "Tcl for Windows" "Tcl para Windows"
+ ::msgcat::mcset pt "Text Files" "Arquivos de texto"
+ ::msgcat::mcset pt "&Yes" "&Sim"
+ ::msgcat::mcset pt "abort" "abortar"
+ ::msgcat::mcset pt "blue" "azul"
+ ::msgcat::mcset pt "cancel" "cancelar"
+ ::msgcat::mcset pt "extension" "extens\u00e3o"
+ ::msgcat::mcset pt "extensions" "extens\u00f5es"
+ ::msgcat::mcset pt "green" "verde"
+ ::msgcat::mcset pt "ignore" "ignorar"
+ ::msgcat::mcset pt "ok"
+ ::msgcat::mcset pt "red" "vermelho"
+ ::msgcat::mcset pt "retry" "tentar novamente"
+ ::msgcat::mcset pt "yes" "sim"
+}
diff --git a/tk8.6/library/msgs/ru.msg b/tk8.6/library/msgs/ru.msg
new file mode 100644
index 0000000..2aac5bb
--- /dev/null
+++ b/tk8.6/library/msgs/ru.msg
@@ -0,0 +1,75 @@
+namespace eval ::tk {
+ ::msgcat::mcset ru "&Abort" "&\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c"
+ ::msgcat::mcset ru "&About..." "\u041f\u0440\u043e..."
+ ::msgcat::mcset ru "All Files" "\u0412\u0441\u0435 \u0444\u0430\u0439\u043b\u044b"
+ ::msgcat::mcset ru "Application Error" "\u041e\u0448\u0438\u0431\u043a\u0430 \u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0435"
+ ::msgcat::mcset ru "&Blue" " &\u0413\u043e\u043b\u0443\u0431\u043e\u0439"
+ ::msgcat::mcset ru "Cancel" "\u041e\u0442&\u043c\u0435\u043d\u0430"
+ ::msgcat::mcset ru "&Cancel" "\u041e\u0442&\u043c\u0435\u043d\u0430"
+ ::msgcat::mcset ru "Cannot change to the directory \"%1\$s\".\nPermission denied." \
+ "\u041d\u0435 \u043c\u043e\u0433\u0443 \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \"%1\$s\".\n\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u0430\u0432 \u0434\u043e\u0441\u0442\u0443\u043f\u0430"
+ ::msgcat::mcset ru "Choose Directory" "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043a\u0430\u0442\u0430\u043b\u043e\u0433"
+ ::msgcat::mcset ru "Cl&ear" "\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u044c"
+ ::msgcat::mcset ru "Color" "\u0426\u0432\u0435\u0442"
+ ::msgcat::mcset ru "Console" "\u041a\u043e\u043d\u0441\u043e\u043b\u044c"
+ ::msgcat::mcset ru "&Copy" "\u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c"
+ ::msgcat::mcset ru "Cu&t" "\u0412\u044b\u0440\u0435\u0437\u0430\u0442\u044c"
+ ::msgcat::mcset ru "&Delete" "\u0423\u0434\u0430\u043b\u0438\u0442\u044c"
+ ::msgcat::mcset ru "Details >>" "\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 >>"
+ ::msgcat::mcset ru "Directory \"%1\$s\" does not exist." "\u041a\u0430\u0442\u0430\u043b\u043e\u0433\u0430 \"%1\$s\" \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442."
+ ::msgcat::mcset ru "&Directory:" "&\u041a\u0430\u0442\u0430\u043b\u043e\u0433:"
+ ::msgcat::mcset ru "Error: %1\$s" "\u041e\u0448\u0438\u0431\u043a\u0430: %1\$s"
+ ::msgcat::mcset ru "E&xit" "\u0412\u044b\u0445\u043e\u0434"
+ ::msgcat::mcset ru "File \"%1\$s\" already exists.\nDo you want to overwrite it?" \
+ "\u0424\u0430\u0439\u043b \"%1\$s\" \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.\n\u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0435\u0433\u043e?"
+ ::msgcat::mcset ru "File \"%1\$s\" already exists.\n\n" "\u0424\u0430\u0439\u043b \"%1\$s\" \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.\n\n"
+ ::msgcat::mcset ru "File \"%1\$s\" does not exist." "\u0424\u0430\u0439\u043b \"%1\$s\" \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d."
+ ::msgcat::mcset ru "File &name:" "&\u0418\u043c\u044f \u0444\u0430\u0439\u043b\u0430:"
+ ::msgcat::mcset ru "File &names:" "&\u0418\u043c\u0435\u043d\u0430 \u0444\u0430\u0439\u043b\u043e\u0432:"
+ ::msgcat::mcset ru "Files of &type:" "&\u0422\u0438\u043f \u0444\u0430\u0439\u043b\u043e\u0432:"
+ ::msgcat::mcset ru "Fi&les:" "\u0424\u0430\u0439&\u043b\u044b:"
+ ::msgcat::mcset ru "&Filter" "&\u0424\u0438\u043b\u044c\u0442\u0440"
+ ::msgcat::mcset ru "Fil&ter:" "\u0424\u0438\u043b\u044c&\u0442\u0440:"
+ ::msgcat::mcset ru "&Green" " &\u0417\u0435\u043b\u0435\u043d\u044b\u0439"
+ ::msgcat::mcset ru "Hi" "\u041f\u0440\u0438\u0432\u0435\u0442"
+ ::msgcat::mcset ru "&Hide Console" "\u0421\u043f\u0440\u044f\u0442\u0430\u0442\u044c \u043a\u043e\u043d\u0441\u043e\u043b\u044c"
+ ::msgcat::mcset ru "&Ignore" "&\u0418\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c"
+ ::msgcat::mcset ru "Invalid file name \"%1\$s\"." "\u041d\u0435\u0432\u0435\u0440\u043d\u043e\u0435 \u0438\u043c\u044f \u0444\u0430\u0439\u043b\u0430 \"%1\$s\"."
+ ::msgcat::mcset ru "Log Files" "\u0424\u0430\u0439\u043b\u044b \u0436\u0443\u0440\u043d\u0430\u043b\u0430"
+ ::msgcat::mcset ru "&No" "&\u041d\u0435\u0442"
+ ::msgcat::mcset ru "&OK" "&\u041e\u041a"
+ ::msgcat::mcset ru "OK" "\u041e\u041a"
+ ::msgcat::mcset ru "Ok" "\u0414\u0430"
+ ::msgcat::mcset ru "Open" "\u041e\u0442\u043a\u0440\u044b\u0442\u044c"
+ ::msgcat::mcset ru "&Open" "&\u041e\u0442\u043a\u0440\u044b\u0442\u044c"
+ ::msgcat::mcset ru "Open Multiple Files" "\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u0430\u0439\u043b\u043e\u0432"
+ ::msgcat::mcset ru "P&aste" "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c"
+ ::msgcat::mcset ru "&Quit" "\u0412\u044b\u0445\u043e\u0434"
+ ::msgcat::mcset ru "&Red" " &\u041a\u0440\u0430\u0441\u043d\u044b\u0439"
+ ::msgcat::mcset ru "Replace existing file?" "\u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u0444\u0430\u0439\u043b?"
+ ::msgcat::mcset ru "&Retry" "&\u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c"
+ ::msgcat::mcset ru "&Save" "&\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c"
+ ::msgcat::mcset ru "Save As" "\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u0430\u043a"
+ ::msgcat::mcset ru "Save To Log" "\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u0436\u0443\u0440\u043d\u0430\u043b"
+ ::msgcat::mcset ru "Select Log File" "\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u0436\u0443\u0440\u043d\u0430\u043b"
+ ::msgcat::mcset ru "Select a file to source" "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0444\u0430\u0439\u043b \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0446\u0438\u0438"
+ ::msgcat::mcset ru "&Selection:"
+ ::msgcat::mcset ru "Skip Messages" "\u041f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f"
+ ::msgcat::mcset ru "&Source..." "\u0418\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b..."
+ ::msgcat::mcset ru "Tcl Scripts" "\u041f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u043d\u0430 \u044f\u0437\u044b\u043a\u0435 TCL"
+ ::msgcat::mcset ru "Tcl for Windows" "TCL \u0434\u043b\u044f Windows"
+ ::msgcat::mcset ru "Text Files" "\u0422\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0435 \u0444\u0430\u0439\u043b\u044b"
+ ::msgcat::mcset ru "&Yes" "&\u0414\u0430"
+ ::msgcat::mcset ru "abort" "\u043e\u0442\u043c\u0435\u043d\u0430"
+ ::msgcat::mcset ru "blue" " \u0433\u043e\u043b\u0443\u0431\u043e\u0439"
+ ::msgcat::mcset ru "cancel" "\u043e\u0442\u043c\u0435\u043d\u0430"
+ ::msgcat::mcset ru "extension" "\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435"
+ ::msgcat::mcset ru "extensions" "\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f"
+ ::msgcat::mcset ru "green" " \u0437\u0435\u043b\u0435\u043d\u044b\u0439"
+ ::msgcat::mcset ru "ignore" "\u043f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c"
+ ::msgcat::mcset ru "ok" "\u043e\u043a"
+ ::msgcat::mcset ru "red" " \u043a\u0440\u0430\u0441\u043d\u044b\u0439"
+ ::msgcat::mcset ru "retry" "\u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c"
+ ::msgcat::mcset ru "yes" "\u0434\u0430"
+}
+
diff --git a/tk8.6/library/msgs/sv.msg b/tk8.6/library/msgs/sv.msg
new file mode 100644
index 0000000..62bfcbd
--- /dev/null
+++ b/tk8.6/library/msgs/sv.msg
@@ -0,0 +1,76 @@
+namespace eval ::tk {
+ ::msgcat::mcset sv "&Abort" "&Avsluta"
+ ::msgcat::mcset sv "&About..." "&Om..."
+ ::msgcat::mcset sv "All Files" "Samtliga filer"
+ ::msgcat::mcset sv "Application Error" "Programfel"
+ ::msgcat::mcset sv "&Blue" "&Bl\u00e5"
+ ::msgcat::mcset sv "Cancel" "Avbryt"
+ ::msgcat::mcset sv "&Cancel" "&Avbryt"
+ ::msgcat::mcset sv "Cannot change to the directory \"%1\$s\".\nPermission denied." "Kan ej n\u00e5 mappen \"%1\$s\".\nSaknar r\u00e4ttigheter."
+ ::msgcat::mcset sv "Choose Directory" "V\u00e4lj mapp"
+ ::msgcat::mcset sv "Cl&ear" "&Radera"
+ ::msgcat::mcset sv "&Clear Console" "&Radera konsollen"
+ ::msgcat::mcset sv "Color" "F\u00e4rg"
+ ::msgcat::mcset sv "Console" "Konsoll"
+ ::msgcat::mcset sv "&Copy" "&Kopiera"
+ ::msgcat::mcset sv "Cu&t" "Klipp u&t"
+ ::msgcat::mcset sv "&Delete" "&Radera"
+ ::msgcat::mcset sv "Details >>" "Detaljer >>"
+ ::msgcat::mcset sv "Directory \"%1\$s\" does not exist." "Mappen \"%1\$s\" finns ej."
+ ::msgcat::mcset sv "&Directory:" "&Mapp:"
+ ::msgcat::mcset sv "&Edit" "R&edigera"
+ ::msgcat::mcset sv "Error: %1\$s" "Fel: %1\$s"
+ ::msgcat::mcset sv "E&xit" "&Avsluta"
+ ::msgcat::mcset sv "&File" "&Fil"
+ ::msgcat::mcset sv "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Filen \"%1\$s\" finns redan.\nVill du skriva \u00f6ver den?"
+ ::msgcat::mcset sv "File \"%1\$s\" already exists.\n\n" "Filen \"%1\$s\" finns redan.\n\n"
+ ::msgcat::mcset sv "File \"%1\$s\" does not exist." "Filen \"%1\$s\" finns ej."
+ ::msgcat::mcset sv "File &name:" "Fil&namn:"
+ ::msgcat::mcset sv "File &names:" "Fil&namn:"
+ ::msgcat::mcset sv "Files of &type:" "Filer av &typ:"
+ ::msgcat::mcset sv "Fi&les:" "Fi&ler:"
+ ::msgcat::mcset sv "&Filter"
+ ::msgcat::mcset sv "Fil&ter:"
+ ::msgcat::mcset sv "&Green" "&Gr\u00f6n"
+ ::msgcat::mcset sv "&Help" "&Hj\u00e4lp"
+ ::msgcat::mcset sv "Hi" "Hej"
+ ::msgcat::mcset sv "&Hide Console" "&G\u00f6m konsollen"
+ ::msgcat::mcset sv "&Ignore" "&Ignorera"
+ ::msgcat::mcset sv "Invalid file name \"%1\$s\"." "Ogiltigt filnamn \"%1\$s\"."
+ ::msgcat::mcset sv "Log Files" "Loggfiler"
+ ::msgcat::mcset sv "&No" "&Nej"
+ ::msgcat::mcset sv "&OK"
+ ::msgcat::mcset sv "OK"
+ ::msgcat::mcset sv "Ok"
+ ::msgcat::mcset sv "Open" "\u00d6ppna"
+ ::msgcat::mcset sv "&Open" "&\u00d6ppna"
+ ::msgcat::mcset sv "Open Multiple Files" "\u00d6ppna flera filer"
+ ::msgcat::mcset sv "P&aste" "&Klistra in"
+ ::msgcat::mcset sv "&Quit" "&Avsluta"
+ ::msgcat::mcset sv "&Red" "&R\u00f6d"
+ ::msgcat::mcset sv "Replace existing file?" "Ers\u00e4tt existerande fil?"
+ ::msgcat::mcset sv "&Retry" "&F\u00f6rs\u00f6k igen"
+ ::msgcat::mcset sv "&Save" "&Spara"
+ ::msgcat::mcset sv "Save As" "Spara som"
+ ::msgcat::mcset sv "Save To Log" "Spara till logg"
+ ::msgcat::mcset sv "Select Log File" "V\u00e4lj loggfil"
+ ::msgcat::mcset sv "Select a file to source" "V\u00e4lj k\u00e4llfil"
+ ::msgcat::mcset sv "&Selection:" "&Val:"
+ ::msgcat::mcset sv "Skip Messages" "Hoppa \u00f6ver meddelanden"
+ ::msgcat::mcset sv "&Source..." "&K\u00e4lla..."
+ ::msgcat::mcset sv "Tcl Scripts" "Tcl skript"
+ ::msgcat::mcset sv "Tcl for Windows" "Tcl f\u00f6r Windows"
+ ::msgcat::mcset sv "Text Files" "Textfiler"
+ ::msgcat::mcset sv "&Yes" "&Ja"
+ ::msgcat::mcset sv "abort" "avbryt"
+ ::msgcat::mcset sv "blue" "bl\u00e5"
+ ::msgcat::mcset sv "cancel" "avbryt"
+ ::msgcat::mcset sv "extension" "utvidgning"
+ ::msgcat::mcset sv "extensions" "utvidgningar"
+ ::msgcat::mcset sv "green" "gr\u00f6n"
+ ::msgcat::mcset sv "ignore" "ignorera"
+ ::msgcat::mcset sv "ok"
+ ::msgcat::mcset sv "red" "r\u00f6d"
+ ::msgcat::mcset sv "retry" "f\u00f6rs\u00f6k igen"
+ ::msgcat::mcset sv "yes" "ja"
+}
diff --git a/tk8.6/library/obsolete.tcl b/tk8.6/library/obsolete.tcl
new file mode 100644
index 0000000..3ee7f28
--- /dev/null
+++ b/tk8.6/library/obsolete.tcl
@@ -0,0 +1,178 @@
+# obsolete.tcl --
+#
+# This file contains obsolete procedures that people really shouldn't
+# be using anymore, but which are kept around for backward compatibility.
+#
+# Copyright (c) 1994 The Regents of the University of California.
+# Copyright (c) 1994 Sun Microsystems, Inc.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+
+# The procedures below are here strictly for backward compatibility with
+# Tk version 3.6 and earlier. The procedures are no longer needed, so
+# they are no-ops. You should not use these procedures anymore, since
+# they may be removed in some future release.
+
+proc tk_menuBar args {}
+proc tk_bindForTraversal args {}
+
+# ::tk::classic::restore --
+#
+# Restore the pre-8.5 (Tk classic) look as the widget defaults for classic
+# Tk widgets.
+#
+# The value following an 'option add' call is the new 8.5 value.
+#
+namespace eval ::tk::classic {
+ # This may need to be adjusted for some window managers that are
+ # more aggressive with their own Xdefaults (like KDE and CDE)
+ variable prio "widgetDefault"
+}
+
+proc ::tk::classic::restore {args} {
+ # Restore classic (8.4) look to classic Tk widgets
+ variable prio
+
+ if {[llength $args]} {
+ foreach what $args {
+ ::tk::classic::restore_$what
+ }
+ } else {
+ foreach cmd [info procs restore_*] {
+ $cmd
+ }
+ }
+}
+
+proc ::tk::classic::restore_font {args} {
+ # Many widgets were adjusted from hard-coded defaults to using the
+ # TIP#145 fonts defined in fonts.tcl (eg TkDefaultFont, TkFixedFont, ...)
+ # For restoring compatibility, we only correct size and weighting changes,
+ # as the fonts themselves remained mostly the same.
+ if {[tk windowingsystem] eq "x11"} {
+ font configure TkDefaultFont -weight bold ; # normal
+ font configure TkFixedFont -size -12 ; # -10
+ }
+ # Add these with prio 21 to override value in dialog/msgbox.tcl
+ if {[tk windowingsystem] eq "aqua"} {
+ option add *Dialog.msg.font system 21; # TkCaptionFont
+ option add *Dialog.dtl.font system 21; # TkCaptionFont
+ option add *ErrorDialog*Label.font system 21; # TkCaptionFont
+ } else {
+ option add *Dialog.msg.font {Times 12} 21; # TkCaptionFont
+ option add *Dialog.dtl.font {Times 10} 21; # TkCaptionFont
+ option add *ErrorDialog*Label.font {Times -18} 21; # TkCaptionFont
+ }
+}
+
+proc ::tk::classic::restore_button {args} {
+ variable prio
+ if {[tk windowingsystem] eq "x11"} {
+ foreach cls {Button Radiobutton Checkbutton} {
+ option add *$cls.borderWidth 2 $prio; # 1
+ }
+ }
+}
+
+proc ::tk::classic::restore_entry {args} {
+ variable prio
+ # Entry and Spinbox share core defaults
+ foreach cls {Entry Spinbox} {
+ if {[tk windowingsystem] ne "aqua"} {
+ option add *$cls.borderWidth 2 $prio; # 1
+ }
+ if {[tk windowingsystem] eq "x11"} {
+ option add *$cls.background "#d9d9d9" $prio; # "white"
+ option add *$cls.selectBorderWidth 1 $prio; # 0
+ }
+ }
+}
+
+proc ::tk::classic::restore_listbox {args} {
+ variable prio
+ if {[tk windowingsystem] ne "win32"} {
+ option add *Listbox.background "#d9d9d9" $prio; # "white"
+ option add *Listbox.activeStyle "underline" $prio; # "dotbox"
+ }
+ if {[tk windowingsystem] ne "aqua"} {
+ option add *Listbox.borderWidth 2 $prio; # 1
+ }
+ if {[tk windowingsystem] eq "x11"} {
+ option add *Listbox.selectBorderWidth 1 $prio; # 0
+ }
+ # Remove focus into Listbox added for 8.5
+ bind Listbox <1> {
+ if {[winfo exists %W]} {
+ tk::ListboxBeginSelect %W [%W index @%x,%y]
+ }
+ }
+}
+
+proc ::tk::classic::restore_menu {args} {
+ variable prio
+ if {[tk windowingsystem] eq "x11"} {
+ option add *Menu.activeBorderWidth 2 $prio; # 1
+ option add *Menu.borderWidth 2 $prio; # 1
+ option add *Menu.clickToFocus true $prio
+ option add *Menu.useMotifHelp true $prio
+ }
+ if {[tk windowingsystem] ne "aqua"} {
+ option add *Menu.font "TkDefaultFont" $prio; # "TkMenuFont"
+ }
+}
+
+proc ::tk::classic::restore_menubutton {args} {
+ variable prio
+ option add *Menubutton.borderWidth 2 $prio; # 1
+}
+
+proc ::tk::classic::restore_message {args} {
+ variable prio
+ option add *Message.borderWidth 2 $prio; # 1
+}
+
+proc ::tk::classic::restore_panedwindow {args} {
+ variable prio
+ option add *Panedwindow.borderWidth 2 $prio; # 1
+ option add *Panedwindow.sashWidth 2 $prio; # 3
+ option add *Panedwindow.sashPad 2 $prio; # 0
+ option add *Panedwindow.sashRelief raised $prio; # flat
+ option add *Panedwindow.opaqueResize 0 $prio; # 1
+ if {[tk windowingsystem] ne "win32"} {
+ option add *Panedwindow.showHandle 1 $prio; # 0
+ }
+}
+
+proc ::tk::classic::restore_scale {args} {
+ variable prio
+ option add *Scale.borderWidth 2 $prio; # 1
+ if {[tk windowingsystem] eq "x11"} {
+ option add *Scale.troughColor "#c3c3c3" $prio; # "#b3b3b3"
+ }
+}
+
+proc ::tk::classic::restore_scrollbar {args} {
+ variable prio
+ if {[tk windowingsystem] eq "x11"} {
+ option add *Scrollbar.borderWidth 2 $prio; # 1
+ option add *Scrollbar.highlightThickness 1 $prio; # 0
+ option add *Scrollbar.width 15 $prio; # 11
+ option add *Scrollbar.troughColor "#c3c3c3" $prio; # "#b3b3b3"
+ }
+}
+
+proc ::tk::classic::restore_text {args} {
+ variable prio
+ if {[tk windowingsystem] ne "aqua"} {
+ option add *Text.borderWidth 2 $prio; # 1
+ }
+ if {[tk windowingsystem] eq "win32"} {
+ option add *Text.font "TkDefaultFont" $prio; # "TkFixedFont"
+ }
+ if {[tk windowingsystem] eq "x11"} {
+ option add *Text.background "#d9d9d9" $prio; # white
+ option add *Text.selectBorderWidth 1 $prio; # 0
+ }
+}
diff --git a/tk8.6/library/optMenu.tcl b/tk8.6/library/optMenu.tcl
new file mode 100644
index 0000000..7cfdaa0
--- /dev/null
+++ b/tk8.6/library/optMenu.tcl
@@ -0,0 +1,43 @@
+# optMenu.tcl --
+#
+# This file defines the procedure tk_optionMenu, which creates
+# an option button and its associated menu.
+#
+# Copyright (c) 1994 The Regents of the University of California.
+# Copyright (c) 1994 Sun Microsystems, Inc.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+
+# ::tk_optionMenu --
+# This procedure creates an option button named $w and an associated
+# menu. Together they provide the functionality of Motif option menus:
+# they can be used to select one of many values, and the current value
+# appears in the global variable varName, as well as in the text of
+# the option menubutton. The name of the menu is returned as the
+# procedure's result, so that the caller can use it to change configuration
+# options on the menu or otherwise manipulate it.
+#
+# Arguments:
+# w - The name to use for the menubutton.
+# varName - Global variable to hold the currently selected value.
+# firstValue - First of legal values for option (must be >= 1).
+# args - Any number of additional values.
+
+proc ::tk_optionMenu {w varName firstValue args} {
+ upvar #0 $varName var
+
+ if {![info exists var]} {
+ set var $firstValue
+ }
+ menubutton $w -textvariable $varName -indicatoron 1 -menu $w.menu \
+ -relief raised -highlightthickness 1 -anchor c \
+ -direction flush
+ menu $w.menu -tearoff 0
+ $w.menu add radiobutton -label $firstValue -variable $varName
+ foreach i $args {
+ $w.menu add radiobutton -label $i -variable $varName
+ }
+ return $w.menu
+}
diff --git a/tk8.6/library/palette.tcl b/tk8.6/library/palette.tcl
new file mode 100644
index 0000000..42c6a90
--- /dev/null
+++ b/tk8.6/library/palette.tcl
@@ -0,0 +1,244 @@
+# palette.tcl --
+#
+# This file contains procedures that change the color palette used
+# by Tk.
+#
+# 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.
+#
+
+# ::tk_setPalette --
+# Changes the default color scheme for a Tk application by setting
+# default colors in the option database and by modifying all of the
+# color options for existing widgets that have the default value.
+#
+# Arguments:
+# The arguments consist of either a single color name, which
+# will be used as the new background color (all other colors will
+# be computed from this) or an even number of values consisting of
+# option names and values. The name for an option is the one used
+# for the option database, such as activeForeground, not -activeforeground.
+
+proc ::tk_setPalette {args} {
+ if {[winfo depth .] == 1} {
+ # Just return on monochrome displays, otherwise errors will occur
+ return
+ }
+
+ # Create an array that has the complete new palette. If some colors
+ # aren't specified, compute them from other colors that are specified.
+
+ if {[llength $args] == 1} {
+ set new(background) [lindex $args 0]
+ } else {
+ array set new $args
+ }
+ if {![info exists new(background)]} {
+ return -code error -errorcode {TK SET_PALETTE BACKGROUND} \
+ "must specify a background color"
+ }
+ set bg [winfo rgb . $new(background)]
+ if {![info exists new(foreground)]} {
+ # Note that the range of each value in the triple returned by
+ # [winfo rgb] is 0-65535, and your eyes are more sensitive to
+ # green than to red, and more to red than to blue.
+ foreach {r g b} $bg {break}
+ if {$r+1.5*$g+0.5*$b > 100000} {
+ set new(foreground) black
+ } else {
+ set new(foreground) white
+ }
+ }
+ lassign [winfo rgb . $new(foreground)] fg_r fg_g fg_b
+ lassign $bg bg_r bg_g bg_b
+ set darkerBg [format #%02x%02x%02x [expr {(9*$bg_r)/2560}] \
+ [expr {(9*$bg_g)/2560}] [expr {(9*$bg_b)/2560}]]
+
+ foreach i {activeForeground insertBackground selectForeground \
+ highlightColor} {
+ if {![info exists new($i)]} {
+ set new($i) $new(foreground)
+ }
+ }
+ if {![info exists new(disabledForeground)]} {
+ set new(disabledForeground) [format #%02x%02x%02x \
+ [expr {(3*$bg_r + $fg_r)/1024}] \
+ [expr {(3*$bg_g + $fg_g)/1024}] \
+ [expr {(3*$bg_b + $fg_b)/1024}]]
+ }
+ if {![info exists new(highlightBackground)]} {
+ set new(highlightBackground) $new(background)
+ }
+ if {![info exists new(activeBackground)]} {
+ # Pick a default active background that islighter than the
+ # normal background. To do this, round each color component
+ # up by 15% or 1/3 of the way to full white, whichever is
+ # greater.
+
+ foreach i {0 1 2} color $bg {
+ set light($i) [expr {$color/256}]
+ set inc1 [expr {($light($i)*15)/100}]
+ set inc2 [expr {(255-$light($i))/3}]
+ if {$inc1 > $inc2} {
+ incr light($i) $inc1
+ } else {
+ incr light($i) $inc2
+ }
+ if {$light($i) > 255} {
+ set light($i) 255
+ }
+ }
+ set new(activeBackground) [format #%02x%02x%02x $light(0) \
+ $light(1) $light(2)]
+ }
+ if {![info exists new(selectBackground)]} {
+ set new(selectBackground) $darkerBg
+ }
+ if {![info exists new(troughColor)]} {
+ set new(troughColor) $darkerBg
+ }
+
+ # let's make one of each of the widgets so we know what the
+ # defaults are currently for this platform.
+ toplevel .___tk_set_palette
+ wm withdraw .___tk_set_palette
+ foreach q {
+ button canvas checkbutton entry frame label labelframe
+ listbox menubutton menu message radiobutton scale scrollbar
+ spinbox text
+ } {
+ $q .___tk_set_palette.$q
+ }
+
+ # Walk the widget hierarchy, recoloring all existing windows.
+ # The option database must be set according to what we do here,
+ # but it breaks things if we set things in the database while
+ # we are changing colors...so, ::tk::RecolorTree now returns the
+ # option database changes that need to be made, and they
+ # need to be evalled here to take effect.
+ # We have to walk the whole widget tree instead of just
+ # relying on the widgets we've created above to do the work
+ # because different extensions may provide other kinds
+ # of widgets that we don't currently know about, so we'll
+ # walk the whole hierarchy just in case.
+
+ eval [tk::RecolorTree . new]
+
+ destroy .___tk_set_palette
+
+ # Change the option database so that future windows will get the
+ # same colors.
+
+ foreach option [array names new] {
+ option add *$option $new($option) widgetDefault
+ }
+
+ # Save the options in the variable ::tk::Palette, for use the
+ # next time we change the options.
+
+ array set ::tk::Palette [array get new]
+}
+
+# ::tk::RecolorTree --
+# This procedure changes the colors in a window and all of its
+# descendants, according to information provided by the colors
+# argument. This looks at the defaults provided by the option
+# database, if it exists, and if not, then it looks at the default
+# value of the widget itself.
+#
+# Arguments:
+# w - The name of a window. This window and all its
+# descendants are recolored.
+# colors - The name of an array variable in the caller,
+# which contains color information. Each element
+# is named after a widget configuration option, and
+# each value is the value for that option.
+
+proc ::tk::RecolorTree {w colors} {
+ upvar $colors c
+ set result {}
+ set prototype .___tk_set_palette.[string tolower [winfo class $w]]
+ if {![winfo exists $prototype]} {
+ unset prototype
+ }
+ foreach dbOption [array names c] {
+ set option -[string tolower $dbOption]
+ set class [string replace $dbOption 0 0 [string toupper \
+ [string index $dbOption 0]]]
+ if {![catch {$w configure $option} value]} {
+ # if the option database has a preference for this
+ # dbOption, then use it, otherwise use the defaults
+ # for the widget.
+ set defaultcolor [option get $w $dbOption $class]
+ if {$defaultcolor eq "" || \
+ ([info exists prototype] && \
+ [$prototype cget $option] ne "$defaultcolor")} {
+ set defaultcolor [lindex $value 3]
+ }
+ if {$defaultcolor ne ""} {
+ set defaultcolor [winfo rgb . $defaultcolor]
+ }
+ set chosencolor [lindex $value 4]
+ if {$chosencolor ne ""} {
+ set chosencolor [winfo rgb . $chosencolor]
+ }
+ if {[string match $defaultcolor $chosencolor]} {
+ # Change the option database so that future windows will get
+ # the same colors.
+ append result ";\noption add [list \
+ *[winfo class $w].$dbOption $c($dbOption) 60]"
+ $w configure $option $c($dbOption)
+ }
+ }
+ }
+ foreach child [winfo children $w] {
+ append result ";\n[::tk::RecolorTree $child c]"
+ }
+ return $result
+}
+
+# ::tk::Darken --
+# Given a color name, computes a new color value that darkens (or
+# brightens) the given color by a given percent.
+#
+# Arguments:
+# color - Name of starting color.
+# percent - Integer telling how much to brighten or darken as a
+# percent: 50 means darken by 50%, 110 means brighten
+# by 10%.
+
+proc ::tk::Darken {color percent} {
+ if {$percent < 0} {
+ return #000000
+ } elseif {$percent > 200} {
+ return #ffffff
+ } elseif {$percent <= 100} {
+ lassign [winfo rgb . $color] r g b
+ set r [expr {($r/256)*$percent/100}]
+ set g [expr {($g/256)*$percent/100}]
+ set b [expr {($b/256)*$percent/100}]
+ } elseif {$percent > 100} {
+ lassign [winfo rgb . $color] r g b
+ set r [expr {255 - ((65535-$r)/256)*(200-$percent)/100}]
+ set g [expr {255 - ((65535-$g)/256)*(200-$percent)/100}]
+ set b [expr {255 - ((65535-$b)/256)*(200-$percent)/100}]
+ }
+ return [format #%02x%02x%02x $r $g $b]
+}
+
+# ::tk_bisque --
+# Reset the Tk color palette to the old "bisque" colors.
+#
+# Arguments:
+# None.
+
+proc ::tk_bisque {} {
+ tk_setPalette activeBackground #e6ceb1 activeForeground black \
+ background #ffe4c4 disabledForeground #b0b0b0 foreground black \
+ highlightBackground #ffe4c4 highlightColor black \
+ insertBackground black \
+ selectBackground #e6ceb1 selectForeground black \
+ troughColor #cdb79e
+}
diff --git a/tk8.6/library/panedwindow.tcl b/tk8.6/library/panedwindow.tcl
new file mode 100644
index 0000000..d3dfabc
--- /dev/null
+++ b/tk8.6/library/panedwindow.tcl
@@ -0,0 +1,194 @@
+# panedwindow.tcl --
+#
+# This file defines the default bindings for Tk panedwindow widgets and
+# provides procedures that help in implementing those bindings.
+
+bind Panedwindow <Button-1> { ::tk::panedwindow::MarkSash %W %x %y 1 }
+bind Panedwindow <Button-2> { ::tk::panedwindow::MarkSash %W %x %y 0 }
+
+bind Panedwindow <B1-Motion> { ::tk::panedwindow::DragSash %W %x %y 1 }
+bind Panedwindow <B2-Motion> { ::tk::panedwindow::DragSash %W %x %y 0 }
+
+bind Panedwindow <ButtonRelease-1> {::tk::panedwindow::ReleaseSash %W 1}
+bind Panedwindow <ButtonRelease-2> {::tk::panedwindow::ReleaseSash %W 0}
+
+bind Panedwindow <Motion> { ::tk::panedwindow::Motion %W %x %y }
+
+bind Panedwindow <Leave> { ::tk::panedwindow::Leave %W }
+
+# Initialize namespace
+namespace eval ::tk::panedwindow {}
+
+# ::tk::panedwindow::MarkSash --
+#
+# Handle marking the correct sash for possible dragging
+#
+# Arguments:
+# w the widget
+# x widget local x coord
+# y widget local y coord
+# proxy whether this should be a proxy sash
+# Results:
+# None
+#
+proc ::tk::panedwindow::MarkSash {w x y proxy} {
+ variable ::tk::Priv
+ if {[$w cget -opaqueresize]} {
+ set proxy 0
+ }
+ set what [$w identify $x $y]
+ if { [llength $what] == 2 } {
+ lassign $what index which
+ if {!$::tk_strictMotif || $which eq "handle"} {
+ if {!$proxy} {
+ $w sash mark $index $x $y
+ }
+ set Priv(sash) $index
+ lassign [$w sash coord $index] sx sy
+ set Priv(dx) [expr {$sx-$x}]
+ set Priv(dy) [expr {$sy-$y}]
+ # Do this to init the proxy location
+ DragSash $w $x $y $proxy
+ }
+ }
+}
+
+# ::tk::panedwindow::DragSash --
+#
+# Handle dragging of the correct sash
+#
+# Arguments:
+# w the widget
+# x widget local x coord
+# y widget local y coord
+# proxy whether this should be a proxy sash
+# Results:
+# Moves sash
+#
+proc ::tk::panedwindow::DragSash {w x y proxy} {
+ variable ::tk::Priv
+ if {[$w cget -opaqueresize]} {
+ set proxy 0
+ }
+ if {[info exists Priv(sash)]} {
+ if {$proxy} {
+ $w proxy place [expr {$x+$Priv(dx)}] [expr {$y+$Priv(dy)}]
+ } else {
+ $w sash place $Priv(sash) \
+ [expr {$x+$Priv(dx)}] [expr {$y+$Priv(dy)}]
+ }
+ }
+}
+
+# ::tk::panedwindow::ReleaseSash --
+#
+# Handle releasing of the sash
+#
+# Arguments:
+# w the widget
+# proxy whether this should be a proxy sash
+# Results:
+# Returns ...
+#
+proc ::tk::panedwindow::ReleaseSash {w proxy} {
+ variable ::tk::Priv
+ if {[$w cget -opaqueresize]} {
+ set proxy 0
+ }
+ if {[info exists Priv(sash)]} {
+ if {$proxy} {
+ lassign [$w proxy coord] x y
+ $w sash place $Priv(sash) $x $y
+ $w proxy forget
+ }
+ unset Priv(sash) Priv(dx) Priv(dy)
+ }
+}
+
+# ::tk::panedwindow::Motion --
+#
+# Handle motion on the widget. This is used to change the cursor
+# when the user moves over the sash area.
+#
+# Arguments:
+# w the widget
+# x widget local x coord
+# y widget local y coord
+# Results:
+# May change the cursor. Sets up a timer to verify that we are still
+# over the widget.
+#
+proc ::tk::panedwindow::Motion {w x y} {
+ variable ::tk::Priv
+ set id [$w identify $x $y]
+ if {([llength $id] == 2) && \
+ (!$::tk_strictMotif || [lindex $id 1] eq "handle")} {
+ if {![info exists Priv($w,panecursor)]} {
+ set Priv($w,panecursor) [$w cget -cursor]
+ if {[$w cget -sashcursor] ne ""} {
+ $w configure -cursor [$w cget -sashcursor]
+ } elseif {[$w cget -orient] eq "horizontal"} {
+ $w configure -cursor sb_h_double_arrow
+ } else {
+ $w configure -cursor sb_v_double_arrow
+ }
+ if {[info exists Priv($w,pwAfterId)]} {
+ after cancel $Priv($w,pwAfterId)
+ }
+ set Priv($w,pwAfterId) [after 150 \
+ [list ::tk::panedwindow::Cursor $w]]
+ }
+ return
+ }
+ if {[info exists Priv($w,panecursor)]} {
+ $w configure -cursor $Priv($w,panecursor)
+ unset Priv($w,panecursor)
+ }
+}
+
+# ::tk::panedwindow::Cursor --
+#
+# Handles returning the normal cursor when we are no longer over the
+# sash area. This needs to be done this way, because the panedwindow
+# won't see Leave events when the mouse moves from the sash to a
+# paned child, although the child does receive an Enter event.
+#
+# Arguments:
+# w the widget
+# Results:
+# May restore the default cursor, or schedule a timer to do it.
+#
+proc ::tk::panedwindow::Cursor {w} {
+ variable ::tk::Priv
+ # Make sure to check window existence in case it is destroyed.
+ if {[info exists Priv($w,panecursor)] && [winfo exists $w]} {
+ if {[winfo containing [winfo pointerx $w] [winfo pointery $w]] eq $w} {
+ set Priv($w,pwAfterId) [after 150 \
+ [list ::tk::panedwindow::Cursor $w]]
+ } else {
+ $w configure -cursor $Priv($w,panecursor)
+ unset Priv($w,panecursor)
+ if {[info exists Priv($w,pwAfterId)]} {
+ after cancel $Priv($w,pwAfterId)
+ unset Priv($w,pwAfterId)
+ }
+ }
+ }
+}
+
+# ::tk::panedwindow::Leave --
+#
+# Return to default cursor when leaving the pw widget.
+#
+# Arguments:
+# w the widget
+# Results:
+# Restores the default cursor
+#
+proc ::tk::panedwindow::Leave {w} {
+ variable ::tk::Priv
+ if {[info exists Priv($w,panecursor)]} {
+ $w configure -cursor $Priv($w,panecursor)
+ unset Priv($w,panecursor)
+ }
+}
diff --git a/tk8.6/library/safetk.tcl b/tk8.6/library/safetk.tcl
new file mode 100644
index 0000000..9f8e25d
--- /dev/null
+++ b/tk8.6/library/safetk.tcl
@@ -0,0 +1,262 @@
+# safetk.tcl --
+#
+# Support procs to use Tk in safe interpreters.
+#
+# 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.
+
+# see safetk.n for documentation
+
+#
+#
+# Note: It is now ok to let untrusted code being executed
+# between the creation of the interp and the actual loading
+# of Tk in that interp because the C side Tk_Init will
+# now look up the master interp and ask its safe::TkInit
+# for the actual parameters to use for it's initialization (if allowed),
+# not relying on the slave state.
+#
+
+# We use opt (optional arguments parsing)
+package require opt 0.4.1;
+
+namespace eval ::safe {
+
+ # counter for safe toplevels
+ variable tkSafeId 0
+}
+
+#
+# tkInterpInit : prepare the slave interpreter for tk loading
+# most of the real job is done by loadTk
+# returns the slave name (tkInterpInit does)
+#
+proc ::safe::tkInterpInit {slave argv} {
+ global env tk_library
+
+ # We have to make sure that the tk_library variable is normalized.
+ set tk_library [file normalize $tk_library]
+
+ # Clear Tk's access for that interp (path).
+ allowTk $slave $argv
+
+ # Ensure tk_library and subdirs (eg, ttk) are on the access path
+ ::interp eval $slave [list set tk_library [::safe::interpAddToAccessPath $slave $tk_library]]
+ foreach subdir [::safe::AddSubDirs [list $tk_library]] {
+ ::safe::interpAddToAccessPath $slave $subdir
+ }
+ return $slave
+}
+
+
+# tkInterpLoadTk:
+# Do additional configuration as needed (calling tkInterpInit)
+# and actually load Tk into the slave.
+#
+# Either contained in the specified windowId (-use) or
+# creating a decorated toplevel for it.
+
+# empty definition for auto_mkIndex
+proc ::safe::loadTk {} {}
+
+::tcl::OptProc ::safe::loadTk {
+ {slave -interp "name of the slave interpreter"}
+ {-use -windowId {} "window Id to use (new toplevel otherwise)"}
+ {-display -displayName {} "display name to use (current one otherwise)"}
+} {
+ set displayGiven [::tcl::OptProcArgGiven "-display"]
+ if {!$displayGiven} {
+ # Try to get the current display from "."
+ # (which might not exist if the master is tk-less)
+ if {[catch {set display [winfo screen .]}]} {
+ if {[info exists ::env(DISPLAY)]} {
+ set display $::env(DISPLAY)
+ } else {
+ Log $slave "no winfo screen . nor env(DISPLAY)" WARNING
+ set display ":0.0"
+ }
+ }
+ }
+
+ # Get state for access to the cleanupHook.
+ namespace upvar ::safe S$slave state
+
+ if {![::tcl::OptProcArgGiven "-use"]} {
+ # create a decorated toplevel
+ lassign [tkTopLevel $slave $display] w use
+
+ # set our delete hook (slave arg is added by interpDelete)
+ # to clean up both window related code and tkInit(slave)
+ set state(cleanupHook) [list tkDelete {} $w]
+ } else {
+ # set our delete hook (slave arg is added by interpDelete)
+ # to clean up tkInit(slave)
+ set state(cleanupHook) [list disallowTk]
+
+ # Let's be nice and also accept tk window names instead of ids
+ if {[string match ".*" $use]} {
+ set windowName $use
+ set use [winfo id $windowName]
+ set nDisplay [winfo screen $windowName]
+ } else {
+ # Check for a better -display value
+ # (works only for multi screens on single host, but not
+ # cross hosts, for that a tk window name would be better
+ # but embeding is also usefull for non tk names)
+ if {![catch {winfo pathname $use} name]} {
+ set nDisplay [winfo screen $name]
+ } else {
+ # Can't have a better one
+ set nDisplay $display
+ }
+ }
+ if {$nDisplay ne $display} {
+ if {$displayGiven} {
+ return -code error -errorcode {TK DISPLAY SAFE} \
+ "conflicting -display $display and -use $use -> $nDisplay"
+ } else {
+ set display $nDisplay
+ }
+ }
+ }
+
+ # Prepares the slave for tk with those parameters
+ tkInterpInit $slave [list "-use" $use "-display" $display]
+
+ load {} Tk $slave
+
+ return $slave
+}
+
+proc ::safe::TkInit {interpPath} {
+ variable tkInit
+ if {[info exists tkInit($interpPath)]} {
+ set value $tkInit($interpPath)
+ Log $interpPath "TkInit called, returning \"$value\"" NOTICE
+ return $value
+ } else {
+ Log $interpPath "TkInit called for interp with clearance:\
+ preventing Tk init" ERROR
+ return -code error -errorcode {TK SAFE PERMISSION} "not allowed"
+ }
+}
+
+# safe::allowTk --
+#
+# Set tkInit(interpPath) to allow Tk to be initialized in
+# safe::TkInit.
+#
+# Arguments:
+# interpPath slave interpreter handle
+# argv arguments passed to safe::TkInterpInit
+#
+# Results:
+# none.
+
+proc ::safe::allowTk {interpPath argv} {
+ variable tkInit
+ set tkInit($interpPath) $argv
+ return
+}
+
+
+# safe::disallowTk --
+#
+# Unset tkInit(interpPath) to disallow Tk from getting initialized
+# in safe::TkInit.
+#
+# Arguments:
+# interpPath slave interpreter handle
+#
+# Results:
+# none.
+
+proc ::safe::disallowTk {interpPath} {
+ variable tkInit
+ # This can already be deleted by the DeleteHook of the interp
+ if {[info exists tkInit($interpPath)]} {
+ unset tkInit($interpPath)
+ }
+ return
+}
+
+
+# safe::tkDelete --
+#
+# Clean up the window associated with the interp being deleted.
+#
+# Arguments:
+# interpPath slave interpreter handle
+#
+# Results:
+# none.
+
+proc ::safe::tkDelete {W window slave} {
+
+ # we are going to be called for each widget... skip untill it's
+ # top level
+
+ Log $slave "Called tkDelete $W $window" NOTICE
+ if {[::interp exists $slave]} {
+ if {[catch {::safe::interpDelete $slave} msg]} {
+ Log $slave "Deletion error : $msg"
+ }
+ }
+ if {[winfo exists $window]} {
+ Log $slave "Destroy toplevel $window" NOTICE
+ destroy $window
+ }
+
+ # clean up tkInit(slave)
+ disallowTk $slave
+ return
+}
+
+proc ::safe::tkTopLevel {slave display} {
+ variable tkSafeId
+ incr tkSafeId
+ set w ".safe$tkSafeId"
+ if {[catch {toplevel $w -screen $display -class SafeTk} msg]} {
+ return -code error -errorcode {TK TOPLEVEL SAFE} \
+ "Unable to create toplevel for safe slave \"$slave\" ($msg)"
+ }
+ Log $slave "New toplevel $w" NOTICE
+
+ set msg "Untrusted Tcl applet ($slave)"
+ wm title $w $msg
+
+ # Control frame (we must create a style for it)
+ ttk::style layout TWarningFrame {WarningFrame.border -sticky nswe}
+ ttk::style configure TWarningFrame -background red
+
+ set wc $w.fc
+ ttk::frame $wc -relief ridge -borderwidth 4 -style TWarningFrame
+
+ # We will destroy the interp when the window is destroyed
+ bindtags $wc [concat Safe$wc [bindtags $wc]]
+ bind Safe$wc <Destroy> [list ::safe::tkDelete %W $w $slave]
+
+ ttk::label $wc.l -text $msg -anchor w
+
+ # We want the button to be the last visible item
+ # (so be packed first) and at the right and not resizing horizontally
+
+ # frame the button so it does not expand horizontally
+ # but still have the default background instead of red one from the parent
+ ttk::frame $wc.fb -borderwidth 0
+ ttk::button $wc.fb.b -text "Delete" \
+ -command [list ::safe::tkDelete $w $w $slave]
+ pack $wc.fb.b -side right -fill both
+ pack $wc.fb -side right -fill both -expand 1
+ pack $wc.l -side left -fill both -expand 1 -ipady 2
+ pack $wc -side bottom -fill x
+
+ # Container frame
+ frame $w.c -container 1
+ pack $w.c -fill both -expand 1
+
+ # return both the toplevel window name and the id to use for embedding
+ list $w [winfo id $w.c]
+}
diff --git a/tk8.6/library/scale.tcl b/tk8.6/library/scale.tcl
new file mode 100644
index 0000000..fb9b81b
--- /dev/null
+++ b/tk8.6/library/scale.tcl
@@ -0,0 +1,290 @@
+# scale.tcl --
+#
+# This file defines the default bindings for Tk scale widgets and provides
+# procedures that help in implementing the bindings.
+#
+# Copyright (c) 1994 The Regents of the University of California.
+# Copyright (c) 1994-1995 Sun Microsystems, Inc.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+
+#-------------------------------------------------------------------------
+# The code below creates the default class bindings for entries.
+#-------------------------------------------------------------------------
+
+# Standard Motif bindings:
+
+bind Scale <Enter> {
+ if {$tk_strictMotif} {
+ set tk::Priv(activeBg) [%W cget -activebackground]
+ %W configure -activebackground [%W cget -background]
+ }
+ tk::ScaleActivate %W %x %y
+}
+bind Scale <Motion> {
+ tk::ScaleActivate %W %x %y
+}
+bind Scale <Leave> {
+ if {$tk_strictMotif} {
+ %W configure -activebackground $tk::Priv(activeBg)
+ }
+ if {[%W cget -state] eq "active"} {
+ %W configure -state normal
+ }
+}
+bind Scale <1> {
+ tk::ScaleButtonDown %W %x %y
+}
+bind Scale <B1-Motion> {
+ tk::ScaleDrag %W %x %y
+}
+bind Scale <B1-Leave> { }
+bind Scale <B1-Enter> { }
+bind Scale <ButtonRelease-1> {
+ tk::CancelRepeat
+ tk::ScaleEndDrag %W
+ tk::ScaleActivate %W %x %y
+}
+bind Scale <2> {
+ tk::ScaleButton2Down %W %x %y
+}
+bind Scale <B2-Motion> {
+ tk::ScaleDrag %W %x %y
+}
+bind Scale <B2-Leave> { }
+bind Scale <B2-Enter> { }
+bind Scale <ButtonRelease-2> {
+ tk::CancelRepeat
+ tk::ScaleEndDrag %W
+ tk::ScaleActivate %W %x %y
+}
+if {[tk windowingsystem] eq "win32"} {
+ # On Windows do the same with button 3, as that is the right mouse button
+ bind Scale <3> [bind Scale <2>]
+ bind Scale <B3-Motion> [bind Scale <B2-Motion>]
+ bind Scale <B3-Leave> [bind Scale <B2-Leave>]
+ bind Scale <B3-Enter> [bind Scale <B2-Enter>]
+ bind Scale <ButtonRelease-3> [bind Scale <ButtonRelease-2>]
+}
+bind Scale <Control-1> {
+ tk::ScaleControlPress %W %x %y
+}
+bind Scale <<PrevLine>> {
+ tk::ScaleIncrement %W up little noRepeat
+}
+bind Scale <<NextLine>> {
+ tk::ScaleIncrement %W down little noRepeat
+}
+bind Scale <<PrevChar>> {
+ tk::ScaleIncrement %W up little noRepeat
+}
+bind Scale <<NextChar>> {
+ tk::ScaleIncrement %W down little noRepeat
+}
+bind Scale <<PrevPara>> {
+ tk::ScaleIncrement %W up big noRepeat
+}
+bind Scale <<NextPara>> {
+ tk::ScaleIncrement %W down big noRepeat
+}
+bind Scale <<PrevWord>> {
+ tk::ScaleIncrement %W up big noRepeat
+}
+bind Scale <<NextWord>> {
+ tk::ScaleIncrement %W down big noRepeat
+}
+bind Scale <<LineStart>> {
+ %W set [%W cget -from]
+}
+bind Scale <<LineEnd>> {
+ %W set [%W cget -to]
+}
+
+# ::tk::ScaleActivate --
+# This procedure is invoked to check a given x-y position in the
+# scale and activate the slider if the x-y position falls within
+# the slider.
+#
+# Arguments:
+# w - The scale widget.
+# x, y - Mouse coordinates.
+
+proc ::tk::ScaleActivate {w x y} {
+ if {[$w cget -state] eq "disabled"} {
+ return
+ }
+ if {[$w identify $x $y] eq "slider"} {
+ set state active
+ } else {
+ set state normal
+ }
+ if {[$w cget -state] ne $state} {
+ $w configure -state $state
+ }
+}
+
+# ::tk::ScaleButtonDown --
+# This procedure is invoked when a button is pressed in a scale. It
+# takes different actions depending on where the button was pressed.
+#
+# Arguments:
+# w - The scale widget.
+# x, y - Mouse coordinates of button press.
+
+proc ::tk::ScaleButtonDown {w x y} {
+ variable ::tk::Priv
+ set Priv(dragging) 0
+ set el [$w identify $x $y]
+
+ # save the relief
+ set Priv($w,relief) [$w cget -sliderrelief]
+
+ if {$el eq "trough1"} {
+ ScaleIncrement $w up little initial
+ } elseif {$el eq "trough2"} {
+ ScaleIncrement $w down little initial
+ } elseif {$el eq "slider"} {
+ set Priv(dragging) 1
+ set Priv(initValue) [$w get]
+ set coords [$w coords]
+ set Priv(deltaX) [expr {$x - [lindex $coords 0]}]
+ set Priv(deltaY) [expr {$y - [lindex $coords 1]}]
+ switch -exact -- $Priv($w,relief) {
+ "raised" { $w configure -sliderrelief sunken }
+ "ridge" { $w configure -sliderrelief groove }
+ }
+ }
+}
+
+# ::tk::ScaleDrag --
+# This procedure is called when the mouse is dragged with
+# mouse button 1 down. If the drag started inside the slider
+# (i.e. the scale is active) then the scale's value is adjusted
+# to reflect the mouse's position.
+#
+# Arguments:
+# w - The scale widget.
+# x, y - Mouse coordinates.
+
+proc ::tk::ScaleDrag {w x y} {
+ variable ::tk::Priv
+ if {!$Priv(dragging)} {
+ return
+ }
+ $w set [$w get [expr {$x-$Priv(deltaX)}] [expr {$y-$Priv(deltaY)}]]
+}
+
+# ::tk::ScaleEndDrag --
+# This procedure is called to end an interactive drag of the
+# slider. It just marks the drag as over.
+#
+# Arguments:
+# w - The scale widget.
+
+proc ::tk::ScaleEndDrag {w} {
+ variable ::tk::Priv
+ set Priv(dragging) 0
+ if {[info exists Priv($w,relief)]} {
+ $w configure -sliderrelief $Priv($w,relief)
+ unset Priv($w,relief)
+ }
+}
+
+# ::tk::ScaleIncrement --
+# This procedure is invoked to increment the value of a scale and
+# to set up auto-repeating of the action if that is desired. The
+# way the value is incremented depends on the "dir" and "big"
+# arguments.
+#
+# Arguments:
+# w - The scale widget.
+# dir - "up" means move value towards -from, "down" means
+# move towards -to.
+# big - Size of increments: "big" or "little".
+# repeat - Whether and how to auto-repeat the action: "noRepeat"
+# means don't auto-repeat, "initial" means this is the
+# first action in an auto-repeat sequence, and "again"
+# means this is the second repetition or later.
+
+proc ::tk::ScaleIncrement {w dir big repeat} {
+ variable ::tk::Priv
+ if {![winfo exists $w]} return
+ if {$big eq "big"} {
+ set inc [$w cget -bigincrement]
+ if {$inc == 0} {
+ set inc [expr {abs([$w cget -to] - [$w cget -from])/10.0}]
+ }
+ if {$inc < [$w cget -resolution]} {
+ set inc [$w cget -resolution]
+ }
+ } else {
+ set inc [$w cget -resolution]
+ }
+ if {([$w cget -from] > [$w cget -to]) ^ ($dir eq "up")} {
+ if {$inc > 0} {
+ set inc [expr {-$inc}]
+ }
+ } else {
+ if {$inc < 0} {
+ set inc [expr {-$inc}]
+ }
+ }
+ $w set [expr {[$w get] + $inc}]
+
+ if {$repeat eq "again"} {
+ set Priv(afterId) [after [$w cget -repeatinterval] \
+ [list tk::ScaleIncrement $w $dir $big again]]
+ } elseif {$repeat eq "initial"} {
+ set delay [$w cget -repeatdelay]
+ if {$delay > 0} {
+ set Priv(afterId) [after $delay \
+ [list tk::ScaleIncrement $w $dir $big again]]
+ }
+ }
+}
+
+# ::tk::ScaleControlPress --
+# This procedure handles button presses that are made with the Control
+# key down. Depending on the mouse position, it adjusts the scale
+# value to one end of the range or the other.
+#
+# Arguments:
+# w - The scale widget.
+# x, y - Mouse coordinates where the button was pressed.
+
+proc ::tk::ScaleControlPress {w x y} {
+ set el [$w identify $x $y]
+ if {$el eq "trough1"} {
+ $w set [$w cget -from]
+ } elseif {$el eq "trough2"} {
+ $w set [$w cget -to]
+ }
+}
+
+# ::tk::ScaleButton2Down
+# This procedure is invoked when button 2 is pressed over a scale.
+# It sets the value to correspond to the mouse position and starts
+# a slider drag.
+#
+# Arguments:
+# w - The scrollbar widget.
+# x, y - Mouse coordinates within the widget.
+
+proc ::tk::ScaleButton2Down {w x y} {
+ variable ::tk::Priv
+
+ if {[$w cget -state] eq "disabled"} {
+ return
+ }
+
+ $w configure -state active
+ $w set [$w get $x $y]
+ set Priv(dragging) 1
+ set Priv(initValue) [$w get]
+ set Priv($w,relief) [$w cget -sliderrelief]
+ set coords "$x $y"
+ set Priv(deltaX) 0
+ set Priv(deltaY) 0
+}
diff --git a/tk8.6/library/scrlbar.tcl b/tk8.6/library/scrlbar.tcl
new file mode 100644
index 0000000..6f1caa2
--- /dev/null
+++ b/tk8.6/library/scrlbar.tcl
@@ -0,0 +1,454 @@
+# scrlbar.tcl --
+#
+# This file defines the default bindings for Tk scrollbar widgets.
+# It also provides procedures that help in implementing the bindings.
+#
+# Copyright (c) 1994 The Regents of the University of California.
+# Copyright (c) 1994-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.
+#
+
+#-------------------------------------------------------------------------
+# The code below creates the default class bindings for scrollbars.
+#-------------------------------------------------------------------------
+
+# Standard Motif bindings:
+if {[tk windowingsystem] eq "x11" || [tk windowingsystem] eq "aqua"} {
+
+bind Scrollbar <Enter> {
+ if {$tk_strictMotif} {
+ set tk::Priv(activeBg) [%W cget -activebackground]
+ %W configure -activebackground [%W cget -background]
+ }
+ %W activate [%W identify %x %y]
+}
+bind Scrollbar <Motion> {
+ %W activate [%W identify %x %y]
+}
+
+# The "info exists" command in the following binding handles the
+# situation where a Leave event occurs for a scrollbar without the Enter
+# event. This seems to happen on some systems (such as Solaris 2.4) for
+# unknown reasons.
+
+bind Scrollbar <Leave> {
+ if {$tk_strictMotif && [info exists tk::Priv(activeBg)]} {
+ %W configure -activebackground $tk::Priv(activeBg)
+ }
+ %W activate {}
+}
+bind Scrollbar <1> {
+ tk::ScrollButtonDown %W %x %y
+}
+bind Scrollbar <B1-Motion> {
+ tk::ScrollDrag %W %x %y
+}
+bind Scrollbar <B1-B2-Motion> {
+ tk::ScrollDrag %W %x %y
+}
+bind Scrollbar <ButtonRelease-1> {
+ tk::ScrollButtonUp %W %x %y
+}
+bind Scrollbar <B1-Leave> {
+ # Prevents <Leave> binding from being invoked.
+}
+bind Scrollbar <B1-Enter> {
+ # Prevents <Enter> binding from being invoked.
+}
+bind Scrollbar <2> {
+ tk::ScrollButton2Down %W %x %y
+}
+bind Scrollbar <B1-2> {
+ # Do nothing, since button 1 is already down.
+}
+bind Scrollbar <B2-1> {
+ # Do nothing, since button 2 is already down.
+}
+bind Scrollbar <B2-Motion> {
+ tk::ScrollDrag %W %x %y
+}
+bind Scrollbar <ButtonRelease-2> {
+ tk::ScrollButtonUp %W %x %y
+}
+bind Scrollbar <B1-ButtonRelease-2> {
+ # Do nothing: B1 release will handle it.
+}
+bind Scrollbar <B2-ButtonRelease-1> {
+ # Do nothing: B2 release will handle it.
+}
+bind Scrollbar <B2-Leave> {
+ # Prevents <Leave> binding from being invoked.
+}
+bind Scrollbar <B2-Enter> {
+ # Prevents <Enter> binding from being invoked.
+}
+bind Scrollbar <Control-1> {
+ tk::ScrollTopBottom %W %x %y
+}
+bind Scrollbar <Control-2> {
+ tk::ScrollTopBottom %W %x %y
+}
+
+bind Scrollbar <<PrevLine>> {
+ tk::ScrollByUnits %W v -1
+}
+bind Scrollbar <<NextLine>> {
+ tk::ScrollByUnits %W v 1
+}
+bind Scrollbar <<PrevPara>> {
+ tk::ScrollByPages %W v -1
+}
+bind Scrollbar <<NextPara>> {
+ tk::ScrollByPages %W v 1
+}
+bind Scrollbar <<PrevChar>> {
+ tk::ScrollByUnits %W h -1
+}
+bind Scrollbar <<NextChar>> {
+ tk::ScrollByUnits %W h 1
+}
+bind Scrollbar <<PrevWord>> {
+ tk::ScrollByPages %W h -1
+}
+bind Scrollbar <<NextWord>> {
+ tk::ScrollByPages %W h 1
+}
+bind Scrollbar <Prior> {
+ tk::ScrollByPages %W hv -1
+}
+bind Scrollbar <Next> {
+ tk::ScrollByPages %W hv 1
+}
+bind Scrollbar <<LineStart>> {
+ tk::ScrollToPos %W 0
+}
+bind Scrollbar <<LineEnd>> {
+ tk::ScrollToPos %W 1
+}
+}
+switch [tk windowingsystem] {
+ "aqua" {
+ bind Scrollbar <MouseWheel> {
+ tk::ScrollByUnits %W v [expr {- (%D)}]
+ }
+ bind Scrollbar <Option-MouseWheel> {
+ tk::ScrollByUnits %W v [expr {-10 * (%D)}]
+ }
+ bind Scrollbar <Shift-MouseWheel> {
+ tk::ScrollByUnits %W h [expr {- (%D)}]
+ }
+ bind Scrollbar <Shift-Option-MouseWheel> {
+ tk::ScrollByUnits %W h [expr {-10 * (%D)}]
+ }
+ }
+ "win32" {
+ bind Scrollbar <MouseWheel> {
+ tk::ScrollByUnits %W v [expr {- (%D / 120) * 4}]
+ }
+ bind Scrollbar <Shift-MouseWheel> {
+ tk::ScrollByUnits %W h [expr {- (%D / 120) * 4}]
+ }
+ }
+ "x11" {
+ bind Scrollbar <MouseWheel> {
+ tk::ScrollByUnits %W v [expr {- (%D /120 ) * 4}]
+ }
+ bind Scrollbar <Shift-MouseWheel> {
+ tk::ScrollByUnits %W h [expr {- (%D /120 ) * 4}]
+ }
+ bind Scrollbar <4> {tk::ScrollByUnits %W v -5}
+ bind Scrollbar <5> {tk::ScrollByUnits %W v 5}
+ bind Scrollbar <Shift-4> {tk::ScrollByUnits %W h -5}
+ bind Scrollbar <Shift-5> {tk::ScrollByUnits %W h 5}
+ }
+}
+# tk::ScrollButtonDown --
+# This procedure is invoked when a button is pressed in a scrollbar.
+# It changes the way the scrollbar is displayed and takes actions
+# depending on where the mouse is.
+#
+# Arguments:
+# w - The scrollbar widget.
+# x, y - Mouse coordinates.
+
+proc tk::ScrollButtonDown {w x y} {
+ variable ::tk::Priv
+ set Priv(relief) [$w cget -activerelief]
+ $w configure -activerelief sunken
+ set element [$w identify $x $y]
+ if {$element eq "slider"} {
+ ScrollStartDrag $w $x $y
+ } else {
+ ScrollSelect $w $element initial
+ }
+}
+
+# ::tk::ScrollButtonUp --
+# This procedure is invoked when a button is released in a scrollbar.
+# It cancels scans and auto-repeats that were in progress, and restores
+# the way the active element is displayed.
+#
+# Arguments:
+# w - The scrollbar widget.
+# x, y - Mouse coordinates.
+
+proc ::tk::ScrollButtonUp {w x y} {
+ variable ::tk::Priv
+ tk::CancelRepeat
+ if {[info exists Priv(relief)]} {
+ # Avoid error due to spurious release events
+ $w configure -activerelief $Priv(relief)
+ ScrollEndDrag $w $x $y
+ $w activate [$w identify $x $y]
+ }
+}
+
+# ::tk::ScrollSelect --
+# This procedure is invoked when a button is pressed over the scrollbar.
+# It invokes one of several scrolling actions depending on where in
+# the scrollbar the button was pressed.
+#
+# Arguments:
+# w - The scrollbar widget.
+# element - The element of the scrollbar that was selected, such
+# as "arrow1" or "trough2". Shouldn't be "slider".
+# repeat - Whether and how to auto-repeat the action: "noRepeat"
+# means don't auto-repeat, "initial" means this is the
+# first action in an auto-repeat sequence, and "again"
+# means this is the second repetition or later.
+
+proc ::tk::ScrollSelect {w element repeat} {
+ variable ::tk::Priv
+ if {![winfo exists $w]} return
+ switch -- $element {
+ "arrow1" {ScrollByUnits $w hv -1}
+ "trough1" {ScrollByPages $w hv -1}
+ "trough2" {ScrollByPages $w hv 1}
+ "arrow2" {ScrollByUnits $w hv 1}
+ default {return}
+ }
+ if {$repeat eq "again"} {
+ set Priv(afterId) [after [$w cget -repeatinterval] \
+ [list tk::ScrollSelect $w $element again]]
+ } elseif {$repeat eq "initial"} {
+ set delay [$w cget -repeatdelay]
+ if {$delay > 0} {
+ set Priv(afterId) [after $delay \
+ [list tk::ScrollSelect $w $element again]]
+ }
+ }
+}
+
+# ::tk::ScrollStartDrag --
+# This procedure is called to initiate a drag of the slider. It just
+# remembers the starting position of the mouse and slider.
+#
+# Arguments:
+# w - The scrollbar widget.
+# x, y - The mouse position at the start of the drag operation.
+
+proc ::tk::ScrollStartDrag {w x y} {
+ variable ::tk::Priv
+
+ if {[$w cget -command] eq ""} {
+ return
+ }
+ set Priv(pressX) $x
+ set Priv(pressY) $y
+ set Priv(initValues) [$w get]
+ set iv0 [lindex $Priv(initValues) 0]
+ if {[llength $Priv(initValues)] == 2} {
+ set Priv(initPos) $iv0
+ } elseif {$iv0 == 0} {
+ set Priv(initPos) 0.0
+ } else {
+ set Priv(initPos) [expr {(double([lindex $Priv(initValues) 2])) \
+ / [lindex $Priv(initValues) 0]}]
+ }
+}
+
+# ::tk::ScrollDrag --
+# This procedure is called for each mouse motion even when the slider
+# is being dragged. It notifies the associated widget if we're not
+# jump scrolling, and it just updates the scrollbar if we are jump
+# scrolling.
+#
+# Arguments:
+# w - The scrollbar widget.
+# x, y - The current mouse position.
+
+proc ::tk::ScrollDrag {w x y} {
+ variable ::tk::Priv
+
+ if {$Priv(initPos) eq ""} {
+ return
+ }
+ set delta [$w delta [expr {$x - $Priv(pressX)}] [expr {$y - $Priv(pressY)}]]
+ if {[$w cget -jump]} {
+ if {[llength $Priv(initValues)] == 2} {
+ $w set [expr {[lindex $Priv(initValues) 0] + $delta}] \
+ [expr {[lindex $Priv(initValues) 1] + $delta}]
+ } else {
+ set delta [expr {round($delta * [lindex $Priv(initValues) 0])}]
+ eval [list $w] set [lreplace $Priv(initValues) 2 3 \
+ [expr {[lindex $Priv(initValues) 2] + $delta}] \
+ [expr {[lindex $Priv(initValues) 3] + $delta}]]
+ }
+ } else {
+ ScrollToPos $w [expr {$Priv(initPos) + $delta}]
+ }
+}
+
+# ::tk::ScrollEndDrag --
+# This procedure is called to end an interactive drag of the slider.
+# It scrolls the window if we're in jump mode, otherwise it does nothing.
+#
+# Arguments:
+# w - The scrollbar widget.
+# x, y - The mouse position at the end of the drag operation.
+
+proc ::tk::ScrollEndDrag {w x y} {
+ variable ::tk::Priv
+
+ if {$Priv(initPos) eq ""} {
+ return
+ }
+ if {[$w cget -jump]} {
+ set delta [$w delta [expr {$x - $Priv(pressX)}] \
+ [expr {$y - $Priv(pressY)}]]
+ ScrollToPos $w [expr {$Priv(initPos) + $delta}]
+ }
+ set Priv(initPos) ""
+}
+
+# ::tk::ScrollByUnits --
+# This procedure tells the scrollbar's associated widget to scroll up
+# or down by a given number of units. It notifies the associated widget
+# in different ways for old and new command syntaxes.
+#
+# Arguments:
+# w - The scrollbar widget.
+# orient - Which kinds of scrollbars this applies to: "h" for
+# horizontal, "v" for vertical, "hv" for both.
+# amount - How many units to scroll: typically 1 or -1.
+
+proc ::tk::ScrollByUnits {w orient amount} {
+ set cmd [$w cget -command]
+ if {$cmd eq "" || ([string first \
+ [string index [$w cget -orient] 0] $orient] < 0)} {
+ return
+ }
+ set info [$w get]
+ if {[llength $info] == 2} {
+ uplevel #0 $cmd scroll $amount units
+ } else {
+ uplevel #0 $cmd [expr {[lindex $info 2] + $amount}]
+ }
+}
+
+# ::tk::ScrollByPages --
+# This procedure tells the scrollbar's associated widget to scroll up
+# or down by a given number of screenfuls. It notifies the associated
+# widget in different ways for old and new command syntaxes.
+#
+# Arguments:
+# w - The scrollbar widget.
+# orient - Which kinds of scrollbars this applies to: "h" for
+# horizontal, "v" for vertical, "hv" for both.
+# amount - How many screens to scroll: typically 1 or -1.
+
+proc ::tk::ScrollByPages {w orient amount} {
+ set cmd [$w cget -command]
+ if {$cmd eq "" || ([string first \
+ [string index [$w cget -orient] 0] $orient] < 0)} {
+ return
+ }
+ set info [$w get]
+ if {[llength $info] == 2} {
+ uplevel #0 $cmd scroll $amount pages
+ } else {
+ uplevel #0 $cmd [expr {[lindex $info 2] + $amount*([lindex $info 1] - 1)}]
+ }
+}
+
+# ::tk::ScrollToPos --
+# This procedure tells the scrollbar's associated widget to scroll to
+# a particular location, given by a fraction between 0 and 1. It notifies
+# the associated widget in different ways for old and new command syntaxes.
+#
+# Arguments:
+# w - The scrollbar widget.
+# pos - A fraction between 0 and 1 indicating a desired position
+# in the document.
+
+proc ::tk::ScrollToPos {w pos} {
+ set cmd [$w cget -command]
+ if {$cmd eq ""} {
+ return
+ }
+ set info [$w get]
+ if {[llength $info] == 2} {
+ uplevel #0 $cmd moveto $pos
+ } else {
+ uplevel #0 $cmd [expr {round([lindex $info 0]*$pos)}]
+ }
+}
+
+# ::tk::ScrollTopBottom
+# Scroll to the top or bottom of the document, depending on the mouse
+# position.
+#
+# Arguments:
+# w - The scrollbar widget.
+# x, y - Mouse coordinates within the widget.
+
+proc ::tk::ScrollTopBottom {w x y} {
+ variable ::tk::Priv
+ set element [$w identify $x $y]
+ if {[string match *1 $element]} {
+ ScrollToPos $w 0
+ } elseif {[string match *2 $element]} {
+ ScrollToPos $w 1
+ }
+
+ # Set Priv(relief), since it's needed by tk::ScrollButtonUp.
+
+ set Priv(relief) [$w cget -activerelief]
+}
+
+# ::tk::ScrollButton2Down
+# This procedure is invoked when button 2 is pressed over a scrollbar.
+# If the button is over the trough or slider, it sets the scrollbar to
+# the mouse position and starts a slider drag. Otherwise it just
+# behaves the same as button 1.
+#
+# Arguments:
+# w - The scrollbar widget.
+# x, y - Mouse coordinates within the widget.
+
+proc ::tk::ScrollButton2Down {w x y} {
+ variable ::tk::Priv
+ if {![winfo exists $w]} {
+ return
+ }
+ set element [$w identify $x $y]
+ if {[string match {arrow[12]} $element]} {
+ ScrollButtonDown $w $x $y
+ return
+ }
+ ScrollToPos $w [$w fraction $x $y]
+ set Priv(relief) [$w cget -activerelief]
+
+ # Need the "update idletasks" below so that the widget calls us
+ # back to reset the actual scrollbar position before we start the
+ # slider drag.
+
+ update idletasks
+ if {[winfo exists $w]} {
+ $w configure -activerelief sunken
+ $w activate slider
+ ScrollStartDrag $w $x $y
+ }
+}
diff --git a/tk8.6/library/spinbox.tcl b/tk8.6/library/spinbox.tcl
new file mode 100644
index 0000000..1965ed8
--- /dev/null
+++ b/tk8.6/library/spinbox.tcl
@@ -0,0 +1,580 @@
+# spinbox.tcl --
+#
+# This file defines the default bindings for Tk spinbox widgets and provides
+# procedures that help in implementing those bindings. The spinbox builds
+# off the entry widget, so it can reuse Entry bindings and procedures.
+#
+# Copyright (c) 1992-1994 The Regents of the University of California.
+# Copyright (c) 1994-1997 Sun Microsystems, Inc.
+# Copyright (c) 1999-2000 Jeffrey Hobbs
+# Copyright (c) 2000 Ajuba Solutions
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+
+#-------------------------------------------------------------------------
+# Elements of tk::Priv that are used in this file:
+#
+# afterId - If non-null, it means that auto-scanning is underway
+# and it gives the "after" id for the next auto-scan
+# command to be executed.
+# mouseMoved - Non-zero means the mouse has moved a significant
+# amount since the button went down (so, for example,
+# start dragging out a selection).
+# pressX - X-coordinate at which the mouse button was pressed.
+# selectMode - The style of selection currently underway:
+# char, word, or line.
+# x, y - Last known mouse coordinates for scanning
+# and auto-scanning.
+# data - Used for Cut and Copy
+#-------------------------------------------------------------------------
+
+# Initialize namespace
+namespace eval ::tk::spinbox {}
+
+#-------------------------------------------------------------------------
+# The code below creates the default class bindings for entries.
+#-------------------------------------------------------------------------
+bind Spinbox <<Cut>> {
+ if {![catch {::tk::spinbox::GetSelection %W} tk::Priv(data)]} {
+ clipboard clear -displayof %W
+ clipboard append -displayof %W $tk::Priv(data)
+ %W delete sel.first sel.last
+ unset tk::Priv(data)
+ }
+}
+bind Spinbox <<Copy>> {
+ if {![catch {::tk::spinbox::GetSelection %W} tk::Priv(data)]} {
+ clipboard clear -displayof %W
+ clipboard append -displayof %W $tk::Priv(data)
+ unset tk::Priv(data)
+ }
+}
+bind Spinbox <<Paste>> {
+ catch {
+ if {[tk windowingsystem] ne "x11"} {
+ catch {
+ %W delete sel.first sel.last
+ }
+ }
+ %W insert insert [::tk::GetSelection %W CLIPBOARD]
+ ::tk::EntrySeeInsert %W
+ }
+}
+bind Spinbox <<Clear>> {
+ %W delete sel.first sel.last
+}
+bind Spinbox <<PasteSelection>> {
+ if {$tk_strictMotif || ![info exists tk::Priv(mouseMoved)]
+ || !$tk::Priv(mouseMoved)} {
+ ::tk::spinbox::Paste %W %x
+ }
+}
+
+bind Spinbox <<TraverseIn>> {
+ %W selection range 0 end
+ %W icursor end
+}
+
+# Standard Motif bindings:
+
+bind Spinbox <1> {
+ ::tk::spinbox::ButtonDown %W %x %y
+}
+bind Spinbox <B1-Motion> {
+ ::tk::spinbox::Motion %W %x %y
+}
+bind Spinbox <Double-1> {
+ ::tk::spinbox::ArrowPress %W %x %y
+ set tk::Priv(selectMode) word
+ ::tk::spinbox::MouseSelect %W %x sel.first
+}
+bind Spinbox <Triple-1> {
+ ::tk::spinbox::ArrowPress %W %x %y
+ set tk::Priv(selectMode) line
+ ::tk::spinbox::MouseSelect %W %x 0
+}
+bind Spinbox <Shift-1> {
+ set tk::Priv(selectMode) char
+ %W selection adjust @%x
+}
+bind Spinbox <Double-Shift-1> {
+ set tk::Priv(selectMode) word
+ ::tk::spinbox::MouseSelect %W %x
+}
+bind Spinbox <Triple-Shift-1> {
+ set tk::Priv(selectMode) line
+ ::tk::spinbox::MouseSelect %W %x
+}
+bind Spinbox <B1-Leave> {
+ set tk::Priv(x) %x
+ ::tk::spinbox::AutoScan %W
+}
+bind Spinbox <B1-Enter> {
+ tk::CancelRepeat
+}
+bind Spinbox <ButtonRelease-1> {
+ ::tk::spinbox::ButtonUp %W %x %y
+}
+bind Spinbox <Control-1> {
+ %W icursor @%x
+}
+
+bind Spinbox <<PrevLine>> {
+ %W invoke buttonup
+}
+bind Spinbox <<NextLine>> {
+ %W invoke buttondown
+}
+
+bind Spinbox <<PrevChar>> {
+ ::tk::EntrySetCursor %W [expr {[%W index insert] - 1}]
+}
+bind Spinbox <<NextChar>> {
+ ::tk::EntrySetCursor %W [expr {[%W index insert] + 1}]
+}
+bind Spinbox <<SelectPrevChar>> {
+ ::tk::EntryKeySelect %W [expr {[%W index insert] - 1}]
+ ::tk::EntrySeeInsert %W
+}
+bind Spinbox <<SelectNextChar>> {
+ ::tk::EntryKeySelect %W [expr {[%W index insert] + 1}]
+ ::tk::EntrySeeInsert %W
+}
+bind Spinbox <<PrevWord>> {
+ ::tk::EntrySetCursor %W [::tk::EntryPreviousWord %W insert]
+}
+bind Spinbox <<NextWord>> {
+ ::tk::EntrySetCursor %W [::tk::EntryNextWord %W insert]
+}
+bind Spinbox <<SelectPrevWord>> {
+ ::tk::EntryKeySelect %W [::tk::EntryPreviousWord %W insert]
+ ::tk::EntrySeeInsert %W
+}
+bind Spinbox <<SelectNextWord>> {
+ ::tk::EntryKeySelect %W [::tk::EntryNextWord %W insert]
+ ::tk::EntrySeeInsert %W
+}
+bind Spinbox <<LineStart>> {
+ ::tk::EntrySetCursor %W 0
+}
+bind Spinbox <<SelectLineStart>> {
+ ::tk::EntryKeySelect %W 0
+ ::tk::EntrySeeInsert %W
+}
+bind Spinbox <<LineEnd>> {
+ ::tk::EntrySetCursor %W end
+}
+bind Spinbox <<SelectLineEnd>> {
+ ::tk::EntryKeySelect %W end
+ ::tk::EntrySeeInsert %W
+}
+
+bind Spinbox <Delete> {
+ if {[%W selection present]} {
+ %W delete sel.first sel.last
+ } else {
+ %W delete insert
+ }
+}
+bind Spinbox <BackSpace> {
+ ::tk::EntryBackspace %W
+}
+
+bind Spinbox <Control-space> {
+ %W selection from insert
+}
+bind Spinbox <Select> {
+ %W selection from insert
+}
+bind Spinbox <Control-Shift-space> {
+ %W selection adjust insert
+}
+bind Spinbox <Shift-Select> {
+ %W selection adjust insert
+}
+bind Spinbox <<SelectAll>> {
+ %W selection range 0 end
+}
+bind Spinbox <<SelectNone>> {
+ %W selection clear
+}
+bind Spinbox <KeyPress> {
+ ::tk::EntryInsert %W %A
+}
+
+# Ignore all Alt, Meta, and Control keypresses unless explicitly bound.
+# Otherwise, if a widget binding for one of these is defined, the
+# <KeyPress> class binding will also fire and insert the character,
+# which is wrong. Ditto for Escape, Return, and Tab.
+
+bind Spinbox <Alt-KeyPress> {# nothing}
+bind Spinbox <Meta-KeyPress> {# nothing}
+bind Spinbox <Control-KeyPress> {# nothing}
+bind Spinbox <Escape> {# nothing}
+bind Spinbox <Return> {# nothing}
+bind Spinbox <KP_Enter> {# nothing}
+bind Spinbox <Tab> {# nothing}
+bind Spinbox <Prior> {# nothing}
+bind Spinbox <Next> {# nothing}
+if {[tk windowingsystem] eq "aqua"} {
+ bind Spinbox <Command-KeyPress> {# nothing}
+}
+
+# On Windows, paste is done using Shift-Insert. Shift-Insert already
+# generates the <<Paste>> event, so we don't need to do anything here.
+if {[tk windowingsystem] ne "win32"} {
+ bind Spinbox <Insert> {
+ catch {::tk::EntryInsert %W [::tk::GetSelection %W PRIMARY]}
+ }
+}
+
+# Additional emacs-like bindings:
+
+bind Spinbox <Control-d> {
+ if {!$tk_strictMotif} {
+ %W delete insert
+ }
+}
+bind Spinbox <Control-h> {
+ if {!$tk_strictMotif} {
+ ::tk::EntryBackspace %W
+ }
+}
+bind Spinbox <Control-k> {
+ if {!$tk_strictMotif} {
+ %W delete insert end
+ }
+}
+bind Spinbox <Control-t> {
+ if {!$tk_strictMotif} {
+ ::tk::EntryTranspose %W
+ }
+}
+bind Spinbox <Meta-b> {
+ if {!$tk_strictMotif} {
+ ::tk::EntrySetCursor %W [::tk::EntryPreviousWord %W insert]
+ }
+}
+bind Spinbox <Meta-d> {
+ if {!$tk_strictMotif} {
+ %W delete insert [::tk::EntryNextWord %W insert]
+ }
+}
+bind Spinbox <Meta-f> {
+ if {!$tk_strictMotif} {
+ ::tk::EntrySetCursor %W [::tk::EntryNextWord %W insert]
+ }
+}
+bind Spinbox <Meta-BackSpace> {
+ if {!$tk_strictMotif} {
+ %W delete [::tk::EntryPreviousWord %W insert] insert
+ }
+}
+bind Spinbox <Meta-Delete> {
+ if {!$tk_strictMotif} {
+ %W delete [::tk::EntryPreviousWord %W insert] insert
+ }
+}
+
+# A few additional bindings of my own.
+
+bind Spinbox <2> {
+ if {!$tk_strictMotif} {
+ ::tk::EntryScanMark %W %x
+ }
+}
+bind Spinbox <B2-Motion> {
+ if {!$tk_strictMotif} {
+ ::tk::EntryScanDrag %W %x
+ }
+}
+
+# ::tk::spinbox::Invoke --
+# Invoke an element of the spinbox
+#
+# Arguments:
+# w - The spinbox window.
+# elem - Element to invoke
+
+proc ::tk::spinbox::Invoke {w elem} {
+ variable ::tk::Priv
+
+ if {![winfo exists $w]} {
+ return
+ }
+
+ if {![info exists Priv(outsideElement)]} {
+ $w invoke $elem
+ incr Priv(repeated)
+ }
+ set delay [$w cget -repeatinterval]
+ if {$delay > 0} {
+ set Priv(afterId) [after $delay \
+ [list ::tk::spinbox::Invoke $w $elem]]
+ }
+}
+
+# ::tk::spinbox::ClosestGap --
+# Given x and y coordinates, this procedure finds the closest boundary
+# between characters to the given coordinates and returns the index
+# of the character just after the boundary.
+#
+# Arguments:
+# w - The spinbox window.
+# x - X-coordinate within the window.
+
+proc ::tk::spinbox::ClosestGap {w x} {
+ set pos [$w index @$x]
+ set bbox [$w bbox $pos]
+ if {($x - [lindex $bbox 0]) < ([lindex $bbox 2]/2)} {
+ return $pos
+ }
+ incr pos
+}
+
+# ::tk::spinbox::ArrowPress --
+# This procedure is invoked to handle button-1 presses in buttonup
+# or buttondown elements of spinbox widgets.
+#
+# Arguments:
+# w - The spinbox window in which the button was pressed.
+# x - The x-coordinate of the button press.
+# y - The y-coordinate of the button press.
+
+proc ::tk::spinbox::ArrowPress {w x y} {
+ variable ::tk::Priv
+
+ if {[$w cget -state] ne "disabled" && \
+ [string match "button*" $Priv(element)]} {
+ $w selection element $Priv(element)
+ set Priv(repeated) 0
+ set Priv(relief) [$w cget -$Priv(element)relief]
+ catch {after cancel $Priv(afterId)}
+ set delay [$w cget -repeatdelay]
+ if {$delay > 0} {
+ set Priv(afterId) [after $delay \
+ [list ::tk::spinbox::Invoke $w $Priv(element)]]
+ }
+ if {[info exists Priv(outsideElement)]} {
+ unset Priv(outsideElement)
+ }
+ }
+}
+
+# ::tk::spinbox::ButtonDown --
+# This procedure is invoked to handle button-1 presses in spinbox
+# widgets. It moves the insertion cursor, sets the selection anchor,
+# and claims the input focus.
+#
+# Arguments:
+# w - The spinbox window in which the button was pressed.
+# x - The x-coordinate of the button press.
+# y - The y-coordinate of the button press.
+
+proc ::tk::spinbox::ButtonDown {w x y} {
+ variable ::tk::Priv
+
+ # Get the element that was clicked in. If we are not directly over
+ # the spinbox, default to entry. This is necessary for spinbox grabs.
+ #
+ set Priv(element) [$w identify $x $y]
+ if {$Priv(element) eq ""} {
+ set Priv(element) "entry"
+ }
+
+ switch -exact $Priv(element) {
+ "buttonup" - "buttondown" {
+ ::tk::spinbox::ArrowPress $w $x $y
+ }
+ "entry" {
+ set Priv(selectMode) char
+ set Priv(mouseMoved) 0
+ set Priv(pressX) $x
+ $w icursor [::tk::spinbox::ClosestGap $w $x]
+ $w selection from insert
+ if {"disabled" ne [$w cget -state]} {focus $w}
+ $w selection clear
+ }
+ default {
+ return -code error -errorcode {TK SPINBOX UNKNOWN_ELEMENT} \
+ "unknown spinbox element \"$Priv(element)\""
+ }
+ }
+}
+
+# ::tk::spinbox::ButtonUp --
+# This procedure is invoked to handle button-1 releases in spinbox
+# widgets.
+#
+# Arguments:
+# w - The spinbox window in which the button was pressed.
+# x - The x-coordinate of the button press.
+# y - The y-coordinate of the button press.
+
+proc ::tk::spinbox::ButtonUp {w x y} {
+ variable ::tk::Priv
+
+ ::tk::CancelRepeat
+
+ # Priv(relief) may not exist if the ButtonUp is not paired with
+ # a preceding ButtonDown
+ if {[info exists Priv(element)] && [info exists Priv(relief)] && \
+ [string match "button*" $Priv(element)]} {
+ if {[info exists Priv(repeated)] && !$Priv(repeated)} {
+ $w invoke $Priv(element)
+ }
+ $w configure -$Priv(element)relief $Priv(relief)
+ $w selection element none
+ }
+}
+
+# ::tk::spinbox::MouseSelect --
+# This procedure is invoked when dragging out a selection with
+# the mouse. Depending on the selection mode (character, word,
+# line) it selects in different-sized units. This procedure
+# ignores mouse motions initially until the mouse has moved from
+# one character to another or until there have been multiple clicks.
+#
+# Arguments:
+# w - The spinbox window in which the button was pressed.
+# x - The x-coordinate of the mouse.
+# cursor - optional place to set cursor.
+
+proc ::tk::spinbox::MouseSelect {w x {cursor {}}} {
+ variable ::tk::Priv
+
+ if {$Priv(element) ne "entry"} {
+ # The ButtonUp command triggered by ButtonRelease-1 handles
+ # invoking one of the spinbuttons.
+ return
+ }
+ set cur [::tk::spinbox::ClosestGap $w $x]
+ set anchor [$w index anchor]
+ if {($cur ne $anchor) || (abs($Priv(pressX) - $x) >= 3)} {
+ set Priv(mouseMoved) 1
+ }
+ switch $Priv(selectMode) {
+ char {
+ if {$Priv(mouseMoved)} {
+ if {$cur < $anchor} {
+ $w selection range $cur $anchor
+ } elseif {$cur > $anchor} {
+ $w selection range $anchor $cur
+ } else {
+ $w selection clear
+ }
+ }
+ }
+ word {
+ if {$cur < [$w index anchor]} {
+ set before [tcl_wordBreakBefore [$w get] $cur]
+ set after [tcl_wordBreakAfter [$w get] [expr {$anchor-1}]]
+ } else {
+ set before [tcl_wordBreakBefore [$w get] $anchor]
+ set after [tcl_wordBreakAfter [$w get] [expr {$cur - 1}]]
+ }
+ if {$before < 0} {
+ set before 0
+ }
+ if {$after < 0} {
+ set after end
+ }
+ $w selection range $before $after
+ }
+ line {
+ $w selection range 0 end
+ }
+ }
+ if {$cursor ne {} && $cursor ne "ignore"} {
+ catch {$w icursor $cursor}
+ }
+ update idletasks
+}
+
+# ::tk::spinbox::Paste --
+# This procedure sets the insertion cursor to the current mouse position,
+# pastes the selection there, and sets the focus to the window.
+#
+# Arguments:
+# w - The spinbox window.
+# x - X position of the mouse.
+
+proc ::tk::spinbox::Paste {w x} {
+ $w icursor [::tk::spinbox::ClosestGap $w $x]
+ catch {$w insert insert [::tk::GetSelection $w PRIMARY]}
+ if {"disabled" eq [$w cget -state]} {
+ focus $w
+ }
+}
+
+# ::tk::spinbox::Motion --
+# This procedure is invoked when the mouse moves in a spinbox window
+# with button 1 down.
+#
+# Arguments:
+# w - The spinbox window.
+# x - The x-coordinate of the mouse.
+# y - The y-coordinate of the mouse.
+
+proc ::tk::spinbox::Motion {w x y} {
+ variable ::tk::Priv
+
+ if {![info exists Priv(element)]} {
+ set Priv(element) [$w identify $x $y]
+ }
+
+ set Priv(x) $x
+ if {"entry" eq $Priv(element)} {
+ ::tk::spinbox::MouseSelect $w $x ignore
+ } elseif {[$w identify $x $y] ne $Priv(element)} {
+ if {![info exists Priv(outsideElement)]} {
+ # We've wandered out of the spin button
+ # setting outside element will cause ::tk::spinbox::Invoke to
+ # loop without doing anything
+ set Priv(outsideElement) ""
+ $w selection element none
+ }
+ } elseif {[info exists Priv(outsideElement)]} {
+ unset Priv(outsideElement)
+ $w selection element $Priv(element)
+ }
+}
+
+# ::tk::spinbox::AutoScan --
+# This procedure is invoked when the mouse leaves an spinbox window
+# with button 1 down. It scrolls the window left or right,
+# depending on where the mouse is, and reschedules itself as an
+# "after" command so that the window continues to scroll until the
+# mouse moves back into the window or the mouse button is released.
+#
+# Arguments:
+# w - The spinbox window.
+
+proc ::tk::spinbox::AutoScan {w} {
+ variable ::tk::Priv
+
+ set x $Priv(x)
+ if {$x >= [winfo width $w]} {
+ $w xview scroll 2 units
+ ::tk::spinbox::MouseSelect $w $x ignore
+ } elseif {$x < 0} {
+ $w xview scroll -2 units
+ ::tk::spinbox::MouseSelect $w $x ignore
+ }
+ set Priv(afterId) [after 50 [list ::tk::spinbox::AutoScan $w]]
+}
+
+# ::tk::spinbox::GetSelection --
+#
+# Returns the selected text of the spinbox. Differs from entry in that
+# a spinbox has no -show option to obscure contents.
+#
+# Arguments:
+# w - The spinbox window from which the text to get
+
+proc ::tk::spinbox::GetSelection {w} {
+ return [string range [$w get] [$w index sel.first] \
+ [expr {[$w index sel.last] - 1}]]
+}
diff --git a/tk8.6/library/tclIndex b/tk8.6/library/tclIndex
new file mode 100644
index 0000000..b3f37fa
--- /dev/null
+++ b/tk8.6/library/tclIndex
@@ -0,0 +1,253 @@
+# Tcl autoload index file, version 2.0
+# This file is generated by the "auto_mkindex" command
+# and sourced to set up indexing information for one or
+# more commands. Typically each line is a command that
+# sets an element in the auto_index array, where the
+# element name is the name of a command and the value is
+# a script that loads the command.
+
+set auto_index(::tk::dialog::error::Return) [list source [file join $dir bgerror.tcl]]
+set auto_index(::tk::dialog::error::Details) [list source [file join $dir bgerror.tcl]]
+set auto_index(::tk::dialog::error::SaveToLog) [list source [file join $dir bgerror.tcl]]
+set auto_index(::tk::dialog::error::Destroy) [list source [file join $dir bgerror.tcl]]
+set auto_index(::tk::dialog::error::bgerror) [list source [file join $dir bgerror.tcl]]
+set auto_index(bgerror) [list source [file join $dir bgerror.tcl]]
+set auto_index(::tk::ButtonInvoke) [list source [file join $dir button.tcl]]
+set auto_index(::tk::ButtonAutoInvoke) [list source [file join $dir button.tcl]]
+set auto_index(::tk::CheckRadioInvoke) [list source [file join $dir button.tcl]]
+set auto_index(::tk::dialog::file::chooseDir::) [list source [file join $dir choosedir.tcl]]
+set auto_index(::tk::dialog::file::chooseDir::Config) [list source [file join $dir choosedir.tcl]]
+set auto_index(::tk::dialog::file::chooseDir::OkCmd) [list source [file join $dir choosedir.tcl]]
+set auto_index(::tk::dialog::file::chooseDir::DblClick) [list source [file join $dir choosedir.tcl]]
+set auto_index(::tk::dialog::file::chooseDir::ListBrowse) [list source [file join $dir choosedir.tcl]]
+set auto_index(::tk::dialog::file::chooseDir::Done) [list source [file join $dir choosedir.tcl]]
+set auto_index(::tk::dialog::color::) [list source [file join $dir clrpick.tcl]]
+set auto_index(::tk::dialog::color::InitValues) [list source [file join $dir clrpick.tcl]]
+set auto_index(::tk::dialog::color::Config) [list source [file join $dir clrpick.tcl]]
+set auto_index(::tk::dialog::color::BuildDialog) [list source [file join $dir clrpick.tcl]]
+set auto_index(::tk::dialog::color::SetRGBValue) [list source [file join $dir clrpick.tcl]]
+set auto_index(::tk::dialog::color::XToRgb) [list source [file join $dir clrpick.tcl]]
+set auto_index(::tk::dialog::color::RgbToX) [list source [file join $dir clrpick.tcl]]
+set auto_index(::tk::dialog::color::DrawColorScale) [list source [file join $dir clrpick.tcl]]
+set auto_index(::tk::dialog::color::CreateSelector) [list source [file join $dir clrpick.tcl]]
+set auto_index(::tk::dialog::color::RedrawFinalColor) [list source [file join $dir clrpick.tcl]]
+set auto_index(::tk::dialog::color::RedrawColorBars) [list source [file join $dir clrpick.tcl]]
+set auto_index(::tk::dialog::color::StartMove) [list source [file join $dir clrpick.tcl]]
+set auto_index(::tk::dialog::color::MoveSelector) [list source [file join $dir clrpick.tcl]]
+set auto_index(::tk::dialog::color::ReleaseMouse) [list source [file join $dir clrpick.tcl]]
+set auto_index(::tk::dialog::color::ResizeColorBars) [list source [file join $dir clrpick.tcl]]
+set auto_index(::tk::dialog::color::HandleSelEntry) [list source [file join $dir clrpick.tcl]]
+set auto_index(::tk::dialog::color::HandleRGBEntry) [list source [file join $dir clrpick.tcl]]
+set auto_index(::tk::dialog::color::EnterColorBar) [list source [file join $dir clrpick.tcl]]
+set auto_index(::tk::dialog::color::LeaveColorBar) [list source [file join $dir clrpick.tcl]]
+set auto_index(::tk::dialog::color::OkCmd) [list source [file join $dir clrpick.tcl]]
+set auto_index(::tk::dialog::color::CancelCmd) [list source [file join $dir clrpick.tcl]]
+set auto_index(tclParseConfigSpec) [list source [file join $dir comdlg.tcl]]
+set auto_index(tclListValidFlags) [list source [file join $dir comdlg.tcl]]
+set auto_index(::tk::FocusGroup_Create) [list source [file join $dir comdlg.tcl]]
+set auto_index(::tk::FocusGroup_BindIn) [list source [file join $dir comdlg.tcl]]
+set auto_index(::tk::FocusGroup_BindOut) [list source [file join $dir comdlg.tcl]]
+set auto_index(::tk::FocusGroup_Destroy) [list source [file join $dir comdlg.tcl]]
+set auto_index(::tk::FocusGroup_In) [list source [file join $dir comdlg.tcl]]
+set auto_index(::tk::FocusGroup_Out) [list source [file join $dir comdlg.tcl]]
+set auto_index(::tk::FDGetFileTypes) [list source [file join $dir comdlg.tcl]]
+set auto_index(::tk::ConsoleInit) [list source [file join $dir console.tcl]]
+set auto_index(::tk::ConsoleSource) [list source [file join $dir console.tcl]]
+set auto_index(::tk::ConsoleInvoke) [list source [file join $dir console.tcl]]
+set auto_index(::tk::ConsoleHistory) [list source [file join $dir console.tcl]]
+set auto_index(::tk::ConsolePrompt) [list source [file join $dir console.tcl]]
+set auto_index(::tk::ConsoleBind) [list source [file join $dir console.tcl]]
+set auto_index(::tk::ConsoleInsert) [list source [file join $dir console.tcl]]
+set auto_index(::tk::ConsoleOutput) [list source [file join $dir console.tcl]]
+set auto_index(::tk::ConsoleExit) [list source [file join $dir console.tcl]]
+set auto_index(::tk::ConsoleAbout) [list source [file join $dir console.tcl]]
+set auto_index(tk_dialog) [list source [file join $dir dialog.tcl]]
+set auto_index(::tk::EntryClosestGap) [list source [file join $dir entry.tcl]]
+set auto_index(::tk::EntryButton1) [list source [file join $dir entry.tcl]]
+set auto_index(::tk::EntryMouseSelect) [list source [file join $dir entry.tcl]]
+set auto_index(::tk::EntryPaste) [list source [file join $dir entry.tcl]]
+set auto_index(::tk::EntryAutoScan) [list source [file join $dir entry.tcl]]
+set auto_index(::tk::EntryKeySelect) [list source [file join $dir entry.tcl]]
+set auto_index(::tk::EntryInsert) [list source [file join $dir entry.tcl]]
+set auto_index(::tk::EntryBackspace) [list source [file join $dir entry.tcl]]
+set auto_index(::tk::EntrySeeInsert) [list source [file join $dir entry.tcl]]
+set auto_index(::tk::EntrySetCursor) [list source [file join $dir entry.tcl]]
+set auto_index(::tk::EntryTranspose) [list source [file join $dir entry.tcl]]
+set auto_index(::tk::EntryPreviousWord) [list source [file join $dir entry.tcl]]
+set auto_index(::tk::EntryGetSelection) [list source [file join $dir entry.tcl]]
+set auto_index(tk_focusNext) [list source [file join $dir focus.tcl]]
+set auto_index(tk_focusPrev) [list source [file join $dir focus.tcl]]
+set auto_index(::tk::FocusOK) [list source [file join $dir focus.tcl]]
+set auto_index(tk_focusFollowsMouse) [list source [file join $dir focus.tcl]]
+set auto_index(::tk::IconList) [list source [file join $dir iconlist.tcl]]
+set auto_index(::tk::ListboxBeginSelect) [list source [file join $dir listbox.tcl]]
+set auto_index(::tk::ListboxMotion) [list source [file join $dir listbox.tcl]]
+set auto_index(::tk::ListboxBeginExtend) [list source [file join $dir listbox.tcl]]
+set auto_index(::tk::ListboxBeginToggle) [list source [file join $dir listbox.tcl]]
+set auto_index(::tk::ListboxAutoScan) [list source [file join $dir listbox.tcl]]
+set auto_index(::tk::ListboxUpDown) [list source [file join $dir listbox.tcl]]
+set auto_index(::tk::ListboxExtendUpDown) [list source [file join $dir listbox.tcl]]
+set auto_index(::tk::ListboxDataExtend) [list source [file join $dir listbox.tcl]]
+set auto_index(::tk::ListboxCancel) [list source [file join $dir listbox.tcl]]
+set auto_index(::tk::ListboxSelectAll) [list source [file join $dir listbox.tcl]]
+set auto_index(::tk::Megawidget) [list source [file join $dir megawidget.tcl]]
+set auto_index(::tk::MbEnter) [list source [file join $dir menu.tcl]]
+set auto_index(::tk::MbLeave) [list source [file join $dir menu.tcl]]
+set auto_index(::tk::MbPost) [list source [file join $dir menu.tcl]]
+set auto_index(::tk::MenuUnpost) [list source [file join $dir menu.tcl]]
+set auto_index(::tk::MbMotion) [list source [file join $dir menu.tcl]]
+set auto_index(::tk::MbButtonUp) [list source [file join $dir menu.tcl]]
+set auto_index(::tk::MenuMotion) [list source [file join $dir menu.tcl]]
+set auto_index(::tk::MenuButtonDown) [list source [file join $dir menu.tcl]]
+set auto_index(::tk::MenuLeave) [list source [file join $dir menu.tcl]]
+set auto_index(::tk::MenuInvoke) [list source [file join $dir menu.tcl]]
+set auto_index(::tk::MenuEscape) [list source [file join $dir menu.tcl]]
+set auto_index(::tk::MenuUpArrow) [list source [file join $dir menu.tcl]]
+set auto_index(::tk::MenuDownArrow) [list source [file join $dir menu.tcl]]
+set auto_index(::tk::MenuLeftArrow) [list source [file join $dir menu.tcl]]
+set auto_index(::tk::MenuRightArrow) [list source [file join $dir menu.tcl]]
+set auto_index(::tk::MenuNextMenu) [list source [file join $dir menu.tcl]]
+set auto_index(::tk::MenuNextEntry) [list source [file join $dir menu.tcl]]
+set auto_index(::tk::MenuFind) [list source [file join $dir menu.tcl]]
+set auto_index(::tk::TraverseToMenu) [list source [file join $dir menu.tcl]]
+set auto_index(::tk::FirstMenu) [list source [file join $dir menu.tcl]]
+set auto_index(::tk::TraverseWithinMenu) [list source [file join $dir menu.tcl]]
+set auto_index(::tk::MenuFirstEntry) [list source [file join $dir menu.tcl]]
+set auto_index(::tk::MenuFindName) [list source [file join $dir menu.tcl]]
+set auto_index(::tk::PostOverPoint) [list source [file join $dir menu.tcl]]
+set auto_index(::tk::SaveGrabInfo) [list source [file join $dir menu.tcl]]
+set auto_index(::tk::RestoreOldGrab) [list source [file join $dir menu.tcl]]
+set auto_index(tk_menuSetFocus) [list source [file join $dir menu.tcl]]
+set auto_index(::tk::GenerateMenuSelect) [list source [file join $dir menu.tcl]]
+set auto_index(tk_popup) [list source [file join $dir menu.tcl]]
+set auto_index(::tk::ensure_psenc_is_loaded) [list source [file join $dir mkpsenc.tcl]]
+set auto_index(::tk::MessageBox) [list source [file join $dir msgbox.tcl]]
+set auto_index(tk_menuBar) [list source [file join $dir obsolete.tcl]]
+set auto_index(tk_bindForTraversal) [list source [file join $dir obsolete.tcl]]
+set auto_index(::tk::classic::restore) [list source [file join $dir obsolete.tcl]]
+set auto_index(tk_optionMenu) [list source [file join $dir optMenu.tcl]]
+set auto_index(tk_setPalette) [list source [file join $dir palette.tcl]]
+set auto_index(::tk::RecolorTree) [list source [file join $dir palette.tcl]]
+set auto_index(::tk::Darken) [list source [file join $dir palette.tcl]]
+set auto_index(tk_bisque) [list source [file join $dir palette.tcl]]
+set auto_index(::safe::tkInterpInit) [list source [file join $dir safetk.tcl]]
+set auto_index(::safe::loadTk) [list source [file join $dir safetk.tcl]]
+set auto_index(::safe::TkInit) [list source [file join $dir safetk.tcl]]
+set auto_index(::safe::allowTk) [list source [file join $dir safetk.tcl]]
+set auto_index(::safe::disallowTk) [list source [file join $dir safetk.tcl]]
+set auto_index(::safe::tkDelete) [list source [file join $dir safetk.tcl]]
+set auto_index(::safe::tkTopLevel) [list source [file join $dir safetk.tcl]]
+set auto_index(::tk::ScaleActivate) [list source [file join $dir scale.tcl]]
+set auto_index(::tk::ScaleButtonDown) [list source [file join $dir scale.tcl]]
+set auto_index(::tk::ScaleDrag) [list source [file join $dir scale.tcl]]
+set auto_index(::tk::ScaleEndDrag) [list source [file join $dir scale.tcl]]
+set auto_index(::tk::ScaleIncrement) [list source [file join $dir scale.tcl]]
+set auto_index(::tk::ScaleControlPress) [list source [file join $dir scale.tcl]]
+set auto_index(::tk::ScaleButton2Down) [list source [file join $dir scale.tcl]]
+set auto_index(::tk::ScrollButtonDown) [list source [file join $dir scrlbar.tcl]]
+set auto_index(::tk::ScrollButtonUp) [list source [file join $dir scrlbar.tcl]]
+set auto_index(::tk::ScrollSelect) [list source [file join $dir scrlbar.tcl]]
+set auto_index(::tk::ScrollStartDrag) [list source [file join $dir scrlbar.tcl]]
+set auto_index(::tk::ScrollDrag) [list source [file join $dir scrlbar.tcl]]
+set auto_index(::tk::ScrollEndDrag) [list source [file join $dir scrlbar.tcl]]
+set auto_index(::tk::ScrollByUnits) [list source [file join $dir scrlbar.tcl]]
+set auto_index(::tk::ScrollByPages) [list source [file join $dir scrlbar.tcl]]
+set auto_index(::tk::ScrollToPos) [list source [file join $dir scrlbar.tcl]]
+set auto_index(::tk::ScrollTopBottom) [list source [file join $dir scrlbar.tcl]]
+set auto_index(::tk::ScrollButton2Down) [list source [file join $dir scrlbar.tcl]]
+set auto_index(::tk::spinbox::Invoke) [list source [file join $dir spinbox.tcl]]
+set auto_index(::tk::spinbox::ClosestGap) [list source [file join $dir spinbox.tcl]]
+set auto_index(::tk::spinbox::ButtonDown) [list source [file join $dir spinbox.tcl]]
+set auto_index(::tk::spinbox::ButtonUp) [list source [file join $dir spinbox.tcl]]
+set auto_index(::tk::spinbox::MouseSelect) [list source [file join $dir spinbox.tcl]]
+set auto_index(::tk::spinbox::Paste) [list source [file join $dir spinbox.tcl]]
+set auto_index(::tk::spinbox::Motion) [list source [file join $dir spinbox.tcl]]
+set auto_index(::tk::spinbox::AutoScan) [list source [file join $dir spinbox.tcl]]
+set auto_index(::tk::spinbox::KeySelect) [list source [file join $dir spinbox.tcl]]
+set auto_index(::tk::spinbox::Insert) [list source [file join $dir spinbox.tcl]]
+set auto_index(::tk::spinbox::Backspace) [list source [file join $dir spinbox.tcl]]
+set auto_index(::tk::spinbox::SeeInsert) [list source [file join $dir spinbox.tcl]]
+set auto_index(::tk::spinbox::SetCursor) [list source [file join $dir spinbox.tcl]]
+set auto_index(::tk::spinbox::Transpose) [list source [file join $dir spinbox.tcl]]
+set auto_index(::tk::spinbox::PreviousWord) [list source [file join $dir spinbox.tcl]]
+set auto_index(::tk::spinbox::GetSelection) [list source [file join $dir spinbox.tcl]]
+set auto_index(::tk::TearOffMenu) [list source [file join $dir tearoff.tcl]]
+set auto_index(::tk::MenuDup) [list source [file join $dir tearoff.tcl]]
+set auto_index(::tk::TextClosestGap) [list source [file join $dir text.tcl]]
+set auto_index(::tk::TextButton1) [list source [file join $dir text.tcl]]
+set auto_index(::tk::TextSelectTo) [list source [file join $dir text.tcl]]
+set auto_index(::tk::TextKeyExtend) [list source [file join $dir text.tcl]]
+set auto_index(::tk::TextPaste) [list source [file join $dir text.tcl]]
+set auto_index(::tk::TextAutoScan) [list source [file join $dir text.tcl]]
+set auto_index(::tk::TextSetCursor) [list source [file join $dir text.tcl]]
+set auto_index(::tk::TextKeySelect) [list source [file join $dir text.tcl]]
+set auto_index(::tk::TextResetAnchor) [list source [file join $dir text.tcl]]
+set auto_index(::tk::TextInsert) [list source [file join $dir text.tcl]]
+set auto_index(::tk::TextUpDownLine) [list source [file join $dir text.tcl]]
+set auto_index(::tk::TextPrevPara) [list source [file join $dir text.tcl]]
+set auto_index(::tk::TextNextPara) [list source [file join $dir text.tcl]]
+set auto_index(::tk::TextScrollPages) [list source [file join $dir text.tcl]]
+set auto_index(::tk::TextTranspose) [list source [file join $dir text.tcl]]
+set auto_index(tk_textCopy) [list source [file join $dir text.tcl]]
+set auto_index(tk_textCut) [list source [file join $dir text.tcl]]
+set auto_index(tk_textPaste) [list source [file join $dir text.tcl]]
+set auto_index(::tk::TextNextPos) [list source [file join $dir text.tcl]]
+set auto_index(::tk::TextPrevPos) [list source [file join $dir text.tcl]]
+set auto_index(::tk::PlaceWindow) [list source [file join $dir tk.tcl]]
+set auto_index(::tk::SetFocusGrab) [list source [file join $dir tk.tcl]]
+set auto_index(::tk::RestoreFocusGrab) [list source [file join $dir tk.tcl]]
+set auto_index(::tk::ScreenChanged) [list source [file join $dir tk.tcl]]
+set auto_index(::tk::EventMotifBindings) [list source [file join $dir tk.tcl]]
+set auto_index(::tk::CancelRepeat) [list source [file join $dir tk.tcl]]
+set auto_index(::tk::TabToWindow) [list source [file join $dir tk.tcl]]
+set auto_index(::tk::dialog::file::) [list source [file join $dir tkfbox.tcl]]
+set auto_index(::tk::dialog::file::Config) [list source [file join $dir tkfbox.tcl]]
+set auto_index(::tk::dialog::file::Create) [list source [file join $dir tkfbox.tcl]]
+set auto_index(::tk::dialog::file::SetSelectMode) [list source [file join $dir tkfbox.tcl]]
+set auto_index(::tk::dialog::file::UpdateWhenIdle) [list source [file join $dir tkfbox.tcl]]
+set auto_index(::tk::dialog::file::Update) [list source [file join $dir tkfbox.tcl]]
+set auto_index(::tk::dialog::file::SetPathSilently) [list source [file join $dir tkfbox.tcl]]
+set auto_index(::tk::dialog::file::SetPath) [list source [file join $dir tkfbox.tcl]]
+set auto_index(::tk::dialog::file::SetFilter) [list source [file join $dir tkfbox.tcl]]
+set auto_index(::tk::dialog::file::ResolveFile) [list source [file join $dir tkfbox.tcl]]
+set auto_index(::tk::dialog::file::EntFocusIn) [list source [file join $dir tkfbox.tcl]]
+set auto_index(::tk::dialog::file::EntFocusOut) [list source [file join $dir tkfbox.tcl]]
+set auto_index(::tk::dialog::file::ActivateEnt) [list source [file join $dir tkfbox.tcl]]
+set auto_index(::tk::dialog::file::VerifyFileName) [list source [file join $dir tkfbox.tcl]]
+set auto_index(::tk::dialog::file::InvokeBtn) [list source [file join $dir tkfbox.tcl]]
+set auto_index(::tk::dialog::file::UpDirCmd) [list source [file join $dir tkfbox.tcl]]
+set auto_index(::tk::dialog::file::JoinFile) [list source [file join $dir tkfbox.tcl]]
+set auto_index(::tk::dialog::file::OkCmd) [list source [file join $dir tkfbox.tcl]]
+set auto_index(::tk::dialog::file::CancelCmd) [list source [file join $dir tkfbox.tcl]]
+set auto_index(::tk::dialog::file::ListBrowse) [list source [file join $dir tkfbox.tcl]]
+set auto_index(::tk::dialog::file::ListInvoke) [list source [file join $dir tkfbox.tcl]]
+set auto_index(::tk::dialog::file::Done) [list source [file join $dir tkfbox.tcl]]
+set auto_index(::tk::MotifFDialog) [list source [file join $dir xmfbox.tcl]]
+set auto_index(::tk::MotifFDialog_Create) [list source [file join $dir xmfbox.tcl]]
+set auto_index(::tk::MotifFDialog_FileTypes) [list source [file join $dir xmfbox.tcl]]
+set auto_index(::tk::MotifFDialog_SetFilter) [list source [file join $dir xmfbox.tcl]]
+set auto_index(::tk::MotifFDialog_Config) [list source [file join $dir xmfbox.tcl]]
+set auto_index(::tk::MotifFDialog_BuildUI) [list source [file join $dir xmfbox.tcl]]
+set auto_index(::tk::MotifFDialog_SetListMode) [list source [file join $dir xmfbox.tcl]]
+set auto_index(::tk::MotifFDialog_MakeSList) [list source [file join $dir xmfbox.tcl]]
+set auto_index(::tk::MotifFDialog_InterpFilter) [list source [file join $dir xmfbox.tcl]]
+set auto_index(::tk::MotifFDialog_Update) [list source [file join $dir xmfbox.tcl]]
+set auto_index(::tk::MotifFDialog_LoadFiles) [list source [file join $dir xmfbox.tcl]]
+set auto_index(::tk::MotifFDialog_BrowseDList) [list source [file join $dir xmfbox.tcl]]
+set auto_index(::tk::MotifFDialog_ActivateDList) [list source [file join $dir xmfbox.tcl]]
+set auto_index(::tk::MotifFDialog_BrowseFList) [list source [file join $dir xmfbox.tcl]]
+set auto_index(::tk::MotifFDialog_ActivateFList) [list source [file join $dir xmfbox.tcl]]
+set auto_index(::tk::MotifFDialog_ActivateFEnt) [list source [file join $dir xmfbox.tcl]]
+set auto_index(::tk::MotifFDialog_ActivateSEnt) [list source [file join $dir xmfbox.tcl]]
+set auto_index(::tk::MotifFDialog_OkCmd) [list source [file join $dir xmfbox.tcl]]
+set auto_index(::tk::MotifFDialog_FilterCmd) [list source [file join $dir xmfbox.tcl]]
+set auto_index(::tk::MotifFDialog_CancelCmd) [list source [file join $dir xmfbox.tcl]]
+set auto_index(::tk::ListBoxKeyAccel_Set) [list source [file join $dir xmfbox.tcl]]
+set auto_index(::tk::ListBoxKeyAccel_Unset) [list source [file join $dir xmfbox.tcl]]
+set auto_index(::tk::ListBoxKeyAccel_Key) [list source [file join $dir xmfbox.tcl]]
+set auto_index(::tk::ListBoxKeyAccel_Goto) [list source [file join $dir xmfbox.tcl]]
+set auto_index(::tk::ListBoxKeyAccel_Reset) [list source [file join $dir xmfbox.tcl]]
+set auto_index(tk_getFileType) [list source [file join $dir xmfbox.tcl]]
+set auto_index(::tk::unsupported::ExposePrivateCommand) [list source [file join $dir unsupported.tcl]]
+set auto_index(::tk::unsupported::ExposePrivateVariable) [list source [file join $dir unsupported.tcl]]
+set auto_index(::tk::fontchooser) [list source [file join $dir fontchooser.tcl]]
diff --git a/tk8.6/library/tearoff.tcl b/tk8.6/library/tearoff.tcl
new file mode 100644
index 0000000..b500023
--- /dev/null
+++ b/tk8.6/library/tearoff.tcl
@@ -0,0 +1,180 @@
+# tearoff.tcl --
+#
+# This file contains procedures that implement tear-off menus.
+#
+# Copyright (c) 1994 The Regents of the University of California.
+# Copyright (c) 1994-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.
+#
+
+# ::tk::TearoffMenu --
+# Given the name of a menu, this procedure creates a torn-off menu
+# that is identical to the given menu (including nested submenus).
+# The new torn-off menu exists as a toplevel window managed by the
+# window manager. The return value is the name of the new menu.
+# The window is created at the point specified by x and y
+#
+# Arguments:
+# w - The menu to be torn-off (duplicated).
+# x - x coordinate where window is created
+# y - y coordinate where window is created
+
+proc ::tk::TearOffMenu {w {x 0} {y 0}} {
+ # Find a unique name to use for the torn-off menu. Find the first
+ # ancestor of w that is a toplevel but not a menu, and use this as
+ # the parent of the new menu. This guarantees that the torn off
+ # menu will be on the same screen as the original menu. By making
+ # it a child of the ancestor, rather than a child of the menu, it
+ # can continue to live even if the menu is deleted; it will go
+ # away when the toplevel goes away.
+
+ if {$x == 0} {
+ set x [winfo rootx $w]
+ }
+ if {$y == 0} {
+ set y [winfo rooty $w]
+ if {[tk windowingsystem] eq "aqua"} {
+ # Shift by height of tearoff entry minus height of window titlebar
+ catch {incr y [expr {[$w yposition 1] - 16}]}
+ # Avoid the native menu bar which sits on top of everything.
+ if {$y < 22} { set y 22 }
+ }
+ }
+
+ set parent [winfo parent $w]
+ while {[winfo toplevel $parent] ne $parent \
+ || [winfo class $parent] eq "Menu"} {
+ set parent [winfo parent $parent]
+ }
+ if {$parent eq "."} {
+ set parent ""
+ }
+ for {set i 1} 1 {incr i} {
+ set menu $parent.tearoff$i
+ if {![winfo exists $menu]} {
+ break
+ }
+ }
+
+ $w clone $menu tearoff
+
+ # Pick a title for the new menu by looking at the parent of the
+ # original: if the parent is a menu, then use the text of the active
+ # entry. If it's a menubutton then use its text.
+
+ set parent [winfo parent $w]
+ if {[$menu cget -title] ne ""} {
+ wm title $menu [$menu cget -title]
+ } else {
+ switch -- [winfo class $parent] {
+ Menubutton {
+ wm title $menu [$parent cget -text]
+ }
+ Menu {
+ wm title $menu [$parent entrycget active -label]
+ }
+ }
+ }
+
+ if {[tk windowingsystem] eq "win32"} {
+ # [Bug 3181181]: Find the toplevel window for the menu
+ set parent [winfo toplevel $parent]
+ while {[winfo class $parent] eq "Menu"} {
+ set parent [winfo toplevel [winfo parent $parent]]
+ }
+ wm transient $menu [winfo toplevel $parent]
+ wm attributes $menu -toolwindow 1
+ }
+
+ $menu post $x $y
+
+ if {[winfo exists $menu] == 0} {
+ return ""
+ }
+
+ # Set tk::Priv(focus) on entry: otherwise the focus will get lost
+ # after keyboard invocation of a sub-menu (it will stay on the
+ # submenu).
+
+ bind $menu <Enter> {
+ set tk::Priv(focus) %W
+ }
+
+ # If there is a -tearoffcommand option for the menu, invoke it
+ # now.
+
+ set cmd [$w cget -tearoffcommand]
+ if {$cmd ne ""} {
+ uplevel #0 $cmd [list $w $menu]
+ }
+ return $menu
+}
+
+# ::tk::MenuDup --
+# Given a menu (hierarchy), create a duplicate menu (hierarchy)
+# in a given window.
+#
+# Arguments:
+# src - Source window. Must be a menu. It and its
+# menu descendants will be duplicated at dst.
+# dst - Name to use for topmost menu in duplicate
+# hierarchy.
+
+proc ::tk::MenuDup {src dst type} {
+ set cmd [list menu $dst -type $type]
+ foreach option [$src configure] {
+ if {[llength $option] == 2} {
+ continue
+ }
+ if {[lindex $option 0] eq "-type"} {
+ continue
+ }
+ lappend cmd [lindex $option 0] [lindex $option 4]
+ }
+ eval $cmd
+ set last [$src index last]
+ if {$last eq "none"} {
+ return
+ }
+ for {set i [$src cget -tearoff]} {$i <= $last} {incr i} {
+ set cmd [list $dst add [$src type $i]]
+ foreach option [$src entryconfigure $i] {
+ lappend cmd [lindex $option 0] [lindex $option 4]
+ }
+ eval $cmd
+ }
+
+ # Duplicate the binding tags and bindings from the source menu.
+
+ set tags [bindtags $src]
+ set srcLen [string length $src]
+
+ # Copy tags to x, replacing each substring of src with dst.
+
+ while {[set index [string first $src $tags]] != -1} {
+ append x [string range $tags 0 [expr {$index - 1}]]$dst
+ set tags [string range $tags [expr {$index + $srcLen}] end]
+ }
+ append x $tags
+
+ bindtags $dst $x
+
+ foreach event [bind $src] {
+ unset x
+ set script [bind $src $event]
+ set eventLen [string length $event]
+
+ # Copy script to x, replacing each substring of event with dst.
+
+ while {[set index [string first $event $script]] != -1} {
+ append x [string range $script 0 [expr {$index - 1}]]
+ append x $dst
+ set script [string range $script [expr {$index + $eventLen}] end]
+ }
+ append x $script
+
+ bind $dst $event $x
+ }
+}
diff --git a/tk8.6/library/text.tcl b/tk8.6/library/text.tcl
new file mode 100644
index 0000000..7d12e18
--- /dev/null
+++ b/tk8.6/library/text.tcl
@@ -0,0 +1,1217 @@
+# text.tcl --
+#
+# This file defines the default bindings for Tk text widgets and provides
+# procedures that help in implementing the bindings.
+#
+# Copyright (c) 1992-1994 The Regents of the University of California.
+# Copyright (c) 1994-1997 Sun Microsystems, Inc.
+# Copyright (c) 1998 by Scriptics Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+
+#-------------------------------------------------------------------------
+# Elements of ::tk::Priv that are used in this file:
+#
+# afterId - If non-null, it means that auto-scanning is underway
+# and it gives the "after" id for the next auto-scan
+# command to be executed.
+# char - Character position on the line; kept in order
+# to allow moving up or down past short lines while
+# still remembering the desired position.
+# mouseMoved - Non-zero means the mouse has moved a significant
+# amount since the button went down (so, for example,
+# start dragging out a selection).
+# prevPos - Used when moving up or down lines via the keyboard.
+# Keeps track of the previous insert position, so
+# we can distinguish a series of ups and downs, all
+# in a row, from a new up or down.
+# selectMode - The style of selection currently underway:
+# char, word, or line.
+# x, y - Last known mouse coordinates for scanning
+# and auto-scanning.
+#
+#-------------------------------------------------------------------------
+
+#-------------------------------------------------------------------------
+# The code below creates the default class bindings for text widgets.
+#-------------------------------------------------------------------------
+
+
+
+# Standard Motif bindings:
+
+bind Text <Map> {
+ if {[tk windowingsystem] eq "aqua"} {
+ ::tk::RegisterServiceWidget %W
+ }
+}
+
+bind Text <1> {
+ tk::TextButton1 %W %x %y
+ %W tag remove sel 0.0 end
+}
+bind Text <B1-Motion> {
+ set tk::Priv(x) %x
+ set tk::Priv(y) %y
+ tk::TextSelectTo %W %x %y
+}
+bind Text <Double-1> {
+ set tk::Priv(selectMode) word
+ tk::TextSelectTo %W %x %y
+ catch {%W mark set insert sel.first}
+}
+bind Text <Triple-1> {
+ set tk::Priv(selectMode) line
+ tk::TextSelectTo %W %x %y
+ catch {%W mark set insert sel.first}
+}
+bind Text <Shift-1> {
+ tk::TextResetAnchor %W @%x,%y
+ set tk::Priv(selectMode) char
+ tk::TextSelectTo %W %x %y
+}
+bind Text <Double-Shift-1> {
+ set tk::Priv(selectMode) word
+ tk::TextSelectTo %W %x %y 1
+}
+bind Text <Triple-Shift-1> {
+ set tk::Priv(selectMode) line
+ tk::TextSelectTo %W %x %y
+}
+bind Text <B1-Leave> {
+ set tk::Priv(x) %x
+ set tk::Priv(y) %y
+ tk::TextAutoScan %W
+}
+bind Text <B1-Enter> {
+ tk::CancelRepeat
+}
+bind Text <ButtonRelease-1> {
+ tk::CancelRepeat
+}
+
+bind Text <Control-1> {
+ %W mark set insert @%x,%y
+ # An operation that moves the insert mark without making it
+ # one end of the selection must insert an autoseparator
+ if {[%W cget -autoseparators]} {
+ %W edit separator
+ }
+}
+# stop an accidental double click triggering <Double-Button-1>
+bind Text <Double-Control-1> { # nothing }
+# stop an accidental movement triggering <B1-Motion>
+bind Text <Control-B1-Motion> { # nothing }
+bind Text <<PrevChar>> {
+ tk::TextSetCursor %W insert-1displayindices
+}
+bind Text <<NextChar>> {
+ tk::TextSetCursor %W insert+1displayindices
+}
+bind Text <<PrevLine>> {
+ tk::TextSetCursor %W [tk::TextUpDownLine %W -1]
+}
+bind Text <<NextLine>> {
+ tk::TextSetCursor %W [tk::TextUpDownLine %W 1]
+}
+bind Text <<SelectPrevChar>> {
+ tk::TextKeySelect %W [%W index {insert - 1displayindices}]
+}
+bind Text <<SelectNextChar>> {
+ tk::TextKeySelect %W [%W index {insert + 1displayindices}]
+}
+bind Text <<SelectPrevLine>> {
+ tk::TextKeySelect %W [tk::TextUpDownLine %W -1]
+}
+bind Text <<SelectNextLine>> {
+ tk::TextKeySelect %W [tk::TextUpDownLine %W 1]
+}
+bind Text <<PrevWord>> {
+ tk::TextSetCursor %W [tk::TextPrevPos %W insert tcl_startOfPreviousWord]
+}
+bind Text <<NextWord>> {
+ tk::TextSetCursor %W [tk::TextNextWord %W insert]
+}
+bind Text <<PrevPara>> {
+ tk::TextSetCursor %W [tk::TextPrevPara %W insert]
+}
+bind Text <<NextPara>> {
+ tk::TextSetCursor %W [tk::TextNextPara %W insert]
+}
+bind Text <<SelectPrevWord>> {
+ tk::TextKeySelect %W [tk::TextPrevPos %W insert tcl_startOfPreviousWord]
+}
+bind Text <<SelectNextWord>> {
+ tk::TextKeySelect %W [tk::TextNextWord %W insert]
+}
+bind Text <<SelectPrevPara>> {
+ tk::TextKeySelect %W [tk::TextPrevPara %W insert]
+}
+bind Text <<SelectNextPara>> {
+ tk::TextKeySelect %W [tk::TextNextPara %W insert]
+}
+bind Text <Prior> {
+ tk::TextSetCursor %W [tk::TextScrollPages %W -1]
+}
+bind Text <Shift-Prior> {
+ tk::TextKeySelect %W [tk::TextScrollPages %W -1]
+}
+bind Text <Next> {
+ tk::TextSetCursor %W [tk::TextScrollPages %W 1]
+}
+bind Text <Shift-Next> {
+ tk::TextKeySelect %W [tk::TextScrollPages %W 1]
+}
+bind Text <Control-Prior> {
+ %W xview scroll -1 page
+}
+bind Text <Control-Next> {
+ %W xview scroll 1 page
+}
+
+bind Text <<LineStart>> {
+ tk::TextSetCursor %W {insert display linestart}
+}
+bind Text <<SelectLineStart>> {
+ tk::TextKeySelect %W {insert display linestart}
+}
+bind Text <<LineEnd>> {
+ tk::TextSetCursor %W {insert display lineend}
+}
+bind Text <<SelectLineEnd>> {
+ tk::TextKeySelect %W {insert display lineend}
+}
+bind Text <Control-Home> {
+ tk::TextSetCursor %W 1.0
+}
+bind Text <Control-Shift-Home> {
+ tk::TextKeySelect %W 1.0
+}
+bind Text <Control-End> {
+ tk::TextSetCursor %W {end - 1 indices}
+}
+bind Text <Control-Shift-End> {
+ tk::TextKeySelect %W {end - 1 indices}
+}
+
+bind Text <Tab> {
+ if {[%W cget -state] eq "normal"} {
+ tk::TextInsert %W \t
+ focus %W
+ break
+ }
+}
+bind Text <Shift-Tab> {
+ # Needed only to keep <Tab> binding from triggering; doesn't
+ # have to actually do anything.
+ break
+}
+bind Text <Control-Tab> {
+ focus [tk_focusNext %W]
+}
+bind Text <Control-Shift-Tab> {
+ focus [tk_focusPrev %W]
+}
+bind Text <Control-i> {
+ tk::TextInsert %W \t
+}
+bind Text <Return> {
+ tk::TextInsert %W \n
+ if {[%W cget -autoseparators]} {
+ %W edit separator
+ }
+}
+bind Text <Delete> {
+ if {[tk::TextCursorInSelection %W]} {
+ %W delete sel.first sel.last
+ } else {
+ if {[%W compare end != insert+1c]} {
+ %W delete insert
+ }
+ %W see insert
+ }
+}
+bind Text <BackSpace> {
+ if {[tk::TextCursorInSelection %W]} {
+ %W delete sel.first sel.last
+ } else {
+ if {[%W compare insert != 1.0]} {
+ %W delete insert-1c
+ }
+ %W see insert
+ }
+}
+
+bind Text <Control-space> {
+ %W mark set [tk::TextAnchor %W] insert
+}
+bind Text <Select> {
+ %W mark set [tk::TextAnchor %W] insert
+}
+bind Text <Control-Shift-space> {
+ set tk::Priv(selectMode) char
+ tk::TextKeyExtend %W insert
+}
+bind Text <Shift-Select> {
+ set tk::Priv(selectMode) char
+ tk::TextKeyExtend %W insert
+}
+bind Text <<SelectAll>> {
+ %W tag add sel 1.0 end
+}
+bind Text <<SelectNone>> {
+ %W tag remove sel 1.0 end
+ # An operation that clears the selection must insert an autoseparator,
+ # because the selection operation may have moved the insert mark
+ if {[%W cget -autoseparators]} {
+ %W edit separator
+ }
+}
+bind Text <<Cut>> {
+ tk_textCut %W
+}
+bind Text <<Copy>> {
+ tk_textCopy %W
+}
+bind Text <<Paste>> {
+ tk_textPaste %W
+}
+bind Text <<Clear>> {
+ # Make <<Clear>> an atomic operation on the Undo stack,
+ # i.e. separate it from other delete operations on either side
+ if {[%W cget -autoseparators]} {
+ %W edit separator
+ }
+ catch {%W delete sel.first sel.last}
+ if {[%W cget -autoseparators]} {
+ %W edit separator
+ }
+}
+bind Text <<PasteSelection>> {
+ if {$tk_strictMotif || ![info exists tk::Priv(mouseMoved)]
+ || !$tk::Priv(mouseMoved)} {
+ tk::TextPasteSelection %W %x %y
+ }
+}
+bind Text <Insert> {
+ catch {tk::TextInsert %W [::tk::GetSelection %W PRIMARY]}
+}
+bind Text <KeyPress> {
+ tk::TextInsert %W %A
+}
+
+# Ignore all Alt, Meta, and Control keypresses unless explicitly bound.
+# Otherwise, if a widget binding for one of these is defined, the
+# <KeyPress> class binding will also fire and insert the character,
+# which is wrong. Ditto for <Escape>.
+
+bind Text <Alt-KeyPress> {# nothing }
+bind Text <Meta-KeyPress> {# nothing}
+bind Text <Control-KeyPress> {# nothing}
+bind Text <Escape> {# nothing}
+bind Text <KP_Enter> {# nothing}
+if {[tk windowingsystem] eq "aqua"} {
+ bind Text <Command-KeyPress> {# nothing}
+}
+
+# Additional emacs-like bindings:
+
+bind Text <Control-d> {
+ if {!$tk_strictMotif && [%W compare end != insert+1c]} {
+ %W delete insert
+ }
+}
+bind Text <Control-k> {
+ if {!$tk_strictMotif && [%W compare end != insert+1c]} {
+ if {[%W compare insert == {insert lineend}]} {
+ %W delete insert
+ } else {
+ %W delete insert {insert lineend}
+ }
+ }
+}
+bind Text <Control-o> {
+ if {!$tk_strictMotif} {
+ %W insert insert \n
+ %W mark set insert insert-1c
+ }
+}
+bind Text <Control-t> {
+ if {!$tk_strictMotif} {
+ tk::TextTranspose %W
+ }
+}
+
+bind Text <<Undo>> {
+ # An Undo operation may remove the separator at the top of the Undo stack.
+ # Then the item at the top of the stack gets merged with the subsequent changes.
+ # Place separators before and after Undo to prevent this.
+ if {[%W cget -autoseparators]} {
+ %W edit separator
+ }
+ catch { %W edit undo }
+ if {[%W cget -autoseparators]} {
+ %W edit separator
+ }
+}
+
+bind Text <<Redo>> {
+ catch { %W edit redo }
+}
+
+bind Text <Meta-b> {
+ if {!$tk_strictMotif} {
+ tk::TextSetCursor %W [tk::TextPrevPos %W insert tcl_startOfPreviousWord]
+ }
+}
+bind Text <Meta-d> {
+ if {!$tk_strictMotif && [%W compare end != insert+1c]} {
+ %W delete insert [tk::TextNextWord %W insert]
+ }
+}
+bind Text <Meta-f> {
+ if {!$tk_strictMotif} {
+ tk::TextSetCursor %W [tk::TextNextWord %W insert]
+ }
+}
+bind Text <Meta-less> {
+ if {!$tk_strictMotif} {
+ tk::TextSetCursor %W 1.0
+ }
+}
+bind Text <Meta-greater> {
+ if {!$tk_strictMotif} {
+ tk::TextSetCursor %W end-1c
+ }
+}
+bind Text <Meta-BackSpace> {
+ if {!$tk_strictMotif} {
+ %W delete [tk::TextPrevPos %W insert tcl_startOfPreviousWord] insert
+ }
+}
+bind Text <Meta-Delete> {
+ if {!$tk_strictMotif} {
+ %W delete [tk::TextPrevPos %W insert tcl_startOfPreviousWord] insert
+ }
+}
+
+# Macintosh only bindings:
+
+if {[tk windowingsystem] eq "aqua"} {
+bind Text <Control-v> {
+ tk::TextScrollPages %W 1
+}
+
+# End of Mac only bindings
+}
+
+# A few additional bindings of my own.
+
+bind Text <Control-h> {
+ if {!$tk_strictMotif && [%W compare insert != 1.0]} {
+ %W delete insert-1c
+ %W see insert
+ }
+}
+bind Text <2> {
+ if {!$tk_strictMotif} {
+ tk::TextScanMark %W %x %y
+ }
+}
+bind Text <B2-Motion> {
+ if {!$tk_strictMotif} {
+ tk::TextScanDrag %W %x %y
+ }
+}
+set ::tk::Priv(prevPos) {}
+
+# The MouseWheel will typically only fire on Windows and MacOS X.
+# However, someone could use the "event generate" command to produce one
+# on other platforms. We must be careful not to round -ve values of %D
+# down to zero.
+
+if {[tk windowingsystem] eq "aqua"} {
+ bind Text <MouseWheel> {
+ %W yview scroll [expr {-15 * (%D)}] pixels
+ }
+ bind Text <Option-MouseWheel> {
+ %W yview scroll [expr {-150 * (%D)}] pixels
+ }
+ bind Text <Shift-MouseWheel> {
+ %W xview scroll [expr {-15 * (%D)}] pixels
+ }
+ bind Text <Shift-Option-MouseWheel> {
+ %W xview scroll [expr {-150 * (%D)}] pixels
+ }
+} else {
+ # We must make sure that positive and negative movements are rounded
+ # equally to integers, avoiding the problem that
+ # (int)1/3 = 0,
+ # but
+ # (int)-1/3 = -1
+ # The following code ensure equal +/- behaviour.
+ bind Text <MouseWheel> {
+ if {%D >= 0} {
+ %W yview scroll [expr {-%D/3}] pixels
+ } else {
+ %W yview scroll [expr {(2-%D)/3}] pixels
+ }
+ }
+ bind Text <Shift-MouseWheel> {
+ if {%D >= 0} {
+ %W xview scroll [expr {-%D/3}] pixels
+ } else {
+ %W xview scroll [expr {(2-%D)/3}] pixels
+ }
+ }
+}
+
+if {"x11" eq [tk windowingsystem]} {
+ # Support for mousewheels on Linux/Unix commonly comes through mapping
+ # the wheel to the extended buttons. If you have a mousewheel, find
+ # Linux configuration info at:
+ # http://linuxreviews.org/howtos/xfree/mouse/
+ bind Text <4> {
+ if {!$tk_strictMotif} {
+ %W yview scroll -50 pixels
+ }
+ }
+ bind Text <5> {
+ if {!$tk_strictMotif} {
+ %W yview scroll 50 pixels
+ }
+ }
+ bind Text <Shift-4> {
+ if {!$tk_strictMotif} {
+ %W xview scroll -50 pixels
+ }
+ }
+ bind Text <Shift-5> {
+ if {!$tk_strictMotif} {
+ %W xview scroll 50 pixels
+ }
+ }
+}
+
+# ::tk::TextClosestGap --
+# Given x and y coordinates, this procedure finds the closest boundary
+# between characters to the given coordinates and returns the index
+# of the character just after the boundary.
+#
+# Arguments:
+# w - The text window.
+# x - X-coordinate within the window.
+# y - Y-coordinate within the window.
+
+proc ::tk::TextClosestGap {w x y} {
+ set pos [$w index @$x,$y]
+ set bbox [$w bbox $pos]
+ if {$bbox eq ""} {
+ return $pos
+ }
+ if {($x - [lindex $bbox 0]) < ([lindex $bbox 2]/2)} {
+ return $pos
+ }
+ $w index "$pos + 1 char"
+}
+
+# ::tk::TextButton1 --
+# This procedure is invoked to handle button-1 presses in text
+# widgets. It moves the insertion cursor, sets the selection anchor,
+# and claims the input focus.
+#
+# Arguments:
+# w - The text window in which the button was pressed.
+# x - The x-coordinate of the button press.
+# y - The x-coordinate of the button press.
+
+proc ::tk::TextButton1 {w x y} {
+ variable ::tk::Priv
+
+ set Priv(selectMode) char
+ set Priv(mouseMoved) 0
+ set Priv(pressX) $x
+ set anchorname [tk::TextAnchor $w]
+ $w mark set insert [TextClosestGap $w $x $y]
+ $w mark set $anchorname insert
+ # Set the anchor mark's gravity depending on the click position
+ # relative to the gap
+ set bbox [$w bbox [$w index $anchorname]]
+ if {$x > [lindex $bbox 0]} {
+ $w mark gravity $anchorname right
+ } else {
+ $w mark gravity $anchorname left
+ }
+ # Allow focus in any case on Windows, because that will let the
+ # selection be displayed even for state disabled text widgets.
+ if {[tk windowingsystem] eq "win32" \
+ || [$w cget -state] eq "normal"} {
+ focus $w
+ }
+ if {[$w cget -autoseparators]} {
+ $w edit separator
+ }
+}
+
+# ::tk::TextSelectTo --
+# This procedure is invoked to extend the selection, typically when
+# dragging it with the mouse. Depending on the selection mode (character,
+# word, line) it selects in different-sized units. This procedure
+# ignores mouse motions initially until the mouse has moved from
+# one character to another or until there have been multiple clicks.
+#
+# Note that the 'anchor' is implemented programmatically using
+# a text widget mark, and uses a name that will be unique for each
+# text widget (even when there are multiple peers). Currently the
+# anchor is considered private to Tk, hence the name 'tk::anchor$w'.
+#
+# Arguments:
+# w - The text window in which the button was pressed.
+# x - Mouse x position.
+# y - Mouse y position.
+
+set ::tk::Priv(textanchoruid) 0
+
+proc ::tk::TextAnchor {w} {
+ variable Priv
+ if {![info exists Priv(textanchor,$w)]} {
+ set Priv(textanchor,$w) tk::anchor[incr Priv(textanchoruid)]
+ }
+ return $Priv(textanchor,$w)
+}
+
+proc ::tk::TextSelectTo {w x y {extend 0}} {
+ variable ::tk::Priv
+
+ set anchorname [tk::TextAnchor $w]
+ set cur [TextClosestGap $w $x $y]
+ if {[catch {$w index $anchorname}]} {
+ $w mark set $anchorname $cur
+ }
+ set anchor [$w index $anchorname]
+ if {[$w compare $cur != $anchor] || (abs($Priv(pressX) - $x) >= 3)} {
+ set Priv(mouseMoved) 1
+ }
+ switch -- $Priv(selectMode) {
+ char {
+ if {[$w compare $cur < $anchorname]} {
+ set first $cur
+ set last $anchorname
+ } else {
+ set first $anchorname
+ set last $cur
+ }
+ }
+ word {
+ # Set initial range based only on the anchor (1 char min width)
+ if {[$w mark gravity $anchorname] eq "right"} {
+ set first $anchorname
+ set last "$anchorname + 1c"
+ } else {
+ set first "$anchorname - 1c"
+ set last $anchorname
+ }
+ # Extend range (if necessary) based on the current point
+ if {[$w compare $cur < $first]} {
+ set first $cur
+ } elseif {[$w compare $cur > $last]} {
+ set last $cur
+ }
+
+ # Now find word boundaries
+ set first [TextPrevPos $w "$first + 1c" tcl_wordBreakBefore]
+ set last [TextNextPos $w "$last - 1c" tcl_wordBreakAfter]
+ }
+ line {
+ # Set initial range based only on the anchor
+ set first "$anchorname linestart"
+ set last "$anchorname lineend"
+
+ # Extend range (if necessary) based on the current point
+ if {[$w compare $cur < $first]} {
+ set first "$cur linestart"
+ } elseif {[$w compare $cur > $last]} {
+ set last "$cur lineend"
+ }
+ set first [$w index $first]
+ set last [$w index "$last + 1c"]
+ }
+ }
+ if {$Priv(mouseMoved) || ($Priv(selectMode) ne "char")} {
+ $w tag remove sel 0.0 end
+ $w mark set insert $cur
+ $w tag add sel $first $last
+ $w tag remove sel $last end
+ update idletasks
+ }
+}
+
+# ::tk::TextKeyExtend --
+# This procedure handles extending the selection from the keyboard,
+# where the point to extend to is really the boundary between two
+# characters rather than a particular character.
+#
+# Arguments:
+# w - The text window.
+# index - The point to which the selection is to be extended.
+
+proc ::tk::TextKeyExtend {w index} {
+
+ set anchorname [tk::TextAnchor $w]
+ set cur [$w index $index]
+ if {[catch {$w index $anchorname}]} {
+ $w mark set $anchorname $cur
+ }
+ set anchor [$w index $anchorname]
+ if {[$w compare $cur < $anchorname]} {
+ set first $cur
+ set last $anchorname
+ } else {
+ set first $anchorname
+ set last $cur
+ }
+ $w tag remove sel 0.0 $first
+ $w tag add sel $first $last
+ $w tag remove sel $last end
+}
+
+# ::tk::TextPasteSelection --
+# This procedure sets the insertion cursor to the mouse position,
+# inserts the selection, and sets the focus to the window.
+#
+# Arguments:
+# w - The text window.
+# x, y - Position of the mouse.
+
+proc ::tk::TextPasteSelection {w x y} {
+ $w mark set insert [TextClosestGap $w $x $y]
+ if {![catch {::tk::GetSelection $w PRIMARY} sel]} {
+ set oldSeparator [$w cget -autoseparators]
+ if {$oldSeparator} {
+ $w configure -autoseparators 0
+ $w edit separator
+ }
+ $w insert insert $sel
+ if {$oldSeparator} {
+ $w edit separator
+ $w configure -autoseparators 1
+ }
+ }
+ if {[$w cget -state] eq "normal"} {
+ focus $w
+ }
+}
+
+# ::tk::TextAutoScan --
+# This procedure is invoked when the mouse leaves a text window
+# with button 1 down. It scrolls the window up, down, left, or right,
+# depending on where the mouse is (this information was saved in
+# ::tk::Priv(x) and ::tk::Priv(y)), and reschedules itself as an "after"
+# command so that the window continues to scroll until the mouse
+# moves back into the window or the mouse button is released.
+#
+# Arguments:
+# w - The text window.
+
+proc ::tk::TextAutoScan {w} {
+ variable ::tk::Priv
+ if {![winfo exists $w]} {
+ return
+ }
+ if {$Priv(y) >= [winfo height $w]} {
+ $w yview scroll [expr {1 + $Priv(y) - [winfo height $w]}] pixels
+ } elseif {$Priv(y) < 0} {
+ $w yview scroll [expr {-1 + $Priv(y)}] pixels
+ } elseif {$Priv(x) >= [winfo width $w]} {
+ $w xview scroll 2 units
+ } elseif {$Priv(x) < 0} {
+ $w xview scroll -2 units
+ } else {
+ return
+ }
+ TextSelectTo $w $Priv(x) $Priv(y)
+ set Priv(afterId) [after 50 [list tk::TextAutoScan $w]]
+}
+
+# ::tk::TextSetCursor
+# Move the insertion cursor to a given position in a text. Also
+# clears the selection, if there is one in the text, and makes sure
+# that the insertion cursor is visible. Also, don't let the insertion
+# cursor appear on the dummy last line of the text.
+#
+# Arguments:
+# w - The text window.
+# pos - The desired new position for the cursor in the window.
+
+proc ::tk::TextSetCursor {w pos} {
+ if {[$w compare $pos == end]} {
+ set pos {end - 1 chars}
+ }
+ $w mark set insert $pos
+ $w tag remove sel 1.0 end
+ $w see insert
+ if {[$w cget -autoseparators]} {
+ $w edit separator
+ }
+}
+
+# ::tk::TextKeySelect
+# This procedure is invoked when stroking out selections using the
+# keyboard. It moves the cursor to a new position, then extends
+# the selection to that position.
+#
+# Arguments:
+# w - The text window.
+# new - A new position for the insertion cursor (the cursor hasn't
+# actually been moved to this position yet).
+
+proc ::tk::TextKeySelect {w new} {
+ set anchorname [tk::TextAnchor $w]
+ if {[$w tag nextrange sel 1.0 end] eq ""} {
+ if {[$w compare $new < insert]} {
+ $w tag add sel $new insert
+ } else {
+ $w tag add sel insert $new
+ }
+ $w mark set $anchorname insert
+ } else {
+ if {[catch {$w index $anchorname}]} {
+ $w mark set $anchorname insert
+ }
+ if {[$w compare $new < $anchorname]} {
+ set first $new
+ set last $anchorname
+ } else {
+ set first $anchorname
+ set last $new
+ }
+ $w tag remove sel 1.0 $first
+ $w tag add sel $first $last
+ $w tag remove sel $last end
+ }
+ $w mark set insert $new
+ $w see insert
+ update idletasks
+}
+
+# ::tk::TextResetAnchor --
+# Set the selection anchor to whichever end is farthest from the
+# index argument. One special trick: if the selection has two or
+# fewer characters, just leave the anchor where it is. In this
+# case it doesn't matter which point gets chosen for the anchor,
+# and for the things like Shift-Left and Shift-Right this produces
+# better behavior when the cursor moves back and forth across the
+# anchor.
+#
+# Arguments:
+# w - The text widget.
+# index - Position at which mouse button was pressed, which determines
+# which end of selection should be used as anchor point.
+
+proc ::tk::TextResetAnchor {w index} {
+ if {[$w tag ranges sel] eq ""} {
+ # Don't move the anchor if there is no selection now; this
+ # makes the widget behave "correctly" when the user clicks
+ # once, then shift-clicks somewhere -- ie, the area between
+ # the two clicks will be selected. [Bug: 5929].
+ return
+ }
+ set anchorname [tk::TextAnchor $w]
+ set a [$w index $index]
+ set b [$w index sel.first]
+ set c [$w index sel.last]
+ if {[$w compare $a < $b]} {
+ $w mark set $anchorname sel.last
+ return
+ }
+ if {[$w compare $a > $c]} {
+ $w mark set $anchorname sel.first
+ return
+ }
+ scan $a "%d.%d" lineA chA
+ scan $b "%d.%d" lineB chB
+ scan $c "%d.%d" lineC chC
+ if {$lineB < $lineC+2} {
+ set total [string length [$w get $b $c]]
+ if {$total <= 2} {
+ return
+ }
+ if {[string length [$w get $b $a]] < ($total/2)} {
+ $w mark set $anchorname sel.last
+ } else {
+ $w mark set $anchorname sel.first
+ }
+ return
+ }
+ if {($lineA-$lineB) < ($lineC-$lineA)} {
+ $w mark set $anchorname sel.last
+ } else {
+ $w mark set $anchorname sel.first
+ }
+}
+
+# ::tk::TextCursorInSelection --
+# Check whether the selection exists and contains the insertion cursor. Note
+# that it assumes that the selection is contiguous.
+#
+# Arguments:
+# w - The text widget whose selection is to be checked
+
+proc ::tk::TextCursorInSelection {w} {
+ expr {
+ [llength [$w tag ranges sel]]
+ && [$w compare sel.first <= insert]
+ && [$w compare sel.last >= insert]
+ }
+}
+
+# ::tk::TextInsert --
+# Insert a string into a text at the point of the insertion cursor.
+# If there is a selection in the text, and it covers the point of the
+# insertion cursor, then delete the selection before inserting.
+#
+# Arguments:
+# w - The text window in which to insert the string
+# s - The string to insert (usually just a single character)
+
+proc ::tk::TextInsert {w s} {
+ if {$s eq "" || [$w cget -state] eq "disabled"} {
+ return
+ }
+ set compound 0
+ if {[TextCursorInSelection $w]} {
+ set oldSeparator [$w cget -autoseparators]
+ if {$oldSeparator} {
+ $w configure -autoseparators 0
+ $w edit separator
+ set compound 1
+ }
+ $w delete sel.first sel.last
+ }
+ $w insert insert $s
+ $w see insert
+ if {$compound && $oldSeparator} {
+ $w edit separator
+ $w configure -autoseparators 1
+ }
+}
+
+# ::tk::TextUpDownLine --
+# Returns the index of the character one display line above or below the
+# insertion cursor. There are two tricky things here. First, we want to
+# maintain the original x position across repeated operations, even though
+# some lines that will get passed through don't have enough characters to
+# cover the original column. Second, don't try to scroll past the
+# beginning or end of the text.
+#
+# Arguments:
+# w - The text window in which the cursor is to move.
+# n - The number of display lines to move: -1 for up one line,
+# +1 for down one line.
+
+proc ::tk::TextUpDownLine {w n} {
+ variable ::tk::Priv
+
+ set i [$w index insert]
+ if {$Priv(prevPos) ne $i} {
+ set Priv(textPosOrig) $i
+ }
+ set lines [$w count -displaylines $Priv(textPosOrig) $i]
+ set new [$w index \
+ "$Priv(textPosOrig) + [expr {$lines + $n}] displaylines"]
+ if {[$w compare $new == end] \
+ || [$w compare $new == "insert display linestart"]} {
+ set new $i
+ }
+ set Priv(prevPos) $new
+ return $new
+}
+
+# ::tk::TextPrevPara --
+# Returns the index of the beginning of the paragraph just before a given
+# position in the text (the beginning of a paragraph is the first non-blank
+# character after a blank line).
+#
+# Arguments:
+# w - The text window in which the cursor is to move.
+# pos - Position at which to start search.
+
+proc ::tk::TextPrevPara {w pos} {
+ set pos [$w index "$pos linestart"]
+ while {1} {
+ if {([$w get "$pos - 1 line"] eq "\n" && ([$w get $pos] ne "\n")) \
+ || $pos eq "1.0"} {
+ if {[regexp -indices -- {^[ \t]+(.)} \
+ [$w get $pos "$pos lineend"] -> index]} {
+ set pos [$w index "$pos + [lindex $index 0] chars"]
+ }
+ if {[$w compare $pos != insert] || [lindex [split $pos .] 0]==1} {
+ return $pos
+ }
+ }
+ set pos [$w index "$pos - 1 line"]
+ }
+}
+
+# ::tk::TextNextPara --
+# Returns the index of the beginning of the paragraph just after a given
+# position in the text (the beginning of a paragraph is the first non-blank
+# character after a blank line).
+#
+# Arguments:
+# w - The text window in which the cursor is to move.
+# start - Position at which to start search.
+
+proc ::tk::TextNextPara {w start} {
+ set pos [$w index "$start linestart + 1 line"]
+ while {[$w get $pos] ne "\n"} {
+ if {[$w compare $pos == end]} {
+ return [$w index "end - 1c"]
+ }
+ set pos [$w index "$pos + 1 line"]
+ }
+ while {[$w get $pos] eq "\n"} {
+ set pos [$w index "$pos + 1 line"]
+ if {[$w compare $pos == end]} {
+ return [$w index "end - 1c"]
+ }
+ }
+ if {[regexp -indices -- {^[ \t]+(.)} \
+ [$w get $pos "$pos lineend"] -> index]} {
+ return [$w index "$pos + [lindex $index 0] chars"]
+ }
+ return $pos
+}
+
+# ::tk::TextScrollPages --
+# This is a utility procedure used in bindings for moving up and down
+# pages and possibly extending the selection along the way. It scrolls
+# the view in the widget by the number of pages, and it returns the
+# index of the character that is at the same position in the new view
+# as the insertion cursor used to be in the old view.
+#
+# Arguments:
+# w - The text window in which the cursor is to move.
+# count - Number of pages forward to scroll; may be negative
+# to scroll backwards.
+
+proc ::tk::TextScrollPages {w count} {
+ set bbox [$w bbox insert]
+ $w yview scroll $count pages
+ if {$bbox eq ""} {
+ return [$w index @[expr {[winfo height $w]/2}],0]
+ }
+ return [$w index @[lindex $bbox 0],[lindex $bbox 1]]
+}
+
+# ::tk::TextTranspose --
+# This procedure implements the "transpose" function for text widgets.
+# It tranposes the characters on either side of the insertion cursor,
+# unless the cursor is at the end of the line. In this case it
+# transposes the two characters to the left of the cursor. In either
+# case, the cursor ends up to the right of the transposed characters.
+#
+# Arguments:
+# w - Text window in which to transpose.
+
+proc ::tk::TextTranspose w {
+ set pos insert
+ if {[$w compare $pos != "$pos lineend"]} {
+ set pos [$w index "$pos + 1 char"]
+ }
+ set new [$w get "$pos - 1 char"][$w get "$pos - 2 char"]
+ if {[$w compare "$pos - 1 char" == 1.0]} {
+ return
+ }
+ # ensure this is seen as an atomic op to undo
+ set autosep [$w cget -autoseparators]
+ if {$autosep} {
+ $w configure -autoseparators 0
+ $w edit separator
+ }
+ $w delete "$pos - 2 char" $pos
+ $w insert insert $new
+ $w see insert
+ if {$autosep} {
+ $w edit separator
+ $w configure -autoseparators $autosep
+ }
+}
+
+# ::tk_textCopy --
+# This procedure copies the selection from a text widget into the
+# clipboard.
+#
+# Arguments:
+# w - Name of a text widget.
+
+proc ::tk_textCopy w {
+ if {![catch {set data [$w get sel.first sel.last]}]} {
+ clipboard clear -displayof $w
+ clipboard append -displayof $w $data
+ }
+}
+
+# ::tk_textCut --
+# This procedure copies the selection from a text widget into the
+# clipboard, then deletes the selection (if it exists in the given
+# widget).
+#
+# Arguments:
+# w - Name of a text widget.
+
+proc ::tk_textCut w {
+ if {![catch {set data [$w get sel.first sel.last]}]} {
+ # make <<Cut>> an atomic operation on the Undo stack,
+ # i.e. separate it from other delete operations on either side
+ set oldSeparator [$w cget -autoseparators]
+ if {([$w cget -state] eq "normal") && $oldSeparator} {
+ $w edit separator
+ }
+ clipboard clear -displayof $w
+ clipboard append -displayof $w $data
+ $w delete sel.first sel.last
+ if {([$w cget -state] eq "normal") && $oldSeparator} {
+ $w edit separator
+ }
+ }
+}
+
+# ::tk_textPaste --
+# This procedure pastes the contents of the clipboard to the insertion
+# point in a text widget.
+#
+# Arguments:
+# w - Name of a text widget.
+
+proc ::tk_textPaste w {
+ if {![catch {::tk::GetSelection $w CLIPBOARD} sel]} {
+ set oldSeparator [$w cget -autoseparators]
+ if {$oldSeparator} {
+ $w configure -autoseparators 0
+ $w edit separator
+ }
+ if {[tk windowingsystem] ne "x11"} {
+ catch { $w delete sel.first sel.last }
+ }
+ $w insert insert $sel
+ if {$oldSeparator} {
+ $w edit separator
+ $w configure -autoseparators 1
+ }
+ }
+}
+
+# ::tk::TextNextWord --
+# Returns the index of the next word position after a given position in the
+# text. The next word is platform dependent and may be either the next
+# end-of-word position or the next start-of-word position after the next
+# end-of-word position.
+#
+# Arguments:
+# w - The text window in which the cursor is to move.
+# start - Position at which to start search.
+
+if {[tk windowingsystem] eq "win32"} {
+ proc ::tk::TextNextWord {w start} {
+ TextNextPos $w [TextNextPos $w $start tcl_endOfWord] \
+ tcl_startOfNextWord
+ }
+} else {
+ proc ::tk::TextNextWord {w start} {
+ TextNextPos $w $start tcl_endOfWord
+ }
+}
+
+# ::tk::TextNextPos --
+# Returns the index of the next position after the given starting
+# position in the text as computed by a specified function.
+#
+# Arguments:
+# w - The text window in which the cursor is to move.
+# start - Position at which to start search.
+# op - Function to use to find next position.
+
+proc ::tk::TextNextPos {w start op} {
+ set text ""
+ set cur $start
+ while {[$w compare $cur < end]} {
+ set text $text[$w get -displaychars $cur "$cur lineend + 1c"]
+ set pos [$op $text 0]
+ if {$pos >= 0} {
+ return [$w index "$start + $pos display chars"]
+ }
+ set cur [$w index "$cur lineend +1c"]
+ }
+ return end
+}
+
+# ::tk::TextPrevPos --
+# Returns the index of the previous position before the given starting
+# position in the text as computed by a specified function.
+#
+# Arguments:
+# w - The text window in which the cursor is to move.
+# start - Position at which to start search.
+# op - Function to use to find next position.
+
+proc ::tk::TextPrevPos {w start op} {
+ set text ""
+ set cur $start
+ while {[$w compare $cur > 0.0]} {
+ set text [$w get -displaychars "$cur linestart - 1c" $cur]$text
+ set pos [$op $text end]
+ if {$pos >= 0} {
+ return [$w index "$cur linestart - 1c + $pos display chars"]
+ }
+ set cur [$w index "$cur linestart - 1c"]
+ }
+ return 0.0
+}
+
+# ::tk::TextScanMark --
+#
+# Marks the start of a possible scan drag operation
+#
+# Arguments:
+# w - The text window from which the text to get
+# x - x location on screen
+# y - y location on screen
+
+proc ::tk::TextScanMark {w x y} {
+ variable ::tk::Priv
+ $w scan mark $x $y
+ set Priv(x) $x
+ set Priv(y) $y
+ set Priv(mouseMoved) 0
+}
+
+# ::tk::TextScanDrag --
+#
+# Marks the start of a possible scan drag operation
+#
+# Arguments:
+# w - The text window from which the text to get
+# x - x location on screen
+# y - y location on screen
+
+proc ::tk::TextScanDrag {w x y} {
+ variable ::tk::Priv
+ # Make sure these exist, as some weird situations can trigger the
+ # motion binding without the initial press. [Bug #220269]
+ if {![info exists Priv(x)]} {
+ set Priv(x) $x
+ }
+ if {![info exists Priv(y)]} {
+ set Priv(y) $y
+ }
+ if {($x != $Priv(x)) || ($y != $Priv(y))} {
+ set Priv(mouseMoved) 1
+ }
+ if {[info exists Priv(mouseMoved)] && $Priv(mouseMoved)} {
+ $w scan dragto $x $y
+ }
+}
+
diff --git a/tk8.6/library/tk.tcl b/tk8.6/library/tk.tcl
new file mode 100644
index 0000000..9e9d04d
--- /dev/null
+++ b/tk8.6/library/tk.tcl
@@ -0,0 +1,702 @@
+# tk.tcl --
+#
+# Initialization script normally executed in the interpreter for each Tk-based
+# application. Arranges class bindings for widgets.
+#
+# Copyright (c) 1992-1994 The Regents of the University of California.
+# Copyright (c) 1994-1996 Sun Microsystems, Inc.
+# Copyright (c) 1998-2000 Ajuba Solutions.
+#
+# See the file "license.terms" for information on usage and redistribution of
+# this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+# Verify that we have Tk binary and script components from the same release
+package require -exact Tk 8.6.10
+
+# Create a ::tk namespace
+namespace eval ::tk {
+ # Set up the msgcat commands
+ namespace eval msgcat {
+ namespace export mc mcmax
+ if {[interp issafe] || [catch {package require msgcat}]} {
+ # The msgcat package is not available. Supply our own
+ # minimal replacement.
+ proc mc {src args} {
+ return [format $src {*}$args]
+ }
+ proc mcmax {args} {
+ set max 0
+ foreach string $args {
+ set len [string length $string]
+ if {$len>$max} {
+ set max $len
+ }
+ }
+ return $max
+ }
+ } else {
+ # Get the commands from the msgcat package that Tk uses.
+ namespace import ::msgcat::mc
+ namespace import ::msgcat::mcmax
+ ::msgcat::mcload [file join $::tk_library msgs]
+ }
+ }
+ namespace import ::tk::msgcat::*
+}
+# and a ::ttk namespace
+namespace eval ::ttk {
+ if {$::tk_library ne ""} {
+ # avoid file join to work in safe interps, but this is also x-plat ok
+ variable library $::tk_library/ttk
+ }
+}
+
+# Add Ttk & Tk's directory to the end of the auto-load search path, if it
+# isn't already on the path:
+
+if {[info exists ::auto_path] && ($::tk_library ne "")
+ && ($::tk_library ni $::auto_path)
+} then {
+ lappend ::auto_path $::tk_library $::ttk::library
+}
+
+# Turn off strict Motif look and feel as a default.
+
+set ::tk_strictMotif 0
+
+# Turn on useinputmethods (X Input Methods) by default.
+# We catch this because safe interpreters may not allow the call.
+
+catch {tk useinputmethods 1}
+
+# ::tk::PlaceWindow --
+# place a toplevel at a particular position
+# Arguments:
+# toplevel name of toplevel window
+# ?placement? pointer ?center? ; places $w centered on the pointer
+# widget widgetPath ; centers $w over widget_name
+# defaults to placing toplevel in the middle of the screen
+# ?anchor? center or widgetPath
+# Results:
+# Returns nothing
+#
+proc ::tk::PlaceWindow {w {place ""} {anchor ""}} {
+ wm withdraw $w
+ update idletasks
+ set checkBounds 1
+ if {$place eq ""} {
+ set x [expr {([winfo screenwidth $w]-[winfo reqwidth $w])/2}]
+ set y [expr {([winfo screenheight $w]-[winfo reqheight $w])/2}]
+ set checkBounds 0
+ } elseif {[string equal -length [string length $place] $place "pointer"]} {
+ ## place at POINTER (centered if $anchor == center)
+ if {[string equal -length [string length $anchor] $anchor "center"]} {
+ set x [expr {[winfo pointerx $w]-[winfo reqwidth $w]/2}]
+ set y [expr {[winfo pointery $w]-[winfo reqheight $w]/2}]
+ } else {
+ set x [winfo pointerx $w]
+ set y [winfo pointery $w]
+ }
+ } elseif {[string equal -length [string length $place] $place "widget"] && \
+ [winfo exists $anchor] && [winfo ismapped $anchor]} {
+ ## center about WIDGET $anchor, widget must be mapped
+ set x [expr {[winfo rootx $anchor] + \
+ ([winfo width $anchor]-[winfo reqwidth $w])/2}]
+ set y [expr {[winfo rooty $anchor] + \
+ ([winfo height $anchor]-[winfo reqheight $w])/2}]
+ } else {
+ set x [expr {([winfo screenwidth $w]-[winfo reqwidth $w])/2}]
+ set y [expr {([winfo screenheight $w]-[winfo reqheight $w])/2}]
+ set checkBounds 0
+ }
+ if {$checkBounds} {
+ if {$x < [winfo vrootx $w]} {
+ set x [winfo vrootx $w]
+ } elseif {$x > ([winfo vrootx $w]+[winfo vrootwidth $w]-[winfo reqwidth $w])} {
+ set x [expr {[winfo vrootx $w]+[winfo vrootwidth $w]-[winfo reqwidth $w]}]
+ }
+ if {$y < [winfo vrooty $w]} {
+ set y [winfo vrooty $w]
+ } elseif {$y > ([winfo vrooty $w]+[winfo vrootheight $w]-[winfo reqheight $w])} {
+ set y [expr {[winfo vrooty $w]+[winfo vrootheight $w]-[winfo reqheight $w]}]
+ }
+ if {[tk windowingsystem] eq "aqua"} {
+ # Avoid the native menu bar which sits on top of everything.
+ if {$y < 22} {
+ set y 22
+ }
+ }
+ }
+ wm maxsize $w [winfo vrootwidth $w] [winfo vrootheight $w]
+ wm geometry $w +$x+$y
+ wm deiconify $w
+}
+
+# ::tk::SetFocusGrab --
+# swap out current focus and grab temporarily (for dialogs)
+# Arguments:
+# grab new window to grab
+# focus window to give focus to
+# Results:
+# Returns nothing
+#
+proc ::tk::SetFocusGrab {grab {focus {}}} {
+ set index "$grab,$focus"
+ upvar ::tk::FocusGrab($index) data
+
+ lappend data [focus]
+ set oldGrab [grab current $grab]
+ lappend data $oldGrab
+ if {[winfo exists $oldGrab]} {
+ lappend data [grab status $oldGrab]
+ }
+ # The "grab" command will fail if another application
+ # already holds the grab. So catch it.
+ catch {grab $grab}
+ if {[winfo exists $focus]} {
+ focus $focus
+ }
+}
+
+# ::tk::RestoreFocusGrab --
+# restore old focus and grab (for dialogs)
+# Arguments:
+# grab window that had taken grab
+# focus window that had taken focus
+# destroy destroy|withdraw - how to handle the old grabbed window
+# Results:
+# Returns nothing
+#
+proc ::tk::RestoreFocusGrab {grab focus {destroy destroy}} {
+ set index "$grab,$focus"
+ if {[info exists ::tk::FocusGrab($index)]} {
+ foreach {oldFocus oldGrab oldStatus} $::tk::FocusGrab($index) { break }
+ unset ::tk::FocusGrab($index)
+ } else {
+ set oldGrab ""
+ }
+
+ catch {focus $oldFocus}
+ grab release $grab
+ if {$destroy eq "withdraw"} {
+ wm withdraw $grab
+ } else {
+ destroy $grab
+ }
+ if {[winfo exists $oldGrab] && [winfo ismapped $oldGrab]} {
+ if {$oldStatus eq "global"} {
+ grab -global $oldGrab
+ } else {
+ grab $oldGrab
+ }
+ }
+}
+
+# ::tk::GetSelection --
+# This tries to obtain the default selection. On Unix, we first try
+# and get a UTF8_STRING, a type supported by modern Unix apps for
+# passing Unicode data safely. We fall back on the default STRING
+# type otherwise. On Windows, only the STRING type is necessary.
+# Arguments:
+# w The widget for which the selection will be retrieved.
+# Important for the -displayof property.
+# sel The source of the selection (PRIMARY or CLIPBOARD)
+# Results:
+# Returns the selection, or an error if none could be found
+#
+if {[tk windowingsystem] ne "win32"} {
+ proc ::tk::GetSelection {w {sel PRIMARY}} {
+ if {[catch {
+ selection get -displayof $w -selection $sel -type UTF8_STRING
+ } txt] && [catch {
+ selection get -displayof $w -selection $sel
+ } txt]} then {
+ return -code error -errorcode {TK SELECTION NONE} \
+ "could not find default selection"
+ } else {
+ return $txt
+ }
+ }
+} else {
+ proc ::tk::GetSelection {w {sel PRIMARY}} {
+ if {[catch {
+ selection get -displayof $w -selection $sel
+ } txt]} then {
+ return -code error -errorcode {TK SELECTION NONE} \
+ "could not find default selection"
+ } else {
+ return $txt
+ }
+ }
+}
+
+# ::tk::ScreenChanged --
+# This procedure is invoked by the binding mechanism whenever the
+# "current" screen is changing. The procedure does two things.
+# First, it uses "upvar" to make variable "::tk::Priv" point at an
+# array variable that holds state for the current display. Second,
+# it initializes the array if it didn't already exist.
+#
+# Arguments:
+# screen - The name of the new screen.
+
+proc ::tk::ScreenChanged screen {
+ # Extract the display name.
+ set disp [string range $screen 0 [string last . $screen]-1]
+
+ # Ensure that namespace separators never occur in the display name (as
+ # they cause problems in variable names). Double-colons exist in some VNC
+ # display names. [Bug 2912473]
+ set disp [string map {:: _doublecolon_} $disp]
+
+ uplevel #0 [list upvar #0 ::tk::Priv.$disp ::tk::Priv]
+ variable ::tk::Priv
+
+ if {[info exists Priv]} {
+ set Priv(screen) $screen
+ return
+ }
+ array set Priv {
+ activeMenu {}
+ activeItem {}
+ afterId {}
+ buttons 0
+ buttonWindow {}
+ dragging 0
+ focus {}
+ grab {}
+ initPos {}
+ inMenubutton {}
+ listboxPrev {}
+ menuBar {}
+ mouseMoved 0
+ oldGrab {}
+ popup {}
+ postedMb {}
+ pressX 0
+ pressY 0
+ prevPos 0
+ selectMode char
+ }
+ set Priv(screen) $screen
+ set Priv(tearoff) [string equal [tk windowingsystem] "x11"]
+ set Priv(window) {}
+}
+
+# Do initial setup for Priv, so that it is always bound to something
+# (otherwise, if someone references it, it may get set to a non-upvar-ed
+# value, which will cause trouble later).
+
+tk::ScreenChanged [winfo screen .]
+
+# ::tk::EventMotifBindings --
+# This procedure is invoked as a trace whenever ::tk_strictMotif is
+# changed. It is used to turn on or turn off the motif virtual
+# bindings.
+#
+# Arguments:
+# n1 - the name of the variable being changed ("::tk_strictMotif").
+
+proc ::tk::EventMotifBindings {n1 dummy dummy} {
+ upvar $n1 name
+
+ if {$name} {
+ set op delete
+ } else {
+ set op add
+ }
+
+ event $op <<Cut>> <Control-Key-w> <Control-Lock-Key-W> <Shift-Key-Delete>
+ event $op <<Copy>> <Meta-Key-w> <Meta-Lock-Key-W> <Control-Key-Insert>
+ event $op <<Paste>> <Control-Key-y> <Control-Lock-Key-Y> <Shift-Key-Insert>
+ event $op <<PrevChar>> <Control-Key-b> <Control-Lock-Key-B>
+ event $op <<NextChar>> <Control-Key-f> <Control-Lock-Key-F>
+ event $op <<PrevLine>> <Control-Key-p> <Control-Lock-Key-P>
+ event $op <<NextLine>> <Control-Key-n> <Control-Lock-Key-N>
+ event $op <<LineStart>> <Control-Key-a> <Control-Lock-Key-A>
+ event $op <<LineEnd>> <Control-Key-e> <Control-Lock-Key-E>
+ event $op <<SelectPrevChar>> <Control-Key-B> <Control-Lock-Key-b>
+ event $op <<SelectNextChar>> <Control-Key-F> <Control-Lock-Key-f>
+ event $op <<SelectPrevLine>> <Control-Key-P> <Control-Lock-Key-p>
+ event $op <<SelectNextLine>> <Control-Key-N> <Control-Lock-Key-n>
+ event $op <<SelectLineStart>> <Control-Key-A> <Control-Lock-Key-a>
+ event $op <<SelectLineEnd>> <Control-Key-E> <Control-Lock-Key-e>
+}
+
+#----------------------------------------------------------------------
+# Define common dialogs on platforms where they are not implemented
+# using compiled code.
+#----------------------------------------------------------------------
+
+if {![llength [info commands tk_chooseColor]]} {
+ proc ::tk_chooseColor {args} {
+ return [::tk::dialog::color:: {*}$args]
+ }
+}
+if {![llength [info commands tk_getOpenFile]]} {
+ proc ::tk_getOpenFile {args} {
+ if {$::tk_strictMotif} {
+ return [::tk::MotifFDialog open {*}$args]
+ } else {
+ return [::tk::dialog::file:: open {*}$args]
+ }
+ }
+}
+if {![llength [info commands tk_getSaveFile]]} {
+ proc ::tk_getSaveFile {args} {
+ if {$::tk_strictMotif} {
+ return [::tk::MotifFDialog save {*}$args]
+ } else {
+ return [::tk::dialog::file:: save {*}$args]
+ }
+ }
+}
+if {![llength [info commands tk_messageBox]]} {
+ proc ::tk_messageBox {args} {
+ return [::tk::MessageBox {*}$args]
+ }
+}
+if {![llength [info command tk_chooseDirectory]]} {
+ proc ::tk_chooseDirectory {args} {
+ return [::tk::dialog::file::chooseDir:: {*}$args]
+ }
+}
+
+#----------------------------------------------------------------------
+# Define the set of common virtual events.
+#----------------------------------------------------------------------
+
+switch -exact -- [tk windowingsystem] {
+ "x11" {
+ event add <<Cut>> <Control-Key-x> <Key-F20> <Control-Lock-Key-X>
+ event add <<Copy>> <Control-Key-c> <Key-F16> <Control-Lock-Key-C>
+ event add <<Paste>> <Control-Key-v> <Key-F18> <Control-Lock-Key-V>
+ event add <<PasteSelection>> <ButtonRelease-2>
+ event add <<Undo>> <Control-Key-z> <Control-Lock-Key-Z>
+ event add <<Redo>> <Control-Key-Z> <Control-Lock-Key-z>
+ event add <<ContextMenu>> <Button-3>
+ # On Darwin/Aqua, buttons from left to right are 1,3,2. On Darwin/X11 with recent
+ # XQuartz as the X server, they are 1,2,3; other X servers may differ.
+
+ event add <<SelectAll>> <Control-Key-slash>
+ event add <<SelectNone>> <Control-Key-backslash>
+ event add <<NextChar>> <Right>
+ event add <<SelectNextChar>> <Shift-Right>
+ event add <<PrevChar>> <Left>
+ event add <<SelectPrevChar>> <Shift-Left>
+ event add <<NextWord>> <Control-Right>
+ event add <<SelectNextWord>> <Control-Shift-Right>
+ event add <<PrevWord>> <Control-Left>
+ event add <<SelectPrevWord>> <Control-Shift-Left>
+ event add <<LineStart>> <Home>
+ event add <<SelectLineStart>> <Shift-Home>
+ event add <<LineEnd>> <End>
+ event add <<SelectLineEnd>> <Shift-End>
+ event add <<PrevLine>> <Up>
+ event add <<NextLine>> <Down>
+ event add <<SelectPrevLine>> <Shift-Up>
+ event add <<SelectNextLine>> <Shift-Down>
+ event add <<PrevPara>> <Control-Up>
+ event add <<NextPara>> <Control-Down>
+ event add <<SelectPrevPara>> <Control-Shift-Up>
+ event add <<SelectNextPara>> <Control-Shift-Down>
+ event add <<ToggleSelection>> <Control-ButtonPress-1>
+
+ # Some OS's define a goofy (as in, not <Shift-Tab>) keysym that is
+ # returned when the user presses <Shift-Tab>. In order for tab
+ # traversal to work, we have to add these keysyms to the PrevWindow
+ # event. We use catch just in case the keysym isn't recognized.
+
+ # This is needed for XFree86 systems
+ catch { event add <<PrevWindow>> <ISO_Left_Tab> }
+ # This seems to be correct on *some* HP systems.
+ catch { event add <<PrevWindow>> <hpBackTab> }
+
+ trace add variable ::tk_strictMotif write ::tk::EventMotifBindings
+ set ::tk_strictMotif $::tk_strictMotif
+ # On unix, we want to always display entry/text selection,
+ # regardless of which window has focus
+ set ::tk::AlwaysShowSelection 1
+ }
+ "win32" {
+ event add <<Cut>> <Control-Key-x> <Shift-Key-Delete> <Control-Lock-Key-X>
+ event add <<Copy>> <Control-Key-c> <Control-Key-Insert> <Control-Lock-Key-C>
+ event add <<Paste>> <Control-Key-v> <Shift-Key-Insert> <Control-Lock-Key-V>
+ event add <<PasteSelection>> <ButtonRelease-2>
+ event add <<Undo>> <Control-Key-z> <Control-Lock-Key-Z>
+ event add <<Redo>> <Control-Key-y> <Control-Lock-Key-Y>
+ event add <<ContextMenu>> <Button-3>
+
+ event add <<SelectAll>> <Control-Key-slash> <Control-Key-a> <Control-Lock-Key-A>
+ event add <<SelectNone>> <Control-Key-backslash>
+ event add <<NextChar>> <Right>
+ event add <<SelectNextChar>> <Shift-Right>
+ event add <<PrevChar>> <Left>
+ event add <<SelectPrevChar>> <Shift-Left>
+ event add <<NextWord>> <Control-Right>
+ event add <<SelectNextWord>> <Control-Shift-Right>
+ event add <<PrevWord>> <Control-Left>
+ event add <<SelectPrevWord>> <Control-Shift-Left>
+ event add <<LineStart>> <Home>
+ event add <<SelectLineStart>> <Shift-Home>
+ event add <<LineEnd>> <End>
+ event add <<SelectLineEnd>> <Shift-End>
+ event add <<PrevLine>> <Up>
+ event add <<NextLine>> <Down>
+ event add <<SelectPrevLine>> <Shift-Up>
+ event add <<SelectNextLine>> <Shift-Down>
+ event add <<PrevPara>> <Control-Up>
+ event add <<NextPara>> <Control-Down>
+ event add <<SelectPrevPara>> <Control-Shift-Up>
+ event add <<SelectNextPara>> <Control-Shift-Down>
+ event add <<ToggleSelection>> <Control-ButtonPress-1>
+ }
+ "aqua" {
+ event add <<Cut>> <Command-Key-x> <Key-F2> <Command-Lock-Key-X>
+ event add <<Copy>> <Command-Key-c> <Key-F3> <Command-Lock-Key-C>
+ event add <<Paste>> <Command-Key-v> <Key-F4> <Command-Lock-Key-V>
+ event add <<PasteSelection>> <ButtonRelease-3>
+ event add <<Clear>> <Clear>
+ event add <<ContextMenu>> <Button-2>
+
+ # Official bindings
+ # See http://support.apple.com/kb/HT1343
+ event add <<SelectAll>> <Command-Key-a>
+ event add <<SelectNone>> <Option-Command-Key-a>
+ event add <<Undo>> <Command-Key-z> <Command-Lock-Key-Z>
+ event add <<Redo>> <Shift-Command-Key-z> <Shift-Command-Lock-Key-z>
+ event add <<NextChar>> <Right> <Control-Key-f> <Control-Lock-Key-F>
+ event add <<SelectNextChar>> <Shift-Right> <Shift-Control-Key-F> <Shift-Control-Lock-Key-F>
+ event add <<PrevChar>> <Left> <Control-Key-b> <Control-Lock-Key-B>
+ event add <<SelectPrevChar>> <Shift-Left> <Shift-Control-Key-B> <Shift-Control-Lock-Key-B>
+ event add <<NextWord>> <Option-Right>
+ event add <<SelectNextWord>> <Shift-Option-Right>
+ event add <<PrevWord>> <Option-Left>
+ event add <<SelectPrevWord>> <Shift-Option-Left>
+ event add <<LineStart>> <Home> <Command-Left> <Control-Key-a> <Control-Lock-Key-A>
+ event add <<SelectLineStart>> <Shift-Home> <Shift-Command-Left> <Shift-Control-Key-A> <Shift-Control-Lock-Key-A>
+ event add <<LineEnd>> <End> <Command-Right> <Control-Key-e> <Control-Lock-Key-E>
+ event add <<SelectLineEnd>> <Shift-End> <Shift-Command-Right> <Shift-Control-Key-E> <Shift-Control-Lock-Key-E>
+ event add <<PrevLine>> <Up> <Control-Key-p> <Control-Lock-Key-P>
+ event add <<SelectPrevLine>> <Shift-Up> <Shift-Control-Key-P> <Shift-Control-Lock-Key-P>
+ event add <<NextLine>> <Down> <Control-Key-n> <Control-Lock-Key-N>
+ event add <<SelectNextLine>> <Shift-Down> <Shift-Control-Key-N> <Shift-Control-Lock-Key-N>
+ # Not official, but logical extensions of above. Also derived from
+ # bindings present in MS Word on OSX.
+ event add <<PrevPara>> <Option-Up>
+ event add <<NextPara>> <Option-Down>
+ event add <<SelectPrevPara>> <Shift-Option-Up>
+ event add <<SelectNextPara>> <Shift-Option-Down>
+ event add <<ToggleSelection>> <Command-ButtonPress-1>
+ }
+}
+
+# ----------------------------------------------------------------------
+# Read in files that define all of the class bindings.
+# ----------------------------------------------------------------------
+
+if {$::tk_library ne ""} {
+ proc ::tk::SourceLibFile {file} {
+ namespace eval :: [list source [file join $::tk_library $file.tcl]]
+ }
+ namespace eval ::tk {
+ SourceLibFile icons
+ SourceLibFile button
+ SourceLibFile entry
+ SourceLibFile listbox
+ SourceLibFile menu
+ SourceLibFile panedwindow
+ SourceLibFile scale
+ SourceLibFile scrlbar
+ SourceLibFile spinbox
+ SourceLibFile text
+ }
+}
+
+# ----------------------------------------------------------------------
+# Default bindings for keyboard traversal.
+# ----------------------------------------------------------------------
+
+event add <<PrevWindow>> <Shift-Tab>
+event add <<NextWindow>> <Tab>
+bind all <<NextWindow>> {tk::TabToWindow [tk_focusNext %W]}
+bind all <<PrevWindow>> {tk::TabToWindow [tk_focusPrev %W]}
+
+# ::tk::CancelRepeat --
+# This procedure is invoked to cancel an auto-repeat action described
+# by ::tk::Priv(afterId). It's used by several widgets to auto-scroll
+# the widget when the mouse is dragged out of the widget with a
+# button pressed.
+#
+# Arguments:
+# None.
+
+proc ::tk::CancelRepeat {} {
+ variable ::tk::Priv
+ after cancel $Priv(afterId)
+ set Priv(afterId) {}
+}
+
+# ::tk::TabToWindow --
+# This procedure moves the focus to the given widget.
+# It sends a <<TraverseOut>> virtual event to the previous focus window,
+# if any, before changing the focus, and a <<TraverseIn>> event
+# to the new focus window afterwards.
+#
+# Arguments:
+# w - Window to which focus should be set.
+
+proc ::tk::TabToWindow {w} {
+ set focus [focus]
+ if {$focus ne ""} {
+ event generate $focus <<TraverseOut>>
+ }
+ focus $w
+ event generate $w <<TraverseIn>>
+}
+
+# ::tk::UnderlineAmpersand --
+# This procedure takes some text with ampersand and returns text w/o
+# ampersand and position of the ampersand. Double ampersands are
+# converted to single ones. Position returned is -1 when there is no
+# ampersand.
+#
+proc ::tk::UnderlineAmpersand {text} {
+ set s [string map {&& & & \ufeff} $text]
+ set idx [string first \ufeff $s]
+ return [list [string map {\ufeff {}} $s] $idx]
+}
+
+# ::tk::SetAmpText --
+# Given widget path and text with "magic ampersands", sets -text and
+# -underline options for the widget
+#
+proc ::tk::SetAmpText {widget text} {
+ lassign [UnderlineAmpersand $text] newtext under
+ $widget configure -text $newtext -underline $under
+}
+
+# ::tk::AmpWidget --
+# Creates new widget, turning -text option into -text and -underline
+# options, returned by ::tk::UnderlineAmpersand.
+#
+proc ::tk::AmpWidget {class path args} {
+ set options {}
+ foreach {opt val} $args {
+ if {$opt eq "-text"} {
+ lassign [UnderlineAmpersand $val] newtext under
+ lappend options -text $newtext -underline $under
+ } else {
+ lappend options $opt $val
+ }
+ }
+ set result [$class $path {*}$options]
+ if {[string match "*button" $class]} {
+ bind $path <<AltUnderlined>> [list $path invoke]
+ }
+ return $result
+}
+
+# ::tk::AmpMenuArgs --
+# Processes arguments for a menu entry, turning -label option into
+# -label and -underline options, returned by ::tk::UnderlineAmpersand.
+# The cmd argument is supposed to be either "add" or "entryconfigure"
+#
+proc ::tk::AmpMenuArgs {widget cmd type args} {
+ set options {}
+ foreach {opt val} $args {
+ if {$opt eq "-label"} {
+ lassign [UnderlineAmpersand $val] newlabel under
+ lappend options -label $newlabel -underline $under
+ } else {
+ lappend options $opt $val
+ }
+ }
+ $widget $cmd $type {*}$options
+}
+
+# ::tk::FindAltKeyTarget --
+# Search recursively through the hierarchy of visible widgets to find
+# button or label which has $char as underlined character.
+#
+proc ::tk::FindAltKeyTarget {path char} {
+ set class [winfo class $path]
+ if {$class in {
+ Button Checkbutton Label Radiobutton
+ TButton TCheckbutton TLabel TRadiobutton
+ } && [string equal -nocase $char \
+ [string index [$path cget -text] [$path cget -underline]]]} {
+ return $path
+ }
+ set subwins [concat [grid slaves $path] [pack slaves $path] \
+ [place slaves $path]]
+ if {$class eq "Canvas"} {
+ foreach item [$path find all] {
+ if {[$path type $item] eq "window"} {
+ set w [$path itemcget $item -window]
+ if {$w ne ""} {lappend subwins $w}
+ }
+ }
+ } elseif {$class eq "Text"} {
+ lappend subwins {*}[$path window names]
+ }
+ foreach child $subwins {
+ set target [FindAltKeyTarget $child $char]
+ if {$target ne ""} {
+ return $target
+ }
+ }
+}
+
+# ::tk::AltKeyInDialog --
+# <Alt-Key> event handler for standard dialogs. Sends <<AltUnderlined>>
+# to button or label which has appropriate underlined character.
+#
+proc ::tk::AltKeyInDialog {path key} {
+ set target [FindAltKeyTarget $path $key]
+ if {$target ne ""} {
+ event generate $target <<AltUnderlined>>
+ }
+}
+
+# ::tk::mcmaxamp --
+# Replacement for mcmax, used for texts with "magic ampersand" in it.
+#
+
+proc ::tk::mcmaxamp {args} {
+ set maxlen 0
+ foreach arg $args {
+ # Should we run [mc] in caller's namespace?
+ lassign [UnderlineAmpersand [mc $arg]] msg
+ set length [string length $msg]
+ if {$length > $maxlen} {
+ set maxlen $length
+ }
+ }
+ return $maxlen
+}
+
+# For now, turn off the custom mdef proc for the Mac:
+
+if {[tk windowingsystem] eq "aqua"} {
+ namespace eval ::tk::mac {
+ set useCustomMDEF 0
+ }
+}
+
+#register to send data to macOS Services
+if {[tk windowingsystem] eq "aqua"} {
+proc ::tk::RegisterServiceWidget {w} {
+ ::tk::mac::registerServiceWidget $w
+ }
+}
+
+# Run the Ttk themed widget set initialization
+if {$::ttk::library ne ""} {
+ uplevel \#0 [list source $::ttk::library/ttk.tcl]
+}
+
+# Local Variables:
+# mode: tcl
+# fill-column: 78
+# End:
diff --git a/tk8.6/library/tkfbox.tcl b/tk8.6/library/tkfbox.tcl
new file mode 100644
index 0000000..f73fdc5
--- /dev/null
+++ b/tk8.6/library/tkfbox.tcl
@@ -0,0 +1,1240 @@
+# tkfbox.tcl --
+#
+# Implements the "TK" standard file selection dialog box. This dialog
+# box is used on the Unix platforms whenever the tk_strictMotif flag is
+# not set.
+#
+# The "TK" standard file selection dialog box is similar to the file
+# selection dialog box on Win95(TM). The user can navigate the
+# directories by clicking on the folder icons or by selecting the
+# "Directory" option menu. The user can select files by clicking on the
+# file icons or by entering a filename in the "Filename:" entry.
+#
+# Copyright (c) 1994-1998 Sun Microsystems, Inc.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+
+namespace eval ::tk::dialog {}
+namespace eval ::tk::dialog::file {
+ namespace import -force ::tk::msgcat::*
+ variable showHiddenBtn 0
+ variable showHiddenVar 1
+
+ # Create the images if they did not already exist.
+ if {![info exists ::tk::Priv(updirImage)]} {
+ set ::tk::Priv(updirImage) [image create photo -data {
+ iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABmJLR0QA/gD+AP7rGN
+ SCAAAACXBIWXMAAA3WAAAN1gGQb3mcAAAACXZwQWcAAAAWAAAAFgDcxelYAAAENUlE
+ QVQ4y7WUbWiVZRjHf/f9POcc9+Kc5bC2aIq5sGG0XnTzNU13zAIlFMNc9CEhTCKwCC
+ JIgt7AglaR0RcrolAKg14+GBbiGL6xZiYyy63cmzvu7MVznnOe537rw7bDyvlBoT/c
+ n+6L3/3nf13XLZLJJP+HfICysjKvqqpq+rWKysvLR1tbW+11g+fPn/+bEGIe4KYqCs
+ Owu66u7oG2trah6wJrrRc0NTVhjME5h7Vj5pxzCCE4duxYZUdHx/aGhoZmgJ+yb+wF
+ uCO19RmAffv25f8LFslkktraWtvU1CS6u7vRWmOtxVpbAPu+T0tLS04pFU/J34Wd3S
+ cdFtlfZWeZBU4IcaS5uXn1ZLAEMMY4ay1aa4wx/zpKKYIgoL6+vmjxqoXe5ZLTcsPq
+ bTyycjODpe1y3WMrvDAMV14jCuW0VhhjiJQpOJ5w7Zwjk8/y9R+vsHHNNq6oFMrkeX
+ BxI+8d2sktap3YvOPD0lRQrH+Z81fE7t3WB4gihVKazsuaA20aKSUgAG/seQdy2l6W
+ 37+EyopqTv39I6HJUT2zlnlza2jLdgiTaxwmDov6alLHcZUTzXPGGAauWJbfO4dHl9
+ bgJs3HyfNf0N4ZsOa+jbT3/ownY/hO09p1kBULtjBw+Tvq7xzwauds4dWPDleAcP5E
+ xlprgtBRUZRgYCRPTzoHwEi2g6OnX+eFrW/RM9qBE4p43CeTz5ATaU6nDrFm2cPs/+
+ E1SopqkZ7MFJqntXZaa7IKppckwIEvJbg8LWd28OT6nVihCPQQ8UScWCLGqO4hXuQx
+ qDtJ204eWrqWb1ufRspwtABWaqx5gRKUFSdwDnxPcuLcyyxbuIyaqntIBV34MY9YzC
+ Owg+S9YeJFkniRpGPkCLMrZzG3+jbktA/KClMxFoUhiKC0OAbAhd79CO8i6xe/STyW
+ 4O7KVRgUJ/sP0heeJV4kEVKw/vZd40sFKxat4mLvp6VLdvnb/XHHGGPIKwBBpC1/9n
+ 3DpfRZnn9/AwCxRII9O79kVPdjvByxuET6Ai8mePeTt4lyheXzhOSpCcdWa00uckTG
+ kckbGu76nEhbIm2xznH4VB3OWYaiXqQn8GKSWGIMHuXyPL76LBcupmhp69pz4uMnXi
+ w4VloTGcdQRtGdzmHs1f+RdYZslMZJhzUOHVnceN1ooEiP5JUzdqCQMWCD0JCIeQzn
+ NNpO+clhrCYf5rC+A2cxWmDUWG2oHEOZMEKIwclgMnnLrTeXUV7sUzpNXgU9DmijWV
+ v9LEKCkAIhKIBnlvpks6F21qUZ31u/sbExPa9h0/RzwzMov2nGlG5TmW1YOzzlnSfL
+ mVnyGf19Q7lwZHBp+1fPtflAIgiC7389n9qkihP+lWyeqfUO15ZwQTqlw9H+o2cOvN
+ QJCAHEgEqgYnI0NyALjAJdyWQy7wMa6AEujUdzo3LjcAXwD/XCTKIRjWytAAAAJXRF
+ WHRjcmVhdGUtZGF0ZQAyMDA5LTA0LTA2VDIxOjI1OjQxLTAzOjAw8s+uCAAAACV0RV
+ h0bW9kaWZ5LWRhdGUAMjAwOC0wMS0wM1QxNTowODoyMS0wMjowMJEc/44AAAAZdEVY
+ dFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC
+ }]
+ }
+ if {![info exists ::tk::Priv(folderImage)]} {
+ set ::tk::Priv(folderImage) [image create photo -data {
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiA
+ AAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBl
+ Lm9yZ5vuPBoAAAHCSURBVDiNpZAxa5NRFIafc+9XLCni4BC6FBycMnbrLpkcgtDVX6
+ C70D/g4lZX/4coxLlgxFkpiiSSUGm/JiXfveee45AmNlhawXc53HvPee55X+l2u/yP
+ qt3d3Tfu/viatwt3fzIYDI5uBJhZr9fr3TMzzAx3B+D09PR+v98/7HQ6z5fNOWdCCG
+ U4HH6s67oAVDlnV1UmkwmllBUkhMD29nYHeLuEAkyn06qU8qqu64MrgIyqYmZrkHa7
+ 3drc3KTVahFjJITAaDRiPB4/XFlQVVMtHH5IzJo/P4EA4MyB+erWPQB7++zs7ccYvl
+ U5Z08pMW2cl88eIXLZeDUpXzsBkNQ5eP1+p0opmaoCTgzw6fjs6gLLsp58FB60t0Dc
+ K1Ul54yIEIMQ43Uj68pquDmCeJVztpwzuBNE2LgBoMVpslHMCUEAFgDVxQbzVAiA+a
+ K5uGPmmDtZF3VpoUm2ArhqQaRiUjcMf81p1G60UEVhcjZfAFTVUkrgkS+jc06mDX9n
+ vq4YhJ9nlxZExMwMEaHJRutOdWuIIsJFUoBSuTvHJ4YIfP46unV4qdlsjsBRZRtb/X
+ fHd5+C8+P7+J8BIoxFwovfRxYhnhxjpzEAAAAASUVORK5CYII=
+ }]
+ }
+ if {![info exists ::tk::Priv(fileImage)]} {
+ set ::tk::Priv(fileImage) [image create photo -data {
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gva
+ eTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1QQWFA84umAmQgAAANpJREFU
+ OMutkj1uhDAQhb8HSLtbISGfgZ+zbJkix0HmFhwhUdocBnMBGvqtTIqIFSReWKK8ai
+ x73nwzHrVt+zEMwwvH9FrX9TsA1trpqKy10+yUzME4jnjvAZB0LzXHkojjmDRNVyh3
+ A+89zrlVwlKSqKrqVy/J8lAUxSZBSMny4ZLgp54iyPM8UPHGNJ2IomibAKDv+9VlWZ
+ bABbgB5/0WQgSSkC4PF2JF4JzbHN430c4vhAm0TyCJruuClefph4yCBCGT3T3Isoy/
+ KDHGfDZNcz2SZIx547/0BVRRX7n8uT/sAAAAAElFTkSuQmCC
+ }]
+ }
+}
+
+# ::tk::dialog::file:: --
+#
+# Implements the TK file selection dialog. This dialog is used when the
+# tk_strictMotif flag is set to false. This procedure shouldn't be
+# called directly. Call tk_getOpenFile or tk_getSaveFile instead.
+#
+# Arguments:
+# type "open" or "save"
+# args Options parsed by the procedure.
+#
+
+proc ::tk::dialog::file:: {type args} {
+ variable ::tk::Priv
+ variable showHiddenBtn
+ set dataName __tk_filedialog
+ upvar ::tk::dialog::file::$dataName data
+
+ Config $dataName $type $args
+
+ if {$data(-parent) eq "."} {
+ set w .$dataName
+ } else {
+ set w $data(-parent).$dataName
+ }
+
+ # (re)create the dialog box if necessary
+ #
+ if {![winfo exists $w]} {
+ Create $w TkFDialog
+ } elseif {[winfo class $w] ne "TkFDialog"} {
+ destroy $w
+ Create $w TkFDialog
+ } else {
+ set data(dirMenuBtn) $w.contents.f1.menu
+ set data(dirMenu) $w.contents.f1.menu.menu
+ set data(upBtn) $w.contents.f1.up
+ set data(icons) $w.contents.icons
+ set data(ent) $w.contents.f2.ent
+ set data(typeMenuLab) $w.contents.f2.lab2
+ set data(typeMenuBtn) $w.contents.f2.menu
+ set data(typeMenu) $data(typeMenuBtn).m
+ set data(okBtn) $w.contents.f2.ok
+ set data(cancelBtn) $w.contents.f2.cancel
+ set data(hiddenBtn) $w.contents.f2.hidden
+ SetSelectMode $w $data(-multiple)
+ }
+ if {$showHiddenBtn} {
+ $data(hiddenBtn) configure -state normal
+ grid $data(hiddenBtn)
+ } else {
+ $data(hiddenBtn) configure -state disabled
+ grid remove $data(hiddenBtn)
+ }
+
+ # Make sure subseqent uses of this dialog are independent [Bug 845189]
+ unset -nocomplain data(extUsed)
+
+ # Dialog boxes should be transient with respect to their parent, so that
+ # they will always stay on top of their parent window. However, some
+ # window managers will create the window as withdrawn if the parent window
+ # is withdrawn or iconified. Combined with the grab we put on the window,
+ # this can hang the entire application. Therefore we only make the dialog
+ # transient if the parent is viewable.
+
+ if {[winfo viewable [winfo toplevel $data(-parent)]]} {
+ wm transient $w $data(-parent)
+ }
+
+ # Add traces on the selectPath variable
+ #
+
+ trace add variable data(selectPath) write \
+ [list ::tk::dialog::file::SetPath $w]
+ $data(dirMenuBtn) configure \
+ -textvariable ::tk::dialog::file::${dataName}(selectPath)
+
+ # Cleanup previous menu
+ #
+ $data(typeMenu) delete 0 end
+ $data(typeMenuBtn) configure -state normal -text ""
+
+ # Initialize the file types menu
+ #
+ if {[llength $data(-filetypes)]} {
+ # Default type and name to first entry
+ set initialtype [lindex $data(-filetypes) 0]
+ set initialTypeName [lindex $initialtype 0]
+ if {$data(-typevariable) ne ""} {
+ upvar #0 $data(-typevariable) typeVariable
+ if {[info exists typeVariable]} {
+ set initialTypeName $typeVariable
+ }
+ }
+ foreach type $data(-filetypes) {
+ set title [lindex $type 0]
+ set filter [lindex $type 1]
+ $data(typeMenu) add command -label $title \
+ -command [list ::tk::dialog::file::SetFilter $w $type]
+ # [string first] avoids glob-pattern char issues
+ if {[string first ${initialTypeName} $title] == 0} {
+ set initialtype $type
+ }
+ }
+ SetFilter $w $initialtype
+ $data(typeMenuBtn) configure -state normal
+ $data(typeMenuLab) configure -state normal
+ } else {
+ set data(filter) "*"
+ $data(typeMenuBtn) configure -state disabled -takefocus 0
+ $data(typeMenuLab) configure -state disabled
+ }
+ UpdateWhenIdle $w
+
+ # Withdraw the window, then update all the geometry information
+ # so we know how big it wants to be, then center the window in the
+ # display (Motif style) and de-iconify it.
+
+ ::tk::PlaceWindow $w widget $data(-parent)
+ wm title $w $data(-title)
+
+ # Set a grab and claim the focus too.
+
+ ::tk::SetFocusGrab $w $data(ent)
+ $data(ent) delete 0 end
+ $data(ent) insert 0 $data(selectFile)
+ $data(ent) selection range 0 end
+ $data(ent) icursor end
+
+ # Wait for the user to respond, then restore the focus and return the
+ # index of the selected button. Restore the focus before deleting the
+ # window, since otherwise the window manager may take the focus away so we
+ # can't redirect it. Finally, restore any grab that was in effect.
+
+ vwait ::tk::Priv(selectFilePath)
+
+ ::tk::RestoreFocusGrab $w $data(ent) withdraw
+
+ # Cleanup traces on selectPath variable
+ #
+
+ foreach trace [trace info variable data(selectPath)] {
+ trace remove variable data(selectPath) {*}$trace
+ }
+ $data(dirMenuBtn) configure -textvariable {}
+
+ return $Priv(selectFilePath)
+}
+
+# ::tk::dialog::file::Config --
+#
+# Configures the TK filedialog according to the argument list
+#
+proc ::tk::dialog::file::Config {dataName type argList} {
+ upvar ::tk::dialog::file::$dataName data
+
+ set data(type) $type
+
+ # 0: Delete all variable that were set on data(selectPath) the
+ # last time the file dialog is used. The traces may cause troubles
+ # if the dialog is now used with a different -parent option.
+
+ foreach trace [trace info variable data(selectPath)] {
+ trace remove variable data(selectPath) {*}$trace
+ }
+
+ # 1: the configuration specs
+ #
+ set specs {
+ {-defaultextension "" "" ""}
+ {-filetypes "" "" ""}
+ {-initialdir "" "" ""}
+ {-initialfile "" "" ""}
+ {-parent "" "" "."}
+ {-title "" "" ""}
+ {-typevariable "" "" ""}
+ }
+
+ # The "-multiple" option is only available for the "open" file dialog.
+ #
+ if {$type eq "open"} {
+ lappend specs {-multiple "" "" "0"}
+ }
+
+ # The "-confirmoverwrite" option is only for the "save" file dialog.
+ #
+ if {$type eq "save"} {
+ lappend specs {-confirmoverwrite "" "" "1"}
+ }
+
+ # 2: default values depending on the type of the dialog
+ #
+ if {![info exists data(selectPath)]} {
+ # first time the dialog has been popped up
+ set data(selectPath) [pwd]
+ set data(selectFile) ""
+ }
+
+ # 3: parse the arguments
+ #
+ tclParseConfigSpec ::tk::dialog::file::$dataName $specs "" $argList
+
+ if {$data(-title) eq ""} {
+ if {$type eq "open"} {
+ set data(-title) [mc "Open"]
+ } else {
+ set data(-title) [mc "Save As"]
+ }
+ }
+
+ # 4: set the default directory and selection according to the -initial
+ # settings
+ #
+ if {$data(-initialdir) ne ""} {
+ # Ensure that initialdir is an absolute path name.
+ if {[file isdirectory $data(-initialdir)]} {
+ set old [pwd]
+ cd $data(-initialdir)
+ set data(selectPath) [pwd]
+ cd $old
+ } else {
+ set data(selectPath) [pwd]
+ }
+ }
+ set data(selectFile) $data(-initialfile)
+
+ # 5. Parse the -filetypes option
+ #
+ set data(origfiletypes) $data(-filetypes)
+ set data(-filetypes) [::tk::FDGetFileTypes $data(-filetypes)]
+
+ if {![winfo exists $data(-parent)]} {
+ return -code error -errorcode [list TK LOOKUP WINDOW $data(-parent)] \
+ "bad window path name \"$data(-parent)\""
+ }
+
+ # Set -multiple to a one or zero value (not other boolean types like
+ # "yes") so we can use it in tests more easily.
+ if {$type eq "save"} {
+ set data(-multiple) 0
+ } elseif {$data(-multiple)} {
+ set data(-multiple) 1
+ } else {
+ set data(-multiple) 0
+ }
+}
+
+proc ::tk::dialog::file::Create {w class} {
+ set dataName [lindex [split $w .] end]
+ upvar ::tk::dialog::file::$dataName data
+ variable ::tk::Priv
+ global tk_library
+
+ toplevel $w -class $class
+ if {[tk windowingsystem] eq "x11"} {wm attributes $w -type dialog}
+ pack [ttk::frame $w.contents] -expand 1 -fill both
+ #set w $w.contents
+
+ # f1: the frame with the directory option menu
+ #
+ set f1 [ttk::frame $w.contents.f1]
+ bind [::tk::AmpWidget ttk::label $f1.lab -text [mc "&Directory:"]] \
+ <<AltUnderlined>> [list focus $f1.menu]
+
+ set data(dirMenuBtn) $f1.menu
+ if {![info exists data(selectPath)]} {
+ set data(selectPath) ""
+ }
+ set data(dirMenu) $f1.menu.menu
+ ttk::menubutton $f1.menu -menu $data(dirMenu) -direction flush \
+ -textvariable [format %s(selectPath) ::tk::dialog::file::$dataName]
+ menu $data(dirMenu) -tearoff 0
+ $data(dirMenu) add radiobutton -label "" -variable \
+ [format %s(selectPath) ::tk::dialog::file::$dataName]
+ set data(upBtn) [ttk::button $f1.up]
+ $data(upBtn) configure -image $Priv(updirImage)
+
+ $f1.menu configure -takefocus 1;# -highlightthickness 2
+
+ pack $data(upBtn) -side right -padx 4 -fill both
+ pack $f1.lab -side left -padx 4 -fill both
+ pack $f1.menu -expand yes -fill both -padx 4
+
+ # data(icons): the IconList that list the files and directories.
+ #
+ if {$class eq "TkFDialog"} {
+ if { $data(-multiple) } {
+ set fNameCaption [mc "File &names:"]
+ } else {
+ set fNameCaption [mc "File &name:"]
+ }
+ set fTypeCaption [mc "Files of &type:"]
+ set iconListCommand [list ::tk::dialog::file::OkCmd $w]
+ } else {
+ set fNameCaption [mc "&Selection:"]
+ set iconListCommand [list ::tk::dialog::file::chooseDir::DblClick $w]
+ }
+ set data(icons) [::tk::IconList $w.contents.icons \
+ -command $iconListCommand -multiple $data(-multiple)]
+ bind $data(icons) <<ListboxSelect>> \
+ [list ::tk::dialog::file::ListBrowse $w]
+
+ # f2: the frame with the OK button, cancel button, "file name" field
+ # and file types field.
+ #
+ set f2 [ttk::frame $w.contents.f2]
+ bind [::tk::AmpWidget ttk::label $f2.lab -text $fNameCaption -anchor e]\
+ <<AltUnderlined>> [list focus $f2.ent]
+ # -pady 0
+ set data(ent) [ttk::entry $f2.ent]
+
+ # The font to use for the icons. The default Canvas font on Unix is just
+ # deviant.
+ set ::tk::$w.contents.icons(font) [$data(ent) cget -font]
+
+ # Make the file types bits only if this is a File Dialog
+ if {$class eq "TkFDialog"} {
+ set data(typeMenuLab) [::tk::AmpWidget ttk::label $f2.lab2 \
+ -text $fTypeCaption -anchor e]
+ # -pady [$f2.lab cget -pady]
+ set data(typeMenuBtn) [ttk::menubutton $f2.menu \
+ -menu $f2.menu.m]
+ # -indicatoron 1
+ set data(typeMenu) [menu $data(typeMenuBtn).m -tearoff 0]
+ # $data(typeMenuBtn) configure -takefocus 1 -relief raised -anchor w
+ bind $data(typeMenuLab) <<AltUnderlined>> [list \
+ focus $data(typeMenuBtn)]
+ }
+
+ # The hidden button is displayed when ::tk::dialog::file::showHiddenBtn is
+ # true. Create it disabled so the binding doesn't trigger if it isn't
+ # shown.
+ if {$class eq "TkFDialog"} {
+ set text [mc "Show &Hidden Files and Directories"]
+ } else {
+ set text [mc "Show &Hidden Directories"]
+ }
+ set data(hiddenBtn) [::tk::AmpWidget ttk::checkbutton $f2.hidden \
+ -text $text -state disabled \
+ -variable ::tk::dialog::file::showHiddenVar \
+ -command [list ::tk::dialog::file::UpdateWhenIdle $w]]
+# -anchor w -padx 3
+
+ # the okBtn is created after the typeMenu so that the keyboard traversal
+ # is in the right order, and add binding so that we find out when the
+ # dialog is destroyed by the user (added here instead of to the overall
+ # window so no confusion about how much <Destroy> gets called; exactly
+ # once will do). [Bug 987169]
+
+ set data(okBtn) [::tk::AmpWidget ttk::button $f2.ok \
+ -text [mc "&OK"] -default active];# -pady 3]
+ bind $data(okBtn) <Destroy> [list ::tk::dialog::file::Destroyed $w]
+ set data(cancelBtn) [::tk::AmpWidget ttk::button $f2.cancel \
+ -text [mc "&Cancel"] -default normal];# -pady 3]
+
+ # grid the widgets in f2
+ #
+ grid $f2.lab $f2.ent $data(okBtn) -padx 4 -pady 3 -sticky ew
+ grid configure $f2.ent -padx 2
+ if {$class eq "TkFDialog"} {
+ grid $data(typeMenuLab) $data(typeMenuBtn) $data(cancelBtn) \
+ -padx 4 -sticky ew
+ grid configure $data(typeMenuBtn) -padx 0
+ grid $data(hiddenBtn) -columnspan 2 -padx 4 -sticky ew
+ } else {
+ grid $data(hiddenBtn) - $data(cancelBtn) -padx 4 -sticky ew
+ }
+ grid columnconfigure $f2 1 -weight 1
+
+ # Pack all the frames together. We are done with widget construction.
+ #
+ pack $f1 -side top -fill x -pady 4
+ pack $f2 -side bottom -pady 4 -fill x
+ pack $data(icons) -expand yes -fill both -padx 4 -pady 1
+
+ # Set up the event handlers that are common to Directory and File Dialogs
+ #
+
+ wm protocol $w WM_DELETE_WINDOW [list ::tk::dialog::file::CancelCmd $w]
+ $data(upBtn) configure -command [list ::tk::dialog::file::UpDirCmd $w]
+ $data(cancelBtn) configure -command [list ::tk::dialog::file::CancelCmd $w]
+ bind $w <KeyPress-Escape> [list $data(cancelBtn) invoke]
+ bind $w <Alt-Key> [list tk::AltKeyInDialog $w %A]
+
+ # Set up event handlers specific to File or Directory Dialogs
+ #
+ if {$class eq "TkFDialog"} {
+ bind $data(ent) <Return> [list ::tk::dialog::file::ActivateEnt $w]
+ $data(okBtn) configure -command [list ::tk::dialog::file::OkCmd $w]
+ bind $w <Alt-t> [format {
+ if {[%s cget -state] eq "normal"} {
+ focus %s
+ }
+ } $data(typeMenuBtn) $data(typeMenuBtn)]
+ } else {
+ set okCmd [list ::tk::dialog::file::chooseDir::OkCmd $w]
+ bind $data(ent) <Return> $okCmd
+ $data(okBtn) configure -command $okCmd
+ bind $w <Alt-s> [list focus $data(ent)]
+ bind $w <Alt-o> [list $data(okBtn) invoke]
+ }
+ bind $w <Alt-h> [list $data(hiddenBtn) invoke]
+ bind $data(ent) <Tab> [list ::tk::dialog::file::CompleteEnt $w]
+
+ # Build the focus group for all the entries
+ #
+ ::tk::FocusGroup_Create $w
+ ::tk::FocusGroup_BindIn $w $data(ent) [list \
+ ::tk::dialog::file::EntFocusIn $w]
+ ::tk::FocusGroup_BindOut $w $data(ent) [list \
+ ::tk::dialog::file::EntFocusOut $w]
+}
+
+# ::tk::dialog::file::SetSelectMode --
+#
+# Set the select mode of the dialog to single select or multi-select.
+#
+# Arguments:
+# w The dialog path.
+# multi 1 if the dialog is multi-select; 0 otherwise.
+#
+# Results:
+# None.
+
+proc ::tk::dialog::file::SetSelectMode {w multi} {
+ set dataName __tk_filedialog
+ upvar ::tk::dialog::file::$dataName data
+ if { $multi } {
+ set fNameCaption [mc "File &names:"]
+ } else {
+ set fNameCaption [mc "File &name:"]
+ }
+ set iconListCommand [list ::tk::dialog::file::OkCmd $w]
+ ::tk::SetAmpText $w.contents.f2.lab $fNameCaption
+ $data(icons) configure -multiple $multi -command $iconListCommand
+ return
+}
+
+# ::tk::dialog::file::UpdateWhenIdle --
+#
+# Creates an idle event handler which updates the dialog in idle time.
+# This is important because loading the directory may take a long time
+# and we don't want to load the same directory for multiple times due to
+# multiple concurrent events.
+#
+proc ::tk::dialog::file::UpdateWhenIdle {w} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+
+ if {[info exists data(updateId)]} {
+ return
+ }
+ set data(updateId) [after idle [list ::tk::dialog::file::Update $w]]
+}
+
+# ::tk::dialog::file::Update --
+#
+# Loads the files and directories into the IconList widget. Also sets up
+# the directory option menu for quick access to parent directories.
+#
+proc ::tk::dialog::file::Update {w} {
+ # This proc may be called within an idle handler. Make sure that the
+ # window has not been destroyed before this proc is called
+ if {![winfo exists $w]} {
+ return
+ }
+ set class [winfo class $w]
+ if {($class ne "TkFDialog") && ($class ne "TkChooseDir")} {
+ return
+ }
+
+ set dataName [winfo name $w]
+ upvar ::tk::dialog::file::$dataName data
+ variable ::tk::Priv
+ variable showHiddenVar
+ global tk_library
+ unset -nocomplain data(updateId)
+
+ set folder $Priv(folderImage)
+ set file $Priv(fileImage)
+
+ set appPWD [pwd]
+ if {[catch {
+ cd $data(selectPath)
+ }]} then {
+ # We cannot change directory to $data(selectPath). $data(selectPath)
+ # should have been checked before ::tk::dialog::file::Update is
+ # called, so we normally won't come to here. Anyways, give an error
+ # and abort action.
+ tk_messageBox -type ok -parent $w -icon warning -message [mc \
+ "Cannot change to the directory \"%1\$s\".\nPermission denied."\
+ $data(selectPath)]
+ cd $appPWD
+ return
+ }
+
+ # Turn on the busy cursor. BUG?? We haven't disabled X events, though,
+ # so the user may still click and cause havoc ...
+ #
+ set entCursor [$data(ent) cget -cursor]
+ set dlgCursor [$w cget -cursor]
+ $data(ent) configure -cursor watch
+ $w configure -cursor watch
+ update idletasks
+
+ $data(icons) deleteall
+
+ set showHidden $showHiddenVar
+
+ # Make the dir list. Note that using an explicit [pwd] (instead of '.') is
+ # better in some VFS cases.
+ $data(icons) add $folder [GlobFiltered [pwd] d 1]
+
+ if {$class eq "TkFDialog"} {
+ # Make the file list if this is a File Dialog, selecting all but
+ # 'd'irectory type files.
+ #
+ $data(icons) add $file [GlobFiltered [pwd] {f b c l p s}]
+ }
+
+ # Update the Directory: option menu
+ #
+ set list ""
+ set dir ""
+ foreach subdir [file split $data(selectPath)] {
+ set dir [file join $dir $subdir]
+ lappend list $dir
+ }
+
+ $data(dirMenu) delete 0 end
+ set var [format %s(selectPath) ::tk::dialog::file::$dataName]
+ foreach path $list {
+ $data(dirMenu) add command -label $path -command [list set $var $path]
+ }
+
+ # Restore the PWD to the application's PWD
+ #
+ cd $appPWD
+
+ if {$class eq "TkFDialog"} {
+ # Restore the Open/Save Button if this is a File Dialog
+ #
+ if {$data(type) eq "open"} {
+ ::tk::SetAmpText $data(okBtn) [mc "&Open"]
+ } else {
+ ::tk::SetAmpText $data(okBtn) [mc "&Save"]
+ }
+ }
+
+ # turn off the busy cursor.
+ #
+ $data(ent) configure -cursor $entCursor
+ $w configure -cursor $dlgCursor
+}
+
+# ::tk::dialog::file::SetPathSilently --
+#
+# Sets data(selectPath) without invoking the trace procedure
+#
+proc ::tk::dialog::file::SetPathSilently {w path} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+
+ set cb [list ::tk::dialog::file::SetPath $w]
+ trace remove variable data(selectPath) write $cb
+ set data(selectPath) $path
+ trace add variable data(selectPath) write $cb
+}
+
+
+# This proc gets called whenever data(selectPath) is set
+#
+proc ::tk::dialog::file::SetPath {w name1 name2 op} {
+ if {[winfo exists $w]} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+ UpdateWhenIdle $w
+ # On directory dialogs, we keep the entry in sync with the currentdir.
+ if {[winfo class $w] eq "TkChooseDir"} {
+ $data(ent) delete 0 end
+ $data(ent) insert end $data(selectPath)
+ }
+ }
+}
+
+# This proc gets called whenever data(filter) is set
+#
+proc ::tk::dialog::file::SetFilter {w type} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+
+ set data(filterType) $type
+ set data(filter) [lindex $type 1]
+ $data(typeMenuBtn) configure -text [lindex $type 0] ;#-indicatoron 1
+
+ # If we aren't using a default extension, use the one suppled by the
+ # filter.
+ if {![info exists data(extUsed)]} {
+ if {[string length $data(-defaultextension)]} {
+ set data(extUsed) 1
+ } else {
+ set data(extUsed) 0
+ }
+ }
+
+ if {!$data(extUsed)} {
+ # Get the first extension in the list that matches {^\*\.\w+$} and
+ # remove all * from the filter.
+ set index [lsearch -regexp $data(filter) {^\*\.\w+$}]
+ if {$index >= 0} {
+ set data(-defaultextension) \
+ [string trimleft [lindex $data(filter) $index] "*"]
+ } else {
+ # Couldn't find anything! Reset to a safe default...
+ set data(-defaultextension) ""
+ }
+ }
+
+ $data(icons) see 0
+
+ UpdateWhenIdle $w
+}
+
+# tk::dialog::file::ResolveFile --
+#
+# Interpret the user's text input in a file selection dialog. Performs:
+#
+# (1) ~ substitution
+# (2) resolve all instances of . and ..
+# (3) check for non-existent files/directories
+# (4) check for chdir permissions
+# (5) conversion of environment variable references to their
+# contents (once only)
+#
+# Arguments:
+# context: the current directory you are in
+# text: the text entered by the user
+# defaultext: the default extension to add to files with no extension
+# expandEnv: whether to expand environment variables (yes by default)
+#
+# Return vaue:
+# [list $flag $directory $file]
+#
+# flag = OK : valid input
+# = PATTERN : valid directory/pattern
+# = PATH : the directory does not exist
+# = FILE : the directory exists by the file doesn't exist
+# = CHDIR : Cannot change to the directory
+# = ERROR : Invalid entry
+#
+# directory : valid only if flag = OK or PATTERN or FILE
+# file : valid only if flag = OK or PATTERN
+#
+# directory may not be the same as context, because text may contain a
+# subdirectory name
+#
+proc ::tk::dialog::file::ResolveFile {context text defaultext {expandEnv 1}} {
+ set appPWD [pwd]
+
+ set path [JoinFile $context $text]
+
+ # If the file has no extension, append the default. Be careful not to do
+ # this for directories, otherwise typing a dirname in the box will give
+ # back "dirname.extension" instead of trying to change dir.
+ if {
+ ![file isdirectory $path] && ([file ext $path] eq "") &&
+ ![string match {$*} [file tail $path]]
+ } then {
+ set path "$path$defaultext"
+ }
+
+ if {[catch {file exists $path}]} {
+ # This "if" block can be safely removed if the following code stop
+ # generating errors.
+ #
+ # file exists ~nonsuchuser
+ #
+ return [list ERROR $path ""]
+ }
+
+ if {[file exists $path]} {
+ if {[file isdirectory $path]} {
+ if {[catch {cd $path}]} {
+ return [list CHDIR $path ""]
+ }
+ set directory [pwd]
+ set file ""
+ set flag OK
+ cd $appPWD
+ } else {
+ if {[catch {cd [file dirname $path]}]} {
+ return [list CHDIR [file dirname $path] ""]
+ }
+ set directory [pwd]
+ set file [file tail $path]
+ set flag OK
+ cd $appPWD
+ }
+ } else {
+ set dirname [file dirname $path]
+ if {[file exists $dirname]} {
+ if {[catch {cd $dirname}]} {
+ return [list CHDIR $dirname ""]
+ }
+ set directory [pwd]
+ cd $appPWD
+ set file [file tail $path]
+ # It's nothing else, so check to see if it is an env-reference
+ if {$expandEnv && [string match {$*} $file]} {
+ set var [string range $file 1 end]
+ if {[info exist ::env($var)]} {
+ return [ResolveFile $context $::env($var) $defaultext 0]
+ }
+ }
+ if {[regexp {[*?]} $file]} {
+ set flag PATTERN
+ } else {
+ set flag FILE
+ }
+ } else {
+ set directory $dirname
+ set file [file tail $path]
+ set flag PATH
+ # It's nothing else, so check to see if it is an env-reference
+ if {$expandEnv && [string match {$*} $file]} {
+ set var [string range $file 1 end]
+ if {[info exist ::env($var)]} {
+ return [ResolveFile $context $::env($var) $defaultext 0]
+ }
+ }
+ }
+ }
+
+ return [list $flag $directory $file]
+}
+
+
+# Gets called when the entry box gets keyboard focus. We clear the selection
+# from the icon list . This way the user can be certain that the input in the
+# entry box is the selection.
+#
+proc ::tk::dialog::file::EntFocusIn {w} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+
+ if {[$data(ent) get] ne ""} {
+ $data(ent) selection range 0 end
+ $data(ent) icursor end
+ } else {
+ $data(ent) selection clear
+ }
+
+ if {[winfo class $w] eq "TkFDialog"} {
+ # If this is a File Dialog, make sure the buttons are labeled right.
+ if {$data(type) eq "open"} {
+ ::tk::SetAmpText $data(okBtn) [mc "&Open"]
+ } else {
+ ::tk::SetAmpText $data(okBtn) [mc "&Save"]
+ }
+ }
+}
+
+proc ::tk::dialog::file::EntFocusOut {w} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+
+ $data(ent) selection clear
+}
+
+
+# Gets called when user presses Return in the "File name" entry.
+#
+proc ::tk::dialog::file::ActivateEnt {w} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+
+ set text [$data(ent) get]
+ if {$data(-multiple)} {
+ foreach t $text {
+ VerifyFileName $w $t
+ }
+ } else {
+ VerifyFileName $w $text
+ }
+}
+
+# Verification procedure
+#
+proc ::tk::dialog::file::VerifyFileName {w filename} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+
+ set list [ResolveFile $data(selectPath) $filename $data(-defaultextension)]
+ foreach {flag path file} $list {
+ break
+ }
+
+ switch -- $flag {
+ OK {
+ if {$file eq ""} {
+ # user has entered an existing (sub)directory
+ set data(selectPath) $path
+ $data(ent) delete 0 end
+ } else {
+ SetPathSilently $w $path
+ if {$data(-multiple)} {
+ lappend data(selectFile) $file
+ } else {
+ set data(selectFile) $file
+ }
+ Done $w
+ }
+ }
+ PATTERN {
+ set data(selectPath) $path
+ set data(filter) $file
+ }
+ FILE {
+ if {$data(type) eq "open"} {
+ tk_messageBox -icon warning -type ok -parent $w \
+ -message [mc "File \"%1\$s\" does not exist." \
+ [file join $path $file]]
+ $data(ent) selection range 0 end
+ $data(ent) icursor end
+ } else {
+ SetPathSilently $w $path
+ if {$data(-multiple)} {
+ lappend data(selectFile) $file
+ } else {
+ set data(selectFile) $file
+ }
+ Done $w
+ }
+ }
+ PATH {
+ tk_messageBox -icon warning -type ok -parent $w \
+ -message [mc "Directory \"%1\$s\" does not exist." $path]
+ $data(ent) selection range 0 end
+ $data(ent) icursor end
+ }
+ CHDIR {
+ tk_messageBox -type ok -parent $w -icon warning -message \
+ [mc "Cannot change to the directory\
+ \"%1\$s\".\nPermission denied." $path]
+ $data(ent) selection range 0 end
+ $data(ent) icursor end
+ }
+ ERROR {
+ tk_messageBox -type ok -parent $w -icon warning -message \
+ [mc "Invalid file name \"%1\$s\"." $path]
+ $data(ent) selection range 0 end
+ $data(ent) icursor end
+ }
+ }
+}
+
+# Gets called when user presses the Alt-s or Alt-o keys.
+#
+proc ::tk::dialog::file::InvokeBtn {w key} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+
+ if {[$data(okBtn) cget -text] eq $key} {
+ $data(okBtn) invoke
+ }
+}
+
+# Gets called when user presses the "parent directory" button
+#
+proc ::tk::dialog::file::UpDirCmd {w} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+
+ if {$data(selectPath) ne "/"} {
+ set data(selectPath) [file dirname $data(selectPath)]
+ }
+}
+
+# Join a file name to a path name. The "file join" command will break if the
+# filename begins with ~
+#
+proc ::tk::dialog::file::JoinFile {path file} {
+ if {[string match {~*} $file] && [file exists $path/$file]} {
+ return [file join $path ./$file]
+ } else {
+ return [file join $path $file]
+ }
+}
+
+# Gets called when user presses the "OK" button
+#
+proc ::tk::dialog::file::OkCmd {w} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+
+ set filenames {}
+ foreach item [$data(icons) selection get] {
+ lappend filenames [$data(icons) get $item]
+ }
+
+ if {
+ ([llength $filenames] && !$data(-multiple)) ||
+ ($data(-multiple) && ([llength $filenames] == 1))
+ } then {
+ set filename [lindex $filenames 0]
+ set file [JoinFile $data(selectPath) $filename]
+ if {[file isdirectory $file]} {
+ ListInvoke $w [list $filename]
+ return
+ }
+ }
+
+ ActivateEnt $w
+}
+
+# Gets called when user presses the "Cancel" button
+#
+proc ::tk::dialog::file::CancelCmd {w} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+ variable ::tk::Priv
+
+ bind $data(okBtn) <Destroy> {}
+ set Priv(selectFilePath) ""
+}
+
+# Gets called when user destroys the dialog directly [Bug 987169]
+#
+proc ::tk::dialog::file::Destroyed {w} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+ variable ::tk::Priv
+
+ set Priv(selectFilePath) ""
+}
+
+# Gets called when user browses the IconList widget (dragging mouse, arrow
+# keys, etc)
+#
+proc ::tk::dialog::file::ListBrowse {w} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+
+ set text {}
+ foreach item [$data(icons) selection get] {
+ lappend text [$data(icons) get $item]
+ }
+ if {[llength $text] == 0} {
+ return
+ }
+ if {$data(-multiple)} {
+ set newtext {}
+ foreach file $text {
+ set fullfile [JoinFile $data(selectPath) $file]
+ if { ![file isdirectory $fullfile] } {
+ lappend newtext $file
+ }
+ }
+ set text $newtext
+ set isDir 0
+ } else {
+ set text [lindex $text 0]
+ set file [JoinFile $data(selectPath) $text]
+ set isDir [file isdirectory $file]
+ }
+ if {!$isDir} {
+ $data(ent) delete 0 end
+ $data(ent) insert 0 $text
+
+ if {[winfo class $w] eq "TkFDialog"} {
+ if {$data(type) eq "open"} {
+ ::tk::SetAmpText $data(okBtn) [mc "&Open"]
+ } else {
+ ::tk::SetAmpText $data(okBtn) [mc "&Save"]
+ }
+ }
+ } elseif {[winfo class $w] eq "TkFDialog"} {
+ ::tk::SetAmpText $data(okBtn) [mc "&Open"]
+ }
+}
+
+# Gets called when user invokes the IconList widget (double-click, Return key,
+# etc)
+#
+proc ::tk::dialog::file::ListInvoke {w filenames} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+
+ if {[llength $filenames] == 0} {
+ return
+ }
+
+ set file [JoinFile $data(selectPath) [lindex $filenames 0]]
+
+ set class [winfo class $w]
+ if {$class eq "TkChooseDir" || [file isdirectory $file]} {
+ set appPWD [pwd]
+ if {[catch {cd $file}]} {
+ tk_messageBox -type ok -parent $w -icon warning -message \
+ [mc "Cannot change to the directory \"%1\$s\".\nPermission denied." $file]
+ } else {
+ cd $appPWD
+ set data(selectPath) $file
+ }
+ } else {
+ if {$data(-multiple)} {
+ set data(selectFile) $filenames
+ } else {
+ set data(selectFile) $file
+ }
+ Done $w
+ }
+}
+
+# ::tk::dialog::file::Done --
+#
+# Gets called when user has input a valid filename. Pops up a dialog
+# box to confirm selection when necessary. Sets the
+# tk::Priv(selectFilePath) variable, which will break the "vwait" loop
+# in ::tk::dialog::file:: and return the selected filename to the script
+# that calls tk_getOpenFile or tk_getSaveFile
+#
+proc ::tk::dialog::file::Done {w {selectFilePath ""}} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+ variable ::tk::Priv
+
+ if {$selectFilePath eq ""} {
+ if {$data(-multiple)} {
+ set selectFilePath {}
+ foreach f $data(selectFile) {
+ lappend selectFilePath [JoinFile $data(selectPath) $f]
+ }
+ } else {
+ set selectFilePath [JoinFile $data(selectPath) $data(selectFile)]
+ }
+
+ set Priv(selectFile) $data(selectFile)
+ set Priv(selectPath) $data(selectPath)
+
+ if {($data(type) eq "save") && $data(-confirmoverwrite) && [file exists $selectFilePath]} {
+ set reply [tk_messageBox -icon warning -type yesno -parent $w \
+ -message [mc "File \"%1\$s\" already exists.\nDo you want\
+ to overwrite it?" $selectFilePath]]
+ if {$reply eq "no"} {
+ return
+ }
+ }
+ if {
+ [info exists data(-typevariable)] && $data(-typevariable) ne ""
+ && [info exists data(-filetypes)] && [llength $data(-filetypes)]
+ && [info exists data(filterType)] && $data(filterType) ne ""
+ } then {
+ upvar #0 $data(-typevariable) typeVariable
+ set typeVariable [lindex $data(origfiletypes) \
+ [lsearch -exact $data(-filetypes) $data(filterType)] 0]
+
+ }
+ }
+ bind $data(okBtn) <Destroy> {}
+ set Priv(selectFilePath) $selectFilePath
+}
+
+# ::tk::dialog::file::GlobFiltered --
+#
+# Gets called to do globbing, returning the results and filtering them
+# according to the current filter (and removing the entries for '.' and
+# '..' which are never shown). Deals with evil cases such as where the
+# user is supplying a filter which is an invalid list or where it has an
+# unbalanced brace. The resulting list will be dictionary sorted.
+#
+# Arguments:
+# dir Which directory to search
+# type List of filetypes to look for ('d' or 'f b c l p s')
+# overrideFilter Whether to ignore the filter for this search.
+#
+# NB: Assumes that the caller has mapped the state variable to 'data'.
+#
+proc ::tk::dialog::file::GlobFiltered {dir type {overrideFilter 0}} {
+ variable showHiddenVar
+ upvar 1 data(filter) filter
+
+ if {$filter eq "*" || $overrideFilter} {
+ set patterns [list *]
+ if {$showHiddenVar} {
+ lappend patterns .*
+ }
+ } elseif {[string is list $filter]} {
+ set patterns $filter
+ } else {
+ # Invalid list; assume we can use non-whitespace sequences as words
+ set patterns [regexp -inline -all {\S+} $filter]
+ }
+
+ set opts [list -tails -directory $dir -type $type -nocomplain]
+
+ set result {}
+ catch {
+ # We have a catch because we might have a really bad pattern (e.g.,
+ # with an unbalanced brace); even [glob -nocomplain] doesn't like it.
+ # Using a catch ensures that it just means we match nothing instead of
+ # throwing a nasty error at the user...
+ foreach f [glob {*}$opts -- {*}$patterns] {
+ if {$f eq "." || $f eq ".."} {
+ continue
+ }
+ # See ticket [1641721], $f might be a link pointing to a dir
+ if {$type != "d" && [file isdir [file join $dir $f]]} {
+ continue
+ }
+ lappend result $f
+ }
+ }
+ return [lsort -dictionary -unique $result]
+}
+
+proc ::tk::dialog::file::CompleteEnt {w} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+ set f [$data(ent) get]
+ if {$data(-multiple)} {
+ if {![string is list $f] || [llength $f] != 1} {
+ return -code break
+ }
+ set f [lindex $f 0]
+ }
+
+ # Get list of matching filenames and dirnames
+ set files [if {[winfo class $w] eq "TkFDialog"} {
+ GlobFiltered $data(selectPath) {f b c l p s}
+ }]
+ set dirs2 {}
+ foreach d [GlobFiltered $data(selectPath) d] {lappend dirs2 $d/}
+
+ set targets [concat \
+ [lsearch -glob -all -inline $files $f*] \
+ [lsearch -glob -all -inline $dirs2 $f*]]
+
+ if {[llength $targets] == 1} {
+ # We have a winner!
+ set f [lindex $targets 0]
+ } elseif {$f in $targets || [llength $targets] == 0} {
+ if {[string length $f] > 0} {
+ bell
+ }
+ return
+ } elseif {[llength $targets] > 1} {
+ # Multiple possibles
+ if {[string length $f] == 0} {
+ return
+ }
+ set t0 [lindex $targets 0]
+ for {set len [string length $t0]} {$len>0} {} {
+ set allmatch 1
+ foreach s $targets {
+ if {![string equal -length $len $s $t0]} {
+ set allmatch 0
+ break
+ }
+ }
+ incr len -1
+ if {$allmatch} break
+ }
+ set f [string range $t0 0 $len]
+ }
+
+ if {$data(-multiple)} {
+ set f [list $f]
+ }
+ $data(ent) delete 0 end
+ $data(ent) insert 0 $f
+ return -code break
+}
diff --git a/tk8.6/library/ttk/altTheme.tcl b/tk8.6/library/ttk/altTheme.tcl
new file mode 100644
index 0000000..80ef415
--- /dev/null
+++ b/tk8.6/library/ttk/altTheme.tcl
@@ -0,0 +1,109 @@
+#
+# Ttk widget set: Alternate theme
+#
+
+namespace eval ttk::theme::alt {
+
+ variable colors
+ array set colors {
+ -frame "#d9d9d9"
+ -window "#ffffff"
+ -darker "#c3c3c3"
+ -border "#414141"
+ -activebg "#ececec"
+ -disabledfg "#a3a3a3"
+ -selectbg "#4a6984"
+ -selectfg "#ffffff"
+ -altindicator "#aaaaaa"
+ }
+
+ ttk::style theme settings alt {
+
+ ttk::style configure "." \
+ -background $colors(-frame) \
+ -foreground black \
+ -troughcolor $colors(-darker) \
+ -bordercolor $colors(-border) \
+ -selectbackground $colors(-selectbg) \
+ -selectforeground $colors(-selectfg) \
+ -font TkDefaultFont \
+ ;
+
+ ttk::style map "." -background \
+ [list disabled $colors(-frame) active $colors(-activebg)] ;
+ ttk::style map "." -foreground [list disabled $colors(-disabledfg)] ;
+ ttk::style map "." -embossed [list disabled 1] ;
+
+ ttk::style configure TButton \
+ -anchor center -width -11 -padding "1 1" \
+ -relief raised -shiftrelief 1 \
+ -highlightthickness 1 -highlightcolor $colors(-frame)
+
+ ttk::style map TButton -relief {
+ {pressed !disabled} sunken
+ {active !disabled} raised
+ } -highlightcolor {alternate black}
+
+ ttk::style configure TCheckbutton -indicatorcolor "#ffffff" -padding 2
+ ttk::style configure TRadiobutton -indicatorcolor "#ffffff" -padding 2
+ ttk::style map TCheckbutton -indicatorcolor \
+ [list pressed $colors(-frame) \
+ alternate $colors(-altindicator) \
+ disabled $colors(-frame)]
+ ttk::style map TRadiobutton -indicatorcolor \
+ [list pressed $colors(-frame) \
+ alternate $colors(-altindicator) \
+ disabled $colors(-frame)]
+
+ ttk::style configure TMenubutton \
+ -width -11 -padding "3 3" -relief raised
+
+ ttk::style configure TEntry -padding 1
+ ttk::style map TEntry -fieldbackground \
+ [list readonly $colors(-frame) disabled $colors(-frame)]
+ ttk::style configure TCombobox -padding 1
+ ttk::style map TCombobox -fieldbackground \
+ [list readonly $colors(-frame) disabled $colors(-frame)] \
+ -arrowcolor [list disabled $colors(-disabledfg)]
+ ttk::style configure ComboboxPopdownFrame \
+ -relief solid -borderwidth 1
+
+ ttk::style configure TSpinbox -arrowsize 10 -padding {2 0 10 0}
+ ttk::style map TSpinbox -fieldbackground \
+ [list readonly $colors(-frame) disabled $colors(-frame)] \
+ -arrowcolor [list disabled $colors(-disabledfg)]
+
+ ttk::style configure Toolbutton -relief flat -padding 2
+ ttk::style map Toolbutton -relief \
+ {disabled flat selected sunken pressed sunken active raised}
+ ttk::style map Toolbutton -background \
+ [list pressed $colors(-darker) active $colors(-activebg)]
+
+ ttk::style configure TScrollbar -relief raised
+
+ ttk::style configure TLabelframe -relief groove -borderwidth 2
+
+ ttk::style configure TNotebook -tabmargins {2 2 1 0}
+ ttk::style configure TNotebook.Tab \
+ -padding {4 2} -background $colors(-darker)
+ ttk::style map TNotebook.Tab \
+ -background [list selected $colors(-frame)] \
+ -expand [list selected {2 2 1 0}] \
+ ;
+
+ # Treeview:
+ ttk::style configure Heading -font TkHeadingFont -relief raised
+ ttk::style configure Treeview -background $colors(-window)
+ ttk::style map Treeview \
+ -background [list disabled $colors(-frame)\
+ selected $colors(-selectbg)] \
+ -foreground [list disabled $colors(-disabledfg) \
+ selected $colors(-selectfg)]
+
+ ttk::style configure TScale \
+ -groovewidth 4 -troughrelief sunken \
+ -sliderwidth raised -borderwidth 2
+ ttk::style configure TProgressbar \
+ -background $colors(-selectbg) -borderwidth 0
+ }
+}
diff --git a/tk8.6/library/ttk/aquaTheme.tcl b/tk8.6/library/ttk/aquaTheme.tcl
new file mode 100644
index 0000000..92689d8
--- /dev/null
+++ b/tk8.6/library/ttk/aquaTheme.tcl
@@ -0,0 +1,119 @@
+#
+# Aqua theme (OSX native look and feel)
+#
+
+namespace eval ttk::theme::aqua {
+ ttk::style theme settings aqua {
+
+ ttk::style configure . \
+ -font TkDefaultFont \
+ -background systemWindowBackgroundColor \
+ -foreground systemLabelColor \
+ -selectbackground systemHighlight \
+ -selectforeground systemLabelColor \
+ -selectborderwidth 0 \
+ -insertwidth 1
+
+ ttk::style map . \
+ -foreground {
+ disabled systemDisabledControlTextColor
+ background systemLabelColor} \
+ -selectbackground {
+ background systemSelectedTextBackgroundColor
+ !focus systemSelectedTextBackgroundColor} \
+ -selectforeground {
+ background systemSelectedTextColor
+ !focus systemSelectedTextColor}
+
+ # Button
+ ttk::style configure TButton -anchor center -width -6\
+ -foreground systemControlTextColor
+ ttk::style configure TMenubutton -anchor center -padding {2 0 0 2}
+ ttk::style configure Toolbutton -anchor center
+
+ # Entry
+ ttk::style configure TEntry \
+ -foreground systemTextColor \
+ -background systemTextBackgroundColor \
+
+ # Workaround for #1100117:
+ # Actually, on Aqua we probably shouldn't stipple images in
+ # disabled buttons even if it did work...
+ ttk::style configure . -stipple {}
+
+ # Notebook
+ ttk::style configure TNotebook -tabmargins {10 0} -tabposition n
+ ttk::style configure TNotebook -padding {18 8 18 17}
+ ttk::style configure TNotebook.Tab -padding {12 3 12 2}
+ ttk::style configure TNotebook.Tab -foreground systemControlTextColor
+ ttk::style map TNotebook.Tab \
+ -foreground {
+ background systemControlTextColor
+ disabled systemDisabledControlTextColor
+ selected systemSelectedTabTextColor}
+
+ # Combobox:
+ ttk::style configure TCombobox \
+ -foreground systemTextColor \
+ -background systemTransparent \
+ -selectforeground systemSelectedTextColor \
+ -selectbackground systemSelectedTextBackgroundColor
+ ttk::style map TCombobox \
+ -foreground {
+ disabled systemDisabledControlTextColor
+ } \
+ -selectforeground {
+ !active systemTextColor
+ } \
+ -selectbackground {
+ !active systemTextBackgroundColor
+ !focus systemTextBackgroundColor
+ focus systemSelectedTextBackgroundColor
+ }
+
+ # Spinbox
+ ttk::style configure TSpinbox \
+ -foreground systemTextColor \
+ -background systemTextBackgroundColor \
+ -selectforeground systemSelectedTextColor \
+ -selectbackground systemSelectedTextBackgroundColor
+ ttk::style map TSpinbox \
+ -foreground {
+ disabled systemDisabledControlTextColor
+ } \
+ -selectforeground {
+ !active systemTextColor
+ } \
+ -selectbackground {
+ !active systemTextBackgroundColor
+ !focus systemTextBackgroundColor
+ focus systemSelectedTextBackgroundColor
+ }
+
+ # Treeview:
+ ttk::style configure Heading \
+ -font TkHeadingFont \
+ -foreground systemTextColor \
+ -background systemWindowBackgroundColor
+ ttk::style configure Treeview -rowheight 18 \
+ -background systemTextBackgroundColor \
+ -foreground systemTextColor \
+ -fieldbackground systemTextBackgroundColor
+ ttk::style map Treeview \
+ -background {
+ selected systemSelectedTextBackgroundColor
+ }
+
+ # Enable animation for ttk::progressbar widget:
+ ttk::style configure TProgressbar -period 100 -maxphase 255
+
+ # For Aqua, labelframe labels should appear outside the border,
+ # with a 14 pixel inset and 4 pixels spacing between border and label
+ # (ref: Apple Human Interface Guidelines / Controls / Grouping Controls)
+ #
+ ttk::style configure TLabelframe \
+ -labeloutside true -labelmargins {14 0 14 4}
+
+ # TODO: panedwindow sashes should be 9 pixels (HIG:Controls:Split Views)
+ }
+}
diff --git a/tk8.6/library/ttk/button.tcl b/tk8.6/library/ttk/button.tcl
new file mode 100644
index 0000000..9f2cec7
--- /dev/null
+++ b/tk8.6/library/ttk/button.tcl
@@ -0,0 +1,83 @@
+#
+# Bindings for Buttons, Checkbuttons, and Radiobuttons.
+#
+# Notes: <Button1-Leave>, <Button1-Enter> only control the "pressed"
+# state; widgets remain "active" if the pointer is dragged out.
+# This doesn't seem to be conventional, but it's a nice way
+# to provide extra feedback while the grab is active.
+# (If the button is released off the widget, the grab deactivates and
+# we get a <Leave> event then, which turns off the "active" state)
+#
+# Normally, <ButtonRelease> and <ButtonN-Enter/Leave> events are
+# delivered to the widget which received the initial <ButtonPress>
+# event. However, Tk [grab]s (#1223103) and menu interactions
+# (#1222605) can interfere with this. To guard against spurious
+# <Button1-Enter> events, the <Button1-Enter> binding only sets
+# the pressed state if the button is currently active.
+#
+
+namespace eval ttk::button {}
+
+bind TButton <Enter> { %W instate !disabled {%W state active} }
+bind TButton <Leave> { %W state !active }
+bind TButton <Key-space> { ttk::button::activate %W }
+bind TButton <<Invoke>> { ttk::button::activate %W }
+
+bind TButton <ButtonPress-1> \
+ { %W instate !disabled { ttk::clickToFocus %W; %W state pressed } }
+bind TButton <ButtonRelease-1> \
+ { %W instate pressed { %W state !pressed; %W instate !disabled { %W invoke } } }
+bind TButton <Button1-Leave> \
+ { %W state !pressed }
+bind TButton <Button1-Enter> \
+ { %W instate {active !disabled} { %W state pressed } }
+
+# Checkbuttons and Radiobuttons have the same bindings as Buttons:
+#
+ttk::copyBindings TButton TCheckbutton
+ttk::copyBindings TButton TRadiobutton
+
+# ...plus a few more:
+
+bind TRadiobutton <KeyPress-Up> { ttk::button::RadioTraverse %W -1 }
+bind TRadiobutton <KeyPress-Down> { ttk::button::RadioTraverse %W +1 }
+
+# bind TCheckbutton <KeyPress-plus> { %W select }
+# bind TCheckbutton <KeyPress-minus> { %W deselect }
+
+# activate --
+# Simulate a button press: temporarily set the state to 'pressed',
+# then invoke the button.
+#
+proc ttk::button::activate {w} {
+ $w instate disabled { return }
+ set oldState [$w state pressed]
+ update idletasks; after 100 ;# block event loop to avoid reentrancy
+ $w state $oldState
+ $w invoke
+}
+
+# RadioTraverse -- up/down keyboard traversal for radiobutton groups.
+# Set focus to previous/next radiobutton in a group.
+# A radiobutton group consists of all the radiobuttons with
+# the same parent and -variable; this is a pretty good heuristic
+# that works most of the time.
+#
+proc ttk::button::RadioTraverse {w dir} {
+ set group [list]
+ foreach sibling [winfo children [winfo parent $w]] {
+ if { [winfo class $sibling] eq "TRadiobutton"
+ && [$sibling cget -variable] eq [$w cget -variable]
+ && ![$sibling instate disabled]
+ } {
+ lappend group $sibling
+ }
+ }
+
+ if {![llength $group]} { # Shouldn't happen, but can.
+ return
+ }
+
+ set pos [expr {([lsearch -exact $group $w] + $dir) % [llength $group]}]
+ tk::TabToWindow [lindex $group $pos]
+}
diff --git a/tk8.6/library/ttk/clamTheme.tcl b/tk8.6/library/ttk/clamTheme.tcl
new file mode 100644
index 0000000..6935fc7
--- /dev/null
+++ b/tk8.6/library/ttk/clamTheme.tcl
@@ -0,0 +1,147 @@
+#
+# "Clam" theme.
+#
+# Inspired by the XFCE family of Gnome themes.
+#
+
+namespace eval ttk::theme::clam {
+ variable colors
+ array set colors {
+ -disabledfg "#999999"
+ -frame "#dcdad5"
+ -window "#ffffff"
+ -dark "#cfcdc8"
+ -darker "#bab5ab"
+ -darkest "#9e9a91"
+ -lighter "#eeebe7"
+ -lightest "#ffffff"
+ -selectbg "#4a6984"
+ -selectfg "#ffffff"
+ -altindicator "#5895bc"
+ -disabledaltindicator "#a0a0a0"
+ }
+
+ ttk::style theme settings clam {
+
+ ttk::style configure "." \
+ -background $colors(-frame) \
+ -foreground black \
+ -bordercolor $colors(-darkest) \
+ -darkcolor $colors(-dark) \
+ -lightcolor $colors(-lighter) \
+ -troughcolor $colors(-darker) \
+ -selectbackground $colors(-selectbg) \
+ -selectforeground $colors(-selectfg) \
+ -selectborderwidth 0 \
+ -font TkDefaultFont \
+ ;
+
+ ttk::style map "." \
+ -background [list disabled $colors(-frame) \
+ active $colors(-lighter)] \
+ -foreground [list disabled $colors(-disabledfg)] \
+ -selectbackground [list !focus $colors(-darkest)] \
+ -selectforeground [list !focus white] \
+ ;
+ # -selectbackground [list !focus "#847d73"]
+
+ ttk::style configure TButton \
+ -anchor center -width -11 -padding 5 -relief raised
+ ttk::style map TButton \
+ -background [list \
+ disabled $colors(-frame) \
+ pressed $colors(-darker) \
+ active $colors(-lighter)] \
+ -lightcolor [list pressed $colors(-darker)] \
+ -darkcolor [list pressed $colors(-darker)] \
+ -bordercolor [list alternate "#000000"] \
+ ;
+
+ ttk::style configure Toolbutton \
+ -anchor center -padding 2 -relief flat
+ ttk::style map Toolbutton \
+ -relief [list \
+ disabled flat \
+ selected sunken \
+ pressed sunken \
+ active raised] \
+ -background [list \
+ disabled $colors(-frame) \
+ pressed $colors(-darker) \
+ active $colors(-lighter)] \
+ -lightcolor [list pressed $colors(-darker)] \
+ -darkcolor [list pressed $colors(-darker)] \
+ ;
+
+ ttk::style configure TCheckbutton \
+ -indicatorbackground "#ffffff" \
+ -indicatormargin {1 1 4 1} \
+ -padding 2 ;
+ ttk::style configure TRadiobutton \
+ -indicatorbackground "#ffffff" \
+ -indicatormargin {1 1 4 1} \
+ -padding 2 ;
+ ttk::style map TCheckbutton -indicatorbackground \
+ [list pressed $colors(-frame) \
+ {!disabled alternate} $colors(-altindicator) \
+ {disabled alternate} $colors(-disabledaltindicator) \
+ disabled $colors(-frame)]
+ ttk::style map TRadiobutton -indicatorbackground \
+ [list pressed $colors(-frame) \
+ {!disabled alternate} $colors(-altindicator) \
+ {disabled alternate} $colors(-disabledaltindicator) \
+ disabled $colors(-frame)]
+
+ ttk::style configure TMenubutton \
+ -width -11 -padding 5 -relief raised
+
+ ttk::style configure TEntry -padding 1 -insertwidth 1
+ ttk::style map TEntry \
+ -background [list readonly $colors(-frame)] \
+ -bordercolor [list focus $colors(-selectbg)] \
+ -lightcolor [list focus "#6f9dc6"] \
+ -darkcolor [list focus "#6f9dc6"] \
+ ;
+
+ ttk::style configure TCombobox -padding 1 -insertwidth 1
+ ttk::style map TCombobox \
+ -background [list active $colors(-lighter) \
+ pressed $colors(-lighter)] \
+ -fieldbackground [list {readonly focus} $colors(-selectbg) \
+ readonly $colors(-frame)] \
+ -foreground [list {readonly focus} $colors(-selectfg)] \
+ -arrowcolor [list disabled $colors(-disabledfg)]
+ ttk::style configure ComboboxPopdownFrame \
+ -relief solid -borderwidth 1
+
+ ttk::style configure TSpinbox -arrowsize 10 -padding {2 0 10 0}
+ ttk::style map TSpinbox \
+ -background [list readonly $colors(-frame)] \
+ -arrowcolor [list disabled $colors(-disabledfg)]
+
+ ttk::style configure TNotebook.Tab -padding {6 2 6 2}
+ ttk::style map TNotebook.Tab \
+ -padding [list selected {6 4 6 2}] \
+ -background [list selected $colors(-frame) {} $colors(-darker)] \
+ -lightcolor [list selected $colors(-lighter) {} $colors(-dark)] \
+ ;
+
+ # Treeview:
+ ttk::style configure Heading \
+ -font TkHeadingFont -relief raised -padding {3}
+ ttk::style configure Treeview -background $colors(-window)
+ ttk::style map Treeview \
+ -background [list disabled $colors(-frame)\
+ selected $colors(-selectbg)] \
+ -foreground [list disabled $colors(-disabledfg) \
+ selected $colors(-selectfg)]
+
+ ttk::style configure TLabelframe \
+ -labeloutside true -labelmargins {0 0 0 4} \
+ -borderwidth 2 -relief raised
+
+ ttk::style configure TProgressbar -background $colors(-frame)
+
+ ttk::style configure Sash -sashthickness 6 -gripcount 10
+ }
+}
diff --git a/tk8.6/library/ttk/classicTheme.tcl b/tk8.6/library/ttk/classicTheme.tcl
new file mode 100644
index 0000000..f237fba
--- /dev/null
+++ b/tk8.6/library/ttk/classicTheme.tcl
@@ -0,0 +1,115 @@
+#
+# "classic" Tk theme.
+#
+# Implements Tk's traditional Motif-like look and feel.
+#
+
+namespace eval ttk::theme::classic {
+
+ variable colors; array set colors {
+ -frame "#d9d9d9"
+ -window "#ffffff"
+ -activebg "#ececec"
+ -troughbg "#c3c3c3"
+ -selectbg "#c3c3c3"
+ -selectfg "#000000"
+ -disabledfg "#a3a3a3"
+ -indicator "#b03060"
+ -altindicator "#b05e5e"
+ }
+
+ ttk::style theme settings classic {
+ ttk::style configure "." \
+ -font TkDefaultFont \
+ -background $colors(-frame) \
+ -foreground black \
+ -selectbackground $colors(-selectbg) \
+ -selectforeground $colors(-selectfg) \
+ -troughcolor $colors(-troughbg) \
+ -indicatorcolor $colors(-frame) \
+ -highlightcolor $colors(-frame) \
+ -highlightthickness 1 \
+ -selectborderwidth 1 \
+ -insertwidth 2 \
+ ;
+
+ # To match pre-Xft X11 appearance, use:
+ # ttk::style configure . -font {Helvetica 12 bold}
+
+ ttk::style map "." -background \
+ [list disabled $colors(-frame) active $colors(-activebg)]
+ ttk::style map "." -foreground \
+ [list disabled $colors(-disabledfg)]
+
+ ttk::style map "." -highlightcolor [list focus black]
+
+ ttk::style configure TButton \
+ -anchor center -padding "3m 1m" -relief raised -shiftrelief 1
+ ttk::style map TButton -relief [list {!disabled pressed} sunken]
+
+ ttk::style configure TCheckbutton -indicatorrelief raised
+ ttk::style map TCheckbutton \
+ -indicatorcolor [list \
+ pressed $colors(-frame) \
+ alternate $colors(-altindicator) \
+ selected $colors(-indicator)] \
+ -indicatorrelief {alternate raised selected sunken pressed sunken} \
+ ;
+
+ ttk::style configure TRadiobutton -indicatorrelief raised
+ ttk::style map TRadiobutton \
+ -indicatorcolor [list \
+ pressed $colors(-frame) \
+ alternate $colors(-altindicator) \
+ selected $colors(-indicator)] \
+ -indicatorrelief {alternate raised selected sunken pressed sunken} \
+ ;
+
+ ttk::style configure TMenubutton -relief raised -padding "3m 1m"
+
+ ttk::style configure TEntry -relief sunken -padding 1 -font TkTextFont
+ ttk::style map TEntry -fieldbackground \
+ [list readonly $colors(-frame) disabled $colors(-frame)]
+ ttk::style configure TCombobox -padding 1
+ ttk::style map TCombobox -fieldbackground \
+ [list readonly $colors(-frame) disabled $colors(-frame)]
+ ttk::style configure ComboboxPopdownFrame \
+ -relief solid -borderwidth 1
+
+ ttk::style configure TSpinbox -arrowsize 10 -padding {2 0 10 0}
+ ttk::style map TSpinbox -fieldbackground \
+ [list readonly $colors(-frame) disabled $colors(-frame)]
+
+ ttk::style configure TLabelframe -borderwidth 2 -relief groove
+
+ ttk::style configure TScrollbar -relief raised
+ ttk::style map TScrollbar -relief {{pressed !disabled} sunken}
+
+ ttk::style configure TScale -sliderrelief raised
+ ttk::style map TScale -sliderrelief {{pressed !disabled} sunken}
+
+ ttk::style configure TProgressbar -background SteelBlue
+ ttk::style configure TNotebook.Tab \
+ -padding {3m 1m} \
+ -background $colors(-troughbg)
+ ttk::style map TNotebook.Tab -background [list selected $colors(-frame)]
+
+ # Treeview:
+ ttk::style configure Heading -font TkHeadingFont -relief raised
+ ttk::style configure Treeview -background $colors(-window)
+ ttk::style map Treeview \
+ -background [list disabled $colors(-frame)\
+ selected $colors(-selectbg)] \
+ -foreground [list disabled $colors(-disabledfg) \
+ selected $colors(-selectfg)]
+
+ #
+ # Toolbar buttons:
+ #
+ ttk::style configure Toolbutton -padding 2 -relief flat -shiftrelief 2
+ ttk::style map Toolbutton -relief \
+ {disabled flat selected sunken pressed sunken active raised}
+ ttk::style map Toolbutton -background \
+ [list pressed $colors(-troughbg) active $colors(-activebg)]
+ }
+}
diff --git a/tk8.6/library/ttk/combobox.tcl b/tk8.6/library/ttk/combobox.tcl
new file mode 100644
index 0000000..1355a04
--- /dev/null
+++ b/tk8.6/library/ttk/combobox.tcl
@@ -0,0 +1,443 @@
+#
+# Combobox bindings.
+#
+# <<NOTE-WM-TRANSIENT>>:
+#
+# Need to set [wm transient] just before mapping the popdown
+# instead of when it's created, in case a containing frame
+# has been reparented [#1818441].
+#
+# On Windows: setting [wm transient] prevents the parent
+# toplevel from becoming inactive when the popdown is posted
+# (Tk 8.4.8+)
+#
+# On X11: WM_TRANSIENT_FOR on override-redirect windows
+# may be used by compositing managers and by EWMH-aware
+# window managers (even though the older ICCCM spec says
+# it's meaningless).
+#
+# On OSX: [wm transient] does utterly the wrong thing.
+# Instead, we use [MacWindowStyle "help" "noActivates hideOnSuspend"].
+# The "noActivates" attribute prevents the parent toplevel
+# from deactivating when the popdown is posted, and is also
+# necessary for "help" windows to receive mouse events.
+# "hideOnSuspend" makes the popdown disappear (resp. reappear)
+# when the parent toplevel is deactivated (resp. reactivated).
+# (see [#1814778]). Also set [wm resizable 0 0], to prevent
+# TkAqua from shrinking the scrollbar to make room for a grow box
+# that isn't there.
+#
+# In order to work around other platform quirks in TkAqua,
+# [grab] and [focus] are set in <Map> bindings instead of
+# immediately after deiconifying the window.
+#
+
+namespace eval ttk::combobox {
+ variable Values ;# Values($cb) is -listvariable of listbox widget
+ variable State
+ set State(entryPress) 0
+}
+
+### Combobox bindings.
+#
+# Duplicate the Entry bindings, override if needed:
+#
+
+ttk::copyBindings TEntry TCombobox
+
+bind TCombobox <KeyPress-Down> { ttk::combobox::Post %W }
+bind TCombobox <KeyPress-Escape> { ttk::combobox::Unpost %W }
+
+bind TCombobox <ButtonPress-1> { ttk::combobox::Press "" %W %x %y }
+bind TCombobox <Shift-ButtonPress-1> { ttk::combobox::Press "s" %W %x %y }
+bind TCombobox <Double-ButtonPress-1> { ttk::combobox::Press "2" %W %x %y }
+bind TCombobox <Triple-ButtonPress-1> { ttk::combobox::Press "3" %W %x %y }
+bind TCombobox <B1-Motion> { ttk::combobox::Drag %W %x }
+bind TCombobox <Motion> { ttk::combobox::Motion %W %x %y }
+
+ttk::bindMouseWheel TCombobox [list ttk::combobox::Scroll %W]
+
+bind TCombobox <<TraverseIn>> { ttk::combobox::TraverseIn %W }
+
+### Combobox listbox bindings.
+#
+bind ComboboxListbox <ButtonRelease-1> { ttk::combobox::LBSelected %W }
+bind ComboboxListbox <KeyPress-Return> { ttk::combobox::LBSelected %W }
+bind ComboboxListbox <KeyPress-Escape> { ttk::combobox::LBCancel %W }
+bind ComboboxListbox <KeyPress-Tab> { ttk::combobox::LBTab %W next }
+bind ComboboxListbox <<PrevWindow>> { ttk::combobox::LBTab %W prev }
+bind ComboboxListbox <Destroy> { ttk::combobox::LBCleanup %W }
+bind ComboboxListbox <Motion> { ttk::combobox::LBHover %W %x %y }
+bind ComboboxListbox <Map> { focus -force %W }
+
+switch -- [tk windowingsystem] {
+ win32 {
+ # Dismiss listbox when user switches to a different application.
+ # NB: *only* do this on Windows (see #1814778)
+ bind ComboboxListbox <FocusOut> { ttk::combobox::LBCancel %W }
+ }
+}
+
+### Combobox popdown window bindings.
+#
+bind ComboboxPopdown <Map> { ttk::combobox::MapPopdown %W }
+bind ComboboxPopdown <Unmap> { ttk::combobox::UnmapPopdown %W }
+bind ComboboxPopdown <ButtonPress> \
+ { ttk::combobox::Unpost [winfo parent %W] }
+
+### Option database settings.
+#
+
+option add *TCombobox*Listbox.font TkTextFont widgetDefault
+option add *TCombobox*Listbox.relief flat widgetDefault
+option add *TCombobox*Listbox.highlightThickness 0 widgetDefault
+
+## Platform-specific settings.
+#
+switch -- [tk windowingsystem] {
+ x11 {
+ option add *TCombobox*Listbox.background white widgetDefault
+ }
+ aqua {
+ option add *TCombobox*Listbox.borderWidth 0 widgetDefault
+ }
+}
+
+### Binding procedures.
+#
+
+## Press $mode $x $y -- ButtonPress binding for comboboxes.
+# Either post/unpost the listbox, or perform Entry widget binding,
+# depending on widget state and location of button press.
+#
+proc ttk::combobox::Press {mode w x y} {
+ variable State
+
+ $w instate disabled { return }
+
+ set State(entryPress) [expr {
+ [$w instate !readonly]
+ && [string match *textarea [$w identify element $x $y]]
+ }]
+
+ focus $w
+ if {$State(entryPress)} {
+ switch -- $mode {
+ s { ttk::entry::Shift-Press $w $x ; # Shift }
+ 2 { ttk::entry::Select $w $x word ; # Double click}
+ 3 { ttk::entry::Select $w $x line ; # Triple click }
+ "" -
+ default { ttk::entry::Press $w $x }
+ }
+ } else {
+ Post $w
+ }
+}
+
+## Drag -- B1-Motion binding for comboboxes.
+# If the initial ButtonPress event was handled by Entry binding,
+# perform Entry widget drag binding; otherwise nothing.
+#
+proc ttk::combobox::Drag {w x} {
+ variable State
+ if {$State(entryPress)} {
+ ttk::entry::Drag $w $x
+ }
+}
+
+## Motion --
+# Set cursor.
+#
+proc ttk::combobox::Motion {w x y} {
+ if { [$w identify $x $y] eq "textarea"
+ && [$w instate {!readonly !disabled}]
+ } {
+ ttk::setCursor $w text
+ } else {
+ ttk::setCursor $w ""
+ }
+}
+
+## TraverseIn -- receive focus due to keyboard navigation
+# For editable comboboxes, set the selection and insert cursor.
+#
+proc ttk::combobox::TraverseIn {w} {
+ $w instate {!readonly !disabled} {
+ $w selection range 0 end
+ $w icursor end
+ }
+}
+
+## SelectEntry $cb $index --
+# Set the combobox selection in response to a user action.
+#
+proc ttk::combobox::SelectEntry {cb index} {
+ $cb current $index
+ $cb selection range 0 end
+ $cb icursor end
+ event generate $cb <<ComboboxSelected>> -when mark
+}
+
+## Scroll -- Mousewheel binding
+#
+proc ttk::combobox::Scroll {cb dir} {
+ $cb instate disabled { return }
+ set max [llength [$cb cget -values]]
+ set current [$cb current]
+ incr current $dir
+ if {$max != 0 && $current == $current % $max} {
+ SelectEntry $cb $current
+ }
+}
+
+## LBSelected $lb -- Activation binding for listbox
+# Set the combobox value to the currently-selected listbox value
+# and unpost the listbox.
+#
+proc ttk::combobox::LBSelected {lb} {
+ set cb [LBMaster $lb]
+ LBSelect $lb
+ Unpost $cb
+ focus $cb
+}
+
+## LBCancel --
+# Unpost the listbox.
+#
+proc ttk::combobox::LBCancel {lb} {
+ Unpost [LBMaster $lb]
+}
+
+## LBTab -- Tab key binding for combobox listbox.
+# Set the selection, and navigate to next/prev widget.
+#
+proc ttk::combobox::LBTab {lb dir} {
+ set cb [LBMaster $lb]
+ switch -- $dir {
+ next { set newFocus [tk_focusNext $cb] }
+ prev { set newFocus [tk_focusPrev $cb] }
+ }
+
+ if {$newFocus ne ""} {
+ LBSelect $lb
+ Unpost $cb
+ # The [grab release] call in [Unpost] queues events that later
+ # re-set the focus (@@@ NOTE: this might not be true anymore).
+ # Set new focus later:
+ after 0 [list ttk::traverseTo $newFocus]
+ }
+}
+
+## LBHover -- <Motion> binding for combobox listbox.
+# Follow selection on mouseover.
+#
+proc ttk::combobox::LBHover {w x y} {
+ $w selection clear 0 end
+ $w activate @$x,$y
+ $w selection set @$x,$y
+}
+
+## MapPopdown -- <Map> binding for ComboboxPopdown
+#
+proc ttk::combobox::MapPopdown {w} {
+ [winfo parent $w] state pressed
+ ttk::globalGrab $w
+}
+
+## UnmapPopdown -- <Unmap> binding for ComboboxPopdown
+#
+proc ttk::combobox::UnmapPopdown {w} {
+ [winfo parent $w] state !pressed
+ ttk::releaseGrab $w
+}
+
+## PopdownWindow --
+# Returns the popdown widget associated with a combobox,
+# creating it if necessary.
+#
+proc ttk::combobox::PopdownWindow {cb} {
+ if {![winfo exists $cb.popdown]} {
+ set poplevel [PopdownToplevel $cb.popdown]
+ set popdown [ttk::frame $poplevel.f -style ComboboxPopdownFrame]
+
+ ttk::scrollbar $popdown.sb \
+ -orient vertical -command [list $popdown.l yview]
+ listbox $popdown.l \
+ -listvariable ttk::combobox::Values($cb) \
+ -yscrollcommand [list $popdown.sb set] \
+ -exportselection false \
+ -selectmode browse \
+ -activestyle none \
+ ;
+
+ bindtags $popdown.l \
+ [list $popdown.l ComboboxListbox Listbox $popdown all]
+
+ grid $popdown.l -row 0 -column 0 -padx {1 0} -pady 1 -sticky nsew
+ grid $popdown.sb -row 0 -column 1 -padx {0 1} -pady 1 -sticky ns
+ grid columnconfigure $popdown 0 -weight 1
+ grid rowconfigure $popdown 0 -weight 1
+
+ grid $popdown -sticky news -padx 0 -pady 0
+ grid rowconfigure $poplevel 0 -weight 1
+ grid columnconfigure $poplevel 0 -weight 1
+ }
+ return $cb.popdown
+}
+
+## PopdownToplevel -- Create toplevel window for the combobox popdown
+#
+# See also <<NOTE-WM-TRANSIENT>>
+#
+proc ttk::combobox::PopdownToplevel {w} {
+ toplevel $w -class ComboboxPopdown
+ wm withdraw $w
+ switch -- [tk windowingsystem] {
+ default -
+ x11 {
+ $w configure -relief flat -borderwidth 0
+ wm attributes $w -type combo
+ wm overrideredirect $w true
+ }
+ win32 {
+ $w configure -relief flat -borderwidth 0
+ wm overrideredirect $w true
+ wm attributes $w -topmost 1
+ }
+ aqua {
+ $w configure -relief solid -borderwidth 0
+ tk::unsupported::MacWindowStyle style $w \
+ help {noActivates hideOnSuspend}
+ wm resizable $w 0 0
+ }
+ }
+ return $w
+}
+
+## ConfigureListbox --
+# Set listbox values, selection, height, and scrollbar visibility
+# from current combobox values.
+#
+proc ttk::combobox::ConfigureListbox {cb} {
+ variable Values
+
+ set popdown [PopdownWindow $cb].f
+ set values [$cb cget -values]
+ set current [$cb current]
+ if {$current < 0} {
+ set current 0 ;# no current entry, highlight first one
+ }
+ set Values($cb) $values
+ $popdown.l selection clear 0 end
+ $popdown.l selection set $current
+ $popdown.l activate $current
+ $popdown.l see $current
+ set height [llength $values]
+ if {$height > [$cb cget -height]} {
+ set height [$cb cget -height]
+ grid $popdown.sb
+ grid configure $popdown.l -padx {1 0}
+ } else {
+ grid remove $popdown.sb
+ grid configure $popdown.l -padx 1
+ }
+ $popdown.l configure -height $height
+}
+
+## PlacePopdown --
+# Set popdown window geometry.
+#
+# @@@TODO: factor with menubutton::PostPosition
+#
+proc ttk::combobox::PlacePopdown {cb popdown} {
+ set x [winfo rootx $cb]
+ set y [winfo rooty $cb]
+ set w [winfo width $cb]
+ set h [winfo height $cb]
+ set style [$cb cget -style]
+ set postoffset [ttk::style lookup $style -postoffset {} {0 0 0 0}]
+ foreach var {x y w h} delta $postoffset {
+ incr $var $delta
+ }
+
+ set H [winfo reqheight $popdown]
+ if {$y + $h + $H > [winfo screenheight $popdown]} {
+ set Y [expr {$y - $H}]
+ } else {
+ set Y [expr {$y + $h}]
+ }
+ wm geometry $popdown ${w}x${H}+${x}+${Y}
+}
+
+## Post $cb --
+# Pop down the associated listbox.
+#
+proc ttk::combobox::Post {cb} {
+ # Don't do anything if disabled:
+ #
+ $cb instate disabled { return }
+
+ # ASSERT: ![$cb instate pressed]
+
+ # Run -postcommand callback:
+ #
+ uplevel #0 [$cb cget -postcommand]
+
+ set popdown [PopdownWindow $cb]
+ ConfigureListbox $cb
+ update idletasks ;# needed for geometry propagation.
+ PlacePopdown $cb $popdown
+ # See <<NOTE-WM-TRANSIENT>>
+ switch -- [tk windowingsystem] {
+ x11 - win32 { wm transient $popdown [winfo toplevel $cb] }
+ }
+
+ # Post the listbox:
+ #
+ wm attribute $popdown -topmost 1
+ wm deiconify $popdown
+ raise $popdown
+}
+
+## Unpost $cb --
+# Unpost the listbox.
+#
+proc ttk::combobox::Unpost {cb} {
+ if {[winfo exists $cb.popdown]} {
+ wm withdraw $cb.popdown
+ }
+ grab release $cb.popdown ;# in case of stuck or unexpected grab [#1239190]
+}
+
+## LBMaster $lb --
+# Return the combobox main widget that owns the listbox.
+#
+proc ttk::combobox::LBMaster {lb} {
+ winfo parent [winfo parent [winfo parent $lb]]
+}
+
+## LBSelect $lb --
+# Transfer listbox selection to combobox value.
+#
+proc ttk::combobox::LBSelect {lb} {
+ set cb [LBMaster $lb]
+ set selection [$lb curselection]
+ if {[llength $selection] == 1} {
+ SelectEntry $cb [lindex $selection 0]
+ }
+}
+
+## LBCleanup $lb --
+# <Destroy> binding for combobox listboxes.
+# Cleans up by unsetting the linked textvariable.
+#
+# Note: we can't just use { unset [%W cget -listvariable] }
+# because the widget command is already gone when this binding fires).
+# [winfo parent] still works, fortunately.
+#
+proc ttk::combobox::LBCleanup {lb} {
+ variable Values
+ unset Values([LBMaster $lb])
+}
+
+#*EOF*
diff --git a/tk8.6/library/ttk/cursors.tcl b/tk8.6/library/ttk/cursors.tcl
new file mode 100644
index 0000000..75f7791
--- /dev/null
+++ b/tk8.6/library/ttk/cursors.tcl
@@ -0,0 +1,186 @@
+#
+# Map symbolic cursor names to platform-appropriate cursors.
+#
+# The following cursors are defined:
+#
+# standard -- default cursor for most controls
+# "" -- inherit cursor from parent window
+# none -- no cursor
+#
+# text -- editable widgets (entry, text)
+# link -- hyperlinks within text
+# crosshair -- graphic selection, fine control
+# busy -- operation in progress
+# forbidden -- action not allowed
+#
+# hresize -- horizontal resizing
+# vresize -- vertical resizing
+#
+# Also resize cursors for each of the compass points,
+# {nw,n,ne,w,e,sw,s,se}resize.
+#
+# Platform notes:
+#
+# Windows doesn't distinguish resizing at the 8 compass points,
+# only horizontal, vertical, and the two diagonals.
+#
+# OSX doesn't have resize cursors for nw, ne, sw, or se corners.
+# We use the Tk-defined X11 fallbacks for these.
+#
+# X11 doesn't have a "forbidden" cursor (usually a slashed circle);
+# "pirate" seems to be the conventional cursor for this purpose.
+#
+# Windows has an IDC_HELP cursor, but it's not available from Tk.
+#
+# Tk does not support "none" on Windows.
+#
+
+namespace eval ttk {
+
+ variable Cursors
+
+ # Use X11 cursor names as defaults, since Tk supplies these
+ # on all platforms.
+ #
+ array set Cursors {
+ "" ""
+ none none
+
+ standard left_ptr
+ text xterm
+ link hand2
+ crosshair crosshair
+ busy watch
+ forbidden pirate
+
+ hresize sb_h_double_arrow
+ vresize sb_v_double_arrow
+
+ nresize top_side
+ sresize bottom_side
+ wresize left_side
+ eresize right_side
+ nwresize top_left_corner
+ neresize top_right_corner
+ swresize bottom_left_corner
+ seresize bottom_right_corner
+ move fleur
+
+ }
+
+ # Platform-specific overrides for Windows and OSX.
+ #
+ switch [tk windowingsystem] {
+ "win32" {
+ array set Cursors {
+ none {}
+
+ standard arrow
+ text ibeam
+ link hand2
+ crosshair crosshair
+ busy wait
+ forbidden no
+
+ vresize size_ns
+ nresize size_ns
+ sresize size_ns
+
+ wresize size_we
+ eresize size_we
+ hresize size_we
+
+ nwresize size_nw_se
+ swresize size_ne_sw
+
+ neresize size_ne_sw
+ seresize size_nw_se
+ }
+ }
+
+ "aqua" {
+ if {[package vsatisfies [package provide Tk] 8.5]} {
+ # appeared 2007-04-23, Tk 8.5a6
+ array set Cursors {
+ standard arrow
+ text ibeam
+ link pointinghand
+ crosshair crosshair
+ busy watch
+ forbidden notallowed
+
+ hresize resizeleftright
+ vresize resizeupdown
+ nresize resizeup
+ sresize resizedown
+ wresize resizeleft
+ eresize resizeright
+ }
+ }
+ }
+ }
+}
+
+## ttk::cursor $cursor --
+# Return platform-specific cursor for specified symbolic cursor.
+#
+proc ttk::cursor {name} {
+ variable Cursors
+ return $Cursors($name)
+}
+
+## ttk::setCursor $w $cursor --
+# Set the cursor for specified window.
+#
+# [ttk::setCursor] should be used in <Motion> bindings
+# instead of directly calling [$w configure -cursor ...],
+# as the latter always incurs a server round-trip and
+# can lead to high CPU load (see [#1184746])
+#
+
+proc ttk::setCursor {w name} {
+ variable Cursors
+ if {[$w cget -cursor] ne $Cursors($name)} {
+ $w configure -cursor $Cursors($name)
+ }
+}
+
+## Interactive test harness:
+#
+proc ttk::CursorSampler {f} {
+ ttk::frame $f
+
+ set r 0
+ foreach row {
+ {nwresize nresize neresize}
+ { wresize move eresize}
+ {swresize sresize seresize}
+ {text link crosshair}
+ {hresize vresize ""}
+ {busy forbidden ""}
+ {none standard ""}
+ } {
+ set c 0
+ foreach cursor $row {
+ set w $f.${r}${c}
+ ttk::label $w -text $cursor -cursor [ttk::cursor $cursor] \
+ -relief solid -borderwidth 1 -padding 3
+ grid $w -row $r -column $c -sticky nswe
+ grid columnconfigure $f $c -uniform cols -weight 1
+ incr c
+ }
+ grid rowconfigure $f $r -uniform rows -weight 1
+ incr r
+ }
+
+ return $f
+}
+
+if {[info exists argv0] && $argv0 eq [info script]} {
+ wm title . "[array size ::ttk::Cursors] cursors"
+ pack [ttk::CursorSampler .f] -expand true -fill both
+ bind . <KeyPress-Escape> [list destroy .]
+ focus .f
+}
+
+#*EOF*
diff --git a/tk8.6/library/ttk/defaults.tcl b/tk8.6/library/ttk/defaults.tcl
new file mode 100644
index 0000000..a15d1d9
--- /dev/null
+++ b/tk8.6/library/ttk/defaults.tcl
@@ -0,0 +1,143 @@
+#
+# Settings for default theme.
+#
+
+namespace eval ttk::theme::default {
+ variable colors
+ array set colors {
+ -frame "#d9d9d9"
+ -foreground "#000000"
+ -window "#ffffff"
+ -text "#000000"
+ -activebg "#ececec"
+ -selectbg "#4a6984"
+ -selectfg "#ffffff"
+ -darker "#c3c3c3"
+ -disabledfg "#a3a3a3"
+ -indicator "#4a6984"
+ -disabledindicator "#a3a3a3"
+ -altindicator "#9fbdd8"
+ -disabledaltindicator "#c0c0c0"
+ }
+
+ ttk::style theme settings default {
+
+ ttk::style configure "." \
+ -borderwidth 1 \
+ -background $colors(-frame) \
+ -foreground $colors(-foreground) \
+ -troughcolor $colors(-darker) \
+ -font TkDefaultFont \
+ -selectborderwidth 1 \
+ -selectbackground $colors(-selectbg) \
+ -selectforeground $colors(-selectfg) \
+ -insertwidth 1 \
+ -indicatordiameter 10 \
+ ;
+
+ ttk::style map "." -background \
+ [list disabled $colors(-frame) active $colors(-activebg)]
+ ttk::style map "." -foreground \
+ [list disabled $colors(-disabledfg)]
+
+ ttk::style configure TButton \
+ -anchor center -padding "3 3" -width -9 \
+ -relief raised -shiftrelief 1
+ ttk::style map TButton -relief [list {!disabled pressed} sunken]
+
+ ttk::style configure TCheckbutton \
+ -indicatorcolor "#ffffff" -indicatorrelief sunken -padding 1
+ ttk::style map TCheckbutton -indicatorcolor \
+ [list pressed $colors(-activebg) \
+ {!disabled alternate} $colors(-altindicator) \
+ {disabled alternate} $colors(-disabledaltindicator) \
+ {!disabled selected} $colors(-indicator) \
+ {disabled selected} $colors(-disabledindicator)]
+ ttk::style map TCheckbutton -indicatorrelief \
+ [list alternate raised]
+
+ ttk::style configure TRadiobutton \
+ -indicatorcolor "#ffffff" -indicatorrelief sunken -padding 1
+ ttk::style map TRadiobutton -indicatorcolor \
+ [list pressed $colors(-activebg) \
+ {!disabled alternate} $colors(-altindicator) \
+ {disabled alternate} $colors(-disabledaltindicator) \
+ {!disabled selected} $colors(-indicator) \
+ {disabled selected} $colors(-disabledindicator)]
+ ttk::style map TRadiobutton -indicatorrelief \
+ [list alternate raised]
+
+ ttk::style configure TMenubutton \
+ -relief raised -padding "10 3"
+
+ ttk::style configure TEntry \
+ -relief sunken -fieldbackground white -padding 1
+ ttk::style map TEntry -fieldbackground \
+ [list readonly $colors(-frame) disabled $colors(-frame)]
+
+ ttk::style configure TCombobox -arrowsize 12 -padding 1
+ ttk::style map TCombobox -fieldbackground \
+ [list readonly $colors(-frame) disabled $colors(-frame)] \
+ -arrowcolor [list disabled $colors(-disabledfg)]
+
+ ttk::style configure TSpinbox -arrowsize 10 -padding {2 0 10 0}
+ ttk::style map TSpinbox -fieldbackground \
+ [list readonly $colors(-frame) disabled $colors(-frame)] \
+ -arrowcolor [list disabled $colors(-disabledfg)]
+
+ ttk::style configure TLabelframe \
+ -relief groove -borderwidth 2
+
+ ttk::style configure TScrollbar \
+ -width 12 -arrowsize 12
+ ttk::style map TScrollbar \
+ -arrowcolor [list disabled $colors(-disabledfg)]
+
+ ttk::style configure TScale \
+ -sliderrelief raised
+ ttk::style configure TProgressbar \
+ -background $colors(-selectbg)
+
+ ttk::style configure TNotebook.Tab \
+ -padding {4 2} -background $colors(-darker)
+ ttk::style map TNotebook.Tab \
+ -background [list selected $colors(-frame)]
+
+ # Treeview.
+ #
+ ttk::style configure Heading -font TkHeadingFont -relief raised
+ ttk::style configure Treeview \
+ -background $colors(-window) \
+ -foreground $colors(-text) ;
+ ttk::style map Treeview \
+ -background [list disabled $colors(-frame)\
+ selected $colors(-selectbg)] \
+ -foreground [list disabled $colors(-disabledfg) \
+ selected $colors(-selectfg)]
+
+ # Combobox popdown frame
+ ttk::style layout ComboboxPopdownFrame {
+ ComboboxPopdownFrame.border -sticky nswe
+ }
+ ttk::style configure ComboboxPopdownFrame \
+ -borderwidth 1 -relief solid
+
+ #
+ # Toolbar buttons:
+ #
+ ttk::style layout Toolbutton {
+ Toolbutton.border -children {
+ Toolbutton.padding -children {
+ Toolbutton.label
+ }
+ }
+ }
+
+ ttk::style configure Toolbutton \
+ -padding 2 -relief flat
+ ttk::style map Toolbutton -relief \
+ [list disabled flat selected sunken pressed sunken active raised]
+ ttk::style map Toolbutton -background \
+ [list pressed $colors(-darker) active $colors(-activebg)]
+ }
+}
diff --git a/tk8.6/library/ttk/entry.tcl b/tk8.6/library/ttk/entry.tcl
new file mode 100644
index 0000000..383eebd
--- /dev/null
+++ b/tk8.6/library/ttk/entry.tcl
@@ -0,0 +1,613 @@
+#
+# DERIVED FROM: tk/library/entry.tcl r1.22
+#
+# Copyright (c) 1992-1994 The Regents of the University of California.
+# Copyright (c) 1994-1997 Sun Microsystems, Inc.
+# Copyright (c) 2004, Joe English
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+
+namespace eval ttk {
+ namespace eval entry {
+ variable State
+
+ set State(x) 0
+ set State(selectMode) none
+ set State(anchor) 0
+ set State(scanX) 0
+ set State(scanIndex) 0
+ set State(scanMoved) 0
+
+ # Button-2 scan speed is (scanNum/scanDen) characters
+ # per pixel of mouse movement.
+ # The standard Tk entry widget uses the equivalent of
+ # scanNum = 10, scanDen = average character width.
+ # I don't know why that was chosen.
+ #
+ set State(scanNum) 1
+ set State(scanDen) 1
+ set State(deadband) 3 ;# #pixels for mouse-moved deadband.
+ }
+}
+
+### Option database settings.
+#
+option add *TEntry.cursor [ttk::cursor text] widgetDefault
+
+### Bindings.
+#
+# Removed the following standard Tk bindings:
+#
+# <Control-Key-space>, <Control-Shift-Key-space>,
+# <Key-Select>, <Shift-Key-Select>:
+# Ttk entry widget doesn't use selection anchor.
+# <Key-Insert>:
+# Inserts PRIMARY selection (on non-Windows platforms).
+# This is inconsistent with typical platform bindings.
+# <Double-Shift-ButtonPress-1>, <Triple-Shift-ButtonPress-1>:
+# These don't do the right thing to start with.
+# <Meta-Key-b>, <Meta-Key-d>, <Meta-Key-f>,
+# <Meta-Key-BackSpace>, <Meta-Key-Delete>:
+# Judgment call. If <Meta> happens to be assigned to the Alt key,
+# these could conflict with application accelerators.
+# (Plus, who has a Meta key these days?)
+# <Control-Key-t>:
+# Another judgment call. If anyone misses this, let me know
+# and I'll put it back.
+#
+
+##Bindings to register with macOS Services API.
+bind T.Entry <Map> {
+ if {[tk windowingsystem] eq "aqua"} {
+ ::tk::RegisterServiceWidget %W
+ }
+}
+
+## Clipboard events:
+#
+bind TEntry <<Cut>> { ttk::entry::Cut %W }
+bind TEntry <<Copy>> { ttk::entry::Copy %W }
+bind TEntry <<Paste>> { ttk::entry::Paste %W }
+bind TEntry <<Clear>> { ttk::entry::Clear %W }
+
+## Button1 bindings:
+# Used for selection and navigation.
+#
+bind TEntry <ButtonPress-1> { ttk::entry::Press %W %x }
+bind TEntry <Shift-ButtonPress-1> { ttk::entry::Shift-Press %W %x }
+bind TEntry <Double-ButtonPress-1> { ttk::entry::Select %W %x word }
+bind TEntry <Triple-ButtonPress-1> { ttk::entry::Select %W %x line }
+bind TEntry <B1-Motion> { ttk::entry::Drag %W %x }
+
+bind TEntry <B1-Leave> { ttk::entry::DragOut %W %m }
+bind TEntry <B1-Enter> { ttk::entry::DragIn %W }
+bind TEntry <ButtonRelease-1> { ttk::entry::Release %W }
+
+bind TEntry <<ToggleSelection>> {
+ %W instate {!readonly !disabled} { %W icursor @%x ; focus %W }
+}
+
+## Button2 bindings:
+# Used for scanning and primary transfer.
+# Note: ButtonRelease-2 is mapped to <<PasteSelection>> in tk.tcl.
+#
+bind TEntry <ButtonPress-2> { ttk::entry::ScanMark %W %x }
+bind TEntry <B2-Motion> { ttk::entry::ScanDrag %W %x }
+bind TEntry <ButtonRelease-2> { ttk::entry::ScanRelease %W %x }
+bind TEntry <<PasteSelection>> { ttk::entry::ScanRelease %W %x }
+
+## Keyboard navigation bindings:
+#
+bind TEntry <<PrevChar>> { ttk::entry::Move %W prevchar }
+bind TEntry <<NextChar>> { ttk::entry::Move %W nextchar }
+bind TEntry <<PrevWord>> { ttk::entry::Move %W prevword }
+bind TEntry <<NextWord>> { ttk::entry::Move %W nextword }
+bind TEntry <<LineStart>> { ttk::entry::Move %W home }
+bind TEntry <<LineEnd>> { ttk::entry::Move %W end }
+
+bind TEntry <<SelectPrevChar>> { ttk::entry::Extend %W prevchar }
+bind TEntry <<SelectNextChar>> { ttk::entry::Extend %W nextchar }
+bind TEntry <<SelectPrevWord>> { ttk::entry::Extend %W prevword }
+bind TEntry <<SelectNextWord>> { ttk::entry::Extend %W nextword }
+bind TEntry <<SelectLineStart>> { ttk::entry::Extend %W home }
+bind TEntry <<SelectLineEnd>> { ttk::entry::Extend %W end }
+
+bind TEntry <<SelectAll>> { %W selection range 0 end }
+bind TEntry <<SelectNone>> { %W selection clear }
+
+bind TEntry <<TraverseIn>> { %W selection range 0 end; %W icursor end }
+
+## Edit bindings:
+#
+bind TEntry <KeyPress> { ttk::entry::Insert %W %A }
+bind TEntry <Key-Delete> { ttk::entry::Delete %W }
+bind TEntry <Key-BackSpace> { ttk::entry::Backspace %W }
+
+# Ignore all Alt, Meta, and Control keypresses unless explicitly bound.
+# Otherwise, the <KeyPress> class binding will fire and insert the character.
+# Ditto for Escape, Return, and Tab.
+#
+bind TEntry <Alt-KeyPress> {# nothing}
+bind TEntry <Meta-KeyPress> {# nothing}
+bind TEntry <Control-KeyPress> {# nothing}
+bind TEntry <Key-Escape> {# nothing}
+bind TEntry <Key-Return> {# nothing}
+bind TEntry <Key-KP_Enter> {# nothing}
+bind TEntry <Key-Tab> {# nothing}
+
+# Argh. Apparently on Windows, the NumLock modifier is interpreted
+# as a Command modifier.
+if {[tk windowingsystem] eq "aqua"} {
+ bind TEntry <Command-KeyPress> {# nothing}
+}
+# Tk-on-Cocoa generates characters for these two keys. [Bug 2971663]
+bind TEntry <<PrevLine>> {# nothing}
+bind TEntry <<NextLine>> {# nothing}
+
+## Additional emacs-like bindings:
+#
+bind TEntry <Control-Key-d> { ttk::entry::Delete %W }
+bind TEntry <Control-Key-h> { ttk::entry::Backspace %W }
+bind TEntry <Control-Key-k> { %W delete insert end }
+
+### Clipboard procedures.
+#
+
+## EntrySelection -- Return the selected text of the entry.
+# Raises an error if there is no selection.
+#
+proc ttk::entry::EntrySelection {w} {
+ set entryString [string range [$w get] [$w index sel.first] \
+ [expr {[$w index sel.last] - 1}]]
+ if {[$w cget -show] ne ""} {
+ return [string repeat [string index [$w cget -show] 0] \
+ [string length $entryString]]
+ }
+ return $entryString
+}
+
+## Paste -- Insert clipboard contents at current insert point.
+#
+proc ttk::entry::Paste {w} {
+ catch {
+ set clipboard [::tk::GetSelection $w CLIPBOARD]
+ PendingDelete $w
+ $w insert insert $clipboard
+ See $w insert
+ }
+}
+
+## Copy -- Copy selection to clipboard.
+#
+proc ttk::entry::Copy {w} {
+ if {![catch {EntrySelection $w} selection]} {
+ clipboard clear -displayof $w
+ clipboard append -displayof $w $selection
+ }
+}
+
+## Clear -- Delete the selection.
+#
+proc ttk::entry::Clear {w} {
+ catch { $w delete sel.first sel.last }
+}
+
+## Cut -- Copy selection to clipboard then delete it.
+#
+proc ttk::entry::Cut {w} {
+ Copy $w; Clear $w
+}
+
+### Navigation procedures.
+#
+
+## ClosestGap -- Find closest boundary between characters.
+# Returns the index of the character just after the boundary.
+#
+proc ttk::entry::ClosestGap {w x} {
+ set pos [$w index @$x]
+ set bbox [$w bbox $pos]
+ if {$x - [lindex $bbox 0] > [lindex $bbox 2]/2} {
+ incr pos
+ }
+ return $pos
+}
+
+## See $index -- Make sure that the character at $index is visible.
+#
+proc ttk::entry::See {w {index insert}} {
+ set c [$w index $index]
+ # @@@ OR: check [$w index left] / [$w index right]
+ if {$c < [$w index @0] || $c >= [$w index @[winfo width $w]]} {
+ $w xview $c
+ }
+}
+
+## NextWord -- Find the next word position.
+# Note: The "next word position" follows platform conventions:
+# either the next end-of-word position, or the start-of-word
+# position following the next end-of-word position.
+#
+set ::ttk::entry::State(startNext) \
+ [string equal [tk windowingsystem] "win32"]
+
+proc ttk::entry::NextWord {w start} {
+ variable State
+ set pos [tcl_endOfWord [$w get] [$w index $start]]
+ if {$pos >= 0 && $State(startNext)} {
+ set pos [tcl_startOfNextWord [$w get] $pos]
+ }
+ if {$pos < 0} {
+ return end
+ }
+ return $pos
+}
+
+## PrevWord -- Find the previous word position.
+#
+proc ttk::entry::PrevWord {w start} {
+ set pos [tcl_startOfPreviousWord [$w get] [$w index $start]]
+ if {$pos < 0} {
+ return 0
+ }
+ return $pos
+}
+
+## RelIndex -- Compute character/word/line-relative index.
+#
+proc ttk::entry::RelIndex {w where {index insert}} {
+ switch -- $where {
+ prevchar { expr {[$w index $index] - 1} }
+ nextchar { expr {[$w index $index] + 1} }
+ prevword { PrevWord $w $index }
+ nextword { NextWord $w $index }
+ home { return 0 }
+ end { $w index end }
+ default { error "Bad relative index $index" }
+ }
+}
+
+## Move -- Move insert cursor to relative location.
+# Also clears the selection, if any, and makes sure
+# that the insert cursor is visible.
+#
+proc ttk::entry::Move {w where} {
+ $w icursor [RelIndex $w $where]
+ $w selection clear
+ See $w insert
+}
+
+### Selection procedures.
+#
+
+## ExtendTo -- Extend the selection to the specified index.
+#
+# The other end of the selection (the anchor) is determined as follows:
+#
+# (1) if there is no selection, the anchor is the insert cursor;
+# (2) if the index is outside the selection, grow the selection;
+# (3) if the insert cursor is at one end of the selection, anchor the other end
+# (4) otherwise anchor the start of the selection
+#
+# The insert cursor is placed at the new end of the selection.
+#
+# Returns: selection anchor.
+#
+proc ttk::entry::ExtendTo {w index} {
+ set index [$w index $index]
+ set insert [$w index insert]
+
+ # Figure out selection anchor:
+ if {![$w selection present]} {
+ set anchor $insert
+ } else {
+ set selfirst [$w index sel.first]
+ set sellast [$w index sel.last]
+
+ if { ($index < $selfirst)
+ || ($insert == $selfirst && $index <= $sellast)
+ } {
+ set anchor $sellast
+ } else {
+ set anchor $selfirst
+ }
+ }
+
+ # Extend selection:
+ if {$anchor < $index} {
+ $w selection range $anchor $index
+ } else {
+ $w selection range $index $anchor
+ }
+
+ $w icursor $index
+ return $anchor
+}
+
+## Extend -- Extend the selection to a relative position, show insert cursor
+#
+proc ttk::entry::Extend {w where} {
+ ExtendTo $w [RelIndex $w $where]
+ See $w
+}
+
+### Button 1 binding procedures.
+#
+# Double-clicking followed by a drag enters "word-select" mode.
+# Triple-clicking enters "line-select" mode.
+#
+
+## Press -- ButtonPress-1 binding.
+# Set the insertion cursor, claim the input focus, set up for
+# future drag operations.
+#
+proc ttk::entry::Press {w x} {
+ variable State
+
+ $w icursor [ClosestGap $w $x]
+ $w selection clear
+ $w instate !disabled { focus $w }
+
+ # Set up for future drag, double-click, or triple-click.
+ set State(x) $x
+ set State(selectMode) char
+ set State(anchor) [$w index insert]
+}
+
+## Shift-Press -- Shift-ButtonPress-1 binding.
+# Extends the selection, sets anchor for future drag operations.
+#
+proc ttk::entry::Shift-Press {w x} {
+ variable State
+
+ focus $w
+ set anchor [ExtendTo $w @$x]
+
+ set State(x) $x
+ set State(selectMode) char
+ set State(anchor) $anchor
+}
+
+## Select $w $x $mode -- Binding for double- and triple- clicks.
+# Selects a word or line (according to mode),
+# and sets the selection mode for subsequent drag operations.
+#
+proc ttk::entry::Select {w x mode} {
+ variable State
+ set cur [ClosestGap $w $x]
+
+ switch -- $mode {
+ word { WordSelect $w $cur $cur }
+ line { LineSelect $w $cur $cur }
+ char { # no-op }
+ }
+
+ set State(anchor) $cur
+ set State(selectMode) $mode
+}
+
+## Drag -- Button1 motion binding.
+#
+proc ttk::entry::Drag {w x} {
+ variable State
+ set State(x) $x
+ DragTo $w $x
+}
+
+## DragTo $w $x -- Extend selection to $x based on current selection mode.
+#
+proc ttk::entry::DragTo {w x} {
+ variable State
+
+ set cur [ClosestGap $w $x]
+ switch $State(selectMode) {
+ char { CharSelect $w $State(anchor) $cur }
+ word { WordSelect $w $State(anchor) $cur }
+ line { LineSelect $w $State(anchor) $cur }
+ none { # no-op }
+ }
+}
+
+## <B1-Leave> binding:
+# Begin autoscroll.
+#
+proc ttk::entry::DragOut {w mode} {
+ variable State
+ if {$State(selectMode) ne "none" && $mode eq "NotifyNormal"} {
+ ttk::Repeatedly ttk::entry::AutoScroll $w
+ }
+}
+
+## <B1-Enter> binding
+# Suspend autoscroll.
+#
+proc ttk::entry::DragIn {w} {
+ ttk::CancelRepeat
+}
+
+## <ButtonRelease-1> binding
+#
+proc ttk::entry::Release {w} {
+ variable State
+ set State(selectMode) none
+ ttk::CancelRepeat ;# suspend autoscroll
+}
+
+## AutoScroll
+# Called repeatedly when the mouse is outside an entry window
+# with Button 1 down. Scroll the window left or right,
+# depending on where the mouse left the window, and extend
+# the selection according to the current selection mode.
+#
+# TODO: AutoScroll should repeat faster (50ms) than normal autorepeat.
+# TODO: Need a way for Repeat scripts to cancel themselves.
+#
+proc ttk::entry::AutoScroll {w} {
+ variable State
+ if {![winfo exists $w]} return
+ set x $State(x)
+ if {$x > [winfo width $w]} {
+ $w xview scroll 2 units
+ DragTo $w $x
+ } elseif {$x < 0} {
+ $w xview scroll -2 units
+ DragTo $w $x
+ }
+}
+
+## CharSelect -- select characters between index $from and $to
+#
+proc ttk::entry::CharSelect {w from to} {
+ if {$to <= $from} {
+ $w selection range $to $from
+ } else {
+ $w selection range $from $to
+ }
+ $w icursor $to
+}
+
+## WordSelect -- Select whole words between index $from and $to
+#
+proc ttk::entry::WordSelect {w from to} {
+ if {$to < $from} {
+ set first [WordBack [$w get] $to]
+ set last [WordForward [$w get] $from]
+ $w icursor $first
+ } else {
+ set first [WordBack [$w get] $from]
+ set last [WordForward [$w get] $to]
+ $w icursor $last
+ }
+ $w selection range $first $last
+}
+
+## WordBack, WordForward -- helper routines for WordSelect.
+#
+proc ttk::entry::WordBack {text index} {
+ if {[set pos [tcl_wordBreakBefore $text $index]] < 0} { return 0 }
+ return $pos
+}
+proc ttk::entry::WordForward {text index} {
+ if {[set pos [tcl_wordBreakAfter $text $index]] < 0} { return end }
+ return $pos
+}
+
+## LineSelect -- Select the entire line.
+#
+proc ttk::entry::LineSelect {w _ _} {
+ variable State
+ $w selection range 0 end
+ $w icursor end
+}
+
+### Button 2 binding procedures.
+#
+
+## ScanMark -- ButtonPress-2 binding.
+# Marks the start of a scan or primary transfer operation.
+#
+proc ttk::entry::ScanMark {w x} {
+ variable State
+ set State(scanX) $x
+ set State(scanIndex) [$w index @0]
+ set State(scanMoved) 0
+}
+
+## ScanDrag -- Button2 motion binding.
+#
+proc ttk::entry::ScanDrag {w x} {
+ variable State
+
+ set dx [expr {$State(scanX) - $x}]
+ if {abs($dx) > $State(deadband)} {
+ set State(scanMoved) 1
+ }
+ set left [expr {$State(scanIndex) + ($dx*$State(scanNum))/$State(scanDen)}]
+ $w xview $left
+
+ if {$left != [set newLeft [$w index @0]]} {
+ # We've scanned past one end of the entry;
+ # reset the mark so that the text will start dragging again
+ # as soon as the mouse reverses direction.
+ #
+ set State(scanX) $x
+ set State(scanIndex) $newLeft
+ }
+}
+
+## ScanRelease -- Button2 release binding.
+# Do a primary transfer if the mouse has not moved since the button press.
+#
+proc ttk::entry::ScanRelease {w x} {
+ variable State
+ if {!$State(scanMoved)} {
+ $w instate {!disabled !readonly} {
+ $w icursor [ClosestGap $w $x]
+ catch {$w insert insert [::tk::GetSelection $w PRIMARY]}
+ }
+ }
+}
+
+### Insertion and deletion procedures.
+#
+
+## PendingDelete -- Delete selection prior to insert.
+# If the entry currently has a selection, delete it and
+# set the insert position to where the selection was.
+# Returns: 1 if pending delete occurred, 0 if nothing was selected.
+#
+proc ttk::entry::PendingDelete {w} {
+ if {[$w selection present]} {
+ $w icursor sel.first
+ $w delete sel.first sel.last
+ return 1
+ }
+ return 0
+}
+
+## Insert -- Insert text into the entry widget.
+# If a selection is present, the new text replaces it.
+# Otherwise, the new text is inserted at the insert cursor.
+#
+proc ttk::entry::Insert {w s} {
+ if {$s eq ""} { return }
+ PendingDelete $w
+ $w insert insert $s
+ See $w insert
+}
+
+## Backspace -- Backspace over the character just before the insert cursor.
+# If there is a selection, delete that instead.
+# If the new insert position is offscreen to the left,
+# scroll to place the cursor at about the middle of the window.
+#
+proc ttk::entry::Backspace {w} {
+ if {[PendingDelete $w]} {
+ See $w
+ return
+ }
+ set x [expr {[$w index insert] - 1}]
+ if {$x < 0} { return }
+
+ $w delete $x
+
+ if {[$w index @0] >= [$w index insert]} {
+ set range [$w xview]
+ set left [lindex $range 0]
+ set right [lindex $range 1]
+ $w xview moveto [expr {$left - ($right - $left)/2.0}]
+ }
+}
+
+## Delete -- Delete the character after the insert cursor.
+# If there is a selection, delete that instead.
+#
+proc ttk::entry::Delete {w} {
+ if {![PendingDelete $w]} {
+ $w delete insert
+ }
+}
+
+#*EOF*
diff --git a/tk8.6/library/ttk/fonts.tcl b/tk8.6/library/ttk/fonts.tcl
new file mode 100644
index 0000000..a2781c6
--- /dev/null
+++ b/tk8.6/library/ttk/fonts.tcl
@@ -0,0 +1,157 @@
+#
+# Font specifications.
+#
+# This file, [source]d at initialization time, sets up the following
+# symbolic fonts based on the current platform:
+#
+# TkDefaultFont -- default for GUI items not otherwise specified
+# TkTextFont -- font for user text (entry, listbox, others)
+# TkFixedFont -- standard fixed width font
+# TkHeadingFont -- headings (column headings, etc)
+# TkCaptionFont -- dialog captions (primary text in alert dialogs, etc.)
+# TkTooltipFont -- font to use for tooltip windows
+# TkIconFont -- font to use for icon captions
+# TkMenuFont -- used to use for menu items
+#
+# In Tk 8.5, some of these fonts may be provided by the TIP#145 implementation
+# (On Windows and Mac OS X as of Oct 2007).
+#
+# +++ Platform notes:
+#
+# Windows:
+# The default system font changed from "MS Sans Serif" to "Tahoma"
+# in Windows XP/Windows 2000.
+#
+# MS documentation says to use "Tahoma 8" in Windows 2000/XP,
+# although many MS programs still use "MS Sans Serif 8"
+#
+# Should use SystemParametersInfo() instead.
+#
+# Mac OSX / Aqua:
+# Quoth the Apple HIG:
+# The _system font_ (Lucida Grande Regular 13 pt) is used for text
+# in menus, dialogs, and full-size controls.
+# [...] Use the _view font_ (Lucida Grande Regular 12pt) as the default
+# font of text in lists and tables.
+# [...] Use the _emphasized system font_ (Lucida Grande Bold 13 pt)
+# sparingly. It is used for the message text in alerts.
+# [...] The _small system font_ (Lucida Grande Regular 11 pt) [...]
+# is also the default font for column headings in lists, for help tags,
+# and for small controls.
+#
+# Note that the font for column headings (TkHeadingFont) is
+# _smaller_ than the default font.
+#
+# There does not appear to be any recommendations for fixed-width fonts.
+#
+# X11:
+# Need a way to tell if Xft is enabled or not.
+# For now, assume patch #971980 applied.
+#
+# "Classic" look used Helvetica bold for everything except
+# for entry widgets, which use Helvetica medium.
+# Most other toolkits use medium weight for all UI elements,
+# which is what we do now.
+#
+# Font size specified in pixels on X11, not points.
+# This is Theoretically Wrong, but in practice works better; using
+# points leads to huge inconsistencies across different servers.
+#
+
+namespace eval ttk {
+
+variable tip145 [catch {font create TkDefaultFont}]
+catch {font create TkTextFont}
+catch {font create TkHeadingFont}
+catch {font create TkCaptionFont}
+catch {font create TkTooltipFont}
+catch {font create TkFixedFont}
+catch {font create TkIconFont}
+catch {font create TkMenuFont}
+catch {font create TkSmallCaptionFont}
+
+if {!$tip145} {
+variable F ;# miscellaneous platform-specific font parameters
+switch -- [tk windowingsystem] {
+ win32 {
+ # In safe interps there is no osVersion element.
+ if {[info exists tcl_platform(osVersion)]} {
+ if {$tcl_platform(osVersion) >= 5.0} {
+ set F(family) "Tahoma"
+ } else {
+ set F(family) "MS Sans Serif"
+ }
+ } else {
+ if {[lsearch -exact [font families] Tahoma] != -1} {
+ set F(family) "Tahoma"
+ } else {
+ set F(family) "MS Sans Serif"
+ }
+ }
+ set F(size) 8
+
+ font configure TkDefaultFont -family $F(family) -size $F(size)
+ font configure TkTextFont -family $F(family) -size $F(size)
+ font configure TkHeadingFont -family $F(family) -size $F(size)
+ font configure TkCaptionFont -family $F(family) -size $F(size) \
+ -weight bold
+ font configure TkTooltipFont -family $F(family) -size $F(size)
+ font configure TkFixedFont -family Courier -size 10
+ font configure TkIconFont -family $F(family) -size $F(size)
+ font configure TkMenuFont -family $F(family) -size $F(size)
+ font configure TkSmallCaptionFont -family $F(family) -size $F(size)
+ }
+ aqua {
+ set F(family) "Lucida Grande"
+ set F(fixed) "Monaco"
+ set F(menusize) 14
+ set F(size) 13
+ set F(viewsize) 12
+ set F(smallsize) 11
+ set F(labelsize) 10
+ set F(fixedsize) 11
+
+ font configure TkDefaultFont -family $F(family) -size $F(size)
+ font configure TkTextFont -family $F(family) -size $F(size)
+ font configure TkHeadingFont -family $F(family) -size $F(smallsize)
+ font configure TkCaptionFont -family $F(family) -size $F(size) \
+ -weight bold
+ font configure TkTooltipFont -family $F(family) -size $F(smallsize)
+ font configure TkFixedFont -family $F(fixed) -size $F(fixedsize)
+ font configure TkIconFont -family $F(family) -size $F(size)
+ font configure TkMenuFont -family $F(family) -size $F(menusize)
+ font configure TkSmallCaptionFont -family $F(family) -size $F(labelsize)
+ }
+ default -
+ x11 {
+ if {![catch {tk::pkgconfig get fontsystem} F(fs)] && $F(fs) eq "xft"} {
+ set F(family) "sans-serif"
+ set F(fixed) "monospace"
+ } else {
+ set F(family) "Helvetica"
+ set F(fixed) "courier"
+ }
+ set F(size) -12
+ set F(ttsize) -10
+ set F(capsize) -14
+ set F(fixedsize) -12
+
+ font configure TkDefaultFont -family $F(family) -size $F(size)
+ font configure TkTextFont -family $F(family) -size $F(size)
+ font configure TkHeadingFont -family $F(family) -size $F(size) \
+ -weight bold
+ font configure TkCaptionFont -family $F(family) -size $F(capsize) \
+ -weight bold
+ font configure TkTooltipFont -family $F(family) -size $F(ttsize)
+ font configure TkFixedFont -family $F(fixed) -size $F(fixedsize)
+ font configure TkIconFont -family $F(family) -size $F(size)
+ font configure TkMenuFont -family $F(family) -size $F(size)
+ font configure TkSmallCaptionFont -family $F(family) -size $F(ttsize)
+ }
+}
+unset -nocomplain F
+}
+
+}
+
+#*EOF*
diff --git a/tk8.6/library/ttk/menubutton.tcl b/tk8.6/library/ttk/menubutton.tcl
new file mode 100644
index 0000000..43b3cd8
--- /dev/null
+++ b/tk8.6/library/ttk/menubutton.tcl
@@ -0,0 +1,243 @@
+#
+# Bindings for Menubuttons.
+#
+# Menubuttons have three interaction modes:
+#
+# Pulldown: Press menubutton, drag over menu, release to activate menu entry
+# Popdown: Click menubutton to post menu
+# Keyboard: <Key-space> or accelerator key to post menu
+#
+# (In addition, when menu system is active, "dropdown" -- menu posts
+# on mouse-over. Ttk menubuttons don't implement this).
+#
+# For keyboard and popdown mode, we hand off to tk_popup and let
+# the built-in Tk bindings handle the rest of the interaction.
+#
+# ON X11:
+#
+# Standard Tk menubuttons use a global grab on the menubutton.
+# This won't work for Ttk menubuttons in pulldown mode,
+# since we need to process the final <ButtonRelease> event,
+# and this might be delivered to the menu. So instead we
+# rely on the passive grab that occurs on <ButtonPress> events,
+# and transition to popdown mode when the mouse is released
+# or dragged outside the menubutton.
+#
+# ON WINDOWS:
+#
+# I'm not sure what the hell is going on here. [$menu post] apparently
+# sets up some kind of internal grab for native menus.
+# On this platform, just use [tk_popup] for all menu actions.
+#
+# ON MACOS:
+#
+# Same probably applies here.
+#
+
+namespace eval ttk {
+ namespace eval menubutton {
+ variable State
+ array set State {
+ pulldown 0
+ oldcursor {}
+ }
+ }
+}
+
+bind TMenubutton <Enter> { %W instate !disabled {%W state active } }
+bind TMenubutton <Leave> { %W state !active }
+bind TMenubutton <Key-space> { ttk::menubutton::Popdown %W }
+bind TMenubutton <<Invoke>> { ttk::menubutton::Popdown %W }
+
+if {[tk windowingsystem] eq "x11"} {
+ bind TMenubutton <ButtonPress-1> { ttk::menubutton::Pulldown %W }
+ bind TMenubutton <ButtonRelease-1> { ttk::menubutton::TransferGrab %W }
+ bind TMenubutton <B1-Leave> { ttk::menubutton::TransferGrab %W }
+} else {
+ bind TMenubutton <ButtonPress-1> \
+ { %W state pressed ; ttk::menubutton::Popdown %W }
+ bind TMenubutton <ButtonRelease-1> \
+ { if {[winfo exists %W]} { %W state !pressed } }
+}
+
+# PostPosition --
+# Returns x and y coordinates and a menu item index.
+# If the index is not an empty string the menu should
+# be posted so that the upper left corner of the indexed
+# menu item is located at the point (x, y). Otherwise
+# the top left corner of the menu itself should be located
+# at that point.
+#
+# TODO: adjust menu width to be at least as wide as the button
+# for -direction above, below.
+#
+
+if {[tk windowingsystem] eq "aqua"} {
+ proc ::ttk::menubutton::PostPosition {mb menu} {
+ set menuPad 5
+ set buttonPad 1
+ set bevelPad 4
+ set mh [winfo reqheight $menu]
+ set bh [expr {[winfo height $mb]} + $buttonPad]
+ set bbh [expr {[winfo height $mb]} + $bevelPad]
+ set mw [winfo reqwidth $menu]
+ set bw [winfo width $mb]
+ set dF [expr {[winfo width $mb] - [winfo reqwidth $menu] - $menuPad}]
+ set entry ""
+ set entry [::tk::MenuFindName $menu [$mb cget -text]]
+ if {$entry eq ""} {
+ set entry 0
+ }
+ set x [winfo rootx $mb]
+ set y [winfo rooty $mb]
+ switch [$mb cget -direction] {
+ above {
+ set entry ""
+ incr y [expr {-$mh + 2 * $menuPad}]
+ }
+ below {
+ set entry ""
+ incr y $bh
+ }
+ left {
+ incr y $menuPad
+ incr x -$mw
+ }
+ right {
+ incr y $menuPad
+ incr x $bw
+ }
+ default {
+ incr y $bbh
+ }
+ }
+ return [list $x $y $entry]
+ }
+} else {
+ proc ::ttk::menubutton::PostPosition {mb menu} {
+ set mh [expr {[winfo reqheight $menu]}]
+ set bh [expr {[winfo height $mb]}]
+ set mw [expr {[winfo reqwidth $menu]}]
+ set bw [expr {[winfo width $mb]}]
+ set dF [expr {[winfo width $mb] - [winfo reqwidth $menu]}]
+ if {[tk windowingsystem] eq "win32"} {
+ incr mh 6
+ incr mw 16
+ }
+ set entry {}
+ set entry [::tk::MenuFindName $menu [$mb cget -text]]
+ if {$entry eq {}} {
+ set entry 0
+ }
+ set x [winfo rootx $mb]
+ set y [winfo rooty $mb]
+ switch [$mb cget -direction] {
+ above {
+ set entry {}
+ incr y -$mh
+ # if we go offscreen to the top, show as 'below'
+ if {$y < [winfo vrooty $mb]} {
+ set y [expr {[winfo vrooty $mb] + [winfo rooty $mb]\
+ + [winfo reqheight $mb]}]
+ }
+ }
+ below {
+ set entry {}
+ incr y $bh
+ # if we go offscreen to the bottom, show as 'above'
+ if {($y + $mh) > ([winfo vrooty $mb] + [winfo vrootheight $mb])} {
+ set y [expr {[winfo vrooty $mb] + [winfo vrootheight $mb] \
+ + [winfo rooty $mb] - $mh}]
+ }
+ }
+ left {
+ incr x -$mw
+ }
+ right {
+ incr x $bw
+ }
+ default {
+ if {[$mb cget -style] eq ""} {
+ incr x [expr {([winfo width $mb] - \
+ [winfo reqwidth $menu])/ 2}]
+ } else {
+ incr y $bh
+ }
+ }
+ }
+ return [list $x $y $entry]
+ }
+}
+
+# Popdown --
+# Post the menu and set a grab on the menu.
+#
+proc ttk::menubutton::Popdown {mb} {
+ if {[$mb instate disabled] || [set menu [$mb cget -menu]] eq ""} {
+ return
+ }
+ foreach {x y entry} [PostPosition $mb $menu] { break }
+ tk_popup $menu $x $y $entry
+}
+
+# Pulldown (X11 only) --
+# Called when Button1 is pressed on a menubutton.
+# Posts the menu; a subsequent ButtonRelease
+# or Leave event will set a grab on the menu.
+#
+proc ttk::menubutton::Pulldown {mb} {
+ variable State
+ if {[$mb instate disabled] || [set menu [$mb cget -menu]] eq ""} {
+ return
+ }
+ set State(pulldown) 1
+ set State(oldcursor) [$mb cget -cursor]
+
+ $mb state pressed
+ $mb configure -cursor [$menu cget -cursor]
+ foreach {x y entry} [PostPosition $mb $menu] { break }
+ if {$entry ne {}} {
+ $menu post $x $y $entry
+ } else {
+ $menu post $x $y
+ }
+ tk_menuSetFocus $menu
+}
+
+# TransferGrab (X11 only) --
+# Switch from pulldown mode (menubutton has an implicit grab)
+# to popdown mode (menu has an explicit grab).
+#
+proc ttk::menubutton::TransferGrab {mb} {
+ variable State
+ if {$State(pulldown)} {
+ $mb configure -cursor $State(oldcursor)
+ $mb state {!pressed !active}
+ set State(pulldown) 0
+
+ set menu [$mb cget -menu]
+ foreach {x y entry} [PostPosition $mb $menu] { break }
+ tk_popup $menu [winfo rootx $menu] [winfo rooty $menu]
+ }
+}
+
+# FindMenuEntry --
+# Hack to support tk_optionMenus.
+# Returns the index of the menu entry with a matching -label,
+# -1 if not found.
+#
+proc ttk::menubutton::FindMenuEntry {menu s} {
+ set last [$menu index last]
+ if {$last eq "none"} {
+ return ""
+ }
+ for {set i 0} {$i <= $last} {incr i} {
+ if {![catch {$menu entrycget $i -label} label]
+ && ($label eq $s)} {
+ return $i
+ }
+ }
+ return ""
+}
+
+#*EOF*
diff --git a/tk8.6/library/ttk/notebook.tcl b/tk8.6/library/ttk/notebook.tcl
new file mode 100644
index 0000000..72b85e6
--- /dev/null
+++ b/tk8.6/library/ttk/notebook.tcl
@@ -0,0 +1,197 @@
+#
+# Bindings for TNotebook widget
+#
+
+namespace eval ttk::notebook {
+ variable TLNotebooks ;# See enableTraversal
+}
+
+bind TNotebook <ButtonPress-1> { ttk::notebook::Press %W %x %y }
+bind TNotebook <Key-Right> { ttk::notebook::CycleTab %W 1; break }
+bind TNotebook <Key-Left> { ttk::notebook::CycleTab %W -1; break }
+bind TNotebook <Control-Key-Tab> { ttk::notebook::CycleTab %W 1; break }
+bind TNotebook <Control-Shift-Key-Tab> { ttk::notebook::CycleTab %W -1; break }
+catch {
+bind TNotebook <Control-ISO_Left_Tab> { ttk::notebook::CycleTab %W -1; break }
+}
+bind TNotebook <Destroy> { ttk::notebook::Cleanup %W }
+
+# ActivateTab $nb $tab --
+# Select the specified tab and set focus.
+#
+# Desired behavior:
+# + take focus when reselecting the currently-selected tab;
+# + keep focus if the notebook already has it;
+# + otherwise set focus to the first traversable widget
+# in the newly-selected tab;
+# + do not leave the focus in a deselected tab.
+#
+proc ttk::notebook::ActivateTab {w tab} {
+ set oldtab [$w select]
+ $w select $tab
+ set newtab [$w select] ;# NOTE: might not be $tab, if $tab is disabled
+
+ if {[focus] eq $w} { return }
+ if {$newtab eq $oldtab} { focus $w ; return }
+
+ update idletasks ;# needed so focus logic sees correct mapped states
+ if {[set f [ttk::focusFirst $newtab]] ne ""} {
+ ttk::traverseTo $f
+ } else {
+ focus $w
+ }
+}
+
+# Press $nb $x $y --
+# ButtonPress-1 binding for notebook widgets.
+# Activate the tab under the mouse cursor, if any.
+#
+proc ttk::notebook::Press {w x y} {
+ set index [$w index @$x,$y]
+ if {$index ne ""} {
+ ActivateTab $w $index
+ }
+}
+
+# CycleTab --
+# Select the next/previous tab in the list.
+#
+proc ttk::notebook::CycleTab {w dir} {
+ if {[$w index end] != 0} {
+ set current [$w index current]
+ set select [expr {($current + $dir) % [$w index end]}]
+ while {[$w tab $select -state] != "normal" && ($select != $current)} {
+ set select [expr {($select + $dir) % [$w index end]}]
+ }
+ if {$select != $current} {
+ ActivateTab $w $select
+ }
+ }
+}
+
+# MnemonicTab $nb $key --
+# Scan all tabs in the specified notebook for one with the
+# specified mnemonic. If found, returns path name of tab;
+# otherwise returns ""
+#
+proc ttk::notebook::MnemonicTab {nb key} {
+ set key [string toupper $key]
+ foreach tab [$nb tabs] {
+ set label [$nb tab $tab -text]
+ set underline [$nb tab $tab -underline]
+ set mnemonic [string toupper [string index $label $underline]]
+ if {$mnemonic ne "" && $mnemonic eq $key} {
+ return $tab
+ }
+ }
+ return ""
+}
+
+# +++ Toplevel keyboard traversal.
+#
+
+# enableTraversal --
+# Enable keyboard traversal for a notebook widget
+# by adding bindings to the containing toplevel window.
+#
+# TLNotebooks($top) keeps track of the list of all traversal-enabled
+# notebooks contained in the toplevel
+#
+proc ttk::notebook::enableTraversal {nb} {
+ variable TLNotebooks
+
+ set top [winfo toplevel $nb]
+
+ if {![info exists TLNotebooks($top)]} {
+ # Augment $top bindings:
+ #
+ bind $top <Control-Key-Next> {+ttk::notebook::TLCycleTab %W 1}
+ bind $top <Control-Key-Prior> {+ttk::notebook::TLCycleTab %W -1}
+ bind $top <Control-Key-Tab> {+ttk::notebook::TLCycleTab %W 1}
+ bind $top <Control-Shift-Key-Tab> {+ttk::notebook::TLCycleTab %W -1}
+ catch {
+ bind $top <Control-Key-ISO_Left_Tab> {+ttk::notebook::TLCycleTab %W -1}
+ }
+ if {[tk windowingsystem] eq "aqua"} {
+ bind $top <Option-KeyPress> \
+ +[list ttk::notebook::MnemonicActivation $top %K]
+ } else {
+ bind $top <Alt-KeyPress> \
+ +[list ttk::notebook::MnemonicActivation $top %K]
+ }
+ bind $top <Destroy> {+ttk::notebook::TLCleanup %W}
+ }
+
+ lappend TLNotebooks($top) $nb
+}
+
+# TLCleanup -- <Destroy> binding for traversal-enabled toplevels
+#
+proc ttk::notebook::TLCleanup {w} {
+ variable TLNotebooks
+ if {$w eq [winfo toplevel $w]} {
+ unset -nocomplain -please TLNotebooks($w)
+ }
+}
+
+# Cleanup -- <Destroy> binding for notebooks
+#
+proc ttk::notebook::Cleanup {nb} {
+ variable TLNotebooks
+ set top [winfo toplevel $nb]
+ if {[info exists TLNotebooks($top)]} {
+ set index [lsearch -exact $TLNotebooks($top) $nb]
+ set TLNotebooks($top) [lreplace $TLNotebooks($top) $index $index]
+ }
+}
+
+# EnclosingNotebook $w --
+# Return the nearest traversal-enabled notebook widget
+# that contains $w.
+#
+# BUGS: this only works properly for tabs that are direct children
+# of the notebook widget. This routine should follow the
+# geometry manager hierarchy, not window ancestry, but that
+# information is not available in Tk.
+#
+proc ttk::notebook::EnclosingNotebook {w} {
+ variable TLNotebooks
+
+ set top [winfo toplevel $w]
+ if {![info exists TLNotebooks($top)]} { return }
+
+ while {$w ne $top && $w ne ""} {
+ if {[lsearch -exact $TLNotebooks($top) $w] >= 0} {
+ return $w
+ }
+ set w [winfo parent $w]
+ }
+ return ""
+}
+
+# TLCycleTab --
+# toplevel binding procedure for Control-Tab / Control-Shift-Tab
+# Select the next/previous tab in the nearest ancestor notebook.
+#
+proc ttk::notebook::TLCycleTab {w dir} {
+ set nb [EnclosingNotebook $w]
+ if {$nb ne ""} {
+ CycleTab $nb $dir
+ return -code break
+ }
+}
+
+# MnemonicActivation $nb $key --
+# Alt-KeyPress binding procedure for mnemonic activation.
+# Scan all notebooks in specified toplevel for a tab with the
+# the specified mnemonic. If found, activate it and return TCL_BREAK.
+#
+proc ttk::notebook::MnemonicActivation {top key} {
+ variable TLNotebooks
+ foreach nb $TLNotebooks($top) {
+ if {[set tab [MnemonicTab $nb $key]] ne ""} {
+ ActivateTab $nb [$nb index $tab]
+ return -code break
+ }
+ }
+}
diff --git a/tk8.6/library/ttk/panedwindow.tcl b/tk8.6/library/ttk/panedwindow.tcl
new file mode 100644
index 0000000..a2e073b
--- /dev/null
+++ b/tk8.6/library/ttk/panedwindow.tcl
@@ -0,0 +1,82 @@
+#
+# Bindings for ttk::panedwindow widget.
+#
+
+namespace eval ttk::panedwindow {
+ variable State
+ array set State {
+ pressed 0
+ pressX -
+ pressY -
+ sash -
+ sashPos -
+ }
+}
+
+## Bindings:
+#
+bind TPanedwindow <ButtonPress-1> { ttk::panedwindow::Press %W %x %y }
+bind TPanedwindow <B1-Motion> { ttk::panedwindow::Drag %W %x %y }
+bind TPanedwindow <ButtonRelease-1> { ttk::panedwindow::Release %W %x %y }
+
+bind TPanedwindow <Motion> { ttk::panedwindow::SetCursor %W %x %y }
+bind TPanedwindow <Enter> { ttk::panedwindow::SetCursor %W %x %y }
+bind TPanedwindow <Leave> { ttk::panedwindow::ResetCursor %W }
+# See <<NOTE-PW-LEAVE-NOTIFYINFERIOR>>
+bind TPanedwindow <<EnteredChild>> { ttk::panedwindow::ResetCursor %W }
+
+## Sash movement:
+#
+proc ttk::panedwindow::Press {w x y} {
+ variable State
+
+ set sash [$w identify $x $y]
+ if {$sash eq ""} {
+ set State(pressed) 0
+ return
+ }
+ set State(pressed) 1
+ set State(pressX) $x
+ set State(pressY) $y
+ set State(sash) $sash
+ set State(sashPos) [$w sashpos $sash]
+}
+
+proc ttk::panedwindow::Drag {w x y} {
+ variable State
+ if {!$State(pressed)} { return }
+ switch -- [$w cget -orient] {
+ horizontal { set delta [expr {$x - $State(pressX)}] }
+ vertical { set delta [expr {$y - $State(pressY)}] }
+ }
+ $w sashpos $State(sash) [expr {$State(sashPos) + $delta}]
+}
+
+proc ttk::panedwindow::Release {w x y} {
+ variable State
+ set State(pressed) 0
+ SetCursor $w $x $y
+}
+
+## Cursor management:
+#
+proc ttk::panedwindow::ResetCursor {w} {
+ variable State
+ if {!$State(pressed)} {
+ ttk::setCursor $w {}
+ }
+}
+
+proc ttk::panedwindow::SetCursor {w x y} {
+ set cursor ""
+ if {[llength [$w identify $x $y]]} {
+ # Assume we're over a sash.
+ switch -- [$w cget -orient] {
+ horizontal { set cursor hresize }
+ vertical { set cursor vresize }
+ }
+ }
+ ttk::setCursor $w $cursor
+}
+
+#*EOF*
diff --git a/tk8.6/library/ttk/progress.tcl b/tk8.6/library/ttk/progress.tcl
new file mode 100644
index 0000000..34dce72
--- /dev/null
+++ b/tk8.6/library/ttk/progress.tcl
@@ -0,0 +1,49 @@
+#
+# Ttk widget set: progress bar utilities.
+#
+
+namespace eval ttk::progressbar {
+ variable Timers ;# Map: widget name -> after ID
+}
+
+# Autoincrement --
+# Periodic callback procedure for autoincrement mode
+#
+proc ttk::progressbar::Autoincrement {pb steptime stepsize} {
+ variable Timers
+
+ if {![winfo exists $pb]} {
+ # widget has been destroyed -- cancel timer
+ unset -nocomplain Timers($pb)
+ return
+ }
+
+ set Timers($pb) [after $steptime \
+ [list ttk::progressbar::Autoincrement $pb $steptime $stepsize] ]
+
+ $pb step $stepsize
+}
+
+# ttk::progressbar::start --
+# Start autoincrement mode. Invoked by [$pb start] widget code.
+#
+proc ttk::progressbar::start {pb {steptime 50} {stepsize 1}} {
+ variable Timers
+ if {![info exists Timers($pb)]} {
+ Autoincrement $pb $steptime $stepsize
+ }
+}
+
+# ttk::progressbar::stop --
+# Cancel autoincrement mode. Invoked by [$pb stop] widget code.
+#
+proc ttk::progressbar::stop {pb} {
+ variable Timers
+ if {[info exists Timers($pb)]} {
+ after cancel $Timers($pb)
+ unset Timers($pb)
+ }
+ $pb configure -value 0
+}
+
+
diff --git a/tk8.6/library/ttk/scale.tcl b/tk8.6/library/ttk/scale.tcl
new file mode 100644
index 0000000..62c85bf
--- /dev/null
+++ b/tk8.6/library/ttk/scale.tcl
@@ -0,0 +1,94 @@
+# scale.tcl - Copyright (C) 2004 Pat Thoyts <patthoyts@users.sourceforge.net>
+#
+# Bindings for the TScale widget
+
+namespace eval ttk::scale {
+ variable State
+ array set State {
+ dragging 0
+ }
+}
+
+bind TScale <ButtonPress-1> { ttk::scale::Press %W %x %y }
+bind TScale <B1-Motion> { ttk::scale::Drag %W %x %y }
+bind TScale <ButtonRelease-1> { ttk::scale::Release %W %x %y }
+
+bind TScale <ButtonPress-2> { ttk::scale::Jump %W %x %y }
+bind TScale <B2-Motion> { ttk::scale::Drag %W %x %y }
+bind TScale <ButtonRelease-2> { ttk::scale::Release %W %x %y }
+
+bind TScale <ButtonPress-3> { ttk::scale::Jump %W %x %y }
+bind TScale <B3-Motion> { ttk::scale::Drag %W %x %y }
+bind TScale <ButtonRelease-3> { ttk::scale::Release %W %x %y }
+
+## Keyboard navigation bindings:
+#
+bind TScale <<LineStart>> { %W set [%W cget -from] }
+bind TScale <<LineEnd>> { %W set [%W cget -to] }
+
+bind TScale <<PrevChar>> { ttk::scale::Increment %W -1 }
+bind TScale <<PrevLine>> { ttk::scale::Increment %W -1 }
+bind TScale <<NextChar>> { ttk::scale::Increment %W 1 }
+bind TScale <<NextLine>> { ttk::scale::Increment %W 1 }
+bind TScale <<PrevWord>> { ttk::scale::Increment %W -10 }
+bind TScale <<PrevPara>> { ttk::scale::Increment %W -10 }
+bind TScale <<NextWord>> { ttk::scale::Increment %W 10 }
+bind TScale <<NextPara>> { ttk::scale::Increment %W 10 }
+
+proc ttk::scale::Press {w x y} {
+ variable State
+ set State(dragging) 0
+
+ switch -glob -- [$w identify $x $y] {
+ *track -
+ *trough {
+ set inc [expr {([$w get $x $y] <= [$w get]) ^ ([$w cget -from] > [$w cget -to]) ? -1 : 1}]
+ ttk::Repeatedly Increment $w $inc
+ }
+ *slider {
+ set State(dragging) 1
+ set State(initial) [$w get]
+ }
+ }
+}
+
+# scale::Jump -- ButtonPress-2/3 binding for scale acts like
+# Press except that clicking in the trough jumps to the
+# clicked position.
+proc ttk::scale::Jump {w x y} {
+ variable State
+ set State(dragging) 0
+
+ switch -glob -- [$w identify $x $y] {
+ *track -
+ *trough {
+ $w set [$w get $x $y]
+ set State(dragging) 1
+ set State(initial) [$w get]
+ }
+ *slider {
+ Press $w $x $y
+ }
+ }
+}
+
+proc ttk::scale::Drag {w x y} {
+ variable State
+ if {$State(dragging)} {
+ $w set [$w get $x $y]
+ }
+}
+
+proc ttk::scale::Release {w x y} {
+ variable State
+ set State(dragging) 0
+ ttk::CancelRepeat
+}
+
+proc ttk::scale::Increment {w delta} {
+ if {![winfo exists $w]} return
+ if {([$w cget -from] > [$w cget -to])} {
+ set delta [expr {-$delta}]
+ }
+ $w set [expr {[$w get] + $delta}]
+}
diff --git a/tk8.6/library/ttk/scrollbar.tcl b/tk8.6/library/ttk/scrollbar.tcl
new file mode 100644
index 0000000..d08e1e2
--- /dev/null
+++ b/tk8.6/library/ttk/scrollbar.tcl
@@ -0,0 +1,105 @@
+#
+# Bindings for TScrollbar widget
+#
+
+namespace eval ttk::scrollbar {
+ variable State
+ # State(xPress) --
+ # State(yPress) -- initial position of mouse at start of drag.
+ # State(first) -- value of -first at start of drag.
+}
+
+bind TScrollbar <ButtonPress-1> { ttk::scrollbar::Press %W %x %y }
+bind TScrollbar <B1-Motion> { ttk::scrollbar::Drag %W %x %y }
+bind TScrollbar <ButtonRelease-1> { ttk::scrollbar::Release %W %x %y }
+
+bind TScrollbar <ButtonPress-2> { ttk::scrollbar::Jump %W %x %y }
+bind TScrollbar <B2-Motion> { ttk::scrollbar::Drag %W %x %y }
+bind TScrollbar <ButtonRelease-2> { ttk::scrollbar::Release %W %x %y }
+
+proc ttk::scrollbar::Scroll {w n units} {
+ set cmd [$w cget -command]
+ if {$cmd ne ""} {
+ uplevel #0 $cmd scroll $n $units
+ }
+}
+
+proc ttk::scrollbar::Moveto {w fraction} {
+ set cmd [$w cget -command]
+ if {$cmd ne ""} {
+ uplevel #0 $cmd moveto $fraction
+ }
+}
+
+proc ttk::scrollbar::Press {w x y} {
+ variable State
+
+ set State(xPress) $x
+ set State(yPress) $y
+
+ switch -glob -- [$w identify $x $y] {
+ *uparrow -
+ *leftarrow {
+ ttk::Repeatedly Scroll $w -1 units
+ }
+ *downarrow -
+ *rightarrow {
+ ttk::Repeatedly Scroll $w 1 units
+ }
+ *thumb {
+ set State(first) [lindex [$w get] 0]
+ }
+ *trough {
+ set f [$w fraction $x $y]
+ if {$f < [lindex [$w get] 0]} {
+ # Clicked in upper/left trough
+ ttk::Repeatedly Scroll $w -1 pages
+ } elseif {$f > [lindex [$w get] 1]} {
+ # Clicked in lower/right trough
+ ttk::Repeatedly Scroll $w 1 pages
+ } else {
+ # Clicked on thumb (???)
+ set State(first) [lindex [$w get] 0]
+ }
+ }
+ }
+}
+
+proc ttk::scrollbar::Drag {w x y} {
+ variable State
+ if {![info exists State(first)]} {
+ # Initial buttonpress was not on the thumb,
+ # or something screwy has happened. In either case, ignore:
+ return;
+ }
+ set xDelta [expr {$x - $State(xPress)}]
+ set yDelta [expr {$y - $State(yPress)}]
+ Moveto $w [expr {$State(first) + [$w delta $xDelta $yDelta]}]
+}
+
+proc ttk::scrollbar::Release {w x y} {
+ variable State
+ unset -nocomplain State(xPress) State(yPress) State(first)
+ ttk::CancelRepeat
+}
+
+# scrollbar::Jump -- ButtonPress-2 binding for scrollbars.
+# Behaves exactly like scrollbar::Press, except that
+# clicking in the trough jumps to the the selected position.
+#
+proc ttk::scrollbar::Jump {w x y} {
+ variable State
+
+ switch -glob -- [$w identify $x $y] {
+ *thumb -
+ *trough {
+ set State(first) [$w fraction $x $y]
+ Moveto $w $State(first)
+ set State(xPress) $x
+ set State(yPress) $y
+ }
+ default {
+ Press $w $x $y
+ }
+ }
+}
diff --git a/tk8.6/library/ttk/sizegrip.tcl b/tk8.6/library/ttk/sizegrip.tcl
new file mode 100644
index 0000000..24a67c6
--- /dev/null
+++ b/tk8.6/library/ttk/sizegrip.tcl
@@ -0,0 +1,102 @@
+#
+# Sizegrip widget bindings.
+#
+# Dragging a sizegrip widget resizes the containing toplevel.
+#
+# NOTE: the sizegrip widget must be in the lower right hand corner.
+#
+
+switch -- [tk windowingsystem] {
+ x11 -
+ win32 {
+ option add *TSizegrip.cursor [ttk::cursor seresize] widgetDefault
+ }
+ aqua {
+ # Aqua sizegrips use default Arrow cursor.
+ }
+}
+
+namespace eval ttk::sizegrip {
+ variable State
+ array set State {
+ pressed 0
+ pressX 0
+ pressY 0
+ width 0
+ height 0
+ widthInc 1
+ heightInc 1
+ resizeX 1
+ resizeY 1
+ toplevel {}
+ }
+}
+
+bind TSizegrip <ButtonPress-1> { ttk::sizegrip::Press %W %X %Y }
+bind TSizegrip <B1-Motion> { ttk::sizegrip::Drag %W %X %Y }
+bind TSizegrip <ButtonRelease-1> { ttk::sizegrip::Release %W %X %Y }
+
+proc ttk::sizegrip::Press {W X Y} {
+ variable State
+
+ if {[$W instate disabled]} { return }
+
+ set top [winfo toplevel $W]
+
+ # If the toplevel is not resizable then bail
+ foreach {State(resizeX) State(resizeY)} [wm resizable $top] break
+ if {!$State(resizeX) && !$State(resizeY)} {
+ return
+ }
+
+ # Sanity-checks:
+ # If a negative X or Y position was specified for [wm geometry],
+ # just bail out -- there's no way to handle this cleanly.
+ #
+ if {[scan [wm geometry $top] "%dx%d+%d+%d" width height x y] != 4} {
+ return;
+ }
+
+ # Account for gridded geometry:
+ #
+ set grid [wm grid $top]
+ if {[llength $grid]} {
+ set State(widthInc) [lindex $grid 2]
+ set State(heightInc) [lindex $grid 3]
+ } else {
+ set State(widthInc) [set State(heightInc) 1]
+ }
+
+ set State(toplevel) $top
+ set State(pressX) $X
+ set State(pressY) $Y
+ set State(width) $width
+ set State(height) $height
+ set State(x) $x
+ set State(y) $y
+ set State(pressed) 1
+}
+
+proc ttk::sizegrip::Drag {W X Y} {
+ variable State
+ if {!$State(pressed)} { return }
+ set w $State(width)
+ set h $State(height)
+ if {$State(resizeX)} {
+ set w [expr {$w + ($X - $State(pressX))/$State(widthInc)}]
+ }
+ if {$State(resizeY)} {
+ set h [expr {$h + ($Y - $State(pressY))/$State(heightInc)}]
+ }
+ if {$w <= 0} { set w 1 }
+ if {$h <= 0} { set h 1 }
+ set x $State(x) ; set y $State(y)
+ wm geometry $State(toplevel) ${w}x${h}+${x}+${y}
+}
+
+proc ttk::sizegrip::Release {W X Y} {
+ variable State
+ set State(pressed) 0
+}
+
+#*EOF*
diff --git a/tk8.6/library/ttk/spinbox.tcl b/tk8.6/library/ttk/spinbox.tcl
new file mode 100644
index 0000000..1aa0ccb
--- /dev/null
+++ b/tk8.6/library/ttk/spinbox.tcl
@@ -0,0 +1,173 @@
+#
+# ttk::spinbox bindings
+#
+
+namespace eval ttk::spinbox { }
+
+### Spinbox bindings.
+#
+# Duplicate the Entry bindings, override if needed:
+#
+
+ttk::copyBindings TEntry TSpinbox
+
+bind TSpinbox <Motion> { ttk::spinbox::Motion %W %x %y }
+bind TSpinbox <ButtonPress-1> { ttk::spinbox::Press %W %x %y }
+bind TSpinbox <ButtonRelease-1> { ttk::spinbox::Release %W }
+bind TSpinbox <Double-Button-1> { ttk::spinbox::DoubleClick %W %x %y }
+bind TSpinbox <Triple-Button-1> {} ;# disable TEntry triple-click
+
+bind TSpinbox <KeyPress-Up> { event generate %W <<Increment>> }
+bind TSpinbox <KeyPress-Down> { event generate %W <<Decrement>> }
+
+bind TSpinbox <<Increment>> { ttk::spinbox::Spin %W +1 }
+bind TSpinbox <<Decrement>> { ttk::spinbox::Spin %W -1 }
+
+ttk::bindMouseWheel TSpinbox [list ttk::spinbox::MouseWheel %W]
+
+## Motion --
+# Sets cursor.
+#
+proc ttk::spinbox::Motion {w x y} {
+ if { [$w identify $x $y] eq "textarea"
+ && [$w instate {!readonly !disabled}]
+ } {
+ ttk::setCursor $w text
+ } else {
+ ttk::setCursor $w ""
+ }
+}
+
+## Press --
+#
+proc ttk::spinbox::Press {w x y} {
+ if {[$w instate disabled]} { return }
+ focus $w
+ switch -glob -- [$w identify $x $y] {
+ *textarea { ttk::entry::Press $w $x }
+ *rightarrow -
+ *uparrow { ttk::Repeatedly event generate $w <<Increment>> }
+ *leftarrow -
+ *downarrow { ttk::Repeatedly event generate $w <<Decrement>> }
+ *spinbutton {
+ if {$y * 2 >= [winfo height $w]} {
+ set event <<Decrement>>
+ } else {
+ set event <<Increment>>
+ }
+ ttk::Repeatedly event generate $w $event
+ }
+ }
+}
+
+## DoubleClick --
+# Select all if over the text area; otherwise same as Press.
+#
+proc ttk::spinbox::DoubleClick {w x y} {
+ if {[$w instate disabled]} { return }
+
+ switch -glob -- [$w identify $x $y] {
+ *textarea { SelectAll $w }
+ * { Press $w $x $y }
+ }
+}
+
+proc ttk::spinbox::Release {w} {
+ ttk::CancelRepeat
+}
+
+## MouseWheel --
+# Mousewheel callback. Turn these into <<Increment>> (-1, up)
+# or <<Decrement> (+1, down) events.
+#
+proc ttk::spinbox::MouseWheel {w dir} {
+ if {$dir < 0} {
+ event generate $w <<Increment>>
+ } else {
+ event generate $w <<Decrement>>
+ }
+}
+
+## SelectAll --
+# Select widget contents.
+#
+proc ttk::spinbox::SelectAll {w} {
+ $w selection range 0 end
+ $w icursor end
+}
+
+## Limit --
+# Limit $v to lie between $min and $max
+#
+proc ttk::spinbox::Limit {v min max} {
+ if {$v < $min} { return $min }
+ if {$v > $max} { return $max }
+ return $v
+}
+
+## Wrap --
+# Adjust $v to lie between $min and $max, wrapping if out of bounds.
+#
+proc ttk::spinbox::Wrap {v min max} {
+ if {$v < $min} { return $max }
+ if {$v > $max} { return $min }
+ return $v
+}
+
+## Adjust --
+# Limit or wrap spinbox value depending on -wrap.
+#
+proc ttk::spinbox::Adjust {w v min max} {
+ if {[$w cget -wrap]} {
+ return [Wrap $v $min $max]
+ } else {
+ return [Limit $v $min $max]
+ }
+}
+
+## Spin --
+# Handle <<Increment>> and <<Decrement>> events.
+# If -values is specified, cycle through the list.
+# Otherwise cycle through numeric range based on
+# -from, -to, and -increment.
+#
+proc ttk::spinbox::Spin {w dir} {
+ set nvalues [llength [set values [$w cget -values]]]
+ set value [$w get]
+ if {$nvalues} {
+ set current [lsearch -exact $values $value]
+ set index [Adjust $w [expr {$current + $dir}] 0 [expr {$nvalues - 1}]]
+ $w set [lindex $values $index]
+ } else {
+ if {[catch {
+ set v [expr {[scan [$w get] %f] + $dir * [$w cget -increment]}]
+ }]} {
+ set v [$w cget -from]
+ }
+ $w set [FormatValue $w [Adjust $w $v [$w cget -from] [$w cget -to]]]
+ }
+ SelectAll $w
+ uplevel #0 [$w cget -command]
+}
+
+## FormatValue --
+# Reformat numeric value based on -format.
+#
+proc ttk::spinbox::FormatValue {w val} {
+ set fmt [$w cget -format]
+ if {$fmt eq ""} {
+ # Try to guess a suitable -format based on -increment.
+ set delta [expr {abs([$w cget -increment])}]
+ if {0 < $delta && $delta < 1} {
+ # NB: This guesses wrong if -increment has more than 1
+ # significant digit itself, e.g., -increment 0.25
+ set nsd [expr {int(ceil(-log10($delta)))}]
+ set fmt "%.${nsd}f"
+ } else {
+ set fmt "%.0f"
+ }
+ }
+ return [format $fmt $val]
+}
+
+#*EOF*
diff --git a/tk8.6/library/ttk/treeview.tcl b/tk8.6/library/ttk/treeview.tcl
new file mode 100644
index 0000000..0b5d953
--- /dev/null
+++ b/tk8.6/library/ttk/treeview.tcl
@@ -0,0 +1,369 @@
+#
+# ttk::treeview widget bindings and utilities.
+#
+
+namespace eval ttk::treeview {
+ variable State
+
+ # Enter/Leave/Motion
+ #
+ set State(activeWidget) {}
+ set State(activeHeading) {}
+
+ # Press/drag/release:
+ #
+ set State(pressMode) none
+ set State(pressX) 0
+
+ # For pressMode == "resize"
+ set State(resizeColumn) #0
+
+ # For pressmode == "heading"
+ set State(heading) {}
+}
+
+### Widget bindings.
+#
+
+bind Treeview <Motion> { ttk::treeview::Motion %W %x %y }
+bind Treeview <B1-Leave> { #nothing }
+bind Treeview <Leave> { ttk::treeview::ActivateHeading {} {}}
+bind Treeview <ButtonPress-1> { ttk::treeview::Press %W %x %y }
+bind Treeview <Double-ButtonPress-1> { ttk::treeview::DoubleClick %W %x %y }
+bind Treeview <ButtonRelease-1> { ttk::treeview::Release %W %x %y }
+bind Treeview <B1-Motion> { ttk::treeview::Drag %W %x %y }
+bind Treeview <KeyPress-Up> { ttk::treeview::Keynav %W up }
+bind Treeview <KeyPress-Down> { ttk::treeview::Keynav %W down }
+bind Treeview <KeyPress-Right> { ttk::treeview::Keynav %W right }
+bind Treeview <KeyPress-Left> { ttk::treeview::Keynav %W left }
+bind Treeview <KeyPress-Prior> { %W yview scroll -1 pages }
+bind Treeview <KeyPress-Next> { %W yview scroll 1 pages }
+bind Treeview <KeyPress-Return> { ttk::treeview::ToggleFocus %W }
+bind Treeview <KeyPress-space> { ttk::treeview::ToggleFocus %W }
+
+bind Treeview <Shift-ButtonPress-1> \
+ { ttk::treeview::Select %W %x %y extend }
+bind Treeview <<ToggleSelection>> \
+ { ttk::treeview::Select %W %x %y toggle }
+
+ttk::copyBindings TtkScrollable Treeview
+
+### Binding procedures.
+#
+
+## Keynav -- Keyboard navigation
+#
+# @@@ TODO: verify/rewrite up and down code.
+#
+proc ttk::treeview::Keynav {w dir} {
+ set focus [$w focus]
+ if {$focus eq ""} { return }
+
+ switch -- $dir {
+ up {
+ if {[set up [$w prev $focus]] eq ""} {
+ set focus [$w parent $focus]
+ } else {
+ while {[$w item $up -open] && [llength [$w children $up]]} {
+ set up [lindex [$w children $up] end]
+ }
+ set focus $up
+ }
+ }
+ down {
+ if {[$w item $focus -open] && [llength [$w children $focus]]} {
+ set focus [lindex [$w children $focus] 0]
+ } else {
+ set up $focus
+ while {$up ne "" && [set down [$w next $up]] eq ""} {
+ set up [$w parent $up]
+ }
+ set focus $down
+ }
+ }
+ left {
+ if {[$w item $focus -open] && [llength [$w children $focus]]} {
+ CloseItem $w $focus
+ } else {
+ set focus [$w parent $focus]
+ }
+ }
+ right {
+ OpenItem $w $focus
+ }
+ }
+
+ if {$focus != {}} {
+ SelectOp $w $focus choose
+ }
+}
+
+## Motion -- pointer motion binding.
+# Sets cursor, active element ...
+#
+proc ttk::treeview::Motion {w x y} {
+ set cursor {}
+ set activeHeading {}
+
+ switch -- [$w identify region $x $y] {
+ separator { set cursor hresize }
+ heading { set activeHeading [$w identify column $x $y] }
+ }
+
+ ttk::setCursor $w $cursor
+ ActivateHeading $w $activeHeading
+}
+
+## ActivateHeading -- track active heading element
+#
+proc ttk::treeview::ActivateHeading {w heading} {
+ variable State
+
+ if {$w != $State(activeWidget) || $heading != $State(activeHeading)} {
+ if {[winfo exists $State(activeWidget)] && $State(activeHeading) != {}} {
+ $State(activeWidget) heading $State(activeHeading) state !active
+ }
+ if {$heading != {}} {
+ $w heading $heading state active
+ }
+ set State(activeHeading) $heading
+ set State(activeWidget) $w
+ }
+}
+
+## Select $w $x $y $selectop
+# Binding procedure for selection operations.
+# See "Selection modes", below.
+#
+proc ttk::treeview::Select {w x y op} {
+ if {[set item [$w identify row $x $y]] ne "" } {
+ SelectOp $w $item $op
+ }
+}
+
+## DoubleClick -- Double-ButtonPress-1 binding.
+#
+proc ttk::treeview::DoubleClick {w x y} {
+ if {[set row [$w identify row $x $y]] ne ""} {
+ Toggle $w $row
+ } else {
+ Press $w $x $y ;# perform single-click action
+ }
+}
+
+## Press -- ButtonPress binding.
+#
+proc ttk::treeview::Press {w x y} {
+ focus $w
+ switch -- [$w identify region $x $y] {
+ nothing { }
+ heading { heading.press $w $x $y }
+ separator { resize.press $w $x $y }
+ tree -
+ cell {
+ set item [$w identify item $x $y]
+ SelectOp $w $item choose
+ switch -glob -- [$w identify element $x $y] {
+ *indicator -
+ *disclosure { Toggle $w $item }
+ }
+ }
+ }
+}
+
+## Drag -- B1-Motion binding
+#
+proc ttk::treeview::Drag {w x y} {
+ variable State
+ switch $State(pressMode) {
+ resize { resize.drag $w $x }
+ heading { heading.drag $w $x $y }
+ }
+}
+
+proc ttk::treeview::Release {w x y} {
+ variable State
+ switch $State(pressMode) {
+ resize { resize.release $w $x }
+ heading { heading.release $w }
+ }
+ set State(pressMode) none
+ Motion $w $x $y
+}
+
+### Interactive column resizing.
+#
+proc ttk::treeview::resize.press {w x y} {
+ variable State
+ set State(pressMode) "resize"
+ set State(resizeColumn) [$w identify column $x $y]
+}
+
+proc ttk::treeview::resize.drag {w x} {
+ variable State
+ $w drag $State(resizeColumn) $x
+}
+
+proc ttk::treeview::resize.release {w x} {
+ $w drop
+}
+
+### Heading activation.
+#
+
+proc ttk::treeview::heading.press {w x y} {
+ variable State
+ set column [$w identify column $x $y]
+ set State(pressMode) "heading"
+ set State(heading) $column
+ $w heading $column state pressed
+}
+
+proc ttk::treeview::heading.drag {w x y} {
+ variable State
+ if { [$w identify region $x $y] eq "heading"
+ && [$w identify column $x $y] eq $State(heading)
+ } {
+ $w heading $State(heading) state pressed
+ } else {
+ $w heading $State(heading) state !pressed
+ }
+}
+
+proc ttk::treeview::heading.release {w} {
+ variable State
+ if {[lsearch -exact [$w heading $State(heading) state] pressed] >= 0} {
+ after 0 [$w heading $State(heading) -command]
+ }
+ $w heading $State(heading) state !pressed
+}
+
+### Selection modes.
+#
+
+## SelectOp $w $item [ choose | extend | toggle ] --
+# Dispatch to appropriate selection operation
+# depending on current value of -selectmode.
+#
+proc ttk::treeview::SelectOp {w item op} {
+ select.$op.[$w cget -selectmode] $w $item
+}
+
+## -selectmode none:
+#
+proc ttk::treeview::select.choose.none {w item} { $w focus $item }
+proc ttk::treeview::select.toggle.none {w item} { $w focus $item }
+proc ttk::treeview::select.extend.none {w item} { $w focus $item }
+
+## -selectmode browse:
+#
+proc ttk::treeview::select.choose.browse {w item} { BrowseTo $w $item }
+proc ttk::treeview::select.toggle.browse {w item} { BrowseTo $w $item }
+proc ttk::treeview::select.extend.browse {w item} { BrowseTo $w $item }
+
+## -selectmode multiple:
+#
+proc ttk::treeview::select.choose.extended {w item} {
+ BrowseTo $w $item
+}
+proc ttk::treeview::select.toggle.extended {w item} {
+ $w selection toggle [list $item]
+}
+proc ttk::treeview::select.extend.extended {w item} {
+ if {[set anchor [$w focus]] ne ""} {
+ $w selection set [between $w $anchor $item]
+ } else {
+ BrowseTo $w $item
+ }
+}
+
+### Tree structure utilities.
+#
+
+## between $tv $item1 $item2 --
+# Returns a list of all items between $item1 and $item2,
+# in preorder traversal order. $item1 and $item2 may be
+# in either order.
+#
+# NOTES:
+# This routine is O(N) in the size of the tree.
+# There's probably a way to do this that's O(N) in the number
+# of items returned, but I'm not clever enough to figure it out.
+#
+proc ttk::treeview::between {tv item1 item2} {
+ variable between [list]
+ variable selectingBetween 0
+ ScanBetween $tv $item1 $item2 {}
+ return $between
+}
+
+## ScanBetween --
+# Recursive worker routine for ttk::treeview::between
+#
+proc ttk::treeview::ScanBetween {tv item1 item2 item} {
+ variable between
+ variable selectingBetween
+
+ if {$item eq $item1 || $item eq $item2} {
+ lappend between $item
+ set selectingBetween [expr {!$selectingBetween}]
+ } elseif {$selectingBetween} {
+ lappend between $item
+ }
+ foreach child [$tv children $item] {
+ ScanBetween $tv $item1 $item2 $child
+ }
+}
+
+### User interaction utilities.
+#
+
+## OpenItem, CloseItem -- Set the open state of an item, generate event
+#
+
+proc ttk::treeview::OpenItem {w item} {
+ $w focus $item
+ event generate $w <<TreeviewOpen>>
+ $w item $item -open true
+}
+
+proc ttk::treeview::CloseItem {w item} {
+ $w item $item -open false
+ $w focus $item
+ event generate $w <<TreeviewClose>>
+}
+
+## Toggle -- toggle opened/closed state of item
+#
+proc ttk::treeview::Toggle {w item} {
+ # don't allow toggling on indicators that
+ # are not present in front of leaf items
+ if {[$w children $item] == {}} {
+ return
+ }
+ # not a leaf, toggle!
+ if {[$w item $item -open]} {
+ CloseItem $w $item
+ } else {
+ OpenItem $w $item
+ }
+}
+
+## ToggleFocus -- toggle opened/closed state of focus item
+#
+proc ttk::treeview::ToggleFocus {w} {
+ set item [$w focus]
+ if {$item ne ""} {
+ Toggle $w $item
+ }
+}
+
+## BrowseTo -- navigate to specified item; set focus and selection
+#
+proc ttk::treeview::BrowseTo {w item} {
+ $w see $item
+ $w focus $item
+ $w selection set [list $item]
+}
+
+#*EOF*
diff --git a/tk8.6/library/ttk/ttk.tcl b/tk8.6/library/ttk/ttk.tcl
new file mode 100644
index 0000000..7bae211
--- /dev/null
+++ b/tk8.6/library/ttk/ttk.tcl
@@ -0,0 +1,176 @@
+#
+# Ttk widget set initialization script.
+#
+
+### Source library scripts.
+#
+
+namespace eval ::ttk {
+ variable library
+ if {![info exists library]} {
+ set library [file dirname [info script]]
+ }
+}
+
+source [file join $::ttk::library fonts.tcl]
+source [file join $::ttk::library cursors.tcl]
+source [file join $::ttk::library utils.tcl]
+
+## ttk::deprecated $old $new --
+# Define $old command as a deprecated alias for $new command
+# $old and $new must be fully namespace-qualified.
+#
+proc ttk::deprecated {old new} {
+ interp alias {} $old {} ttk::do'deprecate $old $new
+}
+## do'deprecate --
+# Implementation procedure for deprecated commands --
+# issue a warning (once), then re-alias old to new.
+#
+proc ttk::do'deprecate {old new args} {
+ deprecated'warning $old $new
+ interp alias {} $old {} $new
+ uplevel 1 [linsert $args 0 $new]
+}
+
+## deprecated'warning --
+# Gripe about use of deprecated commands.
+#
+proc ttk::deprecated'warning {old new} {
+ puts stderr "$old deprecated -- use $new instead"
+}
+
+### Backward-compatibility.
+#
+#
+# Make [package require tile] an effective no-op;
+# see SF#3016598 for discussion.
+#
+package ifneeded tile 0.8.6 { package provide tile 0.8.6 }
+
+# ttk::panedwindow used to be named ttk::paned. Keep the alias for now.
+#
+::ttk::deprecated ::ttk::paned ::ttk::panedwindow
+
+### ::ttk::ThemeChanged --
+# Called from [::ttk::style theme use].
+# Sends a <<ThemeChanged>> virtual event to all widgets.
+#
+proc ::ttk::ThemeChanged {} {
+ set Q .
+ while {[llength $Q]} {
+ set QN [list]
+ foreach w $Q {
+ event generate $w <<ThemeChanged>>
+ foreach child [winfo children $w] {
+ lappend QN $child
+ }
+ }
+ set Q $QN
+ }
+}
+
+### Public API.
+#
+
+proc ::ttk::themes {{ptn *}} {
+ set themes [list]
+
+ foreach pkg [lsearch -inline -all -glob [package names] ttk::theme::$ptn] {
+ lappend themes [namespace tail $pkg]
+ }
+
+ return $themes
+}
+
+## ttk::setTheme $theme --
+# Set the current theme to $theme, loading it if necessary.
+#
+proc ::ttk::setTheme {theme} {
+ variable currentTheme ;# @@@ Temp -- [::ttk::style theme use] doesn't work
+ if {$theme ni [::ttk::style theme names]} {
+ package require ttk::theme::$theme
+ }
+ ::ttk::style theme use $theme
+ set currentTheme $theme
+}
+
+### Load widget bindings.
+#
+source [file join $::ttk::library button.tcl]
+source [file join $::ttk::library menubutton.tcl]
+source [file join $::ttk::library scrollbar.tcl]
+source [file join $::ttk::library scale.tcl]
+source [file join $::ttk::library progress.tcl]
+source [file join $::ttk::library notebook.tcl]
+source [file join $::ttk::library panedwindow.tcl]
+source [file join $::ttk::library entry.tcl]
+source [file join $::ttk::library combobox.tcl] ;# dependency: entry.tcl
+source [file join $::ttk::library spinbox.tcl] ;# dependency: entry.tcl
+source [file join $::ttk::library treeview.tcl]
+source [file join $::ttk::library sizegrip.tcl]
+
+## Label and Labelframe bindings:
+# (not enough to justify their own file...)
+#
+bind TLabelframe <<Invoke>> { tk::TabToWindow [tk_focusNext %W] }
+bind TLabel <<Invoke>> { tk::TabToWindow [tk_focusNext %W] }
+
+### Load settings for built-in themes:
+#
+proc ttk::LoadThemes {} {
+ variable library
+
+ # "default" always present:
+ uplevel #0 [list source [file join $library defaults.tcl]]
+
+ set builtinThemes [style theme names]
+ foreach {theme scripts} {
+ classic classicTheme.tcl
+ alt altTheme.tcl
+ clam clamTheme.tcl
+ winnative winTheme.tcl
+ xpnative {xpTheme.tcl vistaTheme.tcl}
+ aqua aquaTheme.tcl
+ } {
+ if {[lsearch -exact $builtinThemes $theme] >= 0} {
+ foreach script $scripts {
+ uplevel #0 [list source [file join $library $script]]
+ }
+ }
+ }
+}
+
+ttk::LoadThemes; rename ::ttk::LoadThemes {}
+
+### Select platform-specific default theme:
+#
+# Notes:
+# + On OSX, aqua theme is the default
+# + On Windows, xpnative takes precedence over winnative if available.
+# + On X11, users can use the X resource database to
+# specify a preferred theme (*TkTheme: themeName);
+# otherwise "default" is used.
+#
+
+proc ttk::DefaultTheme {} {
+ set preferred [list aqua vista xpnative winnative]
+
+ set userTheme [option get . tkTheme TkTheme]
+ if {$userTheme ne {} && ![catch {
+ uplevel #0 [list package require ttk::theme::$userTheme]
+ }]} {
+ return $userTheme
+ }
+
+ foreach theme $preferred {
+ if {[package provide ttk::theme::$theme] ne ""} {
+ return $theme
+ }
+ }
+ return "default"
+}
+
+ttk::setTheme [ttk::DefaultTheme] ; rename ttk::DefaultTheme {}
+
+#*EOF*
diff --git a/tk8.6/library/ttk/utils.tcl b/tk8.6/library/ttk/utils.tcl
new file mode 100644
index 0000000..7cc1bb7
--- /dev/null
+++ b/tk8.6/library/ttk/utils.tcl
@@ -0,0 +1,350 @@
+#
+# Utilities for widget implementations.
+#
+
+### Focus management.
+#
+# See also: #1516479
+#
+
+## ttk::takefocus --
+# This is the default value of the "-takefocus" option
+# for ttk::* widgets that participate in keyboard navigation.
+#
+# NOTES:
+# tk::FocusOK (called by tk_focusNext) tests [winfo viewable]
+# if -takefocus is 1, empty, or missing; but not if it's a
+# script prefix, so we have to check that here as well.
+#
+#
+proc ttk::takefocus {w} {
+ expr {[$w instate !disabled] && [winfo viewable $w]}
+}
+
+## ttk::GuessTakeFocus --
+# This routine is called as a fallback for widgets
+# with a missing or empty -takefocus option.
+#
+# It implements the same heuristics as tk::FocusOK.
+#
+proc ttk::GuessTakeFocus {w} {
+ # Don't traverse to widgets with '-state disabled':
+ #
+ if {![catch {$w cget -state} state] && $state eq "disabled"} {
+ return 0
+ }
+
+ # Allow traversal to widgets with explicit key or focus bindings:
+ #
+ if {[regexp {Key|Focus} [concat [bind $w] [bind [winfo class $w]]]]} {
+ return 1;
+ }
+
+ # Default is nontraversable:
+ #
+ return 0;
+}
+
+## ttk::traverseTo $w --
+# Set the keyboard focus to the specified window.
+#
+proc ttk::traverseTo {w} {
+ set focus [focus]
+ if {$focus ne ""} {
+ event generate $focus <<TraverseOut>>
+ }
+ focus $w
+ event generate $w <<TraverseIn>>
+}
+
+## ttk::clickToFocus $w --
+# Utility routine, used in <ButtonPress-1> bindings --
+# Assign keyboard focus to the specified widget if -takefocus is enabled.
+#
+proc ttk::clickToFocus {w} {
+ if {[ttk::takesFocus $w]} { focus $w }
+}
+
+## ttk::takesFocus w --
+# Test if the widget can take keyboard focus.
+#
+# See the description of the -takefocus option in options(n)
+# for details.
+#
+proc ttk::takesFocus {w} {
+ if {![winfo viewable $w]} {
+ return 0
+ } elseif {[catch {$w cget -takefocus} takefocus]} {
+ return [GuessTakeFocus $w]
+ } else {
+ switch -- $takefocus {
+ "" { return [GuessTakeFocus $w] }
+ 0 { return 0 }
+ 1 { return 1 }
+ default {
+ return [expr {[uplevel #0 $takefocus [list $w]] == 1}]
+ }
+ }
+ }
+}
+
+## ttk::focusFirst $w --
+# Return the first descendant of $w, in preorder traversal order,
+# that can take keyboard focus, "" if none do.
+#
+# See also: tk_focusNext
+#
+
+proc ttk::focusFirst {w} {
+ if {[ttk::takesFocus $w]} {
+ return $w
+ }
+ foreach child [winfo children $w] {
+ if {[set c [ttk::focusFirst $child]] ne ""} {
+ return $c
+ }
+ }
+ return ""
+}
+
+### Grabs.
+#
+# Rules:
+# Each call to [grabWindow $w] or [globalGrab $w] must be
+# matched with a call to [releaseGrab $w] in LIFO order.
+#
+# Do not call [grabWindow $w] for a window that currently
+# appears on the grab stack.
+#
+# See #1239190 and #1411983 for more discussion.
+#
+namespace eval ttk {
+ variable Grab ;# map: window name -> grab token
+
+ # grab token details:
+ # Two-element list containing:
+ # 1) a script to evaluate to restore the previous grab (if any);
+ # 2) a script to evaluate to restore the focus (if any)
+}
+
+## SaveGrab --
+# Record current grab and focus windows.
+#
+proc ttk::SaveGrab {w} {
+ variable Grab
+
+ if {[info exists Grab($w)]} {
+ # $w is already on the grab stack.
+ # This should not happen, but bail out in case it does anyway:
+ #
+ return
+ }
+
+ set restoreGrab [set restoreFocus ""]
+
+ set grabbed [grab current $w]
+ if {[winfo exists $grabbed]} {
+ switch [grab status $grabbed] {
+ global { set restoreGrab [list grab -global $grabbed] }
+ local { set restoreGrab [list grab $grabbed] }
+ none { ;# grab window is really in a different interp }
+ }
+ }
+
+ set focus [focus]
+ if {$focus ne ""} {
+ set restoreFocus [list focus -force $focus]
+ }
+
+ set Grab($w) [list $restoreGrab $restoreFocus]
+}
+
+## RestoreGrab --
+# Restore previous grab and focus windows.
+# If called more than once without an intervening [SaveGrab $w],
+# does nothing.
+#
+proc ttk::RestoreGrab {w} {
+ variable Grab
+
+ if {![info exists Grab($w)]} { # Ignore
+ return;
+ }
+
+ # The previous grab/focus window may have been destroyed,
+ # unmapped, or some other abnormal condition; ignore any errors.
+ #
+ foreach script $Grab($w) {
+ catch $script
+ }
+
+ unset Grab($w)
+}
+
+## ttk::grabWindow $w --
+# Records the current focus and grab windows, sets an application-modal
+# grab on window $w.
+#
+proc ttk::grabWindow {w} {
+ SaveGrab $w
+ grab $w
+}
+
+## ttk::globalGrab $w --
+# Same as grabWindow, but sets a global grab on $w.
+#
+proc ttk::globalGrab {w} {
+ SaveGrab $w
+ grab -global $w
+}
+
+## ttk::releaseGrab --
+# Release the grab previously set by [ttk::grabWindow]
+# or [ttk::globalGrab].
+#
+proc ttk::releaseGrab {w} {
+ grab release $w
+ RestoreGrab $w
+}
+
+### Auto-repeat.
+#
+# NOTE: repeating widgets do not have -repeatdelay
+# or -repeatinterval resources as in standard Tk;
+# instead a single set of settings is applied application-wide.
+# (TODO: make this user-configurable)
+#
+# (@@@ Windows seems to use something like 500/50 milliseconds
+# @@@ for -repeatdelay/-repeatinterval)
+#
+
+namespace eval ttk {
+ variable Repeat
+ array set Repeat {
+ delay 300
+ interval 100
+ timer {}
+ script {}
+ }
+}
+
+## ttk::Repeatedly --
+# Begin auto-repeat.
+#
+proc ttk::Repeatedly {args} {
+ variable Repeat
+ after cancel $Repeat(timer)
+ set script [uplevel 1 [list namespace code $args]]
+ set Repeat(script) $script
+ uplevel #0 $script
+ set Repeat(timer) [after $Repeat(delay) ttk::Repeat]
+}
+
+## Repeat --
+# Continue auto-repeat
+#
+proc ttk::Repeat {} {
+ variable Repeat
+ uplevel #0 $Repeat(script)
+ set Repeat(timer) [after $Repeat(interval) ttk::Repeat]
+}
+
+## ttk::CancelRepeat --
+# Halt auto-repeat.
+#
+proc ttk::CancelRepeat {} {
+ variable Repeat
+ after cancel $Repeat(timer)
+}
+
+### Bindings.
+#
+
+## ttk::copyBindings $from $to --
+# Utility routine; copies bindings from one bindtag onto another.
+#
+proc ttk::copyBindings {from to} {
+ foreach event [bind $from] {
+ bind $to $event [bind $from $event]
+ }
+}
+
+### Mousewheel bindings.
+#
+# Platform inconsistencies:
+#
+# On X11, the server typically maps the mouse wheel to Button4 and Button5.
+#
+# On OSX, Tk generates sensible values for the %D field in <MouseWheel> events.
+#
+# On Windows, %D must be scaled by a factor of 120.
+# In addition, Tk redirects mousewheel events to the window with
+# keyboard focus instead of sending them to the window under the pointer.
+# We do not attempt to fix that here, see also TIP#171.
+#
+# OSX conventionally uses Shift+MouseWheel for horizontal scrolling,
+# and Option+MouseWheel for accelerated scrolling.
+#
+# The Shift+MouseWheel behavior is not conventional on Windows or most
+# X11 toolkits, but it's useful.
+#
+# MouseWheel scrolling is accelerated on X11, which is conventional
+# for Tk and appears to be conventional for other toolkits (although
+# Gtk+ and Qt do not appear to use as large a factor).
+#
+
+## ttk::bindMouseWheel $bindtag $command...
+# Adds basic mousewheel support to $bindtag.
+# $command will be passed one additional argument
+# specifying the mousewheel direction (-1: up, +1: down).
+#
+
+proc ttk::bindMouseWheel {bindtag callback} {
+ switch -- [tk windowingsystem] {
+ x11 {
+ bind $bindtag <ButtonPress-4> "$callback -1"
+ bind $bindtag <ButtonPress-5> "$callback +1"
+ }
+ win32 {
+ bind $bindtag <MouseWheel> [append callback { [expr {-(%D/120)}]}]
+ }
+ aqua {
+ bind $bindtag <MouseWheel> [append callback { [expr {-(%D)}]} ]
+ }
+ }
+}
+
+## Mousewheel bindings for standard scrollable widgets.
+#
+# Usage: [ttk::copyBindings TtkScrollable $bindtag]
+#
+# $bindtag should be for a widget that supports the
+# standard scrollbar protocol.
+#
+
+switch -- [tk windowingsystem] {
+ x11 {
+ bind TtkScrollable <ButtonPress-4> { %W yview scroll -5 units }
+ bind TtkScrollable <ButtonPress-5> { %W yview scroll 5 units }
+ bind TtkScrollable <Shift-ButtonPress-4> { %W xview scroll -5 units }
+ bind TtkScrollable <Shift-ButtonPress-5> { %W xview scroll 5 units }
+ }
+ win32 {
+ bind TtkScrollable <MouseWheel> \
+ { %W yview scroll [expr {-(%D/120)}] units }
+ bind TtkScrollable <Shift-MouseWheel> \
+ { %W xview scroll [expr {-(%D/120)}] units }
+ }
+ aqua {
+ bind TtkScrollable <MouseWheel> \
+ { %W yview scroll [expr {-(%D)}] units }
+ bind TtkScrollable <Shift-MouseWheel> \
+ { %W xview scroll [expr {-(%D)}] units }
+ bind TtkScrollable <Option-MouseWheel> \
+ { %W yview scroll [expr {-10*(%D)}] units }
+ bind TtkScrollable <Shift-Option-MouseWheel> \
+ { %W xview scroll [expr {-10*(%D)}] units }
+ }
+}
+
+#*EOF*
diff --git a/tk8.6/library/ttk/vistaTheme.tcl b/tk8.6/library/ttk/vistaTheme.tcl
new file mode 100644
index 0000000..094288c
--- /dev/null
+++ b/tk8.6/library/ttk/vistaTheme.tcl
@@ -0,0 +1,229 @@
+#
+# Settings for Microsoft Windows Vista and Server 2008
+#
+
+# The Vista theme can only be defined on Windows Vista and above. The theme
+# is created in C due to the need to assign a theme-enabled function for
+# detecting when themeing is disabled. On systems that cannot support the
+# Vista theme, there will be no such theme created and we must not
+# evaluate this script.
+
+if {"vista" ni [ttk::style theme names]} {
+ return
+}
+
+namespace eval ttk::theme::vista {
+
+ ttk::style theme settings vista {
+
+ ttk::style configure . \
+ -background SystemButtonFace \
+ -foreground SystemWindowText \
+ -selectforeground SystemHighlightText \
+ -selectbackground SystemHighlight \
+ -insertcolor SystemWindowText \
+ -font TkDefaultFont \
+ ;
+
+ ttk::style map "." \
+ -foreground [list disabled SystemGrayText] \
+ ;
+
+ ttk::style configure TButton -anchor center -padding {1 1} -width -11
+ ttk::style configure TRadiobutton -padding 2
+ ttk::style configure TCheckbutton -padding 2
+ ttk::style configure TMenubutton -padding {8 4}
+
+ ttk::style element create Menubutton.dropdown vsapi \
+ TOOLBAR 4 {{selected active} 6 {selected !active} 5
+ disabled 4 pressed 3 active 2 {} 1} \
+ -syssize {SM_CXVSCROLL SM_CYVSCROLL}
+
+ ttk::style configure TNotebook -tabmargins {2 2 2 0}
+ ttk::style map TNotebook.Tab \
+ -expand [list selected {2 2 2 2}]
+
+ # Treeview:
+ ttk::style configure Heading -font TkHeadingFont
+ ttk::style configure Treeview -background SystemWindow
+ ttk::style map Treeview \
+ -background [list disabled SystemButtonFace \
+ selected SystemHighlight] \
+ -foreground [list disabled SystemGrayText \
+ selected SystemHighlightText]
+
+ # Label and Toolbutton
+ ttk::style configure TLabelframe.Label -foreground SystemButtonText
+
+ ttk::style configure Toolbutton -padding {4 4}
+
+ # Combobox
+ ttk::style configure TCombobox -padding 2
+ ttk::style element create Combobox.border vsapi \
+ COMBOBOX 4 {disabled 4 focus 3 active 2 hover 2 {} 1}
+ ttk::style element create Combobox.background vsapi \
+ EDIT 3 {disabled 3 readonly 5 focus 4 hover 2 {} 1}
+ ttk::style element create Combobox.rightdownarrow vsapi \
+ COMBOBOX 6 {disabled 4 pressed 3 active 2 {} 1} \
+ -syssize {SM_CXVSCROLL SM_CYVSCROLL}
+ ttk::style layout TCombobox {
+ Combobox.border -sticky nswe -border 0 -children {
+ Combobox.rightdownarrow -side right -sticky ns
+ Combobox.padding -expand 1 -sticky nswe -children {
+ Combobox.background -sticky nswe -children {
+ Combobox.focus -expand 1 -sticky nswe -children {
+ Combobox.textarea -sticky nswe
+ }
+ }
+ }
+ }
+ }
+ # Vista.Combobox droplist frame
+ ttk::style element create ComboboxPopdownFrame.background vsapi\
+ LISTBOX 3 {disabled 4 active 3 focus 2 {} 1}
+ ttk::style layout ComboboxPopdownFrame {
+ ComboboxPopdownFrame.background -sticky news -border 1 -children {
+ ComboboxPopdownFrame.padding -sticky news
+ }
+ }
+ ttk::style map TCombobox \
+ -selectbackground [list !focus SystemWindow] \
+ -selectforeground [list !focus SystemWindowText] \
+ -foreground [list \
+ disabled SystemGrayText \
+ {readonly focus} SystemHighlightText \
+ ] \
+ -focusfill [list {readonly focus} SystemHighlight] \
+ ;
+
+ # Entry
+ ttk::style configure TEntry -padding {1 1 1 1} ;# Needs lookup
+ ttk::style element create Entry.field vsapi \
+ EDIT 6 {disabled 4 focus 3 hover 2 {} 1} -padding {2 2 2 2}
+ ttk::style element create Entry.background vsapi \
+ EDIT 3 {disabled 3 readonly 3 focus 4 hover 2 {} 1}
+ ttk::style layout TEntry {
+ Entry.field -sticky news -border 0 -children {
+ Entry.background -sticky news -children {
+ Entry.padding -sticky news -children {
+ Entry.textarea -sticky news
+ }
+ }
+ }
+ }
+ ttk::style map TEntry \
+ -selectbackground [list !focus SystemWindow] \
+ -selectforeground [list !focus SystemWindowText] \
+ ;
+
+ # Spinbox
+ ttk::style configure TSpinbox -padding 0
+ ttk::style element create Spinbox.field vsapi \
+ EDIT 9 {disabled 4 focus 3 hover 2 {} 1} -padding {1 1 1 2}
+ ttk::style element create Spinbox.background vsapi \
+ EDIT 3 {disabled 3 readonly 3 focus 4 hover 2 {} 1}
+ ttk::style element create Spinbox.innerbg vsapi \
+ EDIT 3 {disabled 3 readonly 3 focus 4 hover 2 {} 1}\
+ -padding {2 0 15 2}
+ ttk::style element create Spinbox.uparrow vsapi \
+ SPIN 1 {disabled 4 pressed 3 active 2 {} 1} \
+ -padding 1 -halfheight 1 \
+ -syssize { SM_CXVSCROLL SM_CYVSCROLL }
+ ttk::style element create Spinbox.downarrow vsapi \
+ SPIN 2 {disabled 4 pressed 3 active 2 {} 1} \
+ -padding 1 -halfheight 1 \
+ -syssize { SM_CXVSCROLL SM_CYVSCROLL }
+ ttk::style layout TSpinbox {
+ Spinbox.field -sticky nswe -children {
+ Spinbox.background -sticky news -children {
+ Spinbox.padding -sticky news -children {
+ Spinbox.innerbg -sticky news -children {
+ Spinbox.textarea -expand 1
+ }
+ }
+ Spinbox.uparrow -side top -sticky ens
+ Spinbox.downarrow -side bottom -sticky ens
+ }
+ }
+ }
+ ttk::style map TSpinbox \
+ -selectbackground [list !focus SystemWindow] \
+ -selectforeground [list !focus SystemWindowText] \
+ ;
+
+
+ # SCROLLBAR elements (Vista includes a state for 'hover')
+ ttk::style element create Vertical.Scrollbar.uparrow vsapi \
+ SCROLLBAR 1 {disabled 4 pressed 3 active 2 hover 17 {} 1} \
+ -syssize {SM_CXVSCROLL SM_CYVSCROLL}
+ ttk::style element create Vertical.Scrollbar.downarrow vsapi \
+ SCROLLBAR 1 {disabled 8 pressed 7 active 6 hover 18 {} 5} \
+ -syssize {SM_CXVSCROLL SM_CYVSCROLL}
+ ttk::style element create Vertical.Scrollbar.trough vsapi \
+ SCROLLBAR 7 {disabled 4 pressed 3 active 2 hover 5 {} 1}
+ ttk::style element create Vertical.Scrollbar.thumb vsapi \
+ SCROLLBAR 3 {disabled 4 pressed 3 active 2 hover 5 {} 1} \
+ -syssize {SM_CXVSCROLL SM_CYVSCROLL}
+ ttk::style element create Vertical.Scrollbar.grip vsapi \
+ SCROLLBAR 9 {disabled 4 pressed 3 active 2 hover 5 {} 1} \
+ -syssize {SM_CXVSCROLL SM_CYVSCROLL}
+ ttk::style element create Horizontal.Scrollbar.leftarrow vsapi \
+ SCROLLBAR 1 {disabled 12 pressed 11 active 10 hover 19 {} 9} \
+ -syssize {SM_CXHSCROLL SM_CYHSCROLL}
+ ttk::style element create Horizontal.Scrollbar.rightarrow vsapi \
+ SCROLLBAR 1 {disabled 16 pressed 15 active 14 hover 20 {} 13} \
+ -syssize {SM_CXHSCROLL SM_CYHSCROLL}
+ ttk::style element create Horizontal.Scrollbar.trough vsapi \
+ SCROLLBAR 5 {disabled 4 pressed 3 active 2 hover 5 {} 1}
+ ttk::style element create Horizontal.Scrollbar.thumb vsapi \
+ SCROLLBAR 2 {disabled 4 pressed 3 active 2 hover 5 {} 1} \
+ -syssize {SM_CXHSCROLL SM_CYHSCROLL}
+ ttk::style element create Horizontal.Scrollbar.grip vsapi \
+ SCROLLBAR 8 {disabled 4 pressed 3 active 2 hover 5 {} 1}
+
+ # Progressbar
+ ttk::style element create Horizontal.Progressbar.pbar vsapi \
+ PROGRESS 3 {{} 1} -padding 8
+ ttk::style layout Horizontal.TProgressbar {
+ Horizontal.Progressbar.trough -sticky nswe -children {
+ Horizontal.Progressbar.pbar -side left -sticky ns
+ }
+ }
+ ttk::style element create Vertical.Progressbar.pbar vsapi \
+ PROGRESS 3 {{} 1} -padding 8
+ ttk::style layout Vertical.TProgressbar {
+ Vertical.Progressbar.trough -sticky nswe -children {
+ Vertical.Progressbar.pbar -side bottom -sticky we
+ }
+ }
+
+ # Scale
+ ttk::style element create Horizontal.Scale.slider vsapi \
+ TRACKBAR 3 {disabled 5 focus 4 pressed 3 active 2 {} 1} \
+ -width 6 -height 12
+ ttk::style layout Horizontal.TScale {
+ Scale.focus -expand 1 -sticky nswe -children {
+ Horizontal.Scale.trough -expand 1 -sticky nswe -children {
+ Horizontal.Scale.track -sticky we
+ Horizontal.Scale.slider -side left -sticky {}
+ }
+ }
+ }
+ ttk::style element create Vertical.Scale.slider vsapi \
+ TRACKBAR 6 {disabled 5 focus 4 pressed 3 active 2 {} 1} \
+ -width 12 -height 6
+ ttk::style layout Vertical.TScale {
+ Scale.focus -expand 1 -sticky nswe -children {
+ Vertical.Scale.trough -expand 1 -sticky nswe -children {
+ Vertical.Scale.track -sticky ns
+ Vertical.Scale.slider -side top -sticky {}
+ }
+ }
+ }
+
+ # Treeview
+ ttk::style configure Item -padding {4 0 0 0}
+
+ package provide ttk::theme::vista 1.0
+ }
+}
diff --git a/tk8.6/library/ttk/winTheme.tcl b/tk8.6/library/ttk/winTheme.tcl
new file mode 100644
index 0000000..db05b45
--- /dev/null
+++ b/tk8.6/library/ttk/winTheme.tcl
@@ -0,0 +1,84 @@
+#
+# Settings for 'winnative' theme.
+#
+
+namespace eval ttk::theme::winnative {
+ ttk::style theme settings winnative {
+
+ ttk::style configure "." \
+ -background SystemButtonFace \
+ -foreground SystemWindowText \
+ -selectforeground SystemHighlightText \
+ -selectbackground SystemHighlight \
+ -fieldbackground SystemWindow \
+ -insertcolor SystemWindowText \
+ -troughcolor SystemScrollbar \
+ -font TkDefaultFont \
+ ;
+
+ ttk::style map "." -foreground [list disabled SystemGrayText] ;
+ ttk::style map "." -embossed [list disabled 1] ;
+
+ ttk::style configure TButton \
+ -anchor center -width -11 -relief raised -shiftrelief 1
+ ttk::style configure TCheckbutton -padding "2 4"
+ ttk::style configure TRadiobutton -padding "2 4"
+ ttk::style configure TMenubutton \
+ -padding "8 4" -arrowsize 3 -relief raised
+
+ ttk::style map TButton -relief {{!disabled pressed} sunken}
+
+ ttk::style configure TEntry \
+ -padding 2 -selectborderwidth 0 -insertwidth 1
+ ttk::style map TEntry \
+ -fieldbackground \
+ [list readonly SystemButtonFace disabled SystemButtonFace] \
+ -selectbackground [list !focus SystemWindow] \
+ -selectforeground [list !focus SystemWindowText] \
+ ;
+
+ ttk::style configure TCombobox -padding 2
+ ttk::style map TCombobox \
+ -selectbackground [list !focus SystemWindow] \
+ -selectforeground [list !focus SystemWindowText] \
+ -fieldbackground [list \
+ readonly SystemButtonFace \
+ disabled SystemButtonFace] \
+ -foreground [list \
+ disabled SystemGrayText \
+ {readonly focus} SystemHighlightText \
+ ] \
+ -focusfill [list {readonly focus} SystemHighlight] \
+ ;
+
+ ttk::style element create ComboboxPopdownFrame.border from default
+ ttk::style configure ComboboxPopdownFrame \
+ -borderwidth 1 -relief solid
+
+ ttk::style configure TSpinbox -padding {2 0 16 0}
+
+ ttk::style configure TLabelframe -borderwidth 2 -relief groove
+
+ ttk::style configure Toolbutton -relief flat -padding {8 4}
+ ttk::style map Toolbutton -relief \
+ {disabled flat selected sunken pressed sunken active raised}
+
+ ttk::style configure TScale -groovewidth 4
+
+ ttk::style configure TNotebook -tabmargins {2 2 2 0}
+ ttk::style configure TNotebook.Tab -padding {3 1} -borderwidth 1
+ ttk::style map TNotebook.Tab -expand [list selected {2 2 2 0}]
+
+ # Treeview:
+ ttk::style configure Heading -font TkHeadingFont -relief raised
+ ttk::style configure Treeview -background SystemWindow
+ ttk::style map Treeview \
+ -background [list disabled SystemButtonFace \
+ selected SystemHighlight] \
+ -foreground [list disabled SystemGrayText \
+ selected SystemHighlightText]
+
+ ttk::style configure TProgressbar \
+ -background SystemHighlight -borderwidth 0 ;
+ }
+}
diff --git a/tk8.6/library/ttk/xpTheme.tcl b/tk8.6/library/ttk/xpTheme.tcl
new file mode 100644
index 0000000..4c4f680
--- /dev/null
+++ b/tk8.6/library/ttk/xpTheme.tcl
@@ -0,0 +1,74 @@
+#
+# Settings for 'xpnative' theme
+#
+
+namespace eval ttk::theme::xpnative {
+
+ ttk::style theme settings xpnative {
+
+ ttk::style configure . \
+ -background SystemButtonFace \
+ -foreground SystemWindowText \
+ -selectforeground SystemHighlightText \
+ -selectbackground SystemHighlight \
+ -insertcolor SystemWindowText \
+ -font TkDefaultFont \
+ ;
+
+ ttk::style map "." \
+ -foreground [list disabled SystemGrayText] \
+ ;
+
+ ttk::style configure TButton -anchor center -padding {1 1} -width -11
+ ttk::style configure TRadiobutton -padding 2
+ ttk::style configure TCheckbutton -padding 2
+ ttk::style configure TMenubutton -padding {8 4}
+
+ ttk::style configure TNotebook -tabmargins {2 2 2 0}
+ ttk::style map TNotebook.Tab \
+ -expand [list selected {2 2 2 2}]
+
+ # Treeview:
+ ttk::style configure Heading -font TkHeadingFont
+ ttk::style configure Treeview -background SystemWindow
+ ttk::style map Treeview \
+ -background [list selected SystemHighlight] \
+ -foreground [list selected SystemHighlightText] ;
+
+ ttk::style configure TLabelframe.Label -foreground "#0046d5"
+
+ # OR: -padding {3 3 3 6}, which some apps seem to use.
+ ttk::style configure TEntry -padding {2 2 2 4}
+ ttk::style map TEntry \
+ -selectbackground [list !focus SystemWindow] \
+ -selectforeground [list !focus SystemWindowText] \
+ ;
+ ttk::style configure TCombobox -padding 2
+ ttk::style map TCombobox \
+ -selectbackground [list !focus SystemWindow] \
+ -selectforeground [list !focus SystemWindowText] \
+ -foreground [list \
+ disabled SystemGrayText \
+ {readonly focus} SystemHighlightText \
+ ] \
+ -focusfill [list {readonly focus} SystemHighlight] \
+ ;
+
+ ttk::style configure TSpinbox -padding {2 0 14 0}
+ ttk::style map TSpinbox \
+ -selectbackground [list !focus SystemWindow] \
+ -selectforeground [list !focus SystemWindowText] \
+ ;
+
+ ttk::style configure Toolbutton -padding {4 4}
+
+ # Treeview:
+ ttk::style configure Heading -font TkHeadingFont -relief raised
+ ttk::style configure Treeview -background SystemWindow
+ ttk::style map Treeview \
+ -background [list disabled SystemButtonFace \
+ selected SystemHighlight] \
+ -foreground [list disabled SystemGrayText \
+ selected SystemHighlightText];
+ }
+}
diff --git a/tk8.6/library/unsupported.tcl b/tk8.6/library/unsupported.tcl
new file mode 100644
index 0000000..b5f404a
--- /dev/null
+++ b/tk8.6/library/unsupported.tcl
@@ -0,0 +1,269 @@
+# unsupported.tcl --
+#
+# Commands provided by Tk without official support. Use them at your
+# own risk. They may change or go away without notice.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+# ----------------------------------------------------------------------
+# Unsupported compatibility interface for folks accessing Tk's private
+# commands and variable against recommended usage.
+# ----------------------------------------------------------------------
+
+namespace eval ::tk::unsupported {
+
+ # Map from the old global names of Tk private commands to their
+ # new namespace-encapsulated names.
+
+ variable PrivateCommands
+ array set PrivateCommands {
+ tkButtonAutoInvoke ::tk::ButtonAutoInvoke
+ tkButtonDown ::tk::ButtonDown
+ tkButtonEnter ::tk::ButtonEnter
+ tkButtonInvoke ::tk::ButtonInvoke
+ tkButtonLeave ::tk::ButtonLeave
+ tkButtonUp ::tk::ButtonUp
+ tkCancelRepeat ::tk::CancelRepeat
+ tkCheckRadioDown ::tk::CheckRadioDown
+ tkCheckRadioEnter ::tk::CheckRadioEnter
+ tkCheckRadioInvoke ::tk::CheckRadioInvoke
+ tkColorDialog ::tk::dialog::color::
+ tkColorDialog_BuildDialog ::tk::dialog::color::BuildDialog
+ tkColorDialog_CancelCmd ::tk::dialog::color::CancelCmd
+ tkColorDialog_Config ::tk::dialog::color::Config
+ tkColorDialog_CreateSelector ::tk::dialog::color::CreateSelector
+ tkColorDialog_DrawColorScale ::tk::dialog::color::DrawColorScale
+ tkColorDialog_EnterColorBar ::tk::dialog::color::EnterColorBar
+ tkColorDialog_InitValues ::tk::dialog::color::InitValues
+ tkColorDialog_HandleRGBEntry ::tk::dialog::color::HandleRGBEntry
+ tkColorDialog_HandleSelEntry ::tk::dialog::color::HandleSelEntry
+ tkColorDialog_LeaveColorBar ::tk::dialog::color::LeaveColorBar
+ tkColorDialog_MoveSelector ::tk::dialog::color::MoveSelector
+ tkColorDialog_OkCmd ::tk::dialog::color::OkCmd
+ tkColorDialog_RedrawColorBars ::tk::dialog::color::RedrawColorBars
+ tkColorDialog_RedrawFinalColor ::tk::dialog::color::RedrawFinalColor
+ tkColorDialog_ReleaseMouse ::tk::dialog::color::ReleaseMouse
+ tkColorDialog_ResizeColorBars ::tk::dialog::color::ResizeColorBars
+ tkColorDialog_RgbToX ::tk::dialog::color::RgbToX
+ tkColorDialog_SetRGBValue ::tk::dialog::color::SetRGBValue
+ tkColorDialog_StartMove ::tk::dialog::color::StartMove
+ tkColorDialog_XToRgb ::tk::dialog::color::XToRGB
+ tkConsoleAbout ::tk::ConsoleAbout
+ tkConsoleBind ::tk::ConsoleBind
+ tkConsoleExit ::tk::ConsoleExit
+ tkConsoleHistory ::tk::ConsoleHistory
+ tkConsoleInit ::tk::ConsoleInit
+ tkConsoleInsert ::tk::ConsoleInsert
+ tkConsoleInvoke ::tk::ConsoleInvoke
+ tkConsoleOutput ::tk::ConsoleOutput
+ tkConsolePrompt ::tk::ConsolePrompt
+ tkConsoleSource ::tk::ConsoleSource
+ tkDarken ::tk::Darken
+ tkEntryAutoScan ::tk::EntryAutoScan
+ tkEntryBackspace ::tk::EntryBackspace
+ tkEntryButton1 ::tk::EntryButton1
+ tkEntryClosestGap ::tk::EntryClosestGap
+ tkEntryGetSelection ::tk::EntryGetSelection
+ tkEntryInsert ::tk::EntryInsert
+ tkEntryKeySelect ::tk::EntryKeySelect
+ tkEntryMouseSelect ::tk::EntryMouseSelect
+ tkEntryNextWord ::tk::EntryNextWord
+ tkEntryPaste ::tk::EntryPaste
+ tkEntryPreviousWord ::tk::EntryPreviousWord
+ tkEntrySeeInsert ::tk::EntrySeeInsert
+ tkEntrySetCursor ::tk::EntrySetCursor
+ tkEntryTranspose ::tk::EntryTranspose
+ tkEventMotifBindings ::tk::EventMotifBindings
+ tkFDGetFileTypes ::tk::FDGetFileTypes
+ tkFirstMenu ::tk::FirstMenu
+ tkFocusGroup_BindIn ::tk::FocusGroup_BindIn
+ tkFocusGroup_BindOut ::tk::FocusGroup_BindOut
+ tkFocusGroup_Create ::tk::FocusGroup_Create
+ tkFocusGroup_Destroy ::tk::FocusGroup_Destroy
+ tkFocusGroup_In ::tk::FocusGroup_In
+ tkFocusGroup_Out ::tk::FocusGroup_Out
+ tkFocusOK ::tk::FocusOK
+ tkGenerateMenuSelect ::tk::GenerateMenuSelect
+ tkIconList ::tk::IconList
+ tkListbox ::tk::Listbox
+ tkListboxAutoScan ::tk::ListboxAutoScan
+ tkListboxBeginExtend ::tk::ListboxBeginExtend
+ tkListboxBeginSelect ::tk::ListboxBeginSelect
+ tkListboxBeginToggle ::tk::ListboxBeginToggle
+ tkListboxCancel ::tk::ListboxCancel
+ tkListboxDataExtend ::tk::ListboxDataExtend
+ tkListboxExtendUpDown ::tk::ListboxExtendUpDown
+ tkListboxKeyAccel_Goto ::tk::ListboxKeyAccel_Goto
+ tkListboxKeyAccel_Key ::tk::ListboxKeyAccel_Key
+ tkListboxKeyAccel_Reset ::tk::ListboxKeyAccel_Reset
+ tkListboxKeyAccel_Set ::tk::ListboxKeyAccel_Set
+ tkListboxKeyAccel_Unset ::tk::ListboxKeyAccel_Unxet
+ tkListboxMotion ::tk::ListboxMotion
+ tkListboxSelectAll ::tk::ListboxSelectAll
+ tkListboxUpDown ::tk::ListboxUpDown
+ tkListboxBeginToggle ::tk::ListboxBeginToggle
+ tkMbButtonUp ::tk::MbButtonUp
+ tkMbEnter ::tk::MbEnter
+ tkMbLeave ::tk::MbLeave
+ tkMbMotion ::tk::MbMotion
+ tkMbPost ::tk::MbPost
+ tkMenuButtonDown ::tk::MenuButtonDown
+ tkMenuDownArrow ::tk::MenuDownArrow
+ tkMenuDup ::tk::MenuDup
+ tkMenuEscape ::tk::MenuEscape
+ tkMenuFind ::tk::MenuFind
+ tkMenuFindName ::tk::MenuFindName
+ tkMenuFirstEntry ::tk::MenuFirstEntry
+ tkMenuInvoke ::tk::MenuInvoke
+ tkMenuLeave ::tk::MenuLeave
+ tkMenuLeftArrow ::tk::MenuLeftArrow
+ tkMenuMotion ::tk::MenuMotion
+ tkMenuNextEntry ::tk::MenuNextEntry
+ tkMenuNextMenu ::tk::MenuNextMenu
+ tkMenuRightArrow ::tk::MenuRightArrow
+ tkMenuUnpost ::tk::MenuUnpost
+ tkMenuUpArrow ::tk::MenuUpArrow
+ tkMessageBox ::tk::MessageBox
+ tkMotifFDialog ::tk::MotifFDialog
+ tkMotifFDialog_ActivateDList ::tk::MotifFDialog_ActivateDList
+ tkMotifFDialog_ActivateFList ::tk::MotifFDialog_ActivateFList
+ tkMotifFDialog_ActivateFEnt ::tk::MotifFDialog_ActivateFEnt
+ tkMotifFDialog_ActivateSEnt ::tk::MotifFDialog_ActivateSEnt
+ tkMotifFDialog ::tk::MotifFDialog
+ tkMotifFDialog_BrowseDList ::tk::MotifFDialog_BrowseDList
+ tkMotifFDialog_BrowseFList ::tk::MotifFDialog_BrowseFList
+ tkMotifFDialog_BuildUI ::tk::MotifFDialog_BuildUI
+ tkMotifFDialog_CancelCmd ::tk::MotifFDialog_CancelCmd
+ tkMotifFDialog_Config ::tk::MotifFDialog_Config
+ tkMotifFDialog_Create ::tk::MotifFDialog_Create
+ tkMotifFDialog_FileTypes ::tk::MotifFDialog_FileTypes
+ tkMotifFDialog_FilterCmd ::tk::MotifFDialog_FilterCmd
+ tkMotifFDialog_InterpFilter ::tk::MotifFDialog_InterpFilter
+ tkMotifFDialog_LoadFiles ::tk::MotifFDialog_LoadFiles
+ tkMotifFDialog_MakeSList ::tk::MotifFDialog_MakeSList
+ tkMotifFDialog_OkCmd ::tk::MotifFDialog_OkCmd
+ tkMotifFDialog_SetFilter ::tk::MotifFDialog_SetFilter
+ tkMotifFDialog_SetListMode ::tk::MotifFDialog_SetListMode
+ tkMotifFDialog_Update ::tk::MotifFDialog_Update
+ tkPostOverPoint ::tk::PostOverPoint
+ tkRecolorTree ::tk::RecolorTree
+ tkRestoreOldGrab ::tk::RestoreOldGrab
+ tkSaveGrabInfo ::tk::SaveGrabInfo
+ tkScaleActivate ::tk::ScaleActivate
+ tkScaleButtonDown ::tk::ScaleButtonDown
+ tkScaleButton2Down ::tk::ScaleButton2Down
+ tkScaleControlPress ::tk::ScaleControlPress
+ tkScaleDrag ::tk::ScaleDrag
+ tkScaleEndDrag ::tk::ScaleEndDrag
+ tkScaleIncrement ::tk::ScaleIncrement
+ tkScreenChanged ::tk::ScreenChanged
+ tkScrollButtonDown ::tk::ScrollButtonDown
+ tkScrollButton2Down ::tk::ScrollButton2Down
+ tkScrollButtonDrag ::tk::ScrollButtonDrag
+ tkScrollButtonUp ::tk::ScrollButtonUp
+ tkScrollByPages ::tk::ScrollByPages
+ tkScrollByUnits ::tk::ScrollByUnits
+ tkScrollEndDrag ::tk::ScrollEndDrag
+ tkScrollSelect ::tk::ScrollSelect
+ tkScrollStartDrag ::tk::ScrollStartDrag
+ tkScrollTopBottom ::tk::ScrollTopBottom
+ tkScrollToPos ::tk::ScrollToPos
+ tkTabToWindow ::tk::TabToWindow
+ tkTearOffMenu ::tk::TearOffMenu
+ tkTextAutoScan ::tk::TextAutoScan
+ tkTextButton1 ::tk::TextButton1
+ tkTextClosestGap ::tk::TextClosestGap
+ tkTextInsert ::tk::TextInsert
+ tkTextKeyExtend ::tk::TextKeyExtend
+ tkTextKeySelect ::tk::TextKeySelect
+ tkTextNextPara ::tk::TextNextPara
+ tkTextNextPos ::tk::TextNextPos
+ tkTextNextWord ::tk::TextNextWord
+ tkTextPaste ::tk::TextPaste
+ tkTextPrevPara ::tk::TextPrevPara
+ tkTextPrevPos ::tk::TextPrevPos
+ tkTextPrevWord ::tk::TextPrevWord
+ tkTextResetAnchor ::tk::TextResetAnchor
+ tkTextScrollPages ::tk::TextScrollPages
+ tkTextSelectTo ::tk::TextSelectTo
+ tkTextSetCursor ::tk::TextSetCursor
+ tkTextTranspose ::tk::TextTranspose
+ tkTextUpDownLine ::tk::TextUpDownLine
+ tkTraverseToMenu ::tk::TraverseToMenu
+ tkTraverseWithinMenu ::tk::TraverseWithinMenu
+ unsupported1 ::tk::unsupported::MacWindowStyle
+ }
+
+ # Map from the old global names of Tk private variable to their
+ # new namespace-encapsulated names.
+
+ variable PrivateVariables
+ array set PrivateVariables {
+ droped_to_start ::tk::mac::Droped_to_start
+ histNum ::tk::HistNum
+ stub_location ::tk::mac::Stub_location
+ tkFocusIn ::tk::FocusIn
+ tkFocusOut ::tk::FocusOut
+ tkPalette ::tk::Palette
+ tkPriv ::tk::Priv
+ tkPrivMsgBox ::tk::PrivMsgBox
+ }
+}
+
+# ::tk::unsupported::ExposePrivateCommand --
+#
+# Expose one of Tk's private commands to be visible under its
+# old global name
+#
+# Arguments:
+# cmd Global name by which the command was once known,
+# or a glob-style pattern.
+#
+# Results:
+# None.
+#
+# Side effects:
+# The old command name in the global namespace is aliased to the
+# new private name.
+
+proc ::tk::unsupported::ExposePrivateCommand {cmd} {
+ variable PrivateCommands
+ set cmds [array get PrivateCommands $cmd]
+ if {[llength $cmds] == 0} {
+ return -code error -errorcode {TK EXPOSE_PRIVATE_COMMAND} \
+ "No compatibility support for \[$cmd]"
+ }
+ foreach {old new} $cmds {
+ namespace eval :: [list interp alias {} $old {}] $new
+ }
+}
+
+# ::tk::unsupported::ExposePrivateVariable --
+#
+# Expose one of Tk's private variables to be visible under its
+# old global name
+#
+# Arguments:
+# var Global name by which the variable was once known,
+# or a glob-style pattern.
+#
+# Results:
+# None.
+#
+# Side effects:
+# The old variable name in the global namespace is aliased to the
+# new private name.
+
+proc ::tk::unsupported::ExposePrivateVariable {var} {
+ variable PrivateVariables
+ set vars [array get PrivateVariables $var]
+ if {[llength $vars] == 0} {
+ return -code error -errorcode {TK EXPOSE_PRIVATE_VARIABLE} \
+ "No compatibility support for \$$var"
+ }
+ namespace eval ::tk::mac {}
+ foreach {old new} $vars {
+ namespace eval :: [list upvar "#0" $new $old]
+ }
+}
diff --git a/tk8.6/library/xmfbox.tcl b/tk8.6/library/xmfbox.tcl
new file mode 100644
index 0000000..14d2be5
--- /dev/null
+++ b/tk8.6/library/xmfbox.tcl
@@ -0,0 +1,989 @@
+# xmfbox.tcl --
+#
+# Implements the "Motif" style file selection dialog for the
+# Unix platform. This implementation is used only if the
+# "::tk_strictMotif" flag is set.
+#
+# Copyright (c) 1996 Sun Microsystems, Inc.
+# Copyright (c) 1998-2000 Scriptics Corporation
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+namespace eval ::tk::dialog {}
+namespace eval ::tk::dialog::file {}
+
+
+# ::tk::MotifFDialog --
+#
+# Implements a file dialog similar to the standard Motif file
+# selection box.
+#
+# Arguments:
+# type "open" or "save"
+# args Options parsed by the procedure.
+#
+# Results:
+# When -multiple is set to 0, this returns the absolute pathname
+# of the selected file. (NOTE: This is not the same as a single
+# element list.)
+#
+# When -multiple is set to > 0, this returns a Tcl list of absolute
+# pathnames. The argument for -multiple is ignored, but for consistency
+# with Windows it defines the maximum amount of memory to allocate for
+# the returned filenames.
+
+proc ::tk::MotifFDialog {type args} {
+ variable ::tk::Priv
+ set dataName __tk_filedialog
+ upvar ::tk::dialog::file::$dataName data
+
+ set w [MotifFDialog_Create $dataName $type $args]
+
+ # Set a grab and claim the focus too.
+
+ ::tk::SetFocusGrab $w $data(sEnt)
+ $data(sEnt) selection range 0 end
+
+ # Wait for the user to respond, then restore the focus and
+ # return the index of the selected button. Restore the focus
+ # before deleting the window, since otherwise the window manager
+ # may take the focus away so we can't redirect it. Finally,
+ # restore any grab that was in effect.
+
+ vwait ::tk::Priv(selectFilePath)
+ set result $Priv(selectFilePath)
+ ::tk::RestoreFocusGrab $w $data(sEnt) withdraw
+
+ return $result
+}
+
+# ::tk::MotifFDialog_Create --
+#
+# Creates the Motif file dialog (if it doesn't exist yet) and
+# initialize the internal data structure associated with the
+# dialog.
+#
+# This procedure is used by ::tk::MotifFDialog to create the
+# dialog. It's also used by the test suite to test the Motif
+# file dialog implementation. User code shouldn't call this
+# procedure directly.
+#
+# Arguments:
+# dataName Name of the global "data" array for the file dialog.
+# type "Save" or "Open"
+# argList Options parsed by the procedure.
+#
+# Results:
+# Pathname of the file dialog.
+
+proc ::tk::MotifFDialog_Create {dataName type argList} {
+ upvar ::tk::dialog::file::$dataName data
+
+ MotifFDialog_Config $dataName $type $argList
+
+ if {$data(-parent) eq "."} {
+ set w .$dataName
+ } else {
+ set w $data(-parent).$dataName
+ }
+
+ # (re)create the dialog box if necessary
+ #
+ if {![winfo exists $w]} {
+ MotifFDialog_BuildUI $w
+ } elseif {[winfo class $w] ne "TkMotifFDialog"} {
+ destroy $w
+ MotifFDialog_BuildUI $w
+ } else {
+ set data(fEnt) $w.top.f1.ent
+ set data(dList) $w.top.f2.a.l
+ set data(fList) $w.top.f2.b.l
+ set data(sEnt) $w.top.f3.ent
+ set data(okBtn) $w.bot.ok
+ set data(filterBtn) $w.bot.filter
+ set data(cancelBtn) $w.bot.cancel
+ }
+ MotifFDialog_SetListMode $w
+
+ # Dialog boxes should be transient with respect to their parent,
+ # so that they will always stay on top of their parent window. However,
+ # some window managers will create the window as withdrawn if the parent
+ # window is withdrawn or iconified. Combined with the grab we put on the
+ # window, this can hang the entire application. Therefore we only make
+ # the dialog transient if the parent is viewable.
+
+ if {[winfo viewable [winfo toplevel $data(-parent)]] } {
+ wm transient $w $data(-parent)
+ }
+
+ MotifFDialog_FileTypes $w
+ MotifFDialog_Update $w
+
+ # Withdraw the window, then update all the geometry information
+ # so we know how big it wants to be, then center the window in the
+ # display (Motif style) and de-iconify it.
+
+ ::tk::PlaceWindow $w
+ wm title $w $data(-title)
+
+ return $w
+}
+
+# ::tk::MotifFDialog_FileTypes --
+#
+# Checks the -filetypes option. If present this adds a list of radio-
+# buttons to pick the file types from.
+#
+# Arguments:
+# w Pathname of the tk_get*File dialogue.
+#
+# Results:
+# none
+
+proc ::tk::MotifFDialog_FileTypes {w} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+
+ set f $w.top.f3.types
+ destroy $f
+
+ # No file types: use "*" as the filter and display no radio-buttons
+ if {$data(-filetypes) eq ""} {
+ set data(filter) *
+ return
+ }
+
+ # The filetypes radiobuttons
+ # set data(fileType) $data(-defaulttype)
+ # Default type to first entry
+ set initialTypeName [lindex $data(origfiletypes) 0 0]
+ if {$data(-typevariable) ne ""} {
+ upvar #0 $data(-typevariable) typeVariable
+ if {[info exists typeVariable]} {
+ set initialTypeName $typeVariable
+ }
+ }
+ set ix 0
+ set data(fileType) 0
+ foreach fltr $data(origfiletypes) {
+ set fname [lindex $fltr 0]
+ if {[string first $initialTypeName $fname] == 0} {
+ set data(fileType) $ix
+ break
+ }
+ incr ix
+ }
+
+ MotifFDialog_SetFilter $w [lindex $data(-filetypes) $data(fileType)]
+
+ #don't produce radiobuttons for only one filetype
+ if {[llength $data(-filetypes)] == 1} {
+ return
+ }
+
+ frame $f
+ set cnt 0
+ if {$data(-filetypes) ne {}} {
+ foreach type $data(-filetypes) {
+ set title [lindex $type 0]
+ set filter [lindex $type 1]
+ radiobutton $f.b$cnt \
+ -text $title \
+ -variable ::tk::dialog::file::[winfo name $w](fileType) \
+ -value $cnt \
+ -command [list tk::MotifFDialog_SetFilter $w $type]
+ pack $f.b$cnt -side left
+ incr cnt
+ }
+ }
+ $f.b$data(fileType) invoke
+
+ pack $f -side bottom -fill both
+
+ return
+}
+
+# This proc gets called whenever data(filter) is set
+#
+proc ::tk::MotifFDialog_SetFilter {w type} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+ variable ::tk::Priv
+
+ set data(filter) [lindex $type 1]
+ set Priv(selectFileType) [lindex [lindex $type 0] 0]
+
+ MotifFDialog_Update $w
+}
+
+# ::tk::MotifFDialog_Config --
+#
+# Iterates over the optional arguments to determine the option
+# values for the Motif file dialog; gives default values to
+# unspecified options.
+#
+# Arguments:
+# dataName The name of the global variable in which
+# data for the file dialog is stored.
+# type "Save" or "Open"
+# argList Options parsed by the procedure.
+
+proc ::tk::MotifFDialog_Config {dataName type argList} {
+ upvar ::tk::dialog::file::$dataName data
+
+ set data(type) $type
+
+ # 1: the configuration specs
+ #
+ set specs {
+ {-defaultextension "" "" ""}
+ {-filetypes "" "" ""}
+ {-initialdir "" "" ""}
+ {-initialfile "" "" ""}
+ {-parent "" "" "."}
+ {-title "" "" ""}
+ {-typevariable "" "" ""}
+ }
+ if {$type eq "open"} {
+ lappend specs {-multiple "" "" "0"}
+ }
+ if {$type eq "save"} {
+ lappend specs {-confirmoverwrite "" "" "1"}
+ }
+
+ set data(-multiple) 0
+ set data(-confirmoverwrite) 1
+ # 2: default values depending on the type of the dialog
+ #
+ if {![info exists data(selectPath)]} {
+ # first time the dialog has been popped up
+ set data(selectPath) [pwd]
+ set data(selectFile) ""
+ }
+
+ # 3: parse the arguments
+ #
+ tclParseConfigSpec ::tk::dialog::file::$dataName $specs "" $argList
+
+ if {$data(-title) eq ""} {
+ if {$type eq "open"} {
+ if {$data(-multiple) != 0} {
+ set data(-title) "[mc {Open Multiple Files}]"
+ } else {
+ set data(-title) [mc "Open"]
+ }
+ } else {
+ set data(-title) [mc "Save As"]
+ }
+ }
+
+ # 4: set the default directory and selection according to the -initial
+ # settings
+ #
+ if {$data(-initialdir) ne ""} {
+ if {[file isdirectory $data(-initialdir)]} {
+ set data(selectPath) [lindex [glob $data(-initialdir)] 0]
+ } else {
+ set data(selectPath) [pwd]
+ }
+
+ # Convert the initialdir to an absolute path name.
+
+ set old [pwd]
+ cd $data(selectPath)
+ set data(selectPath) [pwd]
+ cd $old
+ }
+ set data(selectFile) $data(-initialfile)
+
+ # 5. Parse the -filetypes option. It is not used by the motif
+ # file dialog, but we check for validity of the value to make sure
+ # the application code also runs fine with the TK file dialog.
+ #
+ set data(origfiletypes) $data(-filetypes)
+ set data(-filetypes) [::tk::FDGetFileTypes $data(-filetypes)]
+
+ if {![info exists data(filter)]} {
+ set data(filter) *
+ }
+ if {![winfo exists $data(-parent)]} {
+ return -code error -errorcode [list TK LOOKUP WINDOW $data(-parent)] \
+ "bad window path name \"$data(-parent)\""
+ }
+}
+
+# ::tk::MotifFDialog_BuildUI --
+#
+# Builds the UI components of the Motif file dialog.
+#
+# Arguments:
+# w Pathname of the dialog to build.
+#
+# Results:
+# None.
+
+proc ::tk::MotifFDialog_BuildUI {w} {
+ set dataName [lindex [split $w .] end]
+ upvar ::tk::dialog::file::$dataName data
+
+ # Create the dialog toplevel and internal frames.
+ #
+ toplevel $w -class TkMotifFDialog
+ set top [frame $w.top -relief raised -bd 1]
+ set bot [frame $w.bot -relief raised -bd 1]
+
+ pack $w.bot -side bottom -fill x
+ pack $w.top -side top -expand yes -fill both
+
+ set f1 [frame $top.f1]
+ set f2 [frame $top.f2]
+ set f3 [frame $top.f3]
+
+ pack $f1 -side top -fill x
+ pack $f3 -side bottom -fill x
+ pack $f2 -expand yes -fill both
+
+ set f2a [frame $f2.a]
+ set f2b [frame $f2.b]
+
+ grid $f2a -row 0 -column 0 -rowspan 1 -columnspan 1 -padx 4 -pady 4 \
+ -sticky news
+ grid $f2b -row 0 -column 1 -rowspan 1 -columnspan 1 -padx 4 -pady 4 \
+ -sticky news
+ grid rowconfigure $f2 0 -minsize 0 -weight 1
+ grid columnconfigure $f2 0 -minsize 0 -weight 1
+ grid columnconfigure $f2 1 -minsize 150 -weight 2
+
+ # The Filter box
+ #
+ bind [::tk::AmpWidget label $f1.lab -text [mc "Fil&ter:"] -anchor w] \
+ <<AltUnderlined>> [list focus $f1.ent]
+ entry $f1.ent
+ pack $f1.lab -side top -fill x -padx 6 -pady 4
+ pack $f1.ent -side top -fill x -padx 4 -pady 0
+ set data(fEnt) $f1.ent
+
+ # The file and directory lists
+ #
+ set data(dList) [MotifFDialog_MakeSList $w $f2a \
+ [mc "&Directory:"] DList]
+ set data(fList) [MotifFDialog_MakeSList $w $f2b \
+ [mc "Fi&les:"] FList]
+
+ # The Selection box
+ #
+ bind [::tk::AmpWidget label $f3.lab -text [mc "&Selection:"] -anchor w] \
+ <<AltUnderlined>> [list focus $f3.ent]
+ entry $f3.ent
+ pack $f3.lab -side top -fill x -padx 6 -pady 0
+ pack $f3.ent -side top -fill x -padx 4 -pady 4
+ set data(sEnt) $f3.ent
+
+ # The buttons
+ #
+ set maxWidth [::tk::mcmaxamp &OK &Filter &Cancel]
+ set maxWidth [expr {$maxWidth<6?6:$maxWidth}]
+ set data(okBtn) [::tk::AmpWidget button $bot.ok -text [mc "&OK"] \
+ -width $maxWidth \
+ -command [list tk::MotifFDialog_OkCmd $w]]
+ set data(filterBtn) [::tk::AmpWidget button $bot.filter -text [mc "&Filter"] \
+ -width $maxWidth \
+ -command [list tk::MotifFDialog_FilterCmd $w]]
+ set data(cancelBtn) [::tk::AmpWidget button $bot.cancel -text [mc "&Cancel"] \
+ -width $maxWidth \
+ -command [list tk::MotifFDialog_CancelCmd $w]]
+
+ pack $bot.ok $bot.filter $bot.cancel -padx 10 -pady 10 -expand yes \
+ -side left
+
+ # Create the bindings:
+ #
+ bind $w <Alt-Key> [list ::tk::AltKeyInDialog $w %A]
+
+ bind $data(fEnt) <Return> [list tk::MotifFDialog_ActivateFEnt $w]
+ bind $data(sEnt) <Return> [list tk::MotifFDialog_ActivateSEnt $w]
+ bind $w <Escape> [list tk::MotifFDialog_CancelCmd $w]
+ bind $w.bot <Destroy> {set ::tk::Priv(selectFilePath) {}}
+
+ wm protocol $w WM_DELETE_WINDOW [list tk::MotifFDialog_CancelCmd $w]
+}
+
+proc ::tk::MotifFDialog_SetListMode {w} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+
+ if {$data(-multiple) != 0} {
+ set selectmode extended
+ } else {
+ set selectmode browse
+ }
+ set f $w.top.f2.b
+ $f.l configure -selectmode $selectmode
+}
+
+# ::tk::MotifFDialog_MakeSList --
+#
+# Create a scrolled-listbox and set the keyboard accelerator
+# bindings so that the list selection follows what the user
+# types.
+#
+# Arguments:
+# w Pathname of the dialog box.
+# f Frame widget inside which to create the scrolled
+# listbox. This frame widget already exists.
+# label The string to display on top of the listbox.
+# under Sets the -under option of the label.
+# cmdPrefix Specifies procedures to call when the listbox is
+# browsed or activated.
+
+proc ::tk::MotifFDialog_MakeSList {w f label cmdPrefix} {
+ bind [::tk::AmpWidget label $f.lab -text $label -anchor w] \
+ <<AltUnderlined>> [list focus $f.l]
+ listbox $f.l -width 12 -height 5 -exportselection 0\
+ -xscrollcommand [list $f.h set] -yscrollcommand [list $f.v set]
+ scrollbar $f.v -orient vertical -takefocus 0 -command [list $f.l yview]
+ scrollbar $f.h -orient horizontal -takefocus 0 -command [list $f.l xview]
+ grid $f.lab -row 0 -column 0 -sticky news -rowspan 1 -columnspan 2 \
+ -padx 2 -pady 2
+ grid $f.l -row 1 -column 0 -rowspan 1 -columnspan 1 -sticky news
+ grid $f.v -row 1 -column 1 -rowspan 1 -columnspan 1 -sticky news
+ grid $f.h -row 2 -column 0 -rowspan 1 -columnspan 1 -sticky news
+
+ grid rowconfigure $f 0 -weight 0 -minsize 0
+ grid rowconfigure $f 1 -weight 1 -minsize 0
+ grid columnconfigure $f 0 -weight 1 -minsize 0
+
+ # bindings for the listboxes
+ #
+ set list $f.l
+ bind $list <<ListboxSelect>> [list tk::MotifFDialog_Browse$cmdPrefix $w]
+ bind $list <Double-ButtonRelease-1> \
+ [list tk::MotifFDialog_Activate$cmdPrefix $w]
+ bind $list <Return> "tk::MotifFDialog_Browse$cmdPrefix [list $w]; \
+ tk::MotifFDialog_Activate$cmdPrefix [list $w]"
+
+ bindtags $list [list Listbox $list [winfo toplevel $list] all]
+ ListBoxKeyAccel_Set $list
+
+ return $f.l
+}
+
+# ::tk::MotifFDialog_InterpFilter --
+#
+# Interpret the string in the filter entry into two components:
+# the directory and the pattern. If the string is a relative
+# pathname, give a warning to the user and restore the pattern
+# to original.
+#
+# Arguments:
+# w pathname of the dialog box.
+#
+# Results:
+# A list of two elements. The first element is the directory
+# specified # by the filter. The second element is the filter
+# pattern itself.
+
+proc ::tk::MotifFDialog_InterpFilter {w} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+
+ set text [string trim [$data(fEnt) get]]
+
+ # Perform tilde substitution
+ #
+ set badTilde 0
+ if {[string index $text 0] eq "~"} {
+ set list [file split $text]
+ set tilde [lindex $list 0]
+ if {[catch {set tilde [glob $tilde]}]} {
+ set badTilde 1
+ } else {
+ set text [eval file join [concat $tilde [lrange $list 1 end]]]
+ }
+ }
+
+ # If the string is a relative pathname, combine it
+ # with the current selectPath.
+
+ set relative 0
+ if {[file pathtype $text] eq "relative"} {
+ set relative 1
+ } elseif {$badTilde} {
+ set relative 1
+ }
+
+ if {$relative} {
+ tk_messageBox -icon warning -type ok \
+ -message "\"$text\" must be an absolute pathname"
+
+ $data(fEnt) delete 0 end
+ $data(fEnt) insert 0 [::tk::dialog::file::JoinFile $data(selectPath) \
+ $data(filter)]
+
+ return [list $data(selectPath) $data(filter)]
+ }
+
+ set resolved [::tk::dialog::file::JoinFile [file dirname $text] [file tail $text]]
+
+ if {[file isdirectory $resolved]} {
+ set dir $resolved
+ set fil $data(filter)
+ } else {
+ set dir [file dirname $resolved]
+ set fil [file tail $resolved]
+ }
+
+ return [list $dir $fil]
+}
+
+# ::tk::MotifFDialog_Update
+#
+# Load the files and synchronize the "filter" and "selection" fields
+# boxes.
+#
+# Arguments:
+# w pathname of the dialog box.
+#
+# Results:
+# None.
+
+proc ::tk::MotifFDialog_Update {w} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+
+ $data(fEnt) delete 0 end
+ $data(fEnt) insert 0 \
+ [::tk::dialog::file::JoinFile $data(selectPath) $data(filter)]
+ $data(sEnt) delete 0 end
+ $data(sEnt) insert 0 [::tk::dialog::file::JoinFile $data(selectPath) \
+ $data(selectFile)]
+
+ MotifFDialog_LoadFiles $w
+}
+
+# ::tk::MotifFDialog_LoadFiles --
+#
+# Loads the files and directories into the two listboxes according
+# to the filter setting.
+#
+# Arguments:
+# w pathname of the dialog box.
+#
+# Results:
+# None.
+
+proc ::tk::MotifFDialog_LoadFiles {w} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+
+ $data(dList) delete 0 end
+ $data(fList) delete 0 end
+
+ set appPWD [pwd]
+ if {[catch {cd $data(selectPath)}]} {
+ cd $appPWD
+
+ $data(dList) insert end ".."
+ return
+ }
+
+ # Make the dir and file lists
+ #
+ # For speed we only have one glob, which reduces the file system
+ # calls (good for slow NFS networks).
+ #
+ # We also do two smaller sorts (files + dirs) instead of one large sort,
+ # which gives a small speed increase.
+ #
+ set top 0
+ set dlist ""
+ set flist ""
+ foreach f [glob -nocomplain .* *] {
+ if {[file isdir ./$f]} {
+ lappend dlist $f
+ } else {
+ foreach pat $data(filter) {
+ if {[string match $pat $f]} {
+ if {[string match .* $f]} {
+ incr top
+ }
+ lappend flist $f
+ break
+ }
+ }
+ }
+ }
+ eval [list $data(dList) insert end] [lsort -dictionary $dlist]
+ eval [list $data(fList) insert end] [lsort -dictionary $flist]
+
+ # The user probably doesn't want to see the . files. We adjust the view
+ # so that the listbox displays all the non-dot files
+ $data(fList) yview $top
+
+ cd $appPWD
+}
+
+# ::tk::MotifFDialog_BrowseDList --
+#
+# This procedure is called when the directory list is browsed
+# (clicked-over) by the user.
+#
+# Arguments:
+# w The pathname of the dialog box.
+#
+# Results:
+# None.
+
+proc ::tk::MotifFDialog_BrowseDList {w} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+
+ focus $data(dList)
+ if {[$data(dList) curselection] eq ""} {
+ return
+ }
+ set subdir [$data(dList) get [$data(dList) curselection]]
+ if {$subdir eq ""} {
+ return
+ }
+
+ $data(fList) selection clear 0 end
+
+ set list [MotifFDialog_InterpFilter $w]
+ set data(filter) [lindex $list 1]
+
+ switch -- $subdir {
+ . {
+ set newSpec [::tk::dialog::file::JoinFile $data(selectPath) $data(filter)]
+ }
+ .. {
+ set newSpec [::tk::dialog::file::JoinFile [file dirname $data(selectPath)] \
+ $data(filter)]
+ }
+ default {
+ set newSpec [::tk::dialog::file::JoinFile [::tk::dialog::file::JoinFile \
+ $data(selectPath) $subdir] $data(filter)]
+ }
+ }
+
+ $data(fEnt) delete 0 end
+ $data(fEnt) insert 0 $newSpec
+}
+
+# ::tk::MotifFDialog_ActivateDList --
+#
+# This procedure is called when the directory list is activated
+# (double-clicked) by the user.
+#
+# Arguments:
+# w The pathname of the dialog box.
+#
+# Results:
+# None.
+
+proc ::tk::MotifFDialog_ActivateDList {w} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+
+ if {[$data(dList) curselection] eq ""} {
+ return
+ }
+ set subdir [$data(dList) get [$data(dList) curselection]]
+ if {$subdir eq ""} {
+ return
+ }
+
+ $data(fList) selection clear 0 end
+
+ switch -- $subdir {
+ . {
+ set newDir $data(selectPath)
+ }
+ .. {
+ set newDir [file dirname $data(selectPath)]
+ }
+ default {
+ set newDir [::tk::dialog::file::JoinFile $data(selectPath) $subdir]
+ }
+ }
+
+ set data(selectPath) $newDir
+ MotifFDialog_Update $w
+
+ if {$subdir ne ".."} {
+ $data(dList) selection set 0
+ $data(dList) activate 0
+ } else {
+ $data(dList) selection set 1
+ $data(dList) activate 1
+ }
+}
+
+# ::tk::MotifFDialog_BrowseFList --
+#
+# This procedure is called when the file list is browsed
+# (clicked-over) by the user.
+#
+# Arguments:
+# w The pathname of the dialog box.
+#
+# Results:
+# None.
+
+proc ::tk::MotifFDialog_BrowseFList {w} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+
+ focus $data(fList)
+ set data(selectFile) ""
+ foreach item [$data(fList) curselection] {
+ lappend data(selectFile) [$data(fList) get $item]
+ }
+ if {[llength $data(selectFile)] == 0} {
+ return
+ }
+
+ $data(dList) selection clear 0 end
+
+ $data(fEnt) delete 0 end
+ $data(fEnt) insert 0 [::tk::dialog::file::JoinFile $data(selectPath) \
+ $data(filter)]
+ $data(fEnt) xview end
+
+ # if it's a multiple selection box, just put in the filenames
+ # otherwise put in the full path as usual
+ $data(sEnt) delete 0 end
+ if {$data(-multiple) != 0} {
+ $data(sEnt) insert 0 $data(selectFile)
+ } else {
+ $data(sEnt) insert 0 [::tk::dialog::file::JoinFile $data(selectPath) \
+ [lindex $data(selectFile) 0]]
+ }
+ $data(sEnt) xview end
+}
+
+# ::tk::MotifFDialog_ActivateFList --
+#
+# This procedure is called when the file list is activated
+# (double-clicked) by the user.
+#
+# Arguments:
+# w The pathname of the dialog box.
+#
+# Results:
+# None.
+
+proc ::tk::MotifFDialog_ActivateFList {w} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+
+ if {[$data(fList) curselection] eq ""} {
+ return
+ }
+ set data(selectFile) [$data(fList) get [$data(fList) curselection]]
+ if {$data(selectFile) eq ""} {
+ return
+ } else {
+ MotifFDialog_ActivateSEnt $w
+ }
+}
+
+# ::tk::MotifFDialog_ActivateFEnt --
+#
+# This procedure is called when the user presses Return inside
+# the "filter" entry. It updates the dialog according to the
+# text inside the filter entry.
+#
+# Arguments:
+# w The pathname of the dialog box.
+#
+# Results:
+# None.
+
+proc ::tk::MotifFDialog_ActivateFEnt {w} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+
+ set list [MotifFDialog_InterpFilter $w]
+ set data(selectPath) [lindex $list 0]
+ set data(filter) [lindex $list 1]
+
+ MotifFDialog_Update $w
+}
+
+# ::tk::MotifFDialog_ActivateSEnt --
+#
+# This procedure is called when the user presses Return inside
+# the "selection" entry. It sets the ::tk::Priv(selectFilePath)
+# variable so that the vwait loop in tk::MotifFDialog will be
+# terminated.
+#
+# Arguments:
+# w The pathname of the dialog box.
+#
+# Results:
+# None.
+
+proc ::tk::MotifFDialog_ActivateSEnt {w} {
+ variable ::tk::Priv
+ upvar ::tk::dialog::file::[winfo name $w] data
+
+ set selectFilePath [string trim [$data(sEnt) get]]
+
+ if {$selectFilePath eq ""} {
+ MotifFDialog_FilterCmd $w
+ return
+ }
+
+ if {$data(-multiple) == 0} {
+ set selectFilePath [list $selectFilePath]
+ }
+
+ if {[file isdirectory [lindex $selectFilePath 0]]} {
+ set data(selectPath) [lindex [glob $selectFilePath] 0]
+ set data(selectFile) ""
+ MotifFDialog_Update $w
+ return
+ }
+
+ set newFileList ""
+ foreach item $selectFilePath {
+ if {[file pathtype $item] ne "absolute"} {
+ set item [file join $data(selectPath) $item]
+ } elseif {![file exists [file dirname $item]]} {
+ tk_messageBox -icon warning -type ok \
+ -message [mc {Directory "%1$s" does not exist.} \
+ [file dirname $item]]
+ return
+ }
+
+ if {![file exists $item]} {
+ if {$data(type) eq "open"} {
+ tk_messageBox -icon warning -type ok \
+ -message [mc {File "%1$s" does not exist.} $item]
+ return
+ }
+ } elseif {$data(type) eq "save" && $data(-confirmoverwrite)} {
+ set message [format %s%s \
+ [mc "File \"%1\$s\" already exists.\n\n" $selectFilePath] \
+ [mc {Replace existing file?}]]
+ set answer [tk_messageBox -icon warning -type yesno \
+ -message $message]
+ if {$answer eq "no"} {
+ return
+ }
+ }
+
+ lappend newFileList $item
+ }
+
+ # Return selected filter
+ if {[info exists data(-typevariable)] && $data(-typevariable) ne ""
+ && [info exists data(-filetypes)] && $data(-filetypes) ne ""} {
+ upvar #0 $data(-typevariable) typeVariable
+ set typeVariable [lindex $data(origfiletypes) $data(fileType) 0]
+ }
+
+ if {$data(-multiple) != 0} {
+ set Priv(selectFilePath) $newFileList
+ } else {
+ set Priv(selectFilePath) [lindex $newFileList 0]
+ }
+
+ # Set selectFile and selectPath to first item in list
+ set Priv(selectFile) [file tail [lindex $newFileList 0]]
+ set Priv(selectPath) [file dirname [lindex $newFileList 0]]
+}
+
+
+proc ::tk::MotifFDialog_OkCmd {w} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+
+ MotifFDialog_ActivateSEnt $w
+}
+
+proc ::tk::MotifFDialog_FilterCmd {w} {
+ upvar ::tk::dialog::file::[winfo name $w] data
+
+ MotifFDialog_ActivateFEnt $w
+}
+
+proc ::tk::MotifFDialog_CancelCmd {w} {
+ variable ::tk::Priv
+
+ set Priv(selectFilePath) ""
+ set Priv(selectFile) ""
+ set Priv(selectPath) ""
+}
+
+proc ::tk::ListBoxKeyAccel_Set {w} {
+ bind Listbox <Any-KeyPress> ""
+ bind $w <Destroy> [list tk::ListBoxKeyAccel_Unset $w]
+ bind $w <Any-KeyPress> [list tk::ListBoxKeyAccel_Key $w %A]
+}
+
+proc ::tk::ListBoxKeyAccel_Unset {w} {
+ variable ::tk::Priv
+
+ catch {after cancel $Priv(lbAccel,$w,afterId)}
+ unset -nocomplain Priv(lbAccel,$w) Priv(lbAccel,$w,afterId)
+}
+
+# ::tk::ListBoxKeyAccel_Key--
+#
+# This procedure maintains a list of recently entered keystrokes
+# over a listbox widget. It arranges an idle event to move the
+# selection of the listbox to the entry that begins with the
+# keystrokes.
+#
+# Arguments:
+# w The pathname of the listbox.
+# key The key which the user just pressed.
+#
+# Results:
+# None.
+
+proc ::tk::ListBoxKeyAccel_Key {w key} {
+ variable ::tk::Priv
+
+ if { $key eq "" } {
+ return
+ }
+ append Priv(lbAccel,$w) $key
+ ListBoxKeyAccel_Goto $w $Priv(lbAccel,$w)
+ catch {
+ after cancel $Priv(lbAccel,$w,afterId)
+ }
+ set Priv(lbAccel,$w,afterId) [after 500 \
+ [list tk::ListBoxKeyAccel_Reset $w]]
+}
+
+proc ::tk::ListBoxKeyAccel_Goto {w string} {
+ variable ::tk::Priv
+
+ set string [string tolower $string]
+ set end [$w index end]
+ set theIndex -1
+
+ for {set i 0} {$i < $end} {incr i} {
+ set item [string tolower [$w get $i]]
+ if {[string compare $string $item] >= 0} {
+ set theIndex $i
+ }
+ if {[string compare $string $item] <= 0} {
+ set theIndex $i
+ break
+ }
+ }
+
+ if {$theIndex >= 0} {
+ $w selection clear 0 end
+ $w selection set $theIndex $theIndex
+ $w activate $theIndex
+ $w see $theIndex
+ event generate $w <<ListboxSelect>>
+ }
+}
+
+proc ::tk::ListBoxKeyAccel_Reset {w} {
+ variable ::tk::Priv
+
+ unset -nocomplain Priv(lbAccel,$w)
+}
+
+proc ::tk_getFileType {} {
+ variable ::tk::Priv
+
+ return $Priv(selectFileType)
+}
+
diff --git a/tk8.6/license.terms b/tk8.6/license.terms
new file mode 100644
index 0000000..0126435
--- /dev/null
+++ b/tk8.6/license.terms
@@ -0,0 +1,40 @@
+This software is copyrighted by the Regents of the University of
+California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState
+Corporation, Apple Inc. and other parties. The following terms apply to
+all files associated with the software unless explicitly disclaimed in
+individual files.
+
+The authors hereby grant 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 THE AUTHORS OR DISTRIBUTORS 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 THE AUTHORS HAVE BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+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 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 (b) (3) 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.
diff --git a/tk8.6/macosx/GNUmakefile b/tk8.6/macosx/GNUmakefile
new file mode 100644
index 0000000..d0bab1a
--- /dev/null
+++ b/tk8.6/macosx/GNUmakefile
@@ -0,0 +1,315 @@
+########################################################################################################
+#
+# Makefile wrapper to build tk on Mac OS X in a way compatible with the tk/macosx Xcode buildsystem
+# uses the standard unix build system in tk/unix (which can be used directly instead of this
+# if you are not using the tk/macosx projects).
+#
+# Copyright (c) 2002-2008 Daniel A. Steffen <das@users.sourceforge.net>
+#
+# See the file "license.terms" for information on usage and redistribution of
+# this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+########################################################################################################
+
+#-------------------------------------------------------------------------------------------------------
+# customizable settings
+
+DESTDIR ?=
+INSTALL_ROOT ?= ${DESTDIR}
+
+BUILD_DIR ?= ${CURDIR}/../../build
+SYMROOT ?= ${BUILD_DIR}/${PROJECT}
+OBJROOT ?= ${SYMROOT}
+
+EXTRA_CONFIGURE_ARGS ?=
+EXTRA_MAKE_ARGS ?=
+
+INSTALL_PATH ?= /Library/Frameworks
+APPLICATION_INSTALL_PATH ?= /Applications/Utilities
+PREFIX ?= /usr/local
+BINDIR ?= ${PREFIX}/bin
+LIBDIR ?= ${INSTALL_PATH}
+MANDIR ?= ${PREFIX}/man
+
+# tcl build directory (containing tclConfig.sh and Makefile)
+TCL_BUILD_DIR ?= ${BUILD_DIR}/tcl/${BUILD_STYLE}
+# location of installed tcl, only used if tcl in TCL_BUILD_DIR can't be found
+TCL_FRAMEWORK_DIR ?= /Library/Frameworks
+TCLSH_DIR ?= ${PREFIX}/bin
+
+# set to non-empty value to install manpages in addition to html help:
+INSTALL_MANPAGES ?=
+
+# set to non-empty value to build TkX11 instead of TkAqua:
+TK_X11 ?=
+
+#-------------------------------------------------------------------------------------------------------
+# meta targets
+
+meta := all install embedded install-embedded clean distclean test
+
+styles := develop deploy
+
+all := ${styles}
+all : ${all}
+
+install := ${styles:%=install-%}
+install : ${install}
+install-%: action := install-
+
+embedded := ${styles:%=embedded-%}
+embedded : embedded-deploy
+install-embedded := ${embedded:%=install-%}
+install-embedded : install-embedded-deploy
+
+clean := ${styles:%=clean-%}
+clean : ${clean}
+clean-%: action := clean-
+distclean := ${styles:%=distclean-%}
+distclean : ${distclean}
+distclean-%: action := distclean-
+
+test := ${styles:%=test-%}
+test : ${test}
+test-%: action := test-
+
+targets := $(foreach v,${meta},${$v})
+
+#-------------------------------------------------------------------------------------------------------
+# build styles
+
+BUILD_STYLE =
+CONFIGURE_ARGS =
+OBJ_DIR = ${OBJROOT}/${BUILD_STYLE}
+
+empty :=
+space := ${empty} ${empty}
+objdir = $(subst ${space},\ ,${OBJ_DIR})
+
+develop_make_args := BUILD_STYLE=Development CONFIGURE_ARGS=--enable-symbols
+deploy_make_args := BUILD_STYLE=Deployment INSTALL_TARGET=install-strip
+embedded_make_args := EMBEDDED_BUILD=1
+install_make_args := INSTALL_BUILD=1
+
+${targets}:
+ ${MAKE} ${action}${PROJECT} \
+ $(foreach s,${styles} embedded install,$(if $(findstring $s,$@),${${s}_make_args}))
+
+#-------------------------------------------------------------------------------------------------------
+# project specific settings
+
+PROJECT := tk
+PRODUCT_NAME := Tk
+
+UNIX_DIR := ${CURDIR}/../unix
+VERSION := $(shell awk -F= '/^TK_VERSION/ {print $$2; nextfile}' ${UNIX_DIR}/configure.in)
+TCL_VERSION := ${VERSION}
+wish := wish
+WISH = wish${VERSION}
+
+BUILD_TARGET := all tktest
+INSTALL_TARGET := install
+
+ifneq ($(wildcard $(subst ${space},\ ,${TCL_BUILD_DIR})/tclConfig.sh),)
+TCL_DIR := ${TCL_BUILD_DIR}
+TCL_FRAMEWORK_DIR := ${TCL_BUILD_DIR}/..
+MAKE_VARS :=
+else
+TCL_DIR := ${TCL_FRAMEWORK_DIR}/Tcl.framework
+TCL_EXE := ${TCLSH_DIR}/tclsh${TCL_VERSION}
+MAKE_VARS := TCL_EXE
+export DYLD_FRAMEWORK_PATH := ${TCL_FRAMEWORK_DIR}
+endif
+
+export CPPROG := cp -p
+
+ifeq (${TK_X11},)
+override CONFIGURE_ARGS := ${CONFIGURE_ARGS} --enable-aqua
+else
+override CONFIGURE_ARGS := ${CONFIGURE_ARGS} --enable-xft
+VERSION := ${VERSION}-X11
+wish := ${wish}-X11
+override EMBEDDED_BUILD :=
+endif
+
+INSTALL_TARGETS = install-binaries install-libraries
+ifeq (${EMBEDDED_BUILD},)
+INSTALL_TARGETS += install-private-headers install-headers install-demos
+endif
+ifeq (${INSTALL_BUILD}_${EMBEDDED_BUILD}_${BUILD_STYLE},1__Deployment)
+INSTALL_TARGETS += html-tk
+ifneq (${INSTALL_MANPAGES},)
+INSTALL_TARGETS += install-doc
+endif
+endif
+
+MAKE_VARS += INSTALL_ROOT INSTALL_TARGETS VERSION
+MAKE_ARGS_V = $(foreach v,${MAKE_VARS},$v='${$v}')
+
+build-${PROJECT}: target = ${BUILD_TARGET}
+install-${PROJECT}: target = ${INSTALL_TARGET}
+clean-${PROJECT} distclean-${PROJECT} test-${PROJECT}: \
+ target = $*
+
+DO_MAKE = +${MAKE} -C "${OBJ_DIR}" ${target} ${MAKE_ARGS_V} ${MAKE_ARGS} ${EXTRA_MAKE_ARGS}
+
+#-------------------------------------------------------------------------------------------------------
+# locations for custom tk install actions
+
+ifeq (${INSTALL_BUILD},1)
+TOP_DIR := ${INSTALL_ROOT}/
+APP_DIR := ${APPLICATION_INSTALL_PATH}
+FMWK_DIR := ${LIBDIR}
+else
+TOP_DIR := ${SYMROOT}
+APP_DIR := .
+FMWK_DIR := .
+endif
+
+TCL_FMWK_DIR := ${FMWK_DIR}/Tcl.framework/Versions/${TCL_VERSION}
+TK_FMWK_DIR := ${FMWK_DIR}/${PRODUCT_NAME}.framework/Versions/${VERSION}
+
+#-------------------------------------------------------------------------------------------------------
+# build rules
+
+${PROJECT}:
+ ${MAKE} install-${PROJECT} INSTALL_ROOT="${OBJ_DIR}/"
+
+${objdir}/Makefile: ${UNIX_DIR}/Makefile.in ${UNIX_DIR}/configure \
+ ${UNIX_DIR}/tkConfig.sh.in Tk-Info.plist.in Wish-Info.plist.in
+ mkdir -p "${OBJ_DIR}" && cd "${OBJ_DIR}" && \
+ if [ ${UNIX_DIR}/configure -nt config.status ]; then ${UNIX_DIR}/configure -C \
+ --prefix="${PREFIX}" --bindir="${BINDIR}" --libdir="${LIBDIR}" \
+ --mandir="${MANDIR}" --enable-threads --enable-framework \
+ --with-tcl="${TCL_DIR}" \
+ ${CONFIGURE_ARGS} ${EXTRA_CONFIGURE_ARGS}; else ./config.status; fi
+ifneq (${VERSION},${TCL_VERSION})
+ @cd "${OBJ_DIR}" && sed -e 's#/Versions/${TCL_VERSION}#/Versions/${VERSION}#' \
+ tkConfig.sh > tkConfig.sh.1 && mv -f tkConfig.sh.1 tkConfig.sh
+endif
+
+build-${PROJECT}: ${objdir}/Makefile
+ ${DO_MAKE}
+ifeq (${INSTALL_BUILD},)
+# symolic link hackery to trick
+# 'make install INSTALL_ROOT=${OBJ_DIR}'
+# into building Tk.framework and wish in ${SYMROOT}
+ @cd "${OBJ_DIR}" && mkdir -p $(dir $(subst ${space},\ ,./${LIBDIR})) $(dir $(subst ${space},\ ,./${BINDIR})) "${SYMROOT}" && \
+ rm -rf "./${LIBDIR}" "./${BINDIR}" && ln -fs "${SYMROOT}" "./${LIBDIR}" && \
+ ln -fs "${SYMROOT}" "./${BINDIR}" && ln -fs "${OBJ_DIR}/tktest" "${SYMROOT}"
+ifeq (${TK_X11},)
+ @rm -f "${OBJ_DIR}/${BINDIR}" && \
+ ln -fs Wish.app/Contents/MacOS/Wish "${SYMROOT}/${WISH}"
+endif
+# Create symbolic link to Tcl.framework in ${SYMROOT}if necessary
+ @cd "${SYMROOT}" && if [ ! -e Tcl.framework -o -L Tcl.framework ]; then \
+ rm -f Tcl.framework && ln -s "${TCL_FRAMEWORK_DIR}/Tcl.framework" . ; fi
+endif
+
+install-${PROJECT}: build-${PROJECT}
+ifeq (${EMBEDDED_BUILD}_${INSTALL_ROOT},1_)
+ @echo "Cannot install-embedded with empty INSTALL_ROOT !" && false
+endif
+ifeq (${EMBEDDED_BUILD},1)
+ @rm -rf "${INSTALL_ROOT}/${LIBDIR}/Tk.framework"
+endif
+ ${DO_MAKE}
+ifeq (${EMBEDDED_BUILD}_${TK_X11},1_)
+# workaround bug with 'cp -pRH' on Darwin 6 and earlier
+ @if [ "`uname -r | awk -F. '{print $$1}'`" -lt 7 ]; then \
+ mkdir -p "${TOP_DIR}"/{"${TCL_FMWK_DIR}","${TK_FMWK_DIR}"}/PrivateHeaders; fi
+endif
+ifeq (${INSTALL_BUILD},1)
+ifeq (${EMBEDDED_BUILD},1)
+# if we are embedding frameworks, don't install wish
+ @rm -f "${INSTALL_ROOT}${BINDIR}/${WISH}" && \
+ rmdir -p "${INSTALL_ROOT}${BINDIR}" 2>&- || true
+else
+# redo prebinding (when not building for Mac OS X 10.4 or later only)
+ @if [ "`echo "$${MACOSX_DEPLOYMENT_TARGET}" | \
+ awk -F '10\\.' '{print int($$2)}'`" -lt 4 -a "`echo "$${CFLAGS}" | \
+ awk -F '-mmacosx-version-min=10\\.' '{print int($$2)}'`" -lt 4 ]; \
+ then cd ${INSTALL_ROOT}/; \
+ if [ ! -d usr/lib ]; then mkdir -p usr && ln -fs /usr/lib usr/ && RM_USRLIB=1; fi; \
+ if [ -n "${TK_X11}" -a ! -d usr/X11R6 ]; then mkdir -p usr && ln -fs /usr/X11R6 usr/ && RM_USRX11=1; fi; \
+ if [ ! -d System ]; then ln -fs /System . && RM_SYSTEM=1; fi; \
+ if [ ! -d "./${LIBDIR}/Tcl.framework" ]; then ln -fs "${TCL_FRAMEWORK_DIR}/Tcl.framework" "./${LIBDIR}"; RM_TCL=1; fi; \
+ redo_prebinding -r . "./${TK_FMWK_DIR}/${PRODUCT_NAME}"; \
+ if [ -z "${TK_X11}" ]; then redo_prebinding -r . "./${TK_FMWK_DIR}/Resources/Wish.app/Contents/MacOS/Wish"; \
+ else redo_prebinding -r . "./${BINDIR}/${WISH}"; fi; \
+ if [ -n "$${RM_USRLIB:-}" ]; then rm -f usr/lib; rmdir -p usr 2>&-; fi; \
+ if [ -n "$${RM_USRX11:-}" ]; then rm -f usr/X11R6; rmdir -p usr 2>&-; fi; \
+ if [ -n "$${RM_SYSTEM:-}" ]; then rm -f System; fi; \
+ if [ -n "$${RM_TCL:-}" ]; then rm -f "./${LIBDIR}/Tcl.framework"; fi; fi
+# install wish symbolic link
+ @ln -fs ${WISH} "${INSTALL_ROOT}${BINDIR}/${wish}"
+endif
+endif
+ifeq (${BUILD_STYLE}_${EMBEDDED_BUILD},Development_)
+# keep copy of debug library around, so that
+# Deployment build can be installed on top
+# of Development build without overwriting
+# the debug library
+ @cd "${INSTALL_ROOT}${LIBDIR}/${PRODUCT_NAME}.framework/Versions/${VERSION}" && \
+ ln -f "${PRODUCT_NAME}" "${PRODUCT_NAME}_debug"
+endif
+ifeq (${TK_X11},)
+ifeq (${EMBEDDED_BUILD},)
+# install Wish.app link in APPLICATION_INSTALL_PATH and setup 'Wish Shell' compatibility links
+ @cd "${TOP_DIR}" && if [ -n "${APP_DIR}" ]; then mkdir -p "./${APP_DIR}" && rm -rf "./${APP_DIR}/Wish.app" && \
+ ln -fsh "./$$(echo "${APP_DIR}" | sed -e 's#/[^/][^/]*#/..#g')/${FMWK_DIR}/${PRODUCT_NAME}.framework/Resources/Wish.app" "./${APP_DIR}" && \
+ ln -fsh Wish.app "./${APP_DIR}/Wish Shell.app"; fi && \
+ ln -fsh Wish.app "./${TK_FMWK_DIR}/Resources/Wish Shell.app" && \
+ ln -fsh Wish "./${TK_FMWK_DIR}/Resources/Wish.app/Contents/MacOS/Wish Shell"
+else
+# if we are embedding frameworks, move them into the app and fix their install names
+ @cd "${TOP_DIR}" && \
+ rm -rf "./${APP_DIR}/Wish.app" && mkdir -p "./${APP_DIR}" && \
+ mv -f "./${TK_FMWK_DIR}/Resources/Wish.app" "./${APP_DIR}" && \
+ ln -fsh Wish.app "./${APP_DIR}/Wish Shell.app" && \
+ rm -rf "./${APP_DIR}/Wish.app/Contents/Frameworks" && \
+ mkdir -p "./${APP_DIR}/Wish.app/Contents/Frameworks" && \
+ ${CPPROG} -RH "./${FMWK_DIR}"/T{cl,k}.framework "./${APP_DIR}/Wish.app/Contents/Frameworks" && \
+ cd "./${APP_DIR}/Wish.app/Contents" && \
+ rm -rf Frameworks/Tcl.framework/{,/Versions/${TCL_VERSION}}/{Headers,PrivateHeaders,*_debug,lib*.a,*Config.sh} && \
+ rm -rf Frameworks/Tk.framework/{,/Versions/${VERSION}}/{Headers,PrivateHeaders,*_debug,lib*.a,*Config.sh} && \
+ fix_install_id ( ) { \
+ chmod -RH a+w "$$1"; \
+ install_name_tool -id $$(otool -L "$$1" | awk "/$$2\.framework.*[^:]\$$/ {sub(\"^.*/Frameworks\",\"@executable_path/../Frameworks\",\$$1); print \$$1}") "$$1"; \
+ chmod -RH a-w "$$1"; \
+ } && \
+ fix_install_name ( ) { \
+ chmod -RH a+w "$$1"; \
+ install_name_tool -change $$(otool -L "$$1" | awk "/$$2\.framework.*[^:]\$$/ {print \$$1; sub(\"^.*/Frameworks\",\"@executable_path/../Frameworks\",\$$1); print \$$1}") "$$1"; \
+ chmod -RH a-w "$$1"; \
+ } && \
+ fix_install_id Frameworks/Tcl.framework/Tcl Tcl && fix_install_id Frameworks/Tk.framework/Tk Tk && \
+ fix_install_name MacOS/Wish Tcl && fix_install_name MacOS/Wish Tk
+ifeq (${INSTALL_BUILD},1)
+ @cd "${TOP_DIR}" && rm -rf "./${FMWK_DIR}"/T{cl,k}.framework && rmdir -p "./${FMWK_DIR}" 2>&- || true
+endif
+endif
+endif
+
+clean-${PROJECT}: %-${PROJECT}:
+ ${DO_MAKE}
+ rm -rf "${SYMROOT}"/{${PRODUCT_NAME}.framework,${WISH},tktest}
+ rm -f "${OBJ_DIR}"{"${LIBDIR}","${BINDIR}"} && \
+ rmdir -p "${OBJ_DIR}"$(dir $(subst ${space},\ ,${LIBDIR})) 2>&- || true && \
+ rmdir -p "${OBJ_DIR}"$(dir $(subst ${space},\ ,${BINDIR})) 2>&- || true
+
+distclean-${PROJECT}: %-${PROJECT}: clean-${PROJECT}
+ ${DO_MAKE}
+ rm -rf "${OBJ_DIR}"
+
+test-${PROJECT}: %-${PROJECT}: build-${PROJECT}
+ ${DO_MAKE}
+
+#-------------------------------------------------------------------------------------------------------
+
+.PHONY: ${meta} ${targets} ${PROJECT} build-${PROJECT} install-${PROJECT} \
+ clean-${PROJECT} distclean-${PROJECT}
+
+.NOTPARALLEL:
+
+#-------------------------------------------------------------------------------------------------------
diff --git a/tk8.6/macosx/README b/tk8.6/macosx/README
new file mode 100644
index 0000000..7df4893
--- /dev/null
+++ b/tk8.6/macosx/README
@@ -0,0 +1,725 @@
+Tcl/Tk macOS README
+----------------------
+
+This is the README file for the macOS/Darwin version of Tcl/Tk.
+
+1. Where to go for support
+--------------------------
+
+- The tcl-mac mailing list on sourceforge is the best place to ask questions
+specific to Tcl & Tk on macOS:
+ http://lists.sourceforge.net/lists/listinfo/tcl-mac
+(this page also has a link to searchable archives of the list, please check them
+before asking on the list, many questions have already been answered).
+
+- For general Tcl/Tk questions, the newsgroup comp.lang.tcl is your best bet:
+ http://groups.google.com/group/comp.lang.tcl/
+
+- The Tcl'ers Wiki also has many pages dealing with Tcl & Tk on macOS, see
+ http://wiki.tcl.tk/_/ref?N=3753
+ http://wiki.tcl.tk/_/ref?N=8361
+
+- Please report bugs with Tk on macOS to the tracker:
+ http://core.tcl.tk/tk/reportlist
+
+2. Using Tcl/Tk on macOS
+---------------------------
+
+- There are two versions of Tk available on macOS: TkAqua using the native
+aqua widgets and look&feel, and TkX11 using the traditional unix X11 widgets.
+TkX11 requires an X11 server to be installed, such as Apple's X11 (which is
+available as an optional or default install on recent macOS).
+TkAqua and TkX11 can be distinguished at runtime via [tk windowingsystem].
+
+- At a minimum, macOS 10.3 is required to run Tcl and TkX11.
+TkAqua requires macOS 10.6 or later.
+
+- Unless weak-linking is used, Tcl/Tk built on macOS 10.x will not run on
+10.y with y < x; on the other hand Tcl/Tk built on 10.y will always run on 10.x
+with y <= x (but without any of the fixes and optimizations that would be
+available in a binary built on 10.x).
+Weak-linking is available on OS X 10.2 or later, it additionally allows Tcl/Tk
+built on 10.x to run on any 10.y with x > y >= z (for a chosen z >= 2).
+
+- Wish checks the Resources/Scripts directory in its application bundle for a
+file called AppMain.tcl, if found it is used as the startup script and the
+Scripts folder is added to the auto_path. This can be used to emulate the old
+OS9 TclTk droplets.
+
+- If standard input is a special file of zero length (e.g. /dev/null), Wish
+brings up the Tk console window at startup. This is the case when double
+clicking Wish in the Finder (or using 'open Wish.app' from the Terminal).
+
+- Tcl extensions can be installed in any of:
+ $HOME/Library/Tcl /Library/Tcl /System/Library/Tcl
+ $HOME/Library/Frameworks /Library/Frameworks /System/Library/Frameworks
+ (searched in that order).
+Given a potential package directory $pkg, Tcl on OSX checks for the file
+$pkg/Resources/Scripts/pkgIndex.tcl as well as the usual $pkg/pkgIndex.tcl.
+This allows building extensions as frameworks with all script files contained in
+the Resources/Scripts directory of the framework.
+
+- The 'deploy' target of macosx/GNUmakefile installs the html manpages into the
+standard documentation location in the Tcl/Tk frameworks:
+ Tcl.framework/Resources/Documentation/Reference/Tcl
+ Tk.framework/Resources/Documentation/Reference/Tk
+No nroff manpages are installed by default by the GNUmakefile.
+
+- The Tcl and Tk frameworks can be installed in any of the system's standard
+framework directories:
+ $HOME/Library/Frameworks /Library/Frameworks /System/Library/Frameworks
+
+- ${prefix}/bin/wish8.x is a script that calls a copy of 'Wish' contained in
+ Tk.framework/Resources
+
+- if 'Wish' is started from the Finder or via 'open', $argv may contain a
+"-psn_XXXX" argument. This is the process serial number, you may need to filter
+it out for cross platform compatibility of your scripts.
+
+- the env array is different when Wish is started from the Finder (i.e. via
+LaunchServices) than when it (or tclsh) is invoked from the Terminal, in
+particular PATH may not be what you expect. (Wish started by LaunchServices
+inherits loginwindow's environment variables, which are essentially those set in
+$HOME/.MacOSX/environment.plist, and are unrelated to those set in your shell).
+
+- TkAqua provides access to native OS X images via the Tk native bitmap facility
+(including any image file readable by NSImage). A native bitmap name is
+interpreted as follows (in order):
+ - predefined builtin 32x32 icon name (stop, caution, document, etc)
+ - name defined by [tk::mac::iconBitmap]
+ - NSImage named image name
+ - NSImage url string
+ - 4-char OSType of IconServices icon
+the syntax of [tk::mac::iconBitmap] is as follows:
+ tk::mac::iconBitmap name width height -kind value
+where -kind is one of
+ -file icon of file at given path
+ -fileType icon of given file type
+ -osType icon of given 4-char OSType file type
+ -systemType icon for given IconServices 4-char OSType
+ -namedImage named NSImage for given name
+ -imageFile image at given path
+This support was added with the Cocoa-based Tk 8.5.7.
+
+- TkAqua cursor names are interpred as follows (in order):
+ - standard or platform-specific Tk cursor name (c.f. cursors.n)
+ - @path to any image file readable by NSImage
+ - NSImage named image name
+Support for the latter two was added with the Cocoa-based Tk 8.5.7.
+
+- The standard Tk dialog commands [tk_getOpenFile], [tk_chooseDirectory],
+[tk_getSaveFile] and [tk_messageBox] all take an additional optional -command
+parameter on TkAqua. If it is present, the given command prefix is evaluated at
+the global level when the dialog closes, with the dialog command's result
+appended (the dialog command itself returning an emtpy result). If the -parent
+option is also present, the dialog is configured as a modeless (window-modal)
+sheet attached to the parent window and the dialog command returns immediately.
+Support for -command was added with the Cocoa-based Tk 8.5.7.
+
+- The TkAqua-specific [tk::mac::standardAboutPanel] command brings the standard
+Cocoa about panel to the front, with all its information filled in from your
+application bundle files (i.e. standard about panel with no options specified).
+See Apple Technote TN2179 and the AppKit documentation for -[NSApplication
+orderFrontStandardAboutPanelWithOptions:] for details on the Info.plist keys and
+app bundle files used by the about panel.
+This support was added with the Cocoa-based Tk 8.5.7.
+
+- TkAqua has three special menu names that give access to the standard
+Application, Window and Help menus, see menu.n for details. By default, the
+platform-specific standard Help menu item "YourApp Help" performs the default
+Cocoa action of showing the Help Book configured in the application's
+Info.plist (or displaying an alert if no Help Book is set). This action can be
+customized by defining a procedure named [tk::mac::ShowHelp]. If present, this
+procedure is invoked instead by the standard Help menu item. Support for the
+Window menu and [tk::mac::ShowHelp] was added with the Cocoa-based Tk 8.5.7.
+
+- The TkAqua-specific command [tk::unsupported::MacWindowStyle style] is used to
+get and set macOS-specific toplevel window class and attributes. Note that
+the window class and many attributes have to be set before the window is first
+mapped for the change to have any effect.
+The command has the following syntax:
+ tk::unsupported::MacWindowStyle style window ?class? ?attributes?
+The 2 argument form returns a list of the current class and attributes for the
+given window. The 3 argument form sets the class for the given window using the
+default attributes for that class. The 4 argument form sets the class and the
+list of attributes for the given window.
+Window class names:
+ document, modal, floating, utility, toolbar, simple, help, overlay
+Window attribute names:
+ standardDocument, standardFloating, resizable, fullZoom, horizontalZoom,
+ verticalZoom, closeBox, collapseBox, toolbarButton, sideTitlebar,
+ noTitleBar, unifiedTitleAndToolbar, metal, hud, noShadow, doesNotCycle,
+ noActivates, hideOnSuspend, inWindowMenu, ignoreClicks, doesNotHide,
+ canJoinAllSpaces, moveToActiveSpace, nonActivating
+
+Note that not all attributes are valid for all window classes. Support for the
+3 argument form was added with the Cocoa-based Tk 8.5.7, at the same time
+support for some legacy Carbon-specific classes and attributes was removed
+(they are still accepted by the command but no longer have any effect).
+
+- Another command available in the tk::unsupported::MacWindowStyle namespace is:
+ tk::unsupported::MacWindowStyle tabbingid window ?newId?
+which can be used to get or set the tabbingIdentifier for the NSWindow
+associated with a Tk Window. See section 3 for details.
+
+- The command:
+ tk::unsupported::MacWindowStyle appearance window ?newAppearance?
+is available when Tk is built and run on macOS 10.14 (Mojave) or later. In
+that case the Ttk widgets all support the "Dark Mode" appearance which was
+introduced in 10.14. The command accepts the following values for the optional
+newAppearance option: "aqua", "darkaqua", or "auto". If the appearance is set
+to aqua or darkaqua then the window will be displayed with the corresponding
+appearance independent of any preferences settings. If it is set to "auto"
+the appearance will be determined by the preferences. This command can be
+used to opt out of Dark Mode on a per-window basis.
+
+- To determine the current appearance of a window in macOS 10.14 (Mojave) and
+higher, one can use the command:
+ tk::unsupported::MacWindowStyle isdark
+The boolean return value is true if the window is currently displayed with the
+dark appearance.
+
+- If you want to use Remote Debugging with Xcode, you need to set the
+environment variable XCNOSTDIN to 1 in the Executable editor for Wish. That will
+cause us to force closing stdin & stdout. Otherwise, given how Xcode launches
+Wish remotely, they will be left open and then Wish & gdb will fight for stdin.
+
+3. FullScreen, Split View and Tabbed Windows
+--------------------------------------------
+
+Since the release of OSX 10.6 (Snow Leopard) a steadily expanding sequence of
+high level window operations have been added to Apple's window manager. These
+operations are launched by user actions which are handled directly by the
+window manager; they are not initiated by the application. In some, but not
+all cases, the application is notified before and after the operations are
+carried out.
+
+In OSX releases up to and including 10.6 there were three buttons with
+stoplight colors located on the left side of a window's title bar. The
+function of the green button was to "zoom" or "maximize" the window, i.e. to
+expand the window so that it fills the entire screen, while preserving the
+appearance of the window including its title bar. The release of OSX 10.7
+(Lion) introduced the "FullScreen" window which not only filled the screen but
+also hid the window's title bar and the menu bar which normally appears at the
+top of the screen. These hidden objects would only become visible when the
+mouse hovered near the top of the screen. FullScreen mode was initiated by
+pressing a button showing two outward pointing arrows located on the right side
+of the title bar; it was terminated by pressing a similar button with inward
+pointing arrows on the right hand side of the menu bar. In OSX 10.10
+(Yosemite) the FullScreen button was removed. The green button was repurposed
+to cause a window to become a FullScreen window. To zoom a window the user had
+to hold down the option key while pressing the green button. The release of
+OSX 10.11 added a third function to the green button: to create two half-screen
+windows with hidden title bars and a hidden menu bar, called Split View
+windows. If the green button is held down for one second its window expands to
+fill half of the screen. It can be moved to one side or the other with the
+mouse. The opposite side shows thumbnail images of other windows. Selecting
+one of the thumbnails expands its window to fill that half of the screen. The
+divider between the two windows can be moved to adjust the percentage of the
+screen occupied by each of the two tiles. In OSX 10.12 (Sierra) Tabbed windows
+were introduced. These allow an application with multiple windows to display
+its windows as tabs within a single window frame. Clicking on a tab brings its
+window into view. Tabs can be rearranged by dragging. Dragging a tab to the
+desktop turns it into a separate window. Items in the Window menu can be used
+to cycle through the tabs, move tabbed windows to separate windows, or merge a
+set of separate windows as tabs in the same window frame.
+
+Tk now fully supports all of these high level window operations on any system
+where the operation exists. The FullScreen and Split View windows are handled
+automatically with no action required on the part of the programmer. Tabbed
+windows, on the other hand, require some attention from the programmer.
+Because many of the operations with tabs are handled through the application's
+Window menu, it is essential that an application provide a Windows menu to
+avoid presenting a confusing interface to the user. This cannot be ignored, in
+part because the systemwide Dock Preferences offers an option to always attempt
+to open application windows as tabs. An application which does not provide a
+Window menu will necessarily present a confusing interface to any user who has
+selected this option.
+
+A further complication is that it is not neccessarily appropriate for all of an
+application's windows to be grouped together as tabs in the same frame. In
+fact, the Apple guidelines insist that windows which are grouped together as
+tabs should be similar to each other. The mechanism provided for arranging
+this was to assign to each NSwindow a tabbingIdentifier, and to require that
+all windows grouped together as tabs in the same window frame must have the
+same tabbingIdentifier. A tabbingIdentifier is implemented as an arbitrary
+string, and a system-generated default tabbingIdentifier is provided to all new
+windows.
+
+Tk provides a means for getting and setting the tabbingIdentifier of
+the NSWindow underlying a Tk Window. This is handled by the command
+
+tk::unsupported::MacWindowStyle tabbingid window ?newId?
+
+(This command generates an error if used on OSX 10.11 or earlier, since the
+tabbingIdentifier does not exist on those systems.) The command returns the
+tabbingIdentifier which had been assigned to the window prior to execution of
+the command. If the optional newId argument is omitted, the window's
+tabbingIdentifier is not changed. Otherwise it is set to the string specified
+by the argument.
+
+Since NSWindows can only be grouped together as tabs if they all have the same
+tabbingIdentifier, one can prevent a window from becoming a tab by giving it a
+unique tabbingIdentifier. This is independent of any preferences setting. To
+ensure that we maintain consistency, changing the tabbingIdentifier of a window
+which is already displayed as a tab will also cause it to become a separate
+window.
+
+4. Ttk, Dark Mode and semantic colors
+---------------------------------------
+
+With the release of OSX 10.14 (Mojave), Apple introduced the DarkAqua
+appearance. Part of the implementation of the Dark Mode was to make
+some of the named NSColors have dynamic values. Apple calls these
+"semantic colors" because the name does not specify a specific color,
+but rather refers to the context in which the color should be used.
+Tk now provides the following semantic colors as system colors:
+systemTextColor, systemTextBackgroundColor, systemSelectedTextColor,
+systemSelectedTextBackgroundColor, systemControlTextColor,
+systemDisabledControlTextColor, systemLabelColor, and
+systemControlAccentColor. All of these except the last two were
+present in OSX 10.0 (and those two are simulated in systems where they
+do not exist). The change in 10.14 was that the RGB color value of
+these colors became dynamic, meaning that the color value can change
+when the application appearance changes. In particular, when a user
+selects Dark Mode in the system preferences these colors change
+appearance. For example systemTextColor is dark in Aqua and light in
+DarkAqua. One additional color, systemSelectedTabTextColor, does not
+exist in macOS but is used by Tk to match the different colors used
+for Notebook tab text in different OS versions.
+
+The default background and foreground colors of most of the Tk widgets
+have been set to semantic colors, which means that the widgets will change
+appearance, and remain usable, when Dark Mode is selected in the system
+preferences. However, to get a close match to the native Dark Mode style it
+is recommended to use Ttk widgets when possible.
+
+Apple's tab view and GroupBox objects delimit their content by
+displaying it within a rounded rectangle with a background color that
+contrasts with the background of the containing object. This means
+that the background color of a Ttk widget depends on how deeply it is
+nested inside of other widgets that use contrasting backgrounds. To
+support this, there are 8 contrasting system colors named
+systemWindowBackgroundColor, and systemWindowBackgroundColor1 - 7.
+The systemWindowBackgroundColor is the standard background for a
+dialog window and the others match the contrasting background colors
+used in ttk::notebooks and ttk::labelframes which are nested to the
+corresponding depth.
+
+5. Building Tcl/Tk on macOS
+------------------------------
+
+- macOS 10.6 is required to build TkAqua and TkX11. The XCode application provides everything needed to build Tk, but it is not necessary to install the full XCode.
+It suffices to install the Command Line Tools package, which can be done
+by running the command:
+xcode-select --install
+
+- Tcl/Tk are most easily built as macOS frameworks via GNUmakefile in
+tcl/macosx and tk/macosx (see below for details), but can also be built with the
+standard unix configure and make buildsystem in tcl/unix resp. tk/unix as on any
+other unix platform (indeed, the GNUmakefiles are just wrappers around the unix
+buildsystem).
+The macOS specific configure flags are --enable-aqua, --enable-framework and
+--disable-corefoundation (which disables CF and notably reverts to the standard
+select based notifier). Note that --enable-aqua is incompatible with
+--disable-corefoundation (for both Tcl and Tk configure).
+
+- It was once possible to build with the Xcode IDE via the projects in
+tk/macosx, but this has not been tested recently. Take care to use the
+project matching your DevTools and OS version:
+ Tk.xcode: for Xcode 3.1 on 10.5
+ Tk.xcodeproj: for Xcode 3.2 on 10.6
+These have the following targets:
+ Tk: calls through to tk/macosx/GNUMakefile,
+ requires a corresponding build of the Tcl
+ target of tcl/macosx/Tcl.xcode.
+ tktest: static build of TkAqua tktest for debugging.
+ tktest-X11: static build of TkX11 tktest for debugging.
+The following build configurations are available:
+ Debug: debug build for the active architecture,
+ with Fix & Continue enabled.
+ Debug clang: use clang compiler.
+ Debug llvm-gcc: use llvm-gcc compiler.
+ Debug gcc40: use gcc 4.0 compiler.
+ DebugNoGC: disable Objective-C garbage collection.
+ DebugNoFixAndContinue: disable Fix & Continue.
+ DebugUnthreaded: disable threading.
+ DebugNoCF: disable corefoundation (X11 only).
+ DebugNoCFUnthreaded: disable corefoundation an threading.
+ DebugMemCompile: enable memory and bytecode debugging.
+ DebugLeaks: define PURIFY.
+ DebugGCov: enable generation of gcov data files.
+ Debug64bit: configure with --enable-64bit (requires
+ building on a 64bit capable processor).
+ Release: release build for the active architecture.
+ ReleaseUniversal: 32/64-bit universal build.
+ ReleaseUniversal clang: use clang compiler.
+ ReleaseUniversal llvm-gcc: use llvm-gcc compiler.
+ ReleaseUniversal gcc40: use gcc 4.0 compiler.
+ ReleaseUniversal10.5SDK: build against the 10.5 SDK (with 10.5
+ deployment target).
+ Note that the non-SDK configurations have their deployment target set to
+ 10.5 (Tk.xcode) resp. 10.6 (Tk.xcodeproj).
+The Xcode projects refer to the toplevel tcl and tk source directories via the
+the TCL_SRCROOT and TK_SRCROOT user build settings, by default these are set to
+the project-relative paths '../../tcl' and '../../tk', if your source
+directories are named differently, e.g. '../../tcl8.6' and '../../tk8.6', you
+need to manually change the TCL_SRCROOT and TK_SRCROOT settings by editing your
+${USER}.pbxuser file (located inside the Tk.xcodeproj bundle directory) with a
+text editor.
+
+- To enable weak-linking, set the MACOSX_DEPLOYMENT_TARGET environment variable
+to the minimal OS version the binaries should be able to run on, e.g:
+ export MACOSX_DEPLOYMENT_TARGET=10.6
+This requires at least gcc 3.1; with gcc 4 or later, set/add to CFLAGS instead:
+ export CFLAGS="-mmacosx-version-min=10.6"
+Support for weak-linking was added with 8.4.14/8.5a5.
+
+Detailed Instructions for building with macosx/GNUmakefile
+----------------------------------------------------------
+
+- Unpack the Tcl and Tk source release archives and place the tcl and tk source
+trees in a common parent directory.
+[ If you don't want have the two source trees in one directory, you'll need to ]
+[ create the following symbolic link for the build to work as setup by default ]
+[ ln -fs /path_to_tcl/build /path_to_tk/build ]
+[ (where /path_to_{tcl,tk} is the directory containing the tcl resp. tk tree) ]
+[ or you can pass an argument of BUILD_DIR=/somewhere to the tcl and tk make. ]
+
+- The following instructions assume the Tcl and Tk source trees are named
+"tcl${ver}" and "tk${ver}" (where ${ver} is a shell variable containing the
+Tcl/Tk version number, e.g. '8.6').
+Setup this shell variable as follows:
+ ver="8.6"
+If you are building from CVS, omit this step (CVS source tree names usually do
+not contain a version number).
+
+- Setup environment variables as desired, e.g. for a universal build on 10.5:
+ CFLAGS="-arch i386 -arch x86_64 -arch ppc -mmacosx-version-min=10.5"
+ export CFLAGS
+
+- Change to the directory containing the Tcl and Tk source trees and build:
+ make -C tcl${ver}/macosx
+ make -C tk${ver}/macosx
+
+- Install Tcl and Tk onto the root volume (admin password required):
+ sudo make -C tcl${ver}/macosx install
+ sudo make -C tk${ver}/macosx install
+if you don't have an admin password, you can install into your home directory
+instead by passing an INSTALL_ROOT argument to make:
+ make -C tcl${ver}/macosx install INSTALL_ROOT="${HOME}/"
+ make -C tk${ver}/macosx install INSTALL_ROOT="${HOME}/"
+
+- The default GNUmakefile targets will build _both_ debug and optimized versions
+of the Tcl and Tk frameworks with the standard convention of naming the debug
+library Tcl.framework/Tcl_debug resp. Tk.framework/Tk_debug.
+This allows switching to the debug libraries at runtime by setting
+ export DYLD_IMAGE_SUFFIX=_debug
+(c.f. man dyld for more details)
+
+If you only want to build and install the debug or optimized build, use the
+'develop' or 'deploy' target variants of the GNUmakefile, respectively.
+For example, to build and install only the optimized versions:
+ make -C tcl${ver}/macosx deploy
+ make -C tk${ver}/macosx deploy
+ sudo make -C tcl${ver}/macosx install-deploy
+ sudo make -C tk${ver}/macosx install-deploy
+
+- The GNUmakefile can also build a version of Wish.app that has the Tcl and Tk
+frameworks embedded in its application package. This allows for standalone
+deployment of the application with no installation required, e.g. from read-only
+media. To build & install in this manner, use the 'embedded' variants of
+the GNUmakefile targets.
+For example, to build a standalone 'Wish.app' in ./emb/Applications/Utilities:
+ make -C tcl${ver}/macosx embedded
+ make -C tk${ver}/macosx embedded
+ sudo make -C tcl${ver}/macosx install-embedded INSTALL_ROOT=`pwd`/emb/
+ sudo make -C tk${ver}/macosx install-embedded INSTALL_ROOT=`pwd`/emb/
+Notes:
+ * if you've already built standard TclTkAqua, building embedded does not
+ require any new compiling or linking, so you can skip the first two makes.
+ (making relinking unnecessary was added with 8.4.2)
+ * the embedded frameworks include only optimized builds and no documentation.
+ * the standalone Wish has the directory Wish.app/Contents/lib in its
+ auto_path. Thus you can place tcl extensions in this directory (i.e. embed
+ them in the app package) and load them with [package require].
+
+- It is possible to build Tk against an installed Tcl.framework; but you will
+still need a tcl sourcetree in the location specified in TCL_SRC_DIR in
+Tcl.framework/tclConfig.sh. Also, linking with Tcl.framework has to work exactly
+as indicated in TCL_LIB_SPEC in Tcl.framework/tclConfig.sh.
+If you used non-default install locations for Tcl.framework, specify them as
+make overrides to the tk/macosx GNUmakefile, e.g.
+ make -C tk${ver}/macosx \
+ TCL_FRAMEWORK_DIR=$HOME/Library/Frameworks TCLSH_DIR=$HOME/usr/bin
+ sudo make -C tk${ver}/macosx install \
+ TCL_FRAMEWORK_DIR=$HOME/Library/Frameworks TCLSH_DIR=$HOME/usr/bin
+The Makefile variables TCL_FRAMEWORK_DIR and TCLSH_DIR were added with Tk 8.4.3.
+
+5. Details regarding the macOS port of Tk.
+-------------------------------------------
+
+5.1 About the event loop
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+The main program in a typical OSX application looks like this (see
+https://developer.apple.com/library/mac/documentation/Cocoa/\
+Reference/ApplicationKit/Classes/NSApplication_Class)
+
+ void NSApplicationMain(int argc, char *argv[]) {
+ [NSApplication sharedApplication];
+ [NSBundle loadNibNamed:@"myMain" owner:NSApp];
+ [NSApp run];
+ }
+Here NSApp is a standard global variable, initialized by the OS, which
+points to an object in a subclass of NSApplication (called
+TKApplication in the case of the macOS port of Tk).
+
+The [NSApp run] method implements the event loop for a typical Mac
+application. There are three key steps in the run method. First it
+calls [NSApp finishLaunching], which creates the bouncing application
+icon and does other mysterious things. Second it creates an
+NSAutoreleasePool. Third, it starts an event loop which drains the
+NSAutoreleasePool every time the queue is empty, and replaces the
+drained pool with a new one. This third step is essential to
+preventing memory leaks, since the internal methods of Appkit objects
+all assume that an autorelease pool is in scope and will be drained
+when the event processing cycle ends.
+
+The macOS Tk application does not call the [NSApp run] method at
+all. Instead it uses the event loop built in to Tk. So the
+application must take care to replicate the important features of the
+method ourselves. The way that autorelease pools are handled is
+discussed in 5.2 below. Here we discuss the event handling itself.
+
+The Tcl event loop simply consists of repeated calls to TclDoOneEvent.
+Each call to TclDoOneEvent begins by collecting all pending events from
+an "event source", converting them to Tcl events and adding them
+to the Tcl event queue. For macOS, the event source is the NSApp
+object, which maintains an event queue even though its run method
+will never be called to process them. The NSApp provides methods for
+inspecting the queue and removing events from it as well as the
+[NSApp sendevent] which sends an event to all of the application's
+NSWindows which can then send it to subwindows, etc.
+
+The event collection process consists of first calling a platform
+specific SetupProc and then a platform specific CheckProc. In
+the macOS port, these are named TkMacOSXEventsSetupProc and
+TkMacOSXEventsCheckProc.
+
+It is important to understand that the Apple window manager does not
+have the concept of an expose event. Their replacement for an expose
+event is to have the window manager call the [NSView drawRect] method
+in any situation where an expose event for that NSView would be
+generated in X11. The [NSView drawRect] method is a no-op which is
+expected to be overridden by any application. In the case of Tcl, the
+replacement [NSView drawRect] method creates a Tcl expose event
+for each dirty rectangle of the NSView, and then adds the expose
+event to the Tcl queue.
+
+
+5.2 Autorelease pools
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In order to carry out the job of managing autorelease pools, which
+would normally be handled by the [NSApp run] method, a private
+NSAutoreleasePool* property is added to the TkApplication subclass of
+NSApplication. The TkpInit function calls [NSApp _setup] which
+initializes this property by creating an NSAutoreleasePool prior to
+calling [NSApp finishLaunching]. This mimics the behavior of the
+[NSApp run] method, which calls [NSApp finishLaunching] just before
+starting the event loop.
+
+Since the CheckProc function gets called for every Tk event, it is an
+appropriate place to drain the main NSAutoreleasePool and replace it
+with a new pool. This is done by calling the method [NSApp
+_resetAutoreleasePool], where _resetAutoreleasePool is a method which
+we define for the subclass. Unfortunately, by itself this is not
+sufficient for safe memory managememt because, as was made painfully
+evident with the release of OS X 10.13, it is possible for calls to
+TclDoOneEvent, and hence to CheckProc, to be nested. Draining the
+autorelease pool in a nested call leads to crashes as objects in use
+by the outer call can get freed by the inner call and then reused later.
+One particular situation where this happens is when a modal dialogue
+gets posted by a Tk Application. To address this, the NSApp object
+also implements a semaphore to prevent draining the autorelease pool
+in nested calls to CheckProc.
+
+One additional minor caveat for developers is that there are several
+steps of the Tk initialization which precede the call to TkpInit.
+Notably, the font package is initialized first. Since there is no
+NSAutoreleasePool in scope prior to calling TkpInit, the functions
+called in these preliminary stages need to create and drain their own
+NSAutoreleasePools whenever they call methods of Appkit objects
+(e.g. NSFont).
+
+5.3 Clipping regions and "ghost windows"
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Another unusual aspect of the macOS port is its use of clipping
+regions. It was part of Daniel Steffen's original design that the
+TkWindowPrivate struct maintains three HIShapeRef regions, named
+visRgn, aboveVisRgn and drawRgn. These regions are used as clipping
+masks whenever drawing into an NSView. The visRgn is the bounding box
+of the window with a rectangle removed for each subwindow and for each
+sibling window at a higher stacking level. The drawRgn is the
+intersection of the visRgn with the clipping rectangle of the
+window. (Normally, the clipping rectangle is the same as the bounding
+rectangle, but drawing can be clipped to a smaller rectangle by
+calling TkpClipDrawableToRect.) The aboveVisRgn is the intersection of
+the window's bounding rectangle with the bounding rectangle of the
+parent window. Much of the code in tkMacOSXSubwindows.c is devoted to
+rebuilding these clipping regions whenever something changes in the
+layout of the windows. This turns out to be a tricky thing to do and
+it is extremely prone to errors which can be difficult to trace.
+
+It is not entirely clear what the original reason for using these
+clipping regions was. But one benefit is that if they are correctly
+maintained then it allows windows to be drawn in any order. You do
+not have to draw them in the order of the window hierarchy. Each
+window can draw its entire rectangle through its own mask and never
+have to worry about drawing in the wrong place. It is likely that
+the need for using clipping regions arose because, as Apple explicitly
+states in the documentation for [NSView subviews],
+
+ "The order of the subviews may be considered as being
+ back-to-front, but this does not imply invalidation and drawing
+ behavior."
+
+In the early versions of the macOS port, buttons were implemented as
+subviews of class TkButton. This probably exacerbated the likelihood
+that Tk windows would need to be drawn in arbitrary order.
+
+The most obvious side effect caused by not maintaining the clipping
+regions is the appearance of so-called "ghost windows". A common
+situation where these may arise is when a window containing buttons
+is being scrolled. A user may see two images of the same button on
+the screen, one in the pre-scroll location and one in the post-scroll
+location.
+
+To see how these 'ghost windows' can arise, think about what happens if
+the clipping regions are not maintained correctly. A window might
+have a rectangle missing from its clipping region because that
+rectangle is the bounding rectangle for a subwindow, say a button.
+The parent should not draw in the missing rectangle since doing so
+would trash the button. The button is responsible for drawing
+there. Now imagine that the button gets moved, say by a scroll, but
+the missing rectangle in the parent's clipping region does not get
+moved correctly, or it gets moved later on, after the parent has
+redrawn itself. The parent would still not be allowed to draw in the
+old rectangle, so the user would continue to see the image of the
+button in its old location, as well as another image in the new
+location. This is a prototypical example of a "ghost window".
+Anytime you see a "ghost window", you should suspect problems with the
+updates to the clipping region visRgn. It is natural to look for
+timing issues, race conditions, or other "event loop problems". But
+in fact, the whole design of the code is to make those timing issues
+irrelevant. As long as the clipping regions are correctly maintained
+the timing does not matter. And if they are not correctly maintained
+then you will see "ghost windows".
+
+It is worth including a detailed description of one specific place
+where the failure to correctly maintain clipping regions caused "ghost
+window" artifacts that plagued the macOS port for years. These
+occurred when scrolling a Text widget which contained embedded
+subwindows. It involved some specific differences between the
+low-level behavior of Apple's window manager versus those of the other
+platforms, and the fix ultimately required changes in the generic Tk
+implementation (documented in the comments in the DisplayText
+function).
+
+The Text widget attempts to improve perfomance when scrolling by
+minimizing the number of text lines which need to be redisplayed. It
+does this by calling the platform-specific TkScrollWindow function
+which uses a low-level routine to map one rectangle of the window to
+another. The TkScrollWindow function returns a damage region which is
+then used by the Text widget's DisplayText function to determine which
+text lines need to be redrawn. On the unix and win platforms, this
+damage region includes bounding rectangles for all embedded windows
+inside the Text widget. The way that this works is system dependent.
+On unix, the low level scrolling is done by XCopyRegion, which
+generates a GraphicsExpose event for each embedded window. These
+GraphicsExposed events are processsed within TkScrollWindow, using a
+special handler which adds the bounding rectangle of each subwindow to
+the damage region. On the win platform the damage region is built by
+the low level function ScrollWindowEx, and it also includes bounding
+rectangles for all embedded windows. This is possible because on X11
+and Windows every Tk widget is also known to the window manager as a
+window. The situation is different on macOS. The underlying object
+for a top level window on macOS is the NSView. However, Apple
+explicitly warns in its documentation that performance degradation
+occurs when an NSView has more than about 100 subviews. A Text widget
+with thousands of lines of text could easily contain more than 100
+embedded windows. In fact, while the original Cocoa port of Tk did
+use the NSButton object, which is derived from NSView, as the basis
+for its Tk Buttons, that was changed in order to improve performance.
+Moreover, the low level routine used for scrolling on macOS, namely
+[NSView scrollrect:by], does not provide any damage information. So
+TkScrollWindow needs to work differently on macOS. Since it would be
+inefficient to iterate through all embedded windows in a Text widget,
+looking for those which meet the scrolling area, the damage region
+constructed by TkScrollWindow contains only the difference between the
+source and destination rectangles for the scrolling. The embedded
+windows are redrawn within the DisplayText function by some
+conditional code which is only used for macOS.
+
+6.0 Virtual events on 10.14
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+10.14 supports system appearance changes, and has added a "Dark Mode"
+that casts all window frames and menus as black. Tk 8.6.9 has added two
+virtual events, <<LightAqua>> and <<DarkAqua>>, to allow you to update
+your Tk app's appearance when the system appearance changes. Just bind
+your appearance-updating code to these virtual events and you will see
+it triggered when the system appearance toggles between dark and light.
+
+7.0 Mac Services
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+With 8.6.10, Tk supports the Mac's NSServices API, documented at
+https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/SysServices/introduction.html#//apple_ref/doc/uid/10000101-SW1
+and in TIP 536 and Tk's man page. Tk presents a simple,
+straightforward API to implement the Services functionality.
+
+The Tk implementation of the NSServices API is intended for standalone
+applications, such as one wrapped by the standalone version of Wish
+and re-named into a different application. In particular such an
+application would specify its own unique CFBundleIdentifier in its
+Info.plist file. During development, however, if Wish itself is being
+used as the receiver, it may be necessary to take some care to ensure
+that the correct version of Wish.app is available as a receiver of
+NSServices data.
+
+When one macOS app uses NSServices to send data to another app that is
+not running, LaunchServices will launch the receiver. LaunchServices
+assumes that the CFBundleIdentifier uniquely identifies an app among
+all of the apps installed on a system. But this may not be the case
+for Wish.app if, for example, you have compiled Tk from source at some
+time in the past. In that case the Tk build directory will contain
+its own copy of Wish.app that will be visible to LaunchServices. It
+may be necessary when testing your app to take some steps to ensure
+that LaunchServices is launching the correct Wish.app. Instructions
+for doing this are provided below.
+
+The command line tool which manages the LaunchServices database has
+an amazingly unwieldy path name. So, first, run this command:
+
+alias lsregister='/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister'
+
+Then you can reset the LaunchServices database like this:
+
+$ lsregister -kill
+$ lsregister -seed
+
+To find out which versions of Wish.app have been located by
+LaunchServices, run:
+
+$ lsregister -dump | grep path | grep Wish
+
+If more than one version of Wish is showing up in this list, eliminate
+all of the unintended targets by running
+
+lsregister -u /path/to/bad/Wish.app
+
+Continue this until only the correct version of Wish shows up in the
+list.
diff --git a/tk8.6/macosx/Tk-Common.xcconfig b/tk8.6/macosx/Tk-Common.xcconfig
new file mode 100644
index 0000000..4ec1a52
--- /dev/null
+++ b/tk8.6/macosx/Tk-Common.xcconfig
@@ -0,0 +1,46 @@
+//
+// Tk-Common.xcconfig --
+//
+// This file contains the Xcode build settings comon to all
+// project configurations in Wish.xcodeproj.
+//
+// Copyright (c) 2007-2009 Daniel A. Steffen <das@users.sourceforge.net>
+// Copyright 2008-2009, Apple Inc.
+//
+// See the file "license.terms" for information on usage and redistribution
+// of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+HEADER_SEARCH_PATHS = $(TK_SRCROOT)/generic $(TK_SRCROOT)/xlib "$(DERIVED_FILE_DIR)/tcl" "$(DERIVED_FILE_DIR)/tk" $(HEADER_SEARCH_PATHS)
+REZ_SEARCH_PATHS = $(TK_SRCROOT)/generic $(TCL_SRCROOT)/generic $(REZ_SEARCH_PATHS)
+OTHER_LDFLAGS = -headerpad_max_install_names -sectcreate __TEXT __info_plist "$(DERIVED_FILE_DIR)/tk/Wish-Info.plist" $(OTHER_LDFLAGS)
+OTHER_LDFLAGS_AQUA =
+INSTALL_PATH = $(APPLICATION_INSTALL_PATH)
+INSTALL_MODE_FLAG = go-w,a+rX
+GCC_PREFIX_HEADER = $(DERIVED_FILE_DIR)/tk/tkConfig.h
+OTHER_CFLAGS = -imacros "$(DERIVED_FILE_DIR)/tcl/tclConfig.h" $(OTHER_CFLAGS)
+GCC_GENERATE_DEBUGGING_SYMBOLS = YES
+GCC_NO_COMMON_BLOCKS = YES
+GCC_DYNAMIC_NO_PIC = YES
+GCC_VERSION = 4.2
+GCC = gcc-$(GCC_VERSION)
+WARNING_CFLAGS = -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-value -Winit-self -Wpointer-arith -Wcast-align -Wdisabled-optimization -Winline $(WARNING_CFLAGS)
+REZ_RESOURCE_MAP_READ_ONLY = YES
+APPLICATION_INSTALL_PATH = /Applications/Utilities
+BINDIR = $(PREFIX)/bin
+CFLAGS = $(CFLAGS)
+CPPFLAGS = -mmacosx-version-min=$(MACOSX_DEPLOYMENT_TARGET) $(CPPFLAGS)
+FRAMEWORK_INSTALL_PATH = /Library/Frameworks
+INCLUDEDIR = $(PREFIX)/include
+LIBDIR = $(PREFIX)/lib
+MANDIR = $(PREFIX)/man
+PER_ARCH_CFLAGS_ppc = -mcpu=G3 -mtune=G4 $(PER_ARCH_CFLAGS_ppc)
+PREFIX = /usr/local
+TCL_BUILD_DIR = $(OBJROOT)/../tcl/Tcl.build/$(CONFIGURATION)/Tcl.build/Objects
+TCL_CONFIGURE_ARGS = --enable-threads --enable-dtrace
+TCL_FRAMEWORK_DIR = $(SYMROOT)/../tcl/$(CONFIGURATION)
+TCL_LIBRARY = $(LIBDIR)/tcl$(VERSION)
+TCL_PACKAGE_PATH = "$(LIBDIR)"
+TCL_DEFS = HAVE_TCL_CONFIG_H
+TK_LIBRARY = $(LIBDIR)/tk$(VERSION)
+TK_DEFS = HAVE_TK_CONFIG_H
+VERSION = 8.6
diff --git a/tk8.6/macosx/Tk-Debug.xcconfig b/tk8.6/macosx/Tk-Debug.xcconfig
new file mode 100644
index 0000000..2382661
--- /dev/null
+++ b/tk8.6/macosx/Tk-Debug.xcconfig
@@ -0,0 +1,19 @@
+//
+// Tk-Debug.xcconfig --
+//
+// This file contains the Xcode build settings for all Debug
+// project configurations in Wish.xcodeproj.
+//
+// Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
+//
+// See the file "license.terms" for information on usage and redistribution
+// of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+#include "Tk-Common.xcconfig"
+
+DEBUG_INFORMATION_FORMAT = dwarf
+DEPLOYMENT_POSTPROCESSING = NO
+GCC_OPTIMIZATION_LEVEL = 0
+GCC_PREPROCESSOR_DEFINITIONS = DEBUGLEVEL=4 $(TCL_DEFS) $(TK_DEFS) $(GCC_PREPROCESSOR_DEFINITIONS)
+CONFIGURE_ARGS = --enable-symbols $(TCL_CONFIGURE_ARGS) $(CONFIGURE_ARGS)
+MAKE_TARGET = develop
diff --git a/tk8.6/macosx/Tk-Info.plist.in b/tk8.6/macosx/Tk-Info.plist.in
new file mode 100644
index 0000000..7b0c305
--- /dev/null
+++ b/tk8.6/macosx/Tk-Info.plist.in
@@ -0,0 +1,41 @@
+<?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">
+<!--
+ Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ Copyright 2008-2009, Apple Inc.
+
+ See the file "license.terms" for information on usage and redistribution of
+ this file, and for a DISCLAIMER OF ALL WARRANTIES.
+-->
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>@TK_LIB_FILE@</string>
+ <key>CFBundleGetInfoString</key>
+ <string>Tk @TK_WINDOWINGSYSTEM@ @TK_VERSION@@TK_PATCH_LEVEL@,
+Copyright © 1989-@TK_YEAR@ Tcl Core Team,
+Copyright © 2002-@TK_YEAR@ Daniel A. Steffen,
+ Copyright © 1989-@TK_YEAR@ Contributors,
+ Copyright © 2011-@TK_YEAR@ Kevin Walzer/WordTech
+ Communications LLC,
+ Copyright © 2014-@TK_YEAR@ Marc Culler,
+Copyright © 2001-2009 Apple Inc.,
+Copyright © 2001-2002 Jim Ingham &amp; Ian Reid</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.tcltk.tklibrary</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>Tk @TK_WINDOWINGSYSTEM@ @TK_VERSION@</string>
+ <key>CFBundlePackageType</key>
+ <string>FMWK</string>
+ <key>CFBundleShortVersionString</key>
+ <string>@TK_VERSION@@TK_PATCH_LEVEL@</string>
+ <key>CFBundleSignature</key>
+ <string>Tk </string>
+ <key>CFBundleVersion</key>
+ <string>@TK_VERSION@@TK_PATCH_LEVEL@</string>
+</dict>
+</plist>
diff --git a/tk8.6/macosx/Tk-Release.xcconfig b/tk8.6/macosx/Tk-Release.xcconfig
new file mode 100644
index 0000000..505373c
--- /dev/null
+++ b/tk8.6/macosx/Tk-Release.xcconfig
@@ -0,0 +1,19 @@
+//
+// Tk-Release.xcconfig --
+//
+// This file contains the Xcode build settings for all Release
+// project configurations in Wish.xcodeproj.
+//
+// Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
+//
+// See the file "license.terms" for information on usage and redistribution
+// of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+#include "Tk-Common.xcconfig"
+
+DEBUG_INFORMATION_FORMAT = dwarf-with-dsym
+// DEPLOYMENT_POSTPROCESSING = YES
+GCC_OPTIMIZATION_LEVEL = s
+GCC_PREPROCESSOR_DEFINITIONS = NDEBUG $(TCL_DEFS) $(TK_DEFS) $(GCC_PREPROCESSOR_DEFINITIONS)
+CONFIGURE_ARGS = --disable-symbols $(TCL_CONFIGURE_ARGS) $(CONFIGURE_ARGS)
+MAKE_TARGET = deploy
diff --git a/tk8.6/macosx/Tk.icns b/tk8.6/macosx/Tk.icns
new file mode 100644
index 0000000..394b588
--- /dev/null
+++ b/tk8.6/macosx/Tk.icns
Binary files differ
diff --git a/tk8.6/macosx/Tk.tiff b/tk8.6/macosx/Tk.tiff
new file mode 100644
index 0000000..1e2aed5
--- /dev/null
+++ b/tk8.6/macosx/Tk.tiff
Binary files differ
diff --git a/tk8.6/macosx/Tk.xcode/default.pbxuser b/tk8.6/macosx/Tk.xcode/default.pbxuser
new file mode 100644
index 0000000..c8456e8
--- /dev/null
+++ b/tk8.6/macosx/Tk.xcode/default.pbxuser
@@ -0,0 +1,384 @@
+// !$*UTF8*$!
+{
+ 08FB7793FE84155DC02AAC07 /* Project object */ = {
+ activeBuildConfigurationName = Debug;
+ activeExecutable = F9E61D1C090A4282002B3151 /* Wish */;
+ activeTarget = F9E61D16090A3E94002B3151 /* Tk */;
+ codeSenseManager = F944EB9D08F798180049FDD4 /* Code sense */;
+ executables = (
+ F9E61D1C090A4282002B3151 /* Wish */,
+ F944EB8F08F798100049FDD4 /* tktest */,
+ F9FD31F50CC1AD070073837D /* tktest-X11 */,
+ );
+ perUserDictionary = {
+ com.apple.ide.smrt.PBXUserSmartGroupsKey.Rev10 = <040b73747265616d747970656481e8038401408484840e4e534d757461626c654172726179008484074e534172726179008484084e534f626a65637400858401690192848484134e534d757461626c6544696374696f6e6172790084840c4e5344696374696f6e6172790095960792848484084e53537472696e67019584012b046e616d658692849a9a14496d706c656d656e746174696f6e2046696c65738692849a9a146162736f6c75746550617468546f42756e646c658692849a9a008692849a9a195042585472616e7369656e744c6f636174696f6e4174546f708692849a9a06626f74746f6d8692849a9a03636c7a8692849a9a1550425846696c656e616d65536d61727447726f75708692849a9a0b6465736372697074696f6e8692849a9a103c6e6f206465736372697074696f6e3e8692849a9a0b707265666572656e63657386928497960892849a9a07666e6d617463688692849a9a008692849a9a05696d6167658692849a9a0b536d617274466f6c6465728692849a9a04726f6f748692849a9a093c50524f4a4543543e8692849a9a0572656765788692849a9a065c2e286329248692849a9a097265637572736976658692848484084e534e756d626572008484074e5356616c7565009584012a849696018692849a9a0669734c656166869284b09db296008692849a9a0763616e536176658692af92849a9a1250425850726f6a65637453636f70654b65798692849a9a03594553868692849a9a08676c6f62616c49448692849a9a18314343304541343030343335304546393030343434313042868686>;
+ };
+ sourceControlManager = F944EB9C08F798180049FDD4 /* Source Control */;
+ userBuildSettings = {
+ SYMROOT = "${SRCROOT}/../../build/tk";
+ TCL_SRCROOT = "${SRCROOT}/../../tcl";
+ TK_SRCROOT = "${SRCROOT}/../../tk";
+ };
+ };
+ 8DD76FA90486AB0100D96B5E /* tktest */ = {
+ activeExec = 0;
+ executables = (
+ F944EB8F08F798100049FDD4 /* tktest */,
+ );
+ };
+ F944EB8F08F798100049FDD4 /* tktest */ = {
+ isa = PBXExecutable;
+ activeArgIndices = (
+ YES,
+ NO,
+ NO,
+ NO,
+ NO,
+ NO,
+ NO,
+ );
+ argumentStrings = (
+ "${TK_SRCROOT}/library/demos/widget",
+ "${TK_SRCROOT}/tests/all.tcl",
+ "${TK_SRCROOT}/tests/ttk/all.tcl",
+ "-geometry +0+0",
+ "-singleproc 1",
+ "-verbose \"bet\"",
+ "-skip window-2.9",
+ );
+ autoAttachOnCrash = 1;
+ breakpointsEnabled = 1;
+ configStateDict = {
+ "PBXLSLaunchAction-0" = {
+ PBXLSLaunchAction = 0;
+ PBXLSLaunchStartAction = 1;
+ PBXLSLaunchStdioStyle = 2;
+ PBXLSLaunchStyle = 0;
+ class = PBXLSRunLaunchConfig;
+ displayName = "Executable Runner";
+ identifier = com.apple.Xcode.launch.runConfig;
+ remoteHostInfo = "";
+ startActionInfo = "";
+ };
+ "PBXLSLaunchAction-1" = {
+ PBXLSLaunchAction = 1;
+ PBXLSLaunchStartAction = 1;
+ PBXLSLaunchStdioStyle = 2;
+ PBXLSLaunchStyle = 0;
+ class = PBXGDB_LaunchConfig;
+ displayName = GDB;
+ identifier = com.apple.Xcode.launch.GDBMI_Config;
+ remoteHostInfo = "";
+ startActionInfo = "";
+ };
+ };
+ customDataFormattersEnabled = 1;
+ debuggerPlugin = GDBDebugging;
+ disassemblyDisplayState = 0;
+ dylibVariantSuffix = "";
+ enableDebugStr = 0;
+ environmentEntries = (
+ {
+ active = YES;
+ name = TCL_LIBRARY;
+ value = "${TCL_SRCROOT}/library";
+ },
+ {
+ active = YES;
+ name = TK_LIBRARY;
+ value = "${TK_SRCROOT}/library";
+ },
+ {
+ active = YES;
+ name = TCLLIBPATH;
+ value = /Library/Tcl;
+ },
+ {
+ active = YES;
+ name = TK_SRCROOT;
+ value = "${TK_SRCROOT}";
+ },
+ {
+ active = NO;
+ name = TK_CONSOLE;
+ value = 1;
+ },
+ {
+ active = NO;
+ name = DYLD_PRINT_LIBRARIES;
+ },
+ {
+ active = NO;
+ name = NSTraceEvents;
+ value = YES;
+ },
+ {
+ active = NO;
+ name = MallocBadFreeAbort;
+ value = 1;
+ },
+ {
+ active = NO;
+ name = MallocLogFile;
+ value = /tmp/malloc.log;
+ },
+ {
+ active = NO;
+ name = MallocStackLogging;
+ value = 1;
+ },
+ {
+ active = NO;
+ name = MallocStackLoggingNoCompact;
+ value = 1;
+ },
+ {
+ active = NO;
+ name = MallocPreScribble;
+ value = 1;
+ },
+ {
+ active = NO;
+ name = MallocScribble;
+ value = 1;
+ },
+ {
+ active = NO;
+ name = NSZombieEnabled;
+ value = YES;
+ },
+ {
+ active = NO;
+ name = NSDeallocateZombies;
+ value = YES;
+ },
+ {
+ active = NO;
+ name = NSAutoreleaseFreedObjectCheckEnabled;
+ value = YES;
+ },
+ {
+ active = NO;
+ name = NSEnableAutoreleasePool;
+ value = NO;
+ },
+ {
+ active = NO;
+ name = AUTO_LOG_ALL;
+ value = YES;
+ },
+ {
+ active = NO;
+ name = AUTO_LOG_NOISY;
+ value = YES;
+ },
+ {
+ active = NO;
+ name = AUTO_REFERENCE_COUNT_LOGGING;
+ value = YES;
+ },
+ );
+ executableSystemSymbolLevel = 0;
+ executableUserSymbolLevel = 0;
+ libgmallocEnabled = 0;
+ name = tktest;
+ sourceDirectories = (
+ );
+ };
+ F944EB9C08F798180049FDD4 /* Source Control */ = {
+ isa = PBXSourceControlManager;
+ fallbackIsa = XCSourceControlManager;
+ isSCMEnabled = 0;
+ scmConfiguration = {
+ CVSToolPath = /usr/bin/cvs;
+ CVSUseSSH = NO;
+ SubversionToolPath = /usr/bin/svn;
+ repositoryNamesForRoots = {
+ .. = "";
+ };
+ };
+ scmType = scm.cvs;
+ };
+ F944EB9D08F798180049FDD4 /* Code sense */ = {
+ isa = PBXCodeSenseManager;
+ indexTemplatePath = "";
+ };
+ F97258A50A86873C00096C78 /* tktest-X11 */ = {
+ activeExec = 0;
+ executables = (
+ F9FD31F50CC1AD070073837D /* tktest-X11 */,
+ );
+ };
+ F9E61D16090A3E94002B3151 /* Tk */ = {
+ activeExec = 0;
+ executables = (
+ F9E61D1C090A4282002B3151 /* Wish */,
+ );
+ };
+ F9E61D1C090A4282002B3151 /* Wish */ = {
+ isa = PBXExecutable;
+ activeArgIndices = (
+ YES,
+ );
+ argumentStrings = (
+ "${TK_SRCROOT}/library/demos/widget",
+ );
+ autoAttachOnCrash = 1;
+ breakpointsEnabled = 1;
+ configStateDict = {
+ "PBXLSLaunchAction-0" = {
+ PBXLSLaunchAction = 0;
+ PBXLSLaunchStartAction = 1;
+ PBXLSLaunchStdioStyle = 2;
+ PBXLSLaunchStyle = 0;
+ class = PBXLSRunLaunchConfig;
+ displayName = "Executable Runner";
+ identifier = com.apple.Xcode.launch.runConfig;
+ remoteHostInfo = "";
+ startActionInfo = "";
+ };
+ "PBXLSLaunchAction-1" = {
+ PBXLSLaunchAction = 1;
+ PBXLSLaunchStartAction = 1;
+ PBXLSLaunchStdioStyle = 2;
+ PBXLSLaunchStyle = 0;
+ class = PBXGDB_LaunchConfig;
+ displayName = GDB;
+ identifier = com.apple.Xcode.launch.GDBMI_Config;
+ remoteHostInfo = "";
+ startActionInfo = "";
+ };
+ };
+ customDataFormattersEnabled = 1;
+ debuggerPlugin = GDBDebugging;
+ disassemblyDisplayState = 0;
+ dylibVariantSuffix = "";
+ enableDebugStr = 0;
+ environmentEntries = (
+ {
+ active = NO;
+ name = DYLD_PRINT_LIBRARIES;
+ },
+ );
+ executableSystemSymbolLevel = 0;
+ executableUserSymbolLevel = 0;
+ libgmallocEnabled = 0;
+ name = Wish;
+ sourceDirectories = (
+ );
+ };
+ F9FD31F50CC1AD070073837D /* tktest-X11 */ = {
+ isa = PBXExecutable;
+ activeArgIndices = (
+ YES,
+ NO,
+ NO,
+ NO,
+ NO,
+ NO,
+ NO,
+ );
+ argumentStrings = (
+ "${TK_SRCROOT}/library/demos/widget",
+ "${TK_SRCROOT}/tests/all.tcl",
+ "${TK_SRCROOT}/tests/ttk/all.tcl",
+ "-geometry +0+0",
+ "-singleproc 1",
+ "-verbose \"bet\"",
+ "-skip window-2.9",
+ );
+ autoAttachOnCrash = 1;
+ breakpointsEnabled = 1;
+ configStateDict = {
+ "PBXLSLaunchAction-0" = {
+ PBXLSLaunchAction = 0;
+ PBXLSLaunchStartAction = 1;
+ PBXLSLaunchStdioStyle = 2;
+ PBXLSLaunchStyle = 0;
+ class = PBXLSRunLaunchConfig;
+ displayName = "Executable Runner";
+ identifier = com.apple.Xcode.launch.runConfig;
+ remoteHostInfo = "";
+ startActionInfo = "";
+ };
+ "PBXLSLaunchAction-1" = {
+ PBXLSLaunchAction = 1;
+ PBXLSLaunchStartAction = 1;
+ PBXLSLaunchStdioStyle = 2;
+ PBXLSLaunchStyle = 0;
+ class = PBXGDB_LaunchConfig;
+ displayName = GDB;
+ identifier = com.apple.Xcode.launch.GDBMI_Config;
+ remoteHostInfo = "";
+ startActionInfo = "";
+ };
+ };
+ customDataFormattersEnabled = 1;
+ debuggerPlugin = GDBDebugging;
+ disassemblyDisplayState = 0;
+ dylibVariantSuffix = "";
+ enableDebugStr = 0;
+ environmentEntries = (
+ {
+ active = YES;
+ name = TCL_LIBRARY;
+ value = "${TCL_SRCROOT}/library";
+ },
+ {
+ active = YES;
+ name = TK_LIBRARY;
+ value = "${TK_SRCROOT}/library";
+ },
+ {
+ active = YES;
+ name = TCLLIBPATH;
+ value = /Library/Tcl;
+ },
+ {
+ active = YES;
+ name = DISPLAY;
+ value = ":0";
+ },
+ {
+ active = NO;
+ name = DYLD_PRINT_LIBRARIES;
+ },
+ {
+ active = NO;
+ name = MallocBadFreeAbort;
+ value = 1;
+ },
+ {
+ active = NO;
+ name = MallocLogFile;
+ value = /tmp/malloc.log;
+ },
+ {
+ active = NO;
+ name = MallocStackLogging;
+ value = 1;
+ },
+ {
+ active = NO;
+ name = MallocStackLoggingNoCompact;
+ value = 1;
+ },
+ {
+ active = NO;
+ name = MallocPreScribble;
+ value = 1;
+ },
+ {
+ active = NO;
+ name = MallocScribble;
+ value = 1;
+ },
+ );
+ executableSystemSymbolLevel = 0;
+ executableUserSymbolLevel = 0;
+ libgmallocEnabled = 0;
+ name = "tktest-X11";
+ sourceDirectories = (
+ );
+ };
+}
diff --git a/tk8.6/macosx/Tk.xcode/project.pbxproj b/tk8.6/macosx/Tk.xcode/project.pbxproj
new file mode 100644
index 0000000..93143f7
--- /dev/null
+++ b/tk8.6/macosx/Tk.xcode/project.pbxproj
@@ -0,0 +1,5779 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 45;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ F9067BCD0BFBA2900074F726 /* tkOldTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAFE08F27A39005CB29B /* tkOldTest.c */; };
+ F9152B090EAF8A5000CD5C7B /* tkBusy.c in Sources */ = {isa = PBXBuildFile; fileRef = F9152B080EAF8A5000CD5C7B /* tkBusy.c */; };
+ F9152B0A0EAF8A5700CD5C7B /* tkBusy.c in Sources */ = {isa = PBXBuildFile; fileRef = F9152B080EAF8A5000CD5C7B /* tkBusy.c */; };
+ F92EE8BF0E62F846001A6E80 /* tkImgPhInstance.c in Sources */ = {isa = PBXBuildFile; fileRef = F92EE8BE0E62F846001A6E80 /* tkImgPhInstance.c */; };
+ F92EE8D30E62F939001A6E80 /* tkImgPhInstance.c in Sources */ = {isa = PBXBuildFile; fileRef = F92EE8BE0E62F846001A6E80 /* tkImgPhInstance.c */; };
+ F93599B30DF1F75400E04F67 /* tclOO.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599B20DF1F75400E04F67 /* tclOO.c */; };
+ F93599B70DF1F76100E04F67 /* tclOOBasic.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599B60DF1F76100E04F67 /* tclOOBasic.c */; };
+ F93599B90DF1F76600E04F67 /* tclOOCall.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599B80DF1F76600E04F67 /* tclOOCall.c */; };
+ F93599BC0DF1F77000E04F67 /* tclOODefineCmds.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599BB0DF1F77000E04F67 /* tclOODefineCmds.c */; };
+ F93599BE0DF1F77400E04F67 /* tclOOInfo.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599BD0DF1F77400E04F67 /* tclOOInfo.c */; };
+ F93599C20DF1F78300E04F67 /* tclOOMethod.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599C10DF1F78300E04F67 /* tclOOMethod.c */; };
+ F93599C40DF1F78800E04F67 /* tclOOStubInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599C30DF1F78800E04F67 /* tclOOStubInit.c */; };
+ F93599C60DF1F78D00E04F67 /* tclOOStubLib.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599C50DF1F78D00E04F67 /* tclOOStubLib.c */; };
+ F94523A20E6FC2AC00C1D987 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F94523A10E6FC2AC00C1D987 /* Cocoa.framework */; };
+ F95D77EA0DFD820D00A8BF6F /* tclIORTrans.c in Sources */ = {isa = PBXBuildFile; fileRef = F95D77E90DFD820D00A8BF6F /* tclIORTrans.c */; };
+ F96437CA0EF0D4B2003F468E /* tclZlib.c in Sources */ = {isa = PBXBuildFile; fileRef = F96437C90EF0D4B2003F468E /* tclZlib.c */; };
+ F96437CB0EF0D4B2003F468E /* tclZlib.c in Sources */ = {isa = PBXBuildFile; fileRef = F96437C90EF0D4B2003F468E /* tclZlib.c */; };
+ F96437E70EF0D652003F468E /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F96437E60EF0D652003F468E /* libz.dylib */; };
+ F96437E80EF0D652003F468E /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F96437E60EF0D652003F468E /* libz.dylib */; };
+ F966BDCF08F27A3F005CB29B /* tk3d.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAAC08F27A39005CB29B /* tk3d.c */; };
+ F966BDD108F27A3F005CB29B /* tkArgv.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAAE08F27A39005CB29B /* tkArgv.c */; };
+ F966BDD208F27A3F005CB29B /* tkAtom.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAAF08F27A39005CB29B /* tkAtom.c */; };
+ F966BDD308F27A3F005CB29B /* tkBind.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB008F27A39005CB29B /* tkBind.c */; };
+ F966BDD408F27A3F005CB29B /* tkBitmap.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB108F27A39005CB29B /* tkBitmap.c */; };
+ F966BDD508F27A3F005CB29B /* tkButton.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB208F27A39005CB29B /* tkButton.c */; };
+ F966BDD708F27A3F005CB29B /* tkCanvArc.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB408F27A39005CB29B /* tkCanvArc.c */; };
+ F966BDD808F27A3F005CB29B /* tkCanvas.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB508F27A39005CB29B /* tkCanvas.c */; };
+ F966BDDA08F27A3F005CB29B /* tkCanvBmap.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB708F27A39005CB29B /* tkCanvBmap.c */; };
+ F966BDDB08F27A3F005CB29B /* tkCanvImg.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB808F27A39005CB29B /* tkCanvImg.c */; };
+ F966BDDC08F27A3F005CB29B /* tkCanvLine.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB908F27A39005CB29B /* tkCanvLine.c */; };
+ F966BDDD08F27A3F005CB29B /* tkCanvPoly.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BABA08F27A39005CB29B /* tkCanvPoly.c */; };
+ F966BDDE08F27A3F005CB29B /* tkCanvPs.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BABB08F27A39005CB29B /* tkCanvPs.c */; };
+ F966BDE008F27A3F005CB29B /* tkCanvText.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BABD08F27A39005CB29B /* tkCanvText.c */; };
+ F966BDE108F27A3F005CB29B /* tkCanvUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BABE08F27A39005CB29B /* tkCanvUtil.c */; };
+ F966BDE208F27A3F005CB29B /* tkCanvWind.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BABF08F27A39005CB29B /* tkCanvWind.c */; };
+ F966BDE308F27A3F005CB29B /* tkClipboard.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAC008F27A39005CB29B /* tkClipboard.c */; };
+ F966BDE408F27A3F005CB29B /* tkCmds.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAC108F27A39005CB29B /* tkCmds.c */; };
+ F966BDE508F27A3F005CB29B /* tkColor.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAC208F27A39005CB29B /* tkColor.c */; };
+ F966BDE708F27A3F005CB29B /* tkConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAC408F27A39005CB29B /* tkConfig.c */; };
+ F966BDE808F27A3F005CB29B /* tkConsole.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAC508F27A39005CB29B /* tkConsole.c */; };
+ F966BDE908F27A3F005CB29B /* tkCursor.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAC608F27A39005CB29B /* tkCursor.c */; };
+ F966BDEB08F27A3F005CB29B /* tkEntry.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAC808F27A39005CB29B /* tkEntry.c */; };
+ F966BDED08F27A3F005CB29B /* tkError.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BACA08F27A39005CB29B /* tkError.c */; };
+ F966BDEE08F27A3F005CB29B /* tkEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BACB08F27A39005CB29B /* tkEvent.c */; };
+ F966BDEF08F27A3F005CB29B /* tkFileFilter.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BACC08F27A39005CB29B /* tkFileFilter.c */; };
+ F966BDF108F27A3F005CB29B /* tkFocus.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BACE08F27A39005CB29B /* tkFocus.c */; };
+ F966BDF208F27A3F005CB29B /* tkFont.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BACF08F27A39005CB29B /* tkFont.c */; };
+ F966BDF408F27A3F005CB29B /* tkFrame.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD108F27A39005CB29B /* tkFrame.c */; };
+ F966BDF508F27A3F005CB29B /* tkGC.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD208F27A39005CB29B /* tkGC.c */; };
+ F966BDF608F27A3F005CB29B /* tkGeometry.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD308F27A39005CB29B /* tkGeometry.c */; };
+ F966BDF708F27A3F005CB29B /* tkGet.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD408F27A39005CB29B /* tkGet.c */; };
+ F966BDF808F27A3F005CB29B /* tkGrab.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD508F27A39005CB29B /* tkGrab.c */; };
+ F966BDF908F27A3F005CB29B /* tkGrid.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD608F27A39005CB29B /* tkGrid.c */; };
+ F966BDFA08F27A3F005CB29B /* tkImage.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD708F27A39005CB29B /* tkImage.c */; };
+ F966BDFB08F27A3F005CB29B /* tkImgBmap.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD808F27A39005CB29B /* tkImgBmap.c */; };
+ F966BDFC08F27A3F005CB29B /* tkImgGIF.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD908F27A39005CB29B /* tkImgGIF.c */; };
+ F966BDFD08F27A3F005CB29B /* tkImgPhoto.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BADA08F27A39005CB29B /* tkImgPhoto.c */; };
+ F966BDFE08F27A3F005CB29B /* tkImgPPM.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BADB08F27A39005CB29B /* tkImgPPM.c */; };
+ F966BE0708F27A3F005CB29B /* tkListbox.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAE408F27A39005CB29B /* tkListbox.c */; };
+ F966BE0808F27A3F005CB29B /* tkMacWinMenu.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAE508F27A39005CB29B /* tkMacWinMenu.c */; };
+ F966BE0908F27A3F005CB29B /* tkMain.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAE608F27A39005CB29B /* tkMain.c */; };
+ F966BE0A08F27A3F005CB29B /* tkMenu.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAE708F27A39005CB29B /* tkMenu.c */; };
+ F966BE0C08F27A3F005CB29B /* tkMenubutton.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAE908F27A39005CB29B /* tkMenubutton.c */; };
+ F966BE0E08F27A3F005CB29B /* tkMenuDraw.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAEB08F27A39005CB29B /* tkMenuDraw.c */; };
+ F966BE0F08F27A3F005CB29B /* tkMessage.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAEC08F27A39005CB29B /* tkMessage.c */; };
+ F966BE1008F27A3F005CB29B /* tkObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAED08F27A39005CB29B /* tkObj.c */; };
+ F966BE1108F27A3F005CB29B /* tkOldConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAEE08F27A39005CB29B /* tkOldConfig.c */; };
+ F966BE1208F27A3F005CB29B /* tkOption.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAEF08F27A39005CB29B /* tkOption.c */; };
+ F966BE1308F27A3F005CB29B /* tkPack.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAF008F27A39005CB29B /* tkPack.c */; };
+ F966BE1408F27A3F005CB29B /* tkPanedWindow.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAF108F27A39005CB29B /* tkPanedWindow.c */; };
+ F966BE1508F27A3F005CB29B /* tkPlace.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAF208F27A39005CB29B /* tkPlace.c */; };
+ F966BE1708F27A3F005CB29B /* tkPointer.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAF408F27A39005CB29B /* tkPointer.c */; };
+ F966BE1908F27A3F005CB29B /* tkRectOval.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAF608F27A39005CB29B /* tkRectOval.c */; };
+ F966BE1A08F27A3F005CB29B /* tkScale.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAF708F27A39005CB29B /* tkScale.c */; };
+ F966BE1C08F27A40005CB29B /* tkScrollbar.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAF908F27A39005CB29B /* tkScrollbar.c */; };
+ F966BE1E08F27A40005CB29B /* tkSelect.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAFB08F27A39005CB29B /* tkSelect.c */; };
+ F966BE2008F27A40005CB29B /* tkSquare.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAFD08F27A39005CB29B /* tkSquare.c */; };
+ F966BE2208F27A40005CB29B /* tkStubInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAFF08F27A39005CB29B /* tkStubInit.c */; };
+ F966BE2308F27A40005CB29B /* tkStubLib.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0008F27A39005CB29B /* tkStubLib.c */; };
+ F966BE2408F27A40005CB29B /* tkStyle.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0108F27A39005CB29B /* tkStyle.c */; };
+ F966BE2508F27A40005CB29B /* tkTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0208F27A39005CB29B /* tkTest.c */; };
+ F966BE2608F27A40005CB29B /* tkText.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0308F27A39005CB29B /* tkText.c */; };
+ F966BE2808F27A40005CB29B /* tkTextBTree.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0508F27A39005CB29B /* tkTextBTree.c */; };
+ F966BE2908F27A40005CB29B /* tkTextDisp.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0608F27A39005CB29B /* tkTextDisp.c */; };
+ F966BE2B08F27A40005CB29B /* tkTextImage.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0808F27A39005CB29B /* tkTextImage.c */; };
+ F966BE2C08F27A40005CB29B /* tkTextIndex.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0908F27A39005CB29B /* tkTextIndex.c */; };
+ F966BE2D08F27A40005CB29B /* tkTextMark.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0A08F27A39005CB29B /* tkTextMark.c */; };
+ F966BE2E08F27A40005CB29B /* tkTextTag.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0B08F27A39005CB29B /* tkTextTag.c */; };
+ F966BE2F08F27A40005CB29B /* tkTextWind.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0C08F27A39005CB29B /* tkTextWind.c */; };
+ F966BE3008F27A40005CB29B /* tkTrig.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0D08F27A39005CB29B /* tkTrig.c */; };
+ F966BE3108F27A40005CB29B /* tkUndo.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0E08F27A39005CB29B /* tkUndo.c */; };
+ F966BE3308F27A40005CB29B /* tkUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB1008F27A39005CB29B /* tkUtil.c */; };
+ F966BE3408F27A40005CB29B /* tkVisual.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB1108F27A39005CB29B /* tkVisual.c */; };
+ F966BE3508F27A40005CB29B /* tkWindow.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB1208F27A39005CB29B /* tkWindow.c */; };
+ F966BEDB08F27A40005CB29B /* tkMacOSXBitmap.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBC508F27A3B005CB29B /* tkMacOSXBitmap.c */; };
+ F966BEDC08F27A40005CB29B /* tkMacOSXButton.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBC608F27A3B005CB29B /* tkMacOSXButton.c */; };
+ F966BEDE08F27A40005CB29B /* tkMacOSXClipboard.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBC808F27A3B005CB29B /* tkMacOSXClipboard.c */; };
+ F966BEDF08F27A40005CB29B /* tkMacOSXColor.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBC908F27A3B005CB29B /* tkMacOSXColor.c */; };
+ F966BEE008F27A40005CB29B /* tkMacOSXConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBCA08F27A3B005CB29B /* tkMacOSXConfig.c */; };
+ F966BEE108F27A40005CB29B /* tkMacOSXCursor.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBCB08F27A3B005CB29B /* tkMacOSXCursor.c */; };
+ F966BEE308F27A40005CB29B /* tkMacOSXDebug.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBCD08F27A3B005CB29B /* tkMacOSXDebug.c */; };
+ F966BEE608F27A40005CB29B /* tkMacOSXDialog.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBD008F27A3B005CB29B /* tkMacOSXDialog.c */; };
+ F966BEE708F27A40005CB29B /* tkMacOSXDraw.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBD108F27A3B005CB29B /* tkMacOSXDraw.c */; };
+ F966BEE808F27A40005CB29B /* tkMacOSXEmbed.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBD208F27A3B005CB29B /* tkMacOSXEmbed.c */; };
+ F966BEE908F27A40005CB29B /* tkMacOSXEntry.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBD308F27A3B005CB29B /* tkMacOSXEntry.c */; };
+ F966BEEA08F27A40005CB29B /* tkMacOSXEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBD408F27A3B005CB29B /* tkMacOSXEvent.c */; };
+ F966BEEC08F27A40005CB29B /* tkMacOSXFont.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBD608F27A3B005CB29B /* tkMacOSXFont.c */; };
+ F966BEED08F27A40005CB29B /* tkMacOSXHLEvents.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBD708F27A3B005CB29B /* tkMacOSXHLEvents.c */; };
+ F966BEEE08F27A40005CB29B /* tkMacOSXInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBD808F27A3B005CB29B /* tkMacOSXInit.c */; settings = {COMPILER_FLAGS = "-DTK_LIBRARY=\\\"$(TK_LIBRARY)\\\""; }; };
+ F966BEF108F27A40005CB29B /* tkMacOSXKeyboard.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBDB08F27A3B005CB29B /* tkMacOSXKeyboard.c */; };
+ F966BEF208F27A40005CB29B /* tkMacOSXKeyEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBDC08F27A3B005CB29B /* tkMacOSXKeyEvent.c */; };
+ F966BEF308F27A40005CB29B /* tkMacOSXMenu.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBDD08F27A3B005CB29B /* tkMacOSXMenu.c */; };
+ F966BEF608F27A40005CB29B /* tkMacOSXMenubutton.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBE008F27A3B005CB29B /* tkMacOSXMenubutton.c */; };
+ F966BEF708F27A40005CB29B /* tkMacOSXMenus.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBE108F27A3B005CB29B /* tkMacOSXMenus.c */; };
+ F966BEF808F27A40005CB29B /* tkMacOSXMouseEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBE208F27A3B005CB29B /* tkMacOSXMouseEvent.c */; };
+ F966BEF908F27A40005CB29B /* tkMacOSXNotify.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBE308F27A3B005CB29B /* tkMacOSXNotify.c */; };
+ F966BF0108F27A40005CB29B /* tkMacOSXRegion.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBEB08F27A3C005CB29B /* tkMacOSXRegion.c */; };
+ F966BF0308F27A40005CB29B /* tkMacOSXScrlbr.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBED08F27A3C005CB29B /* tkMacOSXScrlbr.c */; };
+ F966BF0408F27A40005CB29B /* tkMacOSXSend.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBEE08F27A3C005CB29B /* tkMacOSXSend.c */; };
+ F966BF0508F27A40005CB29B /* tkMacOSXSubwindows.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBEF08F27A3C005CB29B /* tkMacOSXSubwindows.c */; };
+ F966BF0608F27A40005CB29B /* tkMacOSXTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBF008F27A3C005CB29B /* tkMacOSXTest.c */; };
+ F966BF0708F27A40005CB29B /* tkMacOSXWindowEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBF108F27A3C005CB29B /* tkMacOSXWindowEvent.c */; };
+ F966BF0808F27A40005CB29B /* tkMacOSXWm.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBF208F27A3C005CB29B /* tkMacOSXWm.c */; };
+ F966BF0B08F27A40005CB29B /* tkMacOSXXStubs.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBF508F27A3C005CB29B /* tkMacOSXXStubs.c */; };
+ F966BF7F08F27A41005CB29B /* tkAppInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC7508F27A3D005CB29B /* tkAppInit.c */; settings = {COMPILER_FLAGS = "-DTK_TEST"; }; };
+ F966BF8308F27A41005CB29B /* tkUnix3d.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC7908F27A3D005CB29B /* tkUnix3d.c */; };
+ F966BF9608F27A41005CB29B /* tkUnixScale.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC8C08F27A3D005CB29B /* tkUnixScale.c */; };
+ F966C02A08F27A42005CB29B /* xcolors.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BD2408F27A3F005CB29B /* xcolors.c */; };
+ F966C02B08F27A42005CB29B /* xdraw.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BD2508F27A3F005CB29B /* xdraw.c */; };
+ F966C02C08F27A42005CB29B /* xgc.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BD2608F27A3F005CB29B /* xgc.c */; };
+ F966C02D08F27A42005CB29B /* ximage.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BD2708F27A3F005CB29B /* ximage.c */; };
+ F966C02E08F27A42005CB29B /* xutil.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BD2808F27A3F005CB29B /* xutil.c */; };
+ F966C07508F2820D005CB29B /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F966C07408F2820D005CB29B /* CoreFoundation.framework */; };
+ F966C07708F2821B005CB29B /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F966C07608F2821B005CB29B /* Carbon.framework */; };
+ F966C07908F28233005CB29B /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F966C07808F28233005CB29B /* IOKit.framework */; };
+ F96888050AF786D5000797B5 /* ttkBlink.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E10AF786D5000797B5 /* ttkBlink.c */; };
+ F96888060AF786D5000797B5 /* ttkButton.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E20AF786D5000797B5 /* ttkButton.c */; };
+ F96888070AF786D5000797B5 /* ttkCache.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E30AF786D5000797B5 /* ttkCache.c */; };
+ F96888080AF786D5000797B5 /* ttkClamTheme.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E40AF786D5000797B5 /* ttkClamTheme.c */; };
+ F96888090AF786D5000797B5 /* ttkClassicTheme.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E50AF786D5000797B5 /* ttkClassicTheme.c */; };
+ F968880A0AF786D5000797B5 /* ttkDefaultTheme.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E70AF786D5000797B5 /* ttkDefaultTheme.c */; };
+ F968880B0AF786D5000797B5 /* ttkElements.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E80AF786D5000797B5 /* ttkElements.c */; };
+ F968880C0AF786D5000797B5 /* ttkEntry.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E90AF786D5000797B5 /* ttkEntry.c */; };
+ F968880D0AF786D5000797B5 /* ttkFrame.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887EA0AF786D5000797B5 /* ttkFrame.c */; };
+ F968880E0AF786D5000797B5 /* ttkImage.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887EB0AF786D5000797B5 /* ttkImage.c */; };
+ F968880F0AF786D5000797B5 /* ttkInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887EC0AF786D5000797B5 /* ttkInit.c */; };
+ F96888100AF786D5000797B5 /* ttkLabel.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887ED0AF786D5000797B5 /* ttkLabel.c */; };
+ F96888110AF786D5000797B5 /* ttkLayout.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887EE0AF786D5000797B5 /* ttkLayout.c */; };
+ F96888120AF786D5000797B5 /* ttkManager.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887EF0AF786D5000797B5 /* ttkManager.c */; };
+ F96888130AF786D5000797B5 /* ttkNotebook.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F10AF786D5000797B5 /* ttkNotebook.c */; };
+ F96888140AF786D5000797B5 /* ttkPanedwindow.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F20AF786D5000797B5 /* ttkPanedwindow.c */; };
+ F96888150AF786D5000797B5 /* ttkProgress.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F30AF786D5000797B5 /* ttkProgress.c */; };
+ F96888160AF786D5000797B5 /* ttkScale.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F40AF786D5000797B5 /* ttkScale.c */; };
+ F96888170AF786D5000797B5 /* ttkScroll.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F50AF786D5000797B5 /* ttkScroll.c */; };
+ F96888180AF786D5000797B5 /* ttkScrollbar.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F60AF786D5000797B5 /* ttkScrollbar.c */; };
+ F96888190AF786D5000797B5 /* ttkSeparator.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F70AF786D5000797B5 /* ttkSeparator.c */; };
+ F968881A0AF786D5000797B5 /* ttkSquare.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F80AF786D5000797B5 /* ttkSquare.c */; };
+ F968881B0AF786D5000797B5 /* ttkState.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F90AF786D5000797B5 /* ttkState.c */; };
+ F968881C0AF786D5000797B5 /* ttkStubInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887FA0AF786D5000797B5 /* ttkStubInit.c */; };
+ F968881D0AF786D5000797B5 /* ttkStubLib.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887FB0AF786D5000797B5 /* ttkStubLib.c */; };
+ F968881E0AF786D5000797B5 /* ttkTagSet.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887FC0AF786D5000797B5 /* ttkTagSet.c */; };
+ F968881F0AF786D5000797B5 /* ttkTheme.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887FD0AF786D5000797B5 /* ttkTheme.c */; };
+ F96888200AF786D5000797B5 /* ttkTrace.c in Sources */ = {isa = PBXBuildFile; fileRef = F96888000AF786D5000797B5 /* ttkTrace.c */; };
+ F96888210AF786D5000797B5 /* ttkTrack.c in Sources */ = {isa = PBXBuildFile; fileRef = F96888010AF786D5000797B5 /* ttkTrack.c */; };
+ F96888220AF786D5000797B5 /* ttkTreeview.c in Sources */ = {isa = PBXBuildFile; fileRef = F96888020AF786D5000797B5 /* ttkTreeview.c */; };
+ F96888230AF786D5000797B5 /* ttkWidget.c in Sources */ = {isa = PBXBuildFile; fileRef = F96888030AF786D5000797B5 /* ttkWidget.c */; };
+ F96888850AF78938000797B5 /* ttkMacOSXTheme.c in Sources */ = {isa = PBXBuildFile; fileRef = F96888840AF78938000797B5 /* ttkMacOSXTheme.c */; };
+ F96D456F08F272BB004A47F5 /* regcomp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED008F272A7004A47F5 /* regcomp.c */; };
+ F96D457208F272BB004A47F5 /* regerror.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED308F272A7004A47F5 /* regerror.c */; };
+ F96D457508F272BB004A47F5 /* regexec.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED608F272A7004A47F5 /* regexec.c */; };
+ F96D457608F272BB004A47F5 /* regfree.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED708F272A7004A47F5 /* regfree.c */; };
+ F96D457B08F272BB004A47F5 /* tclAlloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDC08F272A7004A47F5 /* tclAlloc.c */; settings = {COMPILER_FLAGS = "-DUSE_TCLALLOC=0"; }; };
+ F96D457C08F272BB004A47F5 /* tclAsync.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDD08F272A7004A47F5 /* tclAsync.c */; };
+ F96D457D08F272BB004A47F5 /* tclBasic.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDE08F272A7004A47F5 /* tclBasic.c */; };
+ F96D457E08F272BC004A47F5 /* tclBinary.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDF08F272A7004A47F5 /* tclBinary.c */; };
+ F96D457F08F272BC004A47F5 /* tclCkalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE008F272A7004A47F5 /* tclCkalloc.c */; };
+ F96D458008F272BC004A47F5 /* tclClock.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE108F272A7004A47F5 /* tclClock.c */; };
+ F96D458108F272BC004A47F5 /* tclCmdAH.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE208F272A7004A47F5 /* tclCmdAH.c */; };
+ F96D458208F272BC004A47F5 /* tclCmdIL.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE308F272A7004A47F5 /* tclCmdIL.c */; };
+ F96D458308F272BC004A47F5 /* tclCmdMZ.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE408F272A7004A47F5 /* tclCmdMZ.c */; };
+ F96D458408F272BC004A47F5 /* tclCompCmds.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE508F272A7004A47F5 /* tclCompCmds.c */; };
+ F96D458508F272BC004A47F5 /* tclCompExpr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE608F272A7004A47F5 /* tclCompExpr.c */; };
+ F96D458608F272BC004A47F5 /* tclCompile.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE708F272A7004A47F5 /* tclCompile.c */; };
+ F96D458808F272BC004A47F5 /* tclConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE908F272A7004A47F5 /* tclConfig.c */; };
+ F96D458908F272BC004A47F5 /* tclDate.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEA08F272A7004A47F5 /* tclDate.c */; };
+ F96D458B08F272BC004A47F5 /* tclDictObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEC08F272A7004A47F5 /* tclDictObj.c */; };
+ F96D458C08F272BC004A47F5 /* tclEncoding.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EED08F272A7004A47F5 /* tclEncoding.c */; };
+ F96D458D08F272BC004A47F5 /* tclEnv.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEE08F272A7004A47F5 /* tclEnv.c */; };
+ F96D458E08F272BC004A47F5 /* tclEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEF08F272A7004A47F5 /* tclEvent.c */; };
+ F96D458F08F272BC004A47F5 /* tclExecute.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF008F272A7004A47F5 /* tclExecute.c */; };
+ F96D459008F272BC004A47F5 /* tclFCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF108F272A7004A47F5 /* tclFCmd.c */; };
+ F96D459108F272BC004A47F5 /* tclFileName.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF208F272A7004A47F5 /* tclFileName.c */; };
+ F96D459308F272BC004A47F5 /* tclGet.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF408F272A7004A47F5 /* tclGet.c */; };
+ F96D459508F272BC004A47F5 /* tclHash.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF608F272A7004A47F5 /* tclHash.c */; };
+ F96D459608F272BC004A47F5 /* tclHistory.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF708F272A7004A47F5 /* tclHistory.c */; };
+ F96D459708F272BC004A47F5 /* tclIndexObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF808F272A7004A47F5 /* tclIndexObj.c */; };
+ F96D459B08F272BC004A47F5 /* tclInterp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EFC08F272A7004A47F5 /* tclInterp.c */; };
+ F96D459D08F272BC004A47F5 /* tclIO.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EFE08F272A7004A47F5 /* tclIO.c */; };
+ F96D459F08F272BC004A47F5 /* tclIOCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0008F272A7004A47F5 /* tclIOCmd.c */; };
+ F96D45A008F272BC004A47F5 /* tclIOGT.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0108F272A7004A47F5 /* tclIOGT.c */; };
+ F96D45A108F272BC004A47F5 /* tclIORChan.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0208F272A7004A47F5 /* tclIORChan.c */; };
+ F96D45A208F272BC004A47F5 /* tclIOSock.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0308F272A7004A47F5 /* tclIOSock.c */; };
+ F96D45A308F272BC004A47F5 /* tclIOUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0408F272A7004A47F5 /* tclIOUtil.c */; };
+ F96D45A408F272BC004A47F5 /* tclLink.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0508F272A7004A47F5 /* tclLink.c */; };
+ F96D45A508F272BC004A47F5 /* tclListObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0608F272A7004A47F5 /* tclListObj.c */; };
+ F96D45A608F272BC004A47F5 /* tclLiteral.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0708F272A7004A47F5 /* tclLiteral.c */; };
+ F96D45A708F272BC004A47F5 /* tclLoad.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0808F272A7004A47F5 /* tclLoad.c */; };
+ F96D45A908F272BC004A47F5 /* tclMain.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0A08F272A7004A47F5 /* tclMain.c */; };
+ F96D45AA08F272BC004A47F5 /* tclNamesp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0B08F272A7004A47F5 /* tclNamesp.c */; };
+ F96D45AB08F272BC004A47F5 /* tclNotify.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0C08F272A7004A47F5 /* tclNotify.c */; };
+ F96D45AC08F272BC004A47F5 /* tclObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0D08F272A7004A47F5 /* tclObj.c */; };
+ F96D45AD08F272BC004A47F5 /* tclPanic.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0E08F272A7004A47F5 /* tclPanic.c */; };
+ F96D45AE08F272BC004A47F5 /* tclParse.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0F08F272A7004A47F5 /* tclParse.c */; };
+ F96D45B008F272BC004A47F5 /* tclPathObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1108F272A7004A47F5 /* tclPathObj.c */; };
+ F96D45B108F272BC004A47F5 /* tclPipe.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1208F272A7004A47F5 /* tclPipe.c */; };
+ F96D45B208F272BC004A47F5 /* tclPkg.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1308F272A7004A47F5 /* tclPkg.c */; };
+ F96D45B308F272BC004A47F5 /* tclPkgConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1408F272A7004A47F5 /* tclPkgConfig.c */; settings = {COMPILER_FLAGS = "-DCFG_INSTALL_LIBDIR=\\\"$(LIBDIR)\\\" -DCFG_INSTALL_BINDIR=\\\"$(BINDIR)\\\" -DCFG_INSTALL_SCRDIR=\\\"$(TCL_LIBRARY)\\\" -DCFG_INSTALL_INCDIR=\\\"$(INCLUDEDIR)\\\" -DCFG_INSTALL_DOCDIR=\\\"$(MANDIR)\\\" -DCFG_RUNTIME_LIBDIR=\\\"$(LIBDIR)\\\" -DCFG_RUNTIME_BINDIR=\\\"$(BINDIR)\\\" -DCFG_RUNTIME_SCRDIR=\\\"$(TCL_LIBRARY)\\\" -DCFG_RUNTIME_INCDIR=\\\"$(INCLUDEDIR)\\\" -DCFG_RUNTIME_DOCDIR=\\\"$(MANDIR)\\\""; }; };
+ F96D45B608F272BC004A47F5 /* tclPosixStr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1708F272A7004A47F5 /* tclPosixStr.c */; };
+ F96D45B708F272BC004A47F5 /* tclPreserve.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1808F272A7004A47F5 /* tclPreserve.c */; };
+ F96D45B808F272BC004A47F5 /* tclProc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1908F272A7004A47F5 /* tclProc.c */; };
+ F96D45B908F272BC004A47F5 /* tclRegexp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1A08F272A7004A47F5 /* tclRegexp.c */; };
+ F96D45BB08F272BC004A47F5 /* tclResolve.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1C08F272A7004A47F5 /* tclResolve.c */; };
+ F96D45BC08F272BC004A47F5 /* tclResult.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1D08F272A7004A47F5 /* tclResult.c */; };
+ F96D45BD08F272BC004A47F5 /* tclScan.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1E08F272A7004A47F5 /* tclScan.c */; };
+ F96D45BE08F272BC004A47F5 /* tclStringObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1F08F272A7004A47F5 /* tclStringObj.c */; };
+ F96D45C308F272BC004A47F5 /* tclStrToD.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2408F272A7004A47F5 /* tclStrToD.c */; };
+ F96D45C408F272BC004A47F5 /* tclStubInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2508F272A7004A47F5 /* tclStubInit.c */; };
+ F96D45C508F272BC004A47F5 /* tclStubLib.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2608F272A7004A47F5 /* tclStubLib.c */; };
+ F96D45C908F272BC004A47F5 /* tclThread.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2A08F272A7004A47F5 /* tclThread.c */; };
+ F96D45CA08F272BC004A47F5 /* tclThreadAlloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2B08F272A7004A47F5 /* tclThreadAlloc.c */; };
+ F96D45CB08F272BC004A47F5 /* tclThreadJoin.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2C08F272A7004A47F5 /* tclThreadJoin.c */; };
+ F96D45CC08F272BC004A47F5 /* tclThreadStorage.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2D08F272A7004A47F5 /* tclThreadStorage.c */; };
+ F96D45CE08F272BC004A47F5 /* tclTimer.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2F08F272A7004A47F5 /* tclTimer.c */; };
+ F96D45D008F272BC004A47F5 /* tclTomMathInterface.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3108F272A7004A47F5 /* tclTomMathInterface.c */; };
+ F96D45D108F272BC004A47F5 /* tclTrace.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3208F272A7004A47F5 /* tclTrace.c */; };
+ F96D45D308F272BC004A47F5 /* tclUtf.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3408F272A7004A47F5 /* tclUtf.c */; };
+ F96D45D408F272BC004A47F5 /* tclUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3508F272A7004A47F5 /* tclUtil.c */; };
+ F96D45D508F272BC004A47F5 /* tclVar.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3608F272A7004A47F5 /* tclVar.c */; };
+ F96D48E208F272C3004A47F5 /* bn_fast_s_mp_mul_digs.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426408F272B3004A47F5 /* bn_fast_s_mp_mul_digs.c */; };
+ F96D48E408F272C3004A47F5 /* bn_fast_s_mp_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426608F272B3004A47F5 /* bn_fast_s_mp_sqr.c */; };
+ F96D48E708F272C3004A47F5 /* bn_mp_add.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426908F272B3004A47F5 /* bn_mp_add.c */; };
+ F96D48E808F272C3004A47F5 /* bn_mp_add_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426A08F272B3004A47F5 /* bn_mp_add_d.c */; };
+ F96D48EB08F272C3004A47F5 /* bn_mp_clamp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426D08F272B3004A47F5 /* bn_mp_clamp.c */; };
+ F96D48EC08F272C3004A47F5 /* bn_mp_clear.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426E08F272B3004A47F5 /* bn_mp_clear.c */; };
+ F96D48ED08F272C3004A47F5 /* bn_mp_clear_multi.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426F08F272B3004A47F5 /* bn_mp_clear_multi.c */; };
+ F96D48EE08F272C3004A47F5 /* bn_mp_cmp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427008F272B3004A47F5 /* bn_mp_cmp.c */; };
+ F96D48F008F272C3004A47F5 /* bn_mp_cmp_mag.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */; };
+ F96D48F208F272C3004A47F5 /* bn_mp_copy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427408F272B3004A47F5 /* bn_mp_copy.c */; };
+ F96D48F308F272C3004A47F5 /* bn_mp_count_bits.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */; };
+ F96D48F408F272C3004A47F5 /* bn_mp_div.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427608F272B3004A47F5 /* bn_mp_div.c */; };
+ F96D48F508F272C3004A47F5 /* bn_mp_div_2.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427708F272B3004A47F5 /* bn_mp_div_2.c */; };
+ F96D48F608F272C3004A47F5 /* bn_mp_div_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */; };
+ F96D48F708F272C3004A47F5 /* bn_mp_div_3.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427908F272B3004A47F5 /* bn_mp_div_3.c */; };
+ F96D48F808F272C3004A47F5 /* bn_mp_div_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */; };
+ F96D48FC08F272C3004A47F5 /* bn_mp_exch.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427E08F272B3004A47F5 /* bn_mp_exch.c */; };
+ F96D490508F272C3004A47F5 /* bn_mp_grow.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428708F272B3004A47F5 /* bn_mp_grow.c */; };
+ F96D490608F272C3004A47F5 /* bn_mp_init.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428808F272B3004A47F5 /* bn_mp_init.c */; };
+ F96D490708F272C3004A47F5 /* bn_mp_init_copy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428908F272B3004A47F5 /* bn_mp_init_copy.c */; };
+ F96D490808F272C3004A47F5 /* bn_mp_init_multi.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428A08F272B3004A47F5 /* bn_mp_init_multi.c */; };
+ F96D490908F272C3004A47F5 /* bn_mp_init_set.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428B08F272B3004A47F5 /* bn_mp_init_set.c */; };
+ F96D490B08F272C3004A47F5 /* bn_mp_init_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428D08F272B3004A47F5 /* bn_mp_init_size.c */; };
+ F96D491008F272C3004A47F5 /* bn_mp_karatsuba_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429208F272B3004A47F5 /* bn_mp_karatsuba_mul.c */; };
+ F96D491108F272C3004A47F5 /* bn_mp_karatsuba_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429308F272B3004A47F5 /* bn_mp_karatsuba_sqr.c */; };
+ F96D491308F272C3004A47F5 /* bn_mp_lshd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429508F272B3004A47F5 /* bn_mp_lshd.c */; };
+ F96D491408F272C3004A47F5 /* bn_mp_mod.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429608F272B3004A47F5 /* bn_mp_mod.c */; };
+ F96D491508F272C3004A47F5 /* bn_mp_mod_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429708F272B3004A47F5 /* bn_mp_mod_2d.c */; };
+ F96D491A08F272C3004A47F5 /* bn_mp_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429C08F272B3004A47F5 /* bn_mp_mul.c */; };
+ F96D491B08F272C3004A47F5 /* bn_mp_mul_2.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429D08F272B3004A47F5 /* bn_mp_mul_2.c */; };
+ F96D491C08F272C3004A47F5 /* bn_mp_mul_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429E08F272B3004A47F5 /* bn_mp_mul_2d.c */; };
+ F96D491D08F272C3004A47F5 /* bn_mp_mul_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429F08F272B3004A47F5 /* bn_mp_mul_d.c */; };
+ F96D492908F272C3004A47F5 /* bn_mp_radix_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42AB08F272B3004A47F5 /* bn_mp_radix_size.c */; };
+ F96D492A08F272C3004A47F5 /* bn_mp_radix_smap.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42AC08F272B3004A47F5 /* bn_mp_radix_smap.c */; };
+ F96D492C08F272C3004A47F5 /* bn_mp_read_radix.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42AE08F272B3004A47F5 /* bn_mp_read_radix.c */; };
+ F96D493708F272C3004A47F5 /* bn_mp_rshd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42B908F272B3004A47F5 /* bn_mp_rshd.c */; };
+ F96D493808F272C3004A47F5 /* bn_mp_set.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BA08F272B3004A47F5 /* bn_mp_set.c */; };
+ F96D493C08F272C3004A47F5 /* bn_mp_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BE08F272B3004A47F5 /* bn_mp_sqr.c */; };
+ F96D493F08F272C3004A47F5 /* bn_mp_sub.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C108F272B3004A47F5 /* bn_mp_sub.c */; };
+ F96D494008F272C3004A47F5 /* bn_mp_sub_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C208F272B3004A47F5 /* bn_mp_sub_d.c */; };
+ F96D494608F272C3004A47F5 /* bn_mp_toom_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C808F272B3004A47F5 /* bn_mp_toom_mul.c */; };
+ F96D494708F272C3004A47F5 /* bn_mp_toom_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C908F272B3004A47F5 /* bn_mp_toom_sqr.c */; };
+ F96D494908F272C3004A47F5 /* bn_mp_toradix_n.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CB08F272B3004A47F5 /* bn_mp_toradix_n.c */; };
+ F96D494C08F272C3004A47F5 /* bn_mp_zero.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CE08F272B3004A47F5 /* bn_mp_zero.c */; };
+ F96D494E08F272C3004A47F5 /* bn_reverse.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D008F272B3004A47F5 /* bn_reverse.c */; };
+ F96D494F08F272C3004A47F5 /* bn_s_mp_add.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D108F272B3004A47F5 /* bn_s_mp_add.c */; };
+ F96D495108F272C3004A47F5 /* bn_s_mp_mul_digs.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D308F272B3004A47F5 /* bn_s_mp_mul_digs.c */; };
+ F96D495308F272C3004A47F5 /* bn_s_mp_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D508F272B3004A47F5 /* bn_s_mp_sqr.c */; };
+ F96D495408F272C3004A47F5 /* bn_s_mp_sub.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D608F272B3004A47F5 /* bn_s_mp_sub.c */; };
+ F96D495508F272C3004A47F5 /* bncore.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D708F272B3004A47F5 /* bncore.c */; };
+ F96D49A908F272C4004A47F5 /* tclMacOSXBundle.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D433908F272B5004A47F5 /* tclMacOSXBundle.c */; };
+ F96D49AD08F272C4004A47F5 /* tclMacOSXFCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D433D08F272B5004A47F5 /* tclMacOSXFCmd.c */; };
+ F96D49AE08F272C4004A47F5 /* tclMacOSXNotify.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D433E08F272B5004A47F5 /* tclMacOSXNotify.c */; };
+ F96D4AC608F272C9004A47F5 /* tclLoadDyld.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D445B08F272B9004A47F5 /* tclLoadDyld.c */; settings = {COMPILER_FLAGS = "-Wno-deprecated-declarations"; }; };
+ F96D4ACA08F272C9004A47F5 /* tclUnixChan.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D445F08F272B9004A47F5 /* tclUnixChan.c */; };
+ F96D4ACB08F272C9004A47F5 /* tclUnixEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446008F272B9004A47F5 /* tclUnixEvent.c */; };
+ F96D4ACC08F272C9004A47F5 /* tclUnixFCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446108F272B9004A47F5 /* tclUnixFCmd.c */; };
+ F96D4ACD08F272C9004A47F5 /* tclUnixFile.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446208F272B9004A47F5 /* tclUnixFile.c */; };
+ F96D4ACE08F272C9004A47F5 /* tclUnixInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446308F272B9004A47F5 /* tclUnixInit.c */; settings = {COMPILER_FLAGS = "-DTCL_LIBRARY=\\\"$(TCL_LIBRARY)\\\" -DTCL_PACKAGE_PATH=\\\"$(TCL_PACKAGE_PATH)\\\""; }; };
+ F96D4ACF08F272C9004A47F5 /* tclUnixNotfy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446408F272B9004A47F5 /* tclUnixNotfy.c */; };
+ F96D4AD008F272C9004A47F5 /* tclUnixPipe.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446508F272B9004A47F5 /* tclUnixPipe.c */; };
+ F96D4AD208F272CA004A47F5 /* tclUnixSock.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446708F272B9004A47F5 /* tclUnixSock.c */; };
+ F96D4AD408F272CA004A47F5 /* tclUnixThrd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446908F272B9004A47F5 /* tclUnixThrd.c */; };
+ F96D4AD608F272CA004A47F5 /* tclUnixTime.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446B08F272B9004A47F5 /* tclUnixTime.c */; };
+ F9C9CC000E84059800E00935 /* ApplicationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9C9CBFF0E84059800E00935 /* ApplicationServices.framework */; };
+ F9DD99BD0F07DF850018B2E4 /* tkImgPNG.c in Sources */ = {isa = PBXBuildFile; fileRef = F9DD99BC0F07DF850018B2E4 /* tkImgPNG.c */; };
+ F9DD99BE0F07DF850018B2E4 /* tkImgPNG.c in Sources */ = {isa = PBXBuildFile; fileRef = F9DD99BC0F07DF850018B2E4 /* tkImgPNG.c */; };
+ F9E61D28090A481F002B3151 /* bn_mp_cmp_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */; };
+ F9E61D29090A486C002B3151 /* bn_mp_neg.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42A208F272B3004A47F5 /* bn_mp_neg.c */; };
+ F9E61D2A090A4891002B3151 /* bn_mp_sqrt.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C008F272B3004A47F5 /* bn_mp_sqrt.c */; };
+ F9E61D2B090A48A4002B3151 /* bn_mp_and.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426C08F272B3004A47F5 /* bn_mp_and.c */; };
+ F9E61D2C090A48AC002B3151 /* bn_mp_expt_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427F08F272B3004A47F5 /* bn_mp_expt_d.c */; };
+ F9E61D2D090A48BB002B3151 /* bn_mp_xor.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CD08F272B3004A47F5 /* bn_mp_xor.c */; };
+ F9E61D2E090A48BF002B3151 /* bn_mp_or.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42A308F272B3004A47F5 /* bn_mp_or.c */; };
+ F9E61D2F090A48C7002B3151 /* bn_mp_shrink.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BC08F272B3004A47F5 /* bn_mp_shrink.c */; };
+ F9E61D30090A48E2002B3151 /* bn_mp_to_unsigned_bin_n.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C708F272B3004A47F5 /* bn_mp_to_unsigned_bin_n.c */; };
+ F9E61D31090A48F9002B3151 /* bn_mp_to_unsigned_bin.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C608F272B3004A47F5 /* bn_mp_to_unsigned_bin.c */; };
+ F9E61D32090A48FA002B3151 /* bn_mp_unsigned_bin_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CC08F272B3004A47F5 /* bn_mp_unsigned_bin_size.c */; };
+ F9F4415E0C8BAE6F00BCCD67 /* tclDTrace.d in Sources */ = {isa = PBXBuildFile; fileRef = F9F4415D0C8BAE6F00BCCD67 /* tclDTrace.d */; };
+ F9FC77B80AB29E9100B7077D /* tclUnixCompat.c in Sources */ = {isa = PBXBuildFile; fileRef = F9FC77B70AB29E9100B7077D /* tclUnixCompat.c */; };
+ F9FD30BC0CC1AD070073837D /* regcomp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED008F272A7004A47F5 /* regcomp.c */; };
+ F9FD30BD0CC1AD070073837D /* regerror.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED308F272A7004A47F5 /* regerror.c */; };
+ F9FD30BE0CC1AD070073837D /* regexec.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED608F272A7004A47F5 /* regexec.c */; };
+ F9FD30BF0CC1AD070073837D /* regfree.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED708F272A7004A47F5 /* regfree.c */; };
+ F9FD30C00CC1AD070073837D /* tclAlloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDC08F272A7004A47F5 /* tclAlloc.c */; settings = {COMPILER_FLAGS = "-DUSE_TCLALLOC=0"; }; };
+ F9FD30C10CC1AD070073837D /* tclAsync.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDD08F272A7004A47F5 /* tclAsync.c */; };
+ F9FD30C20CC1AD070073837D /* tclBasic.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDE08F272A7004A47F5 /* tclBasic.c */; };
+ F9FD30C30CC1AD070073837D /* tclBinary.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDF08F272A7004A47F5 /* tclBinary.c */; };
+ F9FD30C40CC1AD070073837D /* tclCkalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE008F272A7004A47F5 /* tclCkalloc.c */; };
+ F9FD30C50CC1AD070073837D /* tclClock.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE108F272A7004A47F5 /* tclClock.c */; };
+ F9FD30C60CC1AD070073837D /* tclCmdAH.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE208F272A7004A47F5 /* tclCmdAH.c */; };
+ F9FD30C70CC1AD070073837D /* tclCmdIL.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE308F272A7004A47F5 /* tclCmdIL.c */; };
+ F9FD30C80CC1AD070073837D /* tclCmdMZ.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE408F272A7004A47F5 /* tclCmdMZ.c */; };
+ F9FD30C90CC1AD070073837D /* tclCompCmds.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE508F272A7004A47F5 /* tclCompCmds.c */; };
+ F9FD30CA0CC1AD070073837D /* tclCompExpr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE608F272A7004A47F5 /* tclCompExpr.c */; };
+ F9FD30CB0CC1AD070073837D /* tclCompile.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE708F272A7004A47F5 /* tclCompile.c */; };
+ F9FD30CC0CC1AD070073837D /* tclConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE908F272A7004A47F5 /* tclConfig.c */; };
+ F9FD30CD0CC1AD070073837D /* tclDate.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEA08F272A7004A47F5 /* tclDate.c */; };
+ F9FD30CE0CC1AD070073837D /* tclDictObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEC08F272A7004A47F5 /* tclDictObj.c */; };
+ F9FD30CF0CC1AD070073837D /* tclEncoding.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EED08F272A7004A47F5 /* tclEncoding.c */; };
+ F9FD30D00CC1AD070073837D /* tclEnv.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEE08F272A7004A47F5 /* tclEnv.c */; };
+ F9FD30D10CC1AD070073837D /* tclEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEF08F272A7004A47F5 /* tclEvent.c */; };
+ F9FD30D20CC1AD070073837D /* tclExecute.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF008F272A7004A47F5 /* tclExecute.c */; };
+ F9FD30D30CC1AD070073837D /* tclFCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF108F272A7004A47F5 /* tclFCmd.c */; };
+ F9FD30D40CC1AD070073837D /* tclFileName.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF208F272A7004A47F5 /* tclFileName.c */; };
+ F9FD30D50CC1AD070073837D /* tclGet.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF408F272A7004A47F5 /* tclGet.c */; };
+ F9FD30D60CC1AD070073837D /* tclHash.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF608F272A7004A47F5 /* tclHash.c */; };
+ F9FD30D70CC1AD070073837D /* tclHistory.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF708F272A7004A47F5 /* tclHistory.c */; };
+ F9FD30D80CC1AD070073837D /* tclIndexObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF808F272A7004A47F5 /* tclIndexObj.c */; };
+ F9FD30D90CC1AD070073837D /* tclInterp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EFC08F272A7004A47F5 /* tclInterp.c */; };
+ F9FD30DA0CC1AD070073837D /* tclIO.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EFE08F272A7004A47F5 /* tclIO.c */; };
+ F9FD30DB0CC1AD070073837D /* tclIOCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0008F272A7004A47F5 /* tclIOCmd.c */; };
+ F9FD30DC0CC1AD070073837D /* tclIOGT.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0108F272A7004A47F5 /* tclIOGT.c */; };
+ F9FD30DD0CC1AD070073837D /* tclIORChan.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0208F272A7004A47F5 /* tclIORChan.c */; };
+ F9FD30DE0CC1AD070073837D /* tclIOSock.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0308F272A7004A47F5 /* tclIOSock.c */; };
+ F9FD30DF0CC1AD070073837D /* tclIOUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0408F272A7004A47F5 /* tclIOUtil.c */; };
+ F9FD30E00CC1AD070073837D /* tclLink.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0508F272A7004A47F5 /* tclLink.c */; };
+ F9FD30E10CC1AD070073837D /* tclListObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0608F272A7004A47F5 /* tclListObj.c */; };
+ F9FD30E20CC1AD070073837D /* tclLiteral.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0708F272A7004A47F5 /* tclLiteral.c */; };
+ F9FD30E30CC1AD070073837D /* tclLoad.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0808F272A7004A47F5 /* tclLoad.c */; };
+ F9FD30E40CC1AD070073837D /* tclMain.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0A08F272A7004A47F5 /* tclMain.c */; };
+ F9FD30E50CC1AD070073837D /* tclNamesp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0B08F272A7004A47F5 /* tclNamesp.c */; };
+ F9FD30E60CC1AD070073837D /* tclNotify.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0C08F272A7004A47F5 /* tclNotify.c */; };
+ F9FD30E70CC1AD070073837D /* tclObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0D08F272A7004A47F5 /* tclObj.c */; };
+ F9FD30E80CC1AD070073837D /* tclPanic.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0E08F272A7004A47F5 /* tclPanic.c */; };
+ F9FD30E90CC1AD070073837D /* tclParse.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0F08F272A7004A47F5 /* tclParse.c */; };
+ F9FD30EA0CC1AD070073837D /* tclPathObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1108F272A7004A47F5 /* tclPathObj.c */; };
+ F9FD30EB0CC1AD070073837D /* tclPipe.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1208F272A7004A47F5 /* tclPipe.c */; };
+ F9FD30EC0CC1AD070073837D /* tclPkg.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1308F272A7004A47F5 /* tclPkg.c */; };
+ F9FD30ED0CC1AD070073837D /* tclPkgConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1408F272A7004A47F5 /* tclPkgConfig.c */; settings = {COMPILER_FLAGS = "-DCFG_INSTALL_LIBDIR=\\\"$(LIBDIR)\\\" -DCFG_INSTALL_BINDIR=\\\"$(BINDIR)\\\" -DCFG_INSTALL_SCRDIR=\\\"$(TCL_LIBRARY)\\\" -DCFG_INSTALL_INCDIR=\\\"$(INCLUDEDIR)\\\" -DCFG_INSTALL_DOCDIR=\\\"$(MANDIR)\\\" -DCFG_RUNTIME_LIBDIR=\\\"$(LIBDIR)\\\" -DCFG_RUNTIME_BINDIR=\\\"$(BINDIR)\\\" -DCFG_RUNTIME_SCRDIR=\\\"$(TCL_LIBRARY)\\\" -DCFG_RUNTIME_INCDIR=\\\"$(INCLUDEDIR)\\\" -DCFG_RUNTIME_DOCDIR=\\\"$(MANDIR)\\\""; }; };
+ F9FD30EE0CC1AD070073837D /* tclPosixStr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1708F272A7004A47F5 /* tclPosixStr.c */; };
+ F9FD30EF0CC1AD070073837D /* tclPreserve.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1808F272A7004A47F5 /* tclPreserve.c */; };
+ F9FD30F00CC1AD070073837D /* tclProc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1908F272A7004A47F5 /* tclProc.c */; };
+ F9FD30F10CC1AD070073837D /* tclRegexp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1A08F272A7004A47F5 /* tclRegexp.c */; };
+ F9FD30F20CC1AD070073837D /* tclResolve.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1C08F272A7004A47F5 /* tclResolve.c */; };
+ F9FD30F30CC1AD070073837D /* tclResult.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1D08F272A7004A47F5 /* tclResult.c */; };
+ F9FD30F40CC1AD070073837D /* tclScan.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1E08F272A7004A47F5 /* tclScan.c */; };
+ F9FD30F50CC1AD070073837D /* tclStringObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1F08F272A7004A47F5 /* tclStringObj.c */; };
+ F9FD30F60CC1AD070073837D /* tclStrToD.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2408F272A7004A47F5 /* tclStrToD.c */; };
+ F9FD30F70CC1AD070073837D /* tclStubInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2508F272A7004A47F5 /* tclStubInit.c */; };
+ F9FD30F80CC1AD070073837D /* tclStubLib.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2608F272A7004A47F5 /* tclStubLib.c */; };
+ F9FD30F90CC1AD070073837D /* tclThread.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2A08F272A7004A47F5 /* tclThread.c */; };
+ F9FD30FA0CC1AD070073837D /* tclThreadAlloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2B08F272A7004A47F5 /* tclThreadAlloc.c */; };
+ F9FD30FB0CC1AD070073837D /* tclThreadJoin.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2C08F272A7004A47F5 /* tclThreadJoin.c */; };
+ F9FD30FC0CC1AD070073837D /* tclThreadStorage.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2D08F272A7004A47F5 /* tclThreadStorage.c */; };
+ F9FD30FD0CC1AD070073837D /* tclTimer.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2F08F272A7004A47F5 /* tclTimer.c */; };
+ F9FD30FE0CC1AD070073837D /* tclTomMathInterface.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3108F272A7004A47F5 /* tclTomMathInterface.c */; };
+ F9FD30FF0CC1AD070073837D /* tclTrace.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3208F272A7004A47F5 /* tclTrace.c */; };
+ F9FD31000CC1AD070073837D /* tclUtf.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3408F272A7004A47F5 /* tclUtf.c */; };
+ F9FD31010CC1AD070073837D /* tclUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3508F272A7004A47F5 /* tclUtil.c */; };
+ F9FD31020CC1AD070073837D /* tclVar.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3608F272A7004A47F5 /* tclVar.c */; };
+ F9FD31030CC1AD070073837D /* bn_fast_s_mp_mul_digs.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426408F272B3004A47F5 /* bn_fast_s_mp_mul_digs.c */; };
+ F9FD31040CC1AD070073837D /* bn_fast_s_mp_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426608F272B3004A47F5 /* bn_fast_s_mp_sqr.c */; };
+ F9FD31050CC1AD070073837D /* bn_mp_add.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426908F272B3004A47F5 /* bn_mp_add.c */; };
+ F9FD31060CC1AD070073837D /* bn_mp_add_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426A08F272B3004A47F5 /* bn_mp_add_d.c */; };
+ F9FD31070CC1AD070073837D /* bn_mp_and.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426C08F272B3004A47F5 /* bn_mp_and.c */; };
+ F9FD31080CC1AD070073837D /* bn_mp_clamp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426D08F272B3004A47F5 /* bn_mp_clamp.c */; };
+ F9FD31090CC1AD070073837D /* bn_mp_clear.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426E08F272B3004A47F5 /* bn_mp_clear.c */; };
+ F9FD310A0CC1AD070073837D /* bn_mp_clear_multi.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426F08F272B3004A47F5 /* bn_mp_clear_multi.c */; };
+ F9FD310B0CC1AD070073837D /* bn_mp_cmp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427008F272B3004A47F5 /* bn_mp_cmp.c */; };
+ F9FD310C0CC1AD070073837D /* bn_mp_cmp_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */; };
+ F9FD310D0CC1AD070073837D /* bn_mp_cmp_mag.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */; };
+ F9FD310E0CC1AD070073837D /* bn_mp_copy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427408F272B3004A47F5 /* bn_mp_copy.c */; };
+ F9FD310F0CC1AD070073837D /* bn_mp_count_bits.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */; };
+ F9FD31100CC1AD070073837D /* bn_mp_div.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427608F272B3004A47F5 /* bn_mp_div.c */; };
+ F9FD31110CC1AD070073837D /* bn_mp_div_2.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427708F272B3004A47F5 /* bn_mp_div_2.c */; };
+ F9FD31120CC1AD070073837D /* bn_mp_div_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */; };
+ F9FD31130CC1AD070073837D /* bn_mp_div_3.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427908F272B3004A47F5 /* bn_mp_div_3.c */; };
+ F9FD31140CC1AD070073837D /* bn_mp_div_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */; };
+ F9FD31150CC1AD070073837D /* bn_mp_exch.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427E08F272B3004A47F5 /* bn_mp_exch.c */; };
+ F9FD31160CC1AD070073837D /* bn_mp_expt_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427F08F272B3004A47F5 /* bn_mp_expt_d.c */; };
+ F9FD31170CC1AD070073837D /* bn_mp_grow.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428708F272B3004A47F5 /* bn_mp_grow.c */; };
+ F9FD31180CC1AD070073837D /* bn_mp_init.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428808F272B3004A47F5 /* bn_mp_init.c */; };
+ F9FD31190CC1AD070073837D /* bn_mp_init_copy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428908F272B3004A47F5 /* bn_mp_init_copy.c */; };
+ F9FD311A0CC1AD070073837D /* bn_mp_init_multi.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428A08F272B3004A47F5 /* bn_mp_init_multi.c */; };
+ F9FD311B0CC1AD070073837D /* bn_mp_init_set.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428B08F272B3004A47F5 /* bn_mp_init_set.c */; };
+ F9FD311C0CC1AD070073837D /* bn_mp_init_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428D08F272B3004A47F5 /* bn_mp_init_size.c */; };
+ F9FD311D0CC1AD070073837D /* bn_mp_karatsuba_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429208F272B3004A47F5 /* bn_mp_karatsuba_mul.c */; };
+ F9FD311E0CC1AD070073837D /* bn_mp_karatsuba_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429308F272B3004A47F5 /* bn_mp_karatsuba_sqr.c */; };
+ F9FD311F0CC1AD070073837D /* bn_mp_lshd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429508F272B3004A47F5 /* bn_mp_lshd.c */; };
+ F9FD31200CC1AD070073837D /* bn_mp_mod.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429608F272B3004A47F5 /* bn_mp_mod.c */; };
+ F9FD31210CC1AD070073837D /* bn_mp_mod_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429708F272B3004A47F5 /* bn_mp_mod_2d.c */; };
+ F9FD31220CC1AD070073837D /* bn_mp_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429C08F272B3004A47F5 /* bn_mp_mul.c */; };
+ F9FD31230CC1AD070073837D /* bn_mp_mul_2.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429D08F272B3004A47F5 /* bn_mp_mul_2.c */; };
+ F9FD31240CC1AD070073837D /* bn_mp_mul_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429E08F272B3004A47F5 /* bn_mp_mul_2d.c */; };
+ F9FD31250CC1AD070073837D /* bn_mp_mul_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429F08F272B3004A47F5 /* bn_mp_mul_d.c */; };
+ F9FD31260CC1AD070073837D /* bn_mp_neg.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42A208F272B3004A47F5 /* bn_mp_neg.c */; };
+ F9FD31270CC1AD070073837D /* bn_mp_or.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42A308F272B3004A47F5 /* bn_mp_or.c */; };
+ F9FD31280CC1AD070073837D /* bn_mp_radix_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42AB08F272B3004A47F5 /* bn_mp_radix_size.c */; };
+ F9FD31290CC1AD070073837D /* bn_mp_radix_smap.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42AC08F272B3004A47F5 /* bn_mp_radix_smap.c */; };
+ F9FD312A0CC1AD070073837D /* bn_mp_read_radix.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42AE08F272B3004A47F5 /* bn_mp_read_radix.c */; };
+ F9FD312B0CC1AD070073837D /* bn_mp_rshd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42B908F272B3004A47F5 /* bn_mp_rshd.c */; };
+ F9FD312C0CC1AD070073837D /* bn_mp_set.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BA08F272B3004A47F5 /* bn_mp_set.c */; };
+ F9FD312D0CC1AD070073837D /* bn_mp_shrink.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BC08F272B3004A47F5 /* bn_mp_shrink.c */; };
+ F9FD312E0CC1AD070073837D /* bn_mp_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BE08F272B3004A47F5 /* bn_mp_sqr.c */; };
+ F9FD312F0CC1AD070073837D /* bn_mp_sqrt.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C008F272B3004A47F5 /* bn_mp_sqrt.c */; };
+ F9FD31300CC1AD070073837D /* bn_mp_sub.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C108F272B3004A47F5 /* bn_mp_sub.c */; };
+ F9FD31310CC1AD070073837D /* bn_mp_sub_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C208F272B3004A47F5 /* bn_mp_sub_d.c */; };
+ F9FD31320CC1AD070073837D /* bn_mp_to_unsigned_bin_n.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C708F272B3004A47F5 /* bn_mp_to_unsigned_bin_n.c */; };
+ F9FD31330CC1AD070073837D /* bn_mp_to_unsigned_bin.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C608F272B3004A47F5 /* bn_mp_to_unsigned_bin.c */; };
+ F9FD31340CC1AD070073837D /* bn_mp_toom_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C808F272B3004A47F5 /* bn_mp_toom_mul.c */; };
+ F9FD31350CC1AD070073837D /* bn_mp_toom_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C908F272B3004A47F5 /* bn_mp_toom_sqr.c */; };
+ F9FD31360CC1AD070073837D /* bn_mp_toradix_n.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CB08F272B3004A47F5 /* bn_mp_toradix_n.c */; };
+ F9FD31370CC1AD070073837D /* bn_mp_unsigned_bin_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CC08F272B3004A47F5 /* bn_mp_unsigned_bin_size.c */; };
+ F9FD31380CC1AD070073837D /* bn_mp_xor.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CD08F272B3004A47F5 /* bn_mp_xor.c */; };
+ F9FD31390CC1AD070073837D /* bn_mp_zero.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CE08F272B3004A47F5 /* bn_mp_zero.c */; };
+ F9FD313A0CC1AD070073837D /* bn_reverse.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D008F272B3004A47F5 /* bn_reverse.c */; };
+ F9FD313B0CC1AD070073837D /* bn_s_mp_add.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D108F272B3004A47F5 /* bn_s_mp_add.c */; };
+ F9FD313C0CC1AD070073837D /* bn_s_mp_mul_digs.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D308F272B3004A47F5 /* bn_s_mp_mul_digs.c */; };
+ F9FD313D0CC1AD070073837D /* bn_s_mp_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D508F272B3004A47F5 /* bn_s_mp_sqr.c */; };
+ F9FD313E0CC1AD070073837D /* bn_s_mp_sub.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D608F272B3004A47F5 /* bn_s_mp_sub.c */; };
+ F9FD313F0CC1AD070073837D /* bncore.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D708F272B3004A47F5 /* bncore.c */; };
+ F9FD31400CC1AD070073837D /* tclMacOSXBundle.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D433908F272B5004A47F5 /* tclMacOSXBundle.c */; };
+ F9FD31410CC1AD070073837D /* tclMacOSXFCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D433D08F272B5004A47F5 /* tclMacOSXFCmd.c */; };
+ F9FD31420CC1AD070073837D /* tclMacOSXNotify.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D433E08F272B5004A47F5 /* tclMacOSXNotify.c */; };
+ F9FD31430CC1AD070073837D /* tclLoadDyld.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D445B08F272B9004A47F5 /* tclLoadDyld.c */; settings = {COMPILER_FLAGS = "-Wno-deprecated-declarations"; }; };
+ F9FD31440CC1AD070073837D /* tclUnixChan.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D445F08F272B9004A47F5 /* tclUnixChan.c */; };
+ F9FD31450CC1AD070073837D /* tclUnixCompat.c in Sources */ = {isa = PBXBuildFile; fileRef = F9FC77B70AB29E9100B7077D /* tclUnixCompat.c */; };
+ F9FD31460CC1AD070073837D /* tclUnixEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446008F272B9004A47F5 /* tclUnixEvent.c */; };
+ F9FD31470CC1AD070073837D /* tclUnixFCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446108F272B9004A47F5 /* tclUnixFCmd.c */; };
+ F9FD31480CC1AD070073837D /* tclUnixFile.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446208F272B9004A47F5 /* tclUnixFile.c */; };
+ F9FD31490CC1AD070073837D /* tclUnixInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446308F272B9004A47F5 /* tclUnixInit.c */; settings = {COMPILER_FLAGS = "-DTCL_LIBRARY=\\\"$(TCL_LIBRARY)\\\" -DTCL_PACKAGE_PATH=\\\"$(TCL_PACKAGE_PATH)\\\""; }; };
+ F9FD314A0CC1AD070073837D /* tclUnixNotfy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446408F272B9004A47F5 /* tclUnixNotfy.c */; };
+ F9FD314B0CC1AD070073837D /* tclUnixPipe.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446508F272B9004A47F5 /* tclUnixPipe.c */; };
+ F9FD314C0CC1AD070073837D /* tclUnixSock.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446708F272B9004A47F5 /* tclUnixSock.c */; };
+ F9FD314D0CC1AD070073837D /* tclUnixThrd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446908F272B9004A47F5 /* tclUnixThrd.c */; };
+ F9FD314E0CC1AD070073837D /* tclUnixTime.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446B08F272B9004A47F5 /* tclUnixTime.c */; };
+ F9FD314F0CC1AD070073837D /* tk3d.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAAC08F27A39005CB29B /* tk3d.c */; };
+ F9FD31500CC1AD070073837D /* tkArgv.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAAE08F27A39005CB29B /* tkArgv.c */; };
+ F9FD31510CC1AD070073837D /* tkAtom.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAAF08F27A39005CB29B /* tkAtom.c */; };
+ F9FD31520CC1AD070073837D /* tkBind.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB008F27A39005CB29B /* tkBind.c */; };
+ F9FD31530CC1AD070073837D /* tkBitmap.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB108F27A39005CB29B /* tkBitmap.c */; };
+ F9FD31540CC1AD070073837D /* tkButton.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB208F27A39005CB29B /* tkButton.c */; };
+ F9FD31550CC1AD070073837D /* tkCanvArc.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB408F27A39005CB29B /* tkCanvArc.c */; };
+ F9FD31560CC1AD070073837D /* tkCanvas.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB508F27A39005CB29B /* tkCanvas.c */; };
+ F9FD31570CC1AD070073837D /* tkCanvBmap.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB708F27A39005CB29B /* tkCanvBmap.c */; };
+ F9FD31580CC1AD070073837D /* tkCanvImg.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB808F27A39005CB29B /* tkCanvImg.c */; };
+ F9FD31590CC1AD070073837D /* tkCanvLine.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB908F27A39005CB29B /* tkCanvLine.c */; };
+ F9FD315A0CC1AD070073837D /* tkCanvPoly.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BABA08F27A39005CB29B /* tkCanvPoly.c */; };
+ F9FD315B0CC1AD070073837D /* tkCanvPs.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BABB08F27A39005CB29B /* tkCanvPs.c */; };
+ F9FD315C0CC1AD070073837D /* tkCanvText.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BABD08F27A39005CB29B /* tkCanvText.c */; };
+ F9FD315D0CC1AD070073837D /* tkCanvUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BABE08F27A39005CB29B /* tkCanvUtil.c */; };
+ F9FD315E0CC1AD070073837D /* tkCanvWind.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BABF08F27A39005CB29B /* tkCanvWind.c */; };
+ F9FD315F0CC1AD070073837D /* tkClipboard.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAC008F27A39005CB29B /* tkClipboard.c */; };
+ F9FD31600CC1AD070073837D /* tkCmds.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAC108F27A39005CB29B /* tkCmds.c */; };
+ F9FD31610CC1AD070073837D /* tkColor.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAC208F27A39005CB29B /* tkColor.c */; };
+ F9FD31620CC1AD070073837D /* tkConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAC408F27A39005CB29B /* tkConfig.c */; };
+ F9FD31630CC1AD070073837D /* tkConsole.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAC508F27A39005CB29B /* tkConsole.c */; };
+ F9FD31640CC1AD070073837D /* tkCursor.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAC608F27A39005CB29B /* tkCursor.c */; };
+ F9FD31650CC1AD070073837D /* tkEntry.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAC808F27A39005CB29B /* tkEntry.c */; };
+ F9FD31660CC1AD070073837D /* tkError.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BACA08F27A39005CB29B /* tkError.c */; };
+ F9FD31670CC1AD070073837D /* tkEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BACB08F27A39005CB29B /* tkEvent.c */; };
+ F9FD31680CC1AD070073837D /* tkFileFilter.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BACC08F27A39005CB29B /* tkFileFilter.c */; };
+ F9FD31690CC1AD070073837D /* tkFocus.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BACE08F27A39005CB29B /* tkFocus.c */; };
+ F9FD316A0CC1AD070073837D /* tkFont.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BACF08F27A39005CB29B /* tkFont.c */; };
+ F9FD316B0CC1AD070073837D /* tkFrame.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD108F27A39005CB29B /* tkFrame.c */; };
+ F9FD316C0CC1AD070073837D /* tkGC.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD208F27A39005CB29B /* tkGC.c */; };
+ F9FD316D0CC1AD070073837D /* tkGeometry.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD308F27A39005CB29B /* tkGeometry.c */; };
+ F9FD316E0CC1AD070073837D /* tkGet.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD408F27A39005CB29B /* tkGet.c */; };
+ F9FD316F0CC1AD070073837D /* tkGrab.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD508F27A39005CB29B /* tkGrab.c */; };
+ F9FD31700CC1AD070073837D /* tkGrid.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD608F27A39005CB29B /* tkGrid.c */; };
+ F9FD31710CC1AD070073837D /* tkImage.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD708F27A39005CB29B /* tkImage.c */; };
+ F9FD31720CC1AD070073837D /* tkImgBmap.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD808F27A39005CB29B /* tkImgBmap.c */; };
+ F9FD31730CC1AD070073837D /* tkImgGIF.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD908F27A39005CB29B /* tkImgGIF.c */; };
+ F9FD31740CC1AD070073837D /* tkImgPhoto.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BADA08F27A39005CB29B /* tkImgPhoto.c */; };
+ F9FD31750CC1AD070073837D /* tkImgPPM.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BADB08F27A39005CB29B /* tkImgPPM.c */; };
+ F9FD31760CC1AD070073837D /* tkListbox.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAE408F27A39005CB29B /* tkListbox.c */; };
+ F9FD31770CC1AD070073837D /* tkMacWinMenu.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAE508F27A39005CB29B /* tkMacWinMenu.c */; };
+ F9FD31780CC1AD070073837D /* tkMain.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAE608F27A39005CB29B /* tkMain.c */; };
+ F9FD31790CC1AD070073837D /* tkMenu.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAE708F27A39005CB29B /* tkMenu.c */; };
+ F9FD317A0CC1AD070073837D /* tkMenubutton.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAE908F27A39005CB29B /* tkMenubutton.c */; };
+ F9FD317B0CC1AD070073837D /* tkMenuDraw.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAEB08F27A39005CB29B /* tkMenuDraw.c */; };
+ F9FD317C0CC1AD070073837D /* tkMessage.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAEC08F27A39005CB29B /* tkMessage.c */; };
+ F9FD317D0CC1AD070073837D /* tkObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAED08F27A39005CB29B /* tkObj.c */; };
+ F9FD317E0CC1AD070073837D /* tkOldConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAEE08F27A39005CB29B /* tkOldConfig.c */; };
+ F9FD317F0CC1AD070073837D /* tkOldTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAFE08F27A39005CB29B /* tkOldTest.c */; };
+ F9FD31800CC1AD070073837D /* tkOption.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAEF08F27A39005CB29B /* tkOption.c */; };
+ F9FD31810CC1AD070073837D /* tkPack.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAF008F27A39005CB29B /* tkPack.c */; };
+ F9FD31820CC1AD070073837D /* tkPanedWindow.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAF108F27A39005CB29B /* tkPanedWindow.c */; };
+ F9FD31830CC1AD070073837D /* tkPlace.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAF208F27A39005CB29B /* tkPlace.c */; };
+ F9FD31850CC1AD070073837D /* tkRectOval.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAF608F27A39005CB29B /* tkRectOval.c */; };
+ F9FD31860CC1AD070073837D /* tkScale.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAF708F27A39005CB29B /* tkScale.c */; };
+ F9FD31870CC1AD070073837D /* tkScrollbar.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAF908F27A39005CB29B /* tkScrollbar.c */; };
+ F9FD31880CC1AD070073837D /* tkSelect.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAFB08F27A39005CB29B /* tkSelect.c */; };
+ F9FD31890CC1AD070073837D /* tkSquare.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAFD08F27A39005CB29B /* tkSquare.c */; };
+ F9FD318A0CC1AD070073837D /* tkStubInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAFF08F27A39005CB29B /* tkStubInit.c */; };
+ F9FD318B0CC1AD070073837D /* tkStubLib.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0008F27A39005CB29B /* tkStubLib.c */; };
+ F9FD318C0CC1AD070073837D /* tkStyle.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0108F27A39005CB29B /* tkStyle.c */; };
+ F9FD318D0CC1AD070073837D /* tkTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0208F27A39005CB29B /* tkTest.c */; };
+ F9FD318E0CC1AD070073837D /* tkText.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0308F27A39005CB29B /* tkText.c */; };
+ F9FD318F0CC1AD070073837D /* tkTextBTree.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0508F27A39005CB29B /* tkTextBTree.c */; };
+ F9FD31900CC1AD070073837D /* tkTextDisp.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0608F27A39005CB29B /* tkTextDisp.c */; };
+ F9FD31910CC1AD070073837D /* tkTextImage.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0808F27A39005CB29B /* tkTextImage.c */; };
+ F9FD31920CC1AD070073837D /* tkTextIndex.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0908F27A39005CB29B /* tkTextIndex.c */; };
+ F9FD31930CC1AD070073837D /* tkTextMark.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0A08F27A39005CB29B /* tkTextMark.c */; };
+ F9FD31940CC1AD070073837D /* tkTextTag.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0B08F27A39005CB29B /* tkTextTag.c */; };
+ F9FD31950CC1AD070073837D /* tkTextWind.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0C08F27A39005CB29B /* tkTextWind.c */; };
+ F9FD31960CC1AD070073837D /* tkTrig.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0D08F27A39005CB29B /* tkTrig.c */; };
+ F9FD31970CC1AD070073837D /* tkUndo.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0E08F27A39005CB29B /* tkUndo.c */; };
+ F9FD31980CC1AD070073837D /* tkUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB1008F27A39005CB29B /* tkUtil.c */; };
+ F9FD31990CC1AD070073837D /* tkVisual.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB1108F27A39005CB29B /* tkVisual.c */; };
+ F9FD319A0CC1AD070073837D /* tkWindow.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB1208F27A39005CB29B /* tkWindow.c */; };
+ F9FD319B0CC1AD070073837D /* ttkBlink.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E10AF786D5000797B5 /* ttkBlink.c */; };
+ F9FD319C0CC1AD070073837D /* ttkButton.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E20AF786D5000797B5 /* ttkButton.c */; };
+ F9FD319D0CC1AD070073837D /* ttkCache.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E30AF786D5000797B5 /* ttkCache.c */; };
+ F9FD319E0CC1AD070073837D /* ttkClamTheme.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E40AF786D5000797B5 /* ttkClamTheme.c */; };
+ F9FD319F0CC1AD070073837D /* ttkClassicTheme.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E50AF786D5000797B5 /* ttkClassicTheme.c */; };
+ F9FD31A00CC1AD070073837D /* ttkDefaultTheme.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E70AF786D5000797B5 /* ttkDefaultTheme.c */; };
+ F9FD31A10CC1AD070073837D /* ttkElements.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E80AF786D5000797B5 /* ttkElements.c */; };
+ F9FD31A20CC1AD070073837D /* ttkEntry.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E90AF786D5000797B5 /* ttkEntry.c */; };
+ F9FD31A30CC1AD070073837D /* ttkFrame.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887EA0AF786D5000797B5 /* ttkFrame.c */; };
+ F9FD31A40CC1AD070073837D /* ttkImage.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887EB0AF786D5000797B5 /* ttkImage.c */; };
+ F9FD31A50CC1AD070073837D /* ttkInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887EC0AF786D5000797B5 /* ttkInit.c */; };
+ F9FD31A60CC1AD070073837D /* ttkLabel.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887ED0AF786D5000797B5 /* ttkLabel.c */; };
+ F9FD31A70CC1AD070073837D /* ttkLayout.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887EE0AF786D5000797B5 /* ttkLayout.c */; };
+ F9FD31A80CC1AD070073837D /* ttkManager.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887EF0AF786D5000797B5 /* ttkManager.c */; };
+ F9FD31A90CC1AD070073837D /* ttkNotebook.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F10AF786D5000797B5 /* ttkNotebook.c */; };
+ F9FD31AA0CC1AD070073837D /* ttkPanedwindow.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F20AF786D5000797B5 /* ttkPanedwindow.c */; };
+ F9FD31AB0CC1AD070073837D /* ttkProgress.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F30AF786D5000797B5 /* ttkProgress.c */; };
+ F9FD31AC0CC1AD070073837D /* ttkScale.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F40AF786D5000797B5 /* ttkScale.c */; };
+ F9FD31AD0CC1AD070073837D /* ttkScroll.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F50AF786D5000797B5 /* ttkScroll.c */; };
+ F9FD31AE0CC1AD070073837D /* ttkScrollbar.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F60AF786D5000797B5 /* ttkScrollbar.c */; };
+ F9FD31AF0CC1AD070073837D /* ttkSeparator.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F70AF786D5000797B5 /* ttkSeparator.c */; };
+ F9FD31B00CC1AD070073837D /* ttkSquare.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F80AF786D5000797B5 /* ttkSquare.c */; };
+ F9FD31B10CC1AD070073837D /* ttkState.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F90AF786D5000797B5 /* ttkState.c */; };
+ F9FD31B20CC1AD070073837D /* ttkStubInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887FA0AF786D5000797B5 /* ttkStubInit.c */; };
+ F9FD31B30CC1AD070073837D /* ttkStubLib.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887FB0AF786D5000797B5 /* ttkStubLib.c */; };
+ F9FD31B40CC1AD070073837D /* ttkTagSet.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887FC0AF786D5000797B5 /* ttkTagSet.c */; };
+ F9FD31B50CC1AD070073837D /* ttkTheme.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887FD0AF786D5000797B5 /* ttkTheme.c */; };
+ F9FD31B60CC1AD070073837D /* ttkTrace.c in Sources */ = {isa = PBXBuildFile; fileRef = F96888000AF786D5000797B5 /* ttkTrace.c */; };
+ F9FD31B70CC1AD070073837D /* ttkTrack.c in Sources */ = {isa = PBXBuildFile; fileRef = F96888010AF786D5000797B5 /* ttkTrack.c */; };
+ F9FD31B80CC1AD070073837D /* ttkTreeview.c in Sources */ = {isa = PBXBuildFile; fileRef = F96888020AF786D5000797B5 /* ttkTreeview.c */; };
+ F9FD31B90CC1AD070073837D /* ttkWidget.c in Sources */ = {isa = PBXBuildFile; fileRef = F96888030AF786D5000797B5 /* ttkWidget.c */; };
+ F9FD31DA0CC1AD070073837D /* tkAppInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC7508F27A3D005CB29B /* tkAppInit.c */; settings = {COMPILER_FLAGS = "-DTK_TEST"; }; };
+ F9FD31DB0CC1AD070073837D /* tkUnix3d.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC7908F27A3D005CB29B /* tkUnix3d.c */; };
+ F9FD31DC0CC1AD070073837D /* tkUnixScale.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC8C08F27A3D005CB29B /* tkUnixScale.c */; };
+ F9FD31E20CC1AD070073837D /* tclDTrace.d in Sources */ = {isa = PBXBuildFile; fileRef = F9F4415D0C8BAE6F00BCCD67 /* tclDTrace.d */; };
+ F9FD31E40CC1AD070073837D /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F966C07408F2820D005CB29B /* CoreFoundation.framework */; };
+ F9FD31F80CC1ADB70073837D /* tkUnixCursor.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC7D08F27A3D005CB29B /* tkUnixCursor.c */; };
+ F9FD31FA0CC1ADB70073837D /* tkUnixKey.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC8708F27A3D005CB29B /* tkUnixKey.c */; };
+ F9FD31FB0CC1ADB70073837D /* tkUnixXId.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC9108F27A3D005CB29B /* tkUnixXId.c */; };
+ F9FD31FC0CC1ADB70073837D /* tkUnixInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC8508F27A3D005CB29B /* tkUnixInit.c */; };
+ F9FD31FD0CC1ADB70073837D /* tkUnixEmbed.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC8108F27A3D005CB29B /* tkUnixEmbed.c */; };
+ F9FD31FE0CC1ADB70073837D /* tkUnixSend.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC8F08F27A3D005CB29B /* tkUnixSend.c */; };
+ F9FD31FF0CC1ADB70073837D /* tkUnixFocus.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC8308F27A3D005CB29B /* tkUnixFocus.c */; };
+ F9FD32000CC1ADB70073837D /* tkUnixWm.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC9008F27A3D005CB29B /* tkUnixWm.c */; };
+ F9FD32010CC1ADB70073837D /* tkUnixRFont.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC8B08F27A3D005CB29B /* tkUnixRFont.c */; };
+ F9FD32020CC1ADB70073837D /* tkUnix.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC7808F27A3D005CB29B /* tkUnix.c */; };
+ F9FD32030CC1ADB70073837D /* tkUnixMenu.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC8808F27A3D005CB29B /* tkUnixMenu.c */; };
+ F9FD32040CC1ADB70073837D /* tkUnixConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC7C08F27A3D005CB29B /* tkUnixConfig.c */; };
+ F9FD32050CC1ADB70073837D /* tkUnixDraw.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC8008F27A3D005CB29B /* tkUnixDraw.c */; };
+ F9FD32060CC1ADB70073837D /* tkUnixDialog.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC7F08F27A3D005CB29B /* tkUnixDialog.c */; };
+ F9FD32070CC1ADB70073837D /* tkUnixSelect.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC8E08F27A3D005CB29B /* tkUnixSelect.c */; };
+ F9FD32080CC1ADB70073837D /* tkUnixEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC8208F27A3D005CB29B /* tkUnixEvent.c */; };
+ F9FD32090CC1ADB70073837D /* tkUnixColor.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC7B08F27A3D005CB29B /* tkUnixColor.c */; };
+ F9FD320A0CC1ADB70073837D /* tkUnixButton.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC7A08F27A3D005CB29B /* tkUnixButton.c */; };
+ F9FD320B0CC1ADB70073837D /* tkUnixMenubu.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC8908F27A3D005CB29B /* tkUnixMenubu.c */; };
+ F9FD320C0CC1ADB70073837D /* tkUnixScrlbr.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC8D08F27A3D005CB29B /* tkUnixScrlbr.c */; };
+ F9FD32170CC1AF170073837D /* libX11.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F9FD32140CC1AF170073837D /* libX11.dylib */; };
+ F9FD32180CC1AF170073837D /* libXext.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F9FD32150CC1AF170073837D /* libXext.dylib */; };
+ F9FD32190CC1AF170073837D /* libXss.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F9FD32160CC1AF170073837D /* libXss.dylib */; };
+ F9FD349B0CC1BB0D0073837D /* libfreetype.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F9FD34990CC1BB0D0073837D /* libfreetype.dylib */; };
+ F9FD349C0CC1BB0D0073837D /* libXft.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F9FD349A0CC1BB0D0073837D /* libXft.dylib */; };
+ F9FD34C40CC1BBD70073837D /* libfontconfig.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F9FD34C30CC1BBD70073837D /* libfontconfig.dylib */; };
+ F9FFAF1D0DFDDB26007F8A6A /* tclIORTrans.c in Sources */ = {isa = PBXBuildFile; fileRef = F95D77E90DFD820D00A8BF6F /* tclIORTrans.c */; };
+ F9FFAF1F0DFDDB2F007F8A6A /* tclOO.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599B20DF1F75400E04F67 /* tclOO.c */; };
+ F9FFAF200DFDDB32007F8A6A /* tclOOBasic.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599B60DF1F76100E04F67 /* tclOOBasic.c */; };
+ F9FFAF210DFDDB32007F8A6A /* tclOOCall.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599B80DF1F76600E04F67 /* tclOOCall.c */; };
+ F9FFAF220DFDDB34007F8A6A /* tclOODefineCmds.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599BB0DF1F77000E04F67 /* tclOODefineCmds.c */; };
+ F9FFAF230DFDDB35007F8A6A /* tclOOInfo.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599BD0DF1F77400E04F67 /* tclOOInfo.c */; };
+ F9FFAF240DFDDB36007F8A6A /* tclOOMethod.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599C10DF1F78300E04F67 /* tclOOMethod.c */; };
+ F9FFAF250DFDDB37007F8A6A /* tclOOStubInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599C30DF1F78800E04F67 /* tclOOStubInit.c */; };
+ F9FFAF260DFDDB38007F8A6A /* tclOOStubLib.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599C50DF1F78D00E04F67 /* tclOOStubLib.c */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 8DD76FB20486AB0100D96B5E /* tktest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tktest; sourceTree = BUILT_PRODUCTS_DIR; };
+ F9099B8A0CC67D30005A9580 /* textpeer.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = textpeer.tcl; sourceTree = "<group>"; };
+ F9099B8B0CC67D3E005A9580 /* ttkbut.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = ttkbut.tcl; sourceTree = "<group>"; };
+ F9152B080EAF8A5000CD5C7B /* tkBusy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkBusy.c; sourceTree = "<group>"; };
+ F91543270EF201A90032D1E8 /* fontchoose.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fontchoose.tcl; sourceTree = "<group>"; };
+ F915432A0EF201CF0032D1E8 /* zlib.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = zlib.test; sourceTree = "<group>"; };
+ F915432D0EF201EE0032D1E8 /* zlib.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = zlib.n; sourceTree = "<group>"; };
+ F9183E640EFC80CD0030B814 /* throw.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = throw.n; sourceTree = "<group>"; };
+ F9183E650EFC80D70030B814 /* try.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = try.n; sourceTree = "<group>"; };
+ F9183E6A0EFC81560030B814 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F9183E8F0EFC817B0030B814 /* tdbc */ = {isa = PBXFileReference; lastKnownFileType = folder; path = tdbc; sourceTree = "<group>"; };
+ F91DC23C0E44C51B002CB8D1 /* nre.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = nre.test; sourceTree = "<group>"; };
+ F91E62260C1AE686006C9D96 /* Tclsh-Info.plist.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = "Tclsh-Info.plist.in"; sourceTree = "<group>"; };
+ F92240290D7C620F005EC715 /* knightstour.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = knightstour.tcl; sourceTree = "<group>"; };
+ F92D7F100DE777240033A13A /* tsdPerf.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tsdPerf.tcl; sourceTree = "<group>"; };
+ F92EE8BE0E62F846001A6E80 /* tkImgPhInstance.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkImgPhInstance.c; sourceTree = "<group>"; };
+ F93599B20DF1F75400E04F67 /* tclOO.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOO.c; sourceTree = "<group>"; };
+ F93599B40DF1F75900E04F67 /* tclOO.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclOO.decls; sourceTree = "<group>"; };
+ F93599B50DF1F75D00E04F67 /* tclOO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclOO.h; sourceTree = "<group>"; };
+ F93599B60DF1F76100E04F67 /* tclOOBasic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOBasic.c; sourceTree = "<group>"; };
+ F93599B80DF1F76600E04F67 /* tclOOCall.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOCall.c; sourceTree = "<group>"; };
+ F93599BA0DF1F76A00E04F67 /* tclOODecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclOODecls.h; sourceTree = "<group>"; };
+ F93599BB0DF1F77000E04F67 /* tclOODefineCmds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOODefineCmds.c; sourceTree = "<group>"; };
+ F93599BD0DF1F77400E04F67 /* tclOOInfo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOInfo.c; sourceTree = "<group>"; };
+ F93599BF0DF1F77900E04F67 /* tclOOInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclOOInt.h; sourceTree = "<group>"; };
+ F93599C00DF1F77D00E04F67 /* tclOOIntDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclOOIntDecls.h; sourceTree = "<group>"; };
+ F93599C10DF1F78300E04F67 /* tclOOMethod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOMethod.c; sourceTree = "<group>"; };
+ F93599C30DF1F78800E04F67 /* tclOOStubInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOStubInit.c; sourceTree = "<group>"; };
+ F93599C50DF1F78D00E04F67 /* tclOOStubLib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOStubLib.c; sourceTree = "<group>"; };
+ F93599C80DF1F81900E04F67 /* oo.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = oo.test; sourceTree = "<group>"; };
+ F93599CF0DF1F87F00E04F67 /* Class.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Class.3; sourceTree = "<group>"; };
+ F93599D00DF1F89E00E04F67 /* class.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = class.n; sourceTree = "<group>"; };
+ F93599D20DF1F8DF00E04F67 /* copy.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = copy.n; sourceTree = "<group>"; };
+ F93599D30DF1F8F500E04F67 /* define.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = define.n; sourceTree = "<group>"; };
+ F93599D40DF1F91900E04F67 /* Method.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Method.3; sourceTree = "<group>"; };
+ F93599D50DF1F93700E04F67 /* my.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = my.n; sourceTree = "<group>"; };
+ F93599D60DF1F95000E04F67 /* next.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = next.n; sourceTree = "<group>"; };
+ F93599D70DF1F96800E04F67 /* object.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = object.n; sourceTree = "<group>"; };
+ F93599D80DF1F98300E04F67 /* self.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = self.n; sourceTree = "<group>"; };
+ F936FCD70CCD984500716967 /* ttkprogress.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = ttkprogress.tcl; sourceTree = "<group>"; };
+ F936FCD80CCD984600716967 /* tree.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tree.tcl; sourceTree = "<group>"; };
+ F936FCD90CCD984600716967 /* toolbar.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = toolbar.tcl; sourceTree = "<group>"; };
+ F936FCDA0CCD984600716967 /* ttknote.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = ttknote.tcl; sourceTree = "<group>"; };
+ F936FCDB0CCD984600716967 /* combo.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = combo.tcl; sourceTree = "<group>"; };
+ F93E5EFD09CF8711008FA367 /* tkMacOSXFont.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMacOSXFont.h; sourceTree = "<group>"; };
+ F94523A10E6FC2AC00C1D987 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
+ F946FB8B0FBE3AED00CD6495 /* itcl */ = {isa = PBXFileReference; lastKnownFileType = folder; path = itcl; sourceTree = "<group>"; };
+ F95D77E90DFD820D00A8BF6F /* tclIORTrans.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIORTrans.c; sourceTree = "<group>"; };
+ F95D8D4B0F1715610006B020 /* Tk.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = Tk.icns; sourceTree = "<group>"; };
+ F95D8D4C0F1715610006B020 /* Tk.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = Tk.tiff; sourceTree = "<group>"; };
+ F95FAFF90B34F1130072E431 /* macOSXLoad.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = macOSXLoad.test; sourceTree = "<group>"; };
+ F962F7C60DADC26200648DB8 /* vsapi.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = vsapi.test; sourceTree = "<group>"; };
+ F96437C90EF0D4B2003F468E /* tclZlib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclZlib.c; sourceTree = "<group>"; };
+ F96437E60EF0D652003F468E /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = /usr/lib/libz.dylib; sourceTree = "<absolute>"; };
+ F966BA0408F27A37005CB29B /* error.xbm */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = error.xbm; sourceTree = "<group>"; };
+ F966BA0508F27A37005CB29B /* gray12.xbm */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = gray12.xbm; sourceTree = "<group>"; };
+ F966BA0608F27A37005CB29B /* gray25.xbm */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = gray25.xbm; sourceTree = "<group>"; };
+ F966BA0708F27A37005CB29B /* gray50.xbm */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = gray50.xbm; sourceTree = "<group>"; };
+ F966BA0808F27A37005CB29B /* gray75.xbm */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = gray75.xbm; sourceTree = "<group>"; };
+ F966BA0908F27A37005CB29B /* hourglass.xbm */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = hourglass.xbm; sourceTree = "<group>"; };
+ F966BA0A08F27A37005CB29B /* info.xbm */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = info.xbm; sourceTree = "<group>"; };
+ F966BA0B08F27A37005CB29B /* questhead.xbm */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = questhead.xbm; sourceTree = "<group>"; };
+ F966BA0C08F27A37005CB29B /* question.xbm */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = question.xbm; sourceTree = "<group>"; };
+ F966BA0D08F27A37005CB29B /* warning.xbm */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = warning.xbm; sourceTree = "<group>"; };
+ F966BA0E08F27A37005CB29B /* ChangeLog */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = ChangeLog; sourceTree = "<group>"; };
+ F966BA0F08F27A37005CB29B /* changes */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = changes; sourceTree = "<group>"; };
+ F966BA1108F27A37005CB29B /* 3DBorder.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = 3DBorder.3; sourceTree = "<group>"; };
+ F966BA1208F27A37005CB29B /* AddOption.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AddOption.3; sourceTree = "<group>"; };
+ F966BA1308F27A37005CB29B /* bell.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = bell.n; sourceTree = "<group>"; };
+ F966BA1408F27A37005CB29B /* bind.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = bind.n; sourceTree = "<group>"; };
+ F966BA1508F27A37005CB29B /* BindTable.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = BindTable.3; sourceTree = "<group>"; };
+ F966BA1608F27A37005CB29B /* bindtags.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = bindtags.n; sourceTree = "<group>"; };
+ F966BA1708F27A37005CB29B /* bitmap.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = bitmap.n; sourceTree = "<group>"; };
+ F966BA1808F27A37005CB29B /* button.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = button.n; sourceTree = "<group>"; };
+ F966BA1908F27A37005CB29B /* canvas.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = canvas.n; sourceTree = "<group>"; };
+ F966BA1A08F27A37005CB29B /* CanvPsY.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CanvPsY.3; sourceTree = "<group>"; };
+ F966BA1B08F27A37005CB29B /* CanvTkwin.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CanvTkwin.3; sourceTree = "<group>"; };
+ F966BA1C08F27A37005CB29B /* CanvTxtInfo.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CanvTxtInfo.3; sourceTree = "<group>"; };
+ F966BA1D08F27A37005CB29B /* checkbutton.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = checkbutton.n; sourceTree = "<group>"; };
+ F966BA1E08F27A37005CB29B /* chooseColor.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = chooseColor.n; sourceTree = "<group>"; };
+ F966BA1F08F27A37005CB29B /* chooseDirectory.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = chooseDirectory.n; sourceTree = "<group>"; };
+ F966BA2008F27A37005CB29B /* Clipboard.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Clipboard.3; sourceTree = "<group>"; };
+ F966BA2108F27A37005CB29B /* clipboard.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = clipboard.n; sourceTree = "<group>"; };
+ F966BA2208F27A37005CB29B /* ClrSelect.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ClrSelect.3; sourceTree = "<group>"; };
+ F966BA2308F27A37005CB29B /* colors.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = colors.n; sourceTree = "<group>"; };
+ F966BA2408F27A37005CB29B /* ConfigWidg.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ConfigWidg.3; sourceTree = "<group>"; };
+ F966BA2508F27A37005CB29B /* ConfigWind.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ConfigWind.3; sourceTree = "<group>"; };
+ F966BA2608F27A37005CB29B /* console.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = console.n; sourceTree = "<group>"; };
+ F966BA2708F27A37005CB29B /* CoordToWin.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CoordToWin.3; sourceTree = "<group>"; };
+ F966BA2808F27A37005CB29B /* CrtCmHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtCmHdlr.3; sourceTree = "<group>"; };
+ F966BA2908F27A37005CB29B /* CrtErrHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtErrHdlr.3; sourceTree = "<group>"; };
+ F966BA2A08F27A37005CB29B /* CrtGenHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtGenHdlr.3; sourceTree = "<group>"; };
+ F966BA2B08F27A37005CB29B /* CrtImgType.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtImgType.3; sourceTree = "<group>"; };
+ F966BA2C08F27A37005CB29B /* CrtItemType.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtItemType.3; sourceTree = "<group>"; };
+ F966BA2D08F27A37005CB29B /* CrtPhImgFmt.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtPhImgFmt.3; sourceTree = "<group>"; };
+ F966BA2E08F27A37005CB29B /* CrtSelHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtSelHdlr.3; sourceTree = "<group>"; };
+ F966BA2F08F27A37005CB29B /* CrtWindow.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtWindow.3; sourceTree = "<group>"; };
+ F966BA3008F27A37005CB29B /* cursors.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = cursors.n; sourceTree = "<group>"; };
+ F966BA3108F27A37005CB29B /* DeleteImg.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DeleteImg.3; sourceTree = "<group>"; };
+ F966BA3208F27A37005CB29B /* destroy.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = destroy.n; sourceTree = "<group>"; };
+ F966BA3308F27A37005CB29B /* dialog.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = dialog.n; sourceTree = "<group>"; };
+ F966BA3408F27A37005CB29B /* DrawFocHlt.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DrawFocHlt.3; sourceTree = "<group>"; };
+ F966BA3508F27A37005CB29B /* entry.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = entry.n; sourceTree = "<group>"; };
+ F966BA3608F27A37005CB29B /* event.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = event.n; sourceTree = "<group>"; };
+ F966BA3708F27A37005CB29B /* EventHndlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = EventHndlr.3; sourceTree = "<group>"; };
+ F966BA3808F27A37005CB29B /* FindPhoto.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = FindPhoto.3; sourceTree = "<group>"; };
+ F966BA3908F27A37005CB29B /* focus.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = focus.n; sourceTree = "<group>"; };
+ F966BA3A08F27A37005CB29B /* focusNext.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = focusNext.n; sourceTree = "<group>"; };
+ F966BA3B08F27A37005CB29B /* font.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = font.n; sourceTree = "<group>"; };
+ F966BA3C08F27A37005CB29B /* FontId.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = FontId.3; sourceTree = "<group>"; };
+ F966BA3D08F27A37005CB29B /* frame.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = frame.n; sourceTree = "<group>"; };
+ F966BA3E08F27A37005CB29B /* FreeXId.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = FreeXId.3; sourceTree = "<group>"; };
+ F966BA3F08F27A37005CB29B /* GeomReq.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GeomReq.3; sourceTree = "<group>"; };
+ F966BA4008F27A37005CB29B /* GetAnchor.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetAnchor.3; sourceTree = "<group>"; };
+ F966BA4108F27A37005CB29B /* GetBitmap.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetBitmap.3; sourceTree = "<group>"; };
+ F966BA4208F27A37005CB29B /* GetCapStyl.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetCapStyl.3; sourceTree = "<group>"; };
+ F966BA4308F27A37005CB29B /* GetClrmap.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetClrmap.3; sourceTree = "<group>"; };
+ F966BA4408F27A37005CB29B /* GetColor.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetColor.3; sourceTree = "<group>"; };
+ F966BA4508F27A37005CB29B /* GetCursor.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetCursor.3; sourceTree = "<group>"; };
+ F966BA4608F27A37005CB29B /* GetDash.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetDash.3; sourceTree = "<group>"; };
+ F966BA4708F27A37005CB29B /* GetFont.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetFont.3; sourceTree = "<group>"; };
+ F966BA4808F27A37005CB29B /* GetGC.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetGC.3; sourceTree = "<group>"; };
+ F966BA4908F27A37005CB29B /* GetHINSTANCE.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetHINSTANCE.3; sourceTree = "<group>"; };
+ F966BA4A08F27A37005CB29B /* GetHWND.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetHWND.3; sourceTree = "<group>"; };
+ F966BA4B08F27A37005CB29B /* GetImage.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetImage.3; sourceTree = "<group>"; };
+ F966BA4C08F27A37005CB29B /* GetJoinStl.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetJoinStl.3; sourceTree = "<group>"; };
+ F966BA4D08F27A37005CB29B /* GetJustify.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetJustify.3; sourceTree = "<group>"; };
+ F966BA4E08F27A37005CB29B /* getOpenFile.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = getOpenFile.n; sourceTree = "<group>"; };
+ F966BA4F08F27A37005CB29B /* GetOption.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetOption.3; sourceTree = "<group>"; };
+ F966BA5008F27A38005CB29B /* GetPixels.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetPixels.3; sourceTree = "<group>"; };
+ F966BA5108F27A38005CB29B /* GetPixmap.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetPixmap.3; sourceTree = "<group>"; };
+ F966BA5208F27A38005CB29B /* GetRelief.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetRelief.3; sourceTree = "<group>"; };
+ F966BA5308F27A38005CB29B /* GetRootCrd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetRootCrd.3; sourceTree = "<group>"; };
+ F966BA5408F27A38005CB29B /* GetScroll.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetScroll.3; sourceTree = "<group>"; };
+ F966BA5508F27A38005CB29B /* GetSelect.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetSelect.3; sourceTree = "<group>"; };
+ F966BA5608F27A38005CB29B /* GetUid.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetUid.3; sourceTree = "<group>"; };
+ F966BA5708F27A38005CB29B /* GetVisual.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetVisual.3; sourceTree = "<group>"; };
+ F966BA5808F27A38005CB29B /* GetVRoot.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetVRoot.3; sourceTree = "<group>"; };
+ F966BA5908F27A38005CB29B /* Grab.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Grab.3; sourceTree = "<group>"; };
+ F966BA5A08F27A38005CB29B /* grab.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = grab.n; sourceTree = "<group>"; };
+ F966BA5B08F27A38005CB29B /* grid.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = grid.n; sourceTree = "<group>"; };
+ F966BA5C08F27A38005CB29B /* HandleEvent.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = HandleEvent.3; sourceTree = "<group>"; };
+ F966BA5D08F27A38005CB29B /* HWNDToWindow.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = HWNDToWindow.3; sourceTree = "<group>"; };
+ F966BA5E08F27A38005CB29B /* IdToWindow.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = IdToWindow.3; sourceTree = "<group>"; };
+ F966BA5F08F27A38005CB29B /* image.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = image.n; sourceTree = "<group>"; };
+ F966BA6008F27A38005CB29B /* ImgChanged.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ImgChanged.3; sourceTree = "<group>"; };
+ F966BA6108F27A38005CB29B /* Inactive.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Inactive.3; sourceTree = "<group>"; };
+ F966BA6208F27A38005CB29B /* InternAtom.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = InternAtom.3; sourceTree = "<group>"; };
+ F966BA6308F27A38005CB29B /* keysyms.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = keysyms.n; sourceTree = "<group>"; };
+ F966BA6408F27A38005CB29B /* label.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = label.n; sourceTree = "<group>"; };
+ F966BA6508F27A38005CB29B /* labelframe.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = labelframe.n; sourceTree = "<group>"; };
+ F966BA6608F27A38005CB29B /* listbox.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = listbox.n; sourceTree = "<group>"; };
+ F966BA6708F27A38005CB29B /* loadTk.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = loadTk.n; sourceTree = "<group>"; };
+ F966BA6808F27A38005CB29B /* lower.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lower.n; sourceTree = "<group>"; };
+ F966BA6908F27A38005CB29B /* MainLoop.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = MainLoop.3; sourceTree = "<group>"; };
+ F966BA6A08F27A38005CB29B /* MaintGeom.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = MaintGeom.3; sourceTree = "<group>"; };
+ F966BA6B08F27A38005CB29B /* MainWin.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = MainWin.3; sourceTree = "<group>"; };
+ F966BA6D08F27A38005CB29B /* ManageGeom.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ManageGeom.3; sourceTree = "<group>"; };
+ F966BA6E08F27A38005CB29B /* MapWindow.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = MapWindow.3; sourceTree = "<group>"; };
+ F966BA6F08F27A38005CB29B /* MeasureChar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = MeasureChar.3; sourceTree = "<group>"; };
+ F966BA7008F27A38005CB29B /* menu.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = menu.n; sourceTree = "<group>"; };
+ F966BA7108F27A38005CB29B /* menubar.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = menubar.n; sourceTree = "<group>"; };
+ F966BA7208F27A38005CB29B /* menubutton.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = menubutton.n; sourceTree = "<group>"; };
+ F966BA7308F27A38005CB29B /* message.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = message.n; sourceTree = "<group>"; };
+ F966BA7408F27A38005CB29B /* messageBox.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = messageBox.n; sourceTree = "<group>"; };
+ F966BA7508F27A38005CB29B /* MoveToplev.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = MoveToplev.3; sourceTree = "<group>"; };
+ F966BA7608F27A38005CB29B /* Name.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Name.3; sourceTree = "<group>"; };
+ F966BA7708F27A38005CB29B /* NameOfImg.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = NameOfImg.3; sourceTree = "<group>"; };
+ F966BA7808F27A38005CB29B /* option.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = option.n; sourceTree = "<group>"; };
+ F966BA7908F27A38005CB29B /* optionMenu.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = optionMenu.n; sourceTree = "<group>"; };
+ F966BA7A08F27A38005CB29B /* options.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = options.n; sourceTree = "<group>"; };
+ F966BA7B08F27A38005CB29B /* OwnSelect.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = OwnSelect.3; sourceTree = "<group>"; };
+ F966BA7C08F27A38005CB29B /* pack-old.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = "pack-old.n"; sourceTree = "<group>"; };
+ F966BA7D08F27A38005CB29B /* pack.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = pack.n; sourceTree = "<group>"; };
+ F966BA7E08F27A38005CB29B /* palette.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = palette.n; sourceTree = "<group>"; };
+ F966BA7F08F27A38005CB29B /* panedwindow.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = panedwindow.n; sourceTree = "<group>"; };
+ F966BA8008F27A38005CB29B /* ParseArgv.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ParseArgv.3; sourceTree = "<group>"; };
+ F966BA8108F27A38005CB29B /* photo.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = photo.n; sourceTree = "<group>"; };
+ F966BA8208F27A38005CB29B /* place.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = place.n; sourceTree = "<group>"; };
+ F966BA8308F27A38005CB29B /* popup.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = popup.n; sourceTree = "<group>"; };
+ F966BA8408F27A38005CB29B /* QWinEvent.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = QWinEvent.3; sourceTree = "<group>"; };
+ F966BA8508F27A38005CB29B /* radiobutton.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = radiobutton.n; sourceTree = "<group>"; };
+ F966BA8608F27A38005CB29B /* raise.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = raise.n; sourceTree = "<group>"; };
+ F966BA8708F27A38005CB29B /* Restack.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Restack.3; sourceTree = "<group>"; };
+ F966BA8808F27A38005CB29B /* RestrictEv.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RestrictEv.3; sourceTree = "<group>"; };
+ F966BA8908F27A38005CB29B /* scale.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = scale.n; sourceTree = "<group>"; };
+ F966BA8A08F27A38005CB29B /* scrollbar.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = scrollbar.n; sourceTree = "<group>"; };
+ F966BA8B08F27A38005CB29B /* selection.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = selection.n; sourceTree = "<group>"; };
+ F966BA8C08F27A38005CB29B /* send.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = send.n; sourceTree = "<group>"; };
+ F966BA8D08F27A38005CB29B /* SetAppName.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetAppName.3; sourceTree = "<group>"; };
+ F966BA8E08F27A38005CB29B /* SetCaret.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetCaret.3; sourceTree = "<group>"; };
+ F966BA8F08F27A38005CB29B /* SetClass.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetClass.3; sourceTree = "<group>"; };
+ F966BA9008F27A38005CB29B /* SetClassProcs.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetClassProcs.3; sourceTree = "<group>"; };
+ F966BA9108F27A38005CB29B /* SetGrid.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetGrid.3; sourceTree = "<group>"; };
+ F966BA9208F27A38005CB29B /* SetOptions.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetOptions.3; sourceTree = "<group>"; };
+ F966BA9308F27A38005CB29B /* SetVisual.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetVisual.3; sourceTree = "<group>"; };
+ F966BA9408F27A38005CB29B /* spinbox.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = spinbox.n; sourceTree = "<group>"; };
+ F966BA9508F27A38005CB29B /* StrictMotif.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StrictMotif.3; sourceTree = "<group>"; };
+ F966BA9608F27A38005CB29B /* text.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = text.n; sourceTree = "<group>"; };
+ F966BA9708F27A38005CB29B /* TextLayout.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TextLayout.3; sourceTree = "<group>"; };
+ F966BA9808F27A38005CB29B /* tk.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tk.n; sourceTree = "<group>"; };
+ F966BA9A08F27A38005CB29B /* Tk_Init.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Tk_Init.3; sourceTree = "<group>"; };
+ F966BA9B08F27A38005CB29B /* Tk_Main.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Tk_Main.3; sourceTree = "<group>"; };
+ F966BA9C08F27A38005CB29B /* tkerror.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tkerror.n; sourceTree = "<group>"; };
+ F966BA9D08F27A38005CB29B /* TkInitStubs.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TkInitStubs.3; sourceTree = "<group>"; };
+ F966BA9E08F27A38005CB29B /* tkvars.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tkvars.n; sourceTree = "<group>"; };
+ F966BA9F08F27A38005CB29B /* tkwait.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tkwait.n; sourceTree = "<group>"; };
+ F966BAA008F27A38005CB29B /* toplevel.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = toplevel.n; sourceTree = "<group>"; };
+ F966BAA108F27A38005CB29B /* WindowId.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = WindowId.3; sourceTree = "<group>"; };
+ F966BAA208F27A38005CB29B /* winfo.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = winfo.n; sourceTree = "<group>"; };
+ F966BAA308F27A38005CB29B /* wish.1 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = wish.1; sourceTree = "<group>"; };
+ F966BAA408F27A38005CB29B /* wm.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = wm.n; sourceTree = "<group>"; };
+ F966BAA608F27A38005CB29B /* default.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = default.h; sourceTree = "<group>"; };
+ F966BAA708F27A38005CB29B /* ks_names.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ks_names.h; sourceTree = "<group>"; };
+ F966BAA908F27A39005CB29B /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F966BAAA08F27A39005CB29B /* tk.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tk.decls; sourceTree = "<group>"; };
+ F966BAAB08F27A39005CB29B /* tk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tk.h; sourceTree = "<group>"; };
+ F966BAAC08F27A39005CB29B /* tk3d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tk3d.c; sourceTree = "<group>"; };
+ F966BAAD08F27A39005CB29B /* tk3d.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tk3d.h; sourceTree = "<group>"; };
+ F966BAAE08F27A39005CB29B /* tkArgv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkArgv.c; sourceTree = "<group>"; };
+ F966BAAF08F27A39005CB29B /* tkAtom.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkAtom.c; sourceTree = "<group>"; };
+ F966BAB008F27A39005CB29B /* tkBind.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkBind.c; sourceTree = "<group>"; };
+ F966BAB108F27A39005CB29B /* tkBitmap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkBitmap.c; sourceTree = "<group>"; };
+ F966BAB208F27A39005CB29B /* tkButton.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkButton.c; sourceTree = "<group>"; };
+ F966BAB308F27A39005CB29B /* tkButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkButton.h; sourceTree = "<group>"; };
+ F966BAB408F27A39005CB29B /* tkCanvArc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkCanvArc.c; sourceTree = "<group>"; };
+ F966BAB508F27A39005CB29B /* tkCanvas.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkCanvas.c; sourceTree = "<group>"; };
+ F966BAB608F27A39005CB29B /* tkCanvas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkCanvas.h; sourceTree = "<group>"; };
+ F966BAB708F27A39005CB29B /* tkCanvBmap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkCanvBmap.c; sourceTree = "<group>"; };
+ F966BAB808F27A39005CB29B /* tkCanvImg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkCanvImg.c; sourceTree = "<group>"; };
+ F966BAB908F27A39005CB29B /* tkCanvLine.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkCanvLine.c; sourceTree = "<group>"; };
+ F966BABA08F27A39005CB29B /* tkCanvPoly.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkCanvPoly.c; sourceTree = "<group>"; };
+ F966BABB08F27A39005CB29B /* tkCanvPs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkCanvPs.c; sourceTree = "<group>"; };
+ F966BABD08F27A39005CB29B /* tkCanvText.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkCanvText.c; sourceTree = "<group>"; };
+ F966BABE08F27A39005CB29B /* tkCanvUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkCanvUtil.c; sourceTree = "<group>"; };
+ F966BABF08F27A39005CB29B /* tkCanvWind.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkCanvWind.c; sourceTree = "<group>"; };
+ F966BAC008F27A39005CB29B /* tkClipboard.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkClipboard.c; sourceTree = "<group>"; };
+ F966BAC108F27A39005CB29B /* tkCmds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkCmds.c; sourceTree = "<group>"; };
+ F966BAC208F27A39005CB29B /* tkColor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkColor.c; sourceTree = "<group>"; };
+ F966BAC308F27A39005CB29B /* tkColor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkColor.h; sourceTree = "<group>"; };
+ F966BAC408F27A39005CB29B /* tkConfig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkConfig.c; sourceTree = "<group>"; };
+ F966BAC508F27A39005CB29B /* tkConsole.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkConsole.c; sourceTree = "<group>"; };
+ F966BAC608F27A39005CB29B /* tkCursor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkCursor.c; sourceTree = "<group>"; };
+ F966BAC708F27A39005CB29B /* tkDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkDecls.h; sourceTree = "<group>"; };
+ F966BAC808F27A39005CB29B /* tkEntry.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkEntry.c; sourceTree = "<group>"; };
+ F966BAC908F27A39005CB29B /* tkEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkEntry.h; sourceTree = "<group>"; };
+ F966BACA08F27A39005CB29B /* tkError.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkError.c; sourceTree = "<group>"; };
+ F966BACB08F27A39005CB29B /* tkEvent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkEvent.c; sourceTree = "<group>"; };
+ F966BACC08F27A39005CB29B /* tkFileFilter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkFileFilter.c; sourceTree = "<group>"; };
+ F966BACD08F27A39005CB29B /* tkFileFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkFileFilter.h; sourceTree = "<group>"; };
+ F966BACE08F27A39005CB29B /* tkFocus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkFocus.c; sourceTree = "<group>"; };
+ F966BACF08F27A39005CB29B /* tkFont.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkFont.c; sourceTree = "<group>"; };
+ F966BAD008F27A39005CB29B /* tkFont.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkFont.h; sourceTree = "<group>"; };
+ F966BAD108F27A39005CB29B /* tkFrame.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkFrame.c; sourceTree = "<group>"; };
+ F966BAD208F27A39005CB29B /* tkGC.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkGC.c; sourceTree = "<group>"; };
+ F966BAD308F27A39005CB29B /* tkGeometry.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkGeometry.c; sourceTree = "<group>"; };
+ F966BAD408F27A39005CB29B /* tkGet.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkGet.c; sourceTree = "<group>"; };
+ F966BAD508F27A39005CB29B /* tkGrab.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkGrab.c; sourceTree = "<group>"; };
+ F966BAD608F27A39005CB29B /* tkGrid.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkGrid.c; sourceTree = "<group>"; };
+ F966BAD708F27A39005CB29B /* tkImage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkImage.c; sourceTree = "<group>"; };
+ F966BAD808F27A39005CB29B /* tkImgBmap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkImgBmap.c; sourceTree = "<group>"; };
+ F966BAD908F27A39005CB29B /* tkImgGIF.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkImgGIF.c; sourceTree = "<group>"; };
+ F966BADA08F27A39005CB29B /* tkImgPhoto.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkImgPhoto.c; sourceTree = "<group>"; };
+ F966BADB08F27A39005CB29B /* tkImgPPM.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkImgPPM.c; sourceTree = "<group>"; };
+ F966BADC08F27A39005CB29B /* tkImgUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkImgUtil.c; sourceTree = "<group>"; };
+ F966BADE08F27A39005CB29B /* tkInt.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tkInt.decls; sourceTree = "<group>"; };
+ F966BADF08F27A39005CB29B /* tkInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkInt.h; sourceTree = "<group>"; };
+ F966BAE108F27A39005CB29B /* tkIntDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkIntDecls.h; sourceTree = "<group>"; };
+ F966BAE208F27A39005CB29B /* tkIntPlatDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkIntPlatDecls.h; sourceTree = "<group>"; };
+ F966BAE308F27A39005CB29B /* tkIntXlibDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkIntXlibDecls.h; sourceTree = "<group>"; };
+ F966BAE408F27A39005CB29B /* tkListbox.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkListbox.c; sourceTree = "<group>"; };
+ F966BAE508F27A39005CB29B /* tkMacWinMenu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkMacWinMenu.c; sourceTree = "<group>"; };
+ F966BAE608F27A39005CB29B /* tkMain.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkMain.c; sourceTree = "<group>"; };
+ F966BAE708F27A39005CB29B /* tkMenu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkMenu.c; sourceTree = "<group>"; };
+ F966BAE808F27A39005CB29B /* tkMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMenu.h; sourceTree = "<group>"; };
+ F966BAE908F27A39005CB29B /* tkMenubutton.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkMenubutton.c; sourceTree = "<group>"; };
+ F966BAEA08F27A39005CB29B /* tkMenubutton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMenubutton.h; sourceTree = "<group>"; };
+ F966BAEB08F27A39005CB29B /* tkMenuDraw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkMenuDraw.c; sourceTree = "<group>"; };
+ F966BAEC08F27A39005CB29B /* tkMessage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkMessage.c; sourceTree = "<group>"; };
+ F966BAED08F27A39005CB29B /* tkObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkObj.c; sourceTree = "<group>"; };
+ F966BAEE08F27A39005CB29B /* tkOldConfig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkOldConfig.c; sourceTree = "<group>"; };
+ F966BAEF08F27A39005CB29B /* tkOption.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkOption.c; sourceTree = "<group>"; };
+ F966BAF008F27A39005CB29B /* tkPack.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkPack.c; sourceTree = "<group>"; };
+ F966BAF108F27A39005CB29B /* tkPanedWindow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkPanedWindow.c; sourceTree = "<group>"; };
+ F966BAF208F27A39005CB29B /* tkPlace.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkPlace.c; sourceTree = "<group>"; };
+ F966BAF308F27A39005CB29B /* tkPlatDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkPlatDecls.h; sourceTree = "<group>"; };
+ F966BAF408F27A39005CB29B /* tkPointer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkPointer.c; sourceTree = "<group>"; };
+ F966BAF508F27A39005CB29B /* tkPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkPort.h; sourceTree = "<group>"; };
+ F966BAF608F27A39005CB29B /* tkRectOval.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkRectOval.c; sourceTree = "<group>"; };
+ F966BAF708F27A39005CB29B /* tkScale.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkScale.c; sourceTree = "<group>"; };
+ F966BAF808F27A39005CB29B /* tkScale.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkScale.h; sourceTree = "<group>"; };
+ F966BAF908F27A39005CB29B /* tkScrollbar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkScrollbar.c; sourceTree = "<group>"; };
+ F966BAFA08F27A39005CB29B /* tkScrollbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkScrollbar.h; sourceTree = "<group>"; };
+ F966BAFB08F27A39005CB29B /* tkSelect.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkSelect.c; sourceTree = "<group>"; };
+ F966BAFC08F27A39005CB29B /* tkSelect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkSelect.h; sourceTree = "<group>"; };
+ F966BAFD08F27A39005CB29B /* tkSquare.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkSquare.c; sourceTree = "<group>"; };
+ F966BAFE08F27A39005CB29B /* tkOldTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkOldTest.c; sourceTree = "<group>"; };
+ F966BAFF08F27A39005CB29B /* tkStubInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkStubInit.c; sourceTree = "<group>"; };
+ F966BB0008F27A39005CB29B /* tkStubLib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkStubLib.c; sourceTree = "<group>"; };
+ F966BB0108F27A39005CB29B /* tkStyle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkStyle.c; sourceTree = "<group>"; };
+ F966BB0208F27A39005CB29B /* tkTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkTest.c; sourceTree = "<group>"; };
+ F966BB0308F27A39005CB29B /* tkText.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkText.c; sourceTree = "<group>"; };
+ F966BB0408F27A39005CB29B /* tkText.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkText.h; sourceTree = "<group>"; };
+ F966BB0508F27A39005CB29B /* tkTextBTree.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkTextBTree.c; sourceTree = "<group>"; };
+ F966BB0608F27A39005CB29B /* tkTextDisp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkTextDisp.c; sourceTree = "<group>"; };
+ F966BB0808F27A39005CB29B /* tkTextImage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkTextImage.c; sourceTree = "<group>"; };
+ F966BB0908F27A39005CB29B /* tkTextIndex.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkTextIndex.c; sourceTree = "<group>"; };
+ F966BB0A08F27A39005CB29B /* tkTextMark.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkTextMark.c; sourceTree = "<group>"; };
+ F966BB0B08F27A39005CB29B /* tkTextTag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkTextTag.c; sourceTree = "<group>"; };
+ F966BB0C08F27A39005CB29B /* tkTextWind.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkTextWind.c; sourceTree = "<group>"; };
+ F966BB0D08F27A39005CB29B /* tkTrig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkTrig.c; sourceTree = "<group>"; };
+ F966BB0E08F27A39005CB29B /* tkUndo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUndo.c; sourceTree = "<group>"; };
+ F966BB0F08F27A39005CB29B /* tkUndo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkUndo.h; sourceTree = "<group>"; };
+ F966BB1008F27A39005CB29B /* tkUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUtil.c; sourceTree = "<group>"; };
+ F966BB1108F27A39005CB29B /* tkVisual.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkVisual.c; sourceTree = "<group>"; };
+ F966BB1208F27A39005CB29B /* tkWindow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWindow.c; sourceTree = "<group>"; };
+ F966BB1408F27A39005CB29B /* bgerror.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = bgerror.tcl; sourceTree = "<group>"; };
+ F966BB1508F27A39005CB29B /* button.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = button.tcl; sourceTree = "<group>"; };
+ F966BB1608F27A39005CB29B /* choosedir.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = choosedir.tcl; sourceTree = "<group>"; };
+ F966BB1708F27A39005CB29B /* clrpick.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = clrpick.tcl; sourceTree = "<group>"; };
+ F966BB1808F27A39005CB29B /* comdlg.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = comdlg.tcl; sourceTree = "<group>"; };
+ F966BB1908F27A39005CB29B /* console.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = console.tcl; sourceTree = "<group>"; };
+ F966BB1B08F27A39005CB29B /* anilabel.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = anilabel.tcl; sourceTree = "<group>"; };
+ F966BB1C08F27A39005CB29B /* aniwave.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = aniwave.tcl; sourceTree = "<group>"; };
+ F966BB1D08F27A39005CB29B /* arrow.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = arrow.tcl; sourceTree = "<group>"; };
+ F966BB1E08F27A39005CB29B /* bind.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = bind.tcl; sourceTree = "<group>"; };
+ F966BB1F08F27A39005CB29B /* bitmap.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = bitmap.tcl; sourceTree = "<group>"; };
+ F966BB2008F27A39005CB29B /* browse */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = browse; sourceTree = "<group>"; };
+ F966BB2108F27A39005CB29B /* button.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = button.tcl; sourceTree = "<group>"; };
+ F966BB2208F27A39005CB29B /* check.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = check.tcl; sourceTree = "<group>"; };
+ F966BB2308F27A39005CB29B /* clrpick.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = clrpick.tcl; sourceTree = "<group>"; };
+ F966BB2408F27A39005CB29B /* colors.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = colors.tcl; sourceTree = "<group>"; };
+ F966BB2508F27A39005CB29B /* cscroll.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cscroll.tcl; sourceTree = "<group>"; };
+ F966BB2608F27A39005CB29B /* ctext.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = ctext.tcl; sourceTree = "<group>"; };
+ F966BB2708F27A39005CB29B /* dialog1.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dialog1.tcl; sourceTree = "<group>"; };
+ F966BB2808F27A39005CB29B /* dialog2.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dialog2.tcl; sourceTree = "<group>"; };
+ F966BB2A08F27A39005CB29B /* entry1.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = entry1.tcl; sourceTree = "<group>"; };
+ F966BB2B08F27A39005CB29B /* entry2.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = entry2.tcl; sourceTree = "<group>"; };
+ F966BB2C08F27A39005CB29B /* entry3.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = entry3.tcl; sourceTree = "<group>"; };
+ F966BB2D08F27A39005CB29B /* filebox.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = filebox.tcl; sourceTree = "<group>"; };
+ F966BB2E08F27A39005CB29B /* floor.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = floor.tcl; sourceTree = "<group>"; };
+ F966BB2F08F27A39005CB29B /* form.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = form.tcl; sourceTree = "<group>"; };
+ F966BB3008F27A39005CB29B /* goldberg.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = goldberg.tcl; sourceTree = "<group>"; };
+ F966BB3108F27A39005CB29B /* hello */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = hello; sourceTree = "<group>"; };
+ F966BB3208F27A39005CB29B /* hscale.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = hscale.tcl; sourceTree = "<group>"; };
+ F966BB3308F27A39005CB29B /* icon.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = icon.tcl; sourceTree = "<group>"; };
+ F966BB3408F27A39005CB29B /* image1.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = image1.tcl; sourceTree = "<group>"; };
+ F966BB3508F27A39005CB29B /* image2.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = image2.tcl; sourceTree = "<group>"; };
+ F966BB4208F27A3A005CB29B /* items.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = items.tcl; sourceTree = "<group>"; };
+ F966BB4308F27A3A005CB29B /* ixset */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = ixset; sourceTree = "<group>"; };
+ F966BB4408F27A3A005CB29B /* label.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = label.tcl; sourceTree = "<group>"; };
+ F966BB4508F27A3A005CB29B /* labelframe.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = labelframe.tcl; sourceTree = "<group>"; };
+ F966BB4608F27A3A005CB29B /* menu.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = menu.tcl; sourceTree = "<group>"; };
+ F966BB4708F27A3A005CB29B /* menubu.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = menubu.tcl; sourceTree = "<group>"; };
+ F966BB4808F27A3A005CB29B /* msgbox.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = msgbox.tcl; sourceTree = "<group>"; };
+ F966BB4A08F27A3A005CB29B /* paned1.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = paned1.tcl; sourceTree = "<group>"; };
+ F966BB4B08F27A3A005CB29B /* paned2.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = paned2.tcl; sourceTree = "<group>"; };
+ F966BB4C08F27A3A005CB29B /* pendulum.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pendulum.tcl; sourceTree = "<group>"; };
+ F966BB4D08F27A3A005CB29B /* plot.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = plot.tcl; sourceTree = "<group>"; };
+ F966BB4E08F27A3A005CB29B /* puzzle.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = puzzle.tcl; sourceTree = "<group>"; };
+ F966BB4F08F27A3A005CB29B /* radio.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = radio.tcl; sourceTree = "<group>"; };
+ F966BB5008F27A3A005CB29B /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F966BB5108F27A3A005CB29B /* rmt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = rmt; sourceTree = "<group>"; };
+ F966BB5208F27A3A005CB29B /* rolodex */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = rolodex; sourceTree = "<group>"; };
+ F966BB5308F27A3A005CB29B /* ruler.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = ruler.tcl; sourceTree = "<group>"; };
+ F966BB5408F27A3A005CB29B /* sayings.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = sayings.tcl; sourceTree = "<group>"; };
+ F966BB5508F27A3A005CB29B /* search.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = search.tcl; sourceTree = "<group>"; };
+ F966BB5608F27A3A005CB29B /* spin.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = spin.tcl; sourceTree = "<group>"; };
+ F966BB5708F27A3A005CB29B /* square */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = square; sourceTree = "<group>"; };
+ F966BB5808F27A3A005CB29B /* states.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = states.tcl; sourceTree = "<group>"; };
+ F966BB5908F27A3A005CB29B /* style.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = style.tcl; sourceTree = "<group>"; };
+ F966BB5A08F27A3A005CB29B /* tclIndex */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclIndex; sourceTree = "<group>"; };
+ F966BB5B08F27A3A005CB29B /* tcolor */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = tcolor; sourceTree = "<group>"; };
+ F966BB5C08F27A3A005CB29B /* text.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = text.tcl; sourceTree = "<group>"; };
+ F966BB5D08F27A3A005CB29B /* timer */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = timer; sourceTree = "<group>"; };
+ F966BB5E08F27A3A005CB29B /* twind.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = twind.tcl; sourceTree = "<group>"; };
+ F966BB5F08F27A3A005CB29B /* unicodeout.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unicodeout.tcl; sourceTree = "<group>"; };
+ F966BB6008F27A3A005CB29B /* vscale.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = vscale.tcl; sourceTree = "<group>"; };
+ F966BB6108F27A3A005CB29B /* widget */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = widget; sourceTree = "<group>"; };
+ F966BB6208F27A3A005CB29B /* dialog.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dialog.tcl; sourceTree = "<group>"; };
+ F966BB6308F27A3A005CB29B /* entry.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = entry.tcl; sourceTree = "<group>"; };
+ F966BB6408F27A3A005CB29B /* focus.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = focus.tcl; sourceTree = "<group>"; };
+ F966BB7308F27A3A005CB29B /* listbox.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = listbox.tcl; sourceTree = "<group>"; };
+ F966BB7408F27A3A005CB29B /* menu.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = menu.tcl; sourceTree = "<group>"; };
+ F966BB7508F27A3A005CB29B /* mkpsenc.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = mkpsenc.tcl; sourceTree = "<group>"; };
+ F966BB7608F27A3A005CB29B /* msgbox.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = msgbox.tcl; sourceTree = "<group>"; };
+ F966BB8608F27A3A005CB29B /* obsolete.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = obsolete.tcl; sourceTree = "<group>"; };
+ F966BB8708F27A3A005CB29B /* optMenu.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = optMenu.tcl; sourceTree = "<group>"; };
+ F966BB8808F27A3A005CB29B /* palette.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = palette.tcl; sourceTree = "<group>"; };
+ F966BB8908F27A3B005CB29B /* panedwindow.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = panedwindow.tcl; sourceTree = "<group>"; };
+ F966BB8B08F27A3B005CB29B /* safetk.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = safetk.tcl; sourceTree = "<group>"; };
+ F966BB8C08F27A3B005CB29B /* scale.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = scale.tcl; sourceTree = "<group>"; };
+ F966BB8D08F27A3B005CB29B /* scrlbar.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = scrlbar.tcl; sourceTree = "<group>"; };
+ F966BB8E08F27A3B005CB29B /* spinbox.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = spinbox.tcl; sourceTree = "<group>"; };
+ F966BB8F08F27A3B005CB29B /* tclIndex */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclIndex; sourceTree = "<group>"; };
+ F966BB9008F27A3B005CB29B /* tearoff.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tearoff.tcl; sourceTree = "<group>"; };
+ F966BB9108F27A3B005CB29B /* text.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = text.tcl; sourceTree = "<group>"; };
+ F966BB9208F27A3B005CB29B /* tk.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tk.tcl; sourceTree = "<group>"; };
+ F966BB9308F27A3B005CB29B /* tkfbox.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tkfbox.tcl; sourceTree = "<group>"; };
+ F966BB9408F27A3B005CB29B /* unsupported.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unsupported.tcl; sourceTree = "<group>"; };
+ F966BB9508F27A3B005CB29B /* xmfbox.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = xmfbox.tcl; sourceTree = "<group>"; };
+ F966BB9608F27A3B005CB29B /* license.terms */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = license.terms; sourceTree = "<group>"; };
+ F966BBBA08F27A3B005CB29B /* configure.ac */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure.ac; sourceTree = "<group>"; };
+ F966BBBB08F27A3B005CB29B /* GNUmakefile */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = GNUmakefile; sourceTree = "<group>"; };
+ F966BBBE08F27A3B005CB29B /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F966BBC008F27A3B005CB29B /* Tk-Info.plist.in */ = {isa = PBXFileReference; explicitFileType = text.plist; fileEncoding = 4; path = "Tk-Info.plist.in"; sourceTree = "<group>"; };
+ F966BBC208F27A3B005CB29B /* tkMacOSX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMacOSX.h; sourceTree = "<group>"; };
+ F966BBC508F27A3B005CB29B /* tkMacOSXBitmap.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXBitmap.c; sourceTree = "<group>"; };
+ F966BBC608F27A3B005CB29B /* tkMacOSXButton.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXButton.c; sourceTree = "<group>"; };
+ F966BBC808F27A3B005CB29B /* tkMacOSXClipboard.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXClipboard.c; sourceTree = "<group>"; };
+ F966BBC908F27A3B005CB29B /* tkMacOSXColor.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXColor.c; sourceTree = "<group>"; };
+ F966BBCA08F27A3B005CB29B /* tkMacOSXConfig.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXConfig.c; sourceTree = "<group>"; };
+ F966BBCB08F27A3B005CB29B /* tkMacOSXCursor.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXCursor.c; sourceTree = "<group>"; };
+ F966BBCC08F27A3B005CB29B /* tkMacOSXCursors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMacOSXCursors.h; sourceTree = "<group>"; };
+ F966BBCD08F27A3B005CB29B /* tkMacOSXDebug.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXDebug.c; sourceTree = "<group>"; };
+ F966BBCE08F27A3B005CB29B /* tkMacOSXDebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMacOSXDebug.h; sourceTree = "<group>"; };
+ F966BBCF08F27A3B005CB29B /* tkMacOSXDefault.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMacOSXDefault.h; sourceTree = "<group>"; };
+ F966BBD008F27A3B005CB29B /* tkMacOSXDialog.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXDialog.c; sourceTree = "<group>"; };
+ F966BBD108F27A3B005CB29B /* tkMacOSXDraw.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXDraw.c; sourceTree = "<group>"; };
+ F966BBD208F27A3B005CB29B /* tkMacOSXEmbed.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXEmbed.c; sourceTree = "<group>"; };
+ F966BBD308F27A3B005CB29B /* tkMacOSXEntry.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXEntry.c; sourceTree = "<group>"; };
+ F966BBD408F27A3B005CB29B /* tkMacOSXEvent.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXEvent.c; sourceTree = "<group>"; };
+ F966BBD508F27A3B005CB29B /* tkMacOSXEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMacOSXEvent.h; sourceTree = "<group>"; };
+ F966BBD608F27A3B005CB29B /* tkMacOSXFont.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXFont.c; sourceTree = "<group>"; };
+ F966BBD708F27A3B005CB29B /* tkMacOSXHLEvents.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXHLEvents.c; sourceTree = "<group>"; };
+ F966BBD808F27A3B005CB29B /* tkMacOSXInit.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXInit.c; sourceTree = "<group>"; };
+ F966BBDA08F27A3B005CB29B /* tkMacOSXInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMacOSXInt.h; sourceTree = "<group>"; };
+ F966BBDB08F27A3B005CB29B /* tkMacOSXKeyboard.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXKeyboard.c; sourceTree = "<group>"; };
+ F966BBDC08F27A3B005CB29B /* tkMacOSXKeyEvent.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXKeyEvent.c; sourceTree = "<group>"; };
+ F966BBDD08F27A3B005CB29B /* tkMacOSXMenu.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXMenu.c; sourceTree = "<group>"; };
+ F966BBE008F27A3B005CB29B /* tkMacOSXMenubutton.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXMenubutton.c; sourceTree = "<group>"; };
+ F966BBE108F27A3B005CB29B /* tkMacOSXMenus.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXMenus.c; sourceTree = "<group>"; };
+ F966BBE208F27A3B005CB29B /* tkMacOSXMouseEvent.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXMouseEvent.c; sourceTree = "<group>"; };
+ F966BBE308F27A3B005CB29B /* tkMacOSXNotify.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXNotify.c; sourceTree = "<group>"; };
+ F966BBEA08F27A3C005CB29B /* tkMacOSXPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMacOSXPort.h; sourceTree = "<group>"; };
+ F966BBEB08F27A3C005CB29B /* tkMacOSXRegion.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXRegion.c; sourceTree = "<group>"; };
+ F966BBEC08F27A3C005CB29B /* tkMacOSXScale.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXScale.c; sourceTree = "<group>"; };
+ F966BBED08F27A3C005CB29B /* tkMacOSXScrlbr.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXScrlbr.c; sourceTree = "<group>"; };
+ F966BBEE08F27A3C005CB29B /* tkMacOSXSend.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXSend.c; sourceTree = "<group>"; };
+ F966BBEF08F27A3C005CB29B /* tkMacOSXSubwindows.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXSubwindows.c; sourceTree = "<group>"; };
+ F966BBF008F27A3C005CB29B /* tkMacOSXTest.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXTest.c; sourceTree = "<group>"; };
+ F966BBF108F27A3C005CB29B /* tkMacOSXWindowEvent.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXWindowEvent.c; sourceTree = "<group>"; };
+ F966BBF208F27A3C005CB29B /* tkMacOSXWm.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXWm.c; sourceTree = "<group>"; };
+ F966BBF308F27A3C005CB29B /* tkMacOSXWm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMacOSXWm.h; sourceTree = "<group>"; };
+ F966BBF408F27A3C005CB29B /* tkMacOSXXCursors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMacOSXXCursors.h; sourceTree = "<group>"; };
+ F966BBF508F27A3C005CB29B /* tkMacOSXXStubs.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXXStubs.c; sourceTree = "<group>"; };
+ F966BBF708F27A3C005CB29B /* Wish-Info.plist.in */ = {isa = PBXFileReference; explicitFileType = text.plist; fileEncoding = 4; path = "Wish-Info.plist.in"; sourceTree = "<group>"; };
+ F966BC0308F27A3C005CB29B /* README */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = README; sourceTree = "<group>"; };
+ F966BC0508F27A3C005CB29B /* all.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = all.tcl; sourceTree = "<group>"; };
+ F966BC0608F27A3C005CB29B /* arc.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = arc.tcl; sourceTree = "<group>"; };
+ F966BC0708F27A3C005CB29B /* bell.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = bell.test; sourceTree = "<group>"; };
+ F966BC0808F27A3C005CB29B /* bevel.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = bevel.tcl; sourceTree = "<group>"; };
+ F966BC0908F27A3C005CB29B /* bgerror.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = bgerror.test; sourceTree = "<group>"; };
+ F966BC0A08F27A3C005CB29B /* bind.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = bind.test; sourceTree = "<group>"; };
+ F966BC0B08F27A3C005CB29B /* bitmap.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = bitmap.test; sourceTree = "<group>"; };
+ F966BC0C08F27A3C005CB29B /* border.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = border.test; sourceTree = "<group>"; };
+ F966BC0D08F27A3C005CB29B /* bugs.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = bugs.tcl; sourceTree = "<group>"; };
+ F966BC0E08F27A3C005CB29B /* butGeom.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = butGeom.tcl; sourceTree = "<group>"; };
+ F966BC0F08F27A3C005CB29B /* butGeom2.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = butGeom2.tcl; sourceTree = "<group>"; };
+ F966BC1008F27A3C005CB29B /* button.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = button.test; sourceTree = "<group>"; };
+ F966BC1108F27A3C005CB29B /* canvas.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = canvas.test; sourceTree = "<group>"; };
+ F966BC1208F27A3C005CB29B /* canvImg.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = canvImg.test; sourceTree = "<group>"; };
+ F966BC1308F27A3C005CB29B /* canvPs.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = canvPs.test; sourceTree = "<group>"; };
+ F966BC1408F27A3C005CB29B /* canvPsArc.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = canvPsArc.tcl; sourceTree = "<group>"; };
+ F966BC1508F27A3C005CB29B /* canvPsBmap.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = canvPsBmap.tcl; sourceTree = "<group>"; };
+ F966BC1608F27A3C005CB29B /* canvPsGrph.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = canvPsGrph.tcl; sourceTree = "<group>"; };
+ F966BC1708F27A3C005CB29B /* canvPsImg.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = canvPsImg.tcl; sourceTree = "<group>"; };
+ F966BC1808F27A3C005CB29B /* canvPsText.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = canvPsText.tcl; sourceTree = "<group>"; };
+ F966BC1908F27A3C005CB29B /* canvRect.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = canvRect.test; sourceTree = "<group>"; };
+ F966BC1A08F27A3C005CB29B /* canvText.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = canvText.test; sourceTree = "<group>"; };
+ F966BC1B08F27A3C005CB29B /* canvWind.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = canvWind.test; sourceTree = "<group>"; };
+ F966BC1C08F27A3C005CB29B /* choosedir.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = choosedir.test; sourceTree = "<group>"; };
+ F966BC1D08F27A3C005CB29B /* clipboard.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = clipboard.test; sourceTree = "<group>"; };
+ F966BC1E08F27A3C005CB29B /* clrpick.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = clrpick.test; sourceTree = "<group>"; };
+ F966BC1F08F27A3C005CB29B /* cmap.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmap.tcl; sourceTree = "<group>"; };
+ F966BC2008F27A3C005CB29B /* cmds.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmds.test; sourceTree = "<group>"; };
+ F966BC2108F27A3C005CB29B /* color.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = color.test; sourceTree = "<group>"; };
+ F966BC2208F27A3C005CB29B /* config.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = config.test; sourceTree = "<group>"; };
+ F966BC2308F27A3C005CB29B /* constraints.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = constraints.tcl; sourceTree = "<group>"; };
+ F966BC2408F27A3C005CB29B /* cursor.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cursor.test; sourceTree = "<group>"; };
+ F966BC2508F27A3C005CB29B /* dialog.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dialog.test; sourceTree = "<group>"; };
+ F966BC2608F27A3C005CB29B /* embed.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = embed.test; sourceTree = "<group>"; };
+ F966BC2708F27A3C005CB29B /* entry.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = entry.test; sourceTree = "<group>"; };
+ F966BC2808F27A3C005CB29B /* event.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = event.test; sourceTree = "<group>"; };
+ F966BC2908F27A3C005CB29B /* filebox.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = filebox.test; sourceTree = "<group>"; };
+ F966BC2A08F27A3C005CB29B /* focus.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = focus.test; sourceTree = "<group>"; };
+ F966BC2B08F27A3C005CB29B /* focusTcl.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = focusTcl.test; sourceTree = "<group>"; };
+ F966BC2C08F27A3C005CB29B /* font.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = font.test; sourceTree = "<group>"; };
+ F966BC2D08F27A3C005CB29B /* frame.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = frame.test; sourceTree = "<group>"; };
+ F966BC2E08F27A3C005CB29B /* geometry.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = geometry.test; sourceTree = "<group>"; };
+ F966BC2F08F27A3C005CB29B /* get.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = get.test; sourceTree = "<group>"; };
+ F966BC3008F27A3C005CB29B /* grab.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = grab.test; sourceTree = "<group>"; };
+ F966BC3108F27A3C005CB29B /* grid.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = grid.test; sourceTree = "<group>"; };
+ F966BC3308F27A3C005CB29B /* image.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = image.test; sourceTree = "<group>"; };
+ F966BC3408F27A3C005CB29B /* imgBmap.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = imgBmap.test; sourceTree = "<group>"; };
+ F966BC3508F27A3C005CB29B /* imgPhoto.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = imgPhoto.test; sourceTree = "<group>"; };
+ F966BC3608F27A3C005CB29B /* imgPPM.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = imgPPM.test; sourceTree = "<group>"; };
+ F966BC3708F27A3C005CB29B /* listbox.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = listbox.test; sourceTree = "<group>"; };
+ F966BC3808F27A3C005CB29B /* main.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = main.test; sourceTree = "<group>"; };
+ F966BC3908F27A3C005CB29B /* menu.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = menu.test; sourceTree = "<group>"; };
+ F966BC3A08F27A3C005CB29B /* menubut.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = menubut.test; sourceTree = "<group>"; };
+ F966BC3B08F27A3C005CB29B /* menuDraw.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = menuDraw.test; sourceTree = "<group>"; };
+ F966BC3C08F27A3C005CB29B /* message.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = message.test; sourceTree = "<group>"; };
+ F966BC3D08F27A3C005CB29B /* msgbox.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = msgbox.test; sourceTree = "<group>"; };
+ F966BC3E08F27A3C005CB29B /* obj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = obj.test; sourceTree = "<group>"; };
+ F966BC3F08F27A3C005CB29B /* oldpack.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = oldpack.test; sourceTree = "<group>"; };
+ F966BC4008F27A3C005CB29B /* option.file1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = option.file1; sourceTree = "<group>"; };
+ F966BC4108F27A3C005CB29B /* option.file2 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = option.file2; sourceTree = "<group>"; };
+ F966BC4208F27A3C005CB29B /* option.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = option.test; sourceTree = "<group>"; };
+ F966BC4308F27A3C005CB29B /* pack.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pack.test; sourceTree = "<group>"; };
+ F966BC4408F27A3C005CB29B /* panedwindow.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = panedwindow.test; sourceTree = "<group>"; };
+ F966BC4508F27A3D005CB29B /* place.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = place.test; sourceTree = "<group>"; };
+ F966BC4608F27A3D005CB29B /* raise.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = raise.test; sourceTree = "<group>"; };
+ F966BC4708F27A3D005CB29B /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F966BC4808F27A3D005CB29B /* safe.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = safe.test; sourceTree = "<group>"; };
+ F966BC4908F27A3D005CB29B /* scale.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = scale.test; sourceTree = "<group>"; };
+ F966BC4A08F27A3D005CB29B /* scrollbar.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = scrollbar.test; sourceTree = "<group>"; };
+ F966BC4B08F27A3D005CB29B /* select.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = select.test; sourceTree = "<group>"; };
+ F966BC4C08F27A3D005CB29B /* send.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = send.test; sourceTree = "<group>"; };
+ F966BC4D08F27A3D005CB29B /* spinbox.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = spinbox.test; sourceTree = "<group>"; };
+ F966BC4E08F27A3D005CB29B /* text.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = text.test; sourceTree = "<group>"; };
+ F966BC4F08F27A3D005CB29B /* textBTree.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = textBTree.test; sourceTree = "<group>"; };
+ F966BC5008F27A3D005CB29B /* textDisp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = textDisp.test; sourceTree = "<group>"; };
+ F966BC5108F27A3D005CB29B /* textImage.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = textImage.test; sourceTree = "<group>"; };
+ F966BC5208F27A3D005CB29B /* textIndex.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = textIndex.test; sourceTree = "<group>"; };
+ F966BC5308F27A3D005CB29B /* textMark.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = textMark.test; sourceTree = "<group>"; };
+ F966BC5408F27A3D005CB29B /* textTag.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = textTag.test; sourceTree = "<group>"; };
+ F966BC5508F27A3D005CB29B /* textWind.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = textWind.test; sourceTree = "<group>"; };
+ F966BC5608F27A3D005CB29B /* tk.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tk.test; sourceTree = "<group>"; };
+ F966BC5708F27A3D005CB29B /* unixButton.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixButton.test; sourceTree = "<group>"; };
+ F966BC5808F27A3D005CB29B /* unixEmbed.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixEmbed.test; sourceTree = "<group>"; };
+ F966BC5908F27A3D005CB29B /* unixFont.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixFont.test; sourceTree = "<group>"; };
+ F966BC5A08F27A3D005CB29B /* unixMenu.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixMenu.test; sourceTree = "<group>"; };
+ F966BC5B08F27A3D005CB29B /* unixSelect.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixSelect.test; sourceTree = "<group>"; };
+ F966BC5C08F27A3D005CB29B /* unixWm.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixWm.test; sourceTree = "<group>"; };
+ F966BC5D08F27A3D005CB29B /* util.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = util.test; sourceTree = "<group>"; };
+ F966BC5E08F27A3D005CB29B /* visual.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = visual.test; sourceTree = "<group>"; };
+ F966BC5F08F27A3D005CB29B /* visual_bb.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = visual_bb.test; sourceTree = "<group>"; };
+ F966BC6008F27A3D005CB29B /* winButton.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winButton.test; sourceTree = "<group>"; };
+ F966BC6108F27A3D005CB29B /* winClipboard.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winClipboard.test; sourceTree = "<group>"; };
+ F966BC6208F27A3D005CB29B /* winDialog.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winDialog.test; sourceTree = "<group>"; };
+ F966BC6308F27A3D005CB29B /* window.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = window.test; sourceTree = "<group>"; };
+ F966BC6408F27A3D005CB29B /* winfo.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winfo.test; sourceTree = "<group>"; };
+ F966BC6508F27A3D005CB29B /* winFont.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winFont.test; sourceTree = "<group>"; };
+ F966BC6608F27A3D005CB29B /* winMenu.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winMenu.test; sourceTree = "<group>"; };
+ F966BC6708F27A3D005CB29B /* winSend.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winSend.test; sourceTree = "<group>"; };
+ F966BC6808F27A3D005CB29B /* winWm.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winWm.test; sourceTree = "<group>"; };
+ F966BC6908F27A3D005CB29B /* wm.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = wm.test; sourceTree = "<group>"; };
+ F966BC6A08F27A3D005CB29B /* xmfbox.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = xmfbox.test; sourceTree = "<group>"; };
+ F966BC6C08F27A3D005CB29B /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = "<group>"; };
+ F966BC6D08F27A3D005CB29B /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
+ F966BC6E08F27A3D005CB29B /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
+ F966BC6F08F27A3D005CB29B /* install-sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "install-sh"; sourceTree = "<group>"; };
+ F966BC7008F27A3D005CB29B /* installManPage */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = installManPage; sourceTree = "<group>"; };
+ F966BC7108F27A3D005CB29B /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
+ F966BC7208F27A3D005CB29B /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F966BC7308F27A3D005CB29B /* tcl.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tcl.m4; sourceTree = "<group>"; };
+ F966BC7408F27A3D005CB29B /* tk.spec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tk.spec; sourceTree = "<group>"; };
+ F966BC7508F27A3D005CB29B /* tkAppInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkAppInit.c; sourceTree = "<group>"; };
+ F966BC7608F27A3D005CB29B /* tkConfig.h.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = tkConfig.h.in; sourceTree = "<group>"; };
+ F966BC7708F27A3D005CB29B /* tkConfig.sh.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tkConfig.sh.in; sourceTree = "<group>"; };
+ F966BC7808F27A3D005CB29B /* tkUnix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnix.c; sourceTree = "<group>"; };
+ F966BC7908F27A3D005CB29B /* tkUnix3d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnix3d.c; sourceTree = "<group>"; };
+ F966BC7A08F27A3D005CB29B /* tkUnixButton.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixButton.c; sourceTree = "<group>"; };
+ F966BC7B08F27A3D005CB29B /* tkUnixColor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixColor.c; sourceTree = "<group>"; };
+ F966BC7C08F27A3D005CB29B /* tkUnixConfig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixConfig.c; sourceTree = "<group>"; };
+ F966BC7D08F27A3D005CB29B /* tkUnixCursor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixCursor.c; sourceTree = "<group>"; };
+ F966BC7E08F27A3D005CB29B /* tkUnixDefault.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkUnixDefault.h; sourceTree = "<group>"; };
+ F966BC7F08F27A3D005CB29B /* tkUnixDialog.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixDialog.c; sourceTree = "<group>"; };
+ F966BC8008F27A3D005CB29B /* tkUnixDraw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixDraw.c; sourceTree = "<group>"; };
+ F966BC8108F27A3D005CB29B /* tkUnixEmbed.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixEmbed.c; sourceTree = "<group>"; };
+ F966BC8208F27A3D005CB29B /* tkUnixEvent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixEvent.c; sourceTree = "<group>"; };
+ F966BC8308F27A3D005CB29B /* tkUnixFocus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixFocus.c; sourceTree = "<group>"; };
+ F966BC8408F27A3D005CB29B /* tkUnixFont.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixFont.c; sourceTree = "<group>"; };
+ F966BC8508F27A3D005CB29B /* tkUnixInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixInit.c; sourceTree = "<group>"; };
+ F966BC8608F27A3D005CB29B /* tkUnixInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkUnixInt.h; sourceTree = "<group>"; };
+ F966BC8708F27A3D005CB29B /* tkUnixKey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixKey.c; sourceTree = "<group>"; };
+ F966BC8808F27A3D005CB29B /* tkUnixMenu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixMenu.c; sourceTree = "<group>"; };
+ F966BC8908F27A3D005CB29B /* tkUnixMenubu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixMenubu.c; sourceTree = "<group>"; };
+ F966BC8A08F27A3D005CB29B /* tkUnixPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkUnixPort.h; sourceTree = "<group>"; };
+ F966BC8B08F27A3D005CB29B /* tkUnixRFont.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixRFont.c; sourceTree = "<group>"; };
+ F966BC8C08F27A3D005CB29B /* tkUnixScale.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixScale.c; sourceTree = "<group>"; };
+ F966BC8D08F27A3D005CB29B /* tkUnixScrlbr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixScrlbr.c; sourceTree = "<group>"; };
+ F966BC8E08F27A3D005CB29B /* tkUnixSelect.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixSelect.c; sourceTree = "<group>"; };
+ F966BC8F08F27A3D005CB29B /* tkUnixSend.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixSend.c; sourceTree = "<group>"; };
+ F966BC9008F27A3D005CB29B /* tkUnixWm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixWm.c; sourceTree = "<group>"; };
+ F966BC9108F27A3D005CB29B /* tkUnixXId.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixXId.c; sourceTree = "<group>"; };
+ F966BC9408F27A3D005CB29B /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = "<group>"; };
+ F966BC9508F27A3D005CB29B /* buildall.vc.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = buildall.vc.bat; sourceTree = "<group>"; };
+ F966BC9608F27A3E005CB29B /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
+ F966BC9708F27A3E005CB29B /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
+ F966BC9908F27A3E005CB29B /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
+ F966BC9A08F27A3E005CB29B /* makefile.vc */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = makefile.vc; sourceTree = "<group>"; };
+ F966BC9B08F27A3E005CB29B /* mkd.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = mkd.bat; sourceTree = "<group>"; };
+ F966BC9C08F27A3E005CB29B /* nmakehlp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nmakehlp.c; sourceTree = "<group>"; };
+ F966BCEE08F27A3E005CB29B /* tk.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tk.rc; sourceTree = "<group>"; };
+ F966BCEF08F27A3E005CB29B /* tk_base.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tk_base.rc; sourceTree = "<group>"; };
+ F966BCF208F27A3E005CB29B /* wish.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = wish.rc; sourceTree = "<group>"; };
+ F966BCF308F27A3E005CB29B /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F966BCF408F27A3E005CB29B /* rmd.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rmd.bat; sourceTree = "<group>"; };
+ F966BCF508F27A3F005CB29B /* rules.vc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rules.vc; sourceTree = "<group>"; };
+ F966BCF608F27A3F005CB29B /* stubs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stubs.c; sourceTree = "<group>"; };
+ F966BCF708F27A3F005CB29B /* tcl.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tcl.m4; sourceTree = "<group>"; };
+ F966BCF808F27A3F005CB29B /* tkConfig.sh.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tkConfig.sh.in; sourceTree = "<group>"; };
+ F966BCF908F27A3F005CB29B /* tkWin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkWin.h; sourceTree = "<group>"; };
+ F966BCFA08F27A3F005CB29B /* tkWin32Dll.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWin32Dll.c; sourceTree = "<group>"; };
+ F966BCFB08F27A3F005CB29B /* tkWin3d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWin3d.c; sourceTree = "<group>"; };
+ F966BCFC08F27A3F005CB29B /* tkWinButton.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinButton.c; sourceTree = "<group>"; };
+ F966BCFD08F27A3F005CB29B /* tkWinClipboard.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinClipboard.c; sourceTree = "<group>"; };
+ F966BCFE08F27A3F005CB29B /* tkWinColor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinColor.c; sourceTree = "<group>"; };
+ F966BCFF08F27A3F005CB29B /* tkWinConfig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinConfig.c; sourceTree = "<group>"; };
+ F966BD0008F27A3F005CB29B /* tkWinCursor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinCursor.c; sourceTree = "<group>"; };
+ F966BD0108F27A3F005CB29B /* tkWinDefault.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkWinDefault.h; sourceTree = "<group>"; };
+ F966BD0208F27A3F005CB29B /* tkWinDialog.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinDialog.c; sourceTree = "<group>"; };
+ F966BD0308F27A3F005CB29B /* tkWinDraw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinDraw.c; sourceTree = "<group>"; };
+ F966BD0408F27A3F005CB29B /* tkWinEmbed.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinEmbed.c; sourceTree = "<group>"; };
+ F966BD0508F27A3F005CB29B /* tkWinFont.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinFont.c; sourceTree = "<group>"; };
+ F966BD0708F27A3F005CB29B /* tkWinImage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinImage.c; sourceTree = "<group>"; };
+ F966BD0808F27A3F005CB29B /* tkWinInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinInit.c; sourceTree = "<group>"; };
+ F966BD0908F27A3F005CB29B /* tkWinInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkWinInt.h; sourceTree = "<group>"; };
+ F966BD0A08F27A3F005CB29B /* tkWinKey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinKey.c; sourceTree = "<group>"; };
+ F966BD0B08F27A3F005CB29B /* tkWinMenu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinMenu.c; sourceTree = "<group>"; };
+ F966BD0C08F27A3F005CB29B /* tkWinPixmap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinPixmap.c; sourceTree = "<group>"; };
+ F966BD0D08F27A3F005CB29B /* tkWinPointer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinPointer.c; sourceTree = "<group>"; };
+ F966BD0E08F27A3F005CB29B /* tkWinPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkWinPort.h; sourceTree = "<group>"; };
+ F966BD0F08F27A3F005CB29B /* tkWinRegion.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinRegion.c; sourceTree = "<group>"; };
+ F966BD1008F27A3F005CB29B /* tkWinScrlbr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinScrlbr.c; sourceTree = "<group>"; };
+ F966BD1108F27A3F005CB29B /* tkWinSend.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinSend.c; sourceTree = "<group>"; };
+ F966BD1208F27A3F005CB29B /* tkWinSendCom.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinSendCom.c; sourceTree = "<group>"; };
+ F966BD1308F27A3F005CB29B /* tkWinSendCom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkWinSendCom.h; sourceTree = "<group>"; };
+ F966BD1408F27A3F005CB29B /* tkWinTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinTest.c; sourceTree = "<group>"; };
+ F966BD1508F27A3F005CB29B /* tkWinWindow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinWindow.c; sourceTree = "<group>"; };
+ F966BD1608F27A3F005CB29B /* tkWinWm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinWm.c; sourceTree = "<group>"; };
+ F966BD1708F27A3F005CB29B /* tkWinX.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinX.c; sourceTree = "<group>"; };
+ F966BD1808F27A3F005CB29B /* winMain.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = winMain.c; sourceTree = "<group>"; };
+ F966BD1B08F27A3F005CB29B /* cursorfont.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cursorfont.h; sourceTree = "<group>"; };
+ F966BD1C08F27A3F005CB29B /* keysym.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = keysym.h; sourceTree = "<group>"; };
+ F966BD1D08F27A3F005CB29B /* keysymdef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = keysymdef.h; sourceTree = "<group>"; };
+ F966BD1E08F27A3F005CB29B /* X.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = X.h; sourceTree = "<group>"; };
+ F966BD1F08F27A3F005CB29B /* Xatom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Xatom.h; sourceTree = "<group>"; };
+ F966BD2008F27A3F005CB29B /* Xfuncproto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Xfuncproto.h; sourceTree = "<group>"; };
+ F966BD2108F27A3F005CB29B /* Xlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Xlib.h; sourceTree = "<group>"; };
+ F966BD2208F27A3F005CB29B /* Xutil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Xutil.h; sourceTree = "<group>"; };
+ F966BD2308F27A3F005CB29B /* xbytes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xbytes.h; sourceTree = "<group>"; };
+ F966BD2408F27A3F005CB29B /* xcolors.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xcolors.c; sourceTree = "<group>"; };
+ F966BD2508F27A3F005CB29B /* xdraw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xdraw.c; sourceTree = "<group>"; };
+ F966BD2608F27A3F005CB29B /* xgc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xgc.c; sourceTree = "<group>"; };
+ F966BD2708F27A3F005CB29B /* ximage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ximage.c; sourceTree = "<group>"; };
+ F966BD2808F27A3F005CB29B /* xutil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xutil.c; sourceTree = "<group>"; };
+ F966C07408F2820D005CB29B /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; };
+ F966C07608F2821B005CB29B /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = "<absolute>"; };
+ F966C07808F28233005CB29B /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = /System/Library/Frameworks/IOKit.framework; sourceTree = "<absolute>"; };
+ F96887E00AF786D5000797B5 /* ttk.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = ttk.decls; sourceTree = "<group>"; };
+ F96887E10AF786D5000797B5 /* ttkBlink.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkBlink.c; sourceTree = "<group>"; };
+ F96887E20AF786D5000797B5 /* ttkButton.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkButton.c; sourceTree = "<group>"; };
+ F96887E30AF786D5000797B5 /* ttkCache.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkCache.c; sourceTree = "<group>"; };
+ F96887E40AF786D5000797B5 /* ttkClamTheme.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkClamTheme.c; sourceTree = "<group>"; };
+ F96887E50AF786D5000797B5 /* ttkClassicTheme.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkClassicTheme.c; sourceTree = "<group>"; };
+ F96887E60AF786D5000797B5 /* ttkDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ttkDecls.h; sourceTree = "<group>"; };
+ F96887E70AF786D5000797B5 /* ttkDefaultTheme.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkDefaultTheme.c; sourceTree = "<group>"; };
+ F96887E80AF786D5000797B5 /* ttkElements.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkElements.c; sourceTree = "<group>"; };
+ F96887E90AF786D5000797B5 /* ttkEntry.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkEntry.c; sourceTree = "<group>"; };
+ F96887EA0AF786D5000797B5 /* ttkFrame.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkFrame.c; sourceTree = "<group>"; };
+ F96887EB0AF786D5000797B5 /* ttkImage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkImage.c; sourceTree = "<group>"; };
+ F96887EC0AF786D5000797B5 /* ttkInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkInit.c; sourceTree = "<group>"; };
+ F96887ED0AF786D5000797B5 /* ttkLabel.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkLabel.c; sourceTree = "<group>"; };
+ F96887EE0AF786D5000797B5 /* ttkLayout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkLayout.c; sourceTree = "<group>"; };
+ F96887EF0AF786D5000797B5 /* ttkManager.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkManager.c; sourceTree = "<group>"; };
+ F96887F00AF786D5000797B5 /* ttkManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ttkManager.h; sourceTree = "<group>"; };
+ F96887F10AF786D5000797B5 /* ttkNotebook.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkNotebook.c; sourceTree = "<group>"; };
+ F96887F20AF786D5000797B5 /* ttkPanedwindow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkPanedwindow.c; sourceTree = "<group>"; };
+ F96887F30AF786D5000797B5 /* ttkProgress.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkProgress.c; sourceTree = "<group>"; };
+ F96887F40AF786D5000797B5 /* ttkScale.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkScale.c; sourceTree = "<group>"; };
+ F96887F50AF786D5000797B5 /* ttkScroll.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkScroll.c; sourceTree = "<group>"; };
+ F96887F60AF786D5000797B5 /* ttkScrollbar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkScrollbar.c; sourceTree = "<group>"; };
+ F96887F70AF786D5000797B5 /* ttkSeparator.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkSeparator.c; sourceTree = "<group>"; };
+ F96887F80AF786D5000797B5 /* ttkSquare.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkSquare.c; sourceTree = "<group>"; };
+ F96887F90AF786D5000797B5 /* ttkState.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkState.c; sourceTree = "<group>"; };
+ F96887FA0AF786D5000797B5 /* ttkStubInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkStubInit.c; sourceTree = "<group>"; };
+ F96887FB0AF786D5000797B5 /* ttkStubLib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkStubLib.c; sourceTree = "<group>"; };
+ F96887FC0AF786D5000797B5 /* ttkTagSet.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkTagSet.c; sourceTree = "<group>"; };
+ F96887FD0AF786D5000797B5 /* ttkTheme.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkTheme.c; sourceTree = "<group>"; };
+ F96887FE0AF786D5000797B5 /* ttkTheme.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ttkTheme.h; sourceTree = "<group>"; };
+ F96887FF0AF786D5000797B5 /* ttkThemeInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ttkThemeInt.h; sourceTree = "<group>"; };
+ F96888000AF786D5000797B5 /* ttkTrace.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkTrace.c; sourceTree = "<group>"; };
+ F96888010AF786D5000797B5 /* ttkTrack.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkTrack.c; sourceTree = "<group>"; };
+ F96888020AF786D5000797B5 /* ttkTreeview.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkTreeview.c; sourceTree = "<group>"; };
+ F96888030AF786D5000797B5 /* ttkWidget.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkWidget.c; sourceTree = "<group>"; };
+ F96888040AF786D5000797B5 /* ttkWidget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ttkWidget.h; sourceTree = "<group>"; };
+ F96888370AF787B3000797B5 /* altTheme.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = altTheme.tcl; sourceTree = "<group>"; };
+ F96888380AF787B3000797B5 /* aquaTheme.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = aquaTheme.tcl; sourceTree = "<group>"; };
+ F96888390AF787B3000797B5 /* button.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = button.tcl; sourceTree = "<group>"; };
+ F968883A0AF787B3000797B5 /* clamTheme.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = clamTheme.tcl; sourceTree = "<group>"; };
+ F968883B0AF787B3000797B5 /* classicTheme.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = classicTheme.tcl; sourceTree = "<group>"; };
+ F968883C0AF787B3000797B5 /* combobox.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = combobox.tcl; sourceTree = "<group>"; };
+ F968883D0AF787B3000797B5 /* cursors.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cursors.tcl; sourceTree = "<group>"; };
+ F968883E0AF787B3000797B5 /* defaults.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = defaults.tcl; sourceTree = "<group>"; };
+ F96888400AF787B3000797B5 /* entry.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = entry.tcl; sourceTree = "<group>"; };
+ F96888410AF787B3000797B5 /* fonts.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fonts.tcl; sourceTree = "<group>"; };
+ F96888440AF787B3000797B5 /* menubutton.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = menubutton.tcl; sourceTree = "<group>"; };
+ F96888450AF787B3000797B5 /* notebook.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = notebook.tcl; sourceTree = "<group>"; };
+ F96888460AF787B3000797B5 /* panedwindow.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = panedwindow.tcl; sourceTree = "<group>"; };
+ F96888470AF787B3000797B5 /* progress.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = progress.tcl; sourceTree = "<group>"; };
+ F96888480AF787B3000797B5 /* scale.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = scale.tcl; sourceTree = "<group>"; };
+ F96888490AF787B3000797B5 /* scrollbar.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = scrollbar.tcl; sourceTree = "<group>"; };
+ F968884A0AF787B3000797B5 /* sizegrip.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = sizegrip.tcl; sourceTree = "<group>"; };
+ F968884B0AF787B3000797B5 /* treeview.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = treeview.tcl; sourceTree = "<group>"; };
+ F968884C0AF787B3000797B5 /* ttk.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = ttk.tcl; sourceTree = "<group>"; };
+ F968884D0AF787B3000797B5 /* utils.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = utils.tcl; sourceTree = "<group>"; };
+ F968884E0AF787B3000797B5 /* winTheme.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winTheme.tcl; sourceTree = "<group>"; };
+ F968884F0AF787B3000797B5 /* xpTheme.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = xpTheme.tcl; sourceTree = "<group>"; };
+ F96888540AF7880C000797B5 /* all.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = all.tcl; sourceTree = "<group>"; };
+ F96888560AF7880C000797B5 /* combobox.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = combobox.test; sourceTree = "<group>"; };
+ F96888570AF7880C000797B5 /* entry.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = entry.test; sourceTree = "<group>"; };
+ F96888580AF7880C000797B5 /* image.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = image.test; sourceTree = "<group>"; };
+ F96888590AF7880C000797B5 /* labelframe.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = labelframe.test; sourceTree = "<group>"; };
+ F968885A0AF7880C000797B5 /* layout.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = layout.test; sourceTree = "<group>"; };
+ F968885C0AF7880C000797B5 /* notebook.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = notebook.test; sourceTree = "<group>"; };
+ F968885D0AF7880C000797B5 /* panedwindow.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = panedwindow.test; sourceTree = "<group>"; };
+ F968885E0AF7880C000797B5 /* progressbar.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = progressbar.test; sourceTree = "<group>"; };
+ F968885F0AF7880C000797B5 /* scrollbar.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = scrollbar.test; sourceTree = "<group>"; };
+ F96888600AF7880C000797B5 /* treetags.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = treetags.test; sourceTree = "<group>"; };
+ F96888610AF7880C000797B5 /* treeview.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = treeview.test; sourceTree = "<group>"; };
+ F96888620AF7880C000797B5 /* ttk.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = ttk.test; sourceTree = "<group>"; };
+ F96888630AF7880C000797B5 /* validate.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = validate.test; sourceTree = "<group>"; };
+ F968886B0AF788F6000797B5 /* ttk_button.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_button.n; sourceTree = "<group>"; };
+ F968886C0AF788F6000797B5 /* ttk_checkbutton.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_checkbutton.n; sourceTree = "<group>"; };
+ F968886D0AF788F6000797B5 /* ttk_combobox.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_combobox.n; sourceTree = "<group>"; };
+ F968886F0AF788F6000797B5 /* ttk_entry.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_entry.n; sourceTree = "<group>"; };
+ F96888700AF788F6000797B5 /* ttk_frame.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_frame.n; sourceTree = "<group>"; };
+ F96888710AF788F6000797B5 /* ttk_Geometry.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_Geometry.3; sourceTree = "<group>"; };
+ F96888720AF788F6000797B5 /* ttk_image.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_image.n; sourceTree = "<group>"; };
+ F96888730AF788F6000797B5 /* ttk_intro.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_intro.n; sourceTree = "<group>"; };
+ F96888740AF788F6000797B5 /* ttk_label.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_label.n; sourceTree = "<group>"; };
+ F96888750AF788F6000797B5 /* ttk_labelframe.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_labelframe.n; sourceTree = "<group>"; };
+ F96888760AF788F6000797B5 /* ttk_menubutton.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_menubutton.n; sourceTree = "<group>"; };
+ F96888770AF788F6000797B5 /* ttk_notebook.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_notebook.n; sourceTree = "<group>"; };
+ F96888780AF788F6000797B5 /* ttk_panedwindow.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_panedwindow.n; sourceTree = "<group>"; };
+ F96888790AF788F6000797B5 /* ttk_progressbar.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_progressbar.n; sourceTree = "<group>"; };
+ F968887A0AF788F6000797B5 /* ttk_radiobutton.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_radiobutton.n; sourceTree = "<group>"; };
+ F968887B0AF788F6000797B5 /* ttk_scrollbar.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_scrollbar.n; sourceTree = "<group>"; };
+ F968887C0AF788F6000797B5 /* ttk_separator.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_separator.n; sourceTree = "<group>"; };
+ F968887D0AF788F6000797B5 /* ttk_sizegrip.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_sizegrip.n; sourceTree = "<group>"; };
+ F968887E0AF788F6000797B5 /* ttk_style.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_style.n; sourceTree = "<group>"; };
+ F968887F0AF788F6000797B5 /* ttk_Theme.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_Theme.3; sourceTree = "<group>"; };
+ F96888800AF788F6000797B5 /* ttk_treeview.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_treeview.n; sourceTree = "<group>"; };
+ F96888810AF788F6000797B5 /* ttk_widget.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_widget.n; sourceTree = "<group>"; };
+ F96888840AF78938000797B5 /* ttkMacOSXTheme.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = ttkMacOSXTheme.c; sourceTree = "<group>"; };
+ F96888860AF78953000797B5 /* ttkWinMonitor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkWinMonitor.c; sourceTree = "<group>"; };
+ F96888870AF78953000797B5 /* ttkWinTheme.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkWinTheme.c; sourceTree = "<group>"; };
+ F96888880AF78953000797B5 /* ttkWinXPTheme.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkWinXPTheme.c; sourceTree = "<group>"; };
+ F96D3DFA08F272A4004A47F5 /* ChangeLog */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = ChangeLog; sourceTree = "<group>"; };
+ F96D3DFB08F272A4004A47F5 /* changes */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = changes; sourceTree = "<group>"; };
+ F96D3DFD08F272A4004A47F5 /* Access.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Access.3; sourceTree = "<group>"; };
+ F96D3DFE08F272A4004A47F5 /* AddErrInfo.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AddErrInfo.3; sourceTree = "<group>"; };
+ F96D3DFF08F272A4004A47F5 /* after.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = after.n; sourceTree = "<group>"; };
+ F96D3E0008F272A4004A47F5 /* Alloc.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Alloc.3; sourceTree = "<group>"; };
+ F96D3E0108F272A4004A47F5 /* AllowExc.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AllowExc.3; sourceTree = "<group>"; };
+ F96D3E0208F272A4004A47F5 /* append.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = append.n; sourceTree = "<group>"; };
+ F96D3E0308F272A4004A47F5 /* AppInit.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AppInit.3; sourceTree = "<group>"; };
+ F96D3E0408F272A5004A47F5 /* array.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = array.n; sourceTree = "<group>"; };
+ F96D3E0508F272A5004A47F5 /* AssocData.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AssocData.3; sourceTree = "<group>"; };
+ F96D3E0608F272A5004A47F5 /* Async.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Async.3; sourceTree = "<group>"; };
+ F96D3E0708F272A5004A47F5 /* BackgdErr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = BackgdErr.3; sourceTree = "<group>"; };
+ F96D3E0808F272A5004A47F5 /* Backslash.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Backslash.3; sourceTree = "<group>"; };
+ F96D3E0908F272A5004A47F5 /* bgerror.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = bgerror.n; sourceTree = "<group>"; };
+ F96D3E0A08F272A5004A47F5 /* binary.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = binary.n; sourceTree = "<group>"; };
+ F96D3E0B08F272A5004A47F5 /* BoolObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = BoolObj.3; sourceTree = "<group>"; };
+ F96D3E0C08F272A5004A47F5 /* break.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = break.n; sourceTree = "<group>"; };
+ F96D3E0D08F272A5004A47F5 /* ByteArrObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ByteArrObj.3; sourceTree = "<group>"; };
+ F96D3E0E08F272A5004A47F5 /* CallDel.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CallDel.3; sourceTree = "<group>"; };
+ F96D3E0F08F272A5004A47F5 /* case.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = case.n; sourceTree = "<group>"; };
+ F96D3E1008F272A5004A47F5 /* catch.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = catch.n; sourceTree = "<group>"; };
+ F96D3E1108F272A5004A47F5 /* cd.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = cd.n; sourceTree = "<group>"; };
+ F96D3E1208F272A5004A47F5 /* chan.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = chan.n; sourceTree = "<group>"; };
+ F96D3E1308F272A5004A47F5 /* ChnlStack.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ChnlStack.3; sourceTree = "<group>"; };
+ F96D3E1408F272A5004A47F5 /* clock.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = clock.n; sourceTree = "<group>"; };
+ F96D3E1508F272A5004A47F5 /* close.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = close.n; sourceTree = "<group>"; };
+ F96D3E1608F272A5004A47F5 /* CmdCmplt.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CmdCmplt.3; sourceTree = "<group>"; };
+ F96D3E1708F272A5004A47F5 /* Concat.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Concat.3; sourceTree = "<group>"; };
+ F96D3E1808F272A5004A47F5 /* concat.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = concat.n; sourceTree = "<group>"; };
+ F96D3E1908F272A5004A47F5 /* continue.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = continue.n; sourceTree = "<group>"; };
+ F96D3E1A08F272A5004A47F5 /* CrtChannel.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtChannel.3; sourceTree = "<group>"; };
+ F96D3E1B08F272A5004A47F5 /* CrtChnlHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtChnlHdlr.3; sourceTree = "<group>"; };
+ F96D3E1C08F272A5004A47F5 /* CrtCloseHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtCloseHdlr.3; sourceTree = "<group>"; };
+ F96D3E1D08F272A5004A47F5 /* CrtCommand.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtCommand.3; sourceTree = "<group>"; };
+ F96D3E1E08F272A5004A47F5 /* CrtFileHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtFileHdlr.3; sourceTree = "<group>"; };
+ F96D3E1F08F272A5004A47F5 /* CrtInterp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtInterp.3; sourceTree = "<group>"; };
+ F96D3E2008F272A5004A47F5 /* CrtMathFnc.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtMathFnc.3; sourceTree = "<group>"; };
+ F96D3E2108F272A5004A47F5 /* CrtObjCmd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtObjCmd.3; sourceTree = "<group>"; };
+ F96D3E2208F272A5004A47F5 /* CrtSlave.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtSlave.3; sourceTree = "<group>"; };
+ F96D3E2308F272A5004A47F5 /* CrtTimerHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtTimerHdlr.3; sourceTree = "<group>"; };
+ F96D3E2408F272A5004A47F5 /* CrtTrace.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtTrace.3; sourceTree = "<group>"; };
+ F96D3E2508F272A5004A47F5 /* dde.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = dde.n; sourceTree = "<group>"; };
+ F96D3E2608F272A5004A47F5 /* DetachPids.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DetachPids.3; sourceTree = "<group>"; };
+ F96D3E2708F272A5004A47F5 /* dict.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = dict.n; sourceTree = "<group>"; };
+ F96D3E2808F272A5004A47F5 /* DictObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DictObj.3; sourceTree = "<group>"; };
+ F96D3E2908F272A5004A47F5 /* DoOneEvent.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DoOneEvent.3; sourceTree = "<group>"; };
+ F96D3E2A08F272A5004A47F5 /* DoubleObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DoubleObj.3; sourceTree = "<group>"; };
+ F96D3E2B08F272A5004A47F5 /* DoWhenIdle.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DoWhenIdle.3; sourceTree = "<group>"; };
+ F96D3E2C08F272A5004A47F5 /* DString.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DString.3; sourceTree = "<group>"; };
+ F96D3E2D08F272A5004A47F5 /* DumpActiveMemory.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DumpActiveMemory.3; sourceTree = "<group>"; };
+ F96D3E2E08F272A5004A47F5 /* Encoding.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Encoding.3; sourceTree = "<group>"; };
+ F96D3E2F08F272A5004A47F5 /* encoding.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = encoding.n; sourceTree = "<group>"; };
+ F96D3E3008F272A5004A47F5 /* Ensemble.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Ensemble.3; sourceTree = "<group>"; };
+ F96D3E3108F272A5004A47F5 /* Environment.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Environment.3; sourceTree = "<group>"; };
+ F96D3E3208F272A5004A47F5 /* eof.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = eof.n; sourceTree = "<group>"; };
+ F96D3E3308F272A5004A47F5 /* error.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = error.n; sourceTree = "<group>"; };
+ F96D3E3408F272A5004A47F5 /* Eval.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Eval.3; sourceTree = "<group>"; };
+ F96D3E3508F272A5004A47F5 /* eval.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = eval.n; sourceTree = "<group>"; };
+ F96D3E3608F272A5004A47F5 /* exec.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = exec.n; sourceTree = "<group>"; };
+ F96D3E3708F272A5004A47F5 /* Exit.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Exit.3; sourceTree = "<group>"; };
+ F96D3E3808F272A5004A47F5 /* exit.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = exit.n; sourceTree = "<group>"; };
+ F96D3E3908F272A5004A47F5 /* expr.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = expr.n; sourceTree = "<group>"; };
+ F96D3E3A08F272A5004A47F5 /* ExprLong.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ExprLong.3; sourceTree = "<group>"; };
+ F96D3E3B08F272A5004A47F5 /* ExprLongObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ExprLongObj.3; sourceTree = "<group>"; };
+ F96D3E3C08F272A5004A47F5 /* fblocked.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fblocked.n; sourceTree = "<group>"; };
+ F96D3E3D08F272A5004A47F5 /* fconfigure.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fconfigure.n; sourceTree = "<group>"; };
+ F96D3E3E08F272A5004A47F5 /* fcopy.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fcopy.n; sourceTree = "<group>"; };
+ F96D3E3F08F272A5004A47F5 /* file.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = file.n; sourceTree = "<group>"; };
+ F96D3E4008F272A5004A47F5 /* fileevent.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fileevent.n; sourceTree = "<group>"; };
+ F96D3E4108F272A5004A47F5 /* filename.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = filename.n; sourceTree = "<group>"; };
+ F96D3E4208F272A5004A47F5 /* FileSystem.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = FileSystem.3; sourceTree = "<group>"; };
+ F96D3E4308F272A5004A47F5 /* FindExec.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = FindExec.3; sourceTree = "<group>"; };
+ F96D3E4408F272A5004A47F5 /* flush.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = flush.n; sourceTree = "<group>"; };
+ F96D3E4508F272A5004A47F5 /* for.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = for.n; sourceTree = "<group>"; };
+ F96D3E4608F272A5004A47F5 /* foreach.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = foreach.n; sourceTree = "<group>"; };
+ F96D3E4708F272A5004A47F5 /* format.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = format.n; sourceTree = "<group>"; };
+ F96D3E4808F272A5004A47F5 /* GetCwd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetCwd.3; sourceTree = "<group>"; };
+ F96D3E4908F272A5004A47F5 /* GetHostName.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetHostName.3; sourceTree = "<group>"; };
+ F96D3E4A08F272A5004A47F5 /* GetIndex.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetIndex.3; sourceTree = "<group>"; };
+ F96D3E4B08F272A5004A47F5 /* GetInt.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetInt.3; sourceTree = "<group>"; };
+ F96D3E4C08F272A5004A47F5 /* GetOpnFl.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetOpnFl.3; sourceTree = "<group>"; };
+ F96D3E4D08F272A5004A47F5 /* gets.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = gets.n; sourceTree = "<group>"; };
+ F96D3E4E08F272A5004A47F5 /* GetStdChan.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetStdChan.3; sourceTree = "<group>"; };
+ F96D3E4F08F272A5004A47F5 /* GetTime.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetTime.3; sourceTree = "<group>"; };
+ F96D3E5008F272A5004A47F5 /* GetVersion.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetVersion.3; sourceTree = "<group>"; };
+ F96D3E5108F272A5004A47F5 /* glob.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = glob.n; sourceTree = "<group>"; };
+ F96D3E5208F272A6004A47F5 /* global.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = global.n; sourceTree = "<group>"; };
+ F96D3E5308F272A6004A47F5 /* Hash.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Hash.3; sourceTree = "<group>"; };
+ F96D3E5408F272A6004A47F5 /* history.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = history.n; sourceTree = "<group>"; };
+ F96D3E5508F272A6004A47F5 /* http.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = http.n; sourceTree = "<group>"; };
+ F96D3E5608F272A6004A47F5 /* if.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = if.n; sourceTree = "<group>"; };
+ F96D3E5708F272A6004A47F5 /* incr.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = incr.n; sourceTree = "<group>"; };
+ F96D3E5808F272A6004A47F5 /* info.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = info.n; sourceTree = "<group>"; };
+ F96D3E5908F272A6004A47F5 /* Init.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Init.3; sourceTree = "<group>"; };
+ F96D3E5A08F272A6004A47F5 /* InitStubs.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = InitStubs.3; sourceTree = "<group>"; };
+ F96D3E5B08F272A6004A47F5 /* Interp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Interp.3; sourceTree = "<group>"; };
+ F96D3E5C08F272A6004A47F5 /* interp.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = interp.n; sourceTree = "<group>"; };
+ F96D3E5D08F272A6004A47F5 /* IntObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = IntObj.3; sourceTree = "<group>"; };
+ F96D3E5E08F272A6004A47F5 /* join.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = join.n; sourceTree = "<group>"; };
+ F96D3E5F08F272A6004A47F5 /* lappend.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lappend.n; sourceTree = "<group>"; };
+ F96D3E6008F272A6004A47F5 /* lassign.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lassign.n; sourceTree = "<group>"; };
+ F96D3E6108F272A6004A47F5 /* library.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = library.n; sourceTree = "<group>"; };
+ F96D3E6208F272A6004A47F5 /* Limit.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Limit.3; sourceTree = "<group>"; };
+ F96D3E6308F272A6004A47F5 /* lindex.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lindex.n; sourceTree = "<group>"; };
+ F96D3E6408F272A6004A47F5 /* LinkVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = LinkVar.3; sourceTree = "<group>"; };
+ F96D3E6508F272A6004A47F5 /* linsert.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = linsert.n; sourceTree = "<group>"; };
+ F96D3E6608F272A6004A47F5 /* list.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = list.n; sourceTree = "<group>"; };
+ F96D3E6708F272A6004A47F5 /* ListObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ListObj.3; sourceTree = "<group>"; };
+ F96D3E6808F272A6004A47F5 /* llength.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = llength.n; sourceTree = "<group>"; };
+ F96D3E6908F272A6004A47F5 /* load.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = load.n; sourceTree = "<group>"; };
+ F96D3E6A08F272A6004A47F5 /* lrange.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lrange.n; sourceTree = "<group>"; };
+ F96D3E6B08F272A6004A47F5 /* lrepeat.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lrepeat.n; sourceTree = "<group>"; };
+ F96D3E6C08F272A6004A47F5 /* lreplace.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lreplace.n; sourceTree = "<group>"; };
+ F96D3E6D08F272A6004A47F5 /* lsearch.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lsearch.n; sourceTree = "<group>"; };
+ F96D3E6E08F272A6004A47F5 /* lset.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lset.n; sourceTree = "<group>"; };
+ F96D3E6F08F272A6004A47F5 /* lsort.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lsort.n; sourceTree = "<group>"; };
+ F96D3E7008F272A6004A47F5 /* man.macros */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = man.macros; sourceTree = "<group>"; };
+ F96D3E7108F272A6004A47F5 /* mathfunc.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = mathfunc.n; sourceTree = "<group>"; };
+ F96D3E7208F272A6004A47F5 /* memory.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = memory.n; sourceTree = "<group>"; };
+ F96D3E7308F272A6004A47F5 /* msgcat.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = msgcat.n; sourceTree = "<group>"; };
+ F96D3E7408F272A6004A47F5 /* Namespace.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Namespace.3; sourceTree = "<group>"; };
+ F96D3E7508F272A6004A47F5 /* namespace.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = namespace.n; sourceTree = "<group>"; };
+ F96D3E7608F272A6004A47F5 /* Notifier.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Notifier.3; sourceTree = "<group>"; };
+ F96D3E7708F272A6004A47F5 /* Object.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Object.3; sourceTree = "<group>"; };
+ F96D3E7808F272A6004A47F5 /* ObjectType.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ObjectType.3; sourceTree = "<group>"; };
+ F96D3E7908F272A6004A47F5 /* open.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = open.n; sourceTree = "<group>"; };
+ F96D3E7A08F272A6004A47F5 /* OpenFileChnl.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = OpenFileChnl.3; sourceTree = "<group>"; };
+ F96D3E7B08F272A6004A47F5 /* OpenTcp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = OpenTcp.3; sourceTree = "<group>"; };
+ F96D3E7C08F272A6004A47F5 /* package.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = package.n; sourceTree = "<group>"; };
+ F96D3E7D08F272A6004A47F5 /* packagens.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = packagens.n; sourceTree = "<group>"; };
+ F96D3E7E08F272A6004A47F5 /* Panic.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Panic.3; sourceTree = "<group>"; };
+ F96D3E7F08F272A6004A47F5 /* ParseCmd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ParseCmd.3; sourceTree = "<group>"; };
+ F96D3E8008F272A6004A47F5 /* pid.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = pid.n; sourceTree = "<group>"; };
+ F96D3E8108F272A6004A47F5 /* pkgMkIndex.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = pkgMkIndex.n; sourceTree = "<group>"; };
+ F96D3E8208F272A6004A47F5 /* PkgRequire.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = PkgRequire.3; sourceTree = "<group>"; };
+ F96D3E8308F272A6004A47F5 /* Preserve.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Preserve.3; sourceTree = "<group>"; };
+ F96D3E8408F272A6004A47F5 /* PrintDbl.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = PrintDbl.3; sourceTree = "<group>"; };
+ F96D3E8508F272A6004A47F5 /* proc.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = proc.n; sourceTree = "<group>"; };
+ F96D3E8608F272A6004A47F5 /* puts.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = puts.n; sourceTree = "<group>"; };
+ F96D3E8708F272A6004A47F5 /* pwd.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = pwd.n; sourceTree = "<group>"; };
+ F96D3E8808F272A6004A47F5 /* re_syntax.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = re_syntax.n; sourceTree = "<group>"; };
+ F96D3E8908F272A6004A47F5 /* read.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = read.n; sourceTree = "<group>"; };
+ F96D3E8A08F272A6004A47F5 /* RecEvalObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RecEvalObj.3; sourceTree = "<group>"; };
+ F96D3E8B08F272A6004A47F5 /* RecordEval.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RecordEval.3; sourceTree = "<group>"; };
+ F96D3E8C08F272A6004A47F5 /* RegConfig.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RegConfig.3; sourceTree = "<group>"; };
+ F96D3E8D08F272A6004A47F5 /* RegExp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RegExp.3; sourceTree = "<group>"; };
+ F96D3E8E08F272A6004A47F5 /* regexp.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = regexp.n; sourceTree = "<group>"; };
+ F96D3E8F08F272A6004A47F5 /* registry.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = registry.n; sourceTree = "<group>"; };
+ F96D3E9008F272A6004A47F5 /* regsub.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = regsub.n; sourceTree = "<group>"; };
+ F96D3E9108F272A6004A47F5 /* rename.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = rename.n; sourceTree = "<group>"; };
+ F96D3E9208F272A6004A47F5 /* return.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = return.n; sourceTree = "<group>"; };
+ F96D3E9308F272A6004A47F5 /* safe.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = safe.n; sourceTree = "<group>"; };
+ F96D3E9408F272A6004A47F5 /* SaveResult.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SaveResult.3; sourceTree = "<group>"; };
+ F96D3E9508F272A6004A47F5 /* scan.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = scan.n; sourceTree = "<group>"; };
+ F96D3E9608F272A6004A47F5 /* seek.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = seek.n; sourceTree = "<group>"; };
+ F96D3E9708F272A6004A47F5 /* set.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = set.n; sourceTree = "<group>"; };
+ F96D3E9808F272A6004A47F5 /* SetChanErr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetChanErr.3; sourceTree = "<group>"; };
+ F96D3E9908F272A6004A47F5 /* SetErrno.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetErrno.3; sourceTree = "<group>"; };
+ F96D3E9A08F272A6004A47F5 /* SetRecLmt.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetRecLmt.3; sourceTree = "<group>"; };
+ F96D3E9B08F272A7004A47F5 /* SetResult.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetResult.3; sourceTree = "<group>"; };
+ F96D3E9C08F272A7004A47F5 /* SetVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetVar.3; sourceTree = "<group>"; };
+ F96D3E9D08F272A7004A47F5 /* Signal.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Signal.3; sourceTree = "<group>"; };
+ F96D3E9E08F272A7004A47F5 /* Sleep.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Sleep.3; sourceTree = "<group>"; };
+ F96D3E9F08F272A7004A47F5 /* socket.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = socket.n; sourceTree = "<group>"; };
+ F96D3EA008F272A7004A47F5 /* source.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = source.n; sourceTree = "<group>"; };
+ F96D3EA108F272A7004A47F5 /* SourceRCFile.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SourceRCFile.3; sourceTree = "<group>"; };
+ F96D3EA208F272A7004A47F5 /* split.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = split.n; sourceTree = "<group>"; };
+ F96D3EA308F272A7004A47F5 /* SplitList.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SplitList.3; sourceTree = "<group>"; };
+ F96D3EA408F272A7004A47F5 /* SplitPath.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SplitPath.3; sourceTree = "<group>"; };
+ F96D3EA508F272A7004A47F5 /* StaticPkg.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StaticPkg.3; sourceTree = "<group>"; };
+ F96D3EA608F272A7004A47F5 /* StdChannels.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StdChannels.3; sourceTree = "<group>"; };
+ F96D3EA708F272A7004A47F5 /* string.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = string.n; sourceTree = "<group>"; };
+ F96D3EA808F272A7004A47F5 /* StringObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StringObj.3; sourceTree = "<group>"; };
+ F96D3EA908F272A7004A47F5 /* StrMatch.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StrMatch.3; sourceTree = "<group>"; };
+ F96D3EAA08F272A7004A47F5 /* subst.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = subst.n; sourceTree = "<group>"; };
+ F96D3EAB08F272A7004A47F5 /* SubstObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SubstObj.3; sourceTree = "<group>"; };
+ F96D3EAC08F272A7004A47F5 /* switch.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = switch.n; sourceTree = "<group>"; };
+ F96D3EAD08F272A7004A47F5 /* Tcl.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Tcl.n; sourceTree = "<group>"; };
+ F96D3EAE08F272A7004A47F5 /* Tcl_Main.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Tcl_Main.3; sourceTree = "<group>"; };
+ F96D3EAF08F272A7004A47F5 /* TCL_MEM_DEBUG.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TCL_MEM_DEBUG.3; sourceTree = "<group>"; };
+ F96D3EB008F272A7004A47F5 /* tclsh.1 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tclsh.1; sourceTree = "<group>"; };
+ F96D3EB108F272A7004A47F5 /* tcltest.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tcltest.n; sourceTree = "<group>"; };
+ F96D3EB208F272A7004A47F5 /* tclvars.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tclvars.n; sourceTree = "<group>"; };
+ F96D3EB308F272A7004A47F5 /* tell.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tell.n; sourceTree = "<group>"; };
+ F96D3EB408F272A7004A47F5 /* Thread.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Thread.3; sourceTree = "<group>"; };
+ F96D3EB508F272A7004A47F5 /* time.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = time.n; sourceTree = "<group>"; };
+ F96D3EB608F272A7004A47F5 /* tm.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tm.n; sourceTree = "<group>"; };
+ F96D3EB708F272A7004A47F5 /* ToUpper.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ToUpper.3; sourceTree = "<group>"; };
+ F96D3EB808F272A7004A47F5 /* trace.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = trace.n; sourceTree = "<group>"; };
+ F96D3EB908F272A7004A47F5 /* TraceCmd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TraceCmd.3; sourceTree = "<group>"; };
+ F96D3EBA08F272A7004A47F5 /* TraceVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TraceVar.3; sourceTree = "<group>"; };
+ F96D3EBB08F272A7004A47F5 /* Translate.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Translate.3; sourceTree = "<group>"; };
+ F96D3EBC08F272A7004A47F5 /* UniCharIsAlpha.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = UniCharIsAlpha.3; sourceTree = "<group>"; };
+ F96D3EBD08F272A7004A47F5 /* unknown.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = unknown.n; sourceTree = "<group>"; };
+ F96D3EBE08F272A7004A47F5 /* unload.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = unload.n; sourceTree = "<group>"; };
+ F96D3EBF08F272A7004A47F5 /* unset.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = unset.n; sourceTree = "<group>"; };
+ F96D3EC008F272A7004A47F5 /* update.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = update.n; sourceTree = "<group>"; };
+ F96D3EC108F272A7004A47F5 /* uplevel.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = uplevel.n; sourceTree = "<group>"; };
+ F96D3EC208F272A7004A47F5 /* UpVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = UpVar.3; sourceTree = "<group>"; };
+ F96D3EC308F272A7004A47F5 /* upvar.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = upvar.n; sourceTree = "<group>"; };
+ F96D3EC408F272A7004A47F5 /* Utf.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Utf.3; sourceTree = "<group>"; };
+ F96D3EC508F272A7004A47F5 /* variable.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = variable.n; sourceTree = "<group>"; };
+ F96D3EC608F272A7004A47F5 /* vwait.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = vwait.n; sourceTree = "<group>"; };
+ F96D3EC708F272A7004A47F5 /* while.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = while.n; sourceTree = "<group>"; };
+ F96D3EC808F272A7004A47F5 /* WrongNumArgs.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = WrongNumArgs.3; sourceTree = "<group>"; };
+ F96D3ECA08F272A7004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F96D3ECB08F272A7004A47F5 /* regc_color.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_color.c; sourceTree = "<group>"; };
+ F96D3ECC08F272A7004A47F5 /* regc_cvec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_cvec.c; sourceTree = "<group>"; };
+ F96D3ECD08F272A7004A47F5 /* regc_lex.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_lex.c; sourceTree = "<group>"; };
+ F96D3ECE08F272A7004A47F5 /* regc_locale.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_locale.c; sourceTree = "<group>"; };
+ F96D3ECF08F272A7004A47F5 /* regc_nfa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_nfa.c; sourceTree = "<group>"; };
+ F96D3ED008F272A7004A47F5 /* regcomp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regcomp.c; sourceTree = "<group>"; };
+ F96D3ED108F272A7004A47F5 /* regcustom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regcustom.h; sourceTree = "<group>"; };
+ F96D3ED208F272A7004A47F5 /* rege_dfa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rege_dfa.c; sourceTree = "<group>"; };
+ F96D3ED308F272A7004A47F5 /* regerror.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regerror.c; sourceTree = "<group>"; };
+ F96D3ED408F272A7004A47F5 /* regerrs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regerrs.h; sourceTree = "<group>"; };
+ F96D3ED508F272A7004A47F5 /* regex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regex.h; sourceTree = "<group>"; };
+ F96D3ED608F272A7004A47F5 /* regexec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regexec.c; sourceTree = "<group>"; };
+ F96D3ED708F272A7004A47F5 /* regfree.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regfree.c; sourceTree = "<group>"; };
+ F96D3ED808F272A7004A47F5 /* regfronts.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regfronts.c; sourceTree = "<group>"; };
+ F96D3ED908F272A7004A47F5 /* regguts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regguts.h; sourceTree = "<group>"; };
+ F96D3EDA08F272A7004A47F5 /* tcl.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tcl.decls; sourceTree = "<group>"; };
+ F96D3EDB08F272A7004A47F5 /* tcl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tcl.h; sourceTree = "<group>"; };
+ F96D3EDC08F272A7004A47F5 /* tclAlloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAlloc.c; sourceTree = "<group>"; };
+ F96D3EDD08F272A7004A47F5 /* tclAsync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAsync.c; sourceTree = "<group>"; };
+ F96D3EDE08F272A7004A47F5 /* tclBasic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclBasic.c; sourceTree = "<group>"; };
+ F96D3EDF08F272A7004A47F5 /* tclBinary.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclBinary.c; sourceTree = "<group>"; };
+ F96D3EE008F272A7004A47F5 /* tclCkalloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCkalloc.c; sourceTree = "<group>"; };
+ F96D3EE108F272A7004A47F5 /* tclClock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclClock.c; sourceTree = "<group>"; };
+ F96D3EE208F272A7004A47F5 /* tclCmdAH.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCmdAH.c; sourceTree = "<group>"; };
+ F96D3EE308F272A7004A47F5 /* tclCmdIL.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCmdIL.c; sourceTree = "<group>"; };
+ F96D3EE408F272A7004A47F5 /* tclCmdMZ.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCmdMZ.c; sourceTree = "<group>"; };
+ F96D3EE508F272A7004A47F5 /* tclCompCmds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCompCmds.c; sourceTree = "<group>"; };
+ F96D3EE608F272A7004A47F5 /* tclCompExpr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCompExpr.c; sourceTree = "<group>"; };
+ F96D3EE708F272A7004A47F5 /* tclCompile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCompile.c; sourceTree = "<group>"; };
+ F96D3EE808F272A7004A47F5 /* tclCompile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclCompile.h; sourceTree = "<group>"; };
+ F96D3EE908F272A7004A47F5 /* tclConfig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclConfig.c; sourceTree = "<group>"; };
+ F96D3EEA08F272A7004A47F5 /* tclDate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclDate.c; sourceTree = "<group>"; };
+ F96D3EEB08F272A7004A47F5 /* tclDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclDecls.h; sourceTree = "<group>"; };
+ F96D3EEC08F272A7004A47F5 /* tclDictObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclDictObj.c; sourceTree = "<group>"; };
+ F96D3EED08F272A7004A47F5 /* tclEncoding.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclEncoding.c; sourceTree = "<group>"; };
+ F96D3EEE08F272A7004A47F5 /* tclEnv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclEnv.c; sourceTree = "<group>"; };
+ F96D3EEF08F272A7004A47F5 /* tclEvent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclEvent.c; sourceTree = "<group>"; };
+ F96D3EF008F272A7004A47F5 /* tclExecute.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclExecute.c; sourceTree = "<group>"; };
+ F96D3EF108F272A7004A47F5 /* tclFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclFCmd.c; sourceTree = "<group>"; };
+ F96D3EF208F272A7004A47F5 /* tclFileName.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclFileName.c; sourceTree = "<group>"; };
+ F96D3EF308F272A7004A47F5 /* tclFileSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclFileSystem.h; sourceTree = "<group>"; };
+ F96D3EF408F272A7004A47F5 /* tclGet.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclGet.c; sourceTree = "<group>"; };
+ F96D3EF508F272A7004A47F5 /* tclGetDate.y */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.yacc; path = tclGetDate.y; sourceTree = "<group>"; };
+ F96D3EF608F272A7004A47F5 /* tclHash.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclHash.c; sourceTree = "<group>"; };
+ F96D3EF708F272A7004A47F5 /* tclHistory.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclHistory.c; sourceTree = "<group>"; };
+ F96D3EF808F272A7004A47F5 /* tclIndexObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIndexObj.c; sourceTree = "<group>"; };
+ F96D3EF908F272A7004A47F5 /* tclInt.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclInt.decls; sourceTree = "<group>"; };
+ F96D3EFA08F272A7004A47F5 /* tclInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclInt.h; sourceTree = "<group>"; };
+ F96D3EFB08F272A7004A47F5 /* tclIntDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclIntDecls.h; sourceTree = "<group>"; };
+ F96D3EFC08F272A7004A47F5 /* tclInterp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclInterp.c; sourceTree = "<group>"; };
+ F96D3EFD08F272A7004A47F5 /* tclIntPlatDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclIntPlatDecls.h; sourceTree = "<group>"; };
+ F96D3EFE08F272A7004A47F5 /* tclIO.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIO.c; sourceTree = "<group>"; };
+ F96D3EFF08F272A7004A47F5 /* tclIO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclIO.h; sourceTree = "<group>"; };
+ F96D3F0008F272A7004A47F5 /* tclIOCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOCmd.c; sourceTree = "<group>"; };
+ F96D3F0108F272A7004A47F5 /* tclIOGT.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOGT.c; sourceTree = "<group>"; };
+ F96D3F0208F272A7004A47F5 /* tclIORChan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIORChan.c; sourceTree = "<group>"; };
+ F96D3F0308F272A7004A47F5 /* tclIOSock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOSock.c; sourceTree = "<group>"; };
+ F96D3F0408F272A7004A47F5 /* tclIOUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOUtil.c; sourceTree = "<group>"; };
+ F96D3F0508F272A7004A47F5 /* tclLink.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLink.c; sourceTree = "<group>"; };
+ F96D3F0608F272A7004A47F5 /* tclListObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclListObj.c; sourceTree = "<group>"; };
+ F96D3F0708F272A7004A47F5 /* tclLiteral.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLiteral.c; sourceTree = "<group>"; };
+ F96D3F0808F272A7004A47F5 /* tclLoad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoad.c; sourceTree = "<group>"; };
+ F96D3F0908F272A7004A47F5 /* tclLoadNone.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadNone.c; sourceTree = "<group>"; };
+ F96D3F0A08F272A7004A47F5 /* tclMain.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMain.c; sourceTree = "<group>"; };
+ F96D3F0B08F272A7004A47F5 /* tclNamesp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclNamesp.c; sourceTree = "<group>"; };
+ F96D3F0C08F272A7004A47F5 /* tclNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclNotify.c; sourceTree = "<group>"; };
+ F96D3F0D08F272A7004A47F5 /* tclObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclObj.c; sourceTree = "<group>"; };
+ F96D3F0E08F272A7004A47F5 /* tclPanic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPanic.c; sourceTree = "<group>"; };
+ F96D3F0F08F272A7004A47F5 /* tclParse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclParse.c; sourceTree = "<group>"; };
+ F96D3F1108F272A7004A47F5 /* tclPathObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPathObj.c; sourceTree = "<group>"; };
+ F96D3F1208F272A7004A47F5 /* tclPipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPipe.c; sourceTree = "<group>"; };
+ F96D3F1308F272A7004A47F5 /* tclPkg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPkg.c; sourceTree = "<group>"; };
+ F96D3F1408F272A7004A47F5 /* tclPkgConfig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPkgConfig.c; sourceTree = "<group>"; };
+ F96D3F1508F272A7004A47F5 /* tclPlatDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclPlatDecls.h; sourceTree = "<group>"; };
+ F96D3F1608F272A7004A47F5 /* tclPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclPort.h; sourceTree = "<group>"; };
+ F96D3F1708F272A7004A47F5 /* tclPosixStr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPosixStr.c; sourceTree = "<group>"; };
+ F96D3F1808F272A7004A47F5 /* tclPreserve.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPreserve.c; sourceTree = "<group>"; };
+ F96D3F1908F272A7004A47F5 /* tclProc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclProc.c; sourceTree = "<group>"; };
+ F96D3F1A08F272A7004A47F5 /* tclRegexp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclRegexp.c; sourceTree = "<group>"; };
+ F96D3F1B08F272A7004A47F5 /* tclRegexp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclRegexp.h; sourceTree = "<group>"; };
+ F96D3F1C08F272A7004A47F5 /* tclResolve.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclResolve.c; sourceTree = "<group>"; };
+ F96D3F1D08F272A7004A47F5 /* tclResult.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclResult.c; sourceTree = "<group>"; };
+ F96D3F1E08F272A7004A47F5 /* tclScan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclScan.c; sourceTree = "<group>"; };
+ F96D3F1F08F272A7004A47F5 /* tclStringObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStringObj.c; sourceTree = "<group>"; };
+ F96D3F2408F272A7004A47F5 /* tclStrToD.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStrToD.c; sourceTree = "<group>"; };
+ F96D3F2508F272A7004A47F5 /* tclStubInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStubInit.c; sourceTree = "<group>"; };
+ F96D3F2608F272A7004A47F5 /* tclStubLib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStubLib.c; sourceTree = "<group>"; };
+ F96D3F2708F272A7004A47F5 /* tclTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTest.c; sourceTree = "<group>"; };
+ F96D3F2808F272A7004A47F5 /* tclTestObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTestObj.c; sourceTree = "<group>"; };
+ F96D3F2908F272A7004A47F5 /* tclTestProcBodyObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTestProcBodyObj.c; sourceTree = "<group>"; };
+ F96D3F2A08F272A7004A47F5 /* tclThread.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThread.c; sourceTree = "<group>"; };
+ F96D3F2B08F272A7004A47F5 /* tclThreadAlloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadAlloc.c; sourceTree = "<group>"; };
+ F96D3F2C08F272A7004A47F5 /* tclThreadJoin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadJoin.c; sourceTree = "<group>"; };
+ F96D3F2D08F272A7004A47F5 /* tclThreadStorage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadStorage.c; sourceTree = "<group>"; };
+ F96D3F2E08F272A7004A47F5 /* tclThreadTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadTest.c; sourceTree = "<group>"; };
+ F96D3F2F08F272A7004A47F5 /* tclTimer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTimer.c; sourceTree = "<group>"; };
+ F96D3F3008F272A7004A47F5 /* tclTomMath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclTomMath.h; sourceTree = "<group>"; };
+ F96D3F3108F272A7004A47F5 /* tclTomMathInterface.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTomMathInterface.c; sourceTree = "<group>"; };
+ F96D3F3208F272A7004A47F5 /* tclTrace.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTrace.c; sourceTree = "<group>"; };
+ F96D3F3308F272A7004A47F5 /* tclUniData.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUniData.c; sourceTree = "<group>"; };
+ F96D3F3408F272A7004A47F5 /* tclUtf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUtf.c; sourceTree = "<group>"; };
+ F96D3F3508F272A7004A47F5 /* tclUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUtil.c; sourceTree = "<group>"; };
+ F96D3F3608F272A7004A47F5 /* tclVar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclVar.c; sourceTree = "<group>"; };
+ F96D3F3708F272A7004A47F5 /* tommath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tommath.h; sourceTree = "<group>"; };
+ F96D3F3908F272A8004A47F5 /* auto.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = auto.tcl; sourceTree = "<group>"; };
+ F96D3F3A08F272A8004A47F5 /* clock.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = clock.tcl; sourceTree = "<group>"; };
+ F96D3F3C08F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F96D3F8C08F272A8004A47F5 /* history.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = history.tcl; sourceTree = "<group>"; };
+ F96D3F8E08F272A8004A47F5 /* http.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = http.tcl; sourceTree = "<group>"; };
+ F96D3F8F08F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F96D3F9108F272A8004A47F5 /* http.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = http.tcl; sourceTree = "<group>"; };
+ F96D3F9208F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F96D3F9308F272A8004A47F5 /* init.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = init.tcl; sourceTree = "<group>"; };
+ F96D3F9508F272A8004A47F5 /* msgcat.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = msgcat.tcl; sourceTree = "<group>"; };
+ F96D3F9608F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F96D401808F272AA004A47F5 /* optparse.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = optparse.tcl; sourceTree = "<group>"; };
+ F96D401908F272AA004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F96D401A08F272AA004A47F5 /* package.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = package.tcl; sourceTree = "<group>"; };
+ F96D401B08F272AA004A47F5 /* parray.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parray.tcl; sourceTree = "<group>"; };
+ F96D401D08F272AA004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F96D401E08F272AA004A47F5 /* safe.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = safe.tcl; sourceTree = "<group>"; };
+ F96D401F08F272AA004A47F5 /* tclIndex */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclIndex; sourceTree = "<group>"; };
+ F96D402108F272AA004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F96D402208F272AA004A47F5 /* tcltest.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tcltest.tcl; sourceTree = "<group>"; };
+ F96D402308F272AA004A47F5 /* tm.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tm.tcl; sourceTree = "<group>"; };
+ F96D425B08F272B2004A47F5 /* word.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = word.tcl; sourceTree = "<group>"; };
+ F96D426408F272B3004A47F5 /* bn_fast_s_mp_mul_digs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_fast_s_mp_mul_digs.c; sourceTree = "<group>"; };
+ F96D426608F272B3004A47F5 /* bn_fast_s_mp_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_fast_s_mp_sqr.c; sourceTree = "<group>"; };
+ F96D426908F272B3004A47F5 /* bn_mp_add.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_add.c; sourceTree = "<group>"; };
+ F96D426A08F272B3004A47F5 /* bn_mp_add_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_add_d.c; sourceTree = "<group>"; };
+ F96D426C08F272B3004A47F5 /* bn_mp_and.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_and.c; sourceTree = "<group>"; };
+ F96D426D08F272B3004A47F5 /* bn_mp_clamp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_clamp.c; sourceTree = "<group>"; };
+ F96D426E08F272B3004A47F5 /* bn_mp_clear.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_clear.c; sourceTree = "<group>"; };
+ F96D426F08F272B3004A47F5 /* bn_mp_clear_multi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_clear_multi.c; sourceTree = "<group>"; };
+ F96D427008F272B3004A47F5 /* bn_mp_cmp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_cmp.c; sourceTree = "<group>"; };
+ F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_cmp_d.c; sourceTree = "<group>"; };
+ F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_cmp_mag.c; sourceTree = "<group>"; };
+ F96D427408F272B3004A47F5 /* bn_mp_copy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_copy.c; sourceTree = "<group>"; };
+ F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_count_bits.c; sourceTree = "<group>"; };
+ F96D427608F272B3004A47F5 /* bn_mp_div.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div.c; sourceTree = "<group>"; };
+ F96D427708F272B3004A47F5 /* bn_mp_div_2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_2.c; sourceTree = "<group>"; };
+ F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_2d.c; sourceTree = "<group>"; };
+ F96D427908F272B3004A47F5 /* bn_mp_div_3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_3.c; sourceTree = "<group>"; };
+ F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_d.c; sourceTree = "<group>"; };
+ F96D427E08F272B3004A47F5 /* bn_mp_exch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_exch.c; sourceTree = "<group>"; };
+ F96D427F08F272B3004A47F5 /* bn_mp_expt_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_expt_d.c; sourceTree = "<group>"; };
+ F96D428708F272B3004A47F5 /* bn_mp_grow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_grow.c; sourceTree = "<group>"; };
+ F96D428808F272B3004A47F5 /* bn_mp_init.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init.c; sourceTree = "<group>"; };
+ F96D428908F272B3004A47F5 /* bn_mp_init_copy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_copy.c; sourceTree = "<group>"; };
+ F96D428A08F272B3004A47F5 /* bn_mp_init_multi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_multi.c; sourceTree = "<group>"; };
+ F96D428B08F272B3004A47F5 /* bn_mp_init_set.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_set.c; sourceTree = "<group>"; };
+ F96D428D08F272B3004A47F5 /* bn_mp_init_size.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_size.c; sourceTree = "<group>"; };
+ F96D429208F272B3004A47F5 /* bn_mp_karatsuba_mul.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_karatsuba_mul.c; sourceTree = "<group>"; };
+ F96D429308F272B3004A47F5 /* bn_mp_karatsuba_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_karatsuba_sqr.c; sourceTree = "<group>"; };
+ F96D429508F272B3004A47F5 /* bn_mp_lshd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_lshd.c; sourceTree = "<group>"; };
+ F96D429608F272B3004A47F5 /* bn_mp_mod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mod.c; sourceTree = "<group>"; };
+ F96D429708F272B3004A47F5 /* bn_mp_mod_2d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mod_2d.c; sourceTree = "<group>"; };
+ F96D429C08F272B3004A47F5 /* bn_mp_mul.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul.c; sourceTree = "<group>"; };
+ F96D429D08F272B3004A47F5 /* bn_mp_mul_2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul_2.c; sourceTree = "<group>"; };
+ F96D429E08F272B3004A47F5 /* bn_mp_mul_2d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul_2d.c; sourceTree = "<group>"; };
+ F96D429F08F272B3004A47F5 /* bn_mp_mul_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul_d.c; sourceTree = "<group>"; };
+ F96D42A208F272B3004A47F5 /* bn_mp_neg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_neg.c; sourceTree = "<group>"; };
+ F96D42A308F272B3004A47F5 /* bn_mp_or.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_or.c; sourceTree = "<group>"; };
+ F96D42AB08F272B3004A47F5 /* bn_mp_radix_size.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_radix_size.c; sourceTree = "<group>"; };
+ F96D42AC08F272B3004A47F5 /* bn_mp_radix_smap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_radix_smap.c; sourceTree = "<group>"; };
+ F96D42AE08F272B3004A47F5 /* bn_mp_read_radix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_read_radix.c; sourceTree = "<group>"; };
+ F96D42B908F272B3004A47F5 /* bn_mp_rshd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_rshd.c; sourceTree = "<group>"; };
+ F96D42BA08F272B3004A47F5 /* bn_mp_set.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_set.c; sourceTree = "<group>"; };
+ F96D42BC08F272B3004A47F5 /* bn_mp_shrink.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_shrink.c; sourceTree = "<group>"; };
+ F96D42BE08F272B3004A47F5 /* bn_mp_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sqr.c; sourceTree = "<group>"; };
+ F96D42C008F272B3004A47F5 /* bn_mp_sqrt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sqrt.c; sourceTree = "<group>"; };
+ F96D42C108F272B3004A47F5 /* bn_mp_sub.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sub.c; sourceTree = "<group>"; };
+ F96D42C208F272B3004A47F5 /* bn_mp_sub_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sub_d.c; sourceTree = "<group>"; };
+ F96D42C608F272B3004A47F5 /* bn_mp_to_unsigned_bin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_to_unsigned_bin.c; sourceTree = "<group>"; };
+ F96D42C708F272B3004A47F5 /* bn_mp_to_unsigned_bin_n.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_to_unsigned_bin_n.c; sourceTree = "<group>"; };
+ F96D42C808F272B3004A47F5 /* bn_mp_toom_mul.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_toom_mul.c; sourceTree = "<group>"; };
+ F96D42C908F272B3004A47F5 /* bn_mp_toom_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_toom_sqr.c; sourceTree = "<group>"; };
+ F96D42CB08F272B3004A47F5 /* bn_mp_toradix_n.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_toradix_n.c; sourceTree = "<group>"; };
+ F96D42CC08F272B3004A47F5 /* bn_mp_unsigned_bin_size.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_unsigned_bin_size.c; sourceTree = "<group>"; };
+ F96D42CD08F272B3004A47F5 /* bn_mp_xor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_xor.c; sourceTree = "<group>"; };
+ F96D42CE08F272B3004A47F5 /* bn_mp_zero.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_zero.c; sourceTree = "<group>"; };
+ F96D42D008F272B3004A47F5 /* bn_reverse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_reverse.c; sourceTree = "<group>"; };
+ F96D42D108F272B3004A47F5 /* bn_s_mp_add.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_add.c; sourceTree = "<group>"; };
+ F96D42D308F272B3004A47F5 /* bn_s_mp_mul_digs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_mul_digs.c; sourceTree = "<group>"; };
+ F96D42D508F272B3004A47F5 /* bn_s_mp_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_sqr.c; sourceTree = "<group>"; };
+ F96D42D608F272B3004A47F5 /* bn_s_mp_sub.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_sub.c; sourceTree = "<group>"; };
+ F96D42D708F272B3004A47F5 /* bncore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bncore.c; sourceTree = "<group>"; };
+ F96D432908F272B4004A47F5 /* tommath_class.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tommath_class.h; sourceTree = "<group>"; };
+ F96D432A08F272B4004A47F5 /* tommath_superclass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tommath_superclass.h; sourceTree = "<group>"; };
+ F96D432B08F272B4004A47F5 /* license.terms */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = license.terms; sourceTree = "<group>"; };
+ F96D432E08F272B5004A47F5 /* configure.ac */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure.ac; sourceTree = "<group>"; };
+ F96D432F08F272B5004A47F5 /* GNUmakefile */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = GNUmakefile; sourceTree = "<group>"; };
+ F96D433108F272B5004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F96D433208F272B5004A47F5 /* Tcl-Info.plist.in */ = {isa = PBXFileReference; explicitFileType = text.plist; fileEncoding = 4; path = "Tcl-Info.plist.in"; sourceTree = "<group>"; };
+ F96D433908F272B5004A47F5 /* tclMacOSXBundle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMacOSXBundle.c; sourceTree = "<group>"; };
+ F96D433D08F272B5004A47F5 /* tclMacOSXFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMacOSXFCmd.c; sourceTree = "<group>"; };
+ F96D433E08F272B5004A47F5 /* tclMacOSXNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMacOSXNotify.c; sourceTree = "<group>"; };
+ F96D434308F272B5004A47F5 /* README */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = README; sourceTree = "<group>"; };
+ F96D434508F272B5004A47F5 /* all.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = all.tcl; sourceTree = "<group>"; };
+ F96D434608F272B5004A47F5 /* append.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = append.test; sourceTree = "<group>"; };
+ F96D434708F272B5004A47F5 /* appendComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = appendComp.test; sourceTree = "<group>"; };
+ F96D434808F272B5004A47F5 /* assocd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = assocd.test; sourceTree = "<group>"; };
+ F96D434908F272B5004A47F5 /* async.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = async.test; sourceTree = "<group>"; };
+ F96D434A08F272B5004A47F5 /* autoMkindex.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = autoMkindex.test; sourceTree = "<group>"; };
+ F96D434B08F272B5004A47F5 /* basic.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = basic.test; sourceTree = "<group>"; };
+ F96D434C08F272B5004A47F5 /* binary.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = binary.test; sourceTree = "<group>"; };
+ F96D434D08F272B5004A47F5 /* case.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = case.test; sourceTree = "<group>"; };
+ F96D434E08F272B5004A47F5 /* chan.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = chan.test; sourceTree = "<group>"; };
+ F96D434F08F272B5004A47F5 /* clock.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = clock.test; sourceTree = "<group>"; };
+ F96D435008F272B5004A47F5 /* cmdAH.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdAH.test; sourceTree = "<group>"; };
+ F96D435108F272B5004A47F5 /* cmdIL.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdIL.test; sourceTree = "<group>"; };
+ F96D435208F272B5004A47F5 /* cmdInfo.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdInfo.test; sourceTree = "<group>"; };
+ F96D435308F272B5004A47F5 /* cmdMZ.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdMZ.test; sourceTree = "<group>"; };
+ F96D435408F272B5004A47F5 /* compExpr-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "compExpr-old.test"; sourceTree = "<group>"; };
+ F96D435508F272B5004A47F5 /* compExpr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = compExpr.test; sourceTree = "<group>"; };
+ F96D435608F272B5004A47F5 /* compile.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = compile.test; sourceTree = "<group>"; };
+ F96D435708F272B5004A47F5 /* concat.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = concat.test; sourceTree = "<group>"; };
+ F96D435808F272B5004A47F5 /* config.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = config.test; sourceTree = "<group>"; };
+ F96D435908F272B5004A47F5 /* dcall.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dcall.test; sourceTree = "<group>"; };
+ F96D435A08F272B5004A47F5 /* dict.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dict.test; sourceTree = "<group>"; };
+ F96D435C08F272B5004A47F5 /* dstring.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dstring.test; sourceTree = "<group>"; };
+ F96D435E08F272B5004A47F5 /* encoding.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = encoding.test; sourceTree = "<group>"; };
+ F96D435F08F272B5004A47F5 /* env.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = env.test; sourceTree = "<group>"; };
+ F96D436008F272B5004A47F5 /* error.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = error.test; sourceTree = "<group>"; };
+ F96D436108F272B5004A47F5 /* eval.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = eval.test; sourceTree = "<group>"; };
+ F96D436208F272B5004A47F5 /* event.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = event.test; sourceTree = "<group>"; };
+ F96D436308F272B5004A47F5 /* exec.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = exec.test; sourceTree = "<group>"; };
+ F96D436408F272B5004A47F5 /* execute.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = execute.test; sourceTree = "<group>"; };
+ F96D436508F272B5004A47F5 /* expr-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "expr-old.test"; sourceTree = "<group>"; };
+ F96D436608F272B5004A47F5 /* expr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = expr.test; sourceTree = "<group>"; };
+ F96D436708F272B6004A47F5 /* fCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fCmd.test; sourceTree = "<group>"; };
+ F96D436808F272B6004A47F5 /* fileName.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fileName.test; sourceTree = "<group>"; };
+ F96D436908F272B6004A47F5 /* fileSystem.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fileSystem.test; sourceTree = "<group>"; };
+ F96D436A08F272B6004A47F5 /* for-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "for-old.test"; sourceTree = "<group>"; };
+ F96D436B08F272B6004A47F5 /* for.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = for.test; sourceTree = "<group>"; };
+ F96D436C08F272B6004A47F5 /* foreach.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = foreach.test; sourceTree = "<group>"; };
+ F96D436D08F272B6004A47F5 /* format.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = format.test; sourceTree = "<group>"; };
+ F96D436E08F272B6004A47F5 /* get.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = get.test; sourceTree = "<group>"; };
+ F96D436F08F272B6004A47F5 /* history.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = history.test; sourceTree = "<group>"; };
+ F96D437008F272B6004A47F5 /* http.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = http.test; sourceTree = "<group>"; };
+ F96D437108F272B6004A47F5 /* httpd */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = httpd; sourceTree = "<group>"; };
+ F96D437208F272B6004A47F5 /* httpold.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = httpold.test; sourceTree = "<group>"; };
+ F96D437308F272B6004A47F5 /* if-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "if-old.test"; sourceTree = "<group>"; };
+ F96D437408F272B6004A47F5 /* if.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = if.test; sourceTree = "<group>"; };
+ F96D437508F272B6004A47F5 /* incr-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "incr-old.test"; sourceTree = "<group>"; };
+ F96D437608F272B6004A47F5 /* incr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = incr.test; sourceTree = "<group>"; };
+ F96D437708F272B6004A47F5 /* indexObj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = indexObj.test; sourceTree = "<group>"; };
+ F96D437808F272B6004A47F5 /* info.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = info.test; sourceTree = "<group>"; };
+ F96D437908F272B6004A47F5 /* init.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = init.test; sourceTree = "<group>"; };
+ F96D437A08F272B6004A47F5 /* interp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = interp.test; sourceTree = "<group>"; };
+ F96D437B08F272B6004A47F5 /* io.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = io.test; sourceTree = "<group>"; };
+ F96D437C08F272B6004A47F5 /* ioCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = ioCmd.test; sourceTree = "<group>"; };
+ F96D437D08F272B6004A47F5 /* iogt.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = iogt.test; sourceTree = "<group>"; };
+ F96D437F08F272B6004A47F5 /* join.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = join.test; sourceTree = "<group>"; };
+ F96D438008F272B6004A47F5 /* lindex.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lindex.test; sourceTree = "<group>"; };
+ F96D438108F272B6004A47F5 /* link.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = link.test; sourceTree = "<group>"; };
+ F96D438208F272B6004A47F5 /* linsert.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = linsert.test; sourceTree = "<group>"; };
+ F96D438308F272B6004A47F5 /* list.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = list.test; sourceTree = "<group>"; };
+ F96D438408F272B6004A47F5 /* listObj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = listObj.test; sourceTree = "<group>"; };
+ F96D438508F272B6004A47F5 /* llength.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = llength.test; sourceTree = "<group>"; };
+ F96D438608F272B6004A47F5 /* load.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = load.test; sourceTree = "<group>"; };
+ F96D438708F272B6004A47F5 /* lrange.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lrange.test; sourceTree = "<group>"; };
+ F96D438808F272B6004A47F5 /* lrepeat.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lrepeat.test; sourceTree = "<group>"; };
+ F96D438908F272B6004A47F5 /* lreplace.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lreplace.test; sourceTree = "<group>"; };
+ F96D438A08F272B6004A47F5 /* lsearch.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lsearch.test; sourceTree = "<group>"; };
+ F96D438B08F272B6004A47F5 /* lset.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lset.test; sourceTree = "<group>"; };
+ F96D438C08F272B6004A47F5 /* lsetComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lsetComp.test; sourceTree = "<group>"; };
+ F96D438D08F272B6004A47F5 /* macOSXFCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = macOSXFCmd.test; sourceTree = "<group>"; };
+ F96D438E08F272B6004A47F5 /* main.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = main.test; sourceTree = "<group>"; };
+ F96D438F08F272B6004A47F5 /* misc.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = misc.test; sourceTree = "<group>"; };
+ F96D439008F272B6004A47F5 /* msgcat.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = msgcat.test; sourceTree = "<group>"; };
+ F96D439108F272B6004A47F5 /* namespace-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "namespace-old.test"; sourceTree = "<group>"; };
+ F96D439208F272B7004A47F5 /* namespace.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = namespace.test; sourceTree = "<group>"; };
+ F96D439308F272B7004A47F5 /* notify.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = notify.test; sourceTree = "<group>"; };
+ F96D439408F272B7004A47F5 /* obj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = obj.test; sourceTree = "<group>"; };
+ F96D439508F272B7004A47F5 /* opt.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = opt.test; sourceTree = "<group>"; };
+ F96D439608F272B7004A47F5 /* package.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = package.test; sourceTree = "<group>"; };
+ F96D439708F272B7004A47F5 /* parse.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parse.test; sourceTree = "<group>"; };
+ F96D439808F272B7004A47F5 /* parseExpr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parseExpr.test; sourceTree = "<group>"; };
+ F96D439908F272B7004A47F5 /* parseOld.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parseOld.test; sourceTree = "<group>"; };
+ F96D439A08F272B7004A47F5 /* pid.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pid.test; sourceTree = "<group>"; };
+ F96D439B08F272B7004A47F5 /* pkg.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkg.test; sourceTree = "<group>"; };
+ F96D439C08F272B7004A47F5 /* pkgMkIndex.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgMkIndex.test; sourceTree = "<group>"; };
+ F96D439D08F272B7004A47F5 /* platform.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = platform.test; sourceTree = "<group>"; };
+ F96D439E08F272B7004A47F5 /* proc-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "proc-old.test"; sourceTree = "<group>"; };
+ F96D439F08F272B7004A47F5 /* proc.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = proc.test; sourceTree = "<group>"; };
+ F96D43A008F272B7004A47F5 /* pwd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pwd.test; sourceTree = "<group>"; };
+ F96D43A108F272B7004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F96D43A208F272B7004A47F5 /* reg.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = reg.test; sourceTree = "<group>"; };
+ F96D43A308F272B7004A47F5 /* regexp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = regexp.test; sourceTree = "<group>"; };
+ F96D43A408F272B7004A47F5 /* regexpComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = regexpComp.test; sourceTree = "<group>"; };
+ F96D43A508F272B7004A47F5 /* registry.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = registry.test; sourceTree = "<group>"; };
+ F96D43A608F272B7004A47F5 /* remote.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = remote.tcl; sourceTree = "<group>"; };
+ F96D43A708F272B7004A47F5 /* rename.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = rename.test; sourceTree = "<group>"; };
+ F96D43A808F272B7004A47F5 /* result.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = result.test; sourceTree = "<group>"; };
+ F96D43A908F272B7004A47F5 /* safe.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = safe.test; sourceTree = "<group>"; };
+ F96D43AA08F272B7004A47F5 /* scan.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = scan.test; sourceTree = "<group>"; };
+ F96D43AB08F272B7004A47F5 /* security.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = security.test; sourceTree = "<group>"; };
+ F96D43AC08F272B7004A47F5 /* set-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "set-old.test"; sourceTree = "<group>"; };
+ F96D43AD08F272B7004A47F5 /* set.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = set.test; sourceTree = "<group>"; };
+ F96D43AE08F272B7004A47F5 /* socket.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = socket.test; sourceTree = "<group>"; };
+ F96D43AF08F272B7004A47F5 /* source.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = source.test; sourceTree = "<group>"; };
+ F96D43B008F272B7004A47F5 /* split.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = split.test; sourceTree = "<group>"; };
+ F96D43B108F272B7004A47F5 /* stack.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = stack.test; sourceTree = "<group>"; };
+ F96D43B208F272B7004A47F5 /* string.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = string.test; sourceTree = "<group>"; };
+ F96D43B308F272B7004A47F5 /* stringComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = stringComp.test; sourceTree = "<group>"; };
+ F96D43B408F272B7004A47F5 /* stringObj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = stringObj.test; sourceTree = "<group>"; };
+ F96D43B508F272B7004A47F5 /* subst.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = subst.test; sourceTree = "<group>"; };
+ F96D43B608F272B7004A47F5 /* switch.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = switch.test; sourceTree = "<group>"; };
+ F96D43B708F272B7004A47F5 /* tcltest.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tcltest.test; sourceTree = "<group>"; };
+ F96D43B808F272B7004A47F5 /* thread.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = thread.test; sourceTree = "<group>"; };
+ F96D43B908F272B7004A47F5 /* timer.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = timer.test; sourceTree = "<group>"; };
+ F96D43BA08F272B7004A47F5 /* tm.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tm.test; sourceTree = "<group>"; };
+ F96D43BB08F272B7004A47F5 /* trace.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = trace.test; sourceTree = "<group>"; };
+ F96D43BC08F272B7004A47F5 /* unixFCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixFCmd.test; sourceTree = "<group>"; };
+ F96D43BD08F272B7004A47F5 /* unixFile.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixFile.test; sourceTree = "<group>"; };
+ F96D43BE08F272B7004A47F5 /* unixInit.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixInit.test; sourceTree = "<group>"; };
+ F96D43BF08F272B7004A47F5 /* unixNotfy.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixNotfy.test; sourceTree = "<group>"; };
+ F96D43C008F272B7004A47F5 /* unknown.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unknown.test; sourceTree = "<group>"; };
+ F96D43C108F272B7004A47F5 /* unload.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unload.test; sourceTree = "<group>"; };
+ F96D43C208F272B7004A47F5 /* uplevel.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uplevel.test; sourceTree = "<group>"; };
+ F96D43C308F272B7004A47F5 /* upvar.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = upvar.test; sourceTree = "<group>"; };
+ F96D43C408F272B7004A47F5 /* utf.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = utf.test; sourceTree = "<group>"; };
+ F96D43C508F272B7004A47F5 /* util.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = util.test; sourceTree = "<group>"; };
+ F96D43C608F272B7004A47F5 /* var.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = var.test; sourceTree = "<group>"; };
+ F96D43C708F272B7004A47F5 /* while-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "while-old.test"; sourceTree = "<group>"; };
+ F96D43C808F272B7004A47F5 /* while.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = while.test; sourceTree = "<group>"; };
+ F96D43C908F272B7004A47F5 /* winConsole.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winConsole.test; sourceTree = "<group>"; };
+ F96D43CA08F272B7004A47F5 /* winDde.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winDde.test; sourceTree = "<group>"; };
+ F96D43CB08F272B7004A47F5 /* winFCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winFCmd.test; sourceTree = "<group>"; };
+ F96D43CC08F272B7004A47F5 /* winFile.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winFile.test; sourceTree = "<group>"; };
+ F96D43CD08F272B7004A47F5 /* winNotify.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winNotify.test; sourceTree = "<group>"; };
+ F96D43CE08F272B7004A47F5 /* winPipe.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winPipe.test; sourceTree = "<group>"; };
+ F96D43CF08F272B7004A47F5 /* winTime.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winTime.test; sourceTree = "<group>"; };
+ F96D43D108F272B8004A47F5 /* checkLibraryDoc.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = checkLibraryDoc.tcl; sourceTree = "<group>"; };
+ F96D43D208F272B8004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
+ F96D43D308F272B8004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
+ F96D442208F272B8004A47F5 /* eolFix.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = eolFix.tcl; sourceTree = "<group>"; };
+ F96D442408F272B8004A47F5 /* fix_tommath_h.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fix_tommath_h.tcl; sourceTree = "<group>"; };
+ F96D442508F272B8004A47F5 /* genStubs.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = genStubs.tcl; sourceTree = "<group>"; };
+ F96D442708F272B8004A47F5 /* index.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = index.tcl; sourceTree = "<group>"; };
+ F96D442808F272B8004A47F5 /* installData.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = installData.tcl; sourceTree = "<group>"; };
+ F96D442908F272B8004A47F5 /* loadICU.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = loadICU.tcl; sourceTree = "<group>"; };
+ F96D442A08F272B8004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
+ F96D442B08F272B8004A47F5 /* makeTestCases.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = makeTestCases.tcl; sourceTree = "<group>"; };
+ F96D442C08F272B8004A47F5 /* man2help.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2help.tcl; sourceTree = "<group>"; };
+ F96D442D08F272B8004A47F5 /* man2help2.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2help2.tcl; sourceTree = "<group>"; };
+ F96D442E08F272B8004A47F5 /* man2html.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2html.tcl; sourceTree = "<group>"; };
+ F96D442F08F272B8004A47F5 /* man2html1.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2html1.tcl; sourceTree = "<group>"; };
+ F96D443008F272B8004A47F5 /* man2html2.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2html2.tcl; sourceTree = "<group>"; };
+ F96D443108F272B8004A47F5 /* man2tcl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = man2tcl.c; sourceTree = "<group>"; };
+ F96D443208F272B8004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F96D443308F272B8004A47F5 /* regexpTestLib.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = regexpTestLib.tcl; sourceTree = "<group>"; };
+ F96D443508F272B8004A47F5 /* tcl.hpj.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.hpj.in; sourceTree = "<group>"; };
+ F96D443608F272B8004A47F5 /* tcl.wse.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.wse.in; sourceTree = "<group>"; };
+ F96D443908F272B9004A47F5 /* tcltk-man2html.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "tcltk-man2html.tcl"; sourceTree = "<group>"; };
+ F96D443A08F272B9004A47F5 /* tclZIC.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclZIC.tcl; sourceTree = "<group>"; };
+ F96D443B08F272B9004A47F5 /* uniClass.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uniClass.tcl; sourceTree = "<group>"; };
+ F96D443C08F272B9004A47F5 /* uniParse.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uniParse.tcl; sourceTree = "<group>"; };
+ F96D444008F272B9004A47F5 /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = "<group>"; };
+ F96D444108F272B9004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
+ F96D444208F272B9004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
+ F96D444408F272B9004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
+ F96D444508F272B9004A47F5 /* pkga.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkga.c; sourceTree = "<group>"; };
+ F96D444608F272B9004A47F5 /* pkgb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgb.c; sourceTree = "<group>"; };
+ F96D444708F272B9004A47F5 /* pkgc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgc.c; sourceTree = "<group>"; };
+ F96D444808F272B9004A47F5 /* pkgd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgd.c; sourceTree = "<group>"; };
+ F96D444908F272B9004A47F5 /* pkge.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkge.c; sourceTree = "<group>"; };
+ F96D444B08F272B9004A47F5 /* pkgua.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgua.c; sourceTree = "<group>"; };
+ F96D444C08F272B9004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F96D444D08F272B9004A47F5 /* install-sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "install-sh"; sourceTree = "<group>"; };
+ F96D444E08F272B9004A47F5 /* installManPage */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = installManPage; sourceTree = "<group>"; };
+ F96D444F08F272B9004A47F5 /* ldAix */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = ldAix; sourceTree = "<group>"; };
+ F96D445008F272B9004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
+ F96D445208F272B9004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F96D445308F272B9004A47F5 /* tcl.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tcl.m4; sourceTree = "<group>"; };
+ F96D445408F272B9004A47F5 /* tcl.spec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.spec; sourceTree = "<group>"; };
+ F96D445508F272B9004A47F5 /* tclAppInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAppInit.c; sourceTree = "<group>"; };
+ F96D445608F272B9004A47F5 /* tclConfig.h.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = tclConfig.h.in; sourceTree = "<group>"; };
+ F96D445708F272B9004A47F5 /* tclConfig.sh.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tclConfig.sh.in; sourceTree = "<group>"; };
+ F96D445808F272B9004A47F5 /* tclLoadAix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadAix.c; sourceTree = "<group>"; };
+ F96D445908F272B9004A47F5 /* tclLoadDl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadDl.c; sourceTree = "<group>"; };
+ F96D445B08F272B9004A47F5 /* tclLoadDyld.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadDyld.c; sourceTree = "<group>"; };
+ F96D445C08F272B9004A47F5 /* tclLoadNext.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadNext.c; sourceTree = "<group>"; };
+ F96D445D08F272B9004A47F5 /* tclLoadOSF.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadOSF.c; sourceTree = "<group>"; };
+ F96D445E08F272B9004A47F5 /* tclLoadShl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadShl.c; sourceTree = "<group>"; };
+ F96D445F08F272B9004A47F5 /* tclUnixChan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixChan.c; sourceTree = "<group>"; };
+ F96D446008F272B9004A47F5 /* tclUnixEvent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixEvent.c; sourceTree = "<group>"; };
+ F96D446108F272B9004A47F5 /* tclUnixFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixFCmd.c; sourceTree = "<group>"; };
+ F96D446208F272B9004A47F5 /* tclUnixFile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixFile.c; sourceTree = "<group>"; };
+ F96D446308F272B9004A47F5 /* tclUnixInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixInit.c; sourceTree = "<group>"; };
+ F96D446408F272B9004A47F5 /* tclUnixNotfy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixNotfy.c; sourceTree = "<group>"; };
+ F96D446508F272B9004A47F5 /* tclUnixPipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixPipe.c; sourceTree = "<group>"; };
+ F96D446608F272B9004A47F5 /* tclUnixPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclUnixPort.h; sourceTree = "<group>"; };
+ F96D446708F272B9004A47F5 /* tclUnixSock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixSock.c; sourceTree = "<group>"; };
+ F96D446808F272B9004A47F5 /* tclUnixTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixTest.c; sourceTree = "<group>"; };
+ F96D446908F272B9004A47F5 /* tclUnixThrd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixThrd.c; sourceTree = "<group>"; };
+ F96D446A08F272B9004A47F5 /* tclUnixThrd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclUnixThrd.h; sourceTree = "<group>"; };
+ F96D446B08F272B9004A47F5 /* tclUnixTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixTime.c; sourceTree = "<group>"; };
+ F96D446C08F272B9004A47F5 /* tclXtNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclXtNotify.c; sourceTree = "<group>"; };
+ F96D446D08F272B9004A47F5 /* tclXtTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclXtTest.c; sourceTree = "<group>"; };
+ F96D447008F272BA004A47F5 /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = "<group>"; };
+ F96D447108F272BA004A47F5 /* buildall.vc.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = buildall.vc.bat; sourceTree = "<group>"; };
+ F96D447208F272BA004A47F5 /* cat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cat.c; sourceTree = "<group>"; };
+ F96D447408F272BA004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
+ F96D447508F272BA004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
+ F96D447708F272BA004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
+ F96D447808F272BA004A47F5 /* makefile.vc */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = makefile.vc; sourceTree = "<group>"; };
+ F96D447908F272BA004A47F5 /* nmakehlp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nmakehlp.c; sourceTree = "<group>"; };
+ F96D447A08F272BA004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F96D447C08F272BA004A47F5 /* rules.vc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rules.vc; sourceTree = "<group>"; };
+ F96D447D08F272BA004A47F5 /* stub16.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stub16.c; sourceTree = "<group>"; };
+ F96D447E08F272BA004A47F5 /* tcl.dsp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.dsp; sourceTree = "<group>"; };
+ F96D447F08F272BA004A47F5 /* tcl.dsw */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.dsw; sourceTree = "<group>"; };
+ F96D448008F272BA004A47F5 /* tcl.hpj.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.hpj.in; sourceTree = "<group>"; };
+ F96D448108F272BA004A47F5 /* tcl.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tcl.m4; sourceTree = "<group>"; };
+ F96D448208F272BA004A47F5 /* tcl.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.rc; sourceTree = "<group>"; };
+ F96D448308F272BA004A47F5 /* tclAppInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAppInit.c; sourceTree = "<group>"; };
+ F96D448408F272BA004A47F5 /* tclConfig.sh.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tclConfig.sh.in; sourceTree = "<group>"; };
+ F96D448608F272BA004A47F5 /* tclsh.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tclsh.rc; sourceTree = "<group>"; };
+ F96D448708F272BA004A47F5 /* tclWin32Dll.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWin32Dll.c; sourceTree = "<group>"; };
+ F96D448808F272BA004A47F5 /* tclWinChan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinChan.c; sourceTree = "<group>"; };
+ F96D448908F272BA004A47F5 /* tclWinConsole.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinConsole.c; sourceTree = "<group>"; };
+ F96D448A08F272BA004A47F5 /* tclWinDde.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinDde.c; sourceTree = "<group>"; };
+ F96D448B08F272BA004A47F5 /* tclWinError.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinError.c; sourceTree = "<group>"; };
+ F96D448C08F272BA004A47F5 /* tclWinFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinFCmd.c; sourceTree = "<group>"; };
+ F96D448D08F272BA004A47F5 /* tclWinFile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinFile.c; sourceTree = "<group>"; };
+ F96D448E08F272BA004A47F5 /* tclWinInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinInit.c; sourceTree = "<group>"; };
+ F96D448F08F272BA004A47F5 /* tclWinInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclWinInt.h; sourceTree = "<group>"; };
+ F96D449008F272BA004A47F5 /* tclWinLoad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinLoad.c; sourceTree = "<group>"; };
+ F96D449108F272BA004A47F5 /* tclWinNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinNotify.c; sourceTree = "<group>"; };
+ F96D449208F272BA004A47F5 /* tclWinPipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinPipe.c; sourceTree = "<group>"; };
+ F96D449308F272BA004A47F5 /* tclWinPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclWinPort.h; sourceTree = "<group>"; };
+ F96D449408F272BA004A47F5 /* tclWinReg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinReg.c; sourceTree = "<group>"; };
+ F96D449508F272BA004A47F5 /* tclWinSerial.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinSerial.c; sourceTree = "<group>"; };
+ F96D449608F272BA004A47F5 /* tclWinSock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinSock.c; sourceTree = "<group>"; };
+ F96D449708F272BA004A47F5 /* tclWinTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinTest.c; sourceTree = "<group>"; };
+ F96D449808F272BA004A47F5 /* tclWinThrd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinThrd.c; sourceTree = "<group>"; };
+ F96D449908F272BA004A47F5 /* tclWinThrd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclWinThrd.h; sourceTree = "<group>"; };
+ F96D449A08F272BA004A47F5 /* tclWinTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinTime.c; sourceTree = "<group>"; };
+ F973E5960EE99384001A648E /* vistaTheme.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = vistaTheme.tcl; sourceTree = "<group>"; };
+ F974D56C0FBE7D6300BF728B /* http11.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = http11.test; sourceTree = "<group>"; };
+ F974D56D0FBE7D6300BF728B /* httpd11.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = httpd11.tcl; sourceTree = "<group>"; };
+ F974D5720FBE7DC600BF728B /* coroutine.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = coroutine.n; sourceTree = "<group>"; };
+ F974D5760FBE7E1900BF728B /* tailcall.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tailcall.n; sourceTree = "<group>"; };
+ F974D5770FBE7E6100BF728B /* coroutine.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = coroutine.test; sourceTree = "<group>"; };
+ F974D5780FBE7E6100BF728B /* tailcall.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tailcall.test; sourceTree = "<group>"; };
+ F974D5790FBE7E9C00BF728B /* tcl.pc.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.pc.in; sourceTree = "<group>"; };
+ F974D57B0FBE7EC000BF728B /* tk.pc.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tk.pc.in; sourceTree = "<group>"; };
+ F974D57C0FBE7EFF00BF728B /* iconlist.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = iconlist.tcl; sourceTree = "<group>"; };
+ F974D57D0FBE7EFF00BF728B /* icons.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = icons.tcl; sourceTree = "<group>"; };
+ F97590AE1039A96200558A9A /* Wish.sdef */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.sdef; path = Wish.sdef; sourceTree = "<group>"; };
+ F976F6A70C325FB6005066D9 /* tkMacOSXPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMacOSXPrivate.h; sourceTree = "<group>"; };
+ F97AE7F10B65C1E900310EA2 /* Tk-Common.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tk-Common.xcconfig"; sourceTree = "<group>"; };
+ F97AE82B0B65C69B00310EA2 /* Tk-Release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tk-Release.xcconfig"; sourceTree = "<group>"; };
+ F97AE8330B65C87F00310EA2 /* Tk-Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tk-Debug.xcconfig"; sourceTree = "<group>"; };
+ F98383650F0FA43900171CA6 /* checkbutton.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = checkbutton.test; sourceTree = "<group>"; };
+ F98383680F0FA44700171CA6 /* radiobutton.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = radiobutton.test; sourceTree = "<group>"; };
+ F9903CAF094FAADA004613E9 /* tclTomMath.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclTomMath.decls; sourceTree = "<group>"; };
+ F9903CB0094FAADA004613E9 /* tclTomMathDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclTomMathDecls.h; sourceTree = "<group>"; };
+ F99388380EE0114B0065FE6B /* fontchooser.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fontchooser.tcl; sourceTree = "<group>"; };
+ F99388950EE02D980065FE6B /* fontchooser.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fontchooser.test; sourceTree = "<group>"; };
+ F99D61180EF5573A00BBFE01 /* TclZlib.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TclZlib.3; sourceTree = "<group>"; };
+ F9A3082D08F2D4AB00BAE1AB /* Tk.framework */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.framework; path = Tk.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ F9A3084B08F2D4CE00BAE1AB /* Wish.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Wish.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ F9A3084E08F2D4F400BAE1AB /* Tcl.framework */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.framework; path = Tcl.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ F9A493240CEBF38300B78AE2 /* chanio.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = chanio.test; sourceTree = "<group>"; };
+ F9C888C20EEF6571003F63AD /* fontchooser.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fontchooser.n; sourceTree = "<group>"; };
+ F9C9CBFF0E84059800E00935 /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = /System/Library/Frameworks/ApplicationServices.framework; sourceTree = "<absolute>"; };
+ F9D1360A0CDC252C00DBE0B5 /* mclist.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = mclist.tcl; sourceTree = "<group>"; };
+ F9DD99BC0F07DF850018B2E4 /* tkImgPNG.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkImgPNG.c; sourceTree = "<group>"; };
+ F9DD99BF0F07DFCD0018B2E4 /* imgPNG.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = imgPNG.test; sourceTree = "<group>"; };
+ F9ECB1120B26521500A28025 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F9ECB1130B26521500A28025 /* platform.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = platform.tcl; sourceTree = "<group>"; };
+ F9ECB1140B26521500A28025 /* shell.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = shell.tcl; sourceTree = "<group>"; };
+ F9ECB1CA0B2652D300A28025 /* apply.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = apply.test; sourceTree = "<group>"; };
+ F9ECB1CB0B26534C00A28025 /* mathop.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = mathop.test; sourceTree = "<group>"; };
+ F9ECB1E10B26543C00A28025 /* platform_shell.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = platform_shell.n; sourceTree = "<group>"; };
+ F9ECB1E20B26543C00A28025 /* platform.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = platform.n; sourceTree = "<group>"; };
+ F9F4415D0C8BAE6F00BCCD67 /* tclDTrace.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; path = tclDTrace.d; sourceTree = "<group>"; };
+ F9F4EFDC0CC7B3CA00378A27 /* ttkpane.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; languageSpecificationIdentifier = shell; path = ttkpane.tcl; sourceTree = "<group>"; };
+ F9F4EFDD0CC7B3CB00378A27 /* ttkmenu.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; languageSpecificationIdentifier = shell; path = ttkmenu.tcl; sourceTree = "<group>"; };
+ F9FC77B70AB29E9100B7077D /* tclUnixCompat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixCompat.c; sourceTree = "<group>"; };
+ F9FD31F40CC1AD070073837D /* tktest-X11 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "tktest-X11"; sourceTree = BUILT_PRODUCTS_DIR; };
+ F9FD32140CC1AF170073837D /* libX11.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libX11.dylib; path = /usr/X11R6/lib/libX11.dylib; sourceTree = "<absolute>"; };
+ F9FD32150CC1AF170073837D /* libXext.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libXext.dylib; path = /usr/X11R6/lib/libXext.dylib; sourceTree = "<absolute>"; };
+ F9FD32160CC1AF170073837D /* libXss.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libXss.dylib; path = /usr/X11R6/lib/libXss.dylib; sourceTree = "<absolute>"; };
+ F9FD34990CC1BB0D0073837D /* libfreetype.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libfreetype.dylib; path = /usr/X11R6/lib/libfreetype.dylib; sourceTree = "<absolute>"; };
+ F9FD349A0CC1BB0D0073837D /* libXft.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libXft.dylib; path = /usr/X11R6/lib/libXft.dylib; sourceTree = "<absolute>"; };
+ F9FD34C30CC1BBD70073837D /* libfontconfig.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libfontconfig.dylib; path = /usr/X11R6/lib/libfontconfig.dylib; sourceTree = "<absolute>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 8DD76FAD0486AB0100D96B5E /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F966C07508F2820D005CB29B /* CoreFoundation.framework in Frameworks */,
+ F96437E70EF0D652003F468E /* libz.dylib in Frameworks */,
+ F966C07708F2821B005CB29B /* Carbon.framework in Frameworks */,
+ F966C07908F28233005CB29B /* IOKit.framework in Frameworks */,
+ F94523A20E6FC2AC00C1D987 /* Cocoa.framework in Frameworks */,
+ F9C9CC000E84059800E00935 /* ApplicationServices.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F9FD31E30CC1AD070073837D /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F9FD31E40CC1AD070073837D /* CoreFoundation.framework in Frameworks */,
+ F96437E80EF0D652003F468E /* libz.dylib in Frameworks */,
+ F9FD32170CC1AF170073837D /* libX11.dylib in Frameworks */,
+ F9FD32180CC1AF170073837D /* libXext.dylib in Frameworks */,
+ F9FD32190CC1AF170073837D /* libXss.dylib in Frameworks */,
+ F9FD349C0CC1BB0D0073837D /* libXft.dylib in Frameworks */,
+ F9FD349B0CC1BB0D0073837D /* libfreetype.dylib in Frameworks */,
+ F9FD34C40CC1BBD70073837D /* libfontconfig.dylib in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 08FB7794FE84155DC02AAC07 /* Tk */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3DF708F271BE004A47F5 /* Tk Sources */,
+ F96D3DF608F27169004A47F5 /* Tcl Sources */,
+ F966C06F08F281DC005CB29B /* Frameworks */,
+ 1AB674ADFE9D54B511CA2CBB /* Products */,
+ );
+ comments = "Copyright (c) 2004-2009 Daniel A. Steffen <das@users.sourceforge.net>\nCopyright 2008-2009, Apple Inc.\n\nSee the file \"license.terms\" for information on usage and redistribution of\nthis file, and for a DISCLAIMER OF ALL WARRANTIES.\n";
+ name = Tk;
+ path = .;
+ sourceTree = SOURCE_ROOT;
+ };
+ 1AB674ADFE9D54B511CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ F9A3084B08F2D4CE00BAE1AB /* Wish.app */,
+ F9A3082D08F2D4AB00BAE1AB /* Tk.framework */,
+ F9A3084E08F2D4F400BAE1AB /* Tcl.framework */,
+ 8DD76FB20486AB0100D96B5E /* tktest */,
+ F9FD31F40CC1AD070073837D /* tktest-X11 */,
+ );
+ includeInIndex = 0;
+ name = Products;
+ sourceTree = "<group>";
+ };
+ F9183E690EFC81560030B814 /* pkgs */ = {
+ isa = PBXGroup;
+ children = (
+ F9183E6A0EFC81560030B814 /* README */,
+ F946FB8B0FBE3AED00CD6495 /* itcl */,
+ F9183E8F0EFC817B0030B814 /* tdbc */,
+ );
+ path = pkgs;
+ sourceTree = "<group>";
+ };
+ F966BA0308F27A37005CB29B /* bitmaps */ = {
+ isa = PBXGroup;
+ children = (
+ F966BA0408F27A37005CB29B /* error.xbm */,
+ F966BA0508F27A37005CB29B /* gray12.xbm */,
+ F966BA0608F27A37005CB29B /* gray25.xbm */,
+ F966BA0708F27A37005CB29B /* gray50.xbm */,
+ F966BA0808F27A37005CB29B /* gray75.xbm */,
+ F966BA0908F27A37005CB29B /* hourglass.xbm */,
+ F966BA0A08F27A37005CB29B /* info.xbm */,
+ F966BA0B08F27A37005CB29B /* questhead.xbm */,
+ F966BA0C08F27A37005CB29B /* question.xbm */,
+ F966BA0D08F27A37005CB29B /* warning.xbm */,
+ );
+ path = bitmaps;
+ sourceTree = "<group>";
+ };
+ F966BA1008F27A37005CB29B /* doc */ = {
+ isa = PBXGroup;
+ children = (
+ F966BA1108F27A37005CB29B /* 3DBorder.3 */,
+ F966BA1208F27A37005CB29B /* AddOption.3 */,
+ F966BA1308F27A37005CB29B /* bell.n */,
+ F966BA1408F27A37005CB29B /* bind.n */,
+ F966BA1508F27A37005CB29B /* BindTable.3 */,
+ F966BA1608F27A37005CB29B /* bindtags.n */,
+ F966BA1708F27A37005CB29B /* bitmap.n */,
+ F966BA1808F27A37005CB29B /* button.n */,
+ F966BA1908F27A37005CB29B /* canvas.n */,
+ F966BA1A08F27A37005CB29B /* CanvPsY.3 */,
+ F966BA1B08F27A37005CB29B /* CanvTkwin.3 */,
+ F966BA1C08F27A37005CB29B /* CanvTxtInfo.3 */,
+ F966BA1D08F27A37005CB29B /* checkbutton.n */,
+ F966BA1E08F27A37005CB29B /* chooseColor.n */,
+ F966BA1F08F27A37005CB29B /* chooseDirectory.n */,
+ F966BA2008F27A37005CB29B /* Clipboard.3 */,
+ F966BA2108F27A37005CB29B /* clipboard.n */,
+ F966BA2208F27A37005CB29B /* ClrSelect.3 */,
+ F966BA2308F27A37005CB29B /* colors.n */,
+ F966BA2408F27A37005CB29B /* ConfigWidg.3 */,
+ F966BA2508F27A37005CB29B /* ConfigWind.3 */,
+ F966BA2608F27A37005CB29B /* console.n */,
+ F966BA2708F27A37005CB29B /* CoordToWin.3 */,
+ F966BA2808F27A37005CB29B /* CrtCmHdlr.3 */,
+ F966BA2908F27A37005CB29B /* CrtErrHdlr.3 */,
+ F966BA2A08F27A37005CB29B /* CrtGenHdlr.3 */,
+ F966BA2B08F27A37005CB29B /* CrtImgType.3 */,
+ F966BA2C08F27A37005CB29B /* CrtItemType.3 */,
+ F966BA2D08F27A37005CB29B /* CrtPhImgFmt.3 */,
+ F966BA2E08F27A37005CB29B /* CrtSelHdlr.3 */,
+ F966BA2F08F27A37005CB29B /* CrtWindow.3 */,
+ F966BA3008F27A37005CB29B /* cursors.n */,
+ F966BA3108F27A37005CB29B /* DeleteImg.3 */,
+ F966BA3208F27A37005CB29B /* destroy.n */,
+ F966BA3308F27A37005CB29B /* dialog.n */,
+ F966BA3408F27A37005CB29B /* DrawFocHlt.3 */,
+ F966BA3508F27A37005CB29B /* entry.n */,
+ F966BA3608F27A37005CB29B /* event.n */,
+ F966BA3708F27A37005CB29B /* EventHndlr.3 */,
+ F966BA3808F27A37005CB29B /* FindPhoto.3 */,
+ F966BA3908F27A37005CB29B /* focus.n */,
+ F966BA3A08F27A37005CB29B /* focusNext.n */,
+ F966BA3B08F27A37005CB29B /* font.n */,
+ F9C888C20EEF6571003F63AD /* fontchooser.n */,
+ F966BA3C08F27A37005CB29B /* FontId.3 */,
+ F966BA3D08F27A37005CB29B /* frame.n */,
+ F966BA3E08F27A37005CB29B /* FreeXId.3 */,
+ F966BA3F08F27A37005CB29B /* GeomReq.3 */,
+ F966BA4008F27A37005CB29B /* GetAnchor.3 */,
+ F966BA4108F27A37005CB29B /* GetBitmap.3 */,
+ F966BA4208F27A37005CB29B /* GetCapStyl.3 */,
+ F966BA4308F27A37005CB29B /* GetClrmap.3 */,
+ F966BA4408F27A37005CB29B /* GetColor.3 */,
+ F966BA4508F27A37005CB29B /* GetCursor.3 */,
+ F966BA4608F27A37005CB29B /* GetDash.3 */,
+ F966BA4708F27A37005CB29B /* GetFont.3 */,
+ F966BA4808F27A37005CB29B /* GetGC.3 */,
+ F966BA4908F27A37005CB29B /* GetHINSTANCE.3 */,
+ F966BA4A08F27A37005CB29B /* GetHWND.3 */,
+ F966BA4B08F27A37005CB29B /* GetImage.3 */,
+ F966BA4C08F27A37005CB29B /* GetJoinStl.3 */,
+ F966BA4D08F27A37005CB29B /* GetJustify.3 */,
+ F966BA4E08F27A37005CB29B /* getOpenFile.n */,
+ F966BA4F08F27A37005CB29B /* GetOption.3 */,
+ F966BA5008F27A38005CB29B /* GetPixels.3 */,
+ F966BA5108F27A38005CB29B /* GetPixmap.3 */,
+ F966BA5208F27A38005CB29B /* GetRelief.3 */,
+ F966BA5308F27A38005CB29B /* GetRootCrd.3 */,
+ F966BA5408F27A38005CB29B /* GetScroll.3 */,
+ F966BA5508F27A38005CB29B /* GetSelect.3 */,
+ F966BA5608F27A38005CB29B /* GetUid.3 */,
+ F966BA5708F27A38005CB29B /* GetVisual.3 */,
+ F966BA5808F27A38005CB29B /* GetVRoot.3 */,
+ F966BA5908F27A38005CB29B /* Grab.3 */,
+ F966BA5A08F27A38005CB29B /* grab.n */,
+ F966BA5B08F27A38005CB29B /* grid.n */,
+ F966BA5C08F27A38005CB29B /* HandleEvent.3 */,
+ F966BA5D08F27A38005CB29B /* HWNDToWindow.3 */,
+ F966BA5E08F27A38005CB29B /* IdToWindow.3 */,
+ F966BA5F08F27A38005CB29B /* image.n */,
+ F966BA6008F27A38005CB29B /* ImgChanged.3 */,
+ F966BA6108F27A38005CB29B /* Inactive.3 */,
+ F966BA6208F27A38005CB29B /* InternAtom.3 */,
+ F966BA6308F27A38005CB29B /* keysyms.n */,
+ F966BA6408F27A38005CB29B /* label.n */,
+ F966BA6508F27A38005CB29B /* labelframe.n */,
+ F966BA6608F27A38005CB29B /* listbox.n */,
+ F966BA6708F27A38005CB29B /* loadTk.n */,
+ F966BA6808F27A38005CB29B /* lower.n */,
+ F966BA6908F27A38005CB29B /* MainLoop.3 */,
+ F966BA6A08F27A38005CB29B /* MaintGeom.3 */,
+ F966BA6B08F27A38005CB29B /* MainWin.3 */,
+ F966BA6D08F27A38005CB29B /* ManageGeom.3 */,
+ F966BA6E08F27A38005CB29B /* MapWindow.3 */,
+ F966BA6F08F27A38005CB29B /* MeasureChar.3 */,
+ F966BA7008F27A38005CB29B /* menu.n */,
+ F966BA7108F27A38005CB29B /* menubar.n */,
+ F966BA7208F27A38005CB29B /* menubutton.n */,
+ F966BA7308F27A38005CB29B /* message.n */,
+ F966BA7408F27A38005CB29B /* messageBox.n */,
+ F966BA7508F27A38005CB29B /* MoveToplev.3 */,
+ F966BA7608F27A38005CB29B /* Name.3 */,
+ F966BA7708F27A38005CB29B /* NameOfImg.3 */,
+ F966BA7808F27A38005CB29B /* option.n */,
+ F966BA7908F27A38005CB29B /* optionMenu.n */,
+ F966BA7A08F27A38005CB29B /* options.n */,
+ F966BA7B08F27A38005CB29B /* OwnSelect.3 */,
+ F966BA7C08F27A38005CB29B /* pack-old.n */,
+ F966BA7D08F27A38005CB29B /* pack.n */,
+ F966BA7E08F27A38005CB29B /* palette.n */,
+ F966BA7F08F27A38005CB29B /* panedwindow.n */,
+ F966BA8008F27A38005CB29B /* ParseArgv.3 */,
+ F966BA8108F27A38005CB29B /* photo.n */,
+ F966BA8208F27A38005CB29B /* place.n */,
+ F966BA8308F27A38005CB29B /* popup.n */,
+ F966BA8408F27A38005CB29B /* QWinEvent.3 */,
+ F966BA8508F27A38005CB29B /* radiobutton.n */,
+ F966BA8608F27A38005CB29B /* raise.n */,
+ F966BA8708F27A38005CB29B /* Restack.3 */,
+ F966BA8808F27A38005CB29B /* RestrictEv.3 */,
+ F966BA8908F27A38005CB29B /* scale.n */,
+ F966BA8A08F27A38005CB29B /* scrollbar.n */,
+ F966BA8B08F27A38005CB29B /* selection.n */,
+ F966BA8C08F27A38005CB29B /* send.n */,
+ F966BA8D08F27A38005CB29B /* SetAppName.3 */,
+ F966BA8E08F27A38005CB29B /* SetCaret.3 */,
+ F966BA8F08F27A38005CB29B /* SetClass.3 */,
+ F966BA9008F27A38005CB29B /* SetClassProcs.3 */,
+ F966BA9108F27A38005CB29B /* SetGrid.3 */,
+ F966BA9208F27A38005CB29B /* SetOptions.3 */,
+ F966BA9308F27A38005CB29B /* SetVisual.3 */,
+ F966BA9408F27A38005CB29B /* spinbox.n */,
+ F966BA9508F27A38005CB29B /* StrictMotif.3 */,
+ F966BA9608F27A38005CB29B /* text.n */,
+ F966BA9708F27A38005CB29B /* TextLayout.3 */,
+ F966BA9808F27A38005CB29B /* tk.n */,
+ F966BA9A08F27A38005CB29B /* Tk_Init.3 */,
+ F966BA9B08F27A38005CB29B /* Tk_Main.3 */,
+ F966BA9C08F27A38005CB29B /* tkerror.n */,
+ F966BA9D08F27A38005CB29B /* TkInitStubs.3 */,
+ F966BA9E08F27A38005CB29B /* tkvars.n */,
+ F966BA9F08F27A38005CB29B /* tkwait.n */,
+ F966BAA008F27A38005CB29B /* toplevel.n */,
+ F968886B0AF788F6000797B5 /* ttk_button.n */,
+ F968886C0AF788F6000797B5 /* ttk_checkbutton.n */,
+ F968886D0AF788F6000797B5 /* ttk_combobox.n */,
+ F968886F0AF788F6000797B5 /* ttk_entry.n */,
+ F96888700AF788F6000797B5 /* ttk_frame.n */,
+ F96888710AF788F6000797B5 /* ttk_Geometry.3 */,
+ F96888720AF788F6000797B5 /* ttk_image.n */,
+ F96888730AF788F6000797B5 /* ttk_intro.n */,
+ F96888740AF788F6000797B5 /* ttk_label.n */,
+ F96888750AF788F6000797B5 /* ttk_labelframe.n */,
+ F96888760AF788F6000797B5 /* ttk_menubutton.n */,
+ F96888770AF788F6000797B5 /* ttk_notebook.n */,
+ F96888780AF788F6000797B5 /* ttk_panedwindow.n */,
+ F96888790AF788F6000797B5 /* ttk_progressbar.n */,
+ F968887A0AF788F6000797B5 /* ttk_radiobutton.n */,
+ F968887B0AF788F6000797B5 /* ttk_scrollbar.n */,
+ F968887C0AF788F6000797B5 /* ttk_separator.n */,
+ F968887D0AF788F6000797B5 /* ttk_sizegrip.n */,
+ F968887E0AF788F6000797B5 /* ttk_style.n */,
+ F968887F0AF788F6000797B5 /* ttk_Theme.3 */,
+ F96888800AF788F6000797B5 /* ttk_treeview.n */,
+ F96888810AF788F6000797B5 /* ttk_widget.n */,
+ F966BAA108F27A38005CB29B /* WindowId.3 */,
+ F966BAA208F27A38005CB29B /* winfo.n */,
+ F966BAA308F27A38005CB29B /* wish.1 */,
+ F966BAA408F27A38005CB29B /* wm.n */,
+ );
+ path = doc;
+ sourceTree = "<group>";
+ };
+ F966BAA508F27A38005CB29B /* generic */ = {
+ isa = PBXGroup;
+ children = (
+ F966BAA608F27A38005CB29B /* default.h */,
+ F966BAA708F27A38005CB29B /* ks_names.h */,
+ F966BAA908F27A39005CB29B /* README */,
+ F966BAAA08F27A39005CB29B /* tk.decls */,
+ F966BAAB08F27A39005CB29B /* tk.h */,
+ F966BAAC08F27A39005CB29B /* tk3d.c */,
+ F966BAAD08F27A39005CB29B /* tk3d.h */,
+ F966BAAE08F27A39005CB29B /* tkArgv.c */,
+ F966BAAF08F27A39005CB29B /* tkAtom.c */,
+ F966BAB008F27A39005CB29B /* tkBind.c */,
+ F966BAB108F27A39005CB29B /* tkBitmap.c */,
+ F9152B080EAF8A5000CD5C7B /* tkBusy.c */,
+ F966BAB208F27A39005CB29B /* tkButton.c */,
+ F966BAB308F27A39005CB29B /* tkButton.h */,
+ F966BAB408F27A39005CB29B /* tkCanvArc.c */,
+ F966BAB508F27A39005CB29B /* tkCanvas.c */,
+ F966BAB608F27A39005CB29B /* tkCanvas.h */,
+ F966BAB708F27A39005CB29B /* tkCanvBmap.c */,
+ F966BAB808F27A39005CB29B /* tkCanvImg.c */,
+ F966BAB908F27A39005CB29B /* tkCanvLine.c */,
+ F966BABA08F27A39005CB29B /* tkCanvPoly.c */,
+ F966BABB08F27A39005CB29B /* tkCanvPs.c */,
+ F966BABD08F27A39005CB29B /* tkCanvText.c */,
+ F966BABE08F27A39005CB29B /* tkCanvUtil.c */,
+ F966BABF08F27A39005CB29B /* tkCanvWind.c */,
+ F966BAC008F27A39005CB29B /* tkClipboard.c */,
+ F966BAC108F27A39005CB29B /* tkCmds.c */,
+ F966BAC208F27A39005CB29B /* tkColor.c */,
+ F966BAC308F27A39005CB29B /* tkColor.h */,
+ F966BAC408F27A39005CB29B /* tkConfig.c */,
+ F966BAC508F27A39005CB29B /* tkConsole.c */,
+ F966BAC608F27A39005CB29B /* tkCursor.c */,
+ F966BAC708F27A39005CB29B /* tkDecls.h */,
+ F966BAC808F27A39005CB29B /* tkEntry.c */,
+ F966BAC908F27A39005CB29B /* tkEntry.h */,
+ F966BACA08F27A39005CB29B /* tkError.c */,
+ F966BACB08F27A39005CB29B /* tkEvent.c */,
+ F966BACC08F27A39005CB29B /* tkFileFilter.c */,
+ F966BACD08F27A39005CB29B /* tkFileFilter.h */,
+ F966BACE08F27A39005CB29B /* tkFocus.c */,
+ F966BACF08F27A39005CB29B /* tkFont.c */,
+ F966BAD008F27A39005CB29B /* tkFont.h */,
+ F966BAD108F27A39005CB29B /* tkFrame.c */,
+ F966BAD208F27A39005CB29B /* tkGC.c */,
+ F966BAD308F27A39005CB29B /* tkGeometry.c */,
+ F966BAD408F27A39005CB29B /* tkGet.c */,
+ F966BAD508F27A39005CB29B /* tkGrab.c */,
+ F966BAD608F27A39005CB29B /* tkGrid.c */,
+ F966BAD708F27A39005CB29B /* tkImage.c */,
+ F966BAD808F27A39005CB29B /* tkImgBmap.c */,
+ F966BAD908F27A39005CB29B /* tkImgGIF.c */,
+ F92EE8BE0E62F846001A6E80 /* tkImgPhInstance.c */,
+ F966BADA08F27A39005CB29B /* tkImgPhoto.c */,
+ F9DD99BC0F07DF850018B2E4 /* tkImgPNG.c */,
+ F966BADB08F27A39005CB29B /* tkImgPPM.c */,
+ F966BADC08F27A39005CB29B /* tkImgUtil.c */,
+ F966BADE08F27A39005CB29B /* tkInt.decls */,
+ F966BADF08F27A39005CB29B /* tkInt.h */,
+ F966BAE108F27A39005CB29B /* tkIntDecls.h */,
+ F966BAE208F27A39005CB29B /* tkIntPlatDecls.h */,
+ F966BAE308F27A39005CB29B /* tkIntXlibDecls.h */,
+ F966BAE408F27A39005CB29B /* tkListbox.c */,
+ F966BAE508F27A39005CB29B /* tkMacWinMenu.c */,
+ F966BAE608F27A39005CB29B /* tkMain.c */,
+ F966BAE708F27A39005CB29B /* tkMenu.c */,
+ F966BAE808F27A39005CB29B /* tkMenu.h */,
+ F966BAE908F27A39005CB29B /* tkMenubutton.c */,
+ F966BAEA08F27A39005CB29B /* tkMenubutton.h */,
+ F966BAEB08F27A39005CB29B /* tkMenuDraw.c */,
+ F966BAEC08F27A39005CB29B /* tkMessage.c */,
+ F966BAED08F27A39005CB29B /* tkObj.c */,
+ F966BAEE08F27A39005CB29B /* tkOldConfig.c */,
+ F966BAEF08F27A39005CB29B /* tkOption.c */,
+ F966BAF008F27A39005CB29B /* tkPack.c */,
+ F966BAF108F27A39005CB29B /* tkPanedWindow.c */,
+ F966BAF208F27A39005CB29B /* tkPlace.c */,
+ F966BAF308F27A39005CB29B /* tkPlatDecls.h */,
+ F966BAF408F27A39005CB29B /* tkPointer.c */,
+ F966BAF508F27A39005CB29B /* tkPort.h */,
+ F966BAF608F27A39005CB29B /* tkRectOval.c */,
+ F966BAF708F27A39005CB29B /* tkScale.c */,
+ F966BAF808F27A39005CB29B /* tkScale.h */,
+ F966BAF908F27A39005CB29B /* tkScrollbar.c */,
+ F966BAFA08F27A39005CB29B /* tkScrollbar.h */,
+ F966BAFB08F27A39005CB29B /* tkSelect.c */,
+ F966BAFC08F27A39005CB29B /* tkSelect.h */,
+ F966BAFD08F27A39005CB29B /* tkSquare.c */,
+ F966BAFE08F27A39005CB29B /* tkOldTest.c */,
+ F966BAFF08F27A39005CB29B /* tkStubInit.c */,
+ F966BB0008F27A39005CB29B /* tkStubLib.c */,
+ F966BB0108F27A39005CB29B /* tkStyle.c */,
+ F966BB0208F27A39005CB29B /* tkTest.c */,
+ F966BB0308F27A39005CB29B /* tkText.c */,
+ F966BB0408F27A39005CB29B /* tkText.h */,
+ F966BB0508F27A39005CB29B /* tkTextBTree.c */,
+ F966BB0608F27A39005CB29B /* tkTextDisp.c */,
+ F966BB0808F27A39005CB29B /* tkTextImage.c */,
+ F966BB0908F27A39005CB29B /* tkTextIndex.c */,
+ F966BB0A08F27A39005CB29B /* tkTextMark.c */,
+ F966BB0B08F27A39005CB29B /* tkTextTag.c */,
+ F966BB0C08F27A39005CB29B /* tkTextWind.c */,
+ F966BB0D08F27A39005CB29B /* tkTrig.c */,
+ F966BB0E08F27A39005CB29B /* tkUndo.c */,
+ F966BB0F08F27A39005CB29B /* tkUndo.h */,
+ F966BB1008F27A39005CB29B /* tkUtil.c */,
+ F966BB1108F27A39005CB29B /* tkVisual.c */,
+ F966BB1208F27A39005CB29B /* tkWindow.c */,
+ F96887DF0AF786D5000797B5 /* ttk */,
+ );
+ path = generic;
+ sourceTree = "<group>";
+ };
+ F966BB1308F27A39005CB29B /* library */ = {
+ isa = PBXGroup;
+ children = (
+ F966BB1408F27A39005CB29B /* bgerror.tcl */,
+ F966BB1508F27A39005CB29B /* button.tcl */,
+ F966BB1608F27A39005CB29B /* choosedir.tcl */,
+ F966BB1708F27A39005CB29B /* clrpick.tcl */,
+ F966BB1808F27A39005CB29B /* comdlg.tcl */,
+ F966BB1908F27A39005CB29B /* console.tcl */,
+ F966BB1A08F27A39005CB29B /* demos */,
+ F966BB6208F27A3A005CB29B /* dialog.tcl */,
+ F966BB6308F27A3A005CB29B /* entry.tcl */,
+ F966BB6408F27A3A005CB29B /* focus.tcl */,
+ F99388380EE0114B0065FE6B /* fontchooser.tcl */,
+ F974D57C0FBE7EFF00BF728B /* iconlist.tcl */,
+ F974D57D0FBE7EFF00BF728B /* icons.tcl */,
+ F966BB7308F27A3A005CB29B /* listbox.tcl */,
+ F966BB7408F27A3A005CB29B /* menu.tcl */,
+ F966BB7508F27A3A005CB29B /* mkpsenc.tcl */,
+ F966BB7608F27A3A005CB29B /* msgbox.tcl */,
+ F966BB8608F27A3A005CB29B /* obsolete.tcl */,
+ F966BB8708F27A3A005CB29B /* optMenu.tcl */,
+ F966BB8808F27A3A005CB29B /* palette.tcl */,
+ F966BB8908F27A3B005CB29B /* panedwindow.tcl */,
+ F966BB8B08F27A3B005CB29B /* safetk.tcl */,
+ F966BB8C08F27A3B005CB29B /* scale.tcl */,
+ F966BB8D08F27A3B005CB29B /* scrlbar.tcl */,
+ F966BB8E08F27A3B005CB29B /* spinbox.tcl */,
+ F966BB8F08F27A3B005CB29B /* tclIndex */,
+ F966BB9008F27A3B005CB29B /* tearoff.tcl */,
+ F966BB9108F27A3B005CB29B /* text.tcl */,
+ F966BB9208F27A3B005CB29B /* tk.tcl */,
+ F966BB9308F27A3B005CB29B /* tkfbox.tcl */,
+ F96888360AF787B3000797B5 /* ttk */,
+ F966BB9408F27A3B005CB29B /* unsupported.tcl */,
+ F966BB9508F27A3B005CB29B /* xmfbox.tcl */,
+ );
+ path = library;
+ sourceTree = "<group>";
+ };
+ F966BB1A08F27A39005CB29B /* demos */ = {
+ isa = PBXGroup;
+ children = (
+ F966BB1B08F27A39005CB29B /* anilabel.tcl */,
+ F966BB1C08F27A39005CB29B /* aniwave.tcl */,
+ F966BB1D08F27A39005CB29B /* arrow.tcl */,
+ F966BB1E08F27A39005CB29B /* bind.tcl */,
+ F966BB1F08F27A39005CB29B /* bitmap.tcl */,
+ F966BB2008F27A39005CB29B /* browse */,
+ F966BB2108F27A39005CB29B /* button.tcl */,
+ F966BB2208F27A39005CB29B /* check.tcl */,
+ F966BB2308F27A39005CB29B /* clrpick.tcl */,
+ F966BB2408F27A39005CB29B /* colors.tcl */,
+ F936FCDB0CCD984600716967 /* combo.tcl */,
+ F966BB2508F27A39005CB29B /* cscroll.tcl */,
+ F966BB2608F27A39005CB29B /* ctext.tcl */,
+ F966BB2708F27A39005CB29B /* dialog1.tcl */,
+ F966BB2808F27A39005CB29B /* dialog2.tcl */,
+ F966BB2A08F27A39005CB29B /* entry1.tcl */,
+ F966BB2B08F27A39005CB29B /* entry2.tcl */,
+ F966BB2C08F27A39005CB29B /* entry3.tcl */,
+ F966BB2D08F27A39005CB29B /* filebox.tcl */,
+ F966BB2E08F27A39005CB29B /* floor.tcl */,
+ F91543270EF201A90032D1E8 /* fontchoose.tcl */,
+ F966BB2F08F27A39005CB29B /* form.tcl */,
+ F966BB3008F27A39005CB29B /* goldberg.tcl */,
+ F966BB3108F27A39005CB29B /* hello */,
+ F966BB3208F27A39005CB29B /* hscale.tcl */,
+ F966BB3308F27A39005CB29B /* icon.tcl */,
+ F966BB3408F27A39005CB29B /* image1.tcl */,
+ F966BB3508F27A39005CB29B /* image2.tcl */,
+ F966BB4208F27A3A005CB29B /* items.tcl */,
+ F966BB4308F27A3A005CB29B /* ixset */,
+ F92240290D7C620F005EC715 /* knightstour.tcl */,
+ F966BB4408F27A3A005CB29B /* label.tcl */,
+ F966BB4508F27A3A005CB29B /* labelframe.tcl */,
+ F9D1360A0CDC252C00DBE0B5 /* mclist.tcl */,
+ F966BB4608F27A3A005CB29B /* menu.tcl */,
+ F966BB4708F27A3A005CB29B /* menubu.tcl */,
+ F966BB4808F27A3A005CB29B /* msgbox.tcl */,
+ F966BB4A08F27A3A005CB29B /* paned1.tcl */,
+ F966BB4B08F27A3A005CB29B /* paned2.tcl */,
+ F966BB4C08F27A3A005CB29B /* pendulum.tcl */,
+ F966BB4D08F27A3A005CB29B /* plot.tcl */,
+ F966BB4E08F27A3A005CB29B /* puzzle.tcl */,
+ F966BB4F08F27A3A005CB29B /* radio.tcl */,
+ F966BB5008F27A3A005CB29B /* README */,
+ F966BB5108F27A3A005CB29B /* rmt */,
+ F966BB5208F27A3A005CB29B /* rolodex */,
+ F966BB5308F27A3A005CB29B /* ruler.tcl */,
+ F966BB5408F27A3A005CB29B /* sayings.tcl */,
+ F966BB5508F27A3A005CB29B /* search.tcl */,
+ F966BB5608F27A3A005CB29B /* spin.tcl */,
+ F966BB5708F27A3A005CB29B /* square */,
+ F966BB5808F27A3A005CB29B /* states.tcl */,
+ F966BB5908F27A3A005CB29B /* style.tcl */,
+ F966BB5A08F27A3A005CB29B /* tclIndex */,
+ F966BB5B08F27A3A005CB29B /* tcolor */,
+ F966BB5C08F27A3A005CB29B /* text.tcl */,
+ F9099B8A0CC67D30005A9580 /* textpeer.tcl */,
+ F966BB5D08F27A3A005CB29B /* timer */,
+ F936FCD90CCD984600716967 /* toolbar.tcl */,
+ F936FCD80CCD984600716967 /* tree.tcl */,
+ F9099B8B0CC67D3E005A9580 /* ttkbut.tcl */,
+ F9F4EFDD0CC7B3CB00378A27 /* ttkmenu.tcl */,
+ F936FCDA0CCD984600716967 /* ttknote.tcl */,
+ F9F4EFDC0CC7B3CA00378A27 /* ttkpane.tcl */,
+ F936FCD70CCD984500716967 /* ttkprogress.tcl */,
+ F966BB5E08F27A3A005CB29B /* twind.tcl */,
+ F966BB5F08F27A3A005CB29B /* unicodeout.tcl */,
+ F966BB6008F27A3A005CB29B /* vscale.tcl */,
+ F966BB6108F27A3A005CB29B /* widget */,
+ );
+ path = demos;
+ sourceTree = "<group>";
+ };
+ F966BB9708F27A3B005CB29B /* macosx */ = {
+ isa = PBXGroup;
+ children = (
+ F966BBBA08F27A3B005CB29B /* configure.ac */,
+ F966BBBB08F27A3B005CB29B /* GNUmakefile */,
+ F966BBBE08F27A3B005CB29B /* README */,
+ F966BBC008F27A3B005CB29B /* Tk-Info.plist.in */,
+ F966BBC208F27A3B005CB29B /* tkMacOSX.h */,
+ F966BBC508F27A3B005CB29B /* tkMacOSXBitmap.c */,
+ F966BBC608F27A3B005CB29B /* tkMacOSXButton.c */,
+ F966BBC808F27A3B005CB29B /* tkMacOSXClipboard.c */,
+ F966BBC908F27A3B005CB29B /* tkMacOSXColor.c */,
+ F966BBCA08F27A3B005CB29B /* tkMacOSXConfig.c */,
+ F966BBCB08F27A3B005CB29B /* tkMacOSXCursor.c */,
+ F966BBCC08F27A3B005CB29B /* tkMacOSXCursors.h */,
+ F966BBCD08F27A3B005CB29B /* tkMacOSXDebug.c */,
+ F966BBCE08F27A3B005CB29B /* tkMacOSXDebug.h */,
+ F966BBCF08F27A3B005CB29B /* tkMacOSXDefault.h */,
+ F966BBD008F27A3B005CB29B /* tkMacOSXDialog.c */,
+ F966BBD108F27A3B005CB29B /* tkMacOSXDraw.c */,
+ F966BBD208F27A3B005CB29B /* tkMacOSXEmbed.c */,
+ F966BBD308F27A3B005CB29B /* tkMacOSXEntry.c */,
+ F966BBD408F27A3B005CB29B /* tkMacOSXEvent.c */,
+ F966BBD508F27A3B005CB29B /* tkMacOSXEvent.h */,
+ F966BBD608F27A3B005CB29B /* tkMacOSXFont.c */,
+ F93E5EFD09CF8711008FA367 /* tkMacOSXFont.h */,
+ F966BBD708F27A3B005CB29B /* tkMacOSXHLEvents.c */,
+ F966BBD808F27A3B005CB29B /* tkMacOSXInit.c */,
+ F966BBDA08F27A3B005CB29B /* tkMacOSXInt.h */,
+ F966BBDB08F27A3B005CB29B /* tkMacOSXKeyboard.c */,
+ F966BBDC08F27A3B005CB29B /* tkMacOSXKeyEvent.c */,
+ F966BBDD08F27A3B005CB29B /* tkMacOSXMenu.c */,
+ F966BBE008F27A3B005CB29B /* tkMacOSXMenubutton.c */,
+ F966BBE108F27A3B005CB29B /* tkMacOSXMenus.c */,
+ F966BBE208F27A3B005CB29B /* tkMacOSXMouseEvent.c */,
+ F966BBE308F27A3B005CB29B /* tkMacOSXNotify.c */,
+ F966BBEA08F27A3C005CB29B /* tkMacOSXPort.h */,
+ F976F6A70C325FB6005066D9 /* tkMacOSXPrivate.h */,
+ F966BBEB08F27A3C005CB29B /* tkMacOSXRegion.c */,
+ F966BBEC08F27A3C005CB29B /* tkMacOSXScale.c */,
+ F966BBED08F27A3C005CB29B /* tkMacOSXScrlbr.c */,
+ F966BBEE08F27A3C005CB29B /* tkMacOSXSend.c */,
+ F966BBEF08F27A3C005CB29B /* tkMacOSXSubwindows.c */,
+ F966BBF008F27A3C005CB29B /* tkMacOSXTest.c */,
+ F966BBF108F27A3C005CB29B /* tkMacOSXWindowEvent.c */,
+ F966BBF208F27A3C005CB29B /* tkMacOSXWm.c */,
+ F966BBF308F27A3C005CB29B /* tkMacOSXWm.h */,
+ F966BBF408F27A3C005CB29B /* tkMacOSXXCursors.h */,
+ F966BBF508F27A3C005CB29B /* tkMacOSXXStubs.c */,
+ F96888840AF78938000797B5 /* ttkMacOSXTheme.c */,
+ F95D8D4B0F1715610006B020 /* Tk.icns */,
+ F95D8D4C0F1715610006B020 /* Tk.tiff */,
+ F966BBF708F27A3C005CB29B /* Wish-Info.plist.in */,
+ F97590AE1039A96200558A9A /* Wish.sdef */,
+ F97AE7F10B65C1E900310EA2 /* Tk-Common.xcconfig */,
+ F97AE8330B65C87F00310EA2 /* Tk-Debug.xcconfig */,
+ F97AE82B0B65C69B00310EA2 /* Tk-Release.xcconfig */,
+ );
+ path = macosx;
+ sourceTree = "<group>";
+ };
+ F966BC0408F27A3C005CB29B /* tests */ = {
+ isa = PBXGroup;
+ children = (
+ F966BC0508F27A3C005CB29B /* all.tcl */,
+ F966BC0608F27A3C005CB29B /* arc.tcl */,
+ F966BC0708F27A3C005CB29B /* bell.test */,
+ F966BC0808F27A3C005CB29B /* bevel.tcl */,
+ F966BC0908F27A3C005CB29B /* bgerror.test */,
+ F966BC0A08F27A3C005CB29B /* bind.test */,
+ F966BC0B08F27A3C005CB29B /* bitmap.test */,
+ F966BC0C08F27A3C005CB29B /* border.test */,
+ F966BC0D08F27A3C005CB29B /* bugs.tcl */,
+ F966BC0E08F27A3C005CB29B /* butGeom.tcl */,
+ F966BC0F08F27A3C005CB29B /* butGeom2.tcl */,
+ F966BC1008F27A3C005CB29B /* button.test */,
+ F966BC1108F27A3C005CB29B /* canvas.test */,
+ F966BC1208F27A3C005CB29B /* canvImg.test */,
+ F966BC1308F27A3C005CB29B /* canvPs.test */,
+ F966BC1408F27A3C005CB29B /* canvPsArc.tcl */,
+ F966BC1508F27A3C005CB29B /* canvPsBmap.tcl */,
+ F966BC1608F27A3C005CB29B /* canvPsGrph.tcl */,
+ F966BC1708F27A3C005CB29B /* canvPsImg.tcl */,
+ F966BC1808F27A3C005CB29B /* canvPsText.tcl */,
+ F966BC1908F27A3C005CB29B /* canvRect.test */,
+ F966BC1A08F27A3C005CB29B /* canvText.test */,
+ F966BC1B08F27A3C005CB29B /* canvWind.test */,
+ F966BC1C08F27A3C005CB29B /* choosedir.test */,
+ F966BC1D08F27A3C005CB29B /* clipboard.test */,
+ F966BC1E08F27A3C005CB29B /* clrpick.test */,
+ F966BC1F08F27A3C005CB29B /* cmap.tcl */,
+ F966BC2008F27A3C005CB29B /* cmds.test */,
+ F966BC2108F27A3C005CB29B /* color.test */,
+ F966BC2208F27A3C005CB29B /* config.test */,
+ F966BC2308F27A3C005CB29B /* constraints.tcl */,
+ F966BC2408F27A3C005CB29B /* cursor.test */,
+ F966BC2508F27A3C005CB29B /* dialog.test */,
+ F966BC2608F27A3C005CB29B /* embed.test */,
+ F966BC2708F27A3C005CB29B /* entry.test */,
+ F966BC2808F27A3C005CB29B /* event.test */,
+ F966BC2908F27A3C005CB29B /* filebox.test */,
+ F966BC2A08F27A3C005CB29B /* focus.test */,
+ F966BC2B08F27A3C005CB29B /* focusTcl.test */,
+ F966BC2C08F27A3C005CB29B /* font.test */,
+ F99388950EE02D980065FE6B /* fontchooser.test */,
+ F966BC2D08F27A3C005CB29B /* frame.test */,
+ F966BC2E08F27A3C005CB29B /* geometry.test */,
+ F966BC2F08F27A3C005CB29B /* get.test */,
+ F966BC3008F27A3C005CB29B /* grab.test */,
+ F966BC3108F27A3C005CB29B /* grid.test */,
+ F966BC3308F27A3C005CB29B /* image.test */,
+ F966BC3408F27A3C005CB29B /* imgBmap.test */,
+ F966BC3508F27A3C005CB29B /* imgPhoto.test */,
+ F9DD99BF0F07DFCD0018B2E4 /* imgPNG.test */,
+ F966BC3608F27A3C005CB29B /* imgPPM.test */,
+ F966BC3708F27A3C005CB29B /* listbox.test */,
+ F966BC3808F27A3C005CB29B /* main.test */,
+ F966BC3908F27A3C005CB29B /* menu.test */,
+ F966BC3A08F27A3C005CB29B /* menubut.test */,
+ F966BC3B08F27A3C005CB29B /* menuDraw.test */,
+ F966BC3C08F27A3C005CB29B /* message.test */,
+ F966BC3D08F27A3C005CB29B /* msgbox.test */,
+ F966BC3E08F27A3C005CB29B /* obj.test */,
+ F966BC3F08F27A3C005CB29B /* oldpack.test */,
+ F966BC4008F27A3C005CB29B /* option.file1 */,
+ F966BC4108F27A3C005CB29B /* option.file2 */,
+ F966BC4208F27A3C005CB29B /* option.test */,
+ F966BC4308F27A3C005CB29B /* pack.test */,
+ F966BC4408F27A3C005CB29B /* panedwindow.test */,
+ F966BC4508F27A3D005CB29B /* place.test */,
+ F966BC4608F27A3D005CB29B /* raise.test */,
+ F966BC4708F27A3D005CB29B /* README */,
+ F966BC4808F27A3D005CB29B /* safe.test */,
+ F966BC4908F27A3D005CB29B /* scale.test */,
+ F966BC4A08F27A3D005CB29B /* scrollbar.test */,
+ F966BC4B08F27A3D005CB29B /* select.test */,
+ F966BC4C08F27A3D005CB29B /* send.test */,
+ F966BC4D08F27A3D005CB29B /* spinbox.test */,
+ F966BC4E08F27A3D005CB29B /* text.test */,
+ F966BC4F08F27A3D005CB29B /* textBTree.test */,
+ F966BC5008F27A3D005CB29B /* textDisp.test */,
+ F966BC5108F27A3D005CB29B /* textImage.test */,
+ F966BC5208F27A3D005CB29B /* textIndex.test */,
+ F966BC5308F27A3D005CB29B /* textMark.test */,
+ F966BC5408F27A3D005CB29B /* textTag.test */,
+ F966BC5508F27A3D005CB29B /* textWind.test */,
+ F966BC5608F27A3D005CB29B /* tk.test */,
+ F96888530AF7880C000797B5 /* ttk */,
+ F966BC5708F27A3D005CB29B /* unixButton.test */,
+ F966BC5808F27A3D005CB29B /* unixEmbed.test */,
+ F966BC5908F27A3D005CB29B /* unixFont.test */,
+ F966BC5A08F27A3D005CB29B /* unixMenu.test */,
+ F966BC5B08F27A3D005CB29B /* unixSelect.test */,
+ F966BC5C08F27A3D005CB29B /* unixWm.test */,
+ F966BC5D08F27A3D005CB29B /* util.test */,
+ F966BC5E08F27A3D005CB29B /* visual.test */,
+ F966BC5F08F27A3D005CB29B /* visual_bb.test */,
+ F966BC6008F27A3D005CB29B /* winButton.test */,
+ F966BC6108F27A3D005CB29B /* winClipboard.test */,
+ F966BC6208F27A3D005CB29B /* winDialog.test */,
+ F966BC6308F27A3D005CB29B /* window.test */,
+ F966BC6408F27A3D005CB29B /* winfo.test */,
+ F966BC6508F27A3D005CB29B /* winFont.test */,
+ F966BC6608F27A3D005CB29B /* winMenu.test */,
+ F966BC6708F27A3D005CB29B /* winSend.test */,
+ F966BC6808F27A3D005CB29B /* winWm.test */,
+ F966BC6908F27A3D005CB29B /* wm.test */,
+ F966BC6A08F27A3D005CB29B /* xmfbox.test */,
+ );
+ path = tests;
+ sourceTree = "<group>";
+ };
+ F966BC6B08F27A3D005CB29B /* unix */ = {
+ isa = PBXGroup;
+ children = (
+ F966BC6C08F27A3D005CB29B /* aclocal.m4 */,
+ F966BC6D08F27A3D005CB29B /* configure */,
+ F966BC6E08F27A3D005CB29B /* configure.in */,
+ F966BC6F08F27A3D005CB29B /* install-sh */,
+ F966BC7008F27A3D005CB29B /* installManPage */,
+ F966BC7108F27A3D005CB29B /* Makefile.in */,
+ F966BC7208F27A3D005CB29B /* README */,
+ F966BC7308F27A3D005CB29B /* tcl.m4 */,
+ F974D57B0FBE7EC000BF728B /* tk.pc.in */,
+ F966BC7408F27A3D005CB29B /* tk.spec */,
+ F966BC7508F27A3D005CB29B /* tkAppInit.c */,
+ F966BC7608F27A3D005CB29B /* tkConfig.h.in */,
+ F966BC7708F27A3D005CB29B /* tkConfig.sh.in */,
+ F966BC7808F27A3D005CB29B /* tkUnix.c */,
+ F966BC7908F27A3D005CB29B /* tkUnix3d.c */,
+ F966BC7A08F27A3D005CB29B /* tkUnixButton.c */,
+ F966BC7B08F27A3D005CB29B /* tkUnixColor.c */,
+ F966BC7C08F27A3D005CB29B /* tkUnixConfig.c */,
+ F966BC7D08F27A3D005CB29B /* tkUnixCursor.c */,
+ F966BC7E08F27A3D005CB29B /* tkUnixDefault.h */,
+ F966BC7F08F27A3D005CB29B /* tkUnixDialog.c */,
+ F966BC8008F27A3D005CB29B /* tkUnixDraw.c */,
+ F966BC8108F27A3D005CB29B /* tkUnixEmbed.c */,
+ F966BC8208F27A3D005CB29B /* tkUnixEvent.c */,
+ F966BC8308F27A3D005CB29B /* tkUnixFocus.c */,
+ F966BC8408F27A3D005CB29B /* tkUnixFont.c */,
+ F966BC8508F27A3D005CB29B /* tkUnixInit.c */,
+ F966BC8608F27A3D005CB29B /* tkUnixInt.h */,
+ F966BC8708F27A3D005CB29B /* tkUnixKey.c */,
+ F966BC8808F27A3D005CB29B /* tkUnixMenu.c */,
+ F966BC8908F27A3D005CB29B /* tkUnixMenubu.c */,
+ F966BC8A08F27A3D005CB29B /* tkUnixPort.h */,
+ F966BC8B08F27A3D005CB29B /* tkUnixRFont.c */,
+ F966BC8C08F27A3D005CB29B /* tkUnixScale.c */,
+ F966BC8D08F27A3D005CB29B /* tkUnixScrlbr.c */,
+ F966BC8E08F27A3D005CB29B /* tkUnixSelect.c */,
+ F966BC8F08F27A3D005CB29B /* tkUnixSend.c */,
+ F966BC9008F27A3D005CB29B /* tkUnixWm.c */,
+ F966BC9108F27A3D005CB29B /* tkUnixXId.c */,
+ );
+ path = unix;
+ sourceTree = "<group>";
+ };
+ F966BC9208F27A3D005CB29B /* win */ = {
+ isa = PBXGroup;
+ children = (
+ F966BC9408F27A3D005CB29B /* aclocal.m4 */,
+ F966BC9508F27A3D005CB29B /* buildall.vc.bat */,
+ F966BC9608F27A3E005CB29B /* configure */,
+ F966BC9708F27A3E005CB29B /* configure.in */,
+ F966BC9908F27A3E005CB29B /* Makefile.in */,
+ F966BC9A08F27A3E005CB29B /* makefile.vc */,
+ F966BC9B08F27A3E005CB29B /* mkd.bat */,
+ F966BC9C08F27A3E005CB29B /* nmakehlp.c */,
+ F966BC9D08F27A3E005CB29B /* rc */,
+ F966BCF308F27A3E005CB29B /* README */,
+ F966BCF408F27A3E005CB29B /* rmd.bat */,
+ F966BCF508F27A3F005CB29B /* rules.vc */,
+ F966BCF608F27A3F005CB29B /* stubs.c */,
+ F966BCF708F27A3F005CB29B /* tcl.m4 */,
+ F966BCF808F27A3F005CB29B /* tkConfig.sh.in */,
+ F966BCF908F27A3F005CB29B /* tkWin.h */,
+ F966BCFA08F27A3F005CB29B /* tkWin32Dll.c */,
+ F966BCFB08F27A3F005CB29B /* tkWin3d.c */,
+ F966BCFC08F27A3F005CB29B /* tkWinButton.c */,
+ F966BCFD08F27A3F005CB29B /* tkWinClipboard.c */,
+ F966BCFE08F27A3F005CB29B /* tkWinColor.c */,
+ F966BCFF08F27A3F005CB29B /* tkWinConfig.c */,
+ F966BD0008F27A3F005CB29B /* tkWinCursor.c */,
+ F966BD0108F27A3F005CB29B /* tkWinDefault.h */,
+ F966BD0208F27A3F005CB29B /* tkWinDialog.c */,
+ F966BD0308F27A3F005CB29B /* tkWinDraw.c */,
+ F966BD0408F27A3F005CB29B /* tkWinEmbed.c */,
+ F966BD0508F27A3F005CB29B /* tkWinFont.c */,
+ F966BD0708F27A3F005CB29B /* tkWinImage.c */,
+ F966BD0808F27A3F005CB29B /* tkWinInit.c */,
+ F966BD0908F27A3F005CB29B /* tkWinInt.h */,
+ F966BD0A08F27A3F005CB29B /* tkWinKey.c */,
+ F966BD0B08F27A3F005CB29B /* tkWinMenu.c */,
+ F966BD0C08F27A3F005CB29B /* tkWinPixmap.c */,
+ F966BD0D08F27A3F005CB29B /* tkWinPointer.c */,
+ F966BD0E08F27A3F005CB29B /* tkWinPort.h */,
+ F966BD0F08F27A3F005CB29B /* tkWinRegion.c */,
+ F966BD1008F27A3F005CB29B /* tkWinScrlbr.c */,
+ F966BD1108F27A3F005CB29B /* tkWinSend.c */,
+ F966BD1208F27A3F005CB29B /* tkWinSendCom.c */,
+ F966BD1308F27A3F005CB29B /* tkWinSendCom.h */,
+ F966BD1408F27A3F005CB29B /* tkWinTest.c */,
+ F966BD1508F27A3F005CB29B /* tkWinWindow.c */,
+ F966BD1608F27A3F005CB29B /* tkWinWm.c */,
+ F966BD1708F27A3F005CB29B /* tkWinX.c */,
+ F96888860AF78953000797B5 /* ttkWinMonitor.c */,
+ F96888870AF78953000797B5 /* ttkWinTheme.c */,
+ F96888880AF78953000797B5 /* ttkWinXPTheme.c */,
+ F966BD1808F27A3F005CB29B /* winMain.c */,
+ );
+ path = win;
+ sourceTree = "<group>";
+ };
+ F966BC9D08F27A3E005CB29B /* rc */ = {
+ isa = PBXGroup;
+ children = (
+ F966BCEE08F27A3E005CB29B /* tk.rc */,
+ F966BCEF08F27A3E005CB29B /* tk_base.rc */,
+ F966BCF208F27A3E005CB29B /* wish.rc */,
+ );
+ path = rc;
+ sourceTree = "<group>";
+ };
+ F966BD1908F27A3F005CB29B /* xlib */ = {
+ isa = PBXGroup;
+ children = (
+ F966BD1A08F27A3F005CB29B /* X11 */,
+ F966BD2308F27A3F005CB29B /* xbytes.h */,
+ F966BD2408F27A3F005CB29B /* xcolors.c */,
+ F966BD2508F27A3F005CB29B /* xdraw.c */,
+ F966BD2608F27A3F005CB29B /* xgc.c */,
+ F966BD2708F27A3F005CB29B /* ximage.c */,
+ F966BD2808F27A3F005CB29B /* xutil.c */,
+ );
+ path = xlib;
+ sourceTree = "<group>";
+ };
+ F966BD1A08F27A3F005CB29B /* X11 */ = {
+ isa = PBXGroup;
+ children = (
+ F966BD1B08F27A3F005CB29B /* cursorfont.h */,
+ F966BD1C08F27A3F005CB29B /* keysym.h */,
+ F966BD1D08F27A3F005CB29B /* keysymdef.h */,
+ F966BD1E08F27A3F005CB29B /* X.h */,
+ F966BD1F08F27A3F005CB29B /* Xatom.h */,
+ F966BD2008F27A3F005CB29B /* Xfuncproto.h */,
+ F966BD2108F27A3F005CB29B /* Xlib.h */,
+ F966BD2208F27A3F005CB29B /* Xutil.h */,
+ );
+ path = X11;
+ sourceTree = "<group>";
+ };
+ F966C06F08F281DC005CB29B /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ F9C9CBFF0E84059800E00935 /* ApplicationServices.framework */,
+ F966C07408F2820D005CB29B /* CoreFoundation.framework */,
+ F96437E60EF0D652003F468E /* libz.dylib */,
+ F966C07608F2821B005CB29B /* Carbon.framework */,
+ F94523A10E6FC2AC00C1D987 /* Cocoa.framework */,
+ F966C07808F28233005CB29B /* IOKit.framework */,
+ F9FD32140CC1AF170073837D /* libX11.dylib */,
+ F9FD32150CC1AF170073837D /* libXext.dylib */,
+ F9FD32160CC1AF170073837D /* libXss.dylib */,
+ F9FD349A0CC1BB0D0073837D /* libXft.dylib */,
+ F9FD34990CC1BB0D0073837D /* libfreetype.dylib */,
+ F9FD34C30CC1BBD70073837D /* libfontconfig.dylib */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ F96887DF0AF786D5000797B5 /* ttk */ = {
+ isa = PBXGroup;
+ children = (
+ F96887E00AF786D5000797B5 /* ttk.decls */,
+ F96887E10AF786D5000797B5 /* ttkBlink.c */,
+ F96887E20AF786D5000797B5 /* ttkButton.c */,
+ F96887E30AF786D5000797B5 /* ttkCache.c */,
+ F96887E40AF786D5000797B5 /* ttkClamTheme.c */,
+ F96887E50AF786D5000797B5 /* ttkClassicTheme.c */,
+ F96887E60AF786D5000797B5 /* ttkDecls.h */,
+ F96887E70AF786D5000797B5 /* ttkDefaultTheme.c */,
+ F96887E80AF786D5000797B5 /* ttkElements.c */,
+ F96887E90AF786D5000797B5 /* ttkEntry.c */,
+ F96887EA0AF786D5000797B5 /* ttkFrame.c */,
+ F96887EB0AF786D5000797B5 /* ttkImage.c */,
+ F96887EC0AF786D5000797B5 /* ttkInit.c */,
+ F96887ED0AF786D5000797B5 /* ttkLabel.c */,
+ F96887EE0AF786D5000797B5 /* ttkLayout.c */,
+ F96887EF0AF786D5000797B5 /* ttkManager.c */,
+ F96887F00AF786D5000797B5 /* ttkManager.h */,
+ F96887F10AF786D5000797B5 /* ttkNotebook.c */,
+ F96887F20AF786D5000797B5 /* ttkPanedwindow.c */,
+ F96887F30AF786D5000797B5 /* ttkProgress.c */,
+ F96887F40AF786D5000797B5 /* ttkScale.c */,
+ F96887F50AF786D5000797B5 /* ttkScroll.c */,
+ F96887F60AF786D5000797B5 /* ttkScrollbar.c */,
+ F96887F70AF786D5000797B5 /* ttkSeparator.c */,
+ F96887F80AF786D5000797B5 /* ttkSquare.c */,
+ F96887F90AF786D5000797B5 /* ttkState.c */,
+ F96887FA0AF786D5000797B5 /* ttkStubInit.c */,
+ F96887FB0AF786D5000797B5 /* ttkStubLib.c */,
+ F96887FC0AF786D5000797B5 /* ttkTagSet.c */,
+ F96887FD0AF786D5000797B5 /* ttkTheme.c */,
+ F96887FE0AF786D5000797B5 /* ttkTheme.h */,
+ F96887FF0AF786D5000797B5 /* ttkThemeInt.h */,
+ F96888000AF786D5000797B5 /* ttkTrace.c */,
+ F96888010AF786D5000797B5 /* ttkTrack.c */,
+ F96888020AF786D5000797B5 /* ttkTreeview.c */,
+ F96888030AF786D5000797B5 /* ttkWidget.c */,
+ F96888040AF786D5000797B5 /* ttkWidget.h */,
+ );
+ path = ttk;
+ sourceTree = "<group>";
+ };
+ F96888360AF787B3000797B5 /* ttk */ = {
+ isa = PBXGroup;
+ children = (
+ F96888370AF787B3000797B5 /* altTheme.tcl */,
+ F96888380AF787B3000797B5 /* aquaTheme.tcl */,
+ F96888390AF787B3000797B5 /* button.tcl */,
+ F968883A0AF787B3000797B5 /* clamTheme.tcl */,
+ F968883B0AF787B3000797B5 /* classicTheme.tcl */,
+ F968883C0AF787B3000797B5 /* combobox.tcl */,
+ F968883D0AF787B3000797B5 /* cursors.tcl */,
+ F968883E0AF787B3000797B5 /* defaults.tcl */,
+ F96888400AF787B3000797B5 /* entry.tcl */,
+ F96888410AF787B3000797B5 /* fonts.tcl */,
+ F96888440AF787B3000797B5 /* menubutton.tcl */,
+ F96888450AF787B3000797B5 /* notebook.tcl */,
+ F96888460AF787B3000797B5 /* panedwindow.tcl */,
+ F96888470AF787B3000797B5 /* progress.tcl */,
+ F96888480AF787B3000797B5 /* scale.tcl */,
+ F96888490AF787B3000797B5 /* scrollbar.tcl */,
+ F968884A0AF787B3000797B5 /* sizegrip.tcl */,
+ F968884B0AF787B3000797B5 /* treeview.tcl */,
+ F968884C0AF787B3000797B5 /* ttk.tcl */,
+ F968884D0AF787B3000797B5 /* utils.tcl */,
+ F968884E0AF787B3000797B5 /* winTheme.tcl */,
+ F973E5960EE99384001A648E /* vistaTheme.tcl */,
+ F968884F0AF787B3000797B5 /* xpTheme.tcl */,
+ );
+ path = ttk;
+ sourceTree = "<group>";
+ };
+ F96888530AF7880C000797B5 /* ttk */ = {
+ isa = PBXGroup;
+ children = (
+ F96888540AF7880C000797B5 /* all.tcl */,
+ F98383650F0FA43900171CA6 /* checkbutton.test */,
+ F96888560AF7880C000797B5 /* combobox.test */,
+ F96888570AF7880C000797B5 /* entry.test */,
+ F96888580AF7880C000797B5 /* image.test */,
+ F96888590AF7880C000797B5 /* labelframe.test */,
+ F968885A0AF7880C000797B5 /* layout.test */,
+ F968885C0AF7880C000797B5 /* notebook.test */,
+ F968885D0AF7880C000797B5 /* panedwindow.test */,
+ F968885E0AF7880C000797B5 /* progressbar.test */,
+ F98383680F0FA44700171CA6 /* radiobutton.test */,
+ F968885F0AF7880C000797B5 /* scrollbar.test */,
+ F96888600AF7880C000797B5 /* treetags.test */,
+ F96888610AF7880C000797B5 /* treeview.test */,
+ F96888620AF7880C000797B5 /* ttk.test */,
+ F96888630AF7880C000797B5 /* validate.test */,
+ F962F7C60DADC26200648DB8 /* vsapi.test */,
+ );
+ path = ttk;
+ sourceTree = "<group>";
+ };
+ F96D3DF608F27169004A47F5 /* Tcl Sources */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3EC908F272A7004A47F5 /* generic */,
+ F96D432C08F272B4004A47F5 /* macosx */,
+ F96D443E08F272B9004A47F5 /* unix */,
+ F96D425C08F272B2004A47F5 /* libtommath */,
+ F96D446E08F272B9004A47F5 /* win */,
+ F96D3F3808F272A7004A47F5 /* library */,
+ F96D434408F272B5004A47F5 /* tests */,
+ F96D3DFC08F272A4004A47F5 /* doc */,
+ F96D43D008F272B8004A47F5 /* tools */,
+ F9183E690EFC81560030B814 /* pkgs */,
+ F96D3DFA08F272A4004A47F5 /* ChangeLog */,
+ F96D3DFB08F272A4004A47F5 /* changes */,
+ F96D434308F272B5004A47F5 /* README */,
+ F96D432B08F272B4004A47F5 /* license.terms */,
+ );
+ name = "Tcl Sources";
+ sourceTree = TCL_SRCROOT;
+ };
+ F96D3DF708F271BE004A47F5 /* Tk Sources */ = {
+ isa = PBXGroup;
+ children = (
+ F966BAA508F27A38005CB29B /* generic */,
+ F966BB9708F27A3B005CB29B /* macosx */,
+ F966BC6B08F27A3D005CB29B /* unix */,
+ F966BD1908F27A3F005CB29B /* xlib */,
+ F966BA0308F27A37005CB29B /* bitmaps */,
+ F966BC9208F27A3D005CB29B /* win */,
+ F966BB1308F27A39005CB29B /* library */,
+ F966BC0408F27A3C005CB29B /* tests */,
+ F966BA1008F27A37005CB29B /* doc */,
+ F966BA0E08F27A37005CB29B /* ChangeLog */,
+ F966BA0F08F27A37005CB29B /* changes */,
+ F966BC0308F27A3C005CB29B /* README */,
+ F966BB9608F27A3B005CB29B /* license.terms */,
+ );
+ name = "Tk Sources";
+ sourceTree = TK_SRCROOT;
+ };
+ F96D3DFC08F272A4004A47F5 /* doc */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3DFD08F272A4004A47F5 /* Access.3 */,
+ F96D3DFE08F272A4004A47F5 /* AddErrInfo.3 */,
+ F96D3DFF08F272A4004A47F5 /* after.n */,
+ F96D3E0008F272A4004A47F5 /* Alloc.3 */,
+ F96D3E0108F272A4004A47F5 /* AllowExc.3 */,
+ F96D3E0208F272A4004A47F5 /* append.n */,
+ F96D3E0308F272A4004A47F5 /* AppInit.3 */,
+ F96D3E0408F272A5004A47F5 /* array.n */,
+ F96D3E0508F272A5004A47F5 /* AssocData.3 */,
+ F96D3E0608F272A5004A47F5 /* Async.3 */,
+ F96D3E0708F272A5004A47F5 /* BackgdErr.3 */,
+ F96D3E0808F272A5004A47F5 /* Backslash.3 */,
+ F96D3E0908F272A5004A47F5 /* bgerror.n */,
+ F96D3E0A08F272A5004A47F5 /* binary.n */,
+ F96D3E0B08F272A5004A47F5 /* BoolObj.3 */,
+ F96D3E0C08F272A5004A47F5 /* break.n */,
+ F96D3E0D08F272A5004A47F5 /* ByteArrObj.3 */,
+ F96D3E0E08F272A5004A47F5 /* CallDel.3 */,
+ F96D3E0F08F272A5004A47F5 /* case.n */,
+ F96D3E1008F272A5004A47F5 /* catch.n */,
+ F96D3E1108F272A5004A47F5 /* cd.n */,
+ F96D3E1208F272A5004A47F5 /* chan.n */,
+ F96D3E1308F272A5004A47F5 /* ChnlStack.3 */,
+ F93599CF0DF1F87F00E04F67 /* Class.3 */,
+ F93599D00DF1F89E00E04F67 /* class.n */,
+ F96D3E1408F272A5004A47F5 /* clock.n */,
+ F96D3E1508F272A5004A47F5 /* close.n */,
+ F96D3E1608F272A5004A47F5 /* CmdCmplt.3 */,
+ F96D3E1708F272A5004A47F5 /* Concat.3 */,
+ F96D3E1808F272A5004A47F5 /* concat.n */,
+ F96D3E1908F272A5004A47F5 /* continue.n */,
+ F93599D20DF1F8DF00E04F67 /* copy.n */,
+ F974D5720FBE7DC600BF728B /* coroutine.n */,
+ F96D3E1A08F272A5004A47F5 /* CrtChannel.3 */,
+ F96D3E1B08F272A5004A47F5 /* CrtChnlHdlr.3 */,
+ F96D3E1C08F272A5004A47F5 /* CrtCloseHdlr.3 */,
+ F96D3E1D08F272A5004A47F5 /* CrtCommand.3 */,
+ F96D3E1E08F272A5004A47F5 /* CrtFileHdlr.3 */,
+ F96D3E1F08F272A5004A47F5 /* CrtInterp.3 */,
+ F96D3E2008F272A5004A47F5 /* CrtMathFnc.3 */,
+ F96D3E2108F272A5004A47F5 /* CrtObjCmd.3 */,
+ F96D3E2208F272A5004A47F5 /* CrtSlave.3 */,
+ F96D3E2308F272A5004A47F5 /* CrtTimerHdlr.3 */,
+ F96D3E2408F272A5004A47F5 /* CrtTrace.3 */,
+ F96D3E2508F272A5004A47F5 /* dde.n */,
+ F93599D30DF1F8F500E04F67 /* define.n */,
+ F96D3E2608F272A5004A47F5 /* DetachPids.3 */,
+ F96D3E2708F272A5004A47F5 /* dict.n */,
+ F96D3E2808F272A5004A47F5 /* DictObj.3 */,
+ F96D3E2908F272A5004A47F5 /* DoOneEvent.3 */,
+ F96D3E2A08F272A5004A47F5 /* DoubleObj.3 */,
+ F96D3E2B08F272A5004A47F5 /* DoWhenIdle.3 */,
+ F96D3E2C08F272A5004A47F5 /* DString.3 */,
+ F96D3E2D08F272A5004A47F5 /* DumpActiveMemory.3 */,
+ F96D3E2E08F272A5004A47F5 /* Encoding.3 */,
+ F96D3E2F08F272A5004A47F5 /* encoding.n */,
+ F96D3E3008F272A5004A47F5 /* Ensemble.3 */,
+ F96D3E3108F272A5004A47F5 /* Environment.3 */,
+ F96D3E3208F272A5004A47F5 /* eof.n */,
+ F96D3E3308F272A5004A47F5 /* error.n */,
+ F96D3E3408F272A5004A47F5 /* Eval.3 */,
+ F96D3E3508F272A5004A47F5 /* eval.n */,
+ F96D3E3608F272A5004A47F5 /* exec.n */,
+ F96D3E3708F272A5004A47F5 /* Exit.3 */,
+ F96D3E3808F272A5004A47F5 /* exit.n */,
+ F96D3E3908F272A5004A47F5 /* expr.n */,
+ F96D3E3A08F272A5004A47F5 /* ExprLong.3 */,
+ F96D3E3B08F272A5004A47F5 /* ExprLongObj.3 */,
+ F96D3E3C08F272A5004A47F5 /* fblocked.n */,
+ F96D3E3D08F272A5004A47F5 /* fconfigure.n */,
+ F96D3E3E08F272A5004A47F5 /* fcopy.n */,
+ F96D3E3F08F272A5004A47F5 /* file.n */,
+ F96D3E4008F272A5004A47F5 /* fileevent.n */,
+ F96D3E4108F272A5004A47F5 /* filename.n */,
+ F96D3E4208F272A5004A47F5 /* FileSystem.3 */,
+ F96D3E4308F272A5004A47F5 /* FindExec.3 */,
+ F96D3E4408F272A5004A47F5 /* flush.n */,
+ F96D3E4508F272A5004A47F5 /* for.n */,
+ F96D3E4608F272A5004A47F5 /* foreach.n */,
+ F96D3E4708F272A5004A47F5 /* format.n */,
+ F96D3E4808F272A5004A47F5 /* GetCwd.3 */,
+ F96D3E4908F272A5004A47F5 /* GetHostName.3 */,
+ F96D3E4A08F272A5004A47F5 /* GetIndex.3 */,
+ F96D3E4B08F272A5004A47F5 /* GetInt.3 */,
+ F96D3E4C08F272A5004A47F5 /* GetOpnFl.3 */,
+ F96D3E4D08F272A5004A47F5 /* gets.n */,
+ F96D3E4E08F272A5004A47F5 /* GetStdChan.3 */,
+ F96D3E4F08F272A5004A47F5 /* GetTime.3 */,
+ F96D3E5008F272A5004A47F5 /* GetVersion.3 */,
+ F96D3E5108F272A5004A47F5 /* glob.n */,
+ F96D3E5208F272A6004A47F5 /* global.n */,
+ F96D3E5308F272A6004A47F5 /* Hash.3 */,
+ F96D3E5408F272A6004A47F5 /* history.n */,
+ F96D3E5508F272A6004A47F5 /* http.n */,
+ F96D3E5608F272A6004A47F5 /* if.n */,
+ F96D3E5708F272A6004A47F5 /* incr.n */,
+ F96D3E5808F272A6004A47F5 /* info.n */,
+ F96D3E5908F272A6004A47F5 /* Init.3 */,
+ F96D3E5A08F272A6004A47F5 /* InitStubs.3 */,
+ F96D3E5B08F272A6004A47F5 /* Interp.3 */,
+ F96D3E5C08F272A6004A47F5 /* interp.n */,
+ F96D3E5D08F272A6004A47F5 /* IntObj.3 */,
+ F96D3E5E08F272A6004A47F5 /* join.n */,
+ F96D3E5F08F272A6004A47F5 /* lappend.n */,
+ F96D3E6008F272A6004A47F5 /* lassign.n */,
+ F96D3E6108F272A6004A47F5 /* library.n */,
+ F96D3E6208F272A6004A47F5 /* Limit.3 */,
+ F96D3E6308F272A6004A47F5 /* lindex.n */,
+ F96D3E6408F272A6004A47F5 /* LinkVar.3 */,
+ F96D3E6508F272A6004A47F5 /* linsert.n */,
+ F96D3E6608F272A6004A47F5 /* list.n */,
+ F96D3E6708F272A6004A47F5 /* ListObj.3 */,
+ F96D3E6808F272A6004A47F5 /* llength.n */,
+ F96D3E6908F272A6004A47F5 /* load.n */,
+ F96D3E6A08F272A6004A47F5 /* lrange.n */,
+ F96D3E6B08F272A6004A47F5 /* lrepeat.n */,
+ F96D3E6C08F272A6004A47F5 /* lreplace.n */,
+ F96D3E6D08F272A6004A47F5 /* lsearch.n */,
+ F96D3E6E08F272A6004A47F5 /* lset.n */,
+ F96D3E6F08F272A6004A47F5 /* lsort.n */,
+ F96D3E7008F272A6004A47F5 /* man.macros */,
+ F96D3E7108F272A6004A47F5 /* mathfunc.n */,
+ F96D3E7208F272A6004A47F5 /* memory.n */,
+ F93599D40DF1F91900E04F67 /* Method.3 */,
+ F96D3E7308F272A6004A47F5 /* msgcat.n */,
+ F93599D50DF1F93700E04F67 /* my.n */,
+ F96D3E7408F272A6004A47F5 /* Namespace.3 */,
+ F96D3E7508F272A6004A47F5 /* namespace.n */,
+ F93599D60DF1F95000E04F67 /* next.n */,
+ F96D3E7608F272A6004A47F5 /* Notifier.3 */,
+ F96D3E7708F272A6004A47F5 /* Object.3 */,
+ F93599D70DF1F96800E04F67 /* object.n */,
+ F96D3E7808F272A6004A47F5 /* ObjectType.3 */,
+ F96D3E7908F272A6004A47F5 /* open.n */,
+ F96D3E7A08F272A6004A47F5 /* OpenFileChnl.3 */,
+ F96D3E7B08F272A6004A47F5 /* OpenTcp.3 */,
+ F96D3E7C08F272A6004A47F5 /* package.n */,
+ F96D3E7D08F272A6004A47F5 /* packagens.n */,
+ F96D3E7E08F272A6004A47F5 /* Panic.3 */,
+ F96D3E7F08F272A6004A47F5 /* ParseCmd.3 */,
+ F96D3E8008F272A6004A47F5 /* pid.n */,
+ F96D3E8108F272A6004A47F5 /* pkgMkIndex.n */,
+ F96D3E8208F272A6004A47F5 /* PkgRequire.3 */,
+ F9ECB1E10B26543C00A28025 /* platform_shell.n */,
+ F9ECB1E20B26543C00A28025 /* platform.n */,
+ F96D3E8308F272A6004A47F5 /* Preserve.3 */,
+ F96D3E8408F272A6004A47F5 /* PrintDbl.3 */,
+ F96D3E8508F272A6004A47F5 /* proc.n */,
+ F96D3E8608F272A6004A47F5 /* puts.n */,
+ F96D3E8708F272A6004A47F5 /* pwd.n */,
+ F96D3E8808F272A6004A47F5 /* re_syntax.n */,
+ F96D3E8908F272A6004A47F5 /* read.n */,
+ F96D3E8A08F272A6004A47F5 /* RecEvalObj.3 */,
+ F96D3E8B08F272A6004A47F5 /* RecordEval.3 */,
+ F96D3E8C08F272A6004A47F5 /* RegConfig.3 */,
+ F96D3E8D08F272A6004A47F5 /* RegExp.3 */,
+ F96D3E8E08F272A6004A47F5 /* regexp.n */,
+ F96D3E8F08F272A6004A47F5 /* registry.n */,
+ F96D3E9008F272A6004A47F5 /* regsub.n */,
+ F96D3E9108F272A6004A47F5 /* rename.n */,
+ F96D3E9208F272A6004A47F5 /* return.n */,
+ F96D3E9308F272A6004A47F5 /* safe.n */,
+ F96D3E9408F272A6004A47F5 /* SaveResult.3 */,
+ F96D3E9508F272A6004A47F5 /* scan.n */,
+ F96D3E9608F272A6004A47F5 /* seek.n */,
+ F93599D80DF1F98300E04F67 /* self.n */,
+ F96D3E9708F272A6004A47F5 /* set.n */,
+ F96D3E9808F272A6004A47F5 /* SetChanErr.3 */,
+ F96D3E9908F272A6004A47F5 /* SetErrno.3 */,
+ F96D3E9A08F272A6004A47F5 /* SetRecLmt.3 */,
+ F96D3E9B08F272A7004A47F5 /* SetResult.3 */,
+ F96D3E9C08F272A7004A47F5 /* SetVar.3 */,
+ F96D3E9D08F272A7004A47F5 /* Signal.3 */,
+ F96D3E9E08F272A7004A47F5 /* Sleep.3 */,
+ F96D3E9F08F272A7004A47F5 /* socket.n */,
+ F96D3EA008F272A7004A47F5 /* source.n */,
+ F96D3EA108F272A7004A47F5 /* SourceRCFile.3 */,
+ F96D3EA208F272A7004A47F5 /* split.n */,
+ F96D3EA308F272A7004A47F5 /* SplitList.3 */,
+ F96D3EA408F272A7004A47F5 /* SplitPath.3 */,
+ F96D3EA508F272A7004A47F5 /* StaticPkg.3 */,
+ F96D3EA608F272A7004A47F5 /* StdChannels.3 */,
+ F96D3EA708F272A7004A47F5 /* string.n */,
+ F96D3EA808F272A7004A47F5 /* StringObj.3 */,
+ F96D3EA908F272A7004A47F5 /* StrMatch.3 */,
+ F96D3EAA08F272A7004A47F5 /* subst.n */,
+ F96D3EAB08F272A7004A47F5 /* SubstObj.3 */,
+ F96D3EAC08F272A7004A47F5 /* switch.n */,
+ F974D5760FBE7E1900BF728B /* tailcall.n */,
+ F96D3EAD08F272A7004A47F5 /* Tcl.n */,
+ F99D61180EF5573A00BBFE01 /* TclZlib.3 */,
+ F96D3EAE08F272A7004A47F5 /* Tcl_Main.3 */,
+ F96D3EAF08F272A7004A47F5 /* TCL_MEM_DEBUG.3 */,
+ F96D3EB008F272A7004A47F5 /* tclsh.1 */,
+ F96D3EB108F272A7004A47F5 /* tcltest.n */,
+ F96D3EB208F272A7004A47F5 /* tclvars.n */,
+ F96D3EB308F272A7004A47F5 /* tell.n */,
+ F96D3EB408F272A7004A47F5 /* Thread.3 */,
+ F9183E640EFC80CD0030B814 /* throw.n */,
+ F96D3EB508F272A7004A47F5 /* time.n */,
+ F96D3EB608F272A7004A47F5 /* tm.n */,
+ F96D3EB708F272A7004A47F5 /* ToUpper.3 */,
+ F96D3EB808F272A7004A47F5 /* trace.n */,
+ F96D3EB908F272A7004A47F5 /* TraceCmd.3 */,
+ F96D3EBA08F272A7004A47F5 /* TraceVar.3 */,
+ F96D3EBB08F272A7004A47F5 /* Translate.3 */,
+ F9183E650EFC80D70030B814 /* try.n */,
+ F96D3EBC08F272A7004A47F5 /* UniCharIsAlpha.3 */,
+ F96D3EBD08F272A7004A47F5 /* unknown.n */,
+ F96D3EBE08F272A7004A47F5 /* unload.n */,
+ F96D3EBF08F272A7004A47F5 /* unset.n */,
+ F96D3EC008F272A7004A47F5 /* update.n */,
+ F96D3EC108F272A7004A47F5 /* uplevel.n */,
+ F96D3EC208F272A7004A47F5 /* UpVar.3 */,
+ F96D3EC308F272A7004A47F5 /* upvar.n */,
+ F96D3EC408F272A7004A47F5 /* Utf.3 */,
+ F96D3EC508F272A7004A47F5 /* variable.n */,
+ F96D3EC608F272A7004A47F5 /* vwait.n */,
+ F96D3EC708F272A7004A47F5 /* while.n */,
+ F96D3EC808F272A7004A47F5 /* WrongNumArgs.3 */,
+ F915432D0EF201EE0032D1E8 /* zlib.n */,
+ );
+ path = doc;
+ sourceTree = "<group>";
+ };
+ F96D3EC908F272A7004A47F5 /* generic */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3ECA08F272A7004A47F5 /* README */,
+ F96D3ECB08F272A7004A47F5 /* regc_color.c */,
+ F96D3ECC08F272A7004A47F5 /* regc_cvec.c */,
+ F96D3ECD08F272A7004A47F5 /* regc_lex.c */,
+ F96D3ECE08F272A7004A47F5 /* regc_locale.c */,
+ F96D3ECF08F272A7004A47F5 /* regc_nfa.c */,
+ F96D3ED008F272A7004A47F5 /* regcomp.c */,
+ F96D3ED108F272A7004A47F5 /* regcustom.h */,
+ F96D3ED208F272A7004A47F5 /* rege_dfa.c */,
+ F96D3ED308F272A7004A47F5 /* regerror.c */,
+ F96D3ED408F272A7004A47F5 /* regerrs.h */,
+ F96D3ED508F272A7004A47F5 /* regex.h */,
+ F96D3ED608F272A7004A47F5 /* regexec.c */,
+ F96D3ED708F272A7004A47F5 /* regfree.c */,
+ F96D3ED808F272A7004A47F5 /* regfronts.c */,
+ F96D3ED908F272A7004A47F5 /* regguts.h */,
+ F96D3EDA08F272A7004A47F5 /* tcl.decls */,
+ F96D3EDB08F272A7004A47F5 /* tcl.h */,
+ F96D3EDC08F272A7004A47F5 /* tclAlloc.c */,
+ F96D3EDD08F272A7004A47F5 /* tclAsync.c */,
+ F96D3EDE08F272A7004A47F5 /* tclBasic.c */,
+ F96D3EDF08F272A7004A47F5 /* tclBinary.c */,
+ F96D3EE008F272A7004A47F5 /* tclCkalloc.c */,
+ F96D3EE108F272A7004A47F5 /* tclClock.c */,
+ F96D3EE208F272A7004A47F5 /* tclCmdAH.c */,
+ F96D3EE308F272A7004A47F5 /* tclCmdIL.c */,
+ F96D3EE408F272A7004A47F5 /* tclCmdMZ.c */,
+ F96D3EE508F272A7004A47F5 /* tclCompCmds.c */,
+ F96D3EE608F272A7004A47F5 /* tclCompExpr.c */,
+ F96D3EE708F272A7004A47F5 /* tclCompile.c */,
+ F96D3EE808F272A7004A47F5 /* tclCompile.h */,
+ F96D3EE908F272A7004A47F5 /* tclConfig.c */,
+ F96D3EEA08F272A7004A47F5 /* tclDate.c */,
+ F96D3EEB08F272A7004A47F5 /* tclDecls.h */,
+ F96D3EEC08F272A7004A47F5 /* tclDictObj.c */,
+ F9F4415D0C8BAE6F00BCCD67 /* tclDTrace.d */,
+ F96D3EED08F272A7004A47F5 /* tclEncoding.c */,
+ F96D3EEE08F272A7004A47F5 /* tclEnv.c */,
+ F96D3EEF08F272A7004A47F5 /* tclEvent.c */,
+ F96D3EF008F272A7004A47F5 /* tclExecute.c */,
+ F96D3EF108F272A7004A47F5 /* tclFCmd.c */,
+ F96D3EF208F272A7004A47F5 /* tclFileName.c */,
+ F96D3EF308F272A7004A47F5 /* tclFileSystem.h */,
+ F96D3EF408F272A7004A47F5 /* tclGet.c */,
+ F96D3EF508F272A7004A47F5 /* tclGetDate.y */,
+ F96D3EF608F272A7004A47F5 /* tclHash.c */,
+ F96D3EF708F272A7004A47F5 /* tclHistory.c */,
+ F96D3EF808F272A7004A47F5 /* tclIndexObj.c */,
+ F96D3EF908F272A7004A47F5 /* tclInt.decls */,
+ F96D3EFA08F272A7004A47F5 /* tclInt.h */,
+ F96D3EFB08F272A7004A47F5 /* tclIntDecls.h */,
+ F96D3EFC08F272A7004A47F5 /* tclInterp.c */,
+ F96D3EFD08F272A7004A47F5 /* tclIntPlatDecls.h */,
+ F96D3EFE08F272A7004A47F5 /* tclIO.c */,
+ F96D3EFF08F272A7004A47F5 /* tclIO.h */,
+ F96D3F0008F272A7004A47F5 /* tclIOCmd.c */,
+ F96D3F0108F272A7004A47F5 /* tclIOGT.c */,
+ F96D3F0208F272A7004A47F5 /* tclIORChan.c */,
+ F95D77E90DFD820D00A8BF6F /* tclIORTrans.c */,
+ F96D3F0308F272A7004A47F5 /* tclIOSock.c */,
+ F96D3F0408F272A7004A47F5 /* tclIOUtil.c */,
+ F96D3F0508F272A7004A47F5 /* tclLink.c */,
+ F96D3F0608F272A7004A47F5 /* tclListObj.c */,
+ F96D3F0708F272A7004A47F5 /* tclLiteral.c */,
+ F96D3F0808F272A7004A47F5 /* tclLoad.c */,
+ F96D3F0908F272A7004A47F5 /* tclLoadNone.c */,
+ F96D3F0A08F272A7004A47F5 /* tclMain.c */,
+ F96D3F0B08F272A7004A47F5 /* tclNamesp.c */,
+ F96D3F0C08F272A7004A47F5 /* tclNotify.c */,
+ F96D3F0D08F272A7004A47F5 /* tclObj.c */,
+ F93599B20DF1F75400E04F67 /* tclOO.c */,
+ F93599B40DF1F75900E04F67 /* tclOO.decls */,
+ F93599B50DF1F75D00E04F67 /* tclOO.h */,
+ F93599B60DF1F76100E04F67 /* tclOOBasic.c */,
+ F93599B80DF1F76600E04F67 /* tclOOCall.c */,
+ F93599BA0DF1F76A00E04F67 /* tclOODecls.h */,
+ F93599BB0DF1F77000E04F67 /* tclOODefineCmds.c */,
+ F93599BD0DF1F77400E04F67 /* tclOOInfo.c */,
+ F93599BF0DF1F77900E04F67 /* tclOOInt.h */,
+ F93599C00DF1F77D00E04F67 /* tclOOIntDecls.h */,
+ F93599C10DF1F78300E04F67 /* tclOOMethod.c */,
+ F93599C30DF1F78800E04F67 /* tclOOStubInit.c */,
+ F93599C50DF1F78D00E04F67 /* tclOOStubLib.c */,
+ F96D3F0E08F272A7004A47F5 /* tclPanic.c */,
+ F96D3F0F08F272A7004A47F5 /* tclParse.c */,
+ F96D3F1108F272A7004A47F5 /* tclPathObj.c */,
+ F96D3F1208F272A7004A47F5 /* tclPipe.c */,
+ F96D3F1308F272A7004A47F5 /* tclPkg.c */,
+ F96D3F1408F272A7004A47F5 /* tclPkgConfig.c */,
+ F96D3F1508F272A7004A47F5 /* tclPlatDecls.h */,
+ F96D3F1608F272A7004A47F5 /* tclPort.h */,
+ F96D3F1708F272A7004A47F5 /* tclPosixStr.c */,
+ F96D3F1808F272A7004A47F5 /* tclPreserve.c */,
+ F96D3F1908F272A7004A47F5 /* tclProc.c */,
+ F96D3F1A08F272A7004A47F5 /* tclRegexp.c */,
+ F96D3F1B08F272A7004A47F5 /* tclRegexp.h */,
+ F96D3F1C08F272A7004A47F5 /* tclResolve.c */,
+ F96D3F1D08F272A7004A47F5 /* tclResult.c */,
+ F96D3F1E08F272A7004A47F5 /* tclScan.c */,
+ F96D3F1F08F272A7004A47F5 /* tclStringObj.c */,
+ F96D3F2408F272A7004A47F5 /* tclStrToD.c */,
+ F96D3F2508F272A7004A47F5 /* tclStubInit.c */,
+ F96D3F2608F272A7004A47F5 /* tclStubLib.c */,
+ F96D3F2708F272A7004A47F5 /* tclTest.c */,
+ F96D3F2808F272A7004A47F5 /* tclTestObj.c */,
+ F96D3F2908F272A7004A47F5 /* tclTestProcBodyObj.c */,
+ F96D3F2A08F272A7004A47F5 /* tclThread.c */,
+ F96D3F2B08F272A7004A47F5 /* tclThreadAlloc.c */,
+ F96D3F2C08F272A7004A47F5 /* tclThreadJoin.c */,
+ F96D3F2D08F272A7004A47F5 /* tclThreadStorage.c */,
+ F96D3F2E08F272A7004A47F5 /* tclThreadTest.c */,
+ F96D3F2F08F272A7004A47F5 /* tclTimer.c */,
+ F9903CAF094FAADA004613E9 /* tclTomMath.decls */,
+ F96D3F3008F272A7004A47F5 /* tclTomMath.h */,
+ F9903CB0094FAADA004613E9 /* tclTomMathDecls.h */,
+ F96D3F3108F272A7004A47F5 /* tclTomMathInterface.c */,
+ F96D3F3208F272A7004A47F5 /* tclTrace.c */,
+ F96D3F3308F272A7004A47F5 /* tclUniData.c */,
+ F96D3F3408F272A7004A47F5 /* tclUtf.c */,
+ F96D3F3508F272A7004A47F5 /* tclUtil.c */,
+ F96D3F3608F272A7004A47F5 /* tclVar.c */,
+ F96437C90EF0D4B2003F468E /* tclZlib.c */,
+ F96D3F3708F272A7004A47F5 /* tommath.h */,
+ );
+ path = generic;
+ sourceTree = "<group>";
+ };
+ F96D3F3808F272A7004A47F5 /* library */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3F3908F272A8004A47F5 /* auto.tcl */,
+ F96D3F3A08F272A8004A47F5 /* clock.tcl */,
+ F96D3F3B08F272A8004A47F5 /* dde */,
+ F96D3F8C08F272A8004A47F5 /* history.tcl */,
+ F96D3F8D08F272A8004A47F5 /* http */,
+ F96D3F9008F272A8004A47F5 /* http1.0 */,
+ F96D3F9308F272A8004A47F5 /* init.tcl */,
+ F96D3F9408F272A8004A47F5 /* msgcat */,
+ F96D401708F272AA004A47F5 /* opt */,
+ F96D401A08F272AA004A47F5 /* package.tcl */,
+ F96D401B08F272AA004A47F5 /* parray.tcl */,
+ F9ECB1110B26521500A28025 /* platform */,
+ F96D401C08F272AA004A47F5 /* reg */,
+ F96D401E08F272AA004A47F5 /* safe.tcl */,
+ F96D401F08F272AA004A47F5 /* tclIndex */,
+ F96D402008F272AA004A47F5 /* tcltest */,
+ F96D402308F272AA004A47F5 /* tm.tcl */,
+ F96D425B08F272B2004A47F5 /* word.tcl */,
+ );
+ path = library;
+ sourceTree = "<group>";
+ };
+ F96D3F3B08F272A8004A47F5 /* dde */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3F3C08F272A8004A47F5 /* pkgIndex.tcl */,
+ );
+ path = dde;
+ sourceTree = "<group>";
+ };
+ F96D3F8D08F272A8004A47F5 /* http */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3F8E08F272A8004A47F5 /* http.tcl */,
+ F96D3F8F08F272A8004A47F5 /* pkgIndex.tcl */,
+ );
+ path = http;
+ sourceTree = "<group>";
+ };
+ F96D3F9008F272A8004A47F5 /* http1.0 */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3F9108F272A8004A47F5 /* http.tcl */,
+ F96D3F9208F272A8004A47F5 /* pkgIndex.tcl */,
+ );
+ path = http1.0;
+ sourceTree = "<group>";
+ };
+ F96D3F9408F272A8004A47F5 /* msgcat */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3F9508F272A8004A47F5 /* msgcat.tcl */,
+ F96D3F9608F272A8004A47F5 /* pkgIndex.tcl */,
+ );
+ path = msgcat;
+ sourceTree = "<group>";
+ };
+ F96D401708F272AA004A47F5 /* opt */ = {
+ isa = PBXGroup;
+ children = (
+ F96D401808F272AA004A47F5 /* optparse.tcl */,
+ F96D401908F272AA004A47F5 /* pkgIndex.tcl */,
+ );
+ path = opt;
+ sourceTree = "<group>";
+ };
+ F96D401C08F272AA004A47F5 /* reg */ = {
+ isa = PBXGroup;
+ children = (
+ F96D401D08F272AA004A47F5 /* pkgIndex.tcl */,
+ );
+ path = reg;
+ sourceTree = "<group>";
+ };
+ F96D402008F272AA004A47F5 /* tcltest */ = {
+ isa = PBXGroup;
+ children = (
+ F96D402108F272AA004A47F5 /* pkgIndex.tcl */,
+ F96D402208F272AA004A47F5 /* tcltest.tcl */,
+ );
+ path = tcltest;
+ sourceTree = "<group>";
+ };
+ F96D425C08F272B2004A47F5 /* libtommath */ = {
+ isa = PBXGroup;
+ children = (
+ F96D426408F272B3004A47F5 /* bn_fast_s_mp_mul_digs.c */,
+ F96D426608F272B3004A47F5 /* bn_fast_s_mp_sqr.c */,
+ F96D426908F272B3004A47F5 /* bn_mp_add.c */,
+ F96D426A08F272B3004A47F5 /* bn_mp_add_d.c */,
+ F96D426C08F272B3004A47F5 /* bn_mp_and.c */,
+ F96D426D08F272B3004A47F5 /* bn_mp_clamp.c */,
+ F96D426E08F272B3004A47F5 /* bn_mp_clear.c */,
+ F96D426F08F272B3004A47F5 /* bn_mp_clear_multi.c */,
+ F96D427008F272B3004A47F5 /* bn_mp_cmp.c */,
+ F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */,
+ F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */,
+ F96D427408F272B3004A47F5 /* bn_mp_copy.c */,
+ F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */,
+ F96D427608F272B3004A47F5 /* bn_mp_div.c */,
+ F96D427708F272B3004A47F5 /* bn_mp_div_2.c */,
+ F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */,
+ F96D427908F272B3004A47F5 /* bn_mp_div_3.c */,
+ F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */,
+ F96D427E08F272B3004A47F5 /* bn_mp_exch.c */,
+ F96D427F08F272B3004A47F5 /* bn_mp_expt_d.c */,
+ F96D428708F272B3004A47F5 /* bn_mp_grow.c */,
+ F96D428808F272B3004A47F5 /* bn_mp_init.c */,
+ F96D428908F272B3004A47F5 /* bn_mp_init_copy.c */,
+ F96D428A08F272B3004A47F5 /* bn_mp_init_multi.c */,
+ F96D428B08F272B3004A47F5 /* bn_mp_init_set.c */,
+ F96D428D08F272B3004A47F5 /* bn_mp_init_size.c */,
+ F96D429208F272B3004A47F5 /* bn_mp_karatsuba_mul.c */,
+ F96D429308F272B3004A47F5 /* bn_mp_karatsuba_sqr.c */,
+ F96D429508F272B3004A47F5 /* bn_mp_lshd.c */,
+ F96D429608F272B3004A47F5 /* bn_mp_mod.c */,
+ F96D429708F272B3004A47F5 /* bn_mp_mod_2d.c */,
+ F96D429C08F272B3004A47F5 /* bn_mp_mul.c */,
+ F96D429D08F272B3004A47F5 /* bn_mp_mul_2.c */,
+ F96D429E08F272B3004A47F5 /* bn_mp_mul_2d.c */,
+ F96D429F08F272B3004A47F5 /* bn_mp_mul_d.c */,
+ F96D42A208F272B3004A47F5 /* bn_mp_neg.c */,
+ F96D42A308F272B3004A47F5 /* bn_mp_or.c */,
+ F96D42AB08F272B3004A47F5 /* bn_mp_radix_size.c */,
+ F96D42AC08F272B3004A47F5 /* bn_mp_radix_smap.c */,
+ F96D42AE08F272B3004A47F5 /* bn_mp_read_radix.c */,
+ F96D42B908F272B3004A47F5 /* bn_mp_rshd.c */,
+ F96D42BA08F272B3004A47F5 /* bn_mp_set.c */,
+ F96D42BC08F272B3004A47F5 /* bn_mp_shrink.c */,
+ F96D42BE08F272B3004A47F5 /* bn_mp_sqr.c */,
+ F96D42C008F272B3004A47F5 /* bn_mp_sqrt.c */,
+ F96D42C108F272B3004A47F5 /* bn_mp_sub.c */,
+ F96D42C208F272B3004A47F5 /* bn_mp_sub_d.c */,
+ F96D42C608F272B3004A47F5 /* bn_mp_to_unsigned_bin.c */,
+ F96D42C708F272B3004A47F5 /* bn_mp_to_unsigned_bin_n.c */,
+ F96D42C808F272B3004A47F5 /* bn_mp_toom_mul.c */,
+ F96D42C908F272B3004A47F5 /* bn_mp_toom_sqr.c */,
+ F96D42CB08F272B3004A47F5 /* bn_mp_toradix_n.c */,
+ F96D42CC08F272B3004A47F5 /* bn_mp_unsigned_bin_size.c */,
+ F96D42CD08F272B3004A47F5 /* bn_mp_xor.c */,
+ F96D42CE08F272B3004A47F5 /* bn_mp_zero.c */,
+ F96D42D008F272B3004A47F5 /* bn_reverse.c */,
+ F96D42D108F272B3004A47F5 /* bn_s_mp_add.c */,
+ F96D42D308F272B3004A47F5 /* bn_s_mp_mul_digs.c */,
+ F96D42D508F272B3004A47F5 /* bn_s_mp_sqr.c */,
+ F96D42D608F272B3004A47F5 /* bn_s_mp_sub.c */,
+ F96D42D708F272B3004A47F5 /* bncore.c */,
+ F96D432908F272B4004A47F5 /* tommath_class.h */,
+ F96D432A08F272B4004A47F5 /* tommath_superclass.h */,
+ );
+ path = libtommath;
+ sourceTree = "<group>";
+ };
+ F96D432C08F272B4004A47F5 /* macosx */ = {
+ isa = PBXGroup;
+ children = (
+ F96D432E08F272B5004A47F5 /* configure.ac */,
+ F96D432F08F272B5004A47F5 /* GNUmakefile */,
+ F96D433108F272B5004A47F5 /* README */,
+ F96D433908F272B5004A47F5 /* tclMacOSXBundle.c */,
+ F96D433D08F272B5004A47F5 /* tclMacOSXFCmd.c */,
+ F96D433E08F272B5004A47F5 /* tclMacOSXNotify.c */,
+ F96D433208F272B5004A47F5 /* Tcl-Info.plist.in */,
+ F91E62260C1AE686006C9D96 /* Tclsh-Info.plist.in */,
+ );
+ path = macosx;
+ sourceTree = "<group>";
+ };
+ F96D434408F272B5004A47F5 /* tests */ = {
+ isa = PBXGroup;
+ children = (
+ F96D434508F272B5004A47F5 /* all.tcl */,
+ F96D434608F272B5004A47F5 /* append.test */,
+ F96D434708F272B5004A47F5 /* appendComp.test */,
+ F9ECB1CA0B2652D300A28025 /* apply.test */,
+ F96D434808F272B5004A47F5 /* assocd.test */,
+ F96D434908F272B5004A47F5 /* async.test */,
+ F96D434A08F272B5004A47F5 /* autoMkindex.test */,
+ F96D434B08F272B5004A47F5 /* basic.test */,
+ F96D434C08F272B5004A47F5 /* binary.test */,
+ F96D434D08F272B5004A47F5 /* case.test */,
+ F96D434E08F272B5004A47F5 /* chan.test */,
+ F9A493240CEBF38300B78AE2 /* chanio.test */,
+ F96D434F08F272B5004A47F5 /* clock.test */,
+ F96D435008F272B5004A47F5 /* cmdAH.test */,
+ F96D435108F272B5004A47F5 /* cmdIL.test */,
+ F96D435208F272B5004A47F5 /* cmdInfo.test */,
+ F96D435308F272B5004A47F5 /* cmdMZ.test */,
+ F96D435408F272B5004A47F5 /* compExpr-old.test */,
+ F96D435508F272B5004A47F5 /* compExpr.test */,
+ F96D435608F272B5004A47F5 /* compile.test */,
+ F96D435708F272B5004A47F5 /* concat.test */,
+ F96D435808F272B5004A47F5 /* config.test */,
+ F974D5770FBE7E6100BF728B /* coroutine.test */,
+ F96D435908F272B5004A47F5 /* dcall.test */,
+ F96D435A08F272B5004A47F5 /* dict.test */,
+ F96D435C08F272B5004A47F5 /* dstring.test */,
+ F96D435E08F272B5004A47F5 /* encoding.test */,
+ F96D435F08F272B5004A47F5 /* env.test */,
+ F96D436008F272B5004A47F5 /* error.test */,
+ F96D436108F272B5004A47F5 /* eval.test */,
+ F96D436208F272B5004A47F5 /* event.test */,
+ F96D436308F272B5004A47F5 /* exec.test */,
+ F96D436408F272B5004A47F5 /* execute.test */,
+ F96D436508F272B5004A47F5 /* expr-old.test */,
+ F96D436608F272B5004A47F5 /* expr.test */,
+ F96D436708F272B6004A47F5 /* fCmd.test */,
+ F96D436808F272B6004A47F5 /* fileName.test */,
+ F96D436908F272B6004A47F5 /* fileSystem.test */,
+ F96D436A08F272B6004A47F5 /* for-old.test */,
+ F96D436B08F272B6004A47F5 /* for.test */,
+ F96D436C08F272B6004A47F5 /* foreach.test */,
+ F96D436D08F272B6004A47F5 /* format.test */,
+ F96D436E08F272B6004A47F5 /* get.test */,
+ F96D436F08F272B6004A47F5 /* history.test */,
+ F96D437008F272B6004A47F5 /* http.test */,
+ F974D56C0FBE7D6300BF728B /* http11.test */,
+ F96D437108F272B6004A47F5 /* httpd */,
+ F974D56D0FBE7D6300BF728B /* httpd11.tcl */,
+ F96D437208F272B6004A47F5 /* httpold.test */,
+ F96D437308F272B6004A47F5 /* if-old.test */,
+ F96D437408F272B6004A47F5 /* if.test */,
+ F96D437508F272B6004A47F5 /* incr-old.test */,
+ F96D437608F272B6004A47F5 /* incr.test */,
+ F96D437708F272B6004A47F5 /* indexObj.test */,
+ F96D437808F272B6004A47F5 /* info.test */,
+ F96D437908F272B6004A47F5 /* init.test */,
+ F96D437A08F272B6004A47F5 /* interp.test */,
+ F96D437B08F272B6004A47F5 /* io.test */,
+ F96D437C08F272B6004A47F5 /* ioCmd.test */,
+ F96D437D08F272B6004A47F5 /* iogt.test */,
+ F96D437F08F272B6004A47F5 /* join.test */,
+ F96D438008F272B6004A47F5 /* lindex.test */,
+ F96D438108F272B6004A47F5 /* link.test */,
+ F96D438208F272B6004A47F5 /* linsert.test */,
+ F96D438308F272B6004A47F5 /* list.test */,
+ F96D438408F272B6004A47F5 /* listObj.test */,
+ F96D438508F272B6004A47F5 /* llength.test */,
+ F96D438608F272B6004A47F5 /* load.test */,
+ F96D438708F272B6004A47F5 /* lrange.test */,
+ F96D438808F272B6004A47F5 /* lrepeat.test */,
+ F96D438908F272B6004A47F5 /* lreplace.test */,
+ F96D438A08F272B6004A47F5 /* lsearch.test */,
+ F96D438B08F272B6004A47F5 /* lset.test */,
+ F96D438C08F272B6004A47F5 /* lsetComp.test */,
+ F96D438D08F272B6004A47F5 /* macOSXFCmd.test */,
+ F95FAFF90B34F1130072E431 /* macOSXLoad.test */,
+ F96D438E08F272B6004A47F5 /* main.test */,
+ F9ECB1CB0B26534C00A28025 /* mathop.test */,
+ F96D438F08F272B6004A47F5 /* misc.test */,
+ F96D439008F272B6004A47F5 /* msgcat.test */,
+ F96D439108F272B6004A47F5 /* namespace-old.test */,
+ F96D439208F272B7004A47F5 /* namespace.test */,
+ F96D439308F272B7004A47F5 /* notify.test */,
+ F91DC23C0E44C51B002CB8D1 /* nre.test */,
+ F96D439408F272B7004A47F5 /* obj.test */,
+ F93599C80DF1F81900E04F67 /* oo.test */,
+ F96D439508F272B7004A47F5 /* opt.test */,
+ F96D439608F272B7004A47F5 /* package.test */,
+ F96D439708F272B7004A47F5 /* parse.test */,
+ F96D439808F272B7004A47F5 /* parseExpr.test */,
+ F96D439908F272B7004A47F5 /* parseOld.test */,
+ F96D439A08F272B7004A47F5 /* pid.test */,
+ F96D439B08F272B7004A47F5 /* pkg.test */,
+ F96D439C08F272B7004A47F5 /* pkgMkIndex.test */,
+ F96D439D08F272B7004A47F5 /* platform.test */,
+ F96D439E08F272B7004A47F5 /* proc-old.test */,
+ F96D439F08F272B7004A47F5 /* proc.test */,
+ F96D43A008F272B7004A47F5 /* pwd.test */,
+ F96D43A108F272B7004A47F5 /* README */,
+ F96D43A208F272B7004A47F5 /* reg.test */,
+ F96D43A308F272B7004A47F5 /* regexp.test */,
+ F96D43A408F272B7004A47F5 /* regexpComp.test */,
+ F96D43A508F272B7004A47F5 /* registry.test */,
+ F96D43A608F272B7004A47F5 /* remote.tcl */,
+ F96D43A708F272B7004A47F5 /* rename.test */,
+ F96D43A808F272B7004A47F5 /* result.test */,
+ F96D43A908F272B7004A47F5 /* safe.test */,
+ F96D43AA08F272B7004A47F5 /* scan.test */,
+ F96D43AB08F272B7004A47F5 /* security.test */,
+ F96D43AC08F272B7004A47F5 /* set-old.test */,
+ F96D43AD08F272B7004A47F5 /* set.test */,
+ F96D43AE08F272B7004A47F5 /* socket.test */,
+ F96D43AF08F272B7004A47F5 /* source.test */,
+ F96D43B008F272B7004A47F5 /* split.test */,
+ F96D43B108F272B7004A47F5 /* stack.test */,
+ F96D43B208F272B7004A47F5 /* string.test */,
+ F96D43B308F272B7004A47F5 /* stringComp.test */,
+ F96D43B408F272B7004A47F5 /* stringObj.test */,
+ F96D43B508F272B7004A47F5 /* subst.test */,
+ F96D43B608F272B7004A47F5 /* switch.test */,
+ F974D5780FBE7E6100BF728B /* tailcall.test */,
+ F96D43B708F272B7004A47F5 /* tcltest.test */,
+ F96D43B808F272B7004A47F5 /* thread.test */,
+ F96D43B908F272B7004A47F5 /* timer.test */,
+ F96D43BA08F272B7004A47F5 /* tm.test */,
+ F96D43BB08F272B7004A47F5 /* trace.test */,
+ F96D43BC08F272B7004A47F5 /* unixFCmd.test */,
+ F96D43BD08F272B7004A47F5 /* unixFile.test */,
+ F96D43BE08F272B7004A47F5 /* unixInit.test */,
+ F96D43BF08F272B7004A47F5 /* unixNotfy.test */,
+ F96D43C008F272B7004A47F5 /* unknown.test */,
+ F96D43C108F272B7004A47F5 /* unload.test */,
+ F96D43C208F272B7004A47F5 /* uplevel.test */,
+ F96D43C308F272B7004A47F5 /* upvar.test */,
+ F96D43C408F272B7004A47F5 /* utf.test */,
+ F96D43C508F272B7004A47F5 /* util.test */,
+ F96D43C608F272B7004A47F5 /* var.test */,
+ F96D43C708F272B7004A47F5 /* while-old.test */,
+ F96D43C808F272B7004A47F5 /* while.test */,
+ F96D43C908F272B7004A47F5 /* winConsole.test */,
+ F96D43CA08F272B7004A47F5 /* winDde.test */,
+ F96D43CB08F272B7004A47F5 /* winFCmd.test */,
+ F96D43CC08F272B7004A47F5 /* winFile.test */,
+ F96D43CD08F272B7004A47F5 /* winNotify.test */,
+ F96D43CE08F272B7004A47F5 /* winPipe.test */,
+ F96D43CF08F272B7004A47F5 /* winTime.test */,
+ F915432A0EF201CF0032D1E8 /* zlib.test */,
+ );
+ path = tests;
+ sourceTree = "<group>";
+ };
+ F96D43D008F272B8004A47F5 /* tools */ = {
+ isa = PBXGroup;
+ children = (
+ F96D43D108F272B8004A47F5 /* checkLibraryDoc.tcl */,
+ F96D43D208F272B8004A47F5 /* configure */,
+ F96D43D308F272B8004A47F5 /* configure.in */,
+ F96D442208F272B8004A47F5 /* eolFix.tcl */,
+ F96D442408F272B8004A47F5 /* fix_tommath_h.tcl */,
+ F96D442508F272B8004A47F5 /* genStubs.tcl */,
+ F96D442708F272B8004A47F5 /* index.tcl */,
+ F96D442808F272B8004A47F5 /* installData.tcl */,
+ F96D442908F272B8004A47F5 /* loadICU.tcl */,
+ F96D442A08F272B8004A47F5 /* Makefile.in */,
+ F96D442B08F272B8004A47F5 /* makeTestCases.tcl */,
+ F96D442C08F272B8004A47F5 /* man2help.tcl */,
+ F96D442D08F272B8004A47F5 /* man2help2.tcl */,
+ F96D442E08F272B8004A47F5 /* man2html.tcl */,
+ F96D442F08F272B8004A47F5 /* man2html1.tcl */,
+ F96D443008F272B8004A47F5 /* man2html2.tcl */,
+ F96D443108F272B8004A47F5 /* man2tcl.c */,
+ F96D443208F272B8004A47F5 /* README */,
+ F96D443308F272B8004A47F5 /* regexpTestLib.tcl */,
+ F96D443508F272B8004A47F5 /* tcl.hpj.in */,
+ F96D443608F272B8004A47F5 /* tcl.wse.in */,
+ F96D443908F272B9004A47F5 /* tcltk-man2html.tcl */,
+ F96D443A08F272B9004A47F5 /* tclZIC.tcl */,
+ F92D7F100DE777240033A13A /* tsdPerf.tcl */,
+ F96D443B08F272B9004A47F5 /* uniClass.tcl */,
+ F96D443C08F272B9004A47F5 /* uniParse.tcl */,
+ );
+ path = tools;
+ sourceTree = "<group>";
+ };
+ F96D443E08F272B9004A47F5 /* unix */ = {
+ isa = PBXGroup;
+ children = (
+ F96D444008F272B9004A47F5 /* aclocal.m4 */,
+ F96D444108F272B9004A47F5 /* configure */,
+ F96D444208F272B9004A47F5 /* configure.in */,
+ F96D444308F272B9004A47F5 /* dltest */,
+ F96D444D08F272B9004A47F5 /* install-sh */,
+ F96D444E08F272B9004A47F5 /* installManPage */,
+ F96D444F08F272B9004A47F5 /* ldAix */,
+ F96D445008F272B9004A47F5 /* Makefile.in */,
+ F96D445208F272B9004A47F5 /* README */,
+ F96D445308F272B9004A47F5 /* tcl.m4 */,
+ F974D5790FBE7E9C00BF728B /* tcl.pc.in */,
+ F96D445408F272B9004A47F5 /* tcl.spec */,
+ F96D445508F272B9004A47F5 /* tclAppInit.c */,
+ F96D445608F272B9004A47F5 /* tclConfig.h.in */,
+ F96D445708F272B9004A47F5 /* tclConfig.sh.in */,
+ F96D445808F272B9004A47F5 /* tclLoadAix.c */,
+ F96D445908F272B9004A47F5 /* tclLoadDl.c */,
+ F96D445B08F272B9004A47F5 /* tclLoadDyld.c */,
+ F96D445C08F272B9004A47F5 /* tclLoadNext.c */,
+ F96D445D08F272B9004A47F5 /* tclLoadOSF.c */,
+ F96D445E08F272B9004A47F5 /* tclLoadShl.c */,
+ F96D445F08F272B9004A47F5 /* tclUnixChan.c */,
+ F9FC77B70AB29E9100B7077D /* tclUnixCompat.c */,
+ F96D446008F272B9004A47F5 /* tclUnixEvent.c */,
+ F96D446108F272B9004A47F5 /* tclUnixFCmd.c */,
+ F96D446208F272B9004A47F5 /* tclUnixFile.c */,
+ F96D446308F272B9004A47F5 /* tclUnixInit.c */,
+ F96D446408F272B9004A47F5 /* tclUnixNotfy.c */,
+ F96D446508F272B9004A47F5 /* tclUnixPipe.c */,
+ F96D446608F272B9004A47F5 /* tclUnixPort.h */,
+ F96D446708F272B9004A47F5 /* tclUnixSock.c */,
+ F96D446808F272B9004A47F5 /* tclUnixTest.c */,
+ F96D446908F272B9004A47F5 /* tclUnixThrd.c */,
+ F96D446A08F272B9004A47F5 /* tclUnixThrd.h */,
+ F96D446B08F272B9004A47F5 /* tclUnixTime.c */,
+ F96D446C08F272B9004A47F5 /* tclXtNotify.c */,
+ F96D446D08F272B9004A47F5 /* tclXtTest.c */,
+ );
+ path = unix;
+ sourceTree = "<group>";
+ };
+ F96D444308F272B9004A47F5 /* dltest */ = {
+ isa = PBXGroup;
+ children = (
+ F96D444408F272B9004A47F5 /* Makefile.in */,
+ F96D444508F272B9004A47F5 /* pkga.c */,
+ F96D444608F272B9004A47F5 /* pkgb.c */,
+ F96D444708F272B9004A47F5 /* pkgc.c */,
+ F96D444808F272B9004A47F5 /* pkgd.c */,
+ F96D444908F272B9004A47F5 /* pkge.c */,
+ F96D444B08F272B9004A47F5 /* pkgua.c */,
+ F96D444C08F272B9004A47F5 /* README */,
+ );
+ path = dltest;
+ sourceTree = "<group>";
+ };
+ F96D446E08F272B9004A47F5 /* win */ = {
+ isa = PBXGroup;
+ children = (
+ F96D447008F272BA004A47F5 /* aclocal.m4 */,
+ F96D447108F272BA004A47F5 /* buildall.vc.bat */,
+ F96D447208F272BA004A47F5 /* cat.c */,
+ F96D447408F272BA004A47F5 /* configure */,
+ F96D447508F272BA004A47F5 /* configure.in */,
+ F96D447708F272BA004A47F5 /* Makefile.in */,
+ F96D447808F272BA004A47F5 /* makefile.vc */,
+ F96D447908F272BA004A47F5 /* nmakehlp.c */,
+ F96D447A08F272BA004A47F5 /* README */,
+ F96D447C08F272BA004A47F5 /* rules.vc */,
+ F96D447D08F272BA004A47F5 /* stub16.c */,
+ F96D447E08F272BA004A47F5 /* tcl.dsp */,
+ F96D447F08F272BA004A47F5 /* tcl.dsw */,
+ F96D448008F272BA004A47F5 /* tcl.hpj.in */,
+ F96D448108F272BA004A47F5 /* tcl.m4 */,
+ F96D448208F272BA004A47F5 /* tcl.rc */,
+ F96D448308F272BA004A47F5 /* tclAppInit.c */,
+ F96D448408F272BA004A47F5 /* tclConfig.sh.in */,
+ F96D448608F272BA004A47F5 /* tclsh.rc */,
+ F96D448708F272BA004A47F5 /* tclWin32Dll.c */,
+ F96D448808F272BA004A47F5 /* tclWinChan.c */,
+ F96D448908F272BA004A47F5 /* tclWinConsole.c */,
+ F96D448A08F272BA004A47F5 /* tclWinDde.c */,
+ F96D448B08F272BA004A47F5 /* tclWinError.c */,
+ F96D448C08F272BA004A47F5 /* tclWinFCmd.c */,
+ F96D448D08F272BA004A47F5 /* tclWinFile.c */,
+ F96D448E08F272BA004A47F5 /* tclWinInit.c */,
+ F96D448F08F272BA004A47F5 /* tclWinInt.h */,
+ F96D449008F272BA004A47F5 /* tclWinLoad.c */,
+ F96D449108F272BA004A47F5 /* tclWinNotify.c */,
+ F96D449208F272BA004A47F5 /* tclWinPipe.c */,
+ F96D449308F272BA004A47F5 /* tclWinPort.h */,
+ F96D449408F272BA004A47F5 /* tclWinReg.c */,
+ F96D449508F272BA004A47F5 /* tclWinSerial.c */,
+ F96D449608F272BA004A47F5 /* tclWinSock.c */,
+ F96D449708F272BA004A47F5 /* tclWinTest.c */,
+ F96D449808F272BA004A47F5 /* tclWinThrd.c */,
+ F96D449908F272BA004A47F5 /* tclWinThrd.h */,
+ F96D449A08F272BA004A47F5 /* tclWinTime.c */,
+ );
+ path = win;
+ sourceTree = "<group>";
+ };
+ F9ECB1110B26521500A28025 /* platform */ = {
+ isa = PBXGroup;
+ children = (
+ F9ECB1120B26521500A28025 /* pkgIndex.tcl */,
+ F9ECB1130B26521500A28025 /* platform.tcl */,
+ F9ECB1140B26521500A28025 /* shell.tcl */,
+ );
+ path = platform;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 8DD76FA90486AB0100D96B5E /* tktest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = F95CC8B009158F3100EA5ACE /* Build configuration list for PBXNativeTarget "tktest" */;
+ buildPhases = (
+ F9A5C5F508F651A2008AE941 /* Configure Tcl */,
+ F9A5C5F608F651AB008AE941 /* Configure Tk */,
+ 8DD76FAB0486AB0100D96B5E /* Sources */,
+ 8DD76FAD0486AB0100D96B5E /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = tktest;
+ productInstallPath = "$(BINDIR)";
+ productName = tktest;
+ productReference = 8DD76FB20486AB0100D96B5E /* tktest */;
+ productType = "com.apple.product-type.tool";
+ };
+ F97258A50A86873C00096C78 /* tktest-X11 */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = F97258A80A86873D00096C78 /* Build configuration list for PBXNativeTarget "tktest-X11" */;
+ buildPhases = (
+ F9FD30B40CC1AD070073837D /* Configure Tcl */,
+ F9FD30B50CC1AD070073837D /* Configure Tk */,
+ F9FD30BB0CC1AD070073837D /* Sources */,
+ F9FD31E30CC1AD070073837D /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "tktest-X11";
+ productInstallPath = "$(BINDIR)";
+ productName = tktest;
+ productReference = F9FD31F40CC1AD070073837D /* tktest-X11 */;
+ productType = "com.apple.product-type.tool";
+ };
+ F9E61D16090A3E94002B3151 /* Tk */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = F95CC8AB09158F3100EA5ACE /* Build configuration list for PBXNativeTarget "Tk" */;
+ buildPhases = (
+ F97AF02F0B665DA900310EA2 /* Build Tk */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = Tk;
+ productName = Wish;
+ productReference = F9A3084B08F2D4CE00BAE1AB /* Wish.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 08FB7793FE84155DC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ BuildIndependentTargetsInParallel = YES;
+ };
+ buildConfigurationList = F95CC8B509158F3100EA5ACE /* Build configuration list for PBXProject "Tk" */;
+ compatibilityVersion = "Xcode 3.1";
+ hasScannedForEncodings = 1;
+ mainGroup = 08FB7794FE84155DC02AAC07 /* Tk */;
+ projectDirPath = "";
+ projectRoot = ..;
+ targets = (
+ F9E61D16090A3E94002B3151 /* Tk */,
+ 8DD76FA90486AB0100D96B5E /* tktest */,
+ F97258A50A86873C00096C78 /* tktest-X11 */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ F97AF02F0B665DA900310EA2 /* Build Tk */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "${TARGET_TEMP_DIR}/.none",
+ );
+ name = "Build Tk";
+ outputPaths = (
+ "${TARGET_BUILD_DIR}/${WRAPPER_NAME}",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/bash;
+ shellScript = "export CC=$(xcrun -find ${GCC} || echo ${GCC}); export LD=${CC}\ngnumake -C \"${TK_SRCROOT}/macosx\" -j \"$(sysctl -n hw.activecpu)\" \"$(echo \"${ACTION}\" | sed -e s/build// -e s/clean/distclean/ -e s/..\\*/\\&-/)${MAKE_TARGET}\" CFLAGS_WARNING=\"${WARNING_CFLAGS}\" CFLAGS_OPTIMIZE=\"-O${GCC_OPTIMIZATION_LEVEL}\" SYMROOT=\"${BUILT_PRODUCTS_DIR}\" OBJ_DIR=\"${OBJECT_FILE_DIR}\" INSTALL_ROOT=\"${DSTROOT}\" PREFIX=\"${PREFIX}\" BINDIR=\"${BINDIR}\" LIBDIR=\"${FRAMEWORK_INSTALL_PATH}\" MANDIR=\"${MANDIR}\" EXTRA_CONFIGURE_ARGS=\"${CONFIGURE_ARGS}\" APPLICATION_INSTALL_PATH=\"${APPLICATION_INSTALL_PATH}\" TCL_BUILD_DIR=\"${TCL_BUILD_DIR}\" TCL_FRAMEWORK_DIR=\"${TCL_FRAMEWORK_DIR}\" ${EXTRA_MAKE_FLAGS}\nresult=$?\nif [ -e \"${BUILT_PRODUCTS_DIR}/tktest\" ]; then\n\trm -f \"${BUILT_PRODUCTS_DIR}/tktest\"\nfi\necho \"Done\"\nrm -f \"${SCRIPT_INPUT_FILE_0}\"\nexit ${result}\n";
+ showEnvVarsInLog = 0;
+ };
+ F9A5C5F508F651A2008AE941 /* Configure Tcl */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "$(TCL_SRCROOT)/macosx/configure.ac",
+ "$(TCL_SRCROOT)/unix/configure.in",
+ "$(TCL_SRCROOT)/unix/tcl.m4",
+ "$(TCL_SRCROOT)/unix/aclocal.m4",
+ "$(TCL_SRCROOT)/unix/tclConfig.sh.in",
+ "$(TCL_SRCROOT)/unix/Makefile.in",
+ "$(TCL_SRCROOT)/unix/dltest/Makefile.in",
+ );
+ name = "Configure Tcl";
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/tcl/tclConfig.sh",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/bash;
+ shellScript = "## tcl configure shell script phase\n\ncd \"${TCL_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.in -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n echo \"Running autoconf & autoheader in tcl/macosx\"\n rm -rf autom4te.cache\n ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tcl && cd tcl &&\nif [ \"${TCL_SRCROOT}\"/macosx/configure -nt config.status ]; then\n echo \"Configuring Tcl\"\n CC=$(xcrun -find ${GCC} || echo ${GCC})\n \"${TCL_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n ./config.status\nfi\n";
+ showEnvVarsInLog = 0;
+ };
+ F9A5C5F608F651AB008AE941 /* Configure Tk */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "$(TK_SRCROOT)/macosx/configure.ac",
+ "$(TK_SRCROOT)/unix/configure.in",
+ "$(TK_SRCROOT)/unix/tcl.m4",
+ "$(TK_SRCROOT)/unix/aclocal.m4",
+ "$(TK_SRCROOT)/unix/tkConfig.sh.in",
+ );
+ name = "Configure Tk";
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/tk/tkConfig.sh",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/bash;
+ shellScript = "## tk configure shell script phase\n\ncd \"${TK_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.in -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n echo \"Running autoconf & autoheader in tk/macosx\"\n rm -rf autom4te.cache\n ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tk && cd tk &&\nif [ \"${TK_SRCROOT}\"/macosx/configure -nt config.status ]; then\n echo \"Configuring Tk\"\n CC=$(xcrun -find ${GCC} || echo ${GCC})\n \"${TK_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared --enable-aqua --with-tcl=../tcl CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n ./config.status\nfi\n";
+ showEnvVarsInLog = 0;
+ };
+ F9FD30B40CC1AD070073837D /* Configure Tcl */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "$(TCL_SRCROOT)/macosx/configure.ac",
+ "$(TCL_SRCROOT)/unix/configure.in",
+ "$(TCL_SRCROOT)/unix/tcl.m4",
+ "$(TCL_SRCROOT)/unix/aclocal.m4",
+ "$(TCL_SRCROOT)/unix/tclConfig.sh.in",
+ "$(TCL_SRCROOT)/unix/Makefile.in",
+ "$(TCL_SRCROOT)/unix/dltest/Makefile.in",
+ );
+ name = "Configure Tcl";
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/tcl/tclConfig.sh",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/bash;
+ shellScript = "## tcl configure shell script phase\n\ncd \"${TCL_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.in -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n echo \"Running autoconf & autoheader in tcl/macosx\"\n rm -rf autom4te.cache\n ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tcl && cd tcl &&\nif [ \"${TCL_SRCROOT}\"/macosx/configure -nt config.status ]; then\n echo \"Configuring Tcl\"\n CC=$(xcrun -find ${GCC} || echo ${GCC})\n \"${TCL_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n ./config.status\nfi\n";
+ showEnvVarsInLog = 0;
+ };
+ F9FD30B50CC1AD070073837D /* Configure Tk */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "$(TK_SRCROOT)/macosx/configure.ac",
+ "$(TK_SRCROOT)/unix/configure.in",
+ "$(TK_SRCROOT)/unix/tcl.m4",
+ "$(TK_SRCROOT)/unix/aclocal.m4",
+ "$(TK_SRCROOT)/unix/tkConfig.sh.in",
+ );
+ name = "Configure Tk";
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/tk/tkConfig.sh",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/bash;
+ shellScript = "## tk configure shell script phase\n\ncd \"${TK_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.in -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n echo \"Running autoconf & autoheader in tk/macosx\"\n rm -rf autom4te.cache\n ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tk && cd tk &&\nif [ \"${TK_SRCROOT}\"/macosx/configure -nt config.status ]; then\n echo \"Configuring Tk\"\n CC=$(xcrun -find ${GCC} || echo ${GCC})\n PATH=\"${PATH}:/usr/X11R6/bin\" \"${TK_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared --enable-xft --with-tcl=../tcl CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n ./config.status\nfi";
+ showEnvVarsInLog = 0;
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 8DD76FAB0486AB0100D96B5E /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F96D456F08F272BB004A47F5 /* regcomp.c in Sources */,
+ F96D457208F272BB004A47F5 /* regerror.c in Sources */,
+ F96D457508F272BB004A47F5 /* regexec.c in Sources */,
+ F96D457608F272BB004A47F5 /* regfree.c in Sources */,
+ F96D457B08F272BB004A47F5 /* tclAlloc.c in Sources */,
+ F96D457C08F272BB004A47F5 /* tclAsync.c in Sources */,
+ F96D457D08F272BB004A47F5 /* tclBasic.c in Sources */,
+ F96D457E08F272BC004A47F5 /* tclBinary.c in Sources */,
+ F96D457F08F272BC004A47F5 /* tclCkalloc.c in Sources */,
+ F96D458008F272BC004A47F5 /* tclClock.c in Sources */,
+ F96D458108F272BC004A47F5 /* tclCmdAH.c in Sources */,
+ F96D458208F272BC004A47F5 /* tclCmdIL.c in Sources */,
+ F96D458308F272BC004A47F5 /* tclCmdMZ.c in Sources */,
+ F96D458408F272BC004A47F5 /* tclCompCmds.c in Sources */,
+ F96D458508F272BC004A47F5 /* tclCompExpr.c in Sources */,
+ F96D458608F272BC004A47F5 /* tclCompile.c in Sources */,
+ F96D458808F272BC004A47F5 /* tclConfig.c in Sources */,
+ F96D458908F272BC004A47F5 /* tclDate.c in Sources */,
+ F96D458B08F272BC004A47F5 /* tclDictObj.c in Sources */,
+ F96D458C08F272BC004A47F5 /* tclEncoding.c in Sources */,
+ F96D458D08F272BC004A47F5 /* tclEnv.c in Sources */,
+ F96D458E08F272BC004A47F5 /* tclEvent.c in Sources */,
+ F96D458F08F272BC004A47F5 /* tclExecute.c in Sources */,
+ F96D459008F272BC004A47F5 /* tclFCmd.c in Sources */,
+ F96D459108F272BC004A47F5 /* tclFileName.c in Sources */,
+ F96D459308F272BC004A47F5 /* tclGet.c in Sources */,
+ F96D459508F272BC004A47F5 /* tclHash.c in Sources */,
+ F96D459608F272BC004A47F5 /* tclHistory.c in Sources */,
+ F96D459708F272BC004A47F5 /* tclIndexObj.c in Sources */,
+ F96D459B08F272BC004A47F5 /* tclInterp.c in Sources */,
+ F96D459D08F272BC004A47F5 /* tclIO.c in Sources */,
+ F96D459F08F272BC004A47F5 /* tclIOCmd.c in Sources */,
+ F96D45A008F272BC004A47F5 /* tclIOGT.c in Sources */,
+ F96D45A108F272BC004A47F5 /* tclIORChan.c in Sources */,
+ F95D77EA0DFD820D00A8BF6F /* tclIORTrans.c in Sources */,
+ F96D45A208F272BC004A47F5 /* tclIOSock.c in Sources */,
+ F96D45A308F272BC004A47F5 /* tclIOUtil.c in Sources */,
+ F96D45A408F272BC004A47F5 /* tclLink.c in Sources */,
+ F96D45A508F272BC004A47F5 /* tclListObj.c in Sources */,
+ F96D45A608F272BC004A47F5 /* tclLiteral.c in Sources */,
+ F96D45A708F272BC004A47F5 /* tclLoad.c in Sources */,
+ F96D45A908F272BC004A47F5 /* tclMain.c in Sources */,
+ F96D45AA08F272BC004A47F5 /* tclNamesp.c in Sources */,
+ F96D45AB08F272BC004A47F5 /* tclNotify.c in Sources */,
+ F96D45AC08F272BC004A47F5 /* tclObj.c in Sources */,
+ F93599B30DF1F75400E04F67 /* tclOO.c in Sources */,
+ F93599B70DF1F76100E04F67 /* tclOOBasic.c in Sources */,
+ F93599B90DF1F76600E04F67 /* tclOOCall.c in Sources */,
+ F93599BC0DF1F77000E04F67 /* tclOODefineCmds.c in Sources */,
+ F93599BE0DF1F77400E04F67 /* tclOOInfo.c in Sources */,
+ F93599C20DF1F78300E04F67 /* tclOOMethod.c in Sources */,
+ F93599C40DF1F78800E04F67 /* tclOOStubInit.c in Sources */,
+ F93599C60DF1F78D00E04F67 /* tclOOStubLib.c in Sources */,
+ F96D45AD08F272BC004A47F5 /* tclPanic.c in Sources */,
+ F96D45AE08F272BC004A47F5 /* tclParse.c in Sources */,
+ F96D45B008F272BC004A47F5 /* tclPathObj.c in Sources */,
+ F96D45B108F272BC004A47F5 /* tclPipe.c in Sources */,
+ F96D45B208F272BC004A47F5 /* tclPkg.c in Sources */,
+ F96D45B308F272BC004A47F5 /* tclPkgConfig.c in Sources */,
+ F96D45B608F272BC004A47F5 /* tclPosixStr.c in Sources */,
+ F96D45B708F272BC004A47F5 /* tclPreserve.c in Sources */,
+ F96D45B808F272BC004A47F5 /* tclProc.c in Sources */,
+ F96D45B908F272BC004A47F5 /* tclRegexp.c in Sources */,
+ F96D45BB08F272BC004A47F5 /* tclResolve.c in Sources */,
+ F96D45BC08F272BC004A47F5 /* tclResult.c in Sources */,
+ F96D45BD08F272BC004A47F5 /* tclScan.c in Sources */,
+ F96D45BE08F272BC004A47F5 /* tclStringObj.c in Sources */,
+ F96D45C308F272BC004A47F5 /* tclStrToD.c in Sources */,
+ F96D45C408F272BC004A47F5 /* tclStubInit.c in Sources */,
+ F96D45C508F272BC004A47F5 /* tclStubLib.c in Sources */,
+ F96D45C908F272BC004A47F5 /* tclThread.c in Sources */,
+ F96D45CA08F272BC004A47F5 /* tclThreadAlloc.c in Sources */,
+ F96D45CB08F272BC004A47F5 /* tclThreadJoin.c in Sources */,
+ F96D45CC08F272BC004A47F5 /* tclThreadStorage.c in Sources */,
+ F96D45CE08F272BC004A47F5 /* tclTimer.c in Sources */,
+ F96D45D008F272BC004A47F5 /* tclTomMathInterface.c in Sources */,
+ F96D45D108F272BC004A47F5 /* tclTrace.c in Sources */,
+ F96D45D308F272BC004A47F5 /* tclUtf.c in Sources */,
+ F96D45D408F272BC004A47F5 /* tclUtil.c in Sources */,
+ F96D45D508F272BC004A47F5 /* tclVar.c in Sources */,
+ F96437CA0EF0D4B2003F468E /* tclZlib.c in Sources */,
+ F96D48E208F272C3004A47F5 /* bn_fast_s_mp_mul_digs.c in Sources */,
+ F96D48E408F272C3004A47F5 /* bn_fast_s_mp_sqr.c in Sources */,
+ F96D48E708F272C3004A47F5 /* bn_mp_add.c in Sources */,
+ F96D48E808F272C3004A47F5 /* bn_mp_add_d.c in Sources */,
+ F9E61D2B090A48A4002B3151 /* bn_mp_and.c in Sources */,
+ F96D48EB08F272C3004A47F5 /* bn_mp_clamp.c in Sources */,
+ F96D48EC08F272C3004A47F5 /* bn_mp_clear.c in Sources */,
+ F96D48ED08F272C3004A47F5 /* bn_mp_clear_multi.c in Sources */,
+ F96D48EE08F272C3004A47F5 /* bn_mp_cmp.c in Sources */,
+ F9E61D28090A481F002B3151 /* bn_mp_cmp_d.c in Sources */,
+ F96D48F008F272C3004A47F5 /* bn_mp_cmp_mag.c in Sources */,
+ F96D48F208F272C3004A47F5 /* bn_mp_copy.c in Sources */,
+ F96D48F308F272C3004A47F5 /* bn_mp_count_bits.c in Sources */,
+ F96D48F408F272C3004A47F5 /* bn_mp_div.c in Sources */,
+ F96D48F508F272C3004A47F5 /* bn_mp_div_2.c in Sources */,
+ F96D48F608F272C3004A47F5 /* bn_mp_div_2d.c in Sources */,
+ F96D48F708F272C3004A47F5 /* bn_mp_div_3.c in Sources */,
+ F96D48F808F272C3004A47F5 /* bn_mp_div_d.c in Sources */,
+ F96D48FC08F272C3004A47F5 /* bn_mp_exch.c in Sources */,
+ F9E61D2C090A48AC002B3151 /* bn_mp_expt_d.c in Sources */,
+ F96D490508F272C3004A47F5 /* bn_mp_grow.c in Sources */,
+ F96D490608F272C3004A47F5 /* bn_mp_init.c in Sources */,
+ F96D490708F272C3004A47F5 /* bn_mp_init_copy.c in Sources */,
+ F96D490808F272C3004A47F5 /* bn_mp_init_multi.c in Sources */,
+ F96D490908F272C3004A47F5 /* bn_mp_init_set.c in Sources */,
+ F96D490B08F272C3004A47F5 /* bn_mp_init_size.c in Sources */,
+ F96D491008F272C3004A47F5 /* bn_mp_karatsuba_mul.c in Sources */,
+ F96D491108F272C3004A47F5 /* bn_mp_karatsuba_sqr.c in Sources */,
+ F96D491308F272C3004A47F5 /* bn_mp_lshd.c in Sources */,
+ F96D491408F272C3004A47F5 /* bn_mp_mod.c in Sources */,
+ F96D491508F272C3004A47F5 /* bn_mp_mod_2d.c in Sources */,
+ F96D491A08F272C3004A47F5 /* bn_mp_mul.c in Sources */,
+ F96D491B08F272C3004A47F5 /* bn_mp_mul_2.c in Sources */,
+ F96D491C08F272C3004A47F5 /* bn_mp_mul_2d.c in Sources */,
+ F96D491D08F272C3004A47F5 /* bn_mp_mul_d.c in Sources */,
+ F9E61D29090A486C002B3151 /* bn_mp_neg.c in Sources */,
+ F9E61D2E090A48BF002B3151 /* bn_mp_or.c in Sources */,
+ F96D492908F272C3004A47F5 /* bn_mp_radix_size.c in Sources */,
+ F96D492A08F272C3004A47F5 /* bn_mp_radix_smap.c in Sources */,
+ F96D492C08F272C3004A47F5 /* bn_mp_read_radix.c in Sources */,
+ F96D493708F272C3004A47F5 /* bn_mp_rshd.c in Sources */,
+ F96D493808F272C3004A47F5 /* bn_mp_set.c in Sources */,
+ F9E61D2F090A48C7002B3151 /* bn_mp_shrink.c in Sources */,
+ F96D493C08F272C3004A47F5 /* bn_mp_sqr.c in Sources */,
+ F9E61D2A090A4891002B3151 /* bn_mp_sqrt.c in Sources */,
+ F96D493F08F272C3004A47F5 /* bn_mp_sub.c in Sources */,
+ F96D494008F272C3004A47F5 /* bn_mp_sub_d.c in Sources */,
+ F9E61D30090A48E2002B3151 /* bn_mp_to_unsigned_bin_n.c in Sources */,
+ F9E61D31090A48F9002B3151 /* bn_mp_to_unsigned_bin.c in Sources */,
+ F96D494608F272C3004A47F5 /* bn_mp_toom_mul.c in Sources */,
+ F96D494708F272C3004A47F5 /* bn_mp_toom_sqr.c in Sources */,
+ F96D494908F272C3004A47F5 /* bn_mp_toradix_n.c in Sources */,
+ F9E61D32090A48FA002B3151 /* bn_mp_unsigned_bin_size.c in Sources */,
+ F9E61D2D090A48BB002B3151 /* bn_mp_xor.c in Sources */,
+ F96D494C08F272C3004A47F5 /* bn_mp_zero.c in Sources */,
+ F96D494E08F272C3004A47F5 /* bn_reverse.c in Sources */,
+ F96D494F08F272C3004A47F5 /* bn_s_mp_add.c in Sources */,
+ F96D495108F272C3004A47F5 /* bn_s_mp_mul_digs.c in Sources */,
+ F96D495308F272C3004A47F5 /* bn_s_mp_sqr.c in Sources */,
+ F96D495408F272C3004A47F5 /* bn_s_mp_sub.c in Sources */,
+ F96D495508F272C3004A47F5 /* bncore.c in Sources */,
+ F96D49A908F272C4004A47F5 /* tclMacOSXBundle.c in Sources */,
+ F96D49AD08F272C4004A47F5 /* tclMacOSXFCmd.c in Sources */,
+ F96D49AE08F272C4004A47F5 /* tclMacOSXNotify.c in Sources */,
+ F96D4AC608F272C9004A47F5 /* tclLoadDyld.c in Sources */,
+ F96D4ACA08F272C9004A47F5 /* tclUnixChan.c in Sources */,
+ F9FC77B80AB29E9100B7077D /* tclUnixCompat.c in Sources */,
+ F96D4ACB08F272C9004A47F5 /* tclUnixEvent.c in Sources */,
+ F96D4ACC08F272C9004A47F5 /* tclUnixFCmd.c in Sources */,
+ F96D4ACD08F272C9004A47F5 /* tclUnixFile.c in Sources */,
+ F96D4ACE08F272C9004A47F5 /* tclUnixInit.c in Sources */,
+ F96D4ACF08F272C9004A47F5 /* tclUnixNotfy.c in Sources */,
+ F96D4AD008F272C9004A47F5 /* tclUnixPipe.c in Sources */,
+ F96D4AD208F272CA004A47F5 /* tclUnixSock.c in Sources */,
+ F96D4AD408F272CA004A47F5 /* tclUnixThrd.c in Sources */,
+ F96D4AD608F272CA004A47F5 /* tclUnixTime.c in Sources */,
+ F9F4415E0C8BAE6F00BCCD67 /* tclDTrace.d in Sources */,
+ F966BDCF08F27A3F005CB29B /* tk3d.c in Sources */,
+ F966BDD108F27A3F005CB29B /* tkArgv.c in Sources */,
+ F966BDD208F27A3F005CB29B /* tkAtom.c in Sources */,
+ F966BDD308F27A3F005CB29B /* tkBind.c in Sources */,
+ F966BDD408F27A3F005CB29B /* tkBitmap.c in Sources */,
+ F9152B090EAF8A5000CD5C7B /* tkBusy.c in Sources */,
+ F966BDD508F27A3F005CB29B /* tkButton.c in Sources */,
+ F966BDD708F27A3F005CB29B /* tkCanvArc.c in Sources */,
+ F966BDD808F27A3F005CB29B /* tkCanvas.c in Sources */,
+ F966BDDA08F27A3F005CB29B /* tkCanvBmap.c in Sources */,
+ F966BDDB08F27A3F005CB29B /* tkCanvImg.c in Sources */,
+ F966BDDC08F27A3F005CB29B /* tkCanvLine.c in Sources */,
+ F966BDDD08F27A3F005CB29B /* tkCanvPoly.c in Sources */,
+ F966BDDE08F27A3F005CB29B /* tkCanvPs.c in Sources */,
+ F966BDE008F27A3F005CB29B /* tkCanvText.c in Sources */,
+ F966BDE108F27A3F005CB29B /* tkCanvUtil.c in Sources */,
+ F966BDE208F27A3F005CB29B /* tkCanvWind.c in Sources */,
+ F966BDE308F27A3F005CB29B /* tkClipboard.c in Sources */,
+ F966BDE408F27A3F005CB29B /* tkCmds.c in Sources */,
+ F966BDE508F27A3F005CB29B /* tkColor.c in Sources */,
+ F966BDE708F27A3F005CB29B /* tkConfig.c in Sources */,
+ F966BDE808F27A3F005CB29B /* tkConsole.c in Sources */,
+ F966BDE908F27A3F005CB29B /* tkCursor.c in Sources */,
+ F966BDEB08F27A3F005CB29B /* tkEntry.c in Sources */,
+ F966BDED08F27A3F005CB29B /* tkError.c in Sources */,
+ F966BDEE08F27A3F005CB29B /* tkEvent.c in Sources */,
+ F966BDEF08F27A3F005CB29B /* tkFileFilter.c in Sources */,
+ F966BDF108F27A3F005CB29B /* tkFocus.c in Sources */,
+ F966BDF208F27A3F005CB29B /* tkFont.c in Sources */,
+ F966BDF408F27A3F005CB29B /* tkFrame.c in Sources */,
+ F966BDF508F27A3F005CB29B /* tkGC.c in Sources */,
+ F966BDF608F27A3F005CB29B /* tkGeometry.c in Sources */,
+ F966BDF708F27A3F005CB29B /* tkGet.c in Sources */,
+ F966BDF808F27A3F005CB29B /* tkGrab.c in Sources */,
+ F966BDF908F27A3F005CB29B /* tkGrid.c in Sources */,
+ F966BDFA08F27A3F005CB29B /* tkImage.c in Sources */,
+ F966BDFB08F27A3F005CB29B /* tkImgBmap.c in Sources */,
+ F966BDFC08F27A3F005CB29B /* tkImgGIF.c in Sources */,
+ F92EE8BF0E62F846001A6E80 /* tkImgPhInstance.c in Sources */,
+ F966BDFD08F27A3F005CB29B /* tkImgPhoto.c in Sources */,
+ F9DD99BD0F07DF850018B2E4 /* tkImgPNG.c in Sources */,
+ F966BDFE08F27A3F005CB29B /* tkImgPPM.c in Sources */,
+ F966BE0708F27A3F005CB29B /* tkListbox.c in Sources */,
+ F966BE0808F27A3F005CB29B /* tkMacWinMenu.c in Sources */,
+ F966BE0908F27A3F005CB29B /* tkMain.c in Sources */,
+ F966BE0A08F27A3F005CB29B /* tkMenu.c in Sources */,
+ F966BE0C08F27A3F005CB29B /* tkMenubutton.c in Sources */,
+ F966BE0E08F27A3F005CB29B /* tkMenuDraw.c in Sources */,
+ F966BE0F08F27A3F005CB29B /* tkMessage.c in Sources */,
+ F966BE1008F27A3F005CB29B /* tkObj.c in Sources */,
+ F966BE1108F27A3F005CB29B /* tkOldConfig.c in Sources */,
+ F9067BCD0BFBA2900074F726 /* tkOldTest.c in Sources */,
+ F966BE1208F27A3F005CB29B /* tkOption.c in Sources */,
+ F966BE1308F27A3F005CB29B /* tkPack.c in Sources */,
+ F966BE1408F27A3F005CB29B /* tkPanedWindow.c in Sources */,
+ F966BE1508F27A3F005CB29B /* tkPlace.c in Sources */,
+ F966BE1708F27A3F005CB29B /* tkPointer.c in Sources */,
+ F966BE1908F27A3F005CB29B /* tkRectOval.c in Sources */,
+ F966BE1A08F27A3F005CB29B /* tkScale.c in Sources */,
+ F966BE1C08F27A40005CB29B /* tkScrollbar.c in Sources */,
+ F966BE1E08F27A40005CB29B /* tkSelect.c in Sources */,
+ F966BE2008F27A40005CB29B /* tkSquare.c in Sources */,
+ F966BE2208F27A40005CB29B /* tkStubInit.c in Sources */,
+ F966BE2308F27A40005CB29B /* tkStubLib.c in Sources */,
+ F966BE2408F27A40005CB29B /* tkStyle.c in Sources */,
+ F966BE2508F27A40005CB29B /* tkTest.c in Sources */,
+ F966BE2608F27A40005CB29B /* tkText.c in Sources */,
+ F966BE2808F27A40005CB29B /* tkTextBTree.c in Sources */,
+ F966BE2908F27A40005CB29B /* tkTextDisp.c in Sources */,
+ F966BE2B08F27A40005CB29B /* tkTextImage.c in Sources */,
+ F966BE2C08F27A40005CB29B /* tkTextIndex.c in Sources */,
+ F966BE2D08F27A40005CB29B /* tkTextMark.c in Sources */,
+ F966BE2E08F27A40005CB29B /* tkTextTag.c in Sources */,
+ F966BE2F08F27A40005CB29B /* tkTextWind.c in Sources */,
+ F966BE3008F27A40005CB29B /* tkTrig.c in Sources */,
+ F966BE3108F27A40005CB29B /* tkUndo.c in Sources */,
+ F966BE3308F27A40005CB29B /* tkUtil.c in Sources */,
+ F966BE3408F27A40005CB29B /* tkVisual.c in Sources */,
+ F966BE3508F27A40005CB29B /* tkWindow.c in Sources */,
+ F96888050AF786D5000797B5 /* ttkBlink.c in Sources */,
+ F96888060AF786D5000797B5 /* ttkButton.c in Sources */,
+ F96888070AF786D5000797B5 /* ttkCache.c in Sources */,
+ F96888080AF786D5000797B5 /* ttkClamTheme.c in Sources */,
+ F96888090AF786D5000797B5 /* ttkClassicTheme.c in Sources */,
+ F968880A0AF786D5000797B5 /* ttkDefaultTheme.c in Sources */,
+ F968880B0AF786D5000797B5 /* ttkElements.c in Sources */,
+ F968880C0AF786D5000797B5 /* ttkEntry.c in Sources */,
+ F968880D0AF786D5000797B5 /* ttkFrame.c in Sources */,
+ F968880E0AF786D5000797B5 /* ttkImage.c in Sources */,
+ F968880F0AF786D5000797B5 /* ttkInit.c in Sources */,
+ F96888100AF786D5000797B5 /* ttkLabel.c in Sources */,
+ F96888110AF786D5000797B5 /* ttkLayout.c in Sources */,
+ F96888120AF786D5000797B5 /* ttkManager.c in Sources */,
+ F96888130AF786D5000797B5 /* ttkNotebook.c in Sources */,
+ F96888140AF786D5000797B5 /* ttkPanedwindow.c in Sources */,
+ F96888150AF786D5000797B5 /* ttkProgress.c in Sources */,
+ F96888160AF786D5000797B5 /* ttkScale.c in Sources */,
+ F96888170AF786D5000797B5 /* ttkScroll.c in Sources */,
+ F96888180AF786D5000797B5 /* ttkScrollbar.c in Sources */,
+ F96888190AF786D5000797B5 /* ttkSeparator.c in Sources */,
+ F968881A0AF786D5000797B5 /* ttkSquare.c in Sources */,
+ F968881B0AF786D5000797B5 /* ttkState.c in Sources */,
+ F968881C0AF786D5000797B5 /* ttkStubInit.c in Sources */,
+ F968881D0AF786D5000797B5 /* ttkStubLib.c in Sources */,
+ F968881E0AF786D5000797B5 /* ttkTagSet.c in Sources */,
+ F968881F0AF786D5000797B5 /* ttkTheme.c in Sources */,
+ F96888200AF786D5000797B5 /* ttkTrace.c in Sources */,
+ F96888210AF786D5000797B5 /* ttkTrack.c in Sources */,
+ F96888220AF786D5000797B5 /* ttkTreeview.c in Sources */,
+ F96888230AF786D5000797B5 /* ttkWidget.c in Sources */,
+ F966BEDB08F27A40005CB29B /* tkMacOSXBitmap.c in Sources */,
+ F966BEDC08F27A40005CB29B /* tkMacOSXButton.c in Sources */,
+ F966BEDE08F27A40005CB29B /* tkMacOSXClipboard.c in Sources */,
+ F966BEDF08F27A40005CB29B /* tkMacOSXColor.c in Sources */,
+ F966BEE008F27A40005CB29B /* tkMacOSXConfig.c in Sources */,
+ F966BEE108F27A40005CB29B /* tkMacOSXCursor.c in Sources */,
+ F966BEE308F27A40005CB29B /* tkMacOSXDebug.c in Sources */,
+ F966BEE608F27A40005CB29B /* tkMacOSXDialog.c in Sources */,
+ F966BEE708F27A40005CB29B /* tkMacOSXDraw.c in Sources */,
+ F966BEE808F27A40005CB29B /* tkMacOSXEmbed.c in Sources */,
+ F966BEE908F27A40005CB29B /* tkMacOSXEntry.c in Sources */,
+ F966BEEA08F27A40005CB29B /* tkMacOSXEvent.c in Sources */,
+ F966BEEC08F27A40005CB29B /* tkMacOSXFont.c in Sources */,
+ F966BEED08F27A40005CB29B /* tkMacOSXHLEvents.c in Sources */,
+ F966BEEE08F27A40005CB29B /* tkMacOSXInit.c in Sources */,
+ F966BEF108F27A40005CB29B /* tkMacOSXKeyboard.c in Sources */,
+ F966BEF208F27A40005CB29B /* tkMacOSXKeyEvent.c in Sources */,
+ F966BEF308F27A40005CB29B /* tkMacOSXMenu.c in Sources */,
+ F966BEF608F27A40005CB29B /* tkMacOSXMenubutton.c in Sources */,
+ F966BEF708F27A40005CB29B /* tkMacOSXMenus.c in Sources */,
+ F966BEF808F27A40005CB29B /* tkMacOSXMouseEvent.c in Sources */,
+ F966BEF908F27A40005CB29B /* tkMacOSXNotify.c in Sources */,
+ F966BF0108F27A40005CB29B /* tkMacOSXRegion.c in Sources */,
+ F966BF0308F27A40005CB29B /* tkMacOSXScrlbr.c in Sources */,
+ F966BF0408F27A40005CB29B /* tkMacOSXSend.c in Sources */,
+ F966BF0508F27A40005CB29B /* tkMacOSXSubwindows.c in Sources */,
+ F966BF0608F27A40005CB29B /* tkMacOSXTest.c in Sources */,
+ F966BF0708F27A40005CB29B /* tkMacOSXWindowEvent.c in Sources */,
+ F966BF0808F27A40005CB29B /* tkMacOSXWm.c in Sources */,
+ F966BF0B08F27A40005CB29B /* tkMacOSXXStubs.c in Sources */,
+ F96888850AF78938000797B5 /* ttkMacOSXTheme.c in Sources */,
+ F966BF7F08F27A41005CB29B /* tkAppInit.c in Sources */,
+ F966BF8308F27A41005CB29B /* tkUnix3d.c in Sources */,
+ F966BF9608F27A41005CB29B /* tkUnixScale.c in Sources */,
+ F966C02A08F27A42005CB29B /* xcolors.c in Sources */,
+ F966C02B08F27A42005CB29B /* xdraw.c in Sources */,
+ F966C02C08F27A42005CB29B /* xgc.c in Sources */,
+ F966C02D08F27A42005CB29B /* ximage.c in Sources */,
+ F966C02E08F27A42005CB29B /* xutil.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F9FD30BB0CC1AD070073837D /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F9FD30BC0CC1AD070073837D /* regcomp.c in Sources */,
+ F9FD30BD0CC1AD070073837D /* regerror.c in Sources */,
+ F9FD30BE0CC1AD070073837D /* regexec.c in Sources */,
+ F9FD30BF0CC1AD070073837D /* regfree.c in Sources */,
+ F9FD30C00CC1AD070073837D /* tclAlloc.c in Sources */,
+ F9FD30C10CC1AD070073837D /* tclAsync.c in Sources */,
+ F9FD30C20CC1AD070073837D /* tclBasic.c in Sources */,
+ F9FD30C30CC1AD070073837D /* tclBinary.c in Sources */,
+ F9FD30C40CC1AD070073837D /* tclCkalloc.c in Sources */,
+ F9FD30C50CC1AD070073837D /* tclClock.c in Sources */,
+ F9FD30C60CC1AD070073837D /* tclCmdAH.c in Sources */,
+ F9FD30C70CC1AD070073837D /* tclCmdIL.c in Sources */,
+ F9FD30C80CC1AD070073837D /* tclCmdMZ.c in Sources */,
+ F9FD30C90CC1AD070073837D /* tclCompCmds.c in Sources */,
+ F9FD30CA0CC1AD070073837D /* tclCompExpr.c in Sources */,
+ F9FD30CB0CC1AD070073837D /* tclCompile.c in Sources */,
+ F9FD30CC0CC1AD070073837D /* tclConfig.c in Sources */,
+ F9FD30CD0CC1AD070073837D /* tclDate.c in Sources */,
+ F9FD30CE0CC1AD070073837D /* tclDictObj.c in Sources */,
+ F9FD30CF0CC1AD070073837D /* tclEncoding.c in Sources */,
+ F9FD30D00CC1AD070073837D /* tclEnv.c in Sources */,
+ F9FD30D10CC1AD070073837D /* tclEvent.c in Sources */,
+ F9FD30D20CC1AD070073837D /* tclExecute.c in Sources */,
+ F9FD30D30CC1AD070073837D /* tclFCmd.c in Sources */,
+ F9FD30D40CC1AD070073837D /* tclFileName.c in Sources */,
+ F9FD30D50CC1AD070073837D /* tclGet.c in Sources */,
+ F9FD30D60CC1AD070073837D /* tclHash.c in Sources */,
+ F9FD30D70CC1AD070073837D /* tclHistory.c in Sources */,
+ F9FD30D80CC1AD070073837D /* tclIndexObj.c in Sources */,
+ F9FD30D90CC1AD070073837D /* tclInterp.c in Sources */,
+ F9FD30DA0CC1AD070073837D /* tclIO.c in Sources */,
+ F9FD30DB0CC1AD070073837D /* tclIOCmd.c in Sources */,
+ F9FD30DC0CC1AD070073837D /* tclIOGT.c in Sources */,
+ F9FD30DD0CC1AD070073837D /* tclIORChan.c in Sources */,
+ F9FFAF1D0DFDDB26007F8A6A /* tclIORTrans.c in Sources */,
+ F9FD30DE0CC1AD070073837D /* tclIOSock.c in Sources */,
+ F9FD30DF0CC1AD070073837D /* tclIOUtil.c in Sources */,
+ F9FD30E00CC1AD070073837D /* tclLink.c in Sources */,
+ F9FD30E10CC1AD070073837D /* tclListObj.c in Sources */,
+ F9FD30E20CC1AD070073837D /* tclLiteral.c in Sources */,
+ F9FD30E30CC1AD070073837D /* tclLoad.c in Sources */,
+ F9FD30E40CC1AD070073837D /* tclMain.c in Sources */,
+ F9FD30E50CC1AD070073837D /* tclNamesp.c in Sources */,
+ F9FD30E60CC1AD070073837D /* tclNotify.c in Sources */,
+ F9FD30E70CC1AD070073837D /* tclObj.c in Sources */,
+ F9FFAF1F0DFDDB2F007F8A6A /* tclOO.c in Sources */,
+ F9FFAF200DFDDB32007F8A6A /* tclOOBasic.c in Sources */,
+ F9FFAF210DFDDB32007F8A6A /* tclOOCall.c in Sources */,
+ F9FFAF220DFDDB34007F8A6A /* tclOODefineCmds.c in Sources */,
+ F9FFAF230DFDDB35007F8A6A /* tclOOInfo.c in Sources */,
+ F9FFAF240DFDDB36007F8A6A /* tclOOMethod.c in Sources */,
+ F9FFAF250DFDDB37007F8A6A /* tclOOStubInit.c in Sources */,
+ F9FFAF260DFDDB38007F8A6A /* tclOOStubLib.c in Sources */,
+ F9FD30E80CC1AD070073837D /* tclPanic.c in Sources */,
+ F9FD30E90CC1AD070073837D /* tclParse.c in Sources */,
+ F9FD30EA0CC1AD070073837D /* tclPathObj.c in Sources */,
+ F9FD30EB0CC1AD070073837D /* tclPipe.c in Sources */,
+ F9FD30EC0CC1AD070073837D /* tclPkg.c in Sources */,
+ F9FD30ED0CC1AD070073837D /* tclPkgConfig.c in Sources */,
+ F9FD30EE0CC1AD070073837D /* tclPosixStr.c in Sources */,
+ F9FD30EF0CC1AD070073837D /* tclPreserve.c in Sources */,
+ F9FD30F00CC1AD070073837D /* tclProc.c in Sources */,
+ F9FD30F10CC1AD070073837D /* tclRegexp.c in Sources */,
+ F9FD30F20CC1AD070073837D /* tclResolve.c in Sources */,
+ F9FD30F30CC1AD070073837D /* tclResult.c in Sources */,
+ F9FD30F40CC1AD070073837D /* tclScan.c in Sources */,
+ F9FD30F50CC1AD070073837D /* tclStringObj.c in Sources */,
+ F9FD30F60CC1AD070073837D /* tclStrToD.c in Sources */,
+ F9FD30F70CC1AD070073837D /* tclStubInit.c in Sources */,
+ F9FD30F80CC1AD070073837D /* tclStubLib.c in Sources */,
+ F9FD30F90CC1AD070073837D /* tclThread.c in Sources */,
+ F9FD30FA0CC1AD070073837D /* tclThreadAlloc.c in Sources */,
+ F9FD30FB0CC1AD070073837D /* tclThreadJoin.c in Sources */,
+ F9FD30FC0CC1AD070073837D /* tclThreadStorage.c in Sources */,
+ F9FD30FD0CC1AD070073837D /* tclTimer.c in Sources */,
+ F9FD30FE0CC1AD070073837D /* tclTomMathInterface.c in Sources */,
+ F9FD30FF0CC1AD070073837D /* tclTrace.c in Sources */,
+ F9FD31000CC1AD070073837D /* tclUtf.c in Sources */,
+ F9FD31010CC1AD070073837D /* tclUtil.c in Sources */,
+ F9FD31020CC1AD070073837D /* tclVar.c in Sources */,
+ F96437CB0EF0D4B2003F468E /* tclZlib.c in Sources */,
+ F9FD31030CC1AD070073837D /* bn_fast_s_mp_mul_digs.c in Sources */,
+ F9FD31040CC1AD070073837D /* bn_fast_s_mp_sqr.c in Sources */,
+ F9FD31050CC1AD070073837D /* bn_mp_add.c in Sources */,
+ F9FD31060CC1AD070073837D /* bn_mp_add_d.c in Sources */,
+ F9FD31070CC1AD070073837D /* bn_mp_and.c in Sources */,
+ F9FD31080CC1AD070073837D /* bn_mp_clamp.c in Sources */,
+ F9FD31090CC1AD070073837D /* bn_mp_clear.c in Sources */,
+ F9FD310A0CC1AD070073837D /* bn_mp_clear_multi.c in Sources */,
+ F9FD310B0CC1AD070073837D /* bn_mp_cmp.c in Sources */,
+ F9FD310C0CC1AD070073837D /* bn_mp_cmp_d.c in Sources */,
+ F9FD310D0CC1AD070073837D /* bn_mp_cmp_mag.c in Sources */,
+ F9FD310E0CC1AD070073837D /* bn_mp_copy.c in Sources */,
+ F9FD310F0CC1AD070073837D /* bn_mp_count_bits.c in Sources */,
+ F9FD31100CC1AD070073837D /* bn_mp_div.c in Sources */,
+ F9FD31110CC1AD070073837D /* bn_mp_div_2.c in Sources */,
+ F9FD31120CC1AD070073837D /* bn_mp_div_2d.c in Sources */,
+ F9FD31130CC1AD070073837D /* bn_mp_div_3.c in Sources */,
+ F9FD31140CC1AD070073837D /* bn_mp_div_d.c in Sources */,
+ F9FD31150CC1AD070073837D /* bn_mp_exch.c in Sources */,
+ F9FD31160CC1AD070073837D /* bn_mp_expt_d.c in Sources */,
+ F9FD31170CC1AD070073837D /* bn_mp_grow.c in Sources */,
+ F9FD31180CC1AD070073837D /* bn_mp_init.c in Sources */,
+ F9FD31190CC1AD070073837D /* bn_mp_init_copy.c in Sources */,
+ F9FD311A0CC1AD070073837D /* bn_mp_init_multi.c in Sources */,
+ F9FD311B0CC1AD070073837D /* bn_mp_init_set.c in Sources */,
+ F9FD311C0CC1AD070073837D /* bn_mp_init_size.c in Sources */,
+ F9FD311D0CC1AD070073837D /* bn_mp_karatsuba_mul.c in Sources */,
+ F9FD311E0CC1AD070073837D /* bn_mp_karatsuba_sqr.c in Sources */,
+ F9FD311F0CC1AD070073837D /* bn_mp_lshd.c in Sources */,
+ F9FD31200CC1AD070073837D /* bn_mp_mod.c in Sources */,
+ F9FD31210CC1AD070073837D /* bn_mp_mod_2d.c in Sources */,
+ F9FD31220CC1AD070073837D /* bn_mp_mul.c in Sources */,
+ F9FD31230CC1AD070073837D /* bn_mp_mul_2.c in Sources */,
+ F9FD31240CC1AD070073837D /* bn_mp_mul_2d.c in Sources */,
+ F9FD31250CC1AD070073837D /* bn_mp_mul_d.c in Sources */,
+ F9FD31260CC1AD070073837D /* bn_mp_neg.c in Sources */,
+ F9FD31270CC1AD070073837D /* bn_mp_or.c in Sources */,
+ F9FD31280CC1AD070073837D /* bn_mp_radix_size.c in Sources */,
+ F9FD31290CC1AD070073837D /* bn_mp_radix_smap.c in Sources */,
+ F9FD312A0CC1AD070073837D /* bn_mp_read_radix.c in Sources */,
+ F9FD312B0CC1AD070073837D /* bn_mp_rshd.c in Sources */,
+ F9FD312C0CC1AD070073837D /* bn_mp_set.c in Sources */,
+ F9FD312D0CC1AD070073837D /* bn_mp_shrink.c in Sources */,
+ F9FD312E0CC1AD070073837D /* bn_mp_sqr.c in Sources */,
+ F9FD312F0CC1AD070073837D /* bn_mp_sqrt.c in Sources */,
+ F9FD31300CC1AD070073837D /* bn_mp_sub.c in Sources */,
+ F9FD31310CC1AD070073837D /* bn_mp_sub_d.c in Sources */,
+ F9FD31320CC1AD070073837D /* bn_mp_to_unsigned_bin_n.c in Sources */,
+ F9FD31330CC1AD070073837D /* bn_mp_to_unsigned_bin.c in Sources */,
+ F9FD31340CC1AD070073837D /* bn_mp_toom_mul.c in Sources */,
+ F9FD31350CC1AD070073837D /* bn_mp_toom_sqr.c in Sources */,
+ F9FD31360CC1AD070073837D /* bn_mp_toradix_n.c in Sources */,
+ F9FD31370CC1AD070073837D /* bn_mp_unsigned_bin_size.c in Sources */,
+ F9FD31380CC1AD070073837D /* bn_mp_xor.c in Sources */,
+ F9FD31390CC1AD070073837D /* bn_mp_zero.c in Sources */,
+ F9FD313A0CC1AD070073837D /* bn_reverse.c in Sources */,
+ F9FD313B0CC1AD070073837D /* bn_s_mp_add.c in Sources */,
+ F9FD313C0CC1AD070073837D /* bn_s_mp_mul_digs.c in Sources */,
+ F9FD313D0CC1AD070073837D /* bn_s_mp_sqr.c in Sources */,
+ F9FD313E0CC1AD070073837D /* bn_s_mp_sub.c in Sources */,
+ F9FD313F0CC1AD070073837D /* bncore.c in Sources */,
+ F9FD31400CC1AD070073837D /* tclMacOSXBundle.c in Sources */,
+ F9FD31410CC1AD070073837D /* tclMacOSXFCmd.c in Sources */,
+ F9FD31420CC1AD070073837D /* tclMacOSXNotify.c in Sources */,
+ F9FD31430CC1AD070073837D /* tclLoadDyld.c in Sources */,
+ F9FD31440CC1AD070073837D /* tclUnixChan.c in Sources */,
+ F9FD31450CC1AD070073837D /* tclUnixCompat.c in Sources */,
+ F9FD31460CC1AD070073837D /* tclUnixEvent.c in Sources */,
+ F9FD31470CC1AD070073837D /* tclUnixFCmd.c in Sources */,
+ F9FD31480CC1AD070073837D /* tclUnixFile.c in Sources */,
+ F9FD31490CC1AD070073837D /* tclUnixInit.c in Sources */,
+ F9FD314A0CC1AD070073837D /* tclUnixNotfy.c in Sources */,
+ F9FD314B0CC1AD070073837D /* tclUnixPipe.c in Sources */,
+ F9FD314C0CC1AD070073837D /* tclUnixSock.c in Sources */,
+ F9FD314D0CC1AD070073837D /* tclUnixThrd.c in Sources */,
+ F9FD314E0CC1AD070073837D /* tclUnixTime.c in Sources */,
+ F9FD31E20CC1AD070073837D /* tclDTrace.d in Sources */,
+ F9FD314F0CC1AD070073837D /* tk3d.c in Sources */,
+ F9FD31500CC1AD070073837D /* tkArgv.c in Sources */,
+ F9FD31510CC1AD070073837D /* tkAtom.c in Sources */,
+ F9FD31520CC1AD070073837D /* tkBind.c in Sources */,
+ F9FD31530CC1AD070073837D /* tkBitmap.c in Sources */,
+ F9152B0A0EAF8A5700CD5C7B /* tkBusy.c in Sources */,
+ F9FD31540CC1AD070073837D /* tkButton.c in Sources */,
+ F9FD31550CC1AD070073837D /* tkCanvArc.c in Sources */,
+ F9FD31560CC1AD070073837D /* tkCanvas.c in Sources */,
+ F9FD31570CC1AD070073837D /* tkCanvBmap.c in Sources */,
+ F9FD31580CC1AD070073837D /* tkCanvImg.c in Sources */,
+ F9FD31590CC1AD070073837D /* tkCanvLine.c in Sources */,
+ F9FD315A0CC1AD070073837D /* tkCanvPoly.c in Sources */,
+ F9FD315B0CC1AD070073837D /* tkCanvPs.c in Sources */,
+ F9FD315C0CC1AD070073837D /* tkCanvText.c in Sources */,
+ F9FD315D0CC1AD070073837D /* tkCanvUtil.c in Sources */,
+ F9FD315E0CC1AD070073837D /* tkCanvWind.c in Sources */,
+ F9FD315F0CC1AD070073837D /* tkClipboard.c in Sources */,
+ F9FD31600CC1AD070073837D /* tkCmds.c in Sources */,
+ F9FD31610CC1AD070073837D /* tkColor.c in Sources */,
+ F9FD31620CC1AD070073837D /* tkConfig.c in Sources */,
+ F9FD31630CC1AD070073837D /* tkConsole.c in Sources */,
+ F9FD31640CC1AD070073837D /* tkCursor.c in Sources */,
+ F9FD31650CC1AD070073837D /* tkEntry.c in Sources */,
+ F9FD31660CC1AD070073837D /* tkError.c in Sources */,
+ F9FD31670CC1AD070073837D /* tkEvent.c in Sources */,
+ F9FD31680CC1AD070073837D /* tkFileFilter.c in Sources */,
+ F9FD31690CC1AD070073837D /* tkFocus.c in Sources */,
+ F9FD316A0CC1AD070073837D /* tkFont.c in Sources */,
+ F9FD316B0CC1AD070073837D /* tkFrame.c in Sources */,
+ F9FD316C0CC1AD070073837D /* tkGC.c in Sources */,
+ F9FD316D0CC1AD070073837D /* tkGeometry.c in Sources */,
+ F9FD316E0CC1AD070073837D /* tkGet.c in Sources */,
+ F9FD316F0CC1AD070073837D /* tkGrab.c in Sources */,
+ F9FD31700CC1AD070073837D /* tkGrid.c in Sources */,
+ F9FD31710CC1AD070073837D /* tkImage.c in Sources */,
+ F9FD31720CC1AD070073837D /* tkImgBmap.c in Sources */,
+ F9FD31730CC1AD070073837D /* tkImgGIF.c in Sources */,
+ F92EE8D30E62F939001A6E80 /* tkImgPhInstance.c in Sources */,
+ F9FD31740CC1AD070073837D /* tkImgPhoto.c in Sources */,
+ F9DD99BE0F07DF850018B2E4 /* tkImgPNG.c in Sources */,
+ F9FD31750CC1AD070073837D /* tkImgPPM.c in Sources */,
+ F9FD31760CC1AD070073837D /* tkListbox.c in Sources */,
+ F9FD31770CC1AD070073837D /* tkMacWinMenu.c in Sources */,
+ F9FD31780CC1AD070073837D /* tkMain.c in Sources */,
+ F9FD31790CC1AD070073837D /* tkMenu.c in Sources */,
+ F9FD317A0CC1AD070073837D /* tkMenubutton.c in Sources */,
+ F9FD317B0CC1AD070073837D /* tkMenuDraw.c in Sources */,
+ F9FD317C0CC1AD070073837D /* tkMessage.c in Sources */,
+ F9FD317D0CC1AD070073837D /* tkObj.c in Sources */,
+ F9FD317E0CC1AD070073837D /* tkOldConfig.c in Sources */,
+ F9FD317F0CC1AD070073837D /* tkOldTest.c in Sources */,
+ F9FD31800CC1AD070073837D /* tkOption.c in Sources */,
+ F9FD31810CC1AD070073837D /* tkPack.c in Sources */,
+ F9FD31820CC1AD070073837D /* tkPanedWindow.c in Sources */,
+ F9FD31830CC1AD070073837D /* tkPlace.c in Sources */,
+ F9FD31850CC1AD070073837D /* tkRectOval.c in Sources */,
+ F9FD31860CC1AD070073837D /* tkScale.c in Sources */,
+ F9FD31870CC1AD070073837D /* tkScrollbar.c in Sources */,
+ F9FD31880CC1AD070073837D /* tkSelect.c in Sources */,
+ F9FD31890CC1AD070073837D /* tkSquare.c in Sources */,
+ F9FD318A0CC1AD070073837D /* tkStubInit.c in Sources */,
+ F9FD318B0CC1AD070073837D /* tkStubLib.c in Sources */,
+ F9FD318C0CC1AD070073837D /* tkStyle.c in Sources */,
+ F9FD318D0CC1AD070073837D /* tkTest.c in Sources */,
+ F9FD318E0CC1AD070073837D /* tkText.c in Sources */,
+ F9FD318F0CC1AD070073837D /* tkTextBTree.c in Sources */,
+ F9FD31900CC1AD070073837D /* tkTextDisp.c in Sources */,
+ F9FD31910CC1AD070073837D /* tkTextImage.c in Sources */,
+ F9FD31920CC1AD070073837D /* tkTextIndex.c in Sources */,
+ F9FD31930CC1AD070073837D /* tkTextMark.c in Sources */,
+ F9FD31940CC1AD070073837D /* tkTextTag.c in Sources */,
+ F9FD31950CC1AD070073837D /* tkTextWind.c in Sources */,
+ F9FD31960CC1AD070073837D /* tkTrig.c in Sources */,
+ F9FD31970CC1AD070073837D /* tkUndo.c in Sources */,
+ F9FD31980CC1AD070073837D /* tkUtil.c in Sources */,
+ F9FD31990CC1AD070073837D /* tkVisual.c in Sources */,
+ F9FD319A0CC1AD070073837D /* tkWindow.c in Sources */,
+ F9FD319B0CC1AD070073837D /* ttkBlink.c in Sources */,
+ F9FD319C0CC1AD070073837D /* ttkButton.c in Sources */,
+ F9FD319D0CC1AD070073837D /* ttkCache.c in Sources */,
+ F9FD319E0CC1AD070073837D /* ttkClamTheme.c in Sources */,
+ F9FD319F0CC1AD070073837D /* ttkClassicTheme.c in Sources */,
+ F9FD31A00CC1AD070073837D /* ttkDefaultTheme.c in Sources */,
+ F9FD31A10CC1AD070073837D /* ttkElements.c in Sources */,
+ F9FD31A20CC1AD070073837D /* ttkEntry.c in Sources */,
+ F9FD31A30CC1AD070073837D /* ttkFrame.c in Sources */,
+ F9FD31A40CC1AD070073837D /* ttkImage.c in Sources */,
+ F9FD31A50CC1AD070073837D /* ttkInit.c in Sources */,
+ F9FD31A60CC1AD070073837D /* ttkLabel.c in Sources */,
+ F9FD31A70CC1AD070073837D /* ttkLayout.c in Sources */,
+ F9FD31A80CC1AD070073837D /* ttkManager.c in Sources */,
+ F9FD31A90CC1AD070073837D /* ttkNotebook.c in Sources */,
+ F9FD31AA0CC1AD070073837D /* ttkPanedwindow.c in Sources */,
+ F9FD31AB0CC1AD070073837D /* ttkProgress.c in Sources */,
+ F9FD31AC0CC1AD070073837D /* ttkScale.c in Sources */,
+ F9FD31AD0CC1AD070073837D /* ttkScroll.c in Sources */,
+ F9FD31AE0CC1AD070073837D /* ttkScrollbar.c in Sources */,
+ F9FD31AF0CC1AD070073837D /* ttkSeparator.c in Sources */,
+ F9FD31B00CC1AD070073837D /* ttkSquare.c in Sources */,
+ F9FD31B10CC1AD070073837D /* ttkState.c in Sources */,
+ F9FD31B20CC1AD070073837D /* ttkStubInit.c in Sources */,
+ F9FD31B30CC1AD070073837D /* ttkStubLib.c in Sources */,
+ F9FD31B40CC1AD070073837D /* ttkTagSet.c in Sources */,
+ F9FD31B50CC1AD070073837D /* ttkTheme.c in Sources */,
+ F9FD31B60CC1AD070073837D /* ttkTrace.c in Sources */,
+ F9FD31B70CC1AD070073837D /* ttkTrack.c in Sources */,
+ F9FD31B80CC1AD070073837D /* ttkTreeview.c in Sources */,
+ F9FD31B90CC1AD070073837D /* ttkWidget.c in Sources */,
+ F9FD31DA0CC1AD070073837D /* tkAppInit.c in Sources */,
+ F9FD32020CC1ADB70073837D /* tkUnix.c in Sources */,
+ F9FD31DB0CC1AD070073837D /* tkUnix3d.c in Sources */,
+ F9FD320A0CC1ADB70073837D /* tkUnixButton.c in Sources */,
+ F9FD32090CC1ADB70073837D /* tkUnixColor.c in Sources */,
+ F9FD32040CC1ADB70073837D /* tkUnixConfig.c in Sources */,
+ F9FD31F80CC1ADB70073837D /* tkUnixCursor.c in Sources */,
+ F9FD32060CC1ADB70073837D /* tkUnixDialog.c in Sources */,
+ F9FD32050CC1ADB70073837D /* tkUnixDraw.c in Sources */,
+ F9FD31FD0CC1ADB70073837D /* tkUnixEmbed.c in Sources */,
+ F9FD32080CC1ADB70073837D /* tkUnixEvent.c in Sources */,
+ F9FD31FF0CC1ADB70073837D /* tkUnixFocus.c in Sources */,
+ F9FD31FC0CC1ADB70073837D /* tkUnixInit.c in Sources */,
+ F9FD31FA0CC1ADB70073837D /* tkUnixKey.c in Sources */,
+ F9FD32030CC1ADB70073837D /* tkUnixMenu.c in Sources */,
+ F9FD320B0CC1ADB70073837D /* tkUnixMenubu.c in Sources */,
+ F9FD32010CC1ADB70073837D /* tkUnixRFont.c in Sources */,
+ F9FD31DC0CC1AD070073837D /* tkUnixScale.c in Sources */,
+ F9FD320C0CC1ADB70073837D /* tkUnixScrlbr.c in Sources */,
+ F9FD32070CC1ADB70073837D /* tkUnixSelect.c in Sources */,
+ F9FD31FE0CC1ADB70073837D /* tkUnixSend.c in Sources */,
+ F9FD32000CC1ADB70073837D /* tkUnixWm.c in Sources */,
+ F9FD31FB0CC1ADB70073837D /* tkUnixXId.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ F90E36D50F3B5C8400810A10 /* DebugNoGC */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tk-Debug.xcconfig */;
+ buildSettings = {
+ ARCHS = (
+ "$(NATIVE_ARCH_64_BIT)",
+ "$(NATIVE_ARCH_32_BIT)",
+ );
+ CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = unsupported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ };
+ name = DebugNoGC;
+ };
+ F90E36D60F3B5C8400810A10 /* DebugNoGC */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = DebugNoGC;
+ };
+ F90E36D70F3B5C8400810A10 /* DebugNoGC */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = DebugNoGC;
+ };
+ F90E36D80F3B5C8400810A10 /* DebugNoGC */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)";
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "__private_extern__=extern",
+ "$(GCC_PREPROCESSOR_DEFINITIONS)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = DebugNoGC;
+ };
+ F91BCC4F093152310042A6BF /* ReleaseUniversal */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = ReleaseUniversal;
+ };
+ F91BCC50093152310042A6BF /* ReleaseUniversal */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = ReleaseUniversal;
+ };
+ F91BCC51093152310042A6BF /* ReleaseUniversal */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tk-Release.xcconfig */;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ PREBINDING = NO;
+ };
+ name = ReleaseUniversal;
+ };
+ F93084370BB93D2800CD0B9E /* DebugMemCompile */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = DebugMemCompile;
+ };
+ F93084380BB93D2800CD0B9E /* DebugMemCompile */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = DebugMemCompile;
+ };
+ F93084390BB93D2800CD0B9E /* DebugMemCompile */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = DebugMemCompile;
+ };
+ F930843A0BB93D2800CD0B9E /* DebugMemCompile */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tk-Debug.xcconfig */;
+ buildSettings = {
+ ARCHS = (
+ "$(NATIVE_ARCH_64_BIT)",
+ "$(NATIVE_ARCH_32_BIT)",
+ );
+ CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --enable-symbols=all";
+ CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ };
+ name = DebugMemCompile;
+ };
+ F9359B250DF212DA00E04F67 /* DebugGCov */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tk-Debug.xcconfig */;
+ buildSettings = {
+ ARCHS = (
+ "$(NATIVE_ARCH_64_BIT)",
+ "$(NATIVE_ARCH_32_BIT)",
+ );
+ CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_GENERATE_TEST_COVERAGE_FILES = YES;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ ONLY_ACTIVE_ARCH = YES;
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS)",
+ "-lgcov",
+ );
+ PREBINDING = NO;
+ };
+ name = DebugGCov;
+ };
+ F9359B260DF212DA00E04F67 /* DebugGCov */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = DebugGCov;
+ };
+ F9359B270DF212DA00E04F67 /* DebugGCov */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = DebugGCov;
+ };
+ F9359B280DF212DA00E04F67 /* DebugGCov */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = DebugGCov;
+ };
+ F95CC8AC09158F3100EA5ACE /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = Debug;
+ };
+ F95CC8AD09158F3100EA5ACE /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = Release;
+ };
+ F95CC8AE09158F3100EA5ACE /* DebugNoFixAndContinue */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = DebugNoFixAndContinue;
+ };
+ F95CC8B109158F3100EA5ACE /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)";
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "__private_extern__=extern",
+ "$(GCC_PREPROCESSOR_DEFINITIONS)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = Debug;
+ };
+ F95CC8B209158F3100EA5ACE /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = Release;
+ };
+ F95CC8B309158F3100EA5ACE /* DebugNoFixAndContinue */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = DebugNoFixAndContinue;
+ };
+ F95CC8B609158F3100EA5ACE /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tk-Debug.xcconfig */;
+ buildSettings = {
+ ARCHS = (
+ "$(NATIVE_ARCH_64_BIT)",
+ "$(NATIVE_ARCH_32_BIT)",
+ );
+ CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ };
+ name = Debug;
+ };
+ F95CC8B709158F3100EA5ACE /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tk-Release.xcconfig */;
+ buildSettings = {
+ ARCHS = (
+ "$(NATIVE_ARCH_64_BIT)",
+ "$(NATIVE_ARCH_32_BIT)",
+ );
+ CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ };
+ name = Release;
+ };
+ F95CC8B809158F3100EA5ACE /* DebugNoFixAndContinue */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tk-Debug.xcconfig */;
+ buildSettings = {
+ ARCHS = (
+ "$(NATIVE_ARCH_64_BIT)",
+ "$(NATIVE_ARCH_32_BIT)",
+ );
+ CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ };
+ name = DebugNoFixAndContinue;
+ };
+ F97258A90A86873D00096C78 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)";
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "__private_extern__=extern",
+ "$(GCC_PREPROCESSOR_DEFINITIONS)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = Debug;
+ };
+ F97258AA0A86873D00096C78 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = Release;
+ };
+ F97258AB0A86873D00096C78 /* DebugNoFixAndContinue */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = DebugNoFixAndContinue;
+ };
+ F97258AC0A86873D00096C78 /* ReleaseUniversal */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)";
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = ReleaseUniversal;
+ };
+ F97AED1B0B660B2100310EA2 /* Debug64bit */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = Debug64bit;
+ };
+ F97AED1C0B660B2100310EA2 /* Debug64bit */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = Debug64bit;
+ };
+ F97AED1D0B660B2100310EA2 /* Debug64bit */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = Debug64bit;
+ };
+ F97AED1E0B660B2100310EA2 /* Debug64bit */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tk-Debug.xcconfig */;
+ buildSettings = {
+ ARCHS = "$(NATIVE_ARCH_64_BIT)";
+ CONFIGURE_ARGS = "--enable-64bit $(CONFIGURE_ARGS)";
+ CPPFLAGS = "-arch $(NATIVE_ARCH_64_BIT) $(CPPFLAGS)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ PREBINDING = NO;
+ };
+ name = Debug64bit;
+ };
+ F987512F0DE7B57E00B1C9EC /* DebugNoCF */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tk-Debug.xcconfig */;
+ buildSettings = {
+ ARCHS = (
+ "$(NATIVE_ARCH_64_BIT)",
+ "$(NATIVE_ARCH_32_BIT)",
+ );
+ CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --disable-corefoundation";
+ CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ };
+ name = DebugNoCF;
+ };
+ F98751300DE7B57E00B1C9EC /* DebugNoCF */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --enable-corefoundation";
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = DebugNoCF;
+ };
+ F98751310DE7B57E00B1C9EC /* DebugNoCF */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --enable-corefoundation";
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = DebugNoCF;
+ };
+ F98751320DE7B57E00B1C9EC /* DebugNoCF */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = DebugNoCF;
+ };
+ F98751330DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tk-Debug.xcconfig */;
+ buildSettings = {
+ ARCHS = (
+ "$(NATIVE_ARCH_64_BIT)",
+ "$(NATIVE_ARCH_32_BIT)",
+ );
+ CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --disable-threads --disable-corefoundation";
+ CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ };
+ name = DebugNoCFUnthreaded;
+ };
+ F98751340DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --enable-corefoundation";
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = DebugNoCFUnthreaded;
+ };
+ F98751350DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --enable-corefoundation";
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = DebugNoCFUnthreaded;
+ };
+ F98751360DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = DebugNoCFUnthreaded;
+ };
+ F9988AB10D814C6500B6B03B /* Debug gcc40 */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tk-Debug.xcconfig */;
+ buildSettings = {
+ ARCHS = (
+ "$(NATIVE_ARCH_64_BIT)",
+ "$(NATIVE_ARCH_32_BIT)",
+ );
+ CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ GCC_VERSION = 4.0;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ };
+ name = "Debug gcc40";
+ };
+ F9988AB20D814C6500B6B03B /* Debug gcc40 */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = "Debug gcc40";
+ };
+ F9988AB30D814C6500B6B03B /* Debug gcc40 */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)";
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "__private_extern__=extern",
+ "$(GCC_PREPROCESSOR_DEFINITIONS)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = "Debug gcc40";
+ };
+ F9988AB40D814C6500B6B03B /* Debug gcc40 */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)";
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "__private_extern__=extern",
+ "$(GCC_PREPROCESSOR_DEFINITIONS)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = "Debug gcc40";
+ };
+ F9988AB50D814C7500B6B03B /* Debug llvm-gcc */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tk-Debug.xcconfig */;
+ buildSettings = {
+ ARCHS = (
+ "$(NATIVE_ARCH_64_BIT)",
+ "$(NATIVE_ARCH_32_BIT)",
+ );
+ CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
+ GCC = "llvm-gcc";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ GCC_VERSION = com.apple.compilers.llvmgcc42;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ };
+ name = "Debug llvm-gcc";
+ };
+ F9988AB60D814C7500B6B03B /* Debug llvm-gcc */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = "Debug llvm-gcc";
+ };
+ F9988AB70D814C7500B6B03B /* Debug llvm-gcc */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)";
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "__private_extern__=extern",
+ "$(GCC_PREPROCESSOR_DEFINITIONS)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = "Debug llvm-gcc";
+ };
+ F9988AB80D814C7500B6B03B /* Debug llvm-gcc */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)";
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "__private_extern__=extern",
+ "$(GCC_PREPROCESSOR_DEFINITIONS)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = "Debug llvm-gcc";
+ };
+ F9988BB10D81586D00B6B03B /* ReleaseUniversal gcc40 */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tk-Release.xcconfig */;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ GCC_VERSION = 4.0;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ PREBINDING = NO;
+ };
+ name = "ReleaseUniversal gcc40";
+ };
+ F9988BB20D81586D00B6B03B /* ReleaseUniversal gcc40 */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = "ReleaseUniversal gcc40";
+ };
+ F9988BB30D81586D00B6B03B /* ReleaseUniversal gcc40 */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = "ReleaseUniversal gcc40";
+ };
+ F9988BB40D81586D00B6B03B /* ReleaseUniversal gcc40 */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)";
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = "ReleaseUniversal gcc40";
+ };
+ F9988BB50D81587400B6B03B /* ReleaseUniversal llvm-gcc */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tk-Release.xcconfig */;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)";
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ GCC = "llvm-gcc";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ GCC_OPTIMIZATION_LEVEL = 4;
+ GCC_VERSION = com.apple.compilers.llvmgcc42;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ PREBINDING = NO;
+ };
+ name = "ReleaseUniversal llvm-gcc";
+ };
+ F9988BB60D81587400B6B03B /* ReleaseUniversal llvm-gcc */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = "ReleaseUniversal llvm-gcc";
+ };
+ F9988BB70D81587400B6B03B /* ReleaseUniversal llvm-gcc */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = "ReleaseUniversal llvm-gcc";
+ };
+ F9988BB80D81587400B6B03B /* ReleaseUniversal llvm-gcc */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)";
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = "ReleaseUniversal llvm-gcc";
+ };
+ F99EE73B0BE835310060D4AF /* DebugUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = DebugUnthreaded;
+ };
+ F99EE73C0BE835310060D4AF /* DebugLeaks */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = DebugLeaks;
+ };
+ F99EE73D0BE835310060D4AF /* DebugUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = DebugUnthreaded;
+ };
+ F99EE73E0BE835310060D4AF /* DebugLeaks */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = DebugLeaks;
+ };
+ F99EE73F0BE835310060D4AF /* DebugUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = DebugUnthreaded;
+ };
+ F99EE7400BE835310060D4AF /* DebugLeaks */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = DebugLeaks;
+ };
+ F99EE7410BE835310060D4AF /* DebugUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tk-Debug.xcconfig */;
+ buildSettings = {
+ ARCHS = (
+ "$(NATIVE_ARCH_64_BIT)",
+ "$(NATIVE_ARCH_32_BIT)",
+ );
+ CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --disable-threads";
+ CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ };
+ name = DebugUnthreaded;
+ };
+ F99EE7420BE835310060D4AF /* DebugLeaks */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tk-Debug.xcconfig */;
+ buildSettings = {
+ ARCHS = (
+ "$(NATIVE_ARCH_64_BIT)",
+ "$(NATIVE_ARCH_32_BIT)",
+ );
+ CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = unsupported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ PURIFY,
+ "$(GCC_PREPROCESSOR_DEFINITIONS)",
+ );
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ };
+ name = DebugLeaks;
+ };
+ F9EEED960C2FEFD300396116 /* ReleaseUniversal10.5SDK */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = ReleaseUniversal10.5SDK;
+ };
+ F9EEED970C2FEFD300396116 /* ReleaseUniversal10.5SDK */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = ReleaseUniversal10.5SDK;
+ };
+ F9EEED980C2FEFD300396116 /* ReleaseUniversal10.5SDK */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)";
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = ReleaseUniversal10.5SDK;
+ };
+ F9EEED990C2FEFD300396116 /* ReleaseUniversal10.5SDK */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tk-Release.xcconfig */;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)";
+ CPPFLAGS = "-isysroot $(SDKROOT) $(CPPFLAGS)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ PREBINDING = NO;
+ SDKROOT = macosx10.5;
+ };
+ name = ReleaseUniversal10.5SDK;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ F95CC8AB09158F3100EA5ACE /* Build configuration list for PBXNativeTarget "Tk" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F95CC8AC09158F3100EA5ACE /* Debug */,
+ F9988AB60D814C7500B6B03B /* Debug llvm-gcc */,
+ F9988AB20D814C6500B6B03B /* Debug gcc40 */,
+ F90E36D60F3B5C8400810A10 /* DebugNoGC */,
+ F95CC8AE09158F3100EA5ACE /* DebugNoFixAndContinue */,
+ F99EE73B0BE835310060D4AF /* DebugUnthreaded */,
+ F98751300DE7B57E00B1C9EC /* DebugNoCF */,
+ F98751340DE7B5A200B1C9EC /* DebugNoCFUnthreaded */,
+ F93084370BB93D2800CD0B9E /* DebugMemCompile */,
+ F99EE73C0BE835310060D4AF /* DebugLeaks */,
+ F9359B260DF212DA00E04F67 /* DebugGCov */,
+ F97AED1B0B660B2100310EA2 /* Debug64bit */,
+ F95CC8AD09158F3100EA5ACE /* Release */,
+ F91BCC4F093152310042A6BF /* ReleaseUniversal */,
+ F9988BB60D81587400B6B03B /* ReleaseUniversal llvm-gcc */,
+ F9988BB20D81586D00B6B03B /* ReleaseUniversal gcc40 */,
+ F9EEED960C2FEFD300396116 /* ReleaseUniversal10.5SDK */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ F95CC8B009158F3100EA5ACE /* Build configuration list for PBXNativeTarget "tktest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F95CC8B109158F3100EA5ACE /* Debug */,
+ F9988AB70D814C7500B6B03B /* Debug llvm-gcc */,
+ F9988AB30D814C6500B6B03B /* Debug gcc40 */,
+ F90E36D70F3B5C8400810A10 /* DebugNoGC */,
+ F95CC8B309158F3100EA5ACE /* DebugNoFixAndContinue */,
+ F99EE73D0BE835310060D4AF /* DebugUnthreaded */,
+ F98751310DE7B57E00B1C9EC /* DebugNoCF */,
+ F98751350DE7B5A200B1C9EC /* DebugNoCFUnthreaded */,
+ F93084380BB93D2800CD0B9E /* DebugMemCompile */,
+ F99EE73E0BE835310060D4AF /* DebugLeaks */,
+ F9359B270DF212DA00E04F67 /* DebugGCov */,
+ F97AED1C0B660B2100310EA2 /* Debug64bit */,
+ F95CC8B209158F3100EA5ACE /* Release */,
+ F91BCC50093152310042A6BF /* ReleaseUniversal */,
+ F9988BB70D81587400B6B03B /* ReleaseUniversal llvm-gcc */,
+ F9988BB30D81586D00B6B03B /* ReleaseUniversal gcc40 */,
+ F9EEED970C2FEFD300396116 /* ReleaseUniversal10.5SDK */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ F95CC8B509158F3100EA5ACE /* Build configuration list for PBXProject "Tk" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F95CC8B609158F3100EA5ACE /* Debug */,
+ F9988AB50D814C7500B6B03B /* Debug llvm-gcc */,
+ F9988AB10D814C6500B6B03B /* Debug gcc40 */,
+ F90E36D50F3B5C8400810A10 /* DebugNoGC */,
+ F95CC8B809158F3100EA5ACE /* DebugNoFixAndContinue */,
+ F99EE7410BE835310060D4AF /* DebugUnthreaded */,
+ F987512F0DE7B57E00B1C9EC /* DebugNoCF */,
+ F98751330DE7B5A200B1C9EC /* DebugNoCFUnthreaded */,
+ F930843A0BB93D2800CD0B9E /* DebugMemCompile */,
+ F99EE7420BE835310060D4AF /* DebugLeaks */,
+ F9359B250DF212DA00E04F67 /* DebugGCov */,
+ F97AED1E0B660B2100310EA2 /* Debug64bit */,
+ F95CC8B709158F3100EA5ACE /* Release */,
+ F91BCC51093152310042A6BF /* ReleaseUniversal */,
+ F9988BB50D81587400B6B03B /* ReleaseUniversal llvm-gcc */,
+ F9988BB10D81586D00B6B03B /* ReleaseUniversal gcc40 */,
+ F9EEED990C2FEFD300396116 /* ReleaseUniversal10.5SDK */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ F97258A80A86873D00096C78 /* Build configuration list for PBXNativeTarget "tktest-X11" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F97258A90A86873D00096C78 /* Debug */,
+ F9988AB80D814C7500B6B03B /* Debug llvm-gcc */,
+ F9988AB40D814C6500B6B03B /* Debug gcc40 */,
+ F90E36D80F3B5C8400810A10 /* DebugNoGC */,
+ F97258AB0A86873D00096C78 /* DebugNoFixAndContinue */,
+ F99EE73F0BE835310060D4AF /* DebugUnthreaded */,
+ F98751320DE7B57E00B1C9EC /* DebugNoCF */,
+ F98751360DE7B5A200B1C9EC /* DebugNoCFUnthreaded */,
+ F93084390BB93D2800CD0B9E /* DebugMemCompile */,
+ F99EE7400BE835310060D4AF /* DebugLeaks */,
+ F9359B280DF212DA00E04F67 /* DebugGCov */,
+ F97AED1D0B660B2100310EA2 /* Debug64bit */,
+ F97258AA0A86873D00096C78 /* Release */,
+ F97258AC0A86873D00096C78 /* ReleaseUniversal */,
+ F9988BB80D81587400B6B03B /* ReleaseUniversal llvm-gcc */,
+ F9988BB40D81586D00B6B03B /* ReleaseUniversal gcc40 */,
+ F9EEED980C2FEFD300396116 /* ReleaseUniversal10.5SDK */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
+}
diff --git a/tk8.6/macosx/Tk.xcodeproj/default.pbxuser b/tk8.6/macosx/Tk.xcodeproj/default.pbxuser
new file mode 100644
index 0000000..30bcecb
--- /dev/null
+++ b/tk8.6/macosx/Tk.xcodeproj/default.pbxuser
@@ -0,0 +1,399 @@
+// !$*UTF8*$!
+{
+ 08FB7793FE84155DC02AAC07 /* Project object */ = {
+ activeBuildConfigurationName = Debug;
+ activeExecutable = F9E61D1C090A4282002B3151 /* Wish */;
+ activeTarget = F9E61D16090A3E94002B3151 /* Tk */;
+ codeSenseManager = F944EB9D08F798180049FDD4 /* Code sense */;
+ executables = (
+ F9E61D1C090A4282002B3151 /* Wish */,
+ F944EB8F08F798100049FDD4 /* tktest */,
+ F9FD31F50CC1AD070073837D /* tktest-X11 */,
+ );
+ perUserDictionary = {
+ com.apple.ide.smrt.PBXUserSmartGroupsKey.Rev10 = <040b73747265616d747970656481e8038401408484840e4e534d757461626c654172726179008484074e534172726179008484084e534f626a65637400858401690192848484134e534d757461626c6544696374696f6e6172790084840c4e5344696374696f6e6172790095960792848484084e53537472696e67019584012b046e616d658692849a9a14496d706c656d656e746174696f6e2046696c65738692849a9a195042585472616e7369656e744c6f636174696f6e4174546f708692849a9a06626f74746f6d8692849a9a0b707265666572656e63657386928497960892849a9a0669734c6561668692848484084e534e756d626572008484074e5356616c7565009584012a849696008692849a9a04726f6f748692849a9a093c50524f4a4543543e8692849a9a09726563757273697665869284a29da496018692849a9a05696d6167658692849a9a0b536d617274466f6c6465728692849a9a0763616e536176658692a892849a9a1250425850726f6a65637453636f70654b65798692849a9a035945538692849a9a0572656765788692849a9a065c2e286329248692849a9a07666e6d617463688692849a9a00868692849a9a146162736f6c75746550617468546f42756e646c658692849a9a008692849a9a0b6465736372697074696f6e8692849a9a103c6e6f206465736372697074696f6e3e8692849a9a08676c6f62616c49448692849a9a183143433045413430303433353045463930303434343130428692849a9a03636c7a8692849a9a1550425846696c656e616d65536d61727447726f7570868686>;
+ };
+ sourceControlManager = F944EB9C08F798180049FDD4 /* Source Control */;
+ userBuildSettings = {
+ SYMROOT = "${SRCROOT}/../../build/tk";
+ TCL_SRCROOT = "${SRCROOT}/../../tcl";
+ TK_SRCROOT = "${SRCROOT}/../../tk";
+ };
+ };
+ 8DD76FA90486AB0100D96B5E /* tktest */ = {
+ activeExec = 0;
+ executables = (
+ F944EB8F08F798100049FDD4 /* tktest */,
+ );
+ };
+ F944EB8F08F798100049FDD4 /* tktest */ = {
+ isa = PBXExecutable;
+ activeArgIndices = (
+ YES,
+ NO,
+ NO,
+ NO,
+ NO,
+ NO,
+ NO,
+ );
+ argumentStrings = (
+ "${TK_SRCROOT}/library/demos/widget",
+ "${TK_SRCROOT}/tests/all.tcl",
+ "${TK_SRCROOT}/tests/ttk/all.tcl",
+ "-geometry +0+0",
+ "-singleproc 1",
+ "-verbose \"bet\"",
+ "-skip window-2.9",
+ );
+ autoAttachOnCrash = 1;
+ breakpointsEnabled = 1;
+ configStateDict = {
+ "PBXLSLaunchAction-0" = {
+ PBXLSLaunchAction = 0;
+ PBXLSLaunchStartAction = 1;
+ PBXLSLaunchStdioStyle = 2;
+ PBXLSLaunchStyle = 0;
+ class = PBXLSRunLaunchConfig;
+ displayName = "Executable Runner";
+ identifier = com.apple.Xcode.launch.runConfig;
+ remoteHostInfo = "";
+ startActionInfo = "";
+ };
+ "PBXLSLaunchAction-1" = {
+ PBXLSLaunchAction = 1;
+ PBXLSLaunchStartAction = 1;
+ PBXLSLaunchStdioStyle = 2;
+ PBXLSLaunchStyle = 0;
+ class = PBXGDB_LaunchConfig;
+ displayName = GDB;
+ identifier = com.apple.Xcode.launch.GDBMI_Config;
+ remoteHostInfo = "";
+ startActionInfo = "";
+ };
+ };
+ customDataFormattersEnabled = 1;
+ dataTipCustomDataFormattersEnabled = 1;
+ dataTipShowTypeColumn = 1;
+ dataTipSortType = 0;
+ debuggerPlugin = GDBDebugging;
+ disassemblyDisplayState = 0;
+ dylibVariantSuffix = "";
+ enableDebugStr = 0;
+ environmentEntries = (
+ {
+ active = YES;
+ name = TCL_LIBRARY;
+ value = "${TCL_SRCROOT}/library";
+ },
+ {
+ active = YES;
+ name = TK_LIBRARY;
+ value = "${TK_SRCROOT}/library";
+ },
+ {
+ active = YES;
+ name = TCLLIBPATH;
+ value = /Library/Tcl;
+ },
+ {
+ active = YES;
+ name = TK_SRCROOT;
+ value = "${TK_SRCROOT}";
+ },
+ {
+ active = NO;
+ name = TK_CONSOLE;
+ value = 1;
+ },
+ {
+ active = NO;
+ name = DYLD_PRINT_LIBRARIES;
+ },
+ {
+ active = NO;
+ name = NSTraceEvents;
+ value = YES;
+ },
+ {
+ active = NO;
+ name = MallocBadFreeAbort;
+ value = 1;
+ },
+ {
+ active = NO;
+ name = MallocLogFile;
+ value = /tmp/malloc.log;
+ },
+ {
+ active = NO;
+ name = MallocStackLogging;
+ value = 1;
+ },
+ {
+ active = NO;
+ name = MallocStackLoggingNoCompact;
+ value = 1;
+ },
+ {
+ active = NO;
+ name = MallocPreScribble;
+ value = 1;
+ },
+ {
+ active = NO;
+ name = MallocScribble;
+ value = 1;
+ },
+ {
+ active = NO;
+ name = NSZombieEnabled;
+ value = YES;
+ },
+ {
+ active = NO;
+ name = NSDeallocateZombies;
+ value = YES;
+ },
+ {
+ active = NO;
+ name = NSAutoreleaseFreedObjectCheckEnabled;
+ value = YES;
+ },
+ {
+ active = NO;
+ name = NSEnableAutoreleasePool;
+ value = NO;
+ },
+ {
+ active = NO;
+ name = AUTO_LOG_ALL;
+ value = YES;
+ },
+ {
+ active = NO;
+ name = AUTO_LOG_NOISY;
+ value = YES;
+ },
+ {
+ active = NO;
+ name = AUTO_REFERENCE_COUNT_LOGGING;
+ value = YES;
+ },
+ );
+ executableSystemSymbolLevel = 0;
+ executableUserSymbolLevel = 0;
+ libgmallocEnabled = 0;
+ name = tktest;
+ showTypeColumn = 0;
+ sourceDirectories = (
+ );
+ };
+ F944EB9C08F798180049FDD4 /* Source Control */ = {
+ isa = PBXSourceControlManager;
+ fallbackIsa = XCSourceControlManager;
+ isSCMEnabled = 0;
+ repositoryNamesForRoots = {
+ .. = "";
+ };
+ scmConfiguration = {
+ CVSToolPath = /usr/bin/cvs;
+ CVSUseSSH = NO;
+ SubversionToolPath = /usr/bin/svn;
+ repositoryNamesForRoots = {
+ .. = "";
+ };
+ };
+ scmType = scm.cvs;
+ };
+ F944EB9D08F798180049FDD4 /* Code sense */ = {
+ isa = PBXCodeSenseManager;
+ indexTemplatePath = "";
+ };
+ F97258A50A86873C00096C78 /* tktest-X11 */ = {
+ activeExec = 0;
+ executables = (
+ F9FD31F50CC1AD070073837D /* tktest-X11 */,
+ );
+ };
+ F9E61D16090A3E94002B3151 /* Tk */ = {
+ activeExec = 0;
+ executables = (
+ F9E61D1C090A4282002B3151 /* Wish */,
+ );
+ };
+ F9E61D1C090A4282002B3151 /* Wish */ = {
+ isa = PBXExecutable;
+ activeArgIndices = (
+ YES,
+ );
+ argumentStrings = (
+ "${TK_SRCROOT}/library/demos/widget",
+ );
+ autoAttachOnCrash = 1;
+ breakpointsEnabled = 1;
+ configStateDict = {
+ "PBXLSLaunchAction-0" = {
+ PBXLSLaunchAction = 0;
+ PBXLSLaunchStartAction = 1;
+ PBXLSLaunchStdioStyle = 2;
+ PBXLSLaunchStyle = 0;
+ class = PBXLSRunLaunchConfig;
+ displayName = "Executable Runner";
+ identifier = com.apple.Xcode.launch.runConfig;
+ remoteHostInfo = "";
+ startActionInfo = "";
+ };
+ "PBXLSLaunchAction-1" = {
+ PBXLSLaunchAction = 1;
+ PBXLSLaunchStartAction = 1;
+ PBXLSLaunchStdioStyle = 2;
+ PBXLSLaunchStyle = 0;
+ class = PBXGDB_LaunchConfig;
+ displayName = GDB;
+ identifier = com.apple.Xcode.launch.GDBMI_Config;
+ remoteHostInfo = "";
+ startActionInfo = "";
+ };
+ };
+ customDataFormattersEnabled = 1;
+ dataTipCustomDataFormattersEnabled = 1;
+ dataTipShowTypeColumn = 1;
+ dataTipSortType = 0;
+ debuggerPlugin = GDBDebugging;
+ disassemblyDisplayState = 0;
+ dylibVariantSuffix = "";
+ enableDebugStr = 0;
+ environmentEntries = (
+ {
+ active = NO;
+ name = DYLD_PRINT_LIBRARIES;
+ },
+ );
+ executableSystemSymbolLevel = 0;
+ executableUserSymbolLevel = 0;
+ libgmallocEnabled = 0;
+ name = Wish;
+ showTypeColumn = 0;
+ sourceDirectories = (
+ );
+ };
+ F9FD31F50CC1AD070073837D /* tktest-X11 */ = {
+ isa = PBXExecutable;
+ activeArgIndices = (
+ YES,
+ NO,
+ NO,
+ NO,
+ NO,
+ NO,
+ NO,
+ );
+ argumentStrings = (
+ "${TK_SRCROOT}/library/demos/widget",
+ "${TK_SRCROOT}/tests/all.tcl",
+ "${TK_SRCROOT}/tests/ttk/all.tcl",
+ "-geometry +0+0",
+ "-singleproc 1",
+ "-verbose \"bet\"",
+ "-skip window-2.9",
+ );
+ autoAttachOnCrash = 1;
+ breakpointsEnabled = 1;
+ configStateDict = {
+ "PBXLSLaunchAction-0" = {
+ PBXLSLaunchAction = 0;
+ PBXLSLaunchStartAction = 1;
+ PBXLSLaunchStdioStyle = 2;
+ PBXLSLaunchStyle = 0;
+ class = PBXLSRunLaunchConfig;
+ displayName = "Executable Runner";
+ identifier = com.apple.Xcode.launch.runConfig;
+ remoteHostInfo = "";
+ startActionInfo = "";
+ };
+ "PBXLSLaunchAction-1" = {
+ PBXLSLaunchAction = 1;
+ PBXLSLaunchStartAction = 1;
+ PBXLSLaunchStdioStyle = 2;
+ PBXLSLaunchStyle = 0;
+ class = PBXGDB_LaunchConfig;
+ displayName = GDB;
+ identifier = com.apple.Xcode.launch.GDBMI_Config;
+ remoteHostInfo = "";
+ startActionInfo = "";
+ };
+ };
+ customDataFormattersEnabled = 1;
+ dataTipCustomDataFormattersEnabled = 1;
+ dataTipShowTypeColumn = 1;
+ dataTipSortType = 0;
+ debuggerPlugin = GDBDebugging;
+ disassemblyDisplayState = 0;
+ dylibVariantSuffix = "";
+ enableDebugStr = 0;
+ environmentEntries = (
+ {
+ active = YES;
+ name = TCL_LIBRARY;
+ value = "${TCL_SRCROOT}/library";
+ },
+ {
+ active = YES;
+ name = TK_LIBRARY;
+ value = "${TK_SRCROOT}/library";
+ },
+ {
+ active = YES;
+ name = TCLLIBPATH;
+ value = /Library/Tcl;
+ },
+ {
+ active = YES;
+ name = DISPLAY;
+ value = ":0";
+ },
+ {
+ active = NO;
+ name = DYLD_PRINT_LIBRARIES;
+ },
+ {
+ active = NO;
+ name = MallocBadFreeAbort;
+ value = 1;
+ },
+ {
+ active = NO;
+ name = MallocLogFile;
+ value = /tmp/malloc.log;
+ },
+ {
+ active = NO;
+ name = MallocStackLogging;
+ value = 1;
+ },
+ {
+ active = NO;
+ name = MallocStackLoggingNoCompact;
+ value = 1;
+ },
+ {
+ active = NO;
+ name = MallocPreScribble;
+ value = 1;
+ },
+ {
+ active = NO;
+ name = MallocScribble;
+ value = 1;
+ },
+ );
+ executableSystemSymbolLevel = 0;
+ executableUserSymbolLevel = 0;
+ libgmallocEnabled = 0;
+ name = "tktest-X11";
+ showTypeColumn = 0;
+ sourceDirectories = (
+ );
+ };
+}
diff --git a/tk8.6/macosx/Tk.xcodeproj/project.pbxproj b/tk8.6/macosx/Tk.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..53ebe3e
--- /dev/null
+++ b/tk8.6/macosx/Tk.xcodeproj/project.pbxproj
@@ -0,0 +1,5923 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ F9067BCD0BFBA2900074F726 /* tkOldTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAFE08F27A39005CB29B /* tkOldTest.c */; };
+ F9152B090EAF8A5000CD5C7B /* tkBusy.c in Sources */ = {isa = PBXBuildFile; fileRef = F9152B080EAF8A5000CD5C7B /* tkBusy.c */; };
+ F9152B0A0EAF8A5700CD5C7B /* tkBusy.c in Sources */ = {isa = PBXBuildFile; fileRef = F9152B080EAF8A5000CD5C7B /* tkBusy.c */; };
+ F92EE8BF0E62F846001A6E80 /* tkImgPhInstance.c in Sources */ = {isa = PBXBuildFile; fileRef = F92EE8BE0E62F846001A6E80 /* tkImgPhInstance.c */; };
+ F92EE8D30E62F939001A6E80 /* tkImgPhInstance.c in Sources */ = {isa = PBXBuildFile; fileRef = F92EE8BE0E62F846001A6E80 /* tkImgPhInstance.c */; };
+ F93599B30DF1F75400E04F67 /* tclOO.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599B20DF1F75400E04F67 /* tclOO.c */; };
+ F93599B70DF1F76100E04F67 /* tclOOBasic.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599B60DF1F76100E04F67 /* tclOOBasic.c */; };
+ F93599B90DF1F76600E04F67 /* tclOOCall.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599B80DF1F76600E04F67 /* tclOOCall.c */; };
+ F93599BC0DF1F77000E04F67 /* tclOODefineCmds.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599BB0DF1F77000E04F67 /* tclOODefineCmds.c */; };
+ F93599BE0DF1F77400E04F67 /* tclOOInfo.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599BD0DF1F77400E04F67 /* tclOOInfo.c */; };
+ F93599C20DF1F78300E04F67 /* tclOOMethod.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599C10DF1F78300E04F67 /* tclOOMethod.c */; };
+ F93599C40DF1F78800E04F67 /* tclOOStubInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599C30DF1F78800E04F67 /* tclOOStubInit.c */; };
+ F93599C60DF1F78D00E04F67 /* tclOOStubLib.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599C50DF1F78D00E04F67 /* tclOOStubLib.c */; };
+ F94523A20E6FC2AC00C1D987 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F94523A10E6FC2AC00C1D987 /* Cocoa.framework */; };
+ F95D77EA0DFD820D00A8BF6F /* tclIORTrans.c in Sources */ = {isa = PBXBuildFile; fileRef = F95D77E90DFD820D00A8BF6F /* tclIORTrans.c */; };
+ F96437CA0EF0D4B2003F468E /* tclZlib.c in Sources */ = {isa = PBXBuildFile; fileRef = F96437C90EF0D4B2003F468E /* tclZlib.c */; };
+ F96437CB0EF0D4B2003F468E /* tclZlib.c in Sources */ = {isa = PBXBuildFile; fileRef = F96437C90EF0D4B2003F468E /* tclZlib.c */; };
+ F96437E70EF0D652003F468E /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F96437E60EF0D652003F468E /* libz.dylib */; };
+ F96437E80EF0D652003F468E /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F96437E60EF0D652003F468E /* libz.dylib */; };
+ F966BDCF08F27A3F005CB29B /* tk3d.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAAC08F27A39005CB29B /* tk3d.c */; };
+ F966BDD108F27A3F005CB29B /* tkArgv.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAAE08F27A39005CB29B /* tkArgv.c */; };
+ F966BDD208F27A3F005CB29B /* tkAtom.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAAF08F27A39005CB29B /* tkAtom.c */; };
+ F966BDD308F27A3F005CB29B /* tkBind.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB008F27A39005CB29B /* tkBind.c */; };
+ F966BDD408F27A3F005CB29B /* tkBitmap.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB108F27A39005CB29B /* tkBitmap.c */; };
+ F966BDD508F27A3F005CB29B /* tkButton.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB208F27A39005CB29B /* tkButton.c */; };
+ F966BDD708F27A3F005CB29B /* tkCanvArc.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB408F27A39005CB29B /* tkCanvArc.c */; };
+ F966BDD808F27A3F005CB29B /* tkCanvas.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB508F27A39005CB29B /* tkCanvas.c */; };
+ F966BDDA08F27A3F005CB29B /* tkCanvBmap.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB708F27A39005CB29B /* tkCanvBmap.c */; };
+ F966BDDB08F27A3F005CB29B /* tkCanvImg.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB808F27A39005CB29B /* tkCanvImg.c */; };
+ F966BDDC08F27A3F005CB29B /* tkCanvLine.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB908F27A39005CB29B /* tkCanvLine.c */; };
+ F966BDDD08F27A3F005CB29B /* tkCanvPoly.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BABA08F27A39005CB29B /* tkCanvPoly.c */; };
+ F966BDDE08F27A3F005CB29B /* tkCanvPs.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BABB08F27A39005CB29B /* tkCanvPs.c */; };
+ F966BDE008F27A3F005CB29B /* tkCanvText.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BABD08F27A39005CB29B /* tkCanvText.c */; };
+ F966BDE108F27A3F005CB29B /* tkCanvUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BABE08F27A39005CB29B /* tkCanvUtil.c */; };
+ F966BDE208F27A3F005CB29B /* tkCanvWind.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BABF08F27A39005CB29B /* tkCanvWind.c */; };
+ F966BDE308F27A3F005CB29B /* tkClipboard.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAC008F27A39005CB29B /* tkClipboard.c */; };
+ F966BDE408F27A3F005CB29B /* tkCmds.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAC108F27A39005CB29B /* tkCmds.c */; };
+ F966BDE508F27A3F005CB29B /* tkColor.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAC208F27A39005CB29B /* tkColor.c */; };
+ F966BDE708F27A3F005CB29B /* tkConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAC408F27A39005CB29B /* tkConfig.c */; };
+ F966BDE808F27A3F005CB29B /* tkConsole.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAC508F27A39005CB29B /* tkConsole.c */; };
+ F966BDE908F27A3F005CB29B /* tkCursor.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAC608F27A39005CB29B /* tkCursor.c */; };
+ F966BDEB08F27A3F005CB29B /* tkEntry.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAC808F27A39005CB29B /* tkEntry.c */; };
+ F966BDED08F27A3F005CB29B /* tkError.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BACA08F27A39005CB29B /* tkError.c */; };
+ F966BDEE08F27A3F005CB29B /* tkEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BACB08F27A39005CB29B /* tkEvent.c */; };
+ F966BDEF08F27A3F005CB29B /* tkFileFilter.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BACC08F27A39005CB29B /* tkFileFilter.c */; };
+ F966BDF108F27A3F005CB29B /* tkFocus.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BACE08F27A39005CB29B /* tkFocus.c */; };
+ F966BDF208F27A3F005CB29B /* tkFont.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BACF08F27A39005CB29B /* tkFont.c */; };
+ F966BDF408F27A3F005CB29B /* tkFrame.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD108F27A39005CB29B /* tkFrame.c */; };
+ F966BDF508F27A3F005CB29B /* tkGC.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD208F27A39005CB29B /* tkGC.c */; };
+ F966BDF608F27A3F005CB29B /* tkGeometry.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD308F27A39005CB29B /* tkGeometry.c */; };
+ F966BDF708F27A3F005CB29B /* tkGet.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD408F27A39005CB29B /* tkGet.c */; };
+ F966BDF808F27A3F005CB29B /* tkGrab.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD508F27A39005CB29B /* tkGrab.c */; };
+ F966BDF908F27A3F005CB29B /* tkGrid.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD608F27A39005CB29B /* tkGrid.c */; };
+ F966BDFA08F27A3F005CB29B /* tkImage.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD708F27A39005CB29B /* tkImage.c */; };
+ F966BDFB08F27A3F005CB29B /* tkImgBmap.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD808F27A39005CB29B /* tkImgBmap.c */; };
+ F966BDFC08F27A3F005CB29B /* tkImgGIF.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD908F27A39005CB29B /* tkImgGIF.c */; };
+ F966BDFD08F27A3F005CB29B /* tkImgPhoto.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BADA08F27A39005CB29B /* tkImgPhoto.c */; };
+ F966BDFE08F27A3F005CB29B /* tkImgPPM.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BADB08F27A39005CB29B /* tkImgPPM.c */; };
+ F966BE0708F27A3F005CB29B /* tkListbox.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAE408F27A39005CB29B /* tkListbox.c */; };
+ F966BE0808F27A3F005CB29B /* tkMacWinMenu.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAE508F27A39005CB29B /* tkMacWinMenu.c */; };
+ F966BE0908F27A3F005CB29B /* tkMain.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAE608F27A39005CB29B /* tkMain.c */; };
+ F966BE0A08F27A3F005CB29B /* tkMenu.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAE708F27A39005CB29B /* tkMenu.c */; };
+ F966BE0C08F27A3F005CB29B /* tkMenubutton.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAE908F27A39005CB29B /* tkMenubutton.c */; };
+ F966BE0E08F27A3F005CB29B /* tkMenuDraw.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAEB08F27A39005CB29B /* tkMenuDraw.c */; };
+ F966BE0F08F27A3F005CB29B /* tkMessage.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAEC08F27A39005CB29B /* tkMessage.c */; };
+ F966BE1008F27A3F005CB29B /* tkObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAED08F27A39005CB29B /* tkObj.c */; };
+ F966BE1108F27A3F005CB29B /* tkOldConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAEE08F27A39005CB29B /* tkOldConfig.c */; };
+ F966BE1208F27A3F005CB29B /* tkOption.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAEF08F27A39005CB29B /* tkOption.c */; };
+ F966BE1308F27A3F005CB29B /* tkPack.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAF008F27A39005CB29B /* tkPack.c */; };
+ F966BE1408F27A3F005CB29B /* tkPanedWindow.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAF108F27A39005CB29B /* tkPanedWindow.c */; };
+ F966BE1508F27A3F005CB29B /* tkPlace.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAF208F27A39005CB29B /* tkPlace.c */; };
+ F966BE1708F27A3F005CB29B /* tkPointer.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAF408F27A39005CB29B /* tkPointer.c */; };
+ F966BE1908F27A3F005CB29B /* tkRectOval.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAF608F27A39005CB29B /* tkRectOval.c */; };
+ F966BE1A08F27A3F005CB29B /* tkScale.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAF708F27A39005CB29B /* tkScale.c */; };
+ F966BE1C08F27A40005CB29B /* tkScrollbar.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAF908F27A39005CB29B /* tkScrollbar.c */; };
+ F966BE1E08F27A40005CB29B /* tkSelect.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAFB08F27A39005CB29B /* tkSelect.c */; };
+ F966BE2008F27A40005CB29B /* tkSquare.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAFD08F27A39005CB29B /* tkSquare.c */; };
+ F966BE2208F27A40005CB29B /* tkStubInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAFF08F27A39005CB29B /* tkStubInit.c */; };
+ F966BE2308F27A40005CB29B /* tkStubLib.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0008F27A39005CB29B /* tkStubLib.c */; };
+ F966BE2408F27A40005CB29B /* tkStyle.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0108F27A39005CB29B /* tkStyle.c */; };
+ F966BE2508F27A40005CB29B /* tkTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0208F27A39005CB29B /* tkTest.c */; };
+ F966BE2608F27A40005CB29B /* tkText.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0308F27A39005CB29B /* tkText.c */; };
+ F966BE2808F27A40005CB29B /* tkTextBTree.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0508F27A39005CB29B /* tkTextBTree.c */; };
+ F966BE2908F27A40005CB29B /* tkTextDisp.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0608F27A39005CB29B /* tkTextDisp.c */; };
+ F966BE2B08F27A40005CB29B /* tkTextImage.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0808F27A39005CB29B /* tkTextImage.c */; };
+ F966BE2C08F27A40005CB29B /* tkTextIndex.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0908F27A39005CB29B /* tkTextIndex.c */; };
+ F966BE2D08F27A40005CB29B /* tkTextMark.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0A08F27A39005CB29B /* tkTextMark.c */; };
+ F966BE2E08F27A40005CB29B /* tkTextTag.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0B08F27A39005CB29B /* tkTextTag.c */; };
+ F966BE2F08F27A40005CB29B /* tkTextWind.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0C08F27A39005CB29B /* tkTextWind.c */; };
+ F966BE3008F27A40005CB29B /* tkTrig.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0D08F27A39005CB29B /* tkTrig.c */; };
+ F966BE3108F27A40005CB29B /* tkUndo.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0E08F27A39005CB29B /* tkUndo.c */; };
+ F966BE3308F27A40005CB29B /* tkUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB1008F27A39005CB29B /* tkUtil.c */; };
+ F966BE3408F27A40005CB29B /* tkVisual.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB1108F27A39005CB29B /* tkVisual.c */; };
+ F966BE3508F27A40005CB29B /* tkWindow.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB1208F27A39005CB29B /* tkWindow.c */; };
+ F966BEDB08F27A40005CB29B /* tkMacOSXBitmap.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBC508F27A3B005CB29B /* tkMacOSXBitmap.c */; };
+ F966BEDC08F27A40005CB29B /* tkMacOSXButton.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBC608F27A3B005CB29B /* tkMacOSXButton.c */; };
+ F966BEDE08F27A40005CB29B /* tkMacOSXClipboard.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBC808F27A3B005CB29B /* tkMacOSXClipboard.c */; };
+ F966BEDF08F27A40005CB29B /* tkMacOSXColor.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBC908F27A3B005CB29B /* tkMacOSXColor.c */; };
+ F966BEE008F27A40005CB29B /* tkMacOSXConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBCA08F27A3B005CB29B /* tkMacOSXConfig.c */; };
+ F966BEE108F27A40005CB29B /* tkMacOSXCursor.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBCB08F27A3B005CB29B /* tkMacOSXCursor.c */; };
+ F966BEE308F27A40005CB29B /* tkMacOSXDebug.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBCD08F27A3B005CB29B /* tkMacOSXDebug.c */; };
+ F966BEE608F27A40005CB29B /* tkMacOSXDialog.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBD008F27A3B005CB29B /* tkMacOSXDialog.c */; };
+ F966BEE708F27A40005CB29B /* tkMacOSXDraw.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBD108F27A3B005CB29B /* tkMacOSXDraw.c */; };
+ F966BEE808F27A40005CB29B /* tkMacOSXEmbed.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBD208F27A3B005CB29B /* tkMacOSXEmbed.c */; };
+ F966BEE908F27A40005CB29B /* tkMacOSXEntry.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBD308F27A3B005CB29B /* tkMacOSXEntry.c */; };
+ F966BEEA08F27A40005CB29B /* tkMacOSXEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBD408F27A3B005CB29B /* tkMacOSXEvent.c */; };
+ F966BEEC08F27A40005CB29B /* tkMacOSXFont.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBD608F27A3B005CB29B /* tkMacOSXFont.c */; };
+ F966BEED08F27A40005CB29B /* tkMacOSXHLEvents.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBD708F27A3B005CB29B /* tkMacOSXHLEvents.c */; };
+ F966BEEE08F27A40005CB29B /* tkMacOSXInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBD808F27A3B005CB29B /* tkMacOSXInit.c */; settings = {COMPILER_FLAGS = "-DTK_LIBRARY=\\\"$(TK_LIBRARY)\\\""; }; };
+ F966BEF108F27A40005CB29B /* tkMacOSXKeyboard.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBDB08F27A3B005CB29B /* tkMacOSXKeyboard.c */; };
+ F966BEF208F27A40005CB29B /* tkMacOSXKeyEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBDC08F27A3B005CB29B /* tkMacOSXKeyEvent.c */; };
+ F966BEF308F27A40005CB29B /* tkMacOSXMenu.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBDD08F27A3B005CB29B /* tkMacOSXMenu.c */; };
+ F966BEF608F27A40005CB29B /* tkMacOSXMenubutton.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBE008F27A3B005CB29B /* tkMacOSXMenubutton.c */; };
+ F966BEF708F27A40005CB29B /* tkMacOSXMenus.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBE108F27A3B005CB29B /* tkMacOSXMenus.c */; };
+ F966BEF808F27A40005CB29B /* tkMacOSXMouseEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBE208F27A3B005CB29B /* tkMacOSXMouseEvent.c */; };
+ F966BEF908F27A40005CB29B /* tkMacOSXNotify.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBE308F27A3B005CB29B /* tkMacOSXNotify.c */; };
+ F966BF0108F27A40005CB29B /* tkMacOSXRegion.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBEB08F27A3C005CB29B /* tkMacOSXRegion.c */; };
+ F966BF0308F27A40005CB29B /* tkMacOSXScrlbr.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBED08F27A3C005CB29B /* tkMacOSXScrlbr.c */; };
+ F966BF0408F27A40005CB29B /* tkMacOSXSend.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBEE08F27A3C005CB29B /* tkMacOSXSend.c */; };
+ F966BF0508F27A40005CB29B /* tkMacOSXSubwindows.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBEF08F27A3C005CB29B /* tkMacOSXSubwindows.c */; };
+ F966BF0608F27A40005CB29B /* tkMacOSXTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBF008F27A3C005CB29B /* tkMacOSXTest.c */; };
+ F966BF0708F27A40005CB29B /* tkMacOSXWindowEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBF108F27A3C005CB29B /* tkMacOSXWindowEvent.c */; };
+ F966BF0808F27A40005CB29B /* tkMacOSXWm.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBF208F27A3C005CB29B /* tkMacOSXWm.c */; };
+ F966BF0B08F27A40005CB29B /* tkMacOSXXStubs.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BBF508F27A3C005CB29B /* tkMacOSXXStubs.c */; };
+ F966BF7F08F27A41005CB29B /* tkAppInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC7508F27A3D005CB29B /* tkAppInit.c */; settings = {COMPILER_FLAGS = "-DTK_TEST"; }; };
+ F966BF8308F27A41005CB29B /* tkUnix3d.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC7908F27A3D005CB29B /* tkUnix3d.c */; };
+ F966BF9608F27A41005CB29B /* tkUnixScale.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC8C08F27A3D005CB29B /* tkUnixScale.c */; };
+ F966C02A08F27A42005CB29B /* xcolors.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BD2408F27A3F005CB29B /* xcolors.c */; };
+ F966C02B08F27A42005CB29B /* xdraw.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BD2508F27A3F005CB29B /* xdraw.c */; };
+ F966C02C08F27A42005CB29B /* xgc.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BD2608F27A3F005CB29B /* xgc.c */; };
+ F966C02D08F27A42005CB29B /* ximage.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BD2708F27A3F005CB29B /* ximage.c */; };
+ F966C02E08F27A42005CB29B /* xutil.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BD2808F27A3F005CB29B /* xutil.c */; };
+ F966C07508F2820D005CB29B /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F966C07408F2820D005CB29B /* CoreFoundation.framework */; };
+ F966C07708F2821B005CB29B /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F966C07608F2821B005CB29B /* Carbon.framework */; };
+ F966C07908F28233005CB29B /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F966C07808F28233005CB29B /* IOKit.framework */; };
+ F96888050AF786D5000797B5 /* ttkBlink.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E10AF786D5000797B5 /* ttkBlink.c */; };
+ F96888060AF786D5000797B5 /* ttkButton.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E20AF786D5000797B5 /* ttkButton.c */; };
+ F96888070AF786D5000797B5 /* ttkCache.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E30AF786D5000797B5 /* ttkCache.c */; };
+ F96888080AF786D5000797B5 /* ttkClamTheme.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E40AF786D5000797B5 /* ttkClamTheme.c */; };
+ F96888090AF786D5000797B5 /* ttkClassicTheme.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E50AF786D5000797B5 /* ttkClassicTheme.c */; };
+ F968880A0AF786D5000797B5 /* ttkDefaultTheme.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E70AF786D5000797B5 /* ttkDefaultTheme.c */; };
+ F968880B0AF786D5000797B5 /* ttkElements.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E80AF786D5000797B5 /* ttkElements.c */; };
+ F968880C0AF786D5000797B5 /* ttkEntry.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E90AF786D5000797B5 /* ttkEntry.c */; };
+ F968880D0AF786D5000797B5 /* ttkFrame.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887EA0AF786D5000797B5 /* ttkFrame.c */; };
+ F968880E0AF786D5000797B5 /* ttkImage.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887EB0AF786D5000797B5 /* ttkImage.c */; };
+ F968880F0AF786D5000797B5 /* ttkInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887EC0AF786D5000797B5 /* ttkInit.c */; };
+ F96888100AF786D5000797B5 /* ttkLabel.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887ED0AF786D5000797B5 /* ttkLabel.c */; };
+ F96888110AF786D5000797B5 /* ttkLayout.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887EE0AF786D5000797B5 /* ttkLayout.c */; };
+ F96888120AF786D5000797B5 /* ttkManager.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887EF0AF786D5000797B5 /* ttkManager.c */; };
+ F96888130AF786D5000797B5 /* ttkNotebook.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F10AF786D5000797B5 /* ttkNotebook.c */; };
+ F96888140AF786D5000797B5 /* ttkPanedwindow.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F20AF786D5000797B5 /* ttkPanedwindow.c */; };
+ F96888150AF786D5000797B5 /* ttkProgress.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F30AF786D5000797B5 /* ttkProgress.c */; };
+ F96888160AF786D5000797B5 /* ttkScale.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F40AF786D5000797B5 /* ttkScale.c */; };
+ F96888170AF786D5000797B5 /* ttkScroll.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F50AF786D5000797B5 /* ttkScroll.c */; };
+ F96888180AF786D5000797B5 /* ttkScrollbar.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F60AF786D5000797B5 /* ttkScrollbar.c */; };
+ F96888190AF786D5000797B5 /* ttkSeparator.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F70AF786D5000797B5 /* ttkSeparator.c */; };
+ F968881A0AF786D5000797B5 /* ttkSquare.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F80AF786D5000797B5 /* ttkSquare.c */; };
+ F968881B0AF786D5000797B5 /* ttkState.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F90AF786D5000797B5 /* ttkState.c */; };
+ F968881C0AF786D5000797B5 /* ttkStubInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887FA0AF786D5000797B5 /* ttkStubInit.c */; };
+ F968881D0AF786D5000797B5 /* ttkStubLib.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887FB0AF786D5000797B5 /* ttkStubLib.c */; };
+ F968881E0AF786D5000797B5 /* ttkTagSet.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887FC0AF786D5000797B5 /* ttkTagSet.c */; };
+ F968881F0AF786D5000797B5 /* ttkTheme.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887FD0AF786D5000797B5 /* ttkTheme.c */; };
+ F96888200AF786D5000797B5 /* ttkTrace.c in Sources */ = {isa = PBXBuildFile; fileRef = F96888000AF786D5000797B5 /* ttkTrace.c */; };
+ F96888210AF786D5000797B5 /* ttkTrack.c in Sources */ = {isa = PBXBuildFile; fileRef = F96888010AF786D5000797B5 /* ttkTrack.c */; };
+ F96888220AF786D5000797B5 /* ttkTreeview.c in Sources */ = {isa = PBXBuildFile; fileRef = F96888020AF786D5000797B5 /* ttkTreeview.c */; };
+ F96888230AF786D5000797B5 /* ttkWidget.c in Sources */ = {isa = PBXBuildFile; fileRef = F96888030AF786D5000797B5 /* ttkWidget.c */; };
+ F96888850AF78938000797B5 /* ttkMacOSXTheme.c in Sources */ = {isa = PBXBuildFile; fileRef = F96888840AF78938000797B5 /* ttkMacOSXTheme.c */; };
+ F96D456F08F272BB004A47F5 /* regcomp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED008F272A7004A47F5 /* regcomp.c */; };
+ F96D457208F272BB004A47F5 /* regerror.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED308F272A7004A47F5 /* regerror.c */; };
+ F96D457508F272BB004A47F5 /* regexec.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED608F272A7004A47F5 /* regexec.c */; };
+ F96D457608F272BB004A47F5 /* regfree.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED708F272A7004A47F5 /* regfree.c */; };
+ F96D457B08F272BB004A47F5 /* tclAlloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDC08F272A7004A47F5 /* tclAlloc.c */; settings = {COMPILER_FLAGS = "-DUSE_TCLALLOC=0"; }; };
+ F96D457C08F272BB004A47F5 /* tclAsync.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDD08F272A7004A47F5 /* tclAsync.c */; };
+ F96D457D08F272BB004A47F5 /* tclBasic.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDE08F272A7004A47F5 /* tclBasic.c */; };
+ F96D457E08F272BC004A47F5 /* tclBinary.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDF08F272A7004A47F5 /* tclBinary.c */; };
+ F96D457F08F272BC004A47F5 /* tclCkalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE008F272A7004A47F5 /* tclCkalloc.c */; };
+ F96D458008F272BC004A47F5 /* tclClock.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE108F272A7004A47F5 /* tclClock.c */; };
+ F96D458108F272BC004A47F5 /* tclCmdAH.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE208F272A7004A47F5 /* tclCmdAH.c */; };
+ F96D458208F272BC004A47F5 /* tclCmdIL.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE308F272A7004A47F5 /* tclCmdIL.c */; };
+ F96D458308F272BC004A47F5 /* tclCmdMZ.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE408F272A7004A47F5 /* tclCmdMZ.c */; };
+ F96D458408F272BC004A47F5 /* tclCompCmds.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE508F272A7004A47F5 /* tclCompCmds.c */; };
+ F96D458508F272BC004A47F5 /* tclCompExpr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE608F272A7004A47F5 /* tclCompExpr.c */; };
+ F96D458608F272BC004A47F5 /* tclCompile.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE708F272A7004A47F5 /* tclCompile.c */; };
+ F96D458808F272BC004A47F5 /* tclConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE908F272A7004A47F5 /* tclConfig.c */; };
+ F96D458908F272BC004A47F5 /* tclDate.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEA08F272A7004A47F5 /* tclDate.c */; };
+ F96D458B08F272BC004A47F5 /* tclDictObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEC08F272A7004A47F5 /* tclDictObj.c */; };
+ F96D458C08F272BC004A47F5 /* tclEncoding.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EED08F272A7004A47F5 /* tclEncoding.c */; };
+ F96D458D08F272BC004A47F5 /* tclEnv.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEE08F272A7004A47F5 /* tclEnv.c */; };
+ F96D458E08F272BC004A47F5 /* tclEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEF08F272A7004A47F5 /* tclEvent.c */; };
+ F96D458F08F272BC004A47F5 /* tclExecute.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF008F272A7004A47F5 /* tclExecute.c */; };
+ F96D459008F272BC004A47F5 /* tclFCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF108F272A7004A47F5 /* tclFCmd.c */; };
+ F96D459108F272BC004A47F5 /* tclFileName.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF208F272A7004A47F5 /* tclFileName.c */; };
+ F96D459308F272BC004A47F5 /* tclGet.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF408F272A7004A47F5 /* tclGet.c */; };
+ F96D459508F272BC004A47F5 /* tclHash.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF608F272A7004A47F5 /* tclHash.c */; };
+ F96D459608F272BC004A47F5 /* tclHistory.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF708F272A7004A47F5 /* tclHistory.c */; };
+ F96D459708F272BC004A47F5 /* tclIndexObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF808F272A7004A47F5 /* tclIndexObj.c */; };
+ F96D459B08F272BC004A47F5 /* tclInterp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EFC08F272A7004A47F5 /* tclInterp.c */; };
+ F96D459D08F272BC004A47F5 /* tclIO.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EFE08F272A7004A47F5 /* tclIO.c */; };
+ F96D459F08F272BC004A47F5 /* tclIOCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0008F272A7004A47F5 /* tclIOCmd.c */; };
+ F96D45A008F272BC004A47F5 /* tclIOGT.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0108F272A7004A47F5 /* tclIOGT.c */; };
+ F96D45A108F272BC004A47F5 /* tclIORChan.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0208F272A7004A47F5 /* tclIORChan.c */; };
+ F96D45A208F272BC004A47F5 /* tclIOSock.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0308F272A7004A47F5 /* tclIOSock.c */; };
+ F96D45A308F272BC004A47F5 /* tclIOUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0408F272A7004A47F5 /* tclIOUtil.c */; };
+ F96D45A408F272BC004A47F5 /* tclLink.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0508F272A7004A47F5 /* tclLink.c */; };
+ F96D45A508F272BC004A47F5 /* tclListObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0608F272A7004A47F5 /* tclListObj.c */; };
+ F96D45A608F272BC004A47F5 /* tclLiteral.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0708F272A7004A47F5 /* tclLiteral.c */; };
+ F96D45A708F272BC004A47F5 /* tclLoad.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0808F272A7004A47F5 /* tclLoad.c */; };
+ F96D45A908F272BC004A47F5 /* tclMain.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0A08F272A7004A47F5 /* tclMain.c */; };
+ F96D45AA08F272BC004A47F5 /* tclNamesp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0B08F272A7004A47F5 /* tclNamesp.c */; };
+ F96D45AB08F272BC004A47F5 /* tclNotify.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0C08F272A7004A47F5 /* tclNotify.c */; };
+ F96D45AC08F272BC004A47F5 /* tclObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0D08F272A7004A47F5 /* tclObj.c */; };
+ F96D45AD08F272BC004A47F5 /* tclPanic.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0E08F272A7004A47F5 /* tclPanic.c */; };
+ F96D45AE08F272BC004A47F5 /* tclParse.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0F08F272A7004A47F5 /* tclParse.c */; };
+ F96D45B008F272BC004A47F5 /* tclPathObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1108F272A7004A47F5 /* tclPathObj.c */; };
+ F96D45B108F272BC004A47F5 /* tclPipe.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1208F272A7004A47F5 /* tclPipe.c */; };
+ F96D45B208F272BC004A47F5 /* tclPkg.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1308F272A7004A47F5 /* tclPkg.c */; };
+ F96D45B308F272BC004A47F5 /* tclPkgConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1408F272A7004A47F5 /* tclPkgConfig.c */; settings = {COMPILER_FLAGS = "-DCFG_INSTALL_LIBDIR=\\\"$(LIBDIR)\\\" -DCFG_INSTALL_BINDIR=\\\"$(BINDIR)\\\" -DCFG_INSTALL_SCRDIR=\\\"$(TCL_LIBRARY)\\\" -DCFG_INSTALL_INCDIR=\\\"$(INCLUDEDIR)\\\" -DCFG_INSTALL_DOCDIR=\\\"$(MANDIR)\\\" -DCFG_RUNTIME_LIBDIR=\\\"$(LIBDIR)\\\" -DCFG_RUNTIME_BINDIR=\\\"$(BINDIR)\\\" -DCFG_RUNTIME_SCRDIR=\\\"$(TCL_LIBRARY)\\\" -DCFG_RUNTIME_INCDIR=\\\"$(INCLUDEDIR)\\\" -DCFG_RUNTIME_DOCDIR=\\\"$(MANDIR)\\\""; }; };
+ F96D45B608F272BC004A47F5 /* tclPosixStr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1708F272A7004A47F5 /* tclPosixStr.c */; };
+ F96D45B708F272BC004A47F5 /* tclPreserve.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1808F272A7004A47F5 /* tclPreserve.c */; };
+ F96D45B808F272BC004A47F5 /* tclProc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1908F272A7004A47F5 /* tclProc.c */; };
+ F96D45B908F272BC004A47F5 /* tclRegexp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1A08F272A7004A47F5 /* tclRegexp.c */; };
+ F96D45BB08F272BC004A47F5 /* tclResolve.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1C08F272A7004A47F5 /* tclResolve.c */; };
+ F96D45BC08F272BC004A47F5 /* tclResult.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1D08F272A7004A47F5 /* tclResult.c */; };
+ F96D45BD08F272BC004A47F5 /* tclScan.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1E08F272A7004A47F5 /* tclScan.c */; };
+ F96D45BE08F272BC004A47F5 /* tclStringObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1F08F272A7004A47F5 /* tclStringObj.c */; };
+ F96D45C308F272BC004A47F5 /* tclStrToD.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2408F272A7004A47F5 /* tclStrToD.c */; };
+ F96D45C408F272BC004A47F5 /* tclStubInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2508F272A7004A47F5 /* tclStubInit.c */; };
+ F96D45C508F272BC004A47F5 /* tclStubLib.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2608F272A7004A47F5 /* tclStubLib.c */; };
+ F96D45C908F272BC004A47F5 /* tclThread.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2A08F272A7004A47F5 /* tclThread.c */; };
+ F96D45CA08F272BC004A47F5 /* tclThreadAlloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2B08F272A7004A47F5 /* tclThreadAlloc.c */; };
+ F96D45CB08F272BC004A47F5 /* tclThreadJoin.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2C08F272A7004A47F5 /* tclThreadJoin.c */; };
+ F96D45CC08F272BC004A47F5 /* tclThreadStorage.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2D08F272A7004A47F5 /* tclThreadStorage.c */; };
+ F96D45CE08F272BC004A47F5 /* tclTimer.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2F08F272A7004A47F5 /* tclTimer.c */; };
+ F96D45D008F272BC004A47F5 /* tclTomMathInterface.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3108F272A7004A47F5 /* tclTomMathInterface.c */; };
+ F96D45D108F272BC004A47F5 /* tclTrace.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3208F272A7004A47F5 /* tclTrace.c */; };
+ F96D45D308F272BC004A47F5 /* tclUtf.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3408F272A7004A47F5 /* tclUtf.c */; };
+ F96D45D408F272BC004A47F5 /* tclUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3508F272A7004A47F5 /* tclUtil.c */; };
+ F96D45D508F272BC004A47F5 /* tclVar.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3608F272A7004A47F5 /* tclVar.c */; };
+ F96D48E208F272C3004A47F5 /* bn_fast_s_mp_mul_digs.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426408F272B3004A47F5 /* bn_fast_s_mp_mul_digs.c */; };
+ F96D48E408F272C3004A47F5 /* bn_fast_s_mp_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426608F272B3004A47F5 /* bn_fast_s_mp_sqr.c */; };
+ F96D48E708F272C3004A47F5 /* bn_mp_add.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426908F272B3004A47F5 /* bn_mp_add.c */; };
+ F96D48E808F272C3004A47F5 /* bn_mp_add_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426A08F272B3004A47F5 /* bn_mp_add_d.c */; };
+ F96D48EB08F272C3004A47F5 /* bn_mp_clamp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426D08F272B3004A47F5 /* bn_mp_clamp.c */; };
+ F96D48EC08F272C3004A47F5 /* bn_mp_clear.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426E08F272B3004A47F5 /* bn_mp_clear.c */; };
+ F96D48ED08F272C3004A47F5 /* bn_mp_clear_multi.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426F08F272B3004A47F5 /* bn_mp_clear_multi.c */; };
+ F96D48EE08F272C3004A47F5 /* bn_mp_cmp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427008F272B3004A47F5 /* bn_mp_cmp.c */; };
+ F96D48F008F272C3004A47F5 /* bn_mp_cmp_mag.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */; };
+ F96D48F208F272C3004A47F5 /* bn_mp_copy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427408F272B3004A47F5 /* bn_mp_copy.c */; };
+ F96D48F308F272C3004A47F5 /* bn_mp_count_bits.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */; };
+ F96D48F408F272C3004A47F5 /* bn_mp_div.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427608F272B3004A47F5 /* bn_mp_div.c */; };
+ F96D48F508F272C3004A47F5 /* bn_mp_div_2.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427708F272B3004A47F5 /* bn_mp_div_2.c */; };
+ F96D48F608F272C3004A47F5 /* bn_mp_div_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */; };
+ F96D48F708F272C3004A47F5 /* bn_mp_div_3.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427908F272B3004A47F5 /* bn_mp_div_3.c */; };
+ F96D48F808F272C3004A47F5 /* bn_mp_div_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */; };
+ F96D48FC08F272C3004A47F5 /* bn_mp_exch.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427E08F272B3004A47F5 /* bn_mp_exch.c */; };
+ F96D490508F272C3004A47F5 /* bn_mp_grow.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428708F272B3004A47F5 /* bn_mp_grow.c */; };
+ F96D490608F272C3004A47F5 /* bn_mp_init.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428808F272B3004A47F5 /* bn_mp_init.c */; };
+ F96D490708F272C3004A47F5 /* bn_mp_init_copy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428908F272B3004A47F5 /* bn_mp_init_copy.c */; };
+ F96D490808F272C3004A47F5 /* bn_mp_init_multi.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428A08F272B3004A47F5 /* bn_mp_init_multi.c */; };
+ F96D490908F272C3004A47F5 /* bn_mp_init_set.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428B08F272B3004A47F5 /* bn_mp_init_set.c */; };
+ F96D490B08F272C3004A47F5 /* bn_mp_init_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428D08F272B3004A47F5 /* bn_mp_init_size.c */; };
+ F96D491008F272C3004A47F5 /* bn_mp_karatsuba_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429208F272B3004A47F5 /* bn_mp_karatsuba_mul.c */; };
+ F96D491108F272C3004A47F5 /* bn_mp_karatsuba_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429308F272B3004A47F5 /* bn_mp_karatsuba_sqr.c */; };
+ F96D491308F272C3004A47F5 /* bn_mp_lshd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429508F272B3004A47F5 /* bn_mp_lshd.c */; };
+ F96D491408F272C3004A47F5 /* bn_mp_mod.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429608F272B3004A47F5 /* bn_mp_mod.c */; };
+ F96D491508F272C3004A47F5 /* bn_mp_mod_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429708F272B3004A47F5 /* bn_mp_mod_2d.c */; };
+ F96D491A08F272C3004A47F5 /* bn_mp_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429C08F272B3004A47F5 /* bn_mp_mul.c */; };
+ F96D491B08F272C3004A47F5 /* bn_mp_mul_2.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429D08F272B3004A47F5 /* bn_mp_mul_2.c */; };
+ F96D491C08F272C3004A47F5 /* bn_mp_mul_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429E08F272B3004A47F5 /* bn_mp_mul_2d.c */; };
+ F96D491D08F272C3004A47F5 /* bn_mp_mul_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429F08F272B3004A47F5 /* bn_mp_mul_d.c */; };
+ F96D492908F272C3004A47F5 /* bn_mp_radix_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42AB08F272B3004A47F5 /* bn_mp_radix_size.c */; };
+ F96D492A08F272C3004A47F5 /* bn_mp_radix_smap.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42AC08F272B3004A47F5 /* bn_mp_radix_smap.c */; };
+ F96D492C08F272C3004A47F5 /* bn_mp_read_radix.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42AE08F272B3004A47F5 /* bn_mp_read_radix.c */; };
+ F96D493708F272C3004A47F5 /* bn_mp_rshd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42B908F272B3004A47F5 /* bn_mp_rshd.c */; };
+ F96D493808F272C3004A47F5 /* bn_mp_set.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BA08F272B3004A47F5 /* bn_mp_set.c */; };
+ F96D493C08F272C3004A47F5 /* bn_mp_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BE08F272B3004A47F5 /* bn_mp_sqr.c */; };
+ F96D493F08F272C3004A47F5 /* bn_mp_sub.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C108F272B3004A47F5 /* bn_mp_sub.c */; };
+ F96D494008F272C3004A47F5 /* bn_mp_sub_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C208F272B3004A47F5 /* bn_mp_sub_d.c */; };
+ F96D494608F272C3004A47F5 /* bn_mp_toom_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C808F272B3004A47F5 /* bn_mp_toom_mul.c */; };
+ F96D494708F272C3004A47F5 /* bn_mp_toom_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C908F272B3004A47F5 /* bn_mp_toom_sqr.c */; };
+ F96D494908F272C3004A47F5 /* bn_mp_toradix_n.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CB08F272B3004A47F5 /* bn_mp_toradix_n.c */; };
+ F96D494C08F272C3004A47F5 /* bn_mp_zero.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CE08F272B3004A47F5 /* bn_mp_zero.c */; };
+ F96D494E08F272C3004A47F5 /* bn_reverse.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D008F272B3004A47F5 /* bn_reverse.c */; };
+ F96D494F08F272C3004A47F5 /* bn_s_mp_add.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D108F272B3004A47F5 /* bn_s_mp_add.c */; };
+ F96D495108F272C3004A47F5 /* bn_s_mp_mul_digs.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D308F272B3004A47F5 /* bn_s_mp_mul_digs.c */; };
+ F96D495308F272C3004A47F5 /* bn_s_mp_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D508F272B3004A47F5 /* bn_s_mp_sqr.c */; };
+ F96D495408F272C3004A47F5 /* bn_s_mp_sub.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D608F272B3004A47F5 /* bn_s_mp_sub.c */; };
+ F96D495508F272C3004A47F5 /* bncore.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D708F272B3004A47F5 /* bncore.c */; };
+ F96D49A908F272C4004A47F5 /* tclMacOSXBundle.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D433908F272B5004A47F5 /* tclMacOSXBundle.c */; };
+ F96D49AD08F272C4004A47F5 /* tclMacOSXFCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D433D08F272B5004A47F5 /* tclMacOSXFCmd.c */; };
+ F96D49AE08F272C4004A47F5 /* tclMacOSXNotify.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D433E08F272B5004A47F5 /* tclMacOSXNotify.c */; };
+ F96D4AC608F272C9004A47F5 /* tclLoadDyld.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D445B08F272B9004A47F5 /* tclLoadDyld.c */; settings = {COMPILER_FLAGS = "-Wno-deprecated-declarations"; }; };
+ F96D4ACA08F272C9004A47F5 /* tclUnixChan.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D445F08F272B9004A47F5 /* tclUnixChan.c */; };
+ F96D4ACB08F272C9004A47F5 /* tclUnixEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446008F272B9004A47F5 /* tclUnixEvent.c */; };
+ F96D4ACC08F272C9004A47F5 /* tclUnixFCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446108F272B9004A47F5 /* tclUnixFCmd.c */; };
+ F96D4ACD08F272C9004A47F5 /* tclUnixFile.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446208F272B9004A47F5 /* tclUnixFile.c */; };
+ F96D4ACE08F272C9004A47F5 /* tclUnixInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446308F272B9004A47F5 /* tclUnixInit.c */; settings = {COMPILER_FLAGS = "-DTCL_LIBRARY=\\\"$(TCL_LIBRARY)\\\" -DTCL_PACKAGE_PATH=\\\"$(TCL_PACKAGE_PATH)\\\""; }; };
+ F96D4ACF08F272C9004A47F5 /* tclUnixNotfy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446408F272B9004A47F5 /* tclUnixNotfy.c */; };
+ F96D4AD008F272C9004A47F5 /* tclUnixPipe.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446508F272B9004A47F5 /* tclUnixPipe.c */; };
+ F96D4AD208F272CA004A47F5 /* tclUnixSock.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446708F272B9004A47F5 /* tclUnixSock.c */; };
+ F96D4AD408F272CA004A47F5 /* tclUnixThrd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446908F272B9004A47F5 /* tclUnixThrd.c */; };
+ F96D4AD608F272CA004A47F5 /* tclUnixTime.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446B08F272B9004A47F5 /* tclUnixTime.c */; };
+ F9C9CC000E84059800E00935 /* ApplicationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9C9CBFF0E84059800E00935 /* ApplicationServices.framework */; };
+ F9DD99BD0F07DF850018B2E4 /* tkImgPNG.c in Sources */ = {isa = PBXBuildFile; fileRef = F9DD99BC0F07DF850018B2E4 /* tkImgPNG.c */; };
+ F9DD99BE0F07DF850018B2E4 /* tkImgPNG.c in Sources */ = {isa = PBXBuildFile; fileRef = F9DD99BC0F07DF850018B2E4 /* tkImgPNG.c */; };
+ F9E61D28090A481F002B3151 /* bn_mp_cmp_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */; };
+ F9E61D29090A486C002B3151 /* bn_mp_neg.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42A208F272B3004A47F5 /* bn_mp_neg.c */; };
+ F9E61D2A090A4891002B3151 /* bn_mp_sqrt.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C008F272B3004A47F5 /* bn_mp_sqrt.c */; };
+ F9E61D2B090A48A4002B3151 /* bn_mp_and.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426C08F272B3004A47F5 /* bn_mp_and.c */; };
+ F9E61D2C090A48AC002B3151 /* bn_mp_expt_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427F08F272B3004A47F5 /* bn_mp_expt_d.c */; };
+ F9E61D2D090A48BB002B3151 /* bn_mp_xor.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CD08F272B3004A47F5 /* bn_mp_xor.c */; };
+ F9E61D2E090A48BF002B3151 /* bn_mp_or.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42A308F272B3004A47F5 /* bn_mp_or.c */; };
+ F9E61D2F090A48C7002B3151 /* bn_mp_shrink.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BC08F272B3004A47F5 /* bn_mp_shrink.c */; };
+ F9E61D30090A48E2002B3151 /* bn_mp_to_unsigned_bin_n.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C708F272B3004A47F5 /* bn_mp_to_unsigned_bin_n.c */; };
+ F9E61D31090A48F9002B3151 /* bn_mp_to_unsigned_bin.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C608F272B3004A47F5 /* bn_mp_to_unsigned_bin.c */; };
+ F9E61D32090A48FA002B3151 /* bn_mp_unsigned_bin_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CC08F272B3004A47F5 /* bn_mp_unsigned_bin_size.c */; };
+ F9F4415E0C8BAE6F00BCCD67 /* tclDTrace.d in Sources */ = {isa = PBXBuildFile; fileRef = F9F4415D0C8BAE6F00BCCD67 /* tclDTrace.d */; };
+ F9FC77B80AB29E9100B7077D /* tclUnixCompat.c in Sources */ = {isa = PBXBuildFile; fileRef = F9FC77B70AB29E9100B7077D /* tclUnixCompat.c */; };
+ F9FD30BC0CC1AD070073837D /* regcomp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED008F272A7004A47F5 /* regcomp.c */; };
+ F9FD30BD0CC1AD070073837D /* regerror.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED308F272A7004A47F5 /* regerror.c */; };
+ F9FD30BE0CC1AD070073837D /* regexec.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED608F272A7004A47F5 /* regexec.c */; };
+ F9FD30BF0CC1AD070073837D /* regfree.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED708F272A7004A47F5 /* regfree.c */; };
+ F9FD30C00CC1AD070073837D /* tclAlloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDC08F272A7004A47F5 /* tclAlloc.c */; settings = {COMPILER_FLAGS = "-DUSE_TCLALLOC=0"; }; };
+ F9FD30C10CC1AD070073837D /* tclAsync.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDD08F272A7004A47F5 /* tclAsync.c */; };
+ F9FD30C20CC1AD070073837D /* tclBasic.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDE08F272A7004A47F5 /* tclBasic.c */; };
+ F9FD30C30CC1AD070073837D /* tclBinary.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDF08F272A7004A47F5 /* tclBinary.c */; };
+ F9FD30C40CC1AD070073837D /* tclCkalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE008F272A7004A47F5 /* tclCkalloc.c */; };
+ F9FD30C50CC1AD070073837D /* tclClock.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE108F272A7004A47F5 /* tclClock.c */; };
+ F9FD30C60CC1AD070073837D /* tclCmdAH.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE208F272A7004A47F5 /* tclCmdAH.c */; };
+ F9FD30C70CC1AD070073837D /* tclCmdIL.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE308F272A7004A47F5 /* tclCmdIL.c */; };
+ F9FD30C80CC1AD070073837D /* tclCmdMZ.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE408F272A7004A47F5 /* tclCmdMZ.c */; };
+ F9FD30C90CC1AD070073837D /* tclCompCmds.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE508F272A7004A47F5 /* tclCompCmds.c */; };
+ F9FD30CA0CC1AD070073837D /* tclCompExpr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE608F272A7004A47F5 /* tclCompExpr.c */; };
+ F9FD30CB0CC1AD070073837D /* tclCompile.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE708F272A7004A47F5 /* tclCompile.c */; };
+ F9FD30CC0CC1AD070073837D /* tclConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE908F272A7004A47F5 /* tclConfig.c */; };
+ F9FD30CD0CC1AD070073837D /* tclDate.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEA08F272A7004A47F5 /* tclDate.c */; };
+ F9FD30CE0CC1AD070073837D /* tclDictObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEC08F272A7004A47F5 /* tclDictObj.c */; };
+ F9FD30CF0CC1AD070073837D /* tclEncoding.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EED08F272A7004A47F5 /* tclEncoding.c */; };
+ F9FD30D00CC1AD070073837D /* tclEnv.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEE08F272A7004A47F5 /* tclEnv.c */; };
+ F9FD30D10CC1AD070073837D /* tclEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEF08F272A7004A47F5 /* tclEvent.c */; };
+ F9FD30D20CC1AD070073837D /* tclExecute.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF008F272A7004A47F5 /* tclExecute.c */; };
+ F9FD30D30CC1AD070073837D /* tclFCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF108F272A7004A47F5 /* tclFCmd.c */; };
+ F9FD30D40CC1AD070073837D /* tclFileName.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF208F272A7004A47F5 /* tclFileName.c */; };
+ F9FD30D50CC1AD070073837D /* tclGet.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF408F272A7004A47F5 /* tclGet.c */; };
+ F9FD30D60CC1AD070073837D /* tclHash.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF608F272A7004A47F5 /* tclHash.c */; };
+ F9FD30D70CC1AD070073837D /* tclHistory.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF708F272A7004A47F5 /* tclHistory.c */; };
+ F9FD30D80CC1AD070073837D /* tclIndexObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF808F272A7004A47F5 /* tclIndexObj.c */; };
+ F9FD30D90CC1AD070073837D /* tclInterp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EFC08F272A7004A47F5 /* tclInterp.c */; };
+ F9FD30DA0CC1AD070073837D /* tclIO.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EFE08F272A7004A47F5 /* tclIO.c */; };
+ F9FD30DB0CC1AD070073837D /* tclIOCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0008F272A7004A47F5 /* tclIOCmd.c */; };
+ F9FD30DC0CC1AD070073837D /* tclIOGT.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0108F272A7004A47F5 /* tclIOGT.c */; };
+ F9FD30DD0CC1AD070073837D /* tclIORChan.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0208F272A7004A47F5 /* tclIORChan.c */; };
+ F9FD30DE0CC1AD070073837D /* tclIOSock.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0308F272A7004A47F5 /* tclIOSock.c */; };
+ F9FD30DF0CC1AD070073837D /* tclIOUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0408F272A7004A47F5 /* tclIOUtil.c */; };
+ F9FD30E00CC1AD070073837D /* tclLink.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0508F272A7004A47F5 /* tclLink.c */; };
+ F9FD30E10CC1AD070073837D /* tclListObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0608F272A7004A47F5 /* tclListObj.c */; };
+ F9FD30E20CC1AD070073837D /* tclLiteral.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0708F272A7004A47F5 /* tclLiteral.c */; };
+ F9FD30E30CC1AD070073837D /* tclLoad.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0808F272A7004A47F5 /* tclLoad.c */; };
+ F9FD30E40CC1AD070073837D /* tclMain.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0A08F272A7004A47F5 /* tclMain.c */; };
+ F9FD30E50CC1AD070073837D /* tclNamesp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0B08F272A7004A47F5 /* tclNamesp.c */; };
+ F9FD30E60CC1AD070073837D /* tclNotify.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0C08F272A7004A47F5 /* tclNotify.c */; };
+ F9FD30E70CC1AD070073837D /* tclObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0D08F272A7004A47F5 /* tclObj.c */; };
+ F9FD30E80CC1AD070073837D /* tclPanic.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0E08F272A7004A47F5 /* tclPanic.c */; };
+ F9FD30E90CC1AD070073837D /* tclParse.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0F08F272A7004A47F5 /* tclParse.c */; };
+ F9FD30EA0CC1AD070073837D /* tclPathObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1108F272A7004A47F5 /* tclPathObj.c */; };
+ F9FD30EB0CC1AD070073837D /* tclPipe.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1208F272A7004A47F5 /* tclPipe.c */; };
+ F9FD30EC0CC1AD070073837D /* tclPkg.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1308F272A7004A47F5 /* tclPkg.c */; };
+ F9FD30ED0CC1AD070073837D /* tclPkgConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1408F272A7004A47F5 /* tclPkgConfig.c */; settings = {COMPILER_FLAGS = "-DCFG_INSTALL_LIBDIR=\\\"$(LIBDIR)\\\" -DCFG_INSTALL_BINDIR=\\\"$(BINDIR)\\\" -DCFG_INSTALL_SCRDIR=\\\"$(TCL_LIBRARY)\\\" -DCFG_INSTALL_INCDIR=\\\"$(INCLUDEDIR)\\\" -DCFG_INSTALL_DOCDIR=\\\"$(MANDIR)\\\" -DCFG_RUNTIME_LIBDIR=\\\"$(LIBDIR)\\\" -DCFG_RUNTIME_BINDIR=\\\"$(BINDIR)\\\" -DCFG_RUNTIME_SCRDIR=\\\"$(TCL_LIBRARY)\\\" -DCFG_RUNTIME_INCDIR=\\\"$(INCLUDEDIR)\\\" -DCFG_RUNTIME_DOCDIR=\\\"$(MANDIR)\\\""; }; };
+ F9FD30EE0CC1AD070073837D /* tclPosixStr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1708F272A7004A47F5 /* tclPosixStr.c */; };
+ F9FD30EF0CC1AD070073837D /* tclPreserve.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1808F272A7004A47F5 /* tclPreserve.c */; };
+ F9FD30F00CC1AD070073837D /* tclProc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1908F272A7004A47F5 /* tclProc.c */; };
+ F9FD30F10CC1AD070073837D /* tclRegexp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1A08F272A7004A47F5 /* tclRegexp.c */; };
+ F9FD30F20CC1AD070073837D /* tclResolve.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1C08F272A7004A47F5 /* tclResolve.c */; };
+ F9FD30F30CC1AD070073837D /* tclResult.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1D08F272A7004A47F5 /* tclResult.c */; };
+ F9FD30F40CC1AD070073837D /* tclScan.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1E08F272A7004A47F5 /* tclScan.c */; };
+ F9FD30F50CC1AD070073837D /* tclStringObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1F08F272A7004A47F5 /* tclStringObj.c */; };
+ F9FD30F60CC1AD070073837D /* tclStrToD.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2408F272A7004A47F5 /* tclStrToD.c */; };
+ F9FD30F70CC1AD070073837D /* tclStubInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2508F272A7004A47F5 /* tclStubInit.c */; };
+ F9FD30F80CC1AD070073837D /* tclStubLib.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2608F272A7004A47F5 /* tclStubLib.c */; };
+ F9FD30F90CC1AD070073837D /* tclThread.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2A08F272A7004A47F5 /* tclThread.c */; };
+ F9FD30FA0CC1AD070073837D /* tclThreadAlloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2B08F272A7004A47F5 /* tclThreadAlloc.c */; };
+ F9FD30FB0CC1AD070073837D /* tclThreadJoin.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2C08F272A7004A47F5 /* tclThreadJoin.c */; };
+ F9FD30FC0CC1AD070073837D /* tclThreadStorage.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2D08F272A7004A47F5 /* tclThreadStorage.c */; };
+ F9FD30FD0CC1AD070073837D /* tclTimer.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2F08F272A7004A47F5 /* tclTimer.c */; };
+ F9FD30FE0CC1AD070073837D /* tclTomMathInterface.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3108F272A7004A47F5 /* tclTomMathInterface.c */; };
+ F9FD30FF0CC1AD070073837D /* tclTrace.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3208F272A7004A47F5 /* tclTrace.c */; };
+ F9FD31000CC1AD070073837D /* tclUtf.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3408F272A7004A47F5 /* tclUtf.c */; };
+ F9FD31010CC1AD070073837D /* tclUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3508F272A7004A47F5 /* tclUtil.c */; };
+ F9FD31020CC1AD070073837D /* tclVar.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3608F272A7004A47F5 /* tclVar.c */; };
+ F9FD31030CC1AD070073837D /* bn_fast_s_mp_mul_digs.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426408F272B3004A47F5 /* bn_fast_s_mp_mul_digs.c */; };
+ F9FD31040CC1AD070073837D /* bn_fast_s_mp_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426608F272B3004A47F5 /* bn_fast_s_mp_sqr.c */; };
+ F9FD31050CC1AD070073837D /* bn_mp_add.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426908F272B3004A47F5 /* bn_mp_add.c */; };
+ F9FD31060CC1AD070073837D /* bn_mp_add_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426A08F272B3004A47F5 /* bn_mp_add_d.c */; };
+ F9FD31070CC1AD070073837D /* bn_mp_and.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426C08F272B3004A47F5 /* bn_mp_and.c */; };
+ F9FD31080CC1AD070073837D /* bn_mp_clamp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426D08F272B3004A47F5 /* bn_mp_clamp.c */; };
+ F9FD31090CC1AD070073837D /* bn_mp_clear.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426E08F272B3004A47F5 /* bn_mp_clear.c */; };
+ F9FD310A0CC1AD070073837D /* bn_mp_clear_multi.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426F08F272B3004A47F5 /* bn_mp_clear_multi.c */; };
+ F9FD310B0CC1AD070073837D /* bn_mp_cmp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427008F272B3004A47F5 /* bn_mp_cmp.c */; };
+ F9FD310C0CC1AD070073837D /* bn_mp_cmp_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */; };
+ F9FD310D0CC1AD070073837D /* bn_mp_cmp_mag.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */; };
+ F9FD310E0CC1AD070073837D /* bn_mp_copy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427408F272B3004A47F5 /* bn_mp_copy.c */; };
+ F9FD310F0CC1AD070073837D /* bn_mp_count_bits.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */; };
+ F9FD31100CC1AD070073837D /* bn_mp_div.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427608F272B3004A47F5 /* bn_mp_div.c */; };
+ F9FD31110CC1AD070073837D /* bn_mp_div_2.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427708F272B3004A47F5 /* bn_mp_div_2.c */; };
+ F9FD31120CC1AD070073837D /* bn_mp_div_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */; };
+ F9FD31130CC1AD070073837D /* bn_mp_div_3.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427908F272B3004A47F5 /* bn_mp_div_3.c */; };
+ F9FD31140CC1AD070073837D /* bn_mp_div_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */; };
+ F9FD31150CC1AD070073837D /* bn_mp_exch.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427E08F272B3004A47F5 /* bn_mp_exch.c */; };
+ F9FD31160CC1AD070073837D /* bn_mp_expt_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427F08F272B3004A47F5 /* bn_mp_expt_d.c */; };
+ F9FD31170CC1AD070073837D /* bn_mp_grow.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428708F272B3004A47F5 /* bn_mp_grow.c */; };
+ F9FD31180CC1AD070073837D /* bn_mp_init.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428808F272B3004A47F5 /* bn_mp_init.c */; };
+ F9FD31190CC1AD070073837D /* bn_mp_init_copy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428908F272B3004A47F5 /* bn_mp_init_copy.c */; };
+ F9FD311A0CC1AD070073837D /* bn_mp_init_multi.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428A08F272B3004A47F5 /* bn_mp_init_multi.c */; };
+ F9FD311B0CC1AD070073837D /* bn_mp_init_set.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428B08F272B3004A47F5 /* bn_mp_init_set.c */; };
+ F9FD311C0CC1AD070073837D /* bn_mp_init_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428D08F272B3004A47F5 /* bn_mp_init_size.c */; };
+ F9FD311D0CC1AD070073837D /* bn_mp_karatsuba_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429208F272B3004A47F5 /* bn_mp_karatsuba_mul.c */; };
+ F9FD311E0CC1AD070073837D /* bn_mp_karatsuba_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429308F272B3004A47F5 /* bn_mp_karatsuba_sqr.c */; };
+ F9FD311F0CC1AD070073837D /* bn_mp_lshd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429508F272B3004A47F5 /* bn_mp_lshd.c */; };
+ F9FD31200CC1AD070073837D /* bn_mp_mod.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429608F272B3004A47F5 /* bn_mp_mod.c */; };
+ F9FD31210CC1AD070073837D /* bn_mp_mod_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429708F272B3004A47F5 /* bn_mp_mod_2d.c */; };
+ F9FD31220CC1AD070073837D /* bn_mp_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429C08F272B3004A47F5 /* bn_mp_mul.c */; };
+ F9FD31230CC1AD070073837D /* bn_mp_mul_2.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429D08F272B3004A47F5 /* bn_mp_mul_2.c */; };
+ F9FD31240CC1AD070073837D /* bn_mp_mul_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429E08F272B3004A47F5 /* bn_mp_mul_2d.c */; };
+ F9FD31250CC1AD070073837D /* bn_mp_mul_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429F08F272B3004A47F5 /* bn_mp_mul_d.c */; };
+ F9FD31260CC1AD070073837D /* bn_mp_neg.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42A208F272B3004A47F5 /* bn_mp_neg.c */; };
+ F9FD31270CC1AD070073837D /* bn_mp_or.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42A308F272B3004A47F5 /* bn_mp_or.c */; };
+ F9FD31280CC1AD070073837D /* bn_mp_radix_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42AB08F272B3004A47F5 /* bn_mp_radix_size.c */; };
+ F9FD31290CC1AD070073837D /* bn_mp_radix_smap.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42AC08F272B3004A47F5 /* bn_mp_radix_smap.c */; };
+ F9FD312A0CC1AD070073837D /* bn_mp_read_radix.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42AE08F272B3004A47F5 /* bn_mp_read_radix.c */; };
+ F9FD312B0CC1AD070073837D /* bn_mp_rshd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42B908F272B3004A47F5 /* bn_mp_rshd.c */; };
+ F9FD312C0CC1AD070073837D /* bn_mp_set.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BA08F272B3004A47F5 /* bn_mp_set.c */; };
+ F9FD312D0CC1AD070073837D /* bn_mp_shrink.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BC08F272B3004A47F5 /* bn_mp_shrink.c */; };
+ F9FD312E0CC1AD070073837D /* bn_mp_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BE08F272B3004A47F5 /* bn_mp_sqr.c */; };
+ F9FD312F0CC1AD070073837D /* bn_mp_sqrt.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C008F272B3004A47F5 /* bn_mp_sqrt.c */; };
+ F9FD31300CC1AD070073837D /* bn_mp_sub.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C108F272B3004A47F5 /* bn_mp_sub.c */; };
+ F9FD31310CC1AD070073837D /* bn_mp_sub_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C208F272B3004A47F5 /* bn_mp_sub_d.c */; };
+ F9FD31320CC1AD070073837D /* bn_mp_to_unsigned_bin_n.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C708F272B3004A47F5 /* bn_mp_to_unsigned_bin_n.c */; };
+ F9FD31330CC1AD070073837D /* bn_mp_to_unsigned_bin.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C608F272B3004A47F5 /* bn_mp_to_unsigned_bin.c */; };
+ F9FD31340CC1AD070073837D /* bn_mp_toom_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C808F272B3004A47F5 /* bn_mp_toom_mul.c */; };
+ F9FD31350CC1AD070073837D /* bn_mp_toom_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C908F272B3004A47F5 /* bn_mp_toom_sqr.c */; };
+ F9FD31360CC1AD070073837D /* bn_mp_toradix_n.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CB08F272B3004A47F5 /* bn_mp_toradix_n.c */; };
+ F9FD31370CC1AD070073837D /* bn_mp_unsigned_bin_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CC08F272B3004A47F5 /* bn_mp_unsigned_bin_size.c */; };
+ F9FD31380CC1AD070073837D /* bn_mp_xor.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CD08F272B3004A47F5 /* bn_mp_xor.c */; };
+ F9FD31390CC1AD070073837D /* bn_mp_zero.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CE08F272B3004A47F5 /* bn_mp_zero.c */; };
+ F9FD313A0CC1AD070073837D /* bn_reverse.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D008F272B3004A47F5 /* bn_reverse.c */; };
+ F9FD313B0CC1AD070073837D /* bn_s_mp_add.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D108F272B3004A47F5 /* bn_s_mp_add.c */; };
+ F9FD313C0CC1AD070073837D /* bn_s_mp_mul_digs.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D308F272B3004A47F5 /* bn_s_mp_mul_digs.c */; };
+ F9FD313D0CC1AD070073837D /* bn_s_mp_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D508F272B3004A47F5 /* bn_s_mp_sqr.c */; };
+ F9FD313E0CC1AD070073837D /* bn_s_mp_sub.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D608F272B3004A47F5 /* bn_s_mp_sub.c */; };
+ F9FD313F0CC1AD070073837D /* bncore.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D708F272B3004A47F5 /* bncore.c */; };
+ F9FD31400CC1AD070073837D /* tclMacOSXBundle.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D433908F272B5004A47F5 /* tclMacOSXBundle.c */; };
+ F9FD31410CC1AD070073837D /* tclMacOSXFCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D433D08F272B5004A47F5 /* tclMacOSXFCmd.c */; };
+ F9FD31420CC1AD070073837D /* tclMacOSXNotify.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D433E08F272B5004A47F5 /* tclMacOSXNotify.c */; };
+ F9FD31430CC1AD070073837D /* tclLoadDyld.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D445B08F272B9004A47F5 /* tclLoadDyld.c */; settings = {COMPILER_FLAGS = "-Wno-deprecated-declarations"; }; };
+ F9FD31440CC1AD070073837D /* tclUnixChan.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D445F08F272B9004A47F5 /* tclUnixChan.c */; };
+ F9FD31450CC1AD070073837D /* tclUnixCompat.c in Sources */ = {isa = PBXBuildFile; fileRef = F9FC77B70AB29E9100B7077D /* tclUnixCompat.c */; };
+ F9FD31460CC1AD070073837D /* tclUnixEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446008F272B9004A47F5 /* tclUnixEvent.c */; };
+ F9FD31470CC1AD070073837D /* tclUnixFCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446108F272B9004A47F5 /* tclUnixFCmd.c */; };
+ F9FD31480CC1AD070073837D /* tclUnixFile.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446208F272B9004A47F5 /* tclUnixFile.c */; };
+ F9FD31490CC1AD070073837D /* tclUnixInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446308F272B9004A47F5 /* tclUnixInit.c */; settings = {COMPILER_FLAGS = "-DTCL_LIBRARY=\\\"$(TCL_LIBRARY)\\\" -DTCL_PACKAGE_PATH=\\\"$(TCL_PACKAGE_PATH)\\\""; }; };
+ F9FD314A0CC1AD070073837D /* tclUnixNotfy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446408F272B9004A47F5 /* tclUnixNotfy.c */; };
+ F9FD314B0CC1AD070073837D /* tclUnixPipe.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446508F272B9004A47F5 /* tclUnixPipe.c */; };
+ F9FD314C0CC1AD070073837D /* tclUnixSock.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446708F272B9004A47F5 /* tclUnixSock.c */; };
+ F9FD314D0CC1AD070073837D /* tclUnixThrd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446908F272B9004A47F5 /* tclUnixThrd.c */; };
+ F9FD314E0CC1AD070073837D /* tclUnixTime.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446B08F272B9004A47F5 /* tclUnixTime.c */; };
+ F9FD314F0CC1AD070073837D /* tk3d.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAAC08F27A39005CB29B /* tk3d.c */; };
+ F9FD31500CC1AD070073837D /* tkArgv.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAAE08F27A39005CB29B /* tkArgv.c */; };
+ F9FD31510CC1AD070073837D /* tkAtom.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAAF08F27A39005CB29B /* tkAtom.c */; };
+ F9FD31520CC1AD070073837D /* tkBind.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB008F27A39005CB29B /* tkBind.c */; };
+ F9FD31530CC1AD070073837D /* tkBitmap.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB108F27A39005CB29B /* tkBitmap.c */; };
+ F9FD31540CC1AD070073837D /* tkButton.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB208F27A39005CB29B /* tkButton.c */; };
+ F9FD31550CC1AD070073837D /* tkCanvArc.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB408F27A39005CB29B /* tkCanvArc.c */; };
+ F9FD31560CC1AD070073837D /* tkCanvas.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB508F27A39005CB29B /* tkCanvas.c */; };
+ F9FD31570CC1AD070073837D /* tkCanvBmap.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB708F27A39005CB29B /* tkCanvBmap.c */; };
+ F9FD31580CC1AD070073837D /* tkCanvImg.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB808F27A39005CB29B /* tkCanvImg.c */; };
+ F9FD31590CC1AD070073837D /* tkCanvLine.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAB908F27A39005CB29B /* tkCanvLine.c */; };
+ F9FD315A0CC1AD070073837D /* tkCanvPoly.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BABA08F27A39005CB29B /* tkCanvPoly.c */; };
+ F9FD315B0CC1AD070073837D /* tkCanvPs.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BABB08F27A39005CB29B /* tkCanvPs.c */; };
+ F9FD315C0CC1AD070073837D /* tkCanvText.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BABD08F27A39005CB29B /* tkCanvText.c */; };
+ F9FD315D0CC1AD070073837D /* tkCanvUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BABE08F27A39005CB29B /* tkCanvUtil.c */; };
+ F9FD315E0CC1AD070073837D /* tkCanvWind.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BABF08F27A39005CB29B /* tkCanvWind.c */; };
+ F9FD315F0CC1AD070073837D /* tkClipboard.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAC008F27A39005CB29B /* tkClipboard.c */; };
+ F9FD31600CC1AD070073837D /* tkCmds.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAC108F27A39005CB29B /* tkCmds.c */; };
+ F9FD31610CC1AD070073837D /* tkColor.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAC208F27A39005CB29B /* tkColor.c */; };
+ F9FD31620CC1AD070073837D /* tkConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAC408F27A39005CB29B /* tkConfig.c */; };
+ F9FD31630CC1AD070073837D /* tkConsole.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAC508F27A39005CB29B /* tkConsole.c */; };
+ F9FD31640CC1AD070073837D /* tkCursor.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAC608F27A39005CB29B /* tkCursor.c */; };
+ F9FD31650CC1AD070073837D /* tkEntry.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAC808F27A39005CB29B /* tkEntry.c */; };
+ F9FD31660CC1AD070073837D /* tkError.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BACA08F27A39005CB29B /* tkError.c */; };
+ F9FD31670CC1AD070073837D /* tkEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BACB08F27A39005CB29B /* tkEvent.c */; };
+ F9FD31680CC1AD070073837D /* tkFileFilter.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BACC08F27A39005CB29B /* tkFileFilter.c */; };
+ F9FD31690CC1AD070073837D /* tkFocus.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BACE08F27A39005CB29B /* tkFocus.c */; };
+ F9FD316A0CC1AD070073837D /* tkFont.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BACF08F27A39005CB29B /* tkFont.c */; };
+ F9FD316B0CC1AD070073837D /* tkFrame.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD108F27A39005CB29B /* tkFrame.c */; };
+ F9FD316C0CC1AD070073837D /* tkGC.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD208F27A39005CB29B /* tkGC.c */; };
+ F9FD316D0CC1AD070073837D /* tkGeometry.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD308F27A39005CB29B /* tkGeometry.c */; };
+ F9FD316E0CC1AD070073837D /* tkGet.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD408F27A39005CB29B /* tkGet.c */; };
+ F9FD316F0CC1AD070073837D /* tkGrab.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD508F27A39005CB29B /* tkGrab.c */; };
+ F9FD31700CC1AD070073837D /* tkGrid.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD608F27A39005CB29B /* tkGrid.c */; };
+ F9FD31710CC1AD070073837D /* tkImage.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD708F27A39005CB29B /* tkImage.c */; };
+ F9FD31720CC1AD070073837D /* tkImgBmap.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD808F27A39005CB29B /* tkImgBmap.c */; };
+ F9FD31730CC1AD070073837D /* tkImgGIF.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAD908F27A39005CB29B /* tkImgGIF.c */; };
+ F9FD31740CC1AD070073837D /* tkImgPhoto.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BADA08F27A39005CB29B /* tkImgPhoto.c */; };
+ F9FD31750CC1AD070073837D /* tkImgPPM.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BADB08F27A39005CB29B /* tkImgPPM.c */; };
+ F9FD31760CC1AD070073837D /* tkListbox.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAE408F27A39005CB29B /* tkListbox.c */; };
+ F9FD31770CC1AD070073837D /* tkMacWinMenu.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAE508F27A39005CB29B /* tkMacWinMenu.c */; };
+ F9FD31780CC1AD070073837D /* tkMain.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAE608F27A39005CB29B /* tkMain.c */; };
+ F9FD31790CC1AD070073837D /* tkMenu.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAE708F27A39005CB29B /* tkMenu.c */; };
+ F9FD317A0CC1AD070073837D /* tkMenubutton.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAE908F27A39005CB29B /* tkMenubutton.c */; };
+ F9FD317B0CC1AD070073837D /* tkMenuDraw.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAEB08F27A39005CB29B /* tkMenuDraw.c */; };
+ F9FD317C0CC1AD070073837D /* tkMessage.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAEC08F27A39005CB29B /* tkMessage.c */; };
+ F9FD317D0CC1AD070073837D /* tkObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAED08F27A39005CB29B /* tkObj.c */; };
+ F9FD317E0CC1AD070073837D /* tkOldConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAEE08F27A39005CB29B /* tkOldConfig.c */; };
+ F9FD317F0CC1AD070073837D /* tkOldTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAFE08F27A39005CB29B /* tkOldTest.c */; };
+ F9FD31800CC1AD070073837D /* tkOption.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAEF08F27A39005CB29B /* tkOption.c */; };
+ F9FD31810CC1AD070073837D /* tkPack.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAF008F27A39005CB29B /* tkPack.c */; };
+ F9FD31820CC1AD070073837D /* tkPanedWindow.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAF108F27A39005CB29B /* tkPanedWindow.c */; };
+ F9FD31830CC1AD070073837D /* tkPlace.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAF208F27A39005CB29B /* tkPlace.c */; };
+ F9FD31850CC1AD070073837D /* tkRectOval.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAF608F27A39005CB29B /* tkRectOval.c */; };
+ F9FD31860CC1AD070073837D /* tkScale.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAF708F27A39005CB29B /* tkScale.c */; };
+ F9FD31870CC1AD070073837D /* tkScrollbar.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAF908F27A39005CB29B /* tkScrollbar.c */; };
+ F9FD31880CC1AD070073837D /* tkSelect.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAFB08F27A39005CB29B /* tkSelect.c */; };
+ F9FD31890CC1AD070073837D /* tkSquare.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAFD08F27A39005CB29B /* tkSquare.c */; };
+ F9FD318A0CC1AD070073837D /* tkStubInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BAFF08F27A39005CB29B /* tkStubInit.c */; };
+ F9FD318B0CC1AD070073837D /* tkStubLib.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0008F27A39005CB29B /* tkStubLib.c */; };
+ F9FD318C0CC1AD070073837D /* tkStyle.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0108F27A39005CB29B /* tkStyle.c */; };
+ F9FD318D0CC1AD070073837D /* tkTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0208F27A39005CB29B /* tkTest.c */; };
+ F9FD318E0CC1AD070073837D /* tkText.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0308F27A39005CB29B /* tkText.c */; };
+ F9FD318F0CC1AD070073837D /* tkTextBTree.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0508F27A39005CB29B /* tkTextBTree.c */; };
+ F9FD31900CC1AD070073837D /* tkTextDisp.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0608F27A39005CB29B /* tkTextDisp.c */; };
+ F9FD31910CC1AD070073837D /* tkTextImage.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0808F27A39005CB29B /* tkTextImage.c */; };
+ F9FD31920CC1AD070073837D /* tkTextIndex.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0908F27A39005CB29B /* tkTextIndex.c */; };
+ F9FD31930CC1AD070073837D /* tkTextMark.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0A08F27A39005CB29B /* tkTextMark.c */; };
+ F9FD31940CC1AD070073837D /* tkTextTag.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0B08F27A39005CB29B /* tkTextTag.c */; };
+ F9FD31950CC1AD070073837D /* tkTextWind.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0C08F27A39005CB29B /* tkTextWind.c */; };
+ F9FD31960CC1AD070073837D /* tkTrig.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0D08F27A39005CB29B /* tkTrig.c */; };
+ F9FD31970CC1AD070073837D /* tkUndo.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB0E08F27A39005CB29B /* tkUndo.c */; };
+ F9FD31980CC1AD070073837D /* tkUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB1008F27A39005CB29B /* tkUtil.c */; };
+ F9FD31990CC1AD070073837D /* tkVisual.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB1108F27A39005CB29B /* tkVisual.c */; };
+ F9FD319A0CC1AD070073837D /* tkWindow.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BB1208F27A39005CB29B /* tkWindow.c */; };
+ F9FD319B0CC1AD070073837D /* ttkBlink.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E10AF786D5000797B5 /* ttkBlink.c */; };
+ F9FD319C0CC1AD070073837D /* ttkButton.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E20AF786D5000797B5 /* ttkButton.c */; };
+ F9FD319D0CC1AD070073837D /* ttkCache.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E30AF786D5000797B5 /* ttkCache.c */; };
+ F9FD319E0CC1AD070073837D /* ttkClamTheme.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E40AF786D5000797B5 /* ttkClamTheme.c */; };
+ F9FD319F0CC1AD070073837D /* ttkClassicTheme.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E50AF786D5000797B5 /* ttkClassicTheme.c */; };
+ F9FD31A00CC1AD070073837D /* ttkDefaultTheme.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E70AF786D5000797B5 /* ttkDefaultTheme.c */; };
+ F9FD31A10CC1AD070073837D /* ttkElements.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E80AF786D5000797B5 /* ttkElements.c */; };
+ F9FD31A20CC1AD070073837D /* ttkEntry.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887E90AF786D5000797B5 /* ttkEntry.c */; };
+ F9FD31A30CC1AD070073837D /* ttkFrame.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887EA0AF786D5000797B5 /* ttkFrame.c */; };
+ F9FD31A40CC1AD070073837D /* ttkImage.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887EB0AF786D5000797B5 /* ttkImage.c */; };
+ F9FD31A50CC1AD070073837D /* ttkInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887EC0AF786D5000797B5 /* ttkInit.c */; };
+ F9FD31A60CC1AD070073837D /* ttkLabel.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887ED0AF786D5000797B5 /* ttkLabel.c */; };
+ F9FD31A70CC1AD070073837D /* ttkLayout.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887EE0AF786D5000797B5 /* ttkLayout.c */; };
+ F9FD31A80CC1AD070073837D /* ttkManager.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887EF0AF786D5000797B5 /* ttkManager.c */; };
+ F9FD31A90CC1AD070073837D /* ttkNotebook.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F10AF786D5000797B5 /* ttkNotebook.c */; };
+ F9FD31AA0CC1AD070073837D /* ttkPanedwindow.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F20AF786D5000797B5 /* ttkPanedwindow.c */; };
+ F9FD31AB0CC1AD070073837D /* ttkProgress.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F30AF786D5000797B5 /* ttkProgress.c */; };
+ F9FD31AC0CC1AD070073837D /* ttkScale.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F40AF786D5000797B5 /* ttkScale.c */; };
+ F9FD31AD0CC1AD070073837D /* ttkScroll.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F50AF786D5000797B5 /* ttkScroll.c */; };
+ F9FD31AE0CC1AD070073837D /* ttkScrollbar.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F60AF786D5000797B5 /* ttkScrollbar.c */; };
+ F9FD31AF0CC1AD070073837D /* ttkSeparator.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F70AF786D5000797B5 /* ttkSeparator.c */; };
+ F9FD31B00CC1AD070073837D /* ttkSquare.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F80AF786D5000797B5 /* ttkSquare.c */; };
+ F9FD31B10CC1AD070073837D /* ttkState.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887F90AF786D5000797B5 /* ttkState.c */; };
+ F9FD31B20CC1AD070073837D /* ttkStubInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887FA0AF786D5000797B5 /* ttkStubInit.c */; };
+ F9FD31B30CC1AD070073837D /* ttkStubLib.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887FB0AF786D5000797B5 /* ttkStubLib.c */; };
+ F9FD31B40CC1AD070073837D /* ttkTagSet.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887FC0AF786D5000797B5 /* ttkTagSet.c */; };
+ F9FD31B50CC1AD070073837D /* ttkTheme.c in Sources */ = {isa = PBXBuildFile; fileRef = F96887FD0AF786D5000797B5 /* ttkTheme.c */; };
+ F9FD31B60CC1AD070073837D /* ttkTrace.c in Sources */ = {isa = PBXBuildFile; fileRef = F96888000AF786D5000797B5 /* ttkTrace.c */; };
+ F9FD31B70CC1AD070073837D /* ttkTrack.c in Sources */ = {isa = PBXBuildFile; fileRef = F96888010AF786D5000797B5 /* ttkTrack.c */; };
+ F9FD31B80CC1AD070073837D /* ttkTreeview.c in Sources */ = {isa = PBXBuildFile; fileRef = F96888020AF786D5000797B5 /* ttkTreeview.c */; };
+ F9FD31B90CC1AD070073837D /* ttkWidget.c in Sources */ = {isa = PBXBuildFile; fileRef = F96888030AF786D5000797B5 /* ttkWidget.c */; };
+ F9FD31DA0CC1AD070073837D /* tkAppInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC7508F27A3D005CB29B /* tkAppInit.c */; settings = {COMPILER_FLAGS = "-DTK_TEST"; }; };
+ F9FD31DB0CC1AD070073837D /* tkUnix3d.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC7908F27A3D005CB29B /* tkUnix3d.c */; };
+ F9FD31DC0CC1AD070073837D /* tkUnixScale.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC8C08F27A3D005CB29B /* tkUnixScale.c */; };
+ F9FD31E20CC1AD070073837D /* tclDTrace.d in Sources */ = {isa = PBXBuildFile; fileRef = F9F4415D0C8BAE6F00BCCD67 /* tclDTrace.d */; };
+ F9FD31E40CC1AD070073837D /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F966C07408F2820D005CB29B /* CoreFoundation.framework */; };
+ F9FD31F80CC1ADB70073837D /* tkUnixCursor.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC7D08F27A3D005CB29B /* tkUnixCursor.c */; };
+ F9FD31FA0CC1ADB70073837D /* tkUnixKey.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC8708F27A3D005CB29B /* tkUnixKey.c */; };
+ F9FD31FB0CC1ADB70073837D /* tkUnixXId.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC9108F27A3D005CB29B /* tkUnixXId.c */; };
+ F9FD31FC0CC1ADB70073837D /* tkUnixInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC8508F27A3D005CB29B /* tkUnixInit.c */; };
+ F9FD31FD0CC1ADB70073837D /* tkUnixEmbed.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC8108F27A3D005CB29B /* tkUnixEmbed.c */; };
+ F9FD31FE0CC1ADB70073837D /* tkUnixSend.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC8F08F27A3D005CB29B /* tkUnixSend.c */; };
+ F9FD31FF0CC1ADB70073837D /* tkUnixFocus.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC8308F27A3D005CB29B /* tkUnixFocus.c */; };
+ F9FD32000CC1ADB70073837D /* tkUnixWm.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC9008F27A3D005CB29B /* tkUnixWm.c */; };
+ F9FD32010CC1ADB70073837D /* tkUnixRFont.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC8B08F27A3D005CB29B /* tkUnixRFont.c */; };
+ F9FD32020CC1ADB70073837D /* tkUnix.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC7808F27A3D005CB29B /* tkUnix.c */; };
+ F9FD32030CC1ADB70073837D /* tkUnixMenu.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC8808F27A3D005CB29B /* tkUnixMenu.c */; };
+ F9FD32040CC1ADB70073837D /* tkUnixConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC7C08F27A3D005CB29B /* tkUnixConfig.c */; };
+ F9FD32050CC1ADB70073837D /* tkUnixDraw.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC8008F27A3D005CB29B /* tkUnixDraw.c */; };
+ F9FD32060CC1ADB70073837D /* tkUnixDialog.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC7F08F27A3D005CB29B /* tkUnixDialog.c */; };
+ F9FD32070CC1ADB70073837D /* tkUnixSelect.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC8E08F27A3D005CB29B /* tkUnixSelect.c */; };
+ F9FD32080CC1ADB70073837D /* tkUnixEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC8208F27A3D005CB29B /* tkUnixEvent.c */; };
+ F9FD32090CC1ADB70073837D /* tkUnixColor.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC7B08F27A3D005CB29B /* tkUnixColor.c */; };
+ F9FD320A0CC1ADB70073837D /* tkUnixButton.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC7A08F27A3D005CB29B /* tkUnixButton.c */; };
+ F9FD320B0CC1ADB70073837D /* tkUnixMenubu.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC8908F27A3D005CB29B /* tkUnixMenubu.c */; };
+ F9FD320C0CC1ADB70073837D /* tkUnixScrlbr.c in Sources */ = {isa = PBXBuildFile; fileRef = F966BC8D08F27A3D005CB29B /* tkUnixScrlbr.c */; };
+ F9FD32170CC1AF170073837D /* libX11.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F9FD32140CC1AF170073837D /* libX11.dylib */; };
+ F9FD32180CC1AF170073837D /* libXext.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F9FD32150CC1AF170073837D /* libXext.dylib */; };
+ F9FD32190CC1AF170073837D /* libXss.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F9FD32160CC1AF170073837D /* libXss.dylib */; };
+ F9FD349B0CC1BB0D0073837D /* libfreetype.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F9FD34990CC1BB0D0073837D /* libfreetype.dylib */; };
+ F9FD349C0CC1BB0D0073837D /* libXft.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F9FD349A0CC1BB0D0073837D /* libXft.dylib */; };
+ F9FD34C40CC1BBD70073837D /* libfontconfig.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F9FD34C30CC1BBD70073837D /* libfontconfig.dylib */; };
+ F9FFAF1D0DFDDB26007F8A6A /* tclIORTrans.c in Sources */ = {isa = PBXBuildFile; fileRef = F95D77E90DFD820D00A8BF6F /* tclIORTrans.c */; };
+ F9FFAF1F0DFDDB2F007F8A6A /* tclOO.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599B20DF1F75400E04F67 /* tclOO.c */; };
+ F9FFAF200DFDDB32007F8A6A /* tclOOBasic.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599B60DF1F76100E04F67 /* tclOOBasic.c */; };
+ F9FFAF210DFDDB32007F8A6A /* tclOOCall.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599B80DF1F76600E04F67 /* tclOOCall.c */; };
+ F9FFAF220DFDDB34007F8A6A /* tclOODefineCmds.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599BB0DF1F77000E04F67 /* tclOODefineCmds.c */; };
+ F9FFAF230DFDDB35007F8A6A /* tclOOInfo.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599BD0DF1F77400E04F67 /* tclOOInfo.c */; };
+ F9FFAF240DFDDB36007F8A6A /* tclOOMethod.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599C10DF1F78300E04F67 /* tclOOMethod.c */; };
+ F9FFAF250DFDDB37007F8A6A /* tclOOStubInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599C30DF1F78800E04F67 /* tclOOStubInit.c */; };
+ F9FFAF260DFDDB38007F8A6A /* tclOOStubLib.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599C50DF1F78D00E04F67 /* tclOOStubLib.c */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 8DD76FB20486AB0100D96B5E /* tktest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tktest; sourceTree = BUILT_PRODUCTS_DIR; };
+ F9099B8A0CC67D30005A9580 /* textpeer.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = textpeer.tcl; sourceTree = "<group>"; };
+ F9099B8B0CC67D3E005A9580 /* ttkbut.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = ttkbut.tcl; sourceTree = "<group>"; };
+ F9152B080EAF8A5000CD5C7B /* tkBusy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkBusy.c; sourceTree = "<group>"; };
+ F91543270EF201A90032D1E8 /* fontchoose.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fontchoose.tcl; sourceTree = "<group>"; };
+ F915432A0EF201CF0032D1E8 /* zlib.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = zlib.test; sourceTree = "<group>"; };
+ F915432D0EF201EE0032D1E8 /* zlib.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = zlib.n; sourceTree = "<group>"; };
+ F9183E640EFC80CD0030B814 /* throw.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = throw.n; sourceTree = "<group>"; };
+ F9183E650EFC80D70030B814 /* try.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = try.n; sourceTree = "<group>"; };
+ F9183E6A0EFC81560030B814 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F9183E8F0EFC817B0030B814 /* tdbc */ = {isa = PBXFileReference; lastKnownFileType = folder; path = tdbc; sourceTree = "<group>"; };
+ F91DC23C0E44C51B002CB8D1 /* nre.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = nre.test; sourceTree = "<group>"; };
+ F91E62260C1AE686006C9D96 /* Tclsh-Info.plist.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = "Tclsh-Info.plist.in"; sourceTree = "<group>"; };
+ F92240290D7C620F005EC715 /* knightstour.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = knightstour.tcl; sourceTree = "<group>"; };
+ F92D7F100DE777240033A13A /* tsdPerf.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tsdPerf.tcl; sourceTree = "<group>"; };
+ F92EE8BE0E62F846001A6E80 /* tkImgPhInstance.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkImgPhInstance.c; sourceTree = "<group>"; };
+ F93599B20DF1F75400E04F67 /* tclOO.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOO.c; sourceTree = "<group>"; };
+ F93599B40DF1F75900E04F67 /* tclOO.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclOO.decls; sourceTree = "<group>"; };
+ F93599B50DF1F75D00E04F67 /* tclOO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclOO.h; sourceTree = "<group>"; };
+ F93599B60DF1F76100E04F67 /* tclOOBasic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOBasic.c; sourceTree = "<group>"; };
+ F93599B80DF1F76600E04F67 /* tclOOCall.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOCall.c; sourceTree = "<group>"; };
+ F93599BA0DF1F76A00E04F67 /* tclOODecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclOODecls.h; sourceTree = "<group>"; };
+ F93599BB0DF1F77000E04F67 /* tclOODefineCmds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOODefineCmds.c; sourceTree = "<group>"; };
+ F93599BD0DF1F77400E04F67 /* tclOOInfo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOInfo.c; sourceTree = "<group>"; };
+ F93599BF0DF1F77900E04F67 /* tclOOInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclOOInt.h; sourceTree = "<group>"; };
+ F93599C00DF1F77D00E04F67 /* tclOOIntDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclOOIntDecls.h; sourceTree = "<group>"; };
+ F93599C10DF1F78300E04F67 /* tclOOMethod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOMethod.c; sourceTree = "<group>"; };
+ F93599C30DF1F78800E04F67 /* tclOOStubInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOStubInit.c; sourceTree = "<group>"; };
+ F93599C50DF1F78D00E04F67 /* tclOOStubLib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOStubLib.c; sourceTree = "<group>"; };
+ F93599C80DF1F81900E04F67 /* oo.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = oo.test; sourceTree = "<group>"; };
+ F93599CF0DF1F87F00E04F67 /* Class.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Class.3; sourceTree = "<group>"; };
+ F93599D00DF1F89E00E04F67 /* class.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = class.n; sourceTree = "<group>"; };
+ F93599D20DF1F8DF00E04F67 /* copy.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = copy.n; sourceTree = "<group>"; };
+ F93599D30DF1F8F500E04F67 /* define.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = define.n; sourceTree = "<group>"; };
+ F93599D40DF1F91900E04F67 /* Method.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Method.3; sourceTree = "<group>"; };
+ F93599D50DF1F93700E04F67 /* my.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = my.n; sourceTree = "<group>"; };
+ F93599D60DF1F95000E04F67 /* next.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = next.n; sourceTree = "<group>"; };
+ F93599D70DF1F96800E04F67 /* object.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = object.n; sourceTree = "<group>"; };
+ F93599D80DF1F98300E04F67 /* self.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = self.n; sourceTree = "<group>"; };
+ F936FCD70CCD984500716967 /* ttkprogress.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = ttkprogress.tcl; sourceTree = "<group>"; };
+ F936FCD80CCD984600716967 /* tree.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tree.tcl; sourceTree = "<group>"; };
+ F936FCD90CCD984600716967 /* toolbar.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = toolbar.tcl; sourceTree = "<group>"; };
+ F936FCDA0CCD984600716967 /* ttknote.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = ttknote.tcl; sourceTree = "<group>"; };
+ F936FCDB0CCD984600716967 /* combo.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = combo.tcl; sourceTree = "<group>"; };
+ F93E5EFD09CF8711008FA367 /* tkMacOSXFont.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMacOSXFont.h; sourceTree = "<group>"; };
+ F94523A10E6FC2AC00C1D987 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
+ F946FB8B0FBE3AED00CD6495 /* itcl */ = {isa = PBXFileReference; lastKnownFileType = folder; path = itcl; sourceTree = "<group>"; };
+ F95D77E90DFD820D00A8BF6F /* tclIORTrans.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIORTrans.c; sourceTree = "<group>"; };
+ F95D8D4B0F1715610006B020 /* Tk.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = Tk.icns; sourceTree = "<group>"; };
+ F95D8D4C0F1715610006B020 /* Tk.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = Tk.tiff; sourceTree = "<group>"; };
+ F95FAFF90B34F1130072E431 /* macOSXLoad.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = macOSXLoad.test; sourceTree = "<group>"; };
+ F962F7C60DADC26200648DB8 /* vsapi.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = vsapi.test; sourceTree = "<group>"; };
+ F96437C90EF0D4B2003F468E /* tclZlib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclZlib.c; sourceTree = "<group>"; };
+ F96437E60EF0D652003F468E /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = /usr/lib/libz.dylib; sourceTree = "<absolute>"; };
+ F966BA0408F27A37005CB29B /* error.xbm */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = error.xbm; sourceTree = "<group>"; };
+ F966BA0508F27A37005CB29B /* gray12.xbm */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = gray12.xbm; sourceTree = "<group>"; };
+ F966BA0608F27A37005CB29B /* gray25.xbm */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = gray25.xbm; sourceTree = "<group>"; };
+ F966BA0708F27A37005CB29B /* gray50.xbm */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = gray50.xbm; sourceTree = "<group>"; };
+ F966BA0808F27A37005CB29B /* gray75.xbm */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = gray75.xbm; sourceTree = "<group>"; };
+ F966BA0908F27A37005CB29B /* hourglass.xbm */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = hourglass.xbm; sourceTree = "<group>"; };
+ F966BA0A08F27A37005CB29B /* info.xbm */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = info.xbm; sourceTree = "<group>"; };
+ F966BA0B08F27A37005CB29B /* questhead.xbm */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = questhead.xbm; sourceTree = "<group>"; };
+ F966BA0C08F27A37005CB29B /* question.xbm */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = question.xbm; sourceTree = "<group>"; };
+ F966BA0D08F27A37005CB29B /* warning.xbm */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = warning.xbm; sourceTree = "<group>"; };
+ F966BA0E08F27A37005CB29B /* ChangeLog */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = ChangeLog; sourceTree = "<group>"; };
+ F966BA0F08F27A37005CB29B /* changes */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = changes; sourceTree = "<group>"; };
+ F966BA1108F27A37005CB29B /* 3DBorder.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = 3DBorder.3; sourceTree = "<group>"; };
+ F966BA1208F27A37005CB29B /* AddOption.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AddOption.3; sourceTree = "<group>"; };
+ F966BA1308F27A37005CB29B /* bell.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = bell.n; sourceTree = "<group>"; };
+ F966BA1408F27A37005CB29B /* bind.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = bind.n; sourceTree = "<group>"; };
+ F966BA1508F27A37005CB29B /* BindTable.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = BindTable.3; sourceTree = "<group>"; };
+ F966BA1608F27A37005CB29B /* bindtags.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = bindtags.n; sourceTree = "<group>"; };
+ F966BA1708F27A37005CB29B /* bitmap.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = bitmap.n; sourceTree = "<group>"; };
+ F966BA1808F27A37005CB29B /* button.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = button.n; sourceTree = "<group>"; };
+ F966BA1908F27A37005CB29B /* canvas.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = canvas.n; sourceTree = "<group>"; };
+ F966BA1A08F27A37005CB29B /* CanvPsY.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CanvPsY.3; sourceTree = "<group>"; };
+ F966BA1B08F27A37005CB29B /* CanvTkwin.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CanvTkwin.3; sourceTree = "<group>"; };
+ F966BA1C08F27A37005CB29B /* CanvTxtInfo.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CanvTxtInfo.3; sourceTree = "<group>"; };
+ F966BA1D08F27A37005CB29B /* checkbutton.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = checkbutton.n; sourceTree = "<group>"; };
+ F966BA1E08F27A37005CB29B /* chooseColor.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = chooseColor.n; sourceTree = "<group>"; };
+ F966BA1F08F27A37005CB29B /* chooseDirectory.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = chooseDirectory.n; sourceTree = "<group>"; };
+ F966BA2008F27A37005CB29B /* Clipboard.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Clipboard.3; sourceTree = "<group>"; };
+ F966BA2108F27A37005CB29B /* clipboard.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = clipboard.n; sourceTree = "<group>"; };
+ F966BA2208F27A37005CB29B /* ClrSelect.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ClrSelect.3; sourceTree = "<group>"; };
+ F966BA2308F27A37005CB29B /* colors.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = colors.n; sourceTree = "<group>"; };
+ F966BA2408F27A37005CB29B /* ConfigWidg.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ConfigWidg.3; sourceTree = "<group>"; };
+ F966BA2508F27A37005CB29B /* ConfigWind.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ConfigWind.3; sourceTree = "<group>"; };
+ F966BA2608F27A37005CB29B /* console.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = console.n; sourceTree = "<group>"; };
+ F966BA2708F27A37005CB29B /* CoordToWin.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CoordToWin.3; sourceTree = "<group>"; };
+ F966BA2808F27A37005CB29B /* CrtCmHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtCmHdlr.3; sourceTree = "<group>"; };
+ F966BA2908F27A37005CB29B /* CrtErrHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtErrHdlr.3; sourceTree = "<group>"; };
+ F966BA2A08F27A37005CB29B /* CrtGenHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtGenHdlr.3; sourceTree = "<group>"; };
+ F966BA2B08F27A37005CB29B /* CrtImgType.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtImgType.3; sourceTree = "<group>"; };
+ F966BA2C08F27A37005CB29B /* CrtItemType.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtItemType.3; sourceTree = "<group>"; };
+ F966BA2D08F27A37005CB29B /* CrtPhImgFmt.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtPhImgFmt.3; sourceTree = "<group>"; };
+ F966BA2E08F27A37005CB29B /* CrtSelHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtSelHdlr.3; sourceTree = "<group>"; };
+ F966BA2F08F27A37005CB29B /* CrtWindow.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtWindow.3; sourceTree = "<group>"; };
+ F966BA3008F27A37005CB29B /* cursors.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = cursors.n; sourceTree = "<group>"; };
+ F966BA3108F27A37005CB29B /* DeleteImg.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DeleteImg.3; sourceTree = "<group>"; };
+ F966BA3208F27A37005CB29B /* destroy.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = destroy.n; sourceTree = "<group>"; };
+ F966BA3308F27A37005CB29B /* dialog.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = dialog.n; sourceTree = "<group>"; };
+ F966BA3408F27A37005CB29B /* DrawFocHlt.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DrawFocHlt.3; sourceTree = "<group>"; };
+ F966BA3508F27A37005CB29B /* entry.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = entry.n; sourceTree = "<group>"; };
+ F966BA3608F27A37005CB29B /* event.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = event.n; sourceTree = "<group>"; };
+ F966BA3708F27A37005CB29B /* EventHndlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = EventHndlr.3; sourceTree = "<group>"; };
+ F966BA3808F27A37005CB29B /* FindPhoto.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = FindPhoto.3; sourceTree = "<group>"; };
+ F966BA3908F27A37005CB29B /* focus.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = focus.n; sourceTree = "<group>"; };
+ F966BA3A08F27A37005CB29B /* focusNext.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = focusNext.n; sourceTree = "<group>"; };
+ F966BA3B08F27A37005CB29B /* font.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = font.n; sourceTree = "<group>"; };
+ F966BA3C08F27A37005CB29B /* FontId.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = FontId.3; sourceTree = "<group>"; };
+ F966BA3D08F27A37005CB29B /* frame.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = frame.n; sourceTree = "<group>"; };
+ F966BA3E08F27A37005CB29B /* FreeXId.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = FreeXId.3; sourceTree = "<group>"; };
+ F966BA3F08F27A37005CB29B /* GeomReq.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GeomReq.3; sourceTree = "<group>"; };
+ F966BA4008F27A37005CB29B /* GetAnchor.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetAnchor.3; sourceTree = "<group>"; };
+ F966BA4108F27A37005CB29B /* GetBitmap.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetBitmap.3; sourceTree = "<group>"; };
+ F966BA4208F27A37005CB29B /* GetCapStyl.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetCapStyl.3; sourceTree = "<group>"; };
+ F966BA4308F27A37005CB29B /* GetClrmap.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetClrmap.3; sourceTree = "<group>"; };
+ F966BA4408F27A37005CB29B /* GetColor.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetColor.3; sourceTree = "<group>"; };
+ F966BA4508F27A37005CB29B /* GetCursor.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetCursor.3; sourceTree = "<group>"; };
+ F966BA4608F27A37005CB29B /* GetDash.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetDash.3; sourceTree = "<group>"; };
+ F966BA4708F27A37005CB29B /* GetFont.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetFont.3; sourceTree = "<group>"; };
+ F966BA4808F27A37005CB29B /* GetGC.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetGC.3; sourceTree = "<group>"; };
+ F966BA4908F27A37005CB29B /* GetHINSTANCE.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetHINSTANCE.3; sourceTree = "<group>"; };
+ F966BA4A08F27A37005CB29B /* GetHWND.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetHWND.3; sourceTree = "<group>"; };
+ F966BA4B08F27A37005CB29B /* GetImage.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetImage.3; sourceTree = "<group>"; };
+ F966BA4C08F27A37005CB29B /* GetJoinStl.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetJoinStl.3; sourceTree = "<group>"; };
+ F966BA4D08F27A37005CB29B /* GetJustify.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetJustify.3; sourceTree = "<group>"; };
+ F966BA4E08F27A37005CB29B /* getOpenFile.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = getOpenFile.n; sourceTree = "<group>"; };
+ F966BA4F08F27A37005CB29B /* GetOption.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetOption.3; sourceTree = "<group>"; };
+ F966BA5008F27A38005CB29B /* GetPixels.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetPixels.3; sourceTree = "<group>"; };
+ F966BA5108F27A38005CB29B /* GetPixmap.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetPixmap.3; sourceTree = "<group>"; };
+ F966BA5208F27A38005CB29B /* GetRelief.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetRelief.3; sourceTree = "<group>"; };
+ F966BA5308F27A38005CB29B /* GetRootCrd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetRootCrd.3; sourceTree = "<group>"; };
+ F966BA5408F27A38005CB29B /* GetScroll.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetScroll.3; sourceTree = "<group>"; };
+ F966BA5508F27A38005CB29B /* GetSelect.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetSelect.3; sourceTree = "<group>"; };
+ F966BA5608F27A38005CB29B /* GetUid.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetUid.3; sourceTree = "<group>"; };
+ F966BA5708F27A38005CB29B /* GetVisual.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetVisual.3; sourceTree = "<group>"; };
+ F966BA5808F27A38005CB29B /* GetVRoot.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetVRoot.3; sourceTree = "<group>"; };
+ F966BA5908F27A38005CB29B /* Grab.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Grab.3; sourceTree = "<group>"; };
+ F966BA5A08F27A38005CB29B /* grab.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = grab.n; sourceTree = "<group>"; };
+ F966BA5B08F27A38005CB29B /* grid.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = grid.n; sourceTree = "<group>"; };
+ F966BA5C08F27A38005CB29B /* HandleEvent.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = HandleEvent.3; sourceTree = "<group>"; };
+ F966BA5D08F27A38005CB29B /* HWNDToWindow.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = HWNDToWindow.3; sourceTree = "<group>"; };
+ F966BA5E08F27A38005CB29B /* IdToWindow.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = IdToWindow.3; sourceTree = "<group>"; };
+ F966BA5F08F27A38005CB29B /* image.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = image.n; sourceTree = "<group>"; };
+ F966BA6008F27A38005CB29B /* ImgChanged.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ImgChanged.3; sourceTree = "<group>"; };
+ F966BA6108F27A38005CB29B /* Inactive.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Inactive.3; sourceTree = "<group>"; };
+ F966BA6208F27A38005CB29B /* InternAtom.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = InternAtom.3; sourceTree = "<group>"; };
+ F966BA6308F27A38005CB29B /* keysyms.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = keysyms.n; sourceTree = "<group>"; };
+ F966BA6408F27A38005CB29B /* label.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = label.n; sourceTree = "<group>"; };
+ F966BA6508F27A38005CB29B /* labelframe.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = labelframe.n; sourceTree = "<group>"; };
+ F966BA6608F27A38005CB29B /* listbox.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = listbox.n; sourceTree = "<group>"; };
+ F966BA6708F27A38005CB29B /* loadTk.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = loadTk.n; sourceTree = "<group>"; };
+ F966BA6808F27A38005CB29B /* lower.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lower.n; sourceTree = "<group>"; };
+ F966BA6908F27A38005CB29B /* MainLoop.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = MainLoop.3; sourceTree = "<group>"; };
+ F966BA6A08F27A38005CB29B /* MaintGeom.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = MaintGeom.3; sourceTree = "<group>"; };
+ F966BA6B08F27A38005CB29B /* MainWin.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = MainWin.3; sourceTree = "<group>"; };
+ F966BA6D08F27A38005CB29B /* ManageGeom.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ManageGeom.3; sourceTree = "<group>"; };
+ F966BA6E08F27A38005CB29B /* MapWindow.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = MapWindow.3; sourceTree = "<group>"; };
+ F966BA6F08F27A38005CB29B /* MeasureChar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = MeasureChar.3; sourceTree = "<group>"; };
+ F966BA7008F27A38005CB29B /* menu.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = menu.n; sourceTree = "<group>"; };
+ F966BA7108F27A38005CB29B /* menubar.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = menubar.n; sourceTree = "<group>"; };
+ F966BA7208F27A38005CB29B /* menubutton.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = menubutton.n; sourceTree = "<group>"; };
+ F966BA7308F27A38005CB29B /* message.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = message.n; sourceTree = "<group>"; };
+ F966BA7408F27A38005CB29B /* messageBox.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = messageBox.n; sourceTree = "<group>"; };
+ F966BA7508F27A38005CB29B /* MoveToplev.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = MoveToplev.3; sourceTree = "<group>"; };
+ F966BA7608F27A38005CB29B /* Name.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Name.3; sourceTree = "<group>"; };
+ F966BA7708F27A38005CB29B /* NameOfImg.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = NameOfImg.3; sourceTree = "<group>"; };
+ F966BA7808F27A38005CB29B /* option.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = option.n; sourceTree = "<group>"; };
+ F966BA7908F27A38005CB29B /* optionMenu.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = optionMenu.n; sourceTree = "<group>"; };
+ F966BA7A08F27A38005CB29B /* options.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = options.n; sourceTree = "<group>"; };
+ F966BA7B08F27A38005CB29B /* OwnSelect.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = OwnSelect.3; sourceTree = "<group>"; };
+ F966BA7C08F27A38005CB29B /* pack-old.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = "pack-old.n"; sourceTree = "<group>"; };
+ F966BA7D08F27A38005CB29B /* pack.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = pack.n; sourceTree = "<group>"; };
+ F966BA7E08F27A38005CB29B /* palette.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = palette.n; sourceTree = "<group>"; };
+ F966BA7F08F27A38005CB29B /* panedwindow.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = panedwindow.n; sourceTree = "<group>"; };
+ F966BA8008F27A38005CB29B /* ParseArgv.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ParseArgv.3; sourceTree = "<group>"; };
+ F966BA8108F27A38005CB29B /* photo.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = photo.n; sourceTree = "<group>"; };
+ F966BA8208F27A38005CB29B /* place.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = place.n; sourceTree = "<group>"; };
+ F966BA8308F27A38005CB29B /* popup.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = popup.n; sourceTree = "<group>"; };
+ F966BA8408F27A38005CB29B /* QWinEvent.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = QWinEvent.3; sourceTree = "<group>"; };
+ F966BA8508F27A38005CB29B /* radiobutton.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = radiobutton.n; sourceTree = "<group>"; };
+ F966BA8608F27A38005CB29B /* raise.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = raise.n; sourceTree = "<group>"; };
+ F966BA8708F27A38005CB29B /* Restack.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Restack.3; sourceTree = "<group>"; };
+ F966BA8808F27A38005CB29B /* RestrictEv.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RestrictEv.3; sourceTree = "<group>"; };
+ F966BA8908F27A38005CB29B /* scale.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = scale.n; sourceTree = "<group>"; };
+ F966BA8A08F27A38005CB29B /* scrollbar.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = scrollbar.n; sourceTree = "<group>"; };
+ F966BA8B08F27A38005CB29B /* selection.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = selection.n; sourceTree = "<group>"; };
+ F966BA8C08F27A38005CB29B /* send.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = send.n; sourceTree = "<group>"; };
+ F966BA8D08F27A38005CB29B /* SetAppName.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetAppName.3; sourceTree = "<group>"; };
+ F966BA8E08F27A38005CB29B /* SetCaret.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetCaret.3; sourceTree = "<group>"; };
+ F966BA8F08F27A38005CB29B /* SetClass.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetClass.3; sourceTree = "<group>"; };
+ F966BA9008F27A38005CB29B /* SetClassProcs.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetClassProcs.3; sourceTree = "<group>"; };
+ F966BA9108F27A38005CB29B /* SetGrid.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetGrid.3; sourceTree = "<group>"; };
+ F966BA9208F27A38005CB29B /* SetOptions.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetOptions.3; sourceTree = "<group>"; };
+ F966BA9308F27A38005CB29B /* SetVisual.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetVisual.3; sourceTree = "<group>"; };
+ F966BA9408F27A38005CB29B /* spinbox.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = spinbox.n; sourceTree = "<group>"; };
+ F966BA9508F27A38005CB29B /* StrictMotif.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StrictMotif.3; sourceTree = "<group>"; };
+ F966BA9608F27A38005CB29B /* text.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = text.n; sourceTree = "<group>"; };
+ F966BA9708F27A38005CB29B /* TextLayout.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TextLayout.3; sourceTree = "<group>"; };
+ F966BA9808F27A38005CB29B /* tk.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tk.n; sourceTree = "<group>"; };
+ F966BA9A08F27A38005CB29B /* Tk_Init.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Tk_Init.3; sourceTree = "<group>"; };
+ F966BA9B08F27A38005CB29B /* Tk_Main.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Tk_Main.3; sourceTree = "<group>"; };
+ F966BA9C08F27A38005CB29B /* tkerror.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tkerror.n; sourceTree = "<group>"; };
+ F966BA9D08F27A38005CB29B /* TkInitStubs.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TkInitStubs.3; sourceTree = "<group>"; };
+ F966BA9E08F27A38005CB29B /* tkvars.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tkvars.n; sourceTree = "<group>"; };
+ F966BA9F08F27A38005CB29B /* tkwait.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tkwait.n; sourceTree = "<group>"; };
+ F966BAA008F27A38005CB29B /* toplevel.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = toplevel.n; sourceTree = "<group>"; };
+ F966BAA108F27A38005CB29B /* WindowId.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = WindowId.3; sourceTree = "<group>"; };
+ F966BAA208F27A38005CB29B /* winfo.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = winfo.n; sourceTree = "<group>"; };
+ F966BAA308F27A38005CB29B /* wish.1 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = wish.1; sourceTree = "<group>"; };
+ F966BAA408F27A38005CB29B /* wm.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = wm.n; sourceTree = "<group>"; };
+ F966BAA608F27A38005CB29B /* default.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = default.h; sourceTree = "<group>"; };
+ F966BAA708F27A38005CB29B /* ks_names.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ks_names.h; sourceTree = "<group>"; };
+ F966BAA908F27A39005CB29B /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F966BAAA08F27A39005CB29B /* tk.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tk.decls; sourceTree = "<group>"; };
+ F966BAAB08F27A39005CB29B /* tk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tk.h; sourceTree = "<group>"; };
+ F966BAAC08F27A39005CB29B /* tk3d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tk3d.c; sourceTree = "<group>"; };
+ F966BAAD08F27A39005CB29B /* tk3d.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tk3d.h; sourceTree = "<group>"; };
+ F966BAAE08F27A39005CB29B /* tkArgv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkArgv.c; sourceTree = "<group>"; };
+ F966BAAF08F27A39005CB29B /* tkAtom.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkAtom.c; sourceTree = "<group>"; };
+ F966BAB008F27A39005CB29B /* tkBind.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkBind.c; sourceTree = "<group>"; };
+ F966BAB108F27A39005CB29B /* tkBitmap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkBitmap.c; sourceTree = "<group>"; };
+ F966BAB208F27A39005CB29B /* tkButton.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkButton.c; sourceTree = "<group>"; };
+ F966BAB308F27A39005CB29B /* tkButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkButton.h; sourceTree = "<group>"; };
+ F966BAB408F27A39005CB29B /* tkCanvArc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkCanvArc.c; sourceTree = "<group>"; };
+ F966BAB508F27A39005CB29B /* tkCanvas.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkCanvas.c; sourceTree = "<group>"; };
+ F966BAB608F27A39005CB29B /* tkCanvas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkCanvas.h; sourceTree = "<group>"; };
+ F966BAB708F27A39005CB29B /* tkCanvBmap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkCanvBmap.c; sourceTree = "<group>"; };
+ F966BAB808F27A39005CB29B /* tkCanvImg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkCanvImg.c; sourceTree = "<group>"; };
+ F966BAB908F27A39005CB29B /* tkCanvLine.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkCanvLine.c; sourceTree = "<group>"; };
+ F966BABA08F27A39005CB29B /* tkCanvPoly.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkCanvPoly.c; sourceTree = "<group>"; };
+ F966BABB08F27A39005CB29B /* tkCanvPs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkCanvPs.c; sourceTree = "<group>"; };
+ F966BABD08F27A39005CB29B /* tkCanvText.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkCanvText.c; sourceTree = "<group>"; };
+ F966BABE08F27A39005CB29B /* tkCanvUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkCanvUtil.c; sourceTree = "<group>"; };
+ F966BABF08F27A39005CB29B /* tkCanvWind.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkCanvWind.c; sourceTree = "<group>"; };
+ F966BAC008F27A39005CB29B /* tkClipboard.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkClipboard.c; sourceTree = "<group>"; };
+ F966BAC108F27A39005CB29B /* tkCmds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkCmds.c; sourceTree = "<group>"; };
+ F966BAC208F27A39005CB29B /* tkColor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkColor.c; sourceTree = "<group>"; };
+ F966BAC308F27A39005CB29B /* tkColor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkColor.h; sourceTree = "<group>"; };
+ F966BAC408F27A39005CB29B /* tkConfig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkConfig.c; sourceTree = "<group>"; };
+ F966BAC508F27A39005CB29B /* tkConsole.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkConsole.c; sourceTree = "<group>"; };
+ F966BAC608F27A39005CB29B /* tkCursor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkCursor.c; sourceTree = "<group>"; };
+ F966BAC708F27A39005CB29B /* tkDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkDecls.h; sourceTree = "<group>"; };
+ F966BAC808F27A39005CB29B /* tkEntry.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkEntry.c; sourceTree = "<group>"; };
+ F966BAC908F27A39005CB29B /* tkEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkEntry.h; sourceTree = "<group>"; };
+ F966BACA08F27A39005CB29B /* tkError.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkError.c; sourceTree = "<group>"; };
+ F966BACB08F27A39005CB29B /* tkEvent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkEvent.c; sourceTree = "<group>"; };
+ F966BACC08F27A39005CB29B /* tkFileFilter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkFileFilter.c; sourceTree = "<group>"; };
+ F966BACD08F27A39005CB29B /* tkFileFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkFileFilter.h; sourceTree = "<group>"; };
+ F966BACE08F27A39005CB29B /* tkFocus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkFocus.c; sourceTree = "<group>"; };
+ F966BACF08F27A39005CB29B /* tkFont.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkFont.c; sourceTree = "<group>"; };
+ F966BAD008F27A39005CB29B /* tkFont.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkFont.h; sourceTree = "<group>"; };
+ F966BAD108F27A39005CB29B /* tkFrame.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkFrame.c; sourceTree = "<group>"; };
+ F966BAD208F27A39005CB29B /* tkGC.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkGC.c; sourceTree = "<group>"; };
+ F966BAD308F27A39005CB29B /* tkGeometry.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkGeometry.c; sourceTree = "<group>"; };
+ F966BAD408F27A39005CB29B /* tkGet.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkGet.c; sourceTree = "<group>"; };
+ F966BAD508F27A39005CB29B /* tkGrab.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkGrab.c; sourceTree = "<group>"; };
+ F966BAD608F27A39005CB29B /* tkGrid.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkGrid.c; sourceTree = "<group>"; };
+ F966BAD708F27A39005CB29B /* tkImage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkImage.c; sourceTree = "<group>"; };
+ F966BAD808F27A39005CB29B /* tkImgBmap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkImgBmap.c; sourceTree = "<group>"; };
+ F966BAD908F27A39005CB29B /* tkImgGIF.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkImgGIF.c; sourceTree = "<group>"; };
+ F966BADA08F27A39005CB29B /* tkImgPhoto.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkImgPhoto.c; sourceTree = "<group>"; };
+ F966BADB08F27A39005CB29B /* tkImgPPM.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkImgPPM.c; sourceTree = "<group>"; };
+ F966BADC08F27A39005CB29B /* tkImgUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkImgUtil.c; sourceTree = "<group>"; };
+ F966BADE08F27A39005CB29B /* tkInt.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tkInt.decls; sourceTree = "<group>"; };
+ F966BADF08F27A39005CB29B /* tkInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkInt.h; sourceTree = "<group>"; };
+ F966BAE108F27A39005CB29B /* tkIntDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkIntDecls.h; sourceTree = "<group>"; };
+ F966BAE208F27A39005CB29B /* tkIntPlatDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkIntPlatDecls.h; sourceTree = "<group>"; };
+ F966BAE308F27A39005CB29B /* tkIntXlibDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkIntXlibDecls.h; sourceTree = "<group>"; };
+ F966BAE408F27A39005CB29B /* tkListbox.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkListbox.c; sourceTree = "<group>"; };
+ F966BAE508F27A39005CB29B /* tkMacWinMenu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkMacWinMenu.c; sourceTree = "<group>"; };
+ F966BAE608F27A39005CB29B /* tkMain.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkMain.c; sourceTree = "<group>"; };
+ F966BAE708F27A39005CB29B /* tkMenu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkMenu.c; sourceTree = "<group>"; };
+ F966BAE808F27A39005CB29B /* tkMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMenu.h; sourceTree = "<group>"; };
+ F966BAE908F27A39005CB29B /* tkMenubutton.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkMenubutton.c; sourceTree = "<group>"; };
+ F966BAEA08F27A39005CB29B /* tkMenubutton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMenubutton.h; sourceTree = "<group>"; };
+ F966BAEB08F27A39005CB29B /* tkMenuDraw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkMenuDraw.c; sourceTree = "<group>"; };
+ F966BAEC08F27A39005CB29B /* tkMessage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkMessage.c; sourceTree = "<group>"; };
+ F966BAED08F27A39005CB29B /* tkObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkObj.c; sourceTree = "<group>"; };
+ F966BAEE08F27A39005CB29B /* tkOldConfig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkOldConfig.c; sourceTree = "<group>"; };
+ F966BAEF08F27A39005CB29B /* tkOption.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkOption.c; sourceTree = "<group>"; };
+ F966BAF008F27A39005CB29B /* tkPack.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkPack.c; sourceTree = "<group>"; };
+ F966BAF108F27A39005CB29B /* tkPanedWindow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkPanedWindow.c; sourceTree = "<group>"; };
+ F966BAF208F27A39005CB29B /* tkPlace.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkPlace.c; sourceTree = "<group>"; };
+ F966BAF308F27A39005CB29B /* tkPlatDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkPlatDecls.h; sourceTree = "<group>"; };
+ F966BAF408F27A39005CB29B /* tkPointer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkPointer.c; sourceTree = "<group>"; };
+ F966BAF508F27A39005CB29B /* tkPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkPort.h; sourceTree = "<group>"; };
+ F966BAF608F27A39005CB29B /* tkRectOval.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkRectOval.c; sourceTree = "<group>"; };
+ F966BAF708F27A39005CB29B /* tkScale.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkScale.c; sourceTree = "<group>"; };
+ F966BAF808F27A39005CB29B /* tkScale.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkScale.h; sourceTree = "<group>"; };
+ F966BAF908F27A39005CB29B /* tkScrollbar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkScrollbar.c; sourceTree = "<group>"; };
+ F966BAFA08F27A39005CB29B /* tkScrollbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkScrollbar.h; sourceTree = "<group>"; };
+ F966BAFB08F27A39005CB29B /* tkSelect.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkSelect.c; sourceTree = "<group>"; };
+ F966BAFC08F27A39005CB29B /* tkSelect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkSelect.h; sourceTree = "<group>"; };
+ F966BAFD08F27A39005CB29B /* tkSquare.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkSquare.c; sourceTree = "<group>"; };
+ F966BAFE08F27A39005CB29B /* tkOldTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkOldTest.c; sourceTree = "<group>"; };
+ F966BAFF08F27A39005CB29B /* tkStubInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkStubInit.c; sourceTree = "<group>"; };
+ F966BB0008F27A39005CB29B /* tkStubLib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkStubLib.c; sourceTree = "<group>"; };
+ F966BB0108F27A39005CB29B /* tkStyle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkStyle.c; sourceTree = "<group>"; };
+ F966BB0208F27A39005CB29B /* tkTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkTest.c; sourceTree = "<group>"; };
+ F966BB0308F27A39005CB29B /* tkText.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkText.c; sourceTree = "<group>"; };
+ F966BB0408F27A39005CB29B /* tkText.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkText.h; sourceTree = "<group>"; };
+ F966BB0508F27A39005CB29B /* tkTextBTree.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkTextBTree.c; sourceTree = "<group>"; };
+ F966BB0608F27A39005CB29B /* tkTextDisp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkTextDisp.c; sourceTree = "<group>"; };
+ F966BB0808F27A39005CB29B /* tkTextImage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkTextImage.c; sourceTree = "<group>"; };
+ F966BB0908F27A39005CB29B /* tkTextIndex.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkTextIndex.c; sourceTree = "<group>"; };
+ F966BB0A08F27A39005CB29B /* tkTextMark.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkTextMark.c; sourceTree = "<group>"; };
+ F966BB0B08F27A39005CB29B /* tkTextTag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkTextTag.c; sourceTree = "<group>"; };
+ F966BB0C08F27A39005CB29B /* tkTextWind.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkTextWind.c; sourceTree = "<group>"; };
+ F966BB0D08F27A39005CB29B /* tkTrig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkTrig.c; sourceTree = "<group>"; };
+ F966BB0E08F27A39005CB29B /* tkUndo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUndo.c; sourceTree = "<group>"; };
+ F966BB0F08F27A39005CB29B /* tkUndo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkUndo.h; sourceTree = "<group>"; };
+ F966BB1008F27A39005CB29B /* tkUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUtil.c; sourceTree = "<group>"; };
+ F966BB1108F27A39005CB29B /* tkVisual.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkVisual.c; sourceTree = "<group>"; };
+ F966BB1208F27A39005CB29B /* tkWindow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWindow.c; sourceTree = "<group>"; };
+ F966BB1408F27A39005CB29B /* bgerror.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = bgerror.tcl; sourceTree = "<group>"; };
+ F966BB1508F27A39005CB29B /* button.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = button.tcl; sourceTree = "<group>"; };
+ F966BB1608F27A39005CB29B /* choosedir.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = choosedir.tcl; sourceTree = "<group>"; };
+ F966BB1708F27A39005CB29B /* clrpick.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = clrpick.tcl; sourceTree = "<group>"; };
+ F966BB1808F27A39005CB29B /* comdlg.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = comdlg.tcl; sourceTree = "<group>"; };
+ F966BB1908F27A39005CB29B /* console.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = console.tcl; sourceTree = "<group>"; };
+ F966BB1B08F27A39005CB29B /* anilabel.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = anilabel.tcl; sourceTree = "<group>"; };
+ F966BB1C08F27A39005CB29B /* aniwave.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = aniwave.tcl; sourceTree = "<group>"; };
+ F966BB1D08F27A39005CB29B /* arrow.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = arrow.tcl; sourceTree = "<group>"; };
+ F966BB1E08F27A39005CB29B /* bind.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = bind.tcl; sourceTree = "<group>"; };
+ F966BB1F08F27A39005CB29B /* bitmap.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = bitmap.tcl; sourceTree = "<group>"; };
+ F966BB2008F27A39005CB29B /* browse */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = browse; sourceTree = "<group>"; };
+ F966BB2108F27A39005CB29B /* button.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = button.tcl; sourceTree = "<group>"; };
+ F966BB2208F27A39005CB29B /* check.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = check.tcl; sourceTree = "<group>"; };
+ F966BB2308F27A39005CB29B /* clrpick.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = clrpick.tcl; sourceTree = "<group>"; };
+ F966BB2408F27A39005CB29B /* colors.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = colors.tcl; sourceTree = "<group>"; };
+ F966BB2508F27A39005CB29B /* cscroll.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cscroll.tcl; sourceTree = "<group>"; };
+ F966BB2608F27A39005CB29B /* ctext.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = ctext.tcl; sourceTree = "<group>"; };
+ F966BB2708F27A39005CB29B /* dialog1.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dialog1.tcl; sourceTree = "<group>"; };
+ F966BB2808F27A39005CB29B /* dialog2.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dialog2.tcl; sourceTree = "<group>"; };
+ F966BB2A08F27A39005CB29B /* entry1.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = entry1.tcl; sourceTree = "<group>"; };
+ F966BB2B08F27A39005CB29B /* entry2.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = entry2.tcl; sourceTree = "<group>"; };
+ F966BB2C08F27A39005CB29B /* entry3.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = entry3.tcl; sourceTree = "<group>"; };
+ F966BB2D08F27A39005CB29B /* filebox.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = filebox.tcl; sourceTree = "<group>"; };
+ F966BB2E08F27A39005CB29B /* floor.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = floor.tcl; sourceTree = "<group>"; };
+ F966BB2F08F27A39005CB29B /* form.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = form.tcl; sourceTree = "<group>"; };
+ F966BB3008F27A39005CB29B /* goldberg.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = goldberg.tcl; sourceTree = "<group>"; };
+ F966BB3108F27A39005CB29B /* hello */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = hello; sourceTree = "<group>"; };
+ F966BB3208F27A39005CB29B /* hscale.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = hscale.tcl; sourceTree = "<group>"; };
+ F966BB3308F27A39005CB29B /* icon.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = icon.tcl; sourceTree = "<group>"; };
+ F966BB3408F27A39005CB29B /* image1.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = image1.tcl; sourceTree = "<group>"; };
+ F966BB3508F27A39005CB29B /* image2.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = image2.tcl; sourceTree = "<group>"; };
+ F966BB4208F27A3A005CB29B /* items.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = items.tcl; sourceTree = "<group>"; };
+ F966BB4308F27A3A005CB29B /* ixset */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = ixset; sourceTree = "<group>"; };
+ F966BB4408F27A3A005CB29B /* label.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = label.tcl; sourceTree = "<group>"; };
+ F966BB4508F27A3A005CB29B /* labelframe.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = labelframe.tcl; sourceTree = "<group>"; };
+ F966BB4608F27A3A005CB29B /* menu.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = menu.tcl; sourceTree = "<group>"; };
+ F966BB4708F27A3A005CB29B /* menubu.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = menubu.tcl; sourceTree = "<group>"; };
+ F966BB4808F27A3A005CB29B /* msgbox.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = msgbox.tcl; sourceTree = "<group>"; };
+ F966BB4A08F27A3A005CB29B /* paned1.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = paned1.tcl; sourceTree = "<group>"; };
+ F966BB4B08F27A3A005CB29B /* paned2.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = paned2.tcl; sourceTree = "<group>"; };
+ F966BB4C08F27A3A005CB29B /* pendulum.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pendulum.tcl; sourceTree = "<group>"; };
+ F966BB4D08F27A3A005CB29B /* plot.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = plot.tcl; sourceTree = "<group>"; };
+ F966BB4E08F27A3A005CB29B /* puzzle.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = puzzle.tcl; sourceTree = "<group>"; };
+ F966BB4F08F27A3A005CB29B /* radio.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = radio.tcl; sourceTree = "<group>"; };
+ F966BB5008F27A3A005CB29B /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F966BB5108F27A3A005CB29B /* rmt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = rmt; sourceTree = "<group>"; };
+ F966BB5208F27A3A005CB29B /* rolodex */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = rolodex; sourceTree = "<group>"; };
+ F966BB5308F27A3A005CB29B /* ruler.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = ruler.tcl; sourceTree = "<group>"; };
+ F966BB5408F27A3A005CB29B /* sayings.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = sayings.tcl; sourceTree = "<group>"; };
+ F966BB5508F27A3A005CB29B /* search.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = search.tcl; sourceTree = "<group>"; };
+ F966BB5608F27A3A005CB29B /* spin.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = spin.tcl; sourceTree = "<group>"; };
+ F966BB5708F27A3A005CB29B /* square */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = square; sourceTree = "<group>"; };
+ F966BB5808F27A3A005CB29B /* states.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = states.tcl; sourceTree = "<group>"; };
+ F966BB5908F27A3A005CB29B /* style.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = style.tcl; sourceTree = "<group>"; };
+ F966BB5A08F27A3A005CB29B /* tclIndex */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclIndex; sourceTree = "<group>"; };
+ F966BB5B08F27A3A005CB29B /* tcolor */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = tcolor; sourceTree = "<group>"; };
+ F966BB5C08F27A3A005CB29B /* text.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = text.tcl; sourceTree = "<group>"; };
+ F966BB5D08F27A3A005CB29B /* timer */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = timer; sourceTree = "<group>"; };
+ F966BB5E08F27A3A005CB29B /* twind.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = twind.tcl; sourceTree = "<group>"; };
+ F966BB5F08F27A3A005CB29B /* unicodeout.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unicodeout.tcl; sourceTree = "<group>"; };
+ F966BB6008F27A3A005CB29B /* vscale.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = vscale.tcl; sourceTree = "<group>"; };
+ F966BB6108F27A3A005CB29B /* widget */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = widget; sourceTree = "<group>"; };
+ F966BB6208F27A3A005CB29B /* dialog.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dialog.tcl; sourceTree = "<group>"; };
+ F966BB6308F27A3A005CB29B /* entry.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = entry.tcl; sourceTree = "<group>"; };
+ F966BB6408F27A3A005CB29B /* focus.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = focus.tcl; sourceTree = "<group>"; };
+ F966BB7308F27A3A005CB29B /* listbox.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = listbox.tcl; sourceTree = "<group>"; };
+ F966BB7408F27A3A005CB29B /* menu.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = menu.tcl; sourceTree = "<group>"; };
+ F966BB7508F27A3A005CB29B /* mkpsenc.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = mkpsenc.tcl; sourceTree = "<group>"; };
+ F966BB7608F27A3A005CB29B /* msgbox.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = msgbox.tcl; sourceTree = "<group>"; };
+ F966BB8608F27A3A005CB29B /* obsolete.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = obsolete.tcl; sourceTree = "<group>"; };
+ F966BB8708F27A3A005CB29B /* optMenu.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = optMenu.tcl; sourceTree = "<group>"; };
+ F966BB8808F27A3A005CB29B /* palette.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = palette.tcl; sourceTree = "<group>"; };
+ F966BB8908F27A3B005CB29B /* panedwindow.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = panedwindow.tcl; sourceTree = "<group>"; };
+ F966BB8B08F27A3B005CB29B /* safetk.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = safetk.tcl; sourceTree = "<group>"; };
+ F966BB8C08F27A3B005CB29B /* scale.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = scale.tcl; sourceTree = "<group>"; };
+ F966BB8D08F27A3B005CB29B /* scrlbar.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = scrlbar.tcl; sourceTree = "<group>"; };
+ F966BB8E08F27A3B005CB29B /* spinbox.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = spinbox.tcl; sourceTree = "<group>"; };
+ F966BB8F08F27A3B005CB29B /* tclIndex */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclIndex; sourceTree = "<group>"; };
+ F966BB9008F27A3B005CB29B /* tearoff.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tearoff.tcl; sourceTree = "<group>"; };
+ F966BB9108F27A3B005CB29B /* text.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = text.tcl; sourceTree = "<group>"; };
+ F966BB9208F27A3B005CB29B /* tk.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tk.tcl; sourceTree = "<group>"; };
+ F966BB9308F27A3B005CB29B /* tkfbox.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tkfbox.tcl; sourceTree = "<group>"; };
+ F966BB9408F27A3B005CB29B /* unsupported.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unsupported.tcl; sourceTree = "<group>"; };
+ F966BB9508F27A3B005CB29B /* xmfbox.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = xmfbox.tcl; sourceTree = "<group>"; };
+ F966BB9608F27A3B005CB29B /* license.terms */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = license.terms; sourceTree = "<group>"; };
+ F966BBBA08F27A3B005CB29B /* configure.ac */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure.ac; sourceTree = "<group>"; };
+ F966BBBB08F27A3B005CB29B /* GNUmakefile */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = GNUmakefile; sourceTree = "<group>"; };
+ F966BBBE08F27A3B005CB29B /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F966BBC008F27A3B005CB29B /* Tk-Info.plist.in */ = {isa = PBXFileReference; explicitFileType = text.plist; fileEncoding = 4; path = "Tk-Info.plist.in"; sourceTree = "<group>"; };
+ F966BBC208F27A3B005CB29B /* tkMacOSX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMacOSX.h; sourceTree = "<group>"; };
+ F966BBC508F27A3B005CB29B /* tkMacOSXBitmap.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXBitmap.c; sourceTree = "<group>"; };
+ F966BBC608F27A3B005CB29B /* tkMacOSXButton.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXButton.c; sourceTree = "<group>"; };
+ F966BBC808F27A3B005CB29B /* tkMacOSXClipboard.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXClipboard.c; sourceTree = "<group>"; };
+ F966BBC908F27A3B005CB29B /* tkMacOSXColor.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXColor.c; sourceTree = "<group>"; };
+ F966BBCA08F27A3B005CB29B /* tkMacOSXConfig.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXConfig.c; sourceTree = "<group>"; };
+ F966BBCB08F27A3B005CB29B /* tkMacOSXCursor.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXCursor.c; sourceTree = "<group>"; };
+ F966BBCC08F27A3B005CB29B /* tkMacOSXCursors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMacOSXCursors.h; sourceTree = "<group>"; };
+ F966BBCD08F27A3B005CB29B /* tkMacOSXDebug.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXDebug.c; sourceTree = "<group>"; };
+ F966BBCE08F27A3B005CB29B /* tkMacOSXDebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMacOSXDebug.h; sourceTree = "<group>"; };
+ F966BBCF08F27A3B005CB29B /* tkMacOSXDefault.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMacOSXDefault.h; sourceTree = "<group>"; };
+ F966BBD008F27A3B005CB29B /* tkMacOSXDialog.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXDialog.c; sourceTree = "<group>"; };
+ F966BBD108F27A3B005CB29B /* tkMacOSXDraw.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXDraw.c; sourceTree = "<group>"; };
+ F966BBD208F27A3B005CB29B /* tkMacOSXEmbed.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXEmbed.c; sourceTree = "<group>"; };
+ F966BBD308F27A3B005CB29B /* tkMacOSXEntry.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXEntry.c; sourceTree = "<group>"; };
+ F966BBD408F27A3B005CB29B /* tkMacOSXEvent.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXEvent.c; sourceTree = "<group>"; };
+ F966BBD508F27A3B005CB29B /* tkMacOSXEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMacOSXEvent.h; sourceTree = "<group>"; };
+ F966BBD608F27A3B005CB29B /* tkMacOSXFont.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXFont.c; sourceTree = "<group>"; };
+ F966BBD708F27A3B005CB29B /* tkMacOSXHLEvents.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXHLEvents.c; sourceTree = "<group>"; };
+ F966BBD808F27A3B005CB29B /* tkMacOSXInit.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXInit.c; sourceTree = "<group>"; };
+ F966BBDA08F27A3B005CB29B /* tkMacOSXInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMacOSXInt.h; sourceTree = "<group>"; };
+ F966BBDB08F27A3B005CB29B /* tkMacOSXKeyboard.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXKeyboard.c; sourceTree = "<group>"; };
+ F966BBDC08F27A3B005CB29B /* tkMacOSXKeyEvent.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXKeyEvent.c; sourceTree = "<group>"; };
+ F966BBDD08F27A3B005CB29B /* tkMacOSXMenu.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXMenu.c; sourceTree = "<group>"; };
+ F966BBE008F27A3B005CB29B /* tkMacOSXMenubutton.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXMenubutton.c; sourceTree = "<group>"; };
+ F966BBE108F27A3B005CB29B /* tkMacOSXMenus.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXMenus.c; sourceTree = "<group>"; };
+ F966BBE208F27A3B005CB29B /* tkMacOSXMouseEvent.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXMouseEvent.c; sourceTree = "<group>"; };
+ F966BBE308F27A3B005CB29B /* tkMacOSXNotify.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXNotify.c; sourceTree = "<group>"; };
+ F966BBEA08F27A3C005CB29B /* tkMacOSXPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMacOSXPort.h; sourceTree = "<group>"; };
+ F966BBEB08F27A3C005CB29B /* tkMacOSXRegion.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXRegion.c; sourceTree = "<group>"; };
+ F966BBEC08F27A3C005CB29B /* tkMacOSXScale.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXScale.c; sourceTree = "<group>"; };
+ F966BBED08F27A3C005CB29B /* tkMacOSXScrlbr.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXScrlbr.c; sourceTree = "<group>"; };
+ F966BBEE08F27A3C005CB29B /* tkMacOSXSend.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXSend.c; sourceTree = "<group>"; };
+ F966BBEF08F27A3C005CB29B /* tkMacOSXSubwindows.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXSubwindows.c; sourceTree = "<group>"; };
+ F966BBF008F27A3C005CB29B /* tkMacOSXTest.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXTest.c; sourceTree = "<group>"; };
+ F966BBF108F27A3C005CB29B /* tkMacOSXWindowEvent.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXWindowEvent.c; sourceTree = "<group>"; };
+ F966BBF208F27A3C005CB29B /* tkMacOSXWm.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXWm.c; sourceTree = "<group>"; };
+ F966BBF308F27A3C005CB29B /* tkMacOSXWm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMacOSXWm.h; sourceTree = "<group>"; };
+ F966BBF408F27A3C005CB29B /* tkMacOSXXCursors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMacOSXXCursors.h; sourceTree = "<group>"; };
+ F966BBF508F27A3C005CB29B /* tkMacOSXXStubs.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXXStubs.c; sourceTree = "<group>"; };
+ F966BBF708F27A3C005CB29B /* Wish-Info.plist.in */ = {isa = PBXFileReference; explicitFileType = text.plist; fileEncoding = 4; path = "Wish-Info.plist.in"; sourceTree = "<group>"; };
+ F966BC0308F27A3C005CB29B /* README */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = README; sourceTree = "<group>"; };
+ F966BC0508F27A3C005CB29B /* all.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = all.tcl; sourceTree = "<group>"; };
+ F966BC0608F27A3C005CB29B /* arc.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = arc.tcl; sourceTree = "<group>"; };
+ F966BC0708F27A3C005CB29B /* bell.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = bell.test; sourceTree = "<group>"; };
+ F966BC0808F27A3C005CB29B /* bevel.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = bevel.tcl; sourceTree = "<group>"; };
+ F966BC0908F27A3C005CB29B /* bgerror.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = bgerror.test; sourceTree = "<group>"; };
+ F966BC0A08F27A3C005CB29B /* bind.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = bind.test; sourceTree = "<group>"; };
+ F966BC0B08F27A3C005CB29B /* bitmap.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = bitmap.test; sourceTree = "<group>"; };
+ F966BC0C08F27A3C005CB29B /* border.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = border.test; sourceTree = "<group>"; };
+ F966BC0D08F27A3C005CB29B /* bugs.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = bugs.tcl; sourceTree = "<group>"; };
+ F966BC0E08F27A3C005CB29B /* butGeom.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = butGeom.tcl; sourceTree = "<group>"; };
+ F966BC0F08F27A3C005CB29B /* butGeom2.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = butGeom2.tcl; sourceTree = "<group>"; };
+ F966BC1008F27A3C005CB29B /* button.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = button.test; sourceTree = "<group>"; };
+ F966BC1108F27A3C005CB29B /* canvas.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = canvas.test; sourceTree = "<group>"; };
+ F966BC1208F27A3C005CB29B /* canvImg.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = canvImg.test; sourceTree = "<group>"; };
+ F966BC1308F27A3C005CB29B /* canvPs.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = canvPs.test; sourceTree = "<group>"; };
+ F966BC1408F27A3C005CB29B /* canvPsArc.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = canvPsArc.tcl; sourceTree = "<group>"; };
+ F966BC1508F27A3C005CB29B /* canvPsBmap.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = canvPsBmap.tcl; sourceTree = "<group>"; };
+ F966BC1608F27A3C005CB29B /* canvPsGrph.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = canvPsGrph.tcl; sourceTree = "<group>"; };
+ F966BC1708F27A3C005CB29B /* canvPsImg.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = canvPsImg.tcl; sourceTree = "<group>"; };
+ F966BC1808F27A3C005CB29B /* canvPsText.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = canvPsText.tcl; sourceTree = "<group>"; };
+ F966BC1908F27A3C005CB29B /* canvRect.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = canvRect.test; sourceTree = "<group>"; };
+ F966BC1A08F27A3C005CB29B /* canvText.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = canvText.test; sourceTree = "<group>"; };
+ F966BC1B08F27A3C005CB29B /* canvWind.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = canvWind.test; sourceTree = "<group>"; };
+ F966BC1C08F27A3C005CB29B /* choosedir.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = choosedir.test; sourceTree = "<group>"; };
+ F966BC1D08F27A3C005CB29B /* clipboard.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = clipboard.test; sourceTree = "<group>"; };
+ F966BC1E08F27A3C005CB29B /* clrpick.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = clrpick.test; sourceTree = "<group>"; };
+ F966BC1F08F27A3C005CB29B /* cmap.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmap.tcl; sourceTree = "<group>"; };
+ F966BC2008F27A3C005CB29B /* cmds.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmds.test; sourceTree = "<group>"; };
+ F966BC2108F27A3C005CB29B /* color.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = color.test; sourceTree = "<group>"; };
+ F966BC2208F27A3C005CB29B /* config.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = config.test; sourceTree = "<group>"; };
+ F966BC2308F27A3C005CB29B /* constraints.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = constraints.tcl; sourceTree = "<group>"; };
+ F966BC2408F27A3C005CB29B /* cursor.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cursor.test; sourceTree = "<group>"; };
+ F966BC2508F27A3C005CB29B /* dialog.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dialog.test; sourceTree = "<group>"; };
+ F966BC2608F27A3C005CB29B /* embed.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = embed.test; sourceTree = "<group>"; };
+ F966BC2708F27A3C005CB29B /* entry.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = entry.test; sourceTree = "<group>"; };
+ F966BC2808F27A3C005CB29B /* event.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = event.test; sourceTree = "<group>"; };
+ F966BC2908F27A3C005CB29B /* filebox.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = filebox.test; sourceTree = "<group>"; };
+ F966BC2A08F27A3C005CB29B /* focus.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = focus.test; sourceTree = "<group>"; };
+ F966BC2B08F27A3C005CB29B /* focusTcl.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = focusTcl.test; sourceTree = "<group>"; };
+ F966BC2C08F27A3C005CB29B /* font.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = font.test; sourceTree = "<group>"; };
+ F966BC2D08F27A3C005CB29B /* frame.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = frame.test; sourceTree = "<group>"; };
+ F966BC2E08F27A3C005CB29B /* geometry.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = geometry.test; sourceTree = "<group>"; };
+ F966BC2F08F27A3C005CB29B /* get.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = get.test; sourceTree = "<group>"; };
+ F966BC3008F27A3C005CB29B /* grab.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = grab.test; sourceTree = "<group>"; };
+ F966BC3108F27A3C005CB29B /* grid.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = grid.test; sourceTree = "<group>"; };
+ F966BC3308F27A3C005CB29B /* image.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = image.test; sourceTree = "<group>"; };
+ F966BC3408F27A3C005CB29B /* imgBmap.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = imgBmap.test; sourceTree = "<group>"; };
+ F966BC3508F27A3C005CB29B /* imgPhoto.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = imgPhoto.test; sourceTree = "<group>"; };
+ F966BC3608F27A3C005CB29B /* imgPPM.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = imgPPM.test; sourceTree = "<group>"; };
+ F966BC3708F27A3C005CB29B /* listbox.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = listbox.test; sourceTree = "<group>"; };
+ F966BC3808F27A3C005CB29B /* main.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = main.test; sourceTree = "<group>"; };
+ F966BC3908F27A3C005CB29B /* menu.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = menu.test; sourceTree = "<group>"; };
+ F966BC3A08F27A3C005CB29B /* menubut.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = menubut.test; sourceTree = "<group>"; };
+ F966BC3B08F27A3C005CB29B /* menuDraw.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = menuDraw.test; sourceTree = "<group>"; };
+ F966BC3C08F27A3C005CB29B /* message.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = message.test; sourceTree = "<group>"; };
+ F966BC3D08F27A3C005CB29B /* msgbox.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = msgbox.test; sourceTree = "<group>"; };
+ F966BC3E08F27A3C005CB29B /* obj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = obj.test; sourceTree = "<group>"; };
+ F966BC3F08F27A3C005CB29B /* oldpack.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = oldpack.test; sourceTree = "<group>"; };
+ F966BC4008F27A3C005CB29B /* option.file1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = option.file1; sourceTree = "<group>"; };
+ F966BC4108F27A3C005CB29B /* option.file2 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = option.file2; sourceTree = "<group>"; };
+ F966BC4208F27A3C005CB29B /* option.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = option.test; sourceTree = "<group>"; };
+ F966BC4308F27A3C005CB29B /* pack.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pack.test; sourceTree = "<group>"; };
+ F966BC4408F27A3C005CB29B /* panedwindow.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = panedwindow.test; sourceTree = "<group>"; };
+ F966BC4508F27A3D005CB29B /* place.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = place.test; sourceTree = "<group>"; };
+ F966BC4608F27A3D005CB29B /* raise.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = raise.test; sourceTree = "<group>"; };
+ F966BC4708F27A3D005CB29B /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F966BC4808F27A3D005CB29B /* safe.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = safe.test; sourceTree = "<group>"; };
+ F966BC4908F27A3D005CB29B /* scale.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = scale.test; sourceTree = "<group>"; };
+ F966BC4A08F27A3D005CB29B /* scrollbar.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = scrollbar.test; sourceTree = "<group>"; };
+ F966BC4B08F27A3D005CB29B /* select.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = select.test; sourceTree = "<group>"; };
+ F966BC4C08F27A3D005CB29B /* send.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = send.test; sourceTree = "<group>"; };
+ F966BC4D08F27A3D005CB29B /* spinbox.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = spinbox.test; sourceTree = "<group>"; };
+ F966BC4E08F27A3D005CB29B /* text.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = text.test; sourceTree = "<group>"; };
+ F966BC4F08F27A3D005CB29B /* textBTree.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = textBTree.test; sourceTree = "<group>"; };
+ F966BC5008F27A3D005CB29B /* textDisp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = textDisp.test; sourceTree = "<group>"; };
+ F966BC5108F27A3D005CB29B /* textImage.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = textImage.test; sourceTree = "<group>"; };
+ F966BC5208F27A3D005CB29B /* textIndex.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = textIndex.test; sourceTree = "<group>"; };
+ F966BC5308F27A3D005CB29B /* textMark.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = textMark.test; sourceTree = "<group>"; };
+ F966BC5408F27A3D005CB29B /* textTag.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = textTag.test; sourceTree = "<group>"; };
+ F966BC5508F27A3D005CB29B /* textWind.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = textWind.test; sourceTree = "<group>"; };
+ F966BC5608F27A3D005CB29B /* tk.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tk.test; sourceTree = "<group>"; };
+ F966BC5708F27A3D005CB29B /* unixButton.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixButton.test; sourceTree = "<group>"; };
+ F966BC5808F27A3D005CB29B /* unixEmbed.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixEmbed.test; sourceTree = "<group>"; };
+ F966BC5908F27A3D005CB29B /* unixFont.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixFont.test; sourceTree = "<group>"; };
+ F966BC5A08F27A3D005CB29B /* unixMenu.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixMenu.test; sourceTree = "<group>"; };
+ F966BC5B08F27A3D005CB29B /* unixSelect.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixSelect.test; sourceTree = "<group>"; };
+ F966BC5C08F27A3D005CB29B /* unixWm.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixWm.test; sourceTree = "<group>"; };
+ F966BC5D08F27A3D005CB29B /* util.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = util.test; sourceTree = "<group>"; };
+ F966BC5E08F27A3D005CB29B /* visual.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = visual.test; sourceTree = "<group>"; };
+ F966BC5F08F27A3D005CB29B /* visual_bb.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = visual_bb.test; sourceTree = "<group>"; };
+ F966BC6008F27A3D005CB29B /* winButton.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winButton.test; sourceTree = "<group>"; };
+ F966BC6108F27A3D005CB29B /* winClipboard.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winClipboard.test; sourceTree = "<group>"; };
+ F966BC6208F27A3D005CB29B /* winDialog.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winDialog.test; sourceTree = "<group>"; };
+ F966BC6308F27A3D005CB29B /* window.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = window.test; sourceTree = "<group>"; };
+ F966BC6408F27A3D005CB29B /* winfo.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winfo.test; sourceTree = "<group>"; };
+ F966BC6508F27A3D005CB29B /* winFont.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winFont.test; sourceTree = "<group>"; };
+ F966BC6608F27A3D005CB29B /* winMenu.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winMenu.test; sourceTree = "<group>"; };
+ F966BC6708F27A3D005CB29B /* winSend.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winSend.test; sourceTree = "<group>"; };
+ F966BC6808F27A3D005CB29B /* winWm.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winWm.test; sourceTree = "<group>"; };
+ F966BC6908F27A3D005CB29B /* wm.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = wm.test; sourceTree = "<group>"; };
+ F966BC6A08F27A3D005CB29B /* xmfbox.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = xmfbox.test; sourceTree = "<group>"; };
+ F966BC6C08F27A3D005CB29B /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = "<group>"; };
+ F966BC6D08F27A3D005CB29B /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
+ F966BC6E08F27A3D005CB29B /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
+ F966BC6F08F27A3D005CB29B /* install-sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "install-sh"; sourceTree = "<group>"; };
+ F966BC7008F27A3D005CB29B /* installManPage */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = installManPage; sourceTree = "<group>"; };
+ F966BC7108F27A3D005CB29B /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
+ F966BC7208F27A3D005CB29B /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F966BC7308F27A3D005CB29B /* tcl.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tcl.m4; sourceTree = "<group>"; };
+ F966BC7408F27A3D005CB29B /* tk.spec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tk.spec; sourceTree = "<group>"; };
+ F966BC7508F27A3D005CB29B /* tkAppInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkAppInit.c; sourceTree = "<group>"; };
+ F966BC7608F27A3D005CB29B /* tkConfig.h.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = tkConfig.h.in; sourceTree = "<group>"; };
+ F966BC7708F27A3D005CB29B /* tkConfig.sh.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tkConfig.sh.in; sourceTree = "<group>"; };
+ F966BC7808F27A3D005CB29B /* tkUnix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnix.c; sourceTree = "<group>"; };
+ F966BC7908F27A3D005CB29B /* tkUnix3d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnix3d.c; sourceTree = "<group>"; };
+ F966BC7A08F27A3D005CB29B /* tkUnixButton.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixButton.c; sourceTree = "<group>"; };
+ F966BC7B08F27A3D005CB29B /* tkUnixColor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixColor.c; sourceTree = "<group>"; };
+ F966BC7C08F27A3D005CB29B /* tkUnixConfig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixConfig.c; sourceTree = "<group>"; };
+ F966BC7D08F27A3D005CB29B /* tkUnixCursor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixCursor.c; sourceTree = "<group>"; };
+ F966BC7E08F27A3D005CB29B /* tkUnixDefault.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkUnixDefault.h; sourceTree = "<group>"; };
+ F966BC7F08F27A3D005CB29B /* tkUnixDialog.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixDialog.c; sourceTree = "<group>"; };
+ F966BC8008F27A3D005CB29B /* tkUnixDraw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixDraw.c; sourceTree = "<group>"; };
+ F966BC8108F27A3D005CB29B /* tkUnixEmbed.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixEmbed.c; sourceTree = "<group>"; };
+ F966BC8208F27A3D005CB29B /* tkUnixEvent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixEvent.c; sourceTree = "<group>"; };
+ F966BC8308F27A3D005CB29B /* tkUnixFocus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixFocus.c; sourceTree = "<group>"; };
+ F966BC8408F27A3D005CB29B /* tkUnixFont.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixFont.c; sourceTree = "<group>"; };
+ F966BC8508F27A3D005CB29B /* tkUnixInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixInit.c; sourceTree = "<group>"; };
+ F966BC8608F27A3D005CB29B /* tkUnixInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkUnixInt.h; sourceTree = "<group>"; };
+ F966BC8708F27A3D005CB29B /* tkUnixKey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixKey.c; sourceTree = "<group>"; };
+ F966BC8808F27A3D005CB29B /* tkUnixMenu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixMenu.c; sourceTree = "<group>"; };
+ F966BC8908F27A3D005CB29B /* tkUnixMenubu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixMenubu.c; sourceTree = "<group>"; };
+ F966BC8A08F27A3D005CB29B /* tkUnixPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkUnixPort.h; sourceTree = "<group>"; };
+ F966BC8B08F27A3D005CB29B /* tkUnixRFont.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixRFont.c; sourceTree = "<group>"; };
+ F966BC8C08F27A3D005CB29B /* tkUnixScale.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixScale.c; sourceTree = "<group>"; };
+ F966BC8D08F27A3D005CB29B /* tkUnixScrlbr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixScrlbr.c; sourceTree = "<group>"; };
+ F966BC8E08F27A3D005CB29B /* tkUnixSelect.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixSelect.c; sourceTree = "<group>"; };
+ F966BC8F08F27A3D005CB29B /* tkUnixSend.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixSend.c; sourceTree = "<group>"; };
+ F966BC9008F27A3D005CB29B /* tkUnixWm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixWm.c; sourceTree = "<group>"; };
+ F966BC9108F27A3D005CB29B /* tkUnixXId.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixXId.c; sourceTree = "<group>"; };
+ F966BC9408F27A3D005CB29B /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = "<group>"; };
+ F966BC9508F27A3D005CB29B /* buildall.vc.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = buildall.vc.bat; sourceTree = "<group>"; };
+ F966BC9608F27A3E005CB29B /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
+ F966BC9708F27A3E005CB29B /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
+ F966BC9908F27A3E005CB29B /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
+ F966BC9A08F27A3E005CB29B /* makefile.vc */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = makefile.vc; sourceTree = "<group>"; };
+ F966BC9B08F27A3E005CB29B /* mkd.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = mkd.bat; sourceTree = "<group>"; };
+ F966BC9C08F27A3E005CB29B /* nmakehlp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nmakehlp.c; sourceTree = "<group>"; };
+ F966BCEE08F27A3E005CB29B /* tk.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tk.rc; sourceTree = "<group>"; };
+ F966BCEF08F27A3E005CB29B /* tk_base.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tk_base.rc; sourceTree = "<group>"; };
+ F966BCF208F27A3E005CB29B /* wish.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = wish.rc; sourceTree = "<group>"; };
+ F966BCF308F27A3E005CB29B /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F966BCF408F27A3E005CB29B /* rmd.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rmd.bat; sourceTree = "<group>"; };
+ F966BCF508F27A3F005CB29B /* rules.vc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rules.vc; sourceTree = "<group>"; };
+ F966BCF608F27A3F005CB29B /* stubs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stubs.c; sourceTree = "<group>"; };
+ F966BCF708F27A3F005CB29B /* tcl.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tcl.m4; sourceTree = "<group>"; };
+ F966BCF808F27A3F005CB29B /* tkConfig.sh.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tkConfig.sh.in; sourceTree = "<group>"; };
+ F966BCF908F27A3F005CB29B /* tkWin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkWin.h; sourceTree = "<group>"; };
+ F966BCFA08F27A3F005CB29B /* tkWin32Dll.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWin32Dll.c; sourceTree = "<group>"; };
+ F966BCFB08F27A3F005CB29B /* tkWin3d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWin3d.c; sourceTree = "<group>"; };
+ F966BCFC08F27A3F005CB29B /* tkWinButton.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinButton.c; sourceTree = "<group>"; };
+ F966BCFD08F27A3F005CB29B /* tkWinClipboard.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinClipboard.c; sourceTree = "<group>"; };
+ F966BCFE08F27A3F005CB29B /* tkWinColor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinColor.c; sourceTree = "<group>"; };
+ F966BCFF08F27A3F005CB29B /* tkWinConfig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinConfig.c; sourceTree = "<group>"; };
+ F966BD0008F27A3F005CB29B /* tkWinCursor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinCursor.c; sourceTree = "<group>"; };
+ F966BD0108F27A3F005CB29B /* tkWinDefault.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkWinDefault.h; sourceTree = "<group>"; };
+ F966BD0208F27A3F005CB29B /* tkWinDialog.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinDialog.c; sourceTree = "<group>"; };
+ F966BD0308F27A3F005CB29B /* tkWinDraw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinDraw.c; sourceTree = "<group>"; };
+ F966BD0408F27A3F005CB29B /* tkWinEmbed.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinEmbed.c; sourceTree = "<group>"; };
+ F966BD0508F27A3F005CB29B /* tkWinFont.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinFont.c; sourceTree = "<group>"; };
+ F966BD0708F27A3F005CB29B /* tkWinImage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinImage.c; sourceTree = "<group>"; };
+ F966BD0808F27A3F005CB29B /* tkWinInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinInit.c; sourceTree = "<group>"; };
+ F966BD0908F27A3F005CB29B /* tkWinInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkWinInt.h; sourceTree = "<group>"; };
+ F966BD0A08F27A3F005CB29B /* tkWinKey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinKey.c; sourceTree = "<group>"; };
+ F966BD0B08F27A3F005CB29B /* tkWinMenu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinMenu.c; sourceTree = "<group>"; };
+ F966BD0C08F27A3F005CB29B /* tkWinPixmap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinPixmap.c; sourceTree = "<group>"; };
+ F966BD0D08F27A3F005CB29B /* tkWinPointer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinPointer.c; sourceTree = "<group>"; };
+ F966BD0E08F27A3F005CB29B /* tkWinPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkWinPort.h; sourceTree = "<group>"; };
+ F966BD0F08F27A3F005CB29B /* tkWinRegion.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinRegion.c; sourceTree = "<group>"; };
+ F966BD1008F27A3F005CB29B /* tkWinScrlbr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinScrlbr.c; sourceTree = "<group>"; };
+ F966BD1108F27A3F005CB29B /* tkWinSend.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinSend.c; sourceTree = "<group>"; };
+ F966BD1208F27A3F005CB29B /* tkWinSendCom.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinSendCom.c; sourceTree = "<group>"; };
+ F966BD1308F27A3F005CB29B /* tkWinSendCom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkWinSendCom.h; sourceTree = "<group>"; };
+ F966BD1408F27A3F005CB29B /* tkWinTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinTest.c; sourceTree = "<group>"; };
+ F966BD1508F27A3F005CB29B /* tkWinWindow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinWindow.c; sourceTree = "<group>"; };
+ F966BD1608F27A3F005CB29B /* tkWinWm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinWm.c; sourceTree = "<group>"; };
+ F966BD1708F27A3F005CB29B /* tkWinX.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWinX.c; sourceTree = "<group>"; };
+ F966BD1808F27A3F005CB29B /* winMain.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = winMain.c; sourceTree = "<group>"; };
+ F966BD1B08F27A3F005CB29B /* cursorfont.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cursorfont.h; sourceTree = "<group>"; };
+ F966BD1C08F27A3F005CB29B /* keysym.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = keysym.h; sourceTree = "<group>"; };
+ F966BD1D08F27A3F005CB29B /* keysymdef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = keysymdef.h; sourceTree = "<group>"; };
+ F966BD1E08F27A3F005CB29B /* X.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = X.h; sourceTree = "<group>"; };
+ F966BD1F08F27A3F005CB29B /* Xatom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Xatom.h; sourceTree = "<group>"; };
+ F966BD2008F27A3F005CB29B /* Xfuncproto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Xfuncproto.h; sourceTree = "<group>"; };
+ F966BD2108F27A3F005CB29B /* Xlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Xlib.h; sourceTree = "<group>"; };
+ F966BD2208F27A3F005CB29B /* Xutil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Xutil.h; sourceTree = "<group>"; };
+ F966BD2308F27A3F005CB29B /* xbytes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xbytes.h; sourceTree = "<group>"; };
+ F966BD2408F27A3F005CB29B /* xcolors.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xcolors.c; sourceTree = "<group>"; };
+ F966BD2508F27A3F005CB29B /* xdraw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xdraw.c; sourceTree = "<group>"; };
+ F966BD2608F27A3F005CB29B /* xgc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xgc.c; sourceTree = "<group>"; };
+ F966BD2708F27A3F005CB29B /* ximage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ximage.c; sourceTree = "<group>"; };
+ F966BD2808F27A3F005CB29B /* xutil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xutil.c; sourceTree = "<group>"; };
+ F966C07408F2820D005CB29B /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; };
+ F966C07608F2821B005CB29B /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = "<absolute>"; };
+ F966C07808F28233005CB29B /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = /System/Library/Frameworks/IOKit.framework; sourceTree = "<absolute>"; };
+ F96887E00AF786D5000797B5 /* ttk.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = ttk.decls; sourceTree = "<group>"; };
+ F96887E10AF786D5000797B5 /* ttkBlink.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkBlink.c; sourceTree = "<group>"; };
+ F96887E20AF786D5000797B5 /* ttkButton.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkButton.c; sourceTree = "<group>"; };
+ F96887E30AF786D5000797B5 /* ttkCache.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkCache.c; sourceTree = "<group>"; };
+ F96887E40AF786D5000797B5 /* ttkClamTheme.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkClamTheme.c; sourceTree = "<group>"; };
+ F96887E50AF786D5000797B5 /* ttkClassicTheme.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkClassicTheme.c; sourceTree = "<group>"; };
+ F96887E60AF786D5000797B5 /* ttkDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ttkDecls.h; sourceTree = "<group>"; };
+ F96887E70AF786D5000797B5 /* ttkDefaultTheme.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkDefaultTheme.c; sourceTree = "<group>"; };
+ F96887E80AF786D5000797B5 /* ttkElements.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkElements.c; sourceTree = "<group>"; };
+ F96887E90AF786D5000797B5 /* ttkEntry.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkEntry.c; sourceTree = "<group>"; };
+ F96887EA0AF786D5000797B5 /* ttkFrame.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkFrame.c; sourceTree = "<group>"; };
+ F96887EB0AF786D5000797B5 /* ttkImage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkImage.c; sourceTree = "<group>"; };
+ F96887EC0AF786D5000797B5 /* ttkInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkInit.c; sourceTree = "<group>"; };
+ F96887ED0AF786D5000797B5 /* ttkLabel.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkLabel.c; sourceTree = "<group>"; };
+ F96887EE0AF786D5000797B5 /* ttkLayout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkLayout.c; sourceTree = "<group>"; };
+ F96887EF0AF786D5000797B5 /* ttkManager.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkManager.c; sourceTree = "<group>"; };
+ F96887F00AF786D5000797B5 /* ttkManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ttkManager.h; sourceTree = "<group>"; };
+ F96887F10AF786D5000797B5 /* ttkNotebook.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkNotebook.c; sourceTree = "<group>"; };
+ F96887F20AF786D5000797B5 /* ttkPanedwindow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkPanedwindow.c; sourceTree = "<group>"; };
+ F96887F30AF786D5000797B5 /* ttkProgress.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkProgress.c; sourceTree = "<group>"; };
+ F96887F40AF786D5000797B5 /* ttkScale.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkScale.c; sourceTree = "<group>"; };
+ F96887F50AF786D5000797B5 /* ttkScroll.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkScroll.c; sourceTree = "<group>"; };
+ F96887F60AF786D5000797B5 /* ttkScrollbar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkScrollbar.c; sourceTree = "<group>"; };
+ F96887F70AF786D5000797B5 /* ttkSeparator.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkSeparator.c; sourceTree = "<group>"; };
+ F96887F80AF786D5000797B5 /* ttkSquare.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkSquare.c; sourceTree = "<group>"; };
+ F96887F90AF786D5000797B5 /* ttkState.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkState.c; sourceTree = "<group>"; };
+ F96887FA0AF786D5000797B5 /* ttkStubInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkStubInit.c; sourceTree = "<group>"; };
+ F96887FB0AF786D5000797B5 /* ttkStubLib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkStubLib.c; sourceTree = "<group>"; };
+ F96887FC0AF786D5000797B5 /* ttkTagSet.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkTagSet.c; sourceTree = "<group>"; };
+ F96887FD0AF786D5000797B5 /* ttkTheme.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkTheme.c; sourceTree = "<group>"; };
+ F96887FE0AF786D5000797B5 /* ttkTheme.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ttkTheme.h; sourceTree = "<group>"; };
+ F96887FF0AF786D5000797B5 /* ttkThemeInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ttkThemeInt.h; sourceTree = "<group>"; };
+ F96888000AF786D5000797B5 /* ttkTrace.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkTrace.c; sourceTree = "<group>"; };
+ F96888010AF786D5000797B5 /* ttkTrack.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkTrack.c; sourceTree = "<group>"; };
+ F96888020AF786D5000797B5 /* ttkTreeview.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkTreeview.c; sourceTree = "<group>"; };
+ F96888030AF786D5000797B5 /* ttkWidget.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkWidget.c; sourceTree = "<group>"; };
+ F96888040AF786D5000797B5 /* ttkWidget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ttkWidget.h; sourceTree = "<group>"; };
+ F96888370AF787B3000797B5 /* altTheme.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = altTheme.tcl; sourceTree = "<group>"; };
+ F96888380AF787B3000797B5 /* aquaTheme.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = aquaTheme.tcl; sourceTree = "<group>"; };
+ F96888390AF787B3000797B5 /* button.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = button.tcl; sourceTree = "<group>"; };
+ F968883A0AF787B3000797B5 /* clamTheme.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = clamTheme.tcl; sourceTree = "<group>"; };
+ F968883B0AF787B3000797B5 /* classicTheme.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = classicTheme.tcl; sourceTree = "<group>"; };
+ F968883C0AF787B3000797B5 /* combobox.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = combobox.tcl; sourceTree = "<group>"; };
+ F968883D0AF787B3000797B5 /* cursors.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cursors.tcl; sourceTree = "<group>"; };
+ F968883E0AF787B3000797B5 /* defaults.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = defaults.tcl; sourceTree = "<group>"; };
+ F96888400AF787B3000797B5 /* entry.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = entry.tcl; sourceTree = "<group>"; };
+ F96888410AF787B3000797B5 /* fonts.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fonts.tcl; sourceTree = "<group>"; };
+ F96888440AF787B3000797B5 /* menubutton.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = menubutton.tcl; sourceTree = "<group>"; };
+ F96888450AF787B3000797B5 /* notebook.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = notebook.tcl; sourceTree = "<group>"; };
+ F96888460AF787B3000797B5 /* panedwindow.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = panedwindow.tcl; sourceTree = "<group>"; };
+ F96888470AF787B3000797B5 /* progress.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = progress.tcl; sourceTree = "<group>"; };
+ F96888480AF787B3000797B5 /* scale.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = scale.tcl; sourceTree = "<group>"; };
+ F96888490AF787B3000797B5 /* scrollbar.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = scrollbar.tcl; sourceTree = "<group>"; };
+ F968884A0AF787B3000797B5 /* sizegrip.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = sizegrip.tcl; sourceTree = "<group>"; };
+ F968884B0AF787B3000797B5 /* treeview.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = treeview.tcl; sourceTree = "<group>"; };
+ F968884C0AF787B3000797B5 /* ttk.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = ttk.tcl; sourceTree = "<group>"; };
+ F968884D0AF787B3000797B5 /* utils.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = utils.tcl; sourceTree = "<group>"; };
+ F968884E0AF787B3000797B5 /* winTheme.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winTheme.tcl; sourceTree = "<group>"; };
+ F968884F0AF787B3000797B5 /* xpTheme.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = xpTheme.tcl; sourceTree = "<group>"; };
+ F96888540AF7880C000797B5 /* all.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = all.tcl; sourceTree = "<group>"; };
+ F96888560AF7880C000797B5 /* combobox.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = combobox.test; sourceTree = "<group>"; };
+ F96888570AF7880C000797B5 /* entry.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = entry.test; sourceTree = "<group>"; };
+ F96888580AF7880C000797B5 /* image.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = image.test; sourceTree = "<group>"; };
+ F96888590AF7880C000797B5 /* labelframe.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = labelframe.test; sourceTree = "<group>"; };
+ F968885A0AF7880C000797B5 /* layout.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = layout.test; sourceTree = "<group>"; };
+ F968885C0AF7880C000797B5 /* notebook.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = notebook.test; sourceTree = "<group>"; };
+ F968885D0AF7880C000797B5 /* panedwindow.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = panedwindow.test; sourceTree = "<group>"; };
+ F968885E0AF7880C000797B5 /* progressbar.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = progressbar.test; sourceTree = "<group>"; };
+ F968885F0AF7880C000797B5 /* scrollbar.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = scrollbar.test; sourceTree = "<group>"; };
+ F96888600AF7880C000797B5 /* treetags.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = treetags.test; sourceTree = "<group>"; };
+ F96888610AF7880C000797B5 /* treeview.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = treeview.test; sourceTree = "<group>"; };
+ F96888620AF7880C000797B5 /* ttk.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = ttk.test; sourceTree = "<group>"; };
+ F96888630AF7880C000797B5 /* validate.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = validate.test; sourceTree = "<group>"; };
+ F968886B0AF788F6000797B5 /* ttk_button.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_button.n; sourceTree = "<group>"; };
+ F968886C0AF788F6000797B5 /* ttk_checkbutton.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_checkbutton.n; sourceTree = "<group>"; };
+ F968886D0AF788F6000797B5 /* ttk_combobox.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_combobox.n; sourceTree = "<group>"; };
+ F968886F0AF788F6000797B5 /* ttk_entry.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_entry.n; sourceTree = "<group>"; };
+ F96888700AF788F6000797B5 /* ttk_frame.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_frame.n; sourceTree = "<group>"; };
+ F96888710AF788F6000797B5 /* ttk_Geometry.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_Geometry.3; sourceTree = "<group>"; };
+ F96888720AF788F6000797B5 /* ttk_image.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_image.n; sourceTree = "<group>"; };
+ F96888730AF788F6000797B5 /* ttk_intro.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_intro.n; sourceTree = "<group>"; };
+ F96888740AF788F6000797B5 /* ttk_label.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_label.n; sourceTree = "<group>"; };
+ F96888750AF788F6000797B5 /* ttk_labelframe.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_labelframe.n; sourceTree = "<group>"; };
+ F96888760AF788F6000797B5 /* ttk_menubutton.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_menubutton.n; sourceTree = "<group>"; };
+ F96888770AF788F6000797B5 /* ttk_notebook.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_notebook.n; sourceTree = "<group>"; };
+ F96888780AF788F6000797B5 /* ttk_panedwindow.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_panedwindow.n; sourceTree = "<group>"; };
+ F96888790AF788F6000797B5 /* ttk_progressbar.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_progressbar.n; sourceTree = "<group>"; };
+ F968887A0AF788F6000797B5 /* ttk_radiobutton.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_radiobutton.n; sourceTree = "<group>"; };
+ F968887B0AF788F6000797B5 /* ttk_scrollbar.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_scrollbar.n; sourceTree = "<group>"; };
+ F968887C0AF788F6000797B5 /* ttk_separator.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_separator.n; sourceTree = "<group>"; };
+ F968887D0AF788F6000797B5 /* ttk_sizegrip.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_sizegrip.n; sourceTree = "<group>"; };
+ F968887E0AF788F6000797B5 /* ttk_style.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_style.n; sourceTree = "<group>"; };
+ F968887F0AF788F6000797B5 /* ttk_Theme.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_Theme.3; sourceTree = "<group>"; };
+ F96888800AF788F6000797B5 /* ttk_treeview.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_treeview.n; sourceTree = "<group>"; };
+ F96888810AF788F6000797B5 /* ttk_widget.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ttk_widget.n; sourceTree = "<group>"; };
+ F96888840AF78938000797B5 /* ttkMacOSXTheme.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = ttkMacOSXTheme.c; sourceTree = "<group>"; };
+ F96888860AF78953000797B5 /* ttkWinMonitor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkWinMonitor.c; sourceTree = "<group>"; };
+ F96888870AF78953000797B5 /* ttkWinTheme.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkWinTheme.c; sourceTree = "<group>"; };
+ F96888880AF78953000797B5 /* ttkWinXPTheme.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttkWinXPTheme.c; sourceTree = "<group>"; };
+ F96D3DFA08F272A4004A47F5 /* ChangeLog */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = ChangeLog; sourceTree = "<group>"; };
+ F96D3DFB08F272A4004A47F5 /* changes */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = changes; sourceTree = "<group>"; };
+ F96D3DFD08F272A4004A47F5 /* Access.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Access.3; sourceTree = "<group>"; };
+ F96D3DFE08F272A4004A47F5 /* AddErrInfo.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AddErrInfo.3; sourceTree = "<group>"; };
+ F96D3DFF08F272A4004A47F5 /* after.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = after.n; sourceTree = "<group>"; };
+ F96D3E0008F272A4004A47F5 /* Alloc.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Alloc.3; sourceTree = "<group>"; };
+ F96D3E0108F272A4004A47F5 /* AllowExc.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AllowExc.3; sourceTree = "<group>"; };
+ F96D3E0208F272A4004A47F5 /* append.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = append.n; sourceTree = "<group>"; };
+ F96D3E0308F272A4004A47F5 /* AppInit.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AppInit.3; sourceTree = "<group>"; };
+ F96D3E0408F272A5004A47F5 /* array.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = array.n; sourceTree = "<group>"; };
+ F96D3E0508F272A5004A47F5 /* AssocData.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AssocData.3; sourceTree = "<group>"; };
+ F96D3E0608F272A5004A47F5 /* Async.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Async.3; sourceTree = "<group>"; };
+ F96D3E0708F272A5004A47F5 /* BackgdErr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = BackgdErr.3; sourceTree = "<group>"; };
+ F96D3E0808F272A5004A47F5 /* Backslash.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Backslash.3; sourceTree = "<group>"; };
+ F96D3E0908F272A5004A47F5 /* bgerror.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = bgerror.n; sourceTree = "<group>"; };
+ F96D3E0A08F272A5004A47F5 /* binary.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = binary.n; sourceTree = "<group>"; };
+ F96D3E0B08F272A5004A47F5 /* BoolObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = BoolObj.3; sourceTree = "<group>"; };
+ F96D3E0C08F272A5004A47F5 /* break.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = break.n; sourceTree = "<group>"; };
+ F96D3E0D08F272A5004A47F5 /* ByteArrObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ByteArrObj.3; sourceTree = "<group>"; };
+ F96D3E0E08F272A5004A47F5 /* CallDel.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CallDel.3; sourceTree = "<group>"; };
+ F96D3E0F08F272A5004A47F5 /* case.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = case.n; sourceTree = "<group>"; };
+ F96D3E1008F272A5004A47F5 /* catch.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = catch.n; sourceTree = "<group>"; };
+ F96D3E1108F272A5004A47F5 /* cd.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = cd.n; sourceTree = "<group>"; };
+ F96D3E1208F272A5004A47F5 /* chan.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = chan.n; sourceTree = "<group>"; };
+ F96D3E1308F272A5004A47F5 /* ChnlStack.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ChnlStack.3; sourceTree = "<group>"; };
+ F96D3E1408F272A5004A47F5 /* clock.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = clock.n; sourceTree = "<group>"; };
+ F96D3E1508F272A5004A47F5 /* close.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = close.n; sourceTree = "<group>"; };
+ F96D3E1608F272A5004A47F5 /* CmdCmplt.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CmdCmplt.3; sourceTree = "<group>"; };
+ F96D3E1708F272A5004A47F5 /* Concat.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Concat.3; sourceTree = "<group>"; };
+ F96D3E1808F272A5004A47F5 /* concat.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = concat.n; sourceTree = "<group>"; };
+ F96D3E1908F272A5004A47F5 /* continue.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = continue.n; sourceTree = "<group>"; };
+ F96D3E1A08F272A5004A47F5 /* CrtChannel.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtChannel.3; sourceTree = "<group>"; };
+ F96D3E1B08F272A5004A47F5 /* CrtChnlHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtChnlHdlr.3; sourceTree = "<group>"; };
+ F96D3E1C08F272A5004A47F5 /* CrtCloseHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtCloseHdlr.3; sourceTree = "<group>"; };
+ F96D3E1D08F272A5004A47F5 /* CrtCommand.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtCommand.3; sourceTree = "<group>"; };
+ F96D3E1E08F272A5004A47F5 /* CrtFileHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtFileHdlr.3; sourceTree = "<group>"; };
+ F96D3E1F08F272A5004A47F5 /* CrtInterp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtInterp.3; sourceTree = "<group>"; };
+ F96D3E2008F272A5004A47F5 /* CrtMathFnc.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtMathFnc.3; sourceTree = "<group>"; };
+ F96D3E2108F272A5004A47F5 /* CrtObjCmd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtObjCmd.3; sourceTree = "<group>"; };
+ F96D3E2208F272A5004A47F5 /* CrtSlave.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtSlave.3; sourceTree = "<group>"; };
+ F96D3E2308F272A5004A47F5 /* CrtTimerHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtTimerHdlr.3; sourceTree = "<group>"; };
+ F96D3E2408F272A5004A47F5 /* CrtTrace.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtTrace.3; sourceTree = "<group>"; };
+ F96D3E2508F272A5004A47F5 /* dde.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = dde.n; sourceTree = "<group>"; };
+ F96D3E2608F272A5004A47F5 /* DetachPids.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DetachPids.3; sourceTree = "<group>"; };
+ F96D3E2708F272A5004A47F5 /* dict.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = dict.n; sourceTree = "<group>"; };
+ F96D3E2808F272A5004A47F5 /* DictObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DictObj.3; sourceTree = "<group>"; };
+ F96D3E2908F272A5004A47F5 /* DoOneEvent.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DoOneEvent.3; sourceTree = "<group>"; };
+ F96D3E2A08F272A5004A47F5 /* DoubleObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DoubleObj.3; sourceTree = "<group>"; };
+ F96D3E2B08F272A5004A47F5 /* DoWhenIdle.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DoWhenIdle.3; sourceTree = "<group>"; };
+ F96D3E2C08F272A5004A47F5 /* DString.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DString.3; sourceTree = "<group>"; };
+ F96D3E2D08F272A5004A47F5 /* DumpActiveMemory.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DumpActiveMemory.3; sourceTree = "<group>"; };
+ F96D3E2E08F272A5004A47F5 /* Encoding.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Encoding.3; sourceTree = "<group>"; };
+ F96D3E2F08F272A5004A47F5 /* encoding.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = encoding.n; sourceTree = "<group>"; };
+ F96D3E3008F272A5004A47F5 /* Ensemble.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Ensemble.3; sourceTree = "<group>"; };
+ F96D3E3108F272A5004A47F5 /* Environment.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Environment.3; sourceTree = "<group>"; };
+ F96D3E3208F272A5004A47F5 /* eof.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = eof.n; sourceTree = "<group>"; };
+ F96D3E3308F272A5004A47F5 /* error.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = error.n; sourceTree = "<group>"; };
+ F96D3E3408F272A5004A47F5 /* Eval.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Eval.3; sourceTree = "<group>"; };
+ F96D3E3508F272A5004A47F5 /* eval.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = eval.n; sourceTree = "<group>"; };
+ F96D3E3608F272A5004A47F5 /* exec.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = exec.n; sourceTree = "<group>"; };
+ F96D3E3708F272A5004A47F5 /* Exit.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Exit.3; sourceTree = "<group>"; };
+ F96D3E3808F272A5004A47F5 /* exit.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = exit.n; sourceTree = "<group>"; };
+ F96D3E3908F272A5004A47F5 /* expr.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = expr.n; sourceTree = "<group>"; };
+ F96D3E3A08F272A5004A47F5 /* ExprLong.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ExprLong.3; sourceTree = "<group>"; };
+ F96D3E3B08F272A5004A47F5 /* ExprLongObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ExprLongObj.3; sourceTree = "<group>"; };
+ F96D3E3C08F272A5004A47F5 /* fblocked.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fblocked.n; sourceTree = "<group>"; };
+ F96D3E3D08F272A5004A47F5 /* fconfigure.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fconfigure.n; sourceTree = "<group>"; };
+ F96D3E3E08F272A5004A47F5 /* fcopy.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fcopy.n; sourceTree = "<group>"; };
+ F96D3E3F08F272A5004A47F5 /* file.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = file.n; sourceTree = "<group>"; };
+ F96D3E4008F272A5004A47F5 /* fileevent.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fileevent.n; sourceTree = "<group>"; };
+ F96D3E4108F272A5004A47F5 /* filename.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = filename.n; sourceTree = "<group>"; };
+ F96D3E4208F272A5004A47F5 /* FileSystem.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = FileSystem.3; sourceTree = "<group>"; };
+ F96D3E4308F272A5004A47F5 /* FindExec.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = FindExec.3; sourceTree = "<group>"; };
+ F96D3E4408F272A5004A47F5 /* flush.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = flush.n; sourceTree = "<group>"; };
+ F96D3E4508F272A5004A47F5 /* for.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = for.n; sourceTree = "<group>"; };
+ F96D3E4608F272A5004A47F5 /* foreach.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = foreach.n; sourceTree = "<group>"; };
+ F96D3E4708F272A5004A47F5 /* format.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = format.n; sourceTree = "<group>"; };
+ F96D3E4808F272A5004A47F5 /* GetCwd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetCwd.3; sourceTree = "<group>"; };
+ F96D3E4908F272A5004A47F5 /* GetHostName.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetHostName.3; sourceTree = "<group>"; };
+ F96D3E4A08F272A5004A47F5 /* GetIndex.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetIndex.3; sourceTree = "<group>"; };
+ F96D3E4B08F272A5004A47F5 /* GetInt.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetInt.3; sourceTree = "<group>"; };
+ F96D3E4C08F272A5004A47F5 /* GetOpnFl.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetOpnFl.3; sourceTree = "<group>"; };
+ F96D3E4D08F272A5004A47F5 /* gets.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = gets.n; sourceTree = "<group>"; };
+ F96D3E4E08F272A5004A47F5 /* GetStdChan.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetStdChan.3; sourceTree = "<group>"; };
+ F96D3E4F08F272A5004A47F5 /* GetTime.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetTime.3; sourceTree = "<group>"; };
+ F96D3E5008F272A5004A47F5 /* GetVersion.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetVersion.3; sourceTree = "<group>"; };
+ F96D3E5108F272A5004A47F5 /* glob.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = glob.n; sourceTree = "<group>"; };
+ F96D3E5208F272A6004A47F5 /* global.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = global.n; sourceTree = "<group>"; };
+ F96D3E5308F272A6004A47F5 /* Hash.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Hash.3; sourceTree = "<group>"; };
+ F96D3E5408F272A6004A47F5 /* history.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = history.n; sourceTree = "<group>"; };
+ F96D3E5508F272A6004A47F5 /* http.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = http.n; sourceTree = "<group>"; };
+ F96D3E5608F272A6004A47F5 /* if.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = if.n; sourceTree = "<group>"; };
+ F96D3E5708F272A6004A47F5 /* incr.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = incr.n; sourceTree = "<group>"; };
+ F96D3E5808F272A6004A47F5 /* info.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = info.n; sourceTree = "<group>"; };
+ F96D3E5908F272A6004A47F5 /* Init.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Init.3; sourceTree = "<group>"; };
+ F96D3E5A08F272A6004A47F5 /* InitStubs.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = InitStubs.3; sourceTree = "<group>"; };
+ F96D3E5B08F272A6004A47F5 /* Interp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Interp.3; sourceTree = "<group>"; };
+ F96D3E5C08F272A6004A47F5 /* interp.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = interp.n; sourceTree = "<group>"; };
+ F96D3E5D08F272A6004A47F5 /* IntObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = IntObj.3; sourceTree = "<group>"; };
+ F96D3E5E08F272A6004A47F5 /* join.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = join.n; sourceTree = "<group>"; };
+ F96D3E5F08F272A6004A47F5 /* lappend.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lappend.n; sourceTree = "<group>"; };
+ F96D3E6008F272A6004A47F5 /* lassign.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lassign.n; sourceTree = "<group>"; };
+ F96D3E6108F272A6004A47F5 /* library.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = library.n; sourceTree = "<group>"; };
+ F96D3E6208F272A6004A47F5 /* Limit.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Limit.3; sourceTree = "<group>"; };
+ F96D3E6308F272A6004A47F5 /* lindex.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lindex.n; sourceTree = "<group>"; };
+ F96D3E6408F272A6004A47F5 /* LinkVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = LinkVar.3; sourceTree = "<group>"; };
+ F96D3E6508F272A6004A47F5 /* linsert.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = linsert.n; sourceTree = "<group>"; };
+ F96D3E6608F272A6004A47F5 /* list.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = list.n; sourceTree = "<group>"; };
+ F96D3E6708F272A6004A47F5 /* ListObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ListObj.3; sourceTree = "<group>"; };
+ F96D3E6808F272A6004A47F5 /* llength.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = llength.n; sourceTree = "<group>"; };
+ F96D3E6908F272A6004A47F5 /* load.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = load.n; sourceTree = "<group>"; };
+ F96D3E6A08F272A6004A47F5 /* lrange.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lrange.n; sourceTree = "<group>"; };
+ F96D3E6B08F272A6004A47F5 /* lrepeat.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lrepeat.n; sourceTree = "<group>"; };
+ F96D3E6C08F272A6004A47F5 /* lreplace.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lreplace.n; sourceTree = "<group>"; };
+ F96D3E6D08F272A6004A47F5 /* lsearch.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lsearch.n; sourceTree = "<group>"; };
+ F96D3E6E08F272A6004A47F5 /* lset.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lset.n; sourceTree = "<group>"; };
+ F96D3E6F08F272A6004A47F5 /* lsort.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lsort.n; sourceTree = "<group>"; };
+ F96D3E7008F272A6004A47F5 /* man.macros */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = man.macros; sourceTree = "<group>"; };
+ F96D3E7108F272A6004A47F5 /* mathfunc.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = mathfunc.n; sourceTree = "<group>"; };
+ F96D3E7208F272A6004A47F5 /* memory.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = memory.n; sourceTree = "<group>"; };
+ F96D3E7308F272A6004A47F5 /* msgcat.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = msgcat.n; sourceTree = "<group>"; };
+ F96D3E7408F272A6004A47F5 /* Namespace.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Namespace.3; sourceTree = "<group>"; };
+ F96D3E7508F272A6004A47F5 /* namespace.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = namespace.n; sourceTree = "<group>"; };
+ F96D3E7608F272A6004A47F5 /* Notifier.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Notifier.3; sourceTree = "<group>"; };
+ F96D3E7708F272A6004A47F5 /* Object.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Object.3; sourceTree = "<group>"; };
+ F96D3E7808F272A6004A47F5 /* ObjectType.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ObjectType.3; sourceTree = "<group>"; };
+ F96D3E7908F272A6004A47F5 /* open.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = open.n; sourceTree = "<group>"; };
+ F96D3E7A08F272A6004A47F5 /* OpenFileChnl.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = OpenFileChnl.3; sourceTree = "<group>"; };
+ F96D3E7B08F272A6004A47F5 /* OpenTcp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = OpenTcp.3; sourceTree = "<group>"; };
+ F96D3E7C08F272A6004A47F5 /* package.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = package.n; sourceTree = "<group>"; };
+ F96D3E7D08F272A6004A47F5 /* packagens.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = packagens.n; sourceTree = "<group>"; };
+ F96D3E7E08F272A6004A47F5 /* Panic.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Panic.3; sourceTree = "<group>"; };
+ F96D3E7F08F272A6004A47F5 /* ParseCmd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ParseCmd.3; sourceTree = "<group>"; };
+ F96D3E8008F272A6004A47F5 /* pid.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = pid.n; sourceTree = "<group>"; };
+ F96D3E8108F272A6004A47F5 /* pkgMkIndex.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = pkgMkIndex.n; sourceTree = "<group>"; };
+ F96D3E8208F272A6004A47F5 /* PkgRequire.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = PkgRequire.3; sourceTree = "<group>"; };
+ F96D3E8308F272A6004A47F5 /* Preserve.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Preserve.3; sourceTree = "<group>"; };
+ F96D3E8408F272A6004A47F5 /* PrintDbl.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = PrintDbl.3; sourceTree = "<group>"; };
+ F96D3E8508F272A6004A47F5 /* proc.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = proc.n; sourceTree = "<group>"; };
+ F96D3E8608F272A6004A47F5 /* puts.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = puts.n; sourceTree = "<group>"; };
+ F96D3E8708F272A6004A47F5 /* pwd.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = pwd.n; sourceTree = "<group>"; };
+ F96D3E8808F272A6004A47F5 /* re_syntax.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = re_syntax.n; sourceTree = "<group>"; };
+ F96D3E8908F272A6004A47F5 /* read.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = read.n; sourceTree = "<group>"; };
+ F96D3E8A08F272A6004A47F5 /* RecEvalObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RecEvalObj.3; sourceTree = "<group>"; };
+ F96D3E8B08F272A6004A47F5 /* RecordEval.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RecordEval.3; sourceTree = "<group>"; };
+ F96D3E8C08F272A6004A47F5 /* RegConfig.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RegConfig.3; sourceTree = "<group>"; };
+ F96D3E8D08F272A6004A47F5 /* RegExp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RegExp.3; sourceTree = "<group>"; };
+ F96D3E8E08F272A6004A47F5 /* regexp.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = regexp.n; sourceTree = "<group>"; };
+ F96D3E8F08F272A6004A47F5 /* registry.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = registry.n; sourceTree = "<group>"; };
+ F96D3E9008F272A6004A47F5 /* regsub.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = regsub.n; sourceTree = "<group>"; };
+ F96D3E9108F272A6004A47F5 /* rename.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = rename.n; sourceTree = "<group>"; };
+ F96D3E9208F272A6004A47F5 /* return.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = return.n; sourceTree = "<group>"; };
+ F96D3E9308F272A6004A47F5 /* safe.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = safe.n; sourceTree = "<group>"; };
+ F96D3E9408F272A6004A47F5 /* SaveResult.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SaveResult.3; sourceTree = "<group>"; };
+ F96D3E9508F272A6004A47F5 /* scan.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = scan.n; sourceTree = "<group>"; };
+ F96D3E9608F272A6004A47F5 /* seek.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = seek.n; sourceTree = "<group>"; };
+ F96D3E9708F272A6004A47F5 /* set.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = set.n; sourceTree = "<group>"; };
+ F96D3E9808F272A6004A47F5 /* SetChanErr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetChanErr.3; sourceTree = "<group>"; };
+ F96D3E9908F272A6004A47F5 /* SetErrno.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetErrno.3; sourceTree = "<group>"; };
+ F96D3E9A08F272A6004A47F5 /* SetRecLmt.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetRecLmt.3; sourceTree = "<group>"; };
+ F96D3E9B08F272A7004A47F5 /* SetResult.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetResult.3; sourceTree = "<group>"; };
+ F96D3E9C08F272A7004A47F5 /* SetVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetVar.3; sourceTree = "<group>"; };
+ F96D3E9D08F272A7004A47F5 /* Signal.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Signal.3; sourceTree = "<group>"; };
+ F96D3E9E08F272A7004A47F5 /* Sleep.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Sleep.3; sourceTree = "<group>"; };
+ F96D3E9F08F272A7004A47F5 /* socket.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = socket.n; sourceTree = "<group>"; };
+ F96D3EA008F272A7004A47F5 /* source.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = source.n; sourceTree = "<group>"; };
+ F96D3EA108F272A7004A47F5 /* SourceRCFile.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SourceRCFile.3; sourceTree = "<group>"; };
+ F96D3EA208F272A7004A47F5 /* split.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = split.n; sourceTree = "<group>"; };
+ F96D3EA308F272A7004A47F5 /* SplitList.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SplitList.3; sourceTree = "<group>"; };
+ F96D3EA408F272A7004A47F5 /* SplitPath.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SplitPath.3; sourceTree = "<group>"; };
+ F96D3EA508F272A7004A47F5 /* StaticPkg.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StaticPkg.3; sourceTree = "<group>"; };
+ F96D3EA608F272A7004A47F5 /* StdChannels.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StdChannels.3; sourceTree = "<group>"; };
+ F96D3EA708F272A7004A47F5 /* string.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = string.n; sourceTree = "<group>"; };
+ F96D3EA808F272A7004A47F5 /* StringObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StringObj.3; sourceTree = "<group>"; };
+ F96D3EA908F272A7004A47F5 /* StrMatch.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StrMatch.3; sourceTree = "<group>"; };
+ F96D3EAA08F272A7004A47F5 /* subst.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = subst.n; sourceTree = "<group>"; };
+ F96D3EAB08F272A7004A47F5 /* SubstObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SubstObj.3; sourceTree = "<group>"; };
+ F96D3EAC08F272A7004A47F5 /* switch.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = switch.n; sourceTree = "<group>"; };
+ F96D3EAD08F272A7004A47F5 /* Tcl.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Tcl.n; sourceTree = "<group>"; };
+ F96D3EAE08F272A7004A47F5 /* Tcl_Main.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Tcl_Main.3; sourceTree = "<group>"; };
+ F96D3EAF08F272A7004A47F5 /* TCL_MEM_DEBUG.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TCL_MEM_DEBUG.3; sourceTree = "<group>"; };
+ F96D3EB008F272A7004A47F5 /* tclsh.1 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tclsh.1; sourceTree = "<group>"; };
+ F96D3EB108F272A7004A47F5 /* tcltest.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tcltest.n; sourceTree = "<group>"; };
+ F96D3EB208F272A7004A47F5 /* tclvars.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tclvars.n; sourceTree = "<group>"; };
+ F96D3EB308F272A7004A47F5 /* tell.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tell.n; sourceTree = "<group>"; };
+ F96D3EB408F272A7004A47F5 /* Thread.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Thread.3; sourceTree = "<group>"; };
+ F96D3EB508F272A7004A47F5 /* time.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = time.n; sourceTree = "<group>"; };
+ F96D3EB608F272A7004A47F5 /* tm.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tm.n; sourceTree = "<group>"; };
+ F96D3EB708F272A7004A47F5 /* ToUpper.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ToUpper.3; sourceTree = "<group>"; };
+ F96D3EB808F272A7004A47F5 /* trace.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = trace.n; sourceTree = "<group>"; };
+ F96D3EB908F272A7004A47F5 /* TraceCmd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TraceCmd.3; sourceTree = "<group>"; };
+ F96D3EBA08F272A7004A47F5 /* TraceVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TraceVar.3; sourceTree = "<group>"; };
+ F96D3EBB08F272A7004A47F5 /* Translate.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Translate.3; sourceTree = "<group>"; };
+ F96D3EBC08F272A7004A47F5 /* UniCharIsAlpha.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = UniCharIsAlpha.3; sourceTree = "<group>"; };
+ F96D3EBD08F272A7004A47F5 /* unknown.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = unknown.n; sourceTree = "<group>"; };
+ F96D3EBE08F272A7004A47F5 /* unload.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = unload.n; sourceTree = "<group>"; };
+ F96D3EBF08F272A7004A47F5 /* unset.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = unset.n; sourceTree = "<group>"; };
+ F96D3EC008F272A7004A47F5 /* update.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = update.n; sourceTree = "<group>"; };
+ F96D3EC108F272A7004A47F5 /* uplevel.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = uplevel.n; sourceTree = "<group>"; };
+ F96D3EC208F272A7004A47F5 /* UpVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = UpVar.3; sourceTree = "<group>"; };
+ F96D3EC308F272A7004A47F5 /* upvar.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = upvar.n; sourceTree = "<group>"; };
+ F96D3EC408F272A7004A47F5 /* Utf.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Utf.3; sourceTree = "<group>"; };
+ F96D3EC508F272A7004A47F5 /* variable.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = variable.n; sourceTree = "<group>"; };
+ F96D3EC608F272A7004A47F5 /* vwait.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = vwait.n; sourceTree = "<group>"; };
+ F96D3EC708F272A7004A47F5 /* while.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = while.n; sourceTree = "<group>"; };
+ F96D3EC808F272A7004A47F5 /* WrongNumArgs.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = WrongNumArgs.3; sourceTree = "<group>"; };
+ F96D3ECA08F272A7004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F96D3ECB08F272A7004A47F5 /* regc_color.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_color.c; sourceTree = "<group>"; };
+ F96D3ECC08F272A7004A47F5 /* regc_cvec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_cvec.c; sourceTree = "<group>"; };
+ F96D3ECD08F272A7004A47F5 /* regc_lex.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_lex.c; sourceTree = "<group>"; };
+ F96D3ECE08F272A7004A47F5 /* regc_locale.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_locale.c; sourceTree = "<group>"; };
+ F96D3ECF08F272A7004A47F5 /* regc_nfa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_nfa.c; sourceTree = "<group>"; };
+ F96D3ED008F272A7004A47F5 /* regcomp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regcomp.c; sourceTree = "<group>"; };
+ F96D3ED108F272A7004A47F5 /* regcustom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regcustom.h; sourceTree = "<group>"; };
+ F96D3ED208F272A7004A47F5 /* rege_dfa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rege_dfa.c; sourceTree = "<group>"; };
+ F96D3ED308F272A7004A47F5 /* regerror.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regerror.c; sourceTree = "<group>"; };
+ F96D3ED408F272A7004A47F5 /* regerrs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regerrs.h; sourceTree = "<group>"; };
+ F96D3ED508F272A7004A47F5 /* regex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regex.h; sourceTree = "<group>"; };
+ F96D3ED608F272A7004A47F5 /* regexec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regexec.c; sourceTree = "<group>"; };
+ F96D3ED708F272A7004A47F5 /* regfree.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regfree.c; sourceTree = "<group>"; };
+ F96D3ED808F272A7004A47F5 /* regfronts.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regfronts.c; sourceTree = "<group>"; };
+ F96D3ED908F272A7004A47F5 /* regguts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regguts.h; sourceTree = "<group>"; };
+ F96D3EDA08F272A7004A47F5 /* tcl.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tcl.decls; sourceTree = "<group>"; };
+ F96D3EDB08F272A7004A47F5 /* tcl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tcl.h; sourceTree = "<group>"; };
+ F96D3EDC08F272A7004A47F5 /* tclAlloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAlloc.c; sourceTree = "<group>"; };
+ F96D3EDD08F272A7004A47F5 /* tclAsync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAsync.c; sourceTree = "<group>"; };
+ F96D3EDE08F272A7004A47F5 /* tclBasic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclBasic.c; sourceTree = "<group>"; };
+ F96D3EDF08F272A7004A47F5 /* tclBinary.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclBinary.c; sourceTree = "<group>"; };
+ F96D3EE008F272A7004A47F5 /* tclCkalloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCkalloc.c; sourceTree = "<group>"; };
+ F96D3EE108F272A7004A47F5 /* tclClock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclClock.c; sourceTree = "<group>"; };
+ F96D3EE208F272A7004A47F5 /* tclCmdAH.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCmdAH.c; sourceTree = "<group>"; };
+ F96D3EE308F272A7004A47F5 /* tclCmdIL.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCmdIL.c; sourceTree = "<group>"; };
+ F96D3EE408F272A7004A47F5 /* tclCmdMZ.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCmdMZ.c; sourceTree = "<group>"; };
+ F96D3EE508F272A7004A47F5 /* tclCompCmds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCompCmds.c; sourceTree = "<group>"; };
+ F96D3EE608F272A7004A47F5 /* tclCompExpr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCompExpr.c; sourceTree = "<group>"; };
+ F96D3EE708F272A7004A47F5 /* tclCompile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCompile.c; sourceTree = "<group>"; };
+ F96D3EE808F272A7004A47F5 /* tclCompile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclCompile.h; sourceTree = "<group>"; };
+ F96D3EE908F272A7004A47F5 /* tclConfig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclConfig.c; sourceTree = "<group>"; };
+ F96D3EEA08F272A7004A47F5 /* tclDate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclDate.c; sourceTree = "<group>"; };
+ F96D3EEB08F272A7004A47F5 /* tclDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclDecls.h; sourceTree = "<group>"; };
+ F96D3EEC08F272A7004A47F5 /* tclDictObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclDictObj.c; sourceTree = "<group>"; };
+ F96D3EED08F272A7004A47F5 /* tclEncoding.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclEncoding.c; sourceTree = "<group>"; };
+ F96D3EEE08F272A7004A47F5 /* tclEnv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclEnv.c; sourceTree = "<group>"; };
+ F96D3EEF08F272A7004A47F5 /* tclEvent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclEvent.c; sourceTree = "<group>"; };
+ F96D3EF008F272A7004A47F5 /* tclExecute.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclExecute.c; sourceTree = "<group>"; };
+ F96D3EF108F272A7004A47F5 /* tclFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclFCmd.c; sourceTree = "<group>"; };
+ F96D3EF208F272A7004A47F5 /* tclFileName.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclFileName.c; sourceTree = "<group>"; };
+ F96D3EF308F272A7004A47F5 /* tclFileSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclFileSystem.h; sourceTree = "<group>"; };
+ F96D3EF408F272A7004A47F5 /* tclGet.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclGet.c; sourceTree = "<group>"; };
+ F96D3EF508F272A7004A47F5 /* tclGetDate.y */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.yacc; path = tclGetDate.y; sourceTree = "<group>"; };
+ F96D3EF608F272A7004A47F5 /* tclHash.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclHash.c; sourceTree = "<group>"; };
+ F96D3EF708F272A7004A47F5 /* tclHistory.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclHistory.c; sourceTree = "<group>"; };
+ F96D3EF808F272A7004A47F5 /* tclIndexObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIndexObj.c; sourceTree = "<group>"; };
+ F96D3EF908F272A7004A47F5 /* tclInt.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclInt.decls; sourceTree = "<group>"; };
+ F96D3EFA08F272A7004A47F5 /* tclInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclInt.h; sourceTree = "<group>"; };
+ F96D3EFB08F272A7004A47F5 /* tclIntDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclIntDecls.h; sourceTree = "<group>"; };
+ F96D3EFC08F272A7004A47F5 /* tclInterp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclInterp.c; sourceTree = "<group>"; };
+ F96D3EFD08F272A7004A47F5 /* tclIntPlatDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclIntPlatDecls.h; sourceTree = "<group>"; };
+ F96D3EFE08F272A7004A47F5 /* tclIO.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIO.c; sourceTree = "<group>"; };
+ F96D3EFF08F272A7004A47F5 /* tclIO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclIO.h; sourceTree = "<group>"; };
+ F96D3F0008F272A7004A47F5 /* tclIOCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOCmd.c; sourceTree = "<group>"; };
+ F96D3F0108F272A7004A47F5 /* tclIOGT.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOGT.c; sourceTree = "<group>"; };
+ F96D3F0208F272A7004A47F5 /* tclIORChan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIORChan.c; sourceTree = "<group>"; };
+ F96D3F0308F272A7004A47F5 /* tclIOSock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOSock.c; sourceTree = "<group>"; };
+ F96D3F0408F272A7004A47F5 /* tclIOUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOUtil.c; sourceTree = "<group>"; };
+ F96D3F0508F272A7004A47F5 /* tclLink.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLink.c; sourceTree = "<group>"; };
+ F96D3F0608F272A7004A47F5 /* tclListObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclListObj.c; sourceTree = "<group>"; };
+ F96D3F0708F272A7004A47F5 /* tclLiteral.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLiteral.c; sourceTree = "<group>"; };
+ F96D3F0808F272A7004A47F5 /* tclLoad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoad.c; sourceTree = "<group>"; };
+ F96D3F0908F272A7004A47F5 /* tclLoadNone.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadNone.c; sourceTree = "<group>"; };
+ F96D3F0A08F272A7004A47F5 /* tclMain.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMain.c; sourceTree = "<group>"; };
+ F96D3F0B08F272A7004A47F5 /* tclNamesp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclNamesp.c; sourceTree = "<group>"; };
+ F96D3F0C08F272A7004A47F5 /* tclNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclNotify.c; sourceTree = "<group>"; };
+ F96D3F0D08F272A7004A47F5 /* tclObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclObj.c; sourceTree = "<group>"; };
+ F96D3F0E08F272A7004A47F5 /* tclPanic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPanic.c; sourceTree = "<group>"; };
+ F96D3F0F08F272A7004A47F5 /* tclParse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclParse.c; sourceTree = "<group>"; };
+ F96D3F1108F272A7004A47F5 /* tclPathObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPathObj.c; sourceTree = "<group>"; };
+ F96D3F1208F272A7004A47F5 /* tclPipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPipe.c; sourceTree = "<group>"; };
+ F96D3F1308F272A7004A47F5 /* tclPkg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPkg.c; sourceTree = "<group>"; };
+ F96D3F1408F272A7004A47F5 /* tclPkgConfig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPkgConfig.c; sourceTree = "<group>"; };
+ F96D3F1508F272A7004A47F5 /* tclPlatDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclPlatDecls.h; sourceTree = "<group>"; };
+ F96D3F1608F272A7004A47F5 /* tclPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclPort.h; sourceTree = "<group>"; };
+ F96D3F1708F272A7004A47F5 /* tclPosixStr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPosixStr.c; sourceTree = "<group>"; };
+ F96D3F1808F272A7004A47F5 /* tclPreserve.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPreserve.c; sourceTree = "<group>"; };
+ F96D3F1908F272A7004A47F5 /* tclProc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclProc.c; sourceTree = "<group>"; };
+ F96D3F1A08F272A7004A47F5 /* tclRegexp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclRegexp.c; sourceTree = "<group>"; };
+ F96D3F1B08F272A7004A47F5 /* tclRegexp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclRegexp.h; sourceTree = "<group>"; };
+ F96D3F1C08F272A7004A47F5 /* tclResolve.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclResolve.c; sourceTree = "<group>"; };
+ F96D3F1D08F272A7004A47F5 /* tclResult.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclResult.c; sourceTree = "<group>"; };
+ F96D3F1E08F272A7004A47F5 /* tclScan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclScan.c; sourceTree = "<group>"; };
+ F96D3F1F08F272A7004A47F5 /* tclStringObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStringObj.c; sourceTree = "<group>"; };
+ F96D3F2408F272A7004A47F5 /* tclStrToD.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStrToD.c; sourceTree = "<group>"; };
+ F96D3F2508F272A7004A47F5 /* tclStubInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStubInit.c; sourceTree = "<group>"; };
+ F96D3F2608F272A7004A47F5 /* tclStubLib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStubLib.c; sourceTree = "<group>"; };
+ F96D3F2708F272A7004A47F5 /* tclTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTest.c; sourceTree = "<group>"; };
+ F96D3F2808F272A7004A47F5 /* tclTestObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTestObj.c; sourceTree = "<group>"; };
+ F96D3F2908F272A7004A47F5 /* tclTestProcBodyObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTestProcBodyObj.c; sourceTree = "<group>"; };
+ F96D3F2A08F272A7004A47F5 /* tclThread.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThread.c; sourceTree = "<group>"; };
+ F96D3F2B08F272A7004A47F5 /* tclThreadAlloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadAlloc.c; sourceTree = "<group>"; };
+ F96D3F2C08F272A7004A47F5 /* tclThreadJoin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadJoin.c; sourceTree = "<group>"; };
+ F96D3F2D08F272A7004A47F5 /* tclThreadStorage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadStorage.c; sourceTree = "<group>"; };
+ F96D3F2E08F272A7004A47F5 /* tclThreadTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadTest.c; sourceTree = "<group>"; };
+ F96D3F2F08F272A7004A47F5 /* tclTimer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTimer.c; sourceTree = "<group>"; };
+ F96D3F3008F272A7004A47F5 /* tclTomMath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclTomMath.h; sourceTree = "<group>"; };
+ F96D3F3108F272A7004A47F5 /* tclTomMathInterface.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTomMathInterface.c; sourceTree = "<group>"; };
+ F96D3F3208F272A7004A47F5 /* tclTrace.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTrace.c; sourceTree = "<group>"; };
+ F96D3F3308F272A7004A47F5 /* tclUniData.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUniData.c; sourceTree = "<group>"; };
+ F96D3F3408F272A7004A47F5 /* tclUtf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUtf.c; sourceTree = "<group>"; };
+ F96D3F3508F272A7004A47F5 /* tclUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUtil.c; sourceTree = "<group>"; };
+ F96D3F3608F272A7004A47F5 /* tclVar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclVar.c; sourceTree = "<group>"; };
+ F96D3F3708F272A7004A47F5 /* tommath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tommath.h; sourceTree = "<group>"; };
+ F96D3F3908F272A8004A47F5 /* auto.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = auto.tcl; sourceTree = "<group>"; };
+ F96D3F3A08F272A8004A47F5 /* clock.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = clock.tcl; sourceTree = "<group>"; };
+ F96D3F3C08F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F96D3F8C08F272A8004A47F5 /* history.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = history.tcl; sourceTree = "<group>"; };
+ F96D3F8E08F272A8004A47F5 /* http.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = http.tcl; sourceTree = "<group>"; };
+ F96D3F8F08F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F96D3F9108F272A8004A47F5 /* http.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = http.tcl; sourceTree = "<group>"; };
+ F96D3F9208F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F96D3F9308F272A8004A47F5 /* init.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = init.tcl; sourceTree = "<group>"; };
+ F96D3F9508F272A8004A47F5 /* msgcat.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = msgcat.tcl; sourceTree = "<group>"; };
+ F96D3F9608F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F96D401808F272AA004A47F5 /* optparse.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = optparse.tcl; sourceTree = "<group>"; };
+ F96D401908F272AA004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F96D401A08F272AA004A47F5 /* package.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = package.tcl; sourceTree = "<group>"; };
+ F96D401B08F272AA004A47F5 /* parray.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parray.tcl; sourceTree = "<group>"; };
+ F96D401D08F272AA004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F96D401E08F272AA004A47F5 /* safe.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = safe.tcl; sourceTree = "<group>"; };
+ F96D401F08F272AA004A47F5 /* tclIndex */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclIndex; sourceTree = "<group>"; };
+ F96D402108F272AA004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F96D402208F272AA004A47F5 /* tcltest.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tcltest.tcl; sourceTree = "<group>"; };
+ F96D402308F272AA004A47F5 /* tm.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tm.tcl; sourceTree = "<group>"; };
+ F96D425B08F272B2004A47F5 /* word.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = word.tcl; sourceTree = "<group>"; };
+ F96D426408F272B3004A47F5 /* bn_fast_s_mp_mul_digs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_fast_s_mp_mul_digs.c; sourceTree = "<group>"; };
+ F96D426608F272B3004A47F5 /* bn_fast_s_mp_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_fast_s_mp_sqr.c; sourceTree = "<group>"; };
+ F96D426908F272B3004A47F5 /* bn_mp_add.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_add.c; sourceTree = "<group>"; };
+ F96D426A08F272B3004A47F5 /* bn_mp_add_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_add_d.c; sourceTree = "<group>"; };
+ F96D426C08F272B3004A47F5 /* bn_mp_and.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_and.c; sourceTree = "<group>"; };
+ F96D426D08F272B3004A47F5 /* bn_mp_clamp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_clamp.c; sourceTree = "<group>"; };
+ F96D426E08F272B3004A47F5 /* bn_mp_clear.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_clear.c; sourceTree = "<group>"; };
+ F96D426F08F272B3004A47F5 /* bn_mp_clear_multi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_clear_multi.c; sourceTree = "<group>"; };
+ F96D427008F272B3004A47F5 /* bn_mp_cmp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_cmp.c; sourceTree = "<group>"; };
+ F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_cmp_d.c; sourceTree = "<group>"; };
+ F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_cmp_mag.c; sourceTree = "<group>"; };
+ F96D427408F272B3004A47F5 /* bn_mp_copy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_copy.c; sourceTree = "<group>"; };
+ F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_count_bits.c; sourceTree = "<group>"; };
+ F96D427608F272B3004A47F5 /* bn_mp_div.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div.c; sourceTree = "<group>"; };
+ F96D427708F272B3004A47F5 /* bn_mp_div_2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_2.c; sourceTree = "<group>"; };
+ F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_2d.c; sourceTree = "<group>"; };
+ F96D427908F272B3004A47F5 /* bn_mp_div_3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_3.c; sourceTree = "<group>"; };
+ F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_d.c; sourceTree = "<group>"; };
+ F96D427E08F272B3004A47F5 /* bn_mp_exch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_exch.c; sourceTree = "<group>"; };
+ F96D427F08F272B3004A47F5 /* bn_mp_expt_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_expt_d.c; sourceTree = "<group>"; };
+ F96D428708F272B3004A47F5 /* bn_mp_grow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_grow.c; sourceTree = "<group>"; };
+ F96D428808F272B3004A47F5 /* bn_mp_init.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init.c; sourceTree = "<group>"; };
+ F96D428908F272B3004A47F5 /* bn_mp_init_copy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_copy.c; sourceTree = "<group>"; };
+ F96D428A08F272B3004A47F5 /* bn_mp_init_multi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_multi.c; sourceTree = "<group>"; };
+ F96D428B08F272B3004A47F5 /* bn_mp_init_set.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_set.c; sourceTree = "<group>"; };
+ F96D428D08F272B3004A47F5 /* bn_mp_init_size.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_size.c; sourceTree = "<group>"; };
+ F96D429208F272B3004A47F5 /* bn_mp_karatsuba_mul.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_karatsuba_mul.c; sourceTree = "<group>"; };
+ F96D429308F272B3004A47F5 /* bn_mp_karatsuba_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_karatsuba_sqr.c; sourceTree = "<group>"; };
+ F96D429508F272B3004A47F5 /* bn_mp_lshd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_lshd.c; sourceTree = "<group>"; };
+ F96D429608F272B3004A47F5 /* bn_mp_mod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mod.c; sourceTree = "<group>"; };
+ F96D429708F272B3004A47F5 /* bn_mp_mod_2d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mod_2d.c; sourceTree = "<group>"; };
+ F96D429C08F272B3004A47F5 /* bn_mp_mul.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul.c; sourceTree = "<group>"; };
+ F96D429D08F272B3004A47F5 /* bn_mp_mul_2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul_2.c; sourceTree = "<group>"; };
+ F96D429E08F272B3004A47F5 /* bn_mp_mul_2d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul_2d.c; sourceTree = "<group>"; };
+ F96D429F08F272B3004A47F5 /* bn_mp_mul_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul_d.c; sourceTree = "<group>"; };
+ F96D42A208F272B3004A47F5 /* bn_mp_neg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_neg.c; sourceTree = "<group>"; };
+ F96D42A308F272B3004A47F5 /* bn_mp_or.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_or.c; sourceTree = "<group>"; };
+ F96D42AB08F272B3004A47F5 /* bn_mp_radix_size.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_radix_size.c; sourceTree = "<group>"; };
+ F96D42AC08F272B3004A47F5 /* bn_mp_radix_smap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_radix_smap.c; sourceTree = "<group>"; };
+ F96D42AE08F272B3004A47F5 /* bn_mp_read_radix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_read_radix.c; sourceTree = "<group>"; };
+ F96D42B908F272B3004A47F5 /* bn_mp_rshd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_rshd.c; sourceTree = "<group>"; };
+ F96D42BA08F272B3004A47F5 /* bn_mp_set.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_set.c; sourceTree = "<group>"; };
+ F96D42BC08F272B3004A47F5 /* bn_mp_shrink.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_shrink.c; sourceTree = "<group>"; };
+ F96D42BE08F272B3004A47F5 /* bn_mp_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sqr.c; sourceTree = "<group>"; };
+ F96D42C008F272B3004A47F5 /* bn_mp_sqrt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sqrt.c; sourceTree = "<group>"; };
+ F96D42C108F272B3004A47F5 /* bn_mp_sub.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sub.c; sourceTree = "<group>"; };
+ F96D42C208F272B3004A47F5 /* bn_mp_sub_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sub_d.c; sourceTree = "<group>"; };
+ F96D42C608F272B3004A47F5 /* bn_mp_to_unsigned_bin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_to_unsigned_bin.c; sourceTree = "<group>"; };
+ F96D42C708F272B3004A47F5 /* bn_mp_to_unsigned_bin_n.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_to_unsigned_bin_n.c; sourceTree = "<group>"; };
+ F96D42C808F272B3004A47F5 /* bn_mp_toom_mul.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_toom_mul.c; sourceTree = "<group>"; };
+ F96D42C908F272B3004A47F5 /* bn_mp_toom_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_toom_sqr.c; sourceTree = "<group>"; };
+ F96D42CB08F272B3004A47F5 /* bn_mp_toradix_n.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_toradix_n.c; sourceTree = "<group>"; };
+ F96D42CC08F272B3004A47F5 /* bn_mp_unsigned_bin_size.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_unsigned_bin_size.c; sourceTree = "<group>"; };
+ F96D42CD08F272B3004A47F5 /* bn_mp_xor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_xor.c; sourceTree = "<group>"; };
+ F96D42CE08F272B3004A47F5 /* bn_mp_zero.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_zero.c; sourceTree = "<group>"; };
+ F96D42D008F272B3004A47F5 /* bn_reverse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_reverse.c; sourceTree = "<group>"; };
+ F96D42D108F272B3004A47F5 /* bn_s_mp_add.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_add.c; sourceTree = "<group>"; };
+ F96D42D308F272B3004A47F5 /* bn_s_mp_mul_digs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_mul_digs.c; sourceTree = "<group>"; };
+ F96D42D508F272B3004A47F5 /* bn_s_mp_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_sqr.c; sourceTree = "<group>"; };
+ F96D42D608F272B3004A47F5 /* bn_s_mp_sub.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_sub.c; sourceTree = "<group>"; };
+ F96D42D708F272B3004A47F5 /* bncore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bncore.c; sourceTree = "<group>"; };
+ F96D432908F272B4004A47F5 /* tommath_class.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tommath_class.h; sourceTree = "<group>"; };
+ F96D432A08F272B4004A47F5 /* tommath_superclass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tommath_superclass.h; sourceTree = "<group>"; };
+ F96D432B08F272B4004A47F5 /* license.terms */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = license.terms; sourceTree = "<group>"; };
+ F96D432E08F272B5004A47F5 /* configure.ac */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure.ac; sourceTree = "<group>"; };
+ F96D432F08F272B5004A47F5 /* GNUmakefile */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = GNUmakefile; sourceTree = "<group>"; };
+ F96D433108F272B5004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F96D433208F272B5004A47F5 /* Tcl-Info.plist.in */ = {isa = PBXFileReference; explicitFileType = text.plist; fileEncoding = 4; path = "Tcl-Info.plist.in"; sourceTree = "<group>"; };
+ F96D433908F272B5004A47F5 /* tclMacOSXBundle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMacOSXBundle.c; sourceTree = "<group>"; };
+ F96D433D08F272B5004A47F5 /* tclMacOSXFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMacOSXFCmd.c; sourceTree = "<group>"; };
+ F96D433E08F272B5004A47F5 /* tclMacOSXNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMacOSXNotify.c; sourceTree = "<group>"; };
+ F96D434308F272B5004A47F5 /* README */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = README; sourceTree = "<group>"; };
+ F96D434508F272B5004A47F5 /* all.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = all.tcl; sourceTree = "<group>"; };
+ F96D434608F272B5004A47F5 /* append.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = append.test; sourceTree = "<group>"; };
+ F96D434708F272B5004A47F5 /* appendComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = appendComp.test; sourceTree = "<group>"; };
+ F96D434808F272B5004A47F5 /* assocd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = assocd.test; sourceTree = "<group>"; };
+ F96D434908F272B5004A47F5 /* async.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = async.test; sourceTree = "<group>"; };
+ F96D434A08F272B5004A47F5 /* autoMkindex.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = autoMkindex.test; sourceTree = "<group>"; };
+ F96D434B08F272B5004A47F5 /* basic.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = basic.test; sourceTree = "<group>"; };
+ F96D434C08F272B5004A47F5 /* binary.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = binary.test; sourceTree = "<group>"; };
+ F96D434D08F272B5004A47F5 /* case.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = case.test; sourceTree = "<group>"; };
+ F96D434E08F272B5004A47F5 /* chan.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = chan.test; sourceTree = "<group>"; };
+ F96D434F08F272B5004A47F5 /* clock.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = clock.test; sourceTree = "<group>"; };
+ F96D435008F272B5004A47F5 /* cmdAH.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdAH.test; sourceTree = "<group>"; };
+ F96D435108F272B5004A47F5 /* cmdIL.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdIL.test; sourceTree = "<group>"; };
+ F96D435208F272B5004A47F5 /* cmdInfo.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdInfo.test; sourceTree = "<group>"; };
+ F96D435308F272B5004A47F5 /* cmdMZ.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdMZ.test; sourceTree = "<group>"; };
+ F96D435408F272B5004A47F5 /* compExpr-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "compExpr-old.test"; sourceTree = "<group>"; };
+ F96D435508F272B5004A47F5 /* compExpr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = compExpr.test; sourceTree = "<group>"; };
+ F96D435608F272B5004A47F5 /* compile.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = compile.test; sourceTree = "<group>"; };
+ F96D435708F272B5004A47F5 /* concat.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = concat.test; sourceTree = "<group>"; };
+ F96D435808F272B5004A47F5 /* config.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = config.test; sourceTree = "<group>"; };
+ F96D435908F272B5004A47F5 /* dcall.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dcall.test; sourceTree = "<group>"; };
+ F96D435A08F272B5004A47F5 /* dict.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dict.test; sourceTree = "<group>"; };
+ F96D435C08F272B5004A47F5 /* dstring.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dstring.test; sourceTree = "<group>"; };
+ F96D435E08F272B5004A47F5 /* encoding.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = encoding.test; sourceTree = "<group>"; };
+ F96D435F08F272B5004A47F5 /* env.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = env.test; sourceTree = "<group>"; };
+ F96D436008F272B5004A47F5 /* error.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = error.test; sourceTree = "<group>"; };
+ F96D436108F272B5004A47F5 /* eval.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = eval.test; sourceTree = "<group>"; };
+ F96D436208F272B5004A47F5 /* event.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = event.test; sourceTree = "<group>"; };
+ F96D436308F272B5004A47F5 /* exec.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = exec.test; sourceTree = "<group>"; };
+ F96D436408F272B5004A47F5 /* execute.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = execute.test; sourceTree = "<group>"; };
+ F96D436508F272B5004A47F5 /* expr-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "expr-old.test"; sourceTree = "<group>"; };
+ F96D436608F272B5004A47F5 /* expr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = expr.test; sourceTree = "<group>"; };
+ F96D436708F272B6004A47F5 /* fCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fCmd.test; sourceTree = "<group>"; };
+ F96D436808F272B6004A47F5 /* fileName.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fileName.test; sourceTree = "<group>"; };
+ F96D436908F272B6004A47F5 /* fileSystem.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fileSystem.test; sourceTree = "<group>"; };
+ F96D436A08F272B6004A47F5 /* for-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "for-old.test"; sourceTree = "<group>"; };
+ F96D436B08F272B6004A47F5 /* for.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = for.test; sourceTree = "<group>"; };
+ F96D436C08F272B6004A47F5 /* foreach.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = foreach.test; sourceTree = "<group>"; };
+ F96D436D08F272B6004A47F5 /* format.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = format.test; sourceTree = "<group>"; };
+ F96D436E08F272B6004A47F5 /* get.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = get.test; sourceTree = "<group>"; };
+ F96D436F08F272B6004A47F5 /* history.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = history.test; sourceTree = "<group>"; };
+ F96D437008F272B6004A47F5 /* http.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = http.test; sourceTree = "<group>"; };
+ F96D437108F272B6004A47F5 /* httpd */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = httpd; sourceTree = "<group>"; };
+ F96D437208F272B6004A47F5 /* httpold.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = httpold.test; sourceTree = "<group>"; };
+ F96D437308F272B6004A47F5 /* if-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "if-old.test"; sourceTree = "<group>"; };
+ F96D437408F272B6004A47F5 /* if.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = if.test; sourceTree = "<group>"; };
+ F96D437508F272B6004A47F5 /* incr-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "incr-old.test"; sourceTree = "<group>"; };
+ F96D437608F272B6004A47F5 /* incr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = incr.test; sourceTree = "<group>"; };
+ F96D437708F272B6004A47F5 /* indexObj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = indexObj.test; sourceTree = "<group>"; };
+ F96D437808F272B6004A47F5 /* info.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = info.test; sourceTree = "<group>"; };
+ F96D437908F272B6004A47F5 /* init.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = init.test; sourceTree = "<group>"; };
+ F96D437A08F272B6004A47F5 /* interp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = interp.test; sourceTree = "<group>"; };
+ F96D437B08F272B6004A47F5 /* io.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = io.test; sourceTree = "<group>"; };
+ F96D437C08F272B6004A47F5 /* ioCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = ioCmd.test; sourceTree = "<group>"; };
+ F96D437D08F272B6004A47F5 /* iogt.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = iogt.test; sourceTree = "<group>"; };
+ F96D437F08F272B6004A47F5 /* join.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = join.test; sourceTree = "<group>"; };
+ F96D438008F272B6004A47F5 /* lindex.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lindex.test; sourceTree = "<group>"; };
+ F96D438108F272B6004A47F5 /* link.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = link.test; sourceTree = "<group>"; };
+ F96D438208F272B6004A47F5 /* linsert.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = linsert.test; sourceTree = "<group>"; };
+ F96D438308F272B6004A47F5 /* list.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = list.test; sourceTree = "<group>"; };
+ F96D438408F272B6004A47F5 /* listObj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = listObj.test; sourceTree = "<group>"; };
+ F96D438508F272B6004A47F5 /* llength.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = llength.test; sourceTree = "<group>"; };
+ F96D438608F272B6004A47F5 /* load.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = load.test; sourceTree = "<group>"; };
+ F96D438708F272B6004A47F5 /* lrange.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lrange.test; sourceTree = "<group>"; };
+ F96D438808F272B6004A47F5 /* lrepeat.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lrepeat.test; sourceTree = "<group>"; };
+ F96D438908F272B6004A47F5 /* lreplace.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lreplace.test; sourceTree = "<group>"; };
+ F96D438A08F272B6004A47F5 /* lsearch.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lsearch.test; sourceTree = "<group>"; };
+ F96D438B08F272B6004A47F5 /* lset.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lset.test; sourceTree = "<group>"; };
+ F96D438C08F272B6004A47F5 /* lsetComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lsetComp.test; sourceTree = "<group>"; };
+ F96D438D08F272B6004A47F5 /* macOSXFCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = macOSXFCmd.test; sourceTree = "<group>"; };
+ F96D438E08F272B6004A47F5 /* main.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = main.test; sourceTree = "<group>"; };
+ F96D438F08F272B6004A47F5 /* misc.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = misc.test; sourceTree = "<group>"; };
+ F96D439008F272B6004A47F5 /* msgcat.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = msgcat.test; sourceTree = "<group>"; };
+ F96D439108F272B6004A47F5 /* namespace-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "namespace-old.test"; sourceTree = "<group>"; };
+ F96D439208F272B7004A47F5 /* namespace.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = namespace.test; sourceTree = "<group>"; };
+ F96D439308F272B7004A47F5 /* notify.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = notify.test; sourceTree = "<group>"; };
+ F96D439408F272B7004A47F5 /* obj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = obj.test; sourceTree = "<group>"; };
+ F96D439508F272B7004A47F5 /* opt.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = opt.test; sourceTree = "<group>"; };
+ F96D439608F272B7004A47F5 /* package.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = package.test; sourceTree = "<group>"; };
+ F96D439708F272B7004A47F5 /* parse.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parse.test; sourceTree = "<group>"; };
+ F96D439808F272B7004A47F5 /* parseExpr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parseExpr.test; sourceTree = "<group>"; };
+ F96D439908F272B7004A47F5 /* parseOld.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parseOld.test; sourceTree = "<group>"; };
+ F96D439A08F272B7004A47F5 /* pid.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pid.test; sourceTree = "<group>"; };
+ F96D439B08F272B7004A47F5 /* pkg.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkg.test; sourceTree = "<group>"; };
+ F96D439C08F272B7004A47F5 /* pkgMkIndex.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgMkIndex.test; sourceTree = "<group>"; };
+ F96D439D08F272B7004A47F5 /* platform.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = platform.test; sourceTree = "<group>"; };
+ F96D439E08F272B7004A47F5 /* proc-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "proc-old.test"; sourceTree = "<group>"; };
+ F96D439F08F272B7004A47F5 /* proc.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = proc.test; sourceTree = "<group>"; };
+ F96D43A008F272B7004A47F5 /* pwd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pwd.test; sourceTree = "<group>"; };
+ F96D43A108F272B7004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F96D43A208F272B7004A47F5 /* reg.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = reg.test; sourceTree = "<group>"; };
+ F96D43A308F272B7004A47F5 /* regexp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = regexp.test; sourceTree = "<group>"; };
+ F96D43A408F272B7004A47F5 /* regexpComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = regexpComp.test; sourceTree = "<group>"; };
+ F96D43A508F272B7004A47F5 /* registry.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = registry.test; sourceTree = "<group>"; };
+ F96D43A608F272B7004A47F5 /* remote.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = remote.tcl; sourceTree = "<group>"; };
+ F96D43A708F272B7004A47F5 /* rename.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = rename.test; sourceTree = "<group>"; };
+ F96D43A808F272B7004A47F5 /* result.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = result.test; sourceTree = "<group>"; };
+ F96D43A908F272B7004A47F5 /* safe.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = safe.test; sourceTree = "<group>"; };
+ F96D43AA08F272B7004A47F5 /* scan.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = scan.test; sourceTree = "<group>"; };
+ F96D43AB08F272B7004A47F5 /* security.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = security.test; sourceTree = "<group>"; };
+ F96D43AC08F272B7004A47F5 /* set-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "set-old.test"; sourceTree = "<group>"; };
+ F96D43AD08F272B7004A47F5 /* set.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = set.test; sourceTree = "<group>"; };
+ F96D43AE08F272B7004A47F5 /* socket.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = socket.test; sourceTree = "<group>"; };
+ F96D43AF08F272B7004A47F5 /* source.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = source.test; sourceTree = "<group>"; };
+ F96D43B008F272B7004A47F5 /* split.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = split.test; sourceTree = "<group>"; };
+ F96D43B108F272B7004A47F5 /* stack.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = stack.test; sourceTree = "<group>"; };
+ F96D43B208F272B7004A47F5 /* string.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = string.test; sourceTree = "<group>"; };
+ F96D43B308F272B7004A47F5 /* stringComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = stringComp.test; sourceTree = "<group>"; };
+ F96D43B408F272B7004A47F5 /* stringObj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = stringObj.test; sourceTree = "<group>"; };
+ F96D43B508F272B7004A47F5 /* subst.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = subst.test; sourceTree = "<group>"; };
+ F96D43B608F272B7004A47F5 /* switch.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = switch.test; sourceTree = "<group>"; };
+ F96D43B708F272B7004A47F5 /* tcltest.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tcltest.test; sourceTree = "<group>"; };
+ F96D43B808F272B7004A47F5 /* thread.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = thread.test; sourceTree = "<group>"; };
+ F96D43B908F272B7004A47F5 /* timer.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = timer.test; sourceTree = "<group>"; };
+ F96D43BA08F272B7004A47F5 /* tm.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tm.test; sourceTree = "<group>"; };
+ F96D43BB08F272B7004A47F5 /* trace.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = trace.test; sourceTree = "<group>"; };
+ F96D43BC08F272B7004A47F5 /* unixFCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixFCmd.test; sourceTree = "<group>"; };
+ F96D43BD08F272B7004A47F5 /* unixFile.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixFile.test; sourceTree = "<group>"; };
+ F96D43BE08F272B7004A47F5 /* unixInit.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixInit.test; sourceTree = "<group>"; };
+ F96D43BF08F272B7004A47F5 /* unixNotfy.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixNotfy.test; sourceTree = "<group>"; };
+ F96D43C008F272B7004A47F5 /* unknown.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unknown.test; sourceTree = "<group>"; };
+ F96D43C108F272B7004A47F5 /* unload.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unload.test; sourceTree = "<group>"; };
+ F96D43C208F272B7004A47F5 /* uplevel.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uplevel.test; sourceTree = "<group>"; };
+ F96D43C308F272B7004A47F5 /* upvar.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = upvar.test; sourceTree = "<group>"; };
+ F96D43C408F272B7004A47F5 /* utf.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = utf.test; sourceTree = "<group>"; };
+ F96D43C508F272B7004A47F5 /* util.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = util.test; sourceTree = "<group>"; };
+ F96D43C608F272B7004A47F5 /* var.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = var.test; sourceTree = "<group>"; };
+ F96D43C708F272B7004A47F5 /* while-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "while-old.test"; sourceTree = "<group>"; };
+ F96D43C808F272B7004A47F5 /* while.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = while.test; sourceTree = "<group>"; };
+ F96D43C908F272B7004A47F5 /* winConsole.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winConsole.test; sourceTree = "<group>"; };
+ F96D43CA08F272B7004A47F5 /* winDde.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winDde.test; sourceTree = "<group>"; };
+ F96D43CB08F272B7004A47F5 /* winFCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winFCmd.test; sourceTree = "<group>"; };
+ F96D43CC08F272B7004A47F5 /* winFile.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winFile.test; sourceTree = "<group>"; };
+ F96D43CD08F272B7004A47F5 /* winNotify.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winNotify.test; sourceTree = "<group>"; };
+ F96D43CE08F272B7004A47F5 /* winPipe.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winPipe.test; sourceTree = "<group>"; };
+ F96D43CF08F272B7004A47F5 /* winTime.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winTime.test; sourceTree = "<group>"; };
+ F96D43D108F272B8004A47F5 /* checkLibraryDoc.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = checkLibraryDoc.tcl; sourceTree = "<group>"; };
+ F96D43D208F272B8004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
+ F96D43D308F272B8004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
+ F96D442208F272B8004A47F5 /* eolFix.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = eolFix.tcl; sourceTree = "<group>"; };
+ F96D442408F272B8004A47F5 /* fix_tommath_h.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fix_tommath_h.tcl; sourceTree = "<group>"; };
+ F96D442508F272B8004A47F5 /* genStubs.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = genStubs.tcl; sourceTree = "<group>"; };
+ F96D442708F272B8004A47F5 /* index.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = index.tcl; sourceTree = "<group>"; };
+ F96D442808F272B8004A47F5 /* installData.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = installData.tcl; sourceTree = "<group>"; };
+ F96D442908F272B8004A47F5 /* loadICU.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = loadICU.tcl; sourceTree = "<group>"; };
+ F96D442A08F272B8004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
+ F96D442B08F272B8004A47F5 /* makeTestCases.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = makeTestCases.tcl; sourceTree = "<group>"; };
+ F96D442C08F272B8004A47F5 /* man2help.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2help.tcl; sourceTree = "<group>"; };
+ F96D442D08F272B8004A47F5 /* man2help2.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2help2.tcl; sourceTree = "<group>"; };
+ F96D442E08F272B8004A47F5 /* man2html.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2html.tcl; sourceTree = "<group>"; };
+ F96D442F08F272B8004A47F5 /* man2html1.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2html1.tcl; sourceTree = "<group>"; };
+ F96D443008F272B8004A47F5 /* man2html2.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2html2.tcl; sourceTree = "<group>"; };
+ F96D443108F272B8004A47F5 /* man2tcl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = man2tcl.c; sourceTree = "<group>"; };
+ F96D443208F272B8004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F96D443308F272B8004A47F5 /* regexpTestLib.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = regexpTestLib.tcl; sourceTree = "<group>"; };
+ F96D443508F272B8004A47F5 /* tcl.hpj.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.hpj.in; sourceTree = "<group>"; };
+ F96D443608F272B8004A47F5 /* tcl.wse.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.wse.in; sourceTree = "<group>"; };
+ F96D443908F272B9004A47F5 /* tcltk-man2html.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "tcltk-man2html.tcl"; sourceTree = "<group>"; };
+ F96D443A08F272B9004A47F5 /* tclZIC.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclZIC.tcl; sourceTree = "<group>"; };
+ F96D443B08F272B9004A47F5 /* uniClass.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uniClass.tcl; sourceTree = "<group>"; };
+ F96D443C08F272B9004A47F5 /* uniParse.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uniParse.tcl; sourceTree = "<group>"; };
+ F96D444008F272B9004A47F5 /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = "<group>"; };
+ F96D444108F272B9004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
+ F96D444208F272B9004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
+ F96D444408F272B9004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
+ F96D444508F272B9004A47F5 /* pkga.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkga.c; sourceTree = "<group>"; };
+ F96D444608F272B9004A47F5 /* pkgb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgb.c; sourceTree = "<group>"; };
+ F96D444708F272B9004A47F5 /* pkgc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgc.c; sourceTree = "<group>"; };
+ F96D444808F272B9004A47F5 /* pkgd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgd.c; sourceTree = "<group>"; };
+ F96D444908F272B9004A47F5 /* pkge.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkge.c; sourceTree = "<group>"; };
+ F96D444B08F272B9004A47F5 /* pkgua.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgua.c; sourceTree = "<group>"; };
+ F96D444C08F272B9004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F96D444D08F272B9004A47F5 /* install-sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "install-sh"; sourceTree = "<group>"; };
+ F96D444E08F272B9004A47F5 /* installManPage */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = installManPage; sourceTree = "<group>"; };
+ F96D444F08F272B9004A47F5 /* ldAix */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = ldAix; sourceTree = "<group>"; };
+ F96D445008F272B9004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
+ F96D445208F272B9004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F96D445308F272B9004A47F5 /* tcl.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tcl.m4; sourceTree = "<group>"; };
+ F96D445408F272B9004A47F5 /* tcl.spec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.spec; sourceTree = "<group>"; };
+ F96D445508F272B9004A47F5 /* tclAppInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAppInit.c; sourceTree = "<group>"; };
+ F96D445608F272B9004A47F5 /* tclConfig.h.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = tclConfig.h.in; sourceTree = "<group>"; };
+ F96D445708F272B9004A47F5 /* tclConfig.sh.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tclConfig.sh.in; sourceTree = "<group>"; };
+ F96D445808F272B9004A47F5 /* tclLoadAix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadAix.c; sourceTree = "<group>"; };
+ F96D445908F272B9004A47F5 /* tclLoadDl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadDl.c; sourceTree = "<group>"; };
+ F96D445B08F272B9004A47F5 /* tclLoadDyld.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadDyld.c; sourceTree = "<group>"; };
+ F96D445C08F272B9004A47F5 /* tclLoadNext.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadNext.c; sourceTree = "<group>"; };
+ F96D445D08F272B9004A47F5 /* tclLoadOSF.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadOSF.c; sourceTree = "<group>"; };
+ F96D445E08F272B9004A47F5 /* tclLoadShl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadShl.c; sourceTree = "<group>"; };
+ F96D445F08F272B9004A47F5 /* tclUnixChan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixChan.c; sourceTree = "<group>"; };
+ F96D446008F272B9004A47F5 /* tclUnixEvent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixEvent.c; sourceTree = "<group>"; };
+ F96D446108F272B9004A47F5 /* tclUnixFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixFCmd.c; sourceTree = "<group>"; };
+ F96D446208F272B9004A47F5 /* tclUnixFile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixFile.c; sourceTree = "<group>"; };
+ F96D446308F272B9004A47F5 /* tclUnixInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixInit.c; sourceTree = "<group>"; };
+ F96D446408F272B9004A47F5 /* tclUnixNotfy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixNotfy.c; sourceTree = "<group>"; };
+ F96D446508F272B9004A47F5 /* tclUnixPipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixPipe.c; sourceTree = "<group>"; };
+ F96D446608F272B9004A47F5 /* tclUnixPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclUnixPort.h; sourceTree = "<group>"; };
+ F96D446708F272B9004A47F5 /* tclUnixSock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixSock.c; sourceTree = "<group>"; };
+ F96D446808F272B9004A47F5 /* tclUnixTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixTest.c; sourceTree = "<group>"; };
+ F96D446908F272B9004A47F5 /* tclUnixThrd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixThrd.c; sourceTree = "<group>"; };
+ F96D446A08F272B9004A47F5 /* tclUnixThrd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclUnixThrd.h; sourceTree = "<group>"; };
+ F96D446B08F272B9004A47F5 /* tclUnixTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixTime.c; sourceTree = "<group>"; };
+ F96D446C08F272B9004A47F5 /* tclXtNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclXtNotify.c; sourceTree = "<group>"; };
+ F96D446D08F272B9004A47F5 /* tclXtTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclXtTest.c; sourceTree = "<group>"; };
+ F96D447008F272BA004A47F5 /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = "<group>"; };
+ F96D447108F272BA004A47F5 /* buildall.vc.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = buildall.vc.bat; sourceTree = "<group>"; };
+ F96D447208F272BA004A47F5 /* cat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cat.c; sourceTree = "<group>"; };
+ F96D447408F272BA004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
+ F96D447508F272BA004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
+ F96D447708F272BA004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
+ F96D447808F272BA004A47F5 /* makefile.vc */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = makefile.vc; sourceTree = "<group>"; };
+ F96D447908F272BA004A47F5 /* nmakehlp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nmakehlp.c; sourceTree = "<group>"; };
+ F96D447A08F272BA004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F96D447C08F272BA004A47F5 /* rules.vc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rules.vc; sourceTree = "<group>"; };
+ F96D447D08F272BA004A47F5 /* stub16.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stub16.c; sourceTree = "<group>"; };
+ F96D447E08F272BA004A47F5 /* tcl.dsp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.dsp; sourceTree = "<group>"; };
+ F96D447F08F272BA004A47F5 /* tcl.dsw */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.dsw; sourceTree = "<group>"; };
+ F96D448008F272BA004A47F5 /* tcl.hpj.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.hpj.in; sourceTree = "<group>"; };
+ F96D448108F272BA004A47F5 /* tcl.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tcl.m4; sourceTree = "<group>"; };
+ F96D448208F272BA004A47F5 /* tcl.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.rc; sourceTree = "<group>"; };
+ F96D448308F272BA004A47F5 /* tclAppInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAppInit.c; sourceTree = "<group>"; };
+ F96D448408F272BA004A47F5 /* tclConfig.sh.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tclConfig.sh.in; sourceTree = "<group>"; };
+ F96D448608F272BA004A47F5 /* tclsh.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tclsh.rc; sourceTree = "<group>"; };
+ F96D448708F272BA004A47F5 /* tclWin32Dll.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWin32Dll.c; sourceTree = "<group>"; };
+ F96D448808F272BA004A47F5 /* tclWinChan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinChan.c; sourceTree = "<group>"; };
+ F96D448908F272BA004A47F5 /* tclWinConsole.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinConsole.c; sourceTree = "<group>"; };
+ F96D448A08F272BA004A47F5 /* tclWinDde.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinDde.c; sourceTree = "<group>"; };
+ F96D448B08F272BA004A47F5 /* tclWinError.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinError.c; sourceTree = "<group>"; };
+ F96D448C08F272BA004A47F5 /* tclWinFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinFCmd.c; sourceTree = "<group>"; };
+ F96D448D08F272BA004A47F5 /* tclWinFile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinFile.c; sourceTree = "<group>"; };
+ F96D448E08F272BA004A47F5 /* tclWinInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinInit.c; sourceTree = "<group>"; };
+ F96D448F08F272BA004A47F5 /* tclWinInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclWinInt.h; sourceTree = "<group>"; };
+ F96D449008F272BA004A47F5 /* tclWinLoad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinLoad.c; sourceTree = "<group>"; };
+ F96D449108F272BA004A47F5 /* tclWinNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinNotify.c; sourceTree = "<group>"; };
+ F96D449208F272BA004A47F5 /* tclWinPipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinPipe.c; sourceTree = "<group>"; };
+ F96D449308F272BA004A47F5 /* tclWinPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclWinPort.h; sourceTree = "<group>"; };
+ F96D449408F272BA004A47F5 /* tclWinReg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinReg.c; sourceTree = "<group>"; };
+ F96D449508F272BA004A47F5 /* tclWinSerial.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinSerial.c; sourceTree = "<group>"; };
+ F96D449608F272BA004A47F5 /* tclWinSock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinSock.c; sourceTree = "<group>"; };
+ F96D449708F272BA004A47F5 /* tclWinTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinTest.c; sourceTree = "<group>"; };
+ F96D449808F272BA004A47F5 /* tclWinThrd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinThrd.c; sourceTree = "<group>"; };
+ F96D449908F272BA004A47F5 /* tclWinThrd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclWinThrd.h; sourceTree = "<group>"; };
+ F96D449A08F272BA004A47F5 /* tclWinTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinTime.c; sourceTree = "<group>"; };
+ F973E5960EE99384001A648E /* vistaTheme.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = vistaTheme.tcl; sourceTree = "<group>"; };
+ F974D56C0FBE7D6300BF728B /* http11.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = http11.test; sourceTree = "<group>"; };
+ F974D56D0FBE7D6300BF728B /* httpd11.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = httpd11.tcl; sourceTree = "<group>"; };
+ F974D5720FBE7DC600BF728B /* coroutine.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = coroutine.n; sourceTree = "<group>"; };
+ F974D5760FBE7E1900BF728B /* tailcall.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tailcall.n; sourceTree = "<group>"; };
+ F974D5770FBE7E6100BF728B /* coroutine.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = coroutine.test; sourceTree = "<group>"; };
+ F974D5780FBE7E6100BF728B /* tailcall.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tailcall.test; sourceTree = "<group>"; };
+ F974D5790FBE7E9C00BF728B /* tcl.pc.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.pc.in; sourceTree = "<group>"; };
+ F974D57B0FBE7EC000BF728B /* tk.pc.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tk.pc.in; sourceTree = "<group>"; };
+ F974D57C0FBE7EFF00BF728B /* iconlist.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = iconlist.tcl; sourceTree = "<group>"; };
+ F974D57D0FBE7EFF00BF728B /* icons.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = icons.tcl; sourceTree = "<group>"; };
+ F97590AE1039A96200558A9A /* Wish.sdef */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.sdef; path = Wish.sdef; sourceTree = "<group>"; };
+ F976F6A70C325FB6005066D9 /* tkMacOSXPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMacOSXPrivate.h; sourceTree = "<group>"; };
+ F97AE7F10B65C1E900310EA2 /* Tk-Common.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tk-Common.xcconfig"; sourceTree = "<group>"; };
+ F97AE82B0B65C69B00310EA2 /* Tk-Release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tk-Release.xcconfig"; sourceTree = "<group>"; };
+ F97AE8330B65C87F00310EA2 /* Tk-Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tk-Debug.xcconfig"; sourceTree = "<group>"; };
+ F98383650F0FA43900171CA6 /* checkbutton.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = checkbutton.test; sourceTree = "<group>"; };
+ F98383680F0FA44700171CA6 /* radiobutton.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = radiobutton.test; sourceTree = "<group>"; };
+ F9903CAF094FAADA004613E9 /* tclTomMath.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclTomMath.decls; sourceTree = "<group>"; };
+ F9903CB0094FAADA004613E9 /* tclTomMathDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclTomMathDecls.h; sourceTree = "<group>"; };
+ F99388380EE0114B0065FE6B /* fontchooser.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fontchooser.tcl; sourceTree = "<group>"; };
+ F99388950EE02D980065FE6B /* fontchooser.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fontchooser.test; sourceTree = "<group>"; };
+ F99D61180EF5573A00BBFE01 /* TclZlib.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TclZlib.3; sourceTree = "<group>"; };
+ F9A3082D08F2D4AB00BAE1AB /* Tk.framework */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.framework; path = Tk.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ F9A3084B08F2D4CE00BAE1AB /* Wish.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Wish.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ F9A3084E08F2D4F400BAE1AB /* Tcl.framework */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.framework; path = Tcl.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ F9A493240CEBF38300B78AE2 /* chanio.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = chanio.test; sourceTree = "<group>"; };
+ F9C888C20EEF6571003F63AD /* fontchooser.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fontchooser.n; sourceTree = "<group>"; };
+ F9C9CBFF0E84059800E00935 /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = /System/Library/Frameworks/ApplicationServices.framework; sourceTree = "<absolute>"; };
+ F9D1360A0CDC252C00DBE0B5 /* mclist.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = mclist.tcl; sourceTree = "<group>"; };
+ F9DD99BC0F07DF850018B2E4 /* tkImgPNG.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkImgPNG.c; sourceTree = "<group>"; };
+ F9DD99BF0F07DFCD0018B2E4 /* imgPNG.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = imgPNG.test; sourceTree = "<group>"; };
+ F9ECB1120B26521500A28025 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F9ECB1130B26521500A28025 /* platform.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = platform.tcl; sourceTree = "<group>"; };
+ F9ECB1140B26521500A28025 /* shell.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = shell.tcl; sourceTree = "<group>"; };
+ F9ECB1CA0B2652D300A28025 /* apply.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = apply.test; sourceTree = "<group>"; };
+ F9ECB1CB0B26534C00A28025 /* mathop.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = mathop.test; sourceTree = "<group>"; };
+ F9ECB1E10B26543C00A28025 /* platform_shell.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = platform_shell.n; sourceTree = "<group>"; };
+ F9ECB1E20B26543C00A28025 /* platform.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = platform.n; sourceTree = "<group>"; };
+ F9F4415D0C8BAE6F00BCCD67 /* tclDTrace.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; path = tclDTrace.d; sourceTree = "<group>"; };
+ F9F4EFDC0CC7B3CA00378A27 /* ttkpane.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; languageSpecificationIdentifier = shell; path = ttkpane.tcl; sourceTree = "<group>"; };
+ F9F4EFDD0CC7B3CB00378A27 /* ttkmenu.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; languageSpecificationIdentifier = shell; path = ttkmenu.tcl; sourceTree = "<group>"; };
+ F9FC77B70AB29E9100B7077D /* tclUnixCompat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixCompat.c; sourceTree = "<group>"; };
+ F9FD31F40CC1AD070073837D /* tktest-X11 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "tktest-X11"; sourceTree = BUILT_PRODUCTS_DIR; };
+ F9FD32140CC1AF170073837D /* libX11.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libX11.dylib; path = /usr/X11R6/lib/libX11.dylib; sourceTree = "<absolute>"; };
+ F9FD32150CC1AF170073837D /* libXext.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libXext.dylib; path = /usr/X11R6/lib/libXext.dylib; sourceTree = "<absolute>"; };
+ F9FD32160CC1AF170073837D /* libXss.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libXss.dylib; path = /usr/X11R6/lib/libXss.dylib; sourceTree = "<absolute>"; };
+ F9FD34990CC1BB0D0073837D /* libfreetype.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libfreetype.dylib; path = /usr/X11R6/lib/libfreetype.dylib; sourceTree = "<absolute>"; };
+ F9FD349A0CC1BB0D0073837D /* libXft.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libXft.dylib; path = /usr/X11R6/lib/libXft.dylib; sourceTree = "<absolute>"; };
+ F9FD34C30CC1BBD70073837D /* libfontconfig.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libfontconfig.dylib; path = /usr/X11R6/lib/libfontconfig.dylib; sourceTree = "<absolute>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 8DD76FAD0486AB0100D96B5E /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F966C07508F2820D005CB29B /* CoreFoundation.framework in Frameworks */,
+ F96437E70EF0D652003F468E /* libz.dylib in Frameworks */,
+ F966C07708F2821B005CB29B /* Carbon.framework in Frameworks */,
+ F966C07908F28233005CB29B /* IOKit.framework in Frameworks */,
+ F94523A20E6FC2AC00C1D987 /* Cocoa.framework in Frameworks */,
+ F9C9CC000E84059800E00935 /* ApplicationServices.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F9FD31E30CC1AD070073837D /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F9FD31E40CC1AD070073837D /* CoreFoundation.framework in Frameworks */,
+ F96437E80EF0D652003F468E /* libz.dylib in Frameworks */,
+ F9FD32170CC1AF170073837D /* libX11.dylib in Frameworks */,
+ F9FD32180CC1AF170073837D /* libXext.dylib in Frameworks */,
+ F9FD32190CC1AF170073837D /* libXss.dylib in Frameworks */,
+ F9FD349C0CC1BB0D0073837D /* libXft.dylib in Frameworks */,
+ F9FD349B0CC1BB0D0073837D /* libfreetype.dylib in Frameworks */,
+ F9FD34C40CC1BBD70073837D /* libfontconfig.dylib in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 08FB7794FE84155DC02AAC07 /* Tk */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3DF708F271BE004A47F5 /* Tk Sources */,
+ F96D3DF608F27169004A47F5 /* Tcl Sources */,
+ F966C06F08F281DC005CB29B /* Frameworks */,
+ 1AB674ADFE9D54B511CA2CBB /* Products */,
+ );
+ comments = "Copyright (c) 2004-2009 Daniel A. Steffen <das@users.sourceforge.net>\nCopyright 2008-2009, Apple Inc.\n\nSee the file \"license.terms\" for information on usage and redistribution of\nthis file, and for a DISCLAIMER OF ALL WARRANTIES.\n";
+ name = Tk;
+ path = .;
+ sourceTree = SOURCE_ROOT;
+ };
+ 1AB674ADFE9D54B511CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ F9A3084B08F2D4CE00BAE1AB /* Wish.app */,
+ F9A3082D08F2D4AB00BAE1AB /* Tk.framework */,
+ F9A3084E08F2D4F400BAE1AB /* Tcl.framework */,
+ 8DD76FB20486AB0100D96B5E /* tktest */,
+ F9FD31F40CC1AD070073837D /* tktest-X11 */,
+ );
+ includeInIndex = 0;
+ name = Products;
+ sourceTree = "<group>";
+ };
+ F9183E690EFC81560030B814 /* pkgs */ = {
+ isa = PBXGroup;
+ children = (
+ F9183E6A0EFC81560030B814 /* README */,
+ F946FB8B0FBE3AED00CD6495 /* itcl */,
+ F9183E8F0EFC817B0030B814 /* tdbc */,
+ );
+ path = pkgs;
+ sourceTree = "<group>";
+ };
+ F966BA0308F27A37005CB29B /* bitmaps */ = {
+ isa = PBXGroup;
+ children = (
+ F966BA0408F27A37005CB29B /* error.xbm */,
+ F966BA0508F27A37005CB29B /* gray12.xbm */,
+ F966BA0608F27A37005CB29B /* gray25.xbm */,
+ F966BA0708F27A37005CB29B /* gray50.xbm */,
+ F966BA0808F27A37005CB29B /* gray75.xbm */,
+ F966BA0908F27A37005CB29B /* hourglass.xbm */,
+ F966BA0A08F27A37005CB29B /* info.xbm */,
+ F966BA0B08F27A37005CB29B /* questhead.xbm */,
+ F966BA0C08F27A37005CB29B /* question.xbm */,
+ F966BA0D08F27A37005CB29B /* warning.xbm */,
+ );
+ path = bitmaps;
+ sourceTree = "<group>";
+ };
+ F966BA1008F27A37005CB29B /* doc */ = {
+ isa = PBXGroup;
+ children = (
+ F966BA1108F27A37005CB29B /* 3DBorder.3 */,
+ F966BA1208F27A37005CB29B /* AddOption.3 */,
+ F966BA1308F27A37005CB29B /* bell.n */,
+ F966BA1408F27A37005CB29B /* bind.n */,
+ F966BA1508F27A37005CB29B /* BindTable.3 */,
+ F966BA1608F27A37005CB29B /* bindtags.n */,
+ F966BA1708F27A37005CB29B /* bitmap.n */,
+ F966BA1808F27A37005CB29B /* button.n */,
+ F966BA1908F27A37005CB29B /* canvas.n */,
+ F966BA1A08F27A37005CB29B /* CanvPsY.3 */,
+ F966BA1B08F27A37005CB29B /* CanvTkwin.3 */,
+ F966BA1C08F27A37005CB29B /* CanvTxtInfo.3 */,
+ F966BA1D08F27A37005CB29B /* checkbutton.n */,
+ F966BA1E08F27A37005CB29B /* chooseColor.n */,
+ F966BA1F08F27A37005CB29B /* chooseDirectory.n */,
+ F966BA2008F27A37005CB29B /* Clipboard.3 */,
+ F966BA2108F27A37005CB29B /* clipboard.n */,
+ F966BA2208F27A37005CB29B /* ClrSelect.3 */,
+ F966BA2308F27A37005CB29B /* colors.n */,
+ F966BA2408F27A37005CB29B /* ConfigWidg.3 */,
+ F966BA2508F27A37005CB29B /* ConfigWind.3 */,
+ F966BA2608F27A37005CB29B /* console.n */,
+ F966BA2708F27A37005CB29B /* CoordToWin.3 */,
+ F966BA2808F27A37005CB29B /* CrtCmHdlr.3 */,
+ F966BA2908F27A37005CB29B /* CrtErrHdlr.3 */,
+ F966BA2A08F27A37005CB29B /* CrtGenHdlr.3 */,
+ F966BA2B08F27A37005CB29B /* CrtImgType.3 */,
+ F966BA2C08F27A37005CB29B /* CrtItemType.3 */,
+ F966BA2D08F27A37005CB29B /* CrtPhImgFmt.3 */,
+ F966BA2E08F27A37005CB29B /* CrtSelHdlr.3 */,
+ F966BA2F08F27A37005CB29B /* CrtWindow.3 */,
+ F966BA3008F27A37005CB29B /* cursors.n */,
+ F966BA3108F27A37005CB29B /* DeleteImg.3 */,
+ F966BA3208F27A37005CB29B /* destroy.n */,
+ F966BA3308F27A37005CB29B /* dialog.n */,
+ F966BA3408F27A37005CB29B /* DrawFocHlt.3 */,
+ F966BA3508F27A37005CB29B /* entry.n */,
+ F966BA3608F27A37005CB29B /* event.n */,
+ F966BA3708F27A37005CB29B /* EventHndlr.3 */,
+ F966BA3808F27A37005CB29B /* FindPhoto.3 */,
+ F966BA3908F27A37005CB29B /* focus.n */,
+ F966BA3A08F27A37005CB29B /* focusNext.n */,
+ F966BA3B08F27A37005CB29B /* font.n */,
+ F9C888C20EEF6571003F63AD /* fontchooser.n */,
+ F966BA3C08F27A37005CB29B /* FontId.3 */,
+ F966BA3D08F27A37005CB29B /* frame.n */,
+ F966BA3E08F27A37005CB29B /* FreeXId.3 */,
+ F966BA3F08F27A37005CB29B /* GeomReq.3 */,
+ F966BA4008F27A37005CB29B /* GetAnchor.3 */,
+ F966BA4108F27A37005CB29B /* GetBitmap.3 */,
+ F966BA4208F27A37005CB29B /* GetCapStyl.3 */,
+ F966BA4308F27A37005CB29B /* GetClrmap.3 */,
+ F966BA4408F27A37005CB29B /* GetColor.3 */,
+ F966BA4508F27A37005CB29B /* GetCursor.3 */,
+ F966BA4608F27A37005CB29B /* GetDash.3 */,
+ F966BA4708F27A37005CB29B /* GetFont.3 */,
+ F966BA4808F27A37005CB29B /* GetGC.3 */,
+ F966BA4908F27A37005CB29B /* GetHINSTANCE.3 */,
+ F966BA4A08F27A37005CB29B /* GetHWND.3 */,
+ F966BA4B08F27A37005CB29B /* GetImage.3 */,
+ F966BA4C08F27A37005CB29B /* GetJoinStl.3 */,
+ F966BA4D08F27A37005CB29B /* GetJustify.3 */,
+ F966BA4E08F27A37005CB29B /* getOpenFile.n */,
+ F966BA4F08F27A37005CB29B /* GetOption.3 */,
+ F966BA5008F27A38005CB29B /* GetPixels.3 */,
+ F966BA5108F27A38005CB29B /* GetPixmap.3 */,
+ F966BA5208F27A38005CB29B /* GetRelief.3 */,
+ F966BA5308F27A38005CB29B /* GetRootCrd.3 */,
+ F966BA5408F27A38005CB29B /* GetScroll.3 */,
+ F966BA5508F27A38005CB29B /* GetSelect.3 */,
+ F966BA5608F27A38005CB29B /* GetUid.3 */,
+ F966BA5708F27A38005CB29B /* GetVisual.3 */,
+ F966BA5808F27A38005CB29B /* GetVRoot.3 */,
+ F966BA5908F27A38005CB29B /* Grab.3 */,
+ F966BA5A08F27A38005CB29B /* grab.n */,
+ F966BA5B08F27A38005CB29B /* grid.n */,
+ F966BA5C08F27A38005CB29B /* HandleEvent.3 */,
+ F966BA5D08F27A38005CB29B /* HWNDToWindow.3 */,
+ F966BA5E08F27A38005CB29B /* IdToWindow.3 */,
+ F966BA5F08F27A38005CB29B /* image.n */,
+ F966BA6008F27A38005CB29B /* ImgChanged.3 */,
+ F966BA6108F27A38005CB29B /* Inactive.3 */,
+ F966BA6208F27A38005CB29B /* InternAtom.3 */,
+ F966BA6308F27A38005CB29B /* keysyms.n */,
+ F966BA6408F27A38005CB29B /* label.n */,
+ F966BA6508F27A38005CB29B /* labelframe.n */,
+ F966BA6608F27A38005CB29B /* listbox.n */,
+ F966BA6708F27A38005CB29B /* loadTk.n */,
+ F966BA6808F27A38005CB29B /* lower.n */,
+ F966BA6908F27A38005CB29B /* MainLoop.3 */,
+ F966BA6A08F27A38005CB29B /* MaintGeom.3 */,
+ F966BA6B08F27A38005CB29B /* MainWin.3 */,
+ F966BA6D08F27A38005CB29B /* ManageGeom.3 */,
+ F966BA6E08F27A38005CB29B /* MapWindow.3 */,
+ F966BA6F08F27A38005CB29B /* MeasureChar.3 */,
+ F966BA7008F27A38005CB29B /* menu.n */,
+ F966BA7108F27A38005CB29B /* menubar.n */,
+ F966BA7208F27A38005CB29B /* menubutton.n */,
+ F966BA7308F27A38005CB29B /* message.n */,
+ F966BA7408F27A38005CB29B /* messageBox.n */,
+ F966BA7508F27A38005CB29B /* MoveToplev.3 */,
+ F966BA7608F27A38005CB29B /* Name.3 */,
+ F966BA7708F27A38005CB29B /* NameOfImg.3 */,
+ F966BA7808F27A38005CB29B /* option.n */,
+ F966BA7908F27A38005CB29B /* optionMenu.n */,
+ F966BA7A08F27A38005CB29B /* options.n */,
+ F966BA7B08F27A38005CB29B /* OwnSelect.3 */,
+ F966BA7C08F27A38005CB29B /* pack-old.n */,
+ F966BA7D08F27A38005CB29B /* pack.n */,
+ F966BA7E08F27A38005CB29B /* palette.n */,
+ F966BA7F08F27A38005CB29B /* panedwindow.n */,
+ F966BA8008F27A38005CB29B /* ParseArgv.3 */,
+ F966BA8108F27A38005CB29B /* photo.n */,
+ F966BA8208F27A38005CB29B /* place.n */,
+ F966BA8308F27A38005CB29B /* popup.n */,
+ F966BA8408F27A38005CB29B /* QWinEvent.3 */,
+ F966BA8508F27A38005CB29B /* radiobutton.n */,
+ F966BA8608F27A38005CB29B /* raise.n */,
+ F966BA8708F27A38005CB29B /* Restack.3 */,
+ F966BA8808F27A38005CB29B /* RestrictEv.3 */,
+ F966BA8908F27A38005CB29B /* scale.n */,
+ F966BA8A08F27A38005CB29B /* scrollbar.n */,
+ F966BA8B08F27A38005CB29B /* selection.n */,
+ F966BA8C08F27A38005CB29B /* send.n */,
+ F966BA8D08F27A38005CB29B /* SetAppName.3 */,
+ F966BA8E08F27A38005CB29B /* SetCaret.3 */,
+ F966BA8F08F27A38005CB29B /* SetClass.3 */,
+ F966BA9008F27A38005CB29B /* SetClassProcs.3 */,
+ F966BA9108F27A38005CB29B /* SetGrid.3 */,
+ F966BA9208F27A38005CB29B /* SetOptions.3 */,
+ F966BA9308F27A38005CB29B /* SetVisual.3 */,
+ F966BA9408F27A38005CB29B /* spinbox.n */,
+ F966BA9508F27A38005CB29B /* StrictMotif.3 */,
+ F966BA9608F27A38005CB29B /* text.n */,
+ F966BA9708F27A38005CB29B /* TextLayout.3 */,
+ F966BA9808F27A38005CB29B /* tk.n */,
+ F966BA9A08F27A38005CB29B /* Tk_Init.3 */,
+ F966BA9B08F27A38005CB29B /* Tk_Main.3 */,
+ F966BA9C08F27A38005CB29B /* tkerror.n */,
+ F966BA9D08F27A38005CB29B /* TkInitStubs.3 */,
+ F966BA9E08F27A38005CB29B /* tkvars.n */,
+ F966BA9F08F27A38005CB29B /* tkwait.n */,
+ F966BAA008F27A38005CB29B /* toplevel.n */,
+ F968886B0AF788F6000797B5 /* ttk_button.n */,
+ F968886C0AF788F6000797B5 /* ttk_checkbutton.n */,
+ F968886D0AF788F6000797B5 /* ttk_combobox.n */,
+ F968886F0AF788F6000797B5 /* ttk_entry.n */,
+ F96888700AF788F6000797B5 /* ttk_frame.n */,
+ F96888710AF788F6000797B5 /* ttk_Geometry.3 */,
+ F96888720AF788F6000797B5 /* ttk_image.n */,
+ F96888730AF788F6000797B5 /* ttk_intro.n */,
+ F96888740AF788F6000797B5 /* ttk_label.n */,
+ F96888750AF788F6000797B5 /* ttk_labelframe.n */,
+ F96888760AF788F6000797B5 /* ttk_menubutton.n */,
+ F96888770AF788F6000797B5 /* ttk_notebook.n */,
+ F96888780AF788F6000797B5 /* ttk_panedwindow.n */,
+ F96888790AF788F6000797B5 /* ttk_progressbar.n */,
+ F968887A0AF788F6000797B5 /* ttk_radiobutton.n */,
+ F968887B0AF788F6000797B5 /* ttk_scrollbar.n */,
+ F968887C0AF788F6000797B5 /* ttk_separator.n */,
+ F968887D0AF788F6000797B5 /* ttk_sizegrip.n */,
+ F968887E0AF788F6000797B5 /* ttk_style.n */,
+ F968887F0AF788F6000797B5 /* ttk_Theme.3 */,
+ F96888800AF788F6000797B5 /* ttk_treeview.n */,
+ F96888810AF788F6000797B5 /* ttk_widget.n */,
+ F966BAA108F27A38005CB29B /* WindowId.3 */,
+ F966BAA208F27A38005CB29B /* winfo.n */,
+ F966BAA308F27A38005CB29B /* wish.1 */,
+ F966BAA408F27A38005CB29B /* wm.n */,
+ );
+ path = doc;
+ sourceTree = "<group>";
+ };
+ F966BAA508F27A38005CB29B /* generic */ = {
+ isa = PBXGroup;
+ children = (
+ F966BAA608F27A38005CB29B /* default.h */,
+ F966BAA708F27A38005CB29B /* ks_names.h */,
+ F966BAA908F27A39005CB29B /* README */,
+ F966BAAA08F27A39005CB29B /* tk.decls */,
+ F966BAAB08F27A39005CB29B /* tk.h */,
+ F966BAAC08F27A39005CB29B /* tk3d.c */,
+ F966BAAD08F27A39005CB29B /* tk3d.h */,
+ F966BAAE08F27A39005CB29B /* tkArgv.c */,
+ F966BAAF08F27A39005CB29B /* tkAtom.c */,
+ F966BAB008F27A39005CB29B /* tkBind.c */,
+ F966BAB108F27A39005CB29B /* tkBitmap.c */,
+ F9152B080EAF8A5000CD5C7B /* tkBusy.c */,
+ F966BAB208F27A39005CB29B /* tkButton.c */,
+ F966BAB308F27A39005CB29B /* tkButton.h */,
+ F966BAB408F27A39005CB29B /* tkCanvArc.c */,
+ F966BAB508F27A39005CB29B /* tkCanvas.c */,
+ F966BAB608F27A39005CB29B /* tkCanvas.h */,
+ F966BAB708F27A39005CB29B /* tkCanvBmap.c */,
+ F966BAB808F27A39005CB29B /* tkCanvImg.c */,
+ F966BAB908F27A39005CB29B /* tkCanvLine.c */,
+ F966BABA08F27A39005CB29B /* tkCanvPoly.c */,
+ F966BABB08F27A39005CB29B /* tkCanvPs.c */,
+ F966BABD08F27A39005CB29B /* tkCanvText.c */,
+ F966BABE08F27A39005CB29B /* tkCanvUtil.c */,
+ F966BABF08F27A39005CB29B /* tkCanvWind.c */,
+ F966BAC008F27A39005CB29B /* tkClipboard.c */,
+ F966BAC108F27A39005CB29B /* tkCmds.c */,
+ F966BAC208F27A39005CB29B /* tkColor.c */,
+ F966BAC308F27A39005CB29B /* tkColor.h */,
+ F966BAC408F27A39005CB29B /* tkConfig.c */,
+ F966BAC508F27A39005CB29B /* tkConsole.c */,
+ F966BAC608F27A39005CB29B /* tkCursor.c */,
+ F966BAC708F27A39005CB29B /* tkDecls.h */,
+ F966BAC808F27A39005CB29B /* tkEntry.c */,
+ F966BAC908F27A39005CB29B /* tkEntry.h */,
+ F966BACA08F27A39005CB29B /* tkError.c */,
+ F966BACB08F27A39005CB29B /* tkEvent.c */,
+ F966BACC08F27A39005CB29B /* tkFileFilter.c */,
+ F966BACD08F27A39005CB29B /* tkFileFilter.h */,
+ F966BACE08F27A39005CB29B /* tkFocus.c */,
+ F966BACF08F27A39005CB29B /* tkFont.c */,
+ F966BAD008F27A39005CB29B /* tkFont.h */,
+ F966BAD108F27A39005CB29B /* tkFrame.c */,
+ F966BAD208F27A39005CB29B /* tkGC.c */,
+ F966BAD308F27A39005CB29B /* tkGeometry.c */,
+ F966BAD408F27A39005CB29B /* tkGet.c */,
+ F966BAD508F27A39005CB29B /* tkGrab.c */,
+ F966BAD608F27A39005CB29B /* tkGrid.c */,
+ F966BAD708F27A39005CB29B /* tkImage.c */,
+ F966BAD808F27A39005CB29B /* tkImgBmap.c */,
+ F966BAD908F27A39005CB29B /* tkImgGIF.c */,
+ F92EE8BE0E62F846001A6E80 /* tkImgPhInstance.c */,
+ F966BADA08F27A39005CB29B /* tkImgPhoto.c */,
+ F9DD99BC0F07DF850018B2E4 /* tkImgPNG.c */,
+ F966BADB08F27A39005CB29B /* tkImgPPM.c */,
+ F966BADC08F27A39005CB29B /* tkImgUtil.c */,
+ F966BADE08F27A39005CB29B /* tkInt.decls */,
+ F966BADF08F27A39005CB29B /* tkInt.h */,
+ F966BAE108F27A39005CB29B /* tkIntDecls.h */,
+ F966BAE208F27A39005CB29B /* tkIntPlatDecls.h */,
+ F966BAE308F27A39005CB29B /* tkIntXlibDecls.h */,
+ F966BAE408F27A39005CB29B /* tkListbox.c */,
+ F966BAE508F27A39005CB29B /* tkMacWinMenu.c */,
+ F966BAE608F27A39005CB29B /* tkMain.c */,
+ F966BAE708F27A39005CB29B /* tkMenu.c */,
+ F966BAE808F27A39005CB29B /* tkMenu.h */,
+ F966BAE908F27A39005CB29B /* tkMenubutton.c */,
+ F966BAEA08F27A39005CB29B /* tkMenubutton.h */,
+ F966BAEB08F27A39005CB29B /* tkMenuDraw.c */,
+ F966BAEC08F27A39005CB29B /* tkMessage.c */,
+ F966BAED08F27A39005CB29B /* tkObj.c */,
+ F966BAEE08F27A39005CB29B /* tkOldConfig.c */,
+ F966BAEF08F27A39005CB29B /* tkOption.c */,
+ F966BAF008F27A39005CB29B /* tkPack.c */,
+ F966BAF108F27A39005CB29B /* tkPanedWindow.c */,
+ F966BAF208F27A39005CB29B /* tkPlace.c */,
+ F966BAF308F27A39005CB29B /* tkPlatDecls.h */,
+ F966BAF408F27A39005CB29B /* tkPointer.c */,
+ F966BAF508F27A39005CB29B /* tkPort.h */,
+ F966BAF608F27A39005CB29B /* tkRectOval.c */,
+ F966BAF708F27A39005CB29B /* tkScale.c */,
+ F966BAF808F27A39005CB29B /* tkScale.h */,
+ F966BAF908F27A39005CB29B /* tkScrollbar.c */,
+ F966BAFA08F27A39005CB29B /* tkScrollbar.h */,
+ F966BAFB08F27A39005CB29B /* tkSelect.c */,
+ F966BAFC08F27A39005CB29B /* tkSelect.h */,
+ F966BAFD08F27A39005CB29B /* tkSquare.c */,
+ F966BAFE08F27A39005CB29B /* tkOldTest.c */,
+ F966BAFF08F27A39005CB29B /* tkStubInit.c */,
+ F966BB0008F27A39005CB29B /* tkStubLib.c */,
+ F966BB0108F27A39005CB29B /* tkStyle.c */,
+ F966BB0208F27A39005CB29B /* tkTest.c */,
+ F966BB0308F27A39005CB29B /* tkText.c */,
+ F966BB0408F27A39005CB29B /* tkText.h */,
+ F966BB0508F27A39005CB29B /* tkTextBTree.c */,
+ F966BB0608F27A39005CB29B /* tkTextDisp.c */,
+ F966BB0808F27A39005CB29B /* tkTextImage.c */,
+ F966BB0908F27A39005CB29B /* tkTextIndex.c */,
+ F966BB0A08F27A39005CB29B /* tkTextMark.c */,
+ F966BB0B08F27A39005CB29B /* tkTextTag.c */,
+ F966BB0C08F27A39005CB29B /* tkTextWind.c */,
+ F966BB0D08F27A39005CB29B /* tkTrig.c */,
+ F966BB0E08F27A39005CB29B /* tkUndo.c */,
+ F966BB0F08F27A39005CB29B /* tkUndo.h */,
+ F966BB1008F27A39005CB29B /* tkUtil.c */,
+ F966BB1108F27A39005CB29B /* tkVisual.c */,
+ F966BB1208F27A39005CB29B /* tkWindow.c */,
+ F96887DF0AF786D5000797B5 /* ttk */,
+ );
+ path = generic;
+ sourceTree = "<group>";
+ };
+ F966BB1308F27A39005CB29B /* library */ = {
+ isa = PBXGroup;
+ children = (
+ F966BB1408F27A39005CB29B /* bgerror.tcl */,
+ F966BB1508F27A39005CB29B /* button.tcl */,
+ F966BB1608F27A39005CB29B /* choosedir.tcl */,
+ F966BB1708F27A39005CB29B /* clrpick.tcl */,
+ F966BB1808F27A39005CB29B /* comdlg.tcl */,
+ F966BB1908F27A39005CB29B /* console.tcl */,
+ F966BB1A08F27A39005CB29B /* demos */,
+ F966BB6208F27A3A005CB29B /* dialog.tcl */,
+ F966BB6308F27A3A005CB29B /* entry.tcl */,
+ F966BB6408F27A3A005CB29B /* focus.tcl */,
+ F99388380EE0114B0065FE6B /* fontchooser.tcl */,
+ F974D57C0FBE7EFF00BF728B /* iconlist.tcl */,
+ F974D57D0FBE7EFF00BF728B /* icons.tcl */,
+ F966BB7308F27A3A005CB29B /* listbox.tcl */,
+ F966BB7408F27A3A005CB29B /* menu.tcl */,
+ F966BB7508F27A3A005CB29B /* mkpsenc.tcl */,
+ F966BB7608F27A3A005CB29B /* msgbox.tcl */,
+ F966BB8608F27A3A005CB29B /* obsolete.tcl */,
+ F966BB8708F27A3A005CB29B /* optMenu.tcl */,
+ F966BB8808F27A3A005CB29B /* palette.tcl */,
+ F966BB8908F27A3B005CB29B /* panedwindow.tcl */,
+ F966BB8B08F27A3B005CB29B /* safetk.tcl */,
+ F966BB8C08F27A3B005CB29B /* scale.tcl */,
+ F966BB8D08F27A3B005CB29B /* scrlbar.tcl */,
+ F966BB8E08F27A3B005CB29B /* spinbox.tcl */,
+ F966BB8F08F27A3B005CB29B /* tclIndex */,
+ F966BB9008F27A3B005CB29B /* tearoff.tcl */,
+ F966BB9108F27A3B005CB29B /* text.tcl */,
+ F966BB9208F27A3B005CB29B /* tk.tcl */,
+ F966BB9308F27A3B005CB29B /* tkfbox.tcl */,
+ F96888360AF787B3000797B5 /* ttk */,
+ F966BB9408F27A3B005CB29B /* unsupported.tcl */,
+ F966BB9508F27A3B005CB29B /* xmfbox.tcl */,
+ );
+ path = library;
+ sourceTree = "<group>";
+ };
+ F966BB1A08F27A39005CB29B /* demos */ = {
+ isa = PBXGroup;
+ children = (
+ F966BB1B08F27A39005CB29B /* anilabel.tcl */,
+ F966BB1C08F27A39005CB29B /* aniwave.tcl */,
+ F966BB1D08F27A39005CB29B /* arrow.tcl */,
+ F966BB1E08F27A39005CB29B /* bind.tcl */,
+ F966BB1F08F27A39005CB29B /* bitmap.tcl */,
+ F966BB2008F27A39005CB29B /* browse */,
+ F966BB2108F27A39005CB29B /* button.tcl */,
+ F966BB2208F27A39005CB29B /* check.tcl */,
+ F966BB2308F27A39005CB29B /* clrpick.tcl */,
+ F966BB2408F27A39005CB29B /* colors.tcl */,
+ F936FCDB0CCD984600716967 /* combo.tcl */,
+ F966BB2508F27A39005CB29B /* cscroll.tcl */,
+ F966BB2608F27A39005CB29B /* ctext.tcl */,
+ F966BB2708F27A39005CB29B /* dialog1.tcl */,
+ F966BB2808F27A39005CB29B /* dialog2.tcl */,
+ F966BB2A08F27A39005CB29B /* entry1.tcl */,
+ F966BB2B08F27A39005CB29B /* entry2.tcl */,
+ F966BB2C08F27A39005CB29B /* entry3.tcl */,
+ F966BB2D08F27A39005CB29B /* filebox.tcl */,
+ F966BB2E08F27A39005CB29B /* floor.tcl */,
+ F91543270EF201A90032D1E8 /* fontchoose.tcl */,
+ F966BB2F08F27A39005CB29B /* form.tcl */,
+ F966BB3008F27A39005CB29B /* goldberg.tcl */,
+ F966BB3108F27A39005CB29B /* hello */,
+ F966BB3208F27A39005CB29B /* hscale.tcl */,
+ F966BB3308F27A39005CB29B /* icon.tcl */,
+ F966BB3408F27A39005CB29B /* image1.tcl */,
+ F966BB3508F27A39005CB29B /* image2.tcl */,
+ F966BB4208F27A3A005CB29B /* items.tcl */,
+ F966BB4308F27A3A005CB29B /* ixset */,
+ F92240290D7C620F005EC715 /* knightstour.tcl */,
+ F966BB4408F27A3A005CB29B /* label.tcl */,
+ F966BB4508F27A3A005CB29B /* labelframe.tcl */,
+ F9D1360A0CDC252C00DBE0B5 /* mclist.tcl */,
+ F966BB4608F27A3A005CB29B /* menu.tcl */,
+ F966BB4708F27A3A005CB29B /* menubu.tcl */,
+ F966BB4808F27A3A005CB29B /* msgbox.tcl */,
+ F966BB4A08F27A3A005CB29B /* paned1.tcl */,
+ F966BB4B08F27A3A005CB29B /* paned2.tcl */,
+ F966BB4C08F27A3A005CB29B /* pendulum.tcl */,
+ F966BB4D08F27A3A005CB29B /* plot.tcl */,
+ F966BB4E08F27A3A005CB29B /* puzzle.tcl */,
+ F966BB4F08F27A3A005CB29B /* radio.tcl */,
+ F966BB5008F27A3A005CB29B /* README */,
+ F966BB5108F27A3A005CB29B /* rmt */,
+ F966BB5208F27A3A005CB29B /* rolodex */,
+ F966BB5308F27A3A005CB29B /* ruler.tcl */,
+ F966BB5408F27A3A005CB29B /* sayings.tcl */,
+ F966BB5508F27A3A005CB29B /* search.tcl */,
+ F966BB5608F27A3A005CB29B /* spin.tcl */,
+ F966BB5708F27A3A005CB29B /* square */,
+ F966BB5808F27A3A005CB29B /* states.tcl */,
+ F966BB5908F27A3A005CB29B /* style.tcl */,
+ F966BB5A08F27A3A005CB29B /* tclIndex */,
+ F966BB5B08F27A3A005CB29B /* tcolor */,
+ F966BB5C08F27A3A005CB29B /* text.tcl */,
+ F9099B8A0CC67D30005A9580 /* textpeer.tcl */,
+ F966BB5D08F27A3A005CB29B /* timer */,
+ F936FCD90CCD984600716967 /* toolbar.tcl */,
+ F936FCD80CCD984600716967 /* tree.tcl */,
+ F9099B8B0CC67D3E005A9580 /* ttkbut.tcl */,
+ F9F4EFDD0CC7B3CB00378A27 /* ttkmenu.tcl */,
+ F936FCDA0CCD984600716967 /* ttknote.tcl */,
+ F9F4EFDC0CC7B3CA00378A27 /* ttkpane.tcl */,
+ F936FCD70CCD984500716967 /* ttkprogress.tcl */,
+ F966BB5E08F27A3A005CB29B /* twind.tcl */,
+ F966BB5F08F27A3A005CB29B /* unicodeout.tcl */,
+ F966BB6008F27A3A005CB29B /* vscale.tcl */,
+ F966BB6108F27A3A005CB29B /* widget */,
+ );
+ path = demos;
+ sourceTree = "<group>";
+ };
+ F966BB9708F27A3B005CB29B /* macosx */ = {
+ isa = PBXGroup;
+ children = (
+ F966BBBA08F27A3B005CB29B /* configure.ac */,
+ F966BBBB08F27A3B005CB29B /* GNUmakefile */,
+ F966BBBE08F27A3B005CB29B /* README */,
+ F966BBC008F27A3B005CB29B /* Tk-Info.plist.in */,
+ F966BBC208F27A3B005CB29B /* tkMacOSX.h */,
+ F966BBC508F27A3B005CB29B /* tkMacOSXBitmap.c */,
+ F966BBC608F27A3B005CB29B /* tkMacOSXButton.c */,
+ F966BBC808F27A3B005CB29B /* tkMacOSXClipboard.c */,
+ F966BBC908F27A3B005CB29B /* tkMacOSXColor.c */,
+ F966BBCA08F27A3B005CB29B /* tkMacOSXConfig.c */,
+ F966BBCB08F27A3B005CB29B /* tkMacOSXCursor.c */,
+ F966BBCC08F27A3B005CB29B /* tkMacOSXCursors.h */,
+ F966BBCD08F27A3B005CB29B /* tkMacOSXDebug.c */,
+ F966BBCE08F27A3B005CB29B /* tkMacOSXDebug.h */,
+ F966BBCF08F27A3B005CB29B /* tkMacOSXDefault.h */,
+ F966BBD008F27A3B005CB29B /* tkMacOSXDialog.c */,
+ F966BBD108F27A3B005CB29B /* tkMacOSXDraw.c */,
+ F966BBD208F27A3B005CB29B /* tkMacOSXEmbed.c */,
+ F966BBD308F27A3B005CB29B /* tkMacOSXEntry.c */,
+ F966BBD408F27A3B005CB29B /* tkMacOSXEvent.c */,
+ F966BBD508F27A3B005CB29B /* tkMacOSXEvent.h */,
+ F966BBD608F27A3B005CB29B /* tkMacOSXFont.c */,
+ F93E5EFD09CF8711008FA367 /* tkMacOSXFont.h */,
+ F966BBD708F27A3B005CB29B /* tkMacOSXHLEvents.c */,
+ F966BBD808F27A3B005CB29B /* tkMacOSXInit.c */,
+ F966BBDA08F27A3B005CB29B /* tkMacOSXInt.h */,
+ F966BBDB08F27A3B005CB29B /* tkMacOSXKeyboard.c */,
+ F966BBDC08F27A3B005CB29B /* tkMacOSXKeyEvent.c */,
+ F966BBDD08F27A3B005CB29B /* tkMacOSXMenu.c */,
+ F966BBE008F27A3B005CB29B /* tkMacOSXMenubutton.c */,
+ F966BBE108F27A3B005CB29B /* tkMacOSXMenus.c */,
+ F966BBE208F27A3B005CB29B /* tkMacOSXMouseEvent.c */,
+ F966BBE308F27A3B005CB29B /* tkMacOSXNotify.c */,
+ F966BBEA08F27A3C005CB29B /* tkMacOSXPort.h */,
+ F976F6A70C325FB6005066D9 /* tkMacOSXPrivate.h */,
+ F966BBEB08F27A3C005CB29B /* tkMacOSXRegion.c */,
+ F966BBEC08F27A3C005CB29B /* tkMacOSXScale.c */,
+ F966BBED08F27A3C005CB29B /* tkMacOSXScrlbr.c */,
+ F966BBEE08F27A3C005CB29B /* tkMacOSXSend.c */,
+ F966BBEF08F27A3C005CB29B /* tkMacOSXSubwindows.c */,
+ F966BBF008F27A3C005CB29B /* tkMacOSXTest.c */,
+ F966BBF108F27A3C005CB29B /* tkMacOSXWindowEvent.c */,
+ F966BBF208F27A3C005CB29B /* tkMacOSXWm.c */,
+ F966BBF308F27A3C005CB29B /* tkMacOSXWm.h */,
+ F966BBF408F27A3C005CB29B /* tkMacOSXXCursors.h */,
+ F966BBF508F27A3C005CB29B /* tkMacOSXXStubs.c */,
+ F96888840AF78938000797B5 /* ttkMacOSXTheme.c */,
+ F95D8D4B0F1715610006B020 /* Tk.icns */,
+ F95D8D4C0F1715610006B020 /* Tk.tiff */,
+ F966BBF708F27A3C005CB29B /* Wish-Info.plist.in */,
+ F97590AE1039A96200558A9A /* Wish.sdef */,
+ F97AE7F10B65C1E900310EA2 /* Tk-Common.xcconfig */,
+ F97AE8330B65C87F00310EA2 /* Tk-Debug.xcconfig */,
+ F97AE82B0B65C69B00310EA2 /* Tk-Release.xcconfig */,
+ );
+ path = macosx;
+ sourceTree = "<group>";
+ };
+ F966BC0408F27A3C005CB29B /* tests */ = {
+ isa = PBXGroup;
+ children = (
+ F966BC0508F27A3C005CB29B /* all.tcl */,
+ F966BC0608F27A3C005CB29B /* arc.tcl */,
+ F966BC0708F27A3C005CB29B /* bell.test */,
+ F966BC0808F27A3C005CB29B /* bevel.tcl */,
+ F966BC0908F27A3C005CB29B /* bgerror.test */,
+ F966BC0A08F27A3C005CB29B /* bind.test */,
+ F966BC0B08F27A3C005CB29B /* bitmap.test */,
+ F966BC0C08F27A3C005CB29B /* border.test */,
+ F966BC0D08F27A3C005CB29B /* bugs.tcl */,
+ F966BC0E08F27A3C005CB29B /* butGeom.tcl */,
+ F966BC0F08F27A3C005CB29B /* butGeom2.tcl */,
+ F966BC1008F27A3C005CB29B /* button.test */,
+ F966BC1108F27A3C005CB29B /* canvas.test */,
+ F966BC1208F27A3C005CB29B /* canvImg.test */,
+ F966BC1308F27A3C005CB29B /* canvPs.test */,
+ F966BC1408F27A3C005CB29B /* canvPsArc.tcl */,
+ F966BC1508F27A3C005CB29B /* canvPsBmap.tcl */,
+ F966BC1608F27A3C005CB29B /* canvPsGrph.tcl */,
+ F966BC1708F27A3C005CB29B /* canvPsImg.tcl */,
+ F966BC1808F27A3C005CB29B /* canvPsText.tcl */,
+ F966BC1908F27A3C005CB29B /* canvRect.test */,
+ F966BC1A08F27A3C005CB29B /* canvText.test */,
+ F966BC1B08F27A3C005CB29B /* canvWind.test */,
+ F966BC1C08F27A3C005CB29B /* choosedir.test */,
+ F966BC1D08F27A3C005CB29B /* clipboard.test */,
+ F966BC1E08F27A3C005CB29B /* clrpick.test */,
+ F966BC1F08F27A3C005CB29B /* cmap.tcl */,
+ F966BC2008F27A3C005CB29B /* cmds.test */,
+ F966BC2108F27A3C005CB29B /* color.test */,
+ F966BC2208F27A3C005CB29B /* config.test */,
+ F966BC2308F27A3C005CB29B /* constraints.tcl */,
+ F966BC2408F27A3C005CB29B /* cursor.test */,
+ F966BC2508F27A3C005CB29B /* dialog.test */,
+ F966BC2608F27A3C005CB29B /* embed.test */,
+ F966BC2708F27A3C005CB29B /* entry.test */,
+ F966BC2808F27A3C005CB29B /* event.test */,
+ F966BC2908F27A3C005CB29B /* filebox.test */,
+ F966BC2A08F27A3C005CB29B /* focus.test */,
+ F966BC2B08F27A3C005CB29B /* focusTcl.test */,
+ F966BC2C08F27A3C005CB29B /* font.test */,
+ F99388950EE02D980065FE6B /* fontchooser.test */,
+ F966BC2D08F27A3C005CB29B /* frame.test */,
+ F966BC2E08F27A3C005CB29B /* geometry.test */,
+ F966BC2F08F27A3C005CB29B /* get.test */,
+ F966BC3008F27A3C005CB29B /* grab.test */,
+ F966BC3108F27A3C005CB29B /* grid.test */,
+ F966BC3308F27A3C005CB29B /* image.test */,
+ F966BC3408F27A3C005CB29B /* imgBmap.test */,
+ F966BC3508F27A3C005CB29B /* imgPhoto.test */,
+ F9DD99BF0F07DFCD0018B2E4 /* imgPNG.test */,
+ F966BC3608F27A3C005CB29B /* imgPPM.test */,
+ F966BC3708F27A3C005CB29B /* listbox.test */,
+ F966BC3808F27A3C005CB29B /* main.test */,
+ F966BC3908F27A3C005CB29B /* menu.test */,
+ F966BC3A08F27A3C005CB29B /* menubut.test */,
+ F966BC3B08F27A3C005CB29B /* menuDraw.test */,
+ F966BC3C08F27A3C005CB29B /* message.test */,
+ F966BC3D08F27A3C005CB29B /* msgbox.test */,
+ F966BC3E08F27A3C005CB29B /* obj.test */,
+ F966BC3F08F27A3C005CB29B /* oldpack.test */,
+ F966BC4008F27A3C005CB29B /* option.file1 */,
+ F966BC4108F27A3C005CB29B /* option.file2 */,
+ F966BC4208F27A3C005CB29B /* option.test */,
+ F966BC4308F27A3C005CB29B /* pack.test */,
+ F966BC4408F27A3C005CB29B /* panedwindow.test */,
+ F966BC4508F27A3D005CB29B /* place.test */,
+ F966BC4608F27A3D005CB29B /* raise.test */,
+ F966BC4708F27A3D005CB29B /* README */,
+ F966BC4808F27A3D005CB29B /* safe.test */,
+ F966BC4908F27A3D005CB29B /* scale.test */,
+ F966BC4A08F27A3D005CB29B /* scrollbar.test */,
+ F966BC4B08F27A3D005CB29B /* select.test */,
+ F966BC4C08F27A3D005CB29B /* send.test */,
+ F966BC4D08F27A3D005CB29B /* spinbox.test */,
+ F966BC4E08F27A3D005CB29B /* text.test */,
+ F966BC4F08F27A3D005CB29B /* textBTree.test */,
+ F966BC5008F27A3D005CB29B /* textDisp.test */,
+ F966BC5108F27A3D005CB29B /* textImage.test */,
+ F966BC5208F27A3D005CB29B /* textIndex.test */,
+ F966BC5308F27A3D005CB29B /* textMark.test */,
+ F966BC5408F27A3D005CB29B /* textTag.test */,
+ F966BC5508F27A3D005CB29B /* textWind.test */,
+ F966BC5608F27A3D005CB29B /* tk.test */,
+ F96888530AF7880C000797B5 /* ttk */,
+ F966BC5708F27A3D005CB29B /* unixButton.test */,
+ F966BC5808F27A3D005CB29B /* unixEmbed.test */,
+ F966BC5908F27A3D005CB29B /* unixFont.test */,
+ F966BC5A08F27A3D005CB29B /* unixMenu.test */,
+ F966BC5B08F27A3D005CB29B /* unixSelect.test */,
+ F966BC5C08F27A3D005CB29B /* unixWm.test */,
+ F966BC5D08F27A3D005CB29B /* util.test */,
+ F966BC5E08F27A3D005CB29B /* visual.test */,
+ F966BC5F08F27A3D005CB29B /* visual_bb.test */,
+ F966BC6008F27A3D005CB29B /* winButton.test */,
+ F966BC6108F27A3D005CB29B /* winClipboard.test */,
+ F966BC6208F27A3D005CB29B /* winDialog.test */,
+ F966BC6308F27A3D005CB29B /* window.test */,
+ F966BC6408F27A3D005CB29B /* winfo.test */,
+ F966BC6508F27A3D005CB29B /* winFont.test */,
+ F966BC6608F27A3D005CB29B /* winMenu.test */,
+ F966BC6708F27A3D005CB29B /* winSend.test */,
+ F966BC6808F27A3D005CB29B /* winWm.test */,
+ F966BC6908F27A3D005CB29B /* wm.test */,
+ F966BC6A08F27A3D005CB29B /* xmfbox.test */,
+ );
+ path = tests;
+ sourceTree = "<group>";
+ };
+ F966BC6B08F27A3D005CB29B /* unix */ = {
+ isa = PBXGroup;
+ children = (
+ F966BC6C08F27A3D005CB29B /* aclocal.m4 */,
+ F966BC6D08F27A3D005CB29B /* configure */,
+ F966BC6E08F27A3D005CB29B /* configure.in */,
+ F966BC6F08F27A3D005CB29B /* install-sh */,
+ F966BC7008F27A3D005CB29B /* installManPage */,
+ F966BC7108F27A3D005CB29B /* Makefile.in */,
+ F966BC7208F27A3D005CB29B /* README */,
+ F966BC7308F27A3D005CB29B /* tcl.m4 */,
+ F974D57B0FBE7EC000BF728B /* tk.pc.in */,
+ F966BC7408F27A3D005CB29B /* tk.spec */,
+ F966BC7508F27A3D005CB29B /* tkAppInit.c */,
+ F966BC7608F27A3D005CB29B /* tkConfig.h.in */,
+ F966BC7708F27A3D005CB29B /* tkConfig.sh.in */,
+ F966BC7808F27A3D005CB29B /* tkUnix.c */,
+ F966BC7908F27A3D005CB29B /* tkUnix3d.c */,
+ F966BC7A08F27A3D005CB29B /* tkUnixButton.c */,
+ F966BC7B08F27A3D005CB29B /* tkUnixColor.c */,
+ F966BC7C08F27A3D005CB29B /* tkUnixConfig.c */,
+ F966BC7D08F27A3D005CB29B /* tkUnixCursor.c */,
+ F966BC7E08F27A3D005CB29B /* tkUnixDefault.h */,
+ F966BC7F08F27A3D005CB29B /* tkUnixDialog.c */,
+ F966BC8008F27A3D005CB29B /* tkUnixDraw.c */,
+ F966BC8108F27A3D005CB29B /* tkUnixEmbed.c */,
+ F966BC8208F27A3D005CB29B /* tkUnixEvent.c */,
+ F966BC8308F27A3D005CB29B /* tkUnixFocus.c */,
+ F966BC8408F27A3D005CB29B /* tkUnixFont.c */,
+ F966BC8508F27A3D005CB29B /* tkUnixInit.c */,
+ F966BC8608F27A3D005CB29B /* tkUnixInt.h */,
+ F966BC8708F27A3D005CB29B /* tkUnixKey.c */,
+ F966BC8808F27A3D005CB29B /* tkUnixMenu.c */,
+ F966BC8908F27A3D005CB29B /* tkUnixMenubu.c */,
+ F966BC8A08F27A3D005CB29B /* tkUnixPort.h */,
+ F966BC8B08F27A3D005CB29B /* tkUnixRFont.c */,
+ F966BC8C08F27A3D005CB29B /* tkUnixScale.c */,
+ F966BC8D08F27A3D005CB29B /* tkUnixScrlbr.c */,
+ F966BC8E08F27A3D005CB29B /* tkUnixSelect.c */,
+ F966BC8F08F27A3D005CB29B /* tkUnixSend.c */,
+ F966BC9008F27A3D005CB29B /* tkUnixWm.c */,
+ F966BC9108F27A3D005CB29B /* tkUnixXId.c */,
+ );
+ path = unix;
+ sourceTree = "<group>";
+ };
+ F966BC9208F27A3D005CB29B /* win */ = {
+ isa = PBXGroup;
+ children = (
+ F966BC9408F27A3D005CB29B /* aclocal.m4 */,
+ F966BC9508F27A3D005CB29B /* buildall.vc.bat */,
+ F966BC9608F27A3E005CB29B /* configure */,
+ F966BC9708F27A3E005CB29B /* configure.in */,
+ F966BC9908F27A3E005CB29B /* Makefile.in */,
+ F966BC9A08F27A3E005CB29B /* makefile.vc */,
+ F966BC9B08F27A3E005CB29B /* mkd.bat */,
+ F966BC9C08F27A3E005CB29B /* nmakehlp.c */,
+ F966BC9D08F27A3E005CB29B /* rc */,
+ F966BCF308F27A3E005CB29B /* README */,
+ F966BCF408F27A3E005CB29B /* rmd.bat */,
+ F966BCF508F27A3F005CB29B /* rules.vc */,
+ F966BCF608F27A3F005CB29B /* stubs.c */,
+ F966BCF708F27A3F005CB29B /* tcl.m4 */,
+ F966BCF808F27A3F005CB29B /* tkConfig.sh.in */,
+ F966BCF908F27A3F005CB29B /* tkWin.h */,
+ F966BCFA08F27A3F005CB29B /* tkWin32Dll.c */,
+ F966BCFB08F27A3F005CB29B /* tkWin3d.c */,
+ F966BCFC08F27A3F005CB29B /* tkWinButton.c */,
+ F966BCFD08F27A3F005CB29B /* tkWinClipboard.c */,
+ F966BCFE08F27A3F005CB29B /* tkWinColor.c */,
+ F966BCFF08F27A3F005CB29B /* tkWinConfig.c */,
+ F966BD0008F27A3F005CB29B /* tkWinCursor.c */,
+ F966BD0108F27A3F005CB29B /* tkWinDefault.h */,
+ F966BD0208F27A3F005CB29B /* tkWinDialog.c */,
+ F966BD0308F27A3F005CB29B /* tkWinDraw.c */,
+ F966BD0408F27A3F005CB29B /* tkWinEmbed.c */,
+ F966BD0508F27A3F005CB29B /* tkWinFont.c */,
+ F966BD0708F27A3F005CB29B /* tkWinImage.c */,
+ F966BD0808F27A3F005CB29B /* tkWinInit.c */,
+ F966BD0908F27A3F005CB29B /* tkWinInt.h */,
+ F966BD0A08F27A3F005CB29B /* tkWinKey.c */,
+ F966BD0B08F27A3F005CB29B /* tkWinMenu.c */,
+ F966BD0C08F27A3F005CB29B /* tkWinPixmap.c */,
+ F966BD0D08F27A3F005CB29B /* tkWinPointer.c */,
+ F966BD0E08F27A3F005CB29B /* tkWinPort.h */,
+ F966BD0F08F27A3F005CB29B /* tkWinRegion.c */,
+ F966BD1008F27A3F005CB29B /* tkWinScrlbr.c */,
+ F966BD1108F27A3F005CB29B /* tkWinSend.c */,
+ F966BD1208F27A3F005CB29B /* tkWinSendCom.c */,
+ F966BD1308F27A3F005CB29B /* tkWinSendCom.h */,
+ F966BD1408F27A3F005CB29B /* tkWinTest.c */,
+ F966BD1508F27A3F005CB29B /* tkWinWindow.c */,
+ F966BD1608F27A3F005CB29B /* tkWinWm.c */,
+ F966BD1708F27A3F005CB29B /* tkWinX.c */,
+ F96888860AF78953000797B5 /* ttkWinMonitor.c */,
+ F96888870AF78953000797B5 /* ttkWinTheme.c */,
+ F96888880AF78953000797B5 /* ttkWinXPTheme.c */,
+ F966BD1808F27A3F005CB29B /* winMain.c */,
+ );
+ path = win;
+ sourceTree = "<group>";
+ };
+ F966BC9D08F27A3E005CB29B /* rc */ = {
+ isa = PBXGroup;
+ children = (
+ F966BCEE08F27A3E005CB29B /* tk.rc */,
+ F966BCEF08F27A3E005CB29B /* tk_base.rc */,
+ F966BCF208F27A3E005CB29B /* wish.rc */,
+ );
+ path = rc;
+ sourceTree = "<group>";
+ };
+ F966BD1908F27A3F005CB29B /* xlib */ = {
+ isa = PBXGroup;
+ children = (
+ F966BD1A08F27A3F005CB29B /* X11 */,
+ F966BD2308F27A3F005CB29B /* xbytes.h */,
+ F966BD2408F27A3F005CB29B /* xcolors.c */,
+ F966BD2508F27A3F005CB29B /* xdraw.c */,
+ F966BD2608F27A3F005CB29B /* xgc.c */,
+ F966BD2708F27A3F005CB29B /* ximage.c */,
+ F966BD2808F27A3F005CB29B /* xutil.c */,
+ );
+ path = xlib;
+ sourceTree = "<group>";
+ };
+ F966BD1A08F27A3F005CB29B /* X11 */ = {
+ isa = PBXGroup;
+ children = (
+ F966BD1B08F27A3F005CB29B /* cursorfont.h */,
+ F966BD1C08F27A3F005CB29B /* keysym.h */,
+ F966BD1D08F27A3F005CB29B /* keysymdef.h */,
+ F966BD1E08F27A3F005CB29B /* X.h */,
+ F966BD1F08F27A3F005CB29B /* Xatom.h */,
+ F966BD2008F27A3F005CB29B /* Xfuncproto.h */,
+ F966BD2108F27A3F005CB29B /* Xlib.h */,
+ F966BD2208F27A3F005CB29B /* Xutil.h */,
+ );
+ path = X11;
+ sourceTree = "<group>";
+ };
+ F966C06F08F281DC005CB29B /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ F9C9CBFF0E84059800E00935 /* ApplicationServices.framework */,
+ F966C07408F2820D005CB29B /* CoreFoundation.framework */,
+ F96437E60EF0D652003F468E /* libz.dylib */,
+ F966C07608F2821B005CB29B /* Carbon.framework */,
+ F94523A10E6FC2AC00C1D987 /* Cocoa.framework */,
+ F966C07808F28233005CB29B /* IOKit.framework */,
+ F9FD32140CC1AF170073837D /* libX11.dylib */,
+ F9FD32150CC1AF170073837D /* libXext.dylib */,
+ F9FD32160CC1AF170073837D /* libXss.dylib */,
+ F9FD349A0CC1BB0D0073837D /* libXft.dylib */,
+ F9FD34990CC1BB0D0073837D /* libfreetype.dylib */,
+ F9FD34C30CC1BBD70073837D /* libfontconfig.dylib */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ F96887DF0AF786D5000797B5 /* ttk */ = {
+ isa = PBXGroup;
+ children = (
+ F96887E00AF786D5000797B5 /* ttk.decls */,
+ F96887E10AF786D5000797B5 /* ttkBlink.c */,
+ F96887E20AF786D5000797B5 /* ttkButton.c */,
+ F96887E30AF786D5000797B5 /* ttkCache.c */,
+ F96887E40AF786D5000797B5 /* ttkClamTheme.c */,
+ F96887E50AF786D5000797B5 /* ttkClassicTheme.c */,
+ F96887E60AF786D5000797B5 /* ttkDecls.h */,
+ F96887E70AF786D5000797B5 /* ttkDefaultTheme.c */,
+ F96887E80AF786D5000797B5 /* ttkElements.c */,
+ F96887E90AF786D5000797B5 /* ttkEntry.c */,
+ F96887EA0AF786D5000797B5 /* ttkFrame.c */,
+ F96887EB0AF786D5000797B5 /* ttkImage.c */,
+ F96887EC0AF786D5000797B5 /* ttkInit.c */,
+ F96887ED0AF786D5000797B5 /* ttkLabel.c */,
+ F96887EE0AF786D5000797B5 /* ttkLayout.c */,
+ F96887EF0AF786D5000797B5 /* ttkManager.c */,
+ F96887F00AF786D5000797B5 /* ttkManager.h */,
+ F96887F10AF786D5000797B5 /* ttkNotebook.c */,
+ F96887F20AF786D5000797B5 /* ttkPanedwindow.c */,
+ F96887F30AF786D5000797B5 /* ttkProgress.c */,
+ F96887F40AF786D5000797B5 /* ttkScale.c */,
+ F96887F50AF786D5000797B5 /* ttkScroll.c */,
+ F96887F60AF786D5000797B5 /* ttkScrollbar.c */,
+ F96887F70AF786D5000797B5 /* ttkSeparator.c */,
+ F96887F80AF786D5000797B5 /* ttkSquare.c */,
+ F96887F90AF786D5000797B5 /* ttkState.c */,
+ F96887FA0AF786D5000797B5 /* ttkStubInit.c */,
+ F96887FB0AF786D5000797B5 /* ttkStubLib.c */,
+ F96887FC0AF786D5000797B5 /* ttkTagSet.c */,
+ F96887FD0AF786D5000797B5 /* ttkTheme.c */,
+ F96887FE0AF786D5000797B5 /* ttkTheme.h */,
+ F96887FF0AF786D5000797B5 /* ttkThemeInt.h */,
+ F96888000AF786D5000797B5 /* ttkTrace.c */,
+ F96888010AF786D5000797B5 /* ttkTrack.c */,
+ F96888020AF786D5000797B5 /* ttkTreeview.c */,
+ F96888030AF786D5000797B5 /* ttkWidget.c */,
+ F96888040AF786D5000797B5 /* ttkWidget.h */,
+ );
+ path = ttk;
+ sourceTree = "<group>";
+ };
+ F96888360AF787B3000797B5 /* ttk */ = {
+ isa = PBXGroup;
+ children = (
+ F96888370AF787B3000797B5 /* altTheme.tcl */,
+ F96888380AF787B3000797B5 /* aquaTheme.tcl */,
+ F96888390AF787B3000797B5 /* button.tcl */,
+ F968883A0AF787B3000797B5 /* clamTheme.tcl */,
+ F968883B0AF787B3000797B5 /* classicTheme.tcl */,
+ F968883C0AF787B3000797B5 /* combobox.tcl */,
+ F968883D0AF787B3000797B5 /* cursors.tcl */,
+ F968883E0AF787B3000797B5 /* defaults.tcl */,
+ F96888400AF787B3000797B5 /* entry.tcl */,
+ F96888410AF787B3000797B5 /* fonts.tcl */,
+ F96888440AF787B3000797B5 /* menubutton.tcl */,
+ F96888450AF787B3000797B5 /* notebook.tcl */,
+ F96888460AF787B3000797B5 /* panedwindow.tcl */,
+ F96888470AF787B3000797B5 /* progress.tcl */,
+ F96888480AF787B3000797B5 /* scale.tcl */,
+ F96888490AF787B3000797B5 /* scrollbar.tcl */,
+ F968884A0AF787B3000797B5 /* sizegrip.tcl */,
+ F968884B0AF787B3000797B5 /* treeview.tcl */,
+ F968884C0AF787B3000797B5 /* ttk.tcl */,
+ F968884D0AF787B3000797B5 /* utils.tcl */,
+ F968884E0AF787B3000797B5 /* winTheme.tcl */,
+ F973E5960EE99384001A648E /* vistaTheme.tcl */,
+ F968884F0AF787B3000797B5 /* xpTheme.tcl */,
+ );
+ path = ttk;
+ sourceTree = "<group>";
+ };
+ F96888530AF7880C000797B5 /* ttk */ = {
+ isa = PBXGroup;
+ children = (
+ F96888540AF7880C000797B5 /* all.tcl */,
+ F98383650F0FA43900171CA6 /* checkbutton.test */,
+ F96888560AF7880C000797B5 /* combobox.test */,
+ F96888570AF7880C000797B5 /* entry.test */,
+ F96888580AF7880C000797B5 /* image.test */,
+ F96888590AF7880C000797B5 /* labelframe.test */,
+ F968885A0AF7880C000797B5 /* layout.test */,
+ F968885C0AF7880C000797B5 /* notebook.test */,
+ F968885D0AF7880C000797B5 /* panedwindow.test */,
+ F968885E0AF7880C000797B5 /* progressbar.test */,
+ F98383680F0FA44700171CA6 /* radiobutton.test */,
+ F968885F0AF7880C000797B5 /* scrollbar.test */,
+ F96888600AF7880C000797B5 /* treetags.test */,
+ F96888610AF7880C000797B5 /* treeview.test */,
+ F96888620AF7880C000797B5 /* ttk.test */,
+ F96888630AF7880C000797B5 /* validate.test */,
+ F962F7C60DADC26200648DB8 /* vsapi.test */,
+ );
+ path = ttk;
+ sourceTree = "<group>";
+ };
+ F96D3DF608F27169004A47F5 /* Tcl Sources */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3EC908F272A7004A47F5 /* generic */,
+ F96D432C08F272B4004A47F5 /* macosx */,
+ F96D443E08F272B9004A47F5 /* unix */,
+ F96D425C08F272B2004A47F5 /* libtommath */,
+ F96D446E08F272B9004A47F5 /* win */,
+ F96D3F3808F272A7004A47F5 /* library */,
+ F96D434408F272B5004A47F5 /* tests */,
+ F96D3DFC08F272A4004A47F5 /* doc */,
+ F96D43D008F272B8004A47F5 /* tools */,
+ F9183E690EFC81560030B814 /* pkgs */,
+ F96D3DFA08F272A4004A47F5 /* ChangeLog */,
+ F96D3DFB08F272A4004A47F5 /* changes */,
+ F96D434308F272B5004A47F5 /* README */,
+ F96D432B08F272B4004A47F5 /* license.terms */,
+ );
+ name = "Tcl Sources";
+ sourceTree = TCL_SRCROOT;
+ };
+ F96D3DF708F271BE004A47F5 /* Tk Sources */ = {
+ isa = PBXGroup;
+ children = (
+ F966BAA508F27A38005CB29B /* generic */,
+ F966BB9708F27A3B005CB29B /* macosx */,
+ F966BC6B08F27A3D005CB29B /* unix */,
+ F966BD1908F27A3F005CB29B /* xlib */,
+ F966BA0308F27A37005CB29B /* bitmaps */,
+ F966BC9208F27A3D005CB29B /* win */,
+ F966BB1308F27A39005CB29B /* library */,
+ F966BC0408F27A3C005CB29B /* tests */,
+ F966BA1008F27A37005CB29B /* doc */,
+ F966BA0E08F27A37005CB29B /* ChangeLog */,
+ F966BA0F08F27A37005CB29B /* changes */,
+ F966BC0308F27A3C005CB29B /* README */,
+ F966BB9608F27A3B005CB29B /* license.terms */,
+ );
+ name = "Tk Sources";
+ sourceTree = TK_SRCROOT;
+ };
+ F96D3DFC08F272A4004A47F5 /* doc */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3DFD08F272A4004A47F5 /* Access.3 */,
+ F96D3DFE08F272A4004A47F5 /* AddErrInfo.3 */,
+ F96D3DFF08F272A4004A47F5 /* after.n */,
+ F96D3E0008F272A4004A47F5 /* Alloc.3 */,
+ F96D3E0108F272A4004A47F5 /* AllowExc.3 */,
+ F96D3E0208F272A4004A47F5 /* append.n */,
+ F96D3E0308F272A4004A47F5 /* AppInit.3 */,
+ F96D3E0408F272A5004A47F5 /* array.n */,
+ F96D3E0508F272A5004A47F5 /* AssocData.3 */,
+ F96D3E0608F272A5004A47F5 /* Async.3 */,
+ F96D3E0708F272A5004A47F5 /* BackgdErr.3 */,
+ F96D3E0808F272A5004A47F5 /* Backslash.3 */,
+ F96D3E0908F272A5004A47F5 /* bgerror.n */,
+ F96D3E0A08F272A5004A47F5 /* binary.n */,
+ F96D3E0B08F272A5004A47F5 /* BoolObj.3 */,
+ F96D3E0C08F272A5004A47F5 /* break.n */,
+ F96D3E0D08F272A5004A47F5 /* ByteArrObj.3 */,
+ F96D3E0E08F272A5004A47F5 /* CallDel.3 */,
+ F96D3E0F08F272A5004A47F5 /* case.n */,
+ F96D3E1008F272A5004A47F5 /* catch.n */,
+ F96D3E1108F272A5004A47F5 /* cd.n */,
+ F96D3E1208F272A5004A47F5 /* chan.n */,
+ F96D3E1308F272A5004A47F5 /* ChnlStack.3 */,
+ F93599CF0DF1F87F00E04F67 /* Class.3 */,
+ F93599D00DF1F89E00E04F67 /* class.n */,
+ F96D3E1408F272A5004A47F5 /* clock.n */,
+ F96D3E1508F272A5004A47F5 /* close.n */,
+ F96D3E1608F272A5004A47F5 /* CmdCmplt.3 */,
+ F96D3E1708F272A5004A47F5 /* Concat.3 */,
+ F96D3E1808F272A5004A47F5 /* concat.n */,
+ F96D3E1908F272A5004A47F5 /* continue.n */,
+ F93599D20DF1F8DF00E04F67 /* copy.n */,
+ F974D5720FBE7DC600BF728B /* coroutine.n */,
+ F96D3E1A08F272A5004A47F5 /* CrtChannel.3 */,
+ F96D3E1B08F272A5004A47F5 /* CrtChnlHdlr.3 */,
+ F96D3E1C08F272A5004A47F5 /* CrtCloseHdlr.3 */,
+ F96D3E1D08F272A5004A47F5 /* CrtCommand.3 */,
+ F96D3E1E08F272A5004A47F5 /* CrtFileHdlr.3 */,
+ F96D3E1F08F272A5004A47F5 /* CrtInterp.3 */,
+ F96D3E2008F272A5004A47F5 /* CrtMathFnc.3 */,
+ F96D3E2108F272A5004A47F5 /* CrtObjCmd.3 */,
+ F96D3E2208F272A5004A47F5 /* CrtSlave.3 */,
+ F96D3E2308F272A5004A47F5 /* CrtTimerHdlr.3 */,
+ F96D3E2408F272A5004A47F5 /* CrtTrace.3 */,
+ F96D3E2508F272A5004A47F5 /* dde.n */,
+ F93599D30DF1F8F500E04F67 /* define.n */,
+ F96D3E2608F272A5004A47F5 /* DetachPids.3 */,
+ F96D3E2708F272A5004A47F5 /* dict.n */,
+ F96D3E2808F272A5004A47F5 /* DictObj.3 */,
+ F96D3E2908F272A5004A47F5 /* DoOneEvent.3 */,
+ F96D3E2A08F272A5004A47F5 /* DoubleObj.3 */,
+ F96D3E2B08F272A5004A47F5 /* DoWhenIdle.3 */,
+ F96D3E2C08F272A5004A47F5 /* DString.3 */,
+ F96D3E2D08F272A5004A47F5 /* DumpActiveMemory.3 */,
+ F96D3E2E08F272A5004A47F5 /* Encoding.3 */,
+ F96D3E2F08F272A5004A47F5 /* encoding.n */,
+ F96D3E3008F272A5004A47F5 /* Ensemble.3 */,
+ F96D3E3108F272A5004A47F5 /* Environment.3 */,
+ F96D3E3208F272A5004A47F5 /* eof.n */,
+ F96D3E3308F272A5004A47F5 /* error.n */,
+ F96D3E3408F272A5004A47F5 /* Eval.3 */,
+ F96D3E3508F272A5004A47F5 /* eval.n */,
+ F96D3E3608F272A5004A47F5 /* exec.n */,
+ F96D3E3708F272A5004A47F5 /* Exit.3 */,
+ F96D3E3808F272A5004A47F5 /* exit.n */,
+ F96D3E3908F272A5004A47F5 /* expr.n */,
+ F96D3E3A08F272A5004A47F5 /* ExprLong.3 */,
+ F96D3E3B08F272A5004A47F5 /* ExprLongObj.3 */,
+ F96D3E3C08F272A5004A47F5 /* fblocked.n */,
+ F96D3E3D08F272A5004A47F5 /* fconfigure.n */,
+ F96D3E3E08F272A5004A47F5 /* fcopy.n */,
+ F96D3E3F08F272A5004A47F5 /* file.n */,
+ F96D3E4008F272A5004A47F5 /* fileevent.n */,
+ F96D3E4108F272A5004A47F5 /* filename.n */,
+ F96D3E4208F272A5004A47F5 /* FileSystem.3 */,
+ F96D3E4308F272A5004A47F5 /* FindExec.3 */,
+ F96D3E4408F272A5004A47F5 /* flush.n */,
+ F96D3E4508F272A5004A47F5 /* for.n */,
+ F96D3E4608F272A5004A47F5 /* foreach.n */,
+ F96D3E4708F272A5004A47F5 /* format.n */,
+ F96D3E4808F272A5004A47F5 /* GetCwd.3 */,
+ F96D3E4908F272A5004A47F5 /* GetHostName.3 */,
+ F96D3E4A08F272A5004A47F5 /* GetIndex.3 */,
+ F96D3E4B08F272A5004A47F5 /* GetInt.3 */,
+ F96D3E4C08F272A5004A47F5 /* GetOpnFl.3 */,
+ F96D3E4D08F272A5004A47F5 /* gets.n */,
+ F96D3E4E08F272A5004A47F5 /* GetStdChan.3 */,
+ F96D3E4F08F272A5004A47F5 /* GetTime.3 */,
+ F96D3E5008F272A5004A47F5 /* GetVersion.3 */,
+ F96D3E5108F272A5004A47F5 /* glob.n */,
+ F96D3E5208F272A6004A47F5 /* global.n */,
+ F96D3E5308F272A6004A47F5 /* Hash.3 */,
+ F96D3E5408F272A6004A47F5 /* history.n */,
+ F96D3E5508F272A6004A47F5 /* http.n */,
+ F96D3E5608F272A6004A47F5 /* if.n */,
+ F96D3E5708F272A6004A47F5 /* incr.n */,
+ F96D3E5808F272A6004A47F5 /* info.n */,
+ F96D3E5908F272A6004A47F5 /* Init.3 */,
+ F96D3E5A08F272A6004A47F5 /* InitStubs.3 */,
+ F96D3E5B08F272A6004A47F5 /* Interp.3 */,
+ F96D3E5C08F272A6004A47F5 /* interp.n */,
+ F96D3E5D08F272A6004A47F5 /* IntObj.3 */,
+ F96D3E5E08F272A6004A47F5 /* join.n */,
+ F96D3E5F08F272A6004A47F5 /* lappend.n */,
+ F96D3E6008F272A6004A47F5 /* lassign.n */,
+ F96D3E6108F272A6004A47F5 /* library.n */,
+ F96D3E6208F272A6004A47F5 /* Limit.3 */,
+ F96D3E6308F272A6004A47F5 /* lindex.n */,
+ F96D3E6408F272A6004A47F5 /* LinkVar.3 */,
+ F96D3E6508F272A6004A47F5 /* linsert.n */,
+ F96D3E6608F272A6004A47F5 /* list.n */,
+ F96D3E6708F272A6004A47F5 /* ListObj.3 */,
+ F96D3E6808F272A6004A47F5 /* llength.n */,
+ F96D3E6908F272A6004A47F5 /* load.n */,
+ F96D3E6A08F272A6004A47F5 /* lrange.n */,
+ F96D3E6B08F272A6004A47F5 /* lrepeat.n */,
+ F96D3E6C08F272A6004A47F5 /* lreplace.n */,
+ F96D3E6D08F272A6004A47F5 /* lsearch.n */,
+ F96D3E6E08F272A6004A47F5 /* lset.n */,
+ F96D3E6F08F272A6004A47F5 /* lsort.n */,
+ F96D3E7008F272A6004A47F5 /* man.macros */,
+ F96D3E7108F272A6004A47F5 /* mathfunc.n */,
+ F96D3E7208F272A6004A47F5 /* memory.n */,
+ F93599D40DF1F91900E04F67 /* Method.3 */,
+ F96D3E7308F272A6004A47F5 /* msgcat.n */,
+ F93599D50DF1F93700E04F67 /* my.n */,
+ F96D3E7408F272A6004A47F5 /* Namespace.3 */,
+ F96D3E7508F272A6004A47F5 /* namespace.n */,
+ F93599D60DF1F95000E04F67 /* next.n */,
+ F96D3E7608F272A6004A47F5 /* Notifier.3 */,
+ F96D3E7708F272A6004A47F5 /* Object.3 */,
+ F93599D70DF1F96800E04F67 /* object.n */,
+ F96D3E7808F272A6004A47F5 /* ObjectType.3 */,
+ F96D3E7908F272A6004A47F5 /* open.n */,
+ F96D3E7A08F272A6004A47F5 /* OpenFileChnl.3 */,
+ F96D3E7B08F272A6004A47F5 /* OpenTcp.3 */,
+ F96D3E7C08F272A6004A47F5 /* package.n */,
+ F96D3E7D08F272A6004A47F5 /* packagens.n */,
+ F96D3E7E08F272A6004A47F5 /* Panic.3 */,
+ F96D3E7F08F272A6004A47F5 /* ParseCmd.3 */,
+ F96D3E8008F272A6004A47F5 /* pid.n */,
+ F96D3E8108F272A6004A47F5 /* pkgMkIndex.n */,
+ F96D3E8208F272A6004A47F5 /* PkgRequire.3 */,
+ F9ECB1E10B26543C00A28025 /* platform_shell.n */,
+ F9ECB1E20B26543C00A28025 /* platform.n */,
+ F96D3E8308F272A6004A47F5 /* Preserve.3 */,
+ F96D3E8408F272A6004A47F5 /* PrintDbl.3 */,
+ F96D3E8508F272A6004A47F5 /* proc.n */,
+ F96D3E8608F272A6004A47F5 /* puts.n */,
+ F96D3E8708F272A6004A47F5 /* pwd.n */,
+ F96D3E8808F272A6004A47F5 /* re_syntax.n */,
+ F96D3E8908F272A6004A47F5 /* read.n */,
+ F96D3E8A08F272A6004A47F5 /* RecEvalObj.3 */,
+ F96D3E8B08F272A6004A47F5 /* RecordEval.3 */,
+ F96D3E8C08F272A6004A47F5 /* RegConfig.3 */,
+ F96D3E8D08F272A6004A47F5 /* RegExp.3 */,
+ F96D3E8E08F272A6004A47F5 /* regexp.n */,
+ F96D3E8F08F272A6004A47F5 /* registry.n */,
+ F96D3E9008F272A6004A47F5 /* regsub.n */,
+ F96D3E9108F272A6004A47F5 /* rename.n */,
+ F96D3E9208F272A6004A47F5 /* return.n */,
+ F96D3E9308F272A6004A47F5 /* safe.n */,
+ F96D3E9408F272A6004A47F5 /* SaveResult.3 */,
+ F96D3E9508F272A6004A47F5 /* scan.n */,
+ F96D3E9608F272A6004A47F5 /* seek.n */,
+ F93599D80DF1F98300E04F67 /* self.n */,
+ F96D3E9708F272A6004A47F5 /* set.n */,
+ F96D3E9808F272A6004A47F5 /* SetChanErr.3 */,
+ F96D3E9908F272A6004A47F5 /* SetErrno.3 */,
+ F96D3E9A08F272A6004A47F5 /* SetRecLmt.3 */,
+ F96D3E9B08F272A7004A47F5 /* SetResult.3 */,
+ F96D3E9C08F272A7004A47F5 /* SetVar.3 */,
+ F96D3E9D08F272A7004A47F5 /* Signal.3 */,
+ F96D3E9E08F272A7004A47F5 /* Sleep.3 */,
+ F96D3E9F08F272A7004A47F5 /* socket.n */,
+ F96D3EA008F272A7004A47F5 /* source.n */,
+ F96D3EA108F272A7004A47F5 /* SourceRCFile.3 */,
+ F96D3EA208F272A7004A47F5 /* split.n */,
+ F96D3EA308F272A7004A47F5 /* SplitList.3 */,
+ F96D3EA408F272A7004A47F5 /* SplitPath.3 */,
+ F96D3EA508F272A7004A47F5 /* StaticPkg.3 */,
+ F96D3EA608F272A7004A47F5 /* StdChannels.3 */,
+ F96D3EA708F272A7004A47F5 /* string.n */,
+ F96D3EA808F272A7004A47F5 /* StringObj.3 */,
+ F96D3EA908F272A7004A47F5 /* StrMatch.3 */,
+ F96D3EAA08F272A7004A47F5 /* subst.n */,
+ F96D3EAB08F272A7004A47F5 /* SubstObj.3 */,
+ F96D3EAC08F272A7004A47F5 /* switch.n */,
+ F974D5760FBE7E1900BF728B /* tailcall.n */,
+ F96D3EAD08F272A7004A47F5 /* Tcl.n */,
+ F99D61180EF5573A00BBFE01 /* TclZlib.3 */,
+ F96D3EAE08F272A7004A47F5 /* Tcl_Main.3 */,
+ F96D3EAF08F272A7004A47F5 /* TCL_MEM_DEBUG.3 */,
+ F96D3EB008F272A7004A47F5 /* tclsh.1 */,
+ F96D3EB108F272A7004A47F5 /* tcltest.n */,
+ F96D3EB208F272A7004A47F5 /* tclvars.n */,
+ F96D3EB308F272A7004A47F5 /* tell.n */,
+ F96D3EB408F272A7004A47F5 /* Thread.3 */,
+ F9183E640EFC80CD0030B814 /* throw.n */,
+ F96D3EB508F272A7004A47F5 /* time.n */,
+ F96D3EB608F272A7004A47F5 /* tm.n */,
+ F96D3EB708F272A7004A47F5 /* ToUpper.3 */,
+ F96D3EB808F272A7004A47F5 /* trace.n */,
+ F96D3EB908F272A7004A47F5 /* TraceCmd.3 */,
+ F96D3EBA08F272A7004A47F5 /* TraceVar.3 */,
+ F96D3EBB08F272A7004A47F5 /* Translate.3 */,
+ F9183E650EFC80D70030B814 /* try.n */,
+ F96D3EBC08F272A7004A47F5 /* UniCharIsAlpha.3 */,
+ F96D3EBD08F272A7004A47F5 /* unknown.n */,
+ F96D3EBE08F272A7004A47F5 /* unload.n */,
+ F96D3EBF08F272A7004A47F5 /* unset.n */,
+ F96D3EC008F272A7004A47F5 /* update.n */,
+ F96D3EC108F272A7004A47F5 /* uplevel.n */,
+ F96D3EC208F272A7004A47F5 /* UpVar.3 */,
+ F96D3EC308F272A7004A47F5 /* upvar.n */,
+ F96D3EC408F272A7004A47F5 /* Utf.3 */,
+ F96D3EC508F272A7004A47F5 /* variable.n */,
+ F96D3EC608F272A7004A47F5 /* vwait.n */,
+ F96D3EC708F272A7004A47F5 /* while.n */,
+ F96D3EC808F272A7004A47F5 /* WrongNumArgs.3 */,
+ F915432D0EF201EE0032D1E8 /* zlib.n */,
+ );
+ path = doc;
+ sourceTree = "<group>";
+ };
+ F96D3EC908F272A7004A47F5 /* generic */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3ECA08F272A7004A47F5 /* README */,
+ F96D3ECB08F272A7004A47F5 /* regc_color.c */,
+ F96D3ECC08F272A7004A47F5 /* regc_cvec.c */,
+ F96D3ECD08F272A7004A47F5 /* regc_lex.c */,
+ F96D3ECE08F272A7004A47F5 /* regc_locale.c */,
+ F96D3ECF08F272A7004A47F5 /* regc_nfa.c */,
+ F96D3ED008F272A7004A47F5 /* regcomp.c */,
+ F96D3ED108F272A7004A47F5 /* regcustom.h */,
+ F96D3ED208F272A7004A47F5 /* rege_dfa.c */,
+ F96D3ED308F272A7004A47F5 /* regerror.c */,
+ F96D3ED408F272A7004A47F5 /* regerrs.h */,
+ F96D3ED508F272A7004A47F5 /* regex.h */,
+ F96D3ED608F272A7004A47F5 /* regexec.c */,
+ F96D3ED708F272A7004A47F5 /* regfree.c */,
+ F96D3ED808F272A7004A47F5 /* regfronts.c */,
+ F96D3ED908F272A7004A47F5 /* regguts.h */,
+ F96D3EDA08F272A7004A47F5 /* tcl.decls */,
+ F96D3EDB08F272A7004A47F5 /* tcl.h */,
+ F96D3EDC08F272A7004A47F5 /* tclAlloc.c */,
+ F96D3EDD08F272A7004A47F5 /* tclAsync.c */,
+ F96D3EDE08F272A7004A47F5 /* tclBasic.c */,
+ F96D3EDF08F272A7004A47F5 /* tclBinary.c */,
+ F96D3EE008F272A7004A47F5 /* tclCkalloc.c */,
+ F96D3EE108F272A7004A47F5 /* tclClock.c */,
+ F96D3EE208F272A7004A47F5 /* tclCmdAH.c */,
+ F96D3EE308F272A7004A47F5 /* tclCmdIL.c */,
+ F96D3EE408F272A7004A47F5 /* tclCmdMZ.c */,
+ F96D3EE508F272A7004A47F5 /* tclCompCmds.c */,
+ F96D3EE608F272A7004A47F5 /* tclCompExpr.c */,
+ F96D3EE708F272A7004A47F5 /* tclCompile.c */,
+ F96D3EE808F272A7004A47F5 /* tclCompile.h */,
+ F96D3EE908F272A7004A47F5 /* tclConfig.c */,
+ F96D3EEA08F272A7004A47F5 /* tclDate.c */,
+ F96D3EEB08F272A7004A47F5 /* tclDecls.h */,
+ F96D3EEC08F272A7004A47F5 /* tclDictObj.c */,
+ F9F4415D0C8BAE6F00BCCD67 /* tclDTrace.d */,
+ F96D3EED08F272A7004A47F5 /* tclEncoding.c */,
+ F96D3EEE08F272A7004A47F5 /* tclEnv.c */,
+ F96D3EEF08F272A7004A47F5 /* tclEvent.c */,
+ F96D3EF008F272A7004A47F5 /* tclExecute.c */,
+ F96D3EF108F272A7004A47F5 /* tclFCmd.c */,
+ F96D3EF208F272A7004A47F5 /* tclFileName.c */,
+ F96D3EF308F272A7004A47F5 /* tclFileSystem.h */,
+ F96D3EF408F272A7004A47F5 /* tclGet.c */,
+ F96D3EF508F272A7004A47F5 /* tclGetDate.y */,
+ F96D3EF608F272A7004A47F5 /* tclHash.c */,
+ F96D3EF708F272A7004A47F5 /* tclHistory.c */,
+ F96D3EF808F272A7004A47F5 /* tclIndexObj.c */,
+ F96D3EF908F272A7004A47F5 /* tclInt.decls */,
+ F96D3EFA08F272A7004A47F5 /* tclInt.h */,
+ F96D3EFB08F272A7004A47F5 /* tclIntDecls.h */,
+ F96D3EFC08F272A7004A47F5 /* tclInterp.c */,
+ F96D3EFD08F272A7004A47F5 /* tclIntPlatDecls.h */,
+ F96D3EFE08F272A7004A47F5 /* tclIO.c */,
+ F96D3EFF08F272A7004A47F5 /* tclIO.h */,
+ F96D3F0008F272A7004A47F5 /* tclIOCmd.c */,
+ F96D3F0108F272A7004A47F5 /* tclIOGT.c */,
+ F96D3F0208F272A7004A47F5 /* tclIORChan.c */,
+ F95D77E90DFD820D00A8BF6F /* tclIORTrans.c */,
+ F96D3F0308F272A7004A47F5 /* tclIOSock.c */,
+ F96D3F0408F272A7004A47F5 /* tclIOUtil.c */,
+ F96D3F0508F272A7004A47F5 /* tclLink.c */,
+ F96D3F0608F272A7004A47F5 /* tclListObj.c */,
+ F96D3F0708F272A7004A47F5 /* tclLiteral.c */,
+ F96D3F0808F272A7004A47F5 /* tclLoad.c */,
+ F96D3F0908F272A7004A47F5 /* tclLoadNone.c */,
+ F96D3F0A08F272A7004A47F5 /* tclMain.c */,
+ F96D3F0B08F272A7004A47F5 /* tclNamesp.c */,
+ F96D3F0C08F272A7004A47F5 /* tclNotify.c */,
+ F96D3F0D08F272A7004A47F5 /* tclObj.c */,
+ F93599B20DF1F75400E04F67 /* tclOO.c */,
+ F93599B40DF1F75900E04F67 /* tclOO.decls */,
+ F93599B50DF1F75D00E04F67 /* tclOO.h */,
+ F93599B60DF1F76100E04F67 /* tclOOBasic.c */,
+ F93599B80DF1F76600E04F67 /* tclOOCall.c */,
+ F93599BA0DF1F76A00E04F67 /* tclOODecls.h */,
+ F93599BB0DF1F77000E04F67 /* tclOODefineCmds.c */,
+ F93599BD0DF1F77400E04F67 /* tclOOInfo.c */,
+ F93599BF0DF1F77900E04F67 /* tclOOInt.h */,
+ F93599C00DF1F77D00E04F67 /* tclOOIntDecls.h */,
+ F93599C10DF1F78300E04F67 /* tclOOMethod.c */,
+ F93599C30DF1F78800E04F67 /* tclOOStubInit.c */,
+ F93599C50DF1F78D00E04F67 /* tclOOStubLib.c */,
+ F96D3F0E08F272A7004A47F5 /* tclPanic.c */,
+ F96D3F0F08F272A7004A47F5 /* tclParse.c */,
+ F96D3F1108F272A7004A47F5 /* tclPathObj.c */,
+ F96D3F1208F272A7004A47F5 /* tclPipe.c */,
+ F96D3F1308F272A7004A47F5 /* tclPkg.c */,
+ F96D3F1408F272A7004A47F5 /* tclPkgConfig.c */,
+ F96D3F1508F272A7004A47F5 /* tclPlatDecls.h */,
+ F96D3F1608F272A7004A47F5 /* tclPort.h */,
+ F96D3F1708F272A7004A47F5 /* tclPosixStr.c */,
+ F96D3F1808F272A7004A47F5 /* tclPreserve.c */,
+ F96D3F1908F272A7004A47F5 /* tclProc.c */,
+ F96D3F1A08F272A7004A47F5 /* tclRegexp.c */,
+ F96D3F1B08F272A7004A47F5 /* tclRegexp.h */,
+ F96D3F1C08F272A7004A47F5 /* tclResolve.c */,
+ F96D3F1D08F272A7004A47F5 /* tclResult.c */,
+ F96D3F1E08F272A7004A47F5 /* tclScan.c */,
+ F96D3F1F08F272A7004A47F5 /* tclStringObj.c */,
+ F96D3F2408F272A7004A47F5 /* tclStrToD.c */,
+ F96D3F2508F272A7004A47F5 /* tclStubInit.c */,
+ F96D3F2608F272A7004A47F5 /* tclStubLib.c */,
+ F96D3F2708F272A7004A47F5 /* tclTest.c */,
+ F96D3F2808F272A7004A47F5 /* tclTestObj.c */,
+ F96D3F2908F272A7004A47F5 /* tclTestProcBodyObj.c */,
+ F96D3F2A08F272A7004A47F5 /* tclThread.c */,
+ F96D3F2B08F272A7004A47F5 /* tclThreadAlloc.c */,
+ F96D3F2C08F272A7004A47F5 /* tclThreadJoin.c */,
+ F96D3F2D08F272A7004A47F5 /* tclThreadStorage.c */,
+ F96D3F2E08F272A7004A47F5 /* tclThreadTest.c */,
+ F96D3F2F08F272A7004A47F5 /* tclTimer.c */,
+ F9903CAF094FAADA004613E9 /* tclTomMath.decls */,
+ F96D3F3008F272A7004A47F5 /* tclTomMath.h */,
+ F9903CB0094FAADA004613E9 /* tclTomMathDecls.h */,
+ F96D3F3108F272A7004A47F5 /* tclTomMathInterface.c */,
+ F96D3F3208F272A7004A47F5 /* tclTrace.c */,
+ F96D3F3308F272A7004A47F5 /* tclUniData.c */,
+ F96D3F3408F272A7004A47F5 /* tclUtf.c */,
+ F96D3F3508F272A7004A47F5 /* tclUtil.c */,
+ F96D3F3608F272A7004A47F5 /* tclVar.c */,
+ F96437C90EF0D4B2003F468E /* tclZlib.c */,
+ F96D3F3708F272A7004A47F5 /* tommath.h */,
+ );
+ path = generic;
+ sourceTree = "<group>";
+ };
+ F96D3F3808F272A7004A47F5 /* library */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3F3908F272A8004A47F5 /* auto.tcl */,
+ F96D3F3A08F272A8004A47F5 /* clock.tcl */,
+ F96D3F3B08F272A8004A47F5 /* dde */,
+ F96D3F8C08F272A8004A47F5 /* history.tcl */,
+ F96D3F8D08F272A8004A47F5 /* http */,
+ F96D3F9008F272A8004A47F5 /* http1.0 */,
+ F96D3F9308F272A8004A47F5 /* init.tcl */,
+ F96D3F9408F272A8004A47F5 /* msgcat */,
+ F96D401708F272AA004A47F5 /* opt */,
+ F96D401A08F272AA004A47F5 /* package.tcl */,
+ F96D401B08F272AA004A47F5 /* parray.tcl */,
+ F9ECB1110B26521500A28025 /* platform */,
+ F96D401C08F272AA004A47F5 /* reg */,
+ F96D401E08F272AA004A47F5 /* safe.tcl */,
+ F96D401F08F272AA004A47F5 /* tclIndex */,
+ F96D402008F272AA004A47F5 /* tcltest */,
+ F96D402308F272AA004A47F5 /* tm.tcl */,
+ F96D425B08F272B2004A47F5 /* word.tcl */,
+ );
+ path = library;
+ sourceTree = "<group>";
+ };
+ F96D3F3B08F272A8004A47F5 /* dde */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3F3C08F272A8004A47F5 /* pkgIndex.tcl */,
+ );
+ path = dde;
+ sourceTree = "<group>";
+ };
+ F96D3F8D08F272A8004A47F5 /* http */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3F8E08F272A8004A47F5 /* http.tcl */,
+ F96D3F8F08F272A8004A47F5 /* pkgIndex.tcl */,
+ );
+ path = http;
+ sourceTree = "<group>";
+ };
+ F96D3F9008F272A8004A47F5 /* http1.0 */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3F9108F272A8004A47F5 /* http.tcl */,
+ F96D3F9208F272A8004A47F5 /* pkgIndex.tcl */,
+ );
+ path = http1.0;
+ sourceTree = "<group>";
+ };
+ F96D3F9408F272A8004A47F5 /* msgcat */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3F9508F272A8004A47F5 /* msgcat.tcl */,
+ F96D3F9608F272A8004A47F5 /* pkgIndex.tcl */,
+ );
+ path = msgcat;
+ sourceTree = "<group>";
+ };
+ F96D401708F272AA004A47F5 /* opt */ = {
+ isa = PBXGroup;
+ children = (
+ F96D401808F272AA004A47F5 /* optparse.tcl */,
+ F96D401908F272AA004A47F5 /* pkgIndex.tcl */,
+ );
+ path = opt;
+ sourceTree = "<group>";
+ };
+ F96D401C08F272AA004A47F5 /* reg */ = {
+ isa = PBXGroup;
+ children = (
+ F96D401D08F272AA004A47F5 /* pkgIndex.tcl */,
+ );
+ path = reg;
+ sourceTree = "<group>";
+ };
+ F96D402008F272AA004A47F5 /* tcltest */ = {
+ isa = PBXGroup;
+ children = (
+ F96D402108F272AA004A47F5 /* pkgIndex.tcl */,
+ F96D402208F272AA004A47F5 /* tcltest.tcl */,
+ );
+ path = tcltest;
+ sourceTree = "<group>";
+ };
+ F96D425C08F272B2004A47F5 /* libtommath */ = {
+ isa = PBXGroup;
+ children = (
+ F96D426408F272B3004A47F5 /* bn_fast_s_mp_mul_digs.c */,
+ F96D426608F272B3004A47F5 /* bn_fast_s_mp_sqr.c */,
+ F96D426908F272B3004A47F5 /* bn_mp_add.c */,
+ F96D426A08F272B3004A47F5 /* bn_mp_add_d.c */,
+ F96D426C08F272B3004A47F5 /* bn_mp_and.c */,
+ F96D426D08F272B3004A47F5 /* bn_mp_clamp.c */,
+ F96D426E08F272B3004A47F5 /* bn_mp_clear.c */,
+ F96D426F08F272B3004A47F5 /* bn_mp_clear_multi.c */,
+ F96D427008F272B3004A47F5 /* bn_mp_cmp.c */,
+ F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */,
+ F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */,
+ F96D427408F272B3004A47F5 /* bn_mp_copy.c */,
+ F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */,
+ F96D427608F272B3004A47F5 /* bn_mp_div.c */,
+ F96D427708F272B3004A47F5 /* bn_mp_div_2.c */,
+ F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */,
+ F96D427908F272B3004A47F5 /* bn_mp_div_3.c */,
+ F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */,
+ F96D427E08F272B3004A47F5 /* bn_mp_exch.c */,
+ F96D427F08F272B3004A47F5 /* bn_mp_expt_d.c */,
+ F96D428708F272B3004A47F5 /* bn_mp_grow.c */,
+ F96D428808F272B3004A47F5 /* bn_mp_init.c */,
+ F96D428908F272B3004A47F5 /* bn_mp_init_copy.c */,
+ F96D428A08F272B3004A47F5 /* bn_mp_init_multi.c */,
+ F96D428B08F272B3004A47F5 /* bn_mp_init_set.c */,
+ F96D428D08F272B3004A47F5 /* bn_mp_init_size.c */,
+ F96D429208F272B3004A47F5 /* bn_mp_karatsuba_mul.c */,
+ F96D429308F272B3004A47F5 /* bn_mp_karatsuba_sqr.c */,
+ F96D429508F272B3004A47F5 /* bn_mp_lshd.c */,
+ F96D429608F272B3004A47F5 /* bn_mp_mod.c */,
+ F96D429708F272B3004A47F5 /* bn_mp_mod_2d.c */,
+ F96D429C08F272B3004A47F5 /* bn_mp_mul.c */,
+ F96D429D08F272B3004A47F5 /* bn_mp_mul_2.c */,
+ F96D429E08F272B3004A47F5 /* bn_mp_mul_2d.c */,
+ F96D429F08F272B3004A47F5 /* bn_mp_mul_d.c */,
+ F96D42A208F272B3004A47F5 /* bn_mp_neg.c */,
+ F96D42A308F272B3004A47F5 /* bn_mp_or.c */,
+ F96D42AB08F272B3004A47F5 /* bn_mp_radix_size.c */,
+ F96D42AC08F272B3004A47F5 /* bn_mp_radix_smap.c */,
+ F96D42AE08F272B3004A47F5 /* bn_mp_read_radix.c */,
+ F96D42B908F272B3004A47F5 /* bn_mp_rshd.c */,
+ F96D42BA08F272B3004A47F5 /* bn_mp_set.c */,
+ F96D42BC08F272B3004A47F5 /* bn_mp_shrink.c */,
+ F96D42BE08F272B3004A47F5 /* bn_mp_sqr.c */,
+ F96D42C008F272B3004A47F5 /* bn_mp_sqrt.c */,
+ F96D42C108F272B3004A47F5 /* bn_mp_sub.c */,
+ F96D42C208F272B3004A47F5 /* bn_mp_sub_d.c */,
+ F96D42C608F272B3004A47F5 /* bn_mp_to_unsigned_bin.c */,
+ F96D42C708F272B3004A47F5 /* bn_mp_to_unsigned_bin_n.c */,
+ F96D42C808F272B3004A47F5 /* bn_mp_toom_mul.c */,
+ F96D42C908F272B3004A47F5 /* bn_mp_toom_sqr.c */,
+ F96D42CB08F272B3004A47F5 /* bn_mp_toradix_n.c */,
+ F96D42CC08F272B3004A47F5 /* bn_mp_unsigned_bin_size.c */,
+ F96D42CD08F272B3004A47F5 /* bn_mp_xor.c */,
+ F96D42CE08F272B3004A47F5 /* bn_mp_zero.c */,
+ F96D42D008F272B3004A47F5 /* bn_reverse.c */,
+ F96D42D108F272B3004A47F5 /* bn_s_mp_add.c */,
+ F96D42D308F272B3004A47F5 /* bn_s_mp_mul_digs.c */,
+ F96D42D508F272B3004A47F5 /* bn_s_mp_sqr.c */,
+ F96D42D608F272B3004A47F5 /* bn_s_mp_sub.c */,
+ F96D42D708F272B3004A47F5 /* bncore.c */,
+ F96D432908F272B4004A47F5 /* tommath_class.h */,
+ F96D432A08F272B4004A47F5 /* tommath_superclass.h */,
+ );
+ path = libtommath;
+ sourceTree = "<group>";
+ };
+ F96D432C08F272B4004A47F5 /* macosx */ = {
+ isa = PBXGroup;
+ children = (
+ F96D432E08F272B5004A47F5 /* configure.ac */,
+ F96D432F08F272B5004A47F5 /* GNUmakefile */,
+ F96D433108F272B5004A47F5 /* README */,
+ F96D433908F272B5004A47F5 /* tclMacOSXBundle.c */,
+ F96D433D08F272B5004A47F5 /* tclMacOSXFCmd.c */,
+ F96D433E08F272B5004A47F5 /* tclMacOSXNotify.c */,
+ F96D433208F272B5004A47F5 /* Tcl-Info.plist.in */,
+ F91E62260C1AE686006C9D96 /* Tclsh-Info.plist.in */,
+ );
+ path = macosx;
+ sourceTree = "<group>";
+ };
+ F96D434408F272B5004A47F5 /* tests */ = {
+ isa = PBXGroup;
+ children = (
+ F96D434508F272B5004A47F5 /* all.tcl */,
+ F96D434608F272B5004A47F5 /* append.test */,
+ F96D434708F272B5004A47F5 /* appendComp.test */,
+ F9ECB1CA0B2652D300A28025 /* apply.test */,
+ F96D434808F272B5004A47F5 /* assocd.test */,
+ F96D434908F272B5004A47F5 /* async.test */,
+ F96D434A08F272B5004A47F5 /* autoMkindex.test */,
+ F96D434B08F272B5004A47F5 /* basic.test */,
+ F96D434C08F272B5004A47F5 /* binary.test */,
+ F96D434D08F272B5004A47F5 /* case.test */,
+ F96D434E08F272B5004A47F5 /* chan.test */,
+ F9A493240CEBF38300B78AE2 /* chanio.test */,
+ F96D434F08F272B5004A47F5 /* clock.test */,
+ F96D435008F272B5004A47F5 /* cmdAH.test */,
+ F96D435108F272B5004A47F5 /* cmdIL.test */,
+ F96D435208F272B5004A47F5 /* cmdInfo.test */,
+ F96D435308F272B5004A47F5 /* cmdMZ.test */,
+ F96D435408F272B5004A47F5 /* compExpr-old.test */,
+ F96D435508F272B5004A47F5 /* compExpr.test */,
+ F96D435608F272B5004A47F5 /* compile.test */,
+ F96D435708F272B5004A47F5 /* concat.test */,
+ F96D435808F272B5004A47F5 /* config.test */,
+ F974D5770FBE7E6100BF728B /* coroutine.test */,
+ F96D435908F272B5004A47F5 /* dcall.test */,
+ F96D435A08F272B5004A47F5 /* dict.test */,
+ F96D435C08F272B5004A47F5 /* dstring.test */,
+ F96D435E08F272B5004A47F5 /* encoding.test */,
+ F96D435F08F272B5004A47F5 /* env.test */,
+ F96D436008F272B5004A47F5 /* error.test */,
+ F96D436108F272B5004A47F5 /* eval.test */,
+ F96D436208F272B5004A47F5 /* event.test */,
+ F96D436308F272B5004A47F5 /* exec.test */,
+ F96D436408F272B5004A47F5 /* execute.test */,
+ F96D436508F272B5004A47F5 /* expr-old.test */,
+ F96D436608F272B5004A47F5 /* expr.test */,
+ F96D436708F272B6004A47F5 /* fCmd.test */,
+ F96D436808F272B6004A47F5 /* fileName.test */,
+ F96D436908F272B6004A47F5 /* fileSystem.test */,
+ F96D436A08F272B6004A47F5 /* for-old.test */,
+ F96D436B08F272B6004A47F5 /* for.test */,
+ F96D436C08F272B6004A47F5 /* foreach.test */,
+ F96D436D08F272B6004A47F5 /* format.test */,
+ F96D436E08F272B6004A47F5 /* get.test */,
+ F96D436F08F272B6004A47F5 /* history.test */,
+ F96D437008F272B6004A47F5 /* http.test */,
+ F974D56C0FBE7D6300BF728B /* http11.test */,
+ F96D437108F272B6004A47F5 /* httpd */,
+ F974D56D0FBE7D6300BF728B /* httpd11.tcl */,
+ F96D437208F272B6004A47F5 /* httpold.test */,
+ F96D437308F272B6004A47F5 /* if-old.test */,
+ F96D437408F272B6004A47F5 /* if.test */,
+ F96D437508F272B6004A47F5 /* incr-old.test */,
+ F96D437608F272B6004A47F5 /* incr.test */,
+ F96D437708F272B6004A47F5 /* indexObj.test */,
+ F96D437808F272B6004A47F5 /* info.test */,
+ F96D437908F272B6004A47F5 /* init.test */,
+ F96D437A08F272B6004A47F5 /* interp.test */,
+ F96D437B08F272B6004A47F5 /* io.test */,
+ F96D437C08F272B6004A47F5 /* ioCmd.test */,
+ F96D437D08F272B6004A47F5 /* iogt.test */,
+ F96D437F08F272B6004A47F5 /* join.test */,
+ F96D438008F272B6004A47F5 /* lindex.test */,
+ F96D438108F272B6004A47F5 /* link.test */,
+ F96D438208F272B6004A47F5 /* linsert.test */,
+ F96D438308F272B6004A47F5 /* list.test */,
+ F96D438408F272B6004A47F5 /* listObj.test */,
+ F96D438508F272B6004A47F5 /* llength.test */,
+ F96D438608F272B6004A47F5 /* load.test */,
+ F96D438708F272B6004A47F5 /* lrange.test */,
+ F96D438808F272B6004A47F5 /* lrepeat.test */,
+ F96D438908F272B6004A47F5 /* lreplace.test */,
+ F96D438A08F272B6004A47F5 /* lsearch.test */,
+ F96D438B08F272B6004A47F5 /* lset.test */,
+ F96D438C08F272B6004A47F5 /* lsetComp.test */,
+ F96D438D08F272B6004A47F5 /* macOSXFCmd.test */,
+ F95FAFF90B34F1130072E431 /* macOSXLoad.test */,
+ F96D438E08F272B6004A47F5 /* main.test */,
+ F9ECB1CB0B26534C00A28025 /* mathop.test */,
+ F96D438F08F272B6004A47F5 /* misc.test */,
+ F96D439008F272B6004A47F5 /* msgcat.test */,
+ F96D439108F272B6004A47F5 /* namespace-old.test */,
+ F96D439208F272B7004A47F5 /* namespace.test */,
+ F96D439308F272B7004A47F5 /* notify.test */,
+ F91DC23C0E44C51B002CB8D1 /* nre.test */,
+ F96D439408F272B7004A47F5 /* obj.test */,
+ F93599C80DF1F81900E04F67 /* oo.test */,
+ F96D439508F272B7004A47F5 /* opt.test */,
+ F96D439608F272B7004A47F5 /* package.test */,
+ F96D439708F272B7004A47F5 /* parse.test */,
+ F96D439808F272B7004A47F5 /* parseExpr.test */,
+ F96D439908F272B7004A47F5 /* parseOld.test */,
+ F96D439A08F272B7004A47F5 /* pid.test */,
+ F96D439B08F272B7004A47F5 /* pkg.test */,
+ F96D439C08F272B7004A47F5 /* pkgMkIndex.test */,
+ F96D439D08F272B7004A47F5 /* platform.test */,
+ F96D439E08F272B7004A47F5 /* proc-old.test */,
+ F96D439F08F272B7004A47F5 /* proc.test */,
+ F96D43A008F272B7004A47F5 /* pwd.test */,
+ F96D43A108F272B7004A47F5 /* README */,
+ F96D43A208F272B7004A47F5 /* reg.test */,
+ F96D43A308F272B7004A47F5 /* regexp.test */,
+ F96D43A408F272B7004A47F5 /* regexpComp.test */,
+ F96D43A508F272B7004A47F5 /* registry.test */,
+ F96D43A608F272B7004A47F5 /* remote.tcl */,
+ F96D43A708F272B7004A47F5 /* rename.test */,
+ F96D43A808F272B7004A47F5 /* result.test */,
+ F96D43A908F272B7004A47F5 /* safe.test */,
+ F96D43AA08F272B7004A47F5 /* scan.test */,
+ F96D43AB08F272B7004A47F5 /* security.test */,
+ F96D43AC08F272B7004A47F5 /* set-old.test */,
+ F96D43AD08F272B7004A47F5 /* set.test */,
+ F96D43AE08F272B7004A47F5 /* socket.test */,
+ F96D43AF08F272B7004A47F5 /* source.test */,
+ F96D43B008F272B7004A47F5 /* split.test */,
+ F96D43B108F272B7004A47F5 /* stack.test */,
+ F96D43B208F272B7004A47F5 /* string.test */,
+ F96D43B308F272B7004A47F5 /* stringComp.test */,
+ F96D43B408F272B7004A47F5 /* stringObj.test */,
+ F96D43B508F272B7004A47F5 /* subst.test */,
+ F96D43B608F272B7004A47F5 /* switch.test */,
+ F974D5780FBE7E6100BF728B /* tailcall.test */,
+ F96D43B708F272B7004A47F5 /* tcltest.test */,
+ F96D43B808F272B7004A47F5 /* thread.test */,
+ F96D43B908F272B7004A47F5 /* timer.test */,
+ F96D43BA08F272B7004A47F5 /* tm.test */,
+ F96D43BB08F272B7004A47F5 /* trace.test */,
+ F96D43BC08F272B7004A47F5 /* unixFCmd.test */,
+ F96D43BD08F272B7004A47F5 /* unixFile.test */,
+ F96D43BE08F272B7004A47F5 /* unixInit.test */,
+ F96D43BF08F272B7004A47F5 /* unixNotfy.test */,
+ F96D43C008F272B7004A47F5 /* unknown.test */,
+ F96D43C108F272B7004A47F5 /* unload.test */,
+ F96D43C208F272B7004A47F5 /* uplevel.test */,
+ F96D43C308F272B7004A47F5 /* upvar.test */,
+ F96D43C408F272B7004A47F5 /* utf.test */,
+ F96D43C508F272B7004A47F5 /* util.test */,
+ F96D43C608F272B7004A47F5 /* var.test */,
+ F96D43C708F272B7004A47F5 /* while-old.test */,
+ F96D43C808F272B7004A47F5 /* while.test */,
+ F96D43C908F272B7004A47F5 /* winConsole.test */,
+ F96D43CA08F272B7004A47F5 /* winDde.test */,
+ F96D43CB08F272B7004A47F5 /* winFCmd.test */,
+ F96D43CC08F272B7004A47F5 /* winFile.test */,
+ F96D43CD08F272B7004A47F5 /* winNotify.test */,
+ F96D43CE08F272B7004A47F5 /* winPipe.test */,
+ F96D43CF08F272B7004A47F5 /* winTime.test */,
+ F915432A0EF201CF0032D1E8 /* zlib.test */,
+ );
+ path = tests;
+ sourceTree = "<group>";
+ };
+ F96D43D008F272B8004A47F5 /* tools */ = {
+ isa = PBXGroup;
+ children = (
+ F96D43D108F272B8004A47F5 /* checkLibraryDoc.tcl */,
+ F96D43D208F272B8004A47F5 /* configure */,
+ F96D43D308F272B8004A47F5 /* configure.in */,
+ F96D442208F272B8004A47F5 /* eolFix.tcl */,
+ F96D442408F272B8004A47F5 /* fix_tommath_h.tcl */,
+ F96D442508F272B8004A47F5 /* genStubs.tcl */,
+ F96D442708F272B8004A47F5 /* index.tcl */,
+ F96D442808F272B8004A47F5 /* installData.tcl */,
+ F96D442908F272B8004A47F5 /* loadICU.tcl */,
+ F96D442A08F272B8004A47F5 /* Makefile.in */,
+ F96D442B08F272B8004A47F5 /* makeTestCases.tcl */,
+ F96D442C08F272B8004A47F5 /* man2help.tcl */,
+ F96D442D08F272B8004A47F5 /* man2help2.tcl */,
+ F96D442E08F272B8004A47F5 /* man2html.tcl */,
+ F96D442F08F272B8004A47F5 /* man2html1.tcl */,
+ F96D443008F272B8004A47F5 /* man2html2.tcl */,
+ F96D443108F272B8004A47F5 /* man2tcl.c */,
+ F96D443208F272B8004A47F5 /* README */,
+ F96D443308F272B8004A47F5 /* regexpTestLib.tcl */,
+ F96D443508F272B8004A47F5 /* tcl.hpj.in */,
+ F96D443608F272B8004A47F5 /* tcl.wse.in */,
+ F96D443908F272B9004A47F5 /* tcltk-man2html.tcl */,
+ F96D443A08F272B9004A47F5 /* tclZIC.tcl */,
+ F92D7F100DE777240033A13A /* tsdPerf.tcl */,
+ F96D443B08F272B9004A47F5 /* uniClass.tcl */,
+ F96D443C08F272B9004A47F5 /* uniParse.tcl */,
+ );
+ path = tools;
+ sourceTree = "<group>";
+ };
+ F96D443E08F272B9004A47F5 /* unix */ = {
+ isa = PBXGroup;
+ children = (
+ F96D444008F272B9004A47F5 /* aclocal.m4 */,
+ F96D444108F272B9004A47F5 /* configure */,
+ F96D444208F272B9004A47F5 /* configure.in */,
+ F96D444308F272B9004A47F5 /* dltest */,
+ F96D444D08F272B9004A47F5 /* install-sh */,
+ F96D444E08F272B9004A47F5 /* installManPage */,
+ F96D444F08F272B9004A47F5 /* ldAix */,
+ F96D445008F272B9004A47F5 /* Makefile.in */,
+ F96D445208F272B9004A47F5 /* README */,
+ F96D445308F272B9004A47F5 /* tcl.m4 */,
+ F974D5790FBE7E9C00BF728B /* tcl.pc.in */,
+ F96D445408F272B9004A47F5 /* tcl.spec */,
+ F96D445508F272B9004A47F5 /* tclAppInit.c */,
+ F96D445608F272B9004A47F5 /* tclConfig.h.in */,
+ F96D445708F272B9004A47F5 /* tclConfig.sh.in */,
+ F96D445808F272B9004A47F5 /* tclLoadAix.c */,
+ F96D445908F272B9004A47F5 /* tclLoadDl.c */,
+ F96D445B08F272B9004A47F5 /* tclLoadDyld.c */,
+ F96D445C08F272B9004A47F5 /* tclLoadNext.c */,
+ F96D445D08F272B9004A47F5 /* tclLoadOSF.c */,
+ F96D445E08F272B9004A47F5 /* tclLoadShl.c */,
+ F96D445F08F272B9004A47F5 /* tclUnixChan.c */,
+ F9FC77B70AB29E9100B7077D /* tclUnixCompat.c */,
+ F96D446008F272B9004A47F5 /* tclUnixEvent.c */,
+ F96D446108F272B9004A47F5 /* tclUnixFCmd.c */,
+ F96D446208F272B9004A47F5 /* tclUnixFile.c */,
+ F96D446308F272B9004A47F5 /* tclUnixInit.c */,
+ F96D446408F272B9004A47F5 /* tclUnixNotfy.c */,
+ F96D446508F272B9004A47F5 /* tclUnixPipe.c */,
+ F96D446608F272B9004A47F5 /* tclUnixPort.h */,
+ F96D446708F272B9004A47F5 /* tclUnixSock.c */,
+ F96D446808F272B9004A47F5 /* tclUnixTest.c */,
+ F96D446908F272B9004A47F5 /* tclUnixThrd.c */,
+ F96D446A08F272B9004A47F5 /* tclUnixThrd.h */,
+ F96D446B08F272B9004A47F5 /* tclUnixTime.c */,
+ F96D446C08F272B9004A47F5 /* tclXtNotify.c */,
+ F96D446D08F272B9004A47F5 /* tclXtTest.c */,
+ );
+ path = unix;
+ sourceTree = "<group>";
+ };
+ F96D444308F272B9004A47F5 /* dltest */ = {
+ isa = PBXGroup;
+ children = (
+ F96D444408F272B9004A47F5 /* Makefile.in */,
+ F96D444508F272B9004A47F5 /* pkga.c */,
+ F96D444608F272B9004A47F5 /* pkgb.c */,
+ F96D444708F272B9004A47F5 /* pkgc.c */,
+ F96D444808F272B9004A47F5 /* pkgd.c */,
+ F96D444908F272B9004A47F5 /* pkge.c */,
+ F96D444B08F272B9004A47F5 /* pkgua.c */,
+ F96D444C08F272B9004A47F5 /* README */,
+ );
+ path = dltest;
+ sourceTree = "<group>";
+ };
+ F96D446E08F272B9004A47F5 /* win */ = {
+ isa = PBXGroup;
+ children = (
+ F96D447008F272BA004A47F5 /* aclocal.m4 */,
+ F96D447108F272BA004A47F5 /* buildall.vc.bat */,
+ F96D447208F272BA004A47F5 /* cat.c */,
+ F96D447408F272BA004A47F5 /* configure */,
+ F96D447508F272BA004A47F5 /* configure.in */,
+ F96D447708F272BA004A47F5 /* Makefile.in */,
+ F96D447808F272BA004A47F5 /* makefile.vc */,
+ F96D447908F272BA004A47F5 /* nmakehlp.c */,
+ F96D447A08F272BA004A47F5 /* README */,
+ F96D447C08F272BA004A47F5 /* rules.vc */,
+ F96D447D08F272BA004A47F5 /* stub16.c */,
+ F96D447E08F272BA004A47F5 /* tcl.dsp */,
+ F96D447F08F272BA004A47F5 /* tcl.dsw */,
+ F96D448008F272BA004A47F5 /* tcl.hpj.in */,
+ F96D448108F272BA004A47F5 /* tcl.m4 */,
+ F96D448208F272BA004A47F5 /* tcl.rc */,
+ F96D448308F272BA004A47F5 /* tclAppInit.c */,
+ F96D448408F272BA004A47F5 /* tclConfig.sh.in */,
+ F96D448608F272BA004A47F5 /* tclsh.rc */,
+ F96D448708F272BA004A47F5 /* tclWin32Dll.c */,
+ F96D448808F272BA004A47F5 /* tclWinChan.c */,
+ F96D448908F272BA004A47F5 /* tclWinConsole.c */,
+ F96D448A08F272BA004A47F5 /* tclWinDde.c */,
+ F96D448B08F272BA004A47F5 /* tclWinError.c */,
+ F96D448C08F272BA004A47F5 /* tclWinFCmd.c */,
+ F96D448D08F272BA004A47F5 /* tclWinFile.c */,
+ F96D448E08F272BA004A47F5 /* tclWinInit.c */,
+ F96D448F08F272BA004A47F5 /* tclWinInt.h */,
+ F96D449008F272BA004A47F5 /* tclWinLoad.c */,
+ F96D449108F272BA004A47F5 /* tclWinNotify.c */,
+ F96D449208F272BA004A47F5 /* tclWinPipe.c */,
+ F96D449308F272BA004A47F5 /* tclWinPort.h */,
+ F96D449408F272BA004A47F5 /* tclWinReg.c */,
+ F96D449508F272BA004A47F5 /* tclWinSerial.c */,
+ F96D449608F272BA004A47F5 /* tclWinSock.c */,
+ F96D449708F272BA004A47F5 /* tclWinTest.c */,
+ F96D449808F272BA004A47F5 /* tclWinThrd.c */,
+ F96D449908F272BA004A47F5 /* tclWinThrd.h */,
+ F96D449A08F272BA004A47F5 /* tclWinTime.c */,
+ );
+ path = win;
+ sourceTree = "<group>";
+ };
+ F9ECB1110B26521500A28025 /* platform */ = {
+ isa = PBXGroup;
+ children = (
+ F9ECB1120B26521500A28025 /* pkgIndex.tcl */,
+ F9ECB1130B26521500A28025 /* platform.tcl */,
+ F9ECB1140B26521500A28025 /* shell.tcl */,
+ );
+ path = platform;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 8DD76FA90486AB0100D96B5E /* tktest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = F95CC8B009158F3100EA5ACE /* Build configuration list for PBXNativeTarget "tktest" */;
+ buildPhases = (
+ F9A5C5F508F651A2008AE941 /* Configure Tcl */,
+ F9A5C5F608F651AB008AE941 /* Configure Tk */,
+ 8DD76FAB0486AB0100D96B5E /* Sources */,
+ 8DD76FAD0486AB0100D96B5E /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = tktest;
+ productInstallPath = "$(BINDIR)";
+ productName = tktest;
+ productReference = 8DD76FB20486AB0100D96B5E /* tktest */;
+ productType = "com.apple.product-type.tool";
+ };
+ F97258A50A86873C00096C78 /* tktest-X11 */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = F97258A80A86873D00096C78 /* Build configuration list for PBXNativeTarget "tktest-X11" */;
+ buildPhases = (
+ F9FD30B40CC1AD070073837D /* Configure Tcl */,
+ F9FD30B50CC1AD070073837D /* Configure Tk */,
+ F9FD30BB0CC1AD070073837D /* Sources */,
+ F9FD31E30CC1AD070073837D /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "tktest-X11";
+ productInstallPath = "$(BINDIR)";
+ productName = tktest;
+ productReference = F9FD31F40CC1AD070073837D /* tktest-X11 */;
+ productType = "com.apple.product-type.tool";
+ };
+ F9E61D16090A3E94002B3151 /* Tk */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = F95CC8AB09158F3100EA5ACE /* Build configuration list for PBXNativeTarget "Tk" */;
+ buildPhases = (
+ F97AF02F0B665DA900310EA2 /* Build Tk */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = Tk;
+ productName = Wish;
+ productReference = F9A3084B08F2D4CE00BAE1AB /* Wish.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 08FB7793FE84155DC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ BuildIndependentTargetsInParallel = YES;
+ };
+ buildConfigurationList = F95CC8B509158F3100EA5ACE /* Build configuration list for PBXProject "Tk" */;
+ compatibilityVersion = "Xcode 3.2";
+ hasScannedForEncodings = 1;
+ mainGroup = 08FB7794FE84155DC02AAC07 /* Tk */;
+ projectDirPath = "";
+ projectRoots = (
+ ..,
+ ../../tcl,
+ );
+ targets = (
+ F9E61D16090A3E94002B3151 /* Tk */,
+ 8DD76FA90486AB0100D96B5E /* tktest */,
+ F97258A50A86873C00096C78 /* tktest-X11 */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ F97AF02F0B665DA900310EA2 /* Build Tk */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "${TARGET_TEMP_DIR}/.none",
+ );
+ name = "Build Tk";
+ outputPaths = (
+ "${TARGET_BUILD_DIR}/${WRAPPER_NAME}",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/bash;
+ shellScript = "export CC=$(xcrun -find ${GCC} || echo ${GCC}); export LD=${CC}\ngnumake -C \"${TK_SRCROOT}/macosx\" -j \"$(sysctl -n hw.activecpu)\" \"$(echo \"${ACTION}\" | sed -e s/build// -e s/clean/distclean/ -e s/..\\*/\\&-/)${MAKE_TARGET}\" CFLAGS_WARNING=\"${WARNING_CFLAGS}\" CFLAGS_OPTIMIZE=\"-O${GCC_OPTIMIZATION_LEVEL}\" SYMROOT=\"${BUILT_PRODUCTS_DIR}\" OBJ_DIR=\"${OBJECT_FILE_DIR}\" INSTALL_ROOT=\"${DSTROOT}\" PREFIX=\"${PREFIX}\" BINDIR=\"${BINDIR}\" LIBDIR=\"${FRAMEWORK_INSTALL_PATH}\" MANDIR=\"${MANDIR}\" EXTRA_CONFIGURE_ARGS=\"${CONFIGURE_ARGS}\" APPLICATION_INSTALL_PATH=\"${APPLICATION_INSTALL_PATH}\" TCL_BUILD_DIR=\"${TCL_BUILD_DIR}\" TCL_FRAMEWORK_DIR=\"${TCL_FRAMEWORK_DIR}\" ${EXTRA_MAKE_FLAGS}\nresult=$?\nif [ -e \"${BUILT_PRODUCTS_DIR}/tktest\" ]; then\n\trm -f \"${BUILT_PRODUCTS_DIR}/tktest\"\nfi\necho \"Done\"\nrm -f \"${SCRIPT_INPUT_FILE_0}\"\nexit ${result}\n";
+ showEnvVarsInLog = 0;
+ };
+ F9A5C5F508F651A2008AE941 /* Configure Tcl */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "$(TCL_SRCROOT)/macosx/configure.ac",
+ "$(TCL_SRCROOT)/unix/configure.in",
+ "$(TCL_SRCROOT)/unix/tcl.m4",
+ "$(TCL_SRCROOT)/unix/aclocal.m4",
+ "$(TCL_SRCROOT)/unix/tclConfig.sh.in",
+ "$(TCL_SRCROOT)/unix/Makefile.in",
+ "$(TCL_SRCROOT)/unix/dltest/Makefile.in",
+ );
+ name = "Configure Tcl";
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/tcl/tclConfig.sh",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/bash;
+ shellScript = "## tcl configure shell script phase\n\ncd \"${TCL_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.in -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n echo \"Running autoconf & autoheader in tcl/macosx\"\n rm -rf autom4te.cache\n ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tcl && cd tcl &&\nif [ \"${TCL_SRCROOT}\"/macosx/configure -nt config.status ]; then\n echo \"Configuring Tcl\"\n CC=$(xcrun -find ${GCC} || echo ${GCC})\n \"${TCL_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n ./config.status\nfi\n";
+ showEnvVarsInLog = 0;
+ };
+ F9A5C5F608F651AB008AE941 /* Configure Tk */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "$(TK_SRCROOT)/macosx/configure.ac",
+ "$(TK_SRCROOT)/unix/configure.in",
+ "$(TK_SRCROOT)/unix/tcl.m4",
+ "$(TK_SRCROOT)/unix/aclocal.m4",
+ "$(TK_SRCROOT)/unix/tkConfig.sh.in",
+ );
+ name = "Configure Tk";
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/tk/tkConfig.sh",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/bash;
+ shellScript = "## tk configure shell script phase\n\ncd \"${TK_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.in -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n echo \"Running autoconf & autoheader in tk/macosx\"\n rm -rf autom4te.cache\n ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tk && cd tk &&\nif [ \"${TK_SRCROOT}\"/macosx/configure -nt config.status ]; then\n echo \"Configuring Tk\"\n CC=$(xcrun -find ${GCC} || echo ${GCC})\n \"${TK_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared --enable-aqua --with-tcl=../tcl CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n ./config.status\nfi\n";
+ showEnvVarsInLog = 0;
+ };
+ F9FD30B40CC1AD070073837D /* Configure Tcl */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "$(TCL_SRCROOT)/macosx/configure.ac",
+ "$(TCL_SRCROOT)/unix/configure.in",
+ "$(TCL_SRCROOT)/unix/tcl.m4",
+ "$(TCL_SRCROOT)/unix/aclocal.m4",
+ "$(TCL_SRCROOT)/unix/tclConfig.sh.in",
+ "$(TCL_SRCROOT)/unix/Makefile.in",
+ "$(TCL_SRCROOT)/unix/dltest/Makefile.in",
+ );
+ name = "Configure Tcl";
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/tcl/tclConfig.sh",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/bash;
+ shellScript = "## tcl configure shell script phase\n\ncd \"${TCL_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.in -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n echo \"Running autoconf & autoheader in tcl/macosx\"\n rm -rf autom4te.cache\n ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tcl && cd tcl &&\nif [ \"${TCL_SRCROOT}\"/macosx/configure -nt config.status ]; then\n echo \"Configuring Tcl\"\n CC=$(xcrun -find ${GCC} || echo ${GCC})\n \"${TCL_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n ./config.status\nfi\n";
+ showEnvVarsInLog = 0;
+ };
+ F9FD30B50CC1AD070073837D /* Configure Tk */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "$(TK_SRCROOT)/macosx/configure.ac",
+ "$(TK_SRCROOT)/unix/configure.in",
+ "$(TK_SRCROOT)/unix/tcl.m4",
+ "$(TK_SRCROOT)/unix/aclocal.m4",
+ "$(TK_SRCROOT)/unix/tkConfig.sh.in",
+ );
+ name = "Configure Tk";
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/tk/tkConfig.sh",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/bash;
+ shellScript = "## tk configure shell script phase\n\ncd \"${TK_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.in -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n echo \"Running autoconf & autoheader in tk/macosx\"\n rm -rf autom4te.cache\n ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tk && cd tk &&\nif [ \"${TK_SRCROOT}\"/macosx/configure -nt config.status ]; then\n echo \"Configuring Tk\"\n CC=$(xcrun -find ${GCC} || echo ${GCC})\n PATH=\"${PATH}:/usr/X11R6/bin\" \"${TK_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared --enable-xft --with-tcl=../tcl CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n ./config.status\nfi";
+ showEnvVarsInLog = 0;
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 8DD76FAB0486AB0100D96B5E /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F96D456F08F272BB004A47F5 /* regcomp.c in Sources */,
+ F96D457208F272BB004A47F5 /* regerror.c in Sources */,
+ F96D457508F272BB004A47F5 /* regexec.c in Sources */,
+ F96D457608F272BB004A47F5 /* regfree.c in Sources */,
+ F96D457B08F272BB004A47F5 /* tclAlloc.c in Sources */,
+ F96D457C08F272BB004A47F5 /* tclAsync.c in Sources */,
+ F96D457D08F272BB004A47F5 /* tclBasic.c in Sources */,
+ F96D457E08F272BC004A47F5 /* tclBinary.c in Sources */,
+ F96D457F08F272BC004A47F5 /* tclCkalloc.c in Sources */,
+ F96D458008F272BC004A47F5 /* tclClock.c in Sources */,
+ F96D458108F272BC004A47F5 /* tclCmdAH.c in Sources */,
+ F96D458208F272BC004A47F5 /* tclCmdIL.c in Sources */,
+ F96D458308F272BC004A47F5 /* tclCmdMZ.c in Sources */,
+ F96D458408F272BC004A47F5 /* tclCompCmds.c in Sources */,
+ F96D458508F272BC004A47F5 /* tclCompExpr.c in Sources */,
+ F96D458608F272BC004A47F5 /* tclCompile.c in Sources */,
+ F96D458808F272BC004A47F5 /* tclConfig.c in Sources */,
+ F96D458908F272BC004A47F5 /* tclDate.c in Sources */,
+ F96D458B08F272BC004A47F5 /* tclDictObj.c in Sources */,
+ F96D458C08F272BC004A47F5 /* tclEncoding.c in Sources */,
+ F96D458D08F272BC004A47F5 /* tclEnv.c in Sources */,
+ F96D458E08F272BC004A47F5 /* tclEvent.c in Sources */,
+ F96D458F08F272BC004A47F5 /* tclExecute.c in Sources */,
+ F96D459008F272BC004A47F5 /* tclFCmd.c in Sources */,
+ F96D459108F272BC004A47F5 /* tclFileName.c in Sources */,
+ F96D459308F272BC004A47F5 /* tclGet.c in Sources */,
+ F96D459508F272BC004A47F5 /* tclHash.c in Sources */,
+ F96D459608F272BC004A47F5 /* tclHistory.c in Sources */,
+ F96D459708F272BC004A47F5 /* tclIndexObj.c in Sources */,
+ F96D459B08F272BC004A47F5 /* tclInterp.c in Sources */,
+ F96D459D08F272BC004A47F5 /* tclIO.c in Sources */,
+ F96D459F08F272BC004A47F5 /* tclIOCmd.c in Sources */,
+ F96D45A008F272BC004A47F5 /* tclIOGT.c in Sources */,
+ F96D45A108F272BC004A47F5 /* tclIORChan.c in Sources */,
+ F95D77EA0DFD820D00A8BF6F /* tclIORTrans.c in Sources */,
+ F96D45A208F272BC004A47F5 /* tclIOSock.c in Sources */,
+ F96D45A308F272BC004A47F5 /* tclIOUtil.c in Sources */,
+ F96D45A408F272BC004A47F5 /* tclLink.c in Sources */,
+ F96D45A508F272BC004A47F5 /* tclListObj.c in Sources */,
+ F96D45A608F272BC004A47F5 /* tclLiteral.c in Sources */,
+ F96D45A708F272BC004A47F5 /* tclLoad.c in Sources */,
+ F96D45A908F272BC004A47F5 /* tclMain.c in Sources */,
+ F96D45AA08F272BC004A47F5 /* tclNamesp.c in Sources */,
+ F96D45AB08F272BC004A47F5 /* tclNotify.c in Sources */,
+ F96D45AC08F272BC004A47F5 /* tclObj.c in Sources */,
+ F93599B30DF1F75400E04F67 /* tclOO.c in Sources */,
+ F93599B70DF1F76100E04F67 /* tclOOBasic.c in Sources */,
+ F93599B90DF1F76600E04F67 /* tclOOCall.c in Sources */,
+ F93599BC0DF1F77000E04F67 /* tclOODefineCmds.c in Sources */,
+ F93599BE0DF1F77400E04F67 /* tclOOInfo.c in Sources */,
+ F93599C20DF1F78300E04F67 /* tclOOMethod.c in Sources */,
+ F93599C40DF1F78800E04F67 /* tclOOStubInit.c in Sources */,
+ F93599C60DF1F78D00E04F67 /* tclOOStubLib.c in Sources */,
+ F96D45AD08F272BC004A47F5 /* tclPanic.c in Sources */,
+ F96D45AE08F272BC004A47F5 /* tclParse.c in Sources */,
+ F96D45B008F272BC004A47F5 /* tclPathObj.c in Sources */,
+ F96D45B108F272BC004A47F5 /* tclPipe.c in Sources */,
+ F96D45B208F272BC004A47F5 /* tclPkg.c in Sources */,
+ F96D45B308F272BC004A47F5 /* tclPkgConfig.c in Sources */,
+ F96D45B608F272BC004A47F5 /* tclPosixStr.c in Sources */,
+ F96D45B708F272BC004A47F5 /* tclPreserve.c in Sources */,
+ F96D45B808F272BC004A47F5 /* tclProc.c in Sources */,
+ F96D45B908F272BC004A47F5 /* tclRegexp.c in Sources */,
+ F96D45BB08F272BC004A47F5 /* tclResolve.c in Sources */,
+ F96D45BC08F272BC004A47F5 /* tclResult.c in Sources */,
+ F96D45BD08F272BC004A47F5 /* tclScan.c in Sources */,
+ F96D45BE08F272BC004A47F5 /* tclStringObj.c in Sources */,
+ F96D45C308F272BC004A47F5 /* tclStrToD.c in Sources */,
+ F96D45C408F272BC004A47F5 /* tclStubInit.c in Sources */,
+ F96D45C508F272BC004A47F5 /* tclStubLib.c in Sources */,
+ F96D45C908F272BC004A47F5 /* tclThread.c in Sources */,
+ F96D45CA08F272BC004A47F5 /* tclThreadAlloc.c in Sources */,
+ F96D45CB08F272BC004A47F5 /* tclThreadJoin.c in Sources */,
+ F96D45CC08F272BC004A47F5 /* tclThreadStorage.c in Sources */,
+ F96D45CE08F272BC004A47F5 /* tclTimer.c in Sources */,
+ F96D45D008F272BC004A47F5 /* tclTomMathInterface.c in Sources */,
+ F96D45D108F272BC004A47F5 /* tclTrace.c in Sources */,
+ F96D45D308F272BC004A47F5 /* tclUtf.c in Sources */,
+ F96D45D408F272BC004A47F5 /* tclUtil.c in Sources */,
+ F96D45D508F272BC004A47F5 /* tclVar.c in Sources */,
+ F96437CA0EF0D4B2003F468E /* tclZlib.c in Sources */,
+ F96D48E208F272C3004A47F5 /* bn_fast_s_mp_mul_digs.c in Sources */,
+ F96D48E408F272C3004A47F5 /* bn_fast_s_mp_sqr.c in Sources */,
+ F96D48E708F272C3004A47F5 /* bn_mp_add.c in Sources */,
+ F96D48E808F272C3004A47F5 /* bn_mp_add_d.c in Sources */,
+ F9E61D2B090A48A4002B3151 /* bn_mp_and.c in Sources */,
+ F96D48EB08F272C3004A47F5 /* bn_mp_clamp.c in Sources */,
+ F96D48EC08F272C3004A47F5 /* bn_mp_clear.c in Sources */,
+ F96D48ED08F272C3004A47F5 /* bn_mp_clear_multi.c in Sources */,
+ F96D48EE08F272C3004A47F5 /* bn_mp_cmp.c in Sources */,
+ F9E61D28090A481F002B3151 /* bn_mp_cmp_d.c in Sources */,
+ F96D48F008F272C3004A47F5 /* bn_mp_cmp_mag.c in Sources */,
+ F96D48F208F272C3004A47F5 /* bn_mp_copy.c in Sources */,
+ F96D48F308F272C3004A47F5 /* bn_mp_count_bits.c in Sources */,
+ F96D48F408F272C3004A47F5 /* bn_mp_div.c in Sources */,
+ F96D48F508F272C3004A47F5 /* bn_mp_div_2.c in Sources */,
+ F96D48F608F272C3004A47F5 /* bn_mp_div_2d.c in Sources */,
+ F96D48F708F272C3004A47F5 /* bn_mp_div_3.c in Sources */,
+ F96D48F808F272C3004A47F5 /* bn_mp_div_d.c in Sources */,
+ F96D48FC08F272C3004A47F5 /* bn_mp_exch.c in Sources */,
+ F9E61D2C090A48AC002B3151 /* bn_mp_expt_d.c in Sources */,
+ F96D490508F272C3004A47F5 /* bn_mp_grow.c in Sources */,
+ F96D490608F272C3004A47F5 /* bn_mp_init.c in Sources */,
+ F96D490708F272C3004A47F5 /* bn_mp_init_copy.c in Sources */,
+ F96D490808F272C3004A47F5 /* bn_mp_init_multi.c in Sources */,
+ F96D490908F272C3004A47F5 /* bn_mp_init_set.c in Sources */,
+ F96D490B08F272C3004A47F5 /* bn_mp_init_size.c in Sources */,
+ F96D491008F272C3004A47F5 /* bn_mp_karatsuba_mul.c in Sources */,
+ F96D491108F272C3004A47F5 /* bn_mp_karatsuba_sqr.c in Sources */,
+ F96D491308F272C3004A47F5 /* bn_mp_lshd.c in Sources */,
+ F96D491408F272C3004A47F5 /* bn_mp_mod.c in Sources */,
+ F96D491508F272C3004A47F5 /* bn_mp_mod_2d.c in Sources */,
+ F96D491A08F272C3004A47F5 /* bn_mp_mul.c in Sources */,
+ F96D491B08F272C3004A47F5 /* bn_mp_mul_2.c in Sources */,
+ F96D491C08F272C3004A47F5 /* bn_mp_mul_2d.c in Sources */,
+ F96D491D08F272C3004A47F5 /* bn_mp_mul_d.c in Sources */,
+ F9E61D29090A486C002B3151 /* bn_mp_neg.c in Sources */,
+ F9E61D2E090A48BF002B3151 /* bn_mp_or.c in Sources */,
+ F96D492908F272C3004A47F5 /* bn_mp_radix_size.c in Sources */,
+ F96D492A08F272C3004A47F5 /* bn_mp_radix_smap.c in Sources */,
+ F96D492C08F272C3004A47F5 /* bn_mp_read_radix.c in Sources */,
+ F96D493708F272C3004A47F5 /* bn_mp_rshd.c in Sources */,
+ F96D493808F272C3004A47F5 /* bn_mp_set.c in Sources */,
+ F9E61D2F090A48C7002B3151 /* bn_mp_shrink.c in Sources */,
+ F96D493C08F272C3004A47F5 /* bn_mp_sqr.c in Sources */,
+ F9E61D2A090A4891002B3151 /* bn_mp_sqrt.c in Sources */,
+ F96D493F08F272C3004A47F5 /* bn_mp_sub.c in Sources */,
+ F96D494008F272C3004A47F5 /* bn_mp_sub_d.c in Sources */,
+ F9E61D30090A48E2002B3151 /* bn_mp_to_unsigned_bin_n.c in Sources */,
+ F9E61D31090A48F9002B3151 /* bn_mp_to_unsigned_bin.c in Sources */,
+ F96D494608F272C3004A47F5 /* bn_mp_toom_mul.c in Sources */,
+ F96D494708F272C3004A47F5 /* bn_mp_toom_sqr.c in Sources */,
+ F96D494908F272C3004A47F5 /* bn_mp_toradix_n.c in Sources */,
+ F9E61D32090A48FA002B3151 /* bn_mp_unsigned_bin_size.c in Sources */,
+ F9E61D2D090A48BB002B3151 /* bn_mp_xor.c in Sources */,
+ F96D494C08F272C3004A47F5 /* bn_mp_zero.c in Sources */,
+ F96D494E08F272C3004A47F5 /* bn_reverse.c in Sources */,
+ F96D494F08F272C3004A47F5 /* bn_s_mp_add.c in Sources */,
+ F96D495108F272C3004A47F5 /* bn_s_mp_mul_digs.c in Sources */,
+ F96D495308F272C3004A47F5 /* bn_s_mp_sqr.c in Sources */,
+ F96D495408F272C3004A47F5 /* bn_s_mp_sub.c in Sources */,
+ F96D495508F272C3004A47F5 /* bncore.c in Sources */,
+ F96D49A908F272C4004A47F5 /* tclMacOSXBundle.c in Sources */,
+ F96D49AD08F272C4004A47F5 /* tclMacOSXFCmd.c in Sources */,
+ F96D49AE08F272C4004A47F5 /* tclMacOSXNotify.c in Sources */,
+ F96D4AC608F272C9004A47F5 /* tclLoadDyld.c in Sources */,
+ F96D4ACA08F272C9004A47F5 /* tclUnixChan.c in Sources */,
+ F9FC77B80AB29E9100B7077D /* tclUnixCompat.c in Sources */,
+ F96D4ACB08F272C9004A47F5 /* tclUnixEvent.c in Sources */,
+ F96D4ACC08F272C9004A47F5 /* tclUnixFCmd.c in Sources */,
+ F96D4ACD08F272C9004A47F5 /* tclUnixFile.c in Sources */,
+ F96D4ACE08F272C9004A47F5 /* tclUnixInit.c in Sources */,
+ F96D4ACF08F272C9004A47F5 /* tclUnixNotfy.c in Sources */,
+ F96D4AD008F272C9004A47F5 /* tclUnixPipe.c in Sources */,
+ F96D4AD208F272CA004A47F5 /* tclUnixSock.c in Sources */,
+ F96D4AD408F272CA004A47F5 /* tclUnixThrd.c in Sources */,
+ F96D4AD608F272CA004A47F5 /* tclUnixTime.c in Sources */,
+ F9F4415E0C8BAE6F00BCCD67 /* tclDTrace.d in Sources */,
+ F966BDCF08F27A3F005CB29B /* tk3d.c in Sources */,
+ F966BDD108F27A3F005CB29B /* tkArgv.c in Sources */,
+ F966BDD208F27A3F005CB29B /* tkAtom.c in Sources */,
+ F966BDD308F27A3F005CB29B /* tkBind.c in Sources */,
+ F966BDD408F27A3F005CB29B /* tkBitmap.c in Sources */,
+ F9152B090EAF8A5000CD5C7B /* tkBusy.c in Sources */,
+ F966BDD508F27A3F005CB29B /* tkButton.c in Sources */,
+ F966BDD708F27A3F005CB29B /* tkCanvArc.c in Sources */,
+ F966BDD808F27A3F005CB29B /* tkCanvas.c in Sources */,
+ F966BDDA08F27A3F005CB29B /* tkCanvBmap.c in Sources */,
+ F966BDDB08F27A3F005CB29B /* tkCanvImg.c in Sources */,
+ F966BDDC08F27A3F005CB29B /* tkCanvLine.c in Sources */,
+ F966BDDD08F27A3F005CB29B /* tkCanvPoly.c in Sources */,
+ F966BDDE08F27A3F005CB29B /* tkCanvPs.c in Sources */,
+ F966BDE008F27A3F005CB29B /* tkCanvText.c in Sources */,
+ F966BDE108F27A3F005CB29B /* tkCanvUtil.c in Sources */,
+ F966BDE208F27A3F005CB29B /* tkCanvWind.c in Sources */,
+ F966BDE308F27A3F005CB29B /* tkClipboard.c in Sources */,
+ F966BDE408F27A3F005CB29B /* tkCmds.c in Sources */,
+ F966BDE508F27A3F005CB29B /* tkColor.c in Sources */,
+ F966BDE708F27A3F005CB29B /* tkConfig.c in Sources */,
+ F966BDE808F27A3F005CB29B /* tkConsole.c in Sources */,
+ F966BDE908F27A3F005CB29B /* tkCursor.c in Sources */,
+ F966BDEB08F27A3F005CB29B /* tkEntry.c in Sources */,
+ F966BDED08F27A3F005CB29B /* tkError.c in Sources */,
+ F966BDEE08F27A3F005CB29B /* tkEvent.c in Sources */,
+ F966BDEF08F27A3F005CB29B /* tkFileFilter.c in Sources */,
+ F966BDF108F27A3F005CB29B /* tkFocus.c in Sources */,
+ F966BDF208F27A3F005CB29B /* tkFont.c in Sources */,
+ F966BDF408F27A3F005CB29B /* tkFrame.c in Sources */,
+ F966BDF508F27A3F005CB29B /* tkGC.c in Sources */,
+ F966BDF608F27A3F005CB29B /* tkGeometry.c in Sources */,
+ F966BDF708F27A3F005CB29B /* tkGet.c in Sources */,
+ F966BDF808F27A3F005CB29B /* tkGrab.c in Sources */,
+ F966BDF908F27A3F005CB29B /* tkGrid.c in Sources */,
+ F966BDFA08F27A3F005CB29B /* tkImage.c in Sources */,
+ F966BDFB08F27A3F005CB29B /* tkImgBmap.c in Sources */,
+ F966BDFC08F27A3F005CB29B /* tkImgGIF.c in Sources */,
+ F92EE8BF0E62F846001A6E80 /* tkImgPhInstance.c in Sources */,
+ F966BDFD08F27A3F005CB29B /* tkImgPhoto.c in Sources */,
+ F9DD99BD0F07DF850018B2E4 /* tkImgPNG.c in Sources */,
+ F966BDFE08F27A3F005CB29B /* tkImgPPM.c in Sources */,
+ F966BE0708F27A3F005CB29B /* tkListbox.c in Sources */,
+ F966BE0808F27A3F005CB29B /* tkMacWinMenu.c in Sources */,
+ F966BE0908F27A3F005CB29B /* tkMain.c in Sources */,
+ F966BE0A08F27A3F005CB29B /* tkMenu.c in Sources */,
+ F966BE0C08F27A3F005CB29B /* tkMenubutton.c in Sources */,
+ F966BE0E08F27A3F005CB29B /* tkMenuDraw.c in Sources */,
+ F966BE0F08F27A3F005CB29B /* tkMessage.c in Sources */,
+ F966BE1008F27A3F005CB29B /* tkObj.c in Sources */,
+ F966BE1108F27A3F005CB29B /* tkOldConfig.c in Sources */,
+ F9067BCD0BFBA2900074F726 /* tkOldTest.c in Sources */,
+ F966BE1208F27A3F005CB29B /* tkOption.c in Sources */,
+ F966BE1308F27A3F005CB29B /* tkPack.c in Sources */,
+ F966BE1408F27A3F005CB29B /* tkPanedWindow.c in Sources */,
+ F966BE1508F27A3F005CB29B /* tkPlace.c in Sources */,
+ F966BE1708F27A3F005CB29B /* tkPointer.c in Sources */,
+ F966BE1908F27A3F005CB29B /* tkRectOval.c in Sources */,
+ F966BE1A08F27A3F005CB29B /* tkScale.c in Sources */,
+ F966BE1C08F27A40005CB29B /* tkScrollbar.c in Sources */,
+ F966BE1E08F27A40005CB29B /* tkSelect.c in Sources */,
+ F966BE2008F27A40005CB29B /* tkSquare.c in Sources */,
+ F966BE2208F27A40005CB29B /* tkStubInit.c in Sources */,
+ F966BE2308F27A40005CB29B /* tkStubLib.c in Sources */,
+ F966BE2408F27A40005CB29B /* tkStyle.c in Sources */,
+ F966BE2508F27A40005CB29B /* tkTest.c in Sources */,
+ F966BE2608F27A40005CB29B /* tkText.c in Sources */,
+ F966BE2808F27A40005CB29B /* tkTextBTree.c in Sources */,
+ F966BE2908F27A40005CB29B /* tkTextDisp.c in Sources */,
+ F966BE2B08F27A40005CB29B /* tkTextImage.c in Sources */,
+ F966BE2C08F27A40005CB29B /* tkTextIndex.c in Sources */,
+ F966BE2D08F27A40005CB29B /* tkTextMark.c in Sources */,
+ F966BE2E08F27A40005CB29B /* tkTextTag.c in Sources */,
+ F966BE2F08F27A40005CB29B /* tkTextWind.c in Sources */,
+ F966BE3008F27A40005CB29B /* tkTrig.c in Sources */,
+ F966BE3108F27A40005CB29B /* tkUndo.c in Sources */,
+ F966BE3308F27A40005CB29B /* tkUtil.c in Sources */,
+ F966BE3408F27A40005CB29B /* tkVisual.c in Sources */,
+ F966BE3508F27A40005CB29B /* tkWindow.c in Sources */,
+ F96888050AF786D5000797B5 /* ttkBlink.c in Sources */,
+ F96888060AF786D5000797B5 /* ttkButton.c in Sources */,
+ F96888070AF786D5000797B5 /* ttkCache.c in Sources */,
+ F96888080AF786D5000797B5 /* ttkClamTheme.c in Sources */,
+ F96888090AF786D5000797B5 /* ttkClassicTheme.c in Sources */,
+ F968880A0AF786D5000797B5 /* ttkDefaultTheme.c in Sources */,
+ F968880B0AF786D5000797B5 /* ttkElements.c in Sources */,
+ F968880C0AF786D5000797B5 /* ttkEntry.c in Sources */,
+ F968880D0AF786D5000797B5 /* ttkFrame.c in Sources */,
+ F968880E0AF786D5000797B5 /* ttkImage.c in Sources */,
+ F968880F0AF786D5000797B5 /* ttkInit.c in Sources */,
+ F96888100AF786D5000797B5 /* ttkLabel.c in Sources */,
+ F96888110AF786D5000797B5 /* ttkLayout.c in Sources */,
+ F96888120AF786D5000797B5 /* ttkManager.c in Sources */,
+ F96888130AF786D5000797B5 /* ttkNotebook.c in Sources */,
+ F96888140AF786D5000797B5 /* ttkPanedwindow.c in Sources */,
+ F96888150AF786D5000797B5 /* ttkProgress.c in Sources */,
+ F96888160AF786D5000797B5 /* ttkScale.c in Sources */,
+ F96888170AF786D5000797B5 /* ttkScroll.c in Sources */,
+ F96888180AF786D5000797B5 /* ttkScrollbar.c in Sources */,
+ F96888190AF786D5000797B5 /* ttkSeparator.c in Sources */,
+ F968881A0AF786D5000797B5 /* ttkSquare.c in Sources */,
+ F968881B0AF786D5000797B5 /* ttkState.c in Sources */,
+ F968881C0AF786D5000797B5 /* ttkStubInit.c in Sources */,
+ F968881D0AF786D5000797B5 /* ttkStubLib.c in Sources */,
+ F968881E0AF786D5000797B5 /* ttkTagSet.c in Sources */,
+ F968881F0AF786D5000797B5 /* ttkTheme.c in Sources */,
+ F96888200AF786D5000797B5 /* ttkTrace.c in Sources */,
+ F96888210AF786D5000797B5 /* ttkTrack.c in Sources */,
+ F96888220AF786D5000797B5 /* ttkTreeview.c in Sources */,
+ F96888230AF786D5000797B5 /* ttkWidget.c in Sources */,
+ F966BEDB08F27A40005CB29B /* tkMacOSXBitmap.c in Sources */,
+ F966BEDC08F27A40005CB29B /* tkMacOSXButton.c in Sources */,
+ F966BEDE08F27A40005CB29B /* tkMacOSXClipboard.c in Sources */,
+ F966BEDF08F27A40005CB29B /* tkMacOSXColor.c in Sources */,
+ F966BEE008F27A40005CB29B /* tkMacOSXConfig.c in Sources */,
+ F966BEE108F27A40005CB29B /* tkMacOSXCursor.c in Sources */,
+ F966BEE308F27A40005CB29B /* tkMacOSXDebug.c in Sources */,
+ F966BEE608F27A40005CB29B /* tkMacOSXDialog.c in Sources */,
+ F966BEE708F27A40005CB29B /* tkMacOSXDraw.c in Sources */,
+ F966BEE808F27A40005CB29B /* tkMacOSXEmbed.c in Sources */,
+ F966BEE908F27A40005CB29B /* tkMacOSXEntry.c in Sources */,
+ F966BEEA08F27A40005CB29B /* tkMacOSXEvent.c in Sources */,
+ F966BEEC08F27A40005CB29B /* tkMacOSXFont.c in Sources */,
+ F966BEED08F27A40005CB29B /* tkMacOSXHLEvents.c in Sources */,
+ F966BEEE08F27A40005CB29B /* tkMacOSXInit.c in Sources */,
+ F966BEF108F27A40005CB29B /* tkMacOSXKeyboard.c in Sources */,
+ F966BEF208F27A40005CB29B /* tkMacOSXKeyEvent.c in Sources */,
+ F966BEF308F27A40005CB29B /* tkMacOSXMenu.c in Sources */,
+ F966BEF608F27A40005CB29B /* tkMacOSXMenubutton.c in Sources */,
+ F966BEF708F27A40005CB29B /* tkMacOSXMenus.c in Sources */,
+ F966BEF808F27A40005CB29B /* tkMacOSXMouseEvent.c in Sources */,
+ F966BEF908F27A40005CB29B /* tkMacOSXNotify.c in Sources */,
+ F966BF0108F27A40005CB29B /* tkMacOSXRegion.c in Sources */,
+ F966BF0308F27A40005CB29B /* tkMacOSXScrlbr.c in Sources */,
+ F966BF0408F27A40005CB29B /* tkMacOSXSend.c in Sources */,
+ F966BF0508F27A40005CB29B /* tkMacOSXSubwindows.c in Sources */,
+ F966BF0608F27A40005CB29B /* tkMacOSXTest.c in Sources */,
+ F966BF0708F27A40005CB29B /* tkMacOSXWindowEvent.c in Sources */,
+ F966BF0808F27A40005CB29B /* tkMacOSXWm.c in Sources */,
+ F966BF0B08F27A40005CB29B /* tkMacOSXXStubs.c in Sources */,
+ F96888850AF78938000797B5 /* ttkMacOSXTheme.c in Sources */,
+ F966BF7F08F27A41005CB29B /* tkAppInit.c in Sources */,
+ F966BF8308F27A41005CB29B /* tkUnix3d.c in Sources */,
+ F966BF9608F27A41005CB29B /* tkUnixScale.c in Sources */,
+ F966C02A08F27A42005CB29B /* xcolors.c in Sources */,
+ F966C02B08F27A42005CB29B /* xdraw.c in Sources */,
+ F966C02C08F27A42005CB29B /* xgc.c in Sources */,
+ F966C02D08F27A42005CB29B /* ximage.c in Sources */,
+ F966C02E08F27A42005CB29B /* xutil.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F9FD30BB0CC1AD070073837D /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F9FD30BC0CC1AD070073837D /* regcomp.c in Sources */,
+ F9FD30BD0CC1AD070073837D /* regerror.c in Sources */,
+ F9FD30BE0CC1AD070073837D /* regexec.c in Sources */,
+ F9FD30BF0CC1AD070073837D /* regfree.c in Sources */,
+ F9FD30C00CC1AD070073837D /* tclAlloc.c in Sources */,
+ F9FD30C10CC1AD070073837D /* tclAsync.c in Sources */,
+ F9FD30C20CC1AD070073837D /* tclBasic.c in Sources */,
+ F9FD30C30CC1AD070073837D /* tclBinary.c in Sources */,
+ F9FD30C40CC1AD070073837D /* tclCkalloc.c in Sources */,
+ F9FD30C50CC1AD070073837D /* tclClock.c in Sources */,
+ F9FD30C60CC1AD070073837D /* tclCmdAH.c in Sources */,
+ F9FD30C70CC1AD070073837D /* tclCmdIL.c in Sources */,
+ F9FD30C80CC1AD070073837D /* tclCmdMZ.c in Sources */,
+ F9FD30C90CC1AD070073837D /* tclCompCmds.c in Sources */,
+ F9FD30CA0CC1AD070073837D /* tclCompExpr.c in Sources */,
+ F9FD30CB0CC1AD070073837D /* tclCompile.c in Sources */,
+ F9FD30CC0CC1AD070073837D /* tclConfig.c in Sources */,
+ F9FD30CD0CC1AD070073837D /* tclDate.c in Sources */,
+ F9FD30CE0CC1AD070073837D /* tclDictObj.c in Sources */,
+ F9FD30CF0CC1AD070073837D /* tclEncoding.c in Sources */,
+ F9FD30D00CC1AD070073837D /* tclEnv.c in Sources */,
+ F9FD30D10CC1AD070073837D /* tclEvent.c in Sources */,
+ F9FD30D20CC1AD070073837D /* tclExecute.c in Sources */,
+ F9FD30D30CC1AD070073837D /* tclFCmd.c in Sources */,
+ F9FD30D40CC1AD070073837D /* tclFileName.c in Sources */,
+ F9FD30D50CC1AD070073837D /* tclGet.c in Sources */,
+ F9FD30D60CC1AD070073837D /* tclHash.c in Sources */,
+ F9FD30D70CC1AD070073837D /* tclHistory.c in Sources */,
+ F9FD30D80CC1AD070073837D /* tclIndexObj.c in Sources */,
+ F9FD30D90CC1AD070073837D /* tclInterp.c in Sources */,
+ F9FD30DA0CC1AD070073837D /* tclIO.c in Sources */,
+ F9FD30DB0CC1AD070073837D /* tclIOCmd.c in Sources */,
+ F9FD30DC0CC1AD070073837D /* tclIOGT.c in Sources */,
+ F9FD30DD0CC1AD070073837D /* tclIORChan.c in Sources */,
+ F9FFAF1D0DFDDB26007F8A6A /* tclIORTrans.c in Sources */,
+ F9FD30DE0CC1AD070073837D /* tclIOSock.c in Sources */,
+ F9FD30DF0CC1AD070073837D /* tclIOUtil.c in Sources */,
+ F9FD30E00CC1AD070073837D /* tclLink.c in Sources */,
+ F9FD30E10CC1AD070073837D /* tclListObj.c in Sources */,
+ F9FD30E20CC1AD070073837D /* tclLiteral.c in Sources */,
+ F9FD30E30CC1AD070073837D /* tclLoad.c in Sources */,
+ F9FD30E40CC1AD070073837D /* tclMain.c in Sources */,
+ F9FD30E50CC1AD070073837D /* tclNamesp.c in Sources */,
+ F9FD30E60CC1AD070073837D /* tclNotify.c in Sources */,
+ F9FD30E70CC1AD070073837D /* tclObj.c in Sources */,
+ F9FFAF1F0DFDDB2F007F8A6A /* tclOO.c in Sources */,
+ F9FFAF200DFDDB32007F8A6A /* tclOOBasic.c in Sources */,
+ F9FFAF210DFDDB32007F8A6A /* tclOOCall.c in Sources */,
+ F9FFAF220DFDDB34007F8A6A /* tclOODefineCmds.c in Sources */,
+ F9FFAF230DFDDB35007F8A6A /* tclOOInfo.c in Sources */,
+ F9FFAF240DFDDB36007F8A6A /* tclOOMethod.c in Sources */,
+ F9FFAF250DFDDB37007F8A6A /* tclOOStubInit.c in Sources */,
+ F9FFAF260DFDDB38007F8A6A /* tclOOStubLib.c in Sources */,
+ F9FD30E80CC1AD070073837D /* tclPanic.c in Sources */,
+ F9FD30E90CC1AD070073837D /* tclParse.c in Sources */,
+ F9FD30EA0CC1AD070073837D /* tclPathObj.c in Sources */,
+ F9FD30EB0CC1AD070073837D /* tclPipe.c in Sources */,
+ F9FD30EC0CC1AD070073837D /* tclPkg.c in Sources */,
+ F9FD30ED0CC1AD070073837D /* tclPkgConfig.c in Sources */,
+ F9FD30EE0CC1AD070073837D /* tclPosixStr.c in Sources */,
+ F9FD30EF0CC1AD070073837D /* tclPreserve.c in Sources */,
+ F9FD30F00CC1AD070073837D /* tclProc.c in Sources */,
+ F9FD30F10CC1AD070073837D /* tclRegexp.c in Sources */,
+ F9FD30F20CC1AD070073837D /* tclResolve.c in Sources */,
+ F9FD30F30CC1AD070073837D /* tclResult.c in Sources */,
+ F9FD30F40CC1AD070073837D /* tclScan.c in Sources */,
+ F9FD30F50CC1AD070073837D /* tclStringObj.c in Sources */,
+ F9FD30F60CC1AD070073837D /* tclStrToD.c in Sources */,
+ F9FD30F70CC1AD070073837D /* tclStubInit.c in Sources */,
+ F9FD30F80CC1AD070073837D /* tclStubLib.c in Sources */,
+ F9FD30F90CC1AD070073837D /* tclThread.c in Sources */,
+ F9FD30FA0CC1AD070073837D /* tclThreadAlloc.c in Sources */,
+ F9FD30FB0CC1AD070073837D /* tclThreadJoin.c in Sources */,
+ F9FD30FC0CC1AD070073837D /* tclThreadStorage.c in Sources */,
+ F9FD30FD0CC1AD070073837D /* tclTimer.c in Sources */,
+ F9FD30FE0CC1AD070073837D /* tclTomMathInterface.c in Sources */,
+ F9FD30FF0CC1AD070073837D /* tclTrace.c in Sources */,
+ F9FD31000CC1AD070073837D /* tclUtf.c in Sources */,
+ F9FD31010CC1AD070073837D /* tclUtil.c in Sources */,
+ F9FD31020CC1AD070073837D /* tclVar.c in Sources */,
+ F96437CB0EF0D4B2003F468E /* tclZlib.c in Sources */,
+ F9FD31030CC1AD070073837D /* bn_fast_s_mp_mul_digs.c in Sources */,
+ F9FD31040CC1AD070073837D /* bn_fast_s_mp_sqr.c in Sources */,
+ F9FD31050CC1AD070073837D /* bn_mp_add.c in Sources */,
+ F9FD31060CC1AD070073837D /* bn_mp_add_d.c in Sources */,
+ F9FD31070CC1AD070073837D /* bn_mp_and.c in Sources */,
+ F9FD31080CC1AD070073837D /* bn_mp_clamp.c in Sources */,
+ F9FD31090CC1AD070073837D /* bn_mp_clear.c in Sources */,
+ F9FD310A0CC1AD070073837D /* bn_mp_clear_multi.c in Sources */,
+ F9FD310B0CC1AD070073837D /* bn_mp_cmp.c in Sources */,
+ F9FD310C0CC1AD070073837D /* bn_mp_cmp_d.c in Sources */,
+ F9FD310D0CC1AD070073837D /* bn_mp_cmp_mag.c in Sources */,
+ F9FD310E0CC1AD070073837D /* bn_mp_copy.c in Sources */,
+ F9FD310F0CC1AD070073837D /* bn_mp_count_bits.c in Sources */,
+ F9FD31100CC1AD070073837D /* bn_mp_div.c in Sources */,
+ F9FD31110CC1AD070073837D /* bn_mp_div_2.c in Sources */,
+ F9FD31120CC1AD070073837D /* bn_mp_div_2d.c in Sources */,
+ F9FD31130CC1AD070073837D /* bn_mp_div_3.c in Sources */,
+ F9FD31140CC1AD070073837D /* bn_mp_div_d.c in Sources */,
+ F9FD31150CC1AD070073837D /* bn_mp_exch.c in Sources */,
+ F9FD31160CC1AD070073837D /* bn_mp_expt_d.c in Sources */,
+ F9FD31170CC1AD070073837D /* bn_mp_grow.c in Sources */,
+ F9FD31180CC1AD070073837D /* bn_mp_init.c in Sources */,
+ F9FD31190CC1AD070073837D /* bn_mp_init_copy.c in Sources */,
+ F9FD311A0CC1AD070073837D /* bn_mp_init_multi.c in Sources */,
+ F9FD311B0CC1AD070073837D /* bn_mp_init_set.c in Sources */,
+ F9FD311C0CC1AD070073837D /* bn_mp_init_size.c in Sources */,
+ F9FD311D0CC1AD070073837D /* bn_mp_karatsuba_mul.c in Sources */,
+ F9FD311E0CC1AD070073837D /* bn_mp_karatsuba_sqr.c in Sources */,
+ F9FD311F0CC1AD070073837D /* bn_mp_lshd.c in Sources */,
+ F9FD31200CC1AD070073837D /* bn_mp_mod.c in Sources */,
+ F9FD31210CC1AD070073837D /* bn_mp_mod_2d.c in Sources */,
+ F9FD31220CC1AD070073837D /* bn_mp_mul.c in Sources */,
+ F9FD31230CC1AD070073837D /* bn_mp_mul_2.c in Sources */,
+ F9FD31240CC1AD070073837D /* bn_mp_mul_2d.c in Sources */,
+ F9FD31250CC1AD070073837D /* bn_mp_mul_d.c in Sources */,
+ F9FD31260CC1AD070073837D /* bn_mp_neg.c in Sources */,
+ F9FD31270CC1AD070073837D /* bn_mp_or.c in Sources */,
+ F9FD31280CC1AD070073837D /* bn_mp_radix_size.c in Sources */,
+ F9FD31290CC1AD070073837D /* bn_mp_radix_smap.c in Sources */,
+ F9FD312A0CC1AD070073837D /* bn_mp_read_radix.c in Sources */,
+ F9FD312B0CC1AD070073837D /* bn_mp_rshd.c in Sources */,
+ F9FD312C0CC1AD070073837D /* bn_mp_set.c in Sources */,
+ F9FD312D0CC1AD070073837D /* bn_mp_shrink.c in Sources */,
+ F9FD312E0CC1AD070073837D /* bn_mp_sqr.c in Sources */,
+ F9FD312F0CC1AD070073837D /* bn_mp_sqrt.c in Sources */,
+ F9FD31300CC1AD070073837D /* bn_mp_sub.c in Sources */,
+ F9FD31310CC1AD070073837D /* bn_mp_sub_d.c in Sources */,
+ F9FD31320CC1AD070073837D /* bn_mp_to_unsigned_bin_n.c in Sources */,
+ F9FD31330CC1AD070073837D /* bn_mp_to_unsigned_bin.c in Sources */,
+ F9FD31340CC1AD070073837D /* bn_mp_toom_mul.c in Sources */,
+ F9FD31350CC1AD070073837D /* bn_mp_toom_sqr.c in Sources */,
+ F9FD31360CC1AD070073837D /* bn_mp_toradix_n.c in Sources */,
+ F9FD31370CC1AD070073837D /* bn_mp_unsigned_bin_size.c in Sources */,
+ F9FD31380CC1AD070073837D /* bn_mp_xor.c in Sources */,
+ F9FD31390CC1AD070073837D /* bn_mp_zero.c in Sources */,
+ F9FD313A0CC1AD070073837D /* bn_reverse.c in Sources */,
+ F9FD313B0CC1AD070073837D /* bn_s_mp_add.c in Sources */,
+ F9FD313C0CC1AD070073837D /* bn_s_mp_mul_digs.c in Sources */,
+ F9FD313D0CC1AD070073837D /* bn_s_mp_sqr.c in Sources */,
+ F9FD313E0CC1AD070073837D /* bn_s_mp_sub.c in Sources */,
+ F9FD313F0CC1AD070073837D /* bncore.c in Sources */,
+ F9FD31400CC1AD070073837D /* tclMacOSXBundle.c in Sources */,
+ F9FD31410CC1AD070073837D /* tclMacOSXFCmd.c in Sources */,
+ F9FD31420CC1AD070073837D /* tclMacOSXNotify.c in Sources */,
+ F9FD31430CC1AD070073837D /* tclLoadDyld.c in Sources */,
+ F9FD31440CC1AD070073837D /* tclUnixChan.c in Sources */,
+ F9FD31450CC1AD070073837D /* tclUnixCompat.c in Sources */,
+ F9FD31460CC1AD070073837D /* tclUnixEvent.c in Sources */,
+ F9FD31470CC1AD070073837D /* tclUnixFCmd.c in Sources */,
+ F9FD31480CC1AD070073837D /* tclUnixFile.c in Sources */,
+ F9FD31490CC1AD070073837D /* tclUnixInit.c in Sources */,
+ F9FD314A0CC1AD070073837D /* tclUnixNotfy.c in Sources */,
+ F9FD314B0CC1AD070073837D /* tclUnixPipe.c in Sources */,
+ F9FD314C0CC1AD070073837D /* tclUnixSock.c in Sources */,
+ F9FD314D0CC1AD070073837D /* tclUnixThrd.c in Sources */,
+ F9FD314E0CC1AD070073837D /* tclUnixTime.c in Sources */,
+ F9FD31E20CC1AD070073837D /* tclDTrace.d in Sources */,
+ F9FD314F0CC1AD070073837D /* tk3d.c in Sources */,
+ F9FD31500CC1AD070073837D /* tkArgv.c in Sources */,
+ F9FD31510CC1AD070073837D /* tkAtom.c in Sources */,
+ F9FD31520CC1AD070073837D /* tkBind.c in Sources */,
+ F9FD31530CC1AD070073837D /* tkBitmap.c in Sources */,
+ F9152B0A0EAF8A5700CD5C7B /* tkBusy.c in Sources */,
+ F9FD31540CC1AD070073837D /* tkButton.c in Sources */,
+ F9FD31550CC1AD070073837D /* tkCanvArc.c in Sources */,
+ F9FD31560CC1AD070073837D /* tkCanvas.c in Sources */,
+ F9FD31570CC1AD070073837D /* tkCanvBmap.c in Sources */,
+ F9FD31580CC1AD070073837D /* tkCanvImg.c in Sources */,
+ F9FD31590CC1AD070073837D /* tkCanvLine.c in Sources */,
+ F9FD315A0CC1AD070073837D /* tkCanvPoly.c in Sources */,
+ F9FD315B0CC1AD070073837D /* tkCanvPs.c in Sources */,
+ F9FD315C0CC1AD070073837D /* tkCanvText.c in Sources */,
+ F9FD315D0CC1AD070073837D /* tkCanvUtil.c in Sources */,
+ F9FD315E0CC1AD070073837D /* tkCanvWind.c in Sources */,
+ F9FD315F0CC1AD070073837D /* tkClipboard.c in Sources */,
+ F9FD31600CC1AD070073837D /* tkCmds.c in Sources */,
+ F9FD31610CC1AD070073837D /* tkColor.c in Sources */,
+ F9FD31620CC1AD070073837D /* tkConfig.c in Sources */,
+ F9FD31630CC1AD070073837D /* tkConsole.c in Sources */,
+ F9FD31640CC1AD070073837D /* tkCursor.c in Sources */,
+ F9FD31650CC1AD070073837D /* tkEntry.c in Sources */,
+ F9FD31660CC1AD070073837D /* tkError.c in Sources */,
+ F9FD31670CC1AD070073837D /* tkEvent.c in Sources */,
+ F9FD31680CC1AD070073837D /* tkFileFilter.c in Sources */,
+ F9FD31690CC1AD070073837D /* tkFocus.c in Sources */,
+ F9FD316A0CC1AD070073837D /* tkFont.c in Sources */,
+ F9FD316B0CC1AD070073837D /* tkFrame.c in Sources */,
+ F9FD316C0CC1AD070073837D /* tkGC.c in Sources */,
+ F9FD316D0CC1AD070073837D /* tkGeometry.c in Sources */,
+ F9FD316E0CC1AD070073837D /* tkGet.c in Sources */,
+ F9FD316F0CC1AD070073837D /* tkGrab.c in Sources */,
+ F9FD31700CC1AD070073837D /* tkGrid.c in Sources */,
+ F9FD31710CC1AD070073837D /* tkImage.c in Sources */,
+ F9FD31720CC1AD070073837D /* tkImgBmap.c in Sources */,
+ F9FD31730CC1AD070073837D /* tkImgGIF.c in Sources */,
+ F92EE8D30E62F939001A6E80 /* tkImgPhInstance.c in Sources */,
+ F9FD31740CC1AD070073837D /* tkImgPhoto.c in Sources */,
+ F9DD99BE0F07DF850018B2E4 /* tkImgPNG.c in Sources */,
+ F9FD31750CC1AD070073837D /* tkImgPPM.c in Sources */,
+ F9FD31760CC1AD070073837D /* tkListbox.c in Sources */,
+ F9FD31770CC1AD070073837D /* tkMacWinMenu.c in Sources */,
+ F9FD31780CC1AD070073837D /* tkMain.c in Sources */,
+ F9FD31790CC1AD070073837D /* tkMenu.c in Sources */,
+ F9FD317A0CC1AD070073837D /* tkMenubutton.c in Sources */,
+ F9FD317B0CC1AD070073837D /* tkMenuDraw.c in Sources */,
+ F9FD317C0CC1AD070073837D /* tkMessage.c in Sources */,
+ F9FD317D0CC1AD070073837D /* tkObj.c in Sources */,
+ F9FD317E0CC1AD070073837D /* tkOldConfig.c in Sources */,
+ F9FD317F0CC1AD070073837D /* tkOldTest.c in Sources */,
+ F9FD31800CC1AD070073837D /* tkOption.c in Sources */,
+ F9FD31810CC1AD070073837D /* tkPack.c in Sources */,
+ F9FD31820CC1AD070073837D /* tkPanedWindow.c in Sources */,
+ F9FD31830CC1AD070073837D /* tkPlace.c in Sources */,
+ F9FD31850CC1AD070073837D /* tkRectOval.c in Sources */,
+ F9FD31860CC1AD070073837D /* tkScale.c in Sources */,
+ F9FD31870CC1AD070073837D /* tkScrollbar.c in Sources */,
+ F9FD31880CC1AD070073837D /* tkSelect.c in Sources */,
+ F9FD31890CC1AD070073837D /* tkSquare.c in Sources */,
+ F9FD318A0CC1AD070073837D /* tkStubInit.c in Sources */,
+ F9FD318B0CC1AD070073837D /* tkStubLib.c in Sources */,
+ F9FD318C0CC1AD070073837D /* tkStyle.c in Sources */,
+ F9FD318D0CC1AD070073837D /* tkTest.c in Sources */,
+ F9FD318E0CC1AD070073837D /* tkText.c in Sources */,
+ F9FD318F0CC1AD070073837D /* tkTextBTree.c in Sources */,
+ F9FD31900CC1AD070073837D /* tkTextDisp.c in Sources */,
+ F9FD31910CC1AD070073837D /* tkTextImage.c in Sources */,
+ F9FD31920CC1AD070073837D /* tkTextIndex.c in Sources */,
+ F9FD31930CC1AD070073837D /* tkTextMark.c in Sources */,
+ F9FD31940CC1AD070073837D /* tkTextTag.c in Sources */,
+ F9FD31950CC1AD070073837D /* tkTextWind.c in Sources */,
+ F9FD31960CC1AD070073837D /* tkTrig.c in Sources */,
+ F9FD31970CC1AD070073837D /* tkUndo.c in Sources */,
+ F9FD31980CC1AD070073837D /* tkUtil.c in Sources */,
+ F9FD31990CC1AD070073837D /* tkVisual.c in Sources */,
+ F9FD319A0CC1AD070073837D /* tkWindow.c in Sources */,
+ F9FD319B0CC1AD070073837D /* ttkBlink.c in Sources */,
+ F9FD319C0CC1AD070073837D /* ttkButton.c in Sources */,
+ F9FD319D0CC1AD070073837D /* ttkCache.c in Sources */,
+ F9FD319E0CC1AD070073837D /* ttkClamTheme.c in Sources */,
+ F9FD319F0CC1AD070073837D /* ttkClassicTheme.c in Sources */,
+ F9FD31A00CC1AD070073837D /* ttkDefaultTheme.c in Sources */,
+ F9FD31A10CC1AD070073837D /* ttkElements.c in Sources */,
+ F9FD31A20CC1AD070073837D /* ttkEntry.c in Sources */,
+ F9FD31A30CC1AD070073837D /* ttkFrame.c in Sources */,
+ F9FD31A40CC1AD070073837D /* ttkImage.c in Sources */,
+ F9FD31A50CC1AD070073837D /* ttkInit.c in Sources */,
+ F9FD31A60CC1AD070073837D /* ttkLabel.c in Sources */,
+ F9FD31A70CC1AD070073837D /* ttkLayout.c in Sources */,
+ F9FD31A80CC1AD070073837D /* ttkManager.c in Sources */,
+ F9FD31A90CC1AD070073837D /* ttkNotebook.c in Sources */,
+ F9FD31AA0CC1AD070073837D /* ttkPanedwindow.c in Sources */,
+ F9FD31AB0CC1AD070073837D /* ttkProgress.c in Sources */,
+ F9FD31AC0CC1AD070073837D /* ttkScale.c in Sources */,
+ F9FD31AD0CC1AD070073837D /* ttkScroll.c in Sources */,
+ F9FD31AE0CC1AD070073837D /* ttkScrollbar.c in Sources */,
+ F9FD31AF0CC1AD070073837D /* ttkSeparator.c in Sources */,
+ F9FD31B00CC1AD070073837D /* ttkSquare.c in Sources */,
+ F9FD31B10CC1AD070073837D /* ttkState.c in Sources */,
+ F9FD31B20CC1AD070073837D /* ttkStubInit.c in Sources */,
+ F9FD31B30CC1AD070073837D /* ttkStubLib.c in Sources */,
+ F9FD31B40CC1AD070073837D /* ttkTagSet.c in Sources */,
+ F9FD31B50CC1AD070073837D /* ttkTheme.c in Sources */,
+ F9FD31B60CC1AD070073837D /* ttkTrace.c in Sources */,
+ F9FD31B70CC1AD070073837D /* ttkTrack.c in Sources */,
+ F9FD31B80CC1AD070073837D /* ttkTreeview.c in Sources */,
+ F9FD31B90CC1AD070073837D /* ttkWidget.c in Sources */,
+ F9FD31DA0CC1AD070073837D /* tkAppInit.c in Sources */,
+ F9FD32020CC1ADB70073837D /* tkUnix.c in Sources */,
+ F9FD31DB0CC1AD070073837D /* tkUnix3d.c in Sources */,
+ F9FD320A0CC1ADB70073837D /* tkUnixButton.c in Sources */,
+ F9FD32090CC1ADB70073837D /* tkUnixColor.c in Sources */,
+ F9FD32040CC1ADB70073837D /* tkUnixConfig.c in Sources */,
+ F9FD31F80CC1ADB70073837D /* tkUnixCursor.c in Sources */,
+ F9FD32060CC1ADB70073837D /* tkUnixDialog.c in Sources */,
+ F9FD32050CC1ADB70073837D /* tkUnixDraw.c in Sources */,
+ F9FD31FD0CC1ADB70073837D /* tkUnixEmbed.c in Sources */,
+ F9FD32080CC1ADB70073837D /* tkUnixEvent.c in Sources */,
+ F9FD31FF0CC1ADB70073837D /* tkUnixFocus.c in Sources */,
+ F9FD31FC0CC1ADB70073837D /* tkUnixInit.c in Sources */,
+ F9FD31FA0CC1ADB70073837D /* tkUnixKey.c in Sources */,
+ F9FD32030CC1ADB70073837D /* tkUnixMenu.c in Sources */,
+ F9FD320B0CC1ADB70073837D /* tkUnixMenubu.c in Sources */,
+ F9FD32010CC1ADB70073837D /* tkUnixRFont.c in Sources */,
+ F9FD31DC0CC1AD070073837D /* tkUnixScale.c in Sources */,
+ F9FD320C0CC1ADB70073837D /* tkUnixScrlbr.c in Sources */,
+ F9FD32070CC1ADB70073837D /* tkUnixSelect.c in Sources */,
+ F9FD31FE0CC1ADB70073837D /* tkUnixSend.c in Sources */,
+ F9FD32000CC1ADB70073837D /* tkUnixWm.c in Sources */,
+ F9FD31FB0CC1ADB70073837D /* tkUnixXId.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ F90E36D50F3B5C8400810A10 /* DebugNoGC */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tk-Debug.xcconfig */;
+ buildSettings = {
+ ARCHS = (
+ "$(NATIVE_ARCH_64_BIT)",
+ "$(NATIVE_ARCH_32_BIT)",
+ );
+ CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = unsupported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ MACOSX_DEPLOYMENT_TARGET = 10.6;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ };
+ name = DebugNoGC;
+ };
+ F90E36D60F3B5C8400810A10 /* DebugNoGC */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = DebugNoGC;
+ };
+ F90E36D70F3B5C8400810A10 /* DebugNoGC */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = DebugNoGC;
+ };
+ F90E36D80F3B5C8400810A10 /* DebugNoGC */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)";
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "__private_extern__=extern",
+ "$(GCC_PREPROCESSOR_DEFINITIONS)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = DebugNoGC;
+ };
+ F91BCC4F093152310042A6BF /* ReleaseUniversal */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = ReleaseUniversal;
+ };
+ F91BCC50093152310042A6BF /* ReleaseUniversal */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = ReleaseUniversal;
+ };
+ F91BCC51093152310042A6BF /* ReleaseUniversal */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tk-Release.xcconfig */;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ MACOSX_DEPLOYMENT_TARGET = 10.6;
+ PREBINDING = NO;
+ };
+ name = ReleaseUniversal;
+ };
+ F93084370BB93D2800CD0B9E /* DebugMemCompile */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = DebugMemCompile;
+ };
+ F93084380BB93D2800CD0B9E /* DebugMemCompile */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = DebugMemCompile;
+ };
+ F93084390BB93D2800CD0B9E /* DebugMemCompile */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = DebugMemCompile;
+ };
+ F930843A0BB93D2800CD0B9E /* DebugMemCompile */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tk-Debug.xcconfig */;
+ buildSettings = {
+ ARCHS = (
+ "$(NATIVE_ARCH_64_BIT)",
+ "$(NATIVE_ARCH_32_BIT)",
+ );
+ CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --enable-symbols=all";
+ CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ MACOSX_DEPLOYMENT_TARGET = 10.6;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ };
+ name = DebugMemCompile;
+ };
+ F9359B250DF212DA00E04F67 /* DebugGCov */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tk-Debug.xcconfig */;
+ buildSettings = {
+ ARCHS = (
+ "$(NATIVE_ARCH_64_BIT)",
+ "$(NATIVE_ARCH_32_BIT)",
+ );
+ CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_GENERATE_TEST_COVERAGE_FILES = YES;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.6;
+ ONLY_ACTIVE_ARCH = YES;
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS)",
+ "-lgcov",
+ );
+ PREBINDING = NO;
+ };
+ name = DebugGCov;
+ };
+ F9359B260DF212DA00E04F67 /* DebugGCov */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = DebugGCov;
+ };
+ F9359B270DF212DA00E04F67 /* DebugGCov */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = DebugGCov;
+ };
+ F9359B280DF212DA00E04F67 /* DebugGCov */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = DebugGCov;
+ };
+ F95CC8AC09158F3100EA5ACE /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = Debug;
+ };
+ F95CC8AD09158F3100EA5ACE /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = Release;
+ };
+ F95CC8AE09158F3100EA5ACE /* DebugNoFixAndContinue */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = DebugNoFixAndContinue;
+ };
+ F95CC8B109158F3100EA5ACE /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)";
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "__private_extern__=extern",
+ "$(GCC_PREPROCESSOR_DEFINITIONS)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = Debug;
+ };
+ F95CC8B209158F3100EA5ACE /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = Release;
+ };
+ F95CC8B309158F3100EA5ACE /* DebugNoFixAndContinue */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = DebugNoFixAndContinue;
+ };
+ F95CC8B609158F3100EA5ACE /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tk-Debug.xcconfig */;
+ buildSettings = {
+ ARCHS = (
+ "$(NATIVE_ARCH_64_BIT)",
+ "$(NATIVE_ARCH_32_BIT)",
+ );
+ CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ MACOSX_DEPLOYMENT_TARGET = 10.6;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ };
+ name = Debug;
+ };
+ F95CC8B709158F3100EA5ACE /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tk-Release.xcconfig */;
+ buildSettings = {
+ ARCHS = (
+ "$(NATIVE_ARCH_64_BIT)",
+ "$(NATIVE_ARCH_32_BIT)",
+ );
+ CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ MACOSX_DEPLOYMENT_TARGET = 10.6;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ };
+ name = Release;
+ };
+ F95CC8B809158F3100EA5ACE /* DebugNoFixAndContinue */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tk-Debug.xcconfig */;
+ buildSettings = {
+ ARCHS = (
+ "$(NATIVE_ARCH_64_BIT)",
+ "$(NATIVE_ARCH_32_BIT)",
+ );
+ CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ MACOSX_DEPLOYMENT_TARGET = 10.6;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ };
+ name = DebugNoFixAndContinue;
+ };
+ F97258A90A86873D00096C78 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)";
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "__private_extern__=extern",
+ "$(GCC_PREPROCESSOR_DEFINITIONS)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = Debug;
+ };
+ F97258AA0A86873D00096C78 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = Release;
+ };
+ F97258AB0A86873D00096C78 /* DebugNoFixAndContinue */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = DebugNoFixAndContinue;
+ };
+ F97258AC0A86873D00096C78 /* ReleaseUniversal */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)";
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = ReleaseUniversal;
+ };
+ F97AED1B0B660B2100310EA2 /* Debug64bit */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = Debug64bit;
+ };
+ F97AED1C0B660B2100310EA2 /* Debug64bit */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = Debug64bit;
+ };
+ F97AED1D0B660B2100310EA2 /* Debug64bit */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = Debug64bit;
+ };
+ F97AED1E0B660B2100310EA2 /* Debug64bit */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tk-Debug.xcconfig */;
+ buildSettings = {
+ ARCHS = "$(NATIVE_ARCH_64_BIT)";
+ CONFIGURE_ARGS = "--enable-64bit $(CONFIGURE_ARGS)";
+ CPPFLAGS = "-arch $(NATIVE_ARCH_64_BIT) $(CPPFLAGS)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ MACOSX_DEPLOYMENT_TARGET = 10.6;
+ PREBINDING = NO;
+ };
+ name = Debug64bit;
+ };
+ F987512F0DE7B57E00B1C9EC /* DebugNoCF */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tk-Debug.xcconfig */;
+ buildSettings = {
+ ARCHS = (
+ "$(NATIVE_ARCH_64_BIT)",
+ "$(NATIVE_ARCH_32_BIT)",
+ );
+ CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --disable-corefoundation";
+ CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ MACOSX_DEPLOYMENT_TARGET = 10.6;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ };
+ name = DebugNoCF;
+ };
+ F98751300DE7B57E00B1C9EC /* DebugNoCF */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --enable-corefoundation";
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = DebugNoCF;
+ };
+ F98751310DE7B57E00B1C9EC /* DebugNoCF */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --enable-corefoundation";
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = DebugNoCF;
+ };
+ F98751320DE7B57E00B1C9EC /* DebugNoCF */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = DebugNoCF;
+ };
+ F98751330DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tk-Debug.xcconfig */;
+ buildSettings = {
+ ARCHS = (
+ "$(NATIVE_ARCH_64_BIT)",
+ "$(NATIVE_ARCH_32_BIT)",
+ );
+ CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --disable-threads --disable-corefoundation";
+ CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ MACOSX_DEPLOYMENT_TARGET = 10.6;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ };
+ name = DebugNoCFUnthreaded;
+ };
+ F98751340DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --enable-corefoundation";
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = DebugNoCFUnthreaded;
+ };
+ F98751350DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --enable-corefoundation";
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = DebugNoCFUnthreaded;
+ };
+ F98751360DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = DebugNoCFUnthreaded;
+ };
+ F9988AB10D814C6500B6B03B /* Debug gcc40 */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tk-Debug.xcconfig */;
+ buildSettings = {
+ ARCHS = (
+ "$(NATIVE_ARCH_64_BIT)",
+ "$(NATIVE_ARCH_32_BIT)",
+ );
+ CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ GCC_VERSION = 4.0;
+ MACOSX_DEPLOYMENT_TARGET = 10.6;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ };
+ name = "Debug gcc40";
+ };
+ F9988AB20D814C6500B6B03B /* Debug gcc40 */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = "Debug gcc40";
+ };
+ F9988AB30D814C6500B6B03B /* Debug gcc40 */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)";
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "__private_extern__=extern",
+ "$(GCC_PREPROCESSOR_DEFINITIONS)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = "Debug gcc40";
+ };
+ F9988AB40D814C6500B6B03B /* Debug gcc40 */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)";
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "__private_extern__=extern",
+ "$(GCC_PREPROCESSOR_DEFINITIONS)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = "Debug gcc40";
+ };
+ F9988AB50D814C7500B6B03B /* Debug llvm-gcc */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tk-Debug.xcconfig */;
+ buildSettings = {
+ ARCHS = (
+ "$(NATIVE_ARCH_64_BIT)",
+ "$(NATIVE_ARCH_32_BIT)",
+ );
+ CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
+ GCC = "llvm-gcc";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ GCC_VERSION = com.apple.compilers.llvmgcc42;
+ MACOSX_DEPLOYMENT_TARGET = 10.6;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ };
+ name = "Debug llvm-gcc";
+ };
+ F9988AB60D814C7500B6B03B /* Debug llvm-gcc */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = "Debug llvm-gcc";
+ };
+ F9988AB70D814C7500B6B03B /* Debug llvm-gcc */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)";
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "__private_extern__=extern",
+ "$(GCC_PREPROCESSOR_DEFINITIONS)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = "Debug llvm-gcc";
+ };
+ F9988AB80D814C7500B6B03B /* Debug llvm-gcc */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)";
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "__private_extern__=extern",
+ "$(GCC_PREPROCESSOR_DEFINITIONS)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = "Debug llvm-gcc";
+ };
+ F9988BB10D81586D00B6B03B /* ReleaseUniversal gcc40 */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tk-Release.xcconfig */;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ GCC_VERSION = 4.0;
+ MACOSX_DEPLOYMENT_TARGET = 10.6;
+ PREBINDING = NO;
+ };
+ name = "ReleaseUniversal gcc40";
+ };
+ F9988BB20D81586D00B6B03B /* ReleaseUniversal gcc40 */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = "ReleaseUniversal gcc40";
+ };
+ F9988BB30D81586D00B6B03B /* ReleaseUniversal gcc40 */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = "ReleaseUniversal gcc40";
+ };
+ F9988BB40D81586D00B6B03B /* ReleaseUniversal gcc40 */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)";
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = "ReleaseUniversal gcc40";
+ };
+ F9988BB50D81587400B6B03B /* ReleaseUniversal llvm-gcc */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tk-Release.xcconfig */;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)";
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ GCC = "llvm-gcc";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ GCC_OPTIMIZATION_LEVEL = 4;
+ "GCC_OPTIMIZATION_LEVEL[arch=ppc]" = s;
+ GCC_VERSION = com.apple.compilers.llvmgcc42;
+ MACOSX_DEPLOYMENT_TARGET = 10.6;
+ PREBINDING = NO;
+ };
+ name = "ReleaseUniversal llvm-gcc";
+ };
+ F9988BB60D81587400B6B03B /* ReleaseUniversal llvm-gcc */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = "ReleaseUniversal llvm-gcc";
+ };
+ F9988BB70D81587400B6B03B /* ReleaseUniversal llvm-gcc */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = "ReleaseUniversal llvm-gcc";
+ };
+ F9988BB80D81587400B6B03B /* ReleaseUniversal llvm-gcc */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)";
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = "ReleaseUniversal llvm-gcc";
+ };
+ F99EE73B0BE835310060D4AF /* DebugUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = DebugUnthreaded;
+ };
+ F99EE73C0BE835310060D4AF /* DebugLeaks */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = DebugLeaks;
+ };
+ F99EE73D0BE835310060D4AF /* DebugUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = DebugUnthreaded;
+ };
+ F99EE73E0BE835310060D4AF /* DebugLeaks */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = DebugLeaks;
+ };
+ F99EE73F0BE835310060D4AF /* DebugUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = DebugUnthreaded;
+ };
+ F99EE7400BE835310060D4AF /* DebugLeaks */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = DebugLeaks;
+ };
+ F99EE7410BE835310060D4AF /* DebugUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tk-Debug.xcconfig */;
+ buildSettings = {
+ ARCHS = (
+ "$(NATIVE_ARCH_64_BIT)",
+ "$(NATIVE_ARCH_32_BIT)",
+ );
+ CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --disable-threads";
+ CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ MACOSX_DEPLOYMENT_TARGET = 10.6;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ };
+ name = DebugUnthreaded;
+ };
+ F99EE7420BE835310060D4AF /* DebugLeaks */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tk-Debug.xcconfig */;
+ buildSettings = {
+ ARCHS = (
+ "$(NATIVE_ARCH_64_BIT)",
+ "$(NATIVE_ARCH_32_BIT)",
+ );
+ CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = unsupported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ PURIFY,
+ "$(GCC_PREPROCESSOR_DEFINITIONS)",
+ );
+ MACOSX_DEPLOYMENT_TARGET = 10.6;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ RUN_CLANG_STATIC_ANALYZER = YES;
+ };
+ name = DebugLeaks;
+ };
+ F9A9D1EF0FC77787002A2BE3 /* Debug clang */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tk-Debug.xcconfig */;
+ buildSettings = {
+ ARCHS = (
+ "$(NATIVE_ARCH_64_BIT)",
+ "$(NATIVE_ARCH_32_BIT)",
+ );
+ CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
+ GCC = clang;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ MACOSX_DEPLOYMENT_TARGET = 10.6;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ };
+ name = "Debug clang";
+ };
+ F9A9D1F00FC77787002A2BE3 /* Debug clang */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = "Debug clang";
+ };
+ F9A9D1F10FC77787002A2BE3 /* Debug clang */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)";
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "__private_extern__=extern",
+ "$(GCC_PREPROCESSOR_DEFINITIONS)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = "Debug clang";
+ };
+ F9A9D1F20FC77787002A2BE3 /* Debug clang */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)";
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "__private_extern__=extern",
+ "$(GCC_PREPROCESSOR_DEFINITIONS)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = "Debug clang";
+ };
+ F9A9D1F30FC77799002A2BE3 /* ReleaseUniversal clang */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tk-Release.xcconfig */;
+ buildSettings = {
+ ARCHS = (
+ "$(NATIVE_ARCH_64_BIT)",
+ "$(NATIVE_ARCH_32_BIT)",
+ );
+ CFLAGS = "-arch i386 -arch x86_64 $(CFLAGS)";
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ GCC = clang;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ GCC_OPTIMIZATION_LEVEL = 4;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ MACOSX_DEPLOYMENT_TARGET = 10.6;
+ PREBINDING = NO;
+ };
+ name = "ReleaseUniversal clang";
+ };
+ F9A9D1F40FC77799002A2BE3 /* ReleaseUniversal clang */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = "ReleaseUniversal clang";
+ };
+ F9A9D1F50FC77799002A2BE3 /* ReleaseUniversal clang */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = "ReleaseUniversal clang";
+ };
+ F9A9D1F60FC77799002A2BE3 /* ReleaseUniversal clang */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)";
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = "ReleaseUniversal clang";
+ };
+ F9EEED960C2FEFD300396116 /* ReleaseUniversal10.5SDK */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = Wish;
+ SKIP_INSTALL = NO;
+ };
+ name = ReleaseUniversal10.5SDK;
+ };
+ F9EEED970C2FEFD300396116 /* ReleaseUniversal10.5SDK */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS_AQUA)",
+ "$(OTHER_LDFLAGS)",
+ );
+ PRODUCT_NAME = tktest;
+ };
+ name = ReleaseUniversal10.5SDK;
+ };
+ F9EEED980C2FEFD300396116 /* ReleaseUniversal10.5SDK */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)";
+ GCC_INPUT_FILETYPE = sourcecode.c.c;
+ HEADER_SEARCH_PATHS = (
+ /usr/X11R6/include,
+ /usr/X11R6/include/freetype2,
+ "$(HEADER_SEARCH_PATHS)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ /usr/X11R6/lib,
+ "$(LIBRARY_SEARCH_PATHS)",
+ );
+ PRODUCT_NAME = "tktest-X11";
+ };
+ name = ReleaseUniversal10.5SDK;
+ };
+ F9EEED990C2FEFD300396116 /* ReleaseUniversal10.5SDK */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tk-Release.xcconfig */;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)";
+ CPPFLAGS = "-isysroot $(SDKROOT) $(CPPFLAGS)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = supported;
+ GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_INPUT_FILETYPE = sourcecode.c.objc;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ PREBINDING = NO;
+ SDKROOT = macosx10.5;
+ };
+ name = ReleaseUniversal10.5SDK;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ F95CC8AB09158F3100EA5ACE /* Build configuration list for PBXNativeTarget "Tk" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F95CC8AC09158F3100EA5ACE /* Debug */,
+ F9A9D1F00FC77787002A2BE3 /* Debug clang */,
+ F9988AB60D814C7500B6B03B /* Debug llvm-gcc */,
+ F9988AB20D814C6500B6B03B /* Debug gcc40 */,
+ F90E36D60F3B5C8400810A10 /* DebugNoGC */,
+ F95CC8AE09158F3100EA5ACE /* DebugNoFixAndContinue */,
+ F99EE73B0BE835310060D4AF /* DebugUnthreaded */,
+ F98751300DE7B57E00B1C9EC /* DebugNoCF */,
+ F98751340DE7B5A200B1C9EC /* DebugNoCFUnthreaded */,
+ F93084370BB93D2800CD0B9E /* DebugMemCompile */,
+ F99EE73C0BE835310060D4AF /* DebugLeaks */,
+ F9359B260DF212DA00E04F67 /* DebugGCov */,
+ F97AED1B0B660B2100310EA2 /* Debug64bit */,
+ F95CC8AD09158F3100EA5ACE /* Release */,
+ F91BCC4F093152310042A6BF /* ReleaseUniversal */,
+ F9A9D1F40FC77799002A2BE3 /* ReleaseUniversal clang */,
+ F9988BB60D81587400B6B03B /* ReleaseUniversal llvm-gcc */,
+ F9988BB20D81586D00B6B03B /* ReleaseUniversal gcc40 */,
+ F9EEED960C2FEFD300396116 /* ReleaseUniversal10.5SDK */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ F95CC8B009158F3100EA5ACE /* Build configuration list for PBXNativeTarget "tktest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F95CC8B109158F3100EA5ACE /* Debug */,
+ F9A9D1F10FC77787002A2BE3 /* Debug clang */,
+ F9988AB70D814C7500B6B03B /* Debug llvm-gcc */,
+ F9988AB30D814C6500B6B03B /* Debug gcc40 */,
+ F90E36D70F3B5C8400810A10 /* DebugNoGC */,
+ F95CC8B309158F3100EA5ACE /* DebugNoFixAndContinue */,
+ F99EE73D0BE835310060D4AF /* DebugUnthreaded */,
+ F98751310DE7B57E00B1C9EC /* DebugNoCF */,
+ F98751350DE7B5A200B1C9EC /* DebugNoCFUnthreaded */,
+ F93084380BB93D2800CD0B9E /* DebugMemCompile */,
+ F99EE73E0BE835310060D4AF /* DebugLeaks */,
+ F9359B270DF212DA00E04F67 /* DebugGCov */,
+ F97AED1C0B660B2100310EA2 /* Debug64bit */,
+ F95CC8B209158F3100EA5ACE /* Release */,
+ F91BCC50093152310042A6BF /* ReleaseUniversal */,
+ F9A9D1F50FC77799002A2BE3 /* ReleaseUniversal clang */,
+ F9988BB70D81587400B6B03B /* ReleaseUniversal llvm-gcc */,
+ F9988BB30D81586D00B6B03B /* ReleaseUniversal gcc40 */,
+ F9EEED970C2FEFD300396116 /* ReleaseUniversal10.5SDK */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ F95CC8B509158F3100EA5ACE /* Build configuration list for PBXProject "Tk" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F95CC8B609158F3100EA5ACE /* Debug */,
+ F9A9D1EF0FC77787002A2BE3 /* Debug clang */,
+ F9988AB50D814C7500B6B03B /* Debug llvm-gcc */,
+ F9988AB10D814C6500B6B03B /* Debug gcc40 */,
+ F90E36D50F3B5C8400810A10 /* DebugNoGC */,
+ F95CC8B809158F3100EA5ACE /* DebugNoFixAndContinue */,
+ F99EE7410BE835310060D4AF /* DebugUnthreaded */,
+ F987512F0DE7B57E00B1C9EC /* DebugNoCF */,
+ F98751330DE7B5A200B1C9EC /* DebugNoCFUnthreaded */,
+ F930843A0BB93D2800CD0B9E /* DebugMemCompile */,
+ F99EE7420BE835310060D4AF /* DebugLeaks */,
+ F9359B250DF212DA00E04F67 /* DebugGCov */,
+ F97AED1E0B660B2100310EA2 /* Debug64bit */,
+ F95CC8B709158F3100EA5ACE /* Release */,
+ F91BCC51093152310042A6BF /* ReleaseUniversal */,
+ F9A9D1F30FC77799002A2BE3 /* ReleaseUniversal clang */,
+ F9988BB50D81587400B6B03B /* ReleaseUniversal llvm-gcc */,
+ F9988BB10D81586D00B6B03B /* ReleaseUniversal gcc40 */,
+ F9EEED990C2FEFD300396116 /* ReleaseUniversal10.5SDK */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ F97258A80A86873D00096C78 /* Build configuration list for PBXNativeTarget "tktest-X11" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F97258A90A86873D00096C78 /* Debug */,
+ F9A9D1F20FC77787002A2BE3 /* Debug clang */,
+ F9988AB80D814C7500B6B03B /* Debug llvm-gcc */,
+ F9988AB40D814C6500B6B03B /* Debug gcc40 */,
+ F90E36D80F3B5C8400810A10 /* DebugNoGC */,
+ F97258AB0A86873D00096C78 /* DebugNoFixAndContinue */,
+ F99EE73F0BE835310060D4AF /* DebugUnthreaded */,
+ F98751320DE7B57E00B1C9EC /* DebugNoCF */,
+ F98751360DE7B5A200B1C9EC /* DebugNoCFUnthreaded */,
+ F93084390BB93D2800CD0B9E /* DebugMemCompile */,
+ F99EE7400BE835310060D4AF /* DebugLeaks */,
+ F9359B280DF212DA00E04F67 /* DebugGCov */,
+ F97AED1D0B660B2100310EA2 /* Debug64bit */,
+ F97258AA0A86873D00096C78 /* Release */,
+ F97258AC0A86873D00096C78 /* ReleaseUniversal */,
+ F9A9D1F60FC77799002A2BE3 /* ReleaseUniversal clang */,
+ F9988BB80D81587400B6B03B /* ReleaseUniversal llvm-gcc */,
+ F9988BB40D81586D00B6B03B /* ReleaseUniversal gcc40 */,
+ F9EEED980C2FEFD300396116 /* ReleaseUniversal10.5SDK */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
+}
diff --git a/tk8.6/macosx/Wish-Info.plist.in b/tk8.6/macosx/Wish-Info.plist.in
new file mode 100644
index 0000000..d6f48e9
--- /dev/null
+++ b/tk8.6/macosx/Wish-Info.plist.in
@@ -0,0 +1,116 @@
+<?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">
+<!--
+ Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ Copyright 2008-2009, Apple Inc.
+
+ See the file "license.terms" for information on usage and redistribution of
+ this file, and for a DISCLAIMER OF ALL WARRANTIES.
+-->
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleDocumentTypes</key>
+ <array>
+ <dict>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>tcl</string>
+ <string>TCL</string>
+ <string>*</string>
+ </array>
+ <key>CFBundleTypeMIMETypes</key>
+ <array>
+ <string>application/x-tcl</string>
+ <string>text/plain</string>
+ </array>
+ <key>CFBundleTypeName</key>
+ <string>NSStringPboardType</string>
+ <key>CFBundleTypeOSTypes</key>
+ <array>
+ <string>TEXT</string>
+ <string>****</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Viewer</string>
+ </dict>
+ </array>
+ <key>CFBundleURLTypes</key>
+ <array>
+ <dict>
+ <key>CFBundleTypeRole</key>
+ <string>Viewer</string>
+ <key>CFBundleURLSchemes</key>
+ <array>
+ <string>foo</string>
+ </array>
+ <key>CFBundleURLName</key>
+ <string>Get Foo</string>
+ </dict>
+ </array>
+ <key>CFBundleExecutable</key>
+ <string>Wish</string>
+ <key>CFBundleGetInfoString</key>
+ <string>Wish Shell @TK_VERSION@@TK_PATCH_LEVEL@,
+ Copyright © 1989-@TK_YEAR@ Tcl Core Team,
+ Copyright © 1989-@TK_YEAR@ Contributors,
+ Copyright © 2011-@TK_YEAR@ Kevin Walzer/WordTech
+ Communications LLC,
+ Copyright © 2014-@TK_YEAR@ Marc Culler,
+ Copyright © 2002-@TK_YEAR@ Daniel A. Steffen,
+ Copyright © 2001-2009 Apple Inc.,
+ Copyright © 2001-2002 Jim Ingham &amp; Ian Reid</string>
+ <key>CFBundleIconFile</key>
+ <string>Wish.icns</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.tcltk.wish</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleLocalizations</key>
+ <array>
+ @CFBUNDLELOCALIZATIONS@
+ </array>
+ <key>CFBundleName</key>
+ <string>Wish</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>@TK_VERSION@@TK_PATCH_LEVEL@</string>
+ <key>CFBundleSignature</key>
+ <string>WiSH</string>
+ <key>CFBundleVersion</key>
+ <string>@TK_VERSION@@TK_PATCH_LEVEL@</string>
+ <key>LSMinimumSystemVersion</key>
+ <string>10.6.0</string>
+ <key>LSRequiresCarbon</key>
+ <true/>
+ <key>NSAppleScriptEnabled</key>
+ <true/>
+ <key>OSAScriptingDefinition</key>
+ <string>Wish.sdef</string>
+ <key>NSHighResolutionCapable</key>
+ <string>True</string>
+ <key>NSServices</key>
+ <array>
+ <dict>
+ <key>NSMenuItem</key>
+ <dict>
+ <key>default</key>
+ <string>Wish: Display Test Data</string>
+ </dict>
+ <key>NSMessage</key>
+ <string>provideService</string>
+ <key>NSPortName</key>
+ <string>Wish</string>
+
+ <key>NSSendTypes</key>
+ <array>
+ <string>NSStringPboardType</string>
+ <string>NSPasteboardTypeString</string>
+ </array>
+ </dict>
+ </array>
+
+</dict>
+</plist>
diff --git a/tk8.6/macosx/Wish.sdef b/tk8.6/macosx/Wish.sdef
new file mode 100644
index 0000000..6639f70
--- /dev/null
+++ b/tk8.6/macosx/Wish.sdef
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE dictionary SYSTEM "file://localhost/System/Library/DTDs/sdef.dtd">
+<!--
+ Copyright (c) 1997 Sun Microsystems, Inc.
+ Copyright 2009 Kevin Walzer/WordTech Communications LLC.
+ Copyright (c) 2009 Daniel A. Steffen <das@users.sourceforge.net>
+
+ See the file "license.terms" for information on usage and redistribution of
+ this file, and for a DISCLAIMER OF ALL WARRANTIES.
+-->
+<dictionary title="Wish Terminology">
+ <suite name="Standard Suite" code="reqd" description="Common commands for all applications.">
+ <command name="open" code="aevtodoc" description="Open a document.">
+ <direct-parameter description="The file(s) to be opened.">
+ <type type="file"/>
+ <type type="file" list="yes"/>
+ </direct-parameter>
+ </command>
+ <command name="print" code="aevtpdoc" description="Print a document.">
+ <direct-parameter description="The file(s) to be printed.">
+ <type type="file" list="yes"/>
+ <type type="specifier"/>
+ </direct-parameter>
+ </command>
+ <command name="quit" code="aevtquit" description="Quit the application."/>
+ </suite>
+ <suite name="Wish Suite" code="WIsH" description="Commands for the Wish application.">
+ <command name="do script" code="miscdosc" description="Execute a Tcl script.">
+ <direct-parameter description="Script to execute" type="text">
+ <type type="text"/>
+ </direct-parameter>
+ <result description="Result">
+ <type type="text"/>
+ </result>
+ </command>
+ <command name="open location" code="GURLGURL"
+ description="Open a URL.">
+ <direct-parameter description="URL" type="text">
+ <type type="text"/>
+ </direct-parameter>
+ <result description="Result">
+ <type type="text"/>
+ </result>
+ </command>
+ </suite>
+</dictionary>
diff --git a/tk8.6/macosx/configure.ac b/tk8.6/macosx/configure.ac
new file mode 100644
index 0000000..69573c5
--- /dev/null
+++ b/tk8.6/macosx/configure.ac
@@ -0,0 +1,11 @@
+#! /bin/bash -norc
+dnl This file is an input file used by the GNU "autoconf" program to
+dnl generate the file "configure", which is run during Tk installation
+dnl to configure the system for the local environment.
+
+dnl Ensure that the config (auto)headers support is used, then just
+dnl include the configure sources from ../unix:
+
+m4_include(../unix/aclocal.m4)
+m4_define(SC_USE_CONFIG_HEADERS)
+m4_include(../unix/configure.in)
diff --git a/tk8.6/macosx/tkMacOSX.h b/tk8.6/macosx/tkMacOSX.h
new file mode 100644
index 0000000..05ea6c2
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSX.h
@@ -0,0 +1,34 @@
+/*
+ * tkMacOSX.h --
+ *
+ * Declarations of Macintosh specific exported variables and procedures.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ * Copyright 2001-2009, Apple Inc.
+ * Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef _TKMAC
+#define _TKMAC
+
+#ifndef _TK
+#include "tk.h"
+#endif
+
+/*
+ * Structures and function types for handling Netscape-type in process
+ * embedding where Tk does not control the top-level
+ */
+
+typedef int (Tk_MacOSXEmbedRegisterWinProc) (long winID, Tk_Window window);
+typedef void* (Tk_MacOSXEmbedGetGrafPortProc) (Tk_Window window);
+typedef int (Tk_MacOSXEmbedMakeContainerExistProc) (Tk_Window window);
+typedef void (Tk_MacOSXEmbedGetClipProc) (Tk_Window window, TkRegion rgn);
+typedef void (Tk_MacOSXEmbedGetOffsetInParentProc) (Tk_Window window, void *ulCorner);
+
+#include "tkPlatDecls.h"
+
+#endif /* _TKMAC */
diff --git a/tk8.6/macosx/tkMacOSXBitmap.c b/tk8.6/macosx/tkMacOSXBitmap.c
new file mode 100644
index 0000000..e8cb211
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXBitmap.c
@@ -0,0 +1,428 @@
+/*
+ * tkMacOSXBitmap.c --
+ *
+ * This file handles the implementation of native bitmaps.
+ *
+ * Copyright (c) 1996-1997 Sun Microsystems, Inc.
+ * Copyright 2001-2009, Apple Inc.
+ * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkMacOSXPrivate.h"
+#include "tkMacOSXConstants.h"
+/*
+ * This structure holds information about native bitmaps.
+ */
+
+typedef struct {
+ const char *name; /* Name of icon. */
+ OSType iconType; /* OSType of icon. */
+} BuiltInIcon;
+
+/*
+ * This array mapps a string name to the supported builtin icons
+ * on the Macintosh.
+ */
+
+static BuiltInIcon builtInIcons[] = {
+ {"document", kGenericDocumentIcon},
+ {"stationery", kGenericStationeryIcon},
+ {"edition", kGenericEditionFileIcon},
+ {"application", kGenericApplicationIcon},
+ {"accessory", kGenericDeskAccessoryIcon},
+ {"folder", kGenericFolderIcon},
+ {"pfolder", kPrivateFolderIcon},
+ {"trash", kTrashIcon},
+ {"floppy", kGenericFloppyIcon},
+ {"ramdisk", kGenericRAMDiskIcon},
+ {"cdrom", kGenericCDROMIcon},
+ {"preferences", kGenericPreferencesIcon},
+ {"querydoc", kGenericQueryDocumentIcon},
+ {"stop", kAlertStopIcon},
+ {"note", kAlertNoteIcon},
+ {"caution", kAlertCautionIcon},
+ {NULL}
+};
+
+#define builtInIconSize 32
+
+#define OSTYPE_TO_UTI(x) (NSString *)UTTypeCreatePreferredIdentifierForTag( \
+ kUTTagClassOSType, UTCreateStringForOSType(x), nil)
+
+static Tcl_HashTable iconBitmapTable = {};
+typedef struct {
+ int kind, width, height;
+ char *value;
+} IconBitmap;
+
+static const char *const iconBitmapOptionStrings[] = {
+ "-file", "-fileType", "-osType", "-systemType", "-namedImage",
+ "-imageFile", NULL
+};
+enum iconBitmapOptions {
+ ICON_FILE, ICON_FILETYPE, ICON_OSTYPE, ICON_SYSTEMTYPE, ICON_NAMEDIMAGE,
+ ICON_IMAGEFILE,
+};
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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(void)
+{
+ Tcl_HashTable *tablePtr = TkGetBitmapPredefTable();
+ BuiltInIcon *builtInPtr;
+
+ for (builtInPtr = builtInIcons; builtInPtr->name != NULL; builtInPtr++) {
+ Tcl_HashEntry *predefHashPtr;
+ Tk_Uid name;
+ int isNew;
+
+ name = Tk_GetUid(builtInPtr->name);
+ predefHashPtr = Tcl_CreateHashEntry(tablePtr, name, &isNew);
+ if (isNew) {
+ TkPredefBitmap *predefPtr = ckalloc(sizeof(TkPredefBitmap));
+
+ predefPtr->source = UINT2PTR(builtInPtr->iconType);
+ predefPtr->width = builtInIconSize;
+ predefPtr->height = builtInIconSize;
+ predefPtr->native = 1;
+ Tcl_SetHashValue(predefHashPtr, predefPtr);
+ }
+ }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PixmapFromImage --
+ *
+ * Results:
+ * Returns a Pixmap with an NSImage drawn into it.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Pixmap
+PixmapFromImage(
+ Display *display,
+ NSImage* image,
+ CGSize size)
+{
+ TkMacOSXDrawingContext dc;
+ Pixmap pixmap;
+
+ pixmap = Tk_GetPixmap(display, None, size.width, size.height, 0);
+ if (TkMacOSXSetupDrawingContext(pixmap, NULL, 1, &dc)) {
+ if (dc.context) {
+ CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1,
+ .tx = 0, .ty = size.height};
+ CGContextConcatCTM(dc.context, t);
+ [NSGraphicsContext saveGraphicsState];
+ [NSGraphicsContext setCurrentContext:[NSGraphicsContext
+ graphicsContextWithGraphicsPort:dc.context
+ flipped:NO]];
+ [image drawAtPoint:NSZeroPoint fromRect:NSZeroRect
+ operation:NSCompositeCopy fraction:1.0];
+ [NSGraphicsContext restoreGraphicsState];
+ }
+ TkMacOSXRestoreDrawingContext(&dc);
+ }
+ return pixmap;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpCreateNativeBitmap --
+ *
+ * Create native bitmap.
+ *
+ * Results:
+ * Native bitmap.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Pixmap
+TkpCreateNativeBitmap(
+ Display *display,
+ const void *source) /* Info about the icon to build. */
+{
+ NSString *iconUTI = OSTYPE_TO_UTI(PTR2UINT(source));
+ NSImage *iconImage = [[NSWorkspace sharedWorkspace]
+ iconForFileType: iconUTI];
+ CGSize size = CGSizeMake(builtInIconSize, builtInIconSize);
+ Pixmap pixmap = PixmapFromImage(display, iconImage, NSSizeToCGSize(size));
+ return pixmap;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * OSTypeFromString --
+ *
+ * Helper to convert string to OSType.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * t is set to OSType if conversion successful.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+OSTypeFromString(const char *s, OSType *t) {
+ int result = TCL_ERROR;
+ Tcl_DString ds;
+ Tcl_Encoding encoding = Tcl_GetEncoding(NULL, "macRoman");
+
+ Tcl_UtfToExternalDString(encoding, s, -1, &ds);
+ if (Tcl_DStringLength(&ds) <= 4) {
+ char string[4] = {};
+ memcpy(string, Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));
+ *t = (OSType) string[0] << 24 | (OSType) string[1] << 16 |
+ (OSType) string[2] << 8 | (OSType) string[3];
+ result = TCL_OK;
+ }
+ Tcl_DStringFree(&ds);
+ Tcl_FreeEncoding(encoding);
+ return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpGetNativeAppBitmap --
+ *
+ * Get a named native bitmap.
+ *
+ * Attemps to interpret the given name in order as:
+ * - name defined by ::tk::mac::iconBitmap
+ * - NSImage named image name
+ * - NSImage url string
+ * - 4-char OSType of IconServices icon
+ *
+ * Results:
+ * Native bitmap or None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Pixmap
+TkpGetNativeAppBitmap(
+ Display *display, /* The display. */
+ const char *name, /* The name of the bitmap. */
+ int *width, /* The width & height of the bitmap. */
+ int *height)
+{
+ Tcl_HashEntry *hPtr;
+ Pixmap pixmap = None;
+ NSString *string;
+ NSImage *image = nil;
+ NSSize size = { .width = builtInIconSize, .height = builtInIconSize };
+
+ if (iconBitmapTable.buckets &&
+ (hPtr = Tcl_FindHashEntry(&iconBitmapTable, name))) {
+ OSType type;
+ IconBitmap *iconBitmap = Tcl_GetHashValue(hPtr);
+ name = NULL;
+ size = NSMakeSize(iconBitmap->width, iconBitmap->height);
+ switch (iconBitmap->kind) {
+ case ICON_FILE:
+ string = [[NSString stringWithUTF8String:iconBitmap->value]
+ stringByExpandingTildeInPath];
+ image = [[NSWorkspace sharedWorkspace] iconForFile:string];
+ break;
+ case ICON_FILETYPE:
+ string = [NSString stringWithUTF8String:iconBitmap->value];
+ image = [[NSWorkspace sharedWorkspace] iconForFileType:string];
+ break;
+ case ICON_OSTYPE:
+ if (OSTypeFromString(iconBitmap->value, &type) == TCL_OK) {
+ string = NSFileTypeForHFSTypeCode(type);
+ image = [[NSWorkspace sharedWorkspace] iconForFileType:string];
+ }
+ break;
+ case ICON_SYSTEMTYPE:
+ name = iconBitmap->value;
+ break;
+ case ICON_NAMEDIMAGE:
+ string = [NSString stringWithUTF8String:iconBitmap->value];
+ image = [NSImage imageNamed:string];
+ break;
+ case ICON_IMAGEFILE:
+ string = [[NSString stringWithUTF8String:iconBitmap->value]
+ stringByExpandingTildeInPath];
+ image = [[[NSImage alloc] initWithContentsOfFile:string]
+ autorelease];
+ break;
+ }
+ if (image) {
+ [image setSize:size];
+ }
+ } else {
+ string = [NSString stringWithUTF8String:name];
+ image = [NSImage imageNamed:string];
+ if (!image) {
+ NSURL *url = [NSURL fileURLWithPath:string];
+ if (url) {
+ image = [[[NSImage alloc] initWithContentsOfURL:url]
+ autorelease];
+ }
+ }
+ if (image) {
+ size = [image size];
+ }
+ }
+ if (image) {
+ *width = size.width;
+ *height = size.height;
+ pixmap = PixmapFromImage(display, image, NSSizeToCGSize(size));
+ } else if (name) {
+ OSType iconType;
+ if (OSTypeFromString(name, &iconType) == TCL_OK) {
+ NSString *iconUTI = OSTYPE_TO_UTI(iconType);
+ printf("Found image for UTI %s\n", iconUTI.UTF8String);
+ NSImage *iconImage = [[NSWorkspace sharedWorkspace]
+ iconForFileType: iconUTI];
+ pixmap = PixmapFromImage(display, iconImage, NSSizeToCGSize(size));
+ }
+ }
+ return pixmap;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXIconBitmapObjCmd --
+ *
+ * Implements the ::tk::mac::iconBitmap command.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * none
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkMacOSXIconBitmapObjCmd(
+ ClientData clientData, /* Unused. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Tcl_HashEntry *hPtr;
+ int i = 1, len, isNew, result = TCL_ERROR;
+ const char *name, *value;
+ IconBitmap ib, *iconBitmap;
+
+ if (objc != 6) {
+ Tcl_WrongNumArgs(interp, 1, objv, "name width height "
+ "-file|-fileType|-osType|-systemType|-namedImage|-imageFile "
+ "value");
+ goto end;
+ }
+ name = Tcl_GetStringFromObj(objv[i++], &len);
+ if (!len) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("empty bitmap name", -1));
+ Tcl_SetErrorCode(interp, "TK", "MACBITMAP", "BAD", NULL);
+ goto end;
+ }
+ if (Tcl_GetIntFromObj(interp, objv[i++], &ib.width) != TCL_OK) {
+ goto end;
+ }
+ if (Tcl_GetIntFromObj(interp, objv[i++], &ib.height) != TCL_OK) {
+ goto end;
+ }
+ if (Tcl_GetIndexFromObjStruct(interp, objv[i++], iconBitmapOptionStrings,
+ sizeof(char *), "kind", TCL_EXACT, &ib.kind) != TCL_OK) {
+ goto end;
+ }
+ value = Tcl_GetStringFromObj(objv[i++], &len);
+ if (!len) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("empty bitmap value", -1));
+ Tcl_SetErrorCode(interp, "TK", "MACBITMAP", "EMPTY", NULL);
+ goto end;
+ }
+#if 0
+ if ((kind == ICON_TYPE || kind == ICON_SYSTEM)) {
+ Tcl_DString ds;
+ Tcl_Encoding encoding = Tcl_GetEncoding(NULL, "macRoman");
+
+ Tcl_UtfToExternalDString(encoding, value, -1, &ds);
+ len = Tcl_DStringLength(&ds);
+ Tcl_DStringFree(&ds);
+ Tcl_FreeEncoding(encoding);
+ if (len > 4) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "invalid bitmap value", -1));
+ Tcl_SetErrorCode(interp, "TK", "MACBITMAP", "INVALID", NULL);
+ goto end;
+ }
+ }
+#endif
+ ib.value = ckalloc(len + 1);
+ strcpy(ib.value, value);
+ if (!iconBitmapTable.buckets) {
+ Tcl_InitHashTable(&iconBitmapTable, TCL_STRING_KEYS);
+ }
+ hPtr = Tcl_CreateHashEntry(&iconBitmapTable, name, &isNew);
+ if (!isNew) {
+ iconBitmap = Tcl_GetHashValue(hPtr);
+ ckfree(iconBitmap->value);
+ } else {
+ iconBitmap = ckalloc(sizeof(IconBitmap));
+ Tcl_SetHashValue(hPtr, iconBitmap);
+ }
+ *iconBitmap = ib;
+ result = TCL_OK;
+ end:
+ return result;
+}
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXButton.c b/tk8.6/macosx/tkMacOSXButton.c
new file mode 100644
index 0000000..00c7c9b
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXButton.c
@@ -0,0 +1,1185 @@
+/*
+ * 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.
+ * Copyright (c) 2006-2007 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright 2007 Revar Desmera.
+ * Copyright 2015 Kevin Walzer/WordTech Communications LLC.
+ * Copyright 2015 Marc Culler.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ */
+
+#include "tkMacOSXPrivate.h"
+#include "tkButton.h"
+#include "tkMacOSXFont.h"
+#include "tkMacOSXDebug.h"
+
+#define FIRST_DRAW 2
+#define ACTIVE 4
+
+/*
+ * Extra padding used for computing the content size that should
+ * be allowed when drawing the HITheme button.
+ */
+
+#define HI_PADX 14
+#define HI_PADY 1
+
+/*
+ * The delay in milliseconds between pulsing default button redraws.
+ */
+#define PULSE_TIMER_MSECS 62 /* Largest value that didn't look stuttery */
+
+/*
+ * Declaration of Mac specific button structure.
+ */
+
+
+typedef struct {
+ 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 */
+ ThemeButtonKind btnkind;
+ HIThemeButtonDrawInfo drawinfo;
+ HIThemeButtonDrawInfo lastdrawinfo;
+ DrawParams drawParams;
+ Tcl_TimerToken defaultPulseHandler;
+} MacButton;
+
+/*
+ * Forward declarations for procedures defined later in this file:
+ */
+
+static void ButtonBackgroundDrawCB(const HIRect *btnbounds,
+ MacButton *ptr, SInt16 depth, Boolean isColorDev);
+static void ButtonContentDrawCB(const HIRect *bounds,
+ ThemeButtonKind kind,
+ const HIThemeButtonDrawInfo *info, MacButton *ptr,
+ SInt16 depth, Boolean isColorDev);
+static void ButtonEventProc(ClientData clientData,
+ XEvent *eventPtr);
+static void TkMacOSXComputeButtonParams(TkButton *butPtr,
+ ThemeButtonKind *btnkind,
+ HIThemeButtonDrawInfo *drawinfo);
+static int TkMacOSXComputeButtonDrawParams(TkButton *butPtr,
+ DrawParams * dpPtr);
+static void TkMacOSXDrawButton(MacButton *butPtr, GC gc,
+ Pixmap pixmap);
+static void DrawButtonImageAndText(TkButton *butPtr);
+static void PulseDefaultButtonProc(ClientData clientData);
+
+/*
+ * The class procedure table for the button widgets.
+ */
+
+const Tk_ClassProcs tkpButtonProcs = {
+ sizeof(Tk_ClassProcs), /* size */
+ TkButtonWorldChanged, /* worldChangedProc */
+};
+
+static int bCount;
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpButtonSetDefaults --
+ *
+ * This procedure is invoked before option tables are created for buttons.
+ * It modifies some of the default values to match the current values
+ * defined for this platform.
+ *
+ * Results:
+ * Some of the default values in *specPtr are modified.
+ *
+ * Side effects:
+ * Updates some of.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpButtonSetDefaults()
+{
+ /*No-op.*/
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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 = ckalloc(sizeof(MacButton));
+
+ Tk_CreateEventHandler(tkwin, ActivateMask,
+ ButtonEventProc, macButtonPtr);
+ macButtonPtr->id = bCount++;
+ macButtonPtr->flags = FIRST_DRAW;
+ macButtonPtr->btnkind = kThemePushButton;
+ macButtonPtr->defaultPulseHandler = NULL;
+ bzero(&macButtonPtr->drawinfo, sizeof(macButtonPtr->drawinfo));
+ bzero(&macButtonPtr->lastdrawinfo, sizeof(macButtonPtr->lastdrawinfo));
+
+ 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 = clientData;
+ TkButton *butPtr = clientData;
+ Tk_Window tkwin = butPtr->tkwin;
+ Pixmap pixmap;
+ DrawParams* dpPtr = &macButtonPtr->drawParams;
+ int needhighlight = 0;
+
+ if (butPtr->flags & BUTTON_DELETED) {
+ return;
+ }
+ butPtr->flags &= ~REDRAW_PENDING;
+ if ((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
+ return;
+ }
+ pixmap = (Pixmap) Tk_WindowId(tkwin);
+
+ /*
+ * Set up clipping region. Make sure the we are using the port
+ * for this button, or we will set the wrong window's clip.
+ */
+
+ TkMacOSXSetUpClippingRgn(Tk_WindowId(tkwin));
+
+ if (TkMacOSXComputeButtonDrawParams(butPtr, dpPtr)) {
+ macButtonPtr->useTkText = 0;
+ } else {
+ macButtonPtr->useTkText = 1;
+ }
+ 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);
+ }
+
+ /*
+ * Display image or bitmap or text for labels or custom controls.
+ */
+
+ DrawButtonImageAndText(butPtr);
+ needhighlight = 1;
+ } else {
+ /*
+ * Draw the native portion of the buttons.
+ */
+
+ TkMacOSXDrawButton(macButtonPtr, dpPtr->gc, pixmap);
+
+ /*
+ * Ask for the highlight border, if needed.
+ */
+
+ if (butPtr->highlightWidth < 3) {
+ needhighlight = 1;
+ }
+ }
+
+ /*
+ * Draw highlight border, if needed.
+ */
+
+ if (needhighlight) {
+ GC gc = NULL;
+ if ((butPtr->flags & GOT_FOCUS) && butPtr->highlightColorPtr) {
+ gc = Tk_GCForColor(butPtr->highlightColorPtr, pixmap);
+ } else if (butPtr->type == TYPE_LABEL) {
+ gc = Tk_GCForColor(Tk_3DBorderColor(butPtr->highlightBorder), pixmap);
+ }
+ if (gc) {
+ TkMacOSXDrawSolidBorder(tkwin, gc, 0, butPtr->highlightWidth);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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 = 0, height = 0, charWidth = 1, haveImage = 0, haveText = 0;
+ int txtWidth = 0, txtHeight = 0;
+ MacButton *mbPtr = (MacButton *) butPtr;
+ Tk_FontMetrics fm;
+ char *text = Tcl_GetString(butPtr->textPtr);
+
+ TkMacOSXComputeButtonParams(butPtr, &mbPtr->btnkind, &mbPtr->drawinfo);
+
+ /*
+ * If the indicator is on, get its size.
+ */
+
+ if (butPtr->indicatorOn) {
+ switch (butPtr->type) {
+ case TYPE_RADIO_BUTTON:
+ GetThemeMetric(kThemeMetricRadioButtonWidth,
+ (SInt32 *) &butPtr->indicatorDiameter);
+ break;
+ case TYPE_CHECK_BUTTON:
+ GetThemeMetric(kThemeMetricCheckBoxWidth,
+ (SInt32 *) &butPtr->indicatorDiameter);
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * Allow 2px extra space next to the indicator.
+ */
+
+ butPtr->indicatorSpace = butPtr->indicatorDiameter + 2;
+ } else {
+ butPtr->indicatorSpace = 0;
+ butPtr->indicatorDiameter = 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,
+ text, -1, butPtr->wrapLength, butPtr->justify, 0,
+ &butPtr->textWidth, &butPtr->textHeight);
+
+ txtWidth = butPtr->textWidth + 2*butPtr->padX;
+ txtHeight = butPtr->textHeight + 2*butPtr->padY;
+ haveText = 1;
+ }
+
+ if (haveImage && haveText) { /* Image and Text */
+ 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 + 2*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;
+ default:
+ break;
+ }
+ width += butPtr->indicatorSpace;
+ } else if (haveImage) { /* Image only */
+ width = butPtr->width > 0 ? butPtr->width : width + butPtr->indicatorSpace;
+ height = butPtr->height > 0 ? butPtr->height : height;
+ if (butPtr->type == TYPE_BUTTON) {
+ /*
+ * Allow room to shift the image.
+ */
+ width += 2;
+ height += 2;
+ }
+ } else { /* Text only */
+ width = txtWidth + butPtr->indicatorSpace;
+ height = txtHeight;
+ if (butPtr->width > 0) {
+ charWidth = Tk_TextWidth(butPtr->tkfont, "0", 1);
+ width = butPtr->width * charWidth + 2*butPtr->padX;
+ }
+ if (butPtr->height > 0) {
+ Tk_GetFontMetrics(butPtr->tkfont, &fm);
+ height = butPtr->height * fm.linespace + 2*butPtr->padY;
+ }
+ }
+
+ /*
+ * Now figure out the size of the border decorations for the button.
+ */
+
+ if (butPtr->highlightWidth < 0) {
+ butPtr->highlightWidth = 0;
+ }
+
+ butPtr->inset = butPtr->borderWidth + butPtr->highlightWidth;
+
+ width += butPtr->inset*2;
+ height += butPtr->inset*2;
+ if ([NSApp macMinorVersion] == 6) {
+ width += 12;
+ }
+ if (mbPtr->btnkind == kThemePushButton) {
+ HIRect tmpRect;
+ HIRect contBounds;
+
+ /*
+ * A PushButton has a minimum size. We make sure that we are not
+ * underestimating the size by requesting the content size of a
+ * Pushbutton whose overall size is our content size expanded by the
+ * standard padding.
+ */
+
+ tmpRect = CGRectMake(0, 0, width + 2*HI_PADX, height + 2*HI_PADY);
+ HIThemeGetButtonContentBounds(&tmpRect, &mbPtr->drawinfo, &contBounds);
+ if (height < contBounds.size.height) {
+ height = contBounds.size.height;
+ }
+ if (width < contBounds.size.width) {
+ width = contBounds.size.width;
+ }
+ height += 2*HI_PADY;
+ width += 2*HI_PADX;
+ }
+ Tk_GeometryRequest(butPtr->tkwin, width, height);
+ Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DrawButtonImageAndText --
+ *
+ * Draws the image and text associated with a button or label.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The image and text are drawn.
+ *
+ *----------------------------------------------------------------------
+ */
+static void
+DrawButtonImageAndText(
+ TkButton *butPtr)
+{
+
+ MacButton *mbPtr = (MacButton *) butPtr;
+ Tk_Window tkwin = butPtr->tkwin;
+ Pixmap pixmap;
+ int haveImage = 0, haveText = 0, pressed = 0;
+ int imageWidth = 0, imageHeight = 0;
+ int imageXOffset = 0, imageYOffset = 0;
+ int textXOffset = 0, textYOffset = 0;
+ int width = 0, height = 0;
+ int fullWidth = 0, fullHeight = 0;
+
+ if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
+ return;
+ }
+
+ DrawParams *dpPtr = &mbPtr->drawParams;
+ pixmap = (Pixmap) Tk_WindowId(tkwin);
+
+ if (butPtr->image != None) {
+ Tk_SizeOfImage(butPtr->image, &width, &height);
+ haveImage = 1;
+ } else if (butPtr->bitmap != None) {
+ Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height);
+ haveImage = 1;
+ }
+
+ imageWidth = width;
+ imageHeight = height;
+
+ if (mbPtr->drawinfo.state == kThemeStatePressed) {
+ /*
+ * Offset bitmaps by a bit when the button is pressed.
+ */
+
+ pressed = 1;
+ }
+
+ haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0);
+ if (haveImage && haveText) { /* Image and Text */
+ int x, y;
+
+ 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;
+ default:
+ break;
+ }
+
+ TkComputeAnchor(butPtr->anchor, tkwin,
+ butPtr->padX + butPtr->borderWidth,
+ butPtr->padY + butPtr->borderWidth,
+ fullWidth + butPtr->indicatorSpace, fullHeight, &x, &y);
+ x += butPtr->indicatorSpace;
+
+ if (dpPtr->relief == TK_RELIEF_SUNKEN) {
+ x += dpPtr->offset;
+ y += dpPtr->offset;
+ } else if (dpPtr->relief == TK_RELIEF_RAISED) {
+ x -= dpPtr->offset;
+ y -= dpPtr->offset;
+ }
+ if (pressed) {
+ x += dpPtr->offset;
+ y += dpPtr->offset;
+ }
+ imageXOffset += x;
+ imageYOffset += y;
+
+ if (butPtr->image != NULL) {
+ if ((butPtr->selectImage != NULL) &&
+ (butPtr->flags & SELECTED)) {
+ Tk_RedrawImage(butPtr->selectImage, 0, 0,
+ width, height, pixmap, imageXOffset, imageYOffset);
+ } else if ((butPtr->tristateImage != NULL) &&
+ (butPtr->flags & TRISTATED)) {
+ Tk_RedrawImage(butPtr->tristateImage, 0, 0,
+ width, height, pixmap, imageXOffset, imageYOffset);
+ } else {
+ Tk_RedrawImage(butPtr->image, 0, 0, width,
+ height, pixmap, imageXOffset, imageYOffset);
+ }
+ } else {
+ XSetClipOrigin(butPtr->display, dpPtr->gc,
+ imageXOffset, imageYOffset);
+ XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, dpPtr->gc,
+ 0, 0, (unsigned int) width, (unsigned int) height,
+ imageXOffset, imageYOffset, 1);
+ XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0);
+ }
+
+ y += 1; /* Tweak to match native buttons. */
+ 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);
+ } else if (haveImage) { /* Image only */
+ int x = 0, y;
+
+ TkComputeAnchor(butPtr->anchor, tkwin,
+ butPtr->padX + butPtr->borderWidth,
+ butPtr->padY + butPtr->borderWidth,
+ width + butPtr->indicatorSpace, height, &x, &y);
+ x += butPtr->indicatorSpace;
+ if (pressed) {
+ x += dpPtr->offset;
+ y += dpPtr->offset;
+ }
+ imageXOffset += x;
+ imageYOffset += y;
+
+ if (butPtr->image != NULL) {
+ if ((butPtr->selectImage != NULL) &&
+ (butPtr->flags & SELECTED)) {
+ Tk_RedrawImage(butPtr->selectImage, 0, 0, width,
+ height, pixmap, imageXOffset, imageYOffset);
+ } else if ((butPtr->tristateImage != NULL) &&
+ (butPtr->flags & TRISTATED)) {
+ Tk_RedrawImage(butPtr->tristateImage, 0, 0, width,
+ height, pixmap, imageXOffset, imageYOffset);
+ } else {
+ Tk_RedrawImage(butPtr->image, 0, 0, width, height,
+ pixmap, imageXOffset, imageYOffset);
+ }
+ } else {
+ XSetClipOrigin(butPtr->display, dpPtr->gc, x, y);
+ XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, dpPtr->gc,
+ 0, 0, (unsigned int) width, (unsigned int) height,
+ imageXOffset, imageYOffset, 1);
+ XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0);
+ }
+ } else { /* Text only */
+ int x, y;
+
+ TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX, butPtr->padY,
+ butPtr->textWidth + butPtr->indicatorSpace,
+ butPtr->textHeight, &x, &y);
+ x += butPtr->indicatorSpace;
+ y += 1; /* Tweak to match native buttons */
+ Tk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc,
+ butPtr->textLayout, x, y, 0, -1);
+ }
+
+ /*
+ * If the button is disabled with a stipple rather than a special
+ * foreground color, generate the stippled effect. If the widget is
+ * selected and we use a different background color when selected, must
+ * temporarily modify the GC so the stippling is the right color.
+ */
+
+ if (mbPtr->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->stippleGC,
+ Tk_3DBorderColor(butPtr->selectBorder)->pixel);
+ }
+ /*
+ * Stipple the whole button if no disabledFg was specified,
+ * otherwise restrict stippling only to displayed image
+ */
+ if (butPtr->disabledFg == NULL) {
+ XFillRectangle(butPtr->display, pixmap, butPtr->stippleGC,
+ 0, 0, (unsigned) Tk_Width(tkwin),
+ (unsigned) Tk_Height(tkwin));
+ } else {
+ XFillRectangle(butPtr->display, pixmap, butPtr->stippleGC,
+ imageXOffset, imageYOffset,
+ (unsigned) imageWidth, (unsigned) imageHeight);
+ }
+ if ((butPtr->flags & SELECTED) && !butPtr->indicatorOn
+ && (butPtr->selectBorder != NULL)
+ ) {
+ XSetForeground(butPtr->display, butPtr->stippleGC,
+ Tk_3DBorderColor(butPtr->normalBorder)->pixel);
+ }
+ }
+
+ /*
+ * Draw the border and traversal highlight last. This way, if the
+ * button's contents overflow they'll be covered up by the border.
+ */
+
+ if (dpPtr->relief != TK_RELIEF_FLAT) {
+ int inset = butPtr->highlightWidth;
+
+ Tk_Draw3DRectangle(tkwin, pixmap, dpPtr->border, inset, inset,
+ Tk_Width(tkwin) - 2*inset, Tk_Height(tkwin) - 2*inset,
+ butPtr->borderWidth, dpPtr->relief);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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->defaultPulseHandler) {
+ Tcl_DeleteTimerHandler(mbPtr->defaultPulseHandler);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkMacOSXDrawButton --
+ *
+ * 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
+TkMacOSXDrawButton(
+ MacButton *mbPtr, /* Mac button. */
+ 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;
+ TkWindow *winPtr = (TkWindow *) butPtr->tkwin;
+ HIRect cntrRect;
+ TkMacOSXDrawingContext dc;
+ DrawParams *dpPtr = &mbPtr->drawParams;
+ int useNewerHITools = 1;
+
+ TkMacOSXComputeButtonParams(butPtr, &mbPtr->btnkind, &mbPtr->drawinfo);
+
+ cntrRect = CGRectMake(winPtr->privatePtr->xOff, winPtr->privatePtr->yOff,
+ Tk_Width(butPtr->tkwin), Tk_Height(butPtr->tkwin));
+
+ cntrRect = CGRectInset(cntrRect, butPtr->inset, butPtr->inset);
+
+ if (useNewerHITools == 1) {
+ HIRect contHIRec;
+ static HIThemeButtonDrawInfo hiinfo;
+
+ ButtonBackgroundDrawCB(&cntrRect, mbPtr, 32, true);
+
+ if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, 1, &dc)) {
+ return;
+ }
+
+ hiinfo.version = 0;
+ hiinfo.state = mbPtr->drawinfo.state;
+ hiinfo.kind = mbPtr->btnkind;
+ hiinfo.value = mbPtr->drawinfo.value;
+ hiinfo.adornment = mbPtr->drawinfo.adornment;
+ hiinfo.animation.time.current = CFAbsoluteTimeGetCurrent();
+ if (hiinfo.animation.time.start == 0) {
+ hiinfo.animation.time.start = hiinfo.animation.time.current;
+ }
+
+ /*
+ * To avoid buttons with white text on a white background, we always
+ * set the state to inactive in Dark Mode. It isn't perfect but it is
+ * usable. Using a ttk::button would be a better choice, however.
+ */
+
+ if (TkMacOSXInDarkMode(butPtr->tkwin)) {
+ hiinfo.state = kThemeStateInactive;
+ }
+ HIThemeDrawButton(&cntrRect, &hiinfo, dc.context,
+ kHIThemeOrientationNormal, &contHIRec);
+
+ TkMacOSXRestoreDrawingContext(&dc);
+ ButtonContentDrawCB(&contHIRec, mbPtr->btnkind, &mbPtr->drawinfo,
+ (MacButton *) mbPtr, 32, true);
+ } else {
+ if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, 1, &dc)) {
+ return;
+ }
+
+ TkMacOSXRestoreDrawingContext(&dc);
+ }
+ mbPtr->lastdrawinfo = mbPtr->drawinfo;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ButtonBackgroundDrawCB --
+ *
+ * This function draws the background that lies under checkboxes and
+ * radiobuttons.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The background gets updated to the current color.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ButtonBackgroundDrawCB(
+ const HIRect *btnbounds,
+ MacButton *ptr,
+ SInt16 depth,
+ Boolean isColorDev)
+{
+ MacButton *mbPtr = (MacButton *) ptr;
+ TkButton *butPtr = (TkButton *) mbPtr;
+ Tk_Window tkwin = butPtr->tkwin;
+ Pixmap pixmap;
+ int usehlborder = 0;
+
+ if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
+ return;
+ }
+ pixmap = (Pixmap) Tk_WindowId(tkwin);
+
+ if (butPtr->type != TYPE_LABEL) {
+ switch (mbPtr->btnkind) {
+ case kThemeSmallBevelButton:
+ case kThemeBevelButton:
+ case kThemeRoundedBevelButton:
+ case kThemePushButton:
+ usehlborder = 1;
+ break;
+ }
+ }
+ if (usehlborder) {
+ 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);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ButtonContentDrawCB --
+ *
+ * This function draws the label and image for the button.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The content of the button gets updated.
+ *
+ *--------------------------------------------------------------
+ */
+static void
+ButtonContentDrawCB (
+ const HIRect * btnbounds,
+ ThemeButtonKind kind,
+ const HIThemeButtonDrawInfo *drawinfo,
+ MacButton *ptr,
+ SInt16 depth,
+ Boolean isColorDev)
+{
+ TkButton *butPtr = (TkButton *) ptr;
+ Tk_Window tkwin = butPtr->tkwin;
+
+ if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
+ return;
+ }
+
+ /*
+ * Overlay Tk elements over button native region: drawing elements within
+ * button boundaries/native region causes unpredictable metrics.
+ */
+
+ DrawButtonImageAndText( butPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * 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 = clientData;
+ MacButton *mbPtr = clientData;
+
+ if (eventPtr->type == ActivateNotify
+ || eventPtr->type == DeactivateNotify) {
+ if ((buttonPtr->tkwin == NULL) || (!Tk_IsMapped(buttonPtr->tkwin))) {
+ return;
+ }
+ if (eventPtr->type == ActivateNotify) {
+ mbPtr->flags |= ACTIVE;
+ } else {
+ mbPtr->flags &= ~ACTIVE;
+ }
+ if ((buttonPtr->flags & REDRAW_PENDING) == 0) {
+ Tcl_DoWhenIdle(TkpDisplayButton, buttonPtr);
+ buttonPtr->flags |= REDRAW_PENDING;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXComputeButtonParams --
+ *
+ * This procedure computes the various parameters used when creating a
+ * Carbon Appearance control. These are determined by the various tk
+ * button parameters
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Sets the btnkind and drawinfo parameters
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+TkMacOSXComputeButtonParams(
+ TkButton *butPtr,
+ ThemeButtonKind *btnkind,
+ HIThemeButtonDrawInfo *drawinfo)
+{
+ MacButton *mbPtr = (MacButton *) butPtr;
+
+ if (butPtr->borderWidth <= 2) {
+ *btnkind = kThemeSmallBevelButton;
+ } else if (butPtr->borderWidth == 3) {
+ *btnkind = kThemeBevelButton;
+ } else if (butPtr->borderWidth == 4) {
+ *btnkind = kThemeRoundedBevelButton;
+ } else {
+ *btnkind = kThemePushButton;
+ }
+
+ if ((butPtr->image == None) && (butPtr->bitmap == None)) {
+ switch (butPtr->type) {
+ case TYPE_BUTTON:
+ *btnkind = kThemePushButton;
+ break;
+ case TYPE_RADIO_BUTTON:
+ if (butPtr->borderWidth <= 1) {
+ *btnkind = kThemeSmallRadioButton;
+ } else {
+ *btnkind = kThemeRadioButton;
+ }
+ break;
+ case TYPE_CHECK_BUTTON:
+ if (butPtr->borderWidth <= 1) {
+ *btnkind = kThemeSmallCheckBox;
+ } else {
+ *btnkind = kThemeCheckBox;
+ }
+ break;
+ }
+ }
+
+ if (butPtr->indicatorOn) {
+ switch (butPtr->type) {
+ case TYPE_RADIO_BUTTON:
+ if (butPtr->borderWidth <= 1) {
+ *btnkind = kThemeSmallRadioButton;
+ } else {
+ *btnkind = kThemeRadioButton;
+ }
+ break;
+ case TYPE_CHECK_BUTTON:
+ if (butPtr->borderWidth <= 1) {
+ *btnkind = kThemeSmallCheckBox;
+ } else {
+ *btnkind = kThemeCheckBox;
+ }
+ break;
+ }
+ } else {
+ if (butPtr->type == TYPE_RADIO_BUTTON ||
+ butPtr->type == TYPE_CHECK_BUTTON) {
+ if (*btnkind == kThemePushButton) {
+ *btnkind = kThemeBevelButton;
+ }
+ }
+ }
+
+ if (butPtr->flags & SELECTED) {
+ drawinfo->value = kThemeButtonOn;
+ } else if (butPtr->flags & TRISTATED) {
+ drawinfo->value = kThemeButtonMixed;
+ } else {
+ drawinfo->value = kThemeButtonOff;
+ }
+
+ if ((mbPtr->flags & FIRST_DRAW) != 0) {
+ mbPtr->flags &= ~FIRST_DRAW;
+ if (Tk_MacOSXIsAppInFront()) {
+ mbPtr->flags |= ACTIVE;
+ }
+ }
+
+ drawinfo->state = kThemeStateInactive;
+ if ((mbPtr->flags & ACTIVE) == 0) {
+ if (butPtr->state == STATE_DISABLED) {
+ drawinfo->state = kThemeStateUnavailableInactive;
+ } else {
+ drawinfo->state = kThemeStateInactive;
+ }
+ } else if (butPtr->state == STATE_DISABLED) {
+ drawinfo->state = kThemeStateUnavailable;
+ } else if (butPtr->state == STATE_ACTIVE) {
+ drawinfo->state = kThemeStatePressed;
+ } else {
+ drawinfo->state = kThemeStateActive;
+ }
+
+ drawinfo->adornment = kThemeAdornmentNone;
+ if (butPtr->defaultState == DEFAULT_ACTIVE) {
+ drawinfo->adornment |= kThemeAdornmentDefault;
+ if (!mbPtr->defaultPulseHandler) {
+ mbPtr->defaultPulseHandler = Tcl_CreateTimerHandler(
+ PULSE_TIMER_MSECS, PulseDefaultButtonProc, butPtr);
+ }
+ } else if (mbPtr->defaultPulseHandler) {
+ Tcl_DeleteTimerHandler(mbPtr->defaultPulseHandler);
+ }
+ if (butPtr->highlightWidth >= 3) {
+ if ((butPtr->flags & GOT_FOCUS)) {
+ drawinfo->adornment |= kThemeAdornmentFocus;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXComputeButtonDrawParams --
+ *
+ * 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
+TkMacOSXComputeButtonDrawParams(
+ TkButton *butPtr,
+ DrawParams *dpPtr)
+{
+ MacButton *mbPtr = (MacButton *) butPtr;
+
+ dpPtr->hasImageOrBitmap = ((butPtr->image != NULL)
+ || (butPtr->bitmap != None));
+
+ if (butPtr->type != TYPE_LABEL) {
+ dpPtr->offset = 0;
+ if (dpPtr->hasImageOrBitmap) {
+ switch (mbPtr->btnkind) {
+ case kThemeSmallBevelButton:
+ case kThemeBevelButton:
+ case kThemeRoundedBevelButton:
+ case kThemePushButton:
+ dpPtr->offset = 1;
+ break;
+ }
+ }
+ }
+
+ 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.
+ */
+
+ dpPtr->relief = butPtr->relief;
+
+ if ((butPtr->type >= TYPE_CHECK_BUTTON) && !butPtr->indicatorOn) {
+ if (!dpPtr->hasImageOrBitmap) {
+ dpPtr->relief = (butPtr->flags & SELECTED) ? TK_RELIEF_SUNKEN
+ : TK_RELIEF_RAISED;
+ }
+ }
+
+ if (butPtr->type != TYPE_LABEL && (butPtr->type == TYPE_BUTTON ||
+ butPtr->indicatorOn || dpPtr->hasImageOrBitmap)) {
+ /*
+ * Draw this widget as a native control.
+ */
+
+ return 1;
+ } else {
+ /*
+ * Draw this widget from scratch.
+ */
+
+ return 0;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * PulseDefaultButtonProc --
+ *
+ * This function redraws the button on a timer, to pulse
+ * default buttons.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Sets a timer to run itself again.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+PulseDefaultButtonProc(ClientData clientData)
+{
+ MacButton *mbPtr = clientData;
+
+ TkpDisplayButton(clientData);
+ mbPtr->defaultPulseHandler = Tcl_CreateTimerHandler(
+ PULSE_TIMER_MSECS, PulseDefaultButtonProc, clientData);
+}
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXClipboard.c b/tk8.6/macosx/tkMacOSXClipboard.c
new file mode 100644
index 0000000..6cbcdf6
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXClipboard.c
@@ -0,0 +1,301 @@
+/*
+ * tkMacOSXClipboard.c --
+ *
+ * This file manages the clipboard for the Tk toolkit.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ * Copyright 2001-2009, Apple Inc.
+ * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkMacOSXPrivate.h"
+#include "tkMacOSXConstants.h"
+#include "tkSelect.h"
+
+static NSInteger changeCount = -1;
+static Tk_Window clipboardOwner = NULL;
+
+#pragma mark TKApplication(TKClipboard)
+
+@implementation TKApplication(TKClipboard)
+- (void) tkProvidePasteboard: (TkDisplay *) dispPtr
+ pasteboard: (NSPasteboard *) sender
+ provideDataForType: (NSString *) type
+{
+ NSMutableString *string = [NSMutableString new];
+
+ if (dispPtr && dispPtr->clipboardActive &&
+ [type isEqualToString:NSStringPboardType]) {
+ for (TkClipboardTarget *targetPtr = dispPtr->clipTargetPtr; targetPtr;
+ targetPtr = targetPtr->nextPtr) {
+ if (targetPtr->type == XA_STRING ||
+ targetPtr->type == dispPtr->utf8Atom) {
+ for (TkClipboardBuffer *cbPtr = targetPtr->firstBufferPtr;
+ cbPtr; cbPtr = cbPtr->nextPtr) {
+ NSString *s = [[NSString alloc] initWithBytesNoCopy:
+ cbPtr->buffer length:cbPtr->length
+ encoding:NSUTF8StringEncoding freeWhenDone:NO];
+
+ [string appendString:s];
+ [s release];
+ }
+ break;
+ }
+ }
+ }
+ [sender setString:string forType:type];
+ [string release];
+}
+
+- (void) tkProvidePasteboard: (TkDisplay *) dispPtr
+{
+ if (dispPtr && dispPtr->clipboardActive) {
+ [self tkProvidePasteboard:dispPtr
+ pasteboard:[NSPasteboard generalPasteboard]
+ provideDataForType:NSStringPboardType];
+ }
+}
+
+- (void) pasteboard: (NSPasteboard *) sender
+ provideDataForType: (NSString *) type
+{
+ [self tkProvidePasteboard:TkGetDisplayList() pasteboard:sender
+ provideDataForType:type];
+}
+
+- (void) tkCheckPasteboard
+{
+ if (clipboardOwner && [[NSPasteboard generalPasteboard] changeCount] !=
+ changeCount) {
+ TkDisplay *dispPtr = TkGetDisplayList();
+ if (dispPtr) {
+ XEvent event;
+ event.xany.type = SelectionClear;
+ event.xany.serial = NextRequest(Tk_Display(clipboardOwner));
+ event.xany.send_event = False;
+ event.xany.window = Tk_WindowId(clipboardOwner);
+ event.xany.display = Tk_Display(clipboardOwner);
+ event.xselectionclear.selection = dispPtr->clipboardAtom;
+ Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+ }
+ clipboardOwner = NULL;
+ }
+}
+@end
+
+#pragma mark -
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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 = TCL_ERROR;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+ int haveExternalClip =
+ ([[NSPasteboard generalPasteboard] changeCount] != changeCount);
+
+ if (dispPtr && (haveExternalClip || dispPtr->clipboardActive)
+ && selection == dispPtr->clipboardAtom
+ && (target == XA_STRING || target == dispPtr->utf8Atom)) {
+ NSString *string = nil;
+ NSPasteboard *pb = [NSPasteboard generalPasteboard];
+ NSString *type = [pb availableTypeFromArray:[NSArray arrayWithObject:
+ NSStringPboardType]];
+
+ if (type) {
+ string = [pb stringForType:type];
+ }
+ result = proc(clientData, interp, string ? [string UTF8String] : "");
+ } else {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "%s selection doesn't exist or form \"%s\" not defined",
+ Tk_GetAtomName(tkwin, selection),
+ Tk_GetAtomName(tkwin, target)));
+ Tcl_SetErrorCode(interp, "TK", "SELECTION", "EXISTS", NULL);
+ }
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XSetSelectionOwner --
+ *
+ * This function claims ownership of the specified selection. If the
+ * selection is CLIPBOARD, then we empty the system clipboard.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+XSetSelectionOwner(
+ Display *display, /* X Display. */
+ Atom selection, /* What selection to own. */
+ Window owner, /* Window to be the owner. */
+ Time time) /* The current time? */
+{
+ TkDisplay *dispPtr = TkGetDisplayList();
+
+ if (dispPtr && selection == dispPtr->clipboardAtom) {
+ clipboardOwner = owner ? Tk_IdToWindow(display, owner) : NULL;
+ if (!dispPtr->clipboardActive) {
+ NSPasteboard *pb = [NSPasteboard generalPasteboard];
+
+ changeCount = [pb declareTypes:[NSArray array] owner:NSApp];
+ }
+ }
+ return Success;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXSelDeadWindow --
+ *
+ * This function is invoked just before a TkWindow is deleted. It performs
+ * selection-related cleanup.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * clipboardOwner is cleared.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXSelDeadWindow(
+ TkWindow *winPtr)
+{
+ if (winPtr && winPtr == (TkWindow *)clipboardOwner) {
+ clipboardOwner = NULL;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkSelUpdateClipboard --
+ *
+ * This function is called to force the clipboard to be updated after new
+ * data is added.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkSelUpdateClipboard(
+ TkWindow *winPtr, /* Window associated with clipboard. */
+ TkClipboardTarget *targetPtr)
+ /* Info about the content. */
+{
+ NSPasteboard *pb = [NSPasteboard generalPasteboard];
+
+ changeCount = [pb addTypes:[NSArray arrayWithObject:NSStringPboardType]
+ owner:NSApp];
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * 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) {
+ clipboardOwner = NULL;
+ 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. */
+{
+}
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXColor.c b/tk8.6/macosx/tkMacOSXColor.c
new file mode 100644
index 0000000..015c164
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXColor.c
@@ -0,0 +1,922 @@
+/*
+ * 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-2009, Apple Inc.
+ * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkMacOSXPrivate.h"
+#include "tkColor.h"
+
+/*
+ * The colorType specifies how the color value should be interpreted. For the
+ * unique rgbColor entry, the RGB values are generated from the pixel value of
+ * an XColor. The ttkBackground and semantic types are dynamic, meaning
+ * that they change when dark mode is enabled on OSX 10.13 and later.
+ */
+
+enum colorType {
+ clearColor, /* There should be only one of these. */
+ rgbColor, /* There should be only one of these. */
+ appearance, /* There should be only one of these. */
+ HIBrush, /* The value is a HITheme brush color table index. */
+ HIText, /* The value is a HITheme text color table index. */
+ HIBackground, /* The value is a HITheme background color table index. */
+ ttkBackground, /* The value can be used as a parameter.*/
+ semantic, /* The value can be used as a parameter.*/
+};
+
+/*
+
+ */
+
+struct SystemColorMapEntry {
+ const char *name;
+ enum colorType type;
+ long value;
+}; /* unsigned char pixelCode; */
+
+/*
+ * Array of system color definitions: the array index is required to equal the
+ * color's (pixelCode - MIN_PIXELCODE), i.e. the array order needs to be kept
+ * in sync with the public pixel code values in tkMacOSXPort.h !
+ */
+
+#define MIN_PIXELCODE 30
+static const struct SystemColorMapEntry systemColorMap[] = {
+ { "Transparent", clearColor, 0 }, /* 30: TRANSPARENT_PIXEL */
+ { "Highlight", HIBrush, kThemeBrushPrimaryHighlightColor }, /* 31 */
+ { "HighlightSecondary", HIBrush, kThemeBrushSecondaryHighlightColor }, /* 32 */
+ { "HighlightText", HIBrush, kThemeBrushBlack }, /* 33 */
+ { "HighlightAlternate", HIBrush, kThemeBrushAlternatePrimaryHighlightColor }, /* 34 */
+ { "ButtonText", HIText, kThemeTextColorPushButtonActive }, /* 35 */
+ { "PrimaryHighlightColor", HIBrush, kThemeBrushPrimaryHighlightColor }, /* 36 */
+ { "ButtonFace", HIBrush, kThemeBrushButtonFaceActive }, /* 37 */
+ { "SecondaryHighlightColor", HIBrush, kThemeBrushSecondaryHighlightColor }, /* 38 */
+ { "ButtonFrame", HIBrush, kThemeBrushButtonFrameActive }, /* 39 */
+ { "AlternatePrimaryHighlightColor", HIBrush, kThemeBrushAlternatePrimaryHighlightColor }, /* 40 */
+ { "WindowBody", HIBrush, kThemeBrushDocumentWindowBackground }, /* 41 */
+ { "SheetBackground", HIBrush, kThemeBrushSheetBackground }, /* 42 */
+ { "MenuActive", HIBrush, kThemeBrushMenuBackgroundSelected }, /* 43 */
+ { "Black", HIBrush, kThemeBrushBlack }, /* 44 */
+ { "MenuActiveText", HIText, kThemeTextColorMenuItemSelected }, /* 45 */
+ { "White", HIBrush, kThemeBrushWhite }, /* 46 */
+ { "Menu", HIBrush, kThemeBrushMenuBackground }, /* 47 */
+ { "DialogBackgroundActive", HIBrush, kThemeBrushDialogBackgroundActive }, /* 48 */
+ { "MenuDisabled", HIText, kThemeTextColorMenuItemDisabled }, /* 49 */
+ { "DialogBackgroundInactive", HIBrush, kThemeBrushDialogBackgroundInactive }, /* 50 */
+ { "MenuText", HIText, kThemeTextColorMenuItemActive }, /* 51 */
+ { "AppearanceColor", appearance, 0 }, /* 52: APPEARANCE_PIXEL */
+ { "AlertBackgroundActive", HIBrush, kThemeBrushAlertBackgroundActive }, /* 53 */
+ { "AlertBackgroundInactive", HIBrush, kThemeBrushAlertBackgroundInactive }, /* 54 */
+ { "ModelessDialogBackgroundActive", HIBrush, kThemeBrushModelessDialogBackgroundActive }, /* 55 */
+ { "ModelessDialogBackgroundInactive", HIBrush, kThemeBrushModelessDialogBackgroundInactive }, /* 56 */
+ { "UtilityWindowBackgroundActive", HIBrush, kThemeBrushUtilityWindowBackgroundActive }, /* 57 */
+ { "UtilityWindowBackgroundInactive", HIBrush, kThemeBrushUtilityWindowBackgroundInactive }, /* 58 */
+ { "ListViewSortColumnBackground", HIBrush, kThemeBrushListViewSortColumnBackground }, /* 59 */
+ { "ListViewBackground", HIBrush, kThemeBrushListViewBackground }, /* 60 */
+ { "IconLabelBackground", HIBrush, kThemeBrushIconLabelBackground }, /* 61 */
+ { "ListViewSeparator", HIBrush, kThemeBrushListViewSeparator }, /* 62 */
+ { "ChasingArrows", HIBrush, kThemeBrushChasingArrows }, /* 63 */
+ { "DragHilite", HIBrush, kThemeBrushDragHilite }, /* 64 */
+ { "DocumentWindowBackground", HIBrush, kThemeBrushDocumentWindowBackground }, /* 65 */
+ { "FinderWindowBackground", HIBrush, kThemeBrushFinderWindowBackground }, /* 66 */
+ { "ScrollBarDelimiterActive", HIBrush, kThemeBrushScrollBarDelimiterActive }, /* 67 */
+ { "ScrollBarDelimiterInactive", HIBrush, kThemeBrushScrollBarDelimiterInactive }, /* 68 */
+ { "FocusHighlight", HIBrush, kThemeBrushFocusHighlight }, /* 69 */
+ { "PopupArrowActive", HIBrush, kThemeBrushPopupArrowActive }, /* 70 */
+ { "PopupArrowPressed", HIBrush, kThemeBrushPopupArrowPressed }, /* 71 */
+ { "PopupArrowInactive", HIBrush, kThemeBrushPopupArrowInactive }, /* 72 */
+ { "AppleGuideCoachmark", HIBrush, kThemeBrushAppleGuideCoachmark }, /* 73 */
+ { "IconLabelBackgroundSelected", HIBrush, kThemeBrushIconLabelBackgroundSelected }, /* 74 */
+ { "StaticAreaFill", HIBrush, kThemeBrushStaticAreaFill }, /* 75 */
+ { "ActiveAreaFill", HIBrush, kThemeBrushActiveAreaFill }, /* 76 */
+ { "ButtonFrameActive", HIBrush, kThemeBrushButtonFrameActive }, /* 77 */
+ { "ButtonFrameInactive", HIBrush, kThemeBrushButtonFrameInactive }, /* 78 */
+ { "ButtonFaceActive", HIBrush, kThemeBrushButtonFaceActive }, /* 79 */
+ { "ButtonFaceInactive", HIBrush, kThemeBrushButtonFaceInactive }, /* 80 */
+ { "ButtonFacePressed", HIBrush, kThemeBrushButtonFacePressed }, /* 81 */
+ { "ButtonActiveDarkShadow", HIBrush, kThemeBrushButtonActiveDarkShadow }, /* 82 */
+ { "ButtonActiveDarkHighlight", HIBrush, kThemeBrushButtonActiveDarkHighlight }, /* 83 */
+ { "ButtonActiveLightShadow", HIBrush, kThemeBrushButtonActiveLightShadow }, /* 84 */
+ { "ButtonActiveLightHighlight", HIBrush, kThemeBrushButtonActiveLightHighlight }, /* 85 */
+ { "ButtonInactiveDarkShadow", HIBrush, kThemeBrushButtonInactiveDarkShadow }, /* 86 */
+ { "ButtonInactiveDarkHighlight", HIBrush, kThemeBrushButtonInactiveDarkHighlight }, /* 87 */
+ { "ButtonInactiveLightShadow", HIBrush, kThemeBrushButtonInactiveLightShadow }, /* 88 */
+ { "ButtonInactiveLightHighlight", HIBrush, kThemeBrushButtonInactiveLightHighlight }, /* 89 */
+ { "ButtonPressedDarkShadow", HIBrush, kThemeBrushButtonPressedDarkShadow }, /* 90 */
+ { "ButtonPressedDarkHighlight", HIBrush, kThemeBrushButtonPressedDarkHighlight }, /* 91 */
+ { "ButtonPressedLightShadow", HIBrush, kThemeBrushButtonPressedLightShadow }, /* 92 */
+ { "ButtonPressedLightHighlight", HIBrush, kThemeBrushButtonPressedLightHighlight }, /* 93 */
+ { "BevelActiveLight", HIBrush, kThemeBrushBevelActiveLight }, /* 94 */
+ { "BevelActiveDark", HIBrush, kThemeBrushBevelActiveDark }, /* 95 */
+ { "BevelInactiveLight", HIBrush, kThemeBrushBevelInactiveLight }, /* 96 */
+ { "BevelInactiveDark", HIBrush, kThemeBrushBevelInactiveDark }, /* 97 */
+ { "NotificationWindowBackground", HIBrush, kThemeBrushNotificationWindowBackground }, /* 98 */
+ { "MovableModalBackground", HIBrush, kThemeBrushMovableModalBackground }, /* 99 */
+ { "SheetBackgroundOpaque", HIBrush, kThemeBrushSheetBackgroundOpaque }, /* 100 */
+ { "DrawerBackground", HIBrush, kThemeBrushDrawerBackground }, /* 101 */
+ { "ToolbarBackground", HIBrush, kThemeBrushToolbarBackground }, /* 102 */
+ { "SheetBackgroundTransparent", HIBrush, kThemeBrushSheetBackgroundTransparent }, /* 103 */
+ { "MenuBackground", HIBrush, kThemeBrushMenuBackground }, /* 104 */
+ { "Pixel", rgbColor, 0 }, /* 105: PIXEL_MAGIC */
+ { "MenuBackgroundSelected", HIBrush, kThemeBrushMenuBackgroundSelected }, /* 106 */
+ { "ListViewOddRowBackground", HIBrush, kThemeBrushListViewOddRowBackground }, /* 107 */
+ { "ListViewEvenRowBackground", HIBrush, kThemeBrushListViewEvenRowBackground }, /* 108 */
+ { "ListViewColumnDivider", HIBrush, kThemeBrushListViewColumnDivider }, /* 109 */
+ { "BlackText", HIText, kThemeTextColorBlack }, /* 110 */
+ { "DialogActiveText", HIText, kThemeTextColorDialogActive }, /* 111 */
+ { "DialogInactiveText", HIText, kThemeTextColorDialogInactive }, /* 112 */
+ { "AlertActiveText", HIText, kThemeTextColorAlertActive }, /* 113 */
+ { "AlertInactiveText", HIText, kThemeTextColorAlertInactive }, /* 114 */
+ { "ModelessDialogActiveText", HIText, kThemeTextColorModelessDialogActive }, /* 115 */
+ { "ModelessDialogInactiveText", HIText, kThemeTextColorModelessDialogInactive }, /* 116 */
+ { "WindowHeaderActiveText", HIText, kThemeTextColorWindowHeaderActive }, /* 117 */
+ { "WindowHeaderInactiveText", HIText, kThemeTextColorWindowHeaderInactive }, /* 118 */
+ { "PlacardActiveText", HIText, kThemeTextColorPlacardActive }, /* 119 */
+ { "PlacardInactiveText", HIText, kThemeTextColorPlacardInactive }, /* 120 */
+ { "PlacardPressedText", HIText, kThemeTextColorPlacardPressed }, /* 121 */
+ { "PushButtonActiveText", HIText, kThemeTextColorPushButtonActive }, /* 122 */
+ { "PushButtonInactiveText", HIText, kThemeTextColorPushButtonInactive }, /* 123 */
+ { "PushButtonPressedText", HIText, kThemeTextColorPushButtonPressed }, /* 124 */
+ { "BevelButtonActiveText", HIText, kThemeTextColorBevelButtonActive }, /* 125 */
+ { "BevelButtonInactiveText", HIText, kThemeTextColorBevelButtonInactive }, /* 126 */
+ { "BevelButtonPressedText", HIText, kThemeTextColorBevelButtonPressed }, /* 127 */
+ { "PopupButtonActiveText", HIText, kThemeTextColorPopupButtonActive }, /* 128 */
+ { "PopupButtonInactiveText", HIText, kThemeTextColorPopupButtonInactive }, /* 129 */
+ { "PopupButtonPressedText", HIText, kThemeTextColorPopupButtonPressed }, /* 130 */
+ { "IconLabelText", HIText, kThemeTextColorIconLabel }, /* 131 */
+ { "ListViewText", HIText, kThemeTextColorListView }, /* 132 */
+ { "DocumentWindowTitleActiveText", HIText, kThemeTextColorDocumentWindowTitleActive }, /* 133 */
+ { "DocumentWindowTitleInactiveText", HIText, kThemeTextColorDocumentWindowTitleInactive }, /* 134 */
+ { "MovableModalWindowTitleActiveText", HIText, kThemeTextColorMovableModalWindowTitleActive }, /* 135 */
+ { "MovableModalWindowTitleInactiveText",HIText, kThemeTextColorMovableModalWindowTitleInactive }, /* 136 */
+ { "UtilityWindowTitleActiveText", HIText, kThemeTextColorUtilityWindowTitleActive }, /* 137 */
+ { "UtilityWindowTitleInactiveText", HIText, kThemeTextColorUtilityWindowTitleInactive }, /* 138 */
+ { "PopupWindowTitleActiveText", HIText, kThemeTextColorPopupWindowTitleActive }, /* 139 */
+ { "PopupWindowTitleInactiveText", HIText, kThemeTextColorPopupWindowTitleInactive }, /* 140 */
+ { "RootMenuActiveText", HIText, kThemeTextColorRootMenuActive }, /* 141 */
+ { "RootMenuSelectedText", HIText, kThemeTextColorRootMenuSelected }, /* 142 */
+ { "RootMenuDisabledText", HIText, kThemeTextColorRootMenuDisabled }, /* 143 */
+ { "MenuItemActiveText", HIText, kThemeTextColorMenuItemActive }, /* 144 */
+ { "MenuItemSelectedText", HIText, kThemeTextColorMenuItemSelected }, /* 145 */
+ { "MenuItemDisabledText", HIText, kThemeTextColorMenuItemDisabled }, /* 146 */
+ { "PopupLabelActiveText", HIText, kThemeTextColorPopupLabelActive }, /* 147 */
+ { "PopupLabelInactiveText", HIText, kThemeTextColorPopupLabelInactive }, /* 148 */
+ { "TabFrontActiveText", HIText, kThemeTextColorTabFrontActive }, /* 149 */
+ { "TabNonFrontActiveText", HIText, kThemeTextColorTabNonFrontActive }, /* 150 */
+ { "TabNonFrontPressedText", HIText, kThemeTextColorTabNonFrontPressed }, /* 151 */
+ { "TabFrontInactiveText", HIText, kThemeTextColorTabFrontInactive }, /* 152 */
+ { "TabNonFrontInactiveText", HIText, kThemeTextColorTabNonFrontInactive }, /* 153 */
+ { "IconLabelSelectedText", HIText, kThemeTextColorIconLabelSelected }, /* 154 */
+ { "BevelButtonStickyActiveText", HIText, kThemeTextColorBevelButtonStickyActive }, /* 155 */
+ { "BevelButtonStickyInactiveText", HIText, kThemeTextColorBevelButtonStickyInactive }, /* 156 */
+ { "NotificationText", HIText, kThemeTextColorNotification }, /* 157 */
+ { "SystemDetailText", HIText, kThemeTextColorSystemDetail }, /* 158 */
+ { "WhiteText", HIText, kThemeTextColorWhite }, /* 159 */
+ { "TabPaneBackground", HIBackground, kThemeBackgroundTabPane }, /* 160 */
+ { "PlacardBackground", HIBackground, kThemeBackgroundPlacard }, /* 161 */
+ { "WindowHeaderBackground", HIBackground, kThemeBackgroundWindowHeader }, /* 162 */
+ { "ListViewWindowHeaderBackground", HIBackground, kThemeBackgroundListViewWindowHeader }, /* 163 */
+ { "SecondaryGroupBoxBackground", HIBackground, kThemeBackgroundSecondaryGroupBox }, /* 164 */
+ { "MetalBackground", HIBackground, kThemeBackgroundMetal }, /* 165 */
+
+ /*
+ * Colors based on "semantic" NSColors.
+ */
+
+ { "WindowBackgroundColor", ttkBackground, 0 }, /* 166 */
+ { "WindowBackgroundColor1", ttkBackground, 1 }, /* 167 */
+ { "WindowBackgroundColor2", ttkBackground, 2 }, /* 168 */
+ { "WindowBackgroundColor3", ttkBackground, 3 }, /* 169 */
+ { "WindowBackgroundColor4", ttkBackground, 4 }, /* 170 */
+ { "WindowBackgroundColor5", ttkBackground, 5 }, /* 171 */
+ { "WindowBackgroundColor6", ttkBackground, 6 }, /* 172 */
+ { "WindowBackgroundColor7", ttkBackground, 7 }, /* 173 */
+ { "TextColor", semantic, 0 }, /* 174 */
+ { "SelectedTextColor", semantic, 1 }, /* 175 */
+ { "LabelColor", semantic, 2 }, /* 176 */
+ { "ControlTextColor", semantic, 3 }, /* 177 */
+ { "DisabledControlTextColor", semantic, 4 }, /* 178 */
+ { "SelectedTabTextColor", semantic, 5 }, /* 179 */
+ { "TextBackgroundColor", semantic, 6 }, /* 180 */
+ { "SelectedTextBackgroundColor", semantic, 7 }, /* 181 */
+ { "ControlAccentColor", semantic, 8 }, /* 182 */
+ { NULL, 0, 0 }
+};
+#define FIRST_SEMANTIC_COLOR 166
+#define MAX_PIXELCODE 182
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetEntryFromPixelCode --
+ *
+ * Extract a SystemColorMapEntry from the table.
+ *
+ * Results:
+ * Returns false if the code is out of bounds.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static bool
+GetEntryFromPixelCode(
+ unsigned char code,
+ struct SystemColorMapEntry *entry)
+{
+ if (code >= MIN_PIXELCODE && code <= MAX_PIXELCODE) {
+ *entry = systemColorMap[code - MIN_PIXELCODE];
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetCGColorComponents --
+ *
+ * Set the components of a CGColorRef from an XColor pixel value and a
+ * system color map entry. The pixel value is only used in the case where
+ * the color is of type rgbColor. In that case the normalized XColor RGB
+ * values are copied into the CGColorRef.
+ *
+ * Results:
+ * OSStatus
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static NSColorSpace* deviceRGB = NULL;
+static CGFloat blueAccentRGBA[4] = {0, 122.0 / 255, 1.0, 1.0};
+static CGFloat windowBackground[4] =
+ {236.0 / 255, 236.0 / 255, 236.0 / 255, 1.0};
+
+static OSStatus
+SetCGColorComponents(
+ struct SystemColorMapEntry entry,
+ unsigned long pixel,
+ CGColorRef *c)
+{
+ OSStatus err = noErr;
+ NSColor *bgColor, *color;
+ CGFloat rgba[4] = {0, 0, 0, 1};
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 101400
+ NSInteger colorVariant;
+ static CGFloat graphiteAccentRGBA[4] =
+ {152.0 / 255, 152.0 / 255, 152.0 / 255, 1.0};
+#endif
+
+ if (!deviceRGB) {
+ deviceRGB = [NSColorSpace deviceRGBColorSpace];
+ }
+
+ /*
+ * This function is called before our autorelease pool is set up,
+ * so it needs its own pool.
+ */
+
+ NSAutoreleasePool *pool = [NSAutoreleasePool new];
+
+ switch (entry.type) {
+ case HIBrush:
+ err = ChkErr(HIThemeBrushCreateCGColor, entry.value, c);
+ return err;
+ case rgbColor:
+ rgba[0] = ((pixel >> 16) & 0xff) / 255.0;
+ rgba[1] = ((pixel >> 8) & 0xff) / 255.0;
+ rgba[2] = ((pixel ) & 0xff) / 255.0;
+ break;
+ case ttkBackground:
+
+ /*
+ * Prior to OSX 10.14, getComponents returns black when applied to
+ * windowBackGroundColor.
+ */
+
+ if ([NSApp macMinorVersion] < 14) {
+ for (int i=0; i<3; i++) {
+ rgba[i] = windowBackground[i];
+ }
+ } else {
+ bgColor = [[NSColor windowBackgroundColor] colorUsingColorSpace:
+ deviceRGB];
+ [bgColor getComponents: rgba];
+ }
+ if (rgba[0] + rgba[1] + rgba[2] < 1.5) {
+ for (int i=0; i<3; i++) {
+ rgba[i] += entry.value*8.0 / 255.0;
+ }
+ } else {
+ for (int i=0; i<3; i++) {
+ rgba[i] -= entry.value*8.0 / 255.0;
+ }
+ }
+ break;
+ case semantic:
+ switch (entry.value) {
+ case 0:
+ color = [[NSColor textColor] colorUsingColorSpace: deviceRGB];
+ break;
+ case 1:
+ color = [[NSColor selectedTextColor] colorUsingColorSpace: deviceRGB];
+ break;
+ case 2:
+ if ([NSApp macMinorVersion] > 9) {
+ color = [[NSColor labelColor] colorUsingColorSpace: deviceRGB];
+ } else {
+ color = [[NSColor textColor] colorUsingColorSpace: deviceRGB];
+ }
+ break;
+ case 3:
+ color = [[NSColor controlTextColor] colorUsingColorSpace:
+ deviceRGB];
+ break;
+ case 4:
+ color = [[NSColor disabledControlTextColor] colorUsingColorSpace:
+ deviceRGB];
+ break;
+ case 5:
+ if ([NSApp macMinorVersion] > 6) {
+ color = [[NSColor whiteColor] colorUsingColorSpace:
+ deviceRGB];
+ } else {
+ color = [[NSColor blackColor] colorUsingColorSpace:
+ deviceRGB];
+ }
+ break;
+ case 6:
+ color = [[NSColor textBackgroundColor] colorUsingColorSpace:
+ deviceRGB];
+ break;
+ case 7:
+ color = [[NSColor selectedTextBackgroundColor] colorUsingColorSpace:
+ deviceRGB];
+ break;
+ case 8:
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
+ if (@available(macOS 10.14, *)) {
+ color = [[NSColor controlAccentColor] colorUsingColorSpace:
+ deviceRGB];
+ } else {
+ color = [NSColor colorWithColorSpace: deviceRGB
+ components: blueAccentRGBA
+ count: 4];
+ }
+#else
+ colorVariant = [[NSUserDefaults standardUserDefaults]
+ integerForKey:@"AppleAquaColorVariant"];
+ if (colorVariant == 6) {
+ color = [NSColor colorWithColorSpace: deviceRGB
+ components: graphiteAccentRGBA
+ count: 4];
+ } else {
+ color = [NSColor colorWithColorSpace: deviceRGB
+ components: blueAccentRGBA
+ count: 4];
+ }
+#endif
+ break;
+ default:
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
+ if ([NSApp macMinorVersion] >= 10) {
+ color = [[NSColor labelColor] colorUsingColorSpace:
+ deviceRGB];
+ break;
+ }
+#endif
+ color = [[NSColor textColor] colorUsingColorSpace: deviceRGB];
+ break;
+ }
+ [color getComponents: rgba];
+ break;
+ case clearColor:
+ rgba[3] = 0.0;
+ break;
+
+ /*
+ * There are no HITheme functions which convert Text or background colors
+ * to CGColors. (GetThemeTextColor has been removed, and it was never
+ * possible with backgrounds.) If we get one of these we return black.
+ */
+
+ case HIText:
+ case HIBackground:
+ default:
+ break;
+ }
+ *c = CGColorCreate(deviceRGB.CGColorSpace, rgba);
+ [pool drain];
+ return err;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXInDarkMode --
+ *
+ * Tests whether the given window's NSView has a DarkAqua Appearance.
+ *
+ * Results:
+ * Returns true if the NSView is in DarkMode, false if not.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+MODULE_SCOPE Bool
+TkMacOSXInDarkMode(Tk_Window tkwin)
+{
+ int result = false;
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
+ if ([NSApp macMinorVersion] >= 14) {
+ static NSAppearanceName darkAqua = @"NSAppearanceNameDarkAqua";
+ TkWindow *winPtr = (TkWindow*) tkwin;
+ NSView *view = TkMacOSXDrawableView(winPtr->privatePtr);
+ result = (view &&
+ [view.effectiveAppearance.name isEqualToString:darkAqua]);
+ }
+#endif
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkSetMacColor --
+ *
+ * Sets the components of a CGColorRef from an XColor pixel value.
+ * The high order byte of the pixel value is used as an index into
+ * the system color table, and then SetCGColorComponents is called
+ * with the table entry and the pixel value.
+ *
+ * Results:
+ * Returns false if the high order byte is not a valid index, true
+ * otherwise.
+ *
+ * Side effects:
+ * The variable macColor is set to a new CGColorRef, the caller is
+ * responsible for releasing it!
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkSetMacColor(
+ unsigned long pixel, /* Pixel value to convert. */
+ void *macColor) /* CGColorRef to modify. */
+{
+ CGColorRef *color = (CGColorRef*)macColor;
+ OSStatus err = -1;
+ struct SystemColorMapEntry entry;
+
+ if (GetEntryFromPixelCode((pixel >> 24) & 0xff, &entry)) {
+ err = ChkErr(SetCGColorComponents, entry, pixel, color);
+ }
+ return (err == noErr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpInitGCCache, TkpFreeGCCache, CopyCachedColor, SetCachedColor --
+ *
+ * Maintain a per-GC cache of previously converted CGColorRefs
+ *
+ * Results:
+ * None resp. retained CGColorRef for CopyCachedColor()
+ *
+ * Side effects:M
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpInitGCCache(
+ GC gc)
+{
+ bzero(TkpGetGCCache(gc), sizeof(TkpGCCache));
+}
+
+void
+TkpFreeGCCache(
+ GC gc)
+{
+ TkpGCCache *gcCache = TkpGetGCCache(gc);
+
+ if (gcCache->cachedForegroundColor) {
+ CFRelease(gcCache->cachedForegroundColor);
+ }
+ if (gcCache->cachedBackgroundColor) {
+ CFRelease(gcCache->cachedBackgroundColor);
+ }
+}
+
+static CGColorRef
+CopyCachedColor(
+ GC gc,
+ unsigned long pixel)
+{
+ TkpGCCache *gcCache = TkpGetGCCache(gc);
+ CGColorRef cgColor = NULL;
+
+ if (gcCache) {
+ if (gcCache->cachedForeground == pixel) {
+ cgColor = gcCache->cachedForegroundColor;
+ } else if (gcCache->cachedBackground == pixel) {
+ cgColor = gcCache->cachedBackgroundColor;
+ }
+ if (cgColor) {
+ CFRetain(cgColor);
+ }
+ }
+ return cgColor;
+}
+
+static void
+SetCachedColor(
+ GC gc,
+ unsigned long pixel,
+ CGColorRef cgColor)
+{
+ TkpGCCache *gcCache = TkpGetGCCache(gc);
+
+ if (gcCache && cgColor) {
+ if (gc->foreground == pixel) {
+ if (gcCache->cachedForegroundColor) {
+ CFRelease(gcCache->cachedForegroundColor);
+ }
+ gcCache->cachedForegroundColor = (CGColorRef) CFRetain(cgColor);
+ gcCache->cachedForeground = pixel;
+ } else if (gc->background == pixel) {
+ if (gcCache->cachedBackgroundColor) {
+ CFRelease(gcCache->cachedBackgroundColor);
+ }
+ gcCache->cachedBackgroundColor = (CGColorRef) CFRetain(cgColor);
+ gcCache->cachedBackground = pixel;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXCreateCGColor --
+ *
+ * Creates a CGColorRef from a X style pixel value.
+ *
+ * Results:
+ * Returns NULL if not a real pixel, CGColorRef otherwise.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+CGColorRef
+TkMacOSXCreateCGColor(
+ GC gc,
+ unsigned long pixel) /* Pixel value to convert. */
+{
+ CGColorRef cgColor = CopyCachedColor(gc, pixel);
+
+ if (!cgColor && TkSetMacColor(pixel, &cgColor)) {
+ SetCachedColor(gc, pixel, cgColor);
+ }
+ return cgColor;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXGetNSColor --
+ *
+ * Creates an autoreleased NSColor from a X style pixel value.
+ *
+ * Results:
+ * Returns nil if not a real pixel, NSColor* otherwise.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+NSColor*
+TkMacOSXGetNSColor(
+ GC gc,
+ unsigned long pixel) /* Pixel value to convert. */
+{
+ CGColorRef cgColor = TkMacOSXCreateCGColor(gc, pixel);
+ NSColor *nsColor = nil;
+
+ if (cgColor) {
+ NSColorSpace *colorSpace = [[NSColorSpace alloc]
+ initWithCGColorSpace:CGColorGetColorSpace(cgColor)];
+
+ nsColor = [NSColor colorWithColorSpace:colorSpace
+ components:CGColorGetComponents(cgColor)
+ count:CGColorGetNumberOfComponents(cgColor)];
+ [colorSpace release];
+ CFRelease(cgColor);
+ }
+ return nsColor;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXSetColorInContext --
+ *
+ * Sets fill and stroke color in the given CG context from an X
+ * pixel value, or if the pixel code indicates a system color,
+ * sets the corresponding brush, textColor or background via
+ * HITheme APIs if available or Appearance mgr APIs.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXSetColorInContext(
+ GC gc,
+ unsigned long pixel,
+ CGContextRef context)
+{
+ OSStatus err = noErr;
+ CGColorRef cgColor = nil;
+ struct SystemColorMapEntry entry;
+ CGRect rect;
+ int code = (pixel >> 24) & 0xff;
+ HIThemeBackgroundDrawInfo info = {0, kThemeStateActive, 0};;
+ static CGColorSpaceRef deviceRGBSpace = NULL;
+
+ if (!deviceRGBSpace) {
+ deviceRGBSpace = CGColorSpaceCreateDeviceRGB();
+ }
+ if (code < FIRST_SEMANTIC_COLOR) {
+ cgColor = CopyCachedColor(gc, pixel);
+ }
+ if (!cgColor && GetEntryFromPixelCode(code, &entry)) {
+ switch (entry.type) {
+ case HIBrush:
+ err = ChkErr(HIThemeSetFill, entry.value, NULL, context,
+ kHIThemeOrientationNormal);
+ if (err == noErr) {
+ err = ChkErr(HIThemeSetStroke, entry.value, NULL, context,
+ kHIThemeOrientationNormal);
+ }
+ break;
+ case HIText:
+ err = ChkErr(HIThemeSetTextFill, entry.value, NULL, context,
+ kHIThemeOrientationNormal);
+ break;
+ case HIBackground:
+ info.kind = entry.value;
+ rect = CGContextGetClipBoundingBox(context);
+ err = ChkErr(HIThemeApplyBackground, &rect, &info,
+ context, kHIThemeOrientationNormal);
+ break;
+ default:
+ err = ChkErr(SetCGColorComponents, entry, pixel, &cgColor);
+ if (err == noErr) {
+ SetCachedColor(gc, pixel, cgColor);
+ }
+ break;
+ }
+ }
+ if (cgColor) {
+ CGContextSetFillColorWithColor(context, cgColor);
+ CGContextSetStrokeColorWithColor(context, cgColor);
+ CGColorRelease(cgColor);
+ }
+ if (err != noErr) {
+ TkMacOSXDbgMsg("Ignored unknown pixel value 0x%lx", pixel);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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 be allocated (in form
+ * suitable for passing to XParseColor). */
+{
+ Display *display = tkwin != None ? Tk_Display(tkwin) : NULL;
+ Colormap colormap = tkwin!= None ? Tk_Colormap(tkwin) : None;
+ 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) {
+ Tcl_Obj *strPtr = Tcl_NewStringObj(name+6, -1);
+ int idx, result;
+
+ result = Tcl_GetIndexFromObjStruct(NULL, strPtr, systemColorMap,
+ sizeof(struct SystemColorMapEntry), NULL, TCL_EXACT, &idx);
+ Tcl_DecrRefCount(strPtr);
+ if (result == TCL_OK) {
+ OSStatus err;
+ CGColorRef c;
+ unsigned char pixelCode = idx + MIN_PIXELCODE;
+ struct SystemColorMapEntry entry = systemColorMap[idx];
+
+ err = ChkErr(SetCGColorComponents, entry, 0, &c);
+ if (err == noErr) {
+ const size_t n = CGColorGetNumberOfComponents(c);
+ const CGFloat *rgba = CGColorGetComponents(c);
+
+ switch (n) {
+ case 4:
+ color.red = rgba[0] * 65535.0;
+ color.green = rgba[1] * 65535.0;
+ color.blue = rgba[2] * 65535.0;
+ break;
+ case 2:
+ color.red = color.green = color.blue = rgba[0] * 65535.0;
+ break;
+ default:
+ Tcl_Panic("CGColor with %d components", (int) n);
+ }
+ color.pixel = ((((((pixelCode << 8)
+ | ((color.red >> 8) & 0xff)) << 8)
+ | ((color.green >> 8) & 0xff)) << 8)
+ | ((color.blue >> 8) & 0xff));
+ CGColorRelease(c);
+ goto validXColor;
+ }
+ CGColorRelease(c);
+ }
+ }
+
+ if (TkParseColor(display, colormap, name, &color) == 0) {
+ return NULL;
+ }
+
+validXColor:
+ tkColPtr = 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 = 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;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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++;
+}
+
+int
+XFreeColormap(
+ Display* display, /* Display. */
+ Colormap colormap) /* Colormap. */
+{
+ return Success;
+}
+
+int
+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.
+ */
+ return Success;
+}
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXConfig.c b/tk8.6/macosx/tkMacOSXConfig.c
new file mode 100644
index 0000000..841fc54
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXConfig.c
@@ -0,0 +1,52 @@
+/*
+ * tkMacOSXConfig.c --
+ *
+ * This module implements the Macintosh system defaults for
+ * the configuration package.
+ *
+ * Copyright (c) 1997 by Sun Microsystems, Inc.
+ * Copyright 2001, Apple Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#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;
+}
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXConstants.h b/tk8.6/macosx/tkMacOSXConstants.h
new file mode 100644
index 0000000..8ef535c
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXConstants.h
@@ -0,0 +1,107 @@
+/*
+ * tkMacOSXConstants.h --
+ *
+ * Macros which map the names of NS constants used in the Tk code to
+ * the new name that Apple came up with for subsequent versions of the
+ * operating system. (Each new OS release seems to come with a new
+ * naming convention for the same old constants.)
+ *
+ * Copyright (c) 2017 Marc Culler
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef _TKMACCONSTANTS
+#define _TKMACCONSTANTS
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 1070
+#define NSFullScreenWindowMask (1 << 14)
+#endif
+
+/*
+ * Let's raise a glass for the project manager who improves our lives by
+ * generating deprecation warnings about pointless changes of the names
+ * of constants.
+ */
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
+#define kCTFontDefaultOrientation kCTFontOrientationDefault
+#define kCTFontVerticalOrientation kCTFontOrientationVertical
+#endif
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
+#define NSOKButton NSModalResponseOK
+#endif
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101100
+#define kCTFontUserFixedPitchFontType kCTFontUIFontUserFixedPitch
+#endif
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
+#define NSAppKitDefined NSEventTypeAppKitDefined
+#define NSApplicationDefined NSEventTypeApplicationDefined
+#define NSApplicationActivatedEventType NSEventSubtypeApplicationActivated
+#define NSApplicationDeactivatedEventType NSEventSubtypeApplicationDeactivated
+#define NSWindowExposedEventType NSEventSubtypeWindowExposed
+#define NSScreenChangedEventType NSEventSubtypeScreenChanged
+#define NSWindowMovedEventType NSEventSubtypeWindowMoved
+#define NSKeyUp NSEventTypeKeyUp
+#define NSKeyDown NSEventTypeKeyDown
+#define NSFlagsChanged NSEventTypeFlagsChanged
+#define NSLeftMouseDown NSEventTypeLeftMouseDown
+#define NSLeftMouseUp NSEventTypeLeftMouseUp
+#define NSRightMouseDown NSEventTypeRightMouseDown
+#define NSRightMouseUp NSEventTypeRightMouseUp
+#define NSLeftMouseDragged NSEventTypeLeftMouseDragged
+#define NSRightMouseDragged NSEventTypeRightMouseDragged
+#define NSMouseMoved NSEventTypeMouseMoved
+#define NSMouseEntered NSEventTypeMouseEntered
+#define NSMouseExited NSEventTypeMouseExited
+#define NSScrollWheel NSEventTypeScrollWheel
+#define NSOtherMouseDown NSEventTypeOtherMouseDown
+#define NSOtherMouseUp NSEventTypeOtherMouseUp
+#define NSOtherMouseDragged NSEventTypeOtherMouseDragged
+#define NSTabletPoint NSEventTypeTabletPoint
+#define NSTabletProximity NSEventTypeTabletProximity
+#define NSDeviceIndependentModifierFlagsMask NSEventModifierFlagDeviceIndependentFlagsMask
+#define NSCommandKeyMask NSEventModifierFlagCommand
+#define NSShiftKeyMask NSEventModifierFlagShift
+#define NSAlphaShiftKeyMask NSEventModifierFlagCapsLock
+#define NSAlternateKeyMask NSEventModifierFlagOption
+#define NSControlKeyMask NSEventModifierFlagControl
+#define NSNumericPadKeyMask NSEventModifierFlagNumericPad
+#define NSFunctionKeyMask NSEventModifierFlagFunction
+#define NSCursorUpdate NSEventTypeCursorUpdate
+#define NSTexturedBackgroundWindowMask NSWindowStyleMaskTexturedBackground
+#define NSCompositeCopy NSCompositingOperationCopy
+#define NSWarningAlertStyle NSAlertStyleWarning
+#define NSInformationalAlertStyle NSAlertStyleInformational
+#define NSCriticalAlertStyle NSAlertStyleCritical
+#define NSCenterTextAlignment NSTextAlignmentCenter
+#define NSAnyEventMask NSEventMaskAny
+#define NSApplicationDefinedMask NSEventMaskApplicationDefined
+#define NSUtilityWindowMask NSWindowStyleMaskUtilityWindow
+#define NSNonactivatingPanelMask NSWindowStyleMaskNonactivatingPanel
+#define NSDocModalWindowMask NSWindowStyleMaskDocModalWindow
+#define NSHUDWindowMask NSWindowStyleMaskHUDWindow
+#define NSTitledWindowMask NSWindowStyleMaskTitled
+#define NSClosableWindowMask NSWindowStyleMaskClosable
+#define NSResizableWindowMask NSWindowStyleMaskResizable
+#define NSUnifiedTitleAndToolbarWindowMask NSWindowStyleMaskUnifiedTitleAndToolbar
+#define NSMiniaturizableWindowMask NSWindowStyleMaskMiniaturizable
+#define NSBorderlessWindowMask NSWindowStyleMaskBorderless
+#define NSFullScreenWindowMask NSWindowStyleMaskFullScreen
+#endif
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+#define NSStringPboardType NSPasteboardTypeString
+#define NSOnState NSControlStateValueOn
+#define NSOffState NSControlStateValueOff
+// Now we are also changing names of methods!
+#define graphicsContextWithGraphicsPort graphicsContextWithCGContext
+#endif
+
+
+#endif
+
diff --git a/tk8.6/macosx/tkMacOSXCursor.c b/tk8.6/macosx/tkMacOSXCursor.c
new file mode 100644
index 0000000..03d13dd
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXCursor.c
@@ -0,0 +1,603 @@
+/*
+ * tkMacOSXCursor.c --
+ *
+ * This file contains Macintosh specific cursor related routines.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ * Copyright 2001-2009, Apple Inc.
+ * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkMacOSXPrivate.h"
+#include "tkMacOSXCursors.h"
+#include "tkMacOSXXCursors.h"
+
+/*
+ * Mac Cursor Types.
+ */
+
+#define NONE -1 /* Hidden cursor */
+#define SELECTOR 1 /* NSCursor class method */
+#define IMAGENAMED 2 /* Named NSImage */
+#define IMAGEPATH 3 /* Path to NSImage */
+#define IMAGEBITMAP 4 /* Pointer to 16x16 cursor bitmap data */
+
+#define pix 16 /* Pixel width & height of cursor bitmap data */
+
+/*
+ * 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 */
+ NSCursor *macCursor; /* Macintosh cursor */
+ int type; /* Type of Mac cursor */
+} TkMacOSXCursor;
+
+/*
+ * The table below is used to map from the name of a predefined cursor
+ * to a NSCursor.
+ */
+
+struct CursorName {
+ const char *name;
+ const int kind;
+ id id1, id2;
+ NSPoint hotspot;
+};
+
+#define MacCursorData(n) ((id)tkMacOSXCursors[TK_MAC_CURSOR_##n])
+#define MacXCursorData(n) ((id)tkMacOSXXCursors[TK_MAC_XCURSOR_##n])
+
+static const struct CursorName cursorNames[] = {
+ {"none", NONE, nil},
+ {"arrow", SELECTOR, @"arrowCursor"},
+ {"top_left_arrow", SELECTOR, @"arrowCursor"},
+ {"left_ptr", SELECTOR, @"arrowCursor"},
+ {"copyarrow", SELECTOR, @"dragCopyCursor", @"_copyDragCursor"},
+ {"aliasarrow", SELECTOR, @"dragLinkCursor", @"_linkDragCursor"},
+ {"contextualmenuarrow", SELECTOR, @"contextualMenuCursor"},
+ {"movearrow", SELECTOR, @"_moveCursor"},
+ {"ibeam", SELECTOR, @"IBeamCursor"},
+ {"text", SELECTOR, @"IBeamCursor"},
+ {"xterm", SELECTOR, @"IBeamCursor"},
+ {"cross", SELECTOR, @"crosshairCursor"},
+ {"crosshair", SELECTOR, @"crosshairCursor"},
+ {"cross-hair", SELECTOR, @"crosshairCursor"},
+ {"tcross", SELECTOR, @"crosshairCursor"},
+ {"hand", SELECTOR, @"openHandCursor"},
+ {"openhand", SELECTOR, @"openHandCursor"},
+ {"closedhand", SELECTOR, @"closedHandCursor"},
+ {"fist", SELECTOR, @"closedHandCursor"},
+ {"pointinghand", SELECTOR, @"pointingHandCursor"},
+ {"resize", SELECTOR, @"arrowCursor"},
+ {"resizeleft", SELECTOR, @"resizeLeftCursor"},
+ {"resizeright", SELECTOR, @"resizeRightCursor"},
+ {"resizeleftright", SELECTOR, @"resizeLeftRightCursor"},
+ {"resizeup", SELECTOR, @"resizeUpCursor"},
+ {"resizedown", SELECTOR, @"resizeDownCursor"},
+ {"resizeupdown", SELECTOR, @"resizeUpDownCursor"},
+ {"resizebottomleft", SELECTOR, @"_bottomLeftResizeCursor"},
+ {"resizetopleft", SELECTOR, @"_topLeftResizeCursor"},
+ {"resizebottomright", SELECTOR, @"_bottomRightResizeCursor"},
+ {"resizetopright", SELECTOR, @"_topRightResizeCursor"},
+ {"notallowed", SELECTOR, @"operationNotAllowedCursor"},
+ {"poof", SELECTOR, @"disappearingItemCursor"},
+ {"wait", SELECTOR, @"busyButClickableCursor"},
+ {"spinning", SELECTOR, @"busyButClickableCursor"},
+ {"countinguphand", SELECTOR, @"busyButClickableCursor"},
+ {"countingdownhand", SELECTOR, @"busyButClickableCursor"},
+ {"countingupanddownhand", SELECTOR, @"busyButClickableCursor"},
+ {"help", IMAGENAMED, @"NSHelpCursor", nil, {8, 8}},
+// {"hand", IMAGEBITMAP, MacCursorData(hand)},
+ {"bucket", IMAGEBITMAP, MacCursorData(bucket)},
+ {"cancel", IMAGEBITMAP, MacCursorData(cancel)},
+// {"resize", IMAGEBITMAP, MacCursorData(resize)},
+ {"eyedrop", IMAGEBITMAP, MacCursorData(eyedrop)},
+ {"eyedrop-full", IMAGEBITMAP, MacCursorData(eyedrop_full)},
+ {"zoom-in", IMAGEBITMAP, MacCursorData(zoom_in)},
+ {"zoom-out", IMAGEBITMAP, MacCursorData(zoom_out)},
+ {"X_cursor", IMAGEBITMAP, MacXCursorData(X_cursor)},
+// {"arrow", IMAGEBITMAP, MacXCursorData(arrow)},
+ {"based_arrow_down", IMAGEBITMAP, MacXCursorData(based_arrow_down)},
+ {"based_arrow_up", IMAGEBITMAP, MacXCursorData(based_arrow_up)},
+ {"boat", IMAGEBITMAP, MacXCursorData(boat)},
+ {"bogosity", IMAGEBITMAP, MacXCursorData(bogosity)},
+ {"bottom_left_corner", IMAGEBITMAP, MacXCursorData(bottom_left_corner)},
+ {"bottom_right_corner", IMAGEBITMAP, MacXCursorData(bottom_right_corner)},
+ {"bottom_side", IMAGEBITMAP, MacXCursorData(bottom_side)},
+ {"bottom_tee", IMAGEBITMAP, MacXCursorData(bottom_tee)},
+ {"box_spiral", IMAGEBITMAP, MacXCursorData(box_spiral)},
+ {"center_ptr", IMAGEBITMAP, MacXCursorData(center_ptr)},
+ {"circle", IMAGEBITMAP, MacXCursorData(circle)},
+ {"clock", IMAGEBITMAP, MacXCursorData(clock)},
+ {"coffee_mug", IMAGEBITMAP, MacXCursorData(coffee_mug)},
+// {"cross", IMAGEBITMAP, MacXCursorData(cross)},
+ {"cross_reverse", IMAGEBITMAP, MacXCursorData(cross_reverse)},
+// {"crosshair", IMAGEBITMAP, MacXCursorData(crosshair)},
+ {"diamond_cross", IMAGEBITMAP, MacXCursorData(diamond_cross)},
+ {"dot", IMAGEBITMAP, MacXCursorData(dot)},
+ {"dotbox", IMAGEBITMAP, MacXCursorData(dotbox)},
+ {"double_arrow", IMAGEBITMAP, MacXCursorData(double_arrow)},
+ {"draft_large", IMAGEBITMAP, MacXCursorData(draft_large)},
+ {"draft_small", IMAGEBITMAP, MacXCursorData(draft_small)},
+ {"draped_box", IMAGEBITMAP, MacXCursorData(draped_box)},
+ {"exchange", IMAGEBITMAP, MacXCursorData(exchange)},
+ {"fleur", IMAGEBITMAP, MacXCursorData(fleur)},
+ {"gobbler", IMAGEBITMAP, MacXCursorData(gobbler)},
+ {"gumby", IMAGEBITMAP, MacXCursorData(gumby)},
+ {"hand1", IMAGEBITMAP, MacXCursorData(hand1)},
+ {"hand2", IMAGEBITMAP, MacXCursorData(hand2)},
+ {"heart", IMAGEBITMAP, MacXCursorData(heart)},
+ {"icon", IMAGEBITMAP, MacXCursorData(icon)},
+ {"iron_cross", IMAGEBITMAP, MacXCursorData(iron_cross)},
+// {"left_ptr", IMAGEBITMAP, MacXCursorData(left_ptr)},
+ {"left_side", IMAGEBITMAP, MacXCursorData(left_side)},
+ {"left_tee", IMAGEBITMAP, MacXCursorData(left_tee)},
+ {"leftbutton", IMAGEBITMAP, MacXCursorData(leftbutton)},
+ {"ll_angle", IMAGEBITMAP, MacXCursorData(ll_angle)},
+ {"lr_angle", IMAGEBITMAP, MacXCursorData(lr_angle)},
+ {"man", IMAGEBITMAP, MacXCursorData(man)},
+ {"middlebutton", IMAGEBITMAP, MacXCursorData(middlebutton)},
+ {"mouse", IMAGEBITMAP, MacXCursorData(mouse)},
+ {"pencil", IMAGEBITMAP, MacXCursorData(pencil)},
+ {"pirate", IMAGEBITMAP, MacXCursorData(pirate)},
+ {"plus", IMAGEBITMAP, MacXCursorData(plus)},
+ {"question_arrow", IMAGEBITMAP, MacXCursorData(question_arrow)},
+ {"right_ptr", IMAGEBITMAP, MacXCursorData(right_ptr)},
+ {"right_side", IMAGEBITMAP, MacXCursorData(right_side)},
+ {"right_tee", IMAGEBITMAP, MacXCursorData(right_tee)},
+ {"rightbutton", IMAGEBITMAP, MacXCursorData(rightbutton)},
+ {"rtl_logo", IMAGEBITMAP, MacXCursorData(rtl_logo)},
+ {"sailboat", IMAGEBITMAP, MacXCursorData(sailboat)},
+ {"sb_down_arrow", IMAGEBITMAP, MacXCursorData(sb_down_arrow)},
+ {"sb_h_double_arrow", IMAGEBITMAP, MacXCursorData(sb_h_double_arrow)},
+ {"sb_left_arrow", IMAGEBITMAP, MacXCursorData(sb_left_arrow)},
+ {"sb_right_arrow", IMAGEBITMAP, MacXCursorData(sb_right_arrow)},
+ {"sb_up_arrow", IMAGEBITMAP, MacXCursorData(sb_up_arrow)},
+ {"sb_v_double_arrow", IMAGEBITMAP, MacXCursorData(sb_v_double_arrow)},
+ {"shuttle", IMAGEBITMAP, MacXCursorData(shuttle)},
+ {"sizing", IMAGEBITMAP, MacXCursorData(sizing)},
+ {"spider", IMAGEBITMAP, MacXCursorData(spider)},
+ {"spraycan", IMAGEBITMAP, MacXCursorData(spraycan)},
+ {"star", IMAGEBITMAP, MacXCursorData(star)},
+ {"target", IMAGEBITMAP, MacXCursorData(target)},
+// {"tcross", IMAGEBITMAP, MacXCursorData(tcross)},
+// {"top_left_arrow", IMAGEBITMAP, MacXCursorData(top_left_arrow)},
+ {"top_left_corner", IMAGEBITMAP, MacXCursorData(top_left_corner)},
+ {"top_right_corner", IMAGEBITMAP, MacXCursorData(top_right_corner)},
+ {"top_side", IMAGEBITMAP, MacXCursorData(top_side)},
+ {"top_tee", IMAGEBITMAP, MacXCursorData(top_tee)},
+ {"trek", IMAGEBITMAP, MacXCursorData(trek)},
+ {"ul_angle", IMAGEBITMAP, MacXCursorData(ul_angle)},
+ {"umbrella", IMAGEBITMAP, MacXCursorData(umbrella)},
+ {"ur_angle", IMAGEBITMAP, MacXCursorData(ur_angle)},
+ {"watch", IMAGEBITMAP, MacXCursorData(watch)},
+// {"xterm", IMAGEBITMAP, MacXCursorData(xterm)},
+ {NULL}
+};
+
+/*
+ * 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(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 nil.
+ *
+ * Results:
+ * Fills the macCursorPtr record.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+FindCursorByName(
+ TkMacOSXCursor *macCursorPtr,
+ const char *name)
+{
+ NSString *path = nil;
+ NSImage *image = nil;
+ NSPoint hotSpot = NSZeroPoint;
+ int haveHotSpot = 0, result = TCL_ERROR;
+ NSCursor *macCursor = nil;
+
+ if (name[0] == '@') {
+ /*
+ * System cursor of type @filename
+ */
+
+ macCursorPtr->type = IMAGEPATH;
+ path = [NSString stringWithUTF8String:&name[1]];
+ } else {
+ Tcl_Obj *strPtr = Tcl_NewStringObj(name, -1);
+ int idx;
+
+ result = Tcl_GetIndexFromObjStruct(NULL, strPtr, cursorNames,
+ sizeof(struct CursorName), NULL, TCL_EXACT, &idx);
+ Tcl_DecrRefCount(strPtr);
+ if (result == TCL_OK) {
+ macCursorPtr->type = cursorNames[idx].kind;
+ switch (cursorNames[idx].kind) {
+ case SELECTOR: {
+ SEL selector = NSSelectorFromString(cursorNames[idx].id1);
+ if ([NSCursor respondsToSelector:selector]) {
+ macCursor = [[NSCursor performSelector:selector] retain];
+ } else if (cursorNames[idx].id2) {
+ selector = NSSelectorFromString(cursorNames[idx].id2);
+ if ([NSCursor respondsToSelector:selector]) {
+ macCursor = [[NSCursor performSelector:selector] retain];
+ }
+ }
+ break;
+ }
+ case IMAGENAMED:
+ image = [[NSImage imageNamed:cursorNames[idx].id1] retain];
+ hotSpot = cursorNames[idx].hotspot;
+ haveHotSpot = 1;
+ break;
+ case IMAGEPATH:
+ path = [NSApp tkFrameworkImagePath:cursorNames[idx].id1];
+ break;
+ case IMAGEBITMAP: {
+ unsigned char *bitmap = (unsigned char *)(cursorNames[idx].id1);
+ NSBitmapImageRep *bitmapImageRep = NULL;
+ CGImageRef img = NULL, mask = NULL, maskedImg = NULL;
+ static const CGFloat decodeWB[] = {1, 0};
+ CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(
+ kCGColorSpaceGenericGray);
+ CGDataProviderRef provider = CGDataProviderCreateWithData(NULL,
+ bitmap, pix*pix/8, NULL);
+
+ if (provider) {
+ img = CGImageCreate(pix, pix, 1, 1, pix/8, colorspace,
+ kCGBitmapByteOrderDefault, provider, decodeWB, 0,
+ kCGRenderingIntentDefault);
+ CFRelease(provider);
+ }
+ provider = CGDataProviderCreateWithData(NULL, bitmap +
+ pix*pix/8, pix*pix/8, NULL);
+ if (provider) {
+ mask = CGImageMaskCreate(pix, pix, 1, 1, pix/8, provider,
+ decodeWB, 0);
+ CFRelease(provider);
+ }
+ if (img && mask) {
+ maskedImg = CGImageCreateWithMask(img, mask);
+ }
+ if (maskedImg) {
+ bitmapImageRep = [[NSBitmapImageRep alloc]
+ initWithCGImage:maskedImg];
+ CFRelease(maskedImg);
+ }
+ if (mask) {
+ CFRelease(mask);
+ }
+ if (img) {
+ CFRelease(img);
+ }
+ if (colorspace) {
+ CFRelease(colorspace);
+ }
+ if (bitmapImageRep) {
+ image = [[NSImage alloc] initWithSize:NSMakeSize(pix, pix)];
+ [image addRepresentation:bitmapImageRep];
+ [bitmapImageRep release];
+ }
+
+ uint16_t *hotSpotData = (uint16_t*)(bitmap + 2*pix*pix/8);
+ hotSpot.y = CFSwapInt16BigToHost(*hotSpotData++);
+ hotSpot.x = CFSwapInt16BigToHost(*hotSpotData);
+ haveHotSpot = 1;
+ break;
+ }
+ }
+ }
+ }
+ if (path) {
+ image = [[NSImage alloc] initWithContentsOfFile:path];
+ }
+ if (!image && !macCursor && result != TCL_OK) {
+ macCursorPtr->type = IMAGENAMED;
+ image = [[NSImage imageNamed:[NSString stringWithUTF8String:name]]
+ retain];
+ haveHotSpot = 0;
+ }
+ if (image) {
+ if (!haveHotSpot && [[path pathExtension] isEqualToString:@"cur"]) {
+ NSData *data = [NSData dataWithContentsOfFile:path];
+ if ([data length] > 14) {
+ uint16_t *hotSpotData = (uint16_t*)((char*) [data bytes] + 10);
+ hotSpot.x = CFSwapInt16LittleToHost(*hotSpotData++);
+ hotSpot.y = CFSwapInt16LittleToHost(*hotSpotData);
+ haveHotSpot = 1;
+ }
+ }
+ if (!haveHotSpot) {
+ NSSize size = [image size];
+ hotSpot.x = size.width * 0.5;
+ hotSpot.y = size.height * 0.5;
+ }
+ hotSpot.y = -hotSpot.y;
+ macCursor = [[NSCursor alloc] initWithImage:image hotSpot:hotSpot];
+ [image release];
+ }
+ macCursorPtr->macCursor = macCursor;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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. */
+{
+ TkMacOSXCursor *macCursorPtr = NULL;
+ const char **argv = NULL;
+ int argc;
+
+ /*
+ * All cursor names are valid lists of one element (for
+ * TkX11-compatibility), even unadorned system cursor names.
+ */
+
+ if (Tcl_SplitList(interp, string, &argc, &argv) == TCL_OK) {
+ if (argc) {
+ macCursorPtr = ckalloc(sizeof(TkMacOSXCursor));
+ macCursorPtr->info.cursor = (Tk_Cursor) macCursorPtr;
+ macCursorPtr->macCursor = nil;
+ macCursorPtr->type = 0;
+ FindCursorByName(macCursorPtr, argv[0]);
+ }
+ ckfree(argv);
+ }
+ if (!macCursorPtr || (!macCursorPtr->macCursor &&
+ macCursorPtr->type != NONE)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad cursor spec \"%s\"", string));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "CURSOR", NULL);
+ if (macCursorPtr) {
+ ckfree(macCursorPtr);
+ macCursorPtr = NULL;
+ }
+ }
+ 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;
+
+ [macCursorPtr->macCursor release];
+ macCursorPtr->macCursor = NULL;
+ 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;
+ static int cursorHidden = 0;
+ int cursorNone = 0;
+
+ gResizeOverride = resizeOverride;
+
+ if (resizeOverride || !macCursorPtr) {
+ [[NSCursor arrowCursor] set];
+ } else {
+ switch (macCursorPtr->type) {
+ case NONE:
+ if (!cursorHidden) {
+ cursorHidden = 1;
+ [NSCursor hide];
+ }
+ cursorNone = 1;
+ break;
+ case SELECTOR:
+ case IMAGENAMED:
+ case IMAGEPATH:
+ case IMAGEBITMAP:
+ default:
+ [macCursorPtr->macCursor set];
+ break;
+ }
+ }
+ if (cursorHidden && !cursorNone) {
+ cursorHidden = 0;
+ [NSCursor unhide];
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpSetCursor --
+ *
+ * Set the current cursor and install it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Changes the current cursor.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpSetCursor(
+ TkpCursor cursor)
+{
+ int cursorChanged = 1;
+
+ if (!gTkOwnsCursor) {
+ return;
+ }
+
+ if (cursor == None) {
+ /*
+ * This is a little tricky. We can't really tell whether
+ * gCurrentCursor is NULL because it was NULL last time around or
+ * because we just freed the current cursor. So if the input cursor is
+ * NULL, we always need to reset it, we can't trust the cursorChanged
+ * logic.
+ */
+
+ gCurrentCursor = NULL;
+ } else {
+ if (gCurrentCursor == (TkMacOSXCursor *) cursor) {
+ cursorChanged = 0;
+ }
+ gCurrentCursor = (TkMacOSXCursor *) cursor;
+ }
+
+ if (Tk_MacOSXIsAppInFront() && cursorChanged) {
+ 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;
+}
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXCursors.h b/tk8.6/macosx/tkMacOSXCursors.h
new file mode 100644
index 0000000..2cf00fb
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXCursors.h
@@ -0,0 +1,89 @@
+/*
+ * tkMacOSXCursors.h --
+ *
+ * This file defines a set of Macintosh cursor resources that
+ * are only available on the Macintosh platform.
+ *
+ * Copyright (c) 1995-1996 Sun Microsystems, Inc.
+ * Copyright 2008-2009, Apple Inc.
+ * Copyright (c) 2008-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+static const unsigned char tkMacOSXCursors[][68] = {
+
+#define TK_MAC_CURSOR_hand 0
+[TK_MAC_CURSOR_hand] = {
+ 0x01, 0x80, 0x1A, 0x70, 0x26, 0x48, 0x26, 0x4A, 0x12, 0x4D, 0x12, 0x49, 0x68, 0x09, 0x98, 0x01,
+ 0x88, 0x02, 0x40, 0x02, 0x20, 0x02, 0x20, 0x04, 0x10, 0x04, 0x08, 0x08, 0x04, 0x08, 0x04, 0x08,
+ 0x01, 0x80, 0x1B, 0xF0, 0x3F, 0xF8, 0x3F, 0xFA, 0x1F, 0xFF, 0x1F, 0xFF, 0x6F, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFE, 0x7F, 0xFE, 0x3F, 0xFE, 0x3F, 0xFC, 0x1F, 0xFC, 0x0F, 0xF8, 0x07, 0xF8, 0x07, 0xF8,
+ 0x00, 0x09, 0x00, 0x08,
+},
+
+#define TK_MAC_CURSOR_bucket 2
+[TK_MAC_CURSOR_bucket] = {
+ 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x09, 0x80, 0x09, 0x40, 0x0B, 0x30, 0x0D, 0x18, 0x09, 0x0C,
+ 0x12, 0x9C, 0x21, 0x2C, 0x10, 0x4C, 0x08, 0x8C, 0x05, 0x0C, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x09, 0x80, 0x09, 0xC0, 0x0B, 0xF0, 0x0F, 0xF8, 0x0F, 0xFC,
+ 0x1F, 0xFC, 0x3F, 0xEC, 0x1F, 0xCC, 0x0F, 0x8C, 0x07, 0x0C, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0D, 0x00, 0x0C,
+},
+
+#define TK_MAC_CURSOR_cancel 3
+[TK_MAC_CURSOR_cancel] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x80, 0x4A, 0x40, 0x4A, 0x40, 0x3F, 0x80,
+ 0x0A, 0x00, 0x3F, 0x80, 0x4A, 0x40, 0x4A, 0x46, 0x31, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x80, 0x7B, 0xC0, 0xFF, 0xE0, 0xFF, 0xE0, 0x7F, 0xC0,
+ 0x3F, 0x80, 0x7F, 0xC0, 0xFF, 0xE6, 0xFF, 0xEF, 0x7B, 0xCF, 0x31, 0x86, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x00, 0x05,
+},
+
+#define TK_MAC_CURSOR_resize 4
+[TK_MAC_CURSOR_resize] = {
+ 0xFF, 0xFF, 0x80, 0x01, 0xBF, 0x01, 0xA1, 0x81, 0xA1, 0xF9, 0xA1, 0x8D, 0xA1, 0x8D, 0xBF, 0x8D,
+ 0x9F, 0x8D, 0x88, 0x0D, 0x88, 0x0D, 0x88, 0x0D, 0x8F, 0xFD, 0x87, 0xFD, 0x80, 0x01, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x00, 0x08, 0x00, 0x08,
+},
+
+#define TK_MAC_CURSOR_eyedrop 5
+[TK_MAC_CURSOR_eyedrop] = {
+ 0x00, 0x0E, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0xFF, 0x00, 0x7E, 0x00, 0xB8, 0x01, 0x18, 0x02, 0x28,
+ 0x04, 0x40, 0x08, 0x80, 0x11, 0x00, 0x22, 0x00, 0x44, 0x00, 0x48, 0x00, 0xB0, 0x00, 0x40, 0x00,
+ 0x00, 0x0E, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0xFF, 0x00, 0x7E, 0x00, 0xF8, 0x01, 0xF8, 0x03, 0xE8,
+ 0x07, 0xC0, 0x0F, 0x80, 0x1F, 0x00, 0x3E, 0x00, 0x7C, 0x00, 0x78, 0x00, 0xF0, 0x00, 0x40, 0x00,
+ 0x00, 0x0F, 0x00, 0x00,
+},
+
+#define TK_MAC_CURSOR_eyedrop_full 6
+[TK_MAC_CURSOR_eyedrop_full] = {
+ 0x00, 0x0E, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0xFF, 0x00, 0x7E, 0x00, 0xB8, 0x01, 0x18, 0x03, 0x28,
+ 0x07, 0xC0, 0x0F, 0x80, 0x1F, 0x00, 0x3E, 0x00, 0x7C, 0x00, 0x78, 0x00, 0xF0, 0x00, 0x40, 0x00,
+ 0x00, 0x0E, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0xFF, 0x00, 0x7E, 0x00, 0xF8, 0x01, 0xF8, 0x03, 0xE8,
+ 0x07, 0xC0, 0x0F, 0x80, 0x1F, 0x00, 0x3E, 0x00, 0x7C, 0x00, 0x78, 0x00, 0xF0, 0x00, 0x40, 0x00,
+ 0x00, 0x0F, 0x00, 0x00,
+},
+
+#define TK_MAC_CURSOR_zoom_in 7
+[TK_MAC_CURSOR_zoom_in] = {
+ 0x07, 0x80, 0x18, 0x60, 0x27, 0x90, 0x58, 0x68, 0x53, 0x28, 0xA3, 0x14, 0xAF, 0xD4, 0xAF, 0xD4,
+ 0xA3, 0x14, 0x53, 0x28, 0x58, 0x68, 0x27, 0x98, 0x18, 0x7C, 0x07, 0x8E, 0x00, 0x07, 0x00, 0x03,
+ 0x07, 0x80, 0x1F, 0xE0, 0x3F, 0xF0, 0x78, 0x78, 0x73, 0x38, 0xE3, 0x1C, 0xEF, 0xDC, 0xEF, 0xDC,
+ 0xE3, 0x1C, 0x73, 0x38, 0x78, 0x78, 0x3F, 0xF8, 0x1F, 0xFC, 0x07, 0x8E, 0x00, 0x07, 0x00, 0x03,
+ 0x00, 0x07, 0x00, 0x07,
+},
+
+#define TK_MAC_CURSOR_zoom_out 8
+[TK_MAC_CURSOR_zoom_out] = {
+ 0x07, 0x80, 0x18, 0x60, 0x27, 0x90, 0x58, 0x68, 0x50, 0x28, 0xA0, 0x14, 0xAF, 0xD4, 0xAF, 0xD4,
+ 0xA0, 0x14, 0x50, 0x28, 0x58, 0x68, 0x27, 0x98, 0x18, 0x7C, 0x07, 0x8E, 0x00, 0x07, 0x00, 0x03,
+ 0x07, 0x80, 0x1F, 0xE0, 0x3F, 0xF0, 0x78, 0x78, 0x70, 0x38, 0xE0, 0x1C, 0xEF, 0xDC, 0xEF, 0xDC,
+ 0xE0, 0x1C, 0x70, 0x38, 0x78, 0x78, 0x3F, 0xF8, 0x1F, 0xFC, 0x07, 0x8E, 0x00, 0x07, 0x00, 0x03,
+ 0x00, 0x07, 0x00, 0x07,
+},
+
+};
diff --git a/tk8.6/macosx/tkMacOSXDebug.c b/tk8.6/macosx/tkMacOSXDebug.c
new file mode 100644
index 0000000..78008f0
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXDebug.c
@@ -0,0 +1,166 @@
+/*
+ * tkMacOSXDebug.c --
+ *
+ * Implementation of Macintosh specific functions for debugging MacOS
+ * events, regions, etc...
+ *
+ * Copyright 2001-2009, Apple Inc.
+ * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkMacOSXPrivate.h"
+#include "tkMacOSXDebug.h"
+
+#ifdef TK_MAC_DEBUG
+
+#include <mach-o/dyld.h>
+#include <mach-o/nlist.h>
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXGetNamedDebugSymbol --
+ *
+ * Dynamically acquire address of a named symbol from a loaded dynamic
+ * library, so that we can use API that may not be available on all OS
+ * versions. For debugging purposes, if we cannot find the symbol with
+ * the usual dynamic library APIs, we manually walk the symbol table of
+ * the loaded library. This allows access to unexported symbols such as
+ * private_extern internal debugging functions. If module is NULL or the
+ * empty string, search all loaded libraries (could be very expensive and
+ * should be avoided).
+ *
+ * THIS FUCTION IS ONLY TO BE USED FOR DEBUGGING PURPOSES, IT MAY BREAK
+ * UNEXPECTEDLY IN THE FUTURE!
+ *
+ * Results:
+ * Address of given symbol or NULL if unavailable.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+MODULE_SCOPE void *
+TkMacOSXGetNamedDebugSymbol(
+ const char *module,
+ const char *symbol)
+{
+ void *addr = TkMacOSXGetNamedSymbol(module, symbol);
+
+#ifndef __LP64__
+ if (!addr) {
+ const struct mach_header *mh = NULL;
+ uint32_t i, n = _dyld_image_count();
+ size_t module_len = 0;
+
+ if (module && *module) {
+ module_len = strlen(module);
+ }
+ for (i = 0; i < n; i++) {
+ if (module && *module) {
+ /* Find image with given module name */
+ char *name;
+ const char *path = _dyld_get_image_name(i);
+
+ if (!path) {
+ continue;
+ }
+ name = strrchr(path, '/') + 1;
+ if (strncmp(name, module, module_len) != 0) {
+ continue;
+ }
+ }
+ mh = _dyld_get_image_header(i);
+ if (mh) {
+ struct load_command *lc;
+ struct symtab_command *st = NULL;
+ struct segment_command *sg = NULL;
+ uint32_t j, m, nsect = 0, txtsectx = 0;
+
+ lc = (struct load_command*)((const char*) mh +
+ sizeof(struct mach_header));
+ m = mh->ncmds;
+ for (j = 0; j < m; j++) {
+ /* Find symbol table and index of __text section */
+ if (lc->cmd == LC_SEGMENT) {
+ /* Find last segment before symbol table */
+ sg = (struct segment_command*) lc;
+ if (!txtsectx) {
+ /* Count total sections until (__TEXT, __text) */
+ uint32_t k, ns = sg->nsects;
+
+ if (strcmp(sg->segname, SEG_TEXT) == 0) {
+ struct section *s = (struct section *)(
+ (char *)sg +
+ sizeof(struct segment_command));
+
+ for(k = 0; k < ns; k++) {
+ if (strcmp(s->sectname, SECT_TEXT) == 0) {
+ txtsectx = nsect+k+1;
+ break;
+ }
+ s++;
+ }
+ }
+ nsect += ns;
+ }
+ } else if (!st && lc->cmd == LC_SYMTAB) {
+ st = (struct symtab_command *) lc;
+ break;
+ }
+ lc = (struct load_command *)((char *) lc + lc->cmdsize);
+ }
+ if (st && sg && txtsectx) {
+ intptr_t base, slide = _dyld_get_image_vmaddr_slide(i);
+ char *strings;
+ struct nlist *sym;
+ uint32_t strsize = st->strsize;
+ int32_t strx;
+
+ /*
+ * Offset file positions by difference to actual position
+ * in memory of last segment before symbol table:
+ */
+
+ base = (intptr_t) sg->vmaddr + slide - sg->fileoff;
+ strings = (char *) (base + st->stroff);
+ sym = (struct nlist *) (base + st->symoff);
+ m = st->nsyms;
+ for (j = 0; j < m; j++) {
+ /* Find symbol with given name in __text section */
+ strx = sym->n_un.n_strx;
+ if ((sym->n_type & N_TYPE) == N_SECT &&
+ sym->n_sect == txtsectx &&
+ strx > 0 && (uint32_t) strx < strsize &&
+ strcmp(strings + strx, symbol) == 0) {
+ addr = (char*) sym->n_value + slide;
+ break;
+ }
+ sym++;
+ }
+ }
+ }
+ if (module && *module) {
+ /* If given a module name, only search corresponding image */
+ break;
+ }
+ }
+ }
+#endif /* __LP64__ */
+ return addr;
+}
+#endif /* TK_MAC_DEBUG */
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXDebug.h b/tk8.6/macosx/tkMacOSXDebug.h
new file mode 100644
index 0000000..ab37187
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXDebug.h
@@ -0,0 +1,34 @@
+/*
+ * tkMacOSXDebug.h --
+ *
+ * Declarations of Macintosh specific functions for debugging MacOS events,
+ * regions, etc...
+ *
+ * Copyright 2001-2009, Apple Inc.
+ * Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef _TKMACDEBUG
+#define _TKMACDEBUG
+
+#ifndef _TKMACINT
+#include "tkMacOSXInt.h"
+#endif
+
+#ifdef TK_MAC_DEBUG
+
+MODULE_SCOPE void* TkMacOSXGetNamedDebugSymbol(const char* module, const char* symbol);
+
+/* Macro to abstract common use of TkMacOSXGetNamedDebugSymbol to initialize named symbols */
+#define TkMacOSXInitNamedDebugSymbol(module, ret, symbol, ...) \
+ static ret (* symbol)(__VA_ARGS__) = (void*)(-1L); \
+ if (symbol == (void*)(-1L)) { \
+ symbol = TkMacOSXGetNamedDebugSymbol(STRINGIFY(module), STRINGIFY(_##symbol));\
+ }
+
+#endif /* TK_MAC_DEBUG */
+
+#endif
diff --git a/tk8.6/macosx/tkMacOSXDefault.h b/tk8.6/macosx/tkMacOSXDefault.h
new file mode 100644
index 0000000..9c3654a
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXDefault.h
@@ -0,0 +1,570 @@
+/*
+ * 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-2009, Apple Inc.
+ * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef _TKMACDEFAULT
+#define _TKMACDEFAULT
+
+//#ifndef TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS
+//#define TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS 1
+//#endif
+
+/*
+ * The definitions below provide symbolic names for the default colors.
+ * NORMAL_BG - Normal background color.
+ * NORMAL_FG - Normal foreground color.
+ * ACTIVE_BG - Background color when widget is active.
+ * ACTIVE_FG - Foreground 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 "systemWindowBackgroundColor"
+#define TEXT_BG "systemTextBackgroundColor"
+#define NORMAL_FG "systemTextColor"
+#define ACTIVE_BG "systemWindowBackgroundColor"
+#define ACTIVE_FG "systemTextColor"
+#define SELECT_BG "systemSelectedTextBackgroundColor"
+#define SELECT_FG "systemSelectedTextColor"
+#define INACTIVE_SELECT_BG "systemSelectedTextBackgroundColor"
+#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 ACTIVE_BG
+#define DEF_BUTTON_ACTIVE_BG_MONO BLACK
+#define DEF_BUTTON_ACTIVE_FG_COLOR ACTIVE_FG
+#define DEF_CHKRAD_ACTIVE_FG_COLOR DEF_BUTTON_ACTIVE_FG_COLOR
+#define DEF_BUTTON_ACTIVE_FG_MONO WHITE
+#define DEF_BUTTON_BG_COLOR NORMAL_BG
+#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 ""
+#define DEF_BUTTON_FG NORMAL_FG
+#define DEF_CHKRAD_FG DEF_BUTTON_FG
+#define DEF_BUTTON_FONT "TkDefaultFont"
+#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"
+//#if TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS
+//#define DEF_BUTTON_HIGHLIGHT_WIDTH "4"
+//#define DEF_BUTTON_HIGHLIGHT_WIDTH_NOCM "1"
+//#else
+#define DEF_BUTTON_HIGHLIGHT_WIDTH "1"
+//#endif
+#define DEF_BUTTON_IMAGE 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_TRISTATE_VALUE ""
+#define DEF_BUTTON_OVER_RELIEF ""
+//#if TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS
+//#define DEF_BUTTON_PADX "12"
+//#define DEF_BUTTON_PADX_NOCM "1"
+//#else
+#define DEF_BUTTON_PADX "1"
+//#endif
+#define DEF_LABCHKRAD_PADX "1"
+//#if TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS
+//#define DEF_BUTTON_PADY "3"
+//#define DEF_BUTTON_PADY_NOCM "1"
+//#else
+#define DEF_BUTTON_PADY "1"
+//#endif
+#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 NULL
+#define DEF_BUTTON_STATE "normal"
+#define DEF_LABEL_TAKE_FOCUS "0"
+#define DEF_BUTTON_TAKE_FOCUS 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 SELECT_FG
+#define DEF_CANVAS_SELECT_FG_MONO WHITE
+#define DEF_CANVAS_TAKE_FOCUS 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:
+ */
+
+/*
+ * I test the following two values in TkpDrawEntryBorderAndFocus
+ * to determine whether to use the native entry widget. So if
+ * you change the defaults to be different from these, then you
+ * won't get the native widget by default.
+ */
+
+#define MAC_OSX_FOCUS_WIDTH 3
+#define MAC_OSX_ENTRY_BORDER 2
+#define MAC_OSX_ENTRY_RELIEF TK_RELIEF_SUNKEN
+#define MAC_OSX_ENTRY_SELECT_RELIEF TK_RELIEF_FLAT
+
+#define DEF_ENTRY_BG_COLOR TEXT_BG
+#define DEF_ENTRY_BG_MONO WHITE
+#define DEF_ENTRY_BORDER_WIDTH "2"
+#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 "TkTextFont"
+#define DEF_ENTRY_FG NORMAL_FG
+#define DEF_ENTRY_HIGHLIGHT_BG NORMAL_BG
+#define DEF_ENTRY_HIGHLIGHT BLACK
+#define DEF_ENTRY_HIGHLIGHT_WIDTH "3"
+#define DEF_ENTRY_INSERT_BG NORMAL_FG
+#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 "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_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 NULL
+#define DEF_ENTRY_STATE "normal"
+#define DEF_ENTRY_TAKE_FOCUS 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 NORMAL_FG
+#define DEF_LABELFRAME_FONT "TkDefaultFont"
+#define DEF_LABELFRAME_TEXT ""
+#define DEF_LABELFRAME_LABELANCHOR "nw"
+
+/*
+ * Defaults for listboxes:
+ */
+
+#define DEF_LISTBOX_ACTIVE_STYLE "dotbox"
+#define DEF_LISTBOX_BG_COLOR TEXT_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 "TkTextFont"
+#define DEF_LISTBOX_FG NORMAL_FG
+#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_JUSTIFY "left"
+#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 NULL
+#define DEF_LISTBOX_WIDTH "20"
+
+/*
+ * Defaults for individual entries of menus:
+ */
+
+#define DEF_MENU_ENTRY_ACTIVE_BG NULL
+#define DEF_MENU_ENTRY_ACTIVE_FG NULL
+#define DEF_MENU_ENTRY_ACCELERATOR NULL
+#define DEF_MENU_ENTRY_BG NULL
+#define DEF_MENU_ENTRY_BITMAP NULL
+#define DEF_MENU_ENTRY_COLUMN_BREAK "0"
+#define DEF_MENU_ENTRY_COMMAND NULL
+#define DEF_MENU_ENTRY_COMPOUND "none"
+#define DEF_MENU_ENTRY_FG NULL
+#define DEF_MENU_ENTRY_FONT NULL
+#define DEF_MENU_ENTRY_HIDE_MARGIN "0"
+#define DEF_MENU_ENTRY_IMAGE NULL
+#define DEF_MENU_ENTRY_INDICATOR "1"
+#define DEF_MENU_ENTRY_LABEL NULL
+#define DEF_MENU_ENTRY_MENU NULL
+#define DEF_MENU_ENTRY_OFF_VALUE "0"
+#define DEF_MENU_ENTRY_ON_VALUE "1"
+#define DEF_MENU_ENTRY_SELECT_IMAGE NULL
+#define DEF_MENU_ENTRY_STATE "normal"
+#define DEF_MENU_ENTRY_VALUE NULL
+#define DEF_MENU_ENTRY_CHECK_VARIABLE NULL
+#define DEF_MENU_ENTRY_RADIO_VARIABLE "selectedButton"
+#define DEF_MENU_ENTRY_SELECT 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 "menu" /* special: see tkMacOSXMenu.c */
+#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 "0"
+#define DEF_MENU_TEAROFF_CMD NULL
+#define DEF_MENU_TITLE ""
+#define DEF_MENU_TYPE "normal"
+
+/*
+ * Defaults for menubuttons:
+ */
+
+#define DEF_MENUBUTTON_ANCHOR "w"
+#define DEF_MENUBUTTON_ACTIVE_BG_COLOR ACTIVE_BG
+#define DEF_MENUBUTTON_ACTIVE_BG_MONO WHITE
+#define DEF_MENUBUTTON_ACTIVE_FG_COLOR ACTIVE_FG
+#define DEF_MENUBUTTON_ACTIVE_FG_MONO BLACK
+#define DEF_MENUBUTTON_BG_COLOR NORMAL_BG
+#define DEF_MENUBUTTON_BG_MONO WHITE
+#define DEF_MENUBUTTON_BITMAP ""
+#define DEF_MENUBUTTON_BORDER_WIDTH "0"
+#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 "TkDefaultFont"
+#define DEF_MENUBUTTON_FG NORMAL_FG
+#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 NULL
+#define DEF_MENUBUTTON_INDICATOR "1"
+#define DEF_MENUBUTTON_JUSTIFY "left"
+#define DEF_MENUBUTTON_MENU ""
+#define DEF_MENUBUTTON_PADX "0"
+#define DEF_MENUBUTTON_PADY "0"
+#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 "1"
+#define DEF_MESSAGE_CURSOR ""
+#define DEF_MESSAGE_FG NORMAL_FG
+#define DEF_MESSAGE_FONT "TkDefaultFont"
+#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 "1"
+#define DEF_PANEDWINDOW_CURSOR ""
+#define DEF_PANEDWINDOW_HANDLEPAD "8"
+#define DEF_PANEDWINDOW_HANDLESIZE "8"
+#define DEF_PANEDWINDOW_HEIGHT ""
+#define DEF_PANEDWINDOW_OPAQUERESIZE "1"
+#define DEF_PANEDWINDOW_ORIENT "horizontal"
+#define DEF_PANEDWINDOW_PROXYBORDER "2"
+#define DEF_PANEDWINDOW_RELIEF "flat"
+#define DEF_PANEDWINDOW_SASHCURSOR ""
+#define DEF_PANEDWINDOW_SASHPAD "0"
+#define DEF_PANEDWINDOW_SASHRELIEF "flat"
+#define DEF_PANEDWINDOW_SASHWIDTH "3"
+#define DEF_PANEDWINDOW_SHOWHANDLE "0"
+#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 ""
+#define DEF_PANEDWINDOW_PANE_HIDE "0"
+#define DEF_PANEDWINDOW_PANE_STRETCH "last"
+
+/*
+ * 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 "1"
+#define DEF_SCALE_COMMAND ""
+#define DEF_SCALE_CURSOR ""
+#define DEF_SCALE_DIGITS "0"
+#define DEF_SCALE_FONT "TkDefaultFont"
+#define DEF_SCALE_FG_COLOR NORMAL_FG
+#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 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 "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 "0"
+#define DEF_SCROLLBAR_JUMP "0"
+#define DEF_SCROLLBAR_ORIENT "vertical"
+#define DEF_SCROLLBAR_RELIEF "flat"
+#define DEF_SCROLLBAR_REPEAT_DELAY "300"
+#define DEF_SCROLLBAR_REPEAT_INTERVAL "100"
+#define DEF_SCROLLBAR_TAKE_FOCUS NULL
+#define DEF_SCROLLBAR_TROUGH_COLOR TROUGH
+#define DEF_SCROLLBAR_TROUGH_MONO WHITE
+#define DEF_SCROLLBAR_WIDTH "15"
+
+/*
+ * Defaults for texts:
+ */
+
+#define DEF_TEXT_AUTO_SEPARATORS "1"
+#define DEF_TEXT_BG_COLOR TEXT_BG
+#define DEF_TEXT_BG_MONO WHITE
+#define DEF_TEXT_BLOCK_CURSOR "0"
+#define DEF_TEXT_BORDER_WIDTH "0"
+#define DEF_TEXT_CURSOR "xterm"
+#define DEF_TEXT_FG NORMAL_FG
+#define DEF_TEXT_EXPORT_SELECTION "1"
+#define DEF_TEXT_FONT "TkFixedFont"
+#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 NORMAL_FG
+#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_UNFOCUSSED "none"
+#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_INACTIVE_SELECT_COLOR INACTIVE_SELECT_BG
+#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 "flat"
+#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_TABSTYLE "tabular"
+#define DEF_TEXT_TAKE_FOCUS 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 "TkDefaultFont"
+
+/*
+ * 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 ""
+
+/*
+ * Defaults for busy windows (not really used yet):
+ */
+
+#define DEF_BUSY_CURSOR "watch"
+
+#endif /* _TKMACDEFAULT */
diff --git a/tk8.6/macosx/tkMacOSXDialog.c b/tk8.6/macosx/tkMacOSXDialog.c
new file mode 100644
index 0000000..322519a
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXDialog.c
@@ -0,0 +1,2165 @@
+/*
+ * tkMacOSXDialog.c --
+ *
+ * Contains the Mac implementation of the common dialog boxes.
+ *
+ * Copyright (c) 1996-1997 Sun Microsystems, Inc.
+ * Copyright 2001-2009, Apple Inc.
+ * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright (c) 2017 Christian Gollwitzer.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkMacOSXPrivate.h"
+#include "tkFileFilter.h"
+#include "tkMacOSXConstants.h"
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1090
+#define modalOK NSOKButton
+#define modalCancel NSCancelButton
+#else
+#define modalOK NSModalResponseOK
+#define modalCancel NSModalResponseCancel
+#endif // MAC_OS_X_VERSION_MIN_REQUIRED < 1090
+#define modalOther -1
+#define modalError -2
+
+/*
+ * Vars for filtering in "open file" and "save file" dialogs.
+ */
+
+typedef struct {
+ bool doFileTypes; /* Show the accessory view which
+ * displays the filter menu */
+ bool preselectFilter; /* A filter was selected by the
+ * typevariable. */
+ bool userHasSelectedFilter; /* The user has changed the filter in
+ * the accessory view. */
+ NSMutableArray *fileTypeNames; /* Array of names, e.g. "Text
+ * document". */
+ NSMutableArray *fileTypeExtensions; /* Array of allowed extensions per
+ * name, e.g. "txt", "doc". */
+ NSMutableArray *fileTypeLabels; /* Displayed string, e.g. "Text
+ * document (.txt, .doc)". */
+ NSMutableArray *fileTypeAllowsAll; /* Boolean if the all pattern (*.*) is
+ * included. */
+ NSMutableArray *allowedExtensions; /* Set of all allowed extensions. */
+ bool allowedExtensionsAllowAll; /* Set of all allowed extensions
+ * includes *.* */
+ NSUInteger fileTypeIndex; /* Index of currently selected
+ * filter. */
+} filepanelFilterInfo;
+
+static filepanelFilterInfo filterInfo;
+static NSOpenPanel *openpanel;
+static NSSavePanel *savepanel;
+
+static const char *const colorOptionStrings[] = {
+ "-initialcolor", "-parent", "-title", NULL
+};
+enum colorOptions {
+ COLOR_INITIAL, COLOR_PARENT, COLOR_TITLE
+};
+
+static const char *const openOptionStrings[] = {
+ "-defaultextension", "-filetypes", "-initialdir", "-initialfile",
+ "-message", "-multiple", "-parent", "-title", "-typevariable",
+ "-command", NULL
+};
+enum openOptions {
+ OPEN_DEFAULT, OPEN_FILETYPES, OPEN_INITDIR, OPEN_INITFILE,
+ OPEN_MESSAGE, OPEN_MULTIPLE, OPEN_PARENT, OPEN_TITLE,
+ OPEN_TYPEVARIABLE, OPEN_COMMAND,
+};
+static const char *const saveOptionStrings[] = {
+ "-defaultextension", "-filetypes", "-initialdir", "-initialfile",
+ "-message", "-parent", "-title", "-typevariable", "-command",
+ "-confirmoverwrite", NULL
+};
+enum saveOptions {
+ SAVE_DEFAULT, SAVE_FILETYPES, SAVE_INITDIR, SAVE_INITFILE,
+ SAVE_MESSAGE, SAVE_PARENT, SAVE_TITLE, SAVE_TYPEVARIABLE, SAVE_COMMAND,
+ SAVE_CONFIRMOW
+};
+static const char *const chooseOptionStrings[] = {
+ "-initialdir", "-message", "-mustexist", "-parent", "-title", "-command",
+ NULL
+};
+enum chooseOptions {
+ CHOOSE_INITDIR, CHOOSE_MESSAGE, CHOOSE_MUSTEXIST, CHOOSE_PARENT,
+ CHOOSE_TITLE, CHOOSE_COMMAND,
+};
+typedef struct {
+ Tcl_Interp *interp;
+ Tcl_Obj *cmdObj;
+ int multiple;
+} FilePanelCallbackInfo;
+
+static const char *const alertOptionStrings[] = {
+ "-default", "-detail", "-icon", "-message", "-parent", "-title",
+ "-type", "-command", NULL
+};
+enum alertOptions {
+ ALERT_DEFAULT, ALERT_DETAIL, ALERT_ICON, ALERT_MESSAGE, ALERT_PARENT,
+ ALERT_TITLE, ALERT_TYPE, ALERT_COMMAND,
+};
+typedef struct {
+ Tcl_Interp *interp;
+ Tcl_Obj *cmdObj;
+ int typeIndex;
+} AlertCallbackInfo;
+static const char *const alertTypeStrings[] = {
+ "abortretryignore", "ok", "okcancel", "retrycancel", "yesno",
+ "yesnocancel", NULL
+};
+enum alertTypeOptions {
+ TYPE_ABORTRETRYIGNORE, TYPE_OK, TYPE_OKCANCEL, TYPE_RETRYCANCEL,
+ TYPE_YESNO, TYPE_YESNOCANCEL
+};
+static const char *const alertIconStrings[] = {
+ "error", "info", "question", "warning", NULL
+};
+enum alertIconOptions {
+ ICON_ERROR, ICON_INFO, ICON_QUESTION, ICON_WARNING
+};
+static const char *const alertButtonStrings[] = {
+ "abort", "retry", "ignore", "ok", "cancel", "no", "yes", NULL
+};
+
+static const NSString *const alertButtonNames[][3] = {
+ [TYPE_ABORTRETRYIGNORE] = {@"Abort", @"Retry", @"Ignore"},
+ [TYPE_OK] = {@"OK"},
+ [TYPE_OKCANCEL] = {@"OK", @"Cancel"},
+ [TYPE_RETRYCANCEL] = {@"Retry", @"Cancel"},
+ [TYPE_YESNO] = {@"Yes", @"No"},
+ [TYPE_YESNOCANCEL] = {@"Yes", @"No", @"Cancel"},
+};
+static const NSAlertStyle alertStyles[] = {
+ [ICON_ERROR] = NSWarningAlertStyle,
+ [ICON_INFO] = NSInformationalAlertStyle,
+ [ICON_QUESTION] = NSWarningAlertStyle,
+ [ICON_WARNING] = NSCriticalAlertStyle,
+};
+
+/*
+ * Need to map from 'alertButtonStrings' and its corresponding integer, index
+ * to the native button index, which is 1, 2, 3, from right to left. This is
+ * necessary to do for each separate '-type' of button sets.
+ */
+
+static const short alertButtonIndexAndTypeToNativeButtonIndex[][7] = {
+ /* abort retry ignore ok cancel yes no */
+ [TYPE_ABORTRETRYIGNORE] = {1, 2, 3, 0, 0, 0, 0},
+ [TYPE_OK] = {0, 0, 0, 1, 0, 0, 0},
+ [TYPE_OKCANCEL] = {0, 0, 0, 1, 2, 0, 0},
+ [TYPE_RETRYCANCEL] = {0, 1, 0, 0, 2, 0, 0},
+ [TYPE_YESNO] = {0, 0, 0, 0, 0, 2, 1},
+ [TYPE_YESNOCANCEL] = {0, 0, 0, 0, 3, 2, 1},
+};
+
+/*
+ * Need also the inverse mapping, from NSAlertFirstButtonReturn etc to the
+ * descriptive button text string index.
+ */
+
+static const short alertNativeButtonIndexAndTypeToButtonIndex[][3] = {
+ [TYPE_ABORTRETRYIGNORE] = {0, 1, 2},
+ [TYPE_OK] = {3, 0, 0},
+ [TYPE_OKCANCEL] = {3, 4, 0},
+ [TYPE_RETRYCANCEL] = {1, 4, 0},
+ [TYPE_YESNO] = {6, 5, 0},
+ [TYPE_YESNOCANCEL] = {6, 5, 4},
+};
+
+/*
+ * Construct a file URL from directory and filename. Either may be nil. If both
+ * are nil, returns nil.
+ */
+
+static NSURL *
+getFileURL(
+ NSString *directory,
+ NSString *filename)
+{
+ NSURL *url = nil;
+ if (directory) {
+ url = [NSURL fileURLWithPath:directory isDirectory:YES];
+ }
+ if (filename) {
+ url = [NSURL URLWithString:filename relativeToURL:url];
+ }
+ return url;
+}
+
+#pragma mark TKApplication(TKDialog)
+
+@implementation TKApplication(TKDialog)
+
+- (void) tkFilePanelDidEnd: (NSSavePanel *) panel
+ returnCode: (NSInteger) returnCode contextInfo: (void *) contextInfo
+{
+ FilePanelCallbackInfo *callbackInfo = contextInfo;
+
+ if (returnCode == modalOK) {
+ Tcl_Obj *resultObj;
+
+ if (callbackInfo->multiple) {
+ resultObj = Tcl_NewListObj(0, NULL);
+ for (NSURL *url in [(NSOpenPanel*)panel URLs]) {
+ Tcl_ListObjAppendElement(callbackInfo->interp, resultObj,
+ Tcl_NewStringObj([[url path] UTF8String], -1));
+ }
+ } else {
+ resultObj = Tcl_NewStringObj([[[panel URL]path] UTF8String], -1);
+ }
+ if (callbackInfo->cmdObj) {
+ Tcl_Obj **objv, **tmpv;
+ int objc, result = Tcl_ListObjGetElements(callbackInfo->interp,
+ callbackInfo->cmdObj, &objc, &objv);
+
+ if (result == TCL_OK && objc) {
+ tmpv = ckalloc(sizeof(Tcl_Obj *) * (objc + 2));
+ memcpy(tmpv, objv, sizeof(Tcl_Obj *) * objc);
+ tmpv[objc] = resultObj;
+ TkBackgroundEvalObjv(callbackInfo->interp, objc + 1, tmpv,
+ TCL_EVAL_GLOBAL);
+ ckfree(tmpv);
+ }
+ } else {
+ Tcl_SetObjResult(callbackInfo->interp, resultObj);
+ }
+ } else if (returnCode == modalCancel) {
+ Tcl_ResetResult(callbackInfo->interp);
+ }
+ if (panel == [NSApp modalWindow]) {
+ [NSApp stopModalWithCode:returnCode];
+ }
+ if (callbackInfo->cmdObj) {
+ Tcl_DecrRefCount(callbackInfo->cmdObj);
+ ckfree(callbackInfo);
+ }
+}
+
+- (void) tkAlertDidEnd: (NSAlert *) alert returnCode: (NSInteger) returnCode
+ contextInfo: (void *) contextInfo
+{
+ AlertCallbackInfo *callbackInfo = contextInfo;
+
+ if (returnCode >= NSAlertFirstButtonReturn) {
+ Tcl_Obj *resultObj = Tcl_NewStringObj(alertButtonStrings[
+ alertNativeButtonIndexAndTypeToButtonIndex[callbackInfo->
+ typeIndex][returnCode - NSAlertFirstButtonReturn]], -1);
+
+ if (callbackInfo->cmdObj) {
+ Tcl_Obj **objv, **tmpv;
+ int objc, result = Tcl_ListObjGetElements(callbackInfo->interp,
+ callbackInfo->cmdObj, &objc, &objv);
+
+ if (result == TCL_OK && objc) {
+ tmpv = ckalloc(sizeof(Tcl_Obj *) * (objc + 2));
+ memcpy(tmpv, objv, sizeof(Tcl_Obj *) * objc);
+ tmpv[objc] = resultObj;
+ TkBackgroundEvalObjv(callbackInfo->interp, objc + 1, tmpv,
+ TCL_EVAL_GLOBAL);
+ ckfree(tmpv);
+ }
+ } else {
+ Tcl_SetObjResult(callbackInfo->interp, resultObj);
+ }
+ }
+ if ([alert window] == [NSApp modalWindow]) {
+ [NSApp stopModalWithCode:returnCode];
+ }
+ if (callbackInfo->cmdObj) {
+ Tcl_DecrRefCount(callbackInfo->cmdObj);
+ ckfree(callbackInfo);
+ }
+}
+
+- (void)selectFormat:(id)sender {
+ NSPopUpButton *button = (NSPopUpButton *)sender;
+ filterInfo.fileTypeIndex = [button indexOfSelectedItem];
+
+ if ([[filterInfo.fileTypeAllowsAll objectAtIndex:filterInfo.fileTypeIndex] boolValue]) {
+ [openpanel setAllowsOtherFileTypes:YES];
+
+ /*
+ * setAllowsOtherFileTypes might have no effect; it's inherited from
+ * the NSSavePanel, where it has the effect that it does not append an
+ * extension. Setting the allowed file types to nil allows selecting
+ * any file.
+ */
+
+ [openpanel setAllowedFileTypes:nil];
+ } else {
+ NSMutableArray *allowedtypes =
+ [filterInfo.fileTypeExtensions objectAtIndex:filterInfo.fileTypeIndex];
+ [openpanel setAllowedFileTypes:allowedtypes];
+ [openpanel setAllowsOtherFileTypes:NO];
+ }
+
+ filterInfo.userHasSelectedFilter = true;
+}
+
+- (void)saveFormat:(id)sender {
+ NSPopUpButton *button = (NSPopUpButton *)sender;
+ filterInfo.fileTypeIndex = [button indexOfSelectedItem];
+
+ if ([[filterInfo.fileTypeAllowsAll objectAtIndex:filterInfo.fileTypeIndex] boolValue]) {
+ [savepanel setAllowsOtherFileTypes:YES];
+ [savepanel setAllowedFileTypes:nil];
+ } else {
+ NSMutableArray *allowedtypes =
+ [filterInfo.fileTypeExtensions objectAtIndex:filterInfo.fileTypeIndex];
+ [savepanel setAllowedFileTypes:allowedtypes];
+ [savepanel setAllowsOtherFileTypes:NO];
+ }
+
+ filterInfo.userHasSelectedFilter = true;
+}
+
+@end
+
+#pragma mark -
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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. */
+{
+ int result = TCL_ERROR;
+ Tk_Window parent, tkwin = clientData;
+ const char *title = NULL;
+ int i;
+ NSColor *color = nil, *initialColor = nil;
+ NSColorPanel *colorPanel;
+ NSInteger returnCode, numberOfComponents = 0;
+
+ for (i = 1; i < objc; i += 2) {
+ int index;
+ const char *value;
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[i], colorOptionStrings,
+ sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
+ goto end;
+ }
+ if (i + 1 == objc) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "value for \"%s\" missing", Tcl_GetString(objv[i])));
+ Tcl_SetErrorCode(interp, "TK", "COLORDIALOG", "VALUE", NULL);
+ goto end;
+ }
+ value = Tcl_GetString(objv[i + 1]);
+
+ switch (index) {
+ case COLOR_INITIAL: {
+ XColor *colorPtr;
+
+ colorPtr = Tk_GetColor(interp, tkwin, value);
+ if (colorPtr == NULL) {
+ goto end;
+ }
+ initialColor = TkMacOSXGetNSColor(NULL, colorPtr->pixel);
+ Tk_FreeColor(colorPtr);
+ break;
+ }
+ case COLOR_PARENT:
+ parent = Tk_NameToWindow(interp, value, tkwin);
+ if (parent == NULL) {
+ goto end;
+ }
+ break;
+ case COLOR_TITLE:
+ title = value;
+ break;
+ }
+ }
+ colorPanel = [NSColorPanel sharedColorPanel];
+ [colorPanel orderOut:NSApp];
+ [colorPanel setContinuous:NO];
+ [colorPanel setBecomesKeyOnlyIfNeeded:NO];
+ [colorPanel setShowsAlpha: NO];
+ [colorPanel _setUseModalAppearance:YES];
+ if (title) {
+ NSString *s = [[NSString alloc] initWithUTF8String:title];
+
+ [colorPanel setTitle:s];
+ [s release];
+ }
+ if (initialColor) {
+ [colorPanel setColor:initialColor];
+ }
+ returnCode = [NSApp runModalForWindow:colorPanel];
+ if (returnCode == modalOK) {
+ color = [[colorPanel color] colorUsingColorSpace:
+ [NSColorSpace deviceRGBColorSpace]];
+ numberOfComponents = [color numberOfComponents];
+ }
+ if (color && numberOfComponents >= 3 && numberOfComponents <= 4) {
+ CGFloat components[4];
+ char colorstr[8];
+
+ [color getComponents:components];
+ snprintf(colorstr, 8, "#%02x%02x%02x",
+ (short)(components[0] * 255),
+ (short)(components[1] * 255),
+ (short)(components[2] * 255));
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(colorstr, 7));
+ } else {
+ Tcl_ResetResult(interp);
+ }
+ result = TCL_OK;
+
+end:
+ return result;
+}
+
+/*
+ * Dissect the -filetype nested lists and store the information in the
+ * filterInfo structure.
+ */
+
+static int
+parseFileFilters(
+ Tcl_Interp *interp,
+ Tcl_Obj *fileTypesPtr,
+ Tcl_Obj *typeVariablePtr)
+{
+
+ if (!fileTypesPtr) {
+ filterInfo.doFileTypes = false;
+ return TCL_OK;
+ }
+
+ FileFilterList fl;
+
+ TkInitFileFilters(&fl);
+ if (TkGetFileFilters(interp, &fl, fileTypesPtr, 0) != TCL_OK) {
+ TkFreeFileFilters(&fl);
+ return TCL_ERROR;
+ }
+
+ filterInfo.doFileTypes = (fl.filters != NULL);
+
+ filterInfo.fileTypeIndex = 0;
+ filterInfo.fileTypeExtensions = [NSMutableArray array];
+ filterInfo.fileTypeNames = [NSMutableArray array];
+ filterInfo.fileTypeLabels = [NSMutableArray array];
+ filterInfo.fileTypeAllowsAll = [NSMutableArray array];
+
+ filterInfo.allowedExtensions = [NSMutableArray array];
+ filterInfo.allowedExtensionsAllowAll = NO;
+
+ if (filterInfo.doFileTypes) {
+ for (FileFilter *filterPtr = fl.filters; filterPtr;
+ filterPtr = filterPtr->next) {
+ NSString *name = [[NSString alloc] initWithUTF8String: filterPtr->name];
+
+ [filterInfo.fileTypeNames addObject:name];
+ [name release];
+ NSMutableArray *clauseextensions = [NSMutableArray array];
+ NSMutableArray *displayextensions = [NSMutableArray array];
+ bool allowsAll = NO;
+
+ for (FileFilterClause *clausePtr = filterPtr->clauses; clausePtr;
+ clausePtr = clausePtr->next) {
+
+ for (GlobPattern *globPtr = clausePtr->patterns; globPtr;
+ globPtr = globPtr->next) {
+ const char *str = globPtr->pattern;
+ while (*str && (*str == '*' || *str == '.')) {
+ str++;
+ }
+ if (*str) {
+ NSString *extension = [[NSString alloc] initWithUTF8String:str];
+ if (![filterInfo.allowedExtensions containsObject:extension]) {
+ [filterInfo.allowedExtensions addObject:extension];
+ }
+
+ [clauseextensions addObject:extension];
+ [displayextensions addObject:[@"." stringByAppendingString:extension]];
+
+ [extension release];
+ } else {
+ /*
+ * It is the all pattern (*, .* or *.*)
+ */
+
+ allowsAll = YES;
+ filterInfo.allowedExtensionsAllowAll = YES;
+ [displayextensions addObject:@"*"];
+ }
+ }
+ }
+ [filterInfo.fileTypeExtensions addObject:clauseextensions];
+ [filterInfo.fileTypeAllowsAll addObject:[NSNumber numberWithBool:allowsAll]];
+
+ NSMutableString *label = [[NSMutableString alloc] initWithString:name];
+ [label appendString:@" ("];
+ [label appendString:[displayextensions componentsJoinedByString:@", "]];
+ [label appendString:@")"];
+ [filterInfo.fileTypeLabels addObject:label];
+ [label release];
+ }
+
+ /*
+ * Check if the typevariable exists and matches one of the names.
+ */
+
+ filterInfo.preselectFilter = false;
+ filterInfo.userHasSelectedFilter = false;
+ if (typeVariablePtr) {
+ /*
+ * Extract the variable content as a NSString.
+ */
+
+ Tcl_Obj *selectedFileTypeObj = Tcl_ObjGetVar2(interp,
+ typeVariablePtr, NULL, TCL_GLOBAL_ONLY);
+
+ /*
+ * Check that the typevariable exists.
+ */
+
+ if (selectedFileTypeObj != NULL) {
+ const char *selectedFileType =
+ Tcl_GetString(selectedFileTypeObj);
+ NSString *selectedFileTypeStr =
+ [[NSString alloc] initWithUTF8String:selectedFileType];
+ NSUInteger index =
+ [filterInfo.fileTypeNames indexOfObject:selectedFileTypeStr];
+
+ if (index != NSNotFound) {
+ filterInfo.fileTypeIndex = index;
+ filterInfo.preselectFilter = true;
+ }
+ }
+ }
+
+ }
+
+ TkFreeFileFilters(&fl);
+ return TCL_OK;
+}
+
+static bool
+filterCompatible(
+ NSString *extension,
+ int filterIndex)
+{
+ NSMutableArray *allowedExtensions =
+ [filterInfo.fileTypeExtensions objectAtIndex: filterIndex];
+
+ /*
+ * If this contains the all pattern, accept any extension.
+ */
+
+ if ([[filterInfo.fileTypeAllowsAll objectAtIndex:filterIndex] boolValue]) {
+ return true;
+ }
+
+ return [allowedExtensions containsObject: extension];
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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. */
+{
+ Tk_Window tkwin = clientData;
+ char *str;
+ int i, result = TCL_ERROR, haveParentOption = 0;
+ int index, len, multiple = 0;
+ Tcl_Obj *cmdObj = NULL, *typeVariablePtr = NULL, *fileTypesPtr = NULL;
+ FilePanelCallbackInfo callbackInfoStruct;
+ FilePanelCallbackInfo *callbackInfo = &callbackInfoStruct;
+ NSString *directory = nil, *filename = nil;
+ NSString *message = nil, *title = nil;
+ NSWindow *parent;
+ openpanel = [NSOpenPanel openPanel];
+ NSInteger modalReturnCode = modalError;
+ BOOL parentIsKey = NO;
+
+ for (i = 1; i < objc; i += 2) {
+ if (Tcl_GetIndexFromObjStruct(interp, objv[i], openOptionStrings,
+ sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
+ goto end;
+ }
+ if (i + 1 == objc) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "value for \"%s\" missing", Tcl_GetString(objv[i])));
+ Tcl_SetErrorCode(interp, "TK", "FILEDIALOG", "VALUE", NULL);
+ goto end;
+ }
+ switch (index) {
+ case OPEN_DEFAULT:
+ break;
+ case OPEN_FILETYPES:
+ fileTypesPtr = objv[i + 1];
+ break;
+ case OPEN_INITDIR:
+ str = Tcl_GetStringFromObj(objv[i + 1], &len);
+ if (len) {
+ directory = [[[NSString alloc] initWithUTF8String:str]
+ autorelease];
+ }
+ break;
+ case OPEN_INITFILE:
+ str = Tcl_GetStringFromObj(objv[i + 1], &len);
+ if (len) {
+ filename = [[[NSString alloc] initWithUTF8String:str]
+ autorelease];
+ }
+ break;
+ case OPEN_MESSAGE:
+ message = [[NSString alloc] initWithUTF8String:
+ Tcl_GetString(objv[i + 1])];
+ break;
+ case OPEN_MULTIPLE:
+ if (Tcl_GetBooleanFromObj(interp, objv[i + 1],
+ &multiple) != TCL_OK) {
+ goto end;
+ }
+ break;
+ case OPEN_PARENT:
+ str = Tcl_GetStringFromObj(objv[i + 1], &len);
+ tkwin = Tk_NameToWindow(interp, str, tkwin);
+ if (!tkwin) {
+ goto end;
+ }
+ haveParentOption = 1;
+ break;
+ case OPEN_TITLE:
+ title = [[NSString alloc] initWithUTF8String:
+ Tcl_GetString(objv[i + 1])];
+ break;
+ case OPEN_TYPEVARIABLE:
+ typeVariablePtr = objv[i + 1];
+ break;
+ case OPEN_COMMAND:
+ cmdObj = objv[i+1];
+ break;
+ }
+ }
+
+ if (title) {
+ [openpanel setTitle:title];
+
+ /*
+ * From OSX 10.11, the title string is silently ignored in the open
+ * panel. Prepend the title to the message in this case. NOTE should
+ * be conditional on OSX version, but -mmacosx-version-min does not
+ * revert this behaviour
+ */
+
+ if (message) {
+ NSString *fullmessage =
+ [[NSString alloc] initWithFormat:@"%@\n%@", title, message];
+ [message release];
+ [title release];
+ message = fullmessage;
+ } else {
+ message = title;
+ }
+ }
+
+ if (message) {
+ [openpanel setMessage:message];
+ [message release];
+ }
+
+ [openpanel setAllowsMultipleSelection:multiple];
+
+ if (parseFileFilters(interp, fileTypesPtr, typeVariablePtr) != TCL_OK) {
+ goto end;
+ }
+
+ if (filterInfo.doFileTypes) {
+ NSView *accessoryView = [[NSView alloc]
+ initWithFrame:NSMakeRect(0.0, 0.0, 300, 32.0)];
+ NSTextField *label = [[NSTextField alloc]
+ initWithFrame:NSMakeRect(0, 0, 60, 22)];
+
+ [label setEditable:NO];
+ [label setStringValue:@"Filter:"];
+ [label setBordered:NO];
+ [label setBezeled:NO];
+ [label setDrawsBackground:NO];
+
+ NSPopUpButton *popupButton = [[NSPopUpButton alloc]
+ initWithFrame:NSMakeRect(50.0, 2, 240, 22.0) pullsDown:NO];
+
+ [popupButton addItemsWithTitles:filterInfo.fileTypeLabels];
+ [popupButton setAction:@selector(selectFormat:)];
+
+ [accessoryView addSubview:label];
+ [accessoryView addSubview:popupButton];
+
+ if (filterInfo.preselectFilter) {
+ /*
+ * A specific filter was selected from the typevariable. Select it
+ * and open the accessory view.
+ */
+
+ [popupButton selectItemAtIndex:filterInfo.fileTypeIndex];
+
+ /*
+ * On OSX > 10.11, the options are not visible by default. Ergo
+ * allow all file types
+ [openpanel setAllowedFileTypes:filterInfo.fileTypeExtensions[filterInfo.fileTypeIndex]];
+ */
+ [openpanel setAllowedFileTypes:filterInfo.allowedExtensions];
+ } else {
+ [openpanel setAllowedFileTypes:filterInfo.allowedExtensions];
+ }
+
+ if (filterInfo.allowedExtensionsAllowAll) {
+ [openpanel setAllowsOtherFileTypes:YES];
+ } else {
+ [openpanel setAllowsOtherFileTypes:NO];
+ }
+
+ [openpanel setAccessoryView:accessoryView];
+ } else {
+ /*
+ * No filters are given. Allow picking all files.
+ */
+
+ [openpanel setAllowsOtherFileTypes:YES];
+ }
+
+ if (cmdObj) {
+ callbackInfo = ckalloc(sizeof(FilePanelCallbackInfo));
+ if (Tcl_IsShared(cmdObj)) {
+ cmdObj = Tcl_DuplicateObj(cmdObj);
+ }
+ Tcl_IncrRefCount(cmdObj);
+ }
+
+ callbackInfo->cmdObj = cmdObj;
+ callbackInfo->interp = interp;
+ callbackInfo->multiple = multiple;
+ parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
+ if (haveParentOption && parent && ![parent attachedSheet]) {
+ parentIsKey = [parent isKeyWindow];
+ if (directory || filename) {
+ NSURL *fileURL = getFileURL(directory, filename);
+
+ [openpanel setDirectoryURL:fileURL];
+ }
+
+ [openpanel beginSheetModalForWindow:parent
+ completionHandler:^(NSInteger returnCode) {
+ [NSApp tkFilePanelDidEnd:openpanel
+ returnCode:returnCode
+ contextInfo:callbackInfo ];
+ }];
+ modalReturnCode = cmdObj ? modalOther :
+ [NSApp runModalForWindow:openpanel];
+ } else {
+ if (directory || filename) {
+ NSURL *fileURL = getFileURL(directory, filename);
+
+ [openpanel setDirectoryURL:fileURL];
+ }
+
+ modalReturnCode = [openpanel runModal];
+ [NSApp tkFilePanelDidEnd:openpanel returnCode:modalReturnCode
+ contextInfo:callbackInfo];
+ }
+ result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR;
+ if (parentIsKey) {
+ [parent makeKeyWindow];
+ }
+
+ if ((typeVariablePtr && (modalReturnCode == NSOKButton))
+ && filterInfo.doFileTypes) {
+ /*
+ * The -typevariable must be set to the selected file type, if the
+ * dialog was not cancelled.
+ */
+
+ NSUInteger selectedFilterIndex = filterInfo.fileTypeIndex;
+ NSString *selectedFilter = NULL;
+
+ if (filterInfo.userHasSelectedFilter) {
+ selectedFilterIndex = filterInfo.fileTypeIndex;
+ selectedFilter = [filterInfo.fileTypeNames objectAtIndex:selectedFilterIndex];
+ } else {
+ /*
+ * Difficult case: the user has not touched the filter settings,
+ * but we must return something in the typevariable. First check if
+ * the preselected type is compatible with the selected file,
+ * otherwise choose the first compatible type from the list,
+ * finally fall back to the empty string.
+ */
+
+ NSURL *selectedFile;
+
+ if (multiple) {
+ /*
+ * Use the first file in the case of multiple selection.
+ * Anyway it is not overly useful here.
+ */
+ selectedFile = [[openpanel URLs] objectAtIndex:0];
+ } else {
+ selectedFile = [openpanel URL];
+ }
+
+ NSString *extension = [selectedFile pathExtension];
+
+ if (filterInfo.preselectFilter &&
+ filterCompatible(extension, filterInfo.fileTypeIndex)) {
+ selectedFilterIndex = filterInfo.fileTypeIndex; // The preselection from the typevariable
+ selectedFilter = [filterInfo.fileTypeNames objectAtIndex:selectedFilterIndex];
+ } else {
+ // scan the list
+ NSUInteger i;
+
+ for (i = 0; i < [filterInfo.fileTypeNames count]; i++) {
+ if (filterCompatible(extension, i)) {
+ selectedFilterIndex = i;
+ break;
+ }
+ }
+ if (i == selectedFilterIndex) {
+ selectedFilter = [filterInfo.fileTypeNames objectAtIndex:selectedFilterIndex];
+ } else {
+ selectedFilter = @"";
+ }
+ }
+ }
+
+ Tcl_ObjSetVar2(interp, typeVariablePtr, NULL,
+ Tcl_NewStringObj([selectedFilter UTF8String], -1),
+ TCL_GLOBAL_ONLY);
+ }
+
+ end:
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetSaveFileObjCmd --
+ *
+ * This procedure implements the "save 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_GetSaveFileObjCmd(
+ 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 = clientData;
+ char *str;
+ int i, result = TCL_ERROR, haveParentOption = 0;
+ int confirmOverwrite = 1;
+ int index, len;
+ Tcl_Obj *cmdObj = NULL, *typeVariablePtr = NULL, *fileTypesPtr = NULL;
+ FilePanelCallbackInfo callbackInfoStruct;
+ FilePanelCallbackInfo *callbackInfo = &callbackInfoStruct;
+ NSString *directory = nil, *filename = nil, *defaultType = nil;
+ NSString *message = nil, *title = nil;
+ NSWindow *parent;
+ savepanel = [NSSavePanel savePanel];
+ NSInteger modalReturnCode = modalError;
+ BOOL parentIsKey = NO;
+
+ for (i = 1; i < objc; i += 2) {
+ if (Tcl_GetIndexFromObjStruct(interp, objv[i], saveOptionStrings,
+ sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
+ goto end;
+ }
+ if (i + 1 == objc) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "value for \"%s\" missing", Tcl_GetString(objv[i])));
+ Tcl_SetErrorCode(interp, "TK", "FILEDIALOG", "VALUE", NULL);
+ goto end;
+ }
+ switch (index) {
+ case SAVE_DEFAULT:
+ str = Tcl_GetStringFromObj(objv[i + 1], &len);
+ while (*str && (*str == '*' || *str == '.')) {
+ str++;
+ }
+ if (*str) {
+ defaultType = [[[NSString alloc] initWithUTF8String:str]
+ autorelease];
+ }
+ break;
+ case SAVE_FILETYPES:
+ fileTypesPtr = objv[i + 1];
+ break;
+ case SAVE_INITDIR:
+ str = Tcl_GetStringFromObj(objv[i + 1], &len);
+ if (len) {
+ directory = [[[NSString alloc] initWithUTF8String:str]
+ autorelease];
+ }
+ break;
+ case SAVE_INITFILE:
+ str = Tcl_GetStringFromObj(objv[i + 1], &len);
+ if (len) {
+ filename = [[[NSString alloc] initWithUTF8String:str]
+ autorelease];
+ [savepanel setNameFieldStringValue:filename];
+ }
+ break;
+ case SAVE_MESSAGE:
+ message = [[NSString alloc] initWithUTF8String:
+ Tcl_GetString(objv[i + 1])];
+ break;
+ case SAVE_PARENT:
+ str = Tcl_GetStringFromObj(objv[i + 1], &len);
+ tkwin = Tk_NameToWindow(interp, str, tkwin);
+ if (!tkwin) {
+ goto end;
+ }
+ haveParentOption = 1;
+ break;
+ case SAVE_TITLE:
+ title = [[NSString alloc] initWithUTF8String:
+ Tcl_GetString(objv[i + 1])];
+ break;
+ case SAVE_TYPEVARIABLE:
+ typeVariablePtr = objv[i + 1];
+ break;
+ case SAVE_COMMAND:
+ cmdObj = objv[i+1];
+ break;
+ case SAVE_CONFIRMOW:
+ if (Tcl_GetBooleanFromObj(interp, objv[i + 1],
+ &confirmOverwrite) != TCL_OK) {
+ goto end;
+ }
+ break;
+ }
+ }
+
+ if (title) {
+ [savepanel setTitle:title];
+
+ /*
+ * From OSX 10.11, the title string is silently ignored, if the save
+ * panel is a sheet. Prepend the title to the message in this case.
+ * NOTE: should be conditional on OSX version, but -mmacosx-version-min
+ * does not revert this behaviour.
+ */
+
+ if (haveParentOption) {
+ if (message) {
+ NSString *fullmessage =
+ [[NSString alloc] initWithFormat:@"%@\n%@",title,message];
+ [message release];
+ [title release];
+ message = fullmessage;
+ } else {
+ message = title;
+ }
+ }
+ }
+
+ if (message) {
+ [savepanel setMessage:message];
+ [message release];
+ }
+
+ if (parseFileFilters(interp, fileTypesPtr, typeVariablePtr) != TCL_OK) {
+ goto end;
+ }
+
+ if (filterInfo.doFileTypes) {
+ NSView *accessoryView = [[NSView alloc]
+ initWithFrame:NSMakeRect(0.0, 0.0, 300, 32.0)];
+ NSTextField *label = [[NSTextField alloc]
+ initWithFrame:NSMakeRect(0, 0, 60, 22)];
+
+ [label setEditable:NO];
+ [label setStringValue:NSLocalizedString(@"Format:", nil)];
+ [label setBordered:NO];
+ [label setBezeled:NO];
+ [label setDrawsBackground:NO];
+
+ NSPopUpButton *popupButton = [[NSPopUpButton alloc]
+ initWithFrame:NSMakeRect(50.0, 2, 340, 22.0) pullsDown:NO];
+
+ [popupButton addItemsWithTitles:filterInfo.fileTypeLabels];
+ [popupButton selectItemAtIndex:filterInfo.fileTypeIndex];
+ [popupButton setAction:@selector(saveFormat:)];
+
+ [accessoryView addSubview:label];
+ [accessoryView addSubview:popupButton];
+
+ [savepanel setAccessoryView:accessoryView];
+
+ [savepanel setAllowedFileTypes:[filterInfo.fileTypeExtensions objectAtIndex:filterInfo.fileTypeIndex]];
+ [savepanel setAllowsOtherFileTypes:filterInfo.allowedExtensionsAllowAll];
+ } else if (defaultType) {
+ /*
+ * If no filetypes are given, defaultextension is an alternative way to
+ * specify the attached extension. Just propose this extension, but
+ * don't display an accessory view.
+ */
+
+ NSMutableArray *AllowedFileTypes = [NSMutableArray array];
+
+ [AllowedFileTypes addObject:defaultType];
+ [savepanel setAllowedFileTypes:AllowedFileTypes];
+ [savepanel setAllowsOtherFileTypes:YES];
+ }
+
+ [savepanel setCanSelectHiddenExtension:YES];
+ [savepanel setExtensionHidden:NO];
+
+ if (cmdObj) {
+ callbackInfo = ckalloc(sizeof(FilePanelCallbackInfo));
+ if (Tcl_IsShared(cmdObj)) {
+ cmdObj = Tcl_DuplicateObj(cmdObj);
+ }
+ Tcl_IncrRefCount(cmdObj);
+ }
+ callbackInfo->cmdObj = cmdObj;
+ callbackInfo->interp = interp;
+ callbackInfo->multiple = 0;
+
+ parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
+ if (haveParentOption && parent && ![parent attachedSheet]) {
+ parentIsKey = [parent isKeyWindow];
+ if (directory) {
+ [savepanel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]];
+ }
+
+ /*
+ * Check for file name, otherwise set to empty string; crashes with
+ * uncaught exception if set to nil.
+ */
+
+ if (filename) {
+ [savepanel setNameFieldStringValue:filename];
+ } else {
+ [savepanel setNameFieldStringValue:@""];
+ }
+ [savepanel beginSheetModalForWindow:parent
+ completionHandler:^(NSInteger returnCode) {
+ [NSApp tkFilePanelDidEnd:savepanel
+ returnCode:returnCode
+ contextInfo:callbackInfo];
+ }];
+ modalReturnCode = cmdObj ? modalOther :
+ [NSApp runModalForWindow:savepanel];
+ } else {
+ if (directory) {
+ [savepanel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]];
+ }
+
+ /*
+ * Check for file name, otherwise set to empty string; crashes with
+ * uncaught exception if set to nil.
+ */
+
+ if (filename) {
+ [savepanel setNameFieldStringValue:filename];
+ } else {
+ [savepanel setNameFieldStringValue:@""];
+ }
+ modalReturnCode = [savepanel runModal];
+ [NSApp tkFilePanelDidEnd:savepanel returnCode:modalReturnCode
+ contextInfo:callbackInfo];
+ }
+ result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR;
+ if (parentIsKey) {
+ [parent makeKeyWindow];
+ }
+
+ if (typeVariablePtr && (modalReturnCode == NSOKButton)
+ && filterInfo.doFileTypes) {
+ /*
+ * The -typevariable must be set to the selected file type, if the
+ * dialog was not cancelled.
+ */
+
+ NSString *selectedFilter =
+ [filterInfo.fileTypeNames objectAtIndex:filterInfo.fileTypeIndex];
+ Tcl_ObjSetVar2(interp, typeVariablePtr, NULL,
+ Tcl_NewStringObj([selectedFilter UTF8String], -1),
+ TCL_GLOBAL_ONLY);
+ }
+
+ end:
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_ChooseDirectoryObjCmd --
+ *
+ * This procedure implements the "tk_chooseDirectory" dialog box for the
+ * MacOS X platform. See the user documentation for details on what it
+ * does.
+ *
+ * Results:
+ * See user documentation.
+ *
+ * Side effects:
+ * A modal dialog window is created.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_ChooseDirectoryObjCmd(
+ 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 = clientData;
+ char *str;
+ int i, result = TCL_ERROR, haveParentOption = 0;
+ int index, len, mustexist = 0;
+ Tcl_Obj *cmdObj = NULL;
+ FilePanelCallbackInfo callbackInfoStruct;
+ FilePanelCallbackInfo *callbackInfo = &callbackInfoStruct;
+ NSString *directory = nil;
+ NSString *message, *title;
+ NSWindow *parent;
+ NSOpenPanel *panel = [NSOpenPanel openPanel];
+ NSInteger modalReturnCode = modalError;
+ BOOL parentIsKey = NO;
+
+ for (i = 1; i < objc; i += 2) {
+ if (Tcl_GetIndexFromObjStruct(interp, objv[i], chooseOptionStrings,
+ sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
+ goto end;
+ }
+ if (i + 1 == objc) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "value for \"%s\" missing", Tcl_GetString(objv[i])));
+ Tcl_SetErrorCode(interp, "TK", "DIRDIALOG", "VALUE", NULL);
+ goto end;
+ }
+ switch (index) {
+ case CHOOSE_INITDIR:
+ str = Tcl_GetStringFromObj(objv[i + 1], &len);
+ if (len) {
+ directory = [[[NSString alloc] initWithUTF8String:str]
+ autorelease];
+ }
+ break;
+ case CHOOSE_MESSAGE:
+ message = [[NSString alloc] initWithUTF8String:
+ Tcl_GetString(objv[i + 1])];
+ [panel setMessage:message];
+ [message release];
+ break;
+ case CHOOSE_MUSTEXIST:
+ if (Tcl_GetBooleanFromObj(interp, objv[i + 1],
+ &mustexist) != TCL_OK) {
+ goto end;
+ }
+ break;
+ case CHOOSE_PARENT:
+ str = Tcl_GetStringFromObj(objv[i + 1], &len);
+ tkwin = Tk_NameToWindow(interp, str, tkwin);
+ if (!tkwin) {
+ goto end;
+ }
+ haveParentOption = 1;
+ break;
+ case CHOOSE_TITLE:
+ title = [[NSString alloc] initWithUTF8String:
+ Tcl_GetString(objv[i + 1])];
+ [panel setTitle:title];
+ [title release];
+ break;
+ case CHOOSE_COMMAND:
+ cmdObj = objv[i+1];
+ break;
+ }
+ }
+ [panel setPrompt:@"Choose"];
+ [panel setCanChooseFiles:NO];
+ [panel setCanChooseDirectories:YES];
+ [panel setCanCreateDirectories:!mustexist];
+ if (cmdObj) {
+ callbackInfo = ckalloc(sizeof(FilePanelCallbackInfo));
+ if (Tcl_IsShared(cmdObj)) {
+ cmdObj = Tcl_DuplicateObj(cmdObj);
+ }
+ Tcl_IncrRefCount(cmdObj);
+ }
+ callbackInfo->cmdObj = cmdObj;
+ callbackInfo->interp = interp;
+ callbackInfo->multiple = 0;
+
+ /*
+ * Check for directory value, set to root if not specified; otherwise
+ * crashes with exception because of nil string parameter.
+ */
+
+ if (!directory) {
+ directory = @"/";
+ }
+ parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
+ if (haveParentOption && parent && ![parent attachedSheet]) {
+ parentIsKey = [parent isKeyWindow];
+ [panel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]];
+ [panel beginSheetModalForWindow:parent
+ completionHandler:^(NSInteger returnCode) {
+ [NSApp tkFilePanelDidEnd:panel
+ returnCode:returnCode
+ contextInfo:callbackInfo];
+ }];
+ modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:panel];
+ } else {
+ [panel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]];
+ modalReturnCode = [panel runModal];
+ [NSApp tkFilePanelDidEnd:panel returnCode:modalReturnCode
+ contextInfo:callbackInfo];
+ }
+ result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR;
+ if (parentIsKey) {
+ [parent makeKeyWindow];
+ }
+ end:
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkAboutDlg --
+ *
+ * Displays the default Tk About box.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkAboutDlg(void)
+{
+ NSImage *image;
+ NSString *path = [NSApp tkFrameworkImagePath: @"Tk.tiff"];
+
+ if (path) {
+ image = [[[NSImage alloc] initWithContentsOfFile:path] autorelease];
+ } else {
+ image = [NSApp applicationIconImage];
+ }
+
+ NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
+
+ [dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
+ [dateFormatter setDateFormat:@"Y"];
+
+ NSString *year = [dateFormatter stringFromDate:[NSDate date]];
+
+ [dateFormatter release];
+
+ /*
+ * This replaces the old about dialog with a standard alert that displays
+ * correctly on 10.14.
+ */
+
+ NSString *version = @"Tcl " TCL_PATCH_LEVEL " & Tk " TCL_PATCH_LEVEL;
+ NSString *url = @"www.tcl-lang.org";
+ NSTextView *credits = [[NSTextView alloc] initWithFrame:NSMakeRect(0,0,300,300)];
+ NSFont *font = [NSFont systemFontOfSize:[NSFont systemFontSize]];
+ NSDictionary *textAttributes = [NSDictionary dictionaryWithObject:font
+ forKey:NSFontAttributeName];
+
+ [credits insertText: [[NSAttributedString alloc]
+ initWithString:[NSString stringWithFormat: @"\n"
+ "Tcl and Tk are distributed under a modified BSD license: "
+ "www.tcl.tk/software/tcltk/license.html\n\n"
+ "%1$C 1987-%2$@ Tcl Core Team and Contributers.\n\n"
+ "%1$C 2011-%2$@ Kevin Walzer/WordTech Communications LLC.\n\n"
+ "%1$C 2014-%2$@ Marc Culler.\n\n"
+ "%1$C 2002-2012 Daniel A. Steffen.\n\n"
+ "%1$C 2001-2009 Apple Inc.\n\n"
+ "%1$C 2001-2002 Jim Ingham & Ian Reid\n\n"
+ "%1$C 1998-2000 Jim Ingham & Ray Johnson\n\n"
+ "%1$C 1998-2000 Scriptics Inc.\n\n"
+ "%1$C 1996-1997 Sun Microsystems Inc.", 0xA9, year]
+ attributes:textAttributes]
+ replacementRange:NSMakeRange(0,0)];
+ [credits setDrawsBackground:NO];
+ [credits setEditable:NO];
+
+ NSAlert *about = [[NSAlert alloc] init];
+
+ [[about window] setTitle:@"About Tcl & Tk"];
+ [about setMessageText: version];
+ [about setInformativeText:url];
+ about.accessoryView = credits;
+ [about runModal];
+ [about release];
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXStandardAboutPanelObjCmd --
+ *
+ * Implements the ::tk::mac::standardAboutPanel command.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * none
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkMacOSXStandardAboutPanelObjCmd(
+ ClientData clientData, /* Unused. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ if (objc > 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, NULL);
+ return TCL_ERROR;
+ }
+ TkAboutDlg();
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_MessageBoxObjCmd --
+ *
+ * Implements the tk_messageBox in native Mac OS X style.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * none
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_MessageBoxObjCmd(
+ ClientData clientData, /* Main window associated with interpreter. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Tk_Window tkwin = clientData;
+ char *str;
+ int i, result = TCL_ERROR, haveParentOption = 0;
+ int index, typeIndex, iconIndex, indexDefaultOption = 0;
+ int defaultNativeButtonIndex = 1; /* 1, 2, 3: right to left */
+ Tcl_Obj *cmdObj = NULL;
+ AlertCallbackInfo callbackInfoStruct, *callbackInfo = &callbackInfoStruct;
+ NSString *message, *title;
+ NSWindow *parent;
+ NSArray *buttons;
+ NSAlert *alert = [NSAlert new];
+ NSInteger modalReturnCode = 1;
+ BOOL parentIsKey = NO;
+
+ iconIndex = ICON_INFO;
+ typeIndex = TYPE_OK;
+ for (i = 1; i < objc; i += 2) {
+ if (Tcl_GetIndexFromObjStruct(interp, objv[i], alertOptionStrings,
+ sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
+ goto end;
+ }
+ if (i + 1 == objc) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "value for \"%s\" missing", Tcl_GetString(objv[i])));
+ Tcl_SetErrorCode(interp, "TK", "MSGBOX", "VALUE", NULL);
+ goto end;
+ }
+ switch (index) {
+ case ALERT_DEFAULT:
+ /*
+ * Need to postpone processing of this option until we are sure to
+ * know the '-type' as well.
+ */
+
+ indexDefaultOption = i;
+ break;
+
+ case ALERT_DETAIL:
+ message = [[NSString alloc] initWithUTF8String:
+ Tcl_GetString(objv[i + 1])];
+ [alert setInformativeText:message];
+ [message release];
+ break;
+
+ case ALERT_ICON:
+ if (Tcl_GetIndexFromObjStruct(interp, objv[i + 1], alertIconStrings,
+ sizeof(char *), "-icon value", TCL_EXACT, &iconIndex) != TCL_OK) {
+ goto end;
+ }
+ break;
+
+ case ALERT_MESSAGE:
+ message = [[NSString alloc] initWithUTF8String:
+ Tcl_GetString(objv[i + 1])];
+ [alert setMessageText:message];
+ [message release];
+ break;
+
+ case ALERT_PARENT:
+ str = Tcl_GetString(objv[i + 1]);
+ tkwin = Tk_NameToWindow(interp, str, tkwin);
+ if (!tkwin) {
+ goto end;
+ }
+ haveParentOption = 1;
+ break;
+
+ case ALERT_TITLE:
+ title = [[NSString alloc] initWithUTF8String:
+ Tcl_GetString(objv[i + 1])];
+ [[alert window] setTitle:title];
+ [title release];
+ break;
+
+ case ALERT_TYPE:
+ if (Tcl_GetIndexFromObjStruct(interp, objv[i + 1], alertTypeStrings,
+ sizeof(char *), "-type value", TCL_EXACT, &typeIndex) != TCL_OK) {
+ goto end;
+ }
+ break;
+ case ALERT_COMMAND:
+ cmdObj = objv[i+1];
+ break;
+ }
+ }
+ if (indexDefaultOption) {
+ /*
+ * Any '-default' option needs to know the '-type' option, which is
+ * why we do this here.
+ */
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[indexDefaultOption + 1],
+ alertButtonStrings, sizeof(char *), "-default value",
+ TCL_EXACT, &index) != TCL_OK) {
+ goto end;
+ }
+
+ /*
+ * Need to map from "ok" etc. to 1, 2, 3, right to left.
+ */
+
+ defaultNativeButtonIndex =
+ alertButtonIndexAndTypeToNativeButtonIndex[typeIndex][index];
+ if (!defaultNativeButtonIndex) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj("Illegal default option", -1));
+ Tcl_SetErrorCode(interp, "TK", "MSGBOX", "DEFAULT", NULL);
+ goto end;
+ }
+ }
+ [alert setIcon:[NSApp applicationIconImage]];
+ [alert setAlertStyle:alertStyles[iconIndex]];
+ i = 0;
+ while (i < 3 && alertButtonNames[typeIndex][i]) {
+ [alert addButtonWithTitle:(NSString*) alertButtonNames[typeIndex][i++]];
+ }
+ buttons = [alert buttons];
+ for (NSButton *b in buttons) {
+ NSString *ke = [b keyEquivalent];
+
+ if (([ke isEqualToString:@"\r"] || [ke isEqualToString:@"\033"]) &&
+ ![b keyEquivalentModifierMask]) {
+ [b setKeyEquivalent:@""];
+ }
+ }
+ [[buttons objectAtIndex: [buttons count]-1] setKeyEquivalent: @"\033"];
+ [[buttons objectAtIndex: defaultNativeButtonIndex-1]
+ setKeyEquivalent: @"\r"];
+ if (cmdObj) {
+ callbackInfo = ckalloc(sizeof(AlertCallbackInfo));
+ if (Tcl_IsShared(cmdObj)) {
+ cmdObj = Tcl_DuplicateObj(cmdObj);
+ }
+ Tcl_IncrRefCount(cmdObj);
+ }
+ callbackInfo->cmdObj = cmdObj;
+ callbackInfo->interp = interp;
+ callbackInfo->typeIndex = typeIndex;
+ parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
+ if (haveParentOption && parent && ![parent attachedSheet]) {
+ parentIsKey = [parent isKeyWindow];
+#if MAC_OS_X_VERSION_MIN_REQUIRED > 1090
+ [alert beginSheetModalForWindow:parent
+ completionHandler:^(NSModalResponse returnCode) {
+ [NSApp tkAlertDidEnd:alert
+ returnCode:returnCode
+ contextInfo:callbackInfo];
+ }];
+#else
+ [alert beginSheetModalForWindow:parent
+ modalDelegate:NSApp
+ didEndSelector:@selector(tkAlertDidEnd:returnCode:contextInfo:)
+ contextInfo:callbackInfo];
+#endif
+ modalReturnCode = cmdObj ? 0 :
+ [NSApp runModalForWindow:[alert window]];
+ } else {
+ modalReturnCode = [alert runModal];
+ [NSApp tkAlertDidEnd:alert returnCode:modalReturnCode
+ contextInfo:callbackInfo];
+ }
+ result = (modalReturnCode >= NSAlertFirstButtonReturn) ? TCL_OK : TCL_ERROR;
+ end:
+ [alert release];
+ if (parentIsKey) {
+ [parent makeKeyWindow];
+ }
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ */
+#pragma mark [tk fontchooser] implementation (TIP 324)
+/*
+ *----------------------------------------------------------------------
+ */
+
+#include "tkMacOSXEvent.h"
+#include "tkMacOSXFont.h"
+
+typedef struct FontchooserData {
+ Tcl_Obj *titleObj;
+ Tcl_Obj *cmdObj;
+ Tk_Window parent;
+} FontchooserData;
+
+enum FontchooserEvent {
+ FontchooserClosed,
+ FontchooserSelection
+};
+
+static void FontchooserEvent(int kind);
+static Tcl_Obj * FontchooserCget(FontchooserData *fcdPtr,
+ int optionIndex);
+static int FontchooserConfigureCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int FontchooserShowCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int FontchooserHideCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static void FontchooserParentEventHandler(ClientData clientData,
+ XEvent *eventPtr);
+static void DeleteFontchooserData(ClientData clientData,
+ Tcl_Interp *interp);
+
+MODULE_SCOPE const TkEnsemble tkFontchooserEnsemble[];
+const TkEnsemble tkFontchooserEnsemble[] = {
+ { "configure", FontchooserConfigureCmd, NULL },
+ { "show", FontchooserShowCmd, NULL },
+ { "hide", FontchooserHideCmd, NULL },
+ { NULL, NULL, NULL }
+};
+
+static Tcl_Interp *fontchooserInterp = NULL;
+static NSFont *fontPanelFont = nil;
+static NSMutableDictionary *fontPanelFontAttributes = nil;
+
+static const char *const fontchooserOptionStrings[] = {
+ "-parent", "-title", "-font", "-command",
+ "-visible", NULL
+};
+enum FontchooserOption {
+ FontchooserParent, FontchooserTitle, FontchooserFont, FontchooserCmd,
+ FontchooserVisible
+};
+
+@implementation TKApplication(TKFontPanel)
+
+- (void) changeFont: (id) sender
+{
+ NSFontManager *fm = [NSFontManager sharedFontManager];
+
+ if ([fm currentFontAction] == NSViaPanelFontAction) {
+ NSFont *font = [fm convertFont:fontPanelFont];
+
+ if (![fontPanelFont isEqual:font]) {
+ [fontPanelFont release];
+ fontPanelFont = [font retain];
+ FontchooserEvent(FontchooserSelection);
+ }
+ }
+}
+
+- (void) changeAttributes: (id) sender
+{
+ NSDictionary *attributes = [sender convertAttributes:
+ fontPanelFontAttributes];
+
+ if (![fontPanelFontAttributes isEqual:attributes]) {
+ [fontPanelFontAttributes setDictionary:attributes];
+ FontchooserEvent(FontchooserSelection);
+ }
+}
+
+- (NSUInteger) validModesForFontPanel: (NSFontPanel *) fontPanel
+{
+ return (NSFontPanelStandardModesMask & ~NSFontPanelAllEffectsModeMask) |
+ NSFontPanelUnderlineEffectModeMask |
+ NSFontPanelStrikethroughEffectModeMask;
+}
+
+- (void) windowDidOrderOffScreen: (NSNotification *) notification
+{
+#ifdef TK_MAC_DEBUG_NOTIFICATIONS
+ TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
+#endif
+ if ([[notification object] isEqual:[[NSFontManager sharedFontManager]
+ fontPanel:NO]]) {
+ FontchooserEvent(FontchooserClosed);
+ }
+}
+@end
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FontchooserEvent --
+ *
+ * This processes events generated by user interaction with the font
+ * panel.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Additional events may be place on the Tk event queue.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FontchooserEvent(
+ int kind)
+{
+ FontchooserData *fcdPtr;
+ Tcl_Obj *fontObj;
+
+ if (!fontchooserInterp) {
+ return;
+ }
+ fcdPtr = Tcl_GetAssocData(fontchooserInterp, "::tk::fontchooser", NULL);
+ switch (kind) {
+ case FontchooserClosed:
+ if (fcdPtr->parent != None) {
+ TkSendVirtualEvent(fcdPtr->parent, "TkFontchooserVisibility", NULL);
+ fontchooserInterp = NULL;
+ }
+ break;
+ case FontchooserSelection:
+ fontObj = TkMacOSXFontDescriptionForNSFontAndNSFontAttributes(
+ fontPanelFont, fontPanelFontAttributes);
+ if (fontObj) {
+ if (fcdPtr->cmdObj) {
+ int objc, result;
+ Tcl_Obj **objv, **tmpv;
+
+ result = Tcl_ListObjGetElements(fontchooserInterp,
+ fcdPtr->cmdObj, &objc, &objv);
+ if (result == TCL_OK) {
+ tmpv = ckalloc(sizeof(Tcl_Obj *) * (objc + 2));
+ memcpy(tmpv, objv, sizeof(Tcl_Obj *) * objc);
+ tmpv[objc] = fontObj;
+ TkBackgroundEvalObjv(fontchooserInterp, objc + 1, tmpv,
+ TCL_EVAL_GLOBAL);
+ ckfree(tmpv);
+ }
+ }
+ TkSendVirtualEvent(fcdPtr->parent, "TkFontchooserFontChanged", NULL);
+ }
+ break;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FontchooserCget --
+ *
+ * Helper for the FontchooserConfigure command to return the current value
+ * of any of the options (which may be NULL in the structure).
+ *
+ * Results:
+ * Tcl object of option value.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj *
+FontchooserCget(
+ FontchooserData *fcdPtr,
+ int optionIndex)
+{
+ Tcl_Obj *resObj = NULL;
+
+ switch(optionIndex) {
+ case FontchooserParent:
+ if (fcdPtr->parent != None) {
+ resObj = Tcl_NewStringObj(
+ ((TkWindow *) fcdPtr->parent)->pathName, -1);
+ } else {
+ resObj = Tcl_NewStringObj(".", 1);
+ }
+ break;
+ case FontchooserTitle:
+ if (fcdPtr->titleObj) {
+ resObj = fcdPtr->titleObj;
+ } else {
+ resObj = Tcl_NewObj();
+ }
+ break;
+ case FontchooserFont:
+ resObj = TkMacOSXFontDescriptionForNSFontAndNSFontAttributes(
+ fontPanelFont, fontPanelFontAttributes);
+ if (!resObj) {
+ resObj = Tcl_NewObj();
+ }
+ break;
+ case FontchooserCmd:
+ if (fcdPtr->cmdObj) {
+ resObj = fcdPtr->cmdObj;
+ } else {
+ resObj = Tcl_NewObj();
+ }
+ break;
+ case FontchooserVisible:
+ resObj = Tcl_NewBooleanObj([[[NSFontManager sharedFontManager]
+ fontPanel:NO] isVisible]);
+ break;
+ default:
+ resObj = Tcl_NewObj();
+ }
+ return resObj;
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * FontchooserConfigureCmd --
+ *
+ * Implementation of the 'tk fontchooser configure' ensemble command. See
+ * the user documentation for what it does.
+ *
+ * Results:
+ * See the user documentation.
+ *
+ * Side effects:
+ * Per-interp data structure may be modified
+ *
+ * ----------------------------------------------------------------------
+ */
+
+static int
+FontchooserConfigureCmd(
+ ClientData clientData, /* Main window */
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const objv[])
+{
+ Tk_Window tkwin = (Tk_Window)clientData;
+ FontchooserData *fcdPtr = Tcl_GetAssocData(interp, "::tk::fontchooser",
+ NULL);
+ int i, r = TCL_OK;
+
+ /*
+ * With no arguments we return all the options in a dict
+ */
+
+ if (objc == 1) {
+ Tcl_Obj *keyObj, *valueObj;
+ Tcl_Obj *dictObj = Tcl_NewDictObj();
+
+ for (i = 0; r == TCL_OK && fontchooserOptionStrings[i] != NULL; ++i) {
+ keyObj = Tcl_NewStringObj(fontchooserOptionStrings[i], -1);
+ valueObj = FontchooserCget(fcdPtr, i);
+ r = Tcl_DictObjPut(interp, dictObj, keyObj, valueObj);
+ }
+ if (r == TCL_OK) {
+ Tcl_SetObjResult(interp, dictObj);
+ }
+ return r;
+ }
+
+ for (i = 1; i < objc; i += 2) {
+ int optionIndex, len;
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[i], fontchooserOptionStrings,
+ sizeof(char *), "option", 0, &optionIndex) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (objc == 2) {
+ /*
+ * With one option and no arg, return the current value.
+ */
+
+ Tcl_SetObjResult(interp, FontchooserCget(fcdPtr, optionIndex));
+ return TCL_OK;
+ }
+ if (i + 1 == objc) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "value for \"%s\" missing", Tcl_GetString(objv[i])));
+ Tcl_SetErrorCode(interp, "TK", "FONTDIALOG", "VALUE", NULL);
+ return TCL_ERROR;
+ }
+ switch (optionIndex) {
+ case FontchooserVisible: {
+ const char *msg = "cannot change read-only option "
+ "\"-visible\": use the show or hide command";
+
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(msg, -1));
+ Tcl_SetErrorCode(interp, "TK", "FONTDIALOG", "READONLY", NULL);
+ return TCL_ERROR;
+ }
+ case FontchooserParent: {
+ Tk_Window parent = Tk_NameToWindow(interp,
+ Tcl_GetString(objv[i+1]), tkwin);
+
+ if (parent == None) {
+ return TCL_ERROR;
+ }
+ if (fcdPtr->parent) {
+ Tk_DeleteEventHandler(fcdPtr->parent, StructureNotifyMask,
+ FontchooserParentEventHandler, fcdPtr);
+ }
+ fcdPtr->parent = parent;
+ Tk_CreateEventHandler(fcdPtr->parent, StructureNotifyMask,
+ FontchooserParentEventHandler, fcdPtr);
+ break;
+ }
+ case FontchooserTitle:
+ if (fcdPtr->titleObj) {
+ Tcl_DecrRefCount(fcdPtr->titleObj);
+ }
+ Tcl_GetStringFromObj(objv[i+1], &len);
+ if (len) {
+ fcdPtr->titleObj = objv[i+1];
+ if (Tcl_IsShared(fcdPtr->titleObj)) {
+ fcdPtr->titleObj = Tcl_DuplicateObj(fcdPtr->titleObj);
+ }
+ Tcl_IncrRefCount(fcdPtr->titleObj);
+ } else {
+ fcdPtr->titleObj = NULL;
+ }
+ break;
+ case FontchooserFont:
+ Tcl_GetStringFromObj(objv[i+1], &len);
+ if (len) {
+ Tk_Font f = Tk_AllocFontFromObj(interp, tkwin, objv[i+1]);
+
+ if (!f) {
+ return TCL_ERROR;
+ }
+ [fontPanelFont autorelease];
+ fontPanelFont = [TkMacOSXNSFontForFont(f) retain];
+ [fontPanelFontAttributes setDictionary:
+ TkMacOSXNSFontAttributesForFont(f)];
+ [fontPanelFontAttributes removeObjectsForKeys:[NSArray
+ arrayWithObjects:NSFontAttributeName,
+ NSLigatureAttributeName, NSKernAttributeName, nil]];
+ Tk_FreeFont(f);
+ } else {
+ [fontPanelFont release];
+ fontPanelFont = nil;
+ [fontPanelFontAttributes removeAllObjects];
+ }
+
+ NSFontManager *fm = [NSFontManager sharedFontManager];
+ NSFontPanel *fp = [fm fontPanel:NO];
+
+ [fp setPanelFont:fontPanelFont isMultiple:NO];
+ [fm setSelectedFont:fontPanelFont isMultiple:NO];
+ [fm setSelectedAttributes:fontPanelFontAttributes
+ isMultiple:NO];
+ if ([fp isVisible]) {
+ TkSendVirtualEvent(fcdPtr->parent,
+ "TkFontchooserFontChanged", NULL);
+ }
+ break;
+ case FontchooserCmd:
+ if (fcdPtr->cmdObj) {
+ Tcl_DecrRefCount(fcdPtr->cmdObj);
+ }
+ Tcl_GetStringFromObj(objv[i+1], &len);
+ if (len) {
+ fcdPtr->cmdObj = objv[i+1];
+ if (Tcl_IsShared(fcdPtr->cmdObj)) {
+ fcdPtr->cmdObj = Tcl_DuplicateObj(fcdPtr->cmdObj);
+ }
+ Tcl_IncrRefCount(fcdPtr->cmdObj);
+ } else {
+ fcdPtr->cmdObj = NULL;
+ }
+ break;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * FontchooserShowCmd --
+ *
+ * Implements the 'tk fontchooser show' ensemble command. The per-interp
+ * configuration data for the dialog is held in an interp associated
+ * structure.
+ *
+ * Results:
+ * See the user documentation.
+ *
+ * Side effects:
+ * Font Panel may be shown.
+ *
+ * ----------------------------------------------------------------------
+ */
+
+static int
+FontchooserShowCmd(
+ ClientData clientData, /* Main window */
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const objv[])
+{
+ FontchooserData *fcdPtr = Tcl_GetAssocData(interp, "::tk::fontchooser",
+ NULL);
+
+ if (fcdPtr->parent == None) {
+ fcdPtr->parent = (Tk_Window) clientData;
+ Tk_CreateEventHandler(fcdPtr->parent, StructureNotifyMask,
+ FontchooserParentEventHandler, fcdPtr);
+ }
+
+ NSFontManager *fm = [NSFontManager sharedFontManager];
+ NSFontPanel *fp = [fm fontPanel:YES];
+
+ if ([fp delegate] != NSApp) {
+ [fp setDelegate:NSApp];
+ }
+ if (![fp isVisible]) {
+ [fm orderFrontFontPanel:NSApp];
+ TkSendVirtualEvent(fcdPtr->parent, "TkFontchooserVisibility", NULL);
+ }
+ fontchooserInterp = interp;
+
+ return TCL_OK;
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * FontchooserHideCmd --
+ *
+ * Implementation of the 'tk fontchooser hide' ensemble. See the user
+ * documentation for details.
+ *
+ * Results:
+ * See the user documentation.
+ *
+ * Side effects:
+ * Font Panel may be hidden.
+ *
+ * ----------------------------------------------------------------------
+ */
+
+static int
+FontchooserHideCmd(
+ ClientData clientData, /* Main window */
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const objv[])
+{
+ NSFontPanel *fp = [[NSFontManager sharedFontManager] fontPanel:NO];
+
+ if ([fp isVisible]) {
+ [fp orderOut:NSApp];
+ }
+ return TCL_OK;
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * FontchooserParentEventHandler --
+ *
+ * Event handler for StructureNotify events on the font chooser's parent
+ * window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Font chooser parent info is cleared and font panel is hidden.
+ *
+ * ----------------------------------------------------------------------
+ */
+
+static void
+FontchooserParentEventHandler(
+ ClientData clientData,
+ XEvent *eventPtr)
+{
+ FontchooserData *fcdPtr = clientData;
+
+ if (eventPtr->type == DestroyNotify) {
+ Tk_DeleteEventHandler(fcdPtr->parent, StructureNotifyMask,
+ FontchooserParentEventHandler, fcdPtr);
+ fcdPtr->parent = NULL;
+ FontchooserHideCmd(NULL, NULL, 0, NULL);
+ }
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * DeleteFontchooserData --
+ *
+ * Clean up the font chooser configuration data when the interp is
+ * destroyed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * per-interp configuration data is destroyed.
+ *
+ * ----------------------------------------------------------------------
+ */
+
+static void
+DeleteFontchooserData(
+ ClientData clientData,
+ Tcl_Interp *interp)
+{
+ FontchooserData *fcdPtr = clientData;
+
+ if (fcdPtr->titleObj) {
+ Tcl_DecrRefCount(fcdPtr->titleObj);
+ }
+ if (fcdPtr->cmdObj) {
+ Tcl_DecrRefCount(fcdPtr->cmdObj);
+ }
+ ckfree(fcdPtr);
+
+ if (fontchooserInterp == interp) {
+ fontchooserInterp = NULL;
+ }
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * TkInitFontchooser --
+ *
+ * Associate the font chooser configuration data with the Tcl interpreter.
+ * There is one font chooser per interp.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * per-interp configuration data is destroyed.
+ *
+ * ----------------------------------------------------------------------
+ */
+
+MODULE_SCOPE int
+TkInitFontchooser(
+ Tcl_Interp *interp,
+ ClientData clientData)
+{
+ FontchooserData *fcdPtr = ckalloc(sizeof(FontchooserData));
+
+ bzero(fcdPtr, sizeof(FontchooserData));
+ Tcl_SetAssocData(interp, "::tk::fontchooser", DeleteFontchooserData,
+ fcdPtr);
+ if (!fontPanelFontAttributes) {
+ fontPanelFontAttributes = [NSMutableDictionary new];
+ }
+ return TCL_OK;
+}
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXDraw.c b/tk8.6/macosx/tkMacOSXDraw.c
new file mode 100644
index 0000000..1793b64
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXDraw.c
@@ -0,0 +1,2078 @@
+/*
+ * tkMacOSXDraw.c --
+ *
+ * This file contains functions that perform drawing to Xlib windows. Most
+ * of the functions simply emulate Xlib functions.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ * Copyright 2001-2009, Apple Inc.
+ * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright 2014 Marc Culler.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkMacOSXPrivate.h"
+#include "tkMacOSXDebug.h"
+#include "tkButton.h"
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+#define GET_CGCONTEXT [[NSGraphicsContext currentContext] CGContext]
+#else
+#define GET_CGCONTEXT [[NSGraphicsContext currentContext] graphicsPort]
+#endif
+
+/*
+#ifdef TK_MAC_DEBUG
+#define TK_MAC_DEBUG_DRAWING
+#define TK_MAC_DEBUG_IMAGE_DRAWING
+#endif
+*/
+
+#define radians(d) ((d) * (M_PI/180.0))
+
+/*
+ * Non-antialiased CG drawing looks better and more like X11 drawing when using
+ * very fine lines, so decrease all linewidths by the following constant.
+ */
+#define NON_AA_CG_OFFSET .999
+
+static int cgAntiAliasLimit = 0;
+#define notAA(w) ((w) < cgAntiAliasLimit)
+
+static int useThemedToplevel = 0;
+static int useThemedFrame = 0;
+
+/*
+ * Prototypes for functions used only in this file.
+ */
+
+static void ClipToGC(Drawable d, GC gc, HIShapeRef *clipRgnPtr);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXInitCGDrawing --
+ *
+ * Initializes link vars that control CG drawing.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+MODULE_SCOPE int
+TkMacOSXInitCGDrawing(
+ Tcl_Interp *interp,
+ int enable,
+ int limit)
+{
+ static Boolean initialized = FALSE;
+
+ if (!initialized) {
+ initialized = TRUE;
+
+ if (Tcl_CreateNamespace(interp, "::tk::mac", NULL, NULL) == NULL) {
+ Tcl_ResetResult(interp);
+ }
+
+ if (Tcl_LinkVar(interp, "::tk::mac::CGAntialiasLimit",
+ (char *) &cgAntiAliasLimit, TCL_LINK_INT) != TCL_OK) {
+ Tcl_ResetResult(interp);
+ }
+ cgAntiAliasLimit = limit;
+
+ /*
+ * Piggy-back the themed drawing var init here.
+ */
+
+ if (Tcl_LinkVar(interp, "::tk::mac::useThemedToplevel",
+ (char *) &useThemedToplevel, TCL_LINK_BOOLEAN) != TCL_OK) {
+ Tcl_ResetResult(interp);
+ }
+ if (Tcl_LinkVar(interp, "::tk::mac::useThemedFrame",
+ (char *) &useThemedFrame, TCL_LINK_BOOLEAN) != TCL_OK) {
+ Tcl_ResetResult(interp);
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXBitmapRepFromDrawableRect
+ *
+ * Extract bitmap data from a MacOSX drawable as an NSBitmapImageRep.
+ *
+ * This is only used by XGetImage, which is never called. And this
+ * implementation does not work correctly. Originally it relied on
+ * [NSBitmapImageRep initWithFocusedViewRect:view_rect] which was
+ * deprecated by Apple in OSX 10.14 and also required the use of other
+ * deprecated functions such as [NSView lockFocus]. Apple's suggested
+ * replacement is [NSView cacheDisplayInRect: toBitmapImageRep:] and that
+ * is what is being used here. However, that method only works when the
+ * view has a valid CGContext, and a view is only guaranteed to have a
+ * valid context during a call to [NSView drawRect]. To further complicate
+ * matters, cacheDisplayInRect calls [NSView drawRect]. Essentially it is
+ * asking the view to draw a subrectangle of itself into a special
+ * graphics context which is linked to the BitmapImageRep. But our
+ * implementation of [NSView drawRect] does not allow recursive calls. If
+ * called recursively it returns immediately without doing any drawing.
+ * So the bottom line is that this function either returns a NULL pointer
+ * or a black image. To make it useful would require a significant amount
+ * of rewriting of the drawRect method. Perhaps the next release of OSX
+ * will include some more helpful ways of doing this.
+ *
+ * Results:
+ * Returns an NSBitmapRep representing the image of the given rectangle of
+ * the given drawable. This object is retained. The caller is responsible
+ * for releasing it.
+ *
+ * NOTE: The x,y coordinates should be relative to a coordinate system
+ * with origin at the top left, as used by XImage and CGImage, not bottom
+ * left as used by NSView.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+NSBitmapImageRep *
+TkMacOSXBitmapRepFromDrawableRect(
+ Drawable drawable,
+ int x,
+ int y,
+ unsigned int width,
+ unsigned int height)
+{
+ MacDrawable *mac_drawable = (MacDrawable *) drawable;
+ CGContextRef cg_context = NULL;
+ CGImageRef cg_image = NULL, sub_cg_image = NULL;
+ NSBitmapImageRep *bitmap_rep = NULL;
+ NSView *view = NULL;
+ if (mac_drawable->flags & TK_IS_PIXMAP) {
+ /*
+ * This MacDrawable is a bitmap, so its view is NULL.
+ */
+
+ CGRect image_rect = CGRectMake(x, y, width, height);
+
+ cg_context = TkMacOSXGetCGContextForDrawable(drawable);
+ cg_image = CGBitmapContextCreateImage((CGContextRef) cg_context);
+ sub_cg_image = CGImageCreateWithImageInRect(cg_image, image_rect);
+ if (sub_cg_image) {
+ bitmap_rep = [NSBitmapImageRep alloc];
+ [bitmap_rep initWithCGImage:sub_cg_image];
+ }
+ if (cg_image) {
+ CGImageRelease(cg_image);
+ }
+ } else if ((view = TkMacOSXDrawableView(mac_drawable)) != NULL) {
+ /*
+ * Convert Tk top-left to NSView bottom-left coordinates.
+ */
+
+ int view_height = [view bounds].size.height;
+ NSRect view_rect = NSMakeRect(x + mac_drawable->xOff,
+ view_height - height - y - mac_drawable->yOff,
+ width, height);
+
+ /*
+ * Attempt to copy from the view to a bitmapImageRep. If the view does
+ * not have a valid CGContext, doing this will silently corrupt memory
+ * and make a big mess. So, in that case, we mark the view as needing
+ * display and return NULL.
+ */
+
+ if (view == [NSView focusView]) {
+ bitmap_rep = [view bitmapImageRepForCachingDisplayInRect: view_rect];
+ [bitmap_rep retain];
+ [view cacheDisplayInRect:view_rect toBitmapImageRep:bitmap_rep];
+ } else {
+ TkMacOSXDbgMsg("No CGContext - cannot copy from screen to bitmap.");
+ [view setNeedsDisplay:YES];
+ return NULL;
+ }
+ } else {
+ TkMacOSXDbgMsg("Invalid source drawable");
+ }
+ return bitmap_rep;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XCopyArea --
+ *
+ * Copies data from one drawable to another.
+ *
+ * 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, /* that will be copied. */
+ unsigned int height,
+ int dest_x, /* Dest X & Y on dest rect. */
+ int dest_y)
+{
+ TkMacOSXDrawingContext dc;
+ MacDrawable *srcDraw = (MacDrawable *) src;
+ NSBitmapImageRep *bitmap_rep = NULL;
+ CGImageRef img = NULL;
+ CGRect bounds, srcRect, dstRect;
+
+ display->request++;
+ if (!width || !height) {
+ return;
+ }
+
+ if (!TkMacOSXSetupDrawingContext(dst, gc, 1, &dc)) {
+ TkMacOSXDbgMsg("Failed to setup drawing context.");
+ return;
+ }
+
+ if (!dc.context) {
+ TkMacOSXDbgMsg("Invalid destination drawable - no context.");
+ return;
+ }
+
+ if (srcDraw->flags & TK_IS_PIXMAP) {
+ img = TkMacOSXCreateCGImageWithDrawable(src);
+ } else if (TkMacOSXDrawableWindow(src)) {
+ bitmap_rep = TkMacOSXBitmapRepFromDrawableRect(src,
+ src_x, src_y, width, height);
+ if (bitmap_rep) {
+ img = [bitmap_rep CGImage];
+ }
+ } else {
+ TkMacOSXDbgMsg("Invalid source drawable - neither window nor pixmap.");
+ }
+
+ if (img) {
+ bounds = CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height);
+ srcRect = CGRectMake(src_x, src_y, width, height);
+ dstRect = CGRectMake(dest_x, dest_y, width, height);
+ TkMacOSXDrawCGImage(dst, gc, dc.context, img,
+ gc->foreground, gc->background, bounds, srcRect, dstRect);
+ CFRelease(img);
+ } else {
+ TkMacOSXDbgMsg("Failed to construct CGImage.");
+ }
+
+ TkMacOSXRestoreDrawingContext(&dc);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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, /* GC to use. */
+ int src_x, /* X & Y, width & height */
+ int src_y, /* define the source rectangle */
+ unsigned int width, /* that will be copied. */
+ unsigned int height,
+ int dest_x, /* Dest X & Y on dest rect. */
+ int dest_y,
+ unsigned long plane) /* Which plane to copy. */
+{
+ TkMacOSXDrawingContext dc;
+ MacDrawable *srcDraw = (MacDrawable *) src;
+ MacDrawable *dstDraw = (MacDrawable *) dst;
+ CGRect bounds, srcRect, dstRect;
+ display->request++;
+ if (!width || !height) {
+ /* TkMacOSXDbgMsg("Drawing of empty area requested"); */
+ return;
+ }
+ if (plane != 1) {
+ Tcl_Panic("Unexpected plane specified for XCopyPlane");
+ }
+ if (srcDraw->flags & TK_IS_PIXMAP) {
+ if (!TkMacOSXSetupDrawingContext(dst, gc, 1, &dc)) {
+ return;
+ }
+
+ CGContextRef context = dc.context;
+
+ if (context) {
+ CGImageRef img = TkMacOSXCreateCGImageWithDrawable(src);
+
+ if (img) {
+ TkpClipMask *clipPtr = (TkpClipMask *) gc->clip_mask;
+ unsigned long imageBackground = gc->background;
+
+ if (clipPtr && clipPtr->type == TKP_CLIP_PIXMAP) {
+ srcRect = CGRectMake(src_x, src_y, width, height);
+ CGImageRef mask = TkMacOSXCreateCGImageWithDrawable(
+ clipPtr->value.pixmap);
+ CGImageRef submask = CGImageCreateWithImageInRect(
+ img, srcRect);
+ CGRect rect = CGRectMake(dest_x, dest_y, width, height);
+
+ rect = CGRectOffset(rect, dstDraw->xOff, dstDraw->yOff);
+ CGContextSaveGState(context);
+
+ /*
+ * Move the origin of the destination to top left.
+ */
+
+ CGContextTranslateCTM(context,
+ 0, rect.origin.y + CGRectGetMaxY(rect));
+ CGContextScaleCTM(context, 1, -1);
+
+ /*
+ * Fill with the background color, clipping to the mask.
+ */
+
+ CGContextClipToMask(context, rect, submask);
+ TkMacOSXSetColorInContext(gc, gc->background, dc.context);
+ CGContextFillRect(context, rect);
+
+ /*
+ * Fill with the foreground color, clipping to the
+ * intersection of img and mask.
+ */
+
+ CGImageRef subimage = CGImageCreateWithImageInRect(
+ img, srcRect);
+ CGContextClipToMask(context, rect, subimage);
+ TkMacOSXSetColorInContext(gc, gc->foreground, context);
+ CGContextFillRect(context, rect);
+ CGContextRestoreGState(context);
+ CGImageRelease(img);
+ CGImageRelease(mask);
+ CGImageRelease(submask);
+ CGImageRelease(subimage);
+ } else {
+ bounds = CGRectMake(0, 0,
+ srcDraw->size.width, srcDraw->size.height);
+ srcRect = CGRectMake(src_x, src_y, width, height);
+ dstRect = CGRectMake(dest_x, dest_y, width, height);
+ TkMacOSXDrawCGImage(dst, gc, dc.context, img,
+ gc->foreground, imageBackground, bounds,
+ srcRect, dstRect);
+ CGImageRelease(img);
+ }
+ } else {
+ /* no image */
+ TkMacOSXDbgMsg("Invalid source drawable");
+ }
+ } else {
+ TkMacOSXDbgMsg("Invalid destination drawable - "
+ "could not get a bitmap context.");
+ }
+ TkMacOSXRestoreDrawingContext(&dc);
+ } else {
+ /*
+ * Source drawable is a Window, not a Pixmap.
+ */
+
+ XCopyArea(display, src, dst, gc, src_x, src_y, width, height,
+ dest_x, dest_y);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXCreateCGImageWithDrawable --
+ *
+ * Create a CGImage from the given Drawable.
+ *
+ * Results:
+ * CGImage, release after use.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+CGImageRef
+TkMacOSXCreateCGImageWithDrawable(
+ Drawable drawable)
+{
+ CGImageRef img = NULL;
+ CGContextRef context = TkMacOSXGetCGContextForDrawable(drawable);
+
+ if (context) {
+ img = CGBitmapContextCreateImage(context);
+ }
+ return img;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CreateNSImageWithPixmap --
+ *
+ * Create NSImage for Pixmap.
+ *
+ * Results:
+ * NSImage.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static NSImage *
+CreateNSImageWithPixmap(
+ Pixmap pixmap,
+ int width,
+ int height)
+{
+ CGImageRef cgImage;
+ NSImage *nsImage;
+ NSBitmapImageRep *bitmapImageRep;
+
+ cgImage = TkMacOSXCreateCGImageWithDrawable(pixmap);
+ nsImage = [[NSImage alloc] initWithSize:NSMakeSize(width, height)];
+ bitmapImageRep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage];
+ [nsImage addRepresentation:bitmapImageRep];
+ [bitmapImageRep release];
+ CFRelease(cgImage);
+
+ return nsImage;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXGetNSImageWithTkImage --
+ *
+ * Get autoreleased NSImage for Tk_Image.
+ *
+ * Results:
+ * NSImage.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+NSImage *
+TkMacOSXGetNSImageWithTkImage(
+ Display *display,
+ Tk_Image image,
+ int width,
+ int height)
+{
+ Pixmap pixmap = Tk_GetPixmap(display, None, width, height, 0);
+ NSImage *nsImage;
+
+ Tk_RedrawImage(image, 0, 0, width, height, pixmap, 0, 0);
+ nsImage = CreateNSImageWithPixmap(pixmap, width, height);
+ Tk_FreePixmap(display, pixmap);
+
+ return [nsImage autorelease];
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXGetNSImageWithBitmap --
+ *
+ * Get autoreleased NSImage for Bitmap.
+ *
+ * Results:
+ * NSImage.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+NSImage *
+TkMacOSXGetNSImageWithBitmap(
+ Display *display,
+ Pixmap bitmap,
+ GC gc,
+ int width,
+ int height)
+{
+ Pixmap pixmap = Tk_GetPixmap(display, None, width, height, 0);
+ NSImage *nsImage;
+
+ unsigned long origBackground = gc->background;
+
+ gc->background = TRANSPARENT_PIXEL << 24;
+ XSetClipOrigin(display, gc, 0, 0);
+ XCopyPlane(display, bitmap, pixmap, gc, 0, 0, width, height, 0, 0, 1);
+ gc->background = origBackground;
+ nsImage = CreateNSImageWithPixmap(pixmap, width, height);
+ Tk_FreePixmap(display, pixmap);
+
+ return [nsImage autorelease];
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXGetCGContextForDrawable --
+ *
+ * Get CGContext for given Drawable, creating one if necessary.
+ *
+ * Results:
+ * CGContext.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+CGContextRef
+TkMacOSXGetCGContextForDrawable(
+ Drawable drawable)
+{
+ MacDrawable *macDraw = (MacDrawable *) drawable;
+
+ if (macDraw && (macDraw->flags & TK_IS_PIXMAP) && !macDraw->context) {
+ const size_t bitsPerComponent = 8;
+ size_t bitsPerPixel, bytesPerRow, len;
+ CGColorSpaceRef colorspace = NULL;
+ CGBitmapInfo bitmapInfo =
+#ifdef __LITTLE_ENDIAN__
+ kCGBitmapByteOrder32Host;
+#else
+ kCGBitmapByteOrderDefault;
+#endif
+ char *data;
+ CGRect bounds = CGRectMake(0, 0,
+ macDraw->size.width, macDraw->size.height);
+
+ if (macDraw->flags & TK_IS_BW_PIXMAP) {
+ bitsPerPixel = 8;
+ bitmapInfo = (CGBitmapInfo) kCGImageAlphaOnly;
+ } else {
+ colorspace = CGColorSpaceCreateDeviceRGB();
+ bitsPerPixel = 32;
+ bitmapInfo |= kCGImageAlphaPremultipliedFirst;
+ }
+ bytesPerRow = ((size_t)
+ macDraw->size.width * bitsPerPixel + 127) >> 3 & ~15;
+ len = macDraw->size.height * bytesPerRow;
+ data = ckalloc(len);
+ bzero(data, len);
+ macDraw->context = CGBitmapContextCreate(data, macDraw->size.width,
+ macDraw->size.height, bitsPerComponent, bytesPerRow,
+ colorspace, bitmapInfo);
+ if (macDraw->context) {
+ CGContextClearRect(macDraw->context, bounds);
+ }
+ if (colorspace) {
+ CFRelease(colorspace);
+ }
+ }
+
+ return (macDraw ? macDraw->context : NULL);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXDrawCGImage --
+ *
+ * Draw CG image into drawable.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXDrawCGImage(
+ Drawable d,
+ GC gc,
+ CGContextRef context,
+ CGImageRef image,
+ unsigned long imageForeground,
+ unsigned long imageBackground,
+ CGRect imageBounds,
+ CGRect srcBounds,
+ CGRect dstBounds)
+{
+ MacDrawable *macDraw = (MacDrawable *) d;
+
+ if (macDraw && context && image) {
+ CGImageRef subImage = NULL;
+
+ if (!CGRectEqualToRect(imageBounds, srcBounds)) {
+ if (!CGRectContainsRect(imageBounds, srcBounds)) {
+ TkMacOSXDbgMsg("Mismatch of sub CGImage bounds");
+ }
+ subImage = CGImageCreateWithImageInRect(image, CGRectOffset(
+ srcBounds, -imageBounds.origin.x, -imageBounds.origin.y));
+ if (subImage) {
+ image = subImage;
+ }
+ }
+ dstBounds = CGRectOffset(dstBounds, macDraw->xOff, macDraw->yOff);
+ if (CGImageIsMask(image)) {
+ if (macDraw->flags & TK_IS_BW_PIXMAP) {
+ /*
+ * Set fill color to black; background comes from the context,
+ * or is transparent.
+ */
+
+ if (imageBackground != TRANSPARENT_PIXEL << 24) {
+ CGContextClearRect(context, dstBounds);
+ }
+ CGContextSetRGBFillColor(context, 0.0, 0.0, 0.0, 1.0);
+ } else {
+ if (imageBackground != TRANSPARENT_PIXEL << 24) {
+ TkMacOSXSetColorInContext(gc, imageBackground, context);
+ CGContextFillRect(context, dstBounds);
+ }
+ TkMacOSXSetColorInContext(gc, imageForeground, context);
+ }
+ }
+
+#ifdef TK_MAC_DEBUG_IMAGE_DRAWING
+ CGContextSaveGState(context);
+ CGContextSetLineWidth(context, 1.0);
+ CGContextSetRGBStrokeColor(context, 0, 0, 0, 0.1);
+ CGContextSetRGBFillColor(context, 0, 1, 0, 0.1);
+ CGContextFillRect(context, dstBounds);
+ CGContextStrokeRect(context, dstBounds);
+
+ CGPoint p[4] = {dstBounds.origin,
+ CGPointMake(CGRectGetMaxX(dstBounds), CGRectGetMaxY(dstBounds)),
+ CGPointMake(CGRectGetMinX(dstBounds), CGRectGetMaxY(dstBounds)),
+ CGPointMake(CGRectGetMaxX(dstBounds), CGRectGetMinY(dstBounds))
+ };
+
+ CGContextStrokeLineSegments(context, p, 4);
+ CGContextRestoreGState(context);
+ TkMacOSXDbgMsg("Drawing CGImage at (x=%f, y=%f), (w=%f, h=%f)",
+ dstBounds.origin.x, dstBounds.origin.y,
+ dstBounds.size.width, dstBounds.size.height);
+#else /* TK_MAC_DEBUG_IMAGE_DRAWING */
+ CGContextSaveGState(context);
+ CGContextTranslateCTM(context, 0, dstBounds.origin.y + CGRectGetMaxY(dstBounds));
+ CGContextScaleCTM(context, 1, -1);
+ CGContextDrawImage(context, dstBounds, image);
+ CGContextRestoreGState(context);
+#endif /* TK_MAC_DEBUG_IMAGE_DRAWING */
+ if (subImage) {
+ CFRelease(subImage);
+ }
+ } else {
+ TkMacOSXDbgMsg("Drawing of empty CGImage requested");
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XDrawLines --
+ *
+ * Draw connected lines.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Renders a series of connected lines.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+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;
+ TkMacOSXDrawingContext dc;
+ int i, lw = gc->line_width;
+
+ if (npoints < 2) {
+ return BadValue;
+ }
+
+ display->request++;
+ if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
+ return BadDrawable;
+ }
+ if (dc.context) {
+ double prevx, prevy;
+ double o = (lw % 2) ? .5 : 0;
+
+ CGContextBeginPath(dc.context);
+ prevx = macWin->xOff + points[0].x + o;
+ prevy = macWin->yOff + points[0].y + o;
+ CGContextMoveToPoint(dc.context, prevx, prevy);
+ for (i = 1; i < npoints; i++) {
+ if (mode == CoordModeOrigin) {
+ CGContextAddLineToPoint(dc.context,
+ macWin->xOff + points[i].x + o,
+ macWin->yOff + points[i].y + o);
+ } else {
+ prevx += points[i].x;
+ prevy += points[i].y;
+ CGContextAddLineToPoint(dc.context, prevx, prevy);
+ }
+ }
+
+ /*
+ * In the case of closed polylines, the first and last points are the
+ * same. We want miter or bevel join be rendered also at this point,
+ * this needs telling CoreGraphics that the path is closed.
+ */
+
+ if ((points[0].x == points[npoints-1].x) &&
+ (points[0].y == points[npoints-1].y)) {
+ CGContextClosePath(dc.context);
+ }
+ CGContextStrokePath(dc.context);
+ }
+ TkMacOSXRestoreDrawingContext(&dc);
+ return Success;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XDrawSegments --
+ *
+ * Draw unconnected lines.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Renders a series of unconnected lines.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+XDrawSegments(
+ Display *display,
+ Drawable d,
+ GC gc,
+ XSegment *segments,
+ int nsegments)
+{
+ MacDrawable *macWin = (MacDrawable *) d;
+ TkMacOSXDrawingContext dc;
+ int i, lw = gc->line_width;
+
+ display->request++;
+ if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
+ return BadDrawable;
+ }
+ if (dc.context) {
+ double o = (lw % 2) ? .5 : 0;
+
+ for (i = 0; i < nsegments; i++) {
+ CGContextBeginPath(dc.context);
+ CGContextMoveToPoint(dc.context,
+ macWin->xOff + segments[i].x1 + o,
+ macWin->yOff + segments[i].y1 + o);
+ CGContextAddLineToPoint(dc.context,
+ macWin->xOff + segments[i].x2 + o,
+ macWin->yOff + segments[i].y2 + o);
+ CGContextStrokePath(dc.context);
+ }
+ }
+ TkMacOSXRestoreDrawingContext(&dc);
+ return Success;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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;
+ TkMacOSXDrawingContext dc;
+ int i;
+
+ display->request++;
+ if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
+ return;
+ }
+ if (dc.context) {
+ double prevx, prevy;
+ double o = (gc->line_width % 2) ? .5 : 0;
+
+ CGContextBeginPath(dc.context);
+ prevx = macWin->xOff + points[0].x + o;
+ prevy = macWin->yOff + points[0].y + o;
+ CGContextMoveToPoint(dc.context, prevx, prevy);
+ for (i = 1; i < npoints; i++) {
+ if (mode == CoordModeOrigin) {
+ CGContextAddLineToPoint(dc.context,
+ macWin->xOff + points[i].x + o,
+ macWin->yOff + points[i].y + o);
+ } else {
+ prevx += points[i].x;
+ prevy += points[i].y;
+ CGContextAddLineToPoint(dc.context, prevx, prevy);
+ }
+ }
+ CGContextEOFillPath(dc.context);
+ }
+ TkMacOSXRestoreDrawingContext(&dc);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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, int y, /* Upper left corner. */
+ unsigned int width, /* Width & height of rect. */
+ unsigned int height)
+{
+ MacDrawable *macWin = (MacDrawable *) d;
+ TkMacOSXDrawingContext dc;
+ int lw = gc->line_width;
+
+ if (width == 0 || height == 0) {
+ return;
+ }
+
+ display->request++;
+ if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
+ return;
+ }
+ if (dc.context) {
+ CGRect rect;
+ double o = (lw % 2) ? .5 : 0;
+
+ rect = CGRectMake(
+ macWin->xOff + x + o, macWin->yOff + y + o,
+ width, height);
+ CGContextStrokeRect(dc.context, rect);
+ }
+ TkMacOSXRestoreDrawingContext(&dc);
+}
+
+#ifdef TK_MACOSXDRAW_UNUSED
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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;
+ TkMacOSXDrawingContext dc;
+ XRectangle * rectPtr;
+ int i, lw = gc->line_width;
+
+ display->request++;
+ if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
+ return;
+ }
+ if (dc.context) {
+ CGRect rect;
+ double o = (lw % 2) ? .5 : 0;
+
+ for (i = 0, rectPtr = rectArr; i < nRects; i++, rectPtr++) {
+ if (rectPtr->width == 0 || rectPtr->height == 0) {
+ continue;
+ }
+ rect = CGRectMake(
+ macWin->xOff + rectPtr->x + o,
+ macWin->yOff + rectPtr->y + o,
+ rectPtr->width, rectPtr->height);
+ CGContextStrokeRect(dc.context, rect);
+ }
+ }
+ TkMacOSXRestoreDrawingContext(&dc);
+}
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XFillRectangles --
+ *
+ * Fill multiple rectangular areas in the given drawable.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Draws onto the specified drawable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+XFillRectangles(
+ Display *display, /* Display. */
+ Drawable d, /* Draw on this. */
+ GC gc, /* Use this GC. */
+ XRectangle *rectangles, /* Rectangle array. */
+ int n_rectangles) /* Number of rectangles. */
+{
+ MacDrawable *macWin = (MacDrawable *) d;
+ TkMacOSXDrawingContext dc;
+ XRectangle * rectPtr;
+ int i;
+
+ display->request++;
+ if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
+ return BadDrawable;
+ }
+ if (dc.context) {
+ CGRect rect;
+
+ for (i = 0, rectPtr = rectangles; i < n_rectangles; i++, rectPtr++) {
+ if (rectPtr->width == 0 || rectPtr->height == 0) {
+ continue;
+ }
+ rect = CGRectMake(
+ macWin->xOff + rectPtr->x,
+ macWin->yOff + rectPtr->y,
+ rectPtr->width, rectPtr->height);
+ CGContextFillRect(dc.context, rect);
+ }
+ }
+ TkMacOSXRestoreDrawingContext(&dc);
+ return Success;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXDrawSolidBorder --
+ *
+ * Draws a border rectangle of specified thickness inside the bounding
+ * rectangle of a Tk Window. The border rectangle can be inset within the
+ * bounding rectangle. For a highlight border the inset should be 0, but
+ * for a solid border around the actual window the inset should equal the
+ * thickness of the highlight border. The color of the border rectangle
+ * is the foreground color of the graphics context passed to the function.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Draws a rectangular border inside the bounding rectangle of a window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+MODULE_SCOPE void
+TkMacOSXDrawSolidBorder(
+ Tk_Window tkwin,
+ GC gc,
+ int inset,
+ int thickness)
+{
+ Drawable d = Tk_WindowId(tkwin);
+ TkMacOSXDrawingContext dc;
+ CGRect outerRect, innerRect;
+
+ if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
+ return;
+ }
+ if (dc.context) {
+ outerRect = CGRectMake(Tk_X(tkwin), Tk_Y(tkwin),
+ Tk_Width(tkwin), Tk_Height(tkwin));
+ outerRect = CGRectInset(outerRect, inset, inset);
+ innerRect = CGRectInset(outerRect, thickness, thickness);
+ CGContextBeginPath(dc.context);
+ CGContextAddRect(dc.context, outerRect);
+ CGContextAddRect(dc.context, innerRect);
+ CGContextEOFillPath(dc.context);
+ }
+ TkMacOSXRestoreDrawingContext(&dc);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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, int y, /* Upper left of bounding rect. */
+ unsigned int width, /* Width & height. */
+ unsigned int height,
+ int angle1, /* Staring angle of arc. */
+ int angle2) /* Extent of arc. */
+{
+ MacDrawable *macWin = (MacDrawable *) d;
+ TkMacOSXDrawingContext dc;
+ int lw = gc->line_width;
+
+ if (width == 0 || height == 0 || angle2 == 0) {
+ return;
+ }
+
+ display->request++;
+ if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
+ return;
+ }
+ if (dc.context) {
+ CGRect rect;
+ double o = (lw % 2) ? .5 : 0;
+
+ rect = CGRectMake(
+ macWin->xOff + x + o,
+ macWin->yOff + y + o,
+ width, height);
+ if (angle1 == 0 && angle2 == 23040) {
+ CGContextStrokeEllipseInRect(dc.context, rect);
+ } else {
+ CGMutablePathRef p = CGPathCreateMutable();
+ CGAffineTransform t = CGAffineTransformIdentity;
+ CGPoint c = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
+ double w = CGRectGetWidth(rect);
+
+ if (width != height) {
+ t = CGAffineTransformMakeScale(1.0, CGRectGetHeight(rect)/w);
+ c = CGPointApplyAffineTransform(c, CGAffineTransformInvert(t));
+ }
+ CGPathAddArc(p, &t, c.x, c.y, w/2, radians(-angle1/64.0),
+ radians(-(angle1 + angle2)/64.0), angle2 > 0);
+ CGContextAddPath(dc.context, p);
+ CGPathRelease(p);
+ CGContextStrokePath(dc.context);
+ }
+ }
+ TkMacOSXRestoreDrawingContext(&dc);
+}
+
+#ifdef TK_MACOSXDRAW_UNUSED
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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;
+ TkMacOSXDrawingContext dc;
+ XArc *arcPtr;
+ int i, lw = gc->line_width;
+
+ display->request++;
+ if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
+ return;
+ }
+ if (dc.context) {
+ CGRect rect;
+ double o = (lw % 2) ? .5 : 0;
+
+ for (i=0, arcPtr = arcArr; i < nArcs; i++, arcPtr++) {
+ if (arcPtr->width == 0 || arcPtr->height == 0
+ || arcPtr->angle2 == 0) {
+ continue;
+ }
+ rect = CGRectMake(
+ macWin->xOff + arcPtr->x + o,
+ macWin->yOff + arcPtr->y + o,
+ arcPtr->width, arcPtr->height);
+
+ if (arcPtr->angle1 == 0 && arcPtr->angle2 == 23040) {
+ CGContextStrokeEllipseInRect(dc.context, rect);
+ } else {
+ CGMutablePathRef p = CGPathCreateMutable();
+ CGAffineTransform t = CGAffineTransformIdentity;
+ CGPoint c = CGPointMake(CGRectGetMidX(rect),
+ CGRectGetMidY(rect));
+ double w = CGRectGetWidth(rect);
+
+ if (arcPtr->width != arcPtr->height) {
+ t = CGAffineTransformMakeScale(1, CGRectGetHeight(rect)/w);
+ c = CGPointApplyAffineTransform(c,
+ CGAffineTransformInvert(t));
+ }
+ CGPathAddArc(p, &t, c.x, c.y, w/2,
+ radians(-arcPtr->angle1/64.0),
+ radians(-(arcPtr->angle1 + arcPtr->angle2)/64.0),
+ arcPtr->angle2 > 0);
+ CGContextAddPath(dc.context, p);
+ CGPathRelease(p);
+ CGContextStrokePath(dc.context);
+ }
+ }
+ }
+ TkMacOSXRestoreDrawingContext(&dc);
+}
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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, int y, /* Upper left of bounding rect. */
+ unsigned int width, /* Width & height. */
+ unsigned int height,
+ int angle1, /* Staring angle of arc. */
+ int angle2) /* Extent of arc. */
+{
+ MacDrawable *macWin = (MacDrawable *) d;
+ TkMacOSXDrawingContext dc;
+ int lw = gc->line_width;
+
+ if (width == 0 || height == 0 || angle2 == 0) {
+ return;
+ }
+
+ display->request++;
+ if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
+ return;
+ }
+ if (dc.context) {
+ CGRect rect;
+ double o = (lw % 2) ? .5 : 0, u = 0;
+
+ if (notAA(lw)) {
+ o += NON_AA_CG_OFFSET/2;
+ u += NON_AA_CG_OFFSET;
+ }
+ rect = CGRectMake(
+ macWin->xOff + x + o,
+ macWin->yOff + y + o,
+ width - u, height - u);
+
+ if (angle1 == 0 && angle2 == 23040) {
+ CGContextFillEllipseInRect(dc.context, rect);
+ } else {
+ CGMutablePathRef p = CGPathCreateMutable();
+ CGAffineTransform t = CGAffineTransformIdentity;
+ CGPoint c = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
+ double w = CGRectGetWidth(rect);
+
+ if (width != height) {
+ t = CGAffineTransformMakeScale(1, CGRectGetHeight(rect)/w);
+ c = CGPointApplyAffineTransform(c, CGAffineTransformInvert(t));
+ }
+ if (gc->arc_mode == ArcPieSlice) {
+ CGPathMoveToPoint(p, &t, c.x, c.y);
+ }
+ CGPathAddArc(p, &t, c.x, c.y, w/2, radians(-angle1/64.0),
+ radians(-(angle1 + angle2)/64.0), angle2 > 0);
+ CGPathCloseSubpath(p);
+ CGContextAddPath(dc.context, p);
+ CGPathRelease(p);
+ CGContextFillPath(dc.context);
+ }
+ }
+ TkMacOSXRestoreDrawingContext(&dc);
+}
+
+#ifdef TK_MACOSXDRAW_UNUSED
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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;
+ TkMacOSXDrawingContext dc;
+ XArc * arcPtr;
+ int i, lw = gc->line_width;
+
+ display->request++;
+ if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
+ return;
+ }
+ if (dc.context) {
+ CGRect rect;
+ double o = (lw % 2) ? .5 : 0, u = 0;
+
+ if (notAA(lw)) {
+ o += NON_AA_CG_OFFSET/2;
+ u += NON_AA_CG_OFFSET;
+ }
+ for (i = 0, arcPtr = arcArr; i < nArcs; i++, arcPtr++) {
+ if (arcPtr->width == 0 || arcPtr->height == 0
+ || arcPtr->angle2 == 0) {
+ continue;
+ }
+ rect = CGRectMake(
+ macWin->xOff + arcPtr->x + o,
+ macWin->yOff + arcPtr->y + o,
+ arcPtr->width - u, arcPtr->height - u);
+ if (arcPtr->angle1 == 0 && arcPtr->angle2 == 23040) {
+ CGContextFillEllipseInRect(dc.context, rect);
+ } else {
+ CGMutablePathRef p = CGPathCreateMutable();
+ CGAffineTransform t = CGAffineTransformIdentity;
+ CGPoint c = CGPointMake(CGRectGetMidX(rect),
+ CGRectGetMidY(rect));
+ double w = CGRectGetWidth(rect);
+
+ if (arcPtr->width != arcPtr->height) {
+ t = CGAffineTransformMakeScale(1, CGRectGetHeight(rect)/w);
+ c = CGPointApplyAffineTransform(c,
+ CGAffineTransformInvert(t));
+ }
+ if (gc->arc_mode == ArcPieSlice) {
+ CGPathMoveToPoint(p, &t, c.x, c.y);
+ }
+ CGPathAddArc(p, &t, c.x, c.y, w/2,
+ radians(-arcPtr->angle1/64.0),
+ radians(-(arcPtr->angle1 + arcPtr->angle2)/64.0),
+ arcPtr->angle2 > 0);
+ CGPathCloseSubpath(p);
+ CGContextAddPath(dc.context, p);
+ CGPathRelease(p);
+ CGContextFillPath(dc.context);
+ }
+ }
+ }
+ TkMacOSXRestoreDrawingContext(&dc);
+}
+#endif
+
+#ifdef TK_MACOSXDRAW_UNUSED
+/*
+ *----------------------------------------------------------------------
+ *
+ * XMaxRequestSize --
+ *
+ *----------------------------------------------------------------------
+ */
+
+long
+XMaxRequestSize(
+ Display *display)
+{
+ return (SHRT_MAX / 4);
+}
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkScrollWindow --
+ *
+ * Scroll a rectangle of the specified window and accumulate a damage
+ * region.
+ *
+ * Results:
+ * Returns 0 if the scroll generated 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, int y, /* Position rectangle to be scrolled. */
+ int width, int height,
+ int dx, int dy, /* Distance rectangle should be moved. */
+ TkRegion damageRgn) /* Region to accumulate damage in. */
+{
+ Drawable drawable = Tk_WindowId(tkwin);
+ MacDrawable *macDraw = (MacDrawable *) drawable;
+ TKContentView *view = (TKContentView *) TkMacOSXDrawableView(macDraw);
+ CGRect srcRect, dstRect;
+ HIShapeRef dmgRgn = NULL, extraRgn = NULL;
+ NSRect bounds, visRect, scrollSrc, scrollDst;
+ int result = 0;
+
+ if (view) {
+ /*
+ * Get the scroll area in NSView coordinates (origin at bottom left).
+ */
+
+ bounds = [view bounds];
+ scrollSrc = NSMakeRect(macDraw->xOff + x,
+ bounds.size.height - height - (macDraw->yOff + y),
+ width, height);
+ scrollDst = NSOffsetRect(scrollSrc, dx, -dy);
+
+ /*
+ * Limit scrolling to the window content area.
+ */
+
+ visRect = [view visibleRect];
+ scrollSrc = NSIntersectionRect(scrollSrc, visRect);
+ scrollDst = NSIntersectionRect(scrollDst, visRect);
+ if (!NSIsEmptyRect(scrollSrc) && !NSIsEmptyRect(scrollDst)) {
+ /*
+ * Mark the difference between source and destination as damaged.
+ * This region is described in NSView coordinates (y=0 at the
+ * bottom) and converted to Tk coordinates later.
+ */
+
+ srcRect = CGRectMake(x, y, width, height);
+ dstRect = CGRectOffset(srcRect, dx, dy);
+
+ /*
+ * Compute the damage.
+ */
+
+ dmgRgn = HIShapeCreateMutableWithRect(&srcRect);
+ extraRgn = HIShapeCreateWithRect(&dstRect);
+ ChkErr(HIShapeDifference, dmgRgn, extraRgn,
+ (HIMutableShapeRef) dmgRgn);
+ result = HIShapeIsEmpty(dmgRgn) ? 0 : 1;
+
+ /*
+ * Convert to Tk coordinates, offset by the window origin.
+ */
+
+ TkMacOSXSetWithNativeRegion(damageRgn, dmgRgn);
+ if (extraRgn) {
+ CFRelease(extraRgn);
+ }
+
+ /*
+ * Scroll the rectangle.
+ */
+
+ [view scrollRect:scrollSrc by:NSMakeSize(dx, -dy)];
+ }
+ } else {
+ dmgRgn = HIShapeCreateEmpty();
+ TkMacOSXSetWithNativeRegion(damageRgn, dmgRgn);
+ }
+
+ if (dmgRgn) {
+ CFRelease(dmgRgn);
+ }
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXSetUpGraphicsPort --
+ *
+ * Set up the graphics port from the given GC.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXSetUpGraphicsPort(
+ GC gc, /* GC to apply to current port. */
+ void *destPort)
+{
+ Tcl_Panic("TkMacOSXSetUpGraphicsPort: Obsolete, no more QD!");
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXSetUpDrawingContext --
+ *
+ * Set up a drawing context for the given drawable and GC.
+ *
+ * Results:
+ * Boolean indicating whether it is ok to draw; if false, drawing context
+ * was not setup, so do not attempt to draw and do not call
+ * TkMacOSXRestoreDrawingContext().
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Bool
+TkMacOSXSetupDrawingContext(
+ Drawable d,
+ GC gc,
+ int useCG, /* advisory only ! */
+ TkMacOSXDrawingContext *dcPtr)
+{
+ MacDrawable *macDraw = (MacDrawable *) d;
+ Bool canDraw = true;
+ NSWindow *win = NULL;
+ TkMacOSXDrawingContext dc = {};
+ CGRect clipBounds;
+
+ /*
+ * If the drawable is not a pixmap and it has an associated NSWindow then
+ * we know we are drawing to a window.
+ */
+
+ if (!(macDraw->flags & TK_IS_PIXMAP)) {
+ win = TkMacOSXDrawableWindow(d);
+ }
+
+ /*
+ * Check that we have a non-empty clipping region.
+ */
+
+ dc.clipRgn = TkMacOSXGetClipRgn(d);
+ ClipToGC(d, gc, &dc.clipRgn);
+ if (dc.clipRgn && HIShapeIsEmpty(dc.clipRgn)) {
+ canDraw = false;
+ goto end;
+ }
+
+ /*
+ * If we already have a CGContext, use it. Otherwise, if we are drawing to
+ * a window then we can get one from the window.
+ */
+
+ dc.context = TkMacOSXGetCGContextForDrawable(d);
+ if (dc.context) {
+ dc.portBounds = clipBounds = CGContextGetClipBoundingBox(dc.context);
+ } else if (win) {
+ NSView *view = TkMacOSXDrawableView(macDraw);
+
+ if (!view) {
+ Tcl_Panic("TkMacOSXSetupDrawingContext(): "
+ "no NSView to draw into !");
+ }
+
+ /*
+ * We can only draw into the view when the current CGContext is valid
+ * and belongs to the view. Validity can only be guaranteed inside of
+ * a view's drawRect or setFrame methods. The isDrawing attribute
+ * tells us whether we are being called from one of those methods.
+ *
+ * If the CGContext is not valid, or belongs to a different View, then
+ * we mark our view as needing display and return failure. It should
+ * get drawn in a later call to drawRect.
+ */
+
+ if (view != [NSView focusView]) {
+ [view setNeedsDisplay:YES];
+ canDraw = false;
+ goto end;
+ }
+ dc.view = view;
+ dc.context = GET_CGCONTEXT;
+ dc.portBounds = NSRectToCGRect([view bounds]);
+ if (dc.clipRgn) {
+ clipBounds = CGContextGetClipBoundingBox(dc.context);
+ }
+ } else {
+ Tcl_Panic("TkMacOSXSetupDrawingContext(): "
+ "no context to draw into !");
+ }
+
+ /*
+ * Configure the drawing context.
+ */
+
+ if (dc.context) {
+ CGAffineTransform t = {
+ .a = 1, .b = 0,
+ .c = 0, .d = -1,
+ .tx = 0,
+ .ty = dc.portBounds.size.height
+ };
+
+ dc.portBounds.origin.x += macDraw->xOff;
+ dc.portBounds.origin.y += macDraw->yOff;
+ CGContextSaveGState(dc.context);
+ CGContextSetTextDrawingMode(dc.context, kCGTextFill);
+ CGContextConcatCTM(dc.context, t);
+ if (dc.clipRgn) {
+#ifdef TK_MAC_DEBUG_DRAWING
+ CGContextSaveGState(dc.context);
+ ChkErr(HIShapeReplacePathInCGContext, dc.clipRgn, dc.context);
+ CGContextSetRGBFillColor(dc.context, 1.0, 0.0, 0.0, 0.1);
+ CGContextEOFillPath(dc.context);
+ CGContextRestoreGState(dc.context);
+#endif /* TK_MAC_DEBUG_DRAWING */
+ CGRect r;
+
+ if (!HIShapeIsRectangular(dc.clipRgn) || !CGRectContainsRect(
+ *HIShapeGetBounds(dc.clipRgn, &r),
+ CGRectApplyAffineTransform(clipBounds, t))) {
+ ChkErr(HIShapeReplacePathInCGContext, dc.clipRgn, dc.context);
+ CGContextEOClip(dc.context);
+ }
+ }
+ if (gc) {
+ static const CGLineCap cgCap[] = {
+ [CapNotLast] = kCGLineCapButt,
+ [CapButt] = kCGLineCapButt,
+ [CapRound] = kCGLineCapRound,
+ [CapProjecting] = kCGLineCapSquare,
+ };
+ static const CGLineJoin cgJoin[] = {
+ [JoinMiter] = kCGLineJoinMiter,
+ [JoinRound] = kCGLineJoinRound,
+ [JoinBevel] = kCGLineJoinBevel,
+ };
+ bool shouldAntialias;
+ double w = gc->line_width;
+
+ TkMacOSXSetColorInContext(gc, gc->foreground, dc.context);
+ if (win) {
+ CGContextSetPatternPhase(dc.context, CGSizeMake(
+ dc.portBounds.size.width, dc.portBounds.size.height));
+ }
+ if (gc->function != GXcopy) {
+ TkMacOSXDbgMsg("Logical functions other than GXcopy are "
+ "not supported for CG drawing!");
+ }
+
+ /*
+ * When should we antialias?
+ */
+
+ shouldAntialias = !notAA(gc->line_width);
+ if (!shouldAntialias) {
+ /*
+ * Make non-antialiased CG drawing look more like X11.
+ */
+
+ w -= (gc->line_width ? NON_AA_CG_OFFSET : 0);
+ }
+ CGContextSetShouldAntialias(dc.context, shouldAntialias);
+ CGContextSetLineWidth(dc.context, w);
+ if (gc->line_style != LineSolid) {
+ int num = 0;
+ char *p = &gc->dashes;
+ CGFloat dashOffset = gc->dash_offset;
+ CGFloat lengths[10];
+
+ while (p[num] != '\0' && num < 10) {
+ lengths[num] = p[num];
+ num++;
+ }
+ CGContextSetLineDash(dc.context, dashOffset, lengths, num);
+ }
+ if ((unsigned) gc->cap_style < sizeof(cgCap)/sizeof(CGLineCap)) {
+ CGContextSetLineCap(dc.context,
+ cgCap[(unsigned) gc->cap_style]);
+ }
+ if ((unsigned)gc->join_style < sizeof(cgJoin)/sizeof(CGLineJoin)) {
+ CGContextSetLineJoin(dc.context,
+ cgJoin[(unsigned) gc->join_style]);
+ }
+ }
+ }
+
+end:
+#ifdef TK_MAC_DEBUG_DRAWING
+ if (!canDraw && win != NULL) {
+ TkWindow *winPtr = TkMacOSXGetTkWindow(win);
+
+ if (winPtr) {
+ fprintf(stderr, "Cannot draw in %s - postponing.\n",
+ Tk_PathName(winPtr));
+ }
+ }
+#endif
+ if (!canDraw && dc.clipRgn) {
+ CFRelease(dc.clipRgn);
+ dc.clipRgn = NULL;
+ }
+ *dcPtr = dc;
+ return canDraw;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXRestoreDrawingContext --
+ *
+ * Restore drawing context.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXRestoreDrawingContext(
+ TkMacOSXDrawingContext *dcPtr)
+{
+ if (dcPtr->context) {
+ CGContextSynchronize(dcPtr->context);
+ CGContextRestoreGState(dcPtr->context);
+ }
+ if (dcPtr->clipRgn) {
+ CFRelease(dcPtr->clipRgn);
+ }
+#ifdef TK_MAC_DEBUG
+ bzero(dcPtr, sizeof(TkMacOSXDrawingContext));
+#endif /* TK_MAC_DEBUG */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXGetClipRgn --
+ *
+ * Get the clipping region needed to restrict drawing to the given
+ * drawable.
+ *
+ * Results:
+ * Clipping region. If non-NULL, CFRelease it when done.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+HIShapeRef
+TkMacOSXGetClipRgn(
+ Drawable drawable) /* Drawable. */
+{
+ MacDrawable *macDraw = (MacDrawable *) drawable;
+ HIShapeRef clipRgn = NULL;
+
+ if (macDraw->winPtr && macDraw->flags & TK_CLIP_INVALID) {
+ TkMacOSXUpdateClipRgn(macDraw->winPtr);
+#ifdef TK_MAC_DEBUG_DRAWING
+ TkMacOSXDbgMsg("%s", macDraw->winPtr->pathName);
+
+ NSView *view = TkMacOSXDrawableView(macDraw);
+
+ CGContextSaveGState(context);
+ CGContextConcatCTM(context, CGAffineTransformMake(1.0, 0.0, 0.0,
+ -1.0, 0.0, [view bounds].size.height));
+ ChkErr(HIShapeReplacePathInCGContext, macDraw->visRgn, context);
+ CGContextSetRGBFillColor(context, 0.0, 1.0, 0.0, 0.1);
+ CGContextEOFillPath(context);
+ CGContextRestoreGState(context);
+#endif /* TK_MAC_DEBUG_DRAWING */
+ }
+
+ if (macDraw->drawRgn) {
+ clipRgn = HIShapeCreateCopy(macDraw->drawRgn);
+ } else if (macDraw->visRgn) {
+ clipRgn = HIShapeCreateCopy(macDraw->visRgn);
+ }
+ return clipRgn;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXSetUpClippingRgn --
+ *
+ * Set up the clipping region so that drawing only occurs on the specified
+ * X subwindow.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXSetUpClippingRgn(
+ Drawable drawable) /* Drawable to update. */
+{
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpClipDrawableToRect --
+ *
+ * Clip all drawing into the drawable d to the given rectangle. If width
+ * or height are negative, reset to no clipping.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Subsequent drawing into d is offset and clipped as specified.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpClipDrawableToRect(
+ Display *display,
+ Drawable d,
+ int x, int y,
+ int width, int height)
+{
+ MacDrawable *macDraw = (MacDrawable *) d;
+
+ if (macDraw->drawRgn) {
+ CFRelease(macDraw->drawRgn);
+ macDraw->drawRgn = NULL;
+ }
+ if (width >= 0 && height >= 0) {
+ CGRect clipRect = CGRectMake(x + macDraw->xOff, y + macDraw->yOff,
+ width, height);
+ HIShapeRef drawRgn = HIShapeCreateWithRect(&clipRect);
+
+ if (macDraw->winPtr && macDraw->flags & TK_CLIP_INVALID) {
+ TkMacOSXUpdateClipRgn(macDraw->winPtr);
+ }
+ if (macDraw->visRgn) {
+ macDraw->drawRgn = HIShapeCreateIntersection(macDraw->visRgn,
+ drawRgn);
+ CFRelease(drawRgn);
+ } else {
+ macDraw->drawRgn = drawRgn;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ClipToGC --
+ *
+ * Helper function to intersect given region with gc clip region.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ClipToGC(
+ Drawable d,
+ GC gc,
+ HIShapeRef *clipRgnPtr) /* must point to initialized variable */
+{
+ if (gc && gc->clip_mask &&
+ ((TkpClipMask *) gc->clip_mask)->type == TKP_CLIP_REGION) {
+ TkRegion gcClip = ((TkpClipMask *) gc->clip_mask)->value.region;
+ int xOffset = ((MacDrawable *) d)->xOff + gc->clip_x_origin;
+ int yOffset = ((MacDrawable *) d)->yOff + gc->clip_y_origin;
+ HIShapeRef clipRgn = *clipRgnPtr, gcClipRgn;
+
+ TkMacOSXOffsetRegion(gcClip, xOffset, yOffset);
+ gcClipRgn = TkMacOSXGetNativeRegion(gcClip);
+ if (clipRgn) {
+ *clipRgnPtr = HIShapeCreateIntersection(gcClipRgn, clipRgn);
+ CFRelease(clipRgn);
+ } else {
+ *clipRgnPtr = HIShapeCreateCopy(gcClipRgn);
+ }
+ CFRelease(gcClipRgn);
+ TkMacOSXOffsetRegion(gcClip, -xOffset, -yOffset);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void *
+TkMacOSXMakeStippleMap(
+ Drawable drawable, /* Window to apply stipple. */
+ Drawable stipple) /* The stipple pattern. */
+{
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpDrawHighlightBorder --
+ *
+ * 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);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpDrawFrame --
+ *
+ * This procedure draws the rectangular frame area. If the user has
+ * requested themeing, it draws with the background theme.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Draws inside the tkwin area.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpDrawFrame(
+ Tk_Window tkwin,
+ Tk_3DBorder border,
+ int highlightWidth,
+ int borderWidth,
+ int relief)
+{
+ if (useThemedToplevel && Tk_IsTopLevel(tkwin)) {
+ static Tk_3DBorder themedBorder = NULL;
+
+ if (!themedBorder) {
+ themedBorder = Tk_Get3DBorder(NULL, tkwin,
+ "systemWindowHeaderBackground");
+ }
+ if (themedBorder) {
+ border = themedBorder;
+ }
+ }
+
+ Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin),
+ border, highlightWidth, highlightWidth,
+ Tk_Width(tkwin) - 2 * highlightWidth,
+ Tk_Height(tkwin) - 2 * highlightWidth,
+ borderWidth, relief);
+}
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXEmbed.c b/tk8.6/macosx/tkMacOSXEmbed.c
new file mode 100644
index 0000000..6c4ac1f
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXEmbed.c
@@ -0,0 +1,1225 @@
+/*
+ * 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-2009, Apple Inc.
+ * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkMacOSXPrivate.h"
+#include "tkBusy.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 *tkMacOSXEmbedHandler = NULL;
+
+/*
+ * Prototypes for static procedures defined in this file:
+ */
+
+static void ContainerEventProc(ClientData clientData, XEvent *eventPtr);
+static void EmbeddedEventProc(ClientData clientData, XEvent *eventPtr);
+static void EmbedActivateProc(ClientData clientData, XEvent *eventPtr);
+static void EmbedFocusProc(ClientData clientData, XEvent *eventPtr);
+static void EmbedGeometryRequest(Container *containerPtr, int width,
+ int height);
+static void EmbedSendConfigure(Container *containerPtr);
+static void EmbedStructureProc(ClientData clientData, XEvent *eventPtr);
+static void EmbedWindowDeleted(TkWindow *winPtr);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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 (tkMacOSXEmbedHandler == NULL) {
+ tkMacOSXEmbedHandler = ckalloc(sizeof(TkMacOSXEmbedHandler));
+ }
+ tkMacOSXEmbedHandler->registerWinProc = registerWinProc;
+ tkMacOSXEmbedHandler->getPortProc = getPortProc;
+ tkMacOSXEmbedHandler->containerExistProc = containerExistProc;
+ tkMacOSXEmbedHandler->getClipProc = getClipProc;
+ tkMacOSXEmbedHandler->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;
+
+ /*
+ * If this window is marked as embedded then the window structure should
+ * have already been created in the TkpUseWindow function.
+ */
+
+ if (Tk_IsEmbedded(winPtr)) {
+ macWin = winPtr->privatePtr;
+ } else {
+ /*
+ * Allocate sub window
+ */
+
+ macWin = ckalloc(sizeof(MacDrawable));
+ if (macWin == NULL) {
+ winPtr->privatePtr = NULL;
+ return None;
+ }
+ macWin->winPtr = winPtr;
+ winPtr->privatePtr = macWin;
+ macWin->visRgn = NULL;
+ macWin->aboveVisRgn = NULL;
+ macWin->drawRgn = NULL;
+ macWin->referenceCount = 0;
+ macWin->flags = TK_CLIP_INVALID;
+ macWin->view = nil;
+ macWin->context = NULL;
+ macWin->size = CGSizeZero;
+ if (Tk_IsTopLevel(macWin->winPtr)) {
+ /*
+ * This will be set when we are mapped.
+ */
+
+ macWin->xOff = 0;
+ macWin->yOff = 0;
+ macWin->toplevel = macWin;
+ } else if (winPtr->parentPtr) {
+ 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++;
+ }
+ return (Window) macWin;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpScanWindowId --
+ *
+ * Given a string, produce the corresponding Window Id.
+ *
+ * Results:
+ * The return value is normally TCL_OK; in this case *idPtr will be set
+ * to the Window value equivalent to string. If string is improperly
+ * formed then TCL_ERROR is returned and an error message will be left in
+ * the interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkpScanWindowId(
+ Tcl_Interp *interp,
+ const char * string,
+ Window *idPtr)
+{
+ int code;
+ Tcl_Obj obj;
+
+ obj.refCount = 1;
+ obj.bytes = (char *) string; /* DANGER?! */
+ obj.length = strlen(string);
+ obj.typePtr = NULL;
+
+ code = Tcl_GetLongFromObj(interp, &obj, (long *)idPtr);
+
+ if (obj.refCount > 1) {
+ Tcl_Panic("invalid sharing of Tcl_Obj on C stack");
+ }
+ if (obj.typePtr && obj.typePtr->freeIntRepProc) {
+ obj.typePtr->freeIntRepProc(&obj);
+ }
+ return code;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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;
+ TkWindow *usePtr;
+ MacDrawable *parent, *macWin;
+ Container *containerPtr;
+
+ if (winPtr->window != None) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "can't modify container after widget is created", -1));
+ Tcl_SetErrorCode(interp, "TK", "EMBED", "POST_CREATE", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Decode the container window ID, 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 (TkpScanWindowId(interp, string, (Window *)&parent) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ usePtr = (TkWindow *) Tk_IdToWindow(winPtr->display, (Window) parent);
+ if (usePtr == NULL) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "couldn't create child of window \"%s\"", string));
+ Tcl_SetErrorCode(interp, "TK", "EMBED", "NO_TARGET", NULL);
+ }
+ return TCL_ERROR;
+ } else if (!(usePtr->flags & TK_CONTAINER)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "window \"%s\" doesn't have -container option set",
+ usePtr->pathName));
+ Tcl_SetErrorCode(interp, "TK", "EMBED", "CONTAINER", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Since we do not allow embedding into windows belonging to a different
+ * process, we know that a container will exist showing the parent window
+ * as the parent. This loop finds that container.
+ */
+
+ 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 = ckalloc(sizeof(MacDrawable));
+ if (macWin == NULL) {
+ winPtr->privatePtr = NULL;
+ return TCL_ERROR;
+ }
+
+ macWin->winPtr = winPtr;
+ macWin->view = nil;
+ macWin->context = NULL;
+ macWin->size = CGSizeZero;
+ macWin->visRgn = NULL;
+ macWin->aboveVisRgn = NULL;
+ macWin->drawRgn = NULL;
+ macWin->referenceCount = 0;
+ macWin->flags = TK_CLIP_INVALID;
+ macWin->toplevel = macWin;
+ macWin->toplevel->referenceCount++;
+
+ winPtr->privatePtr = macWin;
+ 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;
+ 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, winPtr);
+
+ 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 = 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, winPtr);
+ Tk_CreateEventHandler(tkwin, StructureNotifyMask, EmbedStructureProc,
+ containerPtr);
+ Tk_CreateEventHandler(tkwin, ActivateMask, EmbedActivateProc,
+ containerPtr);
+ Tk_CreateEventHandler(tkwin, FocusChangeMask, EmbedFocusProc,
+ 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(
+ 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;
+ }
+ }
+ Tcl_Panic("TkMacOSXContainerId couldn't find window");
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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;
+ }
+ contWinPtr = TkpGetOtherWindow(topWinPtr);
+
+ /*
+ * TODO: Here we should handle out of process embedding.
+ */
+
+ if (!contWinPtr) {
+ return NULL;
+ }
+ return TkMacOSXGetHostToplevel(contWinPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpClaimFocus --
+ *
+ * This procedure is invoked when someone asks for the input focus to be
+ * put on a window in an embedded 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_HandleEvent(&event);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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 objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument strings. */
+{
+ int all;
+ Container *containerPtr;
+ Tcl_DString dString;
+ char buffer[50];
+ Tcl_Interp *embeddedInterp = NULL, *parentInterp = NULL;
+
+ if ((objc > 1) && (strcmp(Tcl_GetString(objv[1]), "all") == 0)) {
+ all = 1;
+ } else {
+ all = 0;
+ }
+ Tcl_DStringInit(&dString);
+ for (containerPtr = firstContainerPtr; containerPtr != NULL;
+ containerPtr = containerPtr->nextPtr) {
+ if (containerPtr->embeddedPtr != NULL) {
+ embeddedInterp = containerPtr->embeddedPtr->mainPtr->interp;
+ }
+ if (containerPtr->parentPtr != NULL) {
+ parentInterp = containerPtr->parentPtr->mainPtr->interp;
+ }
+ if (embeddedInterp != interp && parentInterp != interp) {
+ continue;
+ }
+ Tcl_DStringStartSublist(&dString);
+
+ /*
+ * Parent id
+ */
+
+ if (containerPtr->parent == None) {
+ Tcl_DStringAppendElement(&dString, "");
+ } else if (all) {
+ sprintf(buffer, "0x%lx", containerPtr->parent);
+ Tcl_DStringAppendElement(&dString, buffer);
+ } else {
+ Tcl_DStringAppendElement(&dString, "XXX");
+ }
+
+ /*
+ * Parent pathName
+ */
+
+ if (containerPtr->parentPtr == NULL ||
+ parentInterp != interp) {
+ Tcl_DStringAppendElement(&dString, "");
+ } else {
+ Tcl_DStringAppendElement(&dString,
+ containerPtr->parentPtr->pathName);
+ }
+
+ /*
+ * On X11 embedded is a wrapper, which does not exist on macOS.
+ */
+
+ Tcl_DStringAppendElement(&dString, "");
+
+ /*
+ * Embedded window pathName
+ */
+
+ if (containerPtr->embeddedPtr == NULL ||
+ embeddedInterp != interp) {
+ 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). */
+{
+ /* TODO: Implement this or decide it definitely needs no implementation */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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 clientData, /* Token for container window. */
+ XEvent *eventPtr) /* ResizeRequest event. */
+{
+ TkWindow *winPtr = 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 clientData, /* Token for container window. */
+ XEvent *eventPtr) /* ResizeRequest event. */
+{
+ TkWindow *winPtr = clientData;
+ Container *containerPtr;
+ Tk_ErrorHandler errHandler;
+
+ if (!firstContainerPtr) {
+ /*
+ * When the interpreter is being dismantled this can be nil.
+ */
+
+ return;
+ }
+
+ /*
+ * 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, NULL, NULL);
+
+ /*
+ * Find the Container structure associated with the parent window.
+ */
+
+ for (containerPtr = firstContainerPtr;
+ containerPtr->parent != eventPtr->xmaprequest.parent;
+ containerPtr = containerPtr->nextPtr) {
+ if (containerPtr == NULL) {
+ Tcl_Panic("ContainerEventProc couldn't find Container record");
+ }
+ }
+
+ 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) {
+ /*
+ * It is not clear whether the container should be destroyed
+ * when an embedded window is destroyed. See ticket [67384bce7d].
+ * Here we are following unix, by destroying the container.
+ */
+
+ 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 clientData, /* Token for container window. */
+ XEvent *eventPtr) /* ResizeRequest event. */
+{
+ Container *containerPtr = clientData;
+ Tk_ErrorHandler errHandler;
+
+ if (eventPtr->type == ConfigureNotify) {
+
+ /*
+ * Send a ConfigureNotify to the embedded application.
+ */
+
+ if (containerPtr->embeddedPtr != None) {
+ TkDoConfigureNotify(containerPtr->embeddedPtr);
+ }
+ if (containerPtr->embedded != None) {
+ /*
+ * Ignore errors, since the embedded application could have
+ * deleted its window.
+ */
+
+ errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1,
+ -1, -1, NULL, NULL);
+ Tk_MoveResizeWindow((Tk_Window) containerPtr->embeddedPtr, 0, 0,
+ (unsigned) Tk_Width((Tk_Window) containerPtr->parentPtr),
+ (unsigned) 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 clientData, /* Token for container window. */
+ XEvent *eventPtr) /* ResizeRequest event. */
+{
+ Container *containerPtr = 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 clientData, /* Token for container window. */
+ XEvent *eventPtr) /* ResizeRequest event. */
+{
+ Container *containerPtr = 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(
+ Container *containerPtr, /* Information about the embedding. */
+ int width, int 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(
+ 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(
+ 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 = LastKnownRequestProcessed(
+ Tk_Display(containerPtr->parentPtr));
+ 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(containerPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpShowBusyWindow, TkpHideBusyWindow, TkpMakeTransparentWindowExist,
+ * TkpCreateBusy --
+ *
+ * Portability layer for busy windows. Holds platform-specific gunk for
+ * the [tk busy] command, which is currently a dummy implementation for
+ * OSX/Aqua. The individual functions are supposed to do the following:
+ *
+ * TkpShowBusyWindow --
+ * Make the busy window appear.
+ *
+ * TkpHideBusyWindow --
+ * Make the busy window go away.
+ *
+ * TkpMakeTransparentWindowExist --
+ * Actually make a transparent window.
+ *
+ * TkpCreateBusy --
+ * Creates the platform-specific part of a busy window structure.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpShowBusyWindow(
+ TkBusy busy)
+{
+}
+
+void
+TkpHideBusyWindow(
+ TkBusy busy)
+{
+}
+
+void
+TkpMakeTransparentWindowExist(
+ Tk_Window tkwin, /* Token for window. */
+ Window parent) /* Parent window. */
+{
+}
+
+void
+TkpCreateBusy(
+ Tk_FakeWin *winPtr,
+ Tk_Window tkRef,
+ Window* parentPtr,
+ Tk_Window tkParent,
+ TkBusy busy)
+{
+}
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXEntry.c b/tk8.6/macosx/tkMacOSXEntry.c
new file mode 100644
index 0000000..a1c5d60
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXEntry.c
@@ -0,0 +1,282 @@
+/*
+ * tkMacOSXEntry.c --
+ *
+ * This file implements the native aqua entry widget.
+ *
+ * Copyright 2001, Apple Computer, Inc.
+ * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright 2008-2009, Apple Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkMacOSXPrivate.h"
+#include "tkEntry.h"
+
+static ThemeButtonKind ComputeIncDecParameters(int height, int *width);
+
+#define HIOrientation kHIThemeOrientationNormal
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ComputeIncDecParameters --
+ *
+ * This procedure figures out which of the kThemeIncDec buttons to use.
+ * It also sets width to the width of the IncDec button.
+ *
+ * Results:
+ * The ThemeButtonKind of the button we should use.
+ *
+ * Side effects:
+ * May draw the entry border into pixmap.
+ *
+ *--------------------------------------------------------------
+ */
+
+static ThemeButtonKind
+ComputeIncDecParameters(
+ int height,
+ int *width)
+{
+ ThemeButtonKind kind;
+
+ if (height < 11 || height > 28) {
+ *width = 0;
+ kind = (ThemeButtonKind) 0;
+ } else {
+ if (height >= 21) {
+ *width = 13;
+ kind = kThemeIncDecButton;
+ } else if (height >= 18) {
+ *width = 12;
+ kind = kThemeIncDecButtonSmall;
+ } else {
+ *width = 11;
+ kind = kThemeIncDecButtonMini;
+ }
+ }
+
+ return kind;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkpDrawEntryBorderAndFocus --
+ *
+ * This procedure redraws the border of an entry window. It overrides the
+ * generic border drawing code if the entry widget parameters are such
+ * that the native widget drawing is a good fit. This version just
+ * returns 1, so platforms that don't do special native drawing don't
+ * have to implement it.
+ *
+ * Results:
+ * 1 if it has drawn the border, 0 if not.
+ *
+ * Side effects:
+ * May draw the entry border into pixmap.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkpDrawEntryBorderAndFocus(
+ Entry *entryPtr,
+ Drawable d,
+ int isSpinbox)
+{
+ CGRect bounds;
+ TkMacOSXDrawingContext dc;
+ GC bgGC;
+ Tk_Window tkwin = entryPtr->tkwin;
+ int oldWidth = 0;
+ MacDrawable *macDraw = (MacDrawable *) d;
+ const HIThemeFrameDrawInfo info = {
+ .version = 0,
+ .kind = kHIThemeFrameTextFieldSquare,
+ .state = (entryPtr->state == STATE_DISABLED ? kThemeStateInactive :
+ kThemeStateActive),
+ .isFocused = (entryPtr->flags & GOT_FOCUS ? 1 : 0),
+ };
+
+ /*
+ * I use 6 as the borderwidth. 2 of the 5 go into the actual frame the 3
+ * are because the Mac OS Entry widgets leave more space around the Text
+ * than Tk does on X11.
+ */
+
+ if (entryPtr->borderWidth != MAC_OSX_ENTRY_BORDER
+ || entryPtr->highlightWidth != MAC_OSX_FOCUS_WIDTH
+ || entryPtr->relief != MAC_OSX_ENTRY_RELIEF) {
+ return 0;
+ }
+
+ /*
+ * For the spinbox, we have to make the entry part smaller by the size of
+ * the buttons. We also leave 2 pixels to the left (as per the HIG) and
+ * space for one pixel to the right, 'cause it makes the buttons look
+ * nicer.
+ */
+
+ if (isSpinbox) {
+ int incDecWidth;
+
+ /*
+ * Temporarily change the width of the widget so that the same code can
+ * be used for drawing the Entry portion of the Spinbox as is used to
+ * draw an ordinary Entry. The width must be restored before
+ * returning.
+ */
+
+ oldWidth = Tk_Width(tkwin);
+ ComputeIncDecParameters(Tk_Height(tkwin) - 2 * MAC_OSX_FOCUS_WIDTH,
+ &incDecWidth);
+ Tk_Width(tkwin) -= incDecWidth + 1;
+ }
+
+ /*
+ * The focus ring is drawn with an Alpha at the outside part of the ring,
+ * so we have to draw over the edges of the ring before drawing the focus
+ * or the text will peep through.
+ */
+
+ bgGC = Tk_GCForColor(entryPtr->highlightBgColorPtr, d);
+ TkDrawInsetFocusHighlight(entryPtr->tkwin, bgGC, MAC_OSX_FOCUS_WIDTH, d, 0);
+
+ /*
+ * Inset the entry Frame by the maximum width of the focus rect, which is
+ * 3 according to the Carbon docs.
+ */
+
+ bounds.origin.x = macDraw->xOff + MAC_OSX_FOCUS_WIDTH;
+ bounds.origin.y = macDraw->yOff + MAC_OSX_FOCUS_WIDTH;
+ bounds.size.width = Tk_Width(tkwin) - 2*MAC_OSX_FOCUS_WIDTH;
+ bounds.size.height = Tk_Height(tkwin) - 2*MAC_OSX_FOCUS_WIDTH;
+ if (!TkMacOSXSetupDrawingContext(d, NULL, 1, &dc)) {
+
+ /*
+ * No graphics context is available. If the widget is a Spinbox, we
+ * must restore its width before returning 0. (Ticket [273b6a4996].)
+ */
+
+ if (isSpinbox) {
+ Tk_Width(tkwin) = oldWidth;
+ }
+ return 0;
+ }
+ ChkErr(HIThemeDrawFrame, &bounds, &info, dc.context, HIOrientation);
+ TkMacOSXRestoreDrawingContext(&dc);
+ if (isSpinbox) {
+ Tk_Width(tkwin) = oldWidth;
+ }
+ return 1;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkpDrawSpinboxButtons --
+ *
+ * This procedure redraws the buttons of an spinbox widget. It overrides
+ * the generic button drawing code if the spinbox widget parameters are
+ * such that the native widget drawing is a good fit. This version just
+ * returns 0, so platforms that don't do special native drawing don't
+ * have to implement it.
+ *
+ * Results:
+ * 1 if it has drawn the border, 0 if not.
+ *
+ * Side effects:
+ * May draw the entry border into pixmap.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkpDrawSpinboxButtons(
+ Spinbox *sbPtr,
+ Drawable d)
+{
+ CGRect bounds;
+ Tk_Window tkwin = sbPtr->entry.tkwin;
+ int height = Tk_Height(tkwin);
+ int buttonHeight = height - 2 * MAC_OSX_FOCUS_WIDTH;
+ int incDecWidth;
+ TkMacOSXDrawingContext dc;
+ XRectangle rects[1];
+ GC bgGC;
+ MacDrawable *macDraw = (MacDrawable *) d;
+ HIThemeButtonDrawInfo info = {
+ .version = 0,
+ .adornment = kThemeAdornmentNone,
+ };
+
+ /*
+ * FIXME: RAISED really makes more sense
+ */
+
+ if (sbPtr->buRelief != TK_RELIEF_FLAT) {
+ return 0;
+ }
+
+ /*
+ * The actual sizes of the IncDec button are 21 for the normal, 18 for the
+ * small and 15 for the mini. But the spinbox still looks okay if the
+ * entry is a little bigger than this, so we give it a little slop.
+ */
+
+ info.kind = ComputeIncDecParameters(buttonHeight, &incDecWidth);
+ if (info.kind == (ThemeButtonKind) 0) {
+ return 0;
+ }
+
+ if (sbPtr->entry.state == STATE_DISABLED) {
+ info.state = kThemeStateInactive;
+ info.value = kThemeButtonOff;
+ } else if (sbPtr->selElement == SEL_BUTTONUP) {
+ info.state = kThemeStatePressedUp;
+ info.value = kThemeButtonOn;
+ } else if (sbPtr->selElement == SEL_BUTTONDOWN) {
+ info.state = kThemeStatePressedDown;
+ info.value = kThemeButtonOn;
+ } else {
+ info.state = kThemeStateActive;
+ info.value = kThemeButtonOff;
+ }
+
+ bounds.origin.x = macDraw->xOff + Tk_Width(tkwin) - incDecWidth - 1;
+ bounds.origin.y = macDraw->yOff + MAC_OSX_FOCUS_WIDTH;
+ bounds.size.width = incDecWidth;
+ bounds.size.height = Tk_Height(tkwin) - 2*MAC_OSX_FOCUS_WIDTH;
+
+ /*
+ * We had to make the entry part of the window smaller so that we wouldn't
+ * overdraw the spin buttons with the focus highlight. So now we have to
+ * draw the highlightbackground.
+ */
+
+ bgGC = Tk_GCForColor(sbPtr->entry.highlightBgColorPtr, d);
+ rects[0].x = bounds.origin.x;
+ rects[0].y = 0;
+ rects[0].width = Tk_Width(tkwin);
+ rects[0].height = Tk_Height(tkwin);
+ XFillRectangles(Tk_Display(tkwin), d, bgGC, rects, 1);
+
+ if (!TkMacOSXSetupDrawingContext(d, NULL, 1, &dc)) {
+ return 0;
+ }
+ ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL);
+ TkMacOSXRestoreDrawingContext(&dc);
+ return 1;
+}
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXEvent.c b/tk8.6/macosx/tkMacOSXEvent.c
new file mode 100644
index 0000000..b9c9b6a
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXEvent.c
@@ -0,0 +1,151 @@
+/*
+ * tkMacOSXEvent.c --
+ *
+ * This file contains the basic Mac OS X Event handling routines.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ * Copyright 2001-2009, Apple Inc.
+ * Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkMacOSXPrivate.h"
+#include "tkMacOSXEvent.h"
+#include "tkMacOSXDebug.h"
+#include "tkMacOSXConstants.h"
+
+#pragma mark TKApplication(TKEvent)
+
+enum {
+ NSWindowWillMoveEventType = 20
+};
+
+@implementation TKApplication(TKEvent)
+/* TODO: replace by +[addLocalMonitorForEventsMatchingMask ? */
+- (NSEvent *) tkProcessEvent: (NSEvent *) theEvent
+{
+#ifdef TK_MAC_DEBUG_EVENTS
+ TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent);
+#endif
+ NSEvent *processedEvent = theEvent;
+ NSEventType type = [theEvent type];
+ NSInteger subtype;
+
+ switch ((NSInteger)type) {
+ case NSAppKitDefined:
+ subtype = [theEvent subtype];
+
+ switch (subtype) {
+ /* Ignored at the moment. */
+ case NSApplicationActivatedEventType:
+ break;
+ case NSApplicationDeactivatedEventType:
+ break;
+ case NSWindowExposedEventType:
+ break;
+ case NSScreenChangedEventType:
+ break;
+ case NSWindowMovedEventType:
+ break;
+ case NSWindowWillMoveEventType:
+ break;
+
+ default:
+ break;
+ }
+ break; /* AppkitEvent. Return theEvent */
+ case NSKeyUp:
+ case NSKeyDown:
+ case NSFlagsChanged:
+ processedEvent = [self tkProcessKeyEvent:theEvent];
+ break; /* Key event. Return the processed event. */
+ case NSLeftMouseDown:
+ case NSLeftMouseUp:
+ case NSRightMouseDown:
+ case NSRightMouseUp:
+ case NSLeftMouseDragged:
+ case NSRightMouseDragged:
+ case NSMouseMoved:
+ case NSMouseEntered:
+ case NSMouseExited:
+ case NSScrollWheel:
+ case NSOtherMouseDown:
+ case NSOtherMouseUp:
+ case NSOtherMouseDragged:
+ case NSTabletPoint:
+ case NSTabletProximity:
+ processedEvent = [self tkProcessMouseEvent:theEvent];
+ break; /* Mouse event. Return the processed event. */
+#if 0
+ case NSSystemDefined:
+ subtype = [theEvent subtype];
+ break;
+ case NSApplicationDefined: {
+ id win;
+ win = [theEvent window];
+ break;
+ }
+ case NSCursorUpdate:
+ break;
+ case NSEventTypeGesture:
+ case NSEventTypeMagnify:
+ case NSEventTypeRotate:
+ case NSEventTypeSwipe:
+ case NSEventTypeBeginGesture:
+ case NSEventTypeEndGesture:
+ break;
+#endif
+
+ default:
+ break; /* return theEvent */
+ }
+ return processedEvent;
+}
+@end
+
+#pragma mark -
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXFlushWindows --
+ *
+ * This routine is a stub called by XSync, which is called during the Tk
+ * update command. The language specification does not require that the
+ * update command be synchronous but many of the tests implicitly assume
+ * that it is. It is definitely asynchronous on macOS since many idle
+ * tasks are run inside of the drawRect method of a window's contentView,
+ * which will not be called until after this function returns.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects: Processes all pending idle events then calls the display
+ * method of each visible window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+MODULE_SCOPE void
+TkMacOSXFlushWindows(void)
+{
+ if (Tk_GetNumMainWindows() == 0) {
+ return;
+ }
+ while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)){}
+ for (NSWindow *w in [NSApp orderedWindows]) {
+ [w display];
+ }
+}
+
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXEvent.h b/tk8.6/macosx/tkMacOSXEvent.h
new file mode 100644
index 0000000..46d1585
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXEvent.h
@@ -0,0 +1,23 @@
+/*
+ * tkMacOSXEvent.h --
+ *
+ * Declarations of Macintosh specific functions for implementing the
+ * Mac OS X Notifier.
+ *
+ * Copyright 2001-2009, Apple Inc.
+ * Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef _TKMACEVENT
+#define _TKMACEVENT
+
+#ifndef _TKMACINT
+#include "tkMacOSXInt.h"
+#endif
+
+MODULE_SCOPE void TkMacOSXFlushWindows(void);
+
+#endif
diff --git a/tk8.6/macosx/tkMacOSXFont.c b/tk8.6/macosx/tkMacOSXFont.c
new file mode 100644
index 0000000..fb71e85
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXFont.c
@@ -0,0 +1,1335 @@
+/*
+ * tkMacOSXFont.c --
+ *
+ * Contains the Macintosh implementation of the platform-independent font
+ * package interface.
+ *
+ * Copyright 2002-2004 Benjamin Riefenstahl, Benjamin.Riefenstahl@epost.de
+ * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright 2008-2009, Apple Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkMacOSXPrivate.h"
+#include "tkMacOSXFont.h"
+#include "tkMacOSXConstants.h"
+
+#define defaultOrientation kCTFontDefaultOrientation
+#define verticalOrientation kCTFontVerticalOrientation
+#define fixedPitch kCTFontUserFixedPitchFontType
+
+/*
+#ifdef TK_MAC_DEBUG
+#define TK_MAC_DEBUG_FONTS
+#endif
+*/
+
+/*
+ * The following structure represents our Macintosh-specific implementation
+ * of a font object.
+ */
+
+typedef struct {
+ TkFont font; /* Stuff used by generic font package. Must be
+ * first in structure. */
+ NSFont *nsFont;
+ NSDictionary *nsAttributes;
+} MacFont;
+
+/*
+ * The names for our "native" fonts.
+ */
+
+#define SYSTEMFONT_NAME "system"
+#define APPLFONT_NAME "application"
+#define MENUITEMFONT_NAME "menu"
+
+struct SystemFontMapEntry {
+ const ThemeFontID id;
+ const char *systemName;
+ const char *tkName;
+ const char *tkName1;
+};
+
+#define ThemeFont(n, ...) { kTheme##n##Font, "system" #n "Font", ##__VA_ARGS__ }
+static const struct SystemFontMapEntry systemFontMap[] = {
+ ThemeFont(System, "TkDefaultFont", "TkIconFont"),
+ ThemeFont(EmphasizedSystem, "TkCaptionFont"),
+ ThemeFont(SmallSystem, "TkHeadingFont", "TkTooltipFont"),
+ ThemeFont(SmallEmphasizedSystem),
+ ThemeFont(Application, "TkTextFont"),
+ ThemeFont(Label, "TkSmallCaptionFont"),
+ ThemeFont(Views),
+ ThemeFont(MenuTitle),
+ ThemeFont(MenuItem, "TkMenuFont"),
+ ThemeFont(MenuItemMark),
+ ThemeFont(MenuItemCmdKey),
+ ThemeFont(WindowTitle),
+ ThemeFont(PushButton),
+ ThemeFont(UtilityWindowTitle),
+ ThemeFont(AlertHeader),
+ ThemeFont(Toolbar),
+ ThemeFont(MiniSystem),
+ { kThemeSystemFontDetail, "systemDetailSystemFont" },
+ { kThemeSystemFontDetailEmphasized, "systemDetailEmphasizedSystemFont" },
+ { -1, NULL }
+};
+#undef ThemeFont
+
+static int antialiasedTextEnabled = -1;
+static NSCharacterSet *whitespaceCharacterSet = nil;
+static NSCharacterSet *lineendingCharacterSet = nil;
+
+static void GetTkFontAttributesForNSFont(NSFont *nsFont,
+ TkFontAttributes *faPtr);
+static NSFont * FindNSFont(const char *familyName,
+ NSFontTraitMask traits, NSInteger weight,
+ CGFloat size, int fallbackToDefault);
+static void InitFont(NSFont *nsFont,
+ const TkFontAttributes *reqFaPtr,
+ MacFont *fontPtr);
+static int CreateNamedSystemFont(Tcl_Interp *interp,
+ Tk_Window tkwin, const char *name,
+ TkFontAttributes *faPtr);
+static void DrawCharsInContext(Display *display, Drawable drawable,
+ GC gc, Tk_Font tkfont, const char *source,
+ int numBytes, int rangeStart, int rangeLength,
+ int x, int y, double angle);
+
+#pragma mark -
+#pragma mark Font Helpers:
+
+#define GetNSFontTraitsFromTkFontAttributes(faPtr) \
+ ((faPtr)->weight == TK_FW_BOLD ? NSBoldFontMask : NSUnboldFontMask) | \
+ ((faPtr)->slant == TK_FS_ITALIC ? NSItalicFontMask : NSUnitalicFontMask)
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GetTkFontAttributesForNSFont --
+ *
+ * Fill in TkFontAttributes for given NSFont.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+GetTkFontAttributesForNSFont(
+ NSFont *nsFont,
+ TkFontAttributes *faPtr)
+{
+ NSFontTraitMask traits = [[NSFontManager sharedFontManager]
+ traitsOfFont:nsFont];
+
+ faPtr->family = Tk_GetUid([[nsFont familyName] UTF8String]);
+ faPtr->size = [nsFont pointSize];
+ faPtr->weight = (traits & NSBoldFontMask ? TK_FW_BOLD : TK_FW_NORMAL);
+ faPtr->slant = (traits & NSItalicFontMask ? TK_FS_ITALIC : TK_FS_ROMAN);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FindNSFont --
+ *
+ * Find NSFont for given attributes. Use default values for missing
+ * attributes, and do a case-insensitive search for font family names
+ * if necessary. If fallbackToDefault flag is set, use the system font
+ * as a last resort.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static NSFont *
+FindNSFont(
+ const char *familyName,
+ NSFontTraitMask traits,
+ NSInteger weight,
+ CGFloat size,
+ int fallbackToDefault)
+{
+ NSFontManager *fm = [NSFontManager sharedFontManager];
+ NSFont *nsFont, *dflt = nil;
+ #define defaultFont (dflt ? dflt : (dflt = [NSFont systemFontOfSize:0]))
+ NSString *family;
+
+ if (familyName) {
+ family = [[[NSString alloc] initWithUTF8String:familyName] autorelease];
+ } else {
+ family = [defaultFont familyName];
+ }
+ if (size == 0.0) {
+ size = [defaultFont pointSize];
+ }
+ nsFont = [fm fontWithFamily:family traits:traits weight:weight size:size];
+ if (!nsFont) {
+ NSArray *availableFamilies = [fm availableFontFamilies];
+ NSString *caseFamily = nil;
+
+ for (NSString *f in availableFamilies) {
+ if ([family caseInsensitiveCompare:f] == NSOrderedSame) {
+ caseFamily = f;
+ break;
+ }
+ }
+ if (caseFamily) {
+ nsFont = [fm fontWithFamily:caseFamily traits:traits weight:weight
+ size:size];
+ }
+ }
+ if (!nsFont) {
+ nsFont = [NSFont fontWithName:family size:size];
+ }
+ if (!nsFont && fallbackToDefault) {
+ nsFont = [fm convertFont:defaultFont toFamily:family];
+ nsFont = [fm convertFont:nsFont toSize:size];
+ nsFont = [fm convertFont:nsFont toHaveTrait:traits];
+ }
+ [nsFont retain];
+ #undef defaultFont
+ return nsFont;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * InitFont --
+ *
+ * Helper for TkpGetNativeFont() and TkpGetFontFromAttributes().
+ *
+ * Results:
+ * Fills the MacFont structure.
+ *
+ * Side effects:
+ * Memory allocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+InitFont(
+ NSFont *nsFont,
+ const TkFontAttributes *reqFaPtr, /* Can be NULL */
+ MacFont *fontPtr)
+{
+ TkFontAttributes *faPtr;
+ TkFontMetrics *fmPtr;
+ NSDictionary *nsAttributes;
+ NSRect bounds;
+ CGFloat kern = 0.0;
+ NSFontRenderingMode renderingMode = NSFontDefaultRenderingMode;
+ int ascent, descent/*, dontAA*/;
+ static const UniChar ch[] = {'.', 'W', ' ', 0xc4, 0xc1, 0xc2, 0xc3, 0xc7};
+ /* ., W, Space, Auml, Aacute, Acirc, Atilde, Ccedilla */
+#define nCh (sizeof(ch) / sizeof(UniChar))
+ CGGlyph glyphs[nCh];
+ CGRect boundingRects[nCh];
+
+ fontPtr->font.fid = (Font) fontPtr;
+ faPtr = &fontPtr->font.fa;
+ if (reqFaPtr) {
+ *faPtr = *reqFaPtr;
+ } else {
+ TkInitFontAttributes(faPtr);
+ }
+ fontPtr->nsFont = nsFont;
+
+ /*
+ * Some don't like antialiasing on fixed-width even if bigger than limit
+ */
+
+ // dontAA = [nsFont isFixedPitch] && fontPtr->font.fa.size <= 10;
+ if (antialiasedTextEnabled >= 0/* || dontAA*/) {
+ renderingMode = (antialiasedTextEnabled == 0/* || dontAA*/) ?
+ NSFontIntegerAdvancementsRenderingMode :
+ NSFontAntialiasedRenderingMode;
+ }
+ nsFont = [nsFont screenFontWithRenderingMode:renderingMode];
+ GetTkFontAttributesForNSFont(nsFont, faPtr);
+ fmPtr = &fontPtr->font.fm;
+ fmPtr->ascent = floor([nsFont ascender] + [nsFont leading] + 0.5);
+ fmPtr->descent = floor(-[nsFont descender] + 0.5);
+ fmPtr->maxWidth = [nsFont maximumAdvancement].width;
+ fmPtr->fixed = [nsFont isFixedPitch]; /* Does not work for all fonts */
+
+ /*
+ * The ascent, descent and fixed fields are not correct for all fonts, as
+ * a workaround deduce that info from the metrics of some typical glyphs,
+ * along with screenfont kerning (space advance difference to printer font)
+ */
+
+ bounds = [nsFont boundingRectForFont];
+ if (CTFontGetGlyphsForCharacters((CTFontRef) nsFont, ch, glyphs, nCh)) {
+ fmPtr->fixed = [nsFont advancementForGlyph:glyphs[0]].width ==
+ [nsFont advancementForGlyph:glyphs[1]].width;
+ bounds = NSRectFromCGRect(CTFontGetBoundingRectsForGlyphs((CTFontRef)
+ nsFont, defaultOrientation, ch, boundingRects, nCh));
+ kern = [nsFont advancementForGlyph:glyphs[2]].width -
+ [fontPtr->nsFont advancementForGlyph:glyphs[2]].width;
+ }
+ descent = floor(-bounds.origin.y + 0.5);
+ ascent = floor(bounds.size.height + bounds.origin.y + 0.5);
+ if (ascent > fmPtr->ascent) {
+ fmPtr->ascent = ascent;
+ }
+ if (descent > fmPtr->descent) {
+ fmPtr->descent = descent;
+ }
+ nsAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
+ nsFont, NSFontAttributeName,
+ [NSNumber numberWithInt:faPtr->underline ?
+ NSUnderlineStyleSingle|NSUnderlinePatternSolid :
+ NSUnderlineStyleNone], NSUnderlineStyleAttributeName,
+ [NSNumber numberWithInt:faPtr->overstrike ?
+ NSUnderlineStyleSingle|NSUnderlinePatternSolid :
+ NSUnderlineStyleNone], NSStrikethroughStyleAttributeName,
+ [NSNumber numberWithInt:fmPtr->fixed ? 0 : 1],
+ NSLigatureAttributeName,
+ [NSNumber numberWithDouble:kern], NSKernAttributeName, nil];
+ fontPtr->nsAttributes = [nsAttributes retain];
+#undef nCh
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * CreateNamedSystemFont --
+ *
+ * Register a system font with the Tk named font mechanism.
+ *
+ * Results:
+ *
+ * Result from TkCreateNamedFont().
+ *
+ * Side effects:
+ *
+ * A new named font is added to the Tk font registry.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static int
+CreateNamedSystemFont(
+ Tcl_Interp *interp,
+ Tk_Window tkwin,
+ const char* name,
+ TkFontAttributes *faPtr)
+{
+ TkDeleteNamedFont(NULL, tkwin, name);
+ return TkCreateNamedFont(interp, tkwin, name, faPtr);
+}
+
+#pragma mark -
+#pragma mark Font handling:
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * 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.
+ * Note that this is called before TkpInit() !
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Initialize named system fonts.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+void
+TkpFontPkgInit(
+ TkMainInfo *mainPtr) /* The application being created. */
+{
+ Tcl_Interp *interp = mainPtr->interp;
+ Tk_Window tkwin = (Tk_Window) mainPtr->winPtr;
+ const struct SystemFontMapEntry *systemFont = systemFontMap;
+ NSFont *nsFont;
+ TkFontAttributes fa;
+ NSMutableCharacterSet *cs;
+ /*
+ * Since we called before TkpInit, we need our own autorelease pool.
+ */
+ NSAutoreleasePool *pool = [NSAutoreleasePool new];
+
+ /*
+ * Force this for now.
+ */
+ if (!mainPtr->winPtr->mainPtr) {
+ mainPtr->winPtr->mainPtr = mainPtr;
+ }
+ while (systemFont->systemName) {
+ nsFont = (NSFont*) CTFontCreateUIFontForLanguage(
+ HIThemeGetUIFontType(systemFont->id), 0, NULL);
+ if (nsFont) {
+ TkInitFontAttributes(&fa);
+ GetTkFontAttributesForNSFont(nsFont, &fa);
+ CreateNamedSystemFont(interp, tkwin, systemFont->systemName, &fa);
+ if (systemFont->tkName) {
+ CreateNamedSystemFont(interp, tkwin, systemFont->tkName, &fa);
+ }
+ if (systemFont->tkName1) {
+ CreateNamedSystemFont(interp, tkwin, systemFont->tkName1, &fa);
+ }
+ CFRelease(nsFont);
+ }
+ systemFont++;
+ }
+ TkInitFontAttributes(&fa);
+ nsFont = (NSFont*) CTFontCreateUIFontForLanguage(fixedPitch, 11, NULL);
+ if (nsFont) {
+ GetTkFontAttributesForNSFont(nsFont, &fa);
+ CFRelease(nsFont);
+ } else {
+ fa.family = Tk_GetUid("Monaco");
+ fa.size = 11;
+ fa.weight = TK_FW_NORMAL;
+ fa.slant = TK_FS_ROMAN;
+ }
+ CreateNamedSystemFont(interp, tkwin, "TkFixedFont", &fa);
+ if (!whitespaceCharacterSet) {
+ whitespaceCharacterSet = [[NSCharacterSet
+ whitespaceAndNewlineCharacterSet] retain];
+ cs = [whitespaceCharacterSet mutableCopy];
+ [cs removeCharactersInString:@" "];
+ lineendingCharacterSet = [cs copy];
+ [cs release];
+ }
+ [pool drain];
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * 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. */
+{
+ MacFont *fontPtr = NULL;
+ ThemeFontID themeFontId;
+ CTFontRef ctFont;
+
+ if (strcmp(name, SYSTEMFONT_NAME) == 0) {
+ themeFontId = kThemeSystemFont;
+ } else if (strcmp(name, APPLFONT_NAME) == 0) {
+ themeFontId = kThemeApplicationFont;
+ } else if (strcmp(name, MENUITEMFONT_NAME) == 0) {
+ themeFontId = kThemeMenuItemFont;
+ } else {
+ return NULL;
+ }
+ ctFont = CTFontCreateUIFontForLanguage(
+ HIThemeGetUIFontType(themeFontId), 0, NULL);
+ if (ctFont) {
+ fontPtr = ckalloc(sizeof(MacFont));
+ InitFont((NSFont*) ctFont, NULL, 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. */
+{
+ MacFont *fontPtr;
+ int points = (int) (TkFontGetPoints(tkwin, faPtr->size) + 0.5);
+ NSFontTraitMask traits = GetNSFontTraitsFromTkFontAttributes(faPtr);
+ NSInteger weight = (faPtr->weight == TK_FW_BOLD ? 9 : 5);
+ NSFont *nsFont;
+
+ nsFont = FindNSFont(faPtr->family, traits, weight, points, 0);
+ if (!nsFont) {
+ const char *const *aliases = TkFontGetAliasList(faPtr->family);
+
+ while (aliases && !nsFont) {
+ nsFont = FindNSFont(*aliases++, traits, weight, points, 0);
+ }
+ }
+ if (!nsFont) {
+ nsFont = FindNSFont(faPtr->family, traits, weight, points, 1);
+ }
+ if (!nsFont) {
+ Tcl_Panic("Could not determine NSFont from TkFontAttributes");
+ }
+ if (tkFontPtr == NULL) {
+ fontPtr = ckalloc(sizeof(MacFont));
+ } else {
+ fontPtr = (MacFont *) tkFontPtr;
+ TkpDeleteFont(tkFontPtr);
+ }
+ CFRetain(nsFont); /* Always needed to allow unconditional CFRelease below */
+ InitFont(nsFont, faPtr, 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:
+ * TkFont is deallocated.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+TkpDeleteFont(
+ TkFont *tkFontPtr) /* Token of font to be deleted. */
+{
+ MacFont *fontPtr = (MacFont *) tkFontPtr;
+
+ [fontPtr->nsAttributes release];
+ fontPtr->nsAttributes = NULL;
+ CFRelease(fontPtr->nsFont); /* Either a CTFontRef or a CFRetained NSFont */
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * 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. */
+{
+ Tcl_Obj *resultPtr = Tcl_NewListObj(0, NULL);
+ NSArray *list = [[NSFontManager sharedFontManager] availableFontFamilies];
+
+ for (NSString *family in list) {
+ Tcl_ListObjAppendElement(NULL, resultPtr,
+ Tcl_NewStringObj([family UTF8String], -1));
+ }
+ Tcl_SetObjResult(interp, resultPtr);
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * 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(
+ Tcl_Interp *interp, /* Interp to hold result. */
+ Tk_Font tkfont) /* Font object to query. */
+{
+ MacFont *fontPtr = (MacFont *) tkfont;
+ Tcl_Obj *resultPtr = Tcl_NewListObj(0, NULL);
+
+ if (fontPtr->nsFont) {
+ NSArray *list = [[fontPtr->nsFont fontDescriptor]
+ objectForKey:NSFontCascadeListAttribute];
+
+ for (NSFontDescriptor *subFontDesc in list) {
+ NSString *family = [subFontDesc objectForKey:NSFontFamilyAttribute];
+
+ if (family) {
+ Tcl_ListObjAppendElement(NULL, resultPtr,
+ Tcl_NewStringObj([family UTF8String], -1));
+ }
+ }
+ }
+ Tcl_SetObjResult(interp, resultPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpGetFontAttrsForChar --
+ *
+ * Retrieve the font attributes of the actual font used to render a given
+ * character.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The font attributes are stored in *faPtr.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpGetFontAttrsForChar(
+ Tk_Window tkwin, /* Window on the font's display */
+ Tk_Font tkfont, /* Font to query */
+ int c, /* Character of interest */
+ TkFontAttributes* faPtr) /* Output: Font attributes */
+{
+ MacFont *fontPtr = (MacFont *) tkfont;
+ NSFont *nsFont = fontPtr->nsFont;
+ *faPtr = fontPtr->font.fa;
+ if (nsFont && ![[nsFont coveredCharacterSet] characterIsMember:c]) {
+ UTF16Char ch = (UTF16Char) c;
+
+ nsFont = [nsFont bestMatchingFontForCharacters:&ch
+ length:1 attributes:nil actualCoveredLength:NULL];
+ if (nsFont) {
+ GetTkFontAttributesForNSFont(nsFont, faPtr);
+ }
+ }
+}
+
+#pragma mark -
+#pragma mark Measuring and drawing:
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * With ATSUI we need the line context to do this right, so we have the
+ * actual implementation in TkpMeasureCharsInContext().
+ *
+ * Results:
+ * The return value is the number of bytes from source that fit into the
+ * span that extends from 0 to maxLength. *lengthPtr is filled with the
+ * x-coordinate of the right edge of the last character that did fit.
+ *
+ * Side effects:
+ * None.
+ *
+ * Todo:
+ * Effects of the "flags" parameter are untested.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+Tk_MeasureChars(
+ Tk_Font tkfont, /* Font in which characters will be drawn. */
+ const char *source, /* UTF-8 string to be displayed. Need not be
+ * '\0' terminated. */
+ int numBytes, /* Maximum number of bytes to consider from
+ * source string. */
+ int maxLength, /* If >= 0, maxLength specifies the longest
+ * permissible line length; don't consider any
+ * character that would cross this x-position.
+ * If < 0, then line length is unbounded and
+ * the flags argument is ignored. */
+ int flags, /* Various flag bits OR-ed together:
+ * TK_PARTIAL_OK means include the last char
+ * which only partially fit on this line.
+ * TK_WHOLE_WORDS means stop on a word
+ * boundary, if possible. TK_AT_LEAST_ONE
+ * means return at least one character even if
+ * no characters fit. */
+ int *lengthPtr) /* Filled with x-location just after the
+ * terminating character. */
+{
+ return TkpMeasureCharsInContext(tkfont, source, numBytes, 0, numBytes,
+ maxLength, flags, lengthPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkpMeasureCharsInContext --
+ *
+ * Determine the number of bytes from the string that will fit in the
+ * given horizontal span. The measurement is done under the assumption
+ * that TkpDrawCharsInContext() will be used to actually display the
+ * characters.
+ *
+ * This one is almost the same as Tk_MeasureChars(), but with access to
+ * all the characters on the line for context.
+ *
+ * Results:
+ * The return value is the number of bytes from source that fit into the
+ * span that extends from 0 to maxLength. *lengthPtr is filled with the
+ * x-coordinate of the right edge of the last character that did fit.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TkpMeasureCharsInContext(
+ Tk_Font tkfont, /* Font in which characters will be drawn. */
+ const char * source, /* UTF-8 string to be displayed. Need not be
+ * '\0' terminated. */
+ int numBytes, /* Maximum number of bytes to consider from
+ * source string in all. */
+ int rangeStart, /* Index of first byte to measure. */
+ int rangeLength, /* Length of range to measure in bytes. */
+ int maxLength, /* If >= 0, maxLength specifies the longest
+ * permissible line length; don't consider any
+ * character that would cross this x-position.
+ * If < 0, then line length is unbounded and
+ * the flags argument is ignored. */
+ int flags, /* Various flag bits OR-ed together:
+ * TK_PARTIAL_OK means include the last char
+ * which only partially fits on this line.
+ * TK_WHOLE_WORDS means stop on a word
+ * boundary, if possible. TK_AT_LEAST_ONE means
+ * return at least one character even if no
+ * characters fit. If TK_WHOLE_WORDS and
+ * TK_AT_LEAST_ONE are set and the first word
+ * doesn't fit, we return at least one
+ * character or whatever characters fit into
+ * maxLength. TK_ISOLATE_END means that the
+ * last character should not be considered in
+ * context with the rest of the string (used
+ * for breaking lines). */
+ int *lengthPtr) /* Filled with x-location just after the
+ * terminating character. */
+{
+ const MacFont *fontPtr = (const MacFont *) tkfont;
+ NSString *string;
+ NSAttributedString *attributedString;
+ CTTypesetterRef typesetter;
+ CFIndex start, len;
+ CFRange range = {0, 0};
+ CTLineRef line;
+ CGFloat offset = 0;
+ CFIndex index;
+ double width;
+ int length, fit;
+
+ if (rangeStart < 0 || rangeLength <= 0 ||
+ rangeStart + rangeLength > numBytes ||
+ (maxLength == 0 && !(flags & TK_AT_LEAST_ONE))) {
+ *lengthPtr = 0;
+ return 0;
+ }
+ if (maxLength > 32767) {
+ maxLength = 32767;
+ }
+ string = [[NSString alloc] initWithBytesNoCopy:(void*)source
+ length:numBytes encoding:NSUTF8StringEncoding freeWhenDone:NO];
+ if (!string) {
+ length = 0;
+ fit = rangeLength;
+ goto done;
+ }
+ attributedString = [[NSAttributedString alloc] initWithString:string
+ attributes:fontPtr->nsAttributes];
+ typesetter = CTTypesetterCreateWithAttributedString(
+ (CFAttributedStringRef)attributedString);
+ start = Tcl_NumUtfChars(source, rangeStart);
+ len = Tcl_NumUtfChars(source + rangeStart, rangeLength);
+ if (start > 0) {
+ range.length = start;
+ line = CTTypesetterCreateLine(typesetter, range);
+ offset = CTLineGetTypographicBounds(line, NULL, NULL, NULL);
+ CFRelease(line);
+ }
+ if (maxLength < 0) {
+ index = len;
+ range.length = len;
+ line = CTTypesetterCreateLine(typesetter, range);
+ width = CTLineGetTypographicBounds(line, NULL, NULL, NULL);
+ CFRelease(line);
+ } else {
+ double maxWidth = maxLength + offset;
+ NSCharacterSet *cs;
+
+ /*
+ * Get a line breakpoint in the source string.
+ */
+
+ index = start;
+ if (flags & TK_WHOLE_WORDS) {
+ index = CTTypesetterSuggestLineBreak(typesetter, start, maxWidth);
+ if (index <= start && (flags & TK_AT_LEAST_ONE)) {
+ flags &= ~TK_WHOLE_WORDS;
+ }
+ }
+ if (index <= start && !(flags & TK_WHOLE_WORDS)) {
+ index = CTTypesetterSuggestClusterBreak(typesetter, start, maxWidth);
+ }
+
+ /*
+ * Trim right whitespace/lineending characters.
+ */
+
+ cs = (index <= len && (flags & TK_WHOLE_WORDS)) ?
+ whitespaceCharacterSet : lineendingCharacterSet;
+ while (index > start &&
+ [cs characterIsMember:[string characterAtIndex:(index - 1)]]) {
+ index--;
+ }
+
+ /*
+ * If there is no line breakpoint in the source string between its
+ * start and the index position that fits in maxWidth, then
+ * CTTypesetterSuggestLineBreak() returns that very last index.
+ * However if the TK_WHOLE_WORDS flag is set, we want to break at a
+ * word boundary. In this situation, unless TK_AT_LEAST_ONE is set, we
+ * must report that zero chars actually fit (in other words the
+ * smallest word of the source string is still larger than maxWidth).
+ */
+
+ if ((index >= start) && (index < len) &&
+ (flags & TK_WHOLE_WORDS) && !(flags & TK_AT_LEAST_ONE) &&
+ ![cs characterIsMember:[string characterAtIndex:index]]) {
+ index = start;
+ }
+
+ if (index <= start && (flags & TK_AT_LEAST_ONE)) {
+ index = start + 1;
+ }
+
+ /*
+ * Now measure the string width in pixels.
+ */
+
+ if (index > 0) {
+ range.length = index;
+ line = CTTypesetterCreateLine(typesetter, range);
+ width = CTLineGetTypographicBounds(line, NULL, NULL, NULL);
+ CFRelease(line);
+ } else {
+ width = 0;
+ }
+ if (width < maxWidth && (flags & TK_PARTIAL_OK) && index < len) {
+ range.length = ++index;
+ line = CTTypesetterCreateLine(typesetter, range);
+ width = CTLineGetTypographicBounds(line, NULL, NULL, NULL);
+ CFRelease(line);
+ }
+
+ /*
+ * The call to CTTypesetterSuggestClusterBreak above will always return
+ * at least one character regardless of whether it exceeded it or not.
+ * Clean that up now.
+ */
+
+ while (width > maxWidth && !(flags & TK_PARTIAL_OK)
+ && index > start+(flags & TK_AT_LEAST_ONE)) {
+ range.length = --index;
+ line = CTTypesetterCreateLine(typesetter, range);
+ width = CTLineGetTypographicBounds(line, NULL, NULL, NULL);
+ CFRelease(line);
+ }
+
+ }
+ CFRelease(typesetter);
+ [attributedString release];
+ [string release];
+ length = ceil(width - offset);
+ fit = (Tcl_UtfAtIndex(source, index) - source) - rangeStart;
+done:
+#ifdef TK_MAC_DEBUG_FONTS
+ TkMacOSXDbgMsg("measure: source=\"%s\" range=\"%.*s\" maxLength=%d "
+ "flags='%s%s%s%s' -> width=%d bytesFit=%d\n", source, rangeLength,
+ source+rangeStart, maxLength,
+ flags & TK_PARTIAL_OK ? "partialOk " : "",
+ flags & TK_WHOLE_WORDS ? "wholeWords " : "",
+ flags & TK_AT_LEAST_ONE ? "atLeastOne " : "",
+ flags & TK_ISOLATE_END ? "isolateEnd " : "",
+ length, fit);
+#endif
+ *lengthPtr = length;
+ return fit;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_DrawChars --
+ *
+ * Draw a string of characters on the screen.
+ *
+ * With ATSUI we need the line context to do this right, so we have the
+ * actual implementation in TkpDrawCharsInContext().
+ *
+ * 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 the
+ * string when drawing. */
+{
+ DrawCharsInContext(display, drawable, gc, tkfont, source, numBytes,
+ 0, numBytes, x, y, 0.0);
+}
+
+void
+TkDrawAngledChars(
+ 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. */
+ double x, double y, /* Coordinates at which to place origin of
+ * string when drawing. */
+ double angle) /* What angle to put text at, in degrees. */
+{
+ DrawCharsInContext(display, drawable, gc, tkfont, source, numBytes,
+ 0, numBytes, x, y, angle);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkpDrawCharsInContext --
+ *
+ * Draw a string of characters on the screen like Tk_DrawChars(), with
+ * access to all the characters on the line for context.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Information gets drawn on the screen.
+ *
+ * Todo:
+ * Stippled text drawing.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+TkpDrawCharsInContext(
+ Display *display, /* Display on which to draw. */
+ Drawable drawable, /* Window or pixmap in which to draw. */
+ GC gc, /* Graphics context for drawing characters. */
+ Tk_Font tkfont, /* Font in which characters will be drawn; must
+ * be the same as font used in GC. */
+ const char * source, /* UTF-8 string to be displayed. Need not be
+ * '\0' terminated. All Tk meta-characters
+ * (tabs, control characters, and newlines)
+ * should be stripped out of the string that is
+ * passed to this function. If they are not
+ * stripped out, they will be displayed as
+ * regular printing characters. */
+ int numBytes, /* Number of bytes in string. */
+ int rangeStart, /* Index of first byte to draw. */
+ int rangeLength, /* Length of range to draw in bytes. */
+ int x, int y) /* Coordinates at which to place origin of the
+ * whole (not just the range) string when
+ * drawing. */
+{
+ DrawCharsInContext(display, drawable, gc, tkfont, source, numBytes,
+ rangeStart, rangeLength, x, y, 0.0);
+}
+
+static void
+DrawCharsInContext(
+ Display *display, /* Display on which to draw. */
+ Drawable drawable, /* Window or pixmap in which to draw. */
+ GC gc, /* Graphics context for drawing characters. */
+ Tk_Font tkfont, /* Font in which characters will be drawn; must
+ * be the same as font used in GC. */
+ const char * source, /* UTF-8 string to be displayed. Need not be
+ * '\0' terminated. All Tk meta-characters
+ * (tabs, control characters, and newlines)
+ * should be stripped out of the string that is
+ * passed to this function. If they are not
+ * stripped out, they will be displayed as
+ * regular printing characters. */
+ int numBytes, /* Number of bytes in string. */
+ int rangeStart, /* Index of first byte to draw. */
+ int rangeLength, /* Length of range to draw in bytes. */
+ int x, int y, /* Coordinates at which to place origin of the
+ * whole (not just the range) string when
+ * drawing. */
+ double angle)
+{
+ const MacFont *fontPtr = (const MacFont *) tkfont;
+ NSString *string;
+ NSMutableDictionary *attributes;
+ NSAttributedString *attributedString;
+ CTTypesetterRef typesetter;
+ CFIndex start, len;
+ CTLineRef line;
+ MacDrawable *macWin = (MacDrawable *) drawable;
+ TkMacOSXDrawingContext drawingContext;
+ CGContextRef context;
+ CGColorRef fg;
+ NSFont *nsFont;
+ CGAffineTransform t;
+ int h;
+
+ if (rangeStart < 0 || rangeLength <= 0 ||
+ rangeStart + rangeLength > numBytes ||
+ !TkMacOSXSetupDrawingContext(drawable, gc, 1, &drawingContext)) {
+ return;
+ }
+ string = [[NSString alloc] initWithBytesNoCopy:(void*)source
+ length:numBytes encoding:NSUTF8StringEncoding freeWhenDone:NO];
+ if (!string) {
+ return;
+ }
+
+ context = drawingContext.context;
+ fg = TkMacOSXCreateCGColor(gc, gc->foreground);
+ attributes = [fontPtr->nsAttributes mutableCopy];
+ [attributes setObject:(id)fg forKey:(id)kCTForegroundColorAttributeName];
+ CFRelease(fg);
+ nsFont = [attributes objectForKey:NSFontAttributeName];
+ [nsFont setInContext:[NSGraphicsContext graphicsContextWithGraphicsPort:
+ context flipped:NO]];
+ CGContextSetTextMatrix(context, CGAffineTransformIdentity);
+ attributedString = [[NSAttributedString alloc] initWithString:string
+ attributes:attributes];
+ typesetter = CTTypesetterCreateWithAttributedString(
+ (CFAttributedStringRef)attributedString);
+ x += macWin->xOff;
+ y += macWin->yOff;
+ h = drawingContext.portBounds.size.height;
+ y = h - y;
+ t = CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, h);
+ if (angle != 0.0) {
+ t = CGAffineTransformTranslate(CGAffineTransformRotate(
+ CGAffineTransformTranslate(t, x, y), angle*PI/180.0), -x, -y);
+ }
+ CGContextConcatCTM(context, t);
+ CGContextSetTextPosition(context, x, y);
+ start = Tcl_NumUtfChars(source, rangeStart);
+ len = Tcl_NumUtfChars(source, rangeStart + rangeLength);
+ if (start > 0) {
+ CGRect clipRect = CGRectInfinite, startBounds;
+
+ line = CTTypesetterCreateLine(typesetter, CFRangeMake(0, start));
+ startBounds = CTLineGetImageBounds(line, context);
+ CFRelease(line);
+ clipRect.origin.x = startBounds.origin.x + startBounds.size.width;
+ CGContextClipToRect(context, clipRect);
+ }
+ line = CTTypesetterCreateLine(typesetter, CFRangeMake(0, len));
+ CTLineDraw(line, context);
+ CFRelease(line);
+ CFRelease(typesetter);
+ [attributedString release];
+ [string release];
+ [attributes release];
+ TkMacOSXRestoreDrawingContext(&drawingContext);
+}
+
+#pragma mark -
+#pragma mark Accessors:
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkMacOSXNSFontForFont --
+ *
+ * Return an NSFont for the given Tk_Font.
+ *
+ * Results:
+ * NSFont*.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+MODULE_SCOPE NSFont*
+TkMacOSXNSFontForFont(
+ Tk_Font tkfont)
+{
+ return tkfont ? ((MacFont *)tkfont)->nsFont : nil;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkMacOSXNSFontAttributesForFont --
+ *
+ * Return an NSDictionary of font attributes for the given Tk_Font.
+ *
+ * Results:
+ * NSFont*.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+MODULE_SCOPE NSDictionary*
+TkMacOSXNSFontAttributesForFont(
+ Tk_Font tkfont)
+{
+ return tkfont ? ((MacFont *)tkfont)->nsAttributes : nil;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkMacOSXIsCharacterMissing --
+ *
+ * Given a tkFont and a character determine whether the character has
+ * a glyph defined in the font or not.
+ *
+ * Results:
+ * Returns a 1 if the character is missing, a 0 if it is not.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TkMacOSXIsCharacterMissing(
+ Tk_Font tkfont, /* The font we are looking in. */
+ unsigned int searchChar) /* The character we are looking for. */
+{
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXFontDescriptionForNSFontAndNSFontAttributes --
+ *
+ * Get text description of a font specified by NSFont and attributes.
+ *
+ * Results:
+ * List object or NULL.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+MODULE_SCOPE Tcl_Obj *
+TkMacOSXFontDescriptionForNSFontAndNSFontAttributes(
+ NSFont *nsFont,
+ NSDictionary *nsAttributes)
+{
+ Tcl_Obj *objv[6];
+ int i = 0;
+ const char *familyName = [[nsFont familyName] UTF8String];
+
+ if (nsFont && familyName) {
+ NSFontTraitMask traits = [[NSFontManager sharedFontManager]
+ traitsOfFont:nsFont];
+ id underline = [nsAttributes objectForKey:
+ NSUnderlineStyleAttributeName];
+ id strikethrough = [nsAttributes objectForKey:
+ NSStrikethroughStyleAttributeName];
+
+ objv[i++] = Tcl_NewStringObj(familyName, -1);
+ objv[i++] = Tcl_NewIntObj([nsFont pointSize]);
+#define S(s) Tcl_NewStringObj(STRINGIFY(s),(int)(sizeof(STRINGIFY(s))-1))
+ objv[i++] = (traits & NSBoldFontMask) ? S(bold) : S(normal);
+ objv[i++] = (traits & NSItalicFontMask) ? S(italic) : S(roman);
+ if ([underline respondsToSelector:@selector(intValue)] &&
+ ([underline intValue] & (NSUnderlineStyleSingle |
+ NSUnderlineStyleThick | NSUnderlineStyleDouble))) {
+ objv[i++] = S(underline);
+ }
+ if ([strikethrough respondsToSelector:@selector(intValue)] &&
+ ([strikethrough intValue] & (NSUnderlineStyleSingle |
+ NSUnderlineStyleThick | NSUnderlineStyleDouble))) {
+ objv[i++] = S(overstrike);
+ }
+#undef S
+ }
+ return i ? Tcl_NewListObj(i, objv) : NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXUseAntialiasedText --
+ *
+ * Enables or disables application-wide use of antialiased text (where
+ * available). Sets up a linked Tcl global variable to allow disabling of
+ * antialiased text from Tcl.
+ *
+ * The possible values for this variable are:
+ *
+ * -1 - Use system default as configurable in "System Prefs" -> "General".
+ * 0 - Unconditionally disable antialiasing.
+ * 1 - Unconditionally enable antialiasing.
+ *
+ * Results:
+ *
+ * TCL_OK.
+ *
+ * Side effects:
+ *
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+MODULE_SCOPE int
+TkMacOSXUseAntialiasedText(
+ Tcl_Interp * interp, /* The Tcl interpreter to receive the
+ * variable.*/
+ int enable) /* Initial value. */
+{
+ static Boolean initialized = FALSE;
+
+ if (!initialized) {
+ initialized = TRUE;
+
+ if (Tcl_CreateNamespace(interp, "::tk::mac", NULL, NULL) == NULL) {
+ Tcl_ResetResult(interp);
+ }
+ if (Tcl_LinkVar(interp, "::tk::mac::antialiasedtext",
+ (char *) &antialiasedTextEnabled,
+ TCL_LINK_INT) != TCL_OK) {
+ Tcl_ResetResult(interp);
+ }
+ }
+ antialiasedTextEnabled = enable;
+ return TCL_OK;
+}
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXFont.h b/tk8.6/macosx/tkMacOSXFont.h
new file mode 100644
index 0000000..7fc9265
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXFont.h
@@ -0,0 +1,32 @@
+/*
+ * tkMacOSXFont.h --
+ *
+ * Contains the Macintosh implementation of the platform-independent
+ * font package interface.
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright 2001-2009, Apple Inc.
+ * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef TKMACOSXFONT_H
+#define TKMACOSXFONT_H 1
+
+#include "tkFont.h"
+
+#ifndef _TKMACINT
+#include "tkMacOSXInt.h"
+#endif
+
+/*
+ * Function prototypes
+ */
+
+MODULE_SCOPE Tcl_Obj * TkMacOSXFontDescriptionForNSFontAndNSFontAttributes(
+ NSFont *nsFont, NSDictionary *nsAttributes);
+
+#endif /*TKMACOSXFONT_H*/
diff --git a/tk8.6/macosx/tkMacOSXHLEvents.c b/tk8.6/macosx/tkMacOSXHLEvents.c
new file mode 100644
index 0000000..0f63ea6
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXHLEvents.c
@@ -0,0 +1,582 @@
+/*
+ * 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-2009, Apple Inc.
+ * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright (c) 2015 Marc Culler
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkMacOSXPrivate.h"
+#include <sys/param.h>
+#define URL_MAX_LENGTH (17 + MAXPATHLEN)
+
+/*
+ * This is a Tcl_Event structure that the Quit AppleEvent handler uses to
+ * schedule the ReallyKillMe function.
+ */
+
+typedef struct KillEvent {
+ Tcl_Event header; /* Information that is standard for all
+ * events. */
+ Tcl_Interp *interp; /* Interp that was passed to the Quit
+ * AppleEvent */
+} KillEvent;
+
+/*
+ * Static functions used only in this file.
+ */
+
+static void tkMacOSXProcessFiles(NSAppleEventDescriptor* event,
+ NSAppleEventDescriptor* replyEvent,
+ Tcl_Interp *interp,
+ const char* procedure);
+static int MissedAnyParameters(const AppleEvent *theEvent);
+static int ReallyKillMe(Tcl_Event *eventPtr, int flags);
+
+#pragma mark TKApplication(TKHLEvents)
+
+@implementation TKApplication(TKHLEvents)
+- (void) terminate: (id) sender
+{
+ [self handleQuitApplicationEvent:Nil withReplyEvent:Nil];
+}
+
+- (void) preferences: (id) sender
+{
+ [self handleShowPreferencesEvent:Nil withReplyEvent:Nil];
+}
+
+- (void) handleQuitApplicationEvent: (NSAppleEventDescriptor *)event
+ withReplyEvent: (NSAppleEventDescriptor *)replyEvent
+{
+ KillEvent *eventPtr;
+
+ if (_eventInterp) {
+ /*
+ * 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 = ckalloc(sizeof(KillEvent));
+ eventPtr->header.proc = ReallyKillMe;
+ eventPtr->interp = _eventInterp;
+
+ Tcl_QueueEvent((Tcl_Event *) eventPtr, TCL_QUEUE_HEAD);
+ }
+}
+
+- (void) handleOpenApplicationEvent: (NSAppleEventDescriptor *)event
+ withReplyEvent: (NSAppleEventDescriptor *)replyEvent
+{
+ Tcl_Interp *interp = _eventInterp;
+
+ if (interp &&
+ Tcl_FindCommand(_eventInterp, "::tk::mac::OpenApplication", NULL, 0)){
+ int code = Tcl_EvalEx(_eventInterp, "::tk::mac::OpenApplication",
+ -1, TCL_EVAL_GLOBAL);
+ if (code != TCL_OK) {
+ Tcl_BackgroundException(_eventInterp, code);
+ }
+ }
+}
+
+- (void) handleReopenApplicationEvent: (NSAppleEventDescriptor *)event
+ withReplyEvent: (NSAppleEventDescriptor *)replyEvent
+{
+ [NSApp activateIgnoringOtherApps: YES];
+ if (_eventInterp && Tcl_FindCommand(_eventInterp,
+ "::tk::mac::ReopenApplication", NULL, 0)) {
+ int code = Tcl_EvalEx(_eventInterp, "::tk::mac::ReopenApplication",
+ -1, TCL_EVAL_GLOBAL);
+ if (code != TCL_OK){
+ Tcl_BackgroundException(_eventInterp, code);
+ }
+ }
+}
+
+- (void) handleShowPreferencesEvent: (NSAppleEventDescriptor *)event
+ withReplyEvent: (NSAppleEventDescriptor *)replyEvent
+{
+ if (_eventInterp &&
+ Tcl_FindCommand(_eventInterp, "::tk::mac::ShowPreferences", NULL, 0)){
+ int code = Tcl_EvalEx(_eventInterp, "::tk::mac::ShowPreferences",
+ -1, TCL_EVAL_GLOBAL);
+ if (code != TCL_OK) {
+ Tcl_BackgroundException(_eventInterp, code);
+ }
+ }
+}
+
+- (void) handleOpenDocumentsEvent: (NSAppleEventDescriptor *)event
+ withReplyEvent: (NSAppleEventDescriptor *)replyEvent
+{
+ tkMacOSXProcessFiles(event, replyEvent, _eventInterp, "::tk::mac::OpenDocument");
+}
+
+- (void) handlePrintDocumentsEvent: (NSAppleEventDescriptor *)event
+ withReplyEvent: (NSAppleEventDescriptor *)replyEvent
+{
+
+ NSString* file = [[event paramDescriptorForKeyword:keyDirectObject]
+ stringValue];
+ const char *printFile=[file UTF8String];
+ Tcl_DString print;
+ Tcl_DStringInit(&print);
+ if (Tcl_FindCommand(_eventInterp, "::tk::mac::PrintDocument", NULL, 0)) {
+ Tcl_DStringAppend(&print, "::tk::mac::PrintDocument", -1);
+ }
+ Tcl_DStringAppendElement(&print, printFile);
+ int tclErr = Tcl_EvalEx(_eventInterp, Tcl_DStringValue(&print),
+ Tcl_DStringLength(&print), TCL_EVAL_GLOBAL);
+ if (tclErr!= TCL_OK) {
+ Tcl_BackgroundException(_eventInterp, tclErr);
+ }
+}
+
+
+- (void) handleDoScriptEvent: (NSAppleEventDescriptor *)event
+ withReplyEvent: (NSAppleEventDescriptor *)replyEvent
+{
+ OSStatus err;
+ const AEDesc *theDesc = nil;
+ DescType type = 0, initialType = 0;
+ Size actual;
+ int tclErr = -1;
+ char URLBuffer[1 + URL_MAX_LENGTH];
+ char errString[128];
+ char typeString[5];
+
+ /*
+ * The DoScript event receives one parameter that should be text data or a
+ * fileURL.
+ */
+
+ theDesc = [event aeDesc];
+ if (theDesc == nil) {
+ return;
+ }
+
+ err = AEGetParamPtr(theDesc, keyDirectObject, typeWildCard, &initialType,
+ NULL, 0, NULL);
+ if (err != noErr) {
+ sprintf(errString, "AEDoScriptHandler: GetParamDesc error %d", (int)err);
+ AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, typeChar,
+ errString, strlen(errString));
+ return;
+ }
+
+ if (MissedAnyParameters((AppleEvent*)theDesc)) {
+ sprintf(errString, "AEDoScriptHandler: extra parameters");
+ AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, typeChar,
+ errString, strlen(errString));
+ return;
+ }
+
+ if (initialType == typeFileURL || initialType == typeAlias) {
+ /*
+ * The descriptor can be coerced to a file url. Source the file, or
+ * pass the path as a string argument to ::tk::mac::DoScriptFile if
+ * that procedure exists.
+ */
+ err = AEGetParamPtr(theDesc, keyDirectObject, typeFileURL, &type,
+ (Ptr) URLBuffer, URL_MAX_LENGTH, &actual);
+ if (err == noErr && actual > 0){
+ URLBuffer[actual] = '\0';
+ NSString *urlString = [NSString stringWithUTF8String:(char*)URLBuffer];
+ NSURL *fileURL = [NSURL URLWithString:urlString];
+ Tcl_DString command;
+ Tcl_DStringInit(&command);
+ if (Tcl_FindCommand(_eventInterp, "::tk::mac::DoScriptFile", NULL, 0)){
+ Tcl_DStringAppend(&command, "::tk::mac::DoScriptFile", -1);
+ } else {
+ Tcl_DStringAppend(&command, "source", -1);
+ }
+ Tcl_DStringAppendElement(&command, [[fileURL path] UTF8String]);
+ tclErr = Tcl_EvalEx(_eventInterp, Tcl_DStringValue(&command),
+ Tcl_DStringLength(&command), TCL_EVAL_GLOBAL);
+ }
+ } else if (noErr == AEGetParamPtr(theDesc, keyDirectObject, typeUTF8Text, &type,
+ NULL, 0, &actual)) {
+ if (actual > 0) {
+ /*
+ * The descriptor can be coerced to UTF8 text. Evaluate as Tcl, or
+ * or pass the text as a string argument to ::tk::mac::DoScriptText
+ * if that procedure exists.
+ */
+ char *data = ckalloc(actual + 1);
+ if (noErr == AEGetParamPtr(theDesc, keyDirectObject, typeUTF8Text, &type,
+ data, actual, NULL)) {
+ if (Tcl_FindCommand(_eventInterp, "::tk::mac::DoScriptText", NULL, 0)){
+ Tcl_DString command;
+ Tcl_DStringInit(&command);
+ Tcl_DStringAppend(&command, "::tk::mac::DoScriptText", -1);
+ Tcl_DStringAppendElement(&command, data);
+ tclErr = Tcl_EvalEx(_eventInterp, Tcl_DStringValue(&command),
+ Tcl_DStringLength(&command), TCL_EVAL_GLOBAL);
+ } else {
+ tclErr = Tcl_EvalEx(_eventInterp, data, actual, TCL_EVAL_GLOBAL);
+ }
+ }
+ ckfree(data);
+ }
+ } else {
+ /*
+ * The descriptor can not be coerced to a fileURL or UTF8 text.
+ */
+ for (int i = 0; i < 4; i++) {
+ typeString[i] = ((char*)&initialType)[3-i];
+ }
+ typeString[4] = '\0';
+ sprintf(errString, "AEDoScriptHandler: invalid script type '%s', "
+ "must be coercable to 'furl' or 'utf8'", typeString);
+ AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, typeChar, errString,
+ strlen(errString));
+ }
+ /*
+ * If we ran some Tcl code, put the result in the reply.
+ */
+ if (tclErr >= 0) {
+ int reslen;
+ const char *result =
+ Tcl_GetStringFromObj(Tcl_GetObjResult(_eventInterp), &reslen);
+ if (tclErr == TCL_OK) {
+ AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyDirectObject, typeChar,
+ result, reslen);
+ } else {
+ AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, typeChar,
+ result, reslen);
+ AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorNumber, typeSInt32,
+ (Ptr) &tclErr,sizeof(int));
+ }
+ }
+ return;
+}
+
+- (void)handleURLEvent:(NSAppleEventDescriptor*)event
+ withReplyEvent:(NSAppleEventDescriptor*)replyEvent
+{
+ NSString* url = [[event paramDescriptorForKeyword:keyDirectObject]
+ stringValue];
+ const char *cURL=[url UTF8String];
+ Tcl_DString launch;
+ Tcl_DStringInit(&launch);
+ if (Tcl_FindCommand(_eventInterp, "::tk::mac::LaunchURL", NULL, 0)) {
+ Tcl_DStringAppend(&launch, "::tk::mac::LaunchURL", -1);
+ }
+ Tcl_DStringAppendElement(&launch, cURL);
+ int tclErr = Tcl_EvalEx(_eventInterp, Tcl_DStringValue(&launch),
+ Tcl_DStringLength(&launch), TCL_EVAL_GLOBAL);
+ if (tclErr!= TCL_OK) {
+ Tcl_BackgroundException(_eventInterp, tclErr);
+ }
+ }
+
+@end
+
+#pragma mark -
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXProcessFiles --
+ *
+ * Extract a list of fileURLs from an AppleEvent and call the specified
+ * procedure with the file paths as arguments.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The event is handled by running the procedure.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+tkMacOSXProcessFiles(
+ NSAppleEventDescriptor* event,
+ NSAppleEventDescriptor* replyEvent,
+ Tcl_Interp *interp,
+ const char* procedure)
+{
+ Tcl_Encoding utf8;
+ const AEDesc *fileSpecDesc = nil;
+ AEDesc contents;
+ char URLString[1 + URL_MAX_LENGTH];
+ NSURL *fileURL;
+ DescType type;
+ Size actual;
+ long count, index;
+ AEKeyword keyword;
+ Tcl_DString command, pathName;
+ int code;
+
+ /*
+ * Do nothing if we don't have an interpreter or the procedure doesn't exist.
+ */
+
+ if (!interp || !Tcl_FindCommand(interp, procedure, NULL, 0)) {
+ return;
+ }
+
+ fileSpecDesc = [event aeDesc];
+ if (fileSpecDesc == nil ) {
+ return;
+ }
+
+ /*
+ * The AppleEvent's descriptor should either contain a value of
+ * typeObjectSpecifier or typeAEList. In the first case, the descriptor
+ * can be treated as a list of size 1 containing a value which can be
+ * coerced into a fileURL. In the second case we want to work with the list
+ * itself. Values in the list will be coerced into fileURL's if possible;
+ * otherwise they will be ignored.
+ */
+
+ /* Get a copy of the AppleEvent's descriptor. */
+ AEGetParamDesc(fileSpecDesc, keyDirectObject, typeWildCard, &contents);
+ if (contents.descriptorType == typeAEList) {
+ fileSpecDesc = &contents;
+ }
+
+ if (AECountItems(fileSpecDesc, &count) != noErr) {
+ AEDisposeDesc(&contents);
+ return;
+ }
+
+ /*
+ * Construct a Tcl command which calls the procedure, passing the
+ * paths contained in the AppleEvent as arguments.
+ */
+
+ Tcl_DStringInit(&command);
+ Tcl_DStringAppend(&command, procedure, -1);
+ utf8 = Tcl_GetEncoding(NULL, "utf-8");
+
+ for (index = 1; index <= count; index++) {
+ if (noErr != AEGetNthPtr(fileSpecDesc, index, typeFileURL, &keyword,
+ &type, (Ptr) URLString, URL_MAX_LENGTH, &actual)) {
+ continue;
+ }
+ if (type != typeFileURL) {
+ continue;
+ }
+ URLString[actual] = '\0';
+ fileURL = [NSURL URLWithString:[NSString stringWithUTF8String:(char*)URLString]];
+ if (fileURL == nil) {
+ continue;
+ }
+ Tcl_ExternalToUtfDString(utf8, [[fileURL path] UTF8String], -1, &pathName);
+ Tcl_DStringAppendElement(&command, Tcl_DStringValue(&pathName));
+ Tcl_DStringFree(&pathName);
+ }
+
+ Tcl_FreeEncoding(utf8);
+ AEDisposeDesc(&contents);
+
+ /*
+ * Handle the event by evaluating the Tcl expression we constructed.
+ */
+
+ code = Tcl_EvalEx(interp, Tcl_DStringValue(&command),
+ Tcl_DStringLength(&command), TCL_EVAL_GLOBAL);
+ if (code != TCL_OK) {
+ Tcl_BackgroundException(interp, code);
+ }
+ Tcl_DStringFree(&command);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXInitAppleEvents --
+ *
+ * Register AppleEvent handlers with the NSAppleEventManager for
+ * this NSApplication.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXInitAppleEvents(
+ Tcl_Interp *interp) /* not used */
+{
+ NSAppleEventManager *aeManager = [NSAppleEventManager sharedAppleEventManager];
+ static Boolean initialized = FALSE;
+
+ if (!initialized) {
+ initialized = TRUE;
+
+ [aeManager setEventHandler:NSApp
+ andSelector:@selector(handleQuitApplicationEvent:withReplyEvent:)
+ forEventClass:kCoreEventClass andEventID:kAEQuitApplication];
+
+ [aeManager setEventHandler:NSApp
+ andSelector:@selector(handleOpenApplicationEvent:withReplyEvent:)
+ forEventClass:kCoreEventClass andEventID:kAEOpenApplication];
+
+ [aeManager setEventHandler:NSApp
+ andSelector:@selector(handleReopenApplicationEvent:withReplyEvent:)
+ forEventClass:kCoreEventClass andEventID:kAEReopenApplication];
+
+ [aeManager setEventHandler:NSApp
+ andSelector:@selector(handleShowPreferencesEvent:withReplyEvent:)
+ forEventClass:kCoreEventClass andEventID:kAEShowPreferences];
+
+ [aeManager setEventHandler:NSApp
+ andSelector:@selector(handleOpenDocumentsEvent:withReplyEvent:)
+ forEventClass:kCoreEventClass andEventID:kAEOpenDocuments];
+
+ [aeManager setEventHandler:NSApp
+ andSelector:@selector(handlePrintDocumentsEvent:withReplyEvent:)
+ forEventClass:kCoreEventClass andEventID:kAEPrintDocuments];
+
+ [aeManager setEventHandler:NSApp
+ andSelector:@selector(handleDoScriptEvent:withReplyEvent:)
+ forEventClass:kAEMiscStandards andEventID:kAEDoScript];
+
+ [aeManager setEventHandler:NSApp
+ andSelector:@selector(handleURLEvent:withReplyEvent:)
+ forEventClass:kInternetEventClass andEventID:kAEGetURL];
+
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXDoHLEvent --
+ *
+ * Dispatch an AppleEvent.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Depend on the AppleEvent.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkMacOSXDoHLEvent(
+ void *theEvent)
+{
+ /* According to the NSAppleEventManager reference:
+ * "The theReply parameter always specifies a reply Apple event, never
+ * nil. However, the handler should not fill out the reply if the
+ * descriptor type for the reply event is typeNull, indicating the sender
+ * does not want a reply."
+ * The specified way to build such a non-nil descriptor is used here. But
+ * on OSX 10.11, the compiler nonetheless generates a warning. I am
+ * supressing the warning here -- maybe the warnings will stop in a future
+ * compiler release.
+ */
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wnonnull"
+#endif
+
+ NSAppleEventDescriptor* theReply = [NSAppleEventDescriptor nullDescriptor];
+ NSAppleEventManager *aeManager = [NSAppleEventManager sharedAppleEventManager];
+
+ return [aeManager dispatchRawAppleEvent:(const AppleEvent*)theEvent
+ withRawReply: (AppleEvent *)theReply
+ handlerRefCon: (SRefCon)0];
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ReallyKillMe --
+ *
+ * This procedure tries to kill the shell by running exit, called from
+ * an event scheduled by the "Quit" AppleEvent handler.
+ *
+ * Results:
+ * Runs the "exit" command which might kill the shell.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ReallyKillMe(
+ Tcl_Event *eventPtr,
+ int flags)
+{
+ Tcl_Interp *interp = ((KillEvent *) eventPtr)->interp;
+ int quit = Tcl_FindCommand(interp, "::tk::mac::Quit", NULL, 0)!=NULL;
+ int code = Tcl_EvalEx(interp, quit ? "::tk::mac::Quit" : "exit", -1, TCL_EVAL_GLOBAL);
+
+ if (code != TCL_OK) {
+ /*
+ * Should be never reached...
+ */
+
+ Tcl_BackgroundException(interp, code);
+ }
+ 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;
+ OSStatus err;
+
+ err = AEGetAttributePtr(theEvent, keyMissedKeywordAttr,
+ typeWildCard, &returnedType, NULL, 0, &actualSize);
+
+ return (err != errAEDescNotFound);
+}
+
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXImage.c b/tk8.6/macosx/tkMacOSXImage.c
new file mode 100644
index 0000000..36f1fc6
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXImage.c
@@ -0,0 +1,602 @@
+/*
+ * tkMacOSXImage.c --
+ *
+ * The code in this file provides an interface for XImages,
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ * Copyright 2001-2009, Apple Inc.
+ * Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright 2017-2018 Marc Culler.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkMacOSXPrivate.h"
+#include "xbytes.h"
+
+#pragma mark XImage handling
+
+int
+_XInitImageFuncPtrs(
+ XImage *image)
+{
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXCreateCGImageWithXImage --
+ *
+ * Create CGImage from XImage, copying the image data. Called
+ * in Tk_PutImage and (currently) nowhere else.
+ *
+ * Results:
+ * CGImage, release after use.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void ReleaseData(void *info, const void *data, size_t size) {
+ ckfree(info);
+}
+
+CGImageRef
+TkMacOSXCreateCGImageWithXImage(
+ XImage *image)
+{
+ CGImageRef img = NULL;
+ size_t bitsPerComponent, bitsPerPixel;
+ size_t len = image->bytes_per_line * image->height;
+ const CGFloat *decode = NULL;
+ CGBitmapInfo bitmapInfo;
+ CGDataProviderRef provider = NULL;
+ char *data = NULL;
+ CGDataProviderReleaseDataCallback releaseData = ReleaseData;
+
+ if (image->bits_per_pixel == 1) {
+ /*
+ * BW image
+ */
+
+ /* Reverses the sense of the bits */
+ static const CGFloat decodeWB[2] = {1, 0};
+ decode = decodeWB;
+
+ bitsPerComponent = 1;
+ bitsPerPixel = 1;
+ if (image->bitmap_bit_order != MSBFirst) {
+ char *srcPtr = image->data + image->xoffset;
+ char *endPtr = srcPtr + len;
+ char *destPtr = (data = ckalloc(len));
+
+ while (srcPtr < endPtr) {
+ *destPtr++ = xBitReverseTable[(unsigned char)(*(srcPtr++))];
+ }
+ } else {
+ data = memcpy(ckalloc(len), image->data + image->xoffset, len);
+ }
+ if (data) {
+ provider = CGDataProviderCreateWithData(data, data, len,
+ releaseData);
+ }
+ if (provider) {
+ img = CGImageMaskCreate(image->width, image->height,
+ bitsPerComponent, bitsPerPixel, image->bytes_per_line,
+ provider, decode, 0);
+ }
+ } else if ((image->format == ZPixmap) && (image->bits_per_pixel == 32)) {
+ /*
+ * Color image
+ */
+
+ CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
+
+ if (image->width == 0 && image->height == 0) {
+ /*
+ * CGCreateImage complains on early macOS releases.
+ */
+
+ return NULL;
+ }
+ bitsPerComponent = 8;
+ bitsPerPixel = 32;
+ bitmapInfo = (image->byte_order == MSBFirst ?
+ kCGBitmapByteOrder32Little : kCGBitmapByteOrder32Big);
+ bitmapInfo |= kCGImageAlphaLast;
+ data = memcpy(ckalloc(len), image->data + image->xoffset, len);
+ if (data) {
+ provider = CGDataProviderCreateWithData(data, data, len,
+ releaseData);
+ }
+ if (provider) {
+ img = CGImageCreate(image->width, image->height, bitsPerComponent,
+ bitsPerPixel, image->bytes_per_line, colorspace, bitmapInfo,
+ provider, decode, 0, kCGRenderingIntentDefault);
+ CFRelease(provider);
+ }
+ if (colorspace) {
+ CFRelease(colorspace);
+ }
+ } else {
+ TkMacOSXDbgMsg("Unsupported image type");
+ }
+ return img;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XGetImage --
+ *
+ * This function copies data from a pixmap or window into an XImage. It
+ * is essentially never used. At one time it was called by
+ * pTkImgPhotoDisplay, but that is no longer the case. Currently it is
+ * called two places, one of which is requesting an XY image which we do
+ * not support. It probably does not work correctly -- see the comments
+ * for TkMacOSXBitmapRepFromDrawableRect.
+ *
+ * Results:
+ * Returns a newly allocated XImage containing the data from the given
+ * rectangle of the given drawable, or NULL if the XImage could not be
+ * constructed. NOTE: If we are copying from a window on a Retina
+ * display, the dimensions of the XImage will be 2*width x 2*height.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+struct pixel_fmt {int r; int g; int b; int a;};
+static struct pixel_fmt bgra = {2, 1, 0, 3};
+static struct pixel_fmt abgr = {3, 2, 1, 0};
+
+XImage *
+XGetImage(
+ Display *display,
+ Drawable drawable,
+ int x,
+ int y,
+ unsigned int width,
+ unsigned int height,
+ unsigned long plane_mask,
+ int format)
+{
+ NSBitmapImageRep* bitmap_rep = NULL;
+ NSUInteger bitmap_fmt = 0;
+ XImage* imagePtr = NULL;
+ char* bitmap = NULL;
+ char R, G, B, A;
+ int depth = 32, offset = 0, bitmap_pad = 0;
+ unsigned int bytes_per_row, size, row, n, m;
+ unsigned int scalefactor=1, scaled_height=height, scaled_width=width;
+ NSWindow *win = TkMacOSXDrawableWindow(drawable);
+ static enum {unknown, no, yes} has_retina = unknown;
+
+ if (win && has_retina == unknown) {
+#ifdef __clang__
+ has_retina = [win respondsToSelector:@selector(backingScaleFactor)] ?
+ yes : no;
+#else
+ has_retina = no;
+#endif
+ }
+
+ if (has_retina == yes) {
+ /*
+ * We only allow scale factors 1 or 2, as Apple currently does.
+ */
+
+#ifdef __clang__
+ scalefactor = [win backingScaleFactor] == 2.0 ? 2 : 1;
+#endif
+ scaled_height *= scalefactor;
+ scaled_width *= scalefactor;
+ }
+
+ if (format == ZPixmap) {
+ if (width == 0 || height == 0) {
+ return NULL;
+ }
+
+ bitmap_rep = TkMacOSXBitmapRepFromDrawableRect(drawable,
+ x, y, width, height);
+ if (!bitmap_rep) {
+ TkMacOSXDbgMsg("XGetImage: Failed to construct NSBitmapRep");
+ return NULL;
+ }
+ bitmap_fmt = [bitmap_rep bitmapFormat];
+ size = [bitmap_rep bytesPerPlane];
+ bytes_per_row = [bitmap_rep bytesPerRow];
+ bitmap = ckalloc(size);
+ if (!bitmap
+ || (bitmap_fmt != 0 && bitmap_fmt != 1)
+ || [bitmap_rep samplesPerPixel] != 4
+ || [bitmap_rep isPlanar] != 0
+ || bytes_per_row < 4 * scaled_width
+ || size != bytes_per_row * scaled_height) {
+ TkMacOSXDbgMsg("XGetImage: Unrecognized bitmap format");
+ CFRelease(bitmap_rep);
+ return NULL;
+ }
+ memcpy(bitmap, (char *)[bitmap_rep bitmapData], size);
+ CFRelease(bitmap_rep);
+
+ /*
+ * When Apple extracts a bitmap from an NSView, it may be in either
+ * BGRA or ABGR format. For an XImage we need RGBA.
+ */
+
+ struct pixel_fmt pixel = bitmap_fmt == 0 ? bgra : abgr;
+
+ for (row = 0, n = 0; row < scaled_height; row++, n += bytes_per_row) {
+ for (m = n; m < n + 4*scaled_width; m += 4) {
+ R = *(bitmap + m + pixel.r);
+ G = *(bitmap + m + pixel.g);
+ B = *(bitmap + m + pixel.b);
+ A = *(bitmap + m + pixel.a);
+
+ *(bitmap + m) = R;
+ *(bitmap + m + 1) = G;
+ *(bitmap + m + 2) = B;
+ *(bitmap + m + 3) = A;
+ }
+ }
+ imagePtr = XCreateImage(display, NULL, depth, format, offset,
+ (char*) bitmap, scaled_width, scaled_height,
+ bitmap_pad, bytes_per_row);
+ if (scalefactor == 2) {
+ imagePtr->pixelpower = 1;
+ }
+ } else {
+ /*
+ * There are some calls to XGetImage in the generic Tk code which pass
+ * an XYPixmap rather than a ZPixmap. XYPixmaps should be handled
+ * here.
+ */
+ TkMacOSXDbgMsg("XGetImage does not handle XYPixmaps at the moment.");
+ }
+ return imagePtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyImage --
+ *
+ * Destroys storage associated with an image.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Deallocates the image.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DestroyImage(
+ XImage *image)
+{
+ if (image) {
+ if (image->data) {
+ ckfree(image->data);
+ }
+ ckfree(image);
+ }
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImageGetPixel --
+ *
+ * Get a single pixel from an image.
+ *
+ * Results:
+ * Returns the 32 bit pixel value.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static unsigned long
+ImageGetPixel(
+ XImage *image,
+ int x,
+ int y)
+{
+ unsigned char r = 0, g = 0, b = 0;
+
+ if (image && image->data) {
+ unsigned char *srcPtr = ((unsigned char*) image->data)
+ + (y * image->bytes_per_line)
+ + (((image->xoffset + x) * image->bits_per_pixel) / NBBY);
+
+ switch (image->bits_per_pixel) {
+ case 32:
+ r = (*((unsigned int*) srcPtr) >> 16) & 0xff;
+ g = (*((unsigned int*) srcPtr) >> 8) & 0xff;
+ b = (*((unsigned int*) srcPtr) ) & 0xff;
+ /*if (image->byte_order == LSBFirst) {
+ r = srcPtr[2]; g = srcPtr[1]; b = srcPtr[0];
+ } else {
+ r = srcPtr[1]; g = srcPtr[2]; b = srcPtr[3];
+ }*/
+ break;
+ case 16:
+ r = (*((unsigned short*) srcPtr) >> 7) & 0xf8;
+ g = (*((unsigned short*) srcPtr) >> 2) & 0xf8;
+ b = (*((unsigned short*) srcPtr) << 3) & 0xf8;
+ break;
+ case 8:
+ r = (*srcPtr << 2) & 0xc0;
+ g = (*srcPtr << 4) & 0xc0;
+ b = (*srcPtr << 6) & 0xc0;
+ r |= r >> 2 | r >> 4 | r >> 6;
+ g |= g >> 2 | g >> 4 | g >> 6;
+ b |= b >> 2 | b >> 4 | b >> 6;
+ break;
+ case 4: {
+ unsigned char c = (x % 2) ? *srcPtr : (*srcPtr >> 4);
+
+ r = (c & 0x04) ? 0xff : 0;
+ g = (c & 0x02) ? 0xff : 0;
+ b = (c & 0x01) ? 0xff : 0;
+ break;
+ }
+ case 1:
+ r = g = b = ((*srcPtr) & (0x80 >> (x % 8))) ? 0xff : 0;
+ break;
+ }
+ }
+ return (PIXEL_MAGIC << 24) | (r << 16) | (g << 8) | b;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImagePutPixel --
+ *
+ * Set a single pixel in an image.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ImagePutPixel(
+ XImage *image,
+ int x,
+ int y,
+ unsigned long pixel)
+{
+ if (image && image->data) {
+ unsigned char *dstPtr = ((unsigned char*) image->data)
+ + (y * image->bytes_per_line)
+ + (((image->xoffset + x) * image->bits_per_pixel) / NBBY);
+
+ if (image->bits_per_pixel == 32) {
+ *((unsigned int*) dstPtr) = pixel;
+ } else {
+ unsigned char r = ((pixel & image->red_mask) >> 16) & 0xff;
+ unsigned char g = ((pixel & image->green_mask) >> 8) & 0xff;
+ unsigned char b = ((pixel & image->blue_mask) ) & 0xff;
+ switch (image->bits_per_pixel) {
+ case 16:
+ *((unsigned short*) dstPtr) = ((r & 0xf8) << 7) |
+ ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
+ break;
+ case 8:
+ *dstPtr = ((r & 0xc0) >> 2) | ((g & 0xc0) >> 4) |
+ ((b & 0xc0) >> 6);
+ break;
+ case 4: {
+ unsigned char c = ((r & 0x80) >> 5) | ((g & 0x80) >> 6) |
+ ((b & 0x80) >> 7);
+ *dstPtr = (x % 2) ? ((*dstPtr & 0xf0) | (c & 0x0f)) :
+ ((*dstPtr & 0x0f) | ((c << 4) & 0xf0));
+ break;
+ }
+ case 1:
+ *dstPtr = ((r|g|b) & 0x80) ? (*dstPtr | (0x80 >> (x % 8))) :
+ (*dstPtr & ~(0x80 >> (x % 8)));
+ break;
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XCreateImage --
+ *
+ * Allocates storage for a new XImage.
+ *
+ * Results:
+ * Returns a newly allocated XImage.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+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 = ckalloc(sizeof(XImage));
+
+ ximage->height = height;
+ ximage->width = width;
+ ximage->depth = depth;
+ ximage->xoffset = offset;
+ ximage->format = format;
+ ximage->data = data;
+ ximage->obdata = NULL;
+
+ /*
+ * The default pixelpower is 0. This must be explicitly set to 1 in the
+ * case of an XImage extracted from a Retina display.
+ */
+
+ ximage->pixelpower = 0;
+
+ if (format == ZPixmap) {
+ ximage->bits_per_pixel = 32;
+ ximage->bitmap_unit = 32;
+ } else {
+ ximage->bits_per_pixel = 1;
+ ximage->bitmap_unit = 8;
+ }
+ if (bitmap_pad) {
+ ximage->bitmap_pad = bitmap_pad;
+ } else {
+ /*
+ * Use 16 byte alignment for best Quartz perfomance.
+ */
+
+ ximage->bitmap_pad = 128;
+ }
+ if (bytes_per_line) {
+ ximage->bytes_per_line = bytes_per_line;
+ } else {
+ ximage->bytes_per_line = ((width * ximage->bits_per_pixel +
+ (ximage->bitmap_pad - 1)) >> 3) &
+ ~((ximage->bitmap_pad >> 3) - 1);
+ }
+#ifdef WORDS_BIGENDIAN
+ ximage->byte_order = MSBFirst;
+ ximage->bitmap_bit_order = MSBFirst;
+#else
+ ximage->byte_order = LSBFirst;
+ ximage->bitmap_bit_order = LSBFirst;
+#endif
+ ximage->red_mask = 0x00FF0000;
+ ximage->green_mask = 0x0000FF00;
+ ximage->blue_mask = 0x000000FF;
+ ximage->f.create_image = NULL;
+ ximage->f.destroy_image = DestroyImage;
+ ximage->f.get_pixel = ImageGetPixel;
+ ximage->f.put_pixel = ImagePutPixel;
+ ximage->f.sub_image = NULL;
+ ximage->f.add_pixel = NULL;
+
+ return ximage;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkPutImage --
+ *
+ * Copies a rectangular subimage of an XImage into a drawable. Currently
+ * this is only called by TkImgPhotoDisplay, using a Window as the
+ * drawable.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Draws the image on the specified drawable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkPutImage(
+ unsigned long *colors, /* Unused on Macintosh. */
+ int ncolors, /* Unused on Macintosh. */
+ Display* display, /* Display. */
+ Drawable drawable, /* 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. */
+{
+ TkMacOSXDrawingContext dc;
+ MacDrawable *macDraw = (MacDrawable *) drawable;
+
+ display->request++;
+ if (!TkMacOSXSetupDrawingContext(drawable, gc, 1, &dc)) {
+ return BadDrawable;
+ }
+ if (dc.context) {
+ CGRect bounds, srcRect, dstRect;
+ CGImageRef img = TkMacOSXCreateCGImageWithXImage(image);
+
+ /*
+ * The CGContext for a pixmap is RGB only, with A = 0.
+ */
+
+ if (!(macDraw->flags & TK_IS_PIXMAP)) {
+ CGContextSetBlendMode(dc.context, kCGBlendModeSourceAtop);
+ }
+ if (img) {
+
+ /*
+ * If the XImage has big pixels, the source is rescaled to reflect
+ * the actual pixel dimensions. This is not currently used, but
+ * could arise if the image were copied from a retina monitor and
+ * redrawn on an ordinary monitor.
+ */
+
+ int pp = image->pixelpower;
+
+ bounds = CGRectMake(0, 0, image->width, image->height);
+ srcRect = CGRectMake(src_x<<pp, src_y<<pp, width<<pp, height<<pp);
+ dstRect = CGRectMake(dest_x, dest_y, width, height);
+ TkMacOSXDrawCGImage(drawable, gc, dc.context,
+ img, gc->foreground, gc->background,
+ bounds, srcRect, dstRect);
+ CFRelease(img);
+ } else {
+ TkMacOSXDbgMsg("Invalid source drawable");
+ }
+ } else {
+ TkMacOSXDbgMsg("Invalid destination drawable");
+ }
+ TkMacOSXRestoreDrawingContext(&dc);
+ return Success;
+}
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXInit.c b/tk8.6/macosx/tkMacOSXInit.c
new file mode 100644
index 0000000..bf0b9f2
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXInit.c
@@ -0,0 +1,652 @@
+/*
+ * tkMacOSXInit.c --
+ *
+ * This file contains Mac OS X -specific interpreter initialization
+ * functions.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ * Copyright 2001-2009, Apple Inc.
+ * Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright (c) 2017 Marc Culler
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkMacOSXPrivate.h"
+
+#include <sys/stat.h>
+#include <dlfcn.h>
+#include <objc/objc-auto.h>
+
+static char tkLibPath[PATH_MAX + 1] = "";
+
+/*
+ * If the App is in an App package, then we want to add the Scripts directory
+ * to the auto_path.
+ */
+
+static char scriptPath[PATH_MAX + 1] = "";
+
+#pragma mark TKApplication(TKInit)
+
+@implementation TKApplication
+@synthesize poolLock = _poolLock;
+@synthesize macMinorVersion = _macMinorVersion;
+@synthesize isDrawing = _isDrawing;
+@end
+
+/*
+ * #define this to see a message on stderr whenever _resetAutoreleasePool is
+ * called while the pool is locked.
+ */
+#undef DEBUG_LOCK
+
+@implementation TKApplication(TKInit)
+- (void) _resetAutoreleasePool
+{
+ if ([self poolLock] == 0) {
+ [_mainPool drain];
+ _mainPool = [NSAutoreleasePool new];
+ } else {
+#ifdef DEBUG_LOCK
+ fprintf(stderr, "Pool is locked with count %d!!!!\n", [self poolLock]);
+#endif
+ }
+}
+- (void) _lockAutoreleasePool
+{
+ [self setPoolLock:[self poolLock] + 1];
+}
+- (void) _unlockAutoreleasePool
+{
+ [self setPoolLock:[self poolLock] - 1];
+}
+#ifdef TK_MAC_DEBUG_NOTIFICATIONS
+- (void) _postedNotification: (NSNotification *) notification
+{
+ TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
+}
+#endif
+
+- (void) _setupApplicationNotifications
+{
+ NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
+#define observe(n, s) \
+ [nc addObserver:self selector:@selector(s) name:(n) object:nil]
+ observe(NSApplicationDidBecomeActiveNotification, applicationActivate:);
+ observe(NSApplicationDidResignActiveNotification, applicationDeactivate:);
+ observe(NSApplicationDidUnhideNotification, applicationShowHide:);
+ observe(NSApplicationDidHideNotification, applicationShowHide:);
+ observe(NSApplicationDidChangeScreenParametersNotification, displayChanged:);
+ observe(NSTextInputContextKeyboardSelectionDidChangeNotification, keyboardChanged:);
+#undef observe
+}
+
+-(void)applicationWillFinishLaunching:(NSNotification *)aNotification
+{
+
+ /*
+ * Initialize notifications.
+ */
+#ifdef TK_MAC_DEBUG_NOTIFICATIONS
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(_postedNotification:) name:nil object:nil];
+#endif
+ [self _setupWindowNotifications];
+ [self _setupApplicationNotifications];
+
+ /*
+ * Construct the menu bar.
+ */
+ _defaultMainMenu = nil;
+ [self _setupMenus];
+
+ /*
+ * Initialize event processing.
+ */
+ TkMacOSXInitAppleEvents(_eventInterp);
+
+ /*
+ * Initialize the graphics context.
+ */
+ TkMacOSXUseAntialiasedText(_eventInterp, -1);
+ TkMacOSXInitCGDrawing(_eventInterp, TRUE, 0);
+}
+
+-(void)applicationDidFinishLaunching:(NSNotification *)notification
+{
+
+ /*
+ * It is not safe to force activation of the NSApp until this method is
+ * called. Activating too early can cause the menu bar to be unresponsive.
+ */
+
+ [NSApp activateIgnoringOtherApps: YES];
+
+ /*
+ * Process events to ensure that the root window is fully initialized. See
+ * ticket 56a1823c73.
+ */
+
+ [NSApp _lockAutoreleasePool];
+ while (Tcl_DoOneEvent(TCL_WINDOW_EVENTS| TCL_DONT_WAIT)) {}
+ [NSApp _unlockAutoreleasePool];
+}
+
+- (void) _setup: (Tcl_Interp *) interp
+{
+ /*
+ * Remember our interpreter.
+ */
+ _eventInterp = interp;
+
+ /*
+ * Install the global autoreleasePool.
+ */
+ _mainPool = [NSAutoreleasePool new];
+ [NSApp setPoolLock:0];
+
+ /*
+ * Record the OS version we are running on.
+ */
+ int minorVersion;
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 101000
+ Gestalt(gestaltSystemVersionMinor, (SInt32*)&minorVersion);
+#else
+ NSOperatingSystemVersion systemVersion;
+ systemVersion = [[NSProcessInfo processInfo] operatingSystemVersion];
+ minorVersion = systemVersion.minorVersion;
+#endif
+ [NSApp setMacMinorVersion: minorVersion];
+
+ /*
+ * We are not drawing right now.
+ */
+
+ [NSApp setIsDrawing:NO];
+
+ /*
+ * Be our own delegate.
+ */
+
+ [self setDelegate:self];
+
+ /*
+ * Make sure we are allowed to open windows.
+ */
+
+ [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
+
+ /*
+ * If no icon has been set from an Info.plist file, use the Wish icon from
+ * the Tk framework.
+ */
+ NSString *iconFile = [[NSBundle mainBundle] objectForInfoDictionaryKey:
+ @"CFBundleIconFile"];
+ if (!iconFile) {
+ NSString *path = [NSApp tkFrameworkImagePath:@"Tk.icns"];
+ if (path) {
+ NSImage *image = [[NSImage alloc] initWithContentsOfFile:path];
+ if (image) {
+ [NSApp setApplicationIconImage:image];
+ [image release];
+ }
+ }
+ }
+}
+
+- (NSString *) tkFrameworkImagePath: (NSString *) image
+{
+ NSString *path = nil;
+ NSAutoreleasePool *pool = [NSAutoreleasePool new];
+ if (tkLibPath[0] != '\0') {
+ path = [[NSBundle bundleWithPath:[[NSString stringWithUTF8String:
+ tkLibPath] stringByAppendingString:@"/../.."]]
+ pathForImageResource:image];
+ }
+ if (!path) {
+ const char *tk_library = Tcl_GetVar2(_eventInterp, "tk_library", NULL,
+ TCL_GLOBAL_ONLY);
+
+ if (tk_library) {
+ NSFileManager *fm = [NSFileManager defaultManager];
+
+ path = [[NSString stringWithUTF8String:tk_library]
+ stringByAppendingFormat:@"/%@", image];
+ if (![fm isReadableFileAtPath:path]) {
+ path = [[NSString stringWithUTF8String:tk_library]
+ stringByAppendingFormat:@"/../macosx/%@", image];
+ if (![fm isReadableFileAtPath:path]) {
+ path = nil;
+ }
+ }
+ }
+ }
+#ifdef TK_MAC_DEBUG
+ if (!path && getenv("TK_SRCROOT")) {
+ path = [[NSString stringWithUTF8String:getenv("TK_SRCROOT")]
+ stringByAppendingFormat:@"/macosx/%@", image];
+ if (![[NSFileManager defaultManager] isReadableFileAtPath:path]) {
+ path = nil;
+ }
+ }
+#endif
+ [path retain];
+ [pool drain];
+ return path;
+}
+@end
+
+#pragma mark -
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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(
+ Tcl_Interp *interp)
+{
+ static int initialized = 0;
+
+ /*
+ * Since it is possible for TkInit to be called multiple times and we
+ * don't want to do the following initialization multiple times we protect
+ * against doing it more than once.
+ */
+
+ if (!initialized) {
+ struct stat st;
+
+ initialized = 1;
+
+ /*
+ * Initialize/check OS version variable for runtime checks.
+ */
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
+# error Mac OS X 10.6 required
+#endif
+
+#ifdef TK_FRAMEWORK
+ /*
+ * 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?
+ */
+
+ if (Tcl_MacOSXOpenVersionedBundleResources(interp,
+ "com.tcltk.tklibrary", TK_FRAMEWORK_VERSION, 0, PATH_MAX,
+ tkLibPath) != TCL_OK) {
+ # if 0 /* This is not really an error. Wish still runs fine. */
+ TkMacOSXDbgMsg("Tcl_MacOSXOpenVersionedBundleResources failed");
+ # endif
+ }
+#endif
+
+ /*
+ * FIXME: Close stdin & stdout for remote debugging otherwise we will
+ * fight with gdb for stdin & stdout
+ */
+
+ if (getenv("XCNOSTDIN") != NULL) {
+ close(0);
+ close(1);
+ }
+
+ /*
+ * Instantiate our NSApplication object. This needs to be done before
+ * we check whether to open a console window.
+ */
+
+ NSAutoreleasePool *pool = [NSAutoreleasePool new];
+ [[NSUserDefaults standardUserDefaults] registerDefaults:
+ [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithBool:YES],
+ @"_NSCanWrapButtonTitles",
+ [NSNumber numberWithInt:-1],
+ @"NSStringDrawingTypesetterBehavior",
+ nil]];
+ [TKApplication sharedApplication];
+ [pool drain];
+ [NSApp _setup:interp];
+ [NSApp finishLaunching];
+ Tk_MacOSXSetupTkNotifier();
+
+ /*
+ * If the root window is mapped before the App has finished launching
+ * it will open off screen (see ticket 56a1823c73). To avoid this we
+ * ask Tk to process an event with no wait. We expect Tcl_DoOneEvent
+ * to wait until the Mac event loop has been created and then return
+ * immediately since the queue is empty.
+ */
+
+ Tcl_DoOneEvent(TCL_WINDOW_EVENTS | TCL_DONT_WAIT);
+
+ /*
+ * If we don't have a TTY and stdin is a special character file of
+ * length 0, (e.g. /dev/null, which is what Finder sets when double
+ * clicking Wish) then use the Tk based console interpreter.
+ */
+
+ if (getenv("TK_CONSOLE") ||
+ (!isatty(0) && (fstat(0, &st) ||
+ (S_ISCHR(st.st_mode) && st.st_blocks == 0)))) {
+ Tk_InitConsoleChannels(interp);
+ Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDIN));
+ Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDOUT));
+ Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDERR));
+
+ /*
+ * Only show the console if we don't have a startup script and
+ * tcl_interactive hasn't been set already.
+ */
+
+ if (Tcl_GetStartupScript(NULL) == NULL) {
+ const char *intvar = Tcl_GetVar2(interp,
+ "tcl_interactive", NULL, TCL_GLOBAL_ONLY);
+
+ if (intvar == NULL) {
+ Tcl_SetVar2(interp, "tcl_interactive", NULL, "1",
+ TCL_GLOBAL_ONLY);
+ }
+ }
+ if (Tk_CreateConsoleWindow(interp) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ }
+
+ }
+
+ if (tkLibPath[0] != '\0') {
+ Tcl_SetVar2(interp, "tk_library", NULL, tkLibPath, TCL_GLOBAL_ONLY);
+ }
+
+ if (scriptPath[0] != '\0') {
+ Tcl_SetVar2(interp, "auto_path", NULL, scriptPath,
+ TCL_GLOBAL_ONLY|TCL_LIST_ELEMENT|TCL_APPEND_VALUE);
+ }
+
+ Tcl_CreateObjCommand(interp, "::tk::mac::standardAboutPanel",
+ TkMacOSXStandardAboutPanelObjCmd, NULL, NULL);
+ Tcl_CreateObjCommand(interp, "::tk::mac::registerServiceWidget",
+ TkMacOSXRegisterServiceWidgetObjCmd, NULL, NULL);
+ Tcl_CreateObjCommand(interp, "::tk::mac::iconBitmap",
+ TkMacOSXIconBitmapObjCmd, NULL, NULL);
+ Tcl_CreateObjCommand(interp, "::tk::mac::GetAppPath", TkMacOSXGetAppPath, NULL, NULL);
+
+ /*
+ * Initialize the NSServices object here. Apple's docs say to do this
+ * in applicationDidFinishLaunching, but the Tcl interpreter is not
+ * initialized until this function call.
+ */
+
+ TkMacOSXServices_Init(interp);
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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(
+ Tcl_Interp *interp,
+ Tcl_DString *namePtr) /* A previously initialized Tcl_DString. */
+{
+ const char *p, *name;
+
+ name = Tcl_GetVar2(interp, "argv0", NULL, 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);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXGetAppPath --
+ *
+ * Returns the path of the Wish application bundle.
+ *
+ * Results:
+ * Returns the application path.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+int TkMacOSXGetAppPath(
+ ClientData cd,
+ Tcl_Interp *ip,
+ int objc,
+ Tcl_Obj *const objv[])
+{
+
+ CFURLRef mainBundleURL = CFBundleCopyBundleURL(CFBundleGetMainBundle());
+
+
+ /*
+ * Convert the URL reference into a string reference.
+ */
+
+ CFStringRef appPath = CFURLCopyFileSystemPath(mainBundleURL, kCFURLPOSIXPathStyle);
+
+ /*
+ * Get the system encoding method.
+ */
+
+ CFStringEncoding encodingMethod = CFStringGetSystemEncoding();
+
+ /*
+ * Convert the string reference into a C string.
+ */
+
+ char *path = (char *) CFStringGetCStringPtr(appPath, encodingMethod);
+
+ Tcl_SetResult(ip, path, NULL);
+
+ CFRelease(mainBundleURL);
+ CFRelease(appPath);
+ return TCL_OK;
+
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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(
+ 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);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXDefaultStartupScript --
+ *
+ * On MacOS X, we look for a file in the Resources/Scripts directory
+ * called AppMain.tcl and if found, we set argv[1] to that, so that the
+ * rest of the code will find it, and add the Scripts folder to the
+ * auto_path. If we don't find the startup script, we just bag it,
+ * assuming the user is starting up some other way.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Tcl_SetStartupScript() called when AppMain.tcl found.
+ *
+ *----------------------------------------------------------------------
+ */
+
+MODULE_SCOPE void
+TkMacOSXDefaultStartupScript(void)
+{
+ NSAutoreleasePool *pool = [NSAutoreleasePool new];
+ CFBundleRef bundleRef = CFBundleGetMainBundle();
+
+ if (bundleRef != NULL) {
+ CFURLRef appMainURL = CFBundleCopyResourceURL(bundleRef,
+ CFSTR("AppMain"), CFSTR("tcl"), CFSTR("Scripts"));
+
+ if (appMainURL != NULL) {
+ CFURLRef scriptFldrURL;
+ char startupScript[PATH_MAX + 1];
+
+ if (CFURLGetFileSystemRepresentation (appMainURL, true,
+ (unsigned char *) startupScript, PATH_MAX)) {
+ Tcl_SetStartupScript(Tcl_NewStringObj(startupScript,-1), NULL);
+ scriptFldrURL = CFURLCreateCopyDeletingLastPathComponent(NULL,
+ appMainURL);
+ if (scriptFldrURL != NULL) {
+ CFURLGetFileSystemRepresentation(scriptFldrURL, true,
+ (unsigned char *) scriptPath, PATH_MAX);
+ CFRelease(scriptFldrURL);
+ }
+ }
+ CFRelease(appMainURL);
+ }
+ }
+ [pool drain];
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXGetNamedSymbol --
+ *
+ * Dynamically acquire address of a named symbol from a loaded dynamic
+ * library, so that we can use API that may not be available on all OS
+ * versions.
+ *
+ * Results:
+ * Address of given symbol or NULL if unavailable.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+MODULE_SCOPE void*
+TkMacOSXGetNamedSymbol(
+ const char* module,
+ const char* symbol)
+{
+ void *addr = dlsym(RTLD_NEXT, symbol);
+ if (!addr) {
+ (void) dlerror(); /* Clear dlfcn error state */
+ }
+ return addr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXGetStringObjFromCFString --
+ *
+ * Get a string object from a CFString as efficiently as possible.
+ *
+ * Results:
+ * New string object or NULL if conversion failed.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+MODULE_SCOPE Tcl_Obj*
+TkMacOSXGetStringObjFromCFString(
+ CFStringRef str)
+{
+ Tcl_Obj *obj = NULL;
+ const char *c = CFStringGetCStringPtr(str, kCFStringEncodingUTF8);
+
+ if (c) {
+ obj = Tcl_NewStringObj(c, -1);
+ } else {
+ CFRange all = CFRangeMake(0, CFStringGetLength(str));
+ CFIndex len;
+
+ if (CFStringGetBytes(str, all, kCFStringEncodingUTF8, 0, false, NULL,
+ 0, &len) > 0 && len < INT_MAX) {
+ obj = Tcl_NewObj();
+ Tcl_SetObjLength(obj, len);
+ CFStringGetBytes(str, all, kCFStringEncodingUTF8, 0, false,
+ (UInt8*) obj->bytes, len, NULL);
+ }
+ }
+ return obj;
+}
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXInt.h b/tk8.6/macosx/tkMacOSXInt.h
new file mode 100644
index 0000000..9cb75d2
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXInt.h
@@ -0,0 +1,223 @@
+/*
+ * tkMacOSXInt.h --
+ *
+ * Declarations of Macintosh specific shared variables and procedures.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ * Copyright 2001-2009, Apple Inc.
+ * Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef _TKMACINT
+#define _TKMACINT
+
+#ifndef _TKINT
+#include "tkInt.h"
+#endif
+
+/*
+ * Include platform specific public interfaces.
+ */
+
+#ifndef _TKMAC
+#include "tkMacOSX.h"
+#import <Cocoa/Cocoa.h>
+#endif
+
+/*
+ * Define compatibility platform types used in the structures below so that
+ * this header can be included without pulling in the platform headers.
+ */
+
+#ifndef _TKMACPRIV
+# ifndef CGGEOMETRY_H_
+# ifndef CGFLOAT_DEFINED
+# if __LP64__
+# define CGFloat double
+# else
+# define CGFloat float
+# endif
+# endif
+# define CGSize struct {CGFloat width; CGFloat height;}
+# endif
+# ifndef CGCONTEXT_H_
+# define CGContextRef void *
+# endif
+# ifndef CGCOLOR_H_
+# define CGColorRef void *
+# endif
+# ifndef __HISHAPE__
+# define HIShapeRef void *
+# endif
+# ifndef _APPKITDEFINES_H
+# define NSView void *
+# endif
+#endif
+
+struct TkWindowPrivate {
+ TkWindow *winPtr; /* Ptr to tk window or NULL if Pixmap */
+ NSView *view;
+ CGContextRef context;
+ int xOff; /* X offset from toplevel window */
+ int yOff; /* Y offset from toplevel window */
+ CGSize size;
+ HIShapeRef visRgn; /* Visible region of window */
+ HIShapeRef aboveVisRgn; /* Visible region of window & its children */
+ HIShapeRef drawRgn; /* Clipped drawing region */
+ int referenceCount; /* Don't delete toplevel until children are
+ * gone. */
+ struct TkWindowPrivate *toplevel;
+ /* Pointer to the toplevel datastruct. */
+ CGFloat fillRGBA[4]; /* Background used by the ttk FillElement */
+ int flags; /* Various state see defines below. */
+};
+typedef struct TkWindowPrivate MacDrawable;
+
+/*
+ * Defines use for the flags field of the MacDrawable data structure.
+ */
+
+#define TK_SCROLLBAR_GROW 0x01
+#define TK_CLIP_INVALID 0x02
+#define TK_HOST_EXISTS 0x04
+#define TK_DRAWN_UNDER_MENU 0x08
+#define TK_IS_PIXMAP 0x10
+#define TK_IS_BW_PIXMAP 0x20
+#define TK_DO_NOT_DRAW 0x40
+#define TTK_HAS_CONTRASTING_BG 0x80
+
+/*
+ * 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 tkMacOSX.h.
+ */
+
+typedef struct {
+ Tk_MacOSXEmbedRegisterWinProc *registerWinProc;
+ Tk_MacOSXEmbedGetGrafPortProc *getPortProc;
+ Tk_MacOSXEmbedMakeContainerExistProc *containerExistProc;
+ Tk_MacOSXEmbedGetClipProc *getClipProc;
+ Tk_MacOSXEmbedGetOffsetInParentProc *getOffsetProc;
+} TkMacOSXEmbedHandler;
+
+MODULE_SCOPE TkMacOSXEmbedHandler *tkMacOSXEmbedHandler;
+
+/*
+ * GC CGColorRef cache for tkMacOSXColor.c
+ */
+
+typedef struct {
+ unsigned long cachedForeground;
+ CGColorRef cachedForegroundColor;
+ unsigned long cachedBackground;
+ CGColorRef cachedBackgroundColor;
+} TkpGCCache;
+
+MODULE_SCOPE TkpGCCache *TkpGetGCCache(GC gc);
+MODULE_SCOPE void TkpInitGCCache(GC gc);
+MODULE_SCOPE void TkpFreeGCCache(GC gc);
+
+/*
+ * Undef compatibility platform types defined above.
+ */
+
+#ifndef _TKMACPRIV
+# ifndef CGGEOMETRY_H_
+# ifndef CGFLOAT_DEFINED
+# undef CGFloat
+# endif
+# undef CGSize
+# endif
+# ifndef CGCONTEXT_H_
+# undef CGContextRef
+# endif
+# ifndef CGCOLOR_H_
+# undef CGColorRef
+# endif
+# ifndef __HISHAPE__
+# undef HIShapeRef
+# endif
+# ifndef _APPKITDEFINES_H
+# undef NSView
+# endif
+#endif
+
+/*
+ * 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 used for the flags argument to TkGenWMConfigureEvent.
+ */
+
+#define TK_LOCATION_CHANGED 1
+#define TK_SIZE_CHANGED 2
+#define TK_BOTH_CHANGED 3
+#define TK_MACOSX_HANDLE_EVENT_IMMEDIATELY 1024
+
+/*
+ * Defines for tkTextDisp.c
+ */
+
+#define TK_LAYOUT_WITH_BASE_CHUNKS 1
+#define TK_DRAW_IN_CONTEXT 1
+
+/*
+ * Prototypes of internal procs not in the stubs table.
+ */
+
+MODULE_SCOPE void TkMacOSXDefaultStartupScript(void);
+#if 0
+MODULE_SCOPE int XSetClipRectangles(Display *d, GC gc, int clip_x_origin,
+ int clip_y_origin, XRectangle* rectangles, int n, int ordering);
+#endif
+MODULE_SCOPE void TkpClipDrawableToRect(Display *display, Drawable d, int x,
+ int y, int width, int height);
+MODULE_SCOPE void TkpRetainRegion(TkRegion r);
+MODULE_SCOPE void TkpReleaseRegion(TkRegion r);
+MODULE_SCOPE void TkpShiftButton(NSButton *button, NSPoint delta);
+MODULE_SCOPE Bool TkpAppIsDrawing(void);
+MODULE_SCOPE void TkpDisplayWindow(Tk_Window tkwin);
+MODULE_SCOPE Bool TkTestLogDisplay(void);
+MODULE_SCOPE Bool TkMacOSXInDarkMode(Tk_Window tkwin);
+
+/*
+ * Include the stubbed internal platform-specific API.
+ */
+
+#include "tkIntPlatDecls.h"
+
+#endif /* _TKMACINT */
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXKeyEvent.c b/tk8.6/macosx/tkMacOSXKeyEvent.c
new file mode 100644
index 0000000..65b7aee
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXKeyEvent.c
@@ -0,0 +1,762 @@
+/*
+ * tkMacOSXKeyEvent.c --
+ *
+ * This file implements functions that decode & handle keyboard events on
+ * MacOS X.
+ *
+ * Copyright 2001-2009, Apple Inc.
+ * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright (c) 2012 Adrian Robert.
+ * Copyright 2015 Marc Culler.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkMacOSXPrivate.h"
+#include "tkMacOSXEvent.h"
+#include "tkMacOSXConstants.h"
+
+/*
+#ifdef TK_MAC_DEBUG
+#define TK_MAC_DEBUG_KEYBOARD
+#endif
+*/
+#define NS_KEYLOG 0
+
+static Tk_Window keyboardGrabWinPtr = NULL;
+ /* Current keyboard grab window. */
+static NSWindow *keyboardGrabNSWindow = nil;
+ /* NSWindow for the current keyboard grab
+ * window. */
+static NSModalSession modalSession = nil;
+static BOOL processingCompose = NO;
+static BOOL finishedCompose = NO;
+static int caret_x = 0, caret_y = 0, caret_height = 0;
+
+static void setupXEvent(XEvent *xEvent, NSWindow *w,
+ unsigned int state);
+static unsigned isFunctionKey(unsigned int code);
+
+unsigned short releaseCode;
+
+
+#pragma mark TKApplication(TKKeyEvent)
+
+@implementation TKApplication(TKKeyEvent)
+
+- (NSEvent *) tkProcessKeyEvent: (NSEvent *) theEvent
+{
+#ifdef TK_MAC_DEBUG_EVENTS
+ TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent);
+#endif
+ NSWindow *w;
+ NSEventType type = [theEvent type];
+ NSUInteger modifiers = ([theEvent modifierFlags] &
+ NSDeviceIndependentModifierFlagsMask);
+ NSUInteger len = 0;
+ BOOL repeat = NO;
+ unsigned short keyCode = [theEvent keyCode];
+ NSString *characters = nil, *charactersIgnoringModifiers = nil;
+ static NSUInteger savedModifiers = 0;
+ static NSMutableArray *nsEvArray;
+
+ if (nsEvArray == nil) {
+ nsEvArray = [[NSMutableArray alloc] initWithCapacity: 1];
+ processingCompose = NO;
+ }
+
+ w = [theEvent window];
+ TkWindow *winPtr = TkMacOSXGetTkWindow(w);
+ Tk_Window tkwin = (Tk_Window) winPtr;
+ XEvent xEvent;
+
+ if (!winPtr) {
+ return theEvent;
+ }
+
+ /*
+ * Control-Tab and Control-Shift-Tab are used to switch tabs in a tabbed
+ * window. We do not want to generate an Xevent for these since that might
+ * cause the deselected tab to be reactivated.
+ */
+
+ if (keyCode == 48 && (modifiers & NSControlKeyMask) == NSControlKeyMask) {
+ return theEvent;
+ }
+
+ switch (type) {
+ case NSKeyUp:
+ /*Fix for bug #1ba71a86bb: key release firing on key press.*/
+ setupXEvent(&xEvent, w, 0);
+ xEvent.xany.type = KeyRelease;
+ xEvent.xkey.keycode = releaseCode;
+ xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
+ case NSKeyDown:
+ repeat = [theEvent isARepeat];
+ characters = [theEvent characters];
+ charactersIgnoringModifiers = [theEvent charactersIgnoringModifiers];
+ len = [charactersIgnoringModifiers length];
+ case NSFlagsChanged:
+
+#if defined(TK_MAC_DEBUG_EVENTS) || NS_KEYLOG == 1
+ TKLog(@"-[%@(%p) %s] r=%d mods=%u '%@' '%@' code=%u c=%d %@ %d", [self class], self, _cmd, repeat, modifiers, characters, charactersIgnoringModifiers, keyCode,([charactersIgnoringModifiers length] == 0) ? 0 : [charactersIgnoringModifiers characterAtIndex: 0], w, type);
+#endif
+ break;
+
+ default:
+ return theEvent; /* Unrecognized key event. */
+ }
+
+ /*
+ * Create an Xevent to add to the Tk queue.
+ */
+
+ if (!processingCompose) {
+ unsigned int state = 0;
+
+ if (modifiers & NSAlphaShiftKeyMask) {
+ state |= LockMask;
+ }
+ if (modifiers & NSShiftKeyMask) {
+ state |= ShiftMask;
+ }
+ if (modifiers & NSControlKeyMask) {
+ state |= ControlMask;
+ }
+ if (modifiers & NSCommandKeyMask) {
+ state |= Mod1Mask; /* command key */
+ }
+ if (modifiers & NSAlternateKeyMask) {
+ state |= Mod2Mask; /* option key */
+ }
+ if (modifiers & NSNumericPadKeyMask) {
+ state |= Mod3Mask;
+ }
+ if (modifiers & NSFunctionKeyMask) {
+ state |= Mod4Mask;
+ }
+
+ /*
+ * Events are only received for the front Window on the Macintosh. So
+ * to build an XEvent we look up the Tk window associated to the Front
+ * window. If a different window has a local grab we ignore the event.
+ */
+
+ TkWindow *winPtr = TkMacOSXGetTkWindow(w);
+ Tk_Window tkwin = (Tk_Window) winPtr;
+
+ if (tkwin) {
+ TkWindow *grabWinPtr = winPtr->dispPtr->grabWinPtr;
+
+ if (grabWinPtr
+ && grabWinPtr != winPtr
+ && !winPtr->dispPtr->grabFlags /* this means the grab is local. */
+ && grabWinPtr->mainPtr == winPtr->mainPtr) {
+ return theEvent;
+ }
+ } else {
+ tkwin = (Tk_Window) winPtr->dispPtr->focusPtr;
+ }
+ if (!tkwin) {
+ TkMacOSXDbgMsg("tkwin == NULL");
+ return theEvent; /* Give up. No window for this event. */
+ }
+
+ /*
+ * If it's a function key, or we have modifiers other than Shift or
+ * Alt, pass it straight to Tk. Otherwise we'll send for input
+ * processing.
+ */
+
+ int code = (len == 0) ? 0 :
+ [charactersIgnoringModifiers characterAtIndex: 0];
+ if (type != NSKeyDown || isFunctionKey(code)
+ || (len > 0 && state & (ControlMask | Mod1Mask | Mod3Mask | Mod4Mask))) {
+ XEvent xEvent;
+
+ setupXEvent(&xEvent, w, state);
+ if (type == NSFlagsChanged) {
+ if (savedModifiers > modifiers) {
+ xEvent.xany.type = KeyRelease;
+ } else {
+ xEvent.xany.type = KeyPress;
+ }
+
+ /*
+ * Use special '-1' to signify a special keycode to our
+ * platform specific code in tkMacOSXKeyboard.c. This is rather
+ * like what happens on Windows.
+ */
+
+ xEvent.xany.send_event = -1;
+
+ /*
+ * Set keycode (which was zero) to the changed modifier
+ */
+
+ xEvent.xkey.keycode = (modifiers ^ savedModifiers);
+ } else {
+ if (type == NSKeyUp || repeat) {
+ xEvent.xany.type = KeyRelease;
+ } else {
+ xEvent.xany.type = KeyPress;
+ }
+
+ /*
+ * For command key, take input manager's word so things like
+ * dvorak / qwerty layout work.
+ */
+
+ if ((modifiers & NSCommandKeyMask) == NSCommandKeyMask
+ && (modifiers & NSAlternateKeyMask) != NSAlternateKeyMask
+ && len > 0 && !isFunctionKey(code)) {
+ // head off keycode-based translation in tkMacOSXKeyboard.c
+ xEvent.xkey.nbytes = [characters length]; //len
+ }
+
+ if ([characters length] > 0) {
+ xEvent.xkey.keycode = (keyCode << 16) |
+ (UInt16) [characters characterAtIndex:0];
+ if (![characters getCString:xEvent.xkey.trans_chars
+ maxLength:XMaxTransChars encoding:NSUTF8StringEncoding]) {
+ /* prevent SF bug 2907388 (crash on some composite chars) */
+ //PENDING: we might not need this anymore
+ TkMacOSXDbgMsg("characters too long");
+ return theEvent;
+ }
+ }
+
+ if (repeat) {
+ Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
+ xEvent.xany.type = KeyPress;
+ xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
+ }
+ }
+ Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
+ savedModifiers = modifiers;
+ return theEvent;
+ } /* if send straight to TK */
+ } /* if not processing compose */
+
+ if (type == NSKeyDown) {
+ if (NS_KEYLOG) {
+ TKLog(@"keyDown: %s compose sequence.\n",
+ processingCompose == YES ? "Continue" : "Begin");
+ }
+ processingCompose = YES;
+ [nsEvArray addObject: theEvent];
+ [[w contentView] interpretKeyEvents: nsEvArray];
+ [nsEvArray removeObject: theEvent];
+ }
+
+ savedModifiers = modifiers;
+ return theEvent;
+}
+@end
+
+
+@implementation TKContentView
+
+-(id)init {
+ self = [super init];
+ if (self) {
+ _needsRedisplay = NO;
+ }
+ return self;
+}
+
+/* <NSTextInput> implementation (called through interpretKeyEvents:]). */
+
+/* <NSTextInput>: called when done composing;
+ NOTE: also called when we delete over working text, followed immed.
+ by doCommandBySelector: deleteBackward: */
+- (void)insertText: (id)aString
+{
+ int i, len = [(NSString *) aString length];
+ XEvent xEvent;
+
+ if (NS_KEYLOG) {
+ TKLog(@"insertText '%@'\tlen = %d", aString, len);
+ }
+ processingCompose = NO;
+ finishedCompose = YES;
+
+ /*
+ * First, clear any working text.
+ */
+
+ if (privateWorkingText != nil) {
+ [self deleteWorkingText];
+ }
+
+ /*
+ * Now insert the string as keystrokes.
+ */
+
+ setupXEvent(&xEvent, [self window], 0);
+ xEvent.xany.type = KeyPress;
+
+ for (i =0; i<len; i++) {
+ xEvent.xkey.keycode = (UInt16) [aString characterAtIndex: i];
+ [[aString substringWithRange: NSMakeRange(i,1)]
+ getCString: xEvent.xkey.trans_chars
+ maxLength: XMaxTransChars encoding: NSUTF8StringEncoding];
+ xEvent.xkey.nbytes = strlen(xEvent.xkey.trans_chars);
+ xEvent.xany.type = KeyPress;
+ releaseCode = (UInt16) [aString characterAtIndex: 0];
+ Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
+ }
+ releaseCode = (UInt16) [aString characterAtIndex: 0];
+}
+
+
+/* <NSTextInput>: inserts display of composing characters */
+- (void)setMarkedText: (id)aString selectedRange: (NSRange)selRange
+{
+ NSString *str = [aString respondsToSelector: @selector (string)] ?
+ [aString string] : aString;
+ if (NS_KEYLOG) {
+ TKLog(@"setMarkedText '%@' len =%lu range %lu from %lu", str,
+ (unsigned long) [str length], (unsigned long) selRange.length,
+ (unsigned long) selRange.location);
+ }
+
+ if (privateWorkingText != nil) {
+ [self deleteWorkingText];
+ }
+ if ([str length] == 0) {
+ return;
+ }
+
+ processingCompose = YES;
+ privateWorkingText = [str copy];
+
+ //PENDING: insert workingText underlined
+}
+
+
+- (BOOL)hasMarkedText
+{
+ return privateWorkingText != nil;
+}
+
+
+- (NSRange)markedRange
+{
+ NSRange rng = privateWorkingText != nil
+ ? NSMakeRange(0, [privateWorkingText length])
+ : NSMakeRange(NSNotFound, 0);
+
+ if (NS_KEYLOG) {
+ TKLog(@"markedRange request");
+ }
+ return rng;
+}
+
+
+- (void)unmarkText
+{
+ if (NS_KEYLOG) {
+ TKLog(@"unmark (accept) text");
+ }
+ [self deleteWorkingText];
+ processingCompose = NO;
+}
+
+
+/* used to position char selection windows, etc. */
+- (NSRect)firstRectForCharacterRange: (NSRange)theRange
+{
+ NSRect rect;
+ NSPoint pt;
+
+ pt.x = caret_x;
+ pt.y = caret_y;
+
+ pt = [self convertPoint: pt toView: nil];
+ pt = [[self window] tkConvertPointToScreen: pt];
+ pt.y -= caret_height;
+
+ rect.origin = pt;
+ rect.size.width = caret_height;
+ rect.size.height = caret_height;
+ return rect;
+}
+
+
+- (NSInteger)conversationIdentifier
+{
+ return (NSInteger) self;
+}
+
+
+- (void)doCommandBySelector: (SEL)aSelector
+{
+ if (NS_KEYLOG) {
+ TKLog(@"doCommandBySelector: %@", NSStringFromSelector(aSelector));
+ }
+ processingCompose = NO;
+ if (aSelector == @selector (deleteBackward:)) {
+ /*
+ * Happens when user backspaces over an ongoing composition:
+ * throw a 'delete' into the event queue.
+ */
+
+ XEvent xEvent;
+
+ setupXEvent(&xEvent, [self window], 0);
+ xEvent.xany.type = KeyPress;
+ xEvent.xkey.nbytes = 1;
+ xEvent.xkey.keycode = (0x33 << 16) | 0x7F;
+ xEvent.xkey.trans_chars[0] = 0x7F;
+ xEvent.xkey.trans_chars[1] = 0x0;
+ Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
+ }
+}
+
+
+- (NSArray *)validAttributesForMarkedText
+{
+ static NSArray *arr = nil;
+
+ if (arr == nil) {
+ arr = [NSArray new];
+ }
+ /* [[NSArray arrayWithObject: NSUnderlineStyleAttributeName] retain]; */
+ return arr;
+}
+
+
+- (NSRange)selectedRange
+{
+ if (NS_KEYLOG) {
+ TKLog(@"selectedRange request");
+ }
+ return NSMakeRange(NSNotFound, 0);
+}
+
+
+- (NSUInteger)characterIndexForPoint: (NSPoint)thePoint
+{
+ if (NS_KEYLOG) {
+ TKLog(@"characterIndexForPoint request");
+ }
+ return 0;
+}
+
+
+- (NSAttributedString *)attributedSubstringFromRange: (NSRange)theRange
+{
+ static NSAttributedString *str = nil;
+ if (str == nil) {
+ str = [NSAttributedString new];
+ }
+ if (NS_KEYLOG) {
+ TKLog(@"attributedSubstringFromRange request");
+ }
+ return str;
+}
+/* End <NSTextInput> impl. */
+
+@synthesize needsRedisplay = _needsRedisplay;
+@end
+
+
+@implementation TKContentView(TKKeyEvent)
+/* delete display of composing characters [not in <NSTextInput>] */
+- (void)deleteWorkingText
+{
+ if (privateWorkingText == nil) {
+ return;
+ }
+ if (NS_KEYLOG) {
+ TKLog(@"deleteWorkingText len = %lu\n",
+ (unsigned long)[privateWorkingText length]);
+ }
+ [privateWorkingText release];
+ privateWorkingText = nil;
+ processingCompose = NO;
+
+ //PENDING: delete working text
+}
+@end
+
+/*
+ * Set up basic fields in xevent for keyboard input.
+ */
+static void
+setupXEvent(XEvent *xEvent, NSWindow *w, unsigned int state)
+{
+ TkWindow *winPtr = TkMacOSXGetTkWindow(w);
+ Tk_Window tkwin = (Tk_Window) winPtr;
+
+ if (!winPtr) {
+ return;
+ }
+
+ memset(xEvent, 0, sizeof(XEvent));
+ xEvent->xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
+ xEvent->xany.send_event = false;
+ xEvent->xany.display = Tk_Display(tkwin);
+ xEvent->xany.window = Tk_WindowId(tkwin);
+
+ xEvent->xkey.root = XRootWindow(Tk_Display(tkwin), 0);
+ xEvent->xkey.subwindow = None;
+ xEvent->xkey.time = TkpGetMS();
+ xEvent->xkey.state = state;
+ xEvent->xkey.same_screen = true;
+ xEvent->xkey.trans_chars[0] = 0;
+ xEvent->xkey.nbytes = 0;
+}
+
+#pragma mark -
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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)
+{
+ keyboardGrabWinPtr = Tk_IdToWindow(display, grab_window);
+ TkWindow *captureWinPtr = (TkWindow *) TkMacOSXGetCapture();
+
+ if (keyboardGrabWinPtr && captureWinPtr) {
+ NSWindow *w = TkMacOSXDrawableWindow(grab_window);
+ MacDrawable *macWin = (MacDrawable *) grab_window;
+
+ if (w && macWin->toplevel->winPtr == (TkWindow *) captureWinPtr) {
+ if (modalSession) {
+ Tcl_Panic("XGrabKeyboard: already grabbed");
+ }
+ keyboardGrabNSWindow = w;
+ [w retain];
+ modalSession = [NSApp beginModalSessionForWindow:w];
+ }
+ }
+ 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)
+{
+ if (modalSession) {
+ [NSApp endModalSession:modalSession];
+ modalSession = nil;
+ }
+ if (keyboardGrabNSWindow) {
+ [keyboardGrabNSWindow release];
+ keyboardGrabNSWindow = nil;
+ }
+ keyboardGrabWinPtr = NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXGetModalSession --
+ *
+ * Results:
+ * Returns the current modal session
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+MODULE_SCOPE NSModalSession
+TkMacOSXGetModalSession(void)
+{
+ return modalSession;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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(
+ Tk_Window tkwin,
+ int x,
+ int y,
+ int height)
+ {
+ TkCaret *caretPtr = &(((TkWindow *) tkwin)->dispPtr->caret);
+
+ /*
+ * Prevent processing anything if the values haven't changed. Windows only
+ * has one display, so we can do this with statics.
+ */
+
+ if ((caretPtr->winPtr == ((TkWindow *) tkwin))
+ && (caretPtr->x == x) && (caretPtr->y == y)) {
+ return;
+ }
+
+ caretPtr->winPtr = ((TkWindow *) tkwin);
+ caretPtr->x = x;
+ caretPtr->y = y;
+ caretPtr->height = height;
+
+ /*
+ * As in Windows, adjust to the toplevel to get the coords right.
+ */
+
+ while (!Tk_IsTopLevel(tkwin)) {
+ x += Tk_X(tkwin);
+ y += Tk_Y(tkwin);
+ tkwin = Tk_Parent(tkwin);
+ if (tkwin == NULL) {
+ return;
+ }
+ }
+
+ /*
+ * But adjust for fact that NS uses flipped view.
+ */
+
+ y = Tk_Height(tkwin) - y;
+
+ caret_x = x;
+ caret_y = y;
+ caret_height = height;
+}
+
+
+static unsigned convert_ns_to_X_keysym[] =
+{
+ NSHomeFunctionKey, 0x50,
+ NSLeftArrowFunctionKey, 0x51,
+ NSUpArrowFunctionKey, 0x52,
+ NSRightArrowFunctionKey, 0x53,
+ NSDownArrowFunctionKey, 0x54,
+ NSPageUpFunctionKey, 0x55,
+ NSPageDownFunctionKey, 0x56,
+ NSEndFunctionKey, 0x57,
+ NSBeginFunctionKey, 0x58,
+ NSSelectFunctionKey, 0x60,
+ NSPrintFunctionKey, 0x61,
+ NSExecuteFunctionKey, 0x62,
+ NSInsertFunctionKey, 0x63,
+ NSUndoFunctionKey, 0x65,
+ NSRedoFunctionKey, 0x66,
+ NSMenuFunctionKey, 0x67,
+ NSFindFunctionKey, 0x68,
+ NSHelpFunctionKey, 0x6A,
+ NSBreakFunctionKey, 0x6B,
+
+ NSF1FunctionKey, 0xBE,
+ NSF2FunctionKey, 0xBF,
+ NSF3FunctionKey, 0xC0,
+ NSF4FunctionKey, 0xC1,
+ NSF5FunctionKey, 0xC2,
+ NSF6FunctionKey, 0xC3,
+ NSF7FunctionKey, 0xC4,
+ NSF8FunctionKey, 0xC5,
+ NSF9FunctionKey, 0xC6,
+ NSF10FunctionKey, 0xC7,
+ NSF11FunctionKey, 0xC8,
+ NSF12FunctionKey, 0xC9,
+ NSF13FunctionKey, 0xCA,
+ NSF14FunctionKey, 0xCB,
+ NSF15FunctionKey, 0xCC,
+ NSF16FunctionKey, 0xCD,
+ NSF17FunctionKey, 0xCE,
+ NSF18FunctionKey, 0xCF,
+ NSF19FunctionKey, 0xD0,
+ NSF20FunctionKey, 0xD1,
+ NSF21FunctionKey, 0xD2,
+ NSF22FunctionKey, 0xD3,
+ NSF23FunctionKey, 0xD4,
+ NSF24FunctionKey, 0xD5,
+
+ NSBackspaceCharacter, 0x08, /* 8: Not on some KBs. */
+ NSDeleteCharacter, 0xFF, /* 127: Big 'delete' key upper right. */
+ NSDeleteFunctionKey, 0x9F, /* 63272: Del forw key off main array. */
+
+ NSTabCharacter, 0x09,
+ 0x19, 0x09, /* left tab->regular since pass shift */
+ NSCarriageReturnCharacter, 0x0D,
+ NSNewlineCharacter, 0x0D,
+ NSEnterCharacter, 0x8D,
+
+ 0x1B, 0x1B /* escape */
+};
+
+
+static unsigned
+isFunctionKey(
+ unsigned code)
+{
+ const unsigned last_keysym = (sizeof(convert_ns_to_X_keysym)
+ / sizeof(convert_ns_to_X_keysym[0]));
+ unsigned keysym;
+
+ for (keysym = 0; keysym < last_keysym; keysym += 2) {
+ if (code == convert_ns_to_X_keysym[keysym]) {
+ return 0xFF00 | convert_ns_to_X_keysym[keysym + 1];
+ }
+ }
+ return 0;
+}
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXKeyboard.c b/tk8.6/macosx/tkMacOSXKeyboard.c
new file mode 100644
index 0000000..5899064
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXKeyboard.c
@@ -0,0 +1,949 @@
+/*
+ * tkMacOSXKeyboard.c --
+ *
+ * Routines to support keyboard events on the Macintosh.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ * Copyright 2001-2009, Apple Inc.
+ * Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkMacOSXPrivate.h"
+#include "tkMacOSXEvent.h"
+#include "tkMacOSXConstants.h"
+/*
+ * A couple of simple definitions to make code a bit more self-explaining.
+ *
+ * For the assignments of Mod1==meta==command and Mod2==alt==option, see also
+ * tkMacOSXMouseEvent.c.
+ */
+
+#define LATIN1_MAX 255
+#define MAC_KEYCODE_MAX 0x7F
+#define MAC_KEYCODE_MASK 0x7F
+#define COMMAND_MASK Mod1Mask
+#define OPTION_MASK Mod2Mask
+
+
+/*
+ * Tables enumerating the special keys defined on Mac keyboards. These are
+ * necessary for correct keysym mappings for all keys where the keysyms are
+ * not identical with their ASCII or Latin-1 code points.
+ */
+
+typedef struct {
+ int keycode; /* Macintosh keycode. */
+ KeySym keysym; /* X windows keysym. */
+} KeyInfo;
+
+/*
+ * Notes on keyArray:
+ *
+ * 0x34, XK_Return - Powerbooks use this and some keymaps define it.
+ *
+ * 0x4C, XK_Return - XFree86 and Apple's X11 call this one XK_KP_Enter.
+ *
+ * 0x47, XK_Clear - This key is NumLock when used on PCs, but Mac
+ * applications don't use it like that, nor does Apple's X11.
+ *
+ * All other keycodes are taken from the published ADB keyboard layouts.
+ */
+
+static KeyInfo keyArray[] = {
+ {0x24, XK_Return},
+ {0x30, XK_Tab},
+ {0x33, XK_BackSpace},
+ {0x34, XK_Return},
+ {0x35, XK_Escape},
+
+ {0x47, XK_Clear},
+ {0x4C, XK_KP_Enter},
+
+ {0x72, XK_Help},
+ {0x73, XK_Home},
+ {0x74, XK_Page_Up},
+ {0x75, XK_Delete},
+ {0x77, XK_End},
+ {0x79, XK_Page_Down},
+
+ {0x7B, XK_Left},
+ {0x7C, XK_Right},
+ {0x7D, XK_Down},
+ {0x7E, XK_Up},
+
+ {0, 0}
+};
+
+static KeyInfo virtualkeyArray[] = {
+ {122, XK_F1},
+ {120, XK_F2},
+ {99, XK_F3},
+ {118, XK_F4},
+ {96, XK_F5},
+ {97, XK_F6},
+ {98, XK_F7},
+ {100, XK_F8},
+ {101, XK_F9},
+ {109, XK_F10},
+ {103, XK_F11},
+ {111, XK_F12},
+ {105, XK_F13},
+ {107, XK_F14},
+ {113, XK_F15},
+ {0, 0}
+};
+
+#define NUM_MOD_KEYCODES 14
+static KeyCode modKeyArray[NUM_MOD_KEYCODES] = {
+ XK_Shift_L,
+ XK_Shift_R,
+ XK_Control_L,
+ XK_Control_R,
+ XK_Caps_Lock,
+ XK_Shift_Lock,
+ XK_Meta_L,
+ XK_Meta_R,
+ XK_Alt_L,
+ XK_Alt_R,
+ XK_Super_L,
+ XK_Super_R,
+ XK_Hyper_L,
+ XK_Hyper_R,
+};
+
+static int initialized = 0;
+static Tcl_HashTable keycodeTable; /* keyArray hashed by keycode value. */
+static Tcl_HashTable vkeyTable; /* virtualkeyArray hashed by virtual
+ * keycode value. */
+
+static int latin1Table[LATIN1_MAX+1]; /* Reverse mapping table for
+ * controls, ASCII and Latin-1. */
+
+static int keyboardChanged = 1;
+
+/*
+ * Prototypes for static functions used in this file.
+ */
+
+static void InitKeyMaps (void);
+static void InitLatin1Table(Display *display);
+static int XKeysymToMacKeycode(Display *display, KeySym keysym);
+static int KeycodeToUnicode(UniChar * uniChars, int maxChars,
+ UInt16 keyaction, UInt32 keycode, UInt32 modifiers,
+ UInt32 * deadKeyStatePtr);
+
+#pragma mark TKApplication(TKKeyboard)
+
+@implementation TKApplication(TKKeyboard)
+- (void) keyboardChanged: (NSNotification *) notification
+{
+#ifdef TK_MAC_DEBUG_NOTIFICATIONS
+ TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
+#endif
+ keyboardChanged = 1;
+}
+@end
+
+#pragma mark -
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InitKeyMaps --
+ *
+ * Creates hash tables used by some of the functions in this file.
+ *
+ * FIXME: As keycodes are defined to be in the limited range 0-127, it
+ * would be easier and more efficient to use directly initialized plain
+ * arrays and drop this function.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Allocates memory & creates some hash tables.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+InitKeyMaps(void)
+{
+ Tcl_HashEntry *hPtr;
+ KeyInfo *kPtr;
+ int dummy;
+
+ Tcl_InitHashTable(&keycodeTable, TCL_ONE_WORD_KEYS);
+ for (kPtr = keyArray; kPtr->keycode != 0; kPtr++) {
+ hPtr = Tcl_CreateHashEntry(&keycodeTable, INT2PTR(kPtr->keycode),
+ &dummy);
+ Tcl_SetHashValue(hPtr, INT2PTR(kPtr->keysym));
+ }
+ Tcl_InitHashTable(&vkeyTable, TCL_ONE_WORD_KEYS);
+ for (kPtr = virtualkeyArray; kPtr->keycode != 0; kPtr++) {
+ hPtr = Tcl_CreateHashEntry(&vkeyTable, INT2PTR(kPtr->keycode),
+ &dummy);
+ Tcl_SetHashValue(hPtr, INT2PTR(kPtr->keysym));
+ }
+ initialized = 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InitLatin1Table --
+ *
+ * Creates a simple table to be used for mapping from keysyms to keycodes.
+ * Always needs to be called before using latin1Table, because the
+ * keyboard layout may have changed, and than the table must be
+ * re-computed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Sets the global latin1Table.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+InitLatin1Table(
+ Display *display)
+{
+ int keycode;
+ KeySym keysym;
+ int state;
+ int modifiers;
+
+ memset(latin1Table, 0, sizeof(latin1Table));
+
+ /*
+ * In the common X11 implementations, a keymap has four columns
+ * "plain", "Shift", "Mode_switch" and "Mode_switch + Shift". We don't
+ * use "Mode_switch", but we use "Option" instead. (This is similar to
+ * Apple's X11 implementation, where "Mode_switch" is used as an alias
+ * for "Option".)
+ *
+ * So here we go through all 4 columns of the keymap and find all
+ * Latin-1 compatible keycodes. We go through the columns back-to-front
+ * from the more exotic columns to the more simple, so that simple
+ * keycode-modifier combinations are preferred in the resulting table.
+ */
+
+ for (state = 3; state >= 0; state--) {
+ modifiers = 0;
+ if (state & 1) {
+ modifiers |= shiftKey;
+ }
+ if (state & 2) {
+ modifiers |= optionKey;
+ }
+
+ for (keycode = 0; keycode <= MAC_KEYCODE_MAX; keycode++) {
+ keysym = XKeycodeToKeysym(display,keycode<<16,state);
+ if (keysym <= LATIN1_MAX) {
+ latin1Table[keysym] = keycode | modifiers;
+ }
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * KeycodeToUnicode --
+ *
+ * Given MacOS key event data this function generates the Unicode
+ * characters. It does this using OS resources and APIs.
+ *
+ * The parameter deadKeyStatePtr can be NULL, if no deadkey handling is
+ * needed.
+ *
+ * This function is called from XKeycodeToKeysym() in tkMacOSKeyboard.c.
+ *
+ * Results:
+ * The number of characters generated if any, 0 if we are waiting for
+ * another byte of a dead-key sequence. Fills in the uniChars array with a
+ * Unicode string.
+ *
+ * Side Effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+KeycodeToUnicode(
+ UniChar *uniChars,
+ int maxChars,
+ UInt16 keyaction,
+ UInt32 keycode,
+ UInt32 modifiers,
+ UInt32 *deadKeyStatePtr)
+{
+ static const void *uchr = NULL;
+ static UInt32 keyboardType = 0;
+ UniCharCount actuallength = 0;
+
+ if (keyboardChanged) {
+ TISInputSourceRef currentKeyboardLayout =
+ TISCopyCurrentKeyboardLayoutInputSource();
+
+ if (currentKeyboardLayout) {
+ CFDataRef keyLayoutData = (CFDataRef) TISGetInputSourceProperty(
+ currentKeyboardLayout, kTISPropertyUnicodeKeyLayoutData);
+
+ if (keyLayoutData) {
+ uchr = CFDataGetBytePtr(keyLayoutData);
+ keyboardType = LMGetKbdType();
+ }
+ CFRelease(currentKeyboardLayout);
+ }
+ keyboardChanged = 0;
+ }
+ if (uchr) {
+ OptionBits options = 0;
+ UInt32 dummyState;
+ OSStatus err;
+
+ keycode &= 0xFF;
+ modifiers = (modifiers >> 8) & 0xFF;
+
+ if (!deadKeyStatePtr) {
+ options = kUCKeyTranslateNoDeadKeysMask;
+ dummyState = 0;
+ deadKeyStatePtr = &dummyState;
+ }
+
+ err = ChkErr(UCKeyTranslate, uchr, keycode, keyaction, modifiers,
+ keyboardType, options, deadKeyStatePtr, maxChars,
+ &actuallength, uniChars);
+
+ if (!actuallength && *deadKeyStatePtr) {
+ /*
+ * More data later
+ */
+
+ return 0;
+ }
+ *deadKeyStatePtr = 0;
+ if (err != noErr) {
+ actuallength = 0;
+ }
+ }
+ return actuallength;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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 newKeycode;
+ UniChar newChar;
+
+ (void) display; /*unused*/
+
+ if (!initialized) {
+ InitKeyMaps();
+ }
+
+ /*
+ * When determining what keysym to produce we first check to see if the key
+ * is a function key. We then check to see if the character is another
+ * non-printing key. Finally, we return the key syms for all ASCII and
+ * Latin-1 chars.
+ */
+
+ newKeycode = keycode >> 16;
+
+ if ((keycode & 0xFFFF) >= 0xF700) { /* NSEvent.h function key unicodes */
+ hPtr = Tcl_FindHashEntry(&vkeyTable, INT2PTR(newKeycode));
+ if (hPtr != NULL) {
+ return (KeySym) Tcl_GetHashValue(hPtr);
+ }
+ }
+ hPtr = Tcl_FindHashEntry(&keycodeTable, INT2PTR(newKeycode));
+ if (hPtr != NULL) {
+ return (KeySym) Tcl_GetHashValue(hPtr);
+ }
+
+ /*
+ * Add in the Mac modifier flags for shift and option.
+ */
+
+ if (index & 1) {
+ newKeycode |= shiftKey;
+ }
+ if (index & 2) {
+ newKeycode |= optionKey;
+ }
+
+ newChar = 0;
+ KeycodeToUnicode(&newChar, 1, kUCKeyActionDown, newKeycode & 0x00FF,
+ newKeycode & 0xFF00, NULL);
+
+ /*
+ * X11 keysyms are identical to Unicode for ASCII and Latin-1. Give up for
+ * other characters for now.
+ */
+
+ if ((newChar >= XK_space) && (newChar <= LATIN1_MAX)) {
+ return newChar;
+ }
+
+ return NoSymbol;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpGetString --
+ *
+ * Retrieve the string equivalent for the given keyboard event.
+ *
+ * Results:
+ * Returns the UTF string.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+const 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. */
+{
+ (void) winPtr; /*unused*/
+ Tcl_DStringInit(dsPtr);
+ return Tcl_DStringAppend(dsPtr, eventPtr->xkey.trans_chars, -1);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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;
+
+ (void) display; /*unused*/
+
+ /*
+ * MacOSX doesn't use the key codes for the modifiers for anything, and we
+ * don't generate them either. So there is no modifier map.
+ */
+ modmap = 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+XFreeModifiermap(
+ XModifierKeymap *modmap)
+{
+ if (modmap->modifiermap != NULL) {
+ ckfree(modmap->modifiermap);
+ }
+ ckfree(modmap);
+ return Success;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XKeysymToString, XStringToKeysym --
+ *
+ * These X window functions map keysyms to strings & strings to keysyms.
+ * However, Tk already does this for the most common keysyms. Therefore,
+ * these functions only need to support keysyms that will be specific to
+ * the Macintosh. Currently, there are none.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+XKeysymToString(
+ KeySym keysym)
+{
+ return NULL;
+}
+
+KeySym
+XStringToKeysym(
+ const char* string)
+{
+ return NoSymbol;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XKeysymToMacKeycode --
+ *
+ * An internal function like XKeysymToKeycode but only generating the Mac
+ * specific keycode plus the modifiers Shift and Option.
+ *
+ * Results:
+ * A Mac keycode with the actual keycode in the low byte and Mac-style
+ * modifier bits in the high byte.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+XKeysymToMacKeycode(
+ Display *display,
+ KeySym keysym)
+{
+ KeyInfo *kPtr;
+ if (keysym <= LATIN1_MAX) {
+ /*
+ * Handle keysyms in the Latin-1 range where keysym and Unicode
+ * character code point are the same.
+ */
+
+ if (keyboardChanged) {
+ InitLatin1Table(display);
+ keyboardChanged = 0;
+ }
+ return latin1Table[keysym];
+ }
+
+ /*
+ * Handle special keys from our exception tables. Don't mind if this is
+ * slow, neither the test suite nor [event generate] need to be optimized
+ * (we hope).
+ */
+
+ for (kPtr = keyArray; kPtr->keycode != 0; kPtr++) {
+ if (kPtr->keysym == keysym) {
+ return kPtr->keycode;
+ }
+ }
+ for (kPtr = virtualkeyArray; kPtr->keycode != 0; kPtr++) {
+ if (kPtr->keysym == keysym) {
+ return kPtr->keycode;
+ }
+ }
+
+ /*
+ * Modifier keycodes only come from generated events. No translation
+ * is needed.
+ */
+
+ for (int i=0; i < NUM_MOD_KEYCODES; i++) {
+ if (keysym == modKeyArray[i]) {
+ return keysym;
+ }
+ }
+
+ /*
+ * For other keysyms (not Latin-1 and not special keys), we'd need a
+ * generic keysym-to-unicode table. We don't have that, so we give up here.
+ */
+
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XKeysymToKeycode --
+ *
+ * The function XKeysymToKeycode takes an X11 keysym and converts it into
+ * a Mac keycode. It is in the stubs table for compatibility but not used
+ * anywhere in the core.
+ *
+ * Results:
+ * A 32 bit keycode with the the mac keycode (without modifiers) in the
+ * higher 16 bits of the keycode and the ASCII or Latin-1 code in the
+ * lower 8 bits of the keycode.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+KeyCode
+XKeysymToKeycode(
+ Display* display,
+ KeySym keysym)
+{
+ int macKeycode = XKeysymToMacKeycode(display, keysym);
+ KeyCode result;
+
+ /*
+ * See also TkpSetKeycodeAndState. The 0x0010 magic is used in
+ * XKeycodeToKeysym. For special keys like XK_Return the lower 8 bits of
+ * the keysym are usually a related ASCII control code.
+ */
+
+ if ((keysym >= XK_F1) && (keysym <= XK_F35)) {
+ result = 0x0010;
+ } else {
+ result = 0x00FF & keysym;
+ }
+ result |= (macKeycode & MAC_KEYCODE_MASK) << 16;
+
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpSetKeycodeAndState --
+ *
+ * The function TkpSetKeycodeAndState takes a keysym and fills in the
+ * appropriate members of an XEvent. It is similar to XKeysymToKeycode,
+ * but it also sets the modifier mask in the XEvent. It is used by [event
+ * generate] and it is in the stubs table.
+ *
+ * Results:
+ * Fills an XEvent, sets the member xkey.keycode with a keycode
+ * formatted the same as XKeysymToKeycode and the member xkey.state with
+ * the modifiers implied by the keysym. Also fills in xkey.trans_chars,
+ * so that the actual characters can be retrieved later.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpSetKeycodeAndState(
+ Tk_Window tkwin,
+ KeySym keysym,
+ XEvent *eventPtr)
+{
+ if (keysym == NoSymbol) {
+ eventPtr->xkey.keycode = 0;
+ } else if ( modKeyArray[0] <= keysym &&
+ keysym <= modKeyArray[NUM_MOD_KEYCODES - 1]) {
+ /*
+ * Keysyms for pure modifiers only arise in generated events.
+ * We should just copy them to the keycode.
+ */
+ eventPtr->xkey.keycode = keysym;
+ } else {
+ Display *display = Tk_Display(tkwin);
+ int macKeycode = XKeysymToMacKeycode(display, keysym);
+
+ /*
+ * See also XKeysymToKeycode.
+ */
+ if ((keysym >= XK_F1) && (keysym <= XK_F35)) {
+ eventPtr->xkey.keycode = 0x0010;
+ } else {
+ eventPtr->xkey.keycode = 0x00FF & keysym;
+ }
+ eventPtr->xkey.keycode |= (macKeycode & MAC_KEYCODE_MASK) << 16;
+
+ if (shiftKey & macKeycode) {
+ eventPtr->xkey.state |= ShiftMask;
+ }
+ if (optionKey & macKeycode) {
+ eventPtr->xkey.state |= OPTION_MASK;
+ }
+
+ if (keysym <= LATIN1_MAX) {
+ int done = Tcl_UniCharToUtf(keysym, eventPtr->xkey.trans_chars);
+
+ eventPtr->xkey.trans_chars[done] = 0;
+ } else {
+ eventPtr->xkey.trans_chars[0] = 0;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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(
+ 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);
+ }
+
+ /*
+ * Handle pure modifier keys specially. We use -1 as a signal for
+ * this.
+ */
+
+ if (eventPtr->xany.send_event == -1) {
+ int modifier = eventPtr->xkey.keycode & NSDeviceIndependentModifierFlagsMask;
+
+ if (modifier == NSCommandKeyMask) {
+ return XK_Meta_L;
+ } else if (modifier == NSShiftKeyMask) {
+ return XK_Shift_L;
+ } else if (modifier == NSAlphaShiftKeyMask) {
+ return XK_Caps_Lock;
+ } else if (modifier == NSAlternateKeyMask) {
+ return XK_Alt_L;
+ } else if (modifier == NSControlKeyMask) {
+ return XK_Control_L;
+ } else if (modifier == NSNumericPadKeyMask) {
+ return XK_Num_Lock;
+ } else if (modifier == NSFunctionKeyMask) {
+ return XK_Super_L;
+/*
+ } else if (modifier == rightShiftKey) {
+ return XK_Shift_R;
+ } else if (modifier == rightOptionKey) {
+ return XK_Alt_R;
+ } else if (modifier == rightControlKey) {
+ return XK_Control_R;
+*/
+ } else {
+ /*
+ * If we get here, we probably need to implement something new.
+ */
+
+ return NoSymbol;
+ }
+ }
+
+ /* If nbytes has been set, it's not a function key, but a regular key that
+ has been translated in tkMacOSXKeyEvent.c; just use that. */
+ if (eventPtr->xkey.nbytes) {
+ return eventPtr->xkey.keycode & 0xFFFF;
+ }
+
+ /*
+ * Figure out which of the four slots in the keymap vector to use for this
+ * key. Refer to Xlib documentation for more info on how this computation
+ * works. (Note: We use "Option" in keymap columns 2 and 3 where other
+ * implementations have "Mode_switch".)
+ */
+
+ index = 0;
+
+ /*
+ * We want Option key combinations to use their base chars as keysyms, so
+ * we ignore the option modifier here.
+ */
+
+#if 0
+ if (eventPtr->xkey.state & OPTION_MASK) {
+ index |= 2;
+ }
+#endif
+
+ if ((eventPtr->xkey.state & ShiftMask)
+ || (/* (dispPtr->lockUsage != LU_IGNORE)
+ && */ (eventPtr->xkey.state & LockMask))) {
+ index |= 1;
+ }
+
+ /*
+ * First try of the actual translation.
+ */
+
+ 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)*/ ) {
+ /*
+ * FIXME: Keysyms are only identical to Unicode for ASCII and Latin-1,
+ * so we can't use Tcl_UniCharIsUpper() for keysyms outside that range.
+ * This may be a serious problem here.
+ */
+
+ if ((sym == NoSymbol) || (sym > LATIN1_MAX)
+ || !Tcl_UniCharIsUpper(sym)) {
+ index &= ~1;
+ sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
+ index);
+ }
+ }
+
+ /*
+ * 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 the "Mode_switch" keysym.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Keymap-related information in dispPtr is updated.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkpInitKeymapInfo(
+ TkDisplay *dispPtr) /* Display for which to recompute keymap
+ * information. */
+{
+ dispPtr->bindInfoStale = 0;
+
+ /*
+ * Behaviours that are variable on X11 are defined constant on MacOSX.
+ * lockUsage is only used above in TkpGetKeySym(), nowhere else currently.
+ * There is no offical "Mode_switch" key.
+ */
+
+ dispPtr->lockUsage = LU_CAPS;
+ dispPtr->modeModMask = 0;
+
+#if 0
+ /*
+ * With this, <Alt> and <Meta> become synonyms for <Command> and <Option>
+ * in bindings like they are (and always have been) in the keysyms that
+ * are reported by KeyPress events. But the init scripts like text.tcl
+ * have some disabling bindings for <Meta>, so we don't want this without
+ * some changes in those scripts. See also bug #700311.
+ */
+
+ dispPtr->altModMask = OPTION_MASK;
+ dispPtr->metaModMask = COMMAND_MASK;
+#else
+ dispPtr->altModMask = 0;
+ dispPtr->metaModMask = 0;
+#endif
+
+ /*
+ * MacOSX doesn't create a key event when a modifier key is pressed or
+ * released. However, it is possible to generate key events for
+ * modifier keys, and this is done in the tests. So we construct an array
+ * containing the keycodes of the standard modifier keys from static data.
+ */
+
+ if (dispPtr->modKeyCodes != NULL) {
+ ckfree(dispPtr->modKeyCodes);
+ }
+ dispPtr->numModKeyCodes = NUM_MOD_KEYCODES;
+ dispPtr->modKeyCodes = (KeyCode *)ckalloc(NUM_MOD_KEYCODES * sizeof(KeyCode));
+ for (int i = 0; i < NUM_MOD_KEYCODES; i++) {
+ dispPtr->modKeyCodes[i] = modKeyArray[i];
+ }
+}
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXMenu.c b/tk8.6/macosx/tkMacOSXMenu.c
new file mode 100644
index 0000000..790b6ff
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXMenu.c
@@ -0,0 +1,1923 @@
+/*
+ * tkMacOSXMenu.c --
+ *
+ * This module implements the Mac-platform specific features of menus.
+ *
+ * Copyright (c) 1996-1997 by Sun Microsystems, Inc.
+ * Copyright 2001-2009, Apple Inc.
+ * Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright (c) 2012 Adrian Robert.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkMacOSXPrivate.h"
+#include "tkMenubutton.h"
+#include "tkMenu.h"
+#include "tkColor.h"
+#include "tkFont.h"
+#include "tkMacOSXWm.h"
+#include "tkMacOSXDebug.h"
+#include "tkMacOSXConstants.h"
+
+/*
+#ifdef TK_MAC_DEBUG
+#define TK_MAC_DEBUG_MENUS
+#endif
+*/
+
+#define ENTRY_HELP_MENU ENTRY_PLATFORM_FLAG1
+#define ENTRY_APPLE_MENU ENTRY_PLATFORM_FLAG2
+#define ENTRY_WINDOWS_MENU ENTRY_PLATFORM_FLAG3
+
+#define sl(s) ((int) (sizeof(s "") - 1))
+
+#define SPECIALMENU(n, f) {.name = "." #n, .len = sl(#n) + 1, \
+ .flag = ENTRY_##f##_MENU }
+static const struct {
+ const char *name; const size_t len; const int flag;
+} specialMenus[] = {
+ SPECIALMENU(help, HELP),
+ SPECIALMENU(apple, APPLE),
+ SPECIALMENU(window, WINDOWS),
+ {NULL}
+};
+#undef SPECIALMENU
+
+#define MODIFIER(n, f) {.name = #n, .len = sl(#n), .mask = f }
+static const struct {
+ const char *name; const size_t len; const NSUInteger mask;
+} modifiers[] = {
+ MODIFIER(Control, NSControlKeyMask),
+ MODIFIER(Ctrl, NSControlKeyMask),
+ MODIFIER(Option, NSAlternateKeyMask),
+ MODIFIER(Opt, NSAlternateKeyMask),
+ MODIFIER(Alt, NSAlternateKeyMask),
+ MODIFIER(Shift, NSShiftKeyMask),
+ MODIFIER(Command, NSCommandKeyMask),
+ MODIFIER(Cmd, NSCommandKeyMask),
+ MODIFIER(Meta, NSCommandKeyMask),
+ {NULL}
+};
+#undef MODIFIER
+
+#define ACCEL(n, c) {.name = #n, .len = sl(#n), .ch = c }
+static const struct {
+ const char *name; const size_t len; const UniChar ch;
+} specialAccelerators[] = {
+ ACCEL(PageUp, NSPageUpFunctionKey),
+ ACCEL(PageDown, NSPageDownFunctionKey),
+ ACCEL(Left, NSLeftArrowFunctionKey),
+ ACCEL(Right, NSRightArrowFunctionKey),
+ ACCEL(Up, NSUpArrowFunctionKey),
+ ACCEL(Down, NSDownArrowFunctionKey),
+ ACCEL(Escape, 0x001b),
+ ACCEL(Clear, NSClearDisplayFunctionKey),
+ ACCEL(Enter, NSEnterCharacter),
+ ACCEL(Backspace, NSBackspaceCharacter),
+ ACCEL(Space, ' '),
+ ACCEL(Tab, NSTabCharacter),
+ ACCEL(BackTab, NSBackTabCharacter),
+ ACCEL(Delete, NSDeleteCharacter),
+ ACCEL(Home, NSHomeFunctionKey),
+ ACCEL(End, NSEndFunctionKey),
+ ACCEL(Return, NSCarriageReturnCharacter),
+ ACCEL(Help, NSHelpFunctionKey),
+ ACCEL(Power, 0x233d),
+ ACCEL(Eject, 0xf804),
+ {NULL}
+};
+#undef ACCEL
+#undef sl
+
+static int gNoTkMenus = 0; /* This is used by Tk_MacOSXTurnOffMenus as
+ * the flag that Tk is not to draw any
+ * menus. */
+static int inPostMenu = 0;
+static unsigned long defaultBg = 0, defaultFg = 0;
+static SInt32 menuMarkColumnWidth = 0, menuIconTrailingEdgeMargin = 0;
+static SInt32 menuTextLeadingEdgeMargin = 0, menuTextTrailingEdgeMargin = 0;
+static SInt16 menuItemExtraHeight = 0, menuItemExtraWidth = 0;
+static SInt16 menuSeparatorHeight = 0;
+
+static void CheckForSpecialMenu(TkMenu *menuPtr);
+static NSString *ParseAccelerator(const char *accel, NSUInteger *maskPtr);
+static int GenerateMenuSelectEvent(TKMenu *menu, NSMenuItem *menuItem);
+static void MenuSelectEvent(TkMenu *menuPtr);
+static void RecursivelyClearActiveMenu(TkMenu *menuPtr);
+static int ModifierCharWidth(Tk_Font tkfont);
+
+#pragma mark TKMenu
+
+/*
+ * This interface is not declared in tkMacOSXPrivate.h because it requires
+ * tkMenu.h.
+ */
+
+@interface TKMenu(TKMenuPrivate)
+- (id) initWithTkMenu: (TkMenu *) tkMenu;
+- (TkMenu *) tkMenu;
+- (int) tkIndexOfItem: (NSMenuItem *) menuItem;
+- (void) insertItem: (NSMenuItem *) newItem atTkIndex: (NSInteger) index;
+@end
+
+@implementation TKMenu
+- (void) setSpecial: (NSUInteger) special
+{
+ NSAssert(!_tkSpecial, @"Cannot change specialness of a special menu");
+ _tkSpecial = special;
+}
+- (BOOL) isSpecial: (NSUInteger) special
+{
+ return (_tkSpecial == special);
+}
+@end
+
+@implementation TKMenu(TKMenuPrivate)
+
+- (id) initWithTitle: (NSString *) aTitle
+{
+ self = [super initWithTitle:aTitle];
+ if (self) {
+ _tkMenu = NULL;
+ _tkOffset = 0;
+ _tkItemCount = 0;
+ _tkSpecial = 0;
+ [self setDelegate:self];
+ }
+ return self;
+}
+
+- (id) initWithTkMenu: (TkMenu *) tkMenu
+{
+ NSString *title = [[NSString alloc] initWithUTF8String:
+ Tk_PathName(tkMenu->tkwin)];
+
+ self = [self initWithTitle:title];
+ [title release];
+ if (self) {
+ _tkMenu = tkMenu;
+ }
+ return self;
+}
+
+- (id) copyWithZone: (NSZone *) zone
+{
+ TKMenu *copy = [super copyWithZone:zone];
+
+ NSAssert(_tkMenu == nil, @"Cannot copy tkMenu");
+ copy->_tkMenu = _tkMenu;
+ copy->_tkOffset = _tkOffset;
+ copy->_tkItemCount = _tkItemCount;
+ copy->_tkSpecial = _tkSpecial;
+ return copy;
+}
+
+- (TkMenu *) tkMenu
+{
+ return _tkMenu;
+}
+
+- (int) tkIndexOfItem: (NSMenuItem *) menuItem
+{
+ return [self indexOfItem:menuItem] - _tkOffset;
+}
+
+- (void) insertItem: (NSMenuItem *) newItem atTkIndex: (NSInteger) index
+{
+ [super insertItem:newItem atIndex:index + _tkOffset];
+ _tkItemCount++;
+}
+
+- (void) insertItem: (NSMenuItem *) newItem atIndex: (NSInteger) index
+{
+ if (_tkMenu && index >= 0) {
+ if ((NSUInteger) index <= _tkOffset) {
+ _tkOffset++;
+ } else {
+ NSAssert((NSUInteger) index >= _tkItemCount + _tkOffset,
+ @"Cannot insert in the middle of Tk menu");
+ }
+ }
+ [super insertItem:newItem atIndex:index];
+}
+
+- (void) removeItemAtIndex: (NSInteger) index
+{
+ if (_tkMenu && index >= 0) {
+ if ((NSUInteger) index < _tkOffset) {
+ _tkOffset--;
+ } else if ((NSUInteger) index < _tkItemCount + _tkOffset) {
+ _tkItemCount--;
+ }
+ }
+ [super removeItemAtIndex:index];
+}
+
+- (NSMenuItem *) newTkMenuItem: (TkMenuEntry *) mePtr
+{
+ NSMenuItem *menuItem = [[NSMenuItem alloc] initWithTitle:@""
+ action:@selector(tkMenuItemInvoke:) keyEquivalent:@""];
+
+ [menuItem setTarget:self];
+ [menuItem setTag:(NSInteger) mePtr];
+ return menuItem;
+}
+@end
+
+@implementation TKMenu(TKMenuActions)
+
+- (BOOL) validateMenuItem: (NSMenuItem *) menuItem
+{
+ return [menuItem isEnabled];
+}
+
+/*
+ * Workaround for bug 3572016; leave menu items enabled during modal dialog.
+ */
+
+- (BOOL)worksWhenModal
+{
+ return YES;
+}
+
+- (void) tkMenuItemInvoke: (id) sender
+{
+ /*
+ * With the delegate matching key equivalents, when a menu action is sent
+ * in response to a key equivalent, the sender is the whole menu and not the
+ * specific menu item. We use this to ignore key equivalents for Tk
+ * menus (as Tk handles them directly via bindings).
+ */
+
+ if ([sender isKindOfClass:[NSMenuItem class]]) {
+ NSMenuItem *menuItem = (NSMenuItem *) sender;
+ TkMenu *menuPtr = (TkMenu *) _tkMenu;
+ TkMenuEntry *mePtr = (TkMenuEntry *) [menuItem tag];
+
+ if (menuPtr && mePtr) {
+ Tcl_Interp *interp = menuPtr->interp;
+
+ /*
+ * Add time for errors to fire if necessary. This is sub-optimal
+ * but avoids issues with Tcl/Cocoa event loop integration.
+ */
+
+ //Tcl_Sleep(100);
+ Tcl_Preserve(interp);
+ Tcl_Preserve(menuPtr);
+
+ int result = TkInvokeMenu(interp, menuPtr, mePtr->index);
+
+ if (result != TCL_OK && result != TCL_CONTINUE &&
+ result != TCL_BREAK) {
+ Tcl_AddErrorInfo(interp, "\n (menu invoke)");
+ Tcl_BackgroundException(interp, result);
+ }
+ Tcl_Release(menuPtr);
+ Tcl_Release(interp);
+ }
+ }
+}
+@end
+
+@implementation TKMenu(TKMenuDelegate)
+
+- (BOOL) menuHasKeyEquivalent: (NSMenu *) menu forEvent: (NSEvent *) event
+ target: (id *) target action: (SEL *) action
+{
+ /*
+ * Use lowercaseString when comparing keyEquivalents since the notion of
+ * a shifted upper case letter does not make much sense.
+ */
+
+ NSString *key = [[event charactersIgnoringModifiers] lowercaseString];
+ NSUInteger modifiers = [event modifierFlags] &
+ NSDeviceIndependentModifierFlagsMask;
+
+ if (modifiers == (NSCommandKeyMask | NSShiftKeyMask) &&
+ [key compare:@"?"] == NSOrderedSame) {
+ /*
+ * Command-Shift-? has not been allowed as a keyboard equivalent since
+ * the first aqua port, for some mysterious reason.
+ */
+
+ return NO;
+ } else if (modifiers == (NSControlKeyMask | NSShiftKeyMask) &&
+ [event keyCode] == 48) {
+ /*
+ * Starting with OSX 10.12 Control-Tab and Control-Shift-Tab are used
+ * to select window tabs. But for some even more mysterious reason the
+ * Control-Shift-Tab event has character 0x19 = NSBackTabCharacter
+ * rather than 0x09 = NSTabCharacter. At the same time, the
+ * keyEquivalent must be \0x09 in order for it to be displayed
+ * correctly in the menu. This makes it impossible for the standard
+ * "Select Previous Tab" to work correctly, unless we intervene.
+ */
+
+ key = @"\t";
+ } else if (([event modifierFlags] & NSCommandKeyMask) == NSCommandKeyMask) {
+ /*
+ * If the command modifier is set, use the full character string so
+ * things like the dvorak / qwerty layout will work.
+ */
+
+ key = [event characters];
+ }
+
+ NSArray *itemArray = [self itemArray];
+ for (NSMenuItem *item in itemArray) {
+ if ([item isEnabled] &&
+ [[item keyEquivalent] compare:key] == NSOrderedSame) {
+ NSUInteger keyEquivModifiers = [item keyEquivalentModifierMask];
+ if (keyEquivModifiers == modifiers) {
+ *target = [item target];
+ *action = [item action];
+ return YES;
+ }
+ }
+ }
+ return NO;
+}
+
+- (void) menuWillOpen: (NSMenu *) menu
+{
+ if (_tkMenu) {
+ //RecursivelyClearActiveMenu(_tkMenu);
+ GenerateMenuSelectEvent((TKMenu *)[self supermenu],
+ [self itemInSupermenu]);
+ }
+}
+
+- (void) menuDidClose: (NSMenu *) menu
+{
+ if (_tkMenu) {
+ RecursivelyClearActiveMenu(_tkMenu);
+ }
+}
+
+- (void) menu: (NSMenu *) menu willHighlightItem: (NSMenuItem *) item
+{
+ if (_tkMenu) {
+ GenerateMenuSelectEvent(self, item);
+ }
+}
+
+- (void) menuNeedsUpdate: (NSMenu *) menu
+{
+ TkMenu *menuPtr = (TkMenu *) _tkMenu;
+
+ if (menuPtr) {
+ Tcl_Interp *interp = menuPtr->interp;
+
+ Tcl_Preserve(interp);
+ Tcl_Preserve(menuPtr);
+
+ int result = TkPostCommand(_tkMenu);
+
+ if (result!=TCL_OK && result!=TCL_CONTINUE && result!=TCL_BREAK) {
+ Tcl_AddErrorInfo(interp, "\n (menu preprocess)");
+ Tcl_BackgroundException(interp, result);
+ }
+ Tcl_Release(menuPtr);
+ Tcl_Release(interp);
+ }
+}
+@end
+
+#pragma mark TKApplication(TKMenu)
+
+@implementation TKApplication(TKMenu)
+
+- (void) menuBeginTracking: (NSNotification *) notification
+{
+#ifdef TK_MAC_DEBUG_NOTIFICATIONS
+ TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
+#endif
+ //TkMacOSXClearMenubarActive();
+ //TkMacOSXPreprocessMenu();
+}
+
+- (void) menuEndTracking: (NSNotification *) notification
+{
+#ifdef TK_MAC_DEBUG_NOTIFICATIONS
+ TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
+#endif
+ if (!inPostMenu) {
+ TkMacOSXClearMenubarActive();
+ }
+}
+
+- (void) tkSetMainMenu: (TKMenu *) menu
+{
+ if (gNoTkMenus) {
+ return;
+ }
+
+ TKMenu *applicationMenu = nil;
+
+ if (menu) {
+ NSMenuItem *applicationMenuItem = [menu numberOfItems] ?
+ [menu itemAtIndex:0] : nil;
+
+ if (![menu isSpecial:tkMainMenu]) {
+ TkMenuEntry *mePtr = (TkMenuEntry *)[applicationMenuItem tag];
+
+ if (!mePtr || !(mePtr->entryFlags & ENTRY_APPLE_MENU)) {
+ applicationMenuItem = [NSMenuItem itemWithSubmenu:
+ [_defaultApplicationMenu copy]];
+ [menu insertItem:applicationMenuItem atIndex:0];
+ }
+ [menu setSpecial:tkMainMenu];
+ }
+ applicationMenu = (TKMenu *)[applicationMenuItem submenu];
+ if (![applicationMenu isSpecial:tkApplicationMenu]) {
+ for (NSMenuItem *item in _defaultApplicationMenuItems) {
+ [applicationMenu addItem:[item copy]];
+ }
+ [applicationMenu setSpecial:tkApplicationMenu];
+ }
+
+ NSArray *itemArray = [menu itemArray];
+
+ for (NSMenuItem *item in itemArray) {
+ TkMenuEntry *mePtr = (TkMenuEntry *)[item tag];
+ TKMenu *submenu = (TKMenu *)[item submenu];
+ if (mePtr && submenu) {
+ if ((mePtr->entryFlags & ENTRY_WINDOWS_MENU) &&
+ ![submenu isSpecial:tkWindowsMenu]) {
+ NSInteger index = 0;
+
+ for (NSMenuItem *i in _defaultWindowsMenuItems) {
+ [submenu insertItem:[i copy] atIndex:index++];
+ }
+ [self setWindowsMenu:submenu];
+ [submenu setSpecial:tkWindowsMenu];
+ } else if ((mePtr->entryFlags & ENTRY_HELP_MENU) &&
+ ![submenu isSpecial:tkHelpMenu]) {
+ NSInteger index = 0;
+
+ for (NSMenuItem *i in _defaultHelpMenuItems) {
+ [submenu insertItem:[i copy] atIndex:index++];
+ }
+ [submenu setSpecial:tkHelpMenu];
+ }
+ }
+ }
+ } else {
+ menu = _defaultMainMenu;
+ applicationMenu = _defaultApplicationMenu;
+ }
+
+ NSMenuItem *servicesMenuItem =
+ [applicationMenu itemWithTitle:@"Services"];
+
+ if (servicesMenuItem && [servicesMenuItem submenu] != _servicesMenu) {
+ [[_servicesMenu itemInSupermenu] setSubmenu:nil];
+ [servicesMenuItem setSubmenu:_servicesMenu];
+ }
+ [self setAppleMenu:applicationMenu];
+ [self setMainMenu:menu];
+}
+@end
+
+#pragma mark -
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpNewMenu --
+ *
+ * Gets a new blank menu. Only the platform specific options are filled
+ * in.
+ *
+ * Results:
+ * Returns a standard Tcl error.
+ *
+ * Side effects:
+ * Allocates a NSMenu and puts it into the platformData field of the
+ * menuPtr.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkpNewMenu(
+ TkMenu *menuPtr) /* The common structure we are making the
+ * platform structure for. */
+{
+ TKMenu *menu = [[TKMenu alloc] initWithTkMenu:menuPtr];
+ menuPtr->platformData = (TkMenuPlatformData) menu;
+ CheckForSpecialMenu(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 */
+{
+ NSMenu* nsmenu = (NSMenu*)(menuPtr->platformData);
+
+ [nsmenu release];
+ menuPtr->platformData = NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * 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 */
+{
+ TKMenu *menu = (TKMenu *) mePtr->menuPtr->platformData;
+ NSMenuItem *menuItem;
+ if (mePtr->type == SEPARATOR_ENTRY || mePtr->type == TEAROFF_ENTRY) {
+ menuItem = [[NSMenuItem separatorItem] retain];
+ } else {
+ menuItem = [menu newTkMenuItem:mePtr];
+ }
+ mePtr->platformEntryData = (TkMenuPlatformEntryData) menuItem;
+
+ /*
+ * Caller TkMenuEntry() already did this same insertion into the generic
+ * TkMenu so we just match it for the platform menu.
+ */
+
+ [menu insertItem:menuItem atTkIndex:mePtr->index];
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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. */
+{
+ NSMenuItem *menuItem = (NSMenuItem *) mePtr->platformEntryData;
+ NSString *title = @"";
+ NSAttributedString *attributedTitle = nil;
+ NSImage *image = nil;
+ NSString *keyEquivalent = @"";
+ NSUInteger modifierMask = NSCommandKeyMask;
+ NSMenu *submenu = nil;
+ NSDictionary *attributes;
+ int imageWidth, imageHeight;
+ GC gc = (mePtr->textGC ? mePtr->textGC : mePtr->menuPtr->textGC);
+ Tcl_Obj *fontPtr = (mePtr->fontPtr ? mePtr->fontPtr :
+ mePtr->menuPtr->fontPtr);
+
+ if (mePtr->image) {
+ Tk_SizeOfImage(mePtr->image, &imageWidth, &imageHeight);
+ image = TkMacOSXGetNSImageWithTkImage(mePtr->menuPtr->display,
+ mePtr->image, imageWidth, imageHeight);
+ } else if (mePtr->bitmapPtr != None) {
+ Pixmap bitmap = Tk_GetBitmapFromObj(mePtr->menuPtr->tkwin,
+ mePtr->bitmapPtr);
+
+ Tk_SizeOfBitmap(mePtr->menuPtr->display, bitmap, &imageWidth,
+ &imageHeight);
+ image = TkMacOSXGetNSImageWithBitmap(mePtr->menuPtr->display, bitmap,
+ gc, imageWidth, imageHeight);
+ }
+ [menuItem setImage:image];
+ if ((!image || mePtr->compound != COMPOUND_NONE) && mePtr->labelPtr &&
+ mePtr->labelLength) {
+ title = [[[NSString alloc] initWithBytes:Tcl_GetString(mePtr->labelPtr)
+ length:mePtr->labelLength encoding:NSUTF8StringEncoding]
+ autorelease];
+ if ([title hasSuffix:@"..."]) {
+ title = [NSString stringWithFormat:@"%@%C",
+ [title substringToIndex:[title length] - 3], 0x2026];
+ }
+ }
+ [menuItem setTitle:title];
+ if (strcmp(Tcl_GetString(fontPtr), "menu") || gc->foreground != defaultFg
+ || gc->background != defaultBg) {
+ attributes = TkMacOSXNSFontAttributesForFont(Tk_GetFontFromObj(
+ mePtr->menuPtr->tkwin, fontPtr));
+ if (gc->foreground != defaultFg || gc->background != defaultBg) {
+ NSColor *color = TkMacOSXGetNSColor(gc,
+ gc->foreground!=defaultFg? gc->foreground:gc->background);
+
+ attributes = [[attributes mutableCopy] autorelease];
+ [(NSMutableDictionary *) attributes setObject:color
+ forKey:NSForegroundColorAttributeName];
+ }
+ if (attributes) {
+ attributedTitle = [[[NSAttributedString alloc]
+ initWithString:title attributes:attributes] autorelease];
+ }
+ }
+ [menuItem setAttributedTitle:attributedTitle];
+ [menuItem setEnabled:!(mePtr->state == ENTRY_DISABLED)];
+ [menuItem setState:((mePtr->type == CHECK_BUTTON_ENTRY ||
+ mePtr->type == RADIO_BUTTON_ENTRY) && mePtr->indicatorOn &&
+ (mePtr->entryFlags & ENTRY_SELECTED) ? NSOnState : NSOffState)];
+ if (mePtr->type != CASCADE_ENTRY && mePtr->accelPtr && mePtr->accelLength) {
+ keyEquivalent = ParseAccelerator(Tcl_GetString(mePtr->accelPtr),
+ &modifierMask);
+ }
+ [menuItem setKeyEquivalent:keyEquivalent];
+ [menuItem setKeyEquivalentModifierMask:modifierMask];
+ if (mePtr->type == CASCADE_ENTRY && mePtr->namePtr) {
+ TkMenuReferences *menuRefPtr;
+
+ menuRefPtr = TkFindMenuReferencesObj(mePtr->menuPtr->interp,
+ mePtr->namePtr);
+ if (menuRefPtr && menuRefPtr->menuPtr) {
+ CheckForSpecialMenu(menuRefPtr->menuPtr);
+ submenu = (TKMenu *) menuRefPtr->menuPtr->platformData;
+ if ([submenu supermenu] && [menuItem submenu] != submenu) {
+ /*
+ * This happens during a clone, where the parent menu is
+ * cloned before its children, so just ignore this temprary
+ * setting, it will be changed shortly (c.f. tkMenu.c
+ * CloneMenu())
+ */
+
+ submenu = nil;
+ } else {
+ [submenu setTitle:title];
+
+ if ([menuItem isEnabled]) {
+
+ /*
+ * This menuItem might have been previously disabled (XXX:
+ * track this), which would have disabled entries; we must
+ * re-enable the entries here.
+ */
+
+ int i = 0;
+ NSArray *itemArray = [submenu itemArray];
+
+ for (NSMenuItem *item in itemArray) {
+ TkMenuEntry *submePtr = menuRefPtr->menuPtr->entries[i];
+
+ /*
+ * Work around an apparent bug where itemArray can have
+ * more items than the menu's entries[] array.
+ */
+
+ if (i >= (int) menuRefPtr->menuPtr->numEntries) {
+ break;
+ }
+ [item setEnabled: !(submePtr->state == ENTRY_DISABLED)];
+ i++;
+ }
+ }
+ }
+ }
+ }
+ [menuItem setSubmenu:submenu];
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpDestroyMenuEntry --
+ *
+ * Cleans up platform-specific menu entry items.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * All platform-specific allocations are freed up.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpDestroyMenuEntry(
+ TkMenuEntry *mePtr)
+{
+ NSMenuItem *menuItem;
+ TKMenu *menu;
+ NSInteger index;
+
+ if (mePtr->platformEntryData && mePtr->menuPtr->platformData) {
+ menu = (TKMenu *) mePtr->menuPtr->platformData;
+ menuItem = (NSMenuItem *) mePtr->platformEntryData;
+ index = [menu indexOfItem:menuItem];
+
+ if (index > -1) {
+ [menu removeItemAtIndex:index];
+ }
+ [menuItem release];
+ mePtr->platformEntryData = NULL;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpPostMenu --
+ *
+ * Posts a menu on the screen. If entry is < 0 then the menu is drawn so
+ * its top left corner is located at the point with screen coordinates
+ * (x,y). Otherwise the top left corner of the specified entry is located
+ * at that point.
+ *
+ * Results:
+ * Returns a standard Tcl result.
+ *
+ * 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, int y, /* The screen coordinates where the top left
+ * corner of the menu, or of the specified
+ * entry, will be located. */
+ int index)
+{
+ int result;
+ Tk_Window root = Tk_MainWindow(interp);
+
+ if (root == NULL) {
+ return TCL_ERROR;
+ }
+ Drawable d = Tk_WindowId(root);
+ NSView *rootview = TkMacOSXGetRootControl(d);
+ NSWindow *win = [rootview window];
+ NSView *view = [win contentView];
+ NSMenu *menu = (NSMenu *) menuPtr->platformData;
+ NSInteger itemIndex = index;
+ NSInteger numItems = [menu numberOfItems];
+ NSMenuItem *item = nil;
+ NSPoint location = NSMakePoint(x, tkMacOSXZeroScreenHeight - y);
+
+ inPostMenu = 1;
+ result = TkPreprocessMenu(menuPtr);
+ if (result != TCL_OK) {
+ inPostMenu = 0;
+ return result;
+ }
+ if (itemIndex >= numItems) {
+ itemIndex = numItems - 1;
+ }
+ if (itemIndex >= 0) {
+ item = [menu itemAtIndex:itemIndex];
+ }
+
+ /*
+ * The post commands could have deleted the menu, which means we are dead
+ * and should go away.
+ */
+
+ if (menuPtr->tkwin == NULL) {
+ return TCL_OK;
+ }
+
+ [menu popUpMenuPositioningItem:item
+ atLocation:[win tkConvertPointFromScreen:location]
+ inView:view];
+ inPostMenu = 0;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpPostTearoffMenu --
+ *
+ * Tearoff menus are not supported on the Mac. This placeholder function,
+ * which is simply a copy of the unix function, posts a completely useless
+ * window with a black background on the screen. If entry is < 0 then the
+ * window is positioned so that its top left corner is located at the
+ * point with screen coordinates (x, y). Otherwise the window position is
+ * offset so that top left corner of the specified entry would be located
+ * at that point, if there actually were a menu.
+ *
+ * Mac menus steal all mouse or keyboard input from the application until
+ * the menu is dismissed, with or without a selection, by a mouse or key
+ * event. Posting a Mac menu in a regression test will cause the test to
+ * halt waiting for user input. This is why the TkpPostMenu function is
+ * not being used as the placeholder.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A useless window is posted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkpPostTearoffMenu(
+ Tcl_Interp *interp, /* The interpreter this menu lives in */
+ TkMenu *menuPtr, /* The menu we are posting */
+ int x, int y, int index) /* The screen coordinates where the top left
+ * corner of the menu, or of the specified
+ * entry, will be located. */
+{
+ int vRootX, vRootY, vRootWidth, vRootHeight;
+ int result;
+
+ if (index >= (int) menuPtr->numEntries) {
+ index = menuPtr->numEntries - 1;
+ }
+ if (index >= 0) {
+ y -= menuPtr->entries[index]->y;
+ }
+
+ TkActivateMenuEntry(menuPtr, -1);
+ TkRecomputeMenu(menuPtr);
+ result = TkPostCommand(menuPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+
+ /*
+ * The post commands could have deleted the menu, which means we are dead
+ * and should go away.
+ */
+
+ if (menuPtr->tkwin == NULL) {
+ return TCL_OK;
+ }
+
+ /*
+ * Adjust the position of the menu if necessary to keep it visible on the
+ * screen. There are two special tricks to make this work right:
+ *
+ * 1. If a virtual root window manager is being used then the coordinates
+ * are in the virtual root window of menuPtr's parent; since the menu
+ * uses override-redirect mode it will be in the *real* root window for
+ * the screen, so we have to map the coordinates from the virtual root
+ * (if any) to the real root. Can't get the virtual root from the menu
+ * itself (it will never be seen by the wm) so use its parent instead
+ * (it would be better to have an an option that names a window to use
+ * for this...).
+ * 2. The menu may not have been mapped yet, so its current size might be
+ * the default 1x1. To compute how much space it needs, use its
+ * requested size, not its actual size.
+ */
+
+ Tk_GetVRootGeometry(Tk_Parent(menuPtr->tkwin), &vRootX, &vRootY,
+ &vRootWidth, &vRootHeight);
+ vRootWidth -= Tk_ReqWidth(menuPtr->tkwin);
+ if (x > vRootX + vRootWidth) {
+ x = vRootX + vRootWidth;
+ }
+ if (x < vRootX) {
+ x = vRootX;
+ }
+ vRootHeight -= Tk_ReqHeight(menuPtr->tkwin);
+ if (y > vRootY + vRootHeight) {
+ y = vRootY + vRootHeight;
+ }
+ if (y < vRootY) {
+ y = vRootY;
+ }
+ Tk_MoveToplevelWindow(menuPtr->tkwin, x, y);
+ if (!Tk_IsMapped(menuPtr->tkwin)) {
+ Tk_MapWindow(menuPtr->tkwin);
+ }
+ TkWmRestackToplevel((TkWindow *) menuPtr->tkwin, Above, NULL);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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 */
+{
+ TkWindow *winPtr = (TkWindow *) tkwin;
+
+ if (winPtr->wmInfoPtr) {
+ winPtr->wmInfoPtr->menuPtr = menuPtr;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpSetMainMenubar --
+ *
+ * Puts the menu associated with a window into the menubar. Should only be
+ * called when the window is in front.
+ *
+ * This is a no-op on all other platforms. On OS X it is a no-op when
+ * passed a NULL menuName or a nonexistent menuName, with an exception for
+ * the first call in a new interpreter. In that special case, passing a
+ * NULL menuName installs the default menu.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The menubar may be changed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpSetMainMenubar(
+ Tcl_Interp *interp, /* The interpreter of the application */
+ Tk_Window tkwin, /* The frame we are setting up */
+ const char *menuName) /* The name of the menu to put in front. */
+{
+ static Tcl_Interp *currentInterp = NULL;
+ TKMenu *menu = nil;
+ TkWindow *winPtr = (TkWindow *) tkwin;
+
+ /*
+ * We will be called when an embedded window receives an ActivationNotify
+ * event, but we should not change the menubar in that case.
+ */
+
+ if (Tk_IsEmbedded(winPtr)) {
+ return;
+ }
+
+ if (menuName) {
+ Tk_Window menubar = NULL;
+
+ if (winPtr->wmInfoPtr &&
+ winPtr->wmInfoPtr->menuPtr &&
+ winPtr->wmInfoPtr->menuPtr->masterMenuPtr) {
+ menubar = winPtr->wmInfoPtr->menuPtr->masterMenuPtr->tkwin;
+ }
+
+ /*
+ * Attempt to find the NSMenu directly. If that fails, ask Tk to find
+ * it.
+ */
+
+ if (menubar != NULL && strcmp(menuName, Tk_PathName(menubar)) == 0) {
+ menu = (TKMenu *) winPtr->wmInfoPtr->menuPtr->platformData;
+ } else {
+ TkMenuReferences *menuRefPtr = TkFindMenuReferences(interp,
+ menuName);
+
+ if (menuRefPtr && menuRefPtr->menuPtr &&
+ menuRefPtr->menuPtr->platformData) {
+ menu = (TKMenu *) menuRefPtr->menuPtr->platformData;
+ }
+ }
+ }
+
+ /*
+ * If we couldn't find a menu, do nothing unless the window belongs to a
+ * different application. In that case, install the default menubar.
+ */
+
+ if (menu || interp != currentInterp) {
+ [NSApp tkSetMainMenu:menu];
+ }
+ currentInterp = interp;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CheckForSpecialMenu --
+ *
+ * Given a menu, check to see whether or not it is a cascade in a menubar
+ * with one of the special names ".apple", ".help" or ".window". If it is,
+ * the entry that points to this menu will be marked.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Will set entryFlags appropriately.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+CheckForSpecialMenu(
+ TkMenu *menuPtr) /* The menu we are checking */
+{
+ if (!menuPtr->masterMenuPtr->tkwin) {
+ return;
+ }
+ for (TkMenuEntry *cascadeEntryPtr = menuPtr->menuRefPtr->parentEntryPtr;
+ cascadeEntryPtr;
+ cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) {
+ if (cascadeEntryPtr->menuPtr->menuType == MENUBAR
+ && cascadeEntryPtr->menuPtr->masterMenuPtr->tkwin) {
+ TkMenu *masterMenuPtr = cascadeEntryPtr->menuPtr->masterMenuPtr;
+ int i = 0;
+ Tcl_DString ds;
+
+ Tcl_DStringInit(&ds);
+ Tcl_DStringAppend(&ds, Tk_PathName(masterMenuPtr->tkwin), -1);
+ while (specialMenus[i].name) {
+ Tcl_DStringAppend(&ds, specialMenus[i].name,
+ specialMenus[i].len);
+ if (strcmp(Tcl_DStringValue(&ds),
+ Tk_PathName(menuPtr->masterMenuPtr->tkwin)) == 0) {
+ cascadeEntryPtr->entryFlags |= specialMenus[i].flag;
+ } else {
+ cascadeEntryPtr->entryFlags &= ~specialMenus[i].flag;
+ }
+ Tcl_DStringSetLength(&ds, Tcl_DStringLength(&ds) -
+ specialMenus[i].len);
+ i++;
+ }
+ Tcl_DStringFree(&ds);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ParseAccelerator --
+ *
+ * Parse accelerator string.
+ *
+ * Results:
+ * Accelerator string & flags.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static NSString *
+ParseAccelerator(
+ const char *accel,
+ NSUInteger *maskPtr)
+{
+ unichar ch = 0;
+ size_t len;
+ int i;
+
+ *maskPtr = 0;
+ while (1) {
+ i = 0;
+ while (modifiers[i].name) {
+ int l = modifiers[i].len;
+
+ if (!strncasecmp(accel, modifiers[i].name, l) &&
+ (accel[l] == '-' || accel[l] == '+')) {
+ *maskPtr |= modifiers[i].mask;
+ accel += l+1;
+ break;
+ }
+ i++;
+ }
+ if (!modifiers[i].name || !*accel) {
+ break;
+ }
+ }
+ len = strlen(accel);
+ if (len > 1) {
+ i = 0;
+ if (accel[0] == 'F' && len < 4 && accel[1] > '0' && accel[1] <= '9') {
+ int fkey = accel[1] - '0';
+
+ if (len == 3) {
+ if (accel[2] >= '0' && accel[2] <= '9') {
+ fkey = 10 * fkey + (accel[2] - '0');
+ } else {
+ fkey = 0;
+ }
+ }
+ if (fkey >= 1 && fkey <= 15) {
+ ch = NSF1FunctionKey + fkey - 1;
+ }
+ } else while (specialAccelerators[i].name) {
+ if (accel[0] == specialAccelerators[i].name[0] &&
+ len == specialAccelerators[i].len && !strncasecmp(accel,
+ specialAccelerators[i].name, specialAccelerators[i].len)) {
+ ch = specialAccelerators[i].ch;
+ break;
+ }
+ i++;
+ }
+ }
+ if (ch) {
+ return [[[NSString alloc] initWithCharacters:&ch length:1] autorelease];
+ } else {
+ return [[[[NSString alloc] initWithUTF8String:accel] autorelease]
+ lowercaseString];
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ModifierCharWidth --
+ *
+ * Helper mesuring width of command char in given font.
+ *
+ * Results:
+ * Width of command char.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+ModifierCharWidth(
+ Tk_Font tkfont)
+{
+ static NSString *cmdChar = nil;
+
+ if (!cmdChar) {
+ unichar cmd = kCommandUnicode;
+
+ cmdChar = [[NSString alloc] initWithCharacters:&cmd length:1];
+ }
+ return [cmdChar sizeWithAttributes:
+ TkMacOSXNSFontAttributesForFont(tkfont)].width;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * 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. */
+{
+ NSSize menuSize;
+ Tk_Font tkfont, menuFont;
+ Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr;
+ int modifierCharWidth, menuModifierCharWidth;
+ int x, y, modifierWidth, labelWidth, indicatorSpace;
+ int windowWidth, windowHeight, accelWidth;
+ int i, maxWidth;
+ int entryWidth, maxIndicatorSpace, borderWidth, activeBorderWidth;
+ TkMenuEntry *mePtr;
+ int haveAccel = 0;
+
+ /*
+ * Do nothing if this menu is a clone.
+ */
+
+ if (menuPtr->tkwin == NULL || menuPtr->masterMenuPtr != menuPtr) {
+ return;
+ }
+
+ menuSize = [(NSMenu *) menuPtr->platformData size];
+ Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr,
+ &borderWidth);
+ Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->activeBorderWidthPtr,
+ &activeBorderWidth);
+ x = y = borderWidth;
+ windowHeight = maxWidth = 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);
+ menuModifierCharWidth = ModifierCharWidth(menuFont);
+
+ for (i = 0; i < (int) menuPtr->numEntries; i++) {
+ mePtr = menuPtr->entries[i];
+ if (mePtr->type == CASCADE_ENTRY || mePtr->accelLength > 0) {
+ haveAccel = 1;
+ break;
+ }
+ }
+
+ for (i = 0; i < (int) menuPtr->numEntries; i++) {
+ mePtr = menuPtr->entries[i];
+ if (mePtr->type == TEAROFF_ENTRY) {
+ continue;
+ }
+ if (mePtr->fontPtr == NULL) {
+ tkfont = menuFont;
+ fmPtr = &menuMetrics;
+ modifierCharWidth = menuModifierCharWidth;
+ } else {
+ tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr);
+ Tk_GetFontMetrics(tkfont, &entryMetrics);
+ fmPtr = &entryMetrics;
+ modifierCharWidth = ModifierCharWidth(tkfont);
+ }
+ accelWidth = modifierWidth = indicatorSpace = 0;
+ if (mePtr->type == SEPARATOR_ENTRY) {
+ mePtr->height = menuSeparatorHeight;
+ } 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.
+ */
+
+ NSMenuItem *menuItem = (NSMenuItem *) mePtr->platformEntryData;
+ int haveImage = 0, width = 0, height = 0;
+
+ if (mePtr->image) {
+ Tk_SizeOfImage(mePtr->image, &width, &height);
+ haveImage = 1;
+ height += 2; /* tweak */
+ } else if (mePtr->bitmapPtr) {
+ Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin,
+ mePtr->bitmapPtr);
+
+ Tk_SizeOfBitmap(menuPtr->display, bitmap, &width, &height);
+ haveImage = 1;
+ height += 2; /* tweak */
+ }
+ if (!haveImage || (mePtr->compound != COMPOUND_NONE)) {
+ NSAttributedString *attrTitle = [menuItem attributedTitle];
+ NSSize size;
+
+ if (attrTitle) {
+ size = [attrTitle size];
+ } else {
+ size = [[menuItem title] sizeWithAttributes:
+ TkMacOSXNSFontAttributesForFont(tkfont)];
+ }
+ size.width += menuTextLeadingEdgeMargin + menuTextTrailingEdgeMargin;
+ size.height -= 1; /* tweak */
+ if (haveImage && (mePtr->compound != COMPOUND_NONE)) {
+ int margin = width + menuIconTrailingEdgeMargin;
+
+ if (margin > menuTextLeadingEdgeMargin) {
+ margin = menuTextLeadingEdgeMargin;
+ }
+ width += size.width + menuIconTrailingEdgeMargin - margin;
+ if (size.height > height) {
+ height = size.height;
+ }
+ } else {
+ width = size.width;
+ height = size.height;
+ }
+ }
+ else {
+ /* image only. */
+ }
+ labelWidth = width + menuItemExtraWidth;
+ mePtr->height = height + menuItemExtraHeight;
+ if (mePtr->type == CASCADE_ENTRY) {
+ modifierWidth = modifierCharWidth;
+ } else if (mePtr->accelLength == 0) {
+ if (haveAccel && !mePtr->hideMargin) {
+ modifierWidth = modifierCharWidth;
+ }
+ } else {
+ NSUInteger modifMask = [menuItem keyEquivalentModifierMask];
+ int i = 0;
+
+ while (modifiers[i].name) {
+ if (modifMask & modifiers[i].mask) {
+ modifMask &= ~modifiers[i].mask;
+ modifierWidth += modifierCharWidth;
+ }
+ i++;
+ }
+ accelWidth = [[menuItem keyEquivalent] sizeWithAttributes:
+ TkMacOSXNSFontAttributesForFont(tkfont)].width;
+ }
+ if (!mePtr->hideMargin) {
+ indicatorSpace = menuMarkColumnWidth;
+ }
+ if (indicatorSpace > maxIndicatorSpace) {
+ maxIndicatorSpace = indicatorSpace;
+ }
+ entryWidth = labelWidth + modifierWidth + accelWidth;
+ if (entryWidth > maxWidth) {
+ maxWidth = entryWidth;
+ }
+ menuPtr->entries[i]->width = entryWidth;
+ mePtr->height += 2 * activeBorderWidth;
+ }
+ mePtr->x = x;
+ mePtr->y = y;
+ y += menuPtr->entries[i]->height + borderWidth;
+ }
+ windowWidth = menuSize.width;
+ if (windowWidth <= 0) {
+ windowWidth = 1;
+ }
+ windowHeight = menuSize.height;
+ if (windowHeight <= 0) {
+ windowHeight = 1;
+ }
+ menuPtr->totalWidth = windowWidth;
+ menuPtr->totalHeight = windowHeight;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GenerateMenuSelectEvent --
+ *
+ * Respond to a menu item being selected.
+ *
+ * Results:
+ * True if event(s) are generated - false otherwise.
+ *
+ * Side effects:
+ * Places a virtual event on the event queue.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+GenerateMenuSelectEvent(
+ TKMenu *menu,
+ NSMenuItem *menuItem)
+{
+ TkMenu *menuPtr = [menu tkMenu];
+
+ if (menuPtr) {
+ int index = [menu tkIndexOfItem:menuItem];
+
+ if (index < 0 || index >= (int) menuPtr->numEntries ||
+ (menuPtr->entries[index])->state == ENTRY_DISABLED) {
+ TkActivateMenuEntry(menuPtr, -1);
+ } else {
+ TkActivateMenuEntry(menuPtr, index);
+ MenuSelectEvent(menuPtr);
+ return true;
+ }
+ }
+ return false;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+MenuSelectEvent(
+ TkMenu *menuPtr) /* the menu we have selected. */
+{
+ XVirtualEvent event;
+
+ bzero(&event, sizeof(XVirtualEvent));
+ event.type = VirtualEvent;
+ event.serial = LastKnownRequestProcessed(menuPtr->display);
+ event.send_event = false;
+ event.display = menuPtr->display;
+ event.event = Tk_WindowId(menuPtr->tkwin);
+ event.root = XRootWindow(menuPtr->display, 0);
+ event.subwindow = None;
+ event.time = TkpGetMS();
+ XQueryPointer(NULL, None, NULL, NULL, &event.x_root, &event.y_root, NULL,
+ NULL, &event.state);
+ event.same_screen = true;
+ event.name = Tk_GetUid("MenuSelect");
+ Tk_MakeWindowExist(menuPtr->tkwin);
+ if (Tcl_GetServiceMode() != TCL_SERVICE_NONE) {
+ Tk_HandleEvent((XEvent *) &event);
+ } else {
+ 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;
+
+ TkActivateMenuEntry(menuPtr, -1);
+ for (i = 0; i < (int) menuPtr->numEntries; i++) {
+ TkMenuEntry *mePtr = menuPtr->entries[i];
+
+ if (mePtr->type == CASCADE_ENTRY
+ && (mePtr->childMenuRefPtr != NULL)
+ && (mePtr->childMenuRefPtr->menuPtr != NULL)) {
+ RecursivelyClearActiveMenu(mePtr->childMenuRefPtr->menuPtr);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXClearMenubarActive --
+ *
+ * Recursively clears the active entry in the current menubar hierarchy.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Generates <<MenuSelect>> virtual events.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXClearMenubarActive(void)
+{
+ NSMenu *mainMenu = [NSApp mainMenu];
+
+ if (mainMenu && [mainMenu isKindOfClass:[TKMenu class]]) {
+ TkMenu *menuPtr = [(TKMenu *) mainMenu tkMenu];
+
+ if (menuPtr && menuPtr->numEntries && menuPtr->entries) {
+ RecursivelyClearActiveMenu(menuPtr);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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(void)
+{
+ gNoTkMenus = 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpMenuInit --
+ *
+ * Initializes Mac-specific menu data.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Allocates a hash table.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpMenuInit(void)
+{
+ TkColor *tkColPtr;
+
+ NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
+
+#define observe(n, s) \
+ [nc addObserver:NSApp selector:@selector(s) name:(n) object:nil]
+ observe(NSMenuDidBeginTrackingNotification, menuBeginTracking:);
+ observe(NSMenuDidEndTrackingNotification, menuEndTracking:);
+#undef observe
+
+ [NSMenuItem setUsesUserKeyEquivalents:NO];
+ tkColPtr = TkpGetColor(NULL, DEF_MENU_BG_COLOR);
+ defaultBg = tkColPtr->color.pixel;
+ ckfree(tkColPtr);
+ tkColPtr = TkpGetColor(NULL, DEF_MENU_FG);
+ defaultFg = tkColPtr->color.pixel;
+ ckfree(tkColPtr);
+
+ ChkErr(GetThemeMetric, kThemeMetricMenuMarkColumnWidth,
+ &menuMarkColumnWidth);
+ ChkErr(GetThemeMetric, kThemeMetricMenuTextLeadingEdgeMargin,
+ &menuTextLeadingEdgeMargin);
+ ChkErr(GetThemeMetric, kThemeMetricMenuTextTrailingEdgeMargin,
+ &menuTextTrailingEdgeMargin);
+ ChkErr(GetThemeMetric, kThemeMetricMenuIconTrailingEdgeMargin,
+ &menuIconTrailingEdgeMargin);
+ ChkErr(GetThemeMenuItemExtra, kThemeMenuItemPlain, &menuItemExtraHeight,
+ &menuItemExtraWidth);
+ ChkErr(GetThemeMenuSeparatorHeight, &menuSeparatorHeight);
+}
+
+#pragma mark -
+#pragma mark NOPs
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpMenuThreadInit --
+ *
+ * Does platform-specific initialization of thread-specific menu state.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpMenuThreadInit(void)
+{
+ /*
+ * Nothing to do.
+ */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpMenuNotifyToplevelCreate --
+ *
+ * This routine reconfigures the menu and the clones indicated by
+ * menuName because 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. */
+ const char *menuName) /* The name of the menu to reconfigure. */
+{
+ /*
+ * Nothing to do.
+ */
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * 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(
+ 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(
+ TkMenu *menuPtr) /* Structure describing menu. */
+{
+ TkpComputeStandardMenuGeometry(menuPtr);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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. */
+{
+}
+
+#pragma mark Obsolete
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXPreprocessMenu --
+ *
+ * Handle preprocessing of menubar if it exists.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * All post commands for the current menubar get executed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXPreprocessMenu(void)
+{
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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 */
+{
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXDispatchMenuEvent --
+ *
+ * Given a menu id and an item, dispatches the command associated with it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Commands for the event are scheduled for execution at idle time.
+ *
+ *----------------------------------------------------------------------
+ */
+
+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. */
+{
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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)
+{
+ /*
+ * Obsolete: Nothing to do.
+ */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * NB: Nobody uses this any more, since you can get the number of system
+ * help items from HMGetHelpMenu trivially. But it is in the stubs
+ * table...
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Nothing.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXSetHelpMenuItemCount(void)
+{
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXMenuClick --
+ *
+ * Prepares a menubar for MenuSelect or MenuKey.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Any pending configurations of the menubar are completed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXMenuClick(void)
+{
+}
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXMenubutton.c b/tk8.6/macosx/tkMacOSXMenubutton.c
new file mode 100644
index 0000000..53adb01
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXMenubutton.c
@@ -0,0 +1,824 @@
+/*
+ * 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.
+ * Copyright (c) 2006-2007 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright 2007 Revar Desmera.
+ * Copyright 2015 Kevin Walzer/WordTech Communications LLC.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ */
+
+#include "tkMacOSXPrivate.h"
+#include "tkMenu.h"
+#include "tkMenubutton.h"
+#include "tkMacOSXFont.h"
+#include "tkMacOSXDebug.h"
+
+#define FIRST_DRAW 2
+#define ACTIVE 4
+
+
+typedef struct {
+ Tk_3DBorder border;
+ int relief;
+ GC gc;
+ int hasImageOrBitmap;
+} DrawParams;
+
+/*
+ * Declaration of Mac specific button structure.
+ */
+
+typedef struct MacMenuButton {
+ TkMenuButton info; /* Generic button info. */
+ int flags;
+ ThemeButtonKind btnkind;
+ HIThemeButtonDrawInfo drawinfo;
+ HIThemeButtonDrawInfo lastdrawinfo;
+ DrawParams drawParams;
+} MacMenuButton;
+
+/*
+ * Forward declarations for static functions defined later in this file:
+ */
+
+static void MenuButtonEventProc(ClientData clientData,
+ XEvent *eventPtr);
+static void MenuButtonBackgroundDrawCB(MacMenuButton *ptr,
+ SInt16 depth, Boolean isColorDev);
+static void MenuButtonContentDrawCB(ThemeButtonKind kind,
+ const HIThemeButtonDrawInfo *info,
+ MacMenuButton *ptr, SInt16 depth,
+ Boolean isColorDev);
+static void MenuButtonEventProc(ClientData clientData,
+ XEvent *eventPtr);
+static void TkMacOSXComputeMenuButtonParams(TkMenuButton *butPtr,
+ ThemeButtonKind *btnkind,
+ HIThemeButtonDrawInfo *drawinfo);
+static void TkMacOSXComputeMenuButtonDrawParams(
+ TkMenuButton *butPtr, DrawParams *dpPtr);
+static void TkMacOSXDrawMenuButton(MacMenuButton *butPtr, GC gc,
+ Pixmap pixmap);
+static void DrawMenuButtonImageAndText(TkMenuButton *butPtr);
+
+/*
+ * 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 */
+};
+
+/*
+ * We use Apple's Pop-Up Button widget to represent the Tk Menubutton.
+ * However, we do not use the NSPopUpButton class for this control. Instead we
+ * render the Pop-Up Button using the HITheme library. This imposes some
+ * constraints on what can be done. The HITheme renderer allows only specific
+ * dimensions for the button.
+ *
+ * The HITheme library allows drawing a Pop-Up Button with an arbitrary bounds
+ * rectangle. However the button is always drawn as a rounded box which is 22
+ * pixels high. If the bounds rectangle is less than 22 pixels high, the
+ * button is drawn at the top of the rectangle and the bottom of the button is
+ * clipped away. So we set a minimum height of 22 pixels for a Menubutton. If
+ * the bounds rectangle is more than 22 pixels high, then the button is drawn
+ * centered vertically in the bounds rectangle.
+ *
+ * The content rectangle of the button is inset by 14 pixels on the left and 28
+ * pixels on the right. The rightmost part of the button contains the blue
+ * double-arrow symbol which is 28 pixels wide.
+ *
+ * To maintain compatibility with code that runs on multiple operating systems,
+ * the width and height of the content rectangle includes the borderWidth, the
+ * highlightWidth and the padX and padY dimensions of the Menubutton. However,
+ * to be consistent with the standard Apple appearance, the content is always
+ * be drawn at the left side of the content rectangle. All of the excess space
+ * appears on the right side of the content, and the anchor property is
+ * ignored. The easiest way to comply with Apple's Human Interface Guidelines
+ * would be to set bd = highlightthickness = padx = 0 and to specify an
+ * explicit width for the button. Apple also recommends using the same width
+ * for all Pop-Up Buttons in a given window.
+ */
+
+#define LEFT_INSET 8
+#define RIGHT_INSET 28
+#define MIN_HEIGHT 22
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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));
+
+ Tk_CreateEventHandler(tkwin, ActivateMask, MenuButtonEventProc, mbPtr);
+ mbPtr->flags = FIRST_DRAW;
+ mbPtr->btnkind = kThemePopupButton;
+ bzero(&mbPtr->drawinfo, sizeof(mbPtr->drawinfo));
+ bzero(&mbPtr->lastdrawinfo, sizeof(mbPtr->lastdrawinfo));
+ 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. */
+{
+ MacMenuButton *mbPtr = clientData;
+ TkMenuButton *butPtr = clientData;
+ Tk_Window tkwin = butPtr->tkwin;
+ Pixmap pixmap;
+ DrawParams *dpPtr = &mbPtr->drawParams;
+
+ butPtr->flags &= ~REDRAW_PENDING;
+ if ((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
+ return;
+ }
+
+ pixmap = (Pixmap) Tk_WindowId(tkwin);
+
+ TkMacOSXComputeMenuButtonDrawParams(butPtr, dpPtr);
+
+ /*
+ * Set up clipping region. Make sure the we are using the port for this
+ * button, or we will set the wrong window's clip.
+ */
+
+ TkMacOSXSetUpClippingRgn(pixmap);
+
+ /*
+ * Draw the native portion of the buttons.
+ */
+
+ TkMacOSXDrawMenuButton(mbPtr, dpPtr->gc, pixmap);
+
+ /*
+ * Draw highlight border, if needed.
+ */
+
+ if (butPtr->highlightWidth < 3) {
+ if (butPtr->flags & GOT_FOCUS) {
+ GC gc = Tk_GCForColor(butPtr->highlightColorPtr, pixmap);
+ TkMacOSXDrawSolidBorder(tkwin, gc, 0, butPtr->highlightWidth);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpDestroyMenuButton --
+ *
+ * Free data structures associated with the menubutton control. This is a
+ * no-op on the Mac.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpDestroyMenuButton(
+ TkMenuButton *mbPtr)
+{
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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(butPtr)
+ register TkMenuButton *butPtr; /* Widget record for menu button. */
+{
+ int width, height, avgWidth, haveImage = 0, haveText = 0;
+ int txtWidth, txtHeight;
+ Tk_FontMetrics fm;
+ int highlightWidth = butPtr->highlightWidth > 0 ? butPtr->highlightWidth : 0;
+
+ /*
+ * First compute the size of the contents of the button.
+ */
+
+ width = 0;
+ height = 0;
+ txtWidth = 0;
+ txtHeight = 0;
+ avgWidth = 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 (butPtr->text && strlen(butPtr->text) > 0) {
+ haveText = 1;
+ Tk_FreeTextLayout(butPtr->textLayout);
+ butPtr->textLayout = Tk_ComputeTextLayout(butPtr->tkfont,
+ butPtr->text, -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);
+ }
+
+ /*
+ * 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 (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;
+ }
+
+ } else {
+ if (haveImage) { /* Image only */
+ if (butPtr->width > 0) {
+ width = butPtr->width;
+ }
+ if (butPtr->height > 0) {
+ height = butPtr->height;
+ }
+ } else { /* Text only */
+ width = txtWidth;
+ height = txtHeight;
+ if (butPtr->width > 0) {
+ width = butPtr->width * avgWidth + 2*butPtr->padX;
+ }
+ if (butPtr->height > 0) {
+ height = butPtr->height * fm.linespace + 2*butPtr->padY;
+ }
+ }
+ }
+
+ butPtr->inset = highlightWidth + butPtr->borderWidth;
+ width += LEFT_INSET + RIGHT_INSET + 2*butPtr->inset;
+ height += 2*butPtr->inset;
+ height = height < MIN_HEIGHT ? MIN_HEIGHT : height;
+ Tk_GeometryRequest(butPtr->tkwin, width, height);
+ Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DrawMenuButtonImageAndText --
+ *
+ * Draws the image and text associated witha button or label.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The image and text are drawn.
+ *
+ *----------------------------------------------------------------------
+ */
+void
+DrawMenuButtonImageAndText(
+ TkMenuButton *butPtr)
+{
+ MacMenuButton *mbPtr = (MacMenuButton *) butPtr;
+ Tk_Window tkwin = butPtr->tkwin;
+ Pixmap pixmap;
+ int haveImage = 0, haveText = 0;
+ int imageWidth = 0, imageHeight = 0;
+ int imageXOffset = 0, imageYOffset = 0;
+ int textXOffset = 0, textYOffset = 0;
+ int width = 0, height = 0;
+ int fullWidth = 0, fullHeight = 0;
+
+ if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
+ return;
+ }
+
+ DrawParams *dpPtr = &mbPtr->drawParams;
+ pixmap = (Pixmap) Tk_WindowId(tkwin);
+
+ if (butPtr->image != None) {
+ Tk_SizeOfImage(butPtr->image, &width, &height);
+ haveImage = 1;
+ } else if (butPtr->bitmap != None) {
+ Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height);
+ haveImage = 1;
+ }
+
+ imageWidth = width;
+ imageHeight = height;
+
+ haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0);
+ if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) {
+ int x = 0, y = 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 - 2;
+ } 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->inset, butPtr->padY + butPtr->inset,
+ fullWidth, fullHeight, &x, &y);
+ imageXOffset = LEFT_INSET;
+ imageYOffset += y;
+ textYOffset -= 1;
+
+ if (butPtr->image != NULL) {
+ Tk_RedrawImage(butPtr->image, 0, 0, width,
+ height, pixmap, imageXOffset, imageYOffset);
+ } else {
+ XSetClipOrigin(butPtr->display, dpPtr->gc,
+ imageXOffset, imageYOffset);
+ XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, dpPtr->gc,
+ 0, 0, (unsigned int) width, (unsigned int) height,
+ imageXOffset, imageYOffset, 1);
+ XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0);
+ }
+
+ 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);
+ } else {
+ int x, y;
+
+ if (haveImage) {
+ TkComputeAnchor(butPtr->anchor, tkwin,
+ butPtr->padX + butPtr->borderWidth,
+ butPtr->padY + butPtr->borderWidth,
+ width, height, &x, &y);
+ imageXOffset = LEFT_INSET;
+ imageYOffset += y;
+ if (butPtr->image != NULL) {
+ Tk_RedrawImage(butPtr->image, 0, 0, width, height,
+ pixmap, imageXOffset, imageYOffset);
+ } else {
+ XSetClipOrigin(butPtr->display, dpPtr->gc, x, y);
+ XCopyPlane(butPtr->display, butPtr->bitmap,
+ pixmap, dpPtr->gc,
+ 0, 0, (unsigned int) width,
+ (unsigned int) height,
+ imageXOffset, imageYOffset, 1);
+ XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0);
+ }
+ } else {
+ textXOffset = LEFT_INSET;
+ TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX, butPtr->padY,
+ butPtr->textWidth, butPtr->textHeight, &x, &y);
+ Tk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc,
+ butPtr->textLayout, textXOffset, y, 0, -1);
+ y += butPtr->textHeight/2;
+ }
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkMacOSXDrawMenuButton --
+ *
+ * This function draws the tk menubutton using Mac controls. In
+ * addition, this code may apply custom colors passed in the
+ * TkMenubutton.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+TkMacOSXDrawMenuButton(
+ MacMenuButton *mbPtr, /* Mac menubutton. */
+ 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 */
+{
+ TkMenuButton *butPtr = (TkMenuButton *) mbPtr;
+ TkWindow *winPtr = (TkWindow *) butPtr->tkwin;
+ HIRect cntrRect;
+ TkMacOSXDrawingContext dc;
+ DrawParams *dpPtr = &mbPtr->drawParams;
+ int useNewerHITools = 1;
+
+ TkMacOSXComputeMenuButtonParams(butPtr, &mbPtr->btnkind, &mbPtr->drawinfo);
+
+ cntrRect = CGRectMake(winPtr->privatePtr->xOff, winPtr->privatePtr->yOff,
+ Tk_Width(butPtr->tkwin), Tk_Height(butPtr->tkwin));
+
+ if (useNewerHITools == 1) {
+ HIRect contHIRec;
+ static HIThemeButtonDrawInfo hiinfo;
+
+ MenuButtonBackgroundDrawCB(mbPtr, 32, true);
+ if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, 1, &dc)) {
+ return;
+ }
+
+ hiinfo.version = 0;
+ hiinfo.state = mbPtr->drawinfo.state;
+ hiinfo.kind = mbPtr->btnkind;
+ hiinfo.value = mbPtr->drawinfo.value;
+ hiinfo.adornment = mbPtr->drawinfo.adornment;
+ hiinfo.animation.time.current = CFAbsoluteTimeGetCurrent();
+ if (hiinfo.animation.time.start == 0) {
+ hiinfo.animation.time.start = hiinfo.animation.time.current;
+ }
+
+ /*
+ * To avoid menubuttons with white text on a white background, we
+ * always set the state to inactive in Dark Mode. It isn't perfect but
+ * it is usable. Using a ttk::menubutton would be a better choice,
+ * however.
+ */
+
+ if (TkMacOSXInDarkMode(butPtr->tkwin)) {
+ hiinfo.state = kThemeStateInactive;
+ }
+
+ HIThemeDrawButton(&cntrRect, &hiinfo, dc.context,
+ kHIThemeOrientationNormal, &contHIRec);
+ TkMacOSXRestoreDrawingContext(&dc);
+ MenuButtonContentDrawCB(mbPtr->btnkind, &mbPtr->drawinfo,
+ mbPtr, 32, true);
+ } else {
+ if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, 1, &dc)) {
+ return;
+ }
+ TkMacOSXRestoreDrawingContext(&dc);
+ }
+ mbPtr->lastdrawinfo = mbPtr->drawinfo;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * MenuButtonBackgroundDrawCB --
+ *
+ * This function draws the background that lies under checkboxes and
+ * radiobuttons.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The background gets updated to the current color.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+MenuButtonBackgroundDrawCB (
+ MacMenuButton *ptr,
+ SInt16 depth,
+ Boolean isColorDev)
+{
+ TkMenuButton* butPtr = (TkMenuButton *) ptr;
+ Tk_Window tkwin = butPtr->tkwin;
+ Pixmap pixmap;
+
+ if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
+ return;
+ }
+ pixmap = (Pixmap) Tk_WindowId(tkwin);
+ Tk_Fill3DRectangle(tkwin, pixmap, butPtr->normalBorder, 0, 0,
+ Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * MenuButtonContentDrawCB --
+ *
+ * This function draws the label and image for the button.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The content of the button gets updated.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+MenuButtonContentDrawCB (
+ ThemeButtonKind kind,
+ const HIThemeButtonDrawInfo *drawinfo,
+ MacMenuButton *ptr,
+ SInt16 depth,
+ Boolean isColorDev)
+{
+ TkMenuButton *butPtr = (TkMenuButton *) ptr;
+ Tk_Window tkwin = butPtr->tkwin;
+
+ if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
+ return;
+ }
+ DrawMenuButtonImageAndText(butPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * MenuButtonEventProc --
+ *
+ * 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
+MenuButtonEventProc(
+ ClientData clientData, /* Information about window. */
+ XEvent *eventPtr) /* Information about event. */
+{
+ TkMenuButton *buttonPtr = clientData;
+ MacMenuButton *mbPtr = clientData;
+
+ if (eventPtr->type == ActivateNotify
+ || eventPtr->type == DeactivateNotify) {
+ if ((buttonPtr->tkwin == NULL) || (!Tk_IsMapped(buttonPtr->tkwin))) {
+ return;
+ }
+ if (eventPtr->type == ActivateNotify) {
+ mbPtr->flags |= ACTIVE;
+ } else {
+ mbPtr->flags &= ~ACTIVE;
+ }
+ if ((buttonPtr->flags & REDRAW_PENDING) == 0) {
+ Tcl_DoWhenIdle(TkpDisplayMenuButton, (ClientData) buttonPtr);
+ buttonPtr->flags |= REDRAW_PENDING;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXComputeMenuButtonParams --
+ *
+ * This procedure computes the various parameters used when creating a
+ * Carbon Appearance control. These are determined by the various Tk
+ * button parameters
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Sets the btnkind and drawinfo parameters
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+TkMacOSXComputeMenuButtonParams(
+ TkMenuButton *butPtr,
+ ThemeButtonKind *btnkind,
+ HIThemeButtonDrawInfo *drawinfo)
+{
+ MacMenuButton *mbPtr = (MacMenuButton *) butPtr;
+
+ if (butPtr->image || butPtr->bitmap || butPtr->text) {
+ /* TODO: allow for Small and Mini menubuttons. */
+ *btnkind = kThemePopupButton;
+ } else { /* This should never happen. */
+ *btnkind = kThemeArrowButton;
+ }
+
+ drawinfo->value = kThemeButtonOff;
+
+ if ((mbPtr->flags & FIRST_DRAW) != 0) {
+ mbPtr->flags &= ~FIRST_DRAW;
+ if (Tk_MacOSXIsAppInFront()) {
+ mbPtr->flags |= ACTIVE;
+ }
+ }
+
+ drawinfo->state = kThemeStateInactive;
+ if ((mbPtr->flags & ACTIVE) == 0) {
+ if (butPtr->state == STATE_DISABLED) {
+ drawinfo->state = kThemeStateUnavailableInactive;
+ } else {
+ drawinfo->state = kThemeStateInactive;
+ }
+ } else if (butPtr->state == STATE_DISABLED) {
+ drawinfo->state = kThemeStateUnavailable;
+ } else {
+ drawinfo->state = kThemeStateActive;
+ }
+
+ drawinfo->adornment = kThemeAdornmentNone;
+ if (butPtr->highlightWidth >= 3) {
+ if ((butPtr->flags & GOT_FOCUS)) {
+ drawinfo->adornment |= kThemeAdornmentFocus;
+ }
+ }
+ drawinfo->adornment |= kThemeAdornmentArrowDoubleArrow;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXComputeMenuButtonDrawParams --
+ *
+ * This procedure selects an appropriate drawing context for drawing a
+ * menubutton.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Sets the button draw parameters.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+TkMacOSXComputeMenuButtonDrawParams(
+ TkMenuButton *butPtr,
+ DrawParams *dpPtr)
+{
+ dpPtr->hasImageOrBitmap =
+ ((butPtr->image != NULL) || (butPtr->bitmap != None));
+ dpPtr->border = butPtr->normalBorder;
+ if ((butPtr->state == STATE_DISABLED) && (butPtr->disabledFg != NULL)) {
+ dpPtr->gc = butPtr->disabledGC;
+ } else if (butPtr->state == STATE_ACTIVE) {
+ dpPtr->gc = butPtr->activeTextGC;
+ dpPtr->border = butPtr->activeBorder;
+ } else {
+ dpPtr->gc = butPtr->normalTextGC;
+ }
+}
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXMenus.c b/tk8.6/macosx/tkMacOSXMenus.c
new file mode 100644
index 0000000..5e6a37c
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXMenus.c
@@ -0,0 +1,575 @@
+/*
+ * tkMacOSXMenus.c --
+ *
+ * These calls set up the default menus for Tk.
+ *
+ * Copyright (c) 1995-1996 Sun Microsystems, Inc.
+ * Copyright 2001-2009, Apple Inc.
+ * Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkMacOSXPrivate.h"
+#include "tkMenu.h"
+#include "tkMacOSXConstants.h"
+
+static void GenerateEditEvent(const char *name);
+static Tcl_Obj * GetWidgetDemoPath(Tcl_Interp *interp);
+
+
+#pragma mark TKApplication(TKMenus)
+
+@implementation TKApplication(TKMenus)
+- (void) _setupMenus
+{
+ if (_defaultMainMenu) {
+ return;
+ }
+ TkMenuInit();
+
+ NSString *applicationName = [[NSBundle mainBundle]
+ objectForInfoDictionaryKey:@"CFBundleName"];
+
+ if (!applicationName) {
+ applicationName = [[NSProcessInfo processInfo] processName];
+ }
+
+ NSString *aboutName = (applicationName &&
+ ![applicationName isEqualToString:@"Wish"] &&
+ ![applicationName hasPrefix:@"tclsh"]) ?
+ applicationName : @"Tcl & Tk";
+
+ _servicesMenu = [NSMenu menuWithTitle:@"Services"];
+ _defaultApplicationMenuItems = [[NSArray arrayWithObjects:
+ [NSMenuItem separatorItem],
+ [NSMenuItem itemWithTitle:
+ [NSString stringWithFormat:@"Preferences%C", 0x2026]
+ action:@selector(preferences:) keyEquivalent:@","],
+ [NSMenuItem separatorItem],
+ [NSMenuItem itemWithTitle:@"Services" submenu:_servicesMenu],
+ [NSMenuItem separatorItem],
+ [NSMenuItem itemWithTitle:
+ [NSString stringWithFormat:@"Hide %@", applicationName]
+ action:@selector(hide:) keyEquivalent:@"h"],
+ [NSMenuItem itemWithTitle:@"Hide Others"
+ action:@selector(hideOtherApplications:) keyEquivalent:@"h"
+ keyEquivalentModifierMask:
+ NSCommandKeyMask|NSAlternateKeyMask],
+ [NSMenuItem itemWithTitle:@"Show All"
+ action:@selector(unhideAllApplications:)],
+ [NSMenuItem separatorItem],
+ [NSMenuItem itemWithTitle:
+ [NSString stringWithFormat:@"Quit %@", applicationName]
+ action: @selector(terminate:) keyEquivalent:@"q"],
+ nil] retain];
+ _defaultApplicationMenu = [TKMenu menuWithTitle:applicationName
+ menuItems:_defaultApplicationMenuItems];
+ [_defaultApplicationMenu insertItem:
+ [NSMenuItem itemWithTitle:
+ [NSString stringWithFormat:@"About %@", aboutName]
+ action:@selector(orderFrontStandardAboutPanel:)] atIndex:0];
+
+ TKMenu *fileMenu = [TKMenu menuWithTitle:@"File" menuItems:
+ [NSArray arrayWithObjects:
+ [NSMenuItem itemWithTitle:
+ [NSString stringWithFormat:@"Source%C", 0x2026]
+ action:@selector(tkSource:)],
+ [NSMenuItem itemWithTitle:@"Run Widget Demo"
+ action:@selector(tkDemo:)],
+ [NSMenuItem itemWithTitle:@"Close" action:@selector(performClose:)
+ target:nil keyEquivalent:@"w"],
+ nil]];
+ TKMenu *editMenu = [TKMenu menuWithTitle:@"Edit" menuItems:
+ [NSArray arrayWithObjects:
+ [NSMenuItem itemWithTitle:@"Undo" action:@selector(undo:)
+ target:nil keyEquivalent:@"z"],
+ [NSMenuItem itemWithTitle:@"Redo" action:@selector(redo:)
+ target:nil keyEquivalent:@"y"],
+ [NSMenuItem separatorItem],
+ [NSMenuItem itemWithTitle:@"Cut" action:@selector(cut:)
+ target:nil keyEquivalent:@"x"],
+ [NSMenuItem itemWithTitle:@"Copy" action:@selector(copy:)
+ target:nil keyEquivalent:@"c"],
+ [NSMenuItem itemWithTitle:@"Paste" action:@selector(paste:)
+ target:nil keyEquivalent:@"v"],
+ [NSMenuItem itemWithTitle:@"Delete" action:@selector(delete:)
+ target:nil],
+ nil]];
+
+ _defaultWindowsMenuItems = [NSArray arrayWithObjects:
+ [NSMenuItem itemWithTitle:@"Minimize"
+ action:@selector(performMiniaturize:) target:nil
+ keyEquivalent:@"m"],
+ [NSMenuItem itemWithTitle:@"Zoom" action:@selector(performZoom:)
+ target:nil],
+ nil];
+
+ /*
+ * On OS X 10.12 we get duplicate tab control items if we create them here.
+ */
+
+ if ([NSApp macMinorVersion] > 12) {
+ _defaultWindowsMenuItems = [_defaultWindowsMenuItems
+ arrayByAddingObjectsFromArray:
+ [NSArray arrayWithObjects:
+ [NSMenuItem separatorItem],
+ [NSMenuItem itemWithTitle:@"Show Previous Tab"
+ action:@selector(selectPreviousTab:)
+ target:nil
+ keyEquivalent:@"\t"
+ keyEquivalentModifierMask:
+ NSControlKeyMask|NSShiftKeyMask],
+ [NSMenuItem itemWithTitle:@"Show Next Tab"
+ action:@selector(selectNextTab:)
+ target:nil
+ keyEquivalent:@"\t"
+ keyEquivalentModifierMask:NSControlKeyMask],
+ [NSMenuItem itemWithTitle:@"Move Tab To New Window"
+ action:@selector(moveTabToNewWindow:)
+ target:nil],
+ [NSMenuItem itemWithTitle:@"Merge All Windows"
+ action:@selector(mergeAllWindows:)
+ target:nil],
+ [NSMenuItem separatorItem],
+ nil]];
+ }
+ _defaultWindowsMenuItems = [_defaultWindowsMenuItems arrayByAddingObject:
+ [NSMenuItem itemWithTitle:@"Bring All to Front"
+ action:@selector(arrangeInFront:)]];
+ [_defaultWindowsMenuItems retain];
+ TKMenu *windowsMenu = [TKMenu menuWithTitle:@"Window" menuItems:
+ _defaultWindowsMenuItems];
+
+ _defaultHelpMenuItems = [[NSArray arrayWithObjects:
+ [NSMenuItem itemWithTitle:
+ [NSString stringWithFormat:@"%@ Help", applicationName]
+ action:@selector(showHelp:) keyEquivalent:@"?"],
+ nil] retain];
+
+ TKMenu *helpMenu = [TKMenu menuWithTitle:@"Help" menuItems:
+ _defaultHelpMenuItems];
+
+ [self setServicesMenu:_servicesMenu];
+ [self setWindowsMenu:windowsMenu];
+ _defaultMainMenu = [[TKMenu menuWithTitle:@"" submenus:[NSArray
+ arrayWithObjects:_defaultApplicationMenu, fileMenu, editMenu,
+ windowsMenu, helpMenu, nil]] retain];
+ [_defaultMainMenu setSpecial:tkMainMenu];
+ [_defaultApplicationMenu setSpecial:tkApplicationMenu];
+ [windowsMenu setSpecial:tkWindowsMenu];
+ [helpMenu setSpecial:tkHelpMenu];
+ [self tkSetMainMenu:nil];
+}
+
+- (void) dealloc
+{
+ [_defaultMainMenu release];
+ [_defaultHelpMenuItems release];
+ [_defaultWindowsMenuItems release];
+ [_defaultApplicationMenuItems release];
+ [super dealloc];
+}
+
+- (BOOL) validateUserInterfaceItem: (id <NSValidatedUserInterfaceItem>) anItem
+{
+ SEL action = [anItem action];
+
+ if (sel_isEqual(action, @selector(preferences:))) {
+ return (_eventInterp && Tcl_FindCommand(_eventInterp,
+ "::tk::mac::ShowPreferences", NULL, 0));
+ } else if (sel_isEqual(action, @selector(tkDemo:))) {
+ BOOL haveDemo = NO;
+
+ if (_eventInterp) {
+ Tcl_Obj *path = GetWidgetDemoPath(_eventInterp);
+
+ if (path) {
+ Tcl_IncrRefCount(path);
+ haveDemo = (Tcl_FSAccess(path, R_OK) == 0);
+ Tcl_DecrRefCount(path);
+ }
+ }
+ return haveDemo;
+ } else {
+ return [super validateUserInterfaceItem:anItem];
+ }
+}
+
+- (void) orderFrontStandardAboutPanel: (id) sender
+{
+ if (!_eventInterp || !Tcl_FindCommand(_eventInterp, "tkAboutDialog",
+ NULL, 0) || (GetCurrentEventKeyModifiers() & optionKey)) {
+ TkAboutDlg();
+ } else {
+ int code = Tcl_EvalEx(_eventInterp, "tkAboutDialog", -1,
+ TCL_EVAL_GLOBAL);
+
+ if (code != TCL_OK) {
+ Tcl_BackgroundException(_eventInterp, code);
+ }
+ Tcl_ResetResult(_eventInterp);
+ }
+}
+
+- (void) showHelp: (id) sender
+{
+ if (!_eventInterp || !Tcl_FindCommand(_eventInterp,
+ "::tk::mac::ShowHelp", NULL, 0)) {
+ [super showHelp:sender];
+ } else {
+ int code = Tcl_EvalEx(_eventInterp, "::tk::mac::ShowHelp", -1,
+ TCL_EVAL_GLOBAL);
+
+ if (code != TCL_OK) {
+ Tcl_BackgroundException(_eventInterp, code);
+ }
+ Tcl_ResetResult(_eventInterp);
+ }
+}
+
+- (void) tkSource: (id) sender
+{
+ if (_eventInterp) {
+ if (Tcl_EvalEx(_eventInterp, "tk_getOpenFile -filetypes {"
+ "{{TCL Scripts} {.tcl} TEXT} {{Text Files} {} TEXT}}",
+ -1, TCL_EVAL_GLOBAL) == TCL_OK) {
+ Tcl_Obj *path = Tcl_GetObjResult(_eventInterp);
+ int len;
+
+ Tcl_GetStringFromObj(path, &len);
+ if (len) {
+ Tcl_IncrRefCount(path);
+
+ int code = Tcl_FSEvalFileEx(_eventInterp, path, NULL);
+
+ if (code != TCL_OK) {
+ Tcl_BackgroundException(_eventInterp, code);
+ }
+ Tcl_DecrRefCount(path);
+ }
+ }
+ Tcl_ResetResult(_eventInterp);
+ }
+}
+
+- (void) tkDemo: (id) sender
+{
+ if (_eventInterp) {
+ Tcl_Obj *path = GetWidgetDemoPath(_eventInterp);
+
+ if (path) {
+ Tcl_IncrRefCount(path);
+
+ int code = Tcl_FSEvalFileEx(_eventInterp, path, NULL);
+
+ if (code != TCL_OK) {
+ Tcl_BackgroundException(_eventInterp, code);
+ }
+ Tcl_DecrRefCount(path);
+ Tcl_ResetResult(_eventInterp);
+ }
+ }
+}
+@end
+
+#pragma mark TKContentView(TKMenus)
+
+@implementation TKContentView(TKMenus)
+
+- (BOOL) validateUserInterfaceItem: (id <NSValidatedUserInterfaceItem>) anItem
+{
+ return YES;
+}
+
+#define EDIT_ACTION(a, e) \
+ - (void) a: (id) sender \
+ { \
+ if ([sender isKindOfClass:[NSMenuItem class]]) { \
+ GenerateEditEvent(#e); \
+ } \
+ }
+EDIT_ACTION(cut, Cut)
+EDIT_ACTION(copy, Copy)
+EDIT_ACTION(paste, Paste)
+EDIT_ACTION(delete, Clear)
+EDIT_ACTION(undo, Undo)
+EDIT_ACTION(redo, Redo)
+#undef EDIT_ACTION
+@end
+
+#pragma mark -
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetWidgetDemoPath --
+ *
+ * Get path to the widget demo.
+ *
+ * Results:
+ * pathObj with ref count 0.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj *
+GetWidgetDemoPath(
+ Tcl_Interp *interp)
+{
+ Tcl_Obj *libpath, *result = NULL;
+
+ libpath = Tcl_GetVar2Ex(interp, "tk_library", NULL, TCL_GLOBAL_ONLY);
+ if (libpath) {
+ Tcl_Obj *demo[2] = { Tcl_NewStringObj("demos", 5),
+ Tcl_NewStringObj("widget", 6) };
+
+ Tcl_IncrRefCount(libpath);
+ result = Tcl_FSJoinToPath(libpath, 2, demo);
+ Tcl_DecrRefCount(libpath);
+ } else {
+ Tcl_ResetResult(interp);
+ }
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXHandleMenuSelect --
+ *
+ * Handles events that occur in the Menu bar.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXHandleMenuSelect(
+ short theMenu,
+ unsigned short theItem,
+ int optionKeyPressed)
+{
+ Tcl_Panic("TkMacOSXHandleMenuSelect: Obsolete, no more Carbon!");
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXInitMenus --
+ *
+ * This procedure initializes the Macintosh menu bar.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXInitMenus(
+ Tcl_Interp *interp)
+{
+ [NSApp _setupMenus];
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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(
+ const char *name)
+{
+ XVirtualEvent event;
+ int x, y;
+ TkWindow *winPtr = TkMacOSXGetTkWindow([NSApp keyWindow]);
+ Tk_Window tkwin;
+
+ if (!winPtr) {
+ return;
+ }
+ tkwin = (Tk_Window) winPtr->dispPtr->focusPtr;
+ if (!tkwin) {
+ return;
+ }
+ bzero(&event, sizeof(XVirtualEvent));
+ event.type = VirtualEvent;
+ event.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
+ 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();
+ XQueryPointer(NULL, winPtr->window, NULL, NULL,
+ &event.x_root, &event.y_root, &x, &y, &event.state);
+ Tk_TopCoordsToWindow(tkwin, x, y, &event.x, &event.y);
+ event.same_screen = true;
+ event.name = Tk_GetUid(name);
+ Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
+}
+
+#pragma mark -
+
+#pragma mark NSMenu & NSMenuItem Utilities
+
+@implementation NSMenu(TKUtils)
+
++ (id) menuWithTitle: (NSString *) title
+{
+ NSMenu *m = [[self alloc] initWithTitle:title];
+
+ return [m autorelease];
+}
+
++ (id) menuWithTitle: (NSString *) title menuItems: (NSArray *) items
+{
+ NSMenu *m = [[self alloc] initWithTitle:title];
+
+ for (NSMenuItem *i in items) {
+ [m addItem:i];
+ }
+ return [m autorelease];
+}
+
++ (id) menuWithTitle: (NSString *) title submenus: (NSArray *) submenus
+{
+ NSMenu *m = [[self alloc] initWithTitle:title];
+
+ for (NSMenu *i in submenus) {
+ [m addItem:[NSMenuItem itemWithSubmenu:i]];
+ }
+ return [m autorelease];
+}
+
+- (NSMenuItem *) itemWithSubmenu: (NSMenu *) submenu
+{
+ return [self itemAtIndex:[self indexOfItemWithSubmenu:submenu]];
+}
+
+- (NSMenuItem *) itemInSupermenu
+{
+ NSMenu *supermenu = [self supermenu];
+
+ return (supermenu ? [supermenu itemWithSubmenu:self] : nil);
+}
+@end
+
+@implementation NSMenuItem(TKUtils)
+
++ (id) itemWithSubmenu: (NSMenu *) submenu
+{
+ NSMenuItem *i = [[self alloc] initWithTitle:[submenu title] action:NULL
+ keyEquivalent:@""];
+
+ [i setSubmenu:submenu];
+ return [i autorelease];
+}
+
++ (id) itemWithTitle: (NSString *) title submenu: (NSMenu *) submenu
+{
+ NSMenuItem *i = [[self alloc] initWithTitle:title action:NULL
+ keyEquivalent:@""];
+
+ [i setSubmenu:submenu];
+ return [i autorelease];
+}
+
++ (id) itemWithTitle: (NSString *) title action: (SEL) action
+{
+ NSMenuItem *i = [[self alloc] initWithTitle:title action:action
+ keyEquivalent:@""];
+
+ [i setTarget:NSApp];
+ return [i autorelease];
+}
+
++ (id) itemWithTitle: (NSString *) title action: (SEL) action
+ target: (id) target
+{
+ NSMenuItem *i = [[self alloc] initWithTitle:title action:action
+ keyEquivalent:@""];
+
+ [i setTarget:target];
+ return [i autorelease];
+}
+
++ (id) itemWithTitle: (NSString *) title action: (SEL) action
+ keyEquivalent: (NSString *) keyEquivalent
+{
+ NSMenuItem *i = [[self alloc] initWithTitle:title action:action
+ keyEquivalent:keyEquivalent];
+
+ [i setTarget:NSApp];
+ return [i autorelease];
+}
+
++ (id) itemWithTitle: (NSString *) title action: (SEL) action
+ target: (id) target keyEquivalent: (NSString *) keyEquivalent
+{
+ NSMenuItem *i = [[self alloc] initWithTitle:title action:action
+ keyEquivalent:keyEquivalent];
+
+ [i setTarget:target];
+ return [i autorelease];
+}
+
++ (id) itemWithTitle: (NSString *) title action: (SEL) action
+ keyEquivalent: (NSString *) keyEquivalent
+ keyEquivalentModifierMask: (NSUInteger) keyEquivalentModifierMask
+{
+ NSMenuItem *i = [[self alloc] initWithTitle:title action:action
+ keyEquivalent:keyEquivalent];
+
+ [i setTarget:NSApp];
+ [i setKeyEquivalentModifierMask:keyEquivalentModifierMask];
+ return [i autorelease];
+}
+
++ (id) itemWithTitle: (NSString *) title action: (SEL) action
+ target: (id) target keyEquivalent: (NSString *) keyEquivalent
+ keyEquivalentModifierMask: (NSUInteger) keyEquivalentModifierMask
+{
+ NSMenuItem *i = [[self alloc] initWithTitle:title action:action
+ keyEquivalent:keyEquivalent];
+
+ [i setTarget:target];
+ [i setKeyEquivalentModifierMask:keyEquivalentModifierMask];
+ return [i autorelease];
+}
+@end
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXMouseEvent.c b/tk8.6/macosx/tkMacOSXMouseEvent.c
new file mode 100644
index 0000000..2517769
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXMouseEvent.c
@@ -0,0 +1,689 @@
+/*
+ * tkMacOSXMouseEvent.c --
+ *
+ * This file implements functions that decode & handle mouse events on
+ * MacOS X.
+ *
+ * Copyright 2001-2009, Apple Inc.
+ * Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkMacOSXPrivate.h"
+#include "tkMacOSXWm.h"
+#include "tkMacOSXEvent.h"
+#include "tkMacOSXDebug.h"
+#include "tkMacOSXConstants.h"
+
+typedef struct {
+ unsigned int state;
+ long delta;
+ Window window;
+ Point global;
+ Point local;
+} MouseEventData;
+static Tk_Window captureWinPtr = NULL; /* Current capture window; may be
+ * NULL. */
+
+static int GenerateButtonEvent(MouseEventData *medPtr);
+static unsigned int ButtonModifiers2State(UInt32 buttonState,
+ UInt32 keyModifiers);
+
+#pragma mark TKApplication(TKMouseEvent)
+
+enum {
+ NSWindowWillMoveEventType = 20
+};
+/*
+ * In OS X 10.6 an NSEvent of type NSMouseMoved would always have a non-Nil
+ * window attribute pointing to the active window. As of 10.8 this behavior
+ * had changed. The new behavior was that if the mouse were ever moved outside
+ * of a window, all subsequent NSMouseMoved NSEvents would have a Nil window
+ * attribute. To work around this the TKApplication remembers the last non-Nil
+ * window that it received in a mouse event. If it receives an NSEvent with a
+ * Nil window attribute then the saved window is used.
+ */
+
+@implementation TKApplication(TKMouseEvent)
+- (NSEvent *) tkProcessMouseEvent: (NSEvent *) theEvent
+{
+ NSWindow *eventWindow = [theEvent window];
+ NSEventType eventType = [theEvent type];
+ TkWindow *winPtr = NULL, *grabWinPtr;
+ Tk_Window tkwin;
+ NSPoint local, global;
+#if 0
+ NSTrackingArea *trackingArea = nil;
+ NSInteger eventNumber, clickCount, buttonNumber;
+#endif
+
+#ifdef TK_MAC_DEBUG_EVENTS
+ TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent);
+#endif
+ switch (eventType) {
+ case NSMouseEntered:
+ case NSMouseExited:
+ case NSCursorUpdate:
+ case NSLeftMouseDown:
+ case NSLeftMouseUp:
+ case NSRightMouseDown:
+ case NSRightMouseUp:
+ case NSOtherMouseDown:
+ case NSOtherMouseUp:
+ case NSLeftMouseDragged:
+ case NSRightMouseDragged:
+ case NSOtherMouseDragged:
+ case NSMouseMoved:
+ case NSTabletPoint:
+ case NSTabletProximity:
+ case NSScrollWheel:
+ break;
+ default: /* Unrecognized mouse event. */
+ return theEvent;
+ }
+
+ /*
+ * Compute the mouse position in Tk screen coordinates (global) and in the
+ * Tk coordinates of its containing Tk Window (local). If a grab is in effect,
+ * the local coordinates should be relative to the grab window.
+ */
+
+ if (eventWindow) {
+ local = [theEvent locationInWindow];
+ global = [eventWindow tkConvertPointToScreen: local];
+ tkwin = TkMacOSXGetCapture();
+ if (tkwin) {
+ winPtr = (TkWindow *) tkwin;
+ eventWindow = TkMacOSXDrawableWindow(winPtr->window);
+ if (eventWindow) {
+ local = [eventWindow tkConvertPointFromScreen: global];
+ } else {
+ return theEvent;
+ }
+ }
+ local.y = [eventWindow frame].size.height - local.y;
+ global.y = tkMacOSXZeroScreenHeight - global.y;
+ } else {
+
+ /*
+ * If the event has no NSWindow, the location is in screen coordinates.
+ */
+
+ global = [theEvent locationInWindow];
+ tkwin = TkMacOSXGetCapture();
+ if (tkwin) {
+ winPtr = (TkWindow *) tkwin;
+ eventWindow = TkMacOSXDrawableWindow(winPtr->window);
+ } else {
+ eventWindow = [NSApp mainWindow];
+ }
+ if (!eventWindow) {
+ return theEvent;
+ }
+ local = [eventWindow tkConvertPointFromScreen: global];
+ local.y = [eventWindow frame].size.height - local.y;
+ global.y = tkMacOSXZeroScreenHeight - global.y;
+ }
+
+ /*
+ * Make sure tkwin is the toplevel which should receive the event.
+ */
+
+ if (!tkwin) {
+ winPtr = TkMacOSXGetTkWindow(eventWindow);
+ tkwin = (Tk_Window) winPtr;
+ }
+ if (!tkwin) {
+#ifdef TK_MAC_DEBUG_EVENTS
+ TkMacOSXDbgMsg("tkwin == NULL");
+#endif
+ return theEvent; /* Give up. No window for this event. */
+ }
+
+ /*
+ * If another toplevel has a grab, we ignore the event.
+ */
+
+ grabWinPtr = winPtr->dispPtr->grabWinPtr;
+ if (grabWinPtr &&
+ grabWinPtr != winPtr &&
+ !winPtr->dispPtr->grabFlags && /* this means the grab is local. */
+ grabWinPtr->mainPtr == winPtr->mainPtr) {
+ return theEvent;
+ }
+
+ /*
+ * Convert local from NSWindow flipped coordinates to the toplevel's
+ * coordinates.
+ */
+
+ local.x -= winPtr->wmInfoPtr->xInParent;
+ local.y -= winPtr->wmInfoPtr->yInParent;
+
+ /*
+ * Find the containing Tk window, and convert local into the coordinates
+ * of the Tk window. (The converted local coordinates are only needed
+ * for scrollwheel events.)
+ */
+
+ int win_x, win_y;
+ tkwin = Tk_TopCoordsToWindow(tkwin, local.x, local.y, &win_x, &win_y);
+ local.x = win_x;
+ local.y = win_y;
+
+ /*
+ * Generate an XEvent for this mouse event.
+ */
+
+ unsigned int state = 0;
+ NSInteger button = [theEvent buttonNumber];
+ EventRef eventRef = (EventRef)[theEvent eventRef];
+ UInt32 buttons;
+ OSStatus err = GetEventParameter(eventRef, kEventParamMouseChord,
+ typeUInt32, NULL, sizeof(UInt32), NULL, &buttons);
+
+ if (err == noErr) {
+ state |= (buttons & ((1<<5) - 1)) << 8;
+ } else if (button < 5) {
+ switch (eventType) {
+ case NSLeftMouseDown:
+ case NSRightMouseDown:
+ case NSLeftMouseDragged:
+ case NSRightMouseDragged:
+ case NSOtherMouseDown:
+ state |= 1 << (button + 8);
+ break;
+ default:
+ break;
+ }
+ }
+
+ NSUInteger modifiers = [theEvent modifierFlags];
+
+ if (modifiers & NSAlphaShiftKeyMask) {
+ state |= LockMask;
+ }
+ if (modifiers & NSShiftKeyMask) {
+ state |= ShiftMask;
+ }
+ if (modifiers & NSControlKeyMask) {
+ state |= ControlMask;
+ }
+ if (modifiers & NSCommandKeyMask) {
+ state |= Mod1Mask; /* command key */
+ }
+ if (modifiers & NSAlternateKeyMask) {
+ state |= Mod2Mask; /* option key */
+ }
+ if (modifiers & NSNumericPadKeyMask) {
+ state |= Mod3Mask;
+ }
+ if (modifiers & NSFunctionKeyMask) {
+ state |= Mod4Mask;
+ }
+
+ if (eventType != NSScrollWheel) {
+ /*
+ * For normal mouse events, Tk_UpdatePointer will send the XEvent.
+ */
+
+#ifdef TK_MAC_DEBUG_EVENTS
+ TKLog(@"UpdatePointer %p x %f.0 y %f.0 %d",
+ tkwin, global.x, global.y, state);
+#endif
+ Tk_UpdatePointer(tkwin, global.x, global.y, state);
+ } else {
+ /*
+ * For scroll wheel events we need to send the XEvent here.
+ */
+
+ CGFloat delta;
+ int coarseDelta;
+ XEvent xEvent;
+
+ xEvent.type = MouseWheelEvent;
+ xEvent.xbutton.x = local.x;
+ xEvent.xbutton.y = local.y;
+ xEvent.xbutton.x_root = global.x;
+ xEvent.xbutton.y_root = global.y;
+ xEvent.xany.send_event = false;
+ xEvent.xany.display = Tk_Display(tkwin);
+ xEvent.xany.window = Tk_WindowId(tkwin);
+
+ delta = [theEvent deltaY];
+ if (delta != 0.0) {
+ coarseDelta = (delta > -1.0 && delta < 1.0) ?
+ (signbit(delta) ? -1 : 1) : lround(delta);
+ xEvent.xbutton.state = state;
+ xEvent.xkey.keycode = coarseDelta;
+ xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
+ Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
+ }
+ delta = [theEvent deltaX];
+ if (delta != 0.0) {
+ coarseDelta = (delta > -1.0 && delta < 1.0) ?
+ (signbit(delta) ? -1 : 1) : lround(delta);
+ xEvent.xbutton.state = state | ShiftMask;
+ xEvent.xkey.keycode = coarseDelta;
+ xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
+ Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
+ }
+ }
+ return theEvent;
+}
+@end
+
+#pragma mark -
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXKeyModifiers --
+ *
+ * Returns the current state of the modifier keys.
+ *
+ * Results:
+ * An OS Modifier state.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+EventModifiers
+TkMacOSXModifierState(void)
+{
+ UInt32 keyModifiers;
+ int isFrontProcess = (GetCurrentEvent() && Tk_MacOSXIsAppInFront());
+
+ keyModifiers = isFrontProcess ? GetCurrentEventKeyModifiers() :
+ GetCurrentKeyModifiers();
+
+ return (EventModifiers) (keyModifiers & USHRT_MAX);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+unsigned int
+TkMacOSXButtonKeyState(void)
+{
+ UInt32 buttonState = 0, keyModifiers;
+ int isFrontProcess = (GetCurrentEvent() && Tk_MacOSXIsAppInFront());
+
+ buttonState = isFrontProcess ? GetCurrentEventButtonState() :
+ GetCurrentButtonState();
+ keyModifiers = isFrontProcess ? GetCurrentEventKeyModifiers() :
+ GetCurrentKeyModifiers();
+
+ return ButtonModifiers2State(buttonState, keyModifiers);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ButtonModifiers2State --
+ *
+ * Converts Carbon mouse button state and modifier values into a Tk
+ * button/modifier state.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static unsigned int
+ButtonModifiers2State(
+ UInt32 buttonState,
+ UInt32 keyModifiers)
+{
+ unsigned int state;
+
+ /*
+ * Tk supports at most 5 buttons.
+ */
+
+ state = (buttonState & ((1<<5) - 1)) << 8;
+
+ if (keyModifiers & alphaLock) {
+ state |= LockMask;
+ }
+ if (keyModifiers & shiftKey) {
+ state |= ShiftMask;
+ }
+ if (keyModifiers & controlKey) {
+ state |= ControlMask;
+ }
+ if (keyModifiers & cmdKey) {
+ state |= Mod1Mask; /* command key */
+ }
+ if (keyModifiers & optionKey) {
+ state |= Mod2Mask; /* option key */
+ }
+ if (keyModifiers & kEventKeyModifierNumLockMask) {
+ state |= Mod3Mask;
+ }
+ if (keyModifiers & kEventKeyModifierFnMask) {
+ state |= Mod4Mask;
+ }
+
+ 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)
+{
+ int getGlobal = (root_x_return && root_y_return);
+ int getLocal = (win_x_return && win_y_return && w != None);
+
+ if (getGlobal || getLocal) {
+ NSPoint global = [NSEvent mouseLocation];
+
+ if (getLocal) {
+ MacDrawable *macWin = (MacDrawable *) w;
+ NSWindow *win = TkMacOSXDrawableWindow(w);
+
+ if (win) {
+ NSPoint local;
+
+ local = [win tkConvertPointFromScreen:global];
+ local.y = [win frame].size.height - local.y;
+ if (macWin->winPtr && macWin->winPtr->wmInfoPtr) {
+ local.x -= macWin->winPtr->wmInfoPtr->xInParent;
+ local.y -= macWin->winPtr->wmInfoPtr->yInParent;
+ }
+ *win_x_return = local.x;
+ *win_y_return = local.y;
+ }
+ }
+ if (getGlobal) {
+ *root_x_return = global.x;
+ *root_y_return = tkMacOSXZeroScreenHeight - global.y;
+ }
+ }
+ if (mask_return) {
+ *mask_return = TkMacOSXButtonKeyState();
+ }
+ return True;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkGenerateButtonEventForXPointer --
+ *
+ * This procedure generates an X button event for the current pointer
+ * state as reported by XQueryPointer().
+ *
+ * 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+MODULE_SCOPE int
+TkGenerateButtonEventForXPointer(
+ Window window) /* X Window containing button event. */
+{
+ MouseEventData med;
+ int global_x, global_y, local_x, local_y;
+
+ bzero(&med, sizeof(MouseEventData));
+ XQueryPointer(NULL, window, NULL, NULL, &global_x, &global_y,
+ &local_x, &local_y, &med.state);
+ med.global.h = global_x;
+ med.global.v = global_y;
+ med.local.h = local_x;
+ med.local.v = local_y;
+ med.window = window;
+
+ return GenerateButtonEvent(&med);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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. */
+{
+ MacDrawable *macWin = (MacDrawable *) window;
+ NSWindow *win = TkMacOSXDrawableWindow(window);
+ MouseEventData med;
+
+ bzero(&med, sizeof(MouseEventData));
+ med.state = state;
+ med.window = window;
+ med.global.h = x;
+ med.global.v = y;
+ med.local = med.global;
+
+ if (win) {
+ NSPoint local = NSMakePoint(x, tkMacOSXZeroScreenHeight - y);
+
+ local = [win tkConvertPointFromScreen:local];
+ local.y = [win frame].size.height - local.y;
+ if (macWin->winPtr && macWin->winPtr->wmInfoPtr) {
+ local.x -= macWin->winPtr->wmInfoPtr->xInParent;
+ local.y -= macWin->winPtr->wmInfoPtr->yInParent;
+ }
+ med.local.h = local.x;
+ med.local.v = tkMacOSXZeroScreenHeight - local.y;
+ }
+
+ return GenerateButtonEvent(&med);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GenerateButtonEvent --
+ *
+ * Generate an X button event from a MouseEventData structure. 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GenerateButtonEvent(
+ MouseEventData *medPtr)
+{
+ Tk_Window tkwin;
+ int dummy;
+ TkDisplay *dispPtr;
+
+#if UNUSED
+ /*
+ * 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.
+ */
+
+ if ((medPtr->activeNonFloating == NULL)
+ || ((!(TkpIsWindowFloating(medPtr->whichWin))
+ && (medPtr->activeNonFloating != medPtr->whichWin))
+ && TkMacOSXGetCapture() == NULL)) {
+ return false;
+ }
+#endif
+
+ dispPtr = TkGetDisplayList();
+ tkwin = Tk_IdToWindow(dispPtr->display, medPtr->window);
+
+ if (tkwin != NULL) {
+ tkwin = Tk_TopCoordsToWindow(tkwin, medPtr->local.h, medPtr->local.v,
+ &dummy, &dummy);
+ }
+
+ Tk_UpdatePointer(tkwin, medPtr->global.h, medPtr->global.v, medPtr->state);
+ return true;
+}
+
+void
+TkpWarpPointer(
+ TkDisplay *dispPtr)
+{
+ CGPoint pt;
+ UInt32 buttonState;
+
+ if (dispPtr->warpWindow) {
+ int x, y;
+
+ Tk_GetRootCoords(dispPtr->warpWindow, &x, &y);
+ pt.x = x + dispPtr->warpX;
+ pt.y = y + dispPtr->warpY;
+ } else {
+ pt.x = dispPtr->warpX;
+ pt.y = dispPtr->warpY;
+ }
+
+ /*
+ * Tell the OSX core to generate the events to make it happen.
+ */
+
+ buttonState = [NSEvent pressedMouseButtons];
+ CGEventType type = kCGEventMouseMoved;
+ CGEventRef theEvent = CGEventCreateMouseEvent(NULL, type, pt,
+ buttonState);
+ CGWarpMouseCursorPosition(pt);
+ CGEventPost(kCGHIDEventTap, theEvent);
+ CFRelease(theEvent);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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 && !Tk_IsTopLevel(winPtr)) {
+ winPtr = winPtr->parentPtr;
+ }
+ captureWinPtr = (Tk_Window) winPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXGetCapture --
+ *
+ * Results:
+ * Returns the current grab window
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_Window
+TkMacOSXGetCapture(void)
+{
+ return captureWinPtr;
+}
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXNotify.c b/tk8.6/macosx/tkMacOSXNotify.c
new file mode 100644
index 0000000..7267b00
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXNotify.c
@@ -0,0 +1,416 @@
+/*
+ * tkMacOSXNotify.c --
+ *
+ * This file contains the implementation of a tcl event source
+ * for the AppKit event loop.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ * Copyright 2001-2009, Apple Inc.
+ * Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright 2015 Marc Culler.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkMacOSXPrivate.h"
+#include "tkMacOSXEvent.h"
+#include "tkMacOSXConstants.h"
+#include <tclInt.h>
+#import <objc/objc-auto.h>
+
+/* This is not used for anything at the moment. */
+typedef struct ThreadSpecificData {
+ int initialized;
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+
+#define TSD_INIT() ThreadSpecificData *tsdPtr = \
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData))
+
+static void TkMacOSXNotifyExitHandler(ClientData clientData);
+static void TkMacOSXEventsSetupProc(ClientData clientData, int flags);
+static void TkMacOSXEventsCheckProc(ClientData clientData, int flags);
+
+#ifdef TK_MAC_DEBUG_EVENTS
+static const char *Tk_EventName[39] = {
+ "",
+ "",
+ "KeyPress", /*2*/
+ "KeyRelease", /*3*/
+ "ButtonPress", /*4*/
+ "ButtonRelease", /*5*/
+ "MotionNotify", /*6*/
+ "EnterNotify", /*7*/
+ "LeaveNotify", /*8*/
+ "FocusIn", /*9*/
+ "FocusOut", /*10*/
+ "KeymapNotify", /*11*/
+ "Expose", /*12*/
+ "GraphicsExpose", /*13*/
+ "NoExpose", /*14*/
+ "VisibilityNotify", /*15*/
+ "CreateNotify", /*16*/
+ "DestroyNotify", /*17*/
+ "UnmapNotify", /*18*/
+ "MapNotify", /*19*/
+ "MapRequest", /*20*/
+ "ReparentNotify", /*21*/
+ "ConfigureNotify", /*22*/
+ "ConfigureRequest", /*23*/
+ "GravityNotify", /*24*/
+ "ResizeRequest", /*25*/
+ "CirculateNotify", /*26*/
+ "CirculateRequest", /*27*/
+ "PropertyNotify", /*28*/
+ "SelectionClear", /*29*/
+ "SelectionRequest", /*30*/
+ "SelectionNotify", /*31*/
+ "ColormapNotify", /*32*/
+ "ClientMessage", /*33*/
+ "MappingNotify", /*34*/
+ "VirtualEvent", /*35*/
+ "ActivateNotify", /*36*/
+ "DeactivateNotify", /*37*/
+ "MouseWheelEvent" /*38*/
+};
+
+static Tk_RestrictAction
+InspectQueueRestrictProc(
+ ClientData arg,
+ XEvent *eventPtr)
+{
+ XVirtualEvent* ve = (XVirtualEvent*) eventPtr;
+ const char *name;
+ long serial = ve->serial;
+ long time = eventPtr->xkey.time;
+
+ if (eventPtr->type == VirtualEvent) {
+ name = ve->name;
+ } else {
+ name = Tk_EventName[eventPtr->type];
+ }
+ fprintf(stderr, " > %s;serial = %lu; time=%lu)\n",
+ name, serial, time);
+ return TK_DEFER_EVENT;
+}
+
+/*
+ * Debugging tool which prints the current Tcl queue.
+ */
+
+void DebugPrintQueue(void)
+{
+ ClientData oldArg;
+ Tk_RestrictProc *oldProc;
+
+ oldProc = Tk_RestrictEvents(InspectQueueRestrictProc, NULL, &oldArg);
+ fprintf(stderr, "Current queue:\n");
+ while (Tcl_DoOneEvent(TCL_ALL_EVENTS|TCL_DONT_WAIT)) {};
+ Tk_RestrictEvents(oldProc, oldArg, &oldArg);
+}
+# endif
+
+#pragma mark TKApplication(TKNotify)
+
+@implementation TKApplication(TKNotify)
+/*
+ * Earlier versions of Tk would override nextEventMatchingMask here, adding a
+ * call to displayIfNeeded on all windows after calling super. This would cause
+ * windows to be redisplayed (if necessary) each time that an event was
+ * received. This was intended to replace Apple's default autoDisplay
+ * mechanism, which the earlier versions of Tk would disable. When autoDisplay
+ * is set to the default value of YES, the Apple event loop will call
+ * displayIfNeeded on all windows at the beginning of each iteration of their
+ * event loop. Since Tk does not call the Apple event loop, it was thought
+ * that the autoDisplay behavior needed to be replicated.
+ *
+ * However, as of OSX 10.14 (Mojave) the autoDisplay property became
+ * deprecated. Luckily it turns out that, even though we don't ever start the
+ * Apple event loop, the Apple window manager still calls displayIfNeeded on
+ * all windows on a regular basis, perhaps each time the queue is empty. So we
+ * no longer, and perhaps never did need to set autoDisplay to NO, nor call
+ * displayIfNeeded on our windows. We can just leave all of that to the window
+ * manager.
+ */
+
+/*
+ * Since the contentView is the first responder for a Tk Window, it is
+ * responsible for sending events up the responder chain. We also check the
+ * pasteboard here.
+ */
+- (void) sendEvent: (NSEvent *) theEvent
+{
+ [super sendEvent:theEvent];
+ [NSApp tkCheckPasteboard];
+#ifdef TK_MAC_DEBUG_EVENTS
+ fprintf(stderr, "Sending event of type %d\n", (int)[theEvent type]);
+ DebugPrintQueue();
+#endif
+}
+@end
+
+#pragma mark -
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetRunLoopMode --
+ *
+ * Results:
+ * RunLoop mode that should be passed to -nextEventMatchingMask:
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+NSString *
+GetRunLoopMode(NSModalSession modalSession)
+{
+ NSString *runLoopMode = nil;
+
+ if (modalSession) {
+ runLoopMode = NSModalPanelRunLoopMode;
+ } else if (TkMacOSXGetCapture()) {
+ runLoopMode = NSEventTrackingRunLoopMode;
+ }
+ if (!runLoopMode) {
+ runLoopMode = [[NSRunLoop currentRunLoop] currentMode];
+ }
+ if (!runLoopMode) {
+ runLoopMode = NSDefaultRunLoopMode;
+ }
+ return runLoopMode;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_MacOSXSetupTkNotifier --
+ *
+ * This procedure is called during Tk initialization to create the event
+ * source for TkAqua events.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A new event source is created.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_MacOSXSetupTkNotifier(void)
+{
+ TSD_INIT();
+
+ if (!tsdPtr->initialized) {
+ tsdPtr->initialized = 1;
+
+ /*
+ * Install TkAqua event source in main event loop thread.
+ */
+
+ if (CFRunLoopGetMain() == CFRunLoopGetCurrent()) {
+ if (![NSThread isMainThread]) {
+ /*
+ * Panic if main runloop is not on the main application thread.
+ */
+
+ Tcl_Panic("Tk_MacOSXSetupTkNotifier: %s",
+ "first [load] of TkAqua has to occur in the main thread!");
+ }
+ Tcl_CreateEventSource(TkMacOSXEventsSetupProc,
+ TkMacOSXEventsCheckProc, NULL);
+ TkCreateExitHandler(TkMacOSXNotifyExitHandler, NULL);
+ Tcl_SetServiceMode(TCL_SERVICE_ALL);
+ TclMacOSXNotifierAddRunLoopMode(NSEventTrackingRunLoopMode);
+ TclMacOSXNotifierAddRunLoopMode(NSModalPanelRunLoopMode);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXNotifyExitHandler --
+ *
+ * This function is called during finalization to clean up the
+ * TkMacOSXNotify module.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+TkMacOSXNotifyExitHandler(
+ ClientData clientData) /* Not used. */
+{
+ TSD_INIT();
+
+ Tcl_DeleteEventSource(TkMacOSXEventsSetupProc,
+ TkMacOSXEventsCheckProc, NULL);
+ tsdPtr->initialized = 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXEventsSetupProc --
+ *
+ * This procedure implements the setup part of the MacOSX event source. It
+ * is invoked by Tcl_DoOneEvent before calling TkMacOSXEventsProc to
+ * process all queued NSEvents. In our case, all we need to do is to set
+ * the Tcl MaxBlockTime to 0 before starting the loop to process all
+ * queued NSEvents.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ *
+ * If NSEvents are queued, then the maximum block time will be set to 0 to
+ * ensure that control returns immediately to Tcl.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+TkMacOSXEventsSetupProc(
+ ClientData clientData,
+ int flags)
+{
+ NSString *runloopMode = [[NSRunLoop currentRunLoop] currentMode];
+
+ /*
+ * runloopMode will be nil if we are in a Tcl event loop.
+ */
+
+ if (flags & TCL_WINDOW_EVENTS && !runloopMode) {
+ static const Tcl_Time zeroBlockTime = { 0, 0 };
+ [NSApp _resetAutoreleasePool];
+
+ /*
+ * Call this with dequeue=NO -- just checking if the queue is empty.
+ */
+
+ NSEvent *currentEvent =
+ [NSApp nextEventMatchingMask:NSAnyEventMask
+ untilDate:[NSDate distantPast]
+ inMode:GetRunLoopMode(TkMacOSXGetModalSession())
+ dequeue:NO];
+ if (currentEvent) {
+ if (currentEvent.type > 0) {
+ Tcl_SetMaxBlockTime(&zeroBlockTime);
+ }
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXEventsCheckProc --
+ *
+ * This procedure loops through all NSEvents waiting in the TKApplication
+ * event queue, generating X events from them.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * NSevents are used to generate X events, which are added to the Tcl
+ * event queue.
+ *
+ *----------------------------------------------------------------------
+ */
+static void
+TkMacOSXEventsCheckProc(
+ ClientData clientData,
+ int flags)
+{
+ NSString *runloopMode = [[NSRunLoop currentRunLoop] currentMode];
+
+ /*
+ * runloopMode will be nil if we are in a Tcl event loop.
+ */
+
+ if (flags & TCL_WINDOW_EVENTS && !runloopMode) {
+ NSEvent *currentEvent = nil;
+ NSEvent *testEvent = nil;
+ NSModalSession modalSession;
+
+ /*
+ * It is possible for the SetupProc to be called before this function
+ * returns. This happens, for example, when we process an event which
+ * opens a modal window. To prevent premature release of our
+ * application-wide autorelease pool by a nested call to the SetupProc,
+ * we must lock it here.
+ */
+
+ [NSApp _lockAutoreleasePool];
+ do {
+ modalSession = TkMacOSXGetModalSession();
+ testEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
+ untilDate:[NSDate distantPast]
+ inMode:GetRunLoopMode(modalSession)
+ dequeue:NO];
+
+ /*
+ * We must not steal any events during LiveResize.
+ */
+
+ if (testEvent && [[testEvent window] inLiveResize]) {
+ break;
+ }
+ currentEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
+ untilDate:[NSDate distantPast]
+ inMode:GetRunLoopMode(modalSession)
+ dequeue:YES];
+ if (currentEvent) {
+ /*
+ * Generate Xevents.
+ */
+
+ int oldServiceMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
+ NSEvent *processedEvent = [NSApp tkProcessEvent:currentEvent];
+ Tcl_SetServiceMode(oldServiceMode);
+ if (processedEvent) {
+#ifdef TK_MAC_DEBUG_EVENTS
+ TKLog(@" event: %@", currentEvent);
+#endif
+ if (modalSession) {
+ [NSApp _modalSession:modalSession sendEvent:currentEvent];
+ } else {
+ [NSApp sendEvent:currentEvent];
+ }
+ }
+ } else {
+ break;
+ }
+ } while (1);
+
+ /*
+ * Now we can unlock the pool.
+ */
+
+ [NSApp _unlockAutoreleasePool];
+ }
+}
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXPort.h b/tk8.6/macosx/tkMacOSXPort.h
new file mode 100644
index 0000000..617abda
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXPort.h
@@ -0,0 +1,167 @@
+/*
+ * 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-2009, Apple Inc.
+ * Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef _TKMACPORT
+#define _TKMACPORT
+
+#include <stdio.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <math.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#endif
+#include <sys/stat.h>
+#ifndef _TCL
+# include <tcl.h>
+#endif
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#include <unistd.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>
+
+/*
+ * The following macro defines the type of the mask arguments to
+ * select:
+ */
+
+#ifndef NO_FD_SET
+# define SELECT_MASK fd_set
+#else
+# ifndef _AIX
+ typedef long fd_mask;
+# endif
+# if defined(_IBMR2)
+# define SELECT_MASK void
+# else
+# define SELECT_MASK int
+# endif
+#endif
+
+/*
+ * The following macro defines the number of fd_masks in an fd_set:
+ */
+
+#ifndef FD_SETSIZE
+# ifdef OPEN_MAX
+# define FD_SETSIZE OPEN_MAX
+# else
+# define FD_SETSIZE 256
+# endif
+#endif
+#if !defined(howmany)
+# define howmany(x, y) (((x)+((y)-1))/(y))
+#endif
+#ifndef NFDBITS
+# define NFDBITS NBBY*sizeof(fd_mask)
+#endif
+#define MASK_SIZE howmany(FD_SETSIZE, NFDBITS)
+
+/*
+ * Define "NBBY" (number of bits per byte) if it's not already defined.
+ */
+
+#ifndef NBBY
+# define NBBY 8
+#endif
+
+/*
+ * The following define causes Tk to use its internal keysym hash table
+ */
+
+#define REDO_KEYSYM_LOOKUP
+
+/*
+ * 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(data);}
+#define XGrabServer(display)
+#define XNoOp(display) {display->request++;}
+#define XUngrabServer(display)
+#define XSynchronize(display, bool) {display->request++;}
+#define XVisualIDFromVisual(visual) (visual->visualid)
+
+/*
+ * The following functions are not used on the Mac, so we stub them out.
+ */
+
+#define TkpCmapStressed(tkwin,colormap) (0)
+#define TkpFreeColor(tkColPtr)
+#define TkSetPixmapColormap(p,c) {}
+#define TkpSync(display)
+
+/*
+ * This macro stores a representation of the window handle in a string.
+ */
+
+#define TkpPrintWindowId(buf,w) \
+ sprintf((buf), "0x%lx", (unsigned long) (w))
+
+/*
+ * Turn off Tk double-buffering as Aqua windows are already double-buffered.
+ */
+
+#define TK_NO_DOUBLE_BUFFERING 1
+
+/*
+ * Magic pixel code values for system colors.
+ *
+ * NOTE: values must be kept in sync with indices into the
+ * systemColorMap array in tkMacOSXColor.c !
+ */
+
+#define TRANSPARENT_PIXEL 30
+#define APPEARANCE_PIXEL 52
+#define PIXEL_MAGIC ((unsigned char) 0x69)
+
+/*
+ * The following macro returns the pixel value that corresponds to the
+ * 16-bit RGB values in the given XColor structure.
+ * The format is: (PIXEL_MAGIC <<< 24) | (R << 16) | (G << 8) | B
+ * where each of R, G and B is the high order byte of a 16-bit component.
+ */
+
+#define TkpGetPixel(p) ((((((PIXEL_MAGIC << 8) \
+ | (((p)->red >> 8) & 0xff)) << 8) \
+ | (((p)->green >> 8) & 0xff)) << 8) \
+ | (((p)->blue >> 8) & 0xff))
+
+
+#endif /* _TKMACPORT */
diff --git a/tk8.6/macosx/tkMacOSXPrivate.h b/tk8.6/macosx/tkMacOSXPrivate.h
new file mode 100644
index 0000000..282a000
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXPrivate.h
@@ -0,0 +1,440 @@
+/*
+ * tkMacOSXPrivate.h --
+ *
+ * Macros and declarations that are purely internal & private to TkAqua.
+ *
+ * Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright 2008-2009, Apple Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id$
+ */
+
+#ifndef _TKMACPRIV
+#define _TKMACPRIV
+
+#if !__OBJC__
+#error Objective-C compiler required
+#endif
+
+#define TextStyle MacTextStyle
+#import <ApplicationServices/ApplicationServices.h>
+#import <Cocoa/Cocoa.h>
+#ifndef NO_CARBON_H
+#import <Carbon/Carbon.h>
+#endif
+#undef TextStyle
+#import <objc/runtime.h> /* for sel_isEqual() */
+
+#ifndef _TKMACINT
+#include "tkMacOSXInt.h"
+#endif
+#ifndef _TKMACDEFAULT
+#include "tkMacOSXDefault.h"
+#endif
+
+/* Macros for Mac OS X API availability checking */
+#define TK_IF_MAC_OS_X_API(vers, symbol, ...) \
+ tk_if_mac_os_x_10_##vers(symbol != NULL, 1, __VA_ARGS__)
+#define TK_ELSE_MAC_OS_X(vers, ...) \
+ tk_else_mac_os_x_10_##vers(__VA_ARGS__)
+#define TK_IF_MAC_OS_X_API_COND(vers, symbol, cond, ...) \
+ tk_if_mac_os_x_10_##vers(symbol != NULL, cond, __VA_ARGS__)
+#define TK_ELSE(...) \
+ } else { __VA_ARGS__
+#define TK_ENDIF \
+ }
+/* Private macros that implement the checking macros above */
+#define tk_if_mac_os_x_yes(chk, cond, ...) \
+ if (cond) { __VA_ARGS__
+#define tk_else_mac_os_x_yes(...) \
+ } else {
+#define tk_if_mac_os_x_chk(chk, cond, ...) \
+ if ((chk) && (cond)) { __VA_ARGS__
+#define tk_else_mac_os_x_chk(...) \
+ } else { __VA_ARGS__
+#define tk_if_mac_os_x_no(chk, cond, ...) \
+ if (0) {
+#define tk_else_mac_os_x_no(...) \
+ } else { __VA_ARGS__
+
+/*
+ * Macros for DEBUG_ASSERT_MESSAGE et al from Debugging.h.
+ */
+
+#undef kComponentSignatureString
+#undef COMPONENT_SIGNATURE
+#define kComponentSignatureString "TkMacOSX"
+#define COMPONENT_SIGNATURE 'Tk '
+
+/*
+ * Macros abstracting checks only active in a debug build.
+ */
+
+#ifdef TK_MAC_DEBUG
+#define TKLog(f, ...) NSLog(f, ##__VA_ARGS__)
+
+/*
+ * Macro to do debug message output.
+ */
+#define TkMacOSXDbgMsg(m, ...) \
+ do { \
+ TKLog(@"%s:%d: %s(): " m, strrchr(__FILE__, '/')+1, \
+ __LINE__, __func__, ##__VA_ARGS__); \
+ } while (0)
+
+/*
+ * Macro to do debug API failure message output.
+ */
+#define TkMacOSXDbgOSErr(f, err) \
+ do { \
+ TkMacOSXDbgMsg("%s failed: %d", #f, (int)(err)); \
+ } while (0)
+
+/*
+ * Macro to do very common check for noErr return from given API and output
+ * debug message in case of failure.
+ */
+#define ChkErr(f, ...) ({ \
+ OSStatus err = f(__VA_ARGS__); \
+ if (err != noErr) { \
+ TkMacOSXDbgOSErr(f, err); \
+ } \
+ err;})
+
+#else /* TK_MAC_DEBUG */
+#define TKLog(f, ...)
+#define TkMacOSXDbgMsg(m, ...)
+#define TkMacOSXDbgOSErr(f, err)
+#define ChkErr(f, ...) ({f(__VA_ARGS__);})
+#endif /* TK_MAC_DEBUG */
+
+/*
+ * Macro abstracting use of TkMacOSXGetNamedSymbol to init named symbols.
+ */
+
+#define TkMacOSXInitNamedSymbol(module, ret, symbol, ...) \
+ static ret (* symbol)(__VA_ARGS__) = (void*)(-1L); \
+ if (symbol == (void*)(-1L)) { \
+ symbol = TkMacOSXGetNamedSymbol(STRINGIFY(module), \
+ STRINGIFY(symbol)); \
+ }
+
+/*
+ * Structure encapsulating current drawing environment.
+ */
+
+typedef struct TkMacOSXDrawingContext {
+ CGContextRef context;
+ NSView *view;
+ HIShapeRef clipRgn;
+ CGRect portBounds;
+} TkMacOSXDrawingContext;
+
+/*
+ * Variables internal to TkAqua.
+ */
+
+MODULE_SCOPE CGFloat tkMacOSXZeroScreenHeight;
+MODULE_SCOPE CGFloat tkMacOSXZeroScreenTop;
+MODULE_SCOPE long tkMacOSXMacOSXVersion;
+
+/*
+ * Prototypes for TkMacOSXRegion.c.
+ */
+
+#if 0
+MODULE_SCOPE void TkMacOSXEmtpyRegion(TkRegion r);
+MODULE_SCOPE int TkMacOSXIsEmptyRegion(TkRegion r);
+#endif
+MODULE_SCOPE HIShapeRef TkMacOSXGetNativeRegion(TkRegion r);
+MODULE_SCOPE void TkMacOSXSetWithNativeRegion(TkRegion r,
+ HIShapeRef rgn);
+MODULE_SCOPE void TkMacOSXOffsetRegion(TkRegion r, short dx, short dy);
+MODULE_SCOPE HIShapeRef TkMacOSXHIShapeCreateEmpty(void);
+MODULE_SCOPE HIMutableShapeRef TkMacOSXHIShapeCreateMutableWithRect(
+ const CGRect *inRect);
+MODULE_SCOPE OSStatus TkMacOSXHIShapeSetWithShape(
+ HIMutableShapeRef inDestShape,
+ HIShapeRef inSrcShape);
+#if 0
+MODULE_SCOPE OSStatus TkMacOSXHIShapeSetWithRect(HIMutableShapeRef inShape,
+ const CGRect *inRect);
+#endif
+MODULE_SCOPE OSStatus TkMacOSHIShapeDifferenceWithRect(
+ HIMutableShapeRef inShape, const CGRect *inRect);
+MODULE_SCOPE OSStatus TkMacOSHIShapeUnionWithRect(HIMutableShapeRef inShape,
+ const CGRect *inRect);
+MODULE_SCOPE OSStatus TkMacOSHIShapeUnion(HIShapeRef inShape1,
+ HIShapeRef inShape2, HIMutableShapeRef outResult);
+
+/*
+ * Prototypes of TkAqua internal procs.
+ */
+
+MODULE_SCOPE void * TkMacOSXGetNamedSymbol(const char *module,
+ const char *symbol);
+MODULE_SCOPE void TkMacOSXDisplayChanged(Display *display);
+MODULE_SCOPE int TkMacOSXUseAntialiasedText(Tcl_Interp *interp,
+ int enable);
+MODULE_SCOPE int TkMacOSXInitCGDrawing(Tcl_Interp *interp, int enable,
+ int antiAlias);
+MODULE_SCOPE int TkMacOSXGenerateFocusEvent(TkWindow *winPtr,
+ int activeFlag);
+MODULE_SCOPE WindowClass TkMacOSXWindowClass(TkWindow *winPtr);
+MODULE_SCOPE int TkMacOSXIsWindowZoomed(TkWindow *winPtr);
+MODULE_SCOPE int TkGenerateButtonEventForXPointer(Window window);
+MODULE_SCOPE EventModifiers TkMacOSXModifierState(void);
+MODULE_SCOPE NSBitmapImageRep* TkMacOSXBitmapRepFromDrawableRect(Drawable drawable,
+ int x, int y, unsigned int width, unsigned int height);
+MODULE_SCOPE CGImageRef TkMacOSXCreateCGImageWithXImage(XImage *image);
+MODULE_SCOPE void TkMacOSXDrawCGImage(Drawable d, GC gc, CGContextRef context,
+ CGImageRef image, unsigned long imageForeground,
+ unsigned long imageBackground, CGRect imageBounds,
+ CGRect srcBounds, CGRect dstBounds);
+MODULE_SCOPE int TkMacOSXSetupDrawingContext(Drawable d, GC gc,
+ int useCG, TkMacOSXDrawingContext *dcPtr);
+MODULE_SCOPE void TkMacOSXRestoreDrawingContext(
+ TkMacOSXDrawingContext *dcPtr);
+MODULE_SCOPE void TkMacOSXSetColorInContext(GC gc, unsigned long pixel,
+ CGContextRef context);
+MODULE_SCOPE int TkMacOSXMakeFullscreen(TkWindow *winPtr,
+ NSWindow *window, int fullscreen,
+ Tcl_Interp *interp);
+MODULE_SCOPE void TkMacOSXEnterExitFullscreen(TkWindow *winPtr,
+ int active);
+MODULE_SCOPE NSWindow* TkMacOSXDrawableWindow(Drawable drawable);
+MODULE_SCOPE NSView* TkMacOSXDrawableView(MacDrawable *macWin);
+MODULE_SCOPE void TkMacOSXWinCGBounds(TkWindow *winPtr, CGRect *bounds);
+MODULE_SCOPE HIShapeRef TkMacOSXGetClipRgn(Drawable drawable);
+MODULE_SCOPE void TkMacOSXInvalidateViewRegion(NSView *view,
+ HIShapeRef rgn);
+MODULE_SCOPE CGContextRef TkMacOSXGetCGContextForDrawable(Drawable drawable);
+MODULE_SCOPE CGImageRef TkMacOSXCreateCGImageWithDrawable(Drawable drawable);
+MODULE_SCOPE NSImage* TkMacOSXGetNSImageWithTkImage(Display *display,
+ Tk_Image image, int width, int height);
+MODULE_SCOPE NSImage* TkMacOSXGetNSImageWithBitmap(Display *display,
+ Pixmap bitmap, GC gc, int width, int height);
+MODULE_SCOPE CGColorRef TkMacOSXCreateCGColor(GC gc, unsigned long pixel);
+MODULE_SCOPE NSColor* TkMacOSXGetNSColor(GC gc, unsigned long pixel);
+MODULE_SCOPE Tcl_Obj * TkMacOSXGetStringObjFromCFString(CFStringRef str);
+MODULE_SCOPE TkWindow* TkMacOSXGetTkWindow(NSWindow *w);
+MODULE_SCOPE NSFont* TkMacOSXNSFontForFont(Tk_Font tkfont);
+MODULE_SCOPE NSDictionary* TkMacOSXNSFontAttributesForFont(Tk_Font tkfont);
+MODULE_SCOPE NSModalSession TkMacOSXGetModalSession(void);
+MODULE_SCOPE void TkMacOSXSelDeadWindow(TkWindow *winPtr);
+MODULE_SCOPE void TkMacOSXApplyWindowAttributes(TkWindow *winPtr,
+ NSWindow *macWindow);
+MODULE_SCOPE int TkMacOSXStandardAboutPanelObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int TkMacOSXIconBitmapObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE void TkMacOSXDrawSolidBorder(Tk_Window tkwin, GC gc,
+ int inset, int thickness);
+MODULE_SCOPE int TkMacOSXServices_Init(Tcl_Interp *interp);
+MODULE_SCOPE int TkMacOSXRegisterServiceWidgetObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+
+#pragma mark Private Objective-C Classes
+
+#define VISIBILITY_HIDDEN __attribute__((visibility("hidden")))
+
+enum { tkMainMenu = 1, tkApplicationMenu, tkWindowsMenu, tkHelpMenu};
+
+VISIBILITY_HIDDEN
+@interface TKMenu : NSMenu {
+@private
+ void *_tkMenu;
+ NSUInteger _tkOffset, _tkItemCount, _tkSpecial;
+}
+- (void)setSpecial:(NSUInteger)special;
+- (BOOL)isSpecial:(NSUInteger)special;
+@end
+
+@interface TKMenu(TKMenuDelegate) <NSMenuDelegate>
+@end
+
+VISIBILITY_HIDDEN
+@interface TKApplication : NSApplication {
+@private
+ Tcl_Interp *_eventInterp;
+ NSMenu *_servicesMenu;
+ TKMenu *_defaultMainMenu, *_defaultApplicationMenu;
+ NSArray *_defaultApplicationMenuItems, *_defaultWindowsMenuItems;
+ NSArray *_defaultHelpMenuItems;
+ NSAutoreleasePool *_mainPool;
+#ifdef __i386__
+ /* The Objective C runtime used on i386 requires this. */
+ int _poolLock;
+ int _macMinorVersion;
+ Bool _isDrawing;
+#endif
+}
+@property int poolLock;
+@property int macMinorVersion;
+@property Bool isDrawing;
+
+@end
+@interface TKApplication(TKInit)
+- (NSString *)tkFrameworkImagePath:(NSString*)image;
+- (void)_resetAutoreleasePool;
+- (void)_lockAutoreleasePool;
+- (void)_unlockAutoreleasePool;
+@end
+@interface TKApplication(TKKeyboard)
+- (void) keyboardChanged: (NSNotification *) notification;
+@end
+@interface TKApplication(TKWindowEvent) <NSApplicationDelegate>
+- (void) _setupWindowNotifications;
+@end
+@interface TKApplication(TKMenu)
+- (void)tkSetMainMenu:(TKMenu *)menu;
+@end
+@interface TKApplication(TKMenus)
+- (void) _setupMenus;
+@end
+@interface NSApplication(TKNotify)
+/* We need to declare this hidden method. */
+- (void) _modalSession: (NSModalSession) session sendEvent: (NSEvent *) event;
+@end
+@interface TKApplication(TKEvent)
+- (NSEvent *)tkProcessEvent:(NSEvent *)theEvent;
+@end
+@interface TKApplication(TKMouseEvent)
+- (NSEvent *)tkProcessMouseEvent:(NSEvent *)theEvent;
+@end
+@interface TKApplication(TKKeyEvent)
+- (NSEvent *)tkProcessKeyEvent:(NSEvent *)theEvent;
+@end
+@interface TKApplication(TKClipboard)
+- (void)tkProvidePasteboard:(TkDisplay *)dispPtr;
+- (void)tkCheckPasteboard;
+@end
+@interface TKApplication(TKHLEvents)
+- (void) terminate: (id) sender;
+- (void) preferences: (id) sender;
+- (void) handleQuitApplicationEvent: (NSAppleEventDescriptor *)event
+ withReplyEvent: (NSAppleEventDescriptor *)replyEvent;
+- (void) handleOpenApplicationEvent: (NSAppleEventDescriptor *)event
+ withReplyEvent: (NSAppleEventDescriptor *)replyEvent;
+- (void) handleReopenApplicationEvent: (NSAppleEventDescriptor *)event
+ withReplyEvent: (NSAppleEventDescriptor *)replyEvent;
+- (void) handleShowPreferencesEvent: (NSAppleEventDescriptor *)event
+ withReplyEvent: (NSAppleEventDescriptor *)replyEvent;
+- (void) handleOpenDocumentsEvent: (NSAppleEventDescriptor *)event
+ withReplyEvent: (NSAppleEventDescriptor *)replyEvent;
+- (void) handlePrintDocumentsEvent: (NSAppleEventDescriptor *)event
+ withReplyEvent: (NSAppleEventDescriptor *)replyEvent;
+- (void) handleDoScriptEvent: (NSAppleEventDescriptor *)event
+ withReplyEvent: (NSAppleEventDescriptor *)replyEvent;
+- (void)handleURLEvent: (NSAppleEventDescriptor*)event
+ withReplyEvent: (NSAppleEventDescriptor*)replyEvent;
+@end
+
+VISIBILITY_HIDDEN
+@interface TKContentView : NSView <NSTextInput>
+{
+@private
+ NSString *privateWorkingText;
+ Bool _needsRedisplay;
+}
+@property Bool needsRedisplay;
+@end
+
+@interface TKContentView(TKKeyEvent)
+- (void) deleteWorkingText;
+@end
+
+@interface TKContentView(TKWindowEvent)
+- (void) drawRect: (NSRect) rect;
+- (void) generateExposeEvents: (HIShapeRef) shape;
+- (void) tkToolbarButton: (id) sender;
+- (BOOL) isOpaque;
+- (BOOL) wantsDefaultClipping;
+- (BOOL) acceptsFirstResponder;
+- (void) keyDown: (NSEvent *) theEvent;
+@end
+
+@interface NSWindow(TKWm)
+- (NSPoint) tkConvertPointToScreen:(NSPoint)point;
+- (NSPoint) tkConvertPointFromScreen:(NSPoint)point;
+@end
+
+VISIBILITY_HIDDEN
+@interface TKWindow : NSWindow
+@end
+
+@interface TKWindow(TKWm)
+- (void) tkLayoutChanged;
+@end
+
+@interface NSDrawerWindow : NSWindow
+{
+ id _i1, _i2;
+}
+@end
+
+#pragma mark NSMenu & NSMenuItem Utilities
+
+@interface NSMenu(TKUtils)
++ (id)menuWithTitle:(NSString *)title;
++ (id)menuWithTitle:(NSString *)title menuItems:(NSArray *)items;
++ (id)menuWithTitle:(NSString *)title submenus:(NSArray *)submenus;
+- (NSMenuItem *)itemWithSubmenu:(NSMenu *)submenu;
+- (NSMenuItem *)itemInSupermenu;
+@end
+
+@interface NSMenuItem(TKUtils)
++ (id)itemWithSubmenu:(NSMenu *)submenu;
++ (id)itemWithTitle:(NSString *)title submenu:(NSMenu *)submenu;
++ (id)itemWithTitle:(NSString *)title action:(SEL)action;
++ (id)itemWithTitle:(NSString *)title action:(SEL)action
+ target:(id)target;
++ (id)itemWithTitle:(NSString *)title action:(SEL)action
+ keyEquivalent:(NSString *)keyEquivalent;
++ (id)itemWithTitle:(NSString *)title action:(SEL)action
+ target:(id)target keyEquivalent:(NSString *)keyEquivalent;
++ (id)itemWithTitle:(NSString *)title action:(SEL)action
+ keyEquivalent:(NSString *)keyEquivalent
+ keyEquivalentModifierMask:(NSUInteger)keyEquivalentModifierMask;
++ (id)itemWithTitle:(NSString *)title action:(SEL)action
+ target:(id)target keyEquivalent:(NSString *)keyEquivalent
+ keyEquivalentModifierMask:(NSUInteger)keyEquivalentModifierMask;
+@end
+
+@interface NSColorPanel(TKDialog)
+- (void) _setUseModalAppearance: (BOOL) flag;
+@end
+
+@interface NSFont(TKFont)
+- (NSFont *) bestMatchingFontForCharacters: (const UTF16Char *) characters
+ length: (NSUInteger) length attributes: (NSDictionary *) attributes
+ actualCoveredLength: (NSUInteger *) coveredLength;
+@end
+
+/*
+ * This method of NSApplication is not declared in NSApplication.h so we
+ * declare it here to be a method of the TKMenu category.
+ */
+
+@interface NSApplication(TKMenu)
+- (void) setAppleMenu: (NSMenu *) menu;
+@end
+
+#endif /* _TKMACPRIV */
+
+int TkMacOSXGetAppPath(ClientData cd, Tcl_Interp *ip, int objc, Tcl_Obj *const objv[]);
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXRegion.c b/tk8.6/macosx/tkMacOSXRegion.c
new file mode 100644
index 0000000..323318c
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXRegion.c
@@ -0,0 +1,559 @@
+/*
+ * tkMacOSXRegion.c --
+ *
+ * Implements X window calls for manipulating regions
+ *
+ * Copyright (c) 1995-1996 Sun Microsystems, Inc.
+ * Copyright 2001-2009, Apple Inc.
+ * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkMacOSXPrivate.h"
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkCreateRegion --
+ *
+ * Implements the equivelent of the X window function XCreateRegion. See
+ * Xwindow documentation for more details.
+ *
+ * Results:
+ * Returns an allocated region handle.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkRegion
+TkCreateRegion(void)
+{
+ return (TkRegion) HIShapeCreateMutable();
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkDestroyRegion --
+ *
+ * Implements the equivelent of the X window function XDestroyRegion. See
+ * Xwindow documentation for more details.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory is freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkDestroyRegion(
+ TkRegion r)
+{
+ if (r) {
+ CFRelease(r);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkIntersectRegion --
+ *
+ * Implements the equivalent of the X window function XIntersectRegion.
+ * See Xwindow documentation for more details.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkIntersectRegion(
+ TkRegion sra,
+ TkRegion srb,
+ TkRegion dr_return)
+{
+ ChkErr(HIShapeIntersect, (HIShapeRef) sra, (HIShapeRef) srb,
+ (HIMutableShapeRef) dr_return);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkSubtractRegion --
+ *
+ * Implements the equivalent 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)
+{
+ ChkErr(HIShapeDifference, (HIShapeRef) sra, (HIShapeRef) srb,
+ (HIMutableShapeRef) dr_return);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkUnionRectWithRegion --
+ *
+ * Implements the equivelent of the X window function
+ * XUnionRectWithRegion. See Xwindow documentation for more details.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkUnionRectWithRegion(
+ XRectangle* rectangle,
+ TkRegion src_region,
+ TkRegion dest_region_return)
+{
+ const CGRect r = CGRectMake(rectangle->x, rectangle->y,
+ rectangle->width, rectangle->height);
+
+ if (src_region == dest_region_return) {
+ ChkErr(TkMacOSHIShapeUnionWithRect,
+ (HIMutableShapeRef) dest_region_return, &r);
+ } else {
+ HIShapeRef rectRgn = HIShapeCreateWithRect(&r);
+
+ ChkErr(TkMacOSHIShapeUnion, rectRgn, (HIShapeRef) src_region,
+ (HIMutableShapeRef) dest_region_return);
+ CFRelease(rectRgn);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXIsEmptyRegion --
+ *
+ * Return native region for given tk region.
+ *
+ * Results:
+ * 1 if empty, 0 otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkMacOSXIsEmptyRegion(
+ TkRegion r)
+{
+ return HIShapeIsEmpty((HIMutableShapeRef) r) ? 1 : 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkRectInRegion --
+ *
+ * Implements the equivelent of the X window function XRectInRegion. See
+ * Xwindow documentation for more details.
+ *
+ * Results:
+ * Returns RectanglePart or RectangleOut. Note that this is not a complete
+ * implementation since it doesn't test for RectangleIn.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkRectInRegion(
+ TkRegion region,
+ int x,
+ int y,
+ unsigned int width,
+ unsigned int height)
+{
+ if (TkMacOSXIsEmptyRegion(region)) {
+ return RectangleOut;
+ } else {
+ const CGRect r = CGRectMake(x, y, width, height);
+
+ return HIShapeIntersectsRect((HIShapeRef) region, &r) ?
+ RectanglePart : RectangleOut;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkClipBox --
+ *
+ * Implements the equivelent of the X window function XClipBox. See
+ * Xwindow documentation for more details.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkClipBox(
+ TkRegion r,
+ XRectangle *rect_return)
+{
+ CGRect rect;
+
+ HIShapeGetBounds((HIShapeRef) r, &rect);
+ rect_return->x = rect.origin.x;
+ rect_return->y = rect.origin.y;
+ rect_return->width = rect.size.width;
+ rect_return->height = rect.size.height;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpBuildRegionFromAlphaData --
+ *
+ * Set up a rectangle of the given region based on the supplied alpha
+ * data.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * The region is updated, with extra pixels added to it.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpBuildRegionFromAlphaData(
+ TkRegion region, /* Region to update. */
+ unsigned int x, /* Where in region to update. */
+ unsigned int y, /* Where in region to update. */
+ unsigned int width, /* Size of rectangle to update. */
+ unsigned int height, /* Size of rectangle to update. */
+ unsigned char *dataPtr, /* Data to read from. */
+ unsigned int pixelStride, /* num bytes from one piece of alpha
+ * data to the next in the line. */
+ unsigned int lineStride) /* num bytes from one line of alpha
+ * data to the next line. */
+{
+ unsigned char *lineDataPtr;
+ unsigned int x1, y1, end;
+ XRectangle rect;
+
+ for (y1 = 0; y1 < height; y1++) {
+ lineDataPtr = dataPtr;
+ for (x1 = 0; x1 < width; x1 = end) {
+ /*
+ * Search for first non-transparent pixel.
+ */
+
+ while ((x1 < width) && !*lineDataPtr) {
+ x1++;
+ lineDataPtr += pixelStride;
+ }
+ end = x1;
+
+ /*
+ * Search for first transparent pixel.
+ */
+
+ while ((end < width) && *lineDataPtr) {
+ end++;
+ lineDataPtr += pixelStride;
+ }
+ if (end > x1) {
+ rect.x = x + x1;
+ rect.y = y + y1;
+ rect.width = end - x1;
+ rect.height = 1;
+ TkUnionRectWithRegion(&rect, region, region);
+ }
+ }
+ dataPtr += lineStride;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpRetainRegion --
+ *
+ * Increases reference count of region.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpRetainRegion(
+ TkRegion r)
+{
+ CFRetain(r);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpReleaseRegion --
+ *
+ * Decreases reference count of region.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * May free memory.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpReleaseRegion(
+ TkRegion r)
+{
+ CFRelease(r);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXSetEmptyRegion --
+ *
+ * Set region to emtpy.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXSetEmptyRegion(
+ TkRegion r)
+{
+ ChkErr(HIShapeSetEmpty, (HIMutableShapeRef) r);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXGetNativeRegion --
+ *
+ * Return native region for given tk region.
+ *
+ * Results:
+ * Native region, CFRelease when done.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+HIShapeRef
+TkMacOSXGetNativeRegion(
+ TkRegion r)
+{
+ return (HIShapeRef) CFRetain(r);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXSetWithNativeRegion --
+ *
+ * Set region to the native region.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXSetWithNativeRegion(
+ TkRegion r,
+ HIShapeRef rgn)
+{
+ ChkErr(TkMacOSXHIShapeSetWithShape, (HIMutableShapeRef) r, rgn);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXOffsetRegion --
+ *
+ * Offsets region by given distances.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXOffsetRegion(
+ TkRegion r,
+ short dx,
+ short dy)
+{
+ ChkErr(HIShapeOffset, (HIMutableShapeRef) r, dx, dy);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXHIShapeCreateEmpty, TkMacOSXHIShapeCreateMutableWithRect,
+ * TkMacOSXHIShapeSetWithShape, TkMacOSXHIShapeSetWithRect,
+ * TkMacOSHIShapeDifferenceWithRect, TkMacOSHIShapeUnionWithRect,
+ * TkMacOSHIShapeUnion --
+ *
+ * Wrapper functions for missing/buggy HIShape API
+ *
+ *----------------------------------------------------------------------
+ */
+
+HIShapeRef
+TkMacOSXHIShapeCreateEmpty(void)
+{
+ HIShapeRef result;
+
+ result = HIShapeCreateEmpty();
+ return result;
+}
+
+HIMutableShapeRef
+TkMacOSXHIShapeCreateMutableWithRect(
+ const CGRect *inRect)
+{
+ HIMutableShapeRef result;
+
+ result = HIShapeCreateMutableWithRect(inRect);
+ return result;
+}
+
+OSStatus
+TkMacOSXHIShapeSetWithShape(
+ HIMutableShapeRef inDestShape,
+ HIShapeRef inSrcShape)
+{
+ OSStatus result;
+
+ result = HIShapeSetWithShape(inDestShape, inSrcShape);
+ return result;
+}
+
+#if 0
+OSStatus
+TkMacOSXHIShapeSetWithRect(
+ HIMutableShapeRef inShape,
+ const CGRect *inRect)
+{
+ OSStatus result;
+ HIShapeRef rgn = HIShapeCreateWithRect(inRect);
+
+ result = TkMacOSXHIShapeSetWithShape(inShape, rgn);
+ CFRelease(rgn);
+
+ return result;
+}
+#endif
+
+OSStatus
+TkMacOSHIShapeDifferenceWithRect(
+ HIMutableShapeRef inShape,
+ const CGRect *inRect)
+{
+ OSStatus result;
+ HIShapeRef rgn = HIShapeCreateWithRect(inRect);
+
+ result = HIShapeDifference(inShape, rgn, inShape);
+ CFRelease(rgn);
+
+ return result;
+}
+
+OSStatus
+TkMacOSHIShapeUnionWithRect(
+ HIMutableShapeRef inShape,
+ const CGRect *inRect)
+{
+ OSStatus result;
+
+ result = HIShapeUnionWithRect(inShape, inRect);
+ return result;
+}
+
+OSStatus
+TkMacOSHIShapeUnion(
+ HIShapeRef inShape1,
+ HIShapeRef inShape2,
+ HIMutableShapeRef outResult)
+{
+ OSStatus result;
+
+ result = HIShapeUnion(inShape1, inShape2, outResult);
+ return result;
+}
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXScale.c b/tk8.6/macosx/tkMacOSXScale.c
new file mode 100644
index 0000000..0195ffb
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXScale.c
@@ -0,0 +1,500 @@
+/*
+ * 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.
+ * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright 2008-2009, Apple Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkMacOSXPrivate.h"
+#include "tkScale.h"
+
+#ifdef MAC_OSX_TK_TODO
+/*
+#ifdef TK_MAC_DEBUG
+#define TK_MAC_DEBUG_SCALE
+#endif
+*/
+
+/*
+ * 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(ClientData clientData,
+ XEvent *eventPtr);
+static pascal void ScaleActionProc(ControlRef theControl,
+ ControlPartCode partCode);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpCreateScale --
+ *
+ * Allocate a new TkScale structure.
+ *
+ * Results:
+ * Returns a newly allocated TkScale structure.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkScale *
+TkpCreateScale(
+ Tk_Window tkwin)
+{
+ MacScale *macScalePtr = ckalloc(sizeof(MacScale));
+
+ macScalePtr->scaleHandle = NULL;
+ if (scaleActionProc == NULL) {
+ scaleActionProc = NewControlActionUPP(ScaleActionProc);
+ }
+
+ Tk_CreateEventHandler(tkwin, ButtonPressMask,
+ MacScaleEventProc, macScalePtr);
+
+ return (TkScale *) macScalePtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpDestroyScale --
+ *
+ * Free Macintosh specific resources.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * The slider control is destroyed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpDestroyScale(
+ 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) /* Widget record for scale. */
+{
+ TkScale *scalePtr = clientData;
+ Tk_Window tkwin = scalePtr->tkwin;
+ Tcl_Interp *interp = scalePtr->interp;
+ int result;
+ char string[TCL_DOUBLE_SPACE];
+ MacScale *macScalePtr = clientData;
+ Rect r;
+ WindowRef windowRef;
+ CGrafPtr destPort, savePort;
+ Boolean portChanged;
+ MacDrawable *macDraw;
+ SInt32 initialValue, minValue, maxValue;
+ UInt16 numTicks;
+ Tcl_DString buf;
+
+#ifdef TK_MAC_DEBUG_SCALE
+ TkMacOSXDbgMsg("TkpDisplayScale");
+#endif
+ scalePtr->flags &= ~REDRAW_PENDING;
+ if ((scalePtr->tkwin == NULL) || !Tk_IsMapped(scalePtr->tkwin)) {
+ goto done;
+ }
+
+ /*
+ * Invoke the scale's command if needed.
+ */
+
+ Tcl_Preserve(scalePtr);
+ if ((scalePtr->flags & INVOKE_COMMAND) && (scalePtr->command != NULL)) {
+ Tcl_Preserve(interp);
+ if (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->format,
+ scalePtr->value) < 0) {
+ string[TCL_DOUBLE_SPACE - 1] = '\0';
+ }
+ Tcl_DStringInit(&buf);
+ Tcl_DStringAppend(&buf, scalePtr->command, -1);
+ Tcl_DStringAppend(&buf, " ", -1);
+ Tcl_DStringAppend(&buf, string, -1);
+ result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0);
+ Tcl_DStringFree(&buf);
+ if (result != TCL_OK) {
+ Tcl_AddErrorInfo(interp, "\n (command executed by scale)");
+ Tcl_BackgroundException(interp, result);
+ }
+ Tcl_Release(interp);
+ }
+ scalePtr->flags &= ~INVOKE_COMMAND;
+ if (scalePtr->flags & SCALE_DELETED) {
+ Tcl_Release(scalePtr);
+ return;
+ }
+ Tcl_Release(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 = 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 = TkMacOSXDrawableWindow(Tk_WindowId(tkwin));
+ portChanged = QDSwapPort(destPort, &savePort);
+ TkMacOSXSetUpClippingRgn(Tk_WindowId(tkwin));
+
+ /*
+ * Create Macintosh control.
+ */
+
+#define MAC_OSX_SCROLL_WIDTH 10
+
+ if (scalePtr->orient == ORIENT_HORIZONTAL) {
+ int offset = (Tk_Height(tkwin) - MAC_OSX_SCROLL_WIDTH) / 2;
+
+ if (offset < 0) {
+ offset = 0;
+ }
+
+ r.left = macDraw->xOff + scalePtr->inset;
+ r.top = macDraw->yOff + offset;
+ r.right = macDraw->xOff+Tk_Width(tkwin) - scalePtr->inset;
+ r.bottom = macDraw->yOff + offset + MAC_OSX_SCROLL_WIDTH/2;
+ } else {
+ int offset = (Tk_Width(tkwin) - MAC_OSX_SCROLL_WIDTH) / 2;
+
+ if (offset < 0) {
+ offset = 0;
+ }
+
+ r.left = macDraw->xOff + offset;
+ r.top = macDraw->yOff + scalePtr->inset;
+ r.right = macDraw->xOff + offset + MAC_OSX_SCROLL_WIDTH/2;
+ r.bottom = macDraw->yOff + Tk_Height(tkwin) - scalePtr->inset;
+ }
+
+ if (macScalePtr->scaleHandle == NULL) {
+#ifdef TK_MAC_DEBUG_SCALE
+ TkMacOSXDbgMsg("Initialising scale");
+#endif
+ initialValue = scalePtr->value;
+ if (scalePtr->orient == ORIENT_HORIZONTAL) {
+ minValue = scalePtr->fromValue;
+ maxValue = scalePtr->toValue;
+ } else {
+ minValue = scalePtr->fromValue;
+ maxValue = scalePtr->toValue;
+ }
+
+ if (scalePtr->tickInterval == 0) {
+ numTicks = 0;
+ } else {
+ numTicks = (maxValue - minValue)/scalePtr->tickInterval;
+ }
+
+ CreateSliderControl(windowRef, &r, initialValue, minValue, maxValue,
+ kControlSliderPointsDownOrRight, numTicks, 1, scaleActionProc,
+ &macScalePtr->scaleHandle);
+ SetControlReference(macScalePtr->scaleHandle, (UInt32) scalePtr);
+
+ if (IsWindowActive(windowRef)) {
+ macScalePtr->flags |= ACTIVE;
+ }
+ } else {
+ SetControlBounds(macScalePtr->scaleHandle, &r);
+ SetControl32BitValue(macScalePtr->scaleHandle, scalePtr->value);
+ SetControl32BitMinimum(macScalePtr->scaleHandle, scalePtr->fromValue);
+ SetControl32BitMaximum(macScalePtr->scaleHandle, scalePtr->toValue);
+ }
+
+ /*
+ * Finally draw the control.
+ */
+
+ SetControlVisibility(macScalePtr->scaleHandle, true, true);
+ HiliteControl(macScalePtr->scaleHandle, 0);
+ Draw1Control(macScalePtr->scaleHandle);
+
+ if (portChanged) {
+ QDSwapPort(savePort, NULL);
+ }
+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(
+ TkScale *scalePtr, /* Widget record for scale. */
+ int x, int y) /* Coordinates within scalePtr's window. */
+{
+ MacScale *macScalePtr = (MacScale *) scalePtr;
+ ControlPartCode part;
+ Point where;
+ Rect bounds;
+ CGrafPtr destPort, savePort;
+ Boolean portChanged;
+
+#ifdef TK_MAC_DEBUG_SCALE
+ TkMacOSXDbgMsg("TkpScaleElement");
+#endif
+ destPort = TkMacOSXGetDrawablePort(Tk_WindowId(scalePtr->tkwin));
+ portChanged = QDSwapPort(destPort, &savePort);
+
+ /*
+ * 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);
+
+ if (portChanged) {
+ QDSwapPort(savePort, NULL);
+ }
+
+#ifdef TK_MAC_DEBUG_SCALE
+ fprintf (stderr,"ScalePart %d, pos ( %d %d )\n", part, where.h, where.v );
+#endif
+
+ 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 clientData, /* Information about window. */
+ XEvent *eventPtr) /* Information about event. */
+{
+ MacScale *macScalePtr = (MacScale *) clientData;
+ Point where;
+ Rect bounds;
+ int part;
+ CGrafPtr destPort, savePort;
+ Boolean portChanged;
+
+#ifdef TK_MAC_DEBUG_SCALE
+ fprintf(stderr,"MacScaleEventProc\n" );
+#endif
+
+ /*
+ * 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));
+ portChanged = QDSwapPort(destPort, &savePort);
+ 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;
+#ifdef TK_MAC_DEBUG_SCALE
+ TkMacOSXDbgMsg("calling TestControl");
+#endif
+ part = TestControl(macScalePtr->scaleHandle, where);
+ if (part == 0) {
+ return;
+ }
+
+ TkMacOSXTrackingLoop(1);
+ part = HandleControlClick(macScalePtr->scaleHandle, where,
+ TkMacOSXModifierState(), scaleActionProc);
+ TkMacOSXTrackingLoop(0);
+
+ /*
+ * Update the value for the widget.
+ */
+
+ macScalePtr->info.value = GetControlValue(macScalePtr->scaleHandle);
+ /* TkScaleSetValue(&macScalePtr->info, macScalePtr->info.value, 1, 0); */
+
+ /*
+ * The HandleControlClick call will "eat" the ButtonUp event. We now
+ * generate a ButtonUp event so Tk will unset implicit grabs etc.
+ */
+
+ TkGenerateButtonEventForXPointer(Tk_WindowId(macScalePtr->info.tkwin));
+
+ if (portChanged) {
+ QDSwapPort(savePort, NULL);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ScaleActionProc --
+ *
+ * Callback procedure used by the Macintosh toolbox call
+ * HandleControlClick. 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, /* Handle to scrollbat control */
+ ControlPartCode partCode) /* Part of scrollbar that was "hit" */
+{
+ int value;
+ TkScale *scalePtr = (TkScale *) GetControlReference(theControl);
+
+#ifdef TK_MAC_DEBUG_SCALE
+ TkMacOSXDbgMsg("ScaleActionProc");
+#endif
+ value = GetControlValue(theControl);
+ TkScaleSetValue(scalePtr, value, 1, 1);
+ Tcl_Preserve(scalePtr);
+ TkMacOSXRunTclEventLoop();
+ Tcl_Release(scalePtr);
+}
+#endif
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXScrlbr.c b/tk8.6/macosx/tkMacOSXScrlbr.c
new file mode 100644
index 0000000..0f92c70
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXScrlbr.c
@@ -0,0 +1,792 @@
+/*
+ * tkMacOSXScrollbar.c --
+ *
+ * This file implements the Macintosh specific portion of the scrollbar
+ * widget.
+ *
+ * Copyright (c) 1996 by Sun Microsystems, Inc.
+ * Copyright 2001-2009, Apple Inc.
+ * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright (c) 2015 Kevin Walzer/WordTech Commununications LLC.
+ * Copyright (c) 2018-2019 Marc Culler
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkInt.h"
+#include "tkScrollbar.h"
+#include "tkMacOSXPrivate.h"
+
+/*
+ * Minimum slider length, in pixels (designed to make sure that the slider is
+ * always easy to grab with the mouse).
+ */
+
+#define MIN_SLIDER_LENGTH 18
+#define MIN_GAP 4
+
+/*
+ * Borrowed from ttkMacOSXTheme.c to provide appropriate scaling.
+ */
+
+#ifdef __LP64__
+#define RangeToFactor(maximum) (((double) (INT_MAX >> 1)) / (maximum))
+#else
+#define RangeToFactor(maximum) (((double) (LONG_MAX >> 1)) / (maximum))
+#endif /* __LP64__ */
+
+/*
+ * Apple reversed the scroll direction with the release of OSX 10.7 Lion.
+ */
+
+#define SNOW_LEOPARD_STYLE (NSAppKitVersionNumber < 1138)
+
+/*
+ * Declaration of an extended scrollbar structure with Mac specific additions.
+ */
+
+typedef struct MacScrollbar {
+ TkScrollbar information; /* Generic scrollbar info. */
+ GC troughGC; /* For drawing trough. */
+ GC copyGC; /* Used for copying from pixmap onto screen. */
+ Bool buttonDown; /* Is the mouse button down? */
+ Bool mouseOver; /* Is the pointer over the scrollbar. */
+ HIThemeTrackDrawInfo info; /* Controls how the scrollbar is drawn. */
+} MacScrollbar;
+
+/* Used to initialize a MacScrollbar's info field. */
+HIThemeTrackDrawInfo defaultInfo = {
+ .version = 0,
+ .min = 0.0,
+ .max = 100.0,
+ .attributes = kThemeTrackShowThumb,
+};
+
+/*
+ * The class procedure table for the scrollbar widget. All fields except size
+ * are left initialized to NULL, which should happen automatically since the
+ * variable is declared at this scope.
+ */
+
+const Tk_ClassProcs tkpScrollbarProcs = {
+ sizeof(Tk_ClassProcs), /* size */
+ NULL, /* worldChangedProc */
+ NULL, /* createProc */
+ NULL /* modalProc */
+};
+
+/*
+ * Information on scrollbar layout, metrics, and draw info.
+ */
+
+typedef struct ScrollbarMetrics {
+ SInt32 width, minThumbHeight;
+ int minHeight, topArrowHeight, bottomArrowHeight;
+ NSControlSize controlSize;
+} ScrollbarMetrics;
+
+static ScrollbarMetrics metrics = {
+ /* kThemeScrollBarMedium */
+ 15, MIN_SLIDER_LENGTH, 26, 14, 14, kControlSizeNormal
+};
+
+/*
+ * Declarations of static functions defined later in this file:
+ */
+
+static void ScrollbarEventProc(ClientData clientData,
+ XEvent *eventPtr);
+static int ScrollbarEvent(TkScrollbar *scrollPtr,
+ XEvent *eventPtr);
+static void UpdateControlValues(TkScrollbar *scrollPtr);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpCreateScrollbar --
+ *
+ * Allocate a new TkScrollbar structure.
+ *
+ * Results:
+ * Returns a newly allocated TkScrollbar structure.
+ *
+ * Side effects:
+ * Registers an event handler for the widget.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkScrollbar *
+TkpCreateScrollbar(
+ Tk_Window tkwin)
+{
+ MacScrollbar *scrollPtr = ckalloc(sizeof(MacScrollbar));
+
+ scrollPtr->troughGC = NULL;
+ scrollPtr->copyGC = NULL;
+ scrollPtr->info = defaultInfo;
+ scrollPtr->buttonDown = false;
+
+ Tk_CreateEventHandler(tkwin,
+ ExposureMask |
+ StructureNotifyMask |
+ FocusChangeMask |
+ ButtonPressMask |
+ ButtonReleaseMask |
+ EnterWindowMask |
+ LeaveWindowMask |
+ VisibilityChangeMask,
+ ScrollbarEventProc, scrollPtr);
+
+ return (TkScrollbar *) scrollPtr;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * 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:
+ * Draws a scrollbar on the screen.
+ *
+ *--------------------------------------------------------------
+ */
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED > 1080
+
+/*
+ * This stand-alone drawing function is used on macOS 10.9 and newer because
+ * the HIToolbox does not draw the scrollbar thumb at the expected size on
+ * those systems. The thumb is drawn too large, causing a mouse click on the
+ * thumb to be interpreted as a mouse click in the trough.
+ */
+
+static void drawMacScrollbar(
+ TkScrollbar *scrollPtr,
+ MacScrollbar *msPtr,
+ CGContextRef context)
+{
+ MacDrawable *macWin = (MacDrawable *) Tk_WindowId(scrollPtr->tkwin);
+ NSView *view = TkMacOSXDrawableView(macWin);
+ CGPathRef path;
+ CGPoint inner[2], outer[2], thumbOrigin;
+ CGSize thumbSize;
+ CGRect troughBounds = msPtr->info.bounds;
+ troughBounds.origin.y = [view bounds].size.height -
+ (troughBounds.origin.y + troughBounds.size.height);
+ if (scrollPtr->vertical) {
+ thumbOrigin.x = troughBounds.origin.x + MIN_GAP;
+ thumbOrigin.y = troughBounds.origin.y + scrollPtr->sliderFirst;
+ thumbSize.width = troughBounds.size.width - 2*MIN_GAP + 1;
+ thumbSize.height = scrollPtr->sliderLast - scrollPtr->sliderFirst;
+ inner[0] = troughBounds.origin;
+ inner[1] = CGPointMake(inner[0].x,
+ inner[0].y + troughBounds.size.height);
+ outer[0] = CGPointMake(inner[0].x + troughBounds.size.width - 1,
+ inner[0].y);
+ outer[1] = CGPointMake(outer[0].x, inner[1].y);
+ } else {
+ thumbOrigin.x = troughBounds.origin.x + scrollPtr->sliderFirst;
+ thumbOrigin.y = troughBounds.origin.y + MIN_GAP;
+ thumbSize.width = scrollPtr->sliderLast - scrollPtr->sliderFirst;
+ thumbSize.height = troughBounds.size.height - 2*MIN_GAP + 1;
+ inner[0] = troughBounds.origin;
+ inner[1] = CGPointMake(inner[0].x + troughBounds.size.width,
+ inner[0].y + 1);
+ outer[0] = CGPointMake(inner[0].x,
+ inner[0].y + troughBounds.size.height);
+ outer[1] = CGPointMake(inner[1].x, outer[0].y);
+ }
+ CGContextSetShouldAntialias(context, false);
+ CGContextSetGrayFillColor(context, 250.0 / 255, 1.0);
+ CGContextFillRect(context, troughBounds);
+ CGContextSetGrayStrokeColor(context, 232.0 / 255, 1.0);
+ CGContextStrokeLineSegments(context, inner, 2);
+ CGContextSetGrayStrokeColor(context, 238.0 / 255, 1.0);
+ CGContextStrokeLineSegments(context, outer, 2);
+
+ /*
+ * Do not display the thumb unless scrolling is possible.
+ */
+
+ if (scrollPtr->firstFraction > 0.0 || scrollPtr->lastFraction < 1.0) {
+ CGRect thumbBounds = {thumbOrigin, thumbSize};
+ path = CGPathCreateWithRoundedRect(thumbBounds, 4, 4, NULL);
+ CGContextBeginPath(context);
+ CGContextAddPath(context, path);
+ if (msPtr->info.trackInfo.scrollbar.pressState != 0) {
+ CGContextSetGrayFillColor(context, 133.0 / 255, 1.0);
+ } else {
+ CGContextSetGrayFillColor(context, 200.0 / 255, 1.0);
+ }
+ CGContextSetShouldAntialias(context, true);
+ CGContextFillPath(context);
+ CFRelease(path);
+ }
+}
+#endif
+
+void
+TkpDisplayScrollbar(
+ ClientData clientData) /* Information about window. */
+{
+ register TkScrollbar *scrollPtr = clientData;
+ MacScrollbar *msPtr = (MacScrollbar *) scrollPtr;
+ register Tk_Window tkwin = scrollPtr->tkwin;
+ TkWindow *winPtr = (TkWindow *) tkwin;
+ TkMacOSXDrawingContext dc;
+
+ scrollPtr->flags &= ~REDRAW_PENDING;
+
+ if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
+ return;
+ }
+
+ MacDrawable *macWin = (MacDrawable *) winPtr->window;
+ NSView *view = TkMacOSXDrawableView(macWin);
+
+ if ((view == NULL)
+ || (macWin->flags & TK_DO_NOT_DRAW)
+ || !TkMacOSXSetupDrawingContext((Drawable) macWin, NULL, 1, &dc)) {
+ return;
+ }
+
+ /*
+ * Transform NSView coordinates to CoreGraphics coordinates.
+ */
+
+ CGFloat viewHeight = [view bounds].size.height;
+ CGAffineTransform t = {
+ .a = 1, .b = 0,
+ .c = 0, .d = -1,
+ .tx = 0, .ty = viewHeight
+ };
+
+ CGContextConcatCTM(dc.context, t);
+
+ /*
+ * Draw a 3D rectangle to provide a base for the native scrollbar.
+ */
+
+ if (scrollPtr->highlightWidth != 0) {
+ GC fgGC, bgGC;
+
+ bgGC = Tk_GCForColor(scrollPtr->highlightBgColorPtr, (Pixmap) macWin);
+ if (scrollPtr->flags & GOT_FOCUS) {
+ fgGC = Tk_GCForColor(scrollPtr->highlightColorPtr, (Pixmap) macWin);
+ } else {
+ fgGC = bgGC;
+ }
+ TkpDrawHighlightBorder(tkwin, fgGC, bgGC, scrollPtr->highlightWidth,
+ (Pixmap) macWin);
+ }
+
+ Tk_Draw3DRectangle(tkwin, (Pixmap) macWin, scrollPtr->bgBorder,
+ scrollPtr->highlightWidth, scrollPtr->highlightWidth,
+ Tk_Width(tkwin) - 2*scrollPtr->highlightWidth,
+ Tk_Height(tkwin) - 2*scrollPtr->highlightWidth,
+ scrollPtr->borderWidth, scrollPtr->relief);
+ Tk_Fill3DRectangle(tkwin, (Pixmap) macWin, scrollPtr->bgBorder,
+ scrollPtr->inset, scrollPtr->inset,
+ Tk_Width(tkwin) - 2*scrollPtr->inset,
+ Tk_Height(tkwin) - 2*scrollPtr->inset, 0, TK_RELIEF_FLAT);
+
+ /*
+ * Update values and then draw the native scrollbar over the rectangle.
+ */
+
+ UpdateControlValues(scrollPtr);
+
+ if (SNOW_LEOPARD_STYLE) {
+ HIThemeDrawTrack(&msPtr->info, 0, dc.context,
+ kHIThemeOrientationInverted);
+ } else if ([NSApp macMinorVersion] <= 8) {
+ HIThemeDrawTrack(&msPtr->info, 0, dc.context,
+ kHIThemeOrientationNormal);
+ } else {
+#if MAC_OS_X_VERSION_MAX_ALLOWED > 1080
+
+ /*
+ * Switch back to NSView coordinates and draw a modern scrollbar.
+ */
+
+ CGContextConcatCTM(dc.context, t);
+ drawMacScrollbar(scrollPtr, msPtr, dc.context);
+#endif
+ }
+ TkMacOSXRestoreDrawingContext(&dc);
+ scrollPtr->flags &= ~REDRAW_PENDING;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+extern void
+TkpComputeScrollbarGeometry(
+ register TkScrollbar *scrollPtr)
+ /* Scrollbar whose geometry may have
+ * changed. */
+{
+ /*
+ * The code below is borrowed from tkUnixScrlbr.c but has been adjusted to
+ * account for some differences between macOS and X11. The Unix scrollbar
+ * has an arrow button on each end. On macOS 10.6 (Snow Leopard) the
+ * scrollbars by default have both arrow buttons at the bottom or right.
+ * (There is a preferences setting to use the Unix layout, but we are not
+ * supporting that!) On more recent versions of macOS there are no arrow
+ * buttons at all. The case of no arrow buttons can be handled as a special
+ * case of having both buttons at the end, but where scrollPtr->arrowLength
+ * happens to be zero. To adjust for having both arrows at the same end we
+ * shift the scrollbar up by the arrowLength.
+ */
+
+ int fieldLength;
+
+ if (scrollPtr->highlightWidth < 0) {
+ scrollPtr->highlightWidth = 0;
+ }
+ scrollPtr->inset = scrollPtr->highlightWidth + scrollPtr->borderWidth;
+ if ([NSApp macMinorVersion] == 6) {
+ scrollPtr->arrowLength = scrollPtr->width;
+ } else {
+ scrollPtr->arrowLength = 0;
+ }
+ 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 it has at least a minimal size and so there
+ * is a small gap on either end which can be used to scroll by one page.
+ */
+
+ if (scrollPtr->sliderFirst < MIN_GAP) {
+ scrollPtr->sliderFirst = MIN_GAP;
+ scrollPtr->sliderLast += MIN_GAP;
+ }
+ if (scrollPtr->sliderLast > fieldLength - MIN_GAP) {
+ scrollPtr->sliderLast = fieldLength - MIN_GAP;
+ scrollPtr->sliderFirst -= MIN_GAP;
+ }
+ if (scrollPtr->sliderFirst > fieldLength - MIN_SLIDER_LENGTH) {
+ scrollPtr->sliderFirst = fieldLength - MIN_SLIDER_LENGTH;
+ }
+ if (scrollPtr->sliderLast < scrollPtr->sliderFirst + MIN_SLIDER_LENGTH) {
+ scrollPtr->sliderLast = scrollPtr->sliderFirst + MIN_SLIDER_LENGTH;
+ }
+ scrollPtr->sliderFirst += -scrollPtr->arrowLength + scrollPtr->inset;
+ scrollPtr->sliderLast += scrollPtr->inset;
+
+ /*
+ * Register the desired geometry for the window. Leave enough space for the
+ * two arrows, if there are any 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) {
+ Tk_GeometryRequest(scrollPtr->tkwin,
+ scrollPtr->width + 2*scrollPtr->inset,
+ 2*(scrollPtr->arrowLength + scrollPtr->borderWidth
+ + scrollPtr->inset) + metrics.minThumbHeight);
+ } else {
+ Tk_GeometryRequest(scrollPtr->tkwin,
+ 2*(scrollPtr->arrowLength + scrollPtr->borderWidth
+ + scrollPtr->inset) + metrics.minThumbHeight,
+ scrollPtr->width + 2*scrollPtr->inset);
+ }
+ Tk_SetInternalBorder(scrollPtr->tkwin, scrollPtr->inset);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpDestroyScrollbar --
+ *
+ * Free data structures associated with the scrollbar control.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Frees the GCs associated with the scrollbar.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpDestroyScrollbar(
+ TkScrollbar *scrollPtr)
+{
+ MacScrollbar *macScrollPtr = (MacScrollbar *) scrollPtr;
+
+ if (macScrollPtr->troughGC != None) {
+ Tk_FreeGC(scrollPtr->display, macScrollPtr->troughGC);
+ }
+ if (macScrollPtr->copyGC != None) {
+ Tk_FreeGC(scrollPtr->display, macScrollPtr->copyGC);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpConfigureScrollbar --
+ *
+ * This procedure is called after the generic code has finished processing
+ * configuration options, in order to configure platform specific options.
+ * There are no such option on the Mac, however.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Currently, none.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpConfigureScrollbar(
+ register TkScrollbar *scrollPtr)
+{
+ /* empty */
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * 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(
+ register TkScrollbar *scrollPtr,
+ /* Scrollbar widget record. */
+ int x, int y) /* Coordinates within scrollPtr's window. */
+{
+ /*
+ * The code below is borrowed from tkUnixScrlbr.c and needs no adjustment
+ * since it does not involve the arrow buttons.
+ */
+
+ int length, width, tmp;
+ register const int inset = scrollPtr->inset;
+
+ 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 < inset || x >= width - inset ||
+ y < inset || y >= length - inset) {
+ return OUTSIDE;
+ }
+
+ /*
+ * Here we assume that the scrollbar is layed out with both arrow buttons
+ * at the bottom (or right). Except on 10.6, however, the arrows do not
+ * actually exist, i.e. the arrowLength is 0. These are the same
+ * assumptions which are being made in TkpComputeScrollbarGeometry.
+ */
+
+ if (y < scrollPtr->sliderFirst + scrollPtr->arrowLength) {
+ return TOP_GAP;
+ }
+ if (y < scrollPtr->sliderLast) {
+ return SLIDER;
+ }
+ if (y < length - (2*scrollPtr->arrowLength + inset)) {
+ return BOTTOM_GAP;
+ }
+
+ /*
+ * On systems newer than 10.6 we have already returned.
+ */
+
+ if (y < length - (scrollPtr->arrowLength + inset)) {
+ return TOP_ARROW;
+ }
+ return BOTTOM_ARROW;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * UpdateControlValues --
+ *
+ * This procedure updates the Macintosh scrollbar control to display the
+ * values defined by the Tk scrollbar. This is the key interface to the
+ * Mac-native scrollbar; the Unix bindings drive scrolling in the Tk
+ * window and all the Mac scrollbar has to do is redraw itself.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The Macintosh control is updated.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+UpdateControlValues(
+ TkScrollbar *scrollPtr) /* Scrollbar data struct. */
+{
+ MacScrollbar *msPtr = (MacScrollbar *) scrollPtr;
+ Tk_Window tkwin = scrollPtr->tkwin;
+ MacDrawable *macWin = (MacDrawable *) Tk_WindowId(scrollPtr->tkwin);
+ double dViewSize;
+ HIRect contrlRect;
+ short width, height;
+
+ NSView *view = TkMacOSXDrawableView(macWin);
+ CGFloat viewHeight = [view bounds].size.height;
+ NSRect frame;
+
+ frame = NSMakeRect(macWin->xOff, macWin->yOff, Tk_Width(tkwin),
+ Tk_Height(tkwin));
+ frame = NSInsetRect(frame, scrollPtr->inset, scrollPtr->inset);
+ frame.origin.y = viewHeight - (frame.origin.y + frame.size.height);
+
+ contrlRect = NSRectToCGRect(frame);
+ msPtr->info.bounds = contrlRect;
+
+ width = contrlRect.size.width;
+ height = contrlRect.size.height - scrollPtr->arrowLength;
+
+ /*
+ * Ensure we set scrollbar control bounds only once all size adjustments
+ * have been computed.
+ */
+
+ msPtr->info.bounds = contrlRect;
+ if (scrollPtr->vertical) {
+ msPtr->info.attributes &= ~kThemeTrackHorizontal;
+ } else {
+ msPtr->info.attributes |= kThemeTrackHorizontal;
+ }
+
+ /*
+ * Given the Tk parameters for the fractions of the start and end of the
+ * thumb, the following calculation determines the location for the
+ * Macintosh thumb. The Aqua scroll control works as follows. The
+ * scrollbar's value is the position of the left (or top) side of the view
+ * area in the content area being scrolled. The maximum value of the
+ * control is therefore the dimension of the content area less the size of
+ * the view area.
+ */
+
+ double factor = RangeToFactor(100.0);
+ dViewSize = (scrollPtr->lastFraction - scrollPtr->firstFraction) * factor;
+ msPtr->info.max = factor - dViewSize;
+ msPtr->info.trackInfo.scrollbar.viewsize = dViewSize;
+ if (scrollPtr->vertical) {
+ if (SNOW_LEOPARD_STYLE) {
+ msPtr->info.value = factor * scrollPtr->firstFraction;
+ } else {
+ msPtr->info.value = msPtr->info.max -
+ factor * scrollPtr->firstFraction;
+ }
+ } else {
+ msPtr->info.value = factor * scrollPtr->firstFraction;
+ }
+
+ if ((scrollPtr->firstFraction <= 0.0 && scrollPtr->lastFraction >= 1.0)
+ || height <= metrics.minHeight) {
+ msPtr->info.enableState = kThemeTrackHideTrack;
+ } else {
+ msPtr->info.enableState = kThemeTrackActive;
+ msPtr->info.attributes =
+ kThemeTrackShowThumb | kThemeTrackThumbRgnIsNotGhost;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ScrollbarEvent --
+ *
+ * This procedure is invoked in response to <ButtonPress>,
+ * <ButtonRelease>, <EnterNotify>, and <LeaveNotify> events. The
+ * Scrollbar appearance is modified for each event.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+ScrollbarEvent(
+ TkScrollbar *scrollPtr,
+ XEvent *eventPtr)
+{
+ MacScrollbar *msPtr = (MacScrollbar *) scrollPtr;
+
+ /*
+ * The pressState does not indicate whether the moused button was pressed
+ * at some location in the Scrollbar. Rather, it indicates that the
+ * scrollbar should appear as if it were pressed in that location. The
+ * standard Mac behavior is that once the button is pressed inside the
+ * Scrollbar the appearance should not change until the button is released,
+ * even if the mouse moves outside of the scrollbar. However, if the mouse
+ * lies over the scrollbar but the button is not pressed then the
+ * appearance should be the same as if the button had been pressed on the
+ * slider, i.e. kThemeThumbPressed. See the file Appearance.r, or
+ * HIToolbox.bridgesupport on 10.14.
+ */
+
+ if (eventPtr->type == ButtonPress) {
+ msPtr->buttonDown = true;
+ UpdateControlValues(scrollPtr);
+
+ int where = TkpScrollbarPosition(scrollPtr,
+ eventPtr->xbutton.x, eventPtr->xbutton.y);
+
+ switch (where) {
+ case OUTSIDE:
+ msPtr->info.trackInfo.scrollbar.pressState = 0;
+ break;
+ case TOP_GAP:
+ msPtr->info.trackInfo.scrollbar.pressState = kThemeTopTrackPressed;
+ break;
+ case SLIDER:
+ msPtr->info.trackInfo.scrollbar.pressState = kThemeThumbPressed;
+ break;
+ case BOTTOM_GAP:
+ msPtr->info.trackInfo.scrollbar.pressState =
+ kThemeBottomTrackPressed;
+ break;
+ case TOP_ARROW:
+
+ /*
+ * This looks wrong and the docs say it is wrong but it works.
+ */
+
+ msPtr->info.trackInfo.scrollbar.pressState =
+ kThemeTopInsideArrowPressed;
+ break;
+ case BOTTOM_ARROW:
+ msPtr->info.trackInfo.scrollbar.pressState =
+ kThemeBottomOutsideArrowPressed;
+ break;
+ }
+ }
+ if (eventPtr->type == ButtonRelease) {
+ msPtr->buttonDown = false;
+ if (!msPtr->mouseOver) {
+ msPtr->info.trackInfo.scrollbar.pressState = 0;
+ }
+ }
+ if (eventPtr->type == EnterNotify) {
+ msPtr->mouseOver = true;
+ if (!msPtr->buttonDown) {
+ msPtr->info.trackInfo.scrollbar.pressState = kThemeThumbPressed;
+ }
+ }
+ if (eventPtr->type == LeaveNotify) {
+ msPtr->mouseOver = false;
+ if (!msPtr->buttonDown) {
+ msPtr->info.trackInfo.scrollbar.pressState = 0;
+ }
+ }
+ TkScrollbarEventuallyRedraw(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 = clientData;
+
+ switch (eventPtr->type) {
+ case UnmapNotify:
+ TkMacOSXSetScrollbarGrow((TkWindow *) scrollPtr->tkwin, false);
+ break;
+ case ActivateNotify:
+ case DeactivateNotify:
+ TkScrollbarEventuallyRedraw(scrollPtr);
+ break;
+ case ButtonPress:
+ case ButtonRelease:
+ case EnterNotify:
+ case LeaveNotify:
+ ScrollbarEvent(clientData, eventPtr);
+ break;
+ default:
+ TkScrollbarEventProc(clientData, eventPtr);
+ }
+}
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXSend.c b/tk8.6/macosx/tkMacOSXSend.c
new file mode 100644
index 0000000..8b65532
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXSend.c
@@ -0,0 +1,515 @@
+/*
+ * 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-2009, Apple Inc.
+ * Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkMacOSXInt.h"
+
+/*
+ * 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 = 0; /* 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.
+ */
+
+/*
+ * 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(Tcl_Interp *interp);
+
+/*
+ *--------------------------------------------------------------
+ *
+ * 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 (result != TCL_OK || interpNamePtr == NULL) {
+ break;
+ }
+ interpName = Tcl_GetString(interpNamePtr);
+ 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 = ckalloc(sizeof(RegisteredInterp));
+ riPtr->interp = interp;
+ riPtr->name = ckalloc(strlen(actualName) + 1);
+ riPtr->nextPtr = interpListPtr;
+ interpListPtr = riPtr;
+ strcpy(riPtr->name, actualName);
+
+ /*
+ * TODO: DeleteProc
+ */
+
+ Tcl_CreateObjCommand(interp, "send", Tk_SendObjCmd, riPtr, NULL);
+ 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 *const sendOptions[] = {"-async", "-displayof", "--", NULL};
+ char *stringRep, *destName;
+ /*int async = 0;*/
+ int i, index, firstArg;
+ RegisteredInterp *riPtr;
+ Tcl_Obj *listObjPtr;
+ int result = TCL_OK;
+
+ for (i = 1; i < (objc - 1); ) {
+ stringRep = Tcl_GetString(objv[i]);
+ if (stringRep[0] == '-') {
+ if (Tcl_GetIndexFromObjStruct(interp, objv[i], sendOptions,
+ sizeof(char *), "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,
+ "?-option value ...? interpName arg ?arg ...?");
+ return TCL_ERROR;
+ }
+
+ destName = Tcl_GetString(objv[i]);
+ firstArg = i + 1;
+
+ /*
+ * 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(riPtr);
+ localInterp = riPtr->interp;
+ Tcl_Preserve(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, 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", 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(riPtr);
+ Tcl_Release(localInterp);
+ } else {
+ /*
+ * TODO: This is a non-local request. Send the script to the server
+ * and poll it for a result.
+ */
+ }
+
+ 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, 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;
+}
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXServices.c b/tk8.6/macosx/tkMacOSXServices.c
new file mode 100644
index 0000000..02c0fda
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXServices.c
@@ -0,0 +1,240 @@
+/*
+ * tkMacOSXServices.c --
+ *\
+ * This file allows the integration of Tk and the Cocoa NSServices API.
+ *
+ * Copyright (c) 2010-2019 Kevin Walzer/WordTech Communications LLC.
+ * Copyright (c) 2010 Adrian Robert.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include <CoreServices/CoreServices.h>
+#include <tkInt.h>
+#include <tkMacOSXInt.h>
+
+static Tcl_Interp *ServicesInterp;
+
+/*
+ * Event proc which calls the PerformService procedure
+ */
+
+static int
+ServicesEventProc(
+ Tcl_Event *event,
+ int flags)
+{
+ Tcl_GlobalEval(ServicesInterp, "::tk::mac::PerformService");
+ return 1;
+}
+
+/*
+ * Class declarations for TkService class.
+ */
+
+@interface TkService : NSView {
+
+}
+
++ (void) initialize;
+- (void)provideService:(NSPasteboard *)pboard userData:(NSString *)data error:(NSString **)error;
+- (id)validRequestorForSendType:(NSString *)sendType returnType:(NSString *)returnType;
+- (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard types:(NSArray *)types;
+
+@end
+
+/*
+ * Class methods.
+ */
+
+@implementation TkService
+
++ (void) initialize {
+ NSArray *sendTypes = [NSArray arrayWithObjects:@"NSStringPboardType",
+ @"NSPasteboardTypeString", nil];
+ [NSApp registerServicesMenuSendTypes:sendTypes returnTypes:sendTypes];
+ return;
+}
+
+
+- (id)validRequestorForSendType:(NSString *)sendType
+ returnType:(NSString *)returnType
+{
+ if ([sendType isEqualToString:@"NSStringPboardType"] ||
+ [sendType isEqualToString:@"NSPasteboardTypeString"]) {
+ return self;
+ }
+ return [super validRequestorForSendType:sendType returnType:returnType];
+}
+
+/*
+ * Make sure the view accepts events.
+ */
+
+- (BOOL)acceptsFirstResponder
+{
+ return YES;
+}
+- (BOOL)becomeFirstResponder
+{
+ return YES;
+}
+
+/*
+ * Get selected text, copy to pasteboard.
+ */
+
+- (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard
+ types:(NSArray *)types
+{
+ NSArray *typesDeclared = nil;
+ NSString *pboardType = nil;
+
+ for (NSString *typeString in types) {
+ if ([typeString isEqualToString:@"NSStringPboardType"] ||
+ [typeString isEqualToString:@"NSPasteboardTypeString"]) {
+ typesDeclared = [NSArray arrayWithObject:typeString];
+ pboardType = typeString;
+ break;
+ }
+ }
+ if (!typesDeclared) {
+ return NO;
+ }
+ Tcl_Eval(ServicesInterp, "selection get");
+
+ char *copystring = Tcl_GetString(Tcl_GetObjResult(ServicesInterp));
+ NSString *writestring = [NSString stringWithUTF8String:copystring];
+
+ [pboard declareTypes:typesDeclared owner:nil];
+ return [pboard setString:writestring forType:pboardType];
+}
+
+/*
+ * This is the method that actually calls the Tk service; this is the method
+ * that must be defined in info.plist.
+ */
+
+- (void)provideService:(NSPasteboard *)pboard
+ userData:(NSString *)data
+ error:(NSString **)error
+{
+ NSString *pboardString = nil, *pboardType = nil;
+ NSArray *types = [pboard types];
+ Tcl_Event *event;
+
+ /*
+ * Get string from private pasteboard, write to general pasteboard to make
+ * available to Tcl service.
+ */
+
+ for (NSString *typeString in types) {
+ if ([typeString isEqualToString:@"NSStringPboardType"] ||
+ [typeString isEqualToString:@"NSPasteboardTypeString"]) {
+ pboardString = [pboard stringForType:typeString];
+ pboardType = typeString;
+ break;
+ }
+ }
+ if (pboardString) {
+ NSPasteboard *generalpasteboard = [NSPasteboard generalPasteboard];
+ [generalpasteboard declareTypes:[NSArray arrayWithObjects:pboardType, nil]
+ owner:nil];
+ [generalpasteboard setString:pboardString forType:pboardType];
+ event = ckalloc(sizeof(Tcl_Event));
+ event->proc = ServicesEventProc;
+ Tcl_QueueEvent((Tcl_Event *)event, TCL_QUEUE_TAIL);
+ }
+}
+@end
+
+/*
+ * Register a specific widget to access the Services menu.
+ */
+
+int
+TkMacOSXRegisterServiceWidgetObjCmd(
+ ClientData cd,
+ Tcl_Interp *ip,
+ int objc,
+ Tcl_Obj *const objv[])
+{
+ /*
+ * Need proper number of args.
+ */
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(ip, 1, objv, "path?");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Get the object that holds this Tk Window...
+ */
+
+ Rect bounds;
+ NSRect frame;
+ Tk_Window path =
+ Tk_NameToWindow(ip, Tcl_GetString(objv[1]), Tk_MainWindow(ip));
+
+ if (path == NULL) {
+ return TCL_ERROR;
+ }
+
+ Tk_MakeWindowExist(path);
+ Tk_MapWindow(path);
+ Drawable d = Tk_WindowId(path);
+
+ /*
+ * Get NSView from Tk window and add subview.
+ */
+
+ TkService *serviceview = [[TkService alloc] init];
+ NSView *view = TkMacOSXGetRootControl(d);
+
+ if ([serviceview superview] != view) {
+ [view addSubview:serviceview];
+ }
+ TkMacOSXWinBounds((TkWindow*)path, &bounds);
+
+ /*
+ * Hack to make sure subview is set to take up entire geometry of window.
+ */
+
+ frame = NSMakeRect(bounds.left, bounds.top, 100000, 100000);
+ frame.origin.y = 0;
+ if (!NSEqualRects(frame, [serviceview frame])) {
+ [serviceview setFrame:frame];
+ }
+ [serviceview release];
+ return TCL_OK;
+}
+
+/*
+ * Initalize the package in the Tcl interpreter, create Tcl commands.
+ */
+
+int
+TkMacOSXServices_Init(
+ Tcl_Interp *interp)
+{
+ /*
+ * Initialize instance of TclServices to provide service functionality.
+ */
+
+ TkService *service = [[TkService alloc] init];
+
+ ServicesInterp = interp;
+ [NSApp setServicesProvider:service];
+ return TCL_OK;
+}
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXSubwindows.c b/tk8.6/macosx/tkMacOSXSubwindows.c
new file mode 100644
index 0000000..b660917
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXSubwindows.c
@@ -0,0 +1,1481 @@
+/*
+ * tkMacOSXSubwindows.c --
+ *
+ * Implements subwindows for the macintosh version of Tk.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ * Copyright 2001-2009, Apple Inc.
+ * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkMacOSXPrivate.h"
+#include "tkMacOSXDebug.h"
+#include "tkMacOSXWm.h"
+
+/*
+#ifdef TK_MAC_DEBUG
+#define TK_MAC_DEBUG_CLIP_REGIONS
+#endif
+*/
+
+/*
+ * Prototypes for functions used only in this file.
+ */
+
+static void MoveResizeWindow(MacDrawable *macWin);
+static void GenerateConfigureNotify(TkWindow *winPtr,
+ int includeWin);
+static void UpdateOffsets(TkWindow *winPtr, int deltaX,
+ int deltaY);
+static void NotifyVisibility(TkWindow *winPtr, XEvent *eventPtr);
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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;
+
+ /*
+ * Remove any dangling pointers that may exist if the window we are
+ * deleting is being tracked by the grab code.
+ */
+
+ TkPointerDeadWindow(macWin->winPtr);
+ TkMacOSXSelDeadWindow(macWin->winPtr);
+ macWin->toplevel->referenceCount--;
+
+ if (!Tk_IsTopLevel(macWin->winPtr)) {
+ TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
+ if (macWin->winPtr->parentPtr != NULL) {
+ TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr->parentPtr);
+ }
+ if (macWin->visRgn) {
+ CFRelease(macWin->visRgn);
+ macWin->visRgn = NULL;
+ }
+ if (macWin->aboveVisRgn) {
+ CFRelease(macWin->aboveVisRgn);
+ macWin->aboveVisRgn = NULL;
+ }
+ if (macWin->drawRgn) {
+ CFRelease(macWin->drawRgn);
+ macWin->drawRgn = NULL;
+ }
+
+ if (macWin->toplevel->referenceCount == 0) {
+ ckfree(macWin->toplevel);
+ }
+ ckfree(macWin);
+ return;
+ }
+ if (macWin->visRgn) {
+ CFRelease(macWin->visRgn);
+ macWin->visRgn = NULL;
+ }
+ if (macWin->aboveVisRgn) {
+ CFRelease(macWin->aboveVisRgn);
+ macWin->aboveVisRgn = NULL;
+ }
+ if (macWin->drawRgn) {
+ CFRelease(macWin->drawRgn);
+ macWin->drawRgn = NULL;
+ }
+ macWin->view = nil;
+
+ /*
+ * Delay deletion of a toplevel data structure untill all children have
+ * been deleted.
+ */
+
+ if (macWin->toplevel->referenceCount == 0) {
+ ckfree(macWin->toplevel);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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;
+ TkWindow *winPtr = macWin->winPtr;
+ NSWindow *win = TkMacOSXDrawableWindow(window);
+ XEvent event;
+
+ /*
+ * 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);
+ }
+
+ display->request++;
+ winPtr->flags |= TK_MAPPED;
+ if (Tk_IsTopLevel(winPtr)) {
+ if (!Tk_IsEmbedded(winPtr)) {
+
+ /*
+ * We want to activate Tk when a toplevel is mapped but we must not
+ * supply YES here. This is because during Tk initialization the
+ * root window is mapped before applicationDidFinishLaunching
+ * returns. Forcing the app to activate too early can make the menu
+ * bar unresponsive.
+ */
+
+ TkMacOSXApplyWindowAttributes(winPtr, win);
+ [win setExcludedFromWindowsMenu:NO];
+ [NSApp activateIgnoringOtherApps:NO];
+ [[win contentView] setNeedsDisplay:YES];
+ if ([win canBecomeKeyWindow]) {
+ [win makeKeyAndOrderFront:NSApp];
+ } else {
+ [win orderFrontRegardless];
+ }
+ } else {
+ TkWindow *contWinPtr = TkpGetOtherWindow(winPtr);
+
+ /*
+ * Rebuild the container's clipping region and display
+ * the window.
+ */
+
+ TkMacOSXInvalClipRgns((Tk_Window) contWinPtr);
+ TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
+ }
+
+ TkMacOSXInvalClipRgns((Tk_Window) winPtr);
+
+ /*
+ * We only need to send the MapNotify event for toplevel windows.
+ */
+
+ event.xany.serial = LastKnownRequestProcessed(display);
+ 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 = winPtr->atts.override_redirect;
+ Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+ } else {
+
+ /*
+ * For non-toplevel windows, rebuild the parent's clipping region
+ * and redisplay the window.
+ */
+
+ TkMacOSXInvalClipRgns((Tk_Window) winPtr->parentPtr);
+ }
+
+ if ([NSApp isDrawing]) {
+ [[win contentView] setNeedsRedisplay:YES];
+ } else {
+ [[win contentView] setNeedsDisplay:YES];
+ }
+
+ /*
+ * Generate VisibilityNotify events for window and all mapped children.
+ */
+
+ event.xany.send_event = False;
+ event.xany.display = display;
+ event.xvisibility.type = VisibilityNotify;
+ event.xvisibility.state = VisibilityUnobscured;
+ NotifyVisibility(winPtr, &event);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NotifyVisibility --
+ *
+ * Recursively called helper proc for XMapWindow().
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * VisibilityNotify events are queued.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+NotifyVisibility(
+ TkWindow *winPtr,
+ XEvent *eventPtr)
+{
+ if (winPtr->atts.event_mask & VisibilityChangeMask) {
+ eventPtr->xany.serial = LastKnownRequestProcessed(winPtr->display);
+ eventPtr->xvisibility.window = winPtr->window;
+ Tk_QueueWindowEvent(eventPtr, TCL_QUEUE_TAIL);
+ }
+ for (winPtr = winPtr->childList; winPtr != NULL;
+ winPtr = winPtr->nextPtr) {
+ if (winPtr->flags & TK_MAPPED) {
+ NotifyVisibility(winPtr, eventPtr);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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;
+ TkWindow *winPtr = macWin->winPtr;
+ TkWindow *parentPtr = winPtr->parentPtr;
+ NSWindow *win = TkMacOSXDrawableWindow(window);
+ XEvent event;
+
+ display->request++;
+ if (Tk_IsTopLevel(winPtr)) {
+ if (!Tk_IsEmbedded(winPtr) &&
+ winPtr->wmInfoPtr->hints.initial_state!=IconicState) {
+ [win orderOut:nil];
+ }
+ TkMacOSXInvalClipRgns((Tk_Window) winPtr);
+
+ /*
+ * We only need to send the UnmapNotify event for toplevel windows.
+ */
+
+ event.xany.serial = LastKnownRequestProcessed(display);
+ 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 {
+ /*
+ * Rebuild the visRgn clip region for the parent so it will be allowed
+ * to draw in the space from which this subwindow was removed and then
+ * redraw the window.
+ */
+
+ if (parentPtr && parentPtr->privatePtr->visRgn) {
+ TkMacOSXInvalidateViewRegion(
+ TkMacOSXDrawableView(parentPtr->privatePtr),
+ parentPtr->privatePtr->visRgn);
+ }
+ TkMacOSXInvalClipRgns((Tk_Window) parentPtr);
+ TkMacOSXUpdateClipRgn(parentPtr);
+ }
+ winPtr->flags &= ~TK_MAPPED;
+ if ([NSApp isDrawing]) {
+ [[win contentView] setNeedsRedisplay:YES];
+ } else {
+ [[win contentView] setNeedsDisplay:YES];
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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;
+
+ display->request++;
+ if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
+ NSWindow *w = macWin->winPtr->wmInfoPtr->window;
+
+ if (w) {
+ NSRect r = [w contentRectForFrameRect:[w frame]];
+
+ r.origin.y += r.size.height - height;
+ r.size.width = width;
+ r.size.height = height;
+ [w setFrame:[w frameRectForContentRect:r] display:YES];
+ }
+ } else {
+ MoveResizeWindow(macWin);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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;
+
+ display->request++;
+ if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
+ NSWindow *w = macWin->winPtr->wmInfoPtr->window;
+
+ if (w) {
+ /*
+ * We explicitly convert everything to doubles so we don't get
+ * surprised (again) by what happens when you do arithmetic with
+ * unsigned ints.
+ */
+
+ CGFloat X = (CGFloat) x;
+ CGFloat Y = (CGFloat) y;
+ CGFloat Width = (CGFloat) width;
+ CGFloat Height = (CGFloat) height;
+ CGFloat XOff = (CGFloat) macWin->winPtr->wmInfoPtr->xInParent;
+ CGFloat YOff = (CGFloat) macWin->winPtr->wmInfoPtr->yInParent;
+ NSRect r = NSMakeRect(
+ X + XOff, tkMacOSXZeroScreenHeight - Y - YOff - Height,
+ Width, Height);
+
+ [w setFrame:[w frameRectForContentRect:r] display:YES];
+ }
+ } else {
+ MoveResizeWindow(macWin);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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;
+
+ display->request++;
+ if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
+ NSWindow *w = macWin->winPtr->wmInfoPtr->window;
+
+ if (w) {
+ [w setFrameTopLeftPoint: NSMakePoint(
+ x, tkMacOSXZeroScreenHeight - y)];
+ }
+ } else {
+ MoveResizeWindow(macWin);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MoveResizeWindow --
+ *
+ * Helper proc for XResizeWindow, XMoveResizeWindow and XMoveWindow.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+MoveResizeWindow(
+ MacDrawable *macWin)
+{
+ int deltaX = 0, deltaY = 0, parentBorderwidth = 0;
+ MacDrawable *macParent = NULL;
+ NSWindow *macWindow = TkMacOSXDrawableWindow((Drawable) macWin);
+
+ /*
+ * Find the Parent window, for an embedded window it will be its container.
+ */
+
+ if (Tk_IsEmbedded(macWin->winPtr)) {
+ TkWindow *contWinPtr = TkpGetOtherWindow(macWin->winPtr);
+
+ if (contWinPtr) {
+ macParent = contWinPtr->privatePtr;
+ } else {
+ /*
+ * Here we should handle out of process embedding. 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.
+ */
+ }
+ } else {
+ /*
+ * TODO: update all xOff & yOffs
+ */
+
+ macParent = macWin->winPtr->parentPtr->privatePtr;
+ parentBorderwidth = macWin->winPtr->parentPtr->changes.border_width;
+ }
+
+ if (macParent) {
+ deltaX = macParent->xOff + parentBorderwidth +
+ macWin->winPtr->changes.x - macWin->xOff;
+ deltaY = macParent->yOff + parentBorderwidth +
+ macWin->winPtr->changes.y - macWin->yOff;
+ }
+ if (macWindow) {
+ TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
+ if (macParent) {
+ TkMacOSXInvalClipRgns((Tk_Window) macParent->winPtr);
+ }
+ }
+ UpdateOffsets(macWin->winPtr, deltaX, deltaY);
+ if (macWindow) {
+ TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
+ }
+ GenerateConfigureNotify(macWin->winPtr, 0);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GenerateConfigureNotify --
+ *
+ * Generates ConfigureNotify events for all the child widgets of the
+ * widget passed in the winPtr parameter. If includeWin is true, also
+ * generates ConfigureNotify event for the widget itself.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * ConfigureNotify events will be posted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GenerateConfigureNotify(
+ TkWindow *winPtr,
+ int includeWin)
+{
+ TkWindow *childPtr;
+
+ for (childPtr = winPtr->childList; childPtr != NULL;
+ childPtr = childPtr->nextPtr) {
+ if (!Tk_IsMapped(childPtr) || Tk_IsTopLevel(childPtr)) {
+ continue;
+ }
+ GenerateConfigureNotify(childPtr, 1);
+ }
+ if (includeWin) {
+ TkDoConfigureNotify(winPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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
+ */
+ }
+}
+
+#if 0
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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
+ */
+ }
+}
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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 actually 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) {
+ NSView *view = TkMacOSXDrawableView(macWin);
+ Rect bounds;
+ NSRect r;
+
+ if (view) {
+ TkMacOSXInvalClipRgns((Tk_Window) winPtr->parentPtr);
+ TkMacOSXWinBounds(winPtr, &bounds);
+ r = NSMakeRect(bounds.left,
+ [view bounds].size.height - bounds.bottom,
+ bounds.right - bounds.left, bounds.bottom - bounds.top);
+ [view setNeedsDisplayInRect:r];
+ }
+ }
+
+#if 0
+ TkGenWMMoveRequestEvent(macWin->winPtr,
+ macWin->winPtr->changes.x, macWin->winPtr->changes.y);
+#endif
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXSetDrawingEnabled --
+ *
+ * This function sets the TK_DO_NOT_DRAW flag for a given window and
+ * all of its children.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The clipping regions for the window and its children are cleared.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXSetDrawingEnabled(
+ TkWindow *winPtr,
+ int flag)
+{
+ TkWindow *childPtr;
+ MacDrawable *macWin = winPtr->privatePtr;
+
+ if (macWin) {
+ if (flag) {
+ macWin->flags &= ~TK_DO_NOT_DRAW;
+ } else {
+ macWin->flags |= TK_DO_NOT_DRAW;
+ }
+ }
+
+ /*
+ * Set the flag for all children & their descendants, excluding Toplevels.
+ * (??? Do we need to exclude Toplevels?)
+ */
+
+ childPtr = winPtr->childList;
+ while (childPtr) {
+ if (!Tk_IsTopLevel(childPtr)) {
+ TkMacOSXSetDrawingEnabled(childPtr, flag);
+ }
+ childPtr = childPtr->nextPtr;
+ }
+
+ /*
+ * If the window is a container, set the flag for its embedded window.
+ */
+
+ if (Tk_IsContainer(winPtr)) {
+ childPtr = TkpGetOtherWindow(winPtr);
+
+ if (childPtr) {
+ TkMacOSXSetDrawingEnabled(childPtr, flag);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXUpdateClipRgn --
+ *
+ * This function updates the clipping 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)
+{
+ MacDrawable *macWin;
+
+ if (winPtr == NULL) {
+ return;
+ }
+ macWin = winPtr->privatePtr;
+ if (macWin && macWin->flags & TK_CLIP_INVALID) {
+ TkWindow *win2Ptr;
+
+#ifdef TK_MAC_DEBUG_CLIP_REGIONS
+ TkMacOSXDbgMsg("%s", winPtr->pathName);
+#endif
+ if (Tk_IsMapped(winPtr)) {
+ int rgnChanged = 0;
+ CGRect bounds;
+ HIMutableShapeRef rgn;
+
+ /*
+ * Start with a region defined by the window bounds.
+ */
+
+ TkMacOSXWinCGBounds(winPtr, &bounds);
+ rgn = TkMacOSXHIShapeCreateMutableWithRect(&bounds);
+
+ /*
+ * Clip away the area of any windows that may obscure this window.
+ * For a non-toplevel window, first, clip to the parents visible
+ * 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)) {
+ if (winPtr->parentPtr) {
+ TkMacOSXUpdateClipRgn(winPtr->parentPtr);
+ ChkErr(HIShapeIntersect,
+ winPtr->parentPtr->privatePtr->aboveVisRgn,
+ rgn, rgn);
+ }
+ win2Ptr = winPtr;
+ while ((win2Ptr = win2Ptr->nextPtr)) {
+ if (Tk_IsTopLevel(win2Ptr) || !Tk_IsMapped(win2Ptr)) {
+ continue;
+ }
+ TkMacOSXWinCGBounds(win2Ptr, &bounds);
+ ChkErr(TkMacOSHIShapeDifferenceWithRect, rgn, &bounds);
+ }
+ } else if (Tk_IsEmbedded(winPtr)) {
+ win2Ptr = TkpGetOtherWindow(winPtr);
+ if (win2Ptr) {
+ TkMacOSXUpdateClipRgn(win2Ptr);
+ ChkErr(HIShapeIntersect,
+ win2Ptr->privatePtr->aboveVisRgn, rgn, rgn);
+ } else if (tkMacOSXEmbedHandler != NULL) {
+ TkRegion r = TkCreateRegion();
+ HIShapeRef visRgn;
+
+ tkMacOSXEmbedHandler->getClipProc((Tk_Window) winPtr, r);
+ visRgn = TkMacOSXGetNativeRegion(r);
+ ChkErr(HIShapeIntersect, visRgn, rgn, rgn);
+ CFRelease(visRgn);
+ TkpReleaseRegion(r);
+ }
+
+ /*
+ * TODO: Here we should handle out of process embedding.
+ */
+ }
+ macWin->aboveVisRgn = HIShapeCreateCopy(rgn);
+
+ /*
+ * The final clip region is the aboveVis region (or visible region)
+ * minus all the children of this window. If the window is a
+ * container, we must also subtract the region of the embedded
+ * window.
+ */
+
+ win2Ptr = winPtr->childList;
+ while (win2Ptr) {
+ if (Tk_IsTopLevel(win2Ptr) || !Tk_IsMapped(win2Ptr)) {
+ win2Ptr = win2Ptr->nextPtr;
+ continue;
+ }
+ TkMacOSXWinCGBounds(win2Ptr, &bounds);
+ ChkErr(TkMacOSHIShapeDifferenceWithRect, rgn, &bounds);
+ rgnChanged = 1;
+ win2Ptr = win2Ptr->nextPtr;
+ }
+
+ if (Tk_IsContainer(winPtr)) {
+ win2Ptr = TkpGetOtherWindow(winPtr);
+ if (win2Ptr) {
+ if (Tk_IsMapped(win2Ptr)) {
+ TkMacOSXWinCGBounds(win2Ptr, &bounds);
+ ChkErr(TkMacOSHIShapeDifferenceWithRect, rgn, &bounds);
+ rgnChanged = 1;
+ }
+ }
+
+ /*
+ * TODO: Here we should handle out of process embedding.
+ */
+ }
+
+ if (rgnChanged) {
+ HIShapeRef diffRgn = HIShapeCreateDifference(
+ macWin->aboveVisRgn, rgn);
+
+ if (!HIShapeIsEmpty(diffRgn)) {
+ macWin->visRgn = HIShapeCreateCopy(rgn);
+ }
+ CFRelease(diffRgn);
+ }
+ CFRelease(rgn);
+ } else {
+ /*
+ * An unmapped window has empty clip regions to prevent any
+ * (erroneous) drawing into it or its children from becoming
+ * visible. [Bug 940117]
+ */
+
+ if (!Tk_IsTopLevel(winPtr)) {
+ TkMacOSXUpdateClipRgn(winPtr->parentPtr);
+ } else if (Tk_IsEmbedded(winPtr)) {
+ win2Ptr = TkpGetOtherWindow(winPtr);
+ if (win2Ptr) {
+ TkMacOSXUpdateClipRgn(win2Ptr);
+ }
+ }
+ macWin->aboveVisRgn = TkMacOSXHIShapeCreateEmpty();
+ }
+ if (!macWin->visRgn) {
+ macWin->visRgn = HIShapeCreateCopy(macWin->aboveVisRgn);
+ }
+ macWin->flags &= ~TK_CLIP_INVALID;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXVisableClipRgn --
+ *
+ * This function returns the Macintosh clipping region for the given
+ * window. The caller is responsible for disposing of the returned region
+ * via TkDestroyRegion().
+ *
+ * Results:
+ * The region.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkRegion
+TkMacOSXVisableClipRgn(
+ TkWindow *winPtr)
+{
+ if (winPtr->privatePtr->flags & TK_CLIP_INVALID) {
+ TkMacOSXUpdateClipRgn(winPtr);
+ }
+ return (TkRegion) HIShapeCreateMutableCopy(winPtr->privatePtr->visRgn);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXInvalidateViewRegion --
+ *
+ * This function invalidates the given region of a view.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Damage is created.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static OSStatus
+InvalViewRect(
+ int msg,
+ HIShapeRef rgn,
+ const CGRect *rect,
+ void *ref)
+{
+ static CGAffineTransform t;
+ NSView *view = ref;
+
+ if (!view) {
+ return paramErr;
+ }
+ switch (msg) {
+ case kHIShapeEnumerateInit:
+ t = CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0,
+ NSHeight([view bounds]));
+ break;
+ case kHIShapeEnumerateRect:
+ [view setNeedsDisplayInRect:NSRectFromCGRect(
+ CGRectApplyAffineTransform(*rect, t))];
+ break;
+ }
+ return noErr;
+}
+
+void
+TkMacOSXInvalidateViewRegion(
+ NSView *view,
+ HIShapeRef rgn)
+{
+ if (view && !HIShapeIsEmpty(rgn)) {
+ ChkErr(HIShapeEnumerate, rgn,
+ kHIShapeParseFromBottom|kHIShapeParseFromLeft,
+ InvalViewRect, view);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXInvalidateWindow --
+ *
+ * This function invalidates a window and (optionally) its children.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Damage is created.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXInvalidateWindow(
+ MacDrawable *macWin, /* Window to be invalidated. */
+ int flag) /* Should be TK_WINDOW_ONLY or
+ * TK_PARENT_WINDOW */
+{
+#ifdef TK_MAC_DEBUG_CLIP_REGIONS
+ TkMacOSXDbgMsg("%s", macWin->winPtr->pathName);
+#endif
+ if (macWin->flags & TK_CLIP_INVALID) {
+ TkMacOSXUpdateClipRgn(macWin->winPtr);
+ }
+ TkMacOSXInvalidateViewRegion(TkMacOSXDrawableView(macWin),
+ (flag == TK_WINDOW_ONLY) ? macWin->visRgn : macWin->aboveVisRgn);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXDrawableWindow --
+ *
+ * This function returns the NSWindow for a given X drawable.
+ *
+ * Results:
+ * A NSWindow, or nil for off screen pixmaps.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+NSWindow *
+TkMacOSXDrawableWindow(
+ Drawable drawable)
+{
+ MacDrawable *macWin = (MacDrawable *) drawable;
+ NSWindow *result = nil;
+
+ if (!macWin || macWin->flags & TK_IS_PIXMAP) {
+ result = nil;
+ } else if (macWin->toplevel && macWin->toplevel->winPtr &&
+ macWin->toplevel->winPtr->wmInfoPtr &&
+ macWin->toplevel->winPtr->wmInfoPtr->window) {
+ result = macWin->toplevel->winPtr->wmInfoPtr->window;
+ } else if (macWin->winPtr && macWin->winPtr->wmInfoPtr &&
+ macWin->winPtr->wmInfoPtr->window) {
+ result = macWin->winPtr->wmInfoPtr->window;
+ } else if (macWin->toplevel && (macWin->toplevel->flags & TK_EMBEDDED)) {
+ TkWindow *contWinPtr = TkpGetOtherWindow(macWin->toplevel->winPtr);
+
+ if (contWinPtr) {
+ result = TkMacOSXDrawableWindow((Drawable) contWinPtr->privatePtr);
+ }
+ }
+ return result;
+}
+
+void *
+TkMacOSXDrawable(
+ Drawable drawable)
+{
+ return TkMacOSXDrawableWindow(drawable);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXGetDrawablePort --
+ *
+ * This function returns the Graphics Port for a given X drawable.
+ *
+ * Results:
+ * NULL.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void *
+TkMacOSXGetDrawablePort(
+ Drawable drawable)
+{
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXDrawableView --
+ *
+ * This function returns the NSView for a given X drawable.
+ *
+ * Results:
+ * A NSView* or nil.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+NSView *
+TkMacOSXDrawableView(
+ MacDrawable *macWin)
+{
+ NSView *result = nil;
+
+ if (!macWin) {
+ result = nil;
+ } else if (!macWin->toplevel) {
+ result = macWin->view;
+ } else if (!(macWin->toplevel->flags & TK_EMBEDDED)) {
+ result = macWin->toplevel->view;
+ } else {
+ TkWindow *contWinPtr = TkpGetOtherWindow(macWin->toplevel->winPtr);
+
+ if (contWinPtr) {
+ result = TkMacOSXDrawableView(contWinPtr->privatePtr);
+ }
+ }
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXGetRootControl --
+ *
+ * This function returns the NSView for a given X drawable.
+ *
+ * Results:
+ * A NSView* .
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void *
+TkMacOSXGetRootControl(
+ Drawable drawable)
+{
+ /*
+ * will probably need to fix this up for embedding
+ */
+
+ return TkMacOSXDrawableView((MacDrawable *) drawable);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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 affect the size or position of
+ * windows.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The clipping regions for the window and its children are marked invalid.
+ * (Make sure they are valid before drawing.)
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXInvalClipRgns(
+ Tk_Window tkwin)
+{
+ TkWindow *winPtr = (TkWindow *) tkwin;
+ TkWindow *childPtr;
+ MacDrawable *macWin = winPtr->privatePtr;
+
+ /*
+ * If already marked we can stop because all descendants will also already
+ * be marked.
+ */
+
+#ifdef TK_MAC_DEBUG_CLIP_REGIONS
+ TkMacOSXDbgMsg("%s", winPtr->pathName);
+#endif
+
+ if (!macWin || macWin->flags & TK_CLIP_INVALID) {
+ return;
+ }
+
+ macWin->flags |= TK_CLIP_INVALID;
+ if (macWin->visRgn) {
+ CFRelease(macWin->visRgn);
+ macWin->visRgn = NULL;
+ }
+ if (macWin->aboveVisRgn) {
+ CFRelease(macWin->aboveVisRgn);
+ macWin->aboveVisRgn = NULL;
+ }
+ if (macWin->drawRgn) {
+ CFRelease(macWin->drawRgn);
+ macWin->drawRgn = NULL;
+ }
+
+ /*
+ * Invalidate clip regions for all children & their descendants, unless the
+ * child is a toplevel.
+ */
+
+ childPtr = winPtr->childList;
+ while (childPtr) {
+ if (!Tk_IsTopLevel(childPtr)) {
+ TkMacOSXInvalClipRgns((Tk_Window) childPtr);
+ }
+ childPtr = childPtr->nextPtr;
+ }
+
+ /*
+ * Also, if the window is a container, mark its embedded window.
+ */
+
+ if (Tk_IsContainer(winPtr)) {
+ childPtr = TkpGetOtherWindow(winPtr);
+
+ if (childPtr) {
+ TkMacOSXInvalClipRgns((Tk_Window) childPtr);
+ }
+
+ /*
+ * TODO: 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,
+ void *bounds)
+{
+ Rect *b = (Rect *) bounds;
+
+ b->left = winPtr->privatePtr->xOff;
+ b->top = winPtr->privatePtr->yOff;
+ b->right = b->left + winPtr->changes.width;
+ b->bottom = b->top + winPtr->changes.height;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXWinCGBounds --
+ *
+ * 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
+TkMacOSXWinCGBounds(
+ TkWindow *winPtr,
+ CGRect *bounds)
+{
+ bounds->origin.x = winPtr->privatePtr->xOff;
+ bounds->origin.y = winPtr->privatePtr->yOff;
+ bounds->size.width = winPtr->changes.width;
+ bounds->size.height = winPtr->changes.height;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UpdateOffsets --
+ *
+ * Updates the X & Y offsets of the given TkWindow from the TopLevel it is
+ * a descendant 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 haven'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);
+ }
+
+ /*
+ * TODO: 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 CGBitmapContext.
+ *
+ *----------------------------------------------------------------------
+ */
+
+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. */
+{
+ MacDrawable *macPix;
+
+ if (display != NULL) {
+ display->request++;
+ }
+ macPix = ckalloc(sizeof(MacDrawable));
+ macPix->winPtr = NULL;
+ macPix->xOff = 0;
+ macPix->yOff = 0;
+ macPix->visRgn = NULL;
+ macPix->aboveVisRgn = NULL;
+ macPix->drawRgn = NULL;
+ macPix->referenceCount = 0;
+ macPix->toplevel = NULL;
+ macPix->flags = TK_IS_PIXMAP | (depth == 1 ? TK_IS_BW_PIXMAP : 0);
+ macPix->view = nil;
+ macPix->context = NULL;
+ macPix->size = CGSizeMake(width, height);
+
+ return (Pixmap) macPix;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_FreePixmap --
+ *
+ * Release the resources associated with a pixmap.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Deletes the CGBitmapContext created by Tk_GetPixmap.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_FreePixmap(
+ Display *display, /* Display. */
+ Pixmap pixmap) /* Pixmap to destroy */
+{
+ MacDrawable *macPix = (MacDrawable *) pixmap;
+
+ display->request++;
+ if (macPix->context) {
+ char *data = CGBitmapContextGetData(macPix->context);
+
+ if (data) {
+ ckfree(data);
+ }
+ CFRelease(macPix->context);
+ }
+ ckfree(macPix);
+}
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXTest.c b/tk8.6/macosx/tkMacOSXTest.c
new file mode 100644
index 0000000..f109b7a
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXTest.c
@@ -0,0 +1,130 @@
+/*
+ * tkMacOSXTest.c --
+ *
+ * Contains commands for platform specific tests for
+ * the Macintosh platform.
+ *
+ * Copyright (c) 1996 Sun Microsystems, Inc.
+ * Copyright 2001-2009, Apple Inc.
+ * Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkMacOSXPrivate.h"
+
+/*
+ * Forward declarations of procedures defined later in this file:
+ */
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 1080
+static int DebuggerObjCmd (ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+#endif
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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.
+ */
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 1080
+ Tcl_CreateObjCommand(interp, "debugger", DebuggerObjCmd, NULL, NULL);
+#endif
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DebuggerObjCmd --
+ *
+ * This procedure simply calls the low level debugger, which was
+ * deprecated in OSX 10.8.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 1080
+static int
+DebuggerObjCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Not used. */
+ int objc, /* Not used. */
+ Tcl_Obj *const objv[]) /* Not used. */
+{
+ Debugger();
+ return TCL_OK;
+}
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkTestLogDisplay --
+ *
+ * The test image display procedure calls this to determine whether it
+ * should write a log message recording that it has being run. On OSX
+ * 10.14 and later, only calls to the display procedure which occur inside
+ * of the drawRect method should be logged, since those are the only ones
+ * which actually draw anything. On earlier systems the opposite is true.
+ * The calls from within the drawRect method are redundant, since the
+ * first time the display procedure is run it will do the drawing and that
+ * first call will usually not occur inside of drawRect.
+ *
+ * Results:
+ * On OSX 10.14 and later, returns true if and only if called from
+ * within [NSView drawRect]. On earlier systems returns false if
+ * and only if called from with [NSView drawRect].
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+MODULE_SCOPE Bool
+TkTestLogDisplay(void) {
+ if ([NSApp macMinorVersion] >= 14) {
+ return [NSApp isDrawing];
+ } else {
+ return ![NSApp isDrawing];
+ }
+}
+
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXWindowEvent.c b/tk8.6/macosx/tkMacOSXWindowEvent.c
new file mode 100644
index 0000000..b8055e8
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXWindowEvent.c
@@ -0,0 +1,1205 @@
+/*
+ * tkMacOSXWindowEvent.c --
+ *
+ * This file defines the routines for both creating and handling Window
+ * Manager class events for Tk.
+ *
+ * Copyright 2001-2009, Apple Inc.
+ * Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright (c) 2015 Kevin Walzer/WordTech Communications LLC.
+ * Copyright (c) 2015 Marc Culler.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkMacOSXPrivate.h"
+#include "tkMacOSXWm.h"
+#include "tkMacOSXEvent.h"
+#include "tkMacOSXDebug.h"
+#include "tkMacOSXConstants.h"
+
+/*
+#ifdef TK_MAC_DEBUG
+#define TK_MAC_DEBUG_EVENTS
+#define TK_MAC_DEBUG_DRAWING
+#endif
+*/
+
+/*
+ * Declaration of functions used only in this file
+ */
+
+static int GenerateUpdates(HIShapeRef updateRgn,
+ CGRect *updateBounds, TkWindow *winPtr);
+static int GenerateActivateEvents(TkWindow *winPtr,
+ int activeFlag);
+static void DoWindowActivate(ClientData clientData);
+
+#pragma mark TKApplication(TKWindowEvent)
+
+#ifdef TK_MAC_DEBUG_NOTIFICATIONS
+extern NSString *NSWindowWillOrderOnScreenNotification;
+extern NSString *NSWindowDidOrderOnScreenNotification;
+extern NSString *NSWindowDidOrderOffScreenNotification;
+#endif
+
+
+@implementation TKApplication(TKWindowEvent)
+
+- (void) windowActivation: (NSNotification *) notification
+{
+#ifdef TK_MAC_DEBUG_NOTIFICATIONS
+ TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
+#endif
+ BOOL activate = [[notification name]
+ isEqualToString:NSWindowDidBecomeKeyNotification];
+ NSWindow *w = [notification object];
+ TkWindow *winPtr = TkMacOSXGetTkWindow(w);
+
+ if (winPtr && Tk_IsMapped(winPtr)) {
+ GenerateActivateEvents(winPtr, activate);
+ }
+}
+
+- (void) windowBoundsChanged: (NSNotification *) notification
+{
+#ifdef TK_MAC_DEBUG_NOTIFICATIONS
+ TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
+#endif
+ BOOL movedOnly = [[notification name]
+ isEqualToString:NSWindowDidMoveNotification];
+ NSWindow *w = [notification object];
+ TkWindow *winPtr = TkMacOSXGetTkWindow(w);
+
+ if (winPtr) {
+ WmInfo *wmPtr = winPtr->wmInfoPtr;
+ NSRect bounds = [w frame];
+ int x, y, width = -1, height = -1, flags = 0;
+
+ x = bounds.origin.x;
+ y = tkMacOSXZeroScreenHeight - (bounds.origin.y + bounds.size.height);
+ if (winPtr->changes.x != x || winPtr->changes.y != y) {
+ flags |= TK_LOCATION_CHANGED;
+ } else {
+ x = y = -1;
+ }
+ if (!movedOnly && (winPtr->changes.width != bounds.size.width ||
+ winPtr->changes.height != bounds.size.height)) {
+ width = bounds.size.width - wmPtr->xInParent;
+ height = bounds.size.height - wmPtr->yInParent;
+ flags |= TK_SIZE_CHANGED;
+ }
+ if (Tcl_GetServiceMode() != TCL_SERVICE_NONE) {
+ /*
+ * Propagate geometry changes immediately.
+ */
+
+ flags |= TK_MACOSX_HANDLE_EVENT_IMMEDIATELY;
+ }
+
+ TkGenWMConfigureEvent((Tk_Window) winPtr, x, y, width, height, flags);
+ }
+
+}
+
+- (void) windowExpanded: (NSNotification *) notification
+{
+#ifdef TK_MAC_DEBUG_NOTIFICATIONS
+ TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
+#endif
+ NSWindow *w = [notification object];
+ TkWindow *winPtr = TkMacOSXGetTkWindow(w);
+
+ if (winPtr) {
+ winPtr->wmInfoPtr->hints.initial_state =
+ TkMacOSXIsWindowZoomed(winPtr) ? ZoomState : NormalState;
+ Tk_MapWindow((Tk_Window) winPtr);
+ if (Tcl_GetServiceMode() != TCL_SERVICE_NONE) {
+
+ /*
+ * Process all Tk events generated by Tk_MapWindow().
+ */
+
+ while (Tcl_ServiceEvent(0)) {}
+ while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {}
+
+ /*
+ * NSWindowDidDeminiaturizeNotification is received after
+ * NSWindowDidBecomeKeyNotification, so activate manually
+ */
+
+ GenerateActivateEvents(winPtr, 1);
+ } else {
+ Tcl_DoWhenIdle(DoWindowActivate, winPtr);
+ }
+ }
+}
+
+- (NSRect)windowWillUseStandardFrame:(NSWindow *)window
+ defaultFrame:(NSRect)newFrame
+{
+ /*
+ * This method needs to be implemented in order for [NSWindow isZoomed] to
+ * give the correct answer. But it suffices to always validate every
+ * request.
+ */
+
+ return newFrame;
+}
+
+- (NSSize)window:(NSWindow *)window
+ willUseFullScreenContentSize:(NSSize)proposedSize
+{
+ /*
+ * We don't need to change the proposed size, but we do need to implement
+ * this method. Otherwise the full screen window will be sized to the
+ * screen's visibleFrame, leaving black bands at the top and bottom.
+ */
+
+ return proposedSize;
+}
+
+- (void) windowEnteredFullScreen: (NSNotification *) notification
+{
+#ifdef TK_MAC_DEBUG_NOTIFICATIONS
+ TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
+#endif
+ [(TKWindow *)[notification object] tkLayoutChanged];
+}
+
+- (void) windowExitedFullScreen: (NSNotification *) notification
+{
+#ifdef TK_MAC_DEBUG_NOTIFICATIONS
+ TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
+#endif
+ [(TKWindow *)[notification object] tkLayoutChanged];
+}
+
+- (void) windowCollapsed: (NSNotification *) notification
+{
+#ifdef TK_MAC_DEBUG_NOTIFICATIONS
+ TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
+#endif
+ NSWindow *w = [notification object];
+ TkWindow *winPtr = TkMacOSXGetTkWindow(w);
+
+ if (winPtr) {
+ Tk_UnmapWindow((Tk_Window) winPtr);
+ }
+}
+
+- (BOOL) windowShouldClose: (NSWindow *) w
+{
+#ifdef TK_MAC_DEBUG_NOTIFICATIONS
+ TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, w);
+#endif
+ TkWindow *winPtr = TkMacOSXGetTkWindow(w);
+
+ if (winPtr) {
+ TkGenWMDestroyEvent((Tk_Window) winPtr);
+ }
+
+ /*
+ * If necessary, TkGenWMDestroyEvent() handles [close]ing the window, so
+ * can always return NO from -windowShouldClose: for a Tk window.
+ */
+
+ return (winPtr ? NO : YES);
+}
+
+#ifdef TK_MAC_DEBUG_NOTIFICATIONS
+
+- (void) windowDragStart: (NSNotification *) notification
+{
+ TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
+}
+
+- (void) windowLiveResize: (NSNotification *) notification
+{
+ TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
+ //BOOL start = [[notification name] isEqualToString:NSWindowWillStartLiveResizeNotification];
+}
+
+- (void) windowMapped: (NSNotification *) notification
+{
+ TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
+ NSWindow *w = [notification object];
+ TkWindow *winPtr = TkMacOSXGetTkWindow(w);
+
+ if (winPtr) {
+ //Tk_MapWindow((Tk_Window) winPtr);
+ }
+}
+
+- (void) windowBecameVisible: (NSNotification *) notification
+{
+ TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
+}
+
+- (void) windowUnmapped: (NSNotification *) notification
+{
+ TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
+ NSWindow *w = [notification object];
+ TkWindow *winPtr = TkMacOSXGetTkWindow(w);
+
+ if (winPtr) {
+ //Tk_UnmapWindow((Tk_Window) winPtr);
+ }
+}
+
+#endif /* TK_MAC_DEBUG_NOTIFICATIONS */
+
+- (void) _setupWindowNotifications
+{
+ NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
+
+#define observe(n, s) \
+ [nc addObserver:self selector:@selector(s) name:(n) object:nil]
+
+ observe(NSWindowDidBecomeKeyNotification, windowActivation:);
+ observe(NSWindowDidResignKeyNotification, windowActivation:);
+ observe(NSWindowDidMoveNotification, windowBoundsChanged:);
+ observe(NSWindowDidResizeNotification, windowBoundsChanged:);
+ observe(NSWindowDidDeminiaturizeNotification, windowExpanded:);
+ observe(NSWindowDidMiniaturizeNotification, windowCollapsed:);
+
+#if !(MAC_OS_X_VERSION_MAX_ALLOWED < 1070)
+ observe(NSWindowDidEnterFullScreenNotification, windowEnteredFullScreen:);
+ observe(NSWindowDidExitFullScreenNotification, windowExitedFullScreen:);
+#endif
+
+#ifdef TK_MAC_DEBUG_NOTIFICATIONS
+ observe(NSWindowWillMoveNotification, windowDragStart:);
+ observe(NSWindowWillStartLiveResizeNotification, windowLiveResize:);
+ observe(NSWindowDidEndLiveResizeNotification, windowLiveResize:);
+ observe(NSWindowWillOrderOnScreenNotification, windowMapped:);
+ observe(NSWindowDidOrderOnScreenNotification, windowBecameVisible:);
+ observe(NSWindowDidOrderOffScreenNotification, windowUnmapped:);
+#endif
+#undef observe
+
+}
+@end
+
+#pragma mark TKApplication(TKApplicationEvent)
+
+@implementation TKApplication(TKApplicationEvent)
+
+- (void) applicationActivate: (NSNotification *) notification
+{
+#ifdef TK_MAC_DEBUG_NOTIFICATIONS
+ TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
+#endif
+ [NSApp tkCheckPasteboard];
+
+ /*
+ * When the application is activated with Command-Tab it will create a
+ * zombie window for every Tk window which has been withdrawn. So iterate
+ * through the list of windows and order out any withdrawn window.
+ */
+
+ for (NSWindow *win in [NSApp windows]) {
+ TkWindow *winPtr = TkMacOSXGetTkWindow(win);
+ if (!winPtr || !winPtr->wmInfoPtr) {
+ continue;
+ }
+ if (winPtr->wmInfoPtr->hints.initial_state == WithdrawnState) {
+ [win orderOut:nil];
+ }
+ }
+}
+
+- (void) applicationDeactivate: (NSNotification *) notification
+{
+#ifdef TK_MAC_DEBUG_NOTIFICATIONS
+ TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
+#endif
+}
+
+- (BOOL)applicationShouldHandleReopen:(NSApplication *)sender
+ hasVisibleWindows:(BOOL)flag
+{
+ /*
+ * Allowing the default response means that withdrawn windows will get
+ * displayed on the screen with unresponsive title buttons. We don't
+ * really want that. Besides, we can write our own code to handle this
+ * with ::tk::mac::ReopenApplication. So we just say NO.
+ */
+
+ return NO;
+}
+
+
+- (void) applicationShowHide: (NSNotification *) notification
+{
+#ifdef TK_MAC_DEBUG_NOTIFICATIONS
+ TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
+#endif
+ const char *cmd = ([[notification name] isEqualToString:
+ NSApplicationDidUnhideNotification] ?
+ "::tk::mac::OnShow" : "::tk::mac::OnHide");
+
+ if (_eventInterp && Tcl_FindCommand(_eventInterp, cmd, NULL, 0)) {
+ int code = Tcl_EvalEx(_eventInterp, cmd, -1, TCL_EVAL_GLOBAL);
+
+ if (code != TCL_OK) {
+ Tcl_BackgroundException(_eventInterp, code);
+ }
+ Tcl_ResetResult(_eventInterp);
+ }
+}
+
+- (void) displayChanged: (NSNotification *) notification
+{
+#ifdef TK_MAC_DEBUG_NOTIFICATIONS
+ TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
+#endif
+ TkDisplay *dispPtr = TkGetDisplayList();
+
+ if (dispPtr) {
+ TkMacOSXDisplayChanged(dispPtr->display);
+ }
+}
+@end
+
+#pragma mark -
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpAppIsDrawing --
+ *
+ * A widget display procedure can call this to determine whether it is
+ * being run inside of the drawRect method. This is needed for some tests,
+ * especially of the Text widget, which record data in a global Tcl
+ * variable and assume that display procedures will be run in a
+ * predictable sequence as Tcl idle tasks.
+ *
+ * Results:
+ * True only while running the drawRect method of a TKContentView;
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+MODULE_SCOPE Bool
+TkpAppIsDrawing(void) {
+ return [NSApp isDrawing];
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GenerateUpdates --
+ *
+ * Given a Macintosh update region and a Tk window this function geneates
+ * an X Expose event for the window if it meets the update region. The
+ * function will then recursivly have each damaged window generate Expose
+ * events for its child windows.
+ *
+ * Results:
+ * True if event(s) are generated - false otherwise.
+ *
+ * Side effects:
+ * Additional events may be place on the Tk event queue.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GenerateUpdates(
+ HIShapeRef updateRgn,
+ CGRect *updateBounds,
+ TkWindow *winPtr)
+{
+ TkWindow *childPtr;
+ XEvent event;
+ CGRect bounds, damageBounds;
+ HIShapeRef boundsRgn, damageRgn;
+
+ TkMacOSXWinCGBounds(winPtr, &bounds);
+ if (!CGRectIntersectsRect(bounds, *updateBounds)) {
+ return 0;
+ }
+ if (!HIShapeIntersectsRect(updateRgn, &bounds)) {
+ return 0;
+ }
+
+ /*
+ * Compute the bounding box of the area that the damage occured in.
+ */
+
+ boundsRgn = HIShapeCreateWithRect(&bounds);
+ damageRgn = HIShapeCreateIntersection(updateRgn, boundsRgn);
+ if (HIShapeIsEmpty(damageRgn)) {
+ CFRelease(damageRgn);
+ CFRelease(boundsRgn);
+ return 0;
+ }
+ HIShapeGetBounds(damageRgn, &damageBounds);
+
+ CFRelease(damageRgn);
+ CFRelease(boundsRgn);
+
+ event.xany.serial = LastKnownRequestProcessed(Tk_Display(winPtr));
+ event.xany.send_event = false;
+ event.xany.window = Tk_WindowId(winPtr);
+ event.xany.display = Tk_Display(winPtr);
+ event.type = Expose;
+ event.xexpose.x = damageBounds.origin.x - bounds.origin.x;
+ event.xexpose.y = damageBounds.origin.y - bounds.origin.y;
+ event.xexpose.width = damageBounds.size.width;
+ event.xexpose.height = damageBounds.size.height;
+ event.xexpose.count = 0;
+ Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+
+#ifdef TK_MAC_DEBUG_DRAWING
+ TKLog(@"Expose %p {{%d, %d}, {%d, %d}}", event.xany.window, event.xexpose.x,
+ event.xexpose.y, event.xexpose.width, event.xexpose.height);
+#endif
+
+ /*
+ * 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, updateBounds, childPtr);
+ }
+
+ /*
+ * Generate updates for any contained windows
+ */
+
+ if (Tk_IsContainer(winPtr)) {
+ childPtr = TkpGetOtherWindow(winPtr);
+ if (childPtr != NULL && Tk_IsMapped(childPtr)) {
+ GenerateUpdates(updateRgn, updateBounds, childPtr);
+ }
+
+ /*
+ * TODO: Here we should handle out of process embedding.
+ */
+ }
+
+ return 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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(
+ TkWindow *winPtr,
+ int activeFlag)
+{
+ TkGenerateActivateEvents(winPtr, activeFlag);
+ if (activeFlag || ![NSApp isActive]) {
+ TkMacOSXGenerateFocusEvent(winPtr, activeFlag);
+ }
+ return true;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DoWindowActivate --
+ *
+ * Idle handler that calls GenerateActivateEvents().
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Additional events may be place on the Tk event queue.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+DoWindowActivate(
+ ClientData clientData)
+{
+ GenerateActivateEvents(clientData, 1);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXGenerateFocusEvent --
+ *
+ * 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+MODULE_SCOPE int
+TkMacOSXGenerateFocusEvent(
+ TkWindow *winPtr, /* Root X window for event. */
+ int activeFlag)
+{
+ XEvent event;
+
+ /*
+ * Don't send focus events to windows of class help or to windows with the
+ * kWindowNoActivatesAttribute.
+ */
+
+ if (winPtr->wmInfoPtr && (winPtr->wmInfoPtr->macClass == kHelpWindowClass ||
+ winPtr->wmInfoPtr->attributes & kWindowNoActivatesAttribute)) {
+ 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 = LastKnownRequestProcessed(Tk_Display(winPtr));
+ event.xany.send_event = False;
+ event.xfocus.display = Tk_Display(winPtr);
+ event.xfocus.window = winPtr->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 = LastKnownRequestProcessed(Tk_Display(tkwin));
+ 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)) {
+ x = Tk_X(tkwin);
+ y = Tk_Y(tkwin);
+ }
+ if (!(flags & TK_SIZE_CHANGED)) {
+ width = Tk_Width(tkwin);
+ height = Tk_Height(tkwin);
+ }
+ event.xconfigure.x = x;
+ event.xconfigure.y = y;
+ event.xconfigure.width = width;
+ event.xconfigure.height = height;
+
+ if (flags & TK_MACOSX_HANDLE_EVENT_IMMEDIATELY) {
+ Tk_HandleEvent(&event);
+ } else {
+ 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;
+ }
+ if ((flags & TK_SIZE_CHANGED) && !(wmPtr->flags & WM_SYNC_PENDING) &&
+ ((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
+ * visible to the subwindow.
+ */
+
+ winPtr->changes.x = x;
+ winPtr->changes.y = y;
+ winPtr->changes.width = width;
+ winPtr->changes.height = height;
+ TkMacOSXInvalClipRgns(tkwin);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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 = LastKnownRequestProcessed(Tk_Display(tkwin));
+ 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_HandleEvent(&event);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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(protPtr);
+ interp = protPtr->interp;
+ Tcl_Preserve(interp);
+ result = Tcl_EvalEx(interp, protPtr->command, -1, TCL_EVAL_GLOBAL);
+ if (result != TCL_OK) {
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (command for \"%s\" window manager protocol)",
+ Tk_GetAtomName((Tk_Window) winPtr, protocol)));
+ Tcl_BackgroundException(interp, result);
+ }
+ Tcl_Release(interp);
+ Tcl_Release(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 ([NSRunningApplication currentApplication].active == true);
+}
+
+#pragma mark TKContentView
+
+#import <ApplicationServices/ApplicationServices.h>
+
+/*
+ * Custom content view for use in Tk NSWindows.
+ *
+ * Since Tk handles all drawing of widgets, we only use the AppKit event loop
+ * as a source of input events. To do this, we overload the NSView drawRect
+ * method with a method which generates Expose events for Tk but does no
+ * drawing. The redrawing operations are then done when Tk processes these
+ * events.
+ *
+ * Earlier versions of Mac Tk used subclasses of NSView, e.g. NSButton, as the
+ * basis for Tk widgets. These would then appear as subviews of the
+ * TKContentView. To prevent the AppKit from redrawing and corrupting the Tk
+ * Widgets it was necessary to use Apple private API calls. In order to avoid
+ * using private API calls, the NSView-based widgets have been replaced with
+ * normal Tk widgets which draw themselves as native widgets by using the
+ * HITheme API.
+ *
+ */
+
+/*
+ * Restrict event processing to Expose events.
+ */
+
+static Tk_RestrictAction
+ExposeRestrictProc(
+ ClientData arg,
+ XEvent *eventPtr)
+{
+ return (eventPtr->type==Expose && eventPtr->xany.serial==PTR2UINT(arg)
+ ? TK_PROCESS_EVENT : TK_DEFER_EVENT);
+}
+
+/*
+ * Restrict event processing to ConfigureNotify events.
+ */
+
+static Tk_RestrictAction
+ConfigureRestrictProc(
+ ClientData arg,
+ XEvent *eventPtr)
+{
+ return (eventPtr->type==ConfigureNotify ? TK_PROCESS_EVENT : TK_DEFER_EVENT);
+}
+
+/*
+ * If a window gets mapped inside the drawRect method, this will be run as an
+ * idle task, after drawRect returns, to clean up the mess.
+ */
+
+static void
+RedisplayView(
+ ClientData clientdata)
+{
+ NSView *view = (NSView *) clientdata;
+
+ /*
+ * Make sure that we are not trying to displaying a view that no longer
+ * exists.
+ */
+
+ for (NSWindow *w in [NSApp orderedWindows]) {
+ if ([w contentView] == view) {
+ [view setNeedsDisplay:YES];
+ break;
+ }
+ }
+}
+
+@implementation TKContentView(TKWindowEvent)
+
+- (void) drawRect: (NSRect) rect
+{
+ const NSRect *rectsBeingDrawn;
+ NSInteger rectsBeingDrawnCount;
+
+#ifdef TK_MAC_DEBUG_DRAWING
+ TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
+ if (winPtr) fprintf(stderr, "drawRect: drawing %s\n",
+ Tk_PathName(winPtr));
+#endif
+
+ /*
+ * We do not allow recursive calls to drawRect, but we only log them on OSX
+ * > 10.13, where they should never happen.
+ */
+
+ if ([NSApp isDrawing]) {
+ if ([NSApp macMinorVersion] > 13) {
+ TKLog(@"WARNING: a recursive call to drawRect was aborted.");
+ }
+ return;
+ }
+
+ [NSApp setIsDrawing: YES];
+
+ [self getRectsBeingDrawn:&rectsBeingDrawn count:&rectsBeingDrawnCount];
+ CGFloat height = [self bounds].size.height;
+ HIMutableShapeRef drawShape = HIShapeCreateMutable();
+
+ while (rectsBeingDrawnCount--) {
+ CGRect r = NSRectToCGRect(*rectsBeingDrawn++);
+
+#ifdef TK_MAC_DEBUG_DRAWING
+ fprintf(stderr, "drawRect: %dx%d@(%d,%d)\n", (int)r.size.width,
+ (int)r.size.height, (int)r.origin.x, (int)r.origin.y);
+#endif
+
+ r.origin.y = height - (r.origin.y + r.size.height);
+ HIShapeUnionWithRect(drawShape, &r);
+ }
+ [self generateExposeEvents:(HIShapeRef)drawShape];
+ CFRelease(drawShape);
+ [NSApp setIsDrawing: NO];
+
+ if ([self needsRedisplay]) {
+ [self setNeedsRedisplay:NO];
+ Tcl_DoWhenIdle(RedisplayView, self);
+ }
+
+#ifdef TK_MAC_DEBUG_DRAWING
+ fprintf(stderr, "drawRect: done.\n");
+#endif
+}
+
+-(void) setFrameSize: (NSSize)newsize
+{
+ [super setFrameSize: newsize];
+ NSWindow *w = [self window];
+ TkWindow *winPtr = TkMacOSXGetTkWindow(w);
+ Tk_Window tkwin = (Tk_Window) winPtr;
+
+ if (![self inLiveResize] &&
+ [w respondsToSelector: @selector (tkLayoutChanged)]) {
+ [(TKWindow *)w tkLayoutChanged];
+ }
+
+ if (winPtr) {
+ unsigned int width = (unsigned int)newsize.width;
+ unsigned int height=(unsigned int)newsize.height;
+ ClientData oldArg;
+ Tk_RestrictProc *oldProc;
+
+ /*
+ * This can be called from outside the Tk event loop. Since it calls
+ * Tcl_DoOneEvent, we need to make sure we don't clobber the
+ * AutoreleasePool set up by the caller.
+ */
+
+ [NSApp _lockAutoreleasePool];
+
+ /*
+ * Disable Tk drawing until the window has been completely configured.
+ */
+
+ TkMacOSXSetDrawingEnabled(winPtr, 0);
+
+ /*
+ * Generate and handle a ConfigureNotify event for the new size.
+ */
+
+ TkGenWMConfigureEvent(tkwin, Tk_X(tkwin), Tk_Y(tkwin), width, height,
+ TK_SIZE_CHANGED | TK_MACOSX_HANDLE_EVENT_IMMEDIATELY);
+ oldProc = Tk_RestrictEvents(ConfigureRestrictProc, NULL, &oldArg);
+ Tk_RestrictEvents(oldProc, oldArg, &oldArg);
+
+ /*
+ * Now that Tk has configured all subwindows, create the clip regions.
+ */
+
+ TkMacOSXSetDrawingEnabled(winPtr, 1);
+ TkMacOSXInvalClipRgns(tkwin);
+ TkMacOSXUpdateClipRgn(winPtr);
+
+ /*
+ * Generate and process expose events to redraw the window.
+ */
+
+ HIRect bounds = NSRectToCGRect([self bounds]);
+ HIShapeRef shape = HIShapeCreateWithRect(&bounds);
+ [self generateExposeEvents: shape];
+ [w displayIfNeeded];
+
+ /*
+ * Finally, unlock the main autoreleasePool.
+ */
+
+ [NSApp _unlockAutoreleasePool];
+ }
+}
+
+/*
+ * Core method of this class: generates expose events for redrawing. The
+ * expose events are immediately removed from the Tcl event loop and processed.
+ * This causes drawing procedures to be scheduled as idle events. Then all
+ * pending idle events are processed so the drawing will actually take place.
+ */
+
+- (void) generateExposeEvents: (HIShapeRef) shape
+{
+ unsigned long serial;
+ CGRect updateBounds;
+ int updatesNeeded;
+ TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
+ ClientData oldArg;
+ Tk_RestrictProc *oldProc;
+ if (!winPtr) {
+ return;
+ }
+
+ /*
+ * Generate Tk Expose events.
+ */
+
+ HIShapeGetBounds(shape, &updateBounds);
+
+ /*
+ * All of these events will share the same serial number.
+ */
+
+ serial = LastKnownRequestProcessed(Tk_Display(winPtr));
+ updatesNeeded = GenerateUpdates(shape, &updateBounds, winPtr);
+
+ if (updatesNeeded) {
+
+ /*
+ * First process all of the Expose events.
+ */
+
+ oldProc = Tk_RestrictEvents(ExposeRestrictProc, UINT2PTR(serial), &oldArg);
+ while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS)) {};
+ Tk_RestrictEvents(oldProc, oldArg, &oldArg);
+
+ /*
+ * Starting with OSX 10.14, which uses Core Animation to draw windows,
+ * all drawing must be done within the drawRect method. (The CGContext
+ * which draws to the backing CALayer is created by the NSView before
+ * calling drawRect, and destroyed when drawRect returns. Drawing done
+ * with the current CGContext outside of the drawRect method has no
+ * effect.)
+ *
+ * Fortunately, Tk schedules all drawing to be done while Tcl is idle.
+ * So we can do the drawing by processing all of the idle events that
+ * were created when the expose events were processed.
+ */
+ while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {}
+ }
+}
+
+/*
+ * This method is called when a user changes between light and dark mode. The
+ * implementation here generates a Tk virtual event which can be bound to a
+ * function that redraws the window in an appropriate style.
+ */
+
+- (void) viewDidChangeEffectiveAppearance
+{
+ XVirtualEvent event;
+ int x, y;
+ NSWindow *w = [self window];
+ TkWindow *winPtr = TkMacOSXGetTkWindow(w);
+ Tk_Window tkwin = (Tk_Window) winPtr;
+
+ if (!winPtr) {
+ return;
+ }
+ bzero(&event, sizeof(XVirtualEvent));
+ event.type = VirtualEvent;
+ event.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
+ 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();
+ XQueryPointer(NULL, winPtr->window, NULL, NULL,
+ &event.x_root, &event.y_root, &x, &y, &event.state);
+ Tk_TopCoordsToWindow(tkwin, x, y, &event.x, &event.y);
+ event.same_screen = true;
+ if (TkMacOSXInDarkMode(tkwin)) {
+ event.name = Tk_GetUid("DarkAqua");
+ } else {
+ event.name = Tk_GetUid("LightAqua");
+ }
+ Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
+}
+
+/*
+ * This is no-op on 10.7 and up because Apple has removed this widget, but we
+ * are leaving it here for backwards compatibility.
+ */
+
+- (void) tkToolbarButton: (id) sender
+{
+#ifdef TK_MAC_DEBUG_EVENTS
+ TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd);
+#endif
+ XVirtualEvent event;
+ int x, y;
+ TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
+ Tk_Window tkwin = (Tk_Window) winPtr;
+ if (!winPtr){
+ return;
+ }
+ bzero(&event, sizeof(XVirtualEvent));
+ event.type = VirtualEvent;
+ event.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
+ 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();
+ XQueryPointer(NULL, winPtr->window, NULL, NULL,
+ &event.x_root, &event.y_root, &x, &y, &event.state);
+ Tk_TopCoordsToWindow(tkwin, x, y, &event.x, &event.y);
+ event.same_screen = true;
+ event.name = Tk_GetUid("ToolbarButton");
+ Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
+}
+
+- (BOOL) isOpaque
+{
+ NSWindow *w = [self window];
+ return (w && (([w styleMask] & NSTexturedBackgroundWindowMask) ||
+ ![w isOpaque]) ? NO : YES);
+}
+
+- (BOOL) wantsDefaultClipping
+{
+ return NO;
+}
+
+- (BOOL) acceptsFirstResponder
+{
+ return YES;
+}
+
+- (void) keyDown: (NSEvent *) theEvent
+{
+#ifdef TK_MAC_DEBUG_EVENTS
+ TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent);
+#endif
+}
+
+@end
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXWm.c b/tk8.6/macosx/tkMacOSXWm.c
new file mode 100644
index 0000000..4040302
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXWm.c
@@ -0,0 +1,7279 @@
+/*
+ * 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-2009, Apple Inc.
+ * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright (c) 2010 Kevin Walzer/WordTech Communications LLC.
+ * Copyright (c) 2017-2019 Marc Culler.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkMacOSXPrivate.h"
+#include "tkScrollbar.h"
+#include "tkMacOSXWm.h"
+#include "tkMacOSXEvent.h"
+#include "tkMacOSXDebug.h"
+#include "tkMacOSXConstants.h"
+
+#define DEBUG_ZOMBIES 0
+
+/*
+#ifdef TK_MAC_DEBUG
+#define TK_MAC_DEBUG_WINDOWS
+#endif
+*/
+
+/*
+ * Window attributes and classes
+ */
+
+#define WM_NSMASK_SHIFT 36
+#define tkWindowDoesNotHideAttribute \
+ ((UInt64) 1 << kHIWindowBitDoesNotHide)
+#define tkCanJoinAllSpacesAttribute \
+ ((UInt64) NSWindowCollectionBehaviorCanJoinAllSpaces << 34)
+#define tkMoveToActiveSpaceAttribute \
+ ((UInt64) NSWindowCollectionBehaviorMoveToActiveSpace << 34)
+#define tkNonactivatingPanelAttribute \
+ ((UInt64) NSNonactivatingPanelMask << WM_NSMASK_SHIFT)
+#define tkHUDWindowAttribute \
+ ((UInt64) NSHUDWindowMask << WM_NSMASK_SHIFT)
+#define tkAlwaysValidAttributes (kWindowNoUpdatesAttribute \
+ | kWindowNoActivatesAttribute | kWindowHideOnSuspendAttribute \
+ | kWindowHideOnFullScreenAttribute | kWindowNoConstrainAttribute \
+ | kWindowNoShadowAttribute | kWindowLiveResizeAttribute \
+ | kWindowOpaqueForEventsAttribute | kWindowIgnoreClicksAttribute \
+ | kWindowDoesNotCycleAttribute | tkWindowDoesNotHideAttribute \
+ | tkCanJoinAllSpacesAttribute | tkMoveToActiveSpaceAttribute \
+ | tkNonactivatingPanelAttribute | tkHUDWindowAttribute)
+
+static const struct {
+ const UInt64 validAttrs, defaultAttrs, forceOnAttrs, forceOffAttrs;
+ int flags; NSUInteger styleMask;
+} macClassAttrs[] = {
+ [kAlertWindowClass] = {
+ .defaultAttrs = kWindowDoesNotCycleAttribute, },
+ [kMovableAlertWindowClass] = {
+ .defaultAttrs = kWindowDoesNotCycleAttribute, },
+ [kModalWindowClass] = {
+ .defaultAttrs = kWindowDoesNotCycleAttribute, },
+ [kMovableModalWindowClass] = {
+ .validAttrs = kWindowCloseBoxAttribute | kWindowMetalAttribute |
+ kWindowFullZoomAttribute | kWindowResizableAttribute,
+ .defaultAttrs = kWindowDoesNotCycleAttribute, },
+ [kFloatingWindowClass] = {
+ .validAttrs = kWindowCloseBoxAttribute | kWindowCollapseBoxAttribute |
+ kWindowMetalAttribute | kWindowToolbarButtonAttribute |
+ kWindowNoTitleBarAttribute | kWindowFullZoomAttribute |
+ kWindowResizableAttribute | kWindowSideTitlebarAttribute,
+ .defaultAttrs = kWindowStandardFloatingAttributes |
+ kWindowHideOnSuspendAttribute | kWindowDoesNotCycleAttribute,
+ .forceOnAttrs = kWindowResizableAttribute,
+ .forceOffAttrs = kWindowCollapseBoxAttribute,
+ .styleMask = NSUtilityWindowMask, },
+ [kDocumentWindowClass] = {
+ .validAttrs = kWindowCloseBoxAttribute | kWindowCollapseBoxAttribute |
+ kWindowMetalAttribute | kWindowToolbarButtonAttribute |
+ kWindowNoTitleBarAttribute |
+ kWindowUnifiedTitleAndToolbarAttribute |
+ kWindowInWindowMenuAttribute | kWindowFullZoomAttribute |
+ kWindowResizableAttribute,
+ .forceOnAttrs = kWindowResizableAttribute,
+ .defaultAttrs = kWindowStandardDocumentAttributes |
+ kWindowLiveResizeAttribute | kWindowInWindowMenuAttribute, },
+ [kUtilityWindowClass] = {
+ .validAttrs = kWindowCloseBoxAttribute | kWindowCollapseBoxAttribute |
+ kWindowMetalAttribute | kWindowToolbarButtonAttribute |
+ kWindowNoTitleBarAttribute | kWindowFullZoomAttribute |
+ kWindowResizableAttribute | kWindowSideTitlebarAttribute,
+ .defaultAttrs = kWindowStandardFloatingAttributes |
+ kWindowHideOnFullScreenAttribute |
+ tkWindowDoesNotHideAttribute | tkNonactivatingPanelAttribute |
+ kWindowDoesNotCycleAttribute,
+ .forceOnAttrs = kWindowResizableAttribute,
+ .forceOffAttrs = kWindowCollapseBoxAttribute,
+ .flags = WM_TOPMOST,
+ .styleMask = NSUtilityWindowMask, },
+ [kHelpWindowClass] = {
+ .defaultAttrs = kWindowHideOnSuspendAttribute,
+ .forceOnAttrs = kWindowNoTitleBarAttribute |
+ kWindowDoesNotCycleAttribute,
+ .flags = WM_TOPMOST, },
+ [kSheetWindowClass] = {
+ .validAttrs = kWindowResizableAttribute,
+ .forceOnAttrs = kWindowNoTitleBarAttribute |
+ kWindowDoesNotCycleAttribute,
+ .styleMask = NSDocModalWindowMask, },
+ [kToolbarWindowClass] = {
+ .defaultAttrs = kWindowHideOnSuspendAttribute,
+ .forceOnAttrs = kWindowNoTitleBarAttribute |
+ kWindowDoesNotCycleAttribute,
+ .styleMask = NSUtilityWindowMask, },
+ [kPlainWindowClass] = {
+ .defaultAttrs = kWindowDoesNotCycleAttribute,
+ .forceOnAttrs = kWindowNoTitleBarAttribute, },
+ [kOverlayWindowClass] = {
+ .forceOnAttrs = kWindowNoTitleBarAttribute |
+ kWindowDoesNotCycleAttribute,
+ .flags = WM_TOPMOST | WM_TRANSPARENT, },
+ [kSheetAlertWindowClass] = {
+ .forceOnAttrs = kWindowNoTitleBarAttribute |
+ kWindowDoesNotCycleAttribute,
+ .styleMask = NSDocModalWindowMask, },
+ [kAltPlainWindowClass] = {
+ .defaultAttrs = kWindowDoesNotCycleAttribute,
+ .forceOnAttrs = kWindowNoTitleBarAttribute, },
+ [kSimpleWindowClass] = {
+ .defaultAttrs = kWindowDoesNotCycleAttribute,
+ .forceOnAttrs = kWindowNoTitleBarAttribute, },
+ [kDrawerWindowClass] = {
+ .validAttrs = kWindowMetalAttribute | kWindowResizableAttribute,
+ .forceOnAttrs = kWindowNoTitleBarAttribute |
+ kWindowDoesNotCycleAttribute, },
+};
+
+#define ForceAttributes(attributes, class) \
+ ((attributes) & (~macClassAttrs[(class)].forceOffAttrs | \
+ (macClassAttrs[(class)].forceOnAttrs & ~kWindowResizableAttribute)))
+
+/*
+ * Data for [wm attributes] command:
+ */
+
+typedef enum {
+ WMATT_ALPHA, WMATT_FULLSCREEN, WMATT_MODIFIED, WMATT_NOTIFY,
+ WMATT_TITLEPATH, WMATT_TOPMOST, WMATT_TRANSPARENT,
+ WMATT_TYPE, _WMATT_LAST_ATTRIBUTE
+} WmAttribute;
+
+static const char *const WmAttributeNames[] = {
+ "-alpha", "-fullscreen", "-modified", "-notify",
+ "-titlepath", "-topmost", "-transparent",
+ "-type", 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(ClientData dummy, Tk_Window tkwin);
+
+static const Tk_GeomMgr wmMgrType = {
+ "wm", /* name */
+ TopLevelReqProc, /* requestProc */
+ NULL, /* lostSlaveProc */
+};
+
+/*
+ * The following keeps state for Aqua dock icon bounce notification.
+ */
+
+static int tkMacOSXWmAttrNotifyVal = 0;
+
+/*
+ * Hash table for Mac Window -> TkWindow mapping.
+ */
+
+static Tcl_HashTable windowTable;
+static int windowHashInit = false;
+
+/*
+ * Forward declarations for procedures defined in this file:
+ */
+
+static NSRect InitialWindowBounds(TkWindow *winPtr,
+ NSWindow *macWindow);
+static int ParseGeometry(Tcl_Interp *interp, char *string,
+ TkWindow *winPtr);
+static void TopLevelEventProc(ClientData clientData,
+ XEvent *eventPtr);
+static void WmStackorderToplevelWrapperMap(TkWindow *winPtr,
+ Display *display, Tcl_HashTable *table);
+static void UpdateGeometryInfo(ClientData clientData);
+static void UpdateSizeHints(TkWindow *winPtr);
+static void UpdateVRootGeometry(WmInfo *wmPtr);
+static int WmAspectCmd(Tk_Window tkwin, TkWindow *winPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmAttributesCmd(Tk_Window tkwin, TkWindow *winPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmClientCmd(Tk_Window tkwin, TkWindow *winPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmColormapwindowsCmd(Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmCommandCmd(Tk_Window tkwin, TkWindow *winPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmDeiconifyCmd(Tk_Window tkwin, TkWindow *winPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmFocusmodelCmd(Tk_Window tkwin, TkWindow *winPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmForgetCmd(Tk_Window tkwin, TkWindow *winPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmFrameCmd(Tk_Window tkwin, TkWindow *winPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmGeometryCmd(Tk_Window tkwin, TkWindow *winPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmGridCmd(Tk_Window tkwin, TkWindow *winPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmGroupCmd(Tk_Window tkwin, TkWindow *winPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmIconbitmapCmd(Tk_Window tkwin, TkWindow *winPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmIconifyCmd(Tk_Window tkwin, TkWindow *winPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmIconmaskCmd(Tk_Window tkwin, TkWindow *winPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmIconnameCmd(Tk_Window tkwin, TkWindow *winPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmIconphotoCmd(Tk_Window tkwin, TkWindow *winPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmIconpositionCmd(Tk_Window tkwin, TkWindow *winPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmIconwindowCmd(Tk_Window tkwin, TkWindow *winPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmManageCmd(Tk_Window tkwin, TkWindow *winPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmMaxsizeCmd(Tk_Window tkwin, TkWindow *winPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmMinsizeCmd(Tk_Window tkwin, TkWindow *winPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmOverrideredirectCmd(Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmPositionfromCmd(Tk_Window tkwin, TkWindow *winPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmProtocolCmd(Tk_Window tkwin, TkWindow *winPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmResizableCmd(Tk_Window tkwin, TkWindow *winPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmSizefromCmd(Tk_Window tkwin, TkWindow *winPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmStackorderCmd(Tk_Window tkwin, TkWindow *winPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmStateCmd(Tk_Window tkwin, TkWindow *winPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmTitleCmd(Tk_Window tkwin, TkWindow *winPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmTransientCmd(Tk_Window tkwin, TkWindow *winPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int WmWithdrawCmd(Tk_Window tkwin, TkWindow *winPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static void WmUpdateGeom(WmInfo *wmPtr, TkWindow *winPtr);
+static int WmWinStyle(Tcl_Interp *interp, TkWindow *winPtr,
+ int objc, Tcl_Obj *const objv[]);
+static int WmWinTabbingId(Tcl_Interp *interp, TkWindow *winPtr,
+ int objc, Tcl_Obj *const objv[]);
+static int WmWinAppearance(Tcl_Interp *interp, TkWindow *winPtr,
+ int objc, Tcl_Obj *const objv[]);
+static void ApplyWindowAttributeFlagChanges(TkWindow *winPtr,
+ NSWindow *macWindow, UInt64 oldAttributes,
+ int oldFlags, int create, int initial);
+static void ApplyMasterOverrideChanges(TkWindow *winPtr,
+ NSWindow *macWindow);
+static void GetMinSize(TkWindow *winPtr, int *minWidthPtr,
+ int *minHeightPtr);
+static void GetMaxSize(TkWindow *winPtr, int *maxWidthPtr,
+ int *maxHeightPtr);
+static void RemapWindows(TkWindow *winPtr,
+ MacDrawable *parentWin);
+static void RemoveTransient(TkWindow *winPtr);
+
+#pragma mark NSWindow(TKWm)
+
+@implementation NSWindow(TKWm)
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
+- (NSPoint) tkConvertPointToScreen: (NSPoint) point
+{
+ return [self convertBaseToScreen:point];
+}
+- (NSPoint) tkConvertPointFromScreen: (NSPoint)point
+{
+ return [self convertScreenToBase:point];
+}
+#else
+- (NSPoint) tkConvertPointToScreen: (NSPoint) point
+{
+ NSRect pointrect = {point, {0,0}};
+ return [self convertRectToScreen:pointrect].origin;
+}
+- (NSPoint) tkConvertPointFromScreen: (NSPoint)point
+{
+ NSRect pointrect = {point, {0,0}};
+ return [self convertRectFromScreen:pointrect].origin;
+}
+#endif
+
+@end
+
+#pragma mark -
+
+#pragma mark TKWindow(TKWm)
+
+@implementation TKWindow: NSWindow
+
+@end
+
+@implementation TKWindow(TKWm)
+
+/*
+ * This method synchronizes Tk's understanding of the bounds of a contentView
+ * with the window's. It is needed because there are situations when the
+ * window manager can change the layout of an NSWindow without having been
+ * requested to do so by Tk. Examples are when a window goes FullScreen or
+ * shows a tab bar. NSWindow methods which involve such layout changes should
+ * be overridden or protected by methods which call this.
+ */
+
+- (void) tkLayoutChanged
+{
+ TkWindow *winPtr = TkMacOSXGetTkWindow(self);
+
+ if (winPtr) {
+ NSRect frameRect;
+
+ /*
+ * This avoids including the title bar for full screen windows
+ * but does include it for normal windows.
+ */
+
+ if ([self styleMask] & NSFullScreenWindowMask) {
+ frameRect = [NSWindow frameRectForContentRect:NSZeroRect
+ styleMask:[self styleMask]];
+ } else {
+ frameRect = [self frameRectForContentRect:NSZeroRect];
+ }
+
+ WmInfo *wmPtr = winPtr->wmInfoPtr;
+
+ wmPtr->xInParent = -frameRect.origin.x;
+ wmPtr->yInParent = frameRect.origin.y + frameRect.size.height;
+ wmPtr->parentWidth = winPtr->changes.width + frameRect.size.width;
+ wmPtr->parentHeight = winPtr->changes.height + frameRect.size.height;
+ }
+}
+
+#if !(MAC_OS_X_VERSION_MAX_ALLOWED < 101200)
+- (void)toggleTabBar:(id)sender
+{
+ TkWindow *winPtr = TkMacOSXGetTkWindow(self);
+ if (!winPtr) {
+ return;
+ }
+ [super toggleTabBar:sender];
+ [self tkLayoutChanged];
+}
+#endif
+
+- (NSSize)windowWillResize:(NSWindow *)sender
+ toSize:(NSSize)frameSize
+{
+ NSRect currentFrame = [sender frame];
+ TkWindow *winPtr = TkMacOSXGetTkWindow(sender);
+ if (winPtr) {
+ if (winPtr->wmInfoPtr->flags & WM_WIDTH_NOT_RESIZABLE) {
+ frameSize.width = currentFrame.size.width;
+ }
+ if (winPtr->wmInfoPtr->flags & WM_HEIGHT_NOT_RESIZABLE) {
+ frameSize.height = currentFrame.size.height;
+ }
+ }
+ return frameSize;
+}
+
+- (BOOL) canBecomeKeyWindow
+{
+ TkWindow *winPtr = TkMacOSXGetTkWindow(self);
+ if (!winPtr) {
+ return NO;
+ }
+ return (winPtr->wmInfoPtr &&
+ (winPtr->wmInfoPtr->macClass == kHelpWindowClass ||
+ winPtr->wmInfoPtr->attributes & kWindowNoActivatesAttribute)
+ ) ? NO : YES;
+}
+
+#if DEBUG_ZOMBIES
+- (id) retain
+{
+ id result = [super retain];
+ const char *title = [[self title] UTF8String];
+ if (title == nil) {
+ title = "unnamed window";
+ }
+ if (DEBUG_ZOMBIES > 1) {
+ fprintf(stderr, "Retained <%s>. Count is: %lu\n",
+ title, [self retainCount]);
+ }
+ return result;
+}
+
+- (id) autorelease
+{
+ id result = [super autorelease];
+ const char *title = [[self title] UTF8String];
+ if (title == nil) {
+ title = "unnamed window";
+ }
+ if (DEBUG_ZOMBIES > 1) {
+ fprintf(stderr, "Autoreleased <%s>. Count is %lu\n",
+ title, [self retainCount]);
+ }
+ return result;
+}
+
+- (oneway void) release {
+ const char *title = [[self title] UTF8String];
+ if (title == nil) {
+ title = "unnamed window";
+ }
+ if (DEBUG_ZOMBIES > 1) {
+ fprintf(stderr, "Releasing <%s>. Count is %lu\n",
+ title, [self retainCount]);
+ }
+ [super release];
+}
+
+- (void) dealloc {
+ const char *title = [[self title] UTF8String];
+ if (title == nil) {
+ title = "unnamed window";
+ }
+ if (DEBUG_ZOMBIES > 0) {
+ fprintf(stderr, ">>>> Freeing <%s>. Count is %lu\n",
+ title, [self retainCount]);
+ }
+ [super dealloc];
+}
+
+#endif
+@end
+
+#pragma mark -
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetWindowSizeLimits --
+ *
+ * Sets NSWindow size limits
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+SetWindowSizeLimits(
+ TkWindow *winPtr)
+{
+ NSWindow *macWindow = TkMacOSXDrawableWindow(winPtr->window);
+ WmInfo *wmPtr = winPtr->wmInfoPtr;
+ int minWidth, minHeight, maxWidth, maxHeight, base;
+
+ if (!macWindow) {
+ return;
+ }
+ GetMinSize(winPtr, &minWidth, &minHeight);
+ GetMaxSize(winPtr, &maxWidth, &maxHeight);
+ if (wmPtr->gridWin) {
+ base = winPtr->reqWidth - (wmPtr->reqGridWidth * wmPtr->widthInc);
+ if (base < 0) {
+ base = 0;
+ }
+ minWidth = base + (minWidth * wmPtr->widthInc);
+ maxWidth = base + (maxWidth * wmPtr->widthInc);
+ base = winPtr->reqHeight - (wmPtr->reqGridHeight * wmPtr->heightInc);
+ if (base < 0) {
+ base = 0;
+ }
+ minHeight = base + (minHeight * wmPtr->heightInc);
+ maxHeight = base + (maxHeight * wmPtr->heightInc);
+ }
+ if (wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) {
+ minWidth = maxWidth = wmPtr->configWidth;
+ }
+ if (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE) {
+ minHeight = maxHeight = wmPtr->configHeight;
+ }
+ if (wmPtr->gridWin) {
+ [macWindow setResizeIncrements:NSMakeSize(wmPtr->widthInc,
+ wmPtr->heightInc)];
+ } else if (wmPtr->sizeHintsFlags & PAspect && wmPtr->minAspect.x ==
+ wmPtr->maxAspect.x && wmPtr->minAspect.y == wmPtr->maxAspect.y) {
+ NSSize aspect = NSMakeSize(wmPtr->minAspect.x, wmPtr->minAspect.y);
+ CGFloat ratio = aspect.width/aspect.height;
+
+ [macWindow setContentAspectRatio:aspect];
+ if ((CGFloat)minWidth/(CGFloat)minHeight > ratio) {
+ minHeight = lround(minWidth / ratio);
+ } else {
+ minWidth = lround(minHeight * ratio);
+ }
+ if ((CGFloat)maxWidth/(CGFloat)maxHeight > ratio) {
+ maxWidth = lround(maxHeight * ratio);
+ } else {
+ maxHeight = lround(maxWidth / ratio);
+ }
+ if ((CGFloat)wmPtr->configWidth/(CGFloat)wmPtr->configHeight > ratio) {
+ wmPtr->configWidth = lround(wmPtr->configHeight * ratio);
+ if (wmPtr->configWidth < minWidth) {
+ wmPtr->configWidth = minWidth;
+ wmPtr->configHeight = minHeight;
+ }
+ } else {
+ wmPtr->configHeight = lround(wmPtr->configWidth / ratio);
+ if (wmPtr->configHeight < minHeight) {
+ wmPtr->configWidth = minWidth;
+ wmPtr->configHeight = minHeight;
+ }
+ }
+ } else {
+ [macWindow setResizeIncrements:NSMakeSize(1.0, 1.0)];
+ }
+ [macWindow setContentMinSize:NSMakeSize(minWidth, minHeight)];
+ [macWindow setContentMaxSize:NSMakeSize(maxWidth, maxHeight)];
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FrontWindowAtPoint --
+ *
+ * Find frontmost toplevel window at a given screen location which has the
+ * specified mainPtr. If the location is in the title bar, return NULL.
+ *
+ * Results:
+ * TkWindow*.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static TkWindow*
+FrontWindowAtPoint(
+ int x,
+ int y)
+{
+ NSPoint p = NSMakePoint(x, tkMacOSXZeroScreenHeight - y);
+ NSArray *windows = [NSApp orderedWindows];
+ TkWindow *winPtr = NULL;
+
+ for (NSWindow *w in windows) {
+ winPtr = TkMacOSXGetTkWindow(w);
+ if (winPtr) {
+ WmInfo *wmPtr = winPtr->wmInfoPtr;
+ NSRect windowFrame = [w frame];
+ NSRect contentFrame = [w frame];
+
+ contentFrame.size.height = [[w contentView] frame].size.height;
+ /*
+ * For consistency with other platforms, points in the
+ * title bar are not considered to be contained in the
+ * window.
+ */
+
+ if ((wmPtr->hints.initial_state == NormalState ||
+ wmPtr->hints.initial_state == ZoomState)) {
+ if (NSMouseInRect(p, contentFrame, NO)) {
+ return winPtr;
+ } else if (NSMouseInRect(p, windowFrame, NO)) {
+ return NULL;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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 = ckalloc(sizeof(WmInfo));
+
+ wmPtr->winPtr = winPtr;
+ wmPtr->reparent = None;
+ wmPtr->titleUid = NULL;
+ wmPtr->iconName = NULL;
+ wmPtr->master = NULL;
+ 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->icon = NULL;
+ wmPtr->iconFor = NULL;
+ wmPtr->transientPtr = NULL;
+ wmPtr->sizeHintsFlags = 0;
+ wmPtr->minWidth = wmPtr->minHeight = 1;
+ wmPtr->maxWidth = 0;
+ wmPtr->maxHeight = 0;
+ 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->configX = 0;
+ wmPtr->configY = 0;
+ wmPtr->configWidth = -1;
+ wmPtr->configHeight = -1;
+ wmPtr->vRoot = None;
+ wmPtr->protPtr = NULL;
+ wmPtr->commandObj = NULL;
+ wmPtr->clientMachine = NULL;
+ wmPtr->flags = WM_NEVER_MAPPED;
+ wmPtr->macClass = kDocumentWindowClass;
+ wmPtr->attributes = macClassAttrs[kDocumentWindowClass].defaultAttrs;
+ wmPtr->scrollWinPtr = NULL;
+ wmPtr->menuPtr = NULL;
+ wmPtr->window = nil;
+ 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, 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;
+ if (wmPtr->flags & WM_NEVER_MAPPED) {
+ /*
+ * Create the underlying Mac window for this Tk window.
+ */
+
+ if (!TkMacOSXHostToplevelExists(winPtr)) {
+ TkMacOSXMakeRealWindowExist(winPtr);
+ }
+
+ wmPtr->flags &= ~WM_NEVER_MAPPED;
+
+ /*
+ * Generate configure event when we first map the window.
+ */
+
+ TkGenWMConfigureEvent((Tk_Window) winPtr, wmPtr->x, wmPtr->y, -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) {
+ Tcl_CancelIdleCall(UpdateGeometryInfo, winPtr);
+ }
+ UpdateGeometryInfo(winPtr);
+ wmPtr->flags &= ~WM_ABOUT_TO_MAP;
+
+ /*
+ * Map the window.
+ */
+
+ XMapWindow(winPtr->display, winPtr->window);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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
+ * unmapped. */
+{
+ 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(
+ TkWindow *winPtr) /* Top-level window that's being deleted. */
+{
+ WmInfo *wmPtr = winPtr->wmInfoPtr, *wmPtr2;
+
+ if (wmPtr == NULL) {
+ return;
+ }
+
+ /*
+ *If the dead window is a transient, remove it from the master's list.
+ */
+
+ RemoveTransient(winPtr);
+ Tk_ManageGeometry((Tk_Window) winPtr, NULL, NULL);
+ Tk_DeleteEventHandler((Tk_Window) winPtr, StructureNotifyMask,
+ TopLevelEventProc, winPtr);
+ 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->iconName != NULL) {
+ ckfree(wmPtr->iconName);
+ }
+ if (wmPtr->leaderName != NULL) {
+ ckfree(wmPtr->leaderName);
+ }
+ 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 = wmPtr->protPtr;
+ wmPtr->protPtr = protPtr->nextPtr;
+ Tcl_EventuallyFree(protPtr, TCL_DYNAMIC);
+ }
+ if (wmPtr->commandObj != NULL) {
+ Tcl_DecrRefCount(wmPtr->commandObj);
+ }
+ if (wmPtr->clientMachine != NULL) {
+ ckfree(wmPtr->clientMachine);
+ }
+ if (wmPtr->flags & WM_UPDATE_PENDING) {
+ Tcl_CancelIdleCall(UpdateGeometryInfo, winPtr);
+ }
+
+ /*
+ * If the dead window has a transient, remove references to it from
+ * the transient.
+ */
+
+ for (Transient *transientPtr = wmPtr->transientPtr;
+ transientPtr != NULL; transientPtr = transientPtr->nextPtr) {
+ TkWindow *winPtr2 = transientPtr->winPtr;
+ TkWindow *masterPtr = (TkWindow *) TkGetTransientMaster(winPtr2);
+
+ if (masterPtr == winPtr) {
+ wmPtr2 = winPtr2->wmInfoPtr;
+ wmPtr2->master = NULL;
+ }
+ }
+
+ while (wmPtr->transientPtr != NULL) {
+ Transient *transientPtr = wmPtr->transientPtr;
+
+ wmPtr->transientPtr = transientPtr->nextPtr;
+ ckfree(transientPtr);
+ }
+
+ /*
+ * Delete the Mac window and remove it from the windowTable. The window
+ * could be nil 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.
+ */
+
+ NSWindow *window = wmPtr->window;
+
+ if (window && !Tk_IsEmbedded(winPtr)) {
+ NSWindow *parent = [window parentWindow];
+
+ if (parent) {
+ [parent removeChildWindow:window];
+ }
+#if DEBUG_ZOMBIES > 0
+ {
+ const char *title = [[window title] UTF8String];
+ if (title == nil) {
+ title = "unnamed window";
+ }
+ fprintf(stderr, ">>>> Closing <%s>. Count is: %lu\n", title,
+ [window retainCount]);
+ }
+#endif
+ [window close];
+ TkMacOSXUnregisterMacWindow(window);
+ if (winPtr->window) {
+ ((MacDrawable *) winPtr->window)->view = nil;
+ }
+ wmPtr->window = NULL;
+ [window release];
+
+ /* Activate the highest window left on the screen. */
+ NSArray *windows = [NSApp orderedWindows];
+ for (id nswindow in windows) {
+ TkWindow *winPtr2 = TkMacOSXGetTkWindow(nswindow);
+
+ if (winPtr2 && nswindow != window) {
+ WmInfo *wmPtr = winPtr2->wmInfoPtr;
+ BOOL minimized = (wmPtr->hints.initial_state == IconicState
+ || wmPtr->hints.initial_state == WithdrawnState);
+
+ /*
+ * If no windows are left on the screen and the next window is
+ * iconified or withdrawn, we don't want to make it be the
+ * KeyWindow because that would cause it to be displayed on the
+ * screen.
+ */
+
+ if ([nswindow canBecomeKeyWindow] && !minimized) {
+ [nswindow makeKeyAndOrderFront:NSApp];
+ break;
+ }
+ }
+ }
+
+ /*
+ * Process all window events immediately to force the closed window to
+ * be deallocated. But don't do this for the root window as that is
+ * unnecessary and can lead to segfaults.
+ */
+
+ if (winPtr->parentPtr) {
+ while (Tcl_DoOneEvent(TCL_WINDOW_EVENTS|TCL_DONT_WAIT)) {}
+ }
+ [NSApp _resetAutoreleasePool];
+#if DEBUG_ZOMBIES > 0
+ fprintf(stderr, "================= Pool dump ===================\n");
+ [NSAutoreleasePool showPools];
+#endif
+ }
+ ckfree(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 *const optionStrings[] = {
+ "aspect", "attributes", "client", "colormapwindows",
+ "command", "deiconify", "focusmodel", "forget",
+ "frame", "geometry", "grid", "group",
+ "iconbitmap", "iconify", "iconmask", "iconname",
+ "iconphoto", "iconposition", "iconwindow",
+ "manage", "maxsize", "minsize", "overrideredirect",
+ "positionfrom", "protocol", "resizable", "sizefrom",
+ "stackorder", "state", "title", "transient",
+ "withdraw", NULL };
+ enum options {
+ WMOPT_ASPECT, WMOPT_ATTRIBUTES, WMOPT_CLIENT, WMOPT_COLORMAPWINDOWS,
+ WMOPT_COMMAND, WMOPT_DEICONIFY, WMOPT_FOCUSMODEL, WMOPT_FORGET,
+ WMOPT_FRAME, WMOPT_GEOMETRY, WMOPT_GRID, WMOPT_GROUP,
+ WMOPT_ICONBITMAP, WMOPT_ICONIFY, WMOPT_ICONMASK, WMOPT_ICONNAME,
+ WMOPT_ICONPHOTO, WMOPT_ICONPOSITION, WMOPT_ICONWINDOW,
+ WMOPT_MANAGE, 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_SetObjResult(interp, Tcl_NewBooleanObj(wmTracing));
+ return TCL_OK;
+ }
+ return Tcl_GetBooleanFromObj(interp, objv[2], &wmTracing);
+ }
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings,
+ sizeof(char *), "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)
+ && (index != WMOPT_MANAGE) && (index != WMOPT_FORGET)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "window \"%s\" isn't a top-level window", winPtr->pathName));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "TOPLEVEL", winPtr->pathName,
+ 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_FORGET:
+ return WmForgetCmd(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_ICONPHOTO:
+ return WmIconphotoCmd(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_MANAGE:
+ return WmManageCmd(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(
+ 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) {
+ Tcl_Obj *results[4];
+
+ results[0] = Tcl_NewIntObj(wmPtr->minAspect.x);
+ results[1] = Tcl_NewIntObj(wmPtr->minAspect.y);
+ results[2] = Tcl_NewIntObj(wmPtr->maxAspect.x);
+ results[3] = Tcl_NewIntObj(wmPtr->maxAspect.y);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(4, results));
+ }
+ 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_SetObjResult(interp, Tcl_NewStringObj(
+ "aspect number can't be <= 0", -1));
+ Tcl_SetErrorCode(interp, "TK", "WM", "ASPECT", NULL);
+ 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;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmSetAttribute --
+ *
+ * Helper routine for WmAttributesCmd. Sets the value of the specified
+ * attribute.
+ *
+ * Returns:
+ *
+ * TCL_OK if successful, TCL_ERROR otherwise. In case of an error, leaves
+ * a message in the interpreter's result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WmSetAttribute(
+ TkWindow *winPtr, /* Toplevel to work with */
+ NSWindow *macWindow,
+ Tcl_Interp *interp, /* Current interpreter */
+ WmAttribute attribute, /* Code of attribute to set */
+ Tcl_Obj *value) /* New value */
+{
+ WmInfo *wmPtr = winPtr->wmInfoPtr;
+ int boolean;
+
+ switch (attribute) {
+ case WMATT_ALPHA: {
+ double dval;
+
+ if (Tcl_GetDoubleFromObj(interp, value, &dval) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * The user should give (transparent) 0 .. 1.0 (opaque)
+ */
+
+ if (dval < 0.0) {
+ dval = 0.0;
+ } else if (dval > 1.0) {
+ dval = 1.0;
+ }
+ [macWindow setAlphaValue:dval];
+ break;
+ }
+ case WMATT_FULLSCREEN:
+ if (Tcl_GetBooleanFromObj(interp, value, &boolean) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (boolean != ((wmPtr->flags & WM_FULLSCREEN) != 0)) {
+#if !(MAC_OS_X_VERSION_MAX_ALLOWED < 1070)
+ [macWindow toggleFullScreen:macWindow];
+#else
+ TKLog(@"The fullscreen attribute is ignored on this system.");
+#endif
+ }
+ break;
+ case WMATT_MODIFIED:
+ if (Tcl_GetBooleanFromObj(interp, value, &boolean) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (boolean != [macWindow isDocumentEdited]) {
+ [macWindow setDocumentEdited:boolean];
+ }
+ break;
+ case WMATT_NOTIFY:
+ if (Tcl_GetBooleanFromObj(interp, value, &boolean) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (boolean == !tkMacOSXWmAttrNotifyVal) {
+ static NSInteger request = -1;
+
+ if (request >= 0) {
+ [NSApp cancelUserAttentionRequest:request];
+ request = -1;
+ }
+ if (boolean) {
+ request = [NSApp requestUserAttention:NSCriticalRequest];
+ }
+ tkMacOSXWmAttrNotifyVal = boolean;
+ }
+ break;
+ case WMATT_TITLEPATH: {
+ const char *path = Tcl_FSGetNativePath(value);
+ NSString *filename = @"";
+
+ if (path && *path) {
+ filename = [NSString stringWithUTF8String:path];
+ }
+ [macWindow setRepresentedFilename:filename];
+ break;
+ }
+ case WMATT_TOPMOST:
+ if (Tcl_GetBooleanFromObj(interp, value, &boolean) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (boolean != ((wmPtr->flags & WM_TOPMOST) != 0)) {
+ int oldFlags = wmPtr->flags;
+
+ if (boolean) {
+ wmPtr->flags |= WM_TOPMOST;
+ } else {
+ wmPtr->flags &= ~WM_TOPMOST;
+ }
+ ApplyWindowAttributeFlagChanges(winPtr, macWindow,
+ wmPtr->attributes, oldFlags, 1, 0);
+ }
+ break;
+ case WMATT_TRANSPARENT:
+ if (Tcl_GetBooleanFromObj(interp, value, &boolean) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (boolean != ((wmPtr->flags & WM_TRANSPARENT) != 0)) {
+ UInt64 oldAttributes = wmPtr->attributes;
+ int oldFlags = wmPtr->flags;
+
+ if (boolean) {
+ wmPtr->flags |= WM_TRANSPARENT;
+ wmPtr->attributes |= kWindowNoShadowAttribute;
+ } else {
+ wmPtr->flags &= ~WM_TRANSPARENT;
+ wmPtr->attributes &= ~kWindowNoShadowAttribute;
+ }
+ ApplyWindowAttributeFlagChanges(winPtr, macWindow, oldAttributes,
+ oldFlags, 1, 0);
+ [macWindow setBackgroundColor:boolean ? [NSColor clearColor] : nil];
+ [macWindow setOpaque:!boolean];
+ TkMacOSXInvalidateWindow((MacDrawable *) winPtr->window,
+ TK_PARENT_WINDOW);
+ }
+ break;
+ case WMATT_TYPE:
+ TKLog(@"The type attribute is ignored on macOS.");
+ break;
+ case _WMATT_LAST_ATTRIBUTE:
+ default:
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmGetAttribute --
+ *
+ * Helper routine for WmAttributesCmd. Returns the current value of the
+ * specified attribute.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj *
+WmGetAttribute(
+ TkWindow *winPtr, /* Toplevel to work with */
+ NSWindow *macWindow,
+ WmAttribute attribute) /* Code of attribute to get */
+{
+ Tcl_Obj *result = NULL;
+ WmInfo *wmPtr = winPtr->wmInfoPtr;
+
+ switch (attribute) {
+ case WMATT_ALPHA:
+ result = Tcl_NewDoubleObj([macWindow alphaValue]);
+ break;
+ case WMATT_FULLSCREEN:
+ result = Tcl_NewBooleanObj(wmPtr->flags & WM_FULLSCREEN);
+ break;
+ case WMATT_MODIFIED:
+ result = Tcl_NewBooleanObj([macWindow isDocumentEdited]);
+ break;
+ case WMATT_NOTIFY:
+ result = Tcl_NewBooleanObj(tkMacOSXWmAttrNotifyVal);
+ break;
+ case WMATT_TITLEPATH:
+ result = Tcl_NewStringObj([[macWindow representedFilename] UTF8String],
+ -1);
+ break;
+ case WMATT_TOPMOST:
+ result = Tcl_NewBooleanObj(wmPtr->flags & WM_TOPMOST);
+ break;
+ case WMATT_TRANSPARENT:
+ result = Tcl_NewBooleanObj(wmPtr->flags & WM_TRANSPARENT);
+ break;
+ case WMATT_TYPE:
+ result = Tcl_NewStringObj("unsupported", -1);
+ break;
+ case _WMATT_LAST_ATTRIBUTE:
+ default:
+ break;
+ }
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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(
+ 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. */
+{
+ int attribute = 0;
+ NSWindow *macWindow;
+
+ if (winPtr->window == None) {
+ Tk_MakeWindowExist((Tk_Window) winPtr);
+ }
+ if (!TkMacOSXHostToplevelExists(winPtr)) {
+ TkMacOSXMakeRealWindowExist(winPtr);
+ }
+ macWindow = TkMacOSXDrawableWindow(winPtr->window);
+
+ if (objc == 3) { /* wm attributes $win */
+ Tcl_Obj *result = Tcl_NewObj();
+
+ for (attribute = 0; attribute < _WMATT_LAST_ATTRIBUTE; ++attribute) {
+ Tcl_ListObjAppendElement(NULL, result,
+ Tcl_NewStringObj(WmAttributeNames[attribute], -1));
+ Tcl_ListObjAppendElement(NULL, result,
+ WmGetAttribute(winPtr, macWindow, attribute));
+ }
+ Tcl_SetObjResult(interp, result);
+ } else if (objc == 4) { /* wm attributes $win -attribute */
+ if (Tcl_GetIndexFromObjStruct(interp, objv[3], WmAttributeNames,
+ sizeof(char *), "attribute", 0, &attribute) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, WmGetAttribute(winPtr, macWindow, attribute));
+ } else if ((objc - 3) % 2 == 0) { /* wm attributes $win -att value... */
+ int i;
+
+ for (i = 3; i < objc; i += 2) {
+ if (Tcl_GetIndexFromObjStruct(interp, objv[i], WmAttributeNames,
+ sizeof(char *), "attribute", 0, &attribute) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (WmSetAttribute(winPtr, macWindow, interp, attribute, objv[i+1])
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ } else {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?-attribute ?value ...??");
+ return TCL_ERROR;
+ }
+ 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(
+ 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_SetObjResult(interp,
+ Tcl_NewStringObj(wmPtr->clientMachine, -1));
+ }
+ return TCL_OK;
+ }
+ argv3 = Tcl_GetStringFromObj(objv[3], &length);
+ if (argv3[0] == 0) {
+ if (wmPtr->clientMachine != NULL) {
+ ckfree(wmPtr->clientMachine);
+ wmPtr->clientMachine = NULL;
+ }
+ return TCL_OK;
+ }
+ if (wmPtr->clientMachine != NULL) {
+ ckfree(wmPtr->clientMachine);
+ }
+ wmPtr->clientMachine = ckalloc(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(
+ 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, *winPtr2;
+ int i, windowObjc, gotToplevel = 0;
+ Tcl_Obj **windowObjv, *resultObj;
+
+ if ((objc != 3) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?windowList?");
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ Tk_MakeWindowExist((Tk_Window) winPtr);
+ resultObj = Tcl_NewObj();
+ for (i = 0; i < wmPtr->cmapCount; i++) {
+ if ((i == (wmPtr->cmapCount-1))
+ && (wmPtr->flags & WM_ADDED_TOPLEVEL_COLORMAP)) {
+ break;
+ }
+ Tcl_ListObjAppendElement(NULL, resultObj,
+ TkNewWindowObj((Tk_Window) wmPtr->cmapList[i]));
+ }
+ Tcl_SetObjResult(interp, resultObj);
+ return TCL_OK;
+ }
+ if (Tcl_ListObjGetElements(interp, objv[3], &windowObjc, &windowObjv)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ cmapList = ckalloc((windowObjc+1) * sizeof(TkWindow*));
+ for (i = 0; i < windowObjc; i++) {
+ if (TkGetWindowFromObj(interp, tkwin, windowObjv[i],
+ (Tk_Window *) &winPtr2) != TCL_OK) {
+ ckfree(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(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(
+ 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 len;
+
+ if ((objc != 3) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?value?");
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ if (wmPtr->commandObj != NULL) {
+ Tcl_SetObjResult(interp, wmPtr->commandObj);
+ }
+ return TCL_OK;
+ }
+ if (*Tcl_GetString(objv[3]) == '\0') {
+ if (wmPtr->commandObj != NULL) {
+ Tcl_DecrRefCount(wmPtr->commandObj);
+ wmPtr->commandObj = NULL;
+ }
+ return TCL_OK;
+ }
+ if (Tcl_ListObjLength(interp, objv[3], &len) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (wmPtr->commandObj != NULL) {
+ Tcl_DecrRefCount(wmPtr->commandObj);
+ }
+ wmPtr->commandObj = Tcl_DuplicateObj(objv[3]);
+ Tcl_IncrRefCount(wmPtr->commandObj);
+ Tcl_InvalidateStringRep(wmPtr->commandObj);
+ 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(
+ 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;
+ NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window");
+ return TCL_ERROR;
+ }
+
+ if (wmPtr->iconFor != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't deiconify %s: it is an icon for %s",
+ Tcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor)));
+ Tcl_SetErrorCode(interp, "TK", "WM", "DEICONIFY", "ICON", NULL);
+ return TCL_ERROR;
+ } else if (winPtr->flags & TK_EMBEDDED) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't deiconify %s: it is an embedded window",
+ winPtr->pathName));
+ Tcl_SetErrorCode(interp, "TK", "WM", "DEICONIFY", "EMBEDDED", NULL);
+ return TCL_ERROR;
+ }
+
+ TkpWmSetState(winPtr, TkMacOSXIsWindowZoomed(winPtr) ?
+ ZoomState : NormalState);
+ [win setExcludedFromWindowsMenu:NO];
+ TkMacOSXApplyWindowAttributes(winPtr, win);
+ [win orderFront:nil];
+ if (wmPtr->icon) {
+ Tk_UnmapWindow((Tk_Window)wmPtr->icon);
+ }
+
+ /*
+ * If this window has a transient, the transient must also be deiconified if
+ * it was withdrawn by the master.
+ */
+
+ for (Transient *transientPtr = wmPtr->transientPtr;
+ transientPtr != NULL; transientPtr = transientPtr->nextPtr) {
+ TkWindow *winPtr2 = transientPtr->winPtr;
+ WmInfo *wmPtr2 = winPtr2->wmInfoPtr;
+ TkWindow *masterPtr = (TkWindow *) TkGetTransientMaster(winPtr2);
+
+ if (masterPtr == winPtr) {
+ if ((wmPtr2->hints.initial_state == WithdrawnState) &&
+ ((transientPtr->flags & WITHDRAWN_BY_MASTER) != 0)) {
+ TkpWmSetState(winPtr2, NormalState);
+ transientPtr->flags &= ~WITHDRAWN_BY_MASTER;
+ }
+ }
+ }
+
+ 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(
+ 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 *const optionStrings[] = {
+ "active", "passive", 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_SetObjResult(interp, Tcl_NewStringObj(
+ wmPtr->hints.input ? "passive" : "active", -1));
+ return TCL_OK;
+ }
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[3], optionStrings,
+ sizeof(char *), "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;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmForgetCmd --
+ *
+ * This procedure is invoked to process the "wm forget" 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
+WmForgetCmd(
+ Tk_Window tkwin, /* Main window of the application. */
+ TkWindow *winPtr, /* Toplevel or Frame to work with */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ register Tk_Window frameWin = (Tk_Window) winPtr;
+
+ if (Tk_IsTopLevel(frameWin)) {
+ MacDrawable *macWin;
+
+ Tk_MakeWindowExist(frameWin);
+ Tk_MakeWindowExist((Tk_Window)winPtr->parentPtr);
+
+ macWin = (MacDrawable *) winPtr->window;
+
+ TkFocusJoin(winPtr);
+ Tk_UnmapWindow(frameWin);
+
+ macWin->toplevel->referenceCount--;
+ macWin->toplevel = winPtr->parentPtr->privatePtr->toplevel;
+ macWin->toplevel->referenceCount++;
+ macWin->flags &= ~TK_HOST_EXISTS;
+
+ TkWmDeadWindow(winPtr);
+ RemapWindows(winPtr, (MacDrawable *) winPtr->parentPtr->window);
+
+ /*
+ * Make sure wm no longer manages this window
+ */
+ Tk_ManageGeometry(frameWin, NULL, NULL);
+
+ winPtr->flags &= ~(TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED);
+
+ /*
+ * Flags (above) must be cleared before calling TkMapTopFrame (below).
+ */
+
+ TkMapTopFrame(frameWin);
+ } else {
+ /*
+ * Already not managed by wm - ignore it.
+ */
+ }
+ 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(
+ 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;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window");
+ return TCL_ERROR;
+ }
+ window = wmPtr->reparent;
+ if (window == None) {
+ window = Tk_WindowId((Tk_Window) winPtr);
+ }
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf("0x%x", (unsigned) window));
+ 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(
+ 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;
+ NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
+ char xSign = '+', ySign = '+';
+ int width, height, x = wmPtr->x, y= wmPtr->y;
+ char *argv3;
+
+ if ((objc != 3) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?newGeometry?");
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ 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;
+ }
+ if (win) {
+ if (wmPtr->flags & WM_NEGATIVE_X) {
+ xSign = '-';
+ x = wmPtr->vRootWidth - wmPtr->x
+ - (width + (wmPtr->parentWidth - winPtr->changes.width));
+ }
+ if (wmPtr->flags & WM_NEGATIVE_Y) {
+ ySign = '-';
+ y = wmPtr->vRootHeight - wmPtr->y
+ - (height + (wmPtr->parentHeight - winPtr->changes.height));
+ }
+ }
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf("%dx%d%c%d%c%d",
+ width, height, xSign, x, ySign, y));
+ 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(
+ 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;
+ const char *errorMsg;
+
+ 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) {
+ Tcl_Obj *results[4];
+
+ results[0] = Tcl_NewIntObj(wmPtr->reqGridWidth);
+ results[1] = Tcl_NewIntObj(wmPtr->reqGridHeight);
+ results[2] = Tcl_NewIntObj(wmPtr->widthInc);
+ results[3] = Tcl_NewIntObj(wmPtr->heightInc);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(4, results));
+ }
+ 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) {
+ errorMsg = "baseWidth can't be < 0";
+ goto error;
+ } else if (reqHeight < 0) {
+ errorMsg = "baseHeight can't be < 0";
+ goto error;
+ } else if (widthInc <= 0) {
+ errorMsg = "widthInc can't be <= 0";
+ goto error;
+ } else if (heightInc <= 0) {
+ errorMsg = "heightInc can't be <= 0";
+ goto error;
+ }
+ Tk_SetGrid((Tk_Window) winPtr, reqWidth, reqHeight, widthInc,
+ heightInc);
+ }
+ wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
+ WmUpdateGeom(wmPtr, winPtr);
+ return TCL_OK;
+
+ error:
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(errorMsg, -1));
+ Tcl_SetErrorCode(interp, "TK", "WM", "GRID", NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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(
+ 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_SetObjResult(interp, Tcl_NewStringObj(wmPtr->leaderName, -1));
+ }
+ 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(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(
+ 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 *str;
+ int len;
+
+ if ((objc != 3) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?bitmap?");
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ if (wmPtr->hints.flags & IconPixmapHint) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ Tk_NameOfBitmap(winPtr->display,wmPtr->hints.icon_pixmap),
+ -1));
+ }
+ return TCL_OK;
+ }
+ str = Tcl_GetStringFromObj(objv[3], &len);
+ if (winPtr->window == None) {
+ Tk_MakeWindowExist((Tk_Window) winPtr);
+ }
+ if (!TkMacOSXHostToplevelExists(winPtr)) {
+ TkMacOSXMakeRealWindowExist(winPtr);
+ }
+ if (WmSetAttribute(winPtr, TkMacOSXDrawableWindow(winPtr->window), interp,
+ WMATT_TITLEPATH, objv[3]) == TCL_OK) {
+ if (!len) {
+ if (wmPtr->hints.icon_pixmap != None) {
+ Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap);
+ wmPtr->hints.icon_pixmap = None;
+ }
+ wmPtr->hints.flags &= ~IconPixmapHint;
+ }
+ } else {
+ pixmap = Tk_GetBitmap(interp, (Tk_Window) winPtr, Tk_GetUid(str));
+ 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(
+ 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_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't iconify \"%s\": override-redirect flag is set",
+ winPtr->pathName));
+ Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "OVERRIDE_REDIRECT",
+ NULL);
+ return TCL_ERROR;
+ } else if (wmPtr->master != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't iconify \"%s\": it is a transient", winPtr->pathName));
+ Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "TRANSIENT", NULL);
+ return TCL_ERROR;
+ } else if (wmPtr->iconFor != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't iconify %s: it is an icon for %s",
+ winPtr->pathName, Tk_PathName(wmPtr->iconFor)));
+ Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "ICON", NULL);
+ return TCL_ERROR;
+ } else if (winPtr->flags & TK_EMBEDDED) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't iconify %s: it is an embedded window",
+ winPtr->pathName));
+ Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "EMBEDDED", NULL);
+ return TCL_ERROR;
+ }
+
+ TkpWmSetState(winPtr, IconicState);
+ if (wmPtr->icon) {
+ Tk_MapWindow((Tk_Window)wmPtr->icon);
+ }
+
+ /*
+ * If this window has a transient the transient must be withdrawn when
+ * the master is iconified.
+ */
+
+ for (Transient *transientPtr = wmPtr->transientPtr;
+ transientPtr != NULL; transientPtr = transientPtr->nextPtr) {
+ TkWindow *winPtr2 = transientPtr->winPtr;
+ TkWindow *masterPtr = (TkWindow *) TkGetTransientMaster(winPtr2);
+ if (masterPtr == winPtr &&
+ winPtr2->wmInfoPtr->hints.initial_state != WithdrawnState) {
+ TkpWmSetState(winPtr2, WithdrawnState);
+ transientPtr->flags |= WITHDRAWN_BY_MASTER;
+ }
+ }
+
+ 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(
+ 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_SetObjResult(interp, Tcl_NewStringObj(
+ Tk_NameOfBitmap(winPtr->display, wmPtr->hints.icon_mask),
+ -1));
+ }
+ 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(
+ 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) {
+ if (wmPtr->iconName != NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(wmPtr->iconName, -1));
+ }
+ return TCL_OK;
+ }
+
+ if (wmPtr->iconName != NULL) {
+ ckfree(wmPtr->iconName);
+ }
+ argv3 = Tcl_GetStringFromObj(objv[3], &length);
+ wmPtr->iconName = ckalloc(length + 1);
+ strcpy(wmPtr->iconName, argv3);
+ if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
+ XSetIconName(winPtr->display, winPtr->window, wmPtr->iconName);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmIconphotoCmd --
+ *
+ * This procedure is invoked to process the "wm iconphoto" 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
+WmIconphotoCmd(
+ 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. */
+{
+ Tk_Image tk_icon;
+ int width, height, isDefault = 0;
+
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "window ?-default? image1 ?image2 ...?");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Parse args.
+ */
+
+ if (strcmp(Tcl_GetString(objv[3]), "-default") == 0) {
+ isDefault = 1;
+ if (objc == 4) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "window ?-default? image1 ?image2 ...?");
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * Get icon name. We only use the first icon name because macOS does not
+ * support multiple images in Tk photos.
+ */
+
+ char *icon;
+ if (strcmp(Tcl_GetString(objv[3]), "-default") == 0) {
+ icon = Tcl_GetString(objv[4]);
+ } else {
+ icon = Tcl_GetString(objv[3]);
+ }
+
+ /*
+ * Get image and convert to NSImage that can be displayed as icon.
+ */
+
+ tk_icon = Tk_GetImage(interp, tkwin, icon, NULL, NULL);
+ if (tk_icon == NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't use \"%s\" as iconphoto: not a photo image",
+ icon));
+ Tcl_SetErrorCode(interp, "TK", "WM", "ICONPHOTO", "PHOTO", NULL);
+ return TCL_ERROR;
+ }
+
+ NSImage *newIcon;
+ Tk_SizeOfImage(tk_icon, &width, &height);
+ newIcon = TkMacOSXGetNSImageWithTkImage(winPtr->display, tk_icon,
+ width, height);
+ Tk_FreeImage(tk_icon);
+ if (newIcon == NULL) {
+ return TCL_ERROR;
+ }
+ [NSApp setApplicationIconImage: newIcon];
+ 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(
+ 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) {
+ Tcl_Obj *results[2];
+
+ results[0] = Tcl_NewIntObj(wmPtr->hints.icon_x);
+ results[1] = Tcl_NewIntObj(wmPtr->hints.icon_y);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(2, results));
+ }
+ 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(
+ 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_SetObjResult(interp, TkNewWindowObj(wmPtr->icon));
+ }
+ 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_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't use %s as icon window: not at top level",
+ Tk_PathName(tkwin2)));
+ Tcl_SetErrorCode(interp, "TK", "WM", "ICONWINDOW", "TOPLEVEL",
+ NULL);
+ return TCL_ERROR;
+ }
+ wmPtr2 = ((TkWindow *) tkwin2)->wmInfoPtr;
+ if (wmPtr2->iconFor != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "%s is already an icon for %s",
+ Tcl_GetString(objv[3]), Tk_PathName(wmPtr2->iconFor)));
+ Tcl_SetErrorCode(interp, "TK", "WM", "ICONWINDOW", "ICON", NULL);
+ return TCL_ERROR;
+ }
+ if (wmPtr->icon != NULL) {
+ TkWindow *oldIcon = (TkWindow *)wmPtr->icon;
+ WmInfo *wmPtr3 = oldIcon->wmInfoPtr;
+ NSWindow *win = TkMacOSXDrawableWindow(oldIcon->window);
+
+ /*
+ * The old icon should be withdrawn.
+ */
+
+ TkpWmSetState(oldIcon, WithdrawnState);
+ [win orderOut:nil];
+ [win setExcludedFromWindowsMenu:YES];
+ 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)) {
+ /*
+ * If the window is in normal or zoomed state, the icon should be
+ * unmapped.
+ */
+
+ if (wmPtr->hints.initial_state == NormalState ||
+ wmPtr->hints.initial_state == ZoomState) {
+ Tk_UnmapWindow(tkwin2);
+ }
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmManageCmd --
+ *
+ * This procedure is invoked to process the "wm manage" 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
+WmManageCmd(
+ Tk_Window tkwin, /* Main window of the application. */
+ TkWindow *winPtr, /* Toplevel or Frame to work with */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ register Tk_Window frameWin = (Tk_Window) winPtr;
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+
+ if (!Tk_IsTopLevel(frameWin)) {
+ MacDrawable *macWin = (MacDrawable *) winPtr->window;
+
+ if (!Tk_IsManageable(frameWin)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "window \"%s\" is not manageable: must be a"
+ " frame, labelframe or toplevel",
+ Tk_PathName(frameWin)));
+ Tcl_SetErrorCode(interp, "TK", "WM", "MANAGE", NULL);
+ return TCL_ERROR;
+ }
+ TkFocusSplit(winPtr);
+ Tk_UnmapWindow(frameWin);
+ if (wmPtr == NULL) {
+ TkWmNewWindow(winPtr);
+ if (winPtr->window == None) {
+ Tk_MakeWindowExist((Tk_Window) winPtr);
+ macWin = (MacDrawable *) winPtr->window;
+ }
+ }
+ wmPtr = winPtr->wmInfoPtr;
+ winPtr->flags &= ~TK_MAPPED;
+ macWin->toplevel->referenceCount--;
+ macWin->toplevel = macWin;
+ macWin->toplevel->referenceCount++;
+ RemapWindows(winPtr, macWin);
+ winPtr->flags |=
+ (TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED);
+ TkMapTopFrame(frameWin);
+ TkWmMapWindow(winPtr);
+ } else if (Tk_IsTopLevel(frameWin)) {
+ /* Already managed by wm - ignore it */
+ }
+ 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(
+ 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) {
+ Tcl_Obj *results[2];
+
+ GetMaxSize(winPtr, &width, &height);
+ results[0] = Tcl_NewIntObj(width);
+ results[1] = Tcl_NewIntObj(height);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(2, results));
+ 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(
+ 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) {
+ Tcl_Obj *results[2];
+
+ GetMinSize(winPtr, &width, &height);
+ results[0] = Tcl_NewIntObj(width);
+ results[1] = Tcl_NewIntObj(height);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(2, results));
+ 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(
+ 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. */
+{
+ int flag;
+ XSetWindowAttributes atts;
+ TKWindow *win = (TKWindow *)TkMacOSXDrawableWindow(winPtr->window);
+
+ if ((objc != 3) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?boolean?");
+ return TCL_ERROR;
+ }
+
+ if (objc == 3) {
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
+ Tk_Attributes((Tk_Window) winPtr)->override_redirect));
+ return TCL_OK;
+ }
+
+ if (Tcl_GetBooleanFromObj(interp, objv[3], &flag) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ atts.override_redirect = flag ? True : False;
+ Tk_ChangeWindowAttributes((Tk_Window) winPtr, CWOverrideRedirect, &atts);
+ ApplyMasterOverrideChanges(winPtr, win);
+ 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(
+ 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 *const optionStrings[] = {
+ "program", "user", 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_SetObjResult(interp, Tcl_NewStringObj("user", -1));
+ } else if (wmPtr->sizeHintsFlags & PPosition) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("program", -1));
+ }
+ return TCL_OK;
+ }
+
+ if (*Tcl_GetString(objv[3]) == '\0') {
+ wmPtr->sizeHintsFlags &= ~(USPosition|PPosition);
+ } else {
+ if (Tcl_GetIndexFromObjStruct(interp, objv[3], optionStrings,
+ sizeof(char *), "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(
+ 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;
+ Tcl_Obj *resultObj;
+
+ 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.
+ */
+
+ resultObj = Tcl_NewObj();
+ for (protPtr = wmPtr->protPtr; protPtr != NULL;
+ protPtr = protPtr->nextPtr) {
+ Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(
+ Tk_GetAtomName((Tk_Window)winPtr, protPtr->protocol),-1));
+ }
+ Tcl_SetObjResult(interp, resultObj);
+ 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_SetObjResult(interp,
+ Tcl_NewStringObj(protPtr->command, -1));
+ 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;
+ }
+ if (protPtr->command)
+ ckfree(protPtr->command);
+ Tcl_EventuallyFree(protPtr, TCL_DYNAMIC);
+ break;
+ }
+ }
+ cmd = Tcl_GetStringFromObj(objv[4], &cmdLength);
+ if (cmdLength > 0) {
+ protPtr = ckalloc(sizeof(ProtocolHandler));
+ protPtr->protocol = protocol;
+ protPtr->nextPtr = wmPtr->protPtr;
+ wmPtr->protPtr = protPtr;
+ protPtr->interp = interp;
+ protPtr->command = ckalloc(cmdLength+1);
+ strcpy(protPtr->command, cmd);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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(
+ 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;
+ UInt64 oldAttributes = wmPtr->attributes;
+ int oldFlags = wmPtr->flags;
+
+ if ((objc != 3) && (objc != 5)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?width height?");
+ return TCL_ERROR;
+ }
+
+ if (objc == 3) {
+ Tcl_Obj *results[2];
+
+ results[0] = Tcl_NewBooleanObj(!(wmPtr->flags & WM_WIDTH_NOT_RESIZABLE));
+ results[1] = Tcl_NewBooleanObj(!(wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE));
+ Tcl_SetObjResult(interp, Tcl_NewListObj(2, results));
+ 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;
+ wmPtr->attributes |= kWindowHorizontalZoomAttribute;
+ } else {
+ wmPtr->flags |= WM_WIDTH_NOT_RESIZABLE;
+ wmPtr->attributes &= ~kWindowHorizontalZoomAttribute;
+ }
+ if (height) {
+ wmPtr->flags &= ~WM_HEIGHT_NOT_RESIZABLE;
+ wmPtr->attributes |= kWindowVerticalZoomAttribute;
+ } else {
+ wmPtr->flags |= WM_HEIGHT_NOT_RESIZABLE;
+ wmPtr->attributes &= ~kWindowVerticalZoomAttribute;
+ }
+ if (width || height) {
+ wmPtr->attributes |= kWindowResizableAttribute;
+ } else {
+ wmPtr->attributes &= ~kWindowResizableAttribute;
+ }
+ wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
+ if (wmPtr->scrollWinPtr != NULL) {
+ TkScrollbarEventuallyRedraw((TkScrollbar *)
+ wmPtr->scrollWinPtr->instanceData);
+ }
+ WmUpdateGeom(wmPtr, winPtr);
+ ApplyWindowAttributeFlagChanges(winPtr, NULL, oldAttributes, oldFlags, 1,0);
+ 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(
+ 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 *const optionStrings[] = {
+ "program", "user", 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_SetObjResult(interp, Tcl_NewStringObj("user", -1));
+ } else if (wmPtr->sizeHintsFlags & PSize) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("program", -1));
+ }
+ return TCL_OK;
+ }
+
+ if (*Tcl_GetString(objv[3]) == '\0') {
+ wmPtr->sizeHintsFlags &= ~(USSize|PSize);
+ } else {
+ if (Tcl_GetIndexFromObjStruct(interp, objv[3], optionStrings,
+ sizeof(char *), "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(
+ 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, **windowPtr;
+ static const char *const optionStrings[] = {
+ "isabove", "isbelow", NULL
+ };
+ enum options {
+ OPT_ISABOVE, OPT_ISBELOW
+ };
+ Tcl_Obj *resultObj;
+ 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) {
+ Tcl_Panic("TkWmStackorderToplevel failed");
+ }
+
+ resultObj = Tcl_NewObj();
+ for (windowPtr = windows; *windowPtr ; windowPtr++) {
+ Tcl_ListObjAppendElement(NULL, resultObj,
+ TkNewWindowObj((Tk_Window) *windowPtr));
+ }
+ Tcl_SetObjResult(interp, resultObj);
+ ckfree(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_SetObjResult(interp, Tcl_ObjPrintf(
+ "window \"%s\" isn't a top-level window",
+ winPtr2->pathName));
+ Tcl_SetErrorCode(interp, "TK", "WM", "STACK", "TOPLEVEL", NULL);
+ return TCL_ERROR;
+ }
+
+ if (!Tk_IsMapped(winPtr)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "window \"%s\" isn't mapped", winPtr->pathName));
+ Tcl_SetErrorCode(interp, "TK", "WM", "STACK", "MAPPED", NULL);
+ return TCL_ERROR;
+ } else if (!Tk_IsMapped(winPtr2)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "window \"%s\" isn't mapped", winPtr2->pathName));
+ Tcl_SetErrorCode(interp, "TK", "WM", "STACK", "MAPPED", 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_SetObjResult(interp, Tcl_NewStringObj(
+ "TkWmStackorderToplevel failed", -1));
+ Tcl_SetErrorCode(interp, "TK", "WM", "STACK", "FAIL", NULL);
+ return TCL_ERROR;
+ }
+
+ for (windowPtr = windows; *windowPtr ; windowPtr++) {
+ if (*windowPtr == winPtr) {
+ index1 = windowPtr - windows;
+ }
+ if (*windowPtr == winPtr2) {
+ index2 = windowPtr - windows;
+ }
+ }
+ if (index1 == -1) {
+ Tcl_Panic("winPtr window not found");
+ } else if (index2 == -1) {
+ Tcl_Panic("winPtr2 window not found");
+ }
+
+ ckfree(windows);
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[3], optionStrings,
+ sizeof(char *), "argument", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (index == OPT_ISABOVE) {
+ result = index1 > index2;
+ } else { /* OPT_ISBELOW */
+ result = index1 < index2;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result));
+ 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(
+ 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 *const optionStrings[] = {
+ "normal", "iconic", "withdrawn", "zoomed", 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_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't change state of %s: it is an icon for %s",
+ Tcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor)));
+ Tcl_SetErrorCode(interp, "TK", "WM", "STATE", "ICON", NULL);
+ return TCL_ERROR;
+ }
+ if (winPtr->flags & TK_EMBEDDED) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't change state of %s: it is an embedded window",
+ winPtr->pathName));
+ Tcl_SetErrorCode(interp, "TK", "WM", "STATE", "EMBEDDED", NULL);
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[3], optionStrings,
+ sizeof(char *), "argument", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch (index) {
+ case OPT_NORMAL:
+ TkpWmSetState(winPtr, NormalState);
+
+ /*
+ * This varies from 'wm deiconify' because it does not force the
+ * window to be raised and receive focus
+ */
+
+ break;
+ case OPT_ICONIC:
+ if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't iconify \"%s\": override-redirect flag is set",
+ winPtr->pathName));
+ Tcl_SetErrorCode(interp, "TK", "WM", "STATE",
+ "OVERRIDE_REDIRECT", NULL);
+ return TCL_ERROR;
+ }
+ if (wmPtr->master != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't iconify \"%s\": it is a transient",
+ winPtr->pathName));
+ Tcl_SetErrorCode(interp, "TK", "WM", "STATE", "TRANSIENT",
+ NULL);
+ return TCL_ERROR;
+ }
+ TkpWmSetState(winPtr, IconicState);
+ break;
+ case OPT_WITHDRAWN:
+ TkpWmSetState(winPtr, WithdrawnState);
+ break;
+ default: /* OPT_ZOOMED */
+ TkpWmSetState(winPtr, ZoomState);
+ break;
+ }
+ } else if (wmPtr->iconFor != NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("icon", -1));
+ } else {
+ if (wmPtr->hints.initial_state == NormalState ||
+ wmPtr->hints.initial_state == ZoomState) {
+ wmPtr->hints.initial_state = (TkMacOSXIsWindowZoomed(winPtr) ?
+ ZoomState : NormalState);
+ }
+ switch (wmPtr->hints.initial_state) {
+ case NormalState:
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("normal", -1));
+ break;
+ case IconicState:
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("iconic", -1));
+ break;
+ case WithdrawnState:
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("withdrawn", -1));
+ break;
+ case ZoomState:
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("zoomed", -1));
+ 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(
+ 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_SetObjResult(interp, Tcl_NewStringObj(
+ wmPtr->titleUid ? wmPtr->titleUid : winPtr->nameUid, -1));
+ return TCL_OK;
+ }
+
+ 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(
+ 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;
+ TkWindow *masterPtr, *w;
+ WmInfo *wmPtr2;
+ Transient *transient;
+
+ if ((objc != 3) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?master?");
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ if (wmPtr->master != NULL) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj(Tk_PathName(wmPtr->master), -1));
+ }
+ return TCL_OK;
+ }
+ if (*Tcl_GetString(objv[3]) == '\0') {
+ RemoveTransient(winPtr);
+ } else {
+ if (TkGetWindowFromObj(interp, tkwin, objv[3], &master) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ masterPtr = (TkWindow*) master;
+ while (!Tk_TopWinHierarchy(masterPtr)) {
+ /*
+ * Ensure that the master window is actually a Tk toplevel.
+ */
+
+ masterPtr = masterPtr->parentPtr;
+ }
+ Tk_MakeWindowExist((Tk_Window)masterPtr);
+
+ if (wmPtr->iconFor != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't make \"%s\" a transient: it is an icon for %s",
+ Tcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor)));
+ Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "ICON", NULL);
+ return TCL_ERROR;
+ }
+
+ wmPtr2 = masterPtr->wmInfoPtr;
+
+ /*
+ * Under some circumstances, wmPtr2 is NULL here.
+ */
+
+ if (wmPtr2 != NULL && wmPtr2->iconFor != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't make \"%s\" a master: it is an icon for %s",
+ Tcl_GetString(objv[3]), Tk_PathName(wmPtr2->iconFor)));
+ Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "ICON", NULL);
+ return TCL_ERROR;
+ }
+
+ for (w = masterPtr; w != NULL && w->wmInfoPtr != NULL;
+ w = (TkWindow *)w->wmInfoPtr->master) {
+ if (w == winPtr) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "setting \"%s\" as master creates a transient/master cycle",
+ Tk_PathName(masterPtr)));
+ Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * Add the transient to the master's list, if it not already there.
+ */
+
+ for (transient = wmPtr2->transientPtr;
+ transient != NULL && transient->winPtr != winPtr;
+ transient = transient->nextPtr) {}
+ if (transient == NULL) {
+ transient = ckalloc(sizeof(Transient));
+ transient->winPtr = winPtr;
+ transient->flags = 0;
+ transient->nextPtr = wmPtr2->transientPtr;
+ wmPtr2->transientPtr = transient;
+ }
+
+ /*
+ * If the master is withdrawn or iconic then withdraw the transient.
+ */
+
+ if ((wmPtr2->hints.initial_state == WithdrawnState ||
+ wmPtr2->hints.initial_state == IconicState) &&
+ wmPtr->hints.initial_state != WithdrawnState) {
+ TkpWmSetState(winPtr, WithdrawnState);
+ transient->flags |= WITHDRAWN_BY_MASTER;
+ }
+
+ wmPtr->master = (Tk_Window) masterPtr;
+ }
+ ApplyMasterOverrideChanges(winPtr, NULL);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * RemoveTransient --
+ *
+ * Clears the transient's master record and removes the transient from the
+ * master's list.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * References to a master are removed from the transient's wmInfo
+ * structure and references to the transient are removed from its master's
+ * wmInfo.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+RemoveTransient(
+ TkWindow *winPtr)
+{
+ WmInfo *wmPtr = winPtr->wmInfoPtr, *wmPtr2;
+ TkWindow *masterPtr;
+ Transient *transPtr, *temp;
+
+ if (wmPtr == NULL || wmPtr->master == NULL) {
+ return;
+ }
+ masterPtr = (TkWindow*)wmPtr->master;
+ wmPtr2 = masterPtr->wmInfoPtr;
+ if (wmPtr2 == NULL) {
+ return;
+ }
+ wmPtr->master = NULL;
+ transPtr = wmPtr2->transientPtr;
+ while (transPtr != NULL) {
+ if (transPtr->winPtr != winPtr) {
+ break;
+ }
+ temp = transPtr->nextPtr;
+ ckfree(transPtr);
+ transPtr = temp;
+ }
+ wmPtr2->transientPtr = transPtr;
+ while (transPtr != NULL) {
+ if (transPtr->nextPtr && transPtr->nextPtr->winPtr == winPtr) {
+ temp = transPtr->nextPtr;
+ transPtr->nextPtr = temp->nextPtr;
+ ckfree(temp);
+ } else {
+ transPtr = transPtr->nextPtr;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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(
+ 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_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't withdraw %s: it is an icon for %s",
+ Tcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor)));
+ Tcl_SetErrorCode(interp, "TK", "WM", "WITHDRAW", "ICON", NULL);
+ return TCL_ERROR;
+ }
+
+ TkpWmSetState(winPtr, WithdrawnState);
+
+ NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
+ [win orderOut:nil];
+ [win setExcludedFromWindowsMenu:YES];
+
+ /*
+ * If this window has a transient, the transient must also be withdrawn.
+ */
+
+ for (Transient *transientPtr = wmPtr->transientPtr;
+ transientPtr != NULL; transientPtr = transientPtr->nextPtr) {
+ TkWindow *winPtr2 = transientPtr->winPtr;
+ TkWindow *masterPtr = (TkWindow *) TkGetTransientMaster(winPtr2);
+
+ if (masterPtr == winPtr &&
+ winPtr2->wmInfoPtr->hints.initial_state != WithdrawnState) {
+ TkpWmSetState(winPtr2, WithdrawnState);
+ transientPtr->flags |= WITHDRAWN_BY_MASTER;
+ }
+ }
+
+ return TCL_OK;
+}
+
+/*
+ * Invoked by those wm subcommands that affect geometry. Schedules a geometry
+ * update.
+ */
+
+static void
+WmUpdateGeom(
+ WmInfo *wmPtr,
+ TkWindow *winPtr)
+{
+ if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {
+ Tcl_DoWhenIdle(UpdateGeometryInfo, 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;
+
+ /*
+ * Ensure widthInc and heightInc are greater than 0
+ */
+
+ if (widthInc <= 0) {
+ widthInc = 1;
+ }
+ if (heightInc <= 0) {
+ heightInc = 1;
+ }
+
+ /*
+ * 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))) {
+ Tcl_DoWhenIdle(UpdateGeometryInfo, 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))) {
+ Tcl_DoWhenIdle(UpdateGeometryInfo, 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 = clientData;
+
+ winPtr->wmInfoPtr->flags |= WM_VROOT_OFFSET_STALE;
+ if (eventPtr->type == DestroyNotify) {
+ 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.
+ */
+
+ Tk_ErrorHandler handler = Tk_CreateErrorHandler(winPtr->display,
+ -1, -1, -1, NULL, NULL);
+
+ Tk_DestroyWindow((Tk_Window) winPtr);
+ Tk_DeleteErrorHandler(handler);
+ }
+ if (wmTracing) {
+ TkMacOSXDbgMsg("TopLevelEventProc: %s deleted", winPtr->pathName);
+ }
+ } else if (eventPtr->type == ReparentNotify) {
+ Tcl_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))) {
+ Tcl_DoWhenIdle(UpdateGeometryInfo, 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 = clientData;
+ WmInfo *wmPtr = winPtr->wmInfoPtr;
+ int x, y, width, height, min, max;
+
+ wmPtr->flags &= ~WM_UPDATE_PENDING;
+
+ if (wmPtr->flags & WM_FULLSCREEN) {
+ return;
+ }
+
+ /*
+ * 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;
+ }
+
+ /*
+ * Account for window max/min width
+ */
+
+ if (wmPtr->gridWin != NULL) {
+ min = winPtr->reqWidth
+ + (wmPtr->minWidth - wmPtr->reqGridWidth)*wmPtr->widthInc;
+ if (wmPtr->maxWidth > 0) {
+ max = winPtr->reqWidth
+ + (wmPtr->maxWidth - wmPtr->reqGridWidth)*wmPtr->widthInc;
+ } else {
+ max = 0;
+ }
+ } else {
+ min = wmPtr->minWidth;
+ max = wmPtr->maxWidth;
+ }
+ if (width < min) {
+ width = min;
+ } else if ((max > 0) && (width > max)) {
+ width = max;
+ }
+
+ 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;
+ }
+
+ /*
+ * Account for window max/min height
+ */
+
+ if (wmPtr->gridWin != NULL) {
+ min = winPtr->reqHeight
+ + (wmPtr->minHeight - wmPtr->reqGridHeight)*wmPtr->heightInc;
+ if (wmPtr->maxHeight > 0) {
+ max = winPtr->reqHeight
+ + (wmPtr->maxHeight-wmPtr->reqGridHeight)*wmPtr->heightInc;
+ } else {
+ max = 0;
+ }
+ } else {
+ min = wmPtr->minHeight;
+ max = wmPtr->maxHeight;
+ }
+ if (height < min) {
+ height = min;
+ } else if ((max > 0) && (height > max)) {
+ height = max;
+ }
+ x = wmPtr->x;
+ 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))) {
+ 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 = TkpGetOtherWindow(winPtr);
+
+ /*
+ * TODO: 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;
+ }
+ if (wmPtr->flags & WM_MOVE_PENDING) {
+ wmPtr->configWidth = width;
+ wmPtr->configHeight = height;
+ if (wmTracing) {
+ TkMacOSXDbgMsg("Moving to %d %d, resizing to %d x %d", x, y,
+ width, height);
+ }
+ SetWindowSizeLimits(winPtr);
+ wmPtr->flags |= WM_SYNC_PENDING;
+ XMoveResizeWindow(winPtr->display, winPtr->window, x, y,
+ wmPtr->configWidth, wmPtr->configHeight);
+ wmPtr->flags &= ~WM_SYNC_PENDING;
+ } else if ((width != wmPtr->configWidth)
+ || (height != wmPtr->configHeight)) {
+ wmPtr->configWidth = width;
+ wmPtr->configHeight = height;
+ if (wmTracing) {
+ TkMacOSXDbgMsg("Resizing to %d x %d\n", width, height);
+ }
+ SetWindowSizeLimits(winPtr);
+ wmPtr->flags |= WM_SYNC_PENDING;
+ XResizeWindow(winPtr->display, winPtr->window, wmPtr->configWidth,
+ wmPtr->configHeight);
+ wmPtr->flags &= ~WM_SYNC_PENDING;
+ } else {
+ SetWindowSizeLimits(winPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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;
+
+ wmPtr->flags &= ~WM_UPDATE_SIZE_HINTS;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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 = -1;
+ y = -1;
+ 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;
+ }
+ p++;
+ if (!isdigit(UCHAR(*p)) && (*p != '-')) {
+ goto error;
+ }
+ x = strtol(p, &end, 10);
+ p = end;
+ if (*p == '-') {
+ flags |= WM_NEGATIVE_Y;
+ } else if (*p != '+') {
+ goto error;
+ }
+ p++;
+ if (!isdigit(UCHAR(*p)) && (*p != '-')) {
+ goto error;
+ }
+ y = strtol(p, &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))) {
+ 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.
+ *
+ * Computing the new position for the upper-left pixel of the window's
+ * decorative frame is tricky because we need to include the border
+ * widths supplied by a reparented parent in the calculation, but we can't
+ * use the parent's current overall size since that may change as a result
+ * of this code.
+ */
+
+ wmPtr->width = width;
+ wmPtr->height = height;
+ if (flags & WM_NEGATIVE_X) {
+ int borderwidth = wmPtr->parentWidth - winPtr->changes.width;
+ int newWidth = width == -1 ? winPtr->changes.width : width;
+
+ x = (x == -1) ?
+ wmPtr->x + winPtr->changes.width - newWidth :
+ wmPtr->vRootWidth - x - newWidth - borderwidth;
+ }
+ if (x == -1) {
+ x = wmPtr->x;
+ }
+ if (flags & WM_NEGATIVE_Y) {
+ int borderheight = wmPtr->parentHeight - winPtr->changes.height;
+ int newHeight = height == -1 ? winPtr->changes.height : height;
+
+ y = (y == -1) ?
+ wmPtr->y + winPtr->changes.height - newHeight :
+ wmPtr->vRootHeight - y - newHeight - borderheight;
+ }
+ if (y == -1) {
+ y = wmPtr->y;
+ }
+ if (wmPtr->flags & WM_FULLSCREEN) {
+ wmPtr->configX = x;
+ wmPtr->configY = y;
+ } else {
+ wmPtr->x = x;
+ wmPtr->y = y;
+ }
+ flags |= WM_MOVE_PENDING;
+ wmPtr->flags = flags;
+ if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {
+ Tcl_DoWhenIdle(UpdateGeometryInfo, winPtr);
+ wmPtr->flags |= WM_UPDATE_PENDING;
+ }
+ return TCL_OK;
+
+ error:
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad geometry specifier \"%s\"", string));
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "GEOMETRY", 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) {
+ TkWindow *otherPtr;
+
+ if (!(Tk_IsEmbedded(winPtr))) {
+ x += winPtr->wmInfoPtr->xInParent;
+ y += winPtr->wmInfoPtr->yInParent;
+ break;
+ }
+
+ otherPtr = TkpGetOtherWindow(winPtr);
+ if (otherPtr == NULL) {
+ if (tkMacOSXEmbedHandler->getOffsetProc != NULL) {
+ Point theOffset;
+
+ /*
+ * 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;
+
+ tkMacOSXEmbedHandler->getOffsetProc((Tk_Window) winPtr,
+ &theOffset);
+
+ x += theOffset.h;
+ y += theOffset.v;
+ }
+ break;
+ }
+
+ /*
+ * The container window is in the same application. Query its
+ * coordinates.
+ */
+
+ winPtr = otherPtr;
+ continue;
+ }
+ 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. */
+{
+ 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;
+
+ /*
+ * Step 1: find the top-level window that contains the desired point.
+ */
+
+ winPtr = FrontWindowAtPoint(rootX, rootY);
+ if (!winPtr) {
+ 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;
+ }
+ }
+ }
+
+ /*
+ * TODO: 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;
+ }
+ if (winPtr->mainPtr != ((TkWindow *) tkwin)->mainPtr) {
+ return NULL;
+ }
+ 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;
+ }
+ }
+
+ /*
+ * TODO: 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, NULL, NULL);
+ status = XGetGeometry(winPtr->display, wmPtr->vRoot,
+ &dummy2, &wmPtr->vRootX, &wmPtr->vRootY,
+ &wmPtr->vRootWidth, &wmPtr->vRootHeight, &bd, &dummy);
+ if (wmTracing) {
+ TkMacOSXDbgMsg("x = %d, y = %d, width = %d, height = %d, status = %d",
+ wmPtr->vRootX, wmPtr->vRootY, wmPtr->vRootWidth,
+ 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)) {
+ Tcl_Panic("Tk_MoveToplevelWindow called with non-toplevel window");
+ }
+ wmPtr->x = x;
+ wmPtr->y = y;
+ wmPtr->flags |= WM_MOVE_PENDING;
+ if (!(wmPtr->sizeHintsFlags & (USPosition|PPosition))) {
+ 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) {
+ Tcl_CancelIdleCall(UpdateGeometryInfo, winPtr);
+ }
+ UpdateGeometryInfo(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. */
+{
+ NSWindow *macWindow;
+ NSWindow *otherMacWindow;
+ WmInfo *wmPtr = winPtr->wmInfoPtr;
+ int macAboveBelow = (aboveBelow == Above ? NSWindowAbove : NSWindowBelow);
+ int otherNumber = 0; /* 0 will be used when otherPtr is NULL. */
+
+ /*
+ * If the Tk windows has no drawable, or is withdrawn do nothing.
+ */
+
+ if (winPtr->window == None ||
+ wmPtr == NULL ||
+ wmPtr->hints.initial_state == WithdrawnState) {
+ return;
+ }
+ macWindow = TkMacOSXDrawableWindow(winPtr->window);
+ if (macWindow == nil) {
+ return;
+ }
+ if (otherPtr) {
+ /*
+ * When otherPtr is non-NULL, if the other window has no drawable or is
+ * withdrawn, do nothing.
+ */
+
+ WmInfo *otherWmPtr = otherPtr->wmInfoPtr;
+ if (winPtr->window == None ||
+ otherWmPtr == NULL ||
+ otherWmPtr->hints.initial_state == WithdrawnState) {
+ return;
+ }
+ otherMacWindow = TkMacOSXDrawableWindow(otherPtr->window);
+ if (otherMacWindow == nil) {
+ return;
+ }
+
+ /*
+ * If the other window is OK, get its number.
+ */
+
+ otherNumber = [otherMacWindow windowNumber];
+ }
+
+ /*
+ * Just let the Mac window manager deal with all the subtleties of keeping
+ * track of off-screen windows, etc.
+ */
+
+ [macWindow orderWindow:macAboveBelow relativeTo:otherNumber];
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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 = ckalloc((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(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, **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. */
+{
+ XQueryPointer(NULL, None, NULL, NULL, xPtr, yPtr, NULL, NULL, NULL);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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:
+ * Window bounds.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static NSRect
+InitialWindowBounds(
+ TkWindow *winPtr, /* Window to get initial bounds for. */
+ NSWindow *macWindow)
+{
+ WmInfo *wmPtr = winPtr->wmInfoPtr;
+
+ if (!(wmPtr->sizeHintsFlags & (USPosition | PPosition))) {
+ static NSPoint cascadePoint = { .x = 0, .y = 0 };
+ NSRect frame;
+
+ cascadePoint = [macWindow cascadeTopLeftFromPoint:cascadePoint];
+ frame = [macWindow frame];
+ wmPtr->x = frame.origin.x;
+ wmPtr->y = tkMacOSXZeroScreenHeight - (frame.origin.y +
+ frame.size.height);
+ }
+ return NSMakeRect(wmPtr->x, wmPtr->y, winPtr->changes.width,
+ 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(
+ void *whichWindow,
+ XPoint start)
+{
+ 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)
+{
+ if (Tk_IsEmbedded(winPtr)) {
+ return;
+ }
+
+ NSString *title = [[NSString alloc] initWithUTF8String:titleUid];
+ [TkMacOSXDrawableWindow(winPtr->window) setTitle:title];
+ [title release];
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_Window
+TkGetTransientMaster(
+ TkWindow *winPtr)
+{
+ if (winPtr->wmInfoPtr != NULL) {
+ return (Tk_Window)winPtr->wmInfoPtr->master;
+ }
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXGetXWindow --
+ *
+ * Returns the X window Id associated with the given NSWindow*.
+ *
+ * Results:
+ * The window id is returned. None is returned if not a Tk window.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Window
+TkMacOSXGetXWindow(
+ void *macWinPtr)
+{
+ Tcl_HashEntry *hPtr;
+
+ if (!macWinPtr || !windowHashInit) {
+ return None;
+ }
+ hPtr = Tcl_FindHashEntry(&windowTable, macWinPtr);
+ if (hPtr == NULL) {
+ return None;
+ }
+ return (Window) Tcl_GetHashValue(hPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXGetTkWindow --
+ *
+ * Returns the TkWindow* associated with the given NSWindow*.
+ *
+ * Results:
+ * The TkWindow* returned. NULL is returned if not a Tk window.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkWindow*
+TkMacOSXGetTkWindow(
+ NSWindow *w)
+{
+ Window window = TkMacOSXGetXWindow(w);
+ TkDisplay *dispPtr = TkGetDisplayList();
+
+ return (window != None ?
+ (TkWindow *)Tk_IdToWindow(dispPtr->display, window) : NULL);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXIsWindowZoomed --
+ *
+ * Ask Cocoa if the given window is in the zoomed out state. Because
+ * dragging & growing a window can change the Cocoa zoom state, we
+ * cannot rely on wmInfoPtr->hints.initial_state for this information.
+ *
+ * Results:
+ * True if window is zoomed out, false otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+MODULE_SCOPE int
+TkMacOSXIsWindowZoomed(
+ TkWindow *winPtr)
+{
+ NSWindow *macWindow = TkMacOSXDrawableWindow(winPtr->window);
+ return [macWindow isZoomed];
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXZoomToplevel --
+ *
+ * The function is invoked when the user clicks in the zoom region of a
+ * Tk window or when the window state is set/unset to "zoomed" manually.
+ * If the window is to be zoomed (in or out), 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(
+ void *whichWindow, /* The Macintosh window to zoom. */
+ short zoomPart) /* Either inZoomIn or inZoomOut */
+{
+ NSWindow *window = whichWindow;
+ TkWindow *winPtr = TkMacOSXGetTkWindow(window);
+ WmInfo *wmPtr;
+
+ if (!winPtr || !winPtr->wmInfoPtr) {
+ return false;
+ }
+ wmPtr = winPtr->wmInfoPtr;
+ if ((wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) &&
+ (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE)) {
+ return false;
+ }
+
+ /*
+ * Do nothing if already in desired zoom state.
+ */
+
+ if (([window isZoomed] == (zoomPart == inZoomOut))) {
+ return false;
+ }
+ [window zoom:NSApp];
+
+ wmPtr->hints.initial_state =
+ (zoomPart == inZoomIn ? NormalState : ZoomState);
+ 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
+TkUnsupported1ObjCmd(
+ ClientData clientData, /* Main window associated with interpreter. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ static const char *const subcmds[] = {
+ "style", "tabbingid", "appearance", "isdark", NULL
+ };
+ enum SubCmds {
+ TKMWS_STYLE, TKMWS_TABID, TKMWS_APPEARANCE, TKMWS_ISDARK
+ };
+ Tk_Window tkwin = clientData;
+ TkWindow *winPtr;
+ int index;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option window ?arg ...?");
+ return TCL_ERROR;
+ }
+
+ winPtr = (TkWindow *)
+ Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin);
+ if (winPtr == NULL) {
+ return TCL_ERROR;
+ }
+ if (!(winPtr->flags & TK_TOP_LEVEL)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "window \"%s\" isn't a top-level window", winPtr->pathName));
+ Tcl_SetErrorCode(interp, "TK", "WINDOWSTYLE", "TOPLEVEL", NULL);
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[1], subcmds,
+ sizeof(char *), "option", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch((enum SubCmds) index) {
+ case TKMWS_STYLE:
+ if ((objc < 3) || (objc > 5)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?class attributes?");
+ return TCL_ERROR;
+ }
+ return WmWinStyle(interp, winPtr, objc, objv);
+ case TKMWS_TABID:
+ if ([NSApp macMinorVersion] < 12) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "Tabbing identifiers did not exist until OSX 10.12.", -1));
+ Tcl_SetErrorCode(interp, "TK", "WINDOWSTYLE", "TABBINGID", NULL);
+ return TCL_ERROR;
+ }
+ if ((objc < 3) || (objc > 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "tabbingid window ?newid?");
+ return TCL_ERROR;
+ }
+ return WmWinTabbingId(interp, winPtr, objc, objv);
+ case TKMWS_APPEARANCE:
+ if ([NSApp macMinorVersion] < 9) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "Window appearances did not exist until OSX 10.9.", -1));
+ Tcl_SetErrorCode(interp, "TK", "WINDOWSTYLE", "APPEARANCE", NULL);
+ return TCL_ERROR;
+ }
+ if ((objc < 3) || (objc > 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?appearancename?");
+ return TCL_ERROR;
+ }
+ if (objc == 4 && [NSApp macMinorVersion] < 14) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "Window appearances cannot be changed before OSX 10.14.",
+ -1));
+ Tcl_SetErrorCode(interp, "TK", "WINDOWSTYLE", "APPEARANCE", NULL);
+ return TCL_ERROR;
+ }
+ return WmWinAppearance(interp, winPtr, objc, objv);
+ case TKMWS_ISDARK:
+ if ((objc != 3)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "isdark window");
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(TkMacOSXInDarkMode(tkwin)));
+ return TCL_OK;
+ default:
+ return TCL_ERROR;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmWinStyle --
+ *
+ * This procedure is invoked to process the
+ * "::tk::unsupported::MacWindowStyle style" subcommand. 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WmWinStyle(
+ Tcl_Interp *interp, /* Current interpreter. */
+ TkWindow *winPtr, /* Window to be manipulated. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj * const objv[]) /* Argument objects. */
+{
+ struct StrIntMap {
+ const char *strValue;
+ UInt64 intValue;
+ };
+ static const struct StrIntMap classMap[] = {
+ { "alert", kAlertWindowClass },
+ { "moveableAlert", kMovableAlertWindowClass },
+ { "modal", kModalWindowClass },
+ { "moveableModal", kMovableModalWindowClass },
+ { "floating", kFloatingWindowClass },
+ { "document", kDocumentWindowClass },
+ { "utility", kUtilityWindowClass },
+ { "help", kHelpWindowClass },
+ { "sheet", kSheetWindowClass },
+ { "toolbar", kToolbarWindowClass },
+ { "plain", kPlainWindowClass },
+ { "overlay", kOverlayWindowClass },
+ { "sheetAlert", kSheetAlertWindowClass },
+ { "altPlain", kAltPlainWindowClass },
+ { "simple", kSimpleWindowClass },
+ { "drawer", kDrawerWindowClass },
+ { NULL }
+ };
+ static const struct StrIntMap compositeAttrMap[] = {
+ { "none", kWindowNoAttributes },
+ { "standardDocument", kWindowStandardDocumentAttributes },
+ { "standardFloating", kWindowStandardFloatingAttributes },
+ { "fullZoom", kWindowFullZoomAttribute },
+ { NULL }
+ };
+
+ /*
+ * Map window attributes. Color and opacity are mapped to NULL; these are
+ * parsed from the objv in TkUnsupported1ObjCmd.
+ */
+
+ static const struct StrIntMap attrMap[] = {
+ { "closeBox", kWindowCloseBoxAttribute },
+ { "horizontalZoom", kWindowHorizontalZoomAttribute },
+ { "verticalZoom", kWindowVerticalZoomAttribute },
+ { "collapseBox", kWindowCollapseBoxAttribute },
+ { "resizable", kWindowResizableAttribute },
+ { "sideTitlebar", kWindowSideTitlebarAttribute },
+ { "toolbarButton", kWindowToolbarButtonAttribute },
+ { "unifiedTitleAndToolbar", kWindowUnifiedTitleAndToolbarAttribute },
+ { "metal", kWindowMetalAttribute },
+ { "noTitleBar", kWindowNoTitleBarAttribute },
+ { "texturedSquareCorners", kWindowTexturedSquareCornersAttribute },
+ { "metalNoContentSeparator", kWindowMetalNoContentSeparatorAttribute },
+ { "doesNotCycle", kWindowDoesNotCycleAttribute },
+ { "noUpdates", kWindowNoUpdatesAttribute },
+ { "noActivates", kWindowNoActivatesAttribute },
+ { "opaqueForEvents", kWindowOpaqueForEventsAttribute },
+ { "noShadow", kWindowNoShadowAttribute },
+ { "hideOnSuspend", kWindowHideOnSuspendAttribute },
+ { "hideOnFullScreen", kWindowHideOnFullScreenAttribute },
+ { "inWindowMenu", kWindowInWindowMenuAttribute },
+ { "liveResize", kWindowLiveResizeAttribute },
+ { "ignoreClicks", kWindowIgnoreClicksAttribute },
+ { "noConstrain", kWindowNoConstrainAttribute },
+ { "doesNotHide", tkWindowDoesNotHideAttribute },
+ { "canJoinAllSpaces", tkCanJoinAllSpacesAttribute },
+ { "moveToActiveSpace", tkMoveToActiveSpaceAttribute },
+ { "nonActivating", tkNonactivatingPanelAttribute },
+ { "hud", tkHUDWindowAttribute },
+ { NULL }
+ };
+
+ int index, i;
+ WmInfo *wmPtr = winPtr->wmInfoPtr;
+
+ if (objc == 3) {
+ Tcl_Obj *attributeList, *newResult = NULL;
+ UInt64 attributes;
+
+ for (i = 0; classMap[i].strValue != NULL; i++) {
+ if (wmPtr->macClass == classMap[i].intValue) {
+ newResult = Tcl_NewStringObj(classMap[i].strValue, -1);
+ break;
+ }
+ }
+ if (newResult == NULL) {
+ Tcl_Panic("invalid class");
+ }
+
+ attributeList = Tcl_NewListObj(0, NULL);
+ attributes = wmPtr->attributes;
+
+ for (i = 0; compositeAttrMap[i].strValue != NULL; i++) {
+ UInt64 intValue = compositeAttrMap[i].intValue;
+
+ if (intValue && (attributes & intValue) == intValue) {
+ Tcl_ListObjAppendElement(NULL, attributeList,
+ Tcl_NewStringObj(compositeAttrMap[i].strValue,
+ -1));
+ attributes &= ~intValue;
+ break;
+ }
+ }
+ for (i = 0; attrMap[i].strValue != NULL; i++) {
+ if (attributes & attrMap[i].intValue) {
+ Tcl_ListObjAppendElement(NULL, attributeList,
+ Tcl_NewStringObj(attrMap[i].strValue, -1));
+ }
+ }
+ Tcl_ListObjAppendElement(NULL, newResult, attributeList);
+ Tcl_SetObjResult(interp, newResult);
+ } else {
+ int attrObjc;
+ Tcl_Obj **attrObjv = NULL;
+ WindowClass macClass;
+ UInt64 oldAttributes = wmPtr->attributes;
+ int oldFlags = wmPtr->flags;
+
+ if (Tcl_GetIndexFromObjStruct(interp, objv[3], classMap,
+ sizeof(struct StrIntMap), "class", 0, &index) != TCL_OK) {
+ goto badClassAttrs;
+ }
+ macClass = classMap[index].intValue;
+ if (objc == 5) {
+ if (Tcl_ListObjGetElements(interp, objv[4], &attrObjc, &attrObjv)
+ != TCL_OK) {
+ goto badClassAttrs;
+ }
+ wmPtr->attributes = kWindowNoAttributes;
+ for (i = 0; i < attrObjc; i++) {
+ if (Tcl_GetIndexFromObjStruct(interp, attrObjv[i],
+ compositeAttrMap, sizeof(struct StrIntMap),
+ "attribute", 0, &index) == TCL_OK) {
+ wmPtr->attributes |= compositeAttrMap[index].intValue;
+ } else if (Tcl_GetIndexFromObjStruct(interp, attrObjv[i],
+ attrMap, sizeof(struct StrIntMap),
+ "attribute", 0, &index) == TCL_OK) {
+ Tcl_ResetResult(interp);
+ wmPtr->attributes |= attrMap[index].intValue;
+ } else {
+ goto badClassAttrs;
+ }
+ }
+ } else {
+ wmPtr->attributes = macClassAttrs[macClass].defaultAttrs;
+ }
+ wmPtr->attributes &= (tkAlwaysValidAttributes |
+ macClassAttrs[macClass].validAttrs);
+ wmPtr->flags |= macClassAttrs[macClass].flags;
+ wmPtr->macClass = macClass;
+ ApplyWindowAttributeFlagChanges(winPtr, NULL, oldAttributes, oldFlags,
+ 0, 1);
+ return TCL_OK;
+
+ badClassAttrs:
+ wmPtr->attributes = oldAttributes;
+ return TCL_ERROR;
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmWinTabbingId --
+ *
+ * This procedure is invoked to process the
+ * "::tk::unsupported::MacWindowStyle tabbingid" subcommand. The command
+ * allows you to get or set the tabbingIdentifier for the NSWindow
+ * associated with a Tk Window. The syntax is:
+ *
+ * tk::unsupported::MacWindowStyle tabbingid window ?newId?
+ *
+ * Results:
+ * Returns the tabbingIdentifier of the window prior to calling this
+ * function. If the optional newId argument is omitted, the window's
+ * tabbingIdentifier is not changed.
+ *
+ * Side effects:
+ * Windows may only be grouped together as tabs if they all have the same
+ * tabbingIdentifier. In particular, by giving a window a unique
+ * tabbingIdentifier one can prevent it from becoming a tab in any other
+ * window. Note, however, that changing the tabbingIdentifier of a window
+ * which is already a tab does not cause it to become a separate window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WmWinTabbingId(
+ Tcl_Interp *interp, /* Current interpreter. */
+ TkWindow *winPtr, /* Window to be manipulated. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj * const objv[]) /* Argument objects. */
+{
+#if !(MAC_OS_X_VERSION_MAX_ALLOWED < 101200)
+ Tcl_Obj *result = NULL;
+ NSString *idString;
+ NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
+ if (win) {
+ idString = win.tabbingIdentifier;
+ result = Tcl_NewStringObj(idString.UTF8String, [idString length]);
+ }
+ if (result == NULL) {
+ Tcl_Panic("Failed to read tabbing identifier.");
+ }
+ Tcl_SetObjResult(interp, result);
+ if (objc == 3) {
+ return TCL_OK;
+ } else if (objc == 4) {
+ int len;
+ char *newId = Tcl_GetStringFromObj(objv[3], &len);
+ NSString *newIdString = [NSString stringWithUTF8String:newId];
+ [win setTabbingIdentifier: newIdString];
+
+ /*
+ * If the tabbingIdentifier of a tab is changed we also turn it into a
+ * separate window so we don't violate the rule that all tabs in the
+ * same frame must have the same tabbingIdentifier.
+ */
+
+ if ([idString compare:newIdString] != NSOrderedSame
+#if MAC_OS_X_VERSION_MIN_REQUIRED > 101200
+ && [win tab]
+#endif
+ ) {
+ [win moveTabToNewWindow:nil];
+ }
+ return TCL_OK;
+ }
+#endif
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmWinAppearance --
+ *
+ * This procedure is invoked to process the
+ * "::tk::unsupported::MacWindowStyle appearance" subcommand. The command
+ * allows you to get or set the appearance for the NSWindow associated
+ * with a Tk Window. The syntax is:
+ *
+ * tk::unsupported::MacWindowStyle tabbingid window ?newAppearance?
+ *
+ * Allowed appearance names are "aqua", "darkaqua", and "auto".
+ *
+ * Results:
+ * Returns the appearance setting of the window prior to calling this
+ * function.
+ *
+ * Side effects:
+ * The underlying NSWindow's appearance property is set to the specified
+ * value if the optional newAppearance argument is supplied. Otherwise the
+ * window's appearance property is not changed. If the appearance is set
+ * to aqua or darkaqua then the window will use the associated
+ * NSAppearance even if the user has selected a different appearance with
+ * the system preferences. If it is set to auto then the appearance
+ * property is set to nil, meaning that the preferences will determine the
+ * appearance.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WmWinAppearance(
+ Tcl_Interp *interp, /* Current interpreter. */
+ TkWindow *winPtr, /* Window to be manipulated. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj * const objv[]) /* Argument objects. */
+{
+#if MAC_OS_X_VERSION_MAX_ALLOWED > 1090
+ static const char *const appearanceStrings[] = {
+ "aqua", "darkaqua", "auto", NULL
+ };
+ enum appearances {
+ APPEARANCE_AQUA, APPEARANCE_DARKAQUA, APPEARANCE_AUTO
+ };
+ Tcl_Obj *result = NULL;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101300
+ NSAppearanceName appearance;
+#else
+ NSString *appearance;
+#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101300
+ const char *resultString = "unrecognized";
+ NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
+ if (win) {
+ appearance = win.appearance.name;
+ if (appearance == nil) {
+ resultString = appearanceStrings[APPEARANCE_AUTO];
+ } else if (appearance == NSAppearanceNameAqua) {
+ resultString = appearanceStrings[APPEARANCE_AQUA];
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
+ } else if (@available(macOS 10.14, *)) {
+ if (appearance == NSAppearanceNameDarkAqua) {
+ resultString = appearanceStrings[APPEARANCE_DARKAQUA];
+ }
+#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
+ }
+ result = Tcl_NewStringObj(resultString, strlen(resultString));
+ }
+ if (result == NULL) {
+ Tcl_Panic("Failed to read appearance name.");
+ }
+ if (objc == 4) {
+ int index;
+ if (Tcl_GetIndexFromObjStruct(interp, objv[3], appearanceStrings,
+ sizeof(char *), "appearancename", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch ((enum appearances) index) {
+ case APPEARANCE_AQUA:
+ win.appearance = [NSAppearance appearanceNamed:
+ NSAppearanceNameAqua];
+ break;
+ case APPEARANCE_DARKAQUA:
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
+ if (@available(macOS 10.14, *)) {
+ win.appearance = [NSAppearance appearanceNamed:
+ NSAppearanceNameDarkAqua];
+ }
+#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
+ break;
+ default:
+ win.appearance = nil;
+ }
+ }
+ Tcl_SetObjResult(interp, result);
+ return TCL_OK;
+#else // MAC_OS_X_VERSION_MAX_ALLOWED > 1090
+ return TCL_ERROR;
+#endif
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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. */
+{
+ TkWindow *winPtr = (TkWindow *) tkwin;
+
+ if (transient) {
+ winPtr->wmInfoPtr->macClass = kSimpleWindowClass;
+ winPtr->wmInfoPtr->attributes = kWindowNoActivatesAttribute;
+ } else {
+ winPtr->wmInfoPtr->macClass = kFloatingWindowClass;
+ winPtr->wmInfoPtr->attributes = kWindowStandardFloatingAttributes;
+ winPtr->wmInfoPtr->flags |= WM_WIDTH_NOT_RESIZABLE;
+ winPtr->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;
+ MacDrawable *macWin;
+ WindowClass macClass;
+ Bool overrideRedirect = Tk_Attributes((Tk_Window) winPtr)->override_redirect;
+
+ 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 = TkpGetOtherWindow(winPtr);
+
+ if (contWinPtr != NULL) {
+ TkMacOSXMakeRealWindowExist(
+ contWinPtr->privatePtr->toplevel->winPtr);
+ macWin->flags |= TK_HOST_EXISTS;
+ return;
+ }
+
+ if (tkMacOSXEmbedHandler == NULL) {
+ Tcl_Panic("TkMacOSXMakeRealWindowExist could not find container");
+ }
+ if (tkMacOSXEmbedHandler->containerExistProc &&
+ tkMacOSXEmbedHandler->containerExistProc((Tk_Window) winPtr)
+ != TCL_OK) {
+ Tcl_Panic("ContainerExistProc could not make container");
+ }
+ return;
+
+ /*
+ * TODO: Here we should handle out of process embedding.
+ */
+ }
+
+ /*
+ * If this is an override-redirect window, the NSWindow is created first as
+ * a document window then converted to a simple window.
+ */
+
+ if (overrideRedirect) {
+ wmPtr->macClass = kDocumentWindowClass;
+ }
+ macClass = wmPtr->macClass;
+ wmPtr->attributes &= (tkAlwaysValidAttributes |
+ macClassAttrs[macClass].validAttrs);
+ wmPtr->flags |= macClassAttrs[macClass].flags |
+ ((wmPtr->attributes & kWindowResizableAttribute) ? 0 :
+ WM_WIDTH_NOT_RESIZABLE|WM_HEIGHT_NOT_RESIZABLE);
+ UInt64 attributes = (wmPtr->attributes &
+ ~macClassAttrs[macClass].forceOffAttrs) |
+ macClassAttrs[macClass].forceOnAttrs;
+ NSUInteger styleMask = macClassAttrs[macClass].styleMask |
+ ((attributes & kWindowNoTitleBarAttribute) ? 0 : NSTitledWindowMask) |
+ ((attributes & kWindowCloseBoxAttribute) ? NSClosableWindowMask : 0) |
+ ((attributes & kWindowCollapseBoxAttribute) ?
+ NSMiniaturizableWindowMask : 0) |
+ ((attributes & kWindowResizableAttribute) ? NSResizableWindowMask : 0) |
+ ((attributes & kWindowMetalAttribute) ?
+ NSTexturedBackgroundWindowMask : 0) |
+ ((attributes & kWindowUnifiedTitleAndToolbarAttribute) ?
+ NSUnifiedTitleAndToolbarWindowMask : 0) |
+ ((attributes & kWindowSideTitlebarAttribute) ? 1 << 9 : 0) |
+ (attributes >> WM_NSMASK_SHIFT);
+ Class winClass = (macClass == kDrawerWindowClass ? [NSDrawerWindow class] :
+ (styleMask & (NSUtilityWindowMask|NSDocModalWindowMask|
+ NSNonactivatingPanelMask|NSHUDWindowMask)) ? [NSPanel class] :
+ [TKWindow class]);
+ NSRect structureRect = [winClass frameRectForContentRect:NSZeroRect
+ styleMask:styleMask];
+ NSRect contentRect = NSMakeRect(5 - structureRect.origin.x,
+ tkMacOSXZeroScreenHeight - (tkMacOSXZeroScreenTop + 5 +
+ structureRect.origin.y + structureRect.size.height + 200), 200, 200);
+ NSWindow *window = [[winClass alloc] initWithContentRect:contentRect
+ styleMask:styleMask backing:NSBackingStoreBuffered defer:YES];
+ if (!window) {
+ Tcl_Panic("couldn't allocate new Mac window");
+ }
+ TKContentView *contentView = [[TKContentView alloc]
+ initWithFrame:NSZeroRect];
+ [window setContentView:contentView];
+ [contentView release];
+ [window setDelegate:NSApp];
+ [window setAcceptsMouseMovedEvents:YES];
+ [window setReleasedWhenClosed:NO];
+ if (styleMask & NSUtilityWindowMask) {
+ [(NSPanel*)window setFloatingPanel:YES];
+ }
+ if ((styleMask & (NSTexturedBackgroundWindowMask|NSHUDWindowMask)) &&
+ !(styleMask & NSDocModalWindowMask)) {
+ /*
+ * Workaround for [Bug 2824538]: Textured windows are draggable from
+ * opaque content.
+ */
+ [window setMovableByWindowBackground:NO];
+ }
+ [window setDocumentEdited:NO];
+ wmPtr->window = window;
+ macWin->view = window.contentView;
+ TkMacOSXApplyWindowAttributes(winPtr, window);
+ NSRect geometry = InitialWindowBounds(winPtr, window);
+ geometry.size.width += structureRect.size.width;
+ geometry.size.height += structureRect.size.height;
+ geometry.origin.y = tkMacOSXZeroScreenHeight - (geometry.origin.y +
+ geometry.size.height);
+ [window setFrame:geometry display:YES];
+ TkMacOSXRegisterOffScreenWindow((Window) macWin, window);
+
+ macWin->flags |= TK_HOST_EXISTS;
+ if (overrideRedirect) {
+ XSetWindowAttributes atts;
+
+ atts.override_redirect = True;
+ Tk_ChangeWindowAttributes((Tk_Window) winPtr, CWOverrideRedirect, &atts);
+ ApplyMasterOverrideChanges(winPtr, NULL);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpDisplayWindow --
+ *
+ * Mark the contentView of this window as needing display so the window
+ * will be drawn by the window manager. If this is called within the
+ * drawRect method, do nothing.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The window's contentView is marked as needing display.
+ *
+ *----------------------------------------------------------------------
+ */
+
+MODULE_SCOPE void
+TkpDisplayWindow(Tk_Window tkwin) {
+ if (![NSApp isDrawing]) {
+ TkWindow *winPtr = (TkWindow *) tkwin;
+ NSWindow *w = TkMacOSXDrawableWindow(winPtr->window);
+
+ [[w contentView] setNeedsDisplay: YES];
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXRegisterOffScreenWindow --
+ *
+ * This function adds the passed in Off Screen Port to the hash table that
+ * maps Mac windows to root X windows.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * An entry is added to the windowTable hash table.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXRegisterOffScreenWindow(
+ Window window, /* Window structure. */
+ void *portPtr) /* Pointer to a Mac Window. */
+{
+ Tcl_HashEntry *valueHashPtr;
+ int isNew;
+
+ if (!windowHashInit) {
+ Tcl_InitHashTable(&windowTable, TCL_ONE_WORD_KEYS);
+ windowHashInit = true;
+ }
+ valueHashPtr = Tcl_CreateHashEntry(&windowTable, (char *) portPtr, &isNew);
+ if (!isNew) {
+ Tcl_Panic("Same macintosh window allocated twice!");
+ }
+ Tcl_SetHashValue(valueHashPtr, window);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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(
+ void *macWinPtr) /* Reference to a Mac Window */
+{
+ Tcl_HashEntry *entryPtr;
+
+ if (!windowHashInit) {
+ Tcl_Panic("TkMacOSXUnregisterMacWindow: unmapping before inited");
+ }
+ entryPtr = Tcl_FindHashEntry(&windowTable, macWinPtr);
+ if (!entryPtr) {
+ TkMacOSXDbgMsg("Failed to find window %p", 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(
+ TkWindow *winPtr, /* Toplevel window to operate on. */
+ int state) /* One of IconicState, ZoomState, NormalState,
+ * or WithdrawnState. */
+{
+ WmInfo *wmPtr = winPtr->wmInfoPtr;
+ NSWindow *macWin;
+
+ wmPtr->hints.initial_state = state;
+ if (wmPtr->flags & WM_NEVER_MAPPED) {
+ return;
+ }
+
+ macWin = TkMacOSXDrawableWindow(winPtr->window);
+
+ if (state == WithdrawnState) {
+ Tk_UnmapWindow((Tk_Window) winPtr);
+ } else if (state == IconicState) {
+ /*
+ * The window always gets unmapped. If we can show the icon version of
+ * the window we also collapse it.
+ */
+
+ if (macWin && ([macWin styleMask] & NSMiniaturizableWindowMask) &&
+ ![macWin isMiniaturized]) {
+ [macWin miniaturize:NSApp];
+ }
+ Tk_UnmapWindow((Tk_Window) winPtr);
+ } else if (state == NormalState || state == ZoomState) {
+ Tk_MapWindow((Tk_Window) winPtr);
+ if (macWin && ([macWin styleMask] & NSMiniaturizableWindowMask) &&
+ [macWin isMiniaturized]) {
+ [macWin deminiaturize:NSApp];
+ }
+ TkMacOSXZoomToplevel(macWin, state == NormalState ? inZoomIn :
+ inZoomOut);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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(
+ void *wRef)
+{
+ return [(NSWindow *)wRef level] == kCGFloatingWindowLevel;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXWindowClass --
+ *
+ * Returns OS X window class of window
+ *
+ * Results:
+ * 1 or 0 depending on window's floating attribute.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+MODULE_SCOPE WindowClass
+TkMacOSXWindowClass(
+ TkWindow *winPtr)
+{
+ return winPtr->wmInfoPtr->macClass;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkMacOSXWindowOffset --
+ *
+ * Determines the x and y offset from the orgin of the toplevel window
+ * dressing (the structure region, i.e. title bar) and the orgin of the
+ * content area.
+ *
+ * Results:
+ * The x & y offset in pixels.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXWindowOffset(
+ void *wRef,
+ int *xOffset,
+ int *yOffset)
+{
+ TkWindow *winPtr = TkMacOSXGetTkWindow(wRef);
+
+ if (winPtr && winPtr->wmInfoPtr) {
+ *xOffset = winPtr->wmInfoPtr->xInParent;
+ *yOffset = winPtr->wmInfoPtr->yInParent;
+ } else {
+ *xOffset = 0;
+ *yOffset = 0;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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(void)
+{
+ Tcl_Time now;
+
+ Tcl_GetTime(&now);
+ return (long) now.sec * 1000 + now.usec / 1000;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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 function is called when Tk moves focus from one window to another.
+ * It should be passed a non-embedded TopLevel. That toplevel gets raised
+ * to the top of the Tk stacking order and the associated NSWindow is
+ * ordered Front.
+ *
+ * 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(
+ 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. */
+{
+ if (winPtr->atts.override_redirect) {
+ return 0;
+ }
+
+ if (Tk_IsTopLevel(winPtr) && !Tk_IsEmbedded(winPtr)) {
+ NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
+
+ TkWmRestackToplevel(winPtr, Above, NULL);
+ if (force) {
+ [NSApp activateIgnoringOtherApps:YES];
+ }
+ if (win && [win canBecomeKeyWindow]) {
+ [win makeKeyAndOrderFront:NSApp];
+ }
+ }
+
+ /*
+ * 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);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmStackorderToplevelWrapperMap --
+ *
+ * This procedure will create a table that maps the reparent wrapper X id
+ * for a toplevel to the TkWindow structure that it 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+WmStackorderToplevelWrapperMap(
+ TkWindow *winPtr, /* TkWindow to recurse on */
+ Display *display, /* X display of parent window */
+ Tcl_HashTable *table) /* Maps mac window to TkWindow */
+{
+ TkWindow *childPtr;
+ Tcl_HashEntry *hPtr;
+ int newEntry;
+
+ if (Tk_IsMapped(winPtr) && Tk_IsTopLevel(winPtr)
+ && (winPtr->display == display)) {
+ hPtr = Tcl_CreateHashEntry(table,
+ (char*) TkMacOSXDrawableWindow(winPtr->window), &newEntry);
+ Tcl_SetHashValue(hPtr, winPtr);
+ }
+
+ for (childPtr = winPtr->childList; childPtr != NULL;
+ childPtr = childPtr->nextPtr) {
+ WmStackorderToplevelWrapperMap(childPtr, display, 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(
+ TkWindow *parentPtr) /* Parent toplevel window. */
+{
+ TkWindow *childWinPtr, **windows, **windowPtr;
+ 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);
+ WmStackorderToplevelWrapperMap(parentPtr, parentPtr->display, &table);
+
+ windows = 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] = Tcl_GetHashValue(hPtr);
+ windows[1] = NULL;
+ goto done;
+ }
+
+ NSArray *macWindows = [NSApp orderedWindows];
+ NSInteger windowCount = [macWindows count];
+
+ if (!windowCount) {
+ ckfree(windows);
+ windows = NULL;
+ } else {
+ windowPtr = windows + table.numEntries;
+ *windowPtr-- = NULL;
+ for (NSWindow *w in macWindows) {
+ hPtr = Tcl_FindHashEntry(&table, (char*) w);
+ if (hPtr != NULL) {
+ childWinPtr = Tcl_GetHashValue(hPtr);
+ *windowPtr-- = childWinPtr;
+ }
+ }
+ if (windowPtr != windows-1) {
+ Tcl_Panic("num matched toplevel windows does not equal num "
+ "children");
+ }
+ }
+
+ done:
+ Tcl_DeleteHashTable(&table);
+ return windows;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXApplyWindowAttributes --
+ *
+ * This procedure applies all window attributes to the NSWindow.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXApplyWindowAttributes(
+ TkWindow *winPtr,
+ NSWindow *macWindow)
+{
+ WmInfo *wmPtr = winPtr->wmInfoPtr;
+
+ ApplyWindowAttributeFlagChanges(winPtr, macWindow, 0, 0, 0, 1);
+ if (wmPtr->master != NULL || winPtr->atts.override_redirect) {
+ ApplyMasterOverrideChanges(winPtr, macWindow);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ApplyWindowAttributeFlagChanges --
+ *
+ * This procedure applies window attribute and flag changes.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ApplyWindowAttributeFlagChanges(
+ TkWindow *winPtr,
+ NSWindow *macWindow,
+ UInt64 oldAttributes,
+ int oldFlags,
+ int create,
+ int initial)
+{
+ WmInfo *wmPtr = winPtr->wmInfoPtr;
+ UInt64 newAttributes = ForceAttributes(wmPtr->attributes, wmPtr->macClass);
+ UInt64 changedAttributes = newAttributes ^ ForceAttributes(oldAttributes,
+ wmPtr->macClass);
+
+ if (changedAttributes || wmPtr->flags != oldFlags || initial) {
+ if (!macWindow) {
+ if (winPtr->window == None) {
+ if (!create) {
+ return;
+ }
+ Tk_MakeWindowExist((Tk_Window) winPtr);
+ }
+ if (!TkMacOSXHostToplevelExists(winPtr)) {
+ if (!create) {
+ return;
+ }
+ TkMacOSXMakeRealWindowExist(winPtr);
+ }
+ macWindow = TkMacOSXDrawableWindow(winPtr->window);
+ }
+ if ((changedAttributes & kWindowCloseBoxAttribute) || initial) {
+ [[macWindow standardWindowButton:NSWindowCloseButton]
+ setEnabled:!!(newAttributes & kWindowCloseBoxAttribute)];
+ }
+ if ((changedAttributes & kWindowCollapseBoxAttribute) || initial) {
+ [[macWindow standardWindowButton:NSWindowMiniaturizeButton]
+ setEnabled:!!(newAttributes & kWindowCollapseBoxAttribute)];
+ }
+ if ((changedAttributes & (kWindowResizableAttribute |
+ kWindowFullZoomAttribute)) || initial) {
+ [macWindow setShowsResizeIndicator:
+ !!(newAttributes & kWindowResizableAttribute)];
+ [[macWindow standardWindowButton:NSWindowZoomButton]
+ setEnabled:(newAttributes & kWindowResizableAttribute) &&
+ (newAttributes & kWindowFullZoomAttribute)];
+ if (newAttributes & kWindowHorizontalZoomAttribute) {
+ wmPtr->flags &= ~(WM_WIDTH_NOT_RESIZABLE);
+ } else {
+ wmPtr->flags |= (WM_WIDTH_NOT_RESIZABLE);
+ }
+ if (newAttributes & kWindowVerticalZoomAttribute) {
+ wmPtr->flags &= ~(WM_HEIGHT_NOT_RESIZABLE);
+ } else {
+ wmPtr->flags |= (WM_HEIGHT_NOT_RESIZABLE);
+ }
+ WmUpdateGeom(wmPtr, winPtr);
+ }
+ if ((changedAttributes & kWindowToolbarButtonAttribute) || initial) {
+ [macWindow setShowsToolbarButton:
+ !!(newAttributes & kWindowToolbarButtonAttribute)];
+ if ((newAttributes & kWindowToolbarButtonAttribute) &&
+ ![macWindow toolbar]) {
+ NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@""];
+
+ [toolbar setVisible:NO];
+ [macWindow setToolbar:toolbar];
+ [toolbar release];
+ NSCell *toolbarButtonCell = [[macWindow standardWindowButton:
+ NSWindowToolbarButton] cell];
+ [toolbarButtonCell setTarget:[macWindow contentView]];
+ [toolbarButtonCell setAction:@selector(tkToolbarButton:)];
+ }
+ }
+ if ((changedAttributes & kWindowNoShadowAttribute) || initial) {
+ [macWindow setHasShadow:
+ !(newAttributes & kWindowNoShadowAttribute)];
+ }
+ if ((changedAttributes & kWindowHideOnSuspendAttribute) || initial) {
+ [macWindow setHidesOnDeactivate:
+ !!(newAttributes & kWindowHideOnSuspendAttribute)];
+ }
+ if ((changedAttributes & kWindowInWindowMenuAttribute) || initial) {
+ [macWindow setExcludedFromWindowsMenu:
+ !(newAttributes & kWindowInWindowMenuAttribute)];
+ }
+ if ((changedAttributes & kWindowIgnoreClicksAttribute) || initial) {
+ [macWindow setIgnoresMouseEvents:
+ !!(newAttributes & kWindowIgnoreClicksAttribute)];
+ }
+ if ((changedAttributes & tkWindowDoesNotHideAttribute) || initial) {
+ [macWindow setCanHide:
+ !(newAttributes & tkWindowDoesNotHideAttribute)];
+ }
+ if ((changedAttributes & (kWindowDoesNotCycleAttribute |
+ tkCanJoinAllSpacesAttribute | tkMoveToActiveSpaceAttribute)) ||
+ initial) {
+ NSWindowCollectionBehavior b = NSWindowCollectionBehaviorDefault;
+
+ /*
+ * This behavior, which makes the green button expand a window to
+ * full screen, was included in the default as of OSX 10.13. For
+ * uniformity we use the new default in all versions of the OS
+ * after 10.10.
+ */
+
+#if !(MAC_OS_X_VERSION_MAX_ALLOWED < 101000)
+ if (!(macWindow.styleMask & NSUtilityWindowMask)) {
+ /*
+ * Exclude overrideredirect, transient, and "help"-styled
+ * windows from moving into their own fullscreen space.
+ */
+
+ if ((winPtr->atts.override_redirect) ||
+ (wmPtr->master != NULL) ||
+ (winPtr->wmInfoPtr->macClass == kHelpWindowClass)) {
+ b |= (NSWindowCollectionBehaviorCanJoinAllSpaces |
+ NSWindowCollectionBehaviorFullScreenAuxiliary);
+ } else {
+ NSSize screenSize = [[macWindow screen] frame].size;
+ b |= NSWindowCollectionBehaviorFullScreenPrimary;
+
+ /*
+ * The default max size has height less than the screen
+ * height. This causes the window manager to refuse to
+ * allow the window to be resized when it is a split
+ * window. To work around this we make the max size equal
+ * to the screen size. (For 10.11 and up, only)
+ */
+ if ([NSApp macMinorVersion] > 10) {
+ [macWindow setMaxFullScreenContentSize:screenSize];
+ }
+ }
+ }
+#endif
+
+ if (newAttributes & tkCanJoinAllSpacesAttribute) {
+ b |= NSWindowCollectionBehaviorCanJoinAllSpaces;
+ } else if (newAttributes & tkMoveToActiveSpaceAttribute) {
+ b |= NSWindowCollectionBehaviorMoveToActiveSpace;
+ }
+ if (newAttributes & kWindowDoesNotCycleAttribute) {
+ b |= NSWindowCollectionBehaviorIgnoresCycle;
+ } else {
+ b |= NSWindowCollectionBehaviorParticipatesInCycle;
+ }
+ [macWindow setCollectionBehavior:b];
+ }
+ if ((wmPtr->flags & WM_TOPMOST) != (oldFlags & WM_TOPMOST)) {
+ [macWindow setLevel:(wmPtr->flags & WM_TOPMOST) ?
+ kCGUtilityWindowLevel : ([macWindow isKindOfClass:
+ [NSPanel class]] && [macWindow isFloatingPanel] ?
+ kCGFloatingWindowLevel : kCGNormalWindowLevel)];
+ }
+
+ /*
+ * The change of window class/attributes might have changed the window
+ * frame geometry:
+ */
+
+ NSRect structureRect = [macWindow frameRectForContentRect:NSZeroRect];
+
+ wmPtr->xInParent = -structureRect.origin.x;
+ wmPtr->yInParent = structureRect.origin.y + structureRect.size.height;
+ wmPtr->parentWidth = winPtr->changes.width + structureRect.size.width;
+ wmPtr->parentHeight = winPtr->changes.height + structureRect.size.height;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ApplyMasterOverrideChanges --
+ *
+ * This procedure applies changes to override_redirect or master.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ApplyMasterOverrideChanges(
+ TkWindow *winPtr,
+ NSWindow *macWindow)
+{
+ WmInfo *wmPtr = winPtr->wmInfoPtr;
+ UInt64 oldAttributes = wmPtr->attributes;
+ int oldFlags = wmPtr->flags;
+ unsigned long styleMask;
+ NSRect structureRect;
+ NSWindow *parentWindow;
+
+ if (!macWindow && winPtr->window != None &&
+ TkMacOSXHostToplevelExists(winPtr)) {
+ macWindow = TkMacOSXDrawableWindow(winPtr->window);
+ }
+ styleMask = [macWindow styleMask];
+
+ /*
+ * FIX: We need an UpdateWrapper equivalent to make this 100% correct
+ */
+
+ if (winPtr->atts.override_redirect) {
+ if (wmPtr->macClass == kDocumentWindowClass) {
+ wmPtr->macClass = kSimpleWindowClass;
+ wmPtr->attributes = macClassAttrs[kSimpleWindowClass].defaultAttrs;
+ }
+ wmPtr->attributes |= kWindowNoActivatesAttribute;
+ if ([NSApp macMinorVersion] == 6) {
+ styleMask = 0;
+ } else {
+ styleMask &= ~NSTitledWindowMask;
+ }
+ } else {
+ if (wmPtr->macClass == kSimpleWindowClass &&
+ oldAttributes == kWindowNoActivatesAttribute) {
+ wmPtr->macClass = kDocumentWindowClass;
+ wmPtr->attributes =
+ macClassAttrs[kDocumentWindowClass].defaultAttrs;
+ }
+ wmPtr->attributes &= ~kWindowNoActivatesAttribute;
+ if ([NSApp macMinorVersion] == 6) {
+ styleMask = NSTitledWindowMask |
+ NSClosableWindowMask |
+ NSMiniaturizableWindowMask |
+ NSResizableWindowMask;
+ } else {
+ styleMask |= NSTitledWindowMask;
+ }
+ }
+ if (macWindow) {
+ structureRect = [NSWindow frameRectForContentRect:NSZeroRect
+ styleMask:styleMask];
+
+ /*
+ * Synchronize the wmInfoPtr to match the new window configuration
+ * so windowBoundsChanged won't corrupt the window manager info.
+ */
+
+ wmPtr->xInParent = -structureRect.origin.x;
+ wmPtr->yInParent = structureRect.origin.y + structureRect.size.height;
+ wmPtr->parentWidth = winPtr->changes.width + structureRect.size.width;
+ wmPtr->parentHeight = winPtr->changes.height + structureRect.size.height;
+ if (winPtr->atts.override_redirect) {
+ [macWindow setExcludedFromWindowsMenu:YES];
+ [macWindow setStyleMask:styleMask];
+ if (wmPtr->hints.initial_state == NormalState) {
+ [macWindow orderFront:nil];
+ }
+ if (wmPtr->master != NULL) {
+ wmPtr->flags |= WM_TOPMOST;
+ } else {
+ wmPtr->flags &= ~WM_TOPMOST;
+ }
+ } else {
+ const char *title = winPtr->wmInfoPtr->titleUid;
+
+ if (!title) {
+ title = winPtr->nameUid;
+ }
+ [macWindow setStyleMask:styleMask];
+ [macWindow setTitle:[NSString stringWithUTF8String:title]];
+ [macWindow setExcludedFromWindowsMenu:NO];
+ wmPtr->flags &= ~WM_TOPMOST;
+ }
+ if (wmPtr->master != None) {
+ TkWindow *masterWinPtr = (TkWindow *) wmPtr->master;
+
+ if (masterWinPtr && (masterWinPtr->window != None)
+ && TkMacOSXHostToplevelExists(masterWinPtr)) {
+ NSWindow *masterMacWin = TkMacOSXDrawableWindow(
+ masterWinPtr->window);
+
+ /*
+ * Try to add the transient window as a child window of the
+ * master. A child NSWindow retains its relative position with
+ * respect to the parent when the parent is moved. This is
+ * pointless if the parent is offscreen, and adding a child to
+ * an offscreen window causes the parent to be displayed as a
+ * zombie. So we only do this if the parent is visible.
+ */
+
+ if (masterMacWin && [masterMacWin isVisible]
+ && (winPtr->flags & TK_MAPPED)) {
+ /*
+ * If the transient is already a child of some other window,
+ * remove it.
+ */
+
+ parentWindow = [macWindow parentWindow];
+ if (parentWindow && parentWindow != masterMacWin) {
+ [parentWindow removeChildWindow:macWindow];
+ }
+
+ [masterMacWin addChildWindow:macWindow
+ ordered:NSWindowAbove];
+ }
+ }
+ } else {
+ parentWindow = [macWindow parentWindow];
+ if (parentWindow) {
+ [parentWindow removeChildWindow:macWindow];
+ }
+ }
+ if (wmPtr->flags & WM_TOPMOST) {
+ [macWindow setLevel:kCGUtilityWindowLevel];
+ }
+ ApplyWindowAttributeFlagChanges(winPtr, macWindow, oldAttributes,
+ oldFlags, 0, 0);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetMinSize --
+ *
+ * This function computes the current minWidth and minHeight values for a
+ * window, taking into account the possibility that they may be
+ * defaulted.
+ *
+ * Results:
+ * The values at *minWidthPtr and *minHeightPtr are filled in with the
+ * minimum allowable dimensions of wmPtr's window, in grid units. If the
+ * requested minimum is smaller than the system required minimum, then
+ * this function computes the smallest size that will satisfy both the
+ * system and the grid constraints.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GetMinSize(
+ TkWindow *winPtr, /* Toplevel window to operate on. */
+ int *minWidthPtr, /* Where to store the current minimum width of
+ * the window. */
+ int *minHeightPtr) /* Where to store the current minimum height
+ * of the window. */
+{
+ WmInfo *wmPtr = winPtr->wmInfoPtr;
+ int minWidth = 1, minHeight = 1;
+
+ /*
+ * Compute the minimum width & height by taking the default client size and
+ * rounding it up to the nearest grid unit. Return the greater of the
+ * default minimum and the specified minimum.
+ */
+
+ switch (wmPtr->macClass) {
+ case kDocumentWindowClass:
+ case kMovableAlertWindowClass:
+ case kMovableModalWindowClass:
+ minWidth = 72;
+ if (wmPtr->attributes & kWindowResizableAttribute) {
+ minHeight = 15;
+ }
+ if (wmPtr->attributes & kWindowToolbarButtonAttribute) {
+ minWidth += 29;
+ }
+ break;
+ case kFloatingWindowClass:
+ case kUtilityWindowClass:
+ minWidth = 59;
+ if (wmPtr->attributes & kWindowResizableAttribute) {
+ minHeight = 11;
+ }
+ if (wmPtr->attributes & kWindowSideTitlebarAttribute) {
+ int tmp = minWidth;
+
+ minWidth = minHeight;
+ minHeight = tmp;
+ } else if (wmPtr->attributes & kWindowToolbarButtonAttribute) {
+ minWidth += 29;
+ }
+ break;
+ default:
+ if (wmPtr->attributes & kWindowResizableAttribute) {
+ minWidth = 15;
+ minHeight = 15;
+ }
+ break;
+ }
+
+ if (wmPtr->gridWin != NULL) {
+ int base = winPtr->reqWidth - (wmPtr->reqGridWidth * wmPtr->widthInc);
+
+ if (base < 0) {
+ base = 0;
+ }
+ minWidth = ((minWidth - base) + wmPtr->widthInc-1)/wmPtr->widthInc;
+ base = winPtr->reqHeight - (wmPtr->reqGridHeight * wmPtr->heightInc);
+ if (base < 0) {
+ base = 0;
+ }
+ minHeight = ((minHeight - base) + wmPtr->heightInc-1)/wmPtr->heightInc;
+ }
+ if (minWidth < wmPtr->minWidth) {
+ minWidth = wmPtr->minWidth;
+ }
+ if (minHeight < wmPtr->minHeight) {
+ minHeight = wmPtr->minHeight;
+ }
+ *minWidthPtr = minWidth;
+ *minHeightPtr = minHeight;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetMaxSize --
+ *
+ * This function computes the current maxWidth and maxHeight values for a
+ * window, taking into account the possibility that they may be
+ * defaulted.
+ *
+ * Results:
+ * The values at *maxWidthPtr and *maxHeightPtr are filled in with the
+ * maximum allowable dimensions of wmPtr's window, in grid units. If no
+ * maximum has been specified for the window, then this function computes
+ * the largest sizes that will fit on the screen.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GetMaxSize(
+ TkWindow *winPtr, /* Toplevel window to operate on. */
+ int *maxWidthPtr, /* Where to store the current maximum width of
+ * the window. */
+ int *maxHeightPtr) /* Where to store the current maximum height
+ * of the window. */
+{
+ WmInfo *wmPtr = winPtr->wmInfoPtr;
+ NSRect *maxBounds = (NSRect*)(winPtr->display->screens->ext_data);
+
+ if (wmPtr->maxWidth > 0) {
+ *maxWidthPtr = wmPtr->maxWidth;
+ } else {
+ int maxWidth = maxBounds->size.width - wmPtr->xInParent;
+
+ if (wmPtr->gridWin != NULL) {
+ maxWidth = wmPtr->reqGridWidth
+ + (maxWidth - winPtr->reqWidth)/wmPtr->widthInc;
+ }
+ *maxWidthPtr = maxWidth;
+ }
+ if (wmPtr->maxHeight > 0) {
+ *maxHeightPtr = wmPtr->maxHeight;
+ } else {
+ int maxHeight = maxBounds->size.height - wmPtr->yInParent;
+
+ if (wmPtr->gridWin != NULL) {
+ maxHeight = wmPtr->reqGridHeight
+ + (maxHeight - winPtr->reqHeight)/wmPtr->heightInc;
+ }
+ *maxHeightPtr = maxHeight;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * RemapWindows
+ *
+ * Adjust parent/child relation ships of the given window hierarchy.
+ *
+ * Results:
+ * none
+ *
+ * Side effects:
+ * keeps windowing system (X11) happy
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+RemapWindows(
+ TkWindow *winPtr,
+ MacDrawable *parentWin)
+{
+ TkWindow *childPtr;
+
+ /*
+ * Remove the OS specific window. It will get rebuilt when the window gets
+ * Mapped.
+ */
+
+ if (winPtr->window != None) {
+ MacDrawable *macWin = (MacDrawable *) winPtr->window;
+
+ macWin->toplevel->referenceCount--;
+ macWin->toplevel = parentWin->toplevel;
+ macWin->toplevel->referenceCount++;
+ winPtr->flags &= ~TK_MAPPED;
+#ifdef TK_REBUILD_TOPLEVEL
+ winPtr->flags |= TK_REBUILD_TOPLEVEL;
+#endif
+ }
+
+ /*
+ * Repeat for all the children.
+ */
+
+ for (childPtr = winPtr->childList; childPtr != NULL;
+ childPtr = childPtr->nextPtr) {
+ RemapWindows(childPtr, (MacDrawable *) winPtr->window);
+ }
+}
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXWm.h b/tk8.6/macosx/tkMacOSXWm.h
new file mode 100644
index 0000000..20bbb6d
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXWm.h
@@ -0,0 +1,277 @@
+/*
+ * tkMacOSXWm.h --
+ *
+ * Declarations of Macintosh specific window manager structures.
+ *
+ * Copyright 2001-2009, Apple Inc.
+ * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef _TKMACWM
+#define _TKMACWM
+
+#include "tkMacOSXInt.h"
+#include "tkMenu.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; /* 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;
+
+/* The following data structure is used in the TkWmInfo to maintain a list of all of the
+ * transient windows belonging to a given master.
+ */
+
+typedef struct Transient {
+ TkWindow *winPtr;
+ int flags;
+ struct Transient *nextPtr;
+} Transient;
+
+#define WITHDRAWN_BY_MASTER 0x1
+
+/*
+ * 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. */
+ Tk_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. */
+ 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. */
+ Transient *transientPtr; /* First item in a list of all transient windows
+ * belonging to this window, or NULL if there
+ * are no transients. */
+
+ /*
+ * 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 configX, configY; /* x,y position of toplevel when window is
+ * switched into fullscreen state, */
+ 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 OS. 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). */
+ Tcl_Obj *commandObj; /* The command (guaranteed to be a list) for
+ * 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.
+ */
+
+ WindowClass macClass;
+ UInt64 attributes, configAttributes;
+ TkWindow *scrollWinPtr; /* Ptr to scrollbar handling grow widget. */
+ TkMenu *menuPtr;
+ NSWindow *window;
+
+ /*
+ * Space to cache current window state when window becomes Fullscreen.
+ */
+
+ unsigned long cachedStyle;
+ unsigned long cachedPresentation;
+ NSRect cachedBounds;
+
+} 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 0x0001
+#define WM_UPDATE_PENDING 0x0002
+#define WM_NEGATIVE_X 0x0004
+#define WM_NEGATIVE_Y 0x0008
+#define WM_UPDATE_SIZE_HINTS 0x0010
+#define WM_SYNC_PENDING 0x0020
+#define WM_VROOT_OFFSET_STALE 0x0040
+#define WM_ABOUT_TO_MAP 0x0080
+#define WM_MOVE_PENDING 0x0100
+#define WM_COLORMAPS_EXPLICIT 0x0200
+#define WM_ADDED_TOPLEVEL_COLORMAP 0x0400
+#define WM_WIDTH_NOT_RESIZABLE 0x0800
+#define WM_HEIGHT_NOT_RESIZABLE 0x1000
+#define WM_TOPMOST 0x2000
+#define WM_FULLSCREEN 0x4000
+#define WM_TRANSPARENT 0x8000
+
+#endif /* _TKMACWM */
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/tkMacOSXXCursors.h b/tk8.6/macosx/tkMacOSXXCursors.h
new file mode 100644
index 0000000..1363bee
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXXCursors.h
@@ -0,0 +1,711 @@
+/*
+ * tkMacOSXXCursors.h --
+ *
+ * This file defines a set of Macintosh cursors 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.
+ * Copyright 2008-2009, Apple Inc.
+ * Copyright (c) 2008-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+static const unsigned char tkMacOSXXCursors[][68] = {
+
+#define TK_MAC_XCURSOR_X_cursor 0
+[TK_MAC_XCURSOR_X_cursor] = {
+ 0xE0, 0x07, 0xF0, 0x0F, 0xF8, 0x1F, 0x7C, 0x3E, 0x3E, 0x7C, 0x1F, 0xF8, 0x0F, 0xF0, 0x07, 0xE0,
+ 0x07, 0xE0, 0x0F, 0xF0, 0x1F, 0xF8, 0x3E, 0x7C, 0x7C, 0x3E, 0xF8, 0x1F, 0xF0, 0x0F, 0xE0, 0x07,
+ 0xE0, 0x07, 0xF0, 0x0F, 0xF8, 0x1F, 0x7C, 0x3E, 0x3E, 0x7C, 0x1F, 0xF8, 0x0F, 0xF0, 0x07, 0xE0,
+ 0x07, 0xE0, 0x0F, 0xF0, 0x1F, 0xF8, 0x3E, 0x7C, 0x7C, 0x3E, 0xF8, 0x1F, 0xF0, 0x0F, 0xE0, 0x07,
+ 0x00, 0x07, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_arrow 1
+[TK_MAC_XCURSOR_arrow] = {
+ 0x00, 0x00, 0x00, 0x06, 0x00, 0x1E, 0x00, 0x7C, 0x01, 0xFC, 0x07, 0xF8, 0x00, 0xF8, 0x01, 0xF0,
+ 0x03, 0xB0, 0x07, 0x20, 0x0E, 0x20, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x1F, 0x00, 0x7F, 0x01, 0xFE, 0x07, 0xFE, 0x1F, 0xFC, 0x7F, 0xFC, 0x03, 0xF8,
+ 0x07, 0xF8, 0x0F, 0xF0, 0x1F, 0x70, 0x3E, 0x60, 0x7C, 0x60, 0xF8, 0x40, 0x70, 0x40, 0x20, 0x00,
+ 0x00, 0x01, 0x00, 0x0E,
+},
+
+#define TK_MAC_XCURSOR_based_arrow_down 2
+[TK_MAC_XCURSOR_based_arrow_down] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x1F, 0xE0, 0x03, 0x00, 0x03, 0x00,
+ 0x03, 0x00, 0x0B, 0x40, 0x07, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x1F, 0xE0, 0x07, 0x80, 0x07, 0x80,
+ 0x3F, 0xF0, 0x1F, 0xE0, 0x0F, 0xC0, 0x07, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0B, 0x00, 0x06,
+},
+
+#define TK_MAC_XCURSOR_based_arrow_up 3
+[TK_MAC_XCURSOR_based_arrow_up] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x07, 0x80, 0x0B, 0x40, 0x03, 0x00,
+ 0x03, 0x00, 0x03, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x07, 0x80, 0x0F, 0xC0, 0x1F, 0xE0, 0x3F, 0xF0,
+ 0x07, 0x80, 0x07, 0x80, 0x1F, 0xE0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x04, 0x00, 0x06,
+},
+
+#define TK_MAC_XCURSOR_boat 4
+[TK_MAC_XCURSOR_boat] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0xC0, 0x84, 0x60, 0xFF, 0xFF,
+ 0x00, 0x18, 0x00, 0x20, 0x00, 0x40, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0xC0, 0x87, 0xE0, 0xFF, 0xFF,
+ 0xFF, 0xF8, 0xFF, 0xE0, 0xFF, 0xC0, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x0F,
+},
+
+#define TK_MAC_XCURSOR_bogosity 5
+[TK_MAC_XCURSOR_bogosity] = {
+ 0x00, 0x00, 0x71, 0x1C, 0x11, 0x10, 0x11, 0x10, 0x11, 0x10, 0x7F, 0xFC, 0x51, 0x14, 0x51, 0x14,
+ 0x51, 0x14, 0x51, 0x14, 0x7F, 0xFC, 0x11, 0x10, 0x11, 0x10, 0x11, 0x10, 0x71, 0x1C, 0x00, 0x00,
+ 0x00, 0x00, 0x71, 0x1C, 0x11, 0x10, 0x11, 0x10, 0x11, 0x10, 0x7F, 0xFC, 0x7F, 0xFC, 0x7F, 0xFC,
+ 0x7F, 0xFC, 0x7F, 0xFC, 0x7F, 0xFC, 0x11, 0x10, 0x11, 0x10, 0x11, 0x10, 0x71, 0x1C, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_bottom_left_corner 6
+[TK_MAC_XCURSOR_bottom_left_corner] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0xC0, 0x20, 0xC8, 0x40, 0xC8, 0x80,
+ 0xC9, 0x00, 0xCA, 0x00, 0xCC, 0x00, 0xCF, 0xC0, 0xC0, 0x00, 0xC0, 0x00, 0xFF, 0xF0, 0xFF, 0xF0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0xC0, 0x20, 0xC8, 0x40, 0xC8, 0x80,
+ 0xC9, 0x00, 0xCA, 0x00, 0xCC, 0x00, 0xCF, 0xC0, 0xC0, 0x00, 0xC0, 0x00, 0xFF, 0xF0, 0xFF, 0xF0,
+ 0x00, 0x0F, 0x00, 0x00,
+},
+
+#define TK_MAC_XCURSOR_bottom_right_corner 7
+[TK_MAC_XCURSOR_bottom_right_corner] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x03, 0x02, 0x13, 0x01, 0x13,
+ 0x00, 0x93, 0x00, 0x53, 0x00, 0x33, 0x03, 0xF3, 0x00, 0x03, 0x00, 0x03, 0x0F, 0xFF, 0x0F, 0xFF,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x03, 0x02, 0x13, 0x01, 0x13,
+ 0x00, 0x93, 0x00, 0x53, 0x00, 0x33, 0x03, 0xF3, 0x00, 0x03, 0x00, 0x03, 0x0F, 0xFF, 0x0F, 0xFF,
+ 0x00, 0x0F, 0x00, 0x0F,
+},
+
+#define TK_MAC_XCURSOR_bottom_side 8
+[TK_MAC_XCURSOR_bottom_side] = {
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x11, 0x10,
+ 0x09, 0x20, 0x05, 0x40, 0x03, 0x80, 0x01, 0x00, 0x00, 0x00, 0x7F, 0xFC, 0x7F, 0xFC, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x11, 0x10,
+ 0x09, 0x20, 0x05, 0x40, 0x03, 0x80, 0x01, 0x00, 0x00, 0x00, 0x7F, 0xFC, 0x7F, 0xFC, 0x00, 0x00,
+ 0x00, 0x0B, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_bottom_tee 9
+[TK_MAC_XCURSOR_bottom_tee] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,
+ 0x01, 0x80, 0x01, 0x80, 0x7F, 0xFE, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,
+ 0x01, 0x80, 0x01, 0x80, 0x7F, 0xFE, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0B, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_box_spiral 10
+[TK_MAC_XCURSOR_box_spiral] = {
+ 0xFF, 0xFE, 0x80, 0x00, 0xBF, 0xFE, 0xA0, 0x02, 0xAF, 0xFA, 0xA8, 0x0A, 0xAB, 0xEA, 0xAA, 0x2A,
+ 0xAA, 0xAA, 0xAB, 0xAA, 0xA8, 0x2A, 0xAF, 0xEA, 0xA0, 0x0A, 0xBF, 0xFA, 0x80, 0x02, 0xFF, 0xFE,
+ 0xFF, 0xFE, 0x80, 0x00, 0xBF, 0xFE, 0xA0, 0x02, 0xAF, 0xFA, 0xA8, 0x0A, 0xAB, 0xEA, 0xAA, 0x2A,
+ 0xAA, 0xAA, 0xAB, 0xAA, 0xA8, 0x2A, 0xAF, 0xEA, 0xA0, 0x0A, 0xBF, 0xFA, 0x80, 0x02, 0xFF, 0xFE,
+ 0x00, 0x08, 0x00, 0x08,
+},
+
+#define TK_MAC_XCURSOR_center_ptr 11
+[TK_MAC_XCURSOR_center_ptr] = {
+ 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x07, 0x80, 0x07, 0x80, 0x0F, 0xC0, 0x0F, 0xC0, 0x1F, 0xE0,
+ 0x1F, 0xE0, 0x33, 0x30, 0x23, 0x10, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x07, 0x80, 0x07, 0x80, 0x0F, 0xC0, 0x0F, 0xC0, 0x1F, 0xE0, 0x1F, 0xE0, 0x3F, 0xF0,
+ 0x3F, 0xF0, 0x7F, 0xF8, 0x77, 0xB8, 0x67, 0x98, 0x07, 0x80, 0x07, 0x80, 0x07, 0x80, 0x07, 0x80,
+ 0x00, 0x01, 0x00, 0x06,
+},
+
+#define TK_MAC_XCURSOR_circle 12
+[TK_MAC_XCURSOR_circle] = {
+ 0x00, 0x00, 0x03, 0xC0, 0x0F, 0xF0, 0x1F, 0xF8, 0x3C, 0x3C, 0x38, 0x1C, 0x70, 0x0E, 0x70, 0x0E,
+ 0x70, 0x0E, 0x70, 0x0E, 0x38, 0x1C, 0x3C, 0x3C, 0x1F, 0xF8, 0x0F, 0xF0, 0x03, 0xC0, 0x00, 0x00,
+ 0x03, 0xC0, 0x0F, 0xF0, 0x1F, 0xF8, 0x3F, 0xFC, 0x7F, 0xFE, 0x7C, 0x3E, 0xF8, 0x1F, 0xF8, 0x1F,
+ 0xF8, 0x1F, 0xF8, 0x1F, 0x7C, 0x3E, 0x7F, 0xFE, 0x3F, 0xFC, 0x1F, 0xF8, 0x0F, 0xF0, 0x03, 0xC0,
+ 0x00, 0x07, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_clock 13
+[TK_MAC_XCURSOR_clock] = {
+ 0x1F, 0xF8, 0x33, 0xCC, 0x64, 0x66, 0x49, 0x92, 0x4F, 0x12, 0x44, 0x22, 0x63, 0xC6, 0x3F, 0xFC,
+ 0x29, 0x94, 0x29, 0x94, 0x29, 0x94, 0x2B, 0xD4, 0x69, 0x96, 0x78, 0x1E, 0x7F, 0xFE, 0x7F, 0xFE,
+ 0x1F, 0xF8, 0x3F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x3F, 0xFC,
+ 0x3F, 0xFC, 0x3F, 0xFC, 0x3F, 0xFC, 0x3F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE,
+ 0x00, 0x04, 0x00, 0x08,
+},
+
+#define TK_MAC_XCURSOR_coffee_mug 14
+[TK_MAC_XCURSOR_coffee_mug] = {
+ 0x03, 0xF8, 0x0C, 0x06, 0x10, 0x01, 0x1C, 0x07, 0x33, 0xF9, 0x70, 0x01, 0xD0, 0x01, 0x90, 0x01,
+ 0x96, 0x0D, 0xDA, 0x55, 0x7A, 0x55, 0x36, 0xED, 0x10, 0xA1, 0x10, 0x01, 0x08, 0x02, 0x07, 0xFC,
+ 0x03, 0xF8, 0x0F, 0xFE, 0x1F, 0xFF, 0x1F, 0xFF, 0x3F, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x3F, 0xFF, 0x1F, 0xFF, 0x1F, 0xFF, 0x0F, 0xFE, 0x07, 0xFC,
+ 0x00, 0x04, 0x00, 0x03,
+},
+
+#define TK_MAC_XCURSOR_cross 15
+[TK_MAC_XCURSOR_cross] = {
+ 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0xFE, 0xFE, 0x00, 0x00,
+ 0xFE, 0xFE, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x00, 0x00,
+ 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0xFF, 0xFE, 0xFF, 0xFE,
+ 0xFF, 0xFE, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_cross_reverse 16
+[TK_MAC_XCURSOR_cross_reverse] = {
+ 0x42, 0x84, 0xA2, 0x8A, 0x52, 0x94, 0x2A, 0xA8, 0x16, 0xD0, 0x0A, 0xA0, 0xFD, 0x7E, 0x02, 0x80,
+ 0xFD, 0x7E, 0x0A, 0xA0, 0x16, 0xD0, 0x2A, 0xA8, 0x52, 0x94, 0xA2, 0x8A, 0x42, 0x84, 0x00, 0x00,
+ 0x43, 0x84, 0xE3, 0x8E, 0x73, 0x9C, 0x3B, 0xB8, 0x1F, 0xF0, 0x0F, 0xE0, 0xFF, 0xFE, 0xFF, 0xFE,
+ 0xFF, 0xFE, 0x0F, 0xE0, 0x1F, 0xF0, 0x3B, 0xB8, 0x73, 0x9C, 0xE3, 0x8E, 0x43, 0x84, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_crosshair 17
+[TK_MAC_XCURSOR_crosshair] = {
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0xFE, 0xFE,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0xFE, 0xFE,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_diamond_cross 18
+[TK_MAC_XCURSOR_diamond_cross] = {
+ 0x02, 0x80, 0x06, 0xC0, 0x0A, 0xA0, 0x12, 0x90, 0x22, 0x88, 0x42, 0x84, 0xFE, 0xFE, 0x00, 0x00,
+ 0xFE, 0xFE, 0x42, 0x84, 0x22, 0x88, 0x12, 0x90, 0x0A, 0xA0, 0x06, 0xC0, 0x02, 0x80, 0x00, 0x00,
+ 0x02, 0x80, 0x06, 0xC0, 0x0E, 0xE0, 0x1E, 0xF0, 0x3E, 0xF8, 0x7E, 0xFC, 0xFE, 0xFE, 0x00, 0x00,
+ 0xFE, 0xFE, 0x7E, 0xFC, 0x3E, 0xF8, 0x1E, 0xF0, 0x0E, 0xE0, 0x06, 0xC0, 0x02, 0x80, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_dot 19
+[TK_MAC_XCURSOR_dot] = {
+ 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x1F, 0xE0, 0x1F, 0xE0, 0x3F, 0xF0, 0x3F, 0xF0, 0x3F, 0xF0,
+ 0x3F, 0xF0, 0x1F, 0xE0, 0x1F, 0xE0, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x07, 0x80, 0x1F, 0xE0, 0x3F, 0xF0, 0x3F, 0xF0, 0x7F, 0xF8, 0x7F, 0xF8, 0x7F, 0xF8,
+ 0x7F, 0xF8, 0x3F, 0xF0, 0x3F, 0xF0, 0x1F, 0xE0, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x06, 0x00, 0x06,
+},
+
+#define TK_MAC_XCURSOR_dotbox 20
+[TK_MAC_XCURSOR_dotbox] = {
+ 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFC, 0x20, 0x04, 0x20, 0x04, 0x20, 0x04, 0x20, 0x04, 0x21, 0x84,
+ 0x21, 0x84, 0x20, 0x04, 0x20, 0x04, 0x20, 0x04, 0x20, 0x04, 0x3F, 0xFC, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFC, 0x3F, 0xFC, 0x30, 0x0C, 0x30, 0x0C, 0x31, 0x8C, 0x33, 0xCC,
+ 0x33, 0xCC, 0x31, 0x8C, 0x30, 0x0C, 0x30, 0x0C, 0x3F, 0xFC, 0x3F, 0xFC, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_double_arrow 21
+[TK_MAC_XCURSOR_double_arrow] = {
+ 0x00, 0x00, 0x01, 0x80, 0x03, 0xC0, 0x07, 0xE0, 0x0D, 0xB0, 0x19, 0x98, 0x01, 0x80, 0x01, 0x80,
+ 0x01, 0x80, 0x01, 0x80, 0x19, 0x98, 0x0D, 0xB0, 0x07, 0xE0, 0x03, 0xC0, 0x01, 0x80, 0x00, 0x00,
+ 0x01, 0x80, 0x03, 0xC0, 0x07, 0xE0, 0x0F, 0xF0, 0x1F, 0xF8, 0x3F, 0xFC, 0x3B, 0xDC, 0x03, 0xC0,
+ 0x03, 0xC0, 0x3B, 0xDC, 0x3F, 0xFC, 0x1F, 0xF8, 0x0F, 0xF0, 0x07, 0xE0, 0x03, 0xC0, 0x01, 0x80,
+ 0x00, 0x07, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_draft_large 22
+[TK_MAC_XCURSOR_draft_large] = {
+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x0C, 0x00, 0x3C, 0x00, 0xF8, 0x03, 0xF8, 0x0F, 0xF0, 0x00, 0xF0,
+ 0x01, 0x60, 0x02, 0x60, 0x04, 0x40, 0x08, 0x40, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x00, 0x0F, 0x00, 0x3E, 0x00, 0xFE, 0x03, 0xFC, 0x0F, 0xFC, 0x3F, 0xF8, 0xFF, 0xF8,
+ 0x03, 0xF0, 0x07, 0xF0, 0x0E, 0xE0, 0x1C, 0xE0, 0x38, 0xC0, 0x70, 0xC0, 0xE0, 0x80, 0x40, 0x80,
+ 0x00, 0x01, 0x00, 0x0E,
+},
+
+#define TK_MAC_XCURSOR_draft_small 23
+[TK_MAC_XCURSOR_draft_small] = {
+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x0C, 0x00, 0x3C, 0x00, 0xF8, 0x03, 0xF8, 0x00, 0x70, 0x00, 0xB0,
+ 0x01, 0x20, 0x02, 0x20, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x00, 0x0F, 0x00, 0x3E, 0x00, 0xFE, 0x03, 0xFC, 0x0F, 0xFC, 0x3F, 0xF8, 0x01, 0xF8,
+ 0x03, 0xF0, 0x07, 0x70, 0x0E, 0x60, 0x1C, 0x60, 0x38, 0x40, 0x70, 0x40, 0xE0, 0x00, 0x40, 0x00,
+ 0x00, 0x01, 0x00, 0x0E,
+},
+
+#define TK_MAC_XCURSOR_draped_box 24
+[TK_MAC_XCURSOR_draped_box] = {
+ 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFC, 0x22, 0x44, 0x26, 0x64, 0x2C, 0x34, 0x38, 0x1C, 0x21, 0x84,
+ 0x21, 0x84, 0x38, 0x1C, 0x2C, 0x34, 0x26, 0x64, 0x22, 0x44, 0x3F, 0xFC, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFC, 0x3E, 0x7C, 0x3E, 0x7C, 0x3C, 0x3C, 0x39, 0x9C, 0x23, 0xC4,
+ 0x23, 0xC4, 0x39, 0x9C, 0x3C, 0x3C, 0x3E, 0x7C, 0x3E, 0x7C, 0x3F, 0xFC, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_exchange 25
+[TK_MAC_XCURSOR_exchange] = {
+ 0x00, 0x00, 0x47, 0xC0, 0x6F, 0xE0, 0x7C, 0x30, 0x48, 0x10, 0x4C, 0x00, 0x7E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xFC, 0x00, 0x64, 0x10, 0x24, 0x18, 0x7C, 0x0F, 0xEC, 0x07, 0xC4, 0x00, 0x00,
+ 0xC7, 0xC0, 0xEF, 0xE0, 0xFF, 0xF0, 0xFF, 0xF8, 0xFC, 0x38, 0xFE, 0x10, 0xFF, 0x00, 0xFF, 0x80,
+ 0x03, 0xFE, 0x01, 0xFE, 0x10, 0xFE, 0x38, 0x7E, 0x3F, 0xFE, 0x1F, 0xFE, 0x0F, 0xEE, 0x07, 0xC6,
+ 0x00, 0x07, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_fleur 26
+[TK_MAC_XCURSOR_fleur] = {
+ 0x00, 0x00, 0x01, 0x80, 0x03, 0xC0, 0x07, 0xE0, 0x01, 0x80, 0x11, 0x88, 0x31, 0x8C, 0x7F, 0xFE,
+ 0x7F, 0xFE, 0x31, 0x8C, 0x11, 0x88, 0x01, 0x80, 0x07, 0xE0, 0x03, 0xC0, 0x01, 0x80, 0x00, 0x00,
+ 0x01, 0x80, 0x03, 0xC0, 0x07, 0xE0, 0x0F, 0xF0, 0x17, 0xE8, 0x3B, 0xDC, 0x7F, 0xFE, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0x7F, 0xFE, 0x3B, 0xDC, 0x17, 0xE8, 0x0F, 0xF0, 0x07, 0xE0, 0x03, 0xC0, 0x01, 0x80,
+ 0x00, 0x07, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_gobbler 27
+[TK_MAC_XCURSOR_gobbler] = {
+ 0x00, 0x00, 0x00, 0x78, 0x00, 0x70, 0x40, 0x36, 0x4F, 0xB0, 0x7F, 0xF0, 0x7E, 0x30, 0x7C, 0x30,
+ 0x30, 0x38, 0x00, 0xF0, 0x0F, 0xE0, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00,
+ 0x00, 0xFC, 0x00, 0xFC, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xF8, 0xFF, 0xF8,
+ 0xFF, 0xFC, 0x7F, 0xFC, 0x3F, 0xF8, 0x1F, 0xF0, 0x0E, 0x00, 0x1F, 0x80, 0x1F, 0x80, 0x1F, 0x80,
+ 0x00, 0x03, 0x00, 0x0E,
+},
+
+#define TK_MAC_XCURSOR_gumby 28
+[TK_MAC_XCURSOR_gumby] = {
+ 0x3F, 0x00, 0x10, 0xC0, 0xC8, 0x20, 0xEA, 0xA0, 0xC8, 0x20, 0xCB, 0xA0, 0xF8, 0x38, 0x38, 0x3E,
+ 0x08, 0x26, 0x08, 0x26, 0x09, 0x2E, 0x09, 0x26, 0x09, 0x20, 0x11, 0x10, 0x21, 0x08, 0x3E, 0xF8,
+ 0x3F, 0x00, 0x1F, 0xC0, 0xCF, 0xE0, 0xEF, 0xE0, 0xCF, 0xE0, 0xCF, 0xE0, 0xFF, 0xF8, 0x3F, 0xFE,
+ 0x0F, 0xE6, 0x0F, 0xE6, 0x0F, 0xEE, 0x0F, 0xE6, 0x0F, 0xE0, 0x1F, 0xF0, 0x3F, 0xF8, 0x3E, 0xF8,
+ 0x00, 0x00, 0x00, 0x02,
+},
+
+#define TK_MAC_XCURSOR_hand1 29
+[TK_MAC_XCURSOR_hand1] = {
+ 0x00, 0x0C, 0x00, 0x3C, 0x00, 0xF0, 0x01, 0xE0, 0x03, 0xC0, 0x07, 0xE0, 0x0F, 0xF0, 0x2F, 0xE0,
+ 0x7F, 0xF0, 0x5F, 0xF0, 0x07, 0xE0, 0x07, 0xC0, 0x4A, 0x00, 0x62, 0x00, 0x34, 0x00, 0x18, 0x00,
+ 0x00, 0x0C, 0x00, 0x3C, 0x00, 0xF0, 0x01, 0xE0, 0x03, 0xC0, 0x07, 0xE0, 0x0F, 0xF0, 0x2F, 0xE0,
+ 0x7F, 0xF0, 0x7F, 0xF0, 0x7F, 0xE0, 0x7F, 0xC0, 0x7E, 0x00, 0x7E, 0x00, 0x3C, 0x00, 0x18, 0x00,
+ 0x00, 0x00, 0x00, 0x0D,
+},
+
+#define TK_MAC_XCURSOR_hand2 30
+[TK_MAC_XCURSOR_hand2] = {
+ 0x00, 0x00, 0x3F, 0xC0, 0x40, 0x20, 0x3F, 0x10, 0x08, 0x08, 0x07, 0x08, 0x08, 0x08, 0x07, 0x14,
+ 0x08, 0x22, 0x06, 0x41, 0x01, 0x82, 0x01, 0x24, 0x00, 0x88, 0x00, 0x50, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x3F, 0xC0, 0x7F, 0xE0, 0x3F, 0xF0, 0x0F, 0xF8, 0x07, 0xF8, 0x0F, 0xF8, 0x07, 0xFC,
+ 0x0F, 0xFE, 0x07, 0xFF, 0x01, 0xFE, 0x01, 0xFC, 0x00, 0xF8, 0x00, 0x70, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x01,
+},
+
+#define TK_MAC_XCURSOR_heart 31
+[TK_MAC_XCURSOR_heart] = {
+ 0x00, 0x00, 0x3E, 0xF8, 0x63, 0x8C, 0xC1, 0x06, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02,
+ 0xC0, 0x06, 0x60, 0x0C, 0x30, 0x18, 0x18, 0x30, 0x0C, 0x60, 0x06, 0xC0, 0x03, 0x80, 0x00, 0x00,
+ 0x00, 0x00, 0x3E, 0xF8, 0x7F, 0xFC, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE,
+ 0xFF, 0xFE, 0x7F, 0xFC, 0x3F, 0xF8, 0x1F, 0xF0, 0x0F, 0xE0, 0x07, 0xC0, 0x03, 0x80, 0x00, 0x00,
+ 0x00, 0x03, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_icon 32
+[TK_MAC_XCURSOR_icon] = {
+ 0xFF, 0xFF, 0xD5, 0x55, 0xAA, 0xAB, 0xD5, 0x55, 0xA0, 0x0B, 0xD0, 0x05, 0xA0, 0x0B, 0xD0, 0x05,
+ 0xA0, 0x0B, 0xD0, 0x05, 0xA0, 0x0B, 0xD0, 0x05, 0xAA, 0xAB, 0xD5, 0x55, 0xAA, 0xAB, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
+ 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x00, 0x07, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_iron_cross 33
+[TK_MAC_XCURSOR_iron_cross] = {
+ 0x00, 0x00, 0x3F, 0xFC, 0x1F, 0xF8, 0x4F, 0xF2, 0x67, 0xE6, 0x73, 0xCE, 0x79, 0x9E, 0x7F, 0xFE,
+ 0x7F, 0xFE, 0x79, 0x9E, 0x73, 0xCE, 0x67, 0xE6, 0x4F, 0xF2, 0x1F, 0xF8, 0x3F, 0xFC, 0x00, 0x00,
+ 0x7F, 0xFE, 0x7F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFE, 0x7F, 0xFE,
+ 0x00, 0x07, 0x00, 0x06,
+},
+
+#define TK_MAC_XCURSOR_left_ptr 34
+[TK_MAC_XCURSOR_left_ptr] = {
+ 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0E, 0x00, 0x0F, 0x00, 0x0F, 0x80, 0x0F, 0xC0, 0x0F, 0xE0,
+ 0x0F, 0xF0, 0x0F, 0x80, 0x0D, 0x80, 0x08, 0xC0, 0x00, 0xC0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00,
+ 0x18, 0x00, 0x1C, 0x00, 0x1E, 0x00, 0x1F, 0x00, 0x1F, 0x80, 0x1F, 0xC0, 0x1F, 0xE0, 0x1F, 0xF0,
+ 0x1F, 0xF8, 0x1F, 0xFC, 0x1F, 0xC0, 0x1D, 0xE0, 0x19, 0xE0, 0x10, 0xF0, 0x00, 0xF0, 0x00, 0x70,
+ 0x00, 0x01, 0x00, 0x04,
+},
+
+#define TK_MAC_XCURSOR_left_side 35
+[TK_MAC_XCURSOR_left_side] = {
+ 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x80, 0x61, 0x00, 0x62, 0x00, 0x64, 0x00, 0x6F, 0xFC,
+ 0x64, 0x00, 0x62, 0x00, 0x61, 0x00, 0x60, 0x80, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x80, 0x61, 0x00, 0x62, 0x00, 0x64, 0x00, 0x6F, 0xFC,
+ 0x64, 0x00, 0x62, 0x00, 0x61, 0x00, 0x60, 0x80, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x04,
+},
+
+#define TK_MAC_XCURSOR_left_tee 36
+[TK_MAC_XCURSOR_left_tee] = {
+ 0x00, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0F, 0xF8,
+ 0x0F, 0xF8, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0F, 0xF8,
+ 0x0F, 0xF8, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x04,
+},
+
+#define TK_MAC_XCURSOR_leftbutton 37
+[TK_MAC_XCURSOR_leftbutton] = {
+ 0x80, 0x02, 0x7F, 0xFC, 0x7F, 0xFC, 0x44, 0x44, 0x45, 0x54, 0x45, 0x54, 0x45, 0x54, 0x45, 0x54,
+ 0x44, 0x44, 0x7F, 0xFC, 0x7F, 0xFC, 0x7F, 0xFC, 0x7F, 0xFC, 0x7F, 0xFC, 0x7F, 0xFC, 0x80, 0x02,
+ 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE,
+ 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE,
+ 0x00, 0x04, 0x00, 0x03,
+},
+
+#define TK_MAC_XCURSOR_ll_angle 38
+[TK_MAC_XCURSOR_ll_angle] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00,
+ 0x0C, 0x00, 0x0C, 0x00, 0x0F, 0xF8, 0x0F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00,
+ 0x0C, 0x00, 0x0C, 0x00, 0x0F, 0xF8, 0x0F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0B, 0x00, 0x04,
+},
+
+#define TK_MAC_XCURSOR_lr_angle 39
+[TK_MAC_XCURSOR_lr_angle] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30,
+ 0x00, 0x30, 0x00, 0x30, 0x1F, 0xF0, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30,
+ 0x00, 0x30, 0x00, 0x30, 0x1F, 0xF0, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0B, 0x00, 0x0B,
+},
+
+#define TK_MAC_XCURSOR_man 40
+[TK_MAC_XCURSOR_man] = {
+ 0x03, 0x80, 0x1E, 0xF0, 0x02, 0x80, 0x81, 0x00, 0x43, 0x87, 0x24, 0x4B, 0x1D, 0x70, 0x05, 0x40,
+ 0x04, 0x40, 0x02, 0x80, 0x04, 0x40, 0x09, 0x20, 0x12, 0x90, 0x14, 0x50, 0x78, 0x3C, 0xF8, 0x3F,
+ 0x03, 0x80, 0x1F, 0xF0, 0x03, 0x80, 0x81, 0x00, 0x43, 0x87, 0x27, 0xCB, 0x1F, 0xF0, 0x07, 0xC0,
+ 0x07, 0xC0, 0x03, 0x80, 0x07, 0xC0, 0x0F, 0xE0, 0x1E, 0xF0, 0x1C, 0x70, 0x78, 0x3C, 0xF8, 0x3F,
+ 0x00, 0x01, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_middlebutton 41
+[TK_MAC_XCURSOR_middlebutton] = {
+ 0x80, 0x02, 0x7F, 0xFC, 0x7F, 0xFC, 0x44, 0x44, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
+ 0x44, 0x44, 0x7F, 0xFC, 0x7F, 0xFC, 0x7F, 0xFC, 0x7F, 0xFC, 0x7F, 0xFC, 0x7F, 0xFC, 0x80, 0x02,
+ 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE,
+ 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE,
+ 0x00, 0x04, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_mouse 42
+[TK_MAC_XCURSOR_mouse] = {
+ 0x06, 0x00, 0x01, 0x00, 0x01, 0x80, 0x0F, 0xF0, 0x10, 0x08, 0x17, 0xE8, 0x14, 0x28, 0x14, 0x28,
+ 0x17, 0xE8, 0x10, 0x08, 0x10, 0x08, 0x10, 0x08, 0x10, 0x08, 0x10, 0x08, 0x10, 0x08, 0x0F, 0xF0,
+ 0x06, 0x00, 0x01, 0x00, 0x01, 0x80, 0x0F, 0xF0, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8,
+ 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x0F, 0xF0,
+ 0x00, 0x00, 0x00, 0x00,
+},
+
+#define TK_MAC_XCURSOR_pencil 43
+[TK_MAC_XCURSOR_pencil] = {
+ 0x00, 0x00, 0x00, 0xF0, 0x00, 0x88, 0x01, 0x08, 0x01, 0x90, 0x02, 0x70, 0x02, 0x20, 0x04, 0x40,
+ 0x04, 0x40, 0x08, 0x80, 0x08, 0x80, 0x11, 0x00, 0x1E, 0x00, 0x1C, 0x00, 0x18, 0x00, 0x10, 0x00,
+ 0x00, 0x00, 0x00, 0xF0, 0x00, 0xF8, 0x01, 0xF8, 0x01, 0xF0, 0x03, 0xF0, 0x03, 0xE0, 0x07, 0xC0,
+ 0x07, 0xC0, 0x0F, 0x80, 0x0F, 0x80, 0x1F, 0x00, 0x1E, 0x00, 0x1C, 0x00, 0x18, 0x00, 0x10, 0x00,
+ 0x00, 0x0F, 0x00, 0x03,
+},
+
+#define TK_MAC_XCURSOR_pirate 44
+[TK_MAC_XCURSOR_pirate] = {
+ 0x03, 0xC0, 0x07, 0xE0, 0x0F, 0xF0, 0x19, 0x98, 0x19, 0x98, 0x0F, 0xF0, 0x07, 0xE0, 0x03, 0xC0,
+ 0x43, 0xC2, 0x43, 0xC3, 0x21, 0x84, 0x1C, 0x38, 0x03, 0xC0, 0x0F, 0xF1, 0x78, 0x1F, 0x40, 0x02,
+ 0x07, 0xE0, 0x0F, 0xF0, 0x1F, 0xF8, 0x3F, 0xFC, 0x3F, 0xFC, 0x1F, 0xF8, 0x0F, 0xF0, 0x47, 0xE2,
+ 0xE7, 0xE7, 0xE7, 0xE7, 0x7F, 0xFF, 0x3F, 0xFC, 0x1F, 0xF9, 0x7F, 0xFF, 0xFF, 0xFF, 0xF8, 0x1F,
+ 0x00, 0x0A, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_plus 45
+[TK_MAC_XCURSOR_plus] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x1F, 0xF8,
+ 0x1F, 0xF8, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x1F, 0xF8,
+ 0x1F, 0xF8, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_question_arrow 46
+[TK_MAC_XCURSOR_question_arrow] = {
+ 0x07, 0xC0, 0x0F, 0xE0, 0x1C, 0x70, 0x18, 0x30, 0x1C, 0x30, 0x0C, 0x70, 0x00, 0xE0, 0x03, 0xC0,
+ 0x03, 0x80, 0x02, 0x80, 0x02, 0x80, 0x0E, 0xE0, 0x06, 0xC0, 0x03, 0x80, 0x01, 0x00, 0x00, 0x00,
+ 0x07, 0xC0, 0x0F, 0xE0, 0x1C, 0x70, 0x18, 0x30, 0x1C, 0x30, 0x0C, 0x70, 0x00, 0xE0, 0x03, 0xC0,
+ 0x03, 0x80, 0x02, 0x80, 0x3F, 0xF8, 0x1F, 0xF0, 0x0F, 0xE0, 0x07, 0xC0, 0x03, 0x80, 0x01, 0x00,
+ 0x00, 0x0E, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_right_ptr 47
+[TK_MAC_XCURSOR_right_ptr] = {
+ 0x00, 0x00, 0x00, 0x10, 0x00, 0x30, 0x00, 0x70, 0x00, 0xF0, 0x01, 0xF0, 0x03, 0xF0, 0x07, 0xF0,
+ 0x0F, 0xF0, 0x01, 0xF0, 0x01, 0xB0, 0x03, 0x10, 0x03, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xF8, 0x01, 0xF8, 0x03, 0xF8, 0x07, 0xF8, 0x0F, 0xF8,
+ 0x1F, 0xF8, 0x3F, 0xF8, 0x03, 0xF8, 0x07, 0xB8, 0x07, 0x98, 0x0F, 0x08, 0x0F, 0x00, 0x0E, 0x00,
+ 0x00, 0x01, 0x00, 0x0B,
+},
+
+#define TK_MAC_XCURSOR_right_side 48
+[TK_MAC_XCURSOR_right_side] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x01, 0x06, 0x00, 0x86, 0x00, 0x46, 0x00, 0x26,
+ 0x3F, 0xF6, 0x00, 0x26, 0x00, 0x46, 0x00, 0x86, 0x01, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x01, 0x06, 0x00, 0x86, 0x00, 0x46, 0x00, 0x26,
+ 0x3F, 0xF6, 0x00, 0x26, 0x00, 0x46, 0x00, 0x86, 0x01, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00,
+ 0x00, 0x08, 0x00, 0x0B,
+},
+
+#define TK_MAC_XCURSOR_right_tee 49
+[TK_MAC_XCURSOR_right_tee] = {
+ 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x1F, 0xF0,
+ 0x1F, 0xF0, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x1F, 0xF0,
+ 0x1F, 0xF0, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x0A,
+},
+
+#define TK_MAC_XCURSOR_rightbutton 50
+[TK_MAC_XCURSOR_rightbutton] = {
+ 0x80, 0x02, 0x7F, 0xFC, 0x7F, 0xFC, 0x44, 0x44, 0x55, 0x44, 0x55, 0x44, 0x55, 0x44, 0x55, 0x44,
+ 0x44, 0x44, 0x7F, 0xFC, 0x7F, 0xFC, 0x7F, 0xFC, 0x7F, 0xFC, 0x7F, 0xFC, 0x7F, 0xFC, 0x80, 0x02,
+ 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE,
+ 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE,
+ 0x00, 0x04, 0x00, 0x03,
+},
+
+#define TK_MAC_XCURSOR_rtl_logo 51
+[TK_MAC_XCURSOR_rtl_logo] = {
+ 0x00, 0x00, 0x7F, 0xFE, 0x40, 0x22, 0x40, 0x22, 0x40, 0x22, 0x7F, 0xE2, 0x44, 0x22, 0x44, 0x22,
+ 0x44, 0x22, 0x44, 0x22, 0x47, 0xFE, 0x44, 0x02, 0x44, 0x02, 0x44, 0x02, 0x7F, 0xFE, 0x00, 0x00,
+ 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFE, 0x60, 0x76, 0x7F, 0xF6, 0x7F, 0xF6, 0x7C, 0x36, 0x6C, 0x36,
+ 0x6C, 0x36, 0x6C, 0x3E, 0x6F, 0xFE, 0x6F, 0xFE, 0x6E, 0x06, 0x7F, 0xFE, 0x7F, 0xFE, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_sailboat 52
+[TK_MAC_XCURSOR_sailboat] = {
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x01, 0x60, 0x01, 0x60, 0x03, 0x60, 0x03, 0x70, 0x07, 0x70,
+ 0x07, 0x70, 0x0F, 0x78, 0x0F, 0x78, 0x1F, 0x78, 0x1F, 0x7C, 0x3E, 0x38, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x40, 0x00, 0xE0, 0x01, 0xE0, 0x03, 0xF0, 0x03, 0xF0, 0x07, 0xF0, 0x07, 0xF8, 0x0F, 0xF8,
+ 0x0F, 0xF8, 0x1F, 0xFC, 0x1F, 0xFC, 0x3F, 0xFC, 0x3F, 0xFE, 0x7F, 0x7C, 0x7E, 0x38, 0x00, 0x00,
+ 0x00, 0x0C, 0x00, 0x08,
+},
+
+#define TK_MAC_XCURSOR_sb_down_arrow 53
+[TK_MAC_XCURSOR_sb_down_arrow] = {
+ 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80,
+ 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x0F, 0xE0, 0x07, 0xC0, 0x03, 0x80, 0x01, 0x00, 0x00, 0x00,
+ 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80,
+ 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x1F, 0xF0, 0x0F, 0xE0, 0x07, 0xC0, 0x03, 0x80, 0x01, 0x00,
+ 0x00, 0x0E, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_sb_h_double_arrow 54
+[TK_MAC_XCURSOR_sb_h_double_arrow] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x18, 0x18, 0x3F, 0xFC, 0x78, 0x1E,
+ 0x3F, 0xFC, 0x18, 0x18, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x18, 0x18, 0x38, 0x1C, 0x7F, 0xFE, 0xFF, 0xFF,
+ 0x7F, 0xFE, 0x38, 0x1C, 0x18, 0x18, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_sb_left_arrow 55
+[TK_MAC_XCURSOR_sb_left_arrow] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x18, 0x00, 0x3F, 0xFF, 0x78, 0x00,
+ 0x3F, 0xFF, 0x18, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x18, 0x00, 0x38, 0x00, 0x7F, 0xFF, 0xFF, 0xFF,
+ 0x7F, 0xFF, 0x38, 0x00, 0x18, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x01,
+},
+
+#define TK_MAC_XCURSOR_sb_right_arrow 56
+[TK_MAC_XCURSOR_sb_right_arrow] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x18, 0xFF, 0xFC,
+ 0x00, 0x1E, 0xFF, 0xFC, 0x00, 0x18, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x18, 0x00, 0x1C, 0xFF, 0xFE,
+ 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x1C, 0x00, 0x18, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x00, 0x0E,
+},
+
+#define TK_MAC_XCURSOR_sb_up_arrow 57
+[TK_MAC_XCURSOR_sb_up_arrow] = {
+ 0x00, 0x00, 0x00, 0x80, 0x01, 0xC0, 0x03, 0xE0, 0x07, 0xF0, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40,
+ 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40,
+ 0x00, 0x80, 0x01, 0xC0, 0x03, 0xE0, 0x07, 0xF0, 0x0F, 0xF8, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0,
+ 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0,
+ 0x00, 0x01, 0x00, 0x08,
+},
+
+#define TK_MAC_XCURSOR_sb_v_double_arrow 58
+[TK_MAC_XCURSOR_sb_v_double_arrow] = {
+ 0x00, 0x00, 0x01, 0x00, 0x03, 0x80, 0x07, 0xC0, 0x0F, 0xE0, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80,
+ 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x0F, 0xE0, 0x07, 0xC0, 0x03, 0x80, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x03, 0x80, 0x07, 0xC0, 0x0F, 0xE0, 0x1F, 0xF0, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80,
+ 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x1F, 0xF0, 0x0F, 0xE0, 0x07, 0xC0, 0x03, 0x80, 0x01, 0x00,
+ 0x00, 0x07, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_shuttle 59
+[TK_MAC_XCURSOR_shuttle] = {
+ 0x00, 0x20, 0x00, 0x70, 0x00, 0xF8, 0x01, 0xDE, 0x05, 0xDE, 0x09, 0xDE, 0x11, 0xDE, 0x11, 0xDE,
+ 0x11, 0xDE, 0x11, 0xDE, 0x31, 0xDE, 0x71, 0xDE, 0xFD, 0xDE, 0x18, 0x88, 0x00, 0x78, 0x00, 0x30,
+ 0x00, 0x20, 0x00, 0x70, 0x00, 0xF8, 0x01, 0xFE, 0x07, 0xFE, 0x0F, 0xFE, 0x1F, 0xFE, 0x1F, 0xFE,
+ 0x1F, 0xFE, 0x1F, 0xFE, 0x3F, 0xFE, 0x7F, 0xFE, 0xFF, 0xFE, 0x18, 0xF8, 0x00, 0x78, 0x00, 0x30,
+ 0x00, 0x00, 0x00, 0x0A,
+},
+
+#define TK_MAC_XCURSOR_sizing 60
+[TK_MAC_XCURSOR_sizing] = {
+ 0x00, 0x00, 0x7F, 0x80, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x47, 0xE0, 0x44, 0x20, 0x44, 0x22,
+ 0x44, 0x22, 0x04, 0x22, 0x07, 0xE2, 0x00, 0x12, 0x00, 0x0A, 0x00, 0x06, 0x01, 0xFE, 0x00, 0x00,
+ 0xFF, 0xC0, 0xFF, 0xC0, 0xFF, 0xC0, 0xE0, 0x00, 0xEF, 0xF0, 0xEF, 0xF0, 0xEC, 0x37, 0xEC, 0x37,
+ 0xEC, 0x37, 0xEC, 0x37, 0x0F, 0xF7, 0x0F, 0xFF, 0x00, 0x1F, 0x03, 0xFF, 0x03, 0xFF, 0x03, 0xFF,
+ 0x00, 0x0E, 0x00, 0x0E,
+},
+
+#define TK_MAC_XCURSOR_spider 61
+[TK_MAC_XCURSOR_spider] = {
+ 0x20, 0x10, 0x10, 0x20, 0x10, 0x20, 0x08, 0x40, 0x08, 0x40, 0x87, 0x87, 0x67, 0x98, 0x1F, 0xE0,
+ 0x1F, 0xE0, 0x67, 0x98, 0x87, 0x87, 0x08, 0x40, 0x08, 0x40, 0x10, 0x20, 0x10, 0x20, 0x20, 0x10,
+ 0x70, 0x38, 0x38, 0x70, 0x38, 0x70, 0x1C, 0xE0, 0x9F, 0xE7, 0xEF, 0xDF, 0xFF, 0xFF, 0x7F, 0xF8,
+ 0x7F, 0xF8, 0xFF, 0xFF, 0xEF, 0xDF, 0x9F, 0xE7, 0x1C, 0xE0, 0x38, 0x70, 0x38, 0x70, 0x70, 0x38,
+ 0x00, 0x07, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_spraycan 62
+[TK_MAC_XCURSOR_spraycan] = {
+ 0x00, 0x18, 0x00, 0x40, 0x0D, 0x18, 0x1E, 0x40, 0x1A, 0x18, 0x3F, 0x00, 0x21, 0x00, 0x39, 0x00,
+ 0x29, 0x00, 0x39, 0x00, 0x29, 0x00, 0x39, 0x00, 0x39, 0x00, 0x21, 0x00, 0x21, 0x00, 0x3F, 0x00,
+ 0x00, 0x18, 0x00, 0x40, 0x0D, 0x18, 0x1E, 0x40, 0x1E, 0x18, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00,
+ 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00,
+ 0x00, 0x02, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_star 63
+[TK_MAC_XCURSOR_star] = {
+ 0x01, 0x00, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x39, 0x38,
+ 0xC0, 0x06, 0x38, 0x38, 0x09, 0x20, 0x12, 0x90, 0x24, 0x48, 0x28, 0x28, 0x30, 0x18, 0x20, 0x08,
+ 0x01, 0x00, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x07, 0xC0, 0x07, 0xC0, 0x07, 0xC0, 0x3F, 0xF8,
+ 0xFF, 0xFE, 0x3F, 0xF8, 0x0F, 0xE0, 0x1E, 0xF0, 0x3C, 0x78, 0x38, 0x38, 0x30, 0x18, 0x20, 0x08,
+ 0x00, 0x07, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_target 64
+[TK_MAC_XCURSOR_target] = {
+ 0x00, 0x00, 0x03, 0x80, 0x0F, 0xE0, 0x1C, 0x70, 0x30, 0x18, 0x60, 0x0C, 0xC1, 0x06, 0xC2, 0x86,
+ 0xC1, 0x06, 0x60, 0x0C, 0x30, 0x18, 0x1C, 0x70, 0x0F, 0xE0, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x03, 0x80, 0x0F, 0xE0, 0x1F, 0xF0, 0x3C, 0x78, 0x70, 0x1C, 0xE3, 0x8E, 0xE3, 0x8E,
+ 0xE3, 0x8E, 0x70, 0x1C, 0x3C, 0x78, 0x1F, 0xF0, 0x0F, 0xE0, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_tcross 65
+[TK_MAC_XCURSOR_tcross] = {
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0xFF, 0xFE,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0xFF, 0xFE,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_top_left_arrow 66
+[TK_MAC_XCURSOR_top_left_arrow] = {
+ 0x00, 0x00, 0x60, 0x00, 0x78, 0x00, 0x3E, 0x00, 0x3F, 0x80, 0x1F, 0xE0, 0x1E, 0x00, 0x0D, 0x00,
+ 0x0C, 0x80, 0x04, 0x40, 0x04, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0xE0, 0x00, 0xF8, 0x00, 0xFE, 0x00, 0x7F, 0x80, 0x7F, 0xE0, 0x3F, 0xF8, 0x3F, 0xFE, 0x1F, 0x80,
+ 0x1F, 0xC0, 0x0E, 0xE0, 0x0E, 0x70, 0x06, 0x38, 0x06, 0x1C, 0x02, 0x0E, 0x02, 0x04, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x01,
+},
+
+#define TK_MAC_XCURSOR_top_left_corner 67
+[TK_MAC_XCURSOR_top_left_corner] = {
+ 0xFF, 0xF0, 0xFF, 0xF0, 0xC0, 0x00, 0xC0, 0x00, 0xCF, 0xC0, 0xCC, 0x00, 0xCA, 0x00, 0xC9, 0x00,
+ 0xC8, 0x80, 0xC8, 0x40, 0xC0, 0x20, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xF0, 0xFF, 0xF0, 0xC0, 0x00, 0xC0, 0x00, 0xCF, 0xC0, 0xCC, 0x00, 0xCA, 0x00, 0xC9, 0x00,
+ 0xC8, 0x80, 0xC8, 0x40, 0xC0, 0x20, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+},
+
+#define TK_MAC_XCURSOR_top_right_corner 68
+[TK_MAC_XCURSOR_top_right_corner] = {
+ 0x0F, 0xFF, 0x0F, 0xFF, 0x00, 0x03, 0x00, 0x03, 0x03, 0xF3, 0x00, 0x33, 0x00, 0x53, 0x00, 0x93,
+ 0x01, 0x13, 0x02, 0x13, 0x04, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0F, 0xFF, 0x0F, 0xFF, 0x00, 0x03, 0x00, 0x03, 0x03, 0xF3, 0x00, 0x33, 0x00, 0x53, 0x00, 0x93,
+ 0x01, 0x13, 0x02, 0x13, 0x04, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0F,
+},
+
+#define TK_MAC_XCURSOR_top_side 69
+[TK_MAC_XCURSOR_top_side] = {
+ 0x00, 0x00, 0x7F, 0xFC, 0x7F, 0xFC, 0x00, 0x00, 0x01, 0x00, 0x03, 0x80, 0x05, 0x40, 0x09, 0x20,
+ 0x11, 0x10, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x7F, 0xFC, 0x7F, 0xFC, 0x00, 0x00, 0x01, 0x00, 0x03, 0x80, 0x05, 0x40, 0x09, 0x20,
+ 0x11, 0x10, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x04, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_top_tee 70
+[TK_MAC_XCURSOR_top_tee] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFE, 0x01, 0x80, 0x01, 0x80,
+ 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFE, 0x01, 0x80, 0x01, 0x80,
+ 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x04, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_trek 71
+[TK_MAC_XCURSOR_trek] = {
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x80, 0x07, 0xC0, 0x0F, 0xE0, 0x0E, 0xE0, 0x0F, 0xE0, 0x07, 0xC0,
+ 0x03, 0x80, 0x01, 0x00, 0x0B, 0xA0, 0x0D, 0x60, 0x09, 0x20, 0x08, 0x20, 0x08, 0x20, 0x00, 0x00,
+ 0x01, 0x00, 0x03, 0x80, 0x07, 0xC0, 0x0F, 0xE0, 0x1F, 0xF0, 0x1F, 0xF0, 0x1F, 0xF0, 0x0F, 0xE0,
+ 0x07, 0xC0, 0x0B, 0xA0, 0x1F, 0xF0, 0x1F, 0xF0, 0x1F, 0xF0, 0x1D, 0x70, 0x1C, 0x70, 0x08, 0x20,
+ 0x00, 0x00, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_ul_angle 72
+[TK_MAC_XCURSOR_ul_angle] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF8, 0x0F, 0xF8, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00,
+ 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF8, 0x0F, 0xF8, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00,
+ 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x00, 0x04,
+},
+
+#define TK_MAC_XCURSOR_umbrella 73
+[TK_MAC_XCURSOR_umbrella] = {
+ 0x00, 0x00, 0x08, 0x90, 0x02, 0x28, 0x49, 0xA6, 0x27, 0xC8, 0x19, 0x30, 0x61, 0x0C, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x40, 0x01, 0x40, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0x00, 0x0F, 0xF0, 0x1F, 0xF8, 0x7F, 0xFE, 0x7F, 0xFC, 0xFF, 0xFE, 0xFB, 0xBE, 0xE3, 0x8E,
+ 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0xC0, 0x03, 0xE0, 0x03, 0xE0, 0x01, 0xC0, 0x00, 0x80,
+ 0x00, 0x04, 0x00, 0x07,
+},
+
+#define TK_MAC_XCURSOR_ur_angle 74
+[TK_MAC_XCURSOR_ur_angle] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x1F, 0xF0, 0x00, 0x30, 0x00, 0x30,
+ 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x1F, 0xF0, 0x00, 0x30, 0x00, 0x30,
+ 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x04, 0x00, 0x0B,
+},
+
+#define TK_MAC_XCURSOR_watch 75
+[TK_MAC_XCURSOR_watch] = {
+ 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x08, 0x10, 0x10, 0x88, 0x10, 0x88, 0x10, 0x8C,
+ 0x13, 0x8C, 0x10, 0x08, 0x10, 0x08, 0x08, 0x10, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0,
+ 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x0F, 0xF0, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xFC,
+ 0x1F, 0xFC, 0x1F, 0xF8, 0x1F, 0xF8, 0x0F, 0xF0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0,
+ 0x00, 0x08, 0x00, 0x0D,
+},
+
+#define TK_MAC_XCURSOR_xterm 76
+[TK_MAC_XCURSOR_xterm] = {
+ 0x0C, 0x60, 0x02, 0x80, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x80, 0x0C, 0x60,
+ 0x0C, 0x60, 0x02, 0x80, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x80, 0x0C, 0x60,
+ 0x00, 0x0B, 0x00, 0x07,
+},
+
+};
diff --git a/tk8.6/macosx/tkMacOSXXStubs.c b/tk8.6/macosx/tkMacOSXXStubs.c
new file mode 100644
index 0000000..13cba84
--- /dev/null
+++ b/tk8.6/macosx/tkMacOSXXStubs.c
@@ -0,0 +1,987 @@
+/*
+ * 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
+ * their implementation just doesn't do anything. Other calls will
+ * eventually be moved into other files.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ * Copyright 2001-2009, Apple Inc.
+ * Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright 2014 Marc Culler.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkMacOSXPrivate.h"
+#include "tkMacOSXEvent.h"
+
+#include <IOKit/IOKitLib.h>
+#include <IOKit/hidsystem/IOHIDShared.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
+
+CGFloat tkMacOSXZeroScreenHeight = 0;
+CGFloat tkMacOSXZeroScreenTop = 0;
+
+/*
+ * Declarations of static variables used in this file.
+ */
+
+/* The unique Macintosh display. */
+static TkDisplay *gMacDisplay = NULL;
+/* The default name of the Macintosh display. */
+static const char *macScreenName = ":0";
+/* Timestamp showing the last reset of the inactivity timer. */
+static Time lastInactivityReset = 0;
+
+
+/*
+ * Forward declarations of procedures used in this file.
+ */
+
+static XID MacXIdAlloc(Display *display);
+static int DefaultErrorHandler(Display *display,
+ XErrorEvent *err_evt);
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXDisplayChanged --
+ *
+ * Called to set up initial screen info or when an event indicated
+ * display (screen) change.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * May change info regarding the screen.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXDisplayChanged(
+ Display *display)
+{
+ Screen *screen;
+ NSArray *nsScreens;
+
+
+ if (display == NULL || display->screens == NULL) {
+ return;
+ }
+ screen = display->screens;
+
+ nsScreens = [NSScreen screens];
+ if (nsScreens && [nsScreens count]) {
+ NSScreen *s = [nsScreens objectAtIndex:0];
+ NSRect bounds = [s frame], visible = [s visibleFrame];
+ NSRect maxBounds = NSZeroRect;
+
+ tkMacOSXZeroScreenHeight = bounds.size.height;
+ tkMacOSXZeroScreenTop = tkMacOSXZeroScreenHeight -
+ (visible.origin.y + visible.size.height);
+
+ screen->root_depth = NSBitsPerPixelFromDepth([s depth]);
+ screen->width = bounds.size.width;
+ screen->height = bounds.size.height;
+ screen->mwidth = (bounds.size.width * 254 + 360) / 720;
+ screen->mheight = (bounds.size.height * 254 + 360) / 720;
+
+ for (s in nsScreens) {
+ maxBounds = NSUnionRect(maxBounds, [s visibleFrame]);
+ }
+ *((NSRect *)screen->ext_data) = maxBounds;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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;
+ int fd = 0;
+ static NSRect maxBounds = {{0, 0}, {0, 0}};
+ static char vendor[25] = "";
+ NSArray *cgVers;
+ NSAutoreleasePool *pool = [NSAutoreleasePool new];
+
+ if (gMacDisplay != NULL) {
+ if (strcmp(gMacDisplay->display->display_name, display_name) == 0) {
+ return gMacDisplay;
+ } else {
+ return NULL;
+ }
+ }
+
+ display = ckalloc(sizeof(Display));
+ screen = ckalloc(sizeof(Screen));
+ bzero(display, sizeof(Display));
+ bzero(screen, sizeof(Screen));
+
+ display->resource_alloc = MacXIdAlloc;
+ display->request = 0;
+ display->qlen = 0;
+ display->fd = fd;
+ display->screens = screen;
+ display->nscreens = 1;
+ display->default_screen = 0;
+ display->display_name = (char *) macScreenName;
+
+ cgVers = [[[NSBundle bundleWithIdentifier:@"com.apple.CoreGraphics"]
+ objectForInfoDictionaryKey:@"CFBundleShortVersionString"]
+ componentsSeparatedByString:@"."];
+ if ([cgVers count] >= 2) {
+ display->proto_major_version = [[cgVers objectAtIndex:1] integerValue];
+ }
+ if ([cgVers count] >= 3) {
+ display->proto_minor_version = [[cgVers objectAtIndex:2] integerValue];
+ }
+ if (!vendor[0]) {
+ snprintf(vendor, sizeof(vendor), "Apple AppKit %g",
+ NSAppKitVersionNumber);
+ }
+ display->vendor = vendor;
+ {
+ int major, minor, patch;
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 101000
+ Gestalt(gestaltSystemVersionMajor, (SInt32*)&major);
+ Gestalt(gestaltSystemVersionMinor, (SInt32*)&minor);
+ Gestalt(gestaltSystemVersionBugFix, (SInt32*)&patch);
+#else
+ NSOperatingSystemVersion systemVersion = [[NSProcessInfo processInfo] operatingSystemVersion];
+ major = systemVersion.majorVersion;
+ minor = systemVersion.minorVersion;
+ patch = systemVersion.patchVersion;
+#endif
+ display->release = major << 16 | minor << 8 | patch;
+ }
+
+ /*
+ * These screen bits never change
+ */
+ screen->root = ROOT_ID;
+ screen->display = display;
+ screen->black_pixel = 0x00000000 | PIXEL_MAGIC << 24;
+ screen->white_pixel = 0x00FFFFFF | PIXEL_MAGIC << 24;
+ screen->ext_data = (XExtData *) &maxBounds;
+
+ screen->root_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 = 256;
+
+ /*
+ * Initialize screen bits that may change
+ */
+
+ TkMacOSXDisplayChanged(display);
+
+ gMacDisplay = 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;
+ [pool drain];
+
+ /*
+ * Key map info must be available immediately, because of "send event".
+ */
+ TkpInitKeymapInfo(gMacDisplay);
+
+ 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) {
+ Tcl_Panic("TkpCloseDisplay: tried to call TkpCloseDisplay on bad display");
+ }
+
+ gMacDisplay = NULL;
+ if (display->screens != NULL) {
+ if (display->screens->root_visual != NULL) {
+ ckfree(display->screens->root_visual);
+ }
+ ckfree(display->screens);
+ }
+ ckfree(display);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkClipCleanup --
+ *
+ * This procedure is called to cleanup resources associated with claiming
+ * clipboard ownership and for receiving selection get results. This
+ * function is called in tkWindow.c. This has to be called by the display
+ * cleanup function because we still need the access display elements.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Resources are freed - the clipboard may no longer be used.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkClipCleanup(
+ TkDisplay *dispPtr) /* display associated with clipboard */
+{
+ /*
+ * Make sure that the local scrap is transfered to the global scrap if
+ * needed.
+ */
+
+ [NSApp tkProvidePasteboard:dispPtr];
+
+ if (dispPtr->clipWindow != NULL) {
+ Tk_DeleteSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom,
+ dispPtr->applicationAtom);
+ Tk_DeleteSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom,
+ dispPtr->windowAtom);
+
+ Tk_DestroyWindow(dispPtr->clipWindow);
+ Tcl_Release(dispPtr->clipWindow);
+ dispPtr->clipWindow = NULL;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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.
+ */
+
+ Tcl_Panic("Warning hit bogus error handler!");
+ return 0;
+}
+
+char *
+XGetAtomName(
+ Display * display,
+ Atom atom)
+{
+ display->request++;
+ return NULL;
+}
+
+XErrorHandler
+XSetErrorHandler(
+ XErrorHandler handler)
+{
+ return DefaultErrorHandler;
+}
+
+Window
+XRootWindow(
+ Display *display,
+ int screen_number)
+{
+ display->request++;
+ return ROOT_ID;
+}
+
+int
+XGetGeometry(
+ 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)
+{
+ TkWindow *winPtr = ((MacDrawable *) d)->winPtr;
+
+ display->request++;
+ *root_return = ROOT_ID;
+ if (winPtr) {
+ *x_return = Tk_X(winPtr);
+ *y_return = Tk_Y(winPtr);
+ *width_return = Tk_Width(winPtr);
+ *height_return = Tk_Height(winPtr);
+ *border_width_return = winPtr->changes.border_width;
+ *depth_return = Tk_Depth(winPtr);
+ } else {
+ CGSize size = ((MacDrawable *) d)->size;
+ *x_return = 0;
+ *y_return = 0;
+ *width_return = size.width;
+ *height_return = size.height;
+ *border_width_return = 0;
+ *depth_return = 32;
+ }
+ return 1;
+}
+
+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();
+}
+
+int
+XBell(
+ Display* display,
+ int percent)
+{
+ NSBeep();
+ return Success;
+}
+
+#if 0
+void
+XSetWMNormalHints(
+ Display* display,
+ Window w,
+ XSizeHints* hints)
+{
+ /*
+ * Do nothing. Shouldn't even be called.
+ */
+}
+
+XSizeHints *
+XAllocSizeHints(void)
+{
+ /*
+ * Always return NULL. Tk code checks to see if NULL is returned & does
+ * nothing if it is.
+ */
+
+ return NULL;
+}
+#endif
+
+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)
+{
+}
+
+/*
+int
+XDrawPoint(
+ Display* display,
+ Drawable d,
+ GC gc,
+ int x,
+ int y)
+{
+}
+
+int
+XDrawPoints(
+ Display* display,
+ Drawable d,
+ GC gc,
+ XPoint* points,
+ int npoints,
+ int mode)
+{
+}
+*/
+
+int
+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)
+{
+ return Success;
+}
+
+void
+XQueryColor(
+ Display* display,
+ Colormap colormap,
+ XColor* def_in_out)
+{
+ unsigned long p;
+ unsigned char r, g, b;
+ XColor *d = def_in_out;
+
+ p = d->pixel;
+ r = (p & 0x00FF0000) >> 16;
+ g = (p & 0x0000FF00) >> 8;
+ b = (p & 0x000000FF);
+ d->red = (r << 8) | r;
+ d->green = (g << 8) | g;
+ d->blue = (b << 8) | b;
+ d->flags = DoRed|DoGreen|DoBlue;
+ d->pad = 0;
+}
+
+void
+XQueryColors(
+ Display* display,
+ Colormap colormap,
+ XColor* defs_in_out,
+ int ncolors)
+{
+ int i;
+ unsigned long p;
+ unsigned char r, g, b;
+ XColor *d = defs_in_out;
+
+ for (i = 0; i < ncolors; i++, d++) {
+ p = d->pixel;
+ r = (p & 0x00FF0000) >> 16;
+ g = (p & 0x0000FF00) >> 8;
+ b = (p & 0x000000FF);
+ d->red = (r << 8) | r;
+ d->green = (g << 8) | g;
+ d->blue = (b << 8) | b;
+ d->flags = DoRed|DoGreen|DoBlue;
+ d->pad = 0;
+ }
+}
+
+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. */
+}
+
+int
+XSync(
+ Display *display,
+ Bool flag)
+{
+ TkMacOSXFlushWindows();
+ display->request++;
+ return 0;
+}
+
+#if 0
+int
+XSetClipRectangles(
+ Display *d,
+ GC gc,
+ int clip_x_origin,
+ int clip_y_origin,
+ XRectangle* rectangles,
+ int n,
+ int ordering)
+{
+ TkRegion clipRgn = TkCreateRegion();
+
+ while (n--) {
+ XRectangle rect = *rectangles;
+
+ rect.x += clip_x_origin;
+ rect.y += clip_y_origin;
+ TkUnionRectWithRegion(&rect, clipRgn, clipRgn);
+ rectangles++;
+ }
+ TkSetRegion(d, gc, clipRgn);
+ TkDestroyRegion(clipRgn);
+ return 1;
+}
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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[5 + TCL_INTEGER_SPACE * 2];
+ char buffer2[11 + TCL_INTEGER_SPACE];
+
+ snprintf(buffer, sizeof(buffer), "CG%d.%d ",
+ ProtocolVersion(Tk_Display(tkwin)),
+ ProtocolRevision(Tk_Display(tkwin)));
+ snprintf(buffer2, sizeof(buffer2), " Mac OS X %x",
+ VendorRelease(Tk_Display(tkwin)));
+ Tcl_AppendResult(interp, buffer, ServerVendor(Tk_Display(tkwin)),
+ buffer2, NULL);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XChangeWindowAttributes, XSetWindowBackground,
+ * XSetWindowBackgroundPixmap, XSetWindowBorder, XSetWindowBorderPixmap,
+ * XSetWindowBorderWidth, XSetWindowColormap
+ *
+ * These functions are all no-ops. They all have equivalent 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 ((screenName == NULL) || (screenName[0] == '\0')) {
+ screenName = macScreenName;
+ }
+ return screenName;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetUserInactiveTime --
+ *
+ * Return the number of milliseconds the user was inactive.
+ *
+ * Results:
+ * The number of milliseconds the user has been inactive, or -1 if
+ * querying the inactive time is not supported.
+ *
+ * Side effects:
+ * None.
+ *----------------------------------------------------------------------
+ */
+
+long
+Tk_GetUserInactiveTime(
+ Display *dpy)
+{
+ io_registry_entry_t regEntry;
+ CFMutableDictionaryRef props = NULL;
+ CFTypeRef timeObj;
+ long ret = -1l;
+ uint64_t time;
+ IOReturn result;
+
+ regEntry = IOServiceGetMatchingService(kIOMasterPortDefault,
+ IOServiceMatching("IOHIDSystem"));
+
+ if (regEntry == 0) {
+ return -1l;
+ }
+
+ result = IORegistryEntryCreateCFProperties(regEntry, &props,
+ kCFAllocatorDefault, 0);
+ IOObjectRelease(regEntry);
+
+ if (result != KERN_SUCCESS || props == NULL) {
+ return -1l;
+ }
+
+ timeObj = CFDictionaryGetValue(props, CFSTR("HIDIdleTime"));
+
+ if (timeObj) {
+ CFNumberGetValue((CFNumberRef)timeObj,
+ kCFNumberSInt64Type, &time);
+ /* Convert nanoseconds to milliseconds. */
+ ret = (long) (time/kMillisecondScale);
+ }
+ /* Cleanup */
+ CFRelease(props);
+
+ /*
+ * If the idle time reported by the system is larger than the elapsed
+ * time since the last reset, return the elapsed time.
+ */
+ long elapsed = (long)(TkpGetMS() - lastInactivityReset);
+ if (ret > elapsed) {
+ ret = elapsed;
+ }
+
+ return ret;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_ResetUserInactiveTime --
+ *
+ * Reset the user inactivity timer
+ *
+ * Results:
+ * none
+ *
+ * Side effects:
+ * The user inactivity timer of the underlaying windowing system is reset
+ * to zero.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_ResetUserInactiveTime(
+ Display *dpy)
+{
+ lastInactivityReset = TkpGetMS();
+}
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/macosx/ttkMacOSXTheme.c b/tk8.6/macosx/ttkMacOSXTheme.c
new file mode 100644
index 0000000..50c79bb
--- /dev/null
+++ b/tk8.6/macosx/ttkMacOSXTheme.c
@@ -0,0 +1,3186 @@
+/*
+ * ttkMacOSXTheme.c --
+ *
+ * Tk theme engine for Mac OSX, using the Appearance Manager API.
+ *
+ * Copyright (c) 2004 Joe English
+ * Copyright (c) 2005 Neil Madden
+ * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright 2008-2009, Apple Inc.
+ * Copyright 2009 Kevin Walzer/WordTech Communications LLC.
+ * Copyright 2019 Marc Culler
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * See also:
+ *
+ * <URL: http://developer.apple.com/documentation/Carbon/Reference/
+ * Appearance_Manager/appearance_manager/APIIndex.html >
+ *
+ * Notes:
+ * "Active" means different things in Mac and Tk terminology --
+ * On Aqua, widgets are "Active" if they belong to the foreground window,
+ * "Inactive" if they are in a background window. Tk uses the term
+ * "active" to mean that the mouse cursor is over a widget; aka "hover",
+ * "prelight", or "hot-tracked". Aqua doesn't use this kind of feedback.
+ *
+ * The QuickDraw/Carbon coordinate system is relative to the top-level
+ * window, not to the Tk_Window. BoxToRect() accounts for this.
+ */
+
+#include "tkMacOSXPrivate.h"
+#include "ttk/ttkTheme.h"
+#include <math.h>
+
+/*
+ * Macros for handling drawing contexts.
+ */
+
+#define BEGIN_DRAWING(d) { \
+ TkMacOSXDrawingContext dc; \
+ if (!TkMacOSXSetupDrawingContext((d), NULL, 1, &dc)) {return;}
+#define END_DRAWING \
+ TkMacOSXRestoreDrawingContext(&dc);}
+
+#define HIOrientation kHIThemeOrientationNormal
+#define NoThemeMetric 0xFFFFFFFF
+
+#ifdef __LP64__
+#define RangeToFactor(maximum) (((double) (INT_MAX >> 1)) / (maximum))
+#else
+#define RangeToFactor(maximum) (((double) (LONG_MAX >> 1)) / (maximum))
+#endif /* __LP64__ */
+
+#define TTK_STATE_FIRST_TAB TTK_STATE_USER1
+#define TTK_STATE_LAST_TAB TTK_STATE_USER2
+#define TTK_TREEVIEW_STATE_SORTARROW TTK_STATE_USER1
+
+/*
+ * Colors and gradients used in Dark Mode.
+ */
+
+static CGFloat darkButtonFace[4] = {
+ 112.0 / 255, 113.0 / 255, 115.0 / 255, 1.0
+};
+static CGFloat darkPressedBevelFace[4] = {
+ 135.0 / 255, 136.0 / 255, 138.0 / 255, 1.0
+};
+static CGFloat darkSelectedBevelFace[4] = {
+ 162.0 / 255, 163.0 / 255, 165.0 / 255, 1.0
+};
+static CGFloat darkDisabledButtonFace[4] = {
+ 86.0 / 255, 87.0 / 255, 89.0 / 255, 1.0
+};
+static CGFloat darkInactiveSelectedTab[4] = {
+ 159.0 / 255, 160.0 / 255, 161.0 / 255, 1.0
+};
+static CGFloat darkFocusRing[4] = {
+ 38.0 / 255, 113.0 / 255, 159.0 / 255, 1.0
+};
+static CGFloat darkFocusRingTop[4] = {
+ 50.0 / 255, 124.0 / 255, 171.0 / 255, 1.0
+};
+static CGFloat darkFocusRingBottom[4] = {
+ 57.0 / 255, 130.0 / 255, 176.0 / 255, 1.0
+};
+static CGFloat darkTabSeparator[4] = {0.0, 0.0, 0.0, 0.25};
+static CGFloat darkTrack[4] = {1.0, 1.0, 1.0, 0.25};
+static CGFloat darkFrameTop[4] = {1.0, 1.0, 1.0, 0.0625};
+static CGFloat darkFrameBottom[4] = {1.0, 1.0, 1.0, 0.125};
+static CGFloat darkFrameAccent[4] = {0.0, 0.0, 0.0, 0.0625};
+static CGFloat darkTopGradient[8] = {
+ 1.0, 1.0, 1.0, 0.3,
+ 1.0, 1.0, 1.0, 0.0
+};
+static CGFloat darkBackgroundGradient[8] = {
+ 0.0, 0.0, 0.0, 0.1,
+ 0.0, 0.0, 0.0, 0.25
+};
+static CGFloat darkInactiveGradient[8] = {
+ 89.0 / 255, 90.0 / 255, 93.0 / 255, 1.0,
+ 119.0 / 255, 120.0 / 255, 122.0 / 255, 1.0
+};
+static CGFloat darkSelectedGradient[8] = {
+ 23.0 / 255, 111.0 / 255, 232.0 / 255, 1.0,
+ 20.0 / 255, 94.0 / 255, 206.0 / 255, 1.0
+};
+
+/*
+ * When building on systems earlier than 10.8 there is no reasonable way to
+ * convert an NSColor to a CGColor. We do run-time checking of the OS version,
+ * and never need the CGColor property on older systems, so we can use this
+ * CGCOLOR macro, which evaluates to NULL without raising compiler warnings.
+ * Similarly, we never draw rounded rectangles on older systems which did not
+ * have CGPathCreateWithRoundedRect, so we just redefine it to return NULL.
+ */
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
+#define CGCOLOR(nscolor) nscolor.CGColor
+#else
+#define CGCOLOR(nscolor) (0 ? (CGColorRef) nscolor : NULL)
+#define CGPathCreateWithRoundedRect(w, x, y, z) NULL
+#endif
+
+/*----------------------------------------------------------------------
+ * +++ Utilities.
+ */
+
+/*
+ * BoxToRect --
+ * Convert a Ttk_Box in Tk coordinates relative to the given Drawable
+ * to a native Rect relative to the containing port.
+ */
+
+static inline CGRect BoxToRect(
+ Drawable d,
+ Ttk_Box b)
+{
+ MacDrawable *md = (MacDrawable *) d;
+ CGRect rect;
+
+ rect.origin.y = b.y + md->yOff;
+ rect.origin.x = b.x + md->xOff;
+ rect.size.height = b.height;
+ rect.size.width = b.width;
+
+ return rect;
+}
+
+/*
+ * Table mapping Tk states to Appearance manager ThemeStates
+ */
+
+static Ttk_StateTable ThemeStateTable[] = {
+ {kThemeStateUnavailable, TTK_STATE_DISABLED, 0},
+ {kThemeStatePressed, TTK_STATE_PRESSED, 0},
+ {kThemeStateInactive, TTK_STATE_BACKGROUND, 0},
+ {kThemeStateActive, 0, 0}
+
+ /* Others: Not sure what these are supposed to mean. Up/Down have
+ * something to do with "little arrow" increment controls... Dunno what
+ * a "Rollover" is.
+ * NEM: Rollover is TTK_STATE_ACTIVE... but we don't handle that yet, by
+ * the looks of things
+ *
+ * {kThemeStateRollover, 0, 0},
+ * {kThemeStateUnavailableInactive, 0, 0}
+ * {kThemeStatePressedUp, 0, 0},
+ * {kThemeStatePressedDown, 0, 0}
+ */
+};
+
+/*----------------------------------------------------------------------
+ * NormalizeButtonBounds --
+ *
+ * Apple's Human Interface Guidelines only allow three specific heights
+ * for most buttons: Regular, small and mini. We always use the regular
+ * size. However, Ttk may provide an arbitrary bounding rectangle. We
+ * always draw the button centered vertically on the rectangle, and
+ * having the same width as the rectangle. This function returns the
+ * actual bounding rectangle that will be used in drawing the button.
+ *
+ * The BevelButton is allowed to have arbitrary size, and also has
+ * external padding. This is handled separately here.
+ */
+
+static CGRect NormalizeButtonBounds(
+ SInt32 heightMetric,
+ CGRect bounds)
+{
+ SInt32 height;
+
+ if (heightMetric != (SInt32) NoThemeMetric) {
+ ChkErr(GetThemeMetric, heightMetric, &height);
+ bounds.origin.y += (bounds.size.height - height) / 2;
+ bounds.size.height = height;
+ }
+ return bounds;
+}
+
+/*----------------------------------------------------------------------
+ * +++ Backgrounds
+ *
+ * Support for contrasting background colors when GroupBoxes or Tabbed
+ * panes are nested inside each other. Early versions of macOS used ridged
+ * borders, so do not need contrasting backgrounds.
+ */
+
+/*
+ * For systems older than 10.14, [NSColor windowBackGroundColor] generates
+ * garbage when called from this function. In 10.14 it works correctly, and
+ * must be used in order to have a background color which responds to Dark
+ * Mode. So we use this hard-wired RGBA color on the older systems which don't
+ * support Dark Mode anyway.
+ */
+
+static CGFloat windowBackground[4] = {
+ 235.0 / 255, 235.0 / 255, 235.0 / 255, 1.0
+};
+static CGFloat whiteRGBA[4] = {1.0, 1.0, 1.0, 1.0};
+static CGFloat blackRGBA[4] = {0.0, 0.0, 0.0, 1.0};
+
+/*----------------------------------------------------------------------
+ * GetBackgroundColor --
+ *
+ * Fills the array rgba with the color coordinates for a background color.
+ * Start with the background color of a window's geometry master, or the
+ * standard ttk window background if there is no master. If the contrast
+ * parameter is nonzero, modify this color to be darker, for the aqua
+ * appearance, or lighter for the DarkAqua appearance. This is primarily
+ * used by the Fill and Background elements.
+ */
+
+static void GetBackgroundColor(
+ CGContextRef context,
+ Tk_Window tkwin,
+ int contrast,
+ CGFloat *rgba)
+{
+ TkWindow *winPtr = (TkWindow *) tkwin;
+ TkWindow *masterPtr = (TkWindow *) TkGetGeomMaster(tkwin);
+
+ while (masterPtr != NULL) {
+ if (masterPtr->privatePtr->flags & TTK_HAS_CONTRASTING_BG) {
+ break;
+ }
+ masterPtr = (TkWindow *) TkGetGeomMaster(masterPtr);
+ }
+ if (masterPtr) {
+ for (int i = 0; i < 4; i++) {
+ rgba[i] = masterPtr->privatePtr->fillRGBA[i];
+ }
+ } else {
+ if ([NSApp macMinorVersion] > 13) {
+ NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
+ NSColor *windowColor = [[NSColor windowBackgroundColor]
+ colorUsingColorSpace: deviceRGB];
+ [windowColor getComponents: rgba];
+ } else {
+ for (int i = 0; i < 4; i++) {
+ rgba[i] = windowBackground[i];
+ }
+ }
+ }
+ if (contrast) {
+ int isDark = (rgba[0] + rgba[1] + rgba[2] < 1.5);
+
+ if (isDark) {
+ for (int i = 0; i < 3; i++) {
+ rgba[i] += 8.0 / 255.0;
+ }
+ } else {
+ for (int i = 0; i < 3; i++) {
+ rgba[i] -= 8.0 / 255.0;
+ }
+ }
+ winPtr->privatePtr->flags |= TTK_HAS_CONTRASTING_BG;
+ for (int i = 0; i < 4; i++) {
+ winPtr->privatePtr->fillRGBA[i] = rgba[i];
+ }
+ }
+}
+
+
+/*----------------------------------------------------------------------
+ * +++ Single Arrow Buttons --
+ *
+ * Used in ListHeaders and Comboboxes.
+ */
+
+static void DrawDownArrow(
+ CGContextRef context,
+ CGRect bounds,
+ CGFloat inset,
+ CGFloat size,
+ CGFloat *rgba)
+{
+ CGFloat x, y;
+
+ CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]);
+ CGContextSetLineWidth(context, 1.5);
+ x = bounds.origin.x + inset;
+ y = bounds.origin.y + trunc(bounds.size.height / 2);
+ CGContextBeginPath(context);
+ CGPoint arrow[3] = {
+ {x, y - size / 4}, {x + size / 2, y + size / 4},
+ {x + size, y - size / 4}
+ };
+ CGContextAddLines(context, arrow, 3);
+ CGContextStrokePath(context);
+}
+
+static void DrawUpArrow(
+ CGContextRef context,
+ CGRect bounds,
+ CGFloat inset,
+ CGFloat size,
+ CGFloat *rgba)
+{
+ CGFloat x, y;
+
+ CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]);
+ CGContextSetLineWidth(context, 1.5);
+ x = bounds.origin.x + inset;
+ y = bounds.origin.y + trunc(bounds.size.height / 2);
+ CGContextBeginPath(context);
+ CGPoint arrow[3] = {
+ {x, y + size / 4}, {x + size / 2, y - size / 4},
+ {x + size, y + size / 4}
+ };
+ CGContextAddLines(context, arrow, 3);
+ CGContextStrokePath(context);
+}
+
+/*----------------------------------------------------------------------
+ * +++ Double Arrow Buttons --
+ *
+ * Used in MenuButtons and SpinButtons.
+ */
+
+static void DrawUpDownArrows(
+ CGContextRef context,
+ CGRect bounds,
+ CGFloat inset,
+ CGFloat size,
+ CGFloat *rgba)
+{
+ CGFloat x, y;
+
+ CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]);
+ CGContextSetLineWidth(context, 1.5);
+ x = bounds.origin.x + inset;
+ y = bounds.origin.y + trunc(bounds.size.height / 2);
+ CGContextBeginPath(context);
+ CGPoint bottomArrow[3] =
+ {{x, y + 2}, {x + size / 2, y + 2 + size / 2}, {x + size, y + 2}};
+ CGContextAddLines(context, bottomArrow, 3);
+ CGPoint topArrow[3] =
+ {{x, y - 2}, {x + size / 2, y - 2 - size / 2}, {x + size, y - 2}};
+ CGContextAddLines(context, topArrow, 3);
+ CGContextStrokePath(context);
+}
+
+
+/*----------------------------------------------------------------------
+ * +++ FillButtonBackground --
+ *
+ * Fills a rounded rectangle with a transparent black gradient.
+ * This is a no-op if building on 10.8 or older.
+ */
+
+static void FillButtonBackground(
+ CGContextRef context,
+ CGRect bounds,
+ CGFloat radius)
+{
+ CGPathRef path;
+ NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
+ CGGradientRef backgroundGradient = CGGradientCreateWithColorComponents(
+ deviceRGB.CGColorSpace, darkBackgroundGradient, NULL, 2);
+ CGPoint backgroundEnd = {
+ bounds.origin.x,
+ bounds.origin.y + bounds.size.height
+ };
+
+ CGContextBeginPath(context);
+ path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL);
+ CGContextAddPath(context, path);
+ CGContextClip(context);
+ CGContextDrawLinearGradient(context, backgroundGradient,
+ bounds.origin, backgroundEnd, 0);
+ CFRelease(path);
+ CFRelease(backgroundGradient);
+}
+
+/*----------------------------------------------------------------------
+ * +++ HighlightButtonBorder --
+ *
+ * Accent the top border of a rounded rectangle with a transparent
+ * white gradient.
+ */
+
+static void HighlightButtonBorder(
+ CGContextRef context,
+ CGRect bounds)
+{
+ NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
+ CGPoint topEnd = {bounds.origin.x, bounds.origin.y + 3};
+ CGGradientRef topGradient = CGGradientCreateWithColorComponents(
+ deviceRGB.CGColorSpace, darkTopGradient, NULL, 2);
+
+ CGContextSaveGState(context);
+ CGContextBeginPath(context);
+ CGContextAddArc(context, bounds.origin.x + 4, bounds.origin.y + 4,
+ 4, PI, 3 * PI / 2, 0);
+ CGContextAddArc(context, bounds.origin.x + bounds.size.width - 4,
+ bounds.origin.y + 4, 4, 3 * PI / 2, 0, 0);
+ CGContextReplacePathWithStrokedPath(context);
+ CGContextClip(context);
+ CGContextDrawLinearGradient(context, topGradient, bounds.origin, topEnd,
+ 0.0);
+ CGContextRestoreGState(context);
+ CFRelease(topGradient);
+}
+
+/*----------------------------------------------------------------------
+ * DrawGroupBox --
+ *
+ * This is a standalone drawing procedure which draws the contrasting
+ * rounded rectangular box for LabelFrames and Notebook panes used in
+ * more recent versions of macOS.
+ */
+
+static void DrawGroupBox(
+ CGRect bounds,
+ CGContextRef context,
+ Tk_Window tkwin)
+{
+ CGPathRef path;
+ NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
+ NSColor *borderColor, *bgColor;
+ static CGFloat border[4] = {1.0, 1.0, 1.0, 0.25};
+ CGFloat fill[4];
+
+ GetBackgroundColor(context, tkwin, 1, fill);
+ bgColor = [NSColor colorWithColorSpace: deviceRGB components: fill
+ count: 4];
+ CGContextSetFillColorSpace(context, deviceRGB.CGColorSpace);
+ CGContextSetFillColorWithColor(context, CGCOLOR(bgColor));
+ path = CGPathCreateWithRoundedRect(bounds, 4, 4, NULL);
+ CGContextClipToRect(context, bounds);
+ CGContextBeginPath(context);
+ CGContextAddPath(context, path);
+ CGContextFillPath(context);
+ borderColor = [NSColor colorWithColorSpace: deviceRGB components: border
+ count: 4];
+ CGContextSetFillColorWithColor(context, CGCOLOR(borderColor));
+ [borderColor getComponents: fill];
+ CGContextSetRGBFillColor(context, fill[0], fill[1], fill[2], fill[3]);
+
+ CGContextBeginPath(context);
+ CGContextAddPath(context, path);
+ CGContextReplacePathWithStrokedPath(context);
+ CGContextFillPath(context);
+ CFRelease(path);
+}
+
+/*----------------------------------------------------------------------
+ * SolidFillRoundedRectangle --
+ *
+ * Fill a rounded rectangle with a specified solid color.
+ */
+
+static void SolidFillRoundedRectangle(
+ CGContextRef context,
+ CGRect bounds,
+ CGFloat radius,
+ NSColor *color)
+{
+ CGPathRef path;
+
+ CGContextSetFillColorWithColor(context, CGCOLOR(color));
+ path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL);
+ CGContextBeginPath(context);
+ CGContextAddPath(context, path);
+ CGContextFillPath(context);
+ CFRelease(path);
+}
+
+/*----------------------------------------------------------------------
+ * +++ DrawListHeader --
+ *
+ * This is a standalone drawing procedure which draws column headers for
+ * a Treeview in the Aqua appearance. The HITheme headers have not
+ * matched the native ones since OSX 10.8. Note that the header image is
+ * ignored, but we draw arrows according to the state.
+ */
+
+static void DrawListHeader(
+ CGRect bounds,
+ CGContextRef context,
+ Tk_Window tkwin,
+ int state)
+{
+ NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
+ NSColor *strokeColor, *bgColor;
+ static CGFloat borderRGBA[4] = {
+ 200.0 / 255, 200.0 / 255, 200.0 / 255, 1.0
+ };
+ static CGFloat separatorRGBA[4] = {
+ 220.0 / 255, 220.0 / 255, 220.0 / 255, 1.0
+ };
+ static CGFloat activeBgRGBA[4] = {
+ 238.0 / 255, 238.0 / 255, 238.0 / 255, 1.0
+ };
+ static CGFloat inactiveBgRGBA[4] = {
+ 246.0 / 255, 246.0 / 255, 246.0 / 255, 1.0
+ };
+
+ /*
+ * Apple changes the background of a list header when the window is not
+ * active. But Ttk does not indicate that in the state of a TreeHeader.
+ * So we have to query the Apple window manager.
+ */
+
+ NSWindow *win = TkMacOSXDrawableWindow(Tk_WindowId(tkwin));
+ CGFloat *bgRGBA = [win isKeyWindow] ? activeBgRGBA : inactiveBgRGBA;
+ CGFloat x = bounds.origin.x, y = bounds.origin.y;
+ CGFloat w = bounds.size.width, h = bounds.size.height;
+ CGPoint top[2] = {{x, y + 1}, {x + w, y + 1}};
+ CGPoint bottom[2] = {{x, y + h}, {x + w, y + h}};
+ CGPoint separator[2] = {{x + w - 1, y + 3}, {x + w - 1, y + h - 3}};
+
+ bgColor = [NSColor colorWithColorSpace: deviceRGB
+ components: bgRGBA
+ count: 4];
+ CGContextSaveGState(context);
+ CGContextSetShouldAntialias(context, false);
+ CGContextSetFillColorSpace(context, deviceRGB.CGColorSpace);
+ CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace);
+ CGContextBeginPath(context);
+ CGContextSetFillColorWithColor(context, CGCOLOR(bgColor));
+ CGContextAddRect(context, bounds);
+ CGContextFillPath(context);
+ strokeColor = [NSColor colorWithColorSpace: deviceRGB
+ components: separatorRGBA
+ count: 4];
+ CGContextSetStrokeColorWithColor(context, CGCOLOR(strokeColor));
+ CGContextAddLines(context, separator, 2);
+ CGContextStrokePath(context);
+ strokeColor = [NSColor colorWithColorSpace: deviceRGB
+ components: borderRGBA
+ count: 4];
+ CGContextSetStrokeColorWithColor(context, CGCOLOR(strokeColor));
+ CGContextAddLines(context, top, 2);
+ CGContextStrokePath(context);
+ CGContextAddLines(context, bottom, 2);
+ CGContextStrokePath(context);
+ CGContextRestoreGState(context);
+
+ if (state & TTK_TREEVIEW_STATE_SORTARROW) {
+ CGRect arrowBounds = bounds;
+ arrowBounds.origin.x = bounds.origin.x + bounds.size.width - 16;
+ arrowBounds.size.width = 16;
+ if (state & TTK_STATE_ALTERNATE) {
+ DrawUpArrow(context, arrowBounds, 3, 8, blackRGBA);
+ } else if (state & TTK_STATE_SELECTED) {
+ DrawDownArrow(context, arrowBounds, 3, 8, blackRGBA);
+ }
+ }
+}
+
+/*----------------------------------------------------------------------
+ * +++ Drawing procedures for widgets in Apple's "Dark Mode" (10.14 and up).
+ *
+ * The HIToolbox does not support Dark Mode, and apparently never will,
+ * so to make widgets look "native" we have to provide analogues of the
+ * HITheme drawing functions to be used in DarkAqua. We continue to use
+ * HITheme in Aqua, since it understands earlier versions of the OS.
+ *
+ * Drawing the dark widgets requires NSColors that were introduced in OSX
+ * 10.14, so we make some of these functions be no-ops when building on
+ * systems older than 10.14.
+ */
+
+/*----------------------------------------------------------------------
+ * GradientFillRoundedRectangle --
+ *
+ * Fill a rounded rectangle with a specified gradient.
+ */
+
+static void GradientFillRoundedRectangle(
+ CGContextRef context,
+ CGRect bounds,
+ CGFloat radius,
+ CGFloat *colors,
+ int numColors)
+{
+ NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
+ CGPathRef path;
+ CGPoint end = {
+ bounds.origin.x,
+ bounds.origin.y + bounds.size.height
+ };
+ CGGradientRef gradient = CGGradientCreateWithColorComponents(
+ deviceRGB.CGColorSpace, colors, NULL, numColors);
+
+ path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL);
+ CGContextBeginPath(context);
+ CGContextAddPath(context, path);
+ CGContextClip(context);
+ CGContextDrawLinearGradient(context, gradient, bounds.origin, end, 0);
+ CFRelease(path);
+ CFRelease(gradient);
+}
+
+/*----------------------------------------------------------------------
+ * +++ DrawDarkButton --
+ *
+ * This is a standalone drawing procedure which draws PushButtons and
+ * PopupButtons in the Dark Mode style.
+ */
+
+static void DrawDarkButton(
+ CGRect bounds,
+ ThemeButtonKind kind,
+ Ttk_State state,
+ CGContextRef context)
+{
+ NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
+ NSColor *faceColor;
+
+ /*
+ * To match the appearance of Apple's buttons we need to increase the
+ * height by 1 pixel.
+ */
+
+ bounds.size.height += 1;
+
+ CGContextClipToRect(context, bounds);
+ FillButtonBackground(context, bounds, 5);
+
+ /*
+ * Fill the button face with the appropriate color.
+ */
+
+ bounds = CGRectInset(bounds, 1, 1);
+ if (kind == kThemePushButton && (state & TTK_STATE_PRESSED)) {
+ GradientFillRoundedRectangle(context, bounds, 4,
+ darkSelectedGradient, 2);
+ } else {
+ if (state & TTK_STATE_DISABLED) {
+ faceColor = [NSColor colorWithColorSpace: deviceRGB
+ components: darkDisabledButtonFace
+ count: 4];
+ } else {
+ faceColor = [NSColor colorWithColorSpace: deviceRGB
+ components: darkButtonFace
+ count: 4];
+ }
+ SolidFillRoundedRectangle(context, bounds, 4, faceColor);
+ }
+
+ /*
+ * If this is a popup, draw the arrow button.
+ */
+
+ if ((kind == kThemePopupButton) | (kind == kThemeComboBox)) {
+ CGRect arrowBounds = bounds;
+ arrowBounds.size.width = 16;
+ arrowBounds.origin.x += bounds.size.width - 16;
+
+ /*
+ * If the toplevel is front, paint the button blue.
+ */
+
+ if (!(state & TTK_STATE_BACKGROUND) &&
+ !(state & TTK_STATE_DISABLED)) {
+ GradientFillRoundedRectangle(context, arrowBounds, 4,
+ darkSelectedGradient, 2);
+ }
+ if (kind == kThemePopupButton) {
+ DrawUpDownArrows(context, arrowBounds, 3, 7, whiteRGBA);
+ } else {
+ DrawDownArrow(context, arrowBounds, 4, 8, whiteRGBA);
+ }
+ }
+
+ HighlightButtonBorder(context, bounds);
+}
+
+/*----------------------------------------------------------------------
+ * +++ DrawDarkIncDecButton --
+ *
+ * This is a standalone drawing procedure which draws an IncDecButton
+ * (as used in a Spinbox) in the Dark Mode style.
+ */
+
+static void DrawDarkIncDecButton(
+ CGRect bounds,
+ ThemeDrawState drawState,
+ Ttk_State state,
+ CGContextRef context)
+{
+ NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
+ NSColor *faceColor;
+
+ bounds = CGRectInset(bounds, 0, -1);
+ CGContextClipToRect(context, bounds);
+ FillButtonBackground(context, bounds, 6);
+
+ /*
+ * Fill the button face with the appropriate color.
+ */
+
+ bounds = CGRectInset(bounds, 1, 1);
+ if (state & TTK_STATE_DISABLED) {
+ faceColor = [NSColor colorWithColorSpace: deviceRGB
+ components: darkDisabledButtonFace
+ count: 4];
+ } else {
+ faceColor = [NSColor colorWithColorSpace: deviceRGB
+ components: darkButtonFace
+ count: 4];
+ }
+ SolidFillRoundedRectangle(context, bounds, 4, faceColor);
+
+ /*
+ * If pressed, paint the appropriate half blue.
+ */
+
+ if (state & TTK_STATE_PRESSED) {
+ CGRect clip = bounds;
+ clip.size.height /= 2;
+ CGContextSaveGState(context);
+ if (drawState == kThemeStatePressedDown) {
+ clip.origin.y += clip.size.height;
+ }
+ CGContextClipToRect(context, clip);
+ GradientFillRoundedRectangle(context, bounds, 5,
+ darkSelectedGradient, 2);
+ CGContextRestoreGState(context);
+ }
+ DrawUpDownArrows(context, bounds, 3, 5, whiteRGBA);
+ HighlightButtonBorder(context, bounds);
+}
+
+/*----------------------------------------------------------------------
+ * +++ DrawDarkBevelButton --
+ *
+ * This is a standalone drawing procedure which draws RoundedBevelButtons
+ * in the Dark Mode style.
+ */
+
+static void DrawDarkBevelButton(
+ CGRect bounds,
+ Ttk_State state,
+ CGContextRef context)
+{
+ NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
+ NSColor *faceColor;
+
+ CGContextClipToRect(context, bounds);
+ FillButtonBackground(context, bounds, 5);
+
+ /*
+ * Fill the button face with the appropriate color.
+ */
+
+ bounds = CGRectInset(bounds, 1, 1);
+ if (state & TTK_STATE_PRESSED) {
+ faceColor = [NSColor colorWithColorSpace: deviceRGB
+ components: darkPressedBevelFace
+ count: 4];
+ } else if ((state & TTK_STATE_DISABLED) ||
+ (state & TTK_STATE_ALTERNATE)) {
+ faceColor = [NSColor colorWithColorSpace: deviceRGB
+ components: darkDisabledButtonFace
+ count: 4];
+ } else if (state & TTK_STATE_SELECTED) {
+ faceColor = [NSColor colorWithColorSpace: deviceRGB
+ components: darkSelectedBevelFace
+ count: 4];
+ } else {
+ faceColor = [NSColor colorWithColorSpace: deviceRGB
+ components: darkButtonFace
+ count: 4];
+ }
+ SolidFillRoundedRectangle(context, bounds, 4, faceColor);
+ HighlightButtonBorder(context, bounds);
+}
+
+/*----------------------------------------------------------------------
+ * +++ DrawDarkCheckBox --
+ *
+ * This is a standalone drawing procedure which draws Checkboxes in the
+ * Dark Mode style.
+ */
+
+static void DrawDarkCheckBox(
+ CGRect bounds,
+ Ttk_State state,
+ CGContextRef context)
+{
+ CGRect checkbounds = {{0, bounds.size.height / 2 - 8}, {16, 16}};
+ NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
+ NSColor *stroke;
+ CGFloat x, y;
+
+ bounds = CGRectOffset(checkbounds, bounds.origin.x, bounds.origin.y);
+ x = bounds.origin.x;
+ y = bounds.origin.y;
+
+ CGContextClipToRect(context, bounds);
+ FillButtonBackground(context, bounds, 4);
+ bounds = CGRectInset(bounds, 1, 1);
+ if (!(state & TTK_STATE_BACKGROUND) &&
+ !(state & TTK_STATE_DISABLED) &&
+ ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE))) {
+ GradientFillRoundedRectangle(context, bounds, 3,
+ darkSelectedGradient, 2);
+ } else {
+ GradientFillRoundedRectangle(context, bounds, 3,
+ darkInactiveGradient, 2);
+ }
+ HighlightButtonBorder(context, bounds);
+ if ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE)) {
+ CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace);
+ if (state & TTK_STATE_DISABLED) {
+ stroke = [NSColor disabledControlTextColor];
+ } else {
+ stroke = [NSColor controlTextColor];
+ }
+ CGContextSetStrokeColorWithColor(context, CGCOLOR(stroke));
+ }
+ if (state & TTK_STATE_SELECTED) {
+ CGContextSetLineWidth(context, 1.5);
+ CGContextBeginPath(context);
+ CGPoint check[3] = {{x + 4, y + 8}, {x + 7, y + 11}, {x + 11, y + 4}};
+ CGContextAddLines(context, check, 3);
+ CGContextStrokePath(context);
+ } else if (state & TTK_STATE_ALTERNATE) {
+ CGContextSetLineWidth(context, 2.0);
+ CGContextBeginPath(context);
+ CGPoint bar[2] = {{x + 4, y + 8}, {x + 12, y + 8}};
+ CGContextAddLines(context, bar, 2);
+ CGContextStrokePath(context);
+ }
+}
+
+/*----------------------------------------------------------------------
+ * +++ DrawDarkRadioButton --
+ *
+ * This is a standalone drawing procedure which draws RadioButtons
+ * in the Dark Mode style.
+ */
+
+static void DrawDarkRadioButton(
+ CGRect bounds,
+ Ttk_State state,
+ CGContextRef context)
+{
+ CGRect checkbounds = {{0, bounds.size.height / 2 - 9}, {18, 18}};
+ NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
+ NSColor *fill;
+ CGFloat x, y;
+
+ bounds = CGRectOffset(checkbounds, bounds.origin.x, bounds.origin.y);
+ x = bounds.origin.x;
+ y = bounds.origin.y;
+
+ CGContextClipToRect(context, bounds);
+ FillButtonBackground(context, bounds, 9);
+ bounds = CGRectInset(bounds, 1, 1);
+ if (!(state & TTK_STATE_BACKGROUND) &&
+ !(state & TTK_STATE_DISABLED) &&
+ ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE))) {
+ GradientFillRoundedRectangle(context, bounds, 8,
+ darkSelectedGradient, 2);
+ } else {
+ GradientFillRoundedRectangle(context, bounds, 8,
+ darkInactiveGradient, 2);
+ }
+ HighlightButtonBorder(context, bounds);
+ if ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE)) {
+ CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace);
+ if (state & TTK_STATE_DISABLED) {
+ fill = [NSColor disabledControlTextColor];
+ } else {
+ fill = [NSColor controlTextColor];
+ }
+ CGContextSetFillColorWithColor(context, CGCOLOR(fill));
+ }
+ if (state & TTK_STATE_SELECTED) {
+ CGContextBeginPath(context);
+ CGRect dot = {{x + 6, y + 6}, {6, 6}};
+ CGContextAddEllipseInRect(context, dot);
+ CGContextFillPath(context);
+ } else if (state & TTK_STATE_ALTERNATE) {
+ CGRect bar = {{x + 5, y + 8}, {8, 2}};
+ CGContextFillRect(context, bar);
+ }
+}
+
+/*----------------------------------------------------------------------
+ * +++ DrawDarkTab --
+ *
+ * This is a standalone drawing procedure which draws Tabbed Pane
+ * Tabs in the Dark Mode style.
+ */
+
+static void DrawDarkTab(
+ CGRect bounds,
+ Ttk_State state,
+ CGContextRef context)
+{
+ NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
+ NSColor *faceColor, *stroke;
+ CGRect originalBounds = bounds;
+
+ CGContextSetLineWidth(context, 1.0);
+ CGContextClipToRect(context, bounds);
+
+ /*
+ * Extend the bounds to one or both sides so the rounded part will be
+ * clipped off.
+ */
+
+ if (!(state & TTK_STATE_FIRST_TAB)) {
+ bounds.origin.x -= 10;
+ bounds.size.width += 10;
+ }
+
+ if (!(state & TTK_STATE_LAST_TAB)) {
+ bounds.size.width += 10;
+ }
+
+ /*
+ * Fill the tab face with the appropriate color or gradient. Use a solid
+ * color if the tab is not selected, otherwise use a blue or gray
+ * gradient.
+ */
+
+ bounds = CGRectInset(bounds, 1, 1);
+ if (!(state & TTK_STATE_SELECTED)) {
+ if (state & TTK_STATE_DISABLED) {
+ faceColor = [NSColor colorWithColorSpace: deviceRGB
+ components: darkDisabledButtonFace
+ count: 4];
+ } else {
+ faceColor = [NSColor colorWithColorSpace: deviceRGB
+ components: darkButtonFace
+ count: 4];
+ }
+ SolidFillRoundedRectangle(context, bounds, 4, faceColor);
+
+ /*
+ * Draw a separator line on the left side of the tab if it
+ * not first.
+ */
+
+ if (!(state & TTK_STATE_FIRST_TAB)) {
+ CGContextSaveGState(context);
+ CGContextSetShouldAntialias(context, false);
+ stroke = [NSColor colorWithColorSpace: deviceRGB
+ components: darkTabSeparator
+ count: 4];
+ CGContextSetStrokeColorWithColor(context, CGCOLOR(stroke));
+ CGContextBeginPath(context);
+ CGContextMoveToPoint(context, originalBounds.origin.x,
+ originalBounds.origin.y + 1);
+ CGContextAddLineToPoint(context, originalBounds.origin.x,
+ originalBounds.origin.y + originalBounds.size.height - 1);
+ CGContextStrokePath(context);
+ CGContextRestoreGState(context);
+ }
+ } else {
+
+ /*
+ * This is the selected tab; paint it blue. If it is first, cover up
+ * the separator line drawn by the second one. (The selected tab is
+ * always drawn last.)
+ */
+
+ if ((state & TTK_STATE_FIRST_TAB) && !(state & TTK_STATE_LAST_TAB)) {
+ bounds.size.width += 1;
+ }
+ if (!(state & TTK_STATE_BACKGROUND)) {
+ GradientFillRoundedRectangle(context, bounds, 4,
+ darkSelectedGradient, 2);
+ } else {
+ faceColor = [NSColor colorWithColorSpace: deviceRGB
+ components: darkInactiveSelectedTab
+ count: 4];
+ SolidFillRoundedRectangle(context, bounds, 4, faceColor);
+ }
+ HighlightButtonBorder(context, bounds);
+ }
+}
+
+/*----------------------------------------------------------------------
+ * +++ DrawDarkSeparator --
+ *
+ * This is a standalone drawing procedure which draws a separator widget
+ * in Dark Mode.
+ */
+
+static void DrawDarkSeparator(
+ CGRect bounds,
+ CGContextRef context,
+ Tk_Window tkwin)
+{
+ static CGFloat fill[4] = {1.0, 1.0, 1.0, 0.3};
+ NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
+ NSColor *fillColor = [NSColor colorWithColorSpace: deviceRGB
+ components: fill
+ count:4];
+
+ CGContextSetFillColorWithColor(context, CGCOLOR(fillColor));
+ CGContextFillRect(context, bounds);
+}
+
+/*----------------------------------------------------------------------
+ * +++ DrawDarkFocusRing --
+ *
+ * This is a standalone drawing procedure which draws a focus ring around
+ * an Entry widget in Dark Mode.
+ */
+
+static void DrawDarkFocusRing(
+ CGRect bounds,
+ CGContextRef context)
+{
+ NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
+ NSColor *strokeColor;
+ NSColor *fillColor = [NSColor colorWithColorSpace:deviceRGB
+ components:darkFocusRing
+ count:4];
+ CGFloat x = bounds.origin.x, y = bounds.origin.y;
+ CGFloat w = bounds.size.width, h = bounds.size.height;
+ CGPoint topPart[4] = {
+ {x, y + h}, {x, y + 1}, {x + w - 1, y + 1}, {x + w - 1, y + h}
+ };
+ CGPoint bottom[2] = {{x, y + h}, {x + w, y + h}};
+
+ CGContextSaveGState(context);
+ CGContextSetShouldAntialias(context, false);
+ CGContextBeginPath(context);
+ strokeColor = [NSColor colorWithColorSpace: deviceRGB
+ components: darkFocusRingTop
+ count: 4];
+ CGContextSetStrokeColorWithColor(context, CGCOLOR(strokeColor));
+ CGContextAddLines(context, topPart, 4);
+ CGContextStrokePath(context);
+ strokeColor = [NSColor colorWithColorSpace: deviceRGB
+ components: darkFocusRingBottom
+ count: 4];
+ CGContextSetStrokeColorWithColor(context, CGCOLOR(strokeColor));
+ CGContextAddLines(context, bottom, 2);
+ CGContextStrokePath(context);
+ CGContextSetShouldAntialias(context, true);
+ CGContextSetFillColorWithColor(context, CGCOLOR(fillColor));
+ CGPathRef path = CGPathCreateWithRoundedRect(CGRectInset(bounds, -3, -3),
+ 4, 4, NULL);
+ CGContextBeginPath(context);
+ CGContextAddPath(context, path);
+ CGContextAddRect(context, bounds);
+ CGContextEOFillPath(context);
+ CGContextRestoreGState(context);
+}
+/*----------------------------------------------------------------------
+ * +++ DrawDarkFrame --
+ *
+ * This is a standalone drawing procedure which draws various
+ * types of borders in Dark Mode.
+ */
+
+static void DrawDarkFrame(
+ CGRect bounds,
+ CGContextRef context,
+ HIThemeFrameKind kind)
+{
+ NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
+ NSColor *stroke;
+
+ CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace);
+ CGFloat x = bounds.origin.x, y = bounds.origin.y;
+ CGFloat w = bounds.size.width, h = bounds.size.height;
+ CGPoint topPart[4] = {
+ {x, y + h - 1}, {x, y + 1}, {x + w, y + 1}, {x + w, y + h - 1}
+ };
+ CGPoint bottom[2] = {{x, y + h}, {x + w, y + h}};
+ CGPoint accent[2] = {{x, y + 1}, {x + w, y + 1}};
+
+ switch (kind) {
+ case kHIThemeFrameTextFieldSquare:
+ CGContextSaveGState(context);
+ CGContextSetShouldAntialias(context, false);
+ CGContextBeginPath(context);
+ stroke = [NSColor colorWithColorSpace: deviceRGB
+ components: darkFrameTop
+ count: 4];
+ CGContextSetStrokeColorWithColor(context, CGCOLOR(stroke));
+ CGContextAddLines(context, topPart, 4);
+ CGContextStrokePath(context);
+ stroke = [NSColor colorWithColorSpace: deviceRGB
+ components: darkFrameBottom
+ count: 4];
+ CGContextSetStrokeColorWithColor(context, CGCOLOR(stroke));
+ CGContextAddLines(context, bottom, 2);
+ CGContextStrokePath(context);
+ stroke = [NSColor colorWithColorSpace: deviceRGB
+ components: darkFrameAccent
+ count: 4];
+ CGContextSetStrokeColorWithColor(context, CGCOLOR(stroke));
+ CGContextAddLines(context, accent, 2);
+ CGContextStrokePath(context);
+ CGContextRestoreGState(context);
+ break;
+ default:
+ break;
+ }
+}
+
+/*----------------------------------------------------------------------
+ * +++ DrawListHeader --
+ *
+ * This is a standalone drawing procedure which draws column
+ * headers for a Treeview in the Dark Mode.
+ */
+
+static void DrawDarkListHeader(
+ CGRect bounds,
+ CGContextRef context,
+ Tk_Window tkwin,
+ int state)
+{
+ NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
+ NSColor *stroke;
+
+ CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace);
+ CGFloat x = bounds.origin.x, y = bounds.origin.y;
+ CGFloat w = bounds.size.width, h = bounds.size.height;
+ CGPoint top[2] = {{x, y}, {x + w, y}};
+ CGPoint bottom[2] = {{x, y + h}, {x + w, y + h}};
+ CGPoint separator[2] = {{x + w, y + 3}, {x + w, y + h - 3}};
+
+ CGContextSaveGState(context);
+ CGContextSetShouldAntialias(context, false);
+ stroke = [NSColor colorWithColorSpace: deviceRGB
+ components: darkFrameBottom
+ count: 4];
+ CGContextSetStrokeColorWithColor(context, CGCOLOR(stroke));
+ CGContextBeginPath(context);
+ CGContextAddLines(context, top, 2);
+ CGContextStrokePath(context);
+ CGContextAddLines(context, bottom, 2);
+ CGContextStrokePath(context);
+ CGContextAddLines(context, separator, 2);
+ CGContextStrokePath(context);
+ CGContextRestoreGState(context);
+
+ if (state & TTK_TREEVIEW_STATE_SORTARROW) {
+ CGRect arrowBounds = bounds;
+
+ arrowBounds.origin.x = bounds.origin.x + bounds.size.width - 16;
+ arrowBounds.size.width = 16;
+ if (state & TTK_STATE_ALTERNATE) {
+ DrawUpArrow(context, arrowBounds, 3, 8, whiteRGBA);
+ } else if (state & TTK_STATE_SELECTED) {
+ DrawDownArrow(context, arrowBounds, 3, 8, whiteRGBA);
+ }
+ }
+}
+
+/*----------------------------------------------------------------------
+ * +++ Button element: Used for elements drawn with DrawThemeButton.
+ */
+
+/*
+ * When Ttk draws the various types of buttons, a pointer to one of these
+ * is passed as the clientData.
+ */
+
+typedef struct {
+ ThemeButtonKind kind;
+ ThemeMetric heightMetric;
+} ThemeButtonParams;
+static ThemeButtonParams
+ PushButtonParams = {kThemePushButton, kThemeMetricPushButtonHeight},
+ CheckBoxParams = {kThemeCheckBox, kThemeMetricCheckBoxHeight},
+ RadioButtonParams = {kThemeRadioButton, kThemeMetricRadioButtonHeight},
+ BevelButtonParams = {kThemeRoundedBevelButton, NoThemeMetric},
+ PopupButtonParams = {kThemePopupButton, kThemeMetricPopupButtonHeight},
+ DisclosureParams = {
+ kThemeDisclosureButton, kThemeMetricDisclosureTriangleHeight
+},
+ ListHeaderParams =
+{kThemeListHeaderButton, kThemeMetricListHeaderHeight};
+static Ttk_StateTable ButtonValueTable[] = {
+ {kThemeButtonMixed, TTK_STATE_ALTERNATE, 0},
+ {kThemeButtonOn, TTK_STATE_SELECTED, 0},
+ {kThemeButtonOff, 0, 0}
+
+ /*
+ * Others: kThemeDisclosureRight, kThemeDisclosureDown,
+ * kThemeDisclosureLeft
+ */
+
+};
+static Ttk_StateTable ButtonAdornmentTable[] = {
+ {kThemeAdornmentDefault | kThemeAdornmentFocus,
+ TTK_STATE_ALTERNATE | TTK_STATE_FOCUS, 0},
+ {kThemeAdornmentDefault, TTK_STATE_ALTERNATE, 0},
+ {kThemeAdornmentNone, TTK_STATE_ALTERNATE, 0},
+ {kThemeAdornmentFocus, TTK_STATE_FOCUS, 0},
+ {kThemeAdornmentNone, 0, 0}
+};
+
+/*----------------------------------------------------------------------
+ * +++ computeButtonDrawInfo --
+ *
+ * Fill in an appearance manager HIThemeButtonDrawInfo record.
+ */
+
+static inline HIThemeButtonDrawInfo computeButtonDrawInfo(
+ ThemeButtonParams *params,
+ Ttk_State state,
+ Tk_Window tkwin)
+{
+
+ /*
+ * See ButtonElementDraw for the explanation of why we always draw
+ * PushButtons in the active state.
+ */
+
+ SInt32 HIThemeState;
+
+ HIThemeState = Ttk_StateTableLookup(ThemeStateTable, state);
+ switch (params->kind) {
+ case kThemePushButton:
+ HIThemeState &= ~kThemeStateInactive;
+ HIThemeState |= kThemeStateActive;
+ break;
+ default:
+ break;
+ }
+
+ const HIThemeButtonDrawInfo info = {
+ .version = 0,
+ .state = HIThemeState,
+ .kind = params ? params->kind : 0,
+ .value = Ttk_StateTableLookup(ButtonValueTable, state),
+ .adornment = Ttk_StateTableLookup(ButtonAdornmentTable, state),
+ };
+ return info;
+}
+
+/*----------------------------------------------------------------------
+ * +++ Button elements.
+ */
+
+static void ButtonElementMinSize(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ int *minWidth,
+ int *minHeight,
+ Ttk_Padding *paddingPtr)
+{
+ ThemeButtonParams *params = clientData;
+
+ if (params->heightMetric != NoThemeMetric) {
+ ChkErr(GetThemeMetric, params->heightMetric, minHeight);
+
+ /*
+ * The theme height does not include the 1-pixel border around
+ * the button, although it does include the 1-pixel shadow at
+ * the bottom.
+ */
+
+ *minHeight += 2;
+
+ /*
+ * The minwidth must be 0 to force the generic ttk code to compute the
+ * correct text layout. For example, a non-zero value will cause the
+ * text to be left justified, no matter what -anchor setting is used in
+ * the style.
+ */
+
+ *minWidth = 0;
+ }
+}
+
+static void ButtonElementSize(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ int *minWidth,
+ int *minHeight,
+ Ttk_Padding *paddingPtr)
+{
+ ThemeButtonParams *params = clientData;
+ const HIThemeButtonDrawInfo info =
+ computeButtonDrawInfo(params, 0, tkwin);
+ static const CGRect scratchBounds = {{0, 0}, {100, 100}};
+ CGRect contentBounds, backgroundBounds;
+ int verticalPad;
+
+ ButtonElementMinSize(clientData, elementRecord, tkwin,
+ minWidth, minHeight, paddingPtr);
+
+ /*
+ * Given a hypothetical bounding rectangle for a button, HIToolbox will
+ * compute a bounding rectangle for the button contents and a bounding
+ * rectangle for the button background. The background bounds are large
+ * enough to contain the image of the button in any state, which might
+ * include highlight borders, shadows, etc. The content rectangle is not
+ * centered vertically within the background rectangle, presumably because
+ * shadows only appear on the bottom. Nonetheless, when HITools is asked
+ * to draw a button with a certain bounding rectangle it draws the button
+ * centered within the rectangle.
+ *
+ * To compute the effective padding around a button we request the
+ * content and bounding rectangles for a 100x100 button and use the
+ * padding between those. However, we symmetrize the padding on the
+ * top and bottom, because that is how the button will be drawn.
+ */
+
+ ChkErr(HIThemeGetButtonContentBounds,
+ &scratchBounds, &info, &contentBounds);
+ ChkErr(HIThemeGetButtonBackgroundBounds,
+ &scratchBounds, &info, &backgroundBounds);
+ paddingPtr->left = contentBounds.origin.x - backgroundBounds.origin.x;
+ paddingPtr->right =
+ CGRectGetMaxX(backgroundBounds) - CGRectGetMaxX(contentBounds);
+ verticalPad = backgroundBounds.size.height - contentBounds.size.height;
+ paddingPtr->top = paddingPtr->bottom = verticalPad / 2;
+}
+
+static void ButtonElementDraw(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ Drawable d,
+ Ttk_Box b,
+ Ttk_State state)
+{
+ ThemeButtonParams *params = clientData;
+ CGRect bounds = BoxToRect(d, b);
+ HIThemeButtonDrawInfo info = computeButtonDrawInfo(params, state, tkwin);
+
+ bounds = NormalizeButtonBounds(params->heightMetric, bounds);
+
+ BEGIN_DRAWING(d)
+ if (TkMacOSXInDarkMode(tkwin)) {
+ switch (info.kind) {
+ case kThemePushButton:
+ case kThemePopupButton:
+ DrawDarkButton(bounds, info.kind, state, dc.context);
+ break;
+ case kThemeCheckBox:
+ DrawDarkCheckBox(bounds, state, dc.context);
+ break;
+ case kThemeRadioButton:
+ DrawDarkRadioButton(bounds, state, dc.context);
+ break;
+ case kThemeRoundedBevelButton:
+ DrawDarkBevelButton(bounds, state, dc.context);
+ break;
+ default:
+ ChkErr(HIThemeDrawButton, &bounds, &info, dc.context,
+ HIOrientation, NULL);
+ }
+ } else {
+
+ /*
+ * Apple's PushButton and PopupButton do not change their fill color
+ * when the window is inactive. However, except in 10.7 (Lion), the
+ * color of the arrow button on a PopupButton does change. For some
+ * reason HITheme fills inactive buttons with a transparent color that
+ * allows the window background to show through, leading to
+ * inconsistent behavior. We work around this by filling behind an
+ * inactive PopupButton with a text background color before asking
+ * HIToolbox to draw it. For PushButtons, we simply draw them in the
+ * active state.
+ */
+
+ if (info.kind == kThemePopupButton &&
+ (state & TTK_STATE_BACKGROUND)) {
+ CGRect innerBounds = CGRectInset(bounds, 1, 1);
+ NSColor *whiteRGBA = [NSColor whiteColor];
+ SolidFillRoundedRectangle(dc.context, innerBounds, 4, whiteRGBA);
+ }
+
+ /*
+ * A BevelButton with mixed value is drawn borderless, which does make
+ * much sense for us.
+ */
+
+ if (info.kind == kThemeRoundedBevelButton &&
+ info.value == kThemeButtonMixed) {
+ info.value = kThemeButtonOff;
+ info.state = kThemeStateInactive;
+ }
+ ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation,
+ NULL);
+ }
+ END_DRAWING
+}
+
+static Ttk_ElementSpec ButtonElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(NullElement),
+ TtkNullElementOptions,
+ ButtonElementSize,
+ ButtonElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ Notebook elements.
+ */
+
+/* Tab position logic, c.f. ttkNotebook.c TabState() */
+static Ttk_StateTable TabStyleTable[] = {
+ {kThemeTabFrontInactive, TTK_STATE_SELECTED | TTK_STATE_BACKGROUND},
+ {kThemeTabNonFrontInactive, TTK_STATE_BACKGROUND},
+ {kThemeTabFrontUnavailable, TTK_STATE_DISABLED | TTK_STATE_SELECTED},
+ {kThemeTabNonFrontUnavailable, TTK_STATE_DISABLED},
+ {kThemeTabFront, TTK_STATE_SELECTED},
+ {kThemeTabNonFrontPressed, TTK_STATE_PRESSED},
+ {kThemeTabNonFront, 0}
+};
+static Ttk_StateTable TabAdornmentTable[] = {
+ {kHIThemeTabAdornmentNone, TTK_STATE_FIRST_TAB | TTK_STATE_LAST_TAB},
+ {kHIThemeTabAdornmentTrailingSeparator, TTK_STATE_FIRST_TAB},
+ {kHIThemeTabAdornmentNone, TTK_STATE_LAST_TAB},
+ {kHIThemeTabAdornmentTrailingSeparator, 0},
+};
+static Ttk_StateTable TabPositionTable[] = {
+ {kHIThemeTabPositionOnly, TTK_STATE_FIRST_TAB | TTK_STATE_LAST_TAB},
+ {kHIThemeTabPositionFirst, TTK_STATE_FIRST_TAB},
+ {kHIThemeTabPositionLast, TTK_STATE_LAST_TAB},
+ {kHIThemeTabPositionMiddle, 0},
+};
+
+/*
+ * Apple XHIG Tab View Specifications:
+ *
+ * Control sizes: Tab views are available in regular, small, and mini sizes.
+ * The tab height is fixed for each size, but you control the size of the pane
+ * area. The tab heights for each size are listed below:
+ * - Regular size: 20 pixels.
+ * - Small: 17 pixels.
+ * - Mini: 15 pixels.
+ *
+ * Label spacing and fonts: The tab labels should be in a font that’s
+ * proportional to the size of the tab view control. In addition, the label
+ * should be placed so that there are equal margins of space before and after
+ * it. The guidelines below provide the specifications you should use for tab
+ * labels:
+ * - Regular size: System font. Center in tab, leaving 12 pixels on each
+ *side.
+ * - Small: Small system font. Center in tab, leaving 10 pixels on each side.
+ * - Mini: Mini system font. Center in tab, leaving 8 pixels on each side.
+ *
+ * Control spacing: Whether you decide to inset a tab view in a window or
+ * extend its edges to the window sides and bottom, you should place the top
+ * edge of the tab view 12 or 14 pixels below the bottom edge of the title bar
+ * (or toolbar, if there is one). If you choose to inset a tab view in a
+ * window, you should leave a margin of 20 pixels between the sides and bottom
+ * of the tab view and the sides and bottom of the window (although 16 pixels
+ * is also an acceptable margin-width). If you need to provide controls below
+ * the tab view, leave enough space below the tab view so the controls are 20
+ * pixels above the bottom edge of the window and 12 pixels between the tab
+ * view and the controls.
+ *
+ * If you choose to extend the tab view sides and bottom so that they meet the
+ * window sides and bottom, you should leave a margin of at least 20 pixels
+ * between the content in the tab view and the tab-view edges.
+ *
+ * <URL: http://developer.apple.com/documentation/userexperience/Conceptual/
+ * AppleHIGuidelines/XHIGControls/XHIGControls.html#//apple_ref/doc/uid/
+ * TP30000359-TPXREF116>
+ */
+
+static void TabElementSize(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ int *minWidth,
+ int *minHeight,
+ Ttk_Padding *paddingPtr)
+{
+ GetThemeMetric(kThemeMetricLargeTabHeight, (SInt32 *) minHeight);
+ *paddingPtr = Ttk_MakePadding(0, 0, 0, 2);
+
+}
+
+static void TabElementDraw(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ Drawable d,
+ Ttk_Box b,
+ Ttk_State state)
+{
+ CGRect bounds = BoxToRect(d, b);
+ HIThemeTabDrawInfo info = {
+ .version = 1,
+ .style = Ttk_StateTableLookup(TabStyleTable, state),
+ .direction = kThemeTabNorth,
+ .size = kHIThemeTabSizeNormal,
+ .adornment = Ttk_StateTableLookup(TabAdornmentTable, state),
+ .kind = kHIThemeTabKindNormal,
+ .position = Ttk_StateTableLookup(TabPositionTable, state),
+ };
+
+ BEGIN_DRAWING(d)
+ if (TkMacOSXInDarkMode(tkwin)) {
+ DrawDarkTab(bounds, state, dc.context);
+ } else {
+ ChkErr(HIThemeDrawTab, &bounds, &info, dc.context, HIOrientation,
+ NULL);
+ }
+ END_DRAWING
+}
+
+static Ttk_ElementSpec TabElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(NullElement),
+ TtkNullElementOptions,
+ TabElementSize,
+ TabElementDraw
+};
+
+/*
+ * Notebook panes:
+ */
+
+static void PaneElementSize(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ int *minWidth,
+ int *minHeight,
+ Ttk_Padding *paddingPtr)
+{
+ *paddingPtr = Ttk_MakePadding(9, 5, 9, 9);
+}
+
+static void PaneElementDraw(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ Drawable d,
+ Ttk_Box b,
+ Ttk_State state)
+{
+ CGRect bounds = BoxToRect(d, b);
+
+ bounds.origin.y -= kThemeMetricTabFrameOverlap;
+ bounds.size.height += kThemeMetricTabFrameOverlap;
+ BEGIN_DRAWING(d)
+ if ([NSApp macMinorVersion] > 8) {
+ DrawGroupBox(bounds, dc.context, tkwin);
+ } else {
+ HIThemeTabPaneDrawInfo info = {
+ .version = 1,
+ .state = Ttk_StateTableLookup(ThemeStateTable, state),
+ .direction = kThemeTabNorth,
+ .size = kHIThemeTabSizeNormal,
+ .kind = kHIThemeTabKindNormal,
+ .adornment = kHIThemeTabPaneAdornmentNormal,
+ };
+ bounds.origin.y -= kThemeMetricTabFrameOverlap;
+ bounds.size.height += kThemeMetricTabFrameOverlap;
+ ChkErr(HIThemeDrawTabPane, &bounds, &info, dc.context, HIOrientation);
+ }
+ END_DRAWING
+}
+
+static Ttk_ElementSpec PaneElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(NullElement),
+ TtkNullElementOptions,
+ PaneElementSize,
+ PaneElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ Labelframe elements --
+ *
+ * Labelframe borders: Use "primary group box ..." Quoth
+ * DrawThemePrimaryGroup reference: "The primary group box frame is drawn
+ * inside the specified rectangle and is a maximum of 2 pixels thick."
+ *
+ * "Maximum of 2 pixels thick" is apparently a lie; looks more like 4 to me
+ * with shading.
+ */
+
+static void GroupElementSize(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ int *minWidth,
+ int *minHeight,
+ Ttk_Padding *paddingPtr)
+{
+ *paddingPtr = Ttk_UniformPadding(4);
+}
+
+static void GroupElementDraw(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ Drawable d,
+ Ttk_Box b,
+ Ttk_State state)
+{
+ CGRect bounds = BoxToRect(d, b);
+
+ BEGIN_DRAWING(d)
+ if ([NSApp macMinorVersion] > 8) {
+ DrawGroupBox(bounds, dc.context, tkwin);
+ } else {
+ const HIThemeGroupBoxDrawInfo info = {
+ .version = 0,
+ .state = Ttk_StateTableLookup(ThemeStateTable, state),
+ .kind = kHIThemeGroupBoxKindPrimaryOpaque,
+ };
+ ChkErr(HIThemeDrawGroupBox, &bounds, &info, dc.context, HIOrientation);
+ }
+ END_DRAWING
+}
+
+static Ttk_ElementSpec GroupElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(NullElement),
+ TtkNullElementOptions,
+ GroupElementSize,
+ GroupElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ Entry elements --
+ *
+ * 3 pixels padding for focus rectangle
+ * 2 pixels padding for EditTextFrame
+ */
+
+typedef struct {
+ Tcl_Obj *backgroundObj;
+ Tcl_Obj *fieldbackgroundObj;
+} EntryElement;
+
+#define ENTRY_DEFAULT_BACKGROUND "systemTextBackgroundColor"
+
+static Ttk_ElementOptionSpec EntryElementOptions[] = {
+ {"-background", TK_OPTION_BORDER,
+ Tk_Offset(EntryElement, backgroundObj), ENTRY_DEFAULT_BACKGROUND},
+ {"-fieldbackground", TK_OPTION_BORDER,
+ Tk_Offset(EntryElement, fieldbackgroundObj), ENTRY_DEFAULT_BACKGROUND},
+ {0}
+};
+
+static void EntryElementSize(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ int *minWidth,
+ int *minHeight,
+ Ttk_Padding *paddingPtr)
+{
+ *paddingPtr = Ttk_MakePadding(7, 5, 7, 6);
+}
+
+static void EntryElementDraw(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ Drawable d,
+ Ttk_Box b,
+ Ttk_State state)
+{
+ EntryElement *e = elementRecord;
+ Ttk_Box inner = Ttk_PadBox(b, Ttk_UniformPadding(3));
+ CGRect bounds = BoxToRect(d, inner);
+ NSColor *background;
+ Tk_3DBorder backgroundPtr = NULL;
+ static const char *defaultBG = ENTRY_DEFAULT_BACKGROUND;
+
+ if (TkMacOSXInDarkMode(tkwin)) {
+ BEGIN_DRAWING(d)
+ NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
+ CGFloat fill[4];
+ GetBackgroundColor(dc.context, tkwin, 1, fill);
+
+ /*
+ * Lighten the background to provide contrast.
+ */
+
+ for (int i = 0; i < 3; i++) {
+ fill[i] += 9.0 / 255.0;
+ }
+ background = [NSColor colorWithColorSpace: deviceRGB
+ components: fill
+ count: 4];
+ CGContextSetFillColorWithColor(dc.context, CGCOLOR(background));
+ CGContextFillRect(dc.context, bounds);
+ if (state & TTK_STATE_FOCUS) {
+ DrawDarkFocusRing(bounds, dc.context);
+ } else {
+ DrawDarkFrame(bounds, dc.context, kHIThemeFrameTextFieldSquare);
+ }
+ END_DRAWING
+ } else {
+ const HIThemeFrameDrawInfo info = {
+ .version = 0,
+ .kind = kHIThemeFrameTextFieldSquare,
+ .state = Ttk_StateTableLookup(ThemeStateTable, state),
+ .isFocused = state & TTK_STATE_FOCUS,
+ };
+
+ /*
+ * Earlier versions of the Aqua theme ignored the -fieldbackground
+ * option and used the -background as if it were -fieldbackground.
+ * Here we are enabling -fieldbackground. For backwards
+ * compatibility, if -fieldbackground is set to the default color and
+ * -background is set to a different color then we use -background as
+ * -fieldbackground.
+ */
+
+ if (0 != strcmp(Tcl_GetString(e->fieldbackgroundObj), defaultBG)) {
+ backgroundPtr =
+ Tk_Get3DBorderFromObj(tkwin, e->fieldbackgroundObj);
+ } else if (0 != strcmp(Tcl_GetString(e->backgroundObj), defaultBG)) {
+ backgroundPtr = Tk_Get3DBorderFromObj(tkwin, e->backgroundObj);
+ }
+ if (backgroundPtr != NULL) {
+ XFillRectangle(Tk_Display(tkwin), d,
+ Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC),
+ inner.x, inner.y, inner.width, inner.height);
+ }
+ BEGIN_DRAWING(d)
+ if (backgroundPtr == NULL) {
+ if ([NSApp macMinorVersion] > 8) {
+ background = [NSColor textBackgroundColor];
+ CGContextSetFillColorWithColor(dc.context, CGCOLOR(background));
+ } else {
+ CGContextSetRGBFillColor(dc.context, 1.0, 1.0, 1.0, 1.0);
+ }
+ CGContextFillRect(dc.context, bounds);
+ }
+ ChkErr(HIThemeDrawFrame, &bounds, &info, dc.context, HIOrientation);
+ END_DRAWING
+ }
+}
+
+static Ttk_ElementSpec EntryElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(EntryElement),
+ EntryElementOptions,
+ EntryElementSize,
+ EntryElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ Combobox elements --
+ *
+ * NOTES:
+ * The HIToolbox has incomplete and inconsistent support for ComboBoxes.
+ * There is no constant available to get the height of a ComboBox with
+ * GetThemeMetric. In fact, ComboBoxes are the same (fixed) height as
+ * PopupButtons and PushButtons, but they have no shadow at the bottom.
+ * As a result, they are drawn 1 pixel above the center of the bounds
+ * rectangle rather than being centered like the other buttons. One can
+ * request background bounds for a ComboBox, and it is reported with
+ * height 23, while the actual button face, including its 1-pixel border
+ * has height 21. Attempting to request the content bounds returns a 0x0
+ * rectangle. Measurement indicates that the arrow button has width 18.
+ *
+ * With no help available from HIToolbox, we have to use hard-wired
+ * constants for the padding. We shift the bounding rectangle downward by
+ * 1 pixel to account for the fact that the button is not centered.
+ */
+
+static Ttk_Padding ComboboxPadding = {4, 2, 20, 2};
+
+static void ComboboxElementSize(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ int *minWidth,
+ int *minHeight,
+ Ttk_Padding *paddingPtr)
+{
+ *minWidth = 24;
+ *minHeight = 23;
+ *paddingPtr = ComboboxPadding;
+}
+
+static void ComboboxElementDraw(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ Drawable d,
+ Ttk_Box b,
+ Ttk_State state)
+{
+ CGRect bounds = BoxToRect(d, b);
+ const HIThemeButtonDrawInfo info = {
+ .version = 0,
+ .state = Ttk_StateTableLookup(ThemeStateTable, state),
+ .kind = kThemeComboBox,
+ .value = Ttk_StateTableLookup(ButtonValueTable, state),
+ .adornment = Ttk_StateTableLookup(ButtonAdornmentTable, state),
+ };
+
+ BEGIN_DRAWING(d)
+ bounds.origin.y += 1;
+ if (TkMacOSXInDarkMode(tkwin)) {
+ bounds.size.height += 1;
+ DrawDarkButton(bounds, info.kind, state, dc.context);
+ } else if ([NSApp macMinorVersion] > 8) {
+ if ((state & TTK_STATE_BACKGROUND) &&
+ !(state & TTK_STATE_DISABLED)) {
+ NSColor *background = [NSColor textBackgroundColor];
+ CGRect innerBounds = CGRectInset(bounds, 1, 2);
+ SolidFillRoundedRectangle(dc.context, innerBounds, 4, background);
+ }
+ ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation,
+ NULL);
+ }
+ END_DRAWING
+}
+
+static Ttk_ElementSpec ComboboxElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(NullElement),
+ TtkNullElementOptions,
+ ComboboxElementSize,
+ ComboboxElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ Spinbutton elements --
+ *
+ * From Apple HIG, part III, section "Controls", "The Stepper Control":
+ * there should be 2 pixels of space between the stepper control (AKA
+ * IncDecButton, AKA "little arrows") and the text field it modifies.
+ *
+ * Ttk expects the up and down arrows to be distinct elements but
+ * HIToolbox draws them as one widget with two different pressed states.
+ * We work around this by defining them as separate elements in the
+ * layout, but making each one have a drawing method which also draws the
+ * other one. The down button does no drawing when not pressed, and when
+ * pressed draws the entire IncDecButton in its "pressed down" state.
+ * The up button draws the entire IncDecButton when not pressed and when
+ * pressed draws the IncDecButton in its "pressed up" state. NOTE: This
+ * means that when the down button is pressed the IncDecButton will be
+ * drawn twice, first in unpressed state by the up arrow and then in
+ * "pressed down" state by the down button. The drawing must be done in
+ * that order. So the up button must be listed first in the layout.
+ */
+
+static Ttk_Padding SpinbuttonMargins = {0, 0, 2, 0};
+
+static void SpinButtonUpElementSize(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ int *minWidth,
+ int *minHeight,
+ Ttk_Padding *paddingPtr)
+{
+ SInt32 s;
+
+ ChkErr(GetThemeMetric, kThemeMetricLittleArrowsWidth, &s);
+ *minWidth = s + Ttk_PaddingWidth(SpinbuttonMargins);
+ ChkErr(GetThemeMetric, kThemeMetricLittleArrowsHeight, &s);
+ *minHeight = (s + Ttk_PaddingHeight(SpinbuttonMargins)) / 2;
+}
+
+static void SpinButtonUpElementDraw(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ Drawable d,
+ Ttk_Box b,
+ Ttk_State state)
+{
+ CGRect bounds = BoxToRect(d, Ttk_PadBox(b, SpinbuttonMargins));
+ int infoState;
+
+ bounds.size.height *= 2;
+ if (state & TTK_STATE_PRESSED) {
+ infoState = kThemeStatePressedUp;
+ } else {
+ infoState = Ttk_StateTableLookup(ThemeStateTable, state);
+ }
+ const HIThemeButtonDrawInfo info = {
+ .version = 0,
+ .state = infoState,
+ .kind = kThemeIncDecButton,
+ .value = Ttk_StateTableLookup(ButtonValueTable, state),
+ .adornment = kThemeAdornmentNone,
+ };
+ BEGIN_DRAWING(d)
+ if (TkMacOSXInDarkMode(tkwin)) {
+ DrawDarkIncDecButton(bounds, infoState, state, dc.context);
+ } else {
+ ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation,
+ NULL);
+ }
+ END_DRAWING
+}
+
+static Ttk_ElementSpec SpinButtonUpElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(NullElement),
+ TtkNullElementOptions,
+ SpinButtonUpElementSize,
+ SpinButtonUpElementDraw
+};
+static void SpinButtonDownElementSize(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ int *minWidth,
+ int *minHeight,
+ Ttk_Padding *paddingPtr)
+{
+ SInt32 s;
+
+ ChkErr(GetThemeMetric, kThemeMetricLittleArrowsWidth, &s);
+ *minWidth = s + Ttk_PaddingWidth(SpinbuttonMargins);
+ ChkErr(GetThemeMetric, kThemeMetricLittleArrowsHeight, &s);
+ *minHeight = (s + Ttk_PaddingHeight(SpinbuttonMargins)) / 2;
+}
+
+static void SpinButtonDownElementDraw(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ Drawable d,
+ Ttk_Box b,
+ Ttk_State state)
+{
+ CGRect bounds = BoxToRect(d, Ttk_PadBox(b, SpinbuttonMargins));
+ int infoState = 0;
+
+ bounds.origin.y -= bounds.size.height;
+ bounds.size.height *= 2;
+ if (state & TTK_STATE_PRESSED) {
+ infoState = kThemeStatePressedDown;
+ } else {
+ return;
+ }
+ const HIThemeButtonDrawInfo info = {
+ .version = 0,
+ .state = infoState,
+ .kind = kThemeIncDecButton,
+ .value = Ttk_StateTableLookup(ButtonValueTable, state),
+ .adornment = kThemeAdornmentNone,
+ };
+
+ BEGIN_DRAWING(d)
+ if (TkMacOSXInDarkMode(tkwin)) {
+ DrawDarkIncDecButton(bounds, infoState, state, dc.context);
+ } else {
+ ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation,
+ NULL);
+ }
+ END_DRAWING
+}
+
+static Ttk_ElementSpec SpinButtonDownElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(NullElement),
+ TtkNullElementOptions,
+ SpinButtonDownElementSize,
+ SpinButtonDownElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ DrawThemeTrack-based elements --
+ *
+ * Progress bars and scales. (See also: <<NOTE-TRACKS>>)
+ */
+
+/*
+ * Apple does not change the appearance of a slider when the window becomes
+ * inactive. So we shouldn't either.
+ */
+
+static Ttk_StateTable ThemeTrackEnableTable[] = {
+ {kThemeTrackDisabled, TTK_STATE_DISABLED, 0},
+ {kThemeTrackActive, TTK_STATE_BACKGROUND, 0},
+ {kThemeTrackActive, 0, 0}
+ /* { kThemeTrackNothingToScroll, ?, ? }, */
+};
+
+typedef struct { /* TrackElement client data */
+ ThemeTrackKind kind;
+ SInt32 thicknessMetric;
+} TrackElementData;
+
+static TrackElementData ScaleData = {
+ kThemeSlider, kThemeMetricHSliderHeight
+};
+
+typedef struct {
+ Tcl_Obj *fromObj; /* minimum value */
+ Tcl_Obj *toObj; /* maximum value */
+ Tcl_Obj *valueObj; /* current value */
+ Tcl_Obj *orientObj; /* horizontal / vertical */
+} TrackElement;
+
+static Ttk_ElementOptionSpec TrackElementOptions[] = {
+ {"-from", TK_OPTION_DOUBLE, Tk_Offset(TrackElement, fromObj)},
+ {"-to", TK_OPTION_DOUBLE, Tk_Offset(TrackElement, toObj)},
+ {"-value", TK_OPTION_DOUBLE, Tk_Offset(TrackElement, valueObj)},
+ {"-orient", TK_OPTION_STRING, Tk_Offset(TrackElement, orientObj)},
+ {0, 0, 0}
+};
+static void TrackElementSize(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ int *minWidth,
+ int *minHeight,
+ Ttk_Padding *paddingPtr)
+{
+ TrackElementData *data = clientData;
+ SInt32 size = 24; /* reasonable default ... */
+
+ ChkErr(GetThemeMetric, data->thicknessMetric, &size);
+ *minWidth = *minHeight = size;
+}
+
+static void TrackElementDraw(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ Drawable d,
+ Ttk_Box b,
+ Ttk_State state)
+{
+ TrackElementData *data = clientData;
+ TrackElement *elem = elementRecord;
+ int orientation = TTK_ORIENT_HORIZONTAL;
+ double from = 0, to = 100, value = 0, factor;
+
+ Ttk_GetOrientFromObj(NULL, elem->orientObj, &orientation);
+ Tcl_GetDoubleFromObj(NULL, elem->fromObj, &from);
+ Tcl_GetDoubleFromObj(NULL, elem->toObj, &to);
+ Tcl_GetDoubleFromObj(NULL, elem->valueObj, &value);
+ factor = RangeToFactor(to - from);
+
+ HIThemeTrackDrawInfo info = {
+ .version = 0,
+ .kind = data->kind,
+ .bounds = BoxToRect(d, b),
+ .min = from * factor,
+ .max = to * factor,
+ .value = value * factor,
+ .attributes = kThemeTrackShowThumb |
+ (orientation == TTK_ORIENT_HORIZONTAL ?
+ kThemeTrackHorizontal : 0),
+ .enableState = Ttk_StateTableLookup(ThemeTrackEnableTable, state),
+ .trackInfo.progress.phase = 0,
+ };
+
+ if (info.kind == kThemeSlider) {
+ info.trackInfo.slider.pressState = state & TTK_STATE_PRESSED ?
+ kThemeThumbPressed : 0;
+ if (state & TTK_STATE_ALTERNATE) {
+ info.trackInfo.slider.thumbDir = kThemeThumbDownward;
+ } else {
+ info.trackInfo.slider.thumbDir = kThemeThumbPlain;
+ }
+ }
+ BEGIN_DRAWING(d)
+ if (TkMacOSXInDarkMode(tkwin)) {
+ CGRect bounds = BoxToRect(d, b);
+ NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
+ NSColor *trackColor = [NSColor colorWithColorSpace: deviceRGB
+ components: darkTrack
+ count: 4];
+ if (orientation == TTK_ORIENT_HORIZONTAL) {
+ bounds = CGRectInset(bounds, 1, bounds.size.height / 2 - 2);
+ } else {
+ bounds = CGRectInset(bounds, bounds.size.width / 2 - 3, 2);
+ }
+ SolidFillRoundedRectangle(dc.context, bounds, 2, trackColor);
+ }
+ ChkErr(HIThemeDrawTrack, &info, NULL, dc.context, HIOrientation);
+ END_DRAWING
+}
+
+static Ttk_ElementSpec TrackElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(TrackElement),
+ TrackElementOptions,
+ TrackElementSize,
+ TrackElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * Slider elements -- <<NOTE-TRACKS>>
+ *
+ * Has geometry only. The Scale widget adjusts the position of this element,
+ * and uses it for hit detection. In the Aqua theme, the slider is actually
+ * drawn as part of the trough element.
+ *
+ */
+
+static void SliderElementSize(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ int *minWidth,
+ int *minHeight,
+ Ttk_Padding *paddingPtr)
+{
+ *minWidth = *minHeight = 24;
+}
+
+static Ttk_ElementSpec SliderElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(NullElement),
+ TtkNullElementOptions,
+ SliderElementSize,
+ TtkNullElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ Progress bar elements --
+ *
+ * @@@ NOTE: According to an older revision of the Aqua reference docs,
+ * @@@ the 'phase' field is between 0 and 4. Newer revisions say
+ * @@@ that it can be any UInt8 value.
+ */
+
+typedef struct {
+ Tcl_Obj *orientObj; /* horizontal / vertical */
+ Tcl_Obj *valueObj; /* current value */
+ Tcl_Obj *maximumObj; /* maximum value */
+ Tcl_Obj *phaseObj; /* animation phase */
+ Tcl_Obj *modeObj; /* progress bar mode */
+} PbarElement;
+
+static Ttk_ElementOptionSpec PbarElementOptions[] = {
+ {"-orient", TK_OPTION_STRING,
+ Tk_Offset(PbarElement, orientObj), "horizontal"},
+ {"-value", TK_OPTION_DOUBLE,
+ Tk_Offset(PbarElement, valueObj), "0"},
+ {"-maximum", TK_OPTION_DOUBLE,
+ Tk_Offset(PbarElement, maximumObj), "100"},
+ {"-phase", TK_OPTION_INT,
+ Tk_Offset(PbarElement, phaseObj), "0"},
+ {"-mode", TK_OPTION_STRING,
+ Tk_Offset(PbarElement, modeObj), "determinate"},
+ {0, 0, 0, 0}
+};
+static void PbarElementSize(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ int *minWidth,
+ int *minHeight,
+ Ttk_Padding *paddingPtr)
+{
+ SInt32 size = 24; /* @@@ Check HIG for correct default */
+
+ ChkErr(GetThemeMetric, kThemeMetricLargeProgressBarThickness, &size);
+ *minWidth = *minHeight = size;
+}
+
+static void PbarElementDraw(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ Drawable d,
+ Ttk_Box b,
+ Ttk_State state)
+{
+ PbarElement *pbar = elementRecord;
+ int orientation = TTK_ORIENT_HORIZONTAL, phase = 0;
+ double value = 0, maximum = 100, factor;
+
+ Ttk_GetOrientFromObj(NULL, pbar->orientObj, &orientation);
+ Tcl_GetDoubleFromObj(NULL, pbar->valueObj, &value);
+ Tcl_GetDoubleFromObj(NULL, pbar->maximumObj, &maximum);
+ Tcl_GetIntFromObj(NULL, pbar->phaseObj, &phase);
+ factor = RangeToFactor(maximum);
+
+ HIThemeTrackDrawInfo info = {
+ .version = 0,
+ .kind =
+ (!strcmp("indeterminate",
+ Tcl_GetString(pbar->modeObj)) && value) ?
+ kThemeIndeterminateBar : kThemeProgressBar,
+ .bounds = BoxToRect(d, b),
+ .min = 0,
+ .max = maximum * factor,
+ .value = value * factor,
+ .attributes = kThemeTrackShowThumb |
+ (orientation == TTK_ORIENT_HORIZONTAL ?
+ kThemeTrackHorizontal : 0),
+ .enableState = Ttk_StateTableLookup(ThemeTrackEnableTable, state),
+ .trackInfo.progress.phase = phase,
+ };
+
+ BEGIN_DRAWING(d)
+ if (TkMacOSXInDarkMode(tkwin)) {
+ CGRect bounds = BoxToRect(d, b);
+ NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
+ NSColor *trackColor = [NSColor colorWithColorSpace: deviceRGB
+ components: darkTrack
+ count: 4];
+ if (orientation == TTK_ORIENT_HORIZONTAL) {
+ bounds = CGRectInset(bounds, 1, bounds.size.height / 2 - 3);
+ } else {
+ bounds = CGRectInset(bounds, bounds.size.width / 2 - 3, 1);
+ }
+ SolidFillRoundedRectangle(dc.context, bounds, 3, trackColor);
+ }
+ ChkErr(HIThemeDrawTrack, &info, NULL, dc.context, HIOrientation);
+ END_DRAWING
+}
+
+static Ttk_ElementSpec PbarElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(PbarElement),
+ PbarElementOptions,
+ PbarElementSize,
+ PbarElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ Scrollbar elements
+ */
+
+typedef struct
+{
+ Tcl_Obj *orientObj;
+} ScrollbarElement;
+
+static Ttk_ElementOptionSpec ScrollbarElementOptions[] = {
+ {"-orient", TK_OPTION_STRING,
+ Tk_Offset(ScrollbarElement, orientObj), "horizontal"},
+ {0, 0, 0, 0}
+};
+static void TroughElementSize(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ int *minWidth,
+ int *minHeight,
+ Ttk_Padding *paddingPtr)
+{
+ ScrollbarElement *scrollbar = elementRecord;
+ int orientation = TTK_ORIENT_HORIZONTAL;
+ SInt32 thickness = 15;
+
+ Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation);
+ ChkErr(GetThemeMetric, kThemeMetricScrollBarWidth, &thickness);
+ if (orientation == TTK_ORIENT_HORIZONTAL) {
+ *minHeight = thickness;
+ if ([NSApp macMinorVersion] > 7) {
+ *paddingPtr = Ttk_MakePadding(4, 4, 4, 3);
+ }
+ } else {
+ *minWidth = thickness;
+ if ([NSApp macMinorVersion] > 7) {
+ *paddingPtr = Ttk_MakePadding(4, 4, 3, 4);
+ }
+ }
+}
+
+static CGFloat lightTrough[4] = {250.0 / 255, 250.0 / 255, 250.0 / 255, 1.0};
+static CGFloat darkTrough[4] = {45.0 / 255, 46.0 / 255, 49.0 / 255, 1.0};
+static CGFloat lightInactiveThumb[4] = {
+ 200.0 / 255, 200.0 / 255, 200.0 / 255, 1.0
+};
+static CGFloat lightActiveThumb[4] = {
+ 133.0 / 255, 133.0 / 255, 133.0 / 255, 1.0
+};
+static CGFloat darkInactiveThumb[4] = {
+ 116.0 / 255, 117.0 / 255, 118.0 / 255, 1.0
+};
+static CGFloat darkActiveThumb[4] = {
+ 158.0 / 255, 158.0 / 255, 159.0 / 255, 1.0
+};
+static void TroughElementDraw(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ Drawable d,
+ Ttk_Box b,
+ Ttk_State state)
+{
+ ScrollbarElement *scrollbar = elementRecord;
+ int orientation = TTK_ORIENT_HORIZONTAL;
+ CGRect bounds = BoxToRect(d, b);
+ NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
+ NSColor *troughColor;
+ CGFloat *rgba = TkMacOSXInDarkMode(tkwin) ? darkTrough : lightTrough;
+
+ Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation);
+ if (orientation == TTK_ORIENT_HORIZONTAL) {
+ bounds = CGRectInset(bounds, 0, 1);
+ } else {
+ bounds = CGRectInset(bounds, 1, 0);
+ }
+ troughColor = [NSColor colorWithColorSpace: deviceRGB
+ components: rgba
+ count: 4];
+ BEGIN_DRAWING(d)
+ if ([NSApp macMinorVersion] > 8) {
+ CGContextSetFillColorWithColor(dc.context, CGCOLOR(troughColor));
+ } else {
+ ChkErr(HIThemeSetFill, kThemeBrushDocumentWindowBackground, NULL,
+ dc.context, HIOrientation);
+ }
+ CGContextFillRect(dc.context, bounds);
+ END_DRAWING
+}
+
+static Ttk_ElementSpec TroughElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(ScrollbarElement),
+ ScrollbarElementOptions,
+ TroughElementSize,
+ TroughElementDraw
+};
+static void ThumbElementSize(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ int *minWidth,
+ int *minHeight,
+ Ttk_Padding *paddingPtr)
+{
+ ScrollbarElement *scrollbar = elementRecord;
+ int orientation = TTK_ORIENT_HORIZONTAL;
+
+ Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation);
+ if (orientation == TTK_ORIENT_VERTICAL) {
+ *minHeight = 18;
+ *minWidth = 8;
+ } else {
+ *minHeight = 8;
+ *minWidth = 18;
+ }
+}
+
+static void ThumbElementDraw(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ Drawable d,
+ Ttk_Box b,
+ Ttk_State state)
+{
+ ScrollbarElement *scrollbar = elementRecord;
+ int orientation = TTK_ORIENT_HORIZONTAL;
+
+ Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation);
+
+ /*
+ * In order to make ttk scrollbars work correctly it is necessary to be
+ * able to display the thumb element at the size and location which the ttk
+ * scrollbar widget requests. The algorithm that HIToolbox uses to
+ * determine the thumb geometry from the input values of min, max, value
+ * and viewSize is undocumented. A seemingly natural algorithm is
+ * implemented below. This code uses that algorithm for older OS versions,
+ * because using HITools also handles drawing the buttons and 3D thumb used
+ * on those systems. For newer systems the cleanest approach is to just
+ * draw the thumb directly.
+ */
+
+ if ([NSApp macMinorVersion] > 8) {
+ CGRect thumbBounds = BoxToRect(d, b);
+ NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
+ NSColor *thumbColor;
+ CGFloat *rgba;
+ if ((orientation == TTK_ORIENT_HORIZONTAL &&
+ thumbBounds.size.width >= Tk_Width(tkwin) - 8) ||
+ (orientation == TTK_ORIENT_VERTICAL &&
+ thumbBounds.size.height >= Tk_Height(tkwin) - 8)) {
+ return;
+ }
+ int isDark = TkMacOSXInDarkMode(tkwin);
+ if ((state & TTK_STATE_PRESSED) ||
+ (state & TTK_STATE_HOVER)) {
+ rgba = isDark ? darkActiveThumb : lightActiveThumb;
+ } else {
+ rgba = isDark ? darkInactiveThumb : lightInactiveThumb;
+ }
+ thumbColor = [NSColor colorWithColorSpace: deviceRGB
+ components: rgba
+ count: 4];
+ BEGIN_DRAWING(d)
+ SolidFillRoundedRectangle(dc.context, thumbBounds, 4, thumbColor);
+ END_DRAWING
+ } else {
+ double thumbSize, trackSize, visibleSize, factor, fraction;
+ MacDrawable *macWin = (MacDrawable *) Tk_WindowId(tkwin);
+ CGRect troughBounds = {{macWin->xOff, macWin->yOff},
+ {Tk_Width(tkwin), Tk_Height(tkwin)}};
+
+ /*
+ * The info struct has integer fields, which will be converted to
+ * floats in the drawing routine. All of values provided in the info
+ * struct, namely min, max, value, and viewSize are only defined up to
+ * an arbitrary scale factor. To avoid roundoff error we scale so
+ * that the viewSize is a large float which is smaller than the
+ * largest int.
+ */
+
+ HIThemeTrackDrawInfo info = {
+ .version = 0,
+ .bounds = troughBounds,
+ .min = 0,
+ .attributes = kThemeTrackShowThumb |
+ kThemeTrackThumbRgnIsNotGhost,
+ .enableState = kThemeTrackActive
+ };
+ factor = RangeToFactor(100.0);
+ if (orientation == TTK_ORIENT_HORIZONTAL) {
+ trackSize = troughBounds.size.width;
+ thumbSize = b.width;
+ fraction = b.x / trackSize;
+ } else {
+ trackSize = troughBounds.size.height;
+ thumbSize = b.height;
+ fraction = b.y / trackSize;
+ }
+ visibleSize = (thumbSize / trackSize) * factor;
+ info.max = factor - visibleSize;
+ info.trackInfo.scrollbar.viewsize = visibleSize;
+ if ([NSApp macMinorVersion] < 8 ||
+ orientation == TTK_ORIENT_HORIZONTAL) {
+ info.value = factor * fraction;
+ } else {
+ info.value = info.max - factor * fraction;
+ }
+ if ((state & TTK_STATE_PRESSED) ||
+ (state & TTK_STATE_HOVER)) {
+ info.trackInfo.scrollbar.pressState = kThemeThumbPressed;
+ } else {
+ info.trackInfo.scrollbar.pressState = 0;
+ }
+ if (orientation == TTK_ORIENT_HORIZONTAL) {
+ info.attributes |= kThemeTrackHorizontal;
+ } else {
+ info.attributes &= ~kThemeTrackHorizontal;
+ }
+ BEGIN_DRAWING(d)
+ HIThemeDrawTrack(&info, 0, dc.context, kHIThemeOrientationNormal);
+ END_DRAWING
+ }
+}
+
+static Ttk_ElementSpec ThumbElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(ScrollbarElement),
+ ScrollbarElementOptions,
+ ThumbElementSize,
+ ThumbElementDraw
+};
+static void ArrowElementSize(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ int *minWidth,
+ int *minHeight,
+ Ttk_Padding *paddingPtr)
+{
+ if ([NSApp macMinorVersion] < 8) {
+ *minHeight = *minWidth = 14;
+ } else {
+ *minHeight = *minWidth = -1;
+ }
+}
+
+static Ttk_ElementSpec ArrowElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(ScrollbarElement),
+ ScrollbarElementOptions,
+ ArrowElementSize,
+ TtkNullElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ Separator element.
+ *
+ * DrawThemeSeparator() guesses the orientation of the line from the width
+ * and height of the rectangle, so the same element can can be used for
+ * horizontal, vertical, and general separators.
+ */
+
+static void SeparatorElementSize(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ int *minWidth,
+ int *minHeight,
+ Ttk_Padding *paddingPtr)
+{
+ *minWidth = *minHeight = 1;
+}
+
+static void SeparatorElementDraw(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ Drawable d,
+ Ttk_Box b,
+ unsigned int state)
+{
+ CGRect bounds = BoxToRect(d, b);
+ const HIThemeSeparatorDrawInfo info = {
+ .version = 0,
+ /* Separator only supports kThemeStateActive, kThemeStateInactive */
+ .state = Ttk_StateTableLookup(ThemeStateTable,
+ state & TTK_STATE_BACKGROUND),
+ };
+
+ BEGIN_DRAWING(d)
+ if (TkMacOSXInDarkMode(tkwin)) {
+ DrawDarkSeparator(bounds, dc.context, tkwin);
+ } else {
+ ChkErr(HIThemeDrawSeparator, &bounds, &info, dc.context,
+ HIOrientation);
+ }
+ END_DRAWING
+}
+
+static Ttk_ElementSpec SeparatorElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(NullElement),
+ TtkNullElementOptions,
+ SeparatorElementSize,
+ SeparatorElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ Size grip elements -- (obsolete)
+ */
+
+static const ThemeGrowDirection sizegripGrowDirection
+ = kThemeGrowRight | kThemeGrowDown;
+
+static void SizegripElementSize(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ int *minWidth,
+ int *minHeight,
+ Ttk_Padding *paddingPtr)
+{
+ HIThemeGrowBoxDrawInfo info = {
+ .version = 0,
+ .state = kThemeStateActive,
+ .kind = kHIThemeGrowBoxKindNormal,
+ .direction = sizegripGrowDirection,
+ .size = kHIThemeGrowBoxSizeNormal,
+ };
+ CGRect bounds = CGRectZero;
+
+ ChkErr(HIThemeGetGrowBoxBounds, &bounds.origin, &info, &bounds);
+ *minWidth = bounds.size.width;
+ *minHeight = bounds.size.height;
+}
+
+static void SizegripElementDraw(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ Drawable d,
+ Ttk_Box b,
+ unsigned int state)
+{
+ CGRect bounds = BoxToRect(d, b);
+ HIThemeGrowBoxDrawInfo info = {
+ .version = 0,
+ /* Grow box only supports kThemeStateActive, kThemeStateInactive */
+ .state = Ttk_StateTableLookup(ThemeStateTable,
+ state & TTK_STATE_BACKGROUND),
+ .kind = kHIThemeGrowBoxKindNormal,
+ .direction = sizegripGrowDirection,
+ .size = kHIThemeGrowBoxSizeNormal,
+ };
+
+ BEGIN_DRAWING(d)
+ ChkErr(HIThemeDrawGrowBox, &bounds.origin, &info, dc.context,
+ HIOrientation);
+ END_DRAWING
+}
+
+static Ttk_ElementSpec SizegripElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(NullElement),
+ TtkNullElementOptions,
+ SizegripElementSize,
+ SizegripElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ Background and fill elements --
+ *
+ * Before drawing any ttk widget, its bounding rectangle is filled with a
+ * background color. This color must match the background color of the
+ * containing widget to avoid looking ugly. The need for care when doing
+ * this is exacerbated by the fact that ttk enforces its "native look" by
+ * not allowing user control of the background or highlight colors of ttk
+ * widgets.
+ *
+ * This job is made more complicated in recent versions of macOS by the
+ * fact that the Appkit GroupBox (used for ttk LabelFrames) and
+ * TabbedPane (used for the Notebook widget) both place their content
+ * inside a rectangle with rounded corners that has a color which
+ * contrasts with the dialog background color. Moreover, although the
+ * Apple human interface guidelines recommend against doing so, there are
+ * times when one wants to nest these widgets, for example placing a
+ * GroupBox inside of a TabbedPane. To have the right contrast, each
+ * level of nesting requires a different color.
+ *
+ * Previous Tk releases used the HIThemeDrawGroupBox routine to draw
+ * GroupBoxes and TabbedPanes. This meant that the best that could be
+ * done was to set the GroupBox to be of kind
+ * kHIThemeGroupBoxKindPrimaryOpaque, and set its fill color to be the
+ * system background color. If widgets inside the box were drawn with
+ * the system background color the backgrounds would match. But this
+ * produces a GroupBox with no contrast, the only visual clue being a
+ * faint highlighting around the top of the GroupBox. Moreover, the
+ * TabbedPane does not have an Opaque version, so while it is drawn
+ * inside a contrasting rounded rectangle, the widgets inside the pane
+ * needed to be enclosed in a frame with the system background
+ * color. This added a visual artifact since the frame's background color
+ * does not match the Pane's background color. That code has now been
+ * replaced with the standalone drawing procedure macOSXDrawGroupBox,
+ * which draws a rounded rectangle with an appropriate contrasting
+ * background color.
+ *
+ * Patterned backgrounds, which are now obsolete, should be aligned with
+ * the coordinate system of the top-level window. Apparently failing to
+ * do this used to cause graphics anomalies when drawing into an
+ * off-screen graphics port. The code for handling this is currently
+ * commented out.
+ */
+
+static void FillElementDraw(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ Drawable d,
+ Ttk_Box b,
+ Ttk_State state)
+{
+ CGRect bounds = BoxToRect(d, b);
+
+ if ([NSApp macMinorVersion] > 8) {
+ NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
+ NSColor *bgColor;
+ CGFloat fill[4];
+ BEGIN_DRAWING(d)
+ GetBackgroundColor(dc.context, tkwin, 0, fill);
+ bgColor = [NSColor colorWithColorSpace: deviceRGB components: fill
+ count: 4];
+ CGContextSetFillColorSpace(dc.context, deviceRGB.CGColorSpace);
+ CGContextSetFillColorWithColor(dc.context, CGCOLOR(bgColor));
+ CGContextFillRect(dc.context, bounds);
+ END_DRAWING
+ } else {
+ ThemeBrush brush = (state & TTK_STATE_BACKGROUND)
+ ? kThemeBrushModelessDialogBackgroundInactive
+ : kThemeBrushModelessDialogBackgroundActive;
+ BEGIN_DRAWING(d)
+ ChkErr(HIThemeSetFill, brush, NULL, dc.context, HIOrientation);
+ //QDSetPatternOrigin(PatternOrigin(tkwin, d));
+ CGContextFillRect(dc.context, bounds);
+ END_DRAWING
+ }
+}
+
+static void BackgroundElementDraw(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ Drawable d,
+ Ttk_Box b,
+ unsigned int state)
+{
+ FillElementDraw(clientData, elementRecord, tkwin, d, Ttk_WinBox(tkwin),
+ state);
+}
+
+static Ttk_ElementSpec FillElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(NullElement),
+ TtkNullElementOptions,
+ TtkNullElementSize,
+ FillElementDraw
+};
+static Ttk_ElementSpec BackgroundElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(NullElement),
+ TtkNullElementOptions,
+ TtkNullElementSize,
+ BackgroundElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ ToolbarBackground element -- toolbar style for frames.
+ *
+ * This is very similar to the normal background element, but uses a
+ * different ThemeBrush in order to get the lighter pinstripe effect
+ * used in toolbars. We use SetThemeBackground() rather than
+ * ApplyThemeBackground() in order to get the right style.
+ *
+ * <URL: http://developer.apple.com/documentation/Carbon/Reference/
+ * Appearance_Manager/appearance_manager/constant_7.html#/
+ * /apple_ref/doc/uid/TP30000243/C005321>
+ *
+ */
+
+static void ToolbarBackgroundElementDraw(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ Drawable d,
+ Ttk_Box b,
+ Ttk_State state)
+{
+ ThemeBrush brush = kThemeBrushToolbarBackground;
+ CGRect bounds = BoxToRect(d, Ttk_WinBox(tkwin));
+
+ BEGIN_DRAWING(d)
+ ChkErr(HIThemeSetFill, brush, NULL, dc.context, HIOrientation);
+ //QDSetPatternOrigin(PatternOrigin(tkwin, d));
+ CGContextFillRect(dc.context, bounds);
+ END_DRAWING
+}
+
+static Ttk_ElementSpec ToolbarBackgroundElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(NullElement),
+ TtkNullElementOptions,
+ TtkNullElementSize,
+ ToolbarBackgroundElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ Field elements --
+ *
+ * Used for the Treeview widget. This is like the BackgroundElement
+ * except that the fieldbackground color is configureable.
+ */
+
+typedef struct {
+ Tcl_Obj *backgroundObj;
+} FieldElement;
+
+static Ttk_ElementOptionSpec FieldElementOptions[] = {
+ {"-fieldbackground", TK_OPTION_BORDER,
+ Tk_Offset(FieldElement, backgroundObj), "white"},
+ {NULL, 0, 0, NULL}
+};
+
+static void FieldElementDraw(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ Drawable d,
+ Ttk_Box b,
+ Ttk_State state)
+{
+ FieldElement *e = elementRecord;
+ Tk_3DBorder backgroundPtr =
+ Tk_Get3DBorderFromObj(tkwin, e->backgroundObj);
+
+ XFillRectangle(Tk_Display(tkwin), d,
+ Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC),
+ b.x, b.y, b.width, b.height);
+}
+
+static Ttk_ElementSpec FieldElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(FieldElement),
+ FieldElementOptions,
+ TtkNullElementSize,
+ FieldElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ Treeview headers --
+ *
+ * On systems older than 10.9 The header is a kThemeListHeaderButton drawn
+ * by HIToolbox. On newer systems those buttons do not match the Apple
+ * buttons, so we draw them from scratch.
+ */
+
+static Ttk_StateTable TreeHeaderValueTable[] = {
+ {kThemeButtonOn, TTK_STATE_ALTERNATE},
+ {kThemeButtonOn, TTK_STATE_SELECTED},
+ {kThemeButtonOff, 0}
+};
+
+static Ttk_StateTable TreeHeaderAdornmentTable[] = {
+ {kThemeAdornmentHeaderButtonSortUp,
+ TTK_STATE_ALTERNATE | TTK_TREEVIEW_STATE_SORTARROW},
+ {kThemeAdornmentDefault,
+ TTK_STATE_SELECTED | TTK_TREEVIEW_STATE_SORTARROW},
+ {kThemeAdornmentHeaderButtonNoSortArrow, TTK_STATE_ALTERNATE},
+ {kThemeAdornmentHeaderButtonNoSortArrow, TTK_STATE_SELECTED},
+ {kThemeAdornmentFocus, TTK_STATE_FOCUS},
+ {kThemeAdornmentNone, 0}
+};
+
+static void TreeAreaElementSize (
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ int *minWidth,
+ int *minHeight,
+ Ttk_Padding *paddingPtr)
+{
+
+ /*
+ * Padding is needed to get the heading text to align correctly, since the
+ * widget expects the heading to be the same height as a row.
+ */
+
+ if ([NSApp macMinorVersion] > 8) {
+ paddingPtr->top = 4;
+ }
+}
+
+static Ttk_ElementSpec TreeAreaElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(NullElement),
+ TtkNullElementOptions,
+ TreeAreaElementSize,
+ TtkNullElementDraw
+};
+static void TreeHeaderElementSize(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ int *minWidth,
+ int *minHeight,
+ Ttk_Padding *paddingPtr)
+{
+ if ([NSApp macMinorVersion] > 8) {
+ *minHeight = 24;
+ } else {
+ ButtonElementSize(clientData, elementRecord, tkwin, minWidth,
+ minHeight, paddingPtr);
+ }
+}
+
+static void TreeHeaderElementDraw(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ Drawable d,
+ Ttk_Box b,
+ Ttk_State state)
+{
+ ThemeButtonParams *params = clientData;
+ CGRect bounds = BoxToRect(d, b);
+ const HIThemeButtonDrawInfo info = {
+ .version = 0,
+ .state = Ttk_StateTableLookup(ThemeStateTable, state),
+ .kind = params->kind,
+ .value = Ttk_StateTableLookup(TreeHeaderValueTable, state),
+ .adornment = Ttk_StateTableLookup(TreeHeaderAdornmentTable, state),
+ };
+
+ BEGIN_DRAWING(d)
+ if ([NSApp macMinorVersion] > 8) {
+
+ /*
+ * Compensate for the padding added in TreeHeaderElementSize, so
+ * the larger heading will be drawn at the top of the widget.
+ */
+
+ bounds.origin.y -= 4;
+ if (TkMacOSXInDarkMode(tkwin)) {
+ DrawDarkListHeader(bounds, dc.context, tkwin, state);
+ } else {
+ DrawListHeader(bounds, dc.context, tkwin, state);
+ }
+ } else {
+ ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation,
+ NULL);
+ }
+ END_DRAWING
+}
+
+static Ttk_ElementSpec TreeHeaderElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(NullElement),
+ TtkNullElementOptions,
+ TreeHeaderElementSize,
+ TreeHeaderElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ Disclosure triangles --
+ */
+
+#define TTK_TREEVIEW_STATE_OPEN TTK_STATE_USER1
+#define TTK_TREEVIEW_STATE_LEAF TTK_STATE_USER2
+static Ttk_StateTable DisclosureValueTable[] = {
+ {kThemeDisclosureDown, TTK_TREEVIEW_STATE_OPEN, 0},
+ {kThemeDisclosureRight, 0, 0},
+};
+static void DisclosureElementSize(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ int *minWidth,
+ int *minHeight,
+ Ttk_Padding *paddingPtr)
+{
+ SInt32 s;
+
+ ChkErr(GetThemeMetric, kThemeMetricDisclosureTriangleWidth, &s);
+ *minWidth = s;
+ ChkErr(GetThemeMetric, kThemeMetricDisclosureTriangleHeight, &s);
+ *minHeight = s;
+}
+
+static void DisclosureElementDraw(
+ void *clientData,
+ void *elementRecord,
+ Tk_Window tkwin,
+ Drawable d,
+ Ttk_Box b,
+ Ttk_State state)
+{
+ if (!(state & TTK_TREEVIEW_STATE_LEAF)) {
+ int triangleState = TkMacOSXInDarkMode(tkwin) ?
+ kThemeStateInactive : kThemeStateActive;
+ CGRect bounds = BoxToRect(d, b);
+ const HIThemeButtonDrawInfo info = {
+ .version = 0,
+ .state = triangleState,
+ .kind = kThemeDisclosureTriangle,
+ .value = Ttk_StateTableLookup(DisclosureValueTable, state),
+ .adornment = kThemeAdornmentDrawIndicatorOnly,
+ };
+
+ BEGIN_DRAWING(d)
+ ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation,
+ NULL);
+ END_DRAWING
+ }
+}
+
+static Ttk_ElementSpec DisclosureElementSpec = {
+ TK_STYLE_VERSION_2,
+ sizeof(NullElement),
+ TtkNullElementOptions,
+ DisclosureElementSize,
+ DisclosureElementDraw
+};
+
+/*----------------------------------------------------------------------
+ * +++ Widget layouts --
+ */
+
+TTK_BEGIN_LAYOUT_TABLE(LayoutTable)
+
+TTK_LAYOUT("Toolbar",
+ TTK_NODE("Toolbar.background", TTK_FILL_BOTH))
+
+TTK_LAYOUT("TButton",
+ TTK_GROUP("Button.button", TTK_FILL_BOTH,
+ TTK_GROUP("Button.padding", TTK_FILL_BOTH,
+ TTK_NODE("Button.label", TTK_FILL_BOTH))))
+
+TTK_LAYOUT("TRadiobutton",
+ TTK_GROUP("Radiobutton.button", TTK_FILL_BOTH,
+ TTK_GROUP("Radiobutton.padding", TTK_FILL_BOTH,
+ TTK_NODE("Radiobutton.label", TTK_PACK_LEFT))))
+
+TTK_LAYOUT("TCheckbutton",
+ TTK_GROUP("Checkbutton.button", TTK_FILL_BOTH,
+ TTK_GROUP("Checkbutton.padding", TTK_FILL_BOTH,
+ TTK_NODE("Checkbutton.label", TTK_PACK_LEFT))))
+
+TTK_LAYOUT("TMenubutton",
+ TTK_GROUP("Menubutton.button", TTK_FILL_BOTH,
+ TTK_GROUP("Menubutton.padding", TTK_FILL_BOTH,
+ TTK_NODE("Menubutton.label", TTK_PACK_LEFT))))
+
+TTK_LAYOUT("TCombobox",
+ TTK_GROUP("Combobox.button", TTK_FILL_BOTH,
+ TTK_GROUP("Combobox.padding", TTK_FILL_BOTH,
+ TTK_NODE("Combobox.textarea", TTK_FILL_BOTH))))
+
+/* Notebook tabs -- no focus ring */
+TTK_LAYOUT("Tab",
+ TTK_GROUP("Notebook.tab", TTK_FILL_BOTH,
+ TTK_GROUP("Notebook.padding", TTK_EXPAND | TTK_FILL_BOTH,
+ TTK_NODE("Notebook.label", TTK_EXPAND | TTK_FILL_BOTH))))
+
+/* Spinbox -- buttons 2px to the right of the field. */
+TTK_LAYOUT("TSpinbox",
+ TTK_GROUP("Spinbox.buttons", TTK_PACK_RIGHT,
+ TTK_NODE("Spinbox.uparrow", TTK_PACK_TOP | TTK_STICK_E)
+ TTK_NODE("Spinbox.downarrow", TTK_PACK_BOTTOM | TTK_STICK_E))
+ TTK_GROUP("Spinbox.field", TTK_EXPAND | TTK_FILL_X,
+ TTK_NODE("Spinbox.textarea", TTK_EXPAND | TTK_FILL_X)))
+
+/* Progress bars -- track only */
+TTK_LAYOUT("TProgressbar",
+ TTK_NODE("Progressbar.track", TTK_EXPAND | TTK_FILL_BOTH))
+
+/* Treeview -- no border. */
+TTK_LAYOUT("Treeview",
+ TTK_GROUP("Treeview.field", TTK_FILL_BOTH,
+ TTK_GROUP("Treeview.padding", TTK_FILL_BOTH,
+ TTK_NODE("Treeview.treearea", TTK_FILL_BOTH))))
+
+/* Tree heading -- no border, fixed height */
+TTK_LAYOUT("Heading",
+ TTK_NODE("Treeheading.cell", TTK_FILL_BOTH)
+ TTK_NODE("Treeheading.image", TTK_PACK_RIGHT)
+ TTK_NODE("Treeheading.text", TTK_PACK_TOP))
+
+/* Tree items -- omit focus ring */
+TTK_LAYOUT("Item",
+ TTK_GROUP("Treeitem.padding", TTK_FILL_BOTH,
+ TTK_NODE("Treeitem.indicator", TTK_PACK_LEFT)
+ TTK_NODE("Treeitem.image", TTK_PACK_LEFT)
+ TTK_NODE("Treeitem.text", TTK_PACK_LEFT)))
+
+/* Scrollbar Layout -- Buttons at the bottom (Snow Leopard and Lion only) */
+
+TTK_LAYOUT("Vertical.TScrollbar",
+ TTK_GROUP("Vertical.Scrollbar.trough", TTK_FILL_Y,
+ TTK_NODE("Vertical.Scrollbar.thumb",
+ TTK_PACK_TOP | TTK_EXPAND | TTK_FILL_BOTH)
+ TTK_NODE("Vertical.Scrollbar.downarrow", TTK_PACK_BOTTOM)
+ TTK_NODE("Vertical.Scrollbar.uparrow", TTK_PACK_BOTTOM)))
+
+TTK_LAYOUT("Horizontal.TScrollbar",
+ TTK_GROUP("Horizontal.Scrollbar.trough", TTK_FILL_X,
+ TTK_NODE("Horizontal.Scrollbar.thumb",
+ TTK_PACK_LEFT | TTK_EXPAND | TTK_FILL_BOTH)
+ TTK_NODE("Horizontal.Scrollbar.rightarrow", TTK_PACK_RIGHT)
+ TTK_NODE("Horizontal.Scrollbar.leftarrow", TTK_PACK_RIGHT)))
+
+TTK_END_LAYOUT_TABLE
+
+/*----------------------------------------------------------------------
+ * +++ Initialization --
+ */
+
+static int AquaTheme_Init(
+ Tcl_Interp *interp)
+{
+ Ttk_Theme themePtr = Ttk_CreateTheme(interp, "aqua", NULL);
+
+ if (!themePtr) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Elements:
+ */
+
+ Ttk_RegisterElementSpec(themePtr, "background", &BackgroundElementSpec,
+ 0);
+ Ttk_RegisterElementSpec(themePtr, "fill", &FillElementSpec, 0);
+ Ttk_RegisterElementSpec(themePtr, "field", &FieldElementSpec, 0);
+ Ttk_RegisterElementSpec(themePtr, "Toolbar.background",
+ &ToolbarBackgroundElementSpec, 0);
+
+ Ttk_RegisterElementSpec(themePtr, "Button.button",
+ &ButtonElementSpec, &PushButtonParams);
+ Ttk_RegisterElementSpec(themePtr, "Checkbutton.button",
+ &ButtonElementSpec, &CheckBoxParams);
+ Ttk_RegisterElementSpec(themePtr, "Radiobutton.button",
+ &ButtonElementSpec, &RadioButtonParams);
+ Ttk_RegisterElementSpec(themePtr, "Toolbutton.border",
+ &ButtonElementSpec, &BevelButtonParams);
+ Ttk_RegisterElementSpec(themePtr, "Menubutton.button",
+ &ButtonElementSpec, &PopupButtonParams);
+ Ttk_RegisterElementSpec(themePtr, "Spinbox.uparrow",
+ &SpinButtonUpElementSpec, 0);
+ Ttk_RegisterElementSpec(themePtr, "Spinbox.downarrow",
+ &SpinButtonDownElementSpec, 0);
+ Ttk_RegisterElementSpec(themePtr, "Combobox.button",
+ &ComboboxElementSpec, 0);
+ Ttk_RegisterElementSpec(themePtr, "Treeitem.indicator",
+ &DisclosureElementSpec, &DisclosureParams);
+ Ttk_RegisterElementSpec(themePtr, "Treeheading.cell",
+ &TreeHeaderElementSpec, &ListHeaderParams);
+
+ Ttk_RegisterElementSpec(themePtr, "Treeview.treearea",
+ &TreeAreaElementSpec, 0);
+ Ttk_RegisterElementSpec(themePtr, "Notebook.tab", &TabElementSpec, 0);
+ Ttk_RegisterElementSpec(themePtr, "Notebook.client", &PaneElementSpec, 0);
+
+ Ttk_RegisterElementSpec(themePtr, "Labelframe.border", &GroupElementSpec,
+ 0);
+ Ttk_RegisterElementSpec(themePtr, "Entry.field", &EntryElementSpec, 0);
+ Ttk_RegisterElementSpec(themePtr, "Spinbox.field", &EntryElementSpec, 0);
+
+ Ttk_RegisterElementSpec(themePtr, "separator", &SeparatorElementSpec, 0);
+ Ttk_RegisterElementSpec(themePtr, "hseparator", &SeparatorElementSpec, 0);
+ Ttk_RegisterElementSpec(themePtr, "vseparator", &SeparatorElementSpec, 0);
+
+ Ttk_RegisterElementSpec(themePtr, "sizegrip", &SizegripElementSpec, 0);
+
+ /*
+ * <<NOTE-TRACKS>>
+ * In some themes the Layouts for a progress bar has a trough element and a
+ * pbar element. But in our case the appearance manager draws both parts
+ * of the progress bar, so we just have a single element called ".track".
+ */
+
+ Ttk_RegisterElementSpec(themePtr, "Progressbar.track", &PbarElementSpec,
+ 0);
+
+ Ttk_RegisterElementSpec(themePtr, "Scale.trough", &TrackElementSpec,
+ &ScaleData);
+ Ttk_RegisterElementSpec(themePtr, "Scale.slider", &SliderElementSpec, 0);
+
+ Ttk_RegisterElementSpec(themePtr, "Vertical.Scrollbar.trough",
+ &TroughElementSpec, 0);
+ Ttk_RegisterElementSpec(themePtr, "Vertical.Scrollbar.thumb",
+ &ThumbElementSpec, 0);
+ Ttk_RegisterElementSpec(themePtr, "Horizontal.Scrollbar.trough",
+ &TroughElementSpec, 0);
+ Ttk_RegisterElementSpec(themePtr, "Horizontal.Scrollbar.thumb",
+ &ThumbElementSpec, 0);
+
+ /*
+ * If we are not in Snow Leopard or Lion the arrows won't actually be
+ * displayed.
+ */
+
+ Ttk_RegisterElementSpec(themePtr, "Vertical.Scrollbar.uparrow",
+ &ArrowElementSpec, 0);
+ Ttk_RegisterElementSpec(themePtr, "Vertical.Scrollbar.downarrow",
+ &ArrowElementSpec, 0);
+ Ttk_RegisterElementSpec(themePtr, "Horizontal.Scrollbar.leftarrow",
+ &ArrowElementSpec, 0);
+ Ttk_RegisterElementSpec(themePtr, "Horizontal.Scrollbar.rightarrow",
+ &ArrowElementSpec, 0);
+
+ /*
+ * Layouts:
+ */
+
+ Ttk_RegisterLayouts(themePtr, LayoutTable);
+
+ Tcl_PkgProvide(interp, "ttk::theme::aqua", TTK_VERSION);
+ return TCL_OK;
+}
+
+MODULE_SCOPE
+int Ttk_MacOSXPlatformInit(
+ Tcl_Interp *interp)
+{
+ return AquaTheme_Init(interp);
+}
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/tk8.6/tests/README b/tk8.6/tests/README
new file mode 100644
index 0000000..677e76c
--- /dev/null
+++ b/tk8.6/tests/README
@@ -0,0 +1,5 @@
+README -- Tk test suite design document.
+
+This directory contains a set of validation tests for the Tk commands.
+Please see the tests/README file in the Tcl source distribution for
+information about the test suite.
diff --git a/tk8.6/tests/all.tcl b/tk8.6/tests/all.tcl
new file mode 100644
index 0000000..d15e5ca
--- /dev/null
+++ b/tk8.6/tests/all.tcl
@@ -0,0 +1,19 @@
+# all.tcl --
+#
+# This file contains a top-level script to run all of the Tk
+# tests. Execute it by invoking "source all.tcl" when running tktest
+# in this directory.
+#
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+package require Tk ;# This is the Tk test suite; fail early if no Tk!
+package require tcltest 2.2
+tcltest::configure {*}$argv
+tcltest::configure -testdir [file normalize [file dirname [info script]]]
+tcltest::configure -loadfile \
+ [file join [tcltest::testsDirectory] constraints.tcl]
+tcltest::configure -singleproc 1
+tcltest::runAllTests
diff --git a/tk8.6/tests/arc.tcl b/tk8.6/tests/arc.tcl
new file mode 100644
index 0000000..0126c7d
--- /dev/null
+++ b/tk8.6/tests/arc.tcl
@@ -0,0 +1,151 @@
+# This file creates a visual test for arcs. It is part of the Tk
+# visual test suite, which is invoked via the "visual" script.
+
+catch {destroy .t}
+toplevel .t
+wm title .t "Visual Tests for Canvas Arcs"
+wm iconname .t "Arcs"
+wm geom .t +0+0
+wm minsize .t 1 1
+
+canvas .t.c -width 650 -height 600 -relief raised
+pack .t.c -expand yes -fill both
+button .t.quit -text Quit -command {destroy .t}
+pack .t.quit -side bottom -pady 3 -ipadx 4 -ipady 2
+
+puts "depth is [winfo depth .t]"
+if {[winfo depth .t] > 1} {
+ set fill1 aquamarine3
+ set fill2 aquamarine3
+ set fill3 IndianRed1
+ set outline2 IndianRed3
+} else {
+ set fill1 black
+ set fill2 white
+ set fill3 Black
+ set outline2 white
+}
+set outline black
+
+.t.c create arc 20 20 220 120 -start 30 -extent 270 -outline $fill1 -width 14 \
+ -style arc
+.t.c create arc 260 20 460 120 -start 30 -extent 270 -fill $fill2 -width 14 \
+ -style chord -outline $outline
+.t.c create arc 500 20 620 160 -start 30 -extent 270 -fill {} -width 14 \
+ -style chord -outline $outline -outlinestipple gray50
+.t.c create arc 20 260 140 460 -start 45 -extent 90 -fill $fill2 -width 14 \
+ -style pieslice -outline $outline
+.t.c create arc 180 260 300 460 -start 45 -extent 90 -fill {} -width 14 \
+ -style pieslice -outline $outline
+.t.c create arc 340 260 460 460 -start 30 -extent 150 -fill $fill2 -width 14 \
+ -style chord -outline $outline -stipple gray50 -outlinestipple gray25
+.t.c create arc 500 260 620 460 -start 30 -extent 150 -fill {} -width 14 \
+ -style chord -outline $outline
+.t.c create arc 20 450 140 570 -start 135 -extent 270 -fill $fill1 -width 14 \
+ -style pieslice -outline {}
+.t.c create arc 180 450 300 570 -start 30 -extent -90 -fill $fill1 -width 14 \
+ -style pieslice -outline {}
+.t.c create arc 340 450 460 570 -start 320 -extent 270 -fill $fill1 -width 14 \
+ -style chord -outline {}
+.t.c create arc 500 450 620 570 -start 350 -extent -110 -fill $fill1 -width 14 \
+ -style chord -outline {}
+.t.c addtag arc withtag all
+.t.c addtag circle withtag [.t.c create oval 320 200 340 220 -fill MistyRose3]
+
+.t.c bind arc <Any-Enter> {
+ set prevFill [lindex [.t.c itemconf current -fill] 4]
+ set prevOutline [lindex [.t.c itemconf current -outline] 4]
+ if {($prevFill != "") || ($prevOutline == "")} {
+ .t.c itemconf current -fill $fill3
+ }
+ if {$prevOutline != ""} {
+ .t.c itemconf current -outline $outline2
+ }
+}
+.t.c bind arc <Any-Leave> {.t.c itemconf current -fill $prevFill -outline $prevOutline}
+
+bind .t.c <1> {markarea %x %y}
+bind .t.c <B1-Motion> {strokearea %x %y}
+
+proc markarea {x y} {
+ global areaX1 areaY1
+ set areaX1 $x
+ set areaY1 $y
+}
+
+proc strokearea {x y} {
+ global areaX1 areaY1 areaX2 areaY2
+ if {($areaX1 != $x) && ($areaY1 != $y)} {
+ .t.c delete area
+ .t.c addtag area withtag [.t.c create rect $areaX1 $areaY1 $x $y \
+ -outline black]
+ set areaX2 $x
+ set areaY2 $y
+ }
+}
+
+bind .t.c <Control-f> {
+ puts stdout "Enclosed: [.t.c find enclosed $areaX1 $areaY1 $areaX2 $areaY2]"
+ puts stdout "Overlapping: [.t.c find overl $areaX1 $areaY1 $areaX2 $areaY2]"
+}
+
+bind .t.c <3> {puts stdout "%x %y"}
+
+# The code below allows the circle to be move by shift-dragging.
+
+bind .t.c <Shift-1> {
+ set curx %x
+ set cury %y
+}
+
+bind .t.c <Shift-B1-Motion> {
+ .t.c move circle [expr {%x-$curx}] [expr {%y-$cury}]
+ set curx %x
+ set cury %y
+}
+
+# The binding below flashes the closest item to the mouse.
+
+bind .t.c <Control-c> {
+ set closest [.t.c find closest %x %y]
+ set oldfill [lindex [.t.c itemconf $closest -fill] 4]
+ .t.c itemconf $closest -fill IndianRed1
+ after 200 [list .t.c itemconfig $closest -fill $oldfill]
+}
+
+proc c {option value} {.t.c itemconf 2 $option $value}
+
+bind .t.c a {
+ set go 1
+ set i 1
+ while {$go} {
+ if {$i >= 50} {
+ set delta -5
+ }
+ if {$i <= 5} {
+ set delta 5
+ }
+ incr i $delta
+ c -start $i
+ c -extent [expr {360-2*$i}]
+ after 20
+ update
+ }
+}
+
+bind .t.c b {set go 0}
+
+bind .t.c <Control-x> {.t.c delete current}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tk8.6/tests/bell.test b/tk8.6/tests/bell.test
new file mode 100644
index 0000000..4f7df97
--- /dev/null
+++ b/tk8.6/tests/bell.test
@@ -0,0 +1,53 @@
+# This file is a Tcl script to test out Tk's "bell" command.
+# It is organized in the standard fashion for Tcl tests.
+#
+# Copyright (c) 1994 The Regents of the University of California.
+# Copyright (c) 1998-2000 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+
+test bell-1.1 {bell command} -body {
+ bell a
+} -returnCodes {error} -result {bad option "a": must be -displayof or -nice}
+
+test bell-1.2 {bell command} -body {
+ bell a b
+} -returnCodes {error} -result {bad option "a": must be -displayof or -nice}
+
+test bell-1.3 {bell command} -body {
+ bell -displayof gorp
+} -returnCodes {error} -result {bad window path name "gorp"}
+
+test bell-1.4 {bell command} -body {
+ bell -nice -displayof
+} -returnCodes {error} -result {wrong # args: should be "bell ?-displayof window? ?-nice?"}
+
+test bell-1.5 {bell command} -body {
+ bell -nice -nice -nice
+} -returnCodes {ok} -result {} ;#keep -result {} and -retutnCodes {ok} for clarity?
+
+test bell-1.6 {bell command} -body {
+ bell -displayof . -nice
+} -returnCodes {ok} -result {}
+
+test bell-1.7 {bell command} -body {
+ bell -nice -displayof . -nice
+} -returnCodes {error} -result {wrong # args: should be "bell ?-displayof window? ?-nice?"}
+
+test bell-1.8 {bell command} -body {
+ puts "Bell should ring now ..."
+ flush stdout
+ after 200
+ bell -displayof .
+ after 200
+ bell -nice
+ after 200
+ bell
+} -result {}
+
+cleanupTests
+return
diff --git a/tk8.6/tests/bevel.tcl b/tk8.6/tests/bevel.tcl
new file mode 100644
index 0000000..4af60f3
--- /dev/null
+++ b/tk8.6/tests/bevel.tcl
@@ -0,0 +1,158 @@
+# This file creates a visual test for bevels drawn around text in text
+# widgets. It is part of the Tk visual test suite, which is invoked
+# via the "visual" script.
+
+catch {destroy .t}
+toplevel .t
+wm title .t "Visual Tests for Borders in Text Widgets"
+wm iconname .t "Text Borders"
+wm geom .t +0+0
+
+text .t.t -width 60 -height 30 -setgrid true -xscrollcommand {.t.h set} \
+ -font {Courier 12} \
+ -yscrollcommand {.t.v set} -wrap none -relief raised -bd 2
+scrollbar .t.v -orient vertical -command ".t.t yview"
+scrollbar .t.h -orient horizontal -command ".t.t xview"
+button .t.quit -text Quit -command {destroy .t}
+pack .t.quit -side bottom -pady 3 -ipadx 4 -ipady 2
+pack .t.h -side bottom -fill x
+pack .t.v -side right -fill y
+pack .t.t -expand yes -fill both
+wm minsize .t 1 1
+
+if {[winfo depth .t] > 1} {
+ .t.t tag configure r1 -relief raised -borderwidth 2 -background #b2dfee
+ .t.t tag configure r2 -relief raised -borderwidth 2 -background #b2dfee \
+ -offset 2
+ .t.t tag configure s1 -relief sunken -borderwidth 2 -background #b2dfee
+} else {
+ .t.t tag configure r1 -relief raised -borderwidth 2 -background white
+ .t.t tag configure r2 -relief raised -borderwidth 2 -background white \
+ -offset 2
+ .t.t tag configure s1 -relief sunken -borderwidth 2 -background white
+}
+.t.t tag configure indent1 -lmargin1 100
+.t.t tag configure indent2 -lmargin1 200
+
+.t.t insert end {This display contains a bunch of raised and sunken
+regions to exercise the bevel-drawing facilities of
+DisplayLineBackground. The letters have the following
+significance:
+
+r - should appear raised
+u - should appear raised and also slightly offset vertically
+s - should appear sunken
+S - should appear solid
+n - preceding relief should extend right to end of line.
+* - should appear "normal"
+x - extra long lines to allow horizontal scrolling.
+
+Try scrolling the text both vertically and horizontally to
+be sure that the bevels are still drawn correctly.
+
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+
+Pass 1 (side bevels):
+
+}
+.t.t insert end ****
+.t.t insert end rrrrrrr r1
+.t.t insert end uuuu r2
+.t.t insert end ************
+.t.t insert end ssssssssssssssssss s1
+.t.t insert end \n\n****************
+.t.t insert end rrrrrrrrrrrrrrn\n r1
+
+.t.t insert end "\nPass 2 (top bevels):\n\n"
+.t.t insert end rrrrrrrrrrrrrr r1
+.t.t insert end rrrrr {r1 dummy}
+.t.t insert end rrrrrrrrrrrrrrrrrrr r1
+.t.t insert end \n************
+.t.t insert end rrrrrrrrrrrrrrrrr r1
+.t.t insert end ***********\n
+.t.t insert end rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr r1
+.t.t insert end \n\n***
+.t.t insert end rrrrrrrrrrrrrrrrrrr r1
+.t.t insert end ***********\n*
+.t.t insert end rrrrrrrrr r1
+.t.t insert end ********
+.t.t insert end rrrrrrrrrrrrrrrrrrrrrrrrr r1
+.t.t insert end \n\n*
+.t.t insert end *** dummy
+.t.t insert end rrrrrrrrrrrrrrrrrrrrrrrrr r1
+.t.t insert end n\nrrrrrrrrrrrrrrr {r1 indent1}
+.t.t insert end \n\n***
+.t.t insert end rrr r1
+.t.t insert end \n
+.t.t insert end rrrr {r1 indent1}
+
+.t.t insert end \n\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n
+.t.t insert end "Pass 3 (bottom bevels):\n\n"
+.t.t insert end *******
+.t.t insert end ********** dummy
+.t.t insert end rrrrrrrrrrrrrrrr r1
+.t.t insert end **********\n
+.t.t insert end rrrrrrrrr r1
+.t.t insert end uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu r2
+.t.t insert end \n********************
+.t.t insert end rrrrrrrrrrrrrrr r1
+.t.t insert end ************\n\n*
+.t.t insert end rrrrrrrrrrrr r1
+.t.t insert end ********
+.t.t insert end rrrrrrrrrrrrrrrrrrrrrrrrr r1
+.t.t insert end \n*****
+.t.t insert end rrrrrrrrrrrrrrrrrrrr r1
+.t.t insert end **********\n\n
+.t.t insert end rrrrrrrrrrrrrrr {r1 indent1}
+.t.t insert end \n** dummy
+.t.t insert end **
+.t.t insert end rrrrrrrrrrrrrrrrrrrrn\n r1
+.t.t insert end \n
+.t.t insert end rrrr {r1 indent1}
+.t.t insert end \n***
+.t.t insert end rrr r1
+
+.t.t insert end \n\nMiscellaneous:\n\n
+.t.t insert end rrr r1
+.t.t insert end *****
+.t.t insert end rrr r1
+foreach i {1 2 3} {
+ .t.t insert end \n
+ .t.t insert end ***
+ .t.t insert end rrrrr r1
+}
+.t.t insert end \n
+.t.t insert end rrr r1
+.t.t insert end *****
+.t.t insert end rrr r1
+
+font configure TkFixedFont -size 20
+.t.t tag configure sol100 -relief solid -borderwidth 100 \
+ -foreground red -font TkFixedFont
+.t.t tag configure sol12 -relief solid -borderwidth 12 \
+ -foreground red -font TkFixedFont
+.t.t tag configure big -font TkFixedFont
+set ind [.t.t index end]
+
+.t.t insert end "\n\nBorders do not leak on the neighbour chars"
+.t.t insert end "\nOnly \"S\" is on dark background"
+.t.t insert end {
+ xxx
+ x} {} S sol100 {x
+ xxx}
+
+.t.t insert end "\n\nA very thick border grows toward the inside of the tagged area only"
+.t.t insert end "\nOnly \"S\" is on dark background"
+.t.t insert end {
+ xxxx} {} SSSSS sol100 {xxxx
+ x} {} SSSSSSSSSSSSSSSSSS sol100 {x
+ xxx} {} SSSSSSSSS sol100 xxxx {}
+
+.t.t insert end "\n\nA thinner border is continuous"
+.t.t insert end {
+ xxxx} {} SSSSS sol12 {xxxx
+ x} {} SSSSSSSSSSSSSSSSSS sol12 {x
+ xxx} {} SSSSSSSSS sol12 xxxx {}
+
+.t.t tag add big $ind end
+
diff --git a/tk8.6/tests/bgerror.test b/tk8.6/tests/bgerror.test
new file mode 100644
index 0000000..fd9594a
--- /dev/null
+++ b/tk8.6/tests/bgerror.test
@@ -0,0 +1,67 @@
+# This file is a Tcl script to test the bgerror command.
+# It is organized in the standard fashion for Tcl tests.
+#
+# Copyright (c) 1997 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+
+test bgerror-1.1 {bgerror / tkerror compat} -setup {
+ set errRes {}
+ proc tkerror {err} {
+ global errRes;
+ set errRes $err;
+ }
+} -body {
+ after 0 {error err1}
+ vwait errRes;
+ return $errRes;
+} -cleanup {
+ catch {rename tkerror {}}
+} -result {err1}
+
+test bgerror-1.2 {bgerror / tkerror compat / accumulation} -setup {
+ set errRes {}
+ proc tkerror {err} {
+ global errRes;
+ lappend errRes $err;
+ }
+} -body {
+ after 0 {error err1}
+ after 0 {error err2}
+ after 0 {error err3}
+ update
+ return $errRes;
+} -cleanup {
+ catch {rename tkerror {}}
+} -result {err1 err2 err3}
+
+test bgerror-1.3 {bgerror / tkerror compat / accumulation / break} -setup {
+ set errRes {}
+ proc tkerror {err} {
+ global errRes;
+ lappend errRes $err;
+ return -code break "skip!";
+ }
+} -body {
+ after 0 {error err1}
+ after 0 {error err2}
+ after 0 {error err3}
+ update
+ return $errRes;
+} -cleanup {
+ catch {rename tkerror {}}
+} -result {err1}
+
+
+# some testing of the default error dialog
+# would be needed too, but that's not easy at all
+# to emulate.
+
+# cleanup
+cleanupTests
+return
diff --git a/tk8.6/tests/bind.test b/tk8.6/tests/bind.test
new file mode 100644
index 0000000..981ba32
--- /dev/null
+++ b/tk8.6/tests/bind.test
@@ -0,0 +1,6149 @@
+# This file is a Tcl script to test out Tk's "bind" and "bindtags"
+# commands plus the procedures in tkBind.c. It is organized in the
+# standard fashion for Tcl tests.
+#
+# Copyright (c) 1994 The Regents of the University of California.
+# Copyright (c) 1994-1995 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+tk useinputmethods 0
+
+toplevel .t -width 100 -height 50
+wm geom .t +0+0
+update idletasks
+
+foreach p [event info] {event delete $p}
+foreach event [bind Test] {
+ bind Test $event {}
+}
+foreach event [bind all] {
+ bind all $event {}
+}
+
+proc unsetBindings {} {
+ bind all <Enter> {}
+ bind Test <Enter> {}
+ bind Toplevel <Enter> {}
+ bind xyz <Enter> {}
+ bind {a b} <Enter> {}
+ bind .t <Enter> {}
+}
+
+# This function fills the pattern matcher's ring buffer with events of
+# the specified type. This can be used when testing with generated
+# events to make sure that there are no stray events in the ring
+# buffer which might cause the pattern matcher to find unintended
+# matches. The size of the ring buffer is EVENT_BUFFER_SIZE, which is
+# currently set to 30 (or 45 on macOS). If this changes, the code
+# below will need to change.
+proc clearRingBuffer {{event}} {
+ for {set i 0} {$i < 45} {incr i} {
+ event generate . $event
+ }
+}
+
+# move the mouse pointer away of the testing area
+# otherwise some spurious events may pollute the tests
+toplevel .top
+wm geometry .top 50x50-50-50
+update
+event generate .top <Button-1> -warp 1
+update
+destroy .top
+
+test bind-1.1 {bind command} -body {
+ bind
+} -returnCodes error -result {wrong # args: should be "bind window ?pattern? ?command?"}
+test bind-1.2 {bind command} -body {
+ bind a b c d
+} -returnCodes error -result {wrong # args: should be "bind window ?pattern? ?command?"}
+test bind-1.3 {bind command} -body {
+ bind .gorp
+} -returnCodes error -result {bad window path name ".gorp"}
+test bind-1.4 {bind command} -body {
+ bind foo
+} -returnCodes ok -result {}
+test bind-1.5 {bind command} -body {
+ bind .t <gorp-> {}
+} -returnCodes ok -result {}
+test bind-1.6 {bind command} -body {
+ frame .t.f
+ bind .t.f <Enter> {test script}
+ set result [bind .t.f <Enter>]
+ bind .t.f <Enter> {}
+ list $result [bind .t.f <Enter>]
+} -cleanup {
+ destroy .t.f
+} -result {{test script} {}}
+test bind-1.7 {bind command} -body {
+ frame .t.f
+ bind .t.f <Enter> {test script}
+ bind .t.f <Enter> {+more text}
+ bind .t.f <Enter>
+} -cleanup {
+ destroy .t.f
+} -result {test script
+more text}
+test bind-1.8 {bind command} -body {
+ bind .t <gorp-> {test script}
+} -returnCodes error -result {bad event type or keysym "gorp"}
+test bind-1.9 {bind command} -body {
+ catch {bind .t <gorp-> {test script}}
+ bind .t
+} -result {}
+test bind-1.10 {bind command} -body {
+ bind .t <gorp->
+} -returnCodes ok -result {}
+test bind-1.11 {bind command} -body {
+ frame .t.f
+ bind .t.f <Enter> {script 1}
+ bind .t.f <Leave> {script 2}
+ bind .t.f a {script for a}
+ bind .t.f b {script for b}
+ lsort [bind .t.f]
+} -cleanup {
+ destroy .t.f
+} -result {<Enter> <Leave> a b}
+
+test bind-2.1 {bindtags command} -body {
+ bindtags
+} -returnCodes error -result {wrong # args: should be "bindtags window ?taglist?"}
+test bind-2.2 {bindtags command} -body {
+ bindtags a b c
+} -returnCodes error -result {wrong # args: should be "bindtags window ?taglist?"}
+test bind-2.3 {bindtags command} -body {
+ bindtags .foo
+} -returnCodes error -result {bad window path name ".foo"}
+test bind-2.4 {bindtags command} -body {
+ bindtags .t
+} -result {.t Toplevel all}
+test bind-2.5 {bindtags command} -body {
+ frame .t.f
+ bindtags .t.f
+} -cleanup {
+ destroy .t.f
+} -result {.t.f Frame .t all}
+test bind-2.6 {bindtags command} -body {
+ frame .t.f
+ bindtags .t.f {{x y z} b c d}
+ bindtags .t.f
+} -cleanup {
+ destroy .t.f
+} -result {{x y z} b c d}
+test bind-2.7 {bindtags command} -body {
+ frame .t.f
+ bindtags .t.f {x y z}
+ bindtags .t.f {}
+ bindtags .t.f
+} -cleanup {
+ destroy .t.f
+} -result {.t.f Frame .t all}
+test bind-2.8 {bindtags command} -body {
+ frame .t.f
+ bindtags .t.f {x y z}
+ bindtags .t.f {a b c d}
+ bindtags .t.f
+} -cleanup {
+ destroy .t.f
+} -result {a b c d}
+test bind-2.9 {bindtags command} -body {
+ frame .t.f
+ bindtags .t.f {a b c}
+ bindtags .t.f "\{"
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {unmatched open brace in list}
+test bind-2.10 {bindtags command} -body {
+ frame .t.f
+ bindtags .t.f {a b c}
+ catch {bindtags .t.f "\{"}
+ bindtags .t.f
+} -cleanup {
+ destroy .t.f
+} -result {.t.f Frame .t all}
+test bind-2.11 {bindtags command} -body {
+ frame .t.f
+ bindtags .t.f {a b c}
+ bindtags .t.f "a .gorp b"
+} -cleanup {
+ destroy .t.f
+} -returnCodes ok
+test bind-2.12 {bindtags command} -body {
+ frame .t.f
+ bindtags .t.f {a b c}
+ catch {bindtags .t.f "a .gorp b"}
+ bindtags .t.f
+} -cleanup {
+ destroy .t.f
+} -result {a .gorp b}
+
+
+test bind-3.1 {TkFreeBindingTags procedure} -body {
+ frame .t.f
+ bindtags .t.f "a b c d"
+ destroy .t.f
+} -cleanup {
+ destroy .t.f
+} -result {}
+test bind-3.2 {TkFreeBindingTags procedure} -body {
+ frame .t.f
+ catch {bindtags .t.f "a .gorp b .t.f"}
+ destroy .t.f
+} -cleanup {
+ destroy .t.f
+} -result {}
+
+
+test bind-4.1 {TkBindEventProc procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ update
+ set x {}
+} -body {
+ bind all <Enter> {lappend x "%W enter all"}
+ bind Test <Enter> {lappend x "%W enter frame"}
+ bind Toplevel <Enter> {lappend x "%W enter toplevel"}
+ bind xyz <Enter> {lappend x "%W enter xyz"}
+ bind {a b} <Enter> {lappend x "%W enter {a b}"}
+ bind .t <Enter> {lappend x "%W enter .t"}
+ bind .t.f <Enter> {lappend x "%W enter .t.f"}
+
+ event generate .t.f <Enter>
+ return $x
+} -cleanup {
+ destroy .t.f
+ unsetBindings
+} -result {{.t.f enter .t.f} {.t.f enter frame} {.t.f enter .t} {.t.f enter all}}
+test bind-4.2 {TkBindEventProc procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ update
+ set x {}
+} -body {
+ bind all <Enter> {lappend x "%W enter all"}
+ bind Test <Enter> {lappend x "%W enter frame"}
+ bind Toplevel <Enter> {lappend x "%W enter toplevel"}
+ bind xyz <Enter> {lappend x "%W enter xyz"}
+ bind {a b} <Enter> {lappend x "%W enter {a b}"}
+ bind .t <Enter> {lappend x "%W enter .t"}
+ bind .t.f <Enter> {lappend x "%W enter .t.f"}
+
+ bindtags .t.f {.t.f {a b} xyz}
+ event generate .t.f <Enter>
+ return $x
+} -cleanup {
+ destroy .t.f
+ unsetBindings
+} -result {{.t.f enter .t.f} {.t.f enter {a b}} {.t.f enter xyz}}
+test bind-4.3 {TkBindEventProc procedure} -body {
+ set x {}
+ bind all <Enter> {lappend x "%W enter all"}
+ bind Test <Enter> {lappend x "%W enter frame"}
+ bind Toplevel <Enter> {lappend x "%W enter toplevel"}
+ bind xyz <Enter> {lappend x "%W enter xyz"}
+ bind {a b} <Enter> {lappend x "%W enter {a b}"}
+ bind .t <Enter> {lappend x "%W enter .t"}
+
+ event generate .t <Enter>
+ return $x
+} -cleanup {
+ unsetBindings
+} -result {{.t enter .t} {.t enter toplevel} {.t enter all}}
+test bind-4.4 {TkBindEventProc procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ frame .t.f3 -width 50 -height 50
+ pack .t.f3
+ update
+ set x {}
+} -body {
+ bind all <Enter> {lappend x "%W enter all"}
+ bind Test <Enter> {lappend x "%W enter frame"}
+ bind Toplevel <Enter> {lappend x "%W enter toplevel"}
+ bind xyz <Enter> {lappend x "%W enter xyz"}
+ bind {a b} <Enter> {lappend x "%W enter {a b}"}
+ bind .t <Enter> {lappend x "%W enter .t"}
+
+ bindtags .t.f {.t.f .t.f2 .t.f3}
+ bind .t.f <Enter> {lappend x "%W enter .t.f"}
+ bind .t.f3 <Enter> {lappend x "%W enter .t.f3"}
+ event generate .t.f <Enter>
+ return $x
+} -cleanup {
+ destroy .t.f .t.f3
+ unsetBindings
+} -result {{.t.f enter .t.f} {.t.f enter .t.f3}}
+test bind-4.5 {TkBindEventProc procedure} -setup {
+ # This tests memory allocation for objPtr; it won't serve any useful
+ # purpose unless run with some sort of allocation checker turned on.
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ update
+} -body {
+ bind all <Enter> {lappend x "%W enter all"}
+ bind Test <Enter> {lappend x "%W enter frame"}
+ bind Toplevel <Enter> {lappend x "%W enter toplevel"}
+ bind xyz <Enter> {lappend x "%W enter xyz"}
+ bind {a b} <Enter> {lappend x "%W enter {a b}"}
+ bind .t <Enter> {lappend x "%W enter .t"}
+ bindtags .t.f {a b c d e f g h i j k l m n o p q r s t u v w x y z}
+
+ event generate .t.f <Enter>
+} -cleanup {
+ destroy .t.f
+ unsetBindings
+} -result {}
+
+
+test bind-5.1 {Tk_CreateBindingTable procedure} -body {
+ canvas .t.c
+ .t.c bind foo
+} -cleanup {
+ destroy .t.c
+} -result {}
+
+
+test bind-6.1 {Tk_DeleteBindTable procedure} -body {
+ canvas .t.c
+ .t.c bind foo <1> {string 1}
+ .t.c create rectangle 0 0 100 100
+ .t.c bind 1 <2> {string 2}
+ destroy .t.c
+} -cleanup {
+ destroy .t.c
+} -result {}
+test bind-7.1 {Tk_CreateBinding procedure: bad binding} -body {
+ canvas .t.c
+ .t.c bind foo <
+} -cleanup {
+ destroy .t.c
+} -returnCodes error -result {no event type or button # or keysym}
+test bind-7.3 {Tk_CreateBinding procedure: append} -body {
+ canvas .t.c
+ .t.c bind foo <1> "button 1"
+ .t.c bind foo <1> "+more button 1"
+ .t.c bind foo <1>
+} -cleanup {
+ destroy .t.c
+} -result {button 1
+more button 1}
+test bind-7.4 {Tk_CreateBinding procedure: append to non-existing} -body {
+ canvas .t.c
+ .t.c bind foo <1> "+button 1"
+ .t.c bind foo <1>
+} -cleanup {
+ destroy .t.c
+} -result {button 1}
+
+test bind-8.1 {Tk_CreateBinding: error} -body {
+ bind . <xyz> "xyz"
+} -returnCodes error -result {bad event type or keysym "xyz"}
+
+test bind-9.1 {Tk_DeleteBinding procedure} -body {
+ frame .t.f -class Test -width 150 -height 100
+ bind .t.f <
+} -cleanup {
+ destroy .t.f
+} -returnCodes ok
+test bind-9.2 {Tk_DeleteBinding procedure} -setup {
+ set result {}
+} -body {
+ frame .t.f -class Test -width 150 -height 100
+ foreach i {a b c d} {
+ bind .t.f $i "binding for $i"
+ }
+ foreach i {b d a c} {
+ bind .t.f $i {}
+ lappend result [lsort [bind .t.f]]
+ }
+ return $result
+} -cleanup {
+ destroy .t.f
+} -result {{a c d} {a c} c {}}
+test bind-9.3 {Tk_DeleteBinding procedure} -setup {
+ set result {}
+} -body {
+ frame .t.f -class Test -width 150 -height 100
+ foreach i {<1> <Meta-1> <Control-1> <Double-Alt-1>} {
+ bind .t.f $i "binding for $i"
+ }
+ foreach i {<Control-1> <Double-Alt-1> <1> <Meta-1>} {
+ bind .t.f $i {}
+ lappend result [lsort [bind .t.f]]
+ }
+ return $result
+} -cleanup {
+ destroy .t.f
+} -result {{<Button-1> <Double-Alt-Button-1> <Meta-Button-1>} {<Button-1> <Meta-Button-1>} <Meta-Button-1> {}}
+
+test bind-10.1 {Tk_GetBinding procedure} -body {
+ canvas .t.c
+ .t.c bind foo <
+} -cleanup {
+ destroy .t.c
+} -returnCodes error -result {no event type or button # or keysym}
+test bind-10.2 {Tk_GetBinding procedure} -body {
+ canvas .t.c
+ .t.c bind foo a Test
+ .t.c bind foo a
+} -cleanup {
+ destroy .t.c
+} -result {Test}
+
+test bind-11.1 {Tk_GetAllBindings procedure} -body {
+ frame .t.f
+ foreach i "! a \\\{ ~ <Delete> <space> <<Paste>> <Tab> <Linefeed> <less> <Meta-a> <Acircumflex>" {
+ bind .t.f $i Test
+ }
+ lsort [bind .t.f]
+} -cleanup {
+ destroy .t.f
+} -result {! <<Paste>> <Key-Acircumflex> <Key-Delete> <Key-Linefeed> <Key-Tab> <Key-less> <Key-space> <Meta-Key-a> a \{ ~}
+test bind-11.2 {Tk_GetAllBindings procedure} -body {
+ frame .t.f
+ foreach i "<Double-1> <Triple-1> <Meta-Control-a> <Double-Alt-Enter> <1>" {
+ bind .t.f $i Test
+ }
+ lsort [bind .t.f]
+} -cleanup {
+ destroy .t.f
+} -result {<Button-1> <Control-Meta-Key-a> <Double-Alt-Enter> <Double-Button-1> <Triple-Button-1>}
+test bind-11.3 {Tk_GetAllBindings procedure} -body {
+ frame .t.f
+ foreach i "<Double-Triple-1> abcd a<Leave>b" {
+ bind .t.f $i Test
+ }
+ lsort [bind .t.f]
+} -cleanup {
+ destroy .t.f
+} -result {<Triple-Button-1> a<Leave>b abcd}
+
+
+test bind-12.1 {Tk_DeleteAllBindings procedure} -body {
+ frame .t.f -class Test -width 150 -height 100
+ destroy .t.f
+} -result {}
+test bind-12.2 {Tk_DeleteAllBindings procedure} -body {
+ frame .t.f -class Test -width 150 -height 100
+ foreach i "a b c <Meta-1> <Alt-a> <Control-a>" {
+ bind .t.f $i x
+ }
+ destroy .t.f
+} -result {}
+
+test bind-13.1 {Tk_BindEvent procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind Test <KeyPress> {lappend x "%W %K Test KeyPress"}
+ bind all <KeyPress> {lappend x "%W %K all KeyPress"}
+ bind Test : {lappend x "%W %K Test :"}
+ bind all _ {lappend x "%W %K all _"}
+ bind .t.f : {lappend x "%W %K .t.f :"}
+
+ event generate .t.f <Key-colon>
+ event generate .t.f <Key-plus>
+ event generate .t.f <Key-underscore>
+ return $x
+} -cleanup {
+ destroy .t.f
+ bind all <KeyPress> {}
+ bind Test <KeyPress> {}
+ bind all _ {}
+ bind Test : {}
+} -result {{.t.f colon .t.f :} {.t.f colon Test :} {.t.f colon all KeyPress} {.t.f plus Test KeyPress} {.t.f plus all KeyPress} {.t.f underscore Test KeyPress} {.t.f underscore all _}}
+
+test bind-13.2 {Tk_BindEvent procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind Test <KeyPress> {lappend x "%W %K Test press any"; break}
+ bind all <KeyPress> {continue; lappend x "%W %K all press any"}
+ bind .t.f : {lappend x "%W %K .t.f pressed colon"}
+
+ event generate .t.f <Key-colon>
+ return $x
+} -cleanup {
+ destroy .t.f
+ bind all <KeyPress> {}
+ bind Test <KeyPress> {}
+} -result {{.t.f colon .t.f pressed colon} {.t.f colon Test press any}}
+
+test bind-13.3 {Tk_BindEvent procedure} -setup {
+ proc bgerror args {}
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind Test <KeyPress> {lappend x "%W %K Test press any"; error Test}
+ bind .t.f : {lappend x "%W %K .t.f pressed colon"}
+ event generate .t.f <Key-colon>
+ update
+ list $x $errorInfo
+} -cleanup {
+ destroy .t.f
+ bind Test <KeyPress> {}
+ rename bgerror {}
+} -result {{{.t.f colon .t.f pressed colon} {.t.f colon Test press any}} {Test
+ while executing
+"error Test"
+ (command bound to event)}}
+test bind-13.4 {Tk_BindEvent procedure} -setup {
+ proc foo {} {
+ set x 44
+ event generate .t.f <Key-colon>
+ }
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind Test : {lappend x "%W %K Test"}
+ bind .t.f : {lappend x "%W %K .t.f"}
+ foo
+ return $x
+} -cleanup {
+ destroy .t.f
+ bind Test : {}
+} -result {{.t.f colon .t.f} {.t.f colon Test}}
+
+test bind-13.5 {Tk_BindEvent procedure} -body {
+ bind all <Destroy> {lappend x "%W destroyed"}
+ set x {}
+ frame .t.g -gorp foo
+} -cleanup {
+ bind all <Destroy> {}
+} -returnCodes error -result {unknown option "-gorp"}
+test bind-13.6 {Tk_BindEvent procedure} -body {
+ bind all <Destroy> {lappend x "%W destroyed"}
+ set x {}
+ catch {frame .t.g -gorp foo}
+ return $x
+} -cleanup {
+ bind all <Destroy> {}
+} -result {{.t.g destroyed}}
+
+test bind-13.7 {Tk_BindEvent procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f : {lappend x "%W (.t.f binding)"}
+ bind Test : {lappend x "%W (Test binding)"}
+ bind all : {bind .t.f : {}; lappend x "%W (all binding)"}
+ event generate .t.f <Key-colon>
+ return $x
+} -cleanup {
+ bind Test : {}
+ bind all : {}
+ destroy .t.f
+} -result {{.t.f (.t.f binding)} {.t.f (Test binding)} {.t.f (all binding)}}
+test bind-13.8 {Tk_BindEvent procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f : {lappend x "%W (.t.f binding)"}
+ bind Test : {lappend x "%W (Test binding)"}
+ bind all : {destroy .t.f; lappend x "%W (all binding)"}
+ event generate .t.f <Key-colon>
+ return $x
+} -cleanup {
+ bind Test : {}
+ bind all : {}
+ destroy .t.f
+} -result {{.t.f (.t.f binding)} {.t.f (Test binding)} {.t.f (all binding)}}
+
+test bind-13.9 {Tk_BindEvent procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <1> {lappend x "%W z (.t.f <1> binding)"}
+ bind .t.f <ButtonPress> {lappend x "%W z (.t.f <ButtonPress> binding)"}
+ event generate .t.f <Button-1>
+ event generate .t.f <Button-2>
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {{.t.f z (.t.f <1> binding)} {.t.f z (.t.f <ButtonPress> binding)}}
+test bind-13.10 {Tk_BindEvent procedure: ignore NotifyInferior} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Enter> "lappend x Enter%#"
+ bind .t.f <Leave> "lappend x Leave%#"
+ event generate .t.f <Enter> -serial 100 -detail NotifyAncestor
+ event generate .t.f <Enter> -serial 101 -detail NotifyInferior
+ event generate .t.f <Leave> -serial 102 -detail NotifyAncestor
+ event generate .t.f <Leave> -serial 103 -detail NotifyInferior
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {Enter100 Leave102}
+test bind-13.11 {Tk_BindEvent procedure: collapse Motions} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Motion> "lappend x Motion%#(%x,%y)"
+ event generate .t.f <Motion> -serial 100 -x 100 -y 200 -when tail
+ update
+ event generate .t.f <Motion> -serial 101 -x 200 -y 300 -when tail
+ event generate .t.f <Motion> -serial 102 -x 300 -y 400 -when tail
+ update
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {Motion100(100,200) Motion102(300,400)}
+test bind-13.12 {Tk_BindEvent procedure: collapse repeating modifiers} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Key> "lappend x %K%#"
+ bind .t.f <KeyRelease> "lappend x %K%#"
+ event generate .t.f <Key-Shift_L> -serial 100 -when tail
+ event generate .t.f <KeyRelease-Shift_L> -serial 101 -when tail
+ event generate .t.f <Key-Shift_L> -serial 102 -when tail
+ event generate .t.f <KeyRelease-Shift_L> -serial 103 -when tail
+ update
+} -cleanup {
+ destroy .t.f
+} -result {}
+test bind-13.13 {Tk_BindEvent procedure: valid key detail} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x Key%K"
+ bind .t.f <KeyRelease> "lappend x Release%K"
+ event generate .t.f <Key> -keysym colon
+ event generate .t.f <KeyRelease> -keysym colon
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {Keycolon Releasecolon}
+test bind-13.14 {Tk_BindEvent procedure: invalid key detail} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x Key%K"
+ bind .t.f <KeyRelease> "lappend x Release%K"
+ event generate .t.f <Key> -keycode -1
+ event generate .t.f <KeyRelease> -keycode -1
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {Key?? Release??}
+test bind-13.15 {Tk_BindEvent procedure: button detail} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button> "lappend x Button%b"
+ bind .t.f <ButtonRelease> "lappend x Release%b"
+ event generate .t.f <Button> -button 1
+ event generate .t.f <ButtonRelease> -button 3
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {Button1 Release3}
+test bind-13.16 {Tk_BindEvent procedure: virtual detail} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <<Paste>> "lappend x Paste"
+ event generate .t.f <<Paste>>
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {Paste}
+test bind-13.17 {Tk_BindEvent procedure: virtual event in event stream} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <<Paste>> "lappend x Paste"
+ event generate .t.f <<Paste>>
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {Paste}
+test bind-13.18 {Tk_BindEvent procedure: match detail physical} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button-2> {set x Button-2}
+ event add <<Paste>> <Button-2>
+ bind .t.f <<Paste>> {set x Paste}
+ event generate .t.f <Button-2>
+ return $x
+} -cleanup {
+ destroy .t.f
+ event delete <<Paste>> <Button-2>
+} -result {Button-2}
+
+test bind-13.19 {Tk_BindEvent procedure: no match detail physical} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ event add <<Paste>> <Button-2>
+ bind .t.f <<Paste>> {set x Paste}
+ event generate .t.f <Button-2>
+ return $x
+} -cleanup {
+ destroy .t.f
+ event delete <<Paste>> <Button-2>
+} -result {Paste}
+test bind-13.20 {Tk_BindEvent procedure: match detail virtual} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ event add <<Paste>> <Button-2>
+ bind .t.f <<Paste>> "lappend x Paste"
+ event generate .t.f <Button-2>
+ return $x
+} -cleanup {
+ destroy .t.f
+ event delete <<Paste>> <Button-2>
+} -result {Paste}
+test bind-13.21 {Tk_BindEvent procedure: no match detail virtual} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ event add <<Paste>> <Button-2>
+ bind .t.f <<Paste>> "lappend x Paste"
+ event generate .t.f <Button>
+ return $x
+} -cleanup {
+ destroy .t.f
+ event delete <<Paste>> <Button-2>
+} -result {}
+test bind-13.22 {Tk_BindEvent procedure: match no-detail physical} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button> {set x Button}
+ event add <<Paste>> <Button>
+ bind .t.f <<Paste>> {set x Paste}
+ event generate .t.f <Button-2>
+ return $x
+} -cleanup {
+ destroy .t.f
+ event delete <<Paste>> <Button>
+} -result {Button}
+test bind-13.23 {Tk_BindEvent procedure: no match no-detail physical} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ event add <<Paste>> <Button>
+ bind .t.f <<Paste>> {set x Paste}
+ event generate .t.f <Button-2>
+ return $x
+} -cleanup {
+ destroy .t.f
+ event delete <<Paste>> <Button>
+} -result {Paste}
+test bind-13.24 {Tk_BindEvent procedure: match no-detail virtual} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ event add <<Paste>> <Button>
+ bind .t.f <<Paste>> "lappend x Paste"
+ event generate .t.f <Button-2>
+ return $x
+} -cleanup {
+ destroy .t.f
+ event delete <<Paste>> <Button>
+} -result {Paste}
+test bind-13.25 {Tk_BindEvent procedure: no match no-detail virtual} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ event add <<Paste>> <Key>
+ bind .t.f <<Paste>> "lappend x Paste"
+ event generate .t.f <Button>
+ return $x
+} -cleanup {
+ destroy .t.f
+ event delete <<Paste>> <Key>
+} -result {}
+test bind-13.26 {Tk_BindEvent procedure: precedence} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ event add <<Paste>> <Button-2>
+ event add <<Copy>> <Button>
+ bind .t.f <Button-2> "lappend x Button-2"
+ bind .t.f <<Paste>> "lappend x Paste"
+ bind .t.f <Button> "lappend x Button"
+ bind .t.f <<Copy>> "lappend x Copy"
+
+ event generate .t.f <Button-2>
+ bind .t.f <Button-2> {}
+ event generate .t.f <Button-2>
+ bind .t.f <<Paste>> {}
+ event generate .t.f <Button-2>
+ bind .t.f <Button> {}
+ event generate .t.f <Button-2>
+ bind .t.f <<Copy>> {}
+ event generate .t.f <Button-2>
+ return $x
+} -cleanup {
+ destroy .t.f
+ event delete <<Paste>> <Button-2>
+ event delete <<Copy>> <Button>
+} -result {Button-2 Paste Button Copy}
+test bind-13.27 {Tk_BindEvent procedure: no detail virtual pattern list} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button-2> {set x Button-2}
+ event generate .t.f <Button-2>
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {Button-2}
+test bind-13.28 {Tk_BindEvent procedure: detail virtual pattern list} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ event add <<Paste>> <Button-2>
+ bind .t.f <<Paste>> {set x Paste}
+ event generate .t.f <Button-2>
+ return $x
+} -cleanup {
+ destroy .t.f
+ event delete <<Paste>> <Button-2>
+} -result {Paste}
+test bind-13.29 {Tk_BindEvent procedure: no no-detail virtual pattern list} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button> {set x Button}
+ event generate .t.f <Button-2>
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {Button}
+test bind-13.30 {Tk_BindEvent procedure: no-detail virtual pattern list} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ event add <<Paste>> <Button>
+ bind .t.f <<Paste>> {set x Paste}
+ event generate .t.f <Button-2>
+ return $x
+} -cleanup {
+ destroy .t.f
+ event delete <<Paste>> <Button>
+} -result {Paste}
+test bind-13.31 {Tk_BindEvent procedure: no match} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ event generate .t.f <Button-2>
+} -cleanup {
+ destroy .t.f
+} -result {}
+test bind-13.32 {Tk_BindEvent procedure: match} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button-2> {set x Button-2}
+ event generate .t.f <Button-2>
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {Button-2}
+test bind-13.33 {Tk_BindEvent procedure: many C bindings cause realloc} -setup {
+ # this test might not be useful anymore [#3009998]
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bindtags .t.f {a b c d e f g h i j k l m n o p}
+ foreach p [bindtags .t.f] {
+ bind $p <1> "lappend x $p"
+ }
+ event generate .t.f <1>
+ return $x
+} -cleanup {
+ foreach p [bindtags .t.f] {bind $p <1> {}}
+ destroy .t.f
+} -result {a b c d e f g h i j k l m n o p}
+test bind-13.34 {Tk_BindEvent procedure: multiple tags} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button-2> {lappend x .t.f}
+ bind Test <Button-2> {lappend x Button}
+ event generate .t.f <Button-2>
+ return $x
+} -cleanup {
+ destroy .t.f
+ bind Test <Button-2> {}
+} -result {.t.f Button}
+test bind-13.35 {Tk_BindEvent procedure: execute binding} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <1> {lappend x 1}
+ event generate .t.f <1>
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+test bind-13.38 {Tk_BindEvent procedure: binding gets to run} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind Test <1> {lappend x Test}
+ bind .t.f <1> {lappend x .t.f}
+ event generate .t.f <1>
+ return $x
+} -cleanup {
+ destroy .t.f
+ bind Test <1> {}
+} -result {.t.f Test}
+test bind-13.41 {Tk_BindEvent procedure: continue in script} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button-2> {lappend x b1; continue; lappend x b2}
+ bind Test <Button-2> {lappend x B1; continue; lappend x B2}
+ event generate .t.f <Button-2>
+ return $x
+} -cleanup {
+ destroy .t.f
+ bind Test <Button-2> {}
+} -result {b1 B1}
+test bind-13.43 {Tk_BindEvent procedure: break in script} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button-2> {lappend x b1; break; lappend x b2}
+ bind Test <Button-2> {lappend x B1; break; lappend x B2}
+ event generate .t.f <Button-2>
+ return $x
+} -cleanup {
+ destroy .t.f
+ bind Test <Button-2> {}
+} -result {b1}
+test bind-13.45 {Tk_BindEvent procedure: error in script} -setup {
+ proc bgerror msg {
+ global x
+ lappend x $msg
+ }
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button-2> {lappend x b1; blap}
+ bind Test <Button-2> {lappend x B1}
+ event generate .t.f <Button-2>
+ update
+ return $x
+} -cleanup {
+ destroy .t.f
+ bind Test <Button-2> {}
+ proc bgerror args {}
+} -result {b1 {invalid command name "blap"}}
+
+test bind-15.1 {MatchPatterns procedure, ignoring type mismatches} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f 12 {set x 1}
+ set x 0
+ event generate .t.f <Key-1>
+ event generate .t.f <KeyRelease-1>
+ event generate .t.f <Key-2>
+ event generate .t.f <KeyRelease-2>
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+test bind-15.2 {MatchPatterns procedure, ignoring type mismatches} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f 12 {set x 1}
+ set x 0
+ event generate .t.f <Key-1>
+ event generate .t.f <Enter>
+ event generate .t.f <KeyRelease-1>
+ event generate .t.f <Leave>
+ event generate .t.f <Key-2>
+ event generate .t.f <KeyRelease-2>
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+test bind-15.3 {MatchPatterns procedure, ignoring type mismatches} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f 12 {set x 1}
+ set x 0
+ event generate .t.f <Key-1>
+ event generate .t.f <Button-1>
+ event generate .t.f <Key-2>
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {0}
+test bind-15.4 {MatchPatterns procedure, ignoring type mismatches} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Double-1> {set x 1}
+ set x 0
+ event generate .t.f <Button-1>
+ event generate .t.f <ButtonRelease-1>
+ event generate .t.f <Button-1>
+ event generate .t.f <ButtonRelease-1>
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+test bind-15.5 {MatchPatterns procedure, ignoring type mismatches} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Double-ButtonRelease> {set x 1}
+ set x 0
+ event generate .t.f <Button-1>
+ event generate .t.f <ButtonRelease-1>
+ event generate .t.f <Button-2>
+ event generate .t.f <ButtonRelease-2>
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+test bind-15.6 {MatchPatterns procedure, ignoring type mismatches} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Double-1> {set x 1}
+ set x 0
+ event generate .t.f <Button-1>
+ event generate .t.f <Key-a>
+ event generate .t.f <ButtonRelease-1>
+ event generate .t.f <Button-1>
+ event generate .t.f <ButtonRelease-1>
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {0}
+test bind-15.7 {MatchPatterns procedure, ignoring type mismatches} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Double-1> {set x 1}
+ set x 0
+ event generate .t.f <Button-1>
+ event generate .t.f <Key-Shift_L>
+ event generate .t.f <ButtonRelease-1>
+ event generate .t.f <Button-1>
+ event generate .t.f <ButtonRelease-1>
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+test bind-15.8 {MatchPatterns procedure, ignoring type mismatches} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f ab {set x 1}
+ set x 0
+ event generate .t.f <Key-a>
+ event generate .t.f <Key-c>
+ event generate .t.f <Key-b>
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {0}
+test bind-15.9 {MatchPatterns procedure, modifier checks} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <M1-M2-Key> {set x 1}
+ set x 0
+ event generate .t.f <Key-a> -state 0x18
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+test bind-15.10 {MatchPatterns procedure, modifier checks} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <M1-M2-Key> {set x 1}
+ set x 0
+ event generate .t.f <Key-a> -state 0xfc
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+test bind-15.11 {MatchPatterns procedure, modifier checks} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <M1-M2-Key> {set x 1}
+ set x 0
+ event generate .t.f <Key-a> -state 0x8
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {0}
+test bind-15.12 {MatchPatterns procedure, ignore modifier presses and releases} -constraints {
+ nonPortable
+} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ # This test is non-portable because the Shift_L keysym may behave
+ # differently on some platforms.
+ bind .t.f aB {set x 1}
+ set x 0
+ event generate .t.f <Key-a>
+ event generate .t.f <Key-Shift_L>
+ event generate .t.f <Key-b> -state 1
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+test bind-15.13 {MatchPatterns procedure, checking detail} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f ab {set x 1}
+ set x 0
+ event generate .t.f <Key-a>
+ event generate .t.f <Key-c>
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {0}
+test bind-15.14 {MatchPatterns procedure, checking "nearby"} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Double-1> {set x 1}
+ set x 0
+ event generate .t.f <Button-2>
+ event generate .t.f <ButtonRelease-2>
+ event generate .t.f <Button-1> -x 30 -y 40
+ event generate .t.f <Button-1> -x 31 -y 39
+ event generate .t.f <ButtonRelease-1>
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+test bind-15.15 {MatchPatterns procedure, checking "nearby"} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Double-1> {set x 1}
+ set x 0
+ event generate .t.f <Button-2>
+ event generate .t.f <ButtonRelease-2>
+ event generate .t.f <Button-1> -x 30 -y 40
+ event generate .t.f <Button-1> -x 29 -y 41
+ event generate .t.f <ButtonRelease-1>
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+test bind-15.16 {MatchPatterns procedure, checking "nearby"} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Double-1> {set x 1}
+ set x 0
+ event generate .t.f <Button-2>
+ event generate .t.f <ButtonRelease-2>
+ event generate .t.f <Button-1> -x 30 -y 40
+ event generate .t.f <Button-1> -x 40 -y 40
+ event generate .t.f <ButtonRelease-2>
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {0}
+test bind-15.17 {MatchPatterns procedure, checking "nearby"} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Double-1> {set x 1}
+ set x 0
+ event generate .t.f <Button-2>
+ event generate .t.f <ButtonRelease-2>
+ event generate .t.f <Button-1> -x 30 -y 40
+ event generate .t.f <Button-1> -x 20 -y 40
+ event generate .t.f <ButtonRelease-1>
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {0}
+test bind-15.18 {MatchPatterns procedure, checking "nearby"} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Double-1> {set x 1}
+ set x 0
+ event generate .t.f <Button-2>
+ event generate .t.f <ButtonRelease-2>
+ event generate .t.f <Button-1> -x 30 -y 40
+ event generate .t.f <Button-1> -x 30 -y 30
+ event generate .t.f <ButtonRelease-1>
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {0}
+test bind-15.19 {MatchPatterns procedure, checking "nearby"} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Double-1> {set x 1}
+ set x 0
+ event generate .t.f <Button-2>
+ event generate .t.f <ButtonRelease-2>
+ event generate .t.f <Button-1> -x 30 -y 40
+ event generate .t.f <Button-1> -x 30 -y 50
+ event generate .t.f <ButtonRelease-1>
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {0}
+test bind-15.20 {MatchPatterns procedure, checking "nearby"} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Double-1> {set x 1}
+ set x 0
+ event generate .t.f <Button-2>
+ event generate .t.f <ButtonRelease-2>
+ event generate .t.f <Button-1> -time 300
+ event generate .t.f <Button-1> -time 700
+ event generate .t.f <ButtonRelease-1>
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+test bind-15.21 {MatchPatterns procedure, checking "nearby"} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Double-1> {set x 1}
+ set x 0
+ event generate .t.f <Button-2>
+ event generate .t.f <ButtonRelease-2>
+ event generate .t.f <Button-1> -time 300
+ event generate .t.f <Button-1> -time 900
+ event generate .t.f <ButtonRelease-1>
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {0}
+test bind-15.22 {MatchPatterns procedure, time wrap-around} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ clearRingBuffer <Key>
+} -body {
+ bind .t.f <Double-1> {set x 1}
+ set x 0
+ event generate .t.f <Button-1> -time -100
+ event generate .t.f <Button-1> -time 200
+ event generate .t.f <ButtonRelease-1>
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+test bind-15.23 {MatchPatterns procedure, time wrap-around} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ clearRingBuffer <Key>
+} -body {
+ bind .t.f <Double-1> {set x 1}
+ set x 0
+ event generate .t.f <Button-1> -time -100
+ event generate .t.f <Button-1> -time 500
+ event generate .t.f <ButtonRelease-1>
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {0}
+test bind-15.24 {MatchPatterns procedure, virtual event} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+ clearRingBuffer <Key>
+} -body {
+ event add <<Paste>> <Button-1>
+ bind .t.f <<Paste>> {lappend x paste}
+ event generate .t.f <Button-1>
+ event generate .t.f <ButtonRelease-1>
+ set x
+} -cleanup {
+ destroy .t.f
+ event delete <<Paste>> <Button-1>
+} -result {paste}
+test bind-15.25 {MatchPatterns procedure, reject a virtual event} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+ clearRingBuffer <Key>
+} -body {
+ event add <<Paste>> <Shift-Button-1>
+ bind .t.f <<Paste>> {lappend x paste}
+ event generate .t.f <Button-1>
+ event generate .t.f <ButtonRelease-1>
+ set x
+} -cleanup {
+ destroy .t.f
+ event delete <<Paste>> <Shift-Button-1>
+} -result {}
+test bind-15.26 {MatchPatterns procedure, reject a virtual event} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+ clearRingBuffer <Key>
+} -body {
+ event add <<V1>> <Button>
+ event add <<V2>> <Button-1>
+ event add <<V3>> <Shift-Button-1>
+ bind .t.f <<V2>> "lappend x V2%#"
+ event generate .t.f <Button> -serial 101
+ event generate .t.f <Button-1> -serial 102
+ event generate .t.f <Shift-Button-1> -serial 103
+ event generate .t.f <ButtonRelease-1>
+ bind .t.f <Shift-Button-1> "lappend x Shift-Button-1"
+ event generate .t.f <Button> -serial 104
+ event generate .t.f <Button-1> -serial 105
+ event generate .t.f <Shift-Button-1> -serial 106
+ event generate .t.f <ButtonRelease-1>
+ set x
+} -cleanup {
+ destroy .t.f
+ event delete <<V1>> <Button>
+ event delete <<V2>> <Button-1>
+ event delete <<V3>> <Shift-Button-1>
+} -result {V2102 V2103 V2105 Shift-Button-1}
+test bind-15.27 {MatchPatterns procedure, conflict resolution} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ clearRingBuffer <Button>
+} -body {
+ bind .t.f <KeyPress> {set x 0}
+ bind .t.f 1 {set x 1}
+ set x none
+ event generate .t.f <Key-1>
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+test bind-15.28 {MatchPatterns procedure, conflict resolution} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ clearRingBuffer <Button>
+} -body {
+ bind .t.f <KeyPress> {set x 0}
+ bind .t.f 1 {set x 1}
+ set x none
+ event generate .t.f <Key-2>
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {0}
+test bind-15.29 {MatchPatterns procedure, conflict resolution} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ clearRingBuffer <Button>
+} -body {
+ bind .t.f <KeyPress> {lappend x 0}
+ bind .t.f 1 {lappend x 1}
+ bind .t.f 21 {lappend x 2}
+ set x none
+ event generate .t.f <Key-2>
+ event generate .t.f <KeyRelease-2>
+ event generate .t.f <Key-1>
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {none 0 2}
+test bind-15.30 {MatchPatterns procedure, conflict resolution} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ clearRingBuffer <Key>
+} -body {
+ bind .t.f <ButtonPress> {set x 0}
+ bind .t.f <1> {set x 1}
+ set x none
+ event generate .t.f <Button-1>
+ event generate .t.f <ButtonRelease-1>
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+test bind-15.31 {MatchPatterns procedure, conflict resolution} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+ clearRingBuffer <Button>
+} -body {
+ bind .t.f <M1-Key> {set x 0}
+ bind .t.f <M2-Key> {set x 1}
+ event generate .t.f <Key-a> -state 0x18
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+test bind-15.32 {MatchPatterns procedure, conflict resolution} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ clearRingBuffer <Button>
+} -body {
+ bind .t.f <M2-Key> {set x 0}
+ bind .t.f <M1-Key> {set x 1}
+ set x none
+ event generate .t.f <Key-a> -state 0x18
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+test bind-15.33 {MatchPatterns procedure, conflict resolution} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+ clearRingBuffer <Key>
+} -body {
+ bind .t.f <1> {lappend x single}
+ bind Test <1> {lappend x single(Test)}
+ bind Test <Double-1> {lappend x double(Test)}
+ event generate .t.f <Button-1>
+ event generate .t.f <Button-1>
+ event generate .t.f <Button-1>
+ event generate .t.f <ButtonRelease-1>
+ set x
+} -cleanup {
+ destroy .t.f
+ bind Test <1> {}
+ bind Test <Double-1> {}
+} -result {single single(Test) single double(Test) single double(Test)}
+
+
+test bind-16.1 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Enter> {set x abcd}
+ set x none
+ event generate .t.f <Enter>
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {abcd}
+test bind-16.2 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Enter> {set x %#}
+ set x none
+ event generate .t.f <Enter> -serial 1234
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {1234}
+test bind-16.3 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Configure> {set x %a}
+ set x none
+ event generate .t.f <Configure> -above .t -window .t.f
+ set x
+} -cleanup {
+ destroy .t.f
+} -result [winfo id .t]
+test bind-16.4 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Button> {set x %b}
+ set x none
+ event generate .t.f <Button-3>
+ event generate .t.f <ButtonRelease-3>
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {3}
+test bind-16.5 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Expose> {set x %c}
+ set x none
+ event generate .t.f <Expose> -count 47
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {47}
+test bind-16.6 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Enter> {set x %d}
+ set x none
+ event generate .t.f <Enter> -detail NotifyAncestor
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {NotifyAncestor}
+test bind-16.7 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Enter> {set x %d}
+ set x none
+ event generate .t.f <Enter> -detail NotifyVirtual
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {NotifyVirtual}
+test bind-16.8 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Enter> {set x %d}
+ set x none
+ event generate .t.f <Enter> -detail NotifyNonlinear
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {NotifyNonlinear}
+test bind-16.9 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Enter> {set x %d}
+ set x none
+ event generate .t.f <Enter> -detail NotifyNonlinearVirtual
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {NotifyNonlinearVirtual}
+test bind-16.10 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Enter> {set x %d}
+ set x none
+ event generate .t.f <Enter> -detail NotifyPointer
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {NotifyPointer}
+test bind-16.11 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Enter> {set x %d}
+ set x none
+ event generate .t.f <Enter> -detail NotifyPointerRoot
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {NotifyPointerRoot}
+test bind-16.12 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Enter> {set x %d}
+ set x none
+ event generate .t.f <Enter> -detail NotifyDetailNone
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {NotifyDetailNone}
+test bind-16.13 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Enter> {set x %f}
+ set x none
+ event generate .t.f <Enter> -focus 1
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+test bind-16.14 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Expose> {set x "%x %y %w %h"}
+ set x none
+ event generate .t.f <Expose> -x 24 -y 18 -width 147 -height 61
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {24 18 147 61}
+test bind-16.15 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Configure> {set x "%x %y %w %h"}
+ set x none
+ event generate .t.f <Configure> -x 24 -y 18 -width 147 -height 61 -window .t.f
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {24 18 147 61}
+test bind-16.16 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Key> {set x "%k"}
+ set x none
+ event generate .t.f <Key> -keycode 146
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {146}
+test bind-16.17 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Enter> {set x "%m"}
+ set x none
+ event generate .t.f <Enter> -mode NotifyNormal
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {NotifyNormal}
+test bind-16.18 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Enter> {set x "%m"}
+ set x none
+ event generate .t.f <Enter> -mode NotifyGrab
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {NotifyGrab}
+test bind-16.19 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Enter> {set x "%m"}
+ set x none
+ event generate .t.f <Enter> -mode NotifyUngrab
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {NotifyUngrab}
+test bind-16.20 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Enter> {set x "%m"}
+ set x none
+ event generate .t.f <Enter> -mode NotifyWhileGrabbed
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {NotifyWhileGrabbed}
+test bind-16.21 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Map> {set x "%o"}
+ set x none
+ event generate .t.f <Map> -override 1 -window .t.f
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+test bind-16.22 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Reparent> {set x "%o"}
+ set x none
+ event generate .t.f <Reparent> -override true -window .t.f
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+test bind-16.23 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Configure> {set x "%o"}
+ set x none
+ event generate .t.f <Configure> -override 1 -window .t.f
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+test bind-16.24 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Circulate> {set x "%p"}
+ set x none
+ event generate .t.f <Circulate> -place PlaceOnTop -window .t.f
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {PlaceOnTop}
+test bind-16.25 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Circulate> {set x "%p"}
+ set x none
+ event generate .t.f <Circulate> -place PlaceOnBottom -window .t.f
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {PlaceOnBottom}
+test bind-16.26 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <1> {set x "%s"}
+ set x none
+ event generate .t.f <Button-1> -state 1402
+ event generate .t.f <ButtonRelease-1>
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {1402}
+test bind-16.27 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Enter> {set x "%s"}
+ set x none
+ event generate .t.f <Enter> -state 0x3ff
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {1023}
+test bind-16.28 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Visibility> {set x "%s"}
+ set x none
+ event generate .t.f <Visibility> -state VisibilityPartiallyObscured
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {VisibilityPartiallyObscured}
+test bind-16.29 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Visibility> {set x "%s"}
+ set x none
+ event generate .t.f <Visibility> -state VisibilityUnobscured
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {VisibilityUnobscured}
+test bind-16.30 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Visibility> {set x "%s"}
+ set x none
+ event generate .t.f <Visibility> -state VisibilityFullyObscured
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {VisibilityFullyObscured}
+test bind-16.31 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Button> {set x "%t"}
+ set x none
+ event generate .t.f <Button> -time 4294
+ event generate .t.f <ButtonRelease>
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {4294}
+test bind-16.32 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Button> {set x "%x %y"}
+ set x none
+ event generate .t.f <Button> -x 881 -y 432
+ event generate .t.f <ButtonRelease>
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {881 432}
+test bind-16.33 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Reparent> {set x "%x %y"}
+ set x none
+ event generate .t.f <Reparent> -x 882 -y 431 -window .t.f
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {882 431}
+test bind-16.34 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Enter> {set x "%x %y"}
+ set x none
+ event generate .t.f <Enter> -x 781 -y 632
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {781 632}
+test bind-16.35 {ExpandPercents procedure} -constraints {
+ nonPortable
+} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> {lappend x "%A"}
+ event generate .t.f <Key-a>
+ event generate .t.f <Key-A> -state 1
+ event generate .t.f <Key-Tab>
+ event generate .t.f <Key-Return>
+ event generate .t.f <Key-F1>
+ event generate .t.f <Key-Shift_L>
+ event generate .t.f <Key-space>
+ event generate .t.f <Key-dollar> -state 1
+ event generate .t.f <Key-braceleft> -state 1
+ event generate .t.f <Key-Multi_key>
+ event generate .t.f <Key-e>
+ event generate .t.f <Key-apostrophe>
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {a A { } {\r} {{}} {{}} { } {\$} \\\{ {{}} {{}} \u00e9}
+test bind-16.36 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Configure> {set x "%B"}
+ set x none
+ event generate .t.f <Configure> -borderwidth 24 -window .t.f
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {24}
+test bind-16.37 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Enter> {set x "%E"}
+ set x none
+ event generate .t.f <Enter> -sendevent 1
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+test bind-16.38 {ExpandPercents procedure} -constraints {
+ nonPortable
+} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> {lappend x %K}
+ event generate .t.f <Key-a>
+ event generate .t.f <Key-A> -state 1
+ event generate .t.f <Key-Tab>
+ event generate .t.f <Key-F1>
+ event generate .t.f <Key-Shift_L>
+ event generate .t.f <Key-space>
+ event generate .t.f <Key-dollar> -state 1
+ event generate .t.f <Key-braceleft> -state 1
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {a A Tab F1 Shift_L space dollar braceleft}
+test bind-16.39 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Key> {set x "%N"}
+ set x none
+ event generate .t.f <Key-space>
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {32}
+test bind-16.40 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Key> {set x "%S"}
+ set x none
+ event generate .t.f <Key-space> -subwindow .t
+ set x
+} -cleanup {
+ destroy .t.f
+} -result [winfo id .t]
+test bind-16.41 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Key> {set x "%T"}
+ set x none
+ event generate .t.f <Key>
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {2}
+test bind-16.42 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> {set x "%W"}
+ set x none
+ event generate .t.f <Key>
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {.t.f}
+test bind-16.43 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Button> {set x "%X %Y"}
+ set x none
+ event generate .t.f <Button> -rootx 422 -rooty 13
+ event generate .t.f <ButtonRelease>
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {422 13}
+test bind-16.44 {ExpandPercents procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Gravity> {set x "%R %S"}
+ set x none
+ event generate .t.f <Gravity>
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {?? ??}
+
+test bind-16.45 {ExpandPercents procedure} -setup {
+ set savedBind(Entry) [bind Entry <Key>]
+ set savedBind(All) [bind all <Key>]
+ entry .t.e
+ pack .t.e
+ focus -force .t.e
+ foreach p [event info] {event delete $p}
+ update
+} -body {
+ bind .t.e <Key> {set x "%M"}
+ bind Entry <Key> {set y "%M"}
+ bind all <Key> {set z "%M"}
+ set x none; set y none; set z none
+ event gen .t.e <Key-a>
+ list $x $y $z
+} -cleanup {
+ destroy .t.e
+ bind all <Key> $savedBind(All)
+ bind Entry <Key> $savedBind(Entry)
+ unset savedBind
+} -result {0 1 2}
+test bind-16.46 {ExpandPercents procedure} -setup {
+ set savedBind(All) [bind all <Key>]
+ set savedBind(Entry) [bind Entry <Key>]
+ entry .t.e
+ pack .t.e
+ focus -force .t.e
+ foreach p [event info] {event delete $p}
+ update
+ clearRingBuffer <Button>
+} -body {
+ bind all <Key> {set z "%M"}
+ bind Entry <Key> {set y "%M"}
+ bind .t.e <Key> {set x "%M"}
+ set x none; set y none; set z none
+ event gen .t.e <Key-a>
+ list $x $y $z
+} -cleanup {
+ destroy .t.e
+ bind Entry <Key> $savedBind(Entry)
+ bind all <Key> $savedBind(All)
+ unset savedBind
+} -result {0 1 2}
+
+test bind-17.1 {event command} -body {
+ event
+} -returnCodes error -result {wrong # args: should be "event option ?arg?"}
+test bind-17.2 {event command} -body {
+ event xyz
+} -returnCodes error -result {bad option "xyz": must be add, delete, generate, or info}
+test bind-17.3 {event command: add} -body {
+ event add
+} -returnCodes error -result {wrong # args: should be "event add virtual sequence ?sequence ...?"}
+test bind-17.4 {event command: add 1} -body {
+ event delete <<Paste>>
+ event add <<Paste>> <Control-v>
+ event info <<Paste>>
+} -cleanup {
+ event delete <<Paste>> <Control-v>
+} -result {<Control-Key-v>}
+test bind-17.5 {event command: add 2} -body {
+ event delete <<Paste>>
+ event add <<Paste>> <Control-v> <Button-2>
+ lsort [event info <<Paste>>]
+} -cleanup {
+ event delete <<Paste>> <Control-v> <Button-2>
+} -result {<Button-2> <Control-Key-v>}
+
+test bind-17.6 {event command: add with error} -body {
+ event add <<Paste>> <Control-v> <Button-2> abc <xyz> <1>
+} -cleanup {
+ event delete <<Paste>>
+} -returnCodes error -result {bad event type or keysym "xyz"}
+test bind-17.7 {event command: add with error} -body {
+ event delete <<Paste>>
+ catch {event add <<Paste>> <Control-v> <Button-2> abc <xyz> <1>}
+ lsort [event info <<Paste>>]
+} -cleanup {
+ event delete <<Paste>>
+} -result {<Button-2> <Control-Key-v> abc}
+
+test bind-17.8 {event command: delete} -body {
+ event delete
+} -returnCodes error -result {wrong # args: should be "event delete virtual ?sequence ...?"}
+test bind-17.9 {event command: delete many} -body {
+ event delete <<Paste>>
+ event add <<Paste>> <3> <1> <2> t
+ event delete <<Paste>> <1> <2>
+ lsort [event info <<Paste>>]
+} -cleanup {
+ event delete <<Paste>> <3> t
+} -result {<Button-3> t}
+test bind-17.10 {event command: delete all} -body {
+ event add <<Paste>> a b
+ event delete <<Paste>>
+ event info <<Paste>>
+} -cleanup {
+ event delete <<Paste>> a b
+} -result {}
+test bind-17.11 {event command: delete 1} -body {
+ event delete <<Paste>>
+ event add <<Paste>> a b c
+ event delete <<Paste>> b
+ lsort [event info <<Paste>>]
+} -cleanup {
+ event delete <<Paste>>
+} -result {a c}
+test bind-17.12 {event command: info name} -body {
+ event delete <<Paste>>
+ event add <<Paste>> a b c
+ lsort [event info <<Paste>>]
+} -cleanup {
+ event delete <<Paste>>
+} -result {a b c}
+test bind-17.13 {event command: info all} -body {
+ foreach p [event info] {event delete $p}
+ event add <<Paste>> a
+ event add <<Alive>> b
+ lsort [event info]
+} -cleanup {
+ event delete <<Paste>>
+ event delete <<Alive>>
+} -result {<<Alive>> <<Paste>>}
+
+test bind-17.14 {event command: info error} -body {
+ event info <<Paste>> <Control-v>
+} -returnCodes error -result {wrong # args: should be "event info ?virtual?"}
+test bind-17.15 {event command: generate} -body {
+ event generate
+} -returnCodes error -result {wrong # args: should be "event generate window event ?-option value ...?"}
+
+test bind-17.16 {event command: generate} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <1> "lappend x 1"
+ event generate .t.f <1>
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+test bind-17.17 {event command: generate} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ event generate .t.f <xyz>
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {bad event type or keysym "xyz"}
+test bind-17.18 {event command} -body {
+ event foo
+} -returnCodes error -result {bad option "foo": must be add, delete, generate, or info}
+
+
+test bind-18.1 {CreateVirtualEvent procedure: GetVirtualEventUid} -body {
+ event add asd <Ctrl-v>
+} -returnCodes error -result {virtual event "asd" is badly formed}
+test bind-18.2 {CreateVirtualEvent procedure: FindSequence} -body {
+ event add <<asd>> <Ctrl-v>
+} -returnCodes error -result {bad event type or keysym "Ctrl"}
+test bind-18.3 {CreateVirtualEvent procedure: new physical} -body {
+ event delete <<xyz>>
+ event add <<xyz>> <Control-v>
+ event info <<xyz>>
+} -cleanup {
+ event delete <<xyz>>
+} -result {<Control-Key-v>}
+test bind-18.4 {CreateVirtualEvent procedure: duplicate physical} -body {
+ event delete <<xyz>>
+ event add <<xyz>> <Control-v>
+ event add <<xyz>> <Control-v>
+ event info <<xyz>>
+} -cleanup {
+ event delete <<xyz>>
+} -result {<Control-Key-v>}
+test bind-18.5 {CreateVirtualEvent procedure: existing physical} -body {
+ foreach p [event info] {event delete $p}
+ event add <<xyz>> <Control-v>
+ event add <<abc>> <Control-v>
+ list [lsort [event info]] [event info <<xyz>>] [event info <<abc>>]
+} -cleanup {
+ event delete <<xyz>>
+ event delete <<abc>>
+} -result {{<<abc>> <<xyz>>} <Control-Key-v> <Control-Key-v>}
+test bind-18.6 {CreateVirtualEvent procedure: new virtual} -body {
+ foreach p [event info] {event delete $p}
+ event add <<xyz>> <Control-v>
+ list [event info] [event info <<xyz>>]
+} -cleanup {
+ event delete <<abc>>
+} -result {<<xyz>> <Control-Key-v>}
+test bind-18.7 {CreateVirtualEvent procedure: existing virtual} -body {
+ foreach p [event info] {event delete $p}
+ event add <<xyz>> <Control-v>
+ event add <<xyz>> <Button-2>
+ list [event info] [lsort [event info <<xyz>>]]
+} -cleanup {
+ event delete <<xyz>>
+} -result {<<xyz>> {<Button-2> <Control-Key-v>}}
+
+
+test bind-19.1 {DeleteVirtualEvent procedure: GetVirtualEventUid} -body {
+ event add xyz {}
+} -returnCodes error -result {virtual event "xyz" is badly formed}
+test bind-19.2 {DeleteVirtualEvent procedure: non-existent virtual} -setup {
+ foreach p [event info] {event delete $p}
+} -body {
+ event delete <<xyz>>
+ event info
+} -result {}
+test bind-19.3 {DeleteVirtualEvent procedure: delete 1} -setup {
+ event delete <<xyz>>
+} -body {
+ event add <<xyz>> <Control-v>
+ event delete <<xyz>> <Control-v>
+ event info <<xyz>>
+} -result {}
+test bind-19.4 {DeleteVirtualEvent procedure: delete 1, not owned} -setup {
+ event delete <<xyz>>
+} -body {
+ event add <<xyz>> <Control-v>
+ event delete <<xyz>> <Button-1>
+ event info <<xyz>>
+} -result {<Control-Key-v>}
+test bind-19.5 {DeleteVirtualEvent procedure: delete 1, badly formed} -body {
+ event add <<xyz>> <Control-v>
+ event delete <<xyz>> <xyz>
+} -cleanup {
+ event delete <<xyz>>
+} -returnCodes error -result {bad event type or keysym "xyz"}
+test bind-19.6 {DeleteVirtualEvent procedure: delete 1, badly formed} -body {
+ event add <<xyz>> <Control-v>
+ event delete <<xyz>> <<Paste>>
+} -cleanup {
+ event delete <<xyz>>
+} -returnCodes error -result {virtual event not allowed in definition of another virtual event}
+test bind-19.7 {DeleteVirtualEvent procedure: owns 1, delete all} -body {
+ foreach p [event info] {event delete $p}
+ event add <<xyz>> <Control-v>
+ event delete <<xyz>>
+ event info
+} -result {}
+test bind-19.8 {DeleteVirtualEvent procedure: owns 1, delete 1} -body {
+ foreach p [event info] {event delete $p}
+ event add <<xyz>> <Control-v>
+ event delete <<xyz>> <Control-v>
+ event info
+} -result {}
+test bind-19.9 {DeleteVirtualEvent procedure: owns many, delete all} -body {
+ foreach p [event info] {event delete $p}
+ event add <<xyz>> <Control-v> <Control-w> <Control-x>
+ event delete <<xyz>>
+ event info
+} -result {}
+test bind-19.10 {DeleteVirtualEvent procedure: owns many, delete 1} -body {
+ event delete <<xyz>>
+ event add <<xyz>> <Control-v> <Control-w> <Control-x>
+ event delete <<xyz>> <Control-w>
+ lsort [event info <<xyz>>]
+} -cleanup {
+ event delete <<xyz>>
+} -result {<Control-Key-v> <Control-Key-x>}
+test bind-19.11 {DeleteVirtualEvent procedure: owned by 1, only} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+ event delete <<xyz>>
+} -body {
+ event add <<xyz>> <Button-2>
+ bind .t.f <<xyz>> {lappend x %#}
+ event generate .t.f <Button-2> -serial 101
+ event generate .t.f <ButtonRelease-2>
+ event delete <<xyz>>
+ event generate .t.f <Button-2> -serial 102
+ event generate .t.f <ButtonRelease-2>
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {101}
+test bind-19.12 {DeleteVirtualEvent procedure: owned by 1, first in chain} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+ event delete <<xyz>>
+ event delete <<abc>>
+} -body {
+ event add <<abc>> <Control-Button-2>
+ event add <<xyz>> <Button-2>
+ bind .t.f <<xyz>> {lappend x xyz}
+ bind .t.f <<abc>> {lappend x abc}
+ event generate .t.f <Button-2>
+ event generate .t.f <ButtonRelease-2>
+ event generate .t.f <Control-Button-2>
+ event generate .t.f <Control-ButtonRelease-2>
+ event delete <<xyz>>
+ event generate .t.f <Button-2>
+ event generate .t.f <ButtonRelease-2>
+ event generate .t.f <Control-Button-2>
+ event generate .t.f <Control-ButtonRelease-2>
+ list $x [event info <<abc>>]
+} -cleanup {
+ destroy .t.f
+ event delete <<abc>>
+} -result {{xyz abc abc} <Control-Button-2>}
+test bind-19.13 {DeleteVirtualEvent procedure: owned by 1, second in chain} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+ event delete <<def>>
+ event delete <<xyz>>
+ event delete <<abc>>
+} -body {
+ event add <<def>> <Shift-Button-2>
+ event add <<xyz>> <Button-2>
+ event add <<abc>> <Control-Button-2>
+ bind .t.f <<xyz>> {lappend x xyz}
+ bind .t.f <<abc>> {lappend x abc}
+ bind .t.f <<def>> {lappend x def}
+ event generate .t.f <Button-2>
+ event generate .t.f <ButtonRelease-2>
+ event generate .t.f <Control-Button-2>
+ event generate .t.f <Control-ButtonRelease-2>
+ event generate .t.f <Shift-Button-2>
+ event generate .t.f <Shift-ButtonRelease-2>
+ event delete <<xyz>>
+ event generate .t.f <Button-2>
+ event generate .t.f <Control-Button-2>
+ event generate .t.f <Shift-Button-2>
+ event generate .t.f <ButtonRelease-2>
+ event generate .t.f <Control-ButtonRelease-2>
+ event generate .t.f <Shift-ButtonRelease-2>
+ list $x [event info <<def>>] [event info <<xyz>>] [event info <<abc>>]
+} -cleanup {
+ destroy .t.f
+ event delete <<abc>>
+ event delete <<def>>
+} -result {{xyz abc def abc def} <Shift-Button-2> {} <Control-Button-2>}
+test bind-19.14 {DeleteVirtualEvent procedure: owned by 1, last in chain} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+ event delete <<def>>
+ event delete <<xyz>>
+ event delete <<abc>>
+} -body {
+ event add <<xyz>> <Button-2>
+ event add <<abc>> <Control-Button-2>
+ event add <<def>> <Shift-Button-2>
+ bind .t.f <<xyz>> {lappend x xyz}
+ bind .t.f <<abc>> {lappend x abc}
+ bind .t.f <<def>> {lappend x def}
+ event generate .t.f <Button-2>
+ event generate .t.f <ButtonRelease-2>
+ event generate .t.f <Control-Button-2>
+ event generate .t.f <Control-ButtonRelease-2>
+ event generate .t.f <Shift-Button-2>
+ event generate .t.f <Shift-ButtonRelease-2>
+ event delete <<xyz>>
+ event generate .t.f <Button-2>
+ event generate .t.f <ButtonRelease-2>
+ event generate .t.f <Control-Button-2>
+ event generate .t.f <Control-ButtonRelease-2>
+ event generate .t.f <Shift-Button-2>
+ event generate .t.f <Shift-ButtonRelease-2>
+ list $x [event info <<xyz>>] [event info <<abc>>] [event info <<def>>]
+} -cleanup {
+ destroy .t.f
+ event delete <<def>>
+ event delete <<abc>>
+} -result {{xyz abc def abc def} {} <Control-Button-2> <Shift-Button-2>}
+test bind-19.15 {DeleteVirtualEvent procedure: owned by many, first} -setup {
+ pack [frame .t.f -class Test -width 150 -height 100]
+ pack [frame .t.g -class Test -width 150 -height 100]
+ pack [frame .t.h -class Test -width 150 -height 100]
+ focus -force .t.f
+ update
+ set x {}
+ event delete <<def>>
+ event delete <<xyz>>
+ event delete <<abc>>
+} -body {
+ event add <<xyz>> <Button-2>
+ event add <<abc>> <Button-2>
+ event add <<def>> <Button-2>
+ bind .t.f <<xyz>> {lappend x xyz}
+ bind .t.g <<abc>> {lappend x abc}
+ bind .t.h <<def>> {lappend x def}
+ event generate .t.f <Button-2>
+ event generate .t.f <ButtonRelease-2>
+ event generate .t.g <Button-2>
+ event generate .t.g <ButtonRelease-2>
+ event generate .t.h <Button-2>
+ event generate .t.h <ButtonRelease-2>
+ event delete <<xyz>>
+ event generate .t.f <Button-2>
+ event generate .t.f <ButtonRelease-2>
+ event generate .t.g <Button-2>
+ event generate .t.g <ButtonRelease-2>
+ event generate .t.h <Button-2>
+ event generate .t.h <ButtonRelease-2>
+ list $x [event info <<xyz>>] [event info <<abc>>] [event info <<def>>]
+} -cleanup {
+ destroy .t.f .t.g .t.h
+ event delete <<def>>
+ event delete <<abc>>
+} -result {{xyz abc def abc def} {} <Button-2> <Button-2>}
+test bind-19.16 {DeleteVirtualEvent procedure: owned by many, middle} -setup {
+ pack [frame .t.f -class Test -width 150 -height 100]
+ pack [frame .t.g -class Test -width 150 -height 100]
+ pack [frame .t.h -class Test -width 150 -height 100]
+ focus -force .t.f
+ update
+ set x {}
+ event delete <<def>>
+ event delete <<xyz>>
+ event delete <<abc>>
+} -body {
+ event add <<xyz>> <Button-2>
+ event add <<abc>> <Button-2>
+ event add <<def>> <Button-2>
+ bind .t.f <<xyz>> {lappend x xyz}
+ bind .t.g <<abc>> {lappend x abc}
+ bind .t.h <<def>> {lappend x def}
+ event generate .t.f <Button-2>
+ event generate .t.f <ButtonRelease-2>
+ event generate .t.g <Button-2>
+ event generate .t.g <ButtonRelease-2>
+ event generate .t.h <Button-2>
+ event generate .t.h <ButtonRelease-2>
+ event delete <<abc>>
+ event generate .t.f <Button-2>
+ event generate .t.f <ButtonRelease-2>
+ event generate .t.g <Button-2>
+ event generate .t.g <ButtonRelease-2>
+ event generate .t.h <Button-2>
+ event generate .t.h <ButtonRelease-2>
+ list $x [event info <<xyz>>] [event info <<abc>>] [event info <<def>>]
+} -cleanup {
+ destroy .t.f .t.g .t.h
+ event delete <<def>>
+ event delete <<xyz>>
+} -result {{xyz abc def xyz def} <Button-2> {} <Button-2>}
+test bind-19.17 {DeleteVirtualEvent procedure: owned by many, last} -setup {
+ pack [frame .t.f -class Test -width 150 -height 100]
+ pack [frame .t.g -class Test -width 150 -height 100]
+ pack [frame .t.h -class Test -width 150 -height 100]
+ focus -force .t.f
+ update
+ set x {}
+ event delete <<def>>
+ event delete <<xyz>>
+ event delete <<abc>>
+} -body {
+ event add <<xyz>> <Button-2>
+ event add <<abc>> <Button-2>
+ event add <<def>> <Button-2>
+ bind .t.f <<xyz>> {lappend x xyz}
+ bind .t.g <<abc>> {lappend x abc}
+ bind .t.h <<def>> {lappend x def}
+ event generate .t.f <Button-2>
+ event generate .t.f <ButtonRelease-2>
+ event generate .t.g <Button-2>
+ event generate .t.g <ButtonRelease-2>
+ event generate .t.h <Button-2>
+ event generate .t.h <ButtonRelease-2>
+ event delete <<def>>
+ event generate .t.f <Button-2>
+ event generate .t.f <ButtonRelease-2>
+ event generate .t.g <Button-2>
+ event generate .t.g <ButtonRelease-2>
+ event generate .t.h <Button-2>
+ event generate .t.h <ButtonRelease-2>
+ list $x [event info <<xyz>>] [event info <<abc>>] [event info <<def>>]
+} -cleanup {
+ destroy .t.f .t.g .t.h
+ event delete <<xyz>>
+ event delete <<abc>>
+} -result {{xyz abc def xyz abc} <Button-2> <Button-2> {}}
+
+
+test bind-20.1 {GetVirtualEvent procedure: GetVirtualEventUid} -body {
+ event info asd
+} -returnCodes error -result {virtual event "asd" is badly formed}
+test bind-20.2 {GetVirtualEvent procedure: non-existent event} -body {
+ event delete <<asd>>
+ event info <<asd>>
+} -result {}
+test bind-20.3 {GetVirtualEvent procedure: owns 1} -setup {
+ event delete <<xyz>>
+} -body {
+ event add <<xyz>> <Control-Key-v>
+ event info <<xyz>>
+} -cleanup {
+ event delete <<xyz>>
+} -result {<Control-Key-v>}
+test bind-20.4 {GetVirtualEvent procedure: owns many} -setup {
+ event delete <<xyz>>
+} -body {
+ event add <<xyz>> <Control-v> <Button-2> spack
+ event info <<xyz>>
+} -cleanup {
+ event delete <<xyz>>
+} -result {<Control-Key-v> <Button-2> spack}
+
+
+test bind-21.1 {GetAllVirtualEvents procedure: no events} -body {
+ foreach p [event info] {event delete $p}
+ event info
+} -result {}
+test bind-21.2 {GetAllVirtualEvents procedure: 1 event} -body {
+ foreach p [event info] {event delete $p}
+ event add <<xyz>> <Control-v>
+ event info
+} -cleanup {
+ event delete <<xyz>>
+} -result {<<xyz>>}
+test bind-21.3 {GetAllVirtualEvents procedure: many events} -body {
+ foreach p [event info] {event delete $p}
+ event add <<xyz>> <Control-v>
+ event add <<xyz>> <Button-2>
+ event add <<abc>> <Control-v>
+ event add <<def>> <Key-F6>
+ lsort [event info]
+} -cleanup {
+ event delete <<xyz>>
+ event delete <<abc>>
+ event delete <<def>>
+} -result {<<abc>> <<def>> <<xyz>>}
+
+test bind-22.1 {HandleEventGenerate} -setup {
+ destroy .xyz
+} -body {
+ event generate .xyz <Control-v>
+} -returnCodes error -result {bad window path name ".xyz"}
+test bind-22.2 {HandleEventGenerate} -body {
+ event generate zzz <Control-v>
+} -returnCodes error -result {bad window name/identifier "zzz"}
+test bind-22.3 {HandleEventGenerate} -body {
+ event generate 47 <Control-v>
+} -returnCodes error -result {bad window name/identifier "47"}
+test bind-22.4 {HandleEventGenerate} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button> {set x "%s %b"}
+ event generate [winfo id .t.f] <Control-Button-1> -state 260
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {260 1}
+test bind-22.5 {HandleEventGenerate} -body {
+ event generate . <xyz>
+} -returnCodes error -result {bad event type or keysym "xyz"}
+test bind-22.6 {HandleEventGenerate} -body {
+ event generate . <Double-Button-1>
+} -returnCodes error -result {Double or Triple modifier not allowed}
+test bind-22.7 {HandleEventGenerate} -body {
+ event generate . xyz
+} -returnCodes error -result {only one event specification allowed}
+test bind-22.8 {HandleEventGenerate} -body {
+ event generate . <Button> -button
+} -returnCodes error -result {value for "-button" missing}
+test bind-22.9 {HandleEventGenerate} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button> {set x "%s %b"}
+ event generate .t.f <ButtonRelease-1>
+ event generate .t.f <ButtonRelease-2>
+ event generate .t.f <ButtonRelease-3>
+ event generate .t.f <Control-Button-1>
+ event generate .t.f <Control-ButtonRelease-1>
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {4 1}
+test bind-22.10 {HandleEventGenerate} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> {set x "%s %K"}
+ event generate .t.f <Control-Key-space>
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {4 space}
+test bind-22.11 {HandleEventGenerate} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <<Paste>> {set x "%s"}
+ event generate .t.f <<Paste>> -state 1
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+test bind-22.12 {HandleEventGenerate} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Motion> {set x "%s"}
+ event generate .t.f <Control-Motion>
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {4}
+test bind-22.13 {HandleEventGenerate} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button> {lappend x %#}
+ event generate .t.f <Button> -when now -serial 100
+ event generate .t.f <ButtonRelease> -when now
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {100}
+test bind-22.14 {HandleEventGenerate} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button> {lappend x %#}
+ event generate .t.f <Button> -when head -serial 100
+ event generate .t.f <Button> -when head -serial 101
+ event generate .t.f <Button> -when head -serial 102
+ event generate .t.f <ButtonRelease> -when tail
+ lappend x foo
+ update
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {foo 102 101 100}
+test bind-22.15 {HandleEventGenerate} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button> {lappend x %#}
+ event generate .t.f <Button> -when head -serial 99
+ event generate .t.f <Button> -when mark -serial 100
+ event generate .t.f <Button> -when mark -serial 101
+ event generate .t.f <Button> -when mark -serial 102
+ event generate .t.f <ButtonRelease> -when tail
+ lappend x foo
+ update
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {foo 100 101 102 99}
+test bind-22.16 {HandleEventGenerate} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button> {lappend x %#}
+ event generate .t.f <Button> -when head -serial 99
+ event generate .t.f <Button> -when tail -serial 100
+ event generate .t.f <Button> -when tail -serial 101
+ event generate .t.f <Button> -when tail -serial 102
+ event generate .t.f <ButtonRelease> -when tail
+ lappend x foo
+ update
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {foo 99 100 101 102}
+test bind-22.17 {HandleEventGenerate} -body {
+ event generate . <Button> -when xyz
+} -returnCodes error -result {bad -when value "xyz": must be now, head, mark, or tail}
+test bind-22.18 {HandleEventGenerate} -body {
+ # Bug 411307
+ event generate . <a> -root 98765
+} -returnCodes error -result {bad window name/identifier "98765"}
+
+test bind-22.19 {HandleEventGenerate: options <Configure> -above .xyz} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Configure> "lappend x %a"
+ event generate .t.f <Configure> -above .xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {bad window path name ".xyz"}
+test bind-22.20 {HandleEventGenerate: options <Configure> -above .t} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Configure> "lappend x %a"
+ event generate .t.f <Configure> -above .t
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result [winfo id .t]
+test bind-22.21 {HandleEventGenerate: options <Configure> -above xyz} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Configure> "lappend x %a"
+ event generate .t.f <Configure> -above xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {bad window name/identifier "xyz"}
+test bind-22.22 {HandleEventGenerate: options <Configure> -above [winfo id .t]} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Configure> "lappend x %a"
+ event generate .t.f <Configure> -above [winfo id .t]
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result [winfo id .t]
+
+test bind-22.23 {HandleEventGenerate: options <Key> -above .} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %b"
+ event generate .t.f <Key> -above .
+ return $x
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {<Key> event doesn't accept "-above" option}
+
+test bind-22.24 {HandleEventGenerate: options <Configure> -borderwidth xyz} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Configure> "lappend x %B"
+ event generate .t.f <Configure> -borderwidth xyz
+ return $x
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {bad screen distance "xyz"}
+
+test bind-22.25 {HandleEventGenerate: options <Configure> -borderwidth 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Configure> "lappend x %B"
+ event generate .t.f <Configure> -borderwidth 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.26 {HandleEventGenerate: options <Key> -borderwidth 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %k"
+ event generate .t.f <Key> -borderwidth 2i
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {<Key> event doesn't accept "-borderwidth" option}
+
+test bind-22.27 {HandleEventGenerate: options <Button> -button xyz} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button> "lappend x %b"
+ event generate .t.f <Button> -button xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {expected integer but got "xyz"}
+
+test bind-22.28 {HandleEventGenerate: options <Button> -button 1} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button> "lappend x %b"
+ event generate .t.f <Button> -button 1
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result 1
+
+test bind-22.29 {HandleEventGenerate: options <ButtonRelease> -button 1} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <ButtonRelease> "lappend x %b"
+ event generate .t.f <ButtonRelease> -button 1
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result 1
+
+test bind-22.30 {HandleEventGenerate: options <Key> -button 1} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %k"
+ event generate .t.f <Key> -button 1
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {<Key> event doesn't accept "-button" option}
+
+test bind-22.31 {HandleEventGenerate: options <Expose> -count xyz} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Expose> "lappend x %c"
+ event generate .t.f <Expose> -count xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {expected integer but got "xyz"}
+
+test bind-22.32 {HandleEventGenerate: options <Expose> -count 20} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Expose> "lappend x %c"
+ event generate .t.f <Expose> -count 20
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {20}
+
+test bind-22.33 {HandleEventGenerate: options <Key> -count 20} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %b"
+ event generate .t.f <Key> -count 20
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {<Key> event doesn't accept "-count" option}
+
+test bind-22.34 {HandleEventGenerate: options <Enter> -detail xyz} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Enter> "lappend x %d"
+ event generate .t.f <Enter> -detail xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {bad -detail value "xyz": must be NotifyAncestor, NotifyVirtual, NotifyInferior, NotifyNonlinear, NotifyNonlinearVirtual, NotifyPointer, NotifyPointerRoot, or NotifyDetailNone}
+
+test bind-22.35 {HandleEventGenerate: options <FocusIn> -detail NotifyVirtual} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <FocusIn> "lappend x FocusIn %d"
+ event generate .t.f <FocusIn> -detail NotifyVirtual
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {FocusIn NotifyVirtual}
+
+test bind-22.35.1 {HandleEventGenerate: options <FocusOut> -detail NotifyVirtual} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <FocusOut> "lappend x FocusOut %d"
+ event generate .t.f <FocusOut> -detail NotifyVirtual
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {FocusOut NotifyVirtual}
+
+test bind-22.36 {HandleEventGenerate: options <Enter> -detail NotifyVirtual} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Enter> "lappend x %d"
+ event generate .t.f <Enter> -detail NotifyVirtual
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {NotifyVirtual}
+
+test bind-22.37 {HandleEventGenerate: options <Key> -detail NotifyVirtual} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %k"
+ event generate .t.f <Key> -detail NotifyVirtual
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {<Key> event doesn't accept "-detail" option}
+
+test bind-22.38 {HandleEventGenerate: options <Enter> -focus xyz} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Enter> "lappend x %f"
+ event generate .t.f <Enter> -focus xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {expected boolean value but got "xyz"}
+
+test bind-22.39 {HandleEventGenerate: options <Enter> -focus 1} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Enter> "lappend x %f"
+ event generate .t.f <Enter> -focus 1
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.40 {HandleEventGenerate: options <Key> -focus 1} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %k"
+ event generate .t.f <Key> -focus 1
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {<Key> event doesn't accept "-focus" option}
+
+test bind-22.41 {HandleEventGenerate: options <Expose> -height xyz} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Expose> "lappend x %h"
+ event generate .t.f <Expose> -height xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {bad screen distance "xyz"}
+
+test bind-22.42 {HandleEventGenerate: options <Expose> -height 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Expose> "lappend x %h"
+ event generate .t.f <Expose> -height 2i
+ expr {$x eq [winfo pixels .t.f 2i]}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.43 {HandleEventGenerate: options <Configure> -height 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Configure> "lappend x %h"
+ event generate .t.f <Configure> -height 2i
+ expr {$x eq [winfo pixels .t.f 2i]}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.44 {HandleEventGenerate: options <Key> -height 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %k"
+ event generate .t.f <Key> -height 2i
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {<Key> event doesn't accept "-height" option}
+
+test bind-22.45 {HandleEventGenerate: options <Key> -keycode xyz} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %k"
+ event generate .t.f <Key> -keycode xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {expected integer but got "xyz"}
+
+test bind-22.46 {HandleEventGenerate: options <Key> -keycode 20} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %k"
+ event generate .t.f <Key> -keycode 20
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {20}
+
+test bind-22.47 {HandleEventGenerate: options <Button> -keycode 20} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button> "lappend x %b"
+ event generate .t.f <Button> -keycode 20
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {<Button> event doesn't accept "-keycode" option}
+
+test bind-22.48 {HandleEventGenerate: options <Key> -keysym xyz} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %K"
+ event generate .t.f <Key> -keysym xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {unknown keysym "xyz"}
+
+test bind-22.49 {HandleEventGenerate: options <Key> -keysym space} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %K"
+ event generate .t.f <Key> -keysym space
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {space}
+
+test bind-22.50 {HandleEventGenerate: options <Button> -keysym space} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button> "lappend x %b"
+ event generate .t.f <Button> -keysym space
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {<Button> event doesn't accept "-keysym" option}
+
+test bind-22.51 {HandleEventGenerate: options <Enter> -mode xyz} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Enter> "lappend x %m"
+ event generate .t.f <Enter> -mode xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {bad -mode value "xyz": must be NotifyNormal, NotifyGrab, NotifyUngrab, or NotifyWhileGrabbed}
+
+test bind-22.52 {HandleEventGenerate: options <Enter> -mode NotifyNormal} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Enter> "lappend x %m"
+ event generate .t.f <Enter> -mode NotifyNormal
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {NotifyNormal}
+
+test bind-22.53 {HandleEventGenerate: options <FocusIn> -mode NotifyNormal} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <FocusIn> "lappend x %m"
+ event generate .t.f <FocusIn> -mode NotifyNormal
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {NotifyNormal}
+
+test bind-22.54 {HandleEventGenerate: options <Key> -mode NotifyNormal} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %k"
+ event generate .t.f <Key> -mode NotifyNormal
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {<Key> event doesn't accept "-mode" option}
+test bind-22.55 {HandleEventGenerate: options <Map> -override xyz} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Map> "lappend x %o"
+ event generate .t.f <Map> -override xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {expected boolean value but got "xyz"}
+
+test bind-22.56 {HandleEventGenerate: options <Map> -override 1} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Map> "lappend x %o"
+ event generate .t.f <Map> -override 1
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.57 {HandleEventGenerate: options <Reparent> -override 1} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Reparent> "lappend x %o"
+ event generate .t.f <Reparent> -override 1
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.58 {HandleEventGenerate: options <Configure> -override 1} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Configure> "lappend x %o"
+ event generate .t.f <Configure> -override 1
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.59 {HandleEventGenerate: options <Key> -override 1} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %k"
+ event generate .t.f <Key> -override 1
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {<Key> event doesn't accept "-override" option}
+
+test bind-22.60 {HandleEventGenerate: options <Circulate> -place xyz} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Circulate> "lappend x %p"
+ event generate .t.f <Circulate> -place xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {bad -place value "xyz": must be PlaceOnTop, or PlaceOnBottom}
+
+test bind-22.61 {HandleEventGenerate: options <Circulate> -place PlaceOnTop} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Circulate> "lappend x %p"
+ event generate .t.f <Circulate> -place PlaceOnTop
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {PlaceOnTop}
+
+test bind-22.62 {HandleEventGenerate: options <Key> -place PlaceOnTop} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %k"
+ event generate .t.f <Key> -place PlaceOnTop
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {<Key> event doesn't accept "-place" option}
+
+test bind-22.63 {HandleEventGenerate: options <Key> -root .xyz} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %R"
+ event generate .t.f <Key> -root .xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {bad window path name ".xyz"}
+
+test bind-22.64 {HandleEventGenerate: options <Key> -root .t} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %R"
+ event generate .t.f <Key> -root .t
+ expr {[winfo id .t] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.65 {HandleEventGenerate: options <Key> -root xyz} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %R"
+ event generate .t.f <Key> -root xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {bad window name/identifier "xyz"}
+
+test bind-22.66 {HandleEventGenerate: options <Key> -root [winfo id .t]} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %R"
+ event generate .t.f <Key> -root [winfo id .t]
+ expr {[winfo id .t] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.67 {HandleEventGenerate: options <Button> -root .t} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button> "lappend x %R"
+ event generate .t.f <Button> -root .t
+ expr {[winfo id .t] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.68 {HandleEventGenerate: options <ButtonRelease> -root .t} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <ButtonRelease> "lappend x %R"
+ event generate .t.f <ButtonRelease> -root .t
+ expr {[winfo id .t] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.69 {HandleEventGenerate: options <Motion> -root .t} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Motion> "lappend x %R"
+ event generate .t.f <Motion> -root .t
+ expr {[winfo id .t] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.70 {HandleEventGenerate: options <<Paste>> -root .t} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <<Paste>> "lappend x %R"
+ event generate .t.f <<Paste>> -root .t
+ expr {[winfo id .t] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.71 {HandleEventGenerate: options <Enter> -root .t} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Enter> "lappend x %R"
+ event generate .t.f <Enter> -root .t
+ expr {[winfo id .t] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.72 {HandleEventGenerate: options <Configure> -root .t} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Configure> "lappend x %R"
+ event generate .t.f <Configure> -root .t
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {<Configure> event doesn't accept "-root" option}
+
+test bind-22.73 {HandleEventGenerate: options <Key> -rootx xyz} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %X"
+ event generate .t.f <Key> -rootx xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {bad screen distance "xyz"}
+
+test bind-22.74 {HandleEventGenerate: options <Key> -rootx 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %X"
+ event generate .t.f <Key> -rootx 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.75 {HandleEventGenerate: options <Button> -rootx 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button> "lappend x %X"
+ event generate .t.f <Button> -rootx 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.76 {HandleEventGenerate: options <ButtonRelease> -rootx 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <ButtonRelease> "lappend x %X"
+ event generate .t.f <ButtonRelease> -rootx 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.77 {HandleEventGenerate: options <Motion> -rootx 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Motion> "lappend x %X"
+ event generate .t.f <Motion> -rootx 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.78 {HandleEventGenerate: options <<Paste>> -rootx 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <<Paste>> "lappend x %X"
+ event generate .t.f <<Paste>> -rootx 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.79 {HandleEventGenerate: options <Enter> -rootx 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Enter> "lappend x %X"
+ event generate .t.f <Enter> -rootx 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.80 {HandleEventGenerate: options <Configure> -rootx 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Configure> "lappend x %X"
+ event generate .t.f <Configure> -rootx 2i
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {<Configure> event doesn't accept "-rootx" option}
+
+test bind-22.81 {HandleEventGenerate: options <Key> -rooty xyz} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %Y"
+ event generate .t.f <Key> -rooty xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {bad screen distance "xyz"}
+
+test bind-22.82 {HandleEventGenerate: options <Key> -rooty 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %Y"
+ event generate .t.f <Key> -rooty 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.83 {HandleEventGenerate: options <Button> -rooty 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button> "lappend x %Y"
+ event generate .t.f <Button> -rooty 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.84 {HandleEventGenerate: options <ButtonRelease> -rooty 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <ButtonRelease> "lappend x %Y"
+ event generate .t.f <ButtonRelease> -rooty 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.85 {HandleEventGenerate: options <Motion> -rooty 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Motion> "lappend x %Y"
+ event generate .t.f <Motion> -rooty 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.86 {HandleEventGenerate: options <<Paste>> -rooty 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <<Paste>> "lappend x %Y"
+ event generate .t.f <<Paste>> -rooty 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.87 {HandleEventGenerate: options <Enter> -rooty 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Enter> "lappend x %Y"
+ event generate .t.f <Enter> -rooty 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.88 {HandleEventGenerate: options <Configure> -rooty 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Configure> "lappend x %Y"
+ event generate .t.f <Configure> -rooty 2i
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {<Configure> event doesn't accept "-rooty" option}
+
+test bind-22.89 {HandleEventGenerate: options <Key> -sendevent xyz} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %E"
+ event generate .t.f <Key> -sendevent xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {expected boolean value but got "xyz"}
+
+test bind-22.90 {HandleEventGenerate: options <Key> -sendevent 1} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %E"
+ event generate .t.f <Key> -sendevent 1
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.91 {HandleEventGenerate: options <Key> -sendevent yes} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %E"
+ event generate .t.f <Key> -sendevent yes
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.92 {HandleEventGenerate: options <Key> -sendevent 43} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %E"
+ event generate .t.f <Key> -sendevent 43
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {43}
+
+test bind-22.93 {HandleEventGenerate: options <Key> -serial xyz} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %#"
+ event generate .t.f <Key> -serial xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {expected integer but got "xyz"}
+
+test bind-22.94 {HandleEventGenerate: options <Key> -serial 100} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %#"
+ event generate .t.f <Key> -serial 100
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {100}
+
+test bind-22.95 {HandleEventGenerate: options <Key> -state xyz} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %s"
+ event generate .t.f <Key> -state xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {expected integer but got "xyz"}
+
+test bind-22.96 {HandleEventGenerate: options <Key> -state 1} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %s"
+ event generate .t.f <Key> -state 1
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.97 {HandleEventGenerate: options <Button> -state 1025} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button> "lappend x %s"
+ event generate .t.f <Button> -state 1025
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1025}
+
+test bind-22.98 {HandleEventGenerate: options <ButtonRelease> -state 1025} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <ButtonRelease> "lappend x %s"
+ event generate .t.f <ButtonRelease> -state 1025
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1025}
+
+test bind-22.99 {HandleEventGenerate: options <Motion> -state 1} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Motion> "lappend x %s"
+ event generate .t.f <Motion> -state 1
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.100 {HandleEventGenerate: options <<Paste>> -state 1} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <<Paste>> "lappend x %s"
+ event generate .t.f <<Paste>> -state 1
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.101 {HandleEventGenerate: options <Enter> -state 1} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Enter> "lappend x %s"
+ event generate .t.f <Enter> -state 1
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.102 {HandleEventGenerate: options <Visibility> -state xyz} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Visibility> "lappend x %s"
+ event generate .t.f <Visibility> -state xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {bad -state value "xyz": must be VisibilityUnobscured, VisibilityPartiallyObscured, or VisibilityFullyObscured}
+
+test bind-22.103 {HandleEventGenerate: options <Visibility> -state VisibilityUnobscured} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Visibility> "lappend x %s"
+ event generate .t.f <Visibility> -state VisibilityUnobscured
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {VisibilityUnobscured}
+
+test bind-22.104 {HandleEventGenerate: options <Configure> -state xyz} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Configure> "lappend x %s"
+ event generate .t.f <Configure> -state xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {<Configure> event doesn't accept "-state" option}
+
+test bind-22.105 {HandleEventGenerate: options <Key> -subwindow .xyz} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %S"
+ event generate .t.f <Key> -subwindow .xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {bad window path name ".xyz"}
+
+test bind-22.106 {HandleEventGenerate: options <Key> -subwindow .t} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %S"
+ event generate .t.f <Key> -subwindow .t
+ expr {[winfo id .t] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.107 {HandleEventGenerate: options <Key> -subwindow xyz} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %S"
+ event generate .t.f <Key> -subwindow xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {bad window name/identifier "xyz"}
+
+test bind-22.108 {HandleEventGenerate: options <Key> -subwindow [winfo id .t]} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %S"
+ event generate .t.f <Key> -subwindow [winfo id .t]
+ expr {[winfo id .t] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.109 {HandleEventGenerate: options <Button> -subwindow .t} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button> "lappend x %S"
+ event generate .t.f <Button> -subwindow .t
+ expr {[winfo id .t] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.110 {HandleEventGenerate: options <ButtonRelease> -subwindow .t} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <ButtonRelease> "lappend x %S"
+ event generate .t.f <ButtonRelease> -subwindow .t
+ expr {[winfo id .t] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.111 {HandleEventGenerate: options <Motion> -subwindow .t} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Motion> "lappend x %S"
+ event generate .t.f <Motion> -subwindow .t
+ expr {[winfo id .t] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.112 {HandleEventGenerate: options <<Paste>> -subwindow .t} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <<Paste>> "lappend x %S"
+ event generate .t.f <<Paste>> -subwindow .t
+ expr {[winfo id .t] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.113 {HandleEventGenerate: options <Enter> -subwindow .t} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Enter> "lappend x %S"
+ event generate .t.f <Enter> -subwindow .t
+ expr {[winfo id .t] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.114 {HandleEventGenerate: options <Configure> -subwindow .t} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Configure> "lappend x %S"
+ event generate .t.f <Configure> -subwindow .t
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {<Configure> event doesn't accept "-subwindow" option}
+
+test bind-22.115 {HandleEventGenerate: options <Key> -time xyz} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %t"
+ event generate .t.f <Key> -time xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {expected integer but got "xyz"}
+
+test bind-22.116 {HandleEventGenerate: options <Key> -time 100} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %t"
+ event generate .t.f <Key> -time 100
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {100}
+
+test bind-22.117 {HandleEventGenerate: options <Button> -time 100} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button> "lappend x %t"
+ event generate .t.f <Button> -time 100
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {100}
+
+test bind-22.118 {HandleEventGenerate: options <ButtonRelease> -time 100} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <ButtonRelease> "lappend x %t"
+ event generate .t.f <ButtonRelease> -time 100
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {100}
+
+test bind-22.119 {HandleEventGenerate: options <Motion> -time 100} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Motion> "lappend x %t"
+ event generate .t.f <Motion> -time 100
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {100}
+
+test bind-22.120 {HandleEventGenerate: options <<Paste>> -time 100} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <<Paste>> "lappend x %t"
+ event generate .t.f <<Paste>> -time 100
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {100}
+
+test bind-22.121 {HandleEventGenerate: options <Enter> -time 100} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Enter> "lappend x %t"
+ event generate .t.f <Enter> -time 100
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {100}
+
+test bind-22.122 {HandleEventGenerate: options <Property> -time 100} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Property> "lappend x %t"
+ event generate .t.f <Property> -time 100
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {100}
+
+test bind-22.123 {HandleEventGenerate: options <Configure> -time 100} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Configure> "lappend x %t"
+ event generate .t.f <Configure> -time 100
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {<Configure> event doesn't accept "-time" option}
+
+test bind-22.124 {HandleEventGenerate: options <Expose> -width xyz} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Expose> "lappend x %w"
+ event generate .t.f <Expose> -width xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {bad screen distance "xyz"}
+
+test bind-22.125 {HandleEventGenerate: options <Expose> -width 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Expose> "lappend x %w"
+ event generate .t.f <Expose> -width 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.126 {HandleEventGenerate: options <Configure> -width 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Configure> "lappend x %w"
+ event generate .t.f <Configure> -width 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.127 {HandleEventGenerate: options <Key> -width 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %k"
+ event generate .t.f <Key> -width 2i
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {<Key> event doesn't accept "-width" option}
+
+test bind-22.128 {HandleEventGenerate: options <Unmap> -window .xyz} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Unmap> "lappend x %W"
+ event generate .t.f <Unmap> -window .xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {bad window path name ".xyz"}
+
+test bind-22.129 {HandleEventGenerate: options <Unmap> -window .t.f} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Unmap> "lappend x %W"
+ event generate .t.f <Unmap> -window .t.f
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {.t.f}
+
+test bind-22.130 {HandleEventGenerate: options <Unmap> -window xyz} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Unmap> "lappend x %W"
+ event generate .t.f <Unmap> -window xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {bad window name/identifier "xyz"}
+
+test bind-22.131 {HandleEventGenerate: options <Unmap> -window [winfo id .t.f]} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Unmap> "lappend x %W"
+ event generate .t.f <Unmap> -window [winfo id .t.f]
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {.t.f}
+
+test bind-22.132 {HandleEventGenerate: options <Unmap> -window .t.f} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Unmap> "lappend x %W"
+ event generate .t.f <Unmap> -window .t.f
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {.t.f}
+
+test bind-22.133 {HandleEventGenerate: options <Map> -window .t.f} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Map> "lappend x %W"
+ event generate .t.f <Map> -window .t.f
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {.t.f}
+
+test bind-22.134 {HandleEventGenerate: options <Reparent> -window .t.f} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Reparent> "lappend x %W"
+ event generate .t.f <Reparent> -window .t.f
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {.t.f}
+
+test bind-22.135 {HandleEventGenerate: options <Configure> -window .t.f} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Configure> "lappend x %W"
+ event generate .t.f <Configure> -window .t.f
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {.t.f}
+
+test bind-22.136 {HandleEventGenerate: options <Gravity> -window .t.f} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Gravity> "lappend x %W"
+ event generate .t.f <Gravity> -window .t.f
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {.t.f}
+
+test bind-22.137 {HandleEventGenerate: options <Circulate> -window .t.f} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Circulate> "lappend x %W"
+ event generate .t.f <Circulate> -window .t.f
+ return $x
+} -cleanup {
+ destroy .t.f
+} -result {.t.f}
+
+test bind-22.138 {HandleEventGenerate: options <Key> -window .t.f} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %W"
+ event generate .t.f <Key> -window .t.f
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {<Key> event doesn't accept "-window" option}
+
+test bind-22.139 {HandleEventGenerate: options <Key> -x xyz} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %x"
+ event generate .t.f <Key> -x xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {bad screen distance "xyz"}
+
+test bind-22.140 {HandleEventGenerate: options <Key> -x 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %x"
+ event generate .t.f <Key> -x 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.141 {HandleEventGenerate: options <Button> -x 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button> "lappend x %x"
+ event generate .t.f <Button> -x 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.142 {HandleEventGenerate: options <ButtonRelease> -x 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <ButtonRelease> "lappend x %x"
+ event generate .t.f <ButtonRelease> -x 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.143 {HandleEventGenerate: options <Motion> -x 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Motion> "lappend x %x"
+ event generate .t.f <Motion> -x 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.144 {HandleEventGenerate: options <<Paste>> -x 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <<Paste>> "lappend x %x"
+ event generate .t.f <<Paste>> -x 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.145 {HandleEventGenerate: options <Enter> -x 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Enter> "lappend x %x"
+ event generate .t.f <Enter> -x 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.146 {HandleEventGenerate: options <Expose> -x 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Expose> "lappend x %x"
+ event generate .t.f <Expose> -x 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.147 {HandleEventGenerate: options <Configure> -x 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Configure> "lappend x %x"
+ event generate .t.f <Configure> -x 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.148 {HandleEventGenerate: options <Gravity> -x 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Gravity> "lappend x %x"
+ event generate .t.f <Gravity> -x 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.149 {HandleEventGenerate: options <Reparent> -x 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Reparent> "lappend x %x"
+ event generate .t.f <Reparent> -x 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.150 {HandleEventGenerate: options <Map> -x 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Map> "lappend x %x"
+ event generate .t.f <Map> -x 2i
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {<Map> event doesn't accept "-x" option}
+
+test bind-22.151 {HandleEventGenerate: options <Key> -y xyz} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %y"
+ event generate .t.f <Key> -y xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {bad screen distance "xyz"}
+
+test bind-22.152 {HandleEventGenerate: options <Key> -y 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %y"
+ event generate .t.f <Key> -y 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.153 {HandleEventGenerate: options <Button> -y 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button> "lappend x %y"
+ event generate .t.f <Button> -y 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.154 {HandleEventGenerate: options <ButtonRelease> -y 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <ButtonRelease> "lappend x %y"
+ event generate .t.f <ButtonRelease> -y 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.155 {HandleEventGenerate: options <Motion> -y 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Motion> "lappend x %y"
+ event generate .t.f <Motion> -y 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.156 {HandleEventGenerate: options <<Paste>> -y 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <<Paste>> "lappend x %y"
+ event generate .t.f <<Paste>> -y 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.157 {HandleEventGenerate: options <Enter> -y 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Enter> "lappend x %y"
+ event generate .t.f <Enter> -y 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.158 {HandleEventGenerate: options <Expose> -y 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Expose> "lappend x %y"
+ event generate .t.f <Expose> -y 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.159 {HandleEventGenerate: options <Configure> -y 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Configure> "lappend x %y"
+ event generate .t.f <Configure> -y 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.160 {HandleEventGenerate: options <Gravity> -y 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Gravity> "lappend x %y"
+ event generate .t.f <Gravity> -y 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.161 {HandleEventGenerate: options <Reparent> -y 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Reparent> "lappend x %y"
+ event generate .t.f <Reparent> -y 2i
+ expr {[winfo pixels .t.f 2i] eq $x}
+} -cleanup {
+ destroy .t.f
+} -result {1}
+
+test bind-22.162 {HandleEventGenerate: options <Map> -y 2i} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Map> "lappend x %y"
+ event generate .t.f <Map> -y 2i
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {<Map> event doesn't accept "-y" option}
+
+test bind-22.163 {HandleEventGenerate: options <Key> -xyz 1} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Key> "lappend x %k"
+ event generate .t.f <Key> -xyz 1
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {bad option "-xyz": must be -when, -above, -borderwidth, -button, -count, -data, -delta, -detail, -focus, -height, -keycode, -keysym, -mode, -override, -place, -root, -rootx, -rooty, -sendevent, -serial, -state, -subwindow, -time, -warp, -width, -window, -x, or -y}
+# Note that the -data option is tested in bind-32.* because it has
+# more demanding requirements in memory handling
+
+
+test bind-23.1 {GetVirtualEventUid procedure} -body {
+ event info <<asd
+} -returnCodes error -result {virtual event "<<asd" is badly formed}
+test bind-23.2 {GetVirtualEventUid procedure} -body {
+ event info <<>>
+} -returnCodes error -result {virtual event "<<>>" is badly formed}
+test bind-23.3 {GetVirtualEventUid procedure} -body {
+ event info <<asd>
+} -returnCodes error -result {virtual event "<<asd>" is badly formed}
+test bind-23.4 {GetVirtualEventUid procedure} -setup {
+ event delete <<asd>>
+} -body {
+ event info <<asd>>
+} -result {}
+
+
+test bind-24.1 {FindSequence procedure: no event} -body {
+ bind .t {} test
+} -returnCodes error -result {no events specified in binding}
+test bind-24.2 {FindSequence procedure: bad event} -body {
+ bind .t <xyz> test
+} -returnCodes error -result {bad event type or keysym "xyz"}
+test bind-24.3 {FindSequence procedure: virtual allowed} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <<Paste>> test
+} -cleanup {
+ destroy .t.f
+} -result {}
+test bind-24.4 {FindSequence procedure: virtual not allowed} -body {
+ event add <<Paste>> <<Alive>>
+} -returnCodes error -result {virtual event not allowed in definition of another virtual event}
+test bind-24.5 {FindSequence procedure, multiple bindings} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <1> {lappend x single}
+ bind .t.f <Double-1> {lappend x double}
+ bind .t.f <Triple-1> {lappend x triple}
+ bind .t.f <Quadruple-1> {lappend x quadruple}
+ set x press
+ event generate .t.f <Button-1>
+ event generate .t.f <ButtonRelease-1>
+ lappend x press
+ event generate .t.f <Button-1>
+ event generate .t.f <ButtonRelease-1>
+ lappend x press
+ event generate .t.f <Button-1>
+ event generate .t.f <ButtonRelease-1>
+ lappend x press
+ event generate .t.f <Button-1>
+ event generate .t.f <ButtonRelease-1>
+ lappend x press
+ event generate .t.f <Button-1>
+ event generate .t.f <ButtonRelease-1>
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {press single press double press triple press quadruple press quadruple}
+test bind-24.6 {FindSequence procedure: virtual composed} -body {
+ bind .t <Control-b><<Paste>> "puts hi"
+} -returnCodes error -result {virtual events may not be composed}
+test bind-24.7 {FindSequence procedure: new pattern sequence} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button-1><Button-2> {lappend x 1-2}
+ event generate .t.f <Button-1>
+ event generate .t.f <ButtonRelease-1>
+ event generate .t.f <Button-2>
+ event generate .t.f <ButtonRelease-2>
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {1-2}
+test bind-24.8 {FindSequence procedure: similar pattern sequence} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button-1><Button-2> {lappend x 1-2}
+ bind .t.f <Button-2> {lappend x 2}
+ event generate .t.f <Button-3>
+ event generate .t.f <Button-2>
+ event generate .t.f <ButtonRelease-2>
+ event generate .t.f <Button-1>
+ event generate .t.f <ButtonRelease-1>
+ event generate .t.f <Button-2>
+ event generate .t.f <ButtonRelease-2>
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {2 1-2}
+test bind-24.9 {FindSequence procedure: similar pattern sequence} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button-1><Button-2> {lappend x 1-2}
+ bind .t.f <Button-2><Button-2> {lappend x 2-2}
+ event generate .t.f <Button-3>
+ event generate .t.f <Button-2>
+ event generate .t.f <ButtonRelease-2>
+ event generate .t.f <Button-2>
+ event generate .t.f <ButtonRelease-2>
+ event generate .t.f <Button-1>
+ event generate .t.f <ButtonRelease-1>
+ event generate .t.f <Button-2>
+ event generate .t.f <ButtonRelease-2>
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {2-2 1-2}
+test bind-24.10 {FindSequence procedure: similar pattern sequence} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <Button-2><Button-2> {lappend x 2-2}
+ bind .t.f <Double-Button-2> {lappend x d-2}
+ event generate .t.f <Button-3>
+ event generate .t.f <Button-2>
+ event generate .t.f <ButtonRelease-2>
+ event generate .t.f <Button-2>
+ event generate .t.f <ButtonRelease-2>
+ event generate .t.f <Button-1>
+ event generate .t.f <ButtonRelease-1>
+ event generate .t.f <Button-2> -x 100
+ event generate .t.f <ButtonRelease-2>
+ event generate .t.f <Button-2> -x 200
+ event generate .t.f <ButtonRelease-2>
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {d-2 2-2}
+test bind-24.11 {FindSequence procedure: new sequence, don't create} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Button-2>
+} -cleanup {
+ destroy .t.f
+} -result {}
+test bind-24.12 {FindSequence procedure: not new sequence, don't create} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Control-Button-2> "foo"
+ bind .t.f <Button-2>
+} -cleanup {
+ destroy .t.f
+} -result {}
+test bind-24.13 {FindSequence procedure: no binding} -body {
+ frame .t.f -class Test -width 150 -height 100
+ bind .t.f <a>
+} -cleanup {
+ destroy .t.f
+} -returnCodes ok
+test bind-24.14 {FindSequence procedure: no binding} -body {
+ canvas .t.c
+ set i [.t.c create rect 10 10 100 100]
+ .t.c bind $i <a>
+} -cleanup {
+ destroy .t.c
+} -returnCodes ok
+
+test bind-25.1 {ParseEventDescription procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f a test
+ bind .t.f a
+} -cleanup {
+ destroy .t.f
+} -result test
+test bind-25.2 {ParseEventDescription procedure: misinterpreted modifier} -setup {
+ button .b
+} -body {
+ bind .b <Control-M> a
+ bind .b <M-M> b
+ lsort [bind .b]
+} -cleanup {
+ destroy .b
+} -result {<Control-Key-M> <Meta-Key-M>}
+test bind-25.3 {ParseEventDescription procedure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <a---> {nothing}
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result a
+test bind-25.4 {ParseEventDescription} -body {
+ bind .t <<Shift-Paste>> {puts hi}
+ bind .t
+} -result {<<Shift-Paste>>}
+
+# Assorted error cases in event sequence parsing
+test bind-25.5 {ParseEventDescription procedure error cases} -body {
+ bind .t \x7 {puts hi}
+} -returnCodes error -result {bad ASCII character 0x7}
+test bind-25.6 {ParseEventDescription procedure error cases} -body {
+ bind .t \x7f {puts hi}
+} -returnCodes error -result {bad ASCII character 0x7f}
+test bind-25.7 {ParseEventDescription procedure error cases} -body {
+ bind .t \x4 {puts hi}
+} -returnCodes error -result {bad ASCII character 0x4}
+test bind-25.8 {ParseEventDescription procedure error cases} -body {
+ bind .t <<>> {puts hi}
+} -returnCodes error -result {virtual event "<<>>" is badly formed}
+test bind-25.9 {ParseEventDescription procedure error cases} -body {
+ bind .t <<Paste {puts hi}
+} -returnCodes error -result {missing ">" in virtual binding}
+test bind-25.10 {ParseEventDescription procedure error cases} -body {
+ bind .t <<Paste> {puts hi}
+} -returnCodes error -result {missing ">" in virtual binding}
+test bind-25.11 {ParseEventDescription procedure error cases} -body {
+ bind .t <<Paste>>h {puts hi}
+} -returnCodes error -result {virtual events may not be composed}
+test bind-25.12 {ParseEventDescription procedure error cases} -body {
+ bind .t <> {puts hi}
+} -returnCodes error -result {no event type or button # or keysym}
+test bind-25.13 {ParseEventDescription procedure error cases} -body {
+ bind .t <a-- {puts hi}
+} -returnCodes error -result {missing ">" in binding}
+test bind-25.14 {ParseEventDescription procedure error cases} -body {
+ bind .t <a-b> {puts hi}
+} -returnCodes error -result {extra characters after detail in binding}
+test bind-25.15 {ParseEventDescription procedure error cases} -body {
+ bind .t <<abc {puts hi}
+} -returnCodes error -result {missing ">" in virtual binding}
+test bind-25.16 {ParseEventDescription procedure error cases} -body {
+ bind .t <<abc> {puts hi}
+} -returnCodes error -result {missing ">" in virtual binding}
+test bind-25.17 {ParseEventDescription} -body {
+ event add <<xyz>> <<abc>>
+} -returnCodes error -result {virtual event not allowed in definition of another virtual event}
+
+# Modifier canonicalization tests
+
+test bind-25.18 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f {<Control- a>} foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <Control-Key-a>
+
+test bind-25.19 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <Shift-a> foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <Shift-Key-a>
+
+test bind-25.20 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <Lock-a> foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <Lock-Key-a>
+
+test bind-25.21 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <Meta---a> foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <Meta-Key-a>
+
+test bind-25.22 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <M-a> foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <Meta-Key-a>
+
+test bind-25.23 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <Alt-a> foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <Alt-Key-a>
+
+test bind-25.24 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <B1-a> foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <B1-Key-a>
+
+test bind-25.25 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <B2-a> foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <B2-Key-a>
+
+test bind-25.26 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <B3-a> foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <B3-Key-a>
+
+test bind-25.27 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <B4-a> foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <B4-Key-a>
+
+test bind-25.28 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <B5-a> foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <B5-Key-a>
+
+test bind-25.29 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <Button1-a> foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <B1-Key-a>
+
+test bind-25.30 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <Button2-a> foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <B2-Key-a>
+
+test bind-25.31 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <Button3-a> foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <B3-Key-a>
+
+test bind-25.32 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <Button4-a> foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <B4-Key-a>
+
+test bind-25.33 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <Button5-a> foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <B5-Key-a>
+
+test bind-25.34 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <M1-a> foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <Mod1-Key-a>
+
+test bind-25.35 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <M2-a> foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <Mod2-Key-a>
+
+test bind-25.36 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <M3-a> foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <Mod3-Key-a>
+
+test bind-25.37 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <M4-a> foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <Mod4-Key-a>
+
+test bind-25.38 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <M5-a> foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <Mod5-Key-a>
+
+test bind-25.39 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <Mod1-a> foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <Mod1-Key-a>
+
+test bind-25.40 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <Mod2-a> foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <Mod2-Key-a>
+
+test bind-25.41 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <Mod3-a> foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <Mod3-Key-a>
+
+test bind-25.42 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <Mod4-a> foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <Mod4-Key-a>
+
+test bind-25.43 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <Mod5-a> foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <Mod5-Key-a>
+
+test bind-25.44 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <Double-a> foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <Double-Key-a>
+
+test bind-25.45 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <Triple-a> foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <Triple-Key-a>
+
+test bind-25.46 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f {<Double 1>} foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <Double-Button-1>
+
+test bind-25.47 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <Triple-1> foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <Triple-Button-1>
+
+test bind-25.48 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f {<M1-M2 M3-M4 B1-Control-a>} foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <Control-B1-Mod1-Mod2-Mod3-Mod4-Key-a>
+
+test bind-25.49 {modifier names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <Extended-Return> foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <Extended-Key-Return>
+
+
+
+test bind-26.1 {event names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <FocusIn> {nothing}
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <FocusIn>
+test bind-26.2 {event names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+} -body {
+ bind .t.f <FocusOut> {nothing}
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result <FocusOut>
+test bind-26.3 {event names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Destroy> {lappend x "destroyed"}
+ set x [bind .t.f]
+ destroy .t.f
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {<Destroy> destroyed}
+
+test bind-26.4 {event names: Motion} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Motion> "set x {event Motion}"
+ set x xyzzy
+ event generate .t.f <Motion>
+ list $x [bind .t.f]
+} -cleanup {
+ destroy .t.f
+} -result {{event Motion} <Motion>}
+
+test bind-26.5 {event names: Button} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Button> "set x {event Button}"
+ set x xyzzy
+ event generate .t.f <Button>
+ list $x [bind .t.f]
+} -cleanup {
+ destroy .t.f
+} -result {{event Button} <Button>}
+
+test bind-26.6 {event names: ButtonPress} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <ButtonPress> "set x {event ButtonPress}"
+ set x xyzzy
+ event generate .t.f <ButtonPress>
+ list $x [bind .t.f]
+} -cleanup {
+ destroy .t.f
+} -result {{event ButtonPress} <Button>}
+
+test bind-26.7 {event names: ButtonRelease} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <ButtonRelease> "set x {event ButtonRelease}"
+ set x xyzzy
+ event generate .t.f <ButtonRelease>
+ list $x [bind .t.f]
+} -cleanup {
+ destroy .t.f
+} -result {{event ButtonRelease} <ButtonRelease>}
+
+test bind-26.8 {event names: Colormap} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Colormap> "set x {event Colormap}"
+ set x xyzzy
+ event generate .t.f <Colormap>
+ list $x [bind .t.f]
+} -cleanup {
+ destroy .t.f
+} -result {{event Colormap} <Colormap>}
+
+test bind-26.9 {event names: Enter} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Enter> "set x {event Enter}"
+ set x xyzzy
+ event generate .t.f <Enter>
+ list $x [bind .t.f]
+} -cleanup {
+ destroy .t.f
+} -result {{event Enter} <Enter>}
+
+test bind-26.10 {event names: Leave} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Leave> "set x {event Leave}"
+ set x xyzzy
+ event generate .t.f <Leave>
+ list $x [bind .t.f]
+} -cleanup {
+ destroy .t.f
+} -result {{event Leave} <Leave>}
+
+test bind-26.11 {event names: Expose} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Expose> "set x {event Expose}"
+ set x xyzzy
+ event generate .t.f <Expose>
+ list $x [bind .t.f]
+} -cleanup {
+ destroy .t.f
+} -result {{event Expose} <Expose>}
+
+test bind-26.12 {event names: Key} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Key> "set x {event Key}"
+ set x xyzzy
+ event generate .t.f <Key>
+ list $x [bind .t.f]
+} -cleanup {
+ destroy .t.f
+} -result {{event Key} <Key>}
+
+test bind-26.13 {event names: KeyPress} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <KeyPress> "set x {event KeyPress}"
+ set x xyzzy
+ event generate .t.f <KeyPress>
+ list $x [bind .t.f]
+} -cleanup {
+ destroy .t.f
+} -result {{event KeyPress} <Key>}
+
+test bind-26.14 {event names: KeyRelease} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <KeyRelease> "set x {event KeyRelease}"
+ set x xyzzy
+ event generate .t.f <KeyRelease>
+ list $x [bind .t.f]
+} -cleanup {
+ destroy .t.f
+} -result {{event KeyRelease} <KeyRelease>}
+
+test bind-26.15 {event names: Property} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Property> "set x {event Property}"
+ set x xyzzy
+ event generate .t.f <Property>
+ list $x [bind .t.f]
+} -cleanup {
+ destroy .t.f
+} -result {{event Property} <Property>}
+
+test bind-26.16 {event names: Visibility} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Visibility> "set x {event Visibility}"
+ set x xyzzy
+ event generate .t.f <Visibility>
+ list $x [bind .t.f]
+} -cleanup {
+ destroy .t.f
+} -result {{event Visibility} <Visibility>}
+
+test bind-26.17 {event names: Activate} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Activate> "set x {event Activate}"
+ set x xyzzy
+ event generate .t.f <Activate>
+ list $x [bind .t.f]
+} -cleanup {
+ destroy .t.f
+} -result {{event Activate} <Activate>}
+
+test bind-26.18 {event names: Deactivate} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Deactivate> "set x {event Deactivate}"
+ set x xyzzy
+ event generate .t.f <Deactivate>
+ list $x [bind .t.f]
+} -cleanup {
+ destroy .t.f
+} -result {{event Deactivate} <Deactivate>}
+
+
+# These events require an extra argument to [event generate]
+test bind-26.19 {event names: Circulate} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Circulate> "set x {event Circulate}"
+ set x xyzzy
+ event generate .t.f <Circulate>
+ list $x [bind .t.f]
+} -cleanup {
+ destroy .t.f
+} -result {{event Circulate} <Circulate>}
+
+test bind-26.20 {event names: Configure} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Configure> "set x {event Configure}"
+ set x xyzzy
+ event generate .t.f <Configure>
+ list $x [bind .t.f]
+} -cleanup {
+ destroy .t.f
+} -result {{event Configure} <Configure>}
+
+test bind-26.21 {event names: Gravity} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Gravity> "set x {event Gravity}"
+ set x xyzzy
+ event generate .t.f <Gravity>
+ list $x [bind .t.f]
+} -cleanup {
+ destroy .t.f
+} -result {{event Gravity} <Gravity>}
+
+test bind-26.22 {event names: Map} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Map> "set x {event Map}"
+ set x xyzzy
+ event generate .t.f <Map>
+ list $x [bind .t.f]
+} -cleanup {
+ destroy .t.f
+} -result {{event Map} <Map>}
+
+test bind-26.23 {event names: Reparent} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Reparent> "set x {event Reparent}"
+ set x xyzzy
+ event generate .t.f <Reparent>
+ list $x [bind .t.f]
+} -cleanup {
+ destroy .t.f
+} -result {{event Reparent} <Reparent>}
+
+test bind-26.24 {event names: Unmap} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Unmap> "set x {event Unmap}"
+ set x xyzzy
+ event generate .t.f <Unmap>
+ list $x [bind .t.f]
+} -cleanup {
+ destroy .t.f
+} -result {{event Unmap} <Unmap>}
+
+
+test bind-27.1 {button names} -body {
+ bind .t <Expose-1> foo
+} -returnCodes error -result {specified button "1" for non-button event}
+test bind-27.2 {button names} -body {
+ bind .t <Button-6> foo
+} -returnCodes error -result {specified keysym "6" for non-key event}
+test bind-27.3 {button names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Button-1> {lappend x "button 1"}
+ set x [bind .t.f]
+ event generate .t.f <Button-1>
+ event generate .t.f <ButtonRelease-1>
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {<Button-1> {button 1}}
+test bind-27.4 {button names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Button-2> {lappend x "button 2"}
+ set x [bind .t.f]
+ event generate .t.f <Button-2>
+ event generate .t.f <ButtonRelease-2>
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {<Button-2> {button 2}}
+test bind-27.5 {button names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Button-3> {lappend x "button 3"}
+ set x [bind .t.f]
+ event generate .t.f <Button-3>
+ event generate .t.f <ButtonRelease-3>
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {<Button-3> {button 3}}
+test bind-27.6 {button names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Button-4> {lappend x "button 4"}
+ set x [bind .t.f]
+ event generate .t.f <Button-4>
+ event generate .t.f <ButtonRelease-4>
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {<Button-4> {button 4}}
+test bind-27.7 {button names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Button-5> {lappend x "button 5"}
+ set x [bind .t.f]
+ event generate .t.f <Button-5>
+ event generate .t.f <ButtonRelease-5>
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {<Button-5> {button 5}}
+
+test bind-28.1 {keysym names} -body {
+ bind .t <Expose-a> foo
+} -returnCodes error -result {specified keysym "a" for non-key event}
+test bind-28.2 {keysym names} -body {
+ bind .t <Gorp> foo
+} -returnCodes error -result {bad event type or keysym "Gorp"}
+test bind-28.3 {keysym names} -body {
+ bind .t <Key-Stupid> foo
+} -returnCodes error -result {bad event type or keysym "Stupid"}
+test bind-28.4 {keysym names} -body {
+ frame .t.f -class Test -width 150 -height 100
+ bind .t.f <a> foo
+ bind .t.f
+} -cleanup {
+ destroy .t.f
+} -result {a}
+
+test bind-28.5 {keysym names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Key-colon> "lappend x \"keysym received\""
+ bind .t.f <Key-underscore> "lappend x {bad binding match}"
+ set x [lsort [bind .t.f]]
+ event generate .t.f <Key-colon> ;# -state 0
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {: _ {keysym received}}
+test bind-28.6 {keysym names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Key-Return> "lappend x \"keysym Return\""
+ bind .t.f <Key-x> "lappend x {bad binding match}"
+ set x [lsort [bind .t.f]]
+ event generate .t.f <Key-Return> -state 0
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {<Key-Return> x {keysym Return}}
+test bind-28.7 {keysym names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Key-X> "lappend x \"keysym X\""
+ bind .t.f <Key-x> "lappend x {bad binding match}"
+ set x [lsort [bind .t.f]]
+ event generate .t.f <Key-X> -state 1
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {X x {keysym X}}
+test bind-28.8 {keysym names} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Key-X> "lappend x \"keysym X\""
+ bind .t.f <Key-x> "lappend x {bad binding match}"
+ set x [lsort [bind .t.f]]
+ event generate .t.f <Key-X> -state 1
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {X x {keysym X}}
+
+
+test bind-29.1 {Tcl_BackgroundError procedure} -setup {
+ proc bgerror msg {
+ global x errorInfo
+ set x [list $msg $errorInfo]
+ }
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Button> {error "This is a test"}
+ set x none
+ event generate .t.f <Button>
+ event generate .t.f <ButtonRelease>
+ update
+ set x
+} -cleanup {
+ destroy .t.f
+ rename bgerror {}
+} -result {{This is a test} {This is a test
+ while executing
+"error "This is a test""
+ (command bound to event)}}
+
+test bind-29.2 {Tcl_BackgroundError procedure} -setup {
+ proc do {} {
+ event generate .t.f <Button>
+ event generate .t.f <ButtonRelease>
+ }
+ proc bgerror msg {
+ global x errorInfo
+ set x [list $msg $errorInfo]
+ }
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ bind .t.f <Button> {error Message2}
+ set x none
+ do
+ update
+ set x
+} -cleanup {
+ destroy .t.f
+ rename bgerror {}
+ rename do {}
+} -result {Message2 {Message2
+ while executing
+"error Message2"
+ (command bound to event)}}
+
+
+test bind-30.1 {MouseWheel events} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <MouseWheel> {set x Wheel}
+ event generate .t.f <MouseWheel>
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {Wheel}
+test bind-30.2 {MouseWheel events} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <MouseWheel> {set x %D}
+ event generate .t.f <MouseWheel> -delta 120
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {120}
+test bind-30.3 {MouseWheel events} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <MouseWheel> {set x "%D %x %y"}
+ event generate .t.f <MouseWheel> -delta 240 -x 10 -y 30
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {240 10 30}
+
+
+test bind-31.1 {virtual event user_data field - bad generation} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+# Check no confusion, since Focus events use %d for something else
+ event generate .t.f <FocusIn> -data foo
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {<FocusIn> event doesn't accept "-data" option}
+test bind-31.2 {virtual event user_data field - NULL, synch} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <<TestUserData>> {set x "TestUserData >%d<"}
+ event generate .t.f <<TestUserData>>
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {TestUserData >{}<}
+test bind-31.3 {virtual event user_data field - shared, synch} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <<TestUserData>> {set x "TestUserData >%d<"}
+ event generate .t.f <<TestUserData>> -data "foo bar"
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {TestUserData >foo bar<}
+test bind-31.4 {virtual event user_data field - unshared, synch} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <<TestUserData>> {set x "TestUserData >%d<"}
+ event generate .t.f <<TestUserData>> -data [string index abc 1]
+ set x
+} -cleanup {
+ destroy .t.f
+} -result {TestUserData >b<}
+# Note that asynch event handling can only really catch any potential
+# extra errors when used in combination with a tool like Purify or
+# Valgrind. Such testing is rarely done, but at least any problem with
+# reference handling will eventually show up with these tests...
+test bind-31.5 {virtual event user_data field - NULL, asynch} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <<TestUserData>> {set x "TestUserData >%d<"}
+ event generate .t.f <<TestUserData>> -when head
+ list $x [update] $x
+} -cleanup {
+ destroy .t.f
+} -result {{} {} {TestUserData >{}<}}
+test bind-31.6 {virtual event user_data field - shared, asynch} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <<TestUserData>> {set x "TestUserData >%d<"}
+ event generate .t.f <<TestUserData>> -data "foo bar" -when head
+ list $x [update] $x
+} -cleanup {
+ destroy .t.f
+} -result {{} {} {TestUserData >foo bar<}}
+test bind-31.7 {virtual event user_data field - unshared, asynch} -setup {
+ frame .t.f -class Test -width 150 -height 100
+ pack .t.f
+ focus -force .t.f
+ update
+ set x {}
+} -body {
+ bind .t.f <<TestUserData>> {set x "TestUserData >%d<"}
+ event generate .t.f <<TestUserData>> -data [string index abc 1] -when head
+ list $x [update] $x
+} -cleanup {
+ destroy .t.f
+} -result {{} {} {TestUserData >b<}}
+
+test bind-32 {-warp, window was destroyed before the idle callback DoWarp} -setup {
+ frame .t.f
+ pack .t.f
+ focus -force .t.f
+ update
+} -body {
+ event generate .t.f <Button-1> -warp 1
+ event generate .t.f <ButtonRelease-1>
+ destroy .t.f
+ update ; # shall simply not crash
+} -cleanup {
+} -result {}
+
+
+# cleanup
+cleanupTests
+return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tk8.6/tests/bitmap.test b/tk8.6/tests/bitmap.test
new file mode 100644
index 0000000..fea675d
--- /dev/null
+++ b/tk8.6/tests/bitmap.test
@@ -0,0 +1,114 @@
+# This file is a Tcl script to test out the procedures in the file
+# tkBitmap.c. It is organized in the standard white-box fashion for
+# Tcl tests.
+#
+# Copyright (c) 1998 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+
+test bitmap-1.1 {Tk_AllocBitmapFromObj - converting internal reps} -constraints {
+ testbitmap
+} -body {
+ set x gray25
+ lindex $x 0
+ button .b -bitmap $x
+ lindex $x 0
+ testbitmap gray25
+} -cleanup {
+ destroy .b
+} -result {{1 0}}
+test bitmap-1.2 {Tk_AllocBitmapFromObj - discard stale bitmap} -constraints {
+ testbitmap
+} -setup {
+ set result {}
+} -body {
+ set x gray25
+ button .b1 -bitmap $x
+ destroy .b1
+ lappend result [testbitmap gray25]
+ button .b2 -bitmap $x
+ lappend result [testbitmap gray25]
+} -cleanup {
+ destroy .b1 .b2
+} -result {{} {{1 1}}}
+test bitmap-1.3 {Tk_AllocBitmapFromObj - reuse existing bitmap} -constraints {
+ testbitmap
+} -setup {
+ set result {}
+} -body {
+ set x gray25
+ button .b1 -bitmap $x
+ lappend result [testbitmap gray25]
+ button .b2 -bitmap $x
+ pack .b1 .b2 -side top
+ lappend result [testbitmap gray25]
+} -cleanup {
+ destroy .b1 .b2
+} -result {{{1 1}} {{2 1}}}
+
+test bitmap-2.1 {Tk_GetBitmap procedure} -body {
+ button .b1 -bitmap bad_name
+} -cleanup {
+ destroy .b1
+} -returnCodes error -result {bitmap "bad_name" not defined}
+test bitmap-2.2 {Tk_GetBitmap procedure} -body {
+ button .b1 -bitmap @xyzzy
+} -cleanup {
+ destroy .b1
+} -returnCodes error -result {error reading bitmap file "xyzzy"}
+
+test bitmap-3.1 {Tk_FreeBitmapFromObj - reference counts} -constraints {
+ testbitmap
+} -setup {
+ set result {}
+} -body {
+ set x questhead
+ button .b1 -bitmap $x
+ button .b3 -bitmap $x
+ button .b2 -bitmap $x
+ lappend result [testbitmap questhead]
+ destroy .b1
+ lappend result [testbitmap questhead]
+ destroy .b2
+ lappend result [testbitmap questhead]
+ destroy .b3
+ lappend result [testbitmap questhead]
+} -cleanup {
+ destroy .b1 .b2 .b3 ;# destroying just in case
+} -result {{{3 1}} {{2 1}} {{1 1}} {}}
+
+test bitmap-4.1 {FreeBitmapObjProc} -constraints {
+ testbitmap
+} -setup {
+ proc copy {s} {return [string index $s 0][string range $s 1 end]}
+} -body {
+ set x [copy questhead]
+ button .b -bitmap $x
+ set y [copy questhead]
+ .b configure -bitmap $y
+ set z [copy questhead]
+ .b configure -bitmap $z
+ set result {}
+ lappend result [testbitmap questhead]
+ set x red
+ lappend result [testbitmap questhead]
+ set z 32
+ lappend result [testbitmap questhead]
+ destroy .b
+ lappend result [testbitmap questhead]
+ set y bogus
+ return $result
+} -cleanup {
+ rename copy {}
+ destroy .b
+} -result {{{1 3}} {{1 2}} {{1 1}} {}}
+
+
+# cleanup
+cleanupTests
+return
diff --git a/tk8.6/tests/border.test b/tk8.6/tests/border.test
new file mode 100644
index 0000000..f610ad8
--- /dev/null
+++ b/tk8.6/tests/border.test
@@ -0,0 +1,201 @@
+# This file is a Tcl script to test out the procedures in the file
+# tkBorder.c. It is organized in the standard fashion for Tcl tests.
+#
+# Copyright (c) 1998 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+
+test border-1.1 {Tk_AllocBorderFromObj - converting internal reps} -constraints {
+ testborder
+} -body {
+ set x orange
+ lindex $x 0
+ button .b1 -bg $x -text .b1
+ lindex $x 0
+ testborder orange
+} -cleanup {
+ destroy .b1
+} -result {{1 0}}
+test border-1.2 {Tk_AllocBorderFromObj - discard stale border} -constraints {
+ testborder
+} -setup {
+ set result {}
+} -body {
+ set x orange
+ button .b1 -bg $x -text First
+ destroy .b1
+ lappend result [testborder orange]
+ button .b2 -bg $x -text Second
+ lappend result [testborder orange]
+} -cleanup {
+ destroy .b1 .b2
+} -result {{} {{1 1}}}
+test border-1.3 {Tk_AllocBorderFromObj - reuse existing border} -constraints {
+ testborder
+} -setup {
+ set result {}
+} -body {
+ set x orange
+ button .b1 -bg $x -text First
+ lappend result [testborder orange]
+ button .b2 -bg $x -text Second
+ pack .b1 .b2 -side top
+ lappend result [testborder orange]
+} -cleanup {
+ destroy .b1 .b2
+} -result {{{1 1}} {{2 1}}}
+test border-1.4 {Tk_AllocBorderFromObj - try other borders in list} -constraints {
+ testborder pseudocolor8
+} -setup {
+ toplevel .t -visual {pseudocolor 8} -colormap new
+ wm geom .t +0+0
+ set result {}
+} -body {
+ set x purple
+ button .b1 -bg $x -text First
+ pack .b1 -side top
+ lappend result [testborder purple]
+ button .t.b -bg $x -text Second
+ pack .t.b -side top
+ lappend result [testborder purple]
+ button .b2 -bg $x -text Third
+ pack .b2 -side top
+ lappend result [testborder purple]
+} -cleanup {
+ destroy .b1 .b2 .t
+} -result {{{1 1}} {{1 1} {1 0}} {{1 0} {2 1}}}
+
+test border-2.1 {Tk_Free3DBorder - reference counts} -constraints {
+ testborder pseudocolor8
+} -setup {
+ toplevel .t -visual {pseudocolor 8} -colormap new
+ wm geom .t +0+0
+ set result {}
+} -body {
+ set x purple
+ button .b1 -bg $x -text First
+ pack .b1 -side top
+ button .t.b -bg $x -text Second
+ pack .t.b -side top
+ button .b2 -bg $x -text Third
+ pack .b2 -side top
+ lappend result [testborder purple]
+ destroy .b1
+ lappend result [testborder purple]
+ destroy .b2
+ lappend result [testborder purple]
+ destroy .t.b
+ lappend result [testborder purple]
+} -cleanup {
+ destroy .b1 .b2 .t
+} -result {{{1 0} {2 1}} {{1 0} {1 1}} {{1 0}} {}}
+test border-2.2 {Tk_Free3DBorder - unlinking from list} -constraints {
+ testborder pseudocolor8
+} -setup {
+ toplevel .t -visual {pseudocolor 8} -colormap new
+ wm geom .t +0+0
+ toplevel .t2 -visual {pseudocolor 8} -colormap new
+ toplevel .t3 -visual {pseudocolor 8} -colormap new
+ set result {}
+} -body {
+ set x purple
+ button .b -bg $x -text .b1
+ button .t.b1 -bg $x -text .t.b1
+ button .t.b2 -bg $x -text .t.b2
+ button .t2.b1 -bg $x -text .t2.b1
+ button .t2.b2 -bg $x -text .t2.b2
+ button .t2.b3 -bg $x -text .t2.b3
+ button .t3.b1 -bg $x -text .t3.b1
+ button .t3.b2 -bg $x -text .t3.b2
+ button .t3.b3 -bg $x -text .t3.b3
+ button .t3.b4 -bg $x -text .t3.b4
+ lappend result [testborder purple]
+ destroy .t2
+ lappend result [testborder purple]
+ destroy .b
+ lappend result [testborder purple]
+ destroy .t3
+ lappend result [testborder purple]
+ destroy .t
+ lappend result [testborder purple]
+} -cleanup {
+ destroy .b .t2 .t3 .t
+} -result {{{4 1} {3 0} {2 0} {1 0}} {{4 1} {2 0} {1 0}} {{4 1} {2 0}} {{2 0}} {}}
+
+test border-3.1 {FreeBorderObjProc} -constraints {
+ testborder
+} -setup {
+ set result {}
+ proc copy {s} {return [string index $s 0][string range $s 1 end]}
+} -body {
+ set x [copy purple]
+ button .b -bg $x -text .b1
+ set y [copy purple]
+ .b configure -bg $y
+ set z [copy purple]
+ .b configure -bg $z
+ lappend result [testborder purple]
+ set x red
+ lappend result [testborder purple]
+ set z 32
+ lappend result [testborder purple]
+ destroy .b
+ lappend result [testborder purple]
+ set y bogus
+ return $result
+} -cleanup {
+ rename copy {}
+ destroy .b
+} -result {{{1 3}} {{1 2}} {{1 1}} {}}
+
+test border-4.1 {Tk_GetReliefFromObj} -body {
+ button .b -relief flat
+ .b cget -relief
+} -cleanup {
+ destroy .b
+} -result {flat}
+test border-4.2 {Tk_GetReliefFromObj} -body {
+ button .b -relief groove
+ .b cget -relief
+} -cleanup {
+ destroy .b
+} -result {groove}
+test border-4.3 {Tk_GetReliefFromObj} -body {
+ button .b -relief raised
+ .b cget -relief
+} -cleanup {
+ destroy .b
+} -result {raised}
+test border-4.4 {Tk_GetReliefFromObj} -body {
+ button .b -relief ridge
+ .b cget -relief
+} -cleanup {
+ destroy .b
+} -result {ridge}
+test border-4.5 {Tk_GetReliefFromObj} -body {
+ button .b -relief solid
+ .b cget -relief
+} -cleanup {
+ destroy .b
+} -result {solid}
+test border-4.6 {Tk_GetReliefFromObj} -body {
+ button .b -relief sunken
+ .b cget -relief
+} -cleanup {
+ destroy .b
+} -result {sunken}
+test border-4.7 {Tk_GetReliefFromObj - error} -body {
+ button .b -relief upanddown
+} -cleanup {
+ destroy .b
+} -returnCodes error -result {bad relief "upanddown": must be flat, groove, raised, ridge, solid, or sunken}
+
+
+# cleanup
+cleanupTests
+return
diff --git a/tk8.6/tests/bugs.tcl b/tk8.6/tests/bugs.tcl
new file mode 100644
index 0000000..55e5f84
--- /dev/null
+++ b/tk8.6/tests/bugs.tcl
@@ -0,0 +1,41 @@
+# This file is a Tcl script to test out various known bugs that will
+# cause Tk to crash. This file ends with .tcl instead of .test to make
+# sure it isn't run when you type "source all". We currently are not
+# shipping this file with the rest of the source release.
+#
+# 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.
+
+if {[info procs test] != "test"} {
+ source defs
+}
+
+test crash-1.0 {imgPhoto} {
+ image create photo p1
+ image create photo p2
+ catch {image create photo p2 -file bogus}
+ p1 copy p2
+ label .l -image p1
+ destroy .l
+ set foo ""
+} {}
+
+test crash-1.1 {color} {
+ . configure -bg rgb:345
+ set foo ""
+} {}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tk8.6/tests/busy.test b/tk8.6/tests/busy.test
new file mode 100644
index 0000000..cdce30e
--- /dev/null
+++ b/tk8.6/tests/busy.test
@@ -0,0 +1,477 @@
+# Tests for the tk busy command.
+#
+# This file contains a collection of tests for one or more of the Tk built-in
+# commands. Sourcing this file runs the tests and generates output for errors.
+# No output means no errors were found.
+#
+# Copyright (c) 1998-2000 by Jos Decoster. All rights reserved.
+
+package require tcltest 2.1
+tcltest::configure {*}$argv
+tcltest::loadTestedCommands
+namespace import -force tcltest::test
+
+# There's currently no way to test the actual grab effect, per se, in an
+# automated test. Therefore, this test suite only covers the interface to the
+# grab command (ie, error messages, etc.)
+
+test busy-1.1 {Tk_BusyObjCmd} -returnCodes error -body {
+ tk busy
+} -result {wrong # args: should be "tk busy options ?arg arg ...?"}
+
+test busy-2.1 {tk busy hold} -returnCodes error -body {
+ tk busy hold
+} -result {wrong # args: should be "tk busy hold window ?option value ...?"}
+test busy-2.2 {tk busy hold root window} -body {
+ tk busy hold .
+ update
+} -cleanup {
+ tk busy forget .
+} -result {}
+test busy-2.3 {tk busy hold root window with shortcut} -body {
+ tk busy .
+ update
+} -cleanup {
+ tk busy forget .
+} -result {}
+test busy-2.4 {tk busy hold nested window} -setup {
+ pack [frame .f]
+} -body {
+ tk busy hold .f
+ update
+} -cleanup {
+ tk busy forget .f
+ destroy .f
+} -result {}
+test busy-2.5 {tk busy hold nested window with shortcut} -setup {
+ pack [frame .f]
+} -body {
+ tk busy .f
+ update
+} -cleanup {
+ tk busy forget .f
+ destroy .f
+} -result {}
+test busy-2.6 {tk busy hold toplevel window} -setup {
+ toplevel .f
+} -body {
+ tk busy hold .f
+ update
+} -cleanup {
+ tk busy forget .f
+ destroy .f
+} -result {}
+test busy-2.7 {tk busy hold toplevel window with shortcut} -setup {
+ toplevel .f
+} -body {
+ tk busy .f
+ update
+} -cleanup {
+ tk busy forget .f
+ destroy .f
+} -result {}
+test busy-2.8 {tk busy hold non existing window} -body {
+ tk busy hold .f
+ update
+} -returnCodes error -result {bad window path name ".f"}
+test busy-2.9 {tk busy hold (shortcut) non existing window} -body {
+ tk busy .f
+ update
+} -returnCodes {error} -result {bad window path name ".f"}
+test busy-2.10 {tk busy hold root window with cursor} -body {
+ tk busy hold . -cursor arrow
+ update
+} -cleanup {
+ tk busy forget .
+} -result {}
+test busy-2.11 {tk busy hold (shortcut) root window, cursor} -body {
+ tk busy . -cursor arrow
+ update
+} -cleanup {
+ tk busy forget .
+} -result {}
+test busy-2.12 {tk busy hold root window, invalid cursor} -body {
+ tk busy hold . -cursor nonExistingCursor
+ update
+} -returnCodes error -cleanup {
+ tk busy forget .
+} -result {bad cursor spec "nonExistingCursor"}
+test busy-2.13 {tk busy hold (shortcut) root window, invalid cursor} -body {
+ tk busy . -cursor nonExistingCursor
+ update
+} -returnCodes error -cleanup {
+ tk busy forget .
+} -result {bad cursor spec "nonExistingCursor"}
+test busy-2.14 {tk busy hold root window, invalid option} -body {
+ tk busy hold . -invalidOption 1
+ update
+} -returnCodes error -cleanup {
+ tk busy forget .
+} -result {unknown option "-invalidOption"}
+test busy-2.15 {tk busy hold (shortcut) root window, invalid option} -body {
+ tk busy . -invalidOption 1
+ update
+} -returnCodes error -cleanup {
+ tk busy forget .
+} -result {unknown option "-invalidOption"}
+
+test busy-3.1 {tk busy cget no window} -returnCodes error -body {
+ tk busy cget
+} -result {wrong # args: should be "tk busy cget window option"}
+test busy-3.2 {tk busy cget no option} -returnCodes error -body {
+ tk busy cget
+} -result {wrong # args: should be "tk busy cget window option"}
+test busy-3.3 {tk busy cget invalid window} -returnCodes error -body {
+ tk busy cget .f -cursor
+} -result {bad window path name ".f"}
+test busy-3.4 {tk busy cget non-busy window} -setup {
+ pack [frame .f]
+} -body {
+ tk busy cget .f -cursor
+} -cleanup {
+ destroy .f
+} -returnCodes error -result {can't find busy window ".f"}
+test busy-3.5 {tk busy cget invalid option} -setup {
+ pack [frame .f]
+ tk busy hold .f
+ update
+} -body {
+ tk busy cget .f -invalidOption
+} -cleanup {
+ tk busy forget .f
+ destroy .f
+} -returnCodes error -result {unknown option "-invalidOption"}
+test busy-3.6unix {tk busy cget unix} -setup {
+ pack [frame .f]
+ tk busy hold .f
+ update
+} -body {
+ tk busy cget .f -cursor
+} -cleanup {
+ tk busy forget .f
+ destroy .f
+} -result {watch} -constraints unix
+test busy-3.6win {tk busy cget win} -setup {
+ pack [frame .f]
+ tk busy hold .f
+ update
+} -body {
+ tk busy cget .f -cursor
+} -cleanup {
+ tk busy forget .f
+ destroy .f
+} -result {wait} -constraints win
+test busy-3.7 {tk busy cget unix} -setup {
+ pack [frame .f]
+ tk busy hold .f -cursor hand1
+ update
+} -body {
+ tk busy cget .f -cursor
+} -cleanup {
+ tk busy forget .f
+ destroy .f
+} -result {hand1}
+
+test busy-4.1 {tk busy configure no window} -returnCodes error -body {
+ tk busy configure
+} -result {wrong # args: should be "tk busy configure window ?option? ?value ...?"}
+
+test busy-4.2 {tk busy configure invalid window} -body {
+ tk busy configure .f
+} -returnCodes error -result {bad window path name ".f"}
+
+test busy-4.3 {tk busy configure non-busy window} -setup {
+ pack [frame .f]
+} -body {
+ tk busy configure .f
+} -cleanup {
+ destroy .f
+} -returnCodes error -result {can't find busy window ".f"}
+
+test busy-4.4 {tk busy configure} -constraints {nonwin} -setup {
+ pack [frame .f]
+ tk busy hold .f
+ update
+} -body {
+ tk busy configure .f
+} -cleanup {
+ tk busy forget .f
+ destroy .f
+} -result {{-cursor cursor Cursor watch watch}}
+
+test busy-4.4-win {tk busy configure} -constraints {win} -setup {
+ pack [frame .f]
+ tk busy hold .f
+ update
+} -body {
+ tk busy configure .f
+} -cleanup {
+ tk busy forget .f
+ destroy .f
+} -result {{-cursor cursor Cursor wait wait}}
+
+test busy-4.5 {tk busy configure} -constraints {nonwin} -setup {
+ pack [frame .f]
+ tk busy hold .f -cursor hand2
+ update
+} -body {
+ tk busy configure .f
+} -cleanup {
+ tk busy forget .f
+ destroy .f
+} -result {{-cursor cursor Cursor watch hand2}}
+
+test busy-4.5-win {tk busy configure} -constraints win -setup {
+ pack [frame .f]
+ tk busy hold .f -cursor hand2
+ update
+} -body {
+ tk busy configure .f
+} -cleanup {
+ tk busy forget .f
+ destroy .f
+} -result {{-cursor cursor Cursor wait hand2}}
+
+test busy-4.6 {tk busy configure invalid option} -setup {
+ pack [frame .f]
+ tk busy hold .f
+ update
+} -body {
+ tk busy configure .f -invalidOption
+} -cleanup {
+ tk busy forget .f
+ destroy .f
+} -returnCodes error -result {unknown option "-invalidOption"}
+
+test busy-4.7 {tk busy configure valid option} -constraints {nonwin} -setup {
+ pack [frame .f]
+ tk busy hold .f
+ update
+} -body {
+ tk busy configure .f -cursor
+} -cleanup {
+ tk busy forget .f
+ destroy .f
+} -result {-cursor cursor Cursor watch watch}
+
+test busy-4.7-win {tk busy configure valid option} -constraints {win} -setup {
+ pack [frame .f]
+ tk busy hold .f
+ update
+} -body {
+ tk busy configure .f -cursor
+} -cleanup {
+ tk busy forget .f
+ destroy .f
+} -result {-cursor cursor Cursor wait wait}
+
+test busy-4.8 {tk busy configure valid option} -constraints {
+ nonwin
+} -setup {
+ pack [frame .f]
+ tk busy hold .f -cursor circle
+ update
+} -body {
+ tk busy configure .f -cursor
+} -cleanup {
+ tk busy forget .f
+ destroy .f
+} -result {-cursor cursor Cursor watch circle}
+
+test busy-4.8-win {tk busy configure valid option} -constraints win -setup {
+ pack [frame .f]
+ tk busy hold .f -cursor circle
+ update
+} -body {
+ tk busy configure .f -cursor
+} -cleanup {
+ tk busy forget .f
+ destroy .f
+} -result {-cursor cursor Cursor wait circle}
+
+test busy-4.9 {tk busy configure valid option with value} -setup {
+ pack [frame .f]
+ tk busy hold .f
+ update
+} -body {
+ tk busy configure .f -cursor pencil
+ tk busy cget .f -cursor
+} -cleanup {
+ tk busy forget .f
+ destroy .f
+} -result {pencil}
+
+test busy-4.10 {tk busy configure valid option with invalid value} -setup {
+ pack [frame .f]
+ tk busy hold .f
+ update
+} -body {
+ tk busy configure .f -cursor nonExistingCursor
+} -returnCodes error -cleanup {
+ tk busy forget .f
+ destroy .f
+} -result {bad cursor spec "nonExistingCursor"}
+
+test busy-5.1 {tk busy forget} -returnCodes error -body {
+ tk busy forget
+} -result {wrong # args: should be "tk busy forget window"}
+test busy-5.2 {tk busy forget non existing window} -body {
+ tk busy forget .f
+} -returnCodes error -result {bad window path name ".f"}
+test busy-5.3 {tk busy forget non busy window} -setup {
+ pack [frame .f]
+} -body {
+ tk busy forget .f
+} -cleanup {
+ destroy .f
+} -returnCodes error -result {can't find busy window ".f"}
+test busy-5.4 {tk busy forget window} -setup {
+ pack [frame .f]
+ tk busy hold .f
+ update
+} -body {
+ set r [tk busy status .f]
+ tk busy forget .f
+ lappend r [tk busy status .f]
+} -cleanup {
+ destroy .f
+} -result {1 0}
+
+test busy-6.1 {tk busy status} -returnCodes error -body {
+ tk busy status
+} -result {wrong # args: should be "tk busy status window"}
+test busy-6.2 {tk busy status non existing window} -body {
+ tk busy status .f
+} -result {0}
+test busy-6.3 {tk busy status non busy window} -setup {
+ pack [frame .f]
+} -body {
+ tk busy status .f
+} -cleanup {
+ destroy .f
+} -result {0}
+test busy-6.4 {tk busy status busy window} -setup {
+ pack [frame .f]
+ tk busy hold .f
+ update
+} -body {
+ tk busy status .f
+} -cleanup {
+ tk busy forget .f
+ destroy .f
+} -result {1}
+test busy-6.5 {tk busy status forgotten busy window} -setup {
+ pack [frame .f]
+ tk busy hold .f
+ update
+ tk busy forget .f
+} -body {
+ tk busy status .f
+} -cleanup {
+ destroy .f
+} -result {0}
+
+test busy-7.1 {tk busy current no busy} -body {
+ tk busy current
+} -result {}
+test busy-7.2 {tk busy current 1 busy} -setup {
+ pack [frame .f]
+ tk busy hold .f
+ update
+} -body {
+ tk busy current
+} -cleanup {
+ tk busy forget .f
+ destroy .f
+} -result {.f}
+test busy-7.3 {tk busy current 2 busy} -setup {
+ pack [frame .f1]
+ pack [frame .f2]
+ tk busy hold .f1
+ tk busy hold .f2
+ update
+} -body {
+ lsort [tk busy current]
+} -cleanup {
+ tk busy forget .f1
+ tk busy forget .f2
+ destroy .f1 .f2
+} -result {.f1 .f2}
+test busy-7.4 {tk busy current 2 busy with matching filter} -setup {
+ pack [frame .f1]
+ pack [frame .f2]
+ tk busy hold .f1
+ tk busy hold .f2
+ update
+} -body {
+ lsort [tk busy current *2*]
+} -cleanup {
+ tk busy forget .f1
+ tk busy forget .f2
+ destroy .f1 .f2
+} -result {.f2}
+test busy-7.5 {tk busy current 2 busy with non matching filter} -setup {
+ pack [frame .f1]
+ pack [frame .f2]
+ tk busy hold .f1
+ tk busy hold .f2
+ update
+} -body {
+ lsort [tk busy current *3*]
+} -cleanup {
+ tk busy forget .f1
+ tk busy forget .f2
+ destroy .f1 .f2
+} -result {}
+test busy-7.6 {tk busy current 1 busy after forget} -setup {
+ pack [frame .f]
+ tk busy hold .f
+ update
+ tk busy forget .f
+} -body {
+ tk busy current
+} -cleanup {
+ destroy .f
+} -result {}
+test busy-7.7 {tk busy current 2 busy after forget} -setup {
+ pack [frame .f1]
+ pack [frame .f2]
+ tk busy hold .f1
+ tk busy hold .f2
+ update
+ tk busy forget .f1
+} -body {
+ lsort [tk busy current]
+} -cleanup {
+ tk busy forget .f2
+ destroy .f1 .f2
+} -result {.f2}
+test busy-7.8 {tk busy current 2 busy with matching filter after forget} -setup {
+ pack [frame .f1]
+ pack [frame .f2]
+ tk busy hold .f1
+ tk busy hold .f2
+ update
+ tk busy forget .f1
+} -body {
+ lsort [tk busy current *2*]
+} -cleanup {
+ tk busy forget .f2
+ destroy .f1 .f2
+} -result {.f2}
+test busy-7.9 {tk busy current 2 busy with non matching filter after forget} -setup {
+ pack [frame .f1]
+ pack [frame .f2]
+ tk busy hold .f1
+ tk busy hold .f2
+ update
+ tk busy forget .f1
+} -body {
+ lsort [tk busy current *3*]
+} -cleanup {
+ tk busy forget .f2
+ destroy .f1 .f2
+} -result {}
+
+::tcltest::cleanupTests
+return
diff --git a/tk8.6/tests/butGeom.tcl b/tk8.6/tests/butGeom.tcl
new file mode 100644
index 0000000..2ee8fdc
--- /dev/null
+++ b/tk8.6/tests/butGeom.tcl
@@ -0,0 +1,126 @@
+# This file creates a visual test for button layout. It is part of
+# the Tk visual test suite, which is invoked via the "visual" script.
+
+catch {destroy .t}
+toplevel .t
+wm title .t "Visual Tests for Button Geometry"
+wm iconname .t "Button Geometry"
+wm geom .t +0+0
+wm minsize .t 1 1
+
+label .t.l -text {This screen exercises the layout mechanisms for various flavors of buttons. Select display options below, and they will be applied to all of the button widgets. In order to see the effects of different anchor positions, expand the window so that there is extra space in the buttons. The letter "o" in "automatically" should be underlined in the right column of widgets.} -wraplength 5i
+pack .t.l -side top -fill both
+
+button .t.quit -text Quit -command {destroy .t}
+pack .t.quit -side bottom -pady 2m
+
+set sepId 1
+proc sep {} {
+ global sepId
+ frame .t.sep$sepId -height 2 -bd 1 -relief sunken
+ pack .t.sep$sepId -side top -padx 2m -pady 2m -fill x
+ incr sepId
+}
+
+# Create buttons that control configuration options.
+
+frame .t.control
+pack .t.control -side top -fill x -pady 3m
+frame .t.control.left
+frame .t.control.right
+pack .t.control.left .t.control.right -side left -expand 1 -fill x
+label .t.anchorLabel -text "Anchor:"
+frame .t.control.left.f -width 6c -height 3c
+pack .t.anchorLabel .t.control.left.f -in .t.control.left -side top
+foreach anchor {nw n ne w center e sw s se} {
+ button .t.anchor-$anchor -text $anchor -command "config -anchor $anchor"
+}
+place .t.anchor-nw -in .t.control.left.f -relx 0 -relwidth 0.333 \
+ -rely 0 -relheight 0.333
+place .t.anchor-n -in .t.control.left.f -relx 0.333 -relwidth 0.333 \
+ -rely 0 -relheight 0.333
+place .t.anchor-ne -in .t.control.left.f -relx 0.666 -relwidth 0.333 \
+ -rely 0 -relheight 0.333
+place .t.anchor-w -in .t.control.left.f -relx 0 -relwidth 0.333 \
+ -rely 0.333 -relheight 0.333
+place .t.anchor-center -in .t.control.left.f -relx 0.333 -relwidth 0.333 \
+ -rely 0.333 -relheight 0.333
+place .t.anchor-e -in .t.control.left.f -relx 0.666 -relwidth 0.333 \
+ -rely 0.333 -relheight 0.333
+place .t.anchor-sw -in .t.control.left.f -relx 0 -relwidth 0.333 \
+ -rely 0.666 -relheight 0.333
+place .t.anchor-s -in .t.control.left.f -relx 0.333 -relwidth 0.333 \
+ -rely 0.666 -relheight 0.333
+place .t.anchor-se -in .t.control.left.f -relx 0.666 -relwidth 0.333 \
+ -rely 0.666 -relheight 0.333
+
+set justify center
+radiobutton .t.justify-left -text "Justify Left" -relief flat \
+ -command "config -justify left" -variable justify \
+ -value left
+radiobutton .t.justify-center -text "Justify Center" -relief flat \
+ -command "config -justify center" -variable justify \
+ -value center
+radiobutton .t.justify-right -text "Justify Right" -relief flat \
+ -command "config -justify right" -variable justify \
+ -value right
+pack .t.justify-left .t.justify-center .t.justify-right \
+ -in .t.control.right -anchor w
+
+sep
+frame .t.f1
+pack .t.f1 -side top -expand 1 -fill both
+sep
+frame .t.f2
+pack .t.f2 -side top -expand 1 -fill both
+sep
+frame .t.f3
+pack .t.f3 -side top -expand 1 -fill both
+sep
+frame .t.f4
+pack .t.f4 -side top -expand 1 -fill both
+sep
+
+label .t.l1 -text Label -bd 2 -relief sunken
+label .t.l2 -text "Explicit\nnewlines\n\nin the text" -bd 2 -relief sunken
+label .t.l3 -text "This text is quite long, so it must be wrapped automatically by Tk" -wraplength 2i -bd 2 -relief sunken -underline 50
+pack .t.l1 .t.l2 .t.l3 -in .t.f1 -side left -padx 5m -pady 3m \
+ -expand y -fill both
+
+button .t.b1 -text Button
+button .t.b2 -text "Explicit\nnewlines\n\nin the text"
+button .t.b3 -text "This text is quite long, so it must be wrapped automatically by Tk" -wraplength 2i -underline 50
+pack .t.b1 .t.b2 .t.b3 -in .t.f2 -side left -padx 5m -pady 3m \
+ -expand y -fill both
+
+checkbutton .t.c1 -text Checkbutton -variable a
+checkbutton .t.c2 -text "Explicit\nnewlines\n\nin the text" -variable b
+checkbutton .t.c3 -text "This text is quite long, so it must be wrapped automatically by Tk" -wraplength 2i -variable c -underline 50
+pack .t.c1 .t.c2 .t.c3 -in .t.f3 -side left -padx 5m -pady 3m \
+ -expand y -fill both
+
+radiobutton .t.r1 -text Radiobutton -value a
+radiobutton .t.r2 -text "Explicit\nnewlines\n\nin the text" -value b
+radiobutton .t.r3 -text "This text is quite long, so it must be wrapped automatically by Tk" -wraplength 2i -value c -underline 50
+pack .t.r1 .t.r2 .t.r3 -in .t.f4 -side left -padx 5m -pady 3m \
+ -expand y -fill both
+
+proc config {option value} {
+ foreach w {.t.l1 .t.l2 .t.l3 .t.b1 .t.b2 .t.b3 .t.c1 .t.c2 .t.c3
+ .t.r1 .t.r2 .t.r3} {
+ $w configure $option $value
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tk8.6/tests/butGeom2.tcl b/tk8.6/tests/butGeom2.tcl
new file mode 100644
index 0000000..096225c
--- /dev/null
+++ b/tk8.6/tests/butGeom2.tcl
@@ -0,0 +1,124 @@
+# This file creates a visual test for button layout. It is part of
+# the Tk visual test suite, which is invoked via the "visual" script.
+
+catch {destroy .t}
+toplevel .t
+wm title .t "Visual Tests for Button Geometry"
+wm iconname .t "Button Geometry"
+wm geom .t +0+0
+wm minsize .t 1 1
+
+label .t.l -text {This screen exercises the color options for various flavors of buttons. Select display options below, and they will be applied to the appropiate button widgets.} -wraplength 5i
+pack .t.l -side top -fill both
+
+button .t.quit -text Quit -command {destroy .t}
+pack .t.quit -side bottom -pady 2m
+
+set sepId 1
+proc sep {} {
+ global sepId
+ frame .t.sep$sepId -height 2 -bd 1 -relief sunken
+ pack .t.sep$sepId -side top -padx 2m -pady 2m -fill x
+ incr sepId
+}
+
+# Create buttons that control configuration options.
+
+frame .t.control
+pack .t.control -side top -fill x -pady 3m
+frame .t.control.left
+frame .t.control.right
+pack .t.control.left .t.control.right -side left -expand 1 -fill x
+label .t.anchorLabel -text "Color:"
+frame .t.control.left.f -width 6c -height 3c
+pack .t.anchorLabel .t.control.left.f -in .t.control.left -side top -anchor w
+foreach opt {activebackground activeforeground background disabledforeground foreground highlightbackground highlightcolor } {
+ #button .t.color-$opt -text $opt -command "config -$opt \[tk_chooseColor]"
+ menubutton .t.color-$opt -text $opt -menu .t.color-$opt.m -indicatoron 1 \
+ -relief raised -bd 2
+ menu .t.color-$opt.m -tearoff 0
+ .t.color-$opt.m add command -label Red -command "config -$opt red"
+ .t.color-$opt.m add command -label Green -command "config -$opt green"
+ .t.color-$opt.m add command -label Blue -command "config -$opt blue"
+ .t.color-$opt.m add command -label Other... \
+ -command "config -$opt \[tk_chooseColor]"
+ pack .t.color-$opt -in .t.control.left.f -fill x
+}
+
+set default disabled
+label .t.default -text Default:
+radiobutton .t.default-normal -text "Default normal" -relief flat \
+ -command "config-but -default normal" -variable default \
+ -value normal
+radiobutton .t.default-active -text "Default active" -relief flat \
+ -command "config-but -default active" -variable default \
+ -value active
+radiobutton .t.default-disabled -text "Default disabled" -relief flat \
+ -command "config-but -default disabled" -variable default \
+ -value disabled
+pack .t.default .t.default-normal .t.default-active .t.default-disabled \
+ -in .t.control.right -anchor w
+
+sep
+frame .t.f1
+pack .t.f1 -side top -expand 1 -fill both
+sep
+frame .t.f2
+pack .t.f2 -side top -expand 1 -fill both
+sep
+frame .t.f3
+pack .t.f3 -side top -expand 1 -fill both
+sep
+frame .t.f4
+pack .t.f4 -side top -expand 1 -fill both
+sep
+
+label .t.l1 -text Label -bd 2 -relief sunken
+label .t.l2 -text "Explicit\nnewlines\n\nin the text" -bd 2 -relief sunken
+label .t.l3 -text "This text is quite long, so it must be wrapped automatically by Tk" -wraplength 2i -bd 2 -relief sunken -underline 50
+pack .t.l1 .t.l2 .t.l3 -in .t.f1 -side left -padx 5m -pady 3m \
+ -expand y -fill both
+
+button .t.b1 -text Button
+button .t.b2 -text "Explicit\nnewlines\n\nin the text"
+button .t.b3 -text "This text is quite long, so it must be wrapped automatically by Tk" -wraplength 2i -underline 50
+pack .t.b1 .t.b2 .t.b3 -in .t.f2 -side left -padx 5m -pady 3m \
+ -expand y -fill both
+
+checkbutton .t.c1 -text Checkbutton -variable a
+checkbutton .t.c2 -text "Explicit\nnewlines\n\nin the text" -variable b
+checkbutton .t.c3 -text "This text is quite long, so it must be wrapped automatically by Tk" -wraplength 2i -variable c -underline 50
+pack .t.c1 .t.c2 .t.c3 -in .t.f3 -side left -padx 5m -pady 3m \
+ -expand y -fill both
+
+radiobutton .t.r1 -text Radiobutton -value a
+radiobutton .t.r2 -text "Explicit\nnewlines\n\nin the text" -value b
+radiobutton .t.r3 -text "This text is quite long, so it must be wrapped automatically by Tk" -wraplength 2i -value c -underline 50
+pack .t.r1 .t.r2 .t.r3 -in .t.f4 -side left -padx 5m -pady 3m \
+ -expand y -fill both
+
+proc config {option value} {
+ foreach w {.t.l1 .t.l2 .t.l3 .t.b1 .t.b2 .t.b3 .t.c1 .t.c2 .t.c3
+ .t.r1 .t.r2 .t.r3} {
+ catch {$w configure $option $value}
+ }
+}
+
+proc config-but {option value} {
+ foreach w {.t.b1 .t.b2 .t.b3} {
+ $w configure $option $value
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tk8.6/tests/button.test b/tk8.6/tests/button.test
new file mode 100644
index 0000000..e5cb1b9
--- /dev/null
+++ b/tk8.6/tests/button.test
@@ -0,0 +1,4006 @@
+# This file is a Tcl script to test labels, buttons, checkbuttons, and
+# radiobuttons in Tk (i.e., all the widgets defined in tkButton.c). It is
+# organized in the standard fashion for Tcl tests.
+#
+# Copyright (c) 1994 The Regents of the University of California.
+# Copyright (c) 1994-1996 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+imageInit
+
+proc bogusTrace args {
+ error "trace aborted"
+}
+
+test button-1.1 {configuration option: "activebackground" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -activebackground #012345
+ .l cget -activebackground
+} -cleanup {
+ destroy .l
+} -result {#012345}
+test button-1.2 {configuration option: "activebackground" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -activebackground non-existent
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {unknown color name "non-existent"}
+test button-1.3 {configuration option: "activebackground" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -activebackground #012345
+ .b cget -activebackground
+} -cleanup {
+ destroy .b
+} -result {#012345}
+test button-1.4 {configuration option: "activebackground" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -activebackground non-existent
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {unknown color name "non-existent"}
+test button-1.5 {configuration option: "activebackground" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -activebackground #012345
+ .c cget -activebackground
+} -cleanup {
+ destroy .c
+} -result {#012345}
+test button-1.6 {configuration option: "activebackground" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -activebackground non-existent
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {unknown color name "non-existent"}
+test button-1.7 {configuration option: "activebackground" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -activebackground #012345
+ .r cget -activebackground
+} -cleanup {
+ destroy .r
+} -result {#012345}
+test button-1.8 {configuration option: "activebackground" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -activebackground non-existent
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {unknown color name "non-existent"}
+
+test button-1.9 {configuration option: "activeforeground" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -activeforeground #ff0000
+ .l cget -activeforeground
+} -cleanup {
+ destroy .l
+} -result {#ff0000}
+test button-1.10 {configuration option: "activeforeground" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -activeforeground non-existent
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {unknown color name "non-existent"}
+test button-1.11 {configuration option: "activeforeground" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -activeforeground #ff0000
+ .b cget -activeforeground
+} -cleanup {
+ destroy .b
+} -result {#ff0000}
+test button-1.12 {configuration option: "activeforeground" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -activeforeground non-existent
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {unknown color name "non-existent"}
+test button-1.13 {configuration option: "activeforeground" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -activeforeground #ff0000
+ .c cget -activeforeground
+} -cleanup {
+ destroy .c
+} -result {#ff0000}
+test button-1.14 {configuration option: "activeforeground" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -activeforeground non-existent
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {unknown color name "non-existent"}
+test button-1.15 {configuration option: "activeforeground" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -activeforeground #ff0000
+ .r cget -activeforeground
+} -cleanup {
+ destroy .r
+} -result {#ff0000}
+test button-1.16 {configuration option: "activeforeground" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -activeforeground non-existent
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {unknown color name "non-existent"}
+
+test button-1.17 {configuration option: "anchor" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -anchor nw
+ .l cget -anchor
+} -cleanup {
+ destroy .l
+} -result {nw}
+test button-1.18 {configuration option: "anchor" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -anchor bogus
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {bad anchor "bogus": must be n, ne, e, se, s, sw, w, nw, or center}
+test button-1.19 {configuration option: "anchor" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -anchor nw
+ .b cget -anchor
+} -cleanup {
+ destroy .b
+} -result {nw}
+test button-1.20 {configuration option: "anchor" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -anchor bogus
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {bad anchor "bogus": must be n, ne, e, se, s, sw, w, nw, or center}
+test button-1.21 {configuration option: "anchor" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -anchor nw
+ .c cget -anchor
+} -cleanup {
+ destroy .c
+} -result {nw}
+test button-1.22 {configuration option: "anchor" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -anchor bogus
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {bad anchor "bogus": must be n, ne, e, se, s, sw, w, nw, or center}
+test button-1.23 {configuration option: "anchor" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -anchor nw
+ .r cget -anchor
+} -cleanup {
+ destroy .r
+} -result {nw}
+test button-1.24 {configuration option: "anchor" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -anchor bogus
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {bad anchor "bogus": must be n, ne, e, se, s, sw, w, nw, or center}
+
+test button-1.25 {configuration option: "background" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -background #ff0000
+ .l cget -background
+} -cleanup {
+ destroy .l
+} -result {#ff0000}
+test button-1.26 {configuration option: "background" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -background non-existent
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {unknown color name "non-existent"}
+test button-1.27 {configuration option: "background" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -background #ff0000
+ .b cget -background
+} -cleanup {
+ destroy .b
+} -result {#ff0000}
+test button-1.28 {configuration option: "background" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -background non-existent
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {unknown color name "non-existent"}
+test button-1.29 {configuration option: "background" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -background #ff0000
+ .c cget -background
+} -cleanup {
+ destroy .c
+} -result {#ff0000}
+test button-1.30 {configuration option: "background" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -background non-existent
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {unknown color name "non-existent"}
+test button-1.31 {configuration option: "background" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -background #ff0000
+ .r cget -background
+} -cleanup {
+ destroy .r
+} -result {#ff0000}
+test button-1.32 {configuration option: "background" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -background non-existent
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {unknown color name "non-existent"}
+
+test button-1.33 {configuration option: "bd" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -bd 4
+ .l cget -bd
+} -cleanup {
+ destroy .l
+} -result {4}
+test button-1.34 {configuration option: "bd" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -bd badValue
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {bad screen distance "badValue"}
+test button-1.35 {configuration option: "bd" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -bd 4
+ .b cget -bd
+} -cleanup {
+ destroy .b
+} -result {4}
+test button-1.36 {configuration option: "bd" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -bd badValue
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {bad screen distance "badValue"}
+test button-1.37 {configuration option: "bd" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -bd 4
+ .c cget -bd
+} -cleanup {
+ destroy .c
+} -result {4}
+test button-1.38 {configuration option: "bd" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -bd badValue
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {bad screen distance "badValue"}
+test button-1.39 {configuration option: "bd" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -bd 4
+ .r cget -bd
+} -cleanup {
+ destroy .r
+} -result {4}
+test button-1.40 {configuration option: "bd" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -bd badValue
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {bad screen distance "badValue"}
+
+test button-1.41 {configuration option: "bg" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -bg #ff0000
+ .l cget -bg
+} -cleanup {
+ destroy .l
+} -result {#ff0000}
+test button-1.42 {configuration option: "bg" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -bg non-existent
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {unknown color name "non-existent"}
+test button-1.43 {configuration option: "bg" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -bg #ff0000
+ .b cget -bg
+} -cleanup {
+ destroy .b
+} -result {#ff0000}
+test button-1.44 {configuration option: "bg" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -bg non-existent
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {unknown color name "non-existent"}
+test button-1.45 {configuration option: "bg" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -bg #ff0000
+ .c cget -bg
+} -cleanup {
+ destroy .c
+} -result {#ff0000}
+test button-1.46 {configuration option: "bg" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -bg non-existent
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {unknown color name "non-existent"}
+test button-1.47 {configuration option: "bg" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -bg #ff0000
+ .r cget -bg
+} -cleanup {
+ destroy .r
+} -result {#ff0000}
+test button-1.48 {configuration option: "bg" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -bg non-existent
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {unknown color name "non-existent"}
+
+test button-1.49 {configuration option: "bitmap" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -bitmap questhead
+ .l cget -bitmap
+} -cleanup {
+ destroy .l
+} -result {questhead}
+test button-1.50 {configuration option: "bitmap" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -bitmap badValue
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {bitmap "badValue" not defined}
+test button-1.51 {configuration option: "bitmap" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -bitmap questhead
+ .b cget -bitmap
+} -cleanup {
+ destroy .b
+} -result {questhead}
+test button-1.52 {configuration option: "bitmap" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -bitmap badValue
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {bitmap "badValue" not defined}
+test button-1.53 {configuration option: "bitmap" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -bitmap questhead
+ .c cget -bitmap
+} -cleanup {
+ destroy .c
+} -result {questhead}
+test button-1.54 {configuration option: "bitmap" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -bitmap badValue
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {bitmap "badValue" not defined}
+test button-1.55 {configuration option: "bitmap" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -bitmap questhead
+ .r cget -bitmap
+} -cleanup {
+ destroy .r
+} -result {questhead}
+test button-1.56 {configuration option: "bitmap" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -bitmap badValue
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {bitmap "badValue" not defined}
+
+test button-1.57 {configuration option: "borderwidth" for label} -setup {
+ label .l -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -borderwidth 1.3
+ .l cget -borderwidth
+} -cleanup {
+ destroy .l
+} -result {1.3}
+test button-1.58 {configuration option: "borderwidth" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -borderwidth badValue
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {bad screen distance "badValue"}
+test button-1.59 {configuration option: "borderwidth" for button} -setup {
+ button .b -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -borderwidth 1.3
+ .b cget -borderwidth
+} -cleanup {
+ destroy .b
+} -result {1.3}
+test button-1.60 {configuration option: "borderwidth" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -borderwidth badValue
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {bad screen distance "badValue"}
+test button-1.61 {configuration option: "borderwidth" for checkbutton} -setup {
+ checkbutton .c -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -borderwidth 1.3
+ .c cget -borderwidth
+} -cleanup {
+ destroy .c
+} -result {1.3}
+test button-1.62 {configuration option: "borderwidth" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -borderwidth badValue
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {bad screen distance "badValue"}
+test button-1.63 {configuration option: "borderwidth" for radiobutton} -setup {
+ radiobutton .r -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -borderwidth 1.3
+ .r cget -borderwidth
+} -cleanup {
+ destroy .r
+} -result {1.3}
+test button-1.64 {configuration option: "borderwidth" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -borderwidth badValue
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {bad screen distance "badValue"}
+
+test button-1.65 {configuration option: "command" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -command {set x}
+ .b cget -command
+} -cleanup {
+ destroy .b
+} -result {set x}
+test button-1.66 {configuration option: "command" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -command {set x}
+ .b cget -command
+} -cleanup {
+ destroy .b
+} -result {set x}
+test button-1.67 {configuration option: "command" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -command {set x}
+ .c cget -command
+} -cleanup {
+ destroy .c
+} -result {set x}
+test button-1.68 {configuration option: "command" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -command {set x}
+ .r cget -command
+} -cleanup {
+ destroy .r
+} -result {set x}
+
+test button-1.69 {configuration option: "compound" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -compound left
+ .l cget -compound
+} -cleanup {
+ destroy .l
+} -result {left}
+test button-1.70 {configuration option: "compound" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -compound bogus
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {bad compound "bogus": must be bottom, center, left, none, right, or top}
+test button-1.71 {configuration option: "compound" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -compound left
+ .b cget -compound
+} -cleanup {
+ destroy .b
+} -result {left}
+test button-1.72 {configuration option: "compound" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -compound bogus
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {bad compound "bogus": must be bottom, center, left, none, right, or top}
+test button-1.73 {configuration option: "compound" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -compound left
+ .c cget -compound
+} -cleanup {
+ destroy .c
+} -result {left}
+test button-1.74 {configuration option: "compound" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -compound bogus
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {bad compound "bogus": must be bottom, center, left, none, right, or top}
+test button-1.75 {configuration option: "compound" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -compound left
+ .r cget -compound
+} -cleanup {
+ destroy .r
+} -result {left}
+test button-1.76 {configuration option: "compound" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -compound bogus
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {bad compound "bogus": must be bottom, center, left, none, right, or top}
+
+test button-1.77 {configuration option: "cursor" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -cursor arrow
+ .l cget -cursor
+} -cleanup {
+ destroy .l
+} -result {arrow}
+test button-1.78 {configuration option: "cursor" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -cursor badValue
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {bad cursor spec "badValue"}
+test button-1.79 {configuration option: "cursor" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -cursor arrow
+ .b cget -cursor
+} -cleanup {
+ destroy .b
+} -result {arrow}
+test button-1.80 {configuration option: "cursor" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -cursor badValue
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {bad cursor spec "badValue"}
+test button-1.81 {configuration option: "cursor" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -cursor arrow
+ .c cget -cursor
+} -cleanup {
+ destroy .c
+} -result {arrow}
+test button-1.82 {configuration option: "cursor" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -cursor badValue
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {bad cursor spec "badValue"}
+test button-1.83 {configuration option: "cursor" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -cursor arrow
+ .r cget -cursor
+} -cleanup {
+ destroy .r
+} -result {arrow}
+test button-1.84 {configuration option: "cursor" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -cursor badValue
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {bad cursor spec "badValue"}
+
+test button-1.85 {configuration option: "default" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -default active
+ .b cget -default
+} -cleanup {
+ destroy .b
+} -result {active}
+test button-1.86 {configuration option: "default" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -default huh?
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {bad default "huh?": must be active, disabled, or normal}
+
+test button-1.87 {configuration option: "disabledforeground" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -disabledforeground #00ff00
+ .l cget -disabledforeground
+} -cleanup {
+ destroy .l
+} -result {#00ff00}
+test button-1.88 {configuration option: "disabledforeground" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -disabledforeground non-existent
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {unknown color name "non-existent"}
+test button-1.89 {configuration option: "disabledforeground" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -disabledforeground #00ff00
+ .b cget -disabledforeground
+} -cleanup {
+ destroy .b
+} -result {#00ff00}
+test button-1.90 {configuration option: "disabledforeground" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -disabledforeground non-existent
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {unknown color name "non-existent"}
+test button-1.91 {configuration option: "disabledforeground" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -disabledforeground #00ff00
+ .c cget -disabledforeground
+} -cleanup {
+ destroy .c
+} -result {#00ff00}
+test button-1.92 {configuration option: "disabledforeground" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -disabledforeground non-existent
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {unknown color name "non-existent"}
+test button-1.93 {configuration option: "disabledforeground" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -disabledforeground #00ff00
+ .r cget -disabledforeground
+} -cleanup {
+ destroy .r
+} -result {#00ff00}
+test button-1.94 {configuration option: "disabledforeground" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -disabledforeground non-existent
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {unknown color name "non-existent"}
+
+test button-1.95 {configuration option: "fg" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -fg #110022
+ .l cget -fg
+} -cleanup {
+ destroy .l
+} -result {#110022}
+test button-1.96 {configuration option: "fg" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -fg non-existent
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {unknown color name "non-existent"}
+test button-1.97 {configuration option: "fg" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -fg #110022
+ .b cget -fg
+} -cleanup {
+ destroy .b
+} -result {#110022}
+test button-1.98 {configuration option: "fg" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -fg non-existent
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {unknown color name "non-existent"}
+test button-1.99 {configuration option: "fg" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -fg #110022
+ .c cget -fg
+} -cleanup {
+ destroy .c
+} -result {#110022}
+test button-1.100 {configuration option: "fg" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -fg non-existent
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {unknown color name "non-existent"}
+test button-1.101 {configuration option: "fg" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -fg #110022
+ .r cget -fg
+} -cleanup {
+ destroy .r
+} -result {#110022}
+test button-1.102 {configuration option: "fg" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -fg non-existent
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {unknown color name "non-existent"}
+
+test button-1.103 {configuration option: "font" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2
+ pack .l
+ update
+} -body {
+ .l configure -font {Helvetica -12}
+ .l cget -font
+} -cleanup {
+ destroy .l
+} -result {Helvetica -12}
+test button-1.104 {configuration option: "activebackground" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2
+ pack .l
+ update
+} -body {
+ .l configure -font {}
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {font "" doesn't exist}
+test button-1.105 {configuration option: "font" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2
+ pack .b
+ update
+} -body {
+ .b configure -font {Helvetica -12}
+ .b cget -font
+} -cleanup {
+ destroy .b
+} -result {Helvetica -12}
+test button-1.106 {configuration option: "activebackground" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2
+ pack .b
+ update
+} -body {
+ .b configure -font {}
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {font "" doesn't exist}
+test button-1.107 {configuration option: "font" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2
+ pack .c
+ update
+} -body {
+ .c configure -font {Helvetica -12}
+ .c cget -font
+} -cleanup {
+ destroy .c
+} -result {Helvetica -12}
+test button-1.108 {configuration option: "activebackground" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2
+ pack .c
+ update
+} -body {
+ .c configure -font {}
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {font "" doesn't exist}
+test button-1.109 {configuration option: "font" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2
+ pack .r
+ update
+} -body {
+ .r configure -font {Helvetica -12}
+ .r cget -font
+} -cleanup {
+ destroy .r
+} -result {Helvetica -12}
+test button-1.110 {configuration option: "activebackground" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2
+ pack .r
+ update
+} -body {
+ .r configure -font {}
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {font "" doesn't exist}
+
+test button-1.111 {configuration option: "foreground" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -foreground #110022
+ .l cget -foreground
+} -cleanup {
+ destroy .l
+} -result {#110022}
+test button-1.112 {configuration option: "foreground" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -foreground non-existent
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {unknown color name "non-existent"}
+test button-1.113 {configuration option: "foreground" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -foreground #110022
+ .b cget -foreground
+} -cleanup {
+ destroy .b
+} -result {#110022}
+test button-1.114 {configuration option: "foreground" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -foreground non-existent
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {unknown color name "non-existent"}
+test button-1.115 {configuration option: "foreground" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -foreground #110022
+ .c cget -foreground
+} -cleanup {
+ destroy .c
+} -result {#110022}
+test button-1.116 {configuration option: "foreground" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -foreground non-existent
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {unknown color name "non-existent"}
+test button-1.117 {configuration option: "foreground" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -foreground #110022
+ .r cget -foreground
+} -cleanup {
+ destroy .r
+} -result {#110022}
+test button-1.118 {configuration option: "foreground" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -foreground non-existent
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {unknown color name "non-existent"}
+
+test button-1.119 {configuration option: "height" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -height 18
+ .l cget -height
+} -cleanup {
+ destroy .l
+} -result {18}
+test button-1.120 {configuration option: "height" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -height 20.0
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {expected integer but got "20.0"}
+test button-1.121 {configuration option: "height" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -height 18
+ .b cget -height
+} -cleanup {
+ destroy .b
+} -result {18}
+test button-1.122 {configuration option: "height" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -height 20.0
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {expected integer but got "20.0"}
+test button-1.123 {configuration option: "height" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -height 18
+ .c cget -height
+} -cleanup {
+ destroy .c
+} -result {18}
+test button-1.124 {configuration option: "height" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -height 20.0
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {expected integer but got "20.0"}
+test button-1.125 {configuration option: "height" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -height 18
+ .r cget -height
+} -cleanup {
+ destroy .r
+} -result {18}
+test button-1.126 {configuration option: "height" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -height 20.0
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {expected integer but got "20.0"}
+
+test button-1.127 {configuration option: "highlightbackground" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -highlightbackground #110022
+ .l cget -highlightbackground
+} -cleanup {
+ destroy .l
+} -result {#110022}
+test button-1.128 {configuration option: "highlightbackground" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -highlightbackground non-existent
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {unknown color name "non-existent"}
+test button-1.129 {configuration option: "highlightbackground" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -highlightbackground #110022
+ .b cget -highlightbackground
+} -cleanup {
+ destroy .b
+} -result {#110022}
+test button-1.130 {configuration option: "highlightbackground" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -highlightbackground non-existent
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {unknown color name "non-existent"}
+test button-1.131 {configuration option: "highlightbackground" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -highlightbackground #110022
+ .c cget -highlightbackground
+} -cleanup {
+ destroy .c
+} -result {#110022}
+test button-1.132 {configuration option: "highlightbackground" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -highlightbackground non-existent
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {unknown color name "non-existent"}
+test button-1.133 {configuration option: "highlightbackground" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -highlightbackground #110022
+ .r cget -highlightbackground
+} -cleanup {
+ destroy .r
+} -result {#110022}
+test button-1.134 {configuration option: "highlightbackground" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -highlightbackground non-existent
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {unknown color name "non-existent"}
+
+test button-1.135 {configuration option: "highlightcolor" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -highlightcolor #110022
+ .l cget -highlightcolor
+} -cleanup {
+ destroy .l
+} -result {#110022}
+test button-1.136 {configuration option: "highlightcolor" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -highlightcolor non-existent
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {unknown color name "non-existent"}
+test button-1.137 {configuration option: "highlightcolor" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -highlightcolor #110022
+ .b cget -highlightcolor
+} -cleanup {
+ destroy .b
+} -result {#110022}
+test button-1.138 {configuration option: "highlightcolor" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -highlightcolor non-existent
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {unknown color name "non-existent"}
+test button-1.139 {configuration option: "highlightcolor" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -highlightcolor #110022
+ .c cget -highlightcolor
+} -cleanup {
+ destroy .c
+} -result {#110022}
+test button-1.140 {configuration option: "highlightcolor" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -highlightcolor non-existent
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {unknown color name "non-existent"}
+test button-1.141 {configuration option: "highlightcolor" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -highlightcolor #110022
+ .r cget -highlightcolor
+} -cleanup {
+ destroy .r
+} -result {#110022}
+test button-1.142 {configuration option: "highlightcolor" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -highlightcolor non-existent
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {unknown color name "non-existent"}
+
+test button-1.143 {configuration option: "highlightthickness" for label} -setup {
+ label .l -borderwidth 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -highlightthickness 6m
+ .l cget -highlightthickness
+} -cleanup {
+ destroy .l
+} -result {6m}
+test button-1.144 {configuration option: "highlightthickness" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -highlightthickness badValue
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {bad screen distance "badValue"}
+test button-1.145 {configuration option: "highlightthickness" for button} -setup {
+ button .b -borderwidth 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -highlightthickness 6m
+ .b cget -highlightthickness
+} -cleanup {
+ destroy .b
+} -result {6m}
+test button-1.146 {configuration option: "highlightthickness" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -highlightthickness badValue
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {bad screen distance "badValue"}
+test button-1.147 {configuration option: "highlightthickness" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -highlightthickness 6m
+ .c cget -highlightthickness
+} -cleanup {
+ destroy .c
+} -result {6m}
+test button-1.148 {configuration option: "highlightthickness" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -highlightthickness badValue
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {bad screen distance "badValue"}
+test button-1.149 {configuration option: "highlightthickness" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -highlightthickness 6m
+ .r cget -highlightthickness
+} -cleanup {
+ destroy .r
+} -result {6m}
+test button-1.150 {configuration option: "highlightthickness" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -highlightthickness badValue
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {bad screen distance "badValue"}
+
+test button-1.151 {configuration option: "image" for label} -constraints {
+ testImageType
+} -setup {
+ image create test image1
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -image image1
+ .l cget -image
+} -cleanup {
+ destroy .l
+ image delete image1
+} -result {image1}
+test button-1.152 {configuration option: "image" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -image bogus
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {image "bogus" doesn't exist}
+test button-1.153 {configuration option: "image" for button} -constraints {
+ testImageType
+} -setup {
+ image create test image1
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -image image1
+ .b cget -image
+} -cleanup {
+ destroy .b
+ image delete image1
+} -result {image1}
+test button-1.154 {configuration option: "image" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -image bogus
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {image "bogus" doesn't exist}
+test button-1.155 {configuration option: "image" for checkbutton} -constraints {
+ testImageType
+} -setup {
+ image create test image1
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -image image1
+ .c cget -image
+} -cleanup {
+ destroy .c
+ image delete image1
+} -result {image1}
+test button-1.156 {configuration option: "image" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -image bogus
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {image "bogus" doesn't exist}
+test button-1.157 {configuration option: "image" for radiobutton} -constraints {
+ testImageType
+} -setup {
+ image create test image1
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -image image1
+ .r cget -image
+} -cleanup {
+ destroy .r
+ image delete image1
+} -result {image1}
+test button-1.158 {configuration option: "image" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -image bogus
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {image "bogus" doesn't exist}
+
+test button-1.159 {configuration option: "indicatoron" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -indicatoron yes
+ .c cget -indicatoron
+} -cleanup {
+ destroy .c
+} -result {1}
+test button-1.160 {configuration option: "indicatoron" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -indicatoron no_way
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {expected boolean value but got "no_way"}
+test button-1.161 {configuration option: "indicatoron" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -indicatoron yes
+ .r cget -indicatoron
+} -cleanup {
+ destroy .r
+} -result {1}
+test button-1.162 {configuration option: "indicatoron" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -indicatoron no_way
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {expected boolean value but got "no_way"}
+
+test button-1.163 {configuration option: "justify" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -justify right
+ .l cget -justify
+} -cleanup {
+ destroy .l
+} -result {right}
+test button-1.164 {configuration option: "justify" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -justify bogus
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {bad justification "bogus": must be left, right, or center}
+test button-1.165 {configuration option: "justify" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -justify right
+ .b cget -justify
+} -cleanup {
+ destroy .b
+} -result {right}
+test button-1.166 {configuration option: "justify" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -justify bogus
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {bad justification "bogus": must be left, right, or center}
+test button-1.167 {configuration option: "justify" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -justify right
+ .c cget -justify
+} -cleanup {
+ destroy .c
+} -result {right}
+test button-1.168 {configuration option: "justify" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -justify bogus
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {bad justification "bogus": must be left, right, or center}
+test button-1.169 {configuration option: "justify" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -justify right
+ .r cget -justify
+} -cleanup {
+ destroy .r
+} -result {right}
+test button-1.170 {configuration option: "justify" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -justify bogus
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {bad justification "bogus": must be left, right, or center}
+
+test button-1.171 {configuration option: "offrelief" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -offrelief flat
+ .c cget -offrelief
+} -cleanup {
+ destroy .c
+} -result {flat}
+test button-1.172 {configuration option: "offrelief" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -offrelief 1.5
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {bad relief "1.5": must be flat, groove, raised, ridge, solid, or sunken}
+test button-1.173 {configuration option: "offrelief" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -offrelief flat
+ .r cget -offrelief
+} -cleanup {
+ destroy .r
+} -result {flat}
+test button-1.174 {configuration option: "offrelief" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -offrelief 1.5
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {bad relief "1.5": must be flat, groove, raised, ridge, solid, or sunken}
+
+test button-1.175 {configuration option: "offvalue" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -offvalue lousy
+ .c cget -offvalue
+} -cleanup {
+ destroy .c
+} -result {lousy}
+
+test button-1.176 {configuration option: "onvalue" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -onvalue fantastic
+ .c cget -onvalue
+} -cleanup {
+ destroy .c
+} -result {fantastic}
+
+test button-1.177 {configuration option: "overrelief" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -overrelief ""
+ .b cget -overrelief
+} -cleanup {
+ destroy .b
+} -result {}
+test button-1.178 {configuration option: "overrelief" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -overrelief 1.5
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {bad relief "1.5": must be flat, groove, raised, ridge, solid, or sunken}
+test button-1.179 {configuration option: "overrelief" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -overrelief ""
+ .c cget -overrelief
+} -cleanup {
+ destroy .c
+} -result {}
+test button-1.180 {configuration option: "overrelief" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -overrelief 1.5
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {bad relief "1.5": must be flat, groove, raised, ridge, solid, or sunken}
+test button-1.181 {configuration option: "overrelief" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -overrelief ""
+ .r cget -overrelief
+} -cleanup {
+ destroy .r
+} -result {}
+test button-1.182 {configuration option: "overrelief" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -overrelief 1.5
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {bad relief "1.5": must be flat, groove, raised, ridge, solid, or sunken}
+
+test button-1.183 {configuration option: "padx" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -padx 12m
+ .l cget -padx
+} -cleanup {
+ destroy .l
+} -result {12m}
+test button-1.184 {configuration option: "padx" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -padx 420x
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {bad screen distance "420x"}
+test button-1.185 {configuration option: "padx" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -padx 12m
+ .b cget -padx
+} -cleanup {
+ destroy .b
+} -result {12m}
+test button-1.186 {configuration option: "padx" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -padx 420x
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {bad screen distance "420x"}
+test button-1.187 {configuration option: "padx" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -padx 12m
+ .c cget -padx
+} -cleanup {
+ destroy .c
+} -result {12m}
+test button-1.188 {configuration option: "padx" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -padx 420x
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {bad screen distance "420x"}
+test button-1.189 {configuration option: "padx" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -padx 12m
+ .r cget -padx
+} -cleanup {
+ destroy .r
+} -result {12m}
+test button-1.190 {configuration option: "padx" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -padx 420x
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {bad screen distance "420x"}
+
+test button-1.191 {configuration option: "pady" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -pady 12m
+ .l cget -pady
+} -cleanup {
+ destroy .l
+} -result {12m}
+test button-1.192 {configuration option: "pady" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -pady 420x
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {bad screen distance "420x"}
+test button-1.193 {configuration option: "pady" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -pady 12m
+ .b cget -pady
+} -cleanup {
+ destroy .b
+} -result {12m}
+test button-1.194 {configuration option: "pady" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -pady 420x
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {bad screen distance "420x"}
+test button-1.195 {configuration option: "pady" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -pady 12m
+ .c cget -pady
+} -cleanup {
+ destroy .c
+} -result {12m}
+test button-1.196 {configuration option: "pady" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -pady 420x
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {bad screen distance "420x"}
+test button-1.197 {configuration option: "pady" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -pady 12m
+ .r cget -pady
+} -cleanup {
+ destroy .r
+} -result {12m}
+test button-1.198 {configuration option: "pady" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -pady 420x
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {bad screen distance "420x"}
+
+test button-1.199 {configuration option: "repeatdelay" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -repeatdelay 100
+ .b cget -repeatdelay
+} -cleanup {
+ destroy .b
+} -result {100}
+test button-1.200 {configuration option: "repeatdelay" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -repeatdelay foo
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {expected integer but got "foo"}
+
+test button-1.201 {configuration option: "repeatinterval" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -repeatinterval 100
+ .b cget -repeatinterval
+} -cleanup {
+ destroy .b
+} -result {100}
+test button-1.202 {configuration option: "repeatinterval" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -repeatinterval foo
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {expected integer but got "foo"}
+
+test button-1.203 {configuration option: "relief" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -relief flat
+ .l cget -relief
+} -cleanup {
+ destroy .l
+} -result {flat}
+test button-1.204 {configuration option: "relief" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -relief 1.5
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {bad relief "1.5": must be flat, groove, raised, ridge, solid, or sunken}
+test button-1.205 {configuration option: "relief" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -relief flat
+ .b cget -relief
+} -cleanup {
+ destroy .b
+} -result {flat}
+test button-1.206 {configuration option: "relief" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -relief 1.5
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {bad relief "1.5": must be flat, groove, raised, ridge, solid, or sunken}
+test button-1.207 {configuration option: "relief" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -relief flat
+ .c cget -relief
+} -cleanup {
+ destroy .c
+} -result {flat}
+test button-1.208 {configuration option: "relief" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -relief 1.5
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {bad relief "1.5": must be flat, groove, raised, ridge, solid, or sunken}
+test button-1.209 {configuration option: "relief" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -relief flat
+ .r cget -relief
+} -cleanup {
+ destroy .r
+} -result {flat}
+test button-1.210 {configuration option: "relief" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -relief 1.5
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {bad relief "1.5": must be flat, groove, raised, ridge, solid, or sunken}
+
+test button-1.211 {configuration option: "selectcolor" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -selectcolor #110022
+ .c cget -selectcolor
+} -cleanup {
+ destroy .c
+} -result {#110022}
+test button-1.212 {configuration option: "selectcolor" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -selectcolor non-existent
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {unknown color name "non-existent"}
+test button-1.213 {configuration option: "selectcolor" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -selectcolor #110022
+ .r cget -selectcolor
+} -cleanup {
+ destroy .r
+} -result {#110022}
+test button-1.214 {configuration option: "selectcolor" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -selectcolor non-existent
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {unknown color name "non-existent"}
+
+test button-1.215 {configuration option: "selectimage" for checkbutton} -constraints {
+ testImageType
+} -setup {
+ image create test image1
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -selectimage image1
+ .c cget -selectimage
+} -cleanup {
+ destroy .c
+ image delete image1
+} -result {image1}
+test button-1.216 {configuration option: "selectimage" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -selectimage bogus
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {image "bogus" doesn't exist}
+test button-1.217 {configuration option: "selectimage" for radiobutton} -constraints {
+ testImageType
+} -setup {
+ image create test image1
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -selectimage image1
+ .r cget -selectimage
+} -cleanup {
+ destroy .r
+ image delete image1
+} -result {image1}
+test button-1.218 {configuration option: "selectimage" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -selectimage bogus
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {image "bogus" doesn't exist}
+
+test button-1.219 {configuration option: "state" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -state normal
+ .l cget -state
+} -cleanup {
+ destroy .l
+} -result {normal}
+test button-1.220 {configuration option: "state" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -state bogus
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {bad state "bogus": must be active, disabled, or normal}
+test button-1.221 {configuration option: "state" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -state normal
+ .b cget -state
+} -cleanup {
+ destroy .b
+} -result {normal}
+test button-1.222 {configuration option: "state" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -state bogus
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {bad state "bogus": must be active, disabled, or normal}
+test button-1.223 {configuration option: "state" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -state normal
+ .c cget -state
+} -cleanup {
+ destroy .c
+} -result {normal}
+test button-1.224 {configuration option: "state" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -state bogus
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {bad state "bogus": must be active, disabled, or normal}
+test button-1.225 {configuration option: "state" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -state normal
+ .r cget -state
+} -cleanup {
+ destroy .r
+} -result {normal}
+test button-1.226 {configuration option: "state" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -state bogus
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {bad state "bogus": must be active, disabled, or normal}
+
+test button-1.227 {configuration option: "takefocus" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -takefocus "any string"
+ .l cget -takefocus
+} -cleanup {
+ destroy .l
+} -result {any string}
+test button-1.228 {configuration option: "takefocus" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -takefocus "any string"
+ .b cget -takefocus
+} -cleanup {
+ destroy .b
+} -result {any string}
+test button-1.229 {configuration option: "takefocus" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -takefocus "any string"
+ .c cget -takefocus
+} -cleanup {
+ destroy .c
+} -result {any string}
+test button-1.230 {configuration option: "takefocus" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -takefocus "any string"
+ .r cget -takefocus
+} -cleanup {
+ destroy .r
+} -result {any string}
+
+test button-1.231 {configuration option: "text" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -text "Sample text"
+ .l cget -text
+} -cleanup {
+ destroy .l
+} -result {Sample text}
+test button-1.232 {configuration option: "text" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -text "Sample text"
+ .b cget -text
+} -cleanup {
+ destroy .b
+} -result {Sample text}
+test button-1.233 {configuration option: "text" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -text "Sample text"
+ .c cget -text
+} -cleanup {
+ destroy .c
+} -result {Sample text}
+test button-1.234 {configuration option: "text" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -text "Sample text"
+ .r cget -text
+} -cleanup {
+ destroy .r
+} -result {Sample text}
+
+test button-1.235 {configuration option: "textvariable" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -textvariable i
+ .l cget -textvariable
+} -cleanup {
+ destroy .l
+} -result {i}
+test button-1.236 {configuration option: "textvariable" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -textvariable i
+ .b cget -textvariable
+} -cleanup {
+ destroy .b
+} -result {i}
+test button-1.237 {configuration option: "textvariable" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -textvariable i
+ .c cget -textvariable
+} -cleanup {
+ destroy .c
+} -result {i}
+test button-1.238 {configuration option: "textvariable" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -textvariable i
+ .r cget -textvariable
+} -cleanup {
+ destroy .r
+} -result {i}
+
+test button-1.239 {configuration option: "tristateimage" for checkbutton} -constraints {
+ testImageType
+} -setup {
+ image create test image1
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -tristateimage image1
+ .c cget -tristateimage
+} -cleanup {
+ destroy .c
+ image delete image1
+} -result {image1}
+test button-1.240 {configuration option: "tristateimage" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -tristateimage bogus
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {image "bogus" doesn't exist}
+test button-1.241 {configuration option: "tristateimage" for radiobutton} -constraints {
+ testImageType
+} -setup {
+ image create test image1
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -tristateimage image1
+ .r cget -tristateimage
+} -cleanup {
+ destroy .r
+ image delete image1
+} -result {image1}
+test button-1.242 {configuration option: "tristateimage" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -tristateimage bogus
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {image "bogus" doesn't exist}
+
+test button-1.243 {configuration option: "underline" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -underline 5
+ .l cget -underline
+} -cleanup {
+ destroy .l
+} -result {5}
+test button-1.244 {configuration option: "underline" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -underline 3p
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {expected integer but got "3p"}
+test button-1.245 {configuration option: "underline" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -underline 5
+ .b cget -underline
+} -cleanup {
+ destroy .b
+} -result {5}
+test button-1.246 {configuration option: "underline" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -underline 3p
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {expected integer but got "3p"}
+test button-1.247 {configuration option: "underline" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -underline 5
+ .c cget -underline
+} -cleanup {
+ destroy .c
+} -result {5}
+test button-1.248 {configuration option: "underline" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -underline 3p
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {expected integer but got "3p"}
+test button-1.249 {configuration option: "underline" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -underline 5
+ .r cget -underline
+} -cleanup {
+ destroy .r
+} -result {5}
+test button-1.250 {configuration option: "underline" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -underline 3p
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {expected integer but got "3p"}
+
+test button-1.251 {configuration option: "tristatevalue" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -tristatevalue unknowable
+ .c cget -tristatevalue
+} -cleanup {
+ destroy .c
+} -result {unknowable}
+test button-1.252 {configuration option: "tristatevalue" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -tristatevalue unknowable
+ .r cget -tristatevalue
+} -cleanup {
+ destroy .r
+} -result {unknowable}
+
+test button-1.253 {configuration option: "value" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -value anyString
+ .r cget -value
+} -cleanup {
+ destroy .r
+} -result {anyString}
+
+test button-1.254 {configuration option: "width" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -width 402
+ .l cget -width
+} -cleanup {
+ destroy .l
+} -result {402}
+test button-1.255 {configuration option: "width" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -width 3p
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {expected integer but got "3p"}
+test button-1.256 {configuration option: "width" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -width 402
+ .b cget -width
+} -cleanup {
+ destroy .b
+} -result {402}
+test button-1.257 {configuration option: "width" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -width 3p
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {expected integer but got "3p"}
+test button-1.258 {configuration option: "width" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -width 402
+ .c cget -width
+} -cleanup {
+ destroy .c
+} -result {402}
+test button-1.259 {configuration option: "width" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -width 3p
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {expected integer but got "3p"}
+test button-1.260 {configuration option: "width" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -width 402
+ .r cget -width
+} -cleanup {
+ destroy .r
+} -result {402}
+test button-1.261 {configuration option: "width" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -width 3p
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {expected integer but got "3p"}
+
+test button-1.262 {configuration option: "wraplength" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -wraplength 100
+ .l cget -wraplength
+} -cleanup {
+ destroy .l
+} -result {100}
+test button-1.263 {configuration option: "wraplength" for label} -setup {
+ label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .l
+ update
+} -body {
+ .l configure -wraplength 6x
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {bad screen distance "6x"}
+test button-1.264 {configuration option: "wraplength" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -wraplength 100
+ .b cget -wraplength
+} -cleanup {
+ destroy .b
+} -result {100}
+test button-1.265 {configuration option: "wraplength" for button} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .b
+ update
+} -body {
+ .b configure -wraplength 6x
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {bad screen distance "6x"}
+test button-1.266 {configuration option: "wraplength" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -wraplength 100
+ .c cget -wraplength
+} -cleanup {
+ destroy .c
+} -result {100}
+test button-1.267 {configuration option: "wraplength" for checkbutton} -setup {
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .c
+ update
+} -body {
+ .c configure -wraplength 6x
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {bad screen distance "6x"}
+test button-1.268 {configuration option: "wraplength" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -wraplength 100
+ .r cget -wraplength
+} -cleanup {
+ destroy .r
+} -result {100}
+test button-1.269 {configuration option: "wraplength" for radiobutton} -setup {
+ radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .r
+ update
+} -body {
+ .r configure -wraplength 6x
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {bad screen distance "6x"}
+
+test button-1.270 {configuration options} -body {
+# Additional check to make sure that -selectcolor may be empty in
+# checkbox widgets
+ checkbutton .c
+ .c configure -selectcolor {}
+} -cleanup {
+ destroy .c
+} -result {}
+
+# ex-tests 3.*
+test button-2.1 {ButtonCreate - not enough arguments} -body {
+ button
+} -returnCodes {error} -result {wrong # args: should be "button pathName ?-option value ...?"}
+
+test button-2.2 {ButtonCreate procedure - setting label class} -body {
+ label .x
+ winfo class .x
+} -cleanup {
+ destroy .x
+} -result {Label}
+test button-2.3 {ButtonCreate - setting button class} -body {
+ button .x
+ winfo class .x
+} -cleanup {
+ destroy .x
+} -result {Button}
+test button-2.4 {ButtonCreate - setting checkbutton class} -body {
+ checkbutton .x
+ winfo class .x
+} -cleanup {
+ destroy .x
+} -result {Checkbutton}
+test button-2.5 {ButtonCreate - setting radiobutton class} -body {
+ radiobutton .x
+ winfo class .x
+} -cleanup {
+ destroy .x
+} -result {Radiobutton}
+test button-2.6 {ButtonCreate - setting class} -body {
+ rename button gorp
+ gorp .x
+ winfo class .x
+} -cleanup {
+ destroy .x
+ rename gorp button
+} -result {Button}
+
+test button-2.7 {ButtonCreate - bad window name} -body {
+ button foo
+} -cleanup {
+ destroy foo
+} -returnCodes {error} -result {bad window path name "foo"}
+######### test ex 3.8
+test button-2.8 {ButtonCreate procedure - error in default option value} -body {
+ option add *funny.background bogus
+ button .funny
+} -cleanup {
+ option clear
+ destroy .funny
+} -returnCodes {error} -result {unknown color name "bogus"}
+test button-2.9 {ButtonCreate procedure - error in default option value} -body {
+ option add *funny.background bogus
+ catch {button .funny}
+ return $errorInfo
+} -cleanup {
+ option clear
+ destroy .funny
+} -result {unknown color name "bogus"
+ (database entry for "-background" in widget ".funny")
+ invoked from within
+"button .funny"}
+
+test button-2.10 {ButtonCreate procedure - option error} -body {
+ button .x -gorp foo
+} -cleanup {
+ destroy .x
+} -returnCodes {error} -result {unknown option "-gorp"}
+test button-2.11 {ButtonCreate procedure - option error} -body {
+ catch {button .x -gorp foo}
+ winfo exists .x
+} -cleanup {
+ destroy .x
+} -result 0
+######### ex 3.10
+test button-2.12 {ButtonCreate procedure - return value} -body {
+ set x [button .abcd]
+ return $x
+} -cleanup {
+ destroy .abcd
+} -result {.abcd}
+
+######### ex 4.*
+test button-3.1 {ButtonWidgetCmd - too few arguments} -body {
+ button .b
+ .b
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {wrong # args: should be ".b option ?arg ...?"}
+test button-3.2 {ButtonWidgetCmd - bad option name} -body {
+ button .b
+ .b c
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {ambiguous option "c": must be cget, configure, flash, or invoke}
+test button-3.3 {ButtonWidgetCmd - bad option name} -body {
+ button .b
+ .b bogus
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {bad option "bogus": must be cget, configure, flash, or invoke}
+test button-3.4 {ButtonWidgetCmd procedure, "cget" option} -body {
+ button .b
+ .b cget a b
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {wrong # args: should be ".b cget option"}
+test button-3.5 {ButtonWidgetCmd procedure, "cget" option} -body {
+ button .b
+ .b cget -gorp
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {unknown option "-gorp"}
+
+#ex 4.7
+test button-3.6 {ButtonWidgetCmd procedure, "cget" option} -body {
+ label .l
+ .l cget -disabledforeground
+} -cleanup {
+ destroy .l
+} -returnCodes {ok} -match {glob} -result {*}
+test button-3.7 {ButtonWidgetCmd procedure, "cget" option} -body {
+ button .b
+ .b cget -disabledforeground
+} -cleanup {
+ destroy .b
+} -returnCodes {ok} -match {glob} -result {*}
+test button-3.8 {ButtonWidgetCmd procedure, "cget" option} -body {
+ button .b
+ .b cget -variable
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {unknown option "-variable"}
+
+test button-3.9 {ButtonWidgetCmd procedure, "cget" option} -body {
+ checkbutton .c
+ .c cget -variable
+} -cleanup {
+ destroy .c
+} -returnCodes {ok} -match {glob} -result {*}
+test button-3.10 {ButtonWidgetCmd procedure, "cget" option} -body {
+ checkbutton .c
+ .c cget -value
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {unknown option "-value"}
+
+test button-3.11 {ButtonWidgetCmd procedure, "cget" option} -body {
+ radiobutton .r
+ .r cget -value
+} -cleanup {
+ destroy .r
+} -returnCodes {ok} -match {glob} -result {*}
+test button-3.12 {ButtonWidgetCmd procedure, "cget" option} -body {
+ radiobutton .r
+ .r cget -onvalue
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {unknown option "-onvalue"}
+
+# ex 4.6
+test button-3.13 {ButtonWidgetCmd procedure, "configure" option} -body {
+ button .b -highlightthickness 3
+ lindex [.b configure -highlightthickness] 4
+} -cleanup {
+ destroy .b
+} -result {3}
+test button-3.14 {ButtonWidgetCmd procedure, "configure" option} -body {
+ checkbutton .c
+ llength [.c configure]
+} -cleanup {
+ destroy .c
+} -result {41}
+test button-3.15 {ButtonWidgetCmd procedure, "configure" option} -body {
+ button .b
+ .b configure -gorp
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {unknown option "-gorp"}
+test button-3.16 {ButtonWidgetCmd procedure, "configure" option} -setup {
+ button .b
+} -body {
+ .b co -bg #ffffff -fg
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {value for "-fg" missing}
+test button-3.17 {ButtonWidgetCmd procedure, "configure" option} -setup {
+ button .b
+} -body {
+ .b configure -fg #123456
+ .b configure -bg #654321
+ lindex [.b configure -fg] 4
+} -cleanup {
+ destroy .b
+} -result {#123456}
+test button-3.18 {ButtonWidgetCmd procedure, "deselect" option} -body {
+ checkbutton .c
+ .c deselect foo
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {wrong # args: should be ".c deselect"}
+test button-3.19 {ButtonWidgetCmd procedure, "deselect" option} -body {
+ label .l
+ .l deselect
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {bad option "deselect": must be cget or configure}
+test button-3.20 {ButtonWidgetCmd procedure, "deselect" option} -body {
+ button .b
+ .b deselect
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {bad option "deselect": must be cget, configure, flash, or invoke}
+
+test button-3.21 {ButtonWidgetCmd procedure, "deselect" option} -body {
+ checkbutton .c -variable checkvar -onvalue 1 -offvalue 0
+ set checkvar 1
+ .c d
+ return $checkvar
+} -cleanup {
+ destroy .c
+} -result {0}
+test button-3.22 {ButtonWidgetCmd procedure, "deselect" option} -body {
+ radiobutton .r -variable radiovar -value red
+ set radiovar green
+ .r deselect
+ return $radiovar
+} -cleanup {
+ destroy .r
+} -result {green}
+test button-3.23 {ButtonWidgetCmd procedure, "deselect" option} -body {
+ radiobutton .r -variable radiovar -value red
+ set radiovar red
+ .r deselect
+ return $radiovar
+} -cleanup {
+ destroy .r
+} -result {}
+
+test button-3.24 {ButtonWidgetCmd procedure, "deselect" option} -body {
+ checkbutton .c -variable checkvar -onvalue 1 -offvalue 0
+ set checkvar 1
+ trace variable checkvar w bogusTrace
+ .c deselect
+} -cleanup {
+ destroy .c
+ trace vdelete checkvar w bogusTrace
+} -returnCodes {error} -result {can't set "checkvar": trace aborted}
+test button-3.25 {ButtonWidgetCmd procedure, "deselect" option} -body {
+ checkbutton .c -variable checkvar -onvalue 1 -offvalue 0
+ set checkvar 1
+ trace variable checkvar w bogusTrace
+ catch {.c deselect}
+ list $errorInfo $checkvar
+} -cleanup {
+ trace vdelete checkvar w bogusTrace
+ destroy .c
+} -match {glob} -result {{*trace aborted
+ while executing
+*
+".c deselect"} 0}
+test button-3.26 {ButtonWidgetCmd procedure, "deselect" option} -body {
+ radiobutton .r -variable radiovar -value red
+ set radiovar red
+ trace variable radiovar w bogusTrace
+ .r deselect
+} -cleanup {
+ destroy .r
+ trace vdelete radiovar w bogusTrace
+} -match {glob} -returnCodes {error} -result {can't set "radiovar": trace aborted}
+test button-3.27 {ButtonWidgetCmd procedure, "deselect" option} -body {
+ radiobutton .r -variable radiovar -value red
+ set radiovar red
+ trace variable radiovar w bogusTrace
+ catch {.r deselect}
+ list $errorInfo $radiovar
+} -cleanup {
+ destroy .r
+ trace vdelete radiovar w bogusTrace
+} -match glob -result {{*trace aborted
+ while executing
+*
+".r deselect"} {}}
+
+test button-3.28 {ButtonWidgetCmd procedure, "flash" option} -body {
+ button .b
+ .b flash foo
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {wrong # args: should be ".b flash"}
+test button-3.29 {ButtonWidgetCmd procedure, "flash" option} -body {
+ label .l
+ .l flash
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {bad option "flash": must be cget or configure}
+test button-3.30 {ButtonWidgetCmd procedure, "flash" option} -body {
+ button .b
+ catch {.b flash}
+} -cleanup {
+ destroy .b
+} -returnCodes {ok} -match {glob} -result {*}
+test button-3.31 {ButtonWidgetCmd procedure, "flash" option} -body {
+ checkbutton .c
+ catch {.c flash}
+} -cleanup {
+ destroy .c
+} -returnCodes {ok} -match {glob} -result {*}
+test button-3.32 {ButtonWidgetCmd procedure, "flash" option} -body {
+ radiobutton .r
+ catch {.r f}
+} -cleanup {
+ destroy .r
+} -returnCodes {ok} -match {glob} -result {*}
+
+test button-3.33 {ButtonWidgetCmd procedure, "invoke" option} -body {
+ label .l
+ .l invoke
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {bad option "invoke": must be cget or configure}
+test button-3.34 {ButtonWidgetCmd procedure, "invoke" option} -body {
+ button .b
+ .b invoke foo
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {wrong # args: should be ".b invoke"}
+test button-3.35 {ButtonWidgetCmd procedure, "invoke" option} -body {
+ button .b
+ .b configure -command {set x invoked}
+ set x "not invoked"
+ .b invoke
+ return $x
+} -cleanup {
+ destroy .b
+} -result {invoked}
+test button-3.36 {ButtonWidgetCmd procedure, "invoke" option} -body {
+ button .b
+ .b configure -command {set x invoked} -state disabled
+ set x "not invoked"
+ .b invoke
+ return $x
+} -cleanup {
+ destroy .b
+} -result {not invoked}
+test button-3.37 {ButtonWidgetCmd procedure, "invoke" option} -body {
+ checkbutton .c -variable checkvar -onvalue 1 -offvalue 0 \
+ -command {set x invoked}
+ set checkvar bogus
+ set x "not invoked"
+ .c invoke
+ list $x $checkvar
+} -cleanup {
+ destroy .c
+} -result {invoked 1}
+test button-3.38 {ButtonWidgetCmd procedure, "invoke" option} -body {
+ radiobutton .r -command {set x invoked} -variable radiovar -value red
+ set radiovar green
+ set x "not invoked"
+ .r i
+ list $x $radiovar
+} -cleanup {
+ destroy .r
+} -result {invoked red}
+
+test button-3.39 {ButtonWidgetCmd procedure, "select" option} -body {
+ label .l
+ .l select
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {bad option "select": must be cget or configure}
+test button-3.40 {ButtonWidgetCmd procedure, "select" option} -body {
+ button .b
+ .b select
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {bad option "select": must be cget, configure, flash, or invoke}
+test button-3.41 {ButtonWidgetCmd procedure, "select" option} -body {
+ checkbutton .c
+ .c select foo
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {wrong # args: should be ".c select"}
+test button-3.42 {ButtonWidgetCmd procedure, "select" option} -body {
+ checkbutton .c -variable checkvar -onvalue lovely -offvalue 0
+ set checkvar bogus
+ .c s
+ return $checkvar
+} -cleanup {
+ destroy .c
+} -result {lovely}
+test button-3.43 {ButtonWidgetCmd procedure, "select" option} -body {
+ radiobutton .r -variable radiovar -value red
+ set radiovar green
+ .r select
+ return $radiovar
+} -cleanup {
+ destroy .r
+} -result {red}
+test button-3.44 {ButtonWidgetCmd procedure, "select" option} -body {
+ radiobutton .r -variable radiovar -value red
+ set radiovar yellow
+ trace variable radiovar w bogusTrace
+ .r select
+} -cleanup {
+ destroy .r
+ trace vdelete radiovar w bogusTrace
+} -returnCodes {error} -result {can't set "radiovar": trace aborted}
+test button-3.45 {ButtonWidgetCmd procedure, "select" option} -body {
+ radiobutton .r -variable radiovar -value red
+ set radiovar yellow
+ trace variable radiovar w bogusTrace
+ catch {.r select}
+ list $errorInfo $radiovar
+} -cleanup {
+ destroy .r
+ trace vdelete radiovar w bogusTrace
+} -match {glob} -result {{*trace aborted
+ while executing
+*
+".r select"} red}
+
+# ex 4.43
+test button-3.46 {ButtonWidgetCmd procedure, "toggle" option} -body {
+ label .l
+ .l toggle
+} -cleanup {
+ destroy .l
+} -returnCodes {error} -result {bad option "toggle": must be cget or configure}
+test button-3.47 {ButtonWidgetCmd procedure, "toggle" option} -body {
+ button .b
+ .b toggle
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {bad option "toggle": must be cget, configure, flash, or invoke}
+test button-3.48 {ButtonWidgetCmd procedure, "toggle" option} -body {
+ radiobutton .r
+ .r toggle
+} -cleanup {
+ destroy .r
+} -returnCodes {error} -result {bad option "toggle": must be cget, configure, deselect, flash, invoke, or select}
+test button-3.49 {ButtonWidgetCmd procedure, "toggle" option} -body {
+ checkbutton .c
+ .c toggle foo
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {wrong # args: should be ".c toggle"}
+test button-3.50 {ButtonWidgetCmd procedure, "toggle" option} -body {
+ set checkvar bogus
+ checkbutton .c -variable checkvar -onvalue sunshine -offvalue rain
+ .c toggle
+ set result $checkvar
+ .c toggle
+ lappend result $checkvar
+ .c toggle
+ lappend result $checkvar
+ return $result
+} -cleanup {
+ destroy .c
+} -result {sunshine rain sunshine}
+test button-3.51 {ButtonWidgetCmd procedure, "toggle" option} -body {
+ checkbutton .c -variable checkvar -onvalue xyz -offvalue abc
+ set checkvar xyz
+ trace variable checkvar w bogusTrace
+ .c toggle
+} -cleanup {
+ destroy .c
+ trace vdelete checkvar w bogusTrace
+} -returnCodes {error} -result {can't set "checkvar": trace aborted}
+test button-3.52 {ButtonWidgetCmd procedure, "toggle" option} -body {
+ checkbutton .c -variable checkvar -onvalue xyz -offvalue abc
+ set checkvar xyz
+ trace variable checkvar w bogusTrace
+ catch {.c toggle}
+ list $errorInfo $checkvar
+} -cleanup {
+ trace vdelete checkvar w bogusTrace
+ destroy .c
+} -match {glob} -result {{*trace aborted
+ while executing
+*
+".c toggle"} abc}
+test button-3.53 {ButtonWidgetCmd procedure, "toggle" option} -body {
+ checkbutton .c -variable checkvar -onvalue xyz -offvalue abc
+ set checkvar abc
+ trace variable checkvar w bogusTrace
+ .c toggle
+} -cleanup {
+ trace vdelete checkvar w bogusTrace
+ destroy .c
+} -returnCodes {error} -result {can't set "checkvar": trace aborted}
+test button-3.54 {ButtonWidgetCmd procedure, "toggle" option} -body {
+ checkbutton .c -variable checkvar -onvalue xyz -offvalue abc
+ set checkvar abc
+ trace variable checkvar w bogusTrace
+ catch {.c toggle}
+ list $errorInfo $checkvar
+} -cleanup {
+ trace vdelete checkvar w bogusTrace
+ destroy .c
+} -match {glob} -result {{*trace aborted
+ while executing
+*
+".c toggle"} xyz}
+test button-3.55 {ButtonWidgetCmd procedure, "toggle" option} -setup {
+ unset -nocomplain checkvar
+} -body {
+ checkbutton .c -variable checkvar -onvalue xyz -offvalue abc
+ unset checkvar
+ set checkvar(1) 1
+ .c toggle
+} -cleanup {
+ destroy .c
+} -returnCodes {error} -result {can't set "checkvar": variable is array}
+test button-3.56 {ButtonWidgetCmd procedure, "toggle" option} -setup {
+ unset -nocomplain checkvar
+} -body {
+ checkbutton .c -variable checkvar -onvalue xyz -offvalue abc
+ unset checkvar
+ set checkvar(1) 1
+ catch {.c toggle}
+ return $errorInfo
+} -cleanup {
+ destroy .c
+} -match {glob} -result {can't set "checkvar": variable is array
+ while executing
+".c toggle"}
+
+test button-4.1 {DestroyButton procedure} -constraints {
+ testImageType
+} -setup {
+ image create test image1
+ unset -nocomplain x
+} -body {
+ button .b1 -image image1
+ button .b2 -fg #ff0000 -text "Button 2"
+ button .b3 -state active -text "Button 3"
+ button .b4 -disabledforeground #0000ff -state disabled -text "Button 4"
+ checkbutton .b5 -variable x -text "Checkbutton 5"
+ set x 1
+ pack .b1 .b2 .b3 .b4 .b5
+ update
+ deleteWindows
+} -cleanup {
+ destroy .b1 .b2 .b3 .b4 .b5
+ image delete image1
+} -result {}
+
+test button-5.1 {ConfigureButton - textvariable trace} -body {
+ button .b -bd 4 -bg green
+ .b configure -bd 7 -bg red -fg bogus
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {unknown color name "bogus"}
+test button-5.2 {ConfigureButton - textvariable trace} -body {
+ button .b -bd 4 -bg green
+ catch {.b configure -bd 7 -bg red -fg bogus}
+ list [.b cget -bd] [.b cget -bg]
+} -cleanup {
+ destroy .b
+} -result {4 green}
+test button-5.3 {ConfigureButton - textvariable trace} -body {
+ button .b -textvariable x
+ set x From-x
+ set y From-y
+ .b configure -textvariable y
+ set x New
+ lindex [.b configure -text] 4
+} -cleanup {
+ destroy .b
+} -result {From-y}
+test button-5.4 {ConfigureButton - variable trace} -body { ;# ex 6.2a
+ checkbutton .c -variable x
+ set x 1
+ set y 1
+ .c configure -textvariable y
+ set x 0
+ .c toggle
+ return $y
+} -cleanup {
+ destroy .c
+} -result {1}
+
+test button-5.5 {ConfigureButton - image handling} -constraints {
+ testImageType
+} -setup {
+ imageCleanup
+ image create test image1
+ image create test image2
+} -body {
+ button .b -image image1
+ image delete image1
+ .b configure -image image2
+ imageNames
+} -cleanup {
+ destroy .b
+ imageCleanup
+} -result {image2}
+
+test button-5.6 {ConfigureButton - default value for variable} -body {
+ checkbutton .c
+ .c cget -variable
+} -cleanup {
+ destroy .c
+} -result {c}
+test button-5.7 {ConfigureButton - setting selected state from variable} -body {
+ set x 0
+ set y Shiny
+ checkbutton .c -variable x
+ .c configure -variable y -onvalue Shiny
+ .c toggle
+ return $y
+} -cleanup {
+ destroy .c
+} -result {0}
+test button-5.8 {ConfigureButton - setting selected state from variable} -setup {
+ unset -nocomplain x
+} -body {
+ checkbutton .c -variable x -offvalue Bogus
+ return $x
+} -cleanup {
+ destroy .c
+} -result {Bogus}
+
+test button-5.9 {ConfigureButton - setting selected state from variable} -setup {
+ unset -nocomplain x
+} -body {
+ radiobutton .r -variable x
+ return $x
+} -cleanup {
+ destroy .r
+} -result {}
+
+test button-5.10 {ConfigureButton - error in setting variable} -setup {
+ unset -nocomplain x
+} -body {
+ trace variable x w bogusTrace
+ radiobutton .r -variable x
+} -cleanup {
+ destroy .r
+ trace vdelete x w bogusTrace
+} -returnCodes {error} -result {can't set "x": trace aborted}
+
+test button-5.11 {ConfigureButton - bad image name} -body {
+ button .b -image bogus
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {image "bogus" doesn't exist}
+
+test button-5.12 {ConfigureButton - setting variable from current text value} -setup {
+ unset -nocomplain x
+} -body {
+ button .b -textvariable x -text "Button 1"
+ return $x
+} -cleanup {
+ destroy .b
+} -result {Button 1}
+
+test button-5.13 {ConfigureButton - using current value of variable} -body {
+ set x Override
+ button .b -textvariable x -text "Button 1"
+ return $x
+} -cleanup {
+ destroy .b
+} -result {Override}
+
+test button-5.14 {ConfigureButton - variable handling} -setup {
+ unset -nocomplain x
+} -body {
+ trace variable x w bogusTrace
+ radiobutton .r -text foo -textvariable x
+} -cleanup {
+ trace vdelete x w bogusTrace
+ destroy .r
+} -returnCodes {error} -result {can't set "x": trace aborted}
+test button-5.15 {ConfigureButton - variable handling} -setup {
+ unset -nocomplain x
+} -body {
+ trace variable x w bogusTrace
+ catch {radiobutton .r -text foo -textvariable x}
+ return $x
+} -cleanup {
+ trace vdelete x w bogusTrace
+ destroy .r
+} -result {foo}
+
+#ex 6.14
+test button-5.16 {ConfigureButton - -width option} -body {
+ button .b -text "Button 1"
+ .b configure -width 1i
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {expected integer but got "1i"}
+test button-5.17 {ConfigureButton - -width option} -body {
+ button .b -text "Button 1"
+ catch {.b configure -width 1i}
+ return $errorInfo
+} -cleanup {
+ destroy .b
+} -result {expected integer but got "1i"
+ (processing -width option)
+ invoked from within
+".b configure -width 1i"}
+test button-5.18 {ConfigureButton - -height option} -body {
+ button .b -text "Button 1"
+ .b configure -height 0.5c
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {expected integer but got "0.5c"}
+test button-5.19 {ConfigureButton - -height option} -body {
+ button .b -text "Button 1"
+ catch {.b configure -height 0.5c}
+ return $errorInfo
+} -cleanup {
+ destroy .b
+} -result {expected integer but got "0.5c"
+ (processing -height option)
+ invoked from within
+".b configure -height 0.5c"}
+#ex 6.16
+test button-5.20 {ConfigureButton - -width option} -body {
+ button .b -bitmap questhead
+ .b configure -width abc
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {bad screen distance "abc"}
+test button-5.21 {ConfigureButton - -width option} -body {
+ button .b -bitmap questhead
+ catch {.b configure -width abc}
+ return $errorInfo
+} -cleanup {
+ destroy .b
+} -result {bad screen distance "abc"
+ (processing -width option)
+ invoked from within
+".b configure -width abc"}
+test button-5.22 {ConfigureButton - -height option} -constraints {
+ testImageType
+} -setup {
+ image create test image1
+} -body {
+ button .b -image image1
+ .b configure -height 0.5x
+} -cleanup {
+ destroy .b
+ image delete image1
+} -returnCodes {error} -result {bad screen distance "0.5x"}
+test button-5.23 {ConfigureButton - -height option} -constraints {
+ testImageType
+} -setup {
+ image create test image1
+} -body {
+#ztestImageType
+ button .b -image image1
+ catch {.b configure -height 0.5x}
+ return $errorInfo
+} -cleanup {
+ destroy .b
+ image delete image1
+} -result {bad screen distance "0.5x"
+ (processing -height option)
+ invoked from within
+".b configure -height 0.5x"}
+#ex 6.18
+test button-5.24 {ConfigureButton - computing geometry} -constraints {
+ fonts
+} -body {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \
+ -padx 30 -pady 20
+ # 1. button with text
+ .b configure -text "Sample text"
+ pack .b
+ set textwidth [font measure [.b cget -font] -displayof .b [.b cget -text]]
+ set expectedwidth [expr {$textwidth + 2*[.b cget -borderwidth] \
+ + 2*[.b cget -highlightthickness] + 2*[.b cget -padx]}]
+ incr expectedwidth 2 ; # added (hardcoded) in tkUnixButton.c
+ set result [expr {$expectedwidth == [winfo reqwidth .b]}]
+ set linespace [lindex [font metrics [.b cget -font] -displayof .b] 5]
+ set expectedheight [expr {$linespace + 2*[.b cget -borderwidth] \
+ + 2*[.b cget -highlightthickness] + 2*[.b cget -pady]}]
+ incr expectedheight 2 ; # added (hardcoded) in tkUnixButton.c
+ lappend result [expr {$expectedheight == [winfo reqheight .b]}]
+ # 2. button with a bitmap image
+ # there is no access to characteristics the predefined bitmaps,
+ # so define one as an image (copied from questhead.xbm)
+ set myquesthead [image create bitmap -data {
+ #define myquesthead_width 20
+ #define myquesthead_height 22
+ static unsigned char myquesthead_bits[] = {
+ 0xf8, 0x1f, 0x00, 0xac, 0x2a, 0x00, 0x56, 0x55, 0x00, 0xeb, 0xaf, 0x00,
+ 0xf5, 0x5f, 0x01, 0xfb, 0xbf, 0x00, 0x75, 0x5d, 0x01, 0xfb, 0xbe, 0x02,
+ 0x75, 0x5d, 0x05, 0xab, 0xbe, 0x0a, 0x55, 0x5f, 0x07, 0xab, 0xaf, 0x00,
+ 0xd6, 0x57, 0x01, 0xac, 0xab, 0x00, 0xd8, 0x57, 0x00, 0xb0, 0xaa, 0x00,
+ 0x50, 0x55, 0x00, 0xb0, 0x0b, 0x00, 0xd0, 0x17, 0x00, 0xb0, 0x0b, 0x00,
+ 0x58, 0x15, 0x00, 0xa8, 0x2a, 0x00};
+ }]
+ .b configure -image $myquesthead
+ set expectedwidth [expr {[image width $myquesthead] + 2*[.b cget -borderwidth] \
+ + 2*[.b cget -highlightthickness]}]
+ incr expectedwidth 2 ; # added (hardcoded) in tkUnixButton.c
+ lappend result [expr {$expectedwidth == [winfo reqwidth .b]}]
+ set expectedheight [expr {[image height $myquesthead] + 2*[.b cget -borderwidth] \
+ + 2*[.b cget -highlightthickness]}]
+ incr expectedheight 2 ; # added (hardcoded) in tkUnixButton.c
+ lappend result [expr {$expectedheight == [winfo reqheight .b]}]
+} -cleanup {
+ destroy .b
+} -result {1 1 1 1}
+
+test button-5.25 {ConfigureButton - computing geometry} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+} -body {
+ .b configure -text "Button 1"
+ set old [winfo reqwidth .b]
+ .b configure -text "Much longer text"
+ set new [winfo reqwidth .b]
+ expr {$old == $new}
+} -cleanup {
+ destroy .b
+} -result {0}
+
+test button-6.1 {ButtonEventProc procedure} -body {
+ button .b -text "Test Button" -command {
+ destroy .b
+ set x [list [winfo exists .b] [info commands .b]]
+}
+ .b invoke
+ return $x
+} -cleanup {
+ destroy .b
+} -result {0 {}}
+
+test button-6.2 {ButtonEventProc procedure} -setup {
+ set x {}
+} -body {
+ button .b1 -bg #543210
+ rename .b1 .b2
+ lappend x [winfo children .]
+ lappend x [.b2 cget -bg]
+ destroy .b1
+ lappend x [info command .b*] [winfo children .]
+} -cleanup {
+ destroy .b1
+} -result {.b1 #543210 {} {}}
+
+test button-7.1 {ButtonCmdDeletedProc procedure} -body {
+ button .b
+ rename .b {}
+ list [info command .b*] [winfo children .]
+} -cleanup {
+ destroy .b
+} -result {{} {}}
+
+test button-8.1 {TkInvokeButton procedure} -setup {
+ set x 0
+} -body {
+ checkbutton .c -variable x
+ set result $x
+ .c invoke
+ lappend result $x
+ .c invoke
+ lappend result $x
+} -cleanup {
+ destroy .c
+} -result {0 1 0}
+
+test button-8.2 {TkInvokeButton procedure} -setup {
+ set x 0
+} -body {
+ checkbutton .c -variable x
+ trace variable x w bogusTrace
+ .c invoke
+} -cleanup {
+ destroy .c
+ trace vdelete x w bogusTrace
+} -returnCodes {error} -result {can't set "x": trace aborted}
+test button-8.3 {TkInvokeButton procedure} -setup {
+ set x 0
+} -body {
+ checkbutton .c -variable x
+ trace variable x w bogusTrace
+ catch {.c invoke}
+ return $x
+} -cleanup {
+ destroy .c
+ trace vdelete x w bogusTrace
+} -result {1}
+test button-8.4 {TkInvokeButton procedure} -setup {
+ set x 1
+} -body {
+ checkbutton .c -variable x
+ trace variable x w bogusTrace
+ .c invoke
+} -cleanup {
+ destroy .c
+ trace vdelete x w bogusTrace
+} -returnCodes {error} -result {can't set "x": trace aborted}
+test button-8.5 {TkInvokeButton procedure} -setup {
+ set x 1
+} -body {
+ checkbutton .c -variable x
+ trace variable x w bogusTrace
+ catch {.c invoke}
+ return $x
+} -cleanup {
+ destroy .c
+ trace vdelete x w bogusTrace
+} -result {0}
+
+test button-8.6 {TkInvokeButton procedure} -setup {
+ set x 0
+} -body {
+ radiobutton .r -variable x -value red
+ set result $x
+ .r invoke
+ lappend result $x
+ .r invoke
+ lappend result $x
+} -cleanup {
+ destroy .r
+} -result {0 red red}
+
+test button-8.7 {TkInvokeButton procedure} -body {
+ radiobutton .r -variable x -value red
+ set x green
+ trace variable x w bogusTrace
+ .r invoke
+} -cleanup {
+ destroy .r
+ trace vdelete x w bogusTrace
+} -returnCodes {error} -result {can't set "x": trace aborted}
+test button-8.8 {TkInvokeButton procedure} -body {
+ radiobutton .r -variable x -value red
+ set x green
+ trace variable x w bogusTrace
+ catch {.r invoke}
+ list $errorInfo $x
+} -cleanup {
+ destroy .r
+ trace vdelete x w bogusTrace
+} -match {glob} -result {{*trace aborted
+ while executing
+*
+".r invoke"} red}
+
+#ex 9.6
+test button-8.9 {TkInvokeButton procedure} -setup {
+ set result untouched
+} -body {
+ button .b -command {set result invoked}
+ set msg [.b invoke]
+ list $msg $result
+} -cleanup {
+ destroy .b
+} -result {invoked invoked}
+test button-8.10 {TkInvokeButton procedure} -setup {
+ set result untouched
+ set x 0
+} -body {
+ checkbutton .c -variable x -command {set result "invoked $x"}
+ set msg [.c invoke]
+ list $msg $result
+} -cleanup {
+ destroy .c
+} -result {{invoked 1} {invoked 1}}
+test button-8.11 {TkInvokeButton procedure} -setup {
+ set result untouched
+ set x 0
+} -body {
+ radiobutton .r -variable x -value red -command {set result "invoked $x"}
+ set msg [.r invoke]
+ list $msg $result
+} -cleanup {
+ destroy .r
+} -result {{invoked red} {invoked red}}
+
+test button-9.1 {ButtonVarProc procedure} -body {
+ set x 1
+ checkbutton .c -variable x
+ unset x
+ set result [info exists x]
+ .c toggle
+ lappend result $x
+ set x 0
+ .c toggle
+ lappend result $x
+} -cleanup {
+ destroy .c
+} -result {0 1 1}
+test button-9.2 {ButtonVarProc procedure} -body {
+ set x 0
+ checkbutton .c -variable x
+ set x 44
+ .c toggle
+ return $x
+} -cleanup {
+ destroy .c
+} -result {1}
+test button-9.3 {ButtonVarProc procedure} -setup {
+ set x 1
+} -body {
+ checkbutton .c -variable x
+ set x 44
+ .c toggle
+ return $x
+} -cleanup {
+ destroy .c
+} -result {1}
+test button-9.4 {ButtonVarProc procedure} -setup {
+ set x 0
+} -body {
+ checkbutton .c -variable x
+ set x 1
+ .c toggle
+ return $x
+} -cleanup {
+ destroy .c
+} -result {0}
+test button-9.5 {ButtonVarProc procedure} -setup {
+ set x 1
+} -body {
+ checkbutton .c -variable x
+ set x 1
+ .c toggle
+ return $x
+} -cleanup {
+ destroy .c
+} -result {0}
+test button-9.6 {ButtonVarProc procedure} -setup {
+ set x 0
+} -body {
+ checkbutton .c -variable x
+ set x 0
+ .c toggle
+ return $x
+} -cleanup {
+ destroy .c
+} -result {1}
+test button-9.7 {ButtonVarProc procedure} -setup {
+ set x 1
+} -body {
+ checkbutton .c -variable x
+ set x 0
+ .c toggle
+ return $x
+} -cleanup {
+ destroy .c
+} -result {1}
+test button-9.8 {ButtonVarProc procedure, can't read variable} -setup {
+# This test does nothing but produce a core dump if there's a prbblem.
+ unset -nocomplain a
+} -body {
+ checkbutton .c -variable a
+ unset a
+ set a(32) 0
+ unset a
+} -cleanup {
+ destroy .c
+} -result {}
+
+test button-10.1 {ButtonTextVarProc procedure} -body {
+ set x Label
+ button .b -textvariable x
+ unset x
+ set result [list $x [.b cget -text]]
+ set x New
+ lappend result [.b cget -text]
+} -cleanup {
+ destroy .b
+} -result {Label Label New}
+test button-10.2 {ButtonTextVarProc procedure} -setup {
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+} -body {
+# Windows buttons have a default min width, so we have to
+# set this to be longer to force the wider button.
+ set x ExtraLongLabel
+ .b configure -textvariable x
+ set old [winfo reqwidth .b]
+ set x New
+ set new [winfo reqwidth .b]
+ expr {$old == $new}
+} -cleanup {
+ destroy .b
+} -result {0}
+
+test button-11.1 {ButtonImageProc procedure} -constraints {
+ testImageType
+} -setup {
+ label .l -highlightthickness 0 -font {Helvetica -12 bold}
+ image create test image1
+} -body {
+ .l configure -image image1 -padx 0 -pady 0 -bd 0
+ pack .l
+ set result "[winfo reqwidth .l] [winfo reqheight .l]"
+ image1 changed 0 0 0 0 80 100
+ lappend result [winfo reqwidth .l] [winfo reqheight .l]
+} -cleanup {
+ destroy .l
+ image delete image1
+} -result {30 15 80 100}
+
+test button-12.1 {button widget vs hidden commands} -body {
+ button .b -text hello
+ set l [interp hidden]
+ interp hide {} .b
+ destroy .b
+
+ set res1 [list [winfo children .] [interp hidden]]
+ set res2 [list {} $l]
+ expr {$res1 == $res2}
+} -cleanup {
+ destroy .b
+} -result {1}
+
+test button-13.1 {size behavior: label} -setup {
+ label .a -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ label .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ label .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ set result {}
+} -body {
+ .a configure -text Hej
+ .b configure -text Hej -width 10 -height 1
+ .c configure -text "" -width 10 -height 1
+
+# With -width, width should not be affected by text change
+ lappend result [expr {[winfo reqwidth .b] == [winfo reqwidth .c]}]
+# With -height, height should not be affected by text change
+ lappend result [expr {[winfo reqheight .b] == [winfo reqheight .c]}]
+# A one line text should be as high as -height 1
+ lappend result [expr {[winfo reqheight .a] == [winfo reqheight .b]}]
+} -cleanup {
+ destroy .a .b .c
+} -result {1 1 1}
+test button-13.2 {size behavior: label} -setup {
+ label .a -borderwidth 2 -highlightthickness 2 -font {Arial 20}
+ label .b -borderwidth 2 -highlightthickness 2 -font {Arial 20}
+ label .c -borderwidth 2 -highlightthickness 2 -font {Arial 20}
+ set result {}
+} -body {
+ .a configure -text Hej
+ .b configure -text Hej -width 10 -height 1
+ .c configure -text "" -width 10 -height 1
+
+# With -width, width should not be affected by text change
+ lappend result [expr {[winfo reqwidth .b] == [winfo reqwidth .c]}]
+# With -height, height should not be affected by text change
+ lappend result [expr {[winfo reqheight .b] == [winfo reqheight .c]}]
+# A one line text should be as high as -height 1
+ lappend result [expr {[winfo reqheight .a] == [winfo reqheight .b]}]
+} -cleanup {
+ destroy .a .b .c
+} -result {1 1 1}
+
+test button-13.3 {size behavior: button} -setup {
+ button .a -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ button .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ set result {}
+} -body {
+ .a configure -text Hej
+ .b configure -text Hej -width 10 -height 1
+ .c configure -text "" -width 10 -height 1
+
+# With -width, width should not be affected by text change
+ lappend result [expr {[winfo reqwidth .b] == [winfo reqwidth .c]}]
+# With -height, height should not be affected by text change
+ lappend result [expr {[winfo reqheight .b] == [winfo reqheight .c]}]
+# A one line text should be as high as -height 1
+ lappend result [expr {[winfo reqheight .a] == [winfo reqheight .b]}]
+} -cleanup {
+ destroy .a .b .c
+} -result {1 1 1}
+test button-13.4 {size behavior: button} -setup {
+ button .a -borderwidth 2 -highlightthickness 2 -font {Arial 20}
+ button .b -borderwidth 2 -highlightthickness 2 -font {Arial 20}
+ button .c -borderwidth 2 -highlightthickness 2 -font {Arial 20}
+ set result {}
+} -body {
+ .a configure -text Hej
+ .b configure -text Hej -width 10 -height 1
+ .c configure -text "" -width 10 -height 1
+
+# With -width, width should not be affected by text change
+ lappend result [expr {[winfo reqwidth .b] == [winfo reqwidth .c]}]
+# With -height, height should not be affected by text change
+ lappend result [expr {[winfo reqheight .b] == [winfo reqheight .c]}]
+# A one line text should be as high as -height 1
+ lappend result [expr {[winfo reqheight .a] == [winfo reqheight .b]}]
+} -cleanup {
+ destroy .a .b .c
+} -result {1 1 1}
+
+test button-13.5 {size behavior: radiobutton} -setup {
+ radiobutton .a -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ radiobutton .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ radiobutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ set result {}
+} -body {
+ .a configure -text Hej
+ .b configure -text Hej -width 10 -height 1
+ .c configure -text "" -width 10 -height 1
+
+# With -width, width should not be affected by text change
+ lappend result [expr {[winfo reqwidth .b] == [winfo reqwidth .c]}]
+# With -height, height should not be affected by text change
+ lappend result [expr {[winfo reqheight .b] == [winfo reqheight .c]}]
+# A one line text should be as high as -height 1
+ lappend result [expr {[winfo reqheight .a] == [winfo reqheight .b]}]
+} -cleanup {
+ destroy .a .b .c
+} -result {1 1 1}
+
+test button-13.6 {size behavior: radiobutton} -setup {
+ radiobutton .a -borderwidth 2 -highlightthickness 2 -font {Arial 20}
+ radiobutton .b -borderwidth 2 -highlightthickness 2 -font {Arial 20}
+ radiobutton .c -borderwidth 2 -highlightthickness 2 -font {Arial 20}
+ set result {}
+} -body {
+ .a configure -text Hej
+ .b configure -text Hej -width 10 -height 1
+ .c configure -text "" -width 10 -height 1
+
+# With -width, width should not be affected by text change
+ lappend result [expr {[winfo reqwidth .b] == [winfo reqwidth .c]}]
+# With -height, height should not be affected by text change
+ lappend result [expr {[winfo reqheight .b] == [winfo reqheight .c]}]
+# A one line text should be as high as -height 1
+ lappend result [expr {[winfo reqheight .a] == [winfo reqheight .b]}]
+} -cleanup {
+ destroy .a .b .c
+} -result {1 1 1}
+
+test button-13.7 {size behavior: checkbutton} -setup {
+ checkbutton .a -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ checkbutton .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ set result {}
+} -body {
+ .a configure -text Hej
+ .b configure -text Hej -width 10 -height 1
+ .c configure -text "" -width 10 -height 1
+
+# With -width, width should not be affected by text change
+ lappend result [expr {[winfo reqwidth .b] == [winfo reqwidth .c]}]
+# With -height, height should not be affected by text change
+ lappend result [expr {[winfo reqheight .b] == [winfo reqheight .c]}]
+# A one line text should be as high as -height 1
+ lappend result [expr {[winfo reqheight .a] == [winfo reqheight .b]}]
+} -cleanup {
+ destroy .a .b .c
+} -result {1 1 1}
+
+test button-13.8 {size behavior: checkbutton} -setup {
+ checkbutton .a -borderwidth 2 -highlightthickness 2 -font {Arial 20}
+ checkbutton .b -borderwidth 2 -highlightthickness 2 -font {Arial 20}
+ checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Arial 20}
+ set result {}
+} -body {
+ .a configure -text Hej
+ .b configure -text Hej -width 10 -height 1
+ .c configure -text "" -width 10 -height 1
+
+# With -width, width should not be affected by text change
+ lappend result [expr {[winfo reqwidth .b] == [winfo reqwidth .c]}]
+# With -height, height should not be affected by text change
+ lappend result [expr {[winfo reqheight .b] == [winfo reqheight .c]}]
+# A one line text should be as high as -height 1
+ lappend result [expr {[winfo reqheight .a] == [winfo reqheight .b]}]
+} -cleanup {
+ destroy .a .b .c
+} -result {1 1 1}
+
+test button-14.1 {bug fix: [011706ec42] tk::ButtonInvoke unsafe wrt widget destruction} -body {
+ proc destroy_button {} {
+ if {[winfo exists .top.b]} {
+ destroy .top.b
+ }
+ }
+ toplevel .top
+ button .top.b -text Foo -command destroy_button
+ bind .top.b <space> destroy_button
+ pack .top.b
+ focus -force .top.b
+ update
+ event generate .top.b <space>
+ update ; # shall not trigger error invalid command name ".top.b"
+} -cleanup {
+ destroy .top.b .top
+} -result {}
+
+test button-15.1 {Bug [5d991b822e]} {
+ # Want this not to segfault
+ set var INIT
+ button .b -textvariable var
+ trace add variable var unset {apply {args {
+ .b configure -textvariable {}
+ }}}
+ pack .b
+ bind .b <Configure> {unset var}
+ update
+ destroy .b
+} {}
+test button-15.2 {Bug [5d991b822e]} {
+ # Want this not to leak traces
+ set var INIT
+ button .b -textvariable var
+ trace add variable var unset {apply {args {
+ .b configure -textvariable new
+ }}}
+ pack .b
+ bind .b <Configure> {unset -nocomplain var}
+ update
+ destroy .b
+ unset new
+} {}
+test button-15.3 {Bug [5d991b822e]} {
+ # Want this not to leak traces
+ set var INIT
+ checkbutton .b -variable var
+ trace add variable var unset {apply {args {
+ .b configure -variable {}
+ }}}
+ pack .b
+ bind .b <Configure> {unset var}
+ update
+ destroy .b
+} {}
+
+
+imageFinish
+cleanupTests
+return
+
+# Local variables:
+# mode: tcl
+# End:
diff --git a/tk8.6/tests/canvImg.test b/tk8.6/tests/canvImg.test
new file mode 100644
index 0000000..36e937d
--- /dev/null
+++ b/tk8.6/tests/canvImg.test
@@ -0,0 +1,818 @@
+# This file is a Tcl script to test out the procedures in tkCanvImg.c,
+# which implement canvas "image" items. It is organized in the standard
+# fashion for Tcl tests.
+#
+# Copyright (c) 1994 The Regents of the University of California.
+# Copyright (c) 1994-1996 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+imageInit
+
+# Canvas used in every test case of the whole file
+canvas .c
+pack .c
+update
+
+
+test canvImg-1.1 {options for image items} -body {
+ .c create image 50 50 -anchor nw -tags i1
+ .c itemconfigure i1 -anchor
+} -cleanup {
+ .c delete all
+} -result {-anchor {} {} center nw}
+test canvImg-1.2 {options for image items} -body {
+ .c create image 50 50 -anchor gorp -tags i1
+} -cleanup {
+ .c delete all
+} -returnCodes {error} -result {bad anchor position "gorp": must be n, ne, e, se, s, sw, w, nw, or center}
+test canvImg-1.3 {options for image items} -constraints testImageType -setup {
+ image create test foo
+ .c delete all
+} -body {
+ .c create image 50 50 -image foo -tags i1
+ .c itemconfigure i1 -image
+} -cleanup {
+ .c delete all
+ image delete foo
+} -result {-image {} {} {} foo}
+test canvImg-1.4 {options for image items} -body {
+ .c create image 50 50 -image unknown -tags i1
+} -cleanup {
+ .c delete all
+} -returnCodes {error} -result {image "unknown" doesn't exist}
+test canvImg-1.5 {options for image items} -constraints testImageType -setup {
+ image create test foo
+ .c delete all
+} -body {
+ .c create image 50 50 -image foo -tags {i1 foo}
+ .c itemconfigure i1 -tags
+} -cleanup {
+ .c delete all
+ image delete foo
+} -result {-tags {} {} {} {i1 foo}}
+
+test canvImg-2.1 {CreateImage procedure} -body {
+ .c create image 40
+} -cleanup {
+ .c delete all
+} -returnCodes {error} -result {wrong # coordinates: expected 2, got 1}
+test canvImg-2.2 {CreateImage procedure} -body {
+ .c create image 40 50 60
+} -cleanup {
+ .c delete all
+} -returnCodes {error} -result {unknown option "60"}
+test canvImg-2.3 {CreateImage procedure} -body {
+ .c delete all
+ set i [.c create image 50 50]
+ list [lindex [.c itemconf $i -anchor] 4] \
+ [lindex [.c itemconf $i -image] 4] \
+ [lindex [.c itemconf $i -tags] 4]
+} -cleanup {
+ .c delete all
+} -result {center {} {}}
+test canvImg-2.4 {CreateImage procedure} -body {
+ .c create image xyz 40
+} -cleanup {
+ .c delete all
+} -returnCodes {error} -result {bad screen distance "xyz"}
+test canvImg-2.5 {CreateImage procedure} -body {
+ .c create image 50 qrs
+} -cleanup {
+ .c delete all
+} -returnCodes {error} -result {bad screen distance "qrs"}
+test canvImg-2.6 {CreateImage procedure} -constraints testImageType -body {
+ .c create image 50 50 -gorp foo
+} -cleanup {
+ .c delete all
+} -returnCodes {error} -result {unknown option "-gorp"}
+
+
+test canvImg-3.1 {ImageCoords procedure} -constraints testImageType -setup {
+ image create test foo
+} -body {
+ .c create image 50 100 -image foo -tags i1
+ format {%.6g %.6g} {*}[.c coords i1]
+} -cleanup {
+ .c delete all
+ image delete foo
+} -result {50 100}
+test canvImg-3.2 {ImageCoords procedure} -constraints testImageType -setup {
+ image create test foo
+} -body {
+ .c create image 50 100 -image foo -tags i1
+ .c coords i1 dumb 100
+} -cleanup {
+ .c delete all
+ image delete foo
+} -returnCodes {error} -result {bad screen distance "dumb"}
+test canvImg-3.3 {ImageCoords procedure} -constraints testImageType -setup {
+ image create test foo
+} -body {
+ .c delete all
+ .c create image 50 100 -image foo -tags i1
+ .c coords i1 250 dumb0
+} -cleanup {
+ .c delete all
+ image delete foo
+} -returnCodes {error} -result {bad screen distance "dumb0"}
+test canvImg-3.4 {ImageCoords procedure} -constraints testImageType -setup {
+ image create test foo
+} -body {
+ .c delete all
+ .c create image 50 100 -image foo -tags i1
+ .c coords i1 250
+} -cleanup {
+ .c delete all
+ image delete foo
+} -returnCodes {error} -result {wrong # coordinates: expected 2, got 1}
+test canvImg-3.5 {ImageCoords procedure} -constraints testImageType -setup {
+ image create test foo
+} -body {
+ .c delete all
+ .c create image 50 100 -image foo -tags i1
+ .c coords i1 250 300 400
+} -cleanup {
+ .c delete all
+ image delete foo
+} -returnCodes {error} -result {wrong # coordinates: expected 0 or 2, got 3}
+
+
+test canvImg-4.1 {ConfiugreImage procedure} -constraints testImageType -setup {
+ .c delete all
+} -body {
+ image create test foo -variable x
+ .c create image 50 100 -image foo -tags i1
+ update
+ set x {}
+ .c itemconfigure i1 -image {}
+ update
+ list $x [.c bbox i1]
+} -cleanup {
+ .c delete all
+ image delete foo
+} -result {{{foo free}} {}}
+test canvImg-4.2 {ConfigureImage procedure} -constraints testImageType -setup {
+ .c delete all
+} -body {
+ image create test foo -variable x
+ image create test foo2 -variable y
+ foo2 changed 0 0 0 0 80 60
+ .c create image 50 100 -image foo -tags i1 -anchor nw
+ update
+ set x {}
+ set y {}
+ set timer [after 300 {lappend y "timeout"}]
+ .c itemconfigure i1 -image foo2
+ update idletasks
+ update
+ # On MacOS we need to wait for the test image display procedure to run.
+ while {"timeout" ni $y && [lindex $y end 1] ne "display"} {
+ vwait y
+ }
+ after cancel timer
+ list $x $y [.c bbox i1]
+} -cleanup {
+ .c delete all
+ image delete foo
+ image delete foo2
+} -result {{{foo free}} {{foo2 get} {foo2 display 0 0 80 60}} {50 100 130 160}}
+test canvImg-4.3 {ConfiugreImage procedure} -constraints testImageType -setup {
+ .c delete all
+} -body {
+ image create test foo -variable x
+ image create test foo2 -variable y
+ foo2 changed 0 0 0 0 80 60
+ .c create image 50 100 -image foo -tags i1 -anchor nw
+ update
+ set x {}
+ set y {}
+ .c itemconfigure i1 -image lousy
+} -cleanup {
+ .c delete all
+ image delete foo foo2
+} -returnCodes {error} -result {image "lousy" doesn't exist}
+
+
+test canvImg-5.1 {DeleteImage procedure} -constraints testImageType -setup {
+ .c delete all
+ imageCleanup
+} -body {
+ image create test foo -variable x
+ image create test foo2 -variable y
+ image create test xyzzy -variable z
+ .c create image 50 100 -image xyzzy -tags i1
+ update
+ set names [lsort [imageNames]]
+ image delete xyzzy
+ set z {}
+ set names2 [lsort [imageNames]]
+ .c delete i1
+ update
+ list $names $names2 $z [lsort [imageNames]]
+} -cleanup {
+ imageCleanup
+ .c delete all
+} -result {{foo foo2 xyzzy} {foo foo2} {} {foo foo2}}
+test canvImg-5.2 {DeleteImage procedure (don't delete non-existent image)} -body {
+ .c delete all
+ .c create image 50 100 -tags i1
+ update
+ .c delete i1
+ update
+} -result {}
+
+
+test canvImg-6.1 {ComputeImageBbox procedure} -constraints testImageType -setup {
+ image create test foo
+ .c delete all
+} -body {
+ .c create image 15.51 17.51 -image foo -tags i1 -anchor nw
+ .c bbox i1
+} -cleanup {
+ .c delete all
+ imageCleanup
+} -result {16 18 46 33}
+test canvImg-6.2 {ComputeImageBbox procedure} -constraints testImageType -setup {
+ image create test foo
+ .c delete all
+} -body {
+ .c create image 15.49 17.49 -image foo -tags i1 -anchor nw
+ .c bbox i1
+} -cleanup {
+ .c delete all
+ imageCleanup
+} -result {15 17 45 32}
+test canvImg-6.3 {ComputeImageBbox procedure} -setup {
+ .c delete all
+} -body {
+ .c create image 20 30 -tags i1 -anchor nw
+ .c bbox i1
+} -cleanup {
+ .c delete all
+} -result {}
+test canvImg-6.4 {ComputeImageBbox procedure} -constraints testImageType -setup {
+ image create test foo
+ .c delete all
+} -body {
+ .c delete all
+ .c create image 20 30 -image foo -tags i1 -anchor nw
+ .c bbox i1
+} -cleanup {
+ .c delete all
+ imageCleanup
+} -result {20 30 50 45}
+test canvImg-6.5 {ComputeImageBbox procedure} -constraints testImageType -setup {
+ image create test foo
+ .c delete all
+} -body {
+ .c delete all
+ .c create image 20 30 -image foo -tags i1 -anchor n
+ .c bbox i1
+} -cleanup {
+ .c delete all
+ imageCleanup
+} -result {5 30 35 45}
+test canvImg-6.6 {ComputeImageBbox procedure} -constraints testImageType -setup {
+ image create test foo
+ .c delete all
+} -body {
+ .c delete all
+ .c create image 20 30 -image foo -tags i1 -anchor ne
+ .c bbox i1
+} -cleanup {
+ .c delete all
+ imageCleanup
+} -result {-10 30 20 45}
+test canvImg-6.7 {ComputeImageBbox procedure} -constraints testImageType -setup {
+ image create test foo
+ .c delete all
+} -body {
+ .c delete all
+ .c create image 20 30 -image foo -tags i1 -anchor e
+ .c bbox i1
+} -cleanup {
+ .c delete all
+ imageCleanup
+} -result {-10 23 20 38}
+test canvImg-6.8 {ComputeImageBbox procedure} -constraints testImageType -setup {
+ image create test foo
+ .c delete all
+} -body {
+ .c delete all
+ .c create image 20 30 -image foo -tags i1 -anchor se
+ .c bbox i1
+} -cleanup {
+ .c delete all
+ imageCleanup
+} -result {-10 15 20 30}
+test canvImg-6.9 {ComputeImageBbox procedure} -constraints testImageType -setup {
+ image create test foo
+ .c delete all
+} -body {
+ .c delete all
+ .c create image 20 30 -image foo -tags i1 -anchor s
+ .c bbox i1
+} -cleanup {
+ .c delete all
+ imageCleanup
+} -result {5 15 35 30}
+test canvImg-6.10 {ComputeImageBbox procedure} -constraints {
+ testImageType
+} -setup {
+ image create test foo
+ .c delete all
+} -body {
+ .c delete all
+ .c create image 20 30 -image foo -tags i1 -anchor sw
+ .c bbox i1
+} -cleanup {
+ .c delete all
+ image delete foo
+} -result {20 15 50 30}
+test canvImg-6.11 {ComputeImageBbox procedure} -constraints {
+ testImageType
+} -setup {
+ image create test foo
+ .c delete all
+} -body {
+ .c delete all
+ .c create image 20 30 -image foo -tags i1 -anchor w
+ .c bbox i1
+} -cleanup {
+ .c delete all
+ image delete foo
+} -result {20 23 50 38}
+test canvImg-6.12 {ComputeImageBbox procedure} -constraints {
+ testImageType
+} -setup {
+ image create test foo
+ .c delete all
+} -body {
+ .c delete all
+ .c create image 20 30 -image foo -tags i1 -anchor center
+ .c bbox i1
+} -cleanup {
+ .c delete all
+ image delete foo
+} -result {5 23 35 38}
+
+# The following test is non-portable because of differences in
+# coordinate rounding on some machines (does 0.5 round up?).
+
+test canvImg-7.1 {DisplayImage procedure} -constraints {
+ nonPortable testImageType
+} -setup {
+ .c delete all
+} -body {
+ image create test foo -variable x
+ .c create image 50 100 -image foo -tags i1 -anchor nw
+ update
+ set x {}
+ .c create rect 55 110 65 115 -width 1 -outline black -fill white
+ update
+ set x
+} -result {{foo display 4 9 12 6 30 30}}
+test canvImg-7.2 {DisplayImage procedure, no image} -body {
+ .c delete all
+ .c create image 50 100 -tags i1
+ update
+ .c create rect 55 110 65 115 -width 1 -outline black -fill white
+ update
+} -result {}
+
+
+# image used in 8.* test cases
+if {[testConstraint testImageType]} {
+ image create test foo
+}
+test canvImg-8.1 {ImageToArea procedure} -constraints testImageType -setup {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}
+} -body {
+ .c coords rect 50 70 80 81
+ .c gettags [.c find closest 70 90]
+} -cleanup {
+ .c delete all
+} -result {rect}
+test canvImg-8.2 {ImageToArea procedure} -constraints testImageType -setup {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}
+} -body {
+ .c coords rect {*}{50 70 80 79}
+ .c gettags [.c find closest {*}{70 90}]
+} -cleanup {
+ .c delete all
+} -result {image}
+test canvImg-8.3 {ImageToArea procedure} -constraints testImageType -setup {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}
+} -body {
+ .c coords rect {*}{99 70 110 81}
+ .c gettags [.c find closest {*}{90 90}]
+} -cleanup {
+ .c delete all
+} -result {rect}
+test canvImg-8.4 {ImageToArea procedure} -constraints testImageType -setup {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}
+} -body {
+ .c coords rect {*}{101 70 110 79}
+ .c gettags [.c find closest {*}{90 90}]
+} -cleanup {
+ .c delete all
+} -result {image}
+test canvImg-8.5 {ImageToArea procedure} -constraints testImageType -setup {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}
+} -body {
+ .c coords rect {*}{99 100 110 115}
+ .c gettags [.c find closest {*}{90 110}]
+} -cleanup {
+ .c delete all
+} -result {rect}
+test canvImg-8.6 {ImageToArea procedure} -constraints testImageType -setup {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}
+} -body {
+ .c coords rect {*}{101 100 110 115}
+ .c gettags [.c find closest {*}{90 110}]
+} -cleanup {
+ .c delete all
+} -result {image}
+test canvImg-8.7 {ImageToArea procedure} -constraints testImageType -setup {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}
+} -body {
+ .c coords rect {*}{99 134 110 145}
+ .c gettags [.c find closest {*}{90 125}]
+} -cleanup {
+ .c delete all
+} -result {rect}
+test canvImg-8.8 {ImageToArea procedure} -constraints testImageType -setup {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}
+} -body {
+ .c coords rect {*}{101 136 110 145}
+ .c gettags [.c find closest {*}{90 125}]
+} -cleanup {
+ .c delete all
+} -result {image}
+test canvImg-8.9 {ImageToArea procedure} -constraints testImageType -setup {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}
+} -body {
+ .c coords rect {*}{50 134 80 145}
+ .c gettags [.c find closest {*}{70 125}]
+} -cleanup {
+ .c delete all
+} -result {rect}
+test canvImg-8.10 {ImageToArea procedure} -constraints testImageType -setup {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}
+} -body {
+ .c coords rect {*}{50 136 80 145}
+ .c gettags [.c find closest {*}{70 125}]
+} -cleanup {
+ .c delete all
+} -result {image}
+test canvImg-8.11 {ImageToArea procedure} -constraints testImageType -setup {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}
+} -body {
+ .c coords rect {*}{20 134 31 145}
+ .c gettags [.c find closest {*}{40 125}]
+} -cleanup {
+ .c delete all
+} -result {rect}
+test canvImg-8.12 {ImageToArea procedure} -constraints testImageType -setup {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}
+} -body {
+ .c coords rect {*}{20 136 29 145}
+ .c gettags [.c find closest {*}{40 125}]
+} -cleanup {
+ .c delete all
+} -result {image}
+test canvImg-8.13 {ImageToArea procedure} -constraints testImageType -setup {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}
+} -body {
+ .c coords rect {*}{20 100 31 115}
+ .c gettags [.c find closest {*}{40 110}]
+} -cleanup {
+ .c delete all
+} -result {rect}
+test canvImg-8.14 {ImageToArea procedure} -constraints testImageType -setup {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}
+} -body {
+ .c coords rect {*}{20 100 29 115}
+ .c gettags [.c find closest {*}{40 110}]
+} -cleanup {
+ .c delete all
+} -result {image}
+test canvImg-8.15 {ImageToArea procedure} -constraints testImageType -setup {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}
+} -body {
+ .c coords rect {*}{20 70 31 80}
+ .c gettags [.c find closest {*}{40 90}]
+} -cleanup {
+ .c delete all
+} -result {rect}
+test canvImg-8.16 {ImageToArea procedure} -constraints testImageType -setup {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}
+} -body {
+ .c coords rect {*}{20 70 29 79}
+ .c gettags [.c find closest {*}{40 90}]
+} -cleanup {
+ .c delete all
+} -result {image}
+test canvImg-8.17 {ImageToArea procedure} -constraints testImageType -setup {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}
+} -body {
+ .c coords rect {*}{60 70 69 109}
+ .c gettags [.c find closest {*}{70 110}]
+} -cleanup {
+ .c delete all
+} -result {image}
+test canvImg-8.18 {ImageToArea procedure} -constraints testImageType -setup {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}
+} -body {
+ .c coords rect {*}{60 70 71 111}
+ .c gettags [.c find closest {*}{70 110}]
+} -cleanup {
+ .c delete all
+} -result {rect}
+.c delete all
+
+test canvImg-8.19 {ImageToArea procedure} -constraints testImageType -body {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c gettags [.c find overlapping 60 0 70 99]
+} -cleanup {
+ .c delete all
+} -result {}
+test canvImg-8.20 {ImageToArea procedure} -constraints testImageType -body {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c gettags [.c find overlapping 60 0 70 99.999]
+} -cleanup {
+ .c delete all
+} -result {}
+test canvImg-8.21 {ImageToArea procedure} -constraints testImageType -body {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c gettags [.c find overlapping 60 0 70 101]
+} -cleanup {
+ .c delete all
+} -result {image}
+test canvImg-8.22 {ImageToArea procedure} -constraints testImageType -body {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c gettags [.c find overlapping 81 105 120 115]
+} -cleanup {
+ .c delete all
+} -result {}
+test canvImg-8.23 {ImageToArea procedure} -constraints testImageType -body {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c gettags [.c find overlapping 80.001 105 120 115]
+} -cleanup {
+ .c delete all
+} -result {}
+test canvImg-8.24 {ImageToArea procedure} -constraints testImageType -body {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c gettags [.c find overlapping 79 105 120 115]
+} -cleanup {
+ .c delete all
+} -result {image}
+test canvImg-8.25 {ImageToArea procedure} -constraints testImageType -body {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c gettags [.c find overlapping 60 116 70 150]
+} -cleanup {
+ .c delete all
+} -result {}
+test canvImg-8.26 {ImageToArea procedure} -constraints testImageType -body {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c gettags [.c find overlapping 60 115.001 70 150]
+} -cleanup {
+ .c delete all
+} -result {}
+test canvImg-8.27 {ImageToArea procedure} -constraints testImageType -body {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c gettags [.c find overlapping 60 114 70 150]
+} -cleanup {
+ .c delete all
+} -result {image}
+test canvImg-8.28 {ImageToArea procedure} -constraints testImageType -body {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c gettags [.c find overlapping 0 105 49 115]
+} -cleanup {
+ .c delete all
+} -result {}
+test canvImg-8.29 {ImageToArea procedure} -constraints testImageType -body {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c gettags [.c find overlapping 0 105 50 114.999]
+} -cleanup {
+ .c delete all
+} -result {}
+test canvImg-8.30 {ImageToArea procedure} -constraints testImageType -body {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c gettags [.c find overlapping 0 105 51 115]
+} -cleanup {
+ .c delete all
+} -result {image}
+test canvImg-8.31 {ImageToArea procedure} -constraints testImageType -body {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c gettags [.c find overlapping 0 0 49.999 99.999]
+} -cleanup {
+ .c delete all
+} -result {}
+test canvImg-8.32 {ImageToArea procedure} -constraints testImageType -body {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c gettags [.c find overlapping 0 0 51 101]
+} -cleanup {
+ .c delete all
+} -result {image}
+test canvImg-8.33 {ImageToArea procedure} -constraints testImageType -body {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c gettags [.c find overlapping 80 0 150 100]
+} -cleanup {
+ .c delete all
+} -result {}
+test canvImg-8.34 {ImageToArea procedure} -constraints testImageType -body {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c gettags [.c find overlapping 79 0 150 101]
+} -cleanup {
+ .c delete all
+} -result {image}
+test canvImg-8.35 {ImageToArea procedure} -constraints testImageType -body {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c gettags [.c find overlapping 80.001 115.001 150 180]
+} -cleanup {
+ .c delete all
+} -result {}
+test canvImg-8.36 {ImageToArea procedure} -constraints testImageType -body {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c gettags [.c find overlapping 79 114 150 180]
+} -cleanup {
+ .c delete all
+} -result {image}
+test canvImg-8.37 {ImageToArea procedure} -constraints testImageType -body {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c gettags [.c find overlapping 0 115 50 180]
+} -cleanup {
+ .c delete all
+} -result {}
+test canvImg-8.38 {ImageToArea procedure} -constraints testImageType -body {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c gettags [.c find overlapping 0 114 51 180]
+} -cleanup {
+ .c delete all
+} -result {image}
+test canvImg-8.39 {ImageToArea procedure} -constraints testImageType -body {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c gettags [.c find enclosed 0 0 200 200]
+} -cleanup {
+ .c delete all
+} -result {image}
+test canvImg-8.40 {ImageToArea procedure} -constraints testImageType -body {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c gettags [.c find enclosed 49.999 99.999 80.001 115.001]
+} -cleanup {
+ .c delete all
+} -result {image}
+test canvImg-8.41 {ImageToArea procedure} -constraints testImageType -body {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c gettags [.c find enclosed 51 100 80 115]
+} -cleanup {
+ .c delete all
+} -result {}
+test canvImg-8.42 {ImageToArea procedure} -constraints testImageType -body {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c gettags [.c find enclosed 50 101 80 115]
+} -cleanup {
+ .c delete all
+} -result {}
+test canvImg-8.43 {ImageToArea procedure} -constraints testImageType -body {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c gettags [.c find enclosed 50 100 79 115]
+} -cleanup {
+ .c delete all
+} -result {}
+test canvImg-8.44 {ImageToArea procedure} -constraints testImageType -body {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c gettags [.c find enclosed 50 100 80 114]
+} -cleanup {
+ .c delete all
+} -result {}
+if {[testConstraint testImageType]} {
+ image delete foo
+}
+
+
+test canvImg-9.1 {DisplayImage procedure} -constraints testImageType -setup {
+ .c delete all
+ image create test foo
+} -body {
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c scale image 25 0 2.0 1.5
+ .c bbox image
+} -cleanup {
+ .c delete all
+ image delete foo
+} -result {75 150 105 165}
+
+if {[tk windowingsystem] == "aqua" && $tcl_platform(osVersion) > 18} {
+ # Aqua >= 10.14 will redraw the entire image.
+ set result_10_1 {{foo display 0 0 30 15}}
+} else {
+ set result_10_1 {{foo display 2 4 6 8}}
+}
+test canvImg-10.1 {TranslateImage procedure} -constraints testImageType -setup {
+ .c delete all
+ update
+} -body {
+ image create test foo -variable x
+ .c create image 50 100 -image foo -tags image -anchor nw
+ update
+ set x {}
+ foo changed 2 4 6 8 30 15
+ update
+ return $x
+} -cleanup {
+ .c delete all
+ image delete foo
+} -result $result_10_1
+
+test canvImg-11.1 {TranslateImage procedure} -constraints testImageType -setup {
+ .c delete all
+ update
+} -body {
+ image create test foo -variable x
+ .c create image 50 100 -image foo -tags image -anchor nw
+ update
+ set x {}
+ foo changed 2 4 6 8 40 50
+ update
+ return $x
+} -cleanup {
+ .c delete all
+ image delete foo
+} -result {{foo display 0 0 40 50}}
+test canvImg-11.2 {ImageChangedProc procedure} -constraints {
+ testImageType
+} -setup {
+ .c delete all
+} -body {
+ image create test foo -variable x
+ .c create image 50 100 -image foo -tags image -anchor center
+ update
+ set x {}
+ foo changed 0 0 0 0 40 50
+ .c bbox image
+} -cleanup {
+ .c delete all
+ image delete foo
+} -result {30 75 70 125}
+if {[tk windowingsystem] == "aqua" && $tcl_platform(osVersion) > 18} {
+ # Aqua >= 10.14 will redraw the entire image.
+ set result_11_3 {{foo2 display 0 0 80 60}}
+} else {
+ set result_11_3 {{foo2 display 0 0 20 40}}
+}
+test canvImg-11.3 {ImageChangedProc procedure} -constraints {
+ testImageType
+} -setup {
+ .c delete all
+ update
+} -body {
+ image create test foo -variable x
+ image create test foo2 -variable y
+ foo changed 0 0 0 0 40 50
+ foo2 changed 0 0 0 0 80 60
+
+ .c create image 50 100 -image foo -tags image -anchor nw
+ .c create image 70 110 -image foo2 -anchor nw
+ update
+ set y {}
+ image create test foo -variable x
+ update
+ return $y
+} -cleanup {
+ .c delete all
+ image delete foo foo2
+} -result $result_11_3
+
+# cleanup
+imageFinish
+cleanupTests
+return
+
+# Local variables:
+# mode: tcl
+# End:
diff --git a/tk8.6/tests/canvMoveto.test b/tk8.6/tests/canvMoveto.test
new file mode 100644
index 0000000..79761a4
--- /dev/null
+++ b/tk8.6/tests/canvMoveto.test
@@ -0,0 +1,56 @@
+# This file is a Tcl script to test out the canvas "moveto" command. It is
+# derived from canvRect.test.
+#
+# Copyright (c) 1994-1996 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# Copyright (c) 2004 Neil McKay.
+# All rights reserved.
+
+package require tcltest 2.1
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+
+canvas .c -width 400 -height 300 -bd 2 -relief sunken
+.c create rectangle 20 20 80 80 -tag {test rect1}
+.c create rectangle 40 40 90 100 -tag {test rect2}
+
+test canvMoveto-1.1 {Bad args handling for "moveto" command} -body {
+ .c moveto test
+} -returnCodes error -result {wrong # args: should be ".c moveto tagOrId x y"}
+test canvMoveto-1.2 {Bad args handling for "moveto" command} -body {
+ .c moveto rect
+} -returnCodes error -result {wrong # args: should be ".c moveto tagOrId x y"}
+test canvMoveto-1.3 {Bad args handling for "moveto" command} -body {
+ .c moveto test 12
+} -returnCodes error -result {wrong # args: should be ".c moveto tagOrId x y"}
+test canvMoveto-1.4 {Bad args handling for "moveto" command} -body {
+ .c moveto test 12 y
+} -returnCodes error -result {bad screen distance "y"}
+test canvMoveto-1.5 {Bad args handling for "moveto" command} -body {
+ .c moveto test 12 20 -anchor
+} -returnCodes error -result {wrong # args: should be ".c moveto tagOrId x y"}
+
+test canvMoveto-2.1 {Canvas "moveto" command coordinates} {
+ .c moveto test 200 150
+ .c bbox test
+} {200 150 272 232}
+test canvMoveto-2.2 {Canvas "moveto" command, blank y coordinate} {
+ .c moveto test 200 150
+ .c moveto test 150 {}
+ .c bbox test
+} {150 150 222 232}
+test canvMoveto-2.3 {Canvas "moveto" command, blank x coordinate} {
+ .c moveto test 200 150
+ .c moveto test {} 200
+ .c bbox test
+} {200 200 272 282}
+
+.c delete withtag all
+
+# cleanup
+cleanupTests
+return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tk8.6/tests/canvPs.test b/tk8.6/tests/canvPs.test
new file mode 100644
index 0000000..c7ba958
--- /dev/null
+++ b/tk8.6/tests/canvPs.test
@@ -0,0 +1,196 @@
+# This file is a Tcl script to test out procedures to write postscript
+# for canvases to files and channels. It exercises the procedure
+# TkCanvPostscriptCmd in generic/tkCanvPs.c
+#
+# Copyright (c) 1995 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+imageInit
+
+# canvas used in 1.* and 2.* test cases
+canvas .c -width 400 -height 300 -bd 2 -relief sunken
+.c create rectangle 20 20 80 80 -fill red
+pack .c
+update
+
+test canvPs-1.1 {test writing to a file} -constraints {
+ unixOrPc
+} -setup {
+ set foo [makeFile {} foo.ps]
+} -body {
+ .c postscript -file $foo
+ file exists $foo
+} -cleanup {
+ removeFile foo.ps
+} -result 1
+test canvPs-1.2 {test writing to a file, idempotency} -constraints {
+ unixOrPc
+} -setup {
+ set foo [makeFile {} foo.ps]
+ set bar [makeFile {} bar.ps]
+} -body {
+ .c postscript -file $foo
+ .c postscript -file $bar
+ set status ok
+ if {[file size $bar] != [file size $foo]} {
+ set status broken
+ }
+ set status
+} -cleanup {
+ removeFile foo.ps
+ removeFile bar.ps
+} -result ok
+
+
+test canvPs-2.1 {test writing to a channel} -constraints {
+ unixOrPc
+} -setup {
+ set foo [makeFile {} foo.ps]
+ file delete $foo
+} -body {
+ set chan [open $foo w]
+ fconfigure $chan -translation lf
+ .c postscript -channel $chan
+ close $chan
+ file exists $foo
+} -cleanup {
+ removeFile foo.ps
+} -result 1
+test canvPs-2.2 {test writing to channel, idempotency} -constraints {
+ unixOrPc
+} -setup {
+ set foo [makeFile {} foo.ps]
+ set bar [makeFile {} bar.ps]
+ file delete $foo
+ file delete $bar
+} -body {
+ set c1 [open $foo w]
+ set c2 [open $bar w]
+ fconfigure $c1 -translation lf
+ fconfigure $c2 -translation lf
+ .c postscript -channel $c1
+ .c postscript -channel $c2
+ close $c1
+ close $c2
+ set status ok
+ if {[file size $bar] != [file size $foo]} {
+ set status broken
+ }
+ set status
+} -cleanup {
+ removeFile foo.ps
+ removeFile bar.ps
+} -result ok
+test canvPs-2.3 {test writing to channel and file, same output} -constraints {
+ unix
+} -setup {
+ set foo [makeFile {} foo.ps]
+ set bar [makeFile {} bar.ps]
+ file delete $foo
+ file delete $bar
+} -body {
+ set c1 [open $foo w]
+ fconfigure $c1 -translation lf
+ .c postscript -channel $c1
+ close $c1
+ .c postscript -file $bar
+ set status ok
+ if {[file size $foo] != [file size $bar]} {
+ set status broken
+ }
+ set status
+} -cleanup {
+ removeFile foo.ps
+ removeFile bar.ps
+} -result ok
+test canvPs-2.4 {test writing to channel and file, same output} -constraints {
+ win
+} -setup {
+ set foo [makeFile {} foo.ps]
+ set bar [makeFile {} bar.ps]
+ file delete $foo
+ file delete $bar
+} -body {
+ set c1 [open $foo w]
+ fconfigure $c1 -translation crlf
+ .c postscript -channel $c1
+ close $c1
+ .c postscript -file $bar
+ set status ok
+ if {[file size $foo] != [file size $bar]} {
+ set status broken
+ }
+ set status
+} -cleanup {
+ removeFile foo.ps
+ removeFile bar.ps
+} -result ok
+destroy .c
+
+
+test canvPs-3.1 {test ps generation with an embedded window} -constraints {
+ notAqua
+} -setup {
+ set bar [makeFile {} bar.ps]
+ file delete $bar
+} -body {
+ pack [canvas .c -width 200 -height 200 -background white]
+ .c create rect 20 20 150 150 -tags rect0 -dash . -width 2
+ .c create arc 0 50 200 200 -tags arc0 \
+ -dash {4 4} -stipple question -outline red -fill green
+
+ image create photo logo \
+ -file [file join [file dirname [info script]] pwrdLogo150.gif]
+ .c create image 200 50 -image logo -anchor nw
+
+ entry .c.e -background pink -foreground blue -width 14
+ .c.e insert 0 "we gonna be postscripted"
+ .c create window 50 180 -anchor nw -window .c.e
+ update
+ .c postscript -file $bar
+ file exists $bar
+} -cleanup {
+ destroy .c
+ imageCleanup
+ removeFile bar.ps
+} -result {1}
+test canvPs-3.2 {test ps generation with an embedded window not mapped} -setup {
+ set bar [makeFile {} bar.ps]
+ file delete $bar
+} -body {
+ pack [canvas .c -width 200 -height 200 -background white]
+ entry .c.e -background pink -foreground blue -width 14
+ .c.e insert 0 "we gonna be postscripted"
+ .c create window 50 180 -anchor nw -window .c.e
+ .c postscript -file $bar
+ file exists $bar
+} -cleanup {
+ destroy .c
+ removeFile bar.ps
+} -result {1}
+
+
+test canvPs-4.1 {test ps generation with single-point uncolored poly, bug 734498} -body {
+ pack [canvas .c]
+ .c create poly 10 20 10 20
+ .c postscript
+} -cleanup {
+ destroy .c
+} -returnCodes ok -match glob -result *
+
+
+# cleanup
+unset -nocomplain foo bar
+imageFinish
+deleteWindows
+cleanupTests
+return
+
+# Local variables:
+# mode: tcl
+# End:
diff --git a/tk8.6/tests/canvPsArc.tcl b/tk8.6/tests/canvPsArc.tcl
new file mode 100644
index 0000000..ef7ca6c
--- /dev/null
+++ b/tk8.6/tests/canvPsArc.tcl
@@ -0,0 +1,43 @@
+# This file creates a screen to exercise Postscript generation
+# for bitmaps in canvases. It is part of the Tk visual test suite,
+# which is invoked via the "visual" script.
+
+catch {destroy .t}
+toplevel .t
+wm title .t "Postscript Tests for Canvases"
+wm iconname .t "Postscript"
+wm geom .t +0+0
+wm minsize .t 1 1
+
+set c .t.c
+
+message .t.m -text {This screen exercises the Postscript-generation abilities of Tk canvas widgets for arcs. Click on "Print" to print the canvas to your default printer. You can click on items in the canvas to delete them.} -width 6i
+pack .t.m -side top -fill both
+
+frame .t.bot
+pack .t.bot -side bottom -fill both
+button .t.bot.quit -text Quit -command {destroy .t}
+button .t.bot.print -text Print -command "lpr $c"
+pack .t.bot.print .t.bot.quit -side left -pady 1m -expand 1
+
+canvas $c -width 6i -height 6i -bd 2 -relief sunken
+pack $c -expand yes -fill both -padx 2m -pady 2m
+
+$c create arc .5i .5i 2i 2i -style pieslice -start 20 -extent 90 \
+ -fill black -outline {}
+$c create arc 2.5i 0 4.5i 1i -style pieslice -start -45 -extent -135 \
+ -fill {} -outline black -outlinestipple gray50 -width 3m
+$c create arc 5.0i .5i 6.5i 2i -style pieslice -start 45 -extent 315 \
+ -fill black -stipple gray25 -outline black -width 1m
+
+$c create arc -.5i 2.5i 2.0i 3.5i -style chord -start 90 -extent 270 \
+ -fill black -outline {}
+$c create arc 2.5i 2i 4i 6i -style chord -start 20 -extent 140 \
+ -fill black -stipple gray50 -outline black -width 2m
+$c create arc 4i 2.5i 8i 4.5i -style chord -start 60 -extent 60 \
+ -fill {} -outline black
+
+$c create arc .5i 4.5i 2i 6i -style arc -start 135 -extent 315 -width 3m \
+ -outline black -outlinestipple gray25
+$c create arc 3.5i 4.5i 5.5i 5.5i -style arc -start 45 -extent -90 -width 1m \
+ -outline black
diff --git a/tk8.6/tests/canvPsBmap.tcl b/tk8.6/tests/canvPsBmap.tcl
new file mode 100644
index 0000000..4a7a7e2
--- /dev/null
+++ b/tk8.6/tests/canvPsBmap.tcl
@@ -0,0 +1,84 @@
+# This file creates a screen to exercise Postscript generation
+# for bitmaps in canvases. It is part of the Tk visual test suite,
+# which is invoked via the "visual" script.
+
+catch {destroy .t}
+toplevel .t
+wm title .t "Postscript Tests for Canvases"
+wm iconname .t "Postscript"
+wm geom .t +0+0
+wm minsize .t 1 1
+
+set c .t.c
+
+message .t.m -text {This screen exercises the Postscript-generation abilities of Tk canvas widgets for bitmaps. Click on "Print" to print the canvas to your default printer. You can click on items in the canvas to delete them.} -width 6i
+pack .t.m -side top -fill both
+
+frame .t.bot
+pack .t.bot -side bottom -fill both
+button .t.bot.quit -text Quit -command {destroy .t}
+button .t.bot.print -text Print -command "lpr $c"
+pack .t.bot.print .t.bot.quit -side left -pady 1m -expand 1
+
+canvas $c -width 6i -height 6i -bd 2 -relief sunken
+pack $c -expand yes -fill both -padx 2m -pady 2m
+
+set canvPsBmapImageDir [file join [file dirname [info script]] images]
+
+$c create bitmap 0.5i 0.5i \
+ -bitmap @[file join $canvPsBmapImageDir flagdown.xbm] \
+ -background {} -foreground black -anchor nw
+$c create rect 0.47i 0.47i 0.53i 0.53i -fill {} -outline black
+
+$c create bitmap 3.0i 0.5i \
+ -bitmap @[file join $canvPsBmapImageDir flagdown.xbm] \
+ -background {} -foreground black -anchor n
+$c create rect 2.97i 0.47i 3.03i 0.53i -fill {} -outline black
+
+$c create bitmap 5.5i 0.5i \
+ -bitmap @[file join $canvPsBmapImageDir flagdown.xbm] \
+ -background black -foreground white -anchor ne
+$c create rect 5.47i 0.47i 5.53i 0.53i -fill {} -outline black
+
+$c create bitmap 0.5i 3.0i \
+ -bitmap @[file join $canvPsBmapImageDir face.xbm] \
+ -background {} -foreground black -anchor w
+$c create rect 0.47i 2.97i 0.53i 3.03i -fill {} -outline black
+
+$c create bitmap 3.0i 3.0i \
+ -bitmap @[file join $canvPsBmapImageDir face.xbm] \
+ -background {} -foreground black -anchor center
+$c create rect 2.97i 2.97i 3.03i 3.03i -fill {} -outline black
+
+$c create bitmap 5.5i 3.0i \
+ -bitmap @[file join $canvPsBmapImageDir face.xbm] \
+ -background blue -foreground black -anchor e
+$c create rect 5.47i 2.97i 5.53i 3.03i -fill {} -outline black
+
+$c create bitmap 0.5i 5.5i \
+ -bitmap @[file join $canvPsBmapImageDir flagup.xbm] \
+ -background black -foreground white -anchor sw
+$c create rect 0.47i 5.47i 0.53i 5.53i -fill {} -outline black
+
+$c create bitmap 3.0i 5.5i \
+ -bitmap @[file join $canvPsBmapImageDir flagup.xbm] \
+ -background green -foreground white -anchor s
+$c create rect 2.97i 5.47i 3.03i 5.53i -fill {} -outline black
+
+$c create bitmap 5.5i 5.5i \
+ -bitmap @[file join $canvPsBmapImageDir flagup.xbm] \
+ -background {} -foreground black -anchor se
+$c create rect 5.47i 5.47i 5.53i 5.53i -fill {} -outline black
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tk8.6/tests/canvPsGrph.tcl b/tk8.6/tests/canvPsGrph.tcl
new file mode 100644
index 0000000..08ccd74
--- /dev/null
+++ b/tk8.6/tests/canvPsGrph.tcl
@@ -0,0 +1,98 @@
+# This file creates a screen to exercise Postscript generation
+# for some of the graphical objects in canvases. It is part of the Tk
+# visual test suite, which is invoked via the "visual" script.
+
+catch {destroy .t}
+toplevel .t
+wm title .t "Postscript Tests for Canvases"
+wm iconname .t "Postscript"
+wm geom .t +0+0
+wm minsize .t 1 1
+
+set c .t.mid.c
+
+message .t.m -text {This screen exercises the Postscript-generation abilities of Tk canvas widgets. Select what you want to display with the buttons below, then click on "Print" to print it to your default printer. You can click on items in the canvas to delete them.} -width 4i
+pack .t.m -side top -fill both
+
+frame .t.top
+pack .t.top -side top -fill both
+set what rect
+radiobutton .t.top.rect -text Rectangles -variable what -value rect \
+ -command "mkObjs $c" -relief flat
+radiobutton .t.top.oval -text Ovals -variable what -value oval \
+ -command "mkObjs $c" -relief flat
+radiobutton .t.top.poly -text Polygons -variable what -value poly \
+ -command "mkObjs $c" -relief flat
+radiobutton .t.top.line -text Lines -variable what -value line \
+ -command "mkObjs $c" -relief flat
+pack .t.top.rect .t.top.oval .t.top.poly .t.top.line \
+ -side left -pady 2m -ipadx 2m -ipady 1m -expand 1
+
+frame .t.bot
+pack .t.bot -side bottom -fill both
+button .t.bot.quit -text Quit -command {destroy .t}
+button .t.bot.print -text Print -command "lpr $c"
+pack .t.bot.print .t.bot.quit -side left -pady 1m -expand 1
+
+frame .t.mid -relief sunken -bd 2
+pack .t.mid -side top -expand yes -fill both -padx 2m -pady 2m
+canvas $c -width 400 -height 350 -bd 0 -relief sunken
+pack $c -expand yes -fill both -padx 1 -pady 1
+
+proc mkObjs c {
+ global what
+ $c delete all
+ if {$what == "rect"} {
+ $c create rect 0 0 400 350 -outline black
+ $c create rect 2 2 100 50 -fill black -stipple gray25
+ $c create rect -20 180 80 320 -fill black -stipple gray50 -width .5c
+ $c create rect 200 -20 240 20 -fill black
+ $c create rect 380 200 420 240 -fill black
+ $c create rect 200 330 240 370 -fill black
+ }
+
+ if {$what == "oval"} {
+ $c create oval 50 10 150 80 -fill black -stipple gray25 -outline {}
+ $c create oval 100 100 200 150 -outline {} -fill black -stipple gray50
+ $c create oval 250 100 400 300 -width .5c
+ }
+
+ if {$what == "poly"} {
+ $c create poly 100 200 200 50 300 200 -smooth yes -stipple gray25 \
+ -outline black -width 4
+ $c create poly 100 300 100 250 350 250 350 300 350 300 100 300 100 300 \
+ -fill red -smooth yes
+ $c create poly 20 10 40 10 40 60 80 60 80 25 30 25 30 \
+ 35 50 35 50 45 20 45
+ $c create poly 300 20 300 120 380 80 320 100 -fill blue -outline black
+ $c create poly 20 200 100 220 90 100 40 250 \
+ -fill {} -outline brown -width 3
+ }
+
+ if {$what == "line"} {
+ $c create line 20 20 120 20 -arrow both -width 5
+ $c create line 20 80 150 80 20 200 150 200 -smooth yes
+ $c create line 150 20 150 150 250 150 -width .5c -smooth yes \
+ -arrow both -arrowshape {.75c 1.0c .5c} -stipple gray25
+ $c create line 50 340 100 250 150 340 -join round -cap round -width 10
+ $c create line 200 340 250 250 300 340 -join bevel -cap project \
+ -width 10
+ $c create line 300 20 380 20 300 150 380 150 -join miter -cap butt \
+ -width 10 -stipple gray25
+ }
+}
+
+mkObjs $c
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tk8.6/tests/canvPsImg.tcl b/tk8.6/tests/canvPsImg.tcl
new file mode 100644
index 0000000..1f46eca
--- /dev/null
+++ b/tk8.6/tests/canvPsImg.tcl
@@ -0,0 +1,84 @@
+# This file creates a screen to exercise Postscript generation
+# for images in canvases. It is part of the Tk visual test suite,
+# which is invoked via the "visual" script.
+
+# Build a test image in a canvas
+proc BuildTestImage {} {
+ global BitmapImage PhotoImage visual level
+ catch {destroy .t.f}
+ frame .t.f -visual $visual -colormap new
+ pack .t.f -side top -after .t.top
+ bind .t.f <Enter> {wm colormapwindows .t {.t.f .t}}
+ bind .t.f <Leave> {wm colormapwindows .t {.t .t.f}}
+ canvas .t.f.c -width 550 -height 350 -borderwidth 2 -relief raised
+ pack .t.f.c
+ .t.f.c create rectangle 25 25 525 325 -fill {} -outline black
+ .t.f.c create image 50 50 -anchor nw -image $BitmapImage
+ .t.f.c create image 250 50 -anchor nw -image $PhotoImage
+}
+
+# Put postscript in a file
+proc FilePostscript { canvas } {
+ global level
+ $canvas postscript -file /tmp/test.ps -colormode $level
+}
+
+# Send postscript output to printer
+proc PrintPostcript { canvas } {
+ global level
+ $canvas postscript -file tmp.ps -colormode $level
+ exec lpr tmp.ps
+}
+
+catch {destroy .t}
+toplevel .t
+wm title .t "Postscript Tests for Canvases: Images"
+wm iconname .t "Postscript"
+
+message .t.m -text {This screen exercises the Postscript-generation abilities of Tk canvas widgets for images. Click the buttons below to select a Visual type for the canvas and colormode for the Postscript output. Then click "Print" to send the results to the default printer, or "Print to file" to put the Postscript output in a file called "/tmp/test.ps". You can also click on items in the canvas to delete them.
+NOTE: Some Postscript printers may not be able to handle Postscript generated in color mode.} -width 6i
+pack .t.m -side top -fill both
+
+frame .t.top
+pack .t.top -side top
+frame .t.top.l -relief raised -borderwidth 2
+frame .t.top.r -relief raised -borderwidth 2
+pack .t.top.l .t.top.r -side left -fill both -expand 1
+
+label .t.visuals -text "Visuals"
+pack .t.visuals -in .t.top.l
+
+set visual [lindex [winfo visualsavailable .] 0]
+foreach v [winfo visualsavailable .] {
+ # The hack below is necessary for some systems, which have more than one
+ # visual of the same type...
+ if {![winfo exists .t.$v]} {
+ radiobutton .t.$v -text $v -variable visual -value $v \
+ -command BuildTestImage
+ pack .t.$v -in .t.top.l -anchor w
+ }
+}
+
+label .t.levels -text "Color Levels"
+pack .t.levels -in .t.top.r
+set level monochrome
+foreach l { monochrome gray color } {
+ radiobutton .t.$l -text $l -variable level -value $l
+ pack .t.$l -in .t.top.r -anchor w
+}
+
+set BitmapImage [image create bitmap \
+ -file [file join [file dirname [info script]] face.xbm] \
+ -background white -foreground black]
+set PhotoImage [image create photo \
+ -file [file join [file dirname [info script]] teapot.ppm]]
+
+BuildTestImage
+
+frame .t.bot
+pack .t.bot -side top -fill x -expand 1
+
+button .t.file -text "Print to File" -command { FilePostscript .t.f.c }
+button .t.print -text "Print" -command { PrintPostscript .t.f.c }
+button .t.quit -text "Quit" -command { destroy .t }
+pack .t.file .t.print .t.quit -in .t.bot -side left -fill x -expand 1
diff --git a/tk8.6/tests/canvPsText.tcl b/tk8.6/tests/canvPsText.tcl
new file mode 100644
index 0000000..08c9d27
--- /dev/null
+++ b/tk8.6/tests/canvPsText.tcl
@@ -0,0 +1,94 @@
+# This file creates a screen to exercise Postscript generation
+# for text in canvases. It is part of the Tk visual test suite,
+# which is invoked via the "visual" script.
+
+catch {destroy .t}
+toplevel .t
+wm title .t "Postscript Tests for Canvases"
+wm iconname .t "Postscript"
+wm geom .t +0+0
+wm minsize .t 1 1
+
+set c .t.c
+
+message .t.m -text {This screen exercises the Postscript-generation abilities of Tk canvas widgets for text. Click on "Print" to print the canvas to your default printer. The "Stipple" button can be used to turn stippling on and off for the text, but beware: many Postscript printers cannot handle stippled text. You can click on items in the canvas to delete them.} -width 6i
+pack .t.m -side top -fill both
+
+set stipple {}
+checkbutton .t.stipple -text Stippling -variable stipple -onvalue gray50 \
+ -offvalue {} -command "setStipple $c" -relief flat
+pack .t.stipple -side top -pady 2m -expand 1 -anchor w
+
+frame .t.bot
+pack .t.bot -side bottom -fill both
+button .t.bot.quit -text Quit -command {destroy .t}
+button .t.bot.print -text Print -command "lpr $c"
+pack .t.bot.print .t.bot.quit -side left -pady 1m -expand 1
+
+canvas $c -width 6i -height 7i -bd 2 -relief sunken
+pack $c -expand yes -fill both -padx 2m -pady 2m
+
+$c create rect 2.95i 0.45i 3.05i 0.55i -fill {} -outline black
+$c create text 3.0i 0.5i -text "Center Courier Oblique 24" \
+ -anchor center -tags text -font {Courier 24 italic} -stipple $stipple
+$c create rect 2.95i 0.95i 3.05i 1.05i -fill {} -outline black
+$c create text 3.0i 1.0i -text "Northwest Helvetica 24" \
+ -anchor nw -tags text -font {Helvetica 24} -stipple $stipple
+$c create rect 2.95i 1.45i 3.05i 1.55i -fill {} -outline black
+$c create text 3.0i 1.5i -text "North Helvetica Oblique 12 " \
+ -anchor n -tags text -font {Helvetica 12 italic} -stipple $stipple
+$c create rect 2.95i 1.95i 3.05i 2.05i -fill {} -outline blue
+$c create text 3.0i 2.0i -text "Northeast Helvetica Bold 24" \
+ -anchor ne -tags text -font {Helvetica 24 bold} -stipple $stipple
+$c create rect 2.95i 2.45i 3.05i 2.55i -fill {} -outline black
+$c create text 3.0i 2.5i -text "East Helvetica Bold Oblique 18" \
+ -anchor e -tags text -font {Helvetica 18 {bold italic}} -stipple $stipple
+$c create rect 2.95i 2.95i 3.05i 3.05i -fill {} -outline black
+$c create text 3.0i 3.0i -text "Southeast Times 10" \
+ -anchor se -tags text -font {Times 10} -stipple $stipple
+$c create rect 2.95i 3.45i 3.05i 3.55i -fill {} -outline black
+$c create text 3.0i 3.5i -text "South Times Italic 24" \
+ -anchor s -tags text -font {Times 24 italic} -stipple $stipple
+$c create rect 2.95i 3.95i 3.05i 4.05i -fill {} -outline black
+$c create text 3.0i 4.0i -text "Southwest Times Bold 18" \
+ -anchor sw -tags text -font {Times 18 bold} -stipple $stipple
+$c create rect 2.95i 4.45i 3.05i 4.55i -fill {} -outline black
+$c create text 3.0i 4.5i -text "West Times Bold Italic 24"\
+ -anchor w -tags text -font {Times 24 {bold italic}} -stipple $stipple
+
+$c create rect 0.95i 5.20i 1.05i 5.30i -fill {} -outline black
+$c create text 1.0i 5.25i -width 1.9i -anchor c -justify left -tags text \
+ -font {Times 18 bold} -stipple $stipple \
+ -text "This is a sample text item to see how left justification works"
+$c create rect 2.95i 5.20i 3.05i 5.30i -fill {} -outline black
+$c create text 3.0i 5.25i -width 1.8i -anchor c -justify center -tags text \
+ -font {Times 18 bold} -stipple $stipple \
+ -text "This is a sample text item to see how center justification works"
+$c create rect 4.95i 5.20i 5.05i 5.30i -fill {} -outline black
+$c create text 5.0i 5.25i -width 1.8i -anchor c -justify right -tags text \
+ -font {Times 18 bold} -stipple $stipple \
+ -text "This is a sample text item to see how right justification works"
+
+$c create text 3.0i 6.0i -width 5.0i -anchor n -justify right -tags text \
+ -text "This text is\nright justified\nwith a line length equal to\n\
+ the size of the enclosing rectangle.\nMake sure it prints right\
+ justified as well."
+$c create rect 0.5i 6.0i 5.5i 6.9i -fill {} -outline black
+
+proc setStipple c {
+ global stipple
+ $c itemconfigure text -stipple $stipple
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tk8.6/tests/canvRect.test b/tk8.6/tests/canvRect.test
new file mode 100644
index 0000000..a2cc51c
--- /dev/null
+++ b/tk8.6/tests/canvRect.test
@@ -0,0 +1,475 @@
+# This file is a Tcl script to test out the procedures in tkRectOval.c,
+# which implement canvas "rectangle" and "oval" items. It is organized
+# in the standard fashion for Tcl tests.
+#
+# Copyright (c) 1994-1996 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+
+# Canvas used in every test case of the whole file
+canvas .c -width 400 -height 300 -bd 2 -relief sunken
+pack .c
+update
+
+# Rectangle used in canvRect-1.* tests
+.c create rectangle 20 20 80 80 -tag test
+test canvRect-1.1 {configuration options: good value for -fill} -body {
+ .c itemconfigure test -fill #ff0000
+ list [.c itemcget test -fill] [lindex [.c itemconfigure test -fill] 4]
+} -result {{#ff0000} #ff0000}
+test canvRect-1.2 {configuration options: bad value for -fill} -body {
+ .c itemconfigure test -fill non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+test canvRect-1.3 {configuration options: good value for -outline} -body {
+ .c itemconfigure test -outline #123456
+ list [.c itemcget test -outline] [lindex [.c itemconfigure test -outline] 4]
+} -result {{#123456} #123456}
+test canvRect-1.4 {configuration options: bad value for -outline} -body {
+ .c itemconfigure test -outline non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+test canvRect-1.5 {configuration options: good value for -stipple } -body {
+ .c itemconfigure test -stipple gray50
+ list [.c itemcget test -stipple ] [lindex [.c itemconfigure test -stipple ] 4]
+} -result {gray50 gray50}
+test canvRect-1.6 {configuration options: bad value for -stipple } -body {
+ .c itemconfigure test -stipple bogus
+} -returnCodes error -result {bitmap "bogus" not defined}
+test canvRect-1.7 {configuration options: good value for -tags} -body {
+ .c itemconfigure test -tags {test a b c}
+ list [.c itemcget test -tags] [lindex [.c itemconfigure test -tags] 4]
+} -result {{test a b c} {test a b c}}
+test canvRect-1.8 {configuration options} -body {
+ .c itemconfigure test -tags {test xyz}
+ .c itemcget xyz -tags
+} -result {test xyz}
+test canvRect-1.9 {configuration options: good value for -width} -body {
+ .c itemconfigure test -width 6.0
+ list [.c itemcget test -width] [lindex [.c itemconfigure test -width] 4]
+} -result {6.0 6.0}
+test canvRect-1.10 {configuration options: bad value for -width} -body {
+ .c itemconfigure test -width abc
+} -returnCodes error -result {bad screen distance "abc"}
+.c delete withtag all
+
+
+test canvRect-2.1 {CreateRectOval procedure} -body {
+ .c create rect
+} -returnCodes error -result {wrong # args: should be ".c create rect coords ?arg ...?"}
+test canvRect-2.2 {CreateRectOval procedure} -body {
+ .c create oval x y z
+} -returnCodes error -result {wrong # coordinates: expected 0 or 4, got 3}
+test canvRect-2.3 {CreateRectOval procedure} -body {
+ .c create rectangle x 2 3 4
+} -returnCodes error -result {bad screen distance "x"}
+test canvRect-2.4 {CreateRectOval procedure} -body {
+ .c create rectangle 1 y 3 4
+} -returnCodes error -result {bad screen distance "y"}
+test canvRect-2.5 {CreateRectOval procedure} -body {
+ .c create rectangle 1 2 z 4
+} -returnCodes error -result {bad screen distance "z"}
+test canvRect-2.6 {CreateRectOval procedure} -body {
+ .c create rectangle 1 2 3 q
+} -returnCodes error -result {bad screen distance "q"}
+test canvRect-2.7 {CreateRectOval procedure} -body {
+ .c create rectangle 1 2 3 4 -tags x
+ set result {}
+ foreach element [.c coords x] {
+ lappend result [format %.1f $element]
+ }
+ set result
+} -result {1.0 2.0 3.0 4.0}
+test canvRect-2.8 {CreateRectOval procedure} -body {
+ .c create rectangle 1 2 3 4 -gorp foo
+} -returnCodes error -result {unknown option "-gorp"}
+.c delete withtag all
+
+
+test canvRect-3.1 {RectOvalCoords procedure} -body {
+ .c create rectangle 10 20 30 40 -tags x
+ set result {}
+ foreach element [.c coords x] {
+ lappend result [format %.1f $element]
+ }
+ return $result
+} -cleanup {
+ .c delete withtag all
+} -result {10.0 20.0 30.0 40.0}
+test canvRect-3.2 {RectOvalCoords procedure} -body {
+ .c create rectangle 10 20 30 40 -tags x
+ .c coords x a 2 3 4
+} -cleanup {
+ .c delete withtag all
+} -returnCodes error -result {bad screen distance "a"}
+test canvRect-3.3 {RectOvalCoords procedure} -body {
+ .c create rectangle 10 20 30 40 -tags x
+ .c coords x 1 b 3 4
+} -cleanup {
+ .c delete withtag all
+} -returnCodes error -result {bad screen distance "b"}
+test canvRect-3.4 {RectOvalCoords procedure} -body {
+ .c create rectangle 10 20 30 40 -tags x
+ .c coords x 1 2 c 4
+} -cleanup {
+ .c delete withtag all
+} -returnCodes error -result {bad screen distance "c"}
+test canvRect-3.5 {RectOvalCoords procedure} -body {
+ .c create rectangle 10 20 30 40 -tags x
+ .c coords x 1 2 3 d
+} -cleanup {
+ .c delete withtag all
+} -returnCodes error -result {bad screen distance "d"}
+test canvRect-3.6 {RectOvalCoords procedure} -constraints {
+ nonPortable
+} -body {
+ .c create rectangle 10 20 30 40 -tags x
+ # Non-portable due to rounding differences.
+ .c coords x 10 25 15 40
+ .c bbox x
+} -cleanup {
+ .c delete withtag all
+} -result {9 24 16 41}
+test canvRect-3.7 {RectOvalCoords procedure} -body {
+ .c create rectangle 10 20 30 40 -tags x
+ .c coords x 1 2 3 4 5
+} -cleanup {
+ .c delete withtag all
+} -returnCodes error -result {wrong # coordinates: expected 0 or 4, got 5}
+
+
+test canvRect-4.1 {ConfigureRectOval procedure} -body {
+ .c create rectangle 10 20 30 40 -tags x -width 1
+ .c itemconfigure x -width abc
+} -cleanup {
+ .c delete withtag all
+} -returnCodes error -result {bad screen distance "abc"}
+test canvRect-4.2 {ConfigureRectOval procedure} -body {
+ .c create rectangle 10 20 30 40 -tags x -width 1
+ catch {.c itemconfigure x -width abc}
+ .c itemcget x -width
+} -cleanup {
+ .c delete withtag all
+} -result {1.0}
+test canvRect-4.3 {ConfigureRectOval procedure} -body {
+ .c create rectangle 10 20 30 40 -tags x -width 1
+ .c itemconfigure x -width -5
+} -cleanup {
+ .c delete withtag all
+} -returnCodes error -result {bad screen distance "-5"}
+test canvRect-4.4 {ConfigureRectOval procedure} -constraints nonPortable -body {
+ # Non-portable due to rounding differences
+ .c create rectangle 10 20 30 40 -tags x -width 1
+ .c itemconfigure x -width 10
+ .c bbox x
+} -cleanup {
+ .c delete withtag all
+} -result {5 15 35 45}
+
+# I can't come up with any good tests for DeleteRectOval.
+
+test canvRect-5.1 {ComputeRectOvalBbox procedure} -constraints nonPortable -body {
+ # Non-portable due to rounding differences:
+ .c create rectangle 10 20 30 40 -tags x -width 1 -outline {}
+ .c coords x 20 15 10 5
+ .c bbox x
+} -cleanup {
+ .c delete withtag all
+} -result {10 5 20 15}
+test canvRect-5.2 {ComputeRectOvalBbox procedure} -constraints nonPortable -body {
+ # Non-portable due to rounding differences:
+ .c create rectangle 10 20 30 40 -tags x -width 1 -outline {}
+ .c coords x 10 20 30 10
+ .c itemconfigure x -width 1 -outline red
+ .c bbox x
+} -cleanup {
+ .c delete withtag all
+} -result {9 9 31 21}
+test canvRect-5.3 {ComputeRectOvalBbox procedure} -constraints nonPortable -body {
+ # Non-portable due to rounding differences:
+ .c create rectangle 10 20 30 40 -tags x -width 1 -outline {}
+ .c coords x 10 20 30 10
+ .c itemconfigure x -width 2 -outline red
+ .c bbox x
+} -cleanup {
+ .c delete withtag all
+} -result {9 9 31 21}
+test canvRect-5.4 {ComputeRectOvalBbox procedure} -constraints nonPortable -body {
+ # Non-portable due to rounding differences:
+ .c create rectangle 10 20 30 40 -tags x -width 1 -outline {}
+ .c coords x 10 20 30 10
+ .c itemconfigure x -width 3 -outline red
+ .c bbox x
+} -cleanup {
+ .c delete withtag all
+} -result {8 8 32 22}
+
+# I can't come up with any good tests for DisplayRectOval.
+
+test canvRect-6.1 {RectToPoint procedure} -body {
+ set xId [.c create rectangle 10 20 30 35 -tags x -fill green]
+ set yId [.c create rectangle 15 25 25 30 -tags y -fill red]
+ .c itemconfigure y -outline {}
+ list [expr {[.c find closest 14.9 28] eq $xId}] \
+ [expr {[.c find closest 15.1 28] eq $yId}] \
+ [expr {[.c find closest 24.9 28] eq $yId}] \
+ [expr {[.c find closest 25.1 28] eq $xId}]
+} -cleanup {
+ .c delete all
+} -result {1 1 1 1}
+test canvRect-6.2 {RectToPoint procedure} -body {
+ set xId [.c create rectangle 10 20 30 35 -tags x -fill green]
+ set yId [.c create rectangle 15 25 25 30 -tags y -fill red]
+ .c itemconfigure y -outline {}
+ list [expr {[.c find closest 20 24.9] eq $xId}] \
+ [expr {[.c find closest 20 25.1] eq $yId}] \
+ [expr {[.c find closest 20 29.9] eq $yId}] \
+ [expr {[.c find closest 20 30.1] eq $xId}]
+
+} -cleanup {
+ .c delete all
+} -result {1 1 1 1}
+test canvRect-6.3 {RectToPoint procedure} -body {
+ set xId [.c create rectangle 10 20 30 35 -tags x -fill green]
+ set yId [.c create rectangle 15 25 25 30 -tags y -fill red]
+ .c itemconfigure y -width 1 -outline black
+ list [expr {[.c find closest 14.4 28] eq $xId}] \
+ [expr {[.c find closest 14.6 28] eq $yId}] \
+ [expr {[.c find closest 25.4 28] eq $yId}] \
+ [expr {[.c find closest 25.6 28] eq $xId}]
+} -cleanup {
+ .c delete all
+} -result {1 1 1 1}
+test canvRect-6.4 {RectToPoint procedure} -body {
+ set xId [.c create rectangle 10 20 30 35 -tags x -fill green]
+ set yId [.c create rectangle 15 25 25 30 -tags y -fill red]
+ .c itemconfigure y -width 1 -outline black
+ list [expr {[.c find closest 20 24.4] eq $xId}] \
+ [expr {[.c find closest 20 24.6] eq $yId}] \
+ [expr {[.c find closest 20 30.4] eq $yId}] \
+ [expr {[.c find closest 20 30.6] eq $xId}]
+} -cleanup {
+ .c delete all
+} -result {1 1 1 1}
+
+test canvRect-6.5 {RectToPoint procedure} -body {
+ set xId [.c create rectangle 10 20 30 35 -tags x -fill green]
+ set yId [.c create rectangle 15 25 25 30 -tags y -fill red]
+ .c itemconfigure x -fill {} -outline black -width 3
+ .c itemconfigure y -outline {}
+ list [expr {[.c find closest 13.2 28] eq $xId}] \
+ [expr {[.c find closest 13.3 28] eq $yId}] \
+ [expr {[.c find closest 26.7 28] eq $yId}] \
+ [expr {[.c find closest 26.8 28] eq $xId}]
+} -cleanup {
+ .c delete all
+} -result {1 1 1 1}
+test canvRect-6.6 {RectToPoint procedure} -body {
+ set xId [.c create rectangle 10 20 30 35 -tags x -fill green]
+ set yId [.c create rectangle 15 25 25 30 -tags y -fill red]
+ .c itemconfigure x -fill {} -outline black -width 3
+ .c itemconfigure y -outline {}
+ list [expr {[.c find closest 20 23.2] eq $xId}] \
+ [expr {[.c find closest 20 23.3] eq $yId}] \
+ [expr {[.c find closest 20 31.7] eq $yId}] \
+ [expr {[.c find closest 20 31.8] eq $xId}]
+} -cleanup {
+ .c delete all
+} -result {1 1 1 1}
+
+test canvRect-6.7 {RectToPoint procedure} -body {
+ set xId [.c create rectangle 10 20 30 40 -outline {} -fill black]
+ set yId [.c create rectangle 40 40 50 50 -outline {} -fill black]
+ list [expr {[.c find closest 35 35] eq $xId}] \
+ [expr {[.c find closest 36 36] eq $yId}] \
+ [expr {[.c find closest 37 37] eq $yId}] \
+ [expr {[.c find closest 38 38] eq $yId}]
+} -cleanup {
+ .c delete all
+} -result {1 1 1 1}
+
+
+test canvRect-7.1 {RectToArea procedure} -body {
+ set xId [.c create rectangle 10 20 30 35 -fill green -outline {}]
+ set yId [.c create rectangle 40 45 60 70 -fill red -outline black -width 3]
+ set zId [.c create rectangle 100 150 120 170 -fill {} -outline black -width 3]
+ list [expr {[.c find overlapping 20 50 38 60] eq {}}] \
+ [expr {[.c find overlapping 20 50 39 60] eq $yId}] \
+ [expr {[.c find overlapping 20 50 70 60] eq $yId}] \
+ [expr {[.c find overlapping 61 50 70 60] eq $yId}] \
+ [expr {[.c find overlapping 62 50 70 60] eq {}}]
+} -cleanup {
+ .c delete all
+} -result {1 1 1 1 1}
+test canvRect-7.2 {RectToArea procedure} -body {
+ set xId [.c create rectangle 10 20 30 35 -fill green -outline {}]
+ set yId [.c create rectangle 40 45 60 70 -fill red -outline black -width 3]
+ set zId [.c create rectangle 100 150 120 170 -fill {} -outline black -width 3]
+ list [expr {[.c find overlapping 45 20 55 43] eq {}}] \
+ [expr {[.c find overlapping 45 20 55 44] eq $yId}] \
+ [expr {[.c find overlapping 45 20 55 80] eq $yId}] \
+ [expr {[.c find overlapping 45 71 55 80] eq $yId}] \
+ [expr {[.c find overlapping 45 72 55 80] eq {}}]
+} -cleanup {
+ .c delete all
+} -result {1 1 1 1 1}
+test canvRect-7.3 {RectToArea procedure} -body {
+ set xId [.c create rectangle 10 20 30 35 -fill green -outline {}]
+ set yId [.c create rectangle 40 45 60 70 -fill red -outline black -width 3]
+ set zId [.c create rectangle 100 150 120 170 -fill {} -outline black -width 3]
+ list [expr {[.c find overlapping 5 25 9.9 30] eq {}}] \
+ [expr {[.c find overlapping 5 25 10.1 30] eq $xId}]
+} -cleanup {
+ .c delete all
+} -result {1 1}
+test canvRect-7.4 {RectToArea procedure} -body {
+ set xId [.c create rectangle 10 20 30 35 -fill green -outline {}]
+ set yId [.c create rectangle 40 45 60 70 -fill red -outline black -width 3]
+ set zId [.c create rectangle 100 150 120 170 -fill {} -outline black -width 3]
+ list [expr {[.c find overlapping 102 152 118 168] eq {}}]\
+ [expr {[.c find overlapping 101 152 118 168] eq $zId}] \
+ [expr {[.c find overlapping 102 151 118 168] eq $zId}] \
+ [expr {[.c find overlapping 102 152 119 168] eq $zId}] \
+ [expr {[.c find overlapping 102 152 118 169] eq $zId}]
+} -cleanup {
+ .c delete all
+} -result {1 1 1 1 1}
+test canvRect-7.5 {RectToArea procedure} -body {
+ set xId [.c create rectangle 10 20 30 35 -fill green -outline {}]
+ set yId [.c create rectangle 40 45 60 70 -fill red -outline black -width 3]
+ set zId [.c create rectangle 100 150 120 170 -fill {} -outline black -width 3]
+ list [expr {[.c find enclosed 20 40 38 80] eq {}}] \
+ [expr {[.c find enclosed 20 40 39 80] eq {}}] \
+ [expr {[.c find enclosed 20 40 70 80] eq $yId}] \
+ [expr {[.c find enclosed 61 40 70 80] eq {}}] \
+ [expr {[.c find enclosed 62 40 70 80] eq {}}]
+} -cleanup {
+ .c delete all
+} -result {1 1 1 1 1}
+test canvRect-7.6 {RectToArea procedure} -body {
+ set xId [.c create rectangle 10 20 30 35 -fill green -outline {}]
+ set yId [.c create rectangle 40 45 60 70 -fill red -outline black -width 3]
+ set zId [.c create rectangle 100 150 120 170 -fill {} -outline black -width 3]
+ list [expr {[.c find enclosed 20 20 65 43] eq {}}] \
+ [expr {[.c find enclosed 20 20 65 44] eq {}}] \
+ [expr {[.c find enclosed 20 20 65 80] eq $yId}] \
+ [expr {[.c find enclosed 20 71 65 80] eq {}}] \
+ [expr {[.c find enclosed 20 72 65 80] eq {}}]
+} -cleanup {
+ .c delete all
+} -result {1 1 1 1 1}
+
+
+test canvRect-8.1 {OvalToArea procedure} -body {
+ set xId [.c create oval 50 100 200 150 -fill green -outline {}]
+ set yId [.c create oval 50 100 200 150 -fill red -outline black -width 3]
+ set zId [.c create oval 50 100 200 150 -fill {} -outline black -width 3]
+ list [expr {[.c find overlapping 20 120 48 130] eq {}}] \
+ [expr {[.c find overlapping 20 120 49 130] eq "$yId $zId"}] \
+ [expr {[.c find overlapping 20 120 50.2 130] eq "$xId $yId $zId"}] \
+ [expr {[.c find overlapping 20 120 300 130] eq "$xId $yId $zId"}] \
+ [expr {[.c find overlapping 60 120 190 130] eq "$xId $yId"}] \
+ [expr {[.c find overlapping 199.9 120 300 130] eq "$xId $yId $zId"}] \
+ [expr {[.c find overlapping 201 120 300 130] eq "$yId $zId"}] \
+ [expr {[.c find overlapping 202 120 300 130] eq {}}]
+} -cleanup {
+ .c delete all
+} -result {1 1 1 1 1 1 1 1}
+test canvRect-8.2 {OvalToArea procedure} -body {
+ set xId [.c create oval 50 100 200 150 -fill green -outline {}]
+ set yId [.c create oval 50 100 200 150 -fill red -outline black -width 3]
+ set zId [.c create oval 50 100 200 150 -fill {} -outline black -width 3]
+ list [expr {[.c find overlapping 100 50 150 98] eq {}}] \
+ [expr {[.c find overlapping 100 50 150 99] eq "$yId $zId"}] \
+ [expr {[.c find overlapping 100 50 150 100.1] eq "$xId $yId $zId"}] \
+ [expr {[.c find overlapping 100 50 150 200] eq "$xId $yId $zId"}] \
+ [expr {[.c find overlapping 100 110 150 140] eq "$xId $yId"}] \
+ [expr {[.c find overlapping 100 149.9 150 200] eq "$xId $yId $zId"}] \
+ [expr {[.c find overlapping 100 151 150 200] eq "$yId $zId"}] \
+ [expr {[.c find overlapping 100 152 150 200] eq {}}]
+} -cleanup {
+ .c delete all
+} -result {1 1 1 1 1 1 1 1}
+test canvRect-8.3 {OvalToArea procedure} -body {
+ set xId [.c create oval 50 100 200 150 -fill green -outline {}]
+ set yId [.c create oval 50 100 200 150 -fill red -outline black -width 3]
+ set zId [.c create oval 50 100 200 150 -fill {} -outline black -width 3]
+ list [expr {[.c find overlapping 176 104 177 105] eq {}}] \
+ [expr {[.c find overlapping 187 116 188 117] eq "$xId $yId"}] \
+ [expr {[.c find overlapping 192 142 193 143] eq {}}] \
+ [expr {[.c find overlapping 180 138 181 139] eq "$xId $yId"}] \
+ [expr {[.c find overlapping 61 142 62 143] eq {}}] \
+ [expr {[.c find overlapping 65 137 66 136] eq "$xId $yId"}] \
+ [expr {[.c find overlapping 62 108 63 109] eq {}}] \
+ [expr {[.c find overlapping 68 115 69 116] eq "$xId $yId"}]
+} -cleanup {
+ .c delete all
+} -result {1 1 1 1 1 1 1 1}
+
+
+test canvRect-9.1 {ScaleRectOval procedure} -setup {
+ .c delete withtag all
+} -body {
+ .c create rect 100 300 200 350 -tags x
+ .c scale x 50 100 2 4
+ format {%.6g %.6g %.6g %.6g} {*}[.c coords x]
+} -result {150 900 350 1100}
+
+test canvRect-10.1 {TranslateRectOval procedure} -setup {
+ .c delete withtag all
+} -body {
+ .c create rect 100 300 200 350 -tags x
+ .c move x 100 -10
+ format {%.6g %.6g %.6g %.6g} {*}[.c coords x]
+} -result {200 290 300 340}
+
+
+test canvRect-11.1 {RectOvalToPostscript procedure} -constraints {
+ nonPortable macCrash
+} -setup {
+ .c delete withtag all
+} -body {
+ # Crashes on Mac because the XGetImage() call isn't implemented, causing a
+ # dereference of NULL.
+ # This test is non-portable because different color information
+ # will get generated on different displays (e.g. mono displays
+ # vs. color).
+ .c configure -bd 0 -highlightthickness 0
+ .c create rect 50 60 90 80 -fill black -stipple gray50 -outline {}
+ .c create oval 100 150 200 200 -fill {} -outline #ff0000 -width 5
+ update
+ set x [.c postscript]
+ string range $x [string first "-200 -150 translate" $x] end
+} -result {-200 -150 translate
+0 300 moveto 400 300 lineto 400 0 lineto 0 0 lineto closepath clip newpath
+gsave
+50 240 moveto 40 0 rlineto 0 -20 rlineto -40 0 rlineto closepath
+0.000 0.000 0.000 setrgbcolor AdjustColor
+clip 16 16 <5555aaaa5555aaaa5555aaaa5555aaaa5555aaaa5555aaaa5555aaaa5555
+aaaa> StippleFill
+grestore
+gsave
+matrix currentmatrix
+150 125 translate 50 25 scale 1 0 moveto 0 0 1 0 360 arc
+setmatrix
+5 setlinewidth 0 setlinejoin 2 setlinecap
+1.000 0.000 0.000 setrgbcolor AdjustColor
+stroke
+grestore
+restore showpage
+
+%%Trailer
+end
+%%EOF
+}
+
+# cleanup
+cleanupTests
+return
+
+
+
+
diff --git a/tk8.6/tests/canvText.test b/tk8.6/tests/canvText.test
new file mode 100644
index 0000000..b2af39b
--- /dev/null
+++ b/tk8.6/tests/canvText.test
@@ -0,0 +1,950 @@
+# This file is a Tcl script to test out the procedures in tkCanvText.c,
+# which implement canvas "text" items. It is organized in the standard
+# fashion for Tcl tests.
+#
+# Copyright (c) 1996-1997 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+
+# Canvas used in 1.* - 17.* tests
+canvas .c -width 400 -height 300 -bd 2 -relief sunken
+pack .c
+update
+
+# Item used in 1.* tests
+.c create text 20 20 -tag test
+test canvText-1.1 {configuration options: good value for "anchor"} -body {
+ .c itemconfigure test -anchor nw
+ list [lindex [.c itemconfigure test -anchor] 4] [.c itemcget test -anchor]
+} -result {nw nw}
+test canvasText-1.2 {configuration options: bad value for "anchor"} -body {
+ .c itemconfigure test -anchor xyz
+} -returnCodes error -result {bad anchor position "xyz": must be n, ne, e, se, s, sw, w, nw, or center}
+test canvText-1.3 {configuration options: good value for "fill"} -body {
+ .c itemconfigure test -fill #ff0000
+ list [lindex [.c itemconfigure test -fill] 4] [.c itemcget test -fill]
+} -result {{#ff0000} #ff0000}
+test canvasText-1.4 {configuration options: bad value for "fill"} -body {
+ .c itemconfigure test -fill xyz
+} -returnCodes error -result {unknown color name "xyz"}
+test canvText-1.5 {configuration options: good value for "fill"} -body {
+ .c itemconfigure test -fill {}
+ list [lindex [.c itemconfigure test -fill] 4] [.c itemcget test -fill]
+} -result {{} {}}
+test canvText-1.6 {configuration options: good value for "font"} -body {
+ .c itemconfigure test -font {Times 40}
+ list [lindex [.c itemconfigure test -font] 4] [.c itemcget test -font]
+} -result {{Times 40} {Times 40}}
+test canvasText-1.7 {configuration options: bad value for "font"} -body {
+ .c itemconfigure test -font {}
+} -returnCodes error -result {font "" doesn't exist}
+test canvText-1.8 {configuration options: good value for "justify"} -body {
+ .c itemconfigure test -justify left
+ list [lindex [.c itemconfigure test -justify] 4] [.c itemcget test -justify]
+} -result {left left}
+test canvasText-1.9 {configuration options: bad value for "justify"} -body {
+ .c itemconfigure test -justify xyz
+} -returnCodes error -result {bad justification "xyz": must be left, right, or center}
+test canvText-1.10 {configuration options: good value for "stipple"} -body {
+ .c itemconfigure test -stipple gray50
+ list [lindex [.c itemconfigure test -stipple] 4] [.c itemcget test -stipple]
+} -result {gray50 gray50}
+test canvasText-1.11 {configuration options: bad value for "stipple"} -body {
+ .c itemconfigure test -stipple abcxyz
+} -returnCodes error -result {bitmap "abcxyz" not defined}
+test canvText-1.12 {configuration options: good value for "underline"} -body {
+ .c itemconfigure test -underline 0
+ list [lindex [.c itemconfigure test -underline] 4] [.c itemcget test -underline]
+} -result {0 0}
+test canvasText-1.13 {configuration options: bad value for "underline"} -body {
+ .c itemconfigure test -underline xyz
+} -returnCodes error -result {expected integer but got "xyz"}
+test canvText-1.14 {configuration options: good value for "width"} -body {
+ .c itemconfigure test -width 6
+ list [lindex [.c itemconfigure test -width] 4] [.c itemcget test -width]
+} -result {6 6}
+test canvasText-1.15 {configuration options: bad value for "width"} -body {
+ .c itemconfigure test -width xyz
+} -returnCodes error -result {bad screen distance "xyz"}
+test canvText-1.16 {configuration options: good value for "tags"} -body {
+ .c itemconfigure test -tags {test a b c}
+ list [lindex [.c itemconfigure test -tags] 4] [.c itemcget test -tags]
+} -result {{test a b c} {test a b c}}
+test canvasText-1.17 {configuration options: bad value for "angle"} -body {
+ .c itemconfigure test -angle xyz
+} -returnCodes error -result {expected floating-point number but got "xyz"}
+test canvasText-1.18 {configuration options: good value for "angle"} -body {
+ .c itemconfigure test -angle 32.5
+ list [lindex [.c itemconfigure test -angle] 4] [.c itemcget test -angle]
+} -result {32.5 32.5}
+test canvasText-1.19 {configuration options: bounding of "angle"} -body {
+ .c itemconfigure test -angle 390
+ set result [.c itemcget test -angle]
+ .c itemconfigure test -angle -30
+ lappend result [.c itemcget test -angle]
+ .c itemconfigure test -angle -360
+ lappend result [.c itemcget test -angle]
+} -result {30.0 330.0 0.0}
+.c delete test
+
+
+test canvText-2.1 {CreateText procedure: args} -body {
+ .c create text
+} -returnCodes {error} -result {wrong # args: should be ".c create text coords ?arg ...?"}
+test canvText-2.2 {CreateText procedure: args} -body {
+ .c create text xyz 0
+} -cleanup {
+ .c delete all
+} -returnCodes {error} -result {bad screen distance "xyz"}
+test canvText-2.3 {CreateText procedure: args} -body {
+ .c create text 0 xyz
+} -cleanup {
+ .c delete all
+} -returnCodes {error} -result {bad screen distance "xyz"}
+test canvText-2.4 {CreateText procedure: args} -body {
+ .c create text 0 0 -xyz xyz
+} -cleanup {
+ .c delete all
+} -returnCodes {error} -result {unknown option "-xyz"}
+test canvText-2.5 {CreateText procedure} -body {
+ .c create text 0 0 -tags x
+ .c coords x
+} -cleanup {
+ .c delete x
+} -result {0.0 0.0}
+
+
+test canvText-3.1 {TextCoords procedure} -body {
+ .c create text 20 20 -tag test
+ .c coords test 0 0
+ update
+ .c coords test
+} -cleanup {
+ .c delete test
+} -result {0.0 0.0}
+test canvText-3.2 {TextCoords procedure} -setup {
+ .c create text 20 20 -tag test
+} -body {
+ .c coords test xyz 0
+} -cleanup {
+ .c delete test
+} -returnCodes {error} -result {bad screen distance "xyz"}
+test canvText-3.3 {TextCoords procedure} -setup {
+ .c create text 20 20 -tag test
+} -body {
+ .c coords test 0 xyz
+} -cleanup {
+ .c delete test
+} -returnCodes {error} -result {bad screen distance "xyz"}
+test canvText-3.4 {TextCoords procedure} -setup {
+ .c create text 20 20 -tag test
+} -body {
+ .c coords test 10 10
+ set result {}
+ foreach element [.c coords test] {
+ lappend result [format %.1f $element]
+ }
+ return $result
+} -cleanup {
+ .c delete test
+} -result {10.0 10.0}
+test canvText-3.5 {TextCoords procedure} -setup {
+ .c create text 20 20 -tag test
+} -body {
+ .c coords test 10
+} -cleanup {
+ .c delete test
+} -returnCodes {error} -result {wrong # coordinates: expected 2, got 1}
+test canvText-3.6 {TextCoords procedure} -setup {
+ .c create text 20 20 -tag test
+} -body {
+ .c coords test 10 10 10
+} -cleanup {
+ .c delete test
+} -returnCodes {error} -result {wrong # coordinates: expected 0 or 2, got 3}
+
+
+test canvText-4.1 {ConfigureText procedure} -setup {
+ .c create text 20 20 -tag test
+} -body {
+ .c itemconfig test -fill xyz
+} -cleanup {
+ .c delete test
+} -returnCodes {error} -result {unknown color name "xyz"}
+test canvText-4.2 {ConfigureText procedure} -setup {
+ .c create text 20 20 -tag test
+} -body {
+ .c itemconfig test -fill blue
+ .c itemcget test -fill
+} -cleanup {
+ .c delete test
+} -result {blue}
+test canvText-4.3 {ConfigureText procedure: construct font gcs} -setup {
+ .c create text 20 20 -tag test
+} -body {
+ .c itemconfig test -font "times 20" -fill black -stipple gray50
+ list [.c itemcget test -font] [.c itemcget test -fill] [.c itemcget test -stipple]
+} -cleanup {
+ .c delete test
+} -result {{times 20} black gray50}
+test canvText-4.4 {ConfigureText procedure: construct cursor gc} -setup {
+ .c create text 20 20 -tag test
+ focus .c
+ .c focus test
+} -body {
+ .c itemconfig test -text "abcdefg"
+ .c select from test 2
+ .c select to test 4
+ .c icursor test 3
+ # Both black -> cursor becomes white.
+ .c config -insertbackground black
+ .c config -selectbackground black
+ .c itemconfig test -just left
+ update
+ # Both same color (and not black) -> cursor becomes black.
+ .c config -insertbackground red
+ .c config -selectbackground red
+ .c itemconfig test -just left
+ update
+} -cleanup {
+ .c delete test
+} -result {}
+test canvText-4.5 {ConfigureText procedure: adjust selection} -setup {
+ .c create text 20 20 -tag test
+ focus .c
+ .c focus test
+ set x {}
+} -body {
+ .c itemconfig test -text "abcdefghi"
+ .c select from test 2
+ .c select to test 6
+ lappend x [selection get]
+ .c dchars test 1 end
+ lappend x [catch {selection get}]
+ .c insert test end "bcdefghi"
+ .c select from test 2
+ .c select to test 6
+ lappend x [selection get]
+ .c dchars test 4 end
+ lappend x [selection get]
+ .c insert test end "efghi"
+ .c select from test 6
+ .c select to test 2
+ lappend x [selection get]
+ .c dchars test 4 end
+ lappend x [selection get]
+} -cleanup {
+ .c delete test
+} -result {cdefg 1 cdefg cd cdef cd}
+test canvText-4.6 {ConfigureText procedure: adjust cursor} -setup {
+ .c create text 20 20 -tag test
+} -body {
+ .c itemconfig test -text "abcdefghi"
+ .c icursor test 6
+ .c dchars test 4 end
+ .c index test insert
+} -cleanup {
+ .c delete test
+} -result {4}
+
+
+test canvText-5.1 {ConfigureText procedure: adjust cursor} -body {
+ .c create text 10 10 -tag x -fill blue -font "times 40" -stipple gray50 \
+ -text "xyz"
+ .c delete x
+} -result {}
+
+
+test canvText-6.1 {ComputeTextBbox procedure} -constraints fonts -setup {
+ .c delete test
+} -body {
+ set font "-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*"
+ set ay [font metrics $font -linespace]
+ set ax [font measure $font 0]
+ .c create text 0 0 -tag test
+ .c itemconfig test -font $font -text 0
+ expr {[.c itemconfig test -anchor n; .c bbox test] \
+ eq "[expr {-$ax/2-1}] 0 [expr {$ax/2+1}] $ay"}
+} -cleanup {
+ .c delete test
+} -result 1
+test canvText-6.2 {ComputeTextBbox procedure} -constraints fonts -setup {
+ .c delete test
+} -body {
+ set font "-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*"
+ set ay [font metrics $font -linespace]
+ set ax [font measure $font 0]
+ .c create text 0 0 -tag test
+ .c itemconfig test -font $font -text 0
+ expr {[.c itemconfig test -anchor nw; .c bbox test] \
+ eq "-1 0 [expr {$ax+1}] $ay"}
+} -cleanup {
+ .c delete test
+} -result 1
+test canvText-6.3 {ComputeTextBbox procedure} -constraints fonts -setup {
+ .c delete test
+} -body {
+ set font "-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*"
+ set ay [font metrics $font -linespace]
+ set ax [font measure $font 0]
+ .c create text 0 0 -tag test
+ .c itemconfig test -font $font -text 0
+ expr {[.c itemconfig test -anchor w; .c bbox test] \
+ eq "-1 [expr -$ay/2] [expr $ax+1] [expr $ay/2]"}
+} -cleanup {
+ .c delete test
+} -result 1
+test canvText-6.4 {ComputeTextBbox procedure} -constraints fonts -setup {
+ .c delete test
+} -body {
+ set font "-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*"
+ set ay [font metrics $font -linespace]
+ set ax [font measure $font 0]
+ .c create text 0 0 -tag test
+ .c itemconfig test -font $font -text 0
+ expr {[.c itemconfig test -anchor sw; .c bbox test] \
+ eq "-1 -$ay [expr $ax+1] 0"}
+} -cleanup {
+ .c delete test
+} -result 1
+test canvText-6.5 {ComputeTextBbox procedure} -constraints fonts -setup {
+ .c delete test
+} -body {
+ set font "-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*"
+ set ay [font metrics $font -linespace]
+ set ax [font measure $font 0]
+ .c create text 0 0 -tag test
+ .c itemconfig test -font $font -text 0
+ expr {[.c itemconfig test -anchor s; .c bbox test] \
+ eq "[expr -$ax/2-1] -$ay [expr $ax/2+1] 0"}
+} -cleanup {
+ .c delete test
+} -result 1
+test canvText-6.6 {ComputeTextBbox procedure} -constraints fonts -setup {
+ .c delete test
+} -body {
+ set font "-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*"
+ set ay [font metrics $font -linespace]
+ set ax [font measure $font 0]
+ .c create text 0 0 -tag test
+ .c itemconfig test -font $font -text 0
+ expr {[.c itemconfig test -anchor se; .c bbox test] \
+ eq "[expr -$ax-1] -$ay 1 0"}
+} -cleanup {
+ .c delete test
+} -result 1
+test canvText-6.7 {ComputeTextBbox procedure} -constraints fonts -setup {
+ .c delete test
+} -body {
+ set font "-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*"
+ set ay [font metrics $font -linespace]
+ set ax [font measure $font 0]
+ .c create text 0 0 -tag test
+ .c itemconfig test -font $font -text 0
+ expr {[.c itemconfig test -anchor e; .c bbox test]\
+ eq "[expr -$ax-1] [expr -$ay/2] 1 [expr $ay/2]"}
+} -cleanup {
+ .c delete test
+} -result 1
+test canvText-6.8 {ComputeTextBbox procedure} -constraints fonts -setup {
+ .c delete test
+} -body {
+ set font "-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*"
+ set ay [font metrics $font -linespace]
+ set ax [font measure $font 0]
+ .c create text 0 0 -tag test
+ .c itemconfig test -font $font -text 0
+ expr {[.c itemconfig test -anchor ne; .c bbox test] \
+ eq "[expr -$ax-1] 0 1 $ay"}
+} -cleanup {
+ .c delete test
+} -result 1
+test canvText-6.9 {ComputeTextBbox procedure} -constraints fonts -setup {
+ .c delete test
+} -body {
+ set font "-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*"
+ set ay [font metrics $font -linespace]
+ set ax [font measure $font 0]
+ .c create text 0 0 -tag test
+ .c itemconfig test -font $font -text 0
+ expr {[.c itemconfig test -anchor center; .c bbox test] \
+ eq "[expr -$ax/2-1] [expr -$ay/2] [expr $ax/2+1] [expr $ay/2]"}
+} -cleanup {
+ .c delete test
+} -result 1
+
+
+#.c delete test
+#.c create text 20 20 -tag test
+#focus -force .c
+#.c focus test
+focus .c
+.c focus test
+.c itemconfig test -text "abcd\nefghi\njklmnopq"
+test canvText-7.1 {DisplayText procedure: stippling} -body {
+ .c create text 20 20 -tag test
+ .c itemconfig test -stipple gray50
+ update
+ .c itemconfig test -stipple {}
+ update
+} -cleanup {
+ .c delete test
+} -result {}
+test canvText-7.2 {DisplayText procedure: draw selection} -setup {
+ .c create text 20 20 -tag test
+ focus .c
+ .c focus test
+} -body {
+ .c itemconfig test -text "abcd\nefghi\njklmnopq"
+ .c select from test 0
+ .c select to test end
+ update
+ selection get
+} -cleanup {
+ .c delete test
+} -result "abcd\nefghi\njklmnopq"
+test canvText-7.3 {DisplayText procedure: selection} -setup {
+ .c create text 20 20 -tag test
+ focus .c
+ .c focus test
+} -body {
+ .c itemconfig test -text "abcd\nefghi\njklmnopq"
+ .c select from test 0
+ .c select to test end
+ update
+ selection get
+} -cleanup {
+ .c delete test
+} -result "abcd\nefghi\njklmnopq"
+test canvText-7.4 {DisplayText procedure: one line selection} -setup {
+ .c create text 20 20 -tag test
+ focus .c
+ .c focus test
+} -body {
+ .c itemconfig test -text "abcd\nefghi\njklmnopq"
+ .c select from test 2
+ .c select to test 3
+ update
+} -cleanup {
+ .c delete test
+} -result {}
+test canvText-7.5 {DisplayText procedure: multi-line selection} -setup {
+ .c create text 20 20 -tag test
+ focus .c
+ .c focus test
+} -body {
+ .c itemconfig test -text "abcd\nefghi\njklmnopq"
+ .c select from test 2
+ .c select to test 12
+ update
+} -cleanup {
+ .c delete test
+} -result {}
+test canvText-7.6 {DisplayText procedure: draw cursor} -setup {
+ .c create text 20 20 -tag test
+ focus .c
+ .c focus test
+} -body {
+ .c itemconfig test -text "abcd\nefghi\njklmnopq"
+ .c icursor test 3
+ update
+} -cleanup {
+ .c delete test
+} -result {}
+test canvText-7.7 {DisplayText procedure: selected text different color} -setup {
+ .c create text 20 20 -tag test
+ .c itemconfig test -text "abcd\nefghi\njklmnopq"
+ focus .c
+ .c focus test
+} -body {
+ .c config -selectforeground blue
+ .c itemconfig test -anchor n
+ update
+} -cleanup {
+ .c delete test
+} -result {}
+test canvText-7.8 {DisplayText procedure: not selected} -setup {
+ .c create text 20 20 -tag test
+ .c itemconfig test -text "abcd\nefghi\njklmnopq"
+ focus .c
+ .c focus test
+} -body {
+ .c select clear
+ update
+} -cleanup {
+ .c delete test
+} -result {}
+test canvText-7.9 {DisplayText procedure: select end} -setup {
+ destroy .t
+} -body {
+ toplevel .t
+ wm geometry .t +0+0
+ canvas .t.c
+ pack .t.c
+ set id [.t.c create text 0 0 -text Dummy -anchor nw]
+ update
+ .t.c select from $id 0
+ .t.c select to $id end
+ update
+ #catch {destroy .t}
+ update
+} -cleanup {
+ destroy .t
+} -result {}
+
+test canvText-8.1 {TextInsert procedure: 0 length insert} -setup {
+ .c create text 20 20 -tag test
+ .c itemconfig test -text "abcd\nefghi\njklmnopq"
+ focus .c
+ .c focus test
+} -body {
+ .c insert test end {}
+} -cleanup {
+ .c delete test
+} -result {}
+test canvText-8.2 {TextInsert procedure: before beginning/after end} -body {
+ # Can't test this because GetTextIndex filters out those numbers.
+} -result {}
+test canvText-8.3 {TextInsert procedure: inserting in a selected item} -setup {
+ .c create text 20 20 -tag test
+ focus .c
+ .c focus test
+} -body {
+ .c itemconfig test -text "abcdefg"
+ .c select from test 2
+ .c select to test 4
+ .c insert test 1 "xyz"
+ .c itemcget test -text
+} -result {axyzbcdefg}
+test canvText-8.4 {TextInsert procedure: inserting before selection} -setup {
+ .c create text 20 20 -tag test
+ focus .c
+ .c focus test
+} -body {
+ .c itemconfig test -text "abcdefg"
+ .c select from test 2
+ .c select to test 4
+ .c insert test 1 "xyz"
+ list [.c index test sel.first] [.c index test sel.last]
+} -result {5 7}
+test canvText-8.5 {TextInsert procedure: inserting in selection} -setup {
+ .c create text 20 20 -tag test
+ focus .c
+ .c focus test
+} -body {
+ .c itemconfig test -text "abcdefg"
+ .c select from test 2
+ .c select to test 4
+ .c insert test 3 "xyz"
+ list [.c index test sel.first] [.c index test sel.last]
+} -result {2 7}
+test canvText-8.6 {TextInsert procedure: inserting after selection} -setup {
+ .c create text 20 20 -tag test
+ focus .c
+ .c focus test
+} -body {
+ .c itemconfig test -text "abcdefg"
+ .c select from test 2
+ .c select to test 4
+ .c insert test 5 "xyz"
+ list [.c index test sel.first] [.c index test sel.last]
+} -result {2 4}
+test canvText-8.7 {TextInsert procedure: inserting in unselected item} -setup {
+ .c create text 20 20 -tag test
+ focus .c
+ .c focus test
+} -body {
+ .c itemconfig test -text "abcdefg"
+ .c select clear
+ .c insert test 5 "xyz"
+ .c itemcget test -text
+} -result {abcdexyzfg}
+test canvText-8.8 {TextInsert procedure: inserting before cursor} -setup {
+ .c create text 20 20 -tag test
+ focus .c
+ .c focus test
+} -body {
+ .c itemconfig test -text "abcdefg"
+ .c icursor test 3
+ .c insert test 2 "xyz"
+ .c index test insert
+} -result {6}
+test canvText-8.9 {TextInsert procedure: inserting after cursor} -setup {
+ .c create text 20 20 -tag test
+ focus .c
+ .c focus test
+} -body {
+ .c itemconfig test -text "abcdefg"
+ .c icursor test 3
+ .c insert test 4 "xyz"
+ .c index test insert
+} -result {3}
+
+# Item used in 9.* tests
+.c create text 20 20 -tag test
+test canvText-9.1 {TextInsert procedure: before beginning/after end} -body {
+ # Can't test this because GetTextIndex filters out those numbers.
+} -result {}
+test canvText-9.2 {TextInsert procedure: start > end} -body {
+ .c itemconfig test -text "abcdefg"
+ .c dchars test 4 2
+ .c itemcget test -text
+} -result {abcdefg}
+test canvText-9.3 {TextInsert procedure: deleting from a selected item} -body {
+ .c itemconfig test -text "abcdefg"
+ .c select from test 2
+ .c select to test 4
+ .c dchars test 3 5
+ .c itemcget test -text
+} -result {abcg}
+test canvText-9.4 {TextInsert procedure: deleting before start} -body {
+ .c itemconfig test -text "abcdefghijk"
+ .c select from test 4
+ .c select to test 8
+ .c dchars test 1 1
+ list [.c index test sel.first] [.c index test sel.last]
+} -result {3 7}
+test canvText-9.5 {TextInsert procedure: keep start > first char deleted} -body {
+ .c itemconfig test -text "abcdefghijk"
+ .c select from test 4
+ .c select to test 8
+ .c dchars test 2 6
+ list [.c index test sel.first] [.c index test sel.last]
+} -result {2 3}
+test canvText-9.6 {TextInsert procedure: deleting inside selection} -body {
+ .c itemconfig test -text "abcdefghijk"
+ .c select from test 4
+ .c select to test 8
+ .c dchars test 6 6
+ list [.c index test sel.first] [.c index test sel.last]
+} -result {4 7}
+test canvText-9.7 {TextInsert procedure: keep end > first char deleted} -body {
+ .c itemconfig test -text "abcdefghijk"
+ .c select from test 4
+ .c select to test 8
+ .c dchars test 6 10
+ list [.c index test sel.first] [.c index test sel.last]
+} -result {4 5}
+test canvText-9.8 {TextInsert procedure: selectFirst > selectLast: deselect} -body {
+ .c itemconfig test -text "abcdefghijk"
+ .c select from test 4
+ .c select to test 8
+ .c dchars test 3 10
+ .c index test sel.first
+} -returnCodes {error} -result {selection isn't in item}
+test canvText-9.9 {TextInsert procedure: selectFirst <= selectLast} -body {
+ .c itemconfig test -text "abcdefghijk"
+ .c select from test 4
+ .c select to test 8
+ .c dchars test 4 7
+ list [.c index test sel.first] [.c index test sel.last]
+} -result {4 4}
+test canvText-9.10 {TextInsert procedure: move anchor} -body {
+ .c itemconfig test -text "abcdefghijk"
+ .c select from test 6
+ .c select to test 8
+ .c dchars test 2 4
+ .c select to test 1
+ list [.c index test sel.first] [.c index test sel.last]
+} -result {1 2}
+test canvText-9.11 {TextInsert procedure: keep anchor >= first} -body {
+ .c itemconfig test -text "abcdefghijk"
+ .c select from test 6
+ .c select to test 8
+ .c dchars test 5 7
+ .c select to test 1
+ list [.c index test sel.first] [.c index test sel.last]
+} -result {1 4}
+test canvText-9.12 {TextInsert procedure: anchor doesn't move} -body {
+ .c itemconfig test -text "abcdefghijk"
+ .c select from test 2
+ .c select to test 5
+ .c dchars test 6 8
+ .c select to test 8
+ list [.c index test sel.first] [.c index test sel.last]
+} -result {2 8}
+test canvText-9.13 {TextInsert procedure: move cursor} -body {
+ .c itemconfig test -text "abcdefghijk"
+ .c icursor test 6
+ .c dchars test 2 4
+ .c index test insert
+} -result {3}
+test canvText-9.14 {TextInsert procedure: keep cursor >= first} -body {
+ .c itemconfig test -text "abcdefghijk"
+ .c icursor test 6
+ .c dchars test 2 10
+ .c index test insert
+} -result {2}
+test canvText-9.15 {TextInsert procedure: cursor doesn't move} -body {
+ .c itemconfig test -text "abcdefghijk"
+ .c icursor test 5
+ .c dchars test 7 9
+ .c index test insert
+} -result {5}
+.c delete test
+
+
+test canvText-10.1 {TextToPoint procedure} -body {
+ .c create text 0 0 -tag test
+ .c itemconfig test -text 0 -anchor center
+ .c index test @0,0
+} -cleanup {
+ .c delete test
+} -result {0}
+
+
+test canvText-11.1 {TextToArea procedure} -setup {
+ .c create text 0 0 -tag test
+ focus .c
+ .c focus test
+} -body {
+ .c itemconfig test -text 0 -anchor center
+ set res1 [.c find overlapping 0 0 1 1]
+ set res2 [.c find withtag test]
+ expr {$res1 eq $res2}
+} -cleanup {
+ .c delete test
+} -result 1
+test canvText-11.2 {TextToArea procedure} -setup {
+ .c create text 0 0 -tag test
+ focus .c
+ .c focus test
+} -body {
+ .c itemconfig test -text 0 -anchor center
+ .c find overlapping 1000 1000 1001 1001
+} -cleanup {
+ .c delete test
+} -result {}
+
+
+test canvText-12.1 {ScaleText procedure} -body {
+ .c create text 100 100 -tag test
+ .c scale all 50 50 2 2
+ format {%.6g %.6g} {*}[.c coords test]
+} -cleanup {
+ .c delete test
+} -result {150 150}
+
+
+test canvText-13.1 {TranslateText procedure} -body {
+ .c create text 100 100 -tag test
+ .c move all 10 10
+ format {%.6g %.6g} {*}[.c coords test]
+} -cleanup {
+ .c delete test
+} -result {110 110}
+
+
+test canvText-14.1 {GetTextIndex procedure} -setup {
+ .c create text 0 0 -tag test
+ focus .c
+ .c focus test
+} -body {
+ .c itemconfig test -text "abcdefghijklmno" -anchor nw
+ .c select from test 5
+ .c select to test 8
+ .c icursor test 12
+ .c coords test 0 0
+ list [.c index test end] [.c index test insert] \
+ [.c index test sel.first] [.c index test sel.last] \
+ [.c index test @0,0] \
+ [.c index test -1] [.c index test 10] [.c index test 100]
+} -cleanup {
+ .c delete test
+} -result {15 12 5 8 0 0 10 15}
+test canvText-14.2 {GetTextIndex procedure: select error} -setup {
+ .c create text 0 0 -tag test
+ focus .c
+ .c focus test
+} -body {
+ .c select clear
+ .c index test sel.first
+} -cleanup {
+ .c delete test
+} -returnCodes {error} -result {selection isn't in item}
+test canvText-14.3 {GetTextIndex procedure: select error} -setup {
+ .c create text 0 0 -tag test
+ focus .c
+ .c focus test
+} -body {
+ .c select clear
+ .c index test sel.last
+} -cleanup {
+ .c delete test
+} -returnCodes {error} -result {selection isn't in item}
+test canvText-14.4 {GetTextIndex procedure: select error} -setup {
+ .c create text 0 0 -tag test
+ focus .c
+ .c focus test
+} -body {
+ .c select clear
+ .c index test sel.
+} -cleanup {
+ .c delete test
+} -returnCodes {error} -result {bad index "sel."}
+test canvText-14.5 {GetTextIndex procedure: bad int or unknown index} -setup {
+ .c create text 0 0 -tag test
+ focus .c
+ .c focus test
+} -body {
+ .c index test xyz
+} -cleanup {
+ .c delete test
+} -returnCodes {error} -result {bad index "xyz"}
+test canvText-14.6 {select clear errors} -setup {
+ .c create text 0 0 -tag test
+} -body {
+ .c select clear test
+} -cleanup {
+ .c delete test
+} -returnCodes error -result "wrong \# args: should be \".c select clear\""
+
+test canvText-15.1 {SetTextCursor procedure} -setup {
+ .c create text 0 0 -tag test
+ focus .c
+ .c focus test
+} -body {
+ .c itemconfig test -text "abcdefghijklmno" -anchor nw
+ .c itemconfig -text "abcdefg"
+ .c icursor test 3
+ .c index test insert
+} -cleanup {
+ .c delete test
+} -result {3}
+
+test canvText-16.1 {GetSelText procedure} -setup {
+ .c create text 0 0 -tag test
+ focus .c
+ .c focus test
+} -body {
+ .c itemconfig test -text "abcdefghijklmno" -anchor nw
+ .c select from test 5
+ .c select to test 8
+ selection get
+} -cleanup {
+ .c delete test
+} -result {fghi}
+
+test canvText-17.1 {TextToPostscript procedure} -setup {
+ .c delete all
+ set result {findfont [font actual $font -size] scalefont ISOEncode setfont
+0.000 0.000 0.000 setrgbcolor AdjustColor
+0 100 200 \[
+\[(000)\]
+\[(000)\]
+\[(00)\]
+\] $ay -0.5 0 0 false DrawText
+grestore
+restore showpage
+
+%%Trailer
+end
+%%EOF
+}
+} -body {
+ set font {Courier 12 italic}
+ set ax [font measure $font 0]
+ set ay [font metrics $font -linespace]
+ .c config -height 300 -highlightthickness 0 -bd 0
+ update
+ .c create text 100 100 -tags test
+ .c itemconfig test -font $font -text "00000000" -width [expr 3*$ax]
+ .c itemconfig test -anchor n -fill black
+ set x [.c postscript]
+ set x [string range $x [string first "findfont " $x] end]
+ expr {$x eq [subst $result] ? "ok" : $x}
+} -result ok
+
+test canvText-18.1 {bug fix 2525, find enclosed on text with newlines} -setup {
+ destroy .c
+} -body {
+ pack [canvas .c]
+ .c create text 100 100 -text Hello\n -anchor nw
+ set bbox [.c bbox 1]
+ set x2 [lindex $bbox 2]
+ set y2 [lindex $bbox 3]
+ incr y2
+ update
+ .c find enclosed 99 99 [expr $x2 + 1] [expr $y2 + 1]
+} -cleanup {
+ destroy .c
+ unset -nocomplain bbox x2 y2
+} -result 1
+
+test canvText-19.1 {patch 1006286, leading space caused wrap under Win32} -setup {
+ destroy .c
+ set c [canvas .c -bg black -width 964]
+ pack $c
+ $c delete all
+ after 100 "set done 1"; vwait done
+} -body {
+ set f {Arial 28 bold}
+ set s1 { Yeah-ah-ah-ah-oh-oh-oh-oh-oh-oh-oh-oh-oh-oh-oh-oh-oh-oh-oh-oh-Yow}
+ set s2 { Yeah ah ah ah oh oh oh oh oh oh oh oh oh oh oh oh oh oh oh oh Yow}
+ $c create text 21 18 \
+ -font $f \
+ -text $s1 \
+ -fill white \
+ -width 922 \
+ -anchor nw \
+ -tags tbox1
+ $c create rect {*}[$c bbox tbox1] -outline red
+ $c create text 21 160 \
+ -font $f \
+ -text $s2 \
+ -fill white \
+ -width 922 \
+ -anchor nw \
+ -tags tbox2
+ $c create rect {*}[$c bbox tbox2] -outline red
+ after 500 "set done 1" ; vwait done
+ set results [list]
+ $c select from tbox2 4
+ $c select to tbox2 8
+ lappend results [selection get]
+ $c select from tbox1 4
+ $c select to tbox1 8
+ lappend results [selection get]
+ array set metrics [font metrics $f]
+ set x [expr {21 + [font measure $f " "] \
+ + ([font measure {Arial 28 bold} "Y"] / 2)}]
+ set y1 [expr {18 + ($metrics(-linespace) / 2)}]
+ set y2 [expr {160 + ($metrics(-linespace) / 2)}]
+ lappend results [$c index tbox1 @$x,$y1]
+ lappend results [$c index tbox2 @$x,$y2]
+} -cleanup {
+ destroy .c
+} -result {{Yeah } Yeah- 4 4}
+
+test canvText-20.1 {angled text bounding box} -setup {
+ destroy .c
+ canvas .c
+ proc transpose {bbox} {
+ lassign $bbox a b c d
+ list $b $a $d $c
+ }
+} -body {
+ .c create text 2 2 -tag t -anchor center -text 0 -font {Helvetica 24}
+ set bb0 [.c bbox t]
+ .c itemconf t -angle 90
+ set bb1 [.c bbox t]
+ .c itemconf t -angle 180
+ set bb2 [.c bbox t]
+ .c itemconf t -angle 270
+ set bb3 [.c bbox t]
+ list [expr {$bb0 eq $bb2 ? "ok" : "$bb0,$bb2"}] \
+ [expr {$bb1 eq $bb3 ? "ok" : "$bb1,$bb3"}] \
+ [expr {$bb0 eq [transpose $bb1] ? "ok" : "$bb0,$bb1"}] \
+} -cleanup {
+ destroy .c
+ rename transpose {}
+} -result {ok ok ok}
+
+# cleanup
+cleanupTests
+return
diff --git a/tk8.6/tests/canvWind.test b/tk8.6/tests/canvWind.test
new file mode 100644
index 0000000..436ee2c
--- /dev/null
+++ b/tk8.6/tests/canvWind.test
@@ -0,0 +1,144 @@
+# This file is a Tcl script to test out the procedures in tkCanvWind.c,
+# which implement canvas "window" items. It is organized in the standard
+# fashion for Tcl tests.
+#
+# Copyright (c) 1997 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+
+test canvWind-1.1 {DisplayWinItem, windows off-screen vertically} -setup {
+ destroy .t
+} -body {
+ toplevel .t
+ canvas .t.c -scrollregion {0 0 1000 800} -width 250 -height 200 -bd 2 \
+ -relief sunken -xscrollincrement 1 -yscrollincrement 1 \
+ -highlightthickness 1
+ pack .t.c -fill both -expand 1 -padx 20 -pady 20
+ wm geometry .t +0+0
+ set f .t.f
+ frame $f -width 80 -height 50 -bg red
+ .t.c create window 300 400 -window $f -anchor nw
+ .t.c xview moveto .3
+ .t.c yview moveto .50
+ update
+ set x [list [list [winfo ismapped $f] [winfo y $f]]]
+ .t.c yview scroll 52 units
+ update
+ lappend x [list [winfo ismapped $f] [winfo y $f]]
+ .t.c yview scroll 1 units
+ update
+ lappend x [list [winfo ismapped $f] [winfo y $f]]
+ .t.c yview scroll -255 units
+ update
+ lappend x [list [winfo ismapped $f] [winfo y $f]]
+ .t.c yview scroll -1 units
+ update
+ lappend x [list [winfo ismapped $f] [winfo y $f]]
+} -cleanup {
+ destroy .t
+} -result {{1 23} {1 -29} {0 -29} {1 225} {0 225}}
+
+test canvWind-1.2 {DisplayWinItem, windows off-screen vertically} -setup {
+ destroy .t
+} -body {
+ toplevel .t
+ canvas .t.c -scrollregion {0 0 1000 800} -width 250 -height 200 -bd 2 \
+ -relief sunken -xscrollincrement 1 -yscrollincrement 1 \
+ -highlightthickness 1
+ pack .t.c -fill both -expand 1 -padx 20 -pady 20
+ wm geometry .t +0+0
+ set f .t.c.f
+ frame $f -width 80 -height 50 -bg red
+ .t.c create window 300 400 -window $f -anchor nw
+ .t.c xview moveto .3
+ .t.c yview moveto .50
+ update
+ set x [list [list [winfo ismapped $f] [winfo y $f]]]
+ .t.c yview scroll 52 units
+ update
+ lappend x [list [winfo ismapped $f] [winfo y $f]]
+ .t.c yview scroll 1 units
+ update
+ lappend x [list [winfo ismapped $f] [winfo y $f]]
+ .t.c yview scroll -255 units
+ update
+ lappend x [list [winfo ismapped $f] [winfo y $f]]
+ .t.c yview scroll -1 units
+ update
+ lappend x [list [winfo ismapped $f] [winfo y $f]]
+} -cleanup {
+ destroy .t
+} -result {{1 3} {1 -49} {0 -49} {1 205} {0 205}}
+
+test canvWind-1.3 {DisplayWinItem, windows off-screen horizontally} -setup {
+ destroy .t
+} -body {
+ toplevel .t
+ canvas .t.c -scrollregion {0 0 1000 800} -width 250 -height 200 -bd 2 \
+ -relief sunken -xscrollincrement 1 -yscrollincrement 1 \
+ -highlightthickness 1
+ pack .t.c -fill both -expand 1 -padx 20 -pady 20
+ wm geometry .t +0+0
+ set f .t.f
+ frame $f -width 80 -height 50 -bg red
+ .t.c create window 300 400 -window $f -anchor nw
+ .t.c xview moveto .3
+ .t.c yview moveto .50
+ update
+ set x [list [list [winfo ismapped $f] [winfo x $f]]]
+ .t.c xview scroll 82 units
+ update
+ lappend x [list [winfo ismapped $f] [winfo x $f]]
+ .t.c xview scroll 1 units
+ update
+ lappend x [list [winfo ismapped $f] [winfo x $f]]
+ .t.c xview scroll -335 units
+ update
+ lappend x [list [winfo ismapped $f] [winfo x $f]]
+ .t.c xview scroll -1 units
+ update
+ lappend x [list [winfo ismapped $f] [winfo x $f]]
+} -cleanup {
+ destroy .t
+} -result {{1 23} {1 -59} {0 -59} {1 275} {0 275}}
+
+test canvWind-1.4 {DisplayWinItem, windows off-screen horizontally} -setup {
+ destroy .t
+} -body {
+ toplevel .t
+ canvas .t.c -scrollregion {0 0 1000 800} -width 250 -height 200 -bd 2 \
+ -relief sunken -xscrollincrement 1 -yscrollincrement 1 \
+ -highlightthickness 1
+ pack .t.c -fill both -expand 1 -padx 20 -pady 20
+ wm geometry .t +0+0
+ set f .t.c.f
+ frame $f -width 80 -height 50 -bg red
+ .t.c create window 300 400 -window $f -anchor nw
+ .t.c xview moveto .3
+ .t.c yview moveto .50
+ update
+ set x [list [list [winfo ismapped $f] [winfo x $f]]]
+ .t.c xview scroll 82 units
+ update
+ lappend x [list [winfo ismapped $f] [winfo x $f]]
+ .t.c xview scroll 1 units
+ update
+ lappend x [list [winfo ismapped $f] [winfo x $f]]
+ .t.c xview scroll -335 units
+ update
+ lappend x [list [winfo ismapped $f] [winfo x $f]]
+ .t.c xview scroll -1 units
+ update
+ lappend x [list [winfo ismapped $f] [winfo x $f]]
+} -cleanup {
+ destroy .t
+} -result {{1 3} {1 -79} {0 -79} {1 255} {0 255}}
+
+# cleanup
+cleanupTests
+return
diff --git a/tk8.6/tests/canvas.test b/tk8.6/tests/canvas.test
new file mode 100644
index 0000000..fe4c2b7
--- /dev/null
+++ b/tk8.6/tests/canvas.test
@@ -0,0 +1,960 @@
+# This file is a Tcl script to test out the procedures in tkCanvas.c, which
+# implements generic code for canvases. It is organized in the standard
+# fashion for Tcl tests.
+#
+# Copyright (c) 1995-1996 Sun Microsystems, Inc.
+# Copyright (c) 1998-2000 Ajuba Solutions.
+# Copyright (c) 2008 Donal K. Fellows
+# All rights reserved.
+
+package require tcltest 2.1
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+imageInit
+
+# XXX - This test file is woefully incomplete. At present, only a few of the
+# features are tested.
+
+# Canvas used in 1.* test cases
+canvas .c
+pack .c
+update
+
+test canvas-1.1 {configuration options: good value for "background"} -body {
+ .c configure -background #ff0000
+ .c cget -background
+} -result {#ff0000}
+test canvas-1.2 {configuration options: bad value for "background"} -body {
+ .c configure -background non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+test canvas-1.3 {configuration options: good value for "bg"} -body {
+ .c configure -bg #ff0000
+ .c cget -bg
+} -result {#ff0000}
+test canvas-1.4 {configuration options: bad value for "bg"} -body {
+ .c configure -bg non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+test canvas-1.5 {configuration options: good value for "bd"} -body {
+ .c configure -bd 4
+ .c cget -bd
+} -result {4}
+test canvas-1.6 {configuration options: bad value for "bd"} -body {
+ .c configure -bd badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test canvas-1.7 {configuration options: good value for "borderwidth"} -body {
+ .c configure -borderwidth 1.3
+ .c cget -borderwidth
+} -result {1}
+test canvas-1.8 {configuration options: bad value for "borderwidth"} -body {
+ .c configure -borderwidth badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test canvas-1.9 {configuration options: good value for "closeenough"} -body {
+ .c configure -closeenough 24
+ .c cget -closeenough
+} -result {24.0}
+test canvas-1.10 {configuration options: bad value for "closeenough"} -body {
+ .c configure -closeenough bogus
+} -returnCodes error -result {expected floating-point number but got "bogus"}
+test canvas-1.11 {configuration options: good value for "confine"} -body {
+ .c configure -confine true
+ .c cget -confine
+} -result {1}
+test canvas-1.12 {configuration options: bad value for "confine"} -body {
+ .c configure -confine silly
+} -returnCodes error -result {expected boolean value but got "silly"}
+test canvas-1.13 {configuration options: good value for "cursor"} -body {
+ .c configure -cursor arrow
+ .c cget -cursor
+} -result {arrow}
+test canvas-1.14 {configuration options: bad value for "cursor"} -body {
+ .c configure -cursor badValue
+} -returnCodes error -result {bad cursor spec "badValue"}
+test canvas-1.15 {configuration options: good value for "height"} -body {
+ .c configure -height 2.1
+ .c cget -height
+} -result {2}
+test canvas-1.16 {configuration options: bad value for "height"} -body {
+ .c configure -height x42
+} -returnCodes error -result {bad screen distance "x42"}
+test canvas-1.17 {configuration options: good value for "highlightbackground"} -body {
+ .c configure -highlightbackground #112233
+ .c cget -highlightbackground
+} -result {#112233}
+test canvas-1.18 {configuration options: bad value for "highlightbackground"} -body {
+ .c configure -highlightbackground ugly
+} -returnCodes error -result {unknown color name "ugly"}
+test canvas-1.19 {configuration options: good value for "highlightcolor"} -body {
+ .c configure -highlightcolor #110022
+ .c cget -highlightcolor
+} -result {#110022}
+test canvas-1.20 {configuration options: bad value for "highlightcolor"} -body {
+ .c configure -highlightcolor bogus
+} -returnCodes error -result {unknown color name "bogus"}
+test canvas-1.21 {configuration options: good value for "highlightthickness"} -body {
+ .c configure -highlightthickness 18
+ .c cget -highlightthickness
+} -result {18}
+test canvas-1.22 {configuration options: bad value for "highlightthickness"} -body {
+ .c configure -highlightthickness badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test canvas-1.23 {configuration options: good value for "insertbackground"} -body {
+ .c configure -insertbackground #110022
+ .c cget -insertbackground
+} -result {#110022}
+test canvas-1.24 {configuration options: bad value for "insertbackground"} -body {
+ .c configure -insertbackground bogus
+} -returnCodes error -result {unknown color name "bogus"}
+test canvas-1.25 {configuration options: good value for "insertborderwidth"} -body {
+ .c configure -insertborderwidth 1.3
+ .c cget -insertborderwidth
+} -result {1}
+test canvas-1.26 {configuration options: bad value for "insertborderwidth"} -body {
+ .c configure -insertborderwidth 2.6x
+} -returnCodes error -result {bad screen distance "2.6x"}
+test canvas-1.27 {configuration options: good value for "insertofftime"} -body {
+ .c configure -insertofftime 100
+ .c cget -insertofftime
+} -result {100}
+test canvas-1.28 {configuration options: bad value for "insertofftime"} -body {
+ .c configure -insertofftime 3.2
+} -returnCodes error -result {expected integer but got "3.2"}
+test canvas-1.29 {configuration options: good value for "insertontime"} -body {
+ .c configure -insertontime 100
+ .c cget -insertontime
+} -result {100}
+test canvas-1.30 {configuration options: bad value for "insertontime"} -body {
+ .c configure -insertontime 3.2
+} -returnCodes error -result {expected integer but got "3.2"}
+test canvas-1.31 {configuration options: good value for "insertwidth"} -body {
+ .c configure -insertwidth 1.3
+ .c cget -insertwidth
+} -result {1}
+test canvas-1.32 {configuration options: bad value for "insertwidth"} -body {
+ .c configure -insertwidth 6x
+} -returnCodes error -result {bad screen distance "6x"}
+test canvas-1.33 {configuration options: good value for "relief"} -body {
+ .c configure -relief groove
+ .c cget -relief
+} -result {groove}
+test canvas-1.34 {configuration options: bad value for "relief"} -body {
+ .c configure -relief 1.5
+} -returnCodes error -result {bad relief "1.5": must be flat, groove, raised, ridge, solid, or sunken}
+test canvas-1.35 {configuration options: good value for "selectbackground"} -body {
+ .c configure -selectbackground #110022
+ .c cget -selectbackground
+} -result {#110022}
+test canvas-1.36 {configuration options: bad value for "selectbackground"} -body {
+ .c configure -selectbackground bogus
+} -returnCodes error -result {unknown color name "bogus"}
+test canvas-1.37 {configuration options: good value for "selectborderwidth"} -body {
+ .c configure -selectborderwidth 1.3
+ .c cget -selectborderwidth
+} -result {1}
+test canvas-1.38 {configuration options: bad value for "selectborderwidth"} -body {
+ .c configure -selectborderwidth badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test canvas-1.39 {configuration options: good value for "selectforeground"} -body {
+ .c configure -selectforeground #654321
+ .c cget -selectforeground
+} -result {#654321}
+test canvas-1.40 {configuration options: bad value for "selectforeground"} -body {
+ .c configure -selectforeground bogus
+} -returnCodes error -result {unknown color name "bogus"}
+test canvas-1.41 {configuration options: good value for "takefocus"} -body {
+ .c configure -takefocus "any string"
+ .c cget -takefocus
+} -result {any string}
+test canvas-1.42 {configuration options: good value for "width"} -body {
+ .c configure -width 402
+ .c cget -width
+} -result {402}
+test canvas-1.43 {configuration options: bad value for "width"} -body {
+ .c configure -width xyz
+} -returnCodes error -result {bad screen distance "xyz"}
+test canvas-1.44 {configuration options: good value for "xscrollcommand"} -body {
+ .c configure -xscrollcommand {Some command}
+ .c cget -xscrollcommand
+} -result {Some command}
+test canvas-1.45 {configuration options: good value for "yscrollcommand"} -body {
+ .c configure -yscrollcommand {Another command}
+ .c cget -yscrollcommand
+} -result {Another command}
+test canvas-1.46 {configure throws error on bad option} -body {
+ .c configure -gorp foo
+} -returnCodes error -match glob -result {*}
+test canvas-1.47 {configure throws error on bad option} -body {
+ catch {.c configure -gorp foo}
+ .c create rect 10 10 100 100
+ .c configure -gorp foo
+} -returnCodes error -match glob -result {*}
+catch {destroy .c}
+
+# Canvas used in 2.* test cases
+canvas .c -width 60 -height 40 -scrollregion {0 0 200 150} -bd 0 \
+ -highlightthickness 0
+pack .c
+update
+
+test canvas-2.1 {CanvasWidgetCmd, bind option} -body {
+ set i [.c create rect 10 10 100 100]
+ .c bind $i <a>
+} -cleanup {
+ .c delete $i
+} -returnCodes ok
+test canvas-2.2 {CanvasWidgetCmd, bind option} -body {
+ set i [.c create rect 10 10 100 100]
+ .c bind $i <
+} -cleanup {
+ .c delete $i
+} -returnCodes error -result {no event type or button # or keysym}
+test canvas-2.3 {CanvasWidgetCmd, xview option} -body {
+ .c configure -xscrollincrement 40 -yscrollincrement 5
+ .c xview moveto 0
+ update
+ set x [list [.c xview]]
+ .c xview scroll 2 units
+ update
+ lappend x [.c xview]
+} -result {{0.0 0.3} {0.4 0.7}}
+test canvas-2.4 {CanvasWidgetCmd, xview option} -constraints nonPortable -body {
+ # This test gives slightly different results on platforms such as NetBSD.
+ # I don't know why...
+ .c configure -xscrollincrement 0 -yscrollincrement 5
+ .c xview moveto 0.6
+ update
+ set x [list [.c xview]]
+ .c xview scroll 2 units
+ update
+ lappend x [.c xview]
+} -result {{0.6 0.9} {0.66 0.96}}
+catch {destroy .c}
+
+# Canvas used in 3.* test cases
+canvas .c -width 60 -height 40 -scrollregion {0 0 200 80} \
+ -borderwidth 0 -highlightthickness 0
+pack .c
+update
+
+test canvas-3.1 {CanvasWidgetCmd, yview option} -body {
+ .c configure -xscrollincrement 40 -yscrollincrement 5
+ .c yview moveto 0
+ update
+ set x [list [.c yview]]
+ .c yview scroll 3 units
+ update
+ lappend x [.c yview]
+} -result {{0.0 0.5} {0.1875 0.6875}}
+test canvas-3.2 {CanvasWidgetCmd, yview option} -body {
+ .c configure -xscrollincrement 40 -yscrollincrement 0
+ .c yview moveto 0
+ update
+ set x [list [.c yview]]
+ .c yview scroll 2 units
+ update
+ lappend x [.c yview]
+} -result {{0.0 0.5} {0.1 0.6}}
+destroy .c
+
+test canvas-4.1 {ButtonEventProc procedure} -setup {
+ deleteWindows
+ set x {}
+} -body {
+ canvas .c1 -bg #543210
+ rename .c1 .c2
+ lappend x [winfo children .]
+ lappend x [.c2 cget -bg]
+ destroy .c1
+ lappend x [info command .c*] [winfo children .]
+} -result {.c1 #543210 {} {}}
+
+test canvas-5.1 {ButtonCmdDeletedProc procedure} -body {
+ canvas .c1
+ rename .c1 {}
+ list [info command .c*] [winfo children .]
+} -cleanup {
+ destroy .c1
+} -result {{} {}}
+
+# Canvas used in 6.* test cases
+canvas .c -width 100 -height 50 -scrollregion {-200 -100 305 102} \
+ -borderwidth 2 -highlightthickness 3
+pack .c
+update
+
+test canvas-6.1 {CanvasSetOrigin procedure} -body {
+ .c configure -xscrollincrement 0 -yscrollincrement 0
+ .c xview moveto 0
+ .c yview moveto 0
+ update
+ list [.c canvasx 0] [.c canvasy 0]
+} -result {-205.0 -105.0}
+test canvas-6.2 {CanvasSetOrigin procedure} -body {
+ .c configure -xscrollincrement 20 -yscrollincrement 10
+ set x ""
+ foreach i {.08 .10 .48 .50} {
+ .c xview moveto $i
+ update
+ lappend x [.c canvasx 0]
+ }
+ return $x
+} -result {-165.0 -145.0 35.0 55.0}
+test canvas-6.3 {CanvasSetOrigin procedure} -body {
+ .c configure -xscrollincrement 20 -yscrollincrement 10
+ set x ""
+ foreach i {.06 .08 .70 .72} {
+ .c yview moveto $i
+ update
+ lappend x [.c canvasy 0]
+ }
+ return $x
+} -result {-95.0 -85.0 35.0 45.0}
+test canvas-6.4 {CanvasSetOrigin procedure} -body {
+ .c configure -xscrollincrement 20 -yscrollincrement 10
+ .c xview moveto 1.0
+ .c canvasx 0
+} -result {215.0}
+test canvas-6.5 {CanvasSetOrigin procedure} -body {
+ .c configure -xscrollincrement 20 -yscrollincrement 10
+ .c yview moveto 1.0
+ .c canvasy 0
+} -result {55.0}
+deleteWindows
+
+test canvas-7.1 {canvas widget vs hidden commands} -setup {
+ canvas .c
+} -body {
+ interp hide {} .c
+ destroy .c
+ list [winfo children .] [lsort [interp hidden]]
+} -cleanup {
+ destroy .c
+} -result [list {} [lsort [interp hidden]]]
+
+test canvas-8.1 {canvas arc bbox} -setup {
+ catch {destroy .c}
+ canvas .c
+} -body {
+ .c create arc -100 10 100 210 -start 10 -extent 50 -style arc -tags arc1
+ set arcBox [.c bbox arc1]
+ .c create arc 100 10 300 210 -start 10 -extent 50 -style chord -tags arc2
+ set coordBox [.c bbox arc2]
+ .c create arc 300 10 500 210 -start 10 -extent 50 -style pieslice -tags arc3
+ set pieBox [.c bbox arc3]
+ list $arcBox $coordBox $pieBox
+} -result {{48 21 100 94} {248 21 300 94} {398 21 500 112}}
+
+test canvas-9.1 {canvas id creation and deletion} -setup {
+ catch {destroy .c}
+ canvas .c
+} -body {
+ # With Tk 8.0.4 the ids are now stored in a hash table. You can use this
+ # test as a performance test with older versions by changing the value of
+ # size.
+ set size 15
+ for {set i 0} {$i < $size} {incr i} {
+ set x [expr {-10 + 3*$i}]
+ for {set j 0; set y -10} {$j < 10} {incr j; incr y 3} {
+ .c create rect ${x}c ${y}c [expr {$x+2}]c [expr {$y+2}]c \
+ -outline black -fill blue -tags rect
+ .c create text [expr {$x+1}]c [expr {$y+1}]c -text "$i,$j" \
+ -anchor center -tags text
+ }
+ }
+ # The actual bench mark - this code also exercises all the hash table
+ # changes.
+ set time [lindex [time {
+ foreach id [.c find withtag all] {
+ .c lower $id
+ .c raise $id
+ .c find withtag $id
+ .c bind <Return> $id {}
+ .c delete $id
+ }
+ }] 0]
+ set x ""
+} -result {}
+
+test canvas-10.1 {find items using tag expressions} -setup {
+ catch {destroy .c}
+ canvas .c
+ set res {}
+} -body {
+ .c create oval 20 20 40 40 -fill red -tag [list a b c d]
+ .c create oval 20 60 40 80 -fill yellow -tag [list b a]
+ .c create oval 20 100 40 120 -fill green -tag [list c b]
+ .c create oval 20 140 40 160 -fill blue -tag [list b]
+ .c create oval 20 180 40 200 -fill bisque -tag [list a d e]
+ .c create oval 20 220 40 240 -fill bisque -tag b
+ .c create oval 20 260 40 280 -fill bisque -tag [list d "tag with spaces"]
+ lappend res [.c find withtag {!a}]
+ lappend res [.c find withtag {b&&c}]
+ lappend res [.c find withtag {b||c}]
+ lappend res [.c find withtag {a&&!b}]
+ lappend res [.c find withtag {!b&&!c}]
+ lappend res [.c find withtag {d&&a&&c&&b}]
+ lappend res [.c find withtag {b^a}]
+ lappend res [.c find withtag {(a&&!b)||(!a&&b)}]
+ lappend res [.c find withtag { ( a && ! b ) || ( ! a && b ) }]
+ lappend res [.c find withtag {a&&!(c||d)}]
+ lappend res [.c find withtag {d&&"tag with spaces"}]
+ lappend res [.c find withtag "tag with spaces"]
+} -result {{3 4 6 7} {1 3} {1 2 3 4 6} 5 {5 7} 1 {3 4 5 6} {3 4 5 6} {3 4 5 6} 2 7 7}
+test canvas-10.2 {check errors from tag expressions} -setup {
+ catch {destroy .c}
+ canvas .c
+ .c create oval 20 20 40 40 -fill red -tag [list a b c d]
+ .c create oval 20 260 40 280 -fill bisque -tag [list d "tag with spaces"]
+} -body {
+ .c find withtag {&&c}
+} -returnCodes error -result {unexpected operator in tag search expression}
+test canvas-10.3 {check errors from tag expressions} -setup {
+ catch {destroy .c}
+ canvas .c
+ .c create oval 20 20 40 40 -fill red -tag [list a b c d]
+ .c create oval 20 260 40 280 -fill bisque -tag [list d "tag with spaces"]
+} -body {
+ .c find withtag {!!c}
+} -returnCodes error -result {too many '!' in tag search expression}
+test canvas-10.4 {check errors from tag expressions} -setup {
+ catch {destroy .c}
+ canvas .c
+ .c create oval 20 20 40 40 -fill red -tag [list a b c d]
+ .c create oval 20 260 40 280 -fill bisque -tag [list d "tag with spaces"]
+} -body {
+ .c find withtag {b||}
+} -returnCodes error -result {missing tag in tag search expression}
+test canvas-10.5 {check errors from tag expressions} -setup {
+ catch {destroy .c}
+ canvas .c
+ .c create oval 20 20 40 40 -fill red -tag [list a b c d]
+ .c create oval 20 260 40 280 -fill bisque -tag [list d "tag with spaces"]
+} -body {
+ .c find withtag {b&&(c||)}
+} -returnCodes error -result {unexpected operator in tag search expression}
+test canvas-10.6 {check errors from tag expressions} -setup {
+ catch {destroy .c}
+ canvas .c
+ .c create oval 20 20 40 40 -fill red -tag [list a b c d]
+ .c create oval 20 260 40 280 -fill bisque -tag [list d "tag with spaces"]
+} -body {
+ .c find withtag {d&&""}
+} -returnCodes error -result {null quoted tag string in tag search expression}
+test canvas-10.7 {check errors from tag expressions} -setup {
+ catch {destroy .c}
+ canvas .c
+ .c create oval 20 20 40 40 -fill red -tag [list a b c d]
+ .c create oval 20 260 40 280 -fill bisque -tag [list d "tag with spaces"]
+} -body {
+ .c find withtag "d&&\"tag with spaces"
+} -returnCodes error -result {missing endquote in tag search expression}
+test canvas-10.8 {check errors from tag expressions} -setup {
+ catch {destroy .c}
+ canvas .c
+ .c create oval 20 20 40 40 -fill red -tag [list a b c d]
+ .c create oval 20 260 40 280 -fill bisque -tag [list d "tag with spaces"]
+} -returnCodes error -body {
+ .c find withtag {a&&"tag with spaces"z}
+} -result {invalid boolean operator in tag search expression}
+test canvas-10.9 {check errors from tag expressions} -setup {
+ catch {destroy .c}
+ canvas .c
+ .c create oval 20 20 40 40 -fill red -tag [list a b c d]
+ .c create oval 20 260 40 280 -fill bisque -tag [list d "tag with spaces"]
+} -body {
+ .c find withtag {a&&b&c}
+} -returnCodes error -result {singleton '&' in tag search expression}
+test canvas-10.10 {check errors from tag expressions} -setup {
+ catch {destroy .c}
+ canvas .c
+ .c create oval 20 20 40 40 -fill red -tag [list a b c d]
+ .c create oval 20 260 40 280 -fill bisque -tag [list d "tag with spaces"]
+} -body {
+ .c find withtag {a||b|c}
+} -returnCodes error -result {singleton '|' in tag search expression}
+test canvas-10.11 {backward compatility - strange tags that are not expressions} -setup {
+ catch {destroy .c}
+ canvas .c
+ .c create oval 20 20 40 40 -fill red \
+ -tag [list { strange tag(xxx&yyy|zzz) " && \" || ! ^ " }]
+} -body {
+ .c find withtag { strange tag(xxx&yyy|zzz) " && \" || ! ^ " }
+} -result 1
+test canvas-10.12 {multple events bound to same tag expr} -setup {
+ catch {destroy .c}
+ canvas .c
+} -body {
+ .c bind {a && b} <Enter> {puts Enter}
+ .c bind {a && b} <Leave> {puts Leave}
+} -result {}
+test canvas-10.13 {more long tag searches; Bug 2931374} -setup {
+ catch {destroy .c}
+ canvas .c
+} -body {
+ .c find withtag {(A&&B&&C&&D)&&area&&!text}
+ # memory errors on failure
+} -cleanup {
+ destroy .c
+} -result {}
+
+test canvas-11.1 {canvas poly fill check, bug 5783} -setup {
+ destroy .c
+ pack [canvas .c]
+} -body {
+ # This would crash in 8.3.0 and 8.3.1
+ .c create polygon 0 0 100 100 200 50 \
+ -fill {} -stipple gray50 -outline black
+} -result 1
+test canvas-11.2 {canvas poly overlap fill check, bug 226357} -setup {
+ destroy .c
+ pack [canvas .c]
+ set result {}
+} -body {
+ .c create poly 30 30 90 90 30 90 90 30
+ lappend result [.c find over 40 40 45 45]; # rect region inc. edge
+ lappend result [.c find over 60 40 60 40]; # top-center point
+ lappend result [.c find over 0 0 0 0]; # not on poly
+ lappend result [.c find over 60 60 60 60]; # center-point
+ lappend result [.c find over 45 50 45 50]; # outside poly
+ .c itemconfig 1 -fill "" -outline black
+ lappend result [.c find over 40 40 45 45]; # rect region inc. edge
+ lappend result [.c find over 60 40 60 40]; # top-center point
+ lappend result [.c find over 0 0 0 0]; # not on poly
+ lappend result [.c find over 60 60 60 60]; # center-point
+ lappend result [.c find over 45 50 45 50]; # outside poly
+ .c itemconfig 1 -width 8
+ lappend result [.c find over 45 50 45 50]; # outside poly
+} -result {1 1 {} 1 {} 1 1 {} 1 {} 1}
+test canvas-11.3 {canvas poly dchars, bug 3291543} {
+ # This would crash
+ destroy .c
+ pack [canvas .c]
+ .c create polygon 0 0 0 10 10 0
+ .c dchars 1 2 end
+ .c coords 1
+} {}
+
+test canvas-12.1 {canvas mm obj, patch SF-403327, 102471} -setup {
+ destroy .c
+ pack [canvas .c]
+} -body {
+ set qx [expr {1.+1.}]
+ # qx has type double and no string representation
+ .c scale all $qx 0 1. 1.
+ # qx has now type MMRep and no string representation
+ list $qx [string length $qx]
+} -result {2.0 3}
+test canvas-12.2 {canvas mm obj, patch SF-403327, 102471} -setup {
+ destroy .c
+ pack [canvas .c]
+} -body {
+ set val 10
+ incr val
+ # qx has type double and no string representation
+ .c scale all $val 0 1 1
+ # qx has now type MMRep and no string representation
+ incr val
+} -result 12
+
+# procedure used in 13.1 test case
+proc kill_canvas {w} {
+ destroy $w
+ pack [canvas $w -height 200 -width 200] -fill both -expand yes
+ update idle
+ $w create rectangle 80 80 120 120 -fill blue -tags blue
+ # bind a button press to re-build the canvas
+ $w bind blue <ButtonRelease-1> [subst {
+ [lindex [info level 0] 0] $w
+ append ::x ok
+ }]
+}
+test canvas-13.1 {canvas delete during event, SF bug-228024} -body {
+ kill_canvas .c
+ set ::x {}
+ # do this many times to improve chances of triggering the crash
+ for {set i 0} {$i < 30} {incr i} {
+ event generate .c <1> -x 100 -y 100
+ event generate .c <ButtonRelease-1> -x 100 -y 100
+ }
+ return $::x
+} -result {okokokokokokokokokokokokokokokokokokokokokokokokokokokokokok}
+
+test canvas-14.1 {canvas scan SF bug 581560} -setup {
+ destroy .c
+ canvas .c
+} -returnCodes error -body {
+ .c scan
+} -result {wrong # args: should be ".c scan mark|dragto x y ?dragGain?"}
+test canvas-14.2 {canvas scan} -setup {
+ destroy .c
+ canvas .c
+} -returnCodes error -body {
+ .c scan bogus
+} -result {wrong # args: should be ".c scan mark|dragto x y ?dragGain?"}
+test canvas-14.3 {canvas scan} -setup {
+ destroy .c
+ canvas .c
+} -returnCodes error -body {
+ .c scan mark
+} -result {wrong # args: should be ".c scan mark|dragto x y ?dragGain?"}
+test canvas-14.4 {canvas scan} -setup {
+ destroy .c
+ canvas .c
+} -body {
+ .c scan mark 10 10
+} -result {}
+test canvas-14.5 {canvas scan} -setup {
+ destroy .c
+ canvas .c
+} -body {
+ .c scan mark 10 10 5
+} -returnCodes error -result {wrong # args: should be ".c scan mark x y"}
+test canvas-14.6 {canvas scan} -setup {
+ destroy .c
+ canvas .c
+} -body {
+ .c scan dragto 10 10 5
+} -result {}
+
+test canvas-15.1 {basic types check: arc requires coords} -setup {
+ destroy .c
+ canvas .c
+} -returnCodes error -body {
+ .c create arc
+} -result {wrong # args: should be ".c create arc coords ?arg ...?"}
+test canvas-15.2 "basic coords check: arc coords are paired" -setup {
+ destroy .c
+ canvas .c
+} -body {
+ .c create arc 0
+} -returnCodes error -result {wrong # coordinates: expected 4, got 1}
+test canvas-15.3 {basic types check: bitmap requires coords} -setup {
+ destroy .c
+ canvas .c
+} -returnCodes error -body {
+ .c create bitmap
+} -result {wrong # args: should be ".c create bitmap coords ?arg ...?"}
+test canvas-15.4 "basic coords check: bitmap coords are paired" -setup {
+ destroy .c
+ canvas .c
+} -body {
+ .c create bitmap 0
+} -returnCodes error -result {wrong # coordinates: expected 2, got 1}
+test canvas-15.5 {basic types check: image requires coords} -setup {
+ destroy .c
+ canvas .c
+} -returnCodes error -body {
+ .c create image
+} -result {wrong # args: should be ".c create image coords ?arg ...?"}
+test canvas-15.6 "basic coords check: image coords are paired" -setup {
+ destroy .c
+ canvas .c
+} -returnCodes error -body {
+ .c create image 0
+} -result {wrong # coordinates: expected 2, got 1}
+test canvas-15.7 {basic types check: line requires coords} -setup {
+ destroy .c
+ canvas .c
+} -returnCodes error -body {
+ .c create line
+} -result {wrong # args: should be ".c create line coords ?arg ...?"}
+test canvas-15.8 "basic coords check: line coords are paired" -setup {
+ destroy .c
+ canvas .c
+} -returnCodes error -body {
+ .c create line 0
+} -result {wrong # coordinates: expected an even number, got 1}
+test canvas-15.9 {basic types check: oval requires coords} -setup {
+ destroy .c
+ canvas .c
+} -returnCodes error -body {
+ .c create oval
+} -result {wrong # args: should be ".c create oval coords ?arg ...?"}
+test canvas-15.10 "basic coords check: oval coords are paired" -setup {
+ destroy .c
+ canvas .c
+} -returnCodes error -body {
+ .c create oval 0
+} -result {wrong # coordinates: expected 0 or 4, got 1}
+test canvas-15.11 {basic types check: polygon requires coords} -setup {
+ destroy .c
+ canvas .c
+} -returnCodes error -body {
+ .c create polygon
+} -result {wrong # args: should be ".c create polygon coords ?arg ...?"}
+test canvas-15.12 "basic coords check: polygon coords are paired" -setup {
+ destroy .c
+ canvas .c
+} -returnCodes error -body {
+ .c create polygon 0
+} -result {wrong # coordinates: expected an even number, got 1}
+test canvas-15.13 {basic types check: rect requires coords} -setup {
+ destroy .c
+ canvas .c
+} -returnCodes error -body {
+ .c create rect
+} -result {wrong # args: should be ".c create rect coords ?arg ...?"}
+test canvas-15.14 "basic coords check: rect coords are paired" -setup {
+ destroy .c
+ canvas .c
+} -returnCodes error -body {
+ .c create rect 0
+} -result {wrong # coordinates: expected 0 or 4, got 1}
+test canvas-15.15 {basic types check: text requires coords} -setup {
+ destroy .c
+ canvas .c
+} -returnCodes error -body {
+ .c create text
+} -result {wrong # args: should be ".c create text coords ?arg ...?"}
+test canvas-15.16 "basic coords check: text coords are paired" -setup {
+ destroy .c
+ canvas .c
+} -returnCodes error -body {
+ .c create text 0
+} -result {wrong # coordinates: expected 2, got 1}
+test canvas-15.17 {basic types check: window requires coords} -setup {
+ destroy .c
+ canvas .c
+} -returnCodes error -body {
+ .c create window
+} -result {wrong # args: should be ".c create window coords ?arg ...?"}
+test canvas-15.18 "basic coords check: window coords are paired" -setup {
+ destroy .c
+ canvas .c
+} -returnCodes error -body {
+ .c create window 0
+} -result {wrong # coordinates: expected 2, got 1}
+test canvas-15.19 "basic coords check: centimeters are larger than pixels" -setup {
+ destroy .c
+ canvas .c
+} -body {
+ set id [.c create rect 0 0 1cm 1cm]
+ expr {[lindex [.c coords $id] 2]>1}
+} -result {1}
+destroy .c
+
+test canvas-16.1 {arc coords check} -setup {
+ canvas .c
+} -body {
+ set id [.c create arc {0 10 20 30} -start 33]
+ .c itemcget $id -start
+} -cleanup {
+ destroy .c
+} -result {33.0}
+
+test canvas-17.1 {default smooth method handling} -setup {
+ canvas .c
+} -body {
+ set id [.c create line {0 0 1 1 2 2 3 3 4 4 5 5 6 6}]
+ set result [.c itemcget $id -smooth]
+ foreach smoother {yes 1 bezier raw r b} {
+ .c itemconfigure $id -smooth $smoother
+ lappend result [.c itemcget $id -smooth]
+ }
+ return $result
+} -cleanup {
+ destroy .c
+} -result {0 true true true raw raw true}
+
+test canvas-18.1 {imove method - lines} -setup {
+ canvas .c
+} -body {
+ set id [.c create line 0 0 1 1 2 2 3 3]
+ .c imove $id 0 4 4
+ .c coords $id
+} -cleanup {
+ destroy .c
+} -result {4.0 4.0 1.0 1.0 2.0 2.0 3.0 3.0}
+test canvas-18.2 {imove method - lines} -setup {
+ canvas .c
+} -body {
+ set id [.c create line 0 0 1 1]
+ .c imove $id 0 4 4
+ .c coords $id
+} -cleanup {
+ destroy .c
+} -result {4.0 4.0 1.0 1.0}
+test canvas-18.3 {imove method - lines} -setup {
+ canvas .c
+} -body {
+ set id [.c create line 0 0 1 1 2 2 3 3]
+ .c imove $id @1,1 4 4
+ .c coords $id
+} -cleanup {
+ destroy .c
+} -result {0.0 0.0 4.0 4.0 2.0 2.0 3.0 3.0}
+test canvas-18.4 {imove method - lines} -constraints knownBug -setup {
+ canvas .c
+} -body {
+ set id [.c create line 0 0 1 1 2 2 3 3]
+ .c imove $id end 4 4
+ .c coords $id
+} -cleanup {
+ destroy .c
+} -result {0.0 0.0 1.0 1.0 2.0 2.0 4.0 4.0}
+test canvas-18.5 {imove method - polygon} -setup {
+ canvas .c
+} -body {
+ set id [.c create polygon 0 0 1 1 2 2 3 3]
+ .c imove $id 0 4 4
+ .c coords $id
+} -cleanup {
+ destroy .c
+} -result {4.0 4.0 1.0 1.0 2.0 2.0 3.0 3.0}
+test canvas-18.6 {imove method - polygon} -setup {
+ canvas .c
+} -body {
+ set id [.c create polygon 0 0 1 1]
+ .c imove $id 0 4 4
+ .c coords $id
+} -cleanup {
+ destroy .c
+} -result {4.0 4.0 1.0 1.0}
+test canvas-18.7 {imove method - polygon} -setup {
+ canvas .c
+} -body {
+ set id [.c create polygon 0 0 1 1 2 2 3 3]
+ .c imove $id @1,1 4 4
+ .c coords $id
+} -cleanup {
+ destroy .c
+} -result {0.0 0.0 4.0 4.0 2.0 2.0 3.0 3.0}
+test canvas-18.8 {imove method - polygon} -constraints knownBug -setup {
+ canvas .c
+} -body {
+ set id [.c create polygon 0 0 1 1 2 2 3 3]
+ .c imove $id end 4 4
+ .c coords $id
+} -cleanup {
+ destroy .c
+} -result {0.0 0.0 1.0 1.0 2.0 2.0 4.0 4.0}
+test canvas-18.9 {imove method - errors} -setup {
+ canvas .c
+} -body {
+ set id [.c create line 0 0 1 1 2 2 3 3]
+ .c imove $id foobar 4 4
+} -cleanup {
+ destroy .c
+} -returnCodes error -result {bad index "foobar"}
+test canvas-18.10 {imove method - errors} -setup {
+ canvas .c
+} -body {
+ set id [.c create line 0 0 1 1 2 2 3 3]
+ .c imove $id 0 foobar 4
+} -cleanup {
+ destroy .c
+} -returnCodes error -result {bad screen distance "foobar"}
+test canvas-18.11 {imove method - errors} -setup {
+ canvas .c
+} -body {
+ set id [.c create line 0 0 1 1 2 2 3 3]
+ .c imove $id 0 4 foobar
+} -cleanup {
+ destroy .c
+} -returnCodes error -result {bad screen distance "foobar"}
+
+test canvas-19.1 {rchars method - lines} -setup {
+ canvas .c
+} -body {
+ set id [.c create line 0 0 1 1 2 2 3 3]
+ .c rchars $id 2 4 {4 4}
+ .c coords $id
+} -cleanup {
+ destroy .c
+} -result {0.0 0.0 4.0 4.0 3.0 3.0}
+test canvas-19.2 {rchars method - lines} -setup {
+ canvas .c
+} -body {
+ set id [.c create line 0 0 1 1 2 2 3 3]
+ .c rchars $id 2 4 {}
+ .c coords $id
+} -cleanup {
+ destroy .c
+} -result {0.0 0.0 3.0 3.0}
+test canvas-19.3 {rchars method - lines} -setup {
+ canvas .c
+} -body {
+ set id [.c create line 0 0 1 1 2 2 3 3]
+ .c rchars $id 2 4 {10 11 12 13 14 15}
+ .c coords $id
+} -cleanup {
+ destroy .c
+} -result {0.0 0.0 10.0 11.0 12.0 13.0 14.0 15.0 3.0 3.0}
+test canvas-19.4 {rchars method - polygon} -setup {
+ canvas .c
+} -body {
+ set id [.c create polygon 0 0 1 1 2 2 3 3]
+ .c rchars $id 2 4 {4 4}
+ .c coords $id
+} -cleanup {
+ destroy .c
+} -result {0.0 0.0 4.0 4.0 3.0 3.0}
+test canvas-19.5 {rchars method - polygon} -setup {
+ canvas .c
+} -body {
+ set id [.c create polygon 0 0 1 1 2 2 3 3]
+ .c rchars $id 2 4 {}
+ .c coords $id
+} -cleanup {
+ destroy .c
+} -result {0.0 0.0 3.0 3.0}
+test canvas-19.6 {rchars method - polygon} -setup {
+ canvas .c
+} -body {
+ set id [.c create polygon 0 0 1 1 2 2 3 3]
+ .c rchars $id 2 4 {10 11 12 13 14 15}
+ .c coords $id
+} -cleanup {
+ destroy .c
+} -result {0.0 0.0 10.0 11.0 12.0 13.0 14.0 15.0 3.0 3.0}
+test canvas-19.7 {rchars method - text} -setup {
+ canvas .c
+} -body {
+ set id [.c create text 0 0 -text abcde]
+ .c rchars $id 1 3 XYZ
+ .c itemcget $id -text
+} -cleanup {
+ destroy .c
+} -result aXYZe
+test canvas-19.8 {rchars method - text} -setup {
+ canvas .c
+} -body {
+ set id [.c create text 0 0 -text abcde]
+ .c rchars $id 1 3 {}
+ .c itemcget $id -text
+} -cleanup {
+ destroy .c
+} -result ae
+test canvas-19.9 {rchars method - text} -setup {
+ canvas .c
+} -body {
+ set id [.c create text 0 0 -text abcde]
+ .c rchars $id 1 3 FOOBAR
+ .c itemcget $id -text
+} -cleanup {
+ destroy .c
+} -result aFOOBARe
+test canvas-19.10 {rchars method - errors} -setup {
+ canvas .c
+} -body {
+ set id [.c create line 0 0 1 1]
+ .c rchars $id foo 1 {2 2}
+} -cleanup {
+ destroy .c
+} -returnCodes error -result {bad index "foo"}
+test canvas-19.11 {rchars method - errors} -setup {
+ canvas .c
+} -body {
+ set id [.c create line 0 0 1 1]
+ .c rchars $id 1 foo {2 2}
+} -cleanup {
+ destroy .c
+} -returnCodes error -result {bad index "foo"}
+
+# cleanup
+imageCleanup
+cleanupTests
+return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tk8.6/tests/choosedir.test b/tk8.6/tests/choosedir.test
new file mode 100644
index 0000000..f67a721
--- /dev/null
+++ b/tk8.6/tests/choosedir.test
@@ -0,0 +1,174 @@
+# This file is a Tcl script to test out Tk's "tk_chooseDir" and
+# It is organized in the standard fashion for Tcl tests.
+#
+# Copyright (c) 1996 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+
+#----------------------------------------------------------------------
+#
+# Procedures needed by this test file
+#
+#----------------------------------------------------------------------
+
+proc ToPressButton {parent btn} {
+ after 100 SendButtonPress $parent $btn mouse
+}
+
+proc ToEnterDirsByKey {parent dirs} {
+ after 100 [list EnterDirsByKey $parent $dirs]
+}
+
+proc PressButton {btn} {
+ event generate $btn <Enter>
+ event generate $btn <1> -x 5 -y 5
+ event generate $btn <ButtonRelease-1> -x 5 -y 5
+}
+
+proc EnterDirsByKey {parent dirs} {
+ global tk_strictMotif
+ if {$parent == "."} {
+ set w .__tk_choosedir
+ } else {
+ set w $parent.__tk_choosedir
+ }
+ upvar ::tk::dialog::file::__tk_choosedir data
+
+ foreach dir $dirs {
+ $data(ent) delete 0 end
+ $data(ent) insert 0 $dir
+ update
+ SendButtonPress $parent ok mouse
+ after 50
+ }
+}
+
+proc SendButtonPress {parent btn type} {
+ global tk_strictMotif
+ if {$parent == "."} {
+ set w .__tk_choosedir
+ } else {
+ set w $parent.__tk_choosedir
+ }
+ upvar ::tk::dialog::file::__tk_choosedir data
+
+ set button $data($btn\Btn)
+ if ![winfo ismapped $button] {
+ update
+ }
+
+ if {$type == "mouse"} {
+ PressButton $button
+ } else {
+ event generate $w <Enter>
+ focus $w
+ event generate $button <Enter>
+ event generate $w <KeyPress> -keysym Return
+ }
+}
+
+
+#----------------------------------------------------------------------
+#
+# The test suite proper
+#
+#----------------------------------------------------------------------
+# Make a dir for us to rely on for tests
+set real [makeDirectory choosedirTest]
+set dir [file dirname $real]
+set fake [file join $dir non-existant]
+
+set parent .
+
+test choosedir-1.1 {tk_chooseDirectory command} -body {
+ tk_chooseDirectory -initialdir
+} -returnCodes error -result {value for "-initialdir" missing}
+test choosedir-1.2 {tk_chooseDirectory command} -body {
+ tk_chooseDirectory -mustexist
+} -returnCodes error -result {value for "-mustexist" missing}
+test choosedir-1.3 {tk_chooseDirectory command} -body {
+ tk_chooseDirectory -parent
+} -returnCodes error -result {value for "-parent" missing}
+test choosedir-1.4 {tk_chooseDirectory command} -body {
+ tk_chooseDirectory -title
+} -returnCodes error -result {value for "-title" missing}
+test choosedir-1.5.1 {tk_chooseDirectory command} -constraints notAqua -body {
+ tk_chooseDirectory -foo bar
+} -returnCodes error -result {bad option "-foo": must be -initialdir, -mustexist, -parent, or -title}
+test choosedir-1.5.2 {tk_chooseDirectory command} -constraints aqua -body {
+ tk_chooseDirectory -foo bar
+} -returnCodes error -result {bad option "-foo": must be -initialdir, -message, -mustexist, -parent, -title, or -command}
+test choosedir-1.6 {tk_chooseDirectory command} -body {
+ tk_chooseDirectory -parent foo.bar
+} -returnCodes error -result {bad window path name "foo.bar"}
+
+
+test choosedir-2.1 {tk_chooseDirectory command, cancel gives null} -constraints {
+ unix notAqua
+} -body {
+ ToPressButton $parent cancel
+ tk_chooseDirectory -title "Press Cancel" -parent $parent
+} -result {}
+
+
+test choosedir-3.1 {tk_chooseDirectory -mustexist 1} -constraints {
+ unix notAqua
+} -body {
+ # first enter a bogus dirname, then enter a real one.
+ ToEnterDirsByKey $parent [list $fake $real $real]
+ set result [tk_chooseDirectory \
+ -title "Enter \"$fake\", press OK, enter \"$real\", press OK" \
+ -parent $parent -mustexist 1]
+ set result
+} -result $real
+test choosedir-3.2 {tk_chooseDirectory -mustexist 0} -constraints {
+ unix notAqua
+} -body {
+ ToEnterDirsByKey $parent [list $fake $fake]
+ tk_chooseDirectory -title "Enter \"$fake\", press OK" \
+ -parent $parent -mustexist 0
+} -result $fake
+
+
+test choosedir-4.1 {tk_chooseDirectory command, initialdir} -constraints {
+ unix notAqua
+} -body {
+ ToPressButton $parent ok
+ tk_chooseDirectory -title "Press Ok" -parent $parent -initialdir $real
+} -result $real
+test choosedir-4.2 {tk_chooseDirectory command, initialdir} -constraints {
+ unix notAqua
+} -body {
+ ToEnterDirsByKey $parent [list $fake $fake]
+ tk_chooseDirectory \
+ -title "Enter \"$fake\" and press Ok" \
+ -parent $parent -initialdir $real
+} -result $fake
+test choosedir-4.3 {tk_chooseDirectory command, {} initialdir} -constraints {
+ unix notAqua
+} -body {
+ catch {unset ::tk::dialog::file::__tk_choosedir}
+ ToPressButton $parent ok
+ tk_chooseDirectory \
+ -title "Press OK" \
+ -parent $parent -initialdir ""
+} -result [pwd]
+
+
+test choosedir-5.1 {tk_chooseDirectory, handles {} entry text} -constraints {
+ unix notAqua
+} -body {
+ ToEnterDirsByKey $parent [list "" $real $real]
+ tk_chooseDirectory -title "Clear entry, Press OK; Enter $real, press OK" \
+ -parent $parent
+} -result $real
+
+# cleanup
+removeDirectory choosedirTest
+cleanupTests
+return
diff --git a/tk8.6/tests/clipboard.test b/tk8.6/tests/clipboard.test
new file mode 100644
index 0000000..9689942
--- /dev/null
+++ b/tk8.6/tests/clipboard.test
@@ -0,0 +1,364 @@
+# This file is a Tcl script to test out Tk's clipboard management code,
+# especially the "clipboard" command. It is organized in the standard
+# fashion for Tcl tests.
+#
+# Copyright (c) 1994 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+#
+# Note: Multiple display clipboard handling will only be tested if the
+# environment variable TK_ALT_DISPLAY is set to an alternate display.
+#
+
+#################################################################
+# Note that some of these tests may fail if another application #
+# is grabbing the clipboard (e.g. an X server, or a VNC viewer) #
+#################################################################
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+
+# set up a very large buffer to test INCR retrievals
+set longValue ""
+foreach i {a b c d e f g j h i j k l m o p q r s t u v w x y z} {
+ set j $i.1$i.2$i.3$i.4$i.5$i.6$i.7$i.8$i.9$i.10$i.11$i.12$i.13$i.14
+ append longValue A$j B$j C$j D$j E$j F$j G$j H$j I$j K$j L$j M$j N$j
+}
+
+# Now we start the main body of the test code
+
+test clipboard-1.1 {ClipboardHandler procedure} -setup {
+ clipboard clear
+} -body {
+ clipboard append "test"
+ clipboard get
+} -cleanup {
+ clipboard clear
+} -result {test}
+test clipboard-1.2 {ClipboardHandler procedure} -setup {
+ clipboard clear
+} -body {
+ clipboard append "test"
+ clipboard append "ing"
+ clipboard get
+} -cleanup {
+ clipboard clear
+} -result {testing}
+test clipboard-1.3 {ClipboardHandler procedure} -setup {
+ clipboard clear
+} -body {
+ clipboard append "t"
+ clipboard append "e"
+ clipboard append "s"
+ clipboard append "t"
+ clipboard get
+} -cleanup {
+ clipboard clear
+} -result {test}
+test clipboard-1.4 {ClipboardHandler procedure} -setup {
+ clipboard clear
+} -body {
+ clipboard append $longValue
+ clipboard get
+} -cleanup {
+ clipboard clear
+} -result "$longValue"
+test clipboard-1.5 {ClipboardHandler procedure} -setup {
+ clipboard clear
+} -body {
+ clipboard append $longValue
+ clipboard append "test"
+ clipboard get
+} -cleanup {
+ clipboard clear
+} -result "${longValue}test"
+test clipboard-1.6 {ClipboardHandler procedure} -setup {
+ clipboard clear
+} -body {
+ clipboard append -t TEST $longValue
+ clipboard append -t STRING "test"
+ list [clipboard get -t STRING] [clipboard get -t TEST]
+} -cleanup {
+ clipboard clear
+} -result [list test $longValue]
+test clipboard-1.7 {ClipboardHandler procedure} -setup {
+ clipboard clear
+} -body {
+ clipboard append -t TEST [string range $longValue 1 4000]
+ clipboard append -t STRING "test"
+ list [clipboard get -t STRING] [clipboard get -t TEST]
+} -cleanup {
+ clipboard clear
+} -result [list test [string range $longValue 1 4000]]
+test clipboard-1.8 {ClipboardHandler procedure} -setup {
+ clipboard clear
+} -body {
+ clipboard append ""
+ clipboard get
+} -cleanup {
+ clipboard clear
+} -result {}
+test clipboard-1.9 {ClipboardHandler procedure} -setup {
+ clipboard clear
+} -body {
+ clipboard append ""
+ clipboard append "Test"
+ clipboard get
+} -cleanup {
+ clipboard clear
+} -result {Test}
+
+##############################################################################
+
+test clipboard-2.1 {ClipboardAppHandler procedure} -setup {
+ set oldAppName [tk appname]
+ clipboard clear
+} -body {
+ tk appname UnexpectedName
+ clipboard append -type NEW_TYPE Data
+ selection get -selection CLIPBOARD -type TK_APPLICATION
+} -cleanup {
+ tk appname $oldAppName
+ clipboard clear
+} -result {UnexpectedName}
+
+##############################################################################
+
+test clipboard-3.1 {ClipboardWindowHandler procedure} -setup {
+ set oldAppName [tk appname]
+ clipboard clear
+} -body {
+ tk appname UnexpectedName
+ clipboard append -type NEW_TYPE Data
+ selection get -selection CLIPBOARD -type TK_WINDOW
+} -cleanup {
+ tk appname $oldAppName
+ clipboard clear
+} -result {.}
+
+##############################################################################
+
+test clipboard-4.1 {ClipboardLostSel procedure} -setup {
+ clipboard clear
+} -body {
+ clipboard append "Test"
+ selection clear -s CLIPBOARD
+ clipboard get
+} -cleanup {
+ clipboard clear
+} -returnCodes error -result {CLIPBOARD selection doesn't exist or form "STRING" not defined}
+test clipboard-4.2 {ClipboardLostSel procedure} -setup {
+ clipboard clear
+} -body {
+ clipboard append "Test"
+ clipboard append -t TEST "Test2"
+ selection clear -s CLIPBOARD
+ clipboard get
+} -cleanup {
+ clipboard clear
+} -returnCodes error -result {CLIPBOARD selection doesn't exist or form "STRING" not defined}
+test clipboard-4.3 {ClipboardLostSel procedure} -setup {
+ clipboard clear
+} -body {
+ clipboard append "Test"
+ clipboard append -t TEST "Test2"
+ selection clear -s CLIPBOARD
+ clipboard get -t TEST
+} -cleanup {
+ clipboard clear
+} -returnCodes error -result {CLIPBOARD selection doesn't exist or form "TEST" not defined}
+test clipboard-4.4 {ClipboardLostSel procedure} -setup {
+ clipboard clear
+} -body {
+ clipboard append "Test"
+ clipboard append -t TEST "Test2"
+ clipboard append "Test3"
+ selection clear -s CLIPBOARD
+ clipboard get
+} -cleanup {
+ clipboard clear
+} -returnCodes error -result {CLIPBOARD selection doesn't exist or form "STRING" not defined}
+test clipboard-4.5 {ClipboardLostSel procedure} -setup {
+ clipboard clear
+} -body {
+ clipboard append "Test"
+ clipboard append -t TEST "Test2"
+ clipboard append "Test3"
+ selection clear -s CLIPBOARD
+ clipboard get -t TEST
+} -cleanup {
+ clipboard clear
+} -returnCodes error -result {CLIPBOARD selection doesn't exist or form "TEST" not defined}
+
+
+
+##############################################################################
+
+test clipboard-5.1 {Tk_ClipboardClear procedure} -setup {
+ clipboard clear
+} -body {
+ clipboard append -t TEST "test"
+ set result [lsort [clipboard get TARGETS]]
+ clipboard clear
+ list $result [lsort [clipboard get TARGETS]]
+} -cleanup {
+ clipboard clear
+} -result {{MULTIPLE TARGETS TEST TIMESTAMP TK_APPLICATION TK_WINDOW} {MULTIPLE TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW}}
+test clipboard-5.2 {Tk_ClipboardClear procedure} -setup {
+ clipboard clear
+} -body {
+ clipboard append -t TEST "test"
+ set result [lsort [clipboard get TARGETS]]
+ selection own -s CLIPBOARD .
+ lappend result [lsort [clipboard get TARGETS]]
+ clipboard clear
+ clipboard append -t TEST "test"
+ lappend result [lsort [clipboard get TARGETS]]
+} -cleanup {
+ clipboard clear
+} -result {MULTIPLE TARGETS TEST TIMESTAMP TK_APPLICATION TK_WINDOW {MULTIPLE TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW} {MULTIPLE TARGETS TEST TIMESTAMP TK_APPLICATION TK_WINDOW}}
+
+##############################################################################
+
+test clipboard-6.1 {Tk_ClipboardAppend procedure} -setup {
+ clipboard clear
+} -body {
+ clipboard append "first chunk"
+ selection own -s CLIPBOARD .
+ clipboard append " second chunk"
+ clipboard get
+} -cleanup {
+ clipboard clear
+} -returnCodes ok -result {first chunk second chunk}
+test clipboard-6.2 {Tk_ClipboardAppend procedure} -constraints x11 -setup {
+ clipboard clear
+} -body {
+ setupbg
+ clipboard append -f INTEGER -t TEST "16"
+ set result [dobg {clipboard get TEST}]
+ return $result
+} -cleanup {
+ clipboard clear
+ cleanupbg
+} -result {0x10 }
+test clipboard-6.3 {Tk_ClipboardAppend procedure} -setup {
+ clipboard clear
+} -body {
+ clipboard append -f INTEGER -t TEST "16"
+ clipboard append -t TEST "test"
+} -cleanup {
+ clipboard clear
+} -returnCodes error -result {format "STRING" does not match current format "INTEGER" for TEST}
+
+##############################################################################
+
+test clipboard-7.1 {Tk_ClipboardCmd procedure} -body {
+ clipboard
+} -returnCodes error -result {wrong # args: should be "clipboard option ?arg ...?"}
+test clipboard-7.2 {Tk_ClipboardCmd procedure} -setup {
+ clipboard clear
+} -body {
+ clipboard append --
+} -cleanup {
+ clipboard clear
+} -returnCodes ok -result {}
+test clipboard-7.3 {Tk_ClipboardCmd procedure} -setup {
+ clipboard clear
+} -body {
+ clipboard append --
+ selection get -selection CLIPBOARD
+} -cleanup {
+ clipboard clear
+} -result {--}
+test clipboard-7.4 {Tk_ClipboardCmd procedure} -setup {
+ clipboard clear
+} -body {
+ clipboard append -- information
+ selection get -selection CLIPBOARD
+} -cleanup {
+ clipboard clear
+} -result {information}
+test clipboard-7.5 {Tk_ClipboardCmd procedure} -body {
+ clipboard append --x a b
+} -returnCodes error -result {bad option "--x": must be -displayof, -format, or -type}
+test clipboard-7.6 {Tk_ClipboardCmd procedure} -body {
+ clipboard append -- a b
+} -returnCodes error -result {wrong # args: should be "clipboard append ?-option value ...? data"}
+test clipboard-7.7 {Tk_ClipboardCmd procedure} -setup {
+ clipboard clear
+} -body {
+ clipboard append -format
+} -returnCodes ok -result {}
+test clipboard-7.8 {Tk_ClipboardCmd procedure} -setup {
+ clipboard clear
+} -body {
+ clipboard append -format
+ selection get -selection CLIPBOARD
+} -cleanup {
+ clipboard clear
+} -result {-format}
+test clipboard-7.9 {Tk_ClipboardCmd procedure} -body {
+ clipboard append -displayofoo f
+} -returnCodes error -result {bad option "-displayofoo": must be -displayof, -format, or -type}
+test clipboard-7.10 {Tk_ClipboardCmd procedure} -body {
+ clipboard append -type TEST
+} -returnCodes error -result {wrong # args: should be "clipboard append ?-option value ...? data"}
+test clipboard-7.11 {Tk_ClipboardCmd procedure} -body {
+ clipboard append -displayof foo "test"
+} -returnCodes error -result {bad window path name "foo"}
+test clipboard-7.12 {Tk_ClipboardCmd procedure} -body {
+ clipboard clear -displayof
+} -returnCodes error -result {wrong # args: should be "clipboard clear ?-displayof window?"}
+test clipboard-7.13 {Tk_ClipboardCmd procedure} -body {
+ clipboard clear -displayofoo f
+} -returnCodes error -result {bad option "-displayofoo": must be -displayof}
+test clipboard-7.14 {Tk_ClipboardCmd procedure} -body {
+ clipboard clear foo
+} -returnCodes error -result {wrong # args: should be "clipboard clear ?-displayof window?"}
+test clipboard-7.15 {Tk_ClipboardCmd procedure} -body {
+ clipboard clear -displayof foo
+} -returnCodes error -result {bad window path name "foo"}
+test clipboard-7.16 {Tk_ClipboardCmd procedure} -body {
+ clipboard error
+} -returnCodes error -result {bad option "error": must be append, clear, or get}
+test clipboard-7.17 {Tk_ClipboardCmd procedure} -setup {
+ clipboard clear
+} -body {
+ clipboard append -displayof
+} -cleanup {
+ clipboard clear
+} -returnCodes ok -result {}
+test clipboard-7.18 {Tk_ClipboardCmd procedure} -setup {
+ clipboard clear
+} -body {
+ clipboard append -displayof
+ selection get -selection CLIPBOARD
+} -cleanup {
+ clipboard clear
+} -result {-displayof}
+test clipboard-7.19 {Tk_ClipboardCmd procedure} -setup {
+ clipboard clear
+} -body {
+ clipboard append -type
+} -cleanup {
+ clipboard clear
+} -returnCodes ok -result {}
+test clipboard-7.20 {Tk_ClipboardCmd procedure} -setup {
+ clipboard clear
+} -body {
+ clipboard append -type
+ selection get -selection CLIPBOARD
+} -cleanup {
+ clipboard clear
+} -result {-type}
+
+# cleanup
+cleanupTests
+return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tk8.6/tests/clrpick.test b/tk8.6/tests/clrpick.test
new file mode 100644
index 0000000..c15308b
--- /dev/null
+++ b/tk8.6/tests/clrpick.test
@@ -0,0 +1,216 @@
+# This file is a Tcl script to test out Tk's "tk_chooseColor" command.
+# It is organized in the standard fashion for Tcl tests.
+#
+# Copyright (c) 1996 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+namespace import -force tcltest::test
+
+if {[testConstraint defaultPseudocolor8]} {
+ # let's soak up a bunch of colors...so that
+ # machines with small color palettes still fail.
+ # some tests will be skipped if there are no more colors
+ set numcolors 32
+ testConstraint colorsLeftover 1
+ set i 0
+ canvas .c
+ pack .c -expand 1 -fill both
+ while {$i<$numcolors} {
+ set color \#[format "%02x%02x%02x" $i [expr $i+1] [expr $i+3]]
+ .c create rectangle [expr 10+$i] [expr 10+$i] [expr 50+$i] [expr 50+$i] -fill $color -outline $color
+ incr i
+ }
+ set i 0
+ while {$i<$numcolors} {
+ set color [.c itemcget $i -fill]
+ if {$color != ""} {
+ foreach {r g b} [winfo rgb . $color] {}
+ set r [expr $r/256]
+ set g [expr $g/256]
+ set b [expr $b/256]
+ if {"$color" != "#[format %02x%02x%02x $r $g $b]"} {
+ testConstraint colorsLeftover 0
+ }
+ }
+ .c delete $i
+ incr i
+ }
+ destroy .c
+} else {
+ testConstraint colorsLeftover 0
+}
+
+test clrpick-1.1 {tk_chooseColor command} -body {
+ tk_chooseColor -foo
+} -returnCodes error -result {bad option "-foo": must be -initialcolor, -parent, or -title}
+
+test clrpick-1.2 {tk_chooseColor command } -body {
+ tk_chooseColor -initialcolor
+} -returnCodes error -result {value for "-initialcolor" missing}
+test clrpick-1.2.1 {tk_chooseColor command } -body {
+ tk_chooseColor -parent
+} -returnCodes error -result {value for "-parent" missing}
+test clrpick-1.2.2 {tk_chooseColor command } -body {
+ tk_chooseColor -title
+} -returnCodes error -result {value for "-title" missing}
+
+test clrpick-1.3 {tk_chooseColor command} -body {
+ tk_chooseColor -foo bar
+} -returnCodes error -result {bad option "-foo": must be -initialcolor, -parent, or -title}
+test clrpick-1.4 {tk_chooseColor command} -body {
+ tk_chooseColor -initialcolor
+} -returnCodes error -result {value for "-initialcolor" missing}
+test clrpick-1.5 {tk_chooseColor command} -body {
+ tk_chooseColor -parent foo.bar
+} -returnCodes error -result {bad window path name "foo.bar"}
+test clrpick-1.6 {tk_chooseColor command} -body {
+ tk_chooseColor -initialcolor badbadbaadcolor
+} -returnCodes error -result {unknown color name "badbadbaadcolor"}
+test clrpick-1.7 {tk_chooseColor command} -body {
+ tk_chooseColor -initialcolor ##badbadbaadcolor
+} -returnCodes error -result {invalid color name "##badbadbaadcolor"}
+
+
+# tests 3.1 and 3.2 fail when individually run
+# if there is no catch {tk_chooseColor -foo 1} msg
+# before settin isNative
+catch {tk_chooseColor -foo 1} msg
+set isNative [expr {[info commands tk::dialog::color::] eq ""}]
+
+proc ToPressButton {parent btn} {
+ global isNative
+ if {!$isNative} {
+ after 200 "SendButtonPress . $btn mouse"
+ }
+}
+
+proc ToChooseColorByKey {parent r g b} {
+ global isNative
+ if {!$isNative} {
+ after 200 ChooseColorByKey . $r $g $b
+ }
+}
+
+proc PressButton {btn} {
+ event generate $btn <Enter>
+ event generate $btn <1> -x 5 -y 5
+ event generate $btn <ButtonRelease-1> -x 5 -y 5
+}
+
+proc ChooseColorByKey {parent r g b} {
+ set w .__tk__color
+ upvar ::tk::dialog::color::[winfo name $w] data
+
+ update
+ $data(red,entry) delete 0 end
+ $data(green,entry) delete 0 end
+ $data(blue,entry) delete 0 end
+
+ $data(red,entry) insert 0 $r
+ $data(green,entry) insert 0 $g
+ $data(blue,entry) insert 0 $b
+
+ # Manually force the refresh of the color values instead
+ # of counting on the timing of the event stream to change
+ # the values for us.
+ tk::dialog::color::HandleRGBEntry $w
+
+ SendButtonPress . ok mouse
+}
+
+proc SendButtonPress {parent btn type} {
+ set w .__tk__color
+ upvar ::tk::dialog::color::[winfo name $w] data
+
+ set button $data($btn\Btn)
+ if ![winfo ismapped $button] {
+ update
+ }
+
+ if {$type == "mouse"} {
+ PressButton $button
+ } else {
+ event generate $w <Enter>
+ focus $w
+ event generate $button <Enter>
+ event generate $w <KeyPress> -keysym Return
+ }
+}
+
+
+
+test clrpick-2.1 {tk_chooseColor command} -constraints {
+ nonUnixUserInteraction colorsLeftover
+} -setup {
+ set verylongstring longstring:
+ set verylongstring $verylongstring$verylongstring
+ set verylongstring $verylongstring$verylongstring
+ set verylongstring $verylongstring$verylongstring
+ set verylongstring $verylongstring$verylongstring
+ #set verylongstring $verylongstring$verylongstring
+ # Interesting thing...when this is too long, the
+ # delay caused in processing it kills the automated testing,
+ # and makes a lot of the test cases fail.
+ #set verylongstring $verylongstring$verylongstring
+ #set verylongstring $verylongstring$verylongstring
+ #set verylongstring $verylongstring$verylongstring
+ #set verylongstring $verylongstring$verylongstring
+} -body {
+ ToPressButton . ok
+ tk_chooseColor -title "Press Ok $verylongstring" -initialcolor #404040 \
+ -parent .
+} -result {#404040}
+test clrpick-2.2 {tk_chooseColor command} -constraints {
+ nonUnixUserInteraction colorsLeftover
+} -body {
+ set colors "128 128 64"
+ ToChooseColorByKey . 128 128 64
+ tk_chooseColor -parent . -title "choose #808040"
+} -result {#808040}
+test clrpick-2.3 {tk_chooseColor command} -constraints {
+ nonUnixUserInteraction colorsLeftover
+} -body {
+ ToPressButton . ok
+ tk_chooseColor -parent . -title "Press OK"
+} -result {#808040}
+test clrpick-2.4 {tk_chooseColor command} -constraints {
+ nonUnixUserInteraction colorsLeftover
+} -body {
+ ToPressButton . cancel
+ tk_chooseColor -parent . -title "Press Cancel"
+} -result {}
+
+
+test clrpick-3.1 {tk_chooseColor: background events} -constraints {
+ nonUnixUserInteraction
+} -body {
+ after 1 {set x 53}
+ ToPressButton . ok
+ tk_chooseColor -parent . -title "Press OK" -initialcolor #000000
+} -result {#000000}
+test clrpick-3.2 {tk_chooseColor: background events} -constraints {
+ nonUnixUserInteraction
+} -body {
+ after 1 {set x 53}
+ ToPressButton . cancel
+ tk_chooseColor -parent . -title "Press Cancel"
+} -result {}
+
+
+test clrpick-4.1 {tk_chooseColor: screen is inherited from parent} -constraints {
+ unix notAqua
+} -body {
+ after 50 {set ::scr [winfo screen .__tk__color]}
+ ToPressButton . cancel
+ tk_chooseColor -parent .
+ set ::scr
+} -result [winfo screen .]
+
+# cleanup
+cleanupTests
+return
+
diff --git a/tk8.6/tests/cmap.tcl b/tk8.6/tests/cmap.tcl
new file mode 100644
index 0000000..ea19131
--- /dev/null
+++ b/tk8.6/tests/cmap.tcl
@@ -0,0 +1,72 @@
+# This file creates a visual test for colormaps and the WM_COLORMAP_WINDOWS
+# property. It is part of the Tk visual test suite, which is invoked
+# via the "visual" script.
+
+catch {destroy .t}
+toplevel .t -colormap new
+wm title .t "Visual Test for Colormaps"
+wm iconname .t "Colormaps"
+wm geom .t +0+0
+
+# The following procedure creates a whole bunch of frames within a
+# window, in order to eat up all the colors in a colormap.
+
+proc colors {w redInc greenInc blueInc} {
+ set red 0
+ set green 0
+ set blue 0
+ for {set y 0} {$y < 8} {incr y} {
+ for {set x 0} {$x < 8} {incr x} {
+ frame $w.f$x,$y -width 40 -height 40 -bd 2 -relief raised \
+ -bg [format #%02x%02x%02x $red $green $blue]
+ place $w.f$x,$y -x [expr {40*$x}] -y [expr {40*$y}]
+ incr red $redInc
+ incr green $greenInc
+ incr blue $blueInc
+ }
+ }
+}
+
+message .t.m -width 6i -text {This window displays two nested frames, each with a whole bunch of subwindows that eat up a lot of colors. The toplevel window has its own colormap, which is inherited by the outer frame. The inner frame has its own colormap. As you move the mouse around, the colors in the frames should change back and forth.}
+pack .t.m -side top -fill x
+
+button .t.quit -text Quit -command {destroy .t}
+pack .t.quit -side bottom -pady 3 -ipadx 4 -ipady 2
+
+frame .t.f -width 700 -height 450 -relief raised -bd 2
+pack .t.f -side top -padx 1c -pady 1c
+colors .t.f 4 0 0
+frame .t.f.f -width 350 -height 350 -colormap new -bd 2 -relief raised
+place .t.f.f -relx 1.0 -rely 0 -anchor ne
+colors .t.f.f 0 4 0
+bind .t.f.f <Enter> {wm colormapwindows .t {.t.f.f .t}}
+bind .t.f.f <Leave> {wm colormapwindows .t {.t .t.f.f}}
+
+catch {destroy .t2}
+toplevel .t2
+wm title .t2 "Visual Test for Colormaps"
+wm iconname .t2 "Colormaps"
+wm geom .t2 +0-0
+
+message .t2.m -width 6i -text {This window just eats up most of the colors in the default colormap.}
+pack .t2.m -side top -fill x
+
+button .t2.quit -text Quit -command {destroy .t2}
+pack .t2.quit -side bottom -pady 3 -ipadx 4 -ipady 2
+
+frame .t2.f -height 320 -width 320
+pack .t2.f -side bottom
+colors .t2.f 0 0 4
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tk8.6/tests/cmds.test b/tk8.6/tests/cmds.test
new file mode 100644
index 0000000..fa7e788
--- /dev/null
+++ b/tk8.6/tests/cmds.test
@@ -0,0 +1,60 @@
+# This file is a Tcl script to test the procedures in the file
+# tkCmds.c. It is organized in the standard fashion for Tcl tests.
+#
+# Copyright (c) 1996 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+namespace import -force tcltest::test
+
+update
+
+test cmds-1.1 {tkwait visibility, argument errors} -body {
+ tkwait visibility
+} -returnCodes {error} -result {wrong # args: should be "tkwait variable|visibility|window name"}
+test cmds-1.2 {tkwait visibility, argument errors} -body {
+ tkwait visibility foo bar
+} -returnCodes {error} -result {wrong # args: should be "tkwait variable|visibility|window name"}
+test cmds-1.3 {tkwait visibility, argument errors} -body {
+ tkwait visibility bad_window
+} -returnCodes {error} -result {bad window path name "bad_window"}
+test cmds-1.4 {tkwait visibility, waiting for window to be mapped} -setup {
+ button .b -text "Test"
+ set x init
+} -body {
+ after 100 {set x delay; place .b -x 0 -y 0}
+ tkwait visibility .b
+ return $x
+} -cleanup {
+ destroy .b
+} -result {delay}
+test cmds-1.5 {tkwait visibility, window gets deleted} -setup {
+ frame .f
+ button .f.b -text "Test"
+ pack .f.b
+ set x init
+} -body {
+ after 100 {set x deleted; destroy .f}
+ tkwait visibility .f.b
+} -returnCodes {error} -result {window ".f.b" was deleted before its visibility changed}
+test cmds-1.6 {tkwait visibility, window gets deleted} -setup {
+ frame .f
+ button .f.b -text "Test"
+ pack .f.b
+ set x init
+} -body {
+ after 100 {set x deleted; destroy .f}
+ catch {tkwait visibility .f.b}
+ return $x
+} -cleanup {
+ destroy .f
+} -result {deleted}
+
+
+# cleanup
+cleanupTests
+return
+
diff --git a/tk8.6/tests/color.test b/tk8.6/tests/color.test
new file mode 100644
index 0000000..4cdaf23
--- /dev/null
+++ b/tk8.6/tests/color.test
@@ -0,0 +1,310 @@
+# This file is a Tcl script to test out the procedures in the file
+# tkColor.c. It is organized in the standard fashion for Tcl tests.
+#
+# Copyright (c) 1995-1998 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.1
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+
+# cname --
+# Returns a proper name for a color, given its intensities.
+#
+# Arguments:
+# r, g, b - Intensities on a 0-255 scale.
+
+proc cname {r g b} {
+ format #%02x%02x%02x $r $g $b
+}
+proc cname4 {r g b} {
+ format #%04x%04x%04x $r $g $b
+}
+
+# mkColors --
+# Creates a canvas and fills it with a 2-D array of squares, each of a
+# different color.
+#
+# Arguments:
+# c - Name of canvas window to create.
+# width - Number of squares in each row.
+# height - Number of squares in each column.
+# r, g, b - Initial value for red, green, and blue intensities.
+# rx, gx, bx - Change in intensities between adjacent elements in row.
+# ry, gy, by - Change in intensities between adjacent elements in column.
+
+proc mkColors {c width height r g b rx gx bx ry gy by} {
+ catch {destroy $c}
+ canvas $c -width 400 -height 200 -bd 0
+ for {set y 0} {$y < $height} {incr y} {
+ for {set x 0} {$x < $width} {incr x} {
+ set color [format #%02x%02x%02x [expr $r + $y*$ry + $x*$rx] \
+ [expr $g + $y*$gy + $x*$gx] [expr $b + $y*$by + $x*$bx]]
+ $c create rectangle [expr 10*$x] [expr 20*$y] \
+ [expr 10*$x + 10] [expr 20*$y + 20] -outline {} \
+ -fill $color
+ }
+ }
+}
+
+# closest -
+# Given intensities between 0 and 255, return the closest intensities
+# that the server can provide.
+#
+# Arguments:
+# w - Window in which to lookup color
+# r, g, b - Desired intensities, between 0 and 255.
+
+proc closest {w r g b} {
+ set vals [winfo rgb $w [cname $r $g $b]]
+ list [expr [lindex $vals 0]/256] [expr [lindex $vals 1]/256] \
+ [expr [lindex $vals 2]/256]
+}
+
+# c255 -
+# Given a list of red, green, and blue intensities, scale them
+# down to a 0-255 range.
+#
+# Arguments:
+# vals - List of intensities.
+
+proc c255 {vals} {
+ list [expr {[lindex $vals 0]/256}] [expr {[lindex $vals 1]/256}] \
+ [expr {[lindex $vals 2]/256}]
+}
+
+# colorsFree --
+#
+# Returns 1 if there appear to be free colormap entries in a window,
+# 0 otherwise.
+#
+# Arguments:
+# w - Name of window in which to check.
+# red, green, blue - Intensities to use in a trial color allocation
+# to see if there are colormap entries free.
+
+proc colorsFree {w {red 31} {green 245} {blue 192}} {
+ set vals [winfo rgb $w [format #%02x%02x%02x $red $green $blue]]
+ expr ([lindex $vals 0]/256 == $red) && ([lindex $vals 1]/256 == $green) \
+ && ([lindex $vals 2]/256 == $blue)
+}
+
+# -- WARNING (SB, 6.4.2017) --
+#
+# The if block below looks _very_ outdated. It didn't get any
+# substantial changes as far back as the fossil history goes. It might
+# be from a time, when 256 color was the best you could get! :-o.
+#
+# The problem is, on machines with a fancy 24 truecolor display, the
+# 'colorsFree' constraint doesn't get set, turning off pretty much every test
+# in this file.
+
+if {[testConstraint pseudocolor8]} {
+ toplevel .t -visual {pseudocolor 8} -colormap new
+ wm geom .t +0+0
+ mkColors .t.c 40 6 0 0 0 0 6 0 0 0 40
+ pack .t.c
+ update
+
+ testConstraint colorsFree [colorsFree .t.c 101 233 17]
+
+ if {[testConstraint colorsFree]} {
+ mkColors .t.c2 20 1 250 0 0 -10 0 0 0 0 0
+ pack .t.c2
+ testConstraint colorsFree [expr {![colorsFree .t.c]}]
+ }
+ destroy .t.c .t.c2
+}
+
+test color-1.1 {Tk_AllocColorFromObj - converting internal reps} colorsFree {
+ set x green
+ lindex $x 0
+ destroy .b1
+ button .b1 -foreground $x -text .b1
+ lindex $x 0
+ testcolor green
+} {{1 0}}
+test color-1.2 {Tk_AllocColorFromObj - discard stale color} colorsFree {
+ set x green
+ destroy .b1 .b2
+ button .b1 -foreground $x -text First
+ destroy .b1
+ set result {}
+ lappend result [testcolor green]
+ button .b2 -foreground $x -text Second
+ lappend result [testcolor green]
+} {{} {{1 1}}}
+test color-1.3 {Tk_AllocColorFromObj - reuse existing color} colorsFree {
+ set x green
+ destroy .b1 .b2
+ button .b1 -foreground $x -text First
+ set result {}
+ lappend result [testcolor green]
+ button .b2 -foreground $x -text Second
+ pack .b1 .b2 -side top
+ lappend result [testcolor green]
+} {{{1 1}} {{2 1}}}
+test color-1.4 {Tk_AllocColorFromObj - try other colors in list} colorsFree {
+ set x purple
+ destroy .b1 .b2 .t.b
+ button .b1 -foreground $x -text First
+ pack .b1 -side top
+ set result {}
+ lappend result [testcolor purple]
+ button .t.b -foreground $x -text Second
+ pack .t.b -side top
+ lappend result [testcolor purple]
+ button .b2 -foreground $x -text Third
+ pack .b2 -side top
+ lappend result [testcolor purple]
+} {{{1 1}} {{1 1} {1 0}} {{1 0} {2 1}}}
+test color-1.5 {Color table} nonPortable {
+ set fd [open ../xlib/rgb.txt]
+ set result {}
+ while {[gets $fd line] != -1} {
+ if {[string index $line 0] == "!"} continue
+ set rgb [c255 [winfo rgb . [lrange $line 3 end]]]
+ if {$rgb != [lrange $line 0 2] } {
+ append result $line\n
+ }
+
+ }
+ return $result
+} {}
+
+test color-2.1 {Tk_GetColor procedure} colorsFree {
+ c255 [winfo rgb .t #FF0000]
+} {255 0 0}
+test color-2.2 {Tk_GetColor procedure} colorsFree {
+ list [catch {winfo rgb .t noname} msg] $msg
+} {1 {unknown color name "noname"}}
+test color-2.3 {Tk_GetColor procedure} colorsFree {
+ c255 [winfo rgb .t #123456]
+} {18 52 86}
+test color-2.4 {Tk_GetColor procedure} colorsFree {
+ list [catch {winfo rgb .t #xyz} msg] $msg
+} {1 {invalid color name "#xyz"}}
+test color-2.5 {Tk_GetColor procedure} colorsFree {
+ winfo rgb .t #00FF00
+} {0 65535 0}
+test color-2.6 {Tk_GetColor procedure} {colorsFree nonPortable} {
+ # Red doesn't always map to *pure* red
+ winfo rgb .t red
+} {65535 0 0}
+test color-2.7 {Tk_GetColor procedure} colorsFree {
+ winfo rgb .t #ff0000
+} {65535 0 0}
+test color-2.8 {Tk_GetColor, invalid char after 3 valid hex digits} -body {
+ winfo rgb . #abcg
+} -returnCodes error -result {invalid color name "#abcg"}
+test color-2.9 {Tk_GetColor, invalid char after 6 vaild hex digits} -body {
+ winfo rgb . #aabbccz
+} -returnCodes error -result {invalid color name "#aabbccz"}
+test color-2.10 {Tk_GetColor, 3 hex digits, last one invalid} -body {
+ winfo rgb . #abz
+} -returnCodes error -result {invalid color name "#abz"}
+test color-2.11 {Tk_GetColor, 6 hex digits, last one invalid} -body {
+ winfo rgb . #12345g
+} -returnCodes error -result {invalid color name "#12345g"}
+
+test color-3.1 {Tk_FreeColor procedure, reference counting} colorsFree {
+ eval destroy [winfo child .t]
+ mkColors .t.c 40 6 0 240 240 0 -6 0 0 0 -40
+ pack .t.c
+ mkColors .t.c2 20 1 250 0 0 -10 0 0 0 0 0
+ pack .t.c2
+ update
+ set last [.t.c2 create rectangle 50 50 70 60 -outline {} \
+ -fill [cname 0 240 240]]
+ .t.c delete 1
+ set result [colorsFree .t]
+ .t.c2 delete $last
+ lappend result [colorsFree .t]
+} {0 1}
+test color-3.2 {Tk_FreeColor procedure, flushing stressed cmap information} colorsFree {
+ eval destroy [winfo child .t]
+ mkColors .t.c 40 6 0 240 240 0 -6 0 0 0 -40
+ pack .t.c
+ mkColors .t.c2 20 1 250 0 0 -10 0 0 0 0 0
+ mkColors .t.c2 20 1 250 250 0 -10 -10 0 0 0 0
+ pack .t.c2
+ update
+ closest .t 241 241 1
+} {240 240 0}
+test color-3.3 {Tk_FreeColorFromObj - reference counts} colorsFree {
+ set x purple
+ destroy .b1 .b2 .t.b
+ button .b1 -foreground $x -text First
+ pack .b1 -side top
+ button .t.b -foreground $x -text Second
+ pack .t.b -side top
+ button .b2 -foreground $x -text Third
+ pack .b2 -side top
+ set result {}
+ lappend result [testcolor purple]
+ destroy .b1
+ lappend result [testcolor purple]
+ destroy .b2
+ lappend result [testcolor purple]
+ destroy .t.b
+ lappend result [testcolor purple]
+} {{{1 0} {2 1}} {{1 0} {1 1}} {{1 0}} {}}
+test color-3.4 {Tk_FreeColorFromObj - unlinking from list} colorsFree {
+ destroy .b .t.b .t2 .t3
+ toplevel .t2 -visual {pseudocolor 8} -colormap new
+ toplevel .t3 -visual {pseudocolor 8} -colormap new
+ set x purple
+ button .b -foreground $x -text .b1
+ button .t.b1 -foreground $x -text .t.b1
+ button .t.b2 -foreground $x -text .t.b2
+ button .t2.b1 -foreground $x -text .t2.b1
+ button .t2.b2 -foreground $x -text .t2.b2
+ button .t2.b3 -foreground $x -text .t2.b3
+ button .t3.b1 -foreground $x -text .t3.b1
+ button .t3.b2 -foreground $x -text .t3.b2
+ button .t3.b3 -foreground $x -text .t3.b3
+ button .t3.b4 -foreground $x -text .t3.b4
+ set result {}
+ lappend result [testcolor purple]
+ destroy .t2
+ lappend result [testcolor purple]
+ destroy .b
+ lappend result [testcolor purple]
+ destroy .t3
+ lappend result [testcolor purple]
+ destroy .t
+ lappend result [testcolor purple]
+} {{{4 1} {3 0} {2 0} {1 0}} {{4 1} {2 0} {1 0}} {{4 1} {2 0}} {{2 0}} {}}
+
+test color-4.1 {FreeColorObjProc} -constraints {
+ colorsFree
+} -setup {
+ proc copy {s} {return [string index $s 0][string range $s 1 end]}
+} -body {
+ destroy .b
+ set x [copy purple]
+ button .b -foreground $x -text .b1
+ set y [copy purple]
+ .b configure -foreground $y
+ set z [copy purple]
+ .b configure -foreground $z
+ set result {}
+ lappend result [testcolor purple]
+ set x red
+ lappend result [testcolor purple]
+ set z 32
+ lappend result [testcolor purple]
+ destroy .b
+ lappend result [testcolor purple]
+ set y bogus
+ set result
+} -cleanup {
+ rename copy {}
+} -result {{{1 3}} {{1 2}} {{1 1}} {}}
+
+destroy .t
+
+# cleanup
+cleanupTests
+return
diff --git a/tk8.6/tests/config.test b/tk8.6/tests/config.test
new file mode 100644
index 0000000..833e288
--- /dev/null
+++ b/tk8.6/tests/config.test
@@ -0,0 +1,1929 @@
+# This file is a Tcl script to test the procedures in tkConfig.c,
+# which comprise the new new option configuration system. It is
+# organized in the standard "white-box" fashion for Tcl tests.
+#
+# Copyright (c) 1997 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+
+proc killTables {} {
+ # Note: it's important to delete chain2 before chain1, because
+ # chain2 depends on chain1. If chain1 is deleted first, the
+ # delete of chain2 will crash.
+ deleteWindows
+ foreach t {alltypes chain3 chain2 chain1 configerror internal
+ new notenoughparams twowindows} {
+ while {[testobjconfig info $t] != ""} {
+ testobjconfig delete $t
+ }
+ }
+}
+
+
+option clear
+deleteWindows
+if {[testConstraint testobjconfig]} {
+ killTables
+}
+
+test config-1.1 {Tk_CreateOptionTable - reference counts} -constraints {
+ testobjconfig
+} -body {
+ set x {}
+ testobjconfig alltypes .a
+ lappend x [testobjconfig info alltypes]
+ testobjconfig alltypes .b
+ lappend x [testobjconfig info alltypes]
+ set x
+} -cleanup {
+ killTables
+} -result {{1 16 -boolean} {2 16 -boolean}}
+test config-1.2 {Tk_CreateOptionTable - synonym initialization} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .a -synonym green
+ .a cget -color
+} -cleanup {
+ killTables
+} -result {green}
+test config-1.3 {Tk_CreateOptionTable - option database initialization} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .a
+ option add *b.string different
+ testobjconfig alltypes .b
+ list [.a cget -string] [.b cget -string]
+} -cleanup {
+ killTables
+ option clear
+} -result {foo different}
+test config-1.4 {Tk_CreateOptionTable - option database initialization} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .a
+ option add *b.String bar
+ testobjconfig alltypes .b
+ list [.a cget -string] [.b cget -string]
+} -cleanup {
+ killTables
+ option clear
+} -result {foo bar}
+test config-1.5 {Tk_CreateOptionTable - default initialization} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .a
+ .a cget -relief
+} -cleanup {
+ killTables
+} -result {raised}
+test config-1.6 {Tk_CreateOptionTable - chained tables} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig chain1 .a
+ testobjconfig chain2 .b
+ testobjconfig info chain2
+} -cleanup {
+ killTables
+} -result {1 4 -three 2 2 -one}
+test config-1.7 {Tk_CreateOptionTable - chained tables} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig chain2 .b
+ testobjconfig chain1 .a
+ testobjconfig info chain2
+} -cleanup {
+ killTables
+} -result {1 4 -three 2 2 -one}
+test config-1.8 {Tk_CreateOptionTable - chained tables} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig chain1 .a
+ testobjconfig chain2 .b
+ .a cget -four
+} -cleanup {
+ killTables
+} -returnCodes error -result {unknown option "-four"}
+test config-1.9 {Tk_CreateOptionTable - chained tables} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig chain1 .a
+ testobjconfig chain2 .b
+ catch {.a cget -four}
+ list [.a cget -one] [.b cget -four] [.b cget -one]
+} -cleanup {
+ killTables
+} -result {one four one}
+
+
+test config-2.1 {Tk_DeleteOptionTable - reference counts} -constraints {
+ testobjconfig
+} -body {
+ set x {}
+ testobjconfig chain1 .a
+ testobjconfig chain2 .b
+ testobjconfig chain3 .c
+ deleteWindows
+ testobjconfig delete chain3
+ lappend x [testobjconfig info chain2] [testobjconfig info chain1]
+ testobjconfig delete chain2
+ lappend x [testobjconfig info chain2] [testobjconfig info chain1]
+} -cleanup {
+ killTables
+} -result {{3 4 -three 2 2 -one} {2 2 -one} {} {2 2 -one}}
+
+# No tests for DestroyOptionHashTable; couldn't figure out how to test.
+
+test config-3.1 {Tk_InitOptions - priority of chained tables} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig chain1 .a
+ testobjconfig chain2 .b
+ list [.a cget -two] [.b cget -two]
+} -cleanup {
+ killTables
+} -result {two {two and a half}}
+test config-3.2 {Tk_InitOptions - initialize from database} -constraints {
+ testobjconfig
+} -body {
+ option add *a.color blue
+ testobjconfig alltypes .a
+ list [.a cget -color]
+} -cleanup {
+ killTables
+ option clear
+} -result {blue}
+test config-3.3 {Tk_InitOptions - initialize from database} -constraints {
+ testobjconfig
+} -body {
+ option add *a.justify bogus
+ testobjconfig alltypes .a
+ list [.a cget -justify]
+} -cleanup {
+ killTables
+ option clear
+} -result {left}
+test config-3.4 {Tk_InitOptions - initialize from widget class} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .a
+ list [.a cget -color]
+} -cleanup {
+ killTables
+} -result {red}
+test config-3.5 {Tk_InitOptions - no initial value} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .a
+ .a cget -anchor
+} -cleanup {
+ killTables
+} -result {}
+test config-3.6 {Tk_InitOptions - bad initial value} -constraints {
+ testobjconfig
+} -body {
+ option add *a.color non-existent
+ testobjconfig alltypes .a
+} -cleanup {
+ killTables
+ option clear
+} -returnCodes error -result {unknown color name "non-existent"}
+test config-3.7 {Tk_InitOptions - bad initial value} -constraints {
+ testobjconfig
+} -body {
+ option add *a.color non-existent
+ catch {testobjconfig alltypes .a}
+ return $errorInfo
+} -cleanup {
+ killTables
+ option clear
+} -result {unknown color name "non-existent"
+ (database entry for "-color" in widget ".a")
+ invoked from within
+"testobjconfig alltypes .a"}
+
+test config-3.8 {Tk_InitOptions - bad initial value} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig configerror
+} -returnCodes error -result {expected integer but got "bogus"}
+test config-3.9 {Tk_InitOptions - bad initial value} -constraints {
+ testobjconfig
+} -body {
+ catch {testobjconfig configerror}
+ return $errorInfo
+} -result {expected integer but got "bogus"
+ (default value for "-int")
+ invoked from within
+"testobjconfig configerror"}
+
+test config-4.1 {DoObjConfig - boolean} -constraints testobjconfig -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig alltypes .foo -boolean 0
+} -cleanup {
+ killTables
+} -returnCodes ok -result {.foo}
+test config-4.2 {DoObjConfig - boolean} -constraints testobjconfig -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig alltypes .foo -boolean 0
+ .foo cget -boolean
+} -cleanup {
+ killTables
+} -returnCodes ok -result {0}
+test config-4.3 {DoObjConfig - boolean} -constraints testobjconfig -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig alltypes .foo -boolean 0
+ .foo cget -boolean
+ rename .foo {}
+} -cleanup {
+ killTables
+} -returnCodes ok
+test config-4.4 {DoObjConfig - boolean} -constraints testobjconfig -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig alltypes .foo -boolean 1
+} -cleanup {
+ killTables
+} -returnCodes ok -result {.foo}
+test config-4.5 {DoObjConfig - boolean} -constraints testobjconfig -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig alltypes .foo -boolean 1
+ .foo cget -boolean
+} -cleanup {
+ killTables
+} -returnCodes ok -result {1}
+test config-4.6 {DoObjConfig - boolean} -constraints testobjconfig -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig alltypes .foo -boolean 1
+ .foo cget -boolean
+ rename .foo {}
+} -cleanup {
+ killTables
+} -returnCodes ok
+test config-4.7 {DoObjConfig - invalid boolean} -constraints {
+ testobjconfig
+} -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig alltypes .foo -boolean {}
+} -cleanup {
+ killTables
+} -returnCodes error -result {expected boolean value but got ""}
+test config-4.8 {DoObjConfig - boolean internal value} -constraints {
+ testobjconfig
+} -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig internal .foo -boolean 0
+ .foo cget -boolean
+} -cleanup {
+ killTables
+} -result {0}
+
+test config-4.9 {DoObjConfig - integer} -constraints testobjconfig -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig alltypes .foo -integer 3
+} -cleanup {
+ killTables
+} -returnCodes ok -result {.foo}
+test config-4.10 {DoObjConfig - integer} -constraints testobjconfig -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig alltypes .foo -integer 3
+ .foo cget -integer
+} -cleanup {
+ killTables
+} -returnCodes ok -result {3}
+test config-4.11 {DoObjConfig - integer} -constraints testobjconfig -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig alltypes .foo -integer 3
+ .foo cget -integer
+ rename .foo {}
+} -cleanup {
+ killTables
+} -returnCodes ok
+test config-4.12 {DoObjConfig - invalid integer} -constraints {
+ testobjconfig
+} -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig alltypes .foo -integer bar
+} -cleanup {
+ killTables
+} -cleanup {
+ killTables
+} -returnCodes error -result {expected integer but got "bar"}
+test config-4.13 {DoObjConfig - integer internal value} -constraints {
+ testobjconfig
+} -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig internal .foo -integer 421
+ .foo cget -integer
+} -cleanup {
+ killTables
+} -result {421}
+
+test config-4.14 {DoObjConfig - double} -constraints testobjconfig -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig alltypes .foo -double 3.14
+} -cleanup {
+ killTables
+} -returnCodes ok -result {.foo}
+test config-4.15 {DoObjConfig - double} -constraints testobjconfig -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig alltypes .foo -double 3.14
+ .foo cget -double
+} -cleanup {
+ killTables
+} -returnCodes ok -result {3.14}
+test config-4.16 {DoObjConfig - double} -constraints testobjconfig -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig alltypes .foo -double 3.14
+ .foo cget -double
+ rename .foo {}
+} -cleanup {
+ killTables
+} -returnCodes ok
+test config-4.17 {DoObjConfig - invalid double} -constraints {
+ testobjconfig
+} -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig alltypes .foo -double bar
+} -cleanup {
+ killTables
+} -returnCodes error -result {expected floating-point number but got "bar"}
+test config-4.18 {DoObjConfig - double internal value} -constraints {
+ testobjconfig
+} -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig internal .foo -double 62.75
+ .foo cget -double
+} -cleanup {
+ killTables
+} -result {62.75}
+
+test config-4.19 {DoObjConfig - string} -constraints testobjconfig -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig alltypes .foo -string test
+} -cleanup {
+ killTables
+} -returnCodes ok -result {.foo}
+test config-4.20 {DoObjConfig - string} -constraints testobjconfig -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig alltypes .foo -string test
+ .foo cget -string
+} -cleanup {
+ killTables
+} -returnCodes ok -result {test}
+test config-4.21 {DoObjConfig - string} -constraints testobjconfig -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig alltypes .foo -string test
+ .foo cget -string
+ rename .foo {}
+} -cleanup {
+ killTables
+} -returnCodes ok
+test config-4.22 {DoObjConfig - null string} -constraints testobjconfig -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig alltypes .foo -string {}
+} -cleanup {
+ killTables
+} -returnCodes ok -result {.foo}
+test config-4.23 {DoObjConfig - null string} -constraints testobjconfig -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig alltypes .foo -string {}
+ .foo cget -string
+} -cleanup {
+ killTables
+} -returnCodes ok -result {}
+test config-4.24 {DoObjConfig - null string} -constraints testobjconfig -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig alltypes .foo -string {}
+ .foo cget -string
+ rename .foo {}
+} -cleanup {
+ killTables
+} -returnCodes ok
+
+test config-4.25 {DoObjConfig - string internal value} -constraints {
+ testobjconfig
+} -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig internal .foo -string "this is a test"
+ .foo cget -string
+} -cleanup {
+ killTables
+} -result {this is a test}
+
+test config-4.26 {DoObjConfig - string table} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -stringtable two
+} -cleanup {
+ killTables
+} -returnCodes ok -result {.foo}
+test config-4.27 {DoObjConfig - string table} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -stringtable two
+ .foo cget -stringtable
+} -cleanup {
+ killTables
+} -returnCodes ok -result {two}
+test config-4.28 {DoObjConfig - string table} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -stringtable two
+ .foo cget -stringtable
+ rename .foo {}
+} -cleanup {
+ killTables
+} -returnCodes ok
+test config-4.29 {DoObjConfig - invalid string table} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .foo -stringtable foo
+} -cleanup {
+ killTables
+} -returnCodes error -result {bad stringtable "foo": must be one, two, three, or four}
+
+test config-4.30 {DoObjConfig - new string table} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .foo -stringtable two
+ .foo configure -stringtable three
+} -cleanup {
+ killTables
+} -returnCodes ok -result {16}
+test config-4.31 {DoObjConfig - new string table} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .foo -stringtable two
+ .foo configure -stringtable three
+ .foo cget -stringtable
+} -cleanup {
+ killTables
+} -returnCodes ok -result {three}
+test config-4.32 {DoObjConfig - new string table} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .foo -stringtable two
+ .foo configure -stringtable three
+ .foo cget -stringtable
+ rename .foo {}
+} -cleanup {
+ killTables
+} -returnCodes ok
+test config-4.33 {DoObjConfig - stringtable internal value} -constraints {
+ testobjconfig
+} -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig internal .foo -stringtable "four"
+ .foo cget -stringtable
+} -cleanup {
+ killTables
+} -result {four}
+
+test config-4.34 {DoObjConfig - color} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -color blue
+} -cleanup {
+ killTables
+} -returnCodes ok -result {.foo}
+test config-4.35 {DoObjConfig - color} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -color blue
+ .foo cget -color
+} -cleanup {
+ killTables
+} -returnCodes ok -result {blue}
+test config-4.36 {DoObjConfig - color} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -color blue
+ .foo cget -color
+ rename .foo {}
+} -cleanup {
+ killTables
+} -returnCodes ok
+test config-4.37 {DoObjConfig - invalid color} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .foo -color xxx
+} -cleanup {
+ killTables
+} -returnCodes error -result {unknown color name "xxx"}
+test config-4.38 {DoObjConfig - color internal value} -constraints {
+ testobjconfig
+} -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig internal .foo -color purple
+ .foo cget -color
+} -cleanup {
+ killTables
+} -result {purple}
+
+test config-4.39 {DoObjConfig - null color} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -color {}
+} -cleanup {
+ killTables
+} -returnCodes ok -result {.foo}
+test config-4.40 {DoObjConfig - null color} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -color {}
+ .foo cget -color
+} -cleanup {
+ killTables
+} -returnCodes ok -result {}
+test config-4.41 {DoObjConfig - null color} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -color {}
+ .foo cget -color
+ rename .foo {}
+} -cleanup {
+ killTables
+} -returnCodes ok
+test config-4.42 {DoObjConfig - getting rid of old color} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .foo -color #333333
+ .foo configure -color #444444
+} -cleanup {
+ killTables
+} -returnCodes ok -result {32}
+test config-4.43 {DoObjConfig - getting rid of old color} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .foo -color #333333
+ .foo configure -color #444444
+ .foo cget -color
+} -cleanup {
+ killTables
+} -returnCodes ok -result {#444444}
+test config-4.44 {DoObjConfig - getting rid of old color} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .foo -color #333333
+ .foo configure -color #444444
+ .foo cget -color
+ rename .foo {}
+} -cleanup {
+ killTables
+} -returnCodes ok
+
+test config-4.45 {DoObjConfig - font} -constraints testobjconfig -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig alltypes .foo -font {Helvetica 72}
+} -cleanup {
+ killTables
+} -returnCodes ok -result {.foo}
+test config-4.46 {DoObjConfig - font} -constraints testobjconfig -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig alltypes .foo -font {Helvetica 72}
+ .foo cget -font
+} -cleanup {
+ killTables
+} -returnCodes ok -result {Helvetica 72}
+test config-4.47 {DoObjConfig - new font} -constraints testobjconfig -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig alltypes .foo -font {Courier 12}
+ .foo configure -font {Helvetica 72}
+} -cleanup {
+ killTables
+} -returnCodes ok -result {64}
+test config-4.48 {DoObjConfig - new font} -constraints testobjconfig -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig alltypes .foo -font {Courier 12}
+ .foo configure -font {Helvetica 72}
+ .foo cget -font
+} -cleanup {
+ killTables
+} -returnCodes ok -result {Helvetica 72}
+test config-4.49 {DoObjConfig - invalid font} -constraints {
+ testobjconfig
+} -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig alltypes .foo -font {Helvetica 12 foo}
+} -cleanup {
+ killTables
+} -returnCodes error -result {unknown font style "foo"}
+test config-4.50 {DoObjConfig - null font} -constraints testobjconfig -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig alltypes .foo -font {}
+} -cleanup {
+ killTables
+} -returnCodes ok -result {.foo}
+test config-4.51 {DoObjConfig - null font} -constraints testobjconfig -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig alltypes .foo -font {}
+ .foo cget -font
+} -cleanup {
+ killTables
+} -returnCodes ok -result {}
+test config-4.52 {DoObjConfig - font internal value} -constraints {
+ testobjconfig
+} -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig internal .foo -font {Times 16}
+ .foo cget -font
+} -cleanup {
+ killTables
+} -result {Times 16}
+
+test config-4.53 {DoObjConfig - bitmap} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -bitmap gray75
+} -cleanup {
+ killTables
+} -returnCodes ok -result {.foo}
+test config-4.54 {DoObjConfig - bitmap} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -bitmap gray75
+ .foo cget -bitmap
+} -cleanup {
+ killTables
+} -returnCodes ok -result {gray75}
+test config-4.55 {DoObjConfig - new bitmap} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -bitmap gray75
+ .foo configure -bitmap gray50
+} -cleanup {
+ killTables
+} -returnCodes ok -result {128}
+test config-4.56 {DoObjConfig - new bitmap} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -bitmap gray75
+ .foo configure -bitmap gray50
+ .foo cget -bitmap
+} -cleanup {
+ killTables
+} -returnCodes ok -result {gray50}
+test config-4.57 {DoObjConfig - invalid bitmap} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .foo -bitmap foobar
+} -cleanup {
+ killTables
+} -returnCodes error -result {bitmap "foobar" not defined}
+test config-4.58 {DoObjConfig - null bitmap} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -bitmap {}
+} -cleanup {
+ killTables
+} -returnCodes ok -result {.foo}
+test config-4.59 {DoObjConfig - null bitmap} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -bitmap {}
+ .foo cget -bitmap
+} -cleanup {
+ killTables
+} -returnCodes ok -result {}
+test config-4.60 {DoObjConfig - bitmap internal value} -constraints {
+ testobjconfig
+} -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig internal .foo -bitmap gray25
+ .foo cget -bitmap
+} -cleanup {
+ killTables
+} -result {gray25}
+
+test config-4.61 {DoObjConfig - border} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -border green
+} -cleanup {
+ killTables
+} -returnCodes ok -result {.foo}
+test config-4.62 {DoObjConfig - border} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -border green
+ .foo cget -border
+} -cleanup {
+ killTables
+} -returnCodes ok -result {green}
+test config-4.63 {DoObjConfig - invalid border} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .foo -border xxx
+} -cleanup {
+ killTables
+} -returnCodes error -result {unknown color name "xxx"}
+test config-4.64 {DoObjConfig - null border} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -border {}
+} -cleanup {
+ killTables
+} -returnCodes ok -result {.foo}
+test config-4.65 {DoObjConfig - null border} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -border {}
+ .foo cget -border
+} -cleanup {
+ killTables
+} -returnCodes ok -result {}
+test config-4.66 {DoObjConfig - border internal value} -constraints {
+ testobjconfig
+} -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig internal .foo -border #123456
+ .foo cget -border
+} -cleanup {
+ killTables
+} -result {#123456}
+test config-4.67 {DoObjConfig - getting rid of old border} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .foo -border #333333
+ .foo configure -border #444444
+} -cleanup {
+ killTables
+} -returnCodes ok -result {256}
+test config-4.68 {DoObjConfig - getting rid of old border} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .foo -border #333333
+ .foo configure -border #444444
+ .foo cget -border
+} -cleanup {
+ killTables
+} -returnCodes ok -result {#444444}
+
+test config-4.69 {DoObjConfig - relief} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -relief flat
+} -cleanup {
+ killTables
+} -returnCodes ok -result {.foo}
+test config-4.70 {DoObjConfig - relief} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -relief flat
+ .foo cget -relief
+} -cleanup {
+ killTables
+} -returnCodes ok -result {flat}
+test config-4.71 {DoObjConfig - invalid relief} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .foo -relief foo
+} -cleanup {
+ killTables
+} -returnCodes error -result {bad relief "foo": must be flat, groove, raised, ridge, solid, or sunken}
+test config-4.72 {DoObjConfig - relief internal value} -constraints testobjconfig -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig internal .foo -relief ridge
+ .foo cget -relief
+} -cleanup {
+ killTables
+} -result {ridge}
+test config-4.73 {DoObjConfig - new relief} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -relief raised
+ .foo configure -relief flat
+} -cleanup {
+ killTables
+} -returnCodes ok -result {512}
+test config-4.74 {DoObjConfig - new relief} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -relief raised
+ .foo configure -relief flat
+ .foo cget -relief
+} -cleanup {
+ killTables
+} -returnCodes ok -result {flat}
+
+test config-4.75 {DoObjConfig - cursor} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -cursor arrow
+} -cleanup {
+ killTables
+} -returnCodes ok -result {.foo}
+test config-4.76 {DoObjConfig - cursor} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -cursor arrow
+ .foo cget -cursor
+} -cleanup {
+ killTables
+} -returnCodes ok -result {arrow}
+test config-4.77 {DoObjConfig - invalid cursor} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -cursor foo
+} -cleanup {
+ killTables
+} -returnCodes error -result {bad cursor spec "foo"}
+test config-4.78 {DoObjConfig - null cursor} -constraints testobjconfig -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig alltypes .foo -cursor {}
+} -cleanup {
+ killTables
+} -returnCodes ok -result {.foo}
+test config-4.79 {DoObjConfig - null cursor} -constraints testobjconfig -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig alltypes .foo -cursor {}
+ .foo cget -cursor
+} -cleanup {
+ killTables
+} -returnCodes ok -result {}
+test config-4.80 {DoObjConfig - new cursor} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -cursor xterm
+ .foo configure -cursor arrow
+} -cleanup {
+ killTables
+} -returnCodes ok -result {1024}
+test config-4.81 {DoObjConfig - new cursor} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -cursor xterm
+ .foo configure -cursor arrow
+ .foo cget -cursor
+} -cleanup {
+ killTables
+} -returnCodes ok -result {arrow}
+test config-4.82 {DoObjConfig - cursor internal value} -constraints {
+ testobjconfig
+} -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig internal .foo -cursor watch
+ .foo cget -cursor
+} -cleanup {
+ killTables
+} -result {watch}
+
+test config-4.83 {DoObjConfig - justify} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -justify center
+} -cleanup {
+ killTables
+} -returnCodes ok -result {.foo}
+test config-4.84 {DoObjConfig - justify} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -justify center
+ .foo cget -justify
+} -cleanup {
+ killTables
+} -returnCodes ok -result {center}
+test config-4.85 {DoObjConfig - invalid justify} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -justify foo
+} -cleanup {
+ killTables
+} -returnCodes error -result {bad justification "foo": must be left, right, or center}
+test config-4.86 {DoObjConfig - new justify} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -justify left
+ .foo configure -justify right
+} -cleanup {
+ killTables
+} -returnCodes ok -result {2048}
+test config-4.87 {DoObjConfig - new justify} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -justify left
+ .foo configure -justify right
+ .foo cget -justify
+} -cleanup {
+ killTables
+} -returnCodes ok -result {right}
+test config-4.88 {DoObjConfig - justify internal value} -constraints {
+ testobjconfig
+} -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig internal .foo -justify center
+ .foo cget -justify
+} -cleanup {
+ killTables
+} -result {center}
+
+test config-4.89 {DoObjConfig - anchor} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -anchor center
+} -cleanup {
+ killTables
+} -returnCodes ok -result {.foo}
+test config-4.90 {DoObjConfig - anchor} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -anchor center
+ .foo cget -anchor
+} -cleanup {
+ killTables
+} -returnCodes ok -result {center}
+test config-4.91 {DoObjConfig - invalid anchor} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -anchor foo
+} -cleanup {
+ killTables
+} -returnCodes error -result {bad anchor "foo": must be n, ne, e, se, s, sw, w, nw, or center}
+test config-4.92 {DoObjConfig - new anchor} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -anchor e
+ .foo configure -anchor n
+} -cleanup {
+ killTables
+} -returnCodes ok -result {4096}
+test config-4.93 {DoObjConfig - new anchor} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -anchor e
+ .foo configure -anchor n
+ .foo cget -anchor
+} -cleanup {
+ killTables
+} -returnCodes ok -result {n}
+test config-4.94 {DoObjConfig - anchor internal value} -constraints {
+ testobjconfig
+} -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig internal .foo -anchor sw
+ .foo cget -anchor
+} -cleanup {
+ killTables
+} -result {sw}
+test config-4.95 {DoObjConfig - pixel} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -pixel 42
+} -cleanup {
+ killTables
+} -returnCodes ok -result {.foo}
+test config-4.96 {DoObjConfig - pixel} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -pixel 42
+ .foo cget -pixel
+} -cleanup {
+ killTables
+} -returnCodes ok -result {42}
+test config-4.97 {DoObjConfig - invalid pixel} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -pixel foo
+} -cleanup {
+ killTables
+} -returnCodes error -result {bad screen distance "foo"}
+test config-4.98 {DoObjConfig - new pixel} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -pixel 42m
+ .foo configure -pixel 3c
+} -cleanup {
+ killTables
+} -returnCodes ok -result {8192}
+test config-4.99 {DoObjConfig - new pixel} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -pixel 42m
+ .foo configure -pixel 3c
+ .foo cget -pixel
+} -cleanup {
+ killTables
+} -returnCodes ok -result {3c}
+test config-4.100 {DoObjConfig - pixel internal value} -constraints {
+ testobjconfig
+} -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig internal .foo -pixel [winfo screenmmwidth .]m
+ set screenW [winfo screenwidth .]
+ set result [.foo cget -pixel]
+ expr {$screenW eq $result}
+} -cleanup {
+ killTables
+} -result {1}
+
+test config-4.101 {DoObjConfig - window} -constraints testobjconfig -body {
+ toplevel .bar
+ testobjconfig twowindows .foo -window .bar
+} -cleanup {
+ killTables
+} -returnCodes ok -result {.foo}
+test config-4.102 {DoObjConfig - window} -constraints testobjconfig -body {
+ toplevel .bar
+ testobjconfig twowindows .foo -window .bar
+ .foo cget -window
+} -cleanup {
+ killTables
+} -returnCodes ok -result {.bar}
+test config-4.103 {DoObjConfig - invalid window} -constraints testobjconfig -body {
+ toplevel .bar
+ testobjconfig twowindows .foo -window foo
+} -cleanup {
+ killTables
+} -returnCodes error -result {bad window path name "foo"}
+test config-4.104 {DoObjConfig - null window} -constraints testobjconfig -body {
+ toplevel .bar
+ testobjconfig twowindows .foo -window {}
+} -cleanup {
+ killTables
+} -returnCodes ok -result {.foo}
+test config-4.105 {DoObjConfig - null window} -constraints testobjconfig -body {
+ toplevel .bar
+ testobjconfig twowindows .foo -window {}
+ .foo cget -window
+} -cleanup {
+ killTables
+} -returnCodes ok -result {}
+test config-4.106 {DoObjConfig - new window} -constraints testobjconfig -body {
+ toplevel .bar
+ toplevel .blamph
+ testobjconfig twowindows .foo -window .bar
+ .foo configure -window .blamph
+} -cleanup {
+ killTables
+} -returnCodes ok -result {0}
+test config-4.107 {DoObjConfig - new window} -constraints testobjconfig -body {
+ toplevel .bar
+ toplevel .blamph
+ testobjconfig twowindows .foo -window .bar
+ .foo configure -window .blamph
+ .foo cget -window
+} -cleanup {
+ killTables
+} -returnCodes ok -result {.blamph}
+test config-4.108 {DoObjConfig - window internal value} -constraints {
+ testobjconfig
+} -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig internal .foo -window .
+ .foo cget -window
+} -cleanup {
+ killTables
+} -result {.}
+
+test config-4.109 {DoObjConfig - releasing old values} -constraints {
+ testobjconfig
+} -setup {
+ catch {rename .foo {}}
+} -body {
+ # This test doesn't generate a useful value to check; if an
+ # error occurs, it will be detected only by memory checking software
+ # such as Purify or Tcl's built-in checker.
+
+ testobjconfig alltypes .foo -string {Test string} -color yellow \
+ -font {Courier 18} -bitmap questhead -border green -cursor cross \
+ -custom foobar
+ .foo configure -string {new string} -color brown \
+ -font {Times 8} -bitmap gray75 -border pink -cursor watch \
+ -custom barbaz
+ concat {}
+} -cleanup {
+ killTables
+} -result {}
+test config-4.110 {DoObjConfig - releasing old values} -constraints {
+ testobjconfig
+} -setup {
+ catch {rename .foo {}}
+} -body {
+ # This test doesn't generate a useful value to check; if an
+ # error occurs, it will be detected only by memory checking software
+ # such as Purify or Tcl's built-in checker.
+
+ testobjconfig internal .foo -string {Test string} -color yellow \
+ -font {Courier 18} -bitmap questhead -border green -cursor cross \
+ -custom foobar
+ .foo configure -string {new string} -color brown \
+ -font {Times 8} -bitmap gray75 -border pink -cursor watch \
+ -custom barbaz
+ concat {}
+} -cleanup {
+ killTables
+} -result {}
+
+test config-4.111 {DoObjConfig - custom} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -custom test
+} -cleanup {
+ killTables
+} -returnCodes ok -result {.foo}
+test config-4.112 {DoObjConfig - custom} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -custom test
+ .foo cget -custom
+} -cleanup {
+ killTables
+} -returnCodes ok -result {TEST}
+test config-4.113 {DoObjConfig - null custom} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -custom {}
+} -cleanup {
+ killTables
+} -returnCodes ok -result {.foo}
+test config-4.114 {DoObjConfig - null custom} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo -custom {}
+ .foo cget -custom
+} -cleanup {
+ killTables
+} -returnCodes ok -result {}
+test config-4.115 {DoObjConfig - custom internal value} -constraints {
+ testobjconfig
+} -setup {
+ catch {rename .foo {}}
+} -body {
+ testobjconfig internal .foo -custom "this is a test"
+ .foo cget -custom
+} -cleanup {
+ killTables
+} -result {THIS IS A TEST}
+
+
+test config-5.1 {ObjectIsEmpty - object is already string} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .foo -color [format ""]
+ .foo cget -color
+} -cleanup {
+ killTables
+} -result {}
+test config-5.2 {ObjectIsEmpty - object is already string} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .foo -color [format " "]
+} -cleanup {
+ killTables
+} -returnCodes error -result {unknown color name " "}
+test config-5.3 {ObjectIsEmpty - must convert back to string} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .foo -color [list]
+ .foo cget -color
+} -cleanup {
+ killTables
+} -result {}
+
+
+test config-6.1 {GetOptionFromObj - cached answer} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig chain2 .a
+ list [.a cget -three] [.a cget -three]
+} -cleanup {
+ killTables
+} -result {three three}
+test config-6.2 {GetOptionFromObj - exact match} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig chain2 .a
+ .a cget -one
+} -cleanup {
+ killTables
+} -result {one}
+test config-6.3 {GetOptionFromObj - abbreviation} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig chain2 .a
+ .a cget -fo
+} -cleanup {
+ killTables
+} -result {four}
+test config-6.4 {GetOptionFromObj - ambiguous abbreviation} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig chain2 .a
+ .a cget -on
+} -cleanup {
+ killTables
+} -cleanup {
+ killTables
+} -returnCodes error -result {unknown option "-on"}
+test config-6.5 {GetOptionFromObj - duplicate options in different tables} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig chain2 .a
+ .a cget -tw
+} -cleanup {
+ killTables
+} -result {two and a half}
+test config-6.6 {GetOptionFromObj - synonym} -constraints testobjconfig -body {
+ testobjconfig alltypes .b
+ .b cget -synonym
+} -cleanup {
+ killTables
+} -result {red}
+
+
+if {[testConstraint testobjconfig]} {
+ testobjconfig alltypes .a
+}
+test config-7.1 {Tk_SetOptions - basics} -constraints testobjconfig -body {
+ .a configure -color green -rel sunken
+ list [.a cget -color] [.a cget -relief]
+} -result {green sunken}
+test config-7.2 {Tk_SetOptions - bogus option name} -constraints {
+ testobjconfig
+} -body {
+ .a configure -bogus
+} -returnCodes error -result {unknown option "-bogus"}
+test config-7.3 {Tk_SetOptions - synonym} -constraints testobjconfig -body {
+ .a configure -synonym blue
+ .a cget -color
+} -result {blue}
+test config-7.4 {Tk_SetOptions - missing value} -constraints {
+ testobjconfig
+} -body {
+ .a configure -color green -relief
+} -returnCodes error -result {value for "-relief" missing}
+test config-7.5 {Tk_SetOptions - missing value} -constraints {
+ testobjconfig
+} -body {
+ catch {.a configure -color green -relief}
+ .a cget -color
+} -result {green}
+test config-7.6 {Tk_SetOptions - saving old values} -constraints {
+ testobjconfig
+} -body {
+ .a configure -color red -int 7 -relief raised -double 3.14159
+ .a csave -color green -int 432 -relief sunken -double 2.0 -color bogus
+} -returnCodes error -result {unknown color name "bogus"}
+test config-7.7 {Tk_SetOptions - saving old values} -constraints {
+ testobjconfig
+} -body {
+ .a configure -color red -int 7 -relief raised -double 3.14159
+ catch {.a csave -color green -int 432 -relief sunken -double 2.0 -color bogus}
+ list [.a cget -color] [.a cget -int] [.a cget -relief] [.a cget -double]
+} -result {red 7 raised 3.14159}
+
+test config-7.8 {Tk_SetOptions - error in DoObjConfig call} -constraints {
+ testobjconfig
+} -body {
+ .a configure -color bogus
+} -returnCodes error -result {unknown color name "bogus"}
+test config-7.9 {Tk_SetOptions - error in DoObjConfig call} -constraints {
+ testobjconfig
+} -body {
+ catch {.a configure -color bogus}
+ return $errorInfo
+} -result {unknown color name "bogus"
+ (processing "-color" option)
+ invoked from within
+".a configure -color bogus"}
+
+test config-7.10 {Tk_SetOptions - synonym name in error message} -constraints {
+ testobjconfig
+} -body {
+ .a configure -synonym bogus
+} -returnCodes error -result {unknown color name "bogus"}
+test config-7.11 {Tk_SetOptions - synonym name in error message} -constraints {
+ testobjconfig
+} -body {
+ catch {.a configure -synonym bogus}
+ return $errorInfo
+} -result {unknown color name "bogus"
+ (processing "-synonym" option)
+ invoked from within
+".a configure -synonym bogus"}
+test config-7.12 {Tk_SetOptions - returning mask} -constraints testobjconfig -body {
+ format %x [.a configure -color red -int 7 -relief raised -double 3.14159]
+} -result {226}
+test config-7.13 {Tk_SetOptions - error in DoObjConfig with custom option} -constraints {
+ testobjconfig
+} -body {
+ .a configure -custom bad
+} -returnCodes error -result {expected good value, got "BAD"}
+test config-7.14 {Tk_SetOptions - error in DoObjConfig with custom option} -constraints {
+ testobjconfig
+} -body {
+ catch {.a configure -custom bad}
+ return $errorInfo
+} -result {expected good value, got "BAD"
+ (processing "-custom" option)
+ invoked from within
+".a configure -custom bad"}
+if {[testConstraint testobjconfig]} {
+ killTables
+}
+
+
+test config-8.1 {Tk_RestoreSavedOptions - restore in proper order} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .a
+ .a csave -color green -color black -color blue \
+ -color #ffff00 -color #ff00ff -color bogus \
+} -cleanup {
+ killTables
+} -returnCodes error -result {unknown color name "bogus"}
+test config-8.2 {Tk_RestoreSavedOptions - restore in proper order} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .a
+ catch {.a csave -color green -color black -color blue \
+ -color #ffff00 -color #ff00ff -color bogus}
+ .a cget -color
+} -cleanup {
+ killTables
+} -result {red}
+test config-8.3 {Tk_RestoreSavedOptions - freeing object memory} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .a
+ .a csave -color green -color black -color blue -color #ffff00 -color #ff00ff
+} -cleanup {
+ killTables
+} -result {32}
+test config-8.4 {Tk_RestoreSavedOptions - boolean internal form} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig internal .a
+ .a csave -boolean 0 -color bogus
+} -cleanup {
+ killTables
+} -returnCodes error -match glob -result *
+test config-8.5 {Tk_RestoreSavedOptions - boolean internal form} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig internal .a
+ catch {.a csave -boolean 0 -color bogus}
+ .a cget -boolean
+} -cleanup {
+ killTables
+} -result {1}
+test config-8.6 {Tk_RestoreSavedOptions - integer internal form} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig internal .a
+ .a csave -integer 24 -color bogus
+} -cleanup {
+ killTables
+} -returnCodes error -match glob -result *
+test config-8.7 {Tk_RestoreSavedOptions - integer internal form} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig internal .a
+ catch {.a csave -integer 24 -color bogus}
+ .a cget -integer
+} -cleanup {
+ killTables
+} -result {148962237}
+test config-8.8 {Tk_RestoreSavedOptions - double internal form} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig internal .a
+ catch {.a csave -double 62.4 -color bogus}
+ .a cget -double
+} -cleanup {
+ killTables
+} -result {3.14159}
+test config-8.9 {Tk_RestoreSavedOptions - string internal form} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig internal .a
+ catch {.a csave -string "A long string" -color bogus}
+ .a cget -string
+} -cleanup {
+ killTables
+} -result {foo}
+test config-8.10 {Tk_RestoreSavedOptions - string table internal form} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig internal .a
+ catch {.a csave -stringtable three -color bogus}
+ .a cget -stringtable
+} -cleanup {
+ killTables
+} -result {one}
+test config-8.11 {Tk_RestoreSavedOptions - color internal form} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig internal .a
+ catch {.a csave -color green -color bogus}
+ .a cget -color
+} -cleanup {
+ killTables
+} -result {red}
+test config-8.12 {Tk_RestoreSavedOptions - font internal form} -constraints {
+ testobjconfig nonPortable
+} -body {
+ testobjconfig internal .a
+ catch {.a csave -font {Times 12} -color bogus}
+ .a cget -font
+} -cleanup {
+ killTables
+} -result {Helvetica 12}
+test config-8.13 {Tk_RestoreSavedOptions - bitmap internal form} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig internal .a
+ catch {.a csave -bitmap questhead -color bogus}
+ .a cget -bitmap
+} -cleanup {
+ killTables
+} -result {gray50}
+test config-8.14 {Tk_RestoreSavedOptions - border internal form} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig internal .a
+ catch {.a csave -border brown -color bogus}
+ .a cget -border
+} -cleanup {
+ killTables
+} -result {blue}
+test config-8.15 {Tk_RestoreSavedOptions - relief internal form} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig internal .a
+ catch {.a csave -relief sunken -color bogus}
+ .a cget -relief
+} -cleanup {
+ killTables
+} -result {raised}
+test config-8.16 {Tk_RestoreSavedOptions - cursor internal form} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig internal .a
+ catch {.a csave -cursor watch -color bogus}
+ .a cget -cursor
+} -cleanup {
+ killTables
+} -result {xterm}
+test config-8.17 {Tk_RestoreSavedOptions - justify internal form} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig internal .a
+ catch {.a csave -justify right -color bogus}
+ .a cget -justify
+} -cleanup {
+ killTables
+} -result {left}
+test config-8.18 {Tk_RestoreSavedOptions - anchor internal form} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig internal .a
+ catch {.a csave -anchor center -color bogus}
+ .a cget -anchor
+} -cleanup {
+ killTables
+} -result {n}
+test config-8.19 {Tk_RestoreSavedOptions - window internal form} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig internal .a -window .a
+ catch {.a csave -window .a -color bogus}
+ .a cget -window
+} -cleanup {
+ killTables
+} -result {.a}
+test config-8.20 {Tk_RestoreSavedOptions - custom internal form} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig internal .a -custom "foobar"
+ catch {.a csave -custom "barbaz" -color bogus}
+ .a cget -custom
+} -cleanup {
+ killTables
+} -result {FOOBAR}
+
+# Most of the tests below will cause memory leakage if there is a
+# problem. This may not be evident unless the tests are run in
+# conjunction with a memory usage analyzer such as Purify.
+
+test config-9.1 {Tk_FreeConfigOptions/FreeResources - string internal form} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig internal .foo
+ .foo configure -string "two words"
+ destroy .foo
+} -result {}
+test config-9.2 {Tk_FreeConfigOptions/FreeResources - color internal form} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig internal .foo
+ .foo configure -color yellow
+ destroy .foo
+} -result {}
+test config-9.3 {Tk_FreeConfigOptions/FreeResources - color} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .foo
+ .foo configure -color [format blue]
+ destroy .foo
+} -result {}
+test config-9.4 {Tk_FreeConfigOptions/FreeResources - font internal form} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig internal .foo
+ .foo configure -font {Courier 20}
+ destroy .foo
+} -result {}
+test config-9.5 {Tk_FreeConfigOptions/FreeResources - font} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .foo
+ .foo configure -font [format {Courier 24}]
+ destroy .foo
+} -result {}
+test config-9.6 {Tk_FreeConfigOptions/FreeResources - bitmap internal form} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig internal .foo
+ .foo configure -bitmap gray75
+ destroy .foo
+} -result {}
+test config-9.7 {Tk_FreeConfigOptions/FreeResources - bitmap} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .foo
+ .foo configure -bitmap [format gray75]
+ destroy .foo
+} -result {}
+test config-9.8 {Tk_FreeConfigOptions/FreeResources - border internal form} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig internal .foo
+ .foo configure -border orange
+ destroy .foo
+} -result {}
+test config-9.9 {Tk_FreeConfigOptions/FreeResources - border} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .foo
+ .foo configure -border [format blue]
+ destroy .foo
+} -result {}
+test config-9.10 {Tk_FreeConfigOptions/FreeResources - cursor internal form} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig internal .foo
+ .foo configure -cursor cross
+ destroy .foo
+} -result {}
+test config-9.11 {Tk_FreeConfigOptions/FreeResources - cursor} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .foo
+ .foo configure -cursor [format watch]
+ destroy .foo
+} -result {}
+test config-9.12 {Tk_FreeConfigOptions/FreeResources - not special} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .foo
+ .foo configure -integer [format 27]
+ destroy .foo
+} -result {}
+test config-9.13 {Tk_FreeConfigOptions/FreeResources - custom internal form} -constraints {
+ testobjconfig
+} -body {
+ catch {destroy .fpp}
+ testobjconfig internal .foo
+ .foo configure -custom "foobar"
+ destroy .foo
+} -result {}
+if {[testConstraint testobjconfig]} {
+ killTables
+}
+
+
+test config-10.1 {Tk_GetOptionInfo - one item} -constraints testobjconfig -body {
+ testobjconfig alltypes .foo
+ .foo configure -relief groove
+ .foo configure -relief
+} -cleanup {
+ destroy .foo
+} -result {-relief relief Relief raised groove}
+test config-10.2 {Tk_GetOptionInfo - one item, synonym} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .foo
+ .foo configure -color black
+ .foo configure -synonym
+} -cleanup {
+ destroy .foo
+} -result {-color color Color red black}
+test config-10.3 {Tk_GetOptionInfo - all items} -constraints {
+ testobjconfig
+} -body {
+ testobjconfig alltypes .foo -font {Helvetica 18} -integer 13563
+ .foo configure
+} -cleanup {
+ destroy .foo
+} -result {{-boolean boolean Boolean 1 1} {-integer integer Integer 7 13563} {-double double Double 3.14159 3.14159} {-string string String foo foo} {-stringtable StringTable stringTable one one} {-color color Color red red} {-font font Font {Helvetica 12} {Helvetica 18}} {-bitmap bitmap Bitmap gray50 gray50} {-border border Border blue blue} {-relief relief Relief raised raised} {-cursor cursor Cursor xterm xterm} {-justify {} {} left left} {-anchor anchor Anchor {} {}} {-pixel pixel Pixel 1 1} {-custom {} {} {} {}} {-synonym -color}}
+test config-10.4 {Tk_GetOptionInfo - chaining through tables} -constraints testobjconfig -body {
+ testobjconfig chain2 .foo -one asdf -three xyzzy
+ .foo configure
+} -cleanup {
+ destroy .foo
+} -result {{-three three Three three xyzzy} {-four four Four four four} {-two two Two {two and a half} {two and a half}} {-oneAgain oneAgain OneAgain {one again} {one again}} {-one one One one asdf} {-two two Two two {two and a half}}}
+if {[testConstraint testobjconfig]} {
+ killTables
+}
+
+
+if {[testConstraint testobjconfig]} {
+ testobjconfig alltypes .a
+}
+test config-11.1 {GetConfigList - synonym} -constraints testobjconfig -body {
+ lindex [.a configure] end
+} -result {-synonym -color}
+test config-11.2 {GetConfigList - null database names} -constraints {
+ testobjconfig
+} -body {
+ .a configure -justify
+} -result {-justify {} {} left left}
+test config-11.3 {GetConfigList - null default and current value} -constraints {
+ testobjconfig
+} -body {
+ .a configure -anchor
+} -result {-anchor anchor Anchor {} {}}
+if {[testConstraint testobjconfig]} {
+ killTables
+}
+
+
+if {[testConstraint testobjconfig]} {
+ testobjconfig internal .a
+}
+test config-12.1 {GetObjectForOption - boolean} -constraints testobjconfig -body {
+ .a configure -boolean 0
+ .a cget -boolean
+} -result {0}
+test config-12.2 {GetObjectForOption - integer} -constraints testobjconfig -body {
+ .a configure -integer 1247
+ .a cget -integer
+} -result {1247}
+test config-12.3 {GetObjectForOption - double} -constraints testobjconfig -body {
+ .a configure -double -88.82
+ .a cget -double
+} -result {-88.82}
+test config-12.4 {GetObjectForOption - string} -constraints testobjconfig -body {
+ .a configure -string "test value"
+ .a cget -string
+} -result {test value}
+test config-12.5 {GetObjectForOption - stringTable} -constraints {
+ testobjconfig
+} -body {
+ .a configure -stringtable "two"
+ .a cget -stringtable
+} -result {two}
+test config-12.6 {GetObjectForOption - color} -constraints testobjconfig -body {
+ .a configure -color "green"
+ .a cget -color
+} -result {green}
+test config-12.7 {GetObjectForOption - font} -constraints testobjconfig -body {
+ .a configure -font {Times 36}
+ .a cget -font
+} -result {Times 36}
+test config-12.8 {GetObjectForOption - bitmap} -constraints testobjconfig -body {
+ .a configure -bitmap "questhead"
+ .a cget -bitmap
+} -result {questhead}
+test config-12.9 {GetObjectForOption - border} -constraints testobjconfig -body {
+ .a configure -border #33217c
+ .a cget -border
+} -result {#33217c}
+test config-12.10 {GetObjectForOption - relief} -constraints {
+ testobjconfig
+} -body {
+ .a configure -relief groove
+ .a cget -relief
+} -result {groove}
+test config-12.11 {GetObjectForOption - cursor} -constraints {
+ testobjconfig
+} -body {
+ .a configure -cursor watch
+ .a cget -cursor
+} -result {watch}
+test config-12.12 {GetObjectForOption - justify} -constraints {
+ testobjconfig
+} -body {
+ .a configure -justify right
+ .a cget -justify
+} -result {right}
+test config-12.13 {GetObjectForOption - anchor} -constraints testobjconfig -body {
+ .a configure -anchor e
+ .a cget -anchor
+} -result {e}
+test config-12.14 {GetObjectForOption - pixels} -constraints testobjconfig -body {
+ .a configure -pixel 193.2
+ .a cget -pixel
+} -result {193}
+test config-12.15 {GetObjectForOption - window} -constraints testobjconfig -body {
+ .a configure -window .a
+ .a cget -window
+} -result {.a}
+test config-12.16 {GetObjectForOption -custom} -constraints testobjconfig -body {
+ .a configure -custom foobar
+ .a cget -custom
+} -result {FOOBAR}
+test config-12.17 {GetObjectForOption - null values} -constraints {
+ testobjconfig
+} -body {
+ .a configure -string {} -color {} -font {} -bitmap {} -border {} \
+ -cursor {} -window {} -custom {}
+ list [.a cget -string] [.a cget -color] [.a cget -font] \
+ [.a cget -bitmap] [.a cget -border] [.a cget -cursor] \
+ [.a cget -window] [.a cget -custom]
+} -result {{} {} {} {} {} {} {} {}}
+if {[testConstraint testobjconfig]} {
+ killTables
+}
+
+
+test config-13.1 {proper cleanup of options with widget destroy} -body {
+ button .w -cursor crosshair
+ destroy .w
+} -result {}
+test config-13.2 {proper cleanup of options with widget destroy} -body {
+ canvas .w -cursor crosshair
+ destroy .w
+} -result {}
+test config-13.3 {proper cleanup of options with widget destroy} -body {
+ entry .w -cursor crosshair
+ destroy .w
+} -result {}
+test config-13.4 {proper cleanup of options with widget destroy} -body {
+ frame .w -cursor crosshair
+ destroy .w
+} -result {}
+test config-13.5 {proper cleanup of options with widget destroy} -body {
+ listbox .w -cursor crosshair
+ destroy .w
+} -result {}
+test config-13.6 {proper cleanup of options with widget destroy} -body {
+ menu .w -cursor crosshair
+ destroy .w
+} -result {}
+test config-13.7 {proper cleanup of options with widget destroy} -body {
+ menubutton .w -cursor crosshair
+ destroy .w
+} -result {}
+test config-13.8 {proper cleanup of options with widget destroy} -body {
+ message .w -cursor crosshair
+ destroy .w
+} -result {}
+test config-13.9 {proper cleanup of options with widget destroy} -body {
+ scale .w -cursor crosshair
+ destroy .w
+} -result {}
+test config-13.10 {proper cleanup of options with widget destroy} -body {
+ scrollbar .w -cursor crosshair
+ destroy .w
+} -result {}
+test config-13.11 {proper cleanup of options with widget destroy} -body {
+ text .w -cursor crosshair
+ destroy .w
+} -result {}
+test config-13.12 {proper cleanup of options with widget destroy} -body {
+ radiobutton .w -cursor crosshair
+ destroy .w
+} -result {}
+test config-13.13 {proper cleanup of options with widget destroy} -body {
+ checkbutton .w -cursor crosshair
+ destroy .w
+} -result {}
+
+test config-14.1 {Tk_CreateOptionTable - use with namespace import} -setup {
+ namespace export -clear *
+} -body {
+ namespace eval ::foo [subst {
+ namespace import -force ::button
+ ::foo::button .a
+ ::foo::button .b
+ }
+ ]
+ destroy .a .b
+} -result {}
+test config-14.2 {Tk_CreateOptionTable - use with namespace import} -setup {
+ namespace export -clear *
+} -body {
+ namespace eval ::foo [subst {
+ namespace import -force ::canvas
+ ::foo::canvas .a
+ ::foo::canvas .b
+ }
+ ]
+ destroy .a .b
+} -result {}
+test config-14.3 {Tk_CreateOptionTable - use with namespace import} -setup {
+ namespace export -clear *
+} -body {
+ namespace eval ::foo [subst {
+ namespace import -force ::entry
+ ::foo::entry .a
+ ::foo::entry .b
+ }
+ ]
+ destroy .a .b
+} -result {}
+test config-14.4 {Tk_CreateOptionTable - use with namespace import} -setup {
+ namespace export -clear *
+} -body {
+ namespace eval ::foo [subst {
+ namespace import -force ::frame
+ ::foo::frame .a
+ ::foo::frame .b
+ }
+ ]
+ destroy .a .b
+} -result {}
+test config-14.5 {Tk_CreateOptionTable - use with namespace import} -setup {
+ namespace export -clear *
+} -body {
+ namespace eval ::foo [subst {
+ namespace import -force ::listbox
+ ::foo::listbox .a
+ ::foo::listbox .b
+ }
+ ]
+ destroy .a .b
+} -result {}
+test config-14.6 {Tk_CreateOptionTable - use with namespace import} -setup {
+ namespace export -clear *
+} -body {
+ namespace eval ::foo [subst {
+ namespace import -force ::menu
+ ::foo::menu .a
+ ::foo::menu .b
+ }
+ ]
+ destroy .a .b
+} -result {}
+test config-14.7 {Tk_CreateOptionTable - use with namespace import} -setup {
+ namespace export -clear *
+} -body {
+ namespace eval ::foo [subst {
+ namespace import -force ::menubutton
+ ::foo::menubutton .a
+ ::foo::menubutton .b
+ }
+ ]
+ destroy .a .b
+} -result {}
+test config-14.8 {Tk_CreateOptionTable - use with namespace import} -setup {
+ namespace export -clear *
+} -body {
+ namespace eval ::foo [subst {
+ namespace import -force ::message
+ ::foo::message .a
+ ::foo::message .b
+ }
+ ]
+ destroy .a .b
+} -result {}
+test config-14.9 {Tk_CreateOptionTable - use with namespace import} -setup {
+ namespace export -clear *
+} -body {
+ namespace eval ::foo [subst {
+ namespace import -force ::scale
+ ::foo::scale .a
+ ::foo::scale .b
+ }
+ ]
+ destroy .a .b
+} -result {}
+test config-14.10 {Tk_CreateOptionTable - use with namespace import} -setup {
+ namespace export -clear *
+} -body {
+ namespace eval ::foo [subst {
+ namespace import -force ::scrollbar
+ ::foo::scrollbar .a
+ ::foo::scrollbar .b
+ }
+ ]
+ destroy .a .b
+} -result {}
+test config-14.11 {Tk_CreateOptionTable - use with namespace import} -setup {
+ namespace export -clear *
+} -body {
+ namespace eval ::foo [subst {
+ namespace import -force ::spinbox
+ ::foo::spinbox .a
+ ::foo::spinbox .b
+ }
+ ]
+ destroy .a .b
+} -result {}
+test config-14.12 {Tk_CreateOptionTable - use with namespace import} -setup {
+ namespace export -clear *
+} -body {
+ namespace eval ::foo [subst {
+ namespace import -force ::text
+ ::foo::text .a
+ ::foo::text .b
+ }
+ ]
+ destroy .a .b
+} -result {}
+test config-14.13 {Tk_CreateOptionTable - use with namespace import} -setup {
+ namespace export -clear *
+} -body {
+ namespace eval ::foo [subst {
+ namespace import -force ::radiobutton
+ ::foo::radiobutton .a
+ ::foo::radiobutton .b
+ }
+ ]
+ destroy .a .b
+} -result {}
+test config-14.14 {Tk_CreateOptionTable - use with namespace import} -setup {
+ namespace export -clear *
+} -body {
+ namespace eval ::foo [subst {
+ namespace import -force ::checkbutton
+ ::foo::checkbutton .a
+ ::foo::checkbutton .b
+ }
+ ]
+ destroy .a .b
+} -result {}
+
+
+# cleanup
+deleteWindows
+if {[testConstraint testobjconfig]} {
+ killTables
+}
+cleanupTests
+return
+
+
+
+
+
+
+
+
diff --git a/tk8.6/tests/constraints.tcl b/tk8.6/tests/constraints.tcl
new file mode 100644
index 0000000..a87499d
--- /dev/null
+++ b/tk8.6/tests/constraints.tcl
@@ -0,0 +1,286 @@
+if {[namespace exists tk::test]} {
+ deleteWindows
+ wm geometry . {}
+ raise .
+ return
+}
+
+package require Tk 8.4
+tk appname tktest
+wm title . tktest
+# If the main window isn't already mapped (e.g. because the tests are
+# being run automatically) , specify a precise size for it so that the
+# user won't have to position it manually.
+
+if {![winfo ismapped .]} {
+ wm geometry . +0+0
+ update
+}
+
+package require tcltest 2.1
+
+namespace eval tk {
+ namespace eval test {
+
+ namespace export loadTkCommand
+ proc loadTkCommand {} {
+ set tklib {}
+ foreach pair [info loaded {}] {
+ foreach {lib pfx} $pair break
+ if {$pfx eq "Tk"} {
+ set tklib $lib
+ break
+ }
+ }
+ return [list load $tklib Tk]
+ }
+
+ namespace eval bg {
+ # Manage a background process.
+ # Replace with slave interp or thread?
+ namespace import ::tcltest::interpreter
+ namespace import ::tk::test::loadTkCommand
+ namespace export setup cleanup do
+
+ proc cleanup {} {
+ variable fd
+ # catch in case the background process has closed $fd
+ catch {puts $fd exit}
+ catch {close $fd}
+ set fd ""
+ }
+ proc setup args {
+ variable fd
+ if {[info exists fd] && [string length $fd]} {
+ cleanup
+ }
+ set fd [open "|[list [interpreter] \
+ -geometry +0+0 -name tktest] $args" r+]
+ puts $fd "puts foo; flush stdout"
+ flush $fd
+ if {[gets $fd data] < 0} {
+ error "unexpected EOF from \"[interpreter]\""
+ }
+ if {$data ne "foo"} {
+ error "unexpected output from\
+ background process: \"$data\""
+ }
+ puts $fd [loadTkCommand]
+ flush $fd
+ fileevent $fd readable [namespace code Ready]
+ }
+ proc Ready {} {
+ variable fd
+ variable Data
+ variable Done
+ set x [gets $fd]
+ if {[eof $fd]} {
+ fileevent $fd readable {}
+ set Done 1
+ } elseif {$x eq "**DONE**"} {
+ set Done 1
+ } else {
+ append Data $x
+ }
+ }
+ proc do {cmd {block 0}} {
+ variable fd
+ variable Data
+ variable Done
+ if {$block} {
+ fileevent $fd readable {}
+ }
+ puts $fd "[list catch $cmd msg]; update; puts \$msg;\
+ puts **DONE**; flush stdout"
+ flush $fd
+ set Data {}
+ if {$block} {
+ while {![eof $fd]} {
+ set line [gets $fd]
+ if {$line eq "**DONE**"} {
+ break
+ }
+ append Data $line
+ }
+ } else {
+ set Done 0
+ vwait [namespace which -variable Done]
+ }
+ return $Data
+ }
+ }
+
+ proc Export {internal as external} {
+ uplevel 1 [list namespace import $internal]
+ uplevel 1 [list rename [namespace tail $internal] $external]
+ uplevel 1 [list namespace export $external]
+ }
+ Export bg::setup as setupbg
+ Export bg::cleanup as cleanupbg
+ Export bg::do as dobg
+
+ namespace export deleteWindows
+ proc deleteWindows {} {
+ eval destroy [winfo children .]
+ }
+
+ namespace export fixfocus
+ proc fixfocus {} {
+ catch {destroy .focus}
+ toplevel .focus
+ wm geometry .focus +0+0
+ entry .focus.e
+ .focus.e insert 0 "fixfocus"
+ pack .focus.e
+ update
+ focus -force .focus.e
+ destroy .focus
+ }
+
+
+ namespace export imageInit imageFinish imageCleanup imageNames
+ variable ImageNames
+ proc imageInit {} {
+ variable ImageNames
+ if {![info exists ImageNames]} {
+ set ImageNames [lsort [image names]]
+ }
+ imageCleanup
+ if {[lsort [image names]] ne $ImageNames} {
+ return -code error "IMAGE NAMES mismatch: [image names] != $ImageNames"
+ }
+ }
+ proc imageFinish {} {
+ variable ImageNames
+ if {[lsort [image names]] ne $ImageNames} {
+ return -code error "images remaining: [image names] != $ImageNames"
+ }
+ imageCleanup
+ }
+ proc imageCleanup {} {
+ variable ImageNames
+ foreach img [image names] {
+ if {$img ni $ImageNames} {image delete $img}
+ }
+ }
+ proc imageNames {} {
+ variable ImageNames
+ set r {}
+ foreach img [image names] {
+ if {$img ni $ImageNames} {lappend r $img}
+ }
+ return $r
+ }
+
+ }
+}
+
+namespace import -force tk::test::*
+
+namespace import -force tcltest::testConstraint
+testConstraint notAqua [expr {[tk windowingsystem] ne "aqua"}]
+testConstraint aqua [expr {[tk windowingsystem] eq "aqua"}]
+testConstraint x11 [expr {[tk windowingsystem] eq "x11"}]
+testConstraint nonwin [expr {[tk windowingsystem] ne "win32"}]
+testConstraint aquaOrWin32 [expr {
+ ([tk windowingsystem] eq "win32") || [testConstraint aqua]
+}]
+testConstraint userInteraction 0
+testConstraint nonUnixUserInteraction [expr {
+ [testConstraint userInteraction] ||
+ ([testConstraint unix] && [testConstraint notAqua])
+}]
+testConstraint haveDISPLAY [info exists env(DISPLAY)]
+testConstraint altDisplay [info exists env(TK_ALT_DISPLAY)]
+testConstraint noExceed [expr {
+ ![testConstraint unix] || [catch {font actual "\{xyz"}]
+}]
+
+# constraints for testing facilities defined in the tktest executable...
+testConstraint testImageType [expr {[lsearch [image types] test] >= 0}]
+testConstraint testOldImageType [expr {[lsearch [image types] oldtest] >= 0}]
+testConstraint testbitmap [llength [info commands testbitmap]]
+testConstraint testborder [llength [info commands testborder]]
+testConstraint testcbind [llength [info commands testcbind]]
+testConstraint testclipboard [llength [info commands testclipboard]]
+testConstraint testcolor [llength [info commands testcolor]]
+testConstraint testcursor [llength [info commands testcursor]]
+testConstraint testembed [llength [info commands testembed]]
+testConstraint testfont [llength [info commands testfont]]
+testConstraint testmakeexist [llength [info commands testmakeexist]]
+testConstraint testmenubar [llength [info commands testmenubar]]
+testConstraint testmetrics [llength [info commands testmetrics]]
+testConstraint testobjconfig [llength [info commands testobjconfig]]
+testConstraint testsend [llength [info commands testsend]]
+testConstraint testtext [llength [info commands testtext]]
+testConstraint testwinevent [llength [info commands testwinevent]]
+testConstraint testwrapper [llength [info commands testwrapper]]
+
+# constraint to see what sort of fonts are available
+testConstraint fonts 1
+destroy .e
+entry .e -width 0 -font {Helvetica -12} -bd 1 -highlightthickness 1
+.e insert end a.bcd
+if {([winfo reqwidth .e] != 37) || ([winfo reqheight .e] != 20)} {
+ testConstraint fonts 0
+}
+destroy .e
+destroy .t
+text .t -width 80 -height 20 -font {Times -14} -bd 1
+pack .t
+.t insert end "This is\na dot."
+update
+set x [list [.t bbox 1.3] [.t bbox 2.5]]
+destroy .t
+if {![string match {{22 3 6 15} {31 18 [34] 15}} $x]} {
+ testConstraint fonts 0
+}
+testConstraint textfonts [expr {
+ [testConstraint fonts] || [tk windowingsystem] eq "win32"
+}]
+
+# constraints for the visuals available..
+testConstraint pseudocolor8 [expr {
+ ([catch {
+ toplevel .t -visual {pseudocolor 8} -colormap new
+ }] == 0) && ([winfo depth .t] == 8)
+}]
+destroy .t
+testConstraint haveTruecolor24 [expr {
+ [lsearch -exact [winfo visualsavailable .] {truecolor 24}] >= 0
+}]
+testConstraint haveGrayscale8 [expr {
+ [lsearch -exact [winfo visualsavailable .] {grayscale 8}] >= 0
+}]
+testConstraint defaultPseudocolor8 [expr {
+ ([winfo visual .] eq "pseudocolor") && ([winfo depth .] == 8)
+}]
+
+# constraint based on whether our display is secure
+setupbg
+set app [dobg {tk appname}]
+testConstraint secureserver 0
+if {[llength [info commands send]]} {
+ testConstraint secureserver 1
+ if {[catch {send $app set a 0} msg] == 1} {
+ if {[string match "X server insecure *" $msg]} {
+ testConstraint secureserver 0
+ }
+ }
+}
+cleanupbg
+
+eval tcltest::configure $argv
+namespace import -force tcltest::test
+namespace import -force tcltest::makeFile
+namespace import -force tcltest::removeFile
+namespace import -force tcltest::makeDirectory
+namespace import -force tcltest::removeDirectory
+namespace import -force tcltest::interpreter
+namespace import -force tcltest::testsDirectory
+namespace import -force tcltest::cleanupTests
+
+deleteWindows
+wm geometry . {}
+raise .
+
diff --git a/tk8.6/tests/corruptMangled.gif b/tk8.6/tests/corruptMangled.gif
new file mode 100644
index 0000000..9c1637c
--- /dev/null
+++ b/tk8.6/tests/corruptMangled.gif
Binary files differ
diff --git a/tk8.6/tests/corruptMangled4G.gif b/tk8.6/tests/corruptMangled4G.gif
new file mode 100644
index 0000000..7dfde0e
--- /dev/null
+++ b/tk8.6/tests/corruptMangled4G.gif
@@ -0,0 +1,2 @@
+GIF89aÂf3ÿÿ33ÿ3ÿ3ÿ33ÿÿÿÿ3ÿÿÿ!ù
+,!xºÜ-0Bw¤ïÚ¥µê×Jâ8Uæªkir/3Re7 ; \ No newline at end of file
diff --git a/tk8.6/tests/corruptTruncated.gif b/tk8.6/tests/corruptTruncated.gif
new file mode 100644
index 0000000..948305a
--- /dev/null
+++ b/tk8.6/tests/corruptTruncated.gif
Binary files differ
diff --git a/tk8.6/tests/cursor.test b/tk8.6/tests/cursor.test
new file mode 100644
index 0000000..172c982
--- /dev/null
+++ b/tk8.6/tests/cursor.test
@@ -0,0 +1,846 @@
+# This file is a Tcl script to test out the procedures in the file
+# tkCursor.c. It is organized in the standard white-box fashion for
+# Tcl tests.
+#
+# Copyright (c) 1998 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+
+
+# Tests 2.3 and 2.4 need a helper file with a very specific name and
+# controlled format.
+proc setWincur {wincurName} {
+ upvar $wincurName wincur
+ set wincur(data_octal) {
+ 000 000 002 000 001 000 040 040 000 000 007 000 007 000 060 001
+ 000 000 026 000 000 000 050 000 000 000 040 000 000 000 100 000
+ 000 000 001 000 001 000 000 000 000 000 000 000 000 000 000 000
+ 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
+ 000 000 377 377 377 000 000 000 000 000 000 000 000 000 000 000
+ 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
+ 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
+ 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
+ 000 000 000 000 000 000 000 000 000 000 160 016 000 000 170 036
+ 000 000 174 076 000 000 076 174 000 000 037 370 000 000 017 360
+ 000 000 007 340 000 000 007 340 000 000 017 360 000 000 037 370
+ 000 000 076 174 000 000 174 076 000 000 170 036 000 000 160 016
+ 000 000 000 000 000 000 377 377 377 377 377 377 377 377 377 377
+ 377 377 377 377 377 377 377 377 377 377 377 377 377 377 377 377
+ 377 377 377 377 377 377 377 377 377 377 377 377 377 377 377 377
+ 377 377 377 377 377 377 377 377 377 377 377 377 377 377 377 377
+ 377 377 377 377 377 377 017 360 377 377 007 340 377 377 003 300
+ 377 377 001 200 377 377 200 001 377 377 300 003 377 377 340 007
+ 377 377 360 017 377 377 360 017 377 377 340 007 377 377 300 003
+ 377 377 200 001 377 377 001 200 377 377 003 300 377 377 007 340
+ 377 377 017 360 377 377
+ }
+ set wincur(data_binary) {}
+ foreach wincur(num) $wincur(data_octal) {
+ append wincur(data_binary) [binary format c [scan $wincur(num) %o]]
+ }
+ set wincur(dir) [makeDirectory {dir with spaces}]
+ set wincur(file) [makeFile $wincur(data_binary) "test file.cur" $wincur(dir)]
+}
+
+
+test cursor-1.1 {Tk_AllocCursorFromObj - converting internal reps} -constraints {
+ testcursor
+} -body {
+ set x watch
+ lindex $x 0
+ button .b -cursor $x
+ lindex $x 0
+ testcursor watch
+} -cleanup {
+ destroy .b
+} -result {{1 0}}
+test cursor-1.2 {Tk_AllocCursorFromObj - discard stale cursor} -constraints {
+ testcursor
+} -body {
+ set x watch
+ set result {}
+ button .b1 -cursor $x
+ destroy .b1
+ lappend result [testcursor watch]
+ button .b2 -cursor $x
+ lappend result [testcursor watch]
+} -cleanup {
+ destroy .b2
+} -result {{} {{1 1}}}
+test cursor-1.3 {Tk_AllocCursorFromObj - reuse existing cursor} -constraints {
+ testcursor
+} -body {
+ set x watch
+ set result {}
+ button .b1 -cursor $x
+ lappend result [testcursor watch]
+ button .b2 -cursor $x
+ pack .b1 .b2 -side top
+ lappend result [testcursor watch]
+} -cleanup {
+ destroy .b1 .b2
+} -result {{{1 1}} {{2 1}}}
+
+test cursor-2.1 {Tk_GetCursor procedure} -body {
+ button .b -cursor bad_name
+} -cleanup {
+ destroy .b
+} -returnCodes error -result {bad cursor spec "bad_name"}
+test cursor-2.2 {Tk_GetCursor procedure} -body {
+ button .b -cursor @xyzzy
+} -cleanup {
+ destroy .b
+} -returnCodes error -result {bad cursor spec "@xyzzy"}
+
+test cursor-2.3 {Tk_GetCursor procedure: cursor specs are lists} -constraints {
+ win
+} -setup {
+ unset -nocomplain wincur
+ set wincur(file) ""
+} -body {
+ setWincur wincur
+ button .b -cursor [list @$wincur(file)]
+} -cleanup {
+ destroy .b
+ removeDirectory $wincur(dir)
+ unset wincur
+} -result {.b}
+test cursor-2.4 {Tk_GetCursor procedure: cursor specs are lists} -constraints {
+ win
+} -setup {
+ unset -nocomplain wincur
+ set wincur(file) ""
+} -body {
+ setWincur wincur
+ button .b -cursor @[regsub -all {[][ \\{}""$#]} $wincur(file) {\\&}]
+} -cleanup {
+ destroy .b
+ removeDirectory $wincur(dir)
+ unset wincur
+} -result {.b}
+
+test cursor-3.1 {Tk_FreeCursorFromObj - reference counts} -constraints {
+ testcursor
+} -setup {
+ set x heart
+ set result {}
+} -body {
+ button .b1 -cursor $x
+ button .b3 -cursor $x
+ button .b2 -cursor $x
+ lappend result [testcursor heart]
+ destroy .b1
+ lappend result [testcursor heart]
+ destroy .b2
+ lappend result [testcursor heart]
+ destroy .b3
+ lappend result [testcursor heart]
+} -result {{{3 1}} {{2 1}} {{1 1}} {}}
+
+test cursor-4.1 {FreeCursorObjProc} -constraints {
+ testcursor
+} -setup {
+ proc copy {s} {return [string index $s 0][string range $s 1 end]}
+} -body {
+ set x [copy heart]
+ button .b -cursor $x
+ set y [copy heart]
+ .b configure -cursor $y
+ set z [copy heart]
+ .b configure -cursor $z
+ set result {}
+ lappend result [testcursor heart]
+ set x red
+ lappend result [testcursor heart]
+ set z 32
+ lappend result [testcursor heart]
+ destroy .b
+ lappend result [testcursor heart]
+ set y bogus
+ set result
+} -cleanup {
+ rename copy {}
+ destroy .b
+} -result {{{1 3}} {{1 2}} {{1 1}} {}}
+
+# -------------------------------------------------------------------------
+test cursor-5.1 {assert consistent cursor configuration command} -setup {
+ button .b
+} -body {
+ .b configure -cursor {watch red black}
+} -cleanup {
+ destroy .b
+} -result {}
+
+# -------------------------------------------------------------------------
+# Check for the standard set of cursors.
+test cursor-6.1 {check cursor-font cursor X_cursor} -setup {
+ button .b -text X_cursor
+} -body {
+ .b configure -cursor X_cursor
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.2 {check cursor-font cursor arrow} -setup {
+ button .b -text arrow
+} -body {
+ .b configure -cursor arrow
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.3 {check cursor-font cursor based_arrow_down} -setup {
+ button .b -text based_arrow_down
+} -body {
+ .b configure -cursor based_arrow_down
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.4 {check cursor-font cursor based_arrow_up} -setup {
+ button .b -text based_arrow_up
+} -body {
+ .b configure -cursor based_arrow_up
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.5 {check cursor-font cursor boat} -setup {
+ button .b -text boat
+} -body {
+ .b configure -cursor boat
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.6 {check cursor-font cursor bogosity} -setup {
+ button .b -text bogosity
+} -body {
+ .b configure -cursor bogosity
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.7 {check cursor-font cursor bottom_left_corner} -setup {
+ button .b -text bottom_left_corner
+} -body {
+ .b configure -cursor bottom_left_corner
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.8 {check cursor-font cursor bottom_right_corner} -setup {
+ button .b -text bottom_right_corner
+} -body {
+ .b configure -cursor bottom_right_corner
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.9 {check cursor-font cursor bottom_side} -setup {
+ button .b -text bottom_side
+} -body {
+ .b configure -cursor bottom_side
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.10 {check cursor-font cursor bottom_tee} -setup {
+ button .b -text bottom_tee
+} -body {
+ .b configure -cursor bottom_tee
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.11 {check cursor-font cursor box_spiral} -setup {
+ button .b -text box_spiral
+} -body {
+ .b configure -cursor box_spiral
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.12 {check cursor-font cursor center_ptr} -setup {
+ button .b -text center_ptr
+} -body {
+ .b configure -cursor center_ptr
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.13 {check cursor-font cursor circle} -setup {
+ button .b -text circle
+} -body {
+ .b configure -cursor circle
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.14 {check cursor-font cursor clock} -setup {
+ button .b -text clock
+} -body {
+ .b configure -cursor clock
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.15 {check cursor-font cursor coffee_mug} -setup {
+ button .b -text coffee_mug
+} -body {
+ .b configure -cursor coffee_mug
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.16 {check cursor-font cursor cross} -setup {
+ button .b -text cross
+} -body {
+ .b configure -cursor cross
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.17 {check cursor-font cursor cross_reverse} -setup {
+ button .b -text cross_reverse
+} -body {
+ .b configure -cursor cross_reverse
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.18 {check cursor-font cursor crosshair} -setup {
+ button .b -text crosshair
+} -body {
+ .b configure -cursor crosshair
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.19 {check cursor-font cursor diamond_cross} -setup {
+ button .b -text diamond_cross
+} -body {
+ .b configure -cursor diamond_cross
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.20 {check cursor-font cursor dot} -setup {
+ button .b -text dot
+} -body {
+ .b configure -cursor dot
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.21 {check cursor-font cursor dotbox} -setup {
+ button .b -text dotbox
+} -body {
+ .b configure -cursor dotbox
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.22 {check cursor-font cursor double_arrow} -setup {
+ button .b -text double_arrow
+} -body {
+ .b configure -cursor double_arrow
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.23 {check cursor-font cursor draft_large} -setup {
+ button .b -text draft_large
+} -body {
+ .b configure -cursor draft_large
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.24 {check cursor-font cursor draft_small} -setup {
+ button .b -text draft_small
+} -body {
+ .b configure -cursor draft_small
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.25 {check cursor-font cursor draped_box} -setup {
+ button .b -text draped_box
+} -body {
+ .b configure -cursor draped_box
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.26 {check cursor-font cursor exchange} -setup {
+ button .b -text exchange
+} -body {
+ .b configure -cursor exchange
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.27 {check cursor-font cursor fleur} -setup {
+ button .b -text fleur
+} -body {
+ .b configure -cursor fleur
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.28 {check cursor-font cursor gobbler} -setup {
+ button .b -text gobbler
+} -body {
+ .b configure -cursor gobbler
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.29 {check cursor-font cursor gumby} -setup {
+ button .b -text gumby
+} -body {
+ .b configure -cursor gumby
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.30 {check cursor-font cursor hand1} -setup {
+ button .b -text hand1
+} -body {
+ .b configure -cursor hand1
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.31 {check cursor-font cursor hand2} -setup {
+ button .b -text hand2
+} -body {
+ .b configure -cursor hand2
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.32 {check cursor-font cursor heart} -setup {
+ button .b -text heart
+} -body {
+ .b configure -cursor heart
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.33 {check cursor-font cursor icon} -setup {
+ button .b -text icon
+} -body {
+ .b configure -cursor icon
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.34 {check cursor-font cursor iron_cross} -setup {
+ button .b -text iron_cross
+} -body {
+ .b configure -cursor iron_cross
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.35 {check cursor-font cursor left_ptr} -setup {
+ button .b -text left_ptr
+} -body {
+ .b configure -cursor left_ptr
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.36 {check cursor-font cursor left_side} -setup {
+ button .b -text left_side
+} -body {
+ .b configure -cursor left_side
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.37 {check cursor-font cursor left_tee} -setup {
+ button .b -text left_tee
+} -body {
+ .b configure -cursor left_tee
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.38 {check cursor-font cursor leftbutton} -setup {
+ button .b -text leftbutton
+} -body {
+ .b configure -cursor leftbutton
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.39 {check cursor-font cursor ll_angle} -setup {
+ button .b -text ll_angle
+} -body {
+ .b configure -cursor ll_angle
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.40 {check cursor-font cursor lr_angle} -setup {
+ button .b -text lr_angle
+} -body {
+ .b configure -cursor lr_angle
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.41 {check cursor-font cursor man} -setup {
+ button .b -text man
+} -body {
+ .b configure -cursor man
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.42 {check cursor-font cursor middlebutton} -setup {
+ button .b -text middlebutton
+} -body {
+ .b configure -cursor middlebutton
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.43 {check cursor-font cursor mouse} -setup {
+ button .b -text mouse
+} -body {
+ .b configure -cursor mouse
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.44 {check cursor-font cursor pencil} -setup {
+ button .b -text pencil
+} -body {
+ .b configure -cursor pencil
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.45 {check cursor-font cursor pirate} -setup {
+ button .b -text pirate
+} -body {
+ .b configure -cursor pirate
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.46 {check cursor-font cursor plus} -setup {
+ button .b -text plus
+} -body {
+ .b configure -cursor plus
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.47 {check cursor-font cursor question_arrow} -setup {
+ button .b -text question_arrow
+} -body {
+ .b configure -cursor question_arrow
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.48 {check cursor-font cursor right_ptr} -setup {
+ button .b -text right_ptr
+} -body {
+ .b configure -cursor right_ptr
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.49 {check cursor-font cursor right_side} -setup {
+ button .b -text right_side
+} -body {
+ .b configure -cursor right_side
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.50 {check cursor-font cursor right_tee} -setup {
+ button .b -text right_tee
+} -body {
+ .b configure -cursor right_tee
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.51 {check cursor-font cursor rightbutton} -setup {
+ button .b -text rightbutton
+} -body {
+ .b configure -cursor rightbutton
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.52 {check cursor-font cursor rtl_logo} -setup {
+ button .b -text rtl_logo
+} -body {
+ .b configure -cursor rtl_logo
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.53 {check cursor-font cursor sailboat} -setup {
+ button .b -text sailboat
+} -body {
+ .b configure -cursor sailboat
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.54 {check cursor-font cursor sb_down_arrow} -setup {
+ button .b -text sb_down_arrow
+} -body {
+ .b configure -cursor sb_down_arrow
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.55 {check cursor-font cursor sb_h_double_arrow} -setup {
+ button .b -text sb_h_double_arrow
+} -body {
+ .b configure -cursor sb_h_double_arrow
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.56 {check cursor-font cursor sb_left_arrow} -setup {
+ button .b -text sb_left_arrow
+} -body {
+ .b configure -cursor sb_left_arrow
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.57 {check cursor-font cursor sb_right_arrow} -setup {
+ button .b -text sb_right_arrow
+} -body {
+ .b configure -cursor sb_right_arrow
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.58 {check cursor-font cursor sb_up_arrow} -setup {
+ button .b -text sb_up_arrow
+} -body {
+ .b configure -cursor sb_up_arrow
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.59 {check cursor-font cursor sb_v_double_arrow} -setup {
+ button .b -text sb_v_double_arrow
+} -body {
+ .b configure -cursor sb_v_double_arrow
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.60 {check cursor-font cursor shuttle} -setup {
+ button .b -text shuttle
+} -body {
+ .b configure -cursor shuttle
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.61 {check cursor-font cursor sizing} -setup {
+ button .b -text sizing
+} -body {
+ .b configure -cursor sizing
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.62 {check cursor-font cursor spider} -setup {
+ button .b -text spider
+} -body {
+ .b configure -cursor spider
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.63 {check cursor-font cursor spraycan} -setup {
+ button .b -text spraycan
+} -body {
+ .b configure -cursor spraycan
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.64 {check cursor-font cursor star} -setup {
+ button .b -text star
+} -body {
+ .b configure -cursor star
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.65 {check cursor-font cursor target} -setup {
+ button .b -text target
+} -body {
+ .b configure -cursor target
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.66 {check cursor-font cursor tcross} -setup {
+ button .b -text tcross
+} -body {
+ .b configure -cursor tcross
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.67 {check cursor-font cursor top_left_arrow} -setup {
+ button .b -text top_left_arrow
+} -body {
+ .b configure -cursor top_left_arrow
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.68 {check cursor-font cursor top_left_corner} -setup {
+ button .b -text top_left_corner
+} -body {
+ .b configure -cursor top_left_corner
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.69 {check cursor-font cursor top_right_corner} -setup {
+ button .b -text top_right_corner
+} -body {
+ .b configure -cursor top_right_corner
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.70 {check cursor-font cursor top_side} -setup {
+ button .b -text top_side
+} -body {
+ .b configure -cursor top_side
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.71 {check cursor-font cursor top_tee} -setup {
+ button .b -text top_tee
+} -body {
+ .b configure -cursor top_tee
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.72 {check cursor-font cursor trek} -setup {
+ button .b -text trek
+} -body {
+ .b configure -cursor trek
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.73 {check cursor-font cursor ul_angle} -setup {
+ button .b -text ul_angle
+} -body {
+ .b configure -cursor ul_angle
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.74 {check cursor-font cursor umbrella} -setup {
+ button .b -text umbrella
+} -body {
+ .b configure -cursor umbrella
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.75 {check cursor-font cursor ur_angle} -setup {
+ button .b -text ur_angle
+} -body {
+ .b configure -cursor ur_angle
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.76 {check cursor-font cursor watch} -setup {
+ button .b -text watch
+} -body {
+ .b configure -cursor watch
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-6.77 {check cursor-font cursor xterm} -setup {
+ button .b -text xterm
+} -body {
+ .b configure -cursor xterm
+} -cleanup {
+ destroy .b
+} -result {}
+
+# Test cursor named "none", it is not defined in
+# the X cursor table. It is defined in a Tk specific
+# table of named cursors and should be available on
+# all platforms.
+test cursor-6.78 {test cursor named "none"} -setup {
+ button .b -text CButton
+} -body {
+ .b configure -cursor none
+ .b cget -cursor
+} -cleanup {
+ destroy .b
+} -result none
+
+test cursor-6.79 {test cursor named "none"} -setup {
+ button .b -text CButton
+} -body {
+ .b configure -cursor none
+ .b configure -cursor {}
+ .b cget -cursor
+} -cleanup {
+ destroy .b
+} -result {}
+
+test cursor-6.80 {test cursor named "none"} -setup {
+ button .b -text CButton
+} -body {
+ .b configure -cursor none
+ .b configure -cursor {}
+ .b configure -cursor none
+ .b cget -cursor
+} -cleanup {
+ destroy .b
+} -result none
+
+test cursor-6.81 {test cursor named "none"} -setup {
+ button .b -text CButton
+} -body {
+ # Setting fg and bg does nothing for the none cursor
+ # because it displays no fg or bg pixels.
+ set results [list]
+ .b configure -cursor none
+ lappend results [.b cget -cursor]
+ .b configure -cursor {none blue}
+ lappend results [.b cget -cursor]
+ .b configure -cursor {none blue green}
+ lappend results [.b cget -cursor]
+ .b configure -cursor {}
+ lappend results [.b cget -cursor]
+ set results
+} -cleanup {
+ destroy .b
+ unset results
+} -result {none {none blue} {none blue green} {}}
+
+# -------------------------------------------------------------------------
+# Check the Windows specific cursors
+test cursor-7.1 {check Windows cursor no} -constraints win -setup {
+ button .b -text no
+} -body {
+ .b configure -cursor no
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-7.2 {check Windows cursor starting} -constraints win -setup {
+ button .b -text starting
+} -body {
+ .b configure -cursor starting
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-7.3 {check Windows cursor size} -constraints win -setup {
+ button .b -text size
+} -body {
+ .b configure -cursor size
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-7.4 {check Windows cursor size_ne_sw} -constraints win -setup {
+ button .b -text size_ne_sw
+} -body {
+ .b configure -cursor size_ne_sw
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-7.5 {check Windows cursor size_ns} -constraints win -setup {
+ button .b -text size_ns
+} -body {
+ .b configure -cursor size_ns
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-7.6 {check Windows cursor size_nw_se} -constraints win -setup {
+ button .b -text size_nw_se
+} -body {
+ .b configure -cursor size_nw_se
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-7.7 {check Windows cursor size_we} -constraints win -setup {
+ button .b -text size_we
+} -body {
+ .b configure -cursor size_we
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-7.8 {check Windows cursor uparrow} -constraints win -setup {
+ button .b -text uparrow
+} -body {
+ .b configure -cursor uparrow
+} -cleanup {
+ destroy .b
+} -result {}
+test cursor-7.9 {check Windows cursor wait} -constraints win -setup {
+ button .b -text wait
+} -body {
+ .b configure -cursor wait
+} -cleanup {
+ destroy .b
+} -result {}
+
+# -------------------------------------------------------------------------
+
+# cleanup
+cleanupTests
+return
diff --git a/tk8.6/tests/deferredClearCode.gif b/tk8.6/tests/deferredClearCode.gif
new file mode 100644
index 0000000..d530618
--- /dev/null
+++ b/tk8.6/tests/deferredClearCode.gif
Binary files differ
diff --git a/tk8.6/tests/dialog.test b/tk8.6/tests/dialog.test
new file mode 100644
index 0000000..78b6620
--- /dev/null
+++ b/tk8.6/tests/dialog.test
@@ -0,0 +1,67 @@
+# This file is a Tcl script to test out Tk's "tk_dialog" command.
+# It is organized in the standard fashion for Tcl tests.
+
+package require tcltest 2.2
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+namespace import -force tcltest::test
+
+test dialog-1.1 {tk_dialog command} -body {
+ tk_dialog
+} -match glob -returnCodes error -result {wrong # args: should be "tk_dialog w title text bitmap default *"}
+test dialog-1.2 {tk_dialog command} -body {
+ tk_dialog foo foo foo foo foo
+} -returnCodes error -result {bad window path name "foo"}
+test dialog-1.3 {tk_dialog command} -body {
+ tk_dialog .d foo foo fooBitmap foo
+} -cleanup {
+ destroy .d
+} -returnCodes error -result {bitmap "fooBitmap" not defined}
+
+
+test dialog-2.1 {tk_dialog operation} -setup {
+ proc PressButton {btn} {
+ if {![winfo ismapped $btn]} {
+ update
+ }
+ event generate $btn <Enter>
+ event generate $btn <1> -x 5 -y 5
+ event generate $btn <ButtonRelease-1> -x 5 -y 5
+ }
+} -body {
+ set x [after 5000 [list set tk::Priv(button) "no response"]]
+ after 100 PressButton .d.button0
+ set res [tk_dialog .d foo foo info 0 click]
+ after cancel $x
+ return $res
+} -cleanup {
+ destroy .d
+} -result {0}
+test dialog-2.2 {tk_dialog operation} -setup {
+ proc HitReturn {w} {
+ event generate $w <Enter>
+ focus -force $w
+ event generate $w <KeyPress> -keysym Return
+ }
+} -body {
+ set x [after 5000 [list set tk::Priv(button) "no response"]]
+ after 100 HitReturn .d
+ set res [tk_dialog .d foo foo info 1 click default]
+ after cancel $x
+ return $res
+} -cleanup {
+ destroy .d
+} -result {1}
+test dialog-2.3 {tk_dialog operation} -body {
+ set x [after 5000 [list set tk::Priv(button) "no response"]]
+ after 100 destroy .d
+ set res [tk_dialog .d foo foo info 0 click]
+ after cancel $x
+ return $res
+} -cleanup {
+ destroy .b
+} -result {-1}
+
+cleanupTests
+return
+
diff --git a/tk8.6/tests/earth.gif b/tk8.6/tests/earth.gif
new file mode 100644
index 0000000..2c229eb
--- /dev/null
+++ b/tk8.6/tests/earth.gif
Binary files differ
diff --git a/tk8.6/tests/embed.test b/tk8.6/tests/embed.test
new file mode 100644
index 0000000..1fe73ef
--- /dev/null
+++ b/tk8.6/tests/embed.test
@@ -0,0 +1,88 @@
+# This file is a Tcl script to test out embedded Windows.
+#
+# Copyright (c) 1996-1997 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+
+
+test embed-1.1 {TkpUseWindow procedure, bad window identifier} -setup {
+ deleteWindows
+} -body {
+ toplevel .t -use xyz
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {expected integer but got "xyz"}
+
+test embed-1.2 {CreateFrame procedure, bad window identifier} -setup {
+ deleteWindows
+} -body {
+ toplevel .t -container xyz
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {expected boolean value but got "xyz"}
+
+test embed-1.3 {CreateFrame procedure, both -use and -container is invalid} -setup {
+ deleteWindows
+} -body {
+ toplevel .container -container 1
+ toplevel .t -use [winfo id .container] -container 1
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {windows cannot have both the -use and the -container option set}
+
+# testing window embedding for win platforms
+test embed-1.4.win {TkpUseWindow procedure, -container must be set} -constraints {
+ win
+} -setup {
+ deleteWindows
+} -body {
+ toplevel .container
+ toplevel .embd -use [winfo id .container]
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {the window to use is not a Tk container}
+# testing window embedding for win platforms
+test embed-1.5.win {TkpUseWindow procedure, -container must be set} -constraints {
+ win
+} -setup {
+ deleteWindows
+} -body {
+ frame .container
+ toplevel .embd -use [winfo id .container]
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {the window to use is not a Tk container}
+
+# testing window embedding for other than win platforms
+test embed-1.4.nonwin {TkpUseWindow procedure, -container must be set} -constraints {
+ nonwin
+} -setup {
+ deleteWindows
+} -body {
+ toplevel .container
+ toplevel .embd -use [winfo id .container]
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {window ".container" doesn't have -container option set}
+# testing window embedding for other than win platforms
+test embed-1.5.nonwin {TkpUseWindow procedure, -container must be set} -constraints {
+ nonwin
+} -setup {
+ deleteWindows
+} -body {
+ frame .container
+ toplevel .embd -use [winfo id .container]
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {window ".container" doesn't have -container option set}
+
+
+cleanupTests
+return
+
+
diff --git a/tk8.6/tests/entry.test b/tk8.6/tests/entry.test
new file mode 100644
index 0000000..67f8374
--- /dev/null
+++ b/tk8.6/tests/entry.test
@@ -0,0 +1,3546 @@
+# This file is a Tcl script to test entry widgets in Tk. It is
+# organized in the standard fashion for Tcl tests.
+#
+# Copyright (c) 1994 The Regents of the University of California.
+# Copyright (c) 1994-1997 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+
+# For xscrollcommand
+proc scroll args {
+ global scrollInfo
+ set scrollInfo $args
+}
+# For trace variable
+proc override args {
+ global x
+ set x 12345
+}
+
+# Procedures used in widget VALIDATION tests
+proc doval {W d i P s S v V} {
+ set ::vVals [list $W $d $i $P $s $S $v $V]
+ return 1
+}
+proc doval2 {W d i P s S v V} {
+ set ::vVals [list $W $d $i $P $s $S $v $V]
+ set ::e mydata
+ return 1
+}
+proc doval3 {W d i P s S v V} {
+ set ::vVals [list $W $d $i $P $s $S $v $V]
+ return 0
+}
+
+set cy [font metrics {Courier -12} -linespace]
+
+
+test entry-1.1 {configuration option: "background" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -background #ff0000
+ .e cget -background
+} -cleanup {
+ destroy .e
+} -result {#ff0000}
+test entry-1.2 {configuration option: "background" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -background non-existent
+} -cleanup {
+ destroy .e
+} -returnCodes {error} -result {unknown color name "non-existent"}
+
+test entry-1.3 {configuration option: "bd" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -bd 4
+ .e cget -bd
+} -cleanup {
+ destroy .e
+} -result {4}
+test entry-1.4 {configuration option: "bd" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -bd badValue
+} -cleanup {
+ destroy .e
+} -returnCodes {error} -result {bad screen distance "badValue"}
+
+test entry-1.5 {configuration option: "bg" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -bg #ff0000
+ .e cget -bg
+} -cleanup {
+ destroy .e
+} -result {#ff0000}
+test entry-1.6 {configuration option: "bg" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -bg non-existent
+} -cleanup {
+ destroy .e
+} -returnCodes {error} -result {unknown color name "non-existent"}
+
+test entry-1.7 {configuration option: "borderwidth" for entry} -setup {
+ entry .e -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -borderwidth 1.3
+ .e cget -borderwidth
+} -cleanup {
+ destroy .e
+} -result {1}
+test entry-1.8 {configuration option: "borderwidth" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -borderwidth badValue
+} -cleanup {
+ destroy .e
+} -returnCodes {error} -result {bad screen distance "badValue"}
+
+test entry-1.9 {configuration option: "cursor" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -cursor arrow
+ .e cget -cursor
+} -cleanup {
+ destroy .e
+} -result {arrow}
+test entry-1.10 {configuration option: "cursor" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -cursor badValue
+} -cleanup {
+ destroy .e
+} -returnCodes {error} -result {bad cursor spec "badValue"}
+
+test entry-1.11 {configuration option: "disabledbackground" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -disabledbackground green
+ .e cget -disabledbackground
+} -cleanup {
+ destroy .e
+} -result {green}
+test entry-1.12 {configuration option: "disabledbackground" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -disabledbackground non-existent
+} -cleanup {
+ destroy .e
+} -returnCodes {error} -result {unknown color name "non-existent"}
+
+test entry-1.13 {configuration option: "disabledforeground" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -disabledforeground blue
+ .e cget -disabledforeground
+} -cleanup {
+ destroy .e
+} -result {blue}
+test entry-1.14 {configuration option: "disabledforeground" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -disabledforeground non-existent
+} -cleanup {
+ destroy .e
+} -returnCodes {error} -result {unknown color name "non-existent"}
+
+test entry-1.15 {configuration option: "exportselection" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -exportselection yes
+ .e cget -exportselection
+} -cleanup {
+ destroy .e
+} -result {1}
+test entry-1.16 {configuration option: "exportselection" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -exportselection xyzzy
+} -cleanup {
+ destroy .e
+} -returnCodes {error} -result {expected boolean value but got "xyzzy"}
+
+test entry-1.17 {configuration option: "fg" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -fg #110022
+ .e cget -fg
+} -cleanup {
+ destroy .e
+} -result {#110022}
+test entry-1.18 {configuration option: "fg" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -fg non-existent
+} -cleanup {
+ destroy .e
+} -returnCodes {error} -result {unknown color name "non-existent"}
+
+test entry-1.19 {configuration option: "font" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2
+ pack .e
+ update
+} -body {
+ .e configure -font {Helvetica -12}
+ .e cget -font
+} -cleanup {
+ destroy .e
+} -result {Helvetica -12}
+test entry-1.20 {configuration option: "font" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2
+ pack .e
+ update
+} -body {
+ .e configure -font {}
+} -cleanup {
+ destroy .e
+} -returnCodes {error} -result {font "" doesn't exist}
+
+test entry-1.21 {configuration option: "foreground" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -foreground #110022
+ .e cget -foreground
+} -cleanup {
+ destroy .e
+} -result {#110022}
+test entry-1.22 {configuration option: "foreground" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -foreground non-existent
+} -cleanup {
+ destroy .e
+} -returnCodes {error} -result {unknown color name "non-existent"}
+
+test entry-1.23 {configuration option: "highlightbackground" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -highlightbackground #110022
+ .e cget -highlightbackground
+} -cleanup {
+ destroy .e
+} -result {#110022}
+test entry-1.24 {configuration option: "highlightbackground" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -highlightbackground non-existent
+} -cleanup {
+ destroy .e
+} -returnCodes {error} -result {unknown color name "non-existent"}
+
+test entry-1.25 {configuration option: "highlightcolor" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -highlightcolor #110022
+ .e cget -highlightcolor
+} -cleanup {
+ destroy .e
+} -result {#110022}
+test entry-1.26 {configuration option: "highlightcolor" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -highlightcolor non-existent
+} -cleanup {
+ destroy .e
+} -returnCodes {error} -result {unknown color name "non-existent"}
+
+test entry-1.27 {configuration option: "highlightthickness" for entry} -setup {
+ entry .e -borderwidth 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -highlightthickness 6
+ .e cget -highlightthickness
+} -cleanup {
+ destroy .e
+} -result {6}
+test entry-1.28 {configuration option: "highlightthickness" for entry} -setup {
+ entry .e -borderwidth 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -highlightthickness -2
+ .e cget -highlightthickness
+} -cleanup {
+ destroy .e
+} -result {0}
+test entry-1.29 {configuration option: "highlightthickness" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -highlightthickness badValue
+} -cleanup {
+ destroy .e
+} -returnCodes {error} -result {bad screen distance "badValue"}
+
+test entry-1.30 {configuration option: "insertbackground" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -insertbackground #110022
+ .e cget -insertbackground
+} -cleanup {
+ destroy .e
+} -result {#110022}
+test entry-1.31 {configuration option: "insertbackground" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -insertbackground non-existent
+} -cleanup {
+ destroy .e
+} -returnCodes {error} -result {unknown color name "non-existent"}
+
+test entry-1.32 {configuration option: "insertborderwidth" for entry} -setup {
+ entry .e -borderwidth 2 -insertwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -insertborderwidth 1.3
+ .e cget -insertborderwidth
+} -cleanup {
+ destroy .e
+} -result {1}
+test entry-1.33 {configuration option: "insertborderwidth" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -insertborderwidth 2.6x
+} -cleanup {
+ destroy .e
+} -returnCodes {error} -result {bad screen distance "2.6x"}
+
+test entry-1.34 {configuration option: "insertofftime" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -insertofftime 100
+ .e cget -insertofftime
+} -cleanup {
+ destroy .e
+} -result {100}
+test entry-1.35 {configuration option: "insertofftime" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -insertofftime 3.2
+} -cleanup {
+ destroy .e
+} -returnCodes {error} -result {expected integer but got "3.2"}
+
+test entry-1.36 {configuration option: "insertontime" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -insertontime 100
+ .e cget -insertontime
+} -cleanup {
+ destroy .e
+} -result {100}
+test entry-1.37 {configuration option: "insertontime" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -insertontime 3.2
+} -cleanup {
+ destroy .e
+} -returnCodes {error} -result {expected integer but got "3.2"}
+
+test entry-1.38 {configuration option: "invalidcommand" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -invalidcommand "any string"
+ .e cget -invalidcommand
+} -cleanup {
+ destroy .e
+} -result {any string}
+
+test entry-1.39 {configuration option: "invcmd" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -invcmd "any string"
+ .e cget -invcmd
+} -cleanup {
+ destroy .e
+} -result {any string}
+
+test entry-1.40 {configuration option: "justify" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -justify right
+ .e cget -justify
+} -cleanup {
+ destroy .e
+} -result {right}
+test entry-1.41 {configuration option: "justify" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -justify bogus
+} -cleanup {
+ destroy .e
+} -returnCodes {error} -result {bad justification "bogus": must be left, right, or center}
+
+test entry-1.42 {configuration option: "readonlybackground" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -readonlybackground green
+ .e cget -readonlybackground
+} -cleanup {
+ destroy .e
+} -result {green}
+test entry-1.43 {configuration option: "readonlybackground" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -readonlybackground non-existent
+} -cleanup {
+ destroy .e
+} -returnCodes {error} -result {unknown color name "non-existent"}
+
+test entry-1.44 {configuration option: "relief" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -relief flat
+ .e cget -relief
+} -cleanup {
+ destroy .e
+} -result {flat}
+
+test entry-1.45 {configuration option: "selectbackground" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -selectbackground #110022
+ .e cget -selectbackground
+} -cleanup {
+ destroy .e
+} -result {#110022}
+test entry-1.46 {configuration option: "selectbackground" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -selectbackground non-existent
+} -cleanup {
+ destroy .e
+} -returnCodes {error} -result {unknown color name "non-existent"}
+
+test entry-1.47 {configuration option: "selectborderwidth" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -selectborderwidth 1.3
+ .e cget -selectborderwidth
+} -cleanup {
+ destroy .e
+} -result {1}
+test entry-1.48 {configuration option: "selectborderwidth" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -selectborderwidth badValue
+} -cleanup {
+ destroy .e
+} -returnCodes {error} -result {bad screen distance "badValue"}
+
+test entry-1.49 {configuration option: "selectforeground" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -selectforeground #110022
+ .e cget -selectforeground
+} -cleanup {
+ destroy .e
+} -result {#110022}
+test entry-1.50 {configuration option: "selectforeground" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -selectforeground non-existent
+} -cleanup {
+ destroy .e
+} -returnCodes {error} -result {unknown color name "non-existent"}
+
+test entry-1.51 {configuration option: "show" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -show *
+ .e cget -show
+} -cleanup {
+ destroy .e
+} -result {*}
+
+test entry-1.52 {configuration option: "state" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -state n
+ .e cget -state
+} -cleanup {
+ destroy .e
+} -result {normal}
+test entry-1.53 {configuration option: "state" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -state bogus
+} -cleanup {
+ destroy .e
+} -returnCodes {error} -result {bad state "bogus": must be disabled, normal, or readonly}
+
+test entry-1.54 {configuration option: "takefocus" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -takefocus "any string"
+ .e cget -takefocus
+} -cleanup {
+ destroy .e
+} -result {any string}
+
+test entry-1.55 {configuration option: "textvariable" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -textvariable i
+ .e cget -textvariable
+} -cleanup {
+ destroy .e
+} -result {i}
+
+test entry-1.56 {configuration option: "width" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -width 402
+ .e cget -width
+} -cleanup {
+ destroy .e
+} -result {402}
+test entry-1.57 {configuration option: "width" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -width 3p
+} -cleanup {
+ destroy .e
+} -returnCodes {error} -result {expected integer but got "3p"}
+
+test entry-1.58 {configuration option: "xscrollcommand" for entry} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .e
+ update
+} -body {
+ .e configure -xscrollcommand {Some command}
+ .e cget -xscrollcommand
+} -cleanup {
+ destroy .e
+} -result {Some command}
+
+
+
+test entry-2.1 {Tk_EntryCmd procedure} -body {
+ entry
+} -returnCodes error -result {wrong # args: should be "entry pathName ?-option value ...?"}
+test entry-2.2 {Tk_EntryCmd procedure} -body {
+ entry gorp
+} -returnCodes error -result {bad window path name "gorp"}
+test entry-2.3 {Tk_EntryCmd procedure} -body {
+ entry .e
+ pack .e
+ update
+ list [winfo exists .e] [winfo class .e] [info commands .e]
+} -cleanup {
+ destroy .e
+} -result {1 Entry .e}
+test entry-2.4 {Tk_EntryCmd procedure} -body {
+ entry .e -gorp foo
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {unknown option "-gorp"}
+test entry-2.4.1 {Tk_EntryCmd procedure} -body {
+ catch {entry .e -gorp foo}
+ list [winfo exists .e] [info commands .e]
+} -cleanup {
+ destroy .e
+} -result {0 {}}
+test entry-2.5 {Tk_EntryCmd procedure} -body {
+ entry .e
+} -cleanup {
+ destroy .e
+} -result {.e}
+
+
+test entry-3.1 {EntryWidgetCmd procedure} -setup {
+ entry .e
+ pack .e
+ update
+} -body {
+ .e
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {wrong # args: should be ".e option ?arg ...?"}
+test entry-3.2 {EntryWidgetCmd procedure, "bbox" widget command} -setup {
+ entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
+ pack .e
+ update
+} -body {
+ .e bbox
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {wrong # args: should be ".e bbox index"}
+test entry-3.3 {EntryWidgetCmd procedure, "bbox" widget command} -setup {
+ entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
+ pack .e
+ update
+} -body {
+ .e bbox a b
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {wrong # args: should be ".e bbox index"}
+test entry-3.4 {EntryWidgetCmd procedure, "bbox" widget command} -setup {
+ entry .e
+ pack .e
+ update
+} -body {
+ .e bbox bogus
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {bad entry index "bogus"}
+test entry-3.5 {EntryWidgetCmd procedure, "bbox" widget command} -setup {
+ entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
+ pack .e
+ update
+} -body {
+ .e bbox 0
+} -cleanup {
+ destroy .e
+} -result [list 5 5 0 $cy]
+
+# Previously the result was count using previousli counted font measurements
+# and metrics. It was changed to less verbose solution - the result is the one
+# that passes fonts constraint (this concerns tests 3.6, 3.7, 3.8, 3.10)
+test entry-3.6 {EntryWidgetCmd procedure, "bbox" widget command} -constraints {
+ fonts
+} -setup {
+ entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
+ pack .e
+ update
+} -body {
+# Tcl_UtfAtIndex(): no utf chars
+ .e insert 0 "abc"
+ list [.e bbox 3] [.e bbox end]
+} -cleanup {
+ destroy .e
+} -result {{19 5 7 13} {19 5 7 13}}
+test entry-3.7 {EntryWidgetCmd procedure, "bbox" widget command} -constraints {
+ fonts
+} -setup {
+ entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
+ pack .e
+ update
+} -body {
+# Tcl_UtfAtIndex(): utf at end
+ .e insert 0 "ab\u4e4e"
+ .e bbox end
+} -cleanup {
+ destroy .e
+} -result {19 5 12 13}
+test entry-3.8 {EntryWidgetCmd procedure, "bbox" widget command} -constraints {
+ fonts
+} -setup {
+ entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
+ pack .e
+ update
+} -body {
+# Tcl_UtfAtIndex(): utf before index
+ .e insert 0 "ab\u4e4ec"
+ .e bbox 3
+} -cleanup {
+ destroy .e
+} -result {31 5 7 13}
+test entry-3.9 {EntryWidgetCmd procedure, "bbox" widget command} -setup {
+ entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
+ pack .e
+ update
+} -body {
+# Tcl_UtfAtIndex(): no chars
+ .e bbox end
+} -cleanup {
+ destroy .e
+} -result "5 5 0 $cy"
+test entry-3.10 {EntryWidgetCmd procedure, "bbox" widget command} -constraints {
+ fonts
+} -setup {
+ entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
+ pack .e
+ update
+} -body {
+ .e insert 0 "abcdefghij\u4e4eklmnop"
+ list [.e bbox 0] [.e bbox 1] [.e bbox 10] [.e bbox end]
+} -cleanup {
+ destroy .e
+} -result {{5 5 7 13} {12 5 7 13} {75 5 12 13} {122 5 7 13}}
+test entry-3.11 {EntryWidgetCmd procedure, "cget" widget command} -setup {
+ entry .e
+} -body {
+ .e cget
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {wrong # args: should be ".e cget option"}
+test entry-3.12 {EntryWidgetCmd procedure, "cget" widget command} -setup {
+ entry .e
+} -body {
+ .e cget a b
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {wrong # args: should be ".e cget option"}
+test entry-3.13 {EntryWidgetCmd procedure, "cget" widget command} -setup {
+ entry .e
+} -body {
+ .e cget -gorp
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {unknown option "-gorp"}
+test entry-3.14 {EntryWidgetCmd procedure, "cget" widget command} -setup {
+ entry .e
+} -body {
+ .e configure -bd 4
+ .e cget -bd
+} -cleanup {
+ destroy .e
+} -result {4}
+test entry-3.15 {EntryWidgetCmd procedure, "configure" widget command} -setup {
+ entry .e
+ pack .e
+ update
+} -body {
+ llength [.e configure]
+} -cleanup {
+ destroy .e
+} -result {36}
+test entry-3.16 {EntryWidgetCmd procedure, "configure" widget command} -setup {
+ entry .e
+} -body {
+ .e configure -foo
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {unknown option "-foo"}
+test entry-3.17 {EntryWidgetCmd procedure, "configure" widget command} -setup {
+ entry .e
+} -body {
+ .e configure -bd 4
+ .e configure -bg #ffffff
+ lindex [.e configure -bd] 4
+} -cleanup {
+ destroy .e
+} -result {4}
+test entry-3.18 {EntryWidgetCmd procedure, "delete" widget command} -setup {
+ entry .e
+} -body {
+ .e delete
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {wrong # args: should be ".e delete firstIndex ?lastIndex?"}
+test entry-3.19 {EntryWidgetCmd procedure, "delete" widget command} -setup {
+ entry .e
+} -body {
+ .e delete a b c
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {wrong # args: should be ".e delete firstIndex ?lastIndex?"}
+test entry-3.20 {EntryWidgetCmd procedure, "delete" widget command} -setup {
+ entry .e
+} -body {
+ .e delete foo
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {bad entry index "foo"}
+test entry-3.21 {EntryWidgetCmd procedure, "delete" widget command} -setup {
+ entry .e
+} -body {
+ .e delete 0 bar
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {bad entry index "bar"}
+test entry-3.22 {EntryWidgetCmd procedure, "delete" widget command} -setup {
+ entry .e
+ pack .e
+ update
+} -body {
+ .e insert end "01234567890"
+ .e delete 2 4
+ .e get
+} -cleanup {
+ destroy .e
+} -result {014567890}
+test entry-3.23 {EntryWidgetCmd procedure, "delete" widget command} -setup {
+ entry .e
+} -body {
+ .e insert end "01234567890"
+ .e delete 6
+ .e get
+} -cleanup {
+ destroy .e
+} -result {0123457890}
+test entry-3.24 {EntryWidgetCmd procedure, "delete" widget command} -setup {
+ entry .e
+ pack .e
+ update
+ set x {}
+} -body {
+# UTF
+ .e insert end "01234\u4e4e67890"
+ .e delete 6
+ lappend x [.e get]
+ .e delete 0 end
+ .e insert end "012345\u4e4e7890"
+ .e delete 6
+ lappend x [.e get]
+ .e delete 0 end
+ .e insert end "0123456\u4e4e890"
+ .e delete 6
+ lappend x [.e get]
+} -cleanup {
+ destroy .e
+} -result [list "01234\u4e4e7890" "0123457890" "012345\u4e4e890"]
+test entry-3.25 {EntryWidgetCmd procedure, "delete" widget command} -setup {
+ entry .e
+ pack .e
+ update
+} -body {
+ .e insert end "01234567890"
+ .e delete 6 5
+ .e get
+} -cleanup {
+ destroy .e
+} -result {01234567890}
+test entry-3.26 {EntryWidgetCmd procedure, "delete" widget command} -setup {
+ entry .e
+ pack .e
+ update
+} -body {
+ .e insert end "01234567890"
+ .e configure -state disabled
+ .e delete 2 8
+ .e configure -state normal
+ .e get
+} -cleanup {
+ destroy .e
+} -result {01234567890}
+test entry-3.26a {EntryWidgetCmd procedure, "delete" widget command} -setup {
+ entry .e
+ pack .e
+ update
+} -body {
+ .e insert end "01234567890"
+ .e configure -state readonly
+ .e delete 2 8
+ .e configure -state normal
+ .e get
+} -cleanup {
+ destroy .e
+} -result {01234567890}
+test entry-3.27 {EntryWidgetCmd procedure, "get" widget command} -setup {
+ entry .e
+} -body {
+ .e get foo
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {wrong # args: should be ".e get"}
+test entry-3.28 {EntryWidgetCmd procedure, "icursor" widget command} -setup {
+ entry .e
+} -body {
+ .e icursor
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {wrong # args: should be ".e icursor pos"}
+test entry-3.29 {EntryWidgetCmd procedure, "icursor" widget command} -setup {
+ entry .e
+} -body {
+ .e icursor foo
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {bad entry index "foo"}
+test entry-3.30 {EntryWidgetCmd procedure, "icursor" widget command} -setup {
+ entry .e
+} -body {
+ .e insert end "01234567890"
+ .e icursor 4
+ .e index insert
+} -cleanup {
+ destroy .e
+} -result {4}
+test entry-3.31 {EntryWidgetCmd procedure, "index" widget command} -setup {
+ entry .e
+} -body {
+ .e in
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {ambiguous option "in": must be bbox, cget, configure, delete, get, icursor, index, insert, scan, selection, validate, or xview}
+test entry-3.32 {EntryWidgetCmd procedure, "index" widget command} -setup {
+ entry .e
+} -body {
+ .e index
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {wrong # args: should be ".e index string"}
+test entry-3.33 {EntryWidgetCmd procedure, "index" widget command} -setup {
+ entry .e
+} -body {
+ .e index foo
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {bad entry index "foo"}
+test entry-3.34 {EntryWidgetCmd procedure, "index" widget command} -setup {
+ entry .e
+ pack .e
+ update
+} -body {
+ .e index 0
+} -cleanup {
+ destroy .e
+} -returnCodes {ok} -match glob -result {*}
+test entry-3.35 {EntryWidgetCmd procedure, "index" widget command} -setup {
+ entry .e
+ pack .e
+ update
+} -body {
+# UTF
+ .e insert 0 abc\u4e4e\u0153def
+ list [.e index 3] [.e index 4] [.e index end]
+} -cleanup {
+ destroy .e
+} -result {3 4 8}
+test entry-3.36 {EntryWidgetCmd procedure, "insert" widget command} -setup {
+ entry .e
+} -body {
+ .e insert a
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {wrong # args: should be ".e insert index text"}
+test entry-3.37 {EntryWidgetCmd procedure, "insert" widget command} -setup {
+ entry .e
+} -body {
+ .e insert a b c
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {wrong # args: should be ".e insert index text"}
+test entry-3.38 {EntryWidgetCmd procedure, "insert" widget command} -setup {
+ entry .e
+} -body {
+ .e insert foo Text
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {bad entry index "foo"}
+test entry-3.39 {EntryWidgetCmd procedure, "insert" widget command} -setup {
+ entry .e
+ pack .e
+ update
+} -body {
+ .e insert end "01234567890"
+ .e insert 3 xxx
+ .e get
+} -cleanup {
+ destroy .e
+} -result {012xxx34567890}
+test entry-3.40 {EntryWidgetCmd procedure, "insert" widget command} -setup {
+ entry .e
+ pack .e
+ update
+} -body {
+ .e insert end "01234567890"
+ .e configure -state disabled
+ .e insert 3 xxx
+ .e configure -state normal
+ .e get
+} -cleanup {
+ destroy .e
+} -result {01234567890}
+test entry-3.40a {EntryWidgetCmd procedure, "insert" widget command} -setup {
+ entry .e
+ pack .e
+ update
+} -body {
+ .e insert end "01234567890"
+ .e configure -state readonly
+ .e insert 3 xxx
+ .e configure -state normal
+ .e get
+} -cleanup {
+ destroy .e
+} -result {01234567890}
+test entry-3.41 {EntryWidgetCmd procedure, "insert" widget command} -setup {
+ entry .e
+} -body {
+ .e insert a b c
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {wrong # args: should be ".e insert index text"}
+test entry-3.42 {EntryWidgetCmd procedure, "scan" widget command} -setup {
+ entry .e
+ pack .e
+ update
+} -body {
+ .e scan a
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {wrong # args: should be ".e scan mark|dragto x"}
+test entry-3.43 {EntryWidgetCmd procedure, "scan" widget command} -setup {
+ entry .e
+ pack .e
+ update
+} -body {
+ .e scan a b c
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {wrong # args: should be ".e scan mark|dragto x"}
+test entry-3.44 {EntryWidgetCmd procedure, "scan" widget command} -setup {
+ entry .e
+ pack .e
+ update
+} -body {
+ .e scan foobar 20
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {bad scan option "foobar": must be mark or dragto}
+test entry-3.45 {EntryWidgetCmd procedure, "scan" widget command} -setup {
+ entry .e
+ pack .e
+ update
+} -body {
+ .e scan mark 20.1
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {expected integer but got "20.1"}
+
+# This test is non-portable because character sizes vary.
+test entry-3.46 {EntryWidgetCmd procedure, "scan" widget command} -constraints {
+ fonts
+} -setup {
+ entry .e -font {Helvetica -12} -borderwidth 2 -highlightthickness 2
+ pack .e
+ update
+} -body {
+ .e insert end "This is quite a long string, in fact a "
+ .e insert end "very very long string"
+ .e scan mark 30
+ .e scan dragto 28
+ .e index @0
+} -cleanup {
+ destroy .e
+} -result {2}
+test entry-3.47 {EntryWidgetCmd procedure, "select" widget command} -setup {
+ entry .e
+} -body {
+ .e select
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {wrong # args: should be ".e selection option ?index?"}
+test entry-3.48 {EntryWidgetCmd procedure, "select" widget command} -setup {
+ entry .e
+} -body {
+ .e select foo
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {bad selection option "foo": must be adjust, clear, from, present, range, or to}
+
+test entry-3.49 {EntryWidgetCmd procedure, "select clear" widget command} -setup {
+ entry .e
+} -body {
+ .e select clear gorp
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {wrong # args: should be ".e selection clear"}
+test entry-3.50 {EntryWidgetCmd procedure, "select clear" widget command} -setup {
+ entry .e
+} -body {
+ .e insert end "0123456789"
+ .e select from 1
+ .e select to 4
+ update
+ .e select clear
+ selection get
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {PRIMARY selection doesn't exist or form "STRING" not defined}
+test entry-3.50.1 {EntryWidgetCmd procedure, "select clear" widget command} -setup {
+ entry .e
+ pack .e
+ update
+} -body {
+ .e insert end "0123456789"
+ .e select from 1
+ .e select to 4
+ update
+ .e select clear
+ catch {selection get}
+ selection own
+} -cleanup {
+ destroy .e
+} -result {.e}
+
+test entry-3.51 {EntryWidgetCmd procedure, "selection present" widget command} -setup {
+ entry .e
+} -body {
+ .e selection present foo
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {wrong # args: should be ".e selection present"}
+test entry-3.52 {EntryWidgetCmd procedure, "selection present" widget command} -setup {
+ entry .e
+ pack .e
+ update
+} -body {
+ .e insert end 0123456789
+ .e select from 3
+ .e select to 6
+ .e selection present
+} -cleanup {
+ destroy .e
+} -result {1}
+test entry-3.53 {EntryWidgetCmd procedure, "selection present" widget command} -setup {
+ entry .e
+ pack .e
+ update
+} -body {
+ .e insert end 0123456789
+ .e select from 3
+ .e select to 6
+ .e configure -exportselection false
+ .e selection present
+} -cleanup {
+ destroy .e
+} -result {1}
+test entry-3.54 {EntryWidgetCmd procedure, "selection present" widget command} -setup {
+ entry .e
+ pack .e
+ update
+} -body {
+ .e insert end 0123456789
+ .e select from 3
+ .e select to 6
+ .e delete 0 end
+ .e selection present
+} -cleanup {
+ destroy .e
+} -result {0}
+test entry-3.55 {EntryWidgetCmd procedure, "selection adjust" widget command} -setup {
+ entry .e
+} -body {
+ .e select adjust x
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {bad entry index "x"}
+test entry-3.56 {EntryWidgetCmd procedure, "selection adjust" widget command} -setup {
+ entry .e
+} -body {
+ .e select adjust 2 3
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {wrong # args: should be ".e selection adjust index"}
+test entry-3.57 {EntryWidgetCmd procedure, "selection adjust" widget command} -setup {
+ entry .e
+ pack .e
+ update
+} -body {
+ .e insert end "0123456789"
+ .e select from 1
+ .e select to 5
+ update
+ .e select adjust 4
+ selection get
+} -cleanup {
+ destroy .e
+} -result {123}
+test entry-3.58 {EntryWidgetCmd procedure, "selection adjust" widget command} -setup {
+ entry .e
+ pack .e
+ update
+} -body {
+ .e insert end "0123456789"
+ .e select from 1
+ .e select to 5
+ update
+ .e select adjust 2
+ selection get
+} -cleanup {
+ destroy .e
+} -result {234}
+test entry-3.59 {EntryWidgetCmd procedure, "selection from" widget command} -setup {
+ entry .e
+} -body {
+ .e select from 2 3
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {wrong # args: should be ".e selection from index"}
+
+test entry-3.60 {EntryWidgetCmd procedure, "selection range" widget command} -setup {
+ entry .e
+} -body {
+ .e select range 2
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {wrong # args: should be ".e selection range start end"}
+test entry-3.61 {EntryWidgetCmd procedure, "selection range" widget command} -setup {
+ entry .e
+} -body {
+ .e selection range 2 3 4
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {wrong # args: should be ".e selection range start end"}
+test entry-3.62 {EntryWidgetCmd procedure, "selection range" widget command} -setup {
+ entry .e
+} -body {
+ .e insert end 0123456789
+ .e select from 1
+ .e select to 5
+ .e select range 4 4
+ .e index sel.first
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {selection isn't in widget .e}
+test entry-3.63 {EntryWidgetCmd procedure, "selection range" widget command} -setup {
+ entry .e
+ pack .e
+ update
+} -body {
+ .e insert end 0123456789
+ .e select from 3
+ .e select to 7
+ .e select range 2 9
+ list [.e index sel.first] [.e index sel.last] [.e index anchor]
+} -cleanup {
+ destroy .e
+} -result {2 9 3}
+test entry-3.64 {EntryWidgetCmd procedure, "selection" widget command} -setup {
+ entry .e
+ pack .e
+ update
+} -body {
+ .e insert end 0123456789
+ .e selection range 0 end
+ .e configure -state disabled
+ .e selection range 2 4
+ .e configure -state normal
+ list [.e index sel.first] [.e index sel.last]
+} -cleanup {
+ destroy .e
+} -result {0 10}
+test entry-3.64a {EntryWidgetCmd procedure, "selection" widget command} -setup {
+ entry .e
+ pack .e
+ update
+} -body {
+ .e insert end 0123456789
+ .e selection range 0 end
+ .e configure -state readonly
+ .e selection range 2 4
+ .e configure -state normal
+ list [.e index sel.first] [.e index sel.last]
+} -cleanup {
+ destroy .e
+} -result {2 4}
+test entry-3.64b {EntryWidgetCmd procedure, "selection to" widget command} -setup {
+ entry .e
+ pack .e
+ update
+ .e insert end "This is quite a long text string, so long that it "
+ .e insert end "runs off the end of the window quite a bit."
+} -body {
+ .e select to 2 3
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {wrong # args: should be ".e selection to index"}
+
+test entry-3.65 {EntryWidgetCmd procedure, "xview" widget command} -setup {
+ entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
+ pack .e
+ update
+} -body {
+ .e insert end "This is quite a long text string, so long that it "
+ .e insert end "runs off the end of the window quite a bit."
+ .e xview 5
+ format {%.7f %.7f} {*}[.e xview]
+} -cleanup {
+ destroy .e
+} -result {0.0537634 0.2688172}
+test entry-3.66 {EntryWidgetCmd procedure, "xview" widget command} -setup {
+ entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
+ pack .e
+ update
+} -body {
+ .e xview gorp
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {bad entry index "gorp"}
+test entry-3.67 {EntryWidgetCmd procedure, "xview" widget command} -setup {
+ entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
+ pack .e
+ update
+} -body {
+ .e insert end "This is quite a long text string, so long that it "
+ .e insert end "runs off the end of the window quite a bit."
+ .e xview 0
+ .e icursor 10
+ .e xview insert
+ format {%.6f %.6f} {*}[.e xview]
+} -cleanup {
+ destroy .e
+} -result {0.107527 0.322581}
+test entry-3.68 {EntryWidgetCmd procedure, "xview" widget command} -setup {
+ entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
+ pack .e
+ update
+} -body {
+ .e xview moveto foo bar
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {wrong # args: should be ".e xview moveto fraction"}
+test entry-3.69 {EntryWidgetCmd procedure, "xview" widget command} -setup {
+ entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
+ pack .e
+ update
+} -body {
+ .e xview moveto foo
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {expected floating-point number but got "foo"}
+test entry-3.70 {EntryWidgetCmd procedure, "xview" widget command} -setup {
+ entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
+ pack .e
+ update
+} -body {
+ .e insert end "This is quite a long text string, so long that it "
+ .e insert end "runs off the end of the window quite a bit."
+ .e xview moveto 0.5
+ format {%.6f %.6f} {*}[.e xview]
+} -cleanup {
+ destroy .e
+} -result {0.505376 0.720430}
+test entry-3.71 {EntryWidgetCmd procedure, "xview" widget command} -setup {
+ entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
+ pack .e
+ update
+} -body {
+ .e insert end "This is quite a long text string, so long that it "
+ .e insert end "runs off the end of the window quite a bit."
+ .e xview scroll 24
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {wrong # args: should be ".e xview scroll number units|pages"}
+test entry-3.72 {EntryWidgetCmd procedure, "xview" widget command} -setup {
+ entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
+ pack .e
+} -body {
+ .e insert end "This is quite a long text string, so long that it "
+ .e insert end "runs off the end of the window quite a bit."
+ update
+ .e xview scroll gorp units
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {expected integer but got "gorp"}
+test entry-3.73 {EntryWidgetCmd procedure, "xview" widget command} -setup {
+ entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
+ pack .e
+} -body {
+ .e insert end "This is quite a long text string, so long that it "
+ .e insert end "runs off the end of the window quite a bit."
+ update
+ .e xview moveto 0
+ .e xview scroll 1 pages
+ format {%.6f %.6f} {*}[.e xview]
+} -cleanup {
+ destroy .e
+} -result {0.193548 0.408602}
+test entry-3.74 {EntryWidgetCmd procedure, "xview" widget command} -setup {
+ entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
+ pack .e
+ update
+} -body {
+ .e insert end "This is quite a long text string, so long that it "
+ .e insert end "runs off the end of the window quite a bit."
+ .e xview moveto .9
+ update
+ .e xview scroll -2 p
+ format {%.6f %.6f} {*}[.e xview]
+} -cleanup {
+ destroy .e
+} -result {0.397849 0.612903}
+test entry-3.75 {EntryWidgetCmd procedure, "xview" widget command} -setup {
+ entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
+ pack .e
+} -body {
+ .e insert end "This is quite a long text string, so long that it "
+ .e insert end "runs off the end of the window quite a bit."
+ update
+ .e xview 30
+ update
+ .e xview scroll 2 units
+ .e index @0
+} -cleanup {
+ destroy .e
+} -result {32}
+test entry-3.76 {EntryWidgetCmd procedure, "xview" widget command} -setup {
+ entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
+ pack .e
+} -body {
+ .e insert end "This is quite a long text string, so long that it "
+ .e insert end "runs off the end of the window quite a bit."
+ update
+ .e xview 30
+ update
+ .e xview scroll -1 units
+ .e index @0
+} -cleanup {
+ destroy .e
+} -result {29}
+test entry-3.77 {EntryWidgetCmd procedure, "xview" widget command} -setup {
+ entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
+ pack .e
+} -body {
+ .e insert end "This is quite a long text string, so long that it "
+ .e insert end "runs off the end of the window quite a bit."
+ update
+ .e xview scroll 23 foobars
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {bad argument "foobars": must be units or pages}
+test entry-3.78 {EntryWidgetCmd procedure, "xview" widget command} -setup {
+ entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
+ pack .e
+} -body {
+ .e insert end "This is quite a long text string, so long that it "
+ .e insert end "runs off the end of the window quite a bit."
+ update
+ .e xview eat 23 hamburgers
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {unknown option "eat": must be moveto or scroll}
+test entry-3.79 {EntryWidgetCmd procedure, "xview" widget command} -setup {
+ entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
+ pack .e
+ update
+} -body {
+ .e insert end "This is quite a long text string, so long that it "
+ .e insert end "runs off the end of the window quite a bit."
+ .e xview 0
+ update
+ .e xview -4
+ .e index @0
+} -cleanup {
+ destroy .e
+} -result {0}
+test entry-3.80 {EntryWidgetCmd procedure, "xview" widget command} -setup {
+ entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
+ pack .e
+} -body {
+ .e insert end "This is quite a long text string, so long that it "
+ .e insert end "runs off the end of the window quite a bit."
+ update
+ .e xview 300
+ .e index @0
+} -cleanup {
+ destroy .e
+} -result {73}
+test entry-3.86 {EntryWidgetCmd procedure, "xview" widget command} -setup {
+ entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
+ pack .e
+} -body {
+ .e insert end "This is quite a long text string, so long that it "
+ .e insert end "runs off the end of the window quite a bit."
+ .e insert 10 \u4e4e
+ update
+# UTF
+# If Tcl_NumUtfChars wasn't used, wrong answer would be:
+# 0.106383 0.117021 0.117021
+ set x {}
+ .e xview moveto .1
+ lappend x [format {%.6f} [lindex [.e xview] 0]]
+ .e xview moveto .11
+ lappend x [format {%.6f} [lindex [.e xview] 0]]
+ .e xview moveto .12
+ lappend x [format {%.6f} [lindex [.e xview] 0]]
+} -cleanup {
+ destroy .e
+} -result {0.095745 0.106383 0.117021}
+
+test entry-3.82 {EntryWidgetCmd procedure} -setup {
+ entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
+ pack .e
+ update
+} -body {
+ .e gorp
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {bad option "gorp": must be bbox, cget, configure, delete, get, icursor, index, insert, scan, selection, validate, or xview}
+
+# The test below doesn't actually check anything directly, but if run
+# with Purify or some other memory-allocation-checking program it will
+# ensure that resources get properly freed.
+
+test entry-4.1 {DestroyEntry procedure} -body {
+ entry .e -textvariable x -show *
+ pack .e
+ .e insert end "Sample text"
+ update
+ destroy .e
+} -result {}
+
+test entry-5.1 {ConfigureEntry procedure, -textvariable} -body {
+ set x 12345
+ entry .e -textvariable x
+ .e get
+} -cleanup {
+ destroy .e
+} -result {12345}
+test entry-5.2 {ConfigureEntry procedure, -textvariable} -body {
+ set x 12345
+ entry .e -textvariable x
+ set y abcde
+ .e configure -textvariable y
+ set x 54321
+ .e get
+} -cleanup {
+ destroy .e
+} -result {abcde}
+test entry-5.3 {ConfigureEntry procedure, -textvariable} -setup {
+ unset -nocomplain x
+ entry .e
+} -body {
+ .e insert 0 "Some text"
+ .e configure -textvariable x
+ return $x
+} -cleanup {
+ destroy .e
+} -result {Some text}
+test entry-5.4 {ConfigureEntry procedure, -textvariable} -setup {
+ unset -nocomplain x
+ entry .e
+} -body {
+ trace variable x w override
+ .e insert 0 "Some text"
+ .e configure -textvariable x
+ list $x [.e get]
+} -cleanup {
+ destroy .e
+ trace vdelete x w override
+ unset x;
+} -result {12345 12345}
+
+test entry-5.5 {ConfigureEntry procedure} -setup {
+ set x {}
+ entry .e1
+ entry .e2
+} -body {
+ .e2 insert end "This is some sample text"
+ .e1 configure -exportselection false
+ .e1 insert end "0123456789"
+ pack .e1 .e2
+ .e2 select from 0
+ .e2 select to 10
+ lappend x [selection get]
+ .e1 select from 1
+ .e1 select to 5
+ lappend x [selection get]
+ .e1 configure -exportselection 1
+ lappend x [selection get]
+ return $x
+} -cleanup {
+ destroy .e1 .e2
+} -result {{This is so} {This is so} 1234}
+test entry-5.6 {ConfigureEntry procedure} -setup {
+ entry .e
+ pack .e
+} -body {
+ .e insert end "0123456789"
+ .e select from 1
+ .e select to 5
+ .e configure -exportselection 0
+ selection get
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {PRIMARY selection doesn't exist or form "STRING" not defined}
+test entry-5.6.1 {ConfigureEntry procedure} -setup {
+ entry .e
+ pack .e
+} -body {
+ .e insert end "0123456789"
+ .e select from 1
+ .e select to 5
+ .e configure -exportselection 0
+ catch {selection get}
+ list [.e index sel.first] [.e index sel.last]
+} -cleanup {
+ destroy .e
+} -result {1 5}
+
+test entry-5.7 {ConfigureEntry procedure} -setup {
+ entry .e -font {Helvetica -12} -borderwidth 2 -highlightthickness 2
+ pack .e
+} -body {
+ .e configure -font {Courier -12} -width 4 -xscrollcommand scroll
+ .e insert end "01234567890"
+ update
+ .e configure -width 5
+ format {%.6f %.6f} {*}$scrollInfo
+} -cleanup {
+ destroy .e
+} -result {0.000000 0.363636}
+
+
+test entry-5.8 {ConfigureEntry procedure} -constraints {
+ fonts
+} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2
+ pack .e
+} -body {
+ .e configure -width 0 -font {Helvetica -12}
+ .e insert end "0123"
+ update
+ .e configure -font {Helvetica -24}
+ update
+ winfo geom .e
+} -cleanup {
+ destroy .e
+} -result {62x37+0+0}
+test entry-5.9 {ConfigureEntry procedure} -constraints {
+ fonts
+} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2
+ pack .e
+} -body {
+ .e configure -font {Courier -12} -bd 2 -relief raised
+ .e insert end "0123"
+ update
+ list [.e index @10] [.e index @11] [.e index @12] [.e index @13]
+} -cleanup {
+ destroy .e
+} -result {0 0 1 1}
+test entry-5.10 {ConfigureEntry procedure} -constraints {
+ fonts
+} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2
+ pack .e
+} -body {
+ .e configure -font {Courier -12} -bd 2 -relief flat
+ .e insert end "0123"
+ update
+ list [.e index @10] [.e index @11] [.e index @12] [.e index @13]
+} -cleanup {
+ destroy .e
+} -result {0 0 1 1}
+test entry-5.11 {ConfigureEntry procedure} -setup {
+ entry .e -borderwidth 2 -highlightthickness 2
+ pack .e
+} -body {
+# If "0" in selected font had 0 width, caused divide-by-zero error.
+ .e configure -font {{open look glyph}}
+ .e scan dragto 30
+ update
+} -cleanup {
+ destroy .e
+} -result {}
+
+# No tests for DisplayEntry.
+
+test entry-6.1 {EntryComputeGeometry procedure} -constraints {
+ fonts
+} -setup {
+ entry .e
+ pack .e
+} -body {
+ .e configure -font {Courier -12} -bd 2 -relief raised -width 20 \
+ -highlightthickness 3
+ .e insert end 012\t45
+ update
+ list [.e index @61] [.e index @62]
+} -cleanup {
+ destroy .e
+} -result {3 4}
+test entry-6.2 {EntryComputeGeometry procedure} -constraints {
+ fonts
+} -setup {
+ entry .e
+ pack .e
+} -body {
+ .e configure -font {Courier -12} -bd 2 -relief raised -width 20 \
+ -justify center -highlightthickness 3
+ .e insert end 012\t45
+ update
+ list [.e index @96] [.e index @97]
+} -cleanup {
+ destroy .e
+} -result {3 4}
+test entry-6.3 {EntryComputeGeometry procedure} -constraints {
+ fonts
+} -setup {
+ entry .e
+ pack .e
+} -body {
+ .e configure -font {Courier -12} -bd 2 -relief raised -width 20 \
+ -justify right -highlightthickness 3
+ .e insert end 012\t45
+ update
+ list [.e index @131] [.e index @132]
+} -cleanup {
+ destroy .e
+} -result {3 4}
+test entry-6.4 {EntryComputeGeometry procedure} -setup {
+ entry .e
+ pack .e
+} -body {
+ .e configure -font {Courier -12} -bd 2 -relief raised -width 5
+ .e insert end "01234567890"
+ update
+ .e xview 6
+ .e index @0
+} -cleanup {
+ destroy .e
+} -result {6}
+test entry-6.5 {EntryComputeGeometry procedure} -setup {
+ entry .e -highlightthickness 2
+ pack .e
+} -body {
+ .e configure -font {Courier -12} -bd 2 -relief raised -width 5
+ .e insert end "01234567890"
+ update
+ .e xview 7
+ .e index @0
+} -cleanup {
+ destroy .e
+} -result {6}
+test entry-6.6 {EntryComputeGeometry procedure} -constraints {
+ fonts
+} -setup {
+ entry .e -highlightthickness 2
+ pack .e
+} -body {
+ .e configure -font {Courier -12} -bd 2 -relief raised -width 10
+ .e insert end "01234\t67890"
+ update
+ .e xview 3
+ list [.e index @39] [.e index @40]
+} -cleanup {
+ destroy .e
+} -result {5 6}
+test entry-6.7 {EntryComputeGeometry procedure} -constraints {
+ fonts
+} -setup {
+ entry .e -highlightthickness 2
+ pack .e
+} -body {
+ .e configure -font {Helvetica -24} -bd 3 -relief raised -width 5
+ .e insert end "01234567"
+ update
+ list [winfo reqwidth .e] [winfo reqheight .e]
+} -cleanup {
+ destroy .e
+} -result {77 39}
+test entry-6.8 {EntryComputeGeometry procedure} -constraints {
+ fonts
+} -setup {
+ entry .e -highlightthickness 2
+ pack .e
+} -body {
+ .e configure -font {Helvetica -24} -bd 3 -relief raised -width 0
+ .e insert end "01234567"
+ update
+ list [winfo reqwidth .e] [winfo reqheight .e]
+} -cleanup {
+ destroy .e
+} -result {116 39}
+test entry-6.9 {EntryComputeGeometry procedure} -constraints {
+ fonts
+} -setup {
+ entry .e -highlightthickness 2
+ pack .e
+} -body {
+ .e configure -font {Helvetica -24} -bd 3 -relief raised -width 0
+ update
+ list [winfo reqwidth .e] [winfo reqheight .e]
+} -cleanup {
+ destroy .e
+} -result {25 39}
+test entry-6.10 {EntryComputeGeometry procedure} -constraints {
+ unix fonts
+} -setup {
+ entry .e -highlightthickness 2 -font {Helvetica -12}
+ pack .e
+} -body {
+ .e configure -bd 1 -relief raised -width 0 -show .
+ .e insert 0 12345
+ update
+ set x [winfo reqwidth .e]
+ .e configure -show X
+ lappend x [winfo reqwidth .e]
+ .e configure -show ""
+ lappend x [winfo reqwidth .e]
+} -cleanup {
+ destroy .e
+} -result {23 53 43}
+test entry-6.11 {EntryComputeGeometry procedure} -constraints {
+ win
+} -setup {
+ entry .e -highlightthickness 2
+ pack .e
+} -body {
+ .e configure -bd 1 -relief raised -width 0 -show . -font {helvetica 12}
+ .e insert 0 12345
+ update
+ set x1 [winfo reqwidth .e]
+ set x2 [expr {8+5*[font measure {helvetica 12} .]}]
+ set x [expr {$x1 eq $x2}]
+ .e configure -show X
+ set x1 [winfo reqwidth .e]
+ set x2 [expr {8+5*[font measure {helvetica 12} X]}]
+ lappend x [expr {$x1 eq $x2}]
+ .e configure -show ""
+ set x1 [winfo reqwidth .e]
+ set x2 [expr {8+[font measure {helvetica 12} 12345]}]
+ lappend x [expr {$x1 eq $x2}]
+} -cleanup {
+ destroy .e
+} -result {1 1 1}
+test entry-6.12 {EntryComputeGeometry procedure} -constraints {
+ fonts
+} -setup {
+ catch {destroy .e}
+ entry .e -font {Courier -12} -bd 2 -relief raised -width 20
+ pack .e
+} -body {
+ .e insert end "012\t456\t"
+ update
+ list [.e index @80] [.e index @81] [.e index @115] [.e index @116]
+} -cleanup {
+ destroy .e
+} -result {6 7 7 8}
+
+
+test entry-7.1 {InsertChars procedure} -setup {
+ unset -nocomplain contents
+ entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
+ pack .e
+ focus .e
+} -body {
+ .e configure -textvariable contents -xscrollcommand scroll
+ .e insert 0 abcde
+ .e insert 2 XXX
+ update
+ list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]
+} -cleanup {
+ destroy .e
+} -result {abXXXcde abXXXcde {0.000000 1.000000}}
+
+test entry-7.2 {InsertChars procedure} -setup {
+ unset -nocomplain contents
+ entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
+ pack .e
+ focus .e
+} -body {
+ .e configure -textvariable contents -xscrollcommand scroll
+ .e insert 0 abcde
+ .e insert 500 XXX
+ update
+ list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]
+} -cleanup {
+ destroy .e
+} -result {abcdeXXX abcdeXXX {0.000000 1.000000}}
+test entry-7.3 {InsertChars procedure} -setup {
+ entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
+ pack .e
+} -body {
+ .e insert 0 0123456789
+ .e select from 2
+ .e select to 6
+ .e insert 2 XXX
+ set x "[.e index sel.first] [.e index sel.last]"
+ .e select to 8
+ lappend x [.e index sel.first] [.e index sel.last]
+} -cleanup {
+ destroy .e
+} -result {5 9 5 8}
+test entry-7.4 {InsertChars procedure} -setup {
+ entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
+ pack .e
+} -body {
+ .e insert 0 0123456789
+ .e select from 2
+ .e select to 6
+ .e insert 3 XXX
+ set x "[.e index sel.first] [.e index sel.last]"
+ .e select to 8
+ lappend x [.e index sel.first] [.e index sel.last]
+} -cleanup {
+ destroy .e
+} -result {2 9 2 8}
+test entry-7.5 {InsertChars procedure} -setup {
+ entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
+ pack .e
+} -body {
+ .e insert 0 0123456789
+ .e select from 2
+ .e select to 6
+ .e insert 5 XXX
+ set x "[.e index sel.first] [.e index sel.last]"
+ .e select to 8
+ lappend x [.e index sel.first] [.e index sel.last]
+} -cleanup {
+ destroy .e
+} -result {2 9 2 8}
+test entry-7.6 {InsertChars procedure} -setup {
+ entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
+ pack .e
+} -body {
+ .e insert 0 0123456789
+ .e select from 2
+ .e select to 6
+ .e insert 6 XXX
+ set x "[.e index sel.first] [.e index sel.last]"
+ .e select to 5
+ lappend x [.e index sel.first] [.e index sel.last]
+} -cleanup {
+ destroy .e
+} -result {2 6 2 5}
+test entry-7.7 {InsertChars procedure} -setup {
+ entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
+ pack .e
+} -body {
+ .e configure -xscrollcommand scroll
+ .e insert 0 0123456789
+ .e icursor 4
+ .e insert 4 XXX
+ .e index insert
+} -cleanup {
+ destroy .e
+} -result {7}
+test entry-7.8 {InsertChars procedure} -setup {
+ entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
+ pack .e
+} -body {
+ .e insert 0 0123456789
+ .e icursor 4
+ .e insert 5 XXX
+ .e index insert
+} -cleanup {
+ destroy .e
+} -result {4}
+test entry-7.9 {InsertChars procedure} -setup {
+ entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
+ pack .e
+} -body {
+ .e insert 0 "This is a very long string"
+ update
+ .e xview 4
+ .e insert 3 XXX
+ .e index @0
+} -cleanup {
+ destroy .e
+} -result {7}
+test entry-7.10 {InsertChars procedure} -setup {
+ entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
+ pack .e
+} -body {
+ .e insert 0 "This is a very long string"
+ update
+ .e xview 4
+ .e insert 4 XXX
+ .e index @0
+} -cleanup {
+ destroy .e
+} -result {4}
+
+test entry-7.11 {InsertChars procedure} -constraints {
+ fonts
+} -setup {
+ entry .e -width 0 -font {Courier -12} -highlightthickness 2 -bd 2
+ pack .e
+} -body {
+ .e insert 0 "xyzzy"
+ update
+ .e insert 2 00
+ winfo reqwidth .e
+} -cleanup {
+ destroy .e
+} -result {59}
+
+test entry-8.1 {DeleteChars procedure} -setup {
+ unset -nocomplain contents
+ entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
+ pack .e
+ focus .e
+} -body {
+ .e configure -textvariable contents -xscrollcommand scroll
+ .e insert 0 abcde
+ .e delete 2 4
+ update
+ list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]
+} -cleanup {
+ destroy .e
+} -result {abe abe {0.000000 1.000000}}
+test entry-8.2 {DeleteChars procedure} -setup {
+ unset -nocomplain contents
+ entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
+ pack .e
+ focus .e
+} -body {
+ .e configure -textvariable contents -xscrollcommand scroll
+ .e insert 0 abcde
+ .e delete -2 2
+ update
+ list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]
+} -cleanup {
+ destroy .e
+} -result {cde cde {0.000000 1.000000}}
+test entry-8.3 {DeleteChars procedure} -setup {
+ unset -nocomplain contents
+ entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
+ pack .e
+ focus .e
+} -body {
+ .e configure -textvariable contents -xscrollcommand scroll
+ .e insert 0 abcde
+ .e delete 3 1000
+ update
+ list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]
+} -cleanup {
+ destroy .e
+} -result {abc abc {0.000000 1.000000}}
+test entry-8.4 {DeleteChars procedure} -setup {
+ entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
+ pack .e
+ focus .e
+} -body {
+ .e insert 0 0123456789abcde
+ .e select from 3
+ .e select to 8
+ .e delete 1 3
+ update
+ set x "[.e index sel.first] [.e index sel.last]"
+ .e select to 5
+ lappend x [.e index sel.first] [.e index sel.last]
+} -cleanup {
+ destroy .e
+} -result {1 6 1 5}
+test entry-8.5 {DeleteChars procedure} -setup {
+ entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
+ pack .e
+ focus .e
+} -body {
+ .e insert 0 0123456789abcde
+ .e select from 3
+ .e select to 8
+ .e delete 1 4
+ update
+ set x "[.e index sel.first] [.e index sel.last]"
+ .e select to 4
+ lappend x [.e index sel.first] [.e index sel.last]
+} -cleanup {
+ destroy .e
+} -result {1 5 1 4}
+test entry-8.6 {DeleteChars procedure} -setup {
+ entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
+ pack .e
+ focus .e
+} -body {
+ .e insert 0 0123456789abcde
+ .e select from 3
+ .e select to 8
+ .e delete 1 7
+ update
+ set x "[.e index sel.first] [.e index sel.last]"
+ .e select to 5
+ lappend x [.e index sel.first] [.e index sel.last]
+} -cleanup {
+ destroy .e
+} -result {1 2 1 5}
+test entry-8.7 {DeleteChars procedure} -setup {
+ entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
+ pack .e
+ focus .e
+} -body {
+ .e insert 0 0123456789abcde
+ .e select from 3
+ .e select to 8
+ .e delete 1 8
+ update
+ .e index sel.first
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {selection isn't in widget .e}
+test entry-8.8 {DeleteChars procedure} -setup {
+ entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
+ pack .e
+ focus .e
+} -body {
+ .e insert 0 0123456789abcde
+ .e select from 3
+ .e select to 8
+ .e delete 3 7
+ update
+ set x "[.e index sel.first] [.e index sel.last]"
+ .e select to 8
+ lappend x [.e index sel.first] [.e index sel.last]
+} -cleanup {
+ destroy .e
+} -result {3 4 3 8}
+test entry-8.9 {DeleteChars procedure} -setup {
+ entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
+ pack .e
+} -body {
+ .e insert 0 0123456789abcde
+ .e select from 3
+ .e select to 8
+ .e delete 3 8
+ update
+ .e index sel.first
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {selection isn't in widget .e}
+test entry-8.10 {DeleteChars procedure} -setup {
+ entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
+ pack .e
+ focus .e
+} -body {
+ .e insert 0 0123456789abcde
+ .e select from 8
+ .e select to 3
+ .e delete 5 8
+ update
+ set x "[.e index sel.first] [.e index sel.last]"
+ .e select to 8
+ lappend x [.e index sel.first] [.e index sel.last]
+} -cleanup {
+ destroy .e
+} -result {3 5 5 8}
+test entry-8.11 {DeleteChars procedure} -setup {
+ entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
+ pack .e
+ focus .e
+} -body {
+ .e insert 0 0123456789abcde
+ .e select from 8
+ .e select to 3
+ .e delete 8 10
+ update
+ set x "[.e index sel.first] [.e index sel.last]"
+ .e select to 4
+ lappend x [.e index sel.first] [.e index sel.last]
+} -cleanup {
+ destroy .e
+} -result {3 8 4 8}
+test entry-8.12 {DeleteChars procedure} -setup {
+ entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
+ pack .e
+ focus .e
+} -body {
+ .e insert 0 0123456789abcde
+ .e icursor 4
+ .e delete 1 4
+ update
+ .e index insert
+} -cleanup {
+ destroy .e
+} -result {1}
+test entry-8.13 {DeleteChars procedure} -setup {
+ entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
+ pack .e
+ focus .e
+} -body {
+ .e insert 0 0123456789abcde
+ .e icursor 4
+ .e delete 1 5
+ update
+ .e index insert
+} -cleanup {
+ destroy .e
+} -result {1}
+test entry-8.14 {DeleteChars procedure} -setup {
+ entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
+ pack .e
+ focus .e
+} -body {
+ .e insert 0 0123456789abcde
+ .e icursor 4
+ .e delete 4 6
+ update
+ .e index insert
+} -cleanup {
+ destroy .e
+} -result {4}
+test entry-8.15 {DeleteChars procedure} -setup {
+ entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
+ pack .e
+ focus .e
+} -body {
+ .e insert 0 "This is a very long string"
+ .e xview 4
+ .e delete 1 4
+ update
+ .e index @0
+} -cleanup {
+ destroy .e
+} -result {1}
+test entry-8.16 {DeleteChars procedure} -setup {
+ entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
+ pack .e
+ focus .e
+} -body {
+ .e insert 0 "This is a very long string"
+ .e xview 4
+ .e delete 1 5
+ update
+ .e index @0
+} -cleanup {
+ destroy .e
+} -result {1}
+test entry-8.17 {DeleteChars procedure} -setup {
+ entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
+ pack .e
+ focus .e
+} -body {
+ .e insert 0 "This is a very long string"
+ .e xview 4
+ .e delete 4 6
+ update
+ .e index @0
+} -cleanup {
+ destroy .e
+} -result {4}
+test entry-8.18 {DeleteChars procedure} -setup {
+ entry .e -width 0 -font {Courier -12} -highlightthickness 2 -bd 2
+ pack .e
+ focus .e
+} -body {
+ .e insert 0 "xyzzy"
+ update
+ .e delete 2 4
+ winfo reqwidth .e
+} -cleanup {
+ destroy .e
+} -result {31}
+
+test entry-9.1 {EntryValueChanged procedure} -setup {
+ unset -nocomplain x
+} -body {
+ trace variable x w override
+ entry .e -textvariable x -width 0
+ .e insert 0 foo
+ list $x [.e get]
+} -cleanup {
+ destroy .e
+ trace vdelete x w override
+ unset x
+} -result {12345 12345}
+
+
+test entry-10.1 {EntrySetValue procedure} -constraints fonts -body {
+ set x abcde
+ set y ab
+ entry .e -font {Helvetica -12} -highlightthickness 2 -bd 2 -width 0
+ pack .e
+ .e configure -textvariable x
+ .e configure -textvariable y
+ update
+ list [.e get] [winfo reqwidth .e]
+} -cleanup {
+ destroy .e
+} -result {ab 24}
+test entry-10.2 {EntrySetValue procedure, updating selection} -setup {
+ unset -nocomplain x
+ entry .e -font {Helvetica -12} -highlightthickness 2 -bd 2
+ pack .e
+} -body {
+ .e configure -textvariable x
+ .e insert 0 "abcdefghjklmnopqrstu"
+ .e selection range 4 10
+ set x "a"
+ .e index sel.first
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {selection isn't in widget .e}
+test entry-10.3 {EntrySetValue procedure, updating selection} -setup {
+ unset -nocomplain x
+ entry .e -font {Helvetica -12} -highlightthickness 2 -bd 2
+ pack .e
+} -body {
+ .e configure -textvariable x
+ .e insert 0 "abcdefghjklmnopqrstu"
+ .e selection range 4 10
+ set x "abcdefg"
+ list [.e index sel.first] [.e index sel.last]
+} -cleanup {
+ destroy .e
+} -result {4 7}
+test entry-10.4 {EntrySetValue procedure, updating selection} -setup {
+ unset -nocomplain x
+ entry .e -font {Helvetica -12} -highlightthickness 2 -bd 2
+ pack .e
+} -body {
+ .e configure -textvariable x
+ .e insert 0 "abcdefghjklmnopqrstu"
+ .e selection range 4 10
+ set x "abcdefghijklmn"
+ list [.e index sel.first] [.e index sel.last]
+} -cleanup {
+ destroy .e
+} -result {4 10}
+test entry-10.5 {EntrySetValue procedure, updating display position} -setup {
+ unset -nocomplain x
+ entry .e -highlightthickness 2 -bd 2
+ pack .e
+} -body {
+ .e configure -width 10 -font {Courier -12} -textvariable x
+ .e insert 0 "abcdefghjklmnopqrstuvwxyz"
+ .e xview 10
+ update
+ set x "abcdefg"
+ update
+ .e index @0
+} -cleanup {
+ destroy .e
+} -result {0}
+test entry-10.6 {EntrySetValue procedure, updating display position} -setup {
+ unset -nocomplain x
+ entry .e -highlightthickness 2 -bd 2
+ pack .e
+} -body {
+ .e configure -width 10 -font {Courier -12} -textvariable x
+ pack .e
+ .e insert 0 "abcdefghjklmnopqrstuvwxyz"
+ .e xview 10
+ update
+ set x "1234567890123456789012"
+ update
+ .e index @0
+} -cleanup {
+ destroy .e
+} -result {10}
+test entry-10.7 {EntrySetValue procedure, updating insertion cursor} -setup {
+ unset -nocomplain x
+ entry .e -highlightthickness 2 -bd 2
+ pack .e
+ update
+} -body {
+ .e configure -width 10 -font {Courier -12} -textvariable x
+ pack .e
+ .e insert 0 "abcdefghjklmnopqrstuvwxyz"
+ .e icursor 5
+ set x "123"
+ .e index insert
+} -cleanup {
+ destroy .e
+} -result {3}
+test entry-10.8 {EntrySetValue procedure, updating insertion cursor} -setup {
+ unset -nocomplain x
+ entry .e -highlightthickness 2 -bd 2
+ pack .e
+} -body {
+ .e configure -width 10 -font {Courier -12} -textvariable x
+ pack .e
+ .e insert 0 "abcdefghjklmnopqrstuvwxyz"
+ .e icursor 5
+ set x "123456"
+ .e index insert
+} -cleanup {
+ destroy .e
+} -result {5}
+
+test entry-11.1 {EntryEventProc procedure} -setup {
+ entry .e -highlightthickness 2 -bd 2 -font {Helvetica -12}
+ pack .e
+} -body {
+ .e insert 0 abcdefg
+ destroy .e
+ update
+} -cleanup {
+ destroy .e
+} -result {}
+test entry-11.2 {EntryEventProc procedure} -setup {
+ set x {}
+} -body {
+ entry .e1 -fg #112233
+ rename .e1 .e2
+ lappend x [winfo children .]
+ lappend x [.e2 cget -fg]
+ destroy .e1
+ lappend x [info command .e*] [winfo children .]
+} -cleanup {
+ destroy .e1
+} -result {.e1 #112233 {} {}}
+
+test entry-12.1 {EntryCmdDeletedProc procedure} -body {
+ button .b -text "xyz_123"
+ rename .b {}
+ list [info command .b*] [winfo children .]
+} -cleanup {
+ destroy .b
+} -result {{} {}}
+
+
+test entry-13.1 {GetEntryIndex procedure} -setup {
+ entry .e -font {Courier -12} -width 5 -bd 2 -relief sunken
+ pack .e
+} -body {
+ .e insert 0 012345678901234567890
+ .e xview 4
+ update
+ .e index end
+} -cleanup {
+ destroy .e
+} -result {21}
+test entry-13.2 {GetEntryIndex procedure} -body {
+ entry .e
+ .e index abogus
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {bad entry index "abogus"}
+test entry-13.3 {GetEntryIndex procedure} -setup {
+ entry .e -font {Courier -12} -width 5 -bd 2 -relief sunken
+ pack .e
+} -body {
+ .e insert 0 012345678901234567890
+ .e xview 4
+ update
+ .e select from 1
+ .e select to 6
+ .e index anchor
+} -cleanup {
+ destroy .e
+} -result {1}
+test entry-13.4 {GetEntryIndex procedure} -setup {
+ entry .e -font {Courier -12} -width 5 -bd 2 -relief sunken
+ pack .e
+} -body {
+ .e insert 0 012345678901234567890
+ .e xview 4
+ update
+ .e select from 4
+ .e select to 1
+ .e index anchor
+} -cleanup {
+ destroy .e
+} -result {4}
+test entry-13.5 {GetEntryIndex procedure} -setup {
+ entry .e -font {Courier -12} -width 5 -bd 2 -relief sunken
+ pack .e
+} -body {
+ .e insert 0 012345678901234567890
+ .e xview 4
+ update
+ .e select from 3
+ .e select to 15
+ .e select adjust 4
+ .e index anchor
+} -cleanup {
+ destroy .e
+} -result {15}
+test entry-13.6 {GetEntryIndex procedure} -setup {
+ entry .e
+} -body {
+ .e index ebogus
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {bad entry index "ebogus"}
+test entry-13.7 {GetEntryIndex procedure} -setup {
+ entry .e -font {Courier -12} -width 5 -bd 2 -relief sunken
+ pack .e
+} -body {
+ .e insert 0 012345678901234567890
+ .e xview 4
+ update
+ .e icursor 2
+ .e index insert
+} -cleanup {
+ destroy .e
+} -result {2}
+test entry-13.8 {GetEntryIndex procedure} -setup {
+ entry .e
+} -body {
+ .e index ibogus
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {bad entry index "ibogus"}
+test entry-13.9 {GetEntryIndex procedure} -setup {
+ entry .e -font {Courier -12} -width 5 -bd 2 -relief sunken
+ pack .e
+} -body {
+ .e insert 0 012345678901234567890
+ .e xview 4
+ update
+ .e select from 1
+ .e select to 6
+ list [.e index sel.first] [.e index sel.last]
+} -cleanup {
+ destroy .e
+} -result {1 6}
+
+
+
+
+
+
+test entry-13.10 {GetEntryIndex procedure} -constraints x11 -body {
+# On unix, when selection is cleared, entry widget's internal
+# selection range is reset.
+# Previous settings:
+ entry .e -font {Courier -12} -width 5 -bd 2 -relief sunken
+ pack .e
+ .e insert 0 012345678901234567890
+ .e xview 4
+ update
+ .e select from 1
+ .e select to 6
+ list [.e index sel.first] [.e index sel.last]
+# Testing:
+ selection clear .e
+ .e index sel.first
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {selection isn't in widget .e}
+
+test entry-13.11 {GetEntryIndex procedure} -constraints aquaOrWin32 -body {
+# On mac and pc, when selection is cleared, entry widget remembers
+# last selected range. When selection ownership is restored to
+# entry, the old range will be rehighlighted.
+# Previous settings:
+ entry .e -font {Courier -12} -width 5 -bd 2 -relief sunken
+ pack .e
+ .e insert 0 012345678901234567890
+ .e xview 4
+ update
+ .e select from 1
+ .e select to 6
+ list [.e index sel.first] [.e index sel.last]
+# Testing:
+ selection clear .e
+ catch {selection get}
+ .e index sel.first
+} -cleanup {
+ destroy .e
+} -result {1}
+
+test entry-13.12 {GetEntryIndex procedure} -constraints x11 -body {
+# Previous settings:
+ entry .e -font {Courier -12} -width 5 -bd 2 -relief sunken
+ pack .e
+ .e insert 0 012345678901234567890
+ .e xview 4
+ update
+ .e select from 1
+ .e select to 6
+ list [.e index sel.first] [.e index sel.last]
+# Testing:
+ selection clear .e
+ .e index sbogus
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {selection isn't in widget .e}
+
+# why when string in .e index changed to not beginning with s,
+# it behaves differently?
+test entry-13.12.1 {GetEntryIndex procedure} -constraints unix -body {
+# Previous settings:
+ entry .e -font {Courier -12} -width 5 -bd 2 -relief sunken
+ pack .e
+ .e insert 0 012345678901234567890
+ .e xview 4
+ update
+ .e select from 1
+ .e select to 6
+ list [.e index sel.first] [.e index sel.last]
+# Testing:
+ selection clear .e
+ .e index bogus
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {bad entry index "bogus"}
+
+test entry-13.13 {GetEntryIndex procedure} -constraints win -body {
+# Previous settings:
+ entry .e -font {Courier -12} -width 5 -bd 2 -relief sunken
+ pack .e
+ .e insert 0 012345678901234567890
+ .e xview 4
+ update
+ .e select from 1
+ .e select to 6
+ list [.e index sel.first] [.e index sel.last]
+# Testing:
+ selection clear .e
+ .e index sbogus
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {bad entry index "sbogus"}
+
+test entry-13.14 {GetEntryIndex procedure} -constraints win -body {
+# On mac and pc, when selection is cleared, entry widget remembers
+# last selected range. When selection ownership is restored to
+# entry, the old range will be rehighlighted.
+# Previous settings:
+ entry .e -font {Courier -12} -width 5 -bd 2 -relief sunken
+ pack .e
+ .e insert 0 012345678901234567890
+ .e xview 4
+ update
+ .e select from 1
+ .e select to 6
+ list [.e index sel.first] [.e index sel.last]
+# Testing:
+ selection clear .e
+ selection get
+} -cleanup {
+ destroy .e
+} -returnCodes error -match glob -result {*}
+
+test entry-13.14.1 {GetEntryIndex procedure} -constraints win -body {
+# On mac and pc, when selection is cleared, entry widget remembers
+# last selected range. When selection ownership is restored to
+# entry, the old range will be rehighlighted.
+# Previous settings:
+ entry .e -font {Courier -12} -width 5 -bd 2 -relief sunken
+ pack .e
+ .e insert 0 012345678901234567890
+ .e xview 4
+ update
+ .e select from 1
+ .e select to 6
+ list [.e index sel.first] [.e index sel.last]
+# Testing:
+ selection clear .e
+ catch {selection get}
+ .e index sbogus
+} -cleanup {
+ destroy .e
+} -returnCodes error -match glob -result {*}
+
+test entry-13.15 {GetEntryIndex procedure} -body {
+ entry .e
+ selection clear .e
+ .e index @xyz
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {bad entry index "@xyz"}
+
+test entry-13.16 {GetEntryIndex procedure} -constraints fonts -body {
+ entry .e -width 5 -relief sunken -highlightthickness 2 -bd 2\
+ -font {Courier -12}
+ pack .e
+ .e insert 0 012345678901234567890
+ .e xview 4
+ update
+ .e index @4
+} -cleanup {
+ destroy .e
+} -result {4}
+test entry-13.17 {GetEntryIndex procedure} -constraints fonts -body {
+ entry .e -width 5 -relief sunken -highlightthickness 2 -bd 2\
+ -font {Courier -12}
+ pack .e
+ .e insert 0 012345678901234567890
+ .e xview 4
+ update
+ .e index @11
+} -cleanup {
+ destroy .e
+} -result {4}
+test entry-13.18 {GetEntryIndex procedure} -constraints fonts -body {
+ entry .e -width 5 -relief sunken -highlightthickness 2 -bd 2\
+ -font {Courier -12}
+ pack .e
+ .e insert 0 012345678901234567890
+ .e xview 4
+ update
+ .e index @12
+} -cleanup {
+ destroy .e
+} -result {5}
+test entry-13.19 {GetEntryIndex procedure} -constraints fonts -body {
+ entry .e -width 5 -relief sunken -highlightthickness 2 -bd 2\
+ -font {Courier -12}
+ pack .e
+ .e insert 0 012345678901234567890
+ .e xview 4
+ update
+ .e index @[expr {[winfo width .e] - 6}]
+} -cleanup {
+ destroy .e
+} -result {8}
+test entry-13.20 {GetEntryIndex procedure} -constraints fonts -body {
+ entry .e -width 5 -relief sunken -highlightthickness 2 -bd 2\
+ -font {Courier -12}
+ pack .e
+ .e insert 0 012345678901234567890
+ .e xview 4
+ update
+ .e index @[expr {[winfo width .e] - 5}]
+} -cleanup {
+ destroy .e
+} -result {9}
+test entry-13.21 {GetEntryIndex procedure} -body {
+ entry .e -width 5 -relief sunken -highlightthickness 2 -bd 2\
+ -font {Courier -12}
+ pack .e
+ .e insert 0 012345678901234567890
+ .e xview 4
+ update
+ .e index @1000
+} -cleanup {
+ destroy .e
+} -result {9}
+test entry-13.22 {GetEntryIndex procedure} -setup {
+ entry .e
+ pack .e
+ update
+} -body {
+ .e index 1xyz
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {bad entry index "1xyz"}
+test entry-13.23 {GetEntryIndex procedure} -body {
+ entry .e -width 5 -relief sunken -highlightthickness 2 -bd 2\
+ -font {Courier -12}
+ pack .e
+ .e insert 0 012345678901234567890
+ .e xview 4
+ update
+ .e index -10
+} -cleanup {
+ destroy .e
+} -result {0}
+test entry-13.24 {GetEntryIndex procedure} -body {
+ entry .e -width 5 -relief sunken -highlightthickness 2 -bd 2\
+ -font {Courier -12}
+ pack .e
+ .e insert 0 012345678901234567890
+ .e xview 4
+ update
+ .e index 12
+} -cleanup {
+ destroy .e
+} -result {12}
+test entry-13.25 {GetEntryIndex procedure} -body {
+ entry .e -width 5 -relief sunken -highlightthickness 2 -bd 2\
+ -font {Courier -12}
+ pack .e
+ .e insert 0 012345678901234567890
+ .e xview 4
+ update
+ .e index 49
+} -cleanup {
+ destroy .e
+} -result {21}
+test entry-13.26 {GetEntryIndex procedure} -constraints fonts -body {
+ entry .e -highlightthickness 2 -bd 2 -font {Helvetica -12}
+ selection clear .e
+ .e configure -show .
+ .e insert 0 XXXYZZY
+ pack .e
+ update
+ list [.e index @7] [.e index @8]
+} -cleanup {
+ destroy .e
+} -result {0 1}
+
+# XXX Still need to write tests for EntryScanTo and EntrySelectTo.
+
+
+test entry-14.1 {EntryFetchSelection procedure} -body {
+ entry .e
+ .e insert end "This is a test string"
+ .e select from 1
+ .e select to 18
+ selection get
+} -cleanup {
+ destroy .e
+} -result {his is a test str}
+test entry-14.2 {EntryFetchSelection procedure} -body {
+ entry .e -show *
+ .e insert end "This is a test string"
+ .e select from 1
+ .e select to 18
+ selection get
+} -cleanup {
+ destroy .e
+} -result {*****************}
+test entry-14.3 {EntryFetchSelection procedure} -setup {
+ set x {}
+ for {set i 1} {$i <= 500} {incr i} {
+ append x "This is line $i, out of 500\n"
+}
+} -body {
+ entry .e
+ .e insert end $x
+ .e select from 0
+ .e select to end
+ string compare [selection get] $x
+} -cleanup {
+ destroy .e
+} -result {0}
+
+test entry-15.1 {EntryLostSelection} -body {
+ entry .e
+ .e insert 0 "Text"
+ .e select from 0
+ .e select to 4
+ set result [selection get]
+ selection clear
+ .e select from 0
+ .e select to 4
+ lappend result [selection get]
+} -cleanup {
+ destroy .e
+} -result {Text Text}
+
+# is scrollcommand needed here??
+test entry-16.1 {EntryVisibleRange procedure} -constraints fonts -body {
+ entry .e -width 10 -font {Helvetica -12}
+ pack .e
+ update
+ .e insert 0 "............................."
+ format {%.6f %.6f} {*}[.e xview]
+} -cleanup {
+ destroy .e
+} -result {0.000000 0.827586}
+test entry-16.2 {EntryVisibleRange procedure} -constraints {
+ unix fonts
+} -body {
+ entry .e -show X -width 10 -font {Helvetica -12}
+ pack .e
+ update
+ .e insert 0 "............................."
+ format {%.6f %.6f} {*}[.e xview]
+} -cleanup {
+ destroy .e
+} -result {0.000000 0.275862}
+test entry-16.3 {EntryVisibleRange procedure} -constraints {
+ win
+} -body {
+ entry .e -show . -width 10 -font {Helvetica -12}
+ pack .e
+ update
+ .e insert 0 XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ format {%.6f %.6f} {*}[.e xview]
+} -cleanup {
+ destroy .e
+} -result {0.000000 0.827586}
+test entry-16.4 {EntryVisibleRange procedure} -body {
+ entry .e -show ""
+ format {%.6f %.6f} {*}[.e xview]
+} -cleanup {
+ destroy .e
+} -result {0.000000 1.000000}
+
+
+test entry-17.1 {EntryUpdateScrollbar procedure} -body {
+ entry .e -width 10 -xscrollcommand scroll -font {Courier -12}
+ pack .e
+ .e delete 0 end
+ .e insert 0 123
+ update
+ format {%.6f %.6f} {*}$scrollInfo
+} -cleanup {
+ destroy .e
+} -result {0.000000 1.000000}
+test entry-17.2 {EntryUpdateScrollbar procedure} -body {
+ entry .e -width 10 -xscrollcommand scroll -font {Courier -12}
+ pack .e
+ .e insert 0 0123456789abcdef
+ .e xview 3
+ update
+ format {%.6f %.6f} {*}$scrollInfo
+} -cleanup {
+ destroy .e
+} -result {0.187500 0.812500}
+test entry-17.3 {EntryUpdateScrollbar procedure} -body {
+ entry .e -width 10 -xscrollcommand scroll -font {Courier -12}
+ pack .e
+ .e insert 0 abcdefghijklmnopqrs
+ .e xview 6
+ update
+ format {%.6f %.6f} {*}$scrollInfo
+} -cleanup {
+ destroy .e
+} -result {0.315789 0.842105}
+test entry-17.4 {EntryUpdateScrollbar procedure} -setup {
+ proc bgerror msg {
+ global x
+ set x $msg
+}
+} -body {
+ entry .e -width 5 -xscrollcommand thisisnotacommand
+ pack .e
+ update
+ list $x $errorInfo
+} -cleanup {
+ destroy .e
+ rename bgerror {}
+} -result {{invalid command name "thisisnotacommand"} {invalid command name "thisisnotacommand"
+ while executing
+"thisisnotacommand 0.0 1.0"
+ (horizontal scrolling command executed by .e)}}
+
+
+test entry-18.1 {Entry widget vs hiding} -setup {
+ entry .e
+} -body {
+ set l [interp hidden]
+ interp hide {} .e
+ destroy .e
+ set res1 [list [winfo children .] [interp hidden]]
+ set res2 [list {} $l]
+ expr {$res1 == $res2}
+} -result {1}
+
+##
+## Entry widget VALIDATION tests
+##
+# The validation tests build each one upon the previous, so cascading
+# failures aren't good
+#
+
+# 19.* test cases in previous version highly depended on the previous
+# test cases. This was replaced by inserting recently set configurations
+# that matters for the test case
+test entry-19.1 {entry widget validation} -setup {
+ unset -nocomplain ::e ::vVals
+} -body {
+ entry .e -validate all \
+ -validatecommand [list doval %W %d %i %P %s %S %v %V] \
+ -invalidcommand bell \
+ -textvariable ::e \
+ -background red -foreground white
+ pack .e
+ .e insert 0 a
+ return $::vVals
+} -cleanup {
+ destroy .e
+} -result {.e 1 0 a {} a all key}
+
+test entry-19.2 {entry widget validation} -setup {
+ unset -nocomplain ::e ::vVals
+} -body {
+ entry .e -validate all \
+ -validatecommand [list doval %W %d %i %P %s %S %v %V] \
+ -invalidcommand bell \
+ -textvariable ::e \
+ -background red -foreground white
+ pack .e
+ .e insert 0 a ;# previous settings
+ .e insert 1 b
+ return $::vVals
+} -cleanup {
+ destroy .e
+} -result {.e 1 1 ab a b all key}
+
+test entry-19.3 {entry widget validation} -setup {
+ unset -nocomplain ::e ::vVals
+} -body {
+ entry .e -validate all \
+ -validatecommand [list doval %W %d %i %P %s %S %v %V] \
+ -invalidcommand bell \
+ -textvariable ::e \
+ -background red -foreground white
+ pack .e
+ .e insert 0 ab ;# previous settings
+ .e insert end c
+ return $::vVals
+} -cleanup {
+ destroy .e
+} -result {.e 1 2 abc ab c all key}
+
+test entry-19.4 {entry widget validation} -setup {
+ unset -nocomplain ::e ::vVals
+} -body {
+ entry .e -validate all \
+ -validatecommand [list doval %W %d %i %P %s %S %v %V] \
+ -invalidcommand bell \
+ -textvariable ::e \
+ -background red -foreground white
+ pack .e
+ .e insert 0 abc ;# previous settings
+ .e insert 1 123
+ list $::vVals $::e
+} -cleanup {
+ destroy .e
+} -result {{.e 1 1 a123bc abc 123 all key} a123bc}
+
+test entry-19.5 {entry widget validation} -setup {
+ unset -nocomplain ::e ::vVals
+} -body {
+ entry .e -validate all \
+ -validatecommand [list doval %W %d %i %P %s %S %v %V] \
+ -invalidcommand bell \
+ -textvariable ::e \
+ -background red -foreground white
+ pack .e
+ .e insert 0 a123bc ;# previous settings
+ .e delete 2
+ return $::vVals
+} -cleanup {
+ destroy .e
+} -result {.e 0 2 a13bc a123bc 2 all key}
+
+test entry-19.6 {entry widget validation} -setup {
+ unset -nocomplain ::e ::vVals
+} -body {
+ entry .e -validate all \
+ -validatecommand [list doval %W %d %i %P %s %S %v %V] \
+ -invalidcommand bell \
+ -textvariable ::e \
+ -background red -foreground white
+ pack .e
+ .e insert 0 a13bc ;# previous settings
+ .e configure -validate key
+ .e delete 1 3
+ return $::vVals
+} -cleanup {
+ destroy .e
+} -result {.e 0 1 abc a13bc 13 key key}
+
+test entry-19.7 {entry widget validation} -setup {
+ unset -nocomplain ::e ::vVals
+} -body {
+ entry .e -validate focus \
+ -validatecommand [list doval %W %d %i %P %s %S %v %V] \
+ -invalidcommand bell \
+ -textvariable ::e \
+ -background red -foreground white
+ pack .e
+ .e insert end abc ;# previous settings
+ set ::vVals {}
+ .e insert end d
+ return $::vVals
+} -cleanup {
+ destroy .e
+} -result {}
+
+test entry-19.8 {entry widget validation} -setup {
+ unset -nocomplain ::e ::vVals
+} -body {
+ entry .e -validate all \
+ -validatecommand [list doval %W %d %i %P %s %S %v %V] \
+ -invalidcommand bell \
+ -textvariable ::e \
+ -background red -foreground white
+ pack .e
+ .e configure -validate focus ;# previous settings
+ .e insert end abcd ;# previous settings
+ focus -force .e
+# update necessary to process FocusIn event
+ update
+ return $::vVals
+} -cleanup {
+ destroy .e
+} -result {.e -1 -1 abcd abcd {} focus focusin}
+
+test entry-19.9 {entry widget validation} -setup {
+ unset -nocomplain ::e ::vVals
+} -body {
+ entry .e -validate focus \
+ -validatecommand [list doval %W %d %i %P %s %S %v %V] \
+ -invalidcommand bell \
+ -textvariable ::e \
+ -background red -foreground white
+ pack .e
+ .e insert end abcd ;# previous settings
+ focus -force .e ;# previous settings
+ update ;# previous settings
+# update necessary to process FocusIn event
+ focus -force .
+# update necessary to process FocusOut event
+ update
+ return $::vVals
+} -cleanup {
+ destroy .e
+} -result {.e -1 -1 abcd abcd {} focus focusout}
+
+test entry-19.10 {entry widget validation} -setup {
+ unset -nocomplain ::e ::vVals
+} -body {
+ entry .e -validate all \
+ -validatecommand [list doval %W %d %i %P %s %S %v %V] \
+ -invalidcommand bell \
+ -textvariable ::e \
+ -background red -foreground white
+ pack .e
+ .e insert end abcd ;# previous settings
+ focus -force .e
+# update necessary to process FocusIn event
+ update
+ return $::vVals
+} -cleanup {
+ destroy .e
+} -result {.e -1 -1 abcd abcd {} all focusin}
+
+test entry-19.11 {entry widget validation} -setup {
+ unset -nocomplain ::e ::vVals
+} -body {
+ entry .e -validate all \
+ -validatecommand [list doval %W %d %i %P %s %S %v %V] \
+ -invalidcommand bell \
+ -textvariable ::e \
+ -background red -foreground white
+ pack .e
+ .e insert end abcd ;# previous settings
+ focus -force .e ;# previous settings
+# update necessary to process FocusIn event
+ update ;# previous settings
+ focus -force .
+# update necessary to process FocusOut event
+ update
+ return $::vVals
+} -cleanup {
+ destroy .e
+} -result {.e -1 -1 abcd abcd {} all focusout}
+
+test entry-19.12 {entry widget validation} -setup {
+ unset -nocomplain ::e ::vVals
+} -body {
+ entry .e -validate focusin \
+ -validatecommand [list doval %W %d %i %P %s %S %v %V] \
+ -invalidcommand bell \
+ -textvariable ::e \
+ -background red -foreground white
+ pack .e
+ .e insert 0 abcd ;# previous settings
+ focus -force .e
+# update necessary to process FocusIn event
+ update
+ return $::vVals
+} -cleanup {
+ destroy .e
+} -result {.e -1 -1 abcd abcd {} focusin focusin}
+
+test entry-19.13 {entry widget validation} -setup {
+ unset -nocomplain ::e ::vVals
+} -body {
+ entry .e -validate focusin \
+ -validatecommand [list doval %W %d %i %P %s %S %v %V] \
+ -invalidcommand bell \
+ -textvariable ::e \
+ -background red -foreground white
+ pack .e
+ .e insert end abcd ;# previous settings
+ set ::vVals {}
+ focus -force .
+# update necessary to process FocusOut event
+ update
+ return $::vVals
+} -cleanup {
+ destroy .e
+} -result {}
+
+test entry-19.14 {entry widget validation} -setup {
+ unset -nocomplain ::e ::vVals
+} -body {
+ entry .e -validate focuso \
+ -validatecommand [list doval %W %d %i %P %s %S %v %V] \
+ -invalidcommand bell \
+ -textvariable ::e \
+ -background red -foreground white
+ pack .e
+ .e insert end abcd ;# previous settings
+ set ::vVals {} ;# previous settings
+ focus -force .e
+# update necessary to process FocusIn event
+ update
+ return $::vVals
+} -cleanup {
+ destroy .e
+} -result {}
+
+test entry-19.15 {entry widget validation} -setup {
+ unset -nocomplain ::e ::vVals
+} -body {
+ entry .e -validate focuso \
+ -validatecommand [list doval %W %d %i %P %s %S %v %V] \
+ -invalidcommand bell \
+ -textvariable ::e \
+ -background red -foreground white
+ pack .e
+ .e insert end abcd ;# previous settings
+ set ::vVals {} ;# previous settings
+ focus -force .e ;# previous settings
+# update necessary to process FocusIn event
+ update ;# previous settings
+ focus -force .
+# update necessary to process FocusOut event
+ update
+ return $::vVals
+} -cleanup {
+ destroy .e
+} -result {.e -1 -1 abcd abcd {} focusout focusout}
+
+# the same as 19.16 but added [.e validate] to returned list
+test entry-19.16 {entry widget validation} -setup {
+ unset -nocomplain ::e ::vVals
+} -body {
+ entry .e -validate focuso \
+ -validatecommand [list doval %W %d %i %P %s %S %v %V] \
+ -invalidcommand bell \
+ -textvariable ::e \
+ -background red -foreground white
+ pack .e
+ .e insert end abcd ;# previous settings
+ set ::vVals {} ;# previous settings
+ focus -force .e ;# previous settings
+# update necessary to process FocusIn event
+ update ;# previous settings
+ focus -force .
+# update necessary to process FocusOut event
+ update
+ list [.e validate] $::vVals
+} -cleanup {
+ destroy .e
+} -result {1 {.e -1 -1 abcd abcd {} all forced}}
+
+
+test entry-19.17 {entry widget validation} -setup {
+ unset -nocomplain ::e ::vVals
+} -body {
+ entry .e -validate focuso \
+ -validatecommand [list doval %W %d %i %P %s %S %v %V] \
+ -invalidcommand bell \
+ -textvariable ::e \
+ -background red -foreground white
+ pack .e
+ .e insert end abcd ;# previous settings
+ set ::e newdata
+ list [.e cget -validate] $::vVals
+} -cleanup {
+ destroy .e
+} -result {focusout {.e -1 -1 newdata abcd {} focusout forced}}
+
+
+# proc doval changed - returns 0
+test entry-19.18 {entry widget validation} -setup {
+ unset -nocomplain ::e ::vVals
+} -body {
+ entry .e -validate all \
+ -validatecommand [list doval3 %W %d %i %P %s %S %v %V] \
+ -invalidcommand bell \
+ -textvariable ::e \
+ -background red -foreground white
+ pack .e
+ set ::e newdata ;# previous settings
+ .e configure -validate all
+ set ::e nextdata
+ list [.e cget -validate] $::vVals
+} -cleanup {
+ destroy .e
+} -result {none {.e -1 -1 nextdata newdata {} all forced}}
+
+## This sets validate to none because it shows that we prevent a possible
+## loop condition in the validation, when the entry textvar is also set
+# proc doval2 used
+test entry-19.19 {entry widget validation} -setup {
+ unset -nocomplain ::e ::vVals
+} -body {
+ entry .e -validate all \
+ -validatecommand [list doval3 %W %d %i %P %s %S %v %V] \
+ -invalidcommand bell \
+ -textvariable ::e \
+ -background red -foreground white
+ pack .e
+ set ::e nextdata ;# previous settings
+
+ .e configure -validatecommand [list doval2 %W %d %i %P %s %S %v %V]
+ .e validate
+ list [.e cget -validate] [.e get] $::vVals
+} -cleanup {
+ destroy .e
+} -result {none mydata {.e -1 -1 nextdata nextdata {} all forced}}
+
+## This leaves validate alone because we trigger validation through the
+## textvar (a write trace), and the write during validation triggers
+## nothing (by definition of avoiding loops on var traces). This is
+## one of those "dangerous" conditions where the user will have a
+## different value in the entry widget shown as is in the textvar.
+test entry-19.20 {entry widget validation} -setup {
+ unset -nocomplain ::e ::vVals
+} -body {
+ entry .e -validate all \
+ -validatecommand [list doval %W %d %i %P %s %S %v %V] \
+ -invalidcommand bell \
+ -textvariable ::e \
+ -background red -foreground white
+ pack .e
+ set ::e nextdata ;# previous settings
+ .e configure -validatecommand [list doval2 %W %d %i %P %s %S %v %V] ;# prev
+ .e validate ;# previous settings
+
+ .e configure -validate all
+ set ::e testdata
+ list [.e cget -validate] [.e get] $::e $::vVals
+} -cleanup {
+ destroy .e
+} -result {all testdata mydata {.e -1 -1 testdata mydata {} all forced}}
+##
+## End validation tests
+##
+
+test entry-20.1 {widget deletion while active} -body {
+ entry .e -validate all \
+ -validatecommand { destroy %W ; return 1 } \
+ -invalidcommand bell
+ update
+ .e insert 0 abc
+ winfo exists .e
+} -cleanup {
+ destroy .e
+} -result {0}
+
+test entry-20.2 {widget deletion while active} -body {
+ entry .e -validate all \
+ -validatecommand { return 0 } \
+ -invalidcommand { destroy %W }
+ .e insert 0 abc
+ winfo exists .e
+} -cleanup {
+ destroy .e
+} -result {0}
+
+test entry-20.3 {widget deletion while active} -body {
+ entry .e -validate all \
+ -validatecommand { rename .e {} ; return 1 }
+ .e insert 0 abc
+ winfo exists .e
+} -cleanup {
+ destroy .e
+} -result {0}
+
+test entry-20.4 {widget deletion while active} -body {
+ entry .e -validate all \
+ -validatecommand { return 0 } \
+ -invalidcommand { rename .e {} }
+ .e insert 0 abc
+ winfo exists .e
+} -cleanup {
+ destroy .e
+} -result {0}
+
+test entry-20.5 {widget deletion while active} -body {
+ entry .e -validatecommand { destroy .e ; return 0 }
+ .e validate
+ winfo exists .e
+} -cleanup {
+ destroy .e
+} -result {0}
+
+test entry-20.6 {widget deletion while active} -body {
+ pack [entry .e]
+ update
+ .e config -xscrollcommand { destroy .e }
+ update idle
+ winfo exists .e
+} -cleanup {
+ destroy .e
+} -result {0}
+
+test entry-20.7 {widget deletion with textvariable active} -body {
+# SF bugs 607390 and 617446
+ set FOO init
+ entry .e -textvariable FOO -validate all \
+ -vcmd {%W configure -bg white; format 1}
+ bind .e <Destroy> { set FOO hello }
+ destroy .e
+ winfo exists .e
+} -cleanup {
+ destroy .e
+} -result {0}
+
+
+test entry-21.1 {selection present while disabled, bug 637828} -body {
+ entry .e
+ .e insert end 0123456789
+ .e select from 3
+ .e select to 6
+ set out [.e selection present]
+ .e configure -state disabled
+# still return 1 when disabled, because 'selection get' will work,
+# but selection cannot be changed (new behavior since 8.4)
+ .e select to 9
+ lappend out [.e selection present] [selection get]
+} -cleanup {
+ destroy .e
+} -result {1 1 345}
+
+test entry-22.1 {lost namespaced textvar} -body {
+ namespace eval test { variable foo {a b} }
+ entry .e -textvariable ::test::foo
+ namespace delete test
+ set ::test::foo
+} -cleanup {
+ destroy .e
+} -returnCodes error -result {can't read "::test::foo": no such variable}
+test entry-22.2 {lost namespaced textvar} -body {
+ namespace eval test { variable foo {a b} }
+ entry .e -textvariable ::test::foo
+ namespace delete test
+ catch {.e insert end "more stuff"} result1
+ catch {.e delete 5 end } result2
+ catch {set ::test::foo} result3
+ list [.e get] [.e cget -textvar] $result1 $result2 $result3
+} -cleanup {
+ destroy .e
+} -result [list "a bmo" ::test::foo \
+ {can't set "::test::foo": parent namespace doesn't exist} \
+ {can't set "::test::foo": parent namespace doesn't exist} \
+ {can't read "::test::foo": no such variable}]
+
+test entry-23.1 {error in trace proc attached to the textvariable} -setup {
+ destroy .e
+} -body {
+ trace variable myvar w traceit
+ proc traceit args {error "Intentional error here!"}
+ entry .e -textvariable myvar
+ catch {.e insert end mystring} result1
+ catch {.e delete 0} result2
+ list $result1 $result2
+} -cleanup {
+ destroy .e
+} -result [list {can't set "myvar": Intentional error here!} \
+ {can't set "myvar": Intentional error here!}]
+
+test entry-24.1 {textvariable lives in a non-existing namespace} -setup {
+ destroy .e
+} -body {
+ catch {entry .e -textvariable thisnsdoesntexist::myvar} result1
+ set result1
+} -cleanup {
+ destroy .e
+} -result {can't trace "thisnsdoesntexist::myvar": parent namespace doesn't exist}
+
+test entry-25.1 {Bug [5d991b822e]} {
+ # Want this not to segfault, or write to variable with empty name
+ set var INIT
+ entry .b -textvariable var
+ trace add variable var unset {apply {args {
+ .b configure -textvariable {}
+ }}}
+ pack .b
+ bind .b <Configure> {unset var}
+ update
+ destroy .b
+ info exists {}
+} 0
+test entry-25.2 {Bug [5d991b822e]} {
+ # Want this not to leak traces
+ set var INIT
+ entry .b -textvariable var
+ trace add variable var unset {apply {args {
+ .b configure -textvariable new
+ }}}
+ pack .b
+ bind .b <Configure> {unset -nocomplain var}
+ update
+ destroy .b
+ unset new
+} {}
+
+
+# Gathered comments about lacks
+# XXX Still need to write tests for EntryBlinkProc, EntryFocusProc,
+# and EntryTextVarProc.
+# No tests for DisplayEntry.
+# XXX Still need to write tests for EntryScanTo and EntrySelectTo.
+# No tests for EventuallyRedraw
+
+# option clear
+# cleanup
+cleanupTests
+return
+
+
+
diff --git a/tk8.6/tests/event.test b/tk8.6/tests/event.test
new file mode 100644
index 0000000..39beab4
--- /dev/null
+++ b/tk8.6/tests/event.test
@@ -0,0 +1,872 @@
+# This file is a Tcl script to test the code in tkEvent.c. It is
+# organized in the standard fashion for Tcl tests.
+#
+# Copyright (c) 1994 The Regents of the University of California.
+# Copyright (c) 1994-1995 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+namespace import -force tcltest::test
+
+# XXX This test file is woefully incomplete. Right now it only tests
+# a few of the procedures in tkEvent.c. Please add more tests whenever
+# possible.
+
+# Setup table used to query key events.
+
+proc _init_keypress_lookup {} {
+ global keypress_lookup
+
+ scan A %c start
+ scan Z %c finish
+
+ for {set i $start} {$i <= $finish} {incr i} {
+ set l [format %c $i]
+ set keypress_lookup($l) $l
+ }
+
+ scan a %c start
+ scan z %c finish
+
+ for {set i $start} {$i <= $finish} {incr i} {
+ set l [format %c $i]
+ set keypress_lookup($l) $l
+ }
+
+ scan 0 %c start
+ scan 9 %c finish
+
+ for {set i $start} {$i <= $finish} {incr i} {
+ set l [format %c $i]
+ set keypress_lookup($l) $l
+ }
+
+ # Most punctuation
+ array set keypress_lookup {
+ ! exclam
+ % percent
+ & ampersand
+ ( parenleft
+ ) parenright
+ * asterisk
+ + plus
+ , comma
+ - minus
+ . period
+ / slash
+ : colon
+ < less
+ = equal
+ > greater
+ ? question
+ @ at
+ ^ asciicircum
+ _ underscore
+ | bar
+ ~ asciitilde
+ ' apostrophe
+ }
+ # Characters with meaning to Tcl...
+ array set keypress_lookup [list \
+ \" quotedbl \
+ \# numbersign \
+ \$ dollar \
+ \; semicolon \
+ \[ bracketleft \
+ \\ backslash \
+ \] bracketright \
+ \{ braceleft \
+ \} braceright \
+ " " space \
+ "\n" Return \
+ "\t" Tab]
+}
+
+# Lookup an event in the keypress table.
+# For example:
+# Q -> Q
+# . -> period
+# / -> slash
+# Delete -> Delete
+# Escape -> Escape
+
+proc _keypress_lookup {char} {
+ global keypress_lookup
+
+ if {! [info exists keypress_lookup]} {
+ _init_keypress_lookup
+ }
+
+ if {$char == ""} {
+ error "empty char"
+ }
+
+ if {[info exists keypress_lookup($char)]} {
+ return $keypress_lookup($char)
+ } else {
+ return $char
+ }
+}
+
+# Lookup and generate a pair of KeyPress and KeyRelease events
+
+proc _keypress {win key} {
+ set keysym [_keypress_lookup $key]
+
+ # Force focus to the window before delivering
+ # each event so that a window manager using
+ # a focus follows mouse will not steal away
+ # the focus if the mouse is moved around.
+
+ if {[focus] != $win} {
+ focus -force $win
+ }
+ event generate $win <KeyPress-$keysym>
+ _pause 50
+ if {[focus] != $win} {
+ focus -force $win
+ }
+ event generate $win <KeyRelease-$keysym>
+ _pause 50
+}
+
+# Call _keypress for each character in the given string
+
+proc _keypress_string {win string} {
+ foreach letter [split $string ""] {
+ _keypress $win $letter
+ }
+}
+
+# Delay script execution for a given amount of time
+
+proc _pause {{msecs 1000}} {
+ global _pause
+
+ if {! [info exists _pause(number)]} {
+ set _pause(number) 0
+ }
+
+ set num [incr _pause(number)]
+ set _pause($num) 0
+
+ after $msecs "set _pause($num) 1"
+ vwait _pause($num)
+ unset _pause($num)
+}
+
+# Helper proc to convert index to x y position
+
+proc _text_ind_to_x_y {text ind} {
+ set bbox [$text bbox $ind]
+ if {[llength $bbox] != 4} {
+ error "got bbox \{$bbox\} from $text, index $ind"
+ }
+ foreach {x1 y1 width height} $bbox break
+ set middle_y [expr {$y1 + ($height / 2)}]
+ return [list $x1 $middle_y]
+}
+
+# Return selection only if owned by the given widget
+
+proc _get_selection {widget} {
+ if {[string compare $widget [selection own]] != 0} {
+ return ""
+ }
+ if {[catch {selection get} sel]} {
+ return ""
+ }
+ return $sel
+}
+
+# Begining of the actual tests
+
+test event-1.1 {Tk_HandleEvent procedure, filter events for dead windows} -setup {
+ deleteWindows
+ set x {}
+} -body {
+ button .b -text Test
+ pack .b
+ bindtags .b .b
+ update
+ bind .b <Destroy> {
+ lappend x destroy
+ event generate .b <1>
+ event generate .b <ButtonRelease-1>
+ }
+ bind .b <1> {
+ lappend x button
+ }
+
+ destroy .b
+ return $x
+} -cleanup {
+ deleteWindows
+} -result {destroy}
+test event-1.2 {event generate <Alt-z>} -setup {
+ deleteWindows
+ catch {unset ::event12result}
+} -body {
+ set ::event12result 0
+ pack [entry .e]
+ update
+ bind .e <Alt-z> {set ::event12result "1"}
+
+ focus -force .e
+ event generate .e <Alt-z>
+ destroy .e
+ set ::event12result
+} -cleanup {
+ deleteWindows
+} -result 1
+
+
+test event-2.1(keypress) {type into entry widget and hit Return} -setup {
+ deleteWindows
+} -body {
+ set t [toplevel .t]
+ set e [entry $t.e]
+ pack $e
+ set return_binding 0
+ bind $e <Return> {set return_binding 1}
+ tkwait visibility $e
+ _keypress_string $e HELLO\n
+ list [$e get] $return_binding
+} -cleanup {
+ deleteWindows
+} -result {HELLO 1}
+test event-2.2(keypress) {type into entry widget and then delete some text} -setup {
+ deleteWindows
+} -body {
+ set t [toplevel .t]
+ set e [entry $t.e]
+ pack $e
+ tkwait visibility $e
+ _keypress_string $e MELLO
+ _keypress $e BackSpace
+ _keypress $e BackSpace
+ $e get
+} -cleanup {
+ deleteWindows
+} -result {MEL}
+test event-2.3(keypress) {type into entry widget, triple click, hit Delete key,
+ and then type some more} -setup {
+ deleteWindows
+} -body {
+ set t [toplevel .t]
+ set e [entry $t.e]
+ pack $e
+ tkwait visibility $e
+ _keypress_string $e JUMP
+
+ set result [$e get]
+
+ event generate $e <Enter>
+ for {set i 0} {$i < 3} {incr i} {
+ _pause 100
+ event generate $e <ButtonPress-1>
+ _pause 100
+ event generate $e <ButtonRelease-1>
+ }
+
+ _keypress $e Delete
+ _keypress_string $e UP
+ lappend result [$e get]
+} -cleanup {
+ deleteWindows
+} -result {JUMP UP}
+test event-2.4(keypress) {type into text widget and hit Return} -setup {
+ deleteWindows
+} -body {
+ set t [toplevel .t]
+ set e [text $t.e]
+ pack $e
+ set return_binding 0
+ bind $e <Return> {set return_binding 1}
+ tkwait visibility $e
+ _keypress_string $e HELLO\n
+ list [$e get 1.0 end] $return_binding
+} -cleanup {
+ deleteWindows
+} -result [list "HELLO\n\n" 1]
+test event-2.5(keypress) {type into text widget and then delete some text} -setup {
+ deleteWindows
+} -body {
+ set t [toplevel .t]
+ set e [text $t.e]
+ pack $e
+ tkwait visibility $e
+ _keypress_string $e MELLO
+ _keypress $e BackSpace
+ _keypress $e BackSpace
+ $e get 1.0 1.end
+} -cleanup {
+ deleteWindows
+} -result {MEL}
+test event-2.6(keypress) {type into text widget, triple click,
+ hit Delete key, and then type some more} -setup {
+ deleteWindows
+} -body {
+ set t [toplevel .t]
+ set e [text $t.e]
+ pack $e
+ tkwait visibility $e
+ _keypress_string $e JUMP
+
+ set result [$e get 1.0 1.end]
+
+ event generate $e <Enter>
+ for {set i 0} {$i < 3} {incr i} {
+ _pause 100
+ event generate $e <ButtonPress-1>
+ _pause 100
+ event generate $e <ButtonRelease-1>
+ }
+
+ _keypress $e Delete
+ _keypress_string $e UP
+ lappend result [$e get 1.0 1.end]
+} -cleanup {
+ deleteWindows
+} -result {JUMP UP}
+
+test event-3.1(click-drag) {click and drag in a text widget, this tests
+ tkTextSelectTo in text.tcl} -setup {
+ deleteWindows
+} -body {
+ set t [toplevel .t]
+ set e [text $t.e]
+ pack $e
+ tkwait visibility $e
+ _keypress_string $e "A Tcl/Tk selection test!"
+ set anchor 1.6
+ set selend 1.18
+
+ set result [list]
+ lappend result [$e get 1.0 1.end]
+
+ # Get the x,y coords of the second T in "Tcl/Tk"
+ foreach {anchor_x anchor_y} [_text_ind_to_x_y $e $anchor] break
+
+ # Click down to set the insert cursor position
+ event generate $e <Enter>
+ event generate $e <ButtonPress-1> -x $anchor_x -y $anchor_y
+
+ # Save the position of the insert cursor
+ lappend result [$e index insert]
+
+ # Now drag until selend is highlighted, then click up
+
+ set current $anchor
+ while {[$e compare $current <= $selend]} {
+ foreach {current_x current_y} [_text_ind_to_x_y $e $current] break
+ event generate $e <B1-Motion> -x $current_x -y $current_y
+ set current [$e index [list $current + 1 char]]
+ _pause 50
+ }
+
+ event generate $e <ButtonRelease-1> -x $current_x -y $current_y
+ _pause 200
+
+ # Save the position of the insert cursor
+ lappend result [$e index insert]
+
+ # Save the highlighted text
+ lappend result [_get_selection $e]
+
+ # Now click and click and drag to the left, over "Tcl/Tk selection"
+
+ event generate $e <ButtonPress-1> -x $current_x -y $current_y
+
+ while {[$e compare $current >= [list $anchor - 4 char]]} {
+ foreach {current_x current_y} [_text_ind_to_x_y $e $current] break
+ event generate $e <B1-Motion> -x $current_x -y $current_y
+ set current [$e index [list $current - 1 char]]
+ _pause 50
+ }
+
+ event generate $e <ButtonRelease-1> -x $current_x -y $current_y
+ _pause 200
+
+ # Save the position of the insert cursor
+ lappend result [$e index insert]
+
+ # Save the highlighted text
+ lappend result [_get_selection $e]
+
+} -cleanup {
+ deleteWindows
+} -result {{A Tcl/Tk selection test!} 1.6 1.18 {Tk selection} 1.2 {Tcl/Tk selection}}
+ test event-3.2(click-drag) {click and drag in an entry widget, this
+ tests tkEntryMouseSelect in entry.tcl} -setup {
+ deleteWindows
+} -body {
+ set t [toplevel .t]
+ set e [entry $t.e]
+ pack $e
+ tkwait visibility $e
+ _keypress_string $e "A Tcl/Tk selection!"
+ set anchor 6
+ set selend 18
+
+ set result [list]
+ lappend result [$e get]
+
+ # Get the x,y coords of the second T in "Tcl/Tk"
+ foreach {anchor_x anchor_y} [_text_ind_to_x_y $e $anchor] break
+
+ # Click down to set the insert cursor position
+ event generate $e <Enter>
+ event generate $e <ButtonPress-1> -x $anchor_x -y $anchor_y
+
+ # Save the position of the insert cursor
+ lappend result [$e index insert]
+
+ # Now drag until selend is highlighted, then click up
+
+ set current $anchor
+ while {$current <= $selend} {
+ foreach {current_x current_y} [_text_ind_to_x_y $e $current] break
+ event generate $e <B1-Motion> -x $current_x -y $current_y
+ incr current
+ _pause 50
+ }
+
+ event generate $e <ButtonRelease-1> -x $current_x -y $current_y
+ _pause 200
+
+ # Save the position of the insert cursor
+ lappend result [$e index insert]
+
+ # Save the highlighted text
+ lappend result [_get_selection $e]
+
+ # Now click and click and drag to the left, over "Tcl/Tk selection"
+
+ event generate $e <ButtonPress-1> -x $current_x -y $current_y
+
+ while {$current >= ($anchor - 4)} {
+ foreach {current_x current_y} [_text_ind_to_x_y $e $current] break
+ event generate $e <B1-Motion> -x $current_x -y $current_y
+ incr current -1
+ _pause 50
+ }
+
+ event generate $e <ButtonRelease-1> -x $current_x -y $current_y
+ _pause 200
+
+ # Save the position of the insert cursor
+ lappend result [$e index insert]
+
+ # Save the highlighted text
+ lappend result [_get_selection $e]
+
+} -cleanup {
+ deleteWindows
+} -result {{A Tcl/Tk selection!} 6 18 {Tk selection} 2 {Tcl/Tk selection}}
+
+
+test event-4.1(double-click-drag) {click down, click up, click down again,
+ then drag in a text widget} -setup {
+ deleteWindows
+} -body {
+ set t [toplevel .t]
+ set e [text $t.e]
+ pack $e
+ tkwait visibility $e
+ _keypress_string $e "Word select test"
+ set anchor 1.8
+
+ # Get the x,y coords of the second e in "select"
+ foreach {anchor_x anchor_y} [_text_ind_to_x_y $e $anchor] break
+
+ # Click down, release, then click down again
+ event generate $e <Enter>
+ event generate $e <ButtonPress-1> -x $anchor_x -y $anchor_y
+ _pause 50
+ event generate $e <ButtonRelease-1> -x $anchor_x -y $anchor_y
+ _pause 50
+ event generate $e <ButtonPress-1> -x $anchor_x -y $anchor_y
+ _pause 50
+
+ # Save the highlighted text
+ set result [list]
+ lappend result [_get_selection $e]
+
+ # Insert cursor should be at beginning of "select"
+ lappend result [$e index insert]
+
+ # Move mouse one character to the left
+ set current [$e index [list $anchor - 1 char]]
+ foreach {current_x current_y} [_text_ind_to_x_y $e $current] break
+
+ event generate $e <B1-Motion> -x $current_x -y $current_y
+ _pause 50
+
+ # Insert cursor should be before the l in "select"
+ lappend result [$e index insert]
+
+ # Selection should still be the word "select"
+ lappend result [_get_selection $e]
+
+ # Move mouse to the space before the word "select"
+ set current [$e index [list $current - 3 char]]
+
+ foreach {current_x current_y} [_text_ind_to_x_y $e $current] break
+ event generate $e <B1-Motion> -x $current_x -y $current_y
+ _pause 200
+
+ lappend result [$e index insert]
+ lappend result [_get_selection $e]
+
+ # Move mouse to the r in "Word"
+ set current 1.2
+ foreach {current_x current_y} [_text_ind_to_x_y $e $current] break
+
+ event generate $e <B1-Motion> -x $current_x -y $current_y
+ _pause 50
+
+ # Selection should now be "Word select"
+ lappend result [_get_selection $e]
+
+ # Insert cursor should be before the r in "Word"
+ lappend result [$e index insert]
+
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {select 1.5 1.7 select 1.4 { select} {Word select} 1.2}
+test event-4.2(double-click-drag) {click down, click up, click down again,
+ then drag in an entry widget} -setup {
+ deleteWindows
+} -body {
+ set t [toplevel .t]
+ set e [entry $t.e]
+ pack $e
+ tkwait visibility $e
+ _keypress_string $e "Word select test"
+
+ set anchor 8
+
+ # Get the x,y coords of the second e in "select"
+ foreach {anchor_x anchor_y} [_text_ind_to_x_y $e $anchor] break
+
+ # Click down, release, then click down again
+ event generate $e <Enter>
+ event generate $e <ButtonPress-1> -x $anchor_x -y $anchor_y
+ _pause 50
+ event generate $e <ButtonRelease-1> -x $anchor_x -y $anchor_y
+ _pause 50
+ event generate $e <ButtonPress-1> -x $anchor_x -y $anchor_y
+ _pause 50
+
+ set result [list]
+ lappend result [_get_selection $e]
+
+ # Insert cursor should be at the end of "select"
+ lappend result [$e index insert]
+
+ # Move mouse one character to the left
+ set current [expr {$anchor - 1}]
+ foreach {current_x current_y} [_text_ind_to_x_y $e $current] break
+
+ event generate $e <B1-Motion> -x $current_x -y $current_y
+ _pause 50
+
+ # Insert cursor should be before the l in "select"
+ lappend result [$e index insert]
+
+ # Selection should still be the word "select"
+ lappend result [_get_selection $e]
+
+ # Move mouse to the space before the word "select"
+ set current [expr {$current - 3}]
+ foreach {current_x current_y} [_text_ind_to_x_y $e $current] break
+
+ event generate $e <B1-Motion> -x $current_x -y $current_y
+ _pause 50
+
+ lappend result [$e index insert]
+ lappend result [_get_selection $e]
+
+ # Move mouse to the r in "Word"
+ set current [expr {$current - 2}]
+ foreach {current_x current_y} [_text_ind_to_x_y $e $current] break
+
+ event generate $e <B1-Motion> -x $current_x -y $current_y
+ _pause 50
+
+ # Selection should now be "Word select"
+ lappend result [_get_selection $e]
+
+ # Insert cursor should be before the r in "Word"
+ lappend result [$e index insert]
+
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {select 11 7 select 4 { select} {Word select} 2}
+
+test event-5.1(triple-click-drag) {Triple click and drag across lines in a
+ text widget, this should extend the selection to the new line} -setup {
+ deleteWindows
+} -body {
+ set t [toplevel .t]
+ set e [text $t.e]
+ pack $e
+ tkwait visibility $e
+ _keypress_string $e "LINE ONE\nLINE TWO\nLINE THREE"
+
+ set anchor 3.2
+
+ # Triple click one third line leaving mouse down
+
+ foreach {anchor_x anchor_y} [_text_ind_to_x_y $e $anchor] break
+
+ event generate $e <Enter>
+
+ event generate $e <ButtonPress-1> -x $anchor_x -y $anchor_y
+ _pause 50
+ event generate $e <ButtonRelease-1> -x $anchor_x -y $anchor_y
+ _pause 50
+
+ event generate $e <ButtonPress-1> -x $anchor_x -y $anchor_y
+ _pause 50
+ event generate $e <ButtonRelease-1> -x $anchor_x -y $anchor_y
+ _pause 50
+
+ event generate $e <ButtonPress-1> -x $anchor_x -y $anchor_y
+ _pause 50
+
+ set result [list]
+ lappend result [_get_selection $e]
+
+ # Drag up to second line
+
+ set current [$e index [list $anchor - 1 line]]
+ foreach {current_x current_y} [_text_ind_to_x_y $e $current] break
+
+ event generate $e <B1-Motion> -x $current_x -y $current_y
+ _pause 50
+
+ lappend result [_get_selection $e]
+
+ # Drag up to first line
+
+ set current [$e index [list $current - 1 line]]
+ foreach {current_x current_y} [_text_ind_to_x_y $e $current] break
+
+ event generate $e <B1-Motion> -x $current_x -y $current_y
+ _pause 50
+
+ lappend result [_get_selection $e]
+
+ return $result
+} -cleanup {
+ deleteWindows
+} -result [list "LINE THREE\n" "LINE TWO\nLINE THREE\n" \
+ "LINE ONE\nLINE TWO\nLINE THREE\n"]
+
+test event-6.1(button-state) {button press in a window that is then
+ destroyed, when the mouse is moved into another window it
+ should not generate a <B1-motion> event since the mouse
+ was not pressed down in that window} -setup {
+ deleteWindows
+} -body {
+ set t [toplevel .t]
+
+ event generate $t <ButtonPress-1>
+ destroy $t
+ set t [toplevel .t]
+ set motion nomotion
+ bind $t <B1-Motion> {set motion inmotion}
+ event generate $t <Motion>
+ return $motion
+} -cleanup {
+ deleteWindows
+} -result {nomotion}
+
+test event-7.1(double-click) {A double click on a lone character
+ in a text widget should select that character} -setup {
+ deleteWindows
+} -body {
+ set t [toplevel .t]
+ set e [text $t.e]
+ pack $e
+ tkwait visibility $e
+ focus -force $e
+ _keypress_string $e "On A letter"
+
+ set anchor 1.3
+
+ # Get x,y coords just inside the left
+ # and right hand side of the letter A
+ foreach {x1 y1 width height} [$e bbox $anchor] break
+
+ set middle_y [expr {$y1 + ($height / 2)}]
+
+ set left_x [expr {$x1 + 2}]
+ set left_y $middle_y
+
+ set right_x [expr {($x1 + $width) - 2}]
+ set right_y $middle_y
+
+ # Double click near left hand egde of the letter A
+
+ event generate $e <Enter>
+ event generate $e <ButtonPress-1> -x $left_x -y $left_y
+ _pause 50
+ event generate $e <ButtonRelease-1> -x $left_x -y $left_y
+ _pause 50
+ event generate $e <ButtonPress-1> -x $left_x -y $left_y
+ _pause 50
+ event generate $e <ButtonRelease-1> -x $left_x -y $left_y
+ _pause 50
+
+ set result [list]
+ lappend result [$e index insert]
+ lappend result [_get_selection $e]
+
+ # Clear selection by clicking at 0,0
+
+ event generate $e <ButtonPress-1> -x 0 -y 0
+ _pause 50
+ event generate $e <ButtonRelease-1> -x 0 -y 0
+ _pause 50
+
+ # Double click near right hand edge of the letter A
+
+ event generate $e <ButtonPress-1> -x $right_x -y $right_y
+ _pause 50
+ event generate $e <ButtonRelease-1> -x $right_x -y $right_y
+ _pause 50
+ event generate $e <ButtonPress-1> -x $right_x -y $right_y
+ _pause 50
+ event generate $e <ButtonRelease-1> -x $right_x -y $right_y
+ _pause 50
+
+ lappend result [$e index insert]
+ lappend result [_get_selection $e]
+
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {1.3 A 1.3 A}
+test event-7.2(double-click) {A double click on a lone character
+ in an entry widget should select that character} -setup {
+ deleteWindows
+} -body {
+ set t [toplevel .t]
+ set e [entry $t.e]
+ pack $e
+ tkwait visibility $e
+ focus -force $e
+ _keypress_string $e "On A letter"
+
+ set anchor 3
+
+ # Get x,y coords just inside the left
+ # and right hand side of the letter A
+ foreach {x1 y1 width height} [$e bbox $anchor] break
+
+ set middle_y [expr {$y1 + ($height / 2)}]
+
+ set left_x [expr {$x1 + 2}]
+ set left_y $middle_y
+
+ set right_x [expr {($x1 + $width) - 2}]
+ set right_y $middle_y
+
+ # Double click near left hand egde of the letter A
+
+ event generate $e <Enter>
+ event generate $e <ButtonPress-1> -x $left_x -y $left_y
+ _pause 50
+ event generate $e <ButtonRelease-1> -x $left_x -y $left_y
+ _pause 50
+ event generate $e <ButtonPress-1> -x $left_x -y $left_y
+ _pause 50
+ event generate $e <ButtonRelease-1> -x $left_x -y $left_y
+ _pause 50
+
+ set result [list]
+ lappend result [$e index insert]
+ lappend result [_get_selection $e]
+
+ # Clear selection by clicking at 0,0
+
+ event generate $e <ButtonPress-1> -x 0 -y 0
+ _pause 50
+ event generate $e <ButtonRelease-1> -x 0 -y 0
+ _pause 50
+
+ # Double click near right hand edge of the letter A
+
+ event generate $e <ButtonPress-1> -x $right_x -y $right_y
+ _pause 50
+ event generate $e <ButtonRelease-1> -x $right_x -y $right_y
+ _pause 50
+ event generate $e <ButtonPress-1> -x $right_x -y $right_y
+ _pause 50
+ event generate $e <ButtonRelease-1> -x $right_x -y $right_y
+ _pause 50
+
+ lappend result [$e index insert]
+ lappend result [_get_selection $e]
+
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {4 A 4 A}
+
+test event-8 {event generate with keysyms corresponding to
+ multi-byte virtual keycodes - bug
+ e36963bfe8df9f5e528134707a91b9c0051de723} -constraints nonPortable -setup {
+ deleteWindows
+ set res [list ]
+} -body {
+ set t [toplevel .t]
+ set e [entry $t.e]
+ pack $e
+ tkwait visibility $e
+ bind $e <KeyPress> {lappend res keycode: %k keysym: %K}
+ focus -force $e
+ update
+ event generate $e <diaeresis>
+ # The value now contained in $res depends on the actual
+ # physical keyboard layout and keycode generated, from
+ # the hardware on which the test suite happens to run.
+ # We don't need (and we can't really) check correctness
+ # of the (system-dependent) keycode received, however
+ # Tk should be able to associate this keycode to a
+ # (system-independent) known keysym, unless the system
+ # running the test does not have a keyboard with a
+ # diaeresis key.
+ if {[expr {[lindex $res 3] ne "??"}]} {
+ # keyboard has a physical diaeresis key and bug is fixed
+ return "OK"
+ } else {
+ return "Test failed, unless the keyboard tied to the system \
+ on which this test is run does NOT have a diaeresis \
+ physical key - in this case, test is actually void."
+ }
+} -cleanup {
+ deleteWindows
+} -result {OK}
+
+# cleanup
+unset -nocomplain keypress_lookup
+rename _init_keypress_lookup {}
+rename _keypress_lookup {}
+rename _keypress {}
+rename _pause {}
+rename _text_ind_to_x_y {}
+rename _get_selection {}
+
+cleanupTests
+return
+
+
diff --git a/tk8.6/tests/face.xbm b/tk8.6/tests/face.xbm
new file mode 100644
index 0000000..03d829f
--- /dev/null
+++ b/tk8.6/tests/face.xbm
@@ -0,0 +1,173 @@
+#define face_width 108
+#define face_height 144
+#define face_x_hot 48
+#define face_y_hot 80
+static char face_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09,
+ 0x20, 0x80, 0x24, 0x05, 0x00, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0x88,
+ 0x24, 0x20, 0x80, 0x24, 0x00, 0x00, 0x00, 0x10, 0x80, 0x04, 0x00, 0x01,
+ 0x00, 0x01, 0x40, 0x0a, 0x09, 0x00, 0x92, 0x04, 0x80, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x10, 0x40, 0x12, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x84,
+ 0x24, 0x40, 0x22, 0xa8, 0x02, 0x14, 0x84, 0x92, 0x40, 0x42, 0x12, 0x04,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x52, 0x00, 0x52, 0x11, 0x00, 0x12, 0x00,
+ 0x40, 0x02, 0x00, 0x20, 0x00, 0x08, 0x00, 0xaa, 0x02, 0x54, 0x85, 0x24,
+ 0x00, 0x10, 0x12, 0x00, 0x00, 0x81, 0x44, 0x00, 0x90, 0x5a, 0x00, 0xea,
+ 0x1b, 0x00, 0x80, 0x40, 0x40, 0x02, 0x00, 0x08, 0x00, 0x20, 0xa2, 0x05,
+ 0x8a, 0xb4, 0x6e, 0x45, 0x12, 0x04, 0x08, 0x00, 0x00, 0x00, 0x10, 0x02,
+ 0xa8, 0x92, 0x00, 0xda, 0x5f, 0x10, 0x00, 0x10, 0xa1, 0x04, 0x20, 0x41,
+ 0x02, 0x00, 0x5a, 0x25, 0xa0, 0xff, 0xfb, 0x05, 0x41, 0x02, 0x04, 0x00,
+ 0x00, 0x08, 0x40, 0x80, 0xec, 0x9b, 0xec, 0xfe, 0x7f, 0x01, 0x04, 0x20,
+ 0x90, 0x02, 0x04, 0x00, 0x08, 0x20, 0xfb, 0x2e, 0xf5, 0xff, 0xff, 0x57,
+ 0x00, 0x04, 0x02, 0x00, 0x00, 0x20, 0x01, 0xc1, 0x6e, 0xab, 0xfa, 0xff,
+ 0xff, 0x05, 0x90, 0x20, 0x48, 0x02, 0x00, 0x04, 0x20, 0xa8, 0xdf, 0xb5,
+ 0xfe, 0xff, 0xff, 0x0b, 0x01, 0x00, 0x01, 0x00, 0x80, 0x80, 0x04, 0xe0,
+ 0xbb, 0xef, 0xff, 0xff, 0x7f, 0x01, 0x00, 0x04, 0x48, 0x02, 0x00, 0x20,
+ 0x80, 0xf4, 0x6f, 0xfb, 0xff, 0xff, 0xff, 0x20, 0x90, 0x40, 0x02, 0x00,
+ 0x00, 0x04, 0x08, 0xb8, 0xf6, 0xff, 0xff, 0xdf, 0xbe, 0x12, 0x45, 0x10,
+ 0x90, 0x04, 0x90, 0x00, 0x22, 0xfa, 0xff, 0xff, 0xff, 0xbb, 0xd7, 0xe9,
+ 0x3a, 0x02, 0x02, 0x00, 0x04, 0x90, 0x80, 0xfe, 0xdf, 0xf6, 0xb7, 0xef,
+ 0xbe, 0x56, 0x57, 0x40, 0x48, 0x09, 0x00, 0x04, 0x00, 0xfa, 0xf5, 0xdf,
+ 0xed, 0x5a, 0xd5, 0xea, 0xbd, 0x09, 0x00, 0x00, 0x40, 0x00, 0x92, 0xfe,
+ 0xbf, 0x7d, 0xb7, 0x6a, 0x55, 0xbf, 0xf7, 0x02, 0x11, 0x01, 0x00, 0x91,
+ 0x00, 0xff, 0xff, 0xaf, 0x55, 0x55, 0x5b, 0xeb, 0xef, 0x22, 0x04, 0x04,
+ 0x04, 0x00, 0xa4, 0xff, 0xf7, 0xad, 0xaa, 0xaa, 0xaa, 0xbe, 0xfe, 0x03,
+ 0x20, 0x00, 0x10, 0x44, 0x80, 0xff, 0x7f, 0x55, 0x12, 0x91, 0x2a, 0xeb,
+ 0xbf, 0x0b, 0x82, 0x02, 0x00, 0x00, 0xd1, 0x7f, 0xdf, 0xa2, 0xa4, 0x54,
+ 0x55, 0xfd, 0xfd, 0x47, 0x08, 0x08, 0x00, 0x21, 0xe4, 0xff, 0x37, 0x11,
+ 0x09, 0xa5, 0xaa, 0xb6, 0xff, 0x0d, 0x80, 0x00, 0x00, 0x04, 0xd0, 0xff,
+ 0x4f, 0x44, 0x20, 0x48, 0x55, 0xfb, 0xff, 0x27, 0x11, 0x02, 0x40, 0x40,
+ 0xe2, 0xfb, 0x15, 0x11, 0x4a, 0x55, 0x4a, 0x7d, 0xf7, 0x0f, 0x00, 0x00,
+ 0x04, 0x08, 0xf8, 0xdf, 0x52, 0x44, 0x01, 0x52, 0xb5, 0xfa, 0xff, 0x0f,
+ 0x49, 0x02, 0x00, 0x02, 0xe9, 0xf6, 0x0a, 0x11, 0xa4, 0x88, 0x4a, 0x6d,
+ 0xff, 0x5f, 0x00, 0x00, 0x10, 0x20, 0xf0, 0x2f, 0x21, 0x44, 0x10, 0x52,
+ 0xb5, 0xfa, 0xff, 0x0f, 0x44, 0x04, 0x80, 0x08, 0xf8, 0xab, 0x8a, 0x00,
+ 0x81, 0xa4, 0xd4, 0xd6, 0xfe, 0x2f, 0x00, 0x00, 0x04, 0x40, 0xb5, 0x2d,
+ 0x21, 0x08, 0x04, 0x90, 0xaa, 0xfa, 0xff, 0x1f, 0x11, 0x01, 0x00, 0x04,
+ 0xf0, 0x57, 0x0a, 0x22, 0x40, 0x4a, 0xda, 0x5e, 0xfb, 0x1f, 0x40, 0x00,
+ 0x40, 0x20, 0xba, 0x95, 0x90, 0x00, 0x01, 0xa0, 0xaa, 0xea, 0xff, 0x5f,
+ 0x02, 0x02, 0x00, 0x01, 0xe8, 0x57, 0x05, 0x00, 0x00, 0x12, 0xd5, 0xfe,
+ 0xfd, 0x1f, 0x48, 0x00, 0x04, 0x48, 0x7a, 0x95, 0x08, 0x02, 0x10, 0x40,
+ 0xaa, 0x55, 0xf7, 0x1f, 0x00, 0x09, 0x20, 0x00, 0xf8, 0x57, 0x22, 0x10,
+ 0x00, 0x28, 0xa9, 0xfa, 0xff, 0x5f, 0x02, 0x00, 0x00, 0x49, 0xdd, 0x29,
+ 0x01, 0x00, 0x80, 0x80, 0xaa, 0xd7, 0xff, 0x0f, 0x10, 0x00, 0x08, 0x00,
+ 0xf8, 0x96, 0x08, 0x00, 0x00, 0x20, 0x54, 0xfa, 0xee, 0x3f, 0x81, 0x04,
+ 0x40, 0x24, 0xfe, 0x55, 0x82, 0x00, 0x00, 0x82, 0xd2, 0xad, 0xff, 0x0f,
+ 0x08, 0x00, 0x04, 0x80, 0x6c, 0x97, 0x00, 0x00, 0x02, 0x20, 0xa9, 0xf6,
+ 0xdf, 0x5f, 0x00, 0x02, 0x20, 0x09, 0xfa, 0x49, 0x12, 0x00, 0x20, 0x84,
+ 0x54, 0xdb, 0xfe, 0x1f, 0x91, 0x00, 0x00, 0x00, 0xf8, 0x2b, 0x00, 0x20,
+ 0x00, 0x40, 0xa4, 0xf6, 0xbb, 0x1f, 0x04, 0x00, 0x44, 0x92, 0x7e, 0x95,
+ 0x02, 0x00, 0x00, 0x89, 0xaa, 0xdd, 0xff, 0x1f, 0x20, 0x09, 0x10, 0x00,
+ 0xf4, 0x57, 0x20, 0x01, 0x08, 0x20, 0xa9, 0x76, 0xff, 0x5f, 0x02, 0x00,
+ 0x00, 0x21, 0xfc, 0x4a, 0x05, 0x00, 0x01, 0x80, 0x54, 0xdb, 0xff, 0x1e,
+ 0x08, 0x02, 0x04, 0x08, 0xf9, 0x2b, 0x00, 0x00, 0x40, 0x28, 0xd2, 0xf6,
+ 0xff, 0xbf, 0x80, 0x00, 0x90, 0x00, 0xbc, 0x92, 0x08, 0x10, 0x00, 0x82,
+ 0x54, 0xdb, 0xff, 0x1f, 0x20, 0x00, 0x00, 0x44, 0xf9, 0x55, 0x02, 0x01,
+ 0x00, 0x20, 0xaa, 0xbd, 0xfd, 0x3f, 0x08, 0x04, 0x04, 0x10, 0xf4, 0x2a,
+ 0x01, 0x00, 0x22, 0x80, 0xd4, 0xf6, 0xff, 0x5f, 0x82, 0x00, 0x40, 0x02,
+ 0xf8, 0x55, 0x20, 0x00, 0x00, 0x50, 0x6a, 0xdf, 0xfe, 0x3f, 0x00, 0x00,
+ 0x00, 0x48, 0xe9, 0x4a, 0x05, 0x08, 0x00, 0xa5, 0xd5, 0xf5, 0xff, 0x3f,
+ 0x10, 0x01, 0x10, 0x01, 0xb0, 0xab, 0x92, 0x02, 0x40, 0xf8, 0xbf, 0xde,
+ 0xfe, 0x5f, 0x02, 0x04, 0x04, 0x48, 0xfa, 0xd4, 0x6f, 0x20, 0x84, 0xef,
+ 0xff, 0xfb, 0xff, 0x1f, 0x20, 0x00, 0x00, 0x00, 0xe0, 0xed, 0xbf, 0x0b,
+ 0xa1, 0x7e, 0xff, 0xbf, 0xfd, 0x5f, 0x04, 0x01, 0x20, 0x49, 0xd2, 0xfb,
+ 0xfe, 0x55, 0xd4, 0xff, 0xff, 0xf6, 0xff, 0x07, 0x00, 0x04, 0x00, 0x00,
+ 0xc0, 0xaa, 0xfb, 0x2b, 0xa2, 0xfe, 0xff, 0xdf, 0xee, 0x1f, 0x91, 0x00,
+ 0x82, 0xa4, 0xa4, 0xf5, 0xff, 0x57, 0xd5, 0xff, 0xbf, 0xfd, 0xff, 0x4d,
+ 0x00, 0x00, 0x20, 0x00, 0x88, 0x5b, 0xff, 0x2f, 0x69, 0xff, 0xff, 0xdb,
+ 0xfe, 0x1f, 0x24, 0x02, 0x00, 0x49, 0xa2, 0xd6, 0xff, 0x5f, 0xea, 0xff,
+ 0x7f, 0x7f, 0x7f, 0x0d, 0x00, 0x00, 0x10, 0x00, 0x40, 0xab, 0xf7, 0xbb,
+ 0xf0, 0xdf, 0xff, 0xd5, 0xff, 0xbf, 0x82, 0x04, 0x42, 0x24, 0x91, 0xd5,
+ 0xaa, 0xae, 0xd4, 0xaa, 0x52, 0x7b, 0xff, 0x15, 0x08, 0x00, 0x00, 0x01,
+ 0x04, 0x55, 0xd5, 0x55, 0x70, 0x5b, 0x75, 0xdd, 0xdf, 0x1f, 0x40, 0x00,
+ 0x08, 0x48, 0xa0, 0x4a, 0xa9, 0x56, 0xea, 0x56, 0xad, 0x6a, 0x7d, 0x9b,
+ 0x04, 0x01, 0x00, 0x02, 0x42, 0x2a, 0xd5, 0xaa, 0xa8, 0xaa, 0xaa, 0xfa,
+ 0xdf, 0x2f, 0x10, 0x04, 0x22, 0x48, 0x08, 0x45, 0x2a, 0x15, 0x68, 0x55,
+ 0x55, 0xd7, 0x76, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x40, 0x2a, 0x80, 0xa0,
+ 0xb2, 0x09, 0x48, 0xb9, 0xdf, 0x17, 0x22, 0x01, 0x00, 0x24, 0x45, 0x8a,
+ 0x24, 0x4a, 0x54, 0x51, 0x91, 0xf6, 0x6e, 0x4b, 0x00, 0x04, 0x90, 0x00,
+ 0x80, 0x52, 0x00, 0x20, 0x69, 0x05, 0xa4, 0xaa, 0xff, 0x1e, 0x48, 0x00,
+ 0x02, 0x92, 0x08, 0x05, 0x81, 0x94, 0xd4, 0x92, 0x40, 0xfd, 0xb6, 0x8b,
+ 0x00, 0x01, 0x40, 0x00, 0x82, 0x54, 0x00, 0x48, 0x68, 0x05, 0x90, 0xa4,
+ 0xef, 0x06, 0x24, 0x00, 0x08, 0x12, 0x10, 0x05, 0x00, 0x10, 0xb5, 0x01,
+ 0x42, 0xfb, 0xbf, 0x43, 0x00, 0x09, 0x00, 0x40, 0x81, 0xa8, 0x08, 0x4a,
+ 0xaa, 0x96, 0x90, 0xac, 0x6d, 0x15, 0x22, 0x00, 0x20, 0x09, 0x04, 0x15,
+ 0x80, 0x28, 0xdc, 0x01, 0x24, 0xfb, 0xbf, 0x01, 0x80, 0x04, 0x09, 0x00,
+ 0x40, 0x48, 0x02, 0x45, 0xb2, 0x2e, 0x41, 0x6d, 0xef, 0x05, 0x11, 0x00,
+ 0x40, 0x52, 0x02, 0x15, 0x29, 0x2a, 0xac, 0x42, 0x54, 0xfb, 0x3b, 0x51,
+ 0x84, 0x00, 0x08, 0x00, 0x20, 0x54, 0x80, 0x05, 0xb5, 0x3d, 0xa2, 0xb6,
+ 0xdf, 0x00, 0x20, 0x04, 0x20, 0x49, 0x89, 0xa8, 0x6a, 0x29, 0xac, 0xd6,
+ 0x54, 0xff, 0x3f, 0x84, 0x00, 0x01, 0x04, 0x10, 0x00, 0x94, 0xa8, 0x56,
+ 0xda, 0x5f, 0xab, 0xd5, 0x1e, 0x10, 0x48, 0x00, 0x90, 0x82, 0x48, 0xa8,
+ 0xb2, 0xac, 0xfd, 0x55, 0xd5, 0xfe, 0x9f, 0x80, 0x00, 0x0a, 0x02, 0x08,
+ 0x02, 0x55, 0x5a, 0x75, 0xff, 0xaf, 0xb6, 0xf7, 0x2d, 0x12, 0x92, 0x00,
+ 0x10, 0x20, 0x10, 0xa8, 0x54, 0xd5, 0xbf, 0x5d, 0xad, 0xdd, 0x0f, 0x00,
+ 0x00, 0x04, 0x40, 0x09, 0x84, 0xa8, 0xaa, 0x5a, 0xed, 0xeb, 0x6a, 0xff,
+ 0x9f, 0xa4, 0x24, 0x01, 0x02, 0xa0, 0x20, 0x50, 0x55, 0xd5, 0xbe, 0xae,
+ 0xad, 0xfd, 0x16, 0x00, 0x10, 0x04, 0x20, 0x0a, 0x08, 0xb4, 0xaa, 0x95,
+ 0xaa, 0x7b, 0xb7, 0xdb, 0x5f, 0x92, 0x04, 0x01, 0x84, 0x20, 0x21, 0x51,
+ 0xd5, 0x2a, 0xa9, 0xee, 0xd5, 0xfe, 0x0d, 0x00, 0x20, 0x04, 0x10, 0x00,
+ 0x08, 0x50, 0xe9, 0xd7, 0xd4, 0xfb, 0xb5, 0xff, 0x9f, 0x24, 0x09, 0x01,
+ 0x42, 0x4a, 0xa2, 0x64, 0xd5, 0x55, 0x7b, 0x7f, 0xda, 0x7d, 0x4f, 0x00,
+ 0x20, 0x04, 0x00, 0x80, 0x00, 0xa0, 0x2a, 0x13, 0x84, 0x6a, 0x55, 0xff,
+ 0x1d, 0x48, 0x8a, 0x00, 0x94, 0x24, 0x8a, 0xc8, 0xaa, 0x42, 0x20, 0x5d,
+ 0xf5, 0xff, 0x5f, 0x01, 0x00, 0x02, 0x01, 0x00, 0x20, 0xa2, 0x4a, 0x1a,
+ 0x82, 0x56, 0xda, 0xbd, 0x3f, 0x92, 0x92, 0x00, 0x90, 0x92, 0x00, 0x40,
+ 0x95, 0x6a, 0xf4, 0x55, 0x6d, 0xff, 0xd6, 0x00, 0x00, 0x0a, 0x04, 0x20,
+ 0x14, 0x49, 0x4b, 0xaa, 0xaa, 0x56, 0xf5, 0xff, 0xbf, 0xab, 0xa4, 0x00,
+ 0x20, 0x89, 0x40, 0x80, 0xaa, 0xaa, 0xaa, 0xaa, 0xde, 0xbf, 0xeb, 0x03,
+ 0x00, 0x02, 0x04, 0x02, 0x0a, 0x10, 0x2b, 0x2a, 0x55, 0x5b, 0xf5, 0xff,
+ 0xd7, 0x2f, 0x92, 0x00, 0x10, 0x28, 0x21, 0x01, 0x56, 0x95, 0xa0, 0x56,
+ 0xdf, 0xef, 0xea, 0x87, 0x40, 0x0a, 0x42, 0x41, 0x00, 0x90, 0xaa, 0x52,
+ 0xb6, 0xad, 0xfa, 0xff, 0xd5, 0x2f, 0x14, 0x00, 0x00, 0x04, 0x95, 0x04,
+ 0xaa, 0xac, 0x55, 0x6b, 0xff, 0xb7, 0xea, 0x9f, 0x40, 0x02, 0x28, 0x51,
+ 0x00, 0x40, 0x58, 0xd5, 0xda, 0xd6, 0x6e, 0x7f, 0xf9, 0x3f, 0x12, 0x04,
+ 0x02, 0x04, 0x49, 0x25, 0x55, 0xaa, 0x77, 0xab, 0xff, 0x2b, 0xfd, 0x3f,
+ 0x48, 0x01, 0x20, 0x41, 0x00, 0x00, 0x58, 0xa9, 0xda, 0xea, 0xfd, 0xaf,
+ 0xfa, 0xff, 0x02, 0x04, 0x08, 0x14, 0x29, 0x49, 0x52, 0x55, 0x55, 0x55,
+ 0xff, 0x8d, 0xfe, 0x3f, 0xa8, 0x00, 0x02, 0x41, 0x00, 0x02, 0xa0, 0xa2,
+ 0xaa, 0xea, 0xff, 0x53, 0xfd, 0xff, 0x02, 0x04, 0x50, 0x04, 0x25, 0xa8,
+ 0x54, 0x49, 0x52, 0xb5, 0xbf, 0x8a, 0xfe, 0xff, 0xa9, 0x08, 0x04, 0x50,
+ 0x80, 0x02, 0xa1, 0x2a, 0x95, 0xea, 0xff, 0xa1, 0xff, 0xff, 0x03, 0x02,
+ 0x90, 0x02, 0x09, 0x08, 0x44, 0x49, 0x52, 0xbd, 0x7f, 0xca, 0xff, 0xff,
+ 0x2b, 0x09, 0x04, 0x48, 0x40, 0x82, 0x90, 0x56, 0xa9, 0xf6, 0xbf, 0xd0,
+ 0xff, 0xff, 0x47, 0x00, 0x50, 0x02, 0x15, 0x11, 0x40, 0x95, 0xaa, 0xfd,
+ 0x2f, 0xe9, 0xff, 0xff, 0x8f, 0x0a, 0x84, 0x50, 0x40, 0x84, 0x14, 0xaa,
+ 0x6a, 0xff, 0x5f, 0xf2, 0xff, 0xff, 0x7f, 0x00, 0x10, 0x02, 0x09, 0x10,
+ 0x40, 0x7d, 0xf7, 0xff, 0x0b, 0xfc, 0xff, 0xff, 0xaf, 0x02, 0x84, 0x50,
+ 0x42, 0x85, 0x12, 0xd0, 0xdd, 0xff, 0xa7, 0xf2, 0xff, 0xff, 0xff, 0x04,
+ 0x00, 0x0a, 0x08, 0x10, 0x48, 0xf8, 0xff, 0xff, 0x0a, 0xfe, 0xff, 0xff,
+ 0x7f, 0x03, 0xa4, 0x80, 0xa2, 0x8a, 0x02, 0x68, 0xff, 0xff, 0x52, 0xfd,
+ 0xff, 0xff, 0xff, 0x07, 0x00, 0x2a, 0x08, 0x20, 0x28, 0xdc, 0xff, 0x5f,
+ 0x05, 0xff, 0xff, 0xff, 0xff, 0x0d, 0x92, 0x40, 0x22, 0x09, 0x02, 0xea,
+ 0xfb, 0xaf, 0x48, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x12, 0x81, 0xa0,
+ 0x48, 0x9c, 0x6e, 0x93, 0xa2, 0xff, 0xff, 0xff, 0xff, 0x07, 0xa8, 0x40,
+ 0x28, 0x0a, 0x02, 0x74, 0xb5, 0x45, 0x81, 0xff, 0xff, 0xff, 0xff, 0x0f,
+ 0x02, 0x0a, 0x81, 0x20, 0x08, 0xae, 0xaa, 0x90, 0xe8, 0xff, 0xff, 0xff,
+ 0xff, 0x0f, 0x90, 0x40, 0x28, 0x88, 0x12, 0x58, 0x15, 0x50, 0xd0, 0xff,
+ 0xff, 0xff, 0xff, 0x0f, 0x44, 0x0a, 0x41, 0x21, 0x08, 0xae, 0x04, 0x14,
+ 0xf0, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x10, 0x40, 0x14, 0x88, 0x04, 0xba,
+ 0x02, 0x28, 0xe8, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x42, 0x15, 0x41, 0x21,
+ 0x05, 0xad, 0x00, 0x05, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x10, 0x40,
+ 0x24, 0x8a, 0x0e, 0x36, 0x00, 0x0a, 0xf4, 0xff, 0xff, 0xff, 0xff, 0x0f,
+ 0x42, 0x25, 0x90, 0xd0, 0x8b, 0xc2, 0x41, 0x05, 0xfc, 0xff, 0xff, 0xff,
+ 0xff, 0x0f, 0x10, 0x08, 0x05, 0xe8, 0x8e, 0x58, 0x80, 0x02, 0xfa, 0xff,
+ 0xff, 0xff, 0xff, 0x0f, 0x4a, 0x20, 0xa8, 0xba, 0x0b, 0x2b, 0x51, 0x01,
+ 0xfe, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x8a, 0x02, 0xe8, 0xaf, 0x84,
+ 0x90, 0x04, 0xfd, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x52, 0x21, 0x54, 0xbf,
+ 0x1f, 0x15, 0xa5, 0x02, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x08,
+ 0x01, 0xfa, 0xb6, 0xa4, 0x52, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,
+ 0x4a, 0xa2, 0x54, 0xef, 0x5f, 0x4b, 0xa4, 0x80, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x0f, 0x80, 0x10, 0x82, 0xfe, 0xbf, 0x92, 0x52, 0x42, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x0f, 0x12, 0x42, 0xa8, 0xbf, 0x1f, 0x24, 0x80, 0xa0,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x84, 0x28, 0x8a, 0xf7, 0x37, 0x80,
+ 0x52, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x10, 0x82, 0xe0, 0xff,
+ 0x1f, 0x00, 0x20, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x84, 0x28,
+ 0xca, 0xff, 0x1f, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,
+ 0x10, 0x42, 0xf0, 0xfd, 0x1b, 0x00, 0x50, 0xf0, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x0f, 0xa4, 0x10, 0xc5, 0xff, 0x1f, 0x00, 0x00, 0xe0, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x0f, 0x00, 0x22, 0xf8, 0xff, 0x0e, 0x00, 0x00, 0xf0,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xaa, 0x88, 0xe2, 0xff, 0x0f, 0x10,
+ 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x25, 0xfa, 0xff,
+ 0x0f, 0x01, 0x11, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xfb,
+ 0xfb, 0xff, 0x7f, 0x5d, 0xd5, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f};
diff --git a/tk8.6/tests/filebox.test b/tk8.6/tests/filebox.test
new file mode 100644
index 0000000..0114a07
--- /dev/null
+++ b/tk8.6/tests/filebox.test
@@ -0,0 +1,490 @@
+# This file is a Tcl script to test out Tk's "tk_getOpenFile" and
+# "tk_getSaveFile" commands. It is organized in the standard fashion
+# for Tcl tests.
+#
+# Copyright (c) 1996 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.1
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+
+test fileDialog-0.1 {GetFileName: file types: MakeFilter() fails} {
+ # MacOS type that is too long
+
+ set res [list [catch {tk_getSaveFile -filetypes {{"foo" .foo {\0\0\0\0\0}}}} msg] $msg]
+ regsub -all "\0" $res {\\0}
+} {1 {bad Macintosh file type "\0\0\0\0\0"}}
+test fileDialog-0.2 {GetFileName: file types: MakeFilter() fails} {
+ # MacOS type that is too short, but looks ok in utf (4 bytes).
+
+ set x [catch {tk_getSaveFile -filetypes {{"foo" .foo {\0\0}}}} msg]
+ regsub -all "\0" $msg {\\0} msg
+ list $x $msg
+} {1 {bad Macintosh file type "\0\0"}}
+
+set tk_strictMotif_old $tk_strictMotif
+
+#----------------------------------------------------------------------
+#
+# Procedures needed by this test file
+#
+#----------------------------------------------------------------------
+
+proc ToPressButton {parent btn} {
+ global isNative
+ if {!$isNative} {
+ after 100 SendButtonPress $parent $btn mouse
+ }
+}
+
+proc ToEnterFileByKey {parent fileName fileDir} {
+ global isNative
+ if {!$isNative} {
+ after 100 EnterFileByKey $parent [list $fileName] [list $fileDir]
+ }
+}
+
+proc PressButton {btn} {
+ event generate $btn <Enter>
+ event generate $btn <1> -x 5 -y 5
+ event generate $btn <ButtonRelease-1> -x 5 -y 5
+}
+
+proc EnterFileByKey {parent fileName fileDir} {
+ global tk_strictMotif
+ if {$parent == "."} {
+ set w .__tk_filedialog
+ } else {
+ set w $parent.__tk_filedialog
+ }
+ upvar ::tk::dialog::file::__tk_filedialog data
+
+ if {$tk_strictMotif} {
+ $data(sEnt) delete 0 end
+ $data(sEnt) insert 0 [file join $fileDir $fileName]
+ } else {
+ $data(ent) delete 0 end
+ $data(ent) insert 0 $fileName
+ }
+
+ update
+ SendButtonPress $parent ok mouse
+}
+
+proc SendButtonPress {parent btn type} {
+ global tk_strictMotif
+ if {$parent == "."} {
+ set w .__tk_filedialog
+ } else {
+ set w $parent.__tk_filedialog
+ }
+ upvar ::tk::dialog::file::__tk_filedialog data
+
+ set button $data($btn\Btn)
+ if ![winfo ismapped $button] {
+ update
+ }
+
+ if {$type == "mouse"} {
+ PressButton $button
+ } else {
+ event generate $w <Enter>
+ focus $w
+ event generate $button <Enter>
+ event generate $w <KeyPress> -keysym Return
+ }
+}
+
+
+#----------------------------------------------------------------------
+#
+# The test suite proper
+#
+#----------------------------------------------------------------------
+
+if {$tcl_platform(platform) == "unix"} {
+ set modes "0 1"
+} else {
+ set modes 1
+}
+
+set unknownOptionsMsg(tk_getOpenFile,notAqua) {bad option "-foo": must be -defaultextension, -filetypes, -initialdir, -initialfile, -multiple, -parent, -title, or -typevariable}
+set unknownOptionsMsg(tk_getOpenFile,aqua) {bad option "-foo": must be -defaultextension, -filetypes, -initialdir, -initialfile, -message, -multiple, -parent, -title, -typevariable, or -command}
+set unknownOptionsMsg(tk_getSaveFile,notAqua) {bad option "-foo": must be -confirmoverwrite, -defaultextension, -filetypes, -initialdir, -initialfile, -parent, -title, or -typevariable}
+set unknownOptionsMsg(tk_getSaveFile,aqua) {bad option "-foo": must be -defaultextension, -filetypes, -initialdir, -initialfile, -message, -parent, -title, -typevariable, -command, or -confirmoverwrite}
+
+set tmpFile "filebox.tmp"
+makeFile {
+ # this file can be empty!
+} $tmpFile
+
+array set filters {
+ 1 {}
+ 2 {
+ {"Text files" {.txt .doc} }
+ {"Text files" {} TEXT}
+ {"Tcl Scripts" {.tcl} TEXT}
+ {"C Source Files" {.c .h} }
+ {"All Source Files" {.tcl .c .h} }
+ {"Image Files" {.gif} }
+ {"Image Files" {.jpeg .jpg} }
+ {"Image Files" "" {GIFF JPEG}}
+ {"All files" *}
+ }
+ 3 {
+ {"Text files" {.txt .doc} TEXT}
+ {"Foo" {""} TEXT}
+ }
+}
+
+foreach mode $modes {
+ #
+ # Test both the motif version and the "tk" version of the file dialog
+ # box on Unix.
+ #
+ # Note that this means that test names are unusually complex.
+ #
+
+ set addedExtensions {}
+ if {$tcl_platform(platform) == "unix"} {
+ set tk_strictMotif $mode
+ # Extension adding is only done when using the non-motif file
+ # box with an extension-less filename
+ if {!$mode} {
+ set addedExtensions {NONE {} .txt .txt}
+ }
+ }
+
+ test filebox-1.1.1-$mode "tk_getOpenFile command" -constraints notAqua -body {
+ tk_getOpenFile -foo
+ } -returnCodes error -result $unknownOptionsMsg(tk_getOpenFile,notAqua)
+ test filebox-1.1.2-$mode "tk_getOpenFile command" -constraints aqua -body {
+ tk_getOpenFile -foo
+ } -returnCodes error -result $unknownOptionsMsg(tk_getOpenFile,aqua)
+
+ catch {tk_getOpenFile -foo 1} msg
+ regsub -all , $msg "" options
+ regsub \"-foo\" $options "" options
+
+ foreach option $options {
+ if {[string index $option 0] eq "-"} {
+ test filebox-1.2-$mode$option "tk_getOpenFile command" -body {
+ tk_getOpenFile $option
+ } -returnCodes error -result "value for \"$option\" missing"
+ }
+ }
+
+ test filebox-1.3.1-$mode "tk_getOpenFile command" -constraints notAqua -body {
+ tk_getOpenFile -foo bar
+ } -returnCodes error -result $unknownOptionsMsg(tk_getOpenFile,notAqua)
+ test filebox-1.3.2-$mode "tk_getOpenFile command" -constraints aqua -body {
+ tk_getOpenFile -foo bar
+ } -returnCodes error -result $unknownOptionsMsg(tk_getOpenFile,aqua)
+ test filebox-1.4-$mode "tk_getOpenFile command" -body {
+ tk_getOpenFile -initialdir
+ } -returnCodes error -result {value for "-initialdir" missing}
+ test filebox-1.5-$mode "tk_getOpenFile command" -body {
+ tk_getOpenFile -parent foo.bar
+ } -returnCodes error -result {bad window path name "foo.bar"}
+ test filebox-1.6-$mode "tk_getOpenFile command" -body {
+ tk_getOpenFile -filetypes {Foo}
+ } -returnCodes error -result {bad file type "Foo", should be "typeName {extension ?extensions ...?} ?{macType ?macTypes ...?}?"}
+
+ set isNative [expr {
+ [info commands ::tk::MotifFDialog] eq "" &&
+ [info commands ::tk::dialog::file::] eq ""
+ }]
+
+ set parent .
+
+ set verylongstring longstring:
+ set verylongstring $verylongstring$verylongstring
+ set verylongstring $verylongstring$verylongstring
+ set verylongstring $verylongstring$verylongstring
+ set verylongstring $verylongstring$verylongstring
+ # set verylongstring $verylongstring$verylongstring
+ # set verylongstring $verylongstring$verylongstring
+ # set verylongstring $verylongstring$verylongstring
+ # set verylongstring $verylongstring$verylongstring
+ # set verylongstring $verylongstring$verylongstring
+
+ set color #404040
+ test filebox-2.1-$mode "tk_getOpenFile command" nonUnixUserInteraction {
+ ToPressButton $parent cancel
+ tk_getOpenFile -title "Press Cancel ($verylongstring)" -parent $parent
+ } ""
+
+ set fileName $tmpFile
+ set fileDir [tcltest::temporaryDirectory]
+ set pathName [file join $fileDir $fileName]
+
+ test filebox-2.2-$mode "tk_getOpenFile command" nonUnixUserInteraction {
+ ToPressButton $parent ok
+ set choice [tk_getOpenFile -title "Press Ok" \
+ -parent $parent -initialfile $fileName -initialdir $fileDir]
+ } $pathName
+ test filebox-2.3-$mode "tk_getOpenFile command" nonUnixUserInteraction {
+ ToEnterFileByKey $parent $fileName $fileDir
+ set choice [tk_getOpenFile -title "Enter \"$fileName\" and press Ok" \
+ -parent $parent -initialdir $fileDir]
+ } $pathName
+ test filebox-2.4-$mode "tk_getOpenFile command" nonUnixUserInteraction {
+ cd $fileDir
+ ToPressButton $parent ok
+ set choice [tk_getOpenFile -title "Enter \"$fileName\" and press Ok" \
+ -parent $parent -initialdir . -initialfile $fileName]
+ } $pathName
+ test filebox-2.5-$mode "tk_getOpenFile command" nonUnixUserInteraction {
+ ToPressButton $parent ok
+ set choice [tk_getOpenFile -title "Enter \"$fileName\" and press Ok" \
+ -parent $parent -initialdir /badpath -initialfile $fileName]
+ } $pathName
+ test filebox-2.6-$mode "tk_getOpenFile command" -setup {
+ toplevel .t1; toplevel .t2
+ wm geometry .t1 +0+0
+ wm geometry .t2 +0+0
+ } -constraints nonUnixUserInteraction -body {
+ set choice {}
+ ToPressButton .t1 ok
+ lappend choice [tk_getOpenFile \
+ -title "Enter \"$fileName\" and press Ok" \
+ -parent .t1 -initialdir $fileDir \
+ -initialfile $fileName]
+ ToPressButton .t2 ok
+ lappend choice [tk_getOpenFile \
+ -title "Enter \"$fileName\" and press Ok" \
+ -parent .t2 -initialdir $fileDir \
+ -initialfile $fileName]
+ ToPressButton .t1 ok
+ lappend choice [tk_getOpenFile \
+ -title "Enter \"$fileName\" and press Ok" \
+ -parent .t1 -initialdir $fileDir \
+ -initialfile $fileName]
+ } -result [list $pathName $pathName $pathName] -cleanup {
+ destroy .t1
+ destroy .t2
+ }
+
+ foreach x [lsort -integer [array names filters]] {
+ test filebox-3.$x-$mode "tk_getOpenFile command" nonUnixUserInteraction {
+ ToPressButton $parent ok
+ set choice [tk_getOpenFile -title "Press Ok" \
+ -filetypes $filters($x) -parent $parent \
+ -initialfile $fileName -initialdir $fileDir]
+ } $pathName
+ }
+ foreach {x res} [list 1 "-unset-" 2 "Text files"] {
+ set t [expr {$x + [llength [array names filters]]}]
+ test filebox-3.$t-$mode "tk_getOpenFile command" nonUnixUserInteraction {
+ catch {unset tv}
+ catch {unset typeName}
+ ToPressButton $parent ok
+ if {[info exists tv]} {
+ } else {
+ }
+ set choice [tk_getOpenFile -title "Press Ok" \
+ -filetypes $filters($x) -parent $parent \
+ -initialfile $fileName -initialdir $fileDir \
+ -typevariable tv]
+ if {[info exists tv]} {
+ set typeName $tv
+ } else {
+ set typeName "-unset-"
+ }
+ set typeName
+ } $res
+ }
+
+ test filebox-4.1.1-$mode "tk_getSaveFile command" -constraints notAqua -body {
+ tk_getSaveFile -foo
+ } -returnCodes error -result $unknownOptionsMsg(tk_getSaveFile,notAqua)
+ test filebox-4.1.2-$mode "tk_getSaveFile command" -constraints aqua -body {
+ tk_getSaveFile -foo
+ } -returnCodes error -result $unknownOptionsMsg(tk_getSaveFile,aqua)
+
+ catch {tk_getSaveFile -foo 1} msg
+ regsub -all , $msg "" options
+ regsub \"-foo\" $options "" options
+
+ foreach option $options {
+ if {[string index $option 0] eq "-"} {
+ test filebox-4.2-$mode$option "tk_getSaveFile command" -body {
+ tk_getSaveFile $option
+ } -returnCodes error -result "value for \"$option\" missing"
+ }
+ }
+
+ test filebox-4.3.1-$mode "tk_getSaveFile command" -constraints notAqua -body {
+ tk_getSaveFile -foo bar
+ } -returnCodes error -result $unknownOptionsMsg(tk_getSaveFile,notAqua)
+ test filebox-4.3.2-$mode "tk_getSaveFile command" -constraints aqua -body {
+ tk_getSaveFile -foo bar
+ } -returnCodes error -result $unknownOptionsMsg(tk_getSaveFile,aqua)
+ test filebox-4.4-$mode "tk_getSaveFile command" -body {
+ tk_getSaveFile -initialdir
+ } -returnCodes error -result {value for "-initialdir" missing}
+ test filebox-4.5-$mode "tk_getSaveFile command" -body {
+ tk_getSaveFile -parent foo.bar
+ } -returnCodes error -result {bad window path name "foo.bar"}
+ test filebox-4.6-$mode "tk_getSaveFile command" -body {
+ tk_getSaveFile -filetypes {Foo}
+ } -returnCodes error -result {bad file type "Foo", should be "typeName {extension ?extensions ...?} ?{macType ?macTypes ...?}?"}
+
+ set isNative [expr {
+ [info commands ::tk::MotifFDialog] eq "" &&
+ [info commands ::tk::dialog::file::] eq ""
+ }]
+
+ set parent .
+
+ set verylongstring longstring:
+ set verylongstring $verylongstring$verylongstring
+ set verylongstring $verylongstring$verylongstring
+ set verylongstring $verylongstring$verylongstring
+ set verylongstring $verylongstring$verylongstring
+ # set verylongstring $verylongstring$verylongstring
+ # set verylongstring $verylongstring$verylongstring
+ # set verylongstring $verylongstring$verylongstring
+ # set verylongstring $verylongstring$verylongstring
+ # set verylongstring $verylongstring$verylongstring
+
+ set color #404040
+ test filebox-5.1-$mode "tk_getSaveFile command" nonUnixUserInteraction {
+ ToPressButton $parent cancel
+ tk_getSaveFile -title "Press Cancel ($verylongstring)" -parent $parent
+ } ""
+
+ set fileName "12x 455"
+ set fileDir [pwd]
+ set pathName [file join [pwd] $fileName]
+
+ test filebox-5.2-$mode "tk_getSaveFile command" nonUnixUserInteraction {
+ ToPressButton $parent ok
+ set choice [tk_getSaveFile -title "Press Ok" \
+ -parent $parent -initialfile $fileName -initialdir $fileDir]
+ } $pathName
+ test filebox-5.3-$mode "tk_getSaveFile command" nonUnixUserInteraction {
+ ToEnterFileByKey $parent $fileName $fileDir
+ set choice [tk_getSaveFile -title "Enter \"$fileName\" and press Ok" \
+ -parent $parent -initialdir $fileDir]
+ } $pathName
+ test filebox-5.4-$mode "tk_getSaveFile command" nonUnixUserInteraction {
+ ToPressButton $parent ok
+ set choice [tk_getSaveFile -title "Enter \"$fileName\" and press Ok" \
+ -parent $parent -initialdir . -initialfile $fileName]
+ } $pathName
+ test filebox-5.5-$mode "tk_getSaveFile command" nonUnixUserInteraction {
+ ToPressButton $parent ok
+ set choice [tk_getSaveFile -title "Enter \"$fileName\" and press Ok" \
+ -parent $parent -initialdir /badpath -initialfile $fileName]
+ } $pathName
+
+ test filebox-5.6-$mode "tk_getSaveFile command" -setup {
+ toplevel .t1; toplevel .t2
+ wm geometry .t1 +0+0
+ wm geometry .t2 +0+0
+ } -constraints nonUnixUserInteraction -body {
+ set choice {}
+ ToPressButton .t1 ok
+ lappend choice [tk_getSaveFile \
+ -title "Enter \"$fileName\" and press Ok" \
+ -parent .t1 -initialdir $fileDir -initialfile $fileName]
+ ToPressButton .t2 ok
+ lappend choice [tk_getSaveFile \
+ -title "Enter \"$fileName\" and press Ok" \
+ -parent .t2 -initialdir $fileDir -initialfile $fileName]
+ ToPressButton .t1 ok
+ lappend choice [tk_getSaveFile \
+ -title "Enter \"$fileName\" and press Ok" \
+ -parent .t1 -initialdir $fileDir -initialfile $fileName]
+ } -result [list $pathName $pathName $pathName] -cleanup {
+ destroy .t1
+ destroy .t2
+ }
+
+ foreach x [lsort -integer [array names filters]] {
+ test filebox-6.$x-$mode "tk_getSaveFile command" nonUnixUserInteraction {
+ ToPressButton $parent ok
+ set choice [tk_getSaveFile -title "Press Ok" \
+ -filetypes $filters($x) -parent $parent \
+ -initialfile $fileName -initialdir $fileDir]
+ } $pathName[lindex $addedExtensions $x]
+ }
+
+ if {!$mode} {
+
+ test filebox-7.1-$mode "tk_getOpenFile - directory not readable" \
+ -constraints nonUnixUserInteraction \
+ -setup {
+ rename ::tk_messageBox ::saved_messageBox
+ set ::gotmessage {}
+ proc tk_messageBox args {
+ set ::gotmessage $args
+ }
+ toplevel .t1
+ file mkdir [file join $fileDir NOTREADABLE]
+ file attributes [file join $fileDir NOTREADABLE] \
+ -permissions 300
+ } \
+ -cleanup {
+ rename ::tk_messageBox {}
+ rename ::saved_messageBox ::tk_messageBox
+ unset ::gotmessage
+ destroy .t1
+ file delete -force [file join $fileDir NOTREADABLE]
+ } \
+ -body {
+ ToEnterFileByKey .t1 NOTREADABLE $fileDir
+ ToPressButton .t1 ok
+ ToPressButton .t1 cancel
+ tk_getOpenFile -parent .t1 \
+ -title "Please select the NOTREADABLE directory" \
+ -initialdir $fileDir
+ set gotmessage
+ } \
+ -match glob \
+ -result "*NOTREADABLE*"
+
+ test filebox-7.2-$mode "tk_getOpenFile - bad file name" \
+ -constraints nonUnixUserInteraction \
+ -setup {
+ rename ::tk_messageBox ::saved_messageBox
+ set ::gotmessage {}
+ proc tk_messageBox args {
+ set ::gotmessage $args
+ }
+ toplevel .t1
+ } \
+ -cleanup {
+ rename ::tk_messageBox {}
+ rename ::saved_messageBox ::tk_messageBox
+ unset ::gotmessage
+ destroy .t1
+ } \
+ -body {
+ ToEnterFileByKey .t1 RUBBISH $fileDir
+ ToPressButton .t1 ok
+ ToPressButton .t1 cancel
+ tk_getOpenFile -parent .t1 \
+ -title "Please enter RUBBISH as a file name" \
+ -initialdir $fileDir
+ set gotmessage
+ } \
+ -match glob \
+ -result "*RUBBISH*"
+ }
+
+ # The rest of the tests need to be executed on Unix only.
+ # They test whether the dialog box widgets were implemented correctly.
+ # These tests are not
+ # needed on the other platforms because they use native file dialogs.
+}
+
+set tk_strictMotif $tk_strictMotif_old
+
+# cleanup
+removeFile filebox.tmp
+cleanupTests
+return
diff --git a/tk8.6/tests/flagdown.xbm b/tk8.6/tests/flagdown.xbm
new file mode 100644
index 0000000..55abc51
--- /dev/null
+++ b/tk8.6/tests/flagdown.xbm
@@ -0,0 +1,27 @@
+#define flagdown_width 48
+#define flagdown_height 48
+static char flagdown_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xe1, 0x00, 0x00,
+ 0x00, 0x00, 0x70, 0x80, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x03, 0x00,
+ 0x00, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x04,
+ 0x00, 0x00, 0x03, 0x00, 0x06, 0x06, 0x00, 0x80, 0x01, 0x00, 0x06, 0x07,
+ 0x00, 0xc0, 0x1f, 0x00, 0x87, 0x07, 0x00, 0xe0, 0x7f, 0x80, 0xc7, 0x07,
+ 0x00, 0x70, 0xe0, 0xc0, 0xe5, 0x07, 0x00, 0x38, 0x80, 0xe1, 0x74, 0x07,
+ 0x00, 0x18, 0x80, 0x71, 0x3c, 0x07, 0x00, 0x0c, 0x00, 0x3b, 0x1e, 0x03,
+ 0x00, 0x0c, 0x00, 0x1f, 0x0f, 0x00, 0x00, 0x86, 0x1f, 0x8e, 0x07, 0x00,
+ 0x00, 0x06, 0x06, 0xc6, 0x05, 0x00, 0x00, 0x06, 0x00, 0xc6, 0x05, 0x00,
+ 0x00, 0x06, 0x00, 0xc6, 0x04, 0x00, 0x00, 0x06, 0x00, 0x06, 0x04, 0x00,
+ 0x7f, 0x06, 0x00, 0x06, 0xe4, 0xff, 0x00, 0x06, 0x00, 0x06, 0x04, 0x00,
+ 0x00, 0x06, 0x00, 0x06, 0x04, 0x00, 0x00, 0x06, 0x00, 0x06, 0x06, 0x00,
+ 0x00, 0x06, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x00, 0x86, 0x01, 0x00,
+ 0x00, 0x06, 0x00, 0xc6, 0x00, 0x00, 0x00, 0x06, 0x00, 0x66, 0x00, 0x00,
+ 0x00, 0x06, 0x00, 0x36, 0x00, 0x00, 0x00, 0x06, 0x00, 0x3e, 0x00, 0x00,
+ 0x00, 0xfe, 0xff, 0x2f, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x27, 0x00, 0x00,
+ 0x00, 0x00, 0x88, 0x20, 0x00, 0x00, 0x00, 0x00, 0x88, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x88, 0x20, 0x00, 0x00, 0x00, 0x00, 0x88, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x88, 0x20, 0x00, 0x00, 0x00, 0x00, 0x88, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x88, 0x20, 0x00, 0x00, 0x00, 0x00, 0x88, 0x20, 0x00, 0x00,
+ 0xf7, 0xbf, 0x8e, 0xfc, 0xdf, 0xf8, 0x9d, 0xeb, 0x9b, 0x76, 0xd2, 0x7a,
+ 0x46, 0x30, 0xe2, 0x0f, 0xe1, 0x47, 0x55, 0x84, 0x48, 0x11, 0x84, 0x19};
diff --git a/tk8.6/tests/flagup.xbm b/tk8.6/tests/flagup.xbm
new file mode 100644
index 0000000..6eb0d84
--- /dev/null
+++ b/tk8.6/tests/flagup.xbm
@@ -0,0 +1,27 @@
+#define flagup_width 48
+#define flagup_height 48
+static char flagup_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00,
+ 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xef, 0x6a, 0x00,
+ 0x00, 0x00, 0xc0, 0x7b, 0x75, 0x00, 0x00, 0x00, 0xe0, 0xe0, 0x6a, 0x00,
+ 0x00, 0x00, 0x30, 0x60, 0x75, 0x00, 0x00, 0x00, 0x18, 0xe0, 0x7f, 0x00,
+ 0x00, 0x00, 0x0c, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x06, 0xe0, 0x04, 0x00,
+ 0x00, 0x00, 0x03, 0xe0, 0x04, 0x00, 0x00, 0x80, 0x01, 0xe0, 0x06, 0x00,
+ 0x00, 0xc0, 0x1f, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x7f, 0xe0, 0x07, 0x00,
+ 0x00, 0x70, 0xe0, 0xe0, 0x05, 0x00, 0x00, 0x38, 0x80, 0xe1, 0x04, 0x00,
+ 0x00, 0x18, 0x80, 0xf1, 0x04, 0x00, 0x00, 0x0c, 0x00, 0xfb, 0x04, 0x00,
+ 0x00, 0x0c, 0x00, 0xff, 0x04, 0x00, 0x00, 0x86, 0x1f, 0xee, 0x04, 0x00,
+ 0x00, 0x06, 0x06, 0xe6, 0x04, 0x00, 0x00, 0x06, 0x00, 0xe6, 0x04, 0x00,
+ 0x00, 0x06, 0x00, 0xe6, 0x04, 0x00, 0x00, 0x06, 0x00, 0x66, 0x04, 0x00,
+ 0x7f, 0x56, 0x52, 0x06, 0xe4, 0xff, 0x00, 0x76, 0x55, 0x06, 0x04, 0x00,
+ 0x00, 0x56, 0x57, 0x06, 0x04, 0x00, 0x00, 0x56, 0x55, 0x06, 0x06, 0x00,
+ 0x00, 0x56, 0xd5, 0x06, 0x03, 0x00, 0x00, 0x06, 0x00, 0x86, 0x01, 0x00,
+ 0x54, 0x06, 0x00, 0xc6, 0x54, 0x55, 0xaa, 0x06, 0x00, 0x66, 0xaa, 0x2a,
+ 0x54, 0x06, 0x00, 0x36, 0x55, 0x55, 0xaa, 0x06, 0x00, 0xbe, 0xaa, 0x2a,
+ 0x54, 0xfe, 0xff, 0x6f, 0x55, 0x55, 0xaa, 0xfc, 0xff, 0xa7, 0xaa, 0x2a,
+ 0x54, 0x01, 0x88, 0x60, 0x55, 0x55, 0xaa, 0xaa, 0x8a, 0xa0, 0xaa, 0x2a,
+ 0x54, 0x55, 0x8d, 0x60, 0x55, 0x55, 0xaa, 0xaa, 0x8a, 0xa0, 0xaa, 0x2a,
+ 0x54, 0x55, 0x8d, 0x60, 0x55, 0x55, 0xaa, 0xaa, 0x8a, 0xa0, 0xaa, 0x2a,
+ 0x54, 0x55, 0x8d, 0x50, 0x55, 0x55, 0xaa, 0xaa, 0x8a, 0xa8, 0xaa, 0x2a,
+ 0x54, 0x55, 0x95, 0x54, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a,
+ 0x54, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/tk8.6/tests/focus.test b/tk8.6/tests/focus.test
new file mode 100644
index 0000000..45cf73b
--- /dev/null
+++ b/tk8.6/tests/focus.test
@@ -0,0 +1,739 @@
+# This file is a Tcl script to test out the "focus" command and the
+# other procedures in the file tkFocus.c. It is organized in the
+# standard fashion for Tcl tests.
+#
+# Copyright (c) 1994-1996 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+namespace import -force tcltest::test
+
+proc focusSetup {} {
+ destroy .t
+ toplevel .t
+ wm geom .t +0+0
+ foreach i {b1 b2 b3 b4} {
+ button .t.$i -text .t.$i -relief raised -bd 2
+ pack .t.$i
+ }
+ tkwait visibility .t.b4
+}
+proc focusSetupAlt {} {
+ global env
+ destroy .alt
+ toplevel .alt -screen $env(TK_ALT_DISPLAY)
+ foreach i {a b c d} {
+ button .alt.$i -text .alt.$i -relief raised -bd 2
+ pack .alt.$i
+ }
+ tkwait visibility .alt.d
+}
+
+
+# The following procedure ensures that there is no input focus
+# in this application. It does it by arranging for another
+# application to grab the focus. The "after" and "update" stuff
+# is needed to wait long enough for pending actions to get through
+# the X server and possibly also the window manager.
+
+proc focusClear {} {
+ global x;
+ after 200 {set x 1}
+ tkwait variable x
+ dobg {focus -force .; update}
+ update
+}
+
+
+# Button used in some tests in the whole test file
+button .b -text .b -relief raised -bd 2
+pack .b
+
+# Make sure the window manager knows who has focus
+catch {fixfocus}
+
+# cleanupbg will be after 4.3 test
+setupbg
+update
+bind all <FocusIn> {
+ append focusInfo "in %W %d\n"
+}
+bind all <FocusOut> {
+ append focusInfo "out %W %d\n"
+}
+bind all <KeyPress> {
+ append focusInfo "press %W %K"
+}
+focusSetup
+if {[testConstraint altDisplay]} {
+ focusSetupAlt
+}
+
+
+test focus-1.1 {Tk_FocusCmd procedure} -constraints unix -body {
+ focusClear
+ focus
+} -result {}
+test focus-1.2 {Tk_FocusCmd procedure} -constraints {
+ unix altDisplay
+} -body {
+ focus .alt.b
+ focus
+} -result {}
+test focus-1.3 {Tk_FocusCmd procedure} -constraints unix -body {
+ focusClear
+ focus .t.b3
+ focus
+} -result {}
+test focus-1.4 {Tk_FocusCmd procedure} -constraints unix -body {
+ focus ""
+} -returnCodes ok -result {}
+test focus-1.5 {Tk_FocusCmd procedure} -constraints unix -body {
+ focusClear
+ focus -force .t
+ focus .t.b3
+ focus
+} -result {.t.b3}
+test focus-1.6 {Tk_FocusCmd procedure} -constraints unix -body {
+ focus .gorp
+} -returnCodes error -result {bad window path name ".gorp"}
+test focus-1.7 {Tk_FocusCmd procedure} -constraints unix -body {
+ focus .gorp a
+} -returnCodes error -result {bad option ".gorp": must be -displayof, -force, or -lastfor}
+test focus-1.8 {Tk_FocusCmd procedure, focussing on dead window} -constraints {
+ unix
+} -setup {
+ destroy .t2
+} -body {
+ focusClear
+ toplevel .t2
+ wm geom .t2 +10+10
+ frame .t2.f -width 200 -height 100 -bd 2 -relief raised
+ frame .t2.f2 -width 200 -height 100 -bd 2 -relief raised
+ pack .t2.f .t2.f2
+ bind .t2.f <Destroy> {focus .t2.f}
+ bind .t2.f2 <Destroy> {focus .t2}
+ focus -force .t2.f2
+ tkwait visibility .t2.f2
+ update
+ set x [focus]
+ destroy .t2.f2
+ lappend x [focus]
+ destroy .t2.f
+ lappend x [focus]
+ destroy .t2
+ return $x
+} -cleanup {
+ destroy .t2
+} -result {.t2.f2 .t2 .t2}
+test focus-1.9 {Tk_FocusCmd procedure, -displayof option} -constraints {
+ unix
+} -body {
+ focus -displayof
+} -returnCodes error -result {wrong # args: should be "focus -displayof window"}
+test focus-1.10 {Tk_FocusCmd procedure, -displayof option} -constraints {
+ unix
+} -body {
+ focus -displayof a b
+} -returnCodes error -result {wrong # args: should be "focus -displayof window"}
+test focus-1.11 {Tk_FocusCmd procedure, -displayof option} -constraints {
+ unix
+} -body {
+ focus -displayof .lousy
+} -returnCodes error -result {bad window path name ".lousy"}
+test focus-1.12 {Tk_FocusCmd procedure, -displayof option} -constraints {
+ unix
+} -body {
+ focusClear
+ focus .t
+ focus -displayof .t.b3
+} -result {}
+test focus-1.13 {Tk_FocusCmd procedure, -displayof option} -constraints {
+ unix
+} -body {
+ focusClear
+ focus -force .t
+ focus -displayof .t.b3
+} -result {.t}
+test focus-1.14 {Tk_FocusCmd procedure, -displayof option} -constraints {
+ unix altDisplay
+} -body {
+ focusClear
+ focus -force .alt.c
+ focus -displayof .alt
+} -result {.alt.c}
+test focus-1.15 {Tk_FocusCmd procedure, -force option} -constraints unix -body {
+ focus -force
+} -returnCodes error -result {wrong # args: should be "focus -force window"}
+test focus-1.16 {Tk_FocusCmd procedure, -force option} -constraints unix -body {
+ focus -force a b
+} -returnCodes error -result {wrong # args: should be "focus -force window"}
+test focus-1.17 {Tk_FocusCmd procedure, -force option} -constraints unix -body {
+ focus -force foo
+} -returnCodes error -result {bad window path name "foo"}
+test focus-1.18 {Tk_FocusCmd procedure, -force option} -constraints unix -body {
+ focus -force ""
+} -returnCodes ok -result {}
+test focus-1.19 {Tk_FocusCmd procedure, -force option} -constraints unix -body {
+ focusClear
+ focus .t.b1
+ set x [list [focus]]
+ focus -force .t.b1
+ lappend x [focus]
+} -result {{} .t.b1}
+test focus-1.20 {Tk_FocusCmd procedure, -lastfor option} -constraints {
+ unix
+} -body {
+ focus -lastfor
+} -returnCodes error -result {wrong # args: should be "focus -lastfor window"}
+test focus-1.21 {Tk_FocusCmd procedure, -lastfor option} -constraints {
+ unix
+} -body {
+ focus -lastfor 1 2
+} -returnCodes error -result {wrong # args: should be "focus -lastfor window"}
+test focus-1.22 {Tk_FocusCmd procedure, -lastfor option} -constraints {
+ unix
+} -body {
+ focus -lastfor who_knows?
+} -returnCodes error -result {bad window path name "who_knows?"}
+test focus-1.23 {Tk_FocusCmd procedure, -lastfor option} -constraints {
+ unix
+} -body {
+ focusClear
+ focusSetup
+ focus .b
+ focus .t.b1
+ list [focus -lastfor .] [focus -lastfor .t.b3]
+} -result {.b .t.b1}
+test focus-1.24 {Tk_FocusCmd procedure, -lastfor option} -constraints {
+ unix
+} -body {
+ focusClear
+ focusSetup
+ update
+ focus -lastfor .t.b2
+} -result {.t}
+test focus-1.25 {Tk_FocusCmd procedure} -constraints unix -body {
+ focus -unknown
+} -returnCodes error -result {bad option "-unknown": must be -displayof, -force, or -lastfor}
+
+
+focusSetup
+test focus-2.1 {TkFocusFilterEvent procedure} -constraints {
+ unix nonPortable testwrapper
+} -body {
+ focusClear
+ focus -force .b
+ focusSetup
+ update
+ set focusInfo {}
+ event gen [testwrapper .t] <FocusIn> -detail NotifyAncestor \
+ -sendevent 0x54217567
+ return $focusInfo
+} -result {}
+test focus-2.2 {TkFocusFilterEvent procedure} -constraints {
+ unix nonPortable testwrapper
+} -body {
+ focusClear
+ focus -force .b
+ focusSetup
+ update
+ set focusInfo {}
+ event gen .t <FocusIn> -detail NotifyAncestor -sendevent 0x547321ac
+ list $focusInfo [focus]
+} -result {{in .t NotifyAncestor
+} .b}
+test focus-2.3 {TkFocusFilterEvent procedure} -constraints {
+ unix nonPortable testwrapper
+} -body {
+ focusClear
+ focus -force .b
+ focusSetup
+ update
+ set focusInfo {}
+ event gen [testwrapper .t] <FocusIn> -detail NotifyAncestor
+ update
+ list $focusInfo [focus -lastfor .t]
+} -result {{out .b NotifyNonlinear
+out . NotifyNonlinearVirtual
+in .t NotifyNonlinear
+} .t}
+test focus-2.4 {TkFocusFilterEvent procedure, FocusIn events} -constraints {
+ unix nonPortable testwrapper
+} -body {
+ focusClear
+ set result {}
+ focus .t.b1
+ # Important to end with NotifyAncestor, which is an
+ # event that is processed normally. This has a side
+ # effect on text 2.5
+ foreach detail {NotifyAncestor NotifyNonlinear
+ NotifyNonlinearVirtual NotifyPointer NotifyPointerRoot
+ NotifyVirtual NotifyAncestor} {
+ focus -force .
+ update
+ event gen [testwrapper .t] <FocusIn> -detail $detail
+ set focusInfo {}
+ update
+ lappend result $focusInfo
+ }
+ return $result
+} -result {{out . NotifyNonlinear
+in .t NotifyNonlinearVirtual
+in .t.b1 NotifyNonlinear
+} {out . NotifyNonlinear
+in .t NotifyNonlinearVirtual
+in .t.b1 NotifyNonlinear
+} {} {out . NotifyNonlinear
+in .t NotifyNonlinearVirtual
+in .t.b1 NotifyNonlinear
+} {} {} {out . NotifyNonlinear
+in .t NotifyNonlinearVirtual
+in .t.b1 NotifyNonlinear
+}}
+test focus-2.5 {TkFocusFilterEvent procedure, creating FocusInfo struct} -constraints {
+ unix nonPortable testwrapper
+} -body {
+ focusSetup
+ focus .t.b1
+ update
+ event gen [testwrapper .t] <FocusIn> -detail NotifyAncestor
+ list $focusInfo [focus]
+} -result {{out . NotifyNonlinear
+in .t NotifyNonlinearVirtual
+in .t.b1 NotifyNonlinear
+} .t.b1}
+
+test focus-2.6 {TkFocusFilterEvent procedure, FocusIn events} -constraints {
+ unix testwrapper
+} -body {
+ focus .t.b1
+ focus .
+ update
+ event gen [testwrapper .t] <FocusIn> -detail NotifyAncestor
+ set focusInfo {}
+ set x [focus]
+ event gen . <KeyPress-x>
+ list $x $focusInfo
+} -result {.t.b1 {press .t.b1 x}}
+test focus-2.7 {TkFocusFilterEvent procedure, FocusOut events} -constraints {
+ unix testwrapper
+} -body {
+ set result {}
+ foreach detail {NotifyAncestor NotifyInferior NotifyNonlinear
+ NotifyNonlinearVirtual NotifyPointer NotifyPointerRoot
+ NotifyVirtual} {
+ focus -force .t.b1
+ event gen [testwrapper .t] <FocusOut> -detail $detail
+ update
+ lappend result [focus]
+ }
+ return $result
+} -result {{} .t.b1 {} {} .t.b1 .t.b1 {}}
+test focus-2.8 {TkFocusFilterEvent procedure, FocusOut events} -constraints {
+ unix testwrapper
+} -body {
+ focus -force .t.b1
+ event gen .t.b1 <FocusOut> -detail NotifyAncestor
+ focus
+} -result {.t.b1}
+test focus-2.9 {TkFocusFilterEvent procedure, FocusOut events} -constraints {
+ unix testwrapper
+} -body {
+ focus .t.b1
+ event gen [testwrapper .] <FocusOut> -detail NotifyAncestor
+ focus
+} -result {}
+test focus-2.10 {TkFocusFilterEvent procedure, Enter events} -constraints {
+ unix testwrapper
+} -body {
+ set result {}
+ focus .t.b1
+ focusClear
+ foreach detail {NotifyAncestor NotifyInferior NotifyNonlinear
+ NotifyNonlinearVirtual NotifyVirtual} {
+ event gen [testwrapper .t] <Enter> -detail $detail -focus 1
+ update
+ lappend result [focus]
+ event gen [testwrapper .t] <Leave> -detail NotifyAncestor
+ update
+ }
+ return $result
+} -result {.t.b1 {} .t.b1 .t.b1 .t.b1}
+test focus-2.11 {TkFocusFilterEvent procedure, Enter events} -constraints {
+ unix testwrapper
+} -body {
+ focusClear
+ set focusInfo {}
+ event gen [testwrapper .t] <Enter> -detail NotifyAncestor
+ update
+ return $focusInfo
+} -result {}
+test focus-2.12 {TkFocusFilterEvent procedure, Enter events} -constraints {
+ unix testwrapper
+} -body {
+ focus -force .b
+ update
+ set focusInfo {}
+ event gen [testwrapper .t] <Enter> -detail NotifyAncestor -focus 1
+ update
+ return $focusInfo
+} -result {}
+test focus-2.13 {TkFocusFilterEvent procedure, Enter events} -constraints {
+ unix testwrapper
+} -body {
+ focus .t.b1
+ focusClear
+ event gen [testwrapper .t] <Enter> -detail NotifyAncestor -focus 1
+ set focusInfo {}
+ update
+ return $focusInfo
+} -result {in .t NotifyVirtual
+in .t.b1 NotifyAncestor
+}
+test focus-2.14 {TkFocusFilterEvent procedure, Enter events, ignore errors when setting focus due to implicit focus} -constraints {
+ unix testwrapper
+} -setup {
+ destroy .t2
+ set focusInfo {}
+} -body {
+ focusClear
+ toplevel .t2
+ wm withdraw .t2
+ update
+ event gen [testwrapper .t2] <Enter> -detail NotifyAncestor -focus 1
+ update
+} -cleanup {
+ destroy .t2
+} -result {}
+test focus-2.15 {TkFocusFilterEvent procedure, Leave events} -constraints {
+ unix testwrapper
+} -body {
+ set result {}
+ focus .t.b1
+ foreach detail {NotifyAncestor NotifyInferior NotifyNonlinear
+ NotifyNonlinearVirtual NotifyVirtual} {
+ focusClear
+ event gen [testwrapper .t] <Enter> -detail NotifyAncestor -focus 1
+ update
+ event gen [testwrapper .t] <Leave> -detail $detail
+ update
+ lappend result [focus]
+ }
+ return $result
+} -result {{} .t.b1 {} {} {}}
+test focus-2.16 {TkFocusFilterEvent procedure, Leave events} -constraints {
+ unix testwrapper
+} -body {
+ focusClear
+ focus .t.b1
+ event gen [testwrapper .t] <Enter> -detail NotifyAncestor -focus 1
+ update
+ set focusInfo {}
+ event gen [testwrapper .t] <Leave> -detail NotifyAncestor
+ update
+ return $focusInfo
+} -result {out .t.b1 NotifyAncestor
+out .t NotifyVirtual
+}
+test focus-2.17 {TkFocusFilterEvent procedure, Leave events} -constraints {
+ unix testwrapper
+} -body {
+ focusClear
+ focus .t.b1
+ event gen [testwrapper .t] <Enter> -detail NotifyAncestor -focus 1
+ update
+ set focusInfo {}
+ event gen .t.b1 <Leave> -detail NotifyAncestor
+ event gen [testwrapper .] <Leave> -detail NotifyAncestor
+ update
+ list $focusInfo [focus]
+} -result {{out .t.b1 NotifyAncestor
+out .t NotifyVirtual
+} {}}
+
+
+test focus-3.1 {SetFocus procedure, create record on focus} -constraints {
+ unix testwrapper
+} -body {
+ toplevel .t2 -width 250 -height 100
+ wm geometry .t2 +0+0
+ update
+ focus -force .t2
+ update
+ focus
+} -cleanup {
+ destroy .t2
+} -result {.t2}
+# This test produces no result, but it will generate a protocol
+# error if Tk forgets to make the window exist before focussing
+# on it.
+test focus-3.2 {SetFocus procedure, making window exist} -constraints {
+ unix testwrapper
+} -body {
+ update
+ button .b2 -text "Another button"
+ focus .b2
+ update
+} -cleanup {
+ destroy .b2
+ update
+} -result {}
+# The following test doesn't produce a check-able result, but if
+# there are bugs it may generate an X protocol error.
+test focus-3.3 {SetFocus procedure, delaying claim of X focus} -constraints {
+ unix testwrapper
+} -body {
+ focusSetup
+ focus -force .t.b2
+ update
+} -result {}
+test focus-3.4 {SetFocus procedure, delaying claim of X focus} -constraints {
+ unix testwrapper
+} -body {
+ focusSetup
+ wm withdraw .t
+ focus -force .t.b2
+ toplevel .t2 -width 250 -height 100
+ wm geometry .t2 +10+10
+ focus -force .t2
+ wm withdraw .t2
+ update
+ wm deiconify .t2
+ wm deiconify .t
+} -cleanup {
+ destroy .t2
+} -result {}
+test focus-3.5 {SetFocus procedure, generating events} -constraints {
+ unix testwrapper
+} -body {
+ focusSetup
+ focusClear
+ set focusInfo {}
+ focus -force .t.b2
+ update
+ return $focusInfo
+} -result {in .t NotifyVirtual
+in .t.b2 NotifyAncestor
+}
+test focus-3.6 {SetFocus procedure, generating events} -constraints {
+ unix testwrapper
+} -body {
+ focusSetup
+ focus -force .b
+ update
+ set focusInfo {}
+ focus .t.b2
+ update
+ return $focusInfo
+} -result {out .b NotifyNonlinear
+out . NotifyNonlinearVirtual
+in .t NotifyNonlinearVirtual
+in .t.b2 NotifyNonlinear
+}
+test focus-3.7 {SetFocus procedure, generating events} -constraints {
+unix nonPortable testwrapper
+} -body {
+ # Non-portable because some platforms generate extra events.
+ focusSetup
+ focusClear
+ set focusInfo {}
+ focus .t.b2
+ update
+ return $focusInfo
+} -result {}
+
+
+test focus-4.1 {TkFocusDeadWindow procedure} -constraints {
+ unix testwrapper
+} -body {
+ focusSetup
+ update
+ focus -force .b
+ update
+ destroy .t
+ focus
+} -result {.b}
+test focus-4.2 {TkFocusDeadWindow procedure} -constraints {
+ unix testwrapper
+} -body {
+ focusSetup
+ update
+ focus -force .t.b2
+ focus .b
+ update
+ destroy .t.b2
+ update
+ focus
+} -result {.b}
+# Non-portable due to wm-specific redirection of input focus when
+# windows are deleted:
+test focus-4.3 {TkFocusDeadWindow procedure} -constraints {
+ unix nonPortable testwrapper
+} -body {
+ focusSetup
+ update
+ focus .t
+ update
+ destroy .t
+ update
+ focus
+} -result {}
+test focus-4.4 {TkFocusDeadWindow procedure} -constraints {
+ unix testwrapper
+} -body {
+ focusSetup
+ focus -force .t.b2
+ update
+ destroy .t.b2
+ focus
+} -result {.t}
+cleanupbg
+
+
+# I don't know how to test most of the remaining procedures of this file
+# explicitly; they've already been exercised by the preceding tests.
+
+# Test 5.1 fails (before and after update)
+test focus-5.1 {ChangeXFocus procedure, don't take focus unless have it} -constraints {
+ unix testwrapper secureserver
+} -body {
+ setupbg
+ focusSetup
+ focus -force .t
+ update
+ set result [focus]
+ send [dobg {tk appname}] {focus -force .; update}
+ lappend result [focus]
+ focus .t.b2
+ update
+ lappend result [focus]
+} -cleanup {
+ cleanupbg
+} -result {.t {} {}}
+destroy .t
+bind all <FocusIn> {}
+bind all <FocusOut> {}
+bind all <KeyPress> {}
+
+
+fixfocus
+test focus-6.1 {miscellaneous - embedded application in same process} -constraints {
+ unix testwrapper
+} -setup {
+ eval interp delete [interp slaves]
+} -body {
+ toplevel .t
+ wm geometry .t +0+0
+ frame .t.f1 -container 1
+ frame .t.f2
+ pack .t.f1 .t.f2
+ entry .t.f2.e1 -bg red
+ pack .t.f2.e1
+ bind all <FocusIn> {lappend x "focus in %W %d"}
+ bind all <FocusOut> {lappend x "focus out %W %d"}
+ interp create child
+ child eval "set argv {-use [winfo id .t.f1]}"
+ load {} Tk child
+ child eval {
+ entry .e1 -bg lightBlue
+ pack .e1
+ bind all <FocusIn> {lappend x "focus in %W %d"}
+ bind all <FocusOut> {lappend x "focus out %W %d"}
+ set x {}
+ }
+
+ # Claim the focus and wait long enough for it to really arrive.
+
+ focus -force .t.f2.e1
+ after 300 {set timer 1}
+ vwait timer
+ set x {}
+ lappend x [focus] [child eval focus]
+
+ # See if a "focus" command will move the focus to the embedded
+ # application.
+
+ child eval {focus .e1}
+ after 300 {set timer 1}
+ vwait timer
+ lappend x |
+ child eval {lappend x |}
+
+ # Bring the focus back to the main application.
+
+ focus .t.f2.e1
+ after 300 {set timer 1}
+ vwait timer
+ set result [list $x [child eval {set x}]]
+ return $result
+} -cleanup {
+ interp delete child
+ destroy .t
+ bind all <FocusIn> {}
+ bind all <FocusOut> {}
+} -result {{.t.f2.e1 {} {focus out .t.f2.e1 NotifyNonlinear} {focus out .t.f2 NotifyNonlinearVirtual} {focus in .t.f1 NotifyNonlinear} | {focus out .t.f1 NotifyNonlinear} {focus in .t.f2 NotifyNonlinearVirtual} {focus in .t.f2.e1 NotifyNonlinear}} {{focus in . NotifyVirtual} {focus in .e1 NotifyAncestor} | {focus out .e1 NotifyAncestor} {focus out . NotifyVirtual}}}
+
+test focus-6.2 {miscellaneous - embedded application in different process} -constraints {
+ unix testwrapper
+} -body {
+ setupbg
+ toplevel .t
+ wm geometry .t +0+0
+ frame .t.f1 -container 1
+ frame .t.f2
+ pack .t.f1 .t.f2
+ entry .t.f2.e1 -bg red
+ pack .t.f2.e1
+ bind all <FocusIn> {lappend x "focus in %W %d"}
+ bind all <FocusOut> {lappend x "focus out %W %d"}
+ setupbg -use [winfo id .t.f1]
+ dobg {
+ entry .e1 -bg lightBlue
+ pack .e1
+ bind all <FocusIn> {lappend x "focus in %W %d"}
+ bind all <FocusOut> {lappend x "focus out %W %d"}
+ set x {}
+ }
+
+ # Claim the focus and wait long enough for it to really arrive.
+
+ focus -force .t.f2.e1
+ after 300 {set timer 1}
+ vwait timer
+ set x {}
+ lappend x [focus] [dobg focus]
+
+ # See if a "focus" command will move the focus to the embedded
+ # application.
+
+ dobg {focus .e1}
+ after 300 {set timer 1}
+ vwait timer
+ lappend x |
+ dobg {lappend x |}
+
+ # Bring the focus back to the main application.
+
+ focus .t.f2.e1
+ after 300 {set timer 1}
+ vwait timer
+ set result [list $x [dobg {set x}]]
+ return $result
+} -cleanup {
+ destroy .t
+ cleanupbg
+ bind all <FocusIn> {}
+ bind all <FocusOut> {}
+} -result {{.t.f2.e1 {} {focus out .t.f2.e1 NotifyNonlinear} {focus out .t.f2 NotifyNonlinearVirtual} {focus in .t.f1 NotifyNonlinear} | {focus out .t.f1 NotifyNonlinear} {focus in .t.f2 NotifyNonlinearVirtual} {focus in .t.f2.e1 NotifyNonlinear}} {{focus in . NotifyVirtual} {focus in .e1 NotifyAncestor} | {focus out .e1 NotifyAncestor} {focus out . NotifyVirtual}}}
+
+
+
+deleteWindows
+
+# cleanup
+cleanupTests
+return
diff --git a/tk8.6/tests/focusTcl.test b/tk8.6/tests/focusTcl.test
new file mode 100644
index 0000000..0e457a6
--- /dev/null
+++ b/tk8.6/tests/focusTcl.test
@@ -0,0 +1,485 @@
+# This file is a Tcl script to test out the features of the script
+# file focus.tcl, which includes the procedures tk_focusNext and
+# tk_focusPrev, among other things. This file is organized in the
+# standard fashion for Tcl tests.
+#
+# Copyright (c) 1995 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+namespace import -force tcltest::test
+
+option add *takeFocus 1
+option add *highlightThickness 2
+. configure -takefocus 1 -highlightthickness 2
+
+proc setup1 w {
+ if {$w == "."} {
+ set w ""
+ }
+ foreach i {a b c d} {
+ destroy $w.$i
+ frame $w.$i -width 200 -height 50 -bd 2 -relief raised
+ pack $w.$i
+ }
+ .b configure -width 0 -height 0
+ foreach i {x y z} {
+ destroy $w.b.$i
+ button $w.b.$i -text "Button $w.b.$i"
+ pack $w.b.$i -side left
+ }
+ if {![winfo ismapped $w.b.z]} {
+ tkwait visibility $w.b.z
+ }
+}
+
+proc cleanup1 w {
+ if {$w == "."} {
+ set w ""
+ }
+ foreach i {a b c d} {
+ destroy $w.$i
+ }
+ foreach i {x y z} {
+ destroy $w.b.$i
+ }
+}
+
+
+test focusTcl-1.1 {tk_focusNext procedure, no children} -body {
+ tk_focusNext .
+} -result {.}
+
+test focusTcl-1.2 {tk_focusNext procedure, basic tree traversal} -body {
+ setup1 .
+ tk_focusNext .
+} -cleanup {
+ cleanup1 .
+} -result {.a}
+test focusTcl-1.3 {tk_focusNext procedure, basic tree traversal} -body {
+ setup1 .
+ tk_focusNext .a
+} -cleanup {
+ cleanup1 .
+} -result {.b}
+test focusTcl-1.4 {tk_focusNext procedure, basic tree traversal} -body {
+ setup1 .
+ tk_focusNext .b
+} -cleanup {
+ cleanup1 .
+} -result {.b.x}
+test focusTcl-1.5 {tk_focusNext procedure, basic tree traversal} -body {
+ setup1 .
+ tk_focusNext .b.x
+} -cleanup {
+ cleanup1 .
+} -result {.b.y}
+test focusTcl-1.6 {tk_focusNext procedure, basic tree traversal} -body {
+ setup1 .
+ tk_focusNext .b.y
+} -cleanup {
+ cleanup1 .
+} -result {.b.z}
+test focusTcl-1.7 {tk_focusNext procedure, basic tree traversal} -body {
+ setup1 .
+ tk_focusNext .b.z
+} -cleanup {
+ cleanup1 .
+} -result {.c}
+test focusTcl-1.8 {tk_focusNext procedure, basic tree traversal} -body {
+ setup1 .
+ tk_focusNext .c
+} -cleanup {
+ cleanup1 .
+} -result {.d}
+test focusTcl-1.9 {tk_focusNext procedure, basic tree traversal} -body {
+ setup1 .
+ tk_focusNext .d
+} -cleanup {
+ cleanup1 .
+} -result {.}
+
+test focusTcl-1.10 {tk_focusNext procedure, basic tree traversal} -body {
+ setup1 .
+ foreach w {.b .b.x .b.y .c .d} {
+ $w configure -takefocus 0
+ }
+ tk_focusNext .a
+} -cleanup {
+ cleanup1 .
+} -result {.b.z}
+test focusTcl-1.11 {tk_focusNext procedure, basic tree traversal} -body {
+ setup1 .
+ foreach w {.b .b.x .b.y .c .d} {
+ $w configure -takefocus 0
+ }
+ tk_focusNext .b.z
+} -cleanup {
+ cleanup1 .
+} -result {.}
+
+test focusTcl-1.12 {tk_focusNext procedure, basic tree traversal} -body {
+ setup1 .
+ deleteWindows
+ setup1 .
+ update
+ . configure -takefocus 0
+ tk_focusNext .d
+} -cleanup {
+ . configure -takefocus 1
+ cleanup1 .
+} -result {.a}
+
+
+test focusTcl-2.1 {tk_focusNext procedure, toplevels} -setup {
+ deleteWindows
+} -body {
+ setup1 .
+ toplevel .t
+ wm geom .t +0+0
+ toplevel .t2
+ wm geom .t2 -0+0
+ raise .t .a
+
+ tk_focusNext .a
+} -cleanup {
+ deleteWindows
+} -result {.b}
+test focusTcl-2.2 {tk_focusNext procedure, toplevels} -setup {
+ deleteWindows
+} -body {
+ setup1 .
+ toplevel .t
+ wm geom .t +0+0
+ toplevel .t2
+ wm geom .t2 -0+0
+ raise .t .a
+
+ tk_focusNext .d
+} -cleanup {
+ deleteWindows
+} -result {.}
+test focusTcl-2.3 {tk_focusNext procedure, toplevels} -setup {
+ deleteWindows
+} -body {
+ setup1 .
+ toplevel .t
+ wm geom .t +0+0
+ toplevel .t2
+ wm geom .t2 -0+0
+ raise .t .a
+
+ tk_focusNext .t
+} -cleanup {
+ deleteWindows
+} -result {.t}
+test focusTcl-2.4 {tk_focusNext procedure, toplevels} -setup {
+ deleteWindows
+} -body {
+ setup1 .
+ toplevel .t
+ wm geom .t +0+0
+ toplevel .t2
+ wm geom .t2 -0+0
+ raise .t .a
+ setup1 .t
+ raise .t.b
+
+ tk_focusNext .t
+} -cleanup {
+ deleteWindows
+} -result {.t.a}
+test focusTcl-2.5 {tk_focusNext procedure, toplevels} -setup {
+ deleteWindows
+} -body {
+ setup1 .
+ toplevel .t
+ wm geom .t +0+0
+ toplevel .t2
+ wm geom .t2 -0+0
+ raise .t .a
+ setup1 .t
+ raise .t.b
+
+ tk_focusNext .t.b.z
+} -cleanup {
+ deleteWindows
+} -result {.t}
+
+
+test focusTcl-3.1 {tk_focusPrev procedure, no children} -body {
+ tk_focusPrev .
+} -result {.}
+
+test focusTcl-3.2 {tk_focusPrev procedure, basic tree traversal} -body {
+ setup1 .
+ tk_focusPrev .
+} -cleanup {
+ cleanup1 .
+} -result {.d}
+test focusTcl-3.3 {tk_focusPrev procedure, basic tree traversal} -body {
+ setup1 .
+ tk_focusPrev .d
+} -cleanup {
+ cleanup1 .
+} -result {.c}
+test focusTcl-3.4 {tk_focusPrev procedure, basic tree traversal} -body {
+ setup1 .
+ tk_focusPrev .c
+} -cleanup {
+ cleanup1 .
+} -result {.b.z}
+test focusTcl-3.5 {tk_focusPrev procedure, basic tree traversal} -body {
+ setup1 .
+ tk_focusPrev .b.z
+} -cleanup {
+ cleanup1 .
+} -result {.b.y}
+test focusTcl-3.6 {tk_focusPrev procedure, basic tree traversal} -body {
+ setup1 .
+ tk_focusPrev .b.y
+} -cleanup {
+ cleanup1 .
+} -result {.b.x}
+test focusTcl-3.7 {tk_focusPrev procedure, basic tree traversal} -body {
+ setup1 .
+ tk_focusPrev .b.x
+} -cleanup {
+ cleanup1 .
+} -result {.b}
+test focusTcl-3.8 {tk_focusPrev procedure, basic tree traversal} -body {
+ setup1 .
+ tk_focusPrev .b
+} -cleanup {
+ cleanup1 .
+} -result {.a}
+test focusTcl-3.9 {tk_focusPrev procedure, basic tree traversal} -body {
+ setup1 .
+ tk_focusPrev .a
+} -cleanup {
+ cleanup1 .
+} -result {.}
+
+
+deleteWindows
+setup1 .
+toplevel .t
+wm geom .t +0+0
+toplevel .t2
+wm geom .t2 -0+0
+raise .t .a
+test focusTcl-4.1 {tk_focusPrev procedure, toplevels} -setup {
+ deleteWindows
+} -body {
+ setup1 .
+ toplevel .t
+ wm geom .t +0+0
+ toplevel .t2
+ wm geom .t2 -0+0
+ raise .t .a
+
+ tk_focusPrev .
+} -cleanup {
+ deleteWindows
+} -result {.d}
+test focusTcl-4.2 {tk_focusPrev procedure, toplevels} -setup {
+ deleteWindows
+} -body {
+ setup1 .
+ toplevel .t
+ wm geom .t +0+0
+ toplevel .t2
+ wm geom .t2 -0+0
+ raise .t .a
+
+ tk_focusPrev .b
+} -cleanup {
+ deleteWindows
+} -result {.a}
+test focusTcl-4.3 {tk_focusPrev procedure, toplevels} -setup {
+ deleteWindows
+} -body {
+ setup1 .
+ toplevel .t
+ wm geom .t +0+0
+ toplevel .t2
+ wm geom .t2 -0+0
+ raise .t .a
+
+ tk_focusPrev .t
+} -cleanup {
+ deleteWindows
+} -result {.t}
+
+test focusTcl-4.4 {tk_focusPrev procedure, toplevels} -setup {
+ deleteWindows
+} -body {
+ setup1 .
+ toplevel .t
+ wm geom .t +0+0
+ toplevel .t2
+ wm geom .t2 -0+0
+ raise .t .a
+ setup1 .t
+ update
+ .t configure -takefocus 0
+ raise .t.b
+
+ tk_focusPrev .t
+} -cleanup {
+ deleteWindows
+} -result {.t.b.z}
+test focusTcl-4.5 {tk_focusPrev procedure, toplevels} -setup {
+ deleteWindows
+} -body {
+ setup1 .
+ toplevel .t
+ wm geom .t +0+0
+ toplevel .t2
+ wm geom .t2 -0+0
+ raise .t .a
+ setup1 .t
+ update
+ .t configure -takefocus 0
+ raise .t.b
+
+ tk_focusPrev .t.a
+} -cleanup {
+ deleteWindows
+} -result {.t.b.z}
+
+
+test focusTcl-5.1 {tkFocusOK procedure, -takefocus 0} -body {
+ setup1 .
+ .b.x configure -takefocus 0
+ tk_focusNext .b
+} -cleanup {
+ cleanup1 .
+} -result {.b.y}
+test focusTcl-5.2 {tkFocusOK procedure, -takefocus 1} -body {
+ setup1 .
+ pack forget .b
+ update
+ .b configure -takefocus ""
+ .b.y configure -takefocus ""
+ .b.z configure -takefocus ""
+ list [tk_focusNext .a] [tk_focusNext .b.x]
+} -cleanup {
+ cleanup1 .
+} -result {.c .c}
+test focusTcl-5.3 {tkFocusOK procedure, -takefocus procedure} -body {
+ proc t w {
+ if {$w == ".b.x"} {
+ return 1
+ } elseif {$w == ".b.y"} {
+ return ""
+ }
+ return 0
+ }
+
+ setup1 .
+ pack forget .b.y
+ update
+ .b configure -takefocus ""
+ foreach w {.b.x .b.y .b.z .c} {
+ $w configure -takefocus t
+ }
+ list [tk_focusNext .a] [tk_focusNext .b.x]
+} -cleanup {
+ cleanup1 .
+} -result {.b.x .d}
+test focusTcl-5.4 {tkFocusOK procedure, -takefocus ""} -body {
+ setup1 .
+ .b.x configure -takefocus ""
+ update
+ tk_focusNext .b
+} -cleanup {
+ cleanup1 .
+} -result {.b.x}
+test focusTcl-5.5 {tkFocusOK procedure, -takefocus "", not mapped} -body {
+ setup1 .
+ .b.x configure -takefocus ""
+ pack forget .b.x
+ update
+ tk_focusNext .b
+} -cleanup {
+ cleanup1 .
+} -result {.b.y}
+test focusTcl-5.6 {tkFocusOK procedure, -takefocus "", not mapped} -body {
+ setup1 .
+ foreach w {.b.x .b.y .b.z} {
+ $w configure -takefocus ""
+ }
+ pack forget .b
+ update
+ tk_focusNext .b
+} -cleanup {
+ cleanup1 .
+} -result {.c}
+test focusTcl-5.7 {tkFocusOK procedure, -takefocus "", not mapped} -body {
+ setup1 .
+ .b.y configure -takefocus 1
+ pack forget .b.y
+ update
+ tk_focusNext .b.x
+} -cleanup {
+ cleanup1 .
+} -result {.b.z}
+test focusTcl-5.8 {tkFocusOK procedure, -takefocus "", not mapped} -body {
+ proc always args {return 1}
+ setup1 .
+ .b.y configure -takefocus always
+ pack forget .b.y
+ update
+ tk_focusNext .b.x
+} -cleanup {
+ cleanup1 .
+} -result {.b.y}
+test focusTcl-5.9 {tkFocusOK procedure, -takefocus "", window disabled} -body {
+ setup1 .
+ foreach w {.b.x .b.y .b.z} {
+ $w configure -takefocus ""
+ }
+ update
+ .b.x configure -state disabled
+ tk_focusNext .b
+} -cleanup {
+ cleanup1 .
+} -result {.b.y}
+test focusTcl-5.10 {tkFocusOK procedure, -takefocus "", check for bindings} -body {
+ setup1 .
+ foreach w {.a .b .c .d} {
+ $w configure -takefocus ""
+ }
+ update
+ bind .a <Key> {foo}
+ list [tk_focusNext .] [tk_focusNext .a]
+} -cleanup {
+ cleanup1 .
+} -result {.a .b.x}
+test focusTcl-5.11 {tkFocusOK procedure, -takefocus "", check for bindings} -body {
+ setup1 .
+ foreach w {.a .b .c .d} {
+ $w configure -takefocus ""
+ }
+ update
+ bind Frame <Key> {foo}
+ list [tk_focusNext .] [tk_focusNext .a]
+} -cleanup {
+ cleanup1 .
+ bind Frame <Key> {}
+} -result {.a .b}
+
+
+. configure -takefocus 0 -highlightthickness 0
+option clear
+
+# cleanup
+cleanupTests
+return
+
+
+
diff --git a/tk8.6/tests/font.test b/tk8.6/tests/font.test
new file mode 100644
index 0000000..8894d85
--- /dev/null
+++ b/tk8.6/tests/font.test
@@ -0,0 +1,2409 @@
+# This file is a Tcl script to test out Tk's "font" command
+# plus the procedures in tkFont.c. It is organized in the
+# standard white-box fashion for Tcl tests.
+#
+# Copyright (c) 1996-1998 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+
+
+set defaultfontlist [font names]
+
+proc getnondefaultfonts {} {
+ global defaultfontlist
+ set nondeffonts [list ]
+ foreach afont [font names] {
+ if {$afont ni $defaultfontlist} {
+ lappend nondeffonts $afont
+ }
+ }
+ set nondeffonts
+}
+
+proc clearnondefaultfonts {} {
+ foreach afont [getnondefaultfonts] {
+ font delete $afont
+ }
+}
+
+deleteWindows
+# Toplevel used (in some tests) of the whole file
+toplevel .t
+wm geom .t +0+0
+update idletasks
+
+switch [tk windowingsystem] {
+ x11 {set fixed "TkFixedFont"}
+ win32 {set fixed "courier 12"}
+ aqua {set fixed "monaco 9"}
+}
+
+
+# Procedure used in tests: 24.15, 26.*, 28.*, 30.*, 31.*, 32.1
+proc csetup {{str ""}} {
+ focus -force .t.c
+ .t.c dchars text 0 end
+ .t.c insert text 0 $str
+ .t.c focus text
+}
+
+
+test font-1.1 {TkFontPkgInit} -setup {
+ catch {interp delete foo}
+} -body {
+ interp create foo
+ foo eval {
+ load {} Tk
+ wm geometry . +0+0
+ update
+ }
+ interp delete foo
+} -result {}
+
+
+test font-2.1 {TkFontPkgFree} -setup {
+ catch {interp delete foo}
+ set x {}
+} -body {
+ interp create foo
+
+ # Makes sure that named font was visible only to child interp.
+ foo eval {
+ load {} Tk
+ wm geometry . +0+0
+ button .b -font {times 16} -text "hi"
+ pack .b
+ font create wiggles -family courier -underline 1
+ update
+ }
+ lappend x [catch {font configure wiggles} msg; set msg]
+
+ # Tests cancelling the idle handler for TheWorldHasChanged,
+ # because app goes away before idle serviced.
+ foo eval {
+ .b config -font wiggles
+ font config wiggles -size 24
+ destroy .
+ }
+ lappend x [foo eval {catch {font families} msg; set msg}]
+} -cleanup {
+ interp delete foo
+} -result {{named font "wiggles" doesn't exist} {can't invoke "font" command: application has been destroyed}}
+
+
+test font-3.1 {font command: general} -body {
+ font
+} -returnCodes error -result {wrong # args: should be "font option ?arg?"}
+test font-3.2 {font command: general} -body {
+ font xyz
+} -returnCodes error -result {bad option "xyz": must be actual, configure, create, delete, families, measure, metrics, or names}
+
+
+test font-4.1 {font command: actual: arguments} -body {
+ # (skip < 0)
+ font actual xyz -displayof
+} -returnCodes error -result {value for "-displayof" missing}
+test font-4.2 {font command: actual: arguments} -body {
+ # (objc < 3)
+ font actual
+} -returnCodes error -result {wrong # args: should be "font actual font ?-displayof window? ?option? ?--? ?char?"}
+test font-4.3 {font command: actual: arguments} -body {
+ # (objc - skip > 4) when skip == 0
+ font actual xyz abc def
+} -returnCodes error -result {wrong # args: should be "font actual font ?-displayof window? ?option? ?--? ?char?"}
+test font-4.4 {font command: actual: displayof specified, so skip to next} -body {
+ catch {font actual xyz -displayof . -size}
+} -result {0}
+test font-4.5 {font command: actual: displayof specified, so skip to next} -body {
+ lindex [font actual xyz -displayof .] 0
+} -result {-family}
+test font-4.6 {font command: actual: arguments} -body {
+ # (objc - skip > 4) when skip == 2
+ font actual xyz -displayof . abc def
+} -returnCodes error -result {wrong # args: should be "font actual font ?-displayof window? ?option? ?--? ?char?"}
+test font-4.7 {font command: actual: arguments} -constraints noExceed -body {
+ # (tkfont == NULL)
+ font actual "\{xyz"
+} -returnCodes error -result "font \"{xyz\" doesn't exist"
+test font-4.8 {font command: actual: all attributes} -body {
+ # not (objc > 3) so objPtr = NULL
+ lindex [font actual {-family times}] 0
+} -result {-family}
+test font-4.9 {font command: actual} -constraints {unix noExceed} -body {
+ # (objc > 3) so objPtr = objv[3 + skip]
+ string tolower [font actual {-family times} -family]
+} -result {times}
+test font-4.10 {font command: actual} -constraints win -body {
+ # (objc > 3) so objPtr = objv[3 + skip]
+ font actual {-family times} -family
+} -result {Times New Roman}
+test font-4.11 {font command: bad option} -body {
+ font actual xyz -style
+} -returnCodes error -result {bad option "-style": must be -family, -size, -weight, -slant, -underline, or -overstrike}
+test font-4.12 {font command: actual} -body {
+ font actual {-family times} -- \ud800
+} -match glob -result {*}
+test font-4.13 {font command: actual} -body {
+ font actual {-family times} -- \udc00
+} -match glob -result {*}
+test font-4.14 {font command: actual} -constraints win -body {
+ font actual {-family times} -family -- \ud800\udc00
+} -result {Times New Roman}
+test font-4.15 {font command: actual} -body {
+ font actual {-family times} -- \udc00\ud800
+} -returnCodes 1 -match glob -result {expected a single character but got "*"}
+
+
+test font-5.1 {font command: configure} -body {
+ # (objc < 3)
+ font configure
+} -returnCodes error -result {wrong # args: should be "font configure fontname ?-option value ...?"}
+test font-5.2 {font command: configure: non-existent font} -body {
+ # (namedHashPtr == NULL)
+ font configure xyz
+} -returnCodes error -result {named font "xyz" doesn't exist}
+test font-5.3 {font command: configure: "deleted" font} -setup {
+ destroy .t.f
+ catch {font delete xyz}
+ pack [label .t.f]
+ update
+} -body {
+ # (nfPtr->deletePending != 0)
+ font create xyz
+ .t.f configure -font xyz
+ font delete xyz
+ font configure xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {named font "xyz" doesn't exist}
+test font-5.4 {font command: configure: get all options} -setup {
+ catch {font delete xyz}
+} -body {
+ # (objc == 3) so objPtr = NULL
+ font create xyz -family xyz
+ lindex [font configure xyz] 1
+} -cleanup {
+ font delete xyz
+} -result xyz
+test font-5.5 {font command: configure: get one option} -setup {
+ clearnondefaultfonts
+} -body {
+ # (objc == 4) so objPtr = objv[3]
+ font create xyz -family xyz
+ font configure xyz -family
+ getnondefaultfonts
+} -cleanup {
+ font delete xyz
+} -result xyz
+test font-5.6 {font command: configure: update existing font} -setup {
+ catch {font delete xyz}
+} -body {
+ # else result = ConfigAttributesObj()
+ font create xyz
+ font configure xyz -family xyz
+ update
+ font configure xyz -family
+} -cleanup {
+ font delete xyz
+} -result xyz
+test font-5.7 {font command: configure: bad option} -setup {
+ catch {font delete xyz}
+} -body {
+ font create xyz
+ font configure xyz -style
+} -cleanup {
+ font delete xyz
+} -returnCodes error -result {bad option "-style": must be -family, -size, -weight, -slant, -underline, or -overstrike}
+
+
+test font-6.1 {font command: create: make up name} -setup {
+ clearnondefaultfonts
+} -body {
+ # (objc < 3) so name = NULL
+ font create
+ getnondefaultfonts
+} -cleanup {
+ font delete font1
+} -result {font1}
+test font-6.2 {font command: create: name specified} -setup {
+ clearnondefaultfonts
+} -body {
+ # not (objc < 3)
+ font create xyz
+ getnondefaultfonts
+} -cleanup {
+ font delete xyz
+} -result {xyz}
+test font-6.3 {font command: create: name not really specified} -setup {
+ clearnondefaultfonts
+} -body {
+ # (name[0] == '-') so name = NULL
+ font create -family xyz
+ getnondefaultfonts
+} -cleanup {
+ font delete font1
+} -result {font1}
+test font-6.4 {font command: create: generate name} -setup {
+} -body {
+ # (name == NULL)
+ font create -family one
+ font create -family two
+ font create -family three
+ font delete font2
+ font create -family four
+ font configure font2 -family
+} -cleanup {
+ font delete font1 font2 font3
+} -result {four}
+test font-6.5 {font command: create: bad option creating new font} -setup {
+ catch {font delete xyz}
+} -body {
+ # name was specified so skip = 3
+ font create xyz -xyz times
+} -returnCodes error -result {bad option "-xyz": must be -family, -size, -weight, -slant, -underline, or -overstrike}
+test font-6.6 {font command: create: bad option creating new font} -setup {
+ clearnondefaultfonts
+} -body {
+ # name was not specified so skip = 2
+ font create -xyz times
+} -returnCodes error -result {bad option "-xyz": must be -family, -size, -weight, -slant, -underline, or -overstrike}
+test font-6.7 {font command: create: already exists} -setup {
+ catch {font delete xyz}
+} -body {
+ # (CreateNamedFont() != TCL_OK)
+ font create xyz
+ font create xyz
+} -cleanup {
+ font delete xyz
+} -returnCodes error -result {named font "xyz" already exists}
+
+test font-7.1 {font command: delete: arguments} -body {
+ # (objc < 3)
+ font delete
+} -returnCodes error -result {wrong # args: should be "font delete fontname ?fontname ...?"}
+test font-7.2 {font command: delete: loop test} -setup {
+ clearnondefaultfonts
+ set x {}
+} -body {
+ # for (i = 2; i < objc; i++)
+ font create a -underline 1
+ font create b -underline 1
+ font create c -underline 1
+ font create d -underline 1
+ font create e -underline 1
+ lappend x [lsort [getnondefaultfonts]]
+ font delete a e c b
+ lappend x [lsort [getnondefaultfonts]]
+} -cleanup {
+ getnondefaultfonts
+} -result {{a b c d e} d}
+test font-7.3 {font command: delete: loop test} -setup {
+ clearnondefaultfonts
+ set x {}
+} -body {
+ # (namedHashPtr == NULL) in middle of loop
+ font create a -underline 1
+ font create b -underline 1
+ font create c -underline 1
+ font create d -underline 1
+ font create e -underline 1
+ lappend x [lsort [getnondefaultfonts]]
+ catch {font delete a d q c e b}
+ lappend x [lsort [getnondefaultfonts]]
+} -cleanup {
+ clearnondefaultfonts
+} -result {{a b c d e} {b c e}}
+test font-7.4 {font command: delete: non-existent} -setup {
+ catch {font delete xyz}
+} -body {
+ # (namedHashPtr == NULL)
+ font delete xyz
+} -returnCodes error -result {named font "xyz" doesn't exist}
+test font-7.5 {font command: delete: mark for later deletion} -setup {
+ destroy .t.f
+ catch {font delete xyz}
+ pack [label .t.f]
+ update
+} -body {
+ # (nfPtr->refCount != 0)
+ font create xyz
+ .t.f configure -font xyz
+ font delete xyz
+ font actual xyz
+ font configure xyz
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {named font "xyz" doesn't exist}
+test font-7.6 {font command: delete: mark for later deletion} -setup {
+ destroy .t.f
+ catch {font delete xyz}
+ pack [label .t.f]
+ update
+} -body {
+ # (nfPtr->refCount != 0)
+ font create xyz
+ .t.f configure -font xyz
+ font delete xyz
+ font actual xyz
+ catch {font configure xyz}
+ .t.f cget -font
+} -cleanup {
+ destroy .t.f
+} -result xyz
+test font-7.7 {font command: delete: actually delete} -setup {
+ catch {font delete xyz}
+} -body {
+ # not (nfPtr->refCount != 0)
+ font create xyz -underline 1
+ font delete xyz
+ font config xyz
+} -returnCodes error -match glob -result {*}
+
+
+test font-8.1 {font command: families: arguments} -body {
+ # (skip < 0)
+ font families -displayof
+} -returnCodes error -result {value for "-displayof" missing}
+test font-8.2 {font command: families: arguments} -body {
+ # (objc - skip != 2) when skip == 0
+ font families xyz
+} -returnCodes error -result {wrong # args: should be "font families ?-displayof window?"}
+test font-8.3 {font command: families: arguments} -body {
+ # (objc - skip != 2) when skip == 2
+ font families -displayof . xyz
+} -returnCodes error -result {wrong # args: should be "font families ?-displayof window?"}
+test font-8.4 {font command: families} -body {
+ # TkpGetFontFamilies()
+ regexp -nocase times [font families]
+} -result 1
+
+
+test font-9.1 {font command: measure: arguments} -body {
+ # (skip < 0)
+ expr {[font measure xyz -displayof] > 0}
+} -returnCodes ok -result 1
+test font-9.2 {font command: measure: arguments} -body {
+ # (objc - skip != 4)
+ font measure
+} -returnCodes error -result {wrong # args: should be "font measure font ?-displayof window? text"}
+test font-9.3 {font command: measure: arguments} -body {
+ # (objc - skip != 4)
+ font measure xyz abc def
+} -returnCodes error -result {wrong # args: should be "font measure font ?-displayof window? text"}
+test font-9.4 {font command: measure: arguments} -constraints noExceed -body {
+ # (tkfont == NULL)
+ font measure "\{xyz" abc
+} -returnCodes error -result "font \"{xyz\" doesn't exist"
+test font-9.5 {font command: measure} -body {
+ # Tk_TextWidth()
+ expr {[font measure $fixed "abcdefg"] == [font measure $fixed "a"]*7 }
+} -result 1
+test font-9.6 {font command: measure -d} -body {
+ expr {[font measure $fixed -d] > 0}
+} -returnCodes ok -result 1
+test font-9.7 {font command: measure -d with -displayof} -body {
+ expr {[font measure $fixed -displayof . -d] > 0}
+} -returnCodes ok -result 1
+test font-9.8 {font command: measure: arguments} -body {
+ font measure $fixed -displayof .
+} -returnCodes error -result {wrong # args: should be "font measure font ?-displayof window? text"}
+
+
+test font-10.1 {font command: metrics: arguments} -body {
+ font metrics xyz -displayof
+} -returnCodes error -result {value for "-displayof" missing}
+test font-10.2 {font command: metrics: arguments} -body {
+ # (skip < 0)
+ font metrics xyz -displayof
+} -returnCodes error -result {value for "-displayof" missing}
+test font-10.3 {font command: metrics: arguments} -body {
+ # (objc < 3)
+ font metrics
+} -returnCodes error -result {wrong # args: should be "font metrics font ?-displayof window? ?option?"}
+test font-10.4 {font command: metrics: arguments} -body {
+ # (objc - skip) > 4) when skip == 0
+ font metrics xyz abc def
+} -returnCodes error -result {wrong # args: should be "font metrics font ?-displayof window? ?option?"}
+test font-10.5 {font command: metrics: arguments} -body {
+ # (objc - skip) > 4) when skip == 2
+ font metrics xyz -displayof . abc
+} -returnCodes error -result {bad metric "abc": must be -ascent, -descent, -linespace, or -fixed}
+test font-10.6 {font command: metrics: bad font} -constraints noExceed -body {
+ # (tkfont == NULL)
+ font metrics "\{xyz"
+} -returnCodes error -result "font \"{xyz\" doesn't exist"
+test font-10.7 {font command: metrics: get all metrics} -setup {
+ catch {unset a}
+} -body {
+ # (objc == 3)
+ array set a [font metrics {-family xyz}]
+ lsort [array names a]
+} -cleanup {
+ unset a
+} -result {-ascent -descent -fixed -linespace}
+test font-10.8 {font command: metrics: bad metric} -body {
+ # (Tcl_GetIndexFromObj() != TCL_OK)
+ font metrics $fixed -xyz
+} -returnCodes error -result {bad metric "-xyz": must be -ascent, -descent, -linespace, or -fixed}
+test font-10.9 {font command: metrics: get individual metrics} -body {
+ font metrics $fixed -ascent
+ font metrics $fixed -descent
+ font metrics $fixed -linespace
+ font metrics $fixed -fixed
+} -result 1
+
+
+test font-11.1 {font command: names: arguments} -body {
+ # (objc != 2)
+ font names xyz
+} -returnCodes error -result {wrong # args: should be "font names"}
+test font-11.2 {font command: names: loop test: no passes} -setup {
+ clearnondefaultfonts
+} -body {
+ getnondefaultfonts
+} -result {}
+test font-11.3 {font command: names: loop test: one pass} -setup {
+ clearnondefaultfonts
+} -body {
+ font create
+ getnondefaultfonts
+} -result {font1}
+test font-11.4 {font command: names: loop test: multiple passes} -setup {
+ clearnondefaultfonts
+} -body {
+ font create xyz
+ font create abc
+ font create def
+ lsort [getnondefaultfonts]
+} -cleanup {
+ clearnondefaultfonts
+} -result {abc def xyz}
+test font-11.5 {font command: names: skip deletePending fonts} -setup {
+ destroy .t.f
+ clearnondefaultfonts
+ pack [label .t.f]
+ update
+ set x {}
+} -body {
+ # (nfPtr->deletePending == 0)
+ font create xyz
+ font create abc
+ lappend x [lsort [getnondefaultfonts]]
+ .t.f config -font xyz
+ font delete xyz
+ lappend x [getnondefaultfonts]
+} -cleanup {
+ clearnondefaultfonts
+} -result {{abc xyz} abc}
+
+
+test font-12.1 {UpdateDependantFonts procedure: no users} -setup {
+ catch {font delete xyz}
+} -body {
+ # (nfPtr->refCount == 0)
+ font create xyz
+ font configure xyz -family times
+} -cleanup {
+ font delete xyz
+} -result {}
+test font-12.2 {UpdateDependantFonts procedure: pings the widgets} -setup {
+ destroy .t.f
+ catch {font delete xyz}
+ pack [label .t.f]
+ update
+} -body {
+ font create xyz -family times -size 20
+ .t.f config -font xyz -text "abcd" -padx 0 -bd 0 -highlightthickness 0
+ set a1 [font measure xyz "abcd"]
+ update
+ set b1 [winfo reqwidth .t.f]
+ font configure xyz -family helvetica -size 20
+ set a2 [font measure xyz "abcd"]
+ update
+ set b2 [winfo reqwidth .t.f]
+ expr {$a1==$b1 && $a2==$b2}
+} -cleanup {
+ destroy .t.f
+ font delete xyz
+} -result {1}
+
+
+test font-13.1 {CreateNamedFont: new named font} -setup {
+ catch {font delete xyz}
+ set x {}
+} -body {
+ # not (new == 0)
+ lappend x [getnondefaultfonts]
+ font create xyz
+ lappend x [getnondefaultfonts]
+} -cleanup {
+ font delete xyz
+} -result {{} xyz}
+test font-13.2 {CreateNamedFont: named font already exists} -setup {
+ catch {font delete xyz}
+} -body {
+ # (new == 0)
+ font create xyz
+ font create xyz
+} -cleanup {
+ font delete xyz
+} -returnCodes error -result {named font "xyz" already exists}
+test font-13.3 {CreateNamedFont: named font already exists} -setup {
+ catch {font delete xyz}
+} -body {
+ # (nfPtr->deletePending == 0)
+ font create xyz
+ font create xyz
+} -cleanup {
+ font delete xyz
+} -returnCodes error -result {named font "xyz" already exists}
+test font-13.4 {CreateNamedFont: recreate "deleted" font} -setup {
+ destroy .t.f
+ catch {font delete xyz}
+ pack [label .t.f]
+ update
+} -body {
+ # not (nfPtr->deletePending == 0)
+ font create xyz -family times
+ .t.f configure -font xyz
+ font delete xyz
+ font create xyz -family courier
+ font configure xyz -family
+} -cleanup {
+ font delete xyz
+ destroy .t.f
+} -result {courier}
+
+
+test font-14.1 {Tk_GetFont procedure} -body {
+} -result {}
+
+
+test font-15.1 {Tk_AllocFontFromObj - converting internal reps} -constraints {
+ testfont
+} -setup {
+ destroy .b1 .b2
+} -body {
+ set x {Times 16}
+ lindex $x 0
+ button .b1 -font $x
+ lindex $x 0
+ testfont counts {Times 16}
+} -cleanup {
+ destroy .b1 .b2
+} -result {{1 0}}
+test font-15.2 {Tk_AllocFontFromObj - discard stale font} -constraints {
+ testfont
+} -setup {
+ destroy .b1 .b2
+ set result {}
+} -body {
+ set x {Times 16}
+ button .b1 -font $x
+ destroy .b1
+ lappend result [testfont counts {Times 16}]
+ button .b2 -font $x
+ lappend result [testfont counts {Times 16}]
+} -cleanup {
+ destroy .b2
+} -result {{} {{1 1}}}
+test font-15.3 {Tk_AllocFontFromObj - reuse existing font} -constraints {
+ testfont
+} -setup {
+ destroy .b1 .b2
+ set result {}
+} -body {
+ set x {Times 16}
+ button .b1 -font $x
+ lappend result [testfont counts {Times 16}]
+ button .b2 -font $x
+ pack .b1 .b2 -side top
+ lappend result [testfont counts {Times 16}]
+} -cleanup {
+ destroy .b1 .b2
+} -result {{{1 1}} {{2 1}}}
+test font-15.4 {Tk_AllocFontFromObj procedure: bump ref count} -setup {
+ destroy .t.f
+ pack [label .t.f]
+ update
+} -body {
+ # (new == 0)
+ .t.f config -font {-family fixed}
+ lindex [font actual {-family fixed}] 0
+} -cleanup {
+ destroy .t.f
+} -result {-family}
+test font-15.5 {Tk_AllocFontFromObj procedure: get named font} -setup {
+ destroy .t.f
+ catch {font delete xyz}
+ pack [label .t.f]
+ update
+} -body {
+ # (namedHashPtr != NULL)
+ font create xyz
+ .t.f config -font xyz
+} -cleanup {
+ destroy .t.f
+ font delete xyz
+} -result {}
+test font-15.6 {Tk_AllocFontFromObj procedure: not a named font} -setup {
+ destroy .t.f
+ pack [label .t.f]
+ update
+} -body {
+ # not (namedHashPtr != NULL)
+ .t.f config -font {times 20}
+} -cleanup {
+ destroy .t.f
+} -result {-family} -result {}
+test font-15.7 {Tk_AllocFontFromObj procedure: get native font} -constraints {
+ unix
+} -setup {
+ destroy .t.f
+ pack [label .t.f]
+ update
+} -body {
+ # not (fontPtr == NULL)
+ .t.f config -font fixed
+} -result {}
+test font-15.8 {Tk_AllocFontFromObj procedure: get native font} -constraints {
+ win
+} -setup {
+ destroy .t.f
+ clearnondefaultfonts
+ pack [label .t.f]
+ update
+} -body {
+ # not (fontPtr == NULL)
+ .t.f config -font oemfixed
+} -cleanup {
+ destroy .t.f
+} -result {}
+test font-15.9 {Tk_AllocFontFromObj procedure: get attribute font} -setup {
+ destroy .t.f
+ pack [label .t.f]
+ update
+} -body {
+ # (fontPtr == NULL)
+ .t.f config -font {xxx yyy zzz}
+} -cleanup {
+ destroy .t.f
+} -returnCodes error -result {expected integer but got "yyy"}
+test font-15.10 {Tk_AllocFontFromObj procedure: no match} -constraints noExceed -body {
+ # (ParseFontNameObj() != TCL_OK)
+ font actual "\{xyz"
+} -returnCodes error -result "font \"{xyz\" doesn't exist"
+test font-15.11 {Tk_AllocFontFromObj procedure: get attribute font} -body {
+ # not (ParseFontNameObj() != TCL_OK)
+ lindex [font actual {plan 9}] 0
+} -result {-family}
+test font-15.12 {Tk_AllocFontFromObj procedure: setup tab width} -setup {
+ destroy .l
+} -body {
+ # Tk_MeasureChars(fontPtr, "0", ...)
+ label .l -bd 0 -padx 0 -highlightthickness 0 -font $fixed -text "a\tb"
+ update
+ set res1 [winfo reqwidth .l]
+ set res2 [expr [font measure $fixed "0"]*9]
+ expr {$res1 eq $res2}
+} -cleanup {
+ destroy .l
+} -result 1
+test font-15.13 {Tk_AllocFontFromObj procedure: underline position} -setup {
+ destroy .t.f
+ pack [label .t.f]
+ update
+} -body {
+ # (fontPtr->underlineHeight == 0) because size was < 10
+ .t.f config -text "underline" -font "times -8 underline"
+ update
+} -cleanup {
+ destroy .t.f
+} -result {}
+
+
+test font-16.1 {Tk_NameOfFont procedure} -setup {
+ destroy .t.f
+ pack [label .t.f]
+ update
+} -body {
+ .t.f config -font -family\ fixed
+ .t.f cget -font
+} -cleanup {
+ destroy .t.f
+} -result {-family fixed}
+
+
+test font-17.1 {Tk_FreeFontFromObj - reference counts} -constraints {
+ testfont
+} -setup {
+ destroy .b1 .b2 .b3
+ set result {}
+} -body {
+ set x {Courier 12}
+ button .b1 -font $x
+ button .b3 -font $x
+ button .b2 -font $x
+ lappend result [testfont counts {Courier 12}]
+ destroy .b1
+ lappend result [testfont counts {Courier 12}]
+ destroy .b2
+ lappend result [testfont counts {Courier 12}]
+ destroy .b3
+ lappend result [testfont counts {Courier 12}]
+} -result {{{3 1}} {{2 1}} {{1 1}} {}}
+test font-17.2 {Tk_FreeFont procedure: one ref} -setup {
+ destroy .t.f
+ pack [label .t.f]
+ update
+} -body {
+ # (fontPtr->refCount == 0)
+ .t.f config -font {-family fixed}
+ destroy .t.f
+} -result {}
+test font-17.3 {Tk_FreeFont procedure: multiple ref} -setup {
+ destroy .t.f .t.b
+ pack [label .t.f]
+ update
+} -body {
+ # not (fontPtr->refCount == 0)
+ .t.f config -font {-family fixed}
+ button .t.b -font {-family fixed}
+ destroy .t.f
+ .t.b cget -font
+} -cleanup {
+ destroy .t.b
+} -result {-family fixed}
+test font-17.4 {Tk_FreeFont procedure: named font} -setup {
+ destroy .t.f
+ clearnondefaultfonts
+ pack [label .t.f]
+ update
+} -body {
+ # (fontPtr->namedHashPtr != NULL)
+ font create xyz
+ .t.f config -font xyz
+ destroy .t.f
+ getnondefaultfonts
+} -result {xyz}
+test font-17.5 {Tk_FreeFont procedure: named font} -setup {
+ destroy .t.f
+ catch {font delete xyz}
+ pack [label .t.f]
+ update
+} -body {
+ # not (fontPtr->refCount == 0)
+ font create xyz -underline 1
+ .t.f config -font xyz
+ font delete xyz
+ set x [font actual xyz -underline]
+ destroy .t.f
+ list [font actual xyz -underline] $x
+} -result {0 1}
+test font-17.6 {Tk_FreeFont procedure: named font not deleted yet} -setup {
+ destroy .t.f .t.b
+ catch {font delete xyz}
+ pack [label .t.f]
+ update
+} -body {
+ font create xyz
+ .t.f config -font xyz
+ button .t.b -font xyz
+ font delete xyz
+ set x [font actual xyz]
+ destroy .t.b
+ list [lindex [font actual xyz] 0] [lindex $x 0]
+} -cleanup {
+ destroy .t.f
+} -result {-family -family}
+
+
+test font-18.1 {FreeFontObjProc} -constraints testfont -setup {
+ destroy .b1
+ set result {}
+} -body {
+ set x [join {Courier 12} { }]
+ button .b1 -font $x
+ set y [join {Courier 12} { }]
+ .b1 configure -font $y
+ set z [join {Courier 12} { }]
+ .b1 configure -font $z
+ lappend result [testfont counts {Courier 12}]
+ set x red
+ lappend result [testfont counts {Courier 12}]
+ set z 32
+ lappend result [testfont counts {Courier 12}]
+ destroy .b1
+ lappend result [testfont counts {Courier 12}]
+ set y bogus
+ return $result
+} -result {{{1 3}} {{1 2}} {{1 1}} {}}
+
+
+test font-19.1 {Tk_FontId} -setup {
+ destroy .t.f
+ pack [label .t.f]
+ update
+} -body {
+ .t.f config -font "times 20"
+ update
+} -cleanup {
+ destroy .t.f
+} -result {}
+
+
+test font-20.1 {Tk_GetFontMetrics procedure} -setup {
+ destroy .t.w1 .t.w2
+} -body {
+ button .t.w1 -text abc
+ entry .t.w2 -text abcd
+ update
+ destroy .t.w1 .t.w2
+} -result {}
+
+
+# Procedure used in 21.* tests
+proc psfontname {name} {
+ destroy .t.c
+ canvas .t.c -closeenough 0
+ .t.c create text 0 0 -tags text -anchor nw -just left -font "Courier -12"
+ pack .t.c
+ update
+ set a [.t.c itemcget text -font]
+ .t.c itemconfig text -text "We need text" -font $name
+ set post [.t.c postscript]
+ .t.c itemconfig text -font $a
+ set end [string first "findfont" $post]
+ incr end -2
+ set post [string range $post [expr $end-70] $end]
+ set start [string first "gsave" $post]
+ destroy .t.c
+ return [string range $post [expr $start+7] end]
+}
+test font-21.1 {Tk_PostscriptFontName procedure: native} -constraints {
+ unix
+} -body {
+ set x [font actual {{itc avant garde} 10} -family]
+ if {[string match *avant*garde $x]} {
+ psfontname "{itc avant garde} 10"
+ } else {
+ set x {AvantGarde-Book}
+ }
+} -result {AvantGarde-Book}
+test font-21.2 {Tk_PostscriptFontName procedure: native} -constraints {
+ win
+} -body {
+ psfontname "arial 10"
+} -result {Helvetica}
+test font-21.3 {Tk_PostscriptFontName procedure: native} -constraints {
+ win
+} -body {
+ psfontname "{times new roman} 10"
+} -result {Times-Roman}
+test font-21.4 {Tk_PostscriptFontName procedure: native} -constraints {
+ win
+} -body {
+ psfontname "{courier new} 10"
+} -result {Courier}
+test font-21.5 {Tk_PostscriptFontName procedure: spaces} -constraints {
+ unix
+} -body {
+ set x [font actual {{lucida bright} 10} -family]
+ if {[string match lucida*bright $x]} {
+ psfontname "{lucida bright} 10"
+ } else {
+ set x {LucidaBright}
+ }
+} -result {LucidaBright}
+test font-21.6 {Tk_PostscriptFontName procedure: spaces} -constraints {
+ x11
+} -body {
+ psfontname "{new century schoolbook} 10"
+} -result {NewCenturySchlbk-Roman}
+
+test font-21.7 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {avantgarde 12 roman normal}
+ if {[font actual {avantgarde 12 roman normal} -family] == "avantgarde"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x AvantGarde-Book
+ }
+} -result {AvantGarde-Book}
+test font-21.8 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {avantgarde 12 roman bold}
+ if {[font actual {avantgarde 12 roman normal} -family] == "avantgarde"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x AvantGarde-Demi
+ }
+} -result {AvantGarde-Demi}
+test font-21.9 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {avantgarde 12 italic normal}
+ if {[font actual {avantgarde 12 roman normal} -family] == "avantgarde"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x AvantGarde-BookOblique
+ }
+} -result {AvantGarde-BookOblique}
+test font-21.10 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {avantgarde 12 italic bold}
+ if {[font actual {avantgarde 12 roman normal} -family] == "avantgarde"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x AvantGarde-DemiOblique
+ }
+} -result {AvantGarde-DemiOblique}
+
+test font-21.11 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {bookman 12 roman normal}
+ if {[font actual {avantgarde 12 roman normal} -family] == "bookman"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x Bookman-Light
+ }
+} -result {Bookman-Light}
+test font-21.12 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {bookman 12 roman bold}
+ if {[font actual {avantgarde 12 roman normal} -family] == "bookman"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x Bookman-Demi
+ }
+} -result {Bookman-Demi}
+test font-21.13 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {bookman 12 italic normal}
+ if {[font actual {avantgarde 12 roman normal} -family] == "bookman"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x Bookman-LightItalic
+ }
+} -result {Bookman-LightItalic}
+test font-21.14 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {bookman 12 italic bold}
+ if {[font actual {avantgarde 12 roman normal} -family] == "bookman"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x Bookman-DemiItalic
+ }
+} -result {Bookman-DemiItalic}
+
+test font-21.15 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {courier 12 roman normal}
+ if {[font actual {avantgarde 12 roman normal} -family] == "courier"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x Courier
+ }
+} -result {Courier}
+test font-21.16 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {courier 12 roman bold}
+ if {[font actual {avantgarde 12 roman normal} -family] == "courier"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x Courier-Bold
+ }
+} -result {Courier-Bold}
+test font-21.17 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {courier 12 italic normal}
+ if {[font actual {avantgarde 12 roman normal} -family] == "courier"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x Courier-Oblique
+ }
+} -result {Courier-Oblique}
+test font-21.18 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {courier 12 italic bold}
+ if {[font actual {avantgarde 12 roman normal} -family] == "courier"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x Courier-BoldOblique
+ }
+} -result {Courier-BoldOblique}
+
+test font-21.19 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {helvetica 12 roman normal}
+ if {[font actual {avantgarde 12 roman normal} -family] == "helvetica"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x Helvetica
+ }
+} -result {Helvetica}
+test font-21.20 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {helvetica 12 roman bold}
+ if {[font actual {avantgarde 12 roman normal} -family] == "helvetica"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x Helvetica-Bold
+ }
+} -result {Helvetica-Bold}
+test font-21.21 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {helvetica 12 italic normal}
+ if {[font actual {avantgarde 12 roman normal} -family] == "helvetica"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x Helvetica-Oblique
+ }
+} -result {Helvetica-Oblique}
+test font-21.22 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {helvetica 12 italic bold}
+ if {[font actual {avantgarde 12 roman normal} -family] == "helvetica"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x Helvetica-BoldOblique
+ }
+} -result {Helvetica-BoldOblique}
+
+test font-21.23 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {{new century schoolbook} 12 roman normal}
+ if {[font actual {avantgarde 12 roman normal} -family] == "new century schoolbook"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x NewCenturySchlbk-Roman
+ }
+} -result {NewCenturySchlbk-Roman}
+test font-21.24 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {{new century schoolbook} 12 roman bold}
+ if {[font actual {avantgarde 12 roman normal} -family] == "new century schoolbook"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x NewCenturySchlbk-Bold
+ }
+} -result {NewCenturySchlbk-Bold}
+test font-21.25 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {{new century schoolbook} 12 italic normal}
+ if {[font actual {avantgarde 12 roman normal} -family] == "new century schoolbook"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x NewCenturySchlbk-Italic
+ }
+} -result {NewCenturySchlbk-Italic}
+test font-21.26 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {{new century schoolbook} 12 italic bold}
+ if {[font actual {avantgarde 12 roman normal} -family] == "new century schoolbook"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x NewCenturySchlbk-BoldItalic
+ }
+} -result {NewCenturySchlbk-BoldItalic}
+
+test font-21.27 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {palatino 12 roman normal}
+ if {[font actual {avantgarde 12 roman normal} -family] == "palatino"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x Palatino-Roman
+ }
+} -result {Palatino-Roman}
+test font-21.28 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {palatino 12 roman bold}
+ if {[font actual {avantgarde 12 roman normal} -family] == "palatino"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x Palatino-Bold
+ }
+} -result {Palatino-Bold}
+test font-21.29 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {palatino 12 italic normal}
+ if {[font actual {avantgarde 12 roman normal} -family] == "palatino"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x Palatino-Italic
+ }
+} -result {Palatino-Italic}
+test font-21.30 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {palatino 12 italic bold}
+ if {[font actual {avantgarde 12 roman normal} -family] == "palatino"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x Palatino-BoldItalic
+ }
+} -result {Palatino-BoldItalic}
+
+test font-21.31 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {symbol 12 roman normal}
+ if {[font actual {avantgarde 12 roman normal} -family] == "symbol"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x Symbol
+ }
+} -result {Symbol}
+test font-21.32 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {symbol 12 roman bold}
+ if {[font actual {avantgarde 12 roman normal} -family] == "symbol"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x Symbol
+ }
+} -result {Symbol}
+test font-21.33 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {symbol 12 italic normal}
+ if {[font actual {avantgarde 12 roman normal} -family] == "symbol"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x Symbol
+ }
+} -result {Symbol}
+test font-21.34 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {symbol 12 italic bold}
+ if {[font actual {avantgarde 12 roman normal} -family] == "symbol"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x Symbol
+ }
+} -result {Symbol}
+
+test font-21.35 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {times 12 roman normal}
+ if {[font actual {avantgarde 12 roman normal} -family] == "times"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x Times-Roman
+ }
+} -result {Times-Roman}
+test font-21.36 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {times 12 roman bold}
+ if {[font actual {avantgarde 12 roman normal} -family] == "times"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x Times-Bold
+ }
+} -result {Times-Bold}
+test font-21.37 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {times 12 italic normal}
+ if {[font actual {avantgarde 12 roman normal} -family] == "times"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x Times-Italic
+ }
+} -result {Times-Italic}
+test font-21.38 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {times 12 italic bold}
+ if {[font actual {avantgarde 12 roman normal} -family] == "times"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x Times-BoldItalic
+ }
+} -result {Times-BoldItalic}
+
+test font-21.39 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {zapfchancery 12 roman normal}
+ if {[font actual {avantgarde 12 roman normal} -family] == "zapfchancery"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x ZapfChancery-MediumItalic
+ }
+} -result {ZapfChancery-MediumItalic}
+test font-21.40 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {zapfchancery 12 roman bold}
+ if {[font actual {avantgarde 12 roman normal} -family] == "zapfchancery"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x ZapfChancery-MediumItalic
+ }
+} -result {ZapfChancery-MediumItalic}
+test font-21.41 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {zapfchancery 12 italic normal}
+ if {[font actual {avantgarde 12 roman normal} -family] == "zapfchancery"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x ZapfChancery-MediumItalic
+ }
+} -result {ZapfChancery-MediumItalic}
+test font-21.42 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {zapfchancery 12 italic bold}
+ if {[font actual {avantgarde 12 roman normal} -family] == "zapfchancery"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x ZapfChancery-MediumItalic
+ }
+} -result {ZapfChancery-MediumItalic}
+
+test font-21.43 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {zapfdingbats 12 roman normal}
+ if {[font actual {avantgarde 12 roman normal} -family] == "zapfdingbats"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x ZapfDingbats
+ }
+} -result {ZapfDingbats}
+test font-21.44 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {zapfdingbats 12 roman bold}
+ if {[font actual {avantgarde 12 roman normal} -family] == "zapfdingbats"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x ZapfDingbats
+ }
+} -result {ZapfDingbats}
+test font-21.45 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {zapfdingbats 12 italic normal}
+ if {[font actual {avantgarde 12 roman normal} -family] == "zapfdingbats"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x ZapfDingbats
+ }
+} -result {ZapfDingbats}
+test font-21.46 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ unix
+} -body {
+ set name {zapfdingbats 12 italic bold}
+ if {[font actual {avantgarde 12 roman normal} -family] == "zapfdingbats"} {
+ set x [psfontname avantgarde 12 roman normal]
+ } else {
+ set x ZapfDingbats
+ }
+} -result {ZapfDingbats}
+
+test font-21.47 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ win
+} -body {
+ set x [psfontname {arial 12 roman normal}]
+} -result {Helvetica}
+test font-21.48 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ win
+} -body {
+ set x [psfontname {arial 12 roman bold}]
+} -result {Helvetica-Bold}
+test font-21.49 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ win
+} -body {
+ set x [psfontname {arial 12 italic normal}]
+} -result {Helvetica-Oblique}
+test font-21.50 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ win
+} -body {
+ set x [psfontname {arial 12 italic bold}]
+} -result {Helvetica-BoldOblique}
+
+test font-21.51 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ win
+} -body {
+ set x [psfontname {{courier new} 12 roman normal}]
+} -result {Courier}
+test font-21.52 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ win
+} -body {
+ set x [psfontname {{courier new} 12 roman bold}]
+} -result {Courier-Bold}
+test font-21.53 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ win
+} -body {
+ set x [psfontname {{courier new} 12 italic normal}]
+} -result {Courier-Oblique}
+test font-21.54 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ win
+} -body {
+ set x [psfontname {{courier new} 12 italic bold}]
+} -result {Courier-BoldOblique}
+
+test font-21.55 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ win
+} -body {
+ set x [psfontname {helvetica 12 roman normal}]
+} -result {Helvetica}
+test font-21.56 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ win
+} -body {
+ set x [psfontname {helvetica 12 roman bold}]
+} -result {Helvetica-Bold}
+test font-21.57 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ win
+} -body {
+ set x [psfontname {helvetica 12 italic normal}]
+} -result {Helvetica-Oblique}
+test font-21.58 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ win
+} -body {
+ set x [psfontname {helvetica 12 italic bold}]
+} -result {Helvetica-BoldOblique}
+
+test font-21.59 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ win
+} -body {
+ set x [psfontname {symbol 12 roman normal}]
+} -result {Symbol}
+test font-21.60 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ win
+} -body {
+ set x [psfontname {symbol 12 roman bold}]
+} -result {Symbol-Bold}
+test font-21.61 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ win
+} -body {
+ set x [psfontname {symbol 12 italic normal}]
+} -result {Symbol-Italic}
+test font-21.62 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ win
+} -body {
+ set x [psfontname {symbol 12 italic bold}]
+} -result {Symbol-BoldItalic}
+
+test font-21.63 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ win
+} -body {
+ set x [psfontname {{times new roman} 12 roman normal}]
+} -result {Times-Roman}
+test font-21.64 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ win
+} -body {
+ set x [psfontname {{times new roman} 12 roman bold}]
+} -result {Times-Bold}
+test font-21.65 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ win
+} -body {
+ set x [psfontname {{times new roman} 12 italic normal}]
+} -result {Times-Italic}
+test font-21.66 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
+ win
+} -body {
+ set x [psfontname {{times new roman} 12 italic bold}]
+} -result {Times-BoldItalic}
+
+
+test font-22.1 {Tk_TextWidth procedure} -setup {
+ destroy .t.l
+} -body {
+ label .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \
+ -text "0" -font "Courier -12"
+ pack .t.l
+ set ax [winfo reqwidth .t.l]
+ expr {[font measure [.t.l cget -font] "000"] eq $ax*3}
+} -cleanup {
+ destroy .t.l
+} -result 1
+
+
+test font-23.1 {Tk_UnderlineChars procedure} -setup {
+ destroy .t.t
+} -body {
+ text .t.t
+ .t.t insert 1.0 abc\tdefg
+ .t.t tag config sel -underline 1
+ .t.t tag add sel 1.0 end
+ update
+} -cleanup {
+ destroy .t.t
+} -result {}
+
+
+# Data used in 24.* tests
+destroy .t.l
+label .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \
+ -text "0" -font "Courier -12"
+pack .t.l
+update
+set ax [winfo reqwidth .t.l]
+set ay [winfo reqheight .t.l]
+test font-24.1 {Tk_ComputeTextLayout: empty string} -body {
+ .t.l config -text ""
+} -result {}
+test font-24.2 {Tk_ComputeTextLayout: simple string} -body {
+ .t.l config -text "000"
+ update
+ list [expr {[winfo reqwidth .t.l] eq [expr {$ax * 3}]}] \
+ [expr {[winfo reqheight .t.l] eq $ay}]
+} -result {1 1}
+test font-24.3 {Tk_ComputeTextLayout: find special chars} -body {
+ .t.l config -text "000\n000"
+ update
+ list [expr {[winfo reqwidth .t.l] eq [expr {$ax * 3}]}] \
+ [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]
+} -result {1 1}
+test font-24.4 {Tk_ComputeTextLayout: calls Tk_MeasureChars} -body {
+ .t.l config -text "000\n000"
+ update
+ list [expr {[winfo reqwidth .t.l] eq [expr {$ax * 3}]}] \
+ [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]
+} -result {1 1}
+test font-24.5 {Tk_ComputeTextLayout: break line} -body {
+ .t.l config -text "000\t00000" -wrap [expr 9 * $ax]
+ update
+ list [expr {[winfo reqwidth .t.l] eq [expr {$ax * 8}]}] \
+ [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]
+} -cleanup {
+ .t.l config -wrap 0
+} -result {1 1}
+test font-24.6 {Tk_ComputeTextLayout: normal ended on special char} -body {
+ .t.l config -text "000\n000"
+} -result {}
+test font-24.7 {Tk_ComputeTextLayout: special char was \n} -body {
+ .t.l config -text "000\n0000"
+ update
+ list [expr {[winfo reqwidth .t.l] eq [expr {$ax * 4}]}] \
+ [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]
+} -result {1 1}
+test font-24.8 {Tk_ComputeTextLayout: special char was \t} -body {
+ .t.l config -text "000\t00"
+ update
+ list [expr {[winfo reqwidth .t.l] eq [expr {$ax * 10}]}] \
+ [expr {[winfo reqheight .t.l] eq $ay}]
+} -result {1 1}
+test font-24.9 {Tk_ComputeTextLayout: tab didn't cause break} -body {
+ set x {}
+ .t.l config -text "000\t000"
+ update
+ lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 11}]}]
+ lappend x [expr {[winfo reqheight .t.l] eq $ay}]
+ .t.l config -text "000\t000" -wrap [expr 100 * $ax]
+ update
+ lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 11}]}]
+ lappend x [expr {[winfo reqheight .t.l] eq $ay}]
+ return $x
+} -cleanup {
+ .t.l config -wrap 0
+} -result {1 1 1 1}
+test font-24.10 {Tk_ComputeTextLayout: tab caused break} -body {
+ set x {}
+ .t.l config -text "000\t"
+ update
+ lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 8}]}]
+ lappend x [expr {[winfo reqheight .t.l] eq $ay}]
+ .t.l config -text "000\t00" -wrap [expr $ax * 6]
+ update
+ lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 8}]}]
+ lappend x [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]
+ return $x
+} -cleanup {
+ .t.l config -wrap 0
+} -result {1 1 1 1}
+test font-24.11 {Tk_ComputeTextLayout: absorb spaces at eol} -body {
+ set x {}
+ .t.l config -text "000 000" -wrap [expr {$ax * 5}]
+ update
+ lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 3}]}]
+ lappend x [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]
+ .t.l config -text "000 "
+ update
+ lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 3}]}]
+ lappend x [expr {[winfo reqheight .t.l] eq $ay}]
+ return $x
+} -cleanup {
+ .t.l config -wrap 0
+} -result {1 1 1 1}
+test font-24.12 {Tk_ComputeTextLayout: append non-printing spaces to chunk} -body {
+ set x {}
+ .t.l config -text "000 0000" -wrap [expr {$ax * 5}]
+ update
+ lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 4}]}]
+ lappend x [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]
+ .t.l config -text "000\t00 0000" -wrap [expr {$ax * 12}]
+ update
+ lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 10}]}]
+ lappend x [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]
+ return $x
+} -cleanup {
+ .t.l config -wrap 0
+} -result {1 1 1 1}
+test font-24.13 {Tk_ComputeTextLayout: many lines -> realloc line array} -body {
+ .t.l config -text "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
+ update
+ list [expr {[winfo reqwidth .t.l] eq 1}] \
+ [expr {[winfo reqheight .t.l] eq [expr {$ay * 129}]}]
+} -result {1 1}
+test font-24.14 {Tk_ComputeTextLayout: text ended with \n} -body {
+ set x {}
+ .t.l config -text "0000"
+ update
+ lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 4}]}]
+ lappend x [expr {[winfo reqheight .t.l] eq $ay}]
+ .t.l config -text "0000\n"
+ update
+ lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 4}]}]
+ lappend x [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]
+ return $x
+} -result {1 1 1 1}
+destroy .t.l
+
+test font-24.15 {Tk_ComputeTextLayout: justification} -setup {
+ set x {}
+ destroy .t.c
+ canvas .t.c -closeenough 0
+ .t.c create text 0 0 -tags text -anchor nw -just left -font "Courier -12"
+ pack .t.c
+ update
+} -body {
+ csetup "000\n00000"
+ .t.c itemconfig text -just left
+ lappend x [.t.c index text @[expr $ax*2],0]
+ .t.c itemconfig text -just center
+ lappend x [.t.c index text @[expr $ax*2],0]
+ .t.c itemconfig text -just right
+ lappend x [.t.c index text @[expr $ax*2],0]
+ .t.c itemconfig text -just left
+ return $x
+} -cleanup {
+ destroy .t.c
+} -result {2 1 0}
+
+
+test font-25.1 {Tk_FreeTextLayout procedure} -setup {
+ destroy .t.f
+ pack [label .t.f]
+ update
+} -body {
+ .t.f config -text foo
+ .t.f config -text boo
+} -cleanup {
+ destroy .t.f
+} -result {}
+
+
+# Canvas created for tests: 26.*
+destroy .t.c
+canvas .t.c -closeenough 0
+.t.c create text 0 0 -tags text -anchor nw -just left -font "Courier -12"
+pack .t.c
+update
+test font-26.1 {Tk_DrawTextLayout procedure: auto-detect last char} -setup {
+ destroy .t.f
+ pack [label .t.f]
+ update
+} -body {
+ .t.f config -text foo
+} -cleanup {
+ destroy .t.f
+} -result {}
+test font-26.2 {Tk_DrawTextLayout procedure: multiple chunks} -body {
+ csetup "000\t00\n000"
+} -result {}
+test font-26.3 {Tk_DrawTextLayout: draw subset of chunk: numDisplay <= 0} -body {
+ csetup "000\t00"
+ .t.c select from text 3
+ .t.c select to text 5
+} -result {}
+test font-26.4 {Tk_DrawTextLayout: draw subset of chunk: firstChar <= 0} -body {
+ csetup "000\t00"
+ .t.c select from text 3
+ .t.c select to text 5
+} -result {}
+test font-26.5 {Tk_DrawTextLayout: draw subset of chunk: firstChar > 0} -body {
+ csetup "000\t00"
+ .t.c select from text 2
+ .t.c select to text 2
+} -result {}
+test font-26.6 {Tk_DrawTextLayout: draw subset of chunk: lastChar < numChars} -body {
+ csetup "000\t00"
+ .t.c select from text 4
+ .t.c select to text 4
+} -result {}
+destroy .t.c
+
+# Label used in 27.* tests
+destroy .t.f
+pack [label .t.f]
+update
+test font-27.1 {Tk_UnderlineTextLayout procedure: no underline chosen} -body {
+ .t.f config -text "foo" -under -1
+} -result {}
+test font-27.2 {Tk_UnderlineTextLayout procedure: underline not visible} -body {
+ .t.f config -text "000 00000" -wrap [expr $ax*7] -under 10
+} -result {}
+test font-27.3 {Tk_UnderlineTextLayout procedure: underline is visible} -body {
+ .t.f config -text "000 00000" -wrap [expr $ax*7] -under 5
+ .t.f config -wrap -1 -under -1
+} -result {}
+destroy .t.f
+
+
+
+# Canvas created for tests: 28.*
+destroy .t.c
+canvas .t.c -closeenough 0
+.t.c create text 0 0 -tags text -anchor nw -just left -font "Courier -12"
+pack .t.c
+update
+test font-28.1 {Tk_PointToChar procedure: above all lines} -body {
+ csetup "000"
+ .t.c index text @-1,0
+} -result {0}
+test font-28.2 {Tk_PointToChar procedure: no chars} -body {
+ # After fixing the following bug:
+ #
+ # In canvas text item, it was impossible to click to position the
+ # insertion point just after the last character.
+ #
+ # introduced another bug that Tk_PointToChar() would return a character
+ # index of 1 if TextLayout contained 0 characters.
+
+ csetup ""
+ .t.c index text @100,100
+} -result {0}
+test font-28.3 {Tk_PointToChar procedure: loop test} -body {
+ csetup "000\n000\n000\n000"
+ .t.c index text @10000,0
+} -result {3}
+test font-28.4 {Tk_PointToChar procedure: intersect line} -body {
+ csetup "000\n000\n000"
+ .t.c index text @0,$ay
+} -result {4}
+test font-28.5 {Tk_PointToChar procedure: to the left of all chunks} -body {
+ csetup "000\n000\n000"
+ .t.c index text @-100,$ay
+} -result {4}
+test font-28.6 {Tk_PointToChar procedure: past any possible chunk} -body {
+ csetup "000\n000\n000"
+ .t.c index text @100000,$ay
+} -result {7}
+test font-28.7 {Tk_PointToChar procedure: which chunk on this line} -body {
+ csetup "000\n000\t000\t000\n000"
+ .t.c index text @[expr $ax*2],$ay
+} -result {6}
+test font-28.8 {Tk_PointToChar procedure: which chunk on this line} -body {
+ csetup "000\n000\t000\t000\n000"
+ .t.c index text @[expr $ax*10],$ay
+} -result {10}
+test font-28.9 {Tk_PointToChar procedure: in special chunk} -body {
+ csetup "000\n000\t000\t000\n000"
+ .t.c index text @[expr $ax*6],$ay
+} -result {7}
+test font-28.10 {Tk_PointToChar procedure: past all chars in chunk} -body {
+ csetup "000 0000000"
+ .t.c itemconfig text -width [expr $ax*5]
+ set x [.t.c index text @[expr $ax*5],0]
+ .t.c itemconfig text -width 0
+ return $x
+} -result {3}
+test font-28.11 {Tk_PointToChar procedure: below all chunks} -body {
+ csetup "000 0000000"
+ .t.c index text @0,1000000
+} -result {11}
+destroy .t.c
+
+
+# Label used in 29.* tests
+destroy .t.f
+pack [label .t.f]
+update
+test font-29.1 {Tk_CharBBox procedure: index < 0} -body {
+ .t.f config -text "000" -underline -1
+} -result {}
+test font-29.2 {Tk_CharBBox procedure: loop} -body {
+ .t.f config -text "000\t000\t000\t000" -underline 9
+} -result {}
+test font-29.3 {Tk_CharBBox procedure: special char} -body {
+ .t.f config -text "000\t000\t000" -underline 7
+} -result {}
+test font-29.4 {Tk_CharBBox procedure: normal char} -body {
+ .t.f config -text "000" -underline 1
+} -result {}
+test font-29.5 {Tk_CharBBox procedure: right edge of bbox truncated} -body {
+ .t.f config -text "0 0000" -wrap [expr $ax*4] -under 2
+ .t.f config -wrap 0
+} -result {}
+test font-29.6 {Tk_CharBBox procedure: bbox pegged to right edge} -body {
+ .t.f config -text "0 0000" -wrap [expr $ax*4] -under 3
+ .t.f config -wrap 0
+} -result {}
+destroy .t.f
+
+
+
+# Canvas created for tests: 30.*
+destroy .t.c
+canvas .t.c -closeenough 0
+.t.c create text 0 0 -tags text -anchor nw -just left -font "Courier -12"
+pack .t.c
+update
+test font-30.1 {Tk_DistanceToTextLayout procedure: loop once} -body {
+ csetup "000\n000\n000"
+ .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
+ set x {}
+ event generate .t.c <Leave>
+ event generate .t.c <Enter> -x 0 -y 0
+ return $x
+} -cleanup {
+ bind all <Enter> {}
+} -result {0}
+test font-30.2 {Tk_DistanceToTextLayout procedure: loop multiple} -body {
+ csetup "000\n000\n000"
+ .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
+ set x {}
+ event generate .t.c <Leave>
+ event generate .t.c <Enter> -x $ax -y $ay
+ return $x
+} -cleanup {
+ bind all <Enter> {}
+} -result {5}
+test font-30.3 {Tk_DistanceToTextLayout procedure: loop to end} -body {
+ csetup "000\n0\n000"
+ .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
+ set x {}
+ event generate .t.c <Leave>
+ event generate .t.c <Enter> -x [expr $ax*2] -y $ay
+ return $x
+} -cleanup {
+ bind all <Enter> {}
+} -result {}
+test font-30.4 {Tk_DistanceToTextLayout procedure: hit a special char (tab)} -body {
+ csetup "000\t000\n000"
+ .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
+ set x {}
+ event generate .t.c <Leave>
+ event generate .t.c <Enter> -x [expr $ax*6] -y 0
+ return $x
+} -cleanup {
+ bind all <Enter> {}
+} -result {3}
+test font-30.5 {Tk_DistanceToTextLayout procedure: ignore newline} -body {
+ csetup "000\n0\n000"
+ .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
+ set x {}
+ event generate .t.c <Leave>
+ event generate .t.c <Enter> -x [expr $ax*2] -y $ay
+ return $x
+} -cleanup {
+ bind all <Enter> {}
+} -result {}
+test font-30.6 {Tk_DistanceToTextLayout procedure: ignore spaces at eol} -body {
+ csetup "000\n000 000000000"
+ .t.c itemconfig text -width [expr $ax*10]
+ .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
+ set x {}
+ event generate .t.c <Leave>
+ event generate .t.c <Enter> -x [expr $ax*5] -y $ay
+ .t.c itemconfig text -width 0
+ return $x
+} -cleanup {
+ bind all <Enter> {}
+} -result {}
+.t.c itemconfig text -justify center
+test font-30.7 {Tk_DistanceToTextLayout procedure: on left side} -body {
+ csetup "0\n000"
+ .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
+ set x {}
+ event generate .t.c <Leave>
+ event generate .t.c <Enter> -x 0 -y 0
+ return $x
+} -cleanup {
+ bind all <Enter> {}
+} -result {}
+test font-30.8 {Tk_DistanceToTextLayout procedure: on right side} -body {
+ csetup "0\n000"
+ .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
+ set x {}
+ event generate .t.c <Leave>
+ event generate .t.c <Enter> -x [expr $ax*2] -y 0
+ return $x
+} -cleanup {
+ bind all <Enter> {}
+} -result {}
+test font-30.9 {Tk_DistanceToTextLayout procedure: inside line} -body {
+ csetup "0\n000"
+ .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
+ set x {}
+ event generate .t.c <Leave>
+ event generate .t.c <Enter> -x $ax -y 0
+ return $x
+} -cleanup {
+ bind all <Enter> {}
+} -result {0}
+test font-30.10 {Tk_DistanceToTextLayout procedure: above line} -body {
+ csetup "0\n000"
+ .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
+ set x {}
+ event generate .t.c <Leave>
+ event generate .t.c <Enter> -x 0 -y 0
+ return $x
+} -cleanup {
+ bind all <Enter> {}
+} -result {}
+test font-30.11 {Tk_DistanceToTextLayout procedure: below line} -body {
+ csetup "000\n0"
+ .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
+ set x {}
+ event generate .t.c <Leave>
+ event generate .t.c <Enter> -x 0 -y $ay
+ return $x
+} -cleanup {
+ bind all <Enter> {}
+} -result {}
+test font-30.12 {Tk_DistanceToTextLayout procedure: in line} -body {
+ csetup "0\n000"
+ .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
+ set x {}
+ event generate .t.c <Leave>
+ event generate .t.c <Enter> -x $ax -y $ay
+ return $x
+} -cleanup {
+ bind all <Enter> {}
+} -result {3}
+.t.c itemconfig text -justify left
+test font-30.13 {Tk_DistanceToTextLayout procedure: exact hit} -body {
+ csetup "000"
+ .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
+ set x {}
+ event generate .t.c <Leave>
+ event generate .t.c <Enter> -x $ax -y 0
+ return $x
+} -cleanup {
+ bind all <Enter> {}
+} -result {1}
+destroy .t.c
+
+
+# Canvas created for tests 31.*
+destroy .t.c
+canvas .t.c -closeenough 0
+.t.c create text 0 0 -tags text -anchor nw -just left -font "Courier -12"
+pack .t.c
+update
+test font-31.1 {Tk_IntersectTextLayout procedure: loop once} -body {
+ csetup "000\n000\n000"
+ .t.c find overlapping 0 0 0 0
+} -result [.t.c find withtag text]
+test font-31.2 {Tk_IntersectTextLayout procedure: loop multiple} -body {
+ csetup "000\t000\t000"
+ .t.c find overlapping [expr $ax*10] 0 [expr $ax*10] 0
+} -result [.t.c find withtag text]
+test font-31.3 {Tk_IntersectTextLayout procedure: loop to end} -body {
+ csetup "0\n000"
+ .t.c find overlapping [expr $ax*2] 0 [expr $ax*2] 0
+} -result {}
+test font-31.4 {Tk_IntersectTextLayout procedure: hit a special char (tab)} -body {
+ csetup "000\t000"
+ .t.c find overlapping [expr $ax*6] 0 [expr $ax*6] 0
+} -result [.t.c find withtag text]
+test font-31.5 {Tk_IntersectTextLayout procedure: ignore newlines} -body {
+ csetup "000\n0\n000"
+ .t.c find overlapping $ax $ay $ax $ay
+} -result {}
+test font-31.6 {Tk_IntersectTextLayout procedure: ignore spaces at eol} -body {
+ csetup "000\n000 000000000"
+ .t.c itemconfig text -width [expr $ax*10]
+ set x [.t.c find overlapping [expr $ax*5] $ay [expr $ax*5] $ay]
+ .t.c itemconfig text -width 0
+ return $x
+} -result {}
+test font-31.7 {TkIntersectAngledTextLayout procedure: bug [514ff64dd0]} -body {
+ csetup "This is line one\nand line two\nand line three here"
+ .t.c itemconfigure text -angle 90
+ # Coordinates of the rectangle to check can be hardcoded:
+ # The goal of this test is to check whether the overlap detection algorithm
+ # works when the rectangle is entirely included in a chunk of the text layout.
+ # The text has been rotated 90 degrees around it's upper left corner,
+ # so it's enough to check with a small rectangle with small negative y coords.
+ .t.c find overlapping 5 -7 7 -5
+} -result {1}
+destroy .t.c
+
+
+test font-32.1 {Tk_TextLayoutToPostscript: ensure buffer doesn't overflow} -setup {
+ destroy .t.c
+ canvas .t.c -closeenough 0
+ .t.c create text 0 0 -tags text -anchor nw -just left -font "Courier -12"
+ pack .t.c
+ update
+} -body {
+ # If there were a whole bunch of returns or tabs in a row, then the
+ # temporary buffer could overflow and write on the stack.
+ csetup "qwertyuiopasdfghjklzxcvbnm1234qwertyuiopasdfghjklzxcvbnm\n"
+ .t.c itemconfig text -width 800
+ .t.c insert text end "qwertyuiopasdfghjklzxcvbnm1234qwertyuiopasdfghjklzxcvbnm\n"
+ .t.c insert text end "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
+ .t.c insert text end "end"
+ set x [.t.c postscript]
+ set i [string first "(qwerty" $x]
+ string range $x $i [expr {$i + 278}]
+} -cleanup {
+ destroy .t.c
+} -result {(qwertyuiopasdfghjklzxcvbnm1234qwertyuiopasdfghjklzxcvbnm)]
+[(qwertyuiopasdfghjklzxcvbnm1234qwertyuiopasdfghjklzxcvbnm)]
+[()]
+[()]
+[()]
+[()]
+[()]
+[()]
+[()]
+[()]
+[()]
+[()]
+[()]
+[()]
+[()]
+[()]
+[()]
+[()]
+[()]
+[()]
+[()]
+[()]
+[()]
+[()]
+[()]
+[()]
+[()]
+[()]
+[()]
+[()]
+[()]
+[()]
+[(end)]
+}
+
+
+test font-33.1 {Tk_TextWidth procedure} -body {
+} -result {}
+
+
+test font-34.1 {ConfigAttributesObj procedure: arguments} -setup {
+ catch {font delete xyz}
+} -body {
+ # (Tcl_GetIndexFromObj() != TCL_OK)
+ font create xyz -xyz
+} -returnCodes {
+ error
+} -result {bad option "-xyz": must be -family, -size, -weight, -slant, -underline, or -overstrike}
+test font-34.2 {ConfigAttributesObj procedure: arguments} -setup {
+ catch {font delete xyz}
+} -body {
+ # (objc & 1)
+ font create xyz -family
+} -returnCodes error -result {value for "-family" option missing}
+
+test font-34.3 {ConfigAttributesObj procedure: family} -setup {
+ catch {font delete xyz}
+ set x {}
+} -body {
+ font create xyz -family xyz
+ lappend x [font config xyz -family]
+ font config xyz -family times
+ lappend x [font config xyz -family]
+} -cleanup {
+ font delete xyz
+} -result {xyz times}
+test font-34.4 {ConfigAttributesObj procedure: size} -setup {
+ catch {font delete xyz}
+ set x {}
+} -body {
+ font create xyz -size 20
+ lappend x [font config xyz -size]
+ font config xyz -size 40
+ lappend x [font config xyz -size]
+} -cleanup {
+ font delete xyz
+} -result {20 40}
+test font-34.5 {ConfigAttributesObj procedure: weight} -setup {
+ catch {font delete xyz}
+ set x {}
+} -body {
+ font create xyz -weight normal
+ lappend x [font config xyz -weight]
+ font config xyz -weight bold
+ lappend x [font config xyz -weight]
+} -cleanup {
+ font delete xyz
+} -result {normal bold}
+test font-34.6 {ConfigAttributesObj procedure: slant} -setup {
+ catch {font delete xyz}
+ set x {}
+} -body {
+ font create xyz -slant roman
+ lappend x [font config xyz -slant]
+ font config xyz -slant italic
+ lappend x [font config xyz -slant]
+} -cleanup {
+ font delete xyz
+} -result {roman italic}
+test font-34.7 {ConfigAttributesObj procedure: underline} -setup {
+ catch {font delete xyz}
+ set x {}
+} -body {
+ font create xyz -underline 0
+ lappend x [font config xyz -underline]
+ font config xyz -underline 1
+ lappend x [font config xyz -underline]
+} -cleanup {
+ font delete xyz
+} -result {0 1}
+test font-34.8 {ConfigAttributesObj procedure: overstrike} -setup {
+ catch {font delete xyz}
+ set x {}
+} -body {
+ font create xyz -overstrike 0
+ lappend x [font config xyz -overstrike]
+ font config xyz -overstrike 1
+ lappend x [font config xyz -overstrike]
+} -cleanup {
+ font delete xyz
+} -result {0 1}
+
+test font-34.9 {ConfigAttributesObj procedure: size} -body {
+ font create xyz -size xyz
+} -returnCodes error -result {expected integer but got "xyz"}
+test font-34.10 {ConfigAttributesObj procedure: weight} -body {
+ font create xyz -weight xyz
+} -returnCodes error -result {bad -weight value "xyz": must be normal, or bold}
+test font-34.11 {ConfigAttributesObj procedure: slant} -body {
+ font create xyz -slant xyz
+} -returnCodes error -result {bad -slant value "xyz": must be roman, or italic}
+test font-34.12 {ConfigAttributesObj procedure: underline} -body {
+ font create xyz -underline xyz
+} -returnCodes error -result {expected boolean value but got "xyz"}
+test font-34.13 {ConfigAttributesObj procedure: overstrike} -body {
+ font create xyz -overstrike xyz
+} -returnCodes error -result {expected boolean value but got "xyz"}
+
+
+test font-35.1 {GetAttributeInfoObj procedure: one attribute} -setup {
+ catch {font delete xyz}
+} -body {
+ # (objPtr != NULL)
+ font create xyz -family xyz
+ font config xyz -family
+} -cleanup {
+ font delete xyz
+} -result {xyz}
+
+
+test font-36.1 {GetAttributeInfoObj procedure: unknown attribute} -setup {
+ catch {font delete xyz}
+} -body {
+ # (Tcl_GetIndexFromObj() != TCL_OK)
+ font create xyz
+ font config xyz -xyz
+} -cleanup {
+ font delete xyz
+} -returnCodes {
+ error
+} -result {bad option "-xyz": must be -family, -size, -weight, -slant, -underline, or -overstrike}
+
+
+test font-37.1 {GetAttributeInfoObj procedure: all attributes} -setup {
+ catch {font delete xyz}
+} -body {
+ # not (objPtr != NULL)
+ font create xyz -family xyz
+ font config xyz
+} -cleanup {
+ font delete xyz
+} -result {-family xyz -size 0 -weight normal -slant roman -underline 0 -overstrike 0}
+test font-37.2 {GetAttributeInfo procedure: family} -setup {
+ catch {font delete xyz}
+} -body {
+ font create xyz -family xyz
+ font config xyz -family
+} -cleanup {
+ font delete xyz
+} -result {xyz}
+test font-37.3 {GetAttributeInfo procedure: size} -setup {
+ catch {font delete xyz}
+ set x {}
+} -body {
+ font create xyz -size 20
+ font config xyz -size
+} -cleanup {
+ font delete xyz
+} -result {20}
+test font-37.4 {GetAttributeInfo procedure: weight} -setup {
+ catch {font delete xyz}
+ set x {}
+} -body {
+ font create xyz -weight normal
+ font config xyz -weight
+} -cleanup {
+ font delete xyz
+} -result {normal}
+test font-37.5 {GetAttributeInfo procedure: slant} -setup {
+ catch {font delete xyz}
+ set x {}
+} -body {
+ font create xyz -slant italic
+ font config xyz -slant
+} -cleanup {
+ font delete xyz
+} -result {italic}
+test font-37.6 {GetAttributeInfo procedure: underline} -setup {
+ catch {font delete xyz}
+ set x {}
+} -body {
+ font create xyz -underline yes
+ font config xyz -underline
+} -cleanup {
+ font delete xyz
+} -result {1}
+test font-37.7 {GetAttributeInfo procedure: overstrike} -setup {
+ catch {font delete xyz}
+ set x {}
+} -body {
+ font create xyz -overstrike no
+ font config xyz -overstrike
+} -cleanup {
+ font delete xyz
+} -result {0}
+
+
+# In tests below, one field is set to "xyz" so that font name doesn't
+# look like a native X font, so that ParseFontNameObj or TkParseXLFD will
+# be called.
+
+test font-38.1 {ParseFontNameObj procedure: begins with -} -body {
+ lindex [font actual -xyz-times-*-*-*-*-*-*-*-*-*-*-*-*] 1
+} -result [font actual {times 0} -family]
+test font-38.2 {ParseFontNameObj procedure: begins with -*} -body {
+ lindex [font actual -*-times-xyz-*-*-*-*-*-*-*-*-*-*-*] 1
+} -result [font actual {times 0} -family]
+test font-38.3 {ParseFontNameObj procedure: begins with -, doesn't look like list} -body {
+ lindex [font actual -xyz-times-*-*-*-*-*-*-*-*-*-*-*-*] 1
+} -result [font actual {times 0} -family]
+test font-38.4 {ParseFontNameObj procedure: begins with -, looks like list} -body {
+ lindex [font actual {-family times}] 1
+} -result [font actual {times 0} -family]
+test font-38.5 {ParseFontNameObj procedure: begins with *} -body {
+ lindex [font actual *-times-xyz-*-*-*-*-*-*-*-*-*-*-*] 1
+} -result [font actual {times 0} -family]
+test font-38.6 {ParseFontNameObj procedure: begins with *} -body {
+ font actual *-times-xyz -family
+} -result [font actual {times 0} -family]
+test font-38.7 {ParseFontNameObj procedure: arguments} -constraints noExceed -body {
+ font actual "\{xyz"
+} -returnCodes error -result "font \"{xyz\" doesn't exist"
+test font-38.8 {ParseFontNameObj procedure: arguments} -constraints noExceed -body {
+ font actual ""
+} -returnCodes error -result {font "" doesn't exist}
+test font-38.9 {ParseFontNameObj procedure: arguments} -body {
+ font actual {times 20 xyz xyz}
+} -returnCodes error -result {unknown font style "xyz"}
+test font-38.10 {ParseFontNameObj procedure: arguments} -body {
+ font actual {times xyz xyz}
+} -returnCodes error -result {expected integer but got "xyz"}
+test font-38.11 {ParseFontNameObj procedure: stylelist loop} -constraints {
+ unixOrPc
+} -body {
+ lrange [font actual {times 12 bold italic overstrike underline}] 4 end
+} -result {-weight bold -slant italic -underline 1 -overstrike 1}
+test font-38.12 {ParseFontNameObj procedure: stylelist error} -body {
+ font actual {times 12 bold xyz}
+} -returnCodes error -result {unknown font style "xyz"}
+test font-38.13 "ParseFontNameObj: options with hyphenated family: bug #2791352" -body {
+ font actual {-family sans-serif -size 12 -weight bold -slant roman -underline 0 -overstrike 0}
+} -returnCodes ok -result [font actual {sans-serif 12 bold}]
+test font-38.14 "ParseFontNameObj: bug #2791352" -body {
+ font actual {-invalidfont 8 bold}
+} -returnCodes error -match glob -result {bad option "-invalidfont": *}
+
+
+test font-39.1 {NewChunk procedure: test realloc} -setup {
+ destroy .t.f
+ pack [label .t.f]
+ update
+} -body {
+ .t.f config -text "xxx\nxxx\txxx\nxxx\t\t\t"
+} -cleanup {
+ destroy .t.f
+} -result {}
+
+
+test font-40.1 {TkFontParseXLFD procedure: initial dash} -body {
+ font actual -xyz-times-*-*-*-*-*-*-*-*-*-*-*-* -family
+} -result [font actual {times 0} -family]
+test font-40.2 {TkFontParseXLFD procedure: no initial dash} -body {
+ font actual *-times-*-*-*-*-*-*-*-*-*-*-*-xyz -family
+} -result [font actual {times 0} -family]
+test font-40.3 {TkFontParseXLFD procedure: not enough fields} -body {
+ font actual -xyz-times-*-*-* -family
+} -result [font actual {times 0} -family]
+test font-40.4 {TkFontParseXLFD procedure: all fields unspecified} -body {
+ lindex [font actual -xyz-*-*-*-*-*-*-*-*-*-*-*-*-*] 0
+} -result {-family}
+test font-40.5 {TkFontParseXLFD procedure: all fields specified} -body {
+ lindex [font actual \
+ -foundry-times-weight-slant-setwidth-addstyle-10-10-10-10-spacing-avgwidth-registry-encoding] 1
+} -result [font actual {times 0} -family]
+
+
+test font-41.1 {TkParseXLFD procedure: arguments} -body {
+ # XLFD with bad pointsize: fallback to some system font.
+ font actual -*-*-*-*-*-*-xyz-*-*-*-*-*-*-*
+ set x {}
+} -result {}
+
+
+test font-42.1 {TkFontParseXLFD procedure: arguments} -body {
+ # XLFD with bad pixelsize: fallback to some system font.
+ font actual -*-*-*-*-*-*-*-xyz-*-*-*-*-*-*
+ set x {}
+} -result {}
+test font-42.2 {TkFontParseXLFD procedure: pixelsize specified} -body {
+ font metrics -xyz-times-*-*-*-*-12-*-*-*-*-*-*-* -linespace
+ set x {}
+} -result {}
+test font-42.3 {TkFontParseXLFD procedure: weird pixelsize specified} -body {
+ font metrics {-xyz-times-*-*-*-*-[ 12.0 0 12.0 0]-*-*-*-*-*-*-*} -linespace
+ set x {}
+} -result {}
+test font-42.4 {TkFontParseXLFD procedure: pointsize specified} -body {
+ font metrics -xyz-times-*-*-*-*-*-120-*-*-*-*-*-* -linespace
+ set x {}
+} -result {}
+test font-42.5 {TkFontParseXLFD procedure: weird pointsize specified} -body {
+ font metrics {-xyz-times-*-*-*-*-*-[ 12.0 0 12.0 0]-*-*-*-*-*-*} -linespace
+ set x {}
+} -result {}
+
+
+test font-43.1 {FieldSpecified procedure: specified vs. non-specified} -body {
+ font actual -xyz--*-*-*-*-*-*-*-*-*-*-*-*
+ font actual -xyz-*-*-*-*-*-*-*-*-*-*-*-*-*
+ font actual -xyz-?-*-*-*-*-*-*-*-*-*-*-*-*
+ lindex [font actual -xyz-times-*-*-*-*-*-*-*-*-*-*-*-*] 1
+} -result [font actual {times 0} -family]
+
+
+test font-44.1 {TkFontGetPixels: size < 0} -setup {
+ set oldscale [tk scaling]
+} -body {
+ tk scaling 0.5
+ font actual {times -12} -size
+} -cleanup {
+ tk scaling $oldscale
+} -result {24}
+test font-44.2 {TkFontGetPoints: size >= 0} -constraints noExceed -setup {
+ set oldscale [tk scaling]
+} -body {
+ tk scaling 0.5
+ font actual {times 12} -size
+} -cleanup {
+ tk scaling $oldscale
+} -result {12}
+
+
+test font-45.1 {TkFontGetAliasList: no match} -body {
+ font actual {snarky 10} -family
+} -result [font actual {-size 10} -family]
+test font-45.2 {TkFontGetAliasList: match} -constraints win -body {
+ font actual {times 10} -family
+} -result {Times New Roman}
+test font-45.3 {TkFontGetAliasList: match} -constraints {noExceed} -body {
+ if {[font actual {{times new roman} 10} -family] eq "Times New Roman"} {
+ # avoid test failure on systems that have a real "times new roman" font
+ set res 1
+ } else {
+ set res [expr {[font actual {{times new roman} 10} -family] eq \
+ [font actual {times 10} -family]} ]
+ }
+} -result {1}
+
+
+test font-46.1 {font actual, with character, no option, no --} -body {
+ font actual {times 10} a
+} -match glob -result [list -family [font actual {times 10} -family] -size *\
+ -slant roman -underline 0 -overstrike 0]
+
+test font-46.2 {font actual, with character introduced by --} -body {
+ font actual {times 10} -- -
+} -match glob -result [list -family [font actual {times 10} -family] -size *\
+ -slant roman -underline 0 -overstrike 0]
+
+test font-46.3 {font actual, with character and option} -body {
+ font actual {times 10} -family a
+} -result [font actual {times 10} -family]
+
+test font-46.4 {font actual, with character, option and --} -body {
+ font actual {times 10} -family -- -
+} -result [font actual {times 10} -family]
+
+test font-46.5 {font actual, too many chars} -body {
+ font actual {times 10} 123456789012345678901234567890123456789012345678901
+} -returnCodes error -result {expected a single character but got "1234567890123456789012345678901234567..."}
+
+test font-47.1 {Bug f214b8ad5b} -body {
+ interp create one
+ interp create two
+ load {} Tk one
+ load {} Tk two
+ one eval menu .menubar
+ two eval menu .menubar
+ interp delete one
+ interp delete two
+} -result {}
+
+# cleanup
+cleanupTests
+return
+
+
+
+
diff --git a/tk8.6/tests/fontchooser.test b/tk8.6/tests/fontchooser.test
new file mode 100644
index 0000000..4dad5da
--- /dev/null
+++ b/tk8.6/tests/fontchooser.test
@@ -0,0 +1,201 @@
+# Test the "tk::fontchooser" command
+#
+# Copyright (c) 2008 Pat Thoyts
+
+package require tcltest 2.1
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+
+# the following helper functions are related to the functions used
+# in winDialog.test where they are used to send messages to the win32
+# dialog (hence the wierdness).
+
+proc start {cmd} {
+ set ::tk_dialog {}
+ set ::iter_after 0
+ after 1 $cmd
+}
+proc then {cmd} {
+ set ::command $cmd
+ set ::dialogresult {}
+ set ::testfont {}
+ afterbody
+ vwait ::dialogresult
+ return $::dialogresult
+}
+proc afterbody {} {
+ if {$::tk_dialog == {}} {
+ if {[incr ::iter_after] > 30} {
+ set ::dialogresult ">30 iterations waiting for tk_dialog"
+ return
+ }
+ after 150 {afterbody}
+ return
+ }
+ uplevel #0 {set dialogresult [eval $command]}
+}
+proc Click {button} {
+ switch -exact -- $button {
+ ok { $::tk_dialog.ok invoke }
+ cancel { $::tk_dialog.cancel invoke }
+ apply { $::tk_dialog.apply invoke }
+ default { return -code error "invalid button name \"$button\"" }
+ }
+}
+proc ApplyFont {font} {
+# puts stderr "apply: $font"
+ set ::testfont $font
+}
+
+# -------------------------------------------------------------------------
+
+test fontchooser-1.1 {tk fontchooser: usage} -returnCodes error -body {
+ tk fontchooser -z
+} -result {unknown or ambiguous subcommand "-z": must be configure, hide, or show}
+
+test fontchooser-1.2 {tk fontchooser: usage} -returnCodes error -body {
+ tk fontchooser configure -z
+} -match glob -result {bad option "-z":*}
+
+test fontchooser-1.3 {tk fontchooser: usage} -returnCodes error -body {
+ tk fontchooser configure -parent . -font
+} -result {value for "-font" missing}
+
+test fontchooser-1.4 {tk fontchooser: usage} -returnCodes error -body {
+ tk fontchooser configure -parent . -title
+} -result {value for "-title" missing}
+
+test fontchooser-1.5 {tk fontchooser: usage} -returnCodes error -body {
+ tk fontchooser configure -parent . -command
+} -result {value for "-command" missing}
+
+test fontchooser-1.6 {tk fontchooser: usage} -returnCodes error -body {
+ tk fontchooser configure -title . -parent
+} -result {value for "-parent" missing}
+
+test fontchooser-1.7 {tk fontchooser: usage} -returnCodes error -body {
+ tk fontchooser configure -parent abc
+} -result {bad window path name "abc"}
+
+test fontchooser-1.8 {tk fontchooser: usage} -returnCodes ok -body {
+ tk fontchooser configure -visible
+} -result {0}
+
+test fontchooser-1.9 {tk fontchooser: usage} -returnCodes error -body {
+ tk fontchooser configure -visible 1
+} -match glob -result {*}
+
+# -------------------------------------------------------------------------
+#
+# The remaining tests in this file are only relevant for the script
+# implementation. They can be tested by sourcing the script file but
+# the Tk tests are run with -singleproc 1 and doing this affects the
+# result of later attempts to test the native implementations.
+#
+testConstraint scriptImpl [llength [info proc ::tk::fontchooser::Configure]]
+
+test fontchooser-2.0 {fontchooser -title} -constraints scriptImpl -body {
+ start {
+ tk::fontchooser::Configure -title "Hello"
+ tk::fontchooser::Show
+ }
+ then {
+ set x [wm title $::tk_dialog]
+ Click cancel
+ }
+ set x
+} -result {Hello}
+
+test fontchooser-2.1 {fontchooser -title (cyrillic)} -constraints scriptImpl -body {
+ start {
+ tk::fontchooser::Configure \
+ -title "\u041f\u0440\u0438\u0432\u0435\u0442"
+ tk::fontchooser::Show
+ }
+ then {
+ set x [wm title $::tk_dialog]
+ Click cancel
+ }
+ set x
+} -result "\u041f\u0440\u0438\u0432\u0435\u0442"
+
+test fontchooser-3.0 {fontchooser -parent} -constraints scriptImpl -body {
+ start {
+ tk::fontchooser::Configure -parent .
+ tk::fontchooser::Show
+ }
+ then {
+ set x [winfo parent $::tk_dialog]
+ Click cancel
+ }
+ set x
+} -result {.}
+
+test fontchooser-3.1 {fontchooser -parent (invalid)} -constraints scriptImpl -body {
+ tk::fontchooser::Configure -parent junk
+} -returnCodes error -match glob -result {bad window path *}
+
+test fontchooser-4.0 {fontchooser -font} -constraints scriptImpl -body {
+ start {
+ tk::fontchooser::Configure -command ApplyFont -font courier
+ tk::fontchooser::Show
+ }
+ then {
+ Click cancel
+ }
+ set ::testfont
+} -result {}
+
+test fontchooser-4.1 {fontchooser -font} -constraints scriptImpl -body {
+ start {
+ tk::fontchooser::Configure -command ApplyFont -font courier
+ tk::fontchooser::Show
+ }
+ then {
+ Click ok
+ }
+ expr {$::testfont ne {}}
+} -result {1}
+
+test fontchooser-4.2 {fontchooser -font} -constraints scriptImpl -body {
+ start {
+ tk::fontchooser::Configure -command ApplyFont -font TkDefaultFont
+ tk::fontchooser::Show
+ }
+ then {
+ Click ok
+ }
+ expr {$::testfont ne {}}
+} -result {1}
+
+test fontchooser-4.3 {fontchooser -font} -constraints scriptImpl -body {
+ start {
+ tk::fontchooser::Configure -command ApplyFont -font {times 14 bold}
+ tk::fontchooser::Show
+ }
+ then {
+ Click ok
+ }
+ expr {$::testfont ne {}}
+} -result {1}
+
+test fontchooser-4.4 {fontchooser -font} -constraints scriptImpl -body {
+ start {
+ tk::fontchooser::Configure -command ApplyFont -font {times 14 bold}
+ tk::fontchooser::Show
+ }
+ then {
+ Click ok
+ }
+ lrange $::testfont 1 end
+} -result {14 bold}
+
+# -------------------------------------------------------------------------
+
+cleanupTests
+return
+
+# Local Variables:
+# mode: tcl
+# indent-tabs-mode: nil
+# End:
diff --git a/tk8.6/tests/frame.test b/tk8.6/tests/frame.test
new file mode 100644
index 0000000..fe38128
--- /dev/null
+++ b/tk8.6/tests/frame.test
@@ -0,0 +1,1537 @@
+# This file is a Tcl script to test out the "frame" and "toplevel"
+# commands of Tk. It is organized in the standard fashion for Tcl
+# tests.
+#
+# Copyright (c) 1994 The Regents of the University of California.
+# Copyright (c) 1994-1996 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+
+# eatColors --
+# Creates a toplevel window and allocates enough colors in it to
+# use up all the slots in the colormap.
+#
+# Arguments:
+# w - Name of toplevel window to create.
+
+proc eatColors {w} {
+ catch {destroy $w}
+ toplevel $w
+ wm geom $w +0+0
+ canvas $w.c -width 400 -height 200 -bd 0
+ pack $w.c
+ for {set y 0} {$y < 8} {incr y} {
+ for {set x 0} {$x < 40} {incr x} {
+ set color [format #%02x%02x%02x [expr $x*6] [expr $y*30] 0]
+ $w.c create rectangle [expr 10*$x] [expr 20*$y] \
+ [expr 10*$x + 10] [expr 20*$y + 20] -outline {} \
+ -fill $color
+ }
+ }
+ update
+}
+
+# colorsFree --
+#
+# Returns 1 if there appear to be free colormap entries in a window,
+# 0 otherwise.
+#
+# Arguments:
+# w - Name of window in which to check.
+# red, green, blue - Intensities to use in a trial color allocation
+# to see if there are colormap entries free.
+
+proc colorsFree {w {red 31} {green 245} {blue 192}} {
+ set vals [winfo rgb $w [format #%02x%02x%02x $red $green $blue]]
+ expr ([lindex $vals 0]/256 == $red) && ([lindex $vals 1]/256 == $green) \
+ && ([lindex $vals 2]/256 == $blue)
+}
+
+
+test frame-1.1 {frame configuration options} -setup {
+ deleteWindows
+} -body {
+ frame .f -class NewFrame
+ .f configure -class
+} -cleanup {
+ deleteWindows
+} -result {-class class Class Frame NewFrame}
+test frame-1.2 {frame configuration options} -setup {
+ deleteWindows
+} -body {
+ frame .f -class NewFrame
+ .f configure -class Different
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {can't modify -class option after widget is created}
+
+test frame-1.3 {frame configuration options} -setup {
+ deleteWindows
+} -body {
+ frame .f -colormap new
+ .f configure -colormap
+} -cleanup {
+ deleteWindows
+} -result {-colormap colormap Colormap {} new}
+test frame-1.4 {frame configuration options} -setup {
+ deleteWindows
+} -body {
+ frame .f -colormap new
+ .f configure -colormap .
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {can't modify -colormap option after widget is created}
+
+test frame-1.5 {frame configuration options} -setup {
+ deleteWindows
+} -body {
+ frame .f -visual default
+ .f configure -visual
+} -cleanup {
+ deleteWindows
+} -result {-visual visual Visual {} default}
+test frame-1.6 {frame configuration options} -setup {
+ deleteWindows
+} -body {
+ frame .f -visual default
+ .f configure -visual best
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {can't modify -visual option after widget is created}
+
+test frame-1.7 {frame configuration options} -setup {
+ deleteWindows
+} -body {
+ frame .f -screen bogus
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {unknown option "-screen"}
+test frame-1.8 {frame configuration options} -setup {
+ deleteWindows
+} -body {
+ frame .f -container true
+} -cleanup {
+ deleteWindows
+} -result {.f}
+test frame-1.9 {frame configuration options} -setup {
+ deleteWindows
+} -body {
+ frame .f -container true
+ .f configure -container
+} -cleanup {
+ deleteWindows
+} -result {-container container Container 0 1}
+test frame-1.10 {frame configuration options} -setup {
+ deleteWindows
+} -body {
+ frame .f -container bogus
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {expected boolean value but got "bogus"}
+test frame-1.11 {frame configuration options} -setup {
+ deleteWindows
+} -body {
+ frame .f
+ .f configure -container 1
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {can't modify -container option after widget is created}
+test frame-1.12 {frame configuration options} -setup {
+ deleteWindows
+} -body {
+ # Make sure all options can be set to the default value
+ frame .f
+ set opts {}
+ foreach opt [.f configure] {
+ if {[llength $opt] == 5} {
+ lappend opts [lindex $opt 0] [lindex $opt 4]
+ }
+ }
+ eval frame .g $opts
+ destroy .f .g
+} -cleanup {
+ deleteWindows
+} -result {}
+
+destroy .f
+frame .f
+test frame-1.13 {frame configuration options} -body {
+ .f configure -background #ff0000
+ lindex [.f configure -background] 4
+} -cleanup {
+ .f configure -background [lindex [.f configure -background] 3]
+} -result {#ff0000}
+test frame-1.14 {frame configuration options} -body {
+ .f configure -background non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+test frame-1.15 {frame configuration options} -body {
+ .f configure -bd 4
+ lindex [.f configure -bd] 4
+} -cleanup {
+ .f configure -bd [lindex [.f configure -bd] 3]
+} -result {4}
+test frame-1.16 {frame configuration options} -body {
+ .f configure -bd badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test frame-1.17 {frame configuration options} -body {
+ .f configure -bg #00ff00
+ lindex [.f configure -bg] 4
+} -cleanup {
+ .f configure -bg [lindex [.f configure -bg] 3]
+} -result {#00ff00}
+test frame-1.18 {frame configuration options} -body {
+ .f configure -bg non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+test frame-1.19 {frame configuration options} -body {
+ .f configure -borderwidth 1.3
+ lindex [.f configure -borderwidth] 4
+} -cleanup {
+ .f configure -borderwidth [lindex [.f configure -borderwidth] 3]
+} -result {1}
+test frame-1.20 {frame configuration options} -body {
+ .f configure -borderwidth badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test frame-1.21 {frame configuration options} -body {
+ .f configure -cursor arrow
+ lindex [.f configure -cursor] 4
+} -cleanup {
+ .f configure -cursor [lindex [.f configure -cursor] 3]
+} -result {arrow}
+test frame-1.22 {frame configuration options} -body {
+ .f configure -cursor badValue
+} -returnCodes error -result {bad cursor spec "badValue"}
+test frame-1.23 {frame configuration options} -body {
+ .f configure -height 100
+ lindex [.f configure -height] 4
+} -cleanup {
+ .f configure -height [lindex [.f configure -height] 3]
+} -result {100}
+test frame-1.24 {frame configuration options} -body {
+ .f configure -height not_a_number
+} -returnCodes error -result {bad screen distance "not_a_number"}
+test frame-1.25 {frame configuration options} -body {
+ .f configure -highlightbackground #112233
+ lindex [.f configure -highlightbackground] 4
+} -cleanup {
+ .f configure -highlightbackground [lindex [.f configure -highlightbackground] 3]
+} -result {#112233}
+test frame-1.26 {frame configuration options} -body {
+ .f configure -highlightbackground ugly
+} -returnCodes error -result {unknown color name "ugly"}
+test frame-1.27 {frame configuration options} -body {
+ .f configure -highlightcolor #123456
+ lindex [.f configure -highlightcolor] 4
+} -cleanup {
+ .f configure -highlightcolor [lindex [.f configure -highlightcolor] 3]
+} -result {#123456}
+test frame-1.28 {frame configuration options} -body {
+ .f configure -highlightcolor non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+test frame-1.29 {frame configuration options} -body {
+ .f configure -highlightthickness 6
+ lindex [.f configure -highlightthickness] 4
+} -cleanup {
+ .f configure -highlightthickness [lindex [.f configure -highlightthickness] 3]
+} -result {6}
+test frame-1.30 {frame configuration options} -body {
+ .f configure -highlightthickness badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test frame-1.31 {frame configuration options} -body {
+ .f configure -padx 3
+ lindex [.f configure -padx] 4
+} -cleanup {
+ .f configure -padx [lindex [.f configure -padx] 3]
+} -result {3}
+test frame-1.32 {frame configuration options} -body {
+ .f configure -padx badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test frame-1.33 {frame configuration options} -body {
+ .f configure -pady 4
+ lindex [.f configure -pady] 4
+} -cleanup {
+ .f configure -pady [lindex [.f configure -pady] 3]
+} -result {4}
+test frame-1.34 {frame configuration options} -body {
+ .f configure -pady badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test frame-1.35 {frame configuration options} -body {
+ .f configure -relief ridge
+ lindex [.f configure -relief] 4
+} -cleanup {
+ .f configure -relief [lindex [.f configure -relief] 3]
+} -result {ridge}
+test frame-1.36 {frame configuration options} -body {
+ .f configure -relief badValue
+} -returnCodes error -result {bad relief "badValue": must be flat, groove, raised, ridge, solid, or sunken}
+test frame-1.37 {frame configuration options} -body {
+ .f configure -takefocus {any string}
+ lindex [.f configure -takefocus] 4
+} -cleanup {
+ .f configure -takefocus [lindex [.f configure -takefocus] 3]
+} -result {any string}
+test frame-1.38 {frame configuration options} -body {
+ .f configure -width 32
+ lindex [.f configure -width] 4
+} -cleanup {
+ .f configure -width [lindex [.f configure -width] 3]
+} -result {32}
+test frame-1.39 {frame configuration options} -body {
+ .f configure -width badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+destroy .f
+
+
+test frame-2.1 {toplevel configuration options} -setup {
+ deleteWindows
+} -body {
+ toplevel .t -width 200 -height 100 -class NewClass
+ wm geometry .t +0+0
+ .t configure -class
+} -cleanup {
+ deleteWindows
+} -result {-class class Class Toplevel NewClass}
+test frame-2.2 {toplevel configuration options} -setup {
+ deleteWindows
+} -body {
+ toplevel .t -width 200 -height 100 -class NewClass
+ wm geometry .t +0+0
+ .t configure -class Another
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {can't modify -class option after widget is created}
+
+test frame-2.3 {toplevel configuration options} -setup {
+ deleteWindows
+} -body {
+ toplevel .t -width 200 -height 100 -colormap new
+ wm geometry .t +0+0
+ .t configure -colormap
+} -cleanup {
+ deleteWindows
+} -result {-colormap colormap Colormap {} new}
+test frame-2.4 {toplevel configuration options} -setup {
+ deleteWindows
+} -body {
+ toplevel .t -width 200 -height 100 -colormap new
+ wm geometry .t +0+0
+ .t configure -colormap .
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {can't modify -colormap option after widget is created}
+
+test frame-2.5 {toplevel configuration options} -setup {
+ deleteWindows
+} -body {
+ toplevel .t -width 200 -height 100
+ wm geometry .t +0+0
+ .t configure -container 1
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {can't modify -container option after widget is created}
+test frame-2.6 {toplevel configuration options} -setup {
+ deleteWindows
+} -body {
+ catch {destroy .t}
+ toplevel .t -width 200 -height 100
+ wm geometry .t +0+0
+ catch {.t configure -container 1}
+ .t configure -container
+} -cleanup {
+ deleteWindows
+} -result {-container container Container 0 0}
+
+test frame-2.7 {toplevel configuration options} -setup {
+ deleteWindows
+} -body {
+ toplevel .t -width 200 -height 100 -colormap bogus
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {bad window path name "bogus"}
+
+
+test frame-2.8 {toplevel configuration options} -constraints {
+ win
+} -setup {
+ deleteWindows
+} -body {
+ catch {destroy .t}
+ toplevel .t -width 200 -height 100
+ wm geometry .t +0+0
+ .t configure -use 0x44022
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {window "0x44022" doesn't exist}
+test frame-2.9 {toplevel configuration options} -constraints {
+ win
+} -setup {
+ deleteWindows
+} -body {
+ catch {destroy .t}
+ toplevel .t -width 200 -height 100
+ wm geometry .t +0+0
+ catch {.t configure -use 0x44022}
+ .t configure -use
+} -cleanup {
+ deleteWindows
+} -result {-use use Use {} {}}
+
+test frame-2.10 {toplevel configuration options} -constraints {
+ nonwin
+} -setup {
+ deleteWindows
+} -body {
+ catch {destroy .t}
+ toplevel .t -width 200 -height 100
+ wm geometry .t +0+0
+ .t configure -use 0x44022
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {can't modify -use option after widget is created}
+test frame-2.11 {toplevel configuration options} -constraints {
+ nonwin
+} -setup {
+ deleteWindows
+} -body {
+ catch {destroy .t}
+ toplevel .t -width 200 -height 100
+ wm geometry .t +0+0
+ catch {.t configure -use 0x44022}
+ .t configure -use
+} -cleanup {
+ deleteWindows
+} -result {-use use Use {} {}}
+
+test frame-2.12 {toplevel configuration options} -setup {
+ deleteWindows
+} -body {
+ catch {destroy .t}
+ toplevel .t -width 200 -height 100 -visual default
+ wm geometry .t +0+0
+ .t configure -visual
+} -cleanup {
+ deleteWindows
+} -result {-visual visual Visual {} default}
+test frame-2.13 {toplevel configuration options} -setup {
+ deleteWindows
+} -body {
+ catch {destroy .t}
+ toplevel .t -width 200 -height 100 -visual default
+ wm geometry .t +0+0
+ .t configure -visual best
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {can't modify -visual option after widget is created}
+
+test frame-2.14 {toplevel configuration options} -setup {
+ deleteWindows
+} -body {
+ toplevel .t -width 200 -height 100 -visual who_knows?
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {unknown or ambiguous visual name "who_knows?": class must be best, directcolor, grayscale, greyscale, pseudocolor, staticcolor, staticgray, staticgrey, truecolor, or default}
+test frame-2.15 {toplevel configuration options} -constraints haveDISPLAY -setup {
+ deleteWindows
+} -body {
+ toplevel .t -width 200 -height 100 -screen $env(DISPLAY)
+ wm geometry .t +0+0
+ string compare [.t configure -screen] "-screen screen Screen {} $env(DISPLAY)"
+} -cleanup {
+ deleteWindows
+} -result {0}
+test frame-2.16 {toplevel configuration options} -constraints haveDISPLAY -setup {
+ deleteWindows
+} -body {
+ toplevel .t -width 200 -height 100 -screen $env(DISPLAY)
+ wm geometry .t +0+0
+ .t configure -screen another
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {can't modify -screen option after widget is created}
+
+test frame-2.17 {toplevel configuration options} -setup {
+ deleteWindows
+} -body {
+ toplevel .t -width 200 -height 100 -screen bogus
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {couldn't connect to display "bogus"}
+test frame-2.18 {toplevel configuration options} -setup {
+ deleteWindows
+} -body {
+ toplevel .t -container 1 -width 300 -height 120
+ wm geometry .t +0+0
+ toplevel .x -container 1 -use [winfo id .t]
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {windows cannot have both the -use and the -container option set}
+test frame-2.19 {toplevel configuration options} -setup {
+ deleteWindows
+ set opts {}
+} -body {
+ # Make sure all options can be set to the default value
+ toplevel .f
+ foreach opt [.f configure] {
+ if {[llength $opt] == 5} {
+ lappend opts [lindex $opt 0] [lindex $opt 4]
+ }
+ }
+ eval toplevel .g $opts
+ destroy .f .g
+} -cleanup {
+ deleteWindows
+} -result {}
+
+
+destroy .t
+toplevel .t -width 300 -height 150
+wm geometry .t +0+0
+update
+test frame-2.20 {toplevel configuration options} -body {
+ .t configure -background #ff0000
+ lindex [.t configure -background] 4
+} -result {#ff0000}
+test frame-2.21 {toplevel configuration options} -body {
+ .t configure -background non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+test frame-2.22 {toplevel configuration options} -body {
+ .t configure -bd 4
+ lindex [.t configure -bd] 4
+} -result {4}
+test frame-2.23 {toplevel configuration options} -body {
+ .t configure -bd badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test frame-2.24 {toplevel configuration options} -body {
+ .t configure -bg #00ff00
+ lindex [.t configure -bg] 4
+} -result {#00ff00}
+test frame-2.25 {toplevel configuration options} -body {
+ .t configure -bg non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+test frame-2.26 {toplevel configuration options} -body {
+ .t configure -borderwidth 1.3
+ lindex [.t configure -borderwidth] 4
+} -result {1}
+test frame-2.27 {toplevel configuration options} -body {
+ .t configure -borderwidth badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test frame-2.28 {toplevel configuration options} -body {
+ .t configure -cursor arrow
+ lindex [.t configure -cursor] 4
+} -result {arrow}
+test frame-2.29 {toplevel configuration options} -body {
+ .t configure -cursor badValue
+} -returnCodes error -result {bad cursor spec "badValue"}
+test frame-2.30 {toplevel configuration options} -body {
+ .t configure -height 100
+ lindex [.t configure -height] 4
+} -result {100}
+test frame-2.31 {toplevel configuration options} -body {
+ .t configure -height not_a_number
+} -returnCodes error -result {bad screen distance "not_a_number"}
+test frame-2.32 {toplevel configuration options} -body {
+ .t configure -highlightcolor #123456
+ lindex [.t configure -highlightcolor] 4
+} -result {#123456}
+test frame-2.33 {toplevel configuration options} -body {
+ .t configure -highlightcolor non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+test frame-2.34 {toplevel configuration options} -body {
+ .t configure -highlightthickness 3
+ lindex [.t configure -highlightthickness] 4
+} -result {3}
+test frame-2.35 {toplevel configuration options} -body {
+ .t configure -highlightthickness badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test frame-2.36 {toplevel configuration options} -body {
+ .t configure -padx 3
+ lindex [.t configure -padx] 4
+} -result {3}
+test frame-2.37 {toplevel configuration options} -body {
+ .t configure -padx badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test frame-2.38 {toplevel configuration options} -body {
+ .t configure -pady 4
+ lindex [.t configure -pady] 4
+} -result {4}
+test frame-2.39 {toplevel configuration options} -body {
+ .t configure -pady badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test frame-2.40 {toplevel configuration options} -body {
+ .t configure -relief ridge
+ lindex [.t configure -relief] 4
+} -result {ridge}
+test frame-2.41 {toplevel configuration options} -body {
+ .t configure -relief badValue
+} -returnCodes error -result {bad relief "badValue": must be flat, groove, raised, ridge, solid, or sunken}
+test frame-2.42 {toplevel configuration options} -body {
+ .t configure -width 32
+ lindex [.t configure -width] 4
+} -result {32}
+test frame-2.43 {toplevel configuration options} -body {
+ .t configure -width badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+destroy .t
+
+
+test frame-3.1 {TkCreateFrame procedure} -body {
+ frame
+} -returnCodes error -result {wrong # args: should be "frame pathName ?-option value ...?"}
+test frame-3.2 {TkCreateFrame procedure} -setup {
+ deleteWindows
+ frame .f
+} -body {
+ .f configure -class
+} -cleanup {
+ deleteWindows
+} -result {-class class Class Frame Frame}
+test frame-3.3 {TkCreateFrame procedure} -setup {
+ deleteWindows
+ toplevel .t
+ wm geometry .t +0+0
+} -body {
+ .t configure -class
+} -cleanup {
+ deleteWindows
+} -result {-class class Class Toplevel Toplevel}
+test frame-3.4 {TkCreateFrame procedure} -setup {
+ deleteWindows
+} -body {
+ toplevel .t -width 350 -class NewClass -bg black -visual default -height 90
+ wm geometry .t +0+0
+ update
+ list [lindex [.t configure -width] 4] \
+ [lindex [.t configure -background] 4] \
+ [lindex [.t configure -height] 4]
+} -cleanup {
+ deleteWindows
+} -result {350 black 90}
+
+# Be sure that the -class, -colormap, and -visual options are processed
+# before configuring the widget.
+test frame-3.5 {TkCreateFrame procedure} -setup {
+ deleteWindows
+} -body {
+ option add *NewFrame.background #123456
+ frame .f -class NewFrame
+ lindex [.f configure -background] 4
+} -cleanup {
+ deleteWindows
+ option clear
+} -result {#123456}
+test frame-3.6 {TkCreateFrame procedure} -setup {
+ deleteWindows
+} -body {
+ option add *NewFrame.background #123456
+ frame .f -class NewFrame
+ lindex [.f configure -background] 4
+} -cleanup {
+ deleteWindows
+ option clear
+} -result {#123456}
+test frame-3.7 {TkCreateFrame procedure} -setup {
+ deleteWindows
+} -body {
+ option add *NewFrame.background #332211
+ option add *f.class NewFrame
+ frame .f
+ list [lindex [.f configure -class] 4] [lindex [.f configure -background] 4]
+} -cleanup {
+ deleteWindows
+ option clear
+} -result {NewFrame #332211}
+test frame-3.8 {TkCreateFrame procedure} -setup {
+ deleteWindows
+} -body {
+ option add *Silly.background #122334
+ option add *f.Class Silly
+ frame .f
+ list [lindex [.f configure -class] 4] [lindex [.f configure -background] 4]
+} -cleanup {
+ deleteWindows
+ option clear
+} -result {Silly #122334}
+test frame-3.9 {TkCreateFrame procedure, -use option} -constraints {
+ unix
+} -setup {
+ deleteWindows
+} -body {
+ toplevel .t -container 1 -width 300 -height 120
+ wm geometry .t +0+0
+ toplevel .x -width 140 -height 300 -use [winfo id .t] -bg green
+ tkwait visibility .x
+ list [expr {[winfo rootx .x] - [winfo rootx .t]}] \
+ [expr {[winfo rooty .x] - [winfo rooty .t]}] \
+ [winfo width .t] [winfo height .t]
+} -cleanup {
+# This call to update idletasks was added to prevent a crash that was
+# observed on OSX 10.12 (Sierra) only. Any change, such as using the
+# Development version to make debugging symbols available, adding a print
+# statement, or calling update idletasks here, would make the test pass
+# with no segfault.
+ update idletasks
+ deleteWindows
+} -result {0 0 140 300}
+test frame-3.10 {TkCreateFrame procedure, -use option} -constraints {
+ unix
+} -setup {
+ deleteWindows
+} -body {
+ toplevel .t -container 1 -width 300 -height 120
+ wm geometry .t +0+0
+ option add *x.use [winfo id .t]
+ update
+ toplevel .x -width 140 -height 300 -bg green
+ tkwait visibility .x
+ update
+ list [expr {[winfo rootx .x] - [winfo rootx .t]}] \
+ [expr {[winfo rooty .x] - [winfo rooty .t]}] \
+ [winfo width .t] [winfo height .t]
+} -cleanup {
+ destroy .t
+ option clear
+} -result {0 0 140 300}
+
+# The tests below require specific display characteristics (i.e. that
+# they are run on a pseudocolor display of depth 8). Even so, they
+# are non-portable: some machines don't seem to ever run out of
+# colors.
+if {[testConstraint defaultPseudocolor8]} {
+ eatColors .t1
+}
+test frame-3.11 {TkCreateFrame procedure} -constraints {
+ defaultPseudocolor8 nonPortable
+} -setup {
+ deleteWindows
+} -body {
+ toplevel .t -width 300 -height 200 -bg #475601
+ wm geometry .t +0+0
+ update
+ colorsFree .t
+} -cleanup {
+ deleteWindows
+} -result {0}
+test frame-3.12 {TkCreateFrame procedure} -constraints {
+ defaultPseudocolor8 nonPortable
+} -setup {
+ deleteWindows
+} -body {
+ toplevel .t -width 300 -height 200 -bg #475601 -colormap new
+ wm geometry .t +0+0
+ update
+ colorsFree .t
+} -cleanup {
+ deleteWindows
+} -result {1}
+test frame-3.13 {TkCreateFrame procedure} -constraints {
+ defaultPseudocolor8 nonPortable
+} -setup {
+ deleteWindows
+} -body {
+ option add *t.class Toplevel2
+ option add *Toplevel2.colormap new
+ toplevel .t -width 300 -height 200 -bg #475601
+ wm geometry .t +0+0
+ update
+ option clear
+ colorsFree .t
+} -cleanup {
+ deleteWindows
+} -result {1}
+test frame-3.14 {TkCreateFrame procedure} -constraints {
+ defaultPseudocolor8 nonPortable
+} -setup {
+ deleteWindows
+} -body {
+ option add *t.class Toplevel3
+ option add *Toplevel3.Colormap new
+ toplevel .t -width 300 -height 200 -bg #475601 -colormap new
+ wm geometry .t +0+0
+ update
+ option clear
+ colorsFree .t
+} -cleanup {
+ deleteWindows
+} -result {1}
+test frame-3.15 {TkCreateFrame procedure, -use and -colormap} -constraints {
+ defaultPseudocolor8 unix nonPortable
+} -setup {
+ deleteWindows
+} -body {
+ toplevel .t -container 1 -width 300 -height 120
+ wm geometry .t +0+0
+ toplevel .x -width 140 -height 300 -use [winfo id .t] -bg green -colormap new
+ tkwait visibility .x
+ list [colorsFree .t] [colorsFree .x]
+} -cleanup {
+ destroy .t
+} -result {0 1}
+test frame-3.16 {TkCreateFrame procedure} -constraints {
+ defaultPseudocolor8 nonPortable
+} -setup {
+ deleteWindows
+} -body {
+ toplevel .t -width 300 -height 200 -bg #475601 -visual default
+ wm geometry .t +0+0
+ update
+ colorsFree .t
+} -cleanup {
+ deleteWindows
+} -result {0}
+test frame-3.17 {TkCreateFrame procedure} -constraints {
+ defaultPseudocolor8 nonPortable
+} -setup {
+ deleteWindows
+} -body {
+ toplevel .t -width 300 -height 200 -bg #475601 -visual default \
+ -colormap new
+ wm geometry .t +0+0
+ update
+ colorsFree .t
+} -cleanup {
+ deleteWindows
+} -result {1}
+test frame-3.18 {TkCreateFrame procedure} -constraints {
+ defaultPseudocolor8 haveGrayscale8 nonPortable
+} -setup {
+ deleteWindows
+} -body {
+ toplevel .t -visual {grayscale 8} -width 300 -height 200 -bg #434343
+ wm geometry .t +0+0
+ update
+ colorsFree .t 131 131 131
+} -cleanup {
+ deleteWindows
+} -result {1}
+test frame-3.19 {TkCreateFrame procedure} -constraints {
+ defaultPseudocolor8 haveGrayscale8 nonPortable
+} -setup {
+ deleteWindows
+} -body {
+ option add *t.class T4
+ option add *T4.visual {grayscale 8}
+ toplevel .t -width 300 -height 200 -bg #434343
+ wm geometry .t +0+0
+ update
+ option clear
+ list [colorsFree .t 131 131 131] [lindex [.t configure -visual] 4]
+} -cleanup {
+ deleteWindows
+} -result {1 {grayscale 8}}
+test frame-3.20 {TkCreateFrame procedure} -constraints {
+ defaultPseudocolor8 haveGrayscale8 nonPortable
+} -setup {
+ deleteWindows
+} -body {
+ set x ok
+ option add *t.class T5
+ option add *T5.Visual {grayscale 8}
+ toplevel .t -width 300 -height 200 -bg #434343
+ wm geometry .t +0+0
+ update
+ option clear
+ list [colorsFree .t 131 131 131] [lindex [.t configure -visual] 4]
+} -cleanup {
+ deleteWindows
+} -result {1 {grayscale 8}}
+test frame-3.21 {TkCreateFrame procedure} -constraints {
+ defaultPseudocolor8 haveGrayscale8 nonPortable
+} -setup {
+ deleteWindows
+} -body {
+ set x ok
+ toplevel .t -visual {grayscale 8} -width 300 -height 200 -bg #434343
+ wm geometry .t +0+0
+ update
+ colorsFree .t 131 131 131
+} -cleanup {
+ deleteWindows
+} -result {1}
+if {[testConstraint defaultPseudocolor8]} {
+ destroy .t1
+}
+
+test frame-3.22 {TkCreateFrame procedure, default dimensions} -setup {
+ deleteWindows
+} -body {
+ toplevel .t
+ wm geometry .t +0+0
+ update
+ set result "[winfo reqwidth .t] [winfo reqheight .t]"
+ frame .t.f -bg red
+ pack .t.f
+ update
+ lappend result [winfo reqwidth .t.f] [winfo reqheight .t.f]
+} -cleanup {
+ deleteWindows
+} -result {200 200 1 1}
+test frame-3.23 {TkCreateFrame procedure} -setup {
+ deleteWindows
+} -body {
+ frame .f -gorp glob
+} -returnCodes error -result {unknown option "-gorp"}
+test frame-3.24 {TkCreateFrame procedure} -setup {
+ deleteWindows
+} -body {
+ toplevel .t -width 300 -height 200 -colormap new -bogus option
+ wm geometry .t +0+0
+} -returnCodes error -result {unknown option "-bogus"}
+
+
+test frame-4.1 {TkCreateFrame procedure} -setup {
+ deleteWindows
+} -body {
+ catch {frame .f -gorp glob}
+ winfo exists .f
+} -result 0
+test frame-4.2 {TkCreateFrame procedure} -setup {
+ deleteWindows
+} -body {
+ list [frame .f -width 200 -height 100] [winfo exists .f]
+} -cleanup {
+ deleteWindows
+} -result {.f 1}
+
+
+frame .f -highlightcolor black
+test frame-5.1 {FrameWidgetCommand procedure} -body {
+ .f
+} -returnCodes error -result {wrong # args: should be ".f option ?arg ...?"}
+test frame-5.2 {FrameWidgetCommand procedure, cget option} -body {
+ .f cget
+} -returnCodes error -result {wrong # args: should be ".f cget option"}
+test frame-5.3 {FrameWidgetCommand procedure, cget option} -body {
+ .f cget a b
+} -returnCodes error -result {wrong # args: should be ".f cget option"}
+test frame-5.4 {FrameWidgetCommand procedure, cget option} -body {
+ .f cget -gorp
+} -returnCodes error -result {unknown option "-gorp"}
+test frame-5.5 {FrameWidgetCommand procedure, cget option} -body {
+ .f cget -highlightcolor
+} -result {black}
+test frame-5.6 {FrameWidgetCommand procedure, cget option} -body {
+ .f cget -screen
+} -returnCodes error -result {unknown option "-screen"}
+test frame-5.7 {FrameWidgetCommand procedure, cget option} -setup {
+ destroy .t
+} -body {
+ toplevel .t
+ .t cget -screen
+} -cleanup {
+ destroy .t
+} -returnCodes ok -match glob -result *
+
+test frame-5.8 {FrameWidgetCommand procedure, configure option} -body {
+ llength [.f configure]
+} -result {18}
+test frame-5.9 {FrameWidgetCommand procedure, configure option} -body {
+ .f configure -gorp
+} -returnCodes error -result {unknown option "-gorp"}
+test frame-5.10 {FrameWidgetCommand procedure, configure option} -body {
+ .f configure -gorp bogus
+} -returnCodes error -result {unknown option "-gorp"}
+test frame-5.11 {FrameWidgetCommand procedure, configure option} -body {
+ .f configure -width 200 -height
+} -returnCodes error -result {value for "-height" missing}
+test frame-5.12 {FrameWidgetCommand procedure} -body {
+ .f swizzle
+} -returnCodes error -result {bad option "swizzle": must be cget or configure}
+test frame-5.13 {FrameWidgetCommand procedure, configure option} -body {
+ llength [. configure]
+} -result {21}
+destroy .f
+
+test frame-6.1 {ConfigureFrame procedure} -setup {
+ deleteWindows
+} -body {
+ frame .f -width 150
+ list [winfo reqwidth .f] [winfo reqheight .f]
+} -cleanup {
+ deleteWindows
+} -result {150 1}
+test frame-6.2 {ConfigureFrame procedure} -setup {
+ deleteWindows
+} -body {
+ frame .f -height 97
+ list [winfo reqwidth .f] [winfo reqheight .f]
+} -cleanup {
+ deleteWindows
+} -result {1 97}
+test frame-6.3 {ConfigureFrame procedure} -setup {
+ deleteWindows
+} -body {
+ frame .f
+ set result {}
+ lappend result [winfo reqwidth .f] [winfo reqheight .f]
+ .f configure -width 100 -height 180
+ lappend result [winfo reqwidth .f] [winfo reqheight .f]
+ .f configure -width 0 -height 0
+ lappend result [winfo reqwidth .f] [winfo reqheight .f]
+} -cleanup {
+ deleteWindows
+} -result {1 1 100 180 100 180}
+
+test frame-7.1 {FrameEventProc procedure} -setup {
+ deleteWindows
+} -body {
+ frame .frame2
+ set result [info commands .frame2]
+ destroy .frame2
+ lappend result [info commands .frame2]
+} -result {.frame2 {}}
+test frame-7.2 {FrameEventProc procedure} -setup {
+ deleteWindows
+ set x {}
+} -body {
+ frame .f1 -bg #543210
+ rename .f1 .f2
+ lappend x [winfo children .]
+ lappend x [.f2 cget -bg]
+ destroy .f1
+ lappend x [info command .f*] [winfo children .]
+} -cleanup {
+ deleteWindows
+} -result {.f1 #543210 {} {}}
+
+test frame-8.1 {FrameCmdDeletedProc procedure} -setup {
+ deleteWindows
+} -body {
+ frame .f1
+ rename .f1 {}
+ list [info command .f*] [winfo children .]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+test frame-8.2 {FrameCmdDeletedProc procedure} -setup {
+ deleteWindows
+} -body {
+ toplevel .f1 -menu .m
+ wm geometry .f1 +0+0
+ update
+ rename .f1 {}
+ update
+ list [info command .f*] [winfo children .]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+#
+# This one fails with the dash-patch!!!! Still don't know why :-(
+#
+#test frame-8.3 {FrameCmdDeletedProc procedure} -setup {
+# eval destroy [winfo children .]
+# deleteWindows
+#} -body {
+# toplevel .f1 -menu .m
+# wm geometry .f1 +0+0
+# menu .m
+# update
+# rename .f1 {}
+# update
+# list [info command .f*] [winfo children .]
+#} -cleanup {
+# eval destroy [winfo children .]
+# deleteWindows
+#} -result {{} .m}
+
+test frame-9.1 {MapFrame procedure} -setup {
+ deleteWindows
+} -body {
+ toplevel .t -width 100 -height 400
+ wm geometry .t +0+0
+ set result [winfo ismapped .t]
+ update idletasks
+ lappend result [winfo ismapped .t]
+} -cleanup {
+ deleteWindows
+} -result {0 1}
+test frame-9.2 {MapFrame procedure} -setup {
+ deleteWindows
+} -body {
+ toplevel .t -width 100 -height 400
+ wm geometry .t +0+0
+ destroy .t
+ update
+ winfo exists .t
+} -result {0}
+test frame-9.3 {MapFrame procedure, window deleted while mapping} -setup {
+ deleteWindows
+} -body {
+ toplevel .t2 -width 200 -height 200
+ wm geometry .t2 +0+0
+ tkwait visibility .t2
+ toplevel .t -width 100 -height 400
+ wm geometry .t +0+0
+ frame .t2.f -width 50 -height 50
+ bind .t2.f <Configure> {destroy .t}
+ pack .t2.f -side top
+ update idletasks
+ winfo exists .t
+} -cleanup {
+ deleteWindows
+} -result {0}
+
+
+test frame-10.1 {frame widget vs hidden commands} -setup {
+ deleteWindows
+} -body {
+ set l [interp hidden]
+ frame .t
+ interp hide {} .t
+ destroy .t
+ set res1 [list [winfo children .] [interp hidden]]
+ set res2 [list {} $l]
+ expr {$res1 eq $res2}
+} -result 1
+
+
+test frame-11.1 {TkInstallFrameMenu} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add cascade -menu .m1.system
+ menu .m1.system -tearoff 0
+ .m1.system add command -label foo
+ toplevel .t -menu .m1
+} -cleanup {
+ deleteWindows
+} -result {.t}
+test frame-11.2 {TkInstallFrameMenu - frame renamed} -setup {
+ deleteWindows
+} -body {
+ catch {rename foo {}}
+ menu .m1
+ .m1 add cascade -menu .m1.system
+ menu .m1.system -tearoff 0
+ .m1.system add command -label foo
+ toplevel .t
+ rename .t foo
+} -cleanup {
+ deleteWindows
+} -result {}
+
+
+test frame-12.1 {FrameWorldChanged procedure} -setup {
+ deleteWindows
+} -body {
+ # Test -bd -padx and -pady
+ frame .f -borderwidth 2 -padx 3 -pady 4
+ place .f -x 0 -y 0 -width 40 -height 40
+ pack [frame .f.f] -fill both -expand 1
+ update
+ list [winfo x .f.f] [winfo y .f.f] [winfo width .f.f] [winfo height .f.f]
+} -cleanup {
+ deleteWindows
+} -result {5 6 30 28}
+test frame-12.2 {FrameWorldChanged procedure} -setup {
+ deleteWindows
+} -body {
+ # Test all -labelanchor positions
+ set font {helvetica 12}
+ labelframe .f -highlightthickness 1 -bd 3 -padx 1 -pady 2 -font $font \
+ -text "Mupp"
+ set fh [expr {[font metrics $font -linespace] + 2 - 3}]
+ set fw [expr {[font measure $font "Mupp"] + 2 - 3}]
+ if {$fw < 0} {set fw 0}
+ if {$fh < 0} {set fh 0}
+ place .f -x 0 -y 0 -width 100 -height 100
+ pack [frame .f.f] -fill both -expand 1
+
+ set result {}
+ foreach lp {nw n ne en e es se s sw ws w wn} {
+ .f configure -labelanchor $lp
+ update
+ set expx 5
+ set expy 6
+ set expw 90
+ set exph 88
+ switch -glob $lp {
+ n* {incr expy $fh ; incr exph -$fh}
+ s* {incr exph -$fh}
+ w* {incr expx $fw ; incr expw -$fw}
+ e* {incr expw -$fw}
+ }
+ lappend result [expr {\
+ [winfo x .f.f] == $expx && [winfo y .f.f] == $expy &&\
+ [winfo width .f.f] == $expw && [winfo height .f.f] == $exph}]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {1 1 1 1 1 1 1 1 1 1 1 1}
+test frame-12.3 {FrameWorldChanged procedure} -setup {
+ deleteWindows
+} -body {
+ # Check reaction on font change
+ font create myfont -family courier -size 10
+ labelframe .f -font myfont -text Mupp
+ place .f -x 0 -y 0 -width 40 -height 40
+ pack [frame .f.f] -fill both -expand 1
+ update
+ set h1 [font metrics myfont -linespace]
+ set y1 [winfo y .f.f]
+ font configure myfont -size 20
+ update
+ set h2 [font metrics myfont -linespace]
+ set y2 [winfo y .f.f]
+ expr {($h2 - $h1) - ($y2 - $y1)}
+} -cleanup {
+ deleteWindows
+ font delete myfont
+} -result {0}
+
+
+test frame-13.1 {labelframe configuration options} -setup {
+ deleteWindows
+} -body {
+ labelframe .f -class NewFrame
+ .f configure -class
+} -cleanup {
+ deleteWindows
+} -result {-class class Class Labelframe NewFrame}
+test frame-13.2 {labelframe configuration options} -setup {
+ deleteWindows
+} -body {
+ labelframe .f -class NewFrame
+ .f configure -class Different
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {can't modify -class option after widget is created}
+test frame-13.3 {labelframe configuration options} -setup {
+ deleteWindows
+} -body {
+ labelframe .f -colormap new
+} -cleanup {
+ deleteWindows
+} -result {.f}
+test frame-13.4 {labelframe configuration options} -setup {
+ deleteWindows
+} -body {
+ labelframe .f -visual default
+} -cleanup {
+ deleteWindows
+} -result {.f}
+test frame-13.5 {labelframe configuration options} -setup {
+ deleteWindows
+} -body {
+ labelframe .f -screen bogus
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {unknown option "-screen"}
+test frame-13.6 {labelframe configuration options} -setup {
+ deleteWindows
+} -body {
+ labelframe .f -container true
+} -cleanup {
+ deleteWindows
+} -result {.f}
+test frame-13.7 {labelframe configuration options} -setup {
+ deleteWindows
+} -body {
+ labelframe .f -container true
+ .f configure -container
+} -cleanup {
+ deleteWindows
+} -result {-container container Container 0 1}
+test frame-13.8 {labelframe configuration options} -setup {
+ deleteWindows
+} -body {
+ labelframe .f -container bogus
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {expected boolean value but got "bogus"}
+test frame-13.9 {labelframe configuration options} -setup {
+ deleteWindows
+} -body {
+ labelframe .f
+ .f configure -container 1
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {can't modify -container option after widget is created}
+
+destroy .f
+labelframe .f
+test frame-13.10 {labelframe configuration options} -body {
+ .f configure -background #ff0000
+ lindex [.f configure -background] 4
+} -cleanup {
+ .f configure -background [lindex [.f configure -background] 3]
+} -result {#ff0000}
+test frame-13.11 {labelframe configuration options} -body {
+ .f configure -background non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+test frame-13.12 {labelframe configuration options} -body {
+ .f configure -bd 4
+ lindex [.f configure -bd] 4
+} -cleanup {
+ .f configure -bd [lindex [.f configure -bd] 3]
+} -result {4}
+test frame-13.13 {labelframe configuration options} -body {
+ .f configure -bd badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test frame-13.14 {labelframe configuration options} -body {
+ .f configure -bg #00ff00
+ lindex [.f configure -bg] 4
+} -cleanup {
+ .f configure -bg [lindex [.f configure -bg] 3]
+} -result {#00ff00}
+test frame-13.15 {labelframe configuration options} -body {
+ .f configure -bg non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+test frame-13.16 {labelframe configuration options} -body {
+ .f configure -borderwidth 1.3
+ lindex [.f configure -borderwidth] 4
+} -cleanup {
+ .f configure -borderwidth [lindex [.f configure -borderwidth] 3]
+} -result {1}
+test frame-13.17 {labelframe configuration options} -body {
+ .f configure -borderwidth badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test frame-13.18 {labelframe configuration options} -body {
+ .f configure -cursor arrow
+ lindex [.f configure -cursor] 4
+} -cleanup {
+ .f configure -cursor [lindex [.f configure -cursor] 3]
+} -result {arrow}
+test frame-13.19 {labelframe configuration options} -body {
+ .f configure -cursor badValue
+} -returnCodes error -result {bad cursor spec "badValue"}
+test frame-13.20 {labelframe configuration options} -body {
+ .f configure -fg #0000ff
+ lindex [.f configure -fg] 4
+} -cleanup {
+ .f configure -fg [lindex [.f configure -fg] 3]
+} -result {#0000ff}
+test frame-13.21 {labelframe configuration options} -body {
+ .f configure -fg non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+test frame-13.22 {labelframe configuration options} -body {
+ .f configure -font {courier 8}
+ lindex [.f configure -font] 4
+} -cleanup {
+ .f configure -font [lindex [.f configure -font] 3]
+} -result {courier 8}
+test frame-13.23 {labelframe configuration options} -body {
+ .f configure -foreground #ff0000
+ lindex [.f configure -foreground] 4
+} -cleanup {
+ .f configure -foreground [lindex [.f configure -foreground] 3]
+} -result {#ff0000}
+test frame-13.24 {labelframe configuration options} -body {
+ .f configure -foreground non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+test frame-13.25 {labelframe configuration options} -body {
+ .f configure -height 100
+ lindex [.f configure -height] 4
+} -cleanup {
+ .f configure -height [lindex [.f configure -height] 3]
+} -result {100}
+test frame-13.26 {labelframe configuration options} -body {
+ .f configure -height not_a_number
+} -returnCodes error -result {bad screen distance "not_a_number"}
+test frame-13.27 {labelframe configuration options} -body {
+ .f configure -highlightbackground #112233
+ lindex [.f configure -highlightbackground] 4
+} -cleanup {
+ .f configure -highlightbackground [lindex [.f configure -highlightbackground] 3]
+} -result {#112233}
+test frame-13.28 {labelframe configuration options} -body {
+ .f configure -highlightbackground ugly
+} -returnCodes error -result {unknown color name "ugly"}
+test frame-13.29 {labelframe configuration options} -body {
+ .f configure -highlightcolor #123456
+ lindex [.f configure -highlightcolor] 4
+} -cleanup {
+ .f configure -highlightcolor [lindex [.f configure -highlightcolor] 3]
+} -result {#123456}
+test frame-13.30 {labelframe configuration options} -body {
+ .f configure -highlightcolor non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+test frame-13.31 {labelframe configuration options} -body {
+ .f configure -highlightthickness 6
+ lindex [.f configure -highlightthickness] 4
+} -cleanup {
+ .f configure -highlightthickness [lindex [.f configure -highlightthickness] 3]
+} -result {6}
+test frame-13.32 {labelframe configuration options} -body {
+ .f configure -highlightthickness badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test frame-13.33 {labelframe configuration options} -body {
+ .f configure -labelanchor se
+ lindex [.f configure -labelanchor] 4
+} -cleanup {
+ .f configure -labelanchor [lindex [.f configure -labelanchor] 3]
+} -result {se}
+test frame-13.34 {labelframe configuration options} -body {
+ .f configure -labelanchor badValue
+} -returnCodes error -result {bad labelanchor "badValue": must be e, en, es, n, ne, nw, s, se, sw, w, wn, or ws}
+test frame-13.35 {labelframe configuration options} -body {
+ .f configure -padx 3
+ lindex [.f configure -padx] 4
+} -cleanup {
+ .f configure -padx [lindex [.f configure -padx] 3]
+} -result {3}
+test frame-13.36 {labelframe configuration options} -body {
+ .f configure -padx badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test frame-13.37 {labelframe configuration options} -body {
+ .f configure -pady 4
+ lindex [.f configure -pady] 4
+} -cleanup {
+ .f configure -pady [lindex [.f configure -pady] 3]
+} -result {4}
+test frame-13.38 {labelframe configuration options} -body {
+ .f configure -pady badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test frame-13.39 {labelframe configuration options} -body {
+ .f configure -relief ridge
+ lindex [.f configure -relief] 4
+} -cleanup {
+ .f configure -relief [lindex [.f configure -relief] 3]
+} -result {ridge}
+test frame-13.40 {labelframe configuration options} -body {
+ .f configure -relief badValue
+} -returnCodes error -result {bad relief "badValue": must be flat, groove, raised, ridge, solid, or sunken}
+test frame-13.41 {labelframe configuration options} -body {
+ .f configure -takefocus {any string}
+ lindex [.f configure -takefocus] 4
+} -cleanup {
+ .f configure -takefocus [lindex [.f configure -takefocus] 3]
+} -result {any string}
+test frame-13.42 {labelframe configuration options} -body {
+ .f configure -text {any string}
+ lindex [.f configure -text] 4
+} -cleanup {
+ .f configure -text [lindex [.f configure -text] 3]
+} -result {any string}
+test frame-13.43 {labelframe configuration options} -body {
+ .f configure -width 32
+ lindex [.f configure -width] 4
+} -cleanup {
+ .f configure -width [lindex [.f configure -width] 3]
+} -result {32}
+test frame-13.44 {labelframe configuration options} -body {
+ .f configure -width badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+destroy .f
+
+
+test frame-14.1 {labelframe labelwidget option} -setup {
+ deleteWindows
+} -body {
+ # Test that label is moved in stacking order
+ label .l -text Mupp -font {helvetica 8}
+ labelframe .f -labelwidget .l
+ pack .f
+ frame .f.f -width 50 -height 50
+ pack .f.f
+ update
+ list [winfo children .] [winfo width .f] \
+ [expr {[winfo height .f] - [winfo height .l]}]
+} -cleanup {
+ deleteWindows
+} -result {{.f .l} 54 52}
+test frame-14.2 {labelframe labelwidget option} -setup {
+ deleteWindows
+} -body {
+ # Test the labelframe's reaction if the label is destroyed
+ label .l -text Aratherlonglabel
+ labelframe .f -labelwidget .l
+ pack .f
+ label .f.l -text Mupp
+ pack .f.l
+ update
+ set res [list [.f cget -labelwidget]]
+ lappend res [expr {[winfo width .f] - [winfo width .l]}]
+ destroy .l
+ lappend res [.f cget -labelwidget]
+ update
+ lappend res [expr {[winfo width .f] - [winfo width .f.l]}]
+} -cleanup {
+ deleteWindows
+} -result {.l 12 {} 4}
+test frame-14.3 {labelframe labelwidget option} -setup {
+ deleteWindows
+} -body {
+ # Test the labelframe's reaction if the label is stolen
+ label .l -text Aratherlonglabel
+ labelframe .f -labelwidget .l
+ pack .f
+ label .f.l -text Mupp
+ pack .f.l
+ update
+ set res [list [.f cget -labelwidget]]
+ lappend res [expr {[winfo width .f] - [winfo width .l]}]
+ pack .l
+ lappend res [.f cget -labelwidget]
+ update
+ lappend res [expr {[winfo width .f] - [winfo width .f.l]}]
+} -cleanup {
+ deleteWindows
+} -result {.l 12 {} 4}
+test frame-14.4 {labelframe labelwidget option} -setup {
+ deleteWindows
+} -body {
+ # Test the label's reaction if the labelframe is destroyed
+ label .l -text Mupp
+ labelframe .f -labelwidget .l
+ pack .f
+ update
+ set res [list [winfo manager .l]]
+ destroy .f
+ lappend res [winfo manager .l]
+} -cleanup {
+ deleteWindows
+} -result {labelframe {}}
+test frame-14.5 {labelframe labelwidget option} -setup {
+ deleteWindows
+} -body {
+ # Test that the labelframe reacts on changes in label
+ label .l -text Aratherlonglabel
+ labelframe .f -labelwidget .l
+ pack .f
+ label .f.l -text Mupp
+ pack .f.l
+ update
+ set first [winfo width .f]
+ set res [expr {[winfo width .f] - [winfo width .l]}]
+ .l configure -text Shorter
+ update
+ lappend res [expr {[winfo width .f] - [winfo width .l]}]
+ lappend res [expr {[winfo width .f] < $first}]
+ .l configure -text Alotlongerthananytimebefore
+ update
+ lappend res [expr {[winfo width .f] - [winfo width .l]}]
+ lappend res [expr {[winfo width .f] > $first}]
+} -cleanup {
+ deleteWindows
+} -result {12 12 1 12 1}
+test frame-14.6 {labelframe labelwidget option} -setup {
+ deleteWindows
+} -body {
+ # Destroying a labelframe with a child label caused a crash
+ # when not handling mapping of the label correctly.
+ # This test does not test anything directly, it's just ment
+ # to catch if the same mistake is made again.
+ labelframe .f
+ pack .f
+ label .f.l -text Mupp
+ .f configure -labelwidget .f.l
+ update
+} -cleanup {
+ deleteWindows
+} -result {}
+deleteWindows
+rename eatColors {}
+rename colorsFree {}
+
+# cleanup
+cleanupTests
+return
+
+
+
+
diff --git a/tk8.6/tests/geometry.test b/tk8.6/tests/geometry.test
new file mode 100644
index 0000000..13cc515
--- /dev/null
+++ b/tk8.6/tests/geometry.test
@@ -0,0 +1,291 @@
+# This file is a Tcl script to test the procedures in the file
+# tkGeometry.c (generic support for geometry managers). It is
+# organized in the standard fashion for Tcl tests.
+#
+# Copyright (c) 1994 The Regents of the University of California.
+# Copyright (c) 1994 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+proc getsize w {
+ regexp {(^[^+-]*)} [wm geometry $w] foo x
+ return $x
+}
+
+package require tcltest 2.2
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+namespace import -force tcltest::test
+
+
+wm geometry . 300x300
+raise .
+update
+
+frame .f -bd 2 -relief raised
+frame .f.f -bd 2 -relief sunken
+frame .f.f.f -bd 2 -relief raised
+button .b1 -text .b1
+button .b2 -text .b2
+button .b3 -text .b3
+button .f.f.b4 -text .b4
+
+test geometry-1.1 {Tk_ManageGeometry procedure} -setup {
+ foreach w {.f .f.f .f.f.f .b1 .b2 .b3} {
+ place forget $w
+ }
+} -body {
+ place .b1 -x 120 -y 80
+ update
+ list [winfo x .b1] [winfo y .b1]
+} -result {120 80}
+test geometry-1.2 {Tk_ManageGeometry procedure} -setup {
+ foreach w {.f .f.f .f.f.f .b1 .b2 .b3} {
+ place forget $w
+ }
+} -body {
+ place .f -x 20 -y 30 -width 200 -height 200
+ place .b1 -in .f -x 40 -y 30
+ update
+ pack .b1 -side top -anchor w
+ place .f -x 30 -y 40
+ update
+ list [winfo x .b1] [winfo y .b1]
+} -result {0 0}
+
+
+test geometry-2.1 {Tk_GeometryRequest procedure} -setup {
+ foreach w {.f .f.f .f.f.f .b1 .b2 .b3} {
+ place forget $w
+ }
+ destroy .f2
+} -body {
+ frame .f2
+ set result [list [winfo reqwidth .f2] [winfo reqheight .f2]]
+ .f2 configure -width 150 -height 300
+ update
+ lappend result [winfo reqwidth .f2] [winfo reqheight .f2] \
+ [winfo geom .f2]
+ place .f2 -x 10 -y 20
+ update
+ lappend result [winfo geom .f2]
+ .f2 configure -width 100 -height 80
+ update
+ lappend result [winfo geom .f2]
+} -cleanup {
+ destroy .f2
+} -result {1 1 150 300 1x1+0+0 150x300+10+20 100x80+10+20}
+
+
+test geometry-3.1 {Tk_SetInternalBorder procedure} -setup {
+ foreach w {.f .f.f .f.f.f .b1 .b2 .b3} {
+ place forget $w
+ }
+} -body {
+ place .f -x 20 -y 30 -width 200 -height 200
+ place .b1 -in .f -x 50 -y 5
+ update
+ set x [list [winfo x .b1] [winfo y .b1]]
+ .f configure -bd 5
+ update
+ lappend x [winfo x .b1] [winfo y .b1]
+} -cleanup {
+ .f configure -bd 2
+} -result {72 37 75 40}
+
+
+test geometry-4.1 {Tk_MaintainGeometry and Tk_UnmaintainGeometry} -setup {
+ foreach w {.f .f.f .f.f.f .b1 .b2 .b3} {
+ place forget $w
+ }
+} -body {
+ place .f -x 20 -y 30 -width 200 -height 200
+ place .f.f -x 15 -y 5 -width 150 -height 120
+ place .f.f.f -width 100 -height 80
+ place .b1 -in .f.f.f -x 50 -y 5
+ update
+ list [winfo x .b1] [winfo y .b1]
+} -result {91 46}
+test geometry-4.2 {Tk_MaintainGeometry and Tk_UnmaintainGeometry} -setup {
+ foreach w {.f .f.f .f.f.f .b1 .b2 .b3} {
+ place forget $w
+ }
+} -body {
+ place .f -x 20 -y 30 -width 200 -height 200
+ place .f.f -x 15 -y 5 -width 150 -height 120
+ place .f.f.f -width 100 -height 80
+ place .b1 -in .f.f.f -x 50 -y 5
+ place .b2 -in .f.f.f -x 10 -y 25
+ place .b3 -in .f.f.f -x 50 -y 25
+ update
+ place .f -x 30 -y 25
+ update
+ list [winfo x .b1] [winfo y .b1] [winfo x .b2] [winfo y .b2] \
+ [winfo x .b3] [winfo y .b3]
+} -result {101 41 61 61 101 61}
+test geometry-4.3 {Tk_MaintainGeometry and Tk_UnmaintainGeometry} -setup {
+ foreach w {.f .f.f .f.f.f .b1 .b2 .b3} {
+ place forget $w
+ }
+} -body {
+ place .f -x 20 -y 30 -width 200 -height 200
+ place .f.f -x 15 -y 5 -width 150 -height 120
+ place .f.f.f -width 100 -height 80
+ place .b1 -in .f.f.f -x 50 -y 5
+ place .b2 -in .f.f.f -x 10 -y 25
+ place .b3 -in .f.f.f -x 50 -y 25
+ update
+ destroy .b1
+ button .b1 -text .b1
+ place .f.f -x 10 -y 25
+ update
+ list [winfo x .b1] [winfo y .b1] [winfo x .b2] [winfo y .b2] \
+ [winfo x .b3] [winfo y .b3]
+} -result {0 0 46 86 86 86}
+test geometry-4.4 {Tk_MaintainGeometry and Tk_UnmaintainGeometry} -setup {
+ foreach w {.f .f.f .f.f.f .b1 .b2 .b3} {
+ place forget $w
+ }
+} -body {
+ place .f -x 20 -y 30 -width 200 -height 200
+ place .f.f -x 15 -y 5 -width 150 -height 120
+ place .f.f.f -width 100 -height 80
+ place .b1 -in .f.f.f -x 50 -y 5
+ place .b2 -in .f.f.f -x 10 -y 25
+ place .b3 -in .f.f.f -x 50 -y 25
+ update
+ destroy .b2
+ button .b2 -text .b2
+ place .f.f.f -x 2 -y 3
+ update
+ list [winfo x .b1] [winfo y .b1] [winfo x .b2] [winfo y .b2] \
+ [winfo x .b3] [winfo y .b3]
+} -result {93 49 0 0 93 69}
+test geometry-4.5 {Tk_MaintainGeometry and Tk_UnmaintainGeometry} -setup {
+ foreach w {.f .f.f .f.f.f .b1 .b2 .b3} {
+ place forget $w
+ }
+} -body {
+ place .f -x 20 -y 30 -width 200 -height 200
+ place .f.f -x 15 -y 5 -width 150 -height 120
+ place .f.f.f -width 100 -height 80
+ place .b1 -in .f.f.f -x 50 -y 5
+ place .b2 -in .f.f.f -x 10 -y 25
+ place .b3 -in .f.f.f -x 50 -y 25
+ update
+ destroy .b3
+ button .b3 -text .b3
+ place .f.f.f -x 2 -y 3
+ update
+ list [winfo x .b1] [winfo y .b1] [winfo x .b2] [winfo y .b2] \
+ [winfo x .b3] [winfo y .b3]
+} -result {93 49 53 69 0 0}
+test geometry-4.6 {Tk_MaintainGeometry and Tk_UnmaintainGeometry} -setup {
+ foreach w {.f .f.f .f.f.f .b1 .b2 .b3} {
+ place forget $w
+ }
+} -body {
+ foreach w {.f .f.f .f.f.f .b1 .b2 .b3 .f.f.b4} {
+ place forget $w
+ }
+ place .f -x 20 -y 30 -width 200 -height 200
+ place .f.f -x 15 -y 5 -width 150 -height 120
+ place .f.f.f -width 100 -height 80
+ place .f.f.b4 -in .f.f.f -x 50 -y 5
+ place .b2 -in .f.f.f -x 10 -y 25
+ update
+ place .f -x 25 -y 35
+ update
+ list [winfo x .f.f.b4] [winfo y .f.f.b4] [winfo x .b2] [winfo y .b2]
+} -result {54 9 56 71}
+test geometry-4.7 {Tk_MaintainGeometry and Tk_UnmaintainGeometry} -setup {
+ foreach w {.f .f.f .f.f.f .b1 .b2 .b3} {
+ place forget $w
+ }
+} -body {
+ bind .b1 <Configure> {lappend x configure}
+ place .f -x 20 -y 30 -width 200 -height 200
+ place .f.f -x 15 -y 5 -width 150 -height 120
+ place .f.f.f -width 100 -height 80
+ place .f.f.b4 -in .f.f.f -x 50 -y 5
+ place .b1 -in .f.f.f -x 10 -y 25
+ update
+ set x init
+ place .f -x 25 -y 35
+ update
+ lappend x |
+ place .f -x 30 -y 40
+ place .f.f -x 10 -y 0
+ update
+ return $x
+} -cleanup {
+ bind .b1 <Configure> {}
+} -result {init configure |}
+test geometry-4.8 {Tk_MaintainGeometry and Tk_UnmaintainGeometry} -setup {
+ foreach w {.f .f.f .f.f.f .b1 .b2 .b3} {
+ place forget $w
+ }
+} -body {
+ place .f -x 20 -y 30 -width 200 -height 200
+ place .f.f -x 15 -y 5 -width 150 -height 120
+ place .f.f.f -width 100 -height 80
+ place .b1 -in .f.f.f -x 50 -y 5
+ place .b2 -in .f.f.f -x 10 -y 25
+ place .b3 -in .f.f.f -x 50 -y 25
+ update
+ destroy .f.f
+ frame .f.f -bd 2 -relief raised
+ frame .f.f.f -bd 2 -relief raised
+ place .f -x 30 -y 25
+ update
+ list [winfo x .b1] [winfo y .b1] [winfo ismapped .b1] \
+ [winfo x .b2] [winfo y .b2] [winfo ismapped .b2] \
+ [winfo x .b3] [winfo y .b3] [winfo ismapped .b3]
+} -result {91 46 0 51 66 0 91 66 0}
+test geometry-4.9 {Tk_MaintainGeometry and Tk_UnmaintainGeometry} -setup {
+ foreach w {.f .f.f .f.f.f .b1 .b2 .b3} {
+ place forget $w
+ }
+} -body {
+ place .f -x 20 -y 30 -width 200 -height 200
+ place .f.f -x 15 -y 5 -width 150 -height 120
+ place .f.f.f -width 100 -height 80
+ place .b1 -in .f.f.f -x 50 -y 5
+ update
+ set result [winfo ismapped .b1]
+ place forget .f.f
+ update
+ lappend result [winfo ismapped .b1]
+ place .f.f -x 15 -y 5 -width 150 -height 120
+ update
+ lappend result [winfo ismapped .b1]
+} -result {1 0 1}
+test geometry-4.10 {Tk_MaintainGeometry and Tk_UnmaintainGeometry} -setup {
+ foreach w {.f .f.f .f.f.f .b1 .b2 .b3} {
+ place forget $w
+ }
+ destroy .t
+} -body {
+ toplevel .t
+ wm geometry .t +0+0
+ tkwait visibility .t
+ update
+ pack [frame .t.f]
+ button .t.quit -text Quit -command exit
+ pack .t.quit -in .t.f
+ wm iconify .t
+ set x 0
+ after 500 {set x 1}
+ tkwait variable x
+ wm deiconify .t
+ update
+ winfo ismapped .t.quit
+} -cleanup {
+ destroy .t
+} -result {1}
+
+
+# cleanup
+cleanupTests
+return
+
diff --git a/tk8.6/tests/get.test b/tk8.6/tests/get.test
new file mode 100644
index 0000000..ea08c8c
--- /dev/null
+++ b/tk8.6/tests/get.test
@@ -0,0 +1,138 @@
+# This file is a Tcl script to test out the procedures in the file
+# tkGet.c. It is organized in the standard fashion for Tcl
+# white-box tests.
+#
+# Copyright (c) 1998 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+namespace import -force tcltest::test
+
+test get-1.1 {Tk_GetAnchorFromObj} -setup {
+ button .b
+} -body {
+ .b configure -anchor n
+ .b cget -anchor
+} -cleanup {
+ destroy .b
+} -result {n}
+test get-1.2 {Tk_GetAnchorFromObj} -setup {
+ button .b
+} -body {
+ .b configure -anchor ne
+ .b cget -anchor
+} -cleanup {
+ destroy .b
+} -result {ne}
+test get-1.3 {Tk_GetAnchorFromObj} -setup {
+ button .b
+} -body {
+ .b configure -anchor e
+ .b cget -anchor
+} -cleanup {
+ destroy .b
+} -result {e}
+test get-1.4 {Tk_GetAnchorFromObj} -setup {
+ button .b
+} -body {
+ .b configure -anchor se
+ .b cget -anchor
+} -cleanup {
+ destroy .b
+} -result {se}
+test get-1.5 {Tk_GetAnchorFromObj} -setup {
+ button .b
+} -body {
+ .b configure -anchor s
+ .b cget -anchor
+} -cleanup {
+ destroy .b
+} -result {s}
+test get-1.6 {Tk_GetAnchorFromObj} -setup {
+ button .b
+} -body {
+ .b configure -anchor sw
+ .b cget -anchor
+} -cleanup {
+ destroy .b
+} -result {sw}
+test get-1.7 {Tk_GetAnchorFromObj} -setup {
+ button .b
+} -body {
+ .b configure -anchor w
+ .b cget -anchor
+} -cleanup {
+ destroy .b
+} -result {w}
+test get-1.8 {Tk_GetAnchorFromObj} -setup {
+ button .b
+} -body {
+ .b configure -anchor nw
+ .b cget -anchor
+} -cleanup {
+ destroy .b
+} -result {nw}
+test get-1.9 {Tk_GetAnchorFromObj} -setup {
+ button .b
+} -body {
+ .b configure -anchor n
+ .b cget -anchor
+} -cleanup {
+ destroy .b
+} -result {n}
+test get-1.10 {Tk_GetAnchorFromObj} -setup {
+ button .b
+} -body {
+ .b configure -anchor center
+ .b cget -anchor
+} -cleanup {
+ destroy .b
+} -result {center}
+test get-1.11 {Tk_GetAnchorFromObj - error} -setup {
+ button .b
+} -body {
+ .b configure -anchor unknown
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {bad anchor "unknown": must be n, ne, e, se, s, sw, w, nw, or center}
+
+
+test get-2.1 {Tk_GetJustifyFromObj} -setup {
+ button .b
+} -body {
+ .b configure -justify left
+ .b cget -justify
+} -cleanup {
+ destroy .b
+} -result {left}
+test get-2.2 {Tk_GetJustifyFromObj} -setup {
+ button .b
+} -body {
+ .b configure -justify right
+ .b cget -justify
+} -cleanup {
+ destroy .b
+} -result {right}
+test get-2.3 {Tk_GetJustifyFromObj} -setup {
+ button .b
+} -body {
+ .b configure -justify center
+ .b cget -justify
+} -cleanup {
+ destroy .b
+} -result {center}
+test get-2.4 {Tk_GetJustifyFromObj - error} -setup {
+ button .b
+} -body {
+ .b configure -justify stupid
+} -cleanup {
+ destroy .b
+} -returnCodes {error} -result {bad justification "stupid": must be left, right, or center}
+
+# cleanup
+cleanupTests
+return
+
diff --git a/tk8.6/tests/grab.test b/tk8.6/tests/grab.test
new file mode 100644
index 0000000..33399cb
--- /dev/null
+++ b/tk8.6/tests/grab.test
@@ -0,0 +1,188 @@
+# Tests for the grab command.
+#
+# This file contains a collection of tests for one or more of the Tk
+# built-in commands. Sourcing this file runs the tests and
+# generates output for errors. No output means no errors were found.
+#
+# Copyright (c) 1998-2000 by Ajuba Solutions.
+# All rights reserved.
+
+package require tcltest 2.2
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+namespace import -force tcltest::test
+
+# There's currently no way to test the actual grab effect, per se,
+# in an automated test. Therefore, this test suite only covers the
+# interface to the grab command (ie, error messages, etc.)
+
+
+test grab-1.1 {Tk_GrabObjCmd} -body {
+ grab
+} -returnCodes error -result {wrong # args: should be "grab ?-global? window" or "grab option ?arg ...?"}
+test grab-1.2 {Tk_GrabObjCmd} -body {
+ rename grab grabTest1.2
+ grabTest1.2
+} -cleanup {
+ rename grabTest1.2 grab
+} -returnCodes error -result {wrong # args: should be "grabTest1.2 ?-global? window" or "grabTest1.2 option ?arg ...?"}
+
+test grab-1.3 {Tk_GrabObjCmd, "grab ?-global? window"} -body {
+ grab .foo bar baz
+} -returnCodes error -result {wrong # args: should be "grab ?-global? window"}
+test grab-1.4 {Tk_GrabObjCmd, "grab ?-global? window"} -body {
+ destroy .foo
+ grab .foo
+} -returnCodes error -result {bad window path name ".foo"}
+test grab-1.5 {Tk_GrabObjCmd, "grab ?-global? window"} -body {
+ grab -foo bar
+} -returnCodes error -result {bad option "-foo": must be -global}
+test grab-1.6 {Tk_GrabObjCmd, "grab ?-global? window"} -body {
+ destroy .foo
+ grab -global .foo
+} -returnCodes error -result {bad window path name ".foo"}
+
+test grab-1.7 {Tk_GrabObjCmd} -body {
+ grab foo
+} -returnCodes error -result {bad option "foo": must be current, release, set, or status}
+
+test grab-1.8 {Tk_GrabObjCmd, "grab current ?window?"} -body {
+ grab current foo bar
+} -returnCodes error -result {wrong # args: should be "grab current ?window?"}
+test grab-1.9 {Tk_GrabObjCmd, "grab current ?window?"} -body {
+ destroy .foo
+ grab current .foo
+} -returnCodes error -result {bad window path name ".foo"}
+
+test grab-1.10 {Tk_GrabObjCmd, "grab release window"} -body {
+ grab release
+} -returnCodes error -result {wrong # args: should be "grab release window"}
+test grab-1.11 {Tk_GrabObjCmd, "grab release window"} -body {
+ destroy .foo
+ grab release .foo
+} -returnCodes ok -result {}
+test grab-1.12 {Tk_GrabObjCmd, "grab release window"} -body {
+ grab release foo
+} -returnCodes ok -result {}
+
+test grab-1.13 {Tk_GrabObjCmd, "grab set ?-global? window"} -body {
+ grab set
+} -returnCodes error -result {wrong # args: should be "grab set ?-global? window"}
+test grab-1.14 {Tk_GrabObjCmd, "grab set ?-global? window"} -body {
+ grab set foo bar baz
+} -returnCodes error -result {wrong # args: should be "grab set ?-global? window"}
+test grab-1.15 {Tk_GrabObjCmd, "grab set ?-global? window"} -body {
+ destroy .foo
+ grab set .foo
+} -returnCodes error -result {bad window path name ".foo"}
+test grab-1.16 {Tk_GrabObjCmd, "grab set ?-global? window"} -body {
+ grab set -foo bar
+} -returnCodes error -result {bad option "-foo": must be -global}
+test grab-1.17 {Tk_GrabObjCmd, "grab set ?-global? window"} -body {
+ destroy .foo
+ grab set -global .foo
+} -returnCodes error -result {bad window path name ".foo"}
+
+test grab-1.18 {Tk_GrabObjCmd, "grab status window"} -body {
+ grab status
+} -returnCodes error -result {wrong # args: should be "grab status window"}
+test grab-1.19 {Tk_GrabObjCmd, "grab status window"} -body {
+ grab status foo bar
+} -returnCodes error -result {wrong # args: should be "grab status window"}
+test grab-1.20 {Tk_GrabObjCmd, "grab status window"} -body {
+ destroy .foo
+ grab status .foo
+} -returnCodes error -result {bad window path name ".foo"}
+
+
+test grab-2.1 {Tk_GrabObjCmd, grab status gives correct status} -body {
+ set curr [grab current .]
+ if { [string length $curr] > 0 } {
+ grab release $curr
+ }
+ grab status .
+} -cleanup {
+ grab release .
+} -result {none}
+test grab-2.2 {Tk_GrabObjCmd, grab status gives correct status} -body {
+ set curr [grab current .]
+ if { [string length $curr] > 0 } {
+ grab release $curr
+ }
+ grab .
+ grab status .
+} -cleanup {
+ grab release .
+} -result {local}
+test grab-2.3 {Tk_GrabObjCmd, grab status gives correct status} -body {
+ set curr [grab current .]
+ if { [string length $curr] > 0 } {
+ grab release $curr
+ }
+ grab -global .
+ grab status .
+} -cleanup {
+ grab release .
+} -result {global}
+
+
+test grab-3.1 {Tk_GrabObjCmd, grab current gives correct information} -body {
+ set curr [grab current .]
+ if { [string length $curr] > 0 } {
+ grab release $curr
+ }
+ return $curr
+} -result {}
+test grab-3.2 {Tk_GrabObjCmd, grab current gives correct information} -body {
+ set curr [grab current .]
+ if { [string length $curr] > 0 } {
+ grab release $curr
+ }
+ grab .
+ grab current
+} -cleanup {
+ grab release .
+} -result {.}
+
+
+test grab-4.1 {Tk_GrabObjCmd, grab release releases grab} -body {
+ set curr [grab current .]
+ if { [string length $curr] > 0 } {
+ grab release $curr
+ }
+ grab .
+ set result [grab status .]
+ grab release .
+ lappend result [grab status .]
+ grab -global .
+ lappend result [grab status .]
+ grab release .
+ lappend result [grab status .]
+} -result {local none global none}
+
+
+test grab-5.1 {Tk_GrabObjCmd, grab set} -body {
+ set curr [grab current .]
+ if { [string length $curr] > 0 } {
+ grab release $curr
+ }
+ grab set .
+ list [grab current .] [grab status .]
+} -cleanup {
+ grab release .
+} -result {. local}
+test grab-5.2 {Tk_GrabObjCmd, grab set} -body {
+ set curr [grab current .]
+ if { [string length $curr] > 0 } {
+ grab release $curr
+ }
+ grab set -global .
+ list [grab current .] [grab status .]
+} -cleanup {
+ grab release .
+} -result {. global}
+
+
+cleanupTests
+return
+
diff --git a/tk8.6/tests/grid.test b/tk8.6/tests/grid.test
new file mode 100644
index 0000000..62474ff
--- /dev/null
+++ b/tk8.6/tests/grid.test
@@ -0,0 +1,2052 @@
+# This file is a Tcl script to test out the *NEW* "grid" command of Tk. It is
+# (almost) organized in the standard fashion for Tcl tests.
+#
+# Copyright (c) 1996 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+namespace import -force tcltest::test
+
+# helper routine to return "." to a sane state after a test.
+# The variable GRID_VERBOSE can be used to "look" at the result of one or all
+# of the tests
+
+proc grid_reset {{test ?} {top .}} {
+ global GRID_VERBOSE
+ if {[info exists GRID_VERBOSE]} {
+ if {$GRID_VERBOSE eq "" || $GRID_VERBOSE eq $test} {
+ puts -nonewline "grid test $test: "
+ flush stdout
+ gets stdin
+ }
+ }
+ eval destroy [winfo children $top]
+ update
+ foreach {cols rows} [grid size .] {}
+ for {set i 0} {$i <= $cols} {incr i} {
+ grid columnconfigure . $i -weight 0 -minsize 0 -pad 0 -uniform ""
+ }
+ for {set i 0} {$i <= $rows} {incr i} {
+ grid rowconfigure . $i -weight 0 -minsize 0 -pad 0 -uniform ""
+ }
+ grid propagate . 1
+ grid anchor . nw
+ update
+}
+
+grid_reset 0.0
+wm geometry . {}
+
+test grid-1.1 {basic argument checking} -body {
+ grid
+} -returnCodes error -result {wrong # args: should be "grid option arg ?arg ...?"}
+test grid-1.2 {basic argument checking} -body {
+ grid foo bar
+} -returnCodes error -result {bad option "foo": must be anchor, bbox, columnconfigure, configure, forget, info, location, propagate, remove, rowconfigure, size, or slaves}
+test grid-1.3 {basic argument checking} -body {
+ button .b
+ grid .b -row 0 -column
+} -cleanup {
+ grid_reset 1.3
+} -returnCodes error -result {extra option or option with no value}
+test grid-1.4 {basic argument checking} -body {
+ button .b
+ grid configure .b - foo
+} -cleanup {
+ grid_reset 1.4
+} -returnCodes error -result {unexpected parameter "foo" in configure list: should be window name or option}
+test grid-1.5 {basic argument checking} -body {
+ grid .
+} -returnCodes error -result {can't manage ".": it's a top-level window}
+test grid-1.6 {basic argument checking} -body {
+ grid x
+} -returnCodes error -result {can't determine master window}
+test grid-1.7 {basic argument checking} -body {
+ grid configure x
+} -returnCodes error -result {can't determine master window}
+test grid-1.8 {basic argument checking} -body {
+ button .b
+ grid x .b
+} -cleanup {
+ grid_reset 1.8
+} -returnCodes ok -result {}
+test grid-1.9 {basic argument checking} -body {
+ button .b
+ grid configure x .b
+} -cleanup {
+ grid_reset 1.9
+} -returnCodes ok -result {}
+
+
+test grid-2.1 {bbox} -body {
+ grid bbox .
+} -result {0 0 0 0}
+test grid-2.2 {bbox} -body {
+ button .b
+ grid .b
+ destroy .b
+ update
+ grid bbox .
+} -result {0 0 0 0}
+test grid-2.3 {bbox: argument checking} -body {
+ grid bbox . 0 0 5
+} -returnCodes error -result {wrong # args: should be "grid bbox master ?column row ?column row??"}
+test grid-2.4 {bbox} -body {
+ grid bbox .bad 0 0
+} -returnCodes error -result {bad window path name ".bad"}
+test grid-2.5 {bbox} -body {
+ grid bbox . x 0
+} -returnCodes error -result {expected integer but got "x"}
+test grid-2.6 {bbox} -body {
+ grid bbox . 0 x
+} -returnCodes error -result {expected integer but got "x"}
+test grid-2.7 {bbox} -body {
+ grid bbox . 0 0 x 0
+} -returnCodes error -result {expected integer but got "x"}
+test grid-2.8 {bbox} -body {
+ grid bbox . 0 0 0 x
+} -returnCodes error -result {expected integer but got "x"}
+test grid-2.9 {bbox} -body {
+ frame .1 -width 75 -height 75 -bg red
+ frame .2 -width 90 -height 90 -bg red
+ grid .1 -row 0 -column 0
+ grid .2 -row 1 -column 1
+ update
+ set a ""
+ lappend a [grid bbox .]
+ lappend a [grid bbox . 0 0]
+ lappend a [grid bbox . 0 0 1 1]
+ lappend a [grid bbox . 1 1]
+ return $a
+} -cleanup {
+ grid_reset 2.9
+} -result {{0 0 165 165} {0 0 75 75} {0 0 165 165} {75 75 90 90}}
+test grid-2.10 {bbox} -body {
+ frame .1 -width 75 -height 75 -bg red
+ frame .2 -width 90 -height 90 -bg red
+ grid .1 -row 0 -column 0
+ grid .2 -row 1 -column 1
+ update
+ set a ""
+ lappend a [grid bbox . 10 10 0 0]
+ lappend a [grid bbox . -2 -2 -1 -1]
+ lappend a [grid bbox . 10 10 12 12]
+ return $a
+} -cleanup {
+ grid_reset 2.10
+} -result {{0 0 165 165} {0 0 0 0} {165 165 0 0}}
+
+test grid-3.1 {configure: basic argument checking} -body {
+ grid configure foo
+} -returnCodes error -result {bad argument "foo": must be name of window}
+test grid-3.2 {configure: basic argument checking} -body {
+ button .b
+ grid configure .b
+ grid slaves .
+} -cleanup {
+ grid_reset 3.2
+} -result {.b}
+test grid-3.3 {configure: basic argument checking} -body {
+ button .b
+ grid .b -row -1
+} -cleanup {
+ grid_reset 3.3
+} -returnCodes error -result {bad row value "-1": must be a non-negative integer}
+test grid-3.4 {configure: basic argument checking} -body {
+ button .b
+ grid .b -column -1
+} -cleanup {
+ grid_reset 3.4
+} -returnCodes error -result {bad column value "-1": must be a non-negative integer}
+test grid-3.5 {configure: basic argument checking} -body {
+ button .b
+ grid .b -rowspan 0
+} -cleanup {
+ grid_reset 3.5
+} -returnCodes error -result {bad rowspan value "0": must be a positive integer}
+test grid-3.6 {configure: basic argument checking} -body {
+ button .b
+ grid .b -columnspan 0
+} -cleanup {
+ grid_reset 3.6
+} -returnCodes error -result {bad columnspan value "0": must be a positive integer}
+test grid-3.7 {configure: basic argument checking} -body {
+ frame .f
+ button .f.b
+ grid .f .f.b
+} -cleanup {
+ grid_reset 3.7
+} -returnCodes error -result {can't put .f.b inside .}
+test grid-3.8 {configure: basic argument checking} -body {
+ button .b
+ grid configure x .b
+ grid slaves .
+} -cleanup {
+ grid_reset 3.8
+} -result {.b}
+test grid-3.9 {configure: basic argument checking} -body {
+ button .b
+ grid configure y .b
+} -cleanup {
+ grid_reset 3.9
+} -returnCodes error -result {invalid window shortcut, "y" should be '-', 'x', or '^'}
+test grid-3.10 {ConfigureSlave procedure, bad -in option} -body {
+ frame .f
+ grid .f -in .f
+} -cleanup {
+ grid_reset 3.10
+} -returnCodes error -result {window can't be managed in itself}
+test grid-3.11 {prevent management loops} -body {
+ frame .f1
+ frame .f2
+ grid .f1 -in .f2
+ grid .f2 -in .f1
+} -cleanup {
+ grid_reset 3.11
+} -returnCodes error -result {can't put .f2 inside .f1, would cause management loop}
+test grid-3.12 {prevent management loops} -body {
+ frame .f1
+ frame .f2
+ frame .f3
+ grid .f1 -in .f2
+ grid .f2 -in .f3
+ grid .f3 -in .f1
+} -cleanup {
+ grid_reset 3.12
+} -returnCodes error -result {can't put .f3 inside .f1, would cause management loop}
+
+test grid-4.1 {forget: basic argument checking} -body {
+ grid forget foo
+} -returnCodes error -result {bad window path name "foo"}
+test grid-4.2 {forget} -body {
+ button .c
+ grid [button .b]
+ set a [grid slaves .]
+ grid forget .b .c
+ lappend a [grid slaves .]
+ return $a
+} -cleanup {
+ grid_reset 4.2
+} -result {.b {}}
+test grid-4.3 {forget} -body {
+ button .c
+ grid .c -row 2 -column 2 -rowspan 2 -columnspan 2 -padx 3 -pady 4 -sticky ns
+ grid forget .c
+ grid .c -row 0 -column 0
+ grid info .c
+} -cleanup {
+ grid_reset 4.3
+} -result {-in . -column 0 -row 0 -columnspan 1 -rowspan 1 -ipadx 0 -ipady 0 -padx 0 -pady 0 -sticky {}}
+test grid-4.4 {forget} -body {
+ button .c
+ grid .c -row 2 -column 2 -rowspan 2 -columnspan 2 -padx {3 5} -pady {4 7} -sticky ns
+ grid forget .c
+ grid .c -row 0 -column 0
+ grid info .c
+} -cleanup {
+ grid_reset 4.3.1
+} -result {-in . -column 0 -row 0 -columnspan 1 -rowspan 1 -ipadx 0 -ipady 0 -padx 0 -pady 0 -sticky {}}
+test grid-4.5 {forget, calling Tk_UnmaintainGeometry} -body {
+ frame .f -bd 2 -relief raised
+ place .f -x 10 -y 20 -width 200 -height 100
+ frame .f2 -width 50 -height 30 -bg red
+ grid .f2 -in .f
+ update
+ set x [winfo ismapped .f2]
+ grid forget .f2
+ place .f -x 30
+ update
+ lappend x [winfo ismapped .f2]
+} -cleanup {
+ grid_reset 4.4
+} -result {1 0}
+
+test grid-5.1 {info: basic argument checking} -body {
+ grid info a b
+} -returnCodes error -result {wrong # args: should be "grid info window"}
+test grid-5.2 {info} -body {
+ frame .1 -width 75 -height 75 -bg red
+ grid .1 -row 0 -column 0
+ update
+ grid info .x
+} -cleanup {
+ grid_reset 5.2
+} -returnCodes error -result {bad window path name ".x"}
+test grid-5.3 {info} -body {
+ frame .1 -width 75 -height 75 -bg red
+ grid .1 -row 0 -column 0
+ update
+ grid info .1
+} -cleanup {
+ grid_reset 5.3
+} -result {-in . -column 0 -row 0 -columnspan 1 -rowspan 1 -ipadx 0 -ipady 0 -padx 0 -pady 0 -sticky {}}
+test grid-5.4 {info} -body {
+ frame .1 -width 75 -height 75 -bg red
+ update
+ grid info .1
+} -cleanup {
+ grid_reset 5.4
+} -returnCodes ok -result {}
+
+test grid-6.1 {location: basic argument checking} -body {
+ grid location .
+} -returnCodes error -result {wrong # args: should be "grid location master x y"}
+test grid-6.2 {location: basic argument checking} -body {
+ grid location .bad 0 0
+} -returnCodes error -result {bad window path name ".bad"}
+test grid-6.3 {location: basic argument checking} -body {
+ grid location . x y
+} -returnCodes error -result {bad screen distance "x"}
+test grid-6.4 {location: basic argument checking} -body {
+ grid location . 1c y
+} -returnCodes error -result {bad screen distance "y"}
+test grid-6.5 {location: basic argument checking} -body {
+ frame .f
+ grid location .f 10 10
+} -cleanup {
+ grid_reset 6.5
+} -result {-1 -1}
+test grid-6.6 {location (x)} -body {
+ frame .f -width 200 -height 100 -highlightthickness 0 -bg red
+ grid .f
+ update
+ set got ""
+ set result ""
+ for {set x -10} { $x < 220} { incr x} {
+ set a [grid location . $x 0]
+ if {$a != $got} {
+ lappend result $x->$a
+ set got $a
+ }
+ }
+ return $result
+} -cleanup {
+ grid_reset 6.6
+} -result {{-10->-1 0} {0->0 0} {201->1 0}}
+test grid-6.7 {location (y)} -body {
+ frame .f -width 200 -height 100 -highlightthickness 0 -bg red
+ grid .f
+ update
+ set got ""
+ set result ""
+ for {set y -10} { $y < 110} { incr y} {
+ set a [grid location . 0 $y]
+ if {$a != $got} {
+ lappend result $y->$a
+ set got $a
+ }
+ }
+ return $result
+} -cleanup {
+ grid_reset 6.7
+} -result {{-10->0 -1} {0->0 0} {101->0 1}}
+test grid-6.8 {location (weights)} -body {
+ frame .f -width 300 -height 100 -highlightthickness 0 -bg red
+ frame .a
+ grid .a
+ grid .f -in .a
+ grid rowconfigure .f 0 -weight 1
+ grid columnconfigure .f 0 -weight 1
+ grid propagate .a 0
+ .a configure -width 200 -height 15
+ update
+ set got ""
+ set result ""
+ for {set y -10} { $y < 210} { incr y} {
+ set a [grid location . $y $y]
+ if {$a != $got} {
+ lappend result $y->$a
+ set got $a
+ }
+ }
+ return $result
+} -cleanup {
+ grid_reset 6.8
+} -result {{-10->-1 -1} {0->0 0} {16->0 1} {201->1 1}}
+test grid-6.9 {location: check updates pending} -constraints {
+ nonPortable
+} -body {
+ set a ""
+ foreach i {0 1 2} {
+ frame .$i -width 120 -height 75 -bg red
+ lappend a [grid location . 150 90]
+ grid .$i -row $i -column $i
+ }
+ return $a
+} -cleanup {
+ grid_reset 6.9
+} -result {{0 0} {1 1} {1 1}}
+
+test grid-7.1 {propagate} -body {
+ grid propagate . 1 xxx
+} -cleanup {
+ grid_reset 7.1
+} -returnCodes error -result {wrong # args: should be "grid propagate window ?boolean?"}
+test grid-7.2 {propagate} -body {
+ grid propagate .
+} -cleanup {
+ grid_reset 7.2
+} -result {1}
+test grid-7.3 {propagate} -body {
+ grid propagate . 0;grid propagate .
+} -cleanup {
+ grid_reset 7.3
+} -result {0}
+test grid-7.4 {propagate} -body {
+ grid propagate .x
+} -cleanup {
+ grid_reset 7.4
+} -returnCodes error -result {bad window path name ".x"}
+test grid-7.5 {propagate} -body {
+ grid propagate . x
+} -cleanup {
+ grid_reset 7.5
+} -returnCodes error -result {expected boolean value but got "x"}
+test grid-7.6 {propagate} -body {
+ frame .f -width 100 -height 100 -bg red
+ grid .f -row 0 -column 0
+ update
+ set a [winfo width .f]x[winfo height .f]
+ grid propagate .f 0
+ frame .g -width 75 -height 85 -bg green
+ grid .g -in .f -row 0 -column 0
+ update
+ lappend a [winfo width .f]x[winfo height .f]
+ grid propagate .f 1
+ update
+ lappend a [winfo width .f]x[winfo height .f]
+ return $a
+} -cleanup {
+ grid_reset 7.6
+} -result {100x100 100x100 75x85}
+test grid-7.7 {propagate} -body {
+ grid propagate . 1
+ set res [list [grid propagate .]]
+ grid propagate . 0
+ lappend res [grid propagate .]
+ grid propagate . 0
+ lappend res [grid propagate .]
+ return $res
+} -cleanup {
+ grid_reset 7.7
+} -result [list 1 0 0]
+
+test grid-8.1 {size} -body {
+ grid size . foo
+} -cleanup {
+ grid_reset 8.1
+} -returnCodes error -result {wrong # args: should be "grid size window"}
+test grid-8.2 {size} -body {
+ grid size .x
+} -cleanup {
+ grid_reset 8.2
+} -returnCodes error -result {bad window path name ".x"}
+test grid-8.3 {size} -body {
+ frame .f
+ grid size .f
+} -cleanup {
+ grid_reset 8.3
+} -result {0 0}
+test grid-8.4 {size} -body {
+ catch {unset a}
+ scale .f
+ grid .f -row 0 -column 0
+ update
+ lappend a [grid size .]
+ grid .f -row 4 -column 5
+ update
+ lappend a [grid size .]
+ grid .f -row 947 -column 663
+ update
+ lappend a [grid size .]
+ grid .f -row 0 -column 0
+ update
+ lappend a [grid size .]
+ return $a
+} -cleanup {
+ grid_reset 8.4
+} -result {{1 1} {6 5} {664 948} {1 1}}
+test grid-8.5 {size} -body {
+ catch {unset a}
+ scale .f
+ grid .f -row 0 -column 0
+ update
+ lappend a [grid size .]
+ grid rowconfigure . 17 -weight 1
+ update
+ lappend a [grid size .]
+ grid columnconfigure . 63 -weight 1
+ update
+ lappend a [grid size .]
+ grid columnconfigure . 63 -weight 0
+ grid rowconfigure . 17 -weight 0
+ update
+ lappend a [grid size .]
+ return $a
+} -cleanup {
+ grid_reset 8.5
+} -result {{1 1} {1 18} {64 18} {1 1}}
+test grid-8.6 {size} -body {
+ catch {unset a}
+ scale .f
+ grid .f -row 10 -column 50
+ update
+ lappend a [grid size .]
+ grid columnconfigure . 15 -weight 1
+ grid columnconfigure . 30 -weight 1
+ update
+ lappend a [grid size .]
+ grid .f -row 10 -column 20
+ update
+ lappend a [grid size .]
+ grid columnconfigure . 30 -weight 0
+ update
+ lappend a [grid size .]
+ grid .f -row 0 -column 0
+ update
+ lappend a [grid size .]
+ grid columnconfigure . 15 -weight 0
+ update
+ lappend a [grid size .]
+ return $a
+} -cleanup {
+ grid_reset 8.6
+} -result {{51 11} {51 11} {31 11} {21 11} {16 1} {1 1}}
+
+test grid-9.1 {slaves} -body {
+ grid slaves .
+} -returnCodes ok -result {}
+test grid-9.2 {slaves} -body {
+ grid slaves .foo
+} -returnCodes error -result {bad window path name ".foo"}
+test grid-9.3 {slaves} -body {
+ grid slaves a b
+} -returnCodes error -result {wrong # args: should be "grid slaves window ?-option value ...?"}
+test grid-9.4 {slaves} -body {
+ grid slaves . a b
+} -returnCodes error -result {bad option "a": must be -column or -row}
+test grid-9.5 {slaves} -body {
+ grid slaves . -column x
+} -returnCodes error -result {expected integer but got "x"}
+test grid-9.6 {slaves} -body {
+ grid slaves . -row -3
+} -returnCodes error -result {-3 is an invalid value: should NOT be < 0}
+test grid-9.7 {slaves} -body {
+ grid slaves . -foo 3
+} -returnCodes error -result {bad option "-foo": must be -column or -row}
+test grid-9.8 {slaves} -body {
+ grid slaves .x -row 3
+} -returnCodes error -result {bad window path name ".x"}
+test grid-9.9 {slaves} -body {
+ grid slaves . -row 3
+} -returnCodes ok -result {}
+test grid-9.10 {slaves} -body {
+ foreach i {0 1 2} {
+ label .$i -text $i
+ grid .$i -row $i -column $i
+ }
+ grid slaves .
+} -cleanup {
+ grid_reset 9.10
+} -result {.2 .1 .0}
+test grid-9.11 {slaves} -body {
+ catch {unset a}
+ foreach i {0 1 2} {
+ label .$i -text $i
+ label .$i-x -text $i-x
+ grid .$i -row $i -column $i
+ grid .$i-x -row $i -column [incr i]
+ }
+ foreach row {0 1 2 3} {
+ lappend a $row{[grid slaves . -row $row]}
+ }
+ foreach col {0 1 2 3} {
+ lappend a $col{[grid slaves . -column $col]}
+ }
+ return $a
+} -cleanup {
+ grid_reset 9.11
+} -result {{0{.0-x .0}} {1{.1-x .1}} {2{.2-x .2}} 3{} 0{.0} {1{.1 .0-x}} {2{.2 .1-x}} 3{.2-x}}
+
+# column/row configure
+test grid-10.1 {column/row configure} -body {
+ grid columnconfigure .
+} -cleanup {
+ grid_reset 10.1
+} -returnCodes error -result {wrong # args: should be "grid columnconfigure master index ?-option value ...?"}
+test grid-10.2 {column/row configure} -body {
+ grid columnconfigure . 0 -weight 0 -pad
+} -cleanup {
+ grid_reset 10.2
+} -returnCodes error -result {wrong # args: should be "grid columnconfigure master index ?-option value ...?"}
+test grid-10.3 {column/row configure} -body {
+ grid columnconfigure .f 0 -weight
+} -cleanup {
+ grid_reset 10.3
+} -returnCodes error -result {bad window path name ".f"}
+test grid-10.4 {column/row configure} -body {
+ grid columnconfigure . nine -weight
+} -cleanup {
+ grid_reset 10.4
+} -returnCodes error -result {expected integer but got "nine" (when retrieving options only integer indices are allowed)}
+test grid-10.5 {column/row configure} -body {
+ grid columnconfigure . 265 -weight
+} -cleanup {
+ grid_reset 10.5
+} -result {0}
+test grid-10.6 {column/row configure} -body {
+ grid columnconfigure . 0
+} -cleanup {
+ grid_reset 10.6
+} -result {-minsize 0 -pad 0 -uniform {} -weight 0}
+test grid-10.7 {column/row configure} -body {
+ grid columnconfigure . 0 -foo
+} -cleanup {
+ grid_reset 10.7
+} -returnCodes error -result {bad option "-foo": must be -minsize, -pad, -uniform, or -weight}
+test grid-10.8 {column/row configure} -body {
+ grid columnconfigure . 0 -minsize foo
+} -cleanup {
+ grid_reset 10.8
+} -returnCodes error -result {bad screen distance "foo"}
+test grid-10.9 {column/row configure} -body {
+ grid columnconfigure . 0 -minsize foo
+} -cleanup {
+ grid_reset 10.9
+} -returnCodes error -result {bad screen distance "foo"}
+test grid-10.10 {column/row configure} -body {
+ grid columnconfigure . 0 -minsize 10
+ grid columnconfigure . 0 -minsize
+} -cleanup {
+ grid_reset 10.10
+} -result {10}
+test grid-10.11 {column/row configure} -body {
+ grid columnconfigure . 0 -weight bad
+} -cleanup {
+ grid_reset 10.11
+} -returnCodes error -result {expected integer but got "bad"}
+test grid-10.12 {column/row configure} -body {
+ grid columnconfigure . 0 -weight -3
+} -cleanup {
+ grid_reset 10.12
+} -returnCodes error -result {invalid arg "-weight": should be non-negative}
+test grid-10.13 {column/row configure} -body {
+ grid columnconfigure . 0 -weight 3
+ grid columnconfigure . 0 -weight
+} -cleanup {
+ grid_reset 10.13
+} -result {3}
+test grid-10.14 {column/row configure} -body {
+ grid columnconfigure . 0 -pad foo
+} -cleanup {
+ grid_reset 10.14
+} -returnCodes error -result {bad screen distance "foo"}
+test grid-10.15 {column/row configure} -body {
+ grid columnconfigure . 0 -pad -3
+} -cleanup {
+ grid_reset 10.15
+} -returnCodes error -result {invalid arg "-pad": should be non-negative}
+test grid-10.16 {column/row configure} -body {
+ grid columnconfigure . 0 -pad 3
+ grid columnconfigure . 0 -pad
+} -cleanup {
+ grid_reset 10.16
+} -result {3}
+test grid-10.17 {column/row configure} -body {
+ frame .f
+ set a ""
+ grid columnconfigure .f 0 -weight 0
+ lappend a [grid columnconfigure .f 0 -weight]
+ grid columnconfigure .f 0 -weight 1
+ lappend a [grid columnconfigure .f 0 -weight]
+ grid rowconfigure .f 0 -weight 0
+ lappend a [grid rowconfigure .f 0 -weight]
+ grid rowconfigure .f 0 -weight 1
+ lappend a [grid columnconfigure .f 0 -weight]
+ grid columnconfigure .f 0 -weight 0
+ return $a
+} -cleanup {
+ grid_reset 10.17
+} -result {0 1 0 1}
+test grid-10.18 {column/row configure} -body {
+ frame .f
+ grid columnconfigure .f {0 2} -minsize 10 -weight 1
+ list [grid columnconfigure .f 0 -minsize] \
+ [grid columnconfigure .f 1 -minsize] \
+ [grid columnconfigure .f 2 -minsize] \
+ [grid columnconfigure .f 0 -weight] \
+ [grid columnconfigure .f 1 -weight] \
+ [grid columnconfigure .f 2 -weight]
+} -cleanup {
+ grid_reset 10.18
+} -result {10 0 10 1 0 1}
+test grid-10.19 {column/row configure} -body {
+ grid columnconfigure . {0 -1 2} -weight 1
+} -cleanup {
+ grid_reset 10.19
+} -returnCodes error -result {"-1" is out of range}
+test grid-10.20 {column/row configure} -body {
+ grid columnconfigure . 0 -uniform foo
+ grid columnconfigure . 0 -uniform
+} -cleanup {
+ grid_reset 10.20
+} -result {foo}
+test grid-10.21 {column/row configure} -body {
+ grid columnconfigure . .b -weight 1
+} -cleanup {
+ grid_reset 10.21
+} -returnCodes error -result {illegal index ".b"}
+test grid-10.22 {column/row configure} -body {
+ button .b
+ grid columnconfigure . .b -weight 1
+} -cleanup {
+ grid_reset 10.22
+} -returnCodes error -result {the window ".b" is not managed by "."}
+test grid-10.23 {column/row configure} -body {
+ button .b
+ grid .b -column 1 -columnspan 2
+ grid columnconfigure . .b -weight 1
+ set res {}
+ foreach i {0 1 2 3} {
+ lappend res [grid columnconfigure . $i -weight]
+ }
+ return $res
+} -cleanup {
+ grid_reset 10.23
+} -result {0 1 1 0}
+test grid-10.24 {column/row configure} -body {
+ button .b
+ button .c
+ button .d
+ grid .b -column 1 -columnspan 2
+ grid .c -column 2 -columnspan 3
+ grid .d -column 4 -columnspan 2
+ grid columnconfigure . {.b .d} -weight 1
+ grid columnconfigure . .c -weight 2
+ set res {}
+ foreach i {0 1 2 3 4 5 6} {
+ lappend res [grid columnconfigure . $i -weight]
+ }
+ return $res
+} -cleanup {
+ grid_reset 10.24
+} -result {0 1 2 2 2 1 0}
+test grid-10.25 {column/row configure} -body {
+ button .b
+ button .c
+ button .d
+ grid .b -row 1 -rowspan 2
+ grid .c -row 2 -rowspan 3
+ grid .d -row 4 -rowspan 2
+ grid rowconfigure . {7 all} -weight 1
+ grid rowconfigure . {1 .d} -weight 2
+ set res {}
+ foreach i {0 1 2 3 4 5 6 7} {
+ lappend res [grid rowconfigure . $i -weight]
+ }
+ return $res
+} -cleanup {
+ grid_reset 10.25
+} -result {0 2 1 1 2 2 0 1}
+test grid-10.26 {column/row configure} -body {
+ button .b
+ grid columnconfigure .b 0
+} -cleanup {
+ grid_reset 10.26
+} -result {-minsize 0 -pad 0 -uniform {} -weight 0}
+test grid-10.27 {column/row configure - no indices} -body {
+ # Bug 1422430
+ set t [toplevel .test]
+ grid columnconfigure $t "" -weight 1
+} -cleanup {
+ destroy $t
+} -returnCodes error -result {no column indices specified}
+test grid-10.28 {column/row configure - no indices} -body {
+ set t [toplevel .test]
+ grid rowconfigure $t "" -weight 1
+} -cleanup {
+ destroy $t
+} -returnCodes error -result {no row indices specified}
+test grid-10.29 {column/row configure - invalid indices} -body {
+ grid columnconfigure . {0 1 2} -weight
+} -returnCodes error -result {must specify a single element on retrieval}
+test grid-10.30 {column/row configure - invalid indices} -body {
+ grid rowconfigure . {0 1 2} -weight
+} -returnCodes error -result {must specify a single element on retrieval}
+test grid-10.31 {column/row configure - empty 'all' configure} -body {
+ # Bug 1422430
+ set t [toplevel .test]
+ grid rowconfigure $t all -weight 1
+ destroy $t
+} -result {}
+test grid-10.32 {column/row configure} -body {
+ # Test that no lingering message is there
+ frame .f
+ set res [grid columnconfigure .f all -weight 1]
+ append res [grid columnconfigure .f {0 all} -weight 1]
+ frame .f.f
+ grid .f.f
+ append res [grid columnconfigure .f {.f.f} -weight 1]
+ append res [grid columnconfigure .f {.f.f 1} -weight 1]
+ append res [grid columnconfigure .f {2 .f.f} -weight 1]
+ destroy .f
+ return $res
+} -cleanup {
+ grid_reset 10.35
+} -result {}
+test grid-10.33 {column/row configure} -body {
+ grid columnconfigure . all
+} -cleanup {
+ grid_reset 10.36
+} -returnCodes error -result {expected integer but got "all" (when retrieving options only integer indices are allowed)}
+test grid-10.34 {column/row configure} -body {
+ grid columnconfigure . 100000
+} -cleanup {
+ grid_reset 10.37
+} -result {-minsize 0 -pad 0 -uniform {} -weight 0}
+test grid-10.35 {column/row configure} -body {
+ # This is a test for bug 1423666 where a column >= 10000 caused
+ # a crash in layout. The update is needed to reach the layout stage.
+ # Test different combinations of row/column overflow
+ frame .f
+ set res {}
+ lappend res [catch {grid .f -row 10 -column 9999} msg] $msg ; update
+ lappend res [catch {grid .f -row 9999 -column 10} msg] $msg ; update
+ lappend res [catch {grid .f -columnspan 2 -column 9998} msg] $msg ; update
+ lappend res [catch {grid .f -rowspan 2 -row 9998} msg] $msg ; update
+ lappend res [catch {grid .f -column 9998 -columnspan 2} msg] $msg ; update
+ lappend res [catch {grid .f -row 9998 -rowspan 2} msg] $msg ; update
+ return $res
+} -cleanup {destroy .f} -result [lrange {
+ 1 {column out of bounds}
+ 1 {row out of bounds}
+ 1 {column out of bounds}
+ 1 {row out of bounds}
+ 1 {column out of bounds}
+ 1 {row out of bounds}
+} 0 end]
+grid_reset 10.38
+test grid-10.36 {column/row configure} -body {
+ # Additional tests for row/column overflow
+ frame .f
+ frame .g
+ set res {}
+ grid .f -row 9998 -column 0
+ lappend res [catch {grid ^ -in .} msg] $msg ; update
+ lappend res [catch {grid .g} msg] $msg ; update
+ grid forget .f .g
+ lappend res [catch {grid .f - -column 9998} msg] $msg ; update
+ grid forget .f .g
+ lappend res [catch {eval grid [string repeat " x " 9999] .f} msg] $msg
+ update
+ return $res
+} -cleanup {destroy .f .g} -result [lrange {
+ 1 {row out of bounds}
+ 1 {row out of bounds}
+ 1 {column out of bounds}
+ 1 {column out of bounds}
+} 0 end]
+grid_reset 10.39
+
+# auto-placement tests
+test grid-11.1 {default widget placement} -body {
+ grid ^
+} -cleanup {
+ grid_reset 11.1
+} -returnCodes error -result {can't use '^', cant find master}
+test grid-11.2 {default widget placement} -body {
+ button .b
+ grid .b ^
+} -cleanup {
+ grid_reset 11.2
+} -returnCodes error -result {can't find slave to extend with "^"}
+test grid-11.3 {default widget placement} -body {
+ button .b
+ grid .b - - .c
+} -cleanup {
+ grid_reset 11.3
+} -returnCodes error -result {bad window path name ".c"}
+test grid-11.4 {default widget placement} -body {
+ button .b
+ grid .b - - = -
+} -cleanup {
+ grid_reset 11.4
+} -returnCodes error -result {invalid window shortcut, "=" should be '-', 'x', or '^'}
+test grid-11.5 {default widget placement} -body {
+ button .b
+ grid .b - x -
+} -cleanup {
+ grid_reset 11.5
+} -returnCodes error -result {must specify window before shortcut '-'}
+test grid-11.6 {default widget placement} -body {
+ foreach i {1 2 3 4 5 6} {
+ frame .f$i -width 50 -height 50 -highlightthickness 0 -bg red
+ }
+ grid .f1 .f2 .f3 .f4
+ grid .f5 - x .f6 -sticky nsew
+ update
+ set a ""
+ foreach i {5 6} {
+ lappend a "[winfo x .f$i],[winfo y .f$i] \
+ [winfo width .f$i],[winfo height .f$i]"
+ }
+ return $a
+} -cleanup {
+ grid_reset 11.6
+} -result {{0,50 100,50} {150,50 50,50}}
+test grid-11.7 {default widget placement} -body {
+ frame .f -width 20 -height 20 -highlightthickness 0 -bg red
+ grid .f -row 5 -column 5
+ grid .f x -
+} -cleanup {
+ grid_reset 11.7
+} -returnCodes error -result {must specify window before shortcut '-'}
+test grid-11.8 {default widget placement} -body {
+ frame .f -width 20 -height 20 -highlightthickness 0 -bg red
+ grid .f -row 5 -column 5
+ grid .f ^ -
+} -cleanup {
+ grid_reset 11.8
+} -returnCodes error -result {must specify window before shortcut '-'}
+test grid-11.9 {default widget placement} -body {
+ frame .f -width 20 -height 20 -highlightthickness 0 -bg red
+ grid .f -row 5 -column 5
+ grid .f x ^
+} -cleanup {
+ grid_reset 11.9
+} -returnCodes error -result {can't find slave to extend with "^"}
+test grid-11.10 {default widget placement} -body {
+ foreach i {1 2 3} {
+ frame .f$i -width 100 -height 50 -highlightthickness 0 -bg red
+ }
+ grid .f1 .f2 -sticky nsew
+ grid .f3 ^ -sticky nsew
+ update
+ set a ""
+ foreach i {1 2 3} {
+ lappend a "[winfo x .f$i],[winfo y .f$i] \
+ [winfo width .f$i],[winfo height .f$i]"
+ }
+ return $a
+} -cleanup {
+ grid_reset 11.10
+} -result {{0,0 100,50} {100,0 100,100} {0,50 100,50}}
+test grid-11.11 {default widget placement} -body {
+ foreach i {1 2 3 4 5 6 7 8 9 10 11 12} {
+ frame .f$i -width 50 -height 50 -highlightthickness 1 -highlightbackground black
+ }
+ grid .f1 .f2 .f3 .f4 -sticky nsew
+ grid .f5 .f6 - .f7 -sticky nsew
+ grid .f8 ^ ^ .f9 -sticky nsew
+ grid .f10 ^ ^ .f11 -sticky nsew
+ grid .f12 - - - -sticky nsew
+ update
+ set a ""
+ foreach i {5 6 7 8 9 10 11 12 } {
+ lappend a "[winfo x .f$i],[winfo y .f$i] \
+ [winfo width .f$i],[winfo height .f$i]"
+ }
+ return $a
+} -cleanup {
+ grid_reset 11.11
+} -result {{0,50 50,50} {50,50 100,150} {150,50 50,50} {0,100 50,50} {150,100 50,50} {0,150 50,50} {150,150 50,50} {0,200 200,50}}
+test grid-11.12 {default widget placement} -body {
+ foreach i {1 2 3 4} {
+ frame .f$i -width 75 -height 50 -highlightthickness 1 -highlightbackground black
+ }
+ grid .f1 .f2 .f3 -sticky nsew
+ grid .f4 ^ -sticky nsew
+ update
+ set a ""
+ foreach i {1 2 3 4} {
+ lappend a "[winfo x .f$i],[winfo y .f$i] \
+ [winfo width .f$i],[winfo height .f$i]"
+ }
+ grid .f4 ^ -column 1
+ update
+ foreach i {1 2 3 4} {
+ lappend a "[winfo x .f$i],[winfo y .f$i] \
+ [winfo width .f$i],[winfo height .f$i]"
+ }
+ return $a
+} -cleanup {
+ grid_reset 11.12
+} -result {{0,0 75,50} {75,0 75,100} {150,0 75,50} {0,50 75,50} {0,0 75,50} {75,0 75,100} {150,0 75,100} {75,50 75,50}}
+test grid-11.13 {default widget placement} -body {
+ foreach i {1 2 3 4 5 6 7} {
+ frame .f$i -width 40 -height 50 -highlightthickness 1 -highlightbackground black
+ }
+ grid .f1 .f2 .f3 .f4 .f5 -sticky nsew
+ grid .f6 - .f7 -sticky nsew -columnspan 2
+ update
+ set a ""
+ foreach i {6 7} {
+ lappend a "[winfo x .f$i],[winfo y .f$i] \
+ [winfo width .f$i],[winfo height .f$i]"
+ }
+ return $a
+} -cleanup {
+ grid_reset 11.13
+} -result {{0,50 120,50} {120,50 80,50}}
+test grid-11.14 {default widget placement} -body {
+ foreach i {1 2 3} {
+ frame .f$i -width 60 -height 60 -highlightthickness 0 -bg red
+ }
+ grid .f1 .f2
+ grid ^ .f3
+ update
+ set a ""
+ foreach i {1 2 3} {
+ lappend a "[winfo x .f$i],[winfo y .f$i] \
+ [winfo width .f$i],[winfo height .f$i]"
+ }
+ return $a
+} -cleanup {
+ grid_reset 11.14
+} -result {{0,30 60,60} {60,0 60,60} {60,60 60,60}}
+test grid-11.15 {^ ^ test with multiple windows} -body {
+ foreach i {1 2 3 4} {
+ frame .f$i -width 50 -height 50 -bd 1 -relief solid
+ }
+ grid .f1 .f2 .f3 -sticky ns
+ grid .f4 ^ ^
+ update
+ set a ""
+ foreach i {1 2 3 4} {
+ lappend a "[winfo x .f$i],[winfo y .f$i]\
+ [winfo width .f$i],[winfo height .f$i]"
+ }
+ return $a
+} -cleanup {
+ grid_reset 11.15
+} -result {{0,0 50,50} {50,0 50,100} {100,0 50,100} {0,50 50,50}}
+test grid-11.16 {default widget placement} -body {
+ foreach l {a b c d e} {
+ frame .$l -width 50 -height 50
+ }
+ grid .a .b .c .d -sticky news
+ grid x ^ x .e -sticky news
+ update
+ set res ""
+ lappend res [winfo height .a]
+ lappend res [winfo height .b]
+ lappend res [winfo height .c]
+} -cleanup {
+ grid_reset 11.16
+} -result {50 100 50}
+test grid-11.17 {default widget placement} -body {
+ foreach l {a b c d e} {
+ frame .$l -width 50 -height 50
+ }
+ grid .a .b .c .d -sticky news
+ grid ^ x ^ .e -sticky news
+ update
+ set res ""
+ lappend res [winfo height .a]
+ lappend res [winfo height .b]
+ lappend res [winfo height .c]
+} -cleanup {
+ grid_reset 11.17
+} -result {100 50 100}
+test grid-11.18 {default widget placement} -body {
+ foreach l {a b c d e} {
+ frame .$l -width 50 -height 50
+ }
+ grid .a .b .c .d -sticky news
+ grid ^ ^ ^ x -in . ;# ^ and no child should work with -in.
+ grid rowconfigure . {0 1} -uniform a
+ update
+ set res ""
+ lappend res [winfo height .a]
+ lappend res [winfo height .b]
+ lappend res [winfo height .c]
+ lappend res [winfo height .d]
+} -cleanup {
+ grid_reset 11.18
+} -result {100 100 100 50}
+test grid-11.19 {default widget placement} -body {
+ foreach l {a b c d e} {
+ frame .$l -width 50 -height 50
+ }
+ grid .a .b -sticky news
+ grid .c .d -sticky news
+ grid ^ -in . -row 2
+ grid x ^ -in . -row 1
+ grid rowconfigure . {0 1 2} -uniform a
+ update
+ set res ""
+ lappend res [winfo height .a]
+ lappend res [winfo height .b]
+ lappend res [winfo height .c]
+ lappend res [winfo height .d]
+} -cleanup {
+ grid_reset 11.19
+} -result {50 100 100 50}
+
+test grid-12.1 {-sticky} -body {
+ catch {unset data}
+ frame .f -width 200 -height 100 -highlightthickness 0 -bg red
+ set a ""
+ grid .f
+ grid rowconfigure . 0 -weight 1
+ grid columnconfigure . 0 -weight 1
+ grid propagate . 0
+ . configure -width 250 -height 150
+ foreach i { {} n s e w ns ew nw ne se sw nse nsw sew new nsew} {
+ grid .f -sticky $i
+ update
+ array set data [grid info .f]
+ append a "($data(-sticky)) [winfo x .f] [winfo y .f] [winfo width .f] [winfo height .f]\n"
+ }
+ return $a
+} -cleanup {
+ grid_reset 12.1
+} -result {() 25 25 200 100
+(n) 25 0 200 100
+(s) 25 50 200 100
+(e) 50 25 200 100
+(w) 0 25 200 100
+(ns) 25 0 200 150
+(ew) 0 25 250 100
+(nw) 0 0 200 100
+(ne) 50 0 200 100
+(es) 50 50 200 100
+(sw) 0 50 200 100
+(nes) 50 0 200 150
+(nsw) 0 0 200 150
+(esw) 0 50 250 100
+(new) 0 0 250 100
+(nesw) 0 0 250 150
+}
+test grid-12.2 {-sticky} -body {
+ frame .f -bg red
+ grid .f -sticky glue
+} -cleanup {
+ grid_reset 12.2
+} -returnCodes error -result {bad stickyness value "glue": must be a string containing n, e, s, and/or w}
+test grid-12.3 {-sticky} -body {
+ frame .f -bg red
+ grid .f -sticky {n,s,e,w}
+ array set A [grid info .f]
+ set A(-sticky)
+} -cleanup {
+ grid_reset 12.3
+} -result {nesw}
+
+test grid-13.1 {-in} -body {
+ frame .f -bg red
+ grid .f -in .f
+} -cleanup {
+ grid_reset 13.1
+} -returnCodes error -result {window can't be managed in itself}
+test grid-13.2 {-in} -body {
+ frame .f -bg red
+ list [winfo manager .f] \
+ [catch {grid .f -in .f} err] $err \
+ [winfo manager .f]
+} -cleanup {
+ grid_reset 13.1.1
+} -result {{} 1 {window can't be managed in itself} {}}
+test grid-13.3 {-in} -body {
+ frame .f -bg red
+ grid .f -in .bad
+} -cleanup {
+ grid_reset 13.2
+} -returnCodes error -result {bad window path name ".bad"}
+test grid-13.4 {-in} -body {
+ frame .f -bg red
+ toplevel .top
+ grid .f -in .top
+} -cleanup {
+ grid_reset 13.3
+} -returnCodes error -result {can't put .f inside .top}
+destroy .top
+test grid-13.5 {-ipadx} -body {
+ frame .f -width 20 -height 20 -highlightthickness 0 -bg red
+ grid .f -ipadx x
+} -cleanup {
+ grid_reset 13.4
+} -returnCodes error -result {bad ipadx value "x": must be positive screen distance}
+test grid-13.6 {-ipadx} -body {
+ frame .f -width 20 -height 20 -highlightthickness 0 -bg red
+ grid .f -ipadx {5 5}
+} -cleanup {
+ grid_reset 13.4.1
+} -returnCodes error -result {bad ipadx value "5 5": must be positive screen distance}
+test grid-13.7 {-ipadx} -body {
+ frame .f -width 200 -height 100 -highlightthickness 0 -bg red
+ grid .f
+ update
+ set a [winfo width .f]
+ grid .f -ipadx 1
+ update
+ list $a [winfo width .f]
+} -cleanup {
+ grid_reset 13.5
+} -result {200 202}
+test grid-13.8 {-ipady} -body {
+ frame .f -width 20 -height 20 -highlightthickness 0 -bg red
+ grid .f -ipady x
+} -cleanup {
+ grid_reset 13.6
+} -returnCodes error -result {bad ipady value "x": must be positive screen distance}
+test grid-13.9 {-ipady} -body {
+ frame .f -width 20 -height 20 -highlightthickness 0 -bg red
+ grid .f -ipady {5 5}
+} -cleanup {
+ grid_reset 13.6.1
+} -returnCodes error -result {bad ipady value "5 5": must be positive screen distance}
+test grid-13.10 {-ipady} -body {
+ frame .f -width 200 -height 100 -highlightthickness 0 -bg red
+ grid .f
+ update
+ set a [winfo height .f]
+ grid .f -ipady 1
+ update
+ list $a [winfo height .f]
+} -cleanup {
+ grid_reset 13.7
+} -result {100 102}
+test grid-13.11 {-padx} -body {
+ frame .f -width 20 -height 20 -highlightthickness 0 -bg red
+ grid .f -padx x
+} -cleanup {
+ grid_reset 13.8
+} -returnCodes error -result {bad pad value "x": must be positive screen distance}
+test grid-13.12 {-padx} -body {
+ frame .f -width 20 -height 20 -highlightthickness 0 -bg red
+ grid .f -padx {10 x}
+} -cleanup {
+ grid_reset 13.8.1
+} -returnCodes error -result {bad 2nd pad value "x": must be positive screen distance}
+test grid-13.13 {-padx} -body {
+ frame .f -width 200 -height 100 -highlightthickness 0 -bg red
+ grid .f
+ update
+ set a "[winfo width .f] [winfo width .]"
+ grid .f -padx 1
+ update
+ list $a "[winfo width .f] [winfo width .] [winfo x .f]"
+} -cleanup {
+ grid_reset 13.9
+} -result {{200 200} {200 202 1}}
+test grid-13.14 {-padx} -body {
+ frame .f -width 200 -height 100 -highlightthickness 0 -bg red
+ grid .f
+ update
+ set a "[winfo width .f] [winfo width .]"
+ grid .f -padx {10 5}
+ update
+ list $a "[winfo width .f] [winfo width .] [winfo x .f]"
+} -cleanup {
+ grid_reset 13.9.1
+} -result {{200 200} {200 215 10}}
+test grid-13.15 {-pady} -body {
+ frame .f -width 20 -height 20 -highlightthickness 0 -bg red
+ grid .f -pady x
+} -cleanup {
+ grid_reset 13.10
+} -returnCodes error -result {bad pad value "x": must be positive screen distance}
+test grid-13.16 {-pady} -body {
+ frame .f -width 20 -height 20 -highlightthickness 0 -bg red
+ grid .f -pady {10 x}
+} -cleanup {
+ grid_reset 13.10.1
+} -returnCodes error -result {bad 2nd pad value "x": must be positive screen distance}
+test grid-13.17 {-pady} -body {
+ frame .f -width 200 -height 100 -highlightthickness 0 -bg red
+ grid .f
+ update
+ set a "[winfo height .f] [winfo height .]"
+ grid .f -pady 1
+ update
+ list $a "[winfo height .f] [winfo height .] [winfo y .f]"
+} -cleanup {
+ grid_reset 13.11
+} -result {{100 100} {100 102 1}}
+test grid-13.18 {-pady} -body {
+ frame .f -width 200 -height 100 -highlightthickness 0 -bg red
+ grid .f
+ update
+ set a "[winfo height .f] [winfo height .]"
+ grid .f -pady {4 16}
+ update
+ list $a "[winfo height .f] [winfo height .] [winfo y .f]"
+} -cleanup {
+ grid_reset 13.11.1
+} -result {{100 100} {100 120 4}}
+test grid-13.19 {-ipad x and y} -body {
+ frame .f -width 20 -height 20 -highlightthickness 0 -bg red
+ grid columnconfigure . 0 -minsize 150
+ grid rowconfigure . 0 -minsize 100
+ set a ""
+ foreach x {0 5} {
+ foreach y {0 5} {
+ grid .f -ipadx $x -ipady $y
+ update
+ append a " $x,$y:"
+ foreach prop {x y width height} {
+ append a ,[winfo $prop .f]
+ }
+ }
+ }
+ return $a
+} -cleanup {
+ grid_reset 13.12
+} -result { 0,0:,65,40,20,20 0,5:,65,35,20,30 5,0:,60,40,30,20 5,5:,60,35,30,30}
+test grid-13.20 {reparenting} -body {
+ frame .1
+ frame .2
+ button .b
+ grid .1 .2
+ grid .b -in .1
+ set a ""
+ catch {unset info}; array set info [grid info .b]
+ lappend a [grid slaves .1],[grid slaves .2],$info(-in)
+ grid .b -in .2
+ catch {unset info}; array set info [grid info .b]
+ lappend a [grid slaves .1],[grid slaves .2],$info(-in)
+ unset info
+ return $a
+} -cleanup {
+ grid_reset 13.13
+} -result {.b,,.1 ,.b,.2}
+
+test grid-14.1 {structure notify} -body {
+ frame .f -width 200 -height 100 -highlightthickness 0 -bg red
+ frame .g -width 200 -height 100 -highlightthickness 0 -bg red
+ grid .f
+ grid .g -in .f
+ update
+ set a ""
+ lappend a "[winfo x .g],[winfo y .g] \
+ [winfo width .g],[winfo height .g]"
+ .f configure -bd 5 -relief raised
+ update
+ lappend a "[winfo x .g],[winfo y .g] \
+ [winfo width .g],[winfo height .g]"
+ return $a
+} -cleanup {
+ grid_reset 14.1
+} -result {{0,0 200,100} {5,5 200,100}}
+test grid-14.2 {structure notify} -body {
+ frame .f -width 200 -height 100
+ frame .f.g -width 200 -height 100
+ grid .f
+ grid .f.g
+ update
+ set a ""
+ lappend a [grid bbox .],[grid bbox .f]
+ .f config -bd 20
+ update
+ lappend a [grid bbox .],[grid bbox .f]
+} -cleanup {
+ grid_reset 14.2
+} -result {{0 0 200 100,0 0 200 100} {0 0 240 140,20 20 200 100}}
+test grid-14.3 {map notify: bug 1648} -constraints {nonPortable} -body {
+ # This test is nonPortable because the number of times
+ # A(.) will be incremented is unspecified--the behavior
+ # is different accross window managers.
+ global A
+ catch {unset A}
+ bind . <Configure> {incr A(%W)}
+ set A(.) 0
+ foreach i {0 1 2} {
+ frame .$i -width 100 -height 75
+ set A(.$i) 0
+ }
+ grid .0 .1 .2
+ update
+ bind <Configure> .1 {destroy .0}
+ .2 configure -bd 10
+ update
+ bind . <Configure> {}
+ array get A
+} -cleanup {
+ grid_reset 14.3
+} -result {.2 2 .0 1 . 2 .1 1}
+
+test grid-15.1 {lost slave} -body {
+ button .b
+ grid .b
+ set a [grid slaves .]
+ pack .b
+ lappend a [grid slaves .]
+ grid .b
+ lappend a [grid slaves .]
+} -cleanup {
+ grid_reset 15.1
+} -result {.b {} .b}
+test grid-15.2 {lost slave} -body {
+ frame .f
+ grid .f
+ button .b
+ grid .b -in .f
+ set a [grid slaves .f]
+ pack .b -in .f
+ lappend a [grid slaves .f]
+ grid .b -in .f
+ lappend a [grid slaves .f]
+} -cleanup {
+ grid_reset 15.2
+} -result {.b {} .b}
+
+test grid-16.1 {layout centering} -body {
+ foreach i {0 1 2} {
+ frame .$i -bg gray -width 75 -height 50 -bd 2 -relief ridge
+ grid .$i -row $i -column $i -sticky nswe
+ }
+ grid propagate . 0
+ grid anchor . center
+ . configure -width 300 -height 250
+ update
+ grid bbox .
+} -cleanup {
+ grid_reset 16.1
+} -result {37 50 225 150}
+test grid-16.2 {layout weights (expanding)} -body {
+ foreach i {0 1 2} {
+ frame .$i -bg gray -width 75 -height 50 -bd 2 -relief ridge
+ grid .$i -row $i -column $i -sticky nswe
+ grid rowconfigure . $i -weight [expr $i + 1]
+ grid columnconfigure . $i -weight [expr $i + 1]
+ }
+ grid propagate . 0
+ . configure -width 500 -height 300
+ set a ""
+ update
+ foreach i {0 1 2} {
+ lappend a [winfo width .$i]-[winfo height .$i]
+ }
+ return $a
+} -cleanup {
+ grid_reset 16.2
+} -result {120-75 167-100 213-125}
+test grid-16.3 {layout weights (shrinking)} -body {
+ foreach i {0 1 2} {
+ frame .$i -bg gray -width 100 -height 75 -bd 2 -relief ridge
+ grid .$i -row $i -column $i -sticky nswe
+ grid rowconfigure . $i -weight [expr $i + 1]
+ grid columnconfigure . $i -weight [expr $i + 1]
+ }
+ grid propagate . 0
+ . configure -width 200 -height 150
+ set a ""
+ update
+ foreach i {0 1 2} {
+ lappend a [winfo width .$i]-[winfo height .$i]
+ }
+ return $a
+} -cleanup {
+ grid_reset 16.3
+} -result {84-63 66-50 50-37}
+test grid-16.4 {layout weights (shrinking with minsize)} -body {
+ foreach i {0 1 2} {
+ frame .$i -bg gray -width 100 -height 75 -bd 2 -relief ridge
+ grid .$i -row $i -column $i -sticky nswe
+ grid rowconfigure . $i -weight [expr $i + 1] -minsize 45
+ grid columnconfigure . $i -weight [expr $i + 1] -minsize 65
+ }
+ grid propagate . 0
+ . configure -width 200 -height 150
+ set a ""
+ update
+ foreach i {0 1 2} {
+ lappend a [winfo width .$i]-[winfo height .$i]
+ }
+ return $a
+} -cleanup {
+ grid_reset 16.4
+} -result {70-60 65-45 65-45}
+test grid-16.5 {layout weights (shrinking at minsize)} -body {
+ foreach i {0 1 2} {
+ frame .$i -bg gray -width 100 -height 75 -bd 2 -relief ridge
+ grid .$i -row $i -column $i -sticky nswe
+ grid rowconfigure . $i -weight 0 -minsize 70
+ grid columnconfigure . $i -weight 0 -minsize 90
+ }
+ grid propagate . 0
+ . configure -width 100 -height 75
+ set a ""
+ update
+ foreach i {0 1 2} {
+ lappend a [winfo width .$i]-[winfo height .$i]
+ }
+ return $a
+} -cleanup {
+ grid_reset 16.5
+} -result {100-75 100-75 100-75}
+test grid-16.6 {layout weights (shrinking at minsize)} -body {
+ foreach i {0 1 2} {
+ frame .$i -bg gray -width 100 -height 75 -bd 2 -relief ridge
+ grid .$i -row $i -column $i -sticky nswe
+ grid rowconfigure . $i -weight [expr $i + 1] -minsize 52
+ grid columnconfigure . $i -weight [expr $i + 1] -minsize 69
+ }
+ grid propagate . 0
+ . configure -width 200 -height 150
+ set a ""
+ update
+ foreach i {0 1 2} {
+ lappend a [winfo width .$i]-[winfo height .$i]
+ }
+ return $a
+} -cleanup {
+ grid_reset 16.6
+} -result {69-52 69-52 69-52}
+# test fails when run alone
+# reason (I think): -minsize 0 causes both:
+# [winfo ismapped .$i] => 0 and
+# not responding for width ang height settings, so that
+# [winfo width .$i] [winfo height .$i] take different values
+# That doesn't happen if previous tests run
+test grid-16.7 {layout weights (shrinking at minsize)} -body {
+ foreach i {0 1 2} {
+ frame .$i -bg gray -width 100 -height 75 -bd 2 -relief ridge
+ grid .$i -row $i -column $i -sticky nswe
+ }
+ grid propagate . 0
+ grid columnconfigure . 1 -weight 1 -minsize 0
+ grid rowconfigure . 1 -weight 1 -minsize 0
+ . configure -width 100 -height 1
+ set a ""
+ update
+ foreach i {0 1 2} {
+ lappend a [winfo width .$i]-[winfo height .$i]-[winfo ismapped .$i]
+ }
+ return $a
+} -cleanup {
+ grid_reset 16.7
+} -result {100-75-1 1-1-0 100-75-1}
+test grid-16.8 {layout internal constraints} -body {
+ foreach i {0 1 2 3 4} {
+ frame .$i -bg gray -width 30 -height 25 -bd 2 -relief ridge
+ grid .$i -row $i -column $i -sticky nswe
+ }
+ frame .f -bg red -width 250 -height 200
+ frame .g -bg green -width 200 -height 180
+ lower .f
+ raise .g .f
+ grid .f -row 1 -column 1 -rowspan 3 -columnspan 3 -sticky nswe
+ grid .g -row 1 -column 1 -rowspan 2 -columnspan 2 -sticky nswe
+ update
+ set a ""
+ foreach i {0 1 2 3 4} {
+ append a "[winfo x .$i] "
+ }
+ append a ", "
+ grid remove .f
+ update
+ foreach i {0 1 2 3 4} {
+ append a "[winfo x .$i] "
+ }
+ append a ", "
+ grid remove .g
+ grid .f
+ update
+ foreach i {0 1 2 3 4} {
+ append a "[winfo x .$i] "
+ }
+ append a ", "
+ grid remove .f
+ update
+ foreach i {0 1 2 3 4} {
+ append a "[winfo x .$i] "
+ }
+ return $a
+} -cleanup {
+ grid_reset 16.8
+} -result {0 30 130 230 280 , 0 30 130 230 260 , 0 30 113 196 280 , 0 30 60 90 120 }
+test grid-16.9 {layout uniform} -body {
+ frame .f1 -width 75 -height 50
+ frame .f2 -width 60 -height 25
+ frame .f3 -width 95 -height 75
+ frame .f4 -width 135 -height 100
+ frame .f5 -width 80 -height 40
+ for {set t 1} {$t <= 5} {incr t} {
+ grid .f$t
+ }
+ grid rowconfigure . {0 2} -uniform a
+ grid rowconfigure . {1 3} -uniform b
+ update
+ list [grid bbox . 0 0] [grid bbox . 0 1] [grid bbox . 0 2] \
+ [grid bbox . 0 3] [grid bbox . 0 4]
+} -cleanup {
+ grid_reset 16.9
+} -result {{0 0 135 75} {0 75 135 100} {0 175 135 75} {0 250 135 100} {0 350 135 40}}
+test grid-16.10 {layout uniform} -body {
+ grid [frame .f1 -width 75 -height 50] -row 0 -column 0
+ grid [frame .f2 -width 60 -height 30] -row 1 -column 2
+ grid [frame .f3 -width 95 -height 90] -row 2 -column 1
+ grid [frame .f4 -width 60 -height 100] -row 3 -column 4
+ grid [frame .f5 -width 60 -height 40] -row 4 -column 3
+ grid rowconfigure . {0 1} -uniform a
+ grid rowconfigure . {2 4} -uniform b
+ grid rowconfigure . {0 2} -weight 2
+ grid columnconfigure . {0 2} -uniform a
+ grid columnconfigure . {3 4} -uniform b
+ grid columnconfigure . {2 4} -weight 2
+ grid columnconfigure . 3 -minsize 70
+ grid columnconfigure . 4 -minsize 130
+ update
+ list [grid bbox . 0 0] [grid bbox . 2 1] [grid bbox . 1 2] \
+ [grid bbox . 4 3] [grid bbox . 3 4]
+} -cleanup {
+ grid_reset 16.10
+} -result {{0 0 75 60} {170 60 150 30} {75 90 95 90} {390 180 140 100} {320 280 70 45}}
+test grid-16.11 {layout uniform (shrink)} -body {
+ frame .f1 -width 75 -height 50
+ frame .f2 -width 100 -height 95
+ grid .f1 .f2 -sticky news
+ grid columnconfigure . {0 1} -uniform a
+ grid columnconfigure . 0 -weight 1
+ update
+ set res {}
+ lappend res [grid bbox . 0 0] [grid bbox . 1 0]
+ grid propagate . 0
+ . configure -width 150 -height 95
+ update
+ lappend res [grid bbox . 0 0] [grid bbox . 1 0]
+} -cleanup {
+ grid_reset 16.11
+} -result {{0 0 100 95} {100 0 100 95} {0 0 50 95} {50 0 100 95}}
+test grid-16.12 {layout uniform (grow)} -body {
+ frame .f1 -width 40 -height 50
+ frame .f2 -width 50 -height 95
+ frame .f3 -width 60 -height 50
+ frame .f4 -width 70 -height 95
+ grid .f1 .f2 .f3 .f4 -sticky news
+ grid columnconfigure . {0 1 2} -uniform a
+ # Put weight 2 on the biggest in the group to see that the groups
+ # adapt to one of the smaller.
+ grid columnconfigure . 2 -weight 2
+ grid columnconfigure . {0 3} -weight 1
+ update
+ set res {}
+ lappend res [grid bbox . 0 0] [grid bbox . 1 0]
+ lappend res [grid bbox . 2 0] [grid bbox . 3 0]
+ grid propagate . 0
+ . configure -width 350 -height 95
+ update
+ lappend res [grid bbox . 0 0] [grid bbox . 1 0]
+ lappend res [grid bbox . 2 0] [grid bbox . 3 0]
+} -cleanup {
+ grid_reset 16.12
+} -result [list {0 0 50 95} {50 0 50 95} {100 0 100 95} {200 0 70 95} \
+ {0 0 70 95} {70 0 50 95} {120 0 140 95} {260 0 90 95}]
+test grid-16.13 {layout span} -body {
+ frame .f1 -width 24 -height 20
+ frame .f2 -width 38 -height 20
+ frame .f3 -width 150 -height 20
+ grid .f1 - - .f2
+ grid .f3 - - -
+ set res {}
+ foreach w {{0 1 0 0} {0 0 1 0} {1 3 4 0} {1 2 1 2} {1 1 1 12}} {
+ for {set c 0} {$c < 4} {incr c} {
+ grid columnconfigure . $c -weight [lindex $w $c]
+ }
+ update
+ set res2 {}
+ for {set c 0} {$c <= 4} {incr c} {
+ lappend res2 [lindex [grid bbox . $c 0] 2]
+ }
+ lappend res $res2
+ }
+ return $res
+ # The last result below should ideally be 8 8 8 126 but the current
+ # implementation is not exact enough.
+} -cleanup {
+ grid_reset 16.13
+} -result [list [list 0 112 0 38 0] [list 0 0 112 38 0] [list 14 42 56 38 0] \
+ [list 18 38 18 76 0] [list 7 8 9 126 0]]
+test grid-16.14 {layout span} -body {
+ frame .f1 -width 110 -height 20
+ frame .f2 -width 38 -height 20
+ frame .f3 -width 150 -height 20
+ grid .f1 - - .f2
+ grid .f3 - - -
+ set res {}
+ foreach w {{0 1 0 0} {0 0 1 0} {1 3 4 0} {1 2 1 3} {1 1 1 12}} {
+ for {set c 0} {$c < 4} {incr c} {
+ grid columnconfigure . $c -weight [lindex $w $c]
+ }
+ update
+ set res2 {}
+ for {set c 0} {$c <= 4} {incr c} {
+ lappend res2 [lindex [grid bbox . $c 0] 2]
+ }
+ lappend res $res2
+ }
+ return $res
+} -cleanup {
+ grid_reset 16.14
+} -result [list [list 0 112 0 38 0] [list 0 0 112 38 0] [list 14 42 56 38 0] \
+ [list 27 55 28 40 0] [list 36 37 37 40 0]]
+test grid-16.15 {layout span} -body {
+ frame .f1 -width 24 -height 20
+ frame .f2 -width 38 -height 20
+ frame .f3 -width 150 -height 20
+ grid .f1 - - .f2
+ grid x .f3 - -
+ set res {}
+ foreach w {{0 1 0 0} {0 0 1 0} {1 0 1 0} {0 0 0 0} {1 0 0 6}} {
+ for {set c 0} {$c < 4} {incr c} {
+ grid columnconfigure . $c -weight [lindex $w $c]
+ }
+ update
+ set res2 {}
+ for {set c 0} {$c <= 4} {incr c} {
+ lappend res2 [lindex [grid bbox . $c 0] 2]
+ }
+ lappend res $res2
+ }
+ return $res
+} -cleanup {
+ grid_reset 16.15
+} -result [list [list 0 112 0 38 0] [list 0 0 112 38 0] [list 0 0 112 38 0] \
+ [list 0 37 37 76 0] [list 0 12 12 126 0]]
+test grid-16.16 {layout span} -body {
+ frame .f1 -width 64 -height 20
+ frame .f2 -width 38 -height 20
+ frame .f3 -width 150 -height 20
+ frame .f4 -width 15 -height 20
+ frame .f5 -width 18 -height 20
+ frame .f6 -width 20 -height 20
+ grid .f1 - x .f2
+ grid .f3 - - -
+ grid .f4 .f5 .f6
+ set res {}
+ foreach w {{1 1 5 1} {0 0 1 0} {1 3 4 0} {1 2 1 2} {1 1 1 12}} {
+ for {set c 0} {$c < 4} {incr c} {
+ grid columnconfigure . $c -weight [lindex $w $c]
+ }
+ update
+ set res2 {}
+ for {set c 0} {$c <= 4} {incr c} {
+ lappend res2 [lindex [grid bbox . $c 0] 2]
+ }
+ lappend res $res2
+ }
+ return $res
+} -cleanup {
+ grid_reset 16.16
+} -result [list [list 30 34 43 43 0] [list 30 34 48 38 0] [list 22 42 48 38 0] \
+ [list 25 39 29 57 0] [list 30 34 22 64 0]]
+test grid-16.17 {layout weights (shrinking at minsize)} -body {
+ foreach i {0 1 2 3} {
+ frame .$i -bg gray -width 100 -height 75 -bd 2 -relief ridge
+ grid .$i -row $i -column $i -sticky nswe
+ }
+ grid propagate . 0
+ grid columnconfigure . {0 1} -weight 1 -minsize 0
+ grid rowconfigure . {0 1} -weight 1 -minsize 0
+ set a ""
+ . configure -width 250 -height 200
+ update
+ foreach i {0 1 2 3} {
+ lappend a [winfo width .$i]-[winfo height .$i]-[winfo ismapped .$i]
+ }
+ . configure -width 150 -height 100
+ update
+ foreach i {0 1 2 3} {
+ lappend a [winfo width .$i]-[winfo height .$i]-[winfo ismapped .$i]
+ }
+ return $a
+} -cleanup {
+ grid_reset 16.17
+} -result {25-25-1 25-25-1 100-75-1 100-75-1 25-25-0 25-25-0 100-75-1 100-75-1}
+test grid-16.18 {layout span} -body {
+ frame .f1 -width 30 -height 20
+ frame .f2 -width 166 -height 20
+ frame .f3 -width 39 -height 20
+ frame .f4 -width 10 -height 20
+ grid .f1 .f3 -
+ grid .f2 - .f4
+ grid columnconfigure . 0 -weight 1
+ set res {}
+ foreach w {{1 0 0} {0 1 0} {0 0 1}} {
+ for {set c 0} {$c < 3} {incr c} {
+ grid columnconfigure . $c -weight [lindex $w $c]
+ }
+ update
+ set res2 {}
+ for {set c 0} {$c <= 2} {incr c} {
+ lappend res2 [lindex [grid bbox . $c 0] 2]
+ }
+ lappend res $res2
+ }
+ return $res
+} -cleanup {
+ grid_reset 16.18
+} -result [list [list 137 29 10] [list 30 136 10] [list 98 68 10]]
+test grid-16.19 {layout span} -constraints { knownBug } -body {
+ # This test shows the problem in Bug 2075285
+ # Several overlapping multi-span widgets is a weak spot
+ # in the current implementation.
+ # Test present as a reminder in case a future algorithm update is made.
+ frame .f1 -width 100 -height 20
+ frame .f2 -width 20 -height 20
+ frame .f3 -width 10 -height 20
+ frame .f4 -width 20 -height 20
+ grid .f1 - - - - - -sticky we
+ grid .f2 - .f3 - .f4 - -sticky we
+ grid columnconfigure . {1 5} -weight 1
+ set res {}
+ update
+ for {set c 0} {$c <= 5} {incr c} {
+ lappend res [lindex [grid bbox . $c 0] 2]
+ }
+ return $res
+} -cleanup {
+ grid_reset 16.19
+} -result [list 0 45 5 5 0 45]
+
+test grid-17.1 {forget and pending idle handlers} -body {
+ # This test is intended to detect a crash caused by a failure to remove
+ # pending idle handlers when grid forget is invoked.
+ toplevel .t
+ wm geometry .t +0+0
+ frame .t.f
+ label .t.f.l -text foobar
+ grid .t.f.l
+ grid .t.f
+ update
+ grid forget .t.f.l
+ grid forget .t.f
+ destroy .t
+ toplevel .t
+ frame .t.f
+ label .t.f.l -text foobar
+ grid .t.f.l
+ destroy .t
+ set result ok
+} -result ok
+
+
+test grid-18.1 {test respect for internalborder} -body {
+ toplevel .pack
+ wm geometry .pack 200x200
+ frame .pack.l -width 15 -height 10
+ labelframe .pack.lf -labelwidget .pack.l
+ pack .pack.lf -fill both -expand 1
+ frame .pack.lf.f
+ grid .pack.lf.f -sticky news
+ grid columnconfigure .pack.lf 0 -weight 1
+ grid rowconfigure .pack.lf 0 -weight 1
+ update
+ set res [list [winfo geometry .pack.lf.f]]
+ .pack.lf configure -labelanchor e -padx 3 -pady 5
+ update
+ lappend res [winfo geometry .pack.lf.f]
+ destroy .pack
+ return $res
+} -result {196x188+2+10 177x186+5+7}
+test grid-18.2 {test support for minreqsize} -body {
+ toplevel .pack
+ wm geometry .pack {}
+ frame .pack.l -width 150 -height 100
+ labelframe .pack.lf -labelwidget .pack.l
+ pack .pack.lf -fill both -expand 1
+ frame .pack.lf.f -width 20 -height 25
+ grid .pack.lf.f
+ update
+ set res [list [winfo geometry .pack.lf]]
+ .pack.lf configure -labelanchor ws
+ update
+ lappend res [winfo geometry .pack.lf]
+ destroy .pack
+ return $res
+} -result {162x127+0+0 172x112+0+0}
+
+test grid-19.1 {uniform realloc} -body {
+ # Use a lot of uniform groups to test the reallocation mechanism
+ for {set t 0} {$t < 100} {incr t 2} {
+ frame .fa$t -width 5 -height 20
+ frame .fb$t -width 6 -height 20
+ grid .fa$t .fb$t -row 0 -column $t -sticky news
+ grid columnconfigure . [list $t [expr {$t + 1}]] -uniform a$t
+ }
+ update
+ grid bbox .
+} -cleanup {
+ grid_reset 19.1
+} -result {0 0 600 20}
+
+test grid-20.1 {recalculate size after removal (destroy)} -body {
+ label .l1 -text l1
+ grid .l1 -row 2 -column 2
+ destroy .l1
+ label .l2 -text l2
+ grid .l2
+ grid size .
+} -cleanup {
+ grid_reset 20.1
+} -result {1 1}
+test grid-20.2 {recalculate size after removal (forget)} -body {
+ label .l1 -text l1
+ grid .l1 -row 2 -column 2
+ grid forget .l1
+ label .l2 -text l2
+ grid .l2
+ grid size .
+} -cleanup {
+ grid_reset 20.2
+} -result {1 1}
+
+test grid-21.1 {anchor} -body {
+ grid anchor . 1 xxx
+} -cleanup {
+ grid_reset 21.1
+} -returnCodes error -result {wrong # args: should be "grid anchor window ?anchor?"}
+test grid-21.2 {anchor} -body {
+ grid anchor .
+} -cleanup {
+ grid_reset 21.2
+} -result {nw}
+test grid-21.3 {anchor} -body {
+ grid anchor . se;grid anchor .
+} -cleanup {
+ grid_reset 21.3
+} -result {se}
+test grid-21.4 {anchor} -body {
+ grid anchor .x
+} -cleanup {
+ grid_reset 21.4
+} -returnCodes error -result {bad window path name ".x"}
+test grid-21.5 {anchor} -body {
+ grid anchor . x
+} -cleanup {
+ grid_reset 21.5
+} -returnCodes error -result {bad anchor "x": must be n, ne, e, se, s, sw, w, nw, or center}
+test grid-21.6 {anchor} -body {
+ foreach i {0 1 2} {
+ frame .$i -bg gray -width 75 -height 50 -bd 2 -relief ridge
+ grid .$i -row $i -column $i -sticky nswe
+ }
+ grid propagate . 0
+ . configure -width 300 -height 250
+ set res {}
+ foreach a {n ne e se s sw w nw center} {
+ grid anchor . $a
+ update
+ lappend res [grid bbox .]
+ }
+ return $res
+} -cleanup {
+ grid_reset 21.6
+} -result [list {37 0 225 150} {75 0 225 150} {75 50 225 150} {75 100 225 150} \
+ {37 100 225 150} {0 100 225 150} {0 50 225 150} {0 0 225 150} \
+ {37 50 225 150}]
+test grid-21.7 {anchor} -body {
+ # Test with a non-symmetric internal border.
+ # This only tests vertically, there is currently no way to get
+ # it assymetric horizontally.
+ labelframe .f -bd 0
+ frame .f.x -width 20 -height 20
+ .f configure -labelwidget .f.x
+ pack .f -fill both -expand 1
+ foreach i {0 1 2} {
+ frame .$i -bg gray -width 75 -height 50 -bd 2 -relief ridge
+ grid .$i -in .f -row $i -column $i -sticky nswe
+ }
+ pack propagate . 0
+ grid propagate .f 0
+ . configure -width 300 -height 250
+ set res {}
+ foreach a {n ne e se s sw w nw center} {
+ grid anchor .f $a
+ update
+ lappend res [grid bbox .f]
+ }
+ pack propagate . 1 ; wm geometry . {}
+ return $res
+} -cleanup {
+ grid_reset 21.7
+} -result [list {37 20 225 150} {75 20 225 150} {75 60 225 150} {75 100 225 150} \
+ {37 100 225 150} {0 100 225 150} {0 60 225 150} {0 20 225 150} \
+ {37 60 225 150}]
+
+test grid-22.1 {remove: basic argument checking} {
+ list [catch {grid remove foo} msg] $msg
+} {1 {bad window path name "foo"}}
+test grid-22.2 {remove} {
+ button .c
+ grid [button .b]
+ set a [grid slaves .]
+ grid remove .b .c
+ lappend a [grid slaves .]
+ return $a
+} {.b {}}
+grid_reset 22.2
+test grid-22.3 {remove} {
+ button .c
+ grid .c -row 2 -column 2 -rowspan 2 -columnspan 2 -padx 3 -pady 4 -sticky ns
+ grid remove .c
+ grid .c -row 0 -column 0
+ grid info .c
+} {-in . -column 0 -row 0 -columnspan 2 -rowspan 2 -ipadx 0 -ipady 0 -padx 3 -pady 4 -sticky ns}
+grid_reset 22.3
+test grid-22.3.1 {remove} {
+ frame .a
+ button .c
+ grid .c -in .a -row 2 -column 2 -rowspan 2 -columnspan 2 -padx {3 5} -pady {4 7} -sticky ns
+ grid remove .c
+ grid .c -row 0 -column 0
+ grid info .c
+} {-in .a -column 0 -row 0 -columnspan 2 -rowspan 2 -ipadx 0 -ipady 0 -padx {3 5} -pady {4 7} -sticky ns}
+grid_reset 22.3.1
+test grid-22.4 {remove, calling Tk_UnmaintainGeometry} {
+ frame .f -bd 2 -relief raised
+ place .f -x 10 -y 20 -width 200 -height 100
+ frame .f2 -width 50 -height 30 -bg red
+ grid .f2 -in .f
+ update
+ set x [winfo ismapped .f2]
+ grid remove .f2
+ place .f -x 30
+ update
+ lappend x [winfo ismapped .f2]
+} {1 0}
+grid_reset 22.4
+test grid-22.5 {remove} {
+ frame .a
+ button .c
+ grid .c -in .a -row 2 -column 2 -rowspan 2 -columnspan 2 -padx {3 5} -pady {4 7} -sticky ns
+ grid remove .c
+ # If .a was destroyed while remembered by the removed .c, make sure it
+ # is ignored.
+ destroy .a
+ grid .c -row 0 -column 0
+ grid info .c
+} {-in . -column 0 -row 0 -columnspan 2 -rowspan 2 -ipadx 0 -ipady 0 -padx {3 5} -pady {4 7} -sticky ns}
+grid_reset 22.5
+
+test grid-23 {grid configure -in leaked from previous master - bug
+ 6aea69fccbb266b7f0437686379fbe5b55442958} {
+ frame .f
+ frame .g
+ pack .f .g
+ text .t
+ grid .t -in .f
+ pack forget .f
+ update
+ grid .t -in .g
+ # .t is now managed by .g; following lines must have no effect on .t
+ pack .f
+ update
+ pack forget .f
+ update
+ winfo ismapped .t ; # must return 1
+} {1}
+grid_reset 23
+
+# cleanup
+cleanupTests
+return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tk8.6/tests/iDOT.png b/tk8.6/tests/iDOT.png
new file mode 100644
index 0000000..e8cd024
--- /dev/null
+++ b/tk8.6/tests/iDOT.png
Binary files differ
diff --git a/tk8.6/tests/image.test b/tk8.6/tests/image.test
new file mode 100644
index 0000000..5842ce3
--- /dev/null
+++ b/tk8.6/tests/image.test
@@ -0,0 +1,655 @@
+# This file is a Tcl script to test out the "image" command and the
+# other procedures in the file tkImage.c. It is organized in the
+# standard fashion for Tcl tests.
+#
+# Copyright (c) 1994 The Regents of the University of California.
+# Copyright (c) 1994 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+
+imageInit
+
+# Canvas used in some tests in the whole file
+canvas .c -highlightthickness 2
+pack .c
+update
+
+
+test image-1.1 {Tk_ImageCmd procedure, "create" option} -body {
+ image
+} -returnCodes error -result {wrong # args: should be "image option ?args?"}
+test image-1.2 {Tk_ImageCmd procedure, "create" option} -body {
+ image gorp
+} -returnCodes error -result {bad option "gorp": must be create, delete, height, inuse, names, type, types, or width}
+test image-1.3 {Tk_ImageCmd procedure, "create" option} -body {
+ image create
+} -returnCodes error -result {wrong # args: should be "image create type ?name? ?-option value ...?"}
+test image-1.4 {Tk_ImageCmd procedure, "create" option} -body {
+ image c bad_type
+} -returnCodes error -result {image type "bad_type" doesn't exist}
+test image-1.5 {Tk_ImageCmd procedure, "create" option} -constraints {
+ testImageType
+} -body {
+ list [image create test myimage] [imageNames]
+} -cleanup {
+ imageCleanup
+} -result {myimage myimage}
+test image-1.6 {Tk_ImageCmd procedure, "create" option} -constraints {
+ testImageType
+} -setup {
+ imageCleanup
+} -body {
+ scan [image create test] image%d first
+ image create test myimage
+ scan [image create test -variable x] image%d second
+ expr {$second-$first}
+} -cleanup {
+ imageCleanup
+} -result {1}
+
+test image-1.7 {Tk_ImageCmd procedure, "create" option} -constraints {
+ testImageType
+} -setup {
+ imageCleanup
+} -body {
+ image create test myimage -variable x
+ .c create image 100 50 -image myimage
+ .c create image 100 150 -image myimage
+ update
+ set x {}
+ set timer [after 500 {lappend x "timeout"}]
+ image create test myimage -variable x
+ update idletasks
+ update
+ # On MacOS we need to wait for the test image display procedure to run.
+ while {"timeout" ni $x && [lindex $x end 1] ne "display"} {
+ vwait x
+ }
+ after cancel timer
+ if {[lindex $x end] eq "timeout"} {
+ return [lreplace $x end end]
+ }
+ return $x
+} -cleanup {
+ imageCleanup
+} -result {{myimage free} {myimage free} {myimage delete} {myimage get} {myimage get} {myimage display 0 0 30 15} {myimage display 0 0 30 15}}
+test image-1.8 {Tk_ImageCmd procedure, "create" option} -constraints {
+ testImageType
+} -setup {
+ .c delete all
+ imageCleanup
+} -body {
+ image create test myimage -variable x
+ .c create image 100 50 -image myimage
+ .c create image 100 150 -image myimage
+ image delete myimage
+ update
+ set x {}
+ image create test myimage -variable x
+ update
+ return $x
+} -cleanup {
+ .c delete all
+ imageCleanup
+} -result {{myimage get} {myimage get} {myimage display 0 0 30 15} {myimage display 0 0 30 15}}
+test image-1.9 {Tk_ImageCmd procedure, "create" option} -constraints {
+ testImageType
+} -body {
+ image create test -badName foo
+} -returnCodes error -result {bad option name "-badName"}
+test image-1.10 {Tk_ImageCmd procedure, "create" option} -constraints {
+ testImageType
+} -body {
+ catch {image create test -badName foo}
+ imageNames
+} -result {}
+test image-1.11 {Tk_ImageCmd procedure, "create" option with same name as main window} -body {
+ set code [loadTkCommand]
+ append code {
+ update
+ puts [list [catch {image create photo .} msg] $msg]
+ exit
+ }
+ set script [makeFile $code script]
+ exec [interpreter] <$script
+} -cleanup {
+ removeFile script
+} -result {1 {images may not be named the same as the main window}}
+test image-1.12 {Tk_ImageCmd procedure, "create" option with same name as main window after renaming} -body {
+ set code [loadTkCommand]
+ append code {
+ update
+ puts [list [catch {rename . foo;image create photo foo} msg] $msg]
+ exit
+ }
+ set script [makeFile $code script]
+ exec [interpreter] <$script
+} -cleanup {
+ removeFile script
+} -result {1 {images may not be named the same as the main window}}
+test image-1.13 {Tk_ImageCmd, "create" option: do not generated command name in use} -setup {
+ .c delete all
+ imageCleanup
+} -body {
+ set i [image create bitmap]
+ regexp {^image(\d+)$} $i -> serial
+ incr serial
+ proc image$serial {} {return works}
+ set j [image create bitmap]
+
+ image$serial
+} -cleanup {
+ rename image$serial {}
+ image delete $i $j
+} -result works
+
+test image-2.1 {Tk_ImageCmd procedure, "delete" option} -body {
+ image delete
+} -result {}
+test image-2.2 {Tk_ImageCmd procedure, "delete" option} -constraints {
+ testImageType
+} -setup {
+ imageCleanup
+ set result {}
+} -body {
+ image create test myimage
+ image create test img2
+ lappend result [lsort [imageNames]]
+ image d myimage img2
+ lappend result [imageNames]
+} -cleanup {
+ imageCleanup
+} -result {{img2 myimage} {}}
+test image-2.3 {Tk_ImageCmd procedure, "delete" option} -constraints {
+ testImageType
+} -setup {
+ imageCleanup
+} -body {
+ image create test myimage
+ image create test img2
+ image delete myimage gorp img2
+} -cleanup {
+ imageCleanup
+} -returnCodes error -result {image "gorp" doesn't exist}
+test image-2.4 {Tk_ImageCmd procedure, "delete" option} -constraints {
+ testImageType
+} -setup {
+ imageCleanup
+} -body {
+ image create test myimage
+ image create test img2
+ catch {image delete myimage gorp img2}
+ imageNames
+} -cleanup {
+ imageCleanup
+} -result {img2}
+
+
+test image-3.1 {Tk_ImageCmd procedure, "height" option} -body {
+ image height
+} -returnCodes error -result {wrong # args: should be "image height name"}
+test image-3.2 {Tk_ImageCmd procedure, "height" option} -body {
+ image height a b
+} -returnCodes error -result {wrong # args: should be "image height name"}
+test image-3.3 {Tk_ImageCmd procedure, "height" option} -body {
+ image height foo
+} -returnCodes error -result {image "foo" doesn't exist}
+test image-3.4 {Tk_ImageCmd procedure, "height" option} -constraints {
+ testImageType
+} -setup {
+ imageCleanup
+} -body {
+ image create test myimage
+ set x [image h myimage]
+ myimage changed 0 0 0 0 60 50
+ list $x [image height myimage]
+} -cleanup {
+ imageCleanup
+} -result {15 50}
+
+
+test image-4.1 {Tk_ImageCmd procedure, "names" option} -body {
+ image names x
+} -returnCodes error -result {wrong # args: should be "image names"}
+test image-4.2 {Tk_ImageCmd procedure, "names" option} -constraints {
+ testImageType
+} -setup {
+ catch {interp delete testinterp}
+} -body {
+ interp create testinterp
+ load {} Tk testinterp
+ interp eval testinterp {
+ image delete {*}[image names]
+ image create test myimage
+ image create test img2
+ image create test 24613
+ lsort [image names]
+ }
+} -cleanup {
+ interp delete testinterp
+} -result {24613 img2 myimage}
+test image-4.3 {Tk_ImageCmd procedure, "names" option} -setup {
+ catch {interp delete testinterp}
+} -body {
+ interp create testinterp
+ load {} Tk testinterp
+ interp eval testinterp {
+ image delete {*}[image names]
+ eval image delete [image names] [image names]
+ lsort [image names]
+ }
+} -cleanup {
+ interp delete testinterp
+} -result {}
+
+
+test image-5.1 {Tk_ImageCmd procedure, "type" option} -body {
+ image type
+} -returnCodes error -result {wrong # args: should be "image type name"}
+test image-5.2 {Tk_ImageCmd procedure, "type" option} -body {
+ image type a b
+} -returnCodes error -result {wrong # args: should be "image type name"}
+test image-5.3 {Tk_ImageCmd procedure, "type" option} -body {
+ image type foo
+} -returnCodes error -result {image "foo" doesn't exist}
+
+test image-5.4 {Tk_ImageCmd procedure, "type" option} -constraints {
+ testImageType
+} -setup {
+ imageCleanup
+} -body {
+ image create test myimage
+ image type myimage
+} -cleanup {
+ imageCleanup
+} -result {test}
+test image-5.5 {Tk_ImageCmd procedure, "type" option} -constraints {
+ testImageType
+} -setup {
+ imageCleanup
+} -body {
+ image create test myimage
+ .c create image 50 50 -image myimage
+ image delete myimage
+ image type myimage
+} -cleanup {
+ imageCleanup
+} -returnCodes error -result {image "myimage" doesn't exist}
+test image-5.6 {Tk_ImageCmd procedure, "type" option} -constraints {
+ testOldImageType
+} -setup {
+ imageCleanup
+} -body {
+ image create oldtest myimage
+ image type myimage
+} -cleanup {
+ imageCleanup
+} -result {oldtest}
+test image-5.7 {Tk_ImageCmd procedure, "type" option} -constraints {
+ testOldImageType
+} -setup {
+ .c delete all
+ imageCleanup
+} -body {
+ image create oldtest myimage
+ .c create image 50 50 -image myimage
+ image delete myimage
+ image type myimage
+} -cleanup {
+ .c delete all
+ imageCleanup
+} -returnCodes error -result {image "myimage" doesn't exist}
+
+
+test image-6.1 {Tk_ImageCmd procedure, "types" option} -body {
+ image types x
+} -returnCodes error -result {wrong # args: should be "image types"}
+test image-6.2 {Tk_ImageCmd procedure, "types" option} -constraints {
+ testImageType
+} -body {
+ lsort [image types]
+} -result {bitmap oldtest photo test}
+
+
+test image-7.1 {Tk_ImageCmd procedure, "width" option} -body {
+ image width
+} -returnCodes error -result {wrong # args: should be "image width name"}
+test image-7.2 {Tk_ImageCmd procedure, "width" option} -body {
+ image width a b
+} -returnCodes error -result {wrong # args: should be "image width name"}
+test image-7.3 {Tk_ImageCmd procedure, "width" option} -body {
+ image width foo
+} -returnCodes error -result {image "foo" doesn't exist}
+test image-7.4 {Tk_ImageCmd procedure, "width" option} -constraints {
+ testImageType
+} -setup {
+ imageCleanup
+} -body {
+ image create test myimage
+ set x [image w myimage]
+ myimage changed 0 0 0 0 60 50
+ list $x [image width myimage]
+} -cleanup {
+ imageCleanup
+} -result {30 60}
+
+
+test image-8.1 {Tk_ImageCmd procedure, "inuse" option} -constraints {
+ testImageType
+} -setup {
+ imageCleanup
+ set res {}
+ destroy .b
+} -body {
+ image create test myimage2
+ lappend res [image inuse myimage2]
+ button .b -image myimage2
+ lappend res [image inuse myimage2]
+} -cleanup {
+ imageCleanup
+ catch {destroy .b}
+} -result [list 0 1]
+
+if {[tk windowingsystem] == "aqua" && $tcl_platform(osVersion) > 18} {
+ # Aqua >= 10.14 will redraw the entire image in drawRect.
+ set result_9_1 {{foo display 0 0 30 15}}
+} else {
+ set result_9_1 {{foo display 5 6 7 8}}
+}
+test image-9.1 {Tk_ImageChanged procedure} -constraints testImageType -setup {
+ .c delete all
+ imageCleanup
+ update
+} -body {
+ image create test foo -variable x
+ .c create image 50 50 -image foo
+ update
+ set x {}
+ set timer [after 500 {lappend x "timeout"}]
+ foo changed 5 6 7 8 30 15
+ update idletasks
+ update
+ # On MacOS we need to wait for the test image display procedure to run.
+ while {"timeout" ni $x && [lindex $x end 1] ne "display"} {
+ vwait x
+ }
+ after cancel timer
+ return $x
+} -cleanup {
+ .c delete all
+ imageCleanup
+} -result $result_9_1
+if {[tk windowingsystem] == "aqua" && $tcl_platform(osVersion) > 18} {
+ # Aqua >= 10.14 will redraw the entire image.
+ set result_9_2 {{foo display 0 0 30 15} {foo display 0 0 30 15}}
+} else {
+ set result_9_2 {{foo display 5 6 25 9} {foo display 0 0 12 14}}
+}
+test image-9.2 {Tk_ImageChanged procedure} -constraints testImageType -setup {
+ .c delete all
+ imageCleanup
+ update
+} -body {
+ image create test foo -variable x
+ .c create image 50 50 -image foo
+ .c create image 90 100 -image foo
+ update
+ set x {}
+ foo changed 5 6 7 8 30 15
+ update
+ return $x
+} -cleanup {
+ .c delete all
+ imageCleanup
+} -result $result_9_2
+
+test image-10.1 {Tk_GetImage procedure} -setup {
+ imageCleanup
+} -body {
+ .c create image 100 10 -image bad_name
+} -cleanup {
+ imageCleanup
+} -returnCodes error -result {image "bad_name" doesn't exist}
+test image-10.2 {Tk_GetImage procedure} -constraints testImageType -setup {
+ destroy .l
+ imageCleanup
+} -body {
+ image create test mytest
+ label .l -image mytest
+ image delete mytest
+ label .l2 -image mytest
+} -cleanup {
+ destroy .l
+ imageCleanup
+} -returnCodes error -result {image "mytest" doesn't exist}
+
+
+test image-11.1 {Tk_FreeImage procedure} -constraints testImageType -setup {
+ .c delete all
+ imageCleanup
+} -body {
+ image create test foo -variable x
+ .c create image 50 50 -image foo -tags i1
+ .c create image 90 100 -image foo -tags i2
+ pack forget .c
+ update
+ set x {}
+ .c delete i1
+ pack .c
+ update
+ list [imageNames] $x
+} -cleanup {
+ .c delete all
+ imageCleanup
+} -result {foo {{foo free} {foo display 0 0 30 15}}}
+test image-11.2 {Tk_FreeImage procedure} -constraints testImageType -setup {
+ .c delete all
+ imageCleanup
+} -body {
+ image create test foo -variable x
+ .c create image 50 50 -image foo -tags i1
+ set names [imageNames]
+ image delete foo
+ update
+ set names2 [imageNames]
+ set x {}
+ .c delete i1
+ pack forget .c
+ pack .c
+ update
+ list $names $names2 [imageNames] $x
+} -cleanup {
+ .c delete all
+ imageCleanup
+} -result {foo {} {} {}}
+
+
+# Non-portable, apparently due to differences in rounding:
+test image-12.1 {Tk_RedrawImage procedure, redisplay area clipping} -constraints {
+ testImageType nonPortable
+} -setup {
+ imageCleanup
+} -body {
+ image create test foo -variable x
+ .c create image 50 60 -image foo -tags i1 -anchor nw
+ update
+ .c create rectangle 30 40 55 65 -width 0 -fill black -outline {}
+ set x {}
+ update
+ return $x
+} -cleanup {
+ imageCleanup
+} -result {{foo display 0 0 5 5 50 50}}
+test image-12.2 {Tk_RedrawImage procedure, redisplay area clipping} -constraints {
+ testImageType nonPortable
+} -setup {
+ imageCleanup
+} -body {
+ image create test foo -variable x
+ .c create image 50 60 -image foo -tags i1 -anchor nw
+ update
+ .c create rectangle 60 40 100 65 -width 0 -fill black -outline {}
+ set x {}
+ update
+ return $x
+} -cleanup {
+ imageCleanup
+} -result {{foo display 10 0 20 5 30 50}}
+test image-12.3 {Tk_RedrawImage procedure, redisplay area clipping} -constraints {
+ testImageType nonPortable
+} -setup {
+ imageCleanup
+} -body {
+ image create test foo -variable x
+ .c create image 50 60 -image foo -tags i1 -anchor nw
+ update
+ .c create rectangle 60 70 100 200 -width 0 -fill black -outline {}
+ set x {}
+ update
+ return $x
+} -cleanup {
+ imageCleanup
+} -result {{foo display 10 10 20 5 30 30}}
+test image-12.4 {Tk_RedrawImage procedure, redisplay area clipping} -constraints {
+ testImageType nonPortable
+} -setup {
+ imageCleanup
+} -body {
+ image create test foo -variable x
+ .c create image 50 60 -image foo -tags i1 -anchor nw
+ update
+ .c create rectangle 30 70 55 200 -width 0 -fill black -outline {}
+ set x {}
+ update
+ return $x
+} -cleanup {
+ imageCleanup
+} -result {{foo display 0 10 5 5 50 30}}
+test image-12.5 {Tk_RedrawImage procedure, redisplay area clipping} -constraints {
+ testImageType nonPortable
+} -setup {
+ imageCleanup
+} -body {
+ image create test foo -variable x
+ .c create image 50 60 -image foo -tags i1 -anchor nw
+ update
+ .c create rectangle 10 20 120 130 -width 0 -fill black -outline {}
+ set x {}
+ update
+ return $x
+} -cleanup {
+ imageCleanup
+} -result {{foo display 0 0 30 15 70 70}}
+test image-12.6 {Tk_RedrawImage procedure, redisplay area clipping} -constraints {
+ testImageType nonPortable
+} -setup {
+ imageCleanup
+} -body {
+ image create test foo -variable x
+ .c create image 50 60 -image foo -tags i1 -anchor nw
+ update
+ .c create rectangle 55 65 75 70 -width 0 -fill black -outline {}
+ set x {}
+ update
+ return $x
+} -cleanup {
+ imageCleanup
+} -result {{foo display 5 5 20 5 30 30}}
+
+
+test image-13.1 {Tk_SizeOfImage procedure} -constraints testImageType -setup {
+ imageCleanup
+} -body {
+ image create test foo -variable x
+ set result [list [image width foo] [image height foo]]
+ foo changed 0 0 0 0 85 60
+ lappend result [image width foo] [image height foo]
+} -cleanup {
+ imageCleanup
+} -result {30 15 85 60}
+
+test image-13.2 {DeleteImage procedure} -constraints testImageType -setup {
+ .c delete all
+ imageCleanup
+} -body {
+ image create test foo -variable x
+ .c create image 50 50 -image foo -tags i1
+ .c create image 90 100 -image foo -tags i2
+ set x {}
+ image delete foo
+ lappend x | [imageNames] | [catch {image delete foo} msg] | $msg | [imageNames] |
+} -cleanup {
+ imageCleanup
+} -result {{foo free} {foo free} {foo delete} | {} | 1 | {image "foo" doesn't exist} | {} |}
+
+test image-13.3 {Tk_SizeOfImage procedure} -constraints testOldImageType -setup {
+ imageCleanup
+} -body {
+ image create oldtest foo -variable x
+ set result [list [image width foo] [image height foo]]
+ foo changed 0 0 0 0 85 60
+ lappend result [image width foo] [image height foo]
+} -cleanup {
+ imageCleanup
+} -result {30 15 85 60}
+
+test image-13.4 {DeleteImage procedure} -constraints testOldImageType -setup {
+ .c delete all
+ imageCleanup
+} -body {
+ image create oldtest foo -variable x
+ .c create image 50 50 -image foo -tags i1
+ .c create image 90 100 -image foo -tags i2
+ set x {}
+ image delete foo
+ lappend x | [imageNames] | [catch {image delete foo} msg] | $msg | [imageNames] |
+} -cleanup {
+ .c delete all
+ imageCleanup
+} -result {{foo free} {foo free} {foo delete} | {} | 1 | {image "foo" doesn't exist} | {} |}
+
+test image-14.1 {image command vs hidden commands} -body {
+ catch {image delete hidden}
+ set l [imageNames]
+ set h [interp hidden]
+ image create photo hidden
+ interp hide {} hidden
+ image delete hidden
+ set res1 [list [imageNames] [interp hidden]]
+ set res2 [list $l $h]
+ expr {$res1 eq $res2}
+} -result 1
+
+test image-15.1 {deleting image does not make widgets forget about it} -setup {
+ .c delete all
+ imageCleanup
+} -body {
+ image create photo foo -width 10 -height 10
+ .c create image 10 10 -image foo -tags i1 -anchor nw
+ update
+ set x [.c bbox i1]
+ lappend x [imageNames]
+ image delete foo
+ lappend x [imageNames]
+ image create photo foo -width 20 -height 20
+ lappend x [.c bbox i1] [imageNames]
+} -cleanup {
+ .c delete all
+ imageCleanup
+} -result {10 10 20 20 foo {} {10 10 30 30} foo}
+
+destroy .c
+imageFinish
+
+# cleanup
+cleanupTests
+return
+
+# Local variables:
+# mode: tcl
+# End:
diff --git a/tk8.6/tests/imgBmap.test b/tk8.6/tests/imgBmap.test
new file mode 100644
index 0000000..e7f2c7e
--- /dev/null
+++ b/tk8.6/tests/imgBmap.test
@@ -0,0 +1,520 @@
+# This file is a Tcl script to test out images of type "bitmap" (i.e.,
+# the procedures in the file tkImgBmap.c). It is organized in the
+# standard fashion for Tcl tests.
+#
+# Copyright (c) 1994 The Regents of the University of California.
+# Copyright (c) 1994-1995 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+imageInit
+
+set data1 {#define foo_width 16
+#define foo_height 16
+#define foo_x_hot 3
+#define foo_y_hot 3
+static unsigned char foo_bits[] = {
+ 0xff, 0xff, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0xff, 0xff, 0xff, 0xff, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xff, 0xff};
+}
+set data2 {
+ #define foo2_width 16
+ #define foo2_height 16
+ static char foo2_bits[] = {
+ 0xff, 0xff, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,
+ 0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,
+ 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0xff};
+}
+makeFile $data1 foo.bm
+makeFile $data2 foo2.bm
+
+imageCleanup
+#canvas .c
+#pack .c
+#update
+#image create bitmap i1
+#.c create image 200 100 -image i1
+update
+proc bgerror msg {
+ global errMsg
+ set errMsg $msg
+}
+
+test imageBmap-1.1 {options for bitmap images} -body {
+ image create bitmap i1 -background #123456
+ lindex [i1 configure -background] 4
+} -cleanup {
+ image delete i1
+} -result {#123456}
+test imageBmap-1.2 {options for bitmap images} -setup {
+ destroy .c
+ pack [canvas .c]
+ update
+} -body {
+ set errMsg {}
+ image create bitmap i1 -background lousy
+ .c create image 200 100 -image i1
+ update
+ list $errMsg $errorInfo
+} -cleanup {
+ image delete i1
+ destroy .c
+} -result {{unknown color name "lousy"} {unknown color name "lousy"
+ (while configuring image "i1")}}
+test imageBmap-1.3 {options for bitmap images} -body {
+ image create bitmap i1 -data $data1
+ lindex [i1 configure -data] 4
+} -result $data1
+test imageBmap-1.4 {options for bitmap images} -body {
+ image create bitmap i1 -data bogus
+} -returnCodes error -result {format error in bitmap data}
+test imageBmap-1.5 {options for bitmap images} -body {
+ image create bitmap i1 -file foo.bm
+ lindex [i1 configure -file] 4
+} -result foo.bm
+test imageBmap-1.6 {options for bitmap images} -body {
+ list [catch {image create bitmap i1 -file bogus} msg] [string tolower $msg]
+} -result {1 {couldn't read bitmap file "bogus": no such file or directory}}
+test imageBmap-1.7 {options for bitmap images} -body {
+ image create bitmap i1 -foreground #00ff00
+ lindex [i1 configure -foreground] 4
+} -cleanup {
+ image delete i1
+} -result {#00ff00}
+test imageBmap-1.8 {options for bitmap images} -setup {
+ destroy .c
+ pack [canvas .c]
+ update
+} -body {
+ set errMsg {}
+ image create bitmap i1 -foreground bad_color
+ .c create image 200 100 -image i1
+ update
+ list $errMsg $errorInfo
+} -cleanup {
+ destroy .c
+ image delete i1
+} -result {{unknown color name "bad_color"} {unknown color name "bad_color"
+ (while configuring image "i1")}}
+test imageBmap-1.9 {options for bitmap images} -body {
+ image create bitmap i1 -data $data1 -maskdata $data2
+ lindex [i1 configure -maskdata] 4
+} -result $data2
+test imageBmap-1.10 {options for bitmap images} -body {
+ image create bitmap i1 -data $data1 -maskdata bogus
+} -returnCodes error -result {format error in bitmap data}
+test imageBmap-1.11 {options for bitmap images} -body {
+ image create bitmap i1 -file foo.bm -maskfile foo2.bm
+ lindex [i1 configure -maskfile] 4
+} -result foo2.bm
+test imageBmap-1.12 {options for bitmap images} -body {
+ list [catch {image create bitmap i1 -data $data1 -maskfile bogus} msg] \
+ [string tolower $msg]
+} -result {1 {couldn't read bitmap file "bogus": no such file or directory}}
+rename bgerror {}
+
+
+test imageBmap-2.1 {ImgBmapCreate procedure} -setup {
+ imageCleanup
+} -body {
+ list [catch {image create bitmap -gorp dum} msg] $msg [imageNames]
+} -result {1 {unknown option "-gorp"} {}}
+test imageBmap-2.2 {ImgBmapCreate procedure} -setup {
+ imageCleanup
+} -body {
+ image create bitmap image1
+ list [info commands image1] [imageNames] \
+ [image width image1] [image height image1] \
+ [lindex [image1 configure -foreground] 4] \
+ [lindex [image1 configure -background] 4]
+} -cleanup {
+ image delete image1
+} -result {image1 image1 0 0 #000000 {}}
+
+
+test imageBmap-3.1 {ImgBmapConfigureMaster procedure, memory de-allocation} -body {
+ image create bitmap i1 -data $data1
+ i1 configure -data $data1
+} -cleanup {
+ image delete i1
+} -result {}
+test imageBmap-3.2 {ImgBmapConfigureMaster procedure} -body {
+ image create bitmap i1 -data $data1
+ list [catch {i1 configure -data bogus} msg] $msg [image width i1] \
+ [image height i1]
+} -result {1 {format error in bitmap data} 16 16}
+test imageBmap-3.3 {ImgBmapConfigureMaster procedure, memory de-allocation} -body {
+ image create bitmap i1 -data $data1 -maskdata $data2
+ i1 configure -maskdata $data2
+} -cleanup {
+ image delete i1
+} -result {}
+test imageBmap-3.4 {ImgBmapConfigureMaster procedure} -body {
+ image create bitmap i1
+ i1 configure -maskdata $data2
+} -returnCodes error -result {can't have mask without bitmap}
+test imageBmap-3.5 {ImgBmapConfigureMaster procedure} -body {
+ image create bitmap i1 -data $data1 -maskdata {
+ #define foo_width 8
+ #define foo_height 16
+ static char foo_bits[] = {
+ 0xff, 0xff, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0xff, 0xff, 0xff, 0xff, 0x81, 0x81};
+ }
+} -returnCodes error -result {bitmap and mask have different sizes}
+test imageBmap-3.6 {ImgBmapConfigureMaster procedure} -body {
+ image create bitmap i1 -data $data1 -maskdata {
+ #define foo_width 16
+ #define foo_height 8
+ static char foo_bits[] = {
+ 0xff, 0xff, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0xff, 0xff, 0xff, 0xff, 0x81, 0x81};
+ }
+} -returnCodes error -result {bitmap and mask have different sizes}
+test imageBmap-3.7 {ImgBmapConfigureMaster procedure} -setup {
+ destroy .c
+ pack [canvas .c]
+} -body {
+ image create bitmap i1 -data $data1
+ .c create image 100 100 -image i1 -tags i1.1 -anchor nw
+ .c create image 200 100 -image i1 -tags i1.2 -anchor nw
+ update
+ i1 configure -data {
+ #define foo2_height 14
+ #define foo2_width 15
+ static char foo2_bits[] = {
+ 0xff, 0xff, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,
+ 0xff, 0x81, 0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81,
+ 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,
+ 0xff, 0xff};
+ }
+ update
+ list [image width i1] [image height i1] [.c bbox i1.1] [.c bbox i1.2]
+} -cleanup {
+ image delete i1
+ destroy .c
+} -result {15 14 {100 100 115 114} {200 100 215 114}}
+
+
+test imageBmap-4.1 {ImgBmapConfigureInstance procedure: check error handling} -setup {
+ destroy .c
+ pack [canvas .c]
+ update
+} -body {
+ proc bgerror args {}
+ image create bitmap i1 -file foo.bm
+ .c create image 100 100 -image i1
+ update
+ i1 configure -foreground bogus
+ update
+} -cleanup {
+ image delete i1
+ destroy .c
+} -result {}
+
+
+test imageBmap-5.1 {GetBitmapData procedure} -body {
+ list [catch {image create bitmap -file ~bad_user/a/b} msg] \
+ [string tolower $msg]
+} -result {1 {user "bad_user" doesn't exist}}
+test imageBmap-5.2 {GetBitmapData procedure} -body {
+ list [catch {image create bitmap -file bad_name} msg] [string tolower $msg]
+} -result {1 {couldn't read bitmap file "bad_name": no such file or directory}}
+test imageBmap-5.3 {GetBitmapData procedure} -setup {imageCleanup} -body {
+ image create bitmap -data { }
+} -returnCodes error -result {format error in bitmap data}
+test imageBmap-5.4 {GetBitmapData procedure} -setup {imageCleanup} -body {
+ image create bitmap -data "#define foo2_width"
+} -returnCodes error -result {format error in bitmap data}
+test imageBmap-5.5 {GetBitmapData procedure} -setup {imageCleanup} -body {
+ image create bitmap -data "#define foo2_width gorp"
+} -returnCodes error -result {format error in bitmap data}
+test imageBmap-5.6 {GetBitmapData procedure} -setup {imageCleanup} -body {
+ image create bitmap -data "#define foo2_width 1.4"
+} -returnCodes error -result {format error in bitmap data}
+test imageBmap-5.7 {GetBitmapData procedure} -setup {imageCleanup} -body {
+ image create bitmap -data "#define foo2_height"
+} -returnCodes error -result {format error in bitmap data}
+test imageBmap-5.8 {GetBitmapData procedure} -setup {imageCleanup} -body {
+ image create bitmap -data "#define foo2_height gorp"
+} -returnCodes error -result {format error in bitmap data}
+test imageBmap-5.9 {GetBitmapData procedure} -setup {imageCleanup} -body {
+ image create bitmap -data "#define foo2_height 1.4"
+} -returnCodes error -result {format error in bitmap data}
+test imageBmap-5.10 {GetBitmapData procedure} -setup {imageCleanup} -body {
+ image create bitmap i1 -data {
+ #define foo2_height 14
+ #define foo2_width 15 xx _widtg 18 xwidth 18 _heighz 18 xheight 18
+ static char foo2_bits[] = {
+ 0xff, 0xff, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,
+ 0xff, 0x81, 0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81,
+ 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,
+ 0xff, 0xff};
+ }
+ list [image width i1] [image height i1]
+} -cleanup {
+ image delete i1
+} -result {15 14}
+test imageBmap-5.11 {GetBitmapData procedure} -setup {imageCleanup} -body {
+ image create bitmap i1 -data {
+ _height 14 _width 15
+ char {
+ 0xff, 0xff, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,
+ 0xff, 0x81, 0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81,
+ 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,
+ 0xff, 0xff}
+ }
+ list [image width i1] [image height i1]
+} -cleanup {
+ image delete i1
+} -result {15 14}
+test imageBmap-5.12 {GetBitmapData procedure} -setup {imageCleanup} -body {
+ image create bitmap i1 -data {
+ #define foo2_height 14
+ #define foo2_width 15
+ static short foo2_bits[] = {
+ 0xff, 0xff, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,
+ 0xff, 0x81, 0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81,
+ 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,
+ 0xff, 0xff};
+ }
+} -returnCodes error -result {format error in bitmap data; looks like it's an obsolete X10 bitmap file}
+test imageBmap-5.13 {GetBitmapData procedure} -setup {imageCleanup} -body {
+ image create bitmap i1 -data {
+ #define foo2_height 16
+ #define foo2_width 16
+ static char foo2_bits[] =
+ 0xff, 0xff, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,
+ 0xff, 0x81, 0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81,
+ 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,
+ 0xff, 0xff;
+ }
+} -returnCodes error -result {format error in bitmap data}
+test imageBmap-5.14 {GetBitmapData procedure} -setup {imageCleanup} -body {
+ image create bitmap i1 -data {
+ #define foo2_width 16
+ static char foo2_bits[] = {
+ 0xff, 0xff, 0xff, }}
+} -returnCodes error -result {format error in bitmap data}
+test imageBmap-5.15 {GetBitmapData procedure} -setup {imageCleanup} -body {
+ image create bitmap i1 -data {
+ #define foo2_height 16
+ static char foo2_bits[] = {
+ 0xff, 0xff, 0xff, }}
+} -returnCodes error -result {format error in bitmap data}
+test imageBmap-5.16 {GetBitmapData procedure} -setup {imageCleanup} -body {
+ image create bitmap i1 -data {
+ #define foo2_height 16
+ #define foo2_width 16
+ static char foo2_bits[] = {
+ 0xff, 0xff, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,
+ 0xff, 0x81, 0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81,
+ 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,
+ 0xff, foo};
+ }
+} -returnCodes error -result {format error in bitmap data}
+test imageBmap-5.17 {GetBitmapData procedure} -setup {imageCleanup} -body {
+ image create bitmap i1 -data "
+ #define foo2_height 16
+ #define foo2_width 16
+ static char foo2_bits[] = \{
+ 0xff, 0xff, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,
+ 0xff, 0x81, 0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81,
+ 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,
+ 0xff
+ "
+} -returnCodes error -result {format error in bitmap data}
+
+
+test imageBmap-6.1 {NextBitmapWord procedure} -setup {imageCleanup} -body {
+ image create bitmap i1 -data {1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890}
+} -returnCodes error -result {format error in bitmap data}
+test imageBmap-6.2 {NextBitmapWord procedure} -setup {imageCleanup} -body {
+ makeFile {1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890} foo3.bm
+ image create bitmap i1 -file foo3.bm
+} -returnCodes error -result {format error in bitmap data}
+test imageBmap-6.3 {NextBitmapWord procedure} -setup {imageCleanup} -body {
+ makeFile { } foo3.bm
+ image create bitmap i1 -file foo3.bm
+} -returnCodes error -result {format error in bitmap data}
+removeFile foo3.bm
+
+
+imageCleanup
+# Image used in 7.* tests
+image create bitmap i1
+test imageBmap-7.1 {ImgBmapCmd procedure} -body {
+ i1
+} -returnCodes error -result {wrong # args: should be "i1 option ?arg ...?"}
+test imageBmap-7.2 {ImgBmapCmd procedure, "cget" option} -body {
+ i1 cget
+} -returnCodes error -result {wrong # args: should be "i1 cget option"}
+test imageBmap-7.3 {ImgBmapCmd procedure, "cget" option} -body {
+ i1 cget a b
+} -returnCodes error -result {wrong # args: should be "i1 cget option"}
+test imageBmap-7.4 {ImgBmapCmd procedure, "cget" option} -body {
+ i1 co -foreground #123456
+ i1 cget -foreground
+} -result {#123456}
+test imageBmap-7.5 {ImgBmapCmd procedure, "cget" option} -body {
+ i1 cget -stupid
+} -returnCodes error -result {unknown option "-stupid"}
+test imageBmap-7.6 {ImgBmapCmd procedure} -body {
+ llength [i1 configure]
+} -result {6}
+test imageBmap-7.7 {ImgBmapCmd procedure} -body {
+ i1 co -foreground #001122
+ i1 configure -foreground
+} -result {-foreground {} {} #000000 #001122}
+test imageBmap-7.8 {ImgBmapCmd procedure} -body {
+ i1 configure -gorp
+} -returnCodes error -result {unknown option "-gorp"}
+test imageBmap-7.9 {ImgBmapCmd procedure} -body {
+ i1 configure -foreground #221100 -background
+} -returnCodes error -result {value for "-background" missing}
+test imageBmap-7.10 {ImgBmapCmd procedure} -body {
+ i1 gorp
+} -returnCodes error -result {bad option "gorp": must be cget or configure}
+# Clean it up after use!!
+imageCleanup
+
+test imageBmap-8.1 {ImgBmapGet/Free procedures, shared instances} -setup {
+ destroy .c
+ pack [canvas .c]
+ update
+} -body {
+ image create bitmap i1 -data $data1
+ .c create image 50 100 -image i1 -tags i1.1
+ .c create image 150 100 -image i1 -tags i1.2
+ .c create image 250 100 -image i1 -tags i1.3
+ update
+ .c delete i1.1
+ i1 configure -background black
+ update
+ .c delete i1.2
+ i1 configure -background white
+ update
+ .c delete i1.3
+ i1 configure -background black
+ update
+ image delete i1
+} -cleanup {
+ destroy .c
+} -result {}
+
+
+test imageBmap-9.1 {ImgBmapDisplay procedure, nothing to display} -setup {
+ destroy .c
+ pack [canvas .c]
+ update
+} -body {
+ proc bgerror args {}
+ imageCleanup
+ image create bitmap i1 -data $data1
+ .c create image 50 100 -image i1 -tags i1.1
+ i1 configure -data {}
+ update
+} -cleanup {
+ image delete i1
+ destroy .c
+} -result {}
+test imageBmap-9.2 {ImgBmapDisplay procedure, nothing to display} -setup {
+ destroy .c
+ pack [canvas .c]
+ update
+} -body {
+ proc bgerror args {}
+ imageCleanup
+ .c delete all
+ image create bitmap i1 -data $data1
+ .c create image 50 100 -image i1 -tags i1.1
+ i1 configure -foreground bogus
+ update
+} -cleanup {
+ image delete i1
+ destroy .c
+} -result {}
+if {[info exists bgerror]} {
+ rename bgerror {}
+}
+
+
+test imageBmap-10.1 {ImgBmapFree procedure, resource freeing} -setup {
+ destroy .c
+ pack [canvas .c]
+ update
+} -body {
+ imageCleanup
+ image create bitmap i1 -data $data1 -maskdata $data2 -foreground #112233 \
+ -background #445566
+ .c create image 100 100 -image i1
+ update
+ .c delete all
+ image delete i1
+} -cleanup {
+ destroy .c
+} -result {}
+test imageBmap-10.2 {ImgBmapFree procedures, unlinking} -setup {
+ destroy .c
+ pack [canvas .c]
+ update
+} -body {
+ imageCleanup
+ image create bitmap i1 -data $data1 -maskdata $data2 -foreground #112233 \
+ -background #445566
+ .c create image 100 100 -image i1
+ button .b1 -image i1
+ button .b2 -image i1
+ button .b3 -image i1
+ pack .b1 .b2 .b3
+ update
+ destroy .b2
+ update
+ destroy .b3
+ update
+ destroy .b1
+ update
+ .c delete all
+} -cleanup {
+ image delete i1
+ deleteWindows
+} -result {}
+
+
+test imageBmap-11.1 {ImgBmapDelete procedure} -body {
+ image create bitmap i2 -file foo.bm -maskfile foo2.bm
+ image delete i2
+ info command i2
+} -result {}
+test imageBmap-11.2 {ImgBmapDelete procedure} -body {
+ image create bitmap i2 -file foo.bm -maskfile foo2.bm
+ rename i2 newi2
+ set x [list [info command i2] [info command new*] [newi2 cget -file]]
+ image delete i2
+ lappend x [info command new*]
+} -result {{} newi2 foo.bm {}}
+
+
+test imageBmap-12.1 {ImgBmapCmdDeletedProc procedure} -body {
+ image create bitmap i2 -file foo.bm -maskfile foo2.bm
+ rename i2 {}
+ list [lsearch -exact [imageNames] i2] [catch {i2 foo} msg] $msg
+} -result {-1 1 {invalid command name "i2"}}
+
+removeFile foo.bm
+removeFile foo2.bm
+imageFinish
+
+# cleanup
+cleanupTests
+return
+
+# Local Variables:
+# mode: tcl
+# fill-column: 78
+# End:
diff --git a/tk8.6/tests/imgPNG.test b/tk8.6/tests/imgPNG.test
new file mode 100644
index 0000000..4900e9c
--- /dev/null
+++ b/tk8.6/tests/imgPNG.test
@@ -0,0 +1,1127 @@
+# This file is a Tcl script to test out the code in tkImgFmtPNG.c, which reads
+# and write PNG-format image files for photo widgets. The files is organized
+# in the standard fashion for Tcl tests.
+#
+# Copyright (c) 1994-1997 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# Copyright (c) 1998 Willem van Schaik (images only)
+# Copyright (c) 2008 Donal K. Fellows
+# All rights reserved.
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+imageInit
+
+namespace eval png {
+ variable encoded
+ # Key names are from the names of the source images, which come from
+ # http://www.schaik.com/pngsuite/pngsuite.html
+ # The exception is "BadX", which is used to test handling badly compressed
+ # images.
+ array set encoded {
+ basn0g08 "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAAAAABWESUoAAAABGdBTUEAAYag
+MeiWXwAAAEFJREFUeJxjZGAkABQIyLMMBQWMDwgp+PcfP2B5MBwUMMoRkGdkonlcDAYFjI/wyv7/z/
+iH5nExGBQwyuCVZWQEAFDl/nE14thZAAAAAElFTkSuQmCC"
+ basn2c08 "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAABGdBTUEAAYag
+MeiWXwAAAEhJREFUeJzt1cEJADAMAkCF7JH9t3ITO0Qr9KH4zuErtA0EO4AKFPgcoO3kfUx4QIECD0
+qHH8KEBxQo8KB0OCOpQIG7cHejwAGCsfleD0DPSwAAAABJRU5ErkJggg=="
+ basn3p08 "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAABGdBTUEAAYag
+MeiWXwAAAwBQTFRFIkQA9f/td/93y///EQoAOncAIiL//xH/EQAAIiIA/6xVZv9m/2Zm/wH/IhIA3P
+//zP+ZRET/AFVVIgAAy8v/REQAVf9Vy8sAMxoA/+zc7f//5P/L/9zcRP9EZmb/MwAARCIA7e3/ZmYA
+/6RE//+q7e0AAMvL/v///f/+//8BM/8zVSoAAQH/iIj/AKqqAQEARAAAiIgA/+TLulsAIv8iZjIA//
++Zqqr/VQAAqqoAy2MAEf8R1P+qdzoA/0RE3GsAZgAAAf8BiEIA7P/ca9wA/9y6ADMzAO0A7XMA//+I
+mUoAEf//dwAA/4MB/7q6/nsA//7/AMsA/5mZIv//iAAA//93AIiI/9z/GjMAAACqM///AJkAmQAAAA
+ABMmYA/7r/RP///6r/AHcAAP7+qgAASpkA//9m/yIiAACZi/8RVf///wEB/4j/AFUAABER///+//3+
+pP9EZv///2b/ADMA//9V/3d3AACI/0T/ABEAd///AGZm///tAAEA//XtERH///9E/yL//+3tEREAiP
+//AAB3k/8iANzcMzP//gD+urr/mf//MzMAY8sAuroArP9V///c//8ze/4A7QDtVVX/qv//3Nz/VVUA
+AABm3NwA3ADcg/8Bd3f//v7////L/1VVd3cA/v4AywDLAAD+AQIAAQAAEiIA//8iAEREm/8z/9SqAA
+BVmZn/mZkAugC6KlUA/8vLtP9m/5sz//+6qgCqQogAU6oA/6qqAADtALq6//8RAP4AAABEAJmZmQCZ
+/8yZugAAiACIANwA/5MiAADc/v/+qlMAdwB3AgEAywAAAAAz/+3/ALoA/zMz7f/t/8SIvP93AKoAZg
+BmACIi3AAA/8v/3P/c/4sRAADLAAEBVQBVAIgAAAAiAf//y//L7QAA/4iIRABEW7oA/7x3/5n/AGYA
+uv+6AHd3c+0A/gAAMwAzAAC6/3f/AEQAqv+q//7+AAARIgAixP+IAO3tmf+Z/1X/ACIA/7RmEQARCh
+EA/xER3P+6uv//iP+IAQAB/zP/uY7TYgAAAbFJREFUeJwNwQcACAQQAMBHqIxIZCs7Mwlla1hlZ+8V
+itCw9yoqNGiYDatsyt6jjIadlVkysve+u5jC9xTmV/qyl6bcJR7kAQZzg568xXmuE2lIyUNM5So7OM
+AFIhvp+YgGvEtFNnOKeJonSEvwP9NZzhHiOfLzBXPoxKP8yD6iPMXITjP+oTdfsp14lTJMJjGtOMFQ
+fiFe4wWK8BP7qUd31hBNqMos2tKYFbRnJdGGjTzPz2yjEA1ZSKymKCM5ylaWcJrZxCZK8jgfU4vc/M
+W3xE7K8RUvsZb3Wc/XxCEqk4v/qMQlFvMZcZIafMOnLKM13zGceJNqPMU4KnCQAqQgbrKHpXSgFK/Q
+n6REO9YxjWE8Sx2SMJD4jfl8wgzy0YgPuEeUJQcD6EoWWpCaHsQkHuY9RpGON/icK0RyrvE680jG22
+TlHaIbx6jLnySkF+M5QxzmD6pwkTsMoSAdidqsojipuMyHzOQ4sYgfyElpzjKGErQkqvMyC7jFv9xm
+BM2JuTzDRDLxN4l4jF1EZjIwmhfZzSOMpT4xiH70IQG/k5En2UKcowudycsG8jCBmtwHgRv+EIeWyO
+AAAAAASUVORK5CYII="
+ basn6a08 "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAAYag
+MeiWXwAAAG9JREFUeJzt1jEKgDAMRuEnZGhPofc/VQSPIcTdxUV4HVLoUCj8H00o2YoBMF57fpz/uj
+ODHXUFRwPKBqj5DVigB041HiJ9gFyCVOMbsEIPXNwuAHkgiJL/4qABNqB7QAeUPBAE2QAZUDZAfwEb
+8ABSIBqcFg+4TAAAAABJRU5ErkJggg=="
+
+ BadX "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAABHNCSVQICAgIfAhk
+iAAAABN0RVh0U29mdHdhcmUAVGsgOC42YjEuMcrtT1oAAAAcSURBVHicYmBgYPjPgAr+ozP+o0uj68
+BUiWEmAAAA//8SozfjAAAAAElFTkSuQmCC"
+ MultiIDAT "iVBORw0KGgoAAAANSUhEUgAAAN8AAADUCAYAAAAcPvbvAAAAAXNSR0IArs4
+c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9oEGQQKMpLRO
+uoAACAASURBVHja7L158GbZWd/3ec45977bb+2e7p7pnu7ZNzFaRhJCwggjsHqUCgUhiWMSJymwUoV
+UlkumJChCHFWBywQQNqhYpFDB2Ljs2EWqiAmphMQVO2ATQMJCQsuMZrp7lt5++7ve9957lid/3Ptbu
+tWjGRAgZvo9XW//3vXe973nfM/zPN9nE1VlMf58RwHkgFMgJhDAQg0EAJQ+FuYekgVrCBope5YK6F3
+8Vw9UCdbvOnuBwbH2aDnBKy7rtkcA357PYHC0B0/t2xfjaz7M4hJ8jS+6fPnriqKqxLqG1IDTGINpP
+9vtds8bY85j5ABoYBAxX3ly5dbnW4wF+G7PoTcDpvnnYyDEeACYJOlgsozN3xMS71Fx7RQaFIOIbY6
+n5iaMpQX4/gIOt7gEf/7jyzFgQMFIAxODQSShmYXcgICmRr5F9dlwPH3XaFJw3LgMjFcsgiDtcZAG1
+HIEsArIAnwLybcA30urnQcPjSHr5GBNK7kSgpLq6h0XLz63fP36xjKYd4AlYUgYdF/t1MPJlVtJv8V
+YgO92vujmFmJQblAUFbWmfXPCZQaH4mezJ5/+wtM8//yLBJ+ePFQ7pQGdtjhTGkl49LiSFuBbgG8h+
+V5OJU0CAQVJJBQxIBqY7uw8+fyFS2xcvkooqycPxBzSqJU3MjcHE5yOAnAxFjbf7bzjyVG06Y07YWy
+ghEps3AUaMJpB7U8Ue8MnptvbpKSkyj9BTCewbMm+TccR6WdvBLoutM6F5FtIvpvuHFE7DaAaMRiCJ
+hKxnSUlFMW7r1+8ZIrNberhmPHWhsHIu20r16K2yE2HgL55khd+3QX4FuMWNh8KouDUoijG2saWA9B
+EPR6f37t8Fb+zTbW1wdVnn0GHu+eJFYaAMa0uc8MxzWKiF2rnYtys/+nNkjA1Dw4kIAaIiCYAmW3vv
+Pv6xUuc7uY4Z5ltXENC9W6siKKaNEEAK6ZVZxVEDjRbARC7uP4LybcY6WYNsbXVGuDpwStiFIJ//Wh
+r+/Tw6nXcdEI2m7B96Vn8aPc0qX49VIjEBls36pmAaX2A5gZ1dDEW4LvtheCNd1ppqPsATc39afHke
+GsLijlrKXDMKDoZUY92INZPQiASUEmo6OEBAJI2t1ucZzEW4Lttgbcv/W54UsEeqIsREWE2Gp7fvbZ
+BR4S7Bl1ODnosWaXY2wZfnBcCSiRoA8B9cuWQYJEF8BbgW4yviMZDbbMJsEYRUm+8s/fOzWtX6RmHK
+Ut0NiVMp1x5/iJpMn4n0LMI1jQ2nR7x56nqIfAWbr4F+BbjKxuDgrR2HwDvms7GnclwhBXDXXcc5/j
+qEsu9LnVRoMF3IL1LSXitSC3CVF5Kx12MBfhu0xGlSa2LBKDCUIH4AxdBSFABdcrpsgTT4jxXL3C3v
+8bXZZsMj09YX4k8sLfLGy9sYj//AuxMzqc4oxTLmEQtYKRJMxIR1OjNwZ6LsQDf7TteCge29QZYAxC
+Z7e6cH+/tYpLSzRyDwQDnGi9RWZawuwfz+Xln7a1z+F7JSRdjAb7b5aLv+/LM/hTI4ZNiGxUxA/D1u
+d3rVx/b29zAxJqBc2TWISJ0Oh2cs1DMoJw/ZpKegxpzk355g/q5AN8CfLe7xDMcDURpH7VPqECMYAH
+q8vxo8zrz4R5dha4xTQRM5ED61eMRTKcQ03nRwIGr70gcm+4ffzEW4Luth+4D0HBDzvlB1nozMY5Em
+k+fjJMxnbqmbw0dlH7Ww4khxkgxn7K7s0Xc3QEfnlyRDHcTpalH/y4AuADf7Q6+fQA2twaKKg0Zo4C
+zQArWj4bfJtMZfWDZGnoiZGJxJsN1crLMYjWRiikUs2+DZDNNByFl+ypnkhuBuBgL8C2YliM1WBJNU
+kIEnCSopm8rtjfXw2iPzNd0ETpJMcmRuR5Z3qXb79HJLTIvYTRap6ze5lLCHg1wOfJ34eZbgG8x4KD
+Y0X7mwWEiekSIUM7P+71dwniErSqcD1iUvhuQGUeISlGW1MWMajyC8QSinicq0sIs3ax7LsYCfLf3a
+GWQ3giK/SBrQUE9Ops+GcZj0nRGR5WOs0iM+DJRFDVBlYQS64o4HsHuLoTwZBNMLU1qX2qSbJsSobr
+A4AJ8t7vamb7M/jsqnCwKKa2HWfE2PxqSh0DXGHKxZFlGbvt08iUkyxFrsMYQZwVxcwf2Rm+j9uu0M
+Z37Np+9UQ4uxgJ8ty/f8mUA5KbEdu+/rdjdttPtHZxP9GyGMYYsy8ntgKwzQIxDrSOzllTMKba3YDS
+yhPBtaGyO1TKn5sDODIsJWIDv9h3xqPK3z3weAaABKOsnp7tDyuEIGyNWDClBQDBqMZIRsCQBay3UN
+Wk8g2IOSZ9EBYNytGqEFV0Yfwvw3e7gS4dB00cyGQ4iXxRiMTtfjsdQB3JjceIa+w4BzYjJUadETBB
+jRLwnFQVMphDj+abOpxwCW0FIB0TMYizAd9uqnfHmJ/SGx4/NJ9Nz1bRo7Lw2nAzjSEZAHT4mklpqj
+YS6JtWeOJ/D1jaU1TlCfOzgcAnQ2E72AnwL8N3Wki+2ki/emMPXOt6T9+dHe0PqYk4mBougqhjnMFm
+OkYwUmyBQwRBCgBShDky3d2E6AV+dv6FIRVKU2HoTF2MBvttY8qVbsjDN8N6fn02mVPOySQdKiZRS0
+6nIZs3bVZvHzrb2nGBIzGeTxu6r6/OKNhKzJXgWZQP/Yo1F9bI/T9C1iz/Spw9NQz4FejAlUlOzCp1
+sd/td/UtXcFtzenPBxBx1UKSaEC1djWQmI9VgnWsKdkahmxx6bQR/+Hm489S7TLXbKaypCrcK5Aw0x
+4XFrC8k3+180aWtLn1TcmvTaUjfWRVFz1c1GiOookkQNc0tQUqJGCMpNLcYAr6uqeYlVTEnDIcwnvS
+I+k5n7H7vzS8vJ78YC/DdbkP21U5p9M0YIwI4BI3x/GS3sfdSiKR0o7qoKRFCQFOCmNCgaB1IPhCqm
+nI+Z+vaBmzvQEznu8YtBN0CfIuxPxKHlfxAG3uulU5pXj052xsR5h4TFQJoBFFBkqBBCSkRQ0JTQkL
+CREGiIjGhdWCyNyRt7UDpn2wmObah24uxAN9C8jXgsxyEnhgEB6fDdP76+d4YrTwOi2jjXNckEA2xB
+u89IQRSSGhImKRYFSQKEiCVNeONbZjOX0/ktNOI1bb+52LGF+C77S/6fkiLE0S0aXEZw7vr4Uj8aIq
+UHptAVIkxIckiScAnfB3RoCSfSJUn1REJNFLRe0IZ2L56Hba2BR/f7ZKQyyKTfQG+xbhRBLZ/LKDz6
+vx8e0iazJEqYqOgEVLQJjtBHRrb/D9tX/OJWEeiT3gfqavAbDrl6vMvMrx6HWbz88S238OiR9hfqLG
+wxb9GmFONIK5pfpkClszovH63H02xRY2tIyYKISopAmohKkYdYiwiilElJYtGJSbFR8XHyHQ2Z4Qy2
+tpjbVa+m17f4DQhsWFOv+peKYs9eyH5/oKOl3Jmi0jr9G4c5sH7ZhIUqMMTroontp+/Qr03oRMgzit
+iHRFxzOcVVeUbuy8m6ipSzCrms5JyXlNUNUVVMatqyhjx3vO5T3+GsL17gpSeIDVBnokvZ1CPfu/91
+24sNX8TYXTkPTd/fuHIX0i+vzDgk1s41ywGS8LmFjRhswxierIajTCzCqkjztOQJ6ntdxkVrRMEJXR
+NWwLekKIwrz0xRqqYmMbAqC7Y8yXF5hbj3T2ORX0STX+AGoy1reRtgHZ0U9i/LQC0kHyvOsAd3fmP/
+r35BhFNjQM91XWDsKp6cu/aJmkypxPABcUkwbSFADUJMYKvE7WPhAAhQFlFJvOaYVGyPZuyM59RG2F
+rOOTChQtcfPYCeP8kIpRlgVd/ADhjDMaYryitF0BcSL5XpYr50he9bWiibYSnmGVieke5N6YTIasTJ
+iQ0RKIoUSAmg8QGp943sZ6+qqnnJfO6Yh49Y18zToFpmdiaTCh9xYULl3jrpHgHa6vLeZ5PklhU9Yb
+vt39/X53cB+TR3yiL8JiF5HtVECrtQr1ZnTskXJSjmeaQ3uWHw2y0tUU1miCVR+cBX3qqsmZeeXxM+
+AAxKAlH8IlyXjOrAkVITENi5Gt25gWX93YpgqesPBcuXOC5S5cy6vpdMTbnjDEeqJxHpbOINIm5Cwm
+4AN+rSeodVStvBtuXfS4F9jl/cRnU/j17W9vMRmPK0QSqQKw9ofZ4HwkpNfl7SQkRYoI6wLyqmc5Lp
+mXFuCzZLefszAtmGilCYFRMufDsRa5duwZJ35PlOYmm0vVR6bYfK3qzyvxSqvViLMD3qrL/jt72e+g
+RA8TIfDw+v7O13YSKKahP0AZNp5RIsZFWPgbqumY2K5jNCiazOZNpwd5kyt5sxrAoGFZzJlXF3mzGX
+jHl0vPP8cUvfpFrl198/7ycU6Wasizx3h+omfsbxa1s1sVY2HyvKgl4VPW81YKeT6agynhv7wlV/Ya
+969f/zQvPPTfU0fj1/WKe+yph6pqQwoHNl2IilR5becblDF/VFMWcopgz9XOmEijUU2lgHEpCo9zyw
+niHX//1X+daXXDPGx+v1s/c9Uf3nzr7h4PB4FMrKyu/NxgMPu2cwzl3S9fBwtb7MzRPbscdzlPSRFO
+aI38P1QCNbRl3A02nythkipvGZhqSYxBsW+jdtoX5AjAPje/cojjGOPbohhKmNWyPHg07o/Ofuv573
+7o3nn7zZ75waf36iyNOd0/zsDvDyT3D8V3F7pXEqqSQinIgTLPIuJ4xns+oqhK7u0WZAsN6zrYv2CO
+wZwK7WrMdPMMI0UEQRx2UGJU867O+ssbS0hIPn+rz0GOPcuaBezlx7vTeg48/9ltn7z/3/ywtLf1fn
+az7FFHJbQeNhgiI7Ta/jcbtkamSidzQ7OWw6xJH7NkbukQcGenI1ZYjStjLKWLpNaWw3Zbgq6jbhXM
+IQMNhuOWhbdZEoohpc89Nk3M3ItEhawsSgfcRUUfHWaxAVU2QuEcoNvCTjbcVm1e/a+u5y99++UuXH
+r/+4iYvzq+zNRrzhWcuU0yFJ+59gneefTPn/CprY5CdKZoC01QwEc/c1BSpYjgaMRmPSeWYOkUmqWY
+nzNlNnqEJ7BLYS0oBeAvBCDEJITaL3ZGRGYtJBYOOpb/SY+3EKg8/+iCPPPoADz14P/efPfu5+++5/
+zeOrR3/Nddf+X1sBlmHGou3FiHD4m6AzAHAUkA14lrSRm6IZTsKmHgL4L0cqNJrzlq6TcHnj8i8tk+
+QHpnQtp7KfqMRNTe2NDcpYo0AHsE3z6YAsznMZ8StF+4bbVz861svPvXXtq9deny4vcHu9h67uyOKW
+c0w9bi6tculywUuc7zjsb/EW8+9kfWxhetTBkGwBiZhxrCcUlASY2Syt8vuzg4TG6lJzJJnV0tGePb
+wTEiMUGY0SfLxoAeZgaStImpY7TqCr0kR+haODWCtC2dO9Xjg7N08cP+9PPzIYzz2xjd97tT9D/4LT
+p75p7jOJRBULOgpVJu+7yL7x20u3H5VNmk3twOJdnSZSbgFkF6p1HvtgO82tfluVnnayT2KMGsQOSx
+BFI/clpNAqoESZAr1FN3dZHb58neEjSt/Y/vZz3+n33qR6d5lUjFC5gXMSsxc6aqBaYbfKuiUcO7Yn
+Zxbu4s128ekmipFJnUAo5QamMaaedWoodW0REjsGcUnmAFjDEOUCcIMocYQ24bT+z9HJGEyg2gTvbJ
+X1ViFdQd3rcCprjBQZX06x12/wAubz+CvfJ7RC59+/OzDjz1+92Ov+7vH7773X9r1E/9Qlld+nbSMq
+B5tMAjGHdm72n6AB1scN25scjOAbk/ez92e0DMI6aVblB9ZC0nbGs/7QFTAz0Dn4PeIwxcZXr34vtE
+LF95fXn3hDW64Q9q6gp2PWKkndDVA9IwrD7PGRTAZlexsNsdblyVWgiXtzWAcyZNlWhZ4qSnwFMkzr
+ucUkwmhKhCUXQNVikzVM6RmTGRKokLwCMFkHJZpSqhCjG0omQHpOGyK9HJhJXesW+VkFjnWSwxSYm0
+1o6NTphvPcLHeZDp6jjvP3fudJ+8+951rJ05+llP242SdT5D3GgMXA9GRxCKmAxgS9gB+B3gT/hj23
+QJ8r02W6dDK+/IXbnYZxIATwVjXqqEK0yvocIPR1qXvn2xc+v5y44WzYesyDHeQ2YQVEwlaMI0zijI
+yKyF4MGLIxDH2iQgcy7ucXT/NcVlC9mrCzpxU1oToKaiYSs1Ua4ahZuQLEjUWx9B6ilgzoaYgMkWpM
+FTtlhL2u6NYB/ijafONHZsCSZuKZxmGnhGOLy9xetWRuznS9ayudxkc72P74OIOxcacYbmB7Ky/QWL
+28cHy2g/btVM/TW/tp2EA0sPQBTVoS0Dtb1iHXXJTWyb/FstO+YpzcWuyZgG+V92wuh9QbA/L+N2kg
+RpRNNU49U2ty5iI8wnFeEJ1+ffft7dx5YcmVy/eY4Zb9OsJy7MZqS4Ifs60mlJrzRSYOYPv9pDkSHN
+lOvW8MJxQAnf2V1npr9IjR7ynqiLldM48VhQ2sMuMnThjr55RSMCTSMzZTCVlrCgIrdUp1AgRQY1tf
+1DznTGmTZtoMtnFgBihK8rqYIn15S494zHGoM4QMsfa8SX6x3p0VnJsR+h3PaudwHo+Z9V1uT7890h
+YP7vM3f+AcOcH6Zz4cczxT+COgeSI2ltgK+z3TfryZfeytEO6hd23AN+rlGVKLdjsQUNKPaIeGQOWi
+EgNWkAsYLrH9Nrz37Fx5fJH0uan36LFBDcZ0asn5NMZZlpAVWI1kfX6zNVQzBOjOlImQ6kZ89ozmwa
+qXh8NJaY/oPbKbFzSKZt4zTIFtmdjZnlgK824Vo8Yqyc4YZ4ikzhjO84plZbqab51gAZ8GhBnm7DRl
+A515f3OtAoaFTHQdZa15WVWTc3yQFm/Y0BvOTK4w+JWLLan5B1YXepyrJuz5BLEGb1sE9KUqpjjdHy
+Pqacfl+78v4Hwo7j06yI9mgbW2WsSNAvwfTUjNRJBUZLIAQD3BWAiYuIMW4+h3Ibh1fuKjed/bHbtu
+e/WvW1s8RzG13RTSV8rnHiSDXgjRHGUoaJMileDOiEGZV6VVHVNSoGRF3LJGKwdww6W2B3P6UWBHK7
+MR2zHgpRnjHxkbGGKMEmBUgIlllFqgCcCLoOyVoxNaFSyrI+v64boNwZSQjGINmqvoOSZspxZus7Qz
+ZTVnqWbFVhJrK320Kyg03EsrfUYDPr084yutdi8C3kXK2NyF8nzHIwlxkis5m+xMvuXRsb/XNz6Dwv
+LlwyDFoCNA1/bPhN64Ae0yH4ZRb1xeg6y/EURMUfUzbQA36tb9DWz29DkcgMJZ1BsKrA6g2obf/2pD
+46e//xPVpvP5VIOOUbAxjEpVKR6TvB1E6isieQcRjIk1oSipJ6XWGdY63aRgbC7MWW4B0Nfs2oyKjX
+43DHLEluTMbP5jE07Z8fOSNFyfb7HOFbQ7zGtE8NQNYm1rcljLYS2sW2336GqPDE0Va7RdGDrNUlJr
+i1HL9RVhSeBRnKTWOrC8Z5yYiVyx3LN8vGM0A3YvMJZQ+YsttODTg42I3OGzAIyBzGIqREzJ8kUTXv
+fLXr8P0bWf1BY/5hhHRgg0kWTQxRS62o4dMLfWF9GzCthqhfge5WCzzZkgAZUTLs0E4aIY474PardF
+x6eXnnqY9X1Z99jhpfpVtvkYYyJFbaqqOuKOpTU0RNRojT0ukk16gPLWYbVxMx7dveG7OzCuICQQd9
+06Ls+UWCzmOKLis3xFrNQE9YMS3ece6q/tvTUkvpn8l7/uc7S8uU/evrpjd/77L//3Vrrg3CSKBAjd
+JY6fPO3fMuJc2fuXo0+3THaG5+ajEZ3b23u3Luzs/fQbDZ7tKrqR0MIxBhxNgOBmBI2h7X1LneuCHc
+szRnIlCUyEgmkQ6fTpbvSxXT6YHLAkuUDxLomKkHmiKkwpkB1SEo7aNjJxdzxM87e+R4IHwT5EmRNf
+bZWrVf0IKVK1dyU4vSKmJcF+F6dvgaDpoSmiDEBZxJCDWEGfkSx+dx7Z9ee/bnx5ae7rthg3VYsDyJ
+pVlHNh2SlI0aPpAhWiQplnYihRjxIEqRWxCsSG4d5tMokwmYJ8+Dp9hMboxEu2904duyO3zr3yFt+5
+/RD937y9EP3ffrYqfXi+PHjdJ2lm/eoysg//p//GV+4fIW92QzyDnjfBGarcseps3zHd/4n2+e/9V3
+bBrkgQDGZsru9x+bmNpevXOPixUv9C89eemJjY+Prr2xe+cZquPHNV7bGpy5kJWeWTnLfqRWOHV9ib
+bkGU2CyRNYdQLcPuYPctO1tFekstd6CACYh1mNsRZI56BzROaqepOY9Iu4zQvYBcL/UuCVsa52apn/
+EgU1oX0aqvbZUztsWfIojSUBMwJg2arHcJY2u4UdXPjG6/PT32XKXVbYxZoKppsx9Ab5ADaTUVBNTb
+cu4ix7s1knbiM9sQDIdirJmo665XldMctDj8ODxR/+/1z382P/+5te98TcffvCxT9197330T6xjVwf
+kq31cblnpdluvvqEeTukeW8esLLF+Yp2uXaGazyhGOzAe0ukf5/S5+7nn3gcwGknRI0mRRwUxOSkoe
++NJsbmx9e92h6N/90dPf+5nXrzwFNe++Om3msnVJ6cu/YdX5913dAtLbTJO33kS20vQyyBzIBaVCHl
+AugZxDjWpkX42gDGISVgCQoVSoalAdEiQvCti/ycj+vXG1O9D+kB2xIbTWwDLvOZVztsWfHPAiWlqW
+VJBtQd7zz1aXnv6l8vtS2/PptfpMselOeiUyk/xddXszXkHnxlCisRQQ1JcVLrR4MURbM64ipTGsVV
+HLk2Va2VOOvXIH77hG5/453edffh/eewvv/PCmROnOLZ8nMzmuF4fBpZKGrwFLfExkAXAC5Um8rVV7
+nrsIY7dcxab7mVvZ4MvffGP2KmewWTLiPRIgPeBbu7Q1BRRIkXE5Kyur7C8tsq5mPj6b3or0/GI7Su
+XPrV3+eKnys0X/l7Yu/rAeLr1nxbl9nfX4+xNK0lZ7hq6YsAl6CSkGyBXou01G45regY2RWEExGI0A
++2ACEkr0DFJLMmF77OM3yh0vxfufWq/M4U0RRPZDwpQFUQSt4MT/jUJvpeLV40iCIaUPKYcwfDFb68
+2nv0Vv/XsOpMXWLMVUo9JZUEIjVoaOzlRwUdIVommsfFcFKQ22EqoS6FMQpUN2IqWra4je+TRf/ime
+9/8j85+3Tf/9j0Pv50Tp45R5nss5V26ptfEkDZNhvCAp6YvOU4S2MYeTbZElvpkp44zOHsX9698E9e
+vPM/m9RE717fodI/h8iUUyPIOPswRgayTN61XmpK8GCBzlmExpjvocu9jb+Khx95ELArKve0L843LP
+1EPr/3E6NqX3jk1o++Jcfw3+n5GT2qyvIasBOMJrkNmsobxwYI6iFlbCrELKQOTY6xBxZNkiEpFJH8
+7uN+RdOa/NuJ+A5Ebgq8PokTV3kB/vlbTmm5Lybcfr+m9J4333ldtXft42r2GLXcZaImLM0hzjFYkj
+fgEPik+WRKCTwmDkIklw2A1EatELAJTn9A7jg3veuihn/26173548cee+u1/pk3YPp3NKU3gdwsE1E
+CYAViVDxNFGSHHEtTidq6DggY5+gsD+jfsU7v5B1kaRmbL4Prg+nT7awgJqMO4AQ6rnPg0E5AUI/Sq
+I8isNJfImGoGrlP3u/T651j6fg5mIw48+Djv11vf+m397Y/83cm1XPvD8Xsbw365VreqxDjUeNJhiY
+bXg0kBykH6YDpgGaNamkMxiTU1CQ8ikGRdav6vyXC+61kn3jpzVNf08B79YJvvwqD9e3yAchQ7SAJJ
+ArYCLZsJzEj0iGmhqdYtQEtrzLa/cxH6tFnf8RMn6ZXX6cfZ0gSfJ0obZ9pp0dpA9YnlufC2qhGxhU
+lV1HXpzJ9rqaMzbpDOThJ/4GHx71TD/3kfW96x0/nayeLwYk7sUsDkgMvTZKgQ8lxbZ/0ANpMglODi
+rRqZ02n1yrIyeJiYnloeHh4kjPXTrF5WgkZdPo5xIKODUg9o2MgaSK0PWj3SQyR5p7d5w6DHDpXjq7
+tDDi2SvI9smOnOH7u8WvzyfWPlNPNH9+bTr4/K/wPZo6V3ul/g8O0Lc48SAVmBq4HdkCswMgAMdrcp
+ImmbTx9guN3ENP9OKyfhGM/CisoPSIdVBwqTXaEIbZpW9I0isEiWJLsZ078yYApC/B9te6C/f/slxv
+j+2GbakEjSZp+JAo4Azq9wGx67aeqyZUP6XwHG0qESJSEswnNlTpUpKT0nMUqkDxBlV43Y7V3jp3xn
+J1xzYQeq2fu4aGH3vrROx/9hh+zZx4eki9DtgydHvsmTRZBTERECAJW0k0exsNhxZJISPIYDMEp3kQ
+K8RR4MitkxmBMw8tHX0NsAsWN2T9iOrg2+6CT/dOZfXLDHqRN7Wt5AuAskvdxA8Pyas7yfLmoJtt/b
+z7d+fl5Wfywq9Z+IDlwRKyNDetJajYTX2Ftv81yaG8KaERN2w5bPRoFMdMfQbIVcB9uokw7RBXMfgG
+q1haUtsOuIK8gFG0h+f5sh6V1lBug0+oqDXOmZr9ymG1CqVTa8KoKp03C53Dvkz/rp1sfCNMX6NSbd
+MIEazyaRbxJBOtxNtANHkJC50qswbgOMe+wOYRa+3ROrnLs9P3/6/GH3vjfZw++/nOcvB/cEtAjkLX
+2C809kWaVByXkiUQi22dJ9cbNoyEhEl4jmc0JTihsZCaeWRbpSEKMtv3VI1U9b8kfMPaw6bS0f00b4
+bKPdTWpfbW5hnqTOBDTgN9gIetBZuj0u8jy8tCWxQ/aNPsVpfi73k/+o8gYxwxjQTUQqXFm0Pye1Ep
+eEsZEwKMSkDRHqUjJIzZ9SIx0IP9bhlZl1X1Hu6EtGdyUtDiQ1LIA39eMUJF547DVjJuFh0pE2x0ds
+RhjMeIhjonVNn4+J3sJbgAAIABJREFU/NlUfOYDzIfk5R7dMKUrFUYitVWCicTocSZh1aNlRNWQXId
+5EPZmJTtylpN3n9u4/9HHf0Duf/SfcOpuyFaBjEnlMZ0ugYjRSKd16DdxlglEiSQEPSKb2kWv+w5m0
+6Y9WRQhWqU2kXmm1B2l20qPFGvQSDkbU/s5KQasNBn3rtmBjli5h6RiPKD19QCeHKE4BAiqaFSMCJn
+t4lxOvrKCWwmYSfY50vi76nj9vwrp6keTyCljSqwJGDJiDIh4DB6MYIySSFiNDfDjtJG2Mm/iZ0U/A
+A6kBWBsxbc1bXpuBGl8s41/cAG+ryFh0qhjIhxGRQtgpM1gO3zKCkANYZs4e+an5uPLH3DheVwqcDq
+lpw1IkiYSihdFxaC+Iq+bWibRdBipY6w5dZ5z7Bu+/Z8eP3P2b8vZe7dZPtYSDTlITt/mBG1URyMGQ
+0JpJFUjftJB5rfZ93UdyaK3R1RqJ225Bm0kurTEIqmGUKOxAgJlNaepyZluTS+puQXlZI58hxslbyO
+Vs0b9pAsonsi+NdntPAQ6Jo8r/4TY+z986v5MiLt/3eoca1oVX6vGpEw1ooLR/VqlCU1jjLUtW1pBi
+IB8ANOpMJ0Po71Gapo2/pNmbjD7W9YipehrNmK7Z7tDjvpAcqiYg8zzxtyKiB+ixYsf8ZMvfShNnqe
+fxmgscVpiUmx6HqREVEXFNZ2AEjgMErvsjj1b04yVux/jode9+f2Tx5/8RKe/3BAMCKlOmJSD67R9G
+A4MLwJKTSTRqJj7nq3GDjOHdSqO/pbUSC2TBJzgIvRsRs/aRnUOnhjqJspGhBBC6+iX/RZINyauSqu
+WS2Pv2S9LZk1HFDnTxp3LQV5e0ERKbeNq0za1dl3IeuSpv23Cyn9Zh+v/Noatj4c4otcFk+qmxIaax
+vYODqKgSUhujN23CdVCjCQVjMs+hMgYWf1RzKBlgATIDtzxr6Vws1en2vlSmdCt8RKOTJEPu6TJc+9
+jfPFHtHge569hIxAFm1rbMQWSCjZZjOSot5jYJ3rLtHSUrsvKubOfPfvGd75Xvu6tn6q7ZxDyFkSCZ
+IlcHfhIrCtsp7VDTaNm7meTpta+6rYK5Q3kkd78O2zj/EuJgeQcz/usZl160RKDPyiqiyg+xTYKxbS
+M4iGQ9i1D3Y/AwbTf/Oj5jtRY0YTRhtiQNpLHqGCMO/CnRwtGOohkYLs4WQGz/gnPyqdSuvpLyvANa
+iqgQJI2dnnqQuo0THQ+B8kgGdCMpAG0CfcTnf8I9uQm3PEJdBW0ByYjteqnvobaW79K2c7OgdUkN/U
+VkNausQYsM2J9/dt98cLHmT6HrTfpM8FUHVJSotQEqcFEUhKcZOTapyoFX+UMx0rJEicefOJXV5/4l
+u/hjvsKasF0+wcY8YBR25wvd1h3ZGGL4MQcQC0QGtuHnMOaMY1E0v2sb23ivg90Z4XMZKznfdZsn34
+URi3wQghoagKkkzSbUkwRZ83BJpUOKIvDQ+b70360sp+mG8GvjQFqjuLUt691laAGSQ5DjrErOFlG6
+HwqRvuOmMI/Smb2V50qIv5Q8pomtlNMTdKExPyAmVWzAzIlMsTK9ONodRmV34CcGDKikYbDIZG/1sB
+3tLDrrRybL9f26o/jEH25CJSXjVAxDqsJlYi0/jNSE6lvAavg8IhuPTqdXviVevw0Hb9BHqeIn4NfJ
+USP63ZJpmY+HZNj6CRHmM4JswHDMcSl05x93dv+fufhN3+YpbtAl6HfZ0X3yZ1WmphmXdZteUHVgJN
+G/TSAbdVKpzn4gHZa8kAEpKmNWbU5bM6AltB1NDaRb36fVpHZ7hBnB9SDQdNUM0aoSmK0iHUETZgYM
+GIx4g7jTTks/qRAaIkd00pc2S9Sqgl8aM7bBLG2z9/o4gkkjEgjuBKkYBBdRWwgz1JRFJP/zMTqp3y
+qPiQpkhEwWjUbjQkELTHSO5BgST2aiqaqmdlkVmzR78VfEbvyjcSVp6CLNU1MbqBC94k2ubWvT1/OH
+6GvbH3eqpnMV7O+bz6GO/rCX5QKxS/3HSQJxtiWSq9bQ1zaSAvIUkLDFuX04i+H0TPrprqG9buYUKK
+1hyAkLFNfoXlJNrD0Uo5MHTY5ikli9eR9LD/wlh/iwdf/BMfOkOwSUfqoQB4OzSkVmqrSbU55Aqy4w
+2jFqNgUW58jkFwjicy+2zkREWJLFhmg26XJWKjnzTMB6nJO9IGUEpkzDLo9+v1uQzKlRF2XWIROp9t
+8NsXGxhJFbNt3r2mNSSA/IPGlrYZtDDhjkI5raf023We/h98NpE2jQps2takJSHGIDIBj9HoPkEL3w
+7HubqFbP56kwEhoik6RwDbBAJKkFbgBbIExU8SCsVO8H6xnaf2Xxa6+w2oPHzKS9dibuiztO+5fMfD
++hOvvZuHzUs1Fb/X5l1rP7uY3vZI6ni91kldaA/Tl3vdy4LOpZTFl/2InEgHBYlSwcUQ5fv4Txe4X3
+h6nF+nGLWycoqEE39gW2IBPJZo8Wcfii0Q9KYhTh1s+zfI9r/ubPPaGX2DtLtT0KVu/nblpBxVpiB9
+7YJHs49K2722/6JEAfm0dx1E9QSMYiyUjxzblKzSBLyDMweYwnzOa7jGtZlCMkXyV2XREVZUQPcZ28
+VWJL+d0yKGqGollLc4KzjTpO40rXKlCxDmLaVVdrNnfxg4k+kFFQLtPc8QDTtSQHS73NhNdm8A5lFV
+EcqzrIaH/E1H6E5Gdn4ddMGPQEpXG79g0+GxYUCMek0rU1DjxBH8FwvG3590Tn8D03mdjF0mCtY2mc
+HQN3gy4l11fXyVpc6v2AEcfH+1S9cey+f44nUn/pJLyZSXby33pVhtCLJGGZDBGMaaCWMP88nvj+NL
+3yeh5OmGbrpnhYgU+NiUK4ghjPZkoSS2pFHb2avykS69zgpNf943fx+lHf5GlY2Ac03bh2YazBBdvs
+o9AVHF6hI61rSonN15lVZAUcAYy0UNLLHn8tKAeTxDvcbEexNnsLWUVX//czviR55979r4gHula+ks
+ZOzs1KZTgIDeJK5cuvPj7//Zfby0hV06vrV9a6fafXhks/RHdzh/QdTP6GS6zoIG8dxxIhNRE/9AWk
+lKagsLuyBc2R5z1+56drC2QpHJoUR4GrPWBHmgXMX2s7f4C2gkq+j8iHpGIamgiXlqXkW0rCxAbkid
+Tj4YRKV0hsf59puM+aczJXzLSBbIb1sefhbZ2Kwy8Ekwc7U71Sr7TV0243OrH/1mrrkY4Qih0G3cCC
+Sgg7T48Hz3zc2lygbzaoisVOYEUEj427B1phI1CRyHFLlUtlJMe3eX7OXnfN/5NHnvHL5Ktg+lRqCB
+isEdyA8qWUbStH1H22Yx4pPx5MgcZ59q+FFoZ3Q+xKfHgmwrXlCVhOGTvyvUnh1evvHu6ufmXs1S/d
+Xt7m0sbm3zu2i6f3Z4RTtxD7+RJlk2grqfU9RSKERvPX+VX/9k/vvu3fi2/u1f5J+4/eSf3nDjJfWf
+Ocufpuzh5+tSn7rr37v83O3Pq/2Z58JvIDKzBSeuwbsPUQsuGtl3jOdobQY644yW2Es82AFL2k2JzI
+jkSwNJBshyxFoL+Yki1A//zog7STlPZU2qMaTYEUgahf3DBslBR+WuUlaU/kJ9jIL+NnPwSVUI63a9
+q836lNt8fR7rdvCG8kk3B/XFVwj9NCfgn35oOJU5DrxsSFXUcYYvnPlbsPdXNi8t0w5CcAgioT8QQC
+Ah9U0MEVxl8mROrHl13huN3v/2HePibfoHeGdTk1NZisY2/jyYoWtQQJR7MYcQ0sfpiGpZyH22tmpm
+SIpaDpiqIgaKCvR2Kay8yvX71yXo0/Gv17u53za5vrs23tqEsMAaK7Q02r1zhwuVNNjTn1PG7yHOwL
+tEfZJw8tcbOtSXqnRFXLj7DKFQci5Bdu4ZdP4k+/yKbS0ssrQzeevyuE289fueJD/VW+sO1Bx75tWM
+nT/2L7Mzp32RlDYwF63DG4Iw9KPLHkQYy0jrkD2NEE6i2Vb1N6wDIGvZVW/85A8juAJ0hqfgFH+Ny0
+v6PO7fX2HmprasdXbMz+W5zXwIiAak3CbGkVNPtuqWPkS//B8T8K649Qf5U7L6vBg+vlKR0f5onOto
+W66vZmV7281oB3QM1LkkTMjWfbnwwbT/7nlC8QF5vYutJo4a2XiJVIRIQmWNqgxQd/NjQc6dYvvdtf
+597/tJP0HuAQrt4m2GBjERGQmJqYxWhk9mWRVQSBm8EPbKhxnbBWtXGPk2KpECal1RlSe+ZC4ONF59
+//+aFp98737j6qJsWZPM5bjpjuZiT+Rok0h9uszyZ0pmUKCVaFxSzEWa0RVVPIFWkOMeIkpnIshVWj
+GBnE2zWxboMZjPme5a94TbF1Rewzq25Zy587513n/3eex58+KnVc/f8EsdPfJyllRm9JXAGZ8CKaWy
+/g4Brc0TNrg9tWFw7n47U0r/Slg5tNJQMslWsnqIO+hPR908489SHNNaEUGJjxHiL+D7UDfhSmhFkQ
+qljqrhLVUbUr7ynt3L8g3TXPnYrhv6l7L8/TcB9JSLmK61ZERE9fENPmgMVr9jV8Oe1W7yikWqQHFV
+DbON3vff3TabDn6z3rrAUx0icIqGEOrZrRA4CSUJdYKocKTNc1aEzOP2rnH3zh1l/CFgi5IelBM1Bn
+ficI+Kuec3YFvjtxn1EUcuATJqQMMqaajRmtLGxMtkd/kD1yT/44Gjj6nKxcY1+PWcZGJQVrvBk85o
+uiUkxwQ3HdMuKbmqOlwOZgLWCMeB9RZgMkQRdJ3TEYuaBPIMlY1jPM1Z6A/KOJe900JiIoaS4fp1r4
+zGTzZ1Hj794+aMnH3jkI8fuf/BjnHAfpefGGHNY0u9A05BDt4Np07hkP5nWNoqpHrg3CandfCwgPch
+Wcd7ja/fhFPRcivVfTfUEao+pM1xtMFUO0VCUFTUTStnCG4iaKKcnOBUe/Mn8xH2/Dlz6arrkyks3C
+UhH1m9HRPbz1dZEZNZO8TERWQMuA7mqPqSqQVU3gHuBu4wxW+3xHgeSqu4A94vIOeAZ4F8BTzXcfDB
+9iaIk5tLk3giaFCeNgh9KxMQmUxPYMeGgO52haRuV7cdNaLsDxcP5kXaBHmiLDcF3JLjpkF1LNz2+l
+bY5dT2WrCEHuuUYW41h5+kf8xc/mevms6juMPVzbL/LbDRkdWUZrSMSPC4lOuEBtvdKtuou6w9+w2f
+v/Pr3fA8n7yfhCVlFB0enVaYEiEZucHd5tP3VYFKiiyG0wcwekKgsKZi6hs3r8NyzuMvPfdhcufTfh
+Ssvrg2KbU7UEHYnyLiiqxmxKvGxxvU6bO/uIcYy3J1TxUYF7HYGhAxkxeHSEK3HGFUGa2cotrcYT3M
+GuaUT5tRqCHUkD4HV6OnOazq1xznX9Fxfyumh2Osj4m5BcfH6sr3/0t9ZfeSRD3Dv6b/HXad+in6Xm
+TFEDF3pNo5t38xKMA3pYWj7zRMRIN/v856aKAfV1IRtsgRmmdQ9g5qa8rnf+p6Ujj8ymY3fsLm9waD
+XJTeGrRcvMBCHqQJhpiR/Apd3yQZLXJt+hs215/O3nH/+x6aD7/7PnTEYYzoGU7VOmxzVgaruNQSuv
+SdBGVLYxshZhzsJbHpiqsget41M34B4nyBnLGwJ0aZUvz4zRGLcc3C/GLmLFDeoqi4hfh1QlfnWrkl
+6j/PhjPH+ReY+ow4PoBIxnU0/nJ6oxA0KsbO57SRZXV9eO3MWZOkLFenasShBRHBN3TbuxfJXCOmhe
+lK8kCRdNJbjucNA/Bz4RMedoI7XmIyfO35icAqs06TPpCC1VXc3JgzB7aImQ+yAyLDhoLUDVC7UjY5
+oxGCzdFCcsa15KSJou9Ua85Uj153N0JiQELC2C+Od77hy4ep3b17axPmKoIlMG1KyLjsMQ6AsC7Lco
+GJIwTMsEv0Td3HnPQ+/l8FagVpM1m0Dec0BvX60n9GhVLOkFKk1YK29octcjtK1ApMZYeM64y899eT
+u5z/7P8Rrl5/ozEbEYooNNeoTqYqkOpJiatVnS/IROl08Qr6ySpzMmAOTqqCbIikFOp2MTsciLhHFo
+5LwyVPWkb4Gsu4ynW63KSPhGqlknSXLWqYwyxCbgRFCiISiwF/bZmazNR2OPnpHFf+L/K6T/+1gde0
+3yZoolBgb+87YW/Wbb6+SafuqmUZsitjW4dIGutqmH3zgdPH5L372vdvb258cj4eUxRT1gfloSCoq4
+rTCNoQoSQXJOkyqimMnT5Fl93z3I39lXnT6/UhmniPEjKRvwNqalPaoyvuAu3HuslFyF/zjpDTHmG1
+SOi11fVdP9Wq79k7XdUUK9V4KfjWG2sTgVVVDDHUmMYCGqD5YXzZpW6rKXrhOMZ3h56WapMdS5ZmOZ
+0wmU3zg3sIntouSwuSDux5+HW/8xm8ql1ZO/EZ/dfmjFvf7+6qTCz7hjA0YlqpUfevGePN1v//7v0t
+ZTCYrvdycOrYyyJOfGV9tHVvqn7xjbd3ygr9gjPFG3FkVc0Vs53nT6R0jH3Sw7vMELcGcwtprOHcRY
+9ZRtaj+ESIRl5/AmCtgLqHplAHBuc+Jyw1GTjIbb2Lci1hzByJdMM+3qFzHmFnecTVFaBLs5tPq4qe
+++JHf/de/zXTzixwbVOQyoyORfidnHxp1rDl2bA0xifFsgnTXeOz0o+/n3td/iv7xJv7QdJA2/lKOE
+A2N3RMPOtCikLB4E4kHCZ+JTBM2CTocM3rxMnuXLv703jNP/e3Js1+iu7vNegwMFOaxRH0T+WJtjg8
+BtRlJEsO6IACzsmQkym5o+ujWAqbTZHGrlKjU+FDgfYlYxWWCNYY86xCtEl3TOdCnSMdYTJaTd7qIQ
+rSdRiUxGc5ajOsgAdJuga+Umek/Yefyf7q77c+wsvL90usgInjTBGwfePn0JjNlP33qSHaFtBRNg8n
+/n7k3DbYsLet8f++whj2decw5a8ya54GiKCiGy9iIeJ3AFrBDxBuBjY3YHd1BBNGhtqKCVyIE2w4pR
+em4tnJF7QtGKyiFRQ1Q85BT5XTy5Dl55n32tNZ6p/thrX3yZIFfbDvo+lJVmZVZO9dez/s+z//5D4p
+IBhozr6L/7c1vP/rYsZ89eeLYZ7vbbYIpML1A5EtuQVTtc60tDdSsg5HxjKz7LMI98lOjo6M00hrOF
+igPSRQHEZzI+wNsnoVYRzcqITCmwBlLCOGg9x7rClpZb48QAZzH2BxnzLjzecnxtVZ4m0WuyEtjZGe
+UNwVFUewUHyLHGUev1xVb3R6Z92Qe1rt9lre7FHHKzOGr2XfkCq49fM3Rq/dd+btj6dgfEcQagK+el
+w5BeCfCcSnFr5iIv3Gp/Nhm1n7Hdx5/uLVw7CVaEiYT3WgF0ZhIE8YbDeZ1uD5NU5K0HmSkJ5SObkr
+qDRrNEeKkdkdpAy6dkpGK45hIxUYIpaWUQkrpXXOiLaUcr76iC0Jp4ijdoyK9JIS6gFRTUquaUPHzC
+FUg2AfqPEqdRspxW1OxQj0rVN30Fxd/+cRjL7H4/CL9rS3W2Mb0V1EyoIQkjlOEVOhYMz4lsd7QTR2
+33HnrH4/uv+VzNOdBjoBPL6PsDmPExM4iePi2lTsDGZdyl4KCgCfBorICujnrz710++rpU7+7dX7hT
+tobNK2hiaRlPEme47XG5AZvJcZKusbjRSAjsNrLaI6NsrzdZ90Flo0hB0KiQQaMzUvwxQ/Iiw4u2wQ
+PA2vZdgHhAgfmZhG1BNFMkTouS0BHFD7graMWSlqAlBod19H1BrLWRKkU52LUagfHKmrgPiJm8/vZM
+/MzshU/GYSgAJLqEBqCGyUN9PIkJMTuG7JESX0IZVczdgOHr8swf/vS55567rH77aB4r3BQBKhzyfJ
+iSJ9vRnV0UOQXJC88sQorf8xIs0WjlqKlItWKZpwKFTy+yBlrNEWqVZmQaw3B2WpPWyJIPlsr52YR8
+N4SfKmDFMKhgkW6HOEtwReltX1wRK40HPbekm4VZM5AYbBFRmYsfR8wSpEkCQeuvY4H3/mDxc33Pfj
+fmZz+JLXRRxEaslDupnQ5muko0riKmyhT/fjo7MTPvvEdb/qHgwenf+bbf//1I8ce/Rar58+i4xpFr
+cb68hL1rI1vtQjNhpC63ABlSYxptEjqtdLXMihFkEgZoYSOyn9WKBVJ35gcF1WYYgjsCUIhVQTIeR/
+EvPG+5CYq/XqPJARCQN4ohEBKGfKJpnCFfzdW011rs/jyacIGuC3F+nqXZnMECBTGImSMFQERSc4ub
+ZKZnMl7r7w4de29H5EHbgBXA1GHSFO4EiIXQ3uTcGmlcRmI5i79u8WW2y1vsReX6J84+xObzx/7/GB
+xUdPeoOYtaZ6T5gW6nyH7A/JIk2cOKSKciihSTRFFdDCsqR5nN7dYaW/TMZaztmANGODoFQOCy8t5W
+wyItNsR8jdHWjQD0O5ybnOdVDgSKSjqDaaSOjJOGEnqJErRiJt4qRAiBhUjiBBOIgpB7ANprFBtgwv
+bBC/u1JF+DDX+AVHXf6SE+se2r5ev0XaSoAShCuUU1crGOMWBa2/njle/iaeePfGR488//0YT8lkP9
+BDEOi5vcRWhnYS4UTF3HFknsH5umbZcpZ7GjNabjKQ1CiVJpCAm0FFtrJLESiC9QwZf3fCqnHllmyB
+FSQn0BQSLV6VjOcGQ5Z2y6ERFIJCOEALO5BhnmcwU/U4Hgiet1ZAqkDlDfW6ewzfczL1vffvTh2+/9
+z8zOfeHWNHbATiUqDSK5cGkh7YYttJXp1FtTc9M/tb0/a969PqDe3/xxcMH3/7M178ed86dI/WBuk6
+p56vUQ04jSKQD7y2R0NRUThISIh1jfSB4RRAaQlxaqcsYJSP6WwOElAhRra2FREiN9RLrPEJEOCHxT
+uACWI+wLuB9IIQgtluaYhDAxQiriLswJiap1SStmREGRRfjyodWBEXfFJjc0+5vMT41w76bH/jYnhv
+uW6M1j80kUuoStQwVMUVUKGfYDfVcGl3QQ1JvICIQY2Frg/bJY/9+7Ylnf9ktrZBsbJEUBZG3+O42R
+a9P6ktl+GDgsSjQMSaKWA+WC9ttzm6us7i5wUp/q1Qf1Jv0k5ioFtMaqaG1pNlImRyt0WsnjDajSnY
+OQQaS5gjWONCKdec5enGJJRkxGafsG5/k4Px+picmGScpleEyAZXiZYStDhgZFErFEJVkNz8wmI22R
+okvqMnWgbhV/5VhV7mDGsrvxRCRVcBJRT8rY5OQUtLXnlpS574HH+Dc2dNri+fOfuziRv6HzTSlk2U
+MQo4WEc0oKm+ioo8WnoZQ1KVkc6MDwVFPUtyIxSR9YgENJWhEGpWm5Q2HRxGIZCjzFSMNkSSvuTIqM
+Bh8MCjp0TgEFu8zorreIS2GapfssFgFRW5YMV36iWfLedZsh2xsgsNHjnDo3vv8/I23f3nP7Xd+kqj
+5eGa99zoi0RWKUIVjiZ22cxch1VftQUyKSMKje/bu/5fzb3nLT16/7+AHTzzx+K3nXzjG5vIyjZkx4
+jghisseXgtNLZLUIkkiA/3+JsILPBohI7xISmsHYUBHNAa2/IKkqiDsCCk11guMBYSlsJA7CM6DlwQ
+fsMZgrGN7JUfJFFdEmEJS5I5+v0fhCmScsr3ZpT3IcTomE9DJAoVw5D7mrlvv//M7HnzbFxpzh0HW8
+VEJBLwyoy9Q5thdgl7lkMS4o/FUeOI8I1tdYvvYS7+x+fSzHzWnz9Bs99HdjMg5grPkvT7O5uRa4YU
+k0zUGzrHZ67JuLBezgjOdLdbyHJOm7D1yN5PTU4xOTy7oVv3RIo2evlh0jy52239W1xJfdAi2TxpBs
+yYIkeZNb3nzHW978I2H6qgj3cWlW+3m5r356tr+fGWVfL3NxSzHdtps6YjECXRaI1UpkYiRKiFEETK
+pIdMaQSlEpCFKStex3BM6GUrrXxYqniDSv7CL6LlzKA278/LlEpdZQ4UQSo1HKMkIBsPcgTne+JY38
+OzTT3zhq1/563fnPnuXoVxTBGtAeyIHkbUEGYhI0DbDGEUaJ8Q6KWdY5xFSILRESolUIIJDCI+S1d5
+SuYqSKPBBE4IjeIFElmEwFXBmiSgGHZywWG+w3uBF6bmTmYIsy7gQOXwck8cJjE9w4IabueaBB5/Yd
+8sdnxNTc1+0spkNkLgoIqZW6ksDeOOJlKRSfJVLdgUkaCy2rHBvSaVG1kZ6RPXf3Xfn2FN7Zvf94qk
+Dz/7A0Wefl/n5fyh9J4MnDo7WUOLvLN4UNKMIHASh8SrCCYVBlR9CBlpxWXTOhfKGDKakJTuBM5X63
+AaC8eAFIiiEC4TC4KwhjQ1xlLDZ6dJez0DEOAKdXkbP9vCJpp05Qk2QIdiyYLSkMT7FHQ++/uNX3XQ
+bVicQJHJXhJz6Hq1UEENx6qXK7HiIBSTBItvbrL700m8vPvrYh83p00z0C2r9gribo205RQovGKiIL
+RzbRYctH7Pe73FqbZWVIseNjhIfPsid1x7h2ltufvi6W27+8+nZ2a/Wm/UX09E6XTPgO0ef5Utf+Qt
+st0NzrlHKdFxB0S/9XGZnZ5981WsffHJ+fIoUgW1vUWy2r+8sr7xl8cTJd507euI13fUt+kJy5uVNa
+i3DRJrScqArNb0TEqEjBiIQi4ASAa80SqqSydC3EHofZWY0RvBzO7jK7uy/nZtuF/F6SLnaxQ91BJI
+o5qZbb+Ud73gnR1889vGjZ868S2jQGrIccuOIiEijmKaskRZAL0fZhGYSM5Y0SQTEzpNqTUPHpBKiA
+FEoV0WR8MRaVvYWrvxgeUzwgeBceSPHlO+B92ALalGK9wWFFxgv8KqMW5PaoKKE9cMNNvoDRuf2cc+
+b3uyveNVr/oqpuU8SNx51suUMcUVEjMpLLQhSASKSVcb4TvGVT0xVaJSvAPbSc8OXfg210Uflodp7r
+mpNvmf6yE0fWnwqvuvCmTNsLS8zJkEnMSFclcyBAAAgAElEQVTLsL0+0gZM3qdZaxAlKbkXFMZhRAC
+VlL22KZBSo2QJa1hX0rAioYgSTadr0FJTjyIy68kLj7UWUxQUucGYrDQosim1KKaXOTJbYELACMHFr
+XVcFBO0ZBA8F/0WI40Jbnngnl+/6f67nk/qjYoU5odr9J3TCMA6uyNIdVTzZygTgbQqldwaT1jZYOm
+xp39j8fFHP+wvnGckK9D9Ab3VDUaiJqGXM8hy9GiTrrCc7G3S1YEzFxZZbm/QlZLpI1dz0wMPdG589
+X2fO3Dt9Q+Nzcy8mDSaCCUr4qgh8QkTUxOM1uvEiUb7jEYsqxcFigzStE69OUrcGsEai05T9NTsi/X
+DV744e/Mtn7pldeP6pbML71+/uPKhTfdY69zSRZYvXmB/HDEmFKmIUPWy+SJK6HqHDh4pBdp54qKag
+YKhaHc/HCdJQRL9wk7xKS6pJLh0Iw6LUEu98wNWSFLKApDUec39b+Q7jz/3/KmHfv/XpdIfa2d9lNB
+oH1OTCZFPCIUiISEmpk5M2veksWeknqJxJLmgJgOJD0R4arEm1WXBae/RIpRWi9ZTeEG9lmC9RcvAe
+KOOsz16nQFRBKY3KLkDwWOtY+B9+d4KSQgxq/UJrr/nJnfLPa9+bOzKI7/D2NQfE9eBhKIIECuScgt
+caktDxf99hSxGD+OCGQYoBlWuz+UwRSZCqABRPSOp/0FzbOrYdRNv+8XaiePvOP/iC9KtrjHIcoTto
+5IYKS2pLpEll5fCTSUjUp1gpMQNeUcyVK0u2ODYmenKFMeKKlQJVqUoX0atEM4TnMd7S5Zn9AeBTmY
+ZeEPH9en6LlEzpe8K2v1NehI26XBw39Xb9735Nb8yd/Veimo1IIYeyhVdYJiYIxW74qKjHacFKirbw
+HeJs4L+saP/fvU7T39UnlqikXXR+QDyjGa9xvb6Nk2RktZHOLvd4RR9ToQBR5dXaK+nXHPzDbz29a/
+tXH//q351/w03/Nb4/n19kTbKT1Be+JW7Q0A4i9aaWEMqBc2aJlGgnEFVB0KsYhCKzCt0VHYZKqpSe
+NM6amz8xX1zc7840+l+ws7v/8j5k6f/3eLL51rrW336W1tMeolIGihlGBlPCHGMiyK8kGUQSoCosJB
+bQipBqI8SRRvAr+y0nvry9WwQl9Y1lxGaK2ArVgJRi9k7fwWvuvd1PPf8sV958fixnwkuHXHWoq1Ai
+5iEGk2Z0hApTRXTKhyicCR9y0gtRgqHNAVaOVIRkXhB7MqbO9YSrQRxJAjBYYVHxR6hS82jMTndgUE
+Fg0wEUZqgRESn36FvHCaKsUAePGmzxfjEOG94948yv2fvX7b2H/oUrfFHEUnJPxIJtUgRnLwkLduxC
+AmXuHpVBZZYZZCXhh5BOShXg6YVpf+WlgJU5Ega/yDGrv+Bw+N73zsxc/j/Wj1+9J7OyVOqXywhVEQ
+kIA5lgQgf0D6UPpBClR6a3uOjMo65TPvxGFdasgt0RU0yeCkonMdYT+HBBI/Fl6RmKTAOCmPoG0dmD
+T1XMGDAIOTkHtqmz4Yt8HGM1hFH7rz+k69+06u3ZCuqhuuww2AZvhFDAEEisZVbyHC5LocKoQCxGTB
+YvPATq8+98MvF8ZcZ2dqm5gryojwxe6aMZu52MgwFy8Hz3OYqz9otsskmDzzwDu5+8LWfufuNr/1E4
+9D+DZIYh8IBxcCSpro8lHxVfKJ0ftaA8oY4glhZlLQlCQmIVUmKhhKy95XaQgZBrASRkjA+Rjw21o8
+nx3/lmmsOf6750sufWHz22Ic3Tl+gv7aKCZJ9I1dgjcdpXybOWtBG4rWqZjGHGOR4IZFS/TJJdA4p/
+qiyGi0d1v4xMnz1fOtyV0F6UKnmjjvu4DUvPbC1cPb8J8n5JYGn5iUTKmUkJNRDTCOuMZo2GJEGYww
+1nVKPEmSwWGfBC5SQKCkJwVZc3kp1HwTOB4x1GJmjQ4SKSx1oVhSlhSGObOBRaUxPeXpBkEkwKqI+O
+cGBI9ebuWuPPMLdD36GevPPiNLKHEpWORWVT6m8dPiEnUWx37WOkbuI1eEVJ1P1tg2Nd1xlShQA7z1
+NX0eON/5ktDZ1brQ18282GnPv2mqeIDt/ns2NDQpnGU01dR2TBo8xhtxYNIFIKbyUeAc2WGwozWFLj
+01QWmMHBdYV5CaQm0BmPcYHcmvJTY7XksJb+tYxcJ5BMGTSkGMx0tHOe3R8To7DC8HeK/Zv3XbvHZ+
+ePTDPoOgRx+muE9nvMqy87Ecr0VKl7fKgREA4T7yxdvu5p57+fOelo0xkBeNFwPZ6ZH6ASWNWum1at
+Ql6ec7KZo9zZsDLuSW96mrueevrn/uJd/yrj8wd2v81OTeBVYGezdE6IUJSS0rGX6hWil6UWsWyQzE
+IFzDBIGTJ4dSq7AZV8ERCElVroyFGVCUPwrC1doGiIUnSqY35RuPnJmZm//z8M8d/6+UnX7hpNeszZ
+sqViNIS6SKcDdjc4JQijkvGjM4KnChRarz9PLX4RSL95BB0eSU3MFQD4fDdU0LgnccF0EJAJLjimkO
+85jWv4qknHv30M99+8hdSGY2NpTXGRY16EVC5QQZLFElCocsxKYkujVBKIOME4qgiwEqc9DtKe+Md3
+nu8EMTelI4GMiBDgfWDkoMqAwNTYHNLoSOyWDHQmtbefVx9y+3M3H7HV9i3/zdpzT2KrjaRjtImvAo
+cDVXtuF2+POEVUpx0p+3cbQ8gLqFWvvryA1wW4iSlwPo6cZCGuPYwe656eGJ05ocm9h/68Mpzz9538
+djRqNfZIgSPEYLUlbptCUhX0sh6Rcn7FxXxWHqFcyWB1psCpUTZngaH8wYfwHmHcxbvCzo5dAcF2wN
+HpwgMgicXhlwYCixWOTwO6z3G5Ry58chnbr3j1r4Qcif55zIj2WFfOUQLRDXzivJze2dLNXjw2H6X9
+lPP/u7y49/WyZkF6gMHm1vYvAuxYLXYpi0lq2bAQAleLnqc2t5m9u7beN37fvT3rnvg3g/tmbnekyq
+8khg8Wqc7i+UhP3Z403qhEGiiSBGpsrgKv4mMLGlNksSQZUCRI60lGn53cpe6YvjHLOcKnIzJVSCdi
+EibI1+7amru1nR0/HOnXzrx0+fbm4zIQCPWNBp1IhlhAtjcErxAxxGJc5Dn5cEgUk2sfxe4i8qx0Iv
+wXQqPIRpTjoeGgEUqXa48coeoaw4d3suRa6/qXzh+4jNy4D5ed566dCS+XIYZk5ObjCIzJEmEEYHtr
+I93BbVU04g1XitCVD5bpQJBeIpQgHMopVBRTNPn5PkAby2I8rvVWuJLoxiKADaqU5uYYHb/oezALbd
+8s3HT7Z9hcuovEIJyviv/TEHLnRHJDf1x5OWrYf/dLQBDPchug/+y7dTDX+SrGVGidnk7ep1UDzUgE
+glx9Jek6epUEn1Uz068c+3kSQbrF+lurJMUBU0FKaXnii0yrBXlg5AKrUuU1BmPMRneFyRpnWA9prJ
+EF2HYJjokju2BKYsv92ROYISgCI6cghzDwGYYAkJJWqOj3HXXPZ+94vA1BASxqjGM4RBhF0S3CzuXF
+YtfVYZMerg07ndZO3f605uPP3WnWrhA2uliO33c5lZF/VJs9npsNxssZT1eOr/CSi/nyL2v5p0/9VM
+fvfOtb/hUfXYajMKJco4IojSgsN6g8gJFBDJCiPJWs0N9mhRILdBSIBOPrgmiNBApyAVIb5DOgC1n2
+FAFyVo8zjtE5Q0hdqhzGqtduejdO+73xbd90I42j144cfY3V7e7DLoKF2laYhQda6zz+OBA6PImDhY
+bAkoIVKTvJIk/jeTnv+vWC+VkP+w6Q/XeREpirUXqmCIYkiCZ37uH++66h1Pffv6z3cW1j7utLkJ4E
+hUTSY1UEVYIamlCVIsRkabwFm8NkRdVEI5ByUCkS/K7FKG8jV35AZRSYCTClN6sURwhYkXhDZ1+Tl8
+qXKNOc89B9t12O5O33/kVDh7+NPXWY2UvL3Gu7IZKFUcJxiBFNaeHXQYiofIdF99TKqB34Jfhzwu/Q
++AIuMrc1SJDQFYWc0bWKuMgURJ0nStULf6GPLD3GxNzY++Mplof3j5z6v7Nl0+lZn2VojBl22AcPli
+ULjmXIZSkYudc6RcpBFIFgrcI5/G2wJoM5xzBBbyxOFvQyx29PGdgAhaFkYo8WAahoOf69MkpkFgvO
+TS/9/evufrIktYxphgGOsqSElWZ+Ow8mF1tJ/7SjFdadDnaS4tvfv7bT3xk/OQZJnJHnBe47S6xD7j
+CsJF36eE4s7nBmcJyMu9z+PbbeOfPfvC9973pLV9U9WY5I8iKSSOGiKsnFpIo1mDkzm5ReHDK4LF4X
+4as6DiiPpqwvd0F4fABIgX1pARhcIY4jncZB5cvRrTL8kIZj44CQSr60oIP1OZazEZHPhWNjy6fee7
+4H2edPpsbW4ggaDabJejlAKGxwZQng1dY4VDKk+jwERq1r5LovxY7raffMQpmt++JVwgpKUwfqSTIF
+GOAEDE9MUci60uW2u8bb3+qplISUUNpiJKUen2M0bT8vSOp0FLiCKV8y/kK8fEEawlWoqPSXMuZQLA
+WZ6AXwAuNI+CERuuY7QIGkSKZnmLq6qsHk9de+3D9jrs+zd4DXyVOGSDpywiJZrxCAkP16vjd7bW4t
+JiSiFewpORlKlp9mUF/lZFty3sDWUZIVhbml2aj4a55KP9RKsYjiLVEJOKrrRuObDYb8c8nmh/Mzml
+YWydstQkGIjTaxWUmXV5QFAZrLCpExHFEpFO2tvsUhSUfZBRZjnEe4z3WOIwpyEwgN5aCgKXcFRYYM
+nIysp2Tp4+lXm9+IU1rdLa2GZ+eKjV41aPyQZWOmsN2c7cL1hCccq5k95qMtQsX/tNLzz3Nvett6kp
+hsgxX5CRpwtLWOgtbK/SmRljudTi+bZm/7Tp++EM//UN3v/ENX9Kt0UtpQOHybCKNJBaU7GF3yftly
+C0NovTlFFoRx5q4FiNUILcDnC/3YrUkRkVx5e1XHjKqaj3V8H/sPThPolKwDqcVSmuGQWvxbJ1xsfe
+Lzvhs7eTCn/UurjPo9kikRkW63I0pRW4zdBpXyU4KIwIukiSR+k8qkn8t1NB24pK4tZQeVc/WCIgkU
+qQYK9nu9Dl/6hwLR0/x2Fe+Nr292fs//cD/VEKdWNXASaxzyDQhrY8SD3rkgz4+BKJ6Sk3rcp8nNQ2
+tkMGhnCSSksiXgiMTFCE3YApMM8F5QzfLwDkSrTA6pjU3w6HbbqTxqvu/wp49n2Zs8nFURBtJLmsMg
+AwYt0NEvjrMhC9HJkLl0you8cu9vDT4+Uuo8PB7v2ypLIBkSBj8R+h7tpLaaGS5wwiyMrJN8LJZWGE
+f5oqZh5uzN75FLV38+Y1jJ1+zeezlmlvZQFnLjc+9TKgn9Gopg7SgW7Nli+kFsTF4Z1CFoDaIKPrQR
+9KNIja0YxtHMThJYQu8gjxWbHjDVihoY2hbT88DkSLoJt88efJvLvzHT37lvte+5aH7X/PGvzp0+Kp
+8vtVlz8wkcSoIhUV4Vy5dhMLLCEO1yxMgXcn9C+dO/cLZR/72ttb6ecZWF2jUWyxsroGucS5zbMcTL
+DTrHF/vcizXTF5zAz/y0z/33vvf8q4vqZExXCX2UwGyaGvHvzoiQdIsB/WozJgsDXAtEo0mRRpPLUh
+qaZ+QrNLoDEh7OSNyjCLvEEdj9PQMfRGTJgEhsqExYKW6jKpTNxqGV5QAVxWmOYTDPZBMpMzcePWXO
+iq8d00Uf2ysw8cFdRlKoKJf0GKblhwtV0kOokaDYiNHNPPbOHzgF5D8hiJAQ4Hw9Is+cT3FESjI6Xe
+atDsZy+sXWVg8x8mTJ/Y8//RTP3r06ed+cv302VvrxnPt9F4iI8m2+sQqoqU0jWCo5X0W4i5JBKMom
+jhaARpB0rSCNJLk3hBisMrhKBDOoPBEKhBLyfb2RWwcYeoRvVYTuX+e5jVX9mq33Pz3+vqbPuXHx/7
+WqKhSbSpqQtCoDhGFKPMy2C06lyXK+r3qRf4vMFDa6VLFrnt3F7qjdETUbH0t3au641H68716892Lz
+x9j6cwZzMwoubAYEZAioHND0R1grCcScRkSqSV5bOnnnn5e0CsyBtaSFzmFMRgcJihyZxmYnH7IyHA
+4IIkkPevwto/JnHrumWfesd3z71i+uMGhw1f9j/Hx+KGD++a+fOXB/b0D81PMTo6iRelPGyqvWudKe
+RpIWNsYefnFF//D+sJ5+hubbNqCXtZjzfTxhSFHs4Vkqb3Kqhuga01e++YHP3rXfXd+sTGSoqLyFho
+iH4KkojL4Sox8qW+RogJMqmyHshFO0aqGVnW0Aik3gT4+DEpARTmCLzA2J/aq8k8Rl+CWoC/np6piV
+2P03byeNIWrrrrqiyNxMrf88unf3G63CTpCpTUIhl6vQKkC4wP9Isd3+6XaIW+xZ6z5Hxhp/Gdq8fa
+QvSDjBlvdAaub6ywuLXHieMHyysWD5y8svGd9a/0nep3t6zeWl1lv9+j0DY2ojgoRtaRGXIuoW0Ejx
+DRkgio0iS/1mlJ6nHRkyNLzpdreogQhlLxMjUTrGOkNWEtuDIyM0LcFPQSN6Wmuvvte5m6/9a+Yn/t
+tRka/7aXaSdQQQlUd4P+85eA/S/Hp6mOo4QS9y/lYiHLnEfB4pQtZq32TvfPfbDQbbzicpv9GjzZfe
+/7JbzUGnQF+UFCTklrQKKvKwBEV2BoMMGi60tKWBd1gyK2HrJwdCxlwXhC0xIlAESwZbgd2zm354IW
+U6KRGXKvTrNeQItDe2HjT8RX1piePr1DXz39j79TIQ1cfPvClwwfm2wcO7GPPngamKjypyiX70umzH
+3vsG98cW3jpGHZ7i0VnYFDQVeC8xUURG3nBBdel0Jrr7rrx9970L/6PTx268RqsKOU2oZp7yvarhqx
+sisSQWLor7EUKv0OGEL7S/YUU6RsoL4hTQ5wURFFGnEJaEyhtCcEipdgxtRVVyAjD2WPn5MyGE8nO6
+R6ErhJgS5g8GZHM7pn+lOm1j6yY/k9ngwzXGyB8YIYWg1xQGMtmv8fWoMfmYJuQRiy018bueu39H5M
+y+fjK6hZbvYyVrU1OnllgYWn56jPnzr63Z/a+N7f5VYiI2vh+0pEcHxLWVzp4sYV1EYVVJHGd0Vqdt
+O9peEVLJtSKiHEUUkoSytnRKUmmAjJSeFmyFIQrXQucKhOelCj3N0EIVqRk7MBBZg7u783fcN3fNW6
+/7dfZv/fv0XGJhleO38Ojr5Ix7hAIwvez+Ia2eWJ3XJO4JMUJDHeDpd1eIj2Mth6OrrtmcMWe2c7Ku
+P/RlTMLbJ04i11t0xhYdAaiACMKullOHjm2hWdbFPQpysAOa4itwWqBEVCIQIEnrzxUdtmrVCOcwAw
+GeBIatYTZiQlGxiZoNG8g67Zpry0/cGqh88D62qnfP3ps6bHx8RN/MDU9/t8OHZhbG2ulzI/UaYZB4
+4knX/jX33z8SczqBZQ15L5yP9MxwQvyvMfi5hbLwJ6r9j/31h/7oQ9dcdMRgixDtSQO43IiNEpopCj
+DkeXueLBdaLMSnhBM1S4ObQk1wkUEG5PGhiQ2aF2QJFCvS5IIlHAVxStUFILSRPiyutu13S7/G7cjB
+g4IvBDoWIGFuBWz79DeDwlv7l04fuamTq9PGicsbbYRGx16eY/17gar3XWWtlbp+Iz0+Cgn2yv/ujU
+986tnL6z22n17w3Zm/+X6eu/HVVI/UJgR6hP7acjS38X5jPXVRVa3umxs9xg4S4ak188IqaKW1onzD
+JV7oqDRSjMWRdX2WiGjCBJJUIJcljtQiox6JEmiMhOjbzJcsIhIoiKNP7CHvXfewewdd36Z/Xs/Q6v
+xHYQEF7BSlmLNIeGimv3F7iFdfB+Lb+hfuds0dvcH8jtlGRG0xOOQRVFQTx4hnXlk5g33f7Z2auFjS
+XP0dZtPH20Mzq2QVC+OwxOkJJeBgXP0Q0HXZaXhrTHYYMgU9KyhXxT0RCDDVlkJ5YLZhdLuQMcxuSm
+t17c3N9jaWKeWJAzyjEbSojVVQ9oBSgac7d+ztNS559z51d959PGnnhodrf3heE3/Pw1RvPelxx9tP
+XdqCd3v4vMes2mEzQtGR0fBCzpZn5XMMLVnmrvf9taPvPrtb/PJ1Dg9a9C6thPWqVS0wzIqCfbye/T
+yHsiro6sA4urULW/NcoYboJRBi6LM5o1A6aFr9CvM/sTlXqdlJTZ3LZJ8dXQNvU9D5b8dEFFEPFb3j
+dGxj3gd/e1WzyB7jni9YHvQYWVzhdXeKhuDLdYGm3RdhktiXri42Jrad7C72S2WonR8fmRkDp1OMju
+zD9Bs2IQ8H9DpbLK5scy5c8c5f+YUnc4WUsB2aLM90BRhCpHUEap0IsidIE4EDSJcGHrrSNAR6IBxh
+pAbkgBaxeg4wYaCbihwUUx9coT65Hj30Nvf8HezV13xa+w/8E3SuFy1VWwuVBXeMgyX8t+DhKK+j8W
+3U/yvFJuKS21pDpgqe7VAIGOBkIZISKxoPdI4fMUv7Ze1drM2+p6t5gn6Z5cYrKzR6/UYCInxUBSGL
+DfkpsA7h8XgsPSFpBMK+nj6oQwo2Z3EQ+U5Yge9yrouZmnxHNZ4Zmb2MDmT4MfGaTVToliSpglWxRi
+ZYAK0B93b2oPt207b/qdD1qHbCfjpq+i2N+isr9KxA7quoNUuVzCZtwShefX9D37mwR/8sa+N7jlAo
+cvtaJlcDtFw82ov6QEvfWK96/AqsccgKsRZlsigji1RYlGJQyJIdFQaIklLEmuSeOguuptZcinJ1Q+
+PAOHB65KzuSNZlEBR2dh7HA6PR3uHiGvM7N/7tX7PfGZpZfPDLzz7EubiKpvtTTb7m+TC4FIQTU1ja
+hLVbFAfn6Q2MY5qRfON5gyNxgzOxOSZZ21thbX2NlvtDdbWl9jcWmZtbQGzdgGybXyw1HTM+HyT+nR
+CcI4iLlCRwQoFqSh9aaTYSRKVPiBdifIGF0jjlBAEnTxnIC22VWfk4BwHbr6G+cMH/zS+587foTXyF
+FqXaySlsKoE2iSXi6hF+F+XCPhPKr5hVK8YBi76sLN/kG4YKlruV4oqxDIiQmpVtYdNI0cbj6ZXjz4
+6Pzb72dG5/f924cnnX7f6zPPNjYXzmFDuzYrc43JbriUEmEgw8NDH0cfRw5GhyAjlMlqU/J7Z+Wmmp
+ma+luXm9ReX1xlkjvbmKu2NDc6efpnxkQ5jI03Gx8eZnZ1lZn6OWrNBiGNarRbpSJPcW/J8QNZtMzq
+1h/1X3sz6hUV67S3WF49iLq6w5gy2yHFopqenOodvv+8TM1deR89FeClLVkxF89A7ySRcXmhi11ch2
+GmgQ3XzhaEZr+4TdB90j0jFNGp10jhBS0sUlfYFWqvv8V0NjW5LHqPE4UPzslM0EHHJe82WDasOl1y
+jmoL6RPSJQnXff271ROv0C89TeEfaqtGaHqMxOUJrZoKxuRnikRGCroFISVyMtbC+tkKv41ld2uT8+
+UWK7jprG6usbyxBvlUC+DXB7IEx5qcmeM2tt27ftO+K/3cklw8tPXPi79r99rJ2zA7jybJQtsZKCax
+z+J5BKkEsA4oIGSS5s7hEE81NM3vtoe78bdd+ffbGa36N+Zl/IB2BuHzeXmg8ijx4nCvpj1oMxyouy
+6T436L4dkaUncK7/Ea0hSOOy+bUIHDBVQi3onCGhqpRmAKlJGrf3kfrU1P/cWZsdK072nx/fOocRx9
+7EhEGBDK8E1gvKKSgB/S1p+ctfSwZkOPISk/qHSLrvgP7/9t7fuzHf+Tw4StrR186+S+OHT/9/nNnl
+968cH5ZdvsZ7c4ZNhdzTp+D1tg4k1Oz1OojpCPjjE5PMTY9h0wSarUacdKildRIhMDbGlNTMHNoP4s
+LZ9lYW6O3vYG1GeP7Z3916vDVGzZOMdUtF1fPKSkRd0zXEzVk1eyZCnSRpXJiZzCLKwv24T7SIvFYB
+tjQQdJDSkkUxWitKUUHsiS+7xC69I7RbbjMkLFSk1f/qRue7jvDYIwkJs8z4qj0R+22l1i6cI7jx17
+ceHnp8V/rydO/NH/jDHEtZXJ2htHpKYyUFEJAHJMHgR0UbHc7FLlgdWmT5cU18oFje6PL+vomorOMk
+I6JkRozh+bZe2CaK686sH7zLdf92ZGrDj90xdz8tw7vu4LNl07z1e1ttpeWvyGK8MMiSKy0ZMZQRxA
+FhcsNIc9K4XMSQSzpmRw/EtPYO83+O2+0h+679b9G1x3+HKO1p0vLCE0QEuMcQVc5vUIi9K6iC7u44
+GL3QfXPh7jof2rTGYZxwzJclmwqBNQjtQN+yF18NUnZi3vjUaqBkx6LtKKePDF2+60fODI7/18G55b
++7WbhH1x8+oVmZ6tLxwuM1Kxsr+EixcBZOi6jR2VgFMr1glQRloAQnkMHr3jkne/6ASbGJgevfeDBP
++l2sz85dux0dPr0ubedOHnq/U8ce+btx4+fiBbPLrHR6bDRuQjGQ22E1vgUoxMztFqjjI9PMDM1C3G
+d7cJS03UipQlxwTWTY1xcvoB3BUoYrMkOfv2Rb9x2eunUUzfeeB1HrrmKvXvmqKsEbwzBOKJmCs4Tc
+JgwQAWPFgkylETzAMgoYmAlKI0SUVkMpoOQEuMKmmkEQmHMAKUkWkOcSGr1qPRWHapFUHgPWpdB1LJ
+KRaJ66XYsDytrA1kRkK0JBOdpdzdZWDzOiy8+rk+eePat65vn3+9s/917r4EknmNkbIxac4yB8XQ6A
+wqnybqWzfYaKxc3ubC4ysZam/Zmu7QkGBSopIbLB0zXNVdecxW33HLD8m133vQnt9554x8evmr/d5o
+jdSIt0dUYOj45xp5985xLjj4SJ+6H6yHFDzxWBApnsXlGZD31OCGSgqCgiBWmmbLntmt7+++8/m/nb
+7vuVzly+FtEYIUlyARdcUu0luyW2Yldxk2XuSMKf8lWAtBCfz+LT0OZsBwAACAASURBVO4C6OR3X8k
+Vy0eLS9KKy0pXVU7TSPLq98tljJyb+VYtTj/xwI//yPIL84984JmH/0Ff+PZ36Pc6yKRGUJCZHoUKZ
+Uiq8NhwSQ3lQ+nVUavVnoiiiFotIY5rjI6NMT42YW699dYvb21tf/l1qyfEyydPv/npp154/wsvHH3
+nyRPnaqvLq9Bfp2N7dJZPQdqg0RhhrDVGo9ZgtD7C9OQMzVqTYiynNdJgZn6MRiPFu5yLFxc+uLm98
+sH8+MbaqZef+dMn5qb/4ODeuUdvue56rjl8iInREZAZOEvh4lICJFRJYneXoGxvIdEjFH6AcwKtU6Q
+MxFGLOB1FiII0rSNVjoo0JbuvVHsMD0Yty1iXIcteCHBWY51ExhBH2U6RImUVVhLobm+y3d7g1Omj6
+cLiyXecWzj2gazYeHNaD+rA5BhC1ksdpWtQmIIts06/71la22Zpqc3S8hbrGz02ltfRSQOfG+j10El
+C1AwcuXqe+bm5hfvvvvu/XnPN1V+45rorn5+fn2Z0cgQdicpzRV6SBkQNmvVxmvHIE9guFBKdg0sCk
+VQI4bG2oGMLRCTQtQQ50eSmN93P3juv+0Lj0PxnmRp5lnjIolQ77BO5SyrmX7ETF2E3HdrvYMPhu0j
+S36dVw3fZSO/OFReXO36JV0C0QVyea7BjixIlPp6dfrIxOf3B21utz4/tm/93anz0nc889i3a5xdLG
+7gKXDGVM/LQor1UYghirZnfu+epVqtFHMc7XLE4UdSbMSOjNSbm6uGuG2/56psfeP1XT718nmeff+n
+BZ5958f3PPPfsu86cOTOy3RlAb5teb4neWrn3iZMmzeYIWseM7m0wOTnJ2HiLOJqjXo+ZnEgBSz2RU
+4TiQ93txQ+9uH6qvXr++S+9MD350L75mW9cd/XVzMzMYNIDpPX6DkkhVEz44QtgHChZYyj+Fq5OsC0
+a0Tyx6BPEFkJb0toE9foqOkqRsgyNNDsuARWNbXgQStCilL04u47SCikdLu+ytrXC8vK55vnFUz+wt
+r70gU5n6w29bItaU7N/dpLmSIPBYMDqxjqD7ja9osfLp86yeH6N7e2C9dWM9Y2MPJMEp6BnsEWAIie
+txdx5+w0vH7n6ii/ed++df3TjTTccn5o7zOzMVBnuWSVeWG8qdU5StpBCQZQwPbqXqdbsU73gifqO2
+GhMVAJDSil8GmGFIY8CphbwNcc9Nx2mcfdNn2a0dtxgCaJE5/WuOOxKo11BguzkMu20mrtjsnc17+H
+7XXy73S3DK6/of6QAd/9V+HKBLQQkHpy85MNTAF4GWlfs/9at81Mfj0brt6/3t/adv7hE3s/QaBxmJ
++bYV6o77yAIQZrUj05MTPWVkJVdXUnKds6XangEYyKFNGJyb4srpvdy1/W3fX3xgaWvv/jSS5w8ffy
++xx9/5H3PvPD0BxeXzmNMBh4Ku83G5jIIRS+vsbVcZ2SsxfbqNKNjLWq1mPGJBs36CM36CIn2mKw76
+oreB86eu/CBhQXbu7D0/F/MTE19ft+1b/ofY2MjjLeaxLpGpMZRjO1wu6X3BEcVTVbmkrh+naLXoL2
++jXAdlhZ7LC4atrZAKEGeS3xQpFGCD+Hy5z/EzN2AYDJULZB1lllcOjW2sPDSD62tnXp/P1u93/suQ
+lqmZmtMyZg4aaCUZqvdZXFxk6XlLfqDghdefpGzZ5dYXytv6iIHBiXpWuk6KkkYa7U4dPB6Xv/gA2u
+ve/C+qw7u38P8/DSjo02sGi3hpgB5btBaInVSuh8gLr2UacTY2Axjo9N9o7eOCt87EoVSHeO9x0ooE
+uhJWHV9VrbX6YQVbgldZurymiA5bquSqg13qu5SjyleEYR2ufHoP3bdhO/zzRfkZWyl3Q57Qrxi9fA
+9UCJZ/fIYiHfxTi1gfcmxyhWkrfTZycP7fj2ZGvm/iygwoKBGhA/msotWUjLbhZDU6/WjY2Nj5e0aP
+EKVLIgkKsvbq5I9P0w3kQHGR2PGxw9y7aGD9Af3PnL3rdc883v/5Xc++HebC2wYhxXVHR2AOCZb79B
+fg/5GnfbKMkktpjnaYHZ6nK2pcQ7sn2ZyrEE9UaSNFm5E0h+0G2tbF378/PLJH3/66GI+PTP+36++8
+tDnrzx09Vdnpw5aFfcp7QgCWmsICmvqmFxRdGFrpWD9fM75hSWeV4ssnF3h9Ol1Tp2FsdU2Dz/83Pv
+m5q//g9vvugPnHPVGRc4OWVV8A5xbY9Dbmt5eXfvhxYVT7zt16vm7tzrnSZOc0TFNrS6QKqI/6OGCo
+b9tWN/YZPFCxulTm7x8ZoWVi1t0Bz0626Wdu1YQm7KbSVSCkopmrcnYSJMH7r2Hn/5X75u64urDDXz
+RQ4nyMCuFHThf2l8oLXa+/1C9R7p6O3WrTjrSgISjVtojTnu8lmTK03OG9aLNUrbF6d4qS7ZLv6l5V
+96lr/wVEo+uIt7kUB1+WZHJaq96qcFUwxMwfPeF879F23k5ZeLy61hcsur/7gV89fdoqKOrwiSrC6k
+0862gOOMNuXf0XX5gc7DNZtEruZvSs5u5WAbUKowrJTfNZvPE3Mxs+QIPBY/Bl0bTrtzkxPjSrirVl
+z6jgyiF0doYN191xR2TiSYtchpF1Rqb8uVI8AgfkWOwnQFbnRyLI04jVhcuMjZWZ3VxhumpJiMjmun
+JJhNTNUbHRhmbaJQyKhuSbLD87hPHTr373KlH3MTI7Ffn5654aP+Bq/5ydn5PHpxCqEl0JBlsxZw7u
+f6+Yy+8+InzL69z8WKPMxcdFy4Etjuj+HyEtYuCL/3pNx5aXOp+4i1vPfWJt7ztwT+opSCUJ7BJ0W3
+vLfLVH93YPPuT2+2Lt1y4eA5vc0bHDXv2TVNLFcFl9Lpdup0+vU5gfX2b4ycv8sKLy5xbyNnahn4Gh
+amCeT3UY0FCSpABrWLiuNRopxq6G+t0NjcIzmOy4o4gwzdiFaMjTSgMMopKBLwM5qms7cMO8dsIqEV
+gmwI/IrBNfyKvDcBAB4P1sFJsc3Z7hVOdiyzQZgDEssF6dxN8OCC8Q8uojKCuXjkpL38fPfKy1zl8r
+/ui2qSpf+aNwz+t+Pylt19cdiL4S9zd6id38+GGp4by5pJLkKgwJlFZaAuB84ZUlgLefNDbu97eoJA
+Op6BT6XEqDyakkAQpwXmEkNRqjTPNZhMlSoUxIlSaMkmky3jHPvmO7AjKYEYtS8UB3rG6sHDT4OI6z
+aK0LweQKiV3noYcxU02Wd/cQKYpmTVsFz18rtjM+mytdVk4tcT4WDkH7t0/xtyeUabnxzh81X4mJkd
+I9AqtCVcJiQfKmrNvP39h6e0Xlr4DSv3Nddff9tDE+OEvx/qK7qmj+W8//a1zH37hmaOcO32WfrfN4
+oVxCFOMt2qMjyiMz1nfXOSr/9/Dh86eO/VQWnd33HTT4U/t2TPynnyw8hPd7YXrev8/e28eZFl213d
++zna3t+XLvaqylt6rW71Uq1d1awGEBwxjjywghmHMIDuMgcByGBs8eBx2yGMTMTM2HhxjkOzANjMsM
+RgBZgsQGgNSIwn13tXd1VXVtee+v/fyrffec878ce/LzKpuCUd4PN0KkREvKpeot9x7fuf8lu8yWKL
+bXWTQ32VqtpSKFwEuy2ltt1hd3GJ9tUOv63j55cv0hpJW27K5k7HdglEOKjBMNCocCef+OE3T9wdGE
+5mALB0yGgwZjQaMRiPae216bsTlSxdZW17h6InjD0Rx5fPjMsHIHGx+SD2ghCOoAmMzAtCOWEhs3eG
+aYCfsteFOn7yfsdTrs5cPWOu3WU53WKdLD8g1BFqxurQMg/SYiRQm8IxGGSqMsLqENLiDscHbnWbqM
+IjkluRTinfLyecPg+VvPr4p0RWHc+rxB1V5IYJUtENLJUc7jqjCghmpIE3Za7fmBqM+1WaNkRG0W32
+w5aknCx0RJwrOthCCIAiWwjBESllAj3A4Z0u2uEdqTZe05FJ5BJ5QF0aYWPC7exgv7mlGFU5OzpLuD
+Rn2U4QvEBAVl7CRS7Q3NKqTv6LC8H8cefs9Toq/vNtpnR72O0hl6e7t0dpJ2d7pcOkaRBU4crxOc6r
+BfSeGLCxMc+zoJNVKiJYBAkGajuin+TdfvvLcN19XN8gHF7l6znLp9T1uXFpjdWmJne01dtNTzM0cp
+RrXccozOVNlPj3O5evPcf3aDf7X/+1/+fif+3OPfvz9T72HxoRDqxZJPGB6VhKGEwzyFbrtAZubfTZ
+X+yxe3uXSG1tcuQQ7m5Bn0NqDYQZBBWanZ5icnfuPR46f+Ln5o0f+wx3Jfd2rVy//++Wlxe/a3d6i3
+RthhynSe2Kj6Q9HVGSITUfs7e1hrb/HAcMyTd0PPJsVR5E0Bal2DJaAEhdbKPlTBVdjKYtysnzE6uo
+2W3mbFbbZJScTGieL589bHXa3ttGOuUiWGFDn9/VUUqB2iAT7pzZRbmkminca24l565Por0JcuhV3M
+QhLzRLvUGMjEqVASJwQ5ELhbYFXbLf3pqYDhYwcw05BXbniCkJ4Xzr6mcPbLg0KNbOqyNddGLBrYoL
+CewiZF7o6Vhe7amwDjBKFjK/N8dLhhGIoc3zg2N1Zv23OpcwkhnDQxgQZg1GfAZJBugdpyAX6zB+7/
+eX7v+cjVzdC9RO91P7E6sVrxzbPX/3u/vrm965vrD60trfJVs+BNYgduL6UEqs2F051OHHMc9eddU4
+en2J2JmKmCRNVmG5W6bfg9bNXWFpc5Nqi4/zlHa5vbrLSWgfbh6CBVnWkrDNXn6GuYDKZZP7Ox9ncW
+eXcyy/xu5tfpOL2+IvfcTuzM22E7ZD3HNuX21zdqXJ9cYerVzdYXGlzY7HP4ir0BmCMIXOG6YVj9vT
+xE585fnzh3915x22/ffr03cOTp47RbNQRnYw/+n3xssr4rqgXY7KQCd8kiCzejNgx2+QRjPp7LC/dQ
+OX5bcpBRQBZjg+H44ofV64cAcTOEXtLb9CnUp0oHKNVHTVznFbl3PpVUtY3r/J74TJeAVagbIzwAmE
+1FZmBcOSjIRutralKs1kIZgRh4RBcME6h9AlRXw2mKfgvhyv7z0W4/Jf8kqJUf7IZWTZq2jxFSAhDi
+KpwNC8pJLlHSchGB7iOahRsBao4PeW+QdXhwtnhyjRHlSh+xFjavGjOxHF8LI5jdLVGDU9NaJwvZpF
+D59lZ7rGXRzx05sHz3/YX/iL5/DRDB7tLG8ujle2fXH7z0k8u3bg2e+76he+6tr32fVt7rcd2d3fp7
+XQYDoe8eQHWl7a4cWWL4wvTHJmvcmQu4MTRCeanpxB5he3tISsrPa5dGbC81KY9SBE+xlRrNJLbmGr
+OUw/qxIkhCD2GiDCcxVrDyaOW9uASb15a49q1GsNhl531RVavbLJ6o8XrK0O2tmBzq7CH9wLmZivMz
+N2ZTs+e/J0773rg380fOf67p06dyo8cOcL0VJPGRIUg0IUO6F7GiRM3zu8ud8jbHruXkfY1Uo8YCk8
+tqjKSRbMryzKstccO0ypECTR/W6apEERRVBiT5IIgKBoyu7vbW6urS+x0NshVCcn0viQdKxwZ1lncC
+IbDIaPRqOkK0We8EwcqUuLds87fkeC7iYh7uC1++O+iFN+xeRWbE0iBiTVS5xjdoO8yonzA0FqGXRj
+0YOSgEYh2oosdTpSOemNFMC0sFouUJVMAhRB2H4blhS/k8Kyb0UJidOEJUNUhQmkyGTD04NqSyiCnF
+iXXZiencI0ZUiRHGzNU7xb4xx5je3tz4/rm4k8v7Wz+9Hprq7m6vPodS1evf9/26ub7r1z9Mq1Wi5X
+ljNXlLaJgi4k6LByBhSMzVKMpdtYkmxsxi4tDNlspQyRBOMVko0mzcpJGtU4sFFoWAsJOCjRVjA6p1
+yTrO2u8dnaNuN6iVt1me7XD5jK0N2AYFUSA6emIqdnj/WPH7/7NE6fu/3cnTp7+7NTMgp87cpx6Y4p
+ms0kYjMm++T5KRmQB1Wr1mkDhnCP1tpDmS0f0bI8hPfbsCD/ssbi4yNbuzkxSqyKDoEAU7LfLvkKmp
+DXWOryXBKEmy4esbyy31zaW8GRUwyJzFbYAxAkh8V6TYbES8mxEno2qztqbrMtK3fp3TQC+K08+50G
+4IiMXzsZ4i5aeJNAEypJoqEpNQkiGI69Z0m7Ods9T07ZXlQ5TMun0GB3si7mOOkS88RSuQXCzB7tWq
+hFHAZVanQmhqMqCIJypEO0gPtKg09ZMJNU17Rx9NySXIYFUBRXMx8wmC0ydmOdeMoY22+22Oz+7sbz
++s1sra9XV1T//keXl5b9y9erVb1peucH29iK9vRXevJJz9compJuQV9BygV43AKoYAiJVoxbNUw2bR
+CpAuCHWZmQ+I88dLhe0O46dHY+zk+zs7PLFL95ASks1grn6BCdOzTBzx5H23Nz8rx+/7c6fO3Hizs/
+NHb2N5vQxKtVJtEkwYbzfKMvzDOsytCzk1kubNpKkumbxpM4zSlMyl+N8TppldO2AvWwAuWZzc5PRa
+NQQquzOGQ0+Rwh1kx/iPhrDg3dF098EApdBng4Y9Ns9QUoFqGpIbSFhIRghUUhVQOl8AMpbJC4uOuk
+HXvE36df/WfB9hZOxBB3afEQ2Ghg7GqCcxUhPJBXOD4gDRSg8TkJQiRANw+pOj4nAp5HICEgLFAxmn
+04gfCFbsd8A8qWr7FjcxxX/uiyPA22oV6rUECSZxXmJMSFGSAZ9x0Slxky10ZImIpGmWAAcKBQLrVB
+SFKYdQcRE0uDo1FHS2/vd0YBf6PeHv7C1sx2tr6/+hc3tpb+ysvbmt1y99LpcWrzGm69fZXsrx7k9Y
+JaECXTSIKomJGqSSmSItMDnpYU2MEhH9PYGbG0N2On0cDJmonqS6ckppudy7r3rju37Tz/66bmpkz8
+3vTD9J41Gg8bENFG1igkSZBABhsz5cfe/uHraoPCF0psohG+F0CSVWguhyF2hJGfTEdYPGdi0ICS5o
+tHVardJ0zQ+cK+9qZ94SxOvtChwbv9zCeGJEkVzKkk7kyF6NKIZF6OIXIIvx1VeOLwez3EzvHVGlCO
+C/fGC//+4Xfk1nXaOZxH+rQ0ai8NmKaNhT9pRH+1yYiWIPQhbOBNpmeEE1KOAOIiQ1jKZKBeSgstQt
+wJgvS3HDmX24YoxhBcl87vEYgkhVKACwiBA9wdQWn0hLFIWEnXGC5T1Q/ojbGSQiS4oVN4ThuqQXY/
+EOYdRGm0UQSOgWoEpBcdPzg/7w/f8Sub6v9If7OqVlWvftnzj+sf++A+/8Jd+97c+z5Vr24QIavUqj
+eYcYaVKGCdEwQCtDHme461gaHP2eh3ae3tsd9qMrMd7S6N5nA9+8CGeeOruR267febFo3OzNBuTiKC
++Lw6MAGc9zolCeFkKsnLxj2FXGlkqr/nSqVUQBNEwy3L6o5R2v0uWDnB2jx5tEClDn0FqabVaDNORy
+qxHK4/NHVp/FWUhIZFS7KujC5EzMVHlxPFZN1iu0VkfMV0R+FDhrMbnisw6BvmQkacAROQp3qbS2xz
+MAbZYiP8fuihfC8H31nDztzRdCtGhUEoXBkbFpjBc0i4nMuBkhpQeHUqaMWjl6RpHM1JSZanFu0ODf
+nnAxBjvu4eEcguq3QEQdao5aZuNCV3Pc+JhirICm4MzEVZqajM1er1dEl1IjRlbbCR5eYNH1hXS8hQ
+2yNJLcMVJJXJ3MGKRECYQqYTqRJLPzE3/5ul73/ObSdxMX33tqlld3aOWxDRqMfVaQlSto1WEFKsIn
+2BTT5p5+r09dtsb9Ifb9OwODk1gakxOz/PQg9+Yvu+pR16caAKqg9AO0gLQ7csY8FIU7lilvfOYh+i
+xBZy4hFspoUrfdUUQhIVIrfeFdLzR5EIXU4Ryqi100XARQlhT8ueULtJODgHy3a1dx3JDdi5HkhMGj
+lpDy0bDwBBy5fHCgpQ4KRiMUpwvMhohi9peFrnrLeNpf8tI/es47RRv94PwJfzOEQQBSSXKGpVE6Sz
+ADPv4HMIIrPAYA9XEUEs0djQicBmR8oH0+WAfn7evfFtKoXAg8SZ8aYBZOhX5EvVtgnCgg7AmS/dcJ
+TU6NIggJpUa1/fY1EKaR1j6lIZjY0NItY9qtkUjXch97wSMBF22GIVCCkXmLLm1COmI4oTmdHM5jM2
+pSlUzORkTKAkiQ3pXdGj9XuE/kEuGfUervUer0yL1O+Rsk+NoVCJmZhs0J2dX4rhgdWXCIRgVkhPuQ
+CO4PKCLsYsYa74ckspDgvM4Uaa5qSfPXNQbjhilOTkCYwKE0Phc7s/UpPeMRiPSNB1kuUUbhfPuEMD
+hoATz4mBDtNYihCqV8SxZ3sfZXhAmOdNTAm8F3ilsLsjSgiAsFEQKbChLIxmZqbdTzxbvnrNPviOv6
+r9CoScL9rtzrqjHrCXQauBdTiUMMEpST1Thg+EhCQXKpTRCzWQlYrZZZbZRqwibg1TkWRmA5UnjRKH
+FaG0ZeGIs++1w3iGEAiXxUrTjSo3cK4TUmDCiWmugg4ikUsO6Yh6mvZqgnxap5bDQUyn454VXRKG/6
+Q+5Ro5Bghn4FOdHeDKkLNgYRhZ2zWEcvrBwfBbr+vT7WzQahuZETCVJUELjc0E6yun19mh1dukN+gz
+SId2sS8aQZjPg+Kk6tYZAB/aFKC5eV8kAhy9ItJKbFJcFoJVEF0rB+9A959x+MEipca6QpVhdXptIR
+zn9NGOYpfSyEb10yJCUgS2A74M0p1avoLVuj2u+fIxsGm9+4hbWi/cHgectUnlq1Yjp6WplomEwxpM
+YT6QzarEj0hnVGOamJBM1qFc0jVqMkG5QKKEfBLgUEv8uOvnekeAT4qvnoUoqhJLk3uGc6zqXY7O8u
+BkelBKEBiItCRWE0hIrT6QELssaNktvfmI/dlySeGThOckBYxlf/L7gBSp0EG4KrZEmIEhqqCBBhTG
+mUiv+jWOQimFvME+vD6lHe3lI23Gs1ywOlK+4BeNa8ujEWOChtEpz1nH82MJvve99j3Dq1CzIPrnbw
++YDbJrS2W2TD0N63ZxWe5et1jrbvQ32GGBRGJmwsHCM6ZmYkycjji8Ev4UowCSisI3cP/GKE2osoJT
+DIaMAX/oXCiEK3Ut54P6Rjzzd7mA+yyzWwcg6Bnla2qod2EEbCXEYoaXaPLj3f4r+ni/YKO6QlqLSj
+iD0jSSBWg2qMVQDSEJHNYZaFep1zUTD0GzEVBJDGOiuKY++cfA53l1f8p16UfW2AG2/D/cRJTYzDMP
+dMAyRCoxUKAmqtKsKjcEoMMITKQiFJe3vTbs0KyDzohjmukMXP983Az1UCYiCjmRlaQRpgmVfmANgk
+mrhU65DVJQgggpBtYpUIb3e4BS7e+Vr6QMW9L7dZqnjViLn3RhLno/tV1RZcxaSgqE0GKWpJcH/ee/
+dJzdPnprC21263XWs7xIYTxgG5KMq3U5Gp9ein25jGaAJiMUkE/UjTDdnmJk0LCxI5uaHn1a6j6eHw
+CCo4USGF7cGXAHBE5Spsh+feGJfmGlcRWWDjN3N3VODQeGjMXIZgzzDygJDK8vucagVlUoFpdTy+Jo
+L+dWXnBfjgU+JzZWFGUwSi+l6TVFvQC1RVCqCJIZKpQi+Rl1Tr2uqNUO9GpGEwS5S3hTo/yWEb7/ma
+j75dk0XX8jcHZ63KW2o1+vbExMTyLRFYAO0A2MkJlZEgUD5jFB6QiGpGEVn1J8bDfrgCgHew3g8dQg
+Tvs9WFjdnw1ZIZBhfVXEFGUUYHRU6MmhMWMU5j6poVNJilNnTg96AOBf7SF0v3Fvhup6SWSHJAenDf
+VrW2BNCjmXbsUg/JFDDmePHEs4GHW4svki7NWSyYVFimtZOznZnk/ZgkwEtCvnYKlLH1KoRlcQwN6u
+Jky36o3O/VPXZfxMGM0AFn0uUtrfsfGOe9sGpJYXCy4PAs9bjfdFAGg1Strd3Tw/6I1Jryy1mHLqFC
+JHNc5RS1Ks1IhNcVWpcFY8Vlt9uEbj9X+43wZ1FSEtg/FycSORIk0rDaMg+CdkpUJEjt4VLUBQbtJH
+bX7nB92cNl6+Yerr9FghESWU9jivk0qB1EXxRpIliQxBZAm+JjSIS0EhC+riFbNgDm6O0vAkbWwR9X
+uIK2S84itpMlsEHYaV6oT45SbaxjcwsKgebK4hibOrQCVQbEzgdnEmHGXG5Y4jcj12kkftLeXy6Kmz
+J5RSl37uzkDtbaIcIifcjhN2j01784V73Oo8+ukCrfTv/z2fPs9u6QKeTUq0cZ9CpszfcwIkO3u/hh
+CUOKkw2a9x9ep57Toc8+LChUt1kdfmLfzGJ/Q9X6+ankRW0CN8m4yvO6XF+JoS6CUDsfclHkID09Dt
+ddrZ2zwwGRcNFK03qJNZ7LA4jZUGUDgImJyYIw/DCzXxU9zaoSsdbUlPAW4u1GUK6hTAQiAgSYVDag
+RdI47ACZCTJRoU6tQkEQrA+Fsa5yar6Jjfir9dRg//KfZiiVyhL8Vu1LJXC+nL2JFTR7NASLSyhURj
+h0DhiExBJfyrr7UE+hKBseZdiHbJEuAh/06xhv9O5byITRq82ZmZoL63A3gAVV3ApOB2Q+2JxRY0GA
+62fHHQHNEYpuAqoAmCe75/fHJLS8GV9JQ/SYO8Q5GglEMKSDzqMeivvWbzx4r+0bpWHH54jTB5mY2u
+RZ7/co9O6xGDUJc+n6bOOEF10YDEG4kgRVTOakzkPnJnjsccrpOkNdttX2N1q/kujJv4oTOLXURM33
+XaBKsEGB8FXSLvIg8ATrrB7do4sT1ldWWdna/vJ4XDIcDhEmgDlMvK8tx+xWkOtVmN+fp5qUnl17Mx
+0kx/0ftXjbi4DxaHupLd4lyOlO6WNgFAgrcUgC689U5zbBIqRKHC7URSitVweP2nJLHtXdTrfseArU
+i3PLcXXWy6Ml4IwjG/EcYVMBwQ+LAwy1Njt1JWdT1v40qmAQKq7RoMejEYQpQU73BYkTbGv+RCpogA
+AIABJREFU/hK+5UX3hfUEiEC/0JiaZhAn5L0RYRiRCY9TpkB6KEUQJ3T6g+M7Ozv3zXd655hrFt1ac
+3PDYjzu8OVRMtab8SWKR2kQwuLzPq2dRbbXz//aXmeRRn3EKN/C+WV00MPEcM/CJLXkGJ5prq/sEVY
+TGtOTTE+eJB8GrCxe5Prys7T27sIyT3MqLwSG2ssI3vy12SPVe4KKw7s5xs7AeHGoDzROMQ+QEM45l
+CpSRetS2u1drl+7dt/29u7x4TBlMBghRPG5rHcYrXEuIwoDZianOHbkKNVq9YXieR1Cy1tOO/n262O
+M7XUO7x1KiruiUOHSAG0NJvDoIECnKZn3OK0JpcUTUK0mhJG5wf4Gwj64gq/3Od9N2Na3QZqPZTaMC
+qhUKleq1SppFKFlisodWhYSgUIUkgtKgHSeQCtCqU7naVrkdM4f+Ao6QLmipym+yuRDgNRhL6rXnw+
+TyqNCddHaEErIlEFLCp86IRmMhrR2O9867HbPRbkFLYq/SV92zcvk2XNw/OKRWpT1ngORF/qYnW1WV
+678qxtXz949N2epVjwvvPIlXnn1DVp7cPwkfN//8N/z4P0f/kJ/aI699Orzp5zM0mMn71g5ceL+F1Y
+Xt5779P/9s5+4ce13o2dfuMLxk6d575nbqdciNtZ2SNOlu6v1o/8qCNUPeDFfSNU73gJq520RWMUFT
+NMh7c4ua2tr39rf65JlGWmaQiD3RzZKKWzmMCakXq8zOTn5fBRFPcqxhWYs3aBuOvXcIQsC5zjolZT
+mMkqp08YYfKiJCREl+yFNDakrRJVH5HgfkFQiVBheKe2a3irJ8vUcfKmEEIHIS2076UDZ8g0plJcYw
+Mkqo2T6YrBwEn/tZaqjPpNpiwSL0Ak2jOk5zcgIKgkEPqeRbZ+WS+cSrl3o89BxkJJeVNzqyIXoVJI
+GpVmjUCgUykOMA+eRzuJ9yiBUn8vvvv3RvSCm1e5SywRhmhMNU/biGdAJQS8jbw8/Mrix/s+j40dgr
+o7MLanyBCpkLP0yppBpVfyYihYBFYYDB5kkSTTLN85+54U3f/Ov1yfbRJMxV9Y2WVp3PP88rC/Ct//
+5v8wHHv/vvvO2k6d/tc0WJ2d2aeo+jfn3kMk72V44TRwOL/3Sp65/evH5F3lhokYQTnDi9pijJx071
+5/jytk/+OsPnTn9Wdn8xKeFq+NJCjsyDY52KT9skNSQGLJ8SKwt3o4QvkKNGV54eYXnFrsf2RIJ7Wy
+dIMgZDrdIyKkJR3fURaEZpJ6w2WTmtuOfs5FEkBMYRZ5l5Kbg8GknitvuKOaruksuhgyVIaSB0TGZ6
+5LLi0kwsXTa9S2IBayyRMZhzAjLHmGWY1QNX2nSiG9n5ugDZLJ20UvPINujYirlri7Ah++aTod8R1/
+9K7i+jAtkqSCO44tJkqSBidBBSBAnJElCHFcITIRSCi1VaREsMEqj8A+TDcCm+8+/70ki8v3BrvSH+
+y5iv9gXUUJSq362UqsT1yqEcYWwkhAkFUyc4AVESUJjahpp9Ad2O+376PZBCLQxhaTdeLrrfIkNdfv
+i3hLFKBuRJAFR4nn5xT8+8ual135+cqrB1NQM7c6Iy5fXef7ZC7R34cyZB3niqff965m56V81kSSKE
+oIgwhgDQYCJQyYmAm677bZffeyxx/51pVrn1Vff4E++9CJr67vgAyq1CWwOZ18/9/OrK+ePONoInY1
+RbuRekDmNJN6vWMc6OEIZEJLdrS6rq6v39fv9D0hZYFaF89TCGpGJEEJRD+pUq1WOHDnGfQ/cz9Tsz
+GeVUiVOU2CMKQcxvrgnkkNqYqqUOlL7521u+1g3elhIhwkNcRLSbNap1RIqlZg4DjGRIUkSqtUqQRy
+RJElqguCiQh1o+Yxr2ndR0feOBZ/jLXPwA4/NQ2lCEIVUqrVXTRjhhUIYgw6KoBOiMLwX3hagaTxae
+mzafcx2d2DUBj/c/5CeFFRhcy39W4f9Qgi8KNOhKP5MUq+2giRBVyJ0kmAqFVQU44xBVRLiRg2nNOu
+t3Y+12i2wviB5HkbtKwFGFWMUMYZshXib41yX5ZVzvHnl2U9nbjtqTlZxVvDa2at88ZlzPPvl4mmef
+vrDFx5/4skfaE7VIQSlo2KGOV5MqtCDWji5wJPve/oHzjz02IX19TbPPPM6L750nrX1PaK4Sa0xQ6c
+zjG6sPvfpwfAysE2WtwslOVFH+zoQo7wpEC9l17nQuRHcuHGDxcXrHxsNh8Um5cRYtIogCBBCUKvVm
+Zqa4vjx4zz00EOtWq32GUqWw1tXQH4YZV8uR40UukTXFGBt5wePKe2JYk1cjWlMVAoScawxYWFZHcY
+RSbWCMYYkSV6lvI/ysBOUeFeVfO9M8N0ceG9VvPbe77cegyCgVmu8bOK4sPnwpoRIFfWcQqBK5TMlP
+Eo6+r3WU53tVRhsAz0UQwrPpBy0f1uUjUCUQ93SGlZJdBT/uqlUEHGCqMSISgyVCFOt4sMQmSTIJKa
+f5z+42+kkfjjEubHmalnMloiCYi0U8zSbeeIoZHn5As8997v/aGSXn5qaMXT6O1y6tMTzz17m7MtF2
+frwmQ/x8KNPf3Rmdr5QeZJ5oaGBwjqKBexSnC/QJHfeeTcf+sZv/eip2+5nawv+5EvneOXlK/R7gnp
+9nonJOTZ3XnlqY+eVf+TcDYKgC+RID4E05MMD52gAlwtwmvZOl4sXriQrKys/2Nvr0u928d4ThiFKG
+YwJqVarVKtVpqdnOXZ8gRMnTvy6EALrCnn6/Xu7P4axRckhDy9Hg9536+1j/R6IwVPaeII4IIwNYQQ
+q8CgDKpSoQKEDgwkiTBChTfgy3iORCHeIuCvkn518b2lyeFl66ZTpjjroCUsTUWtOPp/UpsDEZMJgy
++6hlJIwMEShIdKa2BQP8vSDw84WpB2QA7QYIkixpAdpJrdsuuUfhBB4KcAE6Erll4N6nbBeR1Sq5FG
+MjRNUNUHEAUGzQW1uFhGEtZ1252+1W3vFmWdBOFHIse/DyYoOqMcirKPf3eHNN1/4wOLyy/9QBy1U0
+GNp6Qavnr3E66/32NmG0/few3/1rf/t37jzngfPCRPgpMOKHHyAkmGxoFVhDZX7YkzeaE7zwAOPnXv
+6qW/5G82JSV5/zfLl5y5y5foO3b6nUptFBzssLj/3D7d2X/uAEB1gSDYqHKZiU7x/l5fluAjJB5LrV
+ze4dOnq39rYWq912x12t3cQOOIwwmY5xhimp6ep1Ko0mhOcPHWKI0eP/vL4RCyCz92y6HJgdJDqeIM
+kLIW3MqANooNUow8GgSQIFTpQxXglcJgAwlgT1xJ0FKLCgEq9ThTFz+M91tt9rua7iEP7zgbfPp31r
+av/pmGrLzg6VOuNL9eaU4i4RiZD8nIZSykwRhEbXULNCumHJFRz2ajzKKM2uAGSERJHZn3hYeD9/g7
+8dpvCPus6jD4TNOrng2YDl0TkUUAWB+QSRBQS1+tUpyZRccz2TufH11bWJ7NuVliiydIkJs/BFZpcu
+lQv8S7jueeeSc6ff/bTQdwnqmQMRi02N7d5440lrl8FEygeevCDv3H/g0/+9ERzFq80QhgKGSANsrB
+GLi0A8SIvvA6ihOn5Uzz88Ad++s47HvmNzh68/tomr7x8haXVLlo3WVios7NzmVdf/6NPt/YuJLCHG
+kvLl5msliCFRiDZ3cp58+LS5OrK5o93u12ydIjEkUQxUVRIvhtjqNSqxHFMc2qKe++99/zMzNxntCl
+QB7mzZd13q0qmLaJ9vAK8RHpVBKVrg2s/qtVoLggVJtQIDVKN0JFHBA4dG6JqBWE0XhkmpqaJK7UvI
+03RUBPyJnzn133a+Xap55hrJzgAY1pbcLaS2sRLjekju2FtChdWEabAiokyzSx8yMtdVUISB+SjvW+
+huwODNti0kJPwGntoxufLhkgxEjiMrhmXH5qgVvs3wUQDWa2QxyGuEiNCg4wCbKBQcUhUrZJntra5s
+vGJ9cVV6HPgxVeqtY7TrOFoj6tXXuONc8//Yq+3OTs9WwGRce3aNS5evMHFiyOUgofPfGjz8ce/4Xs
+mp+bxSkPpI2cxxYkkA2wxiKOQTSzx+kJD0uT2Ox/iqff/199zzz13bW5uwzN//BovvXiRlfU9tNREs
+WJx+cLsl5/9zC9urJ9D6UHB6csOBtM2g34bLl1c49xr1z/RaQ9qaZqSjQbUKgnVOMYoQRzHRElIFEU
+0mk3uu+8+Hjjz8L8xUVgO7YtxwbjuEzd12Q7VfmPLMgfCD7D5Ls63v0UqSxBoTBCgAomOHHFFokKJD
+DVhNcHpAK80UzNHdnUUv8T+ehIH91r82cnHzR6yb9cFLY02ZdEKM9UGyeTM58PGNCJpIEODCCTSlLo
+issAcClU8jFHkw+632+4O9DowZjl4c0id/wBgLTw3nYSWwkfAKtBJ9ElTq+7JaoKoJahGlbhWxSQRO
+YJcSiq1Okkck/WGH99d2vimvNWHgTsUyQ68Jx3s0dnZ5oWXPv9Dw3T3IzOzdRqNGp12j5devsBzz2+
+wtAS33XYX3/hNf/67Hnn8ff1qfaJkXGhSK7EEKHWAQMHbW8FZ4AOmpk/w1NPf3H//+7/1u5QMeOlsh
+z959jyvnL3G8mKHuenjJJHm3Lkvf+SNi1/4oe7wGkL00QE4nwMw7Fk2VoZcPr/yTdcurX2830uxmaO
+7t0tgJFp5nLNUa0lhKprEzMzNct/979m7/c47PmmdY5QVxFkp5KG6j30FMz+OOH+wLIQHXA/vWnjX/
+XZBgROVRiINhJEkSgwmlOhQEyQJ6BBhYmoTU58vLOkk3vp9ZgnvQqDnO0MpOvzC/nCna7/KL3oVRpB
+lKeiA6WMLf2CDCn1ZqES7EuSL8OR5yjAbknkHWhHGAaGR7+vsrN5B3gPlwHqiMCoZE2IfMT+eOxzGE
+7r9YTv4QPaIzL8QSYiqxqhaQrVeK+pCDSYJCMOQSlQhRpHu7v3UztKqREjIIB/2S3MKz/rKMl/8/Of
+ufePCCz8TRpDUYhZvrPPqq1d5/rk2F87D9DQ8+eQ3/JMPfeM3f26i2SB3GbKkOykV4q0iyyDP80Ntd
+I8qxRIRAUiwTrKwcBdPvf/Pfe7+B5/6J87C+Yu7nDu3xPK1nL2OZmZqgUo14MrVl37mued/+17LKsg
+Web4L5HR2u3zhj5+XL714/qc67QFbGzsMBiNmmg2UsHibEoWKOA6IooBGo8bc3Bx3n77nX3T7/Z5Si
+sAEN3WTnbVFiedFybIo9eUOS5/LDG9b2HzrDmz3fbIo/pFaIQOBI8X6DBMaknoDKw1htc7CiTuJk8Y
+foCvgBEoeCMwqJf4s+N6263KLpEPhY1VeKKVBKWRS//1gYhIbVBAmAG0QsgBDS63QUYCMIrxRqEgSV
+iTCD7+TwW6B8xS+8PF0tyJa3P57uHXsaAFXQG3+qYyClkxCZBygAo2OA3QcoLRGh5o4jEh0RGDFA6O
+d7qdYb0N/hNYG8pyl61d57ewrvPHqq79WaWh0JOgPc65e3eDF56/z5oVC2Pf++x//0mNPPP0Pji4cJ
+apEqNLk0LuS/+1LnIy3SO9KnNqYpHUw4tABRLHh9jvv4f0f/PA/uOPOO7/UasHZ167z+tltttYE2kw
+yPTtL7tpcX37p164uPotnkzB27O3ucOHCm1y6cOVTm2ubDzgHRsfkuaNRj1HeEgaSiWYVoyXWpcwem
+eV973+qNTM/908r1fgQUcnvk1jlTbo64/csbzbWsT2gA77znUKMSsU0jdAKYWyBYAkUXhU247nXoBJ
+0Uiepzfz+fiGMRPh3K6fhHePz/SnIcun30ymhdLGz1Zvna3MLr/mkjgwiVBQhTFCkmkajkwqqGkOs0
+RVFpaaQYu+7/d4qpK2igD9kqeS/ygU5LHbliu5DR8fBT+g4QEQGHQiCikHFBh9IlNbEcUxiQoyF1ur
+G9y++eflvd9c3QSm6ey1efuVFXn311U922runZ+Ynsc5z7doGL7x0lddfg0EfTp48Mnr0sQ98x4NnH
+qZar+83J6z3+6lTAQworKIPZmf6kAit3BdFcQLmjy7wwQ99M08++Q3fYQI9unChxzOfv8jLL6+ytWG
+pV2eQWrKxdeX0y6/+wSevL72C911efP5P+OIzf/y311dXvr/X77KztclgMKCeNAi0Q4gUE0AlCanWI
+hYWjnLmzIM89sSjP1Ft1jtSqQPTSSkPLCmFKIx0PHg/DpJb2s++hXdbCL/73YIRSsgi+JRHBUX9V3R
+6NUIF5GicCgmixmsyqZ+HALzaDzzBuzPtfMf4fPJPAb0c7g1nAoKkxsT8wm+b+uX7ZRZjjEGZUiZAC
+YgMMg6KeVokiBLBQHXPDPpLH0hGG89QP47wk6W68a2v7/Z3X/E2aBupwXn5z8jU9/hMPGyVRUqFQjN
+yOVaUilxKYr2g096jPWz/5MZgd22O7i9d2bjGl5977qOt9vYPHpmfQZic1s6AS1fWuXhhh70unDjV5
+Mmnv/l7n3j6g6szc3NF3WVBaUNui8G92Mc95nhXdka8Lh7i0NUt5N+K/6cEx0+c4IPf8OHVa9evfu/
+nv/Af//2Fiy2a05cR2vHex26jWm/S6fW4eOmVHxwO/GePza3/2u//zsvfc/7szk9qMcug7+n2d4gCS
+Rw16HevUatG1OtVlPYEQch977mbBx564KXaRP2fjSea42iSZeA55woVcSnK2ytKROchfp8c4fMtvF/
+/AOye0SItwO5SgnI4leJQCKUJdIC3MQxDEBVUUPttZAzW7F+Tgs3gDwLcf90HnzvYCQ/ZiN1cB/r97
+NMKDWFEdXb+16szR35ctCvFridTvHPksjBK1IFChEULWiYjlMhwdvNjjJafwd4GagLBxAHO+u0CkJu
+tgsfq2VICyv69nPT3clkYbQohsSOPlQ4lix3e+eJ02lhbZ+X6+V9Mz4nhSnvtC0sbN35hfnaS2kSNl
+fWrLC1tc+3qDsvLYLTg/vuf+Nmnn/7GX3nve99LY6IGvrRrLv3UnbcF+MoP8aR4nxUB6kUxHxuTT8d
+plixqJ0dGGIa899En2Frf/pWlleWfffHl83/tjfNLCO2ZnJnixG1NZmccmxtv8MrZF3/hmY3X/87rr
++z8zMZSTmymiaMmlaROEifYzBJHiulmjVq9wmg0oN6scccdt3P02OzfQwq8z3He4w+deAV9aoxuyIr
+T2hUzVS98ybP04NpYv4n3Gx9DtNAqwypTsBtUjpBDRFZHSYEyMcNhSOYVQVAljCd+vWCsqFv6CYeyn
+a93ASXBf8LMRcp93SGLxCpDZWLq2cmjx18L4yZSRXhvEDpEGEOuFM4IZKSQiUVGGWEyQunWX/Xp+hH
+SNRAdlBx+hUH/oS5soXhcEoCKh5QSpdRnlFI/JQLwRuCMKCSzAl0Ag73H5ZZBv8/a2hpfevbL/Mbv/
+PavvvDaK2smjuLmzDTdQZ8r19c4+8plzr5+jdEA5o/c/uYjj7zv++99z/3UGtUy6Iqgwkmw43nViCj
+KQWSF6rPzZVEqbybll4tOiXKIo+DI/DEeefR9PPDg49/fmKq8ub414I0Lq7z6yhKbGylRNMH0zDxRF
+MXtdvtnOp0W2zsr7LYXcW4bE6YERhBFCadOHCWKNVk2YGp6gvc+8hAPnLnvp6qTE58Bh5ASIcUBRQl
+3wBmEcrCe3fSGiw2lB+zg/fYRz+5fFbKLNjkmKDCaQlukHqCUwUtF7iTD1JJmAh1WX4uixrNj256b7
+AfehQP2d0/D5dZUvBSv9YfYlQ6BrtaZXVj45Xp9FmUqeGHQQUgUVwiSCEKFiCUyBEyKruTESY7NNn+
+I4SbQRtD9yrZQb2dj7UuJBekJAk0chz8iQ/W8U55cOVSgMUmA1II0T+mXgXf1+jWuL96gN+hTnWgwe
+3QeGRqW1ld5881lzl24wd421KameOKJb/joo48/xbFjx0owcY7NC61Qm5VBpASFwdUAIR2erKz5xP4
+xvX+9nAPlcQwRWKTWIDVHjhzjQx/8Jt772JmPBqFme6vPSy9f5uyr19jc6DLRmOXY0ROcOnU78/OzR
+LECOcCLHsPhDtZlNJtT1KoxlSRkemqCM2ce5EMf+sDzx+6640fQemxyeGiCVwSeFKrIHjzF5xjX9GW
+e4clx9HC2g/OtH/K+hZJDjPFEJsAYhTYCFTqkVGXjRuK9wgQJjebML1eqjXK8I99md3V/Fnz7L/q2i
+IPy7Vi7/6fxWNYKCWFAY2LyF2vVCQITI5TGmJAwqRBEETowyFAVKhHaQiggBuv7H8+yTgIpvrBe/E8
+6mcddxfEJKLQkigOklj/gsLnDg1GYMEBoRZ7n9Ed9NjY3WV1dZZRlHDtxnDvuup24UmG31WJlbY2rV
+xdp7WYkzRoPn3n8bz7yyKOvnbztFLWJGqExCFnyFFWZQI0vSz7A00f68UlyCA10eOPQ5QjGF3WhFgp
+vLbVqg8cff5InnnjstZmZmb+ZpnDt2hoX3rjO1Wsr5JknjitEUcSxo0eZmm4wGLbYba2R2wFaKwIT0
+e12mJyc4MyZMzz5xGP5kbvu+AGUgnRQvE9nb5LoU0Lt19JZNhZtyt8y+3UuxbpBYl3/454hQuZIJRB
+aFcoFZtz8Vihl0CYkiGJqjQmmpqZ/ERUVPixfI1/qE5/4xDuQduoC5CoPuuPyUMXlpS5nb4XTQuA90
+oH1El9rtLZH6cMrvn+6l+wQz3YIKm0ikyN1FVwdTANbNaSVjGGlRx7lkVJyoG34jMCg9GzZeJGkXpB
+7gSu9rCUjsCOEzRAOpC9kY610DEXOUFl80lzt7PWupp32R6elRLRbdLdX6Yz2eG31Gp+/dI4L3T1qd
+9zO9Kk7IaySecHiyhoXr13jxpUbuB4cq8a/9ReefupHvvPDH+au+QUCpxEmJs0FmOKiCJ3jRQoix0t
+FZg2hW6fd2qNPjXpzChFmBPQKx1eZk7kBSkuMC9DESKsQowxlJBWl2DbrrG6tPLu4eP2R9ra/Z9AVB
+O4YWh0jrEwhKgqf9GgPltnY6uJHQ+aqUxxJJqjkOcGs476HTnPmqYeZvfv49+m6+kyqLGkg8TIAYVB
+eoZ1AO4l0IJwtJPyVpS/fRIoIKWr4AchUI6REuXOMss/9XSfOfptUu8W19xLPEKfaePZw3tExQ4gT+
+nmT1c0a1fojvzF37MlPWVtD6hCUR0hbnsLyJnFQ946ne++WtPMrAlzEWx5Syv3H5MyxfzsxPUcQVwr
+Le60h1BAqqBgINcqE6CBG6QStQqSUfxc/mMB3y/QtO9DUPFyUe1EQCUU5fxKy+N6LciAMLrdMTEz8w
+sTExN/PnCN3FhMVttHLa+vsDQYktTozs/M0mlMArK2s8vqrr3Pu7OtkHYgjmGpO/3AtblANq8ioCio
+Gq9AEaK8LZWerkFYjvEEREagqvp/hcomRIUJHjI0mfQb5yGF0AtbQ7aQwUoABk7C33eP8+Wu88OzrY
+KPJk8fv3IwjydraLq+ff50bS4t0ukOcVTQnj3LqztPMHq2jQkOGQ8aa6lSFhRPHufPuuzh1x51/v9J
+o/ELRryxgem8RpZVvxfAq6ngMzrGvbk2+TZ7vTuR28HeldwXGE4UUAVKZQk1NGBwKoysIDN4rJhpTN
+Kdm/q2RIYEOb6YQvTuX9zt78v3nBqMR8oJm8NE03ZzTskMlFqhIgTLFqo4kVBQyUUijQcUoUQ2lTBR
+CfhZ9tAQQKpwvRg/7IwZfCsp7WcwYhCpP6bHaceFHVAkDDOKZYbdba+/uPbW10+Liles8/+p51vf6J
+JNTzJ08gYlDOu1dFm9c5eqlC4xaXZAw15ylYap/TaUIMRIvuH6WiVxQSaoIr/alHIQXYBXeSlzuyXM
+QvR3a7T54TTWZQOoaiBghE6SICi09IRAuJEsFO+tdXn3pDZ555sv84R9+IXnu7Cs/trXa/rTI1ZN5m
+jPo9un1e2QuJfOWI8ePU7AeY/AR/Z6j2xkw0ZzkPQ/czwc//BR3v+fen4wnm/8A4XDC7WuPeu9Ronj
+/N/mSiLINLMFhEFQQXpeSiW2su0JuL//PgpVv8r6FwqK9QYgAUHjvcCWk3ooGo1FIrxdTb9x5dnb23
+h9RqsnhTqfYZ1DfjGzx76KQ1HwNfe3DwsIJqs1jnxz0Fj7p+tuIpA1iVHQnTApRDMaAUgXx1Osy4Wj
+/GM7/X7jd1xBJ2RGsFqcGY1V3PRauvAl5IUqiiwfCkh6jtSZM6j+aq1ZweWX94y9fvMz6Xp/a7BHmb
+jtFc2aenc4Gq6trXLt8lc5aIdwchwmJqiBSVdtd3v2JN8+++eNpK//U4tG1n5u/vn7u2G0niWt16hN
+VVFLcJSEEikKvBlUnlD2814g0hjwqNh4LaR9GGYxGltWVTa5cucaVNy+zdGPxvs3N7Y+1d1s/uL2b1
+ZYXt9DKksRVJpsjttsdLl++gTWS6YWTBGGM1k3mF+6hvSPYFpvUjk1zxyN3c/qhB/6PaKLxo2BJh0N
+UGCDL2b4U/q2LWx40zYpB02SR0guHND3IlshGV+53buXHtOrhshzhBF4U4xyEQhAgVYQS4PM6o1STp
+wGN2vwnA9Mgtx6txjYo4mtiPb/rg2+ffHl4+q0TRHX2U3Fz4X8aitXjqbJIYZHGISoCtCsq81JEUwi
+P9znQBj/6x7iNv4SsI0QB+C1GvxonwIlCAkK+jXWZRJUSCK50ZlRUGhNMHsn/pqhcS9u5+DtUatTmj
+lCbmQcTsrXTYWV5g531bcigUokIZUx/tw/ZgMnpGLuX1Vqr2z+2ubz7YxfPXXmmeXT+P1QnGr83N3/
+03Mz8DPWJBiaJkIFGakWc5vQ7HqSjZVJUp0V/aNnZ7bG2vsva+g6t3S5raxv3ra5sfGu/O/iItfYDo
+/6QdCRQgwq+a+i7AcoqlNAIB8M+7HWGfP7zz3Pv/Q9x2x13E9QSmscGzBw5zqMffD/3v/+xn5RR8qO
+FOJEniCtFs6QMd7CqAAAgAElEQVT0u9CH8JRe3Nxn3G8PZeWGpgfAOrm7zCi7+I+lWyIQe0hhSxn/g
+yGrUBpJBWSAyCdRKKJodrFanfkUhDhfKoB/FTiZe5dVffprIfBu/V4YAbJO1Fz43zO3+s/T0RCpIY4
+sVIKCkqSLG+d8wU4vArCPEIOP2HztexWjn8cUO6uiqCVUKS447m8qcauf+7g+yYqftEIoxeTRY8zfd
+vePNo4u/p1+PMHUseP4MGJ1c5tLl6+ydGOZdJgRmJiZyWm6OwMG3S7Ga/J+ytbKGoOtPVLg/2XvzYM
+sO8/zvt+3nO3uvffsCzBYBhgsFCASkLGQEjeTFBHGiu3EkURWYkk2VYq1REuKTiKpXLTlhFoiS1YiW
++WyltiyRFKiJHCTCHMndhDAYJkZzNbTMz293P2c823545zuGVByySXHBinNnbrV042pRve95z3f973
+v8/weF8X3TZ95/j6VZv9HZ6Z3dmZu9ovNbufJuJkdj7P0FZmo1eWW27q0vj5xNsg066SlpTeZ2uWtr
+enBi2sbN507t3pHWbg3gNxX5AYtNFprBlsDptMpURQxm87Sn1jGgy2SDLrtBluTCSvn15AbE5Jsns7
+MXmZ68yzsqkBX7aVlOruWflhuGza8QEiPFLLaKPgrssFw1QV/BaZYX3Rqu8E2AVZx/vR/L7j4kKSP8
+EUdRSbrrX+lqQv1GdyHiCJvAykzvf0f0tFcvT2OK+XL1WUe5NdMtfy14vtPXf2CAiETos6uD2X2uh+
+YDooDIk6hOQU5BeEIqkqt3RbXCukRopo8uXLlZ6Qo/1Co+DIyQ5IhRIwjqofC1cnB1rvPP/MILytOe
+WFgamDoecg1mix05+nML7K2scbZlQucOnWa8aW1ykyrNG5cko/6NEXMnrklds3OYCcTNjYGmCAoBBi
+lMcFz/rTcp5N4n4j0d6AlPlIIrZhpSfpbA0IQSBEzzQ0hVFuz8WgKKLyDWCcMBiNcaWikGd57GkmCx
+JPOzZConPPDdaTTzPYWyM0lJtMpTnhefvkkcaPLHXfeRdbusbm5yUtnVnny+dMPfdP1Bz4cAc5W/Jx
+GGgESuS0sCY6A2g4jqoFMcieQWwXwGIpiFWdPzXu3+jNajomEqYxG23lhMlRUOwHeawoH1mnGw4Qon
+T09M3PoQ9DBWomSMcFXvk4h/qNGy9eK7887421zG69+FHi0AJ3NELcPfDA3o1/yOiFEmxTlCmlTVTz
+MbV2fkFdScBEEf3lJePWz+O7fIXRBtBCigZJRxVgh4HZSCq5u2lUYCGQEQWI8DKaWC2uDxRdOr/z6W
+n/MwZsOcfbSKufPn+XUmdOMt7YAaDdbRD6nmOZEGpT3aGVxJmc8yMF40Amj6RSnFWNjKI3DSwVSUOB
+rcK8gEpWlKEubaB2Rj0sEEbGOsaWrAE5Bolst4nKCFIJunAKBNAXSQJY1SPUMG8Nz2NLhSkEr66Cyj
+OFoxHj9MmdOnWRufoHdew8jVINzF4d86jOP/fpc1ji0b8/CpUaiUehKsxlsdWiWsgZRXcl+qGmcr7r
+wbbHKZHIGY87/rJYbS42oQAtZAY6pi06Fyg6GxlhBWWqKUpOXTZJ07oNRuhto4J0mSqLqfy/kFV7rn
+yEx+3oqv6/Lbmf4c4AbRpZ18EmE1OmjaZK+y+F2lz5HJ2BFUTUplKgCSepmCaGCEikC+bi4zU3ERa1
+7jxKaVbdQRBWhWSqMLypVxrYaNzicKVBSQtCsbw7IWglnV4d87ON/8gfnLm1e3+jNMzGWV06fYXNzn
+ZdefJawtorINDONBF/kuKIktzlHDu5ld28OP5lUX3cGhKc922a9vw44bDBM7IjcjfHeErBYlzPOc7z
+b1t55nLEU5ZRQGlIliUWgGUlS5YiFYbYV02vFaEoSLO2ZQJYpApY4iplOCzbHA5IkIWs2MKHEllPG0
+yFSRczP72J+bi/exaxeHEb5ZOP1+w8d+bVWo3pNtRA7xlXqcE3na4Mz4JwlOEusJBqJMGucPPFlTp7
+83Pe68vyPtzJLIivDsVRRta2PAFnibI4NEqE7GNNiNIJO65sfW1q6/u+qaL4qvpAglaop15W5+lWzj
+Z0cm6qw5Z/KibhWfP/RDyfyajtJjBQx3olV5/3f9qIkqBIV+4rytb1qCV2lpgaJM6AxiKA598rGO9c
+v5B+bbe9dIZ0Fux1b7BDyivBabHfxts+AUqOShAtrOZ/74pMfeOHUue9WSRsRJWwNBpw9d5pnn3kce
++Yk2fIc33TbUdtOI9nfWGcyHTE/n9HOUqLgiQOkUYSOFIUv2Bz3afRa5C6nKKdsB1XmTMj9GOdLkqi
+B1hIlBTIE8JZYSBqRohEpEulItKedSNIIOg1Nu6HIYs9MNyHuGZqtGB1r4jSj2emxuGs3Nx69ietvO
+Ex/sG63xluSvGBaGoKP6XV30WwuMR0HJsXmgUbW8nt3Lz4SKXAF6EhW81E8Qmp88FgfUEgiJdFSIox
+lstnnpec/xdNPfuau0yce/4iSQ+a6GY0kRoc6FDMClIHIIWOFlwl5nlGaLkrN02nf9X1pY/4FZLc67
+4loZ6tZZQp+jVbpWvH9pw3Zr34GDJXaP0ZUw9cXvAg3BWFuFcqitEfWtDDhq+G4EJVI2TtJsGO21ic
+88aWXeeIrJ97gpum/2t3ba0TcrIp621ERLNZbvLeIUHVARQgMC804hy89/vS9X3r8q/96aqDZnmVSl
+pw6eYKXXniO0Ssvg4b77nv9//Tud7z1HbfdcuO4mSXfLIJPk5ai02wy0+yQKMV0PGaSjzHCY5Vnfdx
+naqdYTIXFl67GJAaUqpQ+Eg++xJkC6Q1ppGjEmkQHOs2UZqrptBMamaLR0MSJR2lPp9tAtRxRlpC1O
+xy64Sbe8Nfu58E3fxv3v/GBrdtfd9sHSjd5+3S0tbU53HqbMR7nI+Zm97Br6RBx1GaYb1JMyzcePHj
+9J+ba8iwVQOCqpJtKFKGlxDuLrPscfqvPKy+8zMN/9KuNrz7xxY9evnRqababsHd5gWYjQ2mFiBRog
+w85QTpElFCWGYN+incLNLN9v9Xu3fGPEC0QGT7E1d6kHtaHYOsZ6X9o5bti2b525vsLyXIqUuw2Nkm
+qFBV3fyKI+fcQJrHzplav1RSsUP2qQkiUCkhpuLxyjrMnz/Lo5y/fduY4v9ZSB/+bW9+0F+JK76bwe
+BxKVYRlXEBIBd6RO3j+5dPJ408d/+3cwszcEkFKRlt9Lq2cZ/2VExAJjt127GPvfPubf+6d3/YAzST
+6p3fedvRXXjx+/Eeee/GJH1h75Vx7cuEyRV7ghEc2EqSWmGLK+tYWnd4MqUyZDIYUZVHhGAIUdoqSA
+i0jtIyQIhCrmHYW0UpjYqVpJDFCBJKGJo4laTOrViY8ndku01jSm1mks7CPIze/joM3HRv2FhZ/Lmr
+onxnn/UHhBpTl9OcGg8mbz13aesfWxTVeeO5Z0nSR/ftvoNVa4OzKOo899uxvzzdvP7TQoSCAMwEVS
+4wx6KgC72LrzIyi5OWnnuWPH/44f/LHn/g164e37dqb4aaKcipxVkMSqrx6ESomqVA4FzMtUkrbJos
+Wy2Z64CdQHfAK79VOvLX31Cd1f1VfWn7Nue9qs9i1le8vtjIikFXYV71SgpB+S2CHAfc2ZwtUrUQRo
+U7iqVqkVe76tODZJ0/x9KNnefaxDS6c7t+CbbTnm72Pzy0uV99QB7xzaFXh87yv1Ca2tKyMNI898dX
+feunUudfPzC7SaHTZ2NjizOnTvPT8V5leXmHPgeWNd7/9Tfc99M63lTceOUirmTE7P1McveXoH1935
+Iafn59b3Gynrf1JnM4TJE5KchxDU2IiiU4TvLcYW6KVJGtkJEmMEoJOK6bTSul1mvQ6LWY6LeZmOsz
+MdOl1OzTbDeI0Jm6lxM2UxmyP9uwMrbkec3t2ceOtxzj2uru4/a7XH7/u1lv+cWt+5m/5KDwsElXIS
+NCd6SCC5MLKpd9bObf2PfmwyDaGEzyC2blZ4laP6WjC2oUL7WbauGl5cf7fxqpi7jgPKlIUhSE4R6R
+jmOacf/Y4n/jwR3n4dz/yT0+eOPc/SA+znSZzcx3mF7p0ZxrEDY9jjNAWYomQKca1MMU8kTpAu3njD
+8XNw3+EnK1VPDF10FI1NxShHg/5GsKlrr5oroqgE9eK7y9cfF7twFB97firXvDwJUJ4g7f+ei1kxUe
+q5f47CDnvGaxu8exTZ3j2sbNcPOMRZZP1C5N7NzfG+fWHDn+uPdeBJAZnCVIS0AQnUFoyHOT8yWMv/
+I8vvHz6R41TdGcWGY7GvPD8cZ7/6jNcfOEZFvct8+1vf9M7/+uH/voLNx05iFQBFwxxEpM1Wswu7jb
+79x38/NEjR3/xhsM3fXH3nr2mMz97KJuZSRuzPbxWjPKc4XCIVppGo0kkI6RUxHGCllNUcCgZSGNNF
+kfEUYXWi2JN0qhy41szM7QXF9h16BCHbr6R/TffxI233bZ1y7G7fnPfkaM/3ty96x/IVvZ5EmFKYdG
+xRmhBGmV0O3OMx2W5cn7t0fXB6Lt8XlBiSVsR3ZnraDWb9Dc2sNPp0dlOb2V2pv14hasJKF0Bg+M4g
+iBYefY4n/zwR/nCw5/80ZUTr/zD3OWkKqKRxbTbCfMLDRZ2tUg6npIBIrYEpTAhw5gekj000hv+KEu
+PfD9yHnyCJ6pOeK/yYzsk9kqP9c8svvB1U3zfkNvOba9RtbW0eCrrjJQRUrZ/QEbmKRVkiqvORUI6I
+MeZkqKYMuyXDDZzcDGzrSbCzDHZnPL0V57+4L//5CPDBzL5z5aOXYeKr6S4Si0opoETJ07f8NjTz/6
+KKT3d3jxFYTh75jwvPPcC506cJGq1efMD933wPe/665++55vuJFBgyylp1qjGym6KoEmWdWktN9i9s
+P/hY6+/9+Giv/m+l8+cfOvZyxfe/PzLxx84f/b0XZdXVis3gvWMB0OKyRiAVKxTFAYhFN1Wh05nhjR
+pk6VtskabKGvR7PaY372bzuwMy/v3Prr7wL7PNDrtTyS95sMMgAjKvCAIi0gEKha42ubjPCwu7eVb7
+n0jq6uDT5fuTz74/MmXfmwwuMjLLz1Bb/Eu9u9aYKY3z4WVSzz62FO/MtPJPnPocO9FpMCG6tyej8e
+ce/5lPv3hj/L5P3z47108dfqDDaGxYonEB9xUMt6y9LdGDEd9MqMgNRgc1gS8VcjQIUl25ane9QPIO
+fAdvKjyZUO4oneoqIRVAKl6tZ7mz9K6XSu+v/DjStRdNVCnCkmRaFDJizK034/J/x/vYvBxlbKDwTl
+DXkxYX+tz/txqDTXTjLYmQMxwY8inPv6pX/QN7IMN9SvzB5YQjQxEpZU8dfI0n/j4p36nYI5ms03Wb
+HBxdYPV1UusrKyAdbzh3ru/8sYH7//xG66/niSW+KCI45SAoMAQqRjrIUoqPguj6ndJZma4qXPs4Rv
+S2x++c+tuRqNBc7y+8U3Tzf6xyVb/xvFm/9B0NN5jjFmQ5enu1tYgCxY1N7vk5ueWpllzpt9sdNbSV
+u981uye6iwsvdBdXnoGpR8ji8ckUJZVYam0eudjmeA0WAwWg0Lhg0AnCTFw7NY7GQxKVi9v/vjFzbV
+v3ZwO7u4PLnH+/AVSpTiw3GNtbYXjx1/g+kPLv9Pp3njrzHxGaT0mzzn5wnE+9ZGP8bnf+4O/u3Hy9
+C/qSQEURCyjvEf6QLCKySRnc3OdxkJMM6vSi0zhCQ6ypEWazL4f2XsRm4KrzdL1TaJC2m/3VARfX6a
+hv4zFJ0bVNkLIeqOR1JniIEMKpL8aVHK3S7LvkaKLzc8TucvErsRcXOHlF5usXZhhOikwE0/iI5Zb8
+1Bq5DNDzpon//nZUUfPPfC6f6aP7IL5FpMLF/jov/k3v/DyK6dvKW+9hyiTXMo3OXHhZV448RQmv8x
+dd99sHnrr/e9554P3MtOJoazU/iDxEjQRpQOlxgQdY4QjtASxjiAofFlFac3Oz9Ob6405eOARoXjEe
+EthSnywBCEo8xGXXvwEXbPKof134GdvZ121CZGj6R0ZTbxImUYOKUs0AeUTdARWGMp4vLMB2+4Iylq
+LEomKFk2ISBPLHcf2c/ny/WxtbL7nsSefP7l2fjN6KvwuStxOt3eMqBd46ZUT/Pbv9W9RvOsX3nDbs
+e/X0zGnnnycL37sY3z1Tz7196YnT/xi25cktcjMxCfZ1ztIK8yRXkxxl2bIxwm5yZnBIwcSVRzCJm/
+ANe//51ty/69qoCk8Qk3xIdk566fR1czVqH7+6UWuDnO6Vnz/f/Q7r3yUyLoBI+p5uJARQqXfi0tvl
+7LxBmwDSQM73mI0sozWJ/jcEYqA8pJIJyQ6whlBpCRnT53kjz9R/uI4jNoPdL/1H/vJkM9+5o+//dH
+Pfun9QUnSvSMKr1lf2+DFp5/m0tlX6M51ef29d3/Xt77tW8/F7aSyOGl21BZSSKLtzreOqlVGCoLzO
+BcIrto/JVFc/3oxzlUgolgpoiitxyyeqUrIG7O0TYlo9FBZl4Zsg7JkOFQZoUQMosJNyKB3On4BUGT
+sRFTvkFJ9/WoGnDEQKZJGytLuDnfeeTtrG8NzIoq+6/Nf+Mpv9C+scKbVJA2eTMesnjvN+ePHyYx9f
++hvfSIui49+/pMf50uf+tSPDi6ufDDTEcoEQjBodJ0EBT4vmQ4dww3NsO+ZjGA4gaZuEiVddNr9otH
+x95Y7IyjJTpz1X4LHN+jKF+3YfMTVbs0aQ159KUHSfC/Sfl5GvRlnpvTHigsXc0aXxqhSk3gIWtOKu
+rSSjNJ5GklK2omY9vs8+9gTH7TCLAxE8cEvPv3Ub5z76suoJKHVeJlps8XJs6c5/eyzdLtt3vaWB3/
+tzW97428evGkJHWp5FGabXQciQYTqvuy8IkhR+d9UHaCJwgePs5YQqlQfESofm0ShZKXOMaUh012ya
+JaUAnQXaBELTUBXYMQ6CksLWXnnRI1FrM9ikUuuOA7E10roQEVxzaUQKA37D+zlgQfvpQzmN8+tnHn
+Ls8+Nvnv99Gm+cu4MmY5x+ZTpeJPpygrTc+d/Iwv+4MvPPPljq2dO/VALiVQagiAmodfuUGpDR7dIZ
+ULw4EeeyaZnMs7IywbNZAGd7tkkW3zvdljnzqolrhXfa92kfdXsZpvTXNlQxI4RNsjsuCB8J6r4vdK
+N2dySnD43ZXpxSlREZE6hgqalYxJAK0UrTVAV0ZXBpTVOPPPcDxWKH2rbmEPtBS5cvszpR75M3My4s
+HGZFMf933bnyb/x7ne879gdN1OGgFIei6nmTsLXQ34JIULUANyrcyIAgvD0tza4cOEi7XabLK2CHoM
+QqCih2UxRCiIZ4S3gEqRPwMYVp7L+1V8FDwrU7oCvmZK6qzg1r0qJuvLF4KocBqEVOpbs27/Esdtu4
+Olnrnvf5NLW/aurq4eLcoLF0yBmVqTYwYBnvvTlpsyna9pZZuMusbco70hURitNyOKUTtaiFzVpxU1
+E6hFFYHw5MB61COyBdA+kB74TZo9LYpQHvQPUlfxleXyDrnxy5/r62rs2VIGOMo7wZCjk7yPt9wUx/
+aXxtM36uqLlW4g0Im8HjNQkokumWuiGot1uU9qcsSkxhSMpPbGOSOM2Ytf17Ern+czzLzHsXyai4Na
+bb+ftf+1b3nPn0RvDbLcy4loqSJDHVnFhQtacegNOoCK90zlyziK8wzvHhdWzfOGLX0CrmE6nQ7vdJ
+Y4atDodFheWmZmZQydxNXP0dcu8XsLUTvHVPQexXX+vWjcq09TXXsDh1WqsKtG6ztRTgiTWCN3ghiM
+HuP++u8Pqky+9Z+PMqScTAomMEd4x32jTUAqz2SdyjkgrkiDQVpDphJlmk1QrvHXMp7M0UHRlglaCQ
+T6h7GtCuYyKb0Rle74Pln8fOgQv0dsKmlf9kNeK77WctO98CFff6eutlUfVsyCJlPyy0uWiihb/d8Q
+CXZWTxJY886BipE9IZEYjaRDHMT4ouiJha9yHYcm0HJN2uhxsL7A7mydTXY6fOsFYGL719ff84Dvuv
+fepvQtNxgZkHHA4rgAL6qP+dgC5EoRtbJ64kk+nooDUHmMnDEcbKO1pdxo0WpJWOyFOBEp7Yg2TwoE
+oa/ZlCcHipa6htG5nZ1A56AxBOISMaqW/qVwZf87rWsWu1ZOx4Ei14sCeZe6755tZf+LEU2unT/zg5
+tbW/9lSEutLVDFBCIW0JR3dQJgSgSMloqVTmjKhnTRIOhFLrR6xDbRUhYDXskXa2suu2WP0Zm79X6H
+3y5YGmgbCS6KrwMqvis29VnyvzZwvAG4HzhxePUmtJUc2VJKyBEGSLPxkp7n79m5733ui/BTTcYnMK
+6ye8IJYC9JEYcsxG/1N5udnaSmNDBJJRDMkxCEmNyWvO3iYxUaDsTR/eMvu3R9ajBOkhcQanA/oVNU
+6iiqa2AeB8PXXZKU/tNZWmQNa4pxFKsmufcvcfuctXLp0iV5vlsXFRXrdWZKkiVACE6Z4U+JlIOgcX
+F75F+WEIDv1lKtEygiEJghHwBBQtc3H4TEEPb6y5d3Zpm7fKGqynAJjApSOEDyCgHKOXpZx683Xs2/
+3wofsePTmRIW3K2IyKQhFTlckNGoXSUZEJ0lpRzGZjOkmDWa7PTpJRKI9LSkJ2jM7O8Oe6+5iz4G7f
+0cke34yJ8LVISq6ErOC8wQpEDWc+FX3i2/QM+A3ZPEFcTUtwFWev+Drs15FHAtU71nFAtEI1RLtZO5
+f9hqL72kkW1glsDqQZS2CV7SyKk+837fMdJtEKuBLQyNtEmuBH+fkY0PwgtKVHF5cxGbqY/RHnH3qW
+Q6Lo8TLXdARFGFHyOsFuCBqvkmVXamErnDqtdbCuoBQ0OvOcOOtRzlUXo+UVRc2jpNKEhckcZwQ6Yh
+BvglRgVAlaAPaEESoBOfCsY14qP6I6qMItY87YITZwdTInSK8khZkCk+UVt1VLXSF5Chyhpc3WD1zl
+ueee5rxpI/S7mPCh7drBJQez4RW3CYLklglZAjaMmY2bdJptGjoGDEpkcGTKEVa13u32WXv7uugd/h
+fYmJhIxHc9tAgVO8xwRIQVQMpfOMX3jds8W3T4bab5UpsJ5xUhx3rDEFERLIWljkBpQvjtdF9o7URc
+piTyJgkk0Rao6Um+JxBf4qSEik8ZZHTzFKEs0QiRiqFdxJPIDjLeLCJ9sn/Nb44/bZnPjv+wOba2lc
+PH7uR3vICemm+0iZGgjpMh6CrwBdb7wyTONqZtUVxmxAMFk+vt4y1ZRUGKarsh8pQrBBIXAjotCJDu
++BrIphgW1Zs8CQIgqiARdXaK/FB44WtBwox4NAEfI2d10rWoSugoqiiZVtPaQxmPOLC2Vf4yhc/xxO
+PPcpnPvGpW6ej6U+5snio+u4RGsGs7NKQkqj0zGUtmlLRkBEdFdMUikxKmlkDbQsaqSSRgSiOcJMJ0
+7MXyUb+PmLx+9ujuh3mSrAgPEJUcncp1Dd84X3jrnxXSV3kqyJN62y6SGO2GzEehHG49a3rB6tr7wt
+bY9IoxkkHSLSWFRHC1Yk6UkKIdy54WW8XvQuVodU5nHdgJGZsKHMesoP+Q3Yy/ZnR2uY/StrtrSPHb
+mHx4AHY16pWwClMhIeGpAafVabPegWvBOLxVSL8KgY6IPChXtmvijcugsUEgduGPHmJU3WAJhkhVNH
+RQUe1jSZCBoEXMRJwxDsCoUhYnC/xtqJIl8ZjvUZJjbWei+fP8/gXv8BnP/0Jnnr0i72L58/9hED9S
+JHnSOdRIiVSglQqUimJgYaSNISgFcV0opi5dptGHKGEJMYTR5JECaR0SFXtWszWiGxt8300s/9bxbz
+s1JVgk+09chAe93Xjxvur3HB5FRPr6r9fsZN4AgkCjBXDldV3bL5yRoitMVmkCVrVYKUauSPrTHexH
+aioELV41ztwweOExdeQCWs9zkFuDZMyZ7i++SPr5y59T9DRP1k7c+lDh4/eOLnujqM0980jZmKaXYm
+ThpySlGZdSPUY8KqObZAgRXTVKEDtQLy2bzzexRBiJA0QKXiNldRhKhLh69m+Ay8rUbivx3/oajIa3
+DbIWVdzSVmxPtMQGE1Lnnn2eZ588mmee/opnnv8scbLzz71D6bjwf+cSTrBKwSeGE0qNZmKaHhFS0U
+0hGK+3aCrU5pS0U5juo2YRpSAt4gAWaxJYk3AoyKJloJicwPOrwj27H5H4vj5oHZSxF41D/Ffh5kLf
+7W2nfV2Tb5Kx+d3znq2fpOEr+VdRZ5MVi8dzVcvzjXKnFhHV2BMoQqZ9FTbGikCvj4/BukrQhcgpEN
+XzVPiSID1eGvxJsdOppSTknJcdpyQP315de2HL54/9wunz7z4S/NHli4s3bjM0k2LpPMpUhYgFisWp
+VTgVXUnD7U/zV81+5NXwk/U1f0kkSCICV6D11VE2HbM2tUJRRK8kCh5BWQSqDSTwdSNqpBDKMGVbKx
+f5vS5C3zuK4/z5S8/xZcfe3zX5qXL3xem0+/35bCXAJGsUjcTUlpRSlvFZF7SEJqGUnRUxHK3R0trY
+g+JEMQyEElLEB4pBFF9RPBSEJREKUE56JOfOz2X3nLkqGx3kxhyBzUfpj4s/+VpdH5jr3zbBXhltZM
+7e7lqmxYqu633MBzvyS9ffC/9LbrOEym/U3zOORSeIEQNSAoVk0RUhelCteohAjKqCq8IlaNdElAhE
+EyVCe8nE4yHcZH3htOND5xefe4D/jHzL3oHm7929J4b/v3tf+0W9hxeBj0EkVRPFVORliNkqLDvOJB
+U2IsrAKkq09o7V3M2RW1UrVYCvTPkNGBrXikGIad1vrUGaYlCDqEHlOBGUPTxeZ+Lqys88vkv8IlHP
+sfnvvzMfZc2p989GJj3SXQ1La1faWsDs8S0dZNO0iAJksh5WlIzGzeYSVI6cUwnTolw6BCq11tWabp
+KKZSXlQFWK7yO8ALMaMBk5SzppfPvZfVX5S0AACAASURBVD79J5rohKcSpm+Ha1a3QXut+L4uDn3bs
+7N6K1J196qEHomsLsjphMml1b8/vnhZJnlBSnUnrjieAYUlyFDL1KphuNQRPkisr7EE3mNDdecOQlC
+OC6zJcQRwDucsRTGltFB6S+Es07UNpusD8qj/vt4wel/aPf/k0u6t3+o0Dv52b37hhFApRA3QTRAdK
+hZJC0hROgF0JZUL/qo9p0Xi0DTRuDpQ0lVFJRICFilzoGLcICZIOa32mEFCKMBPYHqeUAwxky3K8Tr
+DrTXOnDt93cvPf+5vPPf0U39r/TJ3GF9BsIO1FMESI4lJaTUa9CaBjmrQlQ0iD7H29OKUhaxFL0nRP
+pAoyOKYWAh0tN0cE2gNDdmgjAQiq3I1pIqQZU6xcQnOn5YcmP37JO0flFETJwTCKZTabqdpvr4AgH8
+Vi09ckU1eLV/3XOVUDuBG40OXzq0cmmxcVqmHjhB44eviq3LhJKCkrs93onZMCEQQeCGxwhCCw3tbU
+a2LHFeWWOkw1lGaCYU1dTRcQATLJN+iVH26PTiwO2PPLHckdvWO8aXJB2Xc/IJSyce0bj0sVPdRrWc
+QqodQMwjZAtWugjG3CcxCbOeVIbCEoIEcRQF+CmZYEfdUDnZcubxxYIe4coswzTHTkrwckTMkv3SKf
+NzHTvt3+aL/1vGo/4619fV7YnmB66+DzSms9WFaVq9xJGNSH6NkhHGKGRLaMqMlEiIZaOqI+VaTuax
+BpgQ6OGIpiIVAKo/Scmf11rEgFilWemSaISKNlBBLiZsMyVdOq3Sw/xANechHyakg9I5hlr80ZfcN3
+3DhyqD4yj70VYEYhEAxmswMNta/vRhPmBGCTCsmZVHTAB34ahsXCQg+YEPAW0+okxyFEFWR1zh0hyO
+SgpJtZF9OnueUxiB0hNAKpav7s04li4sN9u+aYdd8g3bmScSU8Xj1HimSe1Ctn5aic1HquUe0mvm8i
+kZfEar3hNbjSSAl7HBnFLrWVzlvMDatVl5bQD6EsMFA5IgoJ7Mjys0xzhsmfoNxvkq+tcVoa9jYGq/
+fOXabd6v+iXvLyfD+RNqlRuSZjIas90cEH9i9nHBwVGDPwKSoFsxEJ8QhQRMTxwkdH9PUGamISJWgE
+yf0Gm2acYz2hkxFaFnZo4K3SKXQuiKNy0jhS4/1vsL1I7CuMsD6PGe0uUY6Hny7K9o/RSucEuJKNPd
+2k+pa8b2WD2MhhlxAiSRBkriKk6sFFDEYB9p6wvrgR5PVTblsPc0ENtYuEssmWmucUlgnyEuPk55UR
+TSFrhiYoUCEymbqlKWILQOfM7QFZXtEbidELsKNHfHQ0kTTV5Zhq+RyvIndPWXXkZT2zU26Bxxzu9Z
+ZSjZoTQ39eBcwwoUBQqwsRVH0HVEUfUd1BvXoqHHcWY5L3XhJiuQV79S5INKLSiWXcaHvB+fHifXl0
+AY/GH1J+qDivAzNydR0TennN/qjJVO6vcPh6GC/3z9SFMVNwYubiqJgmo/Joo3qeAzEcYVfdLaN8Io
+ZmbBPXCSJA3MKhjlIMySLNFmakkQtjgymRJHEZBLbUESdmBCD9o45H9EKAu0VIY4pYgiRIsQRSipcg
+LxxHh81KLUHnyBKyYzz9LKI0eo67sQpqeaXflSF6G8aD6qeiygzpKEMQcxcK77XtNvCq+Bwr/pvzlX
+HQZfndxeDwUEzyVGlwTpLrOrcu51/X1mhvajOdYSAweFDRafWWqJCwBcG70oiAsPcMp1YnI8QcUzUi
+7DBYooBuR/S7Dhm9qUcuq7H4f0ddi/HtNsgoup7OlvNGEIAX+stfbB477HGMw7jm6zhJoGGEFOWjuC
+r2V1ZWkajAQ5BPrVMpiXWVVrWae4Zj3JWL22wtTmkMJY0TQHJeDzGW0eSJIzqOWMcQ9Z0RFFlYxJUO
+InDN+xjbsHS7m5x4sSEyxvgzSaNVoP2TBc/SBCNhFYzQzdisigmEwKpJGQJ1lXAXKkFiZIgBUorZL1
+6i5rPKWsBgQ+WMjiEFZTGs7W2Rm9r66BaMHdLGX0l1PmWqKhq54ZrK9/XQfFJoquHrpIqn0FV/UMzG
+e8era/f7qdTlDV4Z4iTiNhHBARlcHhV6S1FqMYT1nmCtjjrcd7jrcfZkmI6xJqCoATFBMpc4ZViag0
+jM2HoBozEJqprmNsVceONPY7c2GJpOWJ5JiNVAes8LkqQchvs6ncQGN56rDUYY3AuYMqqILyT5FNDW
+XrKwjKZTOn3DVJqxtOCrf6I0ggCMaNxyfrmiNGwaoQ6BwRTZaFTfe5cTltXwTFxQxFEio4CzhXo2NG
+KI8ZmSNJusetgB6dBvTJhPIRCXGZrWjBs7SdppzSaTVpRRCoVWgaiSCFaGYUtEUJUNi0CWqmK4amp9
+JkuqmRrQlb6XAU2VDkapZNML14kvXz59uae6W7VjCq7owAhNdvJD9eK77V6SMnVbZbt4gsCrNzWK3r
+Ga2vvH11YTcR0irKWYC1KS2IUxjmUr9DikoAXlb3HBl9hA4PHuJK8NBRFgTAObT2+CBRT8CLFxgljY
+DM4xqEgNAzz+yUHDkfcfH3MgWXIspxWFCFFggkxZdxGUNQz7QpDDwEfSgiO4F1lgK8s+bh6oBKswZc
+Wm+dMxwVSakzpqsDM0lGWnn5/ytZmrYuWCuccZbkdoSBxzpPngGojhKclIqJEIWyOcY4YRxSmBG1wj
+NDtlKX9TYglK+dG9DcLxqOCc/EScUMz18wq8bSUxInGKY8RDhFJSjzaByIX0Hhk3Sl2ArRUFXYfWcn
+5tMNLsKq6IRX9LdzaesJo8H6yzkeErAYMob5ko2vF91oWXz1Irgkp29sQLyungwSKwdZbBmfP3TK5e
+JFWnhN7hzMlLoC3Ed5XWQhBhtoB4XGumptZ65BCYrAVOdp5lKhyH2w+wQuNShOKNKYfpgy0gqzJzFL
+MwZuaXHdQcGBPi4UOCGmJtcNLQSk0RZRAUSJE7XBAgHdVBzPESF8NlqsbvAYX8IXDFxG28LhSoVSEt
+R7vQcoq3dWUpsL2SXBOsN535CWkicB5wXBY/ftmU7I5lOhI4aQgRCCUxQCZAl1OSJoZ1njiSNOamSF
+qesqwihF9ihzU3mWypT0ksgFbOcIJsjjCYZmUOTpRKAJBVnoUrxxSGVCKEBzGVTcUhScoj1cOpz1BB
+YT2MBliL12Ctcu30J17i4iyj1tZye5CrTu6Vnyv1aRBVFtOEXgVIc7tGEhtOllfv3WyeqEnhgNSZ0m
+EYFpN5gjegncIb1GiTo5zFu9KvAfrHUIoSu8oXMnIGArrGRclk7xk0jQcOXojSzfeyKqZcrp/ga18l
+UZzzNLhBnv2CbodTxoVKFmidEKpIpxUjDE0VMWl9EIQgq9XvmpvJYQmeA9BE7zEm4ApDDb3uFwRygQ
+tHCY4TOkoC8d0ahlPLc4qojhi0i8wFoyB0gacDeR5LcQTgThUWQrSQBgZgi4Rqlp5/DgQ+5LgFRkSF
+ac0eg2uu3mJG25t0m7NcfD6N7EUZYiVTTaffpH+2haRV7SkJpEVLkNIUUXZK4+PFD4WICwieGyo9sA
+imGq1jwKFMkhliBBEpac4fw7OnO6xuHgrWfQISufVHkFdm/O9ps1OKruJuMpAi9zmkVjsdGDGF1beV
+Vy6mMXjEYmzRK6swA6hEuiGYBCyyj8IziBsXkMgQSrJJC8YWcM4OPrOMDIGkaRksz0OHJnhW97xxsk
+db/q278yj+HOvbF566OS5F7/v8qWXblvulizMlmi9hVADhJrgJXilKo+csChtkdIjQhX15Zyt/RkOL
+yobUjXeU/hgcU5Q2kDwleazdKN6wCmZ5lNGY0NegHGK0kBpBSqJUXjGI0Npqu/lPAzHjpmWw0mYWMN
+0nCMiT5JVxyk3EcwkPdKsTaO9RNZeZKa7l11L13Po0M3sWt77dJku/ZK24cNbJ05/i86ifzV9/nTDr
+o+QhaMrU7A5XkjKSOAij0tBaon0DmUcQcfEVV5R1eiSDhdZgvJELhA5z3T1PMPTJ7L2dYfexVzn54h
+afM299lrxvRaPbSm1ugqZcKUX4zGDzXdN1y48aC9fJJ0OEYXHljnOF7gAxutKoBscwllwJaLIq3OVB
+BGnjMsJW4WhUBGjVDDUETNLiywfPOhe99++8SuHj97yAXbPfVIZx/7lI7+864YDv9zfuPXb26p433T
+txLspL2DDBugRjhFOGnTi8cEQ3CZeiKq7KSpIbPCh0piGgPMB7yUEh/GO0o4xzuKEx0vHNDfEUYpQC
+usm5CVYLymtYDg1GK/Y2CrIS4h0jBewNSgJARpZwsiMUV4QyhInAkkKMslIRAOIcWGG5d1HufnoHRz
+YfxOLi/uZm939ER01/4WzfHRU096iRvzvombW35yb/anp0y/dXZ5dV8F6lFdIGXBK4aJAiCTIil0jh
+SdKmkTeowk4GbDaU+pQB9EGdDBM+jl27SIM1h+kXH6XSOIPOxlfK77/7MXl/Z/yal39udv+wbczh23
+FENIK8umgM127+NbJ+TMlW+txIxhi4Sl8jjMFhfGUItDMGrjSMO5vIQXV3Cp4ptOS8WTM0AXGArZ8o
+C8FjX3L4egD94l7H3zwl9qvO/BvUfoRpEM1YiBCRglLy9lHpTUfbSZzh0Sx+d+Z6crfzPOVW0t3Cee
+28GWO0A4nN6rsOi2Q0gIFNpSE4BBS4pxBSMl0lNMfjzAYVKYwefWzTUswLlCUgdJLSge5CYwLz7QUD
+IYGJyRBCoa5pcirZoeOIoSOOb82ZHYWOp123cJXJI1FDh26gT37DnDkhps5fPgGDhy87qtJ1v5/Bfr
+XpUpPVYm3ZdXtl4K402bh6HWfnJ+fLYu9e75j89Hn3r/51RdDpr3oNloEkTOcrIN3NLpNhHcMR2NCL
+NFxghSC3E4oMZBUZ2CbF6iyYCZJmVw8y8zKqZIbD75Vm/jTOokHAXb0rl8bnPq1CcbXiu8vMkm46sX
+7s15I97V7fr3dALWosmiXq6u3i/WNWE2GaGdrf41B14JqG0kmZogtSlQsEc4zHo6Y2BLZyOgPpqxbw
+0peUrRbHLrrbr7lrW+/fMvd3/yb6cLCj+WZnlb709rxgK0HHhFCxUSd5ins4k/r9u6fju3lb7blxf/
+KuovvdHbjVhcmmNIRXKi9gdX80IWC0hUE6yjtlOA8uXFMnaAMIIJj6g3TYEE1MUimzpIbzdQqcgOlU
+1VSQaRwhaCwlkkRKG31OqooRWVtFnfB0tIudu/bz8L8IosLuzl4+DqOXH8TS7t2fzVOG7/f6XR/N0r
+TLztjKL0jkqC0IErjClAYAiZU57l4ef4RncRf8Yn2arH9t7eef3khH/TRBXQ7c2hpCEWOd45Ob4ZBE
+XDBUtbjBaVcpTgyHm8sOIsUloQcu7Ea67WV23XWaqdJGJTXAEr/5YrvP7Tx9Nt8zu0ZkKja8W5z64H
+R2bP3hI3LJOUE6as32ocqzVZLjUsCRZlTmAmp0EgpmDpDfzrFhkCZJAwJpHtmueWee7jrLW99/PDtd
+/zrZHb2Q15IjEpqnb1DBoMMtqZXVF4KG4A4RsRzaGa+rMPClzG7fhy7eRNu/Ja83P+msizvN/l0xro
+cR4FngrADSj/ChkphU4YRRmQ4keOFxzCmRGNCRlFaBhPHuFAUJmFqAqXXBBVTmDGGCJU16LZikrhJs
+91hbnaeTqfD/v372bVrD9ddd4R9ew9uzs8tP9Jo9T4dR8nHkRwX+so8VWpFJKqcQE+ODx5NE+XrAbm
+WeB3Bwuw0a2U/oPctvJLPZH9n8sKJ15VnV2g4T+ShsAU2SFSqifEEW2IpEJFHa4mzFudKpK0FByEnQ
+tNfOcns6b33iKXdD0Rp5zeCSq4V32s7Y6+REWGHJ1HZf6bTrt3YfK9ZuRBUf1MkZoqUUDrD1JYEL5B
+SMTUeGwwGgzUlUZRgIs1QwMZ4wpZWqKVFbn/g/vL+h959eu7WY9/thTw59o4ky7gSOqyQ+OoZLEJIA
+oqpZ8cAK4UkYRYRZaDnjhPM8TSLfj4tS0w2udPZ/PXel3dZM76jyIfHymIYb/XX8G6KFwOCGGBtXmk
+kozFejTBmgKEgzkpmdKA1oymdJIgUqRtMCk+StunNLDC/uMzi4i4WFhdZXFwue73eM1naezKJs0ezr
+PklrdUT28YQ52uHUllvFlQgikVt0rVVkIpwkBvQGi0jcIGJspRC4rIGan/yK91UfjLpZP9uqMSB0em
+V2E4CUZIi0Iy9JYlDZd4KHhUJNI6yLBHWIp3Ay4DHosgZXTpLdPZE6By9/b005j6m0H2uQXP/M44S/
+hz1rKzV1J4qLRZVZeeRT47ZjY0lsdkXyXhMUuecG0oKnyO8QlrJ0E8AsKLK5ekXlo1pzrq3jLOEeHk
+Xtz744Pib3vqWj8xdf+Qn0dELQick242eq54aXSMAq+6PoJKwuat6QdZDFDIIWW0RkhBBpHgigicQt
+bvV5YRQ3LAHe0Pw+eGiGO83xWRPwC3h3VxR5jOTyag13VrN+qNhVBovG62ez7KuCSqdKpWNdNrcTNL
+2ulDxxTjJzsdp64zW+qRQ6kWl1Itaa7RIdzbuvg4bCaFizWyT+XwA5331XoiaXk1U0cLVtsui9lK6q
+mliqsnrOF5cfKYR1Lua6H84TpJ3mwurzbKYYF1OYXJ0UeCFwUmLEJ5gHaK0RF4QaQW+pJQGrKeclBQ
+XVwRba0v0lo8pGX/W6/ha8b1WRRiEZ8chtsOr9NjJ9Nbi0tqxeDIls5YYg5DVaEHEAll6hAsYW2K9x
+3tBieLyeMK5rQF0Z5m74fpwz7veLQ7dfdf/0rvxpj9A6pdyG0h0VWy28MSJrIfE9bKLfBV4Vl1lbJJ
+chZp0QJB4VceX7+ji6k+iFAEvgnlReE+aGFJntznv4BxlWSCWVlhfX6c0gdm5RVqzC4AiyASRNCgmO
+UHUPjmtqpHFdhNLSiZTi1KKKBJXDOLbXBl5lY5BVr9QCBCCQso6pTdy9TIZQEbEWte58WAJKDTp7Ow
+L7dtv+d+6s70vb7z0ws9eevnFMNkohUPTnBY4THV6dwZlHdo6tIjRIqKQghJHMFOkMZSXV+Hs2WMsH
+rqVrPPZa9vO/8Jnv6sL0WOri03Usz0BFKY92uz/8PrZ8zSKksj8f+2deYxd1X3HP2e5975t/Gb1jMf
+GO/bYYBswBgMBgp0GXBkqIG2DQqqoahU1SEGqUrXqH5XaP6q2qVSlCKqqTdp/0gZFbYIapS1UJUogU
+kRD2Yyx8Ybt8Xj29S13O6d/nPvevJkxhQQCM9Yc6cqekWd83znnt/9+32+MTGJSz84PwgImTklkndh
+YapGhZgSJ79G1dRO9u/ey5cAtr+07dPffic7OJ/F9Ujw8PV9TzCkJhNlLqayZVC+IR62JkVI4DvcmY
+G72zyxYlSzoUBTY+c9nRJYJVWAD0C1zUp5rhsZKgqogIcTPd0LQ4cQlAWxAUMjPW7amwnLT4xII8u5
+9LWBMTGpcptXzPCwQRTFaa5T0nRIxztLYJKMY81OHxy1sw4ijwHFfpILUZvRnnWve9kr6a+1tKgkL8
+rft6bP76hOT+PUJIhJiU8fGMaQpOTQa6cotys2HRVGITRLmRi8z+tYxejbv+grl7m+igtlV4fsIhW5
+BBrTBrdMAP7IQ1asPzExOBBMjo+TDkDSsY6IakTDURUoUG2RdYKshdS/CCkW1HjOXWDo2bmH7gdsZu
+OuefyvdcMM36Oz6Ll6+OStO6p55sORaNhnugfUXwq1LiZQqQ45OsTbJujL8ZqiSMtNA03Q8Dg0uBwR
+WuQkFgUQK6XA3WzCirAVlNWEkqdddQd3HA6EyRGpJmmRVmAzHxS4a/4jTEGtTlJIZv7uLow11LBLfl
+xm7qyWNXWyttNtuN1GegM4m7RHExuLHGUW3BWkERkIoDcLXBFvWP7mxlBssFwu/OXLi9P2FmWGkgSS
+qYxLXbKCFRBhBkiSInHQOfBohjaEyOUH4zjk6J8YD1V95gKDtm6vC9zHFfIIqxiT4op0kAc8z0s4Mb
+UtffX7D9qkTeLODzMkKM4FApAG52EfUq4zXp5iws4xX11CVkqjcSXnnLq755Kemtn7i0E9yG7Z8oWb
+9GV/7CJM5gxJQCVbFJKSkJAS0z88zyXfbVk1DP4iFL49P5/v7/FkW12Hm2qb0TSd5/MIMXbWTlAIP0
+k5Cr43UM+i0ii8KrglLgSFGk1lo6XgkAtkSM1lwOJ4tDerWzusT1cgutwiwyTewrZu/xHhLUaQ94/j
+yrChgutq+J29a+8O2nTf+0+Dz6taRc+fak0vQqTyCoIZOK/jxKH5SpTZdJwk8ZizUdY6a9fCGh1Gv/
+M8GOjq2xR1dErRJjCEQHtpCGjokNGwK2pJgSRzKJxqBb7XzDBIgvzzu+YqkfHFWwfUnWgG1arU0Nnj
+5sdr0LPVqhSiqY5IQEYdYE1ELq0xVK1TSBOvnifwcaZCjf9sODh05OnT7PYef6OhZ+6hBTPg5fyFCj
+23dKpFhiHzMhyZla0dCE0RJNHBHPwTP44M81s670Y0/lVJJEAQTxWLx0YFbDj5xzcDAUKFvHUmxjbo
+fEHoBsQyIYoGnAmQsCKx0j4QorDJ86RwMX3jM1GslZWOkSR2AgQDlzHdDW2S6US694GLV8n2gFeAhh
+EeMa96tTc598fLp8+3x+BRerYaKaigiZAqVeoQ1PmngMx3GDE1OEXetY+CmG5NbPv3p6rqDt32Btf0
+/RQfjAq/ZKqpFa8CkmxZMLoMGJyll85Jn2ZCs/CGQQr4v4fpFhw3N92tZvu+jlBpTW7Z9bYPnvVDqK
+H979u2ThcqpN3U4WmeN9WkL1hDOzhDVq2jPR4kITynCNGb48hl6x8+167D+RR0EX5VCZDGBahj2pqK
+UGV43GTTW/++prArfksvxbu6nNpBKSSwEnqG3Mjq2Y+r0ed+bmCap10jSCGvqCCMRVlJJYMJqZoMct
+tDHtbffw8HDh/+j97bb/oZi8dkkjLG6gEETpZacEu5MRUvWQmoH374MhG9JHCzEPFvTMjm/xVaw0Qo
+mpSQWwXhu/aZn17d3PDLb3f07Fz19dFoopseGSecU2sbYNCGnPMKw5mYfpWVq5B3Mhbd8Oz2xg2KhV
+0o1bI0AqZro1q4yIskqUFhMJn6mOQe6Knzv8xCvKICRhJxwEVi1LiuDg/dHg4MEk9OYKKQe1wmjKsY
+oIlFiNIwYlYKe3ddx860HuO7wI38ddHb9I6X2/8XTGN8B8hlALaagaiQbLRngj1w2wpeZwWbiyeKGg
+OVH+f+/h3JoIoIb0yx3xCrASMi1dX2/uNUf2uDlzhS7er48/uorXDp2jK5iBzmr3VlUa5i4jhIxszM
+Vzrz+El0HL9zvl9f8EcUSQlhSFFa62qpqfHgrUYKFkxCrlu9D0PjksjpaQmVy+PHqhbO9ufExctU5S
+GNmowiLZC5MmQgrRJ39XHvzAa47/KlTG/fs+T7X7H7cUfBIUqFIgSjLSTZZbiVLEQvs8ooZhGhkZJZ
+Xx4fJYlApZdNFbgihEC5HaqxPJA1+oeOV0rbc46q4hkh6v1yzcvvEmTN4oaEeVYmNwCQGKRL8esLYq
+bcRZ071dmza8Dj5/B841kxL3CJbooXPT0iZEQeAEGa+7LMqfD9v0OOBNQjCHZVLZ/fXzr1JYXoEXZk
+iVhEzRpJIn1Brgu51XHvbXey5/+gbwXW7/xIveLoeC3KlwKYCIqCWuKJzE6buXYJzK+Y7XJZNzLc44
+fIRXK73ihmVUk0BXPwzUkpUAkJlfbBgY51H9m74/e4b9culrt6vXPjJj6+ffPMNpi6eI+fn8UyIjiN
+yQhGNRpw79jrbdu/aT3f3Dqw+CZDYFIxECYHXCvJpnABaTKZLzUIArVXh+xldTwtxGAnSuZ760Ok90
+cUTFGaHiecmmckZ5vw8w3Mp5a713HToaGX3ffedYWDnQ5QK5xFEAUFz6l0CBa3nU78mRUm1VPjE/AT
+Tsst2tuyPWAamWQhHKf2uMXt2hm6YClKh8b1SvdS/+Z/b2jtfzLWX//WY1lsvRNViPCVR4zGqWiOXK
+irTKZffeoupSxf2tG/a2EObfBuVs1JohMqSKylLqK6Xy9ktOMeV4mouiCEM5PzAzgy+87lLb7zUy9Q
+lVDzNXHWKyPcZsz7d19/KgQd/I9195OGvs3Pv5ymWT1nhRQjXFS9tk7C5WZVTGHzZ4ANwnHDuaSXj/
+OgSFo3Pv3gPkiSZF0AhIFMey43BZ/Fo2Pw7O/g/bSGXPa6fW0dJvu2U6lv/+X33/8rXdx05mkbrrmG
+yWGaqUGYoEkwJOHP6NC+//HIvlcrn0J6N0ihrS1hZa0W6nWkMyk/3MjV+pHb5ohUz4yKVMWkhYDQRd
+F9/k73urqN25x33fpn+Dc8QyMFQOrg8kaR4mWFTC7SjWagfRUOFZow6SOyyKDRcBUulWYlEo6xAGde
+iZiSkeBTKPa+qtra/2HHnPSeKa8pPHP/Bf4sTP/qBmJyN0RGcPHuR7teP213nLx5Zt37z3kAHr0WZE
+xBHDt7zSmGDWBW+D8EaarSZntk/cup0KRyfFCKOGDEp+S3buHbnXrYfeuCF7t23Pk3/5qfwJLMYlHB
+IZ0lcw5OLTqS1f2vJKdmMvNK0JMs+Xh0rRFbBWqGjNREpSkiUSDPUJgfJr1KXrTRKE1s1mF/b/9TWg
+0Xht5V/XZTa73zthR9x/q0TyHrIifPnxevHT5a6du/b73cV3tQ40g0dLHI5pSs3yOa3VhMuH8xX9kk
+qg6N3D588212drCBybei+NWy865fYfNd9/86Om/8UEbyQ2pSahVTLZiIl7+Xnhcs2BI+MlTIbArpCV
+lM2I4flcXgrmRK50UKkGi5oY8+zM5GAEAFWJMi2zievueHAq6We/j9Myj1HzsbfQQ5e5NTQCC+/ebx
+74M7xu9eXu//BWOnQBNRSwTPNLKhcViZwRbaXhcns/qnR4UdmHKb3TAAAAyxJREFUhsZJ04Dyjr1sP
+/qZoc1HP/MMu29+GL/0IkqDD1obRwNm4/lTb8Zyi6ydzWjCMuoxmz1iwbMqeB/80mVN5I0bqLJG2gy
+PlTh1uKbCB+ljc20vdm4deHjPoXuf+cSvPTpU3riJmvQ5fXGIS8Njj2D1fl8pTBS30PwaUtyzINGyj
+OKGlWj5vJnK2IOnjx+L49nQ37nrAAOH75xuv/XmP6Nv078YE9RkaEGnSBUCKRqBFj5e1o1ksxMQjYK
+elQuEsLUwK2m1kpmlVB+/8K1kAQxaNtBmjeMOl8LtcRzV8WQuG6FQGIQVWtbW79zz2L19Gx/uL5f+J
+P+fz5YHR8Z56aevxNt37n2wu7fnNd/TsfNaXBiRZiGDwKDRLbB3q8L3867y+MTlXdMTo8WBbbvi/Qf
+vGOLAvt+qrl37w3EIcxLag4x11laIRAWPAI8Ot/ExpH6jWC8yF2devkyLrInFgmeWh7OwRPBWGG+Wi
+F0jppWWRJBNHxikcD21XjFwUpk6AkatJEkC1orBclf73x564IHjhb7+v3/uv55fNz45VRy+fHlXd09
+PmSgZc0hPNhvYAruYN27V8n2gtXV8fOShnq5O9t+492kG9n2LQv65KWAaWAMUDPhEaG0oIFyOMgkhy
+YOaz2HKRVHc4lqQbf3LMisUrWjrl9XhhBCkwnWnNLiFDVCParR5BeeRJE47aungOASE1gueu+OTh76
+0dt3Gzx47dvzRUnHNQ8Cf2yQZE7mg+XtslqVWi5XocjlDu7K0pgS+dfbs2V8tFotPlUqlr+ZyuXNO+
+duFtaSrZF3pfCpiGjN2imToJJ39m6BjG1XZRwrkAI8YUKSZWlEZQDAIrNArHnyvpXtmM/B7wJeAbwO
+fBcxKuQMrzfLdBoz29fX9led5v6u1XnBJW7vnr/YlrXEoNo22LRYOYlxZ1S6rkOfDcLvPAY/hGmWC7
+H68uFI+x0oSPg2MAN/L5/M/vtqSED/T5cMu9J4Wf7HMGsB/4TEv/DFwe3Y/NPN57VXh+5BWApwFLlh
+r661tV1eju/ne8YJrkWtES0tmRe2VOviv2j2aBp5nHihiRaz/A4oCnsAsje/+AAAAAElFTkSuQmCC"
+ }
+
+# $encoded(basn0g08), $encoded(basn2c08), $encoded(basn3p08), $encoded(basn6a08)
+test imgPNG-1.1 {reading basic images; grayscale} -setup {
+ catch {rename foo ""}
+} -body {
+ image create photo foo -data $encoded(basn0g08)
+ list [image width foo] [image height foo]
+} -cleanup {
+ rename foo ""
+} -result {32 32}
+test imgPNG-1.2 {reading basic images; color} -setup {
+ catch {rename foo ""}
+} -body {
+ image create photo foo -data $encoded(basn2c08)
+ list [image width foo] [image height foo]
+} -cleanup {
+ rename foo ""
+} -result {32 32}
+test imgPNG-1.3 {reading basic images; color with palette} -setup {
+ catch {rename foo ""}
+} -body {
+ image create photo foo -data $encoded(basn3p08)
+ list [image width foo] [image height foo]
+} -cleanup {
+ rename foo ""
+} -result {32 32}
+test imgPNG-1.4 {reading basic images; alpha} -setup {
+ catch {rename foo ""}
+} -body {
+ image create photo foo -data $encoded(basn6a08)
+ list [image width foo] [image height foo]
+} -cleanup {
+ rename foo ""
+} -result {32 32}
+
+test imgPNG-2.1 {reading a bad image} -body {
+ image create photo -data $encoded(BadX)
+} -returnCodes error -result {unfinalized data stream in PNG data}
+test imgPNG-2.2 {reading a good image with multiple IDATs} -setup {
+ set i [image create photo]
+} -body {
+ $i put $encoded(MultiIDAT)
+ return [image width $i]x[image height $i]
+} -cleanup {
+ image delete $i
+} -result 223x212
+
+test imgPNG-3.1 {reading image with unknown ancillary chunk - bug [1c659ef0f1]} -setup {
+ set fileName [file join [file dirname [info script]] iDOT.png]
+} -body {
+ # the image contains an unknown chunk iDOT
+ # since the name of this chunk starts with a lowercase letter,
+ # it's an ancillary chunk that shall not trigger an error
+ catch {set i [image create photo -file $fileName]}
+} -cleanup {
+ image delete $i
+} -result {0}
+
+}
+namespace delete png
+imageFinish
+cleanupTests
+return
+
+# Local Variables:
+# mode: tcl
+# fill-column: 78
+# End:
diff --git a/tk8.6/tests/imgPPM.test b/tk8.6/tests/imgPPM.test
new file mode 100644
index 0000000..e3a738a
--- /dev/null
+++ b/tk8.6/tests/imgPPM.test
@@ -0,0 +1,239 @@
+# This file is a Tcl script to test out the code in tkImgFmtPPM.c,
+# which reads and write PPM-format image files for photo widgets.
+# The files is organized in the standard fashion for Tcl tests.
+#
+# Copyright (c) 1994-1997 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+
+imageInit
+
+# Note that we do not use [tcltest::makeFile] because it is
+# only suitable for text files
+proc put {file data} {
+ set f [open $file w]
+ fconfigure $f -translation lf
+ puts -nonewline $f $data
+ close $f
+}
+
+test imgPPM-1.1 {FileReadPPM procedure} -body {
+ put test.ppm "P6\n0 256\n255\nabcdef"
+ image create photo p1 -file test.ppm
+} -returnCodes error -result {PPM image file "test.ppm" has dimension(s) <= 0}
+test imgPPM-1.2 {FileReadPPM procedure} -body {
+ put test.ppm "P6\n-2 256\n255\nabcdef"
+ image create photo p1 -file test.ppm
+} -returnCodes error -result {PPM image file "test.ppm" has dimension(s) <= 0}
+test imgPPM-1.3 {FileReadPPM procedure} -body {
+ put test.ppm "P6\n10 0\n255\nabcdef"
+ image create photo p1 -file test.ppm
+} -returnCodes error -result {PPM image file "test.ppm" has dimension(s) <= 0}
+test imgPPM-1.4 {FileReadPPM procedure} -body {
+ put test.ppm "P6\n10 -2\n255\nabcdef"
+ image create photo p1 -file test.ppm
+} -returnCodes error -result {PPM image file "test.ppm" has dimension(s) <= 0}
+test imgPPM-1.5 {FileReadPPM procedure} -body {
+ put test.ppm "P6\n10 20\n100000\nabcdef"
+ image create photo p1 -file test.ppm
+} -returnCodes error -result {PPM image file "test.ppm" has bad maximum intensity value 100000}
+test imgPPM-1.6 {FileReadPPM procedure} -body {
+ put test.ppm "P6\n10 20\n0\nabcdef"
+ image create photo p1 -file test.ppm
+} -returnCodes error -result {PPM image file "test.ppm" has bad maximum intensity value 0}
+test imgPPM-1.7 {FileReadPPM procedure} -body {
+ put test.ppm "P6\n10 10\n255\nabcdef"
+ image create photo p1 -file test.ppm
+} -returnCodes error -result {error reading PPM image file "test.ppm": not enough data}
+test imgPPM-1.8 {FileReadPPM procedure} -body {
+ put test.ppm "P6\n5 4\n255\n01234567890123456789012345678901234567890123456789012345678"
+ image create photo p1 -file test.ppm
+} -returnCodes error -result {error reading PPM image file "test.ppm": not enough data}
+test imgPPM-1.9 {FileReadPPM procedure} -body {
+ put test.ppm "P6\n5 4\n150\n012345678901234567890123456789012345678901234567890123456789"
+ list [image create photo p1 -file test.ppm] \
+ [image width p1] [image height p1]
+} -returnCodes ok -result {p1 5 4}
+
+
+test imgPPM-2.1 {FileWritePPM procedure} -setup {
+ catch {image delete p1}
+} -body {
+ put test.ppm "P6\n5 4\n255\n012345678901234567890123456789012345678901234567890123456789"
+ image create photo p1 -file test.ppm
+ list [catch {p1 write not_a_dir/bar/baz/gorp} msg] [string tolower $msg] \
+ [string tolower $errorCode]
+} -cleanup {
+ image delete p1
+} -result {1 {couldn't open "not_a_dir/bar/baz/gorp": no such file or directory} {posix enoent {no such file or directory}}}
+
+test imgPPM-2.2 {FileWritePPM procedure} -setup {
+ catch {image delete p1}
+ catch {unset data}
+} -body {
+ put test.ppm "P6\n5 4\n255\n012345678901234567890123456789012345678901234567890123456789"
+ image create photo p1 -file test.ppm
+ p1 write -format ppm test.ppm
+ set fd [open test.ppm]
+ set data [read $fd]
+ close $fd
+ set data
+} -cleanup {
+ image delete p1
+} -result {P6
+5 4
+255
+012345678901234567890123456789012345678901234567890123456789}
+
+
+test imgPPM-3.1 {ReadPPMFileHeader procedure} -body {
+ put test.ppm "# \n#\n#\nP6\n#\n##\n5 4\n255\n012345678901234567890123456789012345678901234567890123456789"
+ image create photo p1 -file test.ppm
+} -cleanup {
+ image delete p1
+} -returnCodes ok -result p1
+test imgPPM-3.2 {ReadPPMFileHeader procedure} -body {
+ put test.ppm "P6\n5\n 4 255\n012345678901234567890123456789012345678901234567890123456789"
+ image create photo p1 -file test.ppm
+} -cleanup {
+ image delete p1
+} -returnCodes ok -result p1
+test imgPPM-3.3 {ReadPPMFileHeader procedure} -body {
+ put test.ppm "P6\n# asdfasdf\n5 4\n255\n012345678901234567890123456789012345678901234567890123456789"
+ image create photo p1 -file test.ppm
+} -cleanup {
+ image delete p1
+} -returnCodes ok -result p1
+test imgPPM-3.4 {ReadPPMFileHeader procedure} -body {
+ put test.ppm "P6 \n5 4\n255\n012345678901234567890123456789012345678901234567890123456789"
+ image create photo p1 -file test.ppm
+} -cleanup {
+ image delete p1
+} -returnCodes ok -result p1
+test imgPPM-3.5 {ReadPPMFileHeader procedure} -body {
+ put test.ppm "P5\n5 4\n255\n01234567890123456789"
+ image create photo p1 -file test.ppm
+} -cleanup {
+ image delete p1
+} -returnCodes ok -result p1
+test imgPPM-3.6 {ReadPPMFileHeader procedure} -body {
+ put test.ppm "P3\n5 4\n255\n012345678901234567890123456789012345678901234567890123456789"
+ image create photo p1 -file test.ppm
+} -returnCodes error -result {couldn't recognize data in image file "test.ppm"}
+test imgPPM-3.7 {ReadPPMFileHeader procedure} -body {
+ put test.ppm "P6x\n5 4\n255\n012345678901234567890123456789012345678901234567890123456789"
+ image create photo p1 -file test.ppm
+} -returnCodes error -result {couldn't recognize data in image file "test.ppm"}
+test imgPPM-3.8 {ReadPPMFileHeader procedure} -body {
+ put test.ppm "P6\nxy5 4\n255\n012345678901234567890123456789012345678901234567890123456789"
+ image create photo p1 -file test.ppm
+} -returnCodes error -result {couldn't recognize data in image file "test.ppm"}
+test imgPPM-3.9 {ReadPPMFileHeader procedure} -body {
+ put test.ppm "P6\n5\n255\n!012345678901234567890123456789012345678901234567890123456789"
+ image create photo p1 -file test.ppm
+} -returnCodes error -result {couldn't recognize data in image file "test.ppm"}
+test imgPPM-3.10 {ReadPPMFileHeader procedure} -body {
+ put test.ppm "P6\n5 4\nzz255\n012345678901234567890123456789012345678901234567890123456789"
+ image create photo p1 -file test.ppm
+} -returnCodes error -result {couldn't recognize data in image file "test.ppm"}
+test imgPPM-3.11 {ReadPPMFileHeader procedure, empty file} -body {
+ put test.ppm " "
+ image create photo p1 -file test.ppm
+} -returnCodes error -result {couldn't recognize data in image file "test.ppm"}
+test imgPPM-3.12 {ReadPPMFileHeader procedure, file ends too soon} -body {
+ put test.ppm "P6\n566"
+ image create photo p1 -file test.ppm
+} -returnCodes error -result {couldn't recognize data in image file "test.ppm"}
+test imgPPM-3.13 {ReadPPMFileHeader procedure, file ends too soon} -body {
+ put test.ppm "P6\n566\n#asdf"
+ image create photo p1 -file test.ppm
+} -returnCodes error -result {couldn't recognize data in image file "test.ppm"}
+
+
+test imgPPM-4.1 {StringReadPPM procedure, data too short [Bug 1822391]} -body {
+ image create photo I -width 1103 -height 997
+ I put "P5\n1103 997\n255\n"
+} -cleanup {
+ image delete I
+} -returnCodes error -result {truncated PPM data}
+
+test imgPPM-5.1 {StringReadPPM procedure} -setup {
+ image create photo ppm
+} -body {
+ ppm put "P6\n0 256\n255\nabcdef"
+} -returnCodes error -cleanup {
+ image delete ppm
+} -result {PPM image data has dimension(s) <= 0}
+test imgPPM-5.2 {StringReadPPM procedure} -setup {
+ image create photo ppm
+} -body {
+ ppm put "P6\n-2 256\n255\nabcdef"
+} -returnCodes error -cleanup {
+ image delete ppm
+} -result {PPM image data has dimension(s) <= 0}
+test imgPPM-5.3 {StringReadPPM procedure} -setup {
+ image create photo ppm
+} -body {
+ ppm put "P6\n10 0\n255\nabcdef"
+} -returnCodes error -cleanup {
+ image delete ppm
+} -result {PPM image data has dimension(s) <= 0}
+test imgPPM-5.4 {StringReadPPM procedure} -setup {
+ image create photo ppm
+} -body {
+ ppm put "P6\n10 -2\n255\nabcdef"
+} -returnCodes error -cleanup {
+ image delete ppm
+} -result {PPM image data has dimension(s) <= 0}
+test imgPPM-5.5 {StringReadPPM procedure} -setup {
+ image create photo ppm
+} -body {
+ ppm put "P6\n10 20\n100000\nabcdef"
+} -returnCodes error -cleanup {
+ image delete ppm
+} -result {PPM image data has bad maximum intensity value 100000}
+test imgPPM-5.6 {StringReadPPM procedure} -setup {
+ image create photo ppm
+} -body {
+ ppm put "P6\n10 20\n0\nabcdef"
+} -returnCodes error -cleanup {
+ image delete ppm
+} -result {PPM image data has bad maximum intensity value 0}
+test imgPPM-5.7 {StringReadPPM procedure} -setup {
+ image create photo ppm
+} -body {
+ ppm put "P6\n10 10\n255\nabcdef"
+} -returnCodes error -cleanup {
+ image delete ppm
+} -result {truncated PPM data}
+test imgPPM-5.8 {StringReadPPM procedure} -setup {
+ image create photo ppm
+} -body {
+ ppm put "P6\n5 4\n255\n01234567890123456789012345678901234567890123456789012345678"
+} -returnCodes error -cleanup {
+ image delete ppm
+} -result {truncated PPM data}
+test imgPPM-5.9 {StringReadPPM procedure} -setup {
+ image create photo ppm
+} -body {
+ ppm put "P6\n5 4\n150\n012345678901234567890123456789012345678901234567890123456789"
+ list [image width ppm] [image height ppm]
+} -cleanup {
+ image delete ppm
+} -result {5 4}
+
+imageFinish
+
+# cleanup
+catch {file delete test.ppm}
+cleanupTests
+return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tk8.6/tests/imgPhoto.test b/tk8.6/tests/imgPhoto.test
new file mode 100644
index 0000000..c45c5fb
--- /dev/null
+++ b/tk8.6/tests/imgPhoto.test
@@ -0,0 +1,1459 @@
+# This file is a Tcl script to test out the "photo" image type and the other
+# procedures in the file tkImgPhoto.c. It is organized in the standard fashion
+# for Tcl tests.
+#
+# Copyright (c) 1994 The Australian National University
+# Copyright (c) 1994-1997 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# Copyright (c) 2002-2008 Donal K. Fellows
+# All rights reserved.
+#
+# Author: Paul Mackerras (paulus@cs.anu.edu.au)
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+tcltest::configure {*}$argv
+tcltest::loadTestedCommands
+
+# Used for 4.65 - 4.73 tests
+# Now for some heftier testing, checking that setting and resetting of pixels'
+# transparency status doesn't "leak" with any one-off errors.
+proc foreachPixel {img xVar yVar script} {
+ upvar 1 $xVar x $yVar y
+ set width [image width $img]
+ set height [image height $img]
+ for {set x 0} {$x<$width} {incr x} {
+ for {set y 0} {$y<$height} {incr y} {
+ uplevel 1 $script
+ }
+ }
+}
+proc checkImgTrans {img} {
+ set result {}
+ foreachPixel $img x y {
+ if {[$img transparency get $x $y]} {
+ lappend result $x,$y
+ }
+ }
+ return $result
+}
+proc checkImgTransLoop {img script1 script2} {
+ set result {}
+ foreachPixel $img x y {
+ eval $script1
+ lappend result {*}[checkImgTrans $img]
+ append result :
+ eval $script2
+ lappend result {*}[checkImgTrans $img]
+ append result .
+ }
+ return $result
+}
+
+imageInit
+set README [makeFile {
+ README -- Tk test suite design document.
+} README-imgPhoto]
+
+# find the teapot.ppm file for use in these tests
+set teapotPhotoFile [file join [file dirname [info script]] teapot.ppm]
+testConstraint hasTeapotPhoto [file exists $teapotPhotoFile]
+
+proc base64ok {} {
+ expr {
+ ![catch {package require base64}]
+ }
+}
+
+testConstraint base64PackageNeeded [base64ok]
+
+test imgPhoto-1.1 {options for photo images} -body {
+ image create photo photo1 -width 79 -height 83
+ list [photo1 cget -width] [photo1 cget -height] \
+ [image width photo1] [image height photo1]
+} -cleanup {
+ image delete photo1
+} -result {79 83 79 83}
+test imgPhoto-1.2 {options for photo images} -body {
+ list [catch {image create photo photo1 -file no.such.file} err] \
+ [string tolower $err]
+} -result {1 {couldn't open "no.such.file": no such file or directory}}
+test imgPhoto-1.3 {options for photo images} -constraints hasTeapotPhoto -body {
+ image create photo photo1 -file $teapotPhotoFile -format no.such.format
+} -returnCodes error -result {image file format "no.such.format" is not supported}
+test imgPhoto-1.4 {options for photo images} -constraints hasTeapotPhoto -body {
+ image create photo photo1 -file $teapotPhotoFile
+ list [image width photo1] [image height photo1]
+} -cleanup {
+ image delete photo1
+} -result {256 256}
+test imgPhoto-1.5 {options for photo images} -constraints hasTeapotPhoto -body {
+ image create photo photo1 -file $teapotPhotoFile \
+ -format ppm -width 79 -height 83
+ list [image width photo1] [image height photo1] [photo1 cget -file] [photo1 cget -format]
+} -cleanup {
+ image delete photo1
+} -result [list 79 83 $teapotPhotoFile ppm]
+test imgPhoto-1.6 {options for photo images} -body {
+ image create photo photo1 -palette 2/2/2 -gamma 2.2
+ list [format %.1f [photo1 cget -gamma]] [photo1 cget -palette]
+} -cleanup {
+ image delete photo1
+} -result {2.2 2/2/2}
+test imgPhoto-1.7 {options for photo images} -returnCodes error -body {
+ image create photo photo1 -file $README
+} -result [subst {couldn't recognize data in image file "$README"}]
+test imgPhoto-1.8 {options for photo images} -body {
+ image create photo -blah blah
+} -returnCodes error -result {unknown option "-blah"}
+test imgPhoto-1.9 {options for photo images - error case} -body {
+ image create photo -format
+} -returnCodes error -result {value for "-format" missing}
+test imgPhoto-1.10 {options for photo images - error case} -body {
+ image create photo -data
+} -returnCodes error -result {value for "-data" missing}
+test imgPhoto-1.11 {options for photo images - error case} -body {
+ image create photo photo1 -format
+} -returnCodes error -result {value for "-format" missing}
+
+test imgPhoto-2.1 {ImgPhotoCreate procedure} -setup {
+ imageCleanup
+} -body {
+ catch {image create photo -blah blah}
+ imageNames
+} -result {}
+test imgPhoto-2.2 {ImgPhotoCreate procedure} -setup {
+ imageCleanup
+} -body {
+ image create photo image1
+ list [info commands image1] [imageNames] \
+ [image width image1] [image height image1]
+} -cleanup {
+ image delete image1
+} -result {image1 image1 0 0}
+# test imgPhoto-2.3 {ImgPhotoCreate procedure: creation failure} {
+# image create photo photo1
+# image create photo photo2 -width 10 -height 10
+# catch {image create photo photo2 -file bogus.img} msg
+# photo1 copy photo2
+# set msg
+# } {couldn't open "bogus.img": no such file or directory}
+
+test imgPhoto-3.1 {ImgPhotoConfigureMaster procedure} -constraints {
+ hasTeapotPhoto
+} -body {
+ image create photo photo1 -file $teapotPhotoFile
+ photo1 configure -file $teapotPhotoFile
+} -cleanup {
+ image delete photo1
+} -result {}
+test imgPhoto-3.2 {ImgPhotoConfigureMaster procedure} -constraints {
+ hasTeapotPhoto
+} -body {
+ image create photo photo1 -file $teapotPhotoFile
+ list [catch {photo1 configure -file bogus} err] [string tolower $err] \
+ [image width photo1] [image height photo1]
+} -cleanup {
+ image delete photo1
+} -result {1 {couldn't open "bogus": no such file or directory} 256 256}
+test imgPhoto-3.3 {ImgPhotoConfigureMaster procedure} -constraints {
+ hasTeapotPhoto
+} -setup {
+ destroy .c
+ pack [canvas .c]
+ update
+} -body {
+ image create photo photo1
+ .c create image 10 10 -image photo1 -tags photo1.1 -anchor nw
+ .c create image 300 10 -image photo1 -tags photo1.2 -anchor nw
+ update
+ photo1 configure -file $teapotPhotoFile
+ update
+ list [image width photo1] [image height photo1] [.c bbox photo1.1] [.c bbox photo1.2]
+} -cleanup {
+ destroy .c
+ image delete photo1
+} -result {256 256 {10 10 266 266} {300 10 556 266}}
+
+test imgPhoto-4.1 {ImgPhotoCmd procedure} -setup {
+ image create photo photo1
+} -body {
+ photo1
+} -returnCodes error -cleanup {
+ image delete photo1
+} -result {wrong # args: should be "photo1 option ?arg ...?"}
+test imgPhoto-4.2 {ImgPhotoCmd procedure} -setup {
+ image create photo photo1
+} -body {
+ photo1 blah
+} -returnCodes error -cleanup {
+ image delete photo1
+} -match glob -result {bad option "blah": must be *}
+test imgPhoto-4.3 {ImgPhotoCmd procedure: blank option} -setup {
+ image create photo photo1
+} -body {
+ photo1 blank
+ photo1 blank x
+} -cleanup {
+ image delete photo1
+} -returnCodes error -result {wrong # args: should be "photo1 blank"}
+test imgPhoto-4.4 {ImgPhotoCmd procedure: cget option} -setup {
+ image create photo photo1
+} -body {
+ photo1 cget
+} -cleanup {
+ image delete photo1
+} -returnCodes error -result {wrong # args: should be "photo1 cget option"}
+test imgPhoto-4.5 {ImgPhotoCmd procedure: cget option} -setup {
+ image create photo photo2 -width 25 -height 30
+} -body {
+ list [photo2 cget -width] [photo2 cget -height]
+} -cleanup {
+ image delete photo2
+} -result {25 30}
+test imgPhoto-4.6 {ImgPhotoCmd procedure: configure option} -setup {
+ image create photo photo1
+} -body {
+ llength [photo1 configure]
+} -cleanup {
+ image delete photo1
+} -result 7
+test imgPhoto-4.7 {ImgPhotoCmd procedure: configure option} -setup {
+ image create photo photo1
+} -body {
+ photo1 conf -palette 3/4/2
+ photo1 configure -palette
+} -cleanup {
+ image delete photo1
+} -result {-palette {} {} {} 3/4/2}
+test imgPhoto-4.8 {ImgPhotoCmd procedure: configure option} -setup {
+ image create photo photo1
+} -body {
+ photo1 configure -blah
+} -cleanup {
+ image delete photo1
+} -returnCodes error -result {unknown option "-blah"}
+test imgPhoto-4.9 {ImgPhotoCmd procedure: configure option} -setup {
+ image create photo photo1
+} -body {
+ photo1 configure -palette {} -gamma
+} -cleanup {
+ image delete photo1
+} -returnCodes error -result {value for "-gamma" missing}
+test imgPhoto-4.10 {ImgPhotoCmd procedure: copy option} -constraints {
+ hasTeapotPhoto
+} -setup {
+ image create photo photo1
+ image create photo photo2 -width 25 -height 30
+} -body {
+ image create photo photo2 -file $teapotPhotoFile
+ photo1 configure -width 0 -height 0 -palette {} -gamma 1
+ photo1 copy photo2
+ list [image width photo1] [image height photo1] [photo1 get 100 100]
+} -cleanup {
+ image delete photo1 photo2
+} -result {256 256 {169 117 90}}
+test imgPhoto-4.11 {ImgPhotoCmd procedure: copy option} -setup {
+ image create photo photo1
+} -body {
+ photo1 copy
+} -returnCodes error -cleanup {
+ image delete photo1
+} -result {wrong # args: should be "photo1 copy source-image ?-compositingrule rule? ?-from x1 y1 x2 y2? ?-to x1 y1 x2 y2? ?-zoom x y? ?-subsample x y?"}
+test imgPhoto-4.12 {ImgPhotoCmd procedure: copy option} -setup {
+ image create photo photo1
+} -body {
+ photo1 copy blah
+} -returnCodes error -cleanup {
+ image delete photo1
+} -result {image "blah" doesn't exist or is not a photo image}
+test imgPhoto-4.13 {ImgPhotoCmd procedure: copy option} -setup {
+ image create photo photo1
+ image create photo photo2
+} -body {
+ photo1 copy photo2 -blah
+} -returnCodes error -cleanup {
+ image delete photo1 photo2
+} -result {unrecognized option "-blah": must be -compositingrule, -from, -shrink, -subsample, -to, or -zoom}
+test imgPhoto-4.14 {ImgPhotoCmd procedure: copy option} -setup {
+ image create photo photo1
+ image create photo photo2
+} -body {
+ photo1 copy photo2 -from -to
+} -returnCodes error -cleanup {
+ image delete photo1 photo2
+} -result {the "-from" option requires one to four integer values}
+test imgPhoto-4.15 {ImgPhotoCmd procedure: copy option} -constraints {
+ hasTeapotPhoto
+} -setup {
+ image create photo photo1
+ image create photo photo2 -file $teapotPhotoFile
+} -body {
+ photo1 copy photo2
+ photo1 copy photo2 -from 0 70 60 120 -shrink
+ list [image width photo1] [image height photo1] [photo1 get 20 10]
+} -cleanup {
+ image delete photo1 photo2
+} -result {60 50 {215 154 120}}
+test imgPhoto-4.16 {ImgPhotoCmd procedure: copy option} -constraints {
+ hasTeapotPhoto
+} -setup {
+ image create photo photo1
+ image create photo photo2 -file $teapotPhotoFile
+} -body {
+ photo1 copy photo2 -from 60 120 0 70 -to 20 50
+ list [image width photo1] [image height photo1] [photo1 get 40 80]
+} -cleanup {
+ image delete photo1 photo2
+} -result {80 100 {19 92 192}}
+test imgPhoto-4.17 {ImgPhotoCmd procedure: copy option} -constraints {
+ hasTeapotPhoto
+} -setup {
+ image create photo photo1
+ image create photo photo2 -file $teapotPhotoFile
+} -body {
+ photo1 copy photo2 -from 0 120 60 70 -to 0 0 100 100
+ list [image width photo1] [image height photo1] [photo1 get 80 60]
+} -cleanup {
+ image delete photo1 photo2
+} -result {100 100 {215 154 120}}
+test imgPhoto-4.18 {ImgPhotoCmd procedure: copy option} -constraints {
+ hasTeapotPhoto
+} -setup {
+ image create photo photo1
+ image create photo photo2 -file $teapotPhotoFile
+} -body {
+ photo1 copy photo2 -from 60 70 0 120 -zoom 2
+ list [image width photo1] [image height photo1] [photo1 get 100 50]
+} -cleanup {
+ image delete photo1 photo2
+} -result {120 100 {169 99 47}}
+test imgPhoto-4.19 {ImgPhotoCmd procedure: copy option} -constraints {
+ hasTeapotPhoto
+} -setup {
+ image create photo photo1
+ image create photo photo2 -file $teapotPhotoFile
+} -body {
+ photo1 copy photo2 -from 0 70 60 120 -zoom 2
+ list [image width photo1] [image height photo1] [photo1 get 100 50]
+} -cleanup {
+ image delete photo1 photo2
+} -result {120 100 {169 99 47}}
+test imgPhoto-4.20 {ImgPhotoCmd procedure: copy option} -constraints {
+ hasTeapotPhoto
+} -setup {
+ image create photo photo1
+ image create photo photo2 -file $teapotPhotoFile
+} -body {
+ photo1 copy photo2 -from 20 20 200 180 -subsample 2 -shrink
+ list [image width photo1] [image height photo1] [photo1 get 50 30]
+} -cleanup {
+ image delete photo1 photo2
+} -result {90 80 {207 146 112}}
+test imgPhoto-4.21 {ImgPhotoCmd procedure: copy option} -constraints {
+ hasTeapotPhoto
+} -setup {
+ image create photo photo1
+ image create photo photo2 -file $teapotPhotoFile
+} -body {
+ photo1 copy photo2
+ set result [list [image width photo1] [image height photo1]]
+ photo1 conf -width 49 -height 51
+ lappend result [image width photo1] [image height photo1]
+ photo1 copy photo2
+ lappend result [image width photo1] [image height photo1]
+ photo1 copy photo2 -from 0 0 10 10 -shrink
+ lappend result [image width photo1] [image height photo1]
+ photo1 conf -width 0
+ photo1 copy photo2 -from 0 0 10 10 -shrink
+ lappend result [image width photo1] [image height photo1]
+ photo1 conf -height 0
+ photo1 copy photo2 -from 0 0 10 10 -shrink
+ lappend result [image width photo1] [image height photo1]
+} -cleanup {
+ image delete photo1 photo2
+} -result {256 256 49 51 49 51 49 51 10 51 10 10}
+test imgPhoto-4.22 {ImgPhotoCmd procedure: get option} -constraints {
+ hasTeapotPhoto
+} -setup {
+ image create photo photo1
+} -body {
+ photo1 read $teapotPhotoFile
+ list [photo1 get 100 100] [photo1 get 150 100] [photo1 get 100 150]
+} -cleanup {
+ image delete photo1
+} -result {{169 117 90} {172 115 84} {35 35 35}}
+test imgPhoto-4.23 {ImgPhotoCmd procedure: get option} -setup {
+ image create photo photo1
+} -body {
+ photo1 get 256 0
+} -cleanup {
+ image delete photo1
+} -returnCodes error -result {photo1 get: coordinates out of range}
+test imgPhoto-4.24 {ImgPhotoCmd procedure: get option} -setup {
+ image create photo photo1
+} -body {
+ photo1 get 0 -1
+} -cleanup {
+ image delete photo1
+} -returnCodes error -result {photo1 get: coordinates out of range}
+test imgPhoto-4.25 {ImgPhotoCmd procedure: get option} -setup {
+ image create photo photo1
+} -body {
+ photo1 get
+} -cleanup {
+ image delete photo1
+} -returnCodes error -result {wrong # args: should be "photo1 get x y"}
+test imgPhoto-4.26 {ImgPhotoCmd procedure: put option} -setup {
+ image create photo photo1
+} -body {
+ photo1 put
+} -returnCodes error -cleanup {
+ image delete photo1
+} -result {wrong # args: should be "photo1 put data ?-option value ...?"}
+test imgPhoto-4.27 {ImgPhotoCmd procedure: put option} -setup {
+ image create photo photo1
+} -body {
+ photo1 put {{white} {white white}}
+} -returnCodes error -cleanup {
+ image delete photo1
+} -result {all elements of color list must have the same number of elements}
+test imgPhoto-4.28 {ImgPhotoCmd procedure: put option} -setup {
+ image create photo photo1
+} -body {
+ photo1 put {{blahgle}}
+} -cleanup {
+ image delete photo1
+} -returnCodes error -result {can't parse color "blahgle"}
+test imgPhoto-4.29 {ImgPhotoCmd procedure: put option} -setup {
+ image create photo photo1
+} -body {
+ photo1 put -to 10 10 20 20 {{white}}
+ photo1 get 19 19
+} -cleanup {
+ image delete photo1
+} -result {255 255 255}
+test imgPhoto-4.30 {ImgPhotoCmd procedure: read option} -setup {
+ image create photo photo1
+} -body {
+ photo1 read
+} -returnCodes error -cleanup {
+ image delete photo1
+} -result {wrong # args: should be "photo1 read fileName ?-option value ...?"}
+test imgPhoto-4.31 {ImgPhotoCmd procedure: read option} -constraints {
+ hasTeapotPhoto
+} -setup {
+ image create photo photo1
+} -body {
+ photo1 read $teapotPhotoFile -zoom 2
+} -returnCodes error -cleanup {
+ image delete photo1
+} -result {unrecognized option "-zoom": must be -format, -from, -shrink, or -to}
+test imgPhoto-4.32 {ImgPhotoCmd procedure: read option} -setup {
+ image create photo photo1
+} -body {
+ list [catch {photo1 read bogus} err] [string tolower $err]
+} -cleanup {
+ image delete photo1
+} -result {1 {couldn't open "bogus": no such file or directory}}
+test imgPhoto-4.33 {ImgPhotoCmd procedure: read option} -constraints {
+ hasTeapotPhoto
+} -setup {
+ image create photo photo1
+} -body {
+ photo1 read $teapotPhotoFile -format bogus
+} -cleanup {
+ image delete photo1
+} -returnCodes error -result {image file format "bogus" is not supported}
+test imgPhoto-4.34 {ImgPhotoCmd procedure: read option} -setup {
+ image create photo photo1
+} -body {
+ photo1 read $README
+} -returnCodes error -cleanup {
+ image delete photo1
+} -result [subst {couldn't recognize data in image file "$README"}]
+test imgPhoto-4.35 {ImgPhotoCmd procedure: read option} -constraints {
+ hasTeapotPhoto
+} -setup {
+ image create photo photo1
+} -body {
+ photo1 read $teapotPhotoFile
+ list [image width photo1] [image height photo1] [photo1 get 120 120]
+} -cleanup {
+ image delete photo1
+} -result {256 256 {161 109 82}}
+test imgPhoto-4.36 {ImgPhotoCmd procedure: read option} -constraints {
+ hasTeapotPhoto
+} -setup {
+ image create photo photo1
+} -body {
+ photo1 read $teapotPhotoFile -from 0 70 60 120 -to 10 10 -shrink
+ list [image width photo1] [image height photo1] [photo1 get 29 19]
+} -cleanup {
+ image delete photo1
+} -result {70 60 {244 180 144}}
+test imgPhoto-4.37 {ImgPhotoCmd procedure: redither option} -setup {
+ image create photo photo1
+} -body {
+ photo1 redither
+ photo1 redither x
+} -cleanup {
+ image delete photo1
+} -returnCodes error -result {wrong # args: should be "photo1 redither"}
+test imgPhoto-4.38 {ImgPhotoCmd procedure: write option} -setup {
+ image create photo photo1
+} -body {
+ photo1 write
+} -returnCodes error -cleanup {
+ image delete photo1
+} -result {wrong # args: should be "photo1 write fileName ?-option value ...?"}
+test imgPhoto-4.39 {ImgPhotoCmd procedure: write option} -setup {
+ image create photo photo1
+} -body {
+ photo1 write teapot.tmp -format bogus
+} -cleanup {
+ image delete photo1
+} -returnCodes error -result {image file format "bogus" is unknown}
+test imgPhoto-4.40 {ImgPhotoCmd procedure: transparency option} -setup {
+ image create photo photo1
+} -body {
+ photo1 transparency
+} -returnCodes error -cleanup {
+ image delete photo1
+} -result {wrong # args: should be "photo1 transparency option ?arg ...?"}
+test imgPhoto-4.41 {ImgPhotoCmd procedure: transparency get option} -setup {
+ image create photo photo1
+} -body {
+ photo1 transparency get
+} -returnCodes error -cleanup {
+ image delete photo1
+} -result {wrong # args: should be "photo1 transparency get x y"}
+test imgPhoto-4.42 {ImgPhotoCmd procedure: transparency get option} -setup {
+ image create photo photo1
+} -body {
+ photo1 transparency get 0
+} -returnCodes error -cleanup {
+ image delete photo1
+} -result {wrong # args: should be "photo1 transparency get x y"}
+test imgPhoto-4.43 {ImgPhotoCmd procedure: transparency get option} -setup {
+ image create photo photo1
+} -body {
+ photo1 transparency get 0 0 0
+} -returnCodes error -cleanup {
+ image delete photo1
+} -result {wrong # args: should be "photo1 transparency get x y"}
+test imgPhoto-4.44 {ImgPhotoCmd procedure: transparency get option} -setup {
+ image create photo photo1
+} -body {
+ photo1 transparency get bogus 0
+} -cleanup {
+ image delete photo1
+} -returnCodes error -result {expected integer but got "bogus"}
+test imgPhoto-4.45 {ImgPhotoCmd procedure: transparency get option} -setup {
+ image create photo photo1
+} -body {
+ photo1 transparency get 0 bogus
+} -cleanup {
+ image delete photo1
+} -returnCodes error -result {expected integer but got "bogus"}
+test imgPhoto-4.46 {ImgPhotoCmd procedure: transparency get option} -setup {
+ image create photo photo1
+} -body {
+ photo1 put white
+ photo1 transparency get 0 0
+} -cleanup {
+ image delete photo1
+} -result 0
+test imgPhoto-4.47 {ImgPhotoCmd procedure: transparency get option} -setup {
+ image create photo photo1
+} -body {
+ photo1 transparency get 1 0
+} -returnCodes error -cleanup {
+ image delete photo1
+} -result {photo1 transparency get: coordinates out of range}
+test imgPhoto-4.48 {ImgPhotoCmd procedure: transparency get option} -setup {
+ image create photo photo1
+} -body {
+ photo1 transparency get -1 0
+} -returnCodes error -cleanup {
+ image delete photo1
+} -result {photo1 transparency get: coordinates out of range}
+test imgPhoto-4.49 {ImgPhotoCmd procedure: transparency get option} -setup {
+ image create photo photo1
+} -body {
+ photo1 transparency get 0 1
+} -returnCodes error -cleanup {
+ image delete photo1
+} -result {photo1 transparency get: coordinates out of range}
+test imgPhoto-4.50 {ImgPhotoCmd procedure: transparency get option} -setup {
+ image create photo photo1
+} -body {
+ photo1 transparency get 0 -1
+} -returnCodes error -cleanup {
+ image delete photo1
+} -result {photo1 transparency get: coordinates out of range}
+test imgPhoto-4.51 {ImgPhotoCmd procedure: transparency get option} -setup {
+ image create photo photo1
+} -body {
+ photo1 put white
+ photo1 blank
+ photo1 transparency get 0 0
+} -cleanup {
+ image delete photo1
+} -result 1
+test imgPhoto-4.52 {ImgPhotoCmd procedure: transparency set option} -setup {
+ image create photo photo1
+} -body {
+ photo1 transparency set
+} -returnCodes error -cleanup {
+ image delete photo1
+} -result {wrong # args: should be "photo1 transparency set x y boolean"}
+test imgPhoto-4.53 {ImgPhotoCmd procedure: transparency set option} -setup {
+ image create photo photo1
+} -body {
+ photo1 transparency set 0
+} -returnCodes error -cleanup {
+ image delete photo1
+} -result {wrong # args: should be "photo1 transparency set x y boolean"}
+test imgPhoto-4.54 {ImgPhotoCmd procedure: transparency set option} -setup {
+ image create photo photo1
+} -body {
+ photo1 transparency set 0 0
+} -returnCodes error -cleanup {
+ image delete photo1
+} -result {wrong # args: should be "photo1 transparency set x y boolean"}
+test imgPhoto-4.55 {ImgPhotoCmd procedure: transparency set option} -setup {
+ image create photo photo1
+} -body {
+ photo1 transparency set 0 0 0 0
+} -returnCodes error -cleanup {
+ image delete photo1
+} -result {wrong # args: should be "photo1 transparency set x y boolean"}
+test imgPhoto-4.56 {ImgPhotoCmd procedure: transparency set option} -setup {
+ image create photo photo1
+} -body {
+ photo1 transparency set bogus 0 0
+} -cleanup {
+ image delete photo1
+} -returnCodes error -result {expected integer but got "bogus"}
+test imgPhoto-4.57 {ImgPhotoCmd procedure: transparency set option} -setup {
+ image create photo photo1
+} -body {
+ photo1 transparency set 0 bogus 0
+} -cleanup {
+ image delete photo1
+} -returnCodes error -result {expected integer but got "bogus"}
+test imgPhoto-4.58 {ImgPhotoCmd procedure: transparency set option} -setup {
+ image create photo photo1
+} -body {
+ photo1 transparency set 0 0 bogus
+} -cleanup {
+ image delete photo1
+} -returnCodes error -result {expected boolean value but got "bogus"}
+test imgPhoto-4.59 {ImgPhotoCmd procedure: transparency set option} -setup {
+ image create photo photo1
+} -body {
+ photo1 transparency set 1 0 0
+} -returnCodes error -cleanup {
+ image delete photo1
+} -result {photo1 transparency set: coordinates out of range}
+test imgPhoto-4.60 {ImgPhotoCmd procedure: transparency set option} -setup {
+ image create photo photo1
+} -body {
+ photo1 transparency set -1 0 0
+} -returnCodes error -cleanup {
+ image delete photo1
+} -result {photo1 transparency set: coordinates out of range}
+test imgPhoto-4.61 {ImgPhotoCmd procedure: transparency set option} -setup {
+ image create photo photo1
+} -body {
+ photo1 transparency set 0 1 0
+} -returnCodes error -cleanup {
+ image delete photo1
+} -result {photo1 transparency set: coordinates out of range}
+test imgPhoto-4.62 {ImgPhotoCmd procedure: transparency set option} -setup {
+ image create photo photo1
+} -body {
+ photo1 transparency set 0 -1 0
+} -returnCodes error -cleanup {
+ image delete photo1
+} -result {photo1 transparency set: coordinates out of range}
+test imgPhoto-4.63 {ImgPhotoCmd procedure: transparency set option} -setup {
+ image create photo photo1
+} -body {
+ photo1 put white
+ photo1 transparency set 0 0 false
+ photo1 transparency get 0 0
+} -cleanup {
+ image delete photo1
+} -result 0
+test imgPhoto-4.64 {ImgPhotoCmd procedure: transparency set option} -setup {
+ image create photo photo1
+} -body {
+ photo1 put white
+ photo1 transparency set 0 0 true
+ photo1 transparency get 0 0
+} -cleanup {
+ image delete photo1
+} -result 1
+# Now for some heftier testing, checking that setting and resetting of pixels'
+# transparency status doesn't "leak" with any one-off errors.
+test imgPhoto-4.65 {ImgPhotoCmd procedure: transparency get option} -setup {
+ image create photo photo1
+} -body {
+ photo1 put white -to 0 0 3 3
+ checkImgTrans photo1
+} -cleanup {
+ image delete photo1
+} -result {}
+test imgPhoto-4.66 {ImgPhotoCmd procedure: transparency get option} -setup {
+ image create photo photo1
+} -body {
+ photo1 put white -to 0 0 3 3
+ photo1 blank
+ checkImgTrans photo1
+} -result {0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2}
+test imgPhoto-4.67 {ImgPhotoCmd procedure: transparency set option} -setup {
+ image create photo photo1
+} -body {
+ photo1 put white -to 0 0 3 3
+ checkImgTransLoop photo1 {
+ photo1 put white -to 0 0 3 3
+ photo1 transparency set $x $y 1
+ } {
+ photo1 transparency set $x $y 0
+ }
+} -cleanup {
+ image delete photo1
+} -result {0,0:. 0,1:. 0,2:. 1,0:. 1,1:. 1,2:. 2,0:. 2,1:. 2,2:.}
+test imgPhoto-4.68 {ImgPhotoCmd procedure: transparency set option} -setup {
+ image create photo photo1
+} -body {
+ photo1 put white -to 0 0 3 3
+ checkImgTransLoop photo1 {
+ photo1 blank
+ photo1 transparency set $x $y 0
+ } {
+ photo1 transparency set $x $y 1
+ }
+} -cleanup {
+ image delete photo1
+} -result {0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2: 0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2. 0,0 0,2 1,0 1,1 1,2 2,0 2,1 2,2: 0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2. 0,0 0,1 1,0 1,1 1,2 2,0 2,1 2,2: 0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2. 0,0 0,1 0,2 1,1 1,2 2,0 2,1 2,2: 0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2. 0,0 0,1 0,2 1,0 1,2 2,0 2,1 2,2: 0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2. 0,0 0,1 0,2 1,0 1,1 2,0 2,1 2,2: 0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2. 0,0 0,1 0,2 1,0 1,1 1,2 2,1 2,2: 0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2. 0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,2: 0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2. 0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1: 0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2.}
+test imgPhoto-4.69 {ImgPhotoCmd procedure: copy with -compositingrule} -setup {
+ # Test the compositing rules for copying images
+ image create photo photo1 -width 3 -height 3
+ image create photo photo2 -width 2 -height 2
+} -body {
+ photo1 copy photo2 -to 1 1 -compositingrule
+} -cleanup {
+ image delete photo1 photo2
+} -returnCodes error -result {the "-compositingrule" option requires a value}
+test imgPhoto-4.70 {ImgPhotoCmd procedure: copy with -compositingrule} -setup {
+ # Test the compositing rules for copying images
+ image create photo photo1 -width 3 -height 3
+ image create photo photo2 -width 2 -height 2
+} -body {
+ photo1 copy photo2 -to 1 1 -compositingrule BAD
+} -returnCodes error -cleanup {
+ image delete photo1 photo2
+} -result {bad compositing rule "BAD": must be overlay or set}
+test imgPhoto-4.71 {ImgPhotoCmd procedure: copy with -compositingrule} -setup {
+ # Test the compositing rules for copying images
+ image create photo photo1 -width 3 -height 3
+ image create photo photo2 -width 2 -height 2
+} -body {
+ # Tests default compositing rule
+ photo1 blank
+ photo2 blank
+ photo1 put white -to 0 0 2 2
+ photo2 put white -to 0 0 2 2
+ photo2 transparency set 0 0 true
+ photo1 copy photo2 -to 1 1
+ checkImgTrans photo1
+} -cleanup {
+ image delete photo1 photo2
+} -result {0,2 2,0}
+test imgPhoto-4.72 {ImgPhotoCmd procedure: copy with -compositingrule} -setup {
+ # Test the compositing rules for copying images
+ image create photo photo1 -width 3 -height 3
+ image create photo photo2 -width 2 -height 2
+} -body {
+ photo1 blank
+ photo2 blank
+ photo1 put white -to 0 0 2 2
+ photo2 put white -to 0 0 2 2
+ photo2 transparency set 0 0 true
+ photo1 copy photo2 -to 1 1 -compositingrule overlay
+ checkImgTrans photo1
+} -cleanup {
+ image delete photo1 photo2
+} -result {0,2 2,0}
+test imgPhoto-4.73 {ImgPhotoCmd procedure: copy with -compositingrule} -setup {
+ # Test the compositing rules for copying images
+ image create photo photo1 -width 3 -height 3
+ image create photo photo2 -width 2 -height 2
+} -body {
+ photo1 blank
+ photo2 blank
+ photo1 put white -to 0 0 2 2
+ photo2 put white -to 0 0 2 2
+ photo2 transparency set 0 0 true
+ photo1 copy photo2 -to 1 1 -compositingrule set
+ checkImgTrans photo1
+} -cleanup {
+ image delete photo1 photo2
+} -result {0,2 1,1 2,0}
+test imgPhoto-4.74 {ImgPhotoCmd procedure: put option error handling} -setup {
+ image create photo photo1
+} -body {
+ photo1 put {{white}} -to 10 10 20 20 {{white}}
+} -cleanup {
+ image delete photo1
+} -returnCodes 1 -result {wrong # args: should be "photo1 put data ?-option value ...?"}
+test imgPhoto-4.75 {<photo> read command: filename starting with '-'} -constraints {
+ hasTeapotPhoto
+} -body {
+ file copy -force $teapotPhotoFile -teapotPhotoFile
+ image create photo photo1
+ photo1 read -teapotPhotoFile
+} -cleanup {
+ image delete photo1
+ file delete ./-teapotPhotoFile
+} -result {}
+test imgPhoto-4.76 {ImgPhotoCmd procedure: copy to same image} -constraints {
+ hasTeapotPhoto
+} -setup {
+ imageCleanup
+ image create photo photo1 -file $teapotPhotoFile
+} -body {
+ # non-regression test for bug [5239fd749b] - shall just not crash
+ photo1 copy photo1 -to 0 0 2000 1000
+ photo1 copy photo1 -subsample 2 2 -shrink
+} -cleanup {
+ imageCleanup
+} -result {}
+
+test imgPhoto-5.1 {ImgPhotoGet/Free procedures, shared instances} -constraints {
+ hasTeapotPhoto
+} -setup {
+ destroy .c
+ pack [canvas .c]
+ imageCleanup
+} -body {
+ image create photo photo1 -file $teapotPhotoFile
+ .c create image 0 0 -image photo1 -tags photo1.1
+ .c create image 256 0 -image photo1 -tags photo1.2
+ .c create image 0 256 -image photo1 -tags photo1.3
+ update
+ .c delete i1.1
+ photo1 configure -width 1
+ update
+ .c delete i1.2
+ photo1 configure -height 1
+ update
+ image delete photo1
+} -cleanup {
+ destroy .c
+} -result {}
+
+test imgPhoto-6.1 {ImgPhotoDisplay procedure, blank display} -setup {
+ destroy .c
+ pack [canvas .c]
+ imageCleanup
+} -body {
+ image create photo photo1 -width 10 -height 10
+ photo1 blank
+ .c create image 10 10 -image photo1
+ update
+} -cleanup {
+ destroy .c
+ image delete photo1
+} -result {}
+
+test imgPhoto-7.1 {ImgPhotoFree procedure, resource freeing} -constraints {
+ hasTeapotPhoto
+} -setup {
+ destroy .c
+ pack [canvas .c]
+ imageCleanup
+} -body {
+ image create photo photo1 -file $teapotPhotoFile
+ .c create image 0 0 -image photo1 -anchor nw
+ update
+ .c delete all
+ image delete photo1
+} -cleanup {
+ destroy .c
+} -result {}
+test imgPhoto-7.2 {ImgPhotoFree procedures, unlinking} -constraints {
+ hasTeapotPhoto
+} -setup {
+ deleteWindows
+ imageCleanup
+} -body {
+ image create photo photo1 -file $teapotPhotoFile
+ pack [canvas .c]
+ .c create image 10 10 -image photo1 -anchor nw
+ button .b1 -image photo1
+ button .b2 -image photo1
+ button .b3 -image photo1
+ pack .b1 .b2 .b3
+ update
+ destroy .b2
+ update
+ destroy .b3
+ update
+ destroy .b1
+ update
+ .c delete all
+} -cleanup {
+ destroy .c
+ image delete photo1
+} -result {}
+test imgPhoto-7.3 {ImgPhotoFree procedures, multiple visuals} -constraints {
+ hasTeapotPhoto
+} -setup {
+ deleteWindows
+ imageCleanup
+} -body {
+ image create photo photo1 -file $teapotPhotoFile
+ button .b1 -image photo1
+ frame .f -visual best
+ button .f.b2 -image photo1
+ pack .f.b2
+ pack .b1 .f
+ update
+ destroy .b1
+ update
+ .f.b2 configure -image {}
+ update
+ destroy .f
+ image delete photo1
+} -result {}
+
+test imgPhoto-8.1 {ImgPhotoDelete procedure} -constraints hasTeapotPhoto -body {
+ image create photo photo2 -file $teapotPhotoFile
+ image delete photo2
+} -result {}
+test imgPhoto-8.2 {ImgPhotoDelete procedure} -constraints {
+ hasTeapotPhoto
+} -setup {
+ set x {}
+} -body {
+ image create photo photo2 -file $teapotPhotoFile
+ rename photo2 newphoto2
+ lappend x [info command photo2] [info command new*] [newphoto2 cget -file]
+ image delete photo2
+ lappend x [info command new*]
+} -result [list {} newphoto2 $teapotPhotoFile {}]
+test imgPhoto-8.3 {ImgPhotoDelete procedure, name cleanup} -body {
+ image create photo photo1
+ image create photo photo2 -width 10 -height 10
+ image delete photo2
+ photo1 copy photo2
+} -returnCodes error -cleanup {
+ imageCleanup
+} -result {image "photo2" doesn't exist or is not a photo image}
+
+test imgPhoto-9.1 {ImgPhotoCmdDeletedProc procedure} -constraints {
+ hasTeapotPhoto
+} -body {
+ image create photo photo2 -file $teapotPhotoFile
+ rename photo2 {}
+ list [lsearch -exact [imageNames] photo2] [catch {photo2 foo} msg] $msg
+} -result {-1 1 {invalid command name "photo2"}}
+
+test imgPhoto-10.1 {Tk_ImgPhotoPutBlock procedure} -setup {
+ imageCleanup
+} -body {
+ image create photo photo1
+ photo1 put "{#ff0000 #ff0000 #ff0000 #ff0000 #ff0000 #ff0000 #ff0000 #ff0000}" -to 0 0
+ photo1 put "{#00ff00 #00ff00}" -to 2 0
+ list [photo1 get 2 0] [photo1 get 3 0] [photo1 get 4 0]
+} -result {{0 255 0} {0 255 0} {255 0 0}}
+test imgPhoto-10.2 {Tk_ImgPhotoPutBlock, same source and dest img} -constraints {
+ hasTeapotPhoto
+} -setup {
+ imageCleanup
+} -body {
+ # Test for bug e4336bef5d
+ image create photo photo1 -file $teapotPhotoFile
+ image create photo photo2 -file $teapotPhotoFile
+ photo2 copy photo1 -to 1 2
+ photo1 copy photo1 -to 1 2
+ string equal [photo1 data] [photo2 data]
+} -cleanup {
+ imageCleanup
+} -result {1}
+test imgPhoto-10.3 {Tk_ImgPhotoPutBlock, same source and dest img} -constraints {
+ hasTeapotPhoto
+} -setup {
+ imageCleanup
+} -body {
+ # Test for bug e4336bef5d
+ image create photo photo1 -file $teapotPhotoFile
+ image create photo photo2 -file $teapotPhotoFile
+ photo2 copy photo1 -from 2 1 -to 4 5 300 300
+ photo1 copy photo1 -from 2 1 -to 4 5 300 300
+ string equal [photo1 data] [photo2 data]
+} -cleanup {
+ imageCleanup
+} -result {1}
+test imgPhoto-10.4 {Tk_ImgPhotoPutBlock, empty image} -setup {
+ imageCleanup
+} -body {
+ image create photo photo1
+ photo1 copy photo1 -to 0 5 10 20
+ list [image width photo1] [image height photo1]
+} -cleanup {
+ imageCleanup
+} -result {0 0}
+
+
+test imgPhoto-11.1 {Tk_FindPhoto} -setup {
+ imageCleanup
+} -body {
+ image create bitmap i1
+ image create photo photo1
+ photo1 copy i1
+} -cleanup {
+ imageCleanup
+} -returnCodes error -result {image "i1" doesn't exist or is not a photo image}
+
+test imgPhoto-12.1 {Tk_PhotoPutZoomedBlock} -constraints hasTeapotPhoto -body {
+ image create photo p3 -file $teapotPhotoFile
+ set result [list [p3 get 50 50] [p3 get 100 100]]
+ p3 copy p3 -zoom 2
+ lappend result [image width p3] [image height p3] [p3 get 100 100]
+} -cleanup {
+ image delete p3
+} -result {{19 92 192} {169 117 90} 512 512 {19 92 192}}
+test imgPhoto-12.2 {Tk_ImgPhotoPutZoomedBlock, same source and dest img} -constraints {
+ hasTeapotPhoto
+} -setup {
+ imageCleanup
+} -body {
+ # Test for bug e4336bef5d
+ image create photo photo1 -file $teapotPhotoFile
+ image create photo photo2 -file $teapotPhotoFile
+ photo2 copy photo1 -to 0 1 200 200 -zoom 2 3
+ photo1 copy photo1 -to 0 1 200 200 -zoom 2 3
+ string equal [photo1 data] [photo2 data]
+} -cleanup {
+ imageCleanup
+} -result {1}
+test imgPhoto-12.3 {Tk_ImgPhotoPutZoomedBlock, same source and dest img} -setup {
+ imageCleanup
+} -body {
+ # Test for bug e4336bef5d
+ image create photo photo1 -file $teapotPhotoFile
+ image create photo photo2 -file $teapotPhotoFile
+ photo2 copy photo1 -from 1 0 -to 4 5 300 300 -zoom 1 2
+ photo1 copy photo1 -from 1 0 -to 4 5 300 300 -zoom 1 2
+ string equal [photo1 data] [photo2 data]
+} -cleanup {
+ imageCleanup
+} -result {1}
+test imgPhoto-12.4 {Tk_ImgPhotoPutZoomedBlock, empty image} -setup {
+ imageCleanup
+} -body {
+ image create photo photo1
+ photo1 copy photo1 -to 0 5 10 20
+ list [image width photo1] [image height photo1]
+} -cleanup {
+ imageCleanup
+} -result {0 0}
+
+test imgPhoto-13.1 {check separation of images in different interpreters} -setup {
+ imageCleanup
+ set data {
+ R0lGODlhQgBkAPUAANbWxs7Wxs7OxsbOxsbGxsbGvb3Gvca9vcDAwL21vbW1vbW1tbWtta2t
+ ta2ltaWltaWlraWctaWcrZycrZyUrZSUrZSMrZSMpYyMrYyMpYyEpYSEpYR7pYR7nHp7pYRz
+ pYRynHtzpXtznHtrnHNrnHNjnGtjnGtjlGtalGNalGNSlGNSjFpSlFpKlFpKjFJKjFJCjFI5
+ jEo5jEo5hEoxhEIxhDkphDkhhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAQgBkAAAG
+ /kCEcEgsGo/IpHLJbDqf0Kh0Sq1ar9isdsvter/gsHhMLpvP6LR6zW673/C4fE6v2+/4vH7P
+ 7/v/gIGCg4SFhoeIiYqLjI2Oj5CRkpOUlZaXmJmOBZxXnAQEnKIIBUQJCguoDKkIBgWhpUev
+ CA4TDwgEUpwKERUaHCIiJCQjIiEUQhwqKiwqLjDQMCwoIha3oUO5ESMuLSwtLSIMsU4Tzi4o
+ JBwWFA8ODQoMCkIMq6sNDQ4UFhwlzC4qSGhgkMvCsAoM6E0oAWMCOSUFGrgQcauAgAACSqGa
+ l6SAK1EaJXBA0SIDBw0KBiCg8EtEBgEWYCxoooAigFwIJGgQYQIF/goTAjk6sXhxAwwFnHRO
+ mEmAwoQAIUo8lCWhRgoOElJVkJBQFCwhCRqkYlUE1QMKHEywoBCrQaeIMCgQeOCi3AkYMmRI
+ S5EuxEkN7OApkGDhF4fDxoSVMAFUBAWkRxI0a+XghVAkBSqMsFCBwj4OI0igSKGCdLN0wYKd
+ zGDBwUYhn6YOKUCioQECGk7INpIArQgUKkr87TyhAYIDQxQgLkYsRIcQIDjcgi2Lw8RYKaAz
+ MXCgAs8UJrZGmOA5AkeQBlqRKsIpvYMQDx4S4NCCxIJSKJpFYMIgnPlSF2ygAQWuCUHAAp6x
+ E4EEE5BXQQUWYLABBySoAIMLHBSBWwso/jxwIAoyzMAWEw3AEEJCt6nUwAQagCDCYcCQwJcK
+ 6QD3DDQxwNDCCSg9NIAGKpwwgQAOtDADDBbsdkQDIPhkwosDPgDPAg1EAME++1jTnhAKdAnb
+ VAR04EIJFAhwwQs0sBDfE7cZwEAE++yU2joOtDcKE7GUcoIKH6RSmwwnQCZFKAo8cE2es7my
+ HnuxKTDgAA6owEEBjoL3wqRUNDBCCnyRYMFMRSDoWYPvyBPPA738lt1KKTxgpjolrDDiFAWU
+ cAMKE+CipAMRZMDTCSSUQMIJPQHLwWOcrDKBCBpokAIJgmYqQgosxIAOCS8iJEQD7HR2QbMh
+ WCCEK7Ck90Cz/oAFu+YVigpTwTsLyJOcBJ6N6plxRihA3E4cOKTkFCU6FMoAA7wiygAZgURA
+ ekYsEJYFGTSATRccQEMjti8eZsEFFuA7z2WkEJAAl7iEQekEhQHGzgQR4INUKLB8pYAFJaQA
+ KhleKdwAByEkFswHIoxQQn4AcYBvGRosisDICCjQAIMJGnZYBsUd4JEZBIhQwgPzKFwAwggL
+ IHbOQzCtxZ1NL0BlKmmhIOwwHGTg2YMUEBdtKzBfbQWlhMHoHIXBnvABBGE9UMKNMKhgQgnG
+ nNQO0wVQoI4FEohFyr9GzDIYaaPxxWy0rCjKQJUMQvxBaMOgNMQChcU4DAkZ6PoV/hIUoP4i
+ Z7g/YHZHIPXeyWyONgsaCi4AOoLjXP8uhAAvPpCQ2Akr38UpXW60Ij8yPkMmwwj8KAI8QWtQ
+ +eXSixEb37WhcHQBERz2rdZ8leCBBcXNY3XevQ8VG/6+F5CACDYgATlmYYD27aRmLngBNADC
+ GGxxQEAWUJDzqpcctc2DARN4kNRgtJxhnKAFV0kIEhYAJ34IQwUhqkENYFCCE5BmGf9wwWmA
+ 5UGgXAAVtfCFMIgRLMbFLQIPYFACcMI7TjQoH2eJQIs2poEMYMAp5XGAvFrBCYS9ImzQG1vT
+ arGTEQhIhE7QjLA+MKDOxClGwuoJtWi0uBIUIxjDSE2wQ4iHl7ywQDjGwZws/NcAlgBjaKQJ
+ JDVuoQBeUeACoFkMcFqgQL1IgxpRSsjsqHA/gy0tHvmAx2z2BxIupaJrnVxCEAAAOw==
+ }
+ interp create x1
+ interp create x2
+ x1 eval {load {} Tk}
+ x2 eval {load {} Tk}
+} -body {
+ x1 eval [list image create photo T1_data -data $data]
+ x2 eval [list image create photo T1_data -data $data]
+} -cleanup {
+ interp delete x1
+ interp delete x2
+} -result T1_data
+
+test imgPhoto-14.1 {GIF writes work correctly} -setup {
+ set data {
+ R0lGODlhYwA5APcAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgAysnGy8hKzM
+ hASs3MTcjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwP8AAAD/
+ AP//AAAA//8A/wD//////ywAAAAAYwA5AAAI/wAZCBxIsKDBgwgTKlzIsKHD
+ hxAjSpxIsaLFixgzatzIsaPHjyBDihxJsqTJkyhTqlzJsqXLlzBjypxJs6bN
+ mzhz6tzJs6fPn0CDCh1KtKhRiwoSKEXAtGlTpUqPGkyagOmCq1edNsWalWkC
+ BUSXIuDqFepBqFWtZv3KU+zYrkrBSqT6dgECtjOTbu16NwFHvV3lshRLti/J
+ qlgRCE6ZuO9ik4Dt+k0ZVyZiyVIvXr77ODPEy5g9T4zMWfTEzXdNz1VbWvXn
+ uqldP1TAOrbshqBb314Y2W7n3Qdpv7UNPCHpycUVbv6dnODy5sqzQldIe8H0
+ hciva9/Ovbv37+BzBgEEADs=
+ }
+ set tmpfilename [makeFile {} imgPhoto-14.1.gif]
+ removeFile $tmpfilename
+} -body {
+ image create photo photo1 -data $data
+ photo1 write $tmpfilename -format gif
+ image create photo photo2 -file $tmpfilename
+ string equal [photo1 data] [photo2 data]
+} -cleanup {
+ catch {image delete photo1 photo2}
+ catch {file delete -force $tmpfilename}
+} -result 1
+test imgPhoto-14.2 {GIF -index handler buffer sizing} -setup {
+ set data {
+ R0lGODlhIAAgAKEAAPkOSQsi7////////yH/C05FVFNDQVBFMi4wAwEAAAAh
+ +QQJMgAAACwGAAYAFAAUAAACEYyPqcvtD6OctNqLs968+68VACH5BAkyAAEA
+ LAMAAwAaABoAAAI0jH+gq+gfmFzQzUsr3gBybn1gIm5kaUaoubbuC8fyTNel
+ Ohv1CSO533u8KrgbUfc5Ci/EAgA7
+ }
+} -body {
+ # Bug 1458234 makes this crash when trying to access buffers of the wrong
+ # size, caused when the initial frame is not the largest frame.
+ set i [image create photo]
+ $i configure -data $data -format {gif -index 2}
+} -cleanup {
+ image delete $i
+} -returnCodes error -result {no image data for this index}
+test imgPhoto-14.3 {GIF -index interleaving and small frames} -body {
+ # Interleaved GIFs used to crash us when a smaller subsequent frame was
+ # accessed.
+ set i [image create photo]
+ $i configure -format {GIF -index 1} -data {
+ R0lGODdhAQAFAPAAAP8AAAAAACwAAAAAAQAFAEACAoRdACwAAAAAAQAEAEACAoRRADs=
+ }
+} -cleanup {
+ image delete $i
+}
+test imgPhoto-14.4 {GIF buffer overflow} -setup {
+ set data {
+ R0lGODlhCgAKAPcAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/
+ AP//AAAA//8A/wD//////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAMwAAZgAAmQAAzAAA/wAzAAAzMwAzZgAzmQAzzAAz/wBmAABmMwBmZgBm
+ mQBmzABm/wCZAACZMwCZZgCZmQCZzACZ/wDMAADMMwDMZgDMmQDMzADM/wD/
+ AAD/MwD/ZgD/mQD/zAD//zMAADMAMzMAZjMAmTMAzDMA/zMzADMzMzMzZjMz
+ mTMzzDMz/zNmADNmMzNmZjNmmTNmzDNm/zOZADOZMzOZZjOZmTOZzDOZ/zPM
+ ADPMMzPMZjPMmTPMzDPM/zP/ADP/MzP/ZjP/mTP/zDP//2YAAGYAM2YAZmYA
+ mWYAzGYA/2YzAGYzM2YzZmYzmWYzzGYz/2ZmAGZmM2ZmZmZmmWZmzGZm/2aZ
+ AGaZM2aZZmaZmWaZzGaZ/2bMAGbMM2bMZmbMmWbMzGbM/2b/AGb/M2b/Zmb/
+ mWb/zGb//5kAAJkAM5kAZpkAmZkAzJkA/5kzAJkzM5kzZpkzmZkzzJkz/5lm
+ AJlmM5lmZplmmZlmzJlm/5mZAJmZM5mZZpmZmZmZzJmZ/5nMAJnMM5nMZpnM
+ mZnMzJnM/5n/AJn/M5n/Zpn/mZn/zJn//8wAAMwAM8wAZswAmcwAzMwA/8wz
+ AMwzM8wzZswzmcwzzMwz/8xmAMxmM8xmZsxmmcxmzMxm/8yZAMyZM8yZZsyZ
+ mcyZzMyZ/8zMAMzMM8zMZszMmczMzMzM/8z/AMz/M8z/Zsz/mcz/zMz///8A
+ AP8AM/8AZv8Amf8AzP8A//8zAP8zM/8zZv8zmf8zzP8z//9mAP9mM/9mZv9m
+ mf9mzP9m//+ZAP+ZM/+ZZv+Zmf+ZzP+Z///MAP/MM//MZv/Mmf/MzP/M////
+ AP//M///Zv//mf//zP///yH5BAEAABAALAAAAAAKAAoAABUSAAD/HEiwoMGD
+ CBMqXMiwYcKAADs=
+ }
+} -body {
+ # This crashes Tk up to 8.4.17 and 8.5.0
+ set i [image create photo]
+ $i configure -data $data
+} -cleanup {
+ image delete $i
+} -returnCodes error -result {malformed image}
+test imgPhoto-14.5 {Bug [fbaed1f66b] - GIF decoder with deferred clear code} -setup {
+ set fileName [file join [file dirname [info script]] deferredClearCode.gif]
+} -body {
+ # This erroneously produced "malformed image" error.
+ # The animated GIF "deferredClearCode.gif" has two frames, and calling for -index 2
+ # simply is an easy way to trigger the problem of improper management of a deferred
+ # clear code. The effect was that the GIF decoder bailed out before the end of the
+ # image reading, and produced the inappropriate "malformed image error".
+ image create photo -file $fileName -format "gif -index 2"
+} -returnCodes error -result {no image data for this index}
+
+test imgPhoto-14.6 {Access Subimage after Subimage with buffer overflow. Ticket 4da2191b} -setup {
+ set data {
+ R0lGODlhYwA5APcAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgAysnGy8hKzM
+ hASs3MTcjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwP8AAAD/
+ AP//AAAA//8A/wD//////ywAAAAAYwA5AAAI/wAZCBxIsKDBgwgTKlzIsKHD
+ hxAjSpxIsaLFixgzatzIsaPHjyBDihxJsqTJkyhTqlzJsqXLlzBjypxJs6bN
+ mzhz6tzJs6fPn0CDCh1KtKhRiwoSKEXAtGlTpUqPGkyagOmCq1edNsWalWkC
+ BUSXIuDqFepBqFWtZv3KU+zYrkrBSqT6dgECtjOTbu16NwFHvV3lshRLti/J
+ qlgRCE6ZuO9ik4Dt+k0ZVyZiyVIvXr77ODPEy5g9T4zMWfTEzXdNz1VbWvXn
+ uqldP1TAOrbshqBb314Y2W7n3Qdpv7UNPCHpycUVbv6dnODy5sqzQldIe8H0
+ hciva9/Ovbv37+BzBgE7ACH5BAFkAAMALAAAAAAEAAQAAAMEKLrckgA7
+ }
+} -body {
+ image create photo photo1 -data $data -format "GIF -index 1"
+} -cleanup {
+ catch {image delete photo1}
+} -result photo1
+
+test imgPhoto-15.1 {photo images can fail to allocate memory gracefully} -constraints {
+ nonPortable
+} -body {
+ # This is not portable to very large machines with more than around 3GB of
+ # free memory available...
+ image create photo -width 32000 -height 32000
+} -returnCodes error -result {not enough free memory for image buffer}
+
+test imgPhoto-16.1 {copying to self doesn't access freed memory} -setup {
+ set i [image create photo]
+} -body {
+ # Bug 877950 makes this crash when trying to copy out of a deallocated
+ # area.
+ $i put red -to 0 0 1000 1000
+ $i copy $i -from 0 0 1000 1000 -to 500 0
+} -cleanup {
+ image delete $i
+} -result {}
+
+# Check that we can guess our supported output formats [Bug 2983824]
+test imgPhoto-17.1 {photo write: format guessing from filename} -setup {
+ set i [image create photo -width 3 -height 3]
+} -body {
+ set f [makeFile {} test.png]
+ $i write $f
+ set fd [open $f]
+ seek $fd 1
+ read $fd 3
+} -cleanup {
+ catch {close $fd}
+ image delete $i
+ catch {removeFile $f}
+} -result PNG
+test imgPhoto-17.2 {photo write: format guessing from filename} -setup {
+ set i [image create photo -width 3 -height 3]
+} -body {
+ set f [makeFile {} test.gif]
+ $i write $f
+ set fd [open $f]
+ read $fd 3
+} -cleanup {
+ catch {close $fd}
+ image delete $i
+ catch {removeFile $f}
+} -result GIF
+test imgPhoto-17.3 {photo write: format guessing from filename} -setup {
+ set i [image create photo -width 3 -height 3]
+} -body {
+ set f [makeFile {} test.ppm]
+ $i write $f
+ set fd [open $f]
+ read $fd 3
+} -cleanup {
+ catch {close $fd}
+ image delete $i
+ catch {removeFile $f}
+} -result "P6\n"
+
+# Reject corrupted or truncated image [Bug b601ce3ab1].
+# WARNING - tests 18.1-18.9 will cause a segfault on 8.5.19 and lower,
+# and on 8.6.6 and lower.
+test imgPhoto-18.1 {Reject corrupted GIF (binary string)} -constraints {
+ base64PackageNeeded
+} -setup {
+ package require base64
+ set data [base64::decode {
+ R0lGODlhAAQABP8zM/8z/zP/MzP/////M////yH5CiwheLrcLTBCd6Tv2qW16tdK4jhV
+ 5qpraXIvM1JlNyAgOw==
+ }]
+} -body {
+ image create photo gif1 -data $data
+} -cleanup {
+ catch {image delete gif1}
+} -returnCodes error -result {error reading color map|not enough free memory for image buffer} -match regexp
+test imgPhoto-18.2 {Reject corrupted GIF (base 64 string)} -setup {
+ set data {
+ R0lGODlhAAQABP8zM/8z/zP/MzP/////M////yH5CiwheLrcLTBCd6Tv2qW16tdK4jhV
+ 5qpraXIvM1JlNyAgOw==
+ }
+} -body {
+ image create photo gif1 -data $data
+} -cleanup {
+ catch {image delete gif1}
+} -returnCodes error -result {error reading color map|not enough free memory for image buffer} -match regexp
+test imgPhoto-18.3 {Reject corrupted GIF (file)} -setup {
+ set fileName [file join [file dirname [info script]] corruptMangled.gif]
+} -body {
+ image create photo gif1 -file $fileName
+} -cleanup {
+ catch {image delete gif1}
+} -returnCodes error -result {error reading color map|not enough free memory for image buffer} -match regexp
+test imgPhoto-18.4 {Reject truncated GIF (binary string)} -constraints {
+ base64PackageNeeded
+} -setup {
+ package require base64
+ set data [base64::decode {
+ R0lGODlhEAAQAMIHAAAAADMz//8zM/8z/zP/MzP///8=
+ }]
+} -body {
+ image create photo gif1 -data $data
+} -cleanup {
+ catch {image delete gif1}
+} -returnCodes error -result {error reading color map}
+test imgPhoto-18.5 {Reject truncated GIF (base 64 string)} -setup {
+ set data {
+ R0lGODlhEAAQAMIHAAAAADMz//8zM/8z/zP/MzP///8=
+ }
+} -body {
+ image create photo gif1 -data $data
+} -cleanup {
+ catch {image delete gif1}
+} -returnCodes error -result {error reading color map}
+test imgPhoto-18.6 {Reject truncated GIF (file)} -setup {
+ set fileName [file join [file dirname [info script]] corruptTruncated.gif]
+} -body {
+ image create photo gif1 -file $fileName
+} -cleanup {
+ catch {image delete gif1}
+} -returnCodes error -result {error reading color map}
+test imgPhoto-18.7 {Reject corrupted GIF (> 4Gb) (binary string)} -constraints {
+ base64PackageNeeded nonPortable
+} -setup {
+ # About the non portability constraint of this test: see ticket [cc42cc18a5]
+ # If there is insufficient memory, the error message
+ # {not enough free memory for image buffer} should be returned.
+ # Instead, some systems (e.g. FreeBSD 11.1) terminate the test interpreter.
+ package require base64
+ set data [base64::decode {
+ R0lGODlhwmYz//8zM/8z/zP/MzP/////M////yH5Ciwhe
+ LrcLTBCd6Tv2qW16tdK4jhV5qpraXIvM1JlNyAgOw==
+ }]
+} -body {
+ image create photo gif1 -data $data
+} -cleanup {
+ catch {image delete gif1}
+} -returnCodes error -result {error reading color map|not enough free memory for image buffer} -match regexp
+test imgPhoto-18.8 {Reject corrupted GIF (> 4Gb) (base 64 string)} -constraints {
+ nonPortable
+} -setup {
+ # About the non portability constraint of this test: see ticket [cc42cc18a5]
+ # If there is insufficient memory, the error message
+ # {not enough free memory for image buffer} should be returned.
+ # Instead, some systems (e.g. FreeBSD 11.1) terminate the test interpreter.
+ set data {
+ R0lGODlhwmYz//8zM/8z/zP/MzP/////M////yH5Ciwhe
+ LrcLTBCd6Tv2qW16tdK4jhV5qpraXIvM1JlNyAgOw==
+ }
+} -body {
+ image create photo gif1 -data $data
+} -cleanup {
+ catch {image delete gif1}
+} -returnCodes error -result {error reading color map|not enough free memory for image buffer} -match regexp
+test imgPhoto-18.9 {Reject corrupted GIF (> 4Gb) (file)} -constraints {
+ nonPortable
+} -setup {
+ # About the non portability constraint of this test: see ticket [cc42cc18a5]
+ # If there is insufficient memory, the error message
+ # {not enough free memory for image buffer} should be returned.
+ # Instead, some systems (e.g. FreeBSD 11.1) terminate the test interpreter.
+ set fileName [file join [file dirname [info script]] corruptMangled4G.gif]
+} -body {
+ image create photo gif1 -file $fileName
+} -cleanup {
+ catch {image delete gif1}
+} -returnCodes error -result {error reading color map|not enough free memory for image buffer} -match regexp
+test imgPhoto-18.10 {Valid GIF (binary string)} -constraints {
+ base64PackageNeeded
+} -setup {
+ # Test the binary string reader with a valid GIF.
+ # This is not tested elsewhere.
+ # Tests 18.11, 18.12, with matching data, are included for completeness.
+ package require base64
+ set data [base64::decode {
+ R0lGODlhEAAQAMIHAAAAADMz//8zM/8z/zP/MzP/////M////yH5BAEKAAcALAAA
+ AAAQABAAAAMheLrcLTBCd6QV79qlterXB0riOFXmmapraXIvM1IdZTcJADs=
+ }]
+} -body {
+ image create photo gif1 -data $data
+} -cleanup {
+ catch {image delete gif1}
+} -result gif1
+test imgPhoto-18.11 {Valid GIF (base 64 string)} -setup {
+ set data {
+ R0lGODlhEAAQAMIHAAAAADMz//8zM/8z/zP/MzP/////M////yH5BAEKAAcALAAA
+ AAAQABAAAAMheLrcLTBCd6QV79qlterXB0riOFXmmapraXIvM1IdZTcJADs=
+ }
+} -body {
+ image create photo gif1 -data $data
+} -cleanup {
+ catch {image delete gif1}
+} -result gif1
+test imgPhoto-18.12 {Valid GIF (file)} -setup {
+ set fileName [file join [file dirname [info script]] red.gif]
+} -body {
+ image create photo gif1 -file $fileName
+} -cleanup {
+ catch {image delete gif1}
+} -result gif1
+
+catch {rename foreachPixel {}}
+catch {rename checkImgTrans {}}
+catch {rename checkImgTransLoop {}}
+imageFinish
+
+# cleanup
+removeFile README-imgPhoto
+cleanupTests
+return
+
+# Local variables:
+# mode: tcl
+# End:
diff --git a/tk8.6/tests/listbox.test b/tk8.6/tests/listbox.test
new file mode 100644
index 0000000..68cb5d8
--- /dev/null
+++ b/tk8.6/tests/listbox.test
@@ -0,0 +1,3218 @@
+# This file is a Tcl script to test out the "listbox" command
+# of Tk. It is organized in the standard fashion for Tcl tests.
+#
+# Copyright (c) 1993-1994 The Regents of the University of California.
+# Copyright (c) 1994-1997 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+namespace import -force tcltest::test
+
+set fixed {Courier -12}
+
+proc record {name args} {
+ global log
+ lappend log [format {%s %.6g %.6g} $name {*}$args]
+}
+
+proc getsize w {
+ regexp {(^[^+-]*)} [wm geometry $w] foo x
+ return $x
+}
+
+proc resetGridInfo {} {
+ # Some window managers, such as mwm, don't reset gridding information
+ # unless the window is withdrawn and re-mapped. If this procedure
+ # isn't invoked, the window manager will stay in gridded mode, which
+ # can cause all sorts of problems. The "wm positionfrom" command is
+ # needed so that the window manager doesn't ask the user to
+ # manually position the window when it is re-mapped.
+
+ wm withdraw .
+ wm positionfrom . user
+ wm deiconify .
+}
+
+# Procedure that creates a second listbox for checking things related
+# to partially visible lines.
+
+proc mkPartial {{w .partial}} {
+ destroy $w
+ toplevel $w
+ wm geometry $w +0+0
+ listbox $w.l -width 30 -height 5
+ pack $w.l -expand 1 -fill both
+ $w.l insert end one two three four five six seven eight nine ten \
+ eleven twelve thirteen fourteen fifteen
+ update
+ scan [wm geometry $w] "%dx%d" width height
+ wm geometry $w ${width}x[expr $height-3]
+ update
+}
+
+# Create entries in the option database to be sure that geometry options
+# like border width have predictable values.
+
+option add *Listbox.borderWidth 2
+option add *Listbox.selectBorderWidth 1
+option add *Listbox.highlightThickness 2
+option add *Listbox.font {Helvetica -12 bold}
+
+# Listbox used in 3.* configuration options tests
+listbox .l
+pack .l
+update
+resetGridInfo
+test listbox-1.1 {configuration options} -body {
+ .l configure -activestyle under
+ list [lindex [.l configure -activestyle] 4] [.l cget -activestyle]
+} -cleanup {
+ .l configure -activestyle [lindex [.l configure -activestyle] 3]
+} -result {underline underline}
+test listbox-1.2 {configuration options} -body {
+ .l configure -activestyle foo
+} -returnCodes error -result {bad activestyle "foo": must be dotbox, none, or underline}
+test listbox-1.3 {configuration options} -body {
+ .l configure -background #ff0000
+ list [lindex [.l configure -background] 4] [.l cget -background]
+} -cleanup {
+ .l configure -background [lindex [.l configure -background] 3]
+} -result {{#ff0000} #ff0000}
+test listbox-1.4 {configuration options} -body {
+ .l configure -background non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+test listbox-1.5 {configuration options} -body {
+ .l configure -bd 4
+ list [lindex [.l configure -bd] 4] [.l cget -bd]
+} -cleanup {
+ .l configure -bd [lindex [.l configure -bd] 3]
+} -result {4 4}
+test listbox-1.6 {configuration options} -body {
+ .l configure -bd badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test listbox-1.7 {configuration options} -body {
+ .l configure -bg #ff0000
+ list [lindex [.l configure -bg] 4] [.l cget -bg]
+} -cleanup {
+ .l configure -bg [lindex [.l configure -bg] 3]
+} -result {{#ff0000} #ff0000}
+test listbox-1.8 {configuration options} -body {
+ .l configure -bg non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+test listbox-1.9 {configuration options} -body {
+ .l configure -borderwidth 1.3
+ list [lindex [.l configure -borderwidth] 4] [.l cget -borderwidth]
+} -cleanup {
+ .l configure -borderwidth [lindex [.l configure -borderwidth] 3]
+} -result {1 1}
+test listbox-1.10 {configuration options} -body {
+ .l configure -borderwidth badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test listbox-1.11 {configuration options} -body {
+ .l configure -cursor arrow
+ list [lindex [.l configure -cursor] 4] [.l cget -cursor]
+} -cleanup {
+ .l configure -cursor [lindex [.l configure -cursor] 3]
+} -result {arrow arrow}
+test listbox-1.12 {configuration options} -body {
+ .l configure -cursor badValue
+} -returnCodes error -result {bad cursor spec "badValue"}
+test listbox-1.13 {configuration options} -body {
+ .l configure -disabledforeground #110022
+ list [lindex [.l configure -disabledforeground] 4] [.l cget -disabledforeground]
+} -cleanup {
+ .l configure -disabledforeground [lindex [.l configure -disabledforeground] 3]
+} -result {{#110022} #110022}
+test listbox-1.14 {configuration options} -body {
+ .l configure -disabledforeground bogus
+} -returnCodes error -result {unknown color name "bogus"}
+test listbox-1.15 {configuration options} -body {
+ .l configure -exportselection yes
+ list [lindex [.l configure -exportselection] 4] [.l cget -exportselection]
+} -cleanup {
+ .l configure -exportselection [lindex [.l configure -exportselection] 3]
+} -result {1 1}
+test listbox-1.16 {configuration options} -body {
+ .l configure -exportselection xyzzy
+} -returnCodes error -result {expected boolean value but got "xyzzy"}
+test listbox-1.17 {configuration options} -body {
+ .l configure -fg #110022
+ list [lindex [.l configure -fg] 4] [.l cget -fg]
+} -cleanup {
+ .l configure -fg [lindex [.l configure -fg] 3]
+} -result {{#110022} #110022}
+test listbox-1.18 {configuration options} -body {
+ .l configure -fg bogus
+} -returnCodes error -result {unknown color name "bogus"}
+test listbox-1.19 {configuration options} -body {
+ .l configure -font {Helvetica 12}
+ list [lindex [.l configure -font] 4] [.l cget -font]
+} -cleanup {
+ .l configure -font [lindex [.l configure -font] 3]
+} -result {{Helvetica 12} {Helvetica 12}}
+test listbox-1.21 {configuration options} -body {
+ .l configure -foreground #110022
+ list [lindex [.l configure -foreground] 4] [.l cget -foreground]
+} -cleanup {
+ .l configure -foreground [lindex [.l configure -foreground] 3]
+} -result {{#110022} #110022}
+test listbox-1.22 {configuration options} -body {
+ .l configure -foreground bogus
+} -returnCodes error -result {unknown color name "bogus"}
+test listbox-1.23 {configuration options} -body {
+ .l configure -height 30
+ list [lindex [.l configure -height] 4] [.l cget -height]
+} -cleanup {
+ .l configure -height [lindex [.l configure -height] 3]
+} -result {30 30}
+test listbox-1.24 {configuration options} -body {
+ .l configure -height 20p
+} -returnCodes error -result {expected integer but got "20p"}
+test listbox-1.25 {configuration options} -body {
+ .l configure -highlightbackground #112233
+ list [lindex [.l configure -highlightbackground] 4] [.l cget -highlightbackground]
+} -cleanup {
+ .l configure -highlightbackground [lindex [.l configure -highlightbackground] 3]
+} -result {{#112233} #112233}
+test listbox-1.26 {configuration options} -body {
+ .l configure -highlightbackground ugly
+} -returnCodes error -result {unknown color name "ugly"}
+test listbox-1.27 {configuration options} -body {
+ .l configure -highlightcolor #123456
+ list [lindex [.l configure -highlightcolor] 4] [.l cget -highlightcolor]
+} -cleanup {
+ .l configure -highlightcolor [lindex [.l configure -highlightcolor] 3]
+} -result {{#123456} #123456}
+test listbox-1.28 {configuration options} -body {
+ .l configure -highlightcolor bogus
+} -returnCodes error -result {unknown color name "bogus"}
+test listbox-1.29 {configuration options} -body {
+ .l configure -highlightthickness 6
+ list [lindex [.l configure -highlightthickness] 4] [.l cget -highlightthickness]
+} -cleanup {
+ .l configure -highlightthickness [lindex [.l configure -highlightthickness] 3]
+} -result {6 6}
+test listbox-1.30 {configuration options} -body {
+ .l configure -highlightthickness bogus
+} -returnCodes error -result {bad screen distance "bogus"}
+test listbox-1.31 {configuration options} -body {
+ .l configure -highlightthickness -2
+ list [lindex [.l configure -highlightthickness] 4] [.l cget -highlightthickness]
+} -cleanup {
+ .l configure -highlightthickness [lindex [.l configure -highlightthickness] 3]
+} -result {0 0}
+test listbox-1.32.1 {configuration options} -setup {
+ set res {}
+} -body {
+ .l configure -justify left
+ set res [list [lindex [.l configure -justify] 4] [.l cget -justify]]
+ .l configure -justify center
+ lappend res [lindex [.l configure -justify] 4] [.l cget -justify]
+ .l configure -justify right
+ lappend res [lindex [.l configure -justify] 4] [.l cget -justify]
+} -cleanup {
+ .l configure -justify [lindex [.l configure -justify] 3]
+} -result {left left center center right right}
+test listbox-1.32.2 {configuration options} -body {
+ .l configure -justify bogus
+} -returnCodes error -result {bad justification "bogus": must be left, right, or center}
+test listbox-1.33 {configuration options} -body {
+ .l configure -relief groove
+ list [lindex [.l configure -relief] 4] [.l cget -relief]
+} -cleanup {
+ .l configure -relief [lindex [.l configure -relief] 3]
+} -result {groove groove}
+test listbox-1.34 {configuration options} -body {
+ .l configure -relief 1.5
+} -returnCodes error -result {bad relief "1.5": must be flat, groove, raised, ridge, solid, or sunken}
+test listbox-1.35 {configuration options} -body {
+ .l configure -selectbackground #110022
+ list [lindex [.l configure -selectbackground] 4] [.l cget -selectbackground]
+} -cleanup {
+ .l configure -selectbackground [lindex [.l configure -selectbackground] 3]
+} -result {{#110022} #110022}
+test listbox-1.36 {configuration options} -body {
+ .l configure -selectbackground bogus
+} -returnCodes error -result {unknown color name "bogus"}
+test listbox-1.37 {configuration options} -body {
+ .l configure -selectborderwidth 1.3
+ list [lindex [.l configure -selectborderwidth] 4] [.l cget -selectborderwidth]
+} -cleanup {
+ .l configure -selectborderwidth [lindex [.l configure -selectborderwidth] 3]
+} -result {1 1}
+test listbox-1.38 {configuration options} -body {
+ .l configure -selectborderwidth badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test listbox-1.39 {configuration options} -body {
+ .l configure -selectforeground #654321
+ list [lindex [.l configure -selectforeground] 4] [.l cget -selectforeground]
+} -cleanup {
+ .l configure -selectforeground [lindex [.l configure -selectforeground] 3]
+} -result {{#654321} #654321}
+test listbox-1.40 {configuration options} -body {
+ .l configure -selectforeground bogus
+} -returnCodes error -result {unknown color name "bogus"}
+test listbox-1.41 {configuration options} -body {
+ .l configure -selectmode string
+ list [lindex [.l configure -selectmode] 4] [.l cget -selectmode]
+} -cleanup {
+ .l configure -selectmode [lindex [.l configure -selectmode] 3]
+} -result {string string}
+test listbox-1.43 {configuration options} -body {
+ .l configure -setgrid false
+ list [lindex [.l configure -setgrid] 4] [.l cget -setgrid]
+} -cleanup {
+ .l configure -setgrid [lindex [.l configure -setgrid] 3]
+} -result {0 0}
+test listbox-1.44 {configuration options} -body {
+ .l configure -setgrid lousy
+} -returnCodes error -result {expected boolean value but got "lousy"}
+test listbox-1.45 {configuration options} -body {
+ .l configure -state disabled
+ list [lindex [.l configure -state] 4] [.l cget -state]
+} -cleanup {
+ .l configure -state [lindex [.l configure -state] 3]
+} -result {disabled disabled}
+test listbox-1.46 {configuration options} -body {
+ .l configure -state foo
+} -returnCodes error -result {bad state "foo": must be disabled or normal}
+test listbox-1.47 {configuration options} -body {
+ .l configure -takefocus {any string}
+ list [lindex [.l configure -takefocus] 4] [.l cget -takefocus]
+} -cleanup {
+ .l configure -takefocus [lindex [.l configure -takefocus] 3]
+} -result {{any string} {any string}}
+test listbox-1.49 {configuration options} -body {
+ .l configure -width 45
+ list [lindex [.l configure -width] 4] [.l cget -width]
+} -cleanup {
+ .l configure -width [lindex [.l configure -width] 3]
+} -result {45 45}
+test listbox-1.50 {configuration options} -body {
+ .l configure -width 3p
+} -returnCodes error -result {expected integer but got "3p"}
+test listbox-1.51 {configuration options} -body {
+ .l configure -xscrollcommand {Some command}
+ list [lindex [.l configure -xscrollcommand] 4] [.l cget -xscrollcommand]
+} -cleanup {
+ .l configure -xscrollcommand [lindex [.l configure -xscrollcommand] 3]
+} -result {{Some command} {Some command}}
+test listbox-1.53 {configuration options} -body {
+ .l configure -yscrollcommand {Another command}
+ list [lindex [.l configure -yscrollcommand] 4] [.l cget -yscrollcommand]
+} -cleanup {
+ .l configure -yscrollcommand [lindex [.l configure -yscrollcommand] 3]
+} -result {{Another command} {Another command}}
+test listbox-1.55 {configuration options} -body {
+ .l configure -listvar testVariable
+ list [lindex [.l configure -listvar] 4] [.l cget -listvar]
+} -cleanup {
+ .l configure -listvar [lindex [.l configure -listvar] 3]
+} -result {testVariable testVariable}
+
+
+test listbox-2.1 {Tk_ListboxCmd procedure} -body {
+ listbox
+} -returnCodes error -result {wrong # args: should be "listbox pathName ?-option value ...?"}
+test listbox-2.2 {Tk_ListboxCmd procedure} -body {
+ listbox gorp
+} -returnCodes error -result {bad window path name "gorp"}
+test listbox-2.3 {Tk_ListboxCmd procedure} -setup {
+ destroy .l
+} -body {
+ listbox .l
+ list [winfo exists .l] [winfo class .l] [info commands .l]
+} -result {1 Listbox .l}
+test listbox-2.4 {Tk_ListboxCmd procedure} -setup {
+ destroy .l
+} -body {
+ listbox .l -gorp foo
+} -cleanup {
+ destroy .l
+} -returnCodes error -result {unknown option "-gorp"}
+test listbox-2.4.1 {Tk_ListboxCmd procedure} -setup {
+ destroy .l
+} -body {
+ catch {listbox .l -gorp foo}
+ list [winfo exists .l] [info commands .l]
+} -cleanup {
+ destroy .l
+} -result {0 {}}
+test listbox-2.5 {Tk_ListboxCmd procedure} -setup {
+ destroy .l
+} -body {
+ listbox .l
+} -cleanup {
+ destroy .l
+} -result {.l}
+
+
+# Listbox used in 3.1 -3.115 tests
+destroy .l
+listbox .l -width 20 -height 5 -bd 4 -highlightthickness 1 -selectborderwidth 2
+pack .l
+.l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11 el12 el13 el14 \
+ el15 el16 el17
+update
+test listbox-3.1 {ListboxWidgetCmd procedure} -body {
+ .l
+} -returnCodes error -result {wrong # args: should be ".l option ?arg ...?"}
+test listbox-3.2 {ListboxWidgetCmd procedure, "activate" option} -body {
+ .l activate
+} -returnCodes error -result {wrong # args: should be ".l activate index"}
+test listbox-3.3 {ListboxWidgetCmd procedure, "activate" option} -body {
+ .l activate a b
+} -returnCodes error -result {wrong # args: should be ".l activate index"}
+test listbox-3.4 {ListboxWidgetCmd procedure, "activate" option} -body {
+ .l activate fooey
+} -returnCodes error -result {bad listbox index "fooey": must be active, anchor, end, @x,y, or a number}
+test listbox-3.5 {ListboxWidgetCmd procedure, "activate" option} -body {
+ .l activate 3
+ .l index active
+} -result 3
+test listbox-3.6 {ListboxWidgetCmd procedure, "activate" option} -body {
+ .l activate -1
+ .l index active
+} -result {0}
+test listbox-3.7 {ListboxWidgetCmd procedure, "activate" option} -body {
+ .l activate 30
+ .l index active
+} -result {17}
+test listbox-3.8 {ListboxWidgetCmd procedure, "activate" option} -body {
+ .l activate end
+ .l index active
+} -result {17}
+test listbox-3.9 {ListboxWidgetCmd procedure, "bbox" option} -body {
+ .l bbox
+} -returnCodes error -result {wrong # args: should be ".l bbox index"}
+test listbox-3.10 {ListboxWidgetCmd procedure, "bbox" option} -body {
+ .l bbox a b
+} -returnCodes error -result {wrong # args: should be ".l bbox index"}
+test listbox-3.11 {ListboxWidgetCmd procedure, "bbox" option} -body {
+ .l bbox fooey
+} -returnCodes error -result {bad listbox index "fooey": must be active, anchor, end, @x,y, or a number}
+test listbox-3.12 {ListboxWidgetCmd procedure, "bbox" option} -body {
+ .l yview 3
+ update
+ list [.l bbox 2] [.l bbox 8]
+} -result {{} {}}
+test listbox-3.13 {ListboxWidgetCmd procedure, "bbox" option} -cleanup {
+ destroy .l2
+} -body {
+ # Used to generate a core dump before a bug was fixed (the last
+ # element would be on-screen if it existed, but it doesn't exist).
+
+ listbox .l2
+ pack .l2 -side top
+ tkwait visibility .l2
+ set x [.l2 bbox 0]
+ destroy .l2
+ set x
+} -cleanup {
+ destroy .l2
+} -result {}
+test listbox-3.14 {ListboxWidgetCmd procedure, "bbox" option} -constraints {
+ fonts
+} -body {
+ .l yview 3
+ update
+ list [.l bbox 3] [.l bbox 4]
+} -result {{7 7 17 14} {7 26 17 14}}
+test listbox-3.15 {ListboxWidgetCmd procedure, "bbox" option} -constraints {
+ fonts
+} -body {
+ .l yview 0
+ update
+ list [.l bbox -1] [.l bbox 0]
+} -result {{} {7 7 17 14}}
+test listbox-3.16 {ListboxWidgetCmd procedure, "bbox" option} -constraints {
+ fonts
+} -body {
+ .l yview end
+ update
+ list [.l bbox 17] [.l bbox end] [.l bbox 18]
+} -result {{7 83 24 14} {7 83 24 14} {}}
+test listbox-3.17 {ListboxWidgetCmd procedure, "bbox" option} -constraints {
+ fonts
+} -setup {
+ destroy .t
+} -body {
+ toplevel .t
+ wm geom .t +0+0
+ listbox .t.l -width 10 -height 5
+ .t.l insert 0 "Short" "Somewhat longer" "Really, quite a whole lot longer than can possibly fit on the screen" "Short"
+ pack .t.l
+ update
+ .t.l xview moveto .2
+ .t.l bbox 2
+} -cleanup {
+ destroy .t
+} -result {-72 39 393 14}
+test listbox-3.18 {ListboxWidgetCmd procedure, "bbox" option, partial last line} -constraints {
+ fonts
+} -body {
+ mkPartial
+ list [.partial.l bbox 3] [.partial.l bbox 4]
+} -result {{5 56 24 14} {5 73 23 14}}
+test listbox-3.18a {ListboxWidgetCmd procedure, "bbox" option, justified} -constraints {
+ fonts
+} -setup {
+ destroy .top.l .top
+ unset -nocomplain res
+} -body {
+ toplevel .top
+ listbox .top.l -justify left
+ .top.l insert end Item1 LongerItem2 MuchLongerItem3
+ pack .top.l
+ update
+ lappend res [.top.l bbox 0] [.top.l bbox 1] [.top.l bbox 2]
+ .top.l configure -justify center
+ lappend res [.top.l bbox 0] [.top.l bbox 1] [.top.l bbox 2]
+ .top.l configure -justify right
+ lappend res [.top.l bbox 0] [.top.l bbox 1] [.top.l bbox 2]
+} -cleanup {
+ destroy .top.l .top
+ unset -nocomplain res
+} -result [list \
+ {5 5 34 14} {5 22 74 14} {5 39 106 14} \
+ {58 5 34 14} {38 22 74 14} {22 39 106 14} \
+ {111 5 34 14} {71 22 74 14} {39 39 106 14} \
+]
+test listbox-3.18b {ListboxWidgetCmd procedure, "bbox" option, justified, non-default borderwidth} -setup {
+ destroy .top.l .top
+ unset -nocomplain lres res
+} -body {
+ # This test checks whether all "x" values from bbox for different size
+ # items with different justification settings are all positive or zero
+ # This checks a bit the calculation of this x value with non-default
+ # borders widths of the listbox
+ toplevel .top
+ listbox .top.l -justify left -borderwidth 17 -highlightthickness 19 -selectborderwidth 22
+ .top.l insert end Item1 LongerItem2 MuchLongerItem3
+ .top.l selection set 1
+ pack .top.l
+ update
+ lappend lres [.top.l bbox 0] [.top.l bbox 1] [.top.l bbox 2]
+ .top.l configure -justify center
+ lappend lres [.top.l bbox 0] [.top.l bbox 1] [.top.l bbox 2]
+ .top.l configure -justify right
+ lappend lres [.top.l bbox 0] [.top.l bbox 1] [.top.l bbox 2]
+ set res 1
+ for {set i 0} {$i < [llength $lres]} {incr i 4} {
+ set res [expr {$res * [expr {[lindex $lres $i] >= 0}] }]
+ }
+ set res
+} -cleanup {
+ destroy .top.l .top
+ unset -nocomplain lres res
+} -result {1}
+test listbox-3.19 {ListboxWidgetCmd procedure, "cget" option} -body {
+ .l cget
+} -returnCodes error -result {wrong # args: should be ".l cget option"}
+test listbox-3.20 {ListboxWidgetCmd procedure, "cget" option} -body {
+ .l cget a b
+} -returnCodes error -result {wrong # args: should be ".l cget option"}
+test listbox-3.21 {ListboxWidgetCmd procedure, "cget" option} -body {
+ .l cget -gorp
+} -returnCodes error -result {unknown option "-gorp"}
+test listbox-3.22 {ListboxWidgetCmd procedure, "cget" option} -body {
+ .l cget -setgrid
+} -result {0}
+test listbox-3.23 {ListboxWidgetCmd procedure, "configure" option} -body {
+ llength [.l configure]
+} -result {28}
+test listbox-3.24 {ListboxWidgetCmd procedure, "configure" option} -body {
+ .l configure -gorp
+} -returnCodes error -result {unknown option "-gorp"}
+test listbox-3.25 {ListboxWidgetCmd procedure, "configure" option} -body {
+ .l configure -setgrid
+} -result {-setgrid setGrid SetGrid 0 0}
+test listbox-3.26 {ListboxWidgetCmd procedure, "configure" option} -body {
+ .l configure -gorp is_messy
+} -returnCodes error -result {unknown option "-gorp"}
+test listbox-3.27 {ListboxWidgetCmd procedure, "configure" option} -body {
+ set oldbd [.l cget -bd]
+ set oldht [.l cget -highlightthickness]
+ .l configure -bd 3 -highlightthickness 0
+ set x "[.l cget -bd] [.l cget -highlightthickness]"
+ .l configure -bd $oldbd -highlightthickness $oldht
+ set x
+} -result {3 0}
+test listbox-3.28 {ListboxWidgetCmd procedure, "curselection" option} -body {
+ .l curselection a
+} -returnCodes error -result {wrong # args: should be ".l curselection"}
+test listbox-3.29 {ListboxWidgetCmd procedure, "curselection" option} -body {
+ .l selection clear 0 end
+ .l selection set 3 6
+ .l selection set 9
+ .l curselection
+} -result {3 4 5 6 9}
+test listbox-3.30 {ListboxWidgetCmd procedure, "delete" option} -body {
+ .l delete
+} -returnCodes error -result {wrong # args: should be ".l delete firstIndex ?lastIndex?"}
+test listbox-3.31 {ListboxWidgetCmd procedure, "delete" option} -body {
+ .l delete a b c
+} -returnCodes error -result {wrong # args: should be ".l delete firstIndex ?lastIndex?"}
+test listbox-3.32 {ListboxWidgetCmd procedure, "delete" option} -body {
+ .l delete badIndex
+} -returnCodes error -result {bad listbox index "badIndex": must be active, anchor, end, @x,y, or a number}
+test listbox-3.33 {ListboxWidgetCmd procedure, "delete" option} -body {
+ .l delete 2 123ab
+} -returnCodes error -result {bad listbox index "123ab": must be active, anchor, end, @x,y, or a number}
+test listbox-3.34 {ListboxWidgetCmd procedure, "delete" option} -setup {
+ destroy .l2
+} -body {
+ listbox .l2
+ .l2 insert 0 el0 el1 el2 el3 el4 el5 el6 el7
+ .l2 delete 3
+ list [.l2 get 2] [.l2 get 3] [.l2 index end]
+} -cleanup {
+ destroy .l2
+} -result {el2 el4 7}
+test listbox-3.35 {ListboxWidgetCmd procedure, "delete" option} -setup {
+ destroy .l2
+} -body {
+ listbox .l2
+ .l2 insert 0 el0 el1 el2 el3 el4 el5 el6 el7
+ .l2 delete 2 4
+ list [.l2 get 1] [.l2 get 2] [.l2 index end]
+} -cleanup {
+ destroy .l2
+} -result {el1 el5 5}
+test listbox-3.36 {ListboxWidgetCmd procedure, "delete" option} -setup {
+ destroy .l2
+} -body {
+ listbox .l2
+ .l2 insert 0 el0 el1 el2 el3 el4 el5 el6 el7
+ .l2 delete -3 2
+ .l2 get 0 end
+} -cleanup {
+ destroy .l2
+} -result {el3 el4 el5 el6 el7}
+test listbox-3.37 {ListboxWidgetCmd procedure, "delete" option} -setup {
+ destroy .l2
+} -body {
+ listbox .l2
+ .l2 insert 0 el0 el1 el2 el3 el4 el5 el6 el7
+ .l2 delete -3 -1
+ .l2 get 0 end
+} -cleanup {
+ destroy .l2
+} -result {el0 el1 el2 el3 el4 el5 el6 el7}
+test listbox-3.38 {ListboxWidgetCmd procedure, "delete" option} -setup {
+ destroy .l2
+} -body {
+ listbox .l2
+ .l2 insert 0 el0 el1 el2 el3 el4 el5 el6 el7
+ .l2 delete 2 end
+ .l2 get 0 end
+} -cleanup {
+ destroy .l2
+} -result {el0 el1}
+test listbox-3.39 {ListboxWidgetCmd procedure, "delete" option} -setup {
+ destroy .l2
+} -body {
+ listbox .l2
+ .l2 insert 0 el0 el1 el2 el3 el4 el5 el6 el7
+ .l2 delete 5 20
+ .l2 get 0 end
+} -cleanup {
+ destroy .l2
+} -result {el0 el1 el2 el3 el4}
+test listbox-3.40 {ListboxWidgetCmd procedure, "delete" option} -setup {
+ destroy .l2
+} -body {
+ listbox .l2
+ .l2 insert 0 el0 el1 el2 el3 el4 el5 el6 el7
+ .l2 delete end 20
+ .l2 get 0 end
+} -cleanup {
+ destroy .l2
+} -result {el0 el1 el2 el3 el4 el5 el6}
+test listbox-3.41 {ListboxWidgetCmd procedure, "delete" option} -setup {
+ destroy .l2
+} -body {
+ listbox .l2
+ .l2 insert 0 el0 el1 el2 el3 el4 el5 el6 el7
+ .l2 delete 8 20
+ .l2 get 0 end
+} -cleanup {
+ destroy .l2
+} -result {el0 el1 el2 el3 el4 el5 el6 el7}
+test listbox-3.42 {ListboxWidgetCmd procedure, "get" option} -body {
+ .l get
+} -returnCodes error -result {wrong # args: should be ".l get firstIndex ?lastIndex?"}
+test listbox-3.43 {ListboxWidgetCmd procedure, "get" option} -body {
+ .l get a b c
+} -returnCodes error -result {wrong # args: should be ".l get firstIndex ?lastIndex?"}
+test listbox-3.44 {ListboxWidgetCmd procedure, "get" option} -body {
+ .l get 2.4
+} -returnCodes error -result {bad listbox index "2.4": must be active, anchor, end, @x,y, or a number}
+test listbox-3.45 {ListboxWidgetCmd procedure, "get" option} -body {
+ .l get end bogus
+} -returnCodes error -result {bad listbox index "bogus": must be active, anchor, end, @x,y, or a number}
+test listbox-3.46 {ListboxWidgetCmd procedure, "get" option} -setup {
+ destroy .l2
+} -body {
+ listbox .l2
+ .l2 insert 0 el0 el1 el2 el3 el4 el5 el6 el7
+ list [.l2 get 0] [.l2 get 3] [.l2 get end]
+} -cleanup {
+ destroy .l2
+} -result {el0 el3 el7}
+test listbox-3.47 {ListboxWidgetCmd procedure, "get" option} -setup {
+ destroy .l2
+} -body {
+ listbox .l2
+ list [.l2 get 0] [.l2 get end]
+} -cleanup {
+ destroy .l2
+} -result {{} {}}
+test listbox-3.48 {ListboxWidgetCmd procedure, "get" option} -setup {
+ destroy .l2
+} -body {
+ listbox .l2
+ .l2 insert 0 el0 el1 el2 "two words" el4 el5 el6 el7
+ .l2 get 3 end
+} -cleanup {
+ destroy .l2
+} -result {{two words} el4 el5 el6 el7}
+test listbox-3.49 {ListboxWidgetCmd procedure, "get" option} -body {
+ .l get -1
+} -result {}
+test listbox-3.50 {ListboxWidgetCmd procedure, "get" option} -body {
+ .l get -2 -1
+} -result {}
+test listbox-3.51 {ListboxWidgetCmd procedure, "get" option} -body {
+ .l get -2 3
+} -result {el0 el1 el2 el3}
+test listbox-3.52 {ListboxWidgetCmd procedure, "get" option} -body {
+ .l get 12 end
+} -result {el12 el13 el14 el15 el16 el17}
+test listbox-3.53 {ListboxWidgetCmd procedure, "get" option} -body {
+ .l get 12 20
+} -result {el12 el13 el14 el15 el16 el17}
+test listbox-3.54 {ListboxWidgetCmd procedure, "get" option} -body {
+ .l get end
+} -result {el17}
+test listbox-3.55 {ListboxWidgetCmd procedure, "get" option} -body {
+ .l get 30
+} -result {}
+test listbox-3.56 {ListboxWidgetCmd procedure, "get" option} -body {
+ .l get 30 35
+} -result {}
+test listbox-3.57 {ListboxWidgetCmd procedure, "index" option} -body {
+ .l index
+} -returnCodes error -result {wrong # args: should be ".l index index"}
+test listbox-3.58 {ListboxWidgetCmd procedure, "index" option} -body {
+ .l index a b
+} -returnCodes error -result {wrong # args: should be ".l index index"}
+test listbox-3.59 {ListboxWidgetCmd procedure, "index" option} -body {
+ .l index @
+} -returnCodes error -result {bad listbox index "@": must be active, anchor, end, @x,y, or a number}
+test listbox-3.60 {ListboxWidgetCmd procedure, "index" option} -body {
+ .l index 2
+} -result 2
+test listbox-3.61 {ListboxWidgetCmd procedure, "index" option} -body {
+ .l index -1
+} -result {-1}
+test listbox-3.62 {ListboxWidgetCmd procedure, "index" option} -body {
+ .l index end
+} -result 18
+test listbox-3.63 {ListboxWidgetCmd procedure, "index" option} -body {
+ .l index 34
+} -result 34
+test listbox-3.64 {ListboxWidgetCmd procedure, "insert" option} -body {
+ .l insert
+} -returnCodes error -result {wrong # args: should be ".l insert index ?element ...?"}
+test listbox-3.65 {ListboxWidgetCmd procedure, "insert" option} -body {
+ .l insert badIndex
+} -returnCodes error -result {bad listbox index "badIndex": must be active, anchor, end, @x,y, or a number}
+test listbox-3.66 {ListboxWidgetCmd procedure, "insert" option} -setup {
+ destroy .l2
+} -body {
+ listbox .l2
+ .l2 insert end a b c d e
+ .l2 insert 3 x y z
+ .l2 get 0 end
+} -cleanup {
+ destroy .l2
+} -result {a b c x y z d e}
+test listbox-3.67 {ListboxWidgetCmd procedure, "insert" option} -setup {
+ destroy .l2
+} -body {
+ listbox .l2
+ .l2 insert end a b c
+ .l2 insert -1 x
+ .l2 get 0 end
+} -cleanup {
+ destroy .l2
+} -result {x a b c}
+test listbox-3.68 {ListboxWidgetCmd procedure, "insert" option} -setup {
+ destroy .l2
+} -body {
+ listbox .l2
+ .l2 insert end a b c
+ .l2 insert end x
+ .l2 get 0 end
+} -cleanup {
+ destroy .l2
+} -result {a b c x}
+test listbox-3.69 {ListboxWidgetCmd procedure, "insert" option} -setup {
+ destroy .l2
+} -body {
+ listbox .l2
+ .l2 insert end a b c
+ .l2 insert 43 x
+ .l2 get 0 end
+} -cleanup {
+ destroy .l2
+} -result {a b c x}
+test listbox-3.70 {ListboxWidgetCmd procedure, "nearest" option} -body {
+ .l nearest
+} -returnCodes error -result {wrong # args: should be ".l nearest y"}
+test listbox-3.71 {ListboxWidgetCmd procedure, "nearest" option} -body {
+ .l nearest a b
+} -returnCodes error -result {wrong # args: should be ".l nearest y"}
+test listbox-3.72 {ListboxWidgetCmd procedure, "nearest" option} -body {
+ .l nearest 20p
+} -returnCodes error -result {expected integer but got "20p"}
+test listbox-3.73 {ListboxWidgetCmd procedure, "nearest" option} -body {
+ .l yview 3
+ .l nearest 1000
+} -result {7}
+test listbox-3.74 {ListboxWidgetCmd procedure, "scan" option} -body {
+ .l scan a b
+} -returnCodes error -result {wrong # args: should be ".l scan mark|dragto x y"}
+test listbox-3.75 {ListboxWidgetCmd procedure, "scan" option} -body {
+ .l scan a b c d
+} -returnCodes error -result {wrong # args: should be ".l scan mark|dragto x y"}
+test listbox-3.76 {ListboxWidgetCmd procedure, "scan" option} -body {
+ .l scan foo bogus 2
+} -returnCodes error -result {expected integer but got "bogus"}
+test listbox-3.77 {ListboxWidgetCmd procedure, "scan" option} -body {
+ .l scan foo 2 2.3
+} -returnCodes error -result {expected integer but got "2.3"}
+test listbox-3.78 {ListboxWidgetCmd procedure, "scan" option} -constraints {
+ fonts
+} -setup {
+ destroy .t
+} -body {
+ toplevel .t
+ wm geom .t +0+0
+ listbox .t.l -width 10 -height 5
+ .t.l insert 0 "Short" "Somewhat longer" "Really, quite a whole lot longer than can possibly fit on the screen" "Short" a b c d e f g h i j
+ pack .t.l
+ update
+ .t.l scan mark 100 140
+ .t.l scan dragto 90 137
+ update
+ list [format {%.6g %.6g} {*}[.t.l xview]] [format {%.6g %.6g} {*}[.t.l yview]]
+} -cleanup {
+ destroy .t
+} -result {{0.249364 0.427481} {0.0714286 0.428571}}
+test listbox-3.79 {ListboxWidgetCmd procedure, "scan" option} -body {
+ .l scan foo 2 4
+} -returnCodes error -result {bad option "foo": must be mark or dragto}
+test listbox-3.80 {ListboxWidgetCmd procedure, "see" option} -body {
+ .l see
+} -returnCodes error -result {wrong # args: should be ".l see index"}
+test listbox-3.81 {ListboxWidgetCmd procedure, "see" option} -body {
+ .l see a b
+} -returnCodes error -result {wrong # args: should be ".l see index"}
+test listbox-3.82 {ListboxWidgetCmd procedure, "see" option} -body {
+ .l see gorp
+} -returnCodes error -result {bad listbox index "gorp": must be active, anchor, end, @x,y, or a number}
+test listbox-3.83 {ListboxWidgetCmd procedure, "see" option} -body {
+ .l yview 7
+ .l see 7
+ .l index @0,0
+} -result {7}
+test listbox-3.84 {ListboxWidgetCmd procedure, "see" option} -body {
+ .l yview 7
+ .l see 11
+ .l index @0,0
+} -result {7}
+test listbox-3.85 {ListboxWidgetCmd procedure, "see" option} -body {
+ .l yview 7
+ .l see 6
+ .l index @0,0
+} -result {6}
+test listbox-3.86 {ListboxWidgetCmd procedure, "see" option} -body {
+ .l yview 7
+ .l see 5
+ .l index @0,0
+} -result {3}
+test listbox-3.87 {ListboxWidgetCmd procedure, "see" option} -body {
+ .l yview 7
+ .l see 12
+ .l index @0,0
+} -result {8}
+test listbox-3.88 {ListboxWidgetCmd procedure, "see" option} -body {
+ .l yview 7
+ .l see 13
+ .l index @0,0
+} -result {11}
+test listbox-3.89 {ListboxWidgetCmd procedure, "see" option} -body {
+ .l yview 7
+ .l see -1
+ .l index @0,0
+} -result {0}
+test listbox-3.90 {ListboxWidgetCmd procedure, "see" option} -body {
+ .l yview 7
+ .l see end
+ .l index @0,0
+} -result {13}
+test listbox-3.91 {ListboxWidgetCmd procedure, "see" option} -body {
+ .l yview 7
+ .l see 322
+ .l index @0,0
+} -result {13}
+test listbox-3.92 {ListboxWidgetCmd procedure, "see" option, partial last line} -body {
+ mkPartial
+ .partial.l see 4
+ .partial.l index @0,0
+} -result {1}
+test listbox-3.93 {ListboxWidgetCmd procedure, "selection" option} -body {
+ .l select a
+} -returnCodes error -result {wrong # args: should be ".l selection option index ?index?"}
+test listbox-3.94 {ListboxWidgetCmd procedure, "selection" option} -body {
+ .l select a b c d
+} -returnCodes error -result {wrong # args: should be ".l selection option index ?index?"}
+test listbox-3.95 {ListboxWidgetCmd procedure, "selection" option} -body {
+ .l selection a bogus
+} -returnCodes error -result {bad listbox index "bogus": must be active, anchor, end, @x,y, or a number}
+test listbox-3.96 {ListboxWidgetCmd procedure, "selection" option} -body {
+ .l selection a 0 lousy
+} -returnCodes error -result {bad listbox index "lousy": must be active, anchor, end, @x,y, or a number}
+test listbox-3.97 {ListboxWidgetCmd procedure, "selection" option} -body {
+ .l selection anchor 0 0
+} -returnCodes error -result {wrong # args: should be ".l selection anchor index"}
+test listbox-3.98 {ListboxWidgetCmd procedure, "selection" option} -body {
+ list [.l selection anchor 5; .l index anchor] \
+ [.l selection anchor 0; .l index anchor]
+} -result {5 0}
+test listbox-3.99 {ListboxWidgetCmd procedure, "selection" option} -body {
+ .l selection anchor -1
+ .l index anchor
+} -result {0}
+test listbox-3.100 {ListboxWidgetCmd procedure, "selection" option} -body {
+ .l selection anchor end
+ .l index anchor
+} -result {17}
+test listbox-3.101 {ListboxWidgetCmd procedure, "selection" option} -body {
+ .l selection anchor 44
+ .l index anchor
+} -result {17}
+test listbox-3.102 {ListboxWidgetCmd procedure, "selection" option} -body {
+ .l selection clear 0 end
+ .l selection set 2 8
+ .l selection clear 3 4
+ .l curselection
+} -result {2 5 6 7 8}
+test listbox-3.103 {ListboxWidgetCmd procedure, "selection" option} -body {
+ .l selection includes 0 0
+} -returnCodes error -result {wrong # args: should be ".l selection includes index"}
+test listbox-3.104 {ListboxWidgetCmd procedure, "selection" option} -body {
+ .l selection clear 0 end
+ .l selection set 2 8
+ .l selection clear 4
+ list [.l selection includes 3] [.l selection includes 4] \
+ [.l selection includes 5]
+} -result {1 0 1}
+test listbox-3.105 {ListboxWidgetCmd procedure, "selection" option} -body {
+ .l selection set 0 end
+ .l selection includes -1
+} -result {0}
+test listbox-3.106 {ListboxWidgetCmd procedure, "selection" option} -body {
+ .l selection clear 0 end
+ .l selection set end
+ .l selection includes end
+} -result {1}
+test listbox-3.107 {ListboxWidgetCmd procedure, "selection" option} -body {
+ .l selection set 0 end
+ .l selection includes 44
+} -result {0}
+test listbox-3.108 {ListboxWidgetCmd procedure, "selection" option} -setup {
+ destroy .l2
+} -body {
+ listbox .l2
+ .l2 selection includes 0
+} -cleanup {
+ destroy .l2
+} -result {0}
+test listbox-3.109 {ListboxWidgetCmd procedure, "selection" option} -body {
+ .l selection clear 0 end
+ .l selection set 2
+ .l selection set 5 7
+ .l curselection
+} -result {2 5 6 7}
+test listbox-3.110 {ListboxWidgetCmd procedure, "selection" option} -body {
+ .l selection clear 0 end
+ .l selection set 2
+ .l selection set 5 7
+ .l selection set 5 7
+ .l curselection
+} -result {2 5 6 7}
+test listbox-3.111 {ListboxWidgetCmd procedure, "selection" option} -body {
+ .l selection badOption 0 0
+} -returnCodes error -result {bad option "badOption": must be anchor, clear, includes, or set}
+test listbox-3.112 {ListboxWidgetCmd procedure, "size" option} -body {
+ .l size a
+} -returnCodes error -result {wrong # args: should be ".l size"}
+test listbox-3.113 {ListboxWidgetCmd procedure, "size" option} -body {
+ .l size
+} -result {18}
+test listbox-3.114 {ListboxWidgetCmd procedure, "xview" option} -setup {
+ destroy .l2
+} -body {
+ listbox .l2
+ update
+ format {%.6g %.6g} {*}[.l2 xview]
+} -cleanup {
+ destroy .l2
+} -result {0 1}
+test listbox-3.115 {ListboxWidgetCmd procedure, "xview" option} -setup {
+ destroy .l2
+} -body {
+ listbox .l2 -width 10 -height 5 -font $fixed
+ .l2 insert 0 a b c d e f g h i j k l m n o p q r s t
+ pack .l2
+ update
+ format {%.6g %.6g} {*}[.l2 xview]
+} -cleanup {
+ destroy .l2
+} -result {0 1}
+
+test listbox-3.116 {ListboxWidgetCmd procedure, "xview" option} -constraints {
+ fonts
+} -setup {
+ destroy .l2
+ listbox .l2 -width 10 -height 5 -font $fixed
+ pack .l2
+ update
+} -body {
+ .l2 insert 0 a b c d e f g h i j k l m n o p q r s t
+ .l2 insert 1 "0123456789a123456789b123456789c123456789d123456789"
+ .l2 xview 4
+ format {%.6g %.6g} {*}[.l2 xview]
+} -cleanup {
+ destroy .l2
+} -result {0.08 0.28}
+test listbox-3.117 {ListboxWidgetCmd procedure, "xview" option} -body {
+ .l xview foo
+} -returnCodes error -result {expected integer but got "foo"}
+test listbox-3.118 {ListboxWidgetCmd procedure, "xview" option} -body {
+ .l xview zoom a b
+} -returnCodes error -result {unknown option "zoom": must be moveto or scroll}
+test listbox-3.119 {ListboxWidgetCmd procedure, "xview" option} -constraints {
+ fonts
+} -setup {
+ destroy .l2
+ listbox .l2 -width 10 -height 5 -font $fixed
+ pack .l2
+ update
+} -body {
+ .l2 insert 0 a b c d e f g h i j k l m n o p q r s t
+ .l2 insert 1 "0123456789a123456789b123456789c123456789d123456789"
+ .l xview 0
+ .l2 xview moveto .4
+ update
+ format {%.6g %.6g} {*}[.l2 xview]
+} -cleanup {
+ destroy .l2
+} -result {0.4 0.6}
+test listbox-3.120 {ListboxWidgetCmd procedure, "xview" option} -constraints {
+ fonts
+} -setup {
+ destroy .l2
+ listbox .l2 -width 10 -height 5 -font $fixed
+ pack .l2
+ update
+} -body {
+ .l2 insert 0 a b c d e f g h i j k l m n o p q r s t
+ .l2 insert 1 "0123456789a123456789b123456789c123456789d123456789"
+ .l2 xview 0
+ .l2 xview scroll 2 units
+ update
+ format {%.6g %.6g} {*}[.l2 xview]
+} -cleanup {
+ destroy .l2
+} -result {0.04 0.24}
+test listbox-3.121 {ListboxWidgetCmd procedure, "xview" option} -constraints {
+ fonts
+} -setup {
+ destroy .l2
+ listbox .l2 -width 10 -height 5 -font $fixed
+ pack .l2
+ update
+} -body {
+ .l2 insert 0 a b c d e f g h i j k l m n o p q r s t
+ .l2 insert 1 "0123456789a123456789b123456789c123456789d123456789"
+ .l2 xview 30
+ .l2 xview scroll -1 pages
+ update
+ format {%.6g %.6g} {*}[.l2 xview]
+} -cleanup {
+ destroy .l2
+} -result {0.44 0.64}
+test listbox-3.122 {ListboxWidgetCmd procedure, "xview" option} -constraints {
+ fonts
+} -setup {
+ destroy .l2
+ listbox .l2 -width 10 -height 5 -font $fixed
+ pack .l2
+ update
+} -body {
+ .l2 insert 0 a b c d e f g h i j k l m n o p q r s t
+ .l2 insert 1 "0123456789a123456789b123456789c123456789d123456789"
+ .l2 configure -width 1
+ update
+ .l2 xview 30
+ .l2 xview scroll -4 pages
+ update
+ format {%.6g %.6g} {*}[.l2 xview]
+} -cleanup {
+ destroy .l2
+} -result {0.52 0.54}
+test listbox-3.123 {ListboxWidgetCmd procedure, "yview" option} -setup {
+ destroy .l2
+} -body {
+ listbox .l2
+ pack .l2
+ update
+ format {%.6g %.6g} {*}[.l2 yview]
+} -cleanup {
+ destroy .l2
+} -result {0 1}
+test listbox-3.124 {ListboxWidgetCmd procedure, "yview" option} -setup {
+ destroy .l2
+} -body {
+ listbox .l2
+ .l2 insert 0 el1
+ pack .l2
+ update
+ format {%.6g %.6g} {*}[.l2 yview]
+} -cleanup {
+ destroy .l2
+} -result {0 1}
+
+test listbox-3.125 {ListboxWidgetCmd procedure, "yview" option} -setup {
+ destroy .l2
+ listbox .l2 -width 10 -height 5 -font $fixed
+ pack .l2
+ update
+} -body {
+ .l2 insert 0 a b c d e f g h i j k l m n o p q r s t
+ .l2 yview 4
+ update
+ format {%.6g %.6g} {*}[.l2 yview]
+} -cleanup {
+ destroy .l2
+} -result {0.2 0.45}
+test listbox-3.126 {ListboxWidgetCmd procedure, "yview" option, partial last line} -setup {
+ destroy .l
+ listbox .l -width 10 -height 5 -font $fixed
+ pack .l
+ update
+} -body {
+ .l insert 0 a b c d e f g h i j k l m n o p q r s t
+ mkPartial
+ format {%.6g %.6g} {*}[.partial.l yview]
+} -cleanup {
+ destroy .l
+} -result {0 0.266667}
+
+# Listbox used in 3.127 -3.137 tests
+destroy .l
+listbox .l -width 20 -height 5 -bd 4 -highlightthickness 1 -selectborderwidth 2
+pack .l
+.l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11 el12 el13 el14 \
+ el15 el16 el17
+update
+test listbox-3.127 {ListboxWidgetCmd procedure, "xview" option} -body {
+ .l yview foo
+} -returnCodes error -result {bad listbox index "foo": must be active, anchor, end, @x,y, or a number}
+test listbox-3.128 {ListboxWidgetCmd procedure, "xview" option} -body {
+ .l yview foo a b
+} -returnCodes error -result {unknown option "foo": must be moveto or scroll}
+test listbox-3.129 {ListboxWidgetCmd procedure, "xview" option} -setup {
+ destroy .l2
+ listbox .l2 -width 10 -height 5 -font $fixed
+ pack .l2
+ update
+} -body {
+ .l2 insert 0 a b c d e f g h i j k l m n o p q r s t
+ .l2 yview 0
+ .l2 yview moveto .31
+ format {%.6g %.6g} {*}[.l2 yview]
+} -cleanup {
+ destroy .l2
+} -result {0.3 0.55}
+test listbox-3.130 {ListboxWidgetCmd procedure, "xview" option} -setup {
+ destroy .l2
+ listbox .l2 -width 10 -height 5 -font $fixed
+ pack .l2
+ update
+} -body {
+ .l2 insert 0 a b c d e f g h i j k l m n o p q r s t
+ .l2 yview 2
+ .l2 yview scroll 2 pages
+ format {%.6g %.6g} {*}[.l2 yview]
+} -cleanup {
+ destroy .l2
+} -result {0.4 0.65}
+test listbox-3.131 {ListboxWidgetCmd procedure, "xview" option} -setup {
+ destroy .l2
+ listbox .l2 -width 10 -height 5 -font $fixed
+ pack .l2
+ update
+} -body {
+ .l2 insert 0 a b c d e f g h i j k l m n o p q r s t
+ .l2 yview 10
+ .l2 yview scroll -3 units
+ format {%.6g %.6g} {*}[.l2 yview]
+} -cleanup {
+ destroy .l2
+} -result {0.35 0.6}
+test listbox-3.132 {ListboxWidgetCmd procedure, "xview" option} -setup {
+ destroy .l2
+ listbox .l2 -width 10 -height 5 -font $fixed
+ pack .l2
+ update
+} -body {
+ .l2 insert 0 a b c d e f g h i j k l m n o p q r s t
+ .l2 configure -height 2
+ update
+ .l2 yview 15
+ .l2 yview scroll -4 pages
+ format {%.6g %.6g} {*}[.l2 yview]
+} -cleanup {
+ destroy .l2
+} -result {0.55 0.65}
+test listbox-3.133 {ListboxWidgetCmd procedure, "xview" option} -body {
+ .l whoknows
+} -returnCodes error -result {bad option "whoknows": must be activate, bbox, cget, configure, curselection, delete, get, index, insert, itemcget, itemconfigure, nearest, scan, see, selection, size, xview, or yview}
+test listbox-3.134 {ListboxWidgetCmd procedure, "xview" option} -body {
+ .l c
+} -returnCodes error -result {ambiguous option "c": must be activate, bbox, cget, configure, curselection, delete, get, index, insert, itemcget, itemconfigure, nearest, scan, see, selection, size, xview, or yview}
+test listbox-3.135 {ListboxWidgetCmd procedure, "xview" option} -body {
+ .l in
+} -returnCodes error -result {ambiguous option "in": must be activate, bbox, cget, configure, curselection, delete, get, index, insert, itemcget, itemconfigure, nearest, scan, see, selection, size, xview, or yview}
+test listbox-3.136 {ListboxWidgetCmd procedure, "xview" option} -body {
+ .l s
+} -returnCodes error -result {ambiguous option "s": must be activate, bbox, cget, configure, curselection, delete, get, index, insert, itemcget, itemconfigure, nearest, scan, see, selection, size, xview, or yview}
+test listbox-3.137 {ListboxWidgetCmd procedure, "xview" option} -body {
+ .l se
+} -returnCodes error -result {ambiguous option "se": must be activate, bbox, cget, configure, curselection, delete, get, index, insert, itemcget, itemconfigure, nearest, scan, see, selection, size, xview, or yview}
+
+# No tests for DestroyListbox: I can't come up with anything to test
+# in this procedure.
+
+
+test listbox-4.1 {ConfigureListbox procedure} -constraints {
+ fonts
+} -setup {
+ deleteWindows
+ destroy .l
+ listbox .l -setgrid 1 -width 25 -height 15
+ pack .l
+ update
+} -body {
+ update
+ set x [getsize .]
+ .l configure -setgrid 0
+ update
+ list $x [getsize .]
+} -cleanup {
+ deleteWindows
+} -result {25x15 185x263}
+resetGridInfo
+test listbox-4.2 {ConfigureListbox procedure} -setup {
+ deleteWindows
+ destroy .l
+ listbox .l -setgrid 1 -width 25 -height 15
+ pack .l
+ update
+} -body {
+ .l configure -highlightthickness -3
+ .l cget -highlightthickness
+} -cleanup {
+ deleteWindows
+} -result {0}
+test listbox-4.3 {ConfigureListbox procedure} -setup {
+ deleteWindows
+ destroy .l
+ listbox .l -setgrid 1 -width 25 -height 15
+ pack .l
+ update
+} -body {
+ .l configure -exportselection 0
+ .l delete 0 end
+ .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8
+ .l selection set 3 5
+ .l configure -exportselection 1
+ selection get
+} -cleanup {
+ deleteWindows
+} -result {el3
+el4
+el5}
+test listbox-4.4 {ConfigureListbox procedure} -setup {
+ deleteWindows
+ listbox .l -setgrid 1 -width 25 -height 15
+ pack .l
+ update
+} -body {
+ entry .e
+ .e insert 0 abc
+ .e select from 0
+ .e select to 2
+ .l configure -exportselection 0
+ .l delete 0 end
+ .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8
+ .l selection set 3 5
+ .l selection clear 3 5
+ .l configure -exportselection 1
+ list [selection own] [selection get]
+} -cleanup {
+ deleteWindows
+} -result {.e ab}
+test listbox-4.5 {-exportselection option} -setup {
+ deleteWindows
+ listbox .l -setgrid 1 -width 25 -height 15
+ pack .l
+ update
+} -body {
+ selection clear .
+ .l configure -exportselection 1
+ .l delete 0 end
+ .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8
+ .l selection set 1 1
+ set x {}
+ lappend x [catch {selection get} msg] $msg [.l curselection]
+ .l config -exportselection 0
+ lappend x [catch {selection get} msg] $msg [.l curselection]
+ .l selection clear 0 end
+ lappend x [catch {selection get} msg] $msg [.l curselection]
+ .l selection set 1 3
+ lappend x [catch {selection get} msg] $msg [.l curselection]
+ .l config -exportselection 1
+ lappend x [catch {selection get} msg] $msg [.l curselection]
+} -cleanup {
+ deleteWindows
+} -result {0 el1 1 1 {PRIMARY selection doesn't exist or form "STRING" not defined} 1 1 {PRIMARY selection doesn't exist or form "STRING" not defined} {} 1 {PRIMARY selection doesn't exist or form "STRING" not defined} {1 2 3} 0 {el1
+el2
+el3} {1 2 3}}
+test listbox-4.6 {ConfigureListbox procedure} -constraints {
+ fonts
+} -setup {
+ deleteWindows
+} -body {
+
+ # The following code (reset geometry, withdraw, etc.) is necessary
+ # to reset the state of some window managers like olvwm under
+ # SunOS 4.1.3.
+
+ wm geom . 300x300
+ update
+ wm geom . {}
+ wm withdraw .
+ listbox .l2 -font $fixed -width 15 -height 20
+ pack .l2
+ update
+ wm deiconify .
+ set x [getsize .]
+ .l2 configure -setgrid 1
+ update
+ list $x [getsize .]
+} -cleanup {
+ deleteWindows
+} -result {115x328 15x20}
+test listbox-4.7 {ConfigureListbox procedure} -setup {
+ deleteWindows
+} -body {
+ wm withdraw .
+ listbox .l2 -font $fixed -width 30 -height 20 -setgrid 1
+ wm geom . +25+25
+ pack .l2
+ update
+ wm deiconify .
+ set result [getsize .]
+ wm geom . 26x15
+ update
+ lappend result [getsize .]
+ .l2 configure -setgrid 1
+ update
+ lappend result [getsize .]
+} -cleanup {
+ deleteWindows
+ wm geom . {}
+} -result {30x20 26x15 26x15}
+
+resetGridInfo
+test listbox-4.8 {ConfigureListbox procedure} -setup {
+ destroy .l2
+} -body {
+ listbox .l2 -width 15 -height 20 -xscrollcommand "record x" \
+ -yscrollcommand "record y"
+ pack .l2
+ update
+ .l2 configure -fg black
+ set log {}
+ update
+ set log
+} -cleanup {
+ destroy .l2
+} -result {{y 0 1} {x 0 1}}
+test listbox-4.9 {ConfigureListbox procedure, -listvar} -setup {
+ destroy .l2
+} -body {
+ set x [list a b c d]
+ listbox .l2 -listvar x
+ .l2 get 0 end
+} -cleanup {
+ destroy .l2
+} -result [list a b c d]
+test listbox-4.10 {ConfigureListbox, no listvar -> existing listvar} -setup {
+ destroy .l2
+} -body {
+ set x [list a b c d]
+ listbox .l2
+ .l2 insert end 1 2 3 4
+ .l2 configure -listvar x
+ .l2 get 0 end
+} -cleanup {
+ destroy .l2
+} -result [list a b c d]
+test listbox-4.11 {ConfigureListbox procedure, listvar -> no listvar} -setup {
+ destroy .l2
+} -body {
+ set x [list a b c d]
+ listbox .l2 -listvar x
+ .l2 configure -listvar {}
+ .l2 insert end 1 2 3 4
+ list $x [.l2 get 0 end]
+} -cleanup {
+ destroy .l2
+} -result [list [list a b c d] [list a b c d 1 2 3 4]]
+test listbox-4.12 {ConfigureListbox procedure, listvar -> different listvar} -setup {
+ destroy .l2
+} -body {
+ set x [list a b c d]
+ set y [list 1 2 3 4]
+ listbox .l2
+ .l2 configure -listvar x
+ .l2 configure -listvar y
+ .l2 insert end 5 6 7 8
+ list $x $y
+} -cleanup {
+ destroy .l2
+} -result [list [list a b c d] [list 1 2 3 4 5 6 7 8]]
+test listbox-4.13 {ConfigureListbox, no listvar -> non-existant listvar} -setup {
+ destroy .l2
+} -body {
+ catch {unset x}
+ listbox .l2
+ .l2 insert end a b c d
+ .l2 configure -listvar x
+ set x
+} -cleanup {
+ destroy .l2
+} -result [list a b c d]
+test listbox-4.14 {ConfigureListbox, non-existant listvar} -setup {
+ destroy .l2
+} -body {
+ catch {unset x}
+ listbox .l2 -listvar x
+ list [info exists x] $x
+} -cleanup {
+ destroy .l2
+} -result [list 1 {}]
+test listbox-4.15 {ConfigureListbox, listvar -> non-existant listvar} -setup {
+ destroy .l2
+} -body {
+ catch {unset y}
+ set x [list a b c d]
+ listbox .l2 -listvar x
+ .l2 configure -listvar y
+ list [info exists y] $y
+} -cleanup {
+ destroy .l2
+} -result [list 1 [list a b c d]]
+test listbox-4.16 {ConfigureListbox, listvar -> same listvar} -setup {
+ destroy .l2
+} -body {
+ set x [list a b c d]
+ listbox .l2 -listvar x
+ .l2 configure -listvar x
+ set x
+} -cleanup {
+ destroy .l2
+} -result [list a b c d]
+test listbox-4.17 {ConfigureListbox, no listvar -> no listvar} -setup {
+ destroy .l2
+} -body {
+ listbox .l2
+ .l2 insert end a b c d
+ .l2 configure -listvar {}
+ .l2 get 0 end
+} -cleanup {
+ destroy .l2
+} -result [list a b c d]
+test listbox-4.18 {ConfigureListbox, no listvar -> bad listvar} -setup {
+ destroy .l2
+} -body {
+ listbox .l2
+ .l2 insert end a b c d
+ set x "this is a \" bad list"
+ catch {.l2 configure -listvar x} result
+ list [.l2 get 0 end] [.l2 cget -listvar] $result
+} -cleanup {
+ destroy .l2
+} -result [list [list a b c d] {} \
+ "unmatched open quote in list: invalid -listvariable value"]
+test listbox-4.19 {ConfigureListbox, no listvar -> bad non-existent listvar} -setup {
+ destroy .l2
+} -body {
+ unset -nocomplain ::foo
+ listbox .l2 -listvar foo
+ .l2 insert end a b c d
+ catch {.l2 configure -listvar ::zoo::bar::foo} result
+ list [.l2 get 0 end] [.l2 cget -listvar] $foo $result
+} -cleanup {
+ destroy .l2
+} -result [list [list a b c d] foo [list a b c d] \
+ {can't set "::zoo::bar::foo": parent namespace doesn't exist}]
+
+
+# No tests for DisplayListbox: I don't know how to test this procedure.
+
+test listbox-5.1 {ListboxComputeGeometry procedure} -constraints {
+ fonts
+} -setup {
+ destroy .l
+} -body {
+ listbox .l -font $fixed -width 15 -height 20
+ pack .l
+ list [winfo reqwidth .l] [winfo reqheight .l]
+} -result {115 328}
+test listbox-5.2 {ListboxComputeGeometry procedure} -constraints {
+ fonts
+} -setup {
+ destroy .l
+} -body {
+ listbox .l -font $fixed -width 0 -height 10
+ pack .l
+ update
+ list [winfo reqwidth .l] [winfo reqheight .l]
+} -result {17 168}
+test listbox-5.3 {ListboxComputeGeometry procedure} -constraints {
+ fonts
+} -setup {
+ destroy .l
+} -body {
+ listbox .l -font $fixed -width 0 -height 10 -bd 3
+ .l insert 0 Short "Really much longer" Longer
+ pack .l
+ update
+ list [winfo reqwidth .l] [winfo reqheight .l]
+} -result {138 170}
+test listbox-5.4 {ListboxComputeGeometry procedure} -constraints {
+ fonts
+} -setup {
+ destroy .l
+} -body {
+ listbox .l -font $fixed -width 10 -height 0
+ pack .l
+ update
+ list [winfo reqwidth .l] [winfo reqheight .l]
+} -result {80 24}
+test listbox-5.5 {ListboxComputeGeometry procedure} -constraints {
+ fonts
+} -setup {
+ destroy .l
+} -body {
+ listbox .l -font $fixed -width 10 -height 0 -highlightthickness 0
+ .l insert 0 Short "Really much longer" Longer
+ pack .l
+ update
+ list [winfo reqwidth .l] [winfo reqheight .l]
+} -result {76 52}
+test listbox-5.6 {ListboxComputeGeometry procedure} -setup {
+ destroy .l
+} -body {
+ # If "0" in selected font had 0 width, caused divide-by-zero error.
+
+ pack [listbox .l -font {{open look glyph}}]
+ update
+} -cleanup {
+ destroy .l
+} -result {}
+
+
+# Listbox used in 6.*, 7.* tests
+destroy .l
+listbox .l -height 2 -xscrollcommand "record x" -yscrollcommand "record y"
+pack .l
+update
+test listbox-6.1 {InsertEls procedure} -body {
+ .l delete 0 end
+ .l insert end a b c d
+ .l insert 5 x y z
+ .l insert 2 A
+ .l insert 0 q r s
+ .l get 0 end
+} -result {q r s a b A c d x y z}
+test listbox-6.2 {InsertEls procedure} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f g h i j
+ .l selection anchor 2
+ .l insert 2 A B
+ .l index anchor
+} -result {4}
+test listbox-6.3 {InsertEls procedure} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f g h i j
+ .l selection anchor 2
+ .l insert 3 A B
+ .l index anchor
+} -result {2}
+test listbox-6.4 {InsertEls procedure} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f g h i j
+ .l yview 3
+ update
+ .l insert 2 A B
+ .l index @0,0
+} -result {5}
+test listbox-6.5 {InsertEls procedure} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f g h i j
+ .l yview 3
+ update
+ .l insert 3 A B
+ .l index @0,0
+} -result {3}
+test listbox-6.6 {InsertEls procedure} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f g h i j
+ .l activate 5
+ .l insert 5 A B
+ .l index active
+} -result {7}
+test listbox-6.7 {InsertEls procedure} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f g h i j
+ .l activate 5
+ .l insert 6 A B
+ .l index active
+} -result {5}
+test listbox-6.8 {InsertEls procedure} -body {
+ .l delete 0 end
+ .l insert 0 a b c
+ .l index active
+} -result {2}
+test listbox-6.9 {InsertEls procedure} -body {
+ .l delete 0 end
+ .l insert 0
+ .l index active
+} -result {0}
+test listbox-6.10 {InsertEls procedure} -body {
+ .l delete 0 end
+ .l insert 0 a b "two words" c d e f g h i j
+ update
+ set log {}
+ .l insert 0 word
+ update
+ set log
+} -result {{y 0 0.166667}}
+test listbox-6.11 {InsertEls procedure} -body {
+ .l delete 0 end
+ .l insert 0 a b "two words" c d e f g h i j
+ update
+ set log {}
+ .l insert 0 "much longer entry"
+ update
+ set log
+} -result {{y 0 0.166667} {x 0 1}}
+test listbox-6.12 {InsertEls procedure} -constraints {
+ fonts
+} -setup {
+ destroy .l2
+} -body {
+ listbox .l2 -width 0 -height 0
+ pack .l2 -side top
+ .l2 insert 0 a b "two words" c d
+ set x {}
+ lappend x [winfo reqwidth .l2] [winfo reqheight .l2]
+ .l2 insert 0 "much longer entry"
+ lappend x [winfo reqwidth .l2] [winfo reqheight .l2]
+} -cleanup {
+ destroy .l2
+} -result {80 93 122 110}
+test listbox-6.13 {InsertEls procedure, check -listvar update} -setup {
+ destroy .l2
+} -body {
+ set x [list a b c d]
+ listbox .l2 -listvar x
+ .l2 insert 0 1 2 3 4
+ set x
+} -cleanup {
+ destroy .l2
+} -result [list 1 2 3 4 a b c d]
+test listbox-6.14 {InsertEls procedure, check selection update} -setup {
+ destroy .l2
+} -body {
+ listbox .l2
+ .l2 insert 0 0 1 2 3 4
+ .l2 selection set 2 4
+ .l2 insert 0 a
+ .l2 curselection
+} -cleanup {
+ destroy .l2
+} -result [list 3 4 5]
+test listbox-6.15 {InsertEls procedure, lost namespaced listvar} -body {
+ destroy .l2
+ namespace eval test { variable foo {a b} }
+ listbox .l2 -listvar ::test::foo
+ namespace delete test
+ .l2 insert end c d
+ .l2 delete end
+ .l2 insert end e f
+ catch {set ::test::foo} result
+ list [.l2 get 0 end] [.l2 cget -listvar] $result
+} -cleanup {
+ destroy .l2
+} -result [list [list a b c e f] ::test::foo \
+ {can't read "::test::foo": no such variable}]
+
+
+test listbox-7.1 {DeleteEls procedure} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f g h i j
+ .l selection set 1 6
+ .l delete 4 3
+ list [.l size] [selection get]
+} -result {10 {b
+c
+d
+e
+f
+g}}
+test listbox-7.2 {DeleteEls procedure} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f g h i j
+ .l selection set 3 6
+ .l delete 4 4
+ list [.l size] [.l get 4] [.l curselection]
+} -result {9 f {3 4 5}}
+test listbox-7.3 {DeleteEls procedure} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f g h i j
+ .l delete 0 3
+ list [.l size] [.l get 0] [.l get 1]
+} -result {6 e f}
+test listbox-7.4 {DeleteEls procedure} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f g h i j
+ .l delete 8 1000
+ list [.l size] [.l get 7]
+} -result {8 h}
+test listbox-7.5 {DeleteEls procedure} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f g h i j
+ .l selection anchor 2
+ .l delete 0 1
+ .l index anchor
+} -result {0}
+test listbox-7.6 {DeleteEls procedure} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f g h i j
+ .l selection anchor 2
+ .l delete 2
+ .l index anchor
+} -result {2}
+test listbox-7.7 {DeleteEls procedure} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f g h i j
+ .l selection anchor 4
+ .l delete 2 5
+ .l index anchor
+} -result {2}
+test listbox-7.8 {DeleteEls procedure} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f g h i j
+ .l selection anchor 3
+ .l delete 4 5
+ .l index anchor
+} -result {3}
+test listbox-7.9 {DeleteEls procedure} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f g h i j
+ .l yview 3
+ update
+ .l delete 1 2
+ .l index @0,0
+} -result {1}
+test listbox-7.10 {DeleteEls procedure} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f g h i j
+ .l yview 3
+ update
+ .l delete 3 4
+ .l index @0,0
+} -result {3}
+test listbox-7.11 {DeleteEls procedure} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f g h i j
+ .l yview 3
+ update
+ .l delete 4 6
+ .l index @0,0
+} -result {3}
+test listbox-7.12 {DeleteEls procedure} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f g h i j
+ .l yview 3
+ update
+ .l delete 3 end
+ .l index @0,0
+} -result {1}
+test listbox-7.13 {DeleteEls procedure, updating view with partial last line} -body {
+ mkPartial
+ .partial.l yview 8
+ update
+ .partial.l delete 10 13
+ .partial.l index @0,0
+} -result {7}
+test listbox-7.14 {DeleteEls procedure} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f g h i j
+ .l activate 6
+ .l delete 3 4
+ .l index active
+} -result {4}
+test listbox-7.15 {DeleteEls procedure} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f g h i j
+ .l activate 6
+ .l delete 5 7
+ .l index active
+} -result {5}
+test listbox-7.16 {DeleteEls procedure} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f g h i j
+ .l activate 6
+ .l delete 5 end
+ .l index active
+} -result {4}
+test listbox-7.17 {DeleteEls procedure} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f g h i j
+ .l activate 6
+ .l delete 0 end
+ .l index active
+} -result {0}
+test listbox-7.18 {DeleteEls procedure} -body {
+ .l delete 0 end
+ .l insert 0 a b c "two words" d e f g h i j
+ update
+ set log {}
+ .l delete 4 6
+ update
+ set log
+} -result {{y 0 0.25}}
+test listbox-7.19 {DeleteEls procedure} -body {
+ .l delete 0 end
+ .l insert 0 a b c "two words" d e f g h i j
+ update
+ set log {}
+ .l delete 3
+ update
+ set log
+} -result {{y 0 0.2} {x 0 1}}
+test listbox-7.20 {DeleteEls procedure} -constraints {
+ fonts
+} -setup {
+ destroy .l2
+} -body {
+ listbox .l2 -width 0 -height 0
+ pack .l2 -side top
+ .l2 insert 0 a b "two words" c d e f g
+ set x {}
+ lappend x [winfo reqwidth .l2] [winfo reqheight .l2]
+ .l2 delete 2 4
+ lappend x [winfo reqwidth .l2] [winfo reqheight .l2]
+} -result {80 144 17 93}
+test listbox-7.21 {DeleteEls procedure, check -listvar update} -setup {
+ destroy .l2
+} -body {
+ set x [list a b c d]
+ listbox .l2 -listvar x
+ .l2 delete 0 1
+ set x
+} -result [list c d]
+
+
+test listbox-8.1 {ListboxEventProc procedure} -constraints {
+ fonts
+} -setup {
+ destroy .l
+} -body {
+ listbox .l -setgrid 1
+ pack .l
+ update
+ set x [getsize .]
+ destroy .l
+ list $x [getsize .] [winfo exists .l] [info command .l]
+} -cleanup {
+ destroy .l
+} -result {20x10 150x178 0 {}}
+resetGridInfo
+test listbox-8.2 {ListboxEventProc procedure} -constraints {
+ fonts
+} -setup {
+ destroy .l
+} -body {
+ listbox .l -height 5 -width 10
+ .l insert 0 a b c "A string that is very very long" d e f g h i j k
+ pack .l
+ update
+ place .l -width 50 -height 80
+ update
+ list [format {%.6g %.6g} {*}[.l xview]] [format {%.6g %.6g} {*}[.l yview]]
+} -cleanup {
+ destroy .l
+} -result {{0 0.222222} {0 0.333333}}
+test listbox-8.3 {ListboxEventProc procedure} -setup {
+ deleteWindows
+} -body {
+ listbox .l1 -bg #543210
+ rename .l1 .l2
+ set x {}
+ lappend x [winfo children .]
+ lappend x [.l2 cget -bg]
+ destroy .l1
+ lappend x [info command .l*] [winfo children .]
+} -cleanup {
+ deleteWindows
+} -result {.l1 #543210 {} {}}
+
+
+test listbox-9.1 {ListboxCmdDeletedProc procedure} -setup {
+ deleteWindows
+} -body {
+ listbox .l1
+ rename .l1 {}
+ list [info command .l*] [winfo children .]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+test listbox-9.2 {ListboxCmdDeletedProc procedure, disabling -setgrid} -constraints {
+ fonts
+} -setup {
+ destroy .top
+} -body {
+ toplevel .top
+ wm geom .top +0+0
+ listbox .top.l -setgrid 1 -width 20 -height 10
+ pack .top.l
+ update
+ set x [getsize .top]
+ rename .top.l {}
+ update
+ lappend x [getsize .top]
+} -cleanup {
+ destroy .top
+} -result {20x10 150x178}
+
+
+# Listbox used in 10.* tests
+destroy .l
+test listbox-10.1 {GetListboxIndex procedure} -setup {
+ destroy .l
+} -body {
+ pack [listbox .l]
+ .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11
+ .l activate 3
+ update
+ list [.l activate 3; .l index active] [.l activate 6; .l index active]
+} -cleanup {
+ destroy .l
+} -result {3 6}
+test listbox-10.2 {GetListboxIndex procedure} -setup {
+ destroy .l
+} -body {
+ pack [listbox .l]
+ .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11
+ .l selection anchor 2
+ update
+ .l index anchor
+} -cleanup {
+ destroy .l
+} -result 2
+test listbox-10.3 {GetListboxIndex procedure} -setup {
+ destroy .l
+} -body {
+ pack [listbox .l]
+ .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11
+ .l insert end A B C D E
+ .l selection anchor end
+ update
+ .l delete 12 end
+ list [.l index anchor] [.l index end]
+} -cleanup {
+ destroy .l
+} -result {12 12}
+test listbox-10.4 {GetListboxIndex procedure} -setup {
+ destroy .l
+} -body {
+ pack [listbox .l]
+ .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11
+ update
+ .l index a
+} -cleanup {
+ destroy .l
+} -returnCodes error -result {bad listbox index "a": must be active, anchor, end, @x,y, or a number}
+test listbox-10.5 {GetListboxIndex procedure} -setup {
+ destroy .l
+} -body {
+ pack [listbox .l]
+ .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11
+ update
+ .l index end
+} -cleanup {
+ destroy .l
+} -result {12}
+test listbox-10.6 {GetListboxIndex procedure} -setup {
+ destroy .l
+} -body {
+ pack [listbox .l]
+ .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11
+ update
+ .l get end
+} -cleanup {
+ destroy .l
+} -result {el11}
+test listbox-10.7 {GetListboxIndex procedure} -setup {
+ destroy .l
+} -body {
+ pack [listbox .l]
+ .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11
+ .l delete 0 end
+ update
+ .l index end
+} -cleanup {
+ destroy .l
+} -result 0
+test listbox-10.8 {GetListboxIndex procedure} -setup {
+ destroy .l
+} -body {
+ pack [listbox .l]
+ .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11
+ update
+ .l index @
+} -cleanup {
+ destroy .l
+} -returnCodes error -result {bad listbox index "@": must be active, anchor, end, @x,y, or a number}
+test listbox-10.9 {GetListboxIndex procedure} -setup {
+ destroy .l
+} -body {
+ pack [listbox .l]
+ .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11
+ update
+ .l index @foo
+} -cleanup {
+ destroy .l
+} -returnCodes error -result {bad listbox index "@foo": must be active, anchor, end, @x,y, or a number}
+test listbox-10.10 {GetListboxIndex procedure} -setup {
+ destroy .l
+} -body {
+ pack [listbox .l]
+ .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11
+ update
+ .l index @1x3
+} -cleanup {
+ destroy .l
+} -returnCodes error -result {bad listbox index "@1x3": must be active, anchor, end, @x,y, or a number}
+test listbox-10.11 {GetListboxIndex procedure} -setup {
+ destroy .l
+} -body {
+ pack [listbox .l]
+ .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11
+ update
+ .l index @1,
+} -cleanup {
+ destroy .l
+} -returnCodes error -result {bad listbox index "@1,": must be active, anchor, end, @x,y, or a number}
+test listbox-10.12 {GetListboxIndex procedure} -setup {
+ destroy .l
+} -body {
+ pack [listbox .l]
+ .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11
+ update
+ .l index @1,foo
+} -cleanup {
+ destroy .l
+} -returnCodes error -result {bad listbox index "@1,foo": must be active, anchor, end, @x,y, or a number}
+test listbox-10.13 {GetListboxIndex procedure} -setup {
+ destroy .l
+} -body {
+ pack [listbox .l]
+ .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11
+ update
+ .l index @1,2x
+} -cleanup {
+ destroy .l
+} -returnCodes error -result {bad listbox index "@1,2x": must be active, anchor, end, @x,y, or a number}
+test listbox-10.14 {GetListboxIndex procedure} -constraints {
+ fonts
+} -setup {
+ destroy .l
+} -body {
+ pack [listbox .l]
+ .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11
+ update
+ list [.l index @5,57] [.l index @5,58]
+} -cleanup {
+ .l delete 0 end
+} -cleanup {
+ destroy .l
+} -result {3 3}
+test listbox-10.15 {GetListboxIndex procedure} -setup {
+ destroy .l
+} -body {
+ pack [listbox .l]
+ .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11
+ update
+ .l index 1xy
+} -cleanup {
+ destroy .l
+} -returnCodes error -result {bad listbox index "1xy": must be active, anchor, end, @x,y, or a number}
+test listbox-10.16 {GetListboxIndex procedure} -setup {
+ destroy .l
+} -body {
+ pack [listbox .l]
+ .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11
+ update
+ .l index 3
+} -cleanup {
+ destroy .l
+} -result {3}
+test listbox-10.17 {GetListboxIndex procedure} -setup {
+ destroy .l
+} -body {
+ pack [listbox .l]
+ .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11
+ update
+ .l index 20
+} -cleanup {
+ destroy .l
+} -result {20}
+test listbox-10.18 {GetListboxIndex procedure} -setup {
+ destroy .l
+} -body {
+ pack [listbox .l]
+ .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11
+ update
+ .l get 20
+} -cleanup {
+ destroy .l
+} -result {}
+test listbox-10.19 {GetListboxIndex procedure} -setup {
+ destroy .l
+} -body {
+ pack [listbox .l]
+ .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11
+ update
+ .l index -2
+} -cleanup {
+ destroy .l
+} -result -2
+test listbox-10.20 {GetListboxIndex procedure} -setup {
+ destroy .l
+} -body {
+ pack [listbox .l]
+ .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11
+ .l delete 0 end
+ update
+ .l index 1
+} -cleanup {
+ destroy .l
+} -result 1
+
+
+test listbox-11.1 {ChangeListboxView procedure, boundary conditions for index} -setup {
+ destroy .l
+} -body {
+ listbox .l -height 5
+ pack .l
+ .l insert 0 a b c d e f g h i j
+ .l yview 3
+ update
+ set x [.l index @0,0]
+ .l yview -1
+ update
+ lappend x [.l index @0,0]
+} -cleanup {
+ destroy .l
+} -result {3 0}
+test listbox-11.2 {ChangeListboxView procedure, boundary conditions for index} -setup {
+ destroy .l
+} -body {
+ listbox .l -height 5
+ pack .l
+ .l insert 0 a b c d e f g h i j
+ .l yview 3
+ update
+ set x [.l index @0,0]
+ .l yview 20
+ update
+ lappend x [.l index @0,0]
+} -cleanup {
+ destroy .l
+} -result {3 5}
+test listbox-11.3 {ChangeListboxView procedure} -setup {
+ destroy .l
+} -body {
+ listbox .l -height 5 -yscrollcommand "record y"
+ pack .l
+ .l insert 0 a b c d e f g h i j
+ update
+ set log {}
+ .l yview 2
+ update
+ list [format {%.6g %.6g} {*}[.l yview]] $log
+} -cleanup {
+ destroy .l
+} -result {{0.2 0.7} {{y 0.2 0.7}}}
+test listbox-11.4 {ChangeListboxView procedure} -setup {
+ destroy .l
+} -body {
+ listbox .l -height 5 -yscrollcommand "record y"
+ pack .l
+ .l insert 0 a b c d e f g h i j
+ update
+ set log {}
+ .l yview 8
+ update
+ list [format {%.6g %.6g} {*}[.l yview]] $log
+} -cleanup {
+ destroy .l
+} -result {{0.5 1} {{y 0.5 1}}}
+test listbox-11.5 {ChangeListboxView procedure} -setup {
+ destroy .l
+} -body {
+ listbox .l -height 5 -yscrollcommand "record y"
+ pack .l
+ .l insert 0 a b c d e f g h i j
+ .l yview 3
+ update
+ set log {}
+ .l yview 3
+ update
+ list [format {%.6g %.6g} {*}[.l yview]] $log
+} -cleanup {
+ destroy .l
+} -result {{0.3 0.8} {}}
+test listbox-11.6 {ChangeListboxView procedure, partial last line} -body {
+ mkPartial
+ .partial.l yview 13
+ .partial.l index @0,0
+} -cleanup {
+ destroy .l
+} -result {11}
+
+
+# Listbox used in 12.* tests
+destroy .l
+listbox .l -font $fixed -xscrollcommand "record x" -width 10
+.l insert 0 0123456789a123456789b123456789c123456789d123456789e123456789f123456789g123456789h123456789i123456789
+pack .l
+update
+test listbox-12.1 {ChangeListboxOffset procedure} -constraints {
+ fonts
+} -body {
+ set log {}
+ .l xview 99
+ update
+ list [format {%.6g %.6g} {*}[.l xview]] $log
+} -result {{0.9 1} {{x 0.9 1}}}
+test listbox-12.2 {ChangeListboxOffset procedure} -constraints {
+ fonts
+} -body {
+ set log {}
+ .l xview 99
+ .l xview moveto -.25
+ update
+ list [format {%.6g %.6g} {*}[.l xview]] $log
+} -result {{0 0.1} {{x 0 0.1}}}
+test listbox-12.3 {ChangeListboxOffset procedure} -constraints {
+ fonts
+} -body {
+ .l xview 10
+ update
+ set log {}
+ .l xview 10
+ update
+ list [format {%.6g %.6g} {*}[.l xview]] $log
+} -result {{0.1 0.2} {}}
+
+
+# Listbox used in 13.* tests
+destroy .l
+listbox .l -font $fixed -width 10 -height 5
+pack .l
+.l insert 0 a bb c d e f g h i j k l m n o p q r s
+.l insert 0 0123456789a123456789b123456789c123456789d123456789
+update
+set width [expr [lindex [.l bbox 2] 2] - [lindex [.l bbox 1] 2]]
+set height [expr [lindex [.l bbox 2] 1] - [lindex [.l bbox 1] 1]]
+test listbox-13.1 {ListboxScanTo procedure} -constraints {
+ fonts
+} -body {
+ .l yview 0
+ .l xview 0
+ .l scan mark 10 20
+ .l scan dragto [expr 10-$width] [expr 20-$height]
+ update
+ list [format {%.6g %.6g} {*}[.l xview]] [format {%.6g %.6g} {*}[.l yview]]
+} -result {{0.2 0.4} {0.5 0.75}}
+test listbox-13.2 {ListboxScanTo procedure} -constraints {
+ fonts
+} -body {
+ .l yview 5
+ .l xview 10
+ .l scan mark 10 20
+ .l scan dragto 20 40
+ update
+ set x [list [format {%.6g %.6g} {*}[.l xview]] [format {%.6g %.6g} {*}[.l yview]]]
+ .l scan dragto [expr 20-$width] [expr 40-$height]
+ update
+ lappend x [format {%.6g %.6g} {*}[.l xview]] [format {%.6g %.6g} {*}[.l yview]]
+} -result {{0 0.2} {0 0.25} {0.2 0.4} {0.5 0.75}}
+test listbox-13.3 {ListboxScanTo procedure} -constraints {
+ fonts
+} -body {
+ .l yview moveto 1.0
+ .l xview moveto 1.0
+ .l scan mark 10 20
+ .l scan dragto 5 10
+ update
+ set x [list [format {%.6g %.6g} {*}[.l xview]] [format {%.6g %.6g} {*}[.l yview]]]
+ .l scan dragto [expr 5+$width] [expr 10+$height]
+ update
+ lappend x [format {%.6g %.6g} {*}[.l xview]] [format {%.6g %.6g} {*}[.l yview]]
+} -result {{0.8 1} {0.75 1} {0.6 0.8} {0.25 0.5}}
+
+
+test listbox-14.1 {NearestListboxElement procedure, partial last line} -body {
+ mkPartial
+ .partial.l nearest [winfo height .partial.l]
+} -result {4}
+# Listbox used in 14.* tests
+destroy .l
+listbox .l -font $fixed -width 20 -height 10
+.l insert 0 a b c d e f g h i j k l m n o p q r s t
+.l yview 4
+pack .l
+update
+test listbox-14.2 {NearestListboxElement procedure} -constraints {
+ fonts
+} -body {
+ .l index @50,0
+} -result {4}
+test listbox-14.3 {NearestListboxElement procedure} -constraints {
+ fonts
+} -body {
+ list [.l index @50,35] [.l index @50,36]
+} -result {5 6}
+test listbox-14.4 {NearestListboxElement procedure} -constraints {
+ fonts
+} -body {
+ .l index @50,200
+} -result {13}
+
+
+# Listbox used in 15.* 16.* and 17.* tests
+destroy .l
+listbox .l -font $fixed -width 20 -height 10
+pack .l
+update
+test listbox-15.1 {ListboxSelect procedure} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f g h i j k l m n o p
+ .l select set 2 4
+ .l select set 7 12
+ .l select clear 4 7
+ .l curselection
+} -result {2 3 8 9 10 11 12}
+test listbox-15.2 {ListboxSelect procedure} -setup {
+ destroy .e
+} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f g h i j k l m n o p
+ entry .e
+ .e insert 0 "This is some text"
+ .e select from 0
+ .e select to 7
+ .l selection clear 2 4
+ set x [selection own]
+ .l selection set 3
+ list $x [selection own] [selection get]
+} -cleanup {
+ destroy .e
+} -result {.e .l d}
+test listbox-15.3 {ListboxSelect procedure} -body {
+ .l delete 0 end
+ .l selection clear 0 end
+ .l select set 0 end
+ .l curselection
+} -result {}
+test listbox-15.4 {ListboxSelect procedure, boundary conditions for indices} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f
+ .l select clear 0 end
+ .l select set -2 -1
+ .l curselection
+} -result {}
+test listbox-15.5 {ListboxSelect procedure, boundary conditions for indices} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f
+ .l select clear 0 end
+ .l select set -1 3
+ .l curselection
+} -result {0 1 2 3}
+test listbox-15.6 {ListboxSelect procedure, boundary conditions for indices} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f
+ .l select clear 0 end
+ .l select set 2 4
+ .l curselection
+} -result {2 3 4}
+test listbox-15.7 {ListboxSelect procedure, boundary conditions for indices} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f
+ .l select clear 0 end
+ .l select set 4 end
+ .l curselection
+} -result {4 5}
+test listbox-15.8 {ListboxSelect procedure, boundary conditions for indices} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f
+ .l select clear 0 end
+ .l select set 4 30
+ .l curselection
+} -result {4 5}
+test listbox-15.9 {ListboxSelect procedure, boundary conditions for indices} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f
+ .l select clear 0 end
+ .l select set end 30
+ .l curselection
+} -result {5}
+test listbox-15.10 {ListboxSelect procedure, boundary conditions for indices} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e f
+ .l select clear 0 end
+ .l select set 20 25
+ .l curselection
+} -result {}
+
+
+test listbox-16.1 {ListboxFetchSelection procedure} -body {
+ .l delete 0 end
+ .l insert 0 a b c "two words" e f g h i \\ k l m n o p
+ .l selection set 2 4
+ .l selection set 9
+ .l selection set 11 12
+ selection get
+} -result "c\ntwo words\ne\n\\\nl\nm"
+test listbox-16.2 {ListboxFetchSelection procedure} -body {
+ .l delete 0 end
+ .l insert 0 a b c "two words" e f g h i \\ k l m n o p
+ .l selection set 3
+ selection get
+} -result "two words"
+test listbox-16.3 {ListboxFetchSelection procedure, retrieve in several parts} -body {
+ set long "This is quite a long string\n"
+ append long $long $long $long $long
+ append long $long $long $long $long
+ append long $long $long
+ .l delete 0 end
+ .l insert 0 1$long 2$long 3$long 4$long 5$long
+ .l selection set 0 end
+ set sel [selection get]
+ string compare 1$long\n2$long\n3$long\n4$long\n5$long $sel
+} -cleanup {
+ catch {unset long sel}
+} -result {0}
+
+
+test listbox-17.1 {ListboxLostSelection procedure} -setup {
+ destroy .e
+} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e
+ .l select set 0 end
+ entry .e
+ .e insert 0 "This is some text"
+ .e select from 0
+ .e select to 5
+ .l curselection
+} -cleanup {
+ destroy .e
+} -result {}
+test listbox-17.2 {ListboxLostSelection procedure} -setup {
+ destroy .e
+} -body {
+ .l delete 0 end
+ .l insert 0 a b c d e
+ .l select set 0 end
+ .l configure -exportselection 0
+ entry .e
+ .e insert 0 "This is some text"
+ .e select from 0
+ .e select to 5
+ .l curselection
+} -cleanup {
+ destroy .e
+} -result {0 1 2 3 4}
+
+
+# Listbox used in 18.* tests
+destroy .l
+listbox .l -font $fixed -width 10 -height 5
+pack .l
+update
+test listbox-18.1 {ListboxUpdateVScrollbar procedure} -body {
+ .l configure -yscrollcommand "record y"
+ set log {}
+ .l insert 0 a b c
+ update
+ .l insert end d e f g h
+ update
+ .l delete 0 end
+ update
+ set log
+} -result {{y 0 1} {y 0 0.625} {y 0 1}}
+test listbox-18.2 {ListboxUpdateVScrollbar procedure, partial last line} -body {
+ mkPartial
+ .partial.l configure -yscrollcommand "record y"
+ set log {}
+ .partial.l yview 3
+ update
+ set log
+} -result {{y 0.2 0.466667}}
+test listbox-18.3 {ListboxUpdateVScrollbar procedure} -body {
+ proc bgerror args {
+ global x errorInfo
+ set x [list $args $errorInfo]
+ }
+ .l configure -yscrollcommand gorp
+ .l insert 0 foo
+ update
+ set x
+} -cleanup {
+ rename bgerror {}
+} -result {{{invalid command name "gorp"}} {invalid command name "gorp"
+ while executing
+"gorp 0.0 1.0"
+ (vertical scrolling command executed by listbox)}}
+
+
+# Listbox used in 19.* tests
+destroy .l
+listbox .l -font $fixed -width 10 -height 5
+pack .l
+update
+test listbox-19.1 {ListboxUpdateVScrollbar procedure} -constraints {
+ fonts
+} -body {
+ .l configure -xscrollcommand "record x"
+ set log {}
+ .l insert 0 abc
+ update
+ .l insert 0 "This is a much longer string..."
+ update
+ .l delete 0 end
+ update
+ set log
+} -result {{x 0 1} {x 0 0.322581} {x 0 1}}
+test listbox-19.2 {ListboxUpdateVScrollbar procedure} -body {
+ proc bgerror args {
+ global x errorInfo
+ set x [list $args $errorInfo]
+ }
+ .l configure -xscrollcommand bogus
+ .l insert 0 foo
+ update
+ set x
+} -result {{{invalid command name "bogus"}} {invalid command name "bogus"
+ while executing
+"bogus 0.0 1.0"
+ (horizontal scrolling command executed by listbox)}}
+
+
+test listbox-20.1 {listbox vs hidden commands} -setup {
+ deleteWindows
+} -body {
+ set l [interp hidden]
+ listbox .l
+ interp hide {} .l
+ destroy .l
+ set res1 [list [winfo children .] [interp hidden]]
+ set res2 [list {} $l]
+ expr {$res1 eq $res2}
+} -result 1
+
+
+# tests for ListboxListVarProc
+test listbox-21.1 {ListboxListVarProc} -setup {
+ destroy .l
+} -body {
+ catch {unset x}
+ listbox .l -listvar x
+ set x [list a b c d]
+ .l get 0 end
+} -cleanup {
+ destroy .l
+} -result [list a b c d]
+test listbox-21.2 {ListboxListVarProc} -setup {
+ destroy .l
+} -body {
+ set x [list a b c d]
+ listbox .l -listvar x
+ unset x
+ set x
+} -cleanup {
+ destroy .l
+} -result [list a b c d]
+test listbox-21.3 {ListboxListVarProc} -setup {
+ destroy .l
+} -body {
+ set x [list a b c d]
+ listbox .l -listvar x
+ .l configure -listvar {}
+ unset x
+ info exists x
+} -cleanup {
+ destroy .l
+} -result 0
+test listbox-21.4 {ListboxListVarProc} -setup {
+ destroy .l
+} -body {
+ set x [list a b c d]
+ listbox .l -listvar x
+ lappend x e f g
+ .l size
+} -cleanup {
+ destroy .l
+} -result 7
+test listbox-21.5 {ListboxListVarProc, test selection after listvar mod} -setup {
+ destroy .l
+} -body {
+ set x [list a b c d e f g]
+ listbox .l -listvar x
+ .l selection set end
+ set x [list a b c d]
+ set x [list 0 1 2 3 4 5 6]
+ .l curselection
+} -cleanup {
+ destroy .l
+} -result {}
+test listbox-21.6 {ListboxListVarProc, test selection after listvar mod} -setup {
+ destroy .l
+} -body {
+ set x [list a b c d]
+ listbox .l -listvar x
+ .l selection set 3
+ lappend x e f g
+ .l curselection
+} -cleanup {
+ destroy .l
+} -result 3
+test listbox-21.7 {ListboxListVarProc, test selection after listvar mod} -setup {
+ destroy .l
+} -body {
+ set x [list a b c d]
+ listbox .l -listvar x
+ .l selection set 0
+ set x [linsert $x 0 1 2 3 4]
+ .l curselection
+} -cleanup {
+ destroy .l
+} -result 0
+test listbox-21.8 {ListboxListVarProc, test selection after listvar mod} -setup {
+ destroy .l
+} -body {
+ set x [list a b c d]
+ listbox .l -listvar x
+ .l selection set 2
+ set x [list a b c]
+ .l curselection
+} -cleanup {
+ destroy .l
+} -result 2
+test listbox-21.9 {ListboxListVarProc, test hscrollbar after listvar mod} -setup {
+ destroy .l
+} -body {
+ catch {unset x}
+ set log {}
+ listbox .l -font $fixed -width 10 -xscrollcommand "record x" -listvar x
+ pack .l
+ update
+ lappend x "0000000000"
+ update
+ lappend x "00000000000000000000"
+ update
+ set log
+} -cleanup {
+ destroy .l
+} -result [list {x 0 1} {x 0 1} {x 0 0.5}]
+test listbox-21.10 {ListboxListVarProc, test hscrollbar after listvar mod} -setup {
+ destroy .l
+} -body {
+ catch {unset x}
+ set log {}
+ listbox .l -font $fixed -width 10 -xscrollcommand "record x" -listvar x
+ pack .l
+ update
+ lappend x "0000000000"
+ update
+ lappend x "00000000000000000000"
+ update
+ set x [list "0000000000"]
+ update
+ set log
+} -cleanup {
+ destroy .l
+} -result [list {x 0 1} {x 0 1} {x 0 0.5} {x 0 1}]
+test listbox-21.11 {ListboxListVarProc, bad list} -setup {
+ destroy .l
+} -body {
+ catch {unset x}
+ listbox .l -listvar x
+ set x [list a b c d]
+ catch {set x "this is a \" bad list"} result
+ set result
+} -cleanup {
+ destroy .l
+} -result {can't set "x": invalid listvar value}
+test listbox-21.12 {ListboxListVarProc, cleanup item attributes} -setup {
+ destroy .l
+} -body {
+ set x [list a b c d e f g]
+ listbox .l -listvar x
+ .l itemconfigure end -fg red
+ set x [list a b c d]
+ set x [list 0 1 2 3 4 5 6]
+ .l itemcget end -fg
+} -cleanup {
+ destroy .l
+} -result {}
+test listbox-21.12a {ListboxListVarProc, cleanup item attributes} -setup {
+ destroy .l
+} -body {
+ set x [list a b c d e f g]
+ listbox .l -listvar x
+ .l itemconfigure end -fg red
+ set x [list a b c d]
+ set x [list 0 1 2 3 4 5 6]
+ .l itemcget end -fg
+} -cleanup {
+ destroy .l
+} -result {}
+test listbox-21.13 {listbox item configurations and listvar based deletions} -setup {
+ destroy .l
+} -body {
+ catch {unset x}
+ listbox .l -listvar x
+ .l insert end a b c
+ .l itemconfigure 1 -fg red
+ set x [list b c]
+ .l itemcget 1 -fg
+} -cleanup {
+ destroy .l
+} -result red
+test listbox-21.14 {listbox item configurations and listvar based inserts} -setup {
+ destroy .l
+} -body {
+ catch {unset x}
+ listbox .l -listvar x
+ .l insert end a b c
+ .l itemconfigure 0 -fg red
+ set x [list 1 2 3 4 a b c]
+ .l itemcget 0 -fg
+} -cleanup {
+ destroy .l
+} -result red
+test listbox-21.15 {ListboxListVarProc, update vertical scrollbar} -setup {
+ destroy .l
+} -body {
+ catch {unset x}
+ set log {}
+ listbox .l -listvar x -yscrollcommand "record y" -font fixed -height 3
+ pack .l
+ update
+ lappend x a b c d e f
+ update
+ set log
+} -cleanup {
+ destroy .l
+} -result [list {y 0 1} {y 0 0.5}]
+test listbox-21.16 {ListboxListVarProc, update vertical scrollbar} -setup {
+ destroy .l
+} -body {
+ catch {unset x}
+ listbox .l -listvar x -height 3
+ pack .l
+ update
+ set x [list 0 1 2 3 4 5]
+ .l yview scroll 3 units
+ update
+ set result {}
+ lappend result [format {%.6g %.6g} {*}[.l yview]]
+ set x [lreplace $x 3 3]
+ set x [lreplace $x 3 3]
+ set x [lreplace $x 3 3]
+ update
+ lappend result [format {%.6g %.6g} {*}[.l yview]]
+ set result
+} -cleanup {
+ destroy .l
+} -result [list {0.5 1} {0 1}]
+
+
+# UpdateHScrollbar
+test listbox-22.1 {UpdateHScrollbar} -setup {
+ destroy .l
+} -body {
+ set log {}
+ listbox .l -font $fixed -width 10 -xscrollcommand "record x"
+ pack .l
+ update
+ .l insert end "0000000000"
+ update
+ .l insert end "00000000000000000000"
+ update
+ set log
+} -cleanup {
+ destroy .l
+} -result [list {x 0 1} {x 0 1} {x 0 0.5}]
+
+
+# ConfigureListboxItem
+test listbox-23.1 {ConfigureListboxItem} -setup {
+ destroy .l
+} -body {
+ listbox .l
+ catch {.l itemconfigure 0} result
+ set result
+} -cleanup {
+ destroy .l
+} -result {item number "0" out of range}
+test listbox-23.2 {ConfigureListboxItem} -setup {
+ destroy .l
+} -body {
+ listbox .l
+ .l insert end a b c d
+ .l itemconfigure 0
+} -cleanup {
+ destroy .l
+} -result [list {-background background Background {} {}} \
+ {-bg -background} \
+ {-fg -foreground} \
+ {-foreground foreground Foreground {} {}} \
+ {-selectbackground selectBackground Foreground {} {}} \
+ {-selectforeground selectForeground Background {} {}}]
+test listbox-23.3 {ConfigureListboxItem, itemco shortcut} -setup {
+ destroy .l
+} -body {
+ listbox .l
+ .l insert end a b c d
+ .l itemco 0 -background
+} -cleanup {
+ destroy .l
+} -result {-background background Background {} {}}
+test listbox-23.4 {ConfigureListboxItem, wrong num args} -setup {
+ destroy .l
+} -body {
+ listbox .l
+ .l insert end a
+ catch {.l itemco} result
+ set result
+} -cleanup {
+ destroy .l
+} -result {wrong # args: should be ".l itemconfigure index ?-option? ?value? ?-option value ...?"}
+test listbox-23.5 {ConfigureListboxItem, multiple calls} -setup {
+ destroy .l
+} -body {
+ listbox .l
+ set i 0
+ foreach color {red orange yellow green blue white violet} {
+ .l insert end $color
+ .l itemconfigure $i -bg $color
+ incr i
+ }
+ pack .l
+ update
+ list [.l itemcget 0 -bg] [.l itemcget 1 -bg] [.l itemcget 2 -bg] \
+ [.l itemcget 3 -bg] [.l itemcget 4 -bg] [.l itemcget 5 -bg] \
+ [.l itemcget 6 -bg]
+} -cleanup {
+ destroy .l
+} -result {red orange yellow green blue white violet}
+
+# Listbox used in 23.6 -23.17 tests
+destroy .l
+listbox .l
+.l insert end a b c d
+test listbox-23.6 {configuration options} -body {
+ .l itemconfigure 0 -background #ff0000
+ list [lindex [.l itemconfigure 0 -background] 4] [.l itemcget 0 -background]
+} -cleanup {
+ .l configure -background #ffffff
+} -result {{#ff0000} #ff0000}
+test listbox-23.7 {configuration options} -body {
+ .l configure -background non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+test listbox-23.8 {configuration options} -body {
+ .l itemconfigure 0 -bg #ff0000
+ list [lindex [.l itemconfigure 0 -bg] 4] [.l itemcget 0 -bg]
+} -cleanup {
+ .l configure -bg #ffffff
+} -result {{#ff0000} #ff0000}
+test listbox-23.9 {configuration options} -body {
+ .l configure -bg non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+test listbox-23.10 {configuration options} -body {
+ .l itemconfigure 0 -fg #110022
+ list [lindex [.l itemconfigure 0 -fg] 4] [.l itemcget 0 -fg]
+} -cleanup {
+ .l configure -fg #000000
+} -result {{#110022} #110022}
+test listbox-23.11 {configuration options} -body {
+ .l configure -fg bogus
+} -returnCodes error -result {unknown color name "bogus"}
+test listbox-23.12 {configuration options} -body {
+ .l itemconfigure 0 -foreground #110022
+ list [lindex [.l itemconfigure 0 -foreground] 4] [.l itemcget 0 -foreground]
+} -cleanup {
+ .l configure -foreground #000000
+} -result {{#110022} #110022}
+test listbox-23.13 {configuration options} -body {
+ .l configure -foreground bogus
+} -returnCodes error -result {unknown color name "bogus"}
+test listbox-23.14 {configuration options} -body {
+ .l itemconfigure 0 -selectbackground #110022
+ list [lindex [.l itemconfigure 0 -selectbackground] 4] [.l itemcget 0 -selectbackground]
+} -cleanup {
+ .l configure -selectbackground #c3c3c3
+} -result {{#110022} #110022}
+test listbox-23.15 {configuration options} -body {
+ .l configure -selectbackground bogus
+} -returnCodes error -result {unknown color name "bogus"}
+test listbox-23.16 {configuration options} -body {
+ .l itemconfigure 0 -selectforeground #654321
+ list [lindex [.l itemconfigure 0 -selectforeground] 4] [.l itemcget 0 -selectforeground]
+} -cleanup {
+ .l configure -selectforeground #000000
+} -result {{#654321} #654321}
+test listbox-23.17 {configuration options} -body {
+ .l configure -selectforeground bogus
+} -returnCodes error -result {unknown color name "bogus"}
+
+
+# ListboxWidgetObjCmd, itemcget
+test listbox-24.1 {itemcget} -setup {
+ destroy .l
+} -body {
+ listbox .l
+ .l insert end a b c d
+ .l itemcget 0 -fg
+} -cleanup {
+ destroy .l
+} -result {}
+test listbox-24.2 {itemcget} -setup {
+ destroy .l
+} -body {
+ listbox .l
+ .l insert end a b c d
+ .l itemconfigure 0 -fg red
+ .l itemcget 0 -fg
+} -cleanup {
+ destroy .l
+} -result red
+test listbox-24.3 {itemcget} -setup {
+ destroy .l
+} -body {
+ listbox .l
+ .l insert end a b c d
+ catch {.l itemcget 0} result
+ set result
+} -cleanup {
+ destroy .l
+} -result {wrong # args: should be ".l itemcget index option"}
+test listbox-24.4 {itemcget, itemcg shortcut} -setup {
+ destroy .l
+} -body {
+ listbox .l
+ .l insert end a b c d
+ catch {.l itemcg 0} result
+ set result
+} -cleanup {
+ destroy .l
+} -result {wrong # args: should be ".l itemcget index option"}
+
+
+# General item configuration issues
+test listbox-25.1 {listbox item configurations and widget based deletions} -setup {
+ destroy .l
+} -body {
+ listbox .l
+ .l insert end a
+ .l itemconfigure 0 -fg red
+ .l delete 0 end
+ .l insert end a
+ .l itemcget 0 -fg
+} -cleanup {
+ destroy .l
+} -result {}
+test listbox-25.2 {listbox item configurations and widget based inserts} -setup {
+ destroy .l
+} -body {
+ listbox .l
+ .l insert end a b c
+ .l itemconfigure 0 -fg red
+ .l insert 0 1 2 3 4
+ list [.l itemcget 0 -fg] [.l itemcget 4 -fg]
+} -cleanup {
+ destroy .l
+} -result {{} red}
+
+
+# state issues
+test listbox-26.1 {listbox disabled state disallows inserts} -setup {
+ destroy .l
+} -body {
+ listbox .l
+ .l insert end a b c
+ .l configure -state disabled
+ .l insert end d e f
+ .l get 0 end
+} -cleanup {
+ destroy .l
+} -result [list a b c]
+test listbox-26.2 {listbox disabled state disallows deletions} -setup {
+ destroy .l
+} -body {
+ listbox .l
+ .l insert end a b c
+ .l configure -state disabled
+ .l delete 0 end
+ .l get 0 end
+} -cleanup {
+ destroy .l
+} -result [list a b c]
+test listbox-26.3 {listbox disabled state disallows selection modification} -setup {
+ destroy .l
+} -body {
+ listbox .l
+ .l insert end a b c
+ .l selection set 0
+ .l selection set 2
+ .l configure -state disabled
+ .l selection clear 0 end
+ .l selection set 1
+ .l curselection
+} -cleanup {
+ destroy .l
+} -result [list 0 2]
+test listbox-26.4 {listbox disabled state disallows anchor modification} -setup {
+ destroy .l
+} -body {
+ listbox .l
+ .l insert end a b c
+ .l selection anchor 0
+ .l configure -state disabled
+ .l selection anchor 2
+ .l index anchor
+} -cleanup {
+ destroy .l
+} -result 0
+test listbox-26.5 {listbox disabled state disallows active modification} -setup {
+ destroy .l
+} -body {
+ listbox .l
+ .l insert end a b c
+ .l activate 0
+ .l configure -state disabled
+ .l activate 2
+ .l index active
+} -cleanup {
+ destroy .l
+} -result 0
+
+
+test listbox-27.1 {widget deletion while active} -setup {
+ destroy .l
+} -body {
+ pack [listbox .l]
+ update
+ .l configure -cursor xterm -xscrollcommand { destroy .l }
+ update idle
+ winfo exists .l
+} -cleanup {
+ destroy .l
+} -result 0
+
+
+test listbox-28.1 {listbox -activestyle} -setup {
+ destroy .l
+} -body {
+ listbox .l -activ non
+ .l cget -activestyle
+} -cleanup {
+ destroy .l
+} -result none
+test listbox-28.2 {listbox -activestyle} -constraints {
+ nonwin
+} -setup {
+ destroy .l
+} -body {
+ listbox .l
+ .l cget -activestyle
+} -cleanup {
+ destroy .l
+} -result dotbox
+test listbox-28.3 {listbox -activestyle} -constraints {
+ win
+} -setup {
+ destroy .l
+} -body {
+ listbox .l
+ .l cget -activestyle
+} -cleanup {
+ destroy .l
+} -result underline
+test listbox-28.4 {listbox -activestyle} -setup {
+ destroy .l
+} -body {
+ listbox .l -activestyle und
+ .l cget -activestyle
+} -cleanup {
+ destroy .l
+} -result underline
+
+
+test listbox-29.1 {listbox selection behavior, -state disabled} -setup {
+ destroy .l
+} -body {
+ listbox .l
+ .l insert end 1 2 3
+ .l selection set 2
+ set out [.l selection includes 2]
+ .l configure -state disabled
+ # still return 1 when disabled, because 'selection get' will work,
+ # but selection cannot be changed (new behavior since 8.4)
+ .l selection set 3
+ lappend out [.l selection includes 2] [.l curselection]
+} -cleanup {
+ destroy .l
+} -result {1 1 2}
+
+test listbox-30.1 {Bug 3607326} -setup {
+ destroy .l
+ unset -nocomplain a
+} -body {
+ array set a {}
+ listbox .l -listvariable a
+} -cleanup {
+ destroy .l
+ unset -nocomplain a
+} -result * -match glob -returnCodes error
+
+test listbox-31.1 {<<ListboxSelect>> event} -setup {
+ destroy .l
+ unset -nocomplain res
+} -body {
+ pack [listbox .l -state normal]
+ update
+ bind .l <<ListboxSelect>> {lappend res [%W curselection]}
+ .l insert end a b c
+ focus -force .l
+ event generate .l <1> -x 5 -y 5 ; # <<ListboxSelect>> fires
+ .l configure -state disabled
+ focus -force .l
+ event generate .l <Control-Home> ; # <<ListboxSelect>> does NOT fire
+ .l configure -state normal
+ focus -force .l
+ event generate .l <Control-End> ; # <<ListboxSelect>> fires
+ .l selection clear 0 end ; # <<ListboxSelect>> does NOT fire
+ .l selection set 1 1 ; # <<ListboxSelect>> does NOT fire
+ lappend res [.l curselection]
+} -cleanup {
+ destroy .l
+ unset -nocomplain res
+} -result {0 2 1}
+
+test listbox-31.2 {<<ListboxSelect>> event on lost selection} -setup {
+ destroy .l
+} -body {
+ pack [listbox .l -exportselection true]
+ update
+ bind .l <<ListboxSelect>> {lappend res [list [selection own] [%W curselection]]}
+ .l insert end a b c
+ focus -force .l
+ event generate .l <1> -x 5 -y 5 ; # <<ListboxSelect>> fires
+ selection clear ; # <<ListboxSelect>> fires again
+ update
+ set res
+} -cleanup {
+ destroy .l
+} -result {{.l 0} {{} {}}}
+
+test listbox-32.1 {Bug [5d991b822e]} {
+ # Want this not to segfault, or write to variable with empty name
+ set var INIT
+ listbox .b -listvariable var
+ trace add variable var unset {apply {args {
+ .b configure -listvariable {}
+ }}}
+ pack .b
+ bind .b <Configure> {unset var}
+ update
+ destroy .b
+ info exists {}
+} 0
+test listbox-32.2 {Bug [5d991b822e]} {
+ # Want this not to leak traces
+ set var INIT
+ listbox .b -listvariable var
+ trace add variable var unset {apply {args {
+ .b configure -listvariable new
+ }}}
+ pack .b
+ bind .b <Configure> {unset -nocomplain var}
+ update
+ destroy .b
+ unset new
+} {}
+
+resetGridInfo
+deleteWindows
+option clear
+
+# cleanup
+cleanupTests
+return
+
+
+
+
+
diff --git a/tk8.6/tests/main.test b/tk8.6/tests/main.test
new file mode 100644
index 0000000..7ab624f
--- /dev/null
+++ b/tk8.6/tests/main.test
@@ -0,0 +1,120 @@
+# This file contains tests for the tkMain.c file.
+#
+# This file contains a collection of tests for one or more of the Tcl
+# built-in commands. Sourcing this file into Tcl runs the tests and
+# generates output for errors. No output means no errors were found.
+#
+# Copyright (c) 1997 by Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+
+test main-1.1 {StdinProc} -constraints stdio -setup {
+ set script [makeFile {close stdin; exit} script]
+} -body {
+ exec [interpreter] <$script
+} -cleanup {
+ removeFile script
+} -returnCodes ok
+
+test main-2.1 {Tk_MainEx: -encoding option} -constraints stdio -setup {
+ set script [makeFile {} script]
+ file delete $script
+ set f [open $script w]
+ fconfigure $f -encoding utf-8
+ puts $f {puts [list $argv0 $argv $tcl_interactive]}
+ puts -nonewline $f {puts [string equal \u20ac }
+ puts $f "\u20ac]; exit"
+ close $f
+ catch {set f [open "|[list [interpreter] -encoding utf-8 script]" r]}
+} -body {
+ read $f
+} -cleanup {
+ close $f
+ removeFile script
+} -result "script {} 0\n1\n"
+
+test main-2.2 {Tk_MainEx: -encoding option} -constraints stdio -setup {
+ set script [makeFile {} script]
+ file delete $script
+ set f [open $script w]
+ fconfigure $f -encoding utf-8
+ puts $f {puts [list $argv0 $argv $tcl_interactive]}
+ puts -nonewline $f {puts [string equal \u20ac }
+ puts $f "\u20ac]; exit"
+ close $f
+ catch {set f [open "|[list [interpreter] -encoding ascii script]" r]}
+} -body {
+ read $f
+} -cleanup {
+ close $f
+ removeFile script
+} -result "script {} 0\n0\n"
+
+ # Procedure to simulate interactive typing of commands, line by line,
+ # for test 2.3
+ proc type {chan script} {
+ foreach line [split $script \n] {
+ if {[catch {
+ puts $chan $line
+ flush $chan
+ }]} {
+ return
+ }
+ # Grrr... Behavior depends on this value.
+ after 1000
+ }
+ }
+
+test main-2.3 {Tk_MainEx: -encoding option} -constraints stdio -setup {
+ set script [makeFile {} script]
+ file delete $script
+ set f [open $script w]
+ fconfigure $f -encoding utf-8
+ puts $f {puts [list $argv0 $argv $tcl_interactive]}
+ puts -nonewline $f {puts [string equal \u20ac }
+ puts $f "\u20ac]"
+ close $f
+ catch {set f [open "|[list [interpreter] -enc utf-8 script]" r+]}
+} -body {
+ type $f {
+ puts $argv
+ exit
+ }
+ gets $f
+} -cleanup {
+ close $f
+ removeFile script
+} -returnCodes ok -result {-enc utf-8 script}
+
+test main-3.1 {Tk_ParseArgv: -help option} -constraints unix -body {
+ # Run only on unix as Win32 pops up native dialog
+ exec [interpreter] -help
+} -returnCodes error -match glob -result {% application-specific initialization failed: Command-specific options:*}
+
+test main-3.2 {Tk_ParseArgv: -help option} -setup {
+ set maininterp [interp create]
+} -body {
+ $maininterp eval { set argc 1 ; set argv -help }
+ load {} Tk $maininterp
+} -cleanup {
+ interp delete $maininterp
+} -returnCodes error -match glob -result {Command-specific options:*}
+
+test main-3.3 {Tk_ParseArgv: -help option} -setup {
+ set maininterp [interp create]
+} -body {
+ # Repeat of 3.2 to catch cleanup, eg Bug 1927135
+ $maininterp eval { set argc 1 ; set argv -help }
+ load {} Tk $maininterp
+} -cleanup {
+ interp delete $maininterp
+} -returnCodes error -match glob -result {Command-specific options:*}
+
+# cleanup
+cleanupTests
+return
diff --git a/tk8.6/tests/menu.test b/tk8.6/tests/menu.test
new file mode 100644
index 0000000..a7f5956
--- /dev/null
+++ b/tk8.6/tests/menu.test
@@ -0,0 +1,3971 @@
+# This file is a Tcl script to test menus in Tk. It is
+# organized in the standard fashion for Tcl tests.
+#
+# Copyright (c) 1995-1997 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+imageInit
+
+# find the earth.gif file for use in these tests (tests 2.*)
+set earthPhotoFile [file join [file dirname [info script]] earth.gif]
+testConstraint hasEarthPhoto [file exists $earthPhotoFile]
+
+test menu-1.1 {Tk_MenuCmd procedure} -body {
+ menu
+} -returnCodes error -result {wrong # args: should be "menu pathName ?-option value ...?"}
+test menu-1.2 {Tk_MenuCmd procedure} -body {
+ menu bogus
+} -returnCodes error -result {bad window path name "bogus"}
+test menu-1.3 {Tk_MenuCmd procedure} -body {
+ destroy .m1
+ menu .m1 foo
+} -returnCodes error -result {unknown option "foo"}
+test menu-1.4 {Tk_MenuCmd procedure} -body {
+ destroy .m1
+ menu .m1
+} -cleanup {
+ deleteWindows
+} -result {.m1}
+test menu-1.5 {Tk_MenuCmd - creating menubar} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add cascade -label Test -menu ""
+ list [. configure -menu .m1] [. configure -menu ""]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+test menu-1.6 {Tk_MenuCmd procedure menu ref no cascade} -setup {
+ deleteWindows
+} -body {
+ toplevel .t2 -menu .m1
+ wm geometry .t2 +0+0
+ menu .m1
+} -cleanup {
+ deleteWindows
+} -result {.m1}
+test menu-1.7 {Tk_MenuCmd procedure one clone cascade} -setup {
+ deleteWindows
+} -body {
+ toplevel .t2 -menu .m1
+ wm geometry .t2 +0+0
+ menu .m1
+ .m1 add cascade -menu .m2
+ menu .m2
+} -cleanup {
+ deleteWindows
+} -result {.m2}
+test menu-1.8 {Tk_MenuCmd procedure two clone cascades} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add cascade -menu .m2
+ toplevel .t2 -menu .m1
+ wm geometry .t2 +0+0
+ toplevel .t3 -menu .m1
+ wm geometry .t3 +0+0
+ menu .m2
+} -cleanup {
+ deleteWindows
+} -result {.m2}
+test menu-1.9 {Tk_MenuCmd procedure two clone cascades different order} -setup {
+ deleteWindows
+} -body {
+ toplevel .t2 -menu .m1
+ wm geometry .t2 +0+0
+ menu .m1
+ .m1 add cascade -menu .m2
+ toplevel .t3 -menu .m1
+ wm geometry .t3 +0+0
+ list [menu .m2]
+} -cleanup {
+ deleteWindows
+} -result {.m2}
+test menu-1.10 {Tk_MenuCmd procedure two clone cascades menus last} -setup {
+ deleteWindows
+} -body {
+ toplevel .t2 -menu .m1
+ wm geometry .t2 +0+0
+ toplevel .t3 -menu .m1
+ wm geometry .t3 +0+0
+ menu .m1
+ .m1 add cascade -menu .m2
+ list [menu .m2]
+} -cleanup {
+ deleteWindows
+} -result {.m2}
+test menu-1.11 {Tk_MenuCmd procedure three clones cascades} -setup {
+ deleteWindows
+} -body {
+ toplevel .t2 -menu .m1
+ wm geometry .t2 +0+0
+ toplevel .t3 -menu .m1
+ wm geometry .t3 +0+0
+ toplevel .t4 -menu .m1
+ wm geometry .t4 +0+0
+ menu .m1
+ .m1 add cascade -menu .m2
+ list [menu .m2]
+} -cleanup {
+ deleteWindows
+} -result {.m2}
+test menu-1.12 {Tk_MenuCmd procedure} -setup {
+ deleteWindows
+} -body {
+ toplevel .t2 -menu .m1
+ wm geometry .t2 +0+0
+ list [menu .m1]
+} -cleanup {
+ deleteWindows
+} -result {.m1}
+test menu-1.13 {Tk_MenuCmd procedure} -setup {
+ deleteWindows
+} -body {
+ toplevel .t2 -menu .m1
+ wm geometry .t2 +0+0
+ toplevel .t3 -menu .m1
+ wm geometry .t3 +0+0
+ list [menu .m1]
+} -cleanup {
+ deleteWindows
+} -result {.m1}
+test menu-1.14 {Tk_MenuCmd procedure} -setup {
+ deleteWindows
+} -body {
+ toplevel .t2 -menu .m1
+ wm geometry .t2 +0+0
+ toplevel .t3 -menu .m1
+ wm geometry .t3 +0+0
+ toplevel .t4 -menu .m1
+ wm geometry .t4 +0+0
+ list [menu .m1]
+} -cleanup {
+ deleteWindows
+} -result {.m1}
+
+# Used for 2.1 - 2.30 tests
+destroy .m1
+menu .m1
+test menu-2.1 {configuration options -activebackground #012345} -body {
+ .m1 configure -activebackground #012345
+ .m1 cget -activebackground
+} -result {#012345}
+test menu-2.2 {configuration options -activebackground non-existent} -body {
+ .m1 configure -activebackground non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+
+test menu-2.3 {configuration options -activeborderwidth 1.3} -body {
+ .m1 configure -activeborderwidth 1.3
+ .m1 cget -activeborderwidth
+} -result {1.3}
+test menu-2.4 {configuration options -activeborderwidth badValue} -body {
+ .m1 configure -activeborderwidth badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+
+test menu-2.5 {configuration options -activeforeground #ff0000} -body {
+ .m1 configure -activeforeground #ff0000
+ .m1 cget -activeforeground
+} -result {#ff0000}
+test menu-2.6 {configuration options -activeforeground non-existent} -body {
+ .m1 configure -activeforeground non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+
+test menu-2.7 {configuration options -background #ff0000} -body {
+ .m1 configure -background #ff0000
+ .m1 cget -background
+} -result {#ff0000}
+test menu-2.8 {configuration options -background non-existent} -body {
+ .m1 configure -background non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+
+test menu-2.9 {configuration options -bg #110022} -body {
+ .m1 configure -bg #110022
+ .m1 cget -bg
+} -result {#110022}
+test menu-2.10 {configuration options -bg bogus} -body {
+ .m1 configure -bg bogus
+} -returnCodes error -result {unknown color name "bogus"}
+
+test menu-2.11 {configuration options -borderwidth 1.3} -body {
+ .m1 configure -borderwidth 1.3
+ .m1 cget -borderwidth
+} -result {1.3}
+test menu-2.12 {configuration options -borderwidth badValue} -body {
+ .m1 configure -borderwidth badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+
+test menu-2.13 {configuration options -cursor arrow} -body {
+ .m1 configure -cursor arrow
+ .m1 cget -cursor
+} -result {arrow}
+test menu-2.14 {configuration options -cursor badValue} -body {
+ .m1 configure -cursor badValue
+} -returnCodes error -result {bad cursor spec "badValue"}
+
+test menu-2.15 {configuration options -disabledforeground #00ff00} -body {
+ .m1 configure -disabledforeground #00ff00
+ .m1 cget -disabledforeground
+} -result {#00ff00}
+test menu-2.16 {configuration options -disabledforeground xyzzy} -body {
+ .m1 configure -disabledforeground xyzzy
+} -returnCodes error -result {unknown color name "xyzzy"}
+
+test menu-2.17 {configuration options -fg #110022} -body {
+ .m1 configure -fg #110022
+ .m1 cget -fg
+} -result {#110022}
+test menu-2.18 {configuration options -fg bogus} -body {
+ .m1 configure -fg bogus
+} -returnCodes error -result {unknown color name "bogus"}
+
+test menu-2.19 {configuration options -font -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*} -body {
+ .m1 configure -font -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*
+ .m1 cget -font
+} -result {-Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*}
+test menu-2.20 {configuration options -foreground #110022} -body {
+ .m1 configure -foreground #110022
+ .m1 cget -foreground
+} -result {#110022}
+test menu-2.21 {configuration options -foreground bogus} -body {
+ .m1 configure -foreground bogus
+} -returnCodes error -result {unknown color name "bogus"}
+
+test menu-2.22 {configuration options -postcommand {any old string}} -body {
+ .m1 configure -postcommand {any old string}
+ .m1 cget -postcommand
+} -result {any old string}
+test menu-2.23 {configuration options -relief groove} -body {
+ .m1 configure -relief groove
+ .m1 cget -relief
+} -result {groove}
+test menu-2.24 {configuration options -relief 1.5} -body {
+ .m1 configure -relief 1.5
+} -returnCodes error -result {bad relief "1.5": must be flat, groove, raised, ridge, solid, or sunken}
+
+test menu-2.25 {configuration options -selectcolor #110022} -body {
+ .m1 configure -selectcolor #110022
+ .m1 cget -selectcolor
+} -result {#110022}
+test menu-2.26 {configuration options -selectcolor bogus} -body {
+ .m1 configure -selectcolor bogus
+} -returnCodes error -result {unknown color name "bogus"}
+
+test menu-2.27 {configuration options -takefocus {any string}} -body {
+ .m1 configure -takefocus {any string}
+ .m1 cget -takefocus
+} -result {any string}
+test menu-2.28 {configuration options -tearoff 0} -body {
+ .m1 configure -tearoff 0
+ .m1 cget -tearoff
+} -result {0}
+test menu-2.29 {configuration options -tearoff 1} -body {
+ .m1 configure -tearoff 1
+ .m1 cget -tearoff
+} -result {1}
+test menu-2.30 {configuration options -tearoffcommand {any old string}} -body {
+ .m1 configure -tearoffcommand {any old string}
+ .m1 cget -tearoffcommand
+} -result {any old string}
+destroy .m1
+
+# We need to test all of the options with all of the different types of
+# menu entries. The following code sets up .m1 with 6 items. It then
+# runs through the 2.31 - 2.228 tests below
+# index 0 is tearoff, 1 command, 2 cascade, 3 separator, 4 checkbutton,
+# 5 radiobutton
+deleteWindows
+menu .m1 -tearoff 1
+.m1 add command -label "command"
+menu .m2 -tearoff 1
+.m2 add command -label "test"
+.m1 add cascade -label "cascade" -menu .m2
+.m1 add separator
+.m1 add checkbutton -label "checkbutton" -variable check -onvalue on -offvalue off
+.m1 add radiobutton -label "radiobutton" -variable radio
+
+if {[testConstraint hasEarthPhoto]} {
+ image create photo image1 -file $earthPhotoFile
+}
+
+test menu-2.31 {entry configuration options 0 -activebackground #012345 tearoff} -body {
+ .m1 entryconfigure 0 -activebackground #012345
+} -returnCodes error -result {unknown option "-activebackground"}
+
+test menu-2.32 {entry configuration options 1 -activebackground #012345 command} -body {
+ .m1 entryconfigure 1 -activebackground #012345
+ lindex [.m1 entryconfigure 1 -activebackground] 4
+} -result {#012345}
+
+test menu-2.33 {entry configuration options 2 -activebackground #012345 cascade} -body {
+ .m1 entryconfigure 2 -activebackground #012345
+ lindex [.m1 entryconfigure 2 -activebackground] 4
+} -result {#012345}
+
+test menu-2.34 {entry configuration options 3 -activebackground #012345 separator} -body {
+ .m1 entryconfigure 3 -activebackground #012345
+} -returnCodes error -result {unknown option "-activebackground"}
+
+test menu-2.35 {entry configuration options 4 -activebackground #012345 checkbutton} -body {
+ .m1 entryconfigure 4 -activebackground #012345
+ lindex [.m1 entryconfigure 4 -activebackground] 4
+} -result {#012345}
+
+test menu-2.36 {entry configuration options 5 -activebackground #012345 radiobutton} -body {
+ .m1 entryconfigure 5 -activebackground #012345
+ lindex [.m1 entryconfigure 5 -activebackground] 4
+} -result {#012345}
+
+test menu-2.37 {entry configuration options 0 -activebackground non-existent tearoff} -body {
+ .m1 entryconfigure 0 -activebackground non-existent
+} -returnCodes error -result {unknown option "-activebackground"}
+
+test menu-2.38 {entry configuration options 1 -activebackground non-existent command} -body {
+ .m1 entryconfigure 1 -activebackground non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+
+test menu-2.39 {entry configuration options 2 -activebackground non-existent cascade} -body {
+ .m1 entryconfigure 2 -activebackground non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+
+test menu-2.40 {entry configuration options 3 -activebackground non-existent separator} -body {
+ .m1 entryconfigure 3 -activebackground non-existent
+} -returnCodes error -result {unknown option "-activebackground"}
+
+test menu-2.41 {entry configuration options 4 -activebackground non-existent checkbutton} -body {
+ .m1 entryconfigure 4 -activebackground non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+
+test menu-2.42 {entry configuration options 5 -activebackground non-existent radiobutton} -body {
+ .m1 entryconfigure 5 -activebackground non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+
+test menu-2.43 {entry configuration options 0 -activeforeground #ff0000 tearoff} -body {
+ .m1 entryconfigure 0 -activeforeground #ff0000
+} -returnCodes error -result {unknown option "-activeforeground"}
+
+test menu-2.44 {entry configuration options 1 -activeforeground #ff0000 command} -body {
+ .m1 entryconfigure 1 -activeforeground #ff0000
+ lindex [.m1 entryconfigure 1 -activeforeground] 4
+} -result {#ff0000}
+
+test menu-2.45 {entry configuration options 2 -activeforeground #ff0000 cascade} -body {
+ .m1 entryconfigure 2 -activeforeground #ff0000
+ lindex [.m1 entryconfigure 2 -activeforeground] 4
+} -result {#ff0000}
+
+test menu-2.46 {entry configuration options 3 -activeforeground #ff0000 separator} -body {
+ .m1 entryconfigure 3 -activeforeground #ff0000
+} -returnCodes error -result {unknown option "-activeforeground"}
+
+test menu-2.47 {entry configuration options 4 -activeforeground #ff0000 checkbutton} -body {
+ .m1 entryconfigure 4 -activeforeground #ff0000
+ lindex [.m1 entryconfigure 4 -activeforeground] 4
+} -result {#ff0000}
+
+test menu-2.48 {entry configuration options 5 -activeforeground #ff0000 radiobutton} -body {
+ .m1 entryconfigure 5 -activeforeground #ff0000
+ lindex [.m1 entryconfigure 5 -activeforeground] 4
+} -result {#ff0000}
+
+test menu-2.49 {entry configuration options 0 -activeforeground non-existent tearoff} -body {
+ .m1 entryconfigure 0 -activeforeground non-existent
+} -returnCodes error -result {unknown option "-activeforeground"}
+
+test menu-2.50 {entry configuration options 1 -activeforeground non-existent command} -body {
+ .m1 entryconfigure 1 -activeforeground non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+
+test menu-2.51 {entry configuration options 2 -activeforeground non-existent cascade} -body {
+ .m1 entryconfigure 2 -activeforeground non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+
+test menu-2.52 {entry configuration options 3 -activeforeground non-existent separator} -body {
+ .m1 entryconfigure 3 -activeforeground non-existent
+} -returnCodes error -result {unknown option "-activeforeground"}
+
+test menu-2.53 {entry configuration options 4 -activeforeground non-existent checkbutton} -body {
+ .m1 entryconfigure 4 -activeforeground non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+
+test menu-2.54 {entry configuration options 5 -activeforeground non-existent radiobutton} -body {
+ .m1 entryconfigure 5 -activeforeground non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+
+test menu-2.55 {entry configuration options 0 -accelerator Ctrl+S tearoff} -body {
+ .m1 entryconfigure 0 -accelerator Ctrl+S
+} -returnCodes error -result {unknown option "-accelerator"}
+
+test menu-2.56 {entry configuration options 1 -accelerator Ctrl+S command} -body {
+ .m1 entryconfigure 1 -accelerator Ctrl+S
+ lindex [.m1 entryconfigure 1 -accelerator] 4
+} -result {Ctrl+S}
+
+test menu-2.57 {entry configuration options 2 -accelerator Ctrl+S cascade} -body {
+ .m1 entryconfigure 2 -accelerator Ctrl+S
+ lindex [.m1 entryconfigure 2 -accelerator] 4
+} -result {Ctrl+S}
+
+test menu-2.58 {entry configuration options 3 -accelerator Ctrl+S separator} -body {
+ .m1 entryconfigure 3 -accelerator Ctrl+S
+} -returnCodes error -result {unknown option "-accelerator"}
+
+test menu-2.59 {entry configuration options 4 -accelerator Ctrl+S checkbutton} -body {
+ .m1 entryconfigure 4 -accelerator Ctrl+S
+ lindex [.m1 entryconfigure 4 -accelerator] 4
+} -result {Ctrl+S}
+
+test menu-2.60 {entry configuration options 5 -accelerator Ctrl+S radiobutton} -body {
+ .m1 entryconfigure 5 -accelerator Ctrl+S
+ lindex [.m1 entryconfigure 5 -accelerator] 4
+} -result {Ctrl+S}
+
+test menu-2.61 {entry configuration options 0 -background #ff0000 tearoff} -body {
+ .m1 entryconfigure 0 -background #ff0000
+ lindex [.m1 entryconfigure 0 -background] 4
+} -result {#ff0000}
+
+test menu-2.62 {entry configuration options 1 -background #ff0000 command} -body {
+ .m1 entryconfigure 1 -background #ff0000
+ lindex [.m1 entryconfigure 1 -background] 4
+} -result {#ff0000}
+
+test menu-2.63 {entry configuration options 2 -background #ff0000 cascade} -body {
+ .m1 entryconfigure 2 -background #ff0000
+ lindex [.m1 entryconfigure 2 -background] 4
+} -result {#ff0000}
+
+test menu-2.64 {entry configuration options 3 -background #ff0000 separator} -body {
+ .m1 entryconfigure 3 -background #ff0000
+ lindex [.m1 entryconfigure 3 -background] 4
+} -result {#ff0000}
+
+test menu-2.65 {entry configuration options 4 -background #ff0000 checkbutton} -body {
+ .m1 entryconfigure 4 -background #ff0000
+ lindex [.m1 entryconfigure 4 -background] 4
+} -result {#ff0000}
+
+test menu-2.66 {entry configuration options 5 -background #ff0000 radiobutton} -body {
+ .m1 entryconfigure 5 -background #ff0000
+ lindex [.m1 entryconfigure 5 -background] 4
+} -result {#ff0000}
+
+test menu-2.67 {entry configuration options 0 -background non-existent tearoff} -body {
+ .m1 entryconfigure 0 -background non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+
+test menu-2.68 {entry configuration options 1 -background non-existent command} -body {
+ .m1 entryconfigure 1 -background non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+
+test menu-2.69 {entry configuration options 2 -background non-existent cascade} -body {
+ .m1 entryconfigure 2 -background non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+
+test menu-2.70 {entry configuration options 3 -background non-existent separator} -body {
+ .m1 entryconfigure 3 -background non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+
+test menu-2.71 {entry configuration options 4 -background non-existent checkbutton} -body {
+ .m1 entryconfigure 4 -background non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+
+test menu-2.72 {entry configuration options 5 -background non-existent radiobutton} -body {
+ .m1 entryconfigure 5 -background non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+
+test menu-2.73 {entry configuration options 0 -bitmap questhead tearoff} -body {
+ .m1 entryconfigure 0 -bitmap questhead
+} -returnCodes error -result {unknown option "-bitmap"}
+
+test menu-2.74 {entry configuration options 1 -bitmap questhead command} -body {
+ .m1 entryconfigure 1 -bitmap questhead
+ lindex [.m1 entryconfigure 1 -bitmap] 4
+} -result {questhead}
+
+test menu-2.75 {entry configuration options 2 -bitmap questhead cascade} -body {
+ .m1 entryconfigure 2 -bitmap questhead
+ lindex [.m1 entryconfigure 2 -bitmap] 4
+} -result {questhead}
+
+test menu-2.76 {entry configuration options 3 -bitmap questhead separator} -body {
+ .m1 entryconfigure 3 -bitmap questhead
+} -returnCodes error -result {unknown option "-bitmap"}
+
+test menu-2.77 {entry configuration options 4 -bitmap questhead checkbutton} -body {
+ .m1 entryconfigure 4 -bitmap questhead
+ lindex [.m1 entryconfigure 4 -bitmap] 4
+} -result {questhead}
+
+test menu-2.78 {entry configuration options 5 -bitmap questhead radiobutton} -body {
+ .m1 entryconfigure 5 -bitmap questhead
+ lindex [.m1 entryconfigure 5 -bitmap] 4
+} -result {questhead}
+
+test menu-2.79 {entry configuration options 0 -bitmap badValue tearoff} -body {
+ .m1 entryconfigure 0 -bitmap badValue
+} -returnCodes error -result {unknown option "-bitmap"}
+
+test menu-2.80 {entry configuration options 1 -bitmap badValue command} -body {
+ .m1 entryconfigure 1 -bitmap badValue
+} -returnCodes error -result {bitmap "badValue" not defined}
+
+test menu-2.81 {entry configuration options 2 -bitmap badValue cascade} -body {
+ .m1 entryconfigure 2 -bitmap badValue
+} -returnCodes error -result {bitmap "badValue" not defined}
+
+test menu-2.82 {entry configuration options 3 -bitmap badValue separator} -body {
+ .m1 entryconfigure 3 -bitmap badValue
+} -returnCodes error -result {unknown option "-bitmap"}
+
+test menu-2.83 {entry configuration options 4 -bitmap badValue checkbutton} -body {
+ .m1 entryconfigure 4 -bitmap badValue
+} -returnCodes error -result {bitmap "badValue" not defined}
+
+test menu-2.84 {entry configuration options 5 -bitmap badValue radiobutton} -body {
+ .m1 entryconfigure 5 -bitmap badValue
+} -returnCodes error -result {bitmap "badValue" not defined}
+
+test menu-2.85 {entry configuration options 0 -columnbreak 1 tearoff} -body {
+ .m1 entryconfigure 0 -columnbreak 1
+} -returnCodes error -result {unknown option "-columnbreak"}
+
+test menu-2.86 {entry configuration options 1 -columnbreak 1 command} -body {
+ .m1 entryconfigure 1 -columnbreak 1
+ lindex [.m1 entryconfigure 1 -columnbreak] 4
+} -result {1}
+
+test menu-2.87 {entry configuration options 2 -columnbreak 1 cascade} -body {
+ .m1 entryconfigure 2 -columnbreak 1
+ lindex [.m1 entryconfigure 2 -columnbreak] 4
+} -result {1}
+
+test menu-2.88 {entry configuration options 3 -columnbreak 1 separator} -body {
+ .m1 entryconfigure 3 -columnbreak 1
+} -returnCodes error -result {unknown option "-columnbreak"}
+
+test menu-2.89 {entry configuration options 4 -columnbreak 1 checkbutton} -body {
+ .m1 entryconfigure 4 -columnbreak 1
+ lindex [.m1 entryconfigure 4 -columnbreak] 4
+} -result {1}
+
+test menu-2.90 {entry configuration options 5 -columnbreak 1 radiobutton} -body {
+ .m1 entryconfigure 5 -columnbreak 1
+ lindex [.m1 entryconfigure 5 -columnbreak] 4
+} -result {1}
+
+test menu-2.91 {entry configuration options 0 -command beep tearoff} -body {
+ .m1 entryconfigure 0 -command beep
+} -returnCodes error -result {unknown option "-command"}
+
+test menu-2.92 {entry configuration options 1 -command beep command} -body {
+ .m1 entryconfigure 1 -command beep
+ lindex [.m1 entryconfigure 1 -command] 4
+} -result {beep}
+
+test menu-2.93 {entry configuration options 2 -command beep cascade} -body {
+ .m1 entryconfigure 2 -command beep
+ lindex [.m1 entryconfigure 2 -command] 4
+} -result {beep}
+
+test menu-2.94 {entry configuration options 3 -command beep separator} -body {
+ .m1 entryconfigure 3 -command beep
+} -returnCodes error -result {unknown option "-command"}
+
+test menu-2.95 {entry configuration options 4 -command beep checkbutton} -body {
+ .m1 entryconfigure 4 -command beep
+ lindex [.m1 entryconfigure 4 -command] 4
+} -result {beep}
+
+test menu-2.96 {entry configuration options 5 -command beep radiobutton} -body {
+ .m1 entryconfigure 5 -command beep
+ lindex [.m1 entryconfigure 5 -command] 4
+} -result {beep}
+
+test menu-2.97 {entry configuration options 0 -font -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-* tearoff} -body {
+ .m1 entryconfigure 0 -font -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*
+} -returnCodes error -result {unknown option "-font"}
+
+test menu-2.98 {entry configuration options 1 -font -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-* command} -body {
+ .m1 entryconfigure 1 -font -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*
+ lindex [.m1 entryconfigure 1 -font] 4
+} -result {-Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*}
+
+test menu-2.99 {entry configuration options 2 -font -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-* cascade} -body {
+ .m1 entryconfigure 2 -font -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*
+ lindex [.m1 entryconfigure 2 -font] 4
+} -result {-Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*}
+
+test menu-2.100 {entry configuration options 3 -font -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-* separator} -body {
+ .m1 entryconfigure 3 -font -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*
+} -returnCodes error -result {unknown option "-font"}
+
+test menu-2.101 {entry configuration options 4 -font -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-* checkbutton} -body {
+ .m1 entryconfigure 4 -font -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*
+ lindex [.m1 entryconfigure 4 -font] 4
+} -result {-Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*}
+
+test menu-2.102 {entry configuration options 5 -font -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-* radiobutton} -body {
+ .m1 entryconfigure 5 -font -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*
+ lindex [.m1 entryconfigure 5 -font] 4
+} -result {-Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*}
+
+test menu-2.103 {entry configuration options 0 -font {kill rock stars} tearoff} -body {
+ .m1 entryconfigure 0 -font {kill rock stars}
+} -returnCodes error -result {unknown option "-font"}
+
+test menu-2.104 {entry configuration options 1 -font {kill rock stars} command} -body {
+ .m1 entryconfigure 1 -font {kill rock stars}
+} -returnCodes error -result {expected integer but got "rock"}
+
+test menu-2.105 {entry configuration options 2 -font {kill rock stars} cascade} -body {
+ .m1 entryconfigure 2 -font {kill rock stars}
+} -returnCodes error -result {expected integer but got "rock"}
+
+test menu-2.106 {entry configuration options 3 -font {kill rock stars} separator} -body {
+ .m1 entryconfigure 3 -font {kill rock stars}
+} -returnCodes error -result {unknown option "-font"}
+
+test menu-2.107 {entry configuration options 4 -font {kill rock stars} checkbutton} -body {
+ .m1 entryconfigure 4 -font {kill rock stars}
+} -returnCodes error -result {expected integer but got "rock"}
+
+test menu-2.108 {entry configuration options 5 -font {kill rock stars} radiobutton} -body {
+ .m1 entryconfigure 5 -font {kill rock stars}
+} -returnCodes error -result {expected integer but got "rock"}
+
+test menu-2.109 {entry configuration options 0 -foreground #110022 tearoff} -body {
+ .m1 entryconfigure 0 -foreground #110022
+} -returnCodes error -result {unknown option "-foreground"}
+
+test menu-2.110 {entry configuration options 1 -foreground #110022 command} -body {
+ .m1 entryconfigure 1 -foreground #110022
+ lindex [.m1 entryconfigure 1 -foreground] 4
+} -result {#110022}
+
+test menu-2.111 {entry configuration options 2 -foreground #110022 cascade} -body {
+ .m1 entryconfigure 2 -foreground #110022
+ lindex [.m1 entryconfigure 2 -foreground] 4
+} -result {#110022}
+
+test menu-2.112 {entry configuration options 3 -foreground #110022 separator} -body {
+ .m1 entryconfigure 3 -foreground #110022
+} -returnCodes error -result {unknown option "-foreground"}
+
+test menu-2.113 {entry configuration options 4 -foreground #110022 checkbutton} -body {
+ .m1 entryconfigure 4 -foreground #110022
+ lindex [.m1 entryconfigure 4 -foreground] 4
+} -result {#110022}
+
+test menu-2.114 {entry configuration options 5 -foreground #110022 radiobutton} -body {
+ .m1 entryconfigure 5 -foreground #110022
+ lindex [.m1 entryconfigure 5 -foreground] 4
+} -result {#110022}
+
+test menu-2.115 {entry configuration options 0 -foreground non-existent tearoff} -body {
+ .m1 entryconfigure 0 -foreground non-existent
+} -returnCodes error -result {unknown option "-foreground"}
+
+test menu-2.116 {entry configuration options 1 -foreground non-existent command} -body {
+ .m1 entryconfigure 1 -foreground non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+
+test menu-2.117 {entry configuration options 2 -foreground non-existent cascade} -body {
+ .m1 entryconfigure 2 -foreground non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+
+test menu-2.118 {entry configuration options 3 -foreground non-existent separator} -body {
+ .m1 entryconfigure 3 -foreground non-existent
+} -returnCodes error -result {unknown option "-foreground"}
+
+test menu-2.119 {entry configuration options 4 -foreground non-existent checkbutton} -body {
+ .m1 entryconfigure 4 -foreground non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+
+test menu-2.120 {entry configuration options 5 -foreground non-existent radiobutton} -body {
+ .m1 entryconfigure 5 -foreground non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+
+test menu-2.121 {entry configuration options 0 -image image1 tearoff} -constraints {
+ hasEarthPhoto
+} -body {
+ .m1 entryconfigure 0 -image image1
+} -returnCodes error -result {unknown option "-image"}
+
+test menu-2.122 {entry configuration options 1 -image image1 command} -constraints {
+ hasEarthPhoto
+} -setup {
+ .m1 entryconfigure 1 -image {}
+} -body {
+ .m1 entryconfigure 1 -image image1
+ lindex [.m1 entryconfigure 1 -image] 4
+} -cleanup {
+ .m1 entryconfigure 1 -image {}
+} -result {image1}
+
+test menu-2.123 {entry configuration options 2 -image image1 cascade} -constraints {
+ hasEarthPhoto
+} -setup {
+ .m1 entryconfigure 2 -image {}
+} -body {
+ .m1 entryconfigure 2 -image image1
+ lindex [.m1 entryconfigure 2 -image] 4
+} -cleanup {
+ .m1 entryconfigure 2 -image {}
+} -result {image1}
+
+test menu-2.124 {entry configuration options 3 -image image1 separator} -constraints {
+ hasEarthPhoto
+} -body {
+ .m1 entryconfigure 3 -image image1
+} -returnCodes error -result {unknown option "-image"}
+
+test menu-2.125 {entry configuration options 4 -image image1 checkbutton} -constraints {
+ hasEarthPhoto
+} -setup {
+ .m1 entryconfigure 4 -image {}
+} -body {
+ .m1 entryconfigure 4 -image image1
+ lindex [.m1 entryconfigure 4 -image] 4
+} -cleanup {
+ .m1 entryconfigure 4 -image {}
+} -result {image1}
+
+test menu-2.126 {entry configuration options 5 -image image1 radiobutton} -constraints {
+ hasEarthPhoto
+} -setup {
+ .m1 entryconfigure 5 -image {}
+} -body {
+ .m1 entryconfigure 5 -image image1
+ lindex [.m1 entryconfigure 5 -image] 4
+} -cleanup {
+ .m1 entryconfigure 5 -image {}
+} -result {image1}
+
+test menu-2.127 {entry configuration options 0 -image bogus tearoff} -body {
+ .m1 entryconfigure 0 -image bogus
+} -returnCodes error -result {unknown option "-image"}
+
+test menu-2.128 {entry configuration options 1 -image bogus command} -body {
+ .m1 entryconfigure 1 -image bogus
+} -returnCodes error -result {image "bogus" doesn't exist}
+
+test menu-2.129 {entry configuration options 2 -image bogus cascade} -body {
+ .m1 entryconfigure 2 -image bogus
+} -returnCodes error -result {image "bogus" doesn't exist}
+
+test menu-2.130 {entry configuration options 3 -image bogus separator} -body {
+ .m1 entryconfigure 3 -image bogus
+} -returnCodes error -result {unknown option "-image"}
+
+test menu-2.131 {entry configuration options 4 -image bogus checkbutton} -body {
+ .m1 entryconfigure 4 -image bogus
+} -returnCodes error -result {image "bogus" doesn't exist}
+
+test menu-2.132 {entry configuration options 5 -image bogus radiobutton} -body {
+ .m1 entryconfigure 5 -image bogus
+} -returnCodes error -result {image "bogus" doesn't exist}
+
+test menu-2.133 {entry configuration options 0 -image {} tearoff} -body {
+ .m1 entryconfigure 0 -image
+} -returnCodes error -result {unknown option "-image"}
+
+test menu-2.134 {entry configuration options 1 -image {} command} -setup {
+ .m1 entryconfigure 1 -image {}
+} -body {
+ .m1 entryconfigure 1 -image
+ lindex [.m1 entryconfigure 1 -image] 4
+} -result {}
+
+test menu-2.135 {entry configuration options 2 -image {} cascade} -setup {
+ .m1 entryconfigure 2 -image {}
+} -body {
+ .m1 entryconfigure 2 -image
+ lindex [.m1 entryconfigure 2 -image] 4
+} -result {}
+
+test menu-2.136 {entry configuration options 3 -image {} separator} -body {
+ .m1 entryconfigure 3 -image
+} -returnCodes error -result {unknown option "-image"}
+
+test menu-2.137 {entry configuration options 4 -image {} checkbutton} -body {
+ .m1 entryconfigure 4 -image
+ lindex [.m1 entryconfigure 4 -image] 4
+} -result {}
+
+test menu-2.138 {entry configuration options 5 -image {} radiobutton} -body {
+ .m1 entryconfigure 5 -image
+ lindex [.m1 entryconfigure 5 -image] 4
+} -result {}
+
+test menu-2.139 {entry configuration options 0 -indicatoron 1 tearoff} -body {
+ .m1 entryconfigure 0 -indicatoron 1
+} -returnCodes error -result {unknown option "-indicatoron"}
+
+test menu-2.140 {entry configuration options 1 -indicatoron 1 command} -body {
+ .m1 entryconfigure 1 -indicatoron 1
+} -returnCodes error -result {unknown option "-indicatoron"}
+
+test menu-2.141 {entry configuration options 2 -indicatoron 1 cascade} -body {
+ .m1 entryconfigure 2 -indicatoron 1
+} -returnCodes error -result {unknown option "-indicatoron"}
+
+test menu-2.142 {entry configuration options 3 -indicatoron 1 separator} -body {
+ .m1 entryconfigure 3 -indicatoron 1
+} -returnCodes error -result {unknown option "-indicatoron"}
+
+test menu-2.143 {entry configuration options 4 -indicatoron 1 checkbutton} -body {
+ .m1 entryconfigure 4 -indicatoron 1
+ lindex [.m1 entryconfigure 4 -indicatoron] 4
+} -result {1}
+
+test menu-2.144 {entry configuration options 5 -indicatoron 1 radiobutton} -body {
+ .m1 entryconfigure 5 -indicatoron 1
+ lindex [.m1 entryconfigure 5 -indicatoron] 4
+} -result {1}
+
+test menu-2.145 {entry configuration options 0 -label test tearoff} -body {
+ .m1 entryconfigure 0 -label test
+} -returnCodes error -result {unknown option "-label"}
+
+test menu-2.146 {entry configuration options 1 -label test command} -body {
+ .m1 entryconfigure 1 -label test
+ lindex [.m1 entryconfigure 1 -label] 4
+} -result {test}
+
+test menu-2.147 {entry configuration options 2 -label test cascade} -body {
+ .m1 entryconfigure 2 -label test
+ lindex [.m1 entryconfigure 2 -label] 4
+} -result {test}
+
+test menu-2.148 {entry configuration options 3 -label test separator} -body {
+ .m1 entryconfigure 3 -label test
+} -returnCodes error -result {unknown option "-label"}
+
+test menu-2.149 {entry configuration options 4 -label test checkbutton} -body {
+ .m1 entryconfigure 4 -label test
+ lindex [.m1 entryconfigure 4 -label] 4
+} -result {test}
+
+test menu-2.150 {entry configuration options 5 -label test radiobutton} -body {
+ .m1 entryconfigure 5 -label test
+ lindex [.m1 entryconfigure 5 -label] 4
+} -result {test}
+
+test menu-2.151 {entry configuration options 0 -menu .m2 tearoff} -body {
+ .m1 entryconfigure 0 -menu .m2
+} -returnCodes error -result {unknown option "-menu"}
+
+test menu-2.152 {entry configuration options 1 -menu .m2 command} -body {
+ .m1 entryconfigure 1 -menu .m2
+} -returnCodes error -result {unknown option "-menu"}
+
+test menu-2.153 {entry configuration options 2 -menu .m2 cascade} -body {
+ .m1 entryconfigure 2 -menu .m2
+ lindex [.m1 entryconfigure 2 -menu] 4
+} -result {.m2}
+
+test menu-2.154 {entry configuration options 3 -menu .m2 separator} -body {
+ .m1 entryconfigure 3 -menu .m2
+} -returnCodes error -result {unknown option "-menu"}
+
+test menu-2.155 {entry configuration options 4 -menu .m2 checkbutton} -body {
+ .m1 entryconfigure 4 -menu .m2
+} -returnCodes error -result {unknown option "-menu"}
+
+test menu-2.156 {entry configuration options 5 -menu .m2 radiobutton} -body {
+ .m1 entryconfigure 5 -menu .m2
+} -returnCodes error -result {unknown option "-menu"}
+
+test menu-2.157 {entry configuration options 0 -offvalue off tearoff} -body {
+ .m1 entryconfigure 0 -offvalue off
+} -returnCodes error -result {unknown option "-offvalue"}
+
+test menu-2.158 {entry configuration options 1 -offvalue off command} -body {
+ .m1 entryconfigure 1 -offvalue off
+} -returnCodes error -result {unknown option "-offvalue"}
+
+test menu-2.159 {entry configuration options 2 -offvalue off cascade} -body {
+ .m1 entryconfigure 2 -offvalue off
+} -returnCodes error -result {unknown option "-offvalue"}
+
+test menu-2.160 {entry configuration options 3 -offvalue off separator} -body {
+ .m1 entryconfigure 3 -offvalue off
+} -returnCodes error -result {unknown option "-offvalue"}
+
+test menu-2.161 {entry configuration options 4 -offvalue off checkbutton} -body {
+ .m1 entryconfigure 4 -offvalue off
+ lindex [.m1 entryconfigure 4 -offvalue] 4
+} -result {off}
+
+test menu-2.162 {entry configuration options 5 -offvalue off radiobutton} -body {
+ .m1 entryconfigure 5 -offvalue off
+} -returnCodes error -result {unknown option "-offvalue"}
+
+test menu-2.163 {entry configuration options 0 -onvalue on tearoff} -body {
+ .m1 entryconfigure 0 -onvalue on
+} -returnCodes error -result {unknown option "-onvalue"}
+
+test menu-2.164 {entry configuration options 1 -onvalue on command} -body {
+ .m1 entryconfigure 1 -onvalue on
+} -returnCodes error -result {unknown option "-onvalue"}
+
+test menu-2.165 {entry configuration options 2 -onvalue on cascade} -body {
+ .m1 entryconfigure 2 -onvalue on
+} -returnCodes error -result {unknown option "-onvalue"}
+
+test menu-2.166 {entry configuration options 3 -onvalue on separator} -body {
+ .m1 entryconfigure 3 -onvalue on
+} -returnCodes error -result {unknown option "-onvalue"}
+
+test menu-2.167 {entry configuration options 4 -onvalue on checkbutton} -body {
+ .m1 entryconfigure 4 -onvalue on
+ lindex [.m1 entryconfigure 4 -onvalue] 4
+} -result {on}
+
+test menu-2.168 {entry configuration options 5 -onvalue on radiobutton} -body {
+ .m1 entryconfigure 5 -onvalue on
+} -returnCodes error -result {unknown option "-onvalue"}
+
+test menu-2.169 {entry configuration options 0 -selectcolor #110022 tearoff} -body {
+ .m1 entryconfigure 0 -selectcolor #110022
+} -returnCodes error -result {unknown option "-selectcolor"}
+
+test menu-2.170 {entry configuration options 1 -selectcolor #110022 command} -body {
+ .m1 entryconfigure 1 -selectcolor #110022
+} -returnCodes error -result {unknown option "-selectcolor"}
+
+test menu-2.171 {entry configuration options 2 -selectcolor #110022 cascade} -body {
+ .m1 entryconfigure 2 -selectcolor #110022
+} -returnCodes error -result {unknown option "-selectcolor"}
+
+test menu-2.172 {entry configuration options 3 -selectcolor #110022 separator} -body {
+ .m1 entryconfigure 3 -selectcolor #110022
+} -returnCodes error -result {unknown option "-selectcolor"}
+
+test menu-2.173 {entry configuration options 4 -selectcolor #110022 checkbutton} -body {
+ .m1 entryconfigure 4 -selectcolor #110022
+ lindex [.m1 entryconfigure 4 -selectcolor] 4
+} -result {#110022}
+
+test menu-2.174 {entry configuration options 5 -selectcolor #110022 radiobutton} -body {
+ .m1 entryconfigure 5 -selectcolor #110022
+ lindex [.m1 entryconfigure 5 -selectcolor] 4
+} -result {#110022}
+
+test menu-2.175 {entry configuration options 0 -selectcolor non-existent tearoff} -body {
+ .m1 entryconfigure 0 -selectcolor non-existent
+} -returnCodes error -result {unknown option "-selectcolor"}
+
+test menu-2.176 {entry configuration options 1 -selectcolor non-existent command} -body {
+ .m1 entryconfigure 1 -selectcolor non-existent
+} -returnCodes error -result {unknown option "-selectcolor"}
+
+test menu-2.177 {entry configuration options 2 -selectcolor non-existent cascade} -body {
+ .m1 entryconfigure 2 -selectcolor non-existent
+} -returnCodes error -result {unknown option "-selectcolor"}
+
+test menu-2.178 {entry configuration options 3 -selectcolor non-existent separator} -body {
+ .m1 entryconfigure 3 -selectcolor non-existent
+} -returnCodes error -result {unknown option "-selectcolor"}
+
+test menu-2.179 {entry configuration options 4 -selectcolor non-existent checkbutton} -body {
+ .m1 entryconfigure 4 -selectcolor non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+
+test menu-2.180 {entry configuration options 5 -selectcolor non-existent radiobutton} -body {
+ .m1 entryconfigure 5 -selectcolor non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+
+test menu-2.181 {entry configuration options 0 -selectimage image1 tearoff} -constraints {
+ hasEarthPhoto
+} -body {
+ .m1 entryconfigure 0 -selectimage image1
+} -returnCodes error -result {unknown option "-selectimage"}
+
+test menu-2.182 {entry configuration options 1 -selectimage image1 command} -constraints {
+ hasEarthPhoto
+} -body {
+ .m1 entryconfigure 1 -selectimage image1
+} -returnCodes error -result {unknown option "-selectimage"}
+
+test menu-2.183 {entry configuration options 2 -selectimage image1 cascade} -constraints {
+ hasEarthPhoto
+} -body {
+ .m1 entryconfigure 2 -selectimage image1
+} -returnCodes error -result {unknown option "-selectimage"}
+
+test menu-2.184 {entry configuration options 3 -selectimage image1 separator} -constraints {
+ hasEarthPhoto
+} -body {
+ .m1 entryconfigure 3 -selectimage image1
+} -returnCodes error -result {unknown option "-selectimage"}
+
+test menu-2.185 {entry configuration options 4 -selectimage image1 checkbutton} -constraints {
+ hasEarthPhoto
+} -setup {
+ .m1 entryconfigure 4 -selectimage {}
+} -body {
+ .m1 entryconfigure 4 -selectimage image1
+ lindex [.m1 entryconfigure 4 -selectimage] 4
+} -cleanup {
+ .m1 entryconfigure 4 -selectimage {}
+} -result {image1}
+
+test menu-2.186 {entry configuration options 5 -selectimage image1 radiobutton} -constraints {
+ hasEarthPhoto
+} -setup {
+ .m1 entryconfigure 5 -selectimage {}
+} -body {
+ .m1 entryconfigure 5 -selectimage image1
+ lindex [.m1 entryconfigure 5 -selectimage] 4
+} -cleanup {
+ .m1 entryconfigure 5 -selectimage {}
+} -result {image1}
+
+test menu-2.187 {entry configuration options 0 -selectimage bogus tearoff} -body {
+ .m1 entryconfigure 0 -selectimage bogus
+} -returnCodes error -result {unknown option "-selectimage"}
+
+test menu-2.188 {entry configuration options 1 -selectimage bogus command} -body {
+ .m1 entryconfigure 1 -selectimage bogus
+} -returnCodes error -result {unknown option "-selectimage"}
+
+test menu-2.189 {entry configuration options 2 -selectimage bogus cascade} -body {
+ .m1 entryconfigure 2 -selectimage bogus
+} -returnCodes error -result {unknown option "-selectimage"}
+
+test menu-2.190 {entry configuration options 3 -selectimage bogus separator} -body {
+ .m1 entryconfigure 3 -selectimage bogus
+} -returnCodes error -result {unknown option "-selectimage"}
+
+test menu-2.191 {entry configuration options 4 -selectimage bogus checkbutton} -body {
+ .m1 entryconfigure 4 -selectimage bogus
+} -returnCodes error -result {image "bogus" doesn't exist}
+
+test menu-2.192 {entry configuration options 5 -selectimage bogus radiobutton} -body {
+ .m1 entryconfigure 5 -selectimage bogus
+} -returnCodes error -result {image "bogus" doesn't exist}
+
+test menu-2.193 {entry configuration options 0 -selectimage {} tearoff} -body {
+ .m1 entryconfigure 0 -selectimage
+} -returnCodes error -result {unknown option "-selectimage"}
+
+test menu-2.194 {entry configuration options 1 -selectimage {} command} -body {
+ .m1 entryconfigure 1 -selectimage
+} -returnCodes error -result {unknown option "-selectimage"}
+
+test menu-2.195 {entry configuration options 2 -selectimage {} cascade} -body {
+ .m1 entryconfigure 2 -selectimage
+} -returnCodes error -result {unknown option "-selectimage"}
+
+test menu-2.196 {entry configuration options 3 -selectimage {} separator} -body {
+ .m1 entryconfigure 3 -selectimage
+} -returnCodes error -result {unknown option "-selectimage"}
+
+test menu-2.197 {entry configuration options 4 -selectimage {} checkbutton} -body {
+ .m1 entryconfigure 4 -selectimage
+ lindex [.m1 entryconfigure 4 -selectimage] 4
+} -result {}
+
+test menu-2.198 {entry configuration options 5 -selectimage {} radiobutton} -body {
+ .m1 entryconfigure 5 -selectimage
+ lindex [.m1 entryconfigure 5 -selectimage] 4
+} -result {}
+
+test menu-2.199 {entry configuration options 0 -state normal tearoff} -body {
+ .m1 entryconfigure 0 -state normal
+ lindex [.m1 entryconfigure 0 -state] 4
+} -result {normal}
+
+test menu-2.200 {entry configuration options 1 -state normal command} -body {
+ .m1 entryconfigure 1 -state normal
+ lindex [.m1 entryconfigure 1 -state] 4
+} -result {normal}
+
+test menu-2.201 {entry configuration options 2 -state normal cascade} -body {
+ .m1 entryconfigure 2 -state normal
+ lindex [.m1 entryconfigure 2 -state] 4
+} -result {normal}
+
+test menu-2.202 {entry configuration options 3 -state normal separator} -body {
+ .m1 entryconfigure 3 -state normal
+} -returnCodes error -result {unknown option "-state"}
+
+test menu-2.203 {entry configuration options 4 -state normal checkbutton} -body {
+ .m1 entryconfigure 4 -state normal
+ lindex [.m1 entryconfigure 4 -state] 4
+} -result {normal}
+
+test menu-2.204 {entry configuration options 5 -state normal radiobutton} -body {
+ .m1 entryconfigure 5 -state normal
+ lindex [.m1 entryconfigure 5 -state] 4
+} -result {normal}
+
+test menu-2.205 {entry configuration options 0 -value {any string} tearoff} -body {
+ .m1 entryconfigure 0 -value {any string}
+} -returnCodes error -result {unknown option "-value"}
+
+test menu-2.206 {entry configuration options 1 -value {any string} command} -body {
+ .m1 entryconfigure 1 -value {any string}
+} -returnCodes error -result {unknown option "-value"}
+
+test menu-2.207 {entry configuration options 2 -value {any string} cascade} -body {
+ .m1 entryconfigure 2 -value {any string}
+} -returnCodes error -result {unknown option "-value"}
+
+test menu-2.208 {entry configuration options 3 -value {any string} separator} -body {
+ .m1 entryconfigure 3 -value {any string}
+} -returnCodes error -result {unknown option "-value"}
+
+test menu-2.209 {entry configuration options 4 -value {any string} checkbutton} -body {
+ .m1 entryconfigure 4 -value {any string}
+} -returnCodes error -result {unknown option "-value"}
+
+test menu-2.210 {entry configuration options 5 -value {any string} radiobutton} -body {
+ .m1 entryconfigure 5 -value {any string}
+ lindex [.m1 entryconfigure 5 -value] 4
+} -result {any string}
+
+test menu-2.211 {entry configuration options 0 -variable {any string} tearoff} -body {
+ .m1 entryconfigure 0 -variable {any string}
+} -returnCodes error -result {unknown option "-variable"}
+
+test menu-2.212 {entry configuration options 1 -variable {any string} command} -body {
+ .m1 entryconfigure 1 -variable {any string}
+} -returnCodes error -result {unknown option "-variable"}
+
+test menu-2.213 {entry configuration options 2 -variable {any string} cascade} -body {
+ .m1 entryconfigure 2 -variable {any string}
+} -returnCodes error -result {unknown option "-variable"}
+
+test menu-2.214 {entry configuration options 3 -variable {any string} separator} -body {
+ .m1 entryconfigure 3 -variable {any string}
+} -returnCodes error -result {unknown option "-variable"}
+
+test menu-2.215 {entry configuration options 4 -variable {any string} checkbutton} -body {
+ .m1 entryconfigure 4 -variable {any string}
+ lindex [.m1 entryconfigure 4 -variable] 4
+} -result {any string}
+
+test menu-2.216 {entry configuration options 5 -variable {any string} radiobutton} -body {
+ .m1 entryconfigure 5 -variable {any string}
+ lindex [.m1 entryconfigure 5 -variable] 4
+} -result {any string}
+
+test menu-2.217 {entry configuration options 0 -underline 0 tearoff} -body {
+ .m1 entryconfigure 0 -underline 0
+} -returnCodes error -result {unknown option "-underline"}
+
+test menu-2.218 {entry configuration options 1 -underline 0 command} -body {
+ .m1 entryconfigure 1 -underline 0
+ lindex [.m1 entryconfigure 1 -underline] 4
+} -result {0}
+
+test menu-2.219 {entry configuration options 2 -underline 0 cascade} -body {
+ .m1 entryconfigure 2 -underline 0
+ lindex [.m1 entryconfigure 2 -underline] 4
+} -result {0}
+
+test menu-2.220 {entry configuration options 3 -underline 0 separator} -body {
+ .m1 entryconfigure 3 -underline 0
+} -returnCodes error -result {unknown option "-underline"}
+
+test menu-2.221 {entry configuration options 4 -underline 0 checkbutton} -body {
+ .m1 entryconfigure 4 -underline 0
+ lindex [.m1 entryconfigure 4 -underline] 4
+} -result {0}
+
+test menu-2.222 {entry configuration options 5 -underline 0 radiobutton} -body {
+ .m1 entryconfigure 5 -underline 0
+ lindex [.m1 entryconfigure 5 -underline] 4
+} -result {0}
+
+test menu-2.223 {entry configuration options 0 -underline 3p tearoff} -body {
+ .m1 entryconfigure 0 -underline 3p
+} -returnCodes error -result {unknown option "-underline"}
+
+test menu-2.224 {entry configuration options 1 -underline 3p command} -body {
+ .m1 entryconfigure 1 -underline 3p
+} -returnCodes error -result {expected integer but got "3p"}
+
+test menu-2.225 {entry configuration options 2 -underline 3p cascade} -body {
+ .m1 entryconfigure 2 -underline 3p
+} -returnCodes error -result {expected integer but got "3p"}
+
+test menu-2.226 {entry configuration options 3 -underline 3p separator} -body {
+ .m1 entryconfigure 3 -underline 3p
+} -returnCodes error -result {unknown option "-underline"}
+
+test menu-2.227 {entry configuration options 4 -underline 3p checkbutton} -body {
+ .m1 entryconfigure 4 -underline 3p
+} -returnCodes error -result {expected integer but got "3p"}
+
+test menu-2.228 {entry configuration options 5 -underline 3p radiobutton} -body {
+ .m1 entryconfigure 5 -underline 3p
+} -returnCodes error -result {expected integer but got "3p"}
+
+deleteWindows
+if {[testConstraint hasEarthPhoto]} {
+ image delete image1
+}
+
+
+
+test menu-3.1 {MenuWidgetCmd procedure} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1
+} -cleanup {
+ destroy .m1
+} -returnCodes error -result {wrong # args: should be ".m1 option ?arg ...?"}
+test menu-3.2 {MenuWidgetCmd, Tcl_Preserve and Tcl_Release} -constraints {
+ nonUnixUserInteraction
+} -setup {
+ destroy .m1
+} -body {
+ menu .m1 -postcommand "destroy .m1"
+ .m1 add command -label "menu-3.2: Hit Escape"
+ .m1 post 40 40
+} -cleanup {
+ destroy .m1
+} -returnCodes ok -result {}
+test menu-3.3 {MenuWidgetCmd procedure, "activate" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+ .m1 activate
+} -cleanup {
+ destroy .m1
+} -returnCodes error -result {wrong # args: should be ".m1 activate index"}
+test menu-3.4 {MenuWidgetCmd procedure, "activate" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 activate "foo"
+} -returnCodes error -result {bad menu entry index "foo"}
+test menu-3.5 {MenuWidgetCmd procedure, "activate" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+ .m1 add separator
+ .m1 activate 2
+} -cleanup {
+ destroy .m1
+} -result {}
+test menu-3.6 {MenuWidgetCmd procedure, "activate" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+ .m1 entryconfigure 1 -state disabled
+ .m1 activate 1
+} -cleanup {
+ destroy .m1
+} -result {}
+test menu-3.7 {MenuWidgetCmd procedure, "activate" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+ .m1 activate 1
+} -cleanup {
+ destroy .m1
+} -result {}
+test menu-3.8 {MenuWidgetCmd procedure, "add" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add
+} -cleanup {
+ destroy .m1
+} -returnCodes error -result {wrong # args: should be ".m1 add type ?-option value ...?"}
+test menu-3.9 {MenuWidgetCmd procedure, "add" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add foo
+} -cleanup {
+ destroy .m1
+} -returnCodes error -result {bad menu entry type "foo": must be cascade, checkbutton, command, radiobutton, or separator}
+test menu-3.10 {MenuWidgetCmd procedure, "add" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add separator
+} -cleanup {
+ destroy .m1
+} -result {}
+test menu-3.11 {MenuWidgetCmd procedure, "cget" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 cget
+} -returnCodes error -result {wrong # args: should be ".m1 cget option"}
+test menu-3.12 {MenuWidgetCmd procedure, "cget" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 cget -gorp
+} -returnCodes error -result {unknown option "-gorp"}
+test menu-3.13 {MenuWidgetCmd procedure, "cget" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 configure -postcommand "Some string"
+ .m1 cget -postcommand
+} -cleanup {
+ destroy .m1
+} -result {Some string}
+test menu-3.14 {MenuWidgetCmd procedure, "clone" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 clone
+} -returnCodes error -result {wrong # args: should be ".m1 clone newMenuName ?menuType?"}
+test menu-3.15 {MenuWidgetCmd procedure, "clone" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 clone a b c d
+} -returnCodes error -result {wrong # args: should be ".m1 clone newMenuName ?menuType?"}
+test menu-3.16 {MenuWidgetCmd procedure, "clone" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 clone .m1.clone1
+} -cleanup {
+ destroy .m1
+} -result {}
+test menu-3.17 {MenuWidgetCmd procedure, "clone" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 clone .m1.clone1 tearoff
+} -cleanup {
+ destroy .m1
+} -result {}
+test menu-3.18 {MenuWidgetCmd procedure, "configure" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ llength [.m1 configure]
+} -cleanup {
+ destroy .m1
+} -result {20}
+test menu-3.19 {MenuWidgetCmd procedure, "configure" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 configure -gorp
+} -returnCodes error -result {unknown option "-gorp"}
+test menu-3.20 {MenuWidgetCmd procedure, "configure" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 configure -postcommand "A random String"
+} -cleanup {
+ destroy .m1
+} -result {}
+test menu-3.21 {MenuWidgetCmd procedure, "configure" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 configure -postcommand "Another string"
+ lindex [.m1 configure -postcommand] 4
+} -cleanup {
+ destroy .m1
+} -result {Another string}
+test menu-3.22 {MenuWidgetCmd procedure, "delete" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 delete
+} -returnCodes error -result {wrong # args: should be ".m1 delete first ?last?"}
+test menu-3.23 {MenuWidgetCmd procedure, "delete" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 delete foo
+} -returnCodes error -result {bad menu entry index "foo"}
+test menu-3.24 {MenuWidgetCmd procedure, "delete" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1 -tearoff 1
+ .m1 delete 0 "foo"
+} -returnCodes error -result {bad menu entry index "foo"}
+test menu-3.25 {MenuWidgetCmd procedure, "delete" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 delete 0
+} -cleanup {
+ destroy .m1
+} -result {}
+test menu-3.26 {MenuWidgetCmd procedure, "delete" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add command -label "foo"
+ .m1 delete 1 0
+} -cleanup {
+ destroy .m1
+} -result {}
+test menu-3.27 {MenuWidgetCmd procedure, "delete" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add command -label "1"
+ .m1 add command -label "2"
+ .m1 add command -label "3"
+ .m1 delete 1 3
+} -cleanup {
+ destroy .m1
+} -result {}
+test menu-3.28 {MenuWidgetCmd procedure, "delete" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add command -label "1"
+ .m1 add command -label "2"
+ .m1 add command -label "3"
+ .m1 activate 2
+ .m1 delete 1 3
+} -cleanup {
+ destroy .m1
+} -result {}
+test menu-3.29 {MenuWidgetCmd procedure, "delete" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add command -label "1"
+ .m1 add command -label "2"
+ .m1 add command -label "3"
+ .m1 activate 3
+ .m1 delete 1
+} -cleanup {
+ destroy .m1
+} -result {}
+test menu-3.29+1 {MenuWidgetCmd, "delete", Bug 220950} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add command -label "bogus"
+ .m1 add command -label "ok"
+ .m1 delete 10 20
+ .m1 entrycget last -label
+} -cleanup {
+ destroy .m1
+} -result ok
+test menu-3.30 {MenuWidgetCmd procedure, "entrycget" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 entrycget
+} -returnCodes error -result {wrong # args: should be ".m1 entrycget index option"}
+test menu-3.31 {MenuWidgetCmd procedure, "entrycget" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 entrycget index option foo
+} -returnCodes error -result {wrong # args: should be ".m1 entrycget index option"}
+test menu-3.32 {MenuWidgetCmd procedure, "entrycget" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 entrycget foo -label
+} -returnCodes error -result {bad menu entry index "foo"}
+test menu-3.33 {MenuWidgetCmd procedure, "entrycget" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+ .m1 entrycget 1 -label
+} -cleanup {
+ destroy .m1
+} -result {test}
+test menu-3.34 {MenuWidgetCmd procedure, "entryconfigure" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 entryconfigure
+} -returnCodes error -result {wrong # args: should be ".m1 entryconfigure index ?-option value ...?"}
+test menu-3.35 {MenuWidgetCmd procedure, "entryconfigure" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 entryconfigure foo
+} -returnCodes error -result {bad menu entry index "foo"}
+test menu-3.36 {MenuWidgetCmd procedure, "entryconfigure" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+ llength [.m1 entryconfigure 1]
+} -cleanup {
+ destroy .m1
+} -result {15}
+test menu-3.37 {MenuWidgetCmd procedure, "entryconfigure" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+ lindex [.m1 entryconfigure 1 -label] 4
+} -cleanup {
+ destroy .m1
+} -result {test}
+test menu-3.38 {MenuWidgetCmd procedure, "entryconfigure" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+ .m1 entryconfigure 1 -label "changed"
+ lindex [.m1 entryconfigure 1 -label] 4
+} -cleanup {
+ destroy .m1
+} -result {changed}
+test menu-3.39 {MenuWidgetCmd procedure, "index" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 index
+} -returnCodes error -result {wrong # args: should be ".m1 index string"}
+test menu-3.40 {MenuWidgetCmd procedure, "index" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 index foo
+} -returnCodes error -result {bad menu entry index "foo"}
+test menu-3.41 {MenuWidgetCmd procedure, "index" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1 -tearoff 1
+ .m1 add command -label "test"
+ .m1 add command -label "3"
+ .m1 add command -label "another label"
+ .m1 add command -label "end"
+ .m1 add command -label "3a"
+ .m1 add command -label "final entry"
+ list [.m1 index "test"] [.m1 index "3"] [.m1 index "3a"] [.m1 index "end"]
+} -cleanup {
+ destroy .m1
+} -result {1 3 5 6}
+test menu-3.42 {MenuWidgetCmd procedure, "insert" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 insert
+} -returnCodes error -result {wrong # args: should be ".m1 insert index type ?-option value ...?"}
+test menu-3.43 {MenuWidgetCmd procedure, "insert" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 insert 1 command -label "test"
+ .m1 entrycget 1 -label
+} -cleanup {
+ destroy .m1
+} -result {test}
+test menu-3.44 {MenuWidgetCmd procedure, "invoke" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 invoke
+} -cleanup {
+ destroy .m1
+} -returnCodes error -result {wrong # args: should be ".m1 invoke index"}
+test menu-3.45 {MenuWidgetCmd procedure, "invoke" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 invoke foo
+} -cleanup {
+ destroy .m1
+} -returnCodes error -result {bad menu entry index "foo"}
+test menu-3.46 {MenuWidgetCmd procedure, "invoke" option} -setup {
+ destroy .m1
+} -body {
+ catch {unset foo}
+ menu .m1
+ .m1 add command -label "set foo" -command "set foo hello"
+ list [.m1 invoke 1] [set foo] [unset foo]
+} -cleanup {
+ destroy .m1
+} -returnCodes ok -result {hello hello {}}
+test menu-3.47 {MenuWidgetCmd procedure, "post" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add command -label "On Windows, hit Escape to get this menu to go away"
+ .m1 post
+} -cleanup {
+ destroy .m1
+} -returnCodes error -result {wrong # args: should be ".m1 post x y ?index?"}
+test menu-3.48 {MenuWidgetCmd procedure, "post" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 post foo 40
+} -cleanup {
+ destroy .m1
+} -returnCodes error -result {expected integer but got "foo"}
+test menu-3.49 {MenuWidgetCmd procedure, "post" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 post 40 bar
+} -cleanup {
+ destroy .m1
+} -returnCodes error -result {expected integer but got "bar"}
+test menu-3.50 {MenuWidgetCmd procedure, "post" option} -constraints {
+ nonUnixUserInteraction
+} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add command -label "menu-3.53: hit Escape" -command "puts hello"
+ .m1 post 40 40
+} -cleanup {
+ destroy .m1
+} -result {}
+test menu-3.51 {MenuWidgetCmd procedure, "postcascade" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 postcascade
+} -cleanup {
+ destroy .m1
+} -returnCodes error -result {wrong # args: should be ".m1 postcascade index"}
+test menu-3.52 {MenuWidgetCmd procedure, "postcascade" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 postcascade foo
+} -cleanup {
+ destroy .m1
+} -returnCodes error -result {bad menu entry index "foo"}
+test menu-3.53 {MenuWidgetCmd procedure, "postcascade" option} -constraints {
+ nonUnixUserInteraction
+} -setup {
+ destroy .m1 .m2
+} -body {
+ menu .m1
+ .m1 add command -label "menu-3.56 - hit Escape"
+ menu .m2
+ .m1 post 40 40
+ .m1 add cascade -menu .m2
+ .m1 postcascade 1
+} -cleanup {
+ destroy .m1 .m2
+} -result {}
+test menu-3.54 {MenuWidgetCmd procedure, "postcascade" option} -setup {
+ destroy .m1 .m2
+} -body {
+ menu .m1
+ menu .m2
+ .m1 add cascade -menu .m2 -label "menu-3.57 - hit Escape"
+ .m1 postcascade 1
+ .m1 postcascade none
+} -cleanup {
+ destroy .m1 .m2
+} -result {}
+test menu-3.55 {MenuWidgetCmd procedure, "type" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 type
+} -cleanup {
+ destroy .m1
+} -returnCodes error -result {wrong # args: should be ".m1 type index"}
+test menu-3.56 {MenuWidgetCmd procedure, "type" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 type foo
+} -cleanup {
+ destroy .m1
+} -returnCodes error -result {bad menu entry index "foo"}
+test menu-3.57 {MenuWidgetCmd procedure, "type" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+ .m1 type 1
+} -cleanup {
+ destroy .m1
+} -result {command}
+test menu-3.58 {MenuWidgetCmd procedure, "type" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add separator
+ .m1 type 1
+} -cleanup {
+ destroy .m1
+} -result {separator}
+test menu-3.59 {MenuWidgetCmd procedure, "type" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add checkbutton -label "test"
+ .m1 type 1
+} -cleanup {
+ destroy .m1
+} -result {checkbutton}
+test menu-3.60 {MenuWidgetCmd procedure, "type" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add radiobutton -label "test"
+ .m1 type 1
+} -cleanup {
+ destroy .m1
+} -result {radiobutton}
+test menu-3.61 {MenuWidgetCmd procedure, "type" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add cascade -label "test"
+ .m1 type 1
+} -cleanup {
+ destroy .m1
+} -result {cascade}
+test menu-3.62 {MenuWidgetCmd procedure, "type" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1 -tearoff 1
+ .m1 type 0
+} -cleanup {
+ destroy .m1
+} -result {tearoff}
+test menu-3.63 {MenuWidgetCmd procedure, "unpost" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 unpost foo
+} -cleanup {
+ destroy .m1
+} -returnCodes error -result {wrong # args: should be ".m1 unpost"}
+test menu-3.64 {MenuWidgetCmd procedure, "unpost" option} -constraints {
+ nonUnixUserInteraction
+} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add command -label "menu-3.68 - hit Escape"
+ .m1 post 40 40
+ .m1 unpost
+} -cleanup {
+ destroy .m1
+} -result {}
+test menu-3.65 {MenuWidgetCmd procedure, "yposition" option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 yposition
+} -cleanup {
+ destroy .m1
+} -returnCodes error -result {wrong # args: should be ".m1 yposition index"}
+test menu-3.66a {MenuWidgetCmd procedure, "yposition" option, no tearoff} -setup {
+ destroy .m1
+} -body {
+ menu .m1 -tearoff 0
+ .m1 yposition 1
+} -cleanup {
+ destroy .m1
+} -result {0}
+test menu-3.66b {MenuWidgetCmd procedure, "yposition" option, with tearoff} -constraints {
+ notAqua
+} -setup {
+ destroy .m1
+} -body {
+ # on Win or Linux, tearoff menus are supported
+ # see menu-3.66c for aqua
+ menu .m1 -tearoff 1
+ .m1 yposition 1
+} -cleanup {
+ destroy .m1
+} -result {1}
+test menu-3.66c {MenuWidgetCmd procedure, "yposition" option, with tearoff} -constraints {
+ aqua
+} -setup {
+ destroy .m1
+} -body {
+ # on OS X, tearoff menus are not supported
+ # see menu-3.66b for win or linux
+ menu .m1 -tearoff 1
+ .m1 yposition 1
+} -cleanup {
+ destroy .m1
+} -result {0}
+test menu-3.67 {MenuWidgetCmd procedure, bad option} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 foo
+} -cleanup {
+ destroy .m1
+} -returnCodes error -result {bad option "foo": must be activate, add, cget, clone, configure, delete, entrycget, entryconfigure, index, insert, invoke, post, postcascade, type, unpost, xposition, or yposition}
+test menu-3.68 {MenuWidgetCmd procedure, fix for bug#508988} -setup {
+ deleteWindows
+} -body {
+ set t .t
+ set m1 .t.m1
+ set c1 .t.c1
+ set c2 .t.c2
+ toplevel .t
+ menu $m1 -tearoff 1
+ menu $c1 -tearoff 1
+ $c1 add command -label c1
+ menu $c2 -tearoff 1
+ $c2 add command -label c2
+ $m1 add cascade -label c1 -menu $c1
+ $t configure -menu $m1
+ $m1 entryconfigure 1 -menu $c2 -label c2
+ $t configure -menu ""
+ list [winfo exists $c1] [winfo exists $c2]
+} -cleanup {
+ deleteWindows
+} -result {1 1}
+test menu-3.69 {MenuWidgetCmd procedure, "xposition" option} -setup {
+ destroy .m1
+ menu .m1
+} -body {
+ .m1 xposition
+} -cleanup {
+ destroy .m1
+} -returnCodes error -result {wrong # args: should be ".m1 xposition index"}
+test menu-3.70 {MenuWidgetCmd procedure, "xposition" option} -setup {
+ destroy .m1
+ menu .m1
+} -body {
+ .m1 xposition 1
+ subst {} ;# just checking that the xposition does not produce an error...
+} -cleanup {
+ destroy .m1
+} -result {}
+
+
+test menu-4.1 {TkInvokeMenu: disabled} -setup {
+ destroy .m1
+} -body {
+ catch {unset foo}
+ menu .m1
+ .m1 add checkbutton -label "test" -variable foo -onvalue on -offvalue off \
+ -state disabled
+ list [catch {.m1 invoke 1} msg] $foo
+} -cleanup {
+ destroy .m1
+} -result {0 off}
+test menu-4.2 {TkInvokeMenu: tearoff} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ catch {.m1 invoke 0}
+} -cleanup {
+ deleteWindows
+} -result {0}
+test menu-4.3 {TkInvokeMenu: checkbutton -on} -setup {
+ destroy .m1
+} -body {
+ catch {unset foo}
+ menu .m1
+ .m1 add checkbutton -label "test" -variable foo -onvalue on -offvalue off
+ list [catch {.m1 invoke 1} msg] $msg [catch {set foo} msg2] $msg2 \
+ [catch {unset foo} msg3] $msg3
+} -cleanup {
+ destroy .m1
+} -result {0 {} 0 on 0 {}}
+test menu-4.4 {TkInvokeMenu: checkbutton -off} -setup {
+ destroy .m1
+} -body {
+ catch {unset foo}
+ menu .m1
+ .m1 add checkbutton -label "test" -variable foo -onvalue on -offvalue off
+ .m1 invoke 1
+ list [catch {.m1 invoke 1} msg] $msg [catch {set foo} msg2] $msg2 [catch {unset foo} msg3] $msg3
+} -cleanup {
+ destroy .m1
+} -result {0 {} 0 off 0 {}}
+test menu-4.5 {TkInvokeMenu: checkbutton array element} -setup {
+ destroy .m1
+} -body {
+ catch {unset foo}
+ menu .m1
+ .m1 add checkbutton -label "test" -variable foo(1) -onvalue on
+ list [catch {.m1 invoke 1} msg] $msg [catch {set foo(1)} msg2] $msg2 [catch {unset foo} msg3] $msg3
+} -cleanup {
+ destroy .m1
+} -result {0 {} 0 on 0 {}}
+test menu-4.6 {TkInvokeMenu: radiobutton} -setup {
+ destroy .m1
+} -body {
+ catch {unset foo}
+ menu .m1 -tearoff 1
+ .m1 add radiobutton -label "1" -variable foo -value one
+ .m1 add radiobutton -label "2" -variable foo -value two
+ .m1 add radiobutton -label "3" -variable foo -value three
+ list [catch {.m1 invoke 1} msg] $msg [catch {set foo} msg2] $msg2 [catch {unset foo} msg3] $msg3
+} -cleanup {
+ destroy .m1
+} -result {0 {} 0 one 0 {}}
+test menu-4.7 {TkInvokeMenu: radiobutton} -setup {
+ destroy .m1
+} -body {
+ catch {unset foo}
+ menu .m1 -tearoff 1
+ .m1 add radiobutton -label "1" -variable foo -value one
+ .m1 add radiobutton -label "2" -variable foo -value two
+ .m1 add radiobutton -label "3" -variable foo -value three
+ list [catch {.m1 invoke 2} msg] $msg [catch {set foo} msg2] $msg2 [catch {unset foo} msg3] $msg3
+} -cleanup {
+ destroy .m1
+} -result {0 {} 0 two 0 {}}
+test menu-4.8 {TkInvokeMenu: radiobutton} -setup {
+ destroy .m1
+} -body {
+ catch {unset foo}
+ menu .m1
+ .m1 add radiobutton -label "1" -variable foo -value one
+ .m1 add radiobutton -label "2" -variable foo -value two
+ .m1 add radiobutton -label "3" -variable foo -value three
+ list [catch {.m1 invoke 3} msg] $msg [catch {set foo} msg2] $msg2 [catch {unset foo} msg3] $msg3
+} -cleanup {
+ destroy .m1
+} -result {0 {} 0 three 0 {}}
+test menu-4.9 {TkInvokeMenu: radiobutton array element} -setup {
+ destroy .m1
+} -body {
+ catch {unset foo}
+ menu .m1
+ .m1 add radiobutton -label "1" -variable foo(2) -value one
+ .m1 add radiobutton -label "2" -variable foo(2) -value two
+ .m1 add radiobutton -label "3" -variable foo(2) -value three
+ list [catch {.m1 invoke 3} msg] $msg [catch {set foo(2)} msg2] $msg2 [catch {unset foo} msg3] $msg3
+} -cleanup {
+ destroy .m1
+} -result {0 {} 0 three 0 {}}
+test menu-4.10 {TkInvokeMenu} -setup {
+ destroy .m1
+} -body {
+ catch {unset foo}
+ menu .m1
+ .m1 add command -label "test" -command "set menu_test menu-4.8"
+ list [catch {.m1 invoke 1} msg] $msg [catch {set menu_test} msg2] $msg2 [catch {unset menu_test} msg3] $msg3
+} -cleanup {
+ destroy .m1
+} -result {0 menu-4.8 0 menu-4.8 0 {}}
+test menu-4.11 {TkInvokeMenu} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add cascade -label "test" -menu .m1.m2
+ list [catch {.m1 invoke 1} msg] $msg
+} -cleanup {
+ destroy .m1
+} -result {0 {}}
+test menu-4.12 {TkInvokeMenu} -setup {
+ destroy .m1
+} -body {
+ menu .m1 -tearoff 1
+ .m1 add command -label "test" -command ".m1 delete 1"
+ list [catch {.m1 invoke 1} msg] $msg [catch {.m1 type "test"} msg2] $msg2
+} -cleanup {
+ destroy .m1
+} -result {0 {} 1 {bad menu entry index "test"}}
+
+test menu-5.1 {DestroyMenuInstance} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ destroy .m1
+} -returnCodes ok
+test menu-5.2 {DestroyMenuInstance - cascade menu} -setup {
+ destroy .m1 .m2
+} -body {
+ menu .m1
+ .m1 add cascade -menu .m2
+ menu .m2
+ destroy .m1 .m2
+} -returnCodes ok
+test menu-5.3 {DestroyMenuInstance - multiple cascade parents} -setup {
+ destroy .m1 .m2 .m3
+} -body {
+ menu .m1
+ .m1 add cascade -menu .m3
+ menu .m2
+ .m2 add cascade -menu .m3
+ menu .m3
+ list [destroy .m3] [destroy .m1 .m2]
+} -returnCodes ok -result {{} {}}
+test menu-5.4 {DestroyMenuInstance - multiple cascade parents} -setup {
+ destroy .m1 .m2 .m3 .m4
+} -body {
+ menu .m1
+ .m1 add cascade -menu .m4
+ menu .m2
+ .m2 add cascade -menu .m4
+ menu .m3
+ .m3 add cascade -menu .m4
+ menu .m4
+ list [destroy .m4] [destroy .m1 .m2 .m3]
+} -returnCodes ok -result {{} {}}
+test menu-5.5 {DestroyMenuInstance - cascades of cloned menus} -setup {
+ destroy .m1 .m2
+} -body {
+ menu .m1
+ menu .m2
+ .m1 add cascade -menu .m2
+ . configure -menu .m1
+ list [destroy .m2] [.m1 entrycget 1 -menu] [. configure -menu ""] [destroy .m1]
+} -returnCodes ok -result {{} .m2 {} {}}
+test menu-5.6 {DestroyMenuInstance - cascades of cloned menus} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add cascade -menu .m2
+ menu .m2
+ . configure -menu .m1
+ toplevel .t2
+ wm geometry .t2 +0+0
+ .t2 configure -menu .m1
+ list [destroy .m2] [. configure -menu ""] [destroy .t2 .m1]
+} -returnCodes ok -result {{} {} {}}
+test menu-5.7 {DestroyMenuInstance - basic clones} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ set tearoff [tk::TearOffMenu .m1]
+ list [destroy $tearoff] [destroy .m1]
+} -result {{} {}}
+test menu-5.8 {DestroyMenuInstance - multiple clones} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ set tearoff1 [tk::TearOffMenu .m1]
+ set tearoff2 [tk::TearOffMenu .m1]
+ list [destroy $tearoff1] [destroy .m1]
+} -returnCodes ok -result {{} {}}
+test menu-5.9 {DestroyMenuInstace - master menu} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ tk::TearOffMenu .m1
+ destroy .m1
+} -returnCodes ok
+test menu-5.10 {DestroyMenuInstance - freeing entries} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add command -label "foo"
+ destroy .m1
+} -returnCodes ok
+test menu-5.11 {DestroyMenuInstace - no entries} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 configure -tearoff 0
+ destroy .m1
+} -returnCodes ok
+test menu-5.12 {DestroyMenuInstance - platform data} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ destroy .m1
+} -returnCodes ok
+test menu-5.13 {DestroyMenuInstance - clones when mismatched tearoffs} -setup {
+ destroy .m1 .m2
+} -body {
+ menu .m1
+ menu .m2
+ .m1 add cascade -menu .m2
+ set tearoff [tk::TearOffMenu .m1 40 40]
+ list [destroy .m2] [destroy .m1]
+} -result {{} {}}
+
+
+test menu-6.1 {TkDestroyMenu} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ destroy .m1
+} -returnCodes ok
+test menu-6.2 {TkDestroyMenu - reentrancy} -setup {
+ destroy .m1 .m2
+} -body {
+ menu .m1
+ bind .m1 <Destroy> {destroy .m1}
+ menu .m2
+ bind .m2 <Destroy> {destroy .m2}
+ list [destroy .m1] [destroy .m2]
+} -returnCodes ok -result {{} {}}
+test menu-6.3 {TkDestroyMenu - reentrancy} -setup {
+ destroy .m1 .m2 .m3
+} -body {
+ menu .m1
+ bind .m1 <Destroy> {destroy .m2}
+ .m1 clone .m2
+ .m1 clone .m3
+ list [destroy .m1] [winfo exists .m2]
+} -returnCodes ok -result {{} 0}
+test menu-6.4 {TkDestroyMenu - reentrancy - clones} -setup {
+ destroy .m1 .m2
+} -body {
+ menu .m1
+ .m1 clone .m2
+ .m1 clone .m1.m3
+ destroy .m1
+} -cleanup {
+ deleteWindows
+} -returnCodes ok
+test menu-6.5 {TkDestroyMenu} -setup {
+ destroy .m1 .m2
+} -body {
+ menu .m1
+ .m1 clone .m2
+ destroy .m1
+ winfo exists .m2
+} -result {0}
+test menu-6.6 {TkDestroyMenu} -setup {
+ destroy .m1 .m2
+} -body {
+ menu .m1
+ .m1 clone .m2 tearoff
+ destroy .m1
+} -result {}
+test menu-6.7 {TkDestroyMenu} -setup {
+ destroy .m1 .m2
+} -body {
+ menu .m1
+ .m1 clone .m2
+ destroy .m2
+ destroy .m1
+} -returnCodes ok -result {}
+test menu-6.8 {TkDestroyMenu} -setup {
+ destroy .m1 .m2 .m3
+} -body {
+ menu .m1
+ .m1 clone .m2
+ .m1 clone .m3
+ destroy .m1
+ list [winfo exists .m2] [winfo exists .m3]
+} -result {0 0}
+test menu-6.9 {TkDestroyMenu} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 clone .m2
+ .m1 clone .m3
+ list [destroy .m2] [destroy .m3] [destroy .m1]
+} -returnCodes ok -result {{} {} {}}
+test menu-6.10 {TkDestroyMenu} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 clone .m2
+ .m1 clone .m3
+ list [destroy .m3] [destroy .m1]
+} -returnCodes ok -result {{} {}}
+test menu-6.11 {TkDestroyMenu} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 clone .m2
+ .m1 clone .m3
+ .m1 clone .m4
+ list [destroy .m2] [destroy .m1]
+} -returnCodes ok -result {{} {}}
+test menu-6.12 {TkDestroyMenu} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 clone .m2
+ .m1 clone .m3
+ .m1 clone .m4
+ list [destroy .m3] [destroy .m1]
+} -returnCodes ok -result {{} {}}
+test menu-6.13 {TkDestroyMenu} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 clone .m2
+ .m1 clone .m3
+ .m1 clone .m4
+ list [destroy .m4] [destroy .m1]
+} -returnCodes ok -result {{} {}}
+test menu-6.14 {TkDestroyMenu} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ . configure -menu .m1
+ list [destroy .m1] [. configure -menu ""]
+} -returnCodes ok -result {{} {}}
+test menu-6.15 {TkDestroyMenu} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ toplevel .t2
+ wm geometry .t2 +0+0
+ . configure -menu .m1
+ .t2 configure -menu .m1
+ list [destroy .m1] [destroy .t2] [. configure -menu ""]
+} -result {{} {} {}}
+test menu-6.16 {TkDestroyMenu} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ toplevel .t2
+ wm geometry .t2 +0+0
+ toplevel .t3
+ wm geometry .t3 +0+0
+ . configure -menu .m1
+ .t2 configure -menu .m1
+ .t3 configure -menu .m1
+ list [destroy .m1] [destroy .t2] [destroy .t3] [. configure -menu ""]
+} -result {{} {} {} {}}
+
+test menu-7.1 {UnhookCascadeEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+ destroy .m1
+} -returnCodes ok
+test menu-7.2 {UnhookCascadeEntry} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add cascade -menu .m2
+ destroy .m1
+} -returnCodes ok
+test menu-7.3 {UnhookCascadeEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ menu .m2
+ .m2 add cascade -menu .cascade
+ .m1 add cascade -menu .cascade
+ list [destroy .m1] [destroy .m2]
+} -returnCodes ok -result {{} {}}
+test menu-7.4 {UnhookCascadeEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ menu .m2
+ .m1 add cascade -menu .cascade
+ .m2 add cascade -menu .cascade
+ list [destroy .m1] [destroy .m2]
+} -returnCodes ok -result {{} {}}
+test menu-7.5 {UnhookCascadeEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ menu .m2
+ menu .m3
+ .m1 add cascade -menu .cascade
+ .m2 add cascade -menu .cascade
+ .m3 add cascade -menu .cascade
+ list [destroy .m1] [destroy .m2 .m3]
+} -returnCodes ok -result {{} {}}
+test menu-7.6 {UnhookCascadeEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ menu .m2
+ menu .m3
+ .m1 add cascade -menu .cascade
+ .m2 add cascade -menu .cascade
+ .m3 add cascade -menu .cascade
+ list [destroy .m2] [destroy .m1 .m3]
+} -returnCodes ok -result {{} {}}
+test menu-7.7 {UnhookCascadeEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ menu .m2
+ menu .m3
+ .m1 add cascade -menu .cascade
+ .m2 add cascade -menu .cascade
+ .m3 add cascade -menu .cascade
+ list [destroy .m3] [destroy .m1 .m2]
+} -returnCodes ok -result {{} {}}
+test menu-7.8 {UnhookCascadeEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ menu .m2
+ .m1 add cascade -menu .m2
+ list [destroy .m1] [destroy .m2]
+} -returnCodes ok -result {{} {}}
+test menu-7.9 {UnhookCascadeEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ menu .m2
+ .m1 add cascade -menu .m2
+ destroy .m1
+ destroy .m2
+} -returnCodes ok
+
+test menu-8.1 {DestroyMenuEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ menu .m2
+ .m1 add cascade -menu .m2
+ list [.m1 delete 1] [destroy .m1 .m2]
+} -result {{} {}}
+test menu-8.2 {DestroyMenuEntry} -constraints hasEarthPhoto -setup {
+ deleteWindows
+ catch {image delete image1a}
+} -body {
+ image create photo image1a -file $earthPhotoFile
+ menu .m1
+ .m1 add command -image image1a
+ list [.m1 delete 1] [destroy .m1] [image delete image1a]
+} -result {{} {} {}}
+test menu-8.3 {DestroyMenuEntry} -constraints testImageType -setup {
+ deleteWindows
+ imageCleanup
+} -body {
+ image create test image1
+ image create test image2
+ menu .m1
+ .m1 add checkbutton -image image1 -selectimage image2
+ .m1 invoke 1
+ list [.m1 delete 1] [destroy .m1]
+} -cleanup {
+ imageCleanup
+ deleteWindows
+} -result {{} {}}
+test menu-8.4 {DestroyMenuEntry} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add checkbutton -variable foo
+ list [.m1 delete 1] [destroy .m1]
+} -result {{} {}}
+test menu-8.5 {DestroyMenuEntry} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+ list [.m1 delete 1] [destroy .m1]
+} -result {{} {}}
+test menu-8.6 {DestroyMenuEntry} -setup {
+ destroy .m1
+} -body {
+ menu .m1 -tearoff 1
+ .m1 add command -label "one"
+ .m1 add command -label "two"
+ list [.m1 delete 1] [.m1 entrycget 1 -label] [destroy .m1]
+} -result {{} two {}}
+test menu-8.7 {DestroyMenuEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "one"
+ .m1 clone .m2 tearoff
+ list [.m2 delete 1] [destroy .m1]
+} -result {{} {}}
+
+
+# test menu-9 - Can only change when fonts change on system, which cannot
+# be done from tcl.
+test menu-9.1 {ConfigureMenu} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ list [.m1 configure -postcommand "beep"] [.m1 cget -postcommand]
+} -cleanup {
+ deleteWindows
+} -result {{} beep}
+test menu-9.2 {ConfigureMenu} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+ list [.m1 configure -tearoff 0] [.m1 entrycget 1 -label]
+} -cleanup {
+ deleteWindows
+} -result {{} test}
+test menu-9.3 {ConfigureMenu} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ list [.m1 configure -postcommand "beep"] [.m1 cget -postcommand]
+} -cleanup {
+ deleteWindows
+} -result {{} beep}
+test menu-9.4 {ConfigureMenu} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+ .m1 configure -fg red
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-9.5 {ConfigureMenu} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+ .m1 add command -label "two"
+ .m1 configure -fg red
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-9.6 {ConfigureMenu} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+ .m1 add command -label "two"
+ .m1 add command -label "three"
+ .m1 configure -fg red
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-9.7 {ConfigureMenu} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 clone .m2 tearoff
+ list [.m1 configure -fg red] [.m2 cget -fg]
+} -cleanup {
+ deleteWindows
+} -result {{} red}
+test menu-9.8 {ConfigureMenu} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 clone .m2 tearoff
+ list [.m2 configure -fg red] [.m1 cget -fg]
+} -cleanup {
+ deleteWindows
+} -result {{} red}
+test menu-9.9 {ConfigureMenu} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ list [. configure -menu .m1] [. configure -menu ""]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+
+
+test menu-10.1 {PostProcessEntry: array variable} -setup {
+ destroy .m1
+} -body {
+ catch {unset foo}
+ menu .m1
+ set foo(1) on
+ .m1 add checkbutton -variable foo(1) -onvalue on -offvalue off -label "Nonsense"
+ set foo(1)
+} -cleanup {
+ deleteWindows
+} -result {on}
+test menu-10.2 {PostProcessEntry: array variable} -setup {
+ destroy .m1
+} -body {
+ catch {unset foo}
+ menu .m1
+ .m1 add checkbutton -variable foo(1) -onvalue on -offvalue off -label "Nonsense"
+ set foo(1)
+} -cleanup {
+ deleteWindows
+} -result {off}
+
+
+test menu-11.1 {ConfigureMenuEntry} -setup {
+ destroy .m1
+} -body {
+ catch {unset foo}
+ menu .m1
+ .m1 add checkbutton -variable foo -onvalue on -offvalue off -label "Nonsense"
+ list [.m1 entryconfigure 1 -variable bar] [.m1 entrycget 1 -variable]
+} -cleanup {
+ deleteWindows
+} -result {{} bar}
+test menu-11.2 {ConfigureMenuEntry} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+ list [.m1 entryconfigure 1 -label ""] [.m1 entrycget 1 -label]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+test menu-11.3 {ConfigureMenuEntry} -setup {
+ destroy .m1
+} -body {
+ menu .m1
+ .m1 add command
+ list [.m1 entryconfigure 1 -label "test"] [.m1 entrycget 1 -label]
+} -cleanup {
+ deleteWindows
+} -result {{} test}
+test menu-11.4 {ConfigureMenuEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command
+ list [.m1 entryconfigure 1 -accel "S"] [.m1 entrycget 1 -accel]
+} -cleanup {
+ deleteWindows
+} -result {{} S}
+test menu-11.5 {ConfigureMenuEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command
+ list [.m1 entryconfigure 1 -label "test"] [.m1 entrycget 1 -label]
+} -cleanup {
+ deleteWindows
+} -result {{} test}
+test menu-11.6 {ConfigureMenuEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command
+ .m1 entryconfigure 1 -label "test"
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-11.7 {ConfigureMenuEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m2
+ menu .m1
+ .m1 add cascade
+ .m1 entryconfigure 1 -label "test" -menu .m2
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-11.8 {ConfigureMenuEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add cascade
+ .m1 entryconfigure 1 -label "test" -menu .m2
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-11.9 {ConfigureMenuEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add cascade -menu .m3
+ .m1 entryconfigure 1 -label "test" -menu .m2
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-11.10 {ConfigureMenuEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add cascade
+ .m1 entryconfigure 1 -label "test" -menu .m2
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-11.11 {ConfigureMenuEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add cascade -menu .m2
+ .m1 entryconfigure 1 -label "test" -menu .m2
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-11.12 {ConfigureMenuEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ menu .m2
+ .m2 add cascade -menu .m1
+ menu .m3
+ .m3 add cascade -menu .m1
+ menu .m4
+ .m4 add cascade -menu .m1
+ menu .m5
+ .m5 add cascade
+ .m5 entryconfigure 1 -label "test" -menu .m1
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-11.13 {ConfigureMenuEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ menu .m2
+ .m2 add cascade -menu .m1
+ menu .m3
+ .m3 add cascade -menu .m1
+ menu .m4
+ .m4 add cascade -menu .m1
+ .m3 entryconfigure 1 -label "test" -menu .m1
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-11.14 {ConfigureMenuEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add checkbutton
+ list [.m1 entryconfigure 1 -variable "test"] [.m1 entrycget 1 -variable]
+} -cleanup {
+ deleteWindows
+} -result {{} test}
+test menu-11.15 {ConfigureMenuEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ list [.m1 add checkbutton -label "test"] [.m1 entrycget 1 -variable]
+} -cleanup {
+ deleteWindows
+} -result {{} test}
+test menu-11.16 {ConfigureMenuEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add radiobutton -label "test"
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-11.17 {ConfigureMenuEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add checkbutton
+ list [.m1 entryconfigure 1 -onvalue "test"] [.m1 entrycget 1 -onvalue]
+} -cleanup {
+ deleteWindows
+} -result {{} test}
+test menu-11.18 {ConfigureMenuEntry} -constraints testImageType -setup {
+ deleteWindows
+ imageCleanup
+} -body {
+ menu .m1
+ .m1 add command
+ image create test image1
+ .m1 entryconfigure 1 -image image1
+} -cleanup {
+ deleteWindows
+ imageCleanup
+} -result {}
+test menu-11.19 {ConfigureMenuEntry} -constraints {
+ testImageType hasEarthPhoto
+} -setup {
+ deleteWindows
+ imageCleanup
+} -body {
+ image create test image1
+ image create photo image2 -file $earthPhotoFile
+ menu .m1
+ .m1 add command -image image1
+ .m1 entryconfigure 1 -image image2
+} -cleanup {
+ deleteWindows
+ imageCleanup
+} -result {}
+test menu-11.20 {ConfigureMenuEntry} -constraints {
+ testImageType hasEarthPhoto
+} -setup {
+ deleteWindows
+ imageCleanup
+} -body {
+ image create photo image1 -file $earthPhotoFile
+ image create test image2
+ menu .m1
+ .m1 add checkbutton -image image1
+ .m1 entryconfigure 1 -selectimage image2
+} -cleanup {
+ deleteWindows
+ imageCleanup
+} -result {}
+test menu-11.21 {ConfigureMenuEntry} -constraints {
+ testImageType hasEarthPhoto
+} -setup {
+ deleteWindows
+ imageCleanup
+} -body {
+ image create photo image1 -file $earthPhotoFile
+ image create test image2
+ image create test image3
+ menu .m1
+ .m1 add checkbutton -image image1 -selectimage image2
+ .m1 entryconfigure 1 -selectimage image3
+} -cleanup {
+ deleteWindows
+ imageCleanup
+} -result {}
+
+
+test menu-12.1 {ConfigureMenuCloneEntries} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 clone .m2
+ .m2 configure -tearoff 0
+ .m1 clone .m3
+ .m1 add command -label "test"
+ .m1 add command -label "test2"
+ .m1 entryconfigure 1 -gork "foo"
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {unknown option "-gork"}
+test menu-12.2 {ConfigureMenuCloneEntries} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 clone .m2
+ menu .m3
+ .m1 add cascade -menu .m3
+ menu .m4
+ .m1 entryconfigure 1 -menu .m4
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-12.3 {ConfigureMenuCloneEntries} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 clone .m2
+ .m1 add cascade -label dummy
+ .m1 entryconfigure dummy -menu .m3
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-12.4 {ConfigureMenuCloneEntries} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add cascade -label File -menu .m1.foo
+ menu .m1.foo
+ .m1.foo add command -label bar
+ .m1 clone .m2
+ .m1 entryconfigure File -state disabled
+} -cleanup {
+ deleteWindows
+} -result {}
+
+
+test menu-13.1 {TkGetMenuIndex} -setup {
+ deleteWindows
+} -body {
+ menu .m1 -tearoff 1
+ .m1 add command -label "active"
+ .m1 add command -label "test2"
+ .m1 add command -label "test3"
+ .m1 activate 2
+ .m1 entrycget active -label
+} -cleanup {
+ deleteWindows
+} -result {test2}
+test menu-13.2 {TkGetMenuIndex} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "last"
+ .m1 add command -label "test2"
+ .m1 add command -label "test3"
+ .m1 activate 2
+ .m1 entrycget last -label
+} -cleanup {
+ deleteWindows
+} -result {test3}
+test menu-13.3 {TkGetMenuIndex} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "last"
+ .m1 add command -label "test2"
+ .m1 add command -label "test3"
+ .m1 activate 2
+ .m1 entrycget end -label
+} -cleanup {
+ deleteWindows
+} -result {test3}
+test menu-13.4 {TkGetMenuIndex} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+ list [.m1 insert last command -label "test2"] [.m1 entrycget last -label]
+} -cleanup {
+ deleteWindows
+} -result {{} test2}
+test menu-13.5 {TkGetMenuIndex} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+ list [.m1 insert end command -label "test2"] [.m1 entrycget end -label]
+} -cleanup {
+ deleteWindows
+} -result {{} test2}
+test menu-13.6 {TkGetMenuIndex} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "active"
+ .m1 add command -label "test2"
+ .m1 add command -label "test3"
+ .m1 activate 2
+ .m1 entrycget none -label
+} -cleanup {
+ deleteWindows
+} -result {}
+#test menu-13.7 - Need to add @test here.
+test menu-13.7 {TkGetMenuIndex} -setup {
+ deleteWindows
+} -body {
+ menu .m1 -tearoff 1
+ .m1 add command -label "active"
+ .m1 add command -label "test2"
+ .m1 add command -label "test3"
+ .m1 entrycget 1 -label
+} -cleanup {
+ deleteWindows
+} -result {active}
+test menu-13.8 {TkGetMenuIndex} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "active"
+ .m1 entrycget -1 -label
+} -returnCodes error -result {bad menu entry index "-1"}
+test menu-13.9 {TkGetMenuIndex} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+ .m1 add command -label "test2"
+ .m1 entrycget 999 -label
+} -cleanup {
+ deleteWindows
+} -result {test2}
+test menu-13.10 {TkGetMenuIndex} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 insert 999 command -label "test"
+ .m1 entrycget 1 -label
+} -cleanup {
+ deleteWindows
+} -result {test}
+test menu-13.11 {TkGetMenuIndex} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "1test"
+ .m1 entrycget 1test -label
+} -cleanup {
+ deleteWindows
+} -result {1test}
+test menu-13.12 {TkGetMenuIndex} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+ .m1 add command -label "test2" -command "beep"
+ .m1 add command -label "test3"
+ .m1 entrycget test2 -command
+} -cleanup {
+ deleteWindows
+} -result {beep}
+
+test menu-14.1 {MenuCmdDeletedProc} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ destroy .m1
+} -cleanup {
+ deleteWindows
+} -returnCodes ok
+test menu-14.2 {MenuCmdDeletedProc} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 clone .m2
+ destroy .m1
+} -cleanup {
+ deleteWindows
+} -returnCodes ok
+
+test menu-15.1 {MenuNewEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-15.2 {MenuNewEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+ .m1 add command -label "test3"
+ .m1 insert 2 command -label "test2"
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-15.3 {MenuNewEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+ .m1 add command -label "test2"
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-15.4 {MenuNewEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+} -cleanup {
+ deleteWindows
+} -result {}
+
+test menu-16.1 {MenuAddOrInsert} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 insert foo command -label "test"
+} -returnCodes error -result {bad menu entry index "foo"}
+test menu-16.2 {MenuAddOrInsert} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+ .m1 insert test command -label "foo"
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-16.3 {MenuAddOrInsert} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 insert -1 command -label "test"
+} -returnCodes error -result {bad menu entry index "-1"}
+test menu-16.4 {MenuAddOrInsert} -setup {
+ deleteWindows
+} -body {
+ menu .m1 -tearoff 1
+ .m1 add command -label "test"
+ .m1 insert 0 command -label "test2"
+ .m1 entrycget 1 -label
+} -cleanup {
+ deleteWindows
+} -result {test2}
+test menu-16.5 {MenuAddOrInsert} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add cascade
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-16.6 {MenuAddOrInsert} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add checkbutton
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-16.7 {MenuAddOrInsert} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-16.8 {MenuAddOrInsert} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add radiobutton
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-16.9 {MenuAddOrInsert} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add separator
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-16.10 {MenuAddOrInsert} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add blork
+} -returnCodes error -result {bad menu entry type "blork": must be cascade, checkbutton, command, radiobutton, or separator}
+test menu-16.11 {MenuAddOrInsert} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-16.12 {MenuAddOrInsert} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 clone .m2
+ .m2 clone .m3
+ list [.m2 add command -label "test"] [.m1 entrycget 1 -label] [.m3 entrycget 1 -label]
+} -cleanup {
+ deleteWindows
+} -result {{} test test}
+test menu-16.13 {MenuAddOrInsert} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 clone .m2
+ .m2 clone .m3
+ list [.m3 add command -label "test"] [.m1 entrycget 1 -label] [.m2 entrycget 1 -label]
+} -cleanup {
+ deleteWindows
+} -result {{} test test}
+test menu-16.14 {MenuAddOrInsert} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -blork
+} -returnCodes error -result {unknown option "-blork"}
+test menu-16.15 {MenuAddOrInsert} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "File"
+ menu .container
+ . configure -menu .container
+ list [.container add cascade -label "File" -menu .m1] [. configure -menu ""]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+test menu-16.16 {MenuAddOrInsert} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ menu .m2
+ set tearoff [tk::TearOffMenu .m2]
+ list [.m2 add cascade -menu .m1] [$tearoff unpost]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+test menu-16.17 {MenuAddOrInsert} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ menu .container
+ . configure -menu .container
+ set tearoff [tk::TearOffMenu .container]
+ list [.container add cascade -label "File" -menu .m1] [. configure -menu ""]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+test menu-16.18 {MenuAddOrInsert} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ menu .container
+ .container add cascade -menu .m1
+ . configure -menu .container
+ list [.container add cascade -label "File" -menu .m1] [. configure -menu ""]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+test menu-16.19 {MenuAddOrInsert - Insert a cascade deep into the tree} -setup {
+ deleteWindows
+} -body {
+ menu .menubar
+ menu .menubar.test -tearoff 0
+ .menubar add cascade -label Test -underline 0 -menu .menubar.test
+ menu .menubar.test.cascade -tearoff 0
+ .menubar.test.cascade add command -label SubItem -command "puts SubItemSelected"
+ . configure -menu .menubar
+ list [catch {.menubar.test add cascade -label SubMenu \
+ -menu .menubar.test.cascade}] \
+ [info commands .\#menubar.\#menubar\#test.\#menubar\#test\#cascade] \
+ [. configure -menu ""]
+} -cleanup {
+ deleteWindows
+} -result {0 .#menubar.#menubar#test.#menubar#test#cascade {}}
+
+
+test menu-17.1 {MenuVarProc} -setup {
+ deleteWindows
+} -body {
+ catch {unset foo}
+ menu .m1
+ set foo "hello"
+ list [.m1 add checkbutton -variable foo -onvalue hello -offvalue goodbye] \
+ [unset foo]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+# menu-17.2 - Don't know how to generate the flags in the if
+test menu-17.2 {MenuVarProc} -setup {
+ deleteWindows
+} -body {
+ catch {unset foo}
+ menu .m1
+ list [.m1 add checkbutton -variable foo -onvalue hello -offvalue goodbye] \
+ [set foo ""]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+test menu-17.3 {MenuVarProc} -setup {
+ deleteWindows
+} -body {
+ catch {unset foo}
+ menu .m1
+ set foo "hello"
+ list [.m1 add checkbutton -variable foo -onvalue hello -offvalue goodbye] \
+ [set foo "hello"] [unset foo]
+} -cleanup {
+ deleteWindows
+} -result {{} hello {}}
+test menu-17.4 {MenuVarProc} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ set foo "goodbye"
+ list [.m1 add checkbutton -variable foo -onvalue hello -offvalue goodbye] \
+ [set foo "hello"] [unset foo]
+} -cleanup {
+ deleteWindows
+} -result {{} hello {}}
+test menu-17.5 {MenuVarProc} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ set foo "hello"
+ list [.m1 add checkbutton -variable foo -onvalue hello -offvalue goodbye] \
+ [set foo "goodbye"] [unset foo]
+} -cleanup {
+ deleteWindows
+} -result {{} goodbye {}}
+test menu-17.6 {MenuVarProc [5d991b822e]} -setup {
+ deleteWindows
+} -body {
+ # Want this not to crash
+ menu .b
+ set var INIT
+ .b add checkbutton -variable var
+ trace add variable var unset {apply {args {
+ .b entryconfigure 1 -variable {}
+ }}}
+ unset var
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-17.7 {MenuVarProc [5d991b822e]} -setup {
+ deleteWindows
+} -body {
+ # Want this not to duplicate traces
+ menu .b
+ set var INIT
+ .b add checkbutton -variable var
+ trace add variable var unset {apply {args {
+ .b entryconfigure 1 -variable new
+ }}}
+ unset var
+} -cleanup {
+ deleteWindows
+} -result {}
+
+
+test menu-18.1 {TkActivateMenuEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+ .m1 activate 1
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-18.2 {TkActivateMenuEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+ .m1 activate 0
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-18.3 {TkActivateMenuEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+ .m1 add command -label "test2"
+ .m1 activate 1
+ .m1 activate 2
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-18.4 {TkActivateMenuEntry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+ .m1 add command -label "test2"
+ .m1 activate 1
+ .m1 activate 1
+} -cleanup {
+ deleteWindows
+} -result {}
+
+
+test menu-19.1 {TkPostCommand} -constraints nonUnixUserInteraction -setup {
+ deleteWindows
+} -body {
+ menu .m1 -postcommand "set menu_test menu-19.1"
+ .m1 add command -label "menu-19.1 - hit Escape"
+ list [.m1 post 40 40] [.m1 unpost] [set menu_test]
+} -cleanup {
+ deleteWindows
+} -result {menu-19.1 {} menu-19.1}
+test menu-19.2 {TkPostCommand} -constraints nonUnixUserInteraction -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "menu-19.2 - hit Escape"
+ list [.m1 post 40 40] [.m1 unpost]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+
+test menu-20.1 {CloneMenu} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 clone .m2]
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-20.2 {CloneMenu} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 clone .m2 normal
+ deleteWindows
+} -result {}
+test menu-20.3 {CloneMenu} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 clone .m2 tearoff
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-20.4 {CloneMenu} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 clone .m2 menubar
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-20.5 {CloneMenu} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 clone .m2 foo
+} -returnCodes error -result {bad menu type "foo": must be normal, tearoff, or menubar}
+test menu-20.6 {CloneMenu - hooking up bookeeping ptrs} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 clone .m2
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-20.7 {CloneMenu - hooking up bookeeping ptrs - multiple children} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 clone .m2
+ .m1 clone .m3
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-20.8 {CloneMenu - cascade entries} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add cascade -menu .m2
+ .m1 clone .foo
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-20.9 {CloneMenu - cascades entries} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add cascade -menu .m2
+ menu .m2
+ .m1 clone .foo
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-20.10 {CloneMenu - tearoff fields} -setup {
+ deleteWindows
+} -body {
+ menu .m1 -tearoff 1
+ list [.m1 clone .m2 normal] [.m2 cget -tearoff]
+} -cleanup {
+ deleteWindows
+} -result {{} 1}
+test menu-20.11 {CloneMenu} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ menu .m2
+ .m1 clone .m2
+} -returnCodes error -result {window name "m2" already exists in parent}
+
+test menu-21.1 {MenuDoYPosition} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 yposition glorp
+} -returnCodes error -result {bad menu entry index "glorp"}
+test menu-21.2 {MenuDoYPosition} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "Test"
+ .m1 yposition 1
+} -cleanup {
+ deleteWindows
+} -returnCodes ok -match glob -result {*}
+
+test menu-22.1 {GetIndexFromCoords} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+ .m1 configure -tearoff 0
+ .m1 index @5
+} -cleanup {
+ deleteWindows
+} -result {0}
+test menu-22.2 {GetIndexFromCoords} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "test"
+ .m1 configure -tearoff 0
+ .m1 index @5,5
+} -cleanup {
+ deleteWindows
+} -result {0}
+test menu-22.3 {GetIndexFromCoords: mapped window, y only} -setup {
+ deleteWindows
+} -constraints {x11} -body {
+ menu .m1
+ .m1 add command -label "test"
+ .m1 configure -tearoff 0
+ tk_popup .m1 0 0
+ tkwait visibility .m1
+ .m1 index @5
+} -cleanup {
+ deleteWindows
+} -result {0}
+test menu-22.4 {GetIndexFromCoords: mapped window x,y} -setup {
+ deleteWindows
+} -constraints {x11} -body {
+ menu .m1
+ .m1 add command -label "test"
+ .m1 configure -tearoff 0
+ tk_popup .m1 0 0
+ tkwait visibility .m1
+ update
+ set x [expr {[winfo width .m1] - [.m1 cget -borderwidth] - 1}]
+ .m1 index @$x,5
+} -cleanup {
+ deleteWindows
+} -result {0}
+test menu-22.5 {GetIndexFromCoords: mapped wide window} -setup {
+ deleteWindows
+} -constraints {x11} -body {
+ menu .m1
+ .m1 add command -label "test"
+ .m1 configure -tearoff 0
+ tk_popup .m1 0 0
+ tkwait visibility .m1
+ wm geometry .m1 200x100
+ update
+ set x [expr {[winfo width .m1] - [.m1 cget -borderwidth] - 1}]
+ .m1 index @$x,5
+} -cleanup {
+ deleteWindows
+} -result {0}
+
+test menu-23.1 {RecursivelyDeleteMenu} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ . configure -menu .m1
+ . configure -menu ""
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-23.2 {RecursivelyDeleteMenu} -setup {
+ deleteWindows
+} -body {
+ menu .m2
+ .m2 add command -label "test2"
+ menu .m1
+ .m1 add cascade -label "test1" -menu .m2
+ . configure -menu .m1
+ . configure -menu ""
+} -cleanup {
+ deleteWindows
+} -result {}
+
+test menu-24.1 {TkNewMenuName} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ list [. configure -menu .m1] [. configure -menu ""]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+test menu-24.2 {TkNewMenuName} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ menu .m1\#0
+ list [. configure -menu .m1] [. configure -menu ""]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+test menu-24.3 {TkNewMenuName} -setup {
+ deleteWindows
+} -body {
+ menu .#m
+ rename .#m hideme
+ list [catch {. configure -menu [menu .m]}] [. configure -menu ""] [destroy .#m] \
+ [destroy .m] [destroy hideme]
+} -result {0 {} {} {} {}}
+
+
+test menu-25.1 {TkSetWindowMenuBar} -setup {
+ deleteWindows
+} -body {
+ . configure -menu ""
+ list [. configure -menu .m1] [. configure -menu ""]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+test menu-25.2 {TkSetWindowMenuBar} -setup {
+ deleteWindows
+} -body {
+ . configure -menu ""
+ list [. configure -menu .m1] [. configure -menu ""]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+test menu-25.3 {TkSetWindowMenuBar} -setup {
+ deleteWindows
+} -body {
+ . configure -menu ""
+ destroy .m1
+ menu .m1
+ list [. configure -menu .m1] [. configure -menu ""]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+test menu-25.4 {TkSetWindowMenuBar} -setup {
+ deleteWindows
+} -body {
+ . configure -menu ""
+ menu .m1
+ . configure -menu .m1
+ menu .m2
+ list [. configure -menu .m2] [. configure -menu ""]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+test menu-25.5 {TkSetWindowMenuBar} -setup {
+ deleteWindows
+} -body {
+ . configure -menu ""
+ menu .m1
+ . configure -menu .m1
+ .m1 clone .m2
+ menu .m3
+ list [. configure -menu .m3] [. configure -menu ""]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+test menu-25.6 {TkSetWindowMenuBar} -setup {
+ deleteWindows
+} -body {
+ . configure -menu ""
+ menu .m1
+ .m1 clone .m2
+ . configure -menu .m2
+ menu .m3
+ list [. configure -menu .m3] [. configure -menu ""]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+test menu-25.7 {TkSetWindowMenuBar} -setup {
+ deleteWindows
+} -body {
+ . configure -menu ""
+ menu .m1
+ menu .m2
+ . configure -menu .m1
+ toplevel .t2
+ .t2 configure -menu .m1
+ list [.t2 configure -menu .m2] [. configure -menu ""]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+test menu-25.8 {TkSetWindowMenuBar} -setup {
+ deleteWindows
+} -body {
+ . configure -menu ""
+ menu .m1
+ menu .m2
+ . configure -menu .m1
+ toplevel .t2
+ wm geometry .t2 +0+0
+ .t2 configure -menu .m1
+ list [. configure -menu .m2] [. configure -menu ""]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+test menu-25.9 {TkSetWindowMenuBar} -setup {
+ deleteWindows
+} -body {
+ . configure -menu ""
+ menu .m1
+ menu .m2
+ . configure -menu .m1
+ toplevel .t2 -menu .m1
+ wm geometry .t2 +0+0
+ toplevel .t3 -menu .m1
+ wm geometry .t3 +0+0
+ list [.t3 configure -menu .m2] [. configure -menu ""]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+test menu-25.10 {TkSetWindowMenuBar} -setup {
+ deleteWindows
+} -body {
+ . configure -menu ""
+ menu .m1
+ menu .m2
+ . configure -menu .m1
+ toplevel .t2 -menu .m1
+ wm geometry .t2 +0+0
+ toplevel .t3 -menu .m1
+ wm geometry .t3 +0+0
+ list [.t2 configure -menu .m2] [. configure -menu ""]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+test menu-25.11 {TkSetWindowMenuBar} -setup {
+ deleteWindows
+} -body {
+ . configure -menu ""
+ menu .m1
+ menu .m2
+ . configure -menu .m1
+ toplevel .t2 -menu .m1
+ wm geometry .t2 +0+0
+ toplevel .t3 -menu .m1
+ wm geometry .t3 +0+0
+ list [. configure -menu .m2] [. configure -menu ""]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+test menu-25.12 {TkSetWindowMenuBar} -setup {
+ deleteWindows
+} -body {
+ . configure -menu ""
+ menu .m1
+ list [. configure -menu .m1] [. configure -menu ""]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+test menu-25.13 {TkSetWindowMenuBar} -setup {
+ deleteWindows
+} -body {
+ . configure -menu ""
+ list [. configure -menu .m1] [. configure -menu ""]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+test menu-25.14 {TkSetWindowMenuBar} -setup {
+ deleteWindows
+} -body {
+ . configure -menu ""
+ menu .m1
+ list [. configure -menu .m1] [. configure -menu ""]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+test menu-25.15 {TkSetWindowMenuBar} -setup {
+ deleteWindows
+} -body {
+ . configure -menu ""
+ list [. configure -menu .m1] [. configure -menu ""]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+test menu-25.16 {TkSetWindowMenuBar} -setup {
+ deleteWindows
+} -body {
+ . configure -menu ""
+ menu .m1
+ . configure -menu .m1
+ list [toplevel .t2 -menu m1] [. configure -menu ""]
+} -cleanup {
+ deleteWindows
+} -result {.t2 {}}
+
+
+test menu-26.1 {DestroyMenuHashTable} -setup {
+ catch {interp delete testinterp}
+ deleteWindows
+} -body {
+ interp create testinterp
+ load {} Tk testinterp
+ interp eval testinterp {menu .m1}
+ interp delete testinterp
+} -returnCodes ok -result {}
+
+
+test menu-27.1 {GetMenuHashTable} -setup {
+ catch {interp delete testinterp}
+ deleteWindows
+} -body {
+ interp create testinterp
+ load {} Tk testinterp
+ list [catch {interp eval testinterp {menu .m1}} msg] $msg [interp delete testinterp]
+} -cleanup {
+ deleteWindows
+} -result {0 .m1 {}}
+
+
+test menu-28.1 {TkCreateMenuReferences - not there before} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+} -cleanup {
+ deleteWindows
+} -result {.m1}
+test menu-28.2 {TkCreateMenuReferences - there already} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add cascade -menu .m2
+ menu .m2
+} -cleanup {
+ deleteWindows
+} -result {.m2}
+
+
+test menu-29.1 {TkFindMenuReferences - not there} -setup {
+ deleteWindows
+} -body {
+ . configure -menu ""
+ menu .m1
+ .m1 add cascade -menu .m2
+ list [. configure -menu .m1] [. configure -menu ""]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+
+
+test menu-30.1 {TkFindMenuReferences - there already} -setup {
+ deleteWindows
+} -body {
+ . configure -menu ""
+ menu .m1
+ menu .m2
+ .m1 add cascade -menu .m2
+ list [. configure -menu .m1] [. configure -menu ""]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+
+
+test menu-31.1 {TkFreeMenuReferences - menuPtr} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ destroy .m1
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-31.2 {TkFreeMenuReferences - cascadePtr} -setup {
+ deleteWindows
+} -body {
+ . configure -menu ""
+ menu .m1
+ .m1 add cascade -menu .m2
+ .m1 entryconfigure 1 -menu .m3
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-31.3 {TkFreeMenuReferences - topLevelListPtr} -setup {
+ deleteWindows
+} -body {
+ . configure -menu .m1
+ . configure -menu ""
+} -cleanup {
+ deleteWindows
+} -returnCodes ok -result {}
+test menu-31.4 {TkFreeMenuReferences - not empty} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add cascade -menu .m3
+ menu .m2
+ .m2 add cascade -menu .m3
+ .m2 entryconfigure 1 -menu ".foo"
+} -cleanup {
+ deleteWindows
+} -result {}
+
+
+test menu-32.1 {DeleteMenuCloneEntries} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label foo
+ .m1 clone .m2
+ .m1 delete 1
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-32.2 {DeleteMenuCloneEntries} -setup {
+ deleteWindows
+} -body {
+
+ menu .m1
+ .m1 add command -label one
+ .m1 add command -label two
+ .m1 add command -label three
+ .m1 add command -label four
+ .m1 clone .m2
+ .m1 delete 2 3
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-32.3 {DeleteMenuCloneEntries} -setup {
+ deleteWindows
+} -body {
+ menu .m1 -tearoff 0
+ .m1 add command -label one
+ .m1 add command -label two
+ .m1 add command -label three
+ .m1 add command -label four
+ .m1 clone .m2
+ .m2 configure -tearoff 1
+ .m1 delete 1 2
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-32.4 {DeleteMenuCloneEntries} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label one
+ .m1 add command -label two
+ .m1 add command -label three
+ .m1 add command -label four
+ .m1 clone .m2
+ .m2 configure -tearoff 0
+ .m1 delete 2 3
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-32.5 {DeleteMenuCloneEntries} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label one
+ .m1 add command -label two
+ .m1 clone .m2
+ .m1 activate one
+ .m1 delete one
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-32.6 {DeleteMenuCloneEntries - reentrancy - crashes tk8.0} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label test \
+ -command ".m1 delete test ; .m1 add command -label test -command \".m1 delete test\"; .m1 delete test"
+ .m1 invoke test
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-32.7 {DeleteMenuCloneEntries - one entry} -setup {
+ deleteWindows
+} -body {
+ menu .m1 -tearoff 0
+ .m1 add command -label Hello
+ .m1 delete Hello
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-32.8 {Ensure all menu clone commands are deleted} -setup {
+ deleteWindows
+} -body {
+ # SF bug #465324
+ menu .menubar
+ . configure -menu .menubar
+ menu .menubar.test
+ .menubar.test add command -label "hi"
+ for {set i 0} {$i < 10} {incr i} {
+ .menubar add cascade -menu .menubar.test -label "Test"
+ .menubar delete Test
+ }
+
+ info commands .#menubar*test*
+} -cleanup {
+ deleteWindows
+} -result {}
+test menu-32.9 {Ensure deleting of clones doesn't corrupt menu refs} -setup {
+ set res {}
+ deleteWindows
+} -body {
+ menu .menubar
+ . configure -menu .menubar
+ menu .menubar.test
+ .menubar add cascade -menu .menubar.test -label "Test"
+ menu .menubar.cascade
+
+ .menubar.test add cascade -menu .menubar.cascade -label "Cascade"
+ lappend res [.menubar.test entrycget 1 -menu]
+ lappend res [.#menubar.#menubar#test entrycget 1 -menu]
+ destroy .menubar.test
+ menu .menubar.test
+ .menubar.test add cascade -menu .menubar.cascade -label "Cascade"
+ lappend res [.menubar.test entrycget 1 -menu]
+ lappend res [.#menubar.#menubar#test entrycget 1 -menu]
+ return $res
+} -cleanup {
+ deleteWindows
+} -result {.menubar.cascade .#menubar.#menubar#test.#menubar#cascade .menubar.cascade .#menubar.#menubar#test.#menubar#cascade}
+
+
+test menu-33.1 {menu vs command hiding} -setup {
+ deleteWindows
+} -body {
+ set l [interp hidden]
+ menu .m
+ interp hide {} .m
+ destroy .m
+ set result [list [winfo children .] [interp hidden]]
+ expr {$result eq [list {} $l]}
+} -result 1
+
+# menu-34 MenuInit only called at boot time
+
+# creating menus on two different screens then deleting the
+# menu from the first screen crashes Tk8.3.1
+#
+test menu-34.1 {menus on multiple screens - crashes tk8.3.1, Bug 5454} -constraints {
+ altDisplay
+} -setup {
+ deleteWindows
+} -body {
+ toplevel .one
+ menu .one.m
+ toplevel .two -screen $::env(TK_ALT_DISPLAY)
+ menu .two.m
+ destroy .one
+ destroy .two
+} -result {}
+
+test menu-35.1 {menu -underline string overruns Bug 1599877} -setup {
+ destroy .m
+} -body {
+ # ensure that -underline does not do string overruns [Bug 1599877]
+ menu .m
+ .m add command -label "File" -underline [expr {1<<30}]
+ . configure -menu .m
+ update
+ tk::TraverseToMenu . "e"
+} -cleanup {
+ deleteWindows
+} -result {}
+
+test menu-37.1 {menubar menues cannot be posted - bug 2160206} -setup {
+ catch {destroy .m}
+} -body {
+ # On Linux the following used to panic
+ # It now returns an error (on all platforms)
+ menu .m -type menubar
+ list [catch ".m post 1 1" msg] $msg
+} -cleanup {
+ destroy .m
+} -result {1 {a menubar menu cannot be posted}}
+
+test menu-38.1 {Can't dismiss ttk::menubutton menu until mouse has hovered over it - bug fa32290898} -setup {
+} -constraints {userInteraction} -body {
+ toplevel .top
+ ttk::menubutton .top.mb -text "Some menu";
+ menu .top.mb.m;
+ .top.mb.m add command -label "Item 1";
+ .top.mb.m add command -label "Item 2";
+ .top.mb configure -menu .top.mb.m;
+ pack .top.mb
+ update
+ # simulate mouse click on the menubutton, which posts its menu
+ event generate .top.mb <ButtonPress-1> -warp 1
+ update
+ after 50
+ event generate .top.mb <ButtonRelease-1>
+ update
+ # simulate mouse click on the menu again, i.e. without
+ # entering/leaving the posted menu
+ event generate .top.mb <ButtonPress-1>
+ update
+ after 50
+ event generate .top.mb <ButtonRelease-1>
+ update
+ # the menu shall have been unposted by the second click
+ winfo ismapped .top.mb.m
+} -cleanup {
+ destroy .top.mb.m .top.m .top
+} -result {0}
+
+
+# cleanup
+imageFinish
+deleteWindows
+cleanupTests
+return
+
+# Local variables:
+# mode: tcl
+# End:
diff --git a/tk8.6/tests/menuDraw.test b/tk8.6/tests/menuDraw.test
new file mode 100644
index 0000000..0d7a049
--- /dev/null
+++ b/tk8.6/tests/menuDraw.test
@@ -0,0 +1,717 @@
+# This file is a Tcl script to test drawing of menus in Tk. It is
+# organized in the standard fashion for Tcl tests.
+#
+# Copyright (c) 1996-1997 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+namespace import -force tcltest::test
+imageInit
+
+test menuDraw-1.1 {TkMenuInitializeDrawingFields} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+} -cleanup {
+ deleteWindows
+} -result {.m1}
+
+
+test menuDraw-2.1 {TkInitializeMenuEntryDrawingFields} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command
+} -cleanup {
+ deleteWindows
+} -result {}
+
+
+test menuDraw-3.1 {TkMenuFreeDrawOptions} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ destroy .m1
+} -result {}
+
+
+test menuDraw-4.1 {TkMenuEntryFreeDrawOptions} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "This is a test"
+ destroy .m1
+} -result {}
+test menuDraw-4.2 {TkMenuEntryFreeDrawOptions} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add checkbutton -label "This is a test." -font "Courier 12" \
+ -activeforeground red -background green -selectcolor purple
+ destroy .m1
+} -result {}
+
+
+test menuDraw-5.1 {TkMenuConfigureDrawOptions - new menu} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+} -cleanup {
+ deleteWindows
+} -result {.m1}
+test menuDraw-5.2 {TkMenuConfigureDrawOptions - old menu} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 configure -fg red
+} -cleanup {
+ deleteWindows
+} -result {}
+test menuDraw-5.3 {TkMenuConfigureDrawOptions - no disabledFg} -setup {
+ deleteWindows
+} -body {
+ menu .m1 -disabledforeground ""
+} -cleanup {
+ deleteWindows
+} -result {.m1}
+
+
+test menuDraw-6.1 {TkMenuConfigureEntryDrawOptions - no tkfont specified} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "foo"
+} -cleanup {
+ deleteWindows
+} -result {}
+test menuDraw-6.2 {TkMenuConfigureEntryDrawOptions - tkfont specified} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "foo" -font "Courier 12"
+} -cleanup {
+ deleteWindows
+} -result {}
+test menuDraw-6.3 {TkMenuConfigureEntryDrawOptions - active state - wrong entry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "foo"
+ .m1 entryconfigure 1 -state active
+} -cleanup {
+ deleteWindows
+} -result {}
+test menuDraw-6.4 {TkMenuConfigureEntryDrawOptions - active state - correct entry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "foo"
+ .m1 activate 1
+ .m1 entryconfigure 1 -state active
+} -cleanup {
+ deleteWindows
+} -result {}
+test menuDraw-6.5 {TkMenuConfigureEntryDrawOptions - deactivate entry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "foo"
+ .m1 activate 1
+ .m1 entryconfigure 1 -state normal
+} -cleanup {
+ deleteWindows
+} -result {}
+test menuDraw-6.6 {TkMenuConfigureEntryDrawOptions - bad state} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "foo"
+ .m1 entryconfigure 1 -state foo
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {bad state "foo": must be active, normal, or disabled}
+test menuDraw-6.7 {TkMenuConfigureEntryDrawOptions - tkfont specified} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "foo" -font "Courier 12"
+} -cleanup {
+ deleteWindows
+} -result {}
+test menuDraw-6.8 {TkMenuConfigureEntryDrawOptions - border specified} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "foo" -background "red"
+} -cleanup {
+ deleteWindows
+} -result {}
+test menuDraw-6.9 {TkMenuConfigureEntryDrawOptions - foreground specified} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "foo" -foreground "red"
+} -cleanup {
+ deleteWindows
+} -result {}
+test menuDraw-6.10 {TkMenuConfigureEntryDrawOptions - activeBorder specified} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "foo" -activebackground "red"
+} -cleanup {
+ deleteWindows
+} -result {}
+test menuDraw-6.11 {TkMenuConfigureEntryDrawOptions - activeforeground specified} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "foo" -activeforeground "red"
+} -cleanup {
+ deleteWindows
+} -result {}
+test menuDraw-6.12 {TkMenuConfigureEntryDrawOptions - selectcolor specified} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add radiobutton -label "foo" -selectcolor "red"
+} -cleanup {
+ deleteWindows
+} -result {}
+test menuDraw-6.13 {TkMenuConfigureEntryDrawOptions - textGC disposal} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "foo" -font "Helvetica 12"
+ .m1 entryconfigure 1 -font "Courier 12"
+} -cleanup {
+ deleteWindows
+} -result {}
+test menuDraw-6.14 {TkMenuConfigureEntryDrawOptions - activeGC disposal} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "foo" -activeforeground "red"
+ .m1 entryconfigure 1 -activeforeground "green"
+} -cleanup {
+ deleteWindows
+} -result {}
+test menuDraw-6.15 {TkMenuConfigureEntryDrawOptions - disabledGC disposal} -setup {
+ deleteWindows
+} -body {
+ menu .m1 -disabledforeground "red"
+ .m1 add command -label "foo"
+ .m1 configure -disabledforeground "green"
+} -cleanup {
+ deleteWindows
+} -result {}
+test menuDraw-6.16 {TkMenuConfigureEntryDrawOptions - indicatorGC disposal} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add radiobutton -label "foo" -selectcolor "red"
+ .m1 entryconfigure 1 -selectcolor "green"
+} -cleanup {
+ deleteWindows
+} -result {}
+
+
+test menuDraw-7.1 {TkEventuallyRecomputeMenu} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "This is a long label"
+ set tearoff [tk::TearOffMenu .m1]
+ update idletasks
+ .m1 entryconfigure 1 -label "foo"
+} -cleanup {
+ deleteWindows
+} -result {}
+test menuDraw-7.2 {TkEventuallyRecomputeMenu - update pending} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "This is a long label"
+ set tearoff [tk::TearOffMenu .m1]
+ .m1 entryconfigure 1 -label "foo"
+} -cleanup {
+ deleteWindows
+} -result {}
+
+
+test menuDraw-8.1 {TkRecomputeMenu} -constraints {
+ win userInteraction
+} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 configure -postcommand [.m1 add command -label foo]
+ .m1 add command -label "Hit ESCAPE to make this menu go away."
+ .m1 post 0 0
+} -cleanup {
+ deleteWindows
+} -result {}
+
+
+test menuDraw-9.1 {TkEventuallyRedrawMenu - entry test} -setup {
+ deleteWindows
+} -body {
+ catch {unset foo}
+ menu .m1
+ set foo 0
+ .m1 add radiobutton -variable foo -label test
+ tk::TearOffMenu .m1
+ update idletasks
+ list [set foo test] [destroy .m1] [unset foo]
+} -result {test {} {}}
+test menuDraw-9.2 {TkEventuallyRedrawMenu - whole menu} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ tk::TearOffMenu .m1
+} -cleanup {
+ deleteWindows
+} -returnCodes ok -match glob -result *
+
+
+# Don't know how to test when window has been deleted and ComputeMenuGeometry
+# gets called.
+test menuDraw-10.1 {ComputeMenuGeometry - menubar} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label test
+ . configure -menu .m1
+ list [update idletasks] [. configure -menu ""]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+test menuDraw-10.2 {ComputeMenuGeometry - non-menubar} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label test
+ update idletasks
+} -cleanup {
+ deleteWindows
+} -result {}
+test menuDraw-10.3 {ComputeMenuGeometry - Resize necessary} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label test
+ update idletasks
+} -cleanup {
+ deleteWindows
+} -result {}
+test menuDraw-10.4 {ComputeMenuGeometry - resize not necessary} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label test
+ update idletasks
+ .m1 entryconfigure 1 -label test
+ update idletasks
+} -cleanup {
+ deleteWindows
+} -result {}
+
+
+test menuDraw-11.1 {TkMenuSelectImageProc - entry selected; redraw not pending} -constraints {
+ testImageType
+} -setup {
+ deleteWindows
+ imageCleanup
+} -body {
+ image create test image1
+ image create test image2
+ menu .m1
+ .m1 add checkbutton -image image1 -selectimage image2
+ .m1 invoke 1
+ set tearoff [tk::TearOffMenu .m1 40 40]
+ update idletasks
+ list [image delete image2] [destroy .m1]
+} -cleanup {
+ imageCleanup
+} -result {{} {}}
+test menuDraw-11.2 {TkMenuSelectImageProc - entry selected; redraw pending} -constraints {
+ testImageType
+} -setup {
+ deleteWindows
+ imageCleanup
+} -body {
+ image create test image1
+ image create test image2
+ menu .m1
+ .m1 add checkbutton -image image1 -selectimage image2
+ .m1 invoke 1
+ set tearoff [tk::TearOffMenu .m1 40 40]
+ list [image delete image2] [destroy .m1]
+} -cleanup {
+ imageCleanup
+} -result {{} {}}
+test menuDraw-11.3 {TkMenuSelectImageProc - entry not selected} -constraints {
+ testImageType
+} -setup {
+ deleteWindows
+ imageCleanup
+} -body {
+ image create test image1
+ image create test image2
+ menu .m1
+ .m1 add checkbutton -image image1 -selectimage image2
+ set tearoff [tk::TearOffMenu .m1 40 40]
+ update idletasks
+ list [image delete image2] [destroy .m1]
+} -cleanup {
+ imageCleanup
+} -result {{} {}}
+
+#Don't know how to test missing tkwin in DisplayMenu
+test menuDraw-12.1 {DisplayMenu - menubar background} -constraints unix -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add cascade -label foo -menu .m2
+ . configure -menu .m1
+ list [update] [. configure -menu ""]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+test menuDraw-12.2 {Display menu - no entries} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ set tearoff [tk::TearOffMenu .m1 40 40]
+ update
+} -cleanup {
+ deleteWindows
+} -result {}
+test menuDraw-12.3 {DisplayMenu - one entry} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label foo
+ set tearoff [tk::TearOffMenu .m1 40 40]
+ update
+} -cleanup {
+ deleteWindows
+} -result {}
+test menuDraw-12.4 {DisplayMenu - two entries} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "one"
+ .m1 add command -label "two"
+ set tearoff [tk::TearOffMenu .m1 40 40]
+ update
+} -cleanup {
+ deleteWindows
+} -result {}
+test menuDraw.12.5 {DisplayMenu - two columns - first bigger} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "one"
+ .m1 add command -label "two"
+ .m1 add command -label "three" -columnbreak 1
+ set tearoff [tk::TearOffMenu .m1 40 40]
+ update
+} -cleanup {
+ deleteWindows
+} -result {}
+test menuDraw-12.5 {DisplayMenu - two column - second bigger} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "one"
+ .m1 add command -label "two" -columnbreak 1
+ .m1 add command -label "three"
+ set tearoff [tk::TearOffMenu .m1 40 40]
+ update
+} -cleanup {
+ deleteWindows
+} -result {}
+test menuDraw.12.7 {DisplayMenu - three columns} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "one"
+ .m1 add command -label "two" -columnbreak 1
+ .m1 add command -label "three"
+ .m1 add command -label "four"
+ .m1 add command -label "five"
+ .m1 add command -label "six"
+ set tearoff [tk::TearOffMenu .m1 40 40]
+ update
+} -cleanup {
+ deleteWindows
+} -result {}
+test menuDraw-12.6 {Display menu - testing for extra space and menubars} -constraints {
+ unix
+} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add cascade -label foo
+ . configure -menu .m1
+ update
+ . configure -menu ""
+} -cleanup {
+ deleteWindows
+} -result {}
+test menuDraw-12.7 {Display menu - extra space at end of menu} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add cascade -label foo
+ set tearoff [tk::TearOffMenu .m1 40 40]
+ wm geometry $tearoff 200x100
+ update
+} -cleanup {
+ deleteWindows
+} -result {}
+
+
+test menuDraw-13.1 {TkMenuEventProc - Expose} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "one"
+ menu .m2
+ .m2 add command -label "two"
+ set tearoff1 [tk::TearOffMenu .m1 40 40]
+ set tearoff2 [tk::TearOffMenu .m2 40 40]
+ list [raise $tearoff2] [update]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+test menuDraw-13.2 {TkMenuEventProc - ConfigureNotify} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "foo"
+ set tearoff [tk::TearOffMenu .m1 40 40]
+ list [wm geometry $tearoff 200x100] [update]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+# Testing deletes is hard, and I am going to do my best. Don't know how
+# to test the case where we have already cleared the tkwin field in the
+# menuPtr.
+test menuDraw-13.4 {TkMenuEventProc - simple delete} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ destroy .m1
+} -result {}
+test menuDraw-13.5 {TkMenuEventProc - nothing pending} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label foo
+ update idletasks
+ destroy .m1
+} -result {}
+
+
+test menuDraw-14.1 {TkMenuImageProc} -constraints testImageType -setup {
+ deleteWindows
+} -body {
+ catch {image delete image1}
+ menu .m1
+ image create test image1
+ .m1 add command -image image1
+ update idletasks
+ image delete image1
+} -cleanup {
+ deleteWindows
+} -result {}
+test menuDraw-14.2 {TkMenuImageProc} -constraints testImageType -setup {
+ deleteWindows
+} -body {
+ catch {image delete image1}
+ menu .m1
+ image create test image1
+ .m1 add command -image image1
+ image delete image1
+} -cleanup {
+ deleteWindows
+} -result {}
+
+
+test menuDraw-15.1 {TkPostTearoffMenu - Basic posting} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "foo"
+ tk::TearOffMenu .m1 40 40
+} -cleanup {
+ deleteWindows
+} -returnCodes ok -match glob -result *
+test menuDraw-15.2 {TkPostTearoffMenu - Deactivation} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "foo" -state active
+ set tearoff [tk::TearOffMenu .m1 40 40]
+ $tearoff index active
+} -cleanup {
+ deleteWindows
+} -result {none}
+test menuDraw-15.3 {TkPostTearoffMenu - post command} -setup {
+ deleteWindows
+} -body {
+ catch {unset foo}
+ menu .m1 -postcommand "set foo .m1"
+ .m1 add command -label "foo"
+ list [catch {tk::TearOffMenu .m1 40 40}] [set foo] [unset foo] [destroy .m1]
+} -result {0 .m1 {} {}}
+test menuDraw-15.4 {TkPostTearoffMenu - post command deleting the menu} -setup {
+ deleteWindows
+} -body {
+ menu .m1 -postcommand "destroy .m1"
+ .m1 add command -label "foo"
+ list [catch {tk::TearOffMenu .m1 40 40} msg] $msg [winfo exists .m1]
+} -result {0 {} 0}
+test menuDraw-15.5 {TkPostTearoffMenu - tearoff at edge of screen} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "foo"
+ set height [winfo screenheight .m1]
+ tk::TearOffMenu .m1 40 $height
+} -cleanup {
+ deleteWindows
+} -returnCodes ok -match glob -result *
+test menuDraw-15.6 {TkPostTearoffMenu - tearoff off right} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add command -label "foo"
+ set width [winfo screenwidth .m1]
+ tk::TearOffMenu .m1 $width 40
+} -cleanup {
+ deleteWindows
+} -returnCodes ok -match glob -result *
+
+
+test menuDraw-16.1 {TkPostSubmenu} -constraints nonUnixUserInteraction -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add cascade -label test -menu .m2
+ menu .m2
+ .m2 add command -label "Hit ESCAPE to make this menu go away."
+ set tearoff [tk::TearOffMenu .m1 40 40]
+ $tearoff postcascade 0
+ $tearoff postcascade 0
+} -cleanup {
+ deleteWindows
+} -result {}
+test menuDraw-16.2 {TkPostSubMenu} -constraints nonUnixUserInteraction -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add cascade -label "two" -menu .m2
+ .m1 add cascade -label "three" -menu .m3
+ menu .m2
+ .m2 add command -label "two"
+ menu .m3
+ .m3 add command -label "three"
+ set tearoff [tk::TearOffMenu .m1 40 40]
+ $tearoff postcascade 0
+ $tearoff postcascade 1
+} -cleanup {
+ deleteWindows
+} -result {}
+test menuDraw-16.3 {TkPostSubMenu} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add cascade -label test -menu .m2
+ .m1 postcascade 1
+} -cleanup {
+ deleteWindows
+} -result {}
+test menuDraw-16.4 {TkPostSubMenu} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add cascade -label test
+ set tearoff [tk::TearOffMenu .m1 40 40]
+ $tearoff postcascade 0
+} -cleanup {
+ deleteWindows
+} -result {}
+test menuDraw-16.5 {TkPostSubMenu} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add cascade -label test -menu .m2
+ menu .m2 -postcommand "glorp"
+ set tearoff [tk::TearOffMenu .m1 40 40]
+ $tearoff postcascade test
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {invalid command name "glorp"}
+test menuDraw-16.6 {TkPostSubMenu} -constraints {
+ win userInteraction
+} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add cascade -label test -menu .m2
+ menu .m2
+ .m2 add command -label "Hit ESCAPE to get rid of this menu"
+ set tearoff [tk::TearOffMenu .m1 40 40]
+ $tearoff postcascade 0
+} -cleanup {
+ deleteWindows
+} -result {}
+
+
+test menuDraw-17.1 {AdjustMenuCoords - menubar} -constraints unix -setup {
+ deleteWindows
+} -body {
+ menu .m1 -tearoff 0
+ .m1 add cascade -label test -menu .m2
+ menu .m2 -tearoff 0
+ .m2 add command -label foo
+ . configure -menu .m1
+ foreach w [winfo children .] {
+ if {[$w cget -type] == "menubar"} {
+ break
+ }
+ }
+ list [$w postcascade 0] [. configure -menu ""]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+test menuDraw-17.2 {AdjustMenuCoords - menu} -constraints {
+ win userInteraction
+} -setup {
+ deleteWindows
+} -body {
+ menu .m1
+ .m1 add cascade -label test -menu .m2
+ menu .m2
+ .m2 add command -label "Hit ESCAPE to make this menu go away"
+ set tearoff [tk::TearOffMenu .m1 40 40]
+ $tearoff postcascade 0
+} -cleanup {
+ deleteWindows
+} -result {}
+
+# cleanup
+imageFinish
+deleteWindows
+cleanupTests
+return
+
+# Local variables:
+# mode: tcl
+# End:
diff --git a/tk8.6/tests/menubut.test b/tk8.6/tests/menubut.test
new file mode 100644
index 0000000..4ac5d92
--- /dev/null
+++ b/tk8.6/tests/menubut.test
@@ -0,0 +1,795 @@
+# This file is a Tcl script to test menubuttons in Tk. It is
+# organized in the standard fashion for Tcl tests.
+#
+# Copyright (c) 1994 The Regents of the University of California.
+# Copyright (c) 1994-1996 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+# XXX This test file is woefully incomplete right now. If any part
+# XXX of a procedure has tests then the whole procedure has tests,
+# XXX but many procedures have no tests.
+
+package require tcltest 2.2
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+namespace import -force tcltest::test
+imageInit
+
+# Create entries in the option database to be sure that geometry options
+# like border width have predictable values.
+
+option add *Menubutton.borderWidth 2
+option add *Menubutton.highlightThickness 2
+option add *Menubutton.font {Helvetica -12 bold}
+option add *Button.borderWidth 2
+option add *Button.highlightThickness 2
+option add *Button.font {Helvetica -12 bold}
+
+
+menubutton .mb -text "Test"
+pack .mb
+update
+test menubutton-1.1 {configuration options} -body {
+ .mb configure -activebackground #012345
+ .mb cget -activebackground
+} -cleanup {
+ .mb configure -activebackground [lindex [.mb configure -activebackground] 3]
+} -result {#012345}
+test menubutton-1.2 {configuration options} -body {
+ .mb configure -activebackground non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+test menubutton-1.3 {configuration options} -body {
+ .mb configure -activeforeground #ff0000
+ .mb cget -activeforeground
+} -cleanup {
+ .mb configure -activeforeground [lindex [.mb configure -activeforeground] 3]
+} -result {#ff0000}
+test menubutton-1.4 {configuration options} -body {
+ .mb configure -activeforeground non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+test menubutton-1.5 {configuration options} -body {
+ .mb configure -anchor nw
+ .mb cget -anchor
+} -cleanup {
+ .mb configure -anchor [lindex [.mb configure -anchor] 3]
+} -result {nw}
+test menubutton-1.6 {configuration options} -body {
+ .mb configure -anchor bogus
+} -returnCodes error -result {bad anchor "bogus": must be n, ne, e, se, s, sw, w, nw, or center}
+test menubutton-1.7 {configuration options} -body {
+ .mb configure -background #ff0000
+ .mb cget -background
+} -cleanup {
+ .mb configure -background [lindex [.mb configure -background] 3]
+} -result {#ff0000}
+test menubutton-1.8 {configuration options} -body {
+ .mb configure -background non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+test menubutton-1.9 {configuration options} -body {
+ .mb configure -bd 4
+ .mb cget -bd
+} -cleanup {
+ .mb configure -bd [lindex [.mb configure -bd] 3]
+} -result {4}
+test menubutton-1.10 {configuration options} -body {
+ .mb configure -bd badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test menubutton-1.11 {configuration options} -body {
+ .mb configure -bg #ff0000
+ .mb cget -bg
+} -cleanup {
+ .mb configure -bg [lindex [.mb configure -bg] 3]
+} -result {#ff0000}
+test menubutton-1.12 {configuration options} -body {
+ .mb configure -bg non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+test menubutton-1.13 {configuration options} -body {
+ .mb configure -bitmap questhead
+ .mb cget -bitmap
+} -cleanup {
+ .mb configure -bitmap [lindex [.mb configure -bitmap] 3]
+} -result {questhead}
+test menubutton-1.14 {configuration options} -body {
+ .mb configure -bitmap badValue
+} -returnCodes error -result {bitmap "badValue" not defined}
+test menubutton-1.15 {configuration options} -body {
+ .mb configure -borderwidth 1.3
+ .mb cget -borderwidth
+} -cleanup {
+ .mb configure -borderwidth [lindex [.mb configure -borderwidth] 3]
+} -result {1}
+test menubutton-1.16 {configuration options} -body {
+ .mb configure -borderwidth badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test menubutton-1.17 {configuration options} -body {
+ .mb configure -cursor arrow
+ .mb cget -cursor
+} -cleanup {
+ .mb configure -cursor [lindex [.mb configure -cursor] 3]
+} -result {arrow}
+test menubutton-1.18 {configuration options} -body {
+ .mb configure -cursor badValue
+} -returnCodes error -result {bad cursor spec "badValue"}
+test menubutton-1.19 {configuration options} -body {
+ .mb configure -direction below
+ .mb cget -direction
+} -cleanup {
+ .mb configure -direction [lindex [.mb configure -direction] 3]
+} -result {below}
+test menubutton-1.20 {configuration options} -body {
+ .mb configure -direction badValue
+} -returnCodes error -result {bad direction "badValue": must be above, below, flush, left, or right}
+test menubutton-1.21 {configuration options} -body {
+ .mb configure -disabledforeground #00ff00
+ .mb cget -disabledforeground
+} -cleanup {
+ .mb configure -disabledforeground [lindex [.mb configure -disabledforeground] 3]
+} -result {#00ff00}
+test menubutton-1.22 {configuration options} -body {
+ .mb configure -disabledforeground xyzzy
+} -returnCodes error -result {unknown color name "xyzzy"}
+test menubutton-1.23 {configuration options} -body {
+ .mb configure -fg #110022
+ .mb cget -fg
+} -cleanup {
+ .mb configure -fg [lindex [.mb configure -fg] 3]
+} -result {#110022}
+test menubutton-1.24 {configuration options} -body {
+ .mb configure -fg bogus
+} -returnCodes error -result {unknown color name "bogus"}
+test menubutton-1.25 {configuration options} -body {
+ .mb configure -font {Helvetica 12}
+ .mb cget -font
+} -cleanup {
+ .mb configure -font [lindex [.mb configure -font] 3]
+} -result {Helvetica 12}
+test menubutton-1.26 {configuration options} -body {
+ .mb configure -foreground #110022
+ .mb cget -foreground
+} -cleanup {
+ .mb configure -foreground [lindex [.mb configure -foreground] 3]
+} -result {#110022}
+test menubutton-1.27 {configuration options} -body {
+ .mb configure -foreground bogus
+} -returnCodes error -result {unknown color name "bogus"}
+test menubutton-1.28 {configuration options} -body {
+ .mb configure -height 18
+ .mb cget -height
+} -cleanup {
+ .mb configure -height [lindex [.mb configure -height] 3]
+} -result {18}
+test menubutton-1.29 {configuration options} -body {
+ .mb configure -height 20.0
+} -returnCodes error -result {expected integer but got "20.0"}
+test menubutton-1.30 {configuration options} -body {
+ .mb configure -highlightbackground #112233
+ .mb cget -highlightbackground
+} -cleanup {
+ .mb configure -highlightbackground [lindex [.mb configure -highlightbackground] 3]
+} -result {#112233}
+test menubutton-1.31 {configuration options} -body {
+ .mb configure -highlightbackground ugly
+} -returnCodes error -result {unknown color name "ugly"}
+test menubutton-1.32 {configuration options} -body {
+ .mb configure -highlightcolor #110022
+ .mb cget -highlightcolor
+} -cleanup {
+ .mb configure -highlightcolor [lindex [.mb configure -highlightcolor] 3]
+} -result {#110022}
+test menubutton-1.33 {configuration options} -body {
+ .mb configure -highlightcolor bogus
+} -returnCodes error -result {unknown color name "bogus"}
+test menubutton-1.34 {configuration options} -body {
+ .mb configure -highlightthickness 18
+ .mb cget -highlightthickness
+} -cleanup {
+ .mb configure -highlightthickness [lindex [.mb configure -highlightthickness] 3]
+} -result {18}
+test menubutton-1.35 {configuration options} -body {
+ .mb configure -highlightthickness badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test menubutton-1.36 {configuration options} -constraints {
+ testImageType
+} -setup {
+ catch {image delete image1}
+ image create test image1
+} -body {
+ .mb configure -image image1
+ .mb cget -image
+} -cleanup {
+ .mb configure -image [lindex [.mb configure -image] 3]
+ image create test image1
+} -result {image1}
+test menubutton-1.37 {configuration options} -setup {
+ catch {image delete bogus}
+} -body {
+ .mb configure -image bogus
+} -cleanup {
+ .mb configure -image [lindex [.mb configure -image] 3]
+} -returnCodes error -result {image "bogus" doesn't exist}
+test menubutton-1.38 {configuration options} -body {
+ .mb configure -indicatoron yes
+ .mb cget -indicatoron
+} -cleanup {
+ .mb configure -indicatoron [lindex [.mb configure -indicatoron] 3]
+} -result {1}
+test menubutton-1.39 {configuration options} -body {
+ .mb configure -indicatoron no_way
+} -returnCodes error -result {expected boolean value but got "no_way"}
+test menubutton-1.40 {configuration options} -body {
+ .mb configure -justify right
+ .mb cget -justify
+} -cleanup {
+ .mb configure -justify [lindex [.mb configure -justify] 3]
+} -result {right}
+test menubutton-1.41 {configuration options} -body {
+ .mb configure -justify bogus
+} -returnCodes error -result {bad justification "bogus": must be left, right, or center}
+test menubutton-1.42 {configuration options} -body {
+ .mb configure -menu {any old string}
+ .mb cget -menu
+} -cleanup {
+ .mb configure -menu [lindex [.mb configure -menu] 3]
+} -result {any old string}
+test menubutton-1.43 {configuration options} -body {
+ .mb configure -padx 12
+ .mb cget -padx
+} -cleanup {
+ .mb configure -padx [lindex [.mb configure -padx] 3]
+} -result {12}
+test menubutton-1.44 {configuration options} -body {
+ .mb configure -padx 420x
+} -returnCodes error -result {bad screen distance "420x"}
+test menubutton-1.45 {configuration options} -body {
+ .mb configure -pady 12
+ .mb cget -pady
+} -cleanup {
+ .mb configure -pady [lindex [.mb configure -pady] 3]
+} -result {12}
+test menubutton-1.46 {configuration options} -body {
+ .mb configure -pady 420x
+} -returnCodes error -result {bad screen distance "420x"}
+test menubutton-1.47 {configuration options} -body {
+ .mb configure -relief groove
+ .mb cget -relief
+} -cleanup {
+ .mb configure -relief [lindex [.mb configure -relief] 3]
+} -result {groove}
+test menubutton-1.48 {configuration options} -body {
+ .mb configure -relief 1.5
+} -returnCodes error -result {bad relief "1.5": must be flat, groove, raised, ridge, solid, or sunken}
+test menubutton-1.49 {configuration options} -body {
+ .mb configure -state normal
+ .mb cget -state
+} -cleanup {
+ .mb configure -state [lindex [.mb configure -state] 3]
+} -result {normal}
+test menubutton-1.50 {configuration options} -body {
+ .mb configure -state bogus
+} -returnCodes error -result {bad state "bogus": must be active, disabled, or normal}
+test menubutton-1.51 {configuration options} -body {
+ .mb configure -takefocus {any string}
+ .mb cget -takefocus
+} -cleanup {
+ .mb configure -takefocus [lindex [.mb configure -takefocus] 3]
+} -result {any string}
+test menubutton-1.52 {configuration options} -body {
+ .mb configure -text {Sample text}
+ .mb cget -text
+} -cleanup {
+ .mb configure -text [lindex [.mb configure -text] 3]
+} -result {Sample text}
+test menubutton-1.53 {configuration options} -body {
+ .mb configure -textvariable i
+ .mb cget -textvariable
+} -cleanup {
+ .mb configure -textvariable [lindex [.mb configure -textvariable] 3]
+} -result {i}
+test menubutton-1.54 {configuration options} -body {
+ .mb configure -underline 5
+ .mb cget -underline
+} -cleanup {
+ .mb configure -underline [lindex [.mb configure -underline] 3]
+} -result {5}
+test menubutton-1.55 {configuration options} -body {
+ .mb configure -underline 3p
+} -returnCodes error -result {expected integer but got "3p"}
+test menubutton-1.56 {configuration options} -body {
+ .mb configure -width 402
+ .mb cget -width
+} -cleanup {
+ .mb configure -width [lindex [.mb configure -width] 3]
+} -result {402}
+test menubutton-1.57 {configuration options} -body {
+ .mb configure -width 3p
+} -returnCodes error -result {expected integer but got "3p"}
+test menubutton-1.58 {configuration options} -body {
+ .mb configure -wraplength 100
+ .mb cget -wraplength
+} -cleanup {
+ .mb configure -wraplength [lindex [.mb configure -wraplength] 3]
+} -result {100}
+test menubutton-1.59 {configuration options} -body {
+ .mb configure -wraplength 6x
+} -returnCodes error -result {bad screen distance "6x"}
+
+
+deleteWindows
+menubutton .mb -text "Test"
+pack .mb
+update
+test menubutton-2.1 {Tk_MenubuttonCmd procedure} -body {
+ menubutton
+} -returnCodes error -result {wrong # args: should be "menubutton pathName ?-option value ...?"}
+test menubutton-2.2 {Tk_MenubuttonCmd procedure} -body {
+ menubutton foo
+} -returnCodes error -result {bad window path name "foo"}
+test menubutton-2.3 {Tk_MenubuttonCmd procedure} -body {
+ catch {destroy .mb}
+ menubutton .mb
+ winfo class .mb
+} -result {Menubutton}
+test menubutton-2.4 {Tk_ButtonCmd procedure} -setup {
+ destroy .mb
+} -body {
+ menubutton .mb -gorp foo
+} -returnCodes error -result {unknown option "-gorp"}
+test menubutton-2.5 {Tk_ButtonCmd procedure} -setup {
+ destroy .mb
+} -body {
+ catch {menubutton .mb -gorp foo}
+ winfo exists .mb
+} -result 0
+
+
+deleteWindows
+menubutton .mb -text "Test Menu"
+pack .mb
+test menubutton-3.1 {MenuButtonWidgetCmd procedure} -body {
+ .mb
+} -returnCodes error -result {wrong # args: should be ".mb option ?arg ...?"}
+test menubutton-3.2 {ButtonWidgetCmd procedure, "cget" option} -body {
+ .mb c
+} -returnCodes error -result {ambiguous option "c": must be cget or configure}
+test menubutton-3.3 {ButtonWidgetCmd procedure, "cget" option} -body {
+ .mb cget
+} -returnCodes error -result {wrong # args: should be ".mb cget option"}
+test menubutton-3.4 {ButtonWidgetCmd procedure, "cget" option} -body {
+ .mb cget a b
+} -returnCodes error -result {wrong # args: should be ".mb cget option"}
+test menubutton-3.5 {ButtonWidgetCmd procedure, "cget" option} -body {
+ .mb cget -gorp
+} -returnCodes error -result {unknown option "-gorp"}
+test menubutton-3.6 {ButtonWidgetCmd procedure, "cget" option} -body {
+ .mb configure -highlightthickness 3
+ .mb cget -highlightthickness
+} -result {3}
+test menubutton-3.7 {ButtonWidgetCmd procedure, "configure" option} -body {
+ llength [.mb configure]
+} -result {33}
+test menubutton-3.8 {ButtonWidgetCmd procedure, "configure" option} -body {
+ .mb configure -gorp
+} -returnCodes error -result {unknown option "-gorp"}
+test menubutton-3.9 {ButtonWidgetCmd procedure, "configure" option} -body {
+ .mb co -bg #ffffff -fg
+} -returnCodes error -result {value for "-fg" missing}
+test menubutton-3.10 {ButtonWidgetCmd procedure, "configure" option} -body {
+ .mb configure -fg #123456
+ .mb configure -bg #654321
+ lindex [.mb configure -fg] 4
+} -result {#123456}
+test menubutton-3.11 {ButtonWidgetCmd procedure, "configure" option} -body {
+ .mb foobar
+} -returnCodes error -result {bad option "foobar": must be cget or configure}
+deleteWindows
+
+# XXX Need to add tests for several procedures here. The tests for XXX
+# XXX ConfigureMenuButton aren't complete either. XXX
+
+test menubutton-4.1 {ConfigureMenuButton procedure} -setup {
+ deleteWindows
+} -body {
+ button .mb1 -text "Menubutton 1"
+ .mb1 configure -width 1i
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {expected integer but got "1i"}
+test menubutton-4.2 {ConfigureMenuButton procedure} -setup {
+ deleteWindows
+} -body {
+ button .mb1 -text "Menubutton 1"
+ catch {.mb1 configure -width 1i}
+ return $errorInfo
+} -cleanup {
+ deleteWindows
+} -result {expected integer but got "1i"
+ (processing -width option)
+ invoked from within
+".mb1 configure -width 1i"}
+
+test menubutton-4.3 {ConfigureMenuButton procedure} -setup {
+ deleteWindows
+} -body {
+ button .mb1 -text "Menubutton 1"
+ .mb1 configure -height 0.5c
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {expected integer but got "0.5c"}
+test menubutton-4.4 {ConfigureMenuButton procedure} -setup {
+ deleteWindows
+} -body {
+ button .mb1 -text "Menubutton 1"
+ catch {.mb1 configure -height 0.5c}
+ return $errorInfo
+} -cleanup {
+ deleteWindows
+} -result {expected integer but got "0.5c"
+ (processing -height option)
+ invoked from within
+".mb1 configure -height 0.5c"}
+
+test menubutton-4.5 {ConfigureMenuButton procedure} -setup {
+ deleteWindows
+} -body {
+ button .mb1 -bitmap questhead
+ .mb1 configure -width abc
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {bad screen distance "abc"}
+test menubutton-4.6 {ConfigureMenuButton procedure} -setup {
+ deleteWindows
+} -body {
+ button .mb1 -bitmap questhead
+ catch {.mb1 configure -width abc}
+ return $errorInfo
+} -cleanup {
+ deleteWindows
+} -result {bad screen distance "abc"
+ (processing -width option)
+ invoked from within
+".mb1 configure -width abc"}
+
+test menubutton-4.7 {ConfigureMenuButton procedure} -constraints {
+ testImageType
+} -setup {
+ deleteWindows
+ imageCleanup
+} -body {
+ image create test image1
+ button .mb1 -image image1
+ .mb1 configure -height 0.5x
+} -cleanup {
+ deleteWindows
+ imageCleanup
+} -returnCodes error -result {bad screen distance "0.5x"}
+test menubutton-4.8 {ConfigureMenuButton procedure} -constraints {
+ testImageType
+} -setup {
+ deleteWindows
+ imageCleanup
+} -body {
+ image create test image1
+ button .mb1 -image image1
+ catch {.mb1 configure -height 0.5x}
+ return $errorInfo
+} -cleanup {
+ deleteWindows
+ imageCleanup
+} -result {bad screen distance "0.5x"
+ (processing -height option)
+ invoked from within
+".mb1 configure -height 0.5x"}
+
+test menubutton-4.9 {ConfigureMenuButton procedure} -constraints {
+ nonPortable fonts
+} -setup {
+ deleteWindows
+} -body {
+ button .mb1 -text "Sample text" -width 10 -height 2
+ pack .mb1
+ set result "[winfo reqwidth .mb1] [winfo reqheight .mb1]"
+ .mb1 configure -bitmap questhead
+ lappend result [winfo reqwidth .mb1] [winfo reqheight .mb1]
+} -cleanup {
+ deleteWindows
+} -result {102 46 20 12}
+
+test menubutton-4.10 {ConfigureMenuButton procedure - bad direction} -setup {
+ deleteWindows
+} -body {
+ menubutton .mb -text "Test"
+ .mb configure -direction badValue
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {bad direction "badValue": must be above, below, flush, left, or right}
+test menubutton-4.11 {ConfigureMenuButton procedure - bad direction} -setup {
+ deleteWindows
+} -body {
+ menubutton .mb -text "Test"
+ catch {.mb configure -direction badValue}
+ list [.mb cget -direction] [destroy .mb]
+} -cleanup {
+ deleteWindows
+} -result {below {}}
+
+
+
+# XXX Need to add tests for several procedures here. XXX
+
+test menubutton-5.1 {MenuButtonEventProc procedure} -setup {
+ deleteWindows
+ set x {}
+} -body {
+ menubutton .mb1 -bg #543210
+ rename .mb1 .mb2
+ lappend x [winfo children .]
+ lappend x [.mb2 cget -bg]
+ destroy .mb1
+ lappend x [info command .mb*] [winfo children .]
+} -cleanup {
+ deleteWindows
+} -result {.mb1 #543210 {} {}}
+
+
+test menubutton-6.1 {MenuButtonCmdDeletedProc procedure} -setup {
+ deleteWindows
+} -body {
+ menubutton .mb1
+ rename .mb1 {}
+ list [info command .mb*] [winfo children .]
+} -cleanup {
+ deleteWindows
+} -result {{} {}}
+
+if {[tk windowingsystem] == "aqua"} {
+ set extraWidth 36
+} else {
+ set extraWidth 0
+}
+test menubutton-7.1 {ComputeMenuButtonGeometry procedure} -constraints {
+ testImageType
+} -setup {
+ deleteWindows
+ image create test image1
+} -body {
+ menubutton .mb -image image1 -bd 4 -highlightthickness 0
+ pack .mb
+ list [winfo reqwidth .mb] [winfo reqheight .mb]
+} -cleanup {
+ deleteWindows
+ imageCleanup
+} -result [list [expr {38 + $extraWidth}] 23]
+test menubutton-7.2 {ComputeMenuButtonGeometry procedure} -constraints {
+ testImageType
+} -setup {
+ deleteWindows
+ image create test image1
+} -body {
+ menubutton .mb -image image1 -bd 3 -highlightthickness 1
+ pack .mb
+ list [winfo reqwidth .mb] [winfo reqheight .mb]
+} -cleanup {
+ deleteWindows
+ imageCleanup
+} -result [list [expr {38 + $extraWidth}] 23]
+test menubutton-7.3 {ComputeMenuButtonGeometry procedure} -constraints {
+ testImageType
+} -setup {
+ deleteWindows
+ image create test image1
+} -body {
+ menubutton .mb -image image1 -bd 1 -highlightthickness 3 -padx 5 -pady 5
+ pack .mb
+ list [winfo reqwidth .mb] [winfo reqheight .mb]
+} -cleanup {
+ deleteWindows
+ imageCleanup
+} -result [list [expr {38 + $extraWidth}] 23]
+test menubutton-7.4 {ComputeMenuButtonGeometry procedure} -constraints {
+ testImageType
+} -setup {
+ deleteWindows
+ image create test image1
+} -body {
+ menubutton .mb -image image1 -bd 2 -relief raised -width 40 \
+ -highlightthickness 2
+ pack .mb
+ list [winfo reqwidth .mb] [winfo reqheight .mb]
+} -cleanup {
+ deleteWindows
+ imageCleanup
+} -result [list [expr {48 + $extraWidth}] 23]
+test menubutton-7.5 {ComputeMenuButtonGeometry procedure} -constraints {
+ testImageType
+} -setup {
+ deleteWindows
+ image create test image1
+} -body {
+ menubutton .mb -image image1 -bd 2 -relief raised -height 30 \
+ -highlightthickness 2
+ pack .mb
+ list [winfo reqwidth .mb] [winfo reqheight .mb]
+} -cleanup {
+ deleteWindows
+ imageCleanup
+} -result [list [expr {38 + $extraWidth}] 38]
+test menubutton-7.6 {ComputeMenuButtonGeometry procedure} -setup {
+ deleteWindows
+} -body {
+ menubutton .mb -bitmap question -bd 2 -relief raised \
+ -highlightthickness 2
+ pack .mb
+ list [winfo reqwidth .mb] [winfo reqheight .mb]
+} -cleanup {
+ deleteWindows
+} -result [list [expr {25 + $extraWidth}] 35]
+test menubutton-7.7 {ComputeMenuButtonGeometry procedure} -setup {
+ deleteWindows
+} -body {
+ menubutton .mb -bitmap question -bd 2 -relief raised -width 40 \
+ -highlightthickness 1
+ pack .mb
+ list [winfo reqwidth .mb] [winfo reqheight .mb]
+} -cleanup {
+ deleteWindows
+} -result [list [expr {46 + $extraWidth}] 33]
+test menubutton-7.8 {ComputeMenuButtonGeometry procedure} -setup {
+ deleteWindows
+} -body {
+ menubutton .mb -bitmap question -bd 2 -relief raised -height 50 \
+ -highlightthickness 1
+ pack .mb
+ list [winfo reqwidth .mb] [winfo reqheight .mb]
+} -cleanup {
+ deleteWindows
+} -result [list [expr {23 + $extraWidth}] 56]
+test menubutton-7.9 {ComputeMenuButtonGeometry procedure} -constraints {
+ fonts
+} -setup {
+ deleteWindows
+} -body {
+ menubutton .mb -text String -bd 2 -relief raised -padx 0 -pady 0 \
+ -highlightthickness 1
+ pack .mb
+ list [winfo reqwidth .mb] [winfo reqheight .mb]
+} -cleanup {
+ deleteWindows
+} -result {42 20}
+test menubutton-7.10 {ComputeMenuButtonGeometry procedure} -constraints {
+ fonts
+} -setup {
+ deleteWindows
+} -body {
+ menubutton .mb -text String -bd 2 -relief raised -width 20 \
+ -padx 0 -pady 0 -highlightthickness 1
+ pack .mb
+ list [winfo reqwidth .mb] [winfo reqheight .mb]
+} -cleanup {
+ deleteWindows
+} -result {146 20}
+test menubutton-7.11 {ComputeMenuButtonGeometry procedure} -constraints {
+ fonts
+} -setup {
+ deleteWindows
+} -body {
+ menubutton .mb -text String -bd 2 -relief raised -height 2 \
+ -padx 0 -pady 0 -highlightthickness 1
+ pack .mb
+ list [winfo reqwidth .mb] [winfo reqheight .mb]
+} -cleanup {
+ deleteWindows
+} -result {42 34}
+test menubutton-7.12 {ComputeMenuButtonGeometry procedure} -constraints {
+ fonts
+} -setup {
+ deleteWindows
+} -body {
+ menubutton .mb -text String -bd 2 -relief raised -padx 10 -pady 5 \
+ -highlightthickness 1
+ pack .mb
+ list [winfo reqwidth .mb] [winfo reqheight .mb]
+} -cleanup {
+ deleteWindows
+} -result {62 30}
+test menubutton-7.13 {ComputeMenuButtonGeometry procedure} -constraints {
+ nonPortable fonts
+} -setup {
+ deleteWindows
+} -body {
+ menubutton .mb -text String -bd 2 -relief raised \
+ -highlightthickness 1 -indicatoron 1
+ pack .mb
+ list [winfo reqwidth .mb] [winfo reqheight .mb]
+} -cleanup {
+ deleteWindows
+} -result {78 28}
+test menubutton-7.14 {ComputeMenuButtonGeometry procedure} -constraints {
+ testImageType unix nonPortable
+} -setup {
+ deleteWindows
+ image create test image1
+} -body {
+ # The following test is non-portable because the indicator's pixel
+ # size varies to maintain constant absolute size.
+
+ menubutton .mb -image image1 -bd 2 -relief raised \
+ -highlightthickness 2 -indicatoron 1
+ pack .mb
+ list [winfo reqwidth .mb] [winfo reqheight .mb]
+} -cleanup {
+ deleteWindows
+ imageCleanup
+} -result {64 23}
+test menubutton-7.15 {ComputeMenuButtonGeometry procedure} -constraints {
+ testImageType win nonPortable
+} -setup {
+ deleteWindows
+ image create test image1
+} -body {
+ # The following test is non-portable because the indicator's pixel
+ # size varies to maintain constant absolute size.
+
+ menubutton .mb -image image1 -bd 2 -relief raised \
+ -highlightthickness 2 -indicatoron 1
+ pack .mb
+ list [winfo reqwidth .mb] [winfo reqheight .mb]
+} -cleanup {
+ deleteWindows
+ imageCleanup
+} -result {65 23}
+
+
+test menubutton-8.1 {menubutton vs hidden commands} -body {
+ set l [interp hidden]
+ deleteWindows
+ menubutton .mb
+ interp hide {} .mb
+ destroy .mb
+ set res1 [list [winfo children .] [interp hidden]]
+ set res2 [list {} $l]
+ expr {$res1 eq $res2}
+} -result 1
+
+test menubutton-9.1 {Bug [5d991b822e]} {
+ # Want this not to segfault, or write to variable with empty name
+ unset -nocomplain {}
+ set var INIT
+ menubutton .b -textvariable var
+ trace add variable var unset {apply {args {
+ .b configure -textvariable {}
+ }}}
+ pack .b
+ bind .b <Configure> {unset var}
+ update
+ destroy .b
+ info exists {}
+} 0
+test menubutton-9.2 {Bug [5d991b822e]} {
+ # Want this not to leak traces
+ set var INIT
+ menubutton .b -textvariable var
+ trace add variable var unset {apply {args {
+ .b configure -textvariable new
+ }}}
+ pack .b
+ bind .b <Configure> {unset -nocomplain var}
+ update
+ destroy .b
+ unset new
+} {}
+
+
+
+
+deleteWindows
+option clear
+imageFinish
+
+# cleanup
+cleanupTests
+return
+
+# Local variables:
+# mode: tcl
+# End:
diff --git a/tk8.6/tests/message.test b/tk8.6/tests/message.test
new file mode 100644
index 0000000..b90e89c
--- /dev/null
+++ b/tk8.6/tests/message.test
@@ -0,0 +1,502 @@
+# This file is a Tcl script to test out the "message" command
+# of Tk. It is organized in the standard fashion for Tcl tests.
+#
+# Copyright (c) 1994 The Regents of the University of California.
+# Copyright (c) 1994-1996 Sun Microsystems, Inc.
+# Copyright (c) 1998-2000 by Ajuba Solutions.
+# All rights reserved.
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+tcltest::loadTestedCommands
+eval tcltest::configure $argv
+
+
+test message-1.1 {configuration option: "anchor"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -anchor w
+ .m cget -anchor
+} -cleanup {
+ destroy .m
+} -result {w}
+test message-1.2 {configuration option: "anchor"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -anchor bogus
+} -cleanup {
+ destroy .m
+} -returnCodes {error} -result {bad anchor "bogus": must be n, ne, e, se, s, sw, w, nw, or center}
+
+test message-1.3 {configuration option: "aspect"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -aspect 3
+ .m cget -aspect
+} -cleanup {
+ destroy .m
+} -result {3}
+test message-1.4 {configuration option: "aspect"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -aspect bogus
+} -cleanup {
+ destroy .m
+} -returnCodes {error} -result {expected integer but got "bogus"}
+
+test message-1.5 {configuration option: "background"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -background #ff0000
+ .m cget -background
+} -cleanup {
+ destroy .m
+} -result {#ff0000}
+test message-1.6 {configuration option: "background"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -background non-existent
+} -cleanup {
+ destroy .m
+} -returnCodes {error} -result {unknown color name "non-existent"}
+
+test message-1.7 {configuration option: "bd"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -bd 4
+ .m cget -bd
+} -cleanup {
+ destroy .m
+} -result {4}
+test message-1.8 {configuration option: "bd"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -bd badValue
+} -cleanup {
+ destroy .m
+} -returnCodes {error} -result {bad screen distance "badValue"}
+
+test message-1.9 {configuration option: "bg"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -bg #ff0000
+ .m cget -bg
+} -cleanup {
+ destroy .m
+} -result {#ff0000}
+test message-1.10 {configuration option: "bg"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -bg non-existent
+} -cleanup {
+ destroy .m
+} -returnCodes {error} -result {unknown color name "non-existent"}
+
+test message-1.11 {configuration option: "borderwidth"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -borderwidth 1.3
+ .m cget -borderwidth
+} -cleanup {
+ destroy .m
+} -result {1}
+test message-1.12 {configuration option: "borderwidth"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -borderwidth badValue
+} -cleanup {
+ destroy .m
+} -returnCodes {error} -result {bad screen distance "badValue"}
+
+test message-1.13 {configuration option: "cursor"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -cursor arrow
+ .m cget -cursor
+} -cleanup {
+ destroy .m
+} -result {arrow}
+test message-1.14 {configuration option: "cursor"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -cursor badValue
+} -cleanup {
+ destroy .m
+} -returnCodes {error} -result {bad cursor spec "badValue"}
+
+test message-1.15 {configuration option: "fg"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -fg #00ff00
+ .m cget -fg
+} -cleanup {
+ destroy .m
+} -result {#00ff00}
+test message-1.16 {configuration option: "fg"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -fg badValue
+} -cleanup {
+ destroy .m
+} -returnCodes {error} -result {unknown color name "badValue"}
+
+test message-1.17 {configuration option: "font"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -font fixed
+ .m cget -font
+} -cleanup {
+ destroy .m
+} -result {fixed}
+test message-1.18 {configuration option: "font"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -font {}
+} -cleanup {
+ destroy .m
+} -returnCodes {error} -result {font "" doesn't exist}
+
+test message-1.19 {configuration option: "-foreground"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -foreground green
+ .m cget -foreground
+} -cleanup {
+ destroy .m
+} -result {green}
+test message-1.20 {configuration option: "-foreground"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -foreground badValue
+} -cleanup {
+ destroy .m
+} -returnCodes {error} -result {unknown color name "badValue"}
+
+test message-1.21 {configuration option: "highlightbackground"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -highlightbackground #112233
+ .m cget -highlightbackground
+} -cleanup {
+ destroy .m
+} -result {#112233}
+test message-1.22 {configuration option: "highlightbackground"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -highlightbackground ugly
+} -cleanup {
+ destroy .m
+} -returnCodes {error} -result {unknown color name "ugly"}
+
+test message-1.23 {configuration option: "highlightcolor"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -highlightcolor #123456
+ .m cget -highlightcolor
+} -cleanup {
+ destroy .m
+} -result {#123456}
+test message-1.24 {configuration option: "highlightcolor"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -highlightcolor non-existent
+} -cleanup {
+ destroy .m
+} -returnCodes {error} -result {unknown color name "non-existent"}
+
+test message-1.25 {configuration option: "highlightthickness"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -highlightthickness 2
+ .m cget -highlightthickness
+} -cleanup {
+ destroy .m
+} -result {2}
+test message-1.26 {configuration option: "highlightthickness"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -highlightthickness badValue
+} -cleanup {
+ destroy .m
+} -returnCodes {error} -result {bad screen distance "badValue"}
+
+test message-1.27 {configuration option: "justify"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -justify right
+ .m cget -justify
+} -cleanup {
+ destroy .m
+} -result {right}
+test message-1.28 {configuration option: "justify"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -justify bogus
+} -cleanup {
+ destroy .m
+} -returnCodes {error} -result {bad justification "bogus": must be left, right, or center}
+
+test message-1.29 {configuration option: "padx"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -padx 12m
+ .m cget -padx
+} -cleanup {
+ destroy .m
+} -result {12m}
+test message-1.30 {configuration option: "padx"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -padx 420x
+} -cleanup {
+ destroy .m
+} -returnCodes {error} -result {bad screen distance "420x"}
+
+test message-1.31 {configuration option: "pady"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -pady 12m
+ .m cget -pady
+} -cleanup {
+ destroy .m
+} -result {12m}
+test message-1.32 {configuration option: "pady"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -pady 420x
+} -cleanup {
+ destroy .m
+} -returnCodes {error} -result {bad screen distance "420x"}
+
+test message-1.33 {configuration option: "relief"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -relief ridge
+ .m cget -relief
+} -cleanup {
+ destroy .m
+} -result {ridge}
+test message-1.34 {configuration option: "relief"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -relief badValue
+} -cleanup {
+ destroy .m
+} -returnCodes {error} -result {bad relief "badValue": must be flat, groove, raised, ridge, solid, or sunken}
+
+test message-1.35 {configuration options: "text"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -text "Sample text"
+ .m cget -text
+} -cleanup {
+ destroy .m
+} -result {Sample text}
+
+test message-1.36 {configuration option: "textvariable"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -textvariable i
+ .m cget -textvariable
+} -cleanup {
+ destroy .m
+} -result {i}
+
+test message-1.37 {configuration option: "width"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -width 2
+ .m cget -width
+} -cleanup {
+ destroy .m
+} -result {2}
+test message-1.38 {configuration option: "width"} -setup {
+ message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
+ pack .m
+ update
+} -body {
+ .m configure -width badValue
+} -cleanup {
+ destroy .m
+} -returnCodes {error} -result {bad screen distance "badValue"}
+
+
+test message-2.1 {Tk_MessageObjCmd procedure} -body {
+ message
+} -returnCodes {error} -result {wrong # args: should be "message pathName ?-option value ...?"}
+
+test message-2.2 {Tk_MessageObjCmd procedure} -body {
+ message foo
+} -returnCodes {error} -result {bad window path name "foo"}
+test message-2.3 {Tk_MessageObjCmd procedure} -body {
+ catch {message foo}
+ winfo child .
+} -result {}
+
+test message-2.4 {Tk_MessageObjCmd procedure} -body {
+ message .s -gorp dump
+} -returnCodes {error} -result {unknown option "-gorp"}
+test message-2.5 {Tk_MessageObjCmd procedure} -body {
+ catch {message .s -gorp dump}
+ winfo child .
+} -result {}
+
+
+test message-3.1 {MessageWidgetObjCmd procedure} -setup {
+ message .m
+} -body {
+ .m
+} -cleanup {
+ destroy .m
+} -returnCodes error -result {wrong # args: should be ".m option ?arg ...?"}
+test message-3.2 {MessageWidgetObjCmd procedure, "cget"} -setup {
+ message .m
+} -body {
+ .m cget
+} -cleanup {
+ destroy .m
+} -returnCodes error -result {wrong # args: should be ".m cget option"}
+test message-3.3 {MessageWidgetObjCmd procedure, "cget"} -setup {
+ message .m
+} -body {
+ .m cget -gorp
+} -cleanup {
+ destroy .m
+} -returnCodes error -result {unknown option "-gorp"}
+
+test message-3.4 {MessageWidgetObjCmd procedure, "configure"} -setup {
+ message .m
+} -body {
+ .m configure -text foobar
+ lindex [.m configure -text] 4
+} -cleanup {
+ destroy .m
+} -result {foobar}
+test message-3.5 {MessageWidgetObjCmd procedure, "configure"} -setup {
+ message .m
+} -body {
+ llength [.m configure]
+} -cleanup {
+ destroy .m
+} -result {21}
+test message-3.6 {MessageWidgetObjCmd procedure, "configure"} -setup {
+ message .m
+} -body {
+ .m configure -foo
+} -cleanup {
+ destroy .m
+} -returnCodes error -result {unknown option "-foo"}
+test message-3.7 {MessageWidgetObjCmd procedure, "configure"} -setup {
+ message .m
+} -body {
+ .m configure -bd 4
+ .m configure -bg #ffffff
+ lindex [.m configure -bd] 4
+} -cleanup {
+ destroy .m
+} -result {4}
+
+test message-4.1 {Bug [5d991b822e]} {
+ # Want this not to segfault, or write to variable with empty name
+ unset -nocomplain {}
+ set var INIT
+ message .b -textvariable var
+ trace add variable var unset {apply {args {
+ .b configure -textvariable {}
+ }}}
+ pack .b
+ bind .b <Configure> {unset var}
+ update
+ destroy .b
+ info exists {}
+} 0
+test message-4.2 {Bug [5d991b822e]} {
+ # Want this not to leak traces
+ set var INIT
+ message .b -textvariable var
+ trace add variable var unset {apply {args {
+ .b configure -textvariable new
+ }}}
+ pack .b
+ bind .b <Configure> {unset -nocomplain var}
+ update
+ destroy .b
+ unset new
+} {}
+
+cleanupTests
+return
diff --git a/tk8.6/tests/msgbox.test b/tk8.6/tests/msgbox.test
new file mode 100644
index 0000000..1b84463
--- /dev/null
+++ b/tk8.6/tests/msgbox.test
@@ -0,0 +1,447 @@
+# This file is a Tcl script to test out Tk's "tk_messageBox" command.
+# It is organized in the standard fashion for Tcl tests.
+#
+# Copyright (c) 1996 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+namespace import -force tcltest::test
+
+
+test msgbox-1.1.1 {tk_messageBox command} -constraints notAqua -body {
+ tk_messageBox -foo
+} -returnCodes error -result {bad option "-foo": must be -default, -detail, -icon, -message, -parent, -title, or -type}
+test msgbox-1.1.2 {tk_messageBox command} -constraints aqua -body {
+ tk_messageBox -foo
+} -returnCodes error -result {bad option "-foo": must be -default, -detail, -icon, -message, -parent, -title, -type, or -command}
+test msgbox-1.2.1 {tk_messageBox command} -constraints notAqua -body {
+ tk_messageBox -foo bar
+} -returnCodes error -result {bad option "-foo": must be -default, -detail, -icon, -message, -parent, -title, or -type}
+test msgbox-1.2.2 {tk_messageBox command} -constraints aqua -body {
+ tk_messageBox -foo bar
+} -returnCodes error -result {bad option "-foo": must be -default, -detail, -icon, -message, -parent, -title, -type, or -command}
+
+test msgbox-1.3 {tk_messageBox command} -body {
+ tk_messageBox -default
+} -returnCodes error -result {value for "-default" missing}
+test msgbox-1.4 {tk_messageBox command} -body {
+ tk_messageBox -detail
+} -returnCodes error -result {value for "-detail" missing}
+test msgbox-1.5 {tk_messageBox command} -body {
+ tk_messageBox -icon
+} -returnCodes error -result {value for "-icon" missing}
+test msgbox-1.6 {tk_messageBox command} -body {
+ tk_messageBox -message
+} -returnCodes error -result {value for "-message" missing}
+test msgbox-1.7 {tk_messageBox command} -body {
+ tk_messageBox -parent
+} -returnCodes error -result {value for "-parent" missing}
+test msgbox-1.8 {tk_messageBox command} -body {
+ tk_messageBox -title
+} -returnCodes error -result {value for "-title" missing}
+test msgbox-1.9 {tk_messageBox command} -body {
+ tk_messageBox -type
+} -returnCodes error -result {value for "-type" missing}
+
+test msgbox-1.10 {tk_messageBox command} -body {
+ tk_messageBox -default
+} -returnCodes error -result {value for "-default" missing}
+
+test msgbox-1.11 {tk_messageBox command} -body {
+ tk_messageBox -type foo
+} -returnCodes error -result {bad -type value "foo": must be abortretryignore, ok, okcancel, retrycancel, yesno, or yesnocancel}
+
+test msgbox-1.13 {tk_messageBox command} -body {
+ tk_messageBox -default 1.1
+} -returnCodes error -result {bad -default value "1.1": must be abort, retry, ignore, ok, cancel, no, or yes}
+
+test msgbox-1.14 {tk_messageBox command} -body {
+ tk_messageBox -default foo
+} -returnCodes error -result {bad -default value "foo": must be abort, retry, ignore, ok, cancel, no, or yes}
+
+test msgbox-1.16 {tk_messageBox command} -body {
+ tk_messageBox -type yesno -default 3
+} -returnCodes error -result {bad -default value "3": must be abort, retry, ignore, ok, cancel, no, or yes}
+
+test msgbox-1.18 {tk_messageBox command} -body {
+ tk_messageBox -icon foo
+} -returnCodes error -result {bad -icon value "foo": must be error, info, question, or warning}
+
+test msgbox-1.19 {tk_messageBox command} -body {
+ tk_messageBox -parent foo.bar
+} -returnCodes error -result {bad window path name "foo.bar"}
+
+
+catch {tk_messageBox -foo bar}
+set isNative [expr {[info commands tk::MessageBox] == ""}]
+
+proc ChooseMsg {parent btn} {
+ global isNative
+ if {!$isNative} {
+ after 100 SendEventToMsg $parent $btn mouse
+ }
+}
+
+proc ChooseMsgByKey {parent btn} {
+ global isNative
+ if {!$isNative} {
+ after 100 SendEventToMsg $parent $btn key
+ }
+}
+
+proc PressButton {btn} {
+ event generate $btn <Enter>
+ event generate $btn <ButtonPress-1> -x 5 -y 5
+ event generate $btn <ButtonRelease-1> -x 5 -y 5
+}
+
+proc SendEventToMsg {parent btn type} {
+ if {$parent != "."} {
+ set w $parent.__tk__messagebox
+ } else {
+ set w .__tk__messagebox
+ }
+ if ![winfo ismapped $w.$btn] {
+ update
+ }
+ if {$type == "mouse"} {
+ PressButton $w.$btn
+ } else {
+ event generate $w <Enter>
+ focus $w
+ event generate $w.$btn <Enter>
+ event generate $w <KeyPress> -keysym Return
+ }
+}
+#
+# Try out all combinations of (type) x (default button) and
+# (type) x (icon).
+#
+test msgbox-2.1 {tk_messageBox command} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . abort
+ tk_messageBox -title Hi -message "Please press abort" -type abortretryignore
+} -result {abort}
+test msgbox-2.2 {tk_messageBox command -icon option} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . abort
+ tk_messageBox -title Hi -message "Please press abort" \
+ -type abortretryignore -icon warning
+} -result {abort}
+test msgbox-2.3 {tk_messageBox command -icon option} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . abort
+ tk_messageBox -title Hi -message "Please press abort" \
+ -type abortretryignore -icon error
+} -result {abort}
+test msgbox-2.4 {tk_messageBox command -icon option} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . abort
+ tk_messageBox -title Hi -message "Please press abort" \
+ -type abortretryignore -icon info
+} -result {abort}
+test msgbox-2.5 {tk_messageBox command -icon option} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . abort
+ tk_messageBox -title Hi -message "Please press abort" \
+ -type abortretryignore -icon question
+} -result {abort}
+test msgbox-2.6 {tk_messageBox command} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . abort
+ tk_messageBox -title Hi -message "Please press abort" \
+ -type abortretryignore -default abort
+} -result {abort}
+test msgbox-2.7 {tk_messageBox command} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . retry
+ tk_messageBox -title Hi -message "Please press retry" \
+ -type abortretryignore -default retry
+} -result {retry}
+test msgbox-2.8 {tk_messageBox command} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . ignore
+ tk_messageBox -title Hi -message "Please press ignore" \
+ -type abortretryignore -default ignore
+} -result {ignore}
+test msgbox-2.9 {tk_messageBox command} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . ok
+ tk_messageBox -title Hi -message "Please press ok" -type ok
+} -result {ok}
+test msgbox-2.10 {tk_messageBox command -icon option} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . ok
+ tk_messageBox -title Hi -message "Please press ok" \
+ -type ok -icon warning
+} -result {ok}
+test msgbox-2.11 {tk_messageBox command -icon option} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . ok
+ tk_messageBox -title Hi -message "Please press ok" \
+ -type ok -icon error
+} -result {ok}
+test msgbox-2.12 {tk_messageBox command -icon option} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . ok
+ tk_messageBox -title Hi -message "Please press ok" \
+ -type ok -icon info
+} -result {ok}
+test msgbox-2.13 {tk_messageBox command -icon option} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . ok
+ tk_messageBox -title Hi -message "Please press ok" \
+ -type ok -icon question
+} -result {ok}
+test msgbox-2.14 {tk_messageBox command} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . ok
+ tk_messageBox -title Hi -message "Please press ok" \
+ -type ok -default ok
+} -result {ok}
+test msgbox-2.15 {tk_messageBox command} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . ok
+ tk_messageBox -title Hi -message "Please press ok" -type okcancel
+} -result {ok}
+test msgbox-2.16 {tk_messageBox command -icon option} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . ok
+ tk_messageBox -title Hi -message "Please press ok" \
+ -type okcancel -icon warning
+} -result {ok}
+test msgbox-2.17 {tk_messageBox command -icon option} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . ok
+ tk_messageBox -title Hi -message "Please press ok" \
+ -type okcancel -icon error
+} -result {ok}
+test msgbox-2.18 {tk_messageBox command -icon option} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . ok
+ tk_messageBox -title Hi -message "Please press ok" \
+ -type okcancel -icon info
+} -result {ok}
+test msgbox-2.19 {tk_messageBox command -icon option} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . ok
+ tk_messageBox -title Hi -message "Please press ok" \
+ -type okcancel -icon question
+} -result {ok}
+test msgbox-2.20 {tk_messageBox command} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . ok
+ tk_messageBox -title Hi -message "Please press ok" \
+ -type okcancel -default ok
+} -result {ok}
+test msgbox-2.21 {tk_messageBox command} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . cancel
+ tk_messageBox -title Hi -message "Please press cancel" \
+ -type okcancel -default cancel
+} -result {cancel}
+test msgbox-2.22 {tk_messageBox command} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . retry
+ tk_messageBox -title Hi -message "Please press retry" -type retrycancel
+} -result {retry}
+test msgbox-2.23 {tk_messageBox command -icon option} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . retry
+ tk_messageBox -title Hi -message "Please press retry" \
+ -type retrycancel -icon warning
+} -result {retry}
+test msgbox-2.24 {tk_messageBox command -icon option} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . retry
+ tk_messageBox -title Hi -message "Please press retry" \
+ -type retrycancel -icon error
+} -result {retry}
+test msgbox-2.25 {tk_messageBox command -icon option} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . retry
+ tk_messageBox -title Hi -message "Please press retry" \
+ -type retrycancel -icon info
+} -result {retry}
+test msgbox-2.26 {tk_messageBox command -icon option} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . retry
+ tk_messageBox -title Hi -message "Please press retry" \
+ -type retrycancel -icon question
+} -result {retry}
+test msgbox-2.27 {tk_messageBox command} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . retry
+ tk_messageBox -title Hi -message "Please press retry" \
+ -type retrycancel -default retry
+} -result {retry}
+test msgbox-2.28 {tk_messageBox command} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . cancel
+ tk_messageBox -title Hi -message "Please press cancel" \
+ -type retrycancel -default cancel
+} -result {cancel}
+test msgbox-2.29 {tk_messageBox command} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . yes
+ tk_messageBox -title Hi -message "Please press yes" -type yesno
+} -result {yes}
+test msgbox-2.30 {tk_messageBox command -icon option} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . yes
+ tk_messageBox -title Hi -message "Please press yes" \
+ -type yesno -icon warning
+} -result {yes}
+test msgbox-2.31 {tk_messageBox command -icon option} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . yes
+ tk_messageBox -title Hi -message "Please press yes" \
+ -type yesno -icon error
+} -result {yes}
+test msgbox-2.32 {tk_messageBox command -icon option} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . yes
+ tk_messageBox -title Hi -message "Please press yes" \
+ -type yesno -icon info
+} -result {yes}
+test msgbox-2.33 {tk_messageBox command -icon option} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . yes
+ tk_messageBox -title Hi -message "Please press yes" \
+ -type yesno -icon question
+} -result {yes}
+test msgbox-2.34 {tk_messageBox command} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . yes
+ tk_messageBox -title Hi -message "Please press yes" \
+ -type yesno -default yes
+} -result {yes}
+test msgbox-2.35 {tk_messageBox command} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . no
+ tk_messageBox -title Hi -message "Please press no" \
+ -type yesno -default no
+} -result {no}
+test msgbox-2.36 {tk_messageBox command} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . yes
+ tk_messageBox -title Hi -message "Please press yes" -type yesnocancel
+} -result {yes}
+test msgbox-2.37 {tk_messageBox command -icon option} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . yes
+ tk_messageBox -title Hi -message "Please press yes" \
+ -type yesnocancel -icon warning
+} -result {yes}
+test msgbox-2.38 {tk_messageBox command -icon option} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . yes
+ tk_messageBox -title Hi -message "Please press yes" \
+ -type yesnocancel -icon error
+} -result {yes}
+test msgbox-2.39 {tk_messageBox command -icon option} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . yes
+ tk_messageBox -title Hi -message "Please press yes" \
+ -type yesnocancel -icon info
+} -result {yes}
+test msgbox-2.40 {tk_messageBox command -icon option} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . yes
+ tk_messageBox -title Hi -message "Please press yes" \
+ -type yesnocancel -icon question
+} -result {yes}
+test msgbox-2.41 {tk_messageBox command} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . yes
+ tk_messageBox -title Hi -message "Please press yes" \
+ -type yesnocancel -default yes
+} -result {yes}
+test msgbox-2.42 {tk_messageBox command} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . no
+ tk_messageBox -title Hi -message "Please press no" \
+ -type yesnocancel -default no
+} -result {no}
+test msgbox-2.43 {tk_messageBox command} -constraints {
+ nonUnixUserInteraction
+} -body {
+ ChooseMsg . cancel
+ tk_messageBox -title Hi -message "Please press cancel" \
+ -type yesnocancel -default cancel
+} -result {cancel}
+
+
+# These tests will hang your test suite if they fail.
+test msgbox-3.1 {tk_messageBox handles withdrawn parent} -constraints {
+ nonUnixUserInteraction
+} -body {
+ wm withdraw .
+ ChooseMsg . "ok"
+ tk_messageBox -title Hi -message "Please press ok" \
+ -type ok -default ok
+} -cleanup {
+ wm deiconify .
+} -result {ok}
+
+test msgbox-3.2 {tk_messageBox handles iconified parent} -constraints {
+ nonUnixUserInteraction
+} -body {
+ wm iconify .
+ ChooseMsg . "ok"
+ tk_messageBox -title Hi -message "Please press ok" \
+ -type ok -default ok
+} -cleanup {
+ wm deiconify .
+} -result {ok}
+
+# cleanup
+cleanupTests
+return
+
+
diff --git a/tk8.6/tests/obj.test b/tk8.6/tests/obj.test
new file mode 100644
index 0000000..eece58e
--- /dev/null
+++ b/tk8.6/tests/obj.test
@@ -0,0 +1,28 @@
+# This file is a Tcl script to test new object types in Tk.
+# It is organized in the standard fashion for Tcl tests.
+#
+# Copyright (c) 1997 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+
+test obj-1.1 {TkGetPixelsFromObj} -body {
+} -result {}
+
+test obj-2.1 {FreePixelInternalRep} -body {
+} -result {}
+
+test obj-3.1 {DupPixelInternalRep} -body {
+} -result {}
+
+test obj-4.1 {SetPixelFromAny} -body {
+} -result {}
+
+
+# cleanup
+cleanupTests
+return
diff --git a/tk8.6/tests/oldpack.test b/tk8.6/tests/oldpack.test
new file mode 100644
index 0000000..72ec065
--- /dev/null
+++ b/tk8.6/tests/oldpack.test
@@ -0,0 +1,552 @@
+# This file is a Tcl script to test out the old syntax of Tk's
+# "pack" command (before release 3.3). It is organized in the
+# standard fashion for Tcl tests.
+#
+# Copyright (c) 1991-1994 The Regents of the University of California.
+# Copyright (c) 1994 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+namespace import -force tcltest::test
+
+# First, test a single window packed in various ways in a parent
+
+destroy .pack
+frame .pack
+place .pack -width 100 -height 100
+frame .pack.red -width 10 -height 20
+label .pack.red.l -text R -bd 2 -relief raised
+place .pack.red.l -relwidth 1.0 -relheight 1.0
+frame .pack.green -width 30 -height 40
+label .pack.green.l -text G -bd 2 -relief raised
+place .pack.green.l -relwidth 1.0 -relheight 1.0
+frame .pack.blue -width 40 -height 40
+label .pack.blue.l -text B -bd 2 -relief raised
+place .pack.blue.l -relwidth 1.0 -relheight 1.0
+frame .pack.violet -width 80 -height 20
+label .pack.violet.l -text P -bd 2 -relief raised
+place .pack.violet.l -relwidth 1.0 -relheight 1.0
+
+test oldpack-1.1 {basic positioning} -body {
+ pack ap .pack .pack.red top
+ update
+ winfo geometry .pack.red
+} -result 10x20+45+0
+test oldpack-1.2 {basic positioning} -body {
+ pack append .pack .pack.red bottom
+ update
+ winfo geometry .pack.red
+} -result 10x20+45+80
+test oldpack-1.3 {basic positioning} -body {
+ pack append .pack .pack.red left
+ update
+ winfo geometry .pack.red
+} -result 10x20+0+40
+test oldpack-1.4 {basic positioning} -body {
+ pack append .pack .pack.red right
+ update
+ winfo geometry .pack.red
+} -result 10x20+90+40
+
+# Try adding padding around the window and make sure that the
+# window gets a larger frame.
+
+test oldpack-2.1 {padding} -body {
+ pack append .pack .pack.red {t padx 20}
+ update
+ winfo geometry .pack.red
+} -result 10x20+45+0
+test oldpack-2.2 {padding} -body {
+ pack append .pack .pack.red {top pady 20}
+ update
+ winfo geometry .pack.red
+} -result 10x20+45+10
+test oldpack-2.3 {padding} -body {
+ pack append .pack .pack.red {l padx 20}
+ update
+ winfo geometry .pack.red
+} -result 10x20+10+40
+test oldpack-2.4 {padding} -body {
+ pack append .pack .pack.red {left pady 20}
+ update
+ winfo geometry .pack.red
+} -result 10x20+0+40
+
+# Position the window at different positions in its frame to
+# make sure they all work. Try two differenet frame locations,
+# to make sure that frame offsets are being added in correctly.
+
+test oldpack-3.1 {framing} -body {
+ pack append .pack .pack.red {b padx 20 pady 30}
+ update
+ winfo geometry .pack.red
+} -result 10x20+45+65
+test oldpack-3.2 {framing} -body {
+ pack append .pack .pack.red {bottom padx 20 pady 30 fr n}
+ update
+ winfo geometry .pack.red
+} -result 10x20+45+50
+test oldpack-3.3 {framing} -body {
+ pack append .pack .pack.red {bottom padx 20 pady 30 frame ne}
+ update
+ winfo geometry .pack.red
+} -result 10x20+90+50
+test oldpack-3.4 {framing} -body {
+ pack append .pack .pack.red {bottom padx 20 pady 30 frame e}
+ update
+ winfo geometry .pack.red
+} -result 10x20+90+65
+test oldpack-3.5 {framing} -body {
+ pack append .pack .pack.red {bottom padx 20 pady 30 frame se}
+ update
+ winfo geometry .pack.red
+} -result 10x20+90+80
+test oldpack-3.6 {framing} -body {
+ pack append .pack .pack.red {bottom padx 20 pady 30 frame s}
+ update
+ winfo geometry .pack.red
+} -result 10x20+45+80
+test oldpack-3.7 {framing} -body {
+ pack append .pack .pack.red {bottom padx 20 pady 30 frame sw}
+ update
+ winfo geometry .pack.red
+} -result 10x20+0+80
+test oldpack-3.8 {framing} -body {
+ pack append .pack .pack.red {bottom padx 20 pady 30 frame w}
+ update
+ winfo geometry .pack.red
+} -result 10x20+0+65
+test oldpack-3.9 {framing} -body {
+ pack append .pack .pack.red {bottom padx 20 pady 30 frame nw}
+ update
+ winfo geometry .pack.red
+} -result 10x20+0+50
+test oldpack-3.10 {framing} -body {
+ pack append .pack .pack.red {bottom padx 20 pady 30 frame c}
+ update
+ winfo geometry .pack.red
+} -result 10x20+45+65
+test oldpack-3.11 {framing} -body {
+ pack append .pack .pack.red {r padx 20 pady 30}
+ update
+ winfo geometry .pack.red
+} -result 10x20+80+40
+test oldpack-3.12 {framing} -body {
+ pack append .pack .pack.red {right padx 20 pady 30 frame n}
+ update
+ winfo geometry .pack.red
+} -result 10x20+80+0
+test oldpack-3.13 {framing} -body {
+ pack append .pack .pack.red {right padx 20 pady 30 frame ne}
+ update
+ winfo geometry .pack.red
+} -result 10x20+90+0
+test oldpack-3.14 {framing} -body {
+ pack append .pack .pack.red {right padx 20 pady 30 frame e}
+ update
+ winfo geometry .pack.red
+} -result 10x20+90+40
+test oldpack-3.15 {framing} -body {
+ pack append .pack .pack.red {right padx 20 pady 30 frame se}
+ update
+ winfo geometry .pack.red
+} -result 10x20+90+80
+test oldpack-3.16 {framing} -body {
+ pack append .pack .pack.red {right padx 20 pady 30 frame s}
+ update
+ winfo geometry .pack.red
+} -result 10x20+80+80
+test oldpack-3.17 {framing} -body {
+ pack append .pack .pack.red {right padx 20 pady 30 frame sw}
+ update
+ winfo geometry .pack.red
+} -result 10x20+70+80
+test oldpack-3.18 {framing} -body {
+ pack append .pack .pack.red {right padx 20 pady 30 frame w}
+ update
+ winfo geometry .pack.red
+} -result 10x20+70+40
+test oldpack-3.19 {framing} -body {
+ pack append .pack .pack.red {right padx 20 pady 30 frame nw}
+ update
+ winfo geometry .pack.red
+} -result 10x20+70+0
+test oldpack-3.20 {framing} -body {
+ pack append .pack .pack.red {right padx 20 pady 30 frame center}
+ update
+ winfo geometry .pack.red
+} -result 10x20+80+40
+
+# Try out various filling combinations in a couple of different
+# frame locations.
+
+test oldpack-4.1 {filling} -body {
+ pack append .pack .pack.red {bottom padx 20 pady 30 fillx}
+ update
+ winfo geometry .pack.red
+} -result 100x20+0+65
+test oldpack-4.2 {filling} -body {
+ pack append .pack .pack.red {bottom padx 20 pady 30 filly}
+ update
+ winfo geometry .pack.red
+} -result 10x50+45+50
+test oldpack-4.3 {filling} -body {
+ pack append .pack .pack.red {bottom padx 20 pady 30 fill}
+ update
+ winfo geometry .pack.red
+} -result 100x50+0+50
+test oldpack-4.4 {filling} -body {
+ pack append .pack .pack.red {right padx 20 pady 30 fillx}
+ update
+ winfo geometry .pack.red
+} -result 30x20+70+40
+test oldpack-4.5 {filling} -body {
+ pack append .pack .pack.red {right padx 20 pady 30 filly}
+ update
+ winfo geometry .pack.red
+} -result 10x100+80+0
+test oldpack-4.6 {filling} -body {
+ pack append .pack .pack.red {right padx 20 pady 30 fill}
+ update
+ winfo geometry .pack.red
+} -result 30x100+70+0
+
+# Multiple windows: make sure that space is properly subtracted
+# from the cavity as windows are positioned inwards from all
+# different sides. Also make sure that windows get unmapped if
+# there isn't enough space for them.
+
+pack append .pack .pack.red top .pack.green top .pack.blue top \
+ .pack.violet top
+update
+test oldpack-5.1 {multiple windows} -body {
+ winfo geometry .pack.red
+} -result 10x20+45+0
+test oldpack-5.2 {multiple windows} -body {
+ winfo geometry .pack.green
+} -result 30x40+35+20
+test oldpack-5.3 {multiple windows} -body {
+ winfo geometry .pack.blue
+} -result 40x40+30+60
+test oldpack-5.4 {multiple windows} -body {
+ winfo ismapped .pack.violet
+} -result 0
+
+pack b .pack.blue .pack.violet top
+update
+test oldpack-5.5 {multiple windows} -body {
+ winfo ismapped .pack.violet
+} -result 1
+test oldpack-5.6 {multiple windows} -body {
+ winfo geometry .pack.violet
+} -result 80x20+10+60
+test oldpack-5.7 {multiple windows} -body {
+ winfo geometry .pack.blue
+} -result 40x20+30+80
+
+pack after .pack.blue .pack.red top
+update
+test oldpack-5.8 {multiple windows} -body {
+ winfo geometry .pack.green
+} -result 30x40+35+0
+test oldpack-5.9 {multiple windows} -body {
+ winfo geometry .pack.violet
+} -result 80x20+10+40
+test oldpack-5.10 {multiple windows} -body {
+ winfo geometry .pack.blue
+} -result 40x40+30+60
+test oldpack-5.11 {multiple windows} -body {
+ winfo ismapped .pack.red
+} -result 0
+
+pack before .pack.green .pack.red right .pack.blue left
+update
+test oldpack-5.12 {multiple windows} -body {
+ winfo ismapped .pack.red
+} -result 1
+test oldpack-5.13 {multiple windows} -body {
+ winfo geometry .pack.red
+} -result 10x20+90+40
+test oldpack-5.14 {multiple windows} -body {
+ winfo geometry .pack.blue
+} -result 40x40+0+30
+test oldpack-5.15 {multiple windows} -body {
+ winfo geometry .pack.green
+} -result 30x40+50+0
+test oldpack-5.16 {multiple windows} -body {
+ winfo geometry .pack.violet
+} -result 50x20+40+40
+
+pack append .pack .pack.violet left .pack.green bottom .pack.red bottom \
+ .pack.blue bottom
+update
+test oldpack-5.17 {multiple windows} -body {
+ winfo geometry .pack.violet
+} -result 80x20+0+40
+test oldpack-5.18 {multiple windows} -body {
+ winfo geometry .pack.green
+} -result 20x40+80+60
+test oldpack-5.19 {multiple windows} -body {
+ winfo geometry .pack.red
+} -result 10x20+85+40
+test oldpack-5.20 {multiple windows} -body {
+ winfo geometry .pack.blue
+} -result 20x40+80+0
+
+pack after .pack.blue .pack.blue top .pack.red right .pack.green right \
+ .pack.violet right
+update
+test oldpack-5.21 {multiple windows} -body {
+ winfo geometry .pack.blue
+} -result 40x40+30+0
+test oldpack-5.22 {multiple windows} -body {
+ winfo geometry .pack.red
+} -result 10x20+90+60
+test oldpack-5.23 {multiple windows} -body {
+ winfo geometry .pack.green
+} -result 30x40+60+50
+test oldpack-5.24 {multiple windows} -body {
+ winfo geometry .pack.violet
+} -result 60x20+0+60
+
+pack after .pack.blue .pack.red left .pack.green left .pack.violet left
+update
+test oldpack-5.25 {multiple windows} -body {
+ winfo geometry .pack.blue
+} -result 40x40+30+0
+test oldpack-5.26 {multiple windows} -body {
+ winfo geometry .pack.red
+} -result 10x20+0+60
+test oldpack-5.27 {multiple windows} -body {
+ winfo geometry .pack.green
+} -result 30x40+10+50
+test oldpack-5.28 {multiple windows} -body {
+ winfo geometry .pack.violet
+} -result 60x20+40+60
+
+pack append .pack .pack.violet left .pack.green left .pack.blue left \
+ .pack.red left
+update
+test oldpack-5.29 {multiple windows} -body {
+ winfo geometry .pack.violet
+} -result 80x20+0+40
+test oldpack-5.30 {multiple windows} -body {
+ winfo geometry .pack.green
+} -result 20x40+80+30
+test oldpack-5.31 {multiple windows} -body {
+ winfo ismapped .pack.blue
+} -result 0
+test oldpack-5.32 {multiple windows} -body {
+ winfo ismapped .pack.red
+} -result 0
+
+
+# Test the ability of the packer to propagate geometry information
+# to its parent. Make sure it computes the parent's needs both in
+# the direction of packing (width for "left" and "right" windows,
+# for example), and perpendicular to the pack direction (height for
+# "left" and "right" windows).
+
+pack append .pack .pack.red top .pack.green top .pack.blue top \
+ .pack.violet top
+update
+test oldpack-6.1 {geometry propagation} -body {
+ winfo reqwidth .pack} -result 80
+test oldpack-6.2 {geometry propagation} -body {
+ winfo reqheight .pack} -result 120
+destroy .pack.violet
+update
+test oldpack-6.3 {geometry propagation} -body {
+ winfo reqwidth .pack} -result 40
+test oldpack-6.4 {geometry propagation} -body {
+ winfo reqheight .pack} -result 100
+frame .pack.violet -width 80 -height 20 -bg violet
+label .pack.violet.l -text P -bd 2 -relief raised
+place .pack.violet.l -relwidth 1.0 -relheight 1.0
+pack append .pack .pack.red left .pack.green right .pack.blue bottom \
+ .pack.violet top
+update
+test oldpack-6.5 {geometry propagation} -body {
+ winfo reqwidth .pack} -result 120
+test oldpack-6.6 {geometry propagation} -body {
+ winfo reqheight .pack} -result 60
+pack append .pack .pack.violet top .pack.green top .pack.blue left \
+ .pack.red left
+update
+test oldpack-6.7 {geometry propagation} -body {
+ winfo reqwidth .pack} -result 80
+test oldpack-6.8 {geometry propagation} -body {
+ winfo reqheight .pack} -result 100
+
+# Test the "expand" option, and make sure space is evenly divided
+# when several windows request expansion.
+
+pack append .pack .pack.violet top .pack.green {left e} \
+ .pack.blue {left expand} .pack.red {left expand}
+update
+test oldpack-7.1 {multiple expanded windows} -body {
+ pack append .pack .pack.violet top .pack.green {left e} \
+ .pack.blue {left expand} .pack.red {left expand}
+ update
+ list [winfo geometry .pack.green] [winfo geometry .pack.blue] \
+ [winfo geometry .pack.red]
+} -result {30x40+3+40 40x40+39+40 10x20+86+50}
+test oldpack-7.2 {multiple expanded windows} -body {
+ pack append .pack .pack.green left .pack.violet {bottom expand} \
+ .pack.blue {bottom expand} .pack.red {bottom expand}
+ update
+ list [winfo geometry .pack.violet] [winfo geometry .pack.blue] \
+ [winfo geometry .pack.red]
+} -result {70x20+30+77 40x40+45+30 10x20+60+3}
+test oldpack-7.3 {multiple expanded windows} -body {
+ foreach i [winfo child .pack] {
+ pack unpack $i
+ }
+ pack append .pack .pack.green {left e fill} .pack.red {left expand fill} \
+ .pack.blue {top fill}
+ update
+ list [winfo geometry .pack.green] [winfo geometry .pack.red] \
+ [winfo geometry .pack.blue]
+} -result {40x100+0+0 20x100+40+0 40x40+60+0}
+test oldpack-7.4 {multiple expanded windows} -body {
+ foreach i [winfo child .pack] {
+ pack unpack $i
+ }
+ pack append .pack .pack.red {top expand} .pack.violet {top expand} \
+ .pack.blue {right fill}
+ update
+ list [winfo geometry .pack.red] [winfo geometry .pack.violet] \
+ [winfo geometry .pack.blue]
+} -result {10x20+45+5 80x20+10+35 40x40+60+60}
+test oldpack-7.5 {multiple expanded windows} -body {
+ foreach i [winfo child .pack] {
+ pack unpack $i
+ }
+ pack append .pack .pack.green {right frame s} .pack.red {top expand}
+ update
+ list [winfo geometry .pack.green] [winfo geometry .pack.red]
+} -result {30x40+70+60 10x20+30+40}
+test oldpack-7.6 {multiple expanded windows} -body {
+ foreach i [winfo child .pack] {
+ pack unpack $i
+ }
+ pack append .pack .pack.violet {bottom frame e} .pack.red {right expand}
+ update
+ list [winfo geometry .pack.violet] [winfo geometry .pack.red]
+} -result {80x20+20+80 10x20+45+30}
+
+# Need more bizarre tests with combinations of expanded windows and
+# windows in opposing directions! Also, include padding in expanded
+# (and unexpanded) windows.
+
+# Syntax errors on pack commands
+
+test oldpack-8.1 {syntax errors} -body {
+ pack
+} -returnCodes error -result {wrong # args: should be "pack option arg ?arg ...?"}
+test oldpack-8.2 {syntax errors} -body {
+ pack append
+} -returnCodes error -result {wrong # args: should be "pack option arg ?arg ...?"}
+test oldpack-8.3 {syntax errors} -body {
+ pack gorp foo
+} -returnCodes error -result {bad option "gorp": must be configure, forget, info, propagate, or slaves}
+test oldpack-8.4 {syntax errors} -body {
+ pack a .pack
+} -returnCodes error -result {bad option "a": must be configure, forget, info, propagate, or slaves}
+test oldpack-8.5 {syntax errors} -body {
+ pack after foobar
+} -returnCodes error -result {bad window path name "foobar"}
+test oldpack-8.6 {syntax errors} -setup {
+ destroy .pack.yellow
+} -body {
+ frame .pack.yellow -bg yellow
+ pack after .pack.yellow
+} -cleanup {
+ destroy .pack.yellow
+} -returnCodes error -result {window ".pack.yellow" isn't packed}
+test oldpack-8.7 {syntax errors} -body {
+ pack append foobar
+} -returnCodes error -result {bad window path name "foobar"}
+test oldpack-8.8 {syntax errors} -body {
+ pack before foobar
+} -returnCodes error -result {bad window path name "foobar"}
+test oldpack-8.9 {syntax errors} -setup {
+ destroy .pack.yellow
+} -body {
+ frame .pack.yellow -bg yellow
+ pack before .pack.yellow
+} -cleanup {
+ destroy .pack.yellow
+} -returnCodes error -result {window ".pack.yellow" isn't packed}
+test oldpack-8.10 {syntax errors} -body {
+ pack info .pack help
+} -returnCodes error -result {wrong # args: should be "pack info window"}
+test oldpack-8.11 {syntax errors} -body {
+ pack info foobar
+} -returnCodes error -result {bad window path name "foobar"}
+test oldpack-8.12 {syntax errors} -body {
+ pack append .pack .pack.blue
+} -returnCodes error -result {wrong # args: window ".pack.blue" should be followed by options}
+test oldpack-8.13 {syntax errors} -body {
+ pack append . .pack.blue top
+} -returnCodes error -result {can't pack .pack.blue inside .}
+test oldpack-8.14 {syntax errors} -body {
+ pack append .pack .pack.blue f
+} -returnCodes error -result {bad option "f": should be top, bottom, left, right, expand, fill, fillx, filly, padx, pady, or frame}
+test oldpack-8.15 {syntax errors} -body {
+ pack append .pack .pack.blue pad
+} -returnCodes error -result {bad option "pad": should be top, bottom, left, right, expand, fill, fillx, filly, padx, pady, or frame}
+test oldpack-8.16 {syntax errors} -body {
+ pack append .pack .pack.blue {frame south}
+} -returnCodes error -result {bad anchor "south": must be n, ne, e, se, s, sw, w, nw, or center}
+test oldpack-8.17 {syntax errors} -body {
+ pack append .pack .pack.blue {padx -2}
+} -returnCodes error -result {bad pad value "-2": must be positive screen distance}
+test oldpack-8.18 {syntax errors} -body {
+ pack append .pack .pack.blue {padx}
+} -returnCodes error -result {wrong # args: "padx" option must be followed by screen distance}
+test oldpack-8.19 {syntax errors} -body {
+ pack append .pack .pack.blue {pady -2}
+} -returnCodes error -result {bad pad value "-2": must be positive screen distance}
+test oldpack-8.20 {syntax errors} -body {
+ pack append .pack .pack.blue {pady}
+} -returnCodes error -result {wrong # args: "pady" option must be followed by screen distance}
+test oldpack-8.21 {syntax errors} -body {
+ pack append .pack .pack.blue "\{abc"
+} -returnCodes error -result {unmatched open brace in list}
+test oldpack-8.22 {syntax errors} -body {
+ pack append .pack .pack.blue frame
+} -returnCodes error -result {wrong # args: "frame" option must be followed by anchor point}
+
+# Test "pack info" command output.
+
+test oldpack-9.1 {information output} -body {
+ pack append .pack .pack.blue {top fillx frame n} \
+ .pack.red {bottom filly frame s} .pack.green {left fill frame w} \
+ .pack.violet {right expand frame e}
+ list [pack slaves .pack] [pack info .pack.blue] [pack info .pack.red] \
+ [pack info .pack.green] [pack info .pack.violet]
+} -result {{.pack.blue .pack.red .pack.green .pack.violet} {-in .pack -anchor n -expand 0 -fill x -ipadx 0 -ipady 0 -padx 0 -pady 0 -side top} {-in .pack -anchor s -expand 0 -fill y -ipadx 0 -ipady 0 -padx 0 -pady 0 -side bottom} {-in .pack -anchor w -expand 0 -fill both -ipadx 0 -ipady 0 -padx 0 -pady 0 -side left} {-in .pack -anchor e -expand 1 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 0 -side right}}
+test oldpack-9.2 {information output} -body {
+ pack append .pack .pack.blue {padx 10 frame nw} \
+ .pack.red {pady 20 frame ne} .pack.green {frame se} \
+ .pack.violet {frame sw}
+ list [pack slaves .pack] [pack info .pack.blue] [pack info .pack.red] \
+ [pack info .pack.green] [pack info .pack.violet]
+} -result {{.pack.blue .pack.red .pack.green .pack.violet} {-in .pack -anchor nw -expand 0 -fill none -ipadx 0 -ipady 0 -padx 5 -pady 0 -side top} {-in .pack -anchor ne -expand 0 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 10 -side top} {-in .pack -anchor se -expand 0 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 0 -side top} {-in .pack -anchor sw -expand 0 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 0 -side top}}
+test oldpack-9.3 {information output} -body {
+ pack append .pack .pack.blue {frame center} .pack.red {frame center} \
+ .pack.green {frame c} .pack.violet {frame c}
+ list [pack slaves .pack] [pack info .pack.blue] [pack info .pack.red] \
+ [pack info .pack.green] [pack info .pack.violet]
+} -result {{.pack.blue .pack.red .pack.green .pack.violet} {-in .pack -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 0 -side top} {-in .pack -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 0 -side top} {-in .pack -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 0 -side top} {-in .pack -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 0 -side top}}
+
+destroy .pack
+
+# cleanup
+cleanupTests
+return
+
diff --git a/tk8.6/tests/option.file1 b/tk8.6/tests/option.file1
new file mode 100644
index 0000000..32b4a18
--- /dev/null
+++ b/tk8.6/tests/option.file1
@@ -0,0 +1,18 @@
+! This file is a sample option (resource) database used to test
+! Tk's option-handling capabilities.
+
+! Comment line \
+ with a backslash-newline sequence embedded in it.
+
+*x1: blue
+ tktest.x2 : green
+*\
+x3 \
+ : pur\
+ple
+*x 4: brown
+# More comments, this time delimited by hash-marks.
+ # Comment-line with space.
+*x6:
+*x9: \ \ \\\101\n
+# comment line as last line of file.
diff --git a/tk8.6/tests/option.file2 b/tk8.6/tests/option.file2
new file mode 100644
index 0000000..f1d020a
--- /dev/null
+++ b/tk8.6/tests/option.file2
@@ -0,0 +1,2 @@
+*foo1: magenta
+foo2 missing colon
diff --git a/tk8.6/tests/option.file3 b/tk8.6/tests/option.file3
new file mode 100755
index 0000000..146cfd9
--- /dev/null
+++ b/tk8.6/tests/option.file3
@@ -0,0 +1,18 @@
+! This file is a sample option (resource) database used to test
+! Tk's option-handling capabilities.
+
+! Comment line \
+ with a backslash-newline sequence embedded in it.
+
+*x1: blue
+ tktest.x2 : green
+*\
+x3 \
+ : pur\
+ple
+*x 4: brówn
+# More comments, this time delimited by hash-marks.
+ # Comment-line with space.
+*x6:
+*x9: \ \ \\\101\n
+# comment line as last line of file.
diff --git a/tk8.6/tests/option.test b/tk8.6/tests/option.test
new file mode 100644
index 0000000..c8e29da
--- /dev/null
+++ b/tk8.6/tests/option.test
@@ -0,0 +1,441 @@
+# This file is a Tcl script to test out the option-handling facilities
+# of Tk. It is organized in the standard fashion for Tcl tests.
+#
+# Copyright (c) 1991-1993 The Regents of the University of California.
+# Copyright (c) 1994 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+
+testConstraint appNameIsTktest [expr {[winfo name .] eq "tktest"}]
+
+deleteWindows
+set appName [winfo name .]
+
+# First, test basic retrievals, being sure to trigger all the various
+# types of NodeElements (EXACT_LEAF_NAME, WILDCARD_NODE_CLASS, and
+# everything in-between).
+
+frame .op1 -class Class1
+frame .op2 -class Class2
+frame .op1.op3 -class Class1
+frame .op1.op4 -class Class3
+frame .op2.op5 -class Class2
+frame .op1.op3.op6 -class Class4
+
+# Configurations for tests 1.* - 12.*
+option clear
+option add *Color1 red
+option add *x blue
+option add *Class1.x yellow
+option add $appName.op1.x green
+option add *Class2.Color1 orange
+option add $appName.op2.op5.Color2 purple
+option add $appName.Class1.Class3.y brown
+option add $appName*op6*Color2 black
+option add $appName*Class1.op1.Color2 grey
+
+test option-1.1 {basic option retrieval} -body {
+ option get . x Color1
+} -result blue
+test option-1.2 {basic option retrieval} -body {
+ option get . y Color1
+} -result red
+test option-1.3 {basic option retrieval} -body {
+ option get . z Color1
+} -result red
+test option-1.4 {basic option retrieval} -body {
+ option get . x Color2
+} -result blue
+test option-1.5 {basic option retrieval} -body {
+ option get . y Color2
+} -result {}
+test option-1.6 {basic option retrieval} -body {
+ option get . z Color2
+} -result {}
+
+
+test option-2.1 {basic option retrieval} -body {
+ option get .op1 x Color1
+} -result green
+test option-2.2 {basic option retrieval} -body {
+ option get .op1 y Color1
+} -result red
+test option-2.3 {basic option retrieval} -body {
+ option get .op1 z Color1
+} -result red
+test option-2.4 {basic option retrieval} -body {
+ option get .op1 x Color2
+} -result green
+test option-2.5 {basic option retrieval} -body {
+ option get .op1 y Color2
+} -result {}
+test option-2.6 {basic option retrieval} -body {
+ option get .op1 z Color2
+} -result {}
+
+
+test option-3.1 {basic option retrieval} -body {
+ option get .op1.op3 x Color1
+} -result yellow
+test option-3.2 {basic option retrieval} -body {
+ option get .op1.op3 y Color1
+} -result red
+test option-3.3 {basic option retrieval} -body {
+ option get .op1.op3 z Color1
+} -result red
+test option-3.4 {basic option retrieval} -body {
+ option get .op1.op3 x Color2
+} -result yellow
+test option-3.5 {basic option retrieval} -body {
+ option get .op1.op3 y Color2
+} -result {}
+test option-3.6 {basic option retrieval} -body {
+ option get .op1.op3 z Color2
+} -result {}
+
+
+test option-4.1 {basic option retrieval} -body {
+ option get .op1.op3.op6 x Color1
+} -result blue
+test option-4.2 {basic option retrieval} -body {
+ option get .op1.op3.op6 y Color1
+} -result red
+test option-4.3 {basic option retrieval} -body {
+ option get .op1.op3.op6 z Color1
+} -result red
+test option-4.4 {basic option retrieval} -body {
+ option get .op1.op3.op6 x Color2
+} -result black
+test option-4.5 {basic option retrieval} -body {
+ option get .op1.op3.op6 y Color2
+} -result black
+test option-4.6 {basic option retrieval} -body {
+ option get .op1.op3.op6 z Color2
+} -result black
+
+
+test option-5.1 {basic option retrieval} -body {
+ option get .op1.op4 x Color1
+} -result blue
+test option-5.2 {basic option retrieval} -body {
+ option get .op1.op4 y Color1
+} -result brown
+test option-5.3 {basic option retrieval} -body {
+ option get .op1.op4 z Color1
+} -result red
+test option-5.4 {basic option retrieval} -body {
+ option get .op1.op4 x Color2
+} -result blue
+test option-5.5 {basic option retrieval} -body {
+ option get .op1.op4 y Color2
+} -result brown
+test option-5.6 {basic option retrieval} -body {
+ option get .op1.op4 z Color2
+} -result {}
+
+
+test option-6.1 {basic option retrieval} -body {
+ option get .op2 x Color1
+} -result orange
+test option-6.2 {basic option retrieval} -body {
+ option get .op2 y Color1
+} -result orange
+test option-6.3 {basic option retrieval} -body {
+ option get .op2 z Color1
+} -result orange
+test option-6.4 {basic option retrieval} -body {
+ option get .op2 x Color2
+} -result blue
+test option-6.5 {basic option retrieval} -body {
+ option get .op2 y Color2
+} -result {}
+test option-6.6 {basic option retrieval} -body {
+ option get .op2 z Color2
+} -result {}
+
+
+test option-7.1 {basic option retrieval} -body {
+ option get .op2.op5 x Color1
+} -result orange
+test option-7.2 {basic option retrieval} -body {
+ option get .op2.op5 y Color1
+} -result orange
+test option-7.3 {basic option retrieval} -body {
+ option get .op2.op5 z Color1
+} -result orange
+test option-7.4 {basic option retrieval} -body {
+ option get .op2.op5 x Color2
+} -result purple
+test option-7.5 {basic option retrieval} -body {
+ option get .op2.op5 y Color2
+} -result purple
+test option-7.6 {basic option retrieval} -body {
+ option get .op2.op5 z Color2
+} -result purple
+
+
+# Now try similar tests to above, except jump around non-hierarchically
+# between windows to make sure that the option stacks are pushed and
+# popped correctly.
+
+option get . foo Foo
+test option-8.1 {stack pushing/popping} -body {
+ option get .op2.op5 x Color1
+} -result orange
+test option-8.2 {stack pushing/popping} -body {
+ option get .op2.op5 y Color1
+} -result orange
+test option-8.3 {stack pushing/popping} -body {
+ option get .op2.op5 z Color1
+} -result orange
+test option-8.4 {stack pushing/popping} -body {
+ option get .op2.op5 x Color2
+} -result purple
+test option-8.5 {stack pushing/popping} -body {
+ option get .op2.op5 y Color2
+} -result purple
+test option-8.6 {stack pushing/popping} -body {
+ option get .op2.op5 z Color2
+} -result purple
+
+
+test option-9.1 {stack pushing/popping} -body {
+ option get . x Color1
+} -result blue
+test option-9.2 {stack pushing/popping} -body {
+ option get . y Color1
+} -result red
+test option-9.3 {stack pushing/popping} -body {
+ option get . z Color1
+} -result red
+test option-9.4 {stack pushing/popping} -body {
+ option get . x Color2
+} -result blue
+test option-9.5 {stack pushing/popping} -body {
+ option get . y Color2
+} -result {}
+test option-9.6 {stack pushing/popping} -body {
+ option get . z Color2
+} -result {}
+
+
+test option-10.1 {stack pushing/popping} -body {
+ option get .op1.op3.op6 x Color1
+} -result blue
+test option-10.2 {stack pushing/popping} -body {
+ option get .op1.op3.op6 y Color1
+} -result red
+test option-10.3 {stack pushing/popping} -body {
+ option get .op1.op3.op6 z Color1
+} -result red
+test option-10.4 {stack pushing/popping} -body {
+ option get .op1.op3.op6 x Color2
+} -result black
+test option-10.5 {stack pushing/popping} -body {
+ option get .op1.op3.op6 y Color2
+} -result black
+test option-10.6 {stack pushing/popping} -body {
+ option get .op1.op3.op6 z Color2
+} -result black
+
+
+test option-11.1 {stack pushing/popping} -body {
+ option get .op1.op3 x Color1
+} -result yellow
+test option-11.2 {stack pushing/popping} -body {
+ option get .op1.op3 y Color1
+} -result red
+test option-11.3 {stack pushing/popping} -body {
+ option get .op1.op3 z Color1
+} -result red
+test option-11.4 {stack pushing/popping} -body {
+ option get .op1.op3 x Color2
+} -result yellow
+test option-11.5 {stack pushing/popping} -body {
+ option get .op1.op3 y Color2
+} -result {}
+test option-11.6 {stack pushing/popping} -body {
+ option get .op1.op3 z Color2
+} -result {}
+
+
+test option-12.1 {stack pushing/popping} -body {
+ option get .op1 x Color1
+} -result green
+test option-12.2 {stack pushing/popping} -body {
+ option get .op1 y Color1
+} -result red
+test option-12.3 {stack pushing/popping} -body {
+ option get .op1 z Color1
+} -result red
+test option-12.4 {stack pushing/popping} -body {
+ option get .op1 x Color2
+} -result green
+test option-12.5 {stack pushing/popping} -body {
+ option get .op1 y Color2
+} -result {}
+test option-12.6 {stack pushing/popping} -body {
+ option get .op1 z Color2
+} -result {}
+
+# Test the major priority levels (widgetDefault, etc.)
+
+# Configurations for tests 13.*
+option clear
+option add $appName.op1.a 100 100
+option add $appName.op1.A interactive interactive
+option add $appName.op1.b userDefault userDefault
+option add $appName.op1.B startupFile startupFile
+option add $appName.op1.c widgetDefault widgetDefault
+option add $appName.op1.C 0 0
+
+test option-13.1 {priority levels} -body {
+ option get .op1 a A
+} -result 100
+test option-13.2 {priority levels} -body {
+ option get .op1 b A
+} -result interactive
+test option-13.3 {priority levels} -body {
+ option get .op1 b B
+} -result userDefault
+test option-13.4 {priority levels} -body {
+ option get .op1 c B
+} -result startupFile
+test option-13.5 {priority levels} -body {
+ option get .op1 c C
+} -result widgetDefault
+option add $appName.op1.B file2 widget
+test option-13.6 {priority levels} -body {
+ option get .op1 c B
+} -result startupFile
+option add $appName.op1.B file2 startupFile
+test option-13.7 {priority levels} -body {
+ option get .op1 c B
+} -result file2
+
+
+# Test various error conditions
+
+test option-14.1 {error conditions} -body {
+ option
+} -returnCodes error -result {wrong # args: should be "option cmd arg ?arg ...?"}
+test option-14.2 {error conditions} -body {
+ option x
+} -returnCodes error -result {bad option "x": must be add, clear, get, or readfile}
+test option-14.3 {error conditions} -body {
+ option foo 3
+} -returnCodes error -result {bad option "foo": must be add, clear, get, or readfile}
+test option-14.4 {error conditions} -body {
+ option add 3
+} -returnCodes error -result {wrong # args: should be "option add pattern value ?priority?"}
+test option-14.5 {error conditions} -body {
+ option add . a b c
+} -returnCodes error -result {wrong # args: should be "option add pattern value ?priority?"}
+test option-14.6 {error conditions} -body {
+ option add . a -1
+} -returnCodes error -result {bad priority level "-1": must be widgetDefault, startupFile, userDefault, interactive, or a number between 0 and 100}
+test option-14.7 {error conditions} -body {
+ option add . a 101
+} -returnCodes error -result {bad priority level "101": must be widgetDefault, startupFile, userDefault, interactive, or a number between 0 and 100}
+test option-14.8 {error conditions} -body {
+ option add . a gorp
+} -returnCodes error -result {bad priority level "gorp": must be widgetDefault, startupFile, userDefault, interactive, or a number between 0 and 100}
+test option-14.9 {error conditions} -body {
+ option get 3
+} -returnCodes error -result {wrong # args: should be "option get window name class"}
+test option-14.10 {error conditions} -body {
+ option get 3 4
+} -returnCodes error -result {wrong # args: should be "option get window name class"}
+test option-14.11 {error conditions} -body {
+ option get 3 4 5 6
+} -returnCodes error -result {wrong # args: should be "option get window name class"}
+test option-14.12 {error conditions} -body {
+ option get .gorp.gorp a A
+} -returnCodes error -result {bad window path name ".gorp.gorp"}
+
+
+set option1 [file join [testsDirectory] option.file1]
+test option-15.1 {database files} -body {
+ option read non-existent
+} -returnCodes error -result {couldn't open "non-existent": no such file or directory}
+test option-15.2 {database files} -body {
+ option read $option1
+ option get . x1 color
+} -result blue
+test option-15.3 {database files} -constraints appNameIsTktest -body {
+ option read $option1
+ option get . x2 color
+} -result green
+test option-15.4 {database files} -body {
+ option read $option1
+ option get . x3 color
+} -result purple
+test option-15.5 {database files} -body {
+ option read $option1
+ option get . {x 4} color
+} -result brown
+test option-15.6 {database files} -body {
+ option read $option1
+ option get . x6 color
+} -result {}
+test option-15.7 {database files} -body {
+ option read $option1
+ option get . x9 color
+} -result " \\\t\\A\n"
+test option-15.8 {database files} -body {
+ option read $option1 widget foo
+} -returnCodes error -result {wrong # args: should be "option readfile fileName ?priority?"}
+test option-15.9 {database files} -body {
+ option add *x3 burgundy
+ catch {option read $option1 userDefault}
+ option get . x3 color
+} -result burgundy
+test option-15.10 {database files} -body {
+ set option2 [file join [testsDirectory] option.file2]
+ option read $option2
+} -returnCodes error -result {missing colon on line 2}
+set option3 [file join [testsDirectory] option.file3]
+option read $option3
+test option-15.11 {database files} {option get . {x 4} color} br\xf3wn
+
+test option-16.1 {ReadOptionFile} -body {
+ set option4 [makeFile {} option.file3]
+ set file [open $option4 w]
+ fconfigure $file -translation crlf
+ puts $file "*x7: true\n*x8: false"
+ close $file
+ option read $option4 userDefault
+ list [option get . x7 color] [option get . x8 color]
+} -cleanup {
+ removeFile $option4
+} -result {true false}
+
+set opt162val {label {
+ foo bar
+}
+}
+set opt162list [split $opt162val \n]
+
+test option-16.2 {ticket 766ef52f3} {
+ set option5 [makeFile {} option.file4]
+ set file [open $option5 w]
+ fconfigure $file -translation crlf
+ puts $file "*notok: $opt162list"
+ close $file
+ option read $option5 userDefault
+ option get . notok notok
+} $opt162list
+
+deleteWindows
+
+# cleanup
+cleanupTests
+return
+
+
+
diff --git a/tk8.6/tests/pack.test b/tk8.6/tests/pack.test
new file mode 100644
index 0000000..b1c22c7
--- /dev/null
+++ b/tk8.6/tests/pack.test
@@ -0,0 +1,1656 @@
+# This file is a Tcl script to test out the "pack" command
+# of Tk. It is organized in the standard fashion for Tcl tests.
+#
+# Copyright (c) 1993 The Regents of the University of California.
+# Copyright (c) 1994 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+namespace import -force tcltest::test
+
+
+# Create some test windows.
+
+destroy .pack
+toplevel .pack
+wm geom .pack 300x200+0+0
+wm minsize .pack 1 1
+update idletasks
+foreach i {a b c d} {
+ frame .pack.$i
+ label .pack.$i.label -text $i -relief raised
+ place .pack.$i.label -relwidth 1.0 -relheight 1.0
+}
+.pack.a config -width 20 -height 40
+.pack.b config -width 50 -height 30
+.pack.c config -width 80 -height 80
+.pack.d config -width 40 -height 30
+
+test pack-1.1 {-side option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x40+140+0 300x160+0+40}
+test pack-1.2 {-side option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side bottom
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x40+140+160 300x160+0+0}
+test pack-1.3 {-side option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side left
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x40+0+80 280x200+20+0}
+test pack-1.4 {-side option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side right
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x40+280+80 280x200+0+0}
+
+
+test pack-2.1 {x padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side right -padx 20
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x40+260+80 240x200+0+0}
+test pack-2.2 {x padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side right -padx {10 30}
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x40+250+80 240x200+0+0}
+test pack-2.3 {x padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side right -padx {35 5}
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x40+275+80 240x200+0+0}
+test pack-2.4 {x padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side right -ipadx 20
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {60x40+240+80 240x200+0+0}
+test pack-2.5 {x padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side right -ipadx 5 -padx 10
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {30x40+260+80 250x200+0+0}
+test pack-2.6 {x padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side right -padx 20 -fill x
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x40+260+80 240x200+0+0}
+test pack-2.7 {x padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side right -padx {9 31} -fill x
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x40+249+80 240x200+0+0}
+test pack-2.8 {x padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side right -ipadx 20 -fill x
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {60x40+240+80 240x200+0+0}
+test pack-2.9 {x padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side right -ipadx 5 -padx 10 -fill x
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {30x40+260+80 250x200+0+0}
+test pack-2.10 {x padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side right -ipadx 5 -padx {5 15} -fill x
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {30x40+255+80 250x200+0+0}
+test pack-2.11 {x padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -padx 20
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x40+140+0 300x160+0+40}
+test pack-2.12 {x padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -padx {0 40}
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x40+120+0 300x160+0+40}
+test pack-2.13 {x padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -padx {31 9}
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x40+151+0 300x160+0+40}
+test pack-2.14 {x padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -ipadx 20
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {60x40+120+0 300x160+0+40}
+test pack-2.15 {x padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -ipadx 5 -padx 10
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {30x40+135+0 300x160+0+40}
+test pack-2.16 {x padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -ipadx 5 -padx {5 15}
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {30x40+130+0 300x160+0+40}
+test pack-2.17 {x padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -padx 20 -fill x
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {260x40+20+0 300x160+0+40}
+test pack-2.18 {x padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -padx {25 15} -fill x
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {260x40+25+0 300x160+0+40}
+test pack-2.19 {x padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -ipadx 20 -fill x
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {300x40+0+0 300x160+0+40}
+test pack-2.20 {x padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -ipadx 5 -padx 10 -fill x
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {280x40+10+0 300x160+0+40}
+test pack-2.21 {x padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -ipadx 5 -padx {5 15} -fill x
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {280x40+5+0 300x160+0+40}
+
+test pack-2.22 {x padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -padx 1c
+ set x [pack info .pack.a]
+ set res1 [lindex $x [expr [lsearch -exact $x -padx]+1]]
+ set res2 [winfo pixels .pack 1c]
+ expr {$res1 eq $res2}
+} -result 1
+test pack-2.23 {x padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -ipadx 1c
+ set x [pack info .pack.a]
+ set res1 [lindex $x [expr [lsearch -exact $x -ipadx]+1]]
+ set res2 [winfo pixels .pack 1c]
+ expr {$res1 eq $res2}
+} -result 1
+
+
+test pack-3.1 {y padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side right -pady 20
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x40+280+80 280x200+0+0}
+test pack-3.2 {y padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side right -pady {5 35}
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x40+280+65 280x200+0+0}
+test pack-3.3 {y padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side right -pady {40 0}
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x40+280+100 280x200+0+0}
+test pack-3.4 {y padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side right -ipady 20
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x80+280+60 280x200+0+0}
+test pack-3.5 {y padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side right -ipady 5 -pady 10
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x50+280+75 280x200+0+0}
+test pack-3.6 {y padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side right -ipady 5 -pady {5 15}
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x50+280+70 280x200+0+0}
+test pack-3.7 {y padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side right -pady 20 -fill y
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x160+280+20 280x200+0+0}
+test pack-3.8 {y padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side right -pady {35 5} -fill y
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x160+280+35 280x200+0+0}
+test pack-3.9 {y padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side right -ipady 20 -fill y
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x200+280+0 280x200+0+0}
+test pack-3.10 {y padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side right -ipady 5 -pady 10 -fill y
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x180+280+10 280x200+0+0}
+test pack-3.11 {y padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side right -ipady 5 -pady {0 20} -fill y
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x180+280+0 280x200+0+0}
+test pack-3.12 {y padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -pady 20
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x40+140+20 300x120+0+80}
+test pack-3.13 {y padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -pady {40 0}
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x40+140+40 300x120+0+80}
+test pack-3.14 {y padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -ipady 20
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x80+140+0 300x120+0+80}
+test pack-3.15 {y padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -ipady 5 -pady 10
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x50+140+10 300x130+0+70}
+test pack-3.16 {y padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -ipady 5 -pady {3 17}
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x50+140+3 300x130+0+70}
+test pack-3.17 {y padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -pady 20 -fill y
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x40+140+20 300x120+0+80}
+test pack-3.18 {y padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -pady {39 1} -fill y
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x40+140+39 300x120+0+80}
+test pack-3.19 {y padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -ipady 20 -fill y
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x80+140+0 300x120+0+80}
+test pack-3.20 {y padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -ipady 5 -pady 10 -fill y
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x50+140+10 300x130+0+70}
+test pack-3.21 {y padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -ipady 5 -pady {1 19} -fill y
+ pack .pack.b -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b]
+} -result {20x50+140+1 300x130+0+70}
+
+test pack-3.22 {y padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -pady 1c
+ set x [pack info .pack.a]
+ set res1 [lindex $x [expr [lsearch -exact $x -pady]+1]]
+ set res2 [winfo pixels .pack 1c]
+ expr {$res1 eq $res2}
+} -result 1
+test pack-3.23 {y padding and filling} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -ipady 1c
+ set x [pack info .pack.a]
+ set res1 [lindex $x [expr [lsearch -exact $x -ipady]+1]]
+ set res2 [winfo pixels .pack 1c]
+ expr {$res1 eq $res2}
+} -result 1
+
+
+test pack-4.1 {anchors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor n
+ update
+ winfo geometry .pack.a
+} -result {30x70+135+20}
+test pack-4.2 {anchors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor ne
+ update
+ winfo geometry .pack.a
+} -result {30x70+260+20}
+test pack-4.3 {anchors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor e
+ update
+ winfo geometry .pack.a
+} -result {30x70+260+65}
+test pack-4.4 {anchors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor se
+ update
+ winfo geometry .pack.a
+} -result {30x70+260+110}
+test pack-4.5 {anchors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor s
+ update
+ winfo geometry .pack.a
+} -result {30x70+135+110}
+test pack-4.6 {anchors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor sw
+ update
+ winfo geometry .pack.a
+} -result {30x70+10+110}
+test pack-4.7 {anchors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor w
+ update
+ winfo geometry .pack.a
+} -result {30x70+10+65}
+test pack-4.8 {anchors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor nw
+ update
+ winfo geometry .pack.a
+} -result {30x70+10+20}
+test pack-4.9 {anchors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor center
+ update
+ winfo geometry .pack.a
+} -result {30x70+135+65}
+
+
+# Repeat above tests, but with a frame that isn't at (0,0), so that
+# we can be sure that the frame offset is being added in correctly.
+
+test pack-5.1 {more anchors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top
+ pack .pack.c -side left
+ pack .pack.b -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor n
+ update
+ winfo geometry .pack.b
+} -result {60x60+160+60}
+test pack-5.2 {more anchors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top
+ pack .pack.c -side left
+ pack .pack.b -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor ne
+ update
+ winfo geometry .pack.b
+} -result {60x60+230+60}
+test pack-5.3 {more anchors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top
+ pack .pack.c -side left
+ pack .pack.b -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor e
+ update
+ winfo geometry .pack.b
+} -result {60x60+230+90}
+test pack-5.4 {more anchors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top
+ pack .pack.c -side left
+ pack .pack.b -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor se
+ update
+ winfo geometry .pack.b
+} -result {60x60+230+120}
+test pack-5.5 {more anchors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top
+ pack .pack.c -side left
+ pack .pack.b -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor s
+ update
+ winfo geometry .pack.b
+} -result {60x60+160+120}
+test pack-5.6 {more anchors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top
+ pack .pack.c -side left
+ pack .pack.b -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor sw
+ update
+ winfo geometry .pack.b
+} -result {60x60+90+120}
+test pack-5.7 {more anchors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top
+ pack .pack.c -side left
+ pack .pack.b -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor w
+ update
+ winfo geometry .pack.b
+} -result {60x60+90+90}
+test pack-5.8 {more anchors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top
+ pack .pack.c -side left
+ pack .pack.b -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor nw
+ update
+ winfo geometry .pack.b
+} -result {60x60+90+60}
+test pack-5.9 {more anchors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top
+ pack .pack.c -side left
+ pack .pack.b -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor center
+ update
+ winfo geometry .pack.b
+} -result {60x60+160+90}
+
+
+test pack-6.1 {-expand option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a .pack.b .pack.c .pack.d -side left
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b] \
+ [winfo geometry .pack.c] [winfo geometry .pack.d]
+} -result {20x40+0+80 50x30+20+85 80x80+70+60 40x30+150+85}
+test pack-6.2 {-expand option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side left -expand yes
+ pack .pack.b -side left
+ pack .pack.c .pack.d -side left -expand 1
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b] \
+ [winfo geometry .pack.c] [winfo geometry .pack.d]
+} -result {20x40+18+80 50x30+56+85 80x80+124+60 40x30+241+85}
+test pack-6.3 {-expand option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a .pack.b .pack.c .pack.d -side top
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b] \
+ [winfo geometry .pack.c] [winfo geometry .pack.d]
+} -result {20x40+140+0 50x30+125+40 80x80+110+70 40x30+130+150}
+test pack-6.4 {-expand option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -expand yes
+ pack .pack.b -side top
+ pack .pack.c .pack.d -side top -expand 1
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b] \
+ [winfo geometry .pack.c] [winfo geometry .pack.d]
+} -result {20x40+140+3 50x30+125+46 80x80+110+79 40x30+130+166}
+test pack-6.5 {-expand option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a .pack.b .pack.c .pack.d -side right
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b] \
+ [winfo geometry .pack.c] [winfo geometry .pack.d]
+} -result {20x40+280+80 50x30+230+85 80x80+150+60 40x30+110+85}
+test pack-6.6 {-expand option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side right -expand yes
+ pack .pack.b -side right
+ pack .pack.c .pack.d -side right -expand 1
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b] \
+ [winfo geometry .pack.c] [winfo geometry .pack.d]
+} -result {20x40+262+80 50x30+194+85 80x80+95+60 40x30+18+85}
+test pack-6.7 {-expand option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a .pack.b .pack.c .pack.d -side bottom
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b] \
+ [winfo geometry .pack.c] [winfo geometry .pack.d]
+} -result {20x40+140+160 50x30+125+130 80x80+110+50 40x30+130+20}
+test pack-6.8 {-expand option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side bottom -expand yes
+ pack .pack.b -side bottom
+ pack .pack.c .pack.d -side bottom -expand 1
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b] \
+ [winfo geometry .pack.c] [winfo geometry .pack.d]
+} -result {20x40+140+157 50x30+125+124 80x80+110+40 40x30+130+3}
+test pack-6.9 {-expand option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side bottom -expand yes -fill both
+ pack .pack.b -side right
+ pack .pack.c -side top -expand 1 -fill both
+ pack .pack.d -side left
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b] \
+ [winfo geometry .pack.c] [winfo geometry .pack.d]
+} -result {300x65+0+135 50x30+250+52 250x105+0+0 40x30+0+105}
+test pack-6.10 {-expand option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side left -expand yes -fill both
+ pack .pack.b -side top
+ pack .pack.c -side right -expand 1 -fill both
+ pack .pack.d -side bottom
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b] \
+ [winfo geometry .pack.c] [winfo geometry .pack.d]
+} -result {100x200+0+0 50x30+175+0 160x170+140+30 40x30+100+170}
+test pack-6.11 {-expand option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side left -expand yes -fill both
+ pack .pack.b -side top -expand yes -fill both
+ pack .pack.c -side right -expand 1 -fill both
+ pack .pack.d -side bottom -expand yes -fill both
+ update
+ list [winfo geometry .pack.a] [winfo geometry .pack.b] \
+ [winfo geometry .pack.c] [winfo geometry .pack.d]
+} -result {100x200+0+0 200x100+100+0 160x100+140+100 40x100+100+100}
+
+test pack-6.12 {-expand option} -setup {
+ toplevel .pack2 -height 400 -width 400
+ wm geometry .pack2 +0+0
+ pack propagate .pack2 0
+ foreach i {w1 w2 w3} {
+ frame .pack2.$i -width 30 -height 30 -bd 2 -relief raised
+ label .pack2.$i.l -text $i
+ place .pack2.$i.l -relwidth 1.0 -relheight 1.0
+ }
+} -body {
+ pack .pack2.w1 .pack2.w2 .pack2.w3 -padx 5 -ipadx 4 -pady 2 -ipady 6 -expand 1 -side left
+ update
+ list [winfo geometry .pack2.w1] [winfo geometry .pack2.w2] [winfo geometry .pack2.w3]
+} -cleanup {
+ destroy .pack2
+} -result {38x42+47+179 38x42+180+179 38x42+314+179}
+test pack-6.13 {-expand option} -setup {
+ toplevel .pack2 -height 400 -width 400
+ wm geometry .pack2 +0+0
+ pack propagate .pack2 0
+ foreach i {w1 w2 w3} {
+ frame .pack2.$i -width 30 -height 30 -bd 2 -relief raised
+ label .pack2.$i.l -text $i
+ place .pack2.$i.l -relwidth 1.0 -relheight 1.0
+ }
+} -body {
+ pack .pack2.w1 .pack2.w2 .pack2.w3 -padx 5 -ipadx 4 -pady 2 \
+ -ipady 6 -expand 1 -side top
+ update
+ list [winfo geometry .pack2.w1] [winfo geometry .pack2.w2] [winfo geometry .pack2.w3]
+} -cleanup {
+ destroy .pack2
+} -result {38x42+181+45 38x42+181+178 38x42+181+312}
+
+
+wm geometry .pack {}
+test pack-7.1 {requesting size for parent} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a .pack.b .pack.c .pack.d -side left -padx 5 -pady 10
+ update
+ list [winfo reqwidth .pack] [winfo reqheight .pack]
+} -result {230 100}
+test pack-7.2 {requesting size for parent} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a .pack.b .pack.c .pack.d -side top -padx 5 -pady 10
+ update
+ list [winfo reqwidth .pack] [winfo reqheight .pack]
+} -result {90 260}
+test pack-7.3 {requesting size for parent} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a .pack.b .pack.c .pack.d -side right -padx 5 -pady 10
+ update
+ list [winfo reqwidth .pack] [winfo reqheight .pack]
+} -result {230 100}
+test pack-7.4 {requesting size for parent} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a .pack.b .pack.c .pack.d -side bottom -padx 5 -pady 10
+ update
+ list [winfo reqwidth .pack] [winfo reqheight .pack]
+} -result {90 260}
+test pack-7.5 {requesting size for parent} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top -padx 5 -pady 10
+ pack .pack.b -side right -padx 5 -pady 10
+ pack .pack.c -side bottom -padx 5 -pady 10
+ pack .pack.d -side left -padx 5 -pady 10
+ update
+ list [winfo reqwidth .pack] [winfo reqheight .pack]
+} -result {150 210}
+test pack-7.6 {requesting size for parent} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top
+ pack .pack.c -side left
+ pack .pack.d -side bottom
+ update
+ list [winfo reqwidth .pack] [winfo reqheight .pack]
+} -result {120 120}
+test pack-7.7 {requesting size for parent} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side right
+ pack .pack.c -side bottom
+ pack .pack.d -side top
+ update
+ list [winfo reqwidth .pack] [winfo reqheight .pack]
+} -result {100 110}
+
+
+# For the tests below, create a couple of "pad" windows to shrink
+# the available space for the remaining windows. The tests have to
+# be done this way rather than shrinking the whole window, because
+# some window managers like mwm won't let a top-level window get
+# very small.
+
+pack forget .pack.a .pack.b .pack.c .pack.d
+frame .pack.right -width 200 -height 10 -bd 2 -relief raised
+frame .pack.bottom -width 10 -height 150 -bd 2 -relief raised
+pack .pack.right -side right
+pack .pack.bottom -side bottom
+pack .pack.a .pack.b .pack.c -side top
+update
+test pack-8.1 {insufficient space} -body {
+ list [winfo geometry .pack.a] [winfo ismapped .pack.a] \
+ [winfo geometry .pack.b] [winfo ismapped .pack.b] \
+ [winfo geometry .pack.c] [winfo ismapped .pack.c]
+} -result {20x40+30+0 1 50x30+15+40 1 80x80+0+70 1}
+wm geom .pack 270x250
+update
+test pack-8.2 {insufficient space} -body {
+ list [winfo geometry .pack.a] [winfo ismapped .pack.a] \
+ [winfo geometry .pack.b] [winfo ismapped .pack.b] \
+ [winfo geometry .pack.c] [winfo ismapped .pack.c]
+} -result {20x40+25+0 1 50x30+10+40 1 70x30+0+70 1}
+wm geom .pack 240x220
+update
+test pack-8.3 {insufficient space} -body {
+ list [winfo geometry .pack.a] [winfo ismapped .pack.a] \
+ [winfo geometry .pack.b] [winfo ismapped .pack.b] \
+ [winfo geometry .pack.c] [winfo ismapped .pack.c]
+} -result {20x40+10+0 1 40x30+0+40 1 70x30+0+70 0}
+wm geom .pack 350x350
+update
+test pack-8.4 {insufficient space} -body {
+ list [winfo geometry .pack.a] [winfo ismapped .pack.a] \
+ [winfo geometry .pack.b] [winfo ismapped .pack.b] \
+ [winfo geometry .pack.c] [winfo ismapped .pack.c]
+} -result {20x40+65+0 1 50x30+50+40 1 80x80+35+70 1}
+wm geom .pack {}
+pack .pack.a -side left
+pack .pack.b -side right
+pack .pack.c -side left
+update
+test pack-8.5 {insufficient space} -body {
+ list [winfo geometry .pack.a] [winfo ismapped .pack.a] \
+ [winfo geometry .pack.b] [winfo ismapped .pack.b] \
+ [winfo geometry .pack.c] [winfo ismapped .pack.c]
+} -result {20x40+0+20 1 50x30+100+25 1 80x80+20+0 1}
+wm geom .pack 320x180
+update
+test pack-8.6 {insufficient space} -body {
+ list [winfo geometry .pack.a] [winfo ismapped .pack.a] \
+ [winfo geometry .pack.b] [winfo ismapped .pack.b] \
+ [winfo geometry .pack.c] [winfo ismapped .pack.c]
+} -result {20x30+0+0 1 50x30+70+0 1 50x30+20+0 1}
+wm geom .pack 250x180
+update
+test pack-8.7 {insufficient space} -body {
+ list [winfo geometry .pack.a] [winfo ismapped .pack.a] \
+ [winfo geometry .pack.b] [winfo ismapped .pack.b] \
+ [winfo geometry .pack.c] [winfo ismapped .pack.c]
+} -result {20x30+0+0 1 30x30+20+0 1 50x30+20+0 0}
+pack forget .pack.b
+update
+test pack-8.8 {insufficient space} -body {
+ list [winfo geometry .pack.a] [winfo ismapped .pack.a] \
+ [winfo geometry .pack.b] [winfo ismapped .pack.b] \
+ [winfo geometry .pack.c] [winfo ismapped .pack.c]
+} -result {20x30+0+0 1 30x30+20+0 0 30x30+20+0 1}
+pack .pack.b -side right -after .pack.a
+wm geom .pack {}
+update
+test pack-8.9 {insufficient space} -body {
+ list [winfo geometry .pack.a] [winfo ismapped .pack.a] \
+ [winfo geometry .pack.b] [winfo ismapped .pack.b] \
+ [winfo geometry .pack.c] [winfo ismapped .pack.c]
+} -result {20x40+0+20 1 50x30+100+25 1 80x80+20+0 1}
+pack forget .pack.right .pack.bottom
+
+
+test pack-9.1 {window ordering} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a .pack.b .pack.c .pack.d -side top
+ pack .pack.a -after .pack.b
+ pack slaves .pack
+} -result {.pack.b .pack.a .pack.c .pack.d}
+test pack-9.2 {window ordering} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a .pack.b .pack.c .pack.d -side top
+ pack .pack.a -after .pack.a
+ pack slaves .pack
+} -result {.pack.a .pack.b .pack.c .pack.d}
+test pack-9.3 {window ordering} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a .pack.b .pack.c .pack.d -side top
+ pack .pack.a -before .pack.d
+ pack slaves .pack
+} -result {.pack.b .pack.c .pack.a .pack.d}
+test pack-9.4 {window ordering} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a .pack.b .pack.c .pack.d -side top
+ pack .pack.d -before .pack.a
+ pack slaves .pack
+} -result {.pack.d .pack.a .pack.b .pack.c}
+test pack-9.5 {window ordering} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a .pack.b .pack.c .pack.d -side top
+ pack propagate .pack.c 0
+ pack .pack.a -in .pack.c
+ list [pack slaves .pack] [pack slaves .pack.c]
+} -result {{.pack.b .pack.c .pack.d} .pack.a}
+test pack-9.6 {window ordering} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a .pack.b .pack.c .pack.d -side top
+ pack .pack.a -in .pack
+ pack slaves .pack
+} -result {.pack.b .pack.c .pack.d .pack.a}
+test pack-9.7 {window ordering} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a .pack.b .pack.c .pack.d -side top
+ pack .pack.a -padx 0
+ pack slaves .pack
+} -result {.pack.a .pack.b .pack.c .pack.d}
+test pack-9.8 {window ordering} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a .pack.b .pack.c
+ pack .pack.d
+ pack slaves .pack
+} -result {.pack.a .pack.b .pack.c .pack.d}
+test pack-9.9 {window ordering} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a .pack.b .pack.c .pack.d
+ pack .pack.b .pack.d .pack.c -before .pack.a
+ pack slaves .pack
+} -result {.pack.b .pack.d .pack.c .pack.a}
+test pack-9.10 {window ordering} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a .pack.b .pack.c .pack.d
+ pack .pack.a .pack.c .pack.d .pack.b -after .pack.a
+ pack slaves .pack
+} -result {.pack.a .pack.c .pack.d .pack.b}
+
+
+test pack-10.1 {retaining/clearing configuration state} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side bottom -anchor n -padx 1 -pady 2 -ipadx 3 -ipady 4 \
+ -fill both -expand 1
+ pack forget .pack.a
+ pack .pack.a
+ pack info .pack.a
+} -result {-in .pack -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 0 -side top}
+test pack-10.2 {retaining/clearing configuration state} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side bottom -anchor n -padx 1 -pady 2 -ipadx 3 -ipady 4 \
+ -fill both -expand 1
+ pack .pack.a -pady 14
+ pack info .pack.a
+} -result {-in .pack -anchor n -expand 1 -fill both -ipadx 3 -ipady 4 -padx 1 -pady 14 -side bottom}
+test pack-10.3 {bad -in window does not change master} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ set result [list [winfo manager .pack.a]]
+ catch {pack .pack.a -in .pack.a}
+ lappend result [winfo manager .pack.a]
+} -result {{} {}}
+test pack-10.4 {bad -in window does not change master} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ winfo manager .pack.a
+ pack .pack.a -in .pack.a
+} -returnCodes error -result {can't pack .pack.a inside itself}
+test pack-10.5 {prevent management loops} -body {
+ frame .f1
+ frame .f2
+ pack .f1 -in .f2
+ pack .f2 -in .f1
+} -cleanup {
+ destroy .f1
+ destroy .f2
+} -returnCodes error -result {can't put .f2 inside .f1, would cause management loop}
+test pack-10.6 {prevent management loops} -body {
+ frame .f1
+ frame .f2
+ frame .f3
+ pack .f1 -in .f2
+ pack .f2 -in .f3
+ pack .f3 -in .f1
+} -cleanup {
+ destroy .f1
+ destroy .f2
+ destroy .f3
+} -returnCodes error -result {can't put .f3 inside .f1, would cause management loop}
+
+
+test pack-11.1 {info option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -in .pack
+ set i [pack info .pack.a]
+ lindex $i [expr [lsearch -exact $i -in]+1]
+} -result .pack
+test pack-11.2 {info option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -anchor n
+ set i [pack info .pack.a]
+ lindex $i [expr [lsearch -exact $i -anchor]+1]
+} -result n
+test pack-11.3 {info option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -anchor sw
+ set i [pack info .pack.a]
+ lindex $i [expr [lsearch -exact $i -anchor]+1]
+} -result sw
+test pack-11.4 {info option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -expand yes
+ set i [pack info .pack.a]
+ lindex $i [expr [lsearch -exact $i -expand]+1]
+} -result 1
+test pack-11.5 {info option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -expand no
+ set i [pack info .pack.a]
+ lindex $i [expr [lsearch -exact $i -expand]+1]
+} -result 0
+test pack-11.6 {info option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -fill x
+ set i [pack info .pack.a]
+ lindex $i [expr [lsearch -exact $i -fill]+1]
+} -result x
+test pack-11.7 {info option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -fill y
+ set i [pack info .pack.a]
+ lindex $i [expr [lsearch -exact $i -fill]+1]
+} -result y
+test pack-11.8 {info option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -fill both
+ set i [pack info .pack.a]
+ lindex $i [expr [lsearch -exact $i -fill]+1]
+} -result both
+test pack-11.9 {info option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -fill none
+ set i [pack info .pack.a]
+ lindex $i [expr [lsearch -exact $i -fill]+1]
+} -result none
+test pack-11.10 {info option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -ipadx 14
+ set i [pack info .pack.a]
+ lindex $i [expr [lsearch -exact $i -ipadx]+1]
+} -result 14
+test pack-11.11 {info option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -ipady 22
+ set i [pack info .pack.a]
+ lindex $i [expr [lsearch -exact $i -ipady]+1]
+} -result 22
+test pack-11.12 {info option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -padx 2
+ set i [pack info .pack.a]
+ lindex $i [expr [lsearch -exact $i -padx]+1]
+} -result 2
+test pack-11.13 {info option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -padx {2 9}
+ set i [pack info .pack.a]
+ lindex $i [expr [lsearch -exact $i -padx]+1]
+} -result {2 9}
+test pack-11.14 {info option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -pady 3
+ set i [pack info .pack.a]
+ lindex $i [expr [lsearch -exact $i -pady]+1]
+} -result 3
+test pack-11.15 {info option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -pady {3 11}
+ set i [pack info .pack.a]
+ lindex $i [expr [lsearch -exact $i -pady]+1]
+} -result {3 11}
+test pack-11.16 {info option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side top
+ set i [pack info .pack.a]
+ lindex $i [expr [lsearch -exact $i -side]+1]
+} -result top
+test pack-11.17 {info option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side bottom
+ set i [pack info .pack.a]
+ lindex $i [expr [lsearch -exact $i -side]+1]
+} -result bottom
+test pack-11.18 {info option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side left
+ set i [pack info .pack.a]
+ lindex $i [expr [lsearch -exact $i -side]+1]
+} -result left
+test pack-11.19 {info option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side right
+ set i [pack info .pack.a]
+ lindex $i [expr [lsearch -exact $i -side]+1]
+} -result right
+
+
+test pack-12.1 {command options and errors} -body {
+ pack
+} -returnCodes error -result {wrong # args: should be "pack option arg ?arg ...?"}
+test pack-12.2 {command options and errors} -body {
+ pack foo
+} -returnCodes error -result {wrong # args: should be "pack option arg ?arg ...?"}
+test pack-12.3 {command options and errors} -body {
+ pack configure x
+} -returnCodes error -result {bad argument "x": must be name of window}
+test pack-12.4 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack configure .pack.b .pack.c
+ pack slaves .pack
+} -result {.pack.b .pack.c}
+test pack-12.5 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .foo
+} -returnCodes error -result {bad window path name ".foo"}
+test pack-12.6 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack
+} -returnCodes error -result {can't pack ".pack": it's a top-level window}
+test pack-12.7 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -after .foo
+} -returnCodes error -result {bad window path name ".foo"}
+test pack-12.8 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -after .pack.b
+} -returnCodes error -result {window ".pack.b" isn't packed}
+test pack-12.9 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -anchor gorp
+} -returnCodes error -result {bad anchor "gorp": must be n, ne, e, se, s, sw, w, nw, or center}
+test pack-12.10 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -before gorp
+} -returnCodes error -result {bad window path name "gorp"}
+test pack-12.11 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -before .pack.b
+} -returnCodes error -result {window ".pack.b" isn't packed}
+test pack-12.12 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -expand "who cares?"
+} -returnCodes error -result {expected boolean value but got "who cares?"}
+test pack-12.13 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -fill z
+} -returnCodes error -result {bad fill style "z": must be none, x, y, or both}
+test pack-12.14 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -in z
+} -returnCodes error -result {bad window path name "z"}
+set pad [winfo pixels .pack 1c]
+test pack-12.15 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -padx abc
+} -returnCodes error -result {bad pad value "abc": must be positive screen distance}
+test pack-12.16 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -padx {5 abc}
+} -returnCodes error -result {bad 2nd pad value "abc": must be positive screen distance}
+test pack-12.17 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -padx -1
+} -returnCodes error -result {bad pad value "-1": must be positive screen distance}
+test pack-12.18 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -padx {5 -1}
+} -returnCodes error -result {bad 2nd pad value "-1": must be positive screen distance}
+test pack-12.19 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -pady abc
+} -returnCodes error -result {bad pad value "abc": must be positive screen distance}
+test pack-12.20 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -pady {0 abc}
+} -returnCodes error -result {bad 2nd pad value "abc": must be positive screen distance}
+test pack-12.21 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -pady -1
+} -returnCodes error -result {bad pad value "-1": must be positive screen distance}
+test pack-12.22 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -pady {0 -1}
+} -returnCodes error -result {bad 2nd pad value "-1": must be positive screen distance}
+test pack-12.23 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -ipadx abc
+} -returnCodes error -result {bad ipadx value "abc": must be positive screen distance}
+test pack-12.24 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -ipadx -1
+} -returnCodes error -result {bad ipadx value "-1": must be positive screen distance}
+test pack-12.25 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -ipadx {5 5}
+} -returnCodes error -result {bad ipadx value "5 5": must be positive screen distance}
+test pack-12.26 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -ipady abc
+} -returnCodes error -result {bad ipady value "abc": must be positive screen distance}
+test pack-12.27 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -ipady -1
+} -returnCodes error -result {bad ipady value "-1": must be positive screen distance}
+test pack-12.28 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -ipady {5 5}
+} -returnCodes error -result {bad ipady value "5 5": must be positive screen distance}
+test pack-12.29 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -side bac
+} -returnCodes error -result {bad side "bac": must be top, bottom, left, or right}
+test pack-12.30 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -lousy bac
+} -returnCodes error -result {bad option "-lousy": must be -after, -anchor, -before, -expand, -fill, -in, -ipadx, -ipady, -padx, -pady, or -side}
+test pack-12.31 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -padx
+} -returnCodes error -result {extra option "-padx" (option with no value?)}
+test pack-12.32 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a ? 22
+} -returnCodes error -result {bad option "?": must be -after, -anchor, -before, -expand, -fill, -in, -ipadx, -ipady, -padx, -pady, or -side}
+test pack-12.33 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -in .
+} -returnCodes error -result {can't pack .pack.a inside .}
+test pack-12.34 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ frame .pack.a.a
+ pack .pack.a.a -in .pack.b
+} -returnCodes error -result {can't pack .pack.a.a inside .pack.b}
+test pack-12.35 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a -in .pack.a
+} -returnCodes error -result {can't pack .pack.a inside itself}
+test pack-12.36 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a .pack.b .pack.c .pack.d
+ pack forget .pack.a .pack.d
+ pack slaves .pack
+} -result {.pack.b .pack.c}
+test pack-12.37 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ .pack configure -width 300 -height 200
+ pack propagate .pack 0
+ pack .pack.a
+ update
+ set result [list [winfo reqwidth .pack] [winfo reqheight .pack]]
+ pack propagate .pack 1
+ update
+ lappend result [winfo reqwidth .pack] [winfo reqheight .pack]
+ return $result
+} -result {300 200 20 40}
+test pack-12.38 {command options and errors} -body {
+ set result [pack propagate .pack.d]
+ pack propagate .pack.d 0
+ lappend result [pack propagate .pack.d]
+ pack propagate .pack.d 1
+ lappend result [pack propagate .pack.d]
+ return $result
+} -result {1 0 1}
+test pack-12.39 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack propagate .dum
+} -returnCodes error -result {bad window path name ".dum"}
+test pack-12.40 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack propagate .pack foo
+} -returnCodes error -result {expected boolean value but got "foo"}
+test pack-12.41 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack propagate .pack foo bar
+} -returnCodes error -result {wrong # args: should be "pack propagate window ?boolean?"}
+test pack-12.42 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack slaves
+} -returnCodes error -result {wrong # args: should be "pack option arg ?arg ...?"}
+test pack-12.43 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack slaves a b
+} -returnCodes error -result {wrong # args: should be "pack slaves window"}
+test pack-12.44 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack slaves .x
+} -returnCodes error -result {bad window path name ".x"}
+test pack-12.45 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack slaves .pack.a
+} -returnCodes ok -result {}
+test pack-12.46 {command options and errors} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack lousy .pack
+} -returnCodes error -result {bad option "lousy": must be configure, forget, info, propagate, or slaves}
+
+
+test pack-13.1 {window deletion} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d .pack.right .pack.bottom
+} -body {
+ pack .pack.right -side right
+ pack .pack.bottom -side bottom
+ pack .pack.a .pack.d .pack.b .pack.c -side top
+ update
+ destroy .pack.d
+ update
+ set result [list [pack slaves .pack] [winfo geometry .pack.a] \
+ [winfo geometry .pack.b] [winfo geometry .pack.c]]
+} -result {{.pack.right .pack.bottom .pack.a .pack.b .pack.c} 20x40+30+0 50x30+15+40 80x80+0+70}
+
+
+test pack-14.1 {respond to changes in expansion} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d .pack.right .pack.bottom
+} -body {
+ pack .pack.right -side right
+ pack .pack.bottom -side bottom
+ wm geom .pack {}
+ pack .pack.a
+ update
+ set result [winfo geom .pack.a]
+ wm geom .pack 400x300
+ update
+ lappend result [winfo geom .pack.a]
+ pack .pack.a -expand true -fill both
+ update
+ lappend result [winfo geom .pack.a]
+} -cleanup {
+ wm geom .pack {}
+} -result {20x40+0+0 20x40+90+0 200x150+0+0}
+
+
+test pack-15.1 {managing geometry with -in option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+ destroy .pack.f
+} -body {
+ pack .pack.a -side top
+ frame .pack.f
+ lower .pack.f
+ pack .pack.f -side top
+ frame .pack.f.f2
+ lower .pack.f.f2
+ pack .pack.f.f2 -side top
+ pack .pack.b -in .pack.f.f2
+ update
+ set result [winfo geom .pack.b]
+ pack forget .pack.a
+ update
+ lappend result [winfo geom .pack.b]
+} -cleanup {
+ destroy .pack.f
+} -result {50x30+0+40 50x30+0+0}
+test pack-15.2 {managing geometry with -in option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+ destroy .pack.f
+} -body {
+ frame .pack.f
+ lower .pack.f
+ pack .pack.a -in .pack.f -side top
+ update
+ set result [winfo ismapped .pack.a]
+ place .pack.f -x 30 -y 45
+ update
+ lappend result [winfo ismapped .pack.a] [winfo geometry .pack.a]
+ place forget .pack.f
+ update
+ lappend result [winfo ismapped .pack.a]
+} -cleanup {
+ destroy .pack.f
+} -result {0 1 20x40+30+45 0}
+test pack-15.3 {managing geometry with -in option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+ destroy .pack.f
+} -body {
+ pack .pack.a -side top
+ frame .pack.f
+ lower .pack.f
+ pack .pack.f -side top
+ frame .pack.f.f2
+ lower .pack.f.f2
+ pack .pack.f.f2 -side top
+ pack .pack.b -in .pack.f.f2
+ update
+ set result [winfo ismapped .pack.b]
+ pack forget .pack.f
+ update
+ lappend result [winfo ismapped .pack.b]
+} -cleanup {
+ destroy .pack.f
+} -result {1 0}
+test pack-15.4 {managing geometry with -in option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+ destroy .pack.f1 .pack.f2
+} -body {
+ foreach i {1 2} {
+ frame .pack.f$i -width 100 -height 40 -bd 2 -relief raised
+ lower .pack.f$i
+ pack propagate .pack.f$i 0
+ pack .pack.f$i -side top
+ }
+ pack .pack.b -in .pack.f1 -side right
+ update
+ set result {}
+ lappend result [winfo geometry .pack.b] [winfo ismapped .pack.b]
+ pack .pack.b -in .pack.f2 -side bottom
+ update
+ lappend result [winfo geometry .pack.b] [winfo ismapped .pack.b]
+ .pack.f1 configure -width 50 -height 20
+ update
+ lappend result [winfo geometry .pack.b] [winfo ismapped .pack.b]
+ pack forget .pack.b
+ update
+ lappend result [winfo geometry .pack.b] [winfo ismapped .pack.b]
+} -cleanup {
+ destroy .pack.f1 .pack.f2
+} -result {50x30+48+5 1 50x30+25+48 1 50x30+25+28 1 50x30+25+28 0}
+test pack-15.5 {managing geometry with -in option} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+ destroy .pack.f1 .pack.f2
+} -body {
+ foreach i {1 2} {
+ frame .pack.f$i -width 100 -height 20 -bd 2 -relief raised
+ lower .pack.f$i
+ pack propagate .pack.f$i 0
+ pack .pack.f$i -side top
+ }
+ pack .pack.b -in .pack.f2 -side top
+ update
+ set result {}
+ lappend result [winfo geometry .pack.b] [winfo ismapped .pack.b]
+ pack .pack.a -before .pack.b -side top
+ update
+ lappend result [winfo geometry .pack.b] [winfo ismapped .pack.b]
+} -cleanup {
+ destroy .pack.f1 .pack.f2
+} -result {50x16+25+22 1 50x16+25+22 0}
+
+
+test pack-16.1 {geometry manager name} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+ set result {}
+} -body {
+ lappend result [winfo manager .pack.a]
+ pack .pack.a
+ lappend result [winfo manager .pack.a]
+ pack forget .pack.a
+ lappend result [winfo manager .pack.a]
+} -result {{} pack {}}
+
+
+test pack-17.1 {PackLostSlaveProc procedure} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a
+ update
+ place .pack.a -x 40 -y 10
+ update
+ list [winfo manager .pack.a] [winfo geometry .pack.a]
+} -result {place 20x40+40+10}
+test pack-17.2 {PackLostSlaveProc procedure} -setup {
+ pack forget .pack.a .pack.b .pack.c .pack.d
+} -body {
+ pack .pack.a
+ update
+ place .pack.a -x 40 -y 10
+ update
+ winfo manager .pack.a
+ winfo geometry .pack.a
+ pack info .pack.a
+} -returnCodes error -result {window ".pack.a" isn't packed}
+
+
+test pack-18.1 {unmap slaves when master unmapped} -constraints {
+ tempNotPc
+} -setup {
+ eval destroy [winfo child .pack]
+} -body {
+
+ # adjust the position of .pack before test to avoid a screen switch
+ # that occurs with window managers that have desktops four times as big
+ # as the screen (screen switch causes scale and other tests to fail).
+
+ wm geometry .pack +100+100
+
+ # On the PC, when the width/height is configured while the window is
+ # unmapped, the changes don't take effect until the window is remapped.
+ # Who knows why?
+
+ eval destroy [winfo child .pack]
+ frame .pack.a -width 100 -height 50 -relief raised -bd 2
+ pack .pack.a
+ update
+ set result [winfo ismapped .pack.a]
+ wm iconify .pack
+ update
+ lappend result [winfo ismapped .pack.a]
+ .pack.a configure -width 200 -height 75
+ update
+ lappend result [winfo width .pack.a ] [winfo height .pack.a] \
+ [winfo ismapped .pack.a]
+ wm deiconify .pack
+ update
+ lappend result [winfo ismapped .pack.a]
+} -result {1 0 200 75 0 1}
+test pack-18.2 {unmap slaves when master unmapped} -setup {
+ eval destroy [winfo child .pack]
+} -body {
+
+ # adjust the position of .pack before test to avoid a screen switch
+ # that occurs with window managers that have desktops four times as big
+ # as the screen (screen switch causes scale and other tests to fail).
+
+ wm geometry .pack +100+100
+ frame .pack.a -relief raised -bd 2
+ frame .pack.b -width 70 -height 30 -relief sunken -bd 2
+ pack .pack.a
+ pack .pack.b -in .pack.a
+ update
+ set result [winfo ismapped .pack.b]
+ wm iconify .pack
+ update
+ lappend result [winfo ismapped .pack.b]
+ .pack.b configure -width 100 -height 30
+ update
+ lappend result [winfo width .pack.b ] [winfo height .pack.b] \
+ [winfo ismapped .pack.b]
+ wm deiconify .pack
+ update
+ lappend result [winfo ismapped .pack.b]
+} -result {1 0 100 30 0 1}
+
+
+test pack-19.1 {test respect for internalborder} -setup {
+ catch {eval pack forget [pack slaves .pack]}
+ destroy .pack.l .pack.lf
+} -body {
+ wm geometry .pack 200x200
+ frame .pack.l -width 15 -height 10
+ labelframe .pack.lf -labelwidget .pack.l
+ pack .pack.lf -fill both -expand 1
+ frame .pack.lf.f
+ pack .pack.lf.f -fill both -expand 1
+ update
+ set res [list [winfo geometry .pack.lf.f]]
+ .pack.lf configure -labelanchor e -padx 3 -pady 5
+ update
+ lappend res [winfo geometry .pack.lf.f]
+} -cleanup {
+ destroy .pack.l .pack.lf
+} -result {196x188+2+10 177x186+5+7}
+test pack-19.2 {test support for minreqsize} -setup {
+ catch {eval pack forget [pack slaves .pack]}
+ destroy .pack.l .pack.lf
+} -body {
+ wm geometry .pack {}
+ frame .pack.l -width 150 -height 100
+ labelframe .pack.lf -labelwidget .pack.l
+ pack .pack.lf -fill both -expand 1
+ frame .pack.lf.f -width 20 -height 25
+ pack .pack.lf.f
+ update
+ set res [list [winfo geometry .pack.lf]]
+ .pack.lf configure -labelanchor ws
+ update
+ lappend res [winfo geometry .pack.lf]
+} -cleanup {
+ destroy .pack.l .pack.lf
+} -result {162x127+0+0 172x112+0+0}
+
+
+# cleanup
+cleanupTests
+return
+
+
+
diff --git a/tk8.6/tests/packgrid.test b/tk8.6/tests/packgrid.test
new file mode 100644
index 0000000..6074ce9
--- /dev/null
+++ b/tk8.6/tests/packgrid.test
@@ -0,0 +1,280 @@
+# This file is a Tcl script to test out interaction between Tk's "pack" and
+# "grid" commands.
+# It is organized in the standard fashion for Tcl tests.
+#
+# Copyright (c) 2008 Peter Spjuth
+# All rights reserved.
+
+package require tcltest 2.2
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+namespace import -force tcltest::*
+
+test packgrid-1.1 {pack and grid in same master} -setup {
+ grid propagate . true
+ pack propagate . true
+ label .p -text PACK
+ label .g -text GRID
+} -body {
+ # Basic conflict
+ grid .g
+ pack .p
+} -returnCodes error -cleanup {
+ destroy .p
+ destroy .g
+} -result {cannot use geometry manager pack inside . which already has slaves managed by grid}
+
+test packgrid-1.2 {pack and grid in same master} -setup {
+ grid propagate . true
+ pack propagate . true
+ label .p -text PACK
+ label .g -text GRID
+} -body {
+ # Basic conflict
+ pack .p
+ grid .g
+} -returnCodes error -cleanup {
+ destroy .p
+ destroy .g
+} -result {cannot use geometry manager grid inside . which already has slaves managed by pack}
+
+test packgrid-1.3 {pack and grid in same master} -setup {
+ grid propagate . false
+ pack propagate . true
+ label .p -text PACK
+ label .g -text GRID
+} -body {
+ # Ok if one is non-propagating
+ grid .g
+ pack .p
+} -cleanup {
+ destroy .p
+ destroy .g
+} -result {}
+
+test packgrid-1.4 {pack and grid in same master} -setup {
+ grid propagate . false
+ pack propagate . true
+ label .p -text PACK
+ label .g -text GRID
+} -body {
+ # Ok if one is non-propagating
+ pack .p
+ grid .g
+} -cleanup {
+ destroy .p
+ destroy .g
+} -result {}
+
+test packgrid-1.5 {pack and grid in same master} -setup {
+ grid propagate . true
+ pack propagate . false
+ label .p -text PACK
+ label .g -text GRID
+} -body {
+ # Ok if one is non-propagating
+ grid .g
+ pack .p
+} -cleanup {
+ destroy .p
+ destroy .g
+} -result {}
+
+test packgrid-1.6 {pack and grid in same master} -setup {
+ grid propagate . true
+ pack propagate . false
+ label .p -text PACK
+ label .g -text GRID
+} -body {
+ # Ok if one is non-propagating
+ pack .p
+ grid .g
+} -cleanup {
+ destroy .p
+ destroy .g
+} -result {}
+
+test packgrid-1.7 {pack and grid in same master} -setup {
+ grid propagate . true
+ pack propagate . true
+ label .p -text PACK
+ label .g -text GRID
+} -body {
+ # Basic conflict should stop widget from being handled
+ grid .g
+ catch { pack .p }
+ pack slaves .
+} -cleanup {
+ destroy .p
+ destroy .g
+} -result {}
+
+test packgrid-1.8 {pack and grid in same master} -setup {
+ grid propagate . true
+ pack propagate . true
+ label .p -text PACK
+ label .g -text GRID
+} -body {
+ # Basic conflict should stop widget from being handled
+ pack .p
+ catch { grid .g }
+ grid slaves .
+} -cleanup {
+ destroy .p
+ destroy .g
+} -result {}
+
+test packgrid-2.1 {pack and grid in same master, change propagation} -setup {
+ grid propagate . false
+ pack propagate . true
+ label .p -text PACK
+ label .g -text GRID
+ pack .p
+ grid .g
+ update
+} -body {
+ grid propagate . true
+} -returnCodes error -cleanup {
+ destroy .p
+ destroy .g
+} -result {cannot use geometry manager grid inside . which already has slaves managed by pack}
+
+test packgrid-2.2 {pack and grid in same master, change propagation} -setup {
+ grid propagate . true
+ pack propagate . false
+ label .p -text PACK
+ label .g -text GRID
+ pack .p
+ grid .g
+ update
+} -body {
+ pack propagate . true
+} -returnCodes error -cleanup {
+ destroy .p
+ update
+ destroy .g
+} -result {cannot use geometry manager pack inside . which already has slaves managed by grid}
+
+test packgrid-2.3 {pack and grid in same master, change propagation} -setup {
+ grid propagate . false
+ pack propagate . false
+ label .p -text PACK
+ label .g -text GRID
+ pack .p
+ grid .g
+ update
+} -body {
+ grid propagate . true
+ update
+ pack propagate . true
+} -returnCodes error -cleanup {
+ destroy .p
+ destroy .g
+} -result {cannot use geometry manager pack inside . which already has slaves managed by grid}
+
+test packgrid-2.4 {pack and grid in same master, change propagation} -setup {
+ grid propagate . false
+ pack propagate . false
+ label .p -text PACK
+ label .g -text GRID
+ pack .p
+ grid .g
+ update
+} -body {
+ pack propagate . true
+ grid propagate . true
+} -returnCodes error -cleanup {
+ destroy .p
+ destroy .g
+} -result {cannot use geometry manager grid inside . which already has slaves managed by pack}
+
+test packgrid-3.1 {stealing slave} -setup {
+ grid propagate . true
+ pack propagate . true
+ label .p -text PACK
+ label .g -text GRID
+} -body {
+ # Ok to steal if the other one is emptied
+ grid .g
+ pack .g
+} -cleanup {
+ destroy .p
+ destroy .g
+} -result {}
+
+test packgrid-3.2 {stealing slave} -setup {
+ grid propagate . true
+ pack propagate . true
+ label .p -text PACK
+ label .g -text GRID
+} -body {
+ # Ok to steal if the other one is emptied
+ pack .g
+ grid .g
+} -cleanup {
+ destroy .p
+ destroy .g
+} -result {}
+
+test packgrid-3.3 {stealing slave} -setup {
+ grid propagate . true
+ pack propagate . true
+ label .p -text PACK
+ label .g -text GRID
+} -body {
+ # Not ok to steal if the other one is not emptied
+ grid .g
+ grid .p
+ pack .g
+} -returnCodes error -cleanup {
+ destroy .p
+ destroy .g
+} -result {cannot use geometry manager pack inside . which already has slaves managed by grid}
+
+test packgrid-3.4 {stealing slave} -setup {
+ grid propagate . true
+ pack propagate . true
+ label .p -text PACK
+ label .g -text GRID
+} -body {
+ # Not ok to steal if the other one is not emptied
+ pack .g
+ pack .p
+ grid .g
+} -returnCodes error -cleanup {
+ destroy .p
+ destroy .g
+} -result {cannot use geometry manager grid inside . which already has slaves managed by pack}
+
+test packgrid-4.1 {slave stolen after master destruction - bug [aa7679685e]} -setup {
+ frame .f
+ button .b -text hello
+} -body {
+ pack .f
+ grid .b -in .f
+ destroy .f
+ set res [winfo manager .b]
+ # shall not crash
+ pack .b
+ set res
+} -cleanup {
+ destroy .b
+} -result {}
+
+test packgrid-4.2 {slave stolen after master destruction - bug [aa7679685e]} -setup {
+ frame .f
+ button .b -text hello
+} -body {
+ pack .f
+ pack .b -in .f
+ destroy .f
+ set res [winfo manager .b]
+ # shall not crash
+ grid .b
+ set res
+} -cleanup {
+ destroy .b
+} -result {}
+
+cleanupTests
+return
diff --git a/tk8.6/tests/panedwindow.test b/tk8.6/tests/panedwindow.test
new file mode 100644
index 0000000..ee184ce
--- /dev/null
+++ b/tk8.6/tests/panedwindow.test
@@ -0,0 +1,5551 @@
+# This file is a Tcl script to test entry widgets in Tk. It is
+# organized in the standard fashion for Tcl tests.
+#
+# Copyright (c) 1994 The Regents of the University of California.
+# Copyright (c) 1994-1997 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+namespace import -force tcltest::test
+
+deleteWindows
+# Panedwindow for tests 1.*
+panedwindow .p
+# Buttons for tests 1.33 - 1.52
+.p add [button .b]
+.p add [button .c]
+test panedwindow-1.1 {configuration options: -background (good)} -body {
+ .p configure -background #ff0000
+ list [lindex [.p configure -background] 4] [.p cget -background]
+} -cleanup {
+ .p configure -background [lindex [.p configure -background] 3]
+} -result {{#ff0000} #ff0000}
+test panedwindow-1.2 {configuration options: -background (bad)} -body {
+ .p configure -background non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+test panedwindow-1.3 {configuration options: -bd (good)} -body {
+ .p configure -bd 4
+ list [lindex [.p configure -bd] 4] [.p cget -bd]
+} -cleanup {
+ .p configure -bd [lindex [.p configure -bd] 3]
+} -result {4 4}
+test panedwindow-1.4 {configuration options: -bd (bad)} -body {
+ .p configure -bd badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test panedwindow-1.5 {configuration options: -bg (good)} -body {
+ .p configure -bg #ff0000
+ list [lindex [.p configure -bg] 4] [.p cget -bg]
+} -cleanup {
+ .p configure -bg [lindex [.p configure -bg] 3]
+} -result {{#ff0000} #ff0000}
+test panedwindow-1.6 {configuration options: -bg (bad)} -body {
+ .p configure -bg non-existent
+} -returnCodes error -result {unknown color name "non-existent"}
+test panedwindow-1.7 {configuration options: -borderwidth (good)} -body {
+ .p configure -borderwidth 1.3
+ list [lindex [.p configure -borderwidth] 4] [.p cget -borderwidth]
+} -cleanup {
+ .p configure -borderwidth [lindex [.p configure -borderwidth] 3]
+} -result {1 1}
+test panedwindow-1.8 {configuration options: -borderwidth (bad)} -body {
+ .p configure -borderwidth badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test panedwindow-1.9 {configuration options: -cursor (good)} -body {
+ .p configure -cursor arrow
+ list [lindex [.p configure -cursor] 4] [.p cget -cursor]
+} -cleanup {
+ .p configure -cursor [lindex [.p configure -cursor] 3]
+} -result {arrow arrow}
+test panedwindow-1.10 {configuration options: -cursor (bad)} -body {
+ .p configure -cursor badValue
+} -returnCodes error -result {bad cursor spec "badValue"}
+test panedwindow-1.11 {configuration options: -handlesize (good)} -body {
+ .p configure -handlesize 20
+ list [lindex [.p configure -handlesize] 4] [.p cget -handlesize]
+} -cleanup {
+ .p configure -handlesize [lindex [.p configure -handlesize] 3]
+} -result {20 20}
+test panedwindow-1.12 {configuration options: -handlesize (bad)} -body {
+ .p configure -handlesize badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test panedwindow-1.13 {configuration options: -height (good)} -body {
+ .p configure -height 20
+ list [lindex [.p configure -height] 4] [.p cget -height]
+} -cleanup {
+ .p configure -height [lindex [.p configure -height] 3]
+} -result {20 20}
+test panedwindow-1.14 {configuration options: -height (bad)} -body {
+ .p configure -height badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test panedwindow-1.15 {configuration options: -opaqueresize (good)} -body {
+ .p configure -opaqueresize true
+ list [lindex [.p configure -opaqueresize] 4] [.p cget -opaqueresize]
+} -cleanup {
+ .p configure -opaqueresize [lindex [.p configure -opaqueresize] 3]
+} -result {1 1}
+test panedwindow-1.16 {configuration options: -opaqueresize (bad)} -body {
+ .p configure -opaqueresize foo
+} -returnCodes error -result {expected boolean value but got "foo"}
+test panedwindow-1.17 {configuration options: -orient (good)} -body {
+ .p configure -orient horizontal
+ list [lindex [.p configure -orient] 4] [.p cget -orient]
+} -cleanup {
+ .p configure -orient [lindex [.p configure -orient] 3]
+} -result {horizontal horizontal}
+test panedwindow-1.18 {configuration options: -orient (bad)} -body {
+ .p configure -orient badValue
+} -returnCodes error -result {bad orient "badValue": must be horizontal or vertical}
+test panedwindow-1.19 {configuration options: -proxybackground (good)} -body {
+ .p configure -proxybackground "#f0a0a0"
+ list [lindex [.p configure -proxybackground] 4] [.p cget -proxybackground]
+} -cleanup {
+ .p configure -proxybackground [lindex [.p configure -proxybackground] 3]
+} -result {{#f0a0a0} #f0a0a0}
+test panedwindow-1.20 {configuration options: -proxybackground (bad)} -body {
+ .p configure -proxybackground badValue
+} -returnCodes error -result {unknown color name "badValue"}
+test panedwindow-1.21 {configuration options: -proxyborderwidth (good)} -body {
+ .p configure -proxyborderwidth 1.3
+ list [lindex [.p configure -proxyborderwidth] 4] [.p cget -proxyborderwidth]
+} -cleanup {
+ .p configure -proxyborderwidth [lindex [.p configure -proxyborderwidth] 3]
+} -result {1.3 1.3}
+test panedwindow-1.22 {configuration options: -proxyborderwidth (bad)} -body {
+ .p configure -proxyborderwidth badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test panedwindow-1.23 {configuration options: -proxyrelief (good)} -body {
+ .p configure -proxyrelief groove
+ list [lindex [.p configure -proxyrelief] 4] [.p cget -proxyrelief]
+} -cleanup {
+ .p configure -proxyrelief [lindex [.p configure -proxyrelief] 3]
+} -result {groove groove}
+test panedwindow-1.24 {configuration options: -proxyrelief (bad)} -body {
+ .p configure -proxyrelief 1.5
+} -returnCodes error -result {bad relief "1.5": must be flat, groove, raised, ridge, solid, or sunken}
+test panedwindow-1.25 {configuration options: -relief (good)} -body {
+ .p configure -relief groove
+ list [lindex [.p configure -relief] 4] [.p cget -relief]
+} -cleanup {
+ .p configure -relief [lindex [.p configure -relief] 3]
+} -result {groove groove}
+test panedwindow-1.26 {configuration options: -relief (bad)} -body {
+ .p configure -relief 1.5
+} -returnCodes error -result {bad relief "1.5": must be flat, groove, raised, ridge, solid, or sunken}
+test panedwindow-1.27 {configuration options: -sashcursor (good)} -body {
+ .p configure -sashcursor arrow
+ list [lindex [.p configure -sashcursor] 4] [.p cget -sashcursor]
+} -cleanup {
+ .p configure -sashcursor [lindex [.p configure -sashcursor] 3]
+} -result {arrow arrow}
+test panedwindow-1.28 {configuration options: -sashcursor (bad)} -body {
+ .p configure -sashcursor badValue
+} -returnCodes error -result {bad cursor spec "badValue"}
+test panedwindow-1.29 {configuration options: -sashpad (good)} -body {
+ .p configure -sashpad 1.3
+ list [lindex [.p configure -sashpad] 4] [.p cget -sashpad]
+} -cleanup {
+ .p configure -sashpad [lindex [.p configure -sashpad] 3]
+} -result {1 1}
+test panedwindow-1.30 {configuration options: -sashpad (bad)} -body {
+ .p configure -sashpad badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test panedwindow-1.31 {configuration options: -sashrelief (good)} -body {
+ .p configure -sashrelief groove
+ list [lindex [.p configure -sashrelief] 4] [.p cget -sashrelief]
+} -cleanup {
+ .p configure -sashrelief [lindex [.p configure -sashrelief] 3]
+} -result {groove groove}
+test panedwindow-1.32 {configuration options: -sashrelief (bad)} -body {
+ .p configure -sashrelief 1.5
+} -returnCodes error -result {bad relief "1.5": must be flat, groove, raised, ridge, solid, or sunken}
+test panedwindow-1.33 {configuration options: -sashwidth (good)} -body {
+ .p configure -sashwidth 10
+ list [lindex [.p configure -sashwidth] 4] [.p cget -sashwidth]
+} -cleanup {
+ .p configure -sashwidth [lindex [.p configure -sashwidth] 3]
+} -result {10 10}
+test panedwindow-1.34 {configuration options: -sashwidth (bad)} -body {
+ .p configure -sashwidth badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test panedwindow-1.35 {configuration options: -showhandle (good)} -body {
+ .p configure -showhandle true
+ list [lindex [.p configure -showhandle] 4] [.p cget -showhandle]
+} -cleanup {
+ .p configure -showhandle [lindex [.p configure -showhandle] 3]
+} -result {1 1}
+test panedwindow-1.36 {configuration options: -showhandle (bad)} -body {
+ .p configure -showhandle foo
+} -returnCodes error -result {expected boolean value but got "foo"}
+test panedwindow-1.37 {configuration options: -width (good)} -body {
+ .p configure -width 402
+ list [lindex [.p configure -width] 4] [.p cget -width]
+} -cleanup {
+ .p configure -width [lindex [.p configure -width] 3]
+} -result {402 402}
+test panedwindow-1.38 {configuration options: -width (bad)} -body {
+ .p configure -width badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+
+test panedwindow-1.39 {configuration options: -after (good)} -body {
+ .p paneconfigure .b -after .c
+ list [lindex [.p paneconfigure .b -after] 4] \
+ [.p panecget .b -after]
+} -cleanup {
+ .p paneconfig .b -after [lindex [.p paneconfig .b -after] 3]
+} -result {.c .c}
+test panedwindow-1.40 {configuration options: -after (bad)} -body {
+ .p paneconfigure .b -after badValue
+} -returnCodes error -result {bad window path name "badValue"}
+test panedwindow-1.41 {configuration options: -before (good)} -body {
+ .p paneconfigure .b -before .c
+ list [lindex [.p paneconfigure .b -before] 4] \
+ [.p panecget .b -before]
+} -cleanup {
+ .p paneconfig .b -before [lindex [.p paneconfig .b -before] 3]
+} -result {.c .c}
+test panedwindow-1.42 {configuration options: -before (bad)} -body {
+ .p paneconfigure .b -before badValue
+} -returnCodes error -result {bad window path name "badValue"}
+test panedwindow-1.43 {configuration options: -height (good)} -body {
+ .p paneconfigure .b -height 10
+ list [lindex [.p paneconfigure .b -height] 4] \
+ [.p panecget .b -height]
+} -cleanup {
+ .p paneconfig .b -height [lindex [.p paneconfig .b -height] 3]
+} -result {10 10}
+test panedwindow-1.44 {configuration options: -height (bad)} -body {
+ .p paneconfigure .b -height badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test panedwindow-1.45 {configuration options: -hide (good)} -body {
+ .p paneconfigure .b -hide false
+ list [lindex [.p paneconfigure .b -hide] 4] \
+ [.p panecget .b -hide]
+} -cleanup {
+ .p paneconfig .b -hide [lindex [.p paneconfig .b -hide] 3]
+} -result {0 0}
+test panedwindow-1.46 {configuration options: -hide (bad)} -body {
+ .p paneconfigure .b -hide foo
+} -returnCodes error -result {expected boolean value but got "foo"}
+test panedwindow-1.47 {configuration options: -minsize (good)} -body {
+ .p paneconfigure .b -minsize 10
+ list [lindex [.p paneconfigure .b -minsize] 4] \
+ [.p panecget .b -minsize]
+} -cleanup {
+ .p paneconfig .b -minsize [lindex [.p paneconfig .b -minsize] 3]
+} -result {10 10}
+test panedwindow-1.48 {configuration options: -minsize (bad)} -body {
+ .p paneconfigure .b -minsize badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test panedwindow-1.49 {configuration options: -padx (good)} -body {
+ .p paneconfigure .b -padx 1.3
+ list [lindex [.p paneconfigure .b -padx] 4] \
+ [.p panecget .b -padx]
+} -cleanup {
+ .p paneconfig .b -padx [lindex [.p paneconfig .b -padx] 3]
+} -result {1 1}
+test panedwindow-1.50 {configuration options: -padx (bad)} -body {
+ .p paneconfigure .b -padx badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test panedwindow-1.51 {configuration options: -pady (good)} -body {
+ .p paneconfigure .b -pady 1.3
+ list [lindex [.p paneconfigure .b -pady] 4] \
+ [.p panecget .b -pady]
+} -cleanup {
+ .p paneconfig .b -pady [lindex [.p paneconfig .b -pady] 3]
+} -result {1 1}
+test panedwindow-1.52 {configuration options: -pady (bad)} -body {
+ .p paneconfigure .b -pady badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+test panedwindow-1.53 {configuration options: -sticky (good)} -body {
+ .p paneconfigure .b -sticky nsew
+ list [lindex [.p paneconfigure .b -sticky] 4] \
+ [.p panecget .b -sticky]
+} -cleanup {
+ .p paneconfig .b -sticky [lindex [.p paneconfig .b -sticky] 3]
+} -result {nesw nesw}
+test panedwindow-1.54 {configuration options: -sticky (bad)} -body {
+ .p paneconfigure .b -sticky abcd
+} -returnCodes error -result {bad stickyness value "abcd": must be a string containing zero or more of n, e, s, and w}
+test panedwindow-1.55 {configuration options: -stretch (good)} -body {
+ .p paneconfigure .b -stretch alw
+ list [lindex [.p paneconfigure .b -stretch] 4] \
+ [.p panecget .b -stretch]
+} -cleanup {
+ .p paneconfig .b -stretch [lindex [.p paneconfig .b -stretch] 3]
+} -result {always always}
+test panedwindow-1.56 {configuration options: -stretch (bad)} -body {
+ .p paneconfigure .b -stretch foo
+} -returnCodes error -result {bad stretch "foo": must be always, first, last, middle, or never}
+test panedwindow-1.57 {configuration options: -width (good)} -body {
+ .p paneconfigure .b -width 10
+ list [lindex [.p paneconfigure .b -width] 4] \
+ [.p panecget .b -width]
+} -cleanup {
+ .p paneconfig .b -width [lindex [.p paneconfig .b -width] 3]
+} -result {10 10}
+test panedwindow-1.58 {configuration options: -width (bad)} -body {
+ .p paneconfigure .b -width badValue
+} -returnCodes error -result {bad screen distance "badValue"}
+deleteWindows
+
+
+test panedwindow-2.1 {panedwindow widget command} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p foo
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {bad command "foo": must be add, cget, configure, forget, identify, panecget, paneconfigure, panes, proxy, or sash}
+
+
+test panedwindow-3.1 {panedwindow panes subcommand} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p add [button .b]
+ .p add [button .c]
+ set result [list [.p panes]]
+ .p forget .b
+ lappend result [.p panes]
+} -cleanup {
+ deleteWindows
+} -result [list [list .b .c] [list .c]]
+
+
+test panedwindow-4.1 {forget subcommand} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p forget
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {wrong # args: should be ".p forget widget ?widget ...?"}
+test panedwindow-4.2 {forget subcommand, forget one from start} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p add [button .b]
+ .p add [button .c]
+ set result [list [.p panes]]
+ .p forget .b
+ lappend result [.p panes]
+} -cleanup {
+ deleteWindows
+} -result [list {.b .c} .c]
+test panedwindow-4.3 {forget subcommand, forget one from end} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p add [button .b]
+ .p add [button .c]
+ .p add [button .d]
+ set result [list [.p panes]]
+ .p forget .d
+ update
+ lappend result [.p panes]
+} -cleanup {
+ deleteWindows
+} -result [list {.b .c .d} {.b .c}]
+test panedwindow-4.4 {forget subcommand, forget multiple} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p add [button .b]
+ .p add [button .c]
+ .p add [button .d]
+ set result [list [.p panes]]
+ .p forget .b .c
+ update
+ lappend result [.p panes]
+} -cleanup {
+ deleteWindows
+} -result [list {.b .c .d} .d]
+test panedwindow-4.5 {forget subcommand, panes are unmapped} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p add [button .b]
+ .p add [button .c]
+ pack .p
+ update
+ set result [list [winfo ismapped .b] [winfo ismapped .c]]
+ .p forget .b
+ update
+ lappend result [winfo ismapped .b] [winfo ismapped .c]
+} -cleanup {
+ deleteWindows
+} -result [list 1 1 0 1]
+test panedwindow-4.6 {forget subcommand, changes reqsize of panedwindow} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 4 -showhandle false
+ .p add [frame .f -width 20 -height 20] [frame .g -width 20 -height 20]
+ set result [list [winfo reqwidth .p]]
+ .p forget .f
+ lappend result [winfo reqwidth .p]
+} -cleanup {
+ deleteWindows
+} -result [list 44 20]
+
+
+test panedwindow-5.1 {sash subcommand} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p sash
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {wrong # args: should be ".p sash option ?arg ...?"}
+test panedwindow-5.2 {sash subcommand} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p sash foo
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {bad option "foo": must be coord, dragto, mark, or place}
+
+
+test panedwindow-6.1 {sash coord subcommand, errors} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p sash coord
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {wrong # args: should be ".p sash coord index"}
+test panedwindow-6.2 {sash coord subcommand, errors} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 4
+ .p sash coord 0
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {invalid sash index}
+test panedwindow-6.3 {sash coord subcommand, errors} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p sash coord foo
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {expected integer but got "foo"}
+test panedwindow-6.4 {sash coord subcommand sashes correctly placed} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 2 -sashwidth 4 -showhandle false
+ .p add [frame .p.f -width 20 -height 20] \
+ [frame .p.f2 -width 20 -height 20] \
+ [frame .p.f3 -width 20 -height 20]
+ .p sash coord 0
+} -cleanup {
+ deleteWindows
+} -result [list 22 0]
+test panedwindow-6.5 {sash coord subcommand sashes correctly placed} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 2 -sashwidth 4 -showhandle false
+ .p add [frame .p.f -width 20 -height 20] \
+ [frame .p.f2 -width 20 -height 20] \
+ [frame .p.f3 -width 20 -height 20]
+ .p sash coord 1
+} -cleanup {
+ deleteWindows
+} -result [list 50 0]
+test panedwindow-6.6 {sash coord subcommand, sashes correctly placed} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 2 -sashwidth 4 -orient vertical \
+ -showhandle false
+ .p add [frame .p.f -width 20 -height 20] \
+ [frame .p.f2 -width 20 -height 20] \
+ [frame .p.f3 -width 20 -height 20]
+ .p sash coord 0
+} -cleanup {
+ deleteWindows
+} -result [list 0 22]
+test panedwindow-6.7 {sash coord subcommand, sashes correctly placed} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 2 -sashwidth 4 -orient vertical \
+ -showhandle false
+ .p add [frame .p.f -width 20 -height 20] \
+ [frame .p.f2 -width 20 -height 20] \
+ [frame .p.f3 -width 20 -height 20]
+ .p sash coord 1
+} -cleanup {
+ deleteWindows
+} -result [list 0 50]
+test panedwindow-6.8 {sash coord subcommand, errors} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ list [catch {.p sash coord -1} msg] $msg \
+ [catch {.p sash coord 0} msg] $msg \
+ [catch {.p sash coord 1} msg] $msg
+} -cleanup {
+ deleteWindows
+} -result [list 1 "invalid sash index" 1 "invalid sash index" 1 "invalid sash index"]
+test panedwindow-6.9 {sash coord subcommand, errors} -setup {
+ deleteWindows
+} -body {
+ # There are no sashes until you have 2 panes
+ panedwindow .p
+ .p add [frame .p.f]
+ list [catch {.p sash coord -1} msg] $msg \
+ [catch {.p sash coord 0} msg] $msg \
+ [catch {.p sash coord 1} msg] $msg
+} -cleanup {
+ deleteWindows
+} -result [list 1 "invalid sash index" 1 "invalid sash index" 1 "invalid sash index"]
+test panedwindow-6.10 {sash coord subcommand, errors} -setup {
+ deleteWindows
+} -body {
+ # There are no sashes until you have 2 panes
+ panedwindow .p
+ .p add [frame .p.f] [frame .p.f2]
+ list [catch {.p sash coord -1} msg] $msg \
+ [catch {.p sash coord 0} msg] \
+ [catch {.p sash coord 1} msg] $msg \
+ [catch {.p sash coord 2} msg] $msg
+} -cleanup {
+ deleteWindows
+} -result [list 1 "invalid sash index" 0 1 "invalid sash index" 1 "invalid sash index"]
+
+
+test panedwindow-7.1 {sash mark subcommand, errors} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p sash mark
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {wrong # args: should be ".p sash mark index ?x y?"}
+test panedwindow-7.2 {sash mark subcommand, errors} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p sash mark foo
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {expected integer but got "foo"}
+test panedwindow-7.3 {sash mark subcommand, errors} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p sash mark 0 foo bar
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {invalid sash index}
+test panedwindow-7.4 {sash mark subcommand, errors} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p add [button .b] [button .c]
+ .p sash mark 0 foo bar
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {expected integer but got "foo"}
+test panedwindow-7.5 {sash mark subcommand, errors} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p add [button .b] [button .c]
+ .p sash mark 0 0 bar
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {expected integer but got "bar"}
+test panedwindow-7.6 {sash mark subcommand, mark defaults to 0 0} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p add [button .b] [button .c]
+ .p sash mark 0
+} -cleanup {
+ deleteWindows
+} -result [list 0 0]
+test panedwindow-7.7 {sash mark subcommand, set mark} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p add [button .b] [button .c]
+ .p sash mark 0 10 10
+ .p sash mark 0
+} -cleanup {
+ deleteWindows
+} -result [list 10 10]
+
+
+test panedwindow-8.1 {sash dragto subcommand, errors} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p sash dragto
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {wrong # args: should be ".p sash dragto index x y"}
+test panedwindow-8.2 {sash dragto subcommand, errors} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p sash dragto foo bar baz
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {expected integer but got "foo"}
+test panedwindow-8.3 {sash dragto subcommand, errors} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p sash dragto 0 foo bar
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {invalid sash index}
+test panedwindow-8.4 {sash dragto subcommand, errors} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p add [button .b] [button .c]
+ .p sash dragto 0 foo bar
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {expected integer but got "foo"}
+test panedwindow-8.5 {sash dragto subcommand, errors} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p add [button .b] [button .c]
+ .p sash dragto 0 0 bar
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {expected integer but got "bar"}
+
+
+test panedwindow-9.1 {sash mark/sash dragto interaction} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 4 -showhandle false
+ .p add [frame .f -width 20 -height 20] [button .c -text foobar]
+ .p sash mark 0 10 10
+ .p sash dragto 0 20 10
+ .p sash coord 0
+} -cleanup {
+ deleteWindows
+} -result [list 30 0]
+test panedwindow-9.2 {sash mark/sash dragto interaction} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 4 -orient vertical \
+ -showhandle false
+ .p add [frame .p.f -width 20 -height 20] [button .p.c -text foobar]
+ .p sash mark 0 10 10
+ .p sash dragto 0 10 20
+ .p sash coord 0
+} -cleanup {
+ deleteWindows
+} -result [list 0 30]
+test panedwindow-9.3 {sash mark/sash dragto, respects minsize} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 4 -showhandle false
+ .p add [frame .f -width 20 -height 20] [button .c] -minsize 15
+ .p sash mark 0 20 10
+ .p sash dragto 0 10 10
+ .p sash coord 0
+} -cleanup {
+ deleteWindows
+} -result [list 15 0]
+
+
+test panedwindow-10.1 {sash place subcommand, errors} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p sash place
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {wrong # args: should be ".p sash place index x y"}
+test panedwindow-10.2 {sash place subcommand, errors} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p sash place foo bar baz
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {expected integer but got "foo"}
+test panedwindow-10.3 {sash place subcommand, errors} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p sash place 0 foo bar
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {invalid sash index}
+test panedwindow-10.4 {sash place subcommand, errors} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p add [button .b] [button .c]
+ .p sash place 0 foo bar
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {expected integer but got "foo"}
+test panedwindow-10.5 {sash place subcommand, errors} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p add [button .b] [button .c]
+ .p sash place 0 0 bar
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {expected integer but got "bar"}
+test panedwindow-10.6 {sash place subcommand, moves sash} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 4
+ .p add [frame .f -width 20 -height 20] [button .c]
+ .p sash place 0 10 0
+ .p sash coord 0
+} -cleanup {
+ deleteWindows
+} -result [list 10 0]
+test panedwindow-10.7 {sash place subcommand, moves sash} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 4 -orient vertical
+ .p add [frame .f -width 20 -height 20] [button .c]
+ .p sash place 0 0 10
+ .p sash coord 0
+} -cleanup {
+ deleteWindows
+} -result [list 0 10]
+test panedwindow-10.8 {sash place subcommand, respects minsize} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 4 -showhandle false
+ .p add [frame .f -width 20 -height 20] [button .c] -minsize 15
+ .p sash place 0 10 0
+ .p sash coord 0
+} -cleanup {
+ deleteWindows
+} -result [list 15 0]
+test panedwindow-10.9 {sash place subcommand, respects minsize} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p add [frame .f -width 20 -height 20 -bg pink]
+ .p sash place 0 2 0
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {invalid sash index}
+
+
+test panedwindow-11.1 {moving sash changes size of pane to left} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 4 -showhandle false
+ .p add [frame .f -width 20 -height 20] [button .c -text foobar] -sticky nsew
+ .p sash place 0 30 0
+ pack .p
+ update
+ winfo width .f
+} -result 30
+test panedwindow-11.2 {moving sash changes size of pane to right} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4
+ .p add [frame .f -width 20 -height 20] [frame .f2 -width 20 -height 20]
+ pack .p
+ update
+ set result [winfo width .f2]
+ .p sash place 0 30 0
+ update
+ lappend result [winfo width .f2]
+} -cleanup {
+ deleteWindows
+} -result {20 10}
+test panedwindow-11.3 {moving sash does not change reqsize of panedwindow} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4
+ .p add [frame .f -width 20 -height 20] [frame .f2 -width 20 -height 20]
+ .p sash place 0 30 0
+ winfo reqwidth .p
+} -result 44
+test panedwindow-11.4 {moving sash changes size of pane above} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4 \
+ -orient vertical
+ .p add [frame .f -width 20 -height 10] [button .c -text foobar] -sticky nsew
+ .p sash place 0 0 20
+ pack .p
+ update
+ set result [winfo height .f]
+ set result
+} -result 20
+test panedwindow-11.5 {moving sash changes size of pane below} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4 \
+ -orient vertical
+ .p add [frame .f -width 20 -height 10] [frame .f2 -width 20 -height 10]
+ pack .p
+ update
+ set result [winfo height .f2]
+ .p sash place 0 0 15
+ update
+ lappend result [winfo height .f2]
+ set result
+} -cleanup {
+ deleteWindows
+} -result {10 5}
+test panedwindow-11.6 {moving sash does not change reqsize of panedwindow} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4 \
+ -orient vertical
+ .p add [frame .f -width 20 -height 10] [frame .f2 -width 20 -height 10]
+ set result [winfo reqheight .p]
+ .p sash place 0 0 20
+ lappend result [winfo reqheight .p]
+ set result
+} -cleanup {
+ deleteWindows
+} -result [list 24 24]
+test panedwindow-11.7 {moving sash does not alter reqsize of widget} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4 \
+ -orient vertical
+ .p add [frame .f -width 20 -height 10] [frame .f2 -width 20 -height 10]
+ set result [winfo reqheight .f]
+ .p sash place 0 0 20
+ lappend result [winfo reqheight .f]
+} -cleanup {
+ deleteWindows
+} -result [list 10 10]
+test panedwindow-11.8 {moving sash restricted to minsize} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4
+ .p add [frame .f -width 20 -height 20] [button .c] -minsize 15
+ .p sash place 0 10 0
+ pack .p
+ update
+ winfo width .f
+} -result 15
+test panedwindow-11.9 {moving sash restricted to minsize} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4 \
+ -orient vertical
+ .p add [frame .f -width 20 -height 30] [button .c] -minsize 10
+ .p sash place 0 0 5
+ pack .p
+ update
+ winfo height .f
+} -result 10
+test panedwindow-11.10 {moving sash in unmapped window restricted to reqsize} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4
+ .p add [frame .f -width 20 -height 30] [frame .f2 -width 20 -height 20]
+ set result [list [.p sash coord 0]]
+ .p sash place 0 100 0
+ lappend result [.p sash coord 0]
+} -cleanup {
+ deleteWindows
+} -result [list {20 0} {40 0}]
+test panedwindow-11.11 {moving sash right pushes other sashes} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4
+ .p add [frame .f -width 20 -height 30] [frame .f2 -width 20 -height 20] \
+ [frame .f3 -width 20 -height 30]
+ .p sash place 0 80 0
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{60 0} {64 0}}
+test panedwindow-11.12 {moving sash left pushes other sashes} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4
+ .p add [frame .f -width 20 -height 30] [frame .f2 -width 20 -height 20] \
+ [frame .f3 -width 20 -height 30]
+ .p sash place 1 0 0
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{0 0} {4 0}}
+test panedwindow-11.13 {move sash in mapped window restricted to visible win} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4
+ .p add [frame .f -width 20 -height 30] [frame .f2 -width 20 -height 20] \
+ [frame .f3 -width 20 -height 30]
+ place .p -width 50
+ update
+ .p sash place 1 100 0
+ update
+ .p sash coord 1
+} -cleanup {
+ deleteWindows
+} -result {46 0}
+test panedwindow-11.14 {move sash in mapped window restricted to visible win} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4
+ .p add [frame .f -width 20 -height 30] [frame .f2 -width 20 -height 20] \
+ [frame .f3 -width 20 -height 30]
+ place .p -width 100
+ update
+ .p sash place 1 200 0
+ update
+ .p sash coord 1
+} -cleanup {
+ deleteWindows
+} -result {96 0}
+test panedwindow-11.15 {moving sash into "virtual" space on last pane increases reqsize} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4
+ .p add [frame .f -width 20 -height 30] [frame .f2 -width 20 -height 20] \
+ [frame .f3 -width 20 -height 30]
+ place .p -width 100
+ set result [winfo reqwidth .p]
+ update
+ .p sash place 1 200 0
+ update
+ lappend result [winfo reqwidth .p]
+} -cleanup {
+ deleteWindows
+} -result {68 100}
+
+
+test panedwindow-12.1 {horizontal panedwindow lays out widgets properly} -setup {
+ deleteWindows
+ set result {}
+} -body {
+ panedwindow .p -showhandle false -borderwidth 2 -sashpad 2 -sashwidth 2
+ foreach win {.p.f .p.f2 .p.f3} {.p add [frame $win -width 20 -height 10]}
+ pack .p
+ update
+ foreach w [.p panes] {lappend result [winfo x $w] [winfo y $w]}
+ return $result
+} -cleanup {
+ deleteWindows
+} -result [list 2 2 28 2 54 2]
+test panedwindow-12.2 {vertical panedwindow lays out widgets properly} -setup {
+ deleteWindows
+ set result {}
+} -body {
+ panedwindow .p -showhandle false -borderwidth 2 -sashpad 2 -sashwidth 2 \
+ -orient vertical
+ foreach win {.p.f .p.f2 .p.f3} {.p add [frame $win -width 20 -height 10]}
+ pack .p
+ update
+ foreach w [.p panes] {lappend result [winfo x $w] [winfo y $w]}
+ return $result
+} -cleanup {
+ deleteWindows
+} -result [list 2 2 2 18 2 34]
+test panedwindow-12.3 {horizontal panedwindow lays out widgets properly} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ foreach {win color} {.p.f blue .p.f2 green} {
+ .p add [frame $win -width 20 -height 20 -bg $color] -padx 10 -pady 5 \
+ -sticky ""
+ }
+ pack .p
+ update
+ set result [list [winfo reqwidth .p] [winfo reqheight .p]]
+ foreach win {.p.f .p.f2} {lappend result [winfo x $win] [winfo y $win]}
+ .p paneconfigure .p.f -padx 0 -pady 0
+ update
+ lappend result [winfo reqwidth .p] [winfo reqheight .p]
+ foreach win {.p.f .p.f2} {lappend result [winfo x $win] [winfo y $win]}
+ return $result
+} -cleanup {
+ deleteWindows
+} -result [list 80 30 10 5 50 5 60 30 0 5 30 5]
+test panedwindow-12.4 {vertical panedwindow lays out widgets properly} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0 \
+ -orient vertical
+ foreach win {.p.f .p.f2} {
+ .p add [frame $win -width 20 -height 20] -padx 10 -pady 5 -sticky ""
+ }
+ pack .p
+ update
+ set result [list [winfo reqwidth .p] [winfo reqheight .p]]
+ foreach win {.p.f .p.f2} {lappend result [winfo x $win] [winfo y $win]}
+ .p paneconfigure .p.f -padx 0 -pady 0
+ update
+ lappend result [winfo reqwidth .p] [winfo reqheight .p]
+ foreach win {.p.f .p.f2} {lappend result [winfo x $win] [winfo y $win]}
+ return $result
+} -cleanup {
+ deleteWindows
+} -result [list 40 60 10 5 10 35 40 50 10 0 10 25]
+test panedwindow-12.5 {panedwindow respects reqsize of panes when possible} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ .p add [frame .p.f -width 20 -height 20] -sticky ""
+ place .p -width 40
+ update
+ set result [list [winfo width .p.f]]
+ .p.f configure -width 30
+ update
+ lappend result [winfo width .p.f]
+} -cleanup {
+ deleteWindows
+} -result [list 20 30]
+test panedwindow-12.6 {panedwindow takes explicit widget width over reqwidth} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ .p add [frame .p.f -width 20 -height 20] -width 20 -sticky ""
+ place .p -width 40
+ update
+ set result [list [winfo width .p.f]]
+ .p.f configure -width 30
+ update
+ lappend result [winfo width .p.f]
+} -cleanup {
+ deleteWindows
+} -result [list 20 20]
+test panedwindow-12.7 {horizontal panedwindow reqheight is max slave height} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4
+ .p add [frame .p.f -width 20 -height 20] [frame .p.f2 -width 20 -height 20]
+ set result [winfo reqheight .p]
+ .p.f config -height 40
+ lappend result [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {20 40}
+test panedwindow-12.8 {horizontal panedwindow reqheight is max slave height} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4
+ foreach win {.p.f .p.f2} {.p add [frame $win -width 20 -height 20]}
+ .p paneconfigure .p.f -height 15
+ set result [winfo reqheight .p]
+ .p.f config -height 40
+ lappend result [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {20 20}
+test panedwindow-12.9 {panedwindow pane width overrides widget width} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4
+ foreach win {.p.f .p.f2} {.p add [frame $win -width 20 -height 20]}
+ .p sash place 0 10 0
+ pack .p
+ update
+ set result [winfo width .p.f]
+ .p paneconfigure .p.f -width 30
+ lappend result [winfo width .p.f]
+} -cleanup {
+ deleteWindows
+} -result [list 10 10]
+test panedwindow-12.10 {panedwindow respects reqsize of panes when possible} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ .p add [frame .p.f -width 20 -height 20] -sticky ""
+ place .p -height 40
+ update
+ set result [list [winfo height .p.f]]
+ .p.f configure -height 30
+ update
+ lappend result [winfo height .p.f]
+} -cleanup {
+ deleteWindows
+} -result [list 20 30]
+test panedwindow-12.11 {panedwindow takes explicit height over reqheight} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ .p add [frame .p.f -width 20 -height 20] -height 20 -sticky ""
+ place .p -height 40
+ update
+ set result [list [winfo height .p.f]]
+ .p.f configure -height 30
+ update
+ lappend result [winfo height .p.f]
+} -cleanup {
+ deleteWindows
+} -result [list 20 20]
+test panedwindow-12.12 {vertical panedwindow reqwidth is max slave width} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4 \
+ -orient vertical
+ .p add [frame .p.f -width 20 -height 20] [frame .p.f2 -width 20 -height 20]
+ set result [winfo reqwidth .p]
+ .p.f config -width 40
+ lappend result [winfo reqwidth .p]
+} -cleanup {
+ deleteWindows
+} -result {20 40}
+test panedwindow-12.13 {vertical panedwindow reqwidth is max slave width} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4 \
+ -orient vertical
+ foreach win {.p.f .p.f2} {.p add [frame $win -width 20 -height 20]}
+ .p paneconfigure .p.f -width 15
+ set result [winfo reqwidth .p]
+ .p.f config -width 40
+ lappend result [winfo reqwidth .p]
+} -cleanup {
+ deleteWindows
+} -result {20 20}
+test panedwindow-12.14 {panedwindow pane height overrides widget width} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4 \
+ -orient vertical
+ foreach win {.p.f .p.f2} {.p add [frame $win -width 20 -height 20]}
+ .p sash place 0 0 10
+ pack .p
+ update
+ set result [winfo height .p.f]
+ .p paneconfigure .p.f -height 30
+ lappend result [winfo height .p.f]
+} -cleanup {
+ deleteWindows
+} -result [list 10 10]
+
+
+test panedwindow-13.1 {PanestructureProc, widget yields managements} -setup {
+ deleteWindows
+} -body {
+ # Check that the panedwindow correctly yields geometry management of
+ # a slave when the slave is destroyed.
+
+ # This test should not cause a core dump, and it should not cause
+ # a memory leak.
+ panedwindow .p
+ .p add [button .b]
+ destroy .p
+ pack .b
+ destroy .b
+ set result ""
+} -result {}
+test panedwindow-13.2 {PanedWindowLostSlaveProc, widget yields management} -setup {
+ deleteWindows
+} -body {
+ # Check that the paned window correctly yields geometry management of
+ # a slave when some other geometry manager steals the slave from us.
+
+ # This test should not cause a core dump, and it should not cause a
+ # memory leak.
+ panedwindow .p
+ .p add [button .b]
+ pack .p
+ update
+ pack .b
+ update
+ set result [.p panes]
+ destroy .p .b
+ set result
+} -result {}
+
+
+test panedwindow-14.1 {panedwindow sticky settings} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false
+ .p add [button .b]
+ .p paneconfigure .b -sticky n
+ .p panecget .b -sticky
+} -cleanup {
+ deleteWindows
+} -result {n}
+test panedwindow-14.2 {panedwindow sticky settings} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false
+ .p add [button .b]
+ .p paneconfigure .b -sticky s
+ .p panecget .b -sticky
+} -cleanup {
+ deleteWindows
+} -result {s}
+test panedwindow-14.3 {panedwindow sticky settings} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false
+ .p add [button .b]
+ .p paneconfigure .b -sticky e
+ .p panecget .b -sticky
+} -cleanup {
+ deleteWindows
+} -result {e}
+test panedwindow-14.4 {panedwindow sticky settings} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false
+ .p add [button .b]
+ .p paneconfigure .b -sticky w
+ .p panecget .b -sticky
+} -cleanup {
+ deleteWindows
+} -result {w}
+test panedwindow-14.5 {panedwindow sticky settings} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false
+ .p add [button .b]
+ .p paneconfigure .b -sticky sn
+ .p panecget .b -sticky
+} -cleanup {
+ deleteWindows
+} -result {ns}
+test panedwindow-14.6 {panedwindow sticky settings} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false
+ .p add [button .b]
+ .p paneconfigure .b -sticky ns
+ .p panecget .b -sticky
+} -cleanup {
+ deleteWindows
+} -result {ns}
+test panedwindow-14.7 {panedwindow sticky settings} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false
+ .p add [button .b]
+ .p paneconfigure .b -sticky en
+ .p panecget .b -sticky
+} -cleanup {
+ deleteWindows
+} -result {ne}
+test panedwindow-14.8 {panedwindow sticky settings} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false
+ .p add [button .b]
+ .p paneconfigure .b -sticky ne
+ .p panecget .b -sticky
+} -cleanup {
+ deleteWindows
+} -result {ne}
+test panedwindow-14.9 {panedwindow sticky settings} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false
+ .p add [button .b]
+ .p paneconfigure .b -sticky wn
+ .p panecget .b -sticky
+} -cleanup {
+ deleteWindows
+} -result {nw}
+test panedwindow-14.10 {panedwindow sticky settings} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false
+ .p add [button .b]
+ .p paneconfigure .b -sticky nw
+ .p panecget .b -sticky
+} -cleanup {
+ deleteWindows
+} -result {nw}
+test panedwindow-14.11 {panedwindow sticky settings} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false
+ .p add [button .b]
+ .p paneconfigure .b -sticky esn
+ .p panecget .b -sticky
+} -cleanup {
+ deleteWindows
+} -result {nes}
+test panedwindow-14.12 {panedwindow sticky settings} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false
+ .p add [button .b]
+ .p paneconfigure .b -sticky nse
+ .p panecget .b -sticky
+} -cleanup {
+ deleteWindows
+} -result {nes}
+test panedwindow-14.13 {panedwindow sticky settings} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false
+ .p add [button .b]
+ .p paneconfigure .b -sticky nsw
+ .p panecget .b -sticky
+} -cleanup {
+ deleteWindows
+} -result {nsw}
+test panedwindow-14.14 {panedwindow sticky settings} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false
+ .p add [button .b]
+ .p paneconfigure .b -sticky nsew
+ .p panecget .b -sticky
+} -cleanup {
+ deleteWindows
+} -result {nesw}
+test panedwindow-14.15 {panedwindow sticky settings} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false
+ .p add [button .b]
+ .p paneconfigure .b -sticky ""
+ .p panecget .b -sticky
+} -cleanup {
+ deleteWindows
+} -result {}
+
+
+test panedwindow-15.1 {panedwindow sticky works} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ .p add [frame .p.f -height 20 -width 20 -bg red] -sticky {}
+ place .p -width 40 -height 40
+ update
+ list {} [winfo x .p.f] [winfo y .p.f] [winfo width .p.f] [winfo height .p.f]
+} -cleanup {
+ deleteWindows
+} -result {{} 10 10 20 20}
+test panedwindow-15.2 {panedwindow sticky works} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ .p add [frame .p.f -height 20 -width 20 -bg red] -sticky n
+ place .p -width 40 -height 40
+ update
+ list n [winfo x .p.f] [winfo y .p.f] [winfo width .p.f] [winfo height .p.f]
+} -cleanup {
+ deleteWindows
+} -result {n 10 0 20 20}
+test panedwindow-15.3 {panedwindow sticky works} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ .p add [frame .p.f -height 20 -width 20 -bg red] -sticky s
+ place .p -width 40 -height 40
+ update
+ list s [winfo x .p.f] [winfo y .p.f] [winfo width .p.f] [winfo height .p.f]
+} -cleanup {
+ deleteWindows
+} -result {s 10 20 20 20}
+test panedwindow-15.4 {panedwindow sticky works} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ .p add [frame .p.f -height 20 -width 20 -bg red] -sticky e
+ place .p -width 40 -height 40
+ update
+ list e [winfo x .p.f] [winfo y .p.f] [winfo width .p.f] [winfo height .p.f]
+} -cleanup {
+ deleteWindows
+} -result {e 20 10 20 20}
+test panedwindow-15.5 {panedwindow sticky works} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ .p add [frame .p.f -height 20 -width 20 -bg red] -sticky w
+ place .p -width 40 -height 40
+ update
+ list w [winfo x .p.f] [winfo y .p.f] [winfo width .p.f] [winfo height .p.f]
+} -cleanup {
+ deleteWindows
+} -result {w 0 10 20 20}
+test panedwindow-15.6 {panedwindow sticky works} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ .p add [frame .p.f -height 20 -width 20 -bg red] -sticky ns
+ place .p -width 40 -height 40
+ update
+ list ns [winfo x .p.f] [winfo y .p.f] [winfo width .p.f] [winfo height .p.f]
+} -cleanup {
+ deleteWindows
+} -result {ns 10 0 20 40}
+test panedwindow-15.7 {panedwindow sticky works} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ .p add [frame .p.f -height 20 -width 20 -bg red] -sticky ew
+ place .p -width 40 -height 40
+ update
+ list ew [winfo x .p.f] [winfo y .p.f] [winfo width .p.f] [winfo height .p.f]
+} -cleanup {
+ deleteWindows
+} -result {ew 0 10 40 20}
+test panedwindow-15.8 {panedwindow sticky works} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ .p add [frame .p.f -height 20 -width 20 -bg red] -sticky nw
+ place .p -width 40 -height 40
+ update
+ list nw [winfo x .p.f] [winfo y .p.f] [winfo width .p.f] [winfo height .p.f]
+} -cleanup {
+ deleteWindows
+} -result {nw 0 0 20 20}
+test panedwindow-15.9 {panedwindow sticky works} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ .p add [frame .p.f -height 20 -width 20 -bg red] -sticky ne
+ place .p -width 40 -height 40
+ update
+ list ne [winfo x .p.f] [winfo y .p.f] [winfo width .p.f] [winfo height .p.f]
+} -cleanup {
+ deleteWindows
+} -result {ne 20 0 20 20}
+test panedwindow-15.10 {panedwindow sticky works} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ .p add [frame .p.f -height 20 -width 20 -bg red] -sticky se
+ place .p -width 40 -height 40
+ update
+ list se [winfo x .p.f] [winfo y .p.f] [winfo width .p.f] [winfo height .p.f]
+} -cleanup {
+ deleteWindows
+} -result {se 20 20 20 20}
+test panedwindow-15.11 {panedwindow sticky works} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ .p add [frame .p.f -height 20 -width 20 -bg red] -sticky sw
+ place .p -width 40 -height 40
+ update
+ list sw [winfo x .p.f] [winfo y .p.f] [winfo width .p.f] [winfo height .p.f]
+} -cleanup {
+ deleteWindows
+} -result {sw 0 20 20 20}
+test panedwindow-15.12 {panedwindow sticky works} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ .p add [frame .p.f -height 20 -width 20 -bg red] -sticky nse
+ place .p -width 40 -height 40
+ update
+ list nse [winfo x .p.f] [winfo y .p.f] [winfo width .p.f] [winfo height .p.f]
+} -cleanup {
+ deleteWindows
+} -result {nse 20 0 20 40}
+test panedwindow-15.13 {panedwindow sticky works} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ .p add [frame .p.f -height 20 -width 20 -bg red] -sticky nsw
+ place .p -width 40 -height 40
+ update
+ list nsw [winfo x .p.f] [winfo y .p.f] [winfo width .p.f] [winfo height .p.f]
+} -cleanup {
+ deleteWindows
+} -result {nsw 0 0 20 40}
+test panedwindow-15.14 {panedwindow sticky works} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ .p add [frame .p.f -height 20 -width 20 -bg red] -sticky sew
+ place .p -width 40 -height 40
+ update
+ list sew [winfo x .p.f] [winfo y .p.f] [winfo width .p.f] [winfo height .p.f]
+} -cleanup {
+ deleteWindows
+} -result {sew 0 20 40 20}
+test panedwindow-15.15 {panedwindow sticky works} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ .p add [frame .p.f -height 20 -width 20 -bg red] -sticky new
+ place .p -width 40 -height 40
+ update
+ list new [winfo x .p.f] [winfo y .p.f] [winfo width .p.f] [winfo height .p.f]
+} -cleanup {
+ deleteWindows
+} -result {new 0 0 40 20}
+test panedwindow-15.16 {panedwindow sticky works} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ .p add [frame .p.f -height 20 -width 20 -bg red] -sticky news
+ place .p -width 40 -height 40
+ update
+ list news [winfo x .p.f] [winfo y .p.f] [winfo width .p.f] [winfo height .p.f]
+} -cleanup {
+ deleteWindows
+} -result {news 0 0 40 40}
+
+
+test panedwindow-16.1 {setting minsize when pane is too small snaps width} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ .p add [frame .p.f -height 20 -width 20 -bg red]
+ set result [winfo reqwidth .p]
+ .p paneconfigure .p.f -minsize 40
+ lappend result [winfo reqwidth .p]
+} -cleanup {
+ deleteWindows
+} -result [list 20 40]
+
+
+test panedwindow-17.1 {MoveSash, move right} -setup {
+ deleteWindows
+ set result {}
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ # Get the requested width of the paned window
+ lappend result [winfo reqwidth .p]
+
+ .p sash place 0 30 0
+
+ # Get the reqwidth again, to make sure it hasn't changed
+ lappend result [winfo reqwidth .p]
+
+ # Check that the sash moved
+ lappend result [.p sash coord 0]
+} -cleanup {
+ deleteWindows
+} -result [list 42 42 {30 0}]
+test panedwindow-17.2 {MoveSash, move right (unmapped) clipped by reqwidth} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ .p sash place 0 100 0
+
+ # Get the new sash coord; it should be clipped by the reqwidth of
+ # the panedwindow.
+ .p sash coord 0
+} -cleanup {
+ deleteWindows
+} -result [list 40 0]
+test panedwindow-17.3 {MoveSash, move right (mapped, width < reqwidth) clipped by width} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ # Put the panedwindow up on the display and give it a width < reqwidth
+ place .p -x 0 -y 0 -width 32
+ update
+
+ .p sash place 0 100 0
+
+ # Get the new sash coord; it should be clipped by the visible width of
+ # the panedwindow.
+ .p sash coord 0
+} -cleanup {
+ deleteWindows
+} -result [list 30 0]
+test panedwindow-17.4 {MoveSash, move right (mapped, width > reqwidth) clipped by width} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ # Put the panedwindow up on the display and give it a width > reqwidth
+ place .p -x 0 -y 0 -width 102
+ update
+
+ .p sash place 0 200 0
+
+ # Get the new sash coord; it should be clipped by the visible width of
+ # the panedwindow.
+ .p sash coord 0
+} -cleanup {
+ deleteWindows
+} -result [list 100 0]
+test panedwindow-17.5 {MoveSash, move right respects minsize} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
+ }
+
+ .p sash place 0 100 0
+
+ # Get the new sash coord; it should have moved as far as possible while
+ # respecting minsizes.
+ .p sash coord 0
+} -cleanup {
+ deleteWindows
+} -result [list 30 0]
+test panedwindow-17.6 {MoveSash, move right respects minsize} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
+ }
+
+ .p sash place 0 100 0
+
+ # Get the new sash coord; it should have moved as far as possible.
+ .p sash coord 0
+} -cleanup {
+ deleteWindows
+} -result [list 40 0]
+test panedwindow-17.7 {MoveSash, move right pushes other sashes} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ .p sash place 0 100 0
+
+ # Get the new sash coord; it should have moved as far as possible while
+ # respecting minsizes.
+ .p sash coord 1
+} -cleanup {
+ deleteWindows
+} -result [list 62 0]
+test panedwindow-17.8 {MoveSash, move right pushes other sashes, respects minsize} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
+ }
+
+ .p sash place 0 100 0
+
+ # Get the new sash coord; it should have moved as far as possible while
+ # respecting minsizes.
+ .p sash coord 1
+} -cleanup {
+ deleteWindows
+} -result [list 52 0]
+test panedwindow-17.9 {MoveSash, move right respects minsize, exludes pad} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] \
+ -sticky nsew -minsize 10 -padx 5
+ }
+
+ .p sash place 0 100 0
+
+ # Get the new sash coord; it should have moved as far as possible,
+ # respecting minsizes.
+ .p sash coord 0
+} -cleanup {
+ deleteWindows
+} -result [list 50 0]
+test panedwindow-17.10 {MoveSash, move right, negative minsize becomes 0} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] \
+ -sticky nsew -minsize -50
+ }
+
+ .p sash place 0 50 0
+
+ # Get the new sash coord; it should have moved as far as possible,
+ # respecting minsizes.
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result [list [list 50 0] [list 52 0]]
+test panedwindow-17.11 {MoveSash, move left} -setup {
+ deleteWindows
+} -body {
+ set result {}
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ # Get the requested width of the paned window
+ lappend result [winfo reqwidth .p]
+
+ .p sash place 0 10 0
+
+ # Get the reqwidth again, to make sure it hasn't changed
+ lappend result [winfo reqwidth .p]
+
+ # Check that the sash moved
+ lappend result [.p sash coord 0]
+} -cleanup {
+ deleteWindows
+} -result [list 42 42 {10 0}]
+test panedwindow-17.12 {MoveSash, move left, can't move outside of window} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ .p sash place 0 -100 0
+
+ # Get the new sash coord; it should be clipped by the reqwidth of
+ # the panedwindow.
+ .p sash coord 0
+} -cleanup {
+ deleteWindows
+} -result [list 0 0]
+test panedwindow-17.13 {MoveSash, move left respects minsize} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
+ }
+
+ .p sash place 0 0 0
+
+ # Get the new sash coord; it should have moved as far as possible while
+ # respecting minsizes.
+ .p sash coord 0
+} -cleanup {
+ deleteWindows
+} -result [list 10 0]
+test panedwindow-17.14 {MoveSash, move left respects minsize} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
+ }
+
+ .p sash place 1 0 0
+
+ # Get the new sash coord; it should have moved as far as possible.
+ .p sash coord 1
+} -cleanup {
+ deleteWindows
+} -result [list 22 0]
+test panedwindow-17.15 {MoveSash, move left pushes other sashes} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ .p sash place 1 0 0
+
+ # Get the new sash coord; it should have moved as far as possible while
+ # respecting minsizes.
+ .p sash coord 0
+} -cleanup {
+ deleteWindows
+} -result [list 0 0]
+test panedwindow-17.16 {MoveSash, move left pushes other sashes, respects minsize} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
+ }
+
+ .p sash place 1 0 0
+
+ # Get the new sash coord; it should have moved as far as possible while
+ # respecting minsizes.
+ .p sash coord 0
+} -cleanup {
+ deleteWindows
+} -result [list 10 0]
+test panedwindow-17.17 {MoveSash, move left respects minsize, exludes pad} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] \
+ -sticky nsew -minsize 10 -padx 5
+ }
+
+ .p sash place 1 0 0
+
+ # Get the new sash coord; it should have moved as far as possible,
+ # respecting minsizes.
+ .p sash coord 1
+} -cleanup {
+ deleteWindows
+} -result [list 42 0]
+test panedwindow-17.18 {MoveSash, move left, negative minsize becomes 0} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2 .f3} c {red blue green} {
+ .p add [frame $w -height 20 -width 20 -bg $c] \
+ -sticky nsew -minsize -50
+ }
+
+ .p sash place 1 10 0
+
+ # Get the new sash coord; it should have moved as far as possible,
+ # respecting minsizes.
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result [list [list 8 0] [list 10 0]]
+
+
+test panedwindow-18.1 {MoveSash, move down} -setup {
+ deleteWindows
+} -body {
+ set result {}
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ # Get the requested width of the paned window
+ lappend result [winfo reqheight .p]
+
+ .p sash place 0 0 30
+
+ # Get the reqwidth again, to make sure it hasn't changed
+ lappend result [winfo reqheight .p]
+
+ # Check that the sash moved
+ lappend result [.p sash coord 0]
+} -cleanup {
+ deleteWindows
+} -result [list 42 42 {0 30}]
+test panedwindow-18.2 {MoveSash, move down (unmapped) clipped by reqheight} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ .p sash place 0 0 100
+
+ # Get the new sash coord; it should be clipped by the reqheight of
+ # the panedwindow.
+ .p sash coord 0
+} -cleanup {
+ deleteWindows
+} -result [list 0 40]
+test panedwindow-18.3 {MoveSash, move down (mapped, height < reqheight) clipped by height} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ # Put the panedwindow up on the display and give it a height < reqheight
+ place .p -x 0 -y 0 -height 32
+ update
+
+ .p sash place 0 0 100
+
+ # Get the new sash coord; it should be clipped by the visible height of
+ # the panedwindow.
+ .p sash coord 0
+} -cleanup {
+ deleteWindows
+} -result [list 0 30]
+test panedwindow-18.4 {MoveSash, move down (mapped, height > reqheight) clipped by height} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ # Put the panedwindow up on the display and give it a width > reqwidth
+ place .p -x 0 -y 0 -height 102
+ update
+
+ .p sash place 0 0 200
+
+ # Get the new sash coord; it should be clipped by the visible width of
+ # the panedwindow.
+ .p sash coord 0
+} -cleanup {
+ deleteWindows
+} -result [list 0 100]
+test panedwindow-18.5 {MoveSash, move down respects minsize} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
+ }
+
+ .p sash place 0 0 100
+
+ # Get the new sash coord; it should have moved as far as possible while
+ # respecting minsizes.
+ .p sash coord 0
+} -cleanup {
+ deleteWindows
+} -result [list 0 30]
+test panedwindow-18.6 {MoveSash, move down respects minsize} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
+ }
+
+ .p sash place 0 0 100
+
+ # Get the new sash coord; it should have moved as far as possible while
+ # respecting minsizes.
+ .p sash coord 0
+} -cleanup {
+ deleteWindows
+} -result [list 0 40]
+test panedwindow-18.7 {MoveSash, move down pushes other sashes} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ .p sash place 0 0 100
+
+ # Get the new sash coord; it should have moved as far as possible while
+ # respecting minsizes.
+ .p sash coord 1
+} -cleanup {
+ deleteWindows
+} -result [list 0 62]
+test panedwindow-18.8 {MoveSash, move down pushes other sashes, respects minsize} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
+ }
+
+ .p sash place 0 0 100
+
+ # Get the new sash coord; it should have moved as far as possible while
+ # respecting minsizes.
+ .p sash coord 1
+} -cleanup {
+ deleteWindows
+} -result [list 0 52]
+test panedwindow-18.9 {MoveSash, move down respects minsize, exludes pad} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] \
+ -sticky nsew -minsize 10 -pady 5
+ }
+
+ .p sash place 0 0 100
+
+ # Get the new sash coord; it should have moved as far as possible,
+ # respecting minsizes.
+ .p sash coord 0
+} -cleanup {
+ deleteWindows
+} -result [list 0 50]
+test panedwindow-18.10 {MoveSash, move right, negative minsize becomes 0} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] \
+ -sticky nsew -minsize -50
+ }
+
+ .p sash place 0 0 50
+
+ # Get the new sash coord; it should have moved as far as possible,
+ # respecting minsizes.
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result [list [list 0 50] [list 0 52]]
+test panedwindow-18.11 {MoveSash, move up} -setup {
+ deleteWindows
+} -body {
+ set result {}
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ # Get the requested width of the paned window
+ lappend result [winfo reqheight .p]
+
+ .p sash place 0 0 10
+
+ # Get the reqwidth again, to make sure it hasn't changed
+ lappend result [winfo reqheight .p]
+
+ # Check that the sash moved
+ lappend result [.p sash coord 0]
+} -cleanup {
+ deleteWindows
+} -result [list 42 42 {0 10}]
+test panedwindow-18.12 {MoveSash, move up, can't move outside of window} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ .p sash place 0 0 -100
+
+ # Get the new sash coord; it should be clipped by the reqwidth of
+ # the panedwindow.
+ .p sash coord 0
+} -cleanup {
+ deleteWindows
+} -result [list 0 0]
+test panedwindow-18.13 {MoveSash, move up respects minsize} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
+ }
+
+ .p sash place 0 0 0
+
+ # Get the new sash coord; it should have moved as far as possible while
+ # respecting minsizes.
+ .p sash coord 0
+} -cleanup {
+ deleteWindows
+} -result [list 0 10]
+test panedwindow-18.14 {MoveSash, move up respects minsize} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
+ }
+
+ .p sash place 1 0 0
+
+ # Get the new sash coord; it should have moved as far as possible.
+ .p sash coord 1
+} -cleanup {
+ deleteWindows
+} -result [list 0 22]
+test panedwindow-18.15 {MoveSash, move up pushes other sashes} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ .p sash place 1 0 0
+
+ # Get the new sash coord; it should have moved as far as possible while
+ # respecting minsizes.
+ .p sash coord 0
+} -cleanup {
+ deleteWindows
+} -result [list 0 0]
+test panedwindow-18.16 {MoveSash, move up pushes other sashes, respects minsize} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
+ }
+
+ .p sash place 1 0 0
+
+ # Get the new sash coord; it should have moved as far as possible while
+ # respecting minsizes.
+ .p sash coord 0
+} -cleanup {
+ deleteWindows
+} -result [list 0 10]
+test panedwindow-18.17 {MoveSash, move up respects minsize, exludes pad} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] \
+ -sticky nsew -minsize 10 -pady 5
+ }
+
+ .p sash place 1 0 0
+
+ # Get the new sash coord; it should have moved as far as possible,
+ # respecting minsizes.
+ .p sash coord 1
+} -cleanup {
+ deleteWindows
+} -result [list 0 42]
+test panedwindow-18.18 {MoveSash, move up, negative minsize becomes 0} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} c {red blue green} {
+ .p add [frame $w -height 20 -width 20 -bg $c] \
+ -sticky nsew -minsize -50
+ }
+
+ .p sash place 1 0 10
+
+ # Get the new sash coord; it should have moved as far as possible,
+ # respecting minsizes.
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result [list [list 0 8] [list 0 10]]
+
+
+# The following tests check that the panedwindow is correctly computing its
+# geometry based on the various configuration options that can affect the
+# geometry.
+
+test panedwindow-19.1 {ComputeGeometry, reqheight taken from widgets} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue]
+ }
+ set result [list [list [winfo reqwidth .p] [winfo reqheight .p]]]
+ .f3 configure -height 40
+ lappend result [list [winfo reqwidth .p] [winfo reqheight .p]]
+} -cleanup {
+ deleteWindows
+} -result [list [list 60 20] [list 60 40]]
+
+test panedwindow-19.2 {ComputeGeometry, reqheight taken from widgets} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue]
+ }
+ set result [list [list [winfo reqwidth .p] [winfo reqheight .p]]]
+ .p paneconfigure .f3 -height 40
+ lappend result [list [winfo reqwidth .p] [winfo reqheight .p]]
+} -cleanup {
+ deleteWindows
+} -result [list [list 60 20] [list 60 40]]
+
+test panedwindow-19.3 {ComputeGeometry, reqheight taken from widgets} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] -pady 20
+ }
+ set result [list [list [winfo reqwidth .p] [winfo reqheight .p]]]
+ .p paneconfigure .f3 -height 40
+ lappend result [list [winfo reqwidth .p] [winfo reqheight .p]]
+} -cleanup {
+ deleteWindows
+} -result [list [list 60 60] [list 60 80]]
+
+test panedwindow-19.4 {ComputeGeometry, reqwidth taken from widgets} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue]
+ }
+ set result [list [list [winfo reqwidth .p] [winfo reqheight .p]]]
+ .f3 configure -width 40
+ lappend result [list [winfo reqwidth .p] [winfo reqheight .p]]
+} -cleanup {
+ deleteWindows
+} -result [list [list 20 60] [list 40 60]]
+
+test panedwindow-19.5 {ComputeGeometry, reqwidth taken from widgets} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue]
+ }
+ set result [list [list [winfo reqwidth .p] [winfo reqheight .p]]]
+ .p paneconfigure .f3 -width 40
+ lappend result [list [winfo reqwidth .p] [winfo reqheight .p]]
+} -cleanup {
+ deleteWindows
+} -result [list [list 20 60] [list 40 60]]
+
+test panedwindow-19.6 {ComputeGeometry, reqwidth taken from widgets} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] -padx 20
+ }
+ set result [list [list [winfo reqwidth .p] [winfo reqheight .p]]]
+ .p paneconfigure .f3 -width 40
+ lappend result [list [winfo reqwidth .p] [winfo reqheight .p]]
+} -cleanup {
+ deleteWindows
+} -result [list [list 60 60] [list 80 60]]
+
+test panedwindow-19.7 {ComputeGeometry, one slave, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -sashwidth 0 -handlesize 6 -showhandle 0
+ .p add [frame .p.f -width 20 -height 20 -bg red] -padx 0 -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {20 20}
+
+test panedwindow-19.8 {ComputeGeometry, three panes, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -sashwidth 0 -handlesize 6 -showhandle 0
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {60 20}
+
+test panedwindow-19.9 {ComputeGeometry, sash coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -sashwidth 0 -handlesize 6 -showhandle 0
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{20 0} {40 0}}
+
+test panedwindow-19.10 {ComputeGeometry/ArrangePanes, slave coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -sashwidth 0 -handlesize 6 -showhandle 0
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 3 -padx 11
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{11 3 20 20} {53 3 20 20} {95 3 20 20}}
+
+test panedwindow-19.11 {ComputeGeometry, one slave, vertical} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -orient vertical -sashwidth 0 -handlesize 6 \
+ -showhandle 0
+ .p add [frame .f -width 20 -height 20 -bg red] -pady 0 \
+ -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {20 20}
+
+test panedwindow-19.12 {ComputeGeometry, three panes, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -sashwidth 0 -handlesize 6 -showhandle 0 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {20 60}
+
+test panedwindow-19.13 {ComputeGeometry, sash coords, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -sashwidth 0 -handlesize 6 -showhandle 0 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{0 20} {0 40}}
+
+test panedwindow-19.14 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -sashwidth 0 -handlesize 6 -showhandle 0 \
+ -orient vertical
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 11 -padx 3
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{3 11 20 20} {3 53 20 20} {3 95 20 20}}
+test panedwindow-19.15 {ComputeGeometry, one slave, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -sashwidth 0 -handlesize 6 -showhandle 1
+ .p add [frame .p.f -width 20 -height 20 -bg red] -padx 1 -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {22 20}
+
+test panedwindow-19.16 {ComputeGeometry, three panes, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -sashwidth 0 -handlesize 6 -showhandle 1
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {72 20}
+
+test panedwindow-19.17 {ComputeGeometry, sash coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -sashwidth 0 -handlesize 6 -showhandle 1
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{23 0} {49 0}}
+
+test panedwindow-19.18 {ComputeGeometry/ArrangePanes, slave coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -sashwidth 0 -handlesize 6 -showhandle 1
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 3 -padx 11
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{11 3 20 20} {59 3 20 20} {107 3 20 20}}
+
+test panedwindow-19.19 {ComputeGeometry, one slave, vertical} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -orient vertical -sashwidth 0 -handlesize 6 \
+ -showhandle 1
+ .p add [frame .f -width 20 -height 20 -bg red] -pady 1 \
+ -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {20 22}
+
+test panedwindow-19.20 {ComputeGeometry, three panes, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -sashwidth 0 -handlesize 6 -showhandle 1 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {20 72}
+
+test panedwindow-19.21 {ComputeGeometry, sash coords, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -sashwidth 0 -handlesize 6 -showhandle 1 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{0 23} {0 49}}
+
+test panedwindow-19.22 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -sashwidth 0 -handlesize 6 -showhandle 1 \
+ -orient vertical
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 11 -padx 3
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{3 11 20 20} {3 59 20 20} {3 107 20 20}}
+test panedwindow-19.23 {ComputeGeometry, one slave, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -sashwidth 3 -handlesize 6 -showhandle 0
+ .p add [frame .p.f -width 20 -height 20 -bg red] -padx 0 -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {20 20}
+
+test panedwindow-19.24 {ComputeGeometry, three panes, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -sashwidth 3 -handlesize 6 -showhandle 0
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {66 20}
+
+test panedwindow-19.25 {ComputeGeometry, sash coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -sashwidth 3 -handlesize 6 -showhandle 0
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{20 0} {43 0}}
+
+test panedwindow-19.26 {ComputeGeometry/ArrangePanes, slave coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -sashwidth 3 -handlesize 6 -showhandle 0
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 3 -padx 11
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{11 3 20 20} {56 3 20 20} {101 3 20 20}}
+
+test panedwindow-19.27 {ComputeGeometry, one slave, vertical} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -orient vertical -sashwidth 3 -handlesize 6 \
+ -showhandle 0
+ .p add [frame .f -width 20 -height 20 -bg red] -pady 0 \
+ -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {20 20}
+
+test panedwindow-19.28 {ComputeGeometry, three panes, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -sashwidth 3 -handlesize 6 -showhandle 0 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {20 66}
+
+test panedwindow-19.29 {ComputeGeometry, sash coords, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -sashwidth 3 -handlesize 6 -showhandle 0 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{0 20} {0 43}}
+
+test panedwindow-19.30 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -sashwidth 3 -handlesize 6 -showhandle 0 \
+ -orient vertical
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 11 -padx 3
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{3 11 20 20} {3 56 20 20} {3 101 20 20}}
+test panedwindow-19.31 {ComputeGeometry, one slave, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -sashwidth 3 -handlesize 6 -showhandle 1
+ .p add [frame .p.f -width 20 -height 20 -bg red] -padx 1 -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {22 20}
+
+test panedwindow-19.32 {ComputeGeometry, three panes, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -sashwidth 3 -handlesize 6 -showhandle 1
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {72 20}
+
+test panedwindow-19.33 {ComputeGeometry, sash coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -sashwidth 3 -handlesize 6 -showhandle 1
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{21 0} {47 0}}
+
+test panedwindow-19.34 {ComputeGeometry/ArrangePanes, slave coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -sashwidth 3 -handlesize 6 -showhandle 1
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 3 -padx 11
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{11 3 20 20} {59 3 20 20} {107 3 20 20}}
+
+test panedwindow-19.35 {ComputeGeometry, one slave, vertical} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -orient vertical -sashwidth 3 -handlesize 6 \
+ -showhandle 1
+ .p add [frame .f -width 20 -height 20 -bg red] -pady 1 \
+ -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {20 22}
+
+test panedwindow-19.36 {ComputeGeometry, three panes, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -sashwidth 3 -handlesize 6 -showhandle 1 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {20 72}
+
+test panedwindow-19.37 {ComputeGeometry, sash coords, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -sashwidth 3 -handlesize 6 -showhandle 1 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{0 21} {0 47}}
+
+test panedwindow-19.38 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 \
+ -sashwidth 3 -handlesize 6 -showhandle 1 \
+ -orient vertical
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 11 -padx 3
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{3 11 20 20} {3 59 20 20} {3 107 20 20}}
+test panedwindow-19.39 {ComputeGeometry, one slave, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -sashwidth 0 -handlesize 6 -showhandle 0
+ .p add [frame .p.f -width 20 -height 20 -bg red] -padx 0 -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {20 20}
+
+test panedwindow-19.40 {ComputeGeometry, three panes, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -sashwidth 0 -handlesize 6 -showhandle 0
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {80 20}
+
+test panedwindow-19.41 {ComputeGeometry, sash coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -sashwidth 0 -handlesize 6 -showhandle 0
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{25 0} {55 0}}
+
+test panedwindow-19.42 {ComputeGeometry/ArrangePanes, slave coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -sashwidth 0 -handlesize 6 -showhandle 0
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 3 -padx 11
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{11 3 20 20} {63 3 20 20} {115 3 20 20}}
+
+test panedwindow-19.43 {ComputeGeometry, one slave, vertical} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -orient vertical -sashwidth 0 -handlesize 6 \
+ -showhandle 0
+ .p add [frame .f -width 20 -height 20 -bg red] -pady 0 \
+ -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {20 20}
+
+test panedwindow-19.44 {ComputeGeometry, three panes, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -sashwidth 0 -handlesize 6 -showhandle 0 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {20 80}
+
+test panedwindow-19.45 {ComputeGeometry, sash coords, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -sashwidth 0 -handlesize 6 -showhandle 0 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{0 25} {0 55}}
+
+test panedwindow-19.46 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -sashwidth 0 -handlesize 6 -showhandle 0 \
+ -orient vertical
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 11 -padx 3
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{3 11 20 20} {3 63 20 20} {3 115 20 20}}
+test panedwindow-19.47 {ComputeGeometry, one slave, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -sashwidth 0 -handlesize 6 -showhandle 1
+ .p add [frame .p.f -width 20 -height 20 -bg red] -padx 1 -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {22 20}
+
+test panedwindow-19.48 {ComputeGeometry, three panes, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -sashwidth 0 -handlesize 6 -showhandle 1
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {92 20}
+
+test panedwindow-19.49 {ComputeGeometry, sash coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -sashwidth 0 -handlesize 6 -showhandle 1
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{28 0} {64 0}}
+
+test panedwindow-19.50 {ComputeGeometry/ArrangePanes, slave coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -sashwidth 0 -handlesize 6 -showhandle 1
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 3 -padx 11
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{11 3 20 20} {69 3 20 20} {127 3 20 20}}
+
+test panedwindow-19.51 {ComputeGeometry, one slave, vertical} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -orient vertical -sashwidth 0 -handlesize 6 \
+ -showhandle 1
+ .p add [frame .f -width 20 -height 20 -bg red] -pady 1 \
+ -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {20 22}
+
+test panedwindow-19.52 {ComputeGeometry, three panes, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -sashwidth 0 -handlesize 6 -showhandle 1 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {20 92}
+
+test panedwindow-19.53 {ComputeGeometry, sash coords, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -sashwidth 0 -handlesize 6 -showhandle 1 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{0 28} {0 64}}
+
+test panedwindow-19.54 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -sashwidth 0 -handlesize 6 -showhandle 1 \
+ -orient vertical
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 11 -padx 3
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{3 11 20 20} {3 69 20 20} {3 127 20 20}}
+test panedwindow-19.55 {ComputeGeometry, one slave, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -sashwidth 3 -handlesize 6 -showhandle 0
+ .p add [frame .p.f -width 20 -height 20 -bg red] -padx 0 -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {20 20}
+
+test panedwindow-19.56 {ComputeGeometry, three panes, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -sashwidth 3 -handlesize 6 -showhandle 0
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {86 20}
+
+test panedwindow-19.57 {ComputeGeometry, sash coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -sashwidth 3 -handlesize 6 -showhandle 0
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{25 0} {58 0}}
+
+test panedwindow-19.58 {ComputeGeometry/ArrangePanes, slave coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -sashwidth 3 -handlesize 6 -showhandle 0
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 3 -padx 11
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{11 3 20 20} {66 3 20 20} {121 3 20 20}}
+
+test panedwindow-19.59 {ComputeGeometry, one slave, vertical} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -orient vertical -sashwidth 3 -handlesize 6 \
+ -showhandle 0
+ .p add [frame .f -width 20 -height 20 -bg red] -pady 0 \
+ -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {20 20}
+
+test panedwindow-19.60 {ComputeGeometry, three panes, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -sashwidth 3 -handlesize 6 -showhandle 0 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {20 86}
+
+test panedwindow-19.61 {ComputeGeometry, sash coords, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -sashwidth 3 -handlesize 6 -showhandle 0 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{0 25} {0 58}}
+
+test panedwindow-19.62 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -sashwidth 3 -handlesize 6 -showhandle 0 \
+ -orient vertical
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 11 -padx 3
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{3 11 20 20} {3 66 20 20} {3 121 20 20}}
+test panedwindow-19.63 {ComputeGeometry, one slave, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -sashwidth 3 -handlesize 6 -showhandle 1
+ .p add [frame .p.f -width 20 -height 20 -bg red] -padx 1 -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {22 20}
+
+test panedwindow-19.64 {ComputeGeometry, three panes, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -sashwidth 3 -handlesize 6 -showhandle 1
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {92 20}
+
+test panedwindow-19.65 {ComputeGeometry, sash coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -sashwidth 3 -handlesize 6 -showhandle 1
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{26 0} {62 0}}
+
+test panedwindow-19.66 {ComputeGeometry/ArrangePanes, slave coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -sashwidth 3 -handlesize 6 -showhandle 1
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 3 -padx 11
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{11 3 20 20} {69 3 20 20} {127 3 20 20}}
+
+test panedwindow-19.67 {ComputeGeometry, one slave, vertical} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -orient vertical -sashwidth 3 -handlesize 6 \
+ -showhandle 1
+ .p add [frame .f -width 20 -height 20 -bg red] -pady 1 \
+ -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {20 22}
+
+test panedwindow-19.68 {ComputeGeometry, three panes, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -sashwidth 3 -handlesize 6 -showhandle 1 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {20 92}
+
+test panedwindow-19.69 {ComputeGeometry, sash coords, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -sashwidth 3 -handlesize 6 -showhandle 1 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{0 26} {0 62}}
+
+test panedwindow-19.70 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 5 \
+ -sashwidth 3 -handlesize 6 -showhandle 1 \
+ -orient vertical
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 11 -padx 3
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{3 11 20 20} {3 69 20 20} {3 127 20 20}}
+test panedwindow-19.71 {ComputeGeometry, one slave, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -sashwidth 0 -handlesize 6 -showhandle 0
+ .p add [frame .p.f -width 20 -height 20 -bg red] -padx 0 -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {24 24}
+
+test panedwindow-19.72 {ComputeGeometry, three panes, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -sashwidth 0 -handlesize 6 -showhandle 0
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {64 24}
+
+test panedwindow-19.73 {ComputeGeometry, sash coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -sashwidth 0 -handlesize 6 -showhandle 0
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{22 2} {42 2}}
+
+test panedwindow-19.74 {ComputeGeometry/ArrangePanes, slave coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -sashwidth 0 -handlesize 6 -showhandle 0
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 3 -padx 11
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{13 5 20 20} {55 5 20 20} {97 5 20 20}}
+
+test panedwindow-19.75 {ComputeGeometry, one slave, vertical} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -orient vertical -sashwidth 0 -handlesize 6 \
+ -showhandle 0
+ .p add [frame .f -width 20 -height 20 -bg red] -pady 0 \
+ -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {24 24}
+
+test panedwindow-19.76 {ComputeGeometry, three panes, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -sashwidth 0 -handlesize 6 -showhandle 0 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {24 64}
+
+test panedwindow-19.77 {ComputeGeometry, sash coords, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -sashwidth 0 -handlesize 6 -showhandle 0 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{2 22} {2 42}}
+
+test panedwindow-19.78 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -sashwidth 0 -handlesize 6 -showhandle 0 \
+ -orient vertical
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 11 -padx 3
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{5 13 20 20} {5 55 20 20} {5 97 20 20}}
+test panedwindow-19.79 {ComputeGeometry, one slave, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -sashwidth 0 -handlesize 6 -showhandle 1
+ .p add [frame .p.f -width 20 -height 20 -bg red] -padx 1 -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {26 24}
+
+test panedwindow-19.80 {ComputeGeometry, three panes, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -sashwidth 0 -handlesize 6 -showhandle 1
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {76 24}
+
+test panedwindow-19.81 {ComputeGeometry, sash coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -sashwidth 0 -handlesize 6 -showhandle 1
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{25 2} {51 2}}
+
+test panedwindow-19.82 {ComputeGeometry/ArrangePanes, slave coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -sashwidth 0 -handlesize 6 -showhandle 1
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 3 -padx 11
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{13 5 20 20} {61 5 20 20} {109 5 20 20}}
+
+test panedwindow-19.83 {ComputeGeometry, one slave, vertical} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -orient vertical -sashwidth 0 -handlesize 6 \
+ -showhandle 1
+ .p add [frame .f -width 20 -height 20 -bg red] -pady 1 \
+ -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {24 26}
+
+test panedwindow-19.84 {ComputeGeometry, three panes, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -sashwidth 0 -handlesize 6 -showhandle 1 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {24 76}
+
+test panedwindow-19.85 {ComputeGeometry, sash coords, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -sashwidth 0 -handlesize 6 -showhandle 1 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{2 25} {2 51}}
+
+test panedwindow-19.86 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -sashwidth 0 -handlesize 6 -showhandle 1 \
+ -orient vertical
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 11 -padx 3
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{5 13 20 20} {5 61 20 20} {5 109 20 20}}
+test panedwindow-19.87 {ComputeGeometry, one slave, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -sashwidth 3 -handlesize 6 -showhandle 0
+ .p add [frame .p.f -width 20 -height 20 -bg red] -padx 0 -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {24 24}
+
+test panedwindow-19.88 {ComputeGeometry, three panes, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -sashwidth 3 -handlesize 6 -showhandle 0
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {70 24}
+
+test panedwindow-19.89 {ComputeGeometry, sash coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -sashwidth 3 -handlesize 6 -showhandle 0
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{22 2} {45 2}}
+
+test panedwindow-19.90 {ComputeGeometry/ArrangePanes, slave coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -sashwidth 3 -handlesize 6 -showhandle 0
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 3 -padx 11
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{13 5 20 20} {58 5 20 20} {103 5 20 20}}
+
+test panedwindow-19.91 {ComputeGeometry, one slave, vertical} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -orient vertical -sashwidth 3 -handlesize 6 \
+ -showhandle 0
+ .p add [frame .f -width 20 -height 20 -bg red] -pady 0 \
+ -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {24 24}
+
+test panedwindow-19.92 {ComputeGeometry, three panes, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -sashwidth 3 -handlesize 6 -showhandle 0 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {24 70}
+
+test panedwindow-19.93 {ComputeGeometry, sash coords, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -sashwidth 3 -handlesize 6 -showhandle 0 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{2 22} {2 45}}
+
+test panedwindow-19.94 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -sashwidth 3 -handlesize 6 -showhandle 0 \
+ -orient vertical
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 11 -padx 3
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{5 13 20 20} {5 58 20 20} {5 103 20 20}}
+test panedwindow-19.95 {ComputeGeometry, one slave, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -sashwidth 3 -handlesize 6 -showhandle 1
+ .p add [frame .p.f -width 20 -height 20 -bg red] -padx 1 -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {26 24}
+
+test panedwindow-19.96 {ComputeGeometry, three panes, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -sashwidth 3 -handlesize 6 -showhandle 1
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {76 24}
+
+test panedwindow-19.97 {ComputeGeometry, sash coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -sashwidth 3 -handlesize 6 -showhandle 1
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{23 2} {49 2}}
+
+test panedwindow-19.98 {ComputeGeometry/ArrangePanes, slave coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -sashwidth 3 -handlesize 6 -showhandle 1
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 3 -padx 11
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{13 5 20 20} {61 5 20 20} {109 5 20 20}}
+
+test panedwindow-19.99 {ComputeGeometry, one slave, vertical} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -orient vertical -sashwidth 3 -handlesize 6 \
+ -showhandle 1
+ .p add [frame .f -width 20 -height 20 -bg red] -pady 1 \
+ -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {24 26}
+
+test panedwindow-19.100 {ComputeGeometry, three panes, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -sashwidth 3 -handlesize 6 -showhandle 1 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {24 76}
+
+test panedwindow-19.101 {ComputeGeometry, sash coords, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -sashwidth 3 -handlesize 6 -showhandle 1 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{2 23} {2 49}}
+
+test panedwindow-19.102 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 0 \
+ -sashwidth 3 -handlesize 6 -showhandle 1 \
+ -orient vertical
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 11 -padx 3
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{5 13 20 20} {5 61 20 20} {5 109 20 20}}
+test panedwindow-19.103 {ComputeGeometry, one slave, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -sashwidth 0 -handlesize 6 -showhandle 0
+ .p add [frame .p.f -width 20 -height 20 -bg red] -padx 0 -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {24 24}
+
+test panedwindow-19.104 {ComputeGeometry, three panes, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -sashwidth 0 -handlesize 6 -showhandle 0
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {84 24}
+
+test panedwindow-19.105 {ComputeGeometry, sash coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -sashwidth 0 -handlesize 6 -showhandle 0
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{27 2} {57 2}}
+
+test panedwindow-19.106 {ComputeGeometry/ArrangePanes, slave coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -sashwidth 0 -handlesize 6 -showhandle 0
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 3 -padx 11
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{13 5 20 20} {65 5 20 20} {117 5 20 20}}
+
+test panedwindow-19.107 {ComputeGeometry, one slave, vertical} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -orient vertical -sashwidth 0 -handlesize 6 \
+ -showhandle 0
+ .p add [frame .f -width 20 -height 20 -bg red] -pady 0 \
+ -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {24 24}
+
+test panedwindow-19.108 {ComputeGeometry, three panes, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -sashwidth 0 -handlesize 6 -showhandle 0 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {24 84}
+
+test panedwindow-19.109 {ComputeGeometry, sash coords, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -sashwidth 0 -handlesize 6 -showhandle 0 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{2 27} {2 57}}
+
+test panedwindow-19.110 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -sashwidth 0 -handlesize 6 -showhandle 0 \
+ -orient vertical
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 11 -padx 3
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{5 13 20 20} {5 65 20 20} {5 117 20 20}}
+test panedwindow-19.111 {ComputeGeometry, one slave, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -sashwidth 0 -handlesize 6 -showhandle 1
+ .p add [frame .p.f -width 20 -height 20 -bg red] -padx 1 -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {26 24}
+
+test panedwindow-19.112 {ComputeGeometry, three panes, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -sashwidth 0 -handlesize 6 -showhandle 1
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {96 24}
+
+test panedwindow-19.113 {ComputeGeometry, sash coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -sashwidth 0 -handlesize 6 -showhandle 1
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{30 2} {66 2}}
+
+test panedwindow-19.114 {ComputeGeometry/ArrangePanes, slave coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -sashwidth 0 -handlesize 6 -showhandle 1
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 3 -padx 11
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{13 5 20 20} {71 5 20 20} {129 5 20 20}}
+
+test panedwindow-19.115 {ComputeGeometry, one slave, vertical} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -orient vertical -sashwidth 0 -handlesize 6 \
+ -showhandle 1
+ .p add [frame .f -width 20 -height 20 -bg red] -pady 1 \
+ -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {24 26}
+
+test panedwindow-19.116 {ComputeGeometry, three panes, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -sashwidth 0 -handlesize 6 -showhandle 1 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {24 96}
+
+test panedwindow-19.117 {ComputeGeometry, sash coords, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -sashwidth 0 -handlesize 6 -showhandle 1 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{2 30} {2 66}}
+
+test panedwindow-19.118 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -sashwidth 0 -handlesize 6 -showhandle 1 \
+ -orient vertical
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 11 -padx 3
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{5 13 20 20} {5 71 20 20} {5 129 20 20}}
+test panedwindow-19.119 {ComputeGeometry, one slave, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -sashwidth 3 -handlesize 6 -showhandle 0
+ .p add [frame .p.f -width 20 -height 20 -bg red] -padx 0 -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {24 24}
+
+test panedwindow-19.120 {ComputeGeometry, three panes, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -sashwidth 3 -handlesize 6 -showhandle 0
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {90 24}
+
+test panedwindow-19.121 {ComputeGeometry, sash coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -sashwidth 3 -handlesize 6 -showhandle 0
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{27 2} {60 2}}
+
+test panedwindow-19.122 {ComputeGeometry/ArrangePanes, slave coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -sashwidth 3 -handlesize 6 -showhandle 0
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 3 -padx 11
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{13 5 20 20} {68 5 20 20} {123 5 20 20}}
+
+test panedwindow-19.123 {ComputeGeometry, one slave, vertical} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -orient vertical -sashwidth 3 -handlesize 6 \
+ -showhandle 0
+ .p add [frame .f -width 20 -height 20 -bg red] -pady 0 \
+ -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {24 24}
+
+test panedwindow-19.124 {ComputeGeometry, three panes, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -sashwidth 3 -handlesize 6 -showhandle 0 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {24 90}
+
+test panedwindow-19.125 {ComputeGeometry, sash coords, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -sashwidth 3 -handlesize 6 -showhandle 0 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{2 27} {2 60}}
+
+test panedwindow-19.126 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -sashwidth 3 -handlesize 6 -showhandle 0 \
+ -orient vertical
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 11 -padx 3
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{5 13 20 20} {5 68 20 20} {5 123 20 20}}
+test panedwindow-19.127 {ComputeGeometry, one slave, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -sashwidth 3 -handlesize 6 -showhandle 1
+ .p add [frame .p.f -width 20 -height 20 -bg red] -padx 1 -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {26 24}
+
+test panedwindow-19.128 {ComputeGeometry, three panes, reqsize set properly} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -sashwidth 3 -handlesize 6 -showhandle 1
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {96 24}
+
+test panedwindow-19.129 {ComputeGeometry, sash coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -sashwidth 3 -handlesize 6 -showhandle 1
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{28 2} {64 2}}
+
+test panedwindow-19.130 {ComputeGeometry/ArrangePanes, slave coords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -sashwidth 3 -handlesize 6 -showhandle 1
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 3 -padx 11
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{13 5 20 20} {71 5 20 20} {129 5 20 20}}
+
+test panedwindow-19.131 {ComputeGeometry, one slave, vertical} -setup {
+ deleteWindows
+} -body {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -orient vertical -sashwidth 3 -handlesize 6 \
+ -showhandle 1
+ .p add [frame .f -width 20 -height 20 -bg red] -pady 1 \
+ -sticky ""
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {24 26}
+
+test panedwindow-19.132 {ComputeGeometry, three panes, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -sashwidth 3 -handlesize 6 -showhandle 1 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {24 96}
+
+test panedwindow-19.133 {ComputeGeometry, sash coords, vertical} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -sashwidth 3 -handlesize 6 -showhandle 1 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ list [.p sash coord 0] [.p sash coord 1]
+} -cleanup {
+ deleteWindows
+} -result {{2 28} {2 64}}
+
+test panedwindow-19.134 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 2 -sashpad 5 \
+ -sashwidth 3 -handlesize 6 -showhandle 1 \
+ -orient vertical
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 11 -padx 3
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {{5 13 20 20} {5 71 20 20} {5 129 20 20}}
+
+
+test panedwindow-20.1 {destroyed widgets are removed from panedwindow} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p add [frame .f -width 20 -height 20 -bg blue]
+ destroy .f
+ .p panes
+} -cleanup {
+ deleteWindows
+} -result {}
+test panedwindow-20.2 {destroyed slave causes geometry recomputation} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 2
+ .p add [frame .f -width 20 -height 20 -bg blue] \
+ [frame .f2 -width 20 -height 20 -bg red]
+ destroy .f
+ winfo reqwidth .p
+} -cleanup {
+ deleteWindows
+} -result 20
+
+
+test panedwindow-21.1 {ArrangePanes, extra space is given to the last pane} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ .p add [frame .f1 -width 20 -height 20 -bg blue] \
+ [frame .f2 -width 20 -height 20 -bg red] -sticky nsew
+ place .p -width 100 -x 0 -y 0
+ update
+ winfo width .f2
+} -cleanup {
+ deleteWindows
+} -result 78
+test panedwindow-21.2 {ArrangePanes, extra space is given to the last pane} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ .p add [frame .f1 -width 20 -height 20 -bg blue] \
+ [frame .f2 -width 20 -height 20 -bg red] -sticky nsew
+ place .p -height 100 -x 0 -y 0
+ update
+ winfo height .f2
+} -cleanup {
+ deleteWindows
+} -result 78
+test panedwindow-21.3 {ArrangePanes, explicit height/width are preferred} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ .p add [frame .f1 -width 20 -height 20 -bg blue] \
+ [frame .f2 -width 20 -height 20 -bg red] -sticky ""
+ .p paneconfigure .f1 -width 10 -height 15
+ pack .p
+ update
+ list [winfo width .f1] [winfo height .f1]
+} -cleanup {
+ deleteWindows
+} -result {10 15}
+test panedwindow-21.4 {ArrangePanes, panes clipped by size of pane} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ .p add [frame .f1 -width 20 -height 20 -bg blue] \
+ [frame .f2 -width 20 -height 20 -bg red]
+ .p sash place 0 10 0
+ pack .p
+ update
+ list [winfo width .f1] [winfo height .f1]
+} -cleanup {
+ deleteWindows
+} -result {10 20}
+test panedwindow-21.5 {ArrangePanes, panes clipped by size of pane} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ .p add [frame .f1 -width 20 -height 20 -bg blue] \
+ [frame .f2 -width 20 -height 20 -bg red]
+ .p sash place 0 0 10
+ pack .p
+ update
+ list [winfo width .f1] [winfo height .f1]
+} -cleanup {
+ deleteWindows
+} -result {20 10}
+test panedwindow-21.6 {ArrangePanes, height of pane taken from total height} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ .p add [frame .p.f1 -width 20 -height 20 -bg blue] \
+ [frame .p.f2 -width 20 -height 40 -bg red] -sticky ""
+ pack .p
+ update
+ winfo y .p.f1
+} -cleanup {
+ deleteWindows
+} -result 10
+test panedwindow-21.7 {ArrangePanes, width of pane taken from total width} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ .p add [frame .p.f1 -width 20 -height 20 -bg blue] \
+ [frame .p.f2 -width 40 -height 40 -bg red] -sticky ""
+ pack .p
+ update
+ winfo x .p.f1
+} -cleanup {
+ deleteWindows
+} -result 10
+test panedwindow-21.8 {ArrangePanes, panes with width <= 0 are unmapped} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ .p add [frame .f1 -width 20 -height 20 -bg blue] \
+ [frame .f2 -width 20 -height 40 -bg red]
+ pack .p
+ update
+ set result [winfo ismapped .f1]
+ .p sash place 0 0 0
+ update
+ lappend result [winfo ismapped .f1]
+} -cleanup {
+ deleteWindows
+} -result {1 0}
+test panedwindow-21.9 {ArrangePanes, panes with width <= 0 are unmapped} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ .p add [frame .p.f1 -width 20 -height 20 -bg blue] \
+ [frame .p.f2 -width 20 -height 40 -bg red]
+ pack .p
+ update
+ set result [winfo ismapped .p.f1]
+ .p sash place 0 0 0
+ update
+ lappend result [winfo ismapped .p.f1]
+} -cleanup {
+ deleteWindows
+} -result {1 0}
+test panedwindow-21.10 {ArrangePanes, panes with width <= 0 are unmapped} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 -orient vertical
+ .p add [frame .p.f1 -width 20 -height 20 -bg blue] \
+ [frame .p.f2 -width 20 -height 40 -bg red]
+ pack .p
+ update
+ set result [winfo ismapped .p.f1]
+ .p sash place 0 0 0
+ update
+ lappend result [winfo ismapped .p.f1]
+} -cleanup {
+ deleteWindows
+} -result {1 0}
+test panedwindow-21.11 {ArrangePanes, last pane shrinks} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ .p add [frame .f1 -width 20 -height 20 -bg blue] \
+ [frame .f2 -width 20 -height 20 -bg red] -sticky nsew
+ place .p -width 40 -x 0 -y 0
+ update
+ winfo width .f2
+} -cleanup {
+ deleteWindows
+} -result 18
+test panedwindow-21.12 {ArrangePanes, last pane shrinks} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ .p add [frame .f1 -width 20 -height 20 -bg blue] \
+ [frame .f2 -width 20 -height 20 -bg red] -sticky nsew
+ place .p -height 40 -x 0 -y 0
+ update
+ winfo height .f2
+} -cleanup {
+ deleteWindows
+} -result 18
+test panedwindow-21.13 {ArrangePanes, panedwindow resizes} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -width 200 -borderwidth 0
+ frame .f1 -height 50 -bg blue
+ set result [list]
+ lappend result [winfo reqwidth .p] [winfo reqheight .p]
+ .p add .f1
+ pack .p
+ lappend result [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {200 1 200 50}
+test panedwindow-21.14 {ArrangePanes, panedwindow resizes} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -height 200 -borderwidth 0 -orient vertical
+ frame .f1 -width 50 -bg blue
+ set result [list]
+ lappend result [winfo reqwidth .p] [winfo reqheight .p]
+ .p add .f1
+ pack .p
+ lappend result [winfo reqwidth .p] [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {1 200 50 200}
+test panedwindow-21.15 {ArrangePanes, last pane grows} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -height 50
+ .p add [frame .f1 -width 50 -bg red] [frame .f2 -width 50 -bg white] \
+ [frame .f3 -width 50 -bg blue] [frame .f4 -width 50 -bg green]
+ .p sash place 1 250 0
+ pack .p
+ update
+ set result [list]
+ lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3] \
+ [winfo width .f4] [winfo width .p]
+ .p configure -width 300
+ update
+ lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3] \
+ [winfo width .f4] [winfo width .p]
+} -cleanup {
+ deleteWindows
+} -result {50 150 1 1 211 50 150 1 89 300}
+
+
+test panedwindow-22.1 {PanedWindowReqProc, react to slave geometry changes} -setup {
+ deleteWindows
+} -body {
+ # Basically just want to make sure that the PanedWindowReqProc is called
+ panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 2
+ .p add [frame .f1 -width 20 -height 20 -bg blue] \
+ [frame .f2 -width 20 -height 40 -bg red]
+ set result [winfo reqheight .p]
+ .f1 configure -height 80
+ lappend result [winfo reqheight .p]
+} -cleanup {
+ deleteWindows
+} -result {40 80}
+test panedwindow-22.2 {PanedWindowReqProc, react to slave geometry changes} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -orient horizontal -sashpad 0 -sashwidth 2
+ .p add [frame .f1 -width 10] [frame .f2 -width 10]
+ set result [winfo reqwidth .p]
+ .f1 configure -width 20
+ lappend result [winfo reqwidth .p]
+ destroy .p .f1 .f2
+ expr {[lindex $result 1] - [lindex $result 0]}
+} -cleanup {
+ deleteWindows
+} -result {10}
+
+
+test panedwindow-23.1 {ConfigurePanes, can't add panedwindow to itself} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p add .p
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {can't add .p to itself}
+test panedwindow-23.2 {ConfigurePanes, bad window throws error} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p add .b
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {bad window path name ".b"}
+test panedwindow-23.3 {ConfigurePanes, bad window aborts processing} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ button .b
+ catch {.p add .b .a}
+ .p panes
+} -cleanup {
+ deleteWindows
+} -result {}
+test panedwindow-23.4 {ConfigurePanes, bad option aborts processing} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ button .b
+ catch {.p add .b -sticky foobar}
+ .p panes
+} -cleanup {
+ deleteWindows
+} -result {}
+test panedwindow-23.5 {ConfigurePanes, after win isn't managed by panedwin} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ button .b
+ button .c
+ .p add .b -after .c
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {window ".c" is not managed by .p}
+test panedwindow-23.6 {ConfigurePanes, before win isn't managed by panedwin} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ button .b
+ button .c
+ .p add .b -before .c
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {window ".c" is not managed by .p}
+test panedwindow-23.7 {ConfigurePanes, -after {} is a no-op} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p add [button .b] [button .c]
+ .p paneconfigure .b -after {}
+ .p panes
+} -cleanup {
+ deleteWindows
+} -result {.b .c}
+test panedwindow-23.8 {ConfigurePanes, -before {} is a no-op} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p add [button .b] [button .c]
+ .p paneconfigure .b -before {}
+ .p panes
+} -cleanup {
+ deleteWindows
+} -result {.b .c}
+test panedwindow-23.9 {ConfigurePanes, new panes are added} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p add [button .b] [button .c]
+ .p panes
+} -cleanup {
+ deleteWindows
+} -result {.b .c}
+test panedwindow-23.10 {ConfigurePanes, options applied to all panes} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p add [button .b] [button .c] -sticky ne -height 5 -width 5 -minsize 10
+ set result {}
+ foreach w {.b .c} {
+ set val {}
+ foreach option {-sticky -height -width -minsize} {
+ lappend val $option [.p panecget $w $option]
+ }
+ lappend result $w $val
+ }
+ return $result
+} -cleanup {
+ deleteWindows
+} -result {.b {-sticky ne -height 5 -width 5 -minsize 10} .c {-sticky ne -height 5 -width 5 -minsize 10}}
+
+test panedwindow-23.11 {ConfigurePanes, existing panes are reconfigured} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p add [button .b] -sticky nw -height 10
+ .p add .b [button .c] -sticky se -height 2
+ list [.p panes] [.p panecget .b -sticky] [.p panecget .b -height] \
+ [.p panecget .c -sticky] [.p panecget .c -height]
+} -cleanup {
+ deleteWindows
+} -result [list {.b .c} es 2 es 2]
+test panedwindow-23.12 {ConfigurePanes, widgets added to end by default} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p add [button .b]
+ .p add [button .c]
+ .p add [button .d]
+ .p panes
+} -cleanup {
+ deleteWindows
+} -result {.b .c .d}
+test panedwindow-23.13 {ConfigurePanes, -after, single addition} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ button .a
+ button .b
+ button .c
+
+ .p add .a .b
+ .p add .c -after .a
+ .p panes
+} -cleanup {
+ deleteWindows
+} -result {.a .c .b}
+test panedwindow-23.14 {ConfigurePanes, -after, multiple additions} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ button .a
+ button .b
+ button .c
+ button .d
+
+ .p add .a .b
+ .p add .c .d -after .a
+ .p panes
+} -cleanup {
+ deleteWindows
+} -result {.a .c .d .b}
+test panedwindow-23.15 {ConfigurePanes, -after, relocates existing widget} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ button .a
+ button .b
+ button .c
+ button .d
+
+ .p add .a .b .c .d
+ .p add .d -after .a
+ .p panes
+} -cleanup {
+ deleteWindows
+} -result {.a .d .b .c}
+test panedwindow-23.16 {ConfigurePanes, -after, relocates existing widgets} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ button .a
+ button .b
+ button .c
+ button .d
+
+ .p add .a .b .c .d
+ .p add .b .d -after .a
+ .p panes
+} -cleanup {
+ deleteWindows
+} -result {.a .b .d .c}
+test panedwindow-23.17 {ConfigurePanes, -after, relocates existing widgets} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ button .a
+ button .b
+ button .c
+ button .d
+
+ .p add .a .b .c .d
+ .p add .d .a -after .b
+ .p panes
+} -cleanup {
+ deleteWindows
+} -result {.b .d .a .c}
+test panedwindow-23.18 {ConfigurePanes, -after, relocates existing widgets} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ button .a
+ button .b
+ button .c
+ button .d
+
+ .p add .a .b .c .d
+ .p add .d .a -after .a
+ .p panes
+} -cleanup {
+ deleteWindows
+} -result {.d .a .b .c}
+test panedwindow-23.19 {ConfigurePanes, -after, after last window} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ button .a
+ button .b
+ button .c
+ button .d
+
+ .p add .a .b .c
+ .p add .d -after .c
+ .p panes
+} -cleanup {
+ deleteWindows
+} -result {.a .b .c .d}
+test panedwindow-23.20 {ConfigurePanes, -before, before first window} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ button .a
+ button .b
+ button .c
+ button .d
+
+ .p add .a .b .c
+ .p add .d -before .a
+ .p panes
+} -cleanup {
+ deleteWindows
+} -result {.d .a .b .c}
+test panedwindow-23.21 {ConfigurePanes, -before, relocate existing windows} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ button .a
+ button .b
+ button .c
+ button .d
+
+ .p add .a .b .c
+ .p add .d .b -before .a
+ .p panes
+} -cleanup {
+ deleteWindows
+} -result {.d .b .a .c}
+test panedwindow-23.22 {ConfigurePanes, slave specified multiple times} -setup {
+ deleteWindows
+} -body {
+ # This test should not cause a core dump
+
+ panedwindow .p
+ button .a
+ button .b
+ button .c
+
+ .p add .a .a .b .c
+ .p panes
+} -cleanup {
+ deleteWindows
+} -result {.a .b .c}
+test panedwindow-23.23 {ConfigurePanes, slave specified multiple times} -setup {
+ deleteWindows
+} -body {
+ # This test should not cause a core dump
+
+ panedwindow .p
+ button .a
+ button .b
+ button .c
+
+ .p add .a .a .b .c
+ .p add .a .b .a -after .c
+ .p panes
+} -cleanup {
+ deleteWindows
+} -result {.c .a .b}
+test panedwindow-23.24 {ConfigurePanes, panedwindow cannot manage toplevels} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ toplevel .t
+ .p add .t
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {can't add toplevel .t to .p}
+test panedwindow-23.25 {ConfigurePanes, restrict possible panes} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ frame .f
+ button .f.b
+ .p add .f.b
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {can't add .f.b to .p}
+test panedwindow-23.26 {ConfigurePanes, restrict possible panes} -setup {
+ deleteWindows
+} -body {
+ frame .f
+ panedwindow .f.p
+ button .b
+ .f.p add .b
+} -cleanup {
+ deleteWindows
+} -result {}
+test panedwindow-23.27 {ConfigurePanes, restrict possible panes} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ button .p.b
+ .p add .p.b
+} -cleanup {
+ deleteWindows
+} -result {}
+test panedwindow-23.28 {ConfigurePanes, restrict possible panes} -setup {
+ deleteWindows
+} -body {
+ frame .f
+ frame .f.f
+ frame .f.f.f
+ panedwindow .f.f.f.p
+ button .b
+ .f.f.f.p add .b
+} -cleanup {
+ deleteWindows
+} -result {}
+test panedwindow-23.29 {ConfigurePanes, -hide works} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false
+ frame .f1 -width 40 -height 100 -bg red
+ frame .f2 -width 40 -height 100 -bg white
+ frame .f3 -width 40 -height 100 -bg blue
+ frame .f4 -width 40 -height 100 -bg green
+ .p add .f1 .f2 .f3 .f4
+ pack .p
+ update
+ set result [list]
+ lappend result [winfo ismapped .f1] [winfo ismapped .f2] \
+ [winfo ismapped .f3] [winfo ismapped .f4]
+ lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3] \
+ [winfo width .f4] [winfo width .p]
+ .p paneconfigure .f2 -hide 1
+ update
+ lappend result [winfo ismapped .f1] [winfo ismapped .f2] \
+ [winfo ismapped .f3] [winfo ismapped .f4]
+ lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3] \
+ [winfo width .f4] [winfo width .p]
+} -cleanup {
+ deleteWindows
+} -result {1 1 1 1 40 40 40 40 171 1 0 1 1 40 40 40 40 128}
+test panedwindow-23.30 {ConfigurePanes, -hide works} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -width 130 -height 100
+ frame .f1 -width 40 -bg red
+ frame .f2 -width 40 -bg white
+ frame .f3 -width 40 -bg blue
+ frame .f4 -width 40 -bg green
+ .p add .f1 .f2 .f3 .f4
+ pack .p
+ update
+ set result [list]
+ lappend result [winfo ismapped .f1] [winfo ismapped .f2] \
+ [winfo ismapped .f3] [winfo ismapped .f4]
+ lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3] \
+ [winfo width .f4] [winfo width .p]
+ .p paneconfigure .f2 -hide 1
+ update
+ lappend result [winfo ismapped .f1] [winfo ismapped .f2] \
+ [winfo ismapped .f3] [winfo ismapped .f4]
+ lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3] \
+ [winfo width .f4] [winfo width .p]
+} -cleanup {
+ deleteWindows
+} -result {1 1 1 0 39 40 40 1 130 1 0 1 1 40 40 40 42 130}
+test panedwindow-23.30a {ConfigurePanes, hidden panes are unmapped} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p1 -sashrelief raised
+ panedwindow .p2 -sashrelief raised
+ label .l1 -text Label1
+ label .l2 -text Label2
+ label .l3 -text Label3
+ .p2 add .l2 -sticky nsew
+ .p2 add .l3 -sticky nsew
+ .p1 add .p2 -sticky nsew
+ .p1 add .l1 -sticky nsew
+ pack .p1 -side top -expand 1 -fill both
+ update
+ set result [list]
+ lappend result [list [winfo ismapped .p1] [winfo ismapped .p2] \
+ [winfo ismapped .l1] [winfo ismapped .l2] [winfo ismapped .l3]]
+ .p2 paneconfigure .l1 -hide 1
+ update
+ lappend result [list [winfo ismapped .p1] [winfo ismapped .p2] \
+ [winfo ismapped .l1] [winfo ismapped .l2] [winfo ismapped .l3]]
+ .p1 paneconfigure .p2 -hide 1
+ update
+ lappend result [list [winfo ismapped .p1] [winfo ismapped .p2] \
+ [winfo ismapped .l1] [winfo ismapped .l2] [winfo ismapped .l3]]
+ .p1 paneconfigure .p2 -hide 0
+ update
+ lappend result [list [winfo ismapped .p1] [winfo ismapped .p2] \
+ [winfo ismapped .l1] [winfo ismapped .l2] [winfo ismapped .l3]]
+} -cleanup {
+ deleteWindows
+} -result {{1 1 1 1 1} {1 1 0 1 1} {1 0 0 0 0} {1 1 0 1 1}}
+test panedwindow-23.31 {ConfigurePanes, -hide works, last pane stretches} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -width 200 -height 200 -borderwidth 0
+ frame .f1 -width 50 -bg red
+ frame .f2 -width 50 -bg green
+ frame .f3 -width 50 -bg blue
+ .p add .f1 .f2 .f3
+ pack .p
+ update
+ set result [list]
+ lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3]
+ .p paneconfigure .f2 -hide 1
+ update
+ lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3]
+} -cleanup {
+ deleteWindows
+} -result {50 50 94 50 50 147}
+test panedwindow-23.32 {ConfigurePanes, -hide works, last pane stretches} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -width 200 -height 200 \
+ -borderwidth 0 -orient vertical
+ frame .f1 -height 50 -bg red
+ frame .f2 -height 50 -bg green
+ frame .f3 -height 50 -bg blue
+ .p add .f1 .f2 .f3
+ pack .p
+ update
+ set result [list]
+ lappend result [winfo height .f1] [winfo height .f2] [winfo height .f3]
+ .p paneconfigure .f2 -hide 1
+ update
+ lappend result [winfo height .f1] [winfo height .f2] [winfo height .f3]
+} -cleanup {
+ deleteWindows
+} -result {50 50 94 50 50 147}
+
+test panedwindow-23.33 {ConfigurePanes, -stretch first} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -height 100 -width 182
+ frame .f1 -width 40 -bg red
+ frame .f2 -width 40 -bg white
+ frame .f3 -width 40 -bg blue
+ frame .f4 -width 40 -bg green
+ .p add .f1 .f2 .f3 .f4 -stretch first
+ pack .p
+ update
+ set result [list]
+ lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3] \
+ [winfo width .f4]
+ .p paneconfigure .f2 -hide 1
+ update
+ lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3] \
+ [winfo width .f4]
+} -cleanup {
+ deleteWindows
+} -result {51 40 40 40 94 40 40 40}
+test panedwindow-23.34 {ConfigurePanes, -stretch middle} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -height 100 -width 182
+ frame .f1 -width 40 -bg red
+ frame .f2 -width 40 -bg white
+ frame .f3 -width 40 -bg blue
+ frame .f4 -width 40 -bg green
+ .p add .f1 .f2 .f3 .f4 -stretch middle
+ pack .p
+ update
+ set result [list]
+ lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3] \
+ [winfo width .f4]
+ .p paneconfigure .f2 -hide 1
+ update
+ lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3] \
+ [winfo width .f4]
+} -cleanup {
+ deleteWindows
+} -result {40 45 46 40 40 45 94 40}
+test panedwindow-23.35 {ConfigurePanes, -stretch always} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -height 100 -width 182
+ frame .f1 -width 40 -bg red
+ frame .f2 -width 40 -bg white
+ frame .f3 -width 40 -bg blue
+ frame .f4 -width 40 -bg green
+ .p add .f1 .f2 .f3 .f4 -stretch always
+ pack .p
+ update
+ set result [list]
+ lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3] \
+ [winfo width .f4]
+ .p paneconfigure .f2 -hide 1
+ update
+ lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3] \
+ [winfo width .f4]
+} -cleanup {
+ deleteWindows
+} -result {42 43 43 43 58 43 58 58}
+test panedwindow-23.36 {ConfigurePanes, -stretch never} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -height 100 -width 182
+ frame .f1 -width 40 -bg red
+ frame .f2 -width 40 -bg white
+ frame .f3 -width 40 -bg blue
+ frame .f4 -width 40 -bg green
+ .p add .f1 .f2 .f3 .f4 -stretch never
+ pack .p
+ update
+ set result [list]
+ lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3] \
+ [winfo width .f4]
+ .p paneconfigure .f2 -hide 1
+ update
+ lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3] \
+ [winfo width .f4]
+} -cleanup {
+ deleteWindows
+} -result {40 40 40 40 40 40 40 40}
+
+
+test panedwindow-24.1 {Unlink, remove a paned with -before/-after refs} -setup {
+ deleteWindows
+} -body {
+ # Bug 928413
+ set result {}
+ panedwindow .pw
+ label .pw.l1 -text Label1
+ label .pw.l2 -text Label2
+ label .pw.l3 -text Label3
+ .pw add .pw.l1
+ .pw add .pw.l3
+ .pw add .pw.l2 -before .pw.l3
+ lappend result [.pw panecget .pw.l2 -before]
+ destroy .pw.l3
+ lappend result [.pw panecget .pw.l2 -before]
+ .pw paneconfigure .pw.l2 -before .pw.l1
+ lappend result [.pw panecget .pw.l2 -before]
+} -cleanup {
+ deleteWindows
+} -result {.pw.l3 {} .pw.l1}
+
+
+test panedwindow-25.1 {DestroyPanedWindow} -setup {
+ deleteWindows
+} -body {
+ # This test should not result in any memory leaks.
+ panedwindow .p
+ foreach w {.a .b .c .d .e .f .g .h .i .j .k .l .m .n .o .q .r .s .t} {
+ .p add [button $w]
+ }
+ foreach w {.a .b .c .d .e .f .g .h .i .j .k .l .m .n .o .p .q .r .s .t} {
+ destroy $w
+ }
+ set result {}
+} -result {}
+test panedwindow-25.2 {UnmapNotify and MapNotify events are propagated to slaves} -setup {
+ deleteWindows
+} -body {
+ panedwindow .pw
+ .pw add [button .pw.b]
+ pack .pw
+ update
+ set result [winfo ismapped .pw.b]
+ pack forget .pw
+ update
+ lappend result [winfo ismapped .pw.b]
+ lappend result [winfo ismapped .pw]
+ pack .pw
+ update
+ lappend result [winfo ismapped .pw]
+ lappend result [winfo ismapped .pw.b]
+ destroy .pw .pw.b
+ set result
+} -cleanup {
+ deleteWindows
+} -result {1 0 0 1 1}
+
+
+test panedwindow-26.1 {PanedWindowIdentifyCoords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ .p identify 0 0
+} -cleanup {
+ deleteWindows
+} -result {}
+test panedwindow-26.2 {PanedWindowIdentifyCoords, padding is included} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ .p identify 20 0
+} -cleanup {
+ deleteWindows
+} -result {0 sash}
+test panedwindow-26.3 {PanedWindowIdentifyCoords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ .p identify 22 0
+} -cleanup {
+ deleteWindows
+} -result {0 sash}
+test panedwindow-26.4 {PanedWindowIdentifyCoords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ .p identify 24 0
+} -cleanup {
+ deleteWindows
+} -result {0 sash}
+test panedwindow-26.5 {PanedWindowIdentifyCoords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ .p identify 26 0
+} -cleanup {
+ deleteWindows
+} -result {0 sash}
+test panedwindow-26.6 {PanedWindowIdentifyCoords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ .p identify 26 -1
+} -cleanup {
+ deleteWindows
+} -result {}
+test panedwindow-26.7 {PanedWindowIdentifyCoords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ .p identify 26 100
+} -cleanup {
+ deleteWindows
+} -result {}
+test panedwindow-26.8 {PanedWindowIdentifyCoords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -showhandle 1 -handlepad 5 \
+ -handlesize 6
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ .p identify 22 4
+} -cleanup {
+ deleteWindows
+} -result {0 sash}
+test panedwindow-26.9 {PanedWindowIdentifyCoords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -showhandle 1 -handlepad 5 \
+ -handlesize 6
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ .p identify 22 5
+} -cleanup {
+ deleteWindows
+} -result {0 handle}
+test panedwindow-26.10 {PanedWindowIdentifyCoords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -showhandle 1 -handlepad 5 \
+ -handlesize 8
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ .p identify 20 5
+} -cleanup {
+ deleteWindows
+} -result {0 handle}
+test panedwindow-26.11 {PanedWindowIdentifyCoords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -showhandle 1 -handlepad 5 \
+ -handlesize 8
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ .p identify 20 0
+} -cleanup {
+ deleteWindows
+} -result {0 sash}
+test panedwindow-26.12 {PanedWindowIdentifyCoords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -bd 0 -sashwidth 2 -sashpad 2
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20] \
+ [frame .f3 -bg green -width 20 -height 20]
+ .p identify 48 0
+} -cleanup {
+ deleteWindows
+} -result {1 sash}
+test panedwindow-26.13 {identify subcommand errors} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -borderwidth 0 -sashpad 2 -sashwidth 4
+ .p identify
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {wrong # args: should be ".p identify x y"}
+test panedwindow-26.14 {identify subcommand errors} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p identify foo bar
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {expected integer but got "foo"}
+test panedwindow-26.15 {identify subcommand errors} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p
+ .p identify 0 bar
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {expected integer but got "bar"}
+test panedwindow-26.16 {PanedWindowIdentifyCoords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -orient vertical
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ .p identify 0 0
+} -cleanup {
+ deleteWindows
+} -result {}
+test panedwindow-26.17 {PanedWindowIdentifyCoords, padding is included} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -orient vertical
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ .p identify 0 20
+} -cleanup {
+ deleteWindows
+} -result {0 sash}
+test panedwindow-26.18 {PanedWindowIdentifyCoords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -orient vertical
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ .p identify 0 22
+} -cleanup {
+ deleteWindows
+} -result {0 sash}
+test panedwindow-26.19 {PanedWindowIdentifyCoords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -orient vertical
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ .p identify 0 24
+} -cleanup {
+ deleteWindows
+} -result {0 sash}
+test panedwindow-26.20 {PanedWindowIdentifyCoords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -orient vertical
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ .p identify 0 26
+} -cleanup {
+ deleteWindows
+} -result {0 sash}
+test panedwindow-26.21 {PanedWindowIdentifyCoords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -orient vertical
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ .p identify -1 26
+} -cleanup {
+ deleteWindows
+} -result {}
+test panedwindow-26.22 {PanedWindowIdentifyCoords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -orient vertical
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ .p identify 100 26
+} -cleanup {
+ deleteWindows
+} -result {}
+test panedwindow-26.23 {PanedWindowIdentifyCoords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -showhandle 1 -handlepad 5 \
+ -handlesize 6 -orient vertical
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ .p identify 4 22
+} -cleanup {
+ deleteWindows
+} -result {0 sash}
+test panedwindow-26.24 {PanedWindowIdentifyCoords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -showhandle 1 -handlepad 5 \
+ -handlesize 6 -orient vertical
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ .p identify 5 22
+} -cleanup {
+ deleteWindows
+} -result {0 handle}
+test panedwindow-26.25 {PanedWindowIdentifyCoords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -showhandle 1 -handlepad 5 \
+ -handlesize 8 -orient vertical
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ .p identify 5 20
+} -cleanup {
+ deleteWindows
+} -result {0 handle}
+test panedwindow-26.26 {PanedWindowIdentifyCoords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -showhandle 1 -handlepad 5 \
+ -handlesize 8 -orient vertical
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ .p identify 0 20
+} -cleanup {
+ deleteWindows
+} -result {0 sash}
+test panedwindow-26.27 {PanedWindowIdentifyCoords} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -showhandle false -bd 0 -sashwidth 2 -sashpad 2 -orient vertical
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20] \
+ [frame .f3 -bg green -width 20 -height 20]
+ .p identify 0 48
+} -cleanup {
+ deleteWindows
+} -result {1 sash}
+
+
+test panedwindow-27.1 {destroy the window cleanly on error [Bug #616589]} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -bogusopt bogus
+} -cleanup {
+ deleteWindows
+} -returnCodes error -result {unknown option "-bogusopt"}
+test panedwindow-27.2 {destroy the window cleanly on rename [Bug #616589]} -setup {
+ deleteWindows
+} -body {
+ destroy .p
+ panedwindow .p
+ rename .p {}
+ winfo exists .p
+} -cleanup {
+ deleteWindows
+} -result {0}
+
+
+test panedwindow-28.1 {resizing width} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -bd 5
+ frame .f1 -width 100 -height 50 -bg blue
+ frame .f2 -width 100 -height 50 -bg red
+
+ .p add .f1 -sticky news
+ .p add .f2 -sticky news
+ pack .p -side top -fill both -expand 1
+ wm geometry . ""
+ update
+ # Note the width
+ set a [winfo width .f2]
+ # Increase the size by 10
+ regexp {^(\d+)x(\d+)} [wm geometry .] -> w h
+ wm geometry . [expr {$w + 10}]x$h
+ update
+ set b "$a [winfo width .f2]"
+} -cleanup {
+ deleteWindows
+} -result {100 110}
+
+test panedwindow-28.2 {resizing height} -setup {
+ deleteWindows
+} -body {
+ panedwindow .p -orient vertical -bd 5
+ frame .f1 -width 50 -height 100 -bg blue
+ frame .f2 -width 50 -height 100 -bg red
+
+ .p add .f1 -sticky news
+ .p add .f2 -sticky news
+ pack .p -side top -fill both -expand 1
+ wm geometry . ""
+ update
+ # Note the height
+ set a [winfo height .f2]
+ # Increase the size by 10
+ regexp {^(\d+)x(\d+)} [wm geometry .] -> w h
+ wm geometry . ${w}x[expr {$h + 10}]
+ update
+ set b "$a [winfo height .f2]"
+} -cleanup {
+ deleteWindows
+} -result {100 110}
+
+
+test panedwindow-29.1 {display on depths other than the default one} -constraints {
+ pseudocolor8 haveTruecolor24
+} -setup {
+ deleteWindows
+} -body {
+ toplevel .t -visual {truecolor 24}
+ pack [panedwindow .t.p]
+ .t.p add [frame .t.p.f1] [frame .t.p.f2]
+ update
+ # If we got here, we didn't crash and that's good
+} -cleanup {
+ deleteWindows
+} -result {}
+test panedwindow-29.2 {display on depths other than the default one} -constraints {
+ pseudocolor8 haveTruecolor24
+} -setup {
+ deleteWindows
+} -body {
+ toplevel .t -visual {pseudocolor 8}
+ pack [frame .t.f -visual {truecolor 24}]
+ pack [panedwindow .t.f.p]
+ .t.f.p add [frame .t.f.p.f1 -width 5] [frame .t.f.p.f2 -width 5]
+ update
+ .t.f.p proxy place 1 1
+ update
+ .t.f.p proxy forget
+ update
+ # If we got here, we didn't crash and that's good
+} -cleanup {
+ deleteWindows
+} -result {}
+
+
+# cleanup
+cleanupTests
+return
+
+
diff --git a/tk8.6/tests/place.test b/tk8.6/tests/place.test
new file mode 100644
index 0000000..62e0ed2
--- /dev/null
+++ b/tk8.6/tests/place.test
@@ -0,0 +1,523 @@
+# This file is a Tcl script to test out the "place" command. It is
+# organized in the standard fashion for Tcl tests.
+#
+# Copyright (c) 1995 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+
+# Used for constraining memory leak tests
+testConstraint memory [llength [info commands memory]]
+
+# XXX - This test file is woefully incomplete. At present, only a
+# few of the features are tested.
+
+# Widgets used in tests 1.* - 8.*
+toplevel .t -width 300 -height 200 -bd 0
+wm geom .t +0+0
+frame .t.f -width 154 -height 84 -bd 2 -relief raised
+place .t.f -x 48 -y 38
+frame .t.f2 -width 30 -height 60 -bd 2 -relief raised
+update
+
+test place-1.1 {Tk_PlaceCmd procedure, "info" option} -setup {
+ place forget .t.f2
+} -body {
+ place .t.f2 -x 0
+ place info .t.f2
+} -result {-in .t -x 0 -relx 0 -y 0 -rely 0 -width {} -relwidth {} -height {} -relheight {} -anchor nw -bordermode inside}
+test place-1.2 {Tk_PlaceCmd procedure, "info" option} -setup {
+ place forget .t.f2
+} -body {
+ place .t.f2 -x 1 -y 2 -width 3 -height 4 -relx 0.1 -rely 0.2 \
+ -relwidth 0.3 -relheight 0.4 -anchor se -in .t.f \
+ -bordermode outside
+ place info .t.f2
+} -result {-in .t.f -x 1 -relx 0.1 -y 2 -rely 0.2 -width 3 -relwidth 0.3 -height 4 -relheight 0.4 -anchor se -bordermode outside}
+test place-1.3 {Tk_PlaceCmd procedure, "info" option} -setup {
+ place forget .t.f2
+ destroy .t.a.b
+} -body {
+ # Make sure the result is built as a proper list by using a space in parent
+ frame ".t.a b"
+ place .t.f2 -x 1 -y 2 -width {} -height 4 -relx 0.2 -rely 0.2 \
+ -relwidth 0.3 -relheight {} -anchor w -in ".t.a b" \
+ -bordermode ignore
+ place info .t.f2
+} -cleanup {
+ destroy ".t.a.b"
+} -result {-in {.t.a b} -x 1 -relx 0.2 -y 2 -rely 0.2 -width {} -relwidth 0.3 -height 4 -relheight {} -anchor w -bordermode ignore}
+
+
+test place-2.1 {ConfigureSlave procedure, -height option} -body {
+ place .t.f2 -height abcd
+} -returnCodes error -result {bad screen distance "abcd"}
+test place-2.2 {ConfigureSlave procedure, -height option} -setup {
+ place forget .t.f2
+} -body {
+ place .t.f2 -in .t.f -height 40
+ update
+ winfo height .t.f2
+} -result {40}
+test place-2.3 {ConfigureSlave procedure, -height option} -setup {
+ place forget .t.f2
+} -body {
+ place .t.f2 -in .t.f -height 120
+ update
+ place .t.f2 -height {}
+ update
+ winfo height .t.f2
+} -result {60}
+
+
+test place-3.1 {ConfigureSlave procedure, -relheight option} -body {
+ place .t.f2 -relheight abcd
+} -returnCodes error -result {expected floating-point number but got "abcd"}
+test place-3.2 {ConfigureSlave procedure, -relheight option} -setup {
+ place forget .t.f2
+} -body {
+ place .t.f2 -in .t.f -relheight .5
+ update
+ winfo height .t.f2
+} -result {40}
+test place-3.3 {ConfigureSlave procedure, -relheight option} -setup {
+ place forget .t.f2
+} -body {
+ place .t.f2 -in .t.f -relheight .8
+ update
+ place .t.f2 -relheight {}
+ update
+ winfo height .t.f2
+} -result {60}
+
+
+test place-4.1 {ConfigureSlave procedure, bad -in options} -setup {
+ place forget .t.f2
+} -body {
+ place .t.f2 -in .t.f2
+} -returnCodes error -result {can't place .t.f2 relative to itself}
+test place-4.2 {ConfigureSlave procedure, bad -in option} -setup {
+ place forget .t.f2
+} -body {
+ set result [list [winfo manager .t.f2]]
+ catch {place .t.f2 -in .t.f2}
+ lappend result [winfo manager .t.f2]
+} -result {{} {}}
+test place-4.3 {ConfigureSlave procedure, bad -in option} -setup {
+ place forget .t.f2
+} -body {
+ winfo manager .t.f2
+ place .t.f2 -in .t.f2
+} -returnCodes error -result {can't place .t.f2 relative to itself}
+test place-4.4 {ConfigureSlave procedure, bad -in option} -setup {
+ place forget .t.f2
+} -body {
+ place .t.f2 -in .
+} -returnCodes error -result {can't place .t.f2 relative to .}
+test place-4.5 {ConfigureSlave procedure, bad -in option} -setup {
+} -body {
+ frame .t.f1
+ place .t.f1 -in .t.f1
+} -returnCodes error -result {can't place .t.f1 relative to itself}
+test place-4.6 {prevent management loops} -setup {
+ place forget .t.f1
+} -body {
+ place .t.f1 -in .t.f2
+ place .t.f2 -in .t.f1
+} -returnCodes error -result {can't put .t.f2 inside .t.f1, would cause management loop}
+test place-4.7 {prevent management loops} -setup {
+ place forget .t.f1
+ place forget .t.f2
+} -body {
+ frame .t.f3
+ place .t.f1 -in .t.f2
+ place .t.f2 -in .t.f3
+ place .t.f3 -in .t.f1
+} -returnCodes error -result {can't put .t.f3 inside .t.f1, would cause management loop}
+
+test place-5.1 {ConfigureSlave procedure, -relwidth option} -body {
+ place .t.f2 -relwidth abcd
+} -returnCodes error -result {expected floating-point number but got "abcd"}
+test place-5.2 {ConfigureSlave procedure, -relwidth option} -setup {
+ place forget .t.f2
+} -body {
+ place .t.f2 -in .t.f -relwidth .5
+ update
+ winfo width .t.f2
+} -result {75}
+test place-5.3 {ConfigureSlave procedure, -relwidth option} -setup {
+ place forget .t.f2
+} -body {
+ place .t.f2 -in .t.f -relwidth .8
+ update
+ place .t.f2 -relwidth {}
+ update
+ winfo width .t.f2
+} -result {30}
+
+test place-6.1 {ConfigureSlave procedure, -width option} -body {
+ place .t.f2 -width abcd
+} -returnCodes error -result {bad screen distance "abcd"}
+test place-6.2 {ConfigureSlave procedure, -width option} -setup {
+ place forget .t.f2
+} -body {
+ place .t.f2 -in .t.f -width 100
+ update
+ winfo width .t.f2
+} -result {100}
+test place-6.3 {ConfigureSlave procedure, -width option} -setup {
+ place forget .t.f2
+} -body {
+ place .t.f2 -in .t.f -width 120
+ update
+ place .t.f2 -width {}
+ update
+ winfo width .t.f2
+} -result {30}
+
+
+test place-7.1 {ReconfigurePlacement procedure, computing position} -setup {
+ place forget .t.f2
+} -body {
+ place .t.f2 -in .t.f -x -2 -relx .5 -y 3 -rely .4
+ update
+ winfo geometry .t.f2
+} -result {30x60+123+75}
+test place-7.2 {ReconfigurePlacement procedure, position rounding} -setup {
+ place forget .t.f2
+} -body {
+ place .t.f2 -in .t.f -x -1.4 -y -2.3
+ update
+ winfo geometry .t.f2
+} -result {30x60+49+38}
+test place-7.3 {ReconfigurePlacement procedure, position rounding} -setup {
+ place forget .t.f2
+} -body {
+ place .t.f2 -in .t.f -x 1.4 -y 2.3
+ update
+ winfo geometry .t.f2
+} -result {30x60+51+42}
+test place-7.4 {ReconfigurePlacement procedure, position rounding} -setup {
+ place forget .t.f2
+} -body {
+ place .t.f2 -in .t.f -x -1.6 -y -2.7
+ update
+ winfo geometry .t.f2
+} -result {30x60+48+37}
+test place-7.5 {ReconfigurePlacement procedure, position rounding} -setup {
+ place forget .t.f2
+} -body {
+ place .t.f2 -in .t.f -x 1.6 -y 2.7
+ update
+ winfo geometry .t.f2
+} -result {30x60+52+43}
+test place-7.6 {ReconfigurePlacement procedure, position rounding} -setup {
+ destroy .t.f3
+} -body {
+ frame .t.f3 -width 100 -height 100 -bg #f00000 -bd 0
+ place .t.f3 -x 0 -y 0
+ raise .t.f2
+ place forget .t.f2
+ place .t.f2 -in .t.f3 -relx .303 -rely .406 -relwidth .304 -relheight .206
+ update
+ winfo geometry .t.f2
+} -cleanup {
+ destroy .t.f3
+} -result {31x20+30+41}
+test place-7.7 {ReconfigurePlacement procedure, computing size} -setup {
+ place forget .t.f2
+} -body {
+ place .t.f2 -in .t.f -width 120 -height 89
+ update
+ list [winfo width .t.f2] [winfo height .t.f2]
+} -result {120 89}
+test place-7.8 {ReconfigurePlacement procedure, computing size} -setup {
+ place forget .t.f2
+} -body {
+ place .t.f2 -in .t.f -relwidth .4 -relheight .5
+ update
+ list [winfo width .t.f2] [winfo height .t.f2]
+} -result {60 40}
+test place-7.9 {ReconfigurePlacement procedure, computing size} -setup {
+ place forget .t.f2
+} -body {
+ place .t.f2 -in .t.f -width 10 -relwidth .4 -height -4 -relheight .5
+ update
+ list [winfo width .t.f2] [winfo height .t.f2]
+} -result {70 36}
+test place-7.10 {ReconfigurePlacement procedure, computing size} -setup {
+ place forget .t.f2
+} -body {
+ place .t.f2 -in .t.f -width 10 -relwidth .4 -height -4 -relheight .5
+ place .t.f2 -width {} -relwidth {} -height {} -relheight {}
+ update
+ list [winfo width .t.f2] [winfo height .t.f2]
+} -result {30 60}
+
+
+test place-8.1 {MasterStructureProc, mapping and unmapping slaves} -setup {
+ place forget .t.f2
+ place forget .t.f
+} -body {
+ place .t.f2 -relx 1.0 -rely 1.0 -anchor sw
+ update
+ set result [winfo ismapped .t.f2]
+ wm iconify .t
+ update
+ lappend result [winfo ismapped .t.f2]
+ place .t.f2 -x 40 -y 30 -relx 0 -rely 0 -anchor nw
+ update
+ lappend result [winfo x .t.f2] [winfo y .t.f2] [winfo ismapped .t.f2]
+ wm deiconify .t
+ update
+ lappend result [winfo ismapped .t.f2]
+} -result {1 0 40 30 0 1}
+test place-8.2 {MasterStructureProc, mapping and unmapping slaves} -setup {
+ place forget .t.f2
+ place forget .t.f
+} -body {
+ place .t.f -x 0 -y 0 -width 200 -height 100
+ place .t.f2 -in .t.f -relx 1.0 -rely 1.0 -anchor sw -width 50 -height 20
+ update
+ set result [winfo ismapped .t.f2]
+ wm iconify .t
+ update
+ lappend result [winfo ismapped .t.f2]
+ place .t.f2 -x 40 -y 30 -relx 0 -rely 0 -anchor nw
+ update
+ lappend result [winfo x .t.f2] [winfo y .t.f2] [winfo ismapped .t.f2]
+ wm deiconify .t
+ update
+ lappend result [winfo ismapped .t.f2]
+} -result {1 0 42 32 0 1}
+destroy .t
+
+
+test place-9.1 {PlaceObjCmd} -body {
+ place
+} -returnCodes error -result {wrong # args: should be "place option|pathName args"}
+test place-9.2 {PlaceObjCmd} -body {
+ place foo
+} -returnCodes error -result {wrong # args: should be "place option|pathName args"}
+test place-9.3 {PlaceObjCmd} -setup {
+ destroy .foo
+} -body {
+ place .foo bar
+} -returnCodes error -result {bad window path name ".foo"}
+test place-9.4 {PlaceObjCmd} -setup {
+ destroy .foo
+} -body {
+ place bar .foo
+} -cleanup {
+ destroy .foo
+} -returnCodes error -result {bad window path name ".foo"}
+test place-9.5 {PlaceObjCmd} -setup {
+ destroy .foo
+} -body {
+ frame .foo
+ place badopt .foo
+} -cleanup {
+ destroy .foo
+} -returnCodes error -result {bad option "badopt": must be configure, forget, info, or slaves}
+test place-9.6 {PlaceObjCmd, configure errors} -setup {
+ destroy .foo
+} -body {
+ frame .foo
+ place configure .foo
+} -cleanup {
+ destroy .foo
+} -returnCodes ok -result {}
+test place-9.7 {PlaceObjCmd, configure errors} -setup {
+ destroy .foo
+} -body {
+ frame .foo
+ place configure .foo bar
+} -cleanup {
+ destroy .foo
+} -returnCodes ok -result {}
+test place-9.8 {PlaceObjCmd, configure} -setup {
+ destroy .foo
+} -body {
+ frame .foo
+ place .foo -x 0 -y 0
+ place configure .foo
+} -cleanup {
+ destroy .foo
+} -result [list {-anchor {} {} nw nw} {-bordermode {} {} inside inside} {-height {} {} {} {}} {-in {} {} {} .} {-relheight {} {} {} {}} {-relwidth {} {} {} {}} {-relx {} {} 0 0.0} {-rely {} {} 0 0.0} {-width {} {} {} {}} {-x {} {} 0 0} {-y {} {} 0 0}]
+test place-9.9 {PlaceObjCmd, configure} -setup {
+ destroy .foo
+} -body {
+ frame .foo
+ place .foo -x 0 -y 0
+ place configure .foo -x
+} -cleanup {
+ destroy .foo
+} -result {-x {} {} 0 0}
+test place-9.10 {PlaceObjCmd, forget errors} -setup {
+ destroy .foo
+} -body {
+ frame .foo
+ place forget .foo bar
+} -cleanup {
+ destroy .foo
+} -returnCodes error -result {wrong # args: should be "place forget pathName"}
+test place-9.11 {PlaceObjCmd, info errors} -setup {
+ destroy .foo
+} -body {
+ frame .foo
+ place info .foo bar
+} -cleanup {
+ destroy .foo
+} -returnCodes error -result {wrong # args: should be "place info pathName"}
+test place-9.12 {PlaceObjCmd, slaves errors} -setup {
+ destroy .foo
+} -body {
+ frame .foo
+ place slaves .foo bar
+} -cleanup {
+ destroy .foo
+} -returnCodes error -result {wrong # args: should be "place slaves pathName"}
+
+
+test place-10.1 {ConfigureSlave} -setup {
+ destroy .foo
+} -body {
+ frame .foo
+ place .foo -badopt
+} -cleanup {
+ destroy .foo
+} -returnCodes error -result {unknown option "-badopt"}
+test place-10.2 {ConfigureSlave} -setup {
+ destroy .foo
+} -body {
+ frame .foo
+ place .foo -anchor
+} -cleanup {
+ destroy .foo
+} -returnCodes error -result {value for "-anchor" missing}
+test place-10.3 {ConfigureSlave} -setup {
+ destroy .foo
+} -body {
+ frame .foo
+ place .foo -bordermode j
+} -cleanup {
+ destroy .foo
+} -returnCodes error -result {bad bordermode "j": must be inside, outside, or ignore}
+test place-10.4 {ConfigureSlave} -setup {
+ destroy .foo
+} -body {
+ frame .foo
+ place configure .foo -x 0 -y
+} -cleanup {
+ destroy .foo
+} -returnCodes error -result {value for "-y" missing}
+
+
+test place-11.1 {PlaceObjCmd, slaves command} -setup {
+ destroy .foo
+} -body {
+ frame .foo
+ place slaves .foo
+} -cleanup {
+ destroy .foo
+} -result {}
+test place-11.2 {PlaceObjCmd, slaves command} -setup {
+ destroy .foo .bar
+} -body {
+ frame .foo
+ frame .bar
+ place .bar -in .foo
+ place slaves .foo
+} -cleanup {
+ destroy .foo .bar
+} -result [list .bar]
+
+
+test place-12.1 {PlaceObjCmd, forget command} -setup {
+ destroy .foo
+} -body {
+ frame .foo
+ place .foo -width 50 -height 50
+ update
+ set res [winfo ismapped .foo]
+ place forget .foo
+ update
+ lappend res [winfo ismapped .foo]
+} -cleanup {
+ destroy .foo
+} -result {1 0}
+
+
+test place-13.1 {test respect for internalborder} -setup {
+ destroy .pack
+} -body {
+ toplevel .pack
+ wm geometry .pack 200x200
+ frame .pack.l -width 15 -height 10
+ labelframe .pack.lf -labelwidget .pack.l
+ pack .pack.lf -fill both -expand 1
+ frame .pack.lf.f
+ place .pack.lf.f -x 0 -y 0 -relwidth 1.0 -relheight 1.0
+ update
+ set res [list [winfo geometry .pack.lf.f]]
+ .pack.lf configure -labelanchor e -padx 3 -pady 5
+ update
+ lappend res [winfo geometry .pack.lf.f]
+} -cleanup {
+ destroy .pack
+} -result {196x188+2+10 177x186+5+7}
+
+
+test place-14.1 {memory leak testing} -constraints memory -setup {
+ destroy .f
+ proc getbytes {} {
+ set lines [split [memory info] "\n"]
+ lindex [lindex $lines 3] 3
+ }
+ # Repeat each body checking that memory does not increase
+ proc stress {args} {
+ set res {}
+ foreach body $args {
+ set end 0
+ for {set i 0} {$i < 5} {incr i} {
+ uplevel 1 $body
+ set tmp $end
+ set end [getbytes]
+ }
+ lappend res [expr {$end - $tmp}]
+ }
+ return $res
+ }
+} -body {
+ # Test all manners of forgetting a slave
+ frame .f
+ frame .f.f
+ stress {
+ place .f.f -x [expr {1 + 1}] -y [expr {2 + 2}]
+ place forget .f.f
+ } {
+ place .f.f -x [expr {1 + 1}] -y [expr {2 + 2}]
+ pack .f.f
+ } {
+ place .f.f -x [expr {1 + 1}] -y [expr {2 + 2}]
+ destroy .f
+ frame .f
+ frame .f.f
+ }
+} -cleanup {
+ destroy .f
+ rename getbytes {}
+ rename stress {}
+} -result {0 0 0}
+
+
+# cleanup
+cleanupTests
+return
+
+
+
diff --git a/tk8.6/tests/pwrdLogo150.gif b/tk8.6/tests/pwrdLogo150.gif
new file mode 100644
index 0000000..89eec7c
--- /dev/null
+++ b/tk8.6/tests/pwrdLogo150.gif
Binary files differ
diff --git a/tk8.6/tests/raise.test b/tk8.6/tests/raise.test
new file mode 100644
index 0000000..f8674fc
--- /dev/null
+++ b/tk8.6/tests/raise.test
@@ -0,0 +1,320 @@
+# This file is a Tcl script to test out Tk's "raise" and
+# "lower" commands, plus associated code to manage window
+# stacking order. It is organized in the standard fashion
+# for Tcl tests.
+#
+# Copyright (c) 1993-1994 The Regents of the University of California.
+# Copyright (c) 1994 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+namespace import -force tcltest::test
+
+# Procedure to create a bunch of overlapping windows, which should
+# make it easy to detect differences in order.
+
+proc raise_setup {} {
+ foreach i [winfo child .raise] {
+ destroy $i
+ }
+ foreach i {a b c d e} {
+ label .raise.$i -text $i -relief raised -bd 2
+ }
+ place .raise.a -x 20 -y 60 -width 60 -height 80
+ place .raise.b -x 60 -y 60 -width 60 -height 80
+ place .raise.c -x 100 -y 60 -width 60 -height 80
+ place .raise.d -x 40 -y 20 -width 100 -height 60
+ place .raise.e -x 40 -y 120 -width 100 -height 60
+}
+
+# Procedure to return information about which windows are on top
+# of which other windows.
+
+proc raise_getOrder {} {
+ set x [winfo rootx .raise]
+ set y [winfo rooty .raise]
+ list [winfo name [winfo containing [expr $x+50] [expr $y+70]]] \
+ [winfo name [winfo containing [expr $x+90] [expr $y+70]]] \
+ [winfo name [winfo containing [expr $x+130] [expr $y+70]]] \
+ [winfo name [winfo containing [expr $x+70] [expr $y+100]]] \
+ [winfo name [winfo containing [expr $x+110] [expr $y+100]]] \
+ [winfo name [winfo containing [expr $x+50] [expr $y+130]]] \
+ [winfo name [winfo containing [expr $x+90] [expr $y+130]]] \
+ [winfo name [winfo containing [expr $x+130] [expr $y+130]]]
+}
+
+# Procedure to set up a collection of top-level windows
+
+proc raise_makeToplevels {} {
+ deleteWindows
+ foreach i {.raise1 .raise2 .raise3} {
+ toplevel $i
+ wm geom $i 150x100+0+0
+ update
+ }
+}
+
+toplevel .raise
+wm geom .raise 250x200+0+0
+
+
+test raise-1.1 {preserve creation order} -body {
+ raise_setup
+ tkwait visibility .raise.e
+ raise_getOrder
+} -result {d d d b c e e e}
+test raise-1.2 {preserve creation order} -constraints testmakeexist -body {
+ raise_setup
+ testmakeexist .raise.a
+ update
+ raise_getOrder
+} -result {d d d b c e e e}
+test raise-1.3 {preserve creation order} -constraints testmakeexist -body {
+ raise_setup
+ testmakeexist .raise.c
+ update
+ raise_getOrder
+} -result {d d d b c e e e}
+test raise-1.4 {preserve creation order} -constraints testmakeexist -body {
+ raise_setup
+ testmakeexist .raise.e
+ update
+ raise_getOrder
+} -result {d d d b c e e e}
+test raise-1.5 {preserve creation order} -constraints testmakeexist -body {
+ raise_setup
+ testmakeexist .raise.d .raise.c .raise.b
+ update
+ raise_getOrder
+} -result {d d d b c e e e}
+
+
+test raise-2.1 {raise internal windows before creation} -body {
+ raise_setup
+ raise .raise.a
+ update
+ raise_getOrder
+} -result {a d d a c a e e}
+test raise-2.2 {raise internal windows before creation} -body {
+ raise_setup
+ raise .raise.c
+ update
+ raise_getOrder
+} -result {d d c b c e e c}
+test raise-2.3 {raise internal windows before creation} -body {
+ raise_setup
+ raise .raise.e
+ update
+ raise_getOrder
+} -result {d d d b c e e e}
+test raise-2.4 {raise internal windows before creation} -body {
+ raise_setup
+ raise .raise.e .raise.a
+ update
+ raise_getOrder
+} -result {d d d b c e b c}
+test raise-2.5 {raise internal windows before creation} -body {
+ raise_setup
+ raise .raise.a .raise.d
+ update
+ raise_getOrder
+} -result {a d d a c e e e}
+
+
+test raise-3.1 {raise internal windows after creation} -body {
+ raise_setup
+ update
+ raise .raise.a .raise.d
+ raise_getOrder
+} -result {a d d a c e e e}
+test raise-3.2 {raise internal windows after creation} -constraints {
+ testmakeexist
+} -body {
+ raise_setup
+ testmakeexist .raise.a .raise.b
+ raise .raise.a .raise.b
+ update
+ raise_getOrder
+} -result {d d d a c e e e}
+test raise-3.3 {raise internal windows after creation} -constraints {
+ testmakeexist
+} -body {
+ raise_setup
+ testmakeexist .raise.a .raise.d
+ raise .raise.a .raise.b
+ update
+ raise_getOrder
+} -result {d d d a c e e e}
+test raise-3.4 {raise internal windows after creation} -constraints {
+ testmakeexist
+} -body {
+ raise_setup
+ testmakeexist .raise.a .raise.c .raise.d
+ raise .raise.a .raise.b
+ update
+ raise_getOrder
+} -result {d d d a c e e e}
+
+
+test raise-4.1 {raise relative to nephews} -body {
+ raise_setup
+ update
+ frame .raise.d.child
+ raise .raise.a .raise.d.child
+ raise_getOrder
+} -result {a d d a c e e e}
+test raise-4.2 {raise relative to nephews} -setup {
+ destroy .raise2
+} -body {
+ raise_setup
+ update
+ frame .raise2
+ raise .raise.a .raise2
+} -cleanup {
+ destroy .raise2
+} -returnCodes error -result {can't raise ".raise.a" above ".raise2"}
+
+
+test raise-5.1 {lower internal windows} -body {
+ raise_setup
+ update
+ lower .raise.d
+ raise_getOrder
+} -result {a b c b c e e e}
+test raise-5.2 {lower internal windows} -body {
+ raise_setup
+ update
+ lower .raise.d .raise.b
+ raise_getOrder
+} -result {d b c b c e e e}
+test raise-5.3 {lower internal windows} -body {
+ raise_setup
+ update
+ lower .raise.a .raise.e
+ raise_getOrder
+} -result {a d d a c e e e}
+test raise-5.4 {lower internal windows} -setup {
+ destroy .raise2
+} -body {
+ raise_setup
+ update
+ frame .raise2
+ lower .raise.a .raise2
+} -cleanup {
+ destroy .raise2
+} -returnCodes error -result {can't lower ".raise.a" below ".raise2"}
+
+
+test raise-6.1 {raise/lower toplevel windows} -constraints {
+ nonPortable
+} -body {
+ raise_makeToplevels
+ update
+ raise .raise1
+ winfo containing [winfo rootx .raise1] [winfo rooty .raise1]
+} -result {.raise1}
+test raise-6.2 {raise/lower toplevel windows} -constraints {
+ nonPortable
+} -body {
+ raise_makeToplevels
+ update
+ raise .raise2
+ winfo containing [winfo rootx .raise1] [winfo rooty .raise1]
+} -result {.raise2}
+test raise-6.3 {raise/lower toplevel windows} -constraints {
+ nonPortable
+} -body {
+ raise_makeToplevels
+ update
+ raise .raise3
+ raise .raise2
+ raise .raise1 .raise3
+ set result [winfo containing [winfo rootx .raise1] \
+ [winfo rooty .raise1]]
+ destroy .raise2
+ update
+ after 500
+ list $result [winfo containing [winfo rootx .raise1] \
+ [winfo rooty .raise1]]
+} -result {.raise2 .raise1}
+test raise-6.4 {raise/lower toplevel windows} -constraints {
+ nonPortable
+} -body {
+ raise_makeToplevels
+ update
+ raise .raise2
+ raise .raise1
+ lower .raise3 .raise1
+ set result [winfo containing [winfo rootx .raise1] \
+ [winfo rooty .raise1]]
+ wm geometry .raise2 +30+30
+ wm geometry .raise1 +60+60
+ destroy .raise1
+ update
+ after 500
+ list $result [winfo containing [winfo rootx .raise2] \
+ [winfo rooty .raise2]]
+} -result {.raise1 .raise3}
+test raise-6.5 {raise/lower toplevel windows} -constraints {
+ nonPortable
+} -body {
+ raise_makeToplevels
+ raise .raise1
+ set time [lindex [time {raise .raise1}] 0]
+ expr {$time < 2000000}
+} -result 1
+test raise-6.6 {raise/lower toplevel windows} -constraints {
+ nonPortable
+} -body {
+ raise_makeToplevels
+ update
+ raise .raise2
+ raise .raise1
+ raise .raise3
+ frame .raise1.f1
+ frame .raise1.f1.f2
+ lower .raise3 .raise1.f1.f2
+ set result [winfo containing [winfo rootx .raise1] \
+ [winfo rooty .raise1]]
+ destroy .raise1
+ update
+ after 500
+ list $result [winfo containing [winfo rootx .raise2] \
+ [winfo rooty .raise2]]
+} -result {.raise1 .raise3}
+
+
+test raise-7.1 {errors in raise/lower commands} -body {
+ raise
+} -returnCodes error -result {wrong # args: should be "raise window ?aboveThis?"}
+test raise-7.2 {errors in raise/lower commands} -body {
+ raise a b c
+} -returnCodes error -result {wrong # args: should be "raise window ?aboveThis?"}
+test raise-7.3 {errors in raise/lower commands} -body {
+ raise badName
+} -returnCodes error -result {bad window path name "badName"}
+test raise-7.4 {errors in raise/lower commands} -body {
+ raise . badName2
+} -returnCodes error -result {bad window path name "badName2"}
+test raise-7.5 {errors in raise/lower commands} -body {
+ lower
+} -returnCodes error -result {wrong # args: should be "lower window ?belowThis?"}
+test raise-7.6 {errors in raise/lower commands} -body {
+ lower a b c
+} -returnCodes error -result {wrong # args: should be "lower window ?belowThis?"}
+test raise-7.7 {errors in raise/lower commands} -body {
+ lower badName3
+} -returnCodes error -result {bad window path name "badName3"}
+test raise-7.8 {errors in raise/lower commands} -body {
+ lower . badName4
+} -returnCodes error -result {bad window path name "badName4"}
+
+deleteWindows
+
+# cleanup
+cleanupTests
+return
+
diff --git a/tk8.6/tests/red.gif b/tk8.6/tests/red.gif
new file mode 100644
index 0000000..1d12ebb
--- /dev/null
+++ b/tk8.6/tests/red.gif
Binary files differ
diff --git a/tk8.6/tests/safe.test b/tk8.6/tests/safe.test
new file mode 100644
index 0000000..475d938
--- /dev/null
+++ b/tk8.6/tests/safe.test
@@ -0,0 +1,248 @@
+# This file is a Tcl script to test the Safe Tk facility. It is organized in
+# the standard fashion for Tk tests.
+#
+# Copyright (c) 1994 The Regents of the University of California.
+# Copyright (c) 1994-1995 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+
+package require tcltest 2.2
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+namespace import -force tcltest::test
+
+## NOTE: Any time tests fail here with an error like:
+
+# Can't find a usable tk.tcl in the following directories:
+# {$p(:26:)}
+#
+# $p(:26:)/tk.tcl: script error
+# script error
+# invoked from within
+# "source {$p(:26:)/tk.tcl}"
+# ("uplevel" body line 1)
+# invoked from within
+# "uplevel #0 [list source $file]"
+#
+#
+# This probably means that tk wasn't installed properly.
+
+## it indicates that something went wrong sourcing tk.tcl.
+## Ensure that any changes that occured to tk.tcl will work or are properly
+## prevented in a safe interpreter. -- hobbs
+
+# The set of hidden commands is platform dependent:
+
+set hidden_cmds {bell cd clipboard encoding exec exit fconfigure glob grab load menu open pwd selection socket source tcl:encoding:dirs toplevel unload wm}
+lappend hidden_cmds {*}[apply {{} {
+ foreach cmd {
+ atime attributes copy delete dirname executable exists extension
+ isdirectory isfile link lstat mkdir mtime nativename normalize owned
+ readable readlink rename rootname size stat tail tempfile type
+ volumes writable
+ } {lappend result tcl:file:$cmd}; return $result
+}}]
+if {[tk windowingsystem] ne "x11"} {
+ lappend hidden_cmds tk_chooseColor tk_chooseDirectory tk_getOpenFile \
+ tk_getSaveFile tk_messageBox
+}
+if {[llength [info commands send]]} {
+ lappend hidden_cmds send
+}
+
+set saveAutoPath $::auto_path
+set auto_path [list [info library] $::tk_library]
+set hidden_cmds [lsort $hidden_cmds]
+
+test safe-1.1 {Safe Tk loading into an interpreter} -setup {
+ catch {safe::interpDelete a}
+} -body {
+ safe::loadTk [safe::interpCreate a]
+ safe::interpDelete a
+ set x {}
+ return $x
+} -result {}
+test safe-1.2 {Safe Tk loading into an interpreter} -setup {
+ catch {safe::interpDelete a}
+} -body {
+ safe::interpCreate a
+ safe::loadTk a
+ lsort [interp hidden a]
+} -cleanup {
+ safe::interpDelete a
+} -result $hidden_cmds
+test safe-1.3 {Safe Tk loading into an interpreter} -setup {
+ catch {safe::interpDelete a}
+} -body {
+ safe::interpCreate a
+ safe::loadTk a
+ lsort [interp aliases a]
+} -cleanup {
+ safe::interpDelete a
+} -match glob -result {*encoding*exit*glob*load*source*}
+
+test safe-2.1 {Unsafe commands not available} -setup {
+ catch {safe::interpDelete a}
+} -body {
+ safe::interpCreate a
+ safe::loadTk a
+ set status broken
+ if {[catch {interp eval a {toplevel .t}} msg]} {
+ set status ok
+ }
+ return $status
+} -cleanup {
+ safe::interpDelete a
+} -result ok
+test safe-2.2 {Unsafe commands not available} -setup {
+ catch {safe::interpDelete a}
+} -body {
+ safe::interpCreate a
+ safe::loadTk a
+ set status broken
+ if {[catch {interp eval a {menu .m}} msg]} {
+ set status ok
+ }
+ return $status
+} -cleanup {
+ safe::interpDelete a
+} -result ok
+test safe-2.3 {Unsafe subcommands not available} -setup {
+ catch {safe::interpDelete a}
+} -body {
+ safe::interpCreate a
+ safe::loadTk a
+ set status broken
+ if {[catch {interp eval a {tk appname}} msg]} {
+ set status ok
+ }
+ list $status $msg
+} -cleanup {
+ safe::interpDelete a
+} -result {ok {appname not accessible in a safe interpreter}}
+test safe-2.4 {Unsafe subcommands not available} -setup {
+ catch {safe::interpDelete a}
+} -body {
+ safe::interpCreate a
+ safe::loadTk a
+ set status broken
+ if {[catch {interp eval a {tk scaling}} msg]} {
+ set status ok
+ }
+ list $status $msg
+} -cleanup {
+ safe::interpDelete a
+} -result {ok {scaling not accessible in a safe interpreter}}
+
+test safe-3.1 {Unsafe commands are available hidden} -setup {
+ catch {safe::interpDelete a}
+} -body {
+ safe::interpCreate a
+ safe::loadTk a
+ set status ok
+ if {[catch {interp invokehidden a toplevel .t} msg]} {
+ set status broken
+ }
+ return $status
+} -cleanup {
+ safe::interpDelete a
+} -result ok
+test safe-3.2 {Unsafe commands are available hidden} -setup {
+ catch {safe::interpDelete a}
+} -body {
+ safe::interpCreate a
+ safe::loadTk a
+ set status ok
+ if {[catch {interp invokehidden a menu .m} msg]} {
+ set status broken
+ }
+ return $status
+} -cleanup {
+ safe::interpDelete a
+} -result ok
+
+test safe-4.1 {testing loadTk} -body {
+ # no error shall occur, the user will eventually see a new toplevel
+ set i [safe::loadTk [safe::interpCreate]]
+ interp eval $i {button .b -text "hello world!"; pack .b}
+ # lets don't update because it might imply that the user has to position
+ # the window (if the wm does not do it automatically) and thus make the
+ # test suite not runable non interactively
+ safe::interpDelete $i
+} -result {}
+test safe-4.2 {testing loadTk -use} -setup {
+ destroy .safeTkFrame
+} -body {
+ set w .safeTkFrame
+ frame $w -container 1;
+ pack $w
+ set i [safe::loadTk [safe::interpCreate] -use [winfo id $w]]
+ interp eval $i {button .b -text "hello world!"; pack .b}
+ safe::interpDelete $i
+ destroy $w
+} -result {}
+
+test safe-5.1 {loading Tk in safe interps without master's clearance} -body {
+ set i [safe::interpCreate]
+ interp eval $i {load {} Tk}
+} -cleanup {
+ safe::interpDelete $i
+} -returnCodes error -result {not allowed}
+test safe-5.2 {multi-level Tk loading with clearance} -setup {
+ set safeParent [safe::interpCreate]
+} -body {
+ # No error shall occur in that test and no window shall remain at the end.
+ set i [safe::interpCreate [list $safeParent x]]
+ safe::loadTk $i
+ interp eval $i {
+ button .b -text Ok -command {destroy .}
+ pack .b
+# tkwait window . ; # for interactive testing/debugging
+ }
+} -cleanup {
+ catch {safe::interpDelete $i}
+ safe::interpDelete $safeParent
+} -result {}
+
+test safe-6.1 {loadTk -use windowPath} -setup {
+ destroy .safeTkFrame
+} -body {
+ set w .safeTkFrame
+ frame $w -container 1;
+ pack $w
+ set i [safe::loadTk [safe::interpCreate] -use $w]
+ interp eval $i {button .b -text "hello world!"; pack .b}
+ safe::interpDelete $i
+ destroy $w
+} -result {}
+test safe-6.2 {loadTk -use windowPath, conflicting -display} -setup {
+ destroy .safeTkFrame
+} -body {
+ set w .safeTkFrame
+ frame $w -container 1;
+ pack $w
+ set i [safe::interpCreate]
+ catch {safe::loadTk $i -use $w -display :23.56} msg
+ string range $msg 0 36
+} -cleanup {
+ safe::interpDelete $i
+ destroy $w
+} -result {conflicting -display :23.56 and -use }
+
+test safe-7.1 {canvas printing} -body {
+ set i [safe::loadTk [safe::interpCreate]]
+ interp eval $i {canvas .c; .c postscript}
+} -cleanup {
+ safe::interpDelete $i
+} -returnCodes ok -match glob -result *
+
+# cleanup
+set ::auto_path $saveAutoPath
+unset hidden_cmds
+cleanupTests
+return
+
+# Local Variables:
+# mode: tcl
+# fill-column: 78
+# End:
diff --git a/tk8.6/tests/safePrimarySelection.test b/tk8.6/tests/safePrimarySelection.test
new file mode 100644